diff --git a/openBeken_win32_mvsc2017.vcxproj b/openBeken_win32_mvsc2017.vcxproj
index 4f6cfb17f..4b616f94e 100644
--- a/openBeken_win32_mvsc2017.vcxproj
+++ b/openBeken_win32_mvsc2017.vcxproj
@@ -831,6 +831,7 @@
+
diff --git a/openBeken_win32_mvsc2017.vcxproj.filters b/openBeken_win32_mvsc2017.vcxproj.filters
index 4b25b3d02..fb9edd272 100644
--- a/openBeken_win32_mvsc2017.vcxproj.filters
+++ b/openBeken_win32_mvsc2017.vcxproj.filters
@@ -833,6 +833,9 @@
Drv
+
+ SelfTest
+
diff --git a/src/cmnds/cmd_eventHandlers.c b/src/cmnds/cmd_eventHandlers.c
index f8a3e5bd4..da24cf79a 100644
--- a/src/cmnds/cmd_eventHandlers.c
+++ b/src/cmnds/cmd_eventHandlers.c
@@ -123,7 +123,7 @@ static int EVENT_ParseRelation(const char *s) {
return EVENT_DEFAULT;
}
-static int EVENT_ParseEventName(const char *s) {
+int EVENT_ParseEventName(const char *s) {
if(!wal_strnicmp(s,"channel",7)) {
return CMD_EVENT_CHANGE_CHANNEL0 + atoi(s+7);
}
@@ -364,6 +364,8 @@ void EventHandlers_FireEvent(byte eventCode, int argument) {
}
ev = ev->next;
}
+
+ CMD_Script_ProcessWaitersForEvent(eventCode, argument);
}
void EventHandlers_FireEvent_String(byte eventCode, const char *argument) {
struct eventHandler_s *ev;
@@ -435,7 +437,7 @@ static commandResult_t CMD_AddEventHandler(const void *context, const char *cmd,
eventCode = EVENT_ParseEventName(eventName);
if(eventCode == CMD_EVENT_NONE) {
- ADDLOG_ERROR(LOG_FEATURE_EVENT, "CMD_AddEventHandler: %s is not a valid event",eventName);
+ ADDLOG_ERROR(LOG_FEATURE_EVENT, "%s is not a valid event",eventName);
return CMD_RES_BAD_ARGUMENT;
}
diff --git a/src/cmnds/cmd_public.h b/src/cmnds/cmd_public.h
index c5472bd32..5610938c8 100644
--- a/src/cmnds/cmd_public.h
+++ b/src/cmnds/cmd_public.h
@@ -122,6 +122,7 @@ enum EventCode {
CMD_EVENT_MAX_TYPES
};
+int EVENT_ParseEventName(const char *s);
// the slider control in the UI emits values
//in the range from 154-500 (defined
diff --git a/src/cmnds/cmd_script.c b/src/cmnds/cmd_script.c
index 677fa1889..a40eb52b6 100644
--- a/src/cmnds/cmd_script.c
+++ b/src/cmnds/cmd_script.c
@@ -238,6 +238,9 @@ typedef struct scriptInstance_s {
const char *curLine;
int currentDelayMS;
+ int waitingForEvent;
+ int waitingForArgument;
+
struct scriptInstance_s *next;
} scriptInstance_t;
@@ -361,6 +364,10 @@ void SVM_RunThread(scriptInstance_t *t) {
while(1) {
loop++;
+ // check if "waitFor" was executed last frame
+ if (t->waitingForEvent) {
+ return;
+ }
if(t->curLine == 0) {
t->curLine = 0;
t->curFile = 0;
@@ -423,22 +430,45 @@ void SVM_RunThreads(int deltaMS) {
g_activeThread = g_scriptThreads;
while(g_activeThread) {
- if(g_activeThread->currentDelayMS > 0) {
- g_activeThread->currentDelayMS -= deltaMS;
- // the following block is needed to handle with long freezes on simulator
- if (g_activeThread->currentDelayMS < 0) {
- g_activeThread->currentDelayMS = 0;
- }
+ if (g_activeThread->waitingForEvent) {
+ // do nothing
c_sleep++;
- } else {
- SVM_RunThread(g_activeThread);
- c_run++;
+ }
+ else {
+ if (g_activeThread->currentDelayMS > 0) {
+ g_activeThread->currentDelayMS -= deltaMS;
+ // the following block is needed to handle with long freezes on simulator
+ if (g_activeThread->currentDelayMS < 0) {
+ g_activeThread->currentDelayMS = 0;
+ }
+ c_sleep++;
+ }
+ else {
+ SVM_RunThread(g_activeThread);
+ c_run++;
+ }
}
g_activeThread = g_activeThread->next;
}
//ADDLOG_INFO(LOG_FEATURE_CMD, "SCR sleep %i, ran %i",c_sleep,c_run);
}
+void CMD_Script_ProcessWaitersForEvent(byte eventCode, int argument) {
+ scriptInstance_t *t;
+
+ t = g_scriptThreads;
+
+ while (t) {
+ if (t->waitingForEvent == eventCode) {
+ if (t->waitingForArgument == argument) {
+ // unlock!
+ t->waitingForArgument = 0;
+ t->waitingForEvent = 0;
+ }
+ }
+ t = t->next;
+ }
+}
void SVM_GoTo(scriptInstance_t *th, const char *fname, const char *label) {
scriptFile_t *f;
@@ -741,6 +771,37 @@ commandResult_t CMD_resetSVM(const void *context, const char *cmd, const char *a
return CMD_RES_OK;
}
+commandResult_t CMD_waitFor(const void *context, const char *cmd, const char *args, int cmdFlags) {
+ const char *eventName;
+ int reqArg, eventCode;
+
+ if (g_activeThread == 0) {
+ ADDLOG_INFO(LOG_FEATURE_CMD, "CMD_waitFor: this can be only used from a script");
+ return CMD_RES_ERROR;
+ }
+
+ Tokenizer_TokenizeString(args, 0);
+ // following check must be done after 'Tokenizer_TokenizeString',
+ // so we know arguments count in Tokenizer. 'cmd' argument is
+ // only for warning display
+ if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 2)) {
+ return CMD_RES_NOT_ENOUGH_ARGUMENTS;
+ }
+ eventName = Tokenizer_GetArg(0);
+
+ eventCode = EVENT_ParseEventName(eventName);
+ if (eventCode == CMD_EVENT_NONE) {
+ ADDLOG_ERROR(LOG_FEATURE_EVENT, "%s is not a valid event", eventName);
+ return CMD_RES_BAD_ARGUMENT;
+ }
+
+ reqArg = Tokenizer_GetArgInteger(1);
+
+ g_activeThread->waitingForEvent = eventCode;
+ g_activeThread->waitingForArgument = reqArg;
+
+ return CMD_RES_OK;
+}
void CMD_InitScripting(){
//cmddetail:{"name":"startScript","args":"[FileName][Label][UniqueID]",
//cmddetail:"descr":"Starts a script thread from given file, at given label - can be * for whole file, with given unique ID",
@@ -787,6 +848,11 @@ void CMD_InitScripting(){
//cmddetail:"fn":"CMD_resetSVM","file":"cmnds/cmd_script.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("resetSVM", CMD_resetSVM, NULL);
+ //cmddetail:{"name":"waitFor","args":"[EventName] [Argument]",
+ //cmddetail:"descr":"Wait forever for event.",
+ //cmddetail:"fn":"CMD_waitFor","file":"cmnds/cmd_script.c","requires":"",
+ //cmddetail:"examples":""}
+ CMD_RegisterCommand("waitFor", CMD_waitFor, NULL);
}
diff --git a/src/httpserver/http_fns.c b/src/httpserver/http_fns.c
index 2f27c36ef..98e41a1d5 100644
--- a/src/httpserver/http_fns.c
+++ b/src/httpserver/http_fns.c
@@ -2184,7 +2184,7 @@ const char* g_obk_flagNames[] = {
"[LED] Use old linear brightness mode, ignore gamma ramp",
"[MQTT] Apply channel type multiplier on (if any) on channel value before publishing it",
"[MQTT] In HA discovery, add relays as lights",
- "[HASS] Deactivate avty_t flag for sensor when publishing to HASS (permit to keep value)",
+ "[HASS] Deactivate avty_t flag for sensor when publishing to HASS (permit to keep value). You must restart HASS discovery for change to take effect.",
"[DRV] Deactivate Autostart of all drivers",
"[WiFi] Quick connect to WiFi on reboot (TODO: check if it works for you and report on github)",
"[Power] Set power and current to zero if all relays are open",
diff --git a/src/selftest/selftest_local.h b/src/selftest/selftest_local.h
index d9568cf80..a64f9466c 100644
--- a/src/selftest/selftest_local.h
+++ b/src/selftest/selftest_local.h
@@ -98,6 +98,7 @@ void Test_CFG_Via_HTTP();
void Test_Demo_ButtonScrollingChannelValues();
void Test_Demo_ButtonToggleGroup();
void Test_Role_ToggleAll_2();
+void Test_WaitFor();
void Test_GetJSONValue_Setup(const char *text);
void Test_FakeHTTPClientPacket_GET(const char *tg);
diff --git a/src/selftest/selftest_waitFor.c b/src/selftest/selftest_waitFor.c
new file mode 100644
index 000000000..36b4fcce3
--- /dev/null
+++ b/src/selftest/selftest_waitFor.c
@@ -0,0 +1,59 @@
+#ifdef WINDOWS
+
+#include "selftest_local.h".
+
+/*
+Example autoexec.bat usage:
+
+// do anything on startup
+startDriver NTP
+startDriver SSDP
+
+// now wait for MQTT
+waitFor MQTTState 1
+// extra delay, to be sure
+delay_s 1
+publish myVariable 2022
+
+
+*/
+void Test_WaitFor() {
+ int i;
+ char buffer[64];
+
+ // reset whole device
+ SIM_ClearOBK(0);
+
+ // send file content as POST to REST interface
+ Test_FakeHTTPClientPacket_POST("api/lfs/testScript.txt",
+ "setChannel 1 50\n"
+ "setChannel 2 75\n"
+ "waitFor MQTTState 1\n"
+ "setChannel 1 123\n"
+ "setChannel 2 234\n");
+
+ CMD_ExecuteCommand("setChannel 1 0", 0);
+ CMD_ExecuteCommand("setChannel 2 0", 0);
+
+ SELFTEST_ASSERT_CHANNEL(1, 0);
+ SELFTEST_ASSERT_CHANNEL(2, 0);
+
+ CMD_ExecuteCommand("startScript testScript.txt", 0);
+
+ for (i = 0; i < 10; i++) {
+ SVM_RunThreads(5);
+ }
+ SELFTEST_ASSERT_CHANNEL(1, 50);
+ SELFTEST_ASSERT_CHANNEL(2, 75);
+
+ CMD_Script_ProcessWaitersForEvent(CMD_EVENT_MQTT_STATE,1);
+
+ for (i = 0; i < 10; i++) {
+ SVM_RunThreads(5);
+ }
+ SELFTEST_ASSERT_CHANNEL(1, 123);
+ SELFTEST_ASSERT_CHANNEL(2, 234);
+
+}
+
+#endif
diff --git a/src/win_main.c b/src/win_main.c
index 7e45a7e6d..f48cc8a64 100644
--- a/src/win_main.c
+++ b/src/win_main.c
@@ -127,6 +127,7 @@ void SIM_ClearOBK(const char *flashPath) {
Main_Init();
}
void Win_DoUnitTests() {
+ Test_WaitFor();
Test_TwoPWMsOneChannel();
Test_ClockEvents();
Test_HassDiscovery();