Skip to main content

Написання та використання плагінів

Плагін має невеликий набір зовнішніх точок входу, які повинні існувати, щоб Fledge міг завантажити та виконати цей плагін. Наразі плагіни можуть бути написані на Python або C/C++, набір точок входу однаковий для обох мов. Точки входу, деталізовані тут, будуть представлені для обох мов, а потім буде більш глибоке обговорення написання плагінів на C/C++.

Загальне керівництво

Перш ніж заглиблюватися в деталі того, як писати плагіни, які точки входу потрібно надати, як їх створювати та тестувати, кілька загальних вказівок, які повинні враховувати всі розробники плагінів, щоб уникнути труднощів із створенням плагінів.

  • Метою Fledge є забезпечення трубопроводів даних, які сприяють легкому створенню додатків шляхом повторного використання невеликих, цілеспрямованих компонентів обробки. Завжди намагайтеся використовувати наявні плагіни, коли це можливо. Під час написання нових плагінів не піддавайтеся спокусі зробити їх надто специфічними для однієї програми. Це означатиме більшу ймовірність того, що в якийсь момент у майбутньому у вашому наборі інструментів будуть усі компоненти, необхідні для створення наступної програми без необхідності писати нові плагіни.
  • Фільтри в Fledge запускаються в рамках одного процесу, який може бути південним або північним сервісом, вони не запускаються як окремий виконуваний файл. Тому переконайтеся, що під час створення нового сервісу плагіна ви не використовуєте глобальні змінні. Глобальні змінні будуть спільні для всіх плагінів у службі та можуть конфліктувати з іншими плагінами та запобігати використанню того самого плагіна кілька разів у конвеєрі.
  • Не робіть припущень щодо того, як будуть використовуватися дані, які ви обробляєте у своєму плагіні, або скількома компонентами вищестоящої версії вони використовуватимуться. Наприклад, не вставляйте нічого в південний плагін або плагін фільтра, який передбачає, що дані будуть споживатися окремим північним плагіном або лише одним північним плагіном. Прикладом цього може бути південний плагін, який додає підказки OMF AF Location до даних, які він створює. Хоча це добре працює, якщо дані надсилаються до OMF, це не допомагає, якщо дані надсилаються в інше місце призначення, для якого також потрібна інформація про місцезнаходження. Додавання параметрів для різних пунктів призначення лише ускладнює проблему, подумайте, наприклад, про те, що дані можуть бути надіслані до кількох пунктів призначення. Кращим підходом було б додати загальні метадані про місцезнаходження до даних і налаштувати фільтри підказок для кожного з пунктів призначення, які виконують певну роботу.

Загальний API Плагіну Fledge

Кожен плагін надає принаймні одну загальну точку входу API, точку входу plugin_info. Він використовується для отримання інформації про плагін перед його ініціалізацією та використанням. Це дозволяє Fledge визначити тип плагіна, напр. плагін із південним або північним напрямком, отримати інформацію про конфігурацію за замовчуванням для плагіна та визначити інформацію про версію.

Інформація про плагін

Точка входу інформації реалізована як виклик plugin_info, який не приймає аргументів. Дані повертаються з цього виклику API як документ JSON з певними добре відомими властивостями.

Типова реалізація цього в Python просто повертає фіксований об’єкт словника, який кодує необхідні властивості.

def plugin_info():
""" Returns information about the plugin.

Args:
Returns:
dict: plugin information
Raises:
"""

return {
'name': 'DHT11 GPIO',
'version': '1.0',
'mode': 'poll',
'type': 'south',
'interface': '1.0',
'config': _DEFAULT_CONFIG
}

Це властивості, які повертає документ JSON:

  • name - Текстове ім’я, яке використовуватиметься для створення звітів для цього плагіна.
  • version - Ця властивість дозволяє повідомляти версію плагіна завантажувачу плагіна. Це використовується лише для звітування та не впливає на те, як Fledge взаємодіє з плагіном.
  • mode - Набір параметрів, який визначає, як працює плагін. Можна надати кілька значень, різні параметри відокремлюються один від одного за допомогою символу "|".
  • type - Тип плагіна, який використовується завантажувачем плагіна, щоб визначити, чи правильно використовується плагін. Тип — це простий рядок і може бути south, north, filter, rule або delivery.

Примітка

Якщо ви переглядаєте код Fledge, ви можете знайти старі плагіни з типом device: це був тип, який використовувався для позначення плагіна South, і зараз він застарілий.

  • interface - Ця властивість повідомляє версію API плагіна, для якого цей плагін був написаний. Це дозволяє Fledge підтримувати оновлення API, водночас маючи можливість розпізнавати версію, з якою сумісний певний плагін. Наразі всі інтерфейси версії 1.0.
  • configuration - Це дозволяє плагіну повертати документ JSON, який містить стандартну конфігурацію плагіна. Це відповідає механізму розширюваного плагіна Fledge, кожен плагін повертатиме набір елементів конфігурації, які він бажає використати, потім це буде використано для розширення набору елементів конфігурації Fledge. Ця структура, документ JSON, містить значення за замовчуванням, але не містить фактичних значень для кожного параметра конфігурації. Коли менеджер конфігурації Fledge вперше побачить категорію, він зареєструє категорію та створить значення для кожного елемента, використовуючи значення за замовчуванням у документі конфігурації. Під час наступних викликів буде використано значення, яке вже є в менеджері конфігурацій. Цей механізм дозволяє плагіну розширювати набір змінних конфігурації, надаючи користувачеві можливість змінювати значення цих елементів конфігурації. Це також дозволяє новим версіям плагінів додавати нові елементи конфігурації, зберігаючи значення попередніх елементів. Новим елементам автоматично призначатиметься значення за умовчанням для цього елемента. Як приклад, плагін, який хоче підтримувати дві конфігураційні змінні, скажімо, GPIO для використання та інтервал опитування, повертатиме документ конфігурації, який виглядає наступним чином
{
'pollInterval': {
'description': 'The interval between poll calls to the device poll routine expressed in milliseconds.',
'type': 'integer',
'default': '1000'
},
'gpiopin': {
'description': 'The GPIO pin into which the DHT11 data pin is connected',
'type': 'integer',
'default': '4'
}
}

Різні значення, які можуть відображатися в пункті mode, наведено в таблиці нижче

ModeОпис
pollПлагін є опитуваним модулем, і plugin_poll буде періодично викликатися для отримання нових значень.
asyncПлагін є асинхронним плагіном, plugin_poll не буде викликатися, а плагін буде забезпечено функцією зворотного виклику, яку він викликає щоразу, коли має нове значення для передачі в систему. Точка входу plugin_register_ingest буде викликана, щоб зареєструвати зворотний виклик у плагіні. Виклик plugin_start буде викликано один раз, щоб ініціювати асинхронну доставку даних.
noneЦе еквівалентно опитуванню (poll).
controlПлагін підтримує потік керування до пристрою, до якого підключено плагін. Необхідно надати контрольні точки входу plugin_write і plugin_operation.

Плагін C/C++ повертає ту саму інформацію, що й структура, ця структура включає документ конфігурації JSON у вигляді простого рядка C.

#include <plugin_api.h>

extern "C" {

/**
* The plugin information structure
*/
static PLUGIN_INFORMATION info = {
"MyPlugin", // Name
"1.0.1", // Version
0, // Flags
PLUGIN_TYPE_SOUTH, // Type
"1.0.0", // Interface version
default_config // Default configuration
};

/**
* Return the information about this plugin
*/
PLUGIN_INFORMATION *plugin_info()
{
return &info;
}

У наведеному вище прикладі константа default_config — це рядок, який містить документ конфігурації JSON. Щоб спростити керування JSON, у файлі заголовка plugin_api.h визначено спеціальний макрос. Цей макрос називається QUOTE і призначений для полегшення вимог цитування для створення цього документа JSON.

const char *default_config = QUOTE({
"plugin" : {
"description" : "My example plugin in C++",
"type" : "string",
"default" : "MyPlugin",
"readonly" : "true"
},
"asset" : {
"description" : "The name of the asset the plugin will produce",
"type" : "string",
"default" : "MyAsset"
}
});

Елементи flags містять бітову маску значень прапорів, які використовуються для передачі інформації про поведінку та вимоги плагіна. Нижче наведено значення позначок, які наразі підтримуються

Flag НазваОпис
SP_COMMONВикористовується виключно плагінами зберігання. Плагін підтримує спільний доступ до таблиці, необхідний для збереження конфігурації
SP_READINGSВикористовується виключно плагінами зберігання. Плагін підтримує зберігання даних читання
SP_ASYNCПлагін є асинхронним плагіном, plugin_poll не буде викликатися, а плагін буде забезпечено функцією зворотного виклику, яку він викликає щоразу, коли має нове значення для передачі в систему. Точка входу plugin_register_ingest буде викликана, щоб зареєструвати зворотний виклик у плагіні. Виклик plugin_start буде викликано один раз, щоб ініціювати асинхронну доставку даних. Це стосується лише південних плагінів
SP_PERSIST_DATAПлагін бажає зберігати дані між виконаннями
SP_INGESTНе-південний плагін бажає ввести нові дані в систему. Використовується плагінами сповіщень
SP_GET_MANAGEMENTПлагін потребує доступу до інтерфейсу API керування сервісом
SP_GET_STORAGEПлагін потребує доступу до сервісу зберігання
SP_DEPRECATEDПлагін слід вважати застарілим. Новий сервіс не може використовувати цей плагін, але існуючі сервіси можуть продовжувати його використовувати
SP_BUILTINПлагін не реалізований як зовнішній пакет, а вбудований у систему
SP_CONTROLПлагін реалізує функції керування

Ці "flag values" можна комбінувати за допомогою оператора "або" ("or") де більше одного з наведених вище параметрів підтримується.

Ініціалізація плагіна

Ініціалізація плагіна викликається після того, як сервіс, який завантажив плагін, зібрала інформацію про плагін і вирішила конфігурацію плагіна, але до того, як будуть зроблені будь-які інші виклики плагіна. Процедура ініціалізації викликається з дозволеною конфігурацією плагіна, що включає значення на відміну від значень за замовчуванням, які були повернуті під час виклику plugin_info.

Цей виклик використовується плагіном для будь-якої ініціалізації або створення стану, які йому потрібні. Виклик повертає дескриптор, який буде передано кожному наступному виклику плагіна. Дескриптор дозволяє плагіну створювати інформацію про стан, яка зберігається та передається йому, одночасно дозволяючи службі завантажувати кілька екземплярів одного плагіна, якщо це потрібно. Він еквівалентний покажчику this або self для плагіна, хоча плагін не визначено як клас. Дескриптор — це єдиний спосіб, у який плагін має зберігати інформацію між викликами певної точки входу, а також єдиний спосіб, у який інформація має передаватись між точками входу.

У Python, простому прикладі датчика, який зчитує контакт GPIO для даних, ми можемо вибрати використання цього налаштованого висновку GPIO як дескриптора, який ми передаємо іншим викликам.

def plugin_init(config):
""" Initialise the plugin.

Args:
config: JSON configuration document for the device configuration category
Returns:
handle: JSON object to be used in future calls to the plugin
Raises:
"""

handle = config['gpiopin']['value']
return handle

Плагін C/C++ має повертати значення в покажчику void, яке потім можна розіменувати під час наступних викликів. Типова реалізація C++ може створити екземпляр класу та використовувати цей екземпляр як дескриптор для плагіна.

/**
* Initialise the plugin, called to get the plugin handle
*/
PLUGIN_HANDLE plugin_init(ConfigCategory *config)
{
MyPluginClass *plugin = new MyPluginClass();

plugin->configure(config);

return (PLUGIN_HANDLE)plugin;
}

У наведеному вище прикладі C/C++ виклик plugin_init передається вказівником на клас ConfigCategory, який інкапсулює категорію конфігурації JSON для плагіна. Докладні відомості про клас ConfigCategory доступні в розділі .

Вимкнення плагіна

Метод завершення роботи плагіна викликається як частина послідовності завершення роботи сервіси, яка завантажила плагін. Це дає плагіну можливість виконувати будь-які операції очищення перед завершенням роботи. Як і в усіх викликах, йому передається дескриптор екземпляра нашого плагіна. Плагіни не можуть запобігти завершенню роботи і не повинні виконувати жодних дій. У нашому простому прикладі сенсора немає нічого, щоб вимкнути плагін.

Плагін C/C++ може використовувати цей виклик plugin_shutdown для видалення екземпляра класу плагіна, який він створив у відповідному виклику plugin_init.

/**
* Shutdown the plugin
*/
void plugin_shutdown(PLUGIN_HANDLE *handle)
{
MyPluginClass *plugin = (MyPluginClass *)handle;

delete plugin;
}

Переналаштування плагіна

Метод переналаштування плагіна викликається щоразу, коли змінюється конфігурація плагіна. Це дозволяє динамічно змінювати конфігурацію плагіна під час його роботи. Метод викликається за допомогою дескриптора плагіна та оновленого документа конфігурації. Плагін має виконувати будь-які дії, які йому потрібні, і повертати нову або оновлену копію дескриптора, який буде передано майбутнім викликам.

Метод переналаштування плагіна спільний для більшості, але не для всіх типів плагінів. Зокрема, він не існує для плагінів із коротким терміном служби, які створюються для виконання однієї операції, а потім припиняються. Це північні плагіни та плагіни доставки сповіщень.

Використовуючи простий приклад Python, коли наш датчик зчитує PIN-код GPIO, ми витягуємо новий номер PIN-коду з нових конфігураційних даних і повертаємо його як новий дескриптор для екземпляра плагіна..

def plugin_reconfigure(handle, new_config):
""" Reconfigures the plugin, it should be called when the configuration of the plugin is changed during the
operation of the device service.
The new configuration category should be passed.

Args:
handle: handle returned by the plugin initialisation call
new_config: JSON object representing the new configuration category for the category
Returns:
new_handle: new handle to be used in the future calls
Raises:
"""

new_handle = new_config['gpiopin']['value']
return new_handle

У C/C++ метод plugin_reconfigure дуже подібний, однак зауважте, що виклик plugin_reconfigure передає категорію конфігурації JSON як рядок, а не ConfigCategory, однак його легко проаналізувати та створити клас C++, однак назву категорії необхідно вказати.

/**
* Reconfigure the plugin
*/
void plugin_reconfigure(PLUGIN_HANDLE *handle, string& newConfig)
{
ConfigCategory config("newConfiguration", newConfig);
MyPluginClass *plugin = (MyPluginClass *)*handle;

plugin->configure(&config);
}

Слід зазначити, що виклик plugin_reconfigure може бути доставлений в окремому потоці для плагіна C/C++ і що плагін повинен реалізовувати будь-які механізми взаємного виключення, які необхідні на основі дій методу plugin_reconfigure.

Життєвий цикл Конфігурації

Fledge має дуже особливий спосіб обробки конфігурації, існує низка проектних цілей, які призвели до створення системи конфігурації у Fledge.

  • Бажання дозволити плагінам визначати власні елементи конфігурації.
  • Динамічна конфігурація, яка забезпечує максимальний час безвідмовної роботи під час змін конфігурації.
  • Описовий спосіб визначення конфігурації, щоб інтерфейс користувача можна було створювати без попереднього знання елементів, які потрібно налаштувати.
  • Загальний підхід, який працюватиме багатьма різними мовами.

Fledge поділяє свою конфігурацію на категорії. Категорія є набором елементів конфігурації. Категорія також є найменшим елементом конфігурації, на який можна підписатися за допомогою коду. Цей механізм підписки є тим способом, яким Fledge полегшує динамічну реконфігурацію. Це дозволяє службі підписатися на одну або кілька категорій конфігурації, щоразу, коли елемент у категорії змінюється, центральний менеджер конфігурації викликає обробник для передачі щойно оновленої категорії конфігурації. Цей обробник може бути в межах сервісу або між сервісами, які використовують API керування мікросервісом, який має підтримувати кожний сервіс. Проте механізм прозорий для задіяного коду.

Елементи конфігурації в категорії є об’єктом JSON, ключ об’єкта – це ім’я елемента конфігурації, а сам об’єкт містить дані про цей елемент. Як приклад, якби ми хотіли мати елемент конфігурації під назвою MaxRetries, який є цілим числом із значенням за замовчуванням 5, тоді ми б налаштували його за допомогою об’єкта JSON

"MaxRetries" : {
"type" : "integer",
"default" : "5"
}

Ми використали властивості type і default для визначення властивостей елемента конфігурації MaxRetries. Це не єдині властивості, які може мати елемент конфігурації, повний набір типів елементів і властивостей показано нижче

Типи (Types)

Кожен з елементів конфігурації в категорії конфігурації можна визначити як один із набору типів. Наразі Fledge підтримує такі типи

ТипОпис
integerЦіле числове значення. Значення може бути позитивним або негативним, але не може містити дробової частини. Властивості minimum і maximum можна використовувати для керування межами значень, призначених цілому числу.
floatЧисловий елемент із плаваючою комою. Властивості minimum і maximum можна використовувати для керування межами значень, призначених елементу з плаваючою комою..
stringАлфавітно-цифровий масив символів, який може містити будь-які друковані символи. Властивість length можна використовувати для обмеження максимальної довжини рядка.
booleanЛогічне значення, якому можна присвоїти значення true або false..
IPv4IP-адреса 4 версії.
IPv6IP-адреса 6 версії.
X509 certificateСертифікат X509
passwordРядок, який використовується як пароль. Немає різниці між цим або типом рядка, крім того, що інтерфейси користувача не показують це у звичайному тексті.
JSONДокумент JSON. Значення перевіряється, щоб переконатися, що воно є дійсним документом JSON.
URLРядок універсального покажчика активу. API перевірить правильність форматування URL-адреси значення.
enumerationЕлементу можна призначити одне з фіксованого набору значень. Ці значення визначено у властивості options елемента.
scriptБлок тексту, який виконується як скрипт. Тип скрипту слід використовувати для виконання більших блоків коду.
codeБлок тексту, який виконується як код Python. Це використовується для невеликих фрагментів Python, а не для великих скриптів.
northTaskНазва північної задачі. API перевірить, чи значення відповідає назві існуючого північного завдання.
ACLСписок контролю доступу. Значення — це назва рядка списку керування доступом, створеного у Fledge.
listСписок елементів, елементи можуть бути типу string, intege, float, enumeration або object. Типи елементів у списку мають бути однаковими, і це визначається за допомогою властивості items списку. Обмеження на максимальну кількість записів, дозволених у списку, можна застосувати за допомогою властивості listSize.
kvlistСписок пар ключ-значення. Ключ завжди є рядковим значенням, але значення елемента в списку може мати тип string, enumeration, float, integer або object. Тип значень у списку kvlist визначається властивістю items елемента конфігурації. Обмеження на максимальну кількість записів, дозволених у списку, можна застосувати за допомогою властивості listSize.
objectСкладний тип конфігурації з кількома елементами, які можна використовувати лише в елементах list і kvlist, неможливо мати елементи типу object поза списком. Елементи конфігурації типу об’єкта мають визначений набір властивостей (properties), кожен з яких сам по собі є елементом конфігурації.

Список Ключ/Значення

Список ключ/значення — це спосіб зберігання пар елементів із тегами у списку. Наприклад, щоб створити список міток і виразів, ми можемо використати kvlist, який зберігає вирази як рядкові значення в kvlist.

"expressions" : {
"description" : "A set of expressions used to evaluate and label data",
"type" : "kvlist",
"items" : "string",
"default" : "{\"idle\" : \"speed == 0\"}",
"order" : "4",
"displayName" : "Labels"
}

Ключові значення мають бути унікальними в kvlist, оскільки дані зберігаються як об’єкт JSON, де ключ стає назвою властивості, а значення властивості – відповідним значенням для ключа.

Списки об'єктів

Елементи типу об'єкт можуть використовуватися у списках і є механізмом для створення списків груп елементів конфігурації. Елементи типу списку об'єктів повинні вказувати властивість, яка називається properties. Значенням цієї властивості є JSON-об'єкт, який містить список елементів конфігурації, згрупованих в об'єкті.

Приклад використання списку об'єктів може дозволити побудувати структуру мапи для доступу до такого пристрою, як ПЛК. Нижче наведено визначення списку пар ключ/значення, де значенням є об'єкт.

"map": {
"description": "A list of datapoints to read and PLC register definitions",
"type": "kvlist",
"items" : "object",
"default": "{\"speed\" : {\"register\" : \"10\", \"width\" : \"1\", \"type\" : \"integer\"}}",
"order" : "3",
"displayName" : "PLC Map",
"properties" : {
"register" : {
"description" : "The register number to read",
"displayName" : "Register",
"type" : "integer",
"default" : "0"
},
"width" : {
"description" : "Number of registers to read",
"displayName" : "Width",
"type" : "integer",
"maximum" : "4",
"default" : "1"
},
"type" : {
"description" : "The data type to read",
"displayName" : "Data Type",
"type" : "enumeration",
"options" : [ "integer","float", "boolean" ],
"default" : "integer"
}
}
}

Властивості value і default для списку об’єктів повертаються як структура JSON. Приклад наведеного вище списку з двома елементами в списку, напругою та струмом, буде повернуто таким чином:

{
"voltage" : {
"register" : "10",
"width" : "2",
"type" : "integer"
},
"current" : {
"register" : "14",
"width" : "4",
"type" : "float"
}
}

Властивості (Рroperties)

ВластивістьОпис
defaultСтандартне значення для елемента конфігурації. Це завжди виражається у вигляді рядка, незалежно від типу елемента конфігурації.
deprecatedЛогічний прапорець, який вказує, що цей елемент більше не використовується та буде видалено в наступному випуску.
descriptionОпис елемента конфігурації, який використовується в інтерфейсі користувача, щоб надати додаткові відомості про елемент. Зазвичай використовується як підказка довідки при наведенні миші.
displayNameРядок для використання в інтерфейсі користувача під час представлення елемента конфігурації. Зазвичай більш зручна форма назви елемента. У коді є посилання на назви елементів.
itemsТип елементів у списку або елементі конфігурації kvlist.
lengthМаксимальна довжина рядкового значення елемента.
listSizeМаксимальна кількість записів, дозволених у списку або елементі kvlist.
mandatoryЛогічний прапорець, який вказує, що цей елемент не можна залишати порожнім.
maximumМаксимальне значення для елемента числової конфігурації.
minimumМінімальне значення для елемента числової конфігурації.
optionsВикористовується лише для елементів типу перерахування. Це рядковий масив JSON, який містить параметри в переліку.
orderВикористовується в інтерфейсі користувача, щоб вказати, наскільки високо в діалоговому вікні розмістити цей елемент.
groupВикористовується для групування пов’язаних елементів. Основне використання цього — у графічному інтерфейсі користувача, який перетворює кожну групу на вкладку на екранах створення та редагування.
readonlyЛогічна властивість, яку можна використовувати для включення елементів, які не можна змінити за допомогою API.
ruleПравило перевірки, яке виконуватиметься зі значенням. Це має бути істинним, щоб API прийняв нове значення
typeТип елемента конфігурації. Список підтримуваних типів: integer, float, string, password, enumeration, boolean, JSON, URL, IPV4, IPV6, script, code, сертифікат X509 і northTask.
validityВираз, який використовується для визначення дійсності елемента конфігурації. Використовується в інтерфейсі користувача для виділення сірим кольором одного значення на основі значення інших.
valueПоточне значення елемента конфігурації. Це не включено під час визначення набору стандартних конфігурацій, наприклад, у плагіні.
propertiesНабір елементів, які використовуються в елементах типу list і kvlist для створення списку груп елементів конфігурації.

З наведених вище властивостей елемента конфігурації type, default і description є обов’язковими, усі інші необов’язкові.

Note

Наполегливо рекомендується додавати displayName та order до кожного елемента, щоб покращити відображення екранів конфігурації у графічному інтерфейсі. Якщо категорія конфігурації дуже велика, рекомендується також використовувати властивість group для групування пов'язаних елементів. Ці згруповані елементи відображатимуться на окремих вкладках у поточному графічному інтерфейсі Fledge.

Управління

Дані конфігурації зберігаються в сервісі зберігання і підтримуються конфігурацією в основному сервісі Fledge. Коли код вимагає конфігурації, він створює категорію конфігурації з набором елементів у вигляді JSON-документа. Потім він реєструє цю категорію конфігурації у менеджері конфігурацій. Менеджер конфігурацій відповідає за зберігання даних на рівні зберігання, при цьому він спочатку перевіряє, чи вже існує категорія конфігурації з попереднього виконання коду. Якщо така категорія існує, то вони об'єднуються, цей процес об'єднання дозволяє оновленням програмного забезпечення розширювати категорію конфігурації, зберігаючи при цьому будь-які зміни значень, внесені користувачем.

Динамічна реконфігурація у коді Fledge підтримується завдяки можливості підписки коду на зміни у категорії конфігурації. Сервіси, які завантажують плагін, автоматично реєструються у категорії конфігурації плагіна і при появі змін викликають точку входу plugin_reconfigure плагіна з новою конфігурацією. Це дозволяє плагінам отримати оновлену конфігурацію і виконати необхідні дії для того, щоб врахувати зміни у конфігурації. Це дозволяє змінювати конфігурацію без необхідності зупиняти і перезапускати сервіси, однак деяким плагінам може знадобитися закрити з'єднання і відкрити їх знову, що може спричинити невелику перерву в процесі збору даних. Цей вибір залишається за розробниками окремих плагінів.

Виявлення

За допомогою цієї системи можна виконати обмежену кількість виявлень і налаштувати конфігурацію плагінів. Типовим випадком використання виявлення є виявлення пристроїв у мережі, які можна відстежувати. Цього можна досягти, помістивши код виявлення у точку входу plugin_info і використовуючи цей код для зміни конфігурації за замовчуванням, яка повертається як частина інформаційної структури плагіна.

Прикладом цього може бути наявність у конфігурації переліку пристроїв, які потрібно відстежувати. Тоді код виявлення заповнить елемент параметрів переліку різними пристроями, які він виявив під час виклику plugin_info.

Прикладом точки входу plugin_info, яка виконує ці дії, може бути наступний

/**
* Return the information about this plugin
*/
PLUGIN_INFORMATION *plugin_info()
{
DeviceDiscovery discover;

char *config = discover.discover(default_config, "discovered");
info.config = config;
return &info;
}

Передбачається, що конфігурація в default_config містить елемент перерахування під назвою discovered

"discovered" : {
"description" : "The discovered devices, select 'Manual' to manually enter an IP address",
"type" : "enumeration",
"options" : [ "Manual" ],
"default" : "Manual",
"displayName": "Devices",
"mandatory": "true",
"order" : "2"
},
"IP" : {
"description" : "The IP address of your device, used to add a device that could not be discovered",
"type" : "string",
"default" : "127.0.0.1",
"displayName": "IP Address",
"mandatory": "true",
"order" : "3",
"validity" : "discovered == \"Manual\""
},

Зверніть увагу на використання опції Manual, щоб дозволити введення пристроїв, які не вдалося виявити.

Метод discover виконує власне виявлення і маніпулює конфігурацією JSON для додавання елемента options до елемента конфігурації.

Потім код, який підключається до пристрою, повинен переглянути елемент конфігурації discover, якщо він виявить, що він встановлений на Manual, то він отримає IP-адресу з елемента конфігурації IP. В іншому випадку для підключення буде використано інформацію з елемента discovered, зауважте, що це не обов'язково має бути просто IP-адреса, ви можете відформатувати дані у більш зручний для користувача спосіб, щоб код підключення витягнув те, що йому потрібно, або створити таблицю у методі discover, щоб дозволити користувацькі рядки зіставляти з мережевими адресами.

Приклад тут був написаний на C++, але тут немає нічого специфічного для C++, і такий самий підхід може бути застосований у Python.

Однак слід зазначити, що виклик plugin_info використовується для відображення доступних плагінів, тому дуже повільний код виявлення вплине на продуктивність вибору плагінів.

Написання журналу аудиту

Плагіни можуть записувати записи в контрольний журнал. Ці записи повинні використовувати один із попередньо визначених кодів аудиту, які підтримуються системою. Дивиться для детальної інформації про підтримувані коди аудиту в системі.

У C++ ви використовуєте клас AuditLogger для запису цих записів журналу аудиту, це єдиний об’єкт, доступ до якого здійснюється через метод getLogger.

AuditLogger *audit = AuditLogger::getLogger();
audit->audit("NHDWN", "INFORMATION");

Існує також зручна функція, яку можна використовувати, якщо ви не хочете визначати локальний покажчик AuditLogger

AuditLogger::auditLog("NHAVL", "INFORMATION");