Files
ESPEasy/src/_C017.cpp
T

153 lines
5.1 KiB
C++

#include "src/Helpers/_CPlugin_Helper.h"
#ifdef USES_C017
// #######################################################################################################
// ########################### Controller Plugin 017: ZABBIX ##########################################
// #######################################################################################################
// Based on https://www.zabbix.com/documentation/current/manual/appendix/items/trapper
// and https://www.zabbix.com/documentation/4.2/manual/appendix/protocols/header_datalen
// USAGE: at Zabbix server you go at Configuration -> Hosts -> Create host
// The "Host name" should match exactly the EspEasy name (Config -> Unit Name)
// Add a group (mandatory) and hit add. No need to set up IP address or agent.
// Go to the newly created host ->Items ->Create Item
// Name the item something descriptive
// For Key add the EspEasy task Value name (case sensitive)
// Type of information select "Numeric (float)" and press add.
// Aslo make sure that you enable send to controller (under Data Acquisition in tasks)
// and set an interval because you need to actively send the data to Zabbix
# define CPLUGIN_017
# define CPLUGIN_ID_017 17
# define CPLUGIN_NAME_017 "Zabbix"
# include <ArduinoJson.h>
bool CPlugin_017(CPlugin::Function function, struct EventStruct *event, String& string)
{
bool success = false;
switch (function)
{
case CPlugin::Function::CPLUGIN_PROTOCOL_ADD:
{
ProtocolStruct& proto = getProtocolStruct(event->idx); // = CPLUGIN_ID_017;
proto.usesMQTT = false;
proto.usesTemplate = false;
proto.usesAccount = false;
proto.usesPassword = false;
proto.usesID = false;
proto.defaultPort = 10051;
break;
}
case CPlugin::Function::CPLUGIN_GET_DEVICENAME:
{
string = F(CPLUGIN_NAME_017);
break;
}
case CPlugin::Function::CPLUGIN_INIT:
{
success = init_c017_delay_queue(event->ControllerIndex);
break;
}
case CPlugin::Function::CPLUGIN_EXIT:
{
exit_c017_delay_queue();
break;
}
case CPlugin::Function::CPLUGIN_PROTOCOL_SEND:
{
if (C017_DelayHandler == nullptr) {
break;
}
if (C017_DelayHandler->queueFull(event->ControllerIndex)) {
break;
}
std::unique_ptr<C017_queue_element> element(new C017_queue_element(event));
success = C017_DelayHandler->addToQueue(std::move(element));
Scheduler.scheduleNextDelayQueue(SchedulerIntervalTimer_e::TIMER_C017_DELAY_QUEUE, C017_DelayHandler->getNextScheduleTime());
break;
}
case CPlugin::Function::CPLUGIN_FLUSH:
{
process_c017_delay_queue();
delay(0);
break;
}
default:
break;
}
return success;
}
// Uncrustify may change this into multi line, which will result in failed builds
// *INDENT-OFF*
bool do_process_c017_delay_queue(int controller_number, const Queue_element_base& element_base, ControllerSettingsStruct& ControllerSettings) {
const C017_queue_element& element = static_cast<const C017_queue_element&>(element_base);
// *INDENT-ON*
if (element.valueCount == 0) {
return true; // exit if we don't have anything to send.
}
if (!NetworkConnected(10))
{
return false;
}
WiFiClient client;
if (!try_connect_host(controller_number, client, ControllerSettings, F("ZBX : ")))
{
return false;
}
const size_t capacity = JSON_ARRAY_SIZE(VARS_PER_TASK) + JSON_OBJECT_SIZE(2) + VARS_PER_TASK * JSON_OBJECT_SIZE(3) + VARS_PER_TASK * 50; //Size for esp8266 with 4 variables per task: 288+200
String JSON_packet_content;
{
// Place the JSON document in a separate scope to have it destructed as soon as it is no longer needed.
DynamicJsonDocument root(capacity);
// Create the schafolding
root[F("request")] = F("sender data");
JsonArray data = root.createNestedArray(F("data"));
// Populate JSON with the data
for (uint8_t i = 0; i < element.valueCount; i++)
{
const String taskValueName = getTaskValueName(element._taskIndex, i);
if (taskValueName.isEmpty()) {
continue; // Zabbix will ignore an empty key anyway
}
JsonObject block = data.createNestedObject();
block[F("host")] = Settings.getName(); // Zabbix hostname, Unit Name for the ESP easy
block[F("key")] = taskValueName; // Zabbix item key // Value Name for the ESP easy
float value = 0.0f;
validFloatFromString(element.txt[i], value);
block[F("value")] = value; // ESPeasy supports only floats
}
serializeJson(root, JSON_packet_content);
}
// Assemble packet
char packet_header[] = "ZBXD\1";
uint64_t payload_len = JSON_packet_content.length();
// addLog(LOG_LEVEL_INFO, String(F("ZBX: ")) + JSON_packet_content);
// Send the packet
client.write(packet_header, sizeof(packet_header) - 1);
client.write(reinterpret_cast<const char *>(&payload_len), sizeof(payload_len));
client.write(JSON_packet_content.c_str(), payload_len);
client.stop();
return true;
}
#endif // ifdef USES_C017