mirror of
https://github.com/IoTManagerProject/IoTManager.git
synced 2026-03-30 20:09:14 +03:00
Добавил пример модуля
This commit is contained in:
234
src/modules/sensors/ExampleModule/ExampleModule.cpp
Normal file
234
src/modules/sensors/ExampleModule/ExampleModule.cpp
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
//=======================================================================================================
|
||||||
|
// Это файл сенсора, в нем осуществляется чтение сенсора.
|
||||||
|
// для добавления сенсора вам нужно скопировать этот файл и заменить в нем текст 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();
|
||||||
|
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, то сам он не вызовится
|
||||||
|
currentMillis = millis();
|
||||||
|
difference = currentMillis - prevMillis;
|
||||||
|
if (difference >= _interval)
|
||||||
|
{
|
||||||
|
prevMillis = millis();
|
||||||
|
this->doByInterval();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~ExampleModule_A(){};
|
||||||
|
};
|
||||||
|
|
||||||
|
//=========================================================================================================
|
||||||
|
//=========================================================================================================
|
||||||
|
// Второй класс модуля для определения 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> ¶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(){};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//=========================================================================================================
|
||||||
|
//=========================================================================================================
|
||||||
|
// Функция для связи модуля с ядром 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
38
src/modules/sensors/ExampleModule/ExternalLibrary.h
Normal file
38
src/modules/sensors/ExampleModule/ExternalLibrary.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** **
|
||||||
|
** УДАЛИТЬ ЭТО ПРОСТО ПРИМЕР БИБЛИОТЕКИ **
|
||||||
|
** **
|
||||||
|
*******************************************************************************/
|
||||||
|
|
||||||
|
class ExternalLibrary
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/* data */
|
||||||
|
public:
|
||||||
|
ExternalLibrary(/* args */);
|
||||||
|
|
||||||
|
~ExternalLibrary();
|
||||||
|
void begin (int pin);
|
||||||
|
float READ_LIB_DATA_OTHER();
|
||||||
|
};
|
||||||
|
|
||||||
|
ExternalLibrary::ExternalLibrary(/* args */)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ExternalLibrary::~ExternalLibrary()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExternalLibrary::begin(int pin)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
float ExternalLibrary::READ_LIB_DATA_OTHER()
|
||||||
|
{
|
||||||
|
static float f = 0;
|
||||||
|
return f++;
|
||||||
|
}
|
||||||
82
src/modules/sensors/ExampleModule/modinfo.json
Normal file
82
src/modules/sensors/ExampleModule/modinfo.json
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
{
|
||||||
|
"menuSection": "Сенсоры",
|
||||||
|
"configItem": [
|
||||||
|
{
|
||||||
|
"global": 0,
|
||||||
|
"name": "Пример датчика А",
|
||||||
|
"type": "Reading",
|
||||||
|
"subtype": "ExampleModule_A",
|
||||||
|
"id": "Tmp",
|
||||||
|
"widget": "anydataTmp",
|
||||||
|
"page": "Сенсоры",
|
||||||
|
"descr": "Температура",
|
||||||
|
"int": 15,
|
||||||
|
"pin": "32",
|
||||||
|
"round": 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"global": 0,
|
||||||
|
"name": "Пример датчика Б",
|
||||||
|
"type": "Reading",
|
||||||
|
"subtype": "ExampleModule_B",
|
||||||
|
"id": "Press",
|
||||||
|
"widget": "anydataMm",
|
||||||
|
"page": "Сенсоры",
|
||||||
|
"descr": "Давление",
|
||||||
|
"int": 15,
|
||||||
|
"pin": "32",
|
||||||
|
"round": 1,
|
||||||
|
"btn-Example": 100
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"about": {
|
||||||
|
"authorName": "NAME",
|
||||||
|
"authorContact": "https://t.me/NAME",
|
||||||
|
"authorGit": "https://github.com/NAME",
|
||||||
|
"exampleURL": "https://iotmanager.org/wiki",
|
||||||
|
"specialThanks": "",
|
||||||
|
"moduleName": "ExampleModule",
|
||||||
|
"moduleVersion": "1.0",
|
||||||
|
"usedRam": {
|
||||||
|
"esp32_4mb": 15,
|
||||||
|
"esp8266_4mb": 15
|
||||||
|
},
|
||||||
|
"title": "Название модуля",
|
||||||
|
"moduleDesc": "Описание модуля. Что позволяет получить. Особенности работы",
|
||||||
|
"propInfo": {
|
||||||
|
"pin": "Аналоговый GPIO номер, к которому подключен датчик.",
|
||||||
|
"int": "Количество секунд между опросами датчика",
|
||||||
|
"btn-Example": "Кнопка Example. В поле указать ......"
|
||||||
|
},
|
||||||
|
"funcInfo": [
|
||||||
|
{
|
||||||
|
"name": "expampleFunc",
|
||||||
|
"descr": "Пример функции вызываемой из сценария. Принимает Id другого модуля и смотрит его значение",
|
||||||
|
"params": ["ID стороннего модуля"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "expample2",
|
||||||
|
"descr": "Второй Пример функции вызываемой из сценария.",
|
||||||
|
"params": ["Описание педедаваемого параметра",
|
||||||
|
"параметр 2"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "expampleAny",
|
||||||
|
"descr": "Третий Пример функции вызываемой из сценария. С неограниченным числом параметров",
|
||||||
|
"params": ["Описание педедаваемых параметров"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"defActive": false,
|
||||||
|
"usedLibs": {
|
||||||
|
"esp32_4mb": [],
|
||||||
|
"esp32s2_4mb": [],
|
||||||
|
"esp8266_4mb": [],
|
||||||
|
"esp8266_1mb": [],
|
||||||
|
"esp8266_1mb_ota": [],
|
||||||
|
"esp8285_1mb": [],
|
||||||
|
"esp8285_1mb_ota": [],
|
||||||
|
"esp8266_2mb": [],
|
||||||
|
"esp8266_2mb_ota": []
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user