<< Click to Display Table of Contents >> Navigation: API MasterSCADA 4D > Функции, ФБ, Протоколы на С++ > API для ФБ и протоколов > Разработка протоколов > Разработка протокола с модулями > Реализация протокола с модулями в C++ |
Пример реализации подключен к Examples.sln как mplc_module_test_protocol:
Для разработки своих собственных протоколов нужно открыть пример и изменить те части проекта, которые отвечают за логику работы. Вспомогательные файлы, служащие для взаимодействия с исполнительной системой, редактировать не требуется.
Для начала по аналогии с простым протоколом создается класс, унаследованный от ScadaProtocol, реализующий требуемый функционал. Необходимы макросы регистрации класса MPLC_OBJECT(ModuleTestProtocol) в секции public. Также переопределению подлежат чисто виртуальные методы Execute(). И вместо метода Create для каналов, необходимо переопределить метод Create для модулей.
Для этого в примере был создан заголовочный файл module_test_protocol.h:
Содержимое файла:
Скриншот |
Текст |
#pragma once #include "test_protocol_module.h"
class ModuleTestProtocol final : public mplc::api::ScadaProtocol { private: std::vector<TestProtocolModule*> modules; Emulator* emulator;
public: MPLC_OBJECT(ModuleTestProtocol); ModuleTestProtocol(); ~ModuleTestProtocol(); void Execute() override; void Init() override; mplc::api::ScadaModule* Create(const mplc::vm::IOModule* module) override; }; |
Протокол и его свойства надо зарегистрировать в файлах исходных кодов макроса MPLC_PROTOCOL_TYPE.
Для этого в примере был создан файл реализации для модулей с настройками: module_test_protocol.cpp:
Содержимое файла:
Скриншот |
Текст |
#include "module_test_protocol.h"
ModuleTestProtocol::ModuleTestProtocol() { emulator = new Emulator(); }
ModuleTestProtocol::~ModuleTestProtocol() { emulator->close(); delete emulator; }
void ModuleTestProtocol::Init() { emulator->init(); }
void ModuleTestProtocol::Execute() { for (auto mod: modules) { mod->Execute(emulator); }
}
mplc::api::ScadaModule* ModuleTestProtocol::Create(const mplc::vm::IOModule* module) { auto mod = new TestProtocolModule(modules.size()); modules.push_back(mod); mplc::api::ScadaModule& req = *mod; return &req; }
MPLC_PROTOCOL_TYPE(ModuleTestProtocol, ModuleTestProtocol);
|
Если при создании модулей необходимо отличать их, то в методе протокола Create для модулей имеется поле SubType класса vm::IOModule, в котором и содержится значение Подтипа модуля, которое указывалось в редакторе.
В отличие от обычного протокола, модульные протоколы содержат модули, которые сами выполняют задачу создания каналов внутри себя. Создать экземпляр класса ScadaModule нельзя, он является абстрактным. Необходимо переопределить метод Create для каналов, так как он чисто виртуальный.
Для этого в примере был создан файл реализации для протокола с настройками: test_protocol_module.h:
Содержимое файла:
Скриншот |
Текст |
#pragma once #include <mplc/api.h>
#include "emulator.h"
class TestProtocolModule : public mplc::api::ScadaModule { private: int modNum; std::vector<mplc::api::ScadaChannel*> channels;
public: TestProtocolModule(int modNum); ~TestProtocolModule(); virtual mplc::api::ScadaChannel* Create(const mplc::vm::Channel* channel, LuaDataProvider* provider) override; virtual void Execute(Emulator *emulator); }; |
В файле исходных кодов работа с макросами регистрации не отличается от обычного протокола.
Для этого в примере был создан файл реализации для протокола с настройками: test_protocol_module.cpp:
Содержимое файла:
Скриншот |
Текст |
#include "test_protocol_module.h"
TestProtocolModule::TestProtocolModule(int modNum) { this->modNum = modNum; }
TestProtocolModule::~TestProtocolModule() {}
mplc::api::ScadaChannel* TestProtocolModule::Create(const mplc::vm::Channel* channel, LuaDataProvider* provider) { auto ch = new mplc::api::ScadaChannel(); channels.push_back(ch); return ch; }
void TestProtocolModule::Execute(Emulator* emulator) { std::string buff;
for (auto ch : channels) { if (ch->InVar) { buff = emulator->read(modNum); ch->Write(LuaProvider(), buff); } if (ch->OutVar) { ch->OutVar->Read(LuaProvider()); ch->OutVar->Value.GetString(buff); emulator->write(modNum, buff); } } } |
Ввод и вывод данных из каналов модулей происходит методами Read и Write класса ScadaChannel. ch - это указатель на класс ScadaChannel.
Важно! Метод Read выдаёт ошибку и не возвращает значение, пока заменяется на комбинацию методов.
Далее можно компилировать проект.
Для компиляции проекта на ОС Windows нужно выполнить команду Build в контекстном меню проекта:
Скомпилированные файлы появятся в папке проекта: C:\mplc\api\platform\x64\bin\Release (адрес действителен, если название папок, которые делал разработчик, совпадают с названиями, которые давались в этой инструкции).
Чтобы произвести сборку под Linux платформы, нужно сохранить проект и перенести все файлы из папки C:\mplc\api (адрес действителен, если название папок, которые делал разработчик, совпадают с названиями, которые давались в этой инструкции) в созданный каталог на компьютере с ОС Linux. Подробнее смотрите в разделе Сборка под Linux платформы.
После сборки можно приступать к тестированию созданного ФБ.