2022-02-15 11:37:31 +01:00
# include "utils/JsonUtils.h"
# include "utils/SerialPrint.h"
# include "classes/IoTItem.h"
2022-02-02 21:40:45 +01:00
# include "WsServer.h"
2022-02-14 12:48:59 +03:00
# include "ESPConfiguration.h"
2022-02-22 20:16:33 +01:00
# include "EventsAndOrders.h"
2022-01-14 21:48:43 +01:00
2022-10-28 22:19:18 +03:00
IoTItem : : IoTItem ( const String & parameters ) {
2022-11-04 17:01:52 +03:00
jsonRead ( parameters , F ( " int " ) , _interval , false ) ;
2023-02-08 11:20:58 +03:00
if ( _interval = = 0 ) enableDoByInt = false ; // выключаем использование периодического выполнения в модуле
2023-02-08 09:39:24 +03:00
if ( _interval > 0 ) _interval = _interval * 1000 ; // если int положителен, то считаем, что получены секунды
if ( _interval < 0 ) _interval = _interval * - 1 ; // если int отрицательный, то миллисекунды
2022-10-22 11:35:21 +03:00
jsonRead ( parameters , F ( " subtype " ) , _subtype , false ) ;
2022-02-22 16:40:46 +01:00
jsonRead ( parameters , F ( " id " ) , _id ) ;
2022-03-04 01:01:13 +03:00
if ( ! jsonRead ( parameters , F ( " multiply " ) , _multiply , false ) ) _multiply = 1 ;
2022-03-01 21:07:17 +03:00
if ( ! jsonRead ( parameters , F ( " plus " ) , _plus , false ) ) _plus = 0 ;
if ( ! jsonRead ( parameters , F ( " round " ) , _round , false ) ) _round = - 1 ;
2022-02-02 21:17:50 +01:00
2022-08-23 23:17:59 +03:00
if ( ! jsonRead ( parameters , F ( " global " ) , _global , false ) ) _global = false ;
2022-02-01 23:04:06 +03:00
String map ;
2022-02-22 16:40:46 +01:00
jsonRead ( parameters , F ( " map " ) , map , false ) ;
2022-02-01 23:04:06 +03:00
if ( map ! = " " ) {
_map1 = selectFromMarkerToMarker ( map , " , " , 0 ) . toInt ( ) ;
_map2 = selectFromMarkerToMarker ( map , " , " , 1 ) . toInt ( ) ;
_map3 = selectFromMarkerToMarker ( map , " , " , 2 ) . toInt ( ) ;
_map4 = selectFromMarkerToMarker ( map , " , " , 3 ) . toInt ( ) ;
2022-09-08 00:27:38 +02:00
} else
_map1 = _map2 = _map3 = _map4 = 0 ;
2022-10-29 20:04:02 +03:00
String valAsStr = " " ;
if ( jsonRead ( parameters , F ( " val " ) , valAsStr , false ) ) // значение переменной или датчика при инициализации если есть в конфигурации
setValue ( valAsStr , false ) ;
jsonRead ( parameters , F ( " needSave " ) , _needSave , false ) ;
2022-12-04 01:37:27 +01:00
if ( _needSave & & jsonRead ( valuesFlashJson , _id , valAsStr , false ) ) // пробуем достать из сохранения значение элемента, если указано, что нужно сохранять
2022-10-29 20:04:02 +03:00
setValue ( valAsStr , false ) ;
2022-02-01 12:51:34 +03:00
}
2022-02-25 15:38:32 +03:00
2022-08-11 15:21:12 +02:00
void IoTItem : : loop ( ) {
if ( enableDoByInt ) {
currentMillis = millis ( ) ;
difference = currentMillis - prevMillis ;
if ( difference > = _interval ) {
prevMillis = millis ( ) ;
this - > doByInterval ( ) ;
}
}
2022-04-27 14:18:44 +03:00
}
2022-02-26 22:42:57 +03:00
String IoTItem : : getValue ( ) {
2022-09-02 18:22:04 +03:00
if ( value . isDecimal ) {
2022-10-07 22:18:05 +03:00
return getRoundValue ( ) ;
2022-09-08 00:27:38 +02:00
} else
return value . valS ;
2022-02-26 22:42:57 +03:00
}
2022-11-04 16:46:49 +03:00
long IoTItem : : getInterval ( ) { return _interval ; }
2022-12-04 01:37:27 +01:00
bool IoTItem : : isGlobal ( ) { return _global ; }
2022-11-07 17:26:24 +03:00
2022-10-29 20:04:02 +03:00
void IoTItem : : setValue ( const String & valStr , bool genEvent ) {
value . isDecimal = isDigitDotCommaStr ( valStr ) ;
2022-12-04 01:37:27 +01:00
2022-10-29 20:04:02 +03:00
if ( value . isDecimal ) {
2022-08-11 15:21:12 +02:00
value . valD = valStr . toFloat ( ) ;
2022-12-22 15:00:25 +03:00
getRoundValue ( ) ;
2022-08-11 15:21:12 +02:00
} else {
value . valS = valStr ;
2022-01-14 21:48:43 +01:00
}
2022-10-29 20:04:02 +03:00
setValue ( value , genEvent ) ;
2022-01-14 21:48:43 +01:00
}
2022-10-29 20:04:02 +03:00
void IoTItem : : setValue ( const IoTValue & Value , bool genEvent ) {
2022-08-11 15:56:57 +02:00
value = Value ;
2022-12-04 01:37:27 +01:00
2022-10-29 20:04:02 +03:00
if ( value . isDecimal ) {
regEvent ( value . valD , " " , false , genEvent ) ;
} else {
regEvent ( value . valS , " " , false , genEvent ) ;
}
2022-08-11 15:56:57 +02:00
}
2022-12-10 02:13:23 +01:00
// метод отправки из модуля дополнительных json полей виджета в приложение и веб интерфейс,
// необходимый для изменения виджетов "на лету" из модуля
2022-12-04 01:37:27 +01:00
void IoTItem : : sendSubWidgetsValues ( String & id , String & json ) {
publishJsonMqtt ( id , json ) ;
2022-12-04 14:50:16 +01:00
publishJsonWs ( id , json ) ;
2022-12-04 01:37:27 +01:00
}
2022-12-10 02:13:23 +01:00
// когда событие случилось
2022-10-29 20:04:02 +03:00
void IoTItem : : regEvent ( const String & value , const String & consoleInfo , bool error , bool genEvent ) {
2022-10-20 00:18:41 +03:00
if ( _needSave ) {
jsonWriteStr_ ( valuesFlashJson , _id , value ) ;
needSaveValues = true ;
}
2022-02-02 21:17:50 +01:00
publishStatusMqtt ( _id , value ) ;
2022-09-08 23:35:19 +02:00
publishStatusWs ( _id , value ) ;
2022-12-04 01:37:27 +01:00
// SerialPrint("i", "Sensor", consoleInfo + " '" + _id + "' data: " + value + "'");
2022-10-29 20:04:02 +03:00
if ( genEvent ) {
generateEvent ( _id , value ) ;
2022-11-04 16:46:49 +03:00
// распространяем событие через хуки
for ( std : : list < IoTItem * > : : iterator it = IoTItems . begin ( ) ; it ! = IoTItems . end ( ) ; + + it ) {
( * it ) - > onRegEvent ( this ) ;
2022-12-04 01:37:27 +01:00
}
2022-11-04 16:46:49 +03:00
2022-12-10 02:13:23 +01:00
// отправка события другим устройствам в сети если не было ошибки
2022-12-22 22:13:35 +03:00
if ( _global & & ! error ) {
2022-10-29 20:04:02 +03:00
String json = " {} " ;
jsonWriteStr_ ( json , " id " , _id ) ;
jsonWriteStr_ ( json , " val " , value ) ;
2022-12-04 01:37:27 +01:00
jsonWriteInt_ ( json , " int " , _interval / 1000 ) ;
2022-10-29 20:04:02 +03:00
publishEvent ( _id , json ) ;
SerialPrint ( " i " , F ( " <=MQTT " ) , " Broadcast event: " + json ) ;
}
2022-10-22 08:00:48 +03:00
}
2022-02-01 23:04:06 +03:00
}
2022-10-07 22:18:05 +03:00
String IoTItem : : getRoundValue ( ) {
2022-12-22 15:00:25 +03:00
if ( ! value . isDecimal ) return value . valS ;
2022-10-07 22:18:05 +03:00
if ( _round > = 0 & & _round < = 6 ) {
int sot = _round ? pow ( 10 , ( int ) _round ) : 1 ;
value . valD = round ( value . valD * sot ) / sot ;
2022-12-04 01:37:27 +01:00
2022-10-07 22:18:05 +03:00
char buf [ 15 ] ;
sprintf ( buf , ( " %1. " + ( String ) _round + " f " ) . c_str ( ) , value . valD ) ;
2022-12-02 13:56:31 +03:00
value . valS = ( String ) buf ;
return value . valS ;
2022-10-07 22:18:05 +03:00
} else {
2022-12-22 15:00:25 +03:00
value . valS = ( String ) value . valD ;
return value . valS ;
2022-10-07 22:18:05 +03:00
}
}
2022-10-29 20:04:02 +03:00
void IoTItem : : regEvent ( float regvalue , const String & consoleInfo , bool error , bool genEvent ) {
2022-03-01 20:16:12 +03:00
value . valD = regvalue ;
2022-10-07 22:18:05 +03:00
if ( _multiply ) value . valD = value . valD * _multiply ;
if ( _plus ) value . valD = value . valD + _plus ;
if ( _map1 ! = _map2 ) value . valD = map ( value . valD , _map1 , _map2 , _map3 , _map4 ) ;
2022-10-29 20:04:02 +03:00
regEvent ( getRoundValue ( ) , consoleInfo , error , genEvent ) ;
2022-01-14 21:48:43 +01:00
}
2022-02-06 09:11:07 +03:00
void IoTItem : : doByInterval ( ) { }
2022-01-15 16:30:34 +01:00
2022-02-16 00:53:52 +01:00
IoTValue IoTItem : : execute ( String command , std : : vector < IoTValue > & param ) { return { } ; }
2022-02-14 12:48:59 +03:00
2022-08-25 15:46:19 +02:00
String IoTItem : : getSubtype ( ) {
return _subtype ;
}
2022-10-30 12:12:15 +03:00
int IoTItem : : getIntFromNet ( ) {
return _intFromNet ;
}
2022-11-04 16:46:49 +03:00
void IoTItem : : getNetEvent ( String & event ) {
event = " {} " ;
jsonWriteStr_ ( event , " id " , _id ) ;
jsonWriteStr_ ( event , " val " , getValue ( ) ) ;
2022-12-04 01:37:27 +01:00
jsonWriteInt_ ( event , " int " , _interval / 1000 ) ;
2022-11-04 16:46:49 +03:00
}
2022-10-30 12:12:15 +03:00
void IoTItem : : setIntFromNet ( int interval ) {
_intFromNet = interval ;
}
void IoTItem : : checkIntFromNet ( ) {
2022-11-01 12:33:39 +03:00
// проверяем элемент на доверие данным.
2022-10-30 12:12:15 +03:00
if ( _intFromNet > = 0 ) {
2023-02-08 11:20:58 +03:00
// если время жизни истекло, то удаляем элемент чуть позже на следующем такте loop
2022-11-01 12:33:39 +03:00
// если это было уведомление не о б ошибке или начале работы, то сообщаем, что сетевое событие давно не приходило
if ( _intFromNet = = 0 & & _id . indexOf ( " onError " ) = = - 1 & & _id . indexOf ( " onStart " ) = = - 1 ) {
SerialPrint ( " E " , _id , " The new data did not come from the network. The level of trust is low. " , _id ) ;
2022-10-30 12:12:15 +03:00
}
_intFromNet - - ;
}
}
2022-12-04 14:50:16 +01:00
// хуки для системных событий (должны начинаться с "on")
2022-11-04 16:46:49 +03:00
void IoTItem : : onRegEvent ( IoTItem * item ) { }
2022-11-25 22:00:33 +03:00
void IoTItem : : onMqttRecive ( String & topic , String & msg ) { }
2022-12-04 14:50:16 +01:00
void IoTItem : : onMqttWsAppConnectEvent ( ) { }
2022-12-14 00:56:25 +01:00
void IoTItem : : onModuleOrder ( String & key , String & value ) { }
2022-11-25 13:45:50 +03:00
2022-12-10 02:13:23 +01:00
// делаем доступным модулям отправку сообщений в телеграм
void IoTItem : : sendTelegramMsg ( bool often , String msg ) { }
2022-09-11 15:41:50 +02:00
2022-12-10 02:13:23 +01:00
// методы для графиков (будет упрощено)
2022-09-22 22:55:04 +02:00
void IoTItem : : publishValue ( ) { }
void IoTItem : : clearValue ( ) { }
void IoTItem : : setPublishDestination ( int publishType , int wsNum ) { } ;
void IoTItem : : clearHistory ( ) { }
2022-09-18 19:29:46 +02:00
void IoTItem : : setTodayDate ( ) { }
2022-08-11 15:21:12 +02:00
String IoTItem : : getID ( ) {
return _id ;
} ;
2022-11-04 16:46:49 +03:00
void IoTItem : : setInterval ( long interval ) {
2022-08-11 15:21:12 +02:00
_interval = interval ;
2022-04-25 10:48:44 +03:00
}
2022-10-01 22:58:27 +03:00
IoTGpio * IoTItem : : getGpioDriver ( ) {
return nullptr ;
2022-08-11 15:56:57 +02:00
}
2022-12-10 02:13:23 +01:00
// сетевое общение====================================================================================================================================
2022-08-11 15:56:57 +02:00
2022-11-01 12:33:39 +03:00
// externalVariable::externalVariable(const String& parameters) : IoTItem(parameters) {
// prevMillis = millis(); // запоминаем текущее значение таймера для выполения doByInterval после int сек
// iAmLocal = false; // указываем, что это сущность прилетела из сети
// //Serial.printf("Call from externalVariable: parameters %s %d\n", parameters.c_str(), _interval);
// }
2022-02-25 13:20:03 +03:00
2022-11-01 12:33:39 +03:00
// externalVariable::~externalVariable() {
// Serial.printf("Call from ~externalVariable: Im dead\n");
// }
2022-02-25 13:20:03 +03:00
2022-11-01 12:33:39 +03:00
// void externalVariable::doByInterval() { // для данного класса doByInterval+int выполняет роль счетчика обратного отсчета до уничтожения
// iAmDead = true;
// }
2022-02-26 22:42:57 +03:00
2022-08-11 15:21:12 +02:00
//=========================================================================================================================================
2022-02-26 22:42:57 +03:00
IoTItem * myIoTItem ;
2022-08-12 16:05:44 +02:00
// поиск элемента модуля в существующей конфигурации
2022-10-28 22:19:18 +03:00
IoTItem * findIoTItem ( const String & name ) {
2022-11-04 16:46:49 +03:00
if ( name = = " " ) return nullptr ;
2022-02-28 01:10:14 +01:00
for ( std : : list < IoTItem * > : : iterator it = IoTItems . begin ( ) ; it ! = IoTItems . end ( ) ; + + it ) {
2022-02-26 22:42:57 +03:00
if ( ( * it ) - > getID ( ) = = name ) return * it ;
}
return nullptr ;
}
2022-08-13 12:18:58 +02:00
// поиск плюс получение значения
2022-10-28 22:19:18 +03:00
String getItemValue ( const String & name ) {
2022-02-28 00:55:43 +03:00
IoTItem * tmp = findIoTItem ( name ) ;
2022-03-02 00:43:43 +01:00
if ( tmp )
return tmp - > getValue ( ) ;
else
return " " ;
2022-02-28 00:55:43 +03:00
}
2022-08-25 02:18:21 +02:00
// существует ли айтем
2022-10-28 22:19:18 +03:00
bool isItemExist ( const String & name ) {
2022-08-25 02:18:21 +02:00
IoTItem * tmp = findIoTItem ( name ) ;
if ( tmp )
return true ;
else
return false ;
}
2022-11-04 16:46:49 +03:00
// создаем временную копию элемента из сети на основе события
2022-11-01 12:33:39 +03:00
IoTItem * createItemFromNet ( const String & itemId , const String & value , int interval ) {
String jsonStr = " { \" id \" : \" " ;
jsonStr + = itemId ;
jsonStr + = " \" , \" val \" : \" " ;
jsonStr + = value ;
jsonStr + = " \" , \" int \" : " ;
jsonStr + = interval ;
jsonStr + = " } " ;
2022-12-04 01:37:27 +01:00
2022-11-04 16:46:49 +03:00
return createItemFromNet ( jsonStr ) ;
}
// создаем временную копию элемента из сети на основе события
IoTItem * createItemFromNet ( const String & msgFromNet ) {
2022-12-04 01:37:27 +01:00
IoTItem * tmpp = new IoTItem ( msgFromNet ) ;
2023-02-08 11:20:58 +03:00
Serial . println ( " vvvvvvvvvvv " + msgFromNet + " " + ( String ) tmpp - > getInterval ( ) ) ;
2022-12-04 01:37:27 +01:00
if ( tmpp - > getInterval ( ) ) tmpp - > setIntFromNet ( tmpp - > getInterval ( ) / 1000 + 5 ) ;
2022-11-01 12:33:39 +03:00
tmpp - > iAmLocal = false ;
IoTItems . push_back ( tmpp ) ;
2022-11-04 16:46:49 +03:00
generateEvent ( tmpp - > getID ( ) , tmpp - > getValue ( ) ) ;
2022-11-01 12:33:39 +03:00
return tmpp ;
}
2022-11-04 16:46:49 +03:00
void analyzeMsgFromNet ( const String & msg , String altId ) {
2023-02-08 09:39:24 +03:00
if ( ! jsonRead ( msg , F ( " id " ) , altId , altId = = " " ) ) return ; // ничего не предпринимаем, если ошибка и altId = "", вообще данная конструкция нужна для совместимости с форматом данных 3 версией
2022-11-04 16:46:49 +03:00
IoTItem * itemExist = findIoTItem ( altId ) ;
if ( itemExist ) {
String valAsStr = msg ;
jsonRead ( msg , F ( " val " ) , valAsStr , false ) ;
long interval = 0 ;
jsonRead ( msg , F ( " int " ) , interval , false ) ;
2022-12-04 01:37:27 +01:00
itemExist - > setInterval ( interval ) ; // устанавливаем такой же интервал как на источнике события
itemExist - > setValue ( valAsStr , false ) ; // только регистрируем изменения в интерфейсе без создания цикла сетевых событий
if ( interval ) itemExist - > setIntFromNet ( interval + 5 ) ; // если пришедший интервал =0, значит не нужно контролировать доверие, иначе даем фору в 5 сек
2022-11-04 16:46:49 +03:00
generateEvent ( altId , valAsStr ) ;
} else {
// временно зафиксируем данные в базе, если локально элемент отсутствует
createItemFromNet ( msg ) ;
2023-02-08 09:39:24 +03:00
//Serial.println("ffffffffff " + msg + " altId=" + altId);
2022-11-04 16:46:49 +03:00
}
}
2022-02-26 22:42:57 +03:00
StaticJsonDocument < JSON_BUFFER_SIZE > docForExport ;
2022-02-28 01:10:14 +01:00
StaticJsonDocument < JSON_BUFFER_SIZE > * getLocalItemsAsJSON ( ) {
2022-02-26 22:42:57 +03:00
docForExport . clear ( ) ;
2022-02-28 01:10:14 +01:00
for ( std : : list < IoTItem * > : : iterator it = IoTItems . begin ( ) ; it ! = IoTItems . end ( ) ; + + it ) {
2022-02-26 22:42:57 +03:00
if ( ( * it ) - > iAmLocal ) docForExport [ ( * it ) - > getID ( ) ] = ( * it ) - > getValue ( ) ;
}
return & docForExport ;
2022-02-14 18:33:52 +03:00
}