diff --git a/lighthub/inputs.cpp b/lighthub/inputs.cpp index eaad695..798ad75 100644 --- a/lighthub/inputs.cpp +++ b/lighthub/inputs.cpp @@ -526,16 +526,22 @@ if (newState == IS_REQSTATE) { // Requested delayed change State and safe moment newState=store->reqState; //Retrieve requested state - debugSerial<state<") <state == newState) + { + store->delayedState = false; + return false; + } } else return true; // No pended State else if (store->delayedState) return false; //State changing is postponed already (( giving up aJsonObject *cmd = NULL; +itemCmd defCmd; + int8_t toggle=0; -if (newState!=store->state) debugSerial<state<") <state && cause!=CHECK_INTERRUPT) debugSerial<state<") <state) debugSerial<state<toggle1; store->toggle1 = !store->toggle1; + if (!cmd) defCmd.Cmd(CMD_ON); break; case IS_PRESSED2: //scmd2 cmd = aJson.getObjectItem(inputObj, "scmd2"); @@ -580,6 +587,7 @@ if (newState!=store->state) debugSerial<state<toggle1; break; @@ -609,23 +617,31 @@ if (newState!=store->state) debugSerial<state<state=newState; + store->delayedState=false; return true; //nothing to do } + + if (cause != CHECK_INTERRUPT) { store->state=newState; - executeCommand(cmd,toggle); - //Executed store->delayedState=false; + executeCommand(cmd,toggle,defCmd,defaultItem,defaultEmit); return true; } else { //Postpone actual execution - store->reqState=store->state; + store->reqState=newState; store->delayedState=true; return true; } @@ -658,7 +674,8 @@ else else currentInputState = false; } else currentInputState = (digitalRead(pin) == inputOnLevel); -switch (store->state) //Timer based transitions + +if (cause != CHECK_INTERRUPT) switch (store->state) //Timer based transitions { case IS_PRESSED: if (isTimeOver(store->timestamp16,millis() & 0xFFFF,T_LONG,0xFFFF)) @@ -749,19 +766,21 @@ switch (store->state) //Timer based transitions { if (store->bounce) store->bounce = store->bounce - 1; else //confirmed change - { + { + //if (cause == CHECK_INTERRUPT) return; store->timestamp16 = millis() & 0xFFFF; //Saving timestamp of changing +/* if (inType & IN_PUSH_TOGGLE) { //To refactore if (currentInputState) { //react on leading edge only (change from 0 to 1) //store->logicState = !store->logicState; store->lastValue = currentInputState; - onContactChanged(store->toggle1); + onContactChanged(store->toggle1); } - } else + } else */ { - onContactChanged(currentInputState); //Legacy input - to remove later + // onContactChanged(currentInputState); //Legacy input - to remove later bool res = true; if (currentInputState) //Button pressed state transitions @@ -775,7 +794,14 @@ switch (store->state) //Timer based transitions case IS_RELEASED: case IS_WAITPRESS: - res = changeState(IS_PRESSED2, cause); + if ( //No future + !aJson.getObjectItem(inputObj, "scmd2") && + !aJson.getObjectItem(inputObj, "lcmd2") && + !aJson.getObjectItem(inputObj, "rpcmd2") + ) + res = changeState(IS_PRESSED, cause); + + else res = changeState(IS_PRESSED2, cause); break; @@ -790,6 +816,7 @@ switch (store->state) //Timer based transitions case IS_PRESSED: res = changeState(IS_RELEASED, cause); + break; case IS_LONG: @@ -799,7 +826,12 @@ switch (store->state) //Timer based transitions break; case IS_PRESSED2: - res = changeState(IS_RELEASED2, cause); + if ( //No future + !aJson.getObjectItem(inputObj, "scmd2") && + !aJson.getObjectItem(inputObj, "lcmd2") && + !aJson.getObjectItem(inputObj, "rpcmd2") + ) res = changeState(IS_IDLE, cause); + else res = changeState(IS_RELEASED2, cause); break; case IS_LONG2: @@ -826,6 +858,7 @@ switch (store->state) //Timer based transitions void Input::analogPoll(short cause) { int16_t inputVal; int32_t mappedInputVal; // 10x inputVal + if (cause == CHECK_INTERRUPT) return; aJsonObject *inputMap = aJson.getObjectItem(inputObj, "map"); int16_t Noize = ANALOG_NOIZE; short simple = 0; @@ -879,7 +912,7 @@ void Input::analogPoll(short cause) { if (simple) { if (mappedInputVal != store->currentValue) { - onContactChanged(mappedInputVal); + onContactChanged(mappedInputVal); store->currentValue = mappedInputVal; }} else @@ -892,7 +925,7 @@ void Input::analogPoll(short cause) { if ((store->bouncecurrentValue))//confirmed change { - onAnalogChanged(itemCmd().Tens(mappedInputVal)); + onAnalogChanged(itemCmd().Tens(mappedInputVal)); // store->currentValue = mappedInputVal; store->currentValue = inputVal; } @@ -954,6 +987,7 @@ if (!strchr(addrstr,'/')) setTopic(addrstr,sizeof(addrstr),T_OUT,emit->valuestri } } + void Input::onAnalogChanged(itemCmd newValue) { debugSerial << F("IN:") << (pin) << F("="); newValue.debugOut(); diff --git a/lighthub/main.cpp b/lighthub/main.cpp index 7e63b8b..e0188df 100644 --- a/lighthub/main.cpp +++ b/lighthub/main.cpp @@ -183,7 +183,7 @@ while (configLocked && !isTimeOver(stamp,millis(),10000)) #endif if (isNotRetainingStatus()) pollingLoop(); thermoLoop(); - inputLoop(); + inputLoop(CHECK_INPUT); yield(); } @@ -623,17 +623,18 @@ lan_status lanLoop() { lanStatus = DO_REINIT; break; case DHCP_CHECK_RENEW_FAIL: - errorSerial<read(); #endif yield(); - inputLoop(); + inputLoop(CHECK_INPUT); } #ifdef MDNS_ENABLE mdns.run(); @@ -2040,7 +2043,7 @@ void modbusIdle(void) { #endif } -void inputLoop(void) { +void inputLoop(short cause) { if (!inputs) return; configLocked++; @@ -2060,9 +2063,9 @@ configLocked++; while(inputObj) { Input in(inputObj,input); - in.Poll(CHECK_INPUT); + in.Poll(cause); - yield(); + //yield(); inputObj = inputObj->next; } @@ -2070,18 +2073,18 @@ configLocked++; else { Input in(input); - in.Poll(CHECK_INPUT); + in.Poll(cause); } } - yield(); + //yield(); input = input->next; } - timerInputCheck = millis();// + INTERVAL_CHECK_INPUT; + if (cause != CHECK_INTERRUPT) timerInputCheck = millis();// + INTERVAL_CHECK_INPUT; inCache.invalidateInputCache(); } //if (millis() > timerSensorCheck) - if (isTimeOver(timerSensorCheck,millis(),INTERVAL_CHECK_SENSOR)) + if (cause != CHECK_INTERRUPT && isTimeOver(timerSensorCheck,millis(),INTERVAL_CHECK_SENSOR)) { aJsonObject *input = inputs->child; while (input) { @@ -2096,6 +2099,29 @@ configLocked++; } configLocked--; } +volatile unsigned long timerCount=0; + +void TimerHandler(void) +{ + timerCount=millis(); + inputLoop(CHECK_INTERRUPT); + timerCount=millis()-timerCount; + +} + +#define TIMER_INTERVAL_MS 200 // 0.1s = 100ms + +#if defined(__SAM3X8E__) +int16_t attachTimer(double microseconds, timerCallback callback, const char* TimerName) +{ + int16_t timerNumber=-1; + DueTimerInterrupt dueTimerInterrupt = DueTimer.getAvailable(); + dueTimerInterrupt.attachInterruptInterval(microseconds, callback); + timerNumber = dueTimerInterrupt.getTimerNumber(); + debugSerial<next; } +#if defined(__SAM3X8E__) +// Interval in microsecs +attachTimer(TIMER_INTERVAL_MS * 1000, TimerHandler, "ITimer"); +#endif configLocked--; } @@ -2230,8 +2260,9 @@ void thermoLoop(void) { publishStat(); #ifndef DISABLE_FREERAM_PRINT (thermostatCheckPrinted) ? debugSerial< #include #include +#include "TimerInterrupt_Generic.h" #endif #if defined(ARDUINO_ARCH_AVR) @@ -285,7 +286,7 @@ void owIdle(void); void modbusIdle(void); -void inputLoop(void); +void inputLoop(short); void inputSetup(void); diff --git a/lighthub/utils.cpp b/lighthub/utils.cpp index c372646..94fe605 100644 --- a/lighthub/utils.cpp +++ b/lighthub/utils.cpp @@ -417,7 +417,7 @@ void printIPAddress(IPAddress ipAddress) { #ifdef WITH_PRINTEX_LIB (i < 3) ? debugSerial << (ipAddress[i]) << F(".") : debugSerial << (ipAddress[i])<type) +//char * legacyString =NULL; +aJsonObject *item = NULL; +aJsonObject *emit = NULL; +aJsonObject *icmd = NULL; +aJsonObject *ecmd = NULL; +char cmdType = 0; + +if (cmd) cmdType = cmd->type; + +switch (cmdType) { - case aJson_String: //legacy - no action - break; case aJson_Array: //array - recursive iterate { configLocked++; aJsonObject * command = cmd->child; while (command) { - executeCommand(command,toggle,_itemCmd); + executeCommand(command,toggle,_itemCmd,defaultItem,defaultEmit); command = command->next; } configLocked--; } break; - case aJson_Object: -{ -aJsonObject *act = aJson.getObjectItem(cmd, "act"); -if (act) return executeCommand(act,toggle,_itemCmd); + + case aJson_Object: //Modern way + { + aJsonObject *act = aJson.getObjectItem(cmd, "act"); + if (act) return executeCommand(act,toggle,_itemCmd); -aJsonObject *item = aJson.getObjectItem(cmd, "item"); -aJsonObject *emit = aJson.getObjectItem(cmd, "emit"); -aJsonObject *icmd = NULL; -aJsonObject *ecmd = NULL; + item = aJson.getObjectItem(cmd, "item"); + emit = aJson.getObjectItem(cmd, "emit"); + -switch (toggle) - { - case 0: - icmd = aJson.getObjectItem(cmd, "icmd"); - ecmd = aJson.getObjectItem(cmd, "ecmd"); - break; - case 1: - icmd = aJson.getObjectItem(cmd, "irev"); - ecmd = aJson.getObjectItem(cmd, "erev"); - //no *rev parameters - fallback - if (!icmd) icmd = aJson.getObjectItem(cmd, "icmd"); - if (!ecmd) ecmd = aJson.getObjectItem(cmd, "ecmd"); - } - -char * itemCommand = NULL; -char Buffer[16]; -if(icmd && icmd->type == aJson_String) itemCommand = icmd->valuestring; - //else itemCommand = _itemCmd.toString(Buffer,sizeof(Buffer)); - -char * emitCommand; -if(ecmd && ecmd->type == aJson_String) emitCommand = ecmd->valuestring; - else emitCommand = _itemCmd.toString(Buffer,sizeof(Buffer)); - -//debugSerial << F("IN:") << (pin) << F(" : ") <valuestring<< F(" -> ")<valuestring<< F(" -> ");_itemCmd.debugOut(); - } -if (emit) debugSerial << emit->valuestring<< F(" -> ")<type == aJson_String) { -/* -TODO implement -#ifdef WITH_DOMOTICZ - if (getIdxField()) - { (newValue) ? publishDataToDomoticz(0, emit, "{\"command\":\"switchlight\",\"idx\":%s,\"switchcmd\":\"On\"}", - : publishDataToDomoticz(0,emit,"{\"command\":\"switchlight\",\"idx\":%s,\"switchcmd\":\"Off\"}",getIdxField()); getIdxField()) - : publishDataToDomoticz(0, emit, - "{\"command\":\"switchlight\",\"idx\":%s,\"switchcmd\":\"Off\"}", - getIdxField()); - } else -#endif -*/ - - -char addrstr[MQTT_TOPIC_LENGTH]; -strncpy(addrstr,emit->valuestring,sizeof(addrstr)); -if (mqttClient.connected() && !ethernetIdleCount) -{ -if (!strchr(addrstr,'/')) setTopic(addrstr,sizeof(addrstr),T_OUT,emit->valuestring); -mqttClient.publish(addrstr, emitCommand , true); -} - -} // emit - -if (item && item->type == aJson_String) { - //debugSerial <valuestring <valuestring); - if (it.isValid()) - { - if (itemCommand) it.Ctrl(itemCommand); - else it.Ctrl(_itemCmd); - } + switch (toggle) + { + case 0: + icmd = aJson.getObjectItem(cmd, "icmd"); + ecmd = aJson.getObjectItem(cmd, "ecmd"); + break; + case 1: + icmd = aJson.getObjectItem(cmd, "irev"); + ecmd = aJson.getObjectItem(cmd, "erev"); + //no *rev parameters - fallback + if (!icmd) icmd = aJson.getObjectItem(cmd, "icmd"); + if (!ecmd) ecmd = aJson.getObjectItem(cmd, "ecmd"); + } + } + //Continue + case aJson_String: //legacy + if (!icmd) icmd=cmd; + if (!ecmd) ecmd=cmd; + //Continue + case 0: // NULL command object + { + if (!item) item = defaultItem; + if (!emit) emit = defaultEmit; + + char * itemCommand = NULL; + char Buffer[16]; + if(icmd && icmd->type == aJson_String) itemCommand = icmd->valuestring; + //else itemCommand = _itemCmd.toString(Buffer,sizeof(Buffer)); + + char * emitCommand; + if(ecmd && ecmd->type == aJson_String) emitCommand = ecmd->valuestring; + else emitCommand = _itemCmd.toString(Buffer,sizeof(Buffer)); + + //debugSerial << F("IN:") << (pin) << F(" : ") <valuestring<< F(" -> ")<valuestring<< F(" -> ");_itemCmd.debugOut(); + } + + + + + + if (emit && emitCommand && emit->type == aJson_String) { + debugSerial << F("Emit: ")<valuestring<< F(" -> ")<valuestring,sizeof(addrstr)); + if (mqttClient.connected() && !ethernetIdleCount) + { + if (!strchr(addrstr,'/')) setTopic(addrstr,sizeof(addrstr),T_OUT,emit->valuestring); + mqttClient.publish(addrstr, emitCommand , true); + } + + } // emit + + if (item && item->type == aJson_String) { + //debugSerial <valuestring <valuestring); + if (it.isValid()) + { + if (itemCommand) it.Ctrl(itemCommand); + else it.Ctrl(_itemCmd); + } + } + return true; } -return true; -} default: return false; } //switch type diff --git a/lighthub/utils.h b/lighthub/utils.h index a0bbdea..9a82a43 100644 --- a/lighthub/utils.h +++ b/lighthub/utils.h @@ -70,7 +70,7 @@ void softRebootFunc(); bool isTimeOver(uint32_t timestamp, uint32_t currTime, uint32_t time, uint32_t modulo = 0xFFFFFFFF); //bool executeCommand(aJsonObject* cmd, int8_t toggle = -1, char* defCmd = NULL); bool executeCommand(aJsonObject* cmd, int8_t toggle = -1); -bool executeCommand(aJsonObject* cmd, int8_t toggle, itemCmd _itemCmd); +bool executeCommand(aJsonObject* cmd, int8_t toggle, itemCmd _itemCmd, aJsonObject* defaultItem=NULL, aJsonObject* defaultEmit=NULL); itemCmd mapInt(int32_t arg, aJsonObject* map); unsigned long millisNZ(uint8_t shift=0); serialParamType str2SerialParam(char * str); diff --git a/platformio.ini b/platformio.ini index f11790a..76276ac 100644 --- a/platformio.ini +++ b/platformio.ini @@ -117,7 +117,8 @@ lib_deps = Adafruit BusIO https://github.com/arcao/Syslog.git br3ttb/PID@^1.2.1 - ;ArduinoMDNS + TimerInterrupt_Generic + monitor_speed = 115200 [env:m5stack] @@ -175,6 +176,8 @@ lib_deps = https://github.com/arcao/Syslog.git br3ttb/PID@^1.2.1 ArduinoMDNS + https://github.com/khoih-prog/TimerInterrupt_Generic.git + monitor_speed = 115200 [env:esp32-wifi] @@ -237,7 +240,8 @@ lib_deps = https://github.com/arcao/Syslog.git br3ttb/PID@^1.2.1 ArduinoMDNS - + https://github.com/khoih-prog/TimerInterrupt_Generic.git + monitor_speed = 115200 [env:due-5100] @@ -290,6 +294,8 @@ lib_deps = Adafruit BusIO br3ttb/PID@^1.2.1 ArduinoMDNS + https://github.com/khoih-prog/TimerInterrupt_Generic.git + monitor_speed = 115200 [env:due] @@ -350,6 +356,7 @@ lib_deps = Adafruit BusIO br3ttb/PID@^1.2.1 ArduinoMDNS + https://github.com/khoih-prog/TimerInterrupt_Generic.git monitor_speed = 115200 [env:mega2560slim-5100] @@ -398,6 +405,8 @@ lib_deps = Adafruit BusIO br3ttb/PID@^1.2.1 ArduinoMDNS + https://github.com/khoih-prog/TimerInterrupt_Generic.git + monitor_speed = 115200 @@ -463,6 +472,8 @@ lib_deps = Adafruit BusIO br3ttb/PID@^1.2.1 ArduinoMDNS + https://github.com/khoih-prog/TimerInterrupt_Generic.git + monitor_speed = 115200 @@ -512,6 +523,8 @@ lib_deps = Adafruit BusIO br3ttb/PID@^1.2.1 ArduinoMDNS + https://github.com/khoih-prog/TimerInterrupt_Generic.git + monitor_speed = 115200 [env:esp8266-wifi] @@ -550,6 +563,8 @@ lib_ignore = UIPEthernet EEPROM M5Stack + https://github.com/khoih-prog/TimerInterrupt_Generic.git + lib_deps = https://github.com/anklimov/Arduino-Temperature-Control-Library.git ;COMMENT/UNCOMMENT next line for software 1-wire driver on/off @@ -627,6 +642,8 @@ lib_deps = Adafruit BusIO br3ttb/PID@^1.2.1 ArduinoMDNS + https://github.com/khoih-prog/TimerInterrupt_Generic.git + monitor_speed = 115200 [env:due-5500] @@ -680,6 +697,8 @@ lib_deps = Adafruit BusIO br3ttb/PID@^1.2.1 ArduinoMDNS + https://github.com/khoih-prog/TimerInterrupt_Generic.git + monitor_speed = 115200 [env:lighthub21] @@ -737,6 +756,8 @@ lib_deps = Adafruit BusIO br3ttb/PID@^1.2.1 ArduinoMDNS + https://github.com/khoih-prog/TimerInterrupt_Generic.git + monitor_speed = 115200 [env:controllino] @@ -786,6 +807,8 @@ lib_deps = https://github.com/arcao/Syslog.git br3ttb/PID@^1.2.1 ArduinoMDNS + https://github.com/khoih-prog/TimerInterrupt_Generic.git + monitor_speed = 115200 [env:stm32-enc2860] @@ -841,6 +864,8 @@ lib_deps = SPI br3ttb/PID@^1.2.1 ArduinoMDNS + https://github.com/khoih-prog/TimerInterrupt_Generic.git + monitor_speed = 115200 ; Run the following command to upload with this environment