From 13a618634e72e51d3c5e9b765e8049d5f5809994 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 28 Jul 2019 17:14:20 +0200 Subject: [PATCH] Refactor MQTT commands Refactor MQTT commands --- sonoff/support.ino | 39 +-- sonoff/support_command.ino | 22 +- sonoff/xdrv_01_webserver.ino | 2 +- sonoff/xdrv_02_mqtt.ino | 635 +++++++++++++++++++---------------- 4 files changed, 369 insertions(+), 329 deletions(-) diff --git a/sonoff/support.ino b/sonoff/support.ino index 5f6ef6df3..2ede71b0c 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -452,23 +452,23 @@ char IndexSeparator() } } -void SetShortcut(char* str, uint8_t action) +void SetShortcutDefault(void) { - if ('\0' != str[0]) { // There must be at least one character in the buffer - str[0] = '0' + action; // SC_CLEAR, SC_DEFAULT, SC_USER - str[1] = '\0'; + if ('\0' != XdrvMailbox.data[0]) { // There must be at least one character in the buffer + XdrvMailbox.data[0] = '0' + SC_DEFAULT; // SC_CLEAR, SC_DEFAULT, SC_USER + XdrvMailbox.data[1] = '\0'; } } -uint8_t Shortcut(const char* str) +uint8_t Shortcut() { uint8_t result = 10; - if ('\0' == str[1]) { // Only allow single character input for shortcut - if (('"' == str[0]) || ('0' == str[0])) { + if ('\0' == XdrvMailbox.data[1]) { // Only allow single character input for shortcut + if (('"' == XdrvMailbox.data[0]) || ('0' == XdrvMailbox.data[0])) { result = SC_CLEAR; } else { - result = atoi(str); // 1 = SC_DEFAULT, 2 = SC_USER + result = atoi(XdrvMailbox.data); // 1 = SC_DEFAULT, 2 = SC_USER if (0 == result) { result = 10; } @@ -502,29 +502,6 @@ bool ParseIp(uint32_t* addr, const char* str) return (3 == i); } -void MakeValidMqtt(uint32_t option, char* str) -{ -// option 0 = replace by underscore -// option 1 = delete character - uint32_t i = 0; - while (str[i] > 0) { -// if ((str[i] == '/') || (str[i] == '+') || (str[i] == '#') || (str[i] == ' ')) { - if ((str[i] == '+') || (str[i] == '#') || (str[i] == ' ')) { - if (option) { - uint32_t j = i; - while (str[j] > 0) { - str[j] = str[j +1]; - j++; - } - i--; - } else { - str[i] = '_'; - } - } - i++; - } -} - // Function to parse & check if version_str is newer than our currently installed version. bool NewerVersion(char* version_str) { diff --git a/sonoff/support_command.ino b/sonoff/support_command.ino index 2783507a1..e9ea88324 100644 --- a/sonoff/support_command.ino +++ b/sonoff/support_command.ino @@ -142,7 +142,8 @@ void CommandHandler(char* topic, uint8_t* data, uint32_t data_len) backlog_delay = millis() + (100 * MIN_BACKLOG_DELAY); - char command [CMDSZ]; + char command[CMDSZ]; + XdrvMailbox.command = command; XdrvMailbox.index = index; XdrvMailbox.data_len = data_len; XdrvMailbox.payload = payload; @@ -150,9 +151,8 @@ void CommandHandler(char* topic, uint8_t* data, uint32_t data_len) XdrvMailbox.usridx = user_index; XdrvMailbox.topic = type; XdrvMailbox.data = dataBuf; - XdrvMailbox.command = command; - int command_code = GetCommandCode(command, sizeof(command), type, kTasmotaCommands); + int command_code = GetCommandCode(XdrvMailbox.command, CMDSZ, type, kTasmotaCommands); if (command_code >= 0) { TasmotaCommand[command_code](); } else { @@ -398,7 +398,7 @@ void CmndUpgrade(void) void CmndOtaUrl(void) { if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.ota_url))) { - strlcpy(Settings.ota_url, (SC_DEFAULT == Shortcut(XdrvMailbox.data)) ? OTA_URL : XdrvMailbox.data, sizeof(Settings.ota_url)); + strlcpy(Settings.ota_url, (SC_DEFAULT == Shortcut()) ? OTA_URL : XdrvMailbox.data, sizeof(Settings.ota_url)); } Response_P(S_JSON_COMMAND_SVALUE, XdrvMailbox.command, Settings.ota_url); } @@ -946,7 +946,7 @@ void CmndSyslog(void) void CmndLoghost(void) { if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.syslog_host))) { - strlcpy(Settings.syslog_host, (SC_DEFAULT == Shortcut(XdrvMailbox.data)) ? SYS_LOG_HOST : XdrvMailbox.data, sizeof(Settings.syslog_host)); + strlcpy(Settings.syslog_host, (SC_DEFAULT == Shortcut()) ? SYS_LOG_HOST : XdrvMailbox.data, sizeof(Settings.syslog_host)); } Response_P(S_JSON_COMMAND_SVALUE, XdrvMailbox.command, Settings.syslog_host); } @@ -978,7 +978,7 @@ void CmndNtpServer(void) if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 3)) { if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.ntp_server[0]))) { strlcpy(Settings.ntp_server[XdrvMailbox.index -1], - (SC_CLEAR == Shortcut(XdrvMailbox.data)) ? "" : (SC_DEFAULT == Shortcut(XdrvMailbox.data)) ? (1==XdrvMailbox.index)?NTP_SERVER1:(2==XdrvMailbox.index)?NTP_SERVER2:NTP_SERVER3 : XdrvMailbox.data, + (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1==XdrvMailbox.index)?NTP_SERVER1:(2==XdrvMailbox.index)?NTP_SERVER2:NTP_SERVER3 : XdrvMailbox.data, sizeof(Settings.ntp_server[0])); for (uint32_t i = 0; i < strlen(Settings.ntp_server[XdrvMailbox.index -1]); i++) { if (Settings.ntp_server[XdrvMailbox.index -1][i] == ',') Settings.ntp_server[XdrvMailbox.index -1][i] = '.'; @@ -1011,7 +1011,7 @@ void CmndSsid(void) if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.sta_ssid[0]))) { strlcpy(Settings.sta_ssid[XdrvMailbox.index -1], - (SC_CLEAR == Shortcut(XdrvMailbox.data)) ? "" : (SC_DEFAULT == Shortcut(XdrvMailbox.data)) ? (1 == XdrvMailbox.index) ? STA_SSID1 : STA_SSID2 : XdrvMailbox.data, + (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? STA_SSID1 : STA_SSID2 : XdrvMailbox.data, sizeof(Settings.sta_ssid[0])); Settings.sta_active = XdrvMailbox.index -1; restart_flag = 2; @@ -1023,9 +1023,9 @@ void CmndSsid(void) void CmndPassword(void) { if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { - if ((XdrvMailbox.data_len > 4 || SC_CLEAR == Shortcut(XdrvMailbox.data) || SC_DEFAULT == Shortcut(XdrvMailbox.data)) && (XdrvMailbox.data_len < sizeof(Settings.sta_pwd[0]))) { + if ((XdrvMailbox.data_len > 4 || SC_CLEAR == Shortcut() || SC_DEFAULT == Shortcut()) && (XdrvMailbox.data_len < sizeof(Settings.sta_pwd[0]))) { strlcpy(Settings.sta_pwd[XdrvMailbox.index -1], - (SC_CLEAR == Shortcut(XdrvMailbox.data)) ? "" : (SC_DEFAULT == Shortcut(XdrvMailbox.data)) ? (1 == XdrvMailbox.index) ? STA_PASS1 : STA_PASS2 : XdrvMailbox.data, + (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? STA_PASS1 : STA_PASS2 : XdrvMailbox.data, sizeof(Settings.sta_pwd[0])); Settings.sta_active = XdrvMailbox.index -1; restart_flag = 2; @@ -1039,7 +1039,7 @@ void CmndPassword(void) void CmndHostname(void) { if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.hostname))) { - strlcpy(Settings.hostname, (SC_DEFAULT == Shortcut(XdrvMailbox.data)) ? WIFI_HOSTNAME : XdrvMailbox.data, sizeof(Settings.hostname)); + strlcpy(Settings.hostname, (SC_DEFAULT == Shortcut()) ? WIFI_HOSTNAME : XdrvMailbox.data, sizeof(Settings.hostname)); if (strstr(Settings.hostname, "%") != nullptr) { strlcpy(Settings.hostname, WIFI_HOSTNAME, sizeof(Settings.hostname)); } @@ -1076,7 +1076,7 @@ void CmndFriendlyname(void) } else { snprintf_P(stemp1, sizeof(stemp1), PSTR(FRIENDLY_NAME "%d"), XdrvMailbox.index); } - strlcpy(Settings.friendlyname[XdrvMailbox.index -1], (SC_DEFAULT == Shortcut(XdrvMailbox.data)) ? stemp1 : XdrvMailbox.data, sizeof(Settings.friendlyname[XdrvMailbox.index -1])); + strlcpy(Settings.friendlyname[XdrvMailbox.index -1], (SC_DEFAULT == Shortcut()) ? stemp1 : XdrvMailbox.data, sizeof(Settings.friendlyname[XdrvMailbox.index -1])); } Response_P(S_JSON_COMMAND_INDEX_SVALUE, XdrvMailbox.command, XdrvMailbox.index, Settings.friendlyname[XdrvMailbox.index -1]); } diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 99dd96558..119a26ba7 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -2479,7 +2479,7 @@ bool WebCommand(void) } else if (CMND_WEBPASSWORD == command_code) { if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.web_password))) { - strlcpy(Settings.web_password, (SC_CLEAR == Shortcut(XdrvMailbox.data)) ? "" : (SC_DEFAULT == Shortcut(XdrvMailbox.data)) ? WEB_PASSWORD : XdrvMailbox.data, sizeof(Settings.web_password)); + strlcpy(Settings.web_password, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? WEB_PASSWORD : XdrvMailbox.data, sizeof(Settings.web_password)); Response_P(S_JSON_COMMAND_SVALUE, command, Settings.web_password); } else { Response_P(S_JSON_COMMAND_ASTERISK, command); diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 14875abd8..445a81191 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -26,14 +26,26 @@ WiFiClient EspClient; // Wifi Client #endif -enum MqttCommands { - CMND_MQTTHOST, CMND_MQTTPORT, CMND_MQTTRETRY, CMND_STATETEXT, CMND_MQTTFINGERPRINT, CMND_MQTTCLIENT, - CMND_MQTTUSER, CMND_MQTTPASSWORD, CMND_FULLTOPIC, CMND_PREFIX, CMND_GROUPTOPIC, CMND_TOPIC, CMND_PUBLISH, - CMND_BUTTONTOPIC, CMND_SWITCHTOPIC, CMND_BUTTONRETAIN, CMND_SWITCHRETAIN, CMND_POWERRETAIN, CMND_SENSORRETAIN }; const char kMqttCommands[] PROGMEM = - D_CMND_MQTTHOST "|" D_CMND_MQTTPORT "|" D_CMND_MQTTRETRY "|" D_CMND_STATETEXT "|" D_CMND_MQTTFINGERPRINT "|" D_CMND_MQTTCLIENT "|" - D_CMND_MQTTUSER "|" D_CMND_MQTTPASSWORD "|" D_CMND_FULLTOPIC "|" D_CMND_PREFIX "|" D_CMND_GROUPTOPIC "|" D_CMND_TOPIC "|" D_CMND_PUBLISH "|" +#if defined(USE_MQTT_TLS) && !defined(USE_MQTT_TLS_CA_CERT) + D_CMND_MQTTFINGERPRINT "|" +#endif +#if !defined(USE_MQTT_TLS) || !defined(USE_MQTT_AWS_IOT) // user and password are disabled with AWS IoT + D_CMND_MQTTUSER "|" D_CMND_MQTTPASSWORD "|" +#endif + D_CMND_MQTTHOST "|" D_CMND_MQTTPORT "|" D_CMND_MQTTRETRY "|" D_CMND_STATETEXT "|" D_CMND_MQTTCLIENT "|" + D_CMND_FULLTOPIC "|" D_CMND_PREFIX "|" D_CMND_GROUPTOPIC "|" D_CMND_TOPIC "|" D_CMND_PUBLISH "|" D_CMND_BUTTONTOPIC "|" D_CMND_SWITCHTOPIC "|" D_CMND_BUTTONRETAIN "|" D_CMND_SWITCHRETAIN "|" D_CMND_POWERRETAIN "|" D_CMND_SENSORRETAIN ; +void (* const MqttCommand[])(void) PROGMEM = { +#if defined(USE_MQTT_TLS) && !defined(USE_MQTT_TLS_CA_CERT) + &CmndMqttFingerprint, +#endif +#if !defined(USE_MQTT_TLS) || !defined(USE_MQTT_AWS_IOT) // user and password are disabled with AWS IoT + &CmndMqttUser, &CmndMqttPassword, +#endif + &CmndMqttHost, &CmndMqttPort, &CmndMqttRetry, &CmndStateText, &CmndMqttClient, + &CmndFullTopic, &CmndPrefix, &CmndGroupTopic, &CmndTopic, &CmndPublish, + &CmndButtonTopic, &CmndSwitchTopic, &CmndButtonRetain, &CmndSwitchRetain, &CmndPowerRetain, &CmndSensorRetain }; IPAddress mqtt_host_addr; // MQTT host IP address uint32_t mqtt_host_hash = 0; // MQTT host name hash @@ -45,8 +57,6 @@ bool mqtt_connected = false; // MQTT virtual connection status bool mqtt_allowed = false; // MQTT enabled and parameters valid #ifdef USE_MQTT_TLS - - // see https://stackoverflow.com/questions/6357031/how-do-you-convert-a-byte-array-to-a-hexadecimal-string-in-c void to_hex(unsigned char * in, size_t insz, char * out, size_t outsz) { unsigned char * pin = in; @@ -90,8 +100,73 @@ bool is_fingerprint_mono_value(uint8_t finger[20], uint8_t value) { return true; } +#ifdef USE_MQTT_AWS_IOT +void setLongMqttHost(const char *mqtt_host) { + if (strlen(mqtt_host) <= sizeof(Settings.mqtt_host)) { + strlcpy(Settings.mqtt_host, mqtt_host, sizeof(Settings.mqtt_host)); + Settings.mqtt_user[0] = 0; + } else { + // need to split in mqtt_user first then mqtt_host + strlcpy(Settings.mqtt_user, mqtt_host, sizeof(Settings.mqtt_user)); + strlcpy(Settings.mqtt_host, &mqtt_host[sizeof(Settings.mqtt_user)-1], sizeof(Settings.mqtt_host)); + } + strlcpy(AWS_endpoint, mqtt_host, sizeof(AWS_endpoint)); +} +#endif // USE_MQTT_AWS_IOT + #endif // USE_MQTT_TLS +void MakeValidMqtt(uint32_t option, char* str) +{ +// option 0 = replace by underscore +// option 1 = delete character + uint32_t i = 0; + while (str[i] > 0) { +// if ((str[i] == '/') || (str[i] == '+') || (str[i] == '#') || (str[i] == ' ')) { + if ((str[i] == '+') || (str[i] == '#') || (str[i] == ' ')) { + if (option) { + uint32_t j = i; + while (str[j] > 0) { + str[j] = str[j +1]; + j++; + } + i--; + } else { + str[i] = '_'; + } + } + i++; + } +} + +#ifdef USE_DISCOVERY +#ifdef MQTT_HOST_DISCOVERY +void MqttDiscoverServer(void) +{ + if (!mdns_begun) { return; } + + int n = MDNS.queryService("mqtt", "tcp"); // Search for mqtt service + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS D_QUERY_DONE " %d"), n); + + if (n > 0) { + uint32_t i = 0; // If the hostname isn't set, use the first record found. +#ifdef MDNS_HOSTNAME + for (i = n; i > 0; i--) { // Search from last to first and use first if not found + if (!strcmp(MDNS.hostname(i).c_str(), MDNS_HOSTNAME)) { + break; // Stop at matching record + } + } +#endif // MDNS_HOSTNAME + snprintf_P(Settings.mqtt_host, sizeof(Settings.mqtt_host), MDNS.IP(i).toString().c_str()); + Settings.mqtt_port = MDNS.port(i); + + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS D_MQTT_SERVICE_FOUND " %s, " D_IP_ADDRESS " %s, " D_PORT " %d"), MDNS.hostname(i).c_str(), Settings.mqtt_host, Settings.mqtt_port); + } +} +#endif // MQTT_HOST_DISCOVERY +#endif // USE_DISCOVERY + /*********************************************************************************************\ * MQTT driver specific code need to provide the following functions: * @@ -114,8 +189,8 @@ PubSubClient MqttClient; PubSubClient MqttClient(EspClient); #endif - -void MqttInit(void) { +void MqttInit(void) +{ #ifdef USE_MQTT_TLS tlsClient = new BearSSL::WiFiClientSecure_light(1024,1024); @@ -139,7 +214,6 @@ void MqttInit(void) { #endif // USE_MQTT_TLS } - bool MqttIsConnected(void) { return MqttClient.connected(); @@ -206,34 +280,6 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) /*********************************************************************************************/ -#ifdef USE_DISCOVERY -#ifdef MQTT_HOST_DISCOVERY -void MqttDiscoverServer(void) -{ - if (!mdns_begun) { return; } - - int n = MDNS.queryService("mqtt", "tcp"); // Search for mqtt service - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS D_QUERY_DONE " %d"), n); - - if (n > 0) { - uint32_t i = 0; // If the hostname isn't set, use the first record found. -#ifdef MDNS_HOSTNAME - for (i = n; i > 0; i--) { // Search from last to first and use first if not found - if (!strcmp(MDNS.hostname(i).c_str(), MDNS_HOSTNAME)) { - break; // Stop at matching record - } - } -#endif // MDNS_HOSTNAME - snprintf_P(Settings.mqtt_host, sizeof(Settings.mqtt_host), MDNS.IP(i).toString().c_str()); - Settings.mqtt_port = MDNS.port(i); - - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MDNS D_MQTT_SERVICE_FOUND " %s, " D_IP_ADDRESS " %s, " D_PORT " %d"), MDNS.hostname(i).c_str(), Settings.mqtt_host, Settings.mqtt_port); - } -} -#endif // MQTT_HOST_DISCOVERY -#endif // USE_DISCOVERY - void MqttRetryCounter(uint8_t value) { mqtt_retry_counter = value; @@ -311,7 +357,7 @@ void MqttPublish(const char* topic) MqttPublish(topic, false); } -void MqttPublishPrefixTopic_P(uint8_t prefix, const char* subtopic, bool retained) +void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic, bool retained) { /* prefix 0 = cmnd using subtopic * prefix 1 = stat using subtopic @@ -332,12 +378,12 @@ void MqttPublishPrefixTopic_P(uint8_t prefix, const char* subtopic, bool retaine MqttPublish(stopic, retained); } -void MqttPublishPrefixTopic_P(uint8_t prefix, const char* subtopic) +void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic) { MqttPublishPrefixTopic_P(prefix, subtopic, false); } -void MqttPublishPowerState(uint8_t device) +void MqttPublishPowerState(uint32_t device) { char stopic[TOPSZ]; char scommand[33]; @@ -380,7 +426,7 @@ void MqttPublishAllPowerState() } } -void MqttPublishPowerBlinkState(uint8_t device) +void MqttPublishPowerBlinkState(uint32_t device) { char scommand[33]; @@ -518,7 +564,6 @@ void MqttReconnect(void) #endif if (2 == mqtt_initial_connection_state) { // Executed once just after power on and wifi is connected - mqtt_initial_connection_state = 1; } @@ -617,259 +662,273 @@ void MqttCheck(void) } } -/*********************************************************************************************/ +/*********************************************************************************************\ + * Commands +\*********************************************************************************************/ -#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) -void setLongMqttHost(const char *mqtt_host) { - if (strlen(mqtt_host) <= sizeof(Settings.mqtt_host)) { - strlcpy(Settings.mqtt_host, mqtt_host, sizeof(Settings.mqtt_host)); - Settings.mqtt_user[0] = 0; - } else { - // need to split in mqtt_user first then mqtt_host - strlcpy(Settings.mqtt_user, mqtt_host, sizeof(Settings.mqtt_user)); - strlcpy(Settings.mqtt_host, &mqtt_host[sizeof(Settings.mqtt_user)-1], sizeof(Settings.mqtt_host)); - } - strlcpy(AWS_endpoint, mqtt_host, sizeof(AWS_endpoint)); -} -#endif // USE_MQTT_AWS_IOT - -bool MqttCommand(void) -{ - char command [CMDSZ]; - bool serviced = true; - char stemp1[TOPSZ]; - char scommand[CMDSZ]; - - uint32_t index = XdrvMailbox.index; - uint32_t data_len = XdrvMailbox.data_len; - int32_t payload = XdrvMailbox.payload; - bool grpflg = XdrvMailbox.grpflg; - char *type = XdrvMailbox.topic; - char *dataBuf = XdrvMailbox.data; - - int command_code = GetCommandCode(command, sizeof(command), type, kMqttCommands); - if (-1 == command_code) { - serviced = false; // Unknown command - } - else if (CMND_MQTTHOST == command_code) { -#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) - if ((data_len > 0) && (data_len <= sizeof(Settings.mqtt_host) + sizeof(Settings.mqtt_user) - 2)) { - setLongMqttHost((SC_CLEAR == Shortcut(dataBuf)) ? "" : (SC_DEFAULT == Shortcut(dataBuf)) ? MQTT_HOST : dataBuf); - restart_flag = 2; - } - Response_P(S_JSON_COMMAND_SVALUE, command, AWS_endpoint); -#else - if ((data_len > 0) && (data_len < sizeof(Settings.mqtt_host))) { - strlcpy(Settings.mqtt_host, (SC_CLEAR == Shortcut(dataBuf)) ? "" : (SC_DEFAULT == Shortcut(dataBuf)) ? MQTT_HOST : dataBuf, sizeof(Settings.mqtt_host)); - restart_flag = 2; - } - Response_P(S_JSON_COMMAND_SVALUE, command, Settings.mqtt_host); -#endif - } - else if (CMND_MQTTPORT == command_code) { - if ((payload > 0) && (payload < 65536)) { - Settings.mqtt_port = (1 == payload) ? MQTT_PORT : payload; - restart_flag = 2; - } - Response_P(S_JSON_COMMAND_NVALUE, command, Settings.mqtt_port); - } - else if (CMND_MQTTRETRY == command_code) { - if ((payload >= MQTT_RETRY_SECS) && (payload < 32001)) { - Settings.mqtt_retry = payload; - mqtt_retry_counter = Settings.mqtt_retry; - } - Response_P(S_JSON_COMMAND_NVALUE, command, Settings.mqtt_retry); - } - else if ((CMND_STATETEXT == command_code) && (index > 0) && (index <= 4)) { - if ((data_len > 0) && (data_len < sizeof(Settings.state_text[0]))) { - for (uint32_t i = 0; i <= data_len; i++) { - if (dataBuf[i] == ' ') dataBuf[i] = '_'; - } - strlcpy(Settings.state_text[index -1], dataBuf, sizeof(Settings.state_text[0])); - } - Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, GetStateText(index -1)); - } #if defined(USE_MQTT_TLS) && !defined(USE_MQTT_TLS_CA_CERT) - else if ((CMND_MQTTFINGERPRINT == command_code) && (index > 0) && (index <= 2)) { +void CmndMqttFingerprint(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { char fingerprint[60]; - if ((data_len > 0) && (data_len < sizeof(fingerprint))) { - strlcpy(fingerprint, (SC_CLEAR == Shortcut(dataBuf)) ? "" : (SC_DEFAULT == Shortcut(dataBuf)) ? (1 == index) ? MQTT_FINGERPRINT1 : MQTT_FINGERPRINT2 : dataBuf, sizeof(fingerprint)); + if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(fingerprint))) { + strlcpy(fingerprint, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? MQTT_FINGERPRINT1 : MQTT_FINGERPRINT2 : XdrvMailbox.data, sizeof(fingerprint)); char *p = fingerprint; for (uint32_t i = 0; i < 20; i++) { - Settings.mqtt_fingerprint[index -1][i] = strtol(p, &p, 16); + Settings.mqtt_fingerprint[XdrvMailbox.index -1][i] = strtol(p, &p, 16); } restart_flag = 2; } fingerprint[0] = '\0'; - for (uint32_t i = 0; i < sizeof(Settings.mqtt_fingerprint[index -1]); i++) { - snprintf_P(fingerprint, sizeof(fingerprint), PSTR("%s%s%02X"), fingerprint, (i) ? " " : "", Settings.mqtt_fingerprint[index -1][i]); + for (uint32_t i = 0; i < sizeof(Settings.mqtt_fingerprint[XdrvMailbox.index -1]); i++) { + snprintf_P(fingerprint, sizeof(fingerprint), PSTR("%s%s%02X"), fingerprint, (i) ? " " : "", Settings.mqtt_fingerprint[XdrvMailbox.index -1][i]); } - Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, fingerprint); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, XdrvMailbox.command, XdrvMailbox.index, fingerprint); } +} #endif - else if (CMND_MQTTCLIENT == command_code) { - if (!grpflg && (data_len > 0) && (data_len < sizeof(Settings.mqtt_client))) { - strlcpy(Settings.mqtt_client, (SC_DEFAULT == Shortcut(dataBuf)) ? MQTT_CLIENT_ID : dataBuf, sizeof(Settings.mqtt_client)); - restart_flag = 2; - } - Response_P(S_JSON_COMMAND_SVALUE, command, Settings.mqtt_client); - } -#if !defined(USE_MQTT_TLS) || !defined(USE_MQTT_AWS_IOT) // user and password are disabled with AWS IoT - else if (CMND_MQTTUSER == command_code) { - if ((data_len > 0) && (data_len < sizeof(Settings.mqtt_user))) { - strlcpy(Settings.mqtt_user, (SC_CLEAR == Shortcut(dataBuf)) ? "" : (SC_DEFAULT == Shortcut(dataBuf)) ? MQTT_USER : dataBuf, sizeof(Settings.mqtt_user)); - restart_flag = 2; - } - Response_P(S_JSON_COMMAND_SVALUE, command, Settings.mqtt_user); - } - else if (CMND_MQTTPASSWORD == command_code) { - if ((data_len > 0) && (data_len < sizeof(Settings.mqtt_pwd))) { - strlcpy(Settings.mqtt_pwd, (SC_CLEAR == Shortcut(dataBuf)) ? "" : (SC_DEFAULT == Shortcut(dataBuf)) ? MQTT_PASS : dataBuf, sizeof(Settings.mqtt_pwd)); - Response_P(S_JSON_COMMAND_SVALUE, command, Settings.mqtt_pwd); - restart_flag = 2; - } else { - Response_P(S_JSON_COMMAND_ASTERISK, command); - } - } -#endif // USE_MQTT_AWS_IOT - else if (CMND_FULLTOPIC == command_code) { - if ((data_len > 0) && (data_len < sizeof(Settings.mqtt_fulltopic))) { - MakeValidMqtt(1, dataBuf); - if (!strcmp(dataBuf, mqtt_client)) SetShortcut(dataBuf, SC_DEFAULT); - strlcpy(stemp1, (SC_DEFAULT == Shortcut(dataBuf)) ? MQTT_FULLTOPIC : dataBuf, sizeof(stemp1)); - if (strcmp(stemp1, Settings.mqtt_fulltopic)) { - Response_P((Settings.flag.mqtt_offline) ? S_OFFLINE : ""); - MqttPublishPrefixTopic_P(TELE, PSTR(D_LWT), true); // Offline or remove previous retained topic - strlcpy(Settings.mqtt_fulltopic, stemp1, sizeof(Settings.mqtt_fulltopic)); - restart_flag = 2; - } - } - Response_P(S_JSON_COMMAND_SVALUE, command, Settings.mqtt_fulltopic); - } - else if ((CMND_PREFIX == command_code) && (index > 0) && (index <= 3)) { - if ((data_len > 0) && (data_len < sizeof(Settings.mqtt_prefix[0]))) { - MakeValidMqtt(0, dataBuf); - strlcpy(Settings.mqtt_prefix[index -1], (SC_DEFAULT == Shortcut(dataBuf)) ? (1==index)?SUB_PREFIX:(2==index)?PUB_PREFIX:PUB_PREFIX2 : dataBuf, sizeof(Settings.mqtt_prefix[0])); -// if (Settings.mqtt_prefix[index -1][strlen(Settings.mqtt_prefix[index -1])] == '/') Settings.mqtt_prefix[index -1][strlen(Settings.mqtt_prefix[index -1])] = 0; - restart_flag = 2; - } - Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.mqtt_prefix[index -1]); - } - else if (CMND_PUBLISH == command_code) { - if (data_len > 0) { - char *mqtt_part = strtok(dataBuf, " "); - if (mqtt_part) { - strlcpy(stemp1, mqtt_part, sizeof(stemp1)); - mqtt_part = strtok(nullptr, " "); - if (mqtt_part) { - strlcpy(mqtt_data, mqtt_part, sizeof(mqtt_data)); - } else { - mqtt_data[0] = '\0'; - } - MqttPublishDirect(stemp1, (index == 2)); -// Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); - mqtt_data[0] = '\0'; - } - } - } - else if (CMND_GROUPTOPIC == command_code) { - if ((data_len > 0) && (data_len < sizeof(Settings.mqtt_grptopic))) { - MakeValidMqtt(0, dataBuf); - if (!strcmp(dataBuf, mqtt_client)) SetShortcut(dataBuf, SC_DEFAULT); - strlcpy(Settings.mqtt_grptopic, (SC_DEFAULT == Shortcut(dataBuf)) ? MQTT_GRPTOPIC : dataBuf, sizeof(Settings.mqtt_grptopic)); - restart_flag = 2; - } - Response_P(S_JSON_COMMAND_SVALUE, command, Settings.mqtt_grptopic); - } - else if (CMND_TOPIC == command_code) { - if (!grpflg && (data_len > 0) && (data_len < sizeof(Settings.mqtt_topic))) { - MakeValidMqtt(0, dataBuf); - if (!strcmp(dataBuf, mqtt_client)) SetShortcut(dataBuf, SC_DEFAULT); - strlcpy(stemp1, (SC_DEFAULT == Shortcut(dataBuf)) ? MQTT_TOPIC : dataBuf, sizeof(stemp1)); - if (strcmp(stemp1, Settings.mqtt_topic)) { - Response_P((Settings.flag.mqtt_offline) ? S_OFFLINE : ""); - MqttPublishPrefixTopic_P(TELE, PSTR(D_LWT), true); // Offline or remove previous retained topic - strlcpy(Settings.mqtt_topic, stemp1, sizeof(Settings.mqtt_topic)); - restart_flag = 2; - } - } - Response_P(S_JSON_COMMAND_SVALUE, command, Settings.mqtt_topic); - } - else if (CMND_BUTTONTOPIC == command_code) { - if (!grpflg && (data_len > 0) && (data_len < sizeof(Settings.button_topic))) { - MakeValidMqtt(0, dataBuf); - if (!strcmp(dataBuf, mqtt_client)) SetShortcut(dataBuf, SC_DEFAULT); - switch (Shortcut(dataBuf)) { - case SC_CLEAR: strlcpy(Settings.button_topic, "", sizeof(Settings.button_topic)); break; - case SC_DEFAULT: strlcpy(Settings.button_topic, mqtt_topic, sizeof(Settings.button_topic)); break; - case SC_USER: strlcpy(Settings.button_topic, MQTT_BUTTON_TOPIC, sizeof(Settings.button_topic)); break; - default: strlcpy(Settings.button_topic, dataBuf, sizeof(Settings.button_topic)); - } - } - Response_P(S_JSON_COMMAND_SVALUE, command, Settings.button_topic); - } - else if (CMND_SWITCHTOPIC == command_code) { - if ((data_len > 0) && (data_len < sizeof(Settings.switch_topic))) { - MakeValidMqtt(0, dataBuf); - if (!strcmp(dataBuf, mqtt_client)) SetShortcut(dataBuf, SC_DEFAULT); - switch (Shortcut(dataBuf)) { - case SC_CLEAR: strlcpy(Settings.switch_topic, "", sizeof(Settings.switch_topic)); break; - case SC_DEFAULT: strlcpy(Settings.switch_topic, mqtt_topic, sizeof(Settings.switch_topic)); break; - case SC_USER: strlcpy(Settings.switch_topic, MQTT_SWITCH_TOPIC, sizeof(Settings.switch_topic)); break; - default: strlcpy(Settings.switch_topic, dataBuf, sizeof(Settings.switch_topic)); - } - } - Response_P(S_JSON_COMMAND_SVALUE, command, Settings.switch_topic); - } - else if (CMND_BUTTONRETAIN == command_code) { - if ((payload >= 0) && (payload <= 1)) { - if (!payload) { - for (uint32_t i = 1; i <= MAX_KEYS; i++) { - SendKey(0, i, 9); // Clear MQTT retain in broker - } - } - Settings.flag.mqtt_button_retain = payload; - } - Response_P(S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.mqtt_button_retain)); - } - else if (CMND_SWITCHRETAIN == command_code) { - if ((payload >= 0) && (payload <= 1)) { - if (!payload) { - for (uint32_t i = 1; i <= MAX_SWITCHES; i++) { - SendKey(1, i, 9); // Clear MQTT retain in broker - } - } - Settings.flag.mqtt_switch_retain = payload; - } - Response_P(S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.mqtt_switch_retain)); - } - else if (CMND_POWERRETAIN == command_code) { - if ((payload >= 0) && (payload <= 1)) { - if (!payload) { - for (uint32_t i = 1; i <= devices_present; i++) { // Clear MQTT retain in broker - GetTopic_P(stemp1, STAT, mqtt_topic, GetPowerDevice(scommand, i, sizeof(scommand), Settings.flag.device_index_enable)); - mqtt_data[0] = '\0'; - MqttPublish(stemp1, Settings.flag.mqtt_power_retain); - } - } - Settings.flag.mqtt_power_retain = payload; - } - Response_P(S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.mqtt_power_retain)); - } - else if (CMND_SENSORRETAIN == command_code) { - if ((payload >= 0) && (payload <= 1)) { - if (!payload) { - mqtt_data[0] = '\0'; - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); - MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_ENERGY), Settings.flag.mqtt_sensor_retain); - } - Settings.flag.mqtt_sensor_retain = payload; - } - Response_P(S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.mqtt_sensor_retain)); - } - else serviced = false; // Unknown command - return serviced; +#if !defined(USE_MQTT_TLS) || !defined(USE_MQTT_AWS_IOT) // user and password are disabled with AWS IoT +void CmndMqttUser(void) +{ + if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_user))) { + strlcpy(Settings.mqtt_user, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_USER : XdrvMailbox.data, sizeof(Settings.mqtt_user)); + restart_flag = 2; + } + Response_P(S_JSON_COMMAND_SVALUE, XdrvMailbox.command, Settings.mqtt_user); +} + +void CmndMqttPassword(void) +{ + if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_pwd))) { + strlcpy(Settings.mqtt_pwd, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_PASS : XdrvMailbox.data, sizeof(Settings.mqtt_pwd)); + Response_P(S_JSON_COMMAND_SVALUE, XdrvMailbox.command, Settings.mqtt_pwd); + restart_flag = 2; + } else { + Response_P(S_JSON_COMMAND_ASTERISK, XdrvMailbox.command); + } +} +#endif // USE_MQTT_AWS_IOT + +void CmndMqttHost(void) +{ +#if defined(USE_MQTT_TLS) && defined(USE_MQTT_AWS_IOT) + if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len <= sizeof(Settings.mqtt_host) + sizeof(Settings.mqtt_user) - 2)) { + setLongMqttHost((SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_HOST : XdrvMailbox.data); + restart_flag = 2; + } + Response_P(S_JSON_COMMAND_SVALUE, XdrvMailbox.command, AWS_endpoint); +#else + if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_host))) { + strlcpy(Settings.mqtt_host, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? MQTT_HOST : XdrvMailbox.data, sizeof(Settings.mqtt_host)); + restart_flag = 2; + } + Response_P(S_JSON_COMMAND_SVALUE, XdrvMailbox.command, Settings.mqtt_host); +#endif +} + +void CmndMqttPort(void) +{ + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 65536)) { + Settings.mqtt_port = (1 == XdrvMailbox.payload) ? MQTT_PORT : XdrvMailbox.payload; + restart_flag = 2; + } + Response_P(S_JSON_COMMAND_NVALUE, XdrvMailbox.command, Settings.mqtt_port); +} + +void CmndMqttRetry(void) +{ + if ((XdrvMailbox.payload >= MQTT_RETRY_SECS) && (XdrvMailbox.payload < 32001)) { + Settings.mqtt_retry = XdrvMailbox.payload; + mqtt_retry_counter = Settings.mqtt_retry; + } + Response_P(S_JSON_COMMAND_NVALUE, XdrvMailbox.command, Settings.mqtt_retry); +} + +void CmndStateText(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 4)) { + if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.state_text[0]))) { + for (uint32_t i = 0; i <= XdrvMailbox.data_len; i++) { + if (XdrvMailbox.data[i] == ' ') XdrvMailbox.data[i] = '_'; + } + strlcpy(Settings.state_text[XdrvMailbox.index -1], XdrvMailbox.data, sizeof(Settings.state_text[0])); + } + Response_P(S_JSON_COMMAND_INDEX_SVALUE, XdrvMailbox.command, XdrvMailbox.index, GetStateText(XdrvMailbox.index -1)); + } +} + +void CmndMqttClient(void) +{ + if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_client))) { + strlcpy(Settings.mqtt_client, (SC_DEFAULT == Shortcut()) ? MQTT_CLIENT_ID : XdrvMailbox.data, sizeof(Settings.mqtt_client)); + restart_flag = 2; + } + Response_P(S_JSON_COMMAND_SVALUE, XdrvMailbox.command, Settings.mqtt_client); +} + +void CmndFullTopic(void) +{ + if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_fulltopic))) { + MakeValidMqtt(1, XdrvMailbox.data); + if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } + char stemp1[TOPSZ]; + strlcpy(stemp1, (SC_DEFAULT == Shortcut()) ? MQTT_FULLTOPIC : XdrvMailbox.data, sizeof(stemp1)); + if (strcmp(stemp1, Settings.mqtt_fulltopic)) { + Response_P((Settings.flag.mqtt_offline) ? S_OFFLINE : ""); + MqttPublishPrefixTopic_P(TELE, PSTR(D_LWT), true); // Offline or remove previous retained topic + strlcpy(Settings.mqtt_fulltopic, stemp1, sizeof(Settings.mqtt_fulltopic)); + restart_flag = 2; + } + } + Response_P(S_JSON_COMMAND_SVALUE, XdrvMailbox.command, Settings.mqtt_fulltopic); +} + +void CmndPrefix(void) +{ + if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= 3)) { + if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_prefix[0]))) { + MakeValidMqtt(0, XdrvMailbox.data); + strlcpy(Settings.mqtt_prefix[XdrvMailbox.index -1], (SC_DEFAULT == Shortcut()) ? (1==XdrvMailbox.index)?SUB_PREFIX:(2==XdrvMailbox.index)?PUB_PREFIX:PUB_PREFIX2 : XdrvMailbox.data, sizeof(Settings.mqtt_prefix[0])); +// if (Settings.mqtt_prefix[XdrvMailbox.index -1][strlen(Settings.mqtt_prefix[XdrvMailbox.index -1])] == '/') Settings.mqtt_prefix[XdrvMailbox.index -1][strlen(Settings.mqtt_prefix[XdrvMailbox.index -1])] = 0; + restart_flag = 2; + } + Response_P(S_JSON_COMMAND_INDEX_SVALUE, XdrvMailbox.command, XdrvMailbox.index, Settings.mqtt_prefix[XdrvMailbox.index -1]); + } +} + +void CmndPublish(void) +{ + if (XdrvMailbox.data_len > 0) { + char *mqtt_part = strtok(XdrvMailbox.data, " "); + if (mqtt_part) { + char stemp1[TOPSZ]; + strlcpy(stemp1, mqtt_part, sizeof(stemp1)); + mqtt_part = strtok(nullptr, " "); + if (mqtt_part) { + strlcpy(mqtt_data, mqtt_part, sizeof(mqtt_data)); + } else { + mqtt_data[0] = '\0'; + } + MqttPublishDirect(stemp1, (XdrvMailbox.index == 2)); +// Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); + mqtt_data[0] = '\0'; + } + } +} + +void CmndGroupTopic(void) +{ + if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_grptopic))) { + MakeValidMqtt(0, XdrvMailbox.data); + if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } + strlcpy(Settings.mqtt_grptopic, (SC_DEFAULT == Shortcut()) ? MQTT_GRPTOPIC : XdrvMailbox.data, sizeof(Settings.mqtt_grptopic)); + restart_flag = 2; + } + Response_P(S_JSON_COMMAND_SVALUE, XdrvMailbox.command, Settings.mqtt_grptopic); +} + +void CmndTopic(void) +{ + if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.mqtt_topic))) { + MakeValidMqtt(0, XdrvMailbox.data); + if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } + char stemp1[TOPSZ]; + strlcpy(stemp1, (SC_DEFAULT == Shortcut()) ? MQTT_TOPIC : XdrvMailbox.data, sizeof(stemp1)); + if (strcmp(stemp1, Settings.mqtt_topic)) { + Response_P((Settings.flag.mqtt_offline) ? S_OFFLINE : ""); + MqttPublishPrefixTopic_P(TELE, PSTR(D_LWT), true); // Offline or remove previous retained topic + strlcpy(Settings.mqtt_topic, stemp1, sizeof(Settings.mqtt_topic)); + restart_flag = 2; + } + } + Response_P(S_JSON_COMMAND_SVALUE, XdrvMailbox.command, Settings.mqtt_topic); +} + +void CmndButtonTopic(void) +{ + if (!XdrvMailbox.grpflg && (XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.button_topic))) { + MakeValidMqtt(0, XdrvMailbox.data); + if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } + switch (Shortcut()) { + case SC_CLEAR: strlcpy(Settings.button_topic, "", sizeof(Settings.button_topic)); break; + case SC_DEFAULT: strlcpy(Settings.button_topic, mqtt_topic, sizeof(Settings.button_topic)); break; + case SC_USER: strlcpy(Settings.button_topic, MQTT_BUTTON_TOPIC, sizeof(Settings.button_topic)); break; + default: strlcpy(Settings.button_topic, XdrvMailbox.data, sizeof(Settings.button_topic)); + } + } + Response_P(S_JSON_COMMAND_SVALUE, XdrvMailbox.command, Settings.button_topic); +} + +void CmndSwitchTopic(void) +{ + if ((XdrvMailbox.data_len > 0) && (XdrvMailbox.data_len < sizeof(Settings.switch_topic))) { + MakeValidMqtt(0, XdrvMailbox.data); + if (!strcmp(XdrvMailbox.data, mqtt_client)) { SetShortcutDefault(); } + switch (Shortcut()) { + case SC_CLEAR: strlcpy(Settings.switch_topic, "", sizeof(Settings.switch_topic)); break; + case SC_DEFAULT: strlcpy(Settings.switch_topic, mqtt_topic, sizeof(Settings.switch_topic)); break; + case SC_USER: strlcpy(Settings.switch_topic, MQTT_SWITCH_TOPIC, sizeof(Settings.switch_topic)); break; + default: strlcpy(Settings.switch_topic, XdrvMailbox.data, sizeof(Settings.switch_topic)); + } + } + Response_P(S_JSON_COMMAND_SVALUE, XdrvMailbox.command, Settings.switch_topic); +} + +void CmndButtonRetain(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { + if (!XdrvMailbox.payload) { + for (uint32_t i = 1; i <= MAX_KEYS; i++) { + SendKey(0, i, 9); // Clear MQTT retain in broker + } + } + Settings.flag.mqtt_button_retain = XdrvMailbox.payload; + } + Response_P(S_JSON_COMMAND_SVALUE, XdrvMailbox.command, GetStateText(Settings.flag.mqtt_button_retain)); +} + +void CmndSwitchRetain(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { + if (!XdrvMailbox.payload) { + for (uint32_t i = 1; i <= MAX_SWITCHES; i++) { + SendKey(1, i, 9); // Clear MQTT retain in broker + } + } + Settings.flag.mqtt_switch_retain = XdrvMailbox.payload; + } + Response_P(S_JSON_COMMAND_SVALUE, XdrvMailbox.command, GetStateText(Settings.flag.mqtt_switch_retain)); +} + +void CmndPowerRetain(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { + if (!XdrvMailbox.payload) { + char stemp1[TOPSZ]; + char scommand[CMDSZ]; + for (uint32_t i = 1; i <= devices_present; i++) { // Clear MQTT retain in broker + GetTopic_P(stemp1, STAT, mqtt_topic, GetPowerDevice(scommand, i, sizeof(scommand), Settings.flag.device_index_enable)); + mqtt_data[0] = '\0'; + MqttPublish(stemp1, Settings.flag.mqtt_power_retain); + } + } + Settings.flag.mqtt_power_retain = XdrvMailbox.payload; + } + Response_P(S_JSON_COMMAND_SVALUE, XdrvMailbox.command, GetStateText(Settings.flag.mqtt_power_retain)); +} + +void CmndSensorRetain(void) +{ + if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 1)) { + if (!XdrvMailbox.payload) { + mqtt_data[0] = '\0'; + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); + MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_ENERGY), Settings.flag.mqtt_sensor_retain); + } + Settings.flag.mqtt_sensor_retain = XdrvMailbox.payload; + } + Response_P(S_JSON_COMMAND_SVALUE, XdrvMailbox.command, GetStateText(Settings.flag.mqtt_sensor_retain)); } /*********************************************************************************************\ @@ -943,7 +1002,7 @@ void MqttSaveSettings(void) MakeValidMqtt(0, stemp); WebGetArg("mf", tmp, sizeof(tmp)); strlcpy(stemp2, (!strlen(tmp)) ? MQTT_FULLTOPIC : tmp, sizeof(stemp2)); - MakeValidMqtt(1,stemp2); + MakeValidMqtt(1, stemp2); if ((strcmp(stemp, Settings.mqtt_topic)) || (strcmp(stemp2, Settings.mqtt_fulltopic))) { Response_P((Settings.flag.mqtt_offline) ? S_OFFLINE : ""); MqttPublishPrefixTopic_P(TELE, S_LWT, true); // Offline or remove previous retained topic @@ -999,7 +1058,11 @@ bool Xdrv02(uint8_t function) break; #endif // USE_WEBSERVER case FUNC_COMMAND: - result = MqttCommand(); + int command_code = GetCommandCode(XdrvMailbox.command, CMDSZ, XdrvMailbox.topic, kMqttCommands); + if (command_code >= 0) { + MqttCommand[command_code](); + result = true; + } break; } }