From 891701cee1b0e9bc3f4aac4fcbdc9d24a743585d Mon Sep 17 00:00:00 2001 From: Andrey Klimov Date: Sun, 2 Oct 2022 19:31:18 +0300 Subject: [PATCH] Modbus mapping, AC swing, vent, pwm relay fix --- lighthub/item.cpp | 13 ++- lighthub/item.h | 10 +- lighthub/itemCmd.cpp | 159 ++++++++++++++++++++++++++--- lighthub/itemCmd.h | 10 +- lighthub/modules/out_ac.cpp | 16 +-- lighthub/modules/out_modbus.cpp | 27 +++-- lighthub/modules/out_multivent.cpp | 90 +++++++++++++--- lighthub/modules/out_pid.cpp | 12 ++- lighthub/modules/out_relay.cpp | 13 ++- 9 files changed, 279 insertions(+), 71 deletions(-) diff --git a/lighthub/item.cpp b/lighthub/item.cpp index 95f14f8..03fd01c 100644 --- a/lighthub/item.cpp +++ b/lighthub/item.cpp @@ -1122,12 +1122,14 @@ int Item::Ctrl(itemCmd cmd, char* subItem, bool allowRecursion) toExecute=true; break; } - if (chActive) { debugSerial<name, sizeof(addrstr)-1); @@ -1490,6 +1494,7 @@ int Item::SendStatus(int sendFlags) { debugSerial<")<type == aJson_String) + { + int cmd = txt2cmd(verb->valuestring); + if (cmd>0) + { + free(verb->valuestring); + verb->valueint=cmd; + verb->type=aJson_Int; + return verb->valueint; + } + } else if (verb && verb->type == aJson_Int) return verb->valueint; + return 0; + } + // Mapping from unified itemCmd object to some specific device-depended value itemCmd itemCmd::doMapping(aJsonObject *mappingData) { - if (isCommand()) + if (!mappingData) return *this; + aJsonObject *cmdMapping = aJson.getObjectItem(mappingData, "cmd"); + aJsonObject *matchedCmd = NULL; + + if (isCommand() && cmdMapping) + switch (cmdMapping->type) + { + case aJson_Array: { + debugSerial<<"Array mapping"<child; + //if first array element is not array - this is default mapping value + if (i && i->type==aJson_Int) + { + matchedCmd = i; + i=i->next; + } + + while (i) + { + if (i->type == aJson_Array && aJson.getArraySize(i) == 2) + { + int cmdFrom = replaceCmdToInt(aJson.getArrayItem(i,0)); + aJsonObject *to = aJson.getArrayItem(i,1); + if (getCmd()==cmdFrom && to->type == aJson_Int) + { + matchedCmd=to; + break; + } + + } + i=i->next; + } + } + case aJson_String: + if (strcmp(cmdMapping->valuestring,"fan")==0) switch (getCmd()) { + /* case CMD_AUTO: case CMD_ON: return itemCmd().Int((uint32_t)3); - case CMD_OFF: - return itemCmd().Int((uint32_t)0); case CMD_FAN: return itemCmd().Int((uint32_t)1); case CMD_HEAT: return itemCmd().Int((uint32_t)2); - + */ + case CMD_OFF: + return itemCmd().Int((uint32_t)0); case CMD_LOW: - return itemCmd().Int((uint32_t)10); + return itemCmd().Int((uint32_t)20); case CMD_MED: return itemCmd().Int((uint32_t)128); case CMD_HIGH: return itemCmd().Int((uint32_t)255); default: - return itemCmd().Int((uint32_t)0); + return *this; } + + } //switch + +if (matchedCmd) return itemCmd().Int((uint32_t)matchedCmd->valueint); + +aJsonObject *valMapping = aJson.getObjectItem(mappingData, "val"); +if (isValue() && valMapping && valMapping->type == aJson_Array && aJson.getArraySize(valMapping) == 4) + { + if (getInt()valueint) return itemCmd().Int((uint32_t) 0); + return itemCmd().Int((uint32_t) + map(getInt(), + aJson.getArrayItem(valMapping,0)->valueint,aJson.getArrayItem(valMapping,1)->valueint, + aJson.getArrayItem(valMapping,2)->valueint,aJson.getArrayItem(valMapping,3)->valueint)); } return *this; } - itemCmd itemCmd::doReverseMapping (aJsonObject *mappingData) + // Mapping from some device specific value back to unified itemcmd + itemCmd itemCmd::doReverseMapping (aJsonObject *mappingData) { + if (!mappingData) return *this; + aJsonObject *cmdMapping = aJson.getObjectItem(mappingData, "cmd"); + aJsonObject *matchedCmd = NULL; + + if (cmdMapping) + + switch (cmdMapping->type ) + { + case aJson_Array: + { + aJsonObject *i = cmdMapping->child; + //if first array element is not array - this is default mapping value + if (i && i->type==aJson_Int) + { + matchedCmd = i; + i=i->next; + } + + while (i) + { + if (i->type == aJson_Array && aJson.getArraySize(i) == 2) + { + aJsonObject *from =aJson.getArrayItem(i,0); + int cmdFrom = replaceCmdToInt(from); + aJsonObject *to = aJson.getArrayItem(i,1); + if (to->type == aJson_Int && getInt()==to->valueint) + { + matchedCmd=from; + break; + } + + } + i=i->next; + } + } + break; + case aJson_String: + { + if (strcmp(cmdMapping->valuestring,"fan")==0) + { + if (getInt()) + switch (constrain(map(getInt(),0,255,1,3),1,3)) + { + case 1: + return itemCmd().setSuffix(S_FAN).Cmd(CMD_LOW); + case 2: + return itemCmd().setSuffix(S_FAN).Cmd(CMD_MED); + case 3: + return itemCmd().setSuffix(S_FAN).Cmd(CMD_HIGH); + } + else return itemCmd().setSuffix(S_FAN).Cmd(CMD_OFF); + } + } +}//switch + + +if (matchedCmd) return itemCmd().Cmd(matchedCmd->valueint); + +aJsonObject *valMapping = aJson.getObjectItem(mappingData, "val"); +if (valMapping && valMapping->type == aJson_Array && aJson.getArraySize(valMapping) == 4) + { + int a = aJson.getArrayItem(valMapping,0)->valueint; + int b = aJson.getArrayItem(valMapping,1)->valueint; + int c = aJson.getArrayItem(valMapping,2)->valueint; + int d = aJson.getArrayItem(valMapping,3)->valueint; + + if (getInt()valueint) return itemCmd().Int((uint32_t) 0); + int diff = ((b-a)/(d-c))/2; + return itemCmd().Int((uint32_t) constrain(map(getInt(),c,d,a,b)+diff,0,255)); + } return *this; } -int itemCmd::doMappingCmd(aJsonObject *mappingData) - { - return 0; - - } - int itemCmd::doReverseMappingCmd (aJsonObject *mappingData) - - { - return 0; - } char * itemCmd::toString(char * Buffer, int bufLen, int sendFlags, bool scale100 ) { diff --git a/lighthub/itemCmd.h b/lighthub/itemCmd.h index 403c4cf..02eecf1 100644 --- a/lighthub/itemCmd.h +++ b/lighthub/itemCmd.h @@ -26,8 +26,8 @@ typedef char cmdstr[9]; const cmdstr commands_P[] PROGMEM = { "","ON","OFF","REST","TOGGLE","HALT","XON","XOFF","INCREASE","DECREASE", -"HEAT","COOL","AUTO","FAN_ONLY","DRY","STOP","HIGH","MEDIUM","LOW", -"TRUE","FALSE","ENABLED","DISABLED","RGB","HSV" +"HEAT","COOL","AUTO","FAN_ONLY","DRY","STOP","HIGH","MEDIUM","LOW","ENABLE","DISABLE", +"TRUE","FALSE","RGB","HSV" }; #define commandsNum sizeof(commands_P)/sizeof(cmdstr) @@ -50,8 +50,8 @@ const cmdstr commands_P[] PROGMEM = #define CMD_HIGH 0x10 /// AC/Vent fan level HIGH #define CMD_MED 0x11 /// AC/Vent fan level MEDIUM #define CMD_LOW 0x12 /// AC/Vent fan level LOW -#define CMD_ENABLED 0x13 /// Aliase for ON -#define CMD_DISABLED 0x14 /// Aliase for OFF +#define CMD_ENABLE 0x13 /// for PID regulator +#define CMD_DISABLE 0x14 /// for PID regulator #define CMD_TRUE 0x15 /// Aliase for ON #define CMD_FALSE 0x16 /// Aliase for OFF #define CMD_RGB 0x17 @@ -222,8 +222,6 @@ public: itemCmd doMapping(aJsonObject *mappingData); itemCmd doReverseMapping (aJsonObject *mappingData); - int doMappingCmd(aJsonObject *mappingData); - int doReverseMappingCmd (aJsonObject *mappingData); bool scale100(); }; diff --git a/lighthub/modules/out_ac.cpp b/lighthub/modules/out_ac.cpp index 34ffcb8..06d94a6 100644 --- a/lighthub/modules/out_ac.cpp +++ b/lighthub/modules/out_ac.cpp @@ -38,17 +38,7 @@ const char LOCK_P[] PROGMEM = "lock"; const char QUIET_P[] PROGMEM = "queit"; const char SWING_P[] PROGMEM = "swing"; const char RAW_P[] PROGMEM = "raw"; -//const char IDLE_P[] PROGMEM = "IDLE"; -/* -extern const char HEAT_P[] PROGMEM; -extern const char COOL_P[] PROGMEM; -extern const char AUTO_P[] PROGMEM; -extern const char FAN_ONLY_P[] PROGMEM; -extern const char DRY_P[] PROGMEM; -extern const char HIGH_P[] PROGMEM; -extern const char MED_P[] PROGMEM; -extern const char LOW_P[] PROGMEM; -*/ + void out_AC::InsertData(byte data[], size_t size){ char s_mode[10]; @@ -405,11 +395,11 @@ int out_AC::Ctrl(itemCmd cmd, char* subItem , bool toExecute) switch (cmd.getCmd()) { case CMD_ON: - data[B_LOCK_REM] = 3; + data[B_SWING] = 3; publishTopic(item->itemArr->name,"ON","/swing"); break; case CMD_OFF: - data[B_LOCK_REM] = 0; + data[B_SWING] = 0; publishTopic(item->itemArr->name,"OFF","/swing"); break; default: diff --git a/lighthub/modules/out_modbus.cpp b/lighthub/modules/out_modbus.cpp index eaffc70..056b12e 100644 --- a/lighthub/modules/out_modbus.cpp +++ b/lighthub/modules/out_modbus.cpp @@ -300,12 +300,15 @@ int out_Modbus::findRegister(int registerNum, int posInBuffer, int regType) mappedParam.Tens_raw(data * (TENS_BASE/100)); mappedParam.Float((int32_t) data/100.); } - - if (mapObj && (mapObj->type==aJson_Array || mapObj->type==aJson_Object)) - mappedParam.doMapping(mapObj); debugSerial << F("MB got ")<name<type==aJson_Array || mapObj->type==aJson_Object)) + { + mappedParam=mappedParam.doReverseMapping(mapObj); + debugSerial << F("Mapped:")<type ==aJson_Object) { aJsonObject *execObj = aJson.getObjectItem(itemParametersObj,paramObj->name); @@ -329,13 +332,16 @@ int out_Modbus::findRegister(int registerNum, int posInBuffer, int regType) aJson.addNumberToObject(execObj, "@S", (long) param); } if (submitParam) - { // Compare with last submitted val + { + //#ifdef MB_SUPPRESS_OUT_EQ_IN + // Compare with last submitted val (if @V NOT marked as NULL in config) aJsonObject *settedValue = aJson.getObjectItem(execObj,"@V"); - if (settedValue && (settedValue->valueint == param)) + if (settedValue && settedValue->type==aJson_Int && (settedValue->valueint == param)) { debugSerial<type ==aJson_Object) execObj->subtype |= MB_NEED_SEND; aJsonObject *outValue = aJson.getObjectItem(execObj,"@V"); - if (outValue) + if (outValue) // Existant. Preserve original @type { outValue->valueint=Value; - outValue->subtype =regType; - polledValue->valueint=Value; //to pevent suppressing to change back to previously polled value if this occurs before next polling + outValue->subtype =regType & 0xF; + if (outValue->type == aJson_Int) polledValue->valueint=Value; //to pevent suppressing to change back to previously polled value if this occurs before next polling } else //No container to store value yet + // If no @V in config - creating with INT type - normal behavior - no supress in-to-out { debugSerial<name<subtype =regType; + if (outValue) outValue->subtype =regType & 0xF; } } } diff --git a/lighthub/modules/out_multivent.cpp b/lighthub/modules/out_multivent.cpp index 49b940e..57b96f1 100644 --- a/lighthub/modules/out_multivent.cpp +++ b/lighthub/modules/out_multivent.cpp @@ -102,6 +102,24 @@ if (cmd.isCommand() && !suffixCode) suffixCode=S_CMD; //if some known command fi aJsonObject * i = NULL; +if (cmd.isCommand() && cmd.getSuffix()==S_FAN) + switch (cmd.getCmd()) + { + case CMD_HIGH: + cmd.Percents255(255); + break; + + case CMD_MED: + cmd.Percents255(128); + break; + + case CMD_LOW: + cmd.setPercents(10); + break; + +} //switch cmd + + if (gatesObj) i = gatesObj->child; // Pass 1 - calculate summ air value, max value etc int activeV = 0; @@ -116,6 +134,7 @@ while (i) aJsonObject * setObj=aJson.getObjectItem(i, "set"); aJsonObject * cmdObj=aJson.getObjectItem(i, "cmd"); + aJsonObject * cascadeObj=aJson.getObjectItem(i, "cas"); if (setObj && cmdObj && setObj->type==aJson_Int && cmdObj->type==aJson_Int) { @@ -128,30 +147,77 @@ while (i) { cmdObj->valueint = cmd.getCmd(); //publishTopic(i->name,cmdObj->valueint,"/set"); - if (isNotRetainingStatus()) item->SendStatusImmediate(cmd,SEND_COMMAND,i->name); + switch (cmd.getCmd()) + { + case CMD_ON: + cmd.Percents255(setObj->valueint); + break; + case CMD_OFF: + cmd.Percents255(0); } - if (setObj && cmd.isValue()) + if (cmdObj->valueint == CMD_ON && setObj->valueint<20) + { + setObj->valueint=30; + cmd.Percents255(30); + //if (isNotRetainingStatus()) item->SendStatusImmediate(cmd,SEND_PARAMETERS,i->name); + } + + if (isNotRetainingStatus()) item->SendStatusImmediate(cmd,SEND_COMMAND|SEND_PARAMETERS,i->name); + } + + else if (setObj && cmdObj && suffixCode == S_FAN && cmd.isValue()) + { + if (cmd.getInt()) + { + + if (cmdObj->valueint == CMD_OFF || cmdObj->valueint == -1) + { + debugSerial<<"Turning ON"<valueint = CMD_ON; + cmd.Cmd(CMD_ON); + //if (isNotRetainingStatus()) item->SendStatusImmediate(itemCmd().Cmd(CMD_ON),SEND_COMMAND,i->name); + } + + setObj->valueint = cmd.getInt(); + } + else + { + if (cmdObj->valueint != CMD_OFF && cmdObj->valueint != -1) + { debugSerial<<"Turning OFF"<valueint = CMD_OFF; + cmd.Cmd(CMD_OFF); + //if (isNotRetainingStatus()) item->SendStatusImmediate(itemCmd().Cmd(CMD_OFF),SEND_COMMAND,i->name); + } + + setObj->valueint = 0; + } + + if (isNotRetainingStatus()) item->SendStatusImmediate(cmd,SEND_PARAMETERS|SEND_COMMAND,i->name); + } + + else if (setObj && cmd.isValue()) { setObj->valueint = cmd.getPercents255(); //publishTopic(i->name,setObj->valueint,"/set"); if (isNotRetainingStatus()) item->SendStatusImmediate(cmd,SEND_PARAMETERS,i->name); } + if (cascadeObj) executeCommand(cascadeObj,-1,cmd); } - if (cmdObj->valueint != CMD_OFF) + if (cmdObj->valueint != CMD_OFF && cmdObj->valueint != -1) { requestedV=V*setObj->valueint; activeV+=requestedV; + + if (setObj->valueint>maxPercent ) + { + maxRequestedV=requestedV; + maxV=V; + maxPercent=setObj->valueint; + } } totalV+=V; - //if(requestedV>maxRequestedV) - if (setObj->valueint>maxPercent) - { - maxRequestedV=requestedV; - maxV=V; - maxPercent=setObj->valueint; - } } i=i->next; } @@ -161,7 +227,7 @@ if (!totalV) return 0; int fanV=activeV/totalV; debugSerial << F("Total V:")<child; //Pass 2: re-distribute airflow @@ -177,7 +243,7 @@ while (i) if (outObj && setObj && cmdObj && outObj->type==aJson_Int && setObj->type==aJson_Int && cmdObj->type==aJson_Int && V) { long int out = 0; - if (cmdObj->valueint != CMD_OFF && maxRequestedV) + if (cmdObj->valueint != CMD_OFF && cmdObj->valueint != -1 && maxRequestedV) { int requestedV=V*setObj->valueint; out = (( long)requestedV*255L)/(( long)V)*( long)maxV/( long)maxRequestedV; diff --git a/lighthub/modules/out_pid.cpp b/lighthub/modules/out_pid.cpp index 4aeb256..0c4515f 100644 --- a/lighthub/modules/out_pid.cpp +++ b/lighthub/modules/out_pid.cpp @@ -167,7 +167,7 @@ if (store && store->pid && (Status() == CST_INITIALIZED) && item && (item->getCm //itemCmd st; //st.loadItem(item); //short cmd = st.getCmd(); - if (item->getCmd() != CMD_OFF) + if (item->getCmd() != CMD_OFF && item->getCmd() != CMD_DISABLE) { if(store->pid->Compute() ) { @@ -337,7 +337,15 @@ case S_CMD: executeCommand(oCmd,-1,value); return 1; - + case CMD_ENABLE: + item->setCmd(CMD_ENABLE); + item->SendStatus(SEND_COMMAND); + return 1; + + case CMD_DISABLE: + item->setCmd(CMD_DISABLE); + item->SendStatus(SEND_COMMAND); + return 1; /* case CMD_OFF: { diff --git a/lighthub/modules/out_relay.cpp b/lighthub/modules/out_relay.cpp index fbbc83b..70497ad 100644 --- a/lighthub/modules/out_relay.cpp +++ b/lighthub/modules/out_relay.cpp @@ -173,7 +173,18 @@ case S_SET: item->setExt(0); relay(false); } - } + } else //not execute + { + switch (item->getCmd()) + { + case CMD_AUTO: + case CMD_ON: + case CMD_COOL: + case CMD_DRY: + case CMD_HEAT: + if (cmd.getPercents255() && !item->getExt()) item->setExt(millisNZ()); + } + } return 1; case S_CMD: