diff --git a/build-flags/build_flags_stm32-noip b/build-flags/build_flags_stm32-noip index 78aa547..b1d07d9 100644 --- a/build-flags/build_flags_stm32-noip +++ b/build-flags/build_flags_stm32-noip @@ -45,4 +45,5 @@ #HAL_ETH_MODULE_DISABLED #HAL_SD_MODULE_DISABLED #HAL_DAC_MODULE_DISABLED -#-DMERCURY_ENABLE \ No newline at end of file +#-DMERCURY_ENABLE +-D ROTARYENCODER \ No newline at end of file diff --git a/compiled/lighthub21/upload.sh b/compiled/lighthub21/upload.sh index 18f5552..7eb04a7 100755 --- a/compiled/lighthub21/upload.sh +++ b/compiled/lighthub21/upload.sh @@ -1,3 +1,3 @@ -export PORT=cu.usbmodem144101 +export PORT=cu.usbmodem142401 echo . | stty -f /dev/$PORT speed 1200 ../tools/mac/tool-bossac/bossac -U false -p $PORT -i -w -v -b firmware.bin -R \ No newline at end of file diff --git a/compiled/lighthub21/uploadOTA.sh b/compiled/lighthub21/uploadOTA.sh index 818da0b..cf2c810 100755 --- a/compiled/lighthub21/uploadOTA.sh +++ b/compiled/lighthub21/uploadOTA.sh @@ -1 +1 @@ -../tools/mac/arduinoOTA -address 192.168.11.13 -port 80 -username arduino -password password -sketch firmware.bin -b -upload /sketch +../tools/mac/arduinoOTA -address 192.168.11.200 -port 80 -username arduino -password password -sketch firmware.bin -b -upload /sketch diff --git a/config-examples/lh22-test.json b/config-examples/lh22-test.json new file mode 100644 index 0000000..48374c9 --- /dev/null +++ b/config-examples/lh22-test.json @@ -0,0 +1,221 @@ +{ + "dmx":[3,60], + "mqtt":["lh22-test","192.168.11.4"], + "dmxin":["led5","led6","led7","led8"], + "topics":{"root":"test2"}, + "syslog":["192.168.88.2"], + "ow":{ + "282F7E81E3713C59":{"emit":"t_1"} + }, + "modbus": + { + "s8":{ + "poll":{"irs":[[0,3]],"regs":[[0,1],31],"delay":11000}, + "par":{ + "co2":{"ir":3}, + "meterStat":{"ir":0}, + "alarmStat":{"ir":1}, + "hr1":{"reg":0}, + "hr2":{"reg":1}, + "hr32":{"reg":31} + } + }, + "term":{ + "poll":{"regs":[0],"delay":12000}, + "par":{ + "t":{"reg":0,"type":"x10"} + } + }, + "thmeter":{ + "serial":"8N1", + "baud":4800, + "poll":{"regs":[[0,1],[2000,2001],[80,81]],"delay":3000}, + "par":{ + "hum" :{"reg":0,"type":"x10"}, + "temp" :{"reg":1,"type":"x10"}, + "slaveid" :{"reg":2000}, + "baud" :{"reg":2001}, + "tcalib":{"reg":80,"type":"x10"}, + "hcalib":{"reg":81,"type":"x10"} + } + }, + "panel":{ + "serial":"8E1", + "poll":{"regs":[[39993,40008],[30000,30001]],"delay":5000}, + "par":{ + "fanspeed" :{"reg":40000,"prefetch":true,"map":{"val":[1,255,1,5],"cmd":[["OFF",0]]},"id":7}, + "settemp" :{"reg":40002,"prefetch":true,"id":12}, + "alm01":{"reg":40004,"id":13}, + "alm17":{"reg":40005,"id":14}, + "alm33":{"reg":40006,"id":15}, + "sethum" :{"reg":40007,"prefetch":true,"id":16}, + "setvoc" :{"reg":40008,"prefetch":true,"map":{"val":[400,2000,0,100]},"id":17}, + "roomtemp" :{"reg":30000,"type":"x10"}, + "hum" :{"reg":30001}, + "voc" :{"reg":30002}, + "ch_temp" :{"reg":40009,"type":"x10","id":3}, + "ext_temp" :{"reg":40010,"type":"x10","id":18}, + "out_temp" :{"reg":40011,"type":"x10","id":19}, + "floor_temp" :{"reg":40012,"type":"x10","id":20}, + "ch_hum" :{"reg":40013,"id":28}, + "heat_pwr":{"reg":40014,"id":29}, + "extvoc":{"reg":40015,"map":{"val":[400,2000,0,100]},"id":27}, + "actemp":{"reg":40016,"type":"x10","id":25}, + "fanlvl":{"reg":40017,"id":21}, + "floormode":{"reg":39995,"prefetch":true,"id":22}, + "setfloor":{"reg":39996,"prefetch":true,"id":23}, + "humpwr":{"reg":39998,"prefetch":true,"map":{"cmd":[null,["ON",1],["OFF",0]],"val":null},"id":24}, + "fanauto":{"reg":39999,"prefetch":true,"map":{"cmd":[["ENABLE",1],["DISABLE",0],["AUTO",1]],"val":null},"id":7}, + "acsettemp":{"reg":39994,"prefetch":true,"id":26}, + "acon":{"reg":40003,"prefetch":true,"map":{"cmd":[1,["OFF",0]],"val":null,"def":40001},"id":8}, + "acmode" :{"reg":40001,"prefetch":true,"map":{"cmd":[["FAN_ONLY",1],["HEAT",4],["COOL",2],["AUTO",8]]},"id":8}, + "acfanauto":{"reg":39993,"prefetch":true,"map":{"cmd":[0,["AUTO",1]],"val":null,"def":39997},"id":2}, + "acfan":{"reg":39997,"prefetch":true,"map":{"cmd":[["OFF",0],["LOW",1],["HIGH",3],["MEDIUM",2]]},"id":2}, + "y":{"reg":65512}, + "mo":{"reg":65513}, + "d":{"reg":65514}, + "dw":{"reg":65515}, + "h":{"reg":65516}, + "m":{"reg":65517}, + "s":{"reg":65518}, + "blmind":{"reg":50051}, + "blmaxd":{"reg":50052}, + "blminn":{"reg":50053}, + "blmaxn":{"reg":50054} + } + } + }, + + "items": { + "th":[14,[1,"thmeter", + { + "temp":{"emit":"temp","@S":null}, + "hum" :{"emit":"zal2hum","@S":null}, + "slaveid" :{"emit":"slaveid"}, + "baud" :{"emit":"baud"}, + "tcalib":{"emit":"tcalib"}, + "hcalib":{"emit":"hcalib"} + } + ]], + + "pout0":[6,22], + "pout1":[6,23], + "pout2":[6,24], + "pout3":[6,25], + "pout4":[3,9], + "pout5":[3,8], + "pout6":[3,11], + "pout7":[3,12], + "pwm0" :[3,4], + "pwm1" :[3,5], + "pwm2" :[3,6], + "pwm3" :[3,7], + + "unprot0":[6,33], + "unprot1":[6,32], + "unprot2":[6,31], + "unprot3":[6,30], + "unprot4":[6,29], + "unprot5":[6,28], + "unprot6":[6,27], + "unprot7":[6,26], + "led": [1,1], + "led2":[1,5], + "led3":[1,9], + "led4":[1,13], + "led5":[1,17], + "led6":[1,21], + "led7":[1,25], + "led8":[1,29], + "dimmer" :[0,33], + "dimmer2":[0,34], + "dimmer3":[0,35], + "dimmer4":[0,36], + "dimmer5":[0,37], + "dimmer6":[0,38], + "dimmers":[7,["dimmer","dimmer2","dimmer3","dimmer4","dimmer5","dimmer6"]], + "leds":[7,["led","led2","led3","led4","led5","led6"]], + "mbuses":[7,["mbusdim1","mbusdim2","mbusdim3","mbusdim4"]], + "all":[7,["dimmers","uouts","relays","leds"]], + "relays":[7,["pout0","pout1","pout2","pout3","pout4","pout5","pout6","pout7"]], + "uouts":[7,["unprot0","unprot1","unprot2","unprot3","unprot4","unprot5","unprot6","unprot7"]] + }, + "in":{ + "42":{"emit":"in0"}, + "44":{"emit":"in1"}, + "46":{"emit":"in2"}, + "49":{"emit":"in3"}, + "43":{"emit":"in4"}, + "45":{"emit":"in5"}, + "47":{"emit":"in6"}, + "48":{"emit":"in7"}, + "34":{"emit":"in8"}, + "36":{"emit":"in9"}, + "38":{"emit":"in10"}, + "40":{"emit":"in11"}, + "35":{"emit":"in12"}, + "37":{"emit":"in13"}, + "39":{"emit":"in14"}, + "41":{"emit":"in15"}, + + "54":{"T":64,"emit":"a00","item":"water","map":[200,700],"scmd":"ON","rcmd":"OFF"}, + "55":{"T":64,"emit":"a01","item":"water","map":[200,700],"scmd":"ON","rcmd":"OFF"}, + "56":{"T":64,"emit":"a02","map":[0,1024,0,1024,10]}, + "57":{"T":64,"emit":"a03","map":[0,1024,0,1024,10]}, + "58":{"T":64,"emit":"a04","map":[0,1024,0,1024,10]}, + "59":{"T":64,"emit":"a05","map":[0,1024,0,1024,10]}, + "60":{"T":64,"emit":"a06"}, + "61":{"T":64,"emit":"a07","map":[0,1024,0,1024,5]}, + "62":{"T":64,"emit":"a08","map":[0,1024,0,1024,5]}, + "63":{"T":64,"emit":"a09","map":[0,1024,0,1024,5]}, + "64":{"T":64,"emit":"a10","map":[0,1024,0,1024,5]}, + "65":{"T":64,"emit":"a11","map":[0,1024,0,1024,5]}, + "66":{"T":2,"emit":"d12"}, + "67":{ + "T":2, + "scmd":{"emit":"d13","ecmd":"scmd"}, + "rcmd":{"emit":"d13","ecmd":"rcmd"}, + "lcmd":{"emit":"d13","ecmd":"lcmd"}, + "click":{"emit":"d13","ecmd":"click"}, + "dclick":{"emit":"d13","ecmd":"dclick"}, + "tclick":{"emit":"d13","ecmd":"tclick"}, + "scmd2":{"emit":"d13","ecmd":"scmd2"}, + "scmd3":{"emit":"d13","ecmd":"scmd3"}, + "lcmd2":{"emit":"d13","ecmd":"lcmd2"}, + "lcmd3":{"emit":"d13","ecmd":"lcmd3"}, + "rpcmd":{"emit":"d13","ecmd":"rpcmd"}, + "rpcmd2":{"emit":"d13","ecmd":"rpcmd2"}, + "rpcmd3":{"emit":"d13","ecmd":"rpcmd3"} + }, + "68":{"T":2, + "scmd":{"emit":"d14","ecmd":"scmd"}, + "rcmd":{"emit":"d14","ecmd":"rcmd"}, + "lcmd":{"emit":"d14","ecmd":"lcmd"}, + "click":{"emit":"d14","ecmd":"click"}, + "dclick":{"emit":"d14","ecmd":"dclick"}, + "tclick":{"emit":"d14","ecmd":"tclick"}, + "scmd2":{"emit":"d14","ecmd":"scmd2"}, + "scmd3":{"emit":"d14","ecmd":"scmd3"}, + "lcmd2":{"emit":"d14","ecmd":"lcmd2"}, + "lcmd3":{"emit":"d14","ecmd":"lcmd3"}, + "rpcmd":{"emit":"d14","ecmd":"rpcmd"}, + "rpcmd2":{"emit":"d14","ecmd":"rpcmd2"}, + "rpcmd3":{"emit":"d14","ecmd":"rpcmd3"} + }, + "69":{"T":2, + "scmd":{"emit":"d15","ecmd":"scmd"}, + "rcmd":{"emit":"d15","ecmd":"rcmd"}, + "lcmd":{"emit":"d15","ecmd":"lcmd"}, + "click":{"emit":"d15","ecmd":"click"}, + "dclick":{"emit":"d15","ecmd":"dclick"}, + "tclick":{"emit":"d15","ecmd":"tclick"}, + "scmd2":{"emit":"d15","ecmd":"scmd2"}, + "scmd3":{"emit":"d15","ecmd":"scmd3"}, + "lcmd2":{"emit":"d15","ecmd":"lcmd2"}, + "lcmd3":{"emit":"d15","ecmd":"lcmd3"}, + "rpcmd":{"emit":"d15","ecmd":"rpcmd"}, + "rpcmd2":{"emit":"d15","ecmd":"rpcmd2"}, + "rpcmd3":{"emit":"d15","ecmd":"rpcmd3"} + } + } + } \ No newline at end of file diff --git a/lighthub/candriver.cpp b/lighthub/candriver.cpp index 22e0c0f..2c6a52b 100644 --- a/lighthub/candriver.cpp +++ b/lighthub/candriver.cpp @@ -630,6 +630,7 @@ while (remoteConfObj) strncpy(root+rootLen, addrObj->valuestring, buflen-rootLen-1); strncat(root+rootLen, "/", buflen-rootLen-1); strncat(root+rootLen, "#", buflen-rootLen-1); + debugSerial.print("CAN: subscribe "); debugSerial.println(root); mqttClient.subscribe(root); } diff --git a/lighthub/dmx.cpp b/lighthub/dmx.cpp index 7297626..4d18f7d 100644 --- a/lighthub/dmx.cpp +++ b/lighthub/dmx.cpp @@ -272,10 +272,11 @@ for (short rgbwChan=0; rgbwChan < RGBWChannels; rgbwChan++) } } -//#ifdef _dmxout -//for (int i=1; i<17; i++) {debugSerial.print(dmxin.read(i));debugSerial.print(";");} -//debugSerial.println(); -//#endif +#ifdef _dmxout +debugSerial.print(F("DMXIN:")); +for (int i=1; i<17; i++) {debugSerial.print(dmxin.read(i));debugSerial.print(";");} +debugSerial.println(); +#endif #endif } @@ -302,6 +303,7 @@ void DMXinSetup(int channels) if (channels>(32*4)) channels = 32*4; DMXin = new uint8_t [channels]; DMXINChannels=channels; + // debugSerial<state<") <lastValue; if (store->state == newState) { store->delayedState = false; @@ -784,6 +785,20 @@ if (newState!=store->state && cause!=CHECK_INTERRUPT) debugSerial<delayedState=false; + } + else + { + store->delayedState=true; + store->lastValue = contactState; + store->reqState=newState; + } + + if (newState == IS_NOP) return true; + aJsonObject *defaultItem = aJson.getObjectItem(currentInputObject, "item"); aJsonObject *defaultEmit = aJson.getObjectItem(currentInputObject, "emit"); aJsonObject *defaultCan = aJson.getObjectItem(currentInputObject, "can"); @@ -835,7 +850,7 @@ void Input::contactPoll(short cause) contactPollBusy++; aJsonObject * currentInputObject = getCurrentInput(); - changeState(IS_REQSTATE,cause,currentInputObject); //Check for postponed states transitions + changeState(IS_REQSTATE,cause,currentInputObject,false); //Check for postponed states transitions uint8_t inputOnLevel; @@ -865,15 +880,15 @@ switch (store->state) //Timer based transitions case IS_PRESSED: if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_LONG,0xFFFF)) { - if (!aJson.getObjectItem(inputObj, "lcmd") && !aJson.getObjectItem(currentInputObject, "rpcmd")) changeState(IS_WAITRELEASE, cause,currentInputObject); - else changeState(IS_LONG, cause,currentInputObject); + if (!aJson.getObjectItem(inputObj, "lcmd") && !aJson.getObjectItem(currentInputObject, "rpcmd")) changeState(IS_WAITRELEASE, cause,currentInputObject,currentInputState); + else changeState(IS_LONG, cause,currentInputObject,currentInputState); } break; case IS_LONG: if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT,0xFFFF)) { - changeState(IS_REPEAT, cause,currentInputObject); + changeState(IS_REPEAT, cause,currentInputObject,currentInputState); store->timestamp16 = millis() & 0xFFFF; } break; @@ -881,7 +896,7 @@ switch (store->state) //Timer based transitions case IS_REPEAT: if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT_PULSE,0xFFFF)) { - changeState(IS_REPEAT, cause,currentInputObject); + changeState(IS_REPEAT, cause,currentInputObject,currentInputState); store->timestamp16 = millis() & 0xFFFF; } break; @@ -889,15 +904,15 @@ switch (store->state) //Timer based transitions case IS_PRESSED2: if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_LONG,0xFFFF)) { - if (!aJson.getObjectItem(currentInputObject, "lcmd2") && !aJson.getObjectItem(currentInputObject, "rpcmd2")) changeState(IS_WAITRELEASE, cause,currentInputObject); - else changeState(IS_LONG2, cause,currentInputObject); + if (!aJson.getObjectItem(currentInputObject, "lcmd2") && !aJson.getObjectItem(currentInputObject, "rpcmd2")) changeState(IS_WAITRELEASE, cause,currentInputObject,currentInputState); + else changeState(IS_LONG2, cause,currentInputObject,currentInputState); } break; case IS_LONG2: if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT,0xFFFF)) { - changeState(IS_REPEAT2, cause,currentInputObject); + changeState(IS_REPEAT2, cause,currentInputObject,currentInputState); store->timestamp16 = millis() & 0xFFFF; } break; @@ -905,7 +920,7 @@ switch (store->state) //Timer based transitions case IS_REPEAT2: if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT_PULSE,0xFFFF)) { - changeState(IS_REPEAT2, cause,currentInputObject); + changeState(IS_REPEAT2, cause,currentInputObject,currentInputState); store->timestamp16 = millis() & 0xFFFF; } break; @@ -915,17 +930,17 @@ switch (store->state) //Timer based transitions { if (!aJson.getObjectItem(currentInputObject, "lcmd3") && !aJson.getObjectItem(currentInputObject, "rpcmd3")) //No longpress handlers { - if (aJson.getObjectItem(currentInputObject, "scmd3")) changeState(IS_WAITRELEASE, cause,currentInputObject); //was used - else changeState(IS_PRESSED2, cause,currentInputObject); // completely empty trippleClick section - fallback to first click handler + if (aJson.getObjectItem(currentInputObject, "scmd3")) changeState(IS_WAITRELEASE, cause,currentInputObject,currentInputState); //was used + else changeState(IS_PRESSED2, cause,currentInputObject,currentInputState); // completely empty trippleClick section - fallback to first click handler } - else changeState(IS_LONG3, cause,currentInputObject); + else changeState(IS_LONG3, cause,currentInputObject,currentInputState); } break; case IS_LONG3: if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT,0xFFFF)) { - changeState(IS_REPEAT3, cause,currentInputObject); + changeState(IS_REPEAT3, cause,currentInputObject,currentInputState); store->timestamp16 = millis() & 0xFFFF; } break; @@ -933,7 +948,7 @@ switch (store->state) //Timer based transitions case IS_REPEAT3: if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_RPT_PULSE,0xFFFF)) { - changeState(IS_REPEAT3, cause,currentInputObject); + changeState(IS_REPEAT3, cause,currentInputObject,currentInputState); store->timestamp16 = millis() & 0xFFFF; } break; @@ -943,7 +958,7 @@ switch (store->state) //Timer based transitions case IS_WAITPRESS: - if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_IDLE,0xFFFF)) changeState(IS_IDLE, cause,currentInputObject); + if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_IDLE,0xFFFF)) changeState(IS_IDLE, cause,currentInputObject,currentInputState); break; } //switch #ifdef ROTARYENCODER @@ -963,7 +978,8 @@ if (re) } #endif } //if not INTERRUPT - if (currentInputState != store->lastValue) // value changed + if ((currentInputState != store->lastValue) || // value changed + (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_REPEAT,0xFFFF) && getIntFromJson(currentInputObject,"repeat"))) { if (store->bounce) store->bounce = store->bounce - 1; else //confirmed change @@ -981,7 +997,7 @@ if (re) } else */ { - // onContactChanged(currentInputState); //Legacy input - to remove later +////// onContactChanged(currentInputState); //Legacy input - to remove later // wrong place - INTERRUPTS bool res = true; if (currentInputState) //Button pressed state transitions @@ -989,7 +1005,7 @@ if (re) switch (store->state) { case IS_IDLE: - res = changeState(IS_PRESSED, cause,currentInputObject); + res = changeState(IS_PRESSED, cause,currentInputObject,currentInputState); break; @@ -1001,30 +1017,33 @@ if (re) !aJson.getObjectItem(currentInputObject, "rpcmd2") && !aJson.getObjectItem(currentInputObject, "dclick") ) - res = changeState(IS_PRESSED, cause,currentInputObject); + res = changeState(IS_PRESSED, cause,currentInputObject,currentInputState); - else res = changeState(IS_PRESSED2, cause,currentInputObject); + else res = changeState(IS_PRESSED2, cause,currentInputObject,currentInputState); break; case IS_RELEASED2: - res = changeState(IS_PRESSED3, cause,currentInputObject); + res = changeState(IS_PRESSED3, cause,currentInputObject,currentInputState); break; + default: + res = changeState(IS_NOP, cause,currentInputObject,currentInputState); + } else switch (store->state) //Button released state transitions { case IS_PRESSED: - res = changeState(IS_RELEASED, cause,currentInputObject); + res = changeState(IS_RELEASED, cause,currentInputObject,currentInputState); break; case IS_LONG: case IS_REPEAT: case IS_WAITRELEASE: - res = changeState(IS_WAITPRESS, cause,currentInputObject); + res = changeState(IS_WAITPRESS, cause,currentInputObject,currentInputState); break; case IS_PRESSED2: @@ -1033,8 +1052,8 @@ if (re) !aJson.getObjectItem(currentInputObject, "lcmd2") && !aJson.getObjectItem(currentInputObject, "rpcmd2") && !aJson.getObjectItem(currentInputObject, "dclick") - ) res = changeState(IS_IDLE, cause,currentInputObject); - else res = changeState(IS_RELEASED2, cause,currentInputObject); + ) res = changeState(IS_IDLE, cause,currentInputObject,currentInputState); + else res = changeState(IS_RELEASED2, cause,currentInputObject,currentInputState); break; case IS_LONG2: @@ -1042,8 +1061,10 @@ if (re) case IS_LONG3: case IS_REPEAT3: case IS_PRESSED3: - res = changeState(IS_IDLE, cause,currentInputObject); + res = changeState(IS_IDLE, cause,currentInputObject,currentInputState); break; + default: + res = changeState(IS_NOP, cause,currentInputObject,currentInputState); } if (res) { //State changed or postponed // store->logicState = currentInputState; diff --git a/lighthub/inputs.h b/lighthub/inputs.h index a3432a7..3e9b38c 100644 --- a/lighthub/inputs.h +++ b/lighthub/inputs.h @@ -56,6 +56,7 @@ e-mail anklimov@gmail.com #define IS_REPEAT3 12u #define IS_WAITRELEASE 13u #define IS_REQSTATE 0xFF +#define IS_NOP 0xF @@ -73,6 +74,7 @@ e-mail anklimov@gmail.com #define T_IDLE 600 #define T_RPT 300 #define T_RPT_PULSE 150 +#define T_REPEAT 30000 @@ -191,7 +193,7 @@ protected: bool publishDataToDomoticz(int , aJsonObject *, const char *format, ...); char* getIdxField(); - bool changeState(uint8_t newState, short cause, aJsonObject * currentInputObject); + bool changeState(uint8_t newState, short cause, aJsonObject * currentInputObject, bool contactState); void setupRotaryEncoder(); aJsonObject * getCurrentInput(); diff --git a/lighthub/item.cpp b/lighthub/item.cpp index e7b6a6a..da97a5b 100644 --- a/lighthub/item.cpp +++ b/lighthub/item.cpp @@ -358,7 +358,7 @@ uint16_t getCanNum(aJsonObject* verb) char * Item::getSubItemStrById(uint8_t subItem) { -if (subItem == NO_SUBITEM || (subItem | SUBITEM_IS_COMMAND)) return NULL; +if (subItem == NO_SUBITEM || (subItem & SUBITEM_IS_COMMAND)) return NULL; if (!itemArg) return NULL; aJsonObject * i = itemArg; if (i->type == aJson_Array) i=i->child; @@ -421,18 +421,20 @@ return NO_SUBITEM; { if (getCanNum(itemArr->child) == num) { - debugSerial<<"Find item: "<< itemArr->name << " addr:" << num << endl; + debugSerial<<"CAN: Find item: "<< itemArr->name << " id:" << num << "sub:" << subItem; Parse(); - if (subItem | SUBITEM_IS_COMMAND) + if (subItem & SUBITEM_IS_COMMAND) { subItem &=~ SUBITEM_IS_COMMAND; if (subItemnext; @@ -1107,7 +1109,7 @@ int Item::Ctrl(itemCmd cmd, char* subItem, uint8_t flags, bool authorized) uint8_t command2Set = 0; itemCmd originalCmd = cmd; int subitemCmd = subitem2cmd(subItem); - + bool oppositeCommandToBeSchedulled = (suffixCode==S_CMD) && cmd.isValue(); /// Common (GRP & NO GRP) commands switch (cmd.getCmd()) { @@ -1293,14 +1295,14 @@ int Item::Ctrl(itemCmd cmd, char* subItem, uint8_t flags, bool authorized) } else { - //chActive=(isActive()>0); + if (chActive == -1) chActive=(isActive()>0); //need! because activities status will be changed if ((suffixCode!=S_CMD) || (cmd.getCmd() != CMD_XON) || !getFlag(FLAG_DISABLED)) { digGroup(itemArg,&cmd,subItem,authorized,flags); - if ((suffixCode==S_CMD) && cmd.isValue()) + if (oppositeCommandToBeSchedulled)//((suffixCode==S_CMD) && cmd.isValue()) { - scheduleOppositeCommand(originalCmd,-1/*chActive*/,authorized); + scheduleOppositeCommand(originalCmd,-1,authorized); scheduledOppositeCommand = true; } if (subItem && !subitemCmd) status2Send |= FLAG_SEND_IMMEDIATE; @@ -1347,8 +1349,6 @@ int Item::Ctrl(itemCmd cmd, char* subItem, uint8_t flags, bool authorized) if (chActive == -1) chActive=(isActive()>0); if (!chActive) //if channel was'nt active before CMD_XON { - - cmd.loadItemDef(this); cmd.Cmd(CMD_ON); command2Set=CMD_XON; @@ -1424,7 +1424,7 @@ int Item::Ctrl(itemCmd cmd, char* subItem, uint8_t flags, bool authorized) /// bool oppositeCommandToBeSchedulled = (suffixCode==S_CMD) && allowRecursion && cmd.isValue(); - bool oppositeCommandToBeSchedulled = (suffixCode==S_CMD) && cmd.isValue(); + // bool oppositeCommandToBeSchedulled = (suffixCode==S_CMD) && cmd.isValue(); // Commands for NON GROUP //threating Restore, XOFF (special conditional commands)/ convert to ON, OFF and SET values switch (cmd.getCmd()) { @@ -1740,7 +1740,14 @@ if ((!driver || driver->isAllowed(cmd)) //update command for HALT & XON and send MQTT status if (command2Set) setCmd(command2Set | FLAG_COMMAND); - if (operation) SendStatus(status2Send,subItem); + if (operation) { + SendStatus(status2Send);//,subItem); + if (oppositeCommandToBeSchedulled && subItem) + { + debugSerial< OFF scheduled + } + } } //alowed cmd else { @@ -1934,11 +1941,11 @@ int Item::SendStatus(long sendFlags, char * subItem) { } } - int Item::SendStatusImmediate(itemCmd st, long sendFlags, char * subItem) { + int Item::SendStatusImmediate(itemCmd st, long sendFlags, char * subItem, bool retain) { { char addrstr[64]; char valstr[20] = ""; - char cmdstr[9] = ""; + char cmdstr[16] = ""; debugSerial<<"SENDSTATUS: "<")<")<name, sizeof(addrstr)-1); @@ -2128,7 +2138,7 @@ int Item::SendStatus(long sendFlags, char * subItem) { #if not defined (NOIP) if (mqttClient.connected() && !ethernetIdleCount) { - mqttClient.publish(addrstr, cmdstr,true); + mqttClient.publish(addrstr, cmdstr,retain); clearFlag(FLAG_COMMAND); } else @@ -2168,7 +2178,7 @@ int Item::SendStatus(long sendFlags, char * subItem) { #if not defined (NOIP) if (mqttClient.connected() && !ethernetIdleCount) { - mqttClient.publish(addrstr, cmdstr,true); + mqttClient.publish(addrstr, cmdstr,retain); clearFlag(FLAG_FLAGS); } else diff --git a/lighthub/item.h b/lighthub/item.h index bee0f07..816f22d 100644 --- a/lighthub/item.h +++ b/lighthub/item.h @@ -145,7 +145,7 @@ class Item void setSubtype(uint8_t par); int Poll(int cause); int SendStatus(long sendFlags, char * subItem=NULL); - int SendStatusImmediate(itemCmd st, long sendFlags, char * subItem=NULL); + int SendStatusImmediate(itemCmd st, long sendFlags, char * subItem=NULL, bool tetain = true); int isActive(); int getChanType(); inline int On (){return Ctrl(itemCmd(ST_VOID,CMD_ON));}; diff --git a/lighthub/modules/out_ac.cpp b/lighthub/modules/out_ac.cpp index d56d869..34e2395 100644 --- a/lighthub/modules/out_ac.cpp +++ b/lighthub/modules/out_ac.cpp @@ -289,7 +289,7 @@ if (Status() == AC_SENDING) ACSerial->write(getCRC(req, size-1)); //ACSerial->flush(); store->timestamp=millisNZ(); - debugSerial<data)]; if(ACSerial->available() >= 37){ //was 0 - ACSerial->readBytes(store->data, 37); + ACSerial->readBytes(tmpdata, 37); while(ACSerial->available()){ delay(2); ACSerial->read(); } -debugSerial<> "); +debugSerial<> "); for (int i=0; i < 37-1; i++) { - if (store->data[i] < 10){ + if (tmpdata[i] < 10){ debugSerial.print("0"); - debugSerial.print(store->data[i], HEX); + debugSerial.print(tmpdata[i], HEX); } else { - debugSerial.print(store->data[i], HEX); + debugSerial.print(tmpdata[i], HEX); } } debugSerial.println('.'); - uint8_t crc=getCRC(store->data,36); + uint8_t crc=getCRC(tmpdata,36); - if (store->data[36] == crc) + if (tmpdata[36] == crc) { debugSerial<data[36] != store->inCheck) + if (tmpdata[36] != store->inCheck) { //Updated - store->inCheck = store->data[36]; + store->inCheck = tmpdata[36]; + memcpy(store->data,tmpdata,sizeof(store->data)); InsertData(store->data, 37); } } diff --git a/lighthub/modules/out_multivent.cpp b/lighthub/modules/out_multivent.cpp index fc26e95..dec5491 100644 --- a/lighthub/modules/out_multivent.cpp +++ b/lighthub/modules/out_multivent.cpp @@ -126,8 +126,9 @@ int out_Multivent::Poll(short cause) if (gatesObj) { // metrics, collected from AC - float acTemp = getFloatFromJson(aJson.getObjectItem(gatesObj, ""),"val",NAN); - int actualCmd = item->getCmd(); + aJsonObject * a = aJson.getObjectItem(gatesObj, ""); + float acTemp = getFloatFromJson(a,"val",NAN); + int actualCmd = getIntFromJson (a,"mode"); int actualMode = CMD_FAN; if (acTemp>30.0) actualMode = CMD_HEAT; else if (acTemp<15.0) actualMode = CMD_COOL; @@ -189,12 +190,12 @@ int out_Multivent::Poll(short cause) case CMD_HEAT: ((PID *) pidObj->valueint)->SetControllerDirection(DIRECT); debugSerial<itemArr->name<<"/"<name<valuefloat).setSuffix(S_FAN),i->name); + if (actualCmd!=CMD_OFF) Ctrl(itemCmd().Percents255(poObj->valuefloat).setSuffix(S_FAN),i->name); break; case CMD_COOL: ((PID *) pidObj->valueint)->SetControllerDirection(REVERSE); debugSerial<itemArr->name<<"/"<name<valuefloat).setSuffix(S_FAN),i->name); + if (actualCmd!=CMD_OFF) Ctrl(itemCmd().Percents255(poObj->valuefloat).setSuffix(S_FAN),i->name); } break; case CMD_HEAT: @@ -239,7 +240,8 @@ int out_Multivent::sendACcmd (int cmd) aJsonObject * a = aJson.getObjectItem(gatesObj, ""); if (!a) return 0; int lastCmd = getIntFromJson(a,"@lastCmd"); - if (lastCmd && (item->getCmd() != lastCmd)) { + int acCmd = getIntFromJson(a,"mode"); + if (lastCmd && (acCmd != lastCmd)) { //debugSerial<<"VENT: AC MODE changed manually to "<getCmd()<setExt(millisNZ()); setValToJson(aJson.getObjectItem(gatesObj, ""),"val",cmd.getFloat()); - /* - int mode = CMD_FAN; - int temp = cmd.getInt(); - if (temp>30) mode = CMD_HEAT; - else if (temp<17) mode = CMD_COOL; - - if (item->getCmd() != mode) - { - item->setCmd(mode); - pubAction(item->isActive()); - } - */ } return 1; @@ -296,6 +286,10 @@ switch (suffixCode) return 1; case S_MODE: + debugSerial << F("VENT:")<type; +cmdType = cmd->type; switch (cmdType) { @@ -1043,6 +1043,7 @@ if (a->type == aJson_Array) // TODO - human readable JSON objects as alias if (element && element->type == aJson_Int) return element->valueint; if (element && element->type == aJson_Float) return element->valuefloat; +if (element && element->type == aJson_Boolean) return element->valuebool; return def; } @@ -1055,6 +1056,8 @@ if (a->type == aJson_Object) element = aJson.getObjectItem(a, name); if (element && element->type == aJson_Int) return element->valueint; if (element && element->type == aJson_Float) return element->valuefloat; +if (element && element->type == aJson_Boolean) return element->valuebool; + return def; }