Files
IoTManager/src/modules/sensors/ExampleModule/ExampleModule.cpp

244 lines
16 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//=======================================================================================================
// Это файл сенсора, в нем осуществляется чтение сенсора.
// для добавления сенсора вам нужно скопировать этот файл и заменить в нем текст ExamleModule на название вашего сенсора
// Название должно быть уникальным, коротким и отражать суть сенсора.
// Обязательные библиотеки из ядра IoTM
#include "Global.h"
#include "classes/IoTItem.h"
//! Здесь подключаем стороннюю библиотеку при необходимости (ExternalLibrary заменить)
// #include <ExternalLibrary.h>
#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<IoTValue> &param)
{
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;
}
}