From 2898d57ed5d76c327ab4e5a3bd53ec5140287d25 Mon Sep 17 00:00:00 2001 From: openshwprojects <85486843+openshwprojects@users.noreply.github.com> Date: Wed, 3 Dec 2025 09:59:37 +0100 Subject: [PATCH] added vars: - $mqtt_client - $shortName - $name * exp * fix * Update cmd_tasmota.c --- src/cmnds/cmd_berry.c | 2 +- src/cmnds/cmd_if.c | 66 ++++++++++++++++++++--------- src/cmnds/cmd_public.h | 4 +- src/cmnds/cmd_tasmota.c | 13 ++++++ src/cmnds/cmd_tokenizer.c | 4 +- src/mqtt/new_mqtt.c | 4 +- src/selftest/selftest_http_client.c | 3 ++ src/selftest/selftest_mqtt.c | 55 ++++++++++++++++++++++++ src/win_main.c | 4 +- 9 files changed, 126 insertions(+), 29 deletions(-) diff --git a/src/cmnds/cmd_berry.c b/src/cmnds/cmd_berry.c index a099a99eb..a6411ab66 100644 --- a/src/cmnds/cmd_berry.c +++ b/src/cmnds/cmd_berry.c @@ -326,7 +326,7 @@ int be_get(bvm *vm) { const char *name = be_tostring(vm, 1); if (name[0] == '$') { float ret; - CMD_ExpandConstant(name, 0, &ret); + CMD_ExpandConstantFloat(name, 0, &ret); be_pushreal(vm, ret); be_return(vm); } diff --git a/src/cmnds/cmd_if.c b/src/cmnds/cmd_if.c index 8ecb84eae..ec84611a2 100644 --- a/src/cmnds/cmd_if.c +++ b/src/cmnds/cmd_if.c @@ -582,7 +582,7 @@ static int g_totalConstants = sizeof(g_constants) / sizeof(g_constants[0]); // Etc etc // Returns true if constant matches // Returns false if no constants found -const char *CMD_ExpandConstant(const char *s, const char *stop, float *out) { +const char *CMD_ExpandConstantFloat(const char *s, const char *stop, float *out) { #if ENABLE_EXPAND_CONSTANT const constant_t *var; int i; @@ -592,7 +592,7 @@ const char *CMD_ExpandConstant(const char *s, const char *stop, float *out) { const char *ret = strCompareBound(s, var->constantName, stop, bAllowWildCard); if (ret) { *out = var->getValue(s); - ADDLOG_IF_MATHEXP_DBG(LOG_FEATURE_EVENT, "CMD_ExpandConstant: %s", var->name); + ADDLOG_IF_MATHEXP_DBG(LOG_FEATURE_EVENT, "CMD_ExpandConstantFloat: %s", var->name); return ret; } } @@ -611,7 +611,7 @@ byte CMD_ParseOrExpandHexByte(const char **p) { while (*stop && *stop != '$') { stop++; } - CMD_ExpandConstant(*p, stop, &fv); + CMD_ExpandConstantFloat(*p, stop, &fv); val = fv; *p = stop; @@ -662,12 +662,13 @@ void SIM_GenerateChannelStatesDesc(char *o, int outLen) { } } } - +#endif const char *CMD_ExpandConstantString(const char *s, const char *stop, char *out, int outLen) { int idx; const char *ret; char tmp[32]; +#if WINDOWS ret = strCompareBound(s, "$autoexec.bat", stop, false); if (ret) { byte* data = LFS_ReadFile("autoexec.bat"); @@ -728,9 +729,27 @@ const char *CMD_ExpandConstantString(const char *s, const char *stop, char *out, SIM_GeneratePowerStateDesc(out, outLen); return ret; } +#endif + ret = strCompareBound(s, "$mqtt_client", stop, false); + if (ret) { + const char *res = CFG_GetMQTTClientId(); + strcpy_safe(out, res, outLen); + return ret; + } + ret = strCompareBound(s, "$shortName", stop, false); + if (ret) { + const char *res = CFG_GetShortDeviceName(); + strcpy_safe(out, res, outLen); + return ret; + } + ret = strCompareBound(s, "$name", stop, false); + if (ret) { + const char *res = CFG_GetDeviceName(); + strcpy_safe(out, res, outLen); + return ret; + } return false; } -#endif const char* CMD_ExpandConstantToString(const char* constant, char* out, char* stop) { @@ -742,14 +761,12 @@ const char* CMD_ExpandConstantToString(const char* constant, char* out, char* st outLen = (stop - out) - 1; - after = CMD_ExpandConstant(constant, 0, &value); -#if WINDOWS + after = CMD_ExpandConstantFloat(constant, 0, &value); if(after == 0) { after = CMD_ExpandConstantString(constant, 0, out, outLen); return after; } -#endif if(after == 0) return 0; @@ -800,6 +817,17 @@ void CMD_ExpandConstantsWithinString(const char *in, char *out, int outLen) { } *out = 0; } +int CMD_CountVarsInString(const char *in) { + const char *p = in; + int varCount = 0; + while (*p) { + if (*p == '$') { + varCount++; + } + p++; + } + return varCount; +} // like a strdup, but will expand constants. // Please remember to free the returned string char *CMD_ExpandingStrdup(const char *in) { @@ -808,29 +836,25 @@ char *CMD_ExpandingStrdup(const char *in) { int varCount; int realLen; - realLen = 0; - varCount = 0; // I am not sure which approach should I take // It could be easily done with external buffer, but it would have to be on stack or a global one... // Maybe let's just assume that variables cannot grow string way too big - p = in; - while (*p) { - if (*p == '$') { - varCount++; - } - realLen++; - p++; - } - + realLen = strlen(in); + varCount = CMD_CountVarsInString(in); + // not all var names are short, some are long... // but $CH1 is short and could expand to something longer like, idk, 123456? // just to be on safe side.... - realLen += varCount * 5; + realLen += varCount * 10; // space for NULL and also space to be sure realLen += 2; ret = (char*)malloc(realLen); + if (ret == 0) { + // malloc failed + return ret; + } CMD_ExpandConstantsWithinString(in, ret, realLen); return ret; } @@ -964,7 +988,7 @@ float CMD_EvaluateExpression(const char *s, const char *stop) { if (s[0] == '!') { return !CMD_EvaluateExpression(s + 1, stop); } - if (CMD_ExpandConstant(s, stop, &c)) { + if (CMD_ExpandConstantFloat(s, stop, &c)) { return c; } diff --git a/src/cmnds/cmd_public.h b/src/cmnds/cmd_public.h index 7c836ca3b..09e8c06d8 100644 --- a/src/cmnds/cmd_public.h +++ b/src/cmnds/cmd_public.h @@ -75,8 +75,9 @@ commandResult_t CMD_ExecuteCommandArgs(const char* cmd, const char* args, int cm // like a strdup, but will expand constants. // Please remember to free the returned string char* CMD_ExpandingStrdup(const char* in); +int CMD_CountVarsInString(const char *in); commandResult_t CMD_CreateAliasHelper(const char *alias, const char *ocmd); -const char *CMD_ExpandConstant(const char *s, const char *stop, float *out); +const char *CMD_ExpandConstantFloat(const char *s, const char *stop, float *out); byte CMD_ParseOrExpandHexByte(const char **p); enum EventCode { @@ -329,6 +330,7 @@ void SVM_RunThreads(int deltaMS); void CMD_InitScripting(); void SVM_RunStartupCommandAsScript(); byte* LFS_ReadFile(const char* fname); +byte* LFS_ReadFileExpanding(const char* fname); int LFS_WriteFile(const char *fname, const byte *data, int len, bool bAppend); commandResult_t CMD_ClearAllHandlers(const void* context, const char* cmd, const char* args, int cmdFlags); diff --git a/src/cmnds/cmd_tasmota.c b/src/cmnds/cmd_tasmota.c index 7e604fe86..153f0ea6a 100644 --- a/src/cmnds/cmd_tasmota.c +++ b/src/cmnds/cmd_tasmota.c @@ -270,6 +270,19 @@ byte *LFS_ReadFile(const char *fname) { #endif return 0; } +byte* LFS_ReadFileExpanding(const char* fname) { + byte *d = LFS_ReadFile(fname); + if (d == 0) + return 0; + const char *s = (const char *)d; + int vars = CMD_CountVarsInString(s); + if (vars == 0) { + return d; + } + char *r = CMD_ExpandingStrdup(s); + free(d); + return (byte*)r; +} int LFS_WriteFile(const char *fname, const byte *data, int len, bool bAppend) { #if ENABLE_LITTLEFS init_lfs(1); diff --git a/src/cmnds/cmd_tokenizer.c b/src/cmnds/cmd_tokenizer.c index bfdc713b7..82df6dc5c 100644 --- a/src/cmnds/cmd_tokenizer.c +++ b/src/cmnds/cmd_tokenizer.c @@ -123,7 +123,7 @@ const char *Tokenizer_GetArgExpanding(int i) { else { float f; int iValue; - CMD_ExpandConstant(tconst, 0, &f); + CMD_ExpandConstantFloat(tconst, 0, &f); iValue = f; sprintf(convert, "%i", iValue); strcat_safe(Templine, convert, sizeof(Templine)); @@ -184,7 +184,7 @@ const char *Tokenizer_GetArg(int i) { else { float f; int iValue; - CMD_ExpandConstant(s, 0, &f); + CMD_ExpandConstantFloat(s, 0, &f); iValue = f; sprintf(g_argsExpanded[i], "%i", iValue); } diff --git a/src/mqtt/new_mqtt.c b/src/mqtt/new_mqtt.c index 3b8c14ac8..c3c089307 100644 --- a/src/mqtt/new_mqtt.c +++ b/src/mqtt/new_mqtt.c @@ -1555,7 +1555,7 @@ commandResult_t MQTT_PublishFile(const void* context, const char* cmd, const cha int flags = 0; byte*data; - Tokenizer_TokenizeString(args, TOKENIZER_ALLOW_QUOTES | TOKENIZER_ALLOW_ESCAPING_QUOTATIONS); + Tokenizer_TokenizeString(args, TOKENIZER_ALLOW_QUOTES | TOKENIZER_ALLOW_ESCAPING_QUOTATIONS | TOKENIZER_EXPAND_EARLY); if (Tokenizer_GetArgsCount() < 2) { addLogAdv(LOG_INFO, LOG_FEATURE_MQTT, "Publish command requires two arguments (topic and value)"); @@ -1567,7 +1567,7 @@ commandResult_t MQTT_PublishFile(const void* context, const char* cmd, const cha if (Tokenizer_GetArgIntegerDefault(2, 0) != 0) { flags = OBK_PUBLISH_FLAG_RAW_TOPIC_NAME; } - data = LFS_ReadFile(fname); + data = LFS_ReadFileExpanding(fname); if (data) { ret = MQTT_PublishMain_StringString(topic, (const char*)data, flags); free(data); diff --git a/src/selftest/selftest_http_client.c b/src/selftest/selftest_http_client.c index a3938a6b2..087466b6d 100644 --- a/src/selftest/selftest_http_client.c +++ b/src/selftest/selftest_http_client.c @@ -33,6 +33,9 @@ void Test_HTTP_Client() { Sim_RunSeconds(5, true); SELFTEST_ASSERT_CHANNEL(1, 1); #endif + //CMD_ExecuteCommand("SendGet http://127.0.0.1/cm?cmnd=POWER%20TOGGLE", 0); + //Sim_RunFrames(15, false); + //SELFTEST_ASSERT_CHANNEL(1, 1); } diff --git a/src/selftest/selftest_mqtt.c b/src/selftest/selftest_mqtt.c index 1e7f5e1ba..aea5b1ef4 100644 --- a/src/selftest/selftest_mqtt.c +++ b/src/selftest/selftest_mqtt.c @@ -515,6 +515,61 @@ void Test_MQTT_Misc() { SIM_ClearOBK(0); SIM_ClearAndPrepareForMQTTTesting("miscDevice", "bekens"); + CMD_ExecuteCommand("publish homeassistant/test/laaa payload 1", 0); + SELFTEST_ASSERT_HAD_MQTT_PUBLISH_STR("homeassistant/test/laaa", "payload", false); + SIM_ClearMQTTHistory(); + // var in topic + CMD_ExecuteCommand("publish homeassistant/$mqtt_client/laaa payload 1", 0); + SELFTEST_ASSERT_HAD_MQTT_PUBLISH_STR("homeassistant/miscDevice/laaa", "payload", false); + SIM_ClearMQTTHistory(); + // var in payload + CMD_ExecuteCommand("publish homeassistant/hey/laaa $mqtt_client 1", 0); + SELFTEST_ASSERT_HAD_MQTT_PUBLISH_STR("homeassistant/hey/laaa", "miscDevice", false); + // var in payload + CMD_ExecuteCommand("publish homeassistant/hey/laaa my_name_is_$mqtt_client 1", 0); + SELFTEST_ASSERT_HAD_MQTT_PUBLISH_STR("homeassistant/hey/laaa", "my_name_is_miscDevice", false); + SIM_ClearMQTTHistory(); + + + CMD_ExecuteCommand("publish homeassistant/hey/laaa my_name_is_$mqtt_client 1", 0); + SELFTEST_ASSERT_HAD_MQTT_PUBLISH_STR("homeassistant/hey/laaa", "my_name_is_miscDevice", false); + SIM_ClearMQTTHistory(); + + CMD_ExecuteCommand("publish homeassistant/cover/$mqtt_client/config {\"name\":\"$mqtt_client\"} 1", 0); + SELFTEST_ASSERT_HAD_MQTT_PUBLISH_STR("homeassistant/cover/miscDevice/config", "{\"name\":\"miscDevice\"}", false); + SIM_ClearMQTTHistory(); + + + CMD_ExecuteCommand("publish homeassistant/cover/$mqtt_client/config {\"name\":\"$mqtt_client\",\"uniq_id\":\"$mqtt_client\",\"~\":\"$mqtt_client\",\"dev_cla\":\"shutter\",\"cmd_t\":\"~/backlog\",\"stat_t\":\"~/shutterState/get\",\"pl_open\":\"OPEN\",\"pl_cls\":\"CLOSE\",\"pl_stop\":\"STOP\",\"stat_o\":\"open\",\"stat_c\":\"closed\"} 1", 0); + SELFTEST_ASSERT_HAD_MQTT_PUBLISH_STR("homeassistant/cover/miscDevice/config", "{\"name\":\"miscDevice\",\"uniq_id\":\"miscDevice\",\"~\":\"miscDevice\",\"dev_cla\":\"shutter\",\"cmd_t\":\"~/backlog\",\"stat_t\":\"~/shutterState/get\",\"pl_open\":\"OPEN\",\"pl_cls\":\"CLOSE\",\"pl_stop\":\"STOP\",\"stat_o\":\"open\",\"stat_c\":\"closed\"}", false); + SIM_ClearMQTTHistory(); + + + CMD_ExecuteCommand("lfs_format", 0); + // send file content as POST to REST interface + Test_FakeHTTPClientPacket_POST("api/lfs/unitTestFile.txt", "filetext"); + // get this file + CMD_ExecuteCommand("publishFile homeassistant/cover/$mqtt_client/config unitTestFile.txt 1", 0); + SELFTEST_ASSERT_HAD_MQTT_PUBLISH_STR("homeassistant/cover/miscDevice/config", "filetext", false); + SIM_ClearMQTTHistory(); + + CMD_ExecuteCommand("lfs_format", 0); + // send file content as POST to REST interface + Test_FakeHTTPClientPacket_POST("api/lfs/unitTestFile.txt", "My name is $mqtt_client"); + // get this file + CMD_ExecuteCommand("publishFile homeassistant/cover/$mqtt_client/config unitTestFile.txt 1", 0); + SELFTEST_ASSERT_HAD_MQTT_PUBLISH_STR("homeassistant/cover/miscDevice/config", "My name is miscDevice", false); + SIM_ClearMQTTHistory(); + + CMD_ExecuteCommand("lfs_format", 0); + CMD_ExecuteCommand("SetChannel 5 123", 0); + // send file content as POST to REST interface + Test_FakeHTTPClientPacket_POST("api/lfs/unitTestFile.txt", "My name is $mqtt_client $CH5"); + // get this file + CMD_ExecuteCommand("publishFile homeassistant/cover/$mqtt_client/config unitTestFile.txt 1", 0); + SELFTEST_ASSERT_HAD_MQTT_PUBLISH_STR("homeassistant/cover/miscDevice/config", "My name is miscDevice 123", false); + SIM_ClearMQTTHistory(); + CMD_ExecuteCommand("addEventHandler OnChannelChange 5 publish myMagicResult $CH5", 0); // set channel 5 to 50 and see what we get SIM_SendFakeMQTTAndRunSimFrame_CMND("setChannel", "5 50"); diff --git a/src/win_main.c b/src/win_main.c index f382df847..4ed89089b 100644 --- a/src/win_main.c +++ b/src/win_main.c @@ -203,6 +203,8 @@ void Win_DoUnitTests() { // SELFTEST_ASSERT_EXPRESSION("sqrt(4)", 2) + Test_MQTT(); + Test_HTTP_Client(); // Test_PartitionSearch(); Test_OpenWeatherMap(); Test_MAX72XX(); @@ -227,7 +229,6 @@ void Win_DoUnitTests() Test_Backlog(); Test_DoorSensor(); Test_Command_If_Else(); - Test_MQTT(); Test_ChargeLimitDriver(); #if ENABLE_BL_SHARED Test_EnergyMeter(); @@ -276,7 +277,6 @@ void Win_DoUnitTests() Test_NTP(); Test_NTP_DST(); Test_NTP_SunsetSunrise(); - Test_HTTP_Client(); Test_ExpandConstant(); Test_ChangeHandlers_MQTT(); Test_ChangeHandlers();