Skip to main content

Контроль заданої точки

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

Щоб зробити так, щоб південний плагін підтримував функції керування, потрібно виконати два кроки

  • Позначте плагін як такий, що підтримує керування
  • Додайте точки входу для керування

Увімкнути керування

Плагін вмикає функції керування за допомогою прапорів у інформаційній структурі даних плагіна, яка повертається точкою входу 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.

Тут не підключено реальну машину, тому операція відбувається всередині плагіна. У випадку реальної машини операція, швидше за все, спричинить дію на машині, наприклад, запит до машини на повторне калібрування.