Контроль заданої точки
Південні Плагіни також можна використовувати для керування основним пристроєм, до якого вони підключені. Це не призначено для використання як заміна системам керування у реальному часі, а скоріше як механізм для внесення некритичних за часом змін до пристрою або для запуску операції на пристрої.
Щоб зробити так, щоб пів денний плагін підтримував функції керування, потрібно виконати два кроки
- Позначте плагін як такий, що підтримує керування
- Додайте точки входу для керування
Увімкнути керування
Плагін вмикає функції керування за допомогою прапорів у інформаційній структурі даних плагіна, яка повертається точкою входу plugin_info плагіна. Значення прапора SP_CONTROL слід додати до прапорів плагіна.
/**
* The plugin information structure
*/
static PLUGIN_INFORMATION info = {
PLUGIN_NAME, // Name
VERSION, // Version
SP_CONTROL, // Flags - add control
PLUGIN_TYPE_SOUTH, // Type
"1.0.0", // Interface version
CONFIG // Default configuration
};
Додавання цього прапора призведе до того, що під час завантаження плагіна південний сервіс виконає низку дій;
- Південний сервіс намагатиметься вирішити дві точки входу керування.
- До категорії розширеної конфігурації сервісу буде додано перемикач, який дозволить вимкнути сервіси керування.
- До південного сервісу буде додано категорію безпеки, яка міститиме списки контролю доступу та дозволи, пов'язані з цим сервісом.
Контрольні точки входу
Для операцій керування у південному плагіні підтримуються дві точки входу
- plugin_write: використовується для встановлення значення параметра у плагіні або пристрої
- plugin_operation: використовується для виконання операції над плагіном або пристроєм
Південний Плагін може підтримувати одну або обидві з цих точок входу, залежно від типу плагіна.
Write Entry Point
Точка входу запису використовується для встановлення даних у плагіні або запису даних у пристрій.
Точка входу для запису плагіна визначається наступним чином
bool plugin_write(PLUGIN_HANDLE *handle, string name, string value)
Де знаходяться параметри;
- handle дескриптор екземпляра плагіна
- name ім'я елемента, який потрібно змінити
- value рядкове представлення нового значення, яке буде додано до елемента
Значення, що повертається, визначає, чи був запис успішним чи ні. True повертається в разі успішного запису.
bool plugin_write(PLUGIN_HANDLE *handle, string& name, string& value)
{
Random *random = (Random *)handle;
return random->write(operation, name, value);
}
У цьому випадку основна логіка операції запису реалізована у класі, який містить усю логіку плагіна. Зверніть увагу, що припущенням тут є те, що PLUGIN_HANDLE насправді є вказівником на екземпляр класу C++, що часто використовується авторами плагінів.
У цьому випадку ре алізація у класі плагіна виглядає наступним чином:
bool Random::write(string& name, string& value)
{
if (name.compare("mode") == 0)
{
if (value.compare("relative") == 0)
{
m_mode = RELATIVE_MODE;
}
else if (value.compare("absolute") == 0)
{
m_mode = ABSOLUTE_MODE;
}
Logger::getLogger()->error("Unknown mode requested '%s' ignored.", value.c_str());
return false;
}
else
{
Logger::getLogger()->error("Unknown control item '%s' ignored.", name.c_str());
return false;
}
return true;
}
У цьому випадку код відносно простий, оскільки ми припускаємо, що існує єдиний керуючий параметр, який можна записати - режим роботи. Ми шукаємо відому назву, і якщо передається інша назва, то реєструється помилка і повертається false. Якщо введено правильне ім'я, ми перевіряємо значення і виконуємо відповідні дії. Якщо значення не є розпізнаним, буде зареєстровано помилку, і ми знову повернемо false.
У цьому випадку ми просто встановлюємо значення у плагіні, це також можна зробити за допомогою конфігурації, і у цьому випадку значення буде збережено між перезапусками. Зазвичай управління не використовується для цього, а скоріше для внесення змін у самому підключеному пристрої, наприклад, для зміни значення регістра ПЛК. Це просто приклад для демонстрації механізму.
Точка входу в операцію
Плагін підтримуватиме точку входу в операцію. Вона виконуватиме задану операцію синхронно, очікується, що ця точка входу операції буде викликатися за допомогою окремого потоку, тому плагін повинен реалізовувати операції у безпечному для потоків середовищі.
Точка входу операції запису плагіна визначається наступним чином
bool plugin_operation(PLUGIN_HANDLE *handle, string& operation, int count, PLUGIN_PARAMETER **params)
Де знаходяться параметри;
- handle дескриптор екземпляру плагіна
- operation назва операції, яку потрібно виконати
- count кількість параметрів
- params набір пар ім'я/значення, які передаються операції
Параметр operation має використовуватися плагіном для визначення операції, яка має бути виконана, цій операції також може бути передано декілька параметрів. Кількість цих параметрів передається плагіну в аргументі count, а власне параметри передаються в масиві пар ключ/значення у вигляді рядків.
Повернення з виклику є булевим результатом операції, про невдачу операції або виклик нерозпізнаної операції слід повідомити поверненням значення false. Якщо операція завершилася успішно, слід повернути значення true.
У наступному прикладі показано реалізацію точки входу в операцію плагіна.
bool plugin_operation(PLUGIN_HANDLE *handle, string& operation, int count, PLUGIN_PARAMETER **params)
{
Random *random = (Random *)handle;
return random->operation(operation, count, params);
}
У цьому випадку основна логіка роботи реалізована у класі, який містить усю логіку роботи плагіна. Зверніть увагу, що припущенням тут є те, що PLUGIN_HANDLE насправді є вказівником на екземпляр класу C++, який часто використовують розробники плагінів.
У цьому випадку реалізація у класі плагіна виглядає наступним чином:
/**
* SetPoint operation. We support reseeding the random number generator
*/
bool Random::operation(const std::string& operation, int count, PLUGIN_PARAMETER **params)
{
if (operation.compare("seed") == 0)
{
if (count)
{
if (params[0]->name.compare("seed"))
{
long seed = strtol(params[0]->value.c_str(), NULL, 10);
srand(seed);
}
else
{
return false;
}
}
else
{
srand(time(0));
}
Logger::getLogger()->info("Reseeded random number generator");
return true;
}
Logger::getLogger()->error("Unrecognised operation %s", operation.c_str());
return false;
}
У цьому прикладі метод операції перевіряє назву операції, яку потрібно виконати, цей плагін підтримує лише одну операцію. Якщо назва операції відрізняється, метод створить журнал помилок і поверне false. Якщо операцію розпізнано, він перевірить наявність переданих аргументі в, отримає і використає їх. У цьому випадку може бути передано необов'язковий аргумент seed.
Тут не підключено реальну машину, тому операція відбувається всередині плагіна. У випадку реальної машини операція, швидше за все, спричинить дію на машині, наприклад, запит до машини на повторне калібрування.