diff --git a/lighthub/item.cpp b/lighthub/item.cpp index 8faaac0..d74b603 100644 --- a/lighthub/item.cpp +++ b/lighthub/item.cpp @@ -369,21 +369,21 @@ int Item::getArg(short n) //Return arg int or first array element if Arg is arra float Item::getFloatArg(short n) //Return arg float or first array element if Arg is array { - if (!itemArg) return 0;//-1; + if (!itemArg) return 0.0;//-1; if ((itemArg->type == aJson_Array) && ( n < aJson.getArraySize(itemArg))) { aJsonObject * obj = aJson.getArrayItem(itemArg, n); - if (obj && obj->type == aJson_Int) return obj->valueint; + if (obj && obj->type == aJson_Int) return static_cast (obj->valueint); if (obj && obj->type == aJson_Float) return obj->valuefloat; - return 0; + return 0.0; } else if (!n) { - if (itemArg->type == aJson_Int) return itemArg->valueint; + if (itemArg->type == aJson_Int) return static_cast(itemArg->valueint); else if (itemArg->type == aJson_Float) return itemArg->valuefloat; } - return 0; + return 0.0; } short Item::getArgCount() diff --git a/lighthub/main.cpp b/lighthub/main.cpp index 37ad6fe..0f72194 100644 --- a/lighthub/main.cpp +++ b/lighthub/main.cpp @@ -2192,12 +2192,33 @@ void setup_main() { #endif //debugSerialPort << "Checkin EEPROM integrity (signature)"<4) needClean = true; + i++; +} + +//if (needClean) cmdFunctionClearEEPROM(0, NULL); +#endif + + if (!sysConf.isValidSysConf() || needClean) { #if defined(debugSerialPort) && !defined(NOSERIAL) - debugSerialPort.println(F("No valid EEPROM data. Initializing.")); + debugSerialPort.println(F("Initializing EEPROM.")); #endif - sysConf.clear(); + cmdFunctionClearEEPROM(0, NULL); + //sysConf.clear(); } else debugSerialPort << F("EEPROM signature ok")< THERMO_OVERHEAT_CELSIUS) mqttClient.publish("/alarm/ovrht", thermoItem->name); + if (curTemp > overHeatTemp) mqttClient.publish("/alarm/ovrht", thermoItem->name); if (!active) thermoRelay(thermoPin,HEATER_OFF);//OFF else if (curTemp < thermoSetting - THERMO_GIST_CELSIUS) thermoRelay(thermoPin,HEATER_HEAT);//ON diff --git a/lighthub/modules/out_ac.cpp b/lighthub/modules/out_ac.cpp index 5506a19..444651d 100644 --- a/lighthub/modules/out_ac.cpp +++ b/lighthub/modules/out_ac.cpp @@ -24,7 +24,7 @@ extern bool disableCMD; #define AC_IDLE CST_INITIALIZED #define AC_SENDING 2 -byte inCheck = 0; +//byte inCheck = 0; byte qstn[] = {255,255,10,0,0,0,0,0,1,1,77,1,90}; // Команда опроса byte on[] = {255,255,10,0,0,0,0,0,1,1,77,2,91}; // Включение кондиционера @@ -66,6 +66,20 @@ void out_AC::getConfig(){ } +void out_AC::SubmitParameters(const char * name, itemCmd value){ + + if (!item || !item->itemArg) return; + if ((item->itemArg->type == aJson_Array) && ( 1 < aJson.getArraySize(item->itemArg))) + { + aJsonObject * callbackObj = aJson.getArrayItem(item->itemArg, 1); + if (callbackObj && callbackObj->type == aJson_Object) + { + aJsonObject * execObj = aJson.getObjectItem(callbackObj,name); + if (execObj) executeCommand(execObj,-1,value); + } + } +} + void out_AC::InsertData(byte data[], size_t size){ int fresh =0; @@ -77,7 +91,8 @@ void out_AC::InsertData(byte data[], size_t size){ int fan_spd = 0; - char s_mode[10]; + char s_buffer[10]; + itemCmd icmd; set_tmp = data[B_SET_TMP]+16; if (set_tmp>40 || set_tmp<16) return; @@ -128,18 +143,47 @@ void out_AC::InsertData(byte data[], size_t size){ //publishTopic(item->itemArr->name, (long) fan_spd,"/fan"); ///////////////////////////////// + s_buffer[0]='\0'; + switch (fan_spd){ + case 0x00: + strcpy_P(s_buffer,HIGH_P); + icmd.Cmd(CMD_HIGH); + break; + case 0x01: + strcpy_P(s_buffer,MED_P); + icmd.Cmd(CMD_MED); + break; + case 0x02: + strcpy_P(s_buffer,LOW_P); + icmd.Cmd(CMD_LOW); + break; + case 0x03: + strcpy_P(s_buffer,AUTO_P); + icmd.Cmd(CMD_AUTO); + break; + default: + strcpy_P(s_buffer,ERROR_P); + icmd.Cmd(CMD_VOID); + } +publishTopic(item->itemArr->name, s_buffer,"/fan"); +SubmitParameters("fan",icmd); + + /* if (fan_spd == 0x00){ publishTopic(item->itemArr->name, "high","/fan"); + SubmitParameters("fan","") } if (fan_spd == 0x01){ publishTopic(item->itemArr->name, "medium","/fan"); } + if (fan_spd == 0x02){ publishTopic(item->itemArr->name, "low","/fan"); } if (fan_spd == 0x03){ publishTopic(item->itemArr->name, "auto","/fan"); } +*/ if (swing == 0x00) publishTopic(item->itemArr->name, "OFF","/swing"); @@ -159,33 +203,47 @@ void out_AC::InsertData(byte data[], size_t size){ publishTopic(item->itemArr->name,(long)set_tmp,"/set"); if (cur_tmp!=255) publishTopic(item->itemArr->name, (long)cur_tmp, "/temp"); //////////////////////////////////// - s_mode[0]='\0'; + + //itoa(set_tmp,s_buffer,10); + //SubmitParameters("set",itemCmd().Int((int32_t)set_tmp).setSuffix(S_SET)); + SubmitParameters("set",itemCmd().Int((int32_t)set_tmp)); + + //itoa(cur_tmp,s_buffer,10); + SubmitParameters("temp",itemCmd().Int((int32_t)cur_tmp).setSuffix(S_VAL)); + + s_buffer[0]='\0'; if (store->mode == 0x00){ - strcpy_P(s_mode,AUTO_P); + strcpy_P(s_buffer,AUTO_P);icmd.Cmd(CMD_AUTO); } else if (store->mode == 0x01){ - strcpy_P(s_mode,COOL_P); + strcpy_P(s_buffer,COOL_P);icmd.Cmd(CMD_COOL); } else if (store->mode == 0x02){ - strcpy_P(s_mode,HEAT_P); + strcpy_P(s_buffer,HEAT_P);icmd.Cmd(CMD_HEAT); } else if (store->mode == 0x03){ - strcpy_P(s_mode,FAN_ONLY_P); + strcpy_P(s_buffer,FAN_ONLY_P);icmd.Cmd(CMD_FAN); } else if (store->mode == 0x04){ - strcpy_P(s_mode,DRY_P); + strcpy_P(s_buffer,DRY_P);icmd.Cmd(CMD_DRY); } else if (store->mode == 109){ - strcpy_P(s_mode,ERROR_P); + strcpy_P(s_buffer,ERROR_P);icmd.Cmd(CMD_VOID); } publishTopic(item->itemArr->name, (long) store->mode, "/mode"); + if (!(store->power & 0x01)) {strcpy_P(s_buffer,OFF_P);icmd.Cmd(CMD_OFF);} + publishTopic(item->itemArr->name, s_buffer,"/cmd"); + SubmitParameters("cmd",icmd); + /* if (store->power & 0x01) - publishTopic(item->itemArr->name, s_mode,"/cmd"); + publishTopic(item->itemArr->name, s_buffer,"/cmd"); else publishTopic(item->itemArr->name, "OFF","/cmd"); + */ + /* String raw_str; char raw[75]; @@ -220,6 +278,10 @@ if (item->itemArr->subtype == AC_SENDING) while (store->timestamp && !isTimeOver(store->timestamp,millis(),150)) yield(); } + //#if defined (__SAM3X8E__) + //if (item->getArg(0)==2) preTransmission(); + //#endif + ACSerial->write(req, size - 1); ACSerial->write(getCRC(req, size-1)); //ACSerial->flush(); @@ -238,6 +300,9 @@ if (item->itemArr->subtype == AC_SENDING) } debugSerial.println(); item->itemArr->subtype = AC_SENDING; +// #if defined (__SAM3X8E__) +// if (item->getArg(0)==2) postTransmission(); +// #endif } inline unsigned char toHex( char ch ){ @@ -268,6 +333,7 @@ if (!portNum)// && (g_APinDescription[0].ulPinType == PIO_PA8A_URXD)) pinMode(0, INPUT_PULLUP); #if debugSerial == Serial infoSerial<pollingRegisters=aJson.getObjectItem(pollObj, "regs"); store->pollingIrs=aJson.getObjectItem(pollObj, "irs"); + store->pollingCoils=aJson.getObjectItem(pollObj, "coils"); + store->poolingDiscreteIns=aJson.getObjectItem(pollObj, "dins"); aJsonObject * delayObj= aJson.getObjectItem(pollObj, "delay"); if (delayObj) store->pollingInterval = delayObj->valueint; else store->pollingInterval = 1000; @@ -242,31 +246,41 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin //bool is8bit = false; while (paramObj) - { + { + int8_t parType = PAR_I16; aJsonObject *regObj=NULL; switch (regType) { - case MODBUS_HOLDING_REG_TYPE: regObj = aJson.getObjectItem(paramObj, "reg"); + case MODBUS_HOLDING_REG_TYPE: + regObj = aJson.getObjectItem(paramObj, "reg"); break; - case MODBUS_INPUT_REG_TYPE: regObj = aJson.getObjectItem(paramObj, "ir"); + case MODBUS_INPUT_REG_TYPE: + regObj = aJson.getObjectItem(paramObj, "ir"); + break; + case MODBUS_COIL_REG_TYPE: + regObj = aJson.getObjectItem(paramObj, "coil"); + parType = PAR_COIL; + break; + case MODBUS_DISCRETE_REG_TYPE: + regObj = aJson.getObjectItem(paramObj, "din"); + parType = PAR_COIL; } if (regObj && regObj->valueint ==registerNum) { - aJsonObject *typeObj = aJson.getObjectItem(paramObj, "type"); - aJsonObject *mapObj = aJson.getObjectItem(paramObj, "map"); - aJsonObject *idObj = aJson.getObjectItem(paramObj, "id"); + aJsonObject *idObj = aJson.getObjectItem(paramObj, "id"); aJsonObject * itemParametersObj = aJson.getArrayItem(item->itemArg, 2); uint16_t data = node.getResponseBuffer(posInBuffer); - int8_t regType = PAR_I16; - uint32_t param =0; - itemCmd mappedParam; bool executeWithoutCheck=false; //Afler recurrent check, all dublicatess and suppressing checked by recurrent bool submitRecurrentOut = false; //false if recurrent check find duplicates char buf[16]; - //bool isSigned=false; - if (typeObj && typeObj->type == aJson_String) regType=str2regSize(typeObj->valuestring); - switch(regType) { + uint32_t param =0; + itemCmd mappedParam; + aJsonObject *typeObj = aJson.getObjectItem(paramObj, "type"); + aJsonObject *mapObj = aJson.getObjectItem(paramObj, "map"); + + if (typeObj && typeObj->type == aJson_String) parType=str2regSize(typeObj->valuestring); + switch(parType) { case PAR_I16: //isSigned=true; @@ -278,6 +292,7 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin param=data; mappedParam.Int((uint32_t)data); break; + case PAR_I32: //isSigned=true; param = swap(data ) | swap(node.getResponseBuffer(posInBuffer+1)<<16); @@ -310,15 +325,104 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin param=data; mappedParam.Tens_raw((int16_t) data * (TENS_BASE/100)); mappedParam.Float((int32_t) (int16_t) data/100.); + break; + + case PAR_COIL: + param = (node.getResponseBuffer(posInBuffer/16) >> (posInBuffer % 16)) & 1; + mappedParam.Int((uint32_t)param); } - debugSerial << F("MBUSD: got ")<name<name<type==aJson_Array || mapObj->type==aJson_Object)) { mappedParam=mappedParam.doReverseMapping(mapObj); if (!mappedParam.isCommand() && !mappedParam.isValue()) //Not mapped { + aJsonObject *defMappingObj; + defMappingObj = aJson.getObjectItem(mapObj, "def"); + if (defMappingObj) + { + switch (defMappingObj->type) + { + case aJson_Int: //register/coil/.. number + debugSerial<valueint<valueint>= registerFrom) && (defMappingObj->valueint<=registerTo)) + { + mappedParam = findRegister(defMappingObj->valueint,defMappingObj->valueint-registerFrom,regType,registerFrom,registerTo,false,&submitRecurrentOut); + executeWithoutCheck=true; + } + else errorSerial<valuestring<type ==aJson_Object) + { + //Searching item param for nested mapping + aJsonObject *itemParObj = aJson.getObjectItem(itemParametersObj,defMappingObj->valuestring); + if (itemParObj) + { + //aJsonObject * markObj = execObj; + //if (execObj->type == aJson_Array) markObj = execObj->child; + //Retrive previous data + aJsonObject *lastMeasured = aJson.getObjectItem(itemParObj,"@S"); + if (lastMeasured && lastMeasured->type ==aJson_Int) + { + debugSerial<valueint<parameters,defMappingObj->valuestring); + if (templateParObj) + { + int8_t nestedParType = PAR_I16; + + aJsonObject * nestedTypeObj = aJson.getObjectItem(templateParObj, "type"); + if (nestedTypeObj && nestedTypeObj->type == aJson_String) parType=str2regSize(nestedTypeObj->valuestring); + + switch(nestedParType) { + case PAR_I16: + case PAR_I32: + mappedParam.Int((int32_t)lastMeasured->valueint); + break; + + case PAR_U32: + case PAR_U16: + case PAR_U8L: + case PAR_U8H: + case PAR_COIL: + mappedParam.Int((uint32_t)lastMeasured->valueint); + break; + + case PAR_TENS: + mappedParam.Tens((int16_t) data); + break; + + case PAR_100: + mappedParam.Tens_raw((int16_t) lastMeasured->valueint * (TENS_BASE/100)); + mappedParam.Float((int32_t) (int16_t) lastMeasured->valueint/100.); + break; + default: errorSerial<type==aJson_Array || nestedMapObj->type==aJson_Object)) mappedParam=mappedParam.doReverseMapping(nestedMapObj); + debugSerial << F("MBUSD: NestedMapped:")<subtype & MB_VALUE_OUTDATED)) + { + executeWithoutCheck=true; + submitRecurrentOut=true; + lastMeasured->subtype|= MB_VALUE_OUTDATED; + } + + } + } + } + } + break; + } + } +/* aJsonObject *nextRegObj = NULL; int registerType = 0; @@ -328,15 +432,26 @@ itemCmd out_Modbus::findRegister(uint16_t registerNum, uint16_t posInBuffer, uin { nextRegObj = aJson.getObjectItem(paramObj, "nextir"); if (nextRegObj) registerType=MODBUS_INPUT_REG_TYPE; + else + { + nextRegObj = aJson.getObjectItem(paramObj, "nextcoil"); + if (nextRegObj) registerType=MODBUS_COIL_REG_TYPE; + else + { + nextRegObj = aJson.getObjectItem(paramObj, "nextdin"); + if (nextRegObj) registerType=MODBUS_DISCRETE_REG_TYPE; + } + } } - - if (registerType && (nextRegObj->type) ==aJson_Int && (nextRegObj->valueint>= registerFrom) && (nextRegObj->valueint<=registerTo)) + + if (registerType && nextRegObj && (nextRegObj->type) ==aJson_Int && (nextRegObj->valueint>= registerFrom) && (nextRegObj->valueint<=registerTo)) { debugSerial<valueint,nextRegObj->valueint-registerFrom,registerType,registerFrom,registerTo,false,&submitRecurrentOut); executeWithoutCheck=true; } - else errorSerial<valueint == param) *submitParam=false; //supress repeating execution for same val - else lastMeasured->valueint=param; + else + { + lastMeasured->valueint=param; + lastMeasured->subtype&=~MB_VALUE_OUTDATED; + } } } else //No container to store value yet @@ -416,19 +535,16 @@ return itemCmd(); { if (!reg) return; reg=reg->child; - //aJsonObject * reg = store->pollingRegisters->child; while (reg) { switch (reg->type) { case aJson_Int: { - int registerNum = reg->valueint; - //if (readModbus(registerNum,MODBUS_HOLDING_REG_TYPE,1)) + int registerNum = reg->valueint; if (readModbus(registerNum,regType,1)) { findRegister(registerNum,0,regType,registerNum,registerNum); - // data = node.getResponseBuffer(j); } } break; @@ -438,14 +554,12 @@ return itemCmd(); int registerFrom=aJson.getArrayItem(reg, 0)->valueint; int registerTo=aJson.getArrayItem(reg, 1)->valueint; - //if (readModbus(registerFrom,MODBUS_HOLDING_REG_TYPE,registerTo-registerFrom+1)) if (readModbus(registerFrom,regType,registerTo-registerFrom+1)) { debugSerial<valueint,(value & 0xFFFF)>> 8); break; + case PAR_COIL: + res = node.writeSingleCoil (regObj->valueint,value); + break; } mbusSlenceTimer = millisNZ(); debugSerial<valueint<itemArg, 2); if (itemParametersObj && itemParametersObj->type ==aJson_Object) { aJsonObject *execObj = itemParametersObj->child; - while (execObj && (execObj->type == aJson_Object) || (execObj->type == aJson_Array) ) + bool onceSendOk=false; + while (execObj && ((execObj->type == aJson_Object) || (execObj->type == aJson_Array)) && !onceSendOk) { if ((execObj->subtype & MB_NEED_SEND) && !(execObj->subtype & MB_SEND_ERROR)) @@ -553,6 +677,7 @@ if (itemParametersObj && itemParametersObj->type ==aJson_Object) { case 1: //success execObj->subtype&=~ MB_NEED_SEND; + onceSendOk=true; ///return 1; //relax break; @@ -597,7 +722,7 @@ if (itemParametersObj && itemParametersObj->type ==aJson_Object) } // if some polling configured -if (store->pollingRegisters || store->pollingIrs) +if (store->pollingRegisters || store->pollingIrs || store->pollingCoils || store->poolingDiscreteIns) { debugSerial<itemArr->name << endl; modbusBusy=1; @@ -610,6 +735,8 @@ if (store->pollingRegisters || store->pollingIrs) pollModbus(store->pollingRegisters,MODBUS_HOLDING_REG_TYPE); pollModbus(store->pollingIrs,MODBUS_INPUT_REG_TYPE); + pollModbus(store->pollingCoils,MODBUS_COIL_REG_TYPE); + pollModbus(store->poolingDiscreteIns ,MODBUS_DISCRETE_REG_TYPE); debugSerial<itemArr->name << endl; //Non blocking waiting to release line @@ -709,7 +836,11 @@ if (itemParametersObj && itemParametersObj->type ==aJson_Object) } aJsonObject *polledValue = aJson.getObjectItem(markObj,"@S"); - if (polledValue && outValue->type == aJson_Int) polledValue->valueint=Value; //to pevent suppressing to change back to previously polled value if this occurs before next polling + if (polledValue && outValue->type == aJson_Int) + { + polledValue->valueint=Value; //to pevent suppressing to change back to previously polled value if this occurs before next polling + polledValue->subtype&=~MB_VALUE_OUTDATED; + } } } diff --git a/lighthub/modules/out_modbus.h b/lighthub/modules/out_modbus.h index da30ef6..64e0a3d 100644 --- a/lighthub/modules/out_modbus.h +++ b/lighthub/modules/out_modbus.h @@ -19,12 +19,15 @@ public: uint32_t timestamp; aJsonObject * pollingRegisters; aJsonObject * pollingIrs; + aJsonObject * pollingCoils; + aJsonObject * poolingDiscreteIns; aJsonObject * parameters; }; #define MB_NEED_SEND 8 #define MB_SEND_ERROR 4 #define MB_SEND_ATTEMPTS 3 +#define MB_VALUE_OUTDATED 1 class out_Modbus : public abstractOut { diff --git a/lighthub/modules/out_motor.h b/lighthub/modules/out_motor.h index c7831c4..e924365 100644 --- a/lighthub/modules/out_motor.h +++ b/lighthub/modules/out_motor.h @@ -12,7 +12,7 @@ #define MIN_PWM 70 // The number of simultaniusly working motors #ifndef MOTOR_QUOTE -#define MOTOR_QUOTE 1 +#define MOTOR_QUOTE 2 #endif static int8_t motorQuote = MOTOR_QUOTE;