//======================================================================================================= // Это файл сенсора, в нем осуществляется чтение сенсора. // для добавления сенсора вам нужно скопировать этот файл и заменить в нем текст ExamleModule на название вашего сенсора // Название должно быть уникальным, коротким и отражать суть сенсора. // Обязательные библиотеки из ядра IoTM #include "Global.h" #include "classes/IoTItem.h" //! Здесь подключаем стороннюю библиотеку при необходимости (ExternalLibrary заменить) // #include #include "ExternalLibrary.h" //удалить, только для примера. Внешние библиотеки правильно в <> //! Объяевляем класс IoTGpio для работы с GPIO extern IoTGpio IoTgpio; //========================================================================================================= //========================================================================================================= // Объявление сторонней библиотекит с использованием глобавльных объектов //======================================================================================================= //! Объявляем стороннюю библиотеку при необходимости (ExternalLibrary заменить) // !!! ЗДЕСЬ И ДАЛЕЕ libXX НАЗВАТЬ уникальным именем) ExternalLibrary *libXX = nullptr; // Функция инициализации библиотечного класса, возвращает Единстрвенный указать на библиотеку // instanceLibXX НАЗВАТЬ по наименованию модуля (instanceДатчикХ) // ПРИ НЕОБХДИМОСТИ передаем любые нужные параметры для инициализации библиотеки (в данном случае PIN) // // !!! ВЫзвать данную функцию нужно хотябы один раз, // но в каждом конструкторе класса модуля ExampleModule_A, ExampleModule_B и т.д. // или можно вывывать постоянно при обращении к библиотеке, типа: instanceLibXX().READ_LIB_DATA_OTHER(); // // !!!!!! В деструкторах ~ExampleModule_B() и ~ExampleModule_A() надо УДАЛЯТЬ объект libXX, ЕСЛИ в функцию instanceLibXX чтото передается. // Удаляем класс библиотеки, а то при переконфигурации в нем не поменяются PIN и дугие параметры передаваемые в библиотеку. // P.S. Не для всех, если используется map или vector то лучше не надо. ExternalLibrary *instanceLibXX(int pin) { if (!libXX) { // Если библиотека ранее инициализировалась, то просто вернем указатель // Инициализируем библиотеку libXX = new ExternalLibrary(); libXX->begin(pin); // При необходимости делаем begin библиотеке } return libXX; } //========================================================================================================= //========================================================================================================= // Первый класс модуля для определения 1-го элемента (параметра) // Служит для запроса и отображения парметра/элемента датчика // IoTManager система модульная: один парметр - один элемент (класс) // //========================================================================================================= //========================================================================================================= // ребенок - родитель class ExampleModule_A : public IoTItem { private: //======================================================================================================= // Секция переменных. // Это секция где Вы можете объявлять переменные и объекты arduino библиотек, что бы // впоследствии использовать их в loop и setup unsigned int _pin; // пользовательская переменная, в данном случае для считывания аналогового сигнала int adc; public: //======================================================================================================= // setup() // это аналог setup из arduino. Здесь вы можете выполнять методы инициализации сенсора. // Такие как ...begin и подставлять в них параметры полученные из web интерфейса. // Все параметры хранятся в перемененной parameters, вы можете прочитать любой параметр используя jsonRead функции: // jsonReadStr, jsonReadBool, jsonReadInt ExampleModule_A(String parameters) : IoTItem(parameters) { // Читаем пользовательскую переменную PIN, должна быть объявлена в в modeinfo.json _pin = jsonReadInt(parameters, "pin"); // другой вариант чтения парметров модуля jsonRead(parameters, F("int"), _interval, false); } //======================================================================================================= // doByInterval() - основная функция периодической работы // это аналог loop из arduino, но вызываемый каждые int секунд, заданные в настройках. Здесь вы должны выполнить чтение вашего сенсора // а затем выполнить regEvent - это регистрация произошедшего события чтения // здесь так же доступны все переменные из секции переменных, и полученные в setup // если у сенсора несколько величин то делайте несколько regEvent // не используйте delay - помните, что данный loop общий для всех модулей. Если у вас планируется длительная операция, постарайтесь разбить ее на порции // и выполнить за несколько тактов void doByInterval() { // Пример получения данных из библиотеки, где READ_LIB_DATA_OTHER - функция Вашей библиотеки value.valD = instanceLibXX(_pin)->READ_LIB_DATA_OTHER(); // Здесь Наменование произвольным но понятным к какому модулю относится regEvent(value.valD, "ExampleModule"); // обязательный вызов хотяб один для регистрации события в ядре IoTM } //======================================================================================================= // loop(), если не нужно переопределять, удалить. // полный аналог loop() из arduino. Нужно помнить, что все модули имеют равный поочередный доступ к центральному loop(), поэтому, необходимо следить // за задержками в алгоритме и не создавать пауз. Кроме того, данная версия перегружает родительскую, поэтому doByInterval() отключается, если // не повторить механизм расчета интервалов. void loop() { // Пример получения данных с аналоговым датчиком adc = IoTgpio.analogRead(_pin); // Блок вызова doByInterval, так как если определили loop, то сам он не вызовится IoTItem::loop(); } ~ExampleModule_A() { // Удаляем класс библиотеки, а то при переконфигурации в нем не поменяются PIN и дугие параметры передаваемые в библиотеку. delete libXX; libXX = nullptr; }; }; //========================================================================================================= //========================================================================================================= // Второй класс модуля для определения 2-го элемента (параметра) // Делается по аналогии с первым классом, служит для запроса и отображения другого парметра если их несколько с одного датчика // IoTManager система модульная: один парметр - один элемент (класс) // // Содержит описание дополнительных методов onModuleOrder и execute //========================================================================================================= //========================================================================================================= class ExampleModule_B : public IoTItem { private: // Пользовательские переменные unsigned int _pin; public: ExampleModule_B(String parameters) : IoTItem(parameters) { // Читаем пользовательскую переменную PIN, должна быть объявлена в в modeinfo.json _pin = jsonReadInt(parameters, "pin"); // Можно инициализировать библиотеку один раз, а потом используем указатель instanceLibXX(_pin); libXX->READ_LIB_DATA_OTHER(); } void doByInterval() { // Пример получения данных из библиотеки, где READ_LIB_DATA_OTHER - функция Вашей библиотеки value.valD = libXX->READ_LIB_DATA_OTHER(); // Здесь Наменование произвольным но понятным к какому модулю относится regEvent(value.valD, "ExampleModule"); // обязательный вызов хотяб один для регистрации события в ядре IoTM } //================ обработка кнопок из конфигурации =================== // Хук (переопределение виртуальной функции) для обработки кнопки (в value будут данные с собственной панели ввода) // Что бы кнопка была без поля ввода, нужно в modeinfo.json указать "btn-Example": nil void onModuleOrder(String &key, String &value) { if (key == "Example") // название кнопки btn-Example { SerialPrint("i", F("Sensor ExampleModule"), "User run calibration " + value); // ЧТО ТО Делаем } } //================ обработка команд из сценария=================== // Хук (переопределение виртуальной функции) для обработки команды из сценария (в param будут даныые переданные в функции в сценарии) IoTValue execute(String command, std::vector ¶m) { if (command == "expampleFunc") { if (param.size()) { // Забираем данные из другого модуля по его ID // Если в сценарии передадим id модуля String value = getItemValue(param[0].valS); // Что то делаем с этим параметром return {}; } } else if (command == "expample2") { if (param.size() == 2) { SerialPrint("i", F("Sensor ExampleModule"), "expample2: " + param[0].valS + ", " + param[1].valS); // Передаем полученные данные на дальнейшую обработку // foo(param[0].valS, param[1].valS); return {}; } } else if (command == "expampleAny") { if (param.size() >= 1) { int sizeOfParam = param.size(); for (unsigned int i = 0; i < sizeOfParam; i++) { SerialPrint("i", F("Sensor ExampleModule"), "expampleAny: " + param[i].valS); // Что то делаем с каждым принятым значением // foo(param[i].valD); } } } return {}; } void foo(String logid, String value) { // Прсото пример кокой-то функции } ~ExampleModule_B() { // Удаляем класс библиотеки, а то при переконфигурации в нем не поменяются PIN и дугие параметры передаваемые в библиотеку. delete libXX; libXX = nullptr; }; }; //========================================================================================================= //========================================================================================================= // Функция для связи модуля с ядром IoTM // !!! ЗДЕСЬ getAPI_ИМЯ ИМЯ должно совпадать с "moduleName" из modeinfo.json // после замены названия сенсора, на функцию можно не обращать внимания // если сенсор предполагает использование общего объекта библиотеки для нескольких экземпляров сенсора, то в данной функции необходимо предусмотреть // создание и контроль соответствующих глобальных переменных //========================================================================================================= //========================================================================================================= void *getAPI_ExampleModule(String subtype, String param) { if (subtype == F("ExampleModule_A")) { // !!! ЗДЕСЬ subtype ДОЛЖЕН СОВПАДАТЬ С subtype из modeinfo.json return new ExampleModule_A(param); } else if (subtype == F("ExampleModule_B")) { // !!! ЗДЕСЬ subtype ДОЛЖЕН СОВПАДАТЬ С subtype из modeinfo.json return new ExampleModule_B(param); } else { return nullptr; } }