Плагіни доставки сповіщень
Плагіни доставки сповіщень використовуються системою сповіщень для надсилання сповіщень до іншої системи чи пристрою. Вони є транспортом, який дозволяє сповіщати про подію іншу систему чи пристрій.
Плагіни доставки сповіщень можуть бути написані на C або C++ і мають дуже простий інтерфейс. Механізм плагінів і пі дмножина API є загальними для всіх типів плагінів, включаючи фільтри. Ця документація базується на коді . надсилає повідомлення MQTT до настроюваної теми MQTT, коли сповіщення запускається та очищається.
Конфігурація
Плагіни доставки сповіщень використовують той самий механізм конфігурації, що й решта Fledge, використовуючи документ JSON для опису параметрів конфігурації. Як і в будь-якому іншому плагіні, структура визначається плагіном і отримується за допомогою точки входу plugin_info. Потім це зіставляється з вмістом бази даних для передачі налаштованих значень до точки входу plugin_init.
API Плагіну доставки сповіщень
TAPI плагіна доставки сповіщень складається з невеликої кількості точок входу функції C, які викликаються в строгому порядку та базуються на тому самому набор і загальних точок входу API для всіх плагінів Fledge.
Информація про плагін
Точка входу plugin_info є першою точкою входу, яка викликається в плагіні доставки сповіщень і повертає структуру інформації плагіна. Це той самий виклик, який має підтримувати кожен плагін Fledge і який використовується для визначення типу плагіна та категорії конфігурації за замовчуванням для плагіна.
Типова реалізація plugin_info просто повертає вказівник до статичної структури PLUGIN_INFORMATION.
PLUGIN_INFORMATION *plugin_info()
{
return &info;
}
Запуск Плагіну
Другим викликом плагіна є виклик plugin_init, який використовується для отримання дескриптора екземпляра плагіна та налаштування плагіна.
PLUGIN_HANDLE plugin_init(ConfigCategory* config)
{
MQTT *mqtt = new MQTT(config);
return (PLUGIN_HANDLE)mqtt;
}
Параметр config — це категорія конфігурації зі вставленими значеннями, які надає користувач. Ці значення використовуються для налаштування поведінки плагіна. У випадку нашого прикладу MQTT ми використовуємо це для виклику конструктора нашого класу MQTT.
/**
* Construct a MQTT notification plugin
*
* @param category The configuration of the plugin
*/
MQTT::MQTT(ConfigCategory *category)
{
if (category->itemExists("broker"))
m_broker = category->getValue("broker");
if (category->itemExists("topic"))
m_topic = category->getValue("topic");
if (category->itemExists("trigger_payload"))
m_trigger = category->getValue("trigger_payload");
if (category->itemExists("clear_payload"))
m_clear = category->getValue("clear_payload");
}
Цей конструктор просто зберігає значення поза категорією конфігурації як приватні змінні-члени класу MQTT.
Ми повертаємо вказівник на наш клас MQTT як дескриптор для плагіна. Це дозволяє наступним викликам плагіна посилатися на примірник, створений викликом plugin_init.
Доставка Плагіна
Це виклик API, який виконується щоразу, коли плагіну потрібно надіслати активований або очищений стан сповіщення. Його можна викликати кілька разів протягом життя плагіна.
bool plugin_deliver(PLUGIN_HANDLE handle,
const std::string& deliveryName,
const std::string& notificationName,
const std::string& triggerReason,
const std::string& message)
{
MQTT *mqtt = (MQTT *)handle;
return mqtt->notify(notificationName, triggerReason, message);
}
Виклику доставки передається дескриптор, який дає нам клас MQTT екземпляр класу QQTT для цього випадку, назву сповіщення, причину переключення, яка є JSON-документом та повідомленням. JSON-документ причини переключення містить інформацію про те, чому було зроблено виклик доставки, включаючи статус спрацьовування або скидання, мітку часу зчитування, що спричинило спрацьовування сповіщення до запуску, а також ім'я активу або активів, що беруть участь у правилі сповіщення, яке викликало цю подію доставки.
{
"reason": "triggered",
"asset": ["sinusoid"],
"timestamp": "2020-11-18 11:52:33.960530+00:00"
}
Повернення з точки входу plugin_deliver - це булеве значення, яке вказує, чи доставка була успішною, чи ні.
У випадку нашого прикладу з MQTT ми викликаємо метод повідомлення класу, який потім взаємодіє з брокером MQTT.
/**
* Send a notification via MQTT broker
*
* @param notificationName The name of this notification
* @param triggerReason Why the notification is being sent
* @param message The message to send
*/
bool MQTT::notify(const string& notificationName, const string& triggerReason, const string& message)
{
string payload = m_trigger;
MQTTClient client;
lock_guard<mutex> guard(m_mutex);
// Parse the JSON that represents the reason data
Document doc;
doc.Parse(triggerReason.c_str());
if (!doc.HasParseError() && doc.HasMember("reason"))
{
if (!strcmp(doc["reason"].GetString(), "cleared"))
payload = m_clear;
}
// Connect to the MQTT broker
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
MQTTClient_message pubmsg = MQTTClient_message_initializer;
MQTTClient_deliveryToken token;
int rc;
if ((rc = MQTTClient_create(&client, m_broker.c_str(), CLIENTID,
MQTTCLIENT_PERSISTENCE_NONE, NULL)) != MQTTCLIENT_SUCCESS)
{
Logger::getLogger()->error("Failed to create client, return code %d\n", rc);
return false;
}
conn_opts.keepAliveInterval = 20;
conn_opts.cleansession = 1;
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS)
{
Logger::getLogger()->error("Failed to connect, return code %d\n", rc);
return false;
}
// Construct the payload
pubmsg.payload = (void *)payload.c_str();
pubmsg.payloadlen = payload.length();
pubmsg.qos = 1;
pubmsg.retained = 0;
// Publish the message
if ((rc = MQTTClient_publishMessage(client, m_topic.c_str(), &pubmsg, &token)) != MQTTCLIENT_SUCCESS)
{
Logger::getLogger()->error("Failed to publish message, return code %d\n", rc);
return false;
}
// Wait for completion and disconnect
rc = MQTTClient_waitForCompletion(client, token, TIMEOUT);
if ((rc = MQTTClient_disconnect(client, 10000)) != MQTTCLIENT_SUCCESS)
Logger::getLogger()->error("Failed to disconnect, return code %d\n", rc);
MQTTClient_destroy(&client);
return true;
}
Переналаштування плагіна
Як і інші типи плагінів, плагін доставки сповіщень може бути переналаштований протягом його життя. Коли відбувається операція реконфігурації, буде викликано метод plugin_reconfigure з новою конфігурацією плагіна.
void plugin_reconfigure(PLUGIN_HANDLE *handle, const std::string& newConfig)
{
MQTT *mqtt = (MQTT *)handle;
mqtt->reconfigure(newConfig);
return;
}
У випадку нашого прикладу з MQTT ми викликаємо метод reconfigure нашого класу MQTT. У цьому методі нові значення копіюються у локальні змінні-члени екземпляру.
/**
* Reconfigure the MQTT delivery plugin
*
* @param newConfig The new configuration
*/
void MQTT::reconfigure(const string& newConfig)
{
ConfigCategory category("new", newConfig);
lock_guard<mutex> guard(m_mutex);
m_broker = category.getValue("broker");
m_topic = category.getValue("topic");
m_trigger = category.getValue("trigger_payload");
m_clear = category.getValue("clear_payload");
}
Mutex використовується тут, щоб запобігти переконфігурації плагіна під час надсилання сповіщення. Такий самий mutex міститься у методі повідомлення класу MQTT.
Закриття Плагіна
Як і у випадку з іншими плагінами, існує виклик завершення роботи, який може бути використаний плагіном для виконання будь-якого очищення, необхідного при завершенні роботи плагіна.
void plugin_shutdown(PLUGIN_HANDLE *handle)
{
MQTT *mqtt = (MQTT *)handle;
delete mqtt;
}
У випадку нашого прикладу з MQTT ми просто знищуємо екземпляр класу MQTT і дозволяємо деструктору цього класу виконати будь-яке очищення, яке необхідне. У випадку цього прикладу очищення не потрібне.