diff --git a/.vscode/settings.json b/.vscode/settings.json index 889b02bd..01779b03 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,48 @@ { "files.associations": { - "array": "cpp" - } + "array": "cpp", + "atomic": "cpp", + "*.tcc": "cpp", + "bitset": "cpp", + "cctype": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "cstdarg": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "list": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "fstream": "cpp", + "functional": "cpp", + "initializer_list": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "new": "cpp", + "ostream": "cpp", + "numeric": "cpp", + "sstream": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "cinttypes": "cpp", + "regex": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "typeinfo": "cpp", + "chrono": "cpp", + "mutex": "cpp", + "ratio": "cpp", + "system_error": "cpp" + }, + "cmake.configureOnOpen": false } \ No newline at end of file diff --git a/include/Class/IoTModule.h b/include/Class/IoTModule.h new file mode 100644 index 00000000..f13d91e7 --- /dev/null +++ b/include/Class/IoTModule.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +struct ModuleInfo +{ + String name; + String key; + String parameters; + String type; +}; + +class IoTModule { + public: + IoTModule(); + ~IoTModule(); + + virtual void* initInstance(String parameters); + virtual ModuleInfo getInfo(); +}; \ No newline at end of file diff --git a/include/Class/IoTSensor.h b/include/Class/IoTSensor.h new file mode 100644 index 00000000..b41fd9bc --- /dev/null +++ b/include/Class/IoTSensor.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +class IoTSensor { + public: + IoTSensor(); + ~IoTSensor(); + + void loop(); + virtual void doByInterval(); + void init(unsigned long interval, String key); + void regEvent(String value, String consoleInfo); + + unsigned long currentMillis; + unsigned long prevMillis; + unsigned long difference; + unsigned long _interval; + String _key; +}; \ No newline at end of file diff --git a/include/items/vSensorDallas.h b/include/items/vSensorDallas.h deleted file mode 100644 index 23704f3e..00000000 --- a/include/items/vSensorDallas.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifdef EnableSensorDallas -#pragma once -#include -#include -#include -#include "Global.h" - -//ИНТЕГРИРУЮ: Объявляем глагольные переменные необходимые интегрируемой библиотеке -extern DallasTemperature sensors; -extern OneWire* oneWire; - -//ИНТЕГРИРУЮ: следим за наименованиями далее -class SensorDallas; - -typedef std::vector MySensorDallasVector; - -class SensorDallas { - public: - //ИНТЕГРИРУЮ: обращаем внимание на параметры, берутся из таблицы настроек - SensorDallas(unsigned long interval, unsigned int pin, unsigned int index, String addr, String key); - ~SensorDallas(); - - void loop(); - void readDallas(); - - private: - unsigned long currentMillis; - unsigned long prevMillis; - unsigned long difference; - unsigned long _interval; - String _key; - String _addr; - unsigned int _pin; - unsigned int _index; -}; - -extern MySensorDallasVector* mySensorDallas2; - -extern void dallas(); -#endif diff --git a/src/BufferExecute.cpp b/src/BufferExecute.cpp index 44d92a3a..8e847417 100644 --- a/src/BufferExecute.cpp +++ b/src/BufferExecute.cpp @@ -15,7 +15,6 @@ #include "items/vSensorBme280.h" #include "items/vSensorBmp280.h" #include "items/vSensorCcs811.h" -#include "items/vSensorDallas.h" #include "items/vSensorDht.h" #include "items/vSensorNode.h" #include "items/vSensorPzem.h" @@ -23,6 +22,15 @@ #include "items/vSensorUltrasonic.h" #include "items/vSensorUptime.h" +#include "Class/LineParsing.h" +#include "Utils/JsonUtils.h" + +#include "Class/IoTModule.h" +#include "Class/IoTSensor.h" + +extern std::vector iotModules; //v3dev: вектор ссылок базового класса IoTModule - интерфейсы для общения со всеми поддерживаемыми системой модулями +extern std::vector iotSensors; //v3dev: вектор ссылок базового класса IoTSensor - список всех запущенных сенсоров + void loopCmdAdd(const String& cmdStr) { if (cmdStr.endsWith(",")) { orderBuf += cmdStr; @@ -73,6 +81,7 @@ void csvCmdExecute(String& cmdStr) { if (count > 1) { // SerialPrint("I", "Items", buf); String order = selectToMarker(buf, " "); //отсечка самой команды + if (order == F("button-out")) { #ifdef EnableButtonOut sCmd.addCommand(order.c_str(), buttonOut); @@ -103,9 +112,9 @@ void csvCmdExecute(String& cmdStr) { #endif //ИНТЕГРИРУЮ: Первая интеграция в ядро. Следим за наименованием } else if (order == F("dallas-temp")) { -#ifdef EnableSensorDallas - sCmd.addCommand(order.c_str(), dallas); -#endif +// #ifdef EnableSensorDallas +// sCmd.addCommand(order.c_str(), dallas); +// #endif } else if (order == F("dht")) { #ifdef EnableSensorDht sCmd.addCommand(order.c_str(), dhtSensor); @@ -161,6 +170,31 @@ void csvCmdExecute(String& cmdStr) { } sCmd.readStr(buf); + + //v3dev: инициируем экземпляр модулей в случае необходимости + for (unsigned int i = 0; i < iotModules.size(); i++) { + SerialPrint("I", "Debug iotModules count", ""); + + ModuleInfo moduleInfo = iotModules[i]->getInfo(); + if (moduleInfo.key == order) { + SerialPrint("I", "Debug moduleInfo.parameters", buf); + + if (moduleInfo.type == "Sensor") { + myLineParsing.update(); //v3dev: пока используем мостик для совместимости версий, предполагается, что настройки сразу будут в JSON + String interval = myLineParsing.gint(); + String pin = myLineParsing.gpin(); + String index = myLineParsing.gindex(); + String addr = myLineParsing.gaddr(); + myLineParsing.clear(); + String strTmp = "{\"addr\": \"" + addr + "\", \"int\": \"" + interval + "\", \"pin\": \"" + pin + "\", \"index\": \"" + index + "\"}"; + + iotSensors.push_back((IoTSensor*)iotModules[i]->initInstance(strTmp)); + } else if (moduleInfo.type == "Container") + { + //iot.push_back((IoTSensor*)iotModules[i]->initInstance(moduleInfo.parameters)); + } + } + } } cmdStr = deleteBeforeDelimiter(cmdStr, "\n"); } diff --git a/src/Class/IoTModule.cpp b/src/Class/IoTModule.cpp new file mode 100644 index 00000000..93afe034 --- /dev/null +++ b/src/Class/IoTModule.cpp @@ -0,0 +1,6 @@ +#include "Class/IoTModule.h" + +IoTModule::IoTModule() {}; +IoTModule::~IoTModule() {}; +void* IoTModule::initInstance(String parameters) {}; +ModuleInfo IoTModule::getInfo() {}; \ No newline at end of file diff --git a/src/Class/IoTSensor.cpp b/src/Class/IoTSensor.cpp new file mode 100644 index 00000000..1229b2b0 --- /dev/null +++ b/src/Class/IoTSensor.cpp @@ -0,0 +1,31 @@ +#include "Utils/JsonUtils.h" +#include "Utils/SerialPrint.h" +#include "Class/ScenarioClass3.h" +#include "Class/IoTSensor.h" + +void IoTSensor::init(unsigned long interval, String key) { + _interval = interval * 1000; + _key = key; +} + +IoTSensor::IoTSensor() {} +IoTSensor::~IoTSensor() {} + +void IoTSensor::loop() { + currentMillis = millis(); + difference = currentMillis - prevMillis; + if (difference >= _interval) { + prevMillis = millis(); + SerialPrint("I", "Sensor", "Вызывается loop"); + this->doByInterval(); + } +} + +void IoTSensor::regEvent(String value, String consoleInfo = "") { + eventGen2(_key, String(value)); + jsonWriteStr(configLiveJson, _key, String(value)); + publishStatus(_key, String(value)); + SerialPrint("I", "Sensor", "'" + _key + "' data: " + String(value) + "' " + consoleInfo); +} + +void IoTSensor::doByInterval() {} \ No newline at end of file diff --git a/src/Init.cpp b/src/Init.cpp index c782c4bc..8bbad937 100644 --- a/src/Init.cpp +++ b/src/Init.cpp @@ -15,7 +15,6 @@ #include "items/vSensorBme280.h" #include "items/vSensorBmp280.h" #include "items/vSensorCcs811.h" -#include "items/vSensorDallas.h" #include "items/vSensorDht.h" #include "items/vSensorNode.h" #include "items/vSensorPzem.h" @@ -161,13 +160,6 @@ void clearVectors() { } pwmOut_KeyList = ""; pwmOut_EnterCounter = -1; -#endif - //================================== - //ИНТЕГРИРУЮ: Вторая интеграция в ядро. Следим за наименованием -#ifdef EnableSensorDallas - if (mySensorDallas2 != nullptr) { - mySensorDallas2->clear(); - } #endif #ifdef EnableSensorUltrasonic if (mySensorUltrasonic != nullptr) { diff --git a/src/Modules/Sensors/IoTSensorDallasTemp.cpp b/src/Modules/Sensors/IoTSensorDallasTemp.cpp new file mode 100644 index 00000000..1b84f40a --- /dev/null +++ b/src/Modules/Sensors/IoTSensorDallasTemp.cpp @@ -0,0 +1,102 @@ +#include "Utils/JsonUtils.h" +#include "Utils/SerialPrint.h" +#include "Utils/StringUtils.h" +#include "Class/IoTSensor.h" +#include "Class/IoTModule.h" + + +#include "DallasTemperature.h" +#include +#include + +extern std::vector iotModules; //v3dev: вектор ссылок базового класса IoTModule - интерфейсы для общения со всеми поддерживаемыми системой модулями +#define IOTDALLASTEMPKEY "dallas-temp" + +//глобальные списки необходимы для хранения объектов об активных линиях 1-wire используемых разными датчиками из модуля. Ключ - номер пина +std::map oneWireTemperatureArray; +std::map sensorsTemperatureArray; + +class IoTSensorDallas: public IoTSensor { + private: + //описание переменных экземпляра датчика - аналог глобальных переменных из Arduino + //для работы библиотеки с несколькими линиями необходимо обеспечить каждый экземпляр класса ссылками на объекты настроенные на эти линии + OneWire* oneWire; + DallasTemperature* sensors; + + //описание параметров передаваемых из настроек датчика из веба + String _addr; + unsigned int _pin; + unsigned int _index; + + public: + //аналог setup() из Arduino + IoTSensorDallas(String parameters) { + init(jsonReadInt(parameters, "int"), IOTDALLASTEMPKEY); //передаем часть базовых параметров в конструктор базового класса для обеспечения работы его методов + _pin = jsonReadInt(parameters, "pin"); + _index = jsonReadInt(parameters, "index"); + _addr = jsonReadStr(parameters, "addr"); + + //учитываем, что библиотека может работать с несколькими линиями на разных пинах, поэтому инициируем библиотеку, если линия ранее не использовалась + if (oneWireTemperatureArray.find(_pin) == oneWireTemperatureArray.end()) { + oneWire = new OneWire((uint8_t)_pin); + sensors = new DallasTemperature(); + sensors->setOneWire(oneWire); + sensors->begin(); + sensors->setResolution(12); + + oneWireTemperatureArray[_pin] = oneWire; + sensorsTemperatureArray[_pin] = sensors; + } else { + oneWire = oneWireTemperatureArray[_pin]; + sensors = sensorsTemperatureArray[_pin]; + } + } + + ~IoTSensorDallas() {} + + //аналог loop() из Arduino но квотируемый по времени параметром interval + void doByInterval() { + //запускаем опрос измерений у всех датчиков на линии + sensors->requestTemperatures(); + + //Определяем адрес. Если парамтер addr не установлен, то узнаем адрес по индексу + DeviceAddress deviceAddress; + if (_addr == "") { + sensors->getAddress(deviceAddress, _index); + } else { + string2hex(_addr.c_str(), deviceAddress); + } + //получаем температуру по адресу + float value = sensors->getTempC(deviceAddress); + + char addrStr[20] = ""; + hex2string(deviceAddress, 8, addrStr); + + regEvent((String)value, "addr: " + String(addrStr)); //обязательный вызов для отправки результата работы + } +}; + +//технический класс для взаимодействия с ядром, меняются только названия +class IoTModuleDallasTemp: public IoTModule { + //обязательный метод для инициализации экземпляра датчика, вызывается при чтении конфигурации. Нужно учитывать, что некоторые датчики могут обеспечивать + //несколько измерений, для каждого будет отдельный вызов. + void* initInstance(String parameters) { + return new IoTSensorDallas(parameters); + }; + + //обязательный метод для отправки информации о модуле, + ModuleInfo getInfo() { + ModuleInfo MI; + MI.key = IOTDALLASTEMPKEY; + MI.name = "Датчик температуры Ds18b20"; + MI.parameters = "{\"addr\": \"\", \"int\": \"10\", \"pin\": \"18\", \"index\": \"0\"}"; + MI.type = "Sensor"; + return MI; + }; +}; + +//точка входа в модуль для заполнения вектора, требуется только изменить имя и прописать в файле api.cpp +void getApiIoTSensorDallasTemp() { + iotModules.push_back(new IoTModuleDallasTemp()); + return; +} \ No newline at end of file diff --git a/src/Modules/api.cpp b/src/Modules/api.cpp new file mode 100644 index 00000000..978f172e --- /dev/null +++ b/src/Modules/api.cpp @@ -0,0 +1,9 @@ +#include "Utils/SerialPrint.h" +//объявляем функцию для добавления модуля в вектор +void getApiIoTSensorDallasTemp(); + +//формируем вектор модулей путем вызова из каждого модуля специальной функции +//в дальнейшем предполагается отключать вызов, если модуль не участвует в сборке +void InitModulesApi() { + getApiIoTSensorDallasTemp(); +} \ No newline at end of file diff --git a/src/items/vSensorDallas.cpp b/src/items/vSensorDallas.cpp deleted file mode 100644 index 3e621bd4..00000000 --- a/src/items/vSensorDallas.cpp +++ /dev/null @@ -1,96 +0,0 @@ -#include "Consts.h" -#ifdef EnableSensorDallas -#include "items/vSensorDallas.h" -#include "BufferExecute.h" -#include "Class/LineParsing.h" -#include "Global.h" -#include "DallasTemperature.h" -#include "Utils/StringUtils.h" - -#include - -//ИНТЕГРИРУЮ: переменные необходимые для работы интегрируемой библиотеки. Аналог Arduino -OneWire* oneWire; -DallasTemperature sensors; - -//ИНТЕГРИРУЮ: -//Для каждого датчика указанного в конфигурации вызывается конструктор для настройки перед запуском. Аналог функции setup() в Arduino. -//В параметрах передаются дополнительные настройки, указанные все в той же таблице настройки устройства. -SensorDallas::SensorDallas(unsigned long interval, unsigned int pin, unsigned int index, String addr, String key) { - //все особые параметры сливаем в локальные переменные экземпляра для будущего доступа - _interval = interval * 1000; - _key = key; - _pin = pin; - _index = index; - _addr = addr; - - //ИНТЕГРИРУЮ: - //вызываем необходимые инициирующие функции интегрируемой библиотеки - oneWire = new OneWire((uint8_t)_pin); - sensors.setOneWire(oneWire); - sensors.begin(); - sensors.setResolution(12); -} - -//ИНТЕГРИРУЮ: оставляем как есть или развиваем, если нужно правильно завершить работу с интегрируемой библиотекой после отключения датчика -SensorDallas::~SensorDallas() {} - -//ИНТЕГРИРУЮ: аналог loop() в Arduino. Требуется изменить, если интегрируемая библиотека нуждается в другом алгоритме квотирования времени. -void SensorDallas::loop() { - currentMillis = millis(); - difference = currentMillis - prevMillis; - if (difference >= _interval) { - prevMillis = millis(); - readDallas(); - } -} - -//ИНТЕГРИРУЮ: вызывается из цикла loop каждый установленный временно интервал в параметрах датчика. Необходимо изменить для чтения данных из датчика. -void SensorDallas::readDallas() { - //запускаем опрос измерений у всех датчиков на линии - sensors.requestTemperatures(); - - //Определяем адрес. Если парамтер addr не установлен, то узнаем адрес по индексу - DeviceAddress deviceAddress; - if (_addr == "") { - sensors.getAddress(deviceAddress, _index); - } else { - string2hex(_addr.c_str(), deviceAddress); - } - - //получаем температуру по адресу - float value = sensors.getTempC(deviceAddress); - - //ИНТЕГРИРУЮ: блок генерации уведомлений в ядре системы. Стоит обратить внимание только на формат выводимого сообщения в консоли. - eventGen2(_key, String(value)); - jsonWriteStr(configLiveJson, _key, String(value)); - publishStatus(_key, String(value)); - char addrStr[20] = ""; - hex2string(deviceAddress, 8, addrStr); - SerialPrint("I", "Sensor", "'" + _key + "' data: " + String(value) + "' addr: " + String(addrStr)); -} - -//ИНТЕГРИРУЮ: глобальная переменная необходима для интеграции в ядро. Следим за наименованием. -MySensorDallasVector* mySensorDallas2 = nullptr; - -//ИНТЕГРИРУЮ: функция вызывается ядром для каждой записи в таблице настроки для создания экземпляров датчиков -//некоторые датчики записаны в таблице в виде нескольких строк, поэтому необходимо контролировать итерации обращения к данной функции -void dallas() { - //ИНТЕГРИРУЮ: не меняем - myLineParsing.update(); - //ИНТЕГРИРУЮ: устанавливаем в соответствии с параметрами таблицы - String interval = myLineParsing.gint(); - String pin = myLineParsing.gpin(); - String index = myLineParsing.gindex(); - String key = myLineParsing.gkey(); - String addr = myLineParsing.gaddr(); - //ИНТЕГРИРУЮ: не меняем - myLineParsing.clear(); - - //ИНТЕГРИРУЮ: блок создания экземпляров датчиков. Обратить внимание на наименования и передаваемые параметры в конструктор - static bool firstTime = true; - if (firstTime) mySensorDallas2 = new MySensorDallasVector(); - firstTime = false; - mySensorDallas2->push_back(SensorDallas(interval.toInt(), pin.toInt(), index.toInt(), addr, key)); -} -#endif diff --git a/src/main.cpp b/src/main.cpp index 86e7ebd6..c017cd1c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -28,7 +28,6 @@ #include "items/vSensorBme280.h" #include "items/vSensorBmp280.h" #include "items/vSensorCcs811.h" -#include "items/vSensorDallas.h" #include "items/vSensorDht.h" #include "items/vSensorNode.h" #include "items/vSensorPzem.h" @@ -36,6 +35,17 @@ #include "items/vSensorUltrasonic.h" #include "items/vSensorUptime.h" //#include "WebServer.h" + +#include +#include "Class/IoTSensor.h" +#include "Class/IoTModule.h" + + +std::vector iotModules; //v3dev: вектор ссылок базового класса IoTModule - интерфейсы для общения со всеми поддерживаемыми системой модулями +std::vector iotSensors; //v3dev: вектор ссылок базового класса IoTSensor - список всех запущенных сенсоров +void InitModulesApi(); //v3dev: инициализация модуля при первом вызове . + + void not_async_actions(); Timings metric; @@ -60,6 +70,10 @@ void setup() { clockInit(); timeInit(); itemsListInit(); + + SerialPrint("I", "Debug", "call setup"); + InitModulesApi(); //v3dev: инициализация модуля при первом вызове . + espInit(); routerConnect(); #ifdef EnableTelegram @@ -146,13 +160,7 @@ void loop() { } } #endif -#ifdef EnableSensorDallas - if (mySensorDallas2 != nullptr) { - for (unsigned int i = 0; i < mySensorDallas2->size(); i++) { - mySensorDallas2->at(i).loop(); - } - } -#endif + #ifdef EnableSensorUltrasonic if (mySensorUltrasonic != nullptr) { for (unsigned int i = 0; i < mySensorUltrasonic->size(); i++) { @@ -234,4 +242,12 @@ void loop() { #ifdef EnableButtonIn myButtonIn.loop(); #endif + + + + + //v3dev: перебираем все экземпляры сенсоров должно заменить в v4 все вызовы сенсоров выше + for (unsigned int i = 0; i < iotSensors.size(); i++) { + iotSensors[i]->loop(); + } } \ No newline at end of file