From 76b7d778ec7692711eebc653fd1bce1e27bec6ea Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 23 Mar 2019 12:41:35 +0100 Subject: [PATCH 01/81] Fix incomplete syslog Fix incomplete syslog when MQTT is disabled (#5512) --- sonoff/support.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/support.ino b/sonoff/support.ino index e6068fb77..dc0396be2 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -1221,6 +1221,7 @@ void Syslog(void) memcpy(log_data, syslog_preamble, strlen(syslog_preamble)); PortUdp.write(log_data); PortUdp.endPacket(); + delay(1); // Add time for UDP handling (#5512) } else { syslog_level = 0; syslog_timer = SYSLOG_TIMER; From 6922e657d9f6b13d0140aefe6a8c52303c8324bf Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 23 Mar 2019 17:00:59 +0100 Subject: [PATCH 02/81] Shrink code/flash space Shrink code/flash space --- sonoff/sonoff.ino | 261 +++++++++++++++--------------- sonoff/support.ino | 32 +++- sonoff/xdrv_01_webserver.ino | 25 ++- sonoff/xdrv_02_mqtt.ino | 65 ++++---- sonoff/xdrv_03_energy.ino | 46 +++--- sonoff/xdrv_04_light.ino | 68 ++++---- sonoff/xdrv_05_irremote.ino | 32 ++-- sonoff/xdrv_06_snfbridge.ino | 32 ++-- sonoff/xdrv_07_domoticz.ino | 24 ++- sonoff/xdrv_08_serial_bridge.ino | 12 +- sonoff/xdrv_09_timers.ino | 28 ++-- sonoff/xdrv_10_rules.ino | 28 ++-- sonoff/xdrv_12_home_assistant.ino | 3 +- sonoff/xdrv_13_display.ino | 28 ++-- sonoff/xdrv_14_mp3.ino | 4 +- sonoff/xdrv_15_pca9685.ino | 20 +-- sonoff/xdrv_17_rcswitch.ino | 6 +- sonoff/xdrv_99_debug.ino | 24 +-- 18 files changed, 380 insertions(+), 358 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 74fbafee5..cf11abcff 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -506,7 +506,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_RESULT D_GROUP " %d, " D_INDEX " %d, " D_COMMAND " %s, " D_DATA " %s"), grpflg, index, type, dataBuf); if (type != NULL) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_ERROR "\"}")); + Response_P(PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_ERROR "\"}")); if (Settings.ledstate &0x02) { blinks++; } if (!strcmp(dataBuf,"?")) { data_len = 0; } @@ -563,12 +563,12 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) } blcommand = strtok(NULL, ";"); } -// snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_APPENDED); +// Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_APPENDED); mqtt_data[0] = '\0'; } else { uint8_t blflag = (backlog_pointer == backlog_index); backlog_pointer = backlog_index; - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, blflag ? D_JSON_EMPTY : D_JSON_ABORTED); + Response_P(S_JSON_COMMAND_SVALUE, command, blflag ? D_JSON_EMPTY : D_JSON_ABORTED); } } else if (CMND_DELAY == command_code) { @@ -578,7 +578,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) uint16_t bl_delay = 0; long bl_delta = TimePassedSince(backlog_delay); if (bl_delta < 0) { bl_delay = (bl_delta *-1) / 100; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, bl_delay); + Response_P(S_JSON_COMMAND_NVALUE, command, bl_delay); } else if ((CMND_POWER == command_code) && (index > 0) && (index <= devices_present)) { if ((payload < 0) || (payload > 4)) { payload = 9; } @@ -601,7 +601,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) if ((payload >= 0) && (payload < MAX_FAN_SPEED) && (payload != GetFanspeed())) { SetFanspeed(payload); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, GetFanspeed()); + Response_P(S_JSON_COMMAND_NVALUE, command, GetFanspeed()); } else if (CMND_STATUS == command_code) { if ((payload < 0) || (payload > MAX_STATUS)) payload = 99; @@ -627,7 +627,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) sleep = payload; WiFiSetSleepMode(); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE_UNIT_NVALUE_UNIT, command, sleep, (Settings.flag.value_units) ? " " D_UNIT_MILLISECOND : "", Settings.sleep, (Settings.flag.value_units) ? " " D_UNIT_MILLISECOND : ""); + Response_P(S_JSON_COMMAND_NVALUE_UNIT_NVALUE_UNIT, command, sleep, (Settings.flag.value_units) ? " " D_UNIT_MILLISECOND : "", Settings.sleep, (Settings.flag.value_units) ? " " D_UNIT_MILLISECOND : ""); } else if ((CMND_UPGRADE == command_code) || (CMND_UPLOAD == command_code)) { // Check if the payload is numerically 1, and had no trailing chars. @@ -636,36 +636,36 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) // We also need at least 3 chars to make a valid version number string. if (((1 == data_len) && (1 == payload)) || ((data_len >= 3) && NewerVersion(dataBuf))) { ota_state_flag = 3; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"" D_JSON_VERSION " %s " D_JSON_FROM " %s\"}"), command, my_version, GetOtaUrl(stemp1, sizeof(stemp1))); + Response_P(PSTR("{\"%s\":\"" D_JSON_VERSION " %s " D_JSON_FROM " %s\"}"), command, my_version, GetOtaUrl(stemp1, sizeof(stemp1))); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"" D_JSON_ONE_OR_GT "\"}"), command, my_version); + Response_P(PSTR("{\"%s\":\"" D_JSON_ONE_OR_GT "\"}"), command, my_version); } } else if (CMND_OTAURL == command_code) { if ((data_len > 0) && (data_len < sizeof(Settings.ota_url))) { strlcpy(Settings.ota_url, (SC_DEFAULT == Shortcut(dataBuf)) ? OTA_URL : dataBuf, sizeof(Settings.ota_url)); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.ota_url); + Response_P(S_JSON_COMMAND_SVALUE, command, Settings.ota_url); } else if (CMND_SERIALLOG == command_code) { if ((payload >= LOG_LEVEL_NONE) && (payload <= LOG_LEVEL_ALL)) { Settings.flag.mqtt_serial = 0; SetSeriallog(payload); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, command, Settings.seriallog_level, seriallog_level); + Response_P(S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, command, Settings.seriallog_level, seriallog_level); } else if (CMND_RESTART == command_code) { switch (payload) { case 1: restart_flag = 2; - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_RESTARTING); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_RESTARTING); break; case 99: AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_RESTARTING)); EspRestart(); break; default: - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_ONE_TO_RESTART); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_ONE_TO_RESTART); } } else if ((CMND_POWERONSTATE == command_code) && (my_module_type != MOTOR)) { @@ -684,28 +684,28 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) } } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.poweronstate); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.poweronstate); } else if ((CMND_PULSETIME == command_code) && (index > 0) && (index <= MAX_PULSETIMERS)) { if (data_len > 0) { Settings.pulse_timer[index -1] = payload16; // 0 - 65535 SetPulseTimer(index -1, payload16); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_NVALUE_ACTIVE_NVALUE, command, index, Settings.pulse_timer[index -1], GetPulseTimer(index -1)); + Response_P(S_JSON_COMMAND_INDEX_NVALUE_ACTIVE_NVALUE, command, index, Settings.pulse_timer[index -1], GetPulseTimer(index -1)); } else if (CMND_BLINKTIME == command_code) { if ((payload > 1) && (payload <= 3600)) { Settings.blinktime = payload; if (blink_timer > 0) { blink_timer = millis() + (100 * payload); } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.blinktime); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.blinktime); } else if (CMND_BLINKCOUNT == command_code) { if (data_len > 0) { Settings.blinkcount = payload16; // 0 - 65535 if (blink_counter) blink_counter = Settings.blinkcount *2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.blinkcount); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.blinkcount); } else if (CMND_SAVEDATA == command_code) { if ((payload >= 0) && (payload <= 3600)) { @@ -716,7 +716,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) if (Settings.save_data > 1) { snprintf_P(stemp1, sizeof(stemp1), PSTR(D_JSON_EVERY " %d " D_UNIT_SECOND), Settings.save_data); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, (Settings.save_data > 1) ? stemp1 : GetStateText(Settings.save_data)); + Response_P(S_JSON_COMMAND_SVALUE, command, (Settings.save_data > 1) ? stemp1 : GetStateText(Settings.save_data)); } else if ((CMND_SENSOR == command_code) || (CMND_DRIVER == command_code)) { XdrvMailbox.index = index; @@ -814,62 +814,62 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) } if (ptype < 99) { if (2 == ptype) snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), Settings.param[pindex]); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, (2 == ptype) ? stemp1 : (1 == ptype) ? GetStateText(bitRead(Settings.flag3.data, pindex)) : GetStateText(bitRead(Settings.flag.data, pindex))); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, (2 == ptype) ? stemp1 : (1 == ptype) ? GetStateText(bitRead(Settings.flag3.data, pindex)) : GetStateText(bitRead(Settings.flag.data, pindex))); } } else if (CMND_TEMPERATURE_RESOLUTION == command_code) { if ((payload >= 0) && (payload <= 3)) { Settings.flag2.temperature_resolution = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag2.temperature_resolution); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.flag2.temperature_resolution); } else if (CMND_HUMIDITY_RESOLUTION == command_code) { if ((payload >= 0) && (payload <= 3)) { Settings.flag2.humidity_resolution = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag2.humidity_resolution); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.flag2.humidity_resolution); } else if (CMND_PRESSURE_RESOLUTION == command_code) { if ((payload >= 0) && (payload <= 3)) { Settings.flag2.pressure_resolution = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag2.pressure_resolution); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.flag2.pressure_resolution); } else if (CMND_POWER_RESOLUTION == command_code) { if ((payload >= 0) && (payload <= 3)) { Settings.flag2.wattage_resolution = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag2.wattage_resolution); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.flag2.wattage_resolution); } else if (CMND_VOLTAGE_RESOLUTION == command_code) { if ((payload >= 0) && (payload <= 3)) { Settings.flag2.voltage_resolution = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag2.voltage_resolution); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.flag2.voltage_resolution); } else if (CMND_FREQUENCY_RESOLUTION == command_code) { if ((payload >= 0) && (payload <= 3)) { Settings.flag2.frequency_resolution = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag2.frequency_resolution); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.flag2.frequency_resolution); } else if (CMND_CURRENT_RESOLUTION == command_code) { if ((payload >= 0) && (payload <= 3)) { Settings.flag2.current_resolution = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag2.current_resolution); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.flag2.current_resolution); } else if (CMND_ENERGY_RESOLUTION == command_code) { if ((payload >= 0) && (payload <= 5)) { Settings.flag2.energy_resolution = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag2.energy_resolution); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.flag2.energy_resolution); } else if (CMND_WEIGHT_RESOLUTION == command_code) { if ((payload >= 0) && (payload <= 3)) { Settings.flag2.weight_resolution = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag2.weight_resolution); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.flag2.weight_resolution); } else if (CMND_MODULE == command_code) { if ((payload >= 0) && (payload <= MAXMODULE)) { @@ -885,21 +885,24 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) } restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE_SVALUE, command, ModuleNr(), ModuleName().c_str()); + Response_P(S_JSON_COMMAND_NVALUE_SVALUE, command, ModuleNr(), ModuleName().c_str()); } else if (CMND_MODULES == command_code) { for (uint8_t i = 0; i <= MAXMODULE; i++) { if (!jsflg) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_MODULES "%d\":["), lines); + Response_P(PSTR("{\"" D_CMND_MODULES "%d\":["), lines); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); + ResponseAppend_P(PSTR(",")); } jsflg = true; uint8_t j = i; if (0 == i) { j = USER_MODULE; } else { j--; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"%d (%s)\""), mqtt_data, i, AnyModuleName(j).c_str()); - if ((strlen(mqtt_data) > (LOGSZ - TOPSZ)) || (i == MAXMODULE)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s]}"), mqtt_data); + +// ResponseAppend_P(PSTR("\"%d (%s)\""), i, AnyModuleName(j).c_str()); +// if ((strlen(mqtt_data) > (LOGSZ - TOPSZ)) || (i == MAXMODULE)) { + + if ((ResponseAppend_P(PSTR("\"%d (%s)\""), i, AnyModuleName(j).c_str()) > (LOGSZ - TOPSZ)) || (i == MAXMODULE)) { + ResponseAppend_P(PSTR("]}")); MqttPublishPrefixTopic_P(RESULT_OR_STAT, type); jsflg = false; lines++; @@ -926,19 +929,18 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) restart_flag = 2; } } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{")); + Response_P(PSTR("{")); for (uint8_t i = 0; i < sizeof(Settings.my_gp); i++) { if (ValidGPIO(i, cmodule.io[i])) { - if (jsflg) snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); + if (jsflg) { ResponseAppend_P(PSTR(",")); } jsflg = true; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"" D_CMND_GPIO "%d\":\"%d (%s)\""), - mqtt_data, i, Settings.my_gp.io[i], GetTextIndexed(stemp1, sizeof(stemp1), Settings.my_gp.io[i], kSensorNames)); + ResponseAppend_P(PSTR("\"" D_CMND_GPIO "%d\":\"%d (%s)\""), i, Settings.my_gp.io[i], GetTextIndexed(stemp1, sizeof(stemp1), Settings.my_gp.io[i], kSensorNames)); } } if (jsflg) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_NOT_SUPPORTED); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_NOT_SUPPORTED); } } else if (CMND_GPIOS == command_code) { @@ -949,14 +951,17 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) midx = pgm_read_byte(kGpioNiceList + i); if (!GetUsedInModule(midx, cmodule.io)) { if (!jsflg) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_GPIOS "%d\":["), lines); + Response_P(PSTR("{\"" D_CMND_GPIOS "%d\":["), lines); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); + ResponseAppend_P(PSTR(",")); } jsflg = true; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"%d (%s)\""), mqtt_data, midx, GetTextIndexed(stemp1, sizeof(stemp1), midx, kSensorNames)); - if ((strlen(mqtt_data) > (LOGSZ - TOPSZ)) || (i == sizeof(kGpioNiceList) -1)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s]}"), mqtt_data); + +// ResponseAppend_P(PSTR("\"%d (%s)\""), midx, GetTextIndexed(stemp1, sizeof(stemp1), midx, kSensorNames)); +// if ((strlen(mqtt_data) > (LOGSZ - TOPSZ)) || (i == sizeof(kGpioNiceList) -1)) { + + if ((ResponseAppend_P(PSTR("\"%d (%s)\""), midx, GetTextIndexed(stemp1, sizeof(stemp1), midx, kSensorNames)) > (LOGSZ - TOPSZ)) || (i == sizeof(kGpioNiceList) -1)) { + ResponseAppend_P(PSTR("]}")); MqttPublishPrefixTopic_P(RESULT_OR_STAT, type); jsflg = false; lines++; @@ -999,7 +1004,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) if (JsonTemplate(dataBuf)) { // Free 336 bytes StaticJsonBuffer stack space by moving code to function if (USER_MODULE == Settings.module) { restart_flag = 2; } } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_JSON); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_JSON); error = true; } } @@ -1010,16 +1015,16 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) Settings.pwm_value[index -1] = payload; analogWrite(pin[GPIO_PWM1 + index -1], bitRead(pwm_inverted, index -1) ? Settings.pwm_range - payload : payload); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{")); + Response_P(PSTR("{")); MqttShowPWMState(); // Render the PWM status to MQTT - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); } else if (CMND_PWMFREQUENCY == command_code) { if ((1 == payload) || ((payload >= PWM_MIN) && (payload <= PWM_MAX))) { Settings.pwm_frequency = (1 == payload) ? PWM_FREQ : payload; analogWriteFreq(Settings.pwm_frequency); // Default is 1000 (core_esp8266_wiring_pwm.c) } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.pwm_frequency); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.pwm_frequency); } else if (CMND_PWMRANGE == command_code) { if ((1 == payload) || ((payload > 254) && (payload < 1024))) { @@ -1031,7 +1036,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) } analogWriteRange(Settings.pwm_range); // Default is 1023 (Arduino.h) } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.pwm_range); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.pwm_range); } else if ((CMND_COUNTER == command_code) && (index > 0) && (index <= MAX_COUNTERS)) { if ((data_len > 0) && (pin[GPIO_CNTR1 + index -1] < 99)) { @@ -1043,7 +1048,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) Settings.pulse_counter[index -1] = payload32; } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_LVALUE, command, index, RtcSettings.pulse_counter[index -1]); + Response_P(S_JSON_COMMAND_INDEX_LVALUE, command, index, RtcSettings.pulse_counter[index -1]); } else if ((CMND_COUNTERTYPE == command_code) && (index > 0) && (index <= MAX_COUNTERS)) { if ((payload >= 0) && (payload <= 1) && (pin[GPIO_CNTR1 + index -1] < 99)) { @@ -1051,25 +1056,25 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) RtcSettings.pulse_counter[index -1] = 0; Settings.pulse_counter[index -1] = 0; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_NVALUE, command, index, bitRead(Settings.pulse_counter_type, index -1)); + Response_P(S_JSON_COMMAND_INDEX_NVALUE, command, index, bitRead(Settings.pulse_counter_type, index -1)); } else if (CMND_COUNTERDEBOUNCE == command_code) { if ((data_len > 0) && (payload16 < 32001)) { Settings.pulse_counter_debounce = payload16; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.pulse_counter_debounce); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.pulse_counter_debounce); } else if (CMND_BUTTONDEBOUNCE == command_code) { if ((payload > 39) && (payload < 1001)) { Settings.button_debounce = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.button_debounce); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.button_debounce); } else if (CMND_SWITCHDEBOUNCE == command_code) { if ((payload > 39) && (payload < 1001)) { Settings.switch_debounce = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.switch_debounce); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.switch_debounce); } else if (CMND_BAUDRATE == command_code) { if (payload32 > 1200) { @@ -1077,7 +1082,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) baudrate = (1 == payload) ? APP_BAUDRATE : payload32 * 1200; SetSerialBaudrate(baudrate); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.baudrate * 1200); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.baudrate * 1200); } else if ((CMND_SERIALSEND == command_code) && (index > 0) && (index <= 5)) { SetSeriallog(LOG_LEVEL_NONE); @@ -1099,7 +1104,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) else if (5 == index) { SerialSendRaw(RemoveSpace(dataBuf)); // "AA004566" as hex values } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); } } else if (CMND_SERIALDELIMITER == command_code) { @@ -1112,7 +1117,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) Settings.serial_delimiter = dataBuf[0]; } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.serial_delimiter); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.serial_delimiter); } else if (CMND_SYSLOG == command_code) { if ((payload >= LOG_LEVEL_NONE) && (payload <= LOG_LEVEL_ALL)) { @@ -1120,19 +1125,19 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) syslog_level = payload; syslog_timer = 0; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, command, Settings.syslog_level, syslog_level); + Response_P(S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE, command, Settings.syslog_level, syslog_level); } else if (CMND_LOGHOST == command_code) { if ((data_len > 0) && (data_len < sizeof(Settings.syslog_host))) { strlcpy(Settings.syslog_host, (SC_DEFAULT == Shortcut(dataBuf)) ? SYS_LOG_HOST : dataBuf, sizeof(Settings.syslog_host)); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.syslog_host); + Response_P(S_JSON_COMMAND_SVALUE, command, Settings.syslog_host); } else if (CMND_LOGPORT == command_code) { if (payload16 > 0) { Settings.syslog_port = (1 == payload16) ? SYS_LOG_PORT : payload16; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.syslog_port); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.syslog_port); } else if ((CMND_IPADDRESS == command_code) && (index > 0) && (index <= 4)) { if (ParseIp(&address, dataBuf)) { @@ -1140,7 +1145,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) // restart_flag = 2; } snprintf_P(stemp1, sizeof(stemp1), PSTR(" (%s)"), WiFi.localIP().toString().c_str()); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE_SVALUE, command, index, IPAddress(Settings.ip_address[index -1]).toString().c_str(), (1 == index) ? stemp1:""); + Response_P(S_JSON_COMMAND_INDEX_SVALUE_SVALUE, command, index, IPAddress(Settings.ip_address[index -1]).toString().c_str(), (1 == index) ? stemp1:""); } else if ((CMND_NTPSERVER == command_code) && (index > 0) && (index <= 3)) { if ((data_len > 0) && (data_len < sizeof(Settings.ntp_server[0]))) { @@ -1151,7 +1156,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) // restart_flag = 2; // Issue #3890 ntp_force_sync = true; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.ntp_server[index -1]); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.ntp_server[index -1]); } else if (CMND_AP == command_code) { if ((payload >= 0) && (payload <= 2)) { @@ -1165,7 +1170,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) } restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE_SVALUE, command, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active]); + Response_P(S_JSON_COMMAND_NVALUE_SVALUE, command, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active]); } else if ((CMND_SSID == command_code) && (index > 0) && (index <= 2)) { if ((data_len > 0) && (data_len < sizeof(Settings.sta_ssid[0]))) { @@ -1173,16 +1178,16 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) Settings.sta_active = index -1; restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.sta_ssid[index -1]); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.sta_ssid[index -1]); } else if ((CMND_PASSWORD == command_code) && (index > 0) && (index <= 2)) { if ((data_len > 4 || SC_CLEAR == Shortcut(dataBuf) || SC_DEFAULT == Shortcut(dataBuf)) && (data_len < sizeof(Settings.sta_pwd[0]))) { strlcpy(Settings.sta_pwd[index -1], (SC_CLEAR == Shortcut(dataBuf)) ? "" : (SC_DEFAULT == Shortcut(dataBuf)) ? (1 == index) ? STA_PASS1 : STA_PASS2 : dataBuf, sizeof(Settings.sta_pwd[0])); Settings.sta_active = index -1; restart_flag = 2; - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.sta_pwd[index -1]); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.sta_pwd[index -1]); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_ASTERIX, command, index); + Response_P(S_JSON_COMMAND_INDEX_ASTERIX, command, index); } } else if (CMND_HOSTNAME == command_code) { @@ -1193,21 +1198,21 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) } restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.hostname); + Response_P(S_JSON_COMMAND_SVALUE, command, Settings.hostname); } else if (CMND_WIFICONFIG == command_code) { if ((payload >= WIFI_RESTART) && (payload < MAX_WIFI_OPTION)) { Settings.sta_config = payload; wifi_state_flag = Settings.sta_config; snprintf_P(stemp1, sizeof(stemp1), kWifiConfig[Settings.sta_config]); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_WIFICONFIG "\":\"%s " D_JSON_SELECTED "\"}"), stemp1); + Response_P(PSTR("{\"" D_CMND_WIFICONFIG "\":\"%s " D_JSON_SELECTED "\"}"), stemp1); if (WifiState() > WIFI_RESTART) { // snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s after restart"), mqtt_data); restart_flag = 2; } } else { snprintf_P(stemp1, sizeof(stemp1), kWifiConfig[Settings.sta_config]); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE_SVALUE, command, Settings.sta_config, stemp1); + Response_P(S_JSON_COMMAND_NVALUE_SVALUE, command, Settings.sta_config, stemp1); } } else if ((CMND_FRIENDLYNAME == command_code) && (index > 0) && (index <= MAX_FRIENDLYNAMES)) { @@ -1219,13 +1224,13 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) } strlcpy(Settings.friendlyname[index -1], (SC_DEFAULT == Shortcut(dataBuf)) ? stemp1 : dataBuf, sizeof(Settings.friendlyname[index -1])); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.friendlyname[index -1]); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.friendlyname[index -1]); } else if ((CMND_SWITCHMODE == command_code) && (index > 0) && (index <= MAX_SWITCHES)) { if ((payload >= 0) && (payload < MAX_SWITCH_OPTION)) { Settings.switchmode[index -1] = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_NVALUE, command, index, Settings.switchmode[index-1]); + Response_P(S_JSON_COMMAND_INDEX_NVALUE, command, index, Settings.switchmode[index-1]); } else if (CMND_INTERLOCK == command_code) { // Interlock 0 - Off, Interlock 1 - On, Interlock 1,2 3,4 5,6,7 uint8_t max_relays = devices_present; @@ -1267,18 +1272,18 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) } } } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_INTERLOCK "\":\"%s\",\"" D_JSON_GROUPS "\":\""), GetStateText(Settings.flag.interlock)); + Response_P(PSTR("{\"" D_CMND_INTERLOCK "\":\"%s\",\"" D_JSON_GROUPS "\":\""), GetStateText(Settings.flag.interlock)); uint8_t anygroup = 0; for (uint8_t i = 0; i < MAX_INTERLOCKS; i++) { if (Settings.interlock[i]) { anygroup++; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s"), mqtt_data, (anygroup > 1) ? " " : ""); + ResponseAppend_P(PSTR("%s"), (anygroup > 1) ? " " : ""); uint8_t anybit = 0; power_t mask = 1; for (uint8_t j = 0; j < max_relays; j++) { if (Settings.interlock[i] & mask) { anybit++; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s%d"), mqtt_data, (anybit > 1) ? "," : "", j +1); + ResponseAppend_P(PSTR("%s%d"), (anybit > 1) ? "," : "", j +1); } mask <<= 1; } @@ -1286,13 +1291,13 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) } if (!anygroup) { for (uint8_t j = 1; j <= max_relays; j++) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s%d"), mqtt_data, (j > 1) ? "," : "", j); + ResponseAppend_P(PSTR("%s%d"), (j > 1) ? "," : "", j); } } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"}"), mqtt_data); + ResponseAppend_P(PSTR("\"}")); } else { Settings.flag.interlock = 0; - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.interlock)); + Response_P(S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.interlock)); } } else if (CMND_TELEPERIOD == command_code) { @@ -1301,20 +1306,20 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) if ((Settings.tele_period > 0) && (Settings.tele_period < 10)) Settings.tele_period = 10; // Do not allow periods < 10 seconds tele_period = Settings.tele_period; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE_UNIT, command, Settings.tele_period, (Settings.flag.value_units) ? " " D_UNIT_SECOND : ""); + Response_P(S_JSON_COMMAND_NVALUE_UNIT, command, Settings.tele_period, (Settings.flag.value_units) ? " " D_UNIT_SECOND : ""); } else if (CMND_RESET == command_code) { switch (payload) { case 1: restart_flag = 211; - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command , D_JSON_RESET_AND_RESTARTING); + Response_P(S_JSON_COMMAND_SVALUE, command , D_JSON_RESET_AND_RESTARTING); break; case 2 ... 6: restart_flag = 210 + payload; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RESET "\":\"" D_JSON_ERASE ", " D_JSON_RESET_AND_RESTARTING "\"}")); + Response_P(PSTR("{\"" D_CMND_RESET "\":\"" D_JSON_ERASE ", " D_JSON_RESET_AND_RESTARTING "\"}")); break; default: - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_ONE_TO_RESET); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_ONE_TO_RESET); } } else if (CMND_TIMEZONE == command_code) { @@ -1336,10 +1341,10 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) ntp_force_sync = true; } if (99 == Settings.timezone) { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.timezone); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.timezone); } else { snprintf_P(stemp1, sizeof(stemp1), PSTR("%+03d:%02d"), Settings.timezone, Settings.timezone_minutes); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, stemp1); + Response_P(S_JSON_COMMAND_SVALUE, command, stemp1); } } else if ((CMND_TIMESTD == command_code) || (CMND_TIMEDST == command_code)) { @@ -1380,14 +1385,14 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) ntp_force_sync = true; } } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":{\"Hemisphere\":%d,\"Week\":%d,\"Month\":%d,\"Day\":%d,\"Hour\":%d,\"Offset\":%d}}"), + Response_P(PSTR("{\"%s\":{\"Hemisphere\":%d,\"Week\":%d,\"Month\":%d,\"Day\":%d,\"Hour\":%d,\"Offset\":%d}}"), command, Settings.tflag[ts].hemis, Settings.tflag[ts].week, Settings.tflag[ts].month, Settings.tflag[ts].dow, Settings.tflag[ts].hour, Settings.toffset[ts]); } else if (CMND_ALTITUDE == command_code) { if ((data_len > 0) && ((payload >= -30000) && (payload <= 30000))) { Settings.altitude = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.altitude); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.altitude); } else if (CMND_LEDPOWER == command_code) { if ((payload >= 0) && (payload <= 2)) { @@ -1404,7 +1409,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) blinks = 0; SetLedPower(Settings.ledstate &8); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(bitRead(Settings.ledstate, 3))); + Response_P(S_JSON_COMMAND_SVALUE, command, GetStateText(bitRead(Settings.ledstate, 3))); } else if (CMND_LEDSTATE == command_code) { if ((payload >= 0) && (payload < MAX_LED_OPTION)) { @@ -1414,7 +1419,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) SetLedLink(0); } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.ledstate); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.ledstate); } #ifdef USE_I2C else if ((CMND_I2CSCAN == command_code) && i2c_flg) { @@ -1426,10 +1431,10 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) if (type == NULL) { blinks = 201; snprintf_P(topicBuf, sizeof(topicBuf), PSTR(D_JSON_COMMAND)); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_UNKNOWN "\"}")); + Response_P(PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_UNKNOWN "\"}")); type = (char*)topicBuf; } - if (mqtt_data[0] != '\0') MqttPublishPrefixTopic_P(RESULT_OR_STAT, type); + if (mqtt_data[0] != '\0') { MqttPublishPrefixTopic_P(RESULT_OR_STAT, type); } fallback_topic_flag = false; } @@ -1641,19 +1646,19 @@ void PublishStatus(uint8_t payload) for (uint8_t i = 0; i < MAX_SWITCHES; i++) { snprintf_P(stemp2, sizeof(stemp2), PSTR("%s%s%d" ), stemp2, (i > 0 ? "," : ""), Settings.switchmode[i]); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS "\":{\"" D_CMND_MODULE "\":%d,\"" D_CMND_FRIENDLYNAME "\":[%s],\"" D_CMND_TOPIC "\":\"%s\",\"" D_CMND_BUTTONTOPIC "\":\"%s\",\"" D_CMND_POWER "\":%d,\"" D_CMND_POWERONSTATE "\":%d,\"" D_CMND_LEDSTATE "\":%d,\"" D_CMND_SAVEDATA "\":%d,\"" D_JSON_SAVESTATE "\":%d,\"" D_CMND_SWITCHTOPIC "\":\"%s\",\"" D_CMND_SWITCHMODE "\":[%s],\"" D_CMND_BUTTONRETAIN "\":%d,\"" D_CMND_SWITCHRETAIN "\":%d,\"" D_CMND_SENSORRETAIN "\":%d,\"" D_CMND_POWERRETAIN "\":%d}}"), + Response_P(PSTR("{\"" D_CMND_STATUS "\":{\"" D_CMND_MODULE "\":%d,\"" D_CMND_FRIENDLYNAME "\":[%s],\"" D_CMND_TOPIC "\":\"%s\",\"" D_CMND_BUTTONTOPIC "\":\"%s\",\"" D_CMND_POWER "\":%d,\"" D_CMND_POWERONSTATE "\":%d,\"" D_CMND_LEDSTATE "\":%d,\"" D_CMND_SAVEDATA "\":%d,\"" D_JSON_SAVESTATE "\":%d,\"" D_CMND_SWITCHTOPIC "\":\"%s\",\"" D_CMND_SWITCHMODE "\":[%s],\"" D_CMND_BUTTONRETAIN "\":%d,\"" D_CMND_SWITCHRETAIN "\":%d,\"" D_CMND_SENSORRETAIN "\":%d,\"" D_CMND_POWERRETAIN "\":%d}}"), ModuleNr(), stemp, mqtt_topic, Settings.button_topic, power, Settings.poweronstate, Settings.ledstate, Settings.save_data, Settings.flag.save_state, Settings.switch_topic, stemp2, Settings.flag.mqtt_button_retain, Settings.flag.mqtt_switch_retain, Settings.flag.mqtt_sensor_retain, Settings.flag.mqtt_power_retain); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS)); } if ((0 == payload) || (1 == payload)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS1_PARAMETER "\":{\"" D_JSON_BAUDRATE "\":%d,\"" D_CMND_GROUPTOPIC "\":\"%s\",\"" D_CMND_OTAURL "\":\"%s\",\"" D_JSON_RESTARTREASON "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\",\"" D_JSON_STARTUPUTC "\":\"%s\",\"" D_CMND_SLEEP "\":%d,\"" D_JSON_CONFIG_HOLDER "\":%d,\"" D_JSON_BOOTCOUNT "\":%d,\"" D_JSON_SAVECOUNT "\":%d,\"" D_JSON_SAVEADDRESS "\":\"%X\"}}"), + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS1_PARAMETER "\":{\"" D_JSON_BAUDRATE "\":%d,\"" D_CMND_GROUPTOPIC "\":\"%s\",\"" D_CMND_OTAURL "\":\"%s\",\"" D_JSON_RESTARTREASON "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\",\"" D_JSON_STARTUPUTC "\":\"%s\",\"" D_CMND_SLEEP "\":%d,\"" D_JSON_CONFIG_HOLDER "\":%d,\"" D_JSON_BOOTCOUNT "\":%d,\"" D_JSON_SAVECOUNT "\":%d,\"" D_JSON_SAVEADDRESS "\":\"%X\"}}"), baudrate, Settings.mqtt_grptopic, Settings.ota_url, GetResetReason().c_str(), GetUptime().c_str(), GetDateAndTime(DT_RESTART).c_str(), Settings.sleep, Settings.cfg_holder, Settings.bootcount, Settings.save_flag, GetSettingsAddress()); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "1")); } if ((0 == payload) || (2 == payload)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS2_FIRMWARE "\":{\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_BUILDDATETIME "\":\"%s\",\"" D_JSON_BOOTVERSION "\":%d,\"" D_JSON_COREVERSION "\":\"" ARDUINO_ESP8266_RELEASE "\",\"" D_JSON_SDKVERSION "\":\"%s\"}}"), + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS2_FIRMWARE "\":{\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_BUILDDATETIME "\":\"%s\",\"" D_JSON_BOOTVERSION "\":%d,\"" D_JSON_COREVERSION "\":\"" ARDUINO_ESP8266_RELEASE "\",\"" D_JSON_SDKVERSION "\":\"%s\"}}"), my_version, my_image, GetBuildDateAndTime().c_str(), ESP.getBootVersion(), ESP.getSdkVersion()); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "2")); } @@ -1663,26 +1668,26 @@ void PublishStatus(uint8_t payload) for (int8_t i = 0; i < PARAM8_SIZE; i++) { snprintf_P(stemp2, sizeof(stemp2), PSTR("%s%02X"), stemp2, Settings.param[i]); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS3_LOGGING "\":{\"" D_CMND_SERIALLOG "\":%d,\"" D_CMND_WEBLOG "\":%d,\"" D_CMND_SYSLOG "\":%d,\"" D_CMND_LOGHOST "\":\"%s\",\"" D_CMND_LOGPORT "\":%d,\"" D_CMND_SSID "\":[\"%s\",\"%s\"],\"" D_CMND_TELEPERIOD "\":%d,\"" D_JSON_RESOLUTION "\":\"%08X\",\"" D_CMND_SETOPTION "\":[\"%08X\",\"%s\",\"%08X\"]}}"), + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS3_LOGGING "\":{\"" D_CMND_SERIALLOG "\":%d,\"" D_CMND_WEBLOG "\":%d,\"" D_CMND_SYSLOG "\":%d,\"" D_CMND_LOGHOST "\":\"%s\",\"" D_CMND_LOGPORT "\":%d,\"" D_CMND_SSID "\":[\"%s\",\"%s\"],\"" D_CMND_TELEPERIOD "\":%d,\"" D_JSON_RESOLUTION "\":\"%08X\",\"" D_CMND_SETOPTION "\":[\"%08X\",\"%s\",\"%08X\"]}}"), Settings.seriallog_level, Settings.weblog_level, Settings.syslog_level, Settings.syslog_host, Settings.syslog_port, Settings.sta_ssid[0], Settings.sta_ssid[1], Settings.tele_period, Settings.flag2.data, Settings.flag.data, stemp2, Settings.flag3.data); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "3")); } if ((0 == payload) || (4 == payload)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS4_MEMORY "\":{\"" D_JSON_PROGRAMSIZE "\":%d,\"" D_JSON_FREEMEMORY "\":%d,\"" D_JSON_HEAPSIZE "\":%d,\"" D_JSON_PROGRAMFLASHSIZE "\":%d,\"" D_JSON_FLASHSIZE "\":%d,\"" D_JSON_FLASHCHIPID "\":\"%06X\",\"" D_JSON_FLASHMODE "\":%d,\"" D_JSON_FEATURES "\":[\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\"]}}"), + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS4_MEMORY "\":{\"" D_JSON_PROGRAMSIZE "\":%d,\"" D_JSON_FREEMEMORY "\":%d,\"" D_JSON_HEAPSIZE "\":%d,\"" D_JSON_PROGRAMFLASHSIZE "\":%d,\"" D_JSON_FLASHSIZE "\":%d,\"" D_JSON_FLASHCHIPID "\":\"%06X\",\"" D_JSON_FLASHMODE "\":%d,\"" D_JSON_FEATURES "\":[\"%08X\",\"%08X\",\"%08X\",\"%08X\",\"%08X\"]}}"), ESP.getSketchSize()/1024, ESP.getFreeSketchSpace()/1024, ESP.getFreeHeap()/1024, ESP.getFlashChipSize()/1024, ESP.getFlashChipRealSize()/1024, ESP.getFlashChipId(), ESP.getFlashChipMode(), LANGUAGE_LCID, feature_drv1, feature_drv2, feature_sns1, feature_sns2); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "4")); } if ((0 == payload) || (5 == payload)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS5_NETWORK "\":{\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\",\"" D_JSON_GATEWAY "\":\"%s\",\"" D_JSON_SUBNETMASK "\":\"%s\",\"" D_JSON_DNSSERVER "\":\"%s\",\"" D_JSON_MAC "\":\"%s\",\"" D_CMND_WEBSERVER "\":%d,\"" D_CMND_WIFICONFIG "\":%d}}"), + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS5_NETWORK "\":{\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\",\"" D_JSON_GATEWAY "\":\"%s\",\"" D_JSON_SUBNETMASK "\":\"%s\",\"" D_JSON_DNSSERVER "\":\"%s\",\"" D_JSON_MAC "\":\"%s\",\"" D_CMND_WEBSERVER "\":%d,\"" D_CMND_WIFICONFIG "\":%d}}"), my_hostname, WiFi.localIP().toString().c_str(), IPAddress(Settings.ip_address[1]).toString().c_str(), IPAddress(Settings.ip_address[2]).toString().c_str(), IPAddress(Settings.ip_address[3]).toString().c_str(), WiFi.macAddress().c_str(), Settings.webserver, Settings.sta_config); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "5")); } if (((0 == payload) || (6 == payload)) && Settings.flag.mqtt_enabled) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS6_MQTT "\":{\"" D_CMND_MQTTHOST "\":\"%s\",\"" D_CMND_MQTTPORT "\":%d,\"" D_CMND_MQTTCLIENT D_JSON_MASK "\":\"%s\",\"" D_CMND_MQTTCLIENT "\":\"%s\",\"" D_CMND_MQTTUSER "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d,\"MAX_PACKET_SIZE\":%d,\"KEEPALIVE\":%d}}"), + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS6_MQTT "\":{\"" D_CMND_MQTTHOST "\":\"%s\",\"" D_CMND_MQTTPORT "\":%d,\"" D_CMND_MQTTCLIENT D_JSON_MASK "\":\"%s\",\"" D_CMND_MQTTCLIENT "\":\"%s\",\"" D_CMND_MQTTUSER "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d,\"MAX_PACKET_SIZE\":%d,\"KEEPALIVE\":%d}}"), Settings.mqtt_host, Settings.mqtt_port, Settings.mqtt_client, mqtt_client, Settings.mqtt_user, MqttConnectCount(), MQTT_MAX_PACKET_SIZE, MQTT_KEEPALIVE); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "6")); } @@ -1694,10 +1699,10 @@ void PublishStatus(uint8_t payload) snprintf_P(stemp, sizeof(stemp), PSTR("\"%s\"" ), GetTimeZone().c_str()); } #if defined(USE_TIMERS) && defined(USE_SUNRISE) - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS7_TIME "\":{\"" D_JSON_UTC_TIME "\":\"%s\",\"" D_JSON_LOCAL_TIME "\":\"%s\",\"" D_JSON_STARTDST "\":\"%s\",\"" D_JSON_ENDDST "\":\"%s\",\"" D_CMND_TIMEZONE "\":%s,\"" D_JSON_SUNRISE "\":\"%s\",\"" D_JSON_SUNSET "\":\"%s\"}}"), + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS7_TIME "\":{\"" D_JSON_UTC_TIME "\":\"%s\",\"" D_JSON_LOCAL_TIME "\":\"%s\",\"" D_JSON_STARTDST "\":\"%s\",\"" D_JSON_ENDDST "\":\"%s\",\"" D_CMND_TIMEZONE "\":%s,\"" D_JSON_SUNRISE "\":\"%s\",\"" D_JSON_SUNSET "\":\"%s\"}}"), GetTime(0).c_str(), GetTime(1).c_str(), GetTime(2).c_str(), GetTime(3).c_str(), stemp, GetSun(0).c_str(), GetSun(1).c_str()); #else - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS7_TIME "\":{\"" D_JSON_UTC_TIME "\":\"%s\",\"" D_JSON_LOCAL_TIME "\":\"%s\",\"" D_JSON_STARTDST "\":\"%s\",\"" D_JSON_ENDDST "\":\"%s\",\"" D_CMND_TIMEZONE "\":%s}}"), + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS7_TIME "\":{\"" D_JSON_UTC_TIME "\":\"%s\",\"" D_JSON_LOCAL_TIME "\":\"%s\",\"" D_JSON_STARTDST "\":\"%s\",\"" D_JSON_ENDDST "\":\"%s\",\"" D_CMND_TIMEZONE "\":%s}}"), GetTime(0).c_str(), GetTime(1).c_str(), GetTime(2).c_str(), GetTime(3).c_str(), stemp); #endif // USE_TIMERS and USE_SUNRISE MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "7")); @@ -1705,16 +1710,16 @@ void PublishStatus(uint8_t payload) if (energy_flg) { if ((0 == payload) || (9 == payload)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS9_MARGIN "\":{\"" D_CMND_POWERDELTA "\":%d,\"" D_CMND_POWERLOW "\":%d,\"" D_CMND_POWERHIGH "\":%d,\"" D_CMND_VOLTAGELOW "\":%d,\"" D_CMND_VOLTAGEHIGH "\":%d,\"" D_CMND_CURRENTLOW "\":%d,\"" D_CMND_CURRENTHIGH "\":%d}}"), + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS9_MARGIN "\":{\"" D_CMND_POWERDELTA "\":%d,\"" D_CMND_POWERLOW "\":%d,\"" D_CMND_POWERHIGH "\":%d,\"" D_CMND_VOLTAGELOW "\":%d,\"" D_CMND_VOLTAGEHIGH "\":%d,\"" D_CMND_CURRENTLOW "\":%d,\"" D_CMND_CURRENTHIGH "\":%d}}"), Settings.energy_power_delta, Settings.energy_min_power, Settings.energy_max_power, Settings.energy_min_voltage, Settings.energy_max_voltage, Settings.energy_min_current, Settings.energy_max_current); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "9")); } } if ((0 == payload) || (8 == payload) || (10 == payload)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS10_SENSOR "\":")); + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS10_SENSOR "\":")); MqttShowSensor(); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); if (8 == payload) { MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "8")); } else { @@ -1723,9 +1728,9 @@ void PublishStatus(uint8_t payload) } if ((0 == payload) || (11 == payload)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS11_STATUS "\":")); + Response_P(PSTR("{\"" D_CMND_STATUS D_STATUS11_STATUS "\":")); MqttShowState(); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "11")); } @@ -1733,50 +1738,50 @@ void PublishStatus(uint8_t payload) void MqttShowPWMState(void) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"" D_CMND_PWM "\":{"), mqtt_data); + ResponseAppend_P(PSTR("\"" D_CMND_PWM "\":{")); bool first = true; for (uint8_t i = 0; i < MAX_PWMS; i++) { if (pin[GPIO_PWM1 + i] < 99) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_PWM "%d\":%d"), mqtt_data, first ? "" : ",", i+1, Settings.pwm_value[i]); + ResponseAppend_P(PSTR("%s\"" D_CMND_PWM "%d\":%d"), first ? "" : ",", i+1, Settings.pwm_value[i]); first = false; } } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); } void MqttShowState(void) { char stemp1[33]; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s{\"" D_JSON_TIME "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\""), mqtt_data, GetDateAndTime(DT_LOCAL).c_str(), GetUptime().c_str()); + ResponseAppend_P(PSTR("{\"" D_JSON_TIME "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str(), GetUptime().c_str()); #ifdef USE_ADC_VCC dtostrfd((double)ESP.getVcc()/1000, 3, stemp1); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_VCC "\":%s"), mqtt_data, stemp1); + ResponseAppend_P(PSTR(",\"" D_JSON_VCC "\":%s"), stemp1); #endif - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SleepMode\":\"%s\",\"Sleep\":%u,\"LoadAvg\":%u"), - mqtt_data, GetTextIndexed(stemp1, sizeof(stemp1), Settings.flag3.sleep_normal, kSleepMode), sleep, loop_load_avg); + ResponseAppend_P(PSTR(",\"SleepMode\":\"%s\",\"Sleep\":%u,\"LoadAvg\":%u"), + GetTextIndexed(stemp1, sizeof(stemp1), Settings.flag3.sleep_normal, kSleepMode), sleep, loop_load_avg); for (uint8_t i = 0; i < devices_present; i++) { if (i == light_device -1) { LightState(1); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":\"%s\""), mqtt_data, GetPowerDevice(stemp1, i +1, sizeof(stemp1), Settings.flag.device_index_enable), GetStateText(bitRead(power, i))); + ResponseAppend_P(PSTR(",\"%s\":\"%s\""), GetPowerDevice(stemp1, i +1, sizeof(stemp1), Settings.flag.device_index_enable), GetStateText(bitRead(power, i))); if (SONOFF_IFAN02 == my_module_type) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_FANSPEED "\":%d"), mqtt_data, GetFanspeed()); + ResponseAppend_P(PSTR(",\"" D_CMND_FANSPEED "\":%d"), GetFanspeed()); break; } } } if (pwm_present) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); + ResponseAppend_P(PSTR(",")); MqttShowPWMState(); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_BSSID "\":\"%s\",\"" D_JSON_CHANNEL "\":%d,\"" D_JSON_RSSI "\":%d,\"" D_JSON_LINK_COUNT "\":%d,\"" D_JSON_DOWNTIME "\":\"%s\"}}"), - mqtt_data, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WiFi.BSSIDstr().c_str(), WiFi.channel(), WifiGetRssiAsQuality(WiFi.RSSI()), WifiLinkCount(), WifiDowntime().c_str()); + ResponseAppend_P(PSTR(",\"" D_JSON_WIFI "\":{\"" D_JSON_AP "\":%d,\"" D_JSON_SSID "\":\"%s\",\"" D_JSON_BSSID "\":\"%s\",\"" D_JSON_CHANNEL "\":%d,\"" D_JSON_RSSI "\":%d,\"" D_JSON_LINK_COUNT "\":%d,\"" D_JSON_DOWNTIME "\":\"%s\"}}"), + Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WiFi.BSSIDstr().c_str(), WiFi.channel(), WifiGetRssiAsQuality(WiFi.RSSI()), WifiLinkCount(), WifiDowntime().c_str()); } void MqttPublishTeleState(void) @@ -1788,7 +1793,7 @@ void MqttPublishTeleState(void) bool MqttShowSensor(void) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s{\"" D_JSON_TIME "\":\"%s\""), mqtt_data, GetDateAndTime(DT_LOCAL).c_str()); + ResponseAppend_P(PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); int json_data_start = strlen(mqtt_data); for (uint8_t i = 0; i < MAX_SWITCHES; i++) { #ifdef USE_TM1638 @@ -1797,20 +1802,20 @@ bool MqttShowSensor(void) if (pin[GPIO_SWT1 +i] < 99) { #endif // USE_TM1638 bool swm = ((FOLLOW_INV == Settings.switchmode[i]) || (PUSHBUTTON_INV == Settings.switchmode[i]) || (PUSHBUTTONHOLD_INV == Settings.switchmode[i])); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_SWITCH "%d\":\"%s\""), mqtt_data, i +1, GetStateText(swm ^ SwitchLastState(i))); + ResponseAppend_P(PSTR(",\"" D_JSON_SWITCH "%d\":\"%s\""), i +1, GetStateText(swm ^ SwitchLastState(i))); } } XsnsCall(FUNC_JSON_APPEND); bool json_data_available = (strlen(mqtt_data) - json_data_start); if (strstr_P(mqtt_data, PSTR(D_JSON_PRESSURE))) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_PRESSURE_UNIT "\":\"%s\""), mqtt_data, PressureUnit().c_str()); + ResponseAppend_P(PSTR(",\"" D_JSON_PRESSURE_UNIT "\":\"%s\""), PressureUnit().c_str()); } if (strstr_P(mqtt_data, PSTR(D_JSON_TEMPERATURE))) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_TEMPERATURE_UNIT "\":\"%c\""), mqtt_data, TempUnit()); + ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE_UNIT "\":\"%c\""), TempUnit()); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); - if (json_data_available) XdrvCall(FUNC_SHOW_SENSOR); + if (json_data_available) { XdrvCall(FUNC_SHOW_SENSOR); } return json_data_available; } @@ -1880,7 +1885,7 @@ void PerformEverySecond(void) if ((2 == RtcTime.minute) && latest_uptime_flag) { latest_uptime_flag = false; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\"}"), GetDateAndTime(DT_LOCAL).c_str(), GetUptime().c_str()); + Response_P(PSTR("{\"" D_JSON_TIME "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\"}"), GetDateAndTime(DT_LOCAL).c_str(), GetUptime().c_str()); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_UPTIME)); } if ((3 == RtcTime.minute) && !latest_uptime_flag) latest_uptime_flag = true; @@ -2054,9 +2059,9 @@ void Every250mSeconds(void) ota_state_flag = 0; if (ota_result) { // SetFlashModeDout(); // Force DOUT for both ESP8266 and ESP8285 - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(D_JSON_SUCCESSFUL ". " D_JSON_RESTARTING)); + Response_P(PSTR(D_JSON_SUCCESSFUL ". " D_JSON_RESTARTING)); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(D_JSON_FAILED " %s"), ESPhttpUpdate.getLastErrorString().c_str()); + Response_P(PSTR(D_JSON_FAILED " %s"), ESPhttpUpdate.getLastErrorString().c_str()); } restart_flag = 2; // Restart anyway to keep memory clean webserver MqttPublishPrefixTopic_P(STAT, PSTR(D_CMND_UPGRADE)); @@ -2298,13 +2303,13 @@ void SerialInput(void) if (Settings.flag.mqtt_serial && serial_in_byte_counter && (millis() > (serial_polling_window + SERIAL_POLLING))) { serial_in_buffer[serial_in_byte_counter] = 0; // Serial data completed if (!Settings.flag.mqtt_serial_raw) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"%s\"}"), serial_in_buffer); + Response_P(PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"%s\"}"), serial_in_buffer); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"")); + Response_P(PSTR("{\"" D_JSON_SERIALRECEIVED "\":\"")); for (int i = 0; i < serial_in_byte_counter; i++) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%02x"), mqtt_data, serial_in_buffer[i]); + ResponseAppend_P(PSTR("%02x"), serial_in_buffer[i]); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"}"), mqtt_data); + ResponseAppend_P(PSTR("\"}")); } MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SERIALRECEIVED)); // XdrvRulesProcess(); diff --git a/sonoff/support.ino b/sonoff/support.ino index dc0396be2..24f0c6f8c 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -697,6 +697,31 @@ void ShowSource(int source) } } +/*********************************************************************************************\ + * Response data handling +\*********************************************************************************************/ + +int Response_P(const char* formatP, ...) // Content send snprintf_P char data +{ + // This uses char strings. Be aware of sending %% if % is needed + va_list arg; + va_start(arg, formatP); + int len = vsnprintf_P(mqtt_data, sizeof(mqtt_data), formatP, arg); + va_end(arg); + return len; +} + +int ResponseAppend_P(const char* formatP, ...) // Content send snprintf_P char data +{ + // This uses char strings. Be aware of sending %% if % is needed + va_list arg; + va_start(arg, formatP); + int mlen = strlen(mqtt_data); + int len = vsnprintf_P(mqtt_data + mlen, sizeof(mqtt_data) - mlen, formatP, arg); + va_end(arg); + return len + mlen; +} + /*********************************************************************************************\ * GPIO Module and Template management \*********************************************************************************************/ @@ -883,12 +908,11 @@ bool JsonTemplate(const char* dataBuf) void TemplateJson() { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), Settings.user_template.name); + Response_P(PSTR("{\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), Settings.user_template.name); for (uint8_t i = 0; i < sizeof(Settings.user_template.gp); i++) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s%d"), mqtt_data, (i>0)?",":"", Settings.user_template.gp.io[i]); + ResponseAppend_P(PSTR("%s%d"), (i>0)?",":"", Settings.user_template.gp.io[i]); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":%d}"), - mqtt_data, Settings.user_template.flag, Settings.user_template_base +1); + ResponseAppend_P(PSTR("],\"" D_JSON_FLAG "\":%d,\"" D_JSON_BASE "\":%d}"), Settings.user_template.flag, Settings.user_template_base +1); } /*********************************************************************************************\ diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 48a13fe11..f34bfda09 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -2136,13 +2136,12 @@ void HandleNotFound(void) } else #endif // USE_EMULATION { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(D_FILE_NOT_FOUND "\n\nURI: %s\nMethod: %s\nArguments: %d\n"), - WebServer->uri().c_str(), (WebServer->method() == HTTP_GET) ? "GET" : "POST", WebServer->args()); + WSContentBegin(404, CT_PLAIN); + WSContentSend_P(PSTR(D_FILE_NOT_FOUND "\n\nURI: %s\nMethod: %s\nArguments: %d\n"), WebServer->uri().c_str(), (WebServer->method() == HTTP_GET) ? "GET" : "POST", WebServer->args()); for (uint8_t i = 0; i < WebServer->args(); i++) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s %s: %s\n"), mqtt_data, WebServer->argName(i).c_str(), WebServer->arg(i).c_str()); + WSContentSend_P(PSTR(" %s: %s\n"), WebServer->argName(i).c_str(), WebServer->arg(i).c_str()); } - WSHeaderSend(); - WSSend(404, CT_PLAIN, mqtt_data); + WSContentEnd(); } } @@ -2301,33 +2300,33 @@ bool WebCommand(void) if (CMND_WEBSERVER == command_code) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 2)) { Settings.webserver = XdrvMailbox.payload; } if (Settings.webserver) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_WEBSERVER "\":\"" D_JSON_ACTIVE_FOR " %s " D_JSON_ON_DEVICE " %s " D_JSON_WITH_IP_ADDRESS " %s\"}"), + Response_P(PSTR("{\"" D_CMND_WEBSERVER "\":\"" D_JSON_ACTIVE_FOR " %s " D_JSON_ON_DEVICE " %s " D_JSON_WITH_IP_ADDRESS " %s\"}"), (2 == Settings.webserver) ? D_ADMIN : D_USER, my_hostname, WiFi.localIP().toString().c_str()); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(0)); + Response_P(S_JSON_COMMAND_SVALUE, command, GetStateText(0)); } } 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)); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.web_password); + Response_P(S_JSON_COMMAND_SVALUE, command, Settings.web_password); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_ASTERIX, command); + Response_P(S_JSON_COMMAND_ASTERIX, command); } } else if (CMND_WEBLOG == command_code) { if ((XdrvMailbox.payload >= LOG_LEVEL_NONE) && (XdrvMailbox.payload <= LOG_LEVEL_ALL)) { Settings.weblog_level = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.weblog_level); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.weblog_level); } else if (CMND_WEBREFRESH == command_code) { if ((XdrvMailbox.payload > 999) && (XdrvMailbox.payload <= 10000)) { Settings.web_refresh = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.web_refresh); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.web_refresh); } else if (CMND_WEBSEND == command_code) { if (XdrvMailbox.data_len > 0) { uint8_t result = WebSend(XdrvMailbox.data); char stemp1[20]; - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetTextIndexed(stemp1, sizeof(stemp1), result, kWebSendStatus)); + Response_P(S_JSON_COMMAND_SVALUE, command, GetTextIndexed(stemp1, sizeof(stemp1), result, kWebSendStatus)); } } #ifdef USE_EMULATION @@ -2336,7 +2335,7 @@ bool WebCommand(void) Settings.flag2.emulation = XdrvMailbox.payload; restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag2.emulation); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.flag2.emulation); } #endif // USE_EMULATION else serviced = false; // Unknown command diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 57086d46e..21b97edd0 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -237,17 +237,17 @@ void MqttPublishPowerState(uint8_t device) #endif // USE_DOMOTICZ snprintf_P(scommand, sizeof(scommand), PSTR(D_CMND_FANSPEED)); GetTopic_P(stopic, STAT, mqtt_topic, (Settings.flag.mqtt_response) ? scommand : S_RSLT_RESULT); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, scommand, GetFanspeed()); + Response_P(S_JSON_COMMAND_NVALUE, scommand, GetFanspeed()); MqttPublish(stopic); } } else { GetPowerDevice(scommand, device, sizeof(scommand), Settings.flag.device_index_enable); GetTopic_P(stopic, STAT, mqtt_topic, (Settings.flag.mqtt_response) ? scommand : S_RSLT_RESULT); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, scommand, GetStateText(bitRead(power, device -1))); + Response_P(S_JSON_COMMAND_SVALUE, scommand, GetStateText(bitRead(power, device -1))); MqttPublish(stopic); GetTopic_P(stopic, STAT, mqtt_topic, scommand); - snprintf_P(mqtt_data, sizeof(mqtt_data), GetStateText(bitRead(power, device -1))); + Response_P(GetStateText(bitRead(power, device -1))); MqttPublish(stopic, Settings.flag.mqtt_power_retain); } } @@ -259,7 +259,7 @@ void MqttPublishPowerBlinkState(uint8_t device) if ((device < 1) || (device > devices_present)) { device = 1; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":\"" D_JSON_BLINK " %s\"}"), + Response_P(PSTR("{\"%s\":\"" D_JSON_BLINK " %s\"}"), GetPowerDevice(scommand, device, sizeof(scommand), Settings.flag.device_index_enable), GetStateText(bitRead(blink_mask, device -1))); MqttPublishPrefixTopic_P(RESULT_OR_STAT, S_RSLT_POWER); @@ -292,7 +292,7 @@ void MqttConnected(void) mqtt_connect_count++; GetTopic_P(stopic, TELE, mqtt_topic, S_LWT); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR(D_ONLINE)); + Response_P(PSTR(D_ONLINE)); MqttPublish(stopic, true); // Satisfy iobroker (#299) @@ -312,18 +312,17 @@ void MqttConnected(void) } if (mqtt_initial_connection_state) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_MODULE "\":\"%s\",\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_FALLBACKTOPIC "\":\"%s\",\"" D_CMND_GROUPTOPIC "\":\"%s\"}"), + Response_P(PSTR("{\"" D_CMND_MODULE "\":\"%s\",\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_FALLBACKTOPIC "\":\"%s\",\"" D_CMND_GROUPTOPIC "\":\"%s\"}"), ModuleName().c_str(), my_version, my_image, GetFallbackTopic_P(stopic, CMND, ""), Settings.mqtt_grptopic); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "1")); #ifdef USE_WEBSERVER if (Settings.webserver) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_WEBSERVER_MODE "\":\"%s\",\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\"}"), + Response_P(PSTR("{\"" D_JSON_WEBSERVER_MODE "\":\"%s\",\"" D_CMND_HOSTNAME "\":\"%s\",\"" D_CMND_IPADDRESS "\":\"%s\"}"), (2 == Settings.webserver) ? D_ADMIN : D_USER, my_hostname, WiFi.localIP().toString().c_str()); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "2")); } #endif // USE_WEBSERVER - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_RESTARTREASON "\":\"%s\"}"), - (GetResetReason() == "Exception") ? ESP.getResetInfo().c_str() : GetResetReason().c_str()); + Response_P(PSTR("{\"" D_JSON_RESTARTREASON "\":\"%s\"}"), (GetResetReason() == "Exception") ? ESP.getResetInfo().c_str() : GetResetReason().c_str()); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "3")); for (uint8_t i = 1; i <= devices_present; i++) { MqttPublishPowerState(i); @@ -438,7 +437,7 @@ void MqttReconnect(void) if (strlen(Settings.mqtt_pwd) > 0) mqtt_pwd = Settings.mqtt_pwd; GetTopic_P(stopic, TELE, mqtt_topic, S_LWT); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_OFFLINE); + Response_P(S_OFFLINE); #ifdef USE_MQTT_TLS EspClient = WiFiClientSecure(); // Wifi Secure Client reconnect issue 4497 (https://github.com/esp8266/Arduino/issues/4497) @@ -514,21 +513,21 @@ bool MqttCommand(void) strlcpy(Settings.mqtt_host, (SC_CLEAR == Shortcut(dataBuf)) ? "" : (SC_DEFAULT == Shortcut(dataBuf)) ? MQTT_HOST : dataBuf, sizeof(Settings.mqtt_host)); restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.mqtt_host); + Response_P(S_JSON_COMMAND_SVALUE, command, Settings.mqtt_host); } else if (CMND_MQTTPORT == command_code) { if (payload16 > 0) { Settings.mqtt_port = (1 == payload16) ? MQTT_PORT : payload16; restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.mqtt_port); + 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; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, 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]))) { @@ -537,7 +536,7 @@ bool MqttCommand(void) } strlcpy(Settings.state_text[index -1], dataBuf, sizeof(Settings.state_text[0])); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, GetStateText(index -1)); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, GetStateText(index -1)); } #ifdef USE_MQTT_TLS else if ((CMND_MQTTFINGERPRINT == command_code) && (index > 0) && (index <= 2)) { @@ -554,7 +553,7 @@ bool MqttCommand(void) for (uint8_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]); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, fingerprint); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, fingerprint); } #endif else if (CMND_MQTTCLIENT == command_code) { @@ -562,22 +561,22 @@ bool MqttCommand(void) strlcpy(Settings.mqtt_client, (SC_DEFAULT == Shortcut(dataBuf)) ? MQTT_CLIENT_ID : dataBuf, sizeof(Settings.mqtt_client)); restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.mqtt_client); + Response_P(S_JSON_COMMAND_SVALUE, command, Settings.mqtt_client); } 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; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.mqtt_user); + 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)); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.mqtt_pwd); + Response_P(S_JSON_COMMAND_SVALUE, command, Settings.mqtt_pwd); restart_flag = 2; } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_ASTERIX, command); + Response_P(S_JSON_COMMAND_ASTERIX, command); } } else if (CMND_FULLTOPIC == command_code) { @@ -586,13 +585,13 @@ bool MqttCommand(void) 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)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), (Settings.flag.mqtt_offline) ? S_OFFLINE : ""); + 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; } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.mqtt_fulltopic); + 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]))) { @@ -601,7 +600,7 @@ bool MqttCommand(void) // 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; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.mqtt_prefix[index -1]); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.mqtt_prefix[index -1]); } else if (CMND_PUBLISH == command_code) { if (data_len > 0) { @@ -615,7 +614,7 @@ bool MqttCommand(void) mqtt_data[0] = '\0'; } MqttPublishDirect(stemp1, (index == 2)); -// snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); +// Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); mqtt_data[0] = '\0'; } } @@ -627,7 +626,7 @@ bool MqttCommand(void) strlcpy(Settings.mqtt_grptopic, (SC_DEFAULT == Shortcut(dataBuf)) ? MQTT_GRPTOPIC : dataBuf, sizeof(Settings.mqtt_grptopic)); restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.mqtt_grptopic); + 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))) { @@ -635,13 +634,13 @@ bool MqttCommand(void) 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)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), (Settings.flag.mqtt_offline) ? S_OFFLINE : ""); + 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; } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.mqtt_topic); + 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))) { @@ -654,7 +653,7 @@ bool MqttCommand(void) default: strlcpy(Settings.button_topic, dataBuf, sizeof(Settings.button_topic)); } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, 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))) { @@ -667,7 +666,7 @@ bool MqttCommand(void) default: strlcpy(Settings.switch_topic, dataBuf, sizeof(Settings.switch_topic)); } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, Settings.switch_topic); + Response_P(S_JSON_COMMAND_SVALUE, command, Settings.switch_topic); } else if (CMND_BUTTONRETAIN == command_code) { if ((payload >= 0) && (payload <= 1)) { @@ -678,7 +677,7 @@ bool MqttCommand(void) } Settings.flag.mqtt_button_retain = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.mqtt_button_retain)); + Response_P(S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.mqtt_button_retain)); } else if (CMND_SWITCHRETAIN == command_code) { if ((payload >= 0) && (payload <= 1)) { @@ -689,7 +688,7 @@ bool MqttCommand(void) } Settings.flag.mqtt_switch_retain = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.mqtt_switch_retain)); + Response_P(S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.mqtt_switch_retain)); } else if (CMND_POWERRETAIN == command_code) { if ((payload >= 0) && (payload <= 1)) { @@ -702,7 +701,7 @@ bool MqttCommand(void) } Settings.flag.mqtt_power_retain = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.mqtt_power_retain)); + Response_P(S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.mqtt_power_retain)); } else if (CMND_SENSORRETAIN == command_code) { if ((payload >= 0) && (payload <= 1)) { @@ -713,7 +712,7 @@ bool MqttCommand(void) } Settings.flag.mqtt_sensor_retain = payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.mqtt_sensor_retain)); + Response_P(S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag.mqtt_sensor_retain)); } else serviced = false; // Unknown command @@ -790,7 +789,7 @@ void MqttSaveSettings(void) strlcpy(stemp2, (!strlen(tmp)) ? MQTT_FULLTOPIC : tmp, sizeof(stemp2)); MakeValidMqtt(1,stemp2); if ((strcmp(stemp, Settings.mqtt_topic)) || (strcmp(stemp2, Settings.mqtt_fulltopic))) { - snprintf_P(mqtt_data, sizeof(mqtt_data), (Settings.flag.mqtt_offline) ? S_OFFLINE : ""); + Response_P((Settings.flag.mqtt_offline) ? S_OFFLINE : ""); MqttPublishPrefixTopic_P(TELE, S_LWT, true); // Offline or remove previous retained topic } strlcpy(Settings.mqtt_topic, stemp, sizeof(Settings.mqtt_topic)); diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index b2393a311..69d93b244 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -201,34 +201,34 @@ void EnergyMarginCheck(void) // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("NRG: W %d, U %d, I %d"), energy_power_u, energy_voltage_u, energy_current_u); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{")); + Response_P(PSTR("{")); jsonflg = false; if (EnergyMargin(false, Settings.energy_min_power, energy_power_u, flag, energy_min_power_flag)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_POWERLOW "\":\"%s\""), mqtt_data, (jsonflg)?",":"", GetStateText(flag)); + ResponseAppend_P(PSTR("%s\"" D_CMND_POWERLOW "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); jsonflg = true; } if (EnergyMargin(true, Settings.energy_max_power, energy_power_u, flag, energy_max_power_flag)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_POWERHIGH "\":\"%s\""), mqtt_data, (jsonflg)?",":"", GetStateText(flag)); + ResponseAppend_P(PSTR("%s\"" D_CMND_POWERHIGH "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); jsonflg = true; } if (EnergyMargin(false, Settings.energy_min_voltage, energy_voltage_u, flag, energy_min_voltage_flag)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_VOLTAGELOW "\":\"%s\""), mqtt_data, (jsonflg)?",":"", GetStateText(flag)); + ResponseAppend_P(PSTR("%s\"" D_CMND_VOLTAGELOW "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); jsonflg = true; } if (EnergyMargin(true, Settings.energy_max_voltage, energy_voltage_u, flag, energy_max_voltage_flag)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_VOLTAGEHIGH "\":\"%s\""), mqtt_data, (jsonflg)?",":"", GetStateText(flag)); + ResponseAppend_P(PSTR("%s\"" D_CMND_VOLTAGEHIGH "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); jsonflg = true; } if (EnergyMargin(false, Settings.energy_min_current, energy_current_u, flag, energy_min_current_flag)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_CURRENTLOW "\":\"%s\""), mqtt_data, (jsonflg)?",":"", GetStateText(flag)); + ResponseAppend_P(PSTR("%s%s\"" D_CMND_CURRENTLOW "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); jsonflg = true; } if (EnergyMargin(true, Settings.energy_max_current, energy_current_u, flag, energy_max_current_flag)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_CMND_CURRENTHIGH "\":\"%s\""), mqtt_data, (jsonflg)?",":"", GetStateText(flag)); + ResponseAppend_P(PSTR("%s%s\"" D_CMND_CURRENTHIGH "\":\"%s\""), (jsonflg)?",":"", GetStateText(flag)); jsonflg = true; } if (jsonflg) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_MARGINS), MQTT_TELE_RETAIN); EnergyMqttShow(); } @@ -243,7 +243,7 @@ void EnergyMarginCheck(void) } else { energy_mplh_counter--; if (!energy_mplh_counter) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_MAXPOWERREACHED "\":\"%d%s\"}"), energy_power_u, (Settings.flag.value_units) ? " " D_UNIT_WATT : ""); + Response_P(PSTR("{\"" D_JSON_MAXPOWERREACHED "\":\"%d%s\"}"), energy_power_u, (Settings.flag.value_units) ? " " D_UNIT_WATT : ""); MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); EnergyMqttShow(); ExecuteCommandPower(1, POWER_OFF, SRC_MAXPOWER); @@ -266,11 +266,11 @@ void EnergyMarginCheck(void) if (energy_mplr_counter) { energy_mplr_counter--; if (energy_mplr_counter) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_POWERMONITOR "\":\"%s\"}"), GetStateText(1)); + Response_P(PSTR("{\"" D_JSON_POWERMONITOR "\":\"%s\"}"), GetStateText(1)); MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_POWERMONITOR)); ExecuteCommandPower(1, POWER_ON, SRC_MAXPOWER); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_MAXPOWERREACHEDRETRY "\":\"%s\"}"), GetStateText(0)); + Response_P(PSTR("{\"" D_JSON_MAXPOWERREACHEDRETRY "\":\"%s\"}"), GetStateText(0)); MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); EnergyMqttShow(); } @@ -284,14 +284,14 @@ void EnergyMarginCheck(void) energy_daily_u = (uint16_t)(energy_daily * 1000); if (!energy_max_energy_state && (RtcTime.hour == Settings.energy_max_energy_start)) { energy_max_energy_state = 1; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_ENERGYMONITOR "\":\"%s\"}"), GetStateText(1)); + Response_P(PSTR("{\"" D_JSON_ENERGYMONITOR "\":\"%s\"}"), GetStateText(1)); MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_JSON_ENERGYMONITOR)); ExecuteCommandPower(1, POWER_ON, SRC_MAXENERGY); } else if ((1 == energy_max_energy_state) && (energy_daily_u >= Settings.energy_max_energy)) { energy_max_energy_state = 2; dtostrfd(energy_daily, 3, mqtt_data); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_MAXENERGYREACHED "\":\"%s%s\"}"), mqtt_data, (Settings.flag.value_units) ? " " D_UNIT_KILOWATTHOUR : ""); + Response_P(PSTR("{\"" D_JSON_MAXENERGYREACHED "\":\"%s%s\"}"), mqtt_data, (Settings.flag.value_units) ? " " D_UNIT_KILOWATTHOUR : ""); MqttPublishPrefixTopic_P(STAT, S_RSLT_WARNING); EnergyMqttShow(); ExecuteCommandPower(1, POWER_OFF, SRC_MAXENERGY); @@ -305,12 +305,12 @@ void EnergyMarginCheck(void) void EnergyMqttShow(void) { // {"Time":"2017-12-16T11:48:55","ENERGY":{"Total":0.212,"Yesterday":0.000,"Today":0.014,"Period":2.0,"Power":22.0,"Factor":1.00,"Voltage":213.6,"Current":0.100}} - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); + Response_P(PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); int tele_period_save = tele_period; tele_period = 2; EnergyShow(true); tele_period = tele_period_save; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); energy_power_delta = 0; } @@ -414,7 +414,7 @@ bool EnergyCommand(void) char energy_yesterday_chr[33]; dtostrfd((float)Settings.energy_kWhyesterday / 100000, Settings.flag2.energy_resolution, energy_yesterday_chr); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s}}"), + Response_P(PSTR("{\"%s\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s}}"), command, energy_total_chr, energy_yesterday_chr, energy_daily_chr); status_flag = true; } @@ -519,9 +519,9 @@ bool EnergyCommand(void) } if (Settings.flag.value_units) { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_LVALUE_SPACE_UNIT, command, nvalue, GetTextIndexed(sunit, sizeof(sunit), unit, kUnitNames)); + Response_P(S_JSON_COMMAND_LVALUE_SPACE_UNIT, command, nvalue, GetTextIndexed(sunit, sizeof(sunit), unit, kUnitNames)); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_LVALUE, command, nvalue); + Response_P(S_JSON_COMMAND_LVALUE, command, nvalue); } } @@ -637,13 +637,13 @@ void EnergyShow(bool json) } if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL_START_TIME "\":\"%s\",\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s%s,\"" D_JSON_POWERUSAGE "\":%s"), - mqtt_data, GetDateAndTime(DT_ENERGY).c_str(), energy_total_chr, energy_yesterday_chr, energy_daily_chr, (show_energy_period) ? speriod : "", active_power_chr); + ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL_START_TIME "\":\"%s\",\"" D_JSON_TOTAL "\":%s,\"" D_JSON_YESTERDAY "\":%s,\"" D_JSON_TODAY "\":%s%s,\"" D_JSON_POWERUSAGE "\":%s"), + GetDateAndTime(DT_ENERGY).c_str(), energy_total_chr, energy_yesterday_chr, energy_daily_chr, (show_energy_period) ? speriod : "", active_power_chr); if (!energy_type_dc) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_APPARENT_POWERUSAGE "\":%s,\"" D_JSON_REACTIVE_POWERUSAGE "\":%s,\"" D_JSON_POWERFACTOR "\":%s%s"), - mqtt_data, apparent_power_chr, reactive_power_chr, power_factor_chr, (!isnan(energy_frequency)) ? sfrequency : ""); + ResponseAppend_P(PSTR(",\"" D_JSON_APPARENT_POWERUSAGE "\":%s,\"" D_JSON_REACTIVE_POWERUSAGE "\":%s,\"" D_JSON_POWERFACTOR "\":%s%s"), + apparent_power_chr, reactive_power_chr, power_factor_chr, (!isnan(energy_frequency)) ? sfrequency : ""); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s}"), mqtt_data, voltage_chr, current_chr); + ResponseAppend_P(PSTR(",\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s}"), voltage_chr, current_chr); #ifdef USE_DOMOTICZ if (show_energy_period) { // Only send if telemetry diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 532ecc42d..6a4c11db7 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -740,43 +740,42 @@ void LightState(uint8_t append) int16_t h,s,b; if (append) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); + ResponseAppend_P(PSTR(",")); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{")); + Response_P(PSTR("{")); } GetPowerDevice(scommand, light_device, sizeof(scommand), Settings.flag.device_index_enable); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"%s\":\"%s\",\"" D_CMND_DIMMER "\":%d"), - mqtt_data, scommand, GetStateText(light_power), Settings.light_dimmer); + ResponseAppend_P(PSTR("\"%s\":\"%s\",\"" D_CMND_DIMMER "\":%d"), scommand, GetStateText(light_power), Settings.light_dimmer); if (light_subtype > LST_SINGLE) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_COLOR "\":\"%s\""), mqtt_data, LightGetColor(0, scolor)); + ResponseAppend_P(PSTR(",\"" D_CMND_COLOR "\":\"%s\""), LightGetColor(0, scolor)); // Add status for HSB LightGetHsb(&hsb[0],&hsb[1],&hsb[2], false); // Scale these percentages up to the numbers expected by the client h = round(hsb[0] * 360); s = round(hsb[1] * 100); b = round(hsb[2] * 100); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_HSBCOLOR "\":\"%d,%d,%d\""), mqtt_data, h,s,b); + ResponseAppend_P(PSTR(",\"" D_CMND_HSBCOLOR "\":\"%d,%d,%d\""), h,s,b); // Add status for each channel - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_CHANNEL "\":[" ), mqtt_data); + ResponseAppend_P(PSTR(",\"" D_CMND_CHANNEL "\":[" )); for (uint8_t i = 0; i < light_subtype; i++) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s%d" ), mqtt_data, (i > 0 ? "," : ""), light_current_color[i] * 100 / 255); + ResponseAppend_P(PSTR("%s%d" ), (i > 0 ? "," : ""), light_current_color[i] * 100 / 255); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s]" ), mqtt_data); + ResponseAppend_P(PSTR("%s]")); } if ((LST_COLDWARM == light_subtype) || (LST_RGBWC == light_subtype)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_COLORTEMPERATURE "\":%d"), mqtt_data, LightGetColorTemp()); + ResponseAppend_P(PSTR(",\"" D_CMND_COLORTEMPERATURE "\":%d"), LightGetColorTemp()); } if (append) { if (light_subtype >= LST_RGB) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_SCHEME "\":%d"), mqtt_data, Settings.light_scheme); + ResponseAppend_P(PSTR(",\"" D_CMND_SCHEME "\":%d"), Settings.light_scheme); } if (LT_WS2812 == light_type) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_WIDTH "\":%d"), mqtt_data, Settings.light_width); + ResponseAppend_P(PSTR(",\"" D_CMND_WIDTH "\":%d"), Settings.light_width); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_CMND_FADE "\":\"%s\",\"" D_CMND_SPEED "\":%d,\"" D_CMND_LEDTABLE "\":\"%s\""), - mqtt_data, GetStateText(Settings.light_fade), Settings.light_speed, GetStateText(Settings.light_correction)); + ResponseAppend_P(PSTR(",\"" D_CMND_FADE "\":\"%s\",\"" D_CMND_SPEED "\":%d,\"" D_CMND_LEDTABLE "\":\"%s\""), + GetStateText(Settings.light_fade), Settings.light_speed, GetStateText(Settings.light_correction)); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); } } @@ -949,7 +948,7 @@ void LightAnimate(void) light_new_color[i] = light_current_color[i]; } } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_WAKEUP "\":\"" D_JSON_DONE "\"}")); + Response_P(PSTR("{\"" D_CMND_WAKEUP "\":\"" D_JSON_DONE "\"}")); MqttPublishPrefixTopic_P(TELE, PSTR(D_CMND_WAKEUP)); light_wakeup_active = 0; Settings.light_scheme = LS_POWER; @@ -1319,7 +1318,7 @@ bool LightCommand(void) } } if (!valid_entry && (XdrvMailbox.index <= 2)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, LightGetColor(0, scolor)); + Response_P(S_JSON_COMMAND_SVALUE, command, LightGetColor(0, scolor)); } if (XdrvMailbox.index >= 3) { scolor[0] = '\0'; @@ -1330,7 +1329,7 @@ bool LightCommand(void) snprintf_P(scolor, 25, PSTR("%s%02X"), scolor, Settings.ws_color[XdrvMailbox.index -3][i]); } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, scolor); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, scolor); } } else if ((CMND_CHANNEL == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= light_subtype ) ) { @@ -1340,7 +1339,7 @@ bool LightCommand(void) LightSetColor(); coldim = true; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, light_current_color[XdrvMailbox.index -1] * 100 / 255); + Response_P(S_JSON_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, light_current_color[XdrvMailbox.index -1] * 100 / 255); } else if ((CMND_HSBCOLOR == command_code) && ( light_subtype >= LST_RGB)) { bool validHSB = (XdrvMailbox.data_len > 0); @@ -1405,7 +1404,7 @@ bool LightCommand(void) Ws2812ForceUpdate(); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, Ws2812GetColor(XdrvMailbox.index, scolor)); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, Ws2812GetColor(XdrvMailbox.index, scolor)); } else if ((CMND_PIXELS == command_code) && (LT_WS2812 == light_type)) { if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= WS2812_MAX_LEDS)) { @@ -1414,25 +1413,25 @@ bool LightCommand(void) Ws2812Clear(); light_update = 1; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.light_pixels); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.light_pixels); } else if ((CMND_ROTATION == command_code) && (LT_WS2812 == light_type)) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < Settings.light_pixels)) { Settings.light_rotation = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.light_rotation); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.light_rotation); } else if ((CMND_WIDTH == command_code) && (LT_WS2812 == light_type) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 4)) { if (1 == XdrvMailbox.index) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 4)) { Settings.light_width = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.light_width); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.light_width); } else { if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 32)) { Settings.ws_width[XdrvMailbox.index -2] = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, Settings.ws_width[XdrvMailbox.index -2]); + Response_P(S_JSON_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, Settings.ws_width[XdrvMailbox.index -2]); } } #endif // USE_WS2812 ************************************************************************ @@ -1454,7 +1453,7 @@ bool LightCommand(void) // Publish state message for Hass if (Settings.flag3.hass_tele_on_power) { MqttPublishTeleState(); } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.light_scheme); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.light_scheme); } else if (CMND_WAKEUP == command_code) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { @@ -1463,7 +1462,7 @@ bool LightCommand(void) light_wakeup_active = 3; Settings.light_scheme = LS_WAKEUP; LightPowerOn(); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_STARTED); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_STARTED); } else if ((CMND_COLORTEMPERATURE == command_code) && ((LST_COLDWARM == light_subtype) || (LST_RGBWC == light_subtype))) { // ColorTemp if (option != '\0') { @@ -1479,7 +1478,7 @@ bool LightCommand(void) LightSetColorTemp(XdrvMailbox.payload); coldim = true; } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, LightGetColorTemp()); + Response_P(S_JSON_COMMAND_NVALUE, command, LightGetColorTemp()); } } else if (CMND_DIMMER == command_code) { @@ -1494,7 +1493,7 @@ bool LightCommand(void) light_update = 1; coldim = true; } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.light_dimmer); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.light_dimmer); } } else if (CMND_LEDTABLE == command_code) { @@ -1510,7 +1509,7 @@ bool LightCommand(void) } light_update = 1; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.light_correction)); + Response_P(S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.light_correction)); } else if (CMND_RGBWWTABLE == command_code) { bool validtable = (XdrvMailbox.data_len > 0); @@ -1536,7 +1535,7 @@ bool LightCommand(void) for (uint8_t i = 0; i < LST_RGBWC; i++) { snprintf_P(scolor, 25, PSTR("%s%s%d"), scolor, (i > 0) ? "," : "", Settings.rgbwwTable[i]); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, scolor); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, scolor); } else if (CMND_FADE == command_code) { switch (XdrvMailbox.payload) { @@ -1548,7 +1547,7 @@ bool LightCommand(void) Settings.light_fade ^= 1; break; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.light_fade)); + Response_P(S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.light_fade)); } else if (CMND_SPEED == command_code) { // 1 - fast, 20 - very slow if (('+' == option) && (Settings.light_speed > 1)) { @@ -1560,20 +1559,19 @@ bool LightCommand(void) if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= STATES)) { Settings.light_speed = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.light_speed); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.light_speed); } else if (CMND_WAKEUPDURATION == command_code) { if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 3001)) { Settings.light_wakeup = XdrvMailbox.payload; light_wakeup_active = 0; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.light_wakeup); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.light_wakeup); } else if (CMND_UNDOCA == command_code) { // Theos legacy status LightGetColor(1, scolor); scolor[6] = '\0'; // RGB only - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,%d,%d,%d,%d,%d"), - scolor, Settings.light_fade, Settings.light_correction, Settings.light_scheme, Settings.light_speed, Settings.light_width); + Response_P(PSTR("%s,%d,%d,%d,%d,%d"), scolor, Settings.light_fade, Settings.light_correction, Settings.light_scheme, Settings.light_speed, Settings.light_width); MqttPublishPrefixTopic_P(STAT, XdrvMailbox.topic); mqtt_data[0] = '\0'; } diff --git a/sonoff/xdrv_05_irremote.ino b/sonoff/xdrv_05_irremote.ino index a72bc2764..9592555b8 100644 --- a/sonoff/xdrv_05_irremote.ino +++ b/sonoff/xdrv_05_irremote.ino @@ -131,19 +131,19 @@ void IrReceiveCheck(void) } else { snprintf_P(stemp, sizeof(stemp), PSTR("\"0x%lX\""), (uint32_t)results.value); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_IRRECEIVED "\":{\"" D_JSON_IR_PROTOCOL "\":\"%s\",\"" D_JSON_IR_BITS "\":%d,\"" D_JSON_IR_DATA "\":%s"), + Response_P(PSTR("{\"" D_JSON_IRRECEIVED "\":{\"" D_JSON_IR_PROTOCOL "\":\"%s\",\"" D_JSON_IR_BITS "\":%d,\"" D_JSON_IR_DATA "\":%s"), GetTextIndexed(sirtype, sizeof(sirtype), iridx, kIrRemoteProtocols), results.bits, stemp); if (Settings.flag3.receive_raw) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_IR_RAWDATA "\":["), mqtt_data); + ResponseAppend_P(PSTR(",\"" D_JSON_IR_RAWDATA "\":[")); uint16_t i; for (i = 1; i < results.rawlen; i++) { - if (i > 1) { snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); } + if (i > 1) { ResponseAppend_P(PSTR(",")); } uint32_t usecs; for (usecs = results.rawbuf[i] * kRawTick; usecs > UINT16_MAX; usecs -= UINT16_MAX) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%d,0,"), mqtt_data, UINT16_MAX); + ResponseAppend_P(PSTR("%d,0,"), UINT16_MAX); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%d"), mqtt_data, usecs); + ResponseAppend_P(PSTR("%d"), usecs); if (strlen(mqtt_data) > sizeof(mqtt_data) - 40) { break; } // Quit if char string becomes too long } uint16_t extended_length = results.rawlen - 1; @@ -152,10 +152,10 @@ void IrReceiveCheck(void) // Add two extra entries for multiple larger than UINT16_MAX it is. extended_length += (usecs / (UINT16_MAX + 1)) * 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s],\"" D_JSON_IR_RAWDATA "Info\":[%d,%d,%d]"), mqtt_data, extended_length, i -1, results.overflow); + ResponseAppend_P(PSTR("],\"" D_JSON_IR_RAWDATA "Info\":[%d,%d,%d]"), extended_length, i -1, results.overflow); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}}"), mqtt_data); + ResponseAppend_P(PSTR("}}")); MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_IRRECEIVED)); if (iridx) { @@ -516,7 +516,7 @@ bool IrSendCommand(void) } else if (CMND_IRSEND == command_code) { if (XdrvMailbox.data_len) { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); if (!strstr(XdrvMailbox.data, "{")) { // If no JSON it must be rawdata // IRSend frequency, rawdata, rawdata ... @@ -540,11 +540,11 @@ bool IrSendCommand(void) irsend_active = true; irsend->sendRaw(raw_array, count, freq); if (!count) { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_FAILED); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_FAILED); } } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_RAWDATA); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_RAWDATA); } } else { @@ -553,7 +553,7 @@ bool IrSendCommand(void) StaticJsonBuffer<128> jsonBuf; JsonObject &root = jsonBuf.parseObject(dataBufUc); if (!root.success()) { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_JSON); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_JSON); } else { // IRsend { "protocol": "SAMSUNG", "bits": 32, "data": 551502015 } @@ -588,7 +588,7 @@ bool IrSendCommand(void) irsend->sendPanasonic(bits, data); break; default: irsend_active = false; - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_PROTOCOL_NOT_SUPPORTED); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_PROTOCOL_NOT_SUPPORTED); } } else { @@ -601,7 +601,7 @@ bool IrSendCommand(void) error = true; } if (error) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_NO " " D_JSON_IR_PROTOCOL ", " D_JSON_IR_BITS " " D_JSON_OR " " D_JSON_IR_DATA "\"}")); + Response_P(PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_NO " " D_JSON_IR_PROTOCOL ", " D_JSON_IR_BITS " " D_JSON_OR " " D_JSON_IR_DATA "\"}")); } } #ifdef USE_IR_HVAC @@ -618,10 +618,10 @@ bool IrSendCommand(void) StaticJsonBuffer<164> jsonBufer; JsonObject &root = jsonBufer.parseObject(dataBufUc); if (!root.success()) { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_JSON); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_JSON); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); HVAC_Vendor = root[D_JSON_IRHVAC_VENDOR]; HVAC_Power = root[D_JSON_IRHVAC_POWER]; HVAC_Mode = root[D_JSON_IRHVAC_MODE]; @@ -650,7 +650,7 @@ bool IrSendCommand(void) error = true; } if (error) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_IRHVAC "\":\"" D_JSON_WRONG " " D_JSON_IRHVAC_VENDOR ", " D_JSON_IRHVAC_MODE " " D_JSON_OR " " D_JSON_IRHVAC_FANSPEED "\"}")); + Response_P(PSTR("{\"" D_CMND_IRHVAC "\":\"" D_JSON_WRONG " " D_JSON_IRHVAC_VENDOR ", " D_JSON_IRHVAC_MODE " " D_JSON_OR " " D_JSON_IRHVAC_FANSPEED "\"}")); } } #endif // USE_IR_HVAC diff --git a/sonoff/xdrv_06_snfbridge.ino b/sonoff/xdrv_06_snfbridge.ino index c4b4d209b..14947fd77 100644 --- a/sonoff/xdrv_06_snfbridge.ino +++ b/sonoff/xdrv_06_snfbridge.ino @@ -208,17 +208,17 @@ void SonoffBridgeReceivedRaw(void) if (0xB1 == serial_in_buffer[1]) { buckets = serial_in_buffer[2] << 1; } // Bucket sniffing - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RFRAW "\":{\"" D_JSON_DATA "\":\"")); + Response_P(PSTR("{\"" D_CMND_RFRAW "\":{\"" D_JSON_DATA "\":\"")); for (int i = 0; i < serial_in_byte_counter; i++) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%02X"), mqtt_data, serial_in_buffer[i]); + ResponseAppend_P(PSTR("%02X"), serial_in_buffer[i]); if (0xB1 == serial_in_buffer[1]) { if ((i > 3) && buckets) { buckets--; } if ((i < 3) || (buckets % 2) || (i == serial_in_byte_counter -2)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s "), mqtt_data); + ResponseAppend_P(PSTR(" ")); } } } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"}}"), mqtt_data); + ResponseAppend_P(PSTR("\"}}")); MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_CMND_RFRAW)); XdrvRulesProcess(); } @@ -228,7 +228,7 @@ void SonoffBridgeReceivedRaw(void) void SonoffBridgeLearnFailed(void) { sonoff_bridge_learn_active = 0; - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, D_CMND_RFKEY, sonoff_bridge_learn_key, D_JSON_LEARN_FAILED); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, D_CMND_RFKEY, sonoff_bridge_learn_key, D_JSON_LEARN_FAILED); MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_RFKEY)); } @@ -254,7 +254,7 @@ void SonoffBridgeReceived(void) for (uint8_t i = 0; i < 9; i++) { Settings.rf_code[sonoff_bridge_learn_key][i] = serial_in_buffer[i +1]; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, D_CMND_RFKEY, sonoff_bridge_learn_key, D_JSON_LEARNED); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, D_CMND_RFKEY, sonoff_bridge_learn_key, D_JSON_LEARNED); MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_RFKEY)); } else { SonoffBridgeLearnFailed(); @@ -288,7 +288,7 @@ void SonoffBridgeReceived(void) } else { snprintf_P(stemp, sizeof(stemp), PSTR("\"%06X\""), received_id); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_SYNC "\":%d,\"" D_JSON_LOW "\":%d,\"" D_JSON_HIGH "\":%d,\"" D_JSON_DATA "\":%s,\"" D_CMND_RFKEY "\":%s}}"), + Response_P(PSTR("{\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_SYNC "\":%d,\"" D_JSON_LOW "\":%d,\"" D_JSON_HIGH "\":%d,\"" D_JSON_DATA "\":%s,\"" D_CMND_RFKEY "\":%s}}"), sync_time, low_time, high_time, stemp, rfkey); MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_RFRECEIVED)); XdrvRulesProcess(); @@ -470,7 +470,7 @@ bool SonoffBridgeCommand(void) } else { snprintf_P(stemp, sizeof(stemp), PSTR("\"#%X\""), code); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_XVALUE, command, stemp); + Response_P(S_JSON_COMMAND_XVALUE, command, stemp); } else if ((CMND_RFKEY == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 16)) { unsigned long now = millis(); @@ -478,11 +478,11 @@ bool SonoffBridgeCommand(void) sonoff_bridge_learn_active = 0; if (2 == XdrvMailbox.payload) { // Learn RF data SonoffBridgeLearn(XdrvMailbox.index); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, D_JSON_START_LEARNING); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, D_JSON_START_LEARNING); } else if (3 == XdrvMailbox.payload) { // Unlearn RF data Settings.rf_code[XdrvMailbox.index][0] = 0; // Reset sync_time MSB - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, D_JSON_SET_TO_DEFAULT); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, D_JSON_SET_TO_DEFAULT); } else if (4 == XdrvMailbox.payload) { // Save RF data provided by RFSync, RfLow, RfHigh and last RfCode for (uint8_t i = 0; i < 6; i++) { @@ -491,7 +491,7 @@ bool SonoffBridgeCommand(void) Settings.rf_code[XdrvMailbox.index][6] = (sonoff_bridge_last_send_code >> 16) & 0xff; Settings.rf_code[XdrvMailbox.index][7] = (sonoff_bridge_last_send_code >> 8) & 0xff; Settings.rf_code[XdrvMailbox.index][8] = sonoff_bridge_last_send_code & 0xff; - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, D_JSON_SAVED); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, D_JSON_SAVED); } else if (5 == XdrvMailbox.payload) { // Show default or learned RF data uint8_t key = XdrvMailbox.index; uint8_t index = (0 == Settings.rf_code[key][0]) ? 0 : key; // Use default if sync_time MSB = 0 @@ -505,19 +505,19 @@ bool SonoffBridgeCommand(void) } else { code |= Settings.rf_code[index][8]; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s%d\":{\"" D_JSON_SYNC "\":%d,\"" D_JSON_LOW "\":%d,\"" D_JSON_HIGH "\":%d,\"" D_JSON_DATA "\":\"%06X\"}}"), + Response_P(PSTR("{\"%s%d\":{\"" D_JSON_SYNC "\":%d,\"" D_JSON_LOW "\":%d,\"" D_JSON_HIGH "\":%d,\"" D_JSON_DATA "\":\"%06X\"}}"), command, XdrvMailbox.index, sync_time, low_time, high_time, code); } else { if ((1 == XdrvMailbox.payload) || (0 == Settings.rf_code[XdrvMailbox.index][0])) { // Test sync_time MSB SonoffBridgeSend(0, XdrvMailbox.index); // Send default RF data - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, D_JSON_DEFAULT_SENT); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, D_JSON_DEFAULT_SENT); } else { SonoffBridgeSend(XdrvMailbox.index, 0); // Send learned RF data - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, D_JSON_LEARNED_SENT); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, XdrvMailbox.index, D_JSON_LEARNED_SENT); } } } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, sonoff_bridge_learn_key, D_JSON_LEARNING_ACTIVE); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, sonoff_bridge_learn_key, D_JSON_LEARNING_ACTIVE); } } else if (CMND_RFRAW == command_code) { @@ -548,7 +548,7 @@ bool SonoffBridgeCommand(void) sonoff_bridge_receive_raw_flag = 1; } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(sonoff_bridge_receive_raw_flag)); + Response_P(S_JSON_COMMAND_SVALUE, command, GetStateText(sonoff_bridge_receive_raw_flag)); } else serviced = false; // Unknown command return serviced; diff --git a/sonoff/xdrv_07_domoticz.ino b/sonoff/xdrv_07_domoticz.ino index 799b2d4b8..21c191699 100644 --- a/sonoff/xdrv_07_domoticz.ino +++ b/sonoff/xdrv_07_domoticz.ino @@ -79,8 +79,7 @@ void MqttPublishDomoticzFanState() int fan_speed = GetFanspeed(); snprintf_P(svalue, sizeof(svalue), PSTR("%d"), fan_speed * 10); - snprintf_P(mqtt_data, sizeof(mqtt_data), DOMOTICZ_MESSAGE, - (int)Settings.domoticz_relay_idx[1], (0 == fan_speed) ? 0 : 2, svalue, DomoticzBatteryQuality(), DomoticzRssiQuality()); + Response_P(DOMOTICZ_MESSAGE, (int)Settings.domoticz_relay_idx[1], (0 == fan_speed) ? 0 : 2, svalue, DomoticzBatteryQuality(), DomoticzRssiQuality()); MqttPublish(domoticz_in_topic); fan_debounce = millis(); @@ -106,8 +105,7 @@ void MqttPublishDomoticzPowerState(uint8_t device) char svalue[8]; // Dimmer value snprintf_P(svalue, sizeof(svalue), PSTR("%d"), Settings.light_dimmer); - snprintf_P(mqtt_data, sizeof(mqtt_data), DOMOTICZ_MESSAGE, - (int)Settings.domoticz_relay_idx[device -1], (power & (1 << (device -1))) ? 1 : 0, (light_type) ? svalue : "", DomoticzBatteryQuality(), DomoticzRssiQuality()); + Response_P(DOMOTICZ_MESSAGE, (int)Settings.domoticz_relay_idx[device -1], (power & (1 << (device -1))) ? 1 : 0, (light_type) ? svalue : "", DomoticzBatteryQuality(), DomoticzRssiQuality()); MqttPublish(domoticz_in_topic); } } @@ -301,31 +299,31 @@ bool DomoticzCommand(void) Settings.domoticz_relay_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DOMOTICZ_COMMAND_INDEX_LVALUE, command, XdrvMailbox.index, Settings.domoticz_relay_idx[XdrvMailbox.index -1]); + Response_P(S_JSON_DOMOTICZ_COMMAND_INDEX_LVALUE, command, XdrvMailbox.index, Settings.domoticz_relay_idx[XdrvMailbox.index -1]); } else if ((CMND_KEYIDX == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DOMOTICZ_IDX)) { if (XdrvMailbox.payload >= 0) { Settings.domoticz_key_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DOMOTICZ_COMMAND_INDEX_LVALUE, command, XdrvMailbox.index, Settings.domoticz_key_idx[XdrvMailbox.index -1]); + Response_P(S_JSON_DOMOTICZ_COMMAND_INDEX_LVALUE, command, XdrvMailbox.index, Settings.domoticz_key_idx[XdrvMailbox.index -1]); } else if ((CMND_SWITCHIDX == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_DOMOTICZ_IDX)) { if (XdrvMailbox.payload >= 0) { Settings.domoticz_switch_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DOMOTICZ_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, Settings.domoticz_switch_idx[XdrvMailbox.index -1]); + Response_P(S_JSON_DOMOTICZ_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, Settings.domoticz_switch_idx[XdrvMailbox.index -1]); } else if ((CMND_SENSORIDX == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= DZ_MAX_SENSORS)) { if (XdrvMailbox.payload >= 0) { Settings.domoticz_sensor_idx[XdrvMailbox.index -1] = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DOMOTICZ_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, Settings.domoticz_sensor_idx[XdrvMailbox.index -1]); + Response_P(S_JSON_DOMOTICZ_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, Settings.domoticz_sensor_idx[XdrvMailbox.index -1]); } else if (CMND_UPDATETIMER == command_code) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) { Settings.domoticz_update_timer = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_DOMOTICZ "%s\":%d}"), command, Settings.domoticz_update_timer); + Response_P(PSTR("{\"" D_CMND_DOMOTICZ "%s\":%d}"), command, Settings.domoticz_update_timer); } else serviced = false; // Unknown command } @@ -340,7 +338,7 @@ bool DomoticzSendKey(uint8_t key, uint8_t device, uint8_t state, uint8_t svalflg if (device <= MAX_DOMOTICZ_IDX) { if ((Settings.domoticz_key_idx[device -1] || Settings.domoticz_switch_idx[device -1]) && (svalflg)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"command\":\"switchlight\",\"idx\":%d,\"switchcmd\":\"%s\"}"), + Response_P(PSTR("{\"command\":\"switchlight\",\"idx\":%d,\"switchcmd\":\"%s\"}"), (key) ? Settings.domoticz_switch_idx[device -1] : Settings.domoticz_key_idx[device -1], (state) ? (2 == state) ? "Toggle" : "On" : "Off"); MqttPublish(domoticz_in_topic); result = 1; @@ -375,14 +373,14 @@ uint8_t DomoticzHumidityState(char *hum) void DomoticzSensor(uint8_t idx, char *data) { if (Settings.domoticz_sensor_idx[idx]) { - char dmess[90]; + char dmess[100]; memcpy(dmess, mqtt_data, sizeof(dmess)); if (DZ_AIRQUALITY == idx) { - snprintf_P(mqtt_data, sizeof(dmess), PSTR("{\"idx\":%d,\"nvalue\":%s,\"Battery\":%d,\"RSSI\":%d}"), + Response_P(PSTR("{\"idx\":%d,\"nvalue\":%s,\"Battery\":%d,\"RSSI\":%d}"), Settings.domoticz_sensor_idx[idx], data, DomoticzBatteryQuality(), DomoticzRssiQuality()); } else { - snprintf_P(mqtt_data, sizeof(dmess), DOMOTICZ_MESSAGE, + Response_P(DOMOTICZ_MESSAGE, Settings.domoticz_sensor_idx[idx], 0, data, DomoticzBatteryQuality(), DomoticzRssiQuality()); } MqttPublish(domoticz_in_topic); diff --git a/sonoff/xdrv_08_serial_bridge.ino b/sonoff/xdrv_08_serial_bridge.ino index d39e7a6eb..bf3221025 100644 --- a/sonoff/xdrv_08_serial_bridge.ino +++ b/sonoff/xdrv_08_serial_bridge.ino @@ -68,13 +68,13 @@ void SerialBridgeInput(void) if (serial_bridge_in_byte_counter && (millis() > (serial_bridge_polling_window + SERIAL_POLLING))) { serial_bridge_buffer[serial_bridge_in_byte_counter] = 0; // Serial data completed if (!serial_bridge_raw) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SSERIALRECEIVED "\":\"%s\"}"), serial_bridge_buffer); + Response_P(PSTR("{\"" D_JSON_SSERIALRECEIVED "\":\"%s\"}"), serial_bridge_buffer); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_SSERIALRECEIVED "\":\"")); + Response_P(PSTR("{\"" D_JSON_SSERIALRECEIVED "\":\"")); for (int i = 0; i < serial_bridge_in_byte_counter; i++) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%02x"), mqtt_data, serial_bridge_buffer[i]); + ResponseAppend_P(PSTR("%02x"), serial_bridge_buffer[i]); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"}"), mqtt_data); + ResponseAppend_P(PSTR("\"}")); } MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_SSERIALRECEIVED)); // XdrvRulesProcess(); @@ -144,7 +144,7 @@ bool SerialBridgeCommand(void) codes += 2; } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); } } else if (CMND_SBAUDRATE == command_code) { @@ -155,7 +155,7 @@ bool SerialBridgeCommand(void) Settings.sbaudrate = (1 == XdrvMailbox.payload) ? SOFT_BAUDRATE / 1200 : baud; SerialBridgeSerial->begin(Settings.sbaudrate * 1200); // Reinitialize serial port with new baud rate } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.sbaudrate * 1200); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.sbaudrate * 1200); } else serviced = false; // Unknown command diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index a3ab51a1b..adaaf0603 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -325,11 +325,11 @@ void PrepShowTimer(uint8_t index) sign[0] = '-'; } } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"" D_CMND_TIMER "%d\":{\"" D_JSON_TIMER_ARM "\":%d,\"" D_JSON_TIMER_MODE "\":%d,\"" D_JSON_TIMER_TIME "\":\"%s%02d:%02d\",\"" D_JSON_TIMER_WINDOW "\":%d,\"" D_JSON_TIMER_DAYS "\":\"%s\",\"" D_JSON_TIMER_REPEAT "\":%d%s,\"" D_JSON_TIMER_ACTION "\":%d}"), - mqtt_data, index, xtimer.arm, xtimer.mode, sign, hour, xtimer.time % 60, xtimer.window, days, xtimer.repeat, soutput, xtimer.power); + ResponseAppend_P(PSTR("\"" D_CMND_TIMER "%d\":{\"" D_JSON_TIMER_ARM "\":%d,\"" D_JSON_TIMER_MODE "\":%d,\"" D_JSON_TIMER_TIME "\":\"%s%02d:%02d\",\"" D_JSON_TIMER_WINDOW "\":%d,\"" D_JSON_TIMER_DAYS "\":\"%s\",\"" D_JSON_TIMER_REPEAT "\":%d%s,\"" D_JSON_TIMER_ACTION "\":%d}"), + index, xtimer.arm, xtimer.mode, sign, hour, xtimer.time % 60, xtimer.window, days, xtimer.repeat, soutput, xtimer.power); #else - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"" D_CMND_TIMER "%d\":{\"" D_JSON_TIMER_ARM "\":%d,\"" D_JSON_TIMER_TIME "\":\"%02d:%02d\",\"" D_JSON_TIMER_WINDOW "\":%d,\"" D_JSON_TIMER_DAYS "\":\"%s\",\"" D_JSON_TIMER_REPEAT "\":%d%s,\"" D_JSON_TIMER_ACTION "\":%d}"), - mqtt_data, index, xtimer.arm, xtimer.time / 60, xtimer.time % 60, xtimer.window, days, xtimer.repeat, soutput, xtimer.power); + ResponseAppend_P(PSTR("\"" D_CMND_TIMER "%d\":{\"" D_JSON_TIMER_ARM "\":%d,\"" D_JSON_TIMER_TIME "\":\"%02d:%02d\",\"" D_JSON_TIMER_WINDOW "\":%d,\"" D_JSON_TIMER_DAYS "\":\"%s\",\"" D_JSON_TIMER_REPEAT "\":%d%s,\"" D_JSON_TIMER_ACTION "\":%d}"), + index, xtimer.arm, xtimer.time / 60, xtimer.time % 60, xtimer.window, days, xtimer.repeat, soutput, xtimer.power); #endif // USE_SUNRISE } @@ -365,7 +365,7 @@ bool TimerCommand(void) StaticJsonBuffer<256> jsonBuffer; JsonObject& root = jsonBuffer.parseObject(dataBufUc); if (!root.success()) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_TIMER "%d\":\"" D_JSON_INVALID_JSON "\"}"), index); // JSON decode failed + Response_P(PSTR("{\"" D_CMND_TIMER "%d\":\"" D_JSON_INVALID_JSON "\"}"), index); // JSON decode failed error = 1; } else { @@ -439,16 +439,16 @@ bool TimerCommand(void) } #ifndef USE_RULES } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_TIMER "%d\":\"" D_JSON_TIMER_NO_DEVICE "\"}"), index); // No outputs defined so nothing to control + Response_P(PSTR("{\"" D_CMND_TIMER "%d\":\"" D_JSON_TIMER_NO_DEVICE "\"}"), index); // No outputs defined so nothing to control error = 1; } #endif } } if (!error) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{")); + Response_P(PSTR("{")); PrepShowTimer(index); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); } } else if (CMND_TIMERS == command_code) { @@ -461,21 +461,21 @@ bool TimerCommand(void) } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag3.timers_enable)); + Response_P(S_JSON_COMMAND_SVALUE, command, GetStateText(Settings.flag3.timers_enable)); MqttPublishPrefixTopic_P(RESULT_OR_STAT, command); uint8_t jsflg = 0; uint8_t lines = 1; for (uint8_t i = 0; i < MAX_TIMERS; i++) { if (!jsflg) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_TIMERS "%d\":{"), lines++); + Response_P(PSTR("{\"" D_CMND_TIMERS "%d\":{"), lines++); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,"), mqtt_data); + ResponseAppend_P(PSTR(",")); } jsflg++; PrepShowTimer(i +1); if (jsflg > 3) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}}"), mqtt_data); + ResponseAppend_P(PSTR("}}")); MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_TIMERS)); jsflg = 0; } @@ -489,7 +489,7 @@ bool TimerCommand(void) } char lbuff[33]; dtostrfd(((double)Settings.longitude) /1000000, 6, lbuff); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, lbuff); + Response_P(S_JSON_COMMAND_SVALUE, command, lbuff); } else if (CMND_LATITUDE == command_code) { if (XdrvMailbox.data_len) { @@ -497,7 +497,7 @@ bool TimerCommand(void) } char lbuff[33]; dtostrfd(((double)Settings.latitude) /1000000, 6, lbuff); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, lbuff); + Response_P(S_JSON_COMMAND_SVALUE, command, lbuff); } #endif else serviced = false; // Unknown command diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 4d13bf6b9..b2761a2d4 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -369,7 +369,7 @@ bool RuleSetProcess(uint8_t rule_set, String &event_saved) AddLog_P2(LOG_LEVEL_INFO, PSTR("RUL: %s performs \"%s\""), event_trigger.c_str(), command); -// snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, D_CMND_RULE, D_JSON_INITIATED); +// Response_P(S_JSON_COMMAND_SVALUE, D_CMND_RULE, D_JSON_INITIATED); // MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR(D_CMND_RULE)); ExecuteCommand(command, SRC_RULE); @@ -544,7 +544,7 @@ void RulesEvery100ms(void) tele_period = tele_period_save; if (strlen(mqtt_data)) { mqtt_data[0] = '{'; // {"INA219":{"Voltage":4.494,"Current":0.020,"Power":0.089} - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); RulesProcess(); } } @@ -1139,15 +1139,15 @@ bool RulesCommand(void) } mqtt_data[0] = '\0'; for (uint8_t i = 0; i < MAX_RULE_TIMERS; i++) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%c\"T%d\":%d"), mqtt_data, (i) ? ',' : '{', i +1, (rules_timer[i]) ? (rules_timer[i] - millis()) / 1000 : 0); + ResponseAppend_P(PSTR("%c\"T%d\":%d"), (i) ? ',' : '{', i +1, (rules_timer[i]) ? (rules_timer[i] - millis()) / 1000 : 0); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); } else if (CMND_EVENT == command_code) { if (XdrvMailbox.data_len > 0) { strlcpy(event_data, XdrvMailbox.data, sizeof(event_data)); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); } else if ((CMND_VAR == command_code) && (index > 0) && (index <= MAX_RULE_VARS)) { if (XdrvMailbox.data_len > 0) { @@ -1158,7 +1158,7 @@ bool RulesCommand(void) #endif //USE_EXPRESSION bitSet(vars_event, index -1); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); } else if ((CMND_MEM == command_code) && (index > 0) && (index <= MAX_RULE_MEMS)) { if (XdrvMailbox.data_len > 0) { @@ -1169,13 +1169,13 @@ bool RulesCommand(void) #endif //USE_EXPRESSION bitSet(mems_event, index -1); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.mems[index -1]); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, Settings.mems[index -1]); } else if (CMND_CALC_RESOLUTION == command_code) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 7)) { Settings.flag2.calc_resolution = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.flag2.calc_resolution); + Response_P(S_JSON_COMMAND_NVALUE, command, Settings.flag2.calc_resolution); } else if ((CMND_ADD == command_code) && (index > 0) && (index <= MAX_RULE_VARS)) { if (XdrvMailbox.data_len > 0) { @@ -1183,7 +1183,7 @@ bool RulesCommand(void) dtostrfd(tempvar, Settings.flag2.calc_resolution, vars[index -1]); bitSet(vars_event, index -1); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); } else if ((CMND_SUB == command_code) && (index > 0) && (index <= MAX_RULE_VARS)) { if (XdrvMailbox.data_len > 0) { @@ -1191,7 +1191,7 @@ bool RulesCommand(void) dtostrfd(tempvar, Settings.flag2.calc_resolution, vars[index -1]); bitSet(vars_event, index -1); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); } else if ((CMND_MULT == command_code) && (index > 0) && (index <= MAX_RULE_VARS)) { if (XdrvMailbox.data_len > 0) { @@ -1199,7 +1199,7 @@ bool RulesCommand(void) dtostrfd(tempvar, Settings.flag2.calc_resolution, vars[index -1]); bitSet(vars_event, index -1); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); } else if ((CMND_SCALE == command_code) && (index > 0) && (index <= MAX_RULE_VARS)) { if (XdrvMailbox.data_len > 0) { @@ -1216,14 +1216,14 @@ bool RulesCommand(void) bitSet(vars_event, index -1); } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); + Response_P(S_JSON_COMMAND_INDEX_SVALUE, command, index, vars[index -1]); #ifdef SUPPORT_MQTT_EVENT } else if (CMND_SUBSCRIBE == command_code) { //MQTT Subscribe command. Subscribe , [, ] String result = RulesSubscribe(XdrvMailbox.data, XdrvMailbox.data_len); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, result.c_str()); + Response_P(S_JSON_COMMAND_SVALUE, command, result.c_str()); } else if (CMND_UNSUBSCRIBE == command_code) { //MQTT Un-subscribe command. UnSubscribe String result = RulesUnsubscribe(XdrvMailbox.data, XdrvMailbox.data_len); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, result.c_str()); + Response_P(S_JSON_COMMAND_SVALUE, command, result.c_str()); #endif //SUPPORT_MQTT_EVENT } else serviced = false; // Unknown command diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 639c74499..4437a91eb 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -540,8 +540,7 @@ void HAssAnnounceStatusSensor(void) void HAssPublishStatus(void) { - snprintf_P(mqtt_data, sizeof(mqtt_data), - PSTR("{\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_BUILDDATETIME "\":\"%s\"," + Response_P(PSTR("{\"" D_JSON_VERSION "\":\"%s%s\",\"" D_JSON_BUILDDATETIME "\":\"%s\"," "\"" D_JSON_COREVERSION "\":\"" ARDUINO_ESP8266_RELEASE "\",\"" D_JSON_SDKVERSION "\":\"%s\"," "\"" D_CMND_MODULE "\":\"%s\",\"" D_JSON_RESTARTREASON "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\"," "\"WiFi " D_JSON_LINK_COUNT "\":%d,\"WiFi " D_JSON_DOWNTIME "\":\"%s\",\"" D_JSON_MQTT_COUNT "\":%d," diff --git a/sonoff/xdrv_13_display.ino b/sonoff/xdrv_13_display.ino index f14680939..89dde70d1 100644 --- a/sonoff/xdrv_13_display.ino +++ b/sonoff/xdrv_13_display.ino @@ -465,7 +465,7 @@ void DisplayText(void) break; default: // unknown escape - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("Unknown Escape")); + Response_P(PSTR("Unknown Escape")); goto exit; break; } @@ -921,7 +921,7 @@ bool DisplayCommand(void) serviced = false; // Unknown command } else if (CMND_DISPLAY == command_code) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_DISPLAY "\":{\"" D_CMND_DISP_MODEL "\":%d,\"" D_CMND_DISP_MODE "\":%d,\"" D_CMND_DISP_DIMMER "\":%d,\"" + Response_P(PSTR("{\"" D_CMND_DISPLAY "\":{\"" D_CMND_DISP_MODEL "\":%d,\"" D_CMND_DISP_MODE "\":%d,\"" D_CMND_DISP_DIMMER "\":%d,\"" D_CMND_DISP_SIZE "\":%d,\"" D_CMND_DISP_FONT "\":%d,\"" D_CMND_DISP_ROTATE "\":%d,\"" D_CMND_DISP_REFRESH "\":%d,\"" D_CMND_DISP_COLS "\":[%d,%d],\"" D_CMND_DISP_ROWS "\":%d}}"), Settings.display_model, Settings.display_mode, Settings.display_dimmer, Settings.display_size, Settings.display_font, Settings.display_rotate, Settings.display_refresh, Settings.display_cols[0], Settings.display_cols[1], Settings.display_rows); @@ -936,7 +936,7 @@ bool DisplayCommand(void) Settings.display_model = last_display_model; } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_model); + Response_P(S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_model); } else if (CMND_DISP_MODE == command_code) { #ifdef USE_DISPLAY_MODES1TO5 @@ -964,7 +964,7 @@ bool DisplayCommand(void) } } #endif // USE_DISPLAY_MODES1TO5 - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_mode); + Response_P(S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_mode); } else if (CMND_DISP_DIMMER == command_code) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 100)) { @@ -976,19 +976,19 @@ bool DisplayCommand(void) ExecuteCommandPower(disp_device, POWER_OFF, SRC_DISPLAY); } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_dimmer); + Response_P(S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_dimmer); } else if (CMND_DISP_SIZE == command_code) { if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 4)) { Settings.display_size = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_size); + Response_P(S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_size); } else if (CMND_DISP_FONT == command_code) { if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= 4)) { Settings.display_font = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_font); + Response_P(S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_font); } else if (CMND_DISP_ROTATE == command_code) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 4)) { @@ -1011,7 +1011,7 @@ bool DisplayCommand(void) #endif // USE_DISPLAY_MODES1TO5 } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_rotate); + Response_P(S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_rotate); } else if (CMND_DISP_TEXT == command_code) { mqtt_data[0] = '\0'; @@ -1026,23 +1026,23 @@ bool DisplayCommand(void) } #endif // USE_DISPLAY_MODES1TO5 } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("No Text")); + Response_P(PSTR("No Text")); } if (mqtt_data[0] == '\0') { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_VALUE, command, XdrvMailbox.data); + Response_P(S_JSON_DISPLAY_COMMAND_VALUE, command, XdrvMailbox.data); } } else if ((CMND_DISP_ADDRESS == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 8)) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 255)) { Settings.display_address[XdrvMailbox.index -1] = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, Settings.display_address[XdrvMailbox.index -1]); + Response_P(S_JSON_DISPLAY_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, Settings.display_address[XdrvMailbox.index -1]); } else if (CMND_DISP_REFRESH == command_code) { if ((XdrvMailbox.payload >= 1) && (XdrvMailbox.payload <= 7)) { Settings.display_refresh = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_refresh); + Response_P(S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_refresh); } else if ((CMND_DISP_COLS == command_code) && (XdrvMailbox.index > 0) && (XdrvMailbox.index <= 2)) { if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= DISPLAY_MAX_COLS)) { @@ -1054,7 +1054,7 @@ bool DisplayCommand(void) } #endif // USE_DISPLAY_MODES1TO5 } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, Settings.display_cols[XdrvMailbox.index -1]); + Response_P(S_JSON_DISPLAY_COMMAND_INDEX_NVALUE, command, XdrvMailbox.index, Settings.display_cols[XdrvMailbox.index -1]); } else if (CMND_DISP_ROWS == command_code) { if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload <= DISPLAY_MAX_ROWS)) { @@ -1064,7 +1064,7 @@ bool DisplayCommand(void) DisplayReAllocScreenBuffer(); #endif // USE_DISPLAY_MODES1TO5 } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_rows); + Response_P(S_JSON_DISPLAY_COMMAND_NVALUE, command, Settings.display_rows); } else serviced = false; // Unknown command } diff --git a/sonoff/xdrv_14_mp3.ino b/sonoff/xdrv_14_mp3.ino index 4e55cddc5..5e74b7122 100644 --- a/sonoff/xdrv_14_mp3.ino +++ b/sonoff/xdrv_14_mp3.ino @@ -200,7 +200,7 @@ bool MP3PlayerCmd(void) { if (command_code == CMND_MP3_DEVICE) { MP3_CMD(MP3_CMD_DEVICE, XdrvMailbox.payload); } if (command_code == CMND_MP3_DAC) { MP3_CMD(MP3_CMD_DAC, XdrvMailbox.payload); } } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_MP3_COMMAND_NVALUE, command, XdrvMailbox.payload); + Response_P(S_JSON_MP3_COMMAND_NVALUE, command, XdrvMailbox.payload); break; case CMND_MP3_PLAY: case CMND_MP3_PAUSE: @@ -211,7 +211,7 @@ bool MP3PlayerCmd(void) { if (command_code == CMND_MP3_PAUSE) { MP3_CMD(MP3_CMD_PAUSE, 0); } if (command_code == CMND_MP3_STOP) { MP3_CMD(MP3_CMD_STOP, 0); } if (command_code == CMND_MP3_RESET) { MP3_CMD(MP3_CMD_RESET, 0); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_MP3_COMMAND, command, XdrvMailbox.payload); + Response_P(S_JSON_MP3_COMMAND, command, XdrvMailbox.payload); break; default: // else for Unknown command diff --git a/sonoff/xdrv_15_pca9685.ino b/sonoff/xdrv_15_pca9685.ino index de91a02b4..1a27219c8 100644 --- a/sonoff/xdrv_15_pca9685.ino +++ b/sonoff/xdrv_15_pca9685.ino @@ -60,7 +60,7 @@ void PCA9685_Reset(void) PCA9685_SetPWM(pin,0,false); pca9685_pin_pwm_value[pin] = 0; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"PCA9685\":{\"RESET\":\"OK\"}}")); + Response_P(PSTR("{\"PCA9685\":{\"RESET\":\"OK\"}}")); } void PCA9685_SetPWMfreq(double freq) { @@ -127,11 +127,11 @@ bool PCA9685_Command(void) uint16_t new_freq = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); if ((new_freq >= 24) && (new_freq <= 1526)) { PCA9685_SetPWMfreq(new_freq); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"PCA9685\":{\"PWMF\":%i, \"Result\":\"OK\"}}"),new_freq); + Response_P(PSTR("{\"PCA9685\":{\"PWMF\":%i, \"Result\":\"OK\"}}"),new_freq); return serviced; } } else { // No parameter was given for setfreq, so we return current setting - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"PCA9685\":{\"PWMF\":%i}}"),pca9685_freq); + Response_P(PSTR("{\"PCA9685\":{\"PWMF\":%i}}"),pca9685_freq); return serviced; } } @@ -141,20 +141,20 @@ bool PCA9685_Command(void) if (paramcount > 2) { if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 3), "ON")) { PCA9685_SetPWM(pin, 4096, false); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,4096); + Response_P(PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,4096); serviced = true; return serviced; } if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 3), "OFF")) { PCA9685_SetPWM(pin, 0, false); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,0); + Response_P(PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,0); serviced = true; return serviced; } uint16_t pwm = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); if ((pin >= 0 && pin <= 15) && (pwm >= 0 && pwm <= 4096)) { PCA9685_SetPWM(pin, pwm, false); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,pwm); + Response_P(PSTR("{\"PCA9685\":{\"PIN\":%i,\"PWM\":%i}}"),pin,pwm); serviced = true; return serviced; } @@ -166,12 +166,12 @@ bool PCA9685_Command(void) void PCA9685_OutputTelemetry(bool telemetry) { if (0 == pca9685_detected) { return; } // We do not do this if the PCA9685 has not been detected - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\",\"PCA9685\": {"), GetDateAndTime(DT_LOCAL).c_str()); - snprintf_P(mqtt_data,sizeof(mqtt_data), PSTR("%s\"PWM_FREQ\":%i,"),mqtt_data,pca9685_freq); + Response_P(PSTR("{\"" D_JSON_TIME "\":\"%s\",\"PCA9685\": {"), GetDateAndTime(DT_LOCAL).c_str()); + ResponseAppend_P(PSTR("\"PWM_FREQ\":%i,"),pca9685_freq); for (uint8_t pin=0;pin<16;pin++) { - snprintf_P(mqtt_data,sizeof(mqtt_data), PSTR("%s\"PWM%i\":%i,"),mqtt_data,pin,pca9685_pin_pwm_value[pin]); + ResponseAppend_P(PSTR("\"PWM%i\":%i,"),pin,pca9685_pin_pwm_value[pin]); } - snprintf_P(mqtt_data,sizeof(mqtt_data),PSTR("%s\"END\":1}}"),mqtt_data); + ResponseAppend_P(PSTR("\"END\":1}}")); if (telemetry) { MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); } diff --git a/sonoff/xdrv_17_rcswitch.ino b/sonoff/xdrv_17_rcswitch.ino index 300a156f5..aaa594b2a 100644 --- a/sonoff/xdrv_17_rcswitch.ino +++ b/sonoff/xdrv_17_rcswitch.ino @@ -61,7 +61,7 @@ void RfReceiveCheck(void) } else { snprintf_P(stemp, sizeof(stemp), PSTR("\"0x%lX\""), (uint32_t)data); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_RF_DATA "\":%s,\"" D_JSON_RF_BITS "\":%d,\"" D_JSON_RF_PROTOCOL "\":%d,\"" D_JSON_RF_PULSE "\":%d}}"), + Response_P(PSTR("{\"" D_JSON_RFRECEIVED "\":{\"" D_JSON_RF_DATA "\":%s,\"" D_JSON_RF_BITS "\":%d,\"" D_JSON_RF_PROTOCOL "\":%d,\"" D_JSON_RF_PULSE "\":%d}}"), stemp, bits, protocol, delay); MqttPublishPrefixTopic_P(RESULT_OR_TELE, PSTR(D_JSON_RFRECEIVED)); XdrvRulesProcess(); @@ -145,7 +145,7 @@ bool RfSendCommand(void) if (!bits) { bits = 24; } // Default 24 bits if (data) { mySwitch.send(data, bits); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RFSEND "\":\"" D_JSON_DONE "\"}")); + Response_P(PSTR("{\"" D_CMND_RFSEND "\":\"" D_JSON_DONE "\"}")); } else { error = true; } @@ -153,7 +153,7 @@ bool RfSendCommand(void) error = true; } if (error) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_RFSEND "\":\"" D_JSON_NO " " D_JSON_RF_DATA ", " D_JSON_RF_BITS ", " D_JSON_RF_PROTOCOL ", " D_JSON_RF_REPEAT " " D_JSON_OR " " D_JSON_RF_PULSE "\"}")); + Response_P(PSTR("{\"" D_CMND_RFSEND "\":\"" D_JSON_NO " " D_JSON_RF_DATA ", " D_JSON_RF_BITS ", " D_JSON_RF_PROTOCOL ", " D_JSON_RF_REPEAT " " D_JSON_OR " " D_JSON_RF_PULSE "\"}")); } } else serviced = false; // Unknown command diff --git a/sonoff/xdrv_99_debug.ino b/sonoff/xdrv_99_debug.ino index e9da144b8..08a73d4da 100644 --- a/sonoff/xdrv_99_debug.ino +++ b/sonoff/xdrv_99_debug.ino @@ -419,28 +419,28 @@ bool DebugCommand(void) } else if (CMND_HELP == command_code) { AddLog_P(LOG_LEVEL_INFO, kDebugCommands); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); } else if (CMND_RTCDUMP == command_code) { DebugRtcDump(XdrvMailbox.data); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); } else if (CMND_CFGDUMP == command_code) { DebugCfgDump(XdrvMailbox.data); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); } else if (CMND_CFGPEEK == command_code) { DebugCfgPeek(XdrvMailbox.data); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); } else if (CMND_CFGPOKE == command_code) { DebugCfgPoke(XdrvMailbox.data); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); } #ifdef USE_DEBUG_SETTING_NAMES else if (CMND_CFGSHOW == command_code) { DebugCfgShow(XdrvMailbox.payload); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); } #endif // USE_DEBUG_SETTING_NAMES #ifdef USE_WEBSERVER @@ -448,13 +448,13 @@ bool DebugCommand(void) if (XdrvMailbox.data_len > 0) { config_xor_on_set = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, config_xor_on_set); + Response_P(S_JSON_COMMAND_NVALUE, command, config_xor_on_set); } #endif // USE_WEBSERVER #ifdef DEBUG_THEO else if (CMND_EXCEPTION == command_code) { if (XdrvMailbox.data_len > 0) ExceptionTest(XdrvMailbox.payload); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); } #endif // DEBUG_THEO else if (CMND_CPUCHECK == command_code) { @@ -462,26 +462,26 @@ bool DebugCommand(void) CPU_load_check = XdrvMailbox.payload; CPU_last_millis = CPU_last_loop_time; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, CPU_load_check); + Response_P(S_JSON_COMMAND_NVALUE, command, CPU_load_check); } else if (CMND_FREEMEM == command_code) { if (XdrvMailbox.data_len > 0) { CPU_show_freemem = XdrvMailbox.payload; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, CPU_show_freemem); + Response_P(S_JSON_COMMAND_NVALUE, command, CPU_show_freemem); } else if ((CMND_SETSENSOR == command_code) && (XdrvMailbox.index < MAX_XSNS_DRIVERS)) { if ((XdrvMailbox.payload >= 0) && XsnsPresent(XdrvMailbox.index)) { bitWrite(Settings.sensors[XdrvMailbox.index / 32], XdrvMailbox.index % 32, XdrvMailbox.payload &1); if (1 == XdrvMailbox.payload) { restart_flag = 2; } // To safely re-enable a sensor currently most sensor need to follow complete restart init cycle } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_XVALUE, command, XsnsGetSensors().c_str()); + Response_P(S_JSON_COMMAND_XVALUE, command, XsnsGetSensors().c_str()); } else if (CMND_FLASHMODE == command_code) { if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 3)) { SetFlashMode(XdrvMailbox.payload); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, ESP.getFlashChipMode()); + Response_P(S_JSON_COMMAND_NVALUE, command, ESP.getFlashChipMode()); } else serviced = false; // Unknown command From dcc69bdff09717e5b78aa970f955b9682870fbdb Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 23 Mar 2019 17:57:31 +0100 Subject: [PATCH 03/81] Shrink code/flash space pt.2/2 Shrink code/flash space pt.2/2 --- sonoff/i18n.h | 12 +++--- sonoff/sonoff.ino | 4 +- sonoff/xdrv_09_timers.ino | 2 +- sonoff/xsns_01_counter.ino | 6 +-- sonoff/xsns_02_analog.ino | 4 +- sonoff/xsns_04_snfsc.ino | 4 +- sonoff/xsns_05_ds18b20.ino | 2 +- sonoff/xsns_05_ds18x20.ino | 4 +- sonoff/xsns_05_ds18x20_legacy.ino | 8 ++-- sonoff/xsns_06_dht.ino | 2 +- sonoff/xsns_07_sht1x.ino | 2 +- sonoff/xsns_08_htu21.ino | 2 +- sonoff/xsns_09_bmp.ino | 7 ++-- sonoff/xsns_10_bh1750.ino | 2 +- sonoff/xsns_11_veml6070.ino | 8 ++-- sonoff/xsns_12_ads1115.ino | 10 ++--- sonoff/xsns_12_ads1115_i2cdev.ino | 9 ++--- sonoff/xsns_13_ina219.ino | 6 +-- sonoff/xsns_14_sht3x.ino | 2 +- sonoff/xsns_15_mhz19.ino | 22 +++++------ sonoff/xsns_16_tsl2561.ino | 4 +- sonoff/xsns_17_senseair.ino | 6 +-- sonoff/xsns_18_pms5003.ino | 2 +- sonoff/xsns_19_mgs.ino | 16 ++++---- sonoff/xsns_20_novasds.ino | 2 +- sonoff/xsns_21_sgp30.ino | 2 +- sonoff/xsns_22_sr04.ino | 2 +- sonoff/xsns_23_sdm120.ino | 8 ++-- sonoff/xsns_24_si1145.ino | 4 +- sonoff/xsns_25_sdm630.ino | 4 +- sonoff/xsns_26_lm75ad.ino | 2 +- sonoff/xsns_27_apds9960.ino | 12 +++--- sonoff/xsns_29_mcp230xx.ino | 65 +++++++++++++++---------------- sonoff/xsns_30_mpr121.ino | 8 ++-- sonoff/xsns_31_ccs811.ino | 2 +- sonoff/xsns_32_mpu6050.ino | 4 +- sonoff/xsns_34_hx711.ino | 8 ++-- sonoff/xsns_35_tx20.ino | 4 +- sonoff/xsns_36_mgc3130.ino | 8 ++-- sonoff/xsns_37_rfsensor.ino | 23 ++++++----- sonoff/xsns_38_az7798.ino | 2 +- sonoff/xsns_39_max31855.ino | 4 +- sonoff/xsns_40_pn532.ino | 12 +++--- sonoff/xsns_41_max44009.ino | 4 +- sonoff/xsns_42_scd30.ino | 9 +++-- 45 files changed, 163 insertions(+), 172 deletions(-) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index ded4ccd43..ca5e2b79a 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -506,14 +506,14 @@ const char S_JSON_COMMAND_INDEX_ASTERIX[] PROGMEM = "{\"%s%d\":\"" D_A const char S_JSON_COMMAND_INDEX_SVALUE_SVALUE[] PROGMEM = "{\"%s%d\":\"%s%s\"}"; const char S_JSON_COMMAND_INDEX_NVALUE_ACTIVE_NVALUE[] PROGMEM = "{\"%s%d\":\"%d (" D_JSON_ACTIVE " %d)\"}"; -const char S_JSON_SENSOR_INDEX_NVALUE[] PROGMEM = "{\"" D_CMND_SENSOR "%d\":%d}"; -const char S_JSON_SENSOR_INDEX_SVALUE[] PROGMEM = "{\"" D_CMND_SENSOR "%d\":\"%s\"}"; +const char S_JSON_SENSOR_INDEX_NVALUE[] PROGMEM = "{\"" D_CMND_SENSOR "%d\":%d}"; +const char S_JSON_SENSOR_INDEX_SVALUE[] PROGMEM = "{\"" D_CMND_SENSOR "%d\":\"%s\"}"; -const char S_JSON_DRIVER_INDEX_NVALUE[] PROGMEM = "{\"" D_CMND_DRIVER "%d\":%d}"; -const char S_JSON_DRIVER_INDEX_SVALUE[] PROGMEM = "{\"" D_CMND_DRIVER "%d\":\"%s\"}"; +const char S_JSON_DRIVER_INDEX_NVALUE[] PROGMEM = "{\"" D_CMND_DRIVER "%d\":%d}"; +const char S_JSON_DRIVER_INDEX_SVALUE[] PROGMEM = "{\"" D_CMND_DRIVER "%d\":\"%s\"}"; -const char JSON_SNS_TEMP[] PROGMEM = "%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}"; -const char JSON_SNS_TEMPHUM[] PROGMEM = "%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"; +const char JSON_SNS_TEMP[] PROGMEM = ",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}"; +const char JSON_SNS_TEMPHUM[] PROGMEM = ",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"; const char S_LOG_I2C_FOUND_AT[] PROGMEM = D_LOG_I2C "%s " D_FOUND_AT " 0x%x"; diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index cf11abcff..458b12ed6 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -1207,7 +1207,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) snprintf_P(stemp1, sizeof(stemp1), kWifiConfig[Settings.sta_config]); Response_P(PSTR("{\"" D_CMND_WIFICONFIG "\":\"%s " D_JSON_SELECTED "\"}"), stemp1); if (WifiState() > WIFI_RESTART) { -// snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s after restart"), mqtt_data); +// ResponseAppend_P(PSTR(" after restart")); restart_flag = 2; } } else { @@ -1478,7 +1478,7 @@ bool SendKey(uint8_t key, uint8_t device, uint8_t state) #endif // USE_DOMOTICZ result = !Settings.flag3.button_switch_force_local; } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"%s%d\":{\"State\":%d}}"), (key) ? "Switch" : "Button", device, state); + Response_P(PSTR("{\"%s%d\":{\"State\":%d}}"), (key) ? "Switch" : "Button", device, state); result = XdrvRulesProcess(); } #ifdef USE_KNX diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index adaaf0603..59d9300f4 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -287,7 +287,7 @@ void TimerEverySecond(void) Settings.timer[i].arm = xtimer.repeat; #ifdef USE_RULES if (3 == xtimer.power) { // Blink becomes Rule disregarding device and allowing use of Backlog commands - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"Clock\":{\"Timer\":%d}}"), i +1); + Response_P(PSTR("{\"Clock\":{\"Timer\":%d}}"), i +1); XdrvRulesProcess(); } else #endif // USE_RULES diff --git a/sonoff/xsns_01_counter.ino b/sonoff/xsns_01_counter.ino index 901793fec..eadd9a4b9 100644 --- a/sonoff/xsns_01_counter.ino +++ b/sonoff/xsns_01_counter.ino @@ -107,11 +107,11 @@ void CounterShow(bool json) if (json) { if (!header) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"COUNTER\":{"), mqtt_data); + ResponseAppend_P(PSTR(",\"COUNTER\":{")); stemp[0] = '\0'; } header++; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"C%d\":%s"), mqtt_data, stemp, i +1, counter); + ResponseAppend_P(PSTR("%s\"C%d\":%s"), stemp, i +1, counter); strlcpy(stemp, ",", sizeof(stemp)); #ifdef USE_DOMOTICZ if ((0 == tele_period) && (1 == dsxflg)) { @@ -131,7 +131,7 @@ void CounterShow(bool json) } if (json) { if (header) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); } } } diff --git a/sonoff/xsns_02_analog.ino b/sonoff/xsns_02_analog.ino index 79a622f0f..9c6c5074e 100644 --- a/sonoff/xsns_02_analog.ino +++ b/sonoff/xsns_02_analog.ino @@ -44,7 +44,7 @@ void AdcEvery250ms(void) if ((new_value < adc_last_value -10) || (new_value > adc_last_value +10)) { adc_last_value = new_value; uint16_t value = adc_last_value / 10; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"ANALOG\":{\"A0div10\":%d}}"), (value > 99) ? 100 : value); + Response_P(PSTR("{\"ANALOG\":{\"A0div10\":%d}}"), (value > 99) ? 100 : value); XdrvRulesProcess(); } } @@ -55,7 +55,7 @@ void AdcShow(bool json) uint16_t analog = AdcRead(); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"ANALOG\":{\"A0\":%d}"), mqtt_data, analog); + ResponseAppend_P(PSTR(",\"ANALOG\":{\"A0\":%d}"), analog); #ifdef USE_WEBSERVER } else { WSContentSend_PD(HTTP_SNS_ANALOG, "", 0, analog); diff --git a/sonoff/xsns_04_snfsc.ino b/sonoff/xsns_04_snfsc.ino index 98d1f6276..051640f63 100644 --- a/sonoff/xsns_04_snfsc.ino +++ b/sonoff/xsns_04_snfsc.ino @@ -120,8 +120,8 @@ void SonoffScShow(bool json) dtostrfd(h, Settings.flag2.humidity_resolution, humidity); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SonoffSC\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"" D_JSON_LIGHT "\":%d,\"" D_JSON_NOISE "\":%d,\"" D_JSON_AIRQUALITY "\":%d}"), - mqtt_data, temperature, humidity, sc_value[2], sc_value[3], sc_value[4]); + ResponseAppend_P(PSTR(",\"SonoffSC\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"" D_JSON_LIGHT "\":%d,\"" D_JSON_NOISE "\":%d,\"" D_JSON_AIRQUALITY "\":%d}"), + temperature, humidity, sc_value[2], sc_value[3], sc_value[4]); #ifdef USE_DOMOTICZ if (0 == tele_period) { DomoticzTempHumSensor(temperature, humidity); diff --git a/sonoff/xsns_05_ds18b20.ino b/sonoff/xsns_05_ds18b20.ino index 9e82a8e9b..d68664570 100644 --- a/sonoff/xsns_05_ds18b20.ino +++ b/sonoff/xsns_05_ds18b20.ino @@ -205,7 +205,7 @@ void Ds18b20Show(bool json) char temperature[33]; dtostrfd(ds18b20_temperature, Settings.flag2.temperature_resolution, temperature); if(json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMP, mqtt_data, ds18b20_types, temperature); + ResponseAppend_P(JSON_SNS_TEMP, ds18b20_types, temperature); #ifdef USE_DOMOTICZ if (0 == tele_period) { DomoticzSensor(DZ_TEMP, temperature); diff --git a/sonoff/xsns_05_ds18x20.ino b/sonoff/xsns_05_ds18x20.ino index e2ff0767c..7a67f80a9 100644 --- a/sonoff/xsns_05_ds18x20.ino +++ b/sonoff/xsns_05_ds18x20.ino @@ -432,13 +432,13 @@ void Ds18x20Show(bool json) if (json) { if (1 == ds18x20_sensors) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}"), mqtt_data, ds18x20_types, temperature); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}"), ds18x20_types, temperature); } else { char address[17]; for (uint8_t j = 0; j < 6; j++) { sprintf(address+2*j, "%02X", ds18x20_sensor[index].address[6-j]); // Skip sensor type and crc } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_ID "\":\"%s\",\"" D_JSON_TEMPERATURE "\":%s}"), mqtt_data, ds18x20_types, address, temperature); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_ID "\":\"%s\",\"" D_JSON_TEMPERATURE "\":%s}"), ds18x20_types, address, temperature); } #ifdef USE_DOMOTICZ if ((0 == tele_period) && (0 == i)) { diff --git a/sonoff/xsns_05_ds18x20_legacy.ino b/sonoff/xsns_05_ds18x20_legacy.ino index 2b157cfb7..9ecdcbff5 100644 --- a/sonoff/xsns_05_ds18x20_legacy.ino +++ b/sonoff/xsns_05_ds18x20_legacy.ino @@ -178,12 +178,12 @@ void Ds18x20Show(bool json) if (json) { if (!dsxflg) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"DS18x20\":{"), mqtt_data); + ResponseAppend_P(PSTR(",\"DS18x20\":{")); stemp[0] = '\0'; } dsxflg++; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"DS%d\":{\"" D_JSON_TYPE "\":\"%s\",\"" D_JSON_ADDRESS "\":\"%s\",\"" D_JSON_TEMPERATURE "\":%s}"), - mqtt_data, stemp, i +1, ds18x20_types, Ds18x20Addresses(i).c_str(), temperature); + ResponseAppend_P(PSTR("%s\"DS%d\":{\"" D_JSON_TYPE "\":\"%s\",\"" D_JSON_ADDRESS "\":\"%s\",\"" D_JSON_TEMPERATURE "\":%s}"), + stemp, i +1, ds18x20_types, Ds18x20Addresses(i).c_str(), temperature); strlcpy(stemp, ",", sizeof(stemp)); #ifdef USE_DOMOTICZ if ((0 == tele_period) && (1 == dsxflg)) { @@ -205,7 +205,7 @@ void Ds18x20Show(bool json) } if (json) { if (dsxflg) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); } } Ds18x20Search(); // Check for changes in sensors number diff --git a/sonoff/xsns_06_dht.ino b/sonoff/xsns_06_dht.ino index 016f012f0..00bbf7f15 100644 --- a/sonoff/xsns_06_dht.ino +++ b/sonoff/xsns_06_dht.ino @@ -213,7 +213,7 @@ void DhtShow(bool json) dtostrfd(Dht[i].h, Settings.flag2.humidity_resolution, humidity); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, Dht[i].stype, temperature, humidity); + ResponseAppend_P(JSON_SNS_TEMPHUM, Dht[i].stype, temperature, humidity); #ifdef USE_DOMOTICZ if ((0 == tele_period) && (0 == i)) { DomoticzTempHumSensor(temperature, humidity); diff --git a/sonoff/xsns_07_sht1x.ino b/sonoff/xsns_07_sht1x.ino index 0967560b1..12d7f4e79 100644 --- a/sonoff/xsns_07_sht1x.ino +++ b/sonoff/xsns_07_sht1x.ino @@ -194,7 +194,7 @@ void ShtShow(bool json) dtostrfd(sht_humidity, Settings.flag2.humidity_resolution, humidity); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, sht_types, temperature, humidity); + ResponseAppend_P(JSON_SNS_TEMPHUM, sht_types, temperature, humidity); #ifdef USE_DOMOTICZ if (0 == tele_period) { DomoticzTempHumSensor(temperature, humidity); diff --git a/sonoff/xsns_08_htu21.ino b/sonoff/xsns_08_htu21.ino index 1ef208d61..c12a068c9 100644 --- a/sonoff/xsns_08_htu21.ino +++ b/sonoff/xsns_08_htu21.ino @@ -254,7 +254,7 @@ void HtuShow(bool json) dtostrfd(htu_humidity, Settings.flag2.humidity_resolution, humidity); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, htu_types, temperature, humidity); + ResponseAppend_P(JSON_SNS_TEMPHUM, htu_types, temperature, humidity); #ifdef USE_DOMOTICZ if (0 == tele_period) { DomoticzTempHumSensor(temperature, humidity); diff --git a/sonoff/xsns_09_bmp.ino b/sonoff/xsns_09_bmp.ino index 22b0cd365..cc738f977 100755 --- a/sonoff/xsns_09_bmp.ino +++ b/sonoff/xsns_09_bmp.ino @@ -566,8 +566,7 @@ void BmpShow(bool json) char json_gas[40]; snprintf_P(json_gas, sizeof(json_gas), PSTR(",\"" D_JSON_GAS "\":%s"), gas_resistance); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s,\"" D_JSON_PRESSURE "\":%s%s%s}"), - mqtt_data, + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s,\"" D_JSON_PRESSURE "\":%s%s%s}"), name, temperature, (bmp_sensors[bmp_idx].bmp_model >= 2) ? json_humidity : "", @@ -575,8 +574,8 @@ void BmpShow(bool json) (Settings.altitude != 0) ? json_sealevel : "", (bmp_sensors[bmp_idx].bmp_model >= 3) ? json_gas : ""); #else - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s,\"" D_JSON_PRESSURE "\":%s%s}"), - mqtt_data, name, temperature, (bmp_sensors[bmp_idx].bmp_model >= 2) ? json_humidity : "", pressure, (Settings.altitude != 0) ? json_sealevel : ""); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s,\"" D_JSON_PRESSURE "\":%s%s}"), + name, temperature, (bmp_sensors[bmp_idx].bmp_model >= 2) ? json_humidity : "", pressure, (Settings.altitude != 0) ? json_sealevel : ""); #endif // USE_BME680 #ifdef USE_DOMOTICZ diff --git a/sonoff/xsns_10_bh1750.ino b/sonoff/xsns_10_bh1750.ino index d4ffa3a10..5398422b7 100644 --- a/sonoff/xsns_10_bh1750.ino +++ b/sonoff/xsns_10_bh1750.ino @@ -92,7 +92,7 @@ void Bh1750Show(bool json) { if (bh1750_valid) { if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_ILLUMINANCE "\":%d}"), mqtt_data, bh1750_types, bh1750_illuminance); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_ILLUMINANCE "\":%d}"), bh1750_types, bh1750_illuminance); #ifdef USE_DOMOTICZ if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, bh1750_illuminance); diff --git a/sonoff/xsns_11_veml6070.ino b/sonoff/xsns_11_veml6070.ino index 2222cc335..b6f50d05d 100644 --- a/sonoff/xsns_11_veml6070.ino +++ b/sonoff/xsns_11_veml6070.ino @@ -277,11 +277,11 @@ void Veml6070Show(bool json) dtostrfd(uvpower, 3, str_uvpower); if (json) { #ifdef USE_VEML6070_SHOW_RAW - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_UV_LEVEL "\":%s,\"" D_JSON_UV_INDEX "\":%s,\"" D_JSON_UV_INDEX_TEXT "\":\"%s\",\"" D_JSON_UV_POWER "\":%s}"), - mqtt_data, veml6070_name, str_uvlevel, str_uvrisk, str_uvrisk_text, str_uvpower); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_UV_LEVEL "\":%s,\"" D_JSON_UV_INDEX "\":%s,\"" D_JSON_UV_INDEX_TEXT "\":\"%s\",\"" D_JSON_UV_POWER "\":%s}"), + veml6070_name, str_uvlevel, str_uvrisk, str_uvrisk_text, str_uvpower); #else - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_UV_INDEX "\":%s,\"" D_JSON_UV_INDEX_TEXT "\":\"%s\",\"" D_JSON_UV_POWER "\":%s}"), - mqtt_data, veml6070_name, str_uvrisk, str_uvrisk_text, str_uvpower); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_UV_INDEX "\":%s,\"" D_JSON_UV_INDEX_TEXT "\":\"%s\",\"" D_JSON_UV_POWER "\":%s}"), + veml6070_name, str_uvrisk, str_uvrisk_text, str_uvpower); #endif // USE_VEML6070_SHOW_RAW #ifdef USE_DOMOTICZ if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, uvlevel); } diff --git a/sonoff/xsns_12_ads1115.ino b/sonoff/xsns_12_ads1115.ino index 7c674debe..d40b72849 100644 --- a/sonoff/xsns_12_ads1115.ino +++ b/sonoff/xsns_12_ads1115.ino @@ -188,13 +188,13 @@ void Ads1115GetValues(uint8_t address) void Ads1115toJSON(char *comma_j) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s{"), mqtt_data,comma_j); + ResponseAppend_P(PSTR("%s{"), comma_j); char *comma = (char*)""; for (uint8_t i = 0; i < 4; i++) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"A%d\":%d"), mqtt_data, comma, i, ads1115_values[i]); + ResponseAppend_P(PSTR("%s\"A%d\":%d"), comma, i, ads1115_values[i]); comma = (char*)","; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); } void Ads1115toString(uint8_t address) @@ -212,7 +212,7 @@ void Ads1115Show(bool json) if (!ads1115_type) { return; } if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"ADS1115\":["), mqtt_data); + ResponseAppend_P(PSTR(",\"ADS1115\":[")); } char *comma = (char*)""; @@ -234,7 +234,7 @@ void Ads1115Show(bool json) } if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s]"), mqtt_data); + ResponseAppend_P(PSTR("]")); } } diff --git a/sonoff/xsns_12_ads1115_i2cdev.ino b/sonoff/xsns_12_ads1115_i2cdev.ino index 855658647..eb5643c3e 100644 --- a/sonoff/xsns_12_ads1115_i2cdev.ino +++ b/sonoff/xsns_12_ads1115_i2cdev.ino @@ -99,7 +99,6 @@ void Ads1115Detect(void) void Ads1115Show(bool json) { if (ads1115_type) { - char stemp[10]; uint8_t dsxflg = 0; for (uint8_t i = 0; i < 4; i++) { @@ -107,12 +106,10 @@ void Ads1115Show(bool json) if (json) { if (!dsxflg ) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"ADS1115\":{"), mqtt_data); - stemp[0] = '\0'; + ResponseAppend_P(PSTR(",\"ADS1115\":{")); } + ResponseAppend_P(PSTR("%s\"A%d\":%d"), (dsxflg) ? "," : "", i, adc_value); dsxflg++; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"A%d\":%d"), mqtt_data, stemp, i, adc_value); - strlcpy(stemp, ",", sizeof(stemp)); #ifdef USE_WEBSERVER } else { WSContentSend_PD(HTTP_SNS_ANALOG, "ADS1115", i, adc_value); @@ -121,7 +118,7 @@ void Ads1115Show(bool json) } if (json) { if (dsxflg) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); } } } diff --git a/sonoff/xsns_13_ina219.ino b/sonoff/xsns_13_ina219.ino index fa6327f70..0dd7e5398 100644 --- a/sonoff/xsns_13_ina219.ino +++ b/sonoff/xsns_13_ina219.ino @@ -183,7 +183,7 @@ bool Ina219CommandSensor(void) Settings.ina219_mode = XdrvMailbox.payload; restart_flag = 2; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_NVALUE, XSNS_13, Settings.ina219_mode); + Response_P(S_JSON_SENSOR_INDEX_NVALUE, XSNS_13, Settings.ina219_mode); return serviced; } @@ -240,8 +240,8 @@ void Ina219Show(bool json) dtostrfd(ina219_current, Settings.flag2.current_resolution, current); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_POWERUSAGE "\":%s}"), - mqtt_data, ina219_types, voltage, current, power); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_POWERUSAGE "\":%s}"), + ina219_types, voltage, current, power); #ifdef USE_DOMOTICZ if (0 == tele_period) { DomoticzSensor(DZ_VOLTAGE, voltage); diff --git a/sonoff/xsns_14_sht3x.ino b/sonoff/xsns_14_sht3x.ino index e7aa63007..bdaa43e1a 100755 --- a/sonoff/xsns_14_sht3x.ino +++ b/sonoff/xsns_14_sht3x.ino @@ -110,7 +110,7 @@ void Sht3xShow(bool json) snprintf_P(types, sizeof(types), PSTR("%s-0x%02X"), sht3x_sensors[i].types, sht3x_sensors[i].address); // "SHT3X-0xXX" if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, types, temperature, humidity); + ResponseAppend_P(JSON_SNS_TEMPHUM, types, temperature, humidity); #ifdef USE_DOMOTICZ if ((0 == tele_period) && (0 == i)) { // We want the same first sensor to report to Domoticz in case a read is missed DomoticzTempHumSensor(temperature, humidity); diff --git a/sonoff/xsns_15_mhz19.ino b/sonoff/xsns_15_mhz19.ino index 058336f39..00f272a55 100644 --- a/sonoff/xsns_15_mhz19.ino +++ b/sonoff/xsns_15_mhz19.ino @@ -276,42 +276,42 @@ bool MhzCommandSensor(void) case 0: Settings.SensorBits1.mhz19b_abc_disable = true; MhzSendCmd(MHZ_CMND_ABCDISABLE); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_DISABLED); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_DISABLED); break; case 1: Settings.SensorBits1.mhz19b_abc_disable = false; MhzSendCmd(MHZ_CMND_ABCENABLE); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_ENABLED); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_ENABLED); break; case 2: MhzSendCmd(MHZ_CMND_ZEROPOINT); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_ZERO_POINT_CALIBRATION); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_ZERO_POINT_CALIBRATION); break; case 9: MhzSendCmd(MHZ_CMND_RESET); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RESET); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RESET); break; case 1000: MhzSendCmd(MHZ_CMND_RANGE_1000); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_1000); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_1000); break; case 2000: MhzSendCmd(MHZ_CMND_RANGE_2000); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_2000); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_2000); break; case 3000: MhzSendCmd(MHZ_CMND_RANGE_3000); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_3000); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_3000); break; case 5000: MhzSendCmd(MHZ_CMND_RANGE_5000); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_5000); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, D_JSON_RANGE_5000); break; default: if (!Settings.SensorBits1.mhz19b_abc_disable) { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_ENABLED); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_ENABLED); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_DISABLED); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_15, ABC_DISABLED); } } @@ -342,7 +342,7 @@ void MhzShow(bool json) GetTextIndexed(model, sizeof(model), mhz_type -1, kMhzModels); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_MODEL "\":\"%s\",\"" D_JSON_CO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s}"), mqtt_data, types, model, mhz_last_ppm, temperature); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_MODEL "\":\"%s\",\"" D_JSON_CO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s}"), types, model, mhz_last_ppm, temperature); #ifdef USE_DOMOTICZ if (0 == tele_period) { DomoticzSensor(DZ_AIRQUALITY, mhz_last_ppm); diff --git a/sonoff/xsns_16_tsl2561.ino b/sonoff/xsns_16_tsl2561.ino index 74f9fb0fb..af1d60d54 100644 --- a/sonoff/xsns_16_tsl2561.ino +++ b/sonoff/xsns_16_tsl2561.ino @@ -102,8 +102,8 @@ void Tsl2561Show(bool json) { if (tsl2561_valid) { if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"TSL2561\":{\"" D_JSON_ILLUMINANCE "\":%u.%03u}"), - mqtt_data, tsl2561_milliLux / 1000, tsl2561_milliLux % 1000); + ResponseAppend_P(PSTR(",\"TSL2561\":{\"" D_JSON_ILLUMINANCE "\":%u.%03u}"), + tsl2561_milliLux / 1000, tsl2561_milliLux % 1000); #ifdef USE_DOMOTICZ if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, (tsl2561_milliLux + 500) / 1000); } #endif // USE_DOMOTICZ diff --git a/sonoff/xsns_17_senseair.ino b/sonoff/xsns_17_senseair.ino index b5772a4d1..d11195b50 100644 --- a/sonoff/xsns_17_senseair.ino +++ b/sonoff/xsns_17_senseair.ino @@ -149,11 +149,11 @@ void SenseairShow(bool json) GetTextIndexed(senseair_types, sizeof(senseair_types), senseair_type -1, kSenseairTypes); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_CO2 "\":%d"), mqtt_data, senseair_types, senseair_co2); + ResponseAppend_P(PSTR("%s,\"%s\":{\"" D_JSON_CO2 "\":%d"), senseair_types, senseair_co2); if (senseair_type != 2) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s"), mqtt_data, temperature, humidity); + ResponseAppend_P(PSTR("%s,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s"), temperature, humidity); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + ResponseAppend_P(PSTR("}")); #ifdef USE_DOMOTICZ if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, senseair_co2); #endif // USE_DOMOTICZ diff --git a/sonoff/xsns_18_pms5003.ino b/sonoff/xsns_18_pms5003.ino index 6f9c97711..e77eb0271 100644 --- a/sonoff/xsns_18_pms5003.ino +++ b/sonoff/xsns_18_pms5003.ino @@ -132,7 +132,7 @@ void PmsShow(bool json) { if (pms_valid) { if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PMS5003\":{\"CF1\":%d,\"CF2.5\":%d,\"CF10\":%d,\"PM1\":%d,\"PM2.5\":%d,\"PM10\":%d,\"PB0.3\":%d,\"PB0.5\":%d,\"PB1\":%d,\"PB2.5\":%d,\"PB5\":%d,\"PB10\":%d}"), mqtt_data, + ResponseAppend_P(PSTR(",\"PMS5003\":{\"CF1\":%d,\"CF2.5\":%d,\"CF10\":%d,\"PM1\":%d,\"PM2.5\":%d,\"PM10\":%d,\"PB0.3\":%d,\"PB0.5\":%d,\"PB1\":%d,\"PB2.5\":%d,\"PB5\":%d,\"PB10\":%d}"), pms_data.pm10_standard, pms_data.pm25_standard, pms_data.pm100_standard, pms_data.pm10_env, pms_data.pm25_env, pms_data.pm100_env, pms_data.particles_03um, pms_data.particles_05um, pms_data.particles_10um, pms_data.particles_25um, pms_data.particles_50um, pms_data.particles_100um); diff --git a/sonoff/xsns_19_mgs.ino b/sonoff/xsns_19_mgs.ino index 942664b96..30b979eaa 100644 --- a/sonoff/xsns_19_mgs.ino +++ b/sonoff/xsns_19_mgs.ino @@ -64,14 +64,14 @@ void MGSShow(bool json) { char buffer[33]; if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"MGS\":{\"NH3\":%s"), mqtt_data, measure_gas(NH3, buffer)); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"CO\":%s"), mqtt_data, measure_gas(CO, buffer)); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"NO2\":%s"), mqtt_data, measure_gas(NO2, buffer)); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"C3H8\":%s"), mqtt_data, measure_gas(C3H8, buffer)); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"C4H10\":%s"), mqtt_data, measure_gas(C4H10, buffer)); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"CH4\":%s"), mqtt_data, measure_gas(GAS_CH4, buffer)); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"H2\":%s"), mqtt_data, measure_gas(H2, buffer)); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"C2H5OH\":%s}"), mqtt_data, measure_gas(C2H5OH, buffer)); + ResponseAppend_P(PSTR(",\"MGS\":{\"NH3\":%s"), measure_gas(NH3, buffer)); + ResponseAppend_P(PSTR(",\"CO\":%s"), measure_gas(CO, buffer)); + ResponseAppend_P(PSTR(",\"NO2\":%s"), measure_gas(NO2, buffer)); + ResponseAppend_P(PSTR(",\"C3H8\":%s"), measure_gas(C3H8, buffer)); + ResponseAppend_P(PSTR(",\"C4H10\":%s"), measure_gas(C4H10, buffer)); + ResponseAppend_P(PSTR(",\"CH4\":%s"), measure_gas(GAS_CH4, buffer)); + ResponseAppend_P(PSTR(",\"H2\":%s"), measure_gas(H2, buffer)); + ResponseAppend_P(PSTR(",\"C2H5OH\":%s}"), measure_gas(C2H5OH, buffer)); #ifdef USE_WEBSERVER } else { WSContentSend_PD(HTTP_MGS_GAS, "NH3", measure_gas(NH3, buffer)); diff --git a/sonoff/xsns_20_novasds.ino b/sonoff/xsns_20_novasds.ino index 702d3d8fe..25f73c2df 100644 --- a/sonoff/xsns_20_novasds.ino +++ b/sonoff/xsns_20_novasds.ino @@ -195,7 +195,7 @@ void NovaSdsShow(bool json) char pm2_5[33]; dtostrfd(pm2_5f, 1, pm2_5); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SDS0X1\":{\"PM2.5\":%s,\"PM10\":%s}"), mqtt_data, pm2_5, pm10); + ResponseAppend_P(PSTR(",\"SDS0X1\":{\"PM2.5\":%s,\"PM10\":%s}"), pm2_5, pm10); #ifdef USE_DOMOTICZ if (0 == tele_period) { DomoticzSensor(DZ_VOLTAGE, pm2_5); // PM2.5 diff --git a/sonoff/xsns_21_sgp30.ino b/sonoff/xsns_21_sgp30.ino index a544e4472..d8241f1d6 100644 --- a/sonoff/xsns_21_sgp30.ino +++ b/sonoff/xsns_21_sgp30.ino @@ -71,7 +71,7 @@ void Sgp30Show(bool json) { if (sgp30_ready) { if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SGP30\":{\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TVOC "\":%d}"), mqtt_data, sgp.eCO2, sgp.TVOC); + ResponseAppend_P(PSTR(",\"SGP30\":{\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TVOC "\":%d}"), sgp.eCO2, sgp.TVOC); #ifdef USE_DOMOTICZ if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, sgp.eCO2); #endif // USE_DOMOTICZ diff --git a/sonoff/xsns_22_sr04.ino b/sonoff/xsns_22_sr04.ino index 3c8a933bf..f30ff11f7 100644 --- a/sonoff/xsns_22_sr04.ino +++ b/sonoff/xsns_22_sr04.ino @@ -57,7 +57,7 @@ void Sr04Show(bool json) dtostrfd(distance, 3, distance_chr); if(json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SR04\":{\"" D_JSON_DISTANCE "\":%s}"), mqtt_data, distance_chr); + ResponseAppend_P(PSTR(",\"SR04\":{\"" D_JSON_DISTANCE "\":%s}"), distance_chr); #ifdef USE_DOMOTICZ if (0 == tele_period) { DomoticzSensor(DZ_COUNT, distance_chr); // Send distance as Domoticz Counter value diff --git a/sonoff/xsns_23_sdm120.ino b/sonoff/xsns_23_sdm120.ino index c77ca1875..8f0b6b74f 100644 --- a/sonoff/xsns_23_sdm120.ino +++ b/sonoff/xsns_23_sdm120.ino @@ -314,11 +314,11 @@ void SDM120Show(bool json) #endif // USE_SDM220 if (json) { #ifdef USE_SDM220 - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_ACTIVE_POWERUSAGE "\":%s,\"" D_JSON_APPARENT_POWERUSAGE "\":%s,\"" D_JSON_REACTIVE_POWERUSAGE "\":%s,\"" D_JSON_FREQUENCY "\":%s,\"" D_JSON_POWERFACTOR "\":%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_PHASE_ANGLE "\":%s,\"" D_JSON_IMPORT_ACTIVE "\":%s,\"" D_JSON_EXPORT_ACTIVE "\":%s,\"" D_JSON_IMPORT_REACTIVE "\":%s,\"" D_JSON_EXPORT_REACTIVE "\":%s,\"" D_JSON_TOTAL_REACTIVE "\":%s}"), - mqtt_data, energy_total, active_power, apparent_power, reactive_power, frequency, power_factor, voltage, current, phase_angle, import_active, export_active, import_reactive, export_reactive, total_reactive); + ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_ACTIVE_POWERUSAGE "\":%s,\"" D_JSON_APPARENT_POWERUSAGE "\":%s,\"" D_JSON_REACTIVE_POWERUSAGE "\":%s,\"" D_JSON_FREQUENCY "\":%s,\"" D_JSON_POWERFACTOR "\":%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s,\"" D_JSON_PHASE_ANGLE "\":%s,\"" D_JSON_IMPORT_ACTIVE "\":%s,\"" D_JSON_EXPORT_ACTIVE "\":%s,\"" D_JSON_IMPORT_REACTIVE "\":%s,\"" D_JSON_EXPORT_REACTIVE "\":%s,\"" D_JSON_TOTAL_REACTIVE "\":%s}"), + energy_total, active_power, apparent_power, reactive_power, frequency, power_factor, voltage, current, phase_angle, import_active, export_active, import_reactive, export_reactive, total_reactive); #else - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_ACTIVE_POWERUSAGE "\":%s,\"" D_JSON_APPARENT_POWERUSAGE "\":%s,\"" D_JSON_REACTIVE_POWERUSAGE "\":%s,\"" D_JSON_FREQUENCY "\":%s,\"" D_JSON_POWERFACTOR "\":%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s}"), - mqtt_data, energy_total, active_power, apparent_power, reactive_power, frequency, power_factor, voltage, current); + ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_ACTIVE_POWERUSAGE "\":%s,\"" D_JSON_APPARENT_POWERUSAGE "\":%s,\"" D_JSON_REACTIVE_POWERUSAGE "\":%s,\"" D_JSON_FREQUENCY "\":%s,\"" D_JSON_POWERFACTOR "\":%s,\"" D_JSON_VOLTAGE "\":%s,\"" D_JSON_CURRENT "\":%s}"), + energy_total, active_power, apparent_power, reactive_power, frequency, power_factor, voltage, current); #endif // USE_SDM220 #ifdef USE_DOMOTICZ if (0 == tele_period) { diff --git a/sonoff/xsns_24_si1145.ino b/sonoff/xsns_24_si1145.ino index 56bce1018..2a1c26cd5 100644 --- a/sonoff/xsns_24_si1145.ino +++ b/sonoff/xsns_24_si1145.ino @@ -329,8 +329,8 @@ void Si1145Show(bool json) uint16_t infrared = Si1145ReadIR(); uint16_t uvindex = Si1145ReadUV(); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SI1145\":{\"" D_JSON_ILLUMINANCE "\":%d,\"" D_JSON_INFRARED "\":%d,\"" D_JSON_UV_INDEX "\":%d.%d}"), - mqtt_data, visible, infrared, uvindex /100, uvindex %100); + ResponseAppend_P(PSTR(",\"SI1145\":{\"" D_JSON_ILLUMINANCE "\":%d,\"" D_JSON_INFRARED "\":%d,\"" D_JSON_UV_INDEX "\":%d.%d}"), + visible, infrared, uvindex /100, uvindex %100); #ifdef USE_DOMOTICZ if (0 == tele_period) DomoticzSensor(DZ_ILLUMINANCE, visible); #endif // USE_DOMOTICZ diff --git a/sonoff/xsns_25_sdm630.ino b/sonoff/xsns_25_sdm630.ino index 013964915..c71009ce4 100644 --- a/sonoff/xsns_25_sdm630.ino +++ b/sonoff/xsns_25_sdm630.ino @@ -302,10 +302,10 @@ void SDM630Show(bool json) dtostrfd(sdm630_energy_total, Settings.flag2.energy_resolution, energy_total); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL "\":%s,\"" + ResponseAppend_P(PSTR(",\"" D_RSLT_ENERGY "\":{\"" D_JSON_TOTAL "\":%s,\"" D_JSON_ACTIVE_POWERUSAGE "\":[%s,%s,%s],\"" D_JSON_REACTIVE_POWERUSAGE "\":[%s,%s,%s],\"" D_JSON_POWERFACTOR "\":[%s,%s,%s],\"" D_JSON_VOLTAGE "\":[%s,%s,%s],\"" D_JSON_CURRENT "\":[%s,%s,%s]}"), - mqtt_data, energy_total, active_power_l1, active_power_l2, active_power_l3, + energy_total, active_power_l1, active_power_l2, active_power_l3, reactive_power_l1, reactive_power_l2, reactive_power_l3, power_factor_l1, power_factor_l2, power_factor_l3, voltage_l1, voltage_l2, voltage_l3, diff --git a/sonoff/xsns_26_lm75ad.ino b/sonoff/xsns_26_lm75ad.ino index b7b92fca7..88769b3aa 100644 --- a/sonoff/xsns_26_lm75ad.ino +++ b/sonoff/xsns_26_lm75ad.ino @@ -85,7 +85,7 @@ void LM75ADShow(bool json) dtostrfd(t, Settings.flag2.temperature_resolution, temperature); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"LM75AD\":{\"" D_JSON_TEMPERATURE "\":%s}"), mqtt_data, temperature); + ResponseAppend_P(PSTR(",\"LM75AD\":{\"" D_JSON_TEMPERATURE "\":%s}"), temperature); #ifdef USE_DOMOTICZ if (0 == tele_period) DomoticzSensor(DZ_TEMP, temperature); #endif // USE_DOMOTICZ diff --git a/sonoff/xsns_27_apds9960.ino b/sonoff/xsns_27_apds9960.ino index 5be8b0e5b..7594a5322 100644 --- a/sonoff/xsns_27_apds9960.ino +++ b/sonoff/xsns_27_apds9960.ino @@ -1874,7 +1874,7 @@ void APDS9960_loop(void) if (recovery_loop_counter == 1 && APDS9960_overload){ //restart sensor just before the end of recovery from long press enableGestureSensor(); APDS9960_overload = false; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"Gesture\":\"On\"}")); + Response_P(PSTR("{\"Gesture\":\"On\"}")); MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); // only after the long break we report, that we are online again gesture_mode = 1; } @@ -1887,7 +1887,7 @@ void APDS9960_loop(void) { disableGestureSensor(); recovery_loop_counter = APDS9960_LONG_RECOVERY; // long pause after overload/long press - number of stateloops - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"Gesture\":\"Off\"}")); + Response_P(PSTR("{\"Gesture\":\"Off\"}")); MqttPublishPrefixTopic_P(RESULT_OR_TELE, mqtt_data); gesture_mode = 0; } @@ -1959,8 +1959,8 @@ void APDS9960_show(bool json) sprintf (cct_chr, "%u", color_data.cct); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"Red\":%s,\"Green\":%s,\"Blue\":%s,\"Ambient\":%s,\"CCT\":%s,\"Proximity\":%s}"), - mqtt_data, APDS9960stype, red_chr, green_chr, blue_chr, ambient_chr, cct_chr, prox_chr); + ResponseAppend_P(PSTR(",\"%s\":{\"Red\":%s,\"Green\":%s,\"Blue\":%s,\"Ambient\":%s,\"CCT\":%s,\"Proximity\":%s}"), + APDS9960stype, red_chr, green_chr, blue_chr, ambient_chr, cct_chr, prox_chr); #ifdef USE_WEBSERVER } else { WSContentSend_PD(HTTP_APDS_9960_SNS, red_chr, green_chr, blue_chr, ambient_chr, cct_chr, prox_chr ); @@ -1969,7 +1969,7 @@ void APDS9960_show(bool json) } else { if (json && (currentGesture[0] != '\0' )) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"%s\":1}"), mqtt_data, APDS9960stype, currentGesture); + ResponseAppend_P(PSTR(",\"%s\":{\"%s\":1}"), APDS9960stype, currentGesture); currentGesture[0] = '\0'; } } @@ -2025,7 +2025,7 @@ bool APDS9960CommandSensor(void) } break; } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_27, GetStateText(gesture_mode)); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_27, GetStateText(gesture_mode)); return serviced; } diff --git a/sonoff/xsns_29_mcp230xx.ino b/sonoff/xsns_29_mcp230xx.ino index 5aa4992dd..bef4e1738 100644 --- a/sonoff/xsns_29_mcp230xx.ino +++ b/sonoff/xsns_29_mcp230xx.ino @@ -303,9 +303,8 @@ void MCP230xx_CheckForInterrupt(void) { break; } if (int_tele) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"MCP230XX_INT\":{\"D%i\":%i,\"MS\":%lu}"), mqtt_data, intp+(mcp230xx_port*8), ((mcp230xx_intcap >> intp) & 0x01),millis_since_last_int); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + Response_P(PSTR("{\"" D_JSON_TIME "\":\"%s\",\"MCP230XX_INT\":{\"D%i\":%i,\"MS\":%lu}}"), + GetDateAndTime(DT_LOCAL).c_str(), intp+(mcp230xx_port*8), ((mcp230xx_intcap >> intp) & 0x01),millis_since_last_int); MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR("MCP230XX_INT")); } if (int_event) { @@ -329,14 +328,14 @@ void MCP230xx_Show(bool json) if (json) { if (mcp230xx_type > 0) { // we have at least 8 pins uint8_t gpio = MCP230xx_readGPIO(0); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"MCP230XX\":{\"D0\":%i,\"D1\":%i,\"D2\":%i,\"D3\":%i,\"D4\":%i,\"D5\":%i,\"D6\":%i,\"D7\":%i"), - mqtt_data,(gpio>>0)&1,(gpio>>1)&1,(gpio>>2)&1,(gpio>>3)&1,(gpio>>4)&1,(gpio>>5)&1,(gpio>>6)&1,(gpio>>7)&1); + ResponseAppend_P(PSTR(",\"MCP230XX\":{\"D0\":%i,\"D1\":%i,\"D2\":%i,\"D3\":%i,\"D4\":%i,\"D5\":%i,\"D6\":%i,\"D7\":%i"), + (gpio>>0)&1,(gpio>>1)&1,(gpio>>2)&1,(gpio>>3)&1,(gpio>>4)&1,(gpio>>5)&1,(gpio>>6)&1,(gpio>>7)&1); if (2 == mcp230xx_type) { gpio = MCP230xx_readGPIO(1); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"D8\":%i,\"D9\":%i,\"D10\":%i,\"D11\":%i,\"D12\":%i,\"D13\":%i,\"D14\":%i,\"D15\":%i"), - mqtt_data,(gpio>>0)&1,(gpio>>1)&1,(gpio>>2)&1,(gpio>>3)&1,(gpio>>4)&1,(gpio>>5)&1,(gpio>>6)&1,(gpio>>7)&1); + ResponseAppend_P(PSTR(",\"D8\":%i,\"D9\":%i,\"D10\":%i,\"D11\":%i,\"D12\":%i,\"D13\":%i,\"D14\":%i,\"D15\":%i"), + (gpio>>0)&1,(gpio>>1)&1,(gpio>>2)&1,(gpio>>3)&1,(gpio>>4)&1,(gpio>>5)&1,(gpio>>6)&1,(gpio>>7)&1); } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s"),mqtt_data,"}"); + ResponseAppend_P(PSTR("}")); } } } @@ -384,9 +383,9 @@ void MCP230xx_SetOutPin(uint8_t pin,uint8_t pinstate) { if (interlock && (pinmo == Settings.mcp230xx_config[pin+pinadd].pinmode)) { char stt1[4]; sprintf(stt1,ConvertNumTxt((portpins >> (pin+pinadd-(port*8))&1), pinmo)); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"S29cmnd_D%i\":{\"COMMAND\":\"%s\",\"STATE\":\"%s\"},\"S29cmnd_D%i\":{\"STATE\":\"%s\"}}"),pin, cmnd, stt, pin+pinadd, stt1); + Response_P(PSTR("{\"S29cmnd_D%i\":{\"COMMAND\":\"%s\",\"STATE\":\"%s\"},\"S29cmnd_D%i\":{\"STATE\":\"%s\"}}"),pin, cmnd, stt, pin+pinadd, stt1); } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_CMND_RESPONSE, pin, cmnd, stt); + Response_P(MCP230XX_CMND_RESPONSE, pin, cmnd, stt); } } @@ -420,7 +419,7 @@ void MCP230xx_Reset(uint8_t pinmode) { uint8_t intmode = 3; if ((pinmode > 1) && (pinmode < 5)) { intmode = 0; } sprintf(intmodetxt,IntModeTxt(intmode)); - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,99,pinmode,pulluptxt,intmodetxt,""); + Response_P(MCP230XX_SENSOR_RESPONSE,99,pinmode,pulluptxt,intmodetxt,""); } bool MCP230xx_Command(void) { @@ -454,11 +453,11 @@ bool MCP230xx_Command(void) { uint8_t intpri = atoi(subStr(sub_string, XdrvMailbox.data, ",", 2)); if ((intpri >= 0) && (intpri <= 20)) { Settings.mcp230xx_int_prio = intpri; - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_INTCFG_RESPONSE,"PRI",99,Settings.mcp230xx_int_prio); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; + Response_P(MCP230XX_INTCFG_RESPONSE,"PRI",99,Settings.mcp230xx_int_prio); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; return serviced; } } else { // No parameter was given for INTPRI so we return the current configured value - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_INTCFG_RESPONSE,"PRI",99,Settings.mcp230xx_int_prio); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; + Response_P(MCP230XX_INTCFG_RESPONSE,"PRI",99,Settings.mcp230xx_int_prio); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; return serviced; } } @@ -469,11 +468,11 @@ bool MCP230xx_Command(void) { if ((inttim >= 0) && (inttim <= 3600)) { Settings.mcp230xx_int_timer = inttim; MCP230xx_CheckForIntCounter(); // update register on whether or not we should be counting interrupts - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_INTCFG_RESPONSE,"TIMER",99,Settings.mcp230xx_int_timer); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; + Response_P(MCP230XX_INTCFG_RESPONSE,"TIMER",99,Settings.mcp230xx_int_timer); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; return serviced; } } else { // No parameter was given for INTTIM so we return the current configured value - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_INTCFG_RESPONSE,"TIMER",99,Settings.mcp230xx_int_timer); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; + Response_P(MCP230XX_INTCFG_RESPONSE,"TIMER",99,Settings.mcp230xx_int_timer); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; return serviced; } } @@ -498,14 +497,14 @@ bool MCP230xx_Command(void) { MCP230xx_CheckForIntCounter(); AddLog_P2(LOG_LEVEL_INFO, PSTR("*** WARNING *** - Disabled INTCNT for pin D%i"),pin); } - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_INTCFG_RESPONSE,"DEF",pin,Settings.mcp230xx_config[pin].int_report_defer); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; + Response_P(MCP230XX_INTCFG_RESPONSE,"DEF",pin,Settings.mcp230xx_config[pin].int_report_defer); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; return serviced; } else { serviced=false; return serviced; } } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_INTCFG_RESPONSE,"DEF",pin,Settings.mcp230xx_config[pin].int_report_defer); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; + Response_P(MCP230XX_INTCFG_RESPONSE,"DEF",pin,Settings.mcp230xx_config[pin].int_report_defer); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; return serviced; } } @@ -544,14 +543,14 @@ bool MCP230xx_Command(void) { AddLog_P2(LOG_LEVEL_INFO, PSTR("*** WARNING *** - INTCNT enabled for pin D%i but global INTTIMER is disabled!"),pin); } MCP230xx_CheckForIntCounter(); // update register on whether or not we should be counting interrupts - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_INTCFG_RESPONSE,"CNT",pin,Settings.mcp230xx_config[pin].int_count_en); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; + Response_P(MCP230XX_INTCFG_RESPONSE,"CNT",pin,Settings.mcp230xx_config[pin].int_count_en); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; return serviced; } else { serviced=false; return serviced; } } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_INTCFG_RESPONSE,"CNT",pin,Settings.mcp230xx_config[pin].int_count_en); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; + Response_P(MCP230XX_INTCFG_RESPONSE,"CNT",pin,Settings.mcp230xx_config[pin].int_count_en); // "{\"MCP230xx_INT%s\":{\"D_%i\":%i}}"; return serviced; } } @@ -578,7 +577,7 @@ bool MCP230xx_Command(void) { uint8_t int_retain = atoi(subStr(sub_string, XdrvMailbox.data, ",", 3)); if ((int_retain >= 0) && (int_retain <= 1)) { Settings.mcp230xx_config[pin].int_retain_flag=int_retain; - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_INTCFG_RESPONSE,"INT_RETAIN",pin,Settings.mcp230xx_config[pin].int_retain_flag); + Response_P(MCP230XX_INTCFG_RESPONSE,"INT_RETAIN",pin,Settings.mcp230xx_config[pin].int_retain_flag); MCP230xx_CheckForIntRetainer(); return serviced; } else { @@ -586,7 +585,7 @@ bool MCP230xx_Command(void) { return serviced; } } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_INTCFG_RESPONSE,"INT_RETAIN",pin,Settings.mcp230xx_config[pin].int_retain_flag); + Response_P(MCP230XX_INTCFG_RESPONSE,"INT_RETAIN",pin,Settings.mcp230xx_config[pin].int_retain_flag); return serviced; } } @@ -619,10 +618,10 @@ bool MCP230xx_Command(void) { #ifdef USE_MCP230xx_OUTPUT uint8_t pinmod = Settings.mcp230xx_config[pin].pinmode; sprintf(pinstatustxtr,ConvertNumTxt(portdata>>(pin-(port*8))&1,pinmod)); - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,pin,pinmod,pulluptxtr,intmodetxt,pinstatustxtr); + Response_P(MCP230XX_SENSOR_RESPONSE,pin,pinmod,pulluptxtr,intmodetxt,pinstatustxtr); #else // not USE_MCP230xx_OUTPUT sprintf(pinstatustxtr,ConvertNumTxt(portdata>>(pin-(port*8))&1)); - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,pin,Settings.mcp230xx_config[pin].pinmode,pulluptxtr,intmodetxt,pinstatustxtr); + Response_P(MCP230XX_SENSOR_RESPONSE,pin,Settings.mcp230xx_config[pin].pinmode,pulluptxtr,intmodetxt,pinstatustxtr); #endif //USE_MCP230xx_OUTPUT return serviced; } @@ -682,7 +681,7 @@ bool MCP230xx_Command(void) { #else // not USE_MCP230xx_OUTPUT sprintf(pinstatustxtc,ConvertNumTxt(portdata>>(pin-(port*8))&1)); #endif // USE_MCP230xx_OUTPUT - snprintf_P(mqtt_data, sizeof(mqtt_data), MCP230XX_SENSOR_RESPONSE,pin,pinmode,pulluptxtc,intmodetxt,pinstatustxtc); + Response_P(MCP230XX_SENSOR_RESPONSE,pin,pinmode,pulluptxtc,intmodetxt,pinstatustxtc); return serviced; } } else { @@ -730,14 +729,14 @@ void MCP230xx_OutputTelemetry(void) { } if (outputcount) { char stt[7]; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\",\"MCP230_OUT\": {"), GetDateAndTime(DT_LOCAL).c_str()); + Response_P(PSTR("{\"" D_JSON_TIME "\":\"%s\",\"MCP230_OUT\": {"), GetDateAndTime(DT_LOCAL).c_str()); for (uint8_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { if (Settings.mcp230xx_config[pinx].pinmode >= 5) { sprintf(stt,ConvertNumTxt(((gpiototal>>pinx)&1),Settings.mcp230xx_config[pinx].pinmode)); - snprintf_P(mqtt_data,sizeof(mqtt_data), PSTR("%s\"OUT_D%i\":\"%s\","),mqtt_data,pinx,stt); + ResponseAppend_P(PSTR("\"OUT_D%i\":\"%s\","),pinx,stt); } } - snprintf_P(mqtt_data,sizeof(mqtt_data),PSTR("%s\"END\":1}}"),mqtt_data); + ResponseAppend_P(PSTR("\"END\":1}}")); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); } } @@ -745,29 +744,29 @@ void MCP230xx_OutputTelemetry(void) { #endif // USE_MCP230xx_OUTPUT void MCP230xx_Interrupt_Counter_Report(void) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\",\"MCP230_INTTIMER\": {"), GetDateAndTime(DT_LOCAL).c_str()); + Response_P(PSTR("{\"" D_JSON_TIME "\":\"%s\",\"MCP230_INTTIMER\": {"), GetDateAndTime(DT_LOCAL).c_str()); for (uint8_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { if (Settings.mcp230xx_config[pinx].int_count_en) { // Counting is enabled for this pin so we add to report - snprintf_P(mqtt_data,sizeof(mqtt_data), PSTR("%s\"INTCNT_D%i\":%i,"),mqtt_data,pinx,mcp230xx_int_counter[pinx]); + ResponseAppend_P(PSTR("\"INTCNT_D%i\":%i,"),pinx,mcp230xx_int_counter[pinx]); mcp230xx_int_counter[pinx]=0; } } - snprintf_P(mqtt_data,sizeof(mqtt_data),PSTR("%s\"END\":1}}"),mqtt_data); + ResponseAppend_P(PSTR("\"END\":1}}")); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); mcp230xx_int_sec_counter = 0; } void MCP230xx_Interrupt_Retain_Report(void) { uint16_t retainresult = 0; - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\",\"MCP_INTRETAIN\": {"), GetDateAndTime(DT_LOCAL).c_str()); + Response_P(PSTR("{\"" D_JSON_TIME "\":\"%s\",\"MCP_INTRETAIN\": {"), GetDateAndTime(DT_LOCAL).c_str()); for (uint8_t pinx = 0;pinx < mcp230xx_pincount;pinx++) { if (Settings.mcp230xx_config[pinx].int_retain_flag) { - snprintf_P(mqtt_data,sizeof(mqtt_data), PSTR("%s\"D%i\":%i,"),mqtt_data,pinx,mcp230xx_int_retainer[pinx]); + ResponseAppend_P(PSTR("\"D%i\":%i,"),pinx,mcp230xx_int_retainer[pinx]); retainresult |= (((mcp230xx_int_retainer[pinx])&1) << pinx); mcp230xx_int_retainer[pinx]=0; } } - snprintf_P(mqtt_data,sizeof(mqtt_data),PSTR("%s\"Value\":%u}}"),mqtt_data,retainresult); + ResponseAppend_P(PSTR("\"Value\":%u}}"),retainresult); MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); } diff --git a/sonoff/xsns_30_mpr121.ino b/sonoff/xsns_30_mpr121.ino index 10ea46078..6f23117c6 100644 --- a/sonoff/xsns_30_mpr121.ino +++ b/sonoff/xsns_30_mpr121.ino @@ -343,7 +343,7 @@ void Mpr121Show(struct mpr121 *pS, uint8_t function) // Append sensor to JSON message string if (FUNC_JSON_APPEND == function) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"MPR121%c\":{"), mqtt_data, pS->id[i]); + ResponseAppend_P(PSTR(",\"MPR121%c\":{"), pS->id[i]); } // Loop through buttons for (uint8_t j = 0; j < 13; j++) { @@ -351,7 +351,7 @@ void Mpr121Show(struct mpr121 *pS, uint8_t function) // Add sensor, button and state to MQTT JSON message string if ((FUNC_EVERY_50_MSECOND == function) && (BITC(i, j) != BITP(i, j))) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"MPR121%c\":{\"Button%i\":%i}}"), pS->id[i], j, BITC(i, j)); + Response_P(PSTR("{\"MPR121%c\":{\"Button%i\":%i}}"), pS->id[i], j, BITC(i, j)); MqttPublishPrefixTopic_P(RESULT_OR_STAT, mqtt_data); } // Add buttons to web string @@ -363,7 +363,7 @@ void Mpr121Show(struct mpr121 *pS, uint8_t function) // Append JSON message string if (FUNC_JSON_APPEND == function) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"Button%i\":%i"), mqtt_data, (j > 0 ? "," : ""), j, BITC(i, j)); + ResponseAppend_P(PSTR("%s\"Button%i\":%i"), (j > 0 ? "," : ""), j, BITC(i, j)); } } // for-loop j @@ -372,7 +372,7 @@ void Mpr121Show(struct mpr121 *pS, uint8_t function) // Append JSON message string if (FUNC_JSON_APPEND == function) { - snprintf_P(mqtt_data, sizeof(mqtt_data), "%s}", mqtt_data); + ResponseAppend_P(PSTR("}")); } } // if->running } // for-loop i diff --git a/sonoff/xsns_31_ccs811.ino b/sonoff/xsns_31_ccs811.ino index 9ce63b228..2624d0b8c 100644 --- a/sonoff/xsns_31_ccs811.ino +++ b/sonoff/xsns_31_ccs811.ino @@ -85,7 +85,7 @@ void CCS811Show(bool json) { if (CCS811_ready) { if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"CCS811\":{\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TVOC "\":%d}"), mqtt_data,eCO2,TVOC); + ResponseAppend_P(PSTR(",\"CCS811\":{\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TVOC "\":%d}"), eCO2,TVOC); #ifdef USE_DOMOTICZ if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, eCO2); #endif // USE_DOMOTICZ diff --git a/sonoff/xsns_32_mpu6050.ino b/sonoff/xsns_32_mpu6050.ino index e7dddd953..6ac8763bd 100644 --- a/sonoff/xsns_32_mpu6050.ino +++ b/sonoff/xsns_32_mpu6050.ino @@ -205,8 +205,8 @@ void MPU_6050Show(bool json) snprintf_P(json_axis_gy, sizeof(json_axis_gy), PSTR(",\"" D_JSON_AXIS_GY "\":%s"), axis_gy); char json_axis_gz[25]; snprintf_P(json_axis_gz, sizeof(json_axis_gz), PSTR(",\"" D_JSON_AXIS_GZ "\":%s"), axis_gz); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s%s%s%s%s%s}"), - mqtt_data, D_SENSOR_MPU6050, temperature, json_axis_ax, json_axis_ay, json_axis_az, json_axis_gx, json_axis_gy, json_axis_gz); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s%s%s%s%s%s%s}"), + D_SENSOR_MPU6050, temperature, json_axis_ax, json_axis_ay, json_axis_az, json_axis_gx, json_axis_gy, json_axis_gz); #ifdef USE_DOMOTICZ DomoticzSensor(DZ_TEMP, temperature); #endif // USE_DOMOTICZ diff --git a/sonoff/xsns_34_hx711.ino b/sonoff/xsns_34_hx711.ino index 272e35a9e..b72ef0a9f 100644 --- a/sonoff/xsns_34_hx711.ino +++ b/sonoff/xsns_34_hx711.ino @@ -128,7 +128,7 @@ void HxCalibrationStateTextJson(uint8_t msg_id) char cal_text[30]; hx_calibrate_msg = msg_id; - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, GetTextIndexed(cal_text, sizeof(cal_text), hx_calibrate_msg, kHxCalibrationStates)); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, GetTextIndexed(cal_text, sizeof(cal_text), hx_calibrate_msg, kHxCalibrationStates)); if (msg_id < 3) { MqttPublishPrefixTopic_P(RESULT_OR_STAT, PSTR("Sensor34")); } } @@ -162,7 +162,7 @@ bool HxCommand(void) switch (XdrvMailbox.payload) { case 1: // Reset scale HxReset(); - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, "Reset"); + Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, "Reset"); break; case 2: // Calibrate if (strstr(XdrvMailbox.data, ",")) { @@ -206,7 +206,7 @@ bool HxCommand(void) if (show_parms) { char item[33]; dtostrfd((float)Settings.weight_item / 10, 1, item); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"Sensor34\":{\"" D_JSON_WEIGHT_REF "\":%d,\"" D_JSON_WEIGHT_CAL "\":%d,\"" D_JSON_WEIGHT_MAX "\":%d,\"" D_JSON_WEIGHT_ITEM "\":%s}}"), + Response_P(PSTR("{\"Sensor34\":{\"" D_JSON_WEIGHT_REF "\":%d,\"" D_JSON_WEIGHT_CAL "\":%d,\"" D_JSON_WEIGHT_MAX "\":%d,\"" D_JSON_WEIGHT_ITEM "\":%s}}"), Settings.weight_reference, Settings.weight_calibration, Settings.weight_max * 1000, item); } @@ -348,7 +348,7 @@ void HxShow(bool json) dtostrfd(weight, Settings.flag2.weight_resolution, weight_chr); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"HX711\":{\"" D_JSON_WEIGHT "\":%s%s}"), mqtt_data, weight_chr, scount); + ResponseAppend_P(PSTR(",\"HX711\":{\"" D_JSON_WEIGHT "\":%s%s}"), weight_chr, scount); #ifdef USE_WEBSERVER } else { WSContentSend_PD(HTTP_HX711_WEIGHT, weight_chr); diff --git a/sonoff/xsns_35_tx20.ino b/sonoff/xsns_35_tx20.ino index 444c5231d..b5e8a2091 100644 --- a/sonoff/xsns_35_tx20.ino +++ b/sonoff/xsns_35_tx20.ino @@ -182,8 +182,8 @@ void Tx20Show(bool json) GetTextIndexed(wind_direction_string, sizeof(wind_direction_string), tx20_wind_direction, kTx20Directions); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"TX20\":{\"Speed\":%s,\"SpeedAvg\":%s,\"SpeedMax\":%s,\"Direction\":\"%s\"}"), - mqtt_data, wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string); + ResponseAppend_P(PSTR(",\"TX20\":{\"Speed\":%s,\"SpeedAvg\":%s,\"SpeedMax\":%s,\"Direction\":\"%s\"}"), + wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string); #ifdef USE_WEBSERVER } else { WSContentSend_PD(HTTP_SNS_TX20, wind_speed_string, wind_speed_avg_string, wind_speed_max_string, wind_direction_string); diff --git a/sonoff/xsns_36_mgc3130.ino b/sonoff/xsns_36_mgc3130.ino index c767c192c..055126c6d 100644 --- a/sonoff/xsns_36_mgc3130.ino +++ b/sonoff/xsns_36_mgc3130.ino @@ -529,8 +529,8 @@ void MGC3130_show(bool json) if (json) { if (MGC3130_mode == 3 && !MGC3130_triggeredByTouch) { if (MGC_data.out.systemInfo.positionValid && !(MGC_data.out.x == MGC3130_lastSentX && MGC_data.out.y == MGC3130_lastSentY && MGC_data.out.z == MGC3130_lastSentZ)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"X\":%u,\"Y\":%u,\"Z\":%u}"), - mqtt_data, MGC3130stype, MGC_data.out.x/64, MGC_data.out.y/64, (MGC_data.out.z-(uint16_t)MGC3130_MIN_ZVALUE)/64); + ResponseAppend_P(PSTR(",\"%s\":{\"X\":%u,\"Y\":%u,\"Z\":%u}"), + MGC3130stype, MGC_data.out.x/64, MGC_data.out.y/64, (MGC_data.out.z-(uint16_t)MGC3130_MIN_ZVALUE)/64); MGC3130_lastSentX = MGC_data.out.x; MGC3130_lastSentY = MGC_data.out.y; MGC3130_lastSentZ = MGC_data.out.z; @@ -540,7 +540,7 @@ void MGC3130_show(bool json) if (MGC3130_mode == 2) { if (MGC_data.out.systemInfo.airWheelValid && (MGC3130_rotValue != MGC3130_lastSentRotValue)) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"AW\":%i}"), mqtt_data, MGC3130stype, MGC3130_rotValue); + ResponseAppend_P(PSTR(",\"%s\":{\"AW\":%i}"), MGC3130stype, MGC3130_rotValue); MGC3130_lastSentRotValue = MGC3130_rotValue; } } @@ -549,7 +549,7 @@ void MGC3130_show(bool json) if (millis() - MGC3130_touchTimeStamp > 220 ) { MGC3130_touchCounter = 1; } - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"%s\":%u}"), mqtt_data, MGC3130stype, MGC3130_currentGesture, MGC3130_touchCounter); + ResponseAppend_P(PSTR(",\"%s\":{\"%s\":%u}"), MGC3130stype, MGC3130_currentGesture, MGC3130_touchCounter); MGC3130_currentGesture[0] = '\0'; MGC3130_touchTimeStamp = millis(); } diff --git a/sonoff/xsns_37_rfsensor.ino b/sonoff/xsns_37_rfsensor.ino index 7230ae692..4a94e2d77 100644 --- a/sonoff/xsns_37_rfsensor.ino +++ b/sonoff/xsns_37_rfsensor.ino @@ -268,16 +268,16 @@ void RfSnsTheoV2Show(bool json) if (rfsns_theo_v2_t1[i].time < LocalTime() - RFSNS_VALID_WINDOW) { if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_RFRECEIVED "\":\"%s\",\"" D_JSON_VOLTAGE "\":%s}"), - mqtt_data, sensor, GetDT(rfsns_theo_v2_t1[i].time).c_str(), voltage); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_RFRECEIVED "\":\"%s\",\"" D_JSON_VOLTAGE "\":%s}"), + sensor, GetDT(rfsns_theo_v2_t1[i].time).c_str(), voltage); } } else { char temperature[33]; dtostrfd(ConvertTemp((float)rfsns_theo_v2_t1[i].temp / 100), Settings.flag2.temperature_resolution, temperature); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_ILLUMINANCE "\":%d,\"" D_JSON_VOLTAGE "\":%s}"), - mqtt_data, sensor, temperature, rfsns_theo_v2_t1[i].lux, voltage); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_ILLUMINANCE "\":%d,\"" D_JSON_VOLTAGE "\":%s}"), + sensor, temperature, rfsns_theo_v2_t1[i].lux, voltage); #ifdef USE_DOMOTICZ if ((0 == tele_period) && !sensor_once) { DomoticzSensor(DZ_TEMP, temperature); @@ -305,8 +305,8 @@ void RfSnsTheoV2Show(bool json) if (rfsns_theo_v2_t2[i].time < LocalTime() - RFSNS_VALID_WINDOW) { if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_RFRECEIVED" \":\"%s\",\"" D_JSON_VOLTAGE "\":%s}"), - mqtt_data, sensor, GetDT(rfsns_theo_v2_t2[i].time).c_str(), voltage); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_RFRECEIVED" \":\"%s\",\"" D_JSON_VOLTAGE "\":%s}"), + sensor, GetDT(rfsns_theo_v2_t2[i].time).c_str(), voltage); } } else { float temp = ConvertTemp((float)rfsns_theo_v2_t2[i].temp / 100); @@ -317,8 +317,8 @@ void RfSnsTheoV2Show(bool json) dtostrfd(humi, Settings.flag2.humidity_resolution, humidity); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"" D_JSON_VOLTAGE "\":%s}"), - mqtt_data, sensor, temperature, humidity, voltage); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"" D_JSON_VOLTAGE "\":%s}"), + sensor, temperature, humidity, voltage); if ((0 == tele_period) && !sensor_once) { #ifdef USE_DOMOTICZ DomoticzTempHumSensor(temperature, humidity); // @@ -552,8 +552,7 @@ void RfSnsAlectoV2Show(bool json) if (rfsns_alecto_v2->time) { if (rfsns_alecto_v2->time < LocalTime() - RFSNS_VALID_WINDOW) { if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_ALECTOV2 "\":{\"" D_JSON_RFRECEIVED "\":\"%s\"}"), - mqtt_data, GetDT(rfsns_alecto_v2->time).c_str()); + ResponseAppend_P(PSTR(",\"" D_ALECTOV2 "\":{\"" D_JSON_RFRECEIVED "\":\"%s\"}"), GetDT(rfsns_alecto_v2->time).c_str()); } } else { float temp = ConvertTemp(rfsns_alecto_v2->temp); @@ -576,8 +575,8 @@ void RfSnsAlectoV2Show(bool json) } if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"" D_ALECTOV2 "\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"Rain\":%s,\"Wind\":%s,\"Gust\":%s%s}"), - mqtt_data, temperature, humidity, rain, wind, gust, (rfsns_alecto_v2->type) ? direction : ""); + ResponseAppend_P(PSTR(",\"" D_ALECTOV2 "\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s,\"Rain\":%s,\"Wind\":%s,\"Gust\":%s%s}"), + temperature, humidity, rain, wind, gust, (rfsns_alecto_v2->type) ? direction : ""); if (0 == tele_period) { #ifdef USE_DOMOTICZ // Use a rules to send data to Domoticz where also a local BMP280 is connected: diff --git a/sonoff/xsns_38_az7798.ino b/sonoff/xsns_38_az7798.ino index 953832d6f..2aecab9a1 100644 --- a/sonoff/xsns_38_az7798.ino +++ b/sonoff/xsns_38_az7798.ino @@ -258,7 +258,7 @@ void AzShow(bool json) dtostrfd(az_humidity, Settings.flag2.humidity_resolution, humidity); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_CO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"), mqtt_data, ktype, az_co2, temperature, humidity); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_CO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"), ktype, az_co2, temperature, humidity); #ifdef USE_DOMOTICZ if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, az_co2); #endif // USE_DOMOTICZ diff --git a/sonoff/xsns_39_max31855.ino b/sonoff/xsns_39_max31855.ino index a6275caa7..fc43ecac1 100644 --- a/sonoff/xsns_39_max31855.ino +++ b/sonoff/xsns_39_max31855.ino @@ -125,8 +125,8 @@ void MAX31855_Show(bool Json){ dtostrfd(MAX31855_Result.ReferenceTemperature, Settings.flag2.temperature_resolution, referencetemp); if(Json){ - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"%s\":{\"" D_JSON_PROBETEMPERATURE "\":%s,\"" D_JSON_REFERENCETEMPERATURE "\":%s,\"" D_JSON_ERROR "\":%d}"), \ - mqtt_data, "MAX31855", probetemp, referencetemp, MAX31855_Result.ErrorCode); + ResponseAppend_P(PSTR(",\"MAX31855\":{\"" D_JSON_PROBETEMPERATURE "\":%s,\"" D_JSON_REFERENCETEMPERATURE "\":%s,\"" D_JSON_ERROR "\":%d}"), \ + probetemp, referencetemp, MAX31855_Result.ErrorCode); #ifdef USE_DOMOTICZ if (0 == tele_period) { DomoticzSensor(DZ_TEMP, probetemp); diff --git a/sonoff/xsns_40_pn532.ino b/sonoff/xsns_40_pn532.ino index 0bfa8bda1..491996327 100644 --- a/sonoff/xsns_40_pn532.ino +++ b/sonoff/xsns_40_pn532.ino @@ -497,12 +497,12 @@ void PN532_ScanForTag(void) pn532_function = 0; #endif // USE_PN532_DATA_FUNCTION - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); + Response_P(PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); #ifdef USE_PN532_DATA_FUNCTION - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"UID\":\"%s\", \"DATA\":\"%s\"}}"), mqtt_data, uids, card_datas); + ResponseAppend_P(PSTR(",\"PN532\":{\"UID\":\"%s\", \"DATA\":\"%s\"}}"), uids, card_datas); #else - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"UID\":\"%s\"}}"), mqtt_data, uids); + ResponseAppend_P(PSTR(",\"PN532\":{\"UID\":\"%s\"}}"), uids); #endif // USE_PN532_DATA_FUNCTION MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain); @@ -544,8 +544,7 @@ bool PN532_Command(void) if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"E")) { pn532_function = 1; // Block 1 of next card/tag will be reset to 0x00... AddLog_P(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Next scanned tag data block 1 will be erased")); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"COMMAND\":\"E\"\"}}"), mqtt_data); + Response_P(PSTR("{\"" D_JSON_TIME "\":\"%s\",\"PN532\":{\"COMMAND\":\"E\"}}"), GetDateAndTime(DT_LOCAL).c_str()); return serviced; } if (!strcmp(subStr(sub_string, XdrvMailbox.data, ",", 1),"S")) { @@ -561,8 +560,7 @@ bool PN532_Command(void) pn532_newdata[pn532_newdata_len] = 0x00; // Null terminate the string pn532_function = 2; AddLog_P2(LOG_LEVEL_INFO, PSTR("NFC: PN532 NFC - Next scanned tag data block 1 will be set to '%s'"), pn532_newdata); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_JSON_TIME "\":\"%s\""), GetDateAndTime(DT_LOCAL).c_str()); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"PN532\":{\"COMMAND\":\"S\"\"}}"), mqtt_data); + Response_P(PSTR("{\"" D_JSON_TIME "\":\"%s\",\"PN532\":{\"COMMAND\":\"S\"}}"), GetDateAndTime(DT_LOCAL).c_str()); return serviced; } } diff --git a/sonoff/xsns_41_max44009.ino b/sonoff/xsns_41_max44009.ino index 58a809ed9..891b36815 100644 --- a/sonoff/xsns_41_max44009.ino +++ b/sonoff/xsns_41_max44009.ino @@ -128,9 +128,7 @@ void Max4409Show(bool json) dtostrf(max44009_illuminance, sizeof(illum_str) -1, prec, illum_str); if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), - PSTR("%s,\"%s\":{\"" D_JSON_ILLUMINANCE "\":%s}"), - mqtt_data, max44009_types, illum_str); + ResponseAppend_P(PSTR(",\"%s\":{\"" D_JSON_ILLUMINANCE "\":%s}"), max44009_types, illum_str); #ifdef USE_DOMOTICZ if (0 == tele_period) { DomoticzSensor(DZ_ILLUMINANCE, illum_str); diff --git a/sonoff/xsns_42_scd30.ino b/sonoff/xsns_42_scd30.ino index defa01892..44e23ea49 100644 --- a/sonoff/xsns_42_scd30.ino +++ b/sonoff/xsns_42_scd30.ino @@ -401,7 +401,7 @@ bool Scd30CommandSensor() Scd30GetCommand(command_code, &value); } - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SCD30_COMMAND_NVALUE, command, value); + Response_P(S_JSON_SCD30_COMMAND_NVALUE, command, value); } break; @@ -421,7 +421,7 @@ bool Scd30CommandSensor() } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_SCD30_COMMAND_NFW_VALUE, command, major, minor); + Response_P(S_JSON_SCD30_COMMAND_NFW_VALUE, command, major, minor); } } break; @@ -445,8 +445,9 @@ void Scd30Show(bool json) dtostrfd(scd30_Humid, Settings.flag2.humidity_resolution, humidity); dtostrfd(ConvertTemp(scd30_Temp), Settings.flag2.temperature_resolution, temperature); if (json) { - //snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SCD30\":{\"" D_JSON_CO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"), mqtt_data, scd30_CO2, temperature, humidity); - snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s,\"SCD30\":{\"" D_JSON_CO2 "\":%d,\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"), mqtt_data, scd30_CO2, scd30_CO2EAvg, temperature, humidity); + //ResponseAppend_P(PSTR(",\"SCD30\":{\"" D_JSON_CO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"), scd30_CO2, temperature, humidity); + ResponseAppend_P(PSTR(",\"SCD30\":{\"" D_JSON_CO2 "\":%d,\"" D_JSON_ECO2 "\":%d,\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"), + scd30_CO2, scd30_CO2EAvg, temperature, humidity); #ifdef USE_DOMOTICZ if (0 == tele_period) DomoticzSensor(DZ_AIRQUALITY, scd30_CO2); #endif // USE_DOMOTICZ From 10d32accccc4c44eb4e6edd608111e3d7ecd09ac Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 24 Mar 2019 14:23:20 +0100 Subject: [PATCH 04/81] Free some flash used by hass Free some flash used by hass --- sonoff/i18n.h | 22 ++--- sonoff/support.ino | 20 ++--- sonoff/xdrv_12_home_assistant.ino | 139 +++++++++++++----------------- 3 files changed, 80 insertions(+), 101 deletions(-) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index ca5e2b79a..60b5880e0 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -561,20 +561,14 @@ const char kOptionBlinkOff[] PROGMEM = "BLINKOFF|" D_BLINKOFF ; // xdrv_02_webserver.ino #ifdef USE_WEBSERVER -const char HTTP_SNS_TEMP[] PROGMEM = "{s}%s " D_TEMPERATURE "{m}%s°%c{e}"; // {s} = , {m} = , {e} = -const char HTTP_SNS_HUM[] PROGMEM = "{s}%s " D_HUMIDITY "{m}%s%%{e}"; // {s} = , {m} = , {e} = -const char HTTP_SNS_PRESSURE[] PROGMEM = "{s}%s " D_PRESSURE "{m}%s %s{e}"; // {s} = , {m} = , {e} = -const char HTTP_SNS_SEAPRESSURE[] PROGMEM = "{s}%s " D_PRESSUREATSEALEVEL "{m}%s %s{e}"; // {s} = , {m} = , {e} = -const char HTTP_SNS_ANALOG[] PROGMEM = "{s}%s " D_ANALOG_INPUT "%d{m}%d{e}"; // {s} = , {m} = , {e} = -const char HTTP_SNS_ILLUMINANCE[] PROGMEM = "{s}%s " D_ILLUMINANCE "{m}%d " D_UNIT_LUX "{e}"; // {s} = , {m} = , {e} = - -#if defined(USE_MHZ19) || defined(USE_SENSEAIR) || defined(USE_AZ7798) || defined(USE_SCD30) -const char HTTP_SNS_CO2[] PROGMEM = "{s}%s " D_CO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}"; // {s} = , {m} = , {e} = -#endif // USE_MHZ19 - -#if defined(USE_SCD30) -const char HTTP_SNS_CO2EAVG[] PROGMEM = "{s}%s " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}"; // {s} = , {m} = , {e} = -#endif // USE_SCD30 +const char HTTP_SNS_TEMP[] PROGMEM = "{s}%s " D_TEMPERATURE "{m}%s°%c{e}"; // {s} = , {m} = , {e} = +const char HTTP_SNS_HUM[] PROGMEM = "{s}%s " D_HUMIDITY "{m}%s%%{e}"; // {s} = , {m} = , {e} = +const char HTTP_SNS_PRESSURE[] PROGMEM = "{s}%s " D_PRESSURE "{m}%s %s{e}"; // {s} = , {m} = , {e} = +const char HTTP_SNS_SEAPRESSURE[] PROGMEM = "{s}%s " D_PRESSUREATSEALEVEL "{m}%s %s{e}"; // {s} = , {m} = , {e} = +const char HTTP_SNS_ANALOG[] PROGMEM = "{s}%s " D_ANALOG_INPUT "%d{m}%d{e}"; // {s} = , {m} = , {e} = +const char HTTP_SNS_ILLUMINANCE[] PROGMEM = "{s}%s " D_ILLUMINANCE "{m}%d " D_UNIT_LUX "{e}"; // {s} = , {m} = , {e} = +const char HTTP_SNS_CO2[] PROGMEM = "{s}%s " D_CO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}"; // {s} = , {m} = , {e} = +const char HTTP_SNS_CO2EAVG[] PROGMEM = "{s}%s " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}"; // {s} = , {m} = , {e} = const char S_MAIN_MENU[] PROGMEM = D_MAIN_MENU; const char S_CONFIGURATION[] PROGMEM = D_CONFIGURATION; diff --git a/sonoff/support.ino b/sonoff/support.ino index 24f0c6f8c..cfe3e6a6a 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -701,24 +701,24 @@ void ShowSource(int source) * Response data handling \*********************************************************************************************/ -int Response_P(const char* formatP, ...) // Content send snprintf_P char data +int Response_P(const char* format, ...) // Content send snprintf_P char data { // This uses char strings. Be aware of sending %% if % is needed - va_list arg; - va_start(arg, formatP); - int len = vsnprintf_P(mqtt_data, sizeof(mqtt_data), formatP, arg); - va_end(arg); + va_list args; + va_start(args, format); + int len = vsnprintf_P(mqtt_data, sizeof(mqtt_data), format, args); + va_end(args); return len; } -int ResponseAppend_P(const char* formatP, ...) // Content send snprintf_P char data +int ResponseAppend_P(const char* format, ...) // Content send snprintf_P char data { // This uses char strings. Be aware of sending %% if % is needed - va_list arg; - va_start(arg, formatP); + va_list args; + va_start(args, format); int mlen = strlen(mqtt_data); - int len = vsnprintf_P(mqtt_data + mlen, sizeof(mqtt_data) - mlen, formatP, arg); - va_end(arg); + int len = vsnprintf_P(mqtt_data + mlen, sizeof(mqtt_data) - mlen, format, args); + va_end(args); return len + mlen; } diff --git a/sonoff/xdrv_12_home_assistant.ino b/sonoff/xdrv_12_home_assistant.ino index 4437a91eb..406e6d451 100644 --- a/sonoff/xdrv_12_home_assistant.ino +++ b/sonoff/xdrv_12_home_assistant.ino @@ -44,38 +44,37 @@ const char HASS_DISCOVER_BUTTON_SWITCH[] PROGMEM = "\"pl_not_avail\":\"" D_OFFLINE "\""; // Offline const char HASS_DISCOVER_BUTTON_SWITCH_TOGGLE[] PROGMEM = - "%s,\"off_delay\":1"; // Hass has no support for TOGGLE, fake it by resetting to OFF after 1s + ",\"off_delay\":1"; // Hass has no support for TOGGLE, fake it by resetting to OFF after 1s const char HASS_DISCOVER_BUTTON_SWITCH_ONOFF[] PROGMEM = - "%s,\"frc_upd\":true," // In ON/OFF case, enable force_update to make automations work + ",\"frc_upd\":true," // In ON/OFF case, enable force_update to make automations work "\"pl_off\":\"%s\""; // OFF - const char HASS_DISCOVER_LIGHT_DIMMER[] PROGMEM = - "%s,\"bri_cmd_t\":\"%s\"," // cmnd/led2/Dimmer + ",\"bri_cmd_t\":\"%s\"," // cmnd/led2/Dimmer "\"bri_stat_t\":\"%s\"," // stat/led2/RESULT "\"bri_scl\":100," // 100% "\"on_cmd_type\":\"brightness\"," // power on (first), power on (last), no power on (brightness) "\"bri_val_tpl\":\"{{value_json." D_CMND_DIMMER "}}\""; const char HASS_DISCOVER_LIGHT_COLOR[] PROGMEM = - "%s,\"rgb_cmd_t\":\"%s2\"," // cmnd/led2/Color2 + ",\"rgb_cmd_t\":\"%s2\"," // cmnd/led2/Color2 "\"rgb_stat_t\":\"%s\"," // stat/led2/RESULT "\"rgb_val_tpl\":\"{{value_json." D_CMND_COLOR ".split(',')[0:3]|join(',')}}\""; const char HASS_DISCOVER_LIGHT_WHITE[] PROGMEM = - "%s,\"whit_val_cmd_t\":\"%s\"," // cmnd/led2/White + ",\"whit_val_cmd_t\":\"%s\"," // cmnd/led2/White "\"whit_val_stat_t\":\"%s\"," // stat/led2/RESULT "\"white_value_scale\":100," // (No abbreviation defined) "\"whit_val_tpl\":\"{{value_json.Channel[3]}}\""; const char HASS_DISCOVER_LIGHT_CT[] PROGMEM = - "%s,\"clr_temp_cmd_t\":\"%s\"," // cmnd/led2/CT + ",\"clr_temp_cmd_t\":\"%s\"," // cmnd/led2/CT "\"clr_temp_stat_t\":\"%s\"," // stat/led2/RESULT "\"clr_temp_val_tpl\":\"{{value_json." D_CMND_COLORTEMPERATURE "}}\""; const char HASS_DISCOVER_LIGHT_SCHEME[] PROGMEM = - "%s,\"fx_cmd_t\":\"%s\"," // cmnd/led2/Scheme + ",\"fx_cmd_t\":\"%s\"," // cmnd/led2/Scheme "\"fx_stat_t\":\"%s\"," // stat/led2/RESULT "\"fx_val_tpl\":\"{{value_json." D_CMND_SCHEME "}}\"," "\"fx_list\":[\"0\",\"1\",\"2\",\"3\",\"4\"]"; // string list with reference to scheme parameter. @@ -88,47 +87,47 @@ const char HASS_DISCOVER_SENSOR[] PROGMEM = "\"pl_not_avail\":\"" D_OFFLINE "\""; // Offline const char HASS_DISCOVER_SENSOR_TEMP[] PROGMEM = - "%s,\"unit_of_meas\":\"°%c\"," // °C / °F + ",\"unit_of_meas\":\"°%c\"," // °C / °F "\"val_tpl\":\"{{value_json['%s'].Temperature}}\""; // "SI7021-14":{"Temperature":null,"Humidity":null} -> {{ value_json['SI7021-14'].Temperature }} const char HASS_DISCOVER_SENSOR_HUM[] PROGMEM = - "%s,\"unit_of_meas\":\"%%\"," // % + ",\"unit_of_meas\":\"%%\"," // % "\"val_tpl\":\"{{value_json['%s'].Humidity}}\"," // "SI7021-14":{"Temperature":null,"Humidity":null} -> {{ value_json['SI7021-14'].Humidity }} "\"dev_cla\":\"humidity\""; // humidity const char HASS_DISCOVER_SENSOR_PRESS[] PROGMEM = - "%s,\"unit_of_meas\":\"%s\"," // PressureUnit() setting + ",\"unit_of_meas\":\"%s\"," // PressureUnit() setting "\"val_tpl\":\"{{value_json['%s'].Pressure}}\"," // "BME280":{"Temperature":19.7,"Humidity":27.8,"Pressure":990.1} -> {{ value_json['BME280'].Pressure }} "\"dev_cla\":\"pressure\""; // pressure //ENERGY const char HASS_DISCOVER_SENSOR_KWH[] PROGMEM = - "%s,\"unit_of_meas\":\"kWh\"," // kWh + ",\"unit_of_meas\":\"kWh\"," // kWh "\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].Total/Yesterday/Today }} const char HASS_DISCOVER_SENSOR_WATT[] PROGMEM = - "%s,\"unit_of_meas\":\"W\"," // W + ",\"unit_of_meas\":\"W\"," // W "\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].POWER }} const char HASS_DISCOVER_SENSOR_VOLTAGE[] PROGMEM = - "%s,\"unit_of_meas\":\"V\"," // V + ",\"unit_of_meas\":\"V\"," // V "\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].Voltage }} const char HASS_DISCOVER_SENSOR_AMPERE[] PROGMEM = - "%s,\"unit_of_meas\":\"A\"," // A + ",\"unit_of_meas\":\"A\"," // A "\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "ENERGY":{"TotalStartTime":null,"Total":null,"Yesterday":null,"Today":null,"Power":null,"ApparentPower":null,"ReactivePower":null,"Factor":null,"Voltage":null,"Current":null} -> {{ value_json['ENERGY'].Current }} const char HASS_DISCOVER_SENSOR_ANY[] PROGMEM = - "%s,\"unit_of_meas\":\" \"," // " " As unit of measurement to get a value graph in Hass + ",\"unit_of_meas\":\" \"," // " " As unit of measurement to get a value graph in Hass "\"val_tpl\":\"{{value_json['%s'].%s}}\""; // "COUNTER":{"C1":0} -> {{ value_json['COUNTER'].C1 }} const char HASS_DISCOVER_SENSOR_HASS_STATUS[] PROGMEM = - "%s,\"json_attributes_topic\":\"%s\"," + ",\"json_attributes_topic\":\"%s\"," "\"unit_of_meas\":\" \"," // " " As unit of measurement to get a value graph in Hass "\"val_tpl\":\"{{value_json['" D_JSON_RSSI "']}}\"";// "COUNTER":{"C1":0} -> {{ value_json['COUNTER'].C1 }} const char HASS_DISCOVER_DEVICE_INFO[] PROGMEM = - "%s,\"uniq_id\":\"%s\"," + ",\"uniq_id\":\"%s\"," "\"device\":{\"identifiers\":[\"%06X\"]," "\"name\":\"%s\"," "\"model\":\"%s\"," @@ -136,11 +135,11 @@ const char HASS_DISCOVER_DEVICE_INFO[] PROGMEM = "\"manufacturer\":\"Tasmota\"}"; const char HASS_DISCOVER_DEVICE_INFO_SHORT[] PROGMEM = - "%s,\"uniq_id\":\"%s\"," + ",\"uniq_id\":\"%s\"," "\"device\":{\"identifiers\":[\"%06X\"]}"; const char HASS_DISCOVER_TOPIC_PREFIX[] PROGMEM = - "%s, \"~\":\"%s\""; + ",\"~\":\"%s\""; uint8_t hass_init_step = 0; uint8_t hass_mode = 0; @@ -166,21 +165,24 @@ static void Shorten(char** s, char *prefix) } } -void try_snprintf_P(char *s, int n, const char *format, ... ) +void TryResponseAppend_P(const char *format, ... ) { va_list args; va_start(args, format); char dummy[2]; - int len = vsnprintf_P(dummy, 1, format, args); - if (len >= n) { - AddLog_P2(LOG_LEVEL_ERROR, PSTR("ERROR: MQTT discovery failed due to too long topic or friendly name. " - "Please shorten topic and friendly name. Failed to format(%u/%u):"), len, n); + int dlen = vsnprintf_P(dummy, 1, format, args); + + int mlen = strlen(mqtt_data); + int slen = sizeof(mqtt_data) -1 -mlen; + if (dlen >= slen) { + AddLog_P2(LOG_LEVEL_ERROR, PSTR("HASS: MQTT discovery failed due to too long topic or friendly name. " + "Please shorten topic and friendly name. Failed to format(%u/%u):"), dlen, slen); va_start(args, format); vsnprintf_P(log_data, sizeof(log_data), format, args); AddLog(LOG_LEVEL_ERROR); } else { va_start(args, format); - vsnprintf_P(s, n, format, args); + vsnprintf_P(mqtt_data + mlen, slen, format, args); } va_end(args); } @@ -234,30 +236,28 @@ void HAssAnnounceRelayLight(void) Shorten(&state_topic, prefix); Shorten(&availability_topic, prefix); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_RELAY, - name, command_topic, state_topic, value_template, Settings.state_text[0], Settings.state_text[1], availability_topic); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_DEVICE_INFO_SHORT, mqtt_data, - unique_id, ESP.getChipId()); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); + Response_P(HASS_DISCOVER_RELAY, name, command_topic, state_topic, value_template, Settings.state_text[0], Settings.state_text[1], availability_topic); + TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId()); + TryResponseAppend_P(HASS_DISCOVER_TOPIC_PREFIX, prefix); if (is_light) { char *brightness_command_topic = stemp1; GetTopic_P(brightness_command_topic, CMND, mqtt_topic, D_CMND_DIMMER); Shorten(&brightness_command_topic, prefix); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_LIGHT_DIMMER, mqtt_data, brightness_command_topic, state_topic); + TryResponseAppend_P(HASS_DISCOVER_LIGHT_DIMMER, brightness_command_topic, state_topic); if (light_subtype >= LST_RGB) { char *rgb_command_topic = stemp1; GetTopic_P(rgb_command_topic, CMND, mqtt_topic, D_CMND_COLOR); Shorten(&rgb_command_topic, prefix); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_LIGHT_COLOR, mqtt_data, rgb_command_topic, state_topic); + TryResponseAppend_P(HASS_DISCOVER_LIGHT_COLOR, rgb_command_topic, state_topic); char *effect_command_topic = stemp1; GetTopic_P(effect_command_topic, CMND, mqtt_topic, D_CMND_SCHEME); Shorten(&effect_command_topic, prefix); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_LIGHT_SCHEME, mqtt_data, effect_command_topic, state_topic); + TryResponseAppend_P(HASS_DISCOVER_LIGHT_SCHEME, effect_command_topic, state_topic); } if (LST_RGBW == light_subtype) { @@ -265,17 +265,17 @@ void HAssAnnounceRelayLight(void) GetTopic_P(white_temp_command_topic, CMND, mqtt_topic, D_CMND_WHITE); Shorten(&white_temp_command_topic, prefix); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_LIGHT_WHITE, mqtt_data, white_temp_command_topic, state_topic); + TryResponseAppend_P(HASS_DISCOVER_LIGHT_WHITE, white_temp_command_topic, state_topic); } if ((LST_COLDWARM == light_subtype) || (LST_RGBWC == light_subtype)) { char *color_temp_command_topic = stemp1; GetTopic_P(color_temp_command_topic, CMND, mqtt_topic, D_CMND_COLORTEMPERATURE); Shorten(&color_temp_command_topic, prefix); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_LIGHT_CT, mqtt_data, color_temp_command_topic, state_topic); + TryResponseAppend_P(HASS_DISCOVER_LIGHT_CT, color_temp_command_topic, state_topic); } } - try_snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + TryResponseAppend_P(PSTR("}")); } MqttPublish(stopic, true); } @@ -315,15 +315,13 @@ void HAssAnnounceButtonSwitch(uint8_t device, char* topic, uint8_t present, uint FindPrefix(state_topic, availability_topic, prefix); Shorten(&state_topic, prefix); Shorten(&availability_topic, prefix); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_BUTTON_SWITCH, - name, state_topic, Settings.state_text[toggle?2:1], availability_topic); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_DEVICE_INFO_SHORT, mqtt_data, - unique_id, ESP.getChipId()); - if (strlen(prefix) > 0 ) try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); - if (toggle) try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_BUTTON_SWITCH_TOGGLE, mqtt_data); - else try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_BUTTON_SWITCH_ONOFF, mqtt_data, Settings.state_text[0]); + Response_P(HASS_DISCOVER_BUTTON_SWITCH, name, state_topic, Settings.state_text[toggle?2:1], availability_topic); + TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId()); + if (strlen(prefix) > 0 ) TryResponseAppend_P(HASS_DISCOVER_TOPIC_PREFIX, prefix); + if (toggle) TryResponseAppend_P(HASS_DISCOVER_BUTTON_SWITCH_TOGGLE); + else TryResponseAppend_P(HASS_DISCOVER_BUTTON_SWITCH_ONOFF, Settings.state_text[0]); - try_snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + TryResponseAppend_P(PSTR("}")); } MqttPublish(stopic, true); } @@ -416,40 +414,30 @@ void HAssAnnounceSensor(const char* sensorname, const char* subsensortype) Shorten(&state_topic, prefix); Shorten(&availability_topic, prefix); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR, - name, state_topic, availability_topic); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_DEVICE_INFO_SHORT, mqtt_data, - unique_id, ESP.getChipId()); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); + Response_P(HASS_DISCOVER_SENSOR, name, state_topic, availability_topic); + TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO_SHORT, unique_id, ESP.getChipId()); + TryResponseAppend_P(HASS_DISCOVER_TOPIC_PREFIX, prefix); if (!strcmp_P(subsensortype, PSTR(D_JSON_TEMPERATURE))) { - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_TEMP, - mqtt_data, TempUnit(), sensorname); + TryResponseAppend_P(HASS_DISCOVER_SENSOR_TEMP, TempUnit(), sensorname); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_HUMIDITY))) { - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_HUM, - mqtt_data, sensorname); + TryResponseAppend_P(HASS_DISCOVER_SENSOR_HUM, sensorname); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_PRESSURE))) { - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_PRESS, - mqtt_data, PressureUnit().c_str(), sensorname); + TryResponseAppend_P(HASS_DISCOVER_SENSOR_PRESS, PressureUnit().c_str(), sensorname); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_TOTAL)) || !strcmp_P(subsensortype, PSTR(D_JSON_TODAY)) || !strcmp_P(subsensortype, PSTR(D_JSON_YESTERDAY))){ - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_KWH, - mqtt_data, sensorname, subsensortype); + TryResponseAppend_P(HASS_DISCOVER_SENSOR_KWH, sensorname, subsensortype); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_POWERUSAGE))){ - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_WATT, - mqtt_data, sensorname, subsensortype); + TryResponseAppend_P(HASS_DISCOVER_SENSOR_WATT, sensorname, subsensortype); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_VOLTAGE))){ - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_VOLTAGE, - mqtt_data, sensorname, subsensortype); + TryResponseAppend_P(HASS_DISCOVER_SENSOR_VOLTAGE, sensorname, subsensortype); } else if (!strcmp_P(subsensortype, PSTR(D_JSON_CURRENT))){ - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_AMPERE, - mqtt_data, sensorname, subsensortype); + TryResponseAppend_P(HASS_DISCOVER_SENSOR_AMPERE, sensorname, subsensortype); } else { - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_ANY, - mqtt_data, sensorname, subsensortype); + TryResponseAppend_P(HASS_DISCOVER_SENSOR_ANY, sensorname, subsensortype); } - try_snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + TryResponseAppend_P(PSTR("}")); } MqttPublish(stopic, true); } @@ -509,7 +497,7 @@ void HAssAnnounceStatusSensor(void) mqtt_data[0] = '\0'; // Clear retained message // Clear or Set topic - snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_%s"), ESP.getChipId(), "status"); + snprintf_P(unique_id, sizeof(unique_id), PSTR("%06X_status"), ESP.getChipId()); snprintf_P(stopic, sizeof(stopic), PSTR(HOME_ASSISTANT_DISCOVERY_PREFIX "/sensor/%s/config"), unique_id); if (Settings.flag.hass_discovery) { @@ -518,22 +506,19 @@ void HAssAnnounceStatusSensor(void) char *state_topic = stemp1; char *availability_topic = stemp2; - snprintf_P(name, sizeof(name), PSTR("%s %s"), Settings.friendlyname[0], "status"); + snprintf_P(name, sizeof(name), PSTR("%s status"), Settings.friendlyname[0]); GetTopic_P(state_topic, TELE, mqtt_topic, PSTR(D_RSLT_HASS_STATE)); GetTopic_P(availability_topic, TELE, mqtt_topic, S_LWT); FindPrefix(state_topic, availability_topic, prefix); Shorten(&state_topic, prefix); Shorten(&availability_topic, prefix); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR, - name, state_topic, availability_topic); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_SENSOR_HASS_STATUS, - mqtt_data, state_topic); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_DEVICE_INFO, mqtt_data, - unique_id, ESP.getChipId(), + Response_P(HASS_DISCOVER_SENSOR, name, state_topic, availability_topic); + TryResponseAppend_P(HASS_DISCOVER_SENSOR_HASS_STATUS, state_topic); + TryResponseAppend_P(HASS_DISCOVER_DEVICE_INFO, unique_id, ESP.getChipId(), Settings.friendlyname[0], ModuleName().c_str(), my_version, my_image); - try_snprintf_P(mqtt_data, sizeof(mqtt_data)-1, HASS_DISCOVER_TOPIC_PREFIX, mqtt_data, prefix); - try_snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data); + TryResponseAppend_P(HASS_DISCOVER_TOPIC_PREFIX, prefix); + TryResponseAppend_P(PSTR("}")); } MqttPublish(stopic, true); } From a7a07c5b96ab793ed692fdd7fad1dd5c261972d2 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 25 Mar 2019 10:02:12 +0100 Subject: [PATCH 05/81] Fix JSON message error (#5521) Fix JSON message error regression (#5521) --- sonoff/xdrv_04_light.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 6a4c11db7..fc9d1a635 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -760,7 +760,7 @@ void LightState(uint8_t append) for (uint8_t i = 0; i < light_subtype; i++) { ResponseAppend_P(PSTR("%s%d" ), (i > 0 ? "," : ""), light_current_color[i] * 100 / 255); } - ResponseAppend_P(PSTR("%s]")); + ResponseAppend_P(PSTR("]")); } if ((LST_COLDWARM == light_subtype) || (LST_RGBWC == light_subtype)) { ResponseAppend_P(PSTR(",\"" D_CMND_COLORTEMPERATURE "\":%d"), LightGetColorTemp()); From 57cb570b8fa145207e6e1f4879c26a3a2979a41b Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 25 Mar 2019 11:20:03 +0100 Subject: [PATCH 06/81] Fix GUI corruption Fix GUI corruption due to format string usage (#5519) --- sonoff/xdrv_02_mqtt.ino | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 21b97edd0..37bdd97c2 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -741,7 +741,7 @@ const char HTTP_FORM_MQTT1[] PROGMEM = const char HTTP_FORM_MQTT2[] PROGMEM = "

" D_USER " (" MQTT_USER ")

" "

" D_PASSWORD "

" - "

" D_TOPIC " = %%topic%% (" MQTT_TOPIC ")

" + "

" D_TOPIC " = %%topic%% (%s)

" "

" D_FULL_TOPIC " (%s)

"; void HandleMqttConfiguration(void) @@ -763,14 +763,11 @@ void HandleMqttConfiguration(void) WSContentSend_P(HTTP_FORM_MQTT1, Settings.mqtt_host, Settings.mqtt_port, - Format(str, MQTT_CLIENT_ID, sizeof(Settings.mqtt_client)), - MQTT_CLIENT_ID, - Settings.mqtt_client); + Format(str, MQTT_CLIENT_ID, sizeof(str)), MQTT_CLIENT_ID, Settings.mqtt_client); WSContentSend_P(HTTP_FORM_MQTT2, (Settings.mqtt_user[0] == '\0') ? "0" : Settings.mqtt_user, - Settings.mqtt_topic, - MQTT_FULLTOPIC, MQTT_FULLTOPIC, - Settings.mqtt_fulltopic); + Format(str, MQTT_TOPIC, sizeof(str)), MQTT_TOPIC, Settings.mqtt_topic, + MQTT_FULLTOPIC, MQTT_FULLTOPIC, Settings.mqtt_fulltopic); WSContentSend_P(HTTP_FORM_END); WSContentSpaceButton(BUTTON_CONFIGURATION); WSContentStop(); From 1c7fb82af83f391624a20210da6bd67e218d8682 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 25 Mar 2019 16:03:28 +0100 Subject: [PATCH 07/81] 6.5.0.2 Change UDP initial message handling 6.5.0.2 20190325 * Change UDP initial message handling from string to char using static memory and add debug info (#5505) --- sonoff/_changelog.ino | 5 ++++- sonoff/sonoff_version.h | 2 +- sonoff/xplg_wemohue.ino | 43 +++++++++++++++++++++++------------------ 3 files changed, 29 insertions(+), 21 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 978aa861f..54ed9c21f 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.5.0.1 20190319 +/* 6.5.0.2 20190325 + * Change UDP initial message handling from string to char using static memory and add debug info (#5505) + * + * 6.5.0.1 20190319 * Change Web GUI sensor data collection * * 6.5.0 20190319 diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 7a5dac4cc..66b50129c 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06050001 +#define VERSION 0x06050002 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/xplg_wemohue.ino b/sonoff/xplg_wemohue.ino index 2a7b60b80..9a99b3633 100644 --- a/sonoff/xplg_wemohue.ino +++ b/sonoff/xplg_wemohue.ino @@ -222,26 +222,26 @@ bool UdpConnect(void) void PollUdp(void) { - if (udp_connected && !udp_response_mutex) { + if (udp_connected && !udp_response_mutex && devices_present) { if (PortUdp.parsePacket()) { int len = PortUdp.read(packet_buffer, UDP_BUFFER_SIZE -1); if (len > 0) { packet_buffer[len] = 0; } - String request = packet_buffer; -// AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: Packet received")); -// AddLog_P(LOG_LEVEL_DEBUG_MORE, packet_buffer); - - if (request.indexOf("M-SEARCH") >= 0) { - request.toLowerCase(); - request.replace(" ", ""); - -// AddLog_P(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: M-SEARCH Packet received")); -// AddLog_P(LOG_LEVEL_DEBUG_MORE, request.c_str()); + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: Packet (%d)"), len); +// AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("\n%s"), packet_buffer); + if (strstr_P(packet_buffer, PSTR("M-SEARCH"))) { udp_remote_ip = PortUdp.remoteIP(); udp_remote_port = PortUdp.remotePort(); + + AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: M-SEARCH Packet from %s:%d\n%s"), + udp_remote_ip.toString().c_str(), udp_remote_port, packet_buffer); + + String request = packet_buffer; + request.toLowerCase(); + request.replace(" ", ""); if (EMUL_WEMO == Settings.flag2.emulation) { if (request.indexOf(F("urn:belkin:device:**")) > 0) { // type1 echo dot 2g, echo 1g's udp_response_mutex = true; @@ -384,6 +384,9 @@ void HandleUpnpEvent(void) AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_BASIC_EVENT)); String request = WebServer->arg(0); + +// AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("\n%s"), request.c_str()); + String state_xml = FPSTR(WEMO_RESPONSE_STATE_SOAP); //differentiate get and set state if (request.indexOf(F("SetBinaryState")) > 0) { @@ -837,14 +840,16 @@ void HandleHueApi(String *path) void HueWemoAddHandlers(void) { - if (EMUL_WEMO == Settings.flag2.emulation) { - WebServer->on("/upnp/control/basicevent1", HTTP_POST, HandleUpnpEvent); - WebServer->on("/eventservice.xml", HandleUpnpService); - WebServer->on("/metainfoservice.xml", HandleUpnpMetaService); - WebServer->on("/setup.xml", HandleUpnpSetupWemo); - } - if (EMUL_HUE == Settings.flag2.emulation) { - WebServer->on("/description.xml", HandleUpnpSetupHue); + if (devices_present) { + if (EMUL_WEMO == Settings.flag2.emulation) { + WebServer->on("/upnp/control/basicevent1", HTTP_POST, HandleUpnpEvent); + WebServer->on("/eventservice.xml", HandleUpnpService); + WebServer->on("/metainfoservice.xml", HandleUpnpMetaService); + WebServer->on("/setup.xml", HandleUpnpSetupWemo); + } + if (EMUL_HUE == Settings.flag2.emulation) { + WebServer->on("/description.xml", HandleUpnpSetupHue); + } } } From 0b1945cd5dafa9de8cd5d32e046f7071bab026a1 Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Mon, 25 Mar 2019 17:29:20 +0100 Subject: [PATCH 08/81] resolve VSC warning To get ride of VSC warning --- include/dummy.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 include/dummy.txt diff --git a/include/dummy.txt b/include/dummy.txt new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/include/dummy.txt @@ -0,0 +1 @@ + From bf8845c3bdab7da3dd4069be03f0fadc21509cd7 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 26 Mar 2019 10:28:30 +0100 Subject: [PATCH 09/81] Increase emulation stability (#5505) Increase emulation stability (#5505) --- sonoff/xplg_wemohue.ino | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/sonoff/xplg_wemohue.ino b/sonoff/xplg_wemohue.ino index 9a99b3633..4944b41b1 100644 --- a/sonoff/xplg_wemohue.ino +++ b/sonoff/xplg_wemohue.ino @@ -233,37 +233,40 @@ void PollUdp(void) // AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("\n%s"), packet_buffer); if (strstr_P(packet_buffer, PSTR("M-SEARCH"))) { + udp_response_mutex = true; + udp_remote_ip = PortUdp.remoteIP(); udp_remote_port = PortUdp.remotePort(); AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: M-SEARCH Packet from %s:%d\n%s"), udp_remote_ip.toString().c_str(), udp_remote_port, packet_buffer); - String request = packet_buffer; - request.toLowerCase(); - request.replace(" ", ""); + UpperCase(packet_buffer, packet_buffer); + RemoveSpace(packet_buffer); if (EMUL_WEMO == Settings.flag2.emulation) { - if (request.indexOf(F("urn:belkin:device:**")) > 0) { // type1 echo dot 2g, echo 1g's - udp_response_mutex = true; + if (strstr_P(packet_buffer, PSTR("URN:BELKIN:DEVICE:**"))) { // type1 echo dot 2g, echo 1g's TickerMSearch.attach_ms(UDP_MSEARCH_SEND_DELAY, WemoRespondToMSearch, 1); + return; } - else if ((request.indexOf(F("upnp:rootdevice")) > 0) || // type2 Echo 2g (echo & echo plus) - (request.indexOf(F("ssdpsearch:all")) > 0) || - (request.indexOf(F("ssdp:all")) > 0)) { - udp_response_mutex = true; + else if (strstr_P(packet_buffer, PSTR("UPNP:ROOTDEVICE")) || // type2 Echo 2g (echo & echo plus) + strstr_P(packet_buffer, PSTR("SSDPSEARCH:ALL")) || + strstr_P(packet_buffer, PSTR("SSDP:ALL"))) { TickerMSearch.attach_ms(UDP_MSEARCH_SEND_DELAY, WemoRespondToMSearch, 2); + return; + } + } else { + if (strstr_P(packet_buffer, PSTR("URN:SCHEMAS-UPNP-ORG:DEVICE:BASIC:1")) || + strstr_P(packet_buffer, PSTR("UPNP:ROOTDEVICE")) || + strstr_P(packet_buffer, PSTR("SSDPSEARCH:ALL")) || + strstr_P(packet_buffer, PSTR("SSDP:ALL"))) { + TickerMSearch.attach_ms(UDP_MSEARCH_SEND_DELAY, HueRespondToMSearch); + return; } } - else if ((EMUL_HUE == Settings.flag2.emulation) && - ((request.indexOf(F("urn:schemas-upnp-org:device:basic:1")) > 0) || - (request.indexOf(F("upnp:rootdevice")) > 0) || - (request.indexOf(F("ssdpsearch:all")) > 0) || - (request.indexOf(F("ssdp:all")) > 0))) { - udp_response_mutex = true; - TickerMSearch.attach_ms(UDP_MSEARCH_SEND_DELAY, HueRespondToMSearch); - } + udp_response_mutex = false; } } + delay(1); } } From f709ecf78668f7a1389fec3e05802a34a0d69faa Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Tue, 26 Mar 2019 11:46:03 +0100 Subject: [PATCH 10/81] Update Core 2.5.0 to build chain 2.0.4 Update Core 2.5.0 to build chain 2.0.4 Set Compiler Option -O2 for Core 2.5.0 and Core Stage (Faster code) See https://github.com/esp8266/Arduino/issues/5790#issuecomment-475672473 --- platformio.ini | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 671a6f284..8fffc69d3 100644 --- a/platformio.ini +++ b/platformio.ini @@ -67,9 +67,11 @@ build_flags = ${esp82xx_defaults.build_flags} [core_2_5_0] ; *** Esp8266 core for Arduino version 2.5.0 -platform = espressif8266@2.0.1 +platform = espressif8266@~2.0.4 build_flags = ${esp82xx_defaults.build_flags} -Wl,-Teagle.flash.1m.ld +; Code optimization see https://github.com/esp8266/Arduino/issues/5790#issuecomment-475672473 + -O2 ; lwIP 1.4 (Default) ; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH ; lwIP 2 - Low Memory @@ -89,6 +91,8 @@ build_flags = ${esp82xx_defaults.build_flags} platform = https://github.com/platformio/platform-espressif8266.git#feature/stage build_flags = ${esp82xx_defaults.build_flags} -Wl,-Teagle.flash.1m.ld +; Code optimization see https://github.com/esp8266/Arduino/issues/5790#issuecomment-475672473 + -O2 ; nonos-sdk 22x -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x ; nonos-sdk-pre-v3 From f83a5bb9898f99982e17d53197392fd1891bc164 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 26 Mar 2019 17:10:07 +0100 Subject: [PATCH 11/81] More Wemo tuning More Wemo tuning --- sonoff/support.ino | 13 ++++++ sonoff/xplg_wemohue.ino | 97 ++++++++++++++++++++++------------------- 2 files changed, 66 insertions(+), 44 deletions(-) diff --git a/sonoff/support.ino b/sonoff/support.ino index cfe3e6a6a..823655ce4 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -283,6 +283,19 @@ char* RemoveSpace(char* p) return p; } +char* LowerCase(char* dest, const char* source) +{ + char* write = dest; + const char* read = source; + char ch = '.'; + + while (ch != '\0') { + ch = *read++; + *write++ = tolower(ch); + } + return dest; +} + char* UpperCase(char* dest, const char* source) { char* write = dest; diff --git a/sonoff/xplg_wemohue.ino b/sonoff/xplg_wemohue.ino index 4944b41b1..60edf4a64 100644 --- a/sonoff/xplg_wemohue.ino +++ b/sonoff/xplg_wemohue.ino @@ -31,16 +31,22 @@ #include Ticker TickerMSearch; -bool udp_connected = false; - char packet_buffer[UDP_BUFFER_SIZE]; // buffer to hold incoming UDP packet -IPAddress ipMulticast(239,255,255,250); // Simple Service Discovery Protocol (SSDP) -uint32_t port_multicast = 1900; // Multicast address and port - -bool udp_response_mutex = false; // M-Search response mutex to control re-entry IPAddress udp_remote_ip; // M-Search remote IP address uint16_t udp_remote_port; // M-Search remote port +bool udp_connected = false; +bool udp_response_mutex = false; // M-Search response mutex to control re-entry + +/*********************************************************************************************\ + * UPNP search targets +\*********************************************************************************************/ + +const char URN_BELKIN_DEVICE[] PROGMEM = "urn:belkin:device:**"; +const char UPNP_ROOTDEVICE[] PROGMEM = "upnp:rootdevice"; +const char SSDPSEARCH_ALL[] PROGMEM = "ssdpsearch:all"; +const char SSDP_ALL[] PROGMEM = "ssdp:all"; + /*********************************************************************************************\ * WeMo UPNP support routines \*********************************************************************************************/ @@ -50,12 +56,12 @@ const char WEMO_MSEARCH[] PROGMEM = "CACHE-CONTROL: max-age=86400\r\n" "DATE: Fri, 15 Apr 2016 04:56:29 GMT\r\n" "EXT:\r\n" - "LOCATION: http://{r1:80/setup.xml\r\n" + "LOCATION: http://%s:80/setup.xml\r\n" "OPT: \"http://schemas.upnp.org/upnp/1/0/\"; ns=01\r\n" "01-NLS: b9200ebb-736d-4b93-bf03-835149d13983\r\n" "SERVER: Unspecified, UPnP/1.0, Unspecified\r\n" - "ST: {r3\r\n" // type1 = urn:Belkin:device:**, type2 = upnp:rootdevice - "USN: uuid:{r2::{r3\r\n" // type1 = urn:Belkin:device:**, type2 = upnp:rootdevice + "ST: %s\r\n" // type1 = urn:Belkin:device:**, type2 = upnp:rootdevice + "USN: uuid:%s::%s\r\n" // type1 = urn:Belkin:device:**, type2 = upnp:rootdevice "X-User-Agent: redsonic\r\n" "\r\n"; @@ -81,15 +87,15 @@ void WemoRespondToMSearch(int echo_type) TickerMSearch.detach(); if (PortUdp.beginPacket(udp_remote_ip, udp_remote_port)) { - String response = FPSTR(WEMO_MSEARCH); - response.replace("{r1", WiFi.localIP().toString()); - response.replace("{r2", WemoUuid()); + char type[24]; if (1 == echo_type) { // type1 echo 1g & dot 2g - response.replace("{r3", F("urn:Belkin:device:**")); + strcpy_P(type, URN_BELKIN_DEVICE); } else { // type2 echo 2g (echo, plus, show) - response.replace("{r3", F("upnp:rootdevice")); + strcpy_P(type, UPNP_ROOTDEVICE); } - PortUdp.write(response.c_str()); + char response[400]; + snprintf_P(response, sizeof(response), WEMO_MSEARCH, WiFi.localIP().toString().c_str(), type, WemoUuid().c_str(), type); + PortUdp.write(response); PortUdp.endPacket(); snprintf_P(message, sizeof(message), PSTR(D_RESPONSE_SENT)); } else { @@ -208,7 +214,8 @@ bool UdpDisconnect(void) bool UdpConnect(void) { if (!udp_connected) { - if (PortUdp.beginMulticast(WiFi.localIP(), ipMulticast, port_multicast)) { + // Simple Service Discovery Protocol (SSDP) + if (PortUdp.beginMulticast(WiFi.localIP(), IPAddress(239,255,255,250), 1900)) { AddLog_P(LOG_LEVEL_INFO, PSTR(D_LOG_UPNP D_MULTICAST_REJOINED)); udp_response_mutex = false; udp_connected = true; @@ -238,28 +245,30 @@ void PollUdp(void) udp_remote_ip = PortUdp.remoteIP(); udp_remote_port = PortUdp.remotePort(); - AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: M-SEARCH Packet from %s:%d\n%s"), - udp_remote_ip.toString().c_str(), udp_remote_port, packet_buffer); +// AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: M-SEARCH Packet from %s:%d\n%s"), +// udp_remote_ip.toString().c_str(), udp_remote_port, packet_buffer); - UpperCase(packet_buffer, packet_buffer); + uint32_t response_delay = UDP_MSEARCH_SEND_DELAY + ((millis() &0x7) * 100); // 1500 - 2200 msec + + LowerCase(packet_buffer, packet_buffer); RemoveSpace(packet_buffer); if (EMUL_WEMO == Settings.flag2.emulation) { - if (strstr_P(packet_buffer, PSTR("URN:BELKIN:DEVICE:**"))) { // type1 echo dot 2g, echo 1g's - TickerMSearch.attach_ms(UDP_MSEARCH_SEND_DELAY, WemoRespondToMSearch, 1); + if (strstr_P(packet_buffer, URN_BELKIN_DEVICE)) { // type1 echo dot 2g, echo 1g's + TickerMSearch.attach_ms(response_delay, WemoRespondToMSearch, 1); return; } - else if (strstr_P(packet_buffer, PSTR("UPNP:ROOTDEVICE")) || // type2 Echo 2g (echo & echo plus) - strstr_P(packet_buffer, PSTR("SSDPSEARCH:ALL")) || - strstr_P(packet_buffer, PSTR("SSDP:ALL"))) { - TickerMSearch.attach_ms(UDP_MSEARCH_SEND_DELAY, WemoRespondToMSearch, 2); + else if (strstr_P(packet_buffer, UPNP_ROOTDEVICE) || // type2 Echo 2g (echo & echo plus) + strstr_P(packet_buffer, SSDPSEARCH_ALL) || + strstr_P(packet_buffer, SSDP_ALL)) { + TickerMSearch.attach_ms(response_delay, WemoRespondToMSearch, 2); return; } } else { - if (strstr_P(packet_buffer, PSTR("URN:SCHEMAS-UPNP-ORG:DEVICE:BASIC:1")) || - strstr_P(packet_buffer, PSTR("UPNP:ROOTDEVICE")) || - strstr_P(packet_buffer, PSTR("SSDPSEARCH:ALL")) || - strstr_P(packet_buffer, PSTR("SSDP:ALL"))) { - TickerMSearch.attach_ms(UDP_MSEARCH_SEND_DELAY, HueRespondToMSearch); + if (strstr_P(packet_buffer, PSTR("urn:schemas-upnp-org:device:basic:1")) || + strstr_P(packet_buffer, UPNP_ROOTDEVICE) || + strstr_P(packet_buffer, SSDPSEARCH_ALL) || + strstr_P(packet_buffer, SSDP_ALL)) { + TickerMSearch.attach_ms(response_delay, HueRespondToMSearch); return; } } @@ -343,9 +352,9 @@ const char WEMO_METASERVICE_XML[] PROGMEM = const char WEMO_RESPONSE_STATE_SOAP[] PROGMEM = "" "" - "" - "{x1" - "" + "" + "%d" + "" "" "\r\n"; @@ -386,18 +395,20 @@ void HandleUpnpEvent(void) { AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, PSTR(D_WEMO_BASIC_EVENT)); - String request = WebServer->arg(0); + char event[500]; + strlcpy(event, WebServer->arg(0).c_str(), sizeof(event)); -// AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("\n%s"), request.c_str()); +// AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("\n%s"), event); - String state_xml = FPSTR(WEMO_RESPONSE_STATE_SOAP); //differentiate get and set state - if (request.indexOf(F("SetBinaryState")) > 0) { + char state = 'G'; + if (strstr_P(event, PSTR("SetBinaryState"))) { + state = 'S'; uint8_t power = POWER_TOGGLE; - if (request.indexOf(F("State>1 0) { + if (strstr_P(event, PSTR("State>10 0) { + else if (strstr_P(event, PSTR("State>0 0){ - state_xml.replace(F("Set"), F("Get")); - } - state_xml.replace("{x1", String(bitRead(power, devices_present -1))); - WSSend(200, CT_XML, state_xml); + + snprintf_P(event, sizeof(event), WEMO_RESPONSE_STATE_SOAP, state, bitRead(power, devices_present -1), state); + WSSend(200, CT_XML, event); } void HandleUpnpService(void) From e1c92b701b0c5528ca5384b2e1c9c0d8f46620d5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 26 Mar 2019 18:26:50 +0100 Subject: [PATCH 12/81] Change NULL to nullptr Change NULL to nullptr --- sonoff/Parsing.cpp | 6 +-- sonoff/_changelog.ino | 2 +- sonoff/settings.ino | 6 +-- sonoff/sonoff.ino | 68 +++++++++++++++---------------- sonoff/support.ino | 14 +++---- sonoff/support_rtc.ino | 2 +- sonoff/xdrv_01_webserver.ino | 18 ++++---- sonoff/xdrv_02_mqtt.ino | 8 ++-- sonoff/xdrv_04_light.ino | 18 ++++---- sonoff/xdrv_05_irremote.ino | 30 +++++++------- sonoff/xdrv_06_snfbridge.ino | 2 +- sonoff/xdrv_08_serial_bridge.ino | 4 +- sonoff/xdrv_09_timers.ino | 6 +-- sonoff/xdrv_10_rules.ino | 6 +-- sonoff/xdrv_11_knx.ino | 6 +-- sonoff/xdrv_13_display.ino | 28 ++++++------- sonoff/xdrv_16_tuyadimmer.ino | 4 +- sonoff/xdrv_17_rcswitch.ino | 6 +-- sonoff/xdrv_19_ps16dz_dimmer.ino | 16 ++++---- sonoff/xdsp_01_lcd.ino | 2 +- sonoff/xdsp_02_ssd1306.ino | 2 +- sonoff/xdsp_03_matrix.ino | 10 ++--- sonoff/xdsp_04_ili9341.ino | 2 +- sonoff/xdsp_05_epaper_29.ino | 2 +- sonoff/xnrg_03_pzem004t.ino | 2 +- sonoff/xnrg_04_mcp39f501.ino | 4 +- sonoff/xplg_wemohue.ino | 24 +++++------ sonoff/xplg_ws2812.ino | 2 +- sonoff/xsns_04_snfsc.ino | 2 +- sonoff/xsns_05_ds18x20_legacy.ino | 2 +- sonoff/xsns_09_bmp.ino | 8 ++-- sonoff/xsns_20_novasds.ino | 6 +-- sonoff/xsns_22_sr04.ino | 2 +- sonoff/xsns_34_hx711.ino | 18 ++++---- sonoff/xsns_37_rfsensor.ino | 10 ++--- 35 files changed, 174 insertions(+), 174 deletions(-) diff --git a/sonoff/Parsing.cpp b/sonoff/Parsing.cpp index 525277c74..6c68a3af4 100644 --- a/sonoff/Parsing.cpp +++ b/sonoff/Parsing.cpp @@ -415,7 +415,7 @@ bool ESP8266WebServer::_parseForm(WiFiClient& client, String boundary, uint32_t DEBUG_OUTPUT.println(argFilename); #endif //use GET to set the filename if uploading using blob - if (argFilename == F("blob") && hasArg(FPSTR(filename))) + if (argFilename == F("blob") && hasArg(FPSTR(filename))) argFilename = arg(FPSTR(filename)); } #ifdef DEBUG_ESP_HTTP_SERVER @@ -510,7 +510,7 @@ readfile: uint8_t endBuf[boundary.length()]; client.readBytes(endBuf, boundary.length()); - if (strstr((const char*)endBuf, boundary.c_str()) != NULL){ + if (strstr((const char*)endBuf, boundary.c_str()) != nullptr){ if(_currentHandler && _currentHandler->canUpload(_currentUri)) _currentHandler->upload(*this, _currentUri, *_currentUpload); _currentUpload->totalSize += _currentUpload->currentSize; @@ -571,7 +571,7 @@ readfile: arg.value = postArgs[iarg].value; } _currentArgCount = iarg; - if (postArgs) + if (postArgs) delete[] postArgs; return true; } diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 54ed9c21f..3d9c77a9d 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -20,7 +20,7 @@ * Change image name BE_MINIMAL to FIRMWARE_MINIMAL and USE_xyz to FIRMWARE_xyz (#5106) * Change GUI weblog from XML to plain text solving possible empty screens (#5154) * Fix most compiler warnings - * Fix Display exception 28 when JSON value is NULL received + * Fix Display exception 28 when JSON value is nullptr received * Fix epaper driver (#4785) * Fix HAss Sensor Discovery Software Watchdog restart (#4831, #4988) * Fix allowable MAX_RULE_VARS to 16 (#4933) diff --git a/sonoff/settings.ino b/sonoff/settings.ino index dff0d849f..ca8cd1b3a 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -306,7 +306,7 @@ void EepromEnd(void) uint16_t settings_crc = 0; uint32_t settings_location = SETTINGS_LOCATION; -uint8_t *settings_buffer = NULL; +uint8_t *settings_buffer = nullptr; /********************************************************************************************/ /* @@ -333,9 +333,9 @@ void SetFlashModeDout(void) void SettingsBufferFree(void) { - if (settings_buffer != NULL) { + if (settings_buffer != nullptr) { free(settings_buffer); - settings_buffer = NULL; + settings_buffer = nullptr; } } diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index 458b12ed6..bcefc9a08 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -188,15 +188,15 @@ char* Format(char* output, const char* input, int size) char *token; uint8_t digits = 0; - if (strstr(input, "%")) { + if (strstr(input, "%") != nullptr) { strlcpy(output, input, size); token = strtok(output, "%"); if (strstr(input, "%") == input) { output[0] = '\0'; } else { - token = strtok(NULL, ""); + token = strtok(nullptr, ""); } - if (token != NULL) { + if (token != nullptr) { digits = atoi(token); if (digits) { char tmp[size]; @@ -221,10 +221,10 @@ char* Format(char* output, const char* input, int size) char* GetOtaUrl(char *otaurl, size_t otaurl_size) { - if (strstr(Settings.ota_url, "%04d") != NULL) { // OTA url contains placeholder for chip ID + if (strstr(Settings.ota_url, "%04d") != nullptr) { // OTA url contains placeholder for chip ID snprintf(otaurl, otaurl_size, Settings.ota_url, ESP.getChipId() & 0x1fff); } - else if (strstr(Settings.ota_url, "%d") != NULL) { // OTA url contains placeholder for chip ID + else if (strstr(Settings.ota_url, "%d") != nullptr) { // OTA url contains placeholder for chip ID snprintf_P(otaurl, otaurl_size, Settings.ota_url, ESP.getChipId()); } else { @@ -278,7 +278,7 @@ char* GetTopic_P(char *stopic, uint8_t prefix, char *topic, const char* subtopic char* GetFallbackTopic_P(char *stopic, uint8_t prefix, const char* subtopic) { - return GetTopic_P(stopic, prefix +4, NULL, subtopic); + return GetTopic_P(stopic, prefix +4, nullptr, subtopic); } char* GetStateText(uint8_t state) @@ -452,7 +452,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) char command [CMDSZ]; char stemp1[TOPSZ]; char *p; - char *type = NULL; + char *type = nullptr; uint8_t lines = 1; bool jsflg = false; bool grpflg = false; @@ -480,7 +480,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) if (XdrvMqttData(topicBuf, sizeof(topicBuf), dataBuf, sizeof(dataBuf))) { return; } - grpflg = (strstr(topicBuf, Settings.mqtt_grptopic) != NULL); + grpflg = (strstr(topicBuf, Settings.mqtt_grptopic) != nullptr); GetFallbackTopic_P(stemp1, CMND, ""); // Full Fallback topic = cmnd/DVES_xxxxxxxx_fb/ fallback_topic_flag = (!strncmp(topicBuf, stemp1, strlen(stemp1))); @@ -488,7 +488,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) type = strrchr(topicBuf, '/'); // Last part of received topic is always the command (type) index = 1; - if (type != NULL) { + if (type != nullptr) { type++; for (i = 0; i < strlen(type); i++) { type[i] = toupper(type[i]); @@ -505,7 +505,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_RESULT D_GROUP " %d, " D_INDEX " %d, " D_COMMAND " %s, " D_DATA " %s"), grpflg, index, type, dataBuf); - if (type != NULL) { + if (type != nullptr) { Response_P(PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_ERROR "\"}")); if (Settings.ledstate &0x02) { blinks++; } @@ -538,7 +538,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) XdrvMailbox.data = dataBuf; if (!XdrvCall(FUNC_COMMAND)) { if (!XsnsCall(FUNC_COMMAND)) { - type = NULL; // Unknown command + type = nullptr; // Unknown command } } } @@ -547,7 +547,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) uint8_t bl_pointer = (!backlog_pointer) ? MAX_BACKLOG -1 : backlog_pointer; bl_pointer--; char *blcommand = strtok(dataBuf, ";"); - while ((blcommand != NULL) && (backlog_index != bl_pointer)) { + while ((blcommand != nullptr) && (backlog_index != bl_pointer)) { while(true) { blcommand = Trim(blcommand); if (!strncasecmp_P(blcommand, PSTR(D_CMND_BACKLOG), strlen(D_CMND_BACKLOG))) { @@ -561,7 +561,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) backlog_index++; if (backlog_index >= MAX_BACKLOG) backlog_index = 0; } - blcommand = strtok(NULL, ";"); + blcommand = strtok(nullptr, ";"); } // Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_APPENDED); mqtt_data[0] = '\0'; @@ -974,7 +974,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) // {"NAME":"Generic","GPIO":[17,254,29,254,7,254,254,254,138,254,139,254,254],"FLAG":1,"BASE":255} bool error = false; - if (!strstr(dataBuf, "{")) { // If no JSON it must be parameter + if (strstr(dataBuf, "{") == nullptr) { // If no JSON it must be parameter if ((payload > 0) && (payload <= MAXMODULE)) { ModuleDefault(payload -1); // Copy template module if (USER_MODULE == Settings.module) { restart_flag = 2; } @@ -1193,7 +1193,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) else if (CMND_HOSTNAME == command_code) { if (!grpflg && (data_len > 0) && (data_len < sizeof(Settings.hostname))) { strlcpy(Settings.hostname, (SC_DEFAULT == Shortcut(dataBuf)) ? WIFI_HOSTNAME : dataBuf, sizeof(Settings.hostname)); - if (strstr(Settings.hostname,"%")) { + if (strstr(Settings.hostname, "%") != nullptr) { strlcpy(Settings.hostname, WIFI_HOSTNAME, sizeof(Settings.hostname)); } restart_flag = 2; @@ -1238,15 +1238,15 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) if (max_relays > sizeof(Settings.interlock[0]) * 8) { max_relays = sizeof(Settings.interlock[0]) * 8; } if (max_relays > 1) { // Only interlock with more than 1 relay if (data_len > 0) { - if (strstr(dataBuf, ",")) { // Interlock entry + if (strstr(dataBuf, ",") != nullptr) { // Interlock entry for (uint8_t i = 0; i < MAX_INTERLOCKS; i++) { Settings.interlock[i] = 0; } // Reset current interlocks char *group; char *q; uint8_t group_index = 0; power_t relay_mask = 0; - for (group = strtok_r(dataBuf, " ", &q); group && group_index < MAX_INTERLOCKS; group = strtok_r(NULL, " ", &q)) { + for (group = strtok_r(dataBuf, " ", &q); group && group_index < MAX_INTERLOCKS; group = strtok_r(nullptr, " ", &q)) { char *str; - for (str = strtok_r(group, ",", &p); str; str = strtok_r(NULL, ",", &p)) { + for (str = strtok_r(group, ",", &p); str; str = strtok_r(nullptr, ",", &p)) { int pbit = atoi(str); if ((pbit > 0) && (pbit <= max_relays)) { // Only valid relays pbit--; @@ -1329,9 +1329,9 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) if (payload < 15) { p = strtok (dataBuf, ":"); if (p) { - p = strtok (NULL, ":"); + p = strtok (nullptr, ":"); if (p) { - Settings.timezone_minutes = strtol(p, NULL, 10); + Settings.timezone_minutes = strtol(p, nullptr, 10); if (Settings.timezone_minutes > 59) { Settings.timezone_minutes = 59; } } } @@ -1352,7 +1352,7 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) uint8_t ts = 0; if (CMND_TIMEDST == command_code) { ts = 1; } if (data_len > 0) { - if (strstr(dataBuf, ",")) { // Process parameter entry + if (strstr(dataBuf, ",") != nullptr) { // Process parameter entry uint8_t tpos = 0; // Parameter index int value = 0; p = dataBuf; // Parameters like "1, 2,3 , 4 ,5, -120" or ",,,,,+240" @@ -1426,9 +1426,9 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) I2cScan(mqtt_data, sizeof(mqtt_data)); } #endif // USE_I2C - else type = NULL; // Unknown command + else type = nullptr; // Unknown command } - if (type == NULL) { + if (type == nullptr) { blinks = 201; snprintf_P(topicBuf, sizeof(topicBuf), PSTR(D_JSON_COMMAND)); Response_P(PSTR("{\"" D_JSON_COMMAND "\":\"" D_JSON_UNKNOWN "\"}")); @@ -1608,18 +1608,18 @@ void ExecuteCommand(char *cmnd, int source) ShowSource(source); token = strtok(cmnd, " "); - if (token != NULL) { + if (token != nullptr) { start = strrchr(token, '/'); // Skip possible cmnd/sonoff/ preamble if (start) { token = start +1; } } - uint16_t size = (token != NULL) ? strlen(token) : 0; + uint16_t size = (token != nullptr) ? strlen(token) : 0; char stopic[size +2]; // / + \0 - snprintf_P(stopic, sizeof(stopic), PSTR("/%s"), (token == NULL) ? "" : token); + snprintf_P(stopic, sizeof(stopic), PSTR("/%s"), (token == nullptr) ? "" : token); - token = strtok(NULL, ""); - size = (token != NULL) ? strlen(token) : 0; + token = strtok(nullptr, ""); + size = (token != nullptr) ? strlen(token) : 0; char svalue[size +1]; - strlcpy(svalue, (token == NULL) ? "" : token, sizeof(svalue)); // Fixed 5.8.0b + strlcpy(svalue, (token == nullptr) ? "" : token, sizeof(svalue)); // Fixed 5.8.0b MqttDataHandler(stopic, (uint8_t*)svalue, strlen(svalue)); } @@ -1807,10 +1807,10 @@ bool MqttShowSensor(void) } XsnsCall(FUNC_JSON_APPEND); bool json_data_available = (strlen(mqtt_data) - json_data_start); - if (strstr_P(mqtt_data, PSTR(D_JSON_PRESSURE))) { + if (strstr_P(mqtt_data, PSTR(D_JSON_PRESSURE)) != nullptr) { ResponseAppend_P(PSTR(",\"" D_JSON_PRESSURE_UNIT "\":\"%s\""), PressureUnit().c_str()); } - if (strstr_P(mqtt_data, PSTR(D_JSON_TEMPERATURE))) { + if (strstr_P(mqtt_data, PSTR(D_JSON_TEMPERATURE)) != nullptr) { ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE_UNIT "\":\"%c\""), TempUnit()); } ResponseAppend_P(PSTR("}")); @@ -2025,8 +2025,8 @@ void Every250mSeconds(void) #ifndef FIRMWARE_MINIMAL if (RtcSettings.ota_loader) { char *bch = strrchr(mqtt_data, '/'); // Only consider filename after last backslash prevent change of urls having "-" in it - char *pch = strrchr((bch != NULL) ? bch : mqtt_data, '-'); // Change from filename-DE.bin into filename-minimal.bin - char *ech = strrchr((bch != NULL) ? bch : mqtt_data, '.'); // Change from filename.bin into filename-minimal.bin + char *pch = strrchr((bch != nullptr) ? bch : mqtt_data, '-'); // Change from filename-DE.bin into filename-minimal.bin + char *ech = strrchr((bch != nullptr) ? bch : mqtt_data, '.'); // Change from filename.bin into filename-minimal.bin if (!pch) { pch = ech; } if (pch) { mqtt_data[pch - mqtt_data] = '\0'; @@ -2611,7 +2611,7 @@ void setup(void) Format(mqtt_client, Settings.mqtt_client, sizeof(mqtt_client)); Format(mqtt_topic, Settings.mqtt_topic, sizeof(mqtt_topic)); - if (strstr(Settings.hostname, "%")) { + if (strstr(Settings.hostname, "%") != nullptr) { strlcpy(Settings.hostname, WIFI_HOSTNAME, sizeof(Settings.hostname)); snprintf_P(my_hostname, sizeof(my_hostname)-1, Settings.hostname, mqtt_topic, ESP.getChipId() & 0x1FFF); } else { diff --git a/sonoff/support.ino b/sonoff/support.ino index 823655ce4..07edd039a 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -139,15 +139,15 @@ size_t strchrspn(const char *str1, int character) char* subStr(char* dest, char* str, const char *delim, int index) { char *act; - char *sub = NULL; + char *sub = nullptr; char *ptr; int i; // Since strtok consumes the first arg, make a copy strncpy(dest, str, strlen(str)+1); - for (i = 1, act = dest; i <= index; i++, act = NULL) { + for (i = 1, act = dest; i <= index; i++, act = nullptr) { sub = strtok_r(act, delim, &ptr); - if (sub == NULL) break; + if (sub == nullptr) break; } sub = Trim(sub); return sub; @@ -377,9 +377,9 @@ bool ParseIp(uint32_t* addr, const char* str) *addr = 0; for (i = 0; i < 4; i++) { - part[i] = strtoul(str, NULL, 10); // Convert byte + part[i] = strtoul(str, nullptr, 10); // Convert byte str = strchr(str, '.'); - if (str == NULL || *str == '\0') { + if (str == nullptr || *str == '\0') { break; // No more separators, exit } str++; // Point to next character after separator @@ -422,7 +422,7 @@ bool NewerVersion(char* version_str) return false; // Bail if we can't duplicate. Assume bad. } // Loop through the version string, splitting on '.' seperators. - for (char *str = strtok_r(version_dup, ".", &str_ptr); str && i < sizeof(VERSION); str = strtok_r(NULL, ".", &str_ptr), i++) { + for (char *str = strtok_r(version_dup, ".", &str_ptr); str && i < sizeof(VERSION); str = strtok_r(nullptr, ".", &str_ptr), i++) { int field = atoi(str); // The fields in a version string can only range from 0-255. if ((field < 0) || (field > 255)) { @@ -1219,7 +1219,7 @@ void SetSeriallog(uint8_t loglevel) #ifdef USE_WEBSERVER void GetLog(uint8_t idx, char** entry_pp, size_t* len_p) { - char* entry_p = NULL; + char* entry_p = nullptr; size_t len = 0; if (idx) { diff --git a/sonoff/support_rtc.ino b/sonoff/support_rtc.ino index 9a36951f0..5af8b49a0 100644 --- a/sonoff/support_rtc.ino +++ b/sonoff/support_rtc.ino @@ -61,7 +61,7 @@ String GetBuildDateAndTime(void) // sscanf(mdate, "%s %d %d", bdt, &day, &year); // Not implemented in 2.3.0 and probably too much code uint8_t i = 0; - for (char *str = strtok_r(mdate, " ", &p); str && i < 3; str = strtok_r(NULL, " ", &p)) { + for (char *str = strtok_r(mdate, " ", &p); str && i < 3; str = strtok_r(nullptr, " ", &p)) { switch (i++) { case 0: // Month smonth = str; diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index f34bfda09..48932fb0d 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -41,7 +41,7 @@ #include #ifdef USE_RF_FLASH -uint8_t *efm8bb1_update = NULL; +uint8_t *efm8bb1_update = nullptr; #endif // USE_RF_FLASH enum UploadTypes { UPL_TASMOTA, UPL_SETTINGS, UPL_EFM8BB1 }; @@ -524,7 +524,7 @@ void WifiManagerBegin(bool reset_only) int channel = WIFI_SOFT_AP_CHANNEL; if ((channel < 1) || (channel > 13)) { channel = 1; } - WiFi.softAP(my_hostname, NULL, channel); + WiFi.softAP(my_hostname, nullptr, channel); delay(500); // Without delay I've seen the IP address blank /* Setup the DNS server redirecting all the domains to the apIP */ @@ -689,7 +689,7 @@ void WSContentStart_P(const char* title, bool auth) WSContentBegin(200, CT_HTML); - if (title != NULL) { + if (title != nullptr) { char ctitle[strlen_P(title) +1]; strcpy_P(ctitle, title); // Get title from flash to RAM WSContentSend_P(HTTP_HEAD, Settings.friendlyname[0], ctitle); @@ -710,7 +710,7 @@ void WSContentSendStyle_P(const char* style) } WSContentSend_P(HTTP_HEAD_STYLE1); WSContentSend_P(HTTP_HEAD_STYLE2); - if (style != NULL) { + if (style != nullptr) { WSContentSend_P(style); } WSContentSend_P(HTTP_HEAD_STYLE3, ModuleName().c_str(), Settings.friendlyname[0]); @@ -729,7 +729,7 @@ void WSContentSendStyle_P(const char* style) void WSContentSendStyle(void) { - WSContentSendStyle_P(NULL); + WSContentSendStyle_P(nullptr); } void WSContentButton(uint8_t title_index) @@ -1359,7 +1359,7 @@ void WifiSaveSettings(void) WebGetArg("h", tmp, sizeof(tmp)); strlcpy(Settings.hostname, (!strlen(tmp)) ? WIFI_HOSTNAME : tmp, sizeof(Settings.hostname)); - if (strstr(Settings.hostname,"%")) { + if (strstr(Settings.hostname, "%") != nullptr) { strlcpy(Settings.hostname, WIFI_HOSTNAME, sizeof(Settings.hostname)); } WebGetArg("s1", tmp, sizeof(tmp)); @@ -1885,10 +1885,10 @@ void HandleUploadLoop(void) } #ifdef USE_RF_FLASH else if (UPL_EFM8BB1 == upload_file_type) { - if (efm8bb1_update != NULL) { // We have carry over data since last write, i. e. a start but not an end + if (efm8bb1_update != nullptr) { // We have carry over data since last write, i. e. a start but not an end ssize_t result = rf_glue_remnant_with_new_data_and_write(efm8bb1_update, upload.buf, upload.currentSize); free(efm8bb1_update); - efm8bb1_update = NULL; + efm8bb1_update = nullptr; if (result != 0) { upload_error = abs(result); // 2 = Not enough space, 8 = File invalid return; @@ -1907,7 +1907,7 @@ void HandleUploadLoop(void) // A remnant has been detected, allocate data for it plus a null termination byte size_t remnant_sz = upload.currentSize - result; efm8bb1_update = (uint8_t *) malloc(remnant_sz + 1); - if (efm8bb1_update == NULL) { + if (efm8bb1_update == nullptr) { upload_error = 2; // Not enough space - Unable to allocate memory to store new RF firmware return; } diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 37bdd97c2..b4228b11e 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -301,7 +301,7 @@ void MqttConnected(void) GetTopic_P(stopic, CMND, mqtt_topic, PSTR("#")); MqttSubscribe(stopic); - if (strstr(Settings.mqtt_fulltopic, MQTT_TOKEN_TOPIC) != NULL) { + if (strstr(Settings.mqtt_fulltopic, MQTT_TOKEN_TOPIC) != nullptr) { GetTopic_P(stopic, CMND, Settings.mqtt_grptopic, PSTR("#")); MqttSubscribe(stopic); GetFallbackTopic_P(stopic, CMND, PSTR("#")); @@ -431,8 +431,8 @@ void MqttReconnect(void) mqtt_retry_counter = Settings.mqtt_retry; global_state.mqtt_down = 1; - char *mqtt_user = NULL; - char *mqtt_pwd = NULL; + char *mqtt_user = nullptr; + char *mqtt_pwd = nullptr; if (strlen(Settings.mqtt_user) > 0) mqtt_user = Settings.mqtt_user; if (strlen(Settings.mqtt_pwd) > 0) mqtt_pwd = Settings.mqtt_pwd; @@ -607,7 +607,7 @@ bool MqttCommand(void) char *mqtt_part = strtok(dataBuf, " "); if (mqtt_part) { strlcpy(stemp1, mqtt_part, sizeof(stemp1)); - mqtt_part = strtok(NULL, " "); + mqtt_part = strtok(nullptr, " "); if (mqtt_part) { strlcpy(mqtt_data, mqtt_part, sizeof(mqtt_data)); } else { diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index fc9d1a635..5dae14ce7 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -1231,9 +1231,9 @@ bool LightColorEntry(char *buffer, uint8_t buffer_length) } memset(&light_entry_color, 0x00, sizeof(light_entry_color)); - if (strstr(buffer, ",")) { // Decimal entry + if (strstr(buffer, ",") != nullptr) { // Decimal entry int8_t i = 0; - for (str = strtok_r(buffer, ",", &p); str && i < 6; str = strtok_r(NULL, ",", &p)) { + for (str = strtok_r(buffer, ",", &p); str && i < 6; str = strtok_r(nullptr, ",", &p)) { if (i < 5) { light_entry_color[i++] = atoi(str); } @@ -1345,16 +1345,16 @@ bool LightCommand(void) bool validHSB = (XdrvMailbox.data_len > 0); if (validHSB) { uint16_t HSB[3]; - if (strstr(XdrvMailbox.data, ",")) { // Command with 3 comma separated parameters, Hue (0 0); char scolor[25]; if (validtable) { - if (strstr(XdrvMailbox.data, ",")) { // Command with up to 5 comma separated parameters + if (strstr(XdrvMailbox.data, ",") != nullptr) { // Command with up to 5 comma separated parameters for (int i = 0; i < LST_RGBWC; i++) { char *substr; if (0 == i) { substr = strtok(XdrvMailbox.data, ","); } else { - substr = strtok(NULL, ","); + substr = strtok(nullptr, ","); } - if (substr != NULL) { + if (substr != nullptr) { Settings.rgbwwTable[i] = atoi(substr); } } diff --git a/sonoff/xdrv_05_irremote.ino b/sonoff/xdrv_05_irremote.ino index 9592555b8..7e6501142 100644 --- a/sonoff/xdrv_05_irremote.ino +++ b/sonoff/xdrv_05_irremote.ino @@ -54,7 +54,7 @@ const char kIrHvacVendors[] PROGMEM = "Toshiba|Mitsubishi|LG|Fujitsu" ; // HVAC LG #define HVAC_LG_DATALEN 7 -IRMitsubishiAC *mitsubir = NULL; +IRMitsubishiAC *mitsubir = nullptr; const char kFanSpeedOptions[] = "A12345S"; const char kHvacModeOptions[] = "HDCA"; @@ -66,7 +66,7 @@ const char kHvacModeOptions[] = "HDCA"; #include -IRsend *irsend = NULL; +IRsend *irsend = nullptr; bool irsend_active = false; void IrSendInit(void) @@ -90,7 +90,7 @@ void IrSendInit(void) #include -IRrecv *irrecv = NULL; +IRrecv *irrecv = nullptr; unsigned long ir_lasttime = 0; @@ -189,7 +189,7 @@ bool IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Po char *p; uint8_t mode; - if (HVAC_Mode == NULL) { + if (HVAC_Mode == nullptr) { p = (char *)kHvacModeOptions; // default HVAC_HOT } else { @@ -204,7 +204,7 @@ bool IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Po data[6] = (uint8_t)0x07; // Turn OFF HVAC } - if (HVAC_FanMode == NULL) { + if (HVAC_FanMode == nullptr) { p = (char *)kFanSpeedOptions; // default FAN_SPEED_AUTO } else { @@ -283,7 +283,7 @@ bool IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC mitsubir->stateReset(); - if (HVAC_Mode == NULL) { + if (HVAC_Mode == nullptr) { p = (char *)kHvacModeOptions; // default HVAC_HOT } else { @@ -297,7 +297,7 @@ bool IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC mitsubir->setPower(HVAC_Power); - if (HVAC_FanMode == NULL) { + if (HVAC_FanMode == nullptr) { p = (char *)kFanSpeedOptions; // default FAN_SPEED_AUTO } else { @@ -350,7 +350,7 @@ bool IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, else { // Set code for HVAC Mode - data[3] - if (HVAC_Mode == NULL) { + if (HVAC_Mode == nullptr) { p = (char *)kHvacModeOptions; // default HVAC_HOT } else { @@ -394,7 +394,7 @@ bool IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, data[4] = (uint8_t)(Temp - 15); // Set code for HVAC fan mode - data[5] - if (HVAC_FanMode == NULL) { + if (HVAC_FanMode == nullptr) { p = (char *)kFanSpeedOptions; // default FAN_SPEED_AUTO } else { @@ -462,7 +462,7 @@ bool IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Po ac.setSwing(FUJITSU_AC_SWING_VERT); char *p; - if (NULL == HVAC_Mode) { + if (nullptr == HVAC_Mode) { p = (char *)kFujitsuHvacModeOptions; } else { @@ -473,7 +473,7 @@ bool IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Po } ac.setMode(modes[p - kFujitsuHvacModeOptions]); - if (HVAC_FanMode == NULL) { + if (HVAC_FanMode == nullptr) { p = (char *)kFanSpeedOptions; // default FAN_SPEED_AUTO } else { @@ -518,7 +518,7 @@ bool IrSendCommand(void) if (XdrvMailbox.data_len) { Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); - if (!strstr(XdrvMailbox.data, "{")) { // If no JSON it must be rawdata + if (strstr(XdrvMailbox.data, "{") == nullptr) { // If no JSON it must be rawdata // IRSend frequency, rawdata, rawdata ... char *p; char *str = strtok_r(XdrvMailbox.data, ", ", &p); @@ -531,8 +531,8 @@ bool IrSendCommand(void) count++; uint16_t raw_array[count]; // It's safe to use stack for up to 240 packets (limited by mqtt_data length) uint8_t i = 0; - for (str = strtok_r(NULL, ", ", &p); str && i < count; str = strtok_r(NULL, ", ", &p)) { - raw_array[i++] = strtoul(str, NULL, 0); // Allow decimal (5246996) and hexadecimal (0x501014) input + for (str = strtok_r(nullptr, ", ", &p); str && i < count; str = strtok_r(nullptr, ", ", &p)) { + raw_array[i++] = strtoul(str, nullptr, 0); // Allow decimal (5246996) and hexadecimal (0x501014) input } // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: Count %d, Freq %d, Arr[0] %d, Arr[count -1] %d"), count, freq, raw_array[0], raw_array[count -1]); @@ -560,7 +560,7 @@ bool IrSendCommand(void) char parm_uc[10]; const char *protocol = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_PROTOCOL))]; uint32_t bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_BITS))]; - uint32_t data = strtoul(root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATA))], NULL, 0); + uint32_t data = strtoul(root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATA))], nullptr, 0); if (protocol && bits) { char protocol_text[20]; int protocol_code = GetCommandCode(protocol_text, sizeof(protocol_text), protocol, kIrRemoteProtocols); diff --git a/sonoff/xdrv_06_snfbridge.ino b/sonoff/xdrv_06_snfbridge.ino index 14947fd77..f2550bf8d 100644 --- a/sonoff/xdrv_06_snfbridge.ino +++ b/sonoff/xdrv_06_snfbridge.ino @@ -98,7 +98,7 @@ ssize_t rf_glue_remnant_with_new_data_and_write(const uint8_t *remnant_data, uin glue_record_sz = strlen((const char *) remnant_data) + record_end; glue_buf = (uint8_t *) malloc(glue_record_sz); - if (glue_buf == NULL) { return -2; } // Not enough space + if (glue_buf == nullptr) { return -2; } // Not enough space // Assemble new glue buffer memcpy(glue_buf, remnant_data, strlen((const char *) remnant_data)); diff --git a/sonoff/xdrv_08_serial_bridge.ino b/sonoff/xdrv_08_serial_bridge.ino index bf3221025..e9f8294ca 100644 --- a/sonoff/xdrv_08_serial_bridge.ino +++ b/sonoff/xdrv_08_serial_bridge.ino @@ -31,10 +31,10 @@ enum SerialBridgeCommands { CMND_SSERIALSEND, CMND_SBAUDRATE }; const char kSerialBridgeCommands[] PROGMEM = D_CMND_SSERIALSEND "|" D_CMND_SBAUDRATE; -TasmotaSerial *SerialBridgeSerial = NULL; +TasmotaSerial *SerialBridgeSerial = nullptr; unsigned long serial_bridge_polling_window = 0; -char *serial_bridge_buffer = NULL; +char *serial_bridge_buffer = nullptr; int serial_bridge_in_byte_counter = 0; bool serial_bridge_active = true; bool serial_bridge_raw = false; diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index 59d9300f4..05e931254 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -387,7 +387,7 @@ bool TimerCommand(void) strlcpy(time_str, root[parm_uc], sizeof(time_str)); const char *substr = strtok(time_str, ":"); - if (substr != NULL) { + if (substr != nullptr) { if (strchr(substr, '-')) { sign = 1; substr++; @@ -396,8 +396,8 @@ bool TimerCommand(void) if (sign) { value += 12; } // Allow entering timer offset from -11:59 to -00:01 converted to 12:01 to 23:59 if (value > 23) { value = 23; } itime = value * 60; - substr = strtok(NULL, ":"); - if (substr != NULL) { + substr = strtok(nullptr, ":"); + if (substr != nullptr) { value = atoi(substr); if (value < 0) { value = 0; } if (value > 59) { value = 59; } diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index b2761a2d4..2a93ee86f 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -672,10 +672,10 @@ String RulesSubscribe(const char *data, int data_len) char * pos = strtok(parameters, ","); if (pos) { event_name = Trim(pos); - pos = strtok(NULL, ","); + pos = strtok(nullptr, ","); if (pos) { topic = Trim(pos); - pos = strtok(NULL, ","); + pos = strtok(nullptr, ","); if (pos) { key = Trim(pos); } @@ -1203,7 +1203,7 @@ bool RulesCommand(void) } else if ((CMND_SCALE == command_code) && (index > 0) && (index <= MAX_RULE_VARS)) { if (XdrvMailbox.data_len > 0) { - if (strstr(XdrvMailbox.data, ",")) { // Process parameter entry + if (strstr(XdrvMailbox.data, ",") != nullptr) { // Process parameter entry char sub_string[XdrvMailbox.data_len +1]; double valueIN = CharToDouble(subStr(sub_string, XdrvMailbox.data, ",", 1)); diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index 45c9fe15f..b92ed1c7b 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -1086,7 +1086,7 @@ bool KnxCommand(void) else if (CMND_KNX_PA == command_code) { if (XdrvMailbox.data_len) { - if (strstr(XdrvMailbox.data, ".")) { // Process parameter entry + if (strstr(XdrvMailbox.data, ".") != nullptr) { // Process parameter entry char sub_string[XdrvMailbox.data_len]; int pa_area = atoi(subStr(sub_string, XdrvMailbox.data, ".", 1)); @@ -1113,7 +1113,7 @@ bool KnxCommand(void) else if ((CMND_KNX_GA == command_code) && (index > 0) && (index <= MAX_KNX_GA)) { if (XdrvMailbox.data_len) { - if (strstr(XdrvMailbox.data, ",")) { // Process parameter entry + if (strstr(XdrvMailbox.data, ",") != nullptr) { // Process parameter entry char sub_string[XdrvMailbox.data_len]; int ga_option = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1)); @@ -1162,7 +1162,7 @@ bool KnxCommand(void) else if ((CMND_KNX_CB == command_code) && (index > 0) && (index <= MAX_KNX_CB)) { if (XdrvMailbox.data_len) { - if (strstr(XdrvMailbox.data, ",")) { // Process parameter entry + if (strstr(XdrvMailbox.data, ",") != nullptr) { // Process parameter entry char sub_string[XdrvMailbox.data_len]; int cb_option = atoi(subStr(sub_string, XdrvMailbox.data, ",", 1)); diff --git a/sonoff/xdrv_13_display.ino b/sonoff/xdrv_13_display.ino index 89dde70d1..8a05d68f3 100644 --- a/sonoff/xdrv_13_display.ino +++ b/sonoff/xdrv_13_display.ino @@ -503,9 +503,9 @@ void DisplayClearScreenBuffer(void) void DisplayFreeScreenBuffer(void) { - if (disp_screen_buffer != NULL) { + if (disp_screen_buffer != nullptr) { for (uint8_t i = 0; i < disp_screen_buffer_rows; i++) { - if (disp_screen_buffer[i] != NULL) { free(disp_screen_buffer[i]); } + if (disp_screen_buffer[i] != nullptr) { free(disp_screen_buffer[i]); } } free(disp_screen_buffer); disp_screen_buffer_cols = 0; @@ -518,16 +518,16 @@ void DisplayAllocScreenBuffer(void) if (!disp_screen_buffer_cols) { disp_screen_buffer_rows = Settings.display_rows; disp_screen_buffer = (char**)malloc(sizeof(*disp_screen_buffer) * disp_screen_buffer_rows); - if (disp_screen_buffer != NULL) { + if (disp_screen_buffer != nullptr) { for (uint8_t i = 0; i < disp_screen_buffer_rows; i++) { disp_screen_buffer[i] = (char*)malloc(sizeof(*disp_screen_buffer[i]) * (Settings.display_cols[0] +1)); - if (disp_screen_buffer[i] == NULL) { + if (disp_screen_buffer[i] == nullptr) { DisplayFreeScreenBuffer(); break; } } } - if (disp_screen_buffer != NULL) { + if (disp_screen_buffer != nullptr) { disp_screen_buffer_cols = Settings.display_cols[0] +1; DisplayClearScreenBuffer(); } @@ -562,9 +562,9 @@ void DisplayClearLogBuffer(void) void DisplayFreeLogBuffer(void) { - if (disp_log_buffer != NULL) { + if (disp_log_buffer != nullptr) { for (uint8_t i = 0; i < DISPLAY_LOG_ROWS; i++) { - if (disp_log_buffer[i] != NULL) { free(disp_log_buffer[i]); } + if (disp_log_buffer[i] != nullptr) { free(disp_log_buffer[i]); } } free(disp_log_buffer); disp_log_buffer_cols = 0; @@ -575,16 +575,16 @@ void DisplayAllocLogBuffer(void) { if (!disp_log_buffer_cols) { disp_log_buffer = (char**)malloc(sizeof(*disp_log_buffer) * DISPLAY_LOG_ROWS); - if (disp_log_buffer != NULL) { + if (disp_log_buffer != nullptr) { for (uint8_t i = 0; i < DISPLAY_LOG_ROWS; i++) { disp_log_buffer[i] = (char*)malloc(sizeof(*disp_log_buffer[i]) * (Settings.display_cols[0] +1)); - if (disp_log_buffer[i] == NULL) { + if (disp_log_buffer[i] == nullptr) { DisplayFreeLogBuffer(); break; } } } - if (disp_log_buffer != NULL) { + if (disp_log_buffer != nullptr) { disp_log_buffer_cols = Settings.display_cols[0] +1; DisplayClearLogBuffer(); } @@ -608,7 +608,7 @@ void DisplayLogBufferAdd(char* txt) char* DisplayLogBuffer(char temp_code) { - char* result = NULL; + char* result = nullptr; if (disp_log_buffer_cols) { if (disp_log_buffer_idx != disp_log_buffer_ptr) { result = disp_log_buffer[disp_log_buffer_ptr]; @@ -616,7 +616,7 @@ char* DisplayLogBuffer(char temp_code) if (DISPLAY_LOG_ROWS == disp_log_buffer_ptr) { disp_log_buffer_ptr = 0; } char *pch = strchr(result, '~'); // = 0x7E (~) Replace degrees character (276 octal) - if (pch != NULL) { result[pch - result] = temp_code; } + if (pch != nullptr) { result[pch - result] = temp_code; } } } return result; @@ -829,12 +829,12 @@ void DisplayMqttSubscribe(void) ntopic[0] = '\0'; strlcpy(stopic, Settings.mqtt_fulltopic, sizeof(stopic)); char *tp = strtok(stopic, "/"); - while (tp != NULL) { + while (tp != nullptr) { if (!strcmp_P(tp, PSTR(MQTT_TOKEN_PREFIX))) { break; } strncat_P(ntopic, PSTR("+/"), sizeof(ntopic) - strlen(ntopic) -1); // Add single-level wildcards - tp = strtok(NULL, "/"); + tp = strtok(nullptr, "/"); } strncat(ntopic, Settings.mqtt_prefix[2], sizeof(ntopic) - strlen(ntopic) -1); // Subscribe to tele messages strncat_P(ntopic, PSTR("/#"), sizeof(ntopic) - strlen(ntopic) -1); // Add multi-level wildcard diff --git a/sonoff/xdrv_16_tuyadimmer.ino b/sonoff/xdrv_16_tuyadimmer.ino index 53c4984cc..f9b3665e4 100644 --- a/sonoff/xdrv_16_tuyadimmer.ino +++ b/sonoff/xdrv_16_tuyadimmer.ino @@ -53,7 +53,7 @@ uint8_t tuya_cmd_checksum = 0; // Checksum of tuya command uint8_t tuya_data_len = 0; // Data lenght of command int8_t tuya_wifi_state = -2; // Keep MCU wifi-status in sync with WifiState() -char *tuya_buffer = NULL; // Serial receive buffer +char *tuya_buffer = nullptr; // Serial receive buffer int tuya_byte_counter = 0; // Index in serial receive buffer /*********************************************************************************************\ @@ -284,7 +284,7 @@ void TuyaInit(void) Settings.param[P_TUYA_DIMMER_ID] = TUYA_DIMMER_ID; } tuya_buffer = (char*)(malloc(TUYA_BUFFER_SIZE)); - if (tuya_buffer != NULL) { + if (tuya_buffer != nullptr) { TuyaSerial = new TasmotaSerial(pin[GPIO_TUYA_RX], pin[GPIO_TUYA_TX], 2); if (TuyaSerial->begin(9600)) { if (TuyaSerial->hardwareSerial()) { ClaimSerial(); } diff --git a/sonoff/xdrv_17_rcswitch.ino b/sonoff/xdrv_17_rcswitch.ino index aaa594b2a..8018eaa2d 100644 --- a/sonoff/xdrv_17_rcswitch.ino +++ b/sonoff/xdrv_17_rcswitch.ino @@ -107,7 +107,7 @@ bool RfSendCommand(void) if (root.success()) { // RFsend {"data":0x501014,"bits":24,"protocol":1,"repeat":10,"pulse":350} char parm_uc[10]; - data = strtoul(root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_DATA))], NULL, 0); // Allow decimal (5246996) and hexadecimal (0x501014) input + data = strtoul(root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_DATA))], nullptr, 0); // Allow decimal (5246996) and hexadecimal (0x501014) input bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_BITS))]; protocol = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_PROTOCOL))]; repeat = root[UpperCase_P(parm_uc, PSTR(D_JSON_RF_REPEAT))]; @@ -116,10 +116,10 @@ bool RfSendCommand(void) // RFsend data, bits, protocol, repeat, pulse char *p; uint8_t i = 0; - for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 5; str = strtok_r(NULL, ", ", &p)) { + for (char *str = strtok_r(XdrvMailbox.data, ", ", &p); str && i < 5; str = strtok_r(nullptr, ", ", &p)) { switch (i++) { case 0: - data = strtoul(str, NULL, 0); // Allow decimal (5246996) and hexadecimal (0x501014) input + data = strtoul(str, nullptr, 0); // Allow decimal (5246996) and hexadecimal (0x501014) input break; case 1: bits = atoi(str); diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index e4b71bb18..ab58b6d9d 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -35,8 +35,8 @@ bool ps16dz_ignore_dim = false; // Flag to skip serial send to preven //uint64_t ps16dz_seq = 0; -char *ps16dz_tx_buffer = NULL; // Serial transmit buffer -char *ps16dz_rx_buffer = NULL; // Serial receive buffer +char *ps16dz_tx_buffer = nullptr; // Serial transmit buffer +char *ps16dz_rx_buffer = nullptr; // Serial receive buffer int ps16dz_byte_counter = 0; /*********************************************************************************************\ @@ -135,9 +135,9 @@ bool PS16DZModuleSelected(void) void PS16DZInit(void) { ps16dz_tx_buffer = (char*)(malloc(PS16DZ_BUFFER_SIZE)); - if (ps16dz_tx_buffer != NULL) { + if (ps16dz_tx_buffer != nullptr) { ps16dz_rx_buffer = (char*)(malloc(PS16DZ_BUFFER_SIZE)); - if (ps16dz_rx_buffer != NULL) { + if (ps16dz_rx_buffer != nullptr) { PS16DZSerial = new TasmotaSerial(pin[GPIO_RXD], pin[GPIO_TXD], 2); if (PS16DZSerial->begin(19200)) { if (PS16DZSerial->hardwareSerial()) { ClaimSerial(); } @@ -168,10 +168,10 @@ void PS16DZSerialInput(void) char *end_str; char *string = ps16dz_rx_buffer+10; char* token = strtok_r(string, ",", &end_str); - while (token != NULL) { + while (token != nullptr) { char* end_token; char* token2 = strtok_r(token, ":", &end_token); - char* token3 = strtok_r(NULL, ":", &end_token); + char* token3 = strtok_r(nullptr, ":", &end_token); if(!strncmp(token2, "\"switch\"", 8)){ bool ps16dz_power = !strncmp(token3, "\"on\"", 4)?true:false; AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: power received: %s"), token3); @@ -193,10 +193,10 @@ void PS16DZSerialInput(void) } } else if(!strncmp(token2, "\"sequence\"", 10)){ - //ps16dz_seq = strtoull(token3+1, NULL, 10); + //ps16dz_seq = strtoull(token3+1, nullptr, 10); AddLog_P2(LOG_LEVEL_DEBUG, PSTR("PSZ: sequence received: %s"), token3); } - token = strtok_r(NULL, ",", &end_str); + token = strtok_r(nullptr, ",", &end_str); } } else if(!strncmp(ps16dz_rx_buffer+3, "SETTING", 7)) { diff --git a/sonoff/xdsp_01_lcd.ino b/sonoff/xdsp_01_lcd.ino index 28d045858..c0877a859 100644 --- a/sonoff/xdsp_01_lcd.ino +++ b/sonoff/xdsp_01_lcd.ino @@ -127,7 +127,7 @@ bool LcdPrintLog(void) if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } char* txt = DisplayLogBuffer('\337'); - if (txt != NULL) { + if (txt != nullptr) { uint8_t last_row = Settings.display_rows -1; for (uint8_t i = 0; i < last_row; i++) { diff --git a/sonoff/xdsp_02_ssd1306.ino b/sonoff/xdsp_02_ssd1306.ino index 9697e4db0..8d8b696d7 100644 --- a/sonoff/xdsp_02_ssd1306.ino +++ b/sonoff/xdsp_02_ssd1306.ino @@ -141,7 +141,7 @@ void Ssd1306PrintLog(void) if (!disp_screen_buffer_cols) { DisplayAllocScreenBuffer(); } char* txt = DisplayLogBuffer('\370'); - if (txt != NULL) { + if (txt != nullptr) { uint8_t last_row = Settings.display_rows -1; oled->clearDisplay(); diff --git a/sonoff/xdsp_03_matrix.ino b/sonoff/xdsp_03_matrix.ino index 2535c92d9..a77b5df1e 100644 --- a/sonoff/xdsp_03_matrix.ino +++ b/sonoff/xdsp_03_matrix.ino @@ -37,7 +37,7 @@ int16_t mtx_x = 0; int16_t mtx_y = 0; //char mtx_buffer[MTX_MAX_SCREEN_BUFFER]; -char *mtx_buffer = NULL; +char *mtx_buffer = nullptr; uint8_t mtx_mode = 0; uint8_t mtx_loop = 0; @@ -140,9 +140,9 @@ void MatrixScrollUp(char* txt, int loop) disp_refresh = Settings.display_refresh; strlcpy(tmpbuf, txt, sizeof(tmpbuf)); char *p = strtok(tmpbuf, separators); - while (p != NULL && wordcounter < 40) { + while (p != nullptr && wordcounter < 40) { words[wordcounter++] = p; - p = strtok(NULL, separators); + p = strtok(nullptr, separators); } for (uint8_t i = 0; i < mtx_matrices; i++) { matrix[i]->clear(); @@ -196,7 +196,7 @@ void MatrixInit(uint8_t mode) void MatrixInitDriver(void) { mtx_buffer = (char*)(malloc(MTX_MAX_SCREEN_BUFFER)); - if (mtx_buffer != NULL) { + if (mtx_buffer != nullptr) { if (!Settings.display_model) { if (I2cDevice(Settings.display_address[1])) { Settings.display_model = XDSP_03; @@ -239,7 +239,7 @@ void MatrixDrawStringAt(uint16_t x, uint16_t y, char *str, uint16_t color, uint8 void MatrixPrintLog(uint8_t direction) { char* txt = (!mtx_done) ? DisplayLogBuffer('\370') : mtx_buffer; - if (txt != NULL) { + if (txt != nullptr) { if (!mtx_state) { mtx_state = 1; } if (!mtx_done) { diff --git a/sonoff/xdsp_04_ili9341.ino b/sonoff/xdsp_04_ili9341.ino index f50164e59..bf3c2729c 100644 --- a/sonoff/xdsp_04_ili9341.ino +++ b/sonoff/xdsp_04_ili9341.ino @@ -147,7 +147,7 @@ void Ili9341PrintLog(void) } char* txt = DisplayLogBuffer('\370'); - if (txt != NULL) { + if (txt != nullptr) { uint8_t size = Settings.display_size; uint16_t theight = size * TFT_FONT_HEIGTH; diff --git a/sonoff/xdsp_05_epaper_29.ino b/sonoff/xdsp_05_epaper_29.ino index 6f4034ece..c1daf8259 100644 --- a/sonoff/xdsp_05_epaper_29.ino +++ b/sonoff/xdsp_05_epaper_29.ino @@ -200,7 +200,7 @@ void EpdPrintLog(void) } char* txt = DisplayLogBuffer('\040'); - if (txt != NULL) { + if (txt != nullptr) { uint8_t size = Settings.display_size; uint16_t theight = size * EPD_FONT_HEIGTH; diff --git a/sonoff/xnrg_03_pzem004t.ino b/sonoff/xnrg_03_pzem004t.ino index a15d61ba1..b2c72bfa8 100644 --- a/sonoff/xnrg_03_pzem004t.ino +++ b/sonoff/xnrg_03_pzem004t.ino @@ -32,7 +32,7 @@ #include -TasmotaSerial *PzemSerial = NULL; +TasmotaSerial *PzemSerial = nullptr; #define PZEM_VOLTAGE (uint8_t)0xB0 #define RESP_VOLTAGE (uint8_t)0xA0 diff --git a/sonoff/xnrg_04_mcp39f501.ino b/sonoff/xnrg_04_mcp39f501.ino index d878d9e8b..5d6adec33 100644 --- a/sonoff/xnrg_04_mcp39f501.ino +++ b/sonoff/xnrg_04_mcp39f501.ino @@ -67,7 +67,7 @@ #define MCP_BUFFER_SIZE 60 #include -TasmotaSerial *McpSerial = NULL; +TasmotaSerial *McpSerial = nullptr; typedef struct mcp_cal_registers_type { uint16_t gain_current_rms; @@ -92,7 +92,7 @@ typedef struct mcp_cal_registers_type { uint16_t accumulation_interval; } mcp_cal_registers_type; -char *mcp_buffer = NULL; +char *mcp_buffer = nullptr; unsigned long mcp_window = 0; unsigned long mcp_kWhcounter = 0; uint32_t mcp_system_configuration = 0x03000000; diff --git a/sonoff/xplg_wemohue.ino b/sonoff/xplg_wemohue.ino index 60edf4a64..1c0a4f782 100644 --- a/sonoff/xplg_wemohue.ino +++ b/sonoff/xplg_wemohue.ino @@ -239,7 +239,7 @@ void PollUdp(void) AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: Packet (%d)"), len); // AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("\n%s"), packet_buffer); - if (strstr_P(packet_buffer, PSTR("M-SEARCH"))) { + if (strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr) { udp_response_mutex = true; udp_remote_ip = PortUdp.remoteIP(); @@ -253,21 +253,21 @@ void PollUdp(void) LowerCase(packet_buffer, packet_buffer); RemoveSpace(packet_buffer); if (EMUL_WEMO == Settings.flag2.emulation) { - if (strstr_P(packet_buffer, URN_BELKIN_DEVICE)) { // type1 echo dot 2g, echo 1g's + if (strstr_P(packet_buffer, URN_BELKIN_DEVICE) != nullptr) { // type1 echo dot 2g, echo 1g's TickerMSearch.attach_ms(response_delay, WemoRespondToMSearch, 1); return; } - else if (strstr_P(packet_buffer, UPNP_ROOTDEVICE) || // type2 Echo 2g (echo & echo plus) - strstr_P(packet_buffer, SSDPSEARCH_ALL) || - strstr_P(packet_buffer, SSDP_ALL)) { + else if ((strstr_P(packet_buffer, UPNP_ROOTDEVICE) != nullptr) || // type2 Echo 2g (echo & echo plus) + (strstr_P(packet_buffer, SSDPSEARCH_ALL) != nullptr) || + (strstr_P(packet_buffer, SSDP_ALL) != nullptr)) { TickerMSearch.attach_ms(response_delay, WemoRespondToMSearch, 2); return; } } else { - if (strstr_P(packet_buffer, PSTR("urn:schemas-upnp-org:device:basic:1")) || - strstr_P(packet_buffer, UPNP_ROOTDEVICE) || - strstr_P(packet_buffer, SSDPSEARCH_ALL) || - strstr_P(packet_buffer, SSDP_ALL)) { + if ((strstr_P(packet_buffer, PSTR("urn:schemas-upnp-org:device:basic:1")) != nullptr) || + (strstr_P(packet_buffer, UPNP_ROOTDEVICE) != nullptr) || + (strstr_P(packet_buffer, SSDPSEARCH_ALL) != nullptr) || + (strstr_P(packet_buffer, SSDP_ALL) != nullptr)) { TickerMSearch.attach_ms(response_delay, HueRespondToMSearch); return; } @@ -402,13 +402,13 @@ void HandleUpnpEvent(void) //differentiate get and set state char state = 'G'; - if (strstr_P(event, PSTR("SetBinaryState"))) { + if (strstr_P(event, PSTR("SetBinaryState")) != nullptr) { state = 'S'; uint8_t power = POWER_TOGGLE; - if (strstr_P(event, PSTR("State>1100 *strip = NULL; + NeoPixelBus *strip = nullptr; struct WsColor { uint8_t red, green, blue; diff --git a/sonoff/xsns_04_snfsc.ino b/sonoff/xsns_04_snfsc.ino index 051640f63..54611fd0d 100644 --- a/sonoff/xsns_04_snfsc.ino +++ b/sonoff/xsns_04_snfsc.ino @@ -81,7 +81,7 @@ void SonoffScSerialInput(char *rcvstat) if (!strncasecmp_P(rcvstat, PSTR("AT+UPDATE="), 10)) { int8_t i = -1; - for (str = strtok_r(rcvstat, ":", &p); str && i < 5; str = strtok_r(NULL, ":", &p)) { + for (str = strtok_r(rcvstat, ":", &p); str && i < 5; str = strtok_r(nullptr, ":", &p)) { value[i++] = atoi(str); } if (value[0] > 0) { diff --git a/sonoff/xsns_05_ds18x20_legacy.ino b/sonoff/xsns_05_ds18x20_legacy.ino index 9ecdcbff5..f02ee9e12 100644 --- a/sonoff/xsns_05_ds18x20_legacy.ino +++ b/sonoff/xsns_05_ds18x20_legacy.ino @@ -36,7 +36,7 @@ #include -OneWire *ds = NULL; +OneWire *ds = nullptr; uint8_t ds18x20_address[DS18X20_MAX_SENSORS][8]; uint8_t ds18x20_index[DS18X20_MAX_SENSORS]; diff --git a/sonoff/xsns_09_bmp.ino b/sonoff/xsns_09_bmp.ino index cc738f977..881738745 100755 --- a/sonoff/xsns_09_bmp.ino +++ b/sonoff/xsns_09_bmp.ino @@ -61,7 +61,7 @@ uint8_t bmp_addresses[] = { BMP_ADDR1, BMP_ADDR2 }; uint8_t bmp_count = 0; uint8_t bmp_once = 1; -bmp_sensors_t *bmp_sensors = NULL; +bmp_sensors_t *bmp_sensors = nullptr; /*********************************************************************************************\ * BMP085 and BME180 @@ -99,7 +99,7 @@ typedef struct { uint16_t cal_ac6; } bmp180_cal_data_t; -bmp180_cal_data_t *bmp180_cal_data = NULL; +bmp180_cal_data_t *bmp180_cal_data = nullptr; bool Bmp180Calibration(uint8_t bmp_idx) { @@ -244,7 +244,7 @@ typedef struct { int8_t dig_H6; } Bme280CalibrationData_t; -Bme280CalibrationData_t *Bme280CalibrationData = NULL; +Bme280CalibrationData_t *Bme280CalibrationData = nullptr; bool Bmx280Calibrate(uint8_t bmp_idx) { @@ -344,7 +344,7 @@ void Bme280Read(uint8_t bmp_idx) #include -struct bme680_dev *gas_sensor = NULL; +struct bme680_dev *gas_sensor = nullptr; static void BmeDelayMs(uint32_t ms) { diff --git a/sonoff/xsns_20_novasds.ino b/sonoff/xsns_20_novasds.ino index 25f73c2df..8b8d6ef52 100644 --- a/sonoff/xsns_20_novasds.ino +++ b/sonoff/xsns_20_novasds.ino @@ -109,7 +109,7 @@ bool NovaSdsCommand(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint16_t sensor NovaSdsSerial->readBytes(&recbuf[1], 9); AddLogBuffer(LOG_LEVEL_DEBUG_MORE, recbuf, sizeof(recbuf)); - if ( NULL != buffer ) { + if ( nullptr != buffer ) { // return data to buffer memcpy(buffer, recbuf, sizeof(recbuf)); } @@ -126,9 +126,9 @@ bool NovaSdsCommand(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint16_t sensor void NovaSdsSetWorkPeriod(void) { // set sensor working period - NovaSdsCommand(NOVA_SDS_WORKING_PERIOD, NOVA_SDS_SET_MODE, WORKING_PERIOD, NOVA_SDS_DEVICE_ID, NULL); + NovaSdsCommand(NOVA_SDS_WORKING_PERIOD, NOVA_SDS_SET_MODE, WORKING_PERIOD, NOVA_SDS_DEVICE_ID, nullptr); // set sensor report only on query - NovaSdsCommand(NOVA_SDS_REPORTING_MODE, NOVA_SDS_SET_MODE, NOVA_SDS_REPORT_QUERY, NOVA_SDS_DEVICE_ID, NULL); + NovaSdsCommand(NOVA_SDS_REPORTING_MODE, NOVA_SDS_SET_MODE, NOVA_SDS_REPORT_QUERY, NOVA_SDS_DEVICE_ID, nullptr); } bool NovaSdsReadData(void) diff --git a/sonoff/xsns_22_sr04.ino b/sonoff/xsns_22_sr04.ino index f30ff11f7..f475790ae 100644 --- a/sonoff/xsns_22_sr04.ino +++ b/sonoff/xsns_22_sr04.ino @@ -34,7 +34,7 @@ uint8_t sr04_echo_pin = 0; uint8_t sr04_trig_pin = 0; real64_t distance; -NewPing* sonar = NULL; +NewPing* sonar = nullptr; void Sr04Init(void) { diff --git a/sonoff/xsns_34_hx711.ino b/sonoff/xsns_34_hx711.ino index b72ef0a9f..c1fd9c20e 100644 --- a/sonoff/xsns_34_hx711.ino +++ b/sonoff/xsns_34_hx711.ino @@ -165,8 +165,8 @@ bool HxCommand(void) Response_P(S_JSON_SENSOR_INDEX_SVALUE, XSNS_34, "Reset"); break; case 2: // Calibrate - if (strstr(XdrvMailbox.data, ",")) { - Settings.weight_reference = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), NULL, 10); + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.weight_reference = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); } hx_scale = 1; HxReset(); @@ -175,26 +175,26 @@ bool HxCommand(void) HxCalibrationStateTextJson(3); break; case 3: // WeightRef to user reference - if (strstr(XdrvMailbox.data, ",")) { - Settings.weight_reference = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), NULL, 10); + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.weight_reference = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); } show_parms = true; break; case 4: // WeightCal to user calculated value - if (strstr(XdrvMailbox.data, ",")) { - Settings.weight_calibration = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), NULL, 10); + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.weight_calibration = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10); hx_scale = Settings.weight_calibration; } show_parms = true; break; case 5: // WeightMax - if (strstr(XdrvMailbox.data, ",")) { - Settings.weight_max = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), NULL, 10) / 1000; + if (strstr(XdrvMailbox.data, ",") != nullptr) { + Settings.weight_max = strtol(subStr(sub_string, XdrvMailbox.data, ",", 2), nullptr, 10) / 1000; } show_parms = true; break; case 6: // WeightItem - if (strstr(XdrvMailbox.data, ",")) { + if (strstr(XdrvMailbox.data, ",") != nullptr) { Settings.weight_item = (unsigned long)(CharToDouble(subStr(sub_string, XdrvMailbox.data, ",", 2)) * 10); } show_parms = true; diff --git a/sonoff/xsns_37_rfsensor.ino b/sonoff/xsns_37_rfsensor.ino index 4a94e2d77..aadcf01d9 100644 --- a/sonoff/xsns_37_rfsensor.ino +++ b/sonoff/xsns_37_rfsensor.ino @@ -56,7 +56,7 @@ typedef struct RawSignalStruct // Variabelen geplaatst in stru // Om legacy redenen zit de eerste puls in element 1. Element 0 wordt dus niet gebruikt. } raw_signal_t; -raw_signal_t *rfsns_raw_signal = NULL; +raw_signal_t *rfsns_raw_signal = nullptr; uint8_t rfsns_rf_bit; uint8_t rfsns_rf_port; uint8_t rfsns_any_sensor = 0; @@ -165,8 +165,8 @@ typedef struct { uint8_t volt; } theo_v2_t2_t; -theo_v2_t1_t *rfsns_theo_v2_t1 = NULL; -theo_v2_t2_t *rfsns_theo_v2_t2 = NULL; +theo_v2_t1_t *rfsns_theo_v2_t1 = nullptr; +theo_v2_t2_t *rfsns_theo_v2_t2 = nullptr; void RfSnsInitTheoV2(void) { @@ -423,7 +423,7 @@ typedef struct { uint8_t wdir; } alecto_v2_t; -alecto_v2_t *rfsns_alecto_v2 = NULL; +alecto_v2_t *rfsns_alecto_v2 = nullptr; uint16_t rfsns_alecto_rain_base = 0; void RfSnsInitAlectoV2(void) @@ -617,7 +617,7 @@ void RfSnsInit(void) pinMode(pin[GPIO_RF_SENSOR], INPUT); } else { free(rfsns_raw_signal); - rfsns_raw_signal = NULL; + rfsns_raw_signal = nullptr; } } } From 43e79e83521c165d011e2c0b77b841c672e1d2d2 Mon Sep 17 00:00:00 2001 From: Christoph Hofmann Date: Wed, 27 Mar 2019 03:39:22 +0100 Subject: [PATCH 13/81] Fix pca9685 driver command --- sonoff/xdrv_15_pca9685.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_15_pca9685.ino b/sonoff/xdrv_15_pca9685.ino index 1a27219c8..e3ffbaa8e 100644 --- a/sonoff/xdrv_15_pca9685.ino +++ b/sonoff/xdrv_15_pca9685.ino @@ -189,9 +189,9 @@ bool Xdrv15(uint8_t function) PCA9685_OutputTelemetry(true); } break; - case FUNC_COMMAND: + case FUNC_COMMAND_DRIVER: if (XDRV_15 == XdrvMailbox.index) { - PCA9685_Command(); + result = PCA9685_Command(); } break; default: From feb11dd49e0003d7e5b6233330b8d8e68b5f17ad Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 27 Mar 2019 18:09:27 +0100 Subject: [PATCH 14/81] wemohue tuning wemohue tuning --- sonoff/xdrv_interface.ino | 2 +- sonoff/xplg_wemohue.ino | 45 +++++++++++++++++---------------------- 2 files changed, 20 insertions(+), 27 deletions(-) diff --git a/sonoff/xdrv_interface.ino b/sonoff/xdrv_interface.ino index 7de5e1bb5..84f80062b 100644 --- a/sonoff/xdrv_interface.ino +++ b/sonoff/xdrv_interface.ino @@ -210,7 +210,7 @@ bool XdrvRulesProcess(void) #ifdef USE_DEBUG_DRIVER void ShowFreeMem(const char *where) { - char stemp[20]; + char stemp[30]; snprintf_P(stemp, sizeof(stemp), where); XdrvMailbox.data = stemp; XdrvCall(FUNC_FREE_MEM); diff --git a/sonoff/xplg_wemohue.ino b/sonoff/xplg_wemohue.ino index 1c0a4f782..e3351fbe4 100644 --- a/sonoff/xplg_wemohue.ino +++ b/sonoff/xplg_wemohue.ino @@ -31,7 +31,6 @@ #include Ticker TickerMSearch; -char packet_buffer[UDP_BUFFER_SIZE]; // buffer to hold incoming UDP packet IPAddress udp_remote_ip; // M-Search remote IP address uint16_t udp_remote_port; // M-Search remote port @@ -120,20 +119,20 @@ const char HUE_RESPONSE[] PROGMEM = "HOST: 239.255.255.250:1900\r\n" "CACHE-CONTROL: max-age=100\r\n" "EXT:\r\n" - "LOCATION: http://{r1:80/description.xml\r\n" + "LOCATION: http://%s:80/description.xml\r\n" "SERVER: Linux/3.14.0 UPnP/1.0 IpBridge/1.17.0\r\n" - "hue-bridgeid: {r2\r\n"; + "hue-bridgeid: %s\r\n"; const char HUE_ST1[] PROGMEM = "ST: upnp:rootdevice\r\n" - "USN: uuid:{r3::upnp:rootdevice\r\n" + "USN: uuid:%s::upnp:rootdevice\r\n" "\r\n"; const char HUE_ST2[] PROGMEM = - "ST: uuid:{r3\r\n" - "USN: uuid:{r3\r\n" + "ST: uuid:%s\r\n" + "USN: uuid:%s\r\n" "\r\n"; const char HUE_ST3[] PROGMEM = "ST: urn:schemas-upnp-org:device:basic:1\r\n" - "USN: uuid:{r3\r\n" + "USN: uuid:%s\r\n" "\r\n"; String HueBridgeId(void) @@ -165,26 +164,20 @@ void HueRespondToMSearch(void) TickerMSearch.detach(); if (PortUdp.beginPacket(udp_remote_ip, udp_remote_port)) { - String response1 = FPSTR(HUE_RESPONSE); - response1.replace("{r1", WiFi.localIP().toString()); - response1.replace("{r2", HueBridgeId()); + char response[320]; + snprintf_P(response, sizeof(response), HUE_RESPONSE, WiFi.localIP().toString().c_str(), HueBridgeId().c_str()); + int len = strlen(response); - String response = response1; - response += FPSTR(HUE_ST1); - response.replace("{r3", HueUuid()); - PortUdp.write(response.c_str()); + snprintf_P(response + len, sizeof(response) - len, HUE_ST1, HueUuid().c_str()); + PortUdp.write(response); PortUdp.endPacket(); - response = response1; - response += FPSTR(HUE_ST2); - response.replace("{r3", HueUuid()); - PortUdp.write(response.c_str()); + snprintf_P(response + len, sizeof(response) - len, HUE_ST2, HueUuid().c_str(), HueUuid().c_str()); + PortUdp.write(response); PortUdp.endPacket(); - response = response1; - response += FPSTR(HUE_ST3); - response.replace("{r3", HueUuid()); - PortUdp.write(response.c_str()); + snprintf_P(response + len, sizeof(response) - len, HUE_ST3, HueUuid().c_str()); + PortUdp.write(response); PortUdp.endPacket(); snprintf_P(message, sizeof(message), PSTR(D_3_RESPONSE_PACKETS_SENT)); @@ -231,10 +224,10 @@ void PollUdp(void) { if (udp_connected && !udp_response_mutex && devices_present) { if (PortUdp.parsePacket()) { + char packet_buffer[UDP_BUFFER_SIZE]; // buffer to hold incoming UDP/SSDP packet + int len = PortUdp.read(packet_buffer, UDP_BUFFER_SIZE -1); - if (len > 0) { - packet_buffer[len] = 0; - } + packet_buffer[len] = 0; AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: Packet (%d)"), len); // AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("\n%s"), packet_buffer); @@ -264,7 +257,7 @@ void PollUdp(void) return; } } else { - if ((strstr_P(packet_buffer, PSTR("urn:schemas-upnp-org:device:basic:1")) != nullptr) || + if ((strstr_P(packet_buffer, PSTR(":device:basic:1")) != nullptr) || (strstr_P(packet_buffer, UPNP_ROOTDEVICE) != nullptr) || (strstr_P(packet_buffer, SSDPSEARCH_ALL) != nullptr) || (strstr_P(packet_buffer, SSDP_ALL) != nullptr)) { From 8ee8fa262c23ce44270acee83c914d614a89f6d0 Mon Sep 17 00:00:00 2001 From: Tom Paine Date: Thu, 28 Mar 2019 00:22:53 +0000 Subject: [PATCH 15/81] Minor spelling --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 8a8402339..586520fc6 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ## Sonoff-Tasmota -Alternative firmware for _ESP8266 based devices_ like [iTead](https://www.itead.cc/) _**Sonoff**_ with **web UI, rules and timers, OTA updates, custome device templates and sensors support**. Allows control over **MQTT**, **HTTP**, **Serial** and **KNX** for integrations with smart home systems. Written for Arduino IDE and PlatformIO. +Alternative firmware for _ESP8266 based devices_ like [iTead](https://www.itead.cc/) _**Sonoff**_ with **web UI, rules and timers, OTA updates, custom device templates and sensor support**. Allows control over **MQTT**, **HTTP**, **Serial** and **KNX** for integrations with smart home systems. Written for Arduino IDE and PlatformIO. [![GitHub version](https://img.shields.io/github/release/arendst/Sonoff-Tasmota.svg)](https://github.com/arendst/Sonoff-Tasmota/releases/latest) [![GitHub download](https://img.shields.io/github/downloads/arendst/Sonoff-Tasmota/total.svg)](https://github.com/arendst/Sonoff-Tasmota/releases/latest) @@ -15,7 +15,7 @@ If you like **Sonoff-Tasmota**, give it a star, or fork it and contribute! See [RELEASENOTES.md](https://github.com/arendst/Sonoff-Tasmota/blob/development/RELEASENOTES.md) for release information. -In addition to the [release webpage](https://github.com/arendst/Sonoff-Tasmota/releases/latest) the binaries can also be OTA downloaded from http://thehackbox.org/tasmota/release/ +In addition to the [release webpage](https://github.com/arendst/Sonoff-Tasmota/releases/latest), the binaries can also be OTA downloaded from http://thehackbox.org/tasmota/release/ ### Development [![Dev Version](https://img.shields.io/badge/development%20version-6.5.0.x-blue.svg)](https://github.com/arendst/Sonoff-Tasmota) @@ -29,12 +29,12 @@ The development codebase is checked hourly for changes and if new commits have b ### Disclaimer :warning: **DANGER OF ELECTROCUTION** :warning: -A Sonoff device is not a toy. It uses Mains AC so there is a danger of electrocution if not installed properly. If you don't know how to install it, please call an electrician. Remember: _**SAFETY FIRST**_. It is not worth to risk yourself, your family and your home if you don't know exactly what you are doing. Never try to flash a Sonoff device while it is connected to MAINS AC. +A Sonoff device is not a toy. It uses Mains AC so there is a danger of electrocution if not installed properly. If you don't know how to install it, please call an electrician. Remember: _**SAFETY FIRST**_. It is not worth risk to yourself, your family, and your home if you don't know exactly what you are doing. Never try to flash a Sonoff device while it is connected to MAINS AC. We don't take any responsibility nor liability for using this software nor for the installation or any tips, advice, videos, etc. given by any member of this site or any related site. ### Note -Please do not ask to add devices where you can't provide a basic working configuration (other than sonoff). Since there are thousands of them.. +Please do not ask to add devices where you can't provide a basic working configuration (other than sonoff). Since there are thousands of them. ### Quick Install Download one of the released binaries from https://github.com/arendst/Sonoff-Tasmota/releases and flash it to your hardware as documented in the wiki. From 3ad804616662fa275bec38aa3a62a915a45d0983 Mon Sep 17 00:00:00 2001 From: Jon Little Date: Sat, 23 Mar 2019 18:26:03 -0500 Subject: [PATCH 16/81] Adding HRE interface for en-GB --- sonoff/i18n.h | 6 + sonoff/language/en-GB.h | 7 +- sonoff/sonoff_template.h | 9 +- sonoff/xsns_91_hre.ino | 299 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 319 insertions(+), 2 deletions(-) create mode 100644 sonoff/xsns_91_hre.ino diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 60b5880e0..766a2cd7e 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -69,6 +69,7 @@ #define D_JSON_FLASHCHIPID "FlashChipId" #define D_JSON_FLASHMODE "FlashMode" #define D_JSON_FLASHSIZE "FlashSize" +#define D_JSON_FLOWRATE "FlowRate" #define D_JSON_FREEMEMORY "Free" #define D_JSON_FREQUENCY "Frequency" #define D_JSON_FROM "from" @@ -143,6 +144,7 @@ #define D_JSON_TIME "Time" #define D_JSON_TODAY "Today" #define D_JSON_TOTAL "Total" +#define D_JSON_TOTAL_USAGE "TotalUsage" #define D_JSON_TOTAL_REACTIVE "TotalReactivePower" #define D_JSON_TOTAL_START_TIME "TotalStartTime" #define D_JSON_TVOC "TVOC" @@ -515,6 +517,8 @@ const char S_JSON_DRIVER_INDEX_SVALUE[] PROGMEM = "{\"" D_CMND_DRIVE const char JSON_SNS_TEMP[] PROGMEM = ",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}"; const char JSON_SNS_TEMPHUM[] PROGMEM = ",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"; +const char JSON_SNS_GNGPM[] PROGMEM = "%s,\"%s\":{\"" D_JSON_TOTAL_USAGE "\":%s,\"" D_JSON_FLOWRATE "\":%s}"; + const char S_LOG_I2C_FOUND_AT[] PROGMEM = D_LOG_I2C "%s " D_FOUND_AT " 0x%x"; const char S_LOG_HTTP[] PROGMEM = D_LOG_HTTP; @@ -569,6 +573,8 @@ const char HTTP_SNS_ANALOG[] PROGMEM = "{s}%s " D_ANALOG_INPUT "%d{m}%d{e}"; const char HTTP_SNS_ILLUMINANCE[] PROGMEM = "{s}%s " D_ILLUMINANCE "{m}%d " D_UNIT_LUX "{e}"; // {s} = , {m} = , {e} = const char HTTP_SNS_CO2[] PROGMEM = "{s}%s " D_CO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}"; // {s} = , {m} = , {e} = const char HTTP_SNS_CO2EAVG[] PROGMEM = "{s}%s " D_ECO2 "{m}%d " D_UNIT_PARTS_PER_MILLION "{e}"; // {s} = , {m} = , {e} = +const char HTTP_SNS_GALLONS[] PROGMEM = "{s}%s " D_TOTAL_USAGE "{m}%s " D_UNIT_GALLONS " {e}"; // {s} = , {m} = , {e} = +const char HTTP_SNS_GPM[] PROGMEM = "{s}%s " D_FLOW_RATE "{m}%s " D_UNIT_GALLONS_PER_MIN" {e}"; // {s} = , {m} = , {e} = const char S_MAIN_MENU[] PROGMEM = D_MAIN_MENU; const char S_CONFIGURATION[] PROGMEM = D_CONFIGURATION; diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index d5e792462..e8ba8f3fb 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Fallback Topic" #define D_FALSE "False" #define D_FILE "File" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Free Memory" #define D_FREQUENCY "Frequency" #define D_GAS "Gas" @@ -156,6 +157,7 @@ #define D_TO "to" #define D_TOGGLE "Toggle" #define D_TOPIC "Topic" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Transmit" #define D_TRUE "True" #define D_TVOC "TVOC" @@ -576,12 +578,15 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" - +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "Hr" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index cf5a1af78..b50c2184b 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -178,6 +178,8 @@ enum UserSelectablePins { GPIO_ROT1B, // Rotary switch1 B Pin GPIO_ROT2A, // Rotary switch2 A Pin GPIO_ROT2B, // Rotary switch2 B Pin + GPIO_HRE_CLOCK, // Clock/Power line for HR-E Water Meter + GPIO_HRE_DATA, // Data line for HR-E Water Meter GPIO_SENSOR_END }; // Programmer selectable GPIO functionality @@ -241,6 +243,7 @@ const char kSensorNames[] PROGMEM = D_SENSOR_CSE7766_TX "|" D_SENSOR_CSE7766_RX "|" D_SENSOR_ARIRFRCV "|" D_SENSOR_TXD "|" D_SENSOR_RXD "|" D_SENSOR_ROTARY "1a|" D_SENSOR_ROTARY "1b|" D_SENSOR_ROTARY "2a|" D_SENSOR_ROTARY "2b|" + D_SENSOR_HRE_CLOCK "|" D_SENSOR_HRE_DATA "|" ; /********************************************************************************************/ @@ -584,7 +587,11 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_ROT1B, // Rotary switch1 B Pin GPIO_ROT2A, // Rotary switch2 A Pin GPIO_ROT2B, // Rotary switch2 B Pin - GPIO_ARIRFRCV // AliLux RF Receive input + GPIO_ARIRFRCV, // AliLux RF Receive input +#ifdef USE_HRE + GPIO_HRE_CLOCK, + GPIO_HRE_DATA +#endif }; const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { diff --git a/sonoff/xsns_91_hre.ino b/sonoff/xsns_91_hre.ino new file mode 100644 index 000000000..ac15a937a --- /dev/null +++ b/sonoff/xsns_91_hre.ino @@ -0,0 +1,299 @@ +/* + xsns_07_sht1x.ino - SHT1x temperature and sensor support for Sonoff-Tasmota + + Copyright (C) 2019 Theo Arends + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +/*********************************************************************************************\ + * HR-E LCD Water meter register interface + * + * https://www.badgermeter.com/business-lines/utility/high-resolution-lcd-encoders-hr-e-lcd/ + * Source: Jon Little, https://github.com/burundiocibu/particle/blob/master/water_meter/src/HRE_Reader.cpp + * + * This code marches the bits out the data line as ASCII characters with the form + * KG44?Q45484=0444444V;RB000000022;IB018435683 + * where the RB...; is the miligalons used + * + * Note that this sensor takes a _long_ time to read. 62 bits * 4 ms/bit for the + * sync sequence plus 46 bytes * 40 ms/byte = 2088 ms minimum. If we aren't alligned + * to the sync sequence, it could be almost twice that. + * To keep from bogging the kernel down, we read 8 bits at a time on the 50 ms callback. + * It will take seconds to discover if the device is there. + * + * In lieu of an actual schematic to describe the electrical interface, here is a description: + * + * hre_clock_pin: drives the power/clock for the water meter through a 1k resister to + * the base of a pnp transistor + * hre_data_pin: is the data and has a 1 k pulldown + * + * The pnp transitor has the collector connected to the power/clock and is pulled up + * to +5 via a 1 k resistor. + * The emitter is connected to ground + * +\*********************************************************************************************/ + +#ifdef USE_HRE + +#define XSNS_91 91 + +enum hre_states { + hre_idle, // Initial state, + hre_sync, // Start search for sync sequence + hre_syncing, // Searching for sync sequence + hre_read, // Start reading data block + hre_reading, // Reading data + hre_sleep, // Start sleeping + hre_sleeping // pausing before reading again +}; + +hre_states hre_state = hre_idle; + +float hre_usage = 0; // total water usage, in gal +float hre_rate = 0; // flow rate, in gal/min +uint32_t hre_usage_time = 0; // uptime associated with hre_usage and hre_rate + +int hre_read_errors = 0; // total number of read errors since boot +bool hre_good = false; + + +// The settling times here were determined using a single unit hooked to a scope +int hreReadBit() +{ + digitalWrite(pin[GPIO_HRE_CLOCK], HIGH); + delay(1); + int bit = digitalRead(pin[GPIO_HRE_DATA]); + digitalWrite(pin[GPIO_HRE_CLOCK], LOW); + delay(1); + return bit; +} + +// With the times in the HreReadBit routine, a characer will take +// 20 ms plus io time. +char hreReadChar(int &parity_errors) +{ + // start bit + hreReadBit(); + + unsigned ch=0; + int sum=0; + for (int i=0; i<7; i++) + { + int b = hreReadBit(); + ch |= b << i; + sum += b; + } + + // parity + if ( (sum & 0x1) != hreReadBit()) + parity_errors++; + + // stop bit + hreReadBit(); + + return ch; +} + +void hreInit(void) +{ + hre_read_errors = 0; + hre_good = false; + + pinMode(pin[GPIO_HRE_CLOCK], OUTPUT); + pinMode(pin[GPIO_HRE_DATA], INPUT); + + // Note that the level shifter inverts this line and we want to leave it + // high when not being read. + digitalWrite(pin[GPIO_HRE_CLOCK], LOW); + + hre_state = hre_sync; +} + + +void hreEvery50ms(void) +{ + static int sync_counter = 0; // Number of sync bit reads + static int sync_run = 0; // Number of consecutive '1's read + + static uint32_t curr_start = 0; // uptime when entered hre_reading for current read + static int read_counter = 0; // number of bytes in the current read + static int parity_errors = 0; // Number of parity errors in current read + static char buff[46]; // 8 char and a term + static char aux[46]; // 8 char and a term + + static char ch; + static size_t i; + + switch (hre_state) + { + case hre_sync: + if (uptime < 15) + break; + sync_run = 0; + sync_counter = 0; + hre_state = hre_syncing; + snprintf_P(log_data, sizeof(log_data), PSTR("HRE: state:syncing")); + AddLog(LOG_LEVEL_DEBUG); + break; + + case hre_syncing: + // Find the header, a string of 62 '1's + // Note that on startup, this could take a a whole block (46 bytes) + // before we start seeing the header + for (int i=0; i<8; i++) + { + if (hreReadBit()) + sync_run++; + else + sync_run = 0; + if (sync_run == 62) + { + hre_state = hre_read; + break; + } + sync_counter++; + } + // If the meter doesn't get in sync within 1000 bits, give up for now + if (sync_counter > 1000) + { + hre_state = hre_sleep; + snprintf_P(log_data, sizeof(log_data), PSTR("HRE: sync error")); + AddLog(LOG_LEVEL_DEBUG); + } + break; + + // Start reading the data block + case hre_read: + snprintf_P(log_data, sizeof(log_data), PSTR("HRE: sync_run:%d, sync_counter:%d"), sync_run, sync_counter); + AddLog(LOG_LEVEL_DEBUG); + read_counter = 0; + parity_errors = 0; + curr_start = uptime; + memset(buff, 0, sizeof(buff)); + hre_state = hre_reading; + snprintf_P(log_data, sizeof(log_data), PSTR("HRE: state:reading")); + AddLog(LOG_LEVEL_DEBUG); + // So this is intended to fall through to the hre_reading section. + // it seems that if there is much of a delay between getting the sync + // bits and starting the read, the HRE won't output the message we + // are looking for... + + case hre_reading: + //ch = hreReadChar(parity_errors); + //i = read_counter - 24; // The water usage reading starts 24 bytes into the block + //if (i>=0 && i 27) + hre_state = hre_sync; + } +} + +void hreShow(boolean json) +{ + if (!hre_good) + return; + + const char hre_types[] = "HRE"; + + char usage[33]; + char rate[33]; + dtostrfd(hre_usage, 2, usage); + dtostrfd(hre_rate, 3, rate); + + if (json) + { + snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_GNGPM, mqtt_data, hre_types, usage, rate); +#ifdef USE_WEBSERVER + } + else + { + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_GALLONS, mqtt_data, hre_types, usage); + snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_GPM, mqtt_data, hre_types, rate); +#endif // USE_WEBSERVER + } +} + + +/*********************************************************************************************\ + * Interface +\*********************************************************************************************/ +bool Xsns91(byte function) +{ + // If we don't have pins assigned give up quickly. + if (pin[GPIO_HRE_CLOCK] >= 99 || pin[GPIO_HRE_DATA] >= 99) + return false; + + switch (function) + { + case FUNC_INIT: + hreInit(); + break; + case FUNC_EVERY_50_MSECOND: + hreEvery50ms(); + break; + case FUNC_EVERY_SECOND: + break; + case FUNC_JSON_APPEND: + hreShow(1); + break; +#ifdef USE_WEBSERVER + case FUNC_WEB_SENSOR: + hreShow(0); + break; +#endif // USE_WEBSERVER + } + return false; +} + +#endif // USE_HRE From 17a5e90e865a4c75d0e5e73bbab196d7415306bf Mon Sep 17 00:00:00 2001 From: Jon Little Date: Sun, 24 Mar 2019 14:58:26 -0500 Subject: [PATCH 17/81] Fixing copyright and name --- sonoff/xsns_91_hre.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xsns_91_hre.ino b/sonoff/xsns_91_hre.ino index ac15a937a..d3410556b 100644 --- a/sonoff/xsns_91_hre.ino +++ b/sonoff/xsns_91_hre.ino @@ -1,7 +1,7 @@ /* - xsns_07_sht1x.ino - SHT1x temperature and sensor support for Sonoff-Tasmota + xsns_09_hre.ino - Badger HR-E Water Meter Encoder interface - Copyright (C) 2019 Theo Arends + Copyright (C) 2019 Jon Little This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by From d375d95529500eddaf28a306de8476d4cfc1b9cd Mon Sep 17 00:00:00 2001 From: Jon Little Date: Mon, 25 Mar 2019 14:10:17 -0500 Subject: [PATCH 18/81] Updating to work with new web/mqtt api --- sonoff/i18n.h | 2 +- sonoff/language/en-GB.h | 3 +++ sonoff/xsns_91_hre.ino | 40 +++++++++++++++------------------------- 3 files changed, 19 insertions(+), 26 deletions(-) diff --git a/sonoff/i18n.h b/sonoff/i18n.h index 766a2cd7e..58e1ba63d 100644 --- a/sonoff/i18n.h +++ b/sonoff/i18n.h @@ -517,7 +517,7 @@ const char S_JSON_DRIVER_INDEX_SVALUE[] PROGMEM = "{\"" D_CMND_DRIVE const char JSON_SNS_TEMP[] PROGMEM = ",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s}"; const char JSON_SNS_TEMPHUM[] PROGMEM = ",\"%s\":{\"" D_JSON_TEMPERATURE "\":%s,\"" D_JSON_HUMIDITY "\":%s}"; -const char JSON_SNS_GNGPM[] PROGMEM = "%s,\"%s\":{\"" D_JSON_TOTAL_USAGE "\":%s,\"" D_JSON_FLOWRATE "\":%s}"; +const char JSON_SNS_GNGPM[] PROGMEM = ",\"%s\":{\"" D_JSON_TOTAL_USAGE "\":%s,\"" D_JSON_FLOWRATE "\":%s}"; const char S_LOG_I2C_FOUND_AT[] PROGMEM = D_LOG_I2C "%s " D_FOUND_AT " 0x%x"; diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index e8ba8f3fb..c1ee1ed5c 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -494,6 +494,9 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "None" #define D_SENSOR_USER "User" diff --git a/sonoff/xsns_91_hre.ino b/sonoff/xsns_91_hre.ino index d3410556b..c73d94338 100644 --- a/sonoff/xsns_91_hre.ino +++ b/sonoff/xsns_91_hre.ino @@ -131,7 +131,6 @@ void hreEvery50ms(void) static int read_counter = 0; // number of bytes in the current read static int parity_errors = 0; // Number of parity errors in current read static char buff[46]; // 8 char and a term - static char aux[46]; // 8 char and a term static char ch; static size_t i; @@ -144,8 +143,7 @@ void hreEvery50ms(void) sync_run = 0; sync_counter = 0; hre_state = hre_syncing; - snprintf_P(log_data, sizeof(log_data), PSTR("HRE: state:syncing")); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "hre_state:hre_syncing")); break; case hre_syncing: @@ -169,40 +167,34 @@ void hreEvery50ms(void) if (sync_counter > 1000) { hre_state = hre_sleep; - snprintf_P(log_data, sizeof(log_data), PSTR("HRE: sync error")); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE D_ERROR)); } break; // Start reading the data block case hre_read: - snprintf_P(log_data, sizeof(log_data), PSTR("HRE: sync_run:%d, sync_counter:%d"), sync_run, sync_counter); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE " sync_run:%d, sync_counter:%d"), sync_run, sync_counter); read_counter = 0; parity_errors = 0; curr_start = uptime; memset(buff, 0, sizeof(buff)); hre_state = hre_reading; - snprintf_P(log_data, sizeof(log_data), PSTR("HRE: state:reading")); - AddLog(LOG_LEVEL_DEBUG); + AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "hre_state:hre_reading")); // So this is intended to fall through to the hre_reading section. // it seems that if there is much of a delay between getting the sync // bits and starting the read, the HRE won't output the message we // are looking for... case hre_reading: - //ch = hreReadChar(parity_errors); - //i = read_counter - 24; // The water usage reading starts 24 bytes into the block - //if (i>=0 && i 27) @@ -243,8 +233,8 @@ void hreShow(boolean json) { if (!hre_good) return; - - const char hre_types[] = "HRE"; + + const char *id = "HRE"; char usage[33]; char rate[33]; @@ -253,13 +243,13 @@ void hreShow(boolean json) if (json) { - snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_GNGPM, mqtt_data, hre_types, usage, rate); + ResponseAppend_P(JSON_SNS_GNGPM, id, usage, rate); #ifdef USE_WEBSERVER } else { - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_GALLONS, mqtt_data, hre_types, usage); - snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_GPM, mqtt_data, hre_types, rate); + WSContentSend_PD(HTTP_SNS_GALLONS, id, usage); + WSContentSend_PD(HTTP_SNS_GPM, id, rate); #endif // USE_WEBSERVER } } From fb81b65bbcf94f5302004a515ace2b1d4d8d3c1b Mon Sep 17 00:00:00 2001 From: Jon Little Date: Mon, 25 Mar 2019 18:33:29 -0500 Subject: [PATCH 19/81] Cleaned up debugging output --- sonoff/xsns_91_hre.ino | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/sonoff/xsns_91_hre.ino b/sonoff/xsns_91_hre.ino index c73d94338..177c40e0c 100644 --- a/sonoff/xsns_91_hre.ino +++ b/sonoff/xsns_91_hre.ino @@ -138,7 +138,7 @@ void hreEvery50ms(void) switch (hre_state) { case hre_sync: - if (uptime < 15) + if (uptime < 10) break; sync_run = 0; sync_counter = 0; @@ -148,9 +148,8 @@ void hreEvery50ms(void) case hre_syncing: // Find the header, a string of 62 '1's - // Note that on startup, this could take a a whole block (46 bytes) - // before we start seeing the header - for (int i=0; i<8; i++) + // Since each bit taks 2 ms, we just read 20 bits at a time + for (int i=0; i<20; i++) { if (hreReadBit()) sync_run++; @@ -173,7 +172,7 @@ void hreEvery50ms(void) // Start reading the data block case hre_read: - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE " sync_run:%d, sync_counter:%d"), sync_run, sync_counter); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "sync_run:%d, sync_counter:%d"), sync_run, sync_counter); read_counter = 0; parity_errors = 0; curr_start = uptime; @@ -186,15 +185,14 @@ void hreEvery50ms(void) // are looking for... case hre_reading: - //KG44?Q45484=0444444V;RB000000022;IB018435683 - // RB003119173;IB018435683 - buff[read_counter] = hreReadChar(parity_errors); + // Read two characters at a time... + buff[read_counter++] = hreReadChar(parity_errors); + buff[read_counter++] = hreReadChar(parity_errors); - read_counter++; if (read_counter == 46) { - //buff[33]='\0'; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE " pe:%d, buff:%s"), parity_errors, buff); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "pe:%d, re:%d, buff:%s"), + parity_errors, hre_read_errors, buff); if (parity_errors == 0) { float curr_usage; @@ -207,7 +205,7 @@ void hreEvery50ms(void) hre_usage = curr_usage; hre_usage_time = curr_start; hre_good = true; - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE " usage:%d, rate:%d"), int(100*hre_usage), int(100*hre_rate)); + hre_state = hre_sleep; } else @@ -224,7 +222,9 @@ void hreEvery50ms(void) AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "hre_state:hre_sleeping")); case hre_sleeping: - if (uptime - hre_usage_time > 27) + // If there isn't some delay between readings, rate calculations + // aren't as accurate. 27 seconds will give about a 30 second refresh rate + if (uptime - hre_usage_time >= 27) hre_state = hre_sync; } } @@ -236,8 +236,8 @@ void hreShow(boolean json) const char *id = "HRE"; - char usage[33]; - char rate[33]; + char usage[16]; + char rate[16]; dtostrfd(hre_usage, 2, usage); dtostrfd(hre_rate, 3, rate); From deaf1f3d5b3064b2d0c2bff27295b8f73a0f9299 Mon Sep 17 00:00:00 2001 From: Jon Little Date: Wed, 27 Mar 2019 21:30:03 -0500 Subject: [PATCH 20/81] Adding additional languages --- sonoff/language/bg-BG.h | 10 ++++++++++ sonoff/language/cs-CZ.h | 9 +++++++++ sonoff/language/de-DE.h | 9 +++++++++ sonoff/language/el-GR.h | 9 +++++++++ sonoff/language/es-AR.h | 9 +++++++++ sonoff/language/fr-FR.h | 9 +++++++++ sonoff/language/he-HE.h | 9 +++++++++ sonoff/language/hu-HU.h | 9 +++++++++ sonoff/language/it-IT.h | 9 +++++++++ sonoff/language/ko-KO.h | 9 +++++++++ sonoff/language/nl-NL.h | 9 +++++++++ sonoff/language/pl-PL.h | 9 +++++++++ sonoff/language/pt-BR.h | 9 +++++++++ sonoff/language/pt-PT.h | 9 +++++++++ sonoff/language/ru-RU.h | 9 +++++++++ sonoff/language/sk-SK.h | 9 +++++++++ sonoff/language/sv-SE.h | 9 +++++++++ sonoff/language/tr-TR.h | 9 +++++++++ sonoff/language/uk-UK.h | 9 +++++++++ sonoff/language/zh-CN.h | 9 +++++++++ sonoff/language/zh-TW.h | 9 +++++++++ 21 files changed, 190 insertions(+) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 2214634f9..7b1a41675 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Помощен топик" #define D_FALSE "Невярно" #define D_FILE "Файл" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Свободна памет" #define D_FREQUENCY "Честота" #define D_GAS "Газ" @@ -156,6 +157,7 @@ #define D_TO "към" #define D_TOGGLE "Превключване" #define D_TOPIC "Топик" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Предаване" #define D_TRUE "Вярно" #define D_TVOC "TVOC" @@ -492,6 +494,10 @@ #define D_TX20_SOUTH "Ю" #define D_TX20_WEST "З" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Няма" #define D_SENSOR_USER "Потребит." @@ -576,12 +582,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "h" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOMETER_PER_HOUR "km/h" diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index 41d4fc9de..ccbb84ed0 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Záložní topic" #define D_FALSE "Nepravda" #define D_FILE "Soubor" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Volná paměť" #define D_FREQUENCY "Kmitočet" #define D_GAS "Plyn" @@ -156,6 +157,7 @@ #define D_TO "do" #define D_TOGGLE "Přepni" #define D_TOPIC "Topic" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Odešli" #define D_TRUE "Pravda" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "J" #define D_TX20_WEST "Z" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Není" #define D_SENSOR_USER "User" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "hod" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index 0808c91c4..f670a3416 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Fallback-Topic" #define D_FALSE "falsch" #define D_FILE "Datei" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Freier Arbeitsspeicher" #define D_FREQUENCY "Frequenz" #define D_GAS "Gas" @@ -156,6 +157,7 @@ #define D_TO "zu" #define D_TOGGLE "An/Aus" #define D_TOPIC "topic" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Übertragen" #define D_TRUE "wahr" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "None" #define D_SENSOR_USER "User" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "h" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index 0e483759d..f3680d639 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Fallback Topic" #define D_FALSE "Ψευδές" #define D_FILE "Αρχείο" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Ελεύθερη μνήμη" #define D_FREQUENCY "Συχνότητα" #define D_GAS "Αέριο" @@ -156,6 +157,7 @@ #define D_TO "έως" #define D_TOGGLE "Εναλλαγή" #define D_TOPIC "Topic" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Μετάδοση" #define D_TRUE "Αληθές" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "Ν" #define D_TX20_WEST "Δ" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Κανένα" #define D_SENSOR_USER "User" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "Hr" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index baf9838bf..17511fd71 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "FallbackTopic" #define D_FALSE "Falso" #define D_FILE "Archivo" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Memoria Libre" #define D_FREQUENCY "Frecuencia" #define D_GAS "Gas" @@ -156,6 +157,7 @@ #define D_TO "a" #define D_TOGGLE "Conmutar" #define D_TOPIC "Topic" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Transmitir" #define D_TRUE "Verdadero" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "O" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Ninguno" #define D_SENSOR_USER "User" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "Hr" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 0b7d29eb7..1436cc33b 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Topic de secours" #define D_FALSE "Faux" #define D_FILE "Fichier" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Mémoire libre" #define D_FREQUENCY "Fréquence" #define D_GAS "Gaz" @@ -156,6 +157,7 @@ #define D_TO "à" #define D_TOGGLE "Inverser" #define D_TOPIC "Topic" // Keep MQTT keyword +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Transmettre" #define D_TRUE "Vrai" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "O" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Aucun" #define D_SENSOR_USER "Utilisateur" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "h" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index b26529cf2..a7041304a 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "נושא לחזרה" #define D_FALSE "שגוי" #define D_FILE "קובץ" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "זכרון פנוי" #define D_FREQUENCY "תדר" #define D_GAS "גז" @@ -156,6 +157,7 @@ #define D_TO "ל" #define D_TOGGLE "מתג" #define D_TOPIC "נושא" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "עבר" #define D_TRUE "נכון" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "None" #define D_SENSOR_USER "משתמש" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "Hr" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index e8b818029..e9b51849d 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "fallback topik" #define D_FALSE "Hamis" #define D_FILE "Fájl" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Szabad memória" #define D_FREQUENCY "Frekvencia" #define D_GAS "Gáz" @@ -156,6 +157,7 @@ #define D_TO "-nak" #define D_TOGGLE "Megfordítás" #define D_TOPIC "Topic" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Továbbít" #define D_TRUE "Igaz" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "D" #define D_TX20_WEST "NY" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Nincs" #define D_SENSOR_USER "User" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "h" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index db8e58475..200d5cd3f 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Topic Riserva" #define D_FALSE "Falso" #define D_FILE "File" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Memoria Libera" #define D_FREQUENCY "Frequenza" #define D_GAS "Gas" @@ -156,6 +157,7 @@ #define D_TO "a" #define D_TOGGLE "Toggle" #define D_TOPIC "Topic" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Trasmesso" #define D_TRUE "Vero" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Nessuno" #define D_SENSOR_USER "User" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "Hr" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/language/ko-KO.h b/sonoff/language/ko-KO.h index ddfaba8d3..3bcb69ff4 100644 --- a/sonoff/language/ko-KO.h +++ b/sonoff/language/ko-KO.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Fallback Topic" #define D_FALSE "거짓" #define D_FILE "파일" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "남은 메모리" #define D_FREQUENCY "빈도" #define D_GAS "가스" @@ -156,6 +157,7 @@ #define D_TO "to" #define D_TOGGLE "전환" #define D_TOPIC "Topic" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "전송" #define D_TRUE "참" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "없음" #define D_SENSOR_USER "User" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "시" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 9e428165d..0c157ae13 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Fallback Topic" #define D_FALSE "Onwaar" #define D_FILE "Bestand" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Vrij geheugen" #define D_FREQUENCY "Frequentie" #define D_GAS "Gas" @@ -156,6 +157,7 @@ #define D_TO "naar" #define D_TOGGLE "Toggle" // Wissel, Tuimel #define D_TOPIC "Topic" // Onderwerp +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Verzend" #define D_TRUE "Waar" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Geen" #define D_SENSOR_USER "Gebruiker" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "h" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 0f13d248a..5e74d9cbb 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Zastępczy temat" #define D_FALSE "Fałsz" #define D_FILE "Plik" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Wolna pamięć" #define D_FREQUENCY "Frequency" #define D_GAS "Gas" @@ -156,6 +157,7 @@ #define D_TO "do" #define D_TOGGLE "Przełącz" #define D_TOPIC "Temat" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Wyślij" #define D_TRUE "Prawda" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Brak" #define D_SENSOR_USER "User" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "Godz" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 63efc3f1e..3ac016f27 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Tópico para retornar" #define D_FALSE "Falso" #define D_FILE "Arquivo" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Memória livre" #define D_FREQUENCY "Frequência" #define D_GAS "Gás" @@ -156,6 +157,7 @@ #define D_TO "Para" #define D_TOGGLE "Inverter" #define D_TOPIC "Tópico" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Transmitir" #define D_TRUE "Verdadeiro" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Nenhum" #define D_SENSOR_USER "User" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "H" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index 171f33d9b..0a573f166 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Tópico para retornar" #define D_FALSE "Falso" #define D_FILE "Ficheiro" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Memoria Livre" #define D_FREQUENCY "Frequency" #define D_GAS "Gás" @@ -156,6 +157,7 @@ #define D_TO "para" #define D_TOGGLE "Pressionar" #define D_TOPIC "Tópico" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Transmitir" #define D_TRUE "Verdadeiro" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Nenhum" #define D_SENSOR_USER "User" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "Hr" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index e4112953c..ee1d30540 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Топик обратной связи" #define D_FALSE "Ложно" #define D_FILE "Файл" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Свободная память" #define D_FREQUENCY "Frequency" #define D_GAS "Газ" @@ -156,6 +157,7 @@ #define D_TO "до" #define D_TOGGLE "Переключить" #define D_TOPIC "Топик" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Передать" #define D_TRUE "Истина" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "-нет-" #define D_SENSOR_USER "User" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "А" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "Ч" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h index cf99703c8..05787f7f2 100644 --- a/sonoff/language/sk-SK.h +++ b/sonoff/language/sk-SK.h @@ -75,6 +75,7 @@ #define D_COUNTER "Počítadlo" #define D_CURRENT "Prúd" // As in Voltage and Current #define D_DATA "Dáta" +#define D_FLOW_RATE "Flow rate" #define D_DARKLIGHT "Tmavý" #define D_DEBUG "Debug" #define D_DISABLED "Zablokované" @@ -156,6 +157,7 @@ #define D_TO "do" #define D_TOGGLE "Prepni" #define D_TOPIC "Topic" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Odošli" #define D_TRUE "Pravda" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "J" #define D_TX20_WEST "Z" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Žiaden" #define D_SENSOR_USER "User" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "hod" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index 6a92c1bc1..59f940e7a 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Reservämne" #define D_FALSE "Falskt" #define D_FILE "Fil" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Ledigt minne" #define D_FREQUENCY "Frekvens" #define D_GAS "Gas" @@ -156,6 +157,7 @@ #define D_TO "till" #define D_TOGGLE "Växla" #define D_TOPIC "Ämne" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Sänd" #define D_TRUE "Sant" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "V" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "Ingen" #define D_SENSOR_USER "User" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "Tim" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "ink" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index b887c89c2..99c7be5b6 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Geri İletim Topiği" #define D_FALSE "False" #define D_FILE "Dosya" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Boş Hafıza" #define D_FREQUENCY "Frekans" #define D_GAS "Gas" @@ -156,6 +157,7 @@ #define D_TO "den" #define D_TOGGLE "Geçiş Tuşu" #define D_TOPIC "Başlık" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "İletim" #define D_TRUE "True" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "None" #define D_SENSOR_USER "User" @@ -576,11 +581,15 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "A" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HOUR "Hr" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 0efdd1c94..3d9efa25a 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Топік зворотнього зв'язку" #define D_FALSE "Помилково" #define D_FILE "Файл" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "Вільна память" #define D_FREQUENCY "Частота" #define D_GAS "Газ" @@ -156,6 +157,7 @@ #define D_TO "до" #define D_TOGGLE "Перекл." #define D_TOPIC "Топік" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "Передати" #define D_TRUE "Істина" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "-відсутньо-" #define D_SENSOR_USER "User" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "А" #define D_UNIT_CENTIMETER "cм" #define D_UNIT_HERTZ "Гц" #define D_UNIT_HOUR "Г" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index 88767053b..bda9e0053 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "回退主题" #define D_FALSE "False" #define D_FILE "文件:" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "空闲内存" #define D_FREQUENCY "频率" #define D_GAS "气体" @@ -156,6 +157,7 @@ #define D_TO "to" #define D_TOGGLE "切换" #define D_TOPIC "主题" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "发送" #define D_TRUE "True" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "南" #define D_TX20_WEST "西" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "无" #define D_SENSOR_USER "User" @@ -576,11 +581,15 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "安" #define D_UNIT_CENTIMETER "厘米" #define D_UNIT_HOUR "时" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "千克" #define D_UNIT_KILOMETER_PER_HOUR "公里/时" // or "km/h" diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 11f85eef2..8273de199 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -93,6 +93,7 @@ #define D_FALLBACK_TOPIC "Fallback Topic" #define D_FALSE "False" #define D_FILE "文件:" +#define D_FLOW_RATE "Flow rate" #define D_FREE_MEMORY "可用記憶體" #define D_FREQUENCY "Frequency" #define D_GAS "氣體" @@ -156,6 +157,7 @@ #define D_TO "to" #define D_TOGGLE "切換" #define D_TOPIC "主題" +#define D_TOTAL_USAGE "Total Usage" #define D_TRANSMIT "發送" #define D_TRUE "True" #define D_TVOC "TVOC" @@ -492,6 +494,9 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" +//xsns_91_hre.ino +#define D_LOG_HRE "HRE: " + // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box #define D_SENSOR_NONE "None" #define D_SENSOR_USER "User" @@ -576,12 +581,16 @@ #define D_SENSOR_TXD "Serial Tx" #define D_SENSOR_RXD "Serial Rx" #define D_SENSOR_ROTARY "Rotary" // Suffix "1A" +#define D_SENSOR_HRE_CLOCK "HRE Clock" +#define D_SENSOR_HRE_DATA "HRE Data" // Units #define D_UNIT_AMPERE "安" #define D_UNIT_CENTIMETER "cm" #define D_UNIT_HERTZ "Hz" #define D_UNIT_HOUR "時" +#define D_UNIT_GALLONS "gal" +#define D_UNIT_GALLONS_PER_MIN "g/m" #define D_UNIT_INCREMENTS "inc" #define D_UNIT_KILOGRAM "kg" #define D_UNIT_KILOMETER_PER_HOUR "km/h" // or "km/h" From a596fc7948caaa97c2cfd38ed2bf5065fb127e8c Mon Sep 17 00:00:00 2001 From: Jon Little Date: Wed, 27 Mar 2019 21:36:32 -0500 Subject: [PATCH 21/81] renamed driver from 91 to 43 --- sonoff/language/bg-BG.h | 2 +- sonoff/language/cs-CZ.h | 2 +- sonoff/language/de-DE.h | 2 +- sonoff/language/el-GR.h | 2 +- sonoff/language/en-GB.h | 2 +- sonoff/language/es-AR.h | 2 +- sonoff/language/fr-FR.h | 2 +- sonoff/language/he-HE.h | 2 +- sonoff/language/hu-HU.h | 2 +- sonoff/language/it-IT.h | 2 +- sonoff/language/ko-KO.h | 2 +- sonoff/language/nl-NL.h | 2 +- sonoff/language/pl-PL.h | 2 +- sonoff/language/pt-BR.h | 2 +- sonoff/language/pt-PT.h | 2 +- sonoff/language/ru-RU.h | 2 +- sonoff/language/sk-SK.h | 2 +- sonoff/language/sv-SE.h | 2 +- sonoff/language/tr-TR.h | 2 +- sonoff/language/uk-UK.h | 2 +- sonoff/language/zh-CN.h | 2 +- sonoff/language/zh-TW.h | 2 +- sonoff/{xsns_91_hre.ino => xsns_43_hre.ino} | 6 +++--- 23 files changed, 25 insertions(+), 25 deletions(-) rename sonoff/{xsns_91_hre.ino => xsns_43_hre.ino} (98%) diff --git a/sonoff/language/bg-BG.h b/sonoff/language/bg-BG.h index 7b1a41675..bd71bf38c 100644 --- a/sonoff/language/bg-BG.h +++ b/sonoff/language/bg-BG.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "Ю" #define D_TX20_WEST "З" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " diff --git a/sonoff/language/cs-CZ.h b/sonoff/language/cs-CZ.h index ccbb84ed0..a0b48f627 100644 --- a/sonoff/language/cs-CZ.h +++ b/sonoff/language/cs-CZ.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "J" #define D_TX20_WEST "Z" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/de-DE.h b/sonoff/language/de-DE.h index f670a3416..dbcc39b9a 100644 --- a/sonoff/language/de-DE.h +++ b/sonoff/language/de-DE.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/el-GR.h b/sonoff/language/el-GR.h index f3680d639..20e4ed47a 100644 --- a/sonoff/language/el-GR.h +++ b/sonoff/language/el-GR.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "Ν" #define D_TX20_WEST "Δ" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/en-GB.h b/sonoff/language/en-GB.h index c1ee1ed5c..911e88d29 100644 --- a/sonoff/language/en-GB.h +++ b/sonoff/language/en-GB.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-AR.h index 17511fd71..9aca4f417 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-AR.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "O" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/fr-FR.h b/sonoff/language/fr-FR.h index 1436cc33b..36e8566f3 100644 --- a/sonoff/language/fr-FR.h +++ b/sonoff/language/fr-FR.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "O" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/he-HE.h b/sonoff/language/he-HE.h index a7041304a..c6061d05a 100644 --- a/sonoff/language/he-HE.h +++ b/sonoff/language/he-HE.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/hu-HU.h b/sonoff/language/hu-HU.h index e9b51849d..76628df43 100644 --- a/sonoff/language/hu-HU.h +++ b/sonoff/language/hu-HU.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "D" #define D_TX20_WEST "NY" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/it-IT.h b/sonoff/language/it-IT.h index 200d5cd3f..b77fc7282 100644 --- a/sonoff/language/it-IT.h +++ b/sonoff/language/it-IT.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/ko-KO.h b/sonoff/language/ko-KO.h index 3bcb69ff4..c1c5d2b43 100644 --- a/sonoff/language/ko-KO.h +++ b/sonoff/language/ko-KO.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/nl-NL.h b/sonoff/language/nl-NL.h index 0c157ae13..dc78b1445 100644 --- a/sonoff/language/nl-NL.h +++ b/sonoff/language/nl-NL.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/pl-PL.h b/sonoff/language/pl-PL.h index 5e74d9cbb..20507fc87 100644 --- a/sonoff/language/pl-PL.h +++ b/sonoff/language/pl-PL.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/pt-BR.h b/sonoff/language/pt-BR.h index 3ac016f27..433390fb6 100644 --- a/sonoff/language/pt-BR.h +++ b/sonoff/language/pt-BR.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/pt-PT.h b/sonoff/language/pt-PT.h index 0a573f166..4240008b4 100644 --- a/sonoff/language/pt-PT.h +++ b/sonoff/language/pt-PT.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/ru-RU.h b/sonoff/language/ru-RU.h index ee1d30540..2c39bb456 100644 --- a/sonoff/language/ru-RU.h +++ b/sonoff/language/ru-RU.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/sk-SK.h b/sonoff/language/sk-SK.h index 05787f7f2..a8134677b 100644 --- a/sonoff/language/sk-SK.h +++ b/sonoff/language/sk-SK.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "J" #define D_TX20_WEST "Z" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/sv-SE.h b/sonoff/language/sv-SE.h index 59f940e7a..786d5c766 100644 --- a/sonoff/language/sv-SE.h +++ b/sonoff/language/sv-SE.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "V" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/tr-TR.h b/sonoff/language/tr-TR.h index 99c7be5b6..59cd95023 100755 --- a/sonoff/language/tr-TR.h +++ b/sonoff/language/tr-TR.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/uk-UK.h b/sonoff/language/uk-UK.h index 3d9efa25a..4cceb18a6 100644 --- a/sonoff/language/uk-UK.h +++ b/sonoff/language/uk-UK.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/zh-CN.h b/sonoff/language/zh-CN.h index bda9e0053..9612b370a 100644 --- a/sonoff/language/zh-CN.h +++ b/sonoff/language/zh-CN.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "南" #define D_TX20_WEST "西" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/language/zh-TW.h b/sonoff/language/zh-TW.h index 8273de199..0a1f8ed03 100644 --- a/sonoff/language/zh-TW.h +++ b/sonoff/language/zh-TW.h @@ -494,7 +494,7 @@ #define D_TX20_SOUTH "S" #define D_TX20_WEST "W" -//xsns_91_hre.ino +//xsns_43_hre.ino #define D_LOG_HRE "HRE: " // sonoff_template.h - keep them as short as possible to be able to fit them in GUI drop down box diff --git a/sonoff/xsns_91_hre.ino b/sonoff/xsns_43_hre.ino similarity index 98% rename from sonoff/xsns_91_hre.ino rename to sonoff/xsns_43_hre.ino index 177c40e0c..5a25b6784 100644 --- a/sonoff/xsns_91_hre.ino +++ b/sonoff/xsns_43_hre.ino @@ -1,5 +1,5 @@ /* - xsns_09_hre.ino - Badger HR-E Water Meter Encoder interface + xsns_43_hre.ino - Badger HR-E Water Meter Encoder interface Copyright (C) 2019 Jon Little @@ -47,7 +47,7 @@ #ifdef USE_HRE -#define XSNS_91 91 +#define XSNS_43 43 enum hre_states { hre_idle, // Initial state, @@ -258,7 +258,7 @@ void hreShow(boolean json) /*********************************************************************************************\ * Interface \*********************************************************************************************/ -bool Xsns91(byte function) +bool Xsns43(byte function) { // If we don't have pins assigned give up quickly. if (pin[GPIO_HRE_CLOCK] >= 99 || pin[GPIO_HRE_DATA] >= 99) From 64ab5d95e5b22d65c586742f449f80fa81cad001 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 28 Mar 2019 11:14:09 +0100 Subject: [PATCH 22/81] Add optional support for Badger HR-E Water Meter Add optional support for Badger HR-E Water Meter (#5539) --- sonoff/_changelog.ino | 1 + sonoff/my_user_config.h | 2 ++ sonoff/sonoff_post.h | 4 ++++ 3 files changed, 7 insertions(+) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 3d9c77a9d..be64368e0 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,6 @@ /* 6.5.0.2 20190325 * Change UDP initial message handling from string to char using static memory and add debug info (#5505) + * Add optional support for Badger HR-E Water Meter (#5539) * * 6.5.0.1 20190319 * Change Web GUI sensor data collection diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index b7e0846e4..29eb632a6 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -415,6 +415,8 @@ #define USE_SM16716 // Add support for SM16716 RGB LED controller (+0k7 code) +//#define USE_HRE // Add support for Badger HR-E Water Meter (+1k4 code) + /*********************************************************************************************\ * Debug features are only supported in development branch \*********************************************************************************************/ diff --git a/sonoff/sonoff_post.h b/sonoff/sonoff_post.h index 095c7e2ac..10a466981 100644 --- a/sonoff/sonoff_post.h +++ b/sonoff/sonoff_post.h @@ -140,6 +140,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); #define USE_RF_SENSOR // Add support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) // #define USE_THEO_V2 // Add support for decoding Theo V2 sensors as documented on https://sidweb.nl using 434MHz RF sensor receiver (+1k4 code) #define USE_ALECTO_V2 // Add support for decoding Alecto V2 sensors like ACH2010, WS3000 and DKW2012 using 868MHz RF sensor receiver (+1k7 code) +#define USE_HRE // Add support for Badger HR-E Water Meter (+1k4 code) #endif // FIRMWARE_SENSORS /*********************************************************************************************\ @@ -197,6 +198,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer #undef USE_RC_SWITCH // Disable support for RF transceiver using library RcSwitch #undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) +#undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code) #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code #endif // FIRMWARE_CLASSIC @@ -326,6 +328,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer #undef USE_RC_SWITCH // Disable support for RF transceiver using library RcSwitch #undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) +#undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code) #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code #endif // FIRMWARE_BASIC @@ -391,6 +394,7 @@ void KNX_CB_Action(message_t const &msg, void *arg); #undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer #undef USE_RC_SWITCH // Disable support for RF transceiver using library RcSwitch #undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code) +#undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code) #undef DEBUG_THEO // Disable debug code #undef USE_DEBUG_DRIVER // Disable debug code #endif // FIRMWARE_MINIMAL From e631d49d0fdd244f3fe21cebce08bca8ea0ede47 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 28 Mar 2019 11:25:38 +0100 Subject: [PATCH 23/81] Housekeeping Housekeeping --- RELEASENOTES.md | 1 + sonoff/support_features.ino | 8 +++++--- tools/decode-status.py | 6 +++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index 4485d3083..c3e3afd4b 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -194,6 +194,7 @@ Core version **2.4.2** binaries can be found at http://thehackbox.org/tasmota/re | USE_RC_SWITCH | - | - | - | x | x | x | x | | USE_RF_SENSOR | - | - | - | - | - | x | - | AlectoV2 only | USE_SM16716 | - | x | x | x | x | x | x | +| USE_HRE | - | - | - | - | - | x | - | | USE_DISPLAY | - | - | - | - | - | - | x | | USE_DISPLAY_LCD | - | - | - | - | - | - | x | | USE_DISPLAY_SSD1306 | - | - | - | - | - | - | x | diff --git a/sonoff/support_features.ino b/sonoff/support_features.ino index f5229e81f..bde88738e 100644 --- a/sonoff/support_features.ino +++ b/sonoff/support_features.ino @@ -382,12 +382,14 @@ void GetFeatures(void) feature_sns2 |= 0x00100000; // xsns_40_pn532.ino #endif #ifdef USE_MAX44009 - feature_sns2 |= 0x00200000; + feature_sns2 |= 0x00200000; // xsns_41_max44009.ino #endif #ifdef USE_SCD30 - feature_sns2 |= 0x00400000; + feature_sns2 |= 0x00400000; // xsns_42_scd30.ino +#endif +#ifdef USE_HRE + feature_sns2 |= 0x00800000; // xsns_43_hre.ino #endif -// feature_sns2 |= 0x00800000; // feature_sns2 |= 0x01000000; // feature_sns2 |= 0x02000000; // feature_sns2 |= 0x04000000; diff --git a/tools/decode-status.py b/tools/decode-status.py index dd90d1669..ca8a35ed4 100755 --- a/tools/decode-status.py +++ b/tools/decode-status.py @@ -89,7 +89,7 @@ a_setoption = [[ "Tuya dimmer device id", "(not used) mDNS delayed start (Sec)", "Boot loop retry offset (0 = disable)", - "", + "RGBWW remap", "","","","","","", "","","","","","", ],[ @@ -105,7 +105,7 @@ a_setoption = [[ "Change state topic from tele/STATE to stat/RESULT", "Enable normal sleep instead of dynamic sleep", "Force local operation when button/switch topic is set", - "Force no pull-up", + "Do not use retain flag on HOLD messages", "","","", "","","","", "","","","", @@ -146,7 +146,7 @@ a_features = [[ "USE_MCP39F501","USE_PZEM_AC","USE_DS3231","USE_HX711", "USE_PZEM_DC","USE_TX20_WIND_SENSOR","USE_MGC3130","USE_RF_SENSOR", "USE_THEO_V2","USE_ALECTO_V2","USE_AZ7798","USE_MAX31855", - "USE_PN532_I2C","USE_MAX44009","","", + "USE_PN532_I2C","USE_MAX44009","USE_SCD30","USE_HRE", "","","","", "","","",""]] From e8e5d1c03c2f51432199064e2325da41233d8ab1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 28 Mar 2019 12:06:48 +0100 Subject: [PATCH 24/81] 6.5.0.3 Add command Sensor20 6.5.0.3 20190328 * Add command Sensor20 1..255 to change Nova Fitness SDS01 working period in minutes (#5452) --- sonoff/_changelog.ino | 5 ++++- sonoff/settings.h | 3 ++- sonoff/settings.ino | 5 +++++ sonoff/sonoff_version.h | 2 +- sonoff/xsns_20_novasds.ino | 28 +++++++++++++++++++++++----- sonoff/xsns_43_hre.ino | 33 ++++++++++++++++----------------- 6 files changed, 51 insertions(+), 25 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index be64368e0..c15f33aff 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.5.0.2 20190325 +/* 6.5.0.3 20190328 + * Add command Sensor20 1..255 to change Nova Fitness SDS01 working period in minutes (#5452) + * + * 6.5.0.2 20190325 * Change UDP initial message handling from string to char using static memory and add debug info (#5505) * Add optional support for Badger HR-E Water Meter (#5539) * diff --git a/sonoff/settings.h b/sonoff/settings.h index 5a7827365..f7eed3f11 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -330,8 +330,9 @@ struct SYSCFG { uint8_t rgbwwTable[5]; // 71A uint8_t user_template_base; // 71F mytmplt user_template; // 720 29 bytes + uint8_t novasds_period; // 73D - uint8_t free_73D[87]; // 73D + uint8_t free_73D[86]; // 73E uint32_t drivers[3]; // 794 uint32_t monitors; // 7A0 diff --git a/sonoff/settings.ino b/sonoff/settings.ino index ca8cd1b3a..1e570a96b 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -815,6 +815,8 @@ void SettingsDefaultSet2(void) Settings.rgbwwTable[j] = 255; } + Settings.novasds_period = WORKING_PERIOD; + memset(&Settings.drivers, 0xFF, 32); // Enable all possible monitors, displays, drivers and sensors } @@ -1055,6 +1057,9 @@ void SettingsDelta(void) if (Settings.version < 0x06040113) { Settings.param[P_RGB_REMAP] = RGB_REMAP_RGBW; } + if (Settings.version < 0x06050003) { + Settings.novasds_period = WORKING_PERIOD; + } Settings.version = VERSION; SettingsSave(1); diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 66b50129c..ac84738ec 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,7 +20,7 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06050002 +#define VERSION 0x06050003 #define D_PROGRAMNAME "Sonoff-Tasmota" #define D_AUTHOR "Theo Arends" diff --git a/sonoff/xsns_20_novasds.ino b/sonoff/xsns_20_novasds.ino index 8b8d6ef52..e9d955af3 100644 --- a/sonoff/xsns_20_novasds.ino +++ b/sonoff/xsns_20_novasds.ino @@ -47,13 +47,11 @@ #define NOVA_SDS_DEVICE_ID 0xFFFF // NodaSDS all sensor response #endif - TasmotaSerial *NovaSdsSerial; uint8_t novasds_type = 1; uint8_t novasds_valid = 0; - struct sds011data { uint16_t pm100; uint16_t pm25; @@ -126,9 +124,9 @@ bool NovaSdsCommand(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint16_t sensor void NovaSdsSetWorkPeriod(void) { // set sensor working period - NovaSdsCommand(NOVA_SDS_WORKING_PERIOD, NOVA_SDS_SET_MODE, WORKING_PERIOD, NOVA_SDS_DEVICE_ID, nullptr); + NovaSdsCommand(NOVA_SDS_WORKING_PERIOD, NOVA_SDS_SET_MODE, Settings.novasds_period, NOVA_SDS_DEVICE_ID, nullptr); // set sensor report only on query - NovaSdsCommand(NOVA_SDS_REPORTING_MODE, NOVA_SDS_SET_MODE, NOVA_SDS_REPORT_QUERY, NOVA_SDS_DEVICE_ID, nullptr); + NovaSdsCommand(NOVA_SDS_REPORTING_MODE, NOVA_SDS_SET_MODE, NOVA_SDS_REPORT_QUERY, NOVA_SDS_DEVICE_ID, nullptr); } bool NovaSdsReadData(void) @@ -162,7 +160,22 @@ void NovaSdsSecond(void) // Every second } } -/*********************************************************************************************/ +/*********************************************************************************************\ + * Command Sensor20 + * + * 1 .. 255 - Set working period in minutes +\*********************************************************************************************/ + +bool NovaSdsCommandSensor(void) +{ + if ((XdrvMailbox.payload > 0) && (XdrvMailbox.payload < 256)) { + Settings.novasds_period = XdrvMailbox.payload; + NovaSdsSetWorkPeriod(); + } + Response_P(S_JSON_SENSOR_INDEX_NVALUE, XSNS_20, Settings.novasds_period); + + return true; +} void NovaSdsInit(void) { @@ -226,6 +239,11 @@ bool Xsns20(uint8_t function) case FUNC_EVERY_SECOND: NovaSdsSecond(); break; + case FUNC_COMMAND_SENSOR: + if (XSNS_20 == XdrvMailbox.index) { + result = NovaSdsCommandSensor(); + } + break; case FUNC_JSON_APPEND: NovaSdsShow(1); break; diff --git a/sonoff/xsns_43_hre.ino b/sonoff/xsns_43_hre.ino index 5a25b6784..08181559f 100644 --- a/sonoff/xsns_43_hre.ino +++ b/sonoff/xsns_43_hre.ino @@ -17,6 +17,7 @@ along with this program. If not, see . */ +#ifdef USE_HRE /*********************************************************************************************\ * HR-E LCD Water meter register interface * @@ -27,26 +28,24 @@ * KG44?Q45484=0444444V;RB000000022;IB018435683 * where the RB...; is the miligalons used * - * Note that this sensor takes a _long_ time to read. 62 bits * 4 ms/bit for the + * Note that this sensor takes a _long_ time to read. 62 bits * 4 ms/bit for the * sync sequence plus 46 bytes * 40 ms/byte = 2088 ms minimum. If we aren't alligned * to the sync sequence, it could be almost twice that. * To keep from bogging the kernel down, we read 8 bits at a time on the 50 ms callback. * It will take seconds to discover if the device is there. * * In lieu of an actual schematic to describe the electrical interface, here is a description: - * + * * hre_clock_pin: drives the power/clock for the water meter through a 1k resister to * the base of a pnp transistor * hre_data_pin: is the data and has a 1 k pulldown - * + * * The pnp transitor has the collector connected to the power/clock and is pulled up * to +5 via a 1 k resistor. * The emitter is connected to ground - * + * \*********************************************************************************************/ -#ifdef USE_HRE - #define XSNS_43 43 enum hre_states { @@ -110,14 +109,14 @@ void hreInit(void) { hre_read_errors = 0; hre_good = false; - + pinMode(pin[GPIO_HRE_CLOCK], OUTPUT); pinMode(pin[GPIO_HRE_DATA], INPUT); // Note that the level shifter inverts this line and we want to leave it // high when not being read. digitalWrite(pin[GPIO_HRE_CLOCK], LOW); - + hre_state = hre_sync; } @@ -134,7 +133,7 @@ void hreEvery50ms(void) static char ch; static size_t i; - + switch (hre_state) { case hre_sync: @@ -145,7 +144,7 @@ void hreEvery50ms(void) hre_state = hre_syncing; AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "hre_state:hre_syncing")); break; - + case hre_syncing: // Find the header, a string of 62 '1's // Since each bit taks 2 ms, we just read 20 bits at a time @@ -183,12 +182,12 @@ void hreEvery50ms(void) // it seems that if there is much of a delay between getting the sync // bits and starting the read, the HRE won't output the message we // are looking for... - + case hre_reading: // Read two characters at a time... buff[read_counter++] = hreReadChar(parity_errors); buff[read_counter++] = hreReadChar(parity_errors); - + if (read_counter == 46) { AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_HRE "pe:%d, re:%d, buff:%s"), @@ -205,7 +204,7 @@ void hreEvery50ms(void) hre_usage = curr_usage; hre_usage_time = curr_start; hre_good = true; - + hre_state = hre_sleep; } else @@ -215,7 +214,7 @@ void hreEvery50ms(void) } } break; - + case hre_sleep: hre_usage_time = curr_start; hre_state = hre_sleeping; @@ -233,14 +232,14 @@ void hreShow(boolean json) { if (!hre_good) return; - + const char *id = "HRE"; char usage[16]; char rate[16]; dtostrfd(hre_usage, 2, usage); dtostrfd(hre_rate, 3, rate); - + if (json) { ResponseAppend_P(JSON_SNS_GNGPM, id, usage, rate); @@ -263,7 +262,7 @@ bool Xsns43(byte function) // If we don't have pins assigned give up quickly. if (pin[GPIO_HRE_CLOCK] >= 99 || pin[GPIO_HRE_DATA] >= 99) return false; - + switch (function) { case FUNC_INIT: From e19ba70c7ff42565a02165c7f1fef1f9aa3d8f88 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 28 Mar 2019 14:39:12 +0100 Subject: [PATCH 25/81] Fix exception due to UDP packet memory flooding (#5540) Fix exception due to UDP packet memory flooding (#5540) --- sonoff/xplg_wemohue.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xplg_wemohue.ino b/sonoff/xplg_wemohue.ino index e3351fbe4..51e51f84b 100644 --- a/sonoff/xplg_wemohue.ino +++ b/sonoff/xplg_wemohue.ino @@ -222,7 +222,7 @@ bool UdpConnect(void) void PollUdp(void) { - if (udp_connected && !udp_response_mutex && devices_present) { + if (udp_connected) { if (PortUdp.parsePacket()) { char packet_buffer[UDP_BUFFER_SIZE]; // buffer to hold incoming UDP/SSDP packet @@ -232,7 +232,7 @@ void PollUdp(void) AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: Packet (%d)"), len); // AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("\n%s"), packet_buffer); - if (strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr) { + if ((strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr) && !udp_response_mutex && devices_present) { udp_response_mutex = true; udp_remote_ip = PortUdp.remoteIP(); From b8dfc6b1b5db4a021a9480101e0961ed71e283e5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 28 Mar 2019 15:29:08 +0100 Subject: [PATCH 26/81] Change order of evaluation Change order of evaluation --- sonoff/xplg_wemohue.ino | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sonoff/xplg_wemohue.ino b/sonoff/xplg_wemohue.ino index 51e51f84b..0dfcc2f5d 100644 --- a/sonoff/xplg_wemohue.ino +++ b/sonoff/xplg_wemohue.ino @@ -197,6 +197,7 @@ void HueRespondToMSearch(void) bool UdpDisconnect(void) { if (udp_connected) { + PortUdp.flush(); WiFiUDP::stopAll(); AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPNP D_MULTICAST_DISABLED)); udp_connected = false; @@ -232,7 +233,7 @@ void PollUdp(void) AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("UDP: Packet (%d)"), len); // AddLog_P2(LOG_LEVEL_DEBUG_MORE, PSTR("\n%s"), packet_buffer); - if ((strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr) && !udp_response_mutex && devices_present) { + if (devices_present && !udp_response_mutex && (strstr_P(packet_buffer, PSTR("M-SEARCH")) != nullptr)) { udp_response_mutex = true; udp_remote_ip = PortUdp.remoteIP(); From 1400a15076a6fd54274fe6d8db51b7fc66798708 Mon Sep 17 00:00:00 2001 From: Staars Date: Fri, 29 Mar 2019 09:42:50 +0100 Subject: [PATCH 27/81] always check for vars_events and mems_events --- sonoff/xdrv_10_rules.ino | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/sonoff/xdrv_10_rules.ino b/sonoff/xdrv_10_rules.ino index 2a93ee86f..d8c0cd5c0 100644 --- a/sonoff/xdrv_10_rules.ino +++ b/sonoff/xdrv_10_rules.ino @@ -486,23 +486,25 @@ void RulesEvery50ms(void) event_data[0] ='\0'; } } - else if (vars_event) { - for (uint8_t i = 0; i < MAX_RULE_VARS-1; i++) { - if (bitRead(vars_event, i)) { - bitClear(vars_event, i); - snprintf_P(json_event, sizeof(json_event), PSTR("{\"Var%d\":{\"State\":%s}}"), i+1, vars[i]); - RulesProcessEvent(json_event); - break; + else if (vars_event || mems_event){ + if (vars_event) { + for (uint8_t i = 0; i < MAX_RULE_VARS-1; i++) { + if (bitRead(vars_event, i)) { + bitClear(vars_event, i); + snprintf_P(json_event, sizeof(json_event), PSTR("{\"Var%d\":{\"State\":%s}}"), i+1, vars[i]); + RulesProcessEvent(json_event); + break; + } } } - } - else if (mems_event) { - for (uint8_t i = 0; i < MAX_RULE_MEMS-1; i++) { - if (bitRead(mems_event, i)) { - bitClear(mems_event, i); - snprintf_P(json_event, sizeof(json_event), PSTR("{\"Mem%d\":{\"State\":%s}}"), i+1, Settings.mems[i]); - RulesProcessEvent(json_event); - break; + if (mems_event) { + for (uint8_t i = 0; i < MAX_RULE_MEMS-1; i++) { + if (bitRead(mems_event, i)) { + bitClear(mems_event, i); + snprintf_P(json_event, sizeof(json_event), PSTR("{\"Mem%d\":{\"State\":%s}}"), i+1, Settings.mems[i]); + RulesProcessEvent(json_event); + break; + } } } } @@ -1275,4 +1277,4 @@ bool Xdrv10(uint8_t function) return result; } -#endif // USE_RULES +#endif // USE_RULES \ No newline at end of file From d9bd95911963188c97dfd9c1b1aae11887170fd1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 30 Mar 2019 10:02:22 +0100 Subject: [PATCH 28/81] Fix compile error (#5544) Fix compile error (#5544) --- sonoff/settings.ino | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 1e570a96b..c3e7203d7 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -61,6 +61,10 @@ #define LONGITUDE 2.294442 // [Longitude] Your location to be used with sunrise and sunset #endif +#ifndef WORKING_PERIOD +#define WORKING_PERIOD 5 // Working period of the SDS Sensor, Takes a reading every X Minutes +#endif + /*********************************************************************************************\ * RTC memory \*********************************************************************************************/ From eb9617e3f91ad1f0075b7ebd42b094825765d924 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 30 Mar 2019 13:03:45 +0100 Subject: [PATCH 29/81] Tune some functionality Tune some functionality --- sonoff/xdrv_01_webserver.ino | 2 +- sonoff/xdrv_02_mqtt.ino | 15 +++++---------- sonoff/xdrv_03_energy.ino | 6 +++--- sonoff/xdrv_08_serial_bridge.ino | 6 +++--- sonoff/xdrv_11_knx.ino | 6 +++--- sonoff/xdrv_16_tuyadimmer.ino | 6 +++--- sonoff/xdrv_18_armtronix_dimmers.ino | 6 +++--- sonoff/xdrv_19_ps16dz_dimmer.ino | 6 +++--- sonoff/xdrv_99_debug.ino | 6 +++--- sonoff/xnrg_04_mcp39f501.ino | 6 +++--- 10 files changed, 30 insertions(+), 35 deletions(-) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 48932fb0d..eb58081ee 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -2355,7 +2355,7 @@ bool Xdrv01(uint8_t function) case FUNC_LOOP: PollDnsWebserver(); #ifdef USE_EMULATION - if (Settings.flag2.emulation) PollUdp(); + if (Settings.flag2.emulation) { PollUdp(); } #endif // USE_EMULATION break; case FUNC_COMMAND: diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index b4228b11e..dda79790c 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -50,7 +50,6 @@ bool mqtt_allowed = false; // MQTT enabled and parameters valid * void MqttDisconnect() * void MqttSubscribeLib(char *topic) * bool MqttPublishLib(const char* topic, bool retained) - * void MqttLoop() \*********************************************************************************************/ #include @@ -91,11 +90,6 @@ bool MqttPublishLib(const char* topic, bool retained) return result; } -void MqttLoop(void) -{ - MqttClient.loop(); -} - /*********************************************************************************************/ #ifdef USE_DISCOVERY @@ -425,7 +419,8 @@ void MqttReconnect(void) UdpDisconnect(); #endif // USE_EMULATION - AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_ATTEMPTING_CONNECTION)); +// AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_ATTEMPTING_CONNECTION)); + AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "(%d) " D_ATTEMPTING_CONNECTION), ESP.getFreeHeap()/1024); mqtt_connected = false; mqtt_retry_counter = Settings.mqtt_retry; @@ -816,6 +811,9 @@ bool Xdrv02(uint8_t function) if (Settings.flag.mqtt_enabled) { switch (function) { + case FUNC_LOOP: + if (MqttIsConnected()) { MqttClient.loop(); } + break; #ifdef USE_WEBSERVER case FUNC_WEB_ADD_BUTTON: WSContentSend_P(HTTP_BTN_MENU_MQTT); @@ -824,9 +822,6 @@ bool Xdrv02(uint8_t function) WebServer->on("/" WEB_HANDLE_MQTT, HandleMqttConfiguration); break; #endif // USE_WEBSERVER - case FUNC_LOOP: - if (!global_state.mqtt_down) { MqttLoop(); } - break; case FUNC_COMMAND: result = MqttCommand(); break; diff --git a/sonoff/xdrv_03_energy.ino b/sonoff/xdrv_03_energy.ino index 69d93b244..c1c65eafe 100644 --- a/sonoff/xdrv_03_energy.ino +++ b/sonoff/xdrv_03_energy.ino @@ -689,15 +689,15 @@ bool Xdrv03(uint8_t function) } else if (energy_flg) { switch (function) { + case FUNC_LOOP: + XnrgCall(FUNC_LOOP); + break; case FUNC_COMMAND: result = EnergyCommand(); break; case FUNC_SET_POWER: EnergySetPowerSteadyCounter(); break; - case FUNC_LOOP: - XnrgCall(FUNC_LOOP); - break; case FUNC_SERIAL: result = XnrgCall(FUNC_SERIAL); break; diff --git a/sonoff/xdrv_08_serial_bridge.ino b/sonoff/xdrv_08_serial_bridge.ino index e9f8294ca..fbad30683 100644 --- a/sonoff/xdrv_08_serial_bridge.ino +++ b/sonoff/xdrv_08_serial_bridge.ino @@ -172,12 +172,12 @@ bool Xdrv08(uint8_t function) if (serial_bridge_active) { switch (function) { - case FUNC_PRE_INIT: - SerialBridgeInit(); - break; case FUNC_LOOP: if (SerialBridgeSerial) { SerialBridgeInput(); } break; + case FUNC_PRE_INIT: + SerialBridgeInit(); + break; case FUNC_COMMAND: result = SerialBridgeCommand(); break; diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index b92ed1c7b..c4111bae3 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -1223,6 +1223,9 @@ bool Xdrv11(uint8_t function) { bool result = false; switch (function) { + case FUNC_LOOP: + if (!global_state.wifi_down) { knx.loop(); } // Process knx events + break; case FUNC_PRE_INIT: KNX_INIT(); break; @@ -1236,9 +1239,6 @@ bool Xdrv11(uint8_t function) break; #endif // USE_KNX_WEB_MENU #endif // USE_WEBSERVER - case FUNC_LOOP: - if (!global_state.wifi_down) { knx.loop(); } // Process knx events - break; case FUNC_EVERY_50_MSECOND: if (toggle_inhibit) { toggle_inhibit--; diff --git a/sonoff/xdrv_16_tuyadimmer.ino b/sonoff/xdrv_16_tuyadimmer.ino index f9b3665e4..d43e6397e 100644 --- a/sonoff/xdrv_16_tuyadimmer.ino +++ b/sonoff/xdrv_16_tuyadimmer.ino @@ -393,15 +393,15 @@ bool Xdrv16(uint8_t function) if (TUYA_DIMMER == my_module_type) { switch (function) { + case FUNC_LOOP: + if (TuyaSerial) { TuyaSerialInput(); } + break; case FUNC_MODULE_INIT: result = TuyaModuleSelected(); break; case FUNC_INIT: TuyaInit(); break; - case FUNC_LOOP: - if (TuyaSerial) { TuyaSerialInput(); } - break; case FUNC_SET_DEVICE_POWER: result = TuyaSetPower(); break; diff --git a/sonoff/xdrv_18_armtronix_dimmers.ino b/sonoff/xdrv_18_armtronix_dimmers.ino index 30af12ce7..79645bdf9 100644 --- a/sonoff/xdrv_18_armtronix_dimmers.ino +++ b/sonoff/xdrv_18_armtronix_dimmers.ino @@ -170,15 +170,15 @@ bool Xdrv18(uint8_t function) if (ARMTRONIX_DIMMERS == my_module_type) { switch (function) { + case FUNC_LOOP: + if (ArmtronixSerial) { ArmtronixSerialInput(); } + break; case FUNC_MODULE_INIT: result = ArmtronixModuleSelected(); break; case FUNC_INIT: ArmtronixInit(); break; - case FUNC_LOOP: - if (ArmtronixSerial) { ArmtronixSerialInput(); } - break; case FUNC_EVERY_SECOND: if (ArmtronixSerial) { if (armtronix_wifi_state!=WifiState()) { ArmtronixSetWifiLed(); } diff --git a/sonoff/xdrv_19_ps16dz_dimmer.ino b/sonoff/xdrv_19_ps16dz_dimmer.ino index ab58b6d9d..bcca6b0be 100644 --- a/sonoff/xdrv_19_ps16dz_dimmer.ino +++ b/sonoff/xdrv_19_ps16dz_dimmer.ino @@ -223,15 +223,15 @@ bool Xdrv19(uint8_t function) if (PS_16_DZ == my_module_type) { switch (function) { + case FUNC_LOOP: + if (PS16DZSerial) { PS16DZSerialInput(); } + break; case FUNC_MODULE_INIT: result = PS16DZModuleSelected(); break; case FUNC_INIT: PS16DZInit(); break; - case FUNC_LOOP: - if (PS16DZSerial) { PS16DZSerialInput(); } - break; case FUNC_SET_DEVICE_POWER: result = PS16DZSetPower(); break; diff --git a/sonoff/xdrv_99_debug.ino b/sonoff/xdrv_99_debug.ino index 08a73d4da..e3e90a398 100644 --- a/sonoff/xdrv_99_debug.ino +++ b/sonoff/xdrv_99_debug.ino @@ -497,12 +497,12 @@ bool Xdrv99(uint8_t function) bool result = false; switch (function) { - case FUNC_PRE_INIT: - CPU_last_millis = millis(); - break; case FUNC_LOOP: CpuLoadLoop(); break; + case FUNC_PRE_INIT: + CPU_last_millis = millis(); + break; case FUNC_COMMAND: result = DebugCommand(); break; diff --git a/sonoff/xnrg_04_mcp39f501.ino b/sonoff/xnrg_04_mcp39f501.ino index 5d6adec33..5441a45ca 100644 --- a/sonoff/xnrg_04_mcp39f501.ino +++ b/sonoff/xnrg_04_mcp39f501.ino @@ -652,12 +652,12 @@ int Xnrg04(uint8_t function) } else if (XNRG_04 == energy_flg) { switch (function) { - case FUNC_INIT: - McpSnsInit(); - break; case FUNC_LOOP: if (McpSerial) { McpSerialInput(); } break; + case FUNC_INIT: + McpSnsInit(); + break; case FUNC_EVERY_SECOND: if (McpSerial) { McpEverySecond(); } break; From 2aad0567bfc0352ef355129c960c522eb40be099 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 30 Mar 2019 16:29:27 +0100 Subject: [PATCH 30/81] Change some defines to const Change some defines to const --- sonoff/_changelog.ino | 1 + sonoff/sonoff.h | 190 ++++++++++++++++++------------------- sonoff/sonoff.ino | 13 +-- sonoff/support_rtc.ino | 9 +- sonoff/xdrv_02_mqtt.ino | 2 +- sonoff/xdrv_13_display.ino | 2 +- 6 files changed, 110 insertions(+), 107 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index c15f33aff..6f40ca4ae 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,5 +1,6 @@ /* 6.5.0.3 20190328 * Add command Sensor20 1..255 to change Nova Fitness SDS01 working period in minutes (#5452) + * Change some defines to const * * 6.5.0.2 20190325 * Change UDP initial message handling from string to char using static memory and add debug info (#5505) diff --git a/sonoff/sonoff.h b/sonoff/sonoff.h index 635a1017a..cd1659388 100644 --- a/sonoff/sonoff.h +++ b/sonoff/sonoff.h @@ -42,109 +42,109 @@ \*********************************************************************************************/ typedef unsigned long power_t; // Power (Relay) type -#define POWER_MASK 0xffffffffUL // Power (Relay) full mask +const uint32_t POWER_MASK = 0xffffffffUL; // Power (Relay) full mask + +/*********************************************************************************************\ + * Constants +\*********************************************************************************************/ + +// Changes to the following MAX_ defines will impact settings layout +const uint8_t MAX_SWITCHES = 8; // Max number of switches +const uint8_t MAX_RELAYS = 8; // Max number of relays +const uint8_t MAX_INTERLOCKS = 4; // Max number of interlock groups (MAX_RELAYS / 2) +const uint8_t MAX_LEDS = 4; // Max number of leds +const uint8_t MAX_KEYS = 4; // Max number of keys or buttons +const uint8_t MAX_PWMS = 5; // Max number of PWM channels +const uint8_t MAX_COUNTERS = 4; // Max number of counter sensors +const uint8_t MAX_TIMERS = 16; // Max number of Timers +const uint8_t MAX_PULSETIMERS = 8; // Max number of supported pulse timers +const uint8_t MAX_FRIENDLYNAMES = 4; // Max number of Friendly names +const uint8_t MAX_DOMOTICZ_IDX = 4; // Max number of Domoticz device, key and switch indices +const uint8_t MAX_DOMOTICZ_SNS_IDX = 12; // Max number of Domoticz sensors indices +const uint8_t MAX_KNX_GA = 10; // Max number of KNX Group Addresses to read that can be set +const uint8_t MAX_KNX_CB = 10; // Max number of KNX Group Addresses to write that can be set +const uint8_t MAX_XNRG_DRIVERS = 32; // Max number of allowed energy drivers +const uint8_t MAX_XDSP_DRIVERS = 32; // Max number of allowed display drivers +const uint8_t MAX_XDRV_DRIVERS = 96; // Max number of allowed driver drivers +const uint8_t MAX_XSNS_DRIVERS = 96; // Max number of allowed sensor drivers +const uint8_t MAX_RULE_MEMS = 5; // Max number of saved vars +const uint8_t MAX_RULE_SETS = 3; // Max number of rule sets of size 512 characters +const uint16_t MAX_RULE_SIZE = 512; // Max number of characters in rules + +const uint8_t MAX_FAN_SPEED = 4; // Max number of iFan02 fan speeds (0 .. 3) + +const char MQTT_TOKEN_PREFIX[] PROGMEM = "%prefix%"; // To be substituted by mqtt_prefix[x] +const char MQTT_TOKEN_TOPIC[] PROGMEM = "%topic%"; // To be substituted by mqtt_topic, mqtt_grptopic, mqtt_buttontopic, mqtt_switchtopic +const char WIFI_HOSTNAME[] = "%s-%04d"; // Expands to - + +const uint8_t CONFIG_FILE_SIGN = 0xA5; // Configuration file signature +const uint8_t CONFIG_FILE_XOR = 0x5A; // Configuration file xor (0 = No Xor) + +const uint32_t HLW_PREF_PULSE = 12530; // was 4975us = 201Hz = 1000W +const uint32_t HLW_UREF_PULSE = 1950; // was 1666us = 600Hz = 220V +const uint32_t HLW_IREF_PULSE = 3500; // was 1666us = 600Hz = 4.545A + +const uint8_t MQTT_RETRY_SECS = 10; // Minimum seconds to retry MQTT connection +const uint32_t GLOBAL_VALUES_VALID = 300; // Max number of seconds to keep last received values +const power_t APP_POWER = 0; // Default saved power state Off +const uint16_t WS2812_MAX_LEDS = 512; // Max number of LEDs + +const uint32_t PWM_RANGE = 1023; // 255..1023 needs to be devisible by 256 +//const uint16_t PWM_FREQ = 1000; // 100..1000 Hz led refresh +//const uint16_t PWM_FREQ = 910; // 100..1000 Hz led refresh (iTead value) +const uint16_t PWM_FREQ = 880; // 100..1000 Hz led refresh (BN-SZ01 value) +const uint16_t PWM_MAX = 4000; // [PWM_MAX] Maximum frequency - Default: 4000 +const uint16_t PWM_MIN = 100; // [PWM_MIN] Minimum frequency - Default: 100 + // For Dimmers use double of your mains AC frequecy (100 for 50Hz and 120 for 60Hz) + // For Controlling Servos use 50 and also set PWM_FREQ as 50 (DO NOT USE THESE VALUES FOR DIMMERS) +//#define PWM_LIGHTSCHEME0_IGNORE_SLEEP // Do not change sleep value for LightAnimate() scheme 0 + +const uint8_t DEFAULT_POWER_DELTA = 80; // Power change percentage +const uint16_t MAX_POWER_HOLD = 10; // Time in SECONDS to allow max agreed power +const uint16_t MAX_POWER_WINDOW = 30; // Time in SECONDS to disable allow max agreed power +const uint16_t SAFE_POWER_HOLD = 10; // Time in SECONDS to allow max unit safe power +const uint16_t SAFE_POWER_WINDOW = 30; // Time in MINUTES to disable allow max unit safe power +const uint8_t MAX_POWER_RETRY = 5; // Retry count allowing agreed power limit overflow + +const uint8_t STATES = 20; // Number of states per second using 50 mSec interval +const uint8_t IMMINENT_RESET_FACTOR = 10; // Factor to extent button hold time for imminent Reset to default 40 seconds using KEY_HOLD_TIME of 40 +const uint32_t BOOT_LOOP_TIME = 10; // Number of seconds to stop detecting boot loops +const uint16_t SYSLOG_TIMER = 600; // Seconds to restore syslog_level +const uint16_t SERIALLOG_TIMER = 600; // Seconds to disable SerialLog +const uint8_t OTA_ATTEMPTS = 5; // Number of times to try fetching the new firmware + +const uint16_t INPUT_BUFFER_SIZE = 520; // Max number of characters in (serial and http) command buffer +const uint16_t CMDSZ = 24; // Max number of characters in command +const uint16_t TOPSZ = 100; // Max number of characters in topic string +const uint16_t LOGSZ = 520; // Max number of characters in log +const uint16_t MIN_MESSZ = 893; // Min number of characters in MQTT message + +const uint8_t SENSOR_MAX_MISS = 5; // Max number of missed sensor reads before deciding it's offline + +#ifdef USE_MQTT_TLS + const uint16_t WEB_LOG_SIZE = 2000; // Max number of characters in weblog +#else + const uint16_t WEB_LOG_SIZE = 4000; // Max number of characters in weblog +#endif + +const uint8_t MAX_BACKLOG = 30; // Max number of commands in backlog +const uint32_t MIN_BACKLOG_DELAY = 2; // Minimal backlog delay in 0.1 seconds + +const uint32_t SOFT_BAUDRATE = 9600; // Default software serial baudrate +const uint32_t APP_BAUDRATE = 115200; // Default serial baudrate +const uint32_t SERIAL_POLLING = 100; // Serial receive polling in ms +const uint8_t MAX_STATUS = 11; // Max number of status lines + +const uint32_t DRIVER_BOOT_DELAY = 1; // Number of milliseconds to retard driver cycles during boot-up time to reduce overall CPU load whilst Wifi is connecting +const uint32_t LOOP_SLEEP_DELAY = 50; // Lowest number of milliseconds to go through the main loop using delay when needed /*********************************************************************************************\ * Defines \*********************************************************************************************/ -// Changes to the following MAX_ defines will impact settings layout -#define MAX_SWITCHES 8 // Max number of switches -#define MAX_RELAYS 8 // Max number of relays -#define MAX_INTERLOCKS 4 // Max number of interlock groups (MAX_RELAYS / 2) -#define MAX_LEDS 4 // Max number of leds -#define MAX_KEYS 4 // Max number of keys or buttons -#define MAX_PWMS 5 // Max number of PWM channels -#define MAX_COUNTERS 4 // Max number of counter sensors -#define MAX_TIMERS 16 // Max number of Timers -#define MAX_PULSETIMERS 8 // Max number of supported pulse timers -#define MAX_FRIENDLYNAMES 4 // Max number of Friendly names -#define MAX_DOMOTICZ_IDX 4 // Max number of Domoticz device, key and switch indices -#define MAX_DOMOTICZ_SNS_IDX 12 // Max number of Domoticz sensors indices -#define MAX_KNX_GA 10 // Max number of KNX Group Addresses to read that can be set -#define MAX_KNX_CB 10 // Max number of KNX Group Addresses to write that can be set -#define MAX_XNRG_DRIVERS 32 // Max number of allowed energy drivers -#define MAX_XDSP_DRIVERS 32 // Max number of allowed display drivers -#define MAX_XDRV_DRIVERS 96 // Max number of allowed driver drivers -#define MAX_XSNS_DRIVERS 96 // Max number of allowed sensor drivers -#define MAX_RULE_MEMS 5 // Max number of saved vars -#define MAX_RULE_SETS 3 // Max number of rule sets of size 512 characters -#define MAX_RULE_SIZE 512 // Max number of characters in rules - -// Changes to the following defines have no impact on settings layout #define MAX_RULE_TIMERS 8 // Max number of rule timers (4 bytes / timer) #define MAX_RULE_VARS 5 // Max number of rule variables (10 bytes / variable) -#define MAX_FAN_SPEED 4 // Max number of iFan02 fan speeds (0 .. 3) - -#define MQTT_TOKEN_PREFIX "%prefix%" // To be substituted by mqtt_prefix[x] -#define MQTT_TOKEN_TOPIC "%topic%" // To be substituted by mqtt_topic, mqtt_grptopic, mqtt_buttontopic, mqtt_switchtopic -#define MQTT_TOKEN_HOSTNAME "%hostname%" // To be substituted by mqtt_topic, mqtt_grptopic, mqtt_buttontopic, mqtt_switchtopic -#define MQTT_TOKEN_ID "%id%" // To be substituted by mqtt_topic, mqtt_grptopic, mqtt_buttontopic, mqtt_switchtopic - -#define WIFI_HOSTNAME "%s-%04d" // Expands to - - -#define CONFIG_FILE_SIGN 0xA5 // Configuration file signature -#define CONFIG_FILE_XOR 0x5A // Configuration file xor (0 = No Xor) - -#define HLW_PREF_PULSE 12530 // was 4975us = 201Hz = 1000W -#define HLW_UREF_PULSE 1950 // was 1666us = 600Hz = 220V -#define HLW_IREF_PULSE 3500 // was 1666us = 600Hz = 4.545A - -#define MQTT_RETRY_SECS 10 // Minimum seconds to retry MQTT connection -#define GLOBAL_VALUES_VALID 300 // Max number of seconds to keep last received values -#define APP_POWER 0 // Default saved power state Off -#define WS2812_MAX_LEDS 512 // Max number of LEDs - -#define PWM_RANGE 1023 // 255..1023 needs to be devisible by 256 -//#define PWM_FREQ 1000 // 100..1000 Hz led refresh -//#define PWM_FREQ 910 // 100..1000 Hz led refresh (iTead value) -#define PWM_FREQ 880 // 100..1000 Hz led refresh (BN-SZ01 value) -#define PWM_MAX 4000 // [PWM_MAX] Maximum frequency - Default: 4000 -#define PWM_MIN 100 // [PWM_MIN] Minimum frequency - Default: 100 - // For Dimmers use double of your mains AC frequecy (100 for 50Hz and 120 for 60Hz) - // For Controlling Servos use 50 and also set PWM_FREQ as 50 (DO NOT USE THESE VALUES FOR DIMMERS) -//#define PWM_LIGHTSCHEME0_IGNORE_SLEEP // Do not change sleep value for LightAnimate() scheme 0 - -#define DEFAULT_POWER_DELTA 80 // Power change percentage -#define MAX_POWER_HOLD 10 // Time in SECONDS to allow max agreed power -#define MAX_POWER_WINDOW 30 // Time in SECONDS to disable allow max agreed power -#define SAFE_POWER_HOLD 10 // Time in SECONDS to allow max unit safe power -#define SAFE_POWER_WINDOW 30 // Time in MINUTES to disable allow max unit safe power -#define MAX_POWER_RETRY 5 // Retry count allowing agreed power limit overflow - -#define STATES 20 // Number of states per second using 50 mSec interval -#define IMMINENT_RESET_FACTOR 10 // Factor to extent button hold time for imminent Reset to default 40 seconds using KEY_HOLD_TIME of 40 -#define BOOT_LOOP_TIME 10 // Number of seconds to stop detecting boot loops -#define SYSLOG_TIMER 600 // Seconds to restore syslog_level -#define SERIALLOG_TIMER 600 // Seconds to disable SerialLog -#define OTA_ATTEMPTS 5 // Number of times to try fetching the new firmware - -#define INPUT_BUFFER_SIZE 520 // Max number of characters in (serial and http) command buffer -#define CMDSZ 24 // Max number of characters in command -#define TOPSZ 100 // Max number of characters in topic string -#define LOGSZ 520 // Max number of characters in log -#define MIN_MESSZ 893 // Min number of characters in MQTT message - -#define SENSOR_MAX_MISS 5 // Max number of missed sensor reads before deciding it's offline - -#ifdef USE_MQTT_TLS - #define WEB_LOG_SIZE 2000 // Max number of characters in weblog -#else - #define WEB_LOG_SIZE 4000 // Max number of characters in weblog -#endif - -#define MAX_BACKLOG 30 // Max number of commands in backlog -#define MIN_BACKLOG_DELAY 2 // Minimal backlog delay in 0.1 seconds - -#define SOFT_BAUDRATE 9600 // Default software serial baudrate -#define APP_BAUDRATE 115200 // Default serial baudrate -#define SERIAL_POLLING 100 // Serial receive polling in ms -#define MAX_STATUS 11 // Max number of status lines - -#define DRIVER_BOOT_DELAY 1 // Number of milliseconds to retard driver cycles during boot-up time to reduce overall CPU load whilst Wifi is connecting -#define LOOP_SLEEP_DELAY 50 // Lowest number of milliseconds to go through the main loop using delay when needed - #define NO_EXTRA_4K_HEAP // Allocate 4k heap for WPS in ESP8166/Arduino core v2.4.2 (was always allocated in previous versions) /* diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index bcefc9a08..e85a26af2 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -254,20 +254,21 @@ char* GetTopic_P(char *stopic, uint8_t prefix, char *topic, const char* subtopic fulltopic += F("_fb"); // cmnd/_fb } else { fulltopic = Settings.mqtt_fulltopic; - if ((0 == prefix) && (-1 == fulltopic.indexOf(F(MQTT_TOKEN_PREFIX)))) { - fulltopic += F("/" MQTT_TOKEN_PREFIX); // Need prefix for commands to handle mqtt topic loops + if ((0 == prefix) && (-1 == fulltopic.indexOf(FPSTR(MQTT_TOKEN_PREFIX)))) { + fulltopic += F("/"); + fulltopic += FPSTR(MQTT_TOKEN_PREFIX); // Need prefix for commands to handle mqtt topic loops } for (uint8_t i = 0; i < 3; i++) { if ('\0' == Settings.mqtt_prefix[i][0]) { snprintf_P(Settings.mqtt_prefix[i], sizeof(Settings.mqtt_prefix[i]), kPrefixes[i]); } } - fulltopic.replace(F(MQTT_TOKEN_PREFIX), Settings.mqtt_prefix[prefix]); - fulltopic.replace(F(MQTT_TOKEN_TOPIC), topic); - fulltopic.replace(F(MQTT_TOKEN_HOSTNAME), my_hostname); + fulltopic.replace(FPSTR(MQTT_TOKEN_PREFIX), Settings.mqtt_prefix[prefix]); + fulltopic.replace(FPSTR(MQTT_TOKEN_TOPIC), topic); + fulltopic.replace(F("%hostname%"), my_hostname); String token_id = WiFi.macAddress(); token_id.replace(":", ""); - fulltopic.replace(F(MQTT_TOKEN_ID), token_id); + fulltopic.replace(F("%id%"), token_id); } fulltopic.replace(F("#"), ""); fulltopic.replace(F("//"), "/"); diff --git a/sonoff/support_rtc.ino b/sonoff/support_rtc.ino index 5af8b49a0..fd9575b32 100644 --- a/sonoff/support_rtc.ino +++ b/sonoff/support_rtc.ino @@ -22,10 +22,11 @@ * Timezone by Jack Christensen (https://github.com/JChristensen/Timezone) \*********************************************************************************************/ -#define SECS_PER_MIN ((uint32_t)(60UL)) -#define SECS_PER_HOUR ((uint32_t)(3600UL)) -#define SECS_PER_DAY ((uint32_t)(SECS_PER_HOUR * 24UL)) -#define MINS_PER_HOUR ((uint32_t)(60UL)) +const uint32_t SECS_PER_MIN = 60UL; +const uint32_t SECS_PER_HOUR = 3600UL; +const uint32_t SECS_PER_DAY = SECS_PER_HOUR * 24UL; +const uint32_t MINS_PER_HOUR = 60UL; + #define LEAP_YEAR(Y) (((1970+Y)>0) && !((1970+Y)%4) && (((1970+Y)%100) || !((1970+Y)%400))) extern "C" { diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index dda79790c..fd58ff8bb 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -295,7 +295,7 @@ void MqttConnected(void) GetTopic_P(stopic, CMND, mqtt_topic, PSTR("#")); MqttSubscribe(stopic); - if (strstr(Settings.mqtt_fulltopic, MQTT_TOKEN_TOPIC) != nullptr) { + if (strstr_P(Settings.mqtt_fulltopic, MQTT_TOKEN_TOPIC) != nullptr) { GetTopic_P(stopic, CMND, Settings.mqtt_grptopic, PSTR("#")); MqttSubscribe(stopic); GetFallbackTopic_P(stopic, CMND, PSTR("#")); diff --git a/sonoff/xdrv_13_display.ino b/sonoff/xdrv_13_display.ino index 8a05d68f3..498cce9fc 100644 --- a/sonoff/xdrv_13_display.ino +++ b/sonoff/xdrv_13_display.ino @@ -830,7 +830,7 @@ void DisplayMqttSubscribe(void) strlcpy(stopic, Settings.mqtt_fulltopic, sizeof(stopic)); char *tp = strtok(stopic, "/"); while (tp != nullptr) { - if (!strcmp_P(tp, PSTR(MQTT_TOKEN_PREFIX))) { + if (!strcmp_P(tp, MQTT_TOKEN_PREFIX)) { break; } strncat_P(ntopic, PSTR("+/"), sizeof(ntopic) - strlen(ntopic) -1); // Add single-level wildcards From 929292f7a8967abfee35fdcf0a1a9cac07c7c8ff Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 30 Mar 2019 16:32:22 +0100 Subject: [PATCH 31/81] Update xdrv_02_mqtt.ino Restore MQTT attempting connection message --- sonoff/xdrv_02_mqtt.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index fd58ff8bb..d3c3c5446 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -419,8 +419,8 @@ void MqttReconnect(void) UdpDisconnect(); #endif // USE_EMULATION -// AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_ATTEMPTING_CONNECTION)); - AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "(%d) " D_ATTEMPTING_CONNECTION), ESP.getFreeHeap()/1024); + AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_ATTEMPTING_CONNECTION)); +// AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "(%d) " D_ATTEMPTING_CONNECTION), ESP.getFreeHeap()/1024); mqtt_connected = false; mqtt_retry_counter = Settings.mqtt_retry; From 5c1fa161ba8f7b1acddc2d4b6fd612f6d88b73de Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Sat, 30 Mar 2019 18:28:40 -0300 Subject: [PATCH 32/81] Update CONTRIBUTING.md --- CONTRIBUTING.md | 52 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7cfcdfadb..3ecb5a9bc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -56,7 +56,57 @@ The process is straight-forward. 7. All pull requests should consider updates to the documentation. 8. Pull requests that address an outstanding issue, particularly an issue deemed to be severe, should be given priority. 9. If a PR is accepted, then it should undergo review and updated based on the feedback provided, then merged. -10. Pull requests that don't meet the above will be denied and closed. +10. By submitting a PR, it is needed to use the provided PR template and check all boxes, performing the required tasks and accepting the CLA. +11. Pull requests that don't meet the above will be denied and closed. + +-------------------------------------- + +## Contributor License Agreement (CLA) + +``` +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the GPL-3.0 license; or + +(b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the GPL-3.0 license; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it) is maintained indefinitely + and may be redistributed consistent with this project or the open + source license(s) involved. +``` + +This Contributor License Agreement (CLA) was adopted on April 1st, 2019. + +The text of this license is available under the [Creative Commons Attribution-ShareAlike 3.0 Unported License](http://creativecommons.org/licenses/by-sa/3.0/). It is based on the Linux [Developer Certificate Of Origin](http://elinux.org/Developer_Certificate_Of_Origin), but is modified to explicitly use the GPL-3.0 license and not mention sign-off (due to GitHub.com keeps an historial, with your user name, of PRs' commits and all editions on PR's comments). + +To accept the CLA it is required to put a x between [ ] on `[ ] I accept the CLA` in the PR template when submitting it. The [ ] is an opt-in box, so you have to manually accept it. + +**Why a CLA ?** + +_"A Contributor Licence Agreement (CLA) is strongly recommended when accepting third party contributions to an open development project, such as an open source software project. In order to redistribute contributions, it is necessary to ensure that the project has the necessary rights to do so. A Contributor Licence Agreement is a lightweight agreement, signed by the copyright holder, that grants the necessary rights for the contribution to be redistributed as part of the project."_ [OSS Watch](http://oss-watch.ac.uk/resources/cla) + +A CLA is a legal document in which you state _you are entitled to contribute the code/documentation/translation to the project_ you’re contributing to and that _you are willing to have it used in distributions and derivative works_. This means that should there be any kind of legal issue in the future as to the origins and ownership of any particular piece of code, then that project has the necessary forms on file from the contributor(s) saying they were permitted to make this contribution. + +CLA is a safety because it also ensures that once you have provided a contribution, you cannot try to withdraw permission for its use at a later date. People can therefore use that software, confident that they will not be asked to stop using pieces of the code at a later date. + +A __license__ grants "outbound" rights to the user of project. + +A __CLA__ enables a contributor to grant "inbound" rights to a project. + + + + From 34d5cbf20f4cd2f8a826f59bc24d34b7d844e24b Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Sat, 30 Mar 2019 18:42:56 -0300 Subject: [PATCH 33/81] Update PULL_REQUEST_TEMPLATE.md --- .github/PULL_REQUEST_TEMPLATE.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index aea7cd816..a4a459a18 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -3,8 +3,9 @@ **Related issue (if applicable):** fixes # ## Checklist: - - [ ] The pull request is done against the dev branch - - [ ] Only relevant files were touched (Also beware if your editor has auto-formatting feature enabled) + - [ ] The pull request is done against the latest dev branch + - [ ] Only relevant files were touched (Also remember to update _changelog.ino_ file) - [ ] Only one feature/fix was added per PR. - [ ] The code change is tested and works. - [ ] The code change pass travis tests. **Your PR cannot be merged unless tests pass** + - [ ] I accept the [CLA](https://github.com/arendst/Sonoff-Tasmota/blob/development/CONTRIBUTING.md#contributor-license-agreement-cla). From f7c30250c10a49bcf6b20e501a7df6afb3e24703 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 31 Mar 2019 11:59:04 +0200 Subject: [PATCH 34/81] Change some more defines to const Change some more defines to const --- sonoff/settings.h | 4 ++-- sonoff/settings.ino | 8 ++++---- sonoff/sonoff_version.h | 7 +------ sonoff/support.ino | 4 ++-- sonoff/support_switch.ino | 2 +- sonoff/support_wifi.ino | 10 +++++----- sonoff/xdrv_01_webserver.ino | 16 ++++++++-------- sonoff/xdrv_02_mqtt.ino | 1 - sonoff/xdrv_04_light.ino | 18 +++++++++--------- sonoff/xdrv_05_irremote.ino | 23 +++++++++++------------ sonoff/xdrv_06_snfbridge.ino | 6 +++--- sonoff/xdrv_08_serial_bridge.ino | 2 +- sonoff/xdrv_13_display.ino | 8 ++++---- 13 files changed, 51 insertions(+), 58 deletions(-) diff --git a/sonoff/settings.h b/sonoff/settings.h index f7eed3f11..07cb646d8 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -20,7 +20,7 @@ #ifndef _SETTINGS_H_ #define _SETTINGS_H_ -#define PARAM8_SIZE 18 // Number of param bytes (SetOption) +const uint8_t PARAM8_SIZE = 18; // Number of param bytes (SetOption) typedef union { // Restricted by MISRA-C Rule 18.4 but so useful... uint32_t data; // Allow bit manipulation using SetOption @@ -397,7 +397,7 @@ struct XDRVMAILBOX { char *data; } XdrvMailbox; -#define MAX_RULES_FLAG 7 // Number of bits used in RulesBitfield (tricky I know...) +const uint8_t MAX_RULES_FLAG = 7; // Number of bits used in RulesBitfield (tricky I know...) typedef union { // Restricted by MISRA-C Rule 18.4 but so useful... uint16_t data; // Allow bit manipulation struct { diff --git a/sonoff/settings.ino b/sonoff/settings.ino index c3e7203d7..dcebe4512 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -69,7 +69,7 @@ * RTC memory \*********************************************************************************************/ -#define RTC_MEM_VALID 0xA55A +const uint16_t RTC_MEM_VALID = 0xA55A; uint32_t rtc_settings_crc = 0; @@ -168,12 +168,12 @@ extern "C" { extern "C" uint32_t _SPIFFS_end; // From libraries/EEPROM/EEPROM.cpp EEPROMClass -#define SPIFFS_END ((uint32_t)&_SPIFFS_end - 0x40200000) / SPI_FLASH_SEC_SIZE +const uint32_t SPIFFS_END = ((uint32_t)&_SPIFFS_end - 0x40200000) / SPI_FLASH_SEC_SIZE; // Version 4.2 config = eeprom area -#define SETTINGS_LOCATION SPIFFS_END // No need for SPIFFS as it uses EEPROM area +const uint32_t SETTINGS_LOCATION = SPIFFS_END; // No need for SPIFFS as it uses EEPROM area // Version 5.2 allow for more flash space -#define CFG_ROTATES 8 // Number of flash sectors used (handles uploads) +const uint8_t CFG_ROTATES = 8; // Number of flash sectors used (handles uploads) /*********************************************************************************************\ * EEPROM support based on EEPROM library and tuned for Tasmota diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index ac84738ec..68c28a9d0 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,11 +20,6 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -#define VERSION 0x06050003 - -#define D_PROGRAMNAME "Sonoff-Tasmota" -#define D_AUTHOR "Theo Arends" -//#define D_WEBLINK "https://github.com/arendst/Sonoff-Tasmota" -#define D_WEBLINK "https://bit.ly/tasmota" +const uint32_t VERSION = 0x06050003; #endif // _SONOFF_VERSION_H_ diff --git a/sonoff/support.ino b/sonoff/support.ino index 07edd039a..e571e6ec1 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -28,7 +28,7 @@ uint32_t syslog_host_hash = 0; // Syslog host name hash Ticker tickerOSWatch; -#define OSWATCH_RESET_TIME 120 +const uint32_t OSWATCH_RESET_TIME = 120; static unsigned long oswatch_last_loop_time; uint8_t oswatch_blocked_loop = 0; @@ -996,7 +996,7 @@ void SetNextTimeInterval(unsigned long& timer, const unsigned long step) \*********************************************************************************************/ #ifdef USE_I2C -#define I2C_RETRY_COUNTER 3 +const uint8_t I2C_RETRY_COUNTER = 3; uint32_t i2c_buffer = 0; diff --git a/sonoff/support_switch.ino b/sonoff/support_switch.ino index 7e84149ba..3eb927388 100644 --- a/sonoff/support_switch.ino +++ b/sonoff/support_switch.ino @@ -25,7 +25,7 @@ * Inspired by (https://github.com/OLIMEX/olimex-iot-firmware-esp8266/blob/master/olimex/user/user_switch2.c) \*********************************************************************************************/ -#define SWITCH_PROBE_INTERVAL 10 // Time in milliseconds between switch input probe +const uint8_t SWITCH_PROBE_INTERVAL = 10; // Time in milliseconds between switch input probe #include diff --git a/sonoff/support_wifi.ino b/sonoff/support_wifi.ino index 2c7299991..445c14c0b 100644 --- a/sonoff/support_wifi.ino +++ b/sonoff/support_wifi.ino @@ -22,15 +22,15 @@ \*********************************************************************************************/ #ifndef WIFI_RSSI_THRESHOLD -#define WIFI_RSSI_THRESHOLD 10 // Difference in dB between current network and scanned network +#define WIFI_RSSI_THRESHOLD 10 // Difference in dB between current network and scanned network #endif #ifndef WIFI_RESCAN_MINUTES -#define WIFI_RESCAN_MINUTES 44 // Number of minutes between wifi network rescan +#define WIFI_RESCAN_MINUTES 44 // Number of minutes between wifi network rescan #endif -#define WIFI_CONFIG_SEC 180 // seconds before restart -#define WIFI_CHECK_SEC 20 // seconds -#define WIFI_RETRY_OFFSET_SEC 20 // seconds +const uint8_t WIFI_CONFIG_SEC = 180; // seconds before restart +const uint8_t WIFI_CHECK_SEC = 20; // seconds +const uint8_t WIFI_RETRY_OFFSET_SEC = 20; // seconds /* // This worked for 2_5_0_BETA2 but fails since then. Waiting for a solution from core team (#4952) diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index eb58081ee..44be997a6 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -27,15 +27,15 @@ #define XDRV_01 1 -#define CHUNKED_BUFFER_SIZE 400 // Chunk buffer size - #ifndef WIFI_SOFT_AP_CHANNEL -#define WIFI_SOFT_AP_CHANNEL 1 // Soft Access Point Channel number between 1 and 11 as used by SmartConfig web GUI +#define WIFI_SOFT_AP_CHANNEL 1 // Soft Access Point Channel number between 1 and 11 as used by SmartConfig web GUI #endif -#define HTTP_REFRESH_TIME 2345 // milliseconds -#define HTTP_RESTART_RECONNECT_TIME 9000 // milliseconds -#define HTTP_OTA_RESTART_RECONNECT_TIME 20000 // milliseconds +const uint16_t CHUNKED_BUFFER_SIZE = 400; // Chunk buffer size (should be smaller than half mqtt_date size) + +const uint16_t HTTP_REFRESH_TIME = 2345; // milliseconds +#define HTTP_RESTART_RECONNECT_TIME 9000 // milliseconds +#define HTTP_OTA_RESTART_RECONNECT_TIME 20000 // milliseconds #include #include @@ -376,7 +376,7 @@ const char HTTP_COUNTER[] PROGMEM = "
"; const char HTTP_END[] PROGMEM = - "
" + "" "" "" ""; @@ -413,7 +413,7 @@ const char kUploadErrors[] PROGMEM = #endif ; -#define DNS_PORT 53 +const uint16_t DNS_PORT = 53; enum HttpOptions {HTTP_OFF, HTTP_USER, HTTP_ADMIN, HTTP_MANAGER, HTTP_MANAGER_RESET_ONLY}; DNSServer *DnsServer; diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index d3c3c5446..5720b9a7d 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -420,7 +420,6 @@ void MqttReconnect(void) #endif // USE_EMULATION AddLog_P(LOG_LEVEL_INFO, S_LOG_MQTT, PSTR(D_ATTEMPTING_CONNECTION)); -// AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_MQTT "(%d) " D_ATTEMPTING_CONNECTION), ESP.getFreeHeap()/1024); mqtt_connected = false; mqtt_retry_counter = Settings.mqtt_retry; diff --git a/sonoff/xdrv_04_light.ino b/sonoff/xdrv_04_light.ino index 5dae14ce7..7597415d6 100644 --- a/sonoff/xdrv_04_light.ino +++ b/sonoff/xdrv_04_light.ino @@ -56,7 +56,7 @@ #define XDRV_04 4 -#define WS2812_SCHEMES 7 // Number of additional WS2812 schemes supported by xdrv_ws2812.ino +const uint8_t WS2812_SCHEMES = 7; // Number of additional WS2812 schemes supported by xdrv_ws2812.ino enum LightCommands { CMND_COLOR, CMND_COLORTEMPERATURE, CMND_DIMMER, CMND_LED, CMND_LEDTABLE, CMND_FADE, @@ -70,23 +70,23 @@ const char kLightCommands[] PROGMEM = struct LRgbColor { uint8_t R, G, B; }; -#define MAX_FIXED_COLOR 12 +const uint8_t MAX_FIXED_COLOR = 12; const LRgbColor kFixedColor[MAX_FIXED_COLOR] PROGMEM = { 255,0,0, 0,255,0, 0,0,255, 228,32,0, 0,228,32, 0,32,228, 188,64,0, 0,160,96, 160,32,240, 255,255,0, 255,0,170, 255,255,255 }; struct LWColor { uint8_t W; }; -#define MAX_FIXED_WHITE 4 +const uint8_t MAX_FIXED_WHITE = 4; const LWColor kFixedWhite[MAX_FIXED_WHITE] PROGMEM = { 0, 255, 128, 32 }; struct LCwColor { uint8_t C, W; }; -#define MAX_FIXED_COLD_WARM 4 +const uint8_t MAX_FIXED_COLD_WARM = 4; const LCwColor kFixedColdWarm[MAX_FIXED_COLD_WARM] PROGMEM = { 0,0, 255,0, 0,255, 128,128 }; -uint8_t ledTable[] = { +const uint8_t ledTable[] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, @@ -132,11 +132,11 @@ unsigned long strip_timer_counter = 0; // Bars and Gradient * Arilux LC11 Rf support stripped from RCSwitch library \*********************************************************************************************/ -#define ARILUX_RF_TIME_AVOID_DUPLICATE 1000 // Milliseconds +const uint32_t ARILUX_RF_TIME_AVOID_DUPLICATE = 1000; // Milliseconds -#define ARILUX_RF_MAX_CHANGES 51 // Pulses (sync + 2 x 24 bits) -#define ARILUX_RF_SEPARATION_LIMIT 4300 // Microseconds -#define ARILUX_RF_RECEIVE_TOLERANCE 60 // Percentage +const uint8_t ARILUX_RF_MAX_CHANGES = 51; // Pulses (sync + 2 x 24 bits) +const uint32_t ARILUX_RF_SEPARATION_LIMIT = 4300; // Microseconds +const uint32_t ARILUX_RF_RECEIVE_TOLERANCE = 60; // Percentage unsigned int arilux_rf_timings[ARILUX_RF_MAX_CHANGES]; diff --git a/sonoff/xdrv_05_irremote.ino b/sonoff/xdrv_05_irremote.ino index 7e6501142..864d77e8c 100644 --- a/sonoff/xdrv_05_irremote.ino +++ b/sonoff/xdrv_05_irremote.ino @@ -42,17 +42,17 @@ enum IrHvacVendors { VNDR_TOSHIBA, VNDR_MITSUBISHI, VNDR_LG, VNDR_FUJITSU }; const char kIrHvacVendors[] PROGMEM = "Toshiba|Mitsubishi|LG|Fujitsu" ; // HVAC TOSHIBA_ -#define HVAC_TOSHIBA_HDR_MARK 4400 -#define HVAC_TOSHIBA_HDR_SPACE 4300 -#define HVAC_TOSHIBA_BIT_MARK 543 -#define HVAC_TOSHIBA_ONE_SPACE 1623 -#define HVAC_MISTUBISHI_ZERO_SPACE 472 -#define HVAC_TOSHIBA_RPT_MARK 440 -#define HVAC_TOSHIBA_RPT_SPACE 7048 // Above original iremote limit -#define HVAC_TOSHIBA_DATALEN 9 +const uint16_t HVAC_TOSHIBA_HDR_MARK = 4400; +const uint16_t HVAC_TOSHIBA_HDR_SPACE = 4300; +const uint16_t HVAC_TOSHIBA_BIT_MARK = 543; +const uint16_t HVAC_TOSHIBA_ONE_SPACE = 1623; +const uint16_t HVAC_MISTUBISHI_ZERO_SPACE = 472; +const uint16_t HVAC_TOSHIBA_RPT_MARK = 440; +const uint16_t HVAC_TOSHIBA_RPT_SPACE = 7048; // Above original iremote limit +const uint8_t HVAC_TOSHIBA_DATALEN = 9; // HVAC LG -#define HVAC_LG_DATALEN 7 +const uint8_t HVAC_LG_DATALEN = 7; IRMitsubishiAC *mitsubir = nullptr; @@ -84,9 +84,8 @@ void IrSendInit(void) * IR Receive \*********************************************************************************************/ -#define IR_RCV_SAVE_BUFFER 0 // 0 = do not use buffer, 1 = use buffer for decoding - -#define IR_TIME_AVOID_DUPLICATE 500 // Milliseconds +const bool IR_RCV_SAVE_BUFFER = false; // false = do not use buffer, true = use buffer for decoding +const uint32_t IR_TIME_AVOID_DUPLICATE = 500; // Milliseconds #include diff --git a/sonoff/xdrv_06_snfbridge.ino b/sonoff/xdrv_06_snfbridge.ino index f2550bf8d..eaf934043 100644 --- a/sonoff/xdrv_06_snfbridge.ino +++ b/sonoff/xdrv_06_snfbridge.ino @@ -23,7 +23,7 @@ #define XDRV_06 6 -#define SFB_TIME_AVOID_DUPLICATE 2000 // Milliseconds +const uint32_t SFB_TIME_AVOID_DUPLICATE = 2000; // Milliseconds enum SonoffBridgeCommands { CMND_RFSYNC, CMND_RFLOW, CMND_RFHIGH, CMND_RFHOST, CMND_RFCODE, CMND_RFKEY, CMND_RFRAW }; @@ -51,8 +51,8 @@ unsigned long sonoff_bridge_last_learn_time = 0; #include "ihx.h" #include "c2.h" -#define RF_RECORD_NO_START_FOUND -1 -#define RF_RECORD_NO_END_FOUND -2 +const ssize_t RF_RECORD_NO_START_FOUND = -1; +const ssize_t RF_RECORD_NO_END_FOUND = -2; ssize_t rf_find_hex_record_start(uint8_t *buf, size_t size) { diff --git a/sonoff/xdrv_08_serial_bridge.ino b/sonoff/xdrv_08_serial_bridge.ino index fbad30683..0125591c1 100644 --- a/sonoff/xdrv_08_serial_bridge.ino +++ b/sonoff/xdrv_08_serial_bridge.ino @@ -24,7 +24,7 @@ #define XDRV_08 8 -#define SERIAL_BRIDGE_BUFFER_SIZE 130 +const uint8_t SERIAL_BRIDGE_BUFFER_SIZE = 130; #include diff --git a/sonoff/xdrv_13_display.ino b/sonoff/xdrv_13_display.ino index 498cce9fc..3f40bdb84 100644 --- a/sonoff/xdrv_13_display.ino +++ b/sonoff/xdrv_13_display.ino @@ -22,11 +22,11 @@ #define XDRV_13 13 -#define DISPLAY_MAX_DRIVERS 16 // Max number of display drivers/models supported by xdsp_interface.ino -#define DISPLAY_MAX_COLS 44 // Max number of columns allowed with command DisplayCols -#define DISPLAY_MAX_ROWS 32 // Max number of lines allowed with command DisplayRows +const uint8_t DISPLAY_MAX_DRIVERS = 16; // Max number of display drivers/models supported by xdsp_interface.ino +const uint8_t DISPLAY_MAX_COLS = 44; // Max number of columns allowed with command DisplayCols +const uint8_t DISPLAY_MAX_ROWS = 32; // Max number of lines allowed with command DisplayRows -#define DISPLAY_LOG_ROWS 32 // Number of lines in display log buffer +const uint8_t DISPLAY_LOG_ROWS = 32; // Number of lines in display log buffer #define D_CMND_DISPLAY "Display" #define D_CMND_DISP_ADDRESS "Address" From d310373c288189f32fd1055b9f96d6f9a2829308 Mon Sep 17 00:00:00 2001 From: Norbert Richter Date: Sun, 31 Mar 2019 12:23:09 +0200 Subject: [PATCH 35/81] decode-config.py: adapt settings - add Sensor20 (novasds_period) --- tools/decode-config.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/decode-config.py b/tools/decode-config.py index feec178cf..161cc850d 100755 --- a/tools/decode-config.py +++ b/tools/decode-config.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -VER = '2.1.0022' +VER = '2.1.0023' """ decode-config.py - Backup/Restore Sonoff-Tasmota configuration data @@ -878,7 +878,13 @@ Setting_6_4_1_18['flag3'][0].update ({ 'no_hold_retain': (' Date: Sun, 31 Mar 2019 13:06:42 +0200 Subject: [PATCH 36/81] Fix parameter exceptions (#5555) Fix parameter exceptions (#5555) --- sonoff/xdrv_05_irremote.ino | 261 +++++++++++++++++++----------------- 1 file changed, 141 insertions(+), 120 deletions(-) diff --git a/sonoff/xdrv_05_irremote.ino b/sonoff/xdrv_05_irremote.ino index 864d77e8c..d62be8ee3 100644 --- a/sonoff/xdrv_05_irremote.ino +++ b/sonoff/xdrv_05_irremote.ino @@ -26,6 +26,8 @@ #include +enum IrErrors { IE_NO_ERROR, IE_INVALID_RAWDATA, IE_INVALID_JSON, IE_SYNTAX_IRSEND, IE_SYNTAX_IRHVAC }; + enum IrRemoteCommands { CMND_IRSEND, CMND_IRHVAC }; const char kIrRemoteCommands[] PROGMEM = D_CMND_IRSEND "|" D_CMND_IRHVAC ; @@ -180,7 +182,7 @@ void IrReceiveCheck(void) TOSHIBA ********************/ -bool IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) +uint8_t IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) { uint16_t rawdata[2 + 2 * 8 * HVAC_TOSHIBA_DATALEN + 2]; uint8_t data[HVAC_TOSHIBA_DATALEN] = {0xF2, 0x0D, 0x03, 0xFC, 0x01, 0x00, 0x00, 0x00, 0x00}; @@ -195,7 +197,7 @@ bool IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Po p = strchr(kHvacModeOptions, toupper(HVAC_Mode[0])); } if (!p) { - return true; + return IE_SYNTAX_IRHVAC; } data[6] = (p - kHvacModeOptions) ^ 0x03; // HOT = 0x03, DRY = 0x02, COOL = 0x01, AUTO = 0x00 @@ -210,7 +212,7 @@ bool IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Po p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); } if (!p) { - return true; + return IE_SYNTAX_IRHVAC; } mode = p - kFanSpeedOptions + 1; if ((1 == mode) || (7 == mode)) { @@ -267,7 +269,7 @@ bool IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Po irsend->sendRaw(rawdata, i, 38); // interrupts(); - return false; + return IE_NO_ERROR; } @@ -275,7 +277,7 @@ bool IrHvacToshiba(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Po MITSUBISHI ********************/ -bool IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) +uint8_t IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) { char *p; uint8_t mode; @@ -289,7 +291,7 @@ bool IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC p = strchr(kHvacModeOptions, toupper(HVAC_Mode[0])); } if (!p) { - return true; + return IE_SYNTAX_IRHVAC; } mode = (p - kHvacModeOptions + 1) << 3; // HOT = 0x08, DRY = 0x10, COOL = 0x18, AUTO = 0x20 mitsubir->setMode(mode); @@ -303,7 +305,7 @@ bool IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); } if (!p) { - return true; + return IE_SYNTAX_IRHVAC; } mode = p - kFanSpeedOptions; // AUTO = 0, SPEED = 1 .. 5, SILENT = 6 mitsubir->setFan(mode); @@ -315,7 +317,7 @@ bool IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRHVAC: Mitsubishi Power %d, Mode %d, FanSpeed %d, Temp %d, VaneMode %d"), // mitsubir->getPower(), mitsubir->getMode(), mitsubir->getFan(), mitsubir->getTemp(), mitsubir->getVane()); - return false; + return IE_NO_ERROR; } @@ -323,7 +325,7 @@ bool IrHvacMitsubishi(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC LG ********************/ -bool IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) +uint8_t IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) { uint32_t LG_Code; uint8_t data[HVAC_LG_DATALEN]; @@ -356,7 +358,7 @@ bool IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, p = strchr(kHvacModeOptions, toupper(HVAC_Mode[0])); } if (!p) { - return true; + return IE_SYNTAX_IRHVAC; } mode = (p - kHvacModeOptions) ^ 0x03; // HOT = 0x03, DRY = 0x02, COOL = 0x01, AUTO = 0x00 switch (mode) { @@ -400,7 +402,7 @@ bool IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); } if (!p) { - return true; + return IE_SYNTAX_IRHVAC; } mode = p - kFanSpeedOptions; if ((mode == 0) || (mode > 3)) { @@ -431,7 +433,7 @@ bool IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, irsend->sendLG(LG_Code, 28); // interrupts(); - return false; + return IE_NO_ERROR; } @@ -439,7 +441,7 @@ bool IrHvacLG(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, Fujitsu ********************/ -bool IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) +uint8_t IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Power, int HVAC_Temp) { const char kFujitsuHvacModeOptions[] = "HDCAF"; @@ -452,7 +454,7 @@ bool IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Po if (0 == HVAC_Power) { ac.off(); ac.send(); - return false; + return IE_NO_ERROR; } uint8_t modes[5] = {FUJITSU_AC_MODE_HEAT, FUJITSU_AC_MODE_DRY, FUJITSU_AC_MODE_COOL, FUJITSU_AC_MODE_AUTO, FUJITSU_AC_MODE_FAN}; @@ -468,7 +470,7 @@ bool IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Po p = strchr(kFujitsuHvacModeOptions, toupper(HVAC_Mode[0])); } if (!p) { - return true; + return IE_SYNTAX_IRHVAC; } ac.setMode(modes[p - kFujitsuHvacModeOptions]); @@ -479,14 +481,14 @@ bool IrHvacFujitsu(const char *HVAC_Mode, const char *HVAC_FanMode, bool HVAC_Po p = strchr(kFanSpeedOptions, toupper(HVAC_FanMode[0])); } if (!p) { - return true; + return IE_SYNTAX_IRHVAC; } ac.setFanSpeed(fanModes[p - kFanSpeedOptions]); ac.setTemp(HVAC_Temp); ac.send(); - return false; + return IE_NO_ERROR; } #endif // USE_IR_HVAC @@ -507,7 +509,7 @@ bool IrSendCommand(void) { char command [CMDSZ]; bool serviced = true; - bool error = false; + uint8_t error = IE_NO_ERROR; int command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic, kIrRemoteCommands); if (-1 == command_code) { @@ -521,86 +523,87 @@ bool IrSendCommand(void) // IRSend frequency, rawdata, rawdata ... char *p; char *str = strtok_r(XdrvMailbox.data, ", ", &p); - uint16_t freq = atoi(str); - if (!freq) { freq = 38000; } // Default to 38kHz - uint16_t count = 0; - char *q = p; - for (; *q; count += (*q++ == ',')); - if (count) { // At least two raw data values - count++; - uint16_t raw_array[count]; // It's safe to use stack for up to 240 packets (limited by mqtt_data length) - uint8_t i = 0; - for (str = strtok_r(nullptr, ", ", &p); str && i < count; str = strtok_r(nullptr, ", ", &p)) { - raw_array[i++] = strtoul(str, nullptr, 0); // Allow decimal (5246996) and hexadecimal (0x501014) input - } + if (p == nullptr) { + error = IE_INVALID_RAWDATA; + } else { + uint16_t freq = atoi(str); + if (!freq) { freq = 38000; } // Default to 38kHz + uint16_t count = 0; + char *q = p; + for (; *q; count += (*q++ == ',')); + if (0 == count) { + error = IE_INVALID_RAWDATA; + } else { // At least two raw data values + count++; + uint16_t raw_array[count]; // It's safe to use stack for up to 240 packets (limited by mqtt_data length) + uint8_t i = 0; + for (str = strtok_r(nullptr, ", ", &p); str && i < count; str = strtok_r(nullptr, ", ", &p)) { + raw_array[i++] = strtoul(str, nullptr, 0); // Allow decimal (5246996) and hexadecimal (0x501014) input + } -// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: Count %d, Freq %d, Arr[0] %d, Arr[count -1] %d"), count, freq, raw_array[0], raw_array[count -1]); - - irsend_active = true; - irsend->sendRaw(raw_array, count, freq); - if (!count) { - Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_FAILED); - } - } - else { - Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_RAWDATA); - } - } - else { - char dataBufUc[XdrvMailbox.data_len]; - UpperCase(dataBufUc, XdrvMailbox.data); - StaticJsonBuffer<128> jsonBuf; - JsonObject &root = jsonBuf.parseObject(dataBufUc); - if (!root.success()) { - Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_JSON); - } - else { - // IRsend { "protocol": "SAMSUNG", "bits": 32, "data": 551502015 } - char parm_uc[10]; - const char *protocol = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_PROTOCOL))]; - uint32_t bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_BITS))]; - uint32_t data = strtoul(root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATA))], nullptr, 0); - if (protocol && bits) { - char protocol_text[20]; - int protocol_code = GetCommandCode(protocol_text, sizeof(protocol_text), protocol, kIrRemoteProtocols); - - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: protocol_text %s, protocol %s, bits %d, data %u (0x%lX), protocol_code %d"), - protocol_text, protocol, bits, data, data, protocol_code); +// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: Count %d, Freq %d, Arr[0] %d, Arr[count -1] %d"), count, freq, raw_array[0], raw_array[count -1]); irsend_active = true; - switch (protocol_code) { - case NEC: - irsend->sendNEC(data, (bits > NEC_BITS) ? NEC_BITS : bits); break; - case SONY: - irsend->sendSony(data, (bits > SONY_20_BITS) ? SONY_20_BITS : bits, 2); break; - case RC5: - irsend->sendRC5(data, bits); break; - case RC6: - irsend->sendRC6(data, bits); break; - case DISH: - irsend->sendDISH(data, (bits > DISH_BITS) ? DISH_BITS : bits); break; - case JVC: - irsend->sendJVC(data, (bits > JVC_BITS) ? JVC_BITS : bits, 1); break; - case SAMSUNG: - irsend->sendSAMSUNG(data, (bits > SAMSUNG_BITS) ? SAMSUNG_BITS : bits); break; - case PANASONIC: - irsend->sendPanasonic(bits, data); break; - default: - irsend_active = false; - Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_PROTOCOL_NOT_SUPPORTED); + irsend->sendRaw(raw_array, count, freq); + if (!count) { + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_FAILED); } } - else { - error = true; + } + } else { + char dataBufUc[XdrvMailbox.data_len]; + UpperCase(dataBufUc, XdrvMailbox.data); + RemoveSpace(dataBufUc); + if (strlen(dataBufUc) < 8) { + error = IE_INVALID_JSON; + } else { + StaticJsonBuffer<128> jsonBuf; + JsonObject &root = jsonBuf.parseObject(dataBufUc); + if (!root.success()) { + error = IE_INVALID_JSON; + } else { + // IRsend { "protocol": "SAMSUNG", "bits": 32, "data": 551502015 } + char parm_uc[10]; + const char *protocol = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_PROTOCOL))]; + uint32_t bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_BITS))]; + uint32_t data = strtoul(root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATA))], nullptr, 0); + if (protocol && bits) { + char protocol_text[20]; + int protocol_code = GetCommandCode(protocol_text, sizeof(protocol_text), protocol, kIrRemoteProtocols); + + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: protocol_text %s, protocol %s, bits %d, data %u (0x%lX), protocol_code %d"), + protocol_text, protocol, bits, data, data, protocol_code); + + irsend_active = true; + switch (protocol_code) { + case NEC: + irsend->sendNEC(data, (bits > NEC_BITS) ? NEC_BITS : bits); break; + case SONY: + irsend->sendSony(data, (bits > SONY_20_BITS) ? SONY_20_BITS : bits, 2); break; + case RC5: + irsend->sendRC5(data, bits); break; + case RC6: + irsend->sendRC6(data, bits); break; + case DISH: + irsend->sendDISH(data, (bits > DISH_BITS) ? DISH_BITS : bits); break; + case JVC: + irsend->sendJVC(data, (bits > JVC_BITS) ? JVC_BITS : bits, 1); break; + case SAMSUNG: + irsend->sendSAMSUNG(data, (bits > SAMSUNG_BITS) ? SAMSUNG_BITS : bits); break; + case PANASONIC: + irsend->sendPanasonic(bits, data); break; + default: + irsend_active = false; + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_PROTOCOL_NOT_SUPPORTED); + } + } else { + error = IE_SYNTAX_IRSEND; + } } } } - } - else { - error = true; - } - if (error) { - Response_P(PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_NO " " D_JSON_IR_PROTOCOL ", " D_JSON_IR_BITS " " D_JSON_OR " " D_JSON_IR_DATA "\"}")); + } else { + error = IE_SYNTAX_IRSEND; } } #ifdef USE_IR_HVAC @@ -614,47 +617,65 @@ bool IrSendCommand(void) if (XdrvMailbox.data_len) { char dataBufUc[XdrvMailbox.data_len]; UpperCase(dataBufUc, XdrvMailbox.data); - StaticJsonBuffer<164> jsonBufer; - JsonObject &root = jsonBufer.parseObject(dataBufUc); - if (!root.success()) { - Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_JSON); - } - else { - Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); - HVAC_Vendor = root[D_JSON_IRHVAC_VENDOR]; - HVAC_Power = root[D_JSON_IRHVAC_POWER]; - HVAC_Mode = root[D_JSON_IRHVAC_MODE]; - HVAC_FanMode = root[D_JSON_IRHVAC_FANSPEED]; - HVAC_Temp = root[D_JSON_IRHVAC_TEMP]; + RemoveSpace(dataBufUc); + if (strlen(dataBufUc) < 8) { + error = IE_INVALID_JSON; + } else { + StaticJsonBuffer<164> jsonBufer; + JsonObject &root = jsonBufer.parseObject(dataBufUc); + if (!root.success()) { + error = IE_INVALID_JSON; + } else { + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_DONE); + HVAC_Vendor = root[D_JSON_IRHVAC_VENDOR]; + HVAC_Power = root[D_JSON_IRHVAC_POWER]; + HVAC_Mode = root[D_JSON_IRHVAC_MODE]; + HVAC_FanMode = root[D_JSON_IRHVAC_FANSPEED]; + HVAC_Temp = root[D_JSON_IRHVAC_TEMP]; -// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRHVAC: Received Vendor %s, Power %d, Mode %s, FanSpeed %s, Temp %d"), HVAC_Vendor, HVAC_Power, HVAC_Mode, HVAC_FanMode, HVAC_Temp); + // AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRHVAC: Received Vendor %s, Power %d, Mode %s, FanSpeed %s, Temp %d"), HVAC_Vendor, HVAC_Power, HVAC_Mode, HVAC_FanMode, HVAC_Temp); - char vendor[20]; - int vendor_code = GetCommandCode(vendor, sizeof(vendor), HVAC_Vendor, kIrHvacVendors); - switch (vendor_code) { - case VNDR_TOSHIBA: - error = IrHvacToshiba(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); break; - case VNDR_MITSUBISHI: - error = IrHvacMitsubishi(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); break; - case VNDR_LG: - error = IrHvacLG(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); break; - case VNDR_FUJITSU: - error = IrHvacFujitsu(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); break; - default: - error = true; + char vendor[20]; + int vendor_code = GetCommandCode(vendor, sizeof(vendor), HVAC_Vendor, kIrHvacVendors); + switch (vendor_code) { + case VNDR_TOSHIBA: + error = IrHvacToshiba(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); break; + case VNDR_MITSUBISHI: + error = IrHvacMitsubishi(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); break; + case VNDR_LG: + error = IrHvacLG(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); break; + case VNDR_FUJITSU: + error = IrHvacFujitsu(HVAC_Mode, HVAC_FanMode, HVAC_Power, HVAC_Temp); break; + default: + error = IE_SYNTAX_IRHVAC; + } } } } else { - error = true; - } - if (error) { - Response_P(PSTR("{\"" D_CMND_IRHVAC "\":\"" D_JSON_WRONG " " D_JSON_IRHVAC_VENDOR ", " D_JSON_IRHVAC_MODE " " D_JSON_OR " " D_JSON_IRHVAC_FANSPEED "\"}")); + error = IE_SYNTAX_IRHVAC; } } #endif // USE_IR_HVAC else serviced = false; // Unknown command + switch (error) { + case IE_INVALID_RAWDATA: + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_RAWDATA); + break; + case IE_INVALID_JSON: + Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_INVALID_JSON); + break; + case IE_SYNTAX_IRSEND: + Response_P(PSTR("{\"" D_CMND_IRSEND "\":\"" D_JSON_NO " " D_JSON_IR_PROTOCOL ", " D_JSON_IR_BITS " " D_JSON_OR " " D_JSON_IR_DATA "\"}")); + break; +#ifdef USE_IR_HVAC + case IE_SYNTAX_IRHVAC: + Response_P(PSTR("{\"" D_CMND_IRHVAC "\":\"" D_JSON_WRONG " " D_JSON_IRHVAC_VENDOR ", " D_JSON_IRHVAC_MODE " " D_JSON_OR " " D_JSON_IRHVAC_FANSPEED "\"}")); + break; +#endif // USE_IR_HVAC + } + return serviced; } From b7adb109238939f9ab11770fb71bcec54830f692 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 31 Mar 2019 17:51:05 +0200 Subject: [PATCH 37/81] Test for easier MQTT reconnects Test for easier MQTT reconnects --- sonoff/support.ino | 13 +++++++++++-- sonoff/xdrv_01_webserver.ino | 12 +----------- sonoff/xdrv_02_mqtt.ino | 14 +++++++++++++- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/sonoff/support.ino b/sonoff/support.ino index e571e6ec1..d101185a6 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -370,6 +370,14 @@ uint8_t Shortcut(const char* str) return result; } +bool ValidIpAddress(const char* str) +{ + const char* p = str; + + while (*p && ( (*p == '.') || (*p >= '0') || (*p <= '9') )) { p++; } + return (*p == '\0'); +} + bool ParseIp(uint32_t* addr, const char* str) { uint8_t *part = (uint8_t*)addr; @@ -1247,8 +1255,9 @@ void Syslog(void) // Destroys log_data char syslog_preamble[64]; // Hostname + Id - if (syslog_host_hash != GetHash(Settings.syslog_host, strlen(Settings.syslog_host))) { - syslog_host_hash = GetHash(Settings.syslog_host, strlen(Settings.syslog_host)); + uint32_t current_hash = GetHash(Settings.syslog_host, strlen(Settings.syslog_host)); + if (syslog_host_hash != current_hash) { + syslog_host_hash = current_hash; WiFi.hostByName(Settings.syslog_host, syslog_host_addr); // If sleep enabled this might result in exception so try to do it once using hash } if (PortUdp.beginPacket(syslog_host_addr, Settings.syslog_port)) { diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 44be997a6..76cdae534 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -2148,7 +2148,7 @@ void HandleNotFound(void) /* Redirect to captive portal if we got a request for another domain. Return true in that case so the page handler do not try to handle the request again. */ bool CaptivePortal(void) { - if ((WifiIsInManagerMode()) && !ValidIpAddress(WebServer->hostHeader())) { + if ((WifiIsInManagerMode()) && !ValidIpAddress(WebServer->hostHeader().c_str())) { AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_REDIRECTED)); WebServer->sendHeader(F("Location"), String("http://") + WebServer->client().localIP().toString(), true); @@ -2159,16 +2159,6 @@ bool CaptivePortal(void) return false; } -/** Is this an IP? */ -bool ValidIpAddress(String str) -{ - for (uint16_t i = 0; i < str.length(); i++) { - int c = str.charAt(i); - if (c != '.' && (c < '0' || c > '9')) { return false; } - } - return true; -} - /*********************************************************************************************/ String UrlEncode(const String& text) diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 5720b9a7d..f001b39d5 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -37,6 +37,9 @@ const char kMqttCommands[] PROGMEM = D_CMND_MQTTUSER "|" D_CMND_MQTTPASSWORD "|" 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 ; +IPAddress mqtt_host_addr; // MQTT host IP address +uint32_t mqtt_host_hash = 0; // MQTT host name hash + uint16_t mqtt_connect_count = 0; // MQTT re-connect count uint16_t mqtt_retry_counter = 1; // MQTT connection retry counter uint8_t mqtt_initial_connection_state = 2; // MQTT connection messages state @@ -448,7 +451,16 @@ void MqttReconnect(void) } MqttClient.setCallback(MqttDataHandler); - MqttClient.setServer(Settings.mqtt_host, Settings.mqtt_port); +// MqttClient.setServer(Settings.mqtt_host, Settings.mqtt_port); + + // Skip MQTT host DNS lookup if not needed + uint32_t current_hash = GetHash(Settings.mqtt_host, strlen(Settings.mqtt_host)); + if (mqtt_host_hash != current_hash) { + mqtt_host_hash = current_hash; + WiFi.hostByName(Settings.mqtt_host, mqtt_host_addr); // Skips DNS lookup if mqtt_host is IP address string as from mDns + } + MqttClient.setServer(mqtt_host_addr, Settings.mqtt_port); + if (MqttClient.connect(mqtt_client, mqtt_user, mqtt_pwd, stopic, 1, true, mqtt_data)) { MqttConnected(); } else { From 8d8e06055086f632365bcdd64f4e255768cbd699 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 31 Mar 2019 17:55:58 +0200 Subject: [PATCH 38/81] Revert "Test for easier MQTT reconnects" This reverts commit b7adb109238939f9ab11770fb71bcec54830f692. --- sonoff/support.ino | 13 ++----------- sonoff/xdrv_01_webserver.ino | 12 +++++++++++- sonoff/xdrv_02_mqtt.ino | 14 +------------- 3 files changed, 14 insertions(+), 25 deletions(-) diff --git a/sonoff/support.ino b/sonoff/support.ino index d101185a6..e571e6ec1 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -370,14 +370,6 @@ uint8_t Shortcut(const char* str) return result; } -bool ValidIpAddress(const char* str) -{ - const char* p = str; - - while (*p && ( (*p == '.') || (*p >= '0') || (*p <= '9') )) { p++; } - return (*p == '\0'); -} - bool ParseIp(uint32_t* addr, const char* str) { uint8_t *part = (uint8_t*)addr; @@ -1255,9 +1247,8 @@ void Syslog(void) // Destroys log_data char syslog_preamble[64]; // Hostname + Id - uint32_t current_hash = GetHash(Settings.syslog_host, strlen(Settings.syslog_host)); - if (syslog_host_hash != current_hash) { - syslog_host_hash = current_hash; + if (syslog_host_hash != GetHash(Settings.syslog_host, strlen(Settings.syslog_host))) { + syslog_host_hash = GetHash(Settings.syslog_host, strlen(Settings.syslog_host)); WiFi.hostByName(Settings.syslog_host, syslog_host_addr); // If sleep enabled this might result in exception so try to do it once using hash } if (PortUdp.beginPacket(syslog_host_addr, Settings.syslog_port)) { diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 76cdae534..44be997a6 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -2148,7 +2148,7 @@ void HandleNotFound(void) /* Redirect to captive portal if we got a request for another domain. Return true in that case so the page handler do not try to handle the request again. */ bool CaptivePortal(void) { - if ((WifiIsInManagerMode()) && !ValidIpAddress(WebServer->hostHeader().c_str())) { + if ((WifiIsInManagerMode()) && !ValidIpAddress(WebServer->hostHeader())) { AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_REDIRECTED)); WebServer->sendHeader(F("Location"), String("http://") + WebServer->client().localIP().toString(), true); @@ -2159,6 +2159,16 @@ bool CaptivePortal(void) return false; } +/** Is this an IP? */ +bool ValidIpAddress(String str) +{ + for (uint16_t i = 0; i < str.length(); i++) { + int c = str.charAt(i); + if (c != '.' && (c < '0' || c > '9')) { return false; } + } + return true; +} + /*********************************************************************************************/ String UrlEncode(const String& text) diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index f001b39d5..5720b9a7d 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -37,9 +37,6 @@ const char kMqttCommands[] PROGMEM = D_CMND_MQTTUSER "|" D_CMND_MQTTPASSWORD "|" 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 ; -IPAddress mqtt_host_addr; // MQTT host IP address -uint32_t mqtt_host_hash = 0; // MQTT host name hash - uint16_t mqtt_connect_count = 0; // MQTT re-connect count uint16_t mqtt_retry_counter = 1; // MQTT connection retry counter uint8_t mqtt_initial_connection_state = 2; // MQTT connection messages state @@ -451,16 +448,7 @@ void MqttReconnect(void) } MqttClient.setCallback(MqttDataHandler); -// MqttClient.setServer(Settings.mqtt_host, Settings.mqtt_port); - - // Skip MQTT host DNS lookup if not needed - uint32_t current_hash = GetHash(Settings.mqtt_host, strlen(Settings.mqtt_host)); - if (mqtt_host_hash != current_hash) { - mqtt_host_hash = current_hash; - WiFi.hostByName(Settings.mqtt_host, mqtt_host_addr); // Skips DNS lookup if mqtt_host is IP address string as from mDns - } - MqttClient.setServer(mqtt_host_addr, Settings.mqtt_port); - + MqttClient.setServer(Settings.mqtt_host, Settings.mqtt_port); if (MqttClient.connect(mqtt_client, mqtt_user, mqtt_pwd, stopic, 1, true, mqtt_data)) { MqttConnected(); } else { From 880bbe357d5c232de81a5cd7db288c26151fc9ef Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sun, 31 Mar 2019 17:57:28 +0200 Subject: [PATCH 39/81] Change String to char Change String to char --- sonoff/support.ino | 13 +++++++++++-- sonoff/xdrv_01_webserver.ino | 12 +----------- sonoff/xdrv_02_mqtt.ino | 12 ++++++++++++ 3 files changed, 24 insertions(+), 13 deletions(-) diff --git a/sonoff/support.ino b/sonoff/support.ino index e571e6ec1..d101185a6 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -370,6 +370,14 @@ uint8_t Shortcut(const char* str) return result; } +bool ValidIpAddress(const char* str) +{ + const char* p = str; + + while (*p && ( (*p == '.') || (*p >= '0') || (*p <= '9') )) { p++; } + return (*p == '\0'); +} + bool ParseIp(uint32_t* addr, const char* str) { uint8_t *part = (uint8_t*)addr; @@ -1247,8 +1255,9 @@ void Syslog(void) // Destroys log_data char syslog_preamble[64]; // Hostname + Id - if (syslog_host_hash != GetHash(Settings.syslog_host, strlen(Settings.syslog_host))) { - syslog_host_hash = GetHash(Settings.syslog_host, strlen(Settings.syslog_host)); + uint32_t current_hash = GetHash(Settings.syslog_host, strlen(Settings.syslog_host)); + if (syslog_host_hash != current_hash) { + syslog_host_hash = current_hash; WiFi.hostByName(Settings.syslog_host, syslog_host_addr); // If sleep enabled this might result in exception so try to do it once using hash } if (PortUdp.beginPacket(syslog_host_addr, Settings.syslog_port)) { diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 44be997a6..76cdae534 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -2148,7 +2148,7 @@ void HandleNotFound(void) /* Redirect to captive portal if we got a request for another domain. Return true in that case so the page handler do not try to handle the request again. */ bool CaptivePortal(void) { - if ((WifiIsInManagerMode()) && !ValidIpAddress(WebServer->hostHeader())) { + if ((WifiIsInManagerMode()) && !ValidIpAddress(WebServer->hostHeader().c_str())) { AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_REDIRECTED)); WebServer->sendHeader(F("Location"), String("http://") + WebServer->client().localIP().toString(), true); @@ -2159,16 +2159,6 @@ bool CaptivePortal(void) return false; } -/** Is this an IP? */ -bool ValidIpAddress(String str) -{ - for (uint16_t i = 0; i < str.length(); i++) { - int c = str.charAt(i); - if (c != '.' && (c < '0' || c > '9')) { return false; } - } - return true; -} - /*********************************************************************************************/ String UrlEncode(const String& text) diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 5720b9a7d..b7daa1f34 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -37,6 +37,9 @@ const char kMqttCommands[] PROGMEM = D_CMND_MQTTUSER "|" D_CMND_MQTTPASSWORD "|" 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 ; +IPAddress mqtt_host_addr; // MQTT host IP address +uint32_t mqtt_host_hash = 0; // MQTT host name hash + uint16_t mqtt_connect_count = 0; // MQTT re-connect count uint16_t mqtt_retry_counter = 1; // MQTT connection retry counter uint8_t mqtt_initial_connection_state = 2; // MQTT connection messages state @@ -449,6 +452,15 @@ void MqttReconnect(void) MqttClient.setCallback(MqttDataHandler); MqttClient.setServer(Settings.mqtt_host, Settings.mqtt_port); +/* + // Skip MQTT host DNS lookup if not needed + uint32_t current_hash = GetHash(Settings.mqtt_host, strlen(Settings.mqtt_host)); + if (mqtt_host_hash != current_hash) { + mqtt_host_hash = current_hash; + WiFi.hostByName(Settings.mqtt_host, mqtt_host_addr); // Skips DNS lookup if mqtt_host is IP address string as from mDns + } + MqttClient.setServer(mqtt_host_addr, Settings.mqtt_port); +*/ if (MqttClient.connect(mqtt_client, mqtt_user, mqtt_pwd, stopic, 1, true, mqtt_data)) { MqttConnected(); } else { From 127892e0c186bef0678b1683fff913918116ced5 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 1 Apr 2019 15:15:16 +0200 Subject: [PATCH 40/81] Change IRsend and receive for 64-bit support * Change IRsend and receive for 64-bit support (#5523) * Change IRSend Panasonic protocol to 64-bit (#5523) --- sonoff/_changelog.ino | 2 ++ sonoff/support.ino | 22 +++++++++++++++++ sonoff/xdrv_05_irremote.ino | 49 ++++++++++++++++++++++++++----------- 3 files changed, 59 insertions(+), 14 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 6f40ca4ae..7ffe22789 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,8 @@ /* 6.5.0.3 20190328 * Add command Sensor20 1..255 to change Nova Fitness SDS01 working period in minutes (#5452) * Change some defines to const + * Change IRsend and receive for 64-bit support (#5523) + * Change IRSend Panasonic protocol to 64-bit (#5523) * * 6.5.0.2 20190325 * Change UDP initial message handling from string to char using static memory and add debug info (#5505) diff --git a/sonoff/support.ino b/sonoff/support.ino index d101185a6..cffcb4690 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -200,6 +200,28 @@ int TextToInt(char *str) return strtol(str, &p, radix); } +char* ulltoa(unsigned long long value, char *str, int radix) +{ + char digits[64]; + char *dst = str; + int i = 0; + int n = 0; + +/* + if (radix < 2 || radix > 36) { radix = 10; } +*/ + do { + n = value % radix; + digits[i++] = (n < 10) ? (char)n+'0' : (char)n-10+'A'; + value /= radix; + } while (value != 0); + + while (i > 0) { *dst++ = digits[--i]; } + + *dst = 0; + return str; +} + char* dtostrfd(double number, unsigned char prec, char *s) { if ((isnan(number)) || (isinf(number))) { // Fix for JSON output (https://stackoverflow.com/questions/1423081/json-left-out-infinity-and-nan-json-status-in-ecmascript) diff --git a/sonoff/xdrv_05_irremote.ino b/sonoff/xdrv_05_irremote.ino index d62be8ee3..9bddc3617 100644 --- a/sonoff/xdrv_05_irremote.ino +++ b/sonoff/xdrv_05_irremote.ino @@ -105,18 +105,37 @@ void IrReceiveInit(void) // AddLog_P(LOG_LEVEL_DEBUG, PSTR("IrReceive initialized")); } +char* IrUint64toHex(uint64_t value, char *str, uint16_t bits) +{ + ulltoa(value, str, 16); // Get 64bit value + + int fill = 8; + if ((bits > 3) && (bits < 65)) { fill = bits / 4 ; } // Max 16 + int len = strlen(str); + fill -= len; + if (fill > 0) { + memmove(str + fill, str, len +1); + memset(str, '0', fill); + } + memmove(str + 2, str, strlen(str) +1); + str[0] = '0'; + str[1] = 'x'; + return str; +} + void IrReceiveCheck(void) { char sirtype[14]; // Max is AIWA_RC_T501 - char stemp[16]; int8_t iridx = 0; decode_results results; if (irrecv->decode(&results)) { + char hvalue[64]; + IrUint64toHex(results.value, hvalue, results.bits); // Get 64bit value as hex 0x00123456 - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_IRR "Echo %d, RawLen %d, Overflow %d, Bits %d, Value 0x%08X, Decode %d"), - irsend_active, results.rawlen, results.overflow, results.bits, results.value, results.decode_type); + AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_IRR "Echo %d, RawLen %d, Overflow %d, Bits %d, Value %s, Decode %d"), + irsend_active, results.rawlen, results.overflow, results.bits, hvalue, results.decode_type); unsigned long now = millis(); // if ((now - ir_lasttime > IR_TIME_AVOID_DUPLICATE) && (UNKNOWN != results.decode_type) && (results.bits > 0)) { @@ -124,16 +143,15 @@ void IrReceiveCheck(void) ir_lasttime = now; iridx = results.decode_type; - if ((iridx < 0) || (iridx > 14)) { - iridx = 0; // UNKNOWN - } + if ((iridx < 0) || (iridx > 14)) { iridx = 0; } // UNKNOWN + char svalue[64]; if (Settings.flag.ir_receive_decimal) { - snprintf_P(stemp, sizeof(stemp), PSTR("%u"), (uint32_t)results.value); + ulltoa(results.value, svalue, 10); } else { - snprintf_P(stemp, sizeof(stemp), PSTR("\"0x%lX\""), (uint32_t)results.value); + snprintf_P(svalue, sizeof(svalue), PSTR("\"%s\""), hvalue); } Response_P(PSTR("{\"" D_JSON_IRRECEIVED "\":{\"" D_JSON_IR_PROTOCOL "\":\"%s\",\"" D_JSON_IR_BITS "\":%d,\"" D_JSON_IR_DATA "\":%s"), - GetTextIndexed(sirtype, sizeof(sirtype), iridx, kIrRemoteProtocols), results.bits, stemp); + GetTextIndexed(sirtype, sizeof(sirtype), iridx, kIrRemoteProtocols), results.bits, svalue); if (Settings.flag3.receive_raw) { ResponseAppend_P(PSTR(",\"" D_JSON_IR_RAWDATA "\":[")); @@ -565,14 +583,16 @@ bool IrSendCommand(void) // IRsend { "protocol": "SAMSUNG", "bits": 32, "data": 551502015 } char parm_uc[10]; const char *protocol = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_PROTOCOL))]; - uint32_t bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_BITS))]; - uint32_t data = strtoul(root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATA))], nullptr, 0); + uint16_t bits = root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_BITS))]; + uint64_t data = strtoull(root[UpperCase_P(parm_uc, PSTR(D_JSON_IR_DATA))], nullptr, 0); if (protocol && bits) { char protocol_text[20]; int protocol_code = GetCommandCode(protocol_text, sizeof(protocol_text), protocol, kIrRemoteProtocols); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: protocol_text %s, protocol %s, bits %d, data %u (0x%lX), protocol_code %d"), - protocol_text, protocol, bits, data, data, protocol_code); + char dvalue[64]; + char hvalue[64]; + AddLog_P2(LOG_LEVEL_DEBUG, PSTR("IRS: protocol_text %s, protocol %s, bits %d, data %s (%s), protocol_code %d"), + protocol_text, protocol, bits, ulltoa(data, dvalue, 10), IrUint64toHex(data, hvalue, bits), protocol_code); irsend_active = true; switch (protocol_code) { @@ -591,7 +611,8 @@ bool IrSendCommand(void) case SAMSUNG: irsend->sendSAMSUNG(data, (bits > SAMSUNG_BITS) ? SAMSUNG_BITS : bits); break; case PANASONIC: - irsend->sendPanasonic(bits, data); break; +// irsend->sendPanasonic(bits, data); break; + irsend->sendPanasonic64(data, bits); break; default: irsend_active = false; Response_P(S_JSON_COMMAND_SVALUE, command, D_JSON_PROTOCOL_NOT_SUPPORTED); From a380eb956643c3202a34a7e1923589c6033b3969 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 1 Apr 2019 16:39:13 +0200 Subject: [PATCH 41/81] Fix possible compile error Fix possible compile error --- sonoff/xdrv_05_irremote.ino | 39 ++++++++++++++++++++----------------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/sonoff/xdrv_05_irremote.ino b/sonoff/xdrv_05_irremote.ino index 9bddc3617..8b6a0de1c 100644 --- a/sonoff/xdrv_05_irremote.ino +++ b/sonoff/xdrv_05_irremote.ino @@ -81,6 +81,27 @@ void IrSendInit(void) #endif //USE_IR_HVAC } +char* IrUint64toHex(uint64_t value, char *str, uint16_t bits) +{ + ulltoa(value, str, 16); // Get 64bit value + + int fill = 8; + if ((bits > 3) && (bits < 65)) { + fill = bits / 4; // Max 16 + if (bits % 4) { fill++; } + } + int len = strlen(str); + fill -= len; + if (fill > 0) { + memmove(str + fill, str, len +1); + memset(str, '0', fill); + } + memmove(str + 2, str, strlen(str) +1); + str[0] = '0'; + str[1] = 'x'; + return str; +} + #ifdef USE_IR_RECEIVE /*********************************************************************************************\ * IR Receive @@ -105,24 +126,6 @@ void IrReceiveInit(void) // AddLog_P(LOG_LEVEL_DEBUG, PSTR("IrReceive initialized")); } -char* IrUint64toHex(uint64_t value, char *str, uint16_t bits) -{ - ulltoa(value, str, 16); // Get 64bit value - - int fill = 8; - if ((bits > 3) && (bits < 65)) { fill = bits / 4 ; } // Max 16 - int len = strlen(str); - fill -= len; - if (fill > 0) { - memmove(str + fill, str, len +1); - memset(str, '0', fill); - } - memmove(str + 2, str, strlen(str) +1); - str[0] = '0'; - str[1] = 'x'; - return str; -} - void IrReceiveCheck(void) { char sirtype[14]; // Max is AIWA_RC_T501 From 7f590e62f3e5fbec230091239040e74113e70fa1 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Mon, 1 Apr 2019 17:41:47 +0200 Subject: [PATCH 42/81] Change Spanish Argentina to Spanish Spain (#5565) Change Spanish Argentina to Spanish Spain (#5565) --- platformio.ini | 2 +- sonoff/language/{es-AR.h => es-ES.h} | 10 +++++----- sonoff/my_user_config.h | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) rename sonoff/language/{es-AR.h => es-ES.h} (99%) diff --git a/platformio.ini b/platformio.ini index 8fffc69d3..9ca59d3e8 100644 --- a/platformio.ini +++ b/platformio.ini @@ -347,7 +347,7 @@ board = ${common.board} board_build.flash_mode = ${common.board_build.flash_mode} board_build.f_cpu = ${common.board_build.f_cpu} build_unflags = ${common.build_unflags} -build_flags = ${common.build_flags} -DMY_LANGUAGE=es-AR +build_flags = ${common.build_flags} -DMY_LANGUAGE=es-ES monitor_speed = ${common.monitor_speed} upload_port = ${common.upload_port} upload_resetmethod = ${common.upload_resetmethod} diff --git a/sonoff/language/es-AR.h b/sonoff/language/es-ES.h similarity index 99% rename from sonoff/language/es-AR.h rename to sonoff/language/es-ES.h index 9aca4f417..426d829bd 100644 --- a/sonoff/language/es-AR.h +++ b/sonoff/language/es-ES.h @@ -1,5 +1,5 @@ /* - es-AR.h - localization for Spanish - Argentina for Sonoff-Tasmota + es-ES.h - localization for Spanish - Spain for Sonoff-Tasmota Copyright (C) 2019 Adrian Scillato @@ -17,8 +17,8 @@ along with this program. If not, see . */ -#ifndef _LANGUAGE_ES_AR_H_ -#define _LANGUAGE_ES_AR_H_ +#ifndef _LANGUAGE_ES_ES_H_ +#define _LANGUAGE_ES_ES_H_ /*************************** ATTENTION *******************************\ * @@ -33,7 +33,7 @@ #define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English) -#define LANGUAGE_LCID 11274 +#define LANGUAGE_LCID 1034 // HTML (ISO 639-1) Language Code #define D_HTML_LANGUAGE "es" @@ -653,4 +653,4 @@ #define D_UNIT_KWARH "kVArH" #define D_UNIT_ANGLE "Grados" -#endif // _LANGUAGE_ES_AR_H_ +#endif // _LANGUAGE_ES_ES_H_ diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 29eb632a6..5ba994a4b 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -204,7 +204,7 @@ //#define MY_LANGUAGE de-DE // German in Germany //#define MY_LANGUAGE el-GR // Greek in Greece //#define MY_LANGUAGE en-GB // English in Great Britain. Enabled by Default -//#define MY_LANGUAGE es-AR // Spanish in Argentina +//#define MY_LANGUAGE es-ES // Spanish in Spain //#define MY_LANGUAGE fr-FR // French in France //#define MY_LANGUAGE he-HE // Hebrew in Israel //#define MY_LANGUAGE hu-HU // Hungarian in Hungary From 7c31bedc9b2ea039119e0ee5bba10fe995d46d0a Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 2 Apr 2019 10:35:19 +0200 Subject: [PATCH 43/81] Fix Configure Timer Gui webinterface (#5568) Fix Configure Timer Gui webinterface (#5568) --- sonoff/xdrv_09_timers.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index 05e931254..2f11421dc 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -620,7 +620,7 @@ const char HTTP_TIMER_SCRIPT5[] PROGMEM = "function it(){" // Initialize elements and select first tab "var b,i,o,s;" "pt=eb('t0').value.split(',').map(Number);" // Get parameters from hidden area to array - "s='';for(i=0;i<" STR(MAX_TIMERS) ";i++){b='';if(0==i){b=\" id='dP'\";}s+=\"\"}" + "s='';for(i=0;i<%d;i++){b='';if(0==i){b=\" id='dP'\";}s+=\"\"}" "eb('bt').innerHTML=s;" // Create tabs "if(%d>0){" // Create Output and Action drop down boxes "eb('oa').innerHTML=\"" D_TIMER_OUTPUT " " D_TIMER_ACTION " \";" @@ -705,7 +705,7 @@ void HandleTimerConfiguration(void) #endif // USE_SUNRISE WSContentSend_P(HTTP_TIMER_SCRIPT3, devices_present); WSContentSend_P(HTTP_TIMER_SCRIPT4, devices_present); - WSContentSend_P(HTTP_TIMER_SCRIPT5, devices_present); + WSContentSend_P(HTTP_TIMER_SCRIPT5, MAX_TIMERS, devices_present); WSContentSend_P(HTTP_TIMER_SCRIPT6, devices_present); WSContentSendStyle_P(HTTP_TIMER_STYLE); WSContentSend_P(HTTP_FORM_TIMER1, (Settings.flag3.timers_enable) ? " checked" : ""); From c58b40e838ed5d52488f7c3e23180c87f7d95c1e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 2 Apr 2019 11:07:30 +0200 Subject: [PATCH 44/81] Revert "Fix Configure Timer Gui webinterface (#5568)" This reverts commit 7c31bedc9b2ea039119e0ee5bba10fe995d46d0a. --- sonoff/xdrv_09_timers.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index 2f11421dc..05e931254 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -620,7 +620,7 @@ const char HTTP_TIMER_SCRIPT5[] PROGMEM = "function it(){" // Initialize elements and select first tab "var b,i,o,s;" "pt=eb('t0').value.split(',').map(Number);" // Get parameters from hidden area to array - "s='';for(i=0;i<%d;i++){b='';if(0==i){b=\" id='dP'\";}s+=\"\"}" + "s='';for(i=0;i<" STR(MAX_TIMERS) ";i++){b='';if(0==i){b=\" id='dP'\";}s+=\"\"}" "eb('bt').innerHTML=s;" // Create tabs "if(%d>0){" // Create Output and Action drop down boxes "eb('oa').innerHTML=\"" D_TIMER_OUTPUT " " D_TIMER_ACTION " \";" @@ -705,7 +705,7 @@ void HandleTimerConfiguration(void) #endif // USE_SUNRISE WSContentSend_P(HTTP_TIMER_SCRIPT3, devices_present); WSContentSend_P(HTTP_TIMER_SCRIPT4, devices_present); - WSContentSend_P(HTTP_TIMER_SCRIPT5, MAX_TIMERS, devices_present); + WSContentSend_P(HTTP_TIMER_SCRIPT5, devices_present); WSContentSend_P(HTTP_TIMER_SCRIPT6, devices_present); WSContentSendStyle_P(HTTP_TIMER_STYLE); WSContentSend_P(HTTP_FORM_TIMER1, (Settings.flag3.timers_enable) ? " checked" : ""); From 76eec9b8ab7e06b7809ec853db31d064c99f6947 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 2 Apr 2019 11:26:55 +0200 Subject: [PATCH 45/81] Fix Configure Timer Gui webinterface (#5568) Fix Configure Timer Gui webinterface (#5568) --- sonoff/xdrv_09_timers.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index 05e931254..e9f7e6c53 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -620,7 +620,7 @@ const char HTTP_TIMER_SCRIPT5[] PROGMEM = "function it(){" // Initialize elements and select first tab "var b,i,o,s;" "pt=eb('t0').value.split(',').map(Number);" // Get parameters from hidden area to array - "s='';for(i=0;i<" STR(MAX_TIMERS) ";i++){b='';if(0==i){b=\" id='dP'\";}s+=\"\"}" + "s='';for(i=0;i<16;i++){b='';if(0==i){b=\" id='dP'\";}s+=\"\"}" "eb('bt').innerHTML=s;" // Create tabs "if(%d>0){" // Create Output and Action drop down boxes "eb('oa').innerHTML=\"" D_TIMER_OUTPUT " " D_TIMER_ACTION " \";" From 8ff2759cccabc0215e0b20abc63ac83798123f0c Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 2 Apr 2019 15:47:39 +0200 Subject: [PATCH 46/81] 6.5.0.4 Fix Configure Timer Web GUI 6.5.0.4 20190402 * Fix Configure Timer Web GUI (#5568) * Add validation check when loading settings from flash --- sonoff/_changelog.ino | 6 +++++- sonoff/settings.h | 8 ++++---- sonoff/settings.ino | 8 ++++++-- sonoff/sonoff_version.h | 2 +- sonoff/xdrv_09_timers.ino | 9 +++++++-- 5 files changed, 23 insertions(+), 10 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index 7ffe22789..abbbc40ae 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,8 @@ -/* 6.5.0.3 20190328 +/* 6.5.0.4 20190402 + * Fix Configure Timer Web GUI (#5568) + * Add validation check when loading settings from flash + * + * 6.5.0.3 20190328 * Add command Sensor20 1..255 to change Nova Fitness SDS01 working period in minutes (#5452) * Change some defines to const * Change IRsend and receive for 64-bit support (#5523) diff --git a/sonoff/settings.h b/sonoff/settings.h index 07cb646d8..329b152f4 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -185,12 +185,12 @@ struct SYSCFG { unsigned long bootcount; // 00C */ struct SYSCFG { - uint16_t cfg_holder; // 000 v6 header - uint16_t cfg_size; // 002 + uint16_t cfg_holder; // 000 v6 header + uint16_t cfg_size; // 002 unsigned long save_flag; // 004 unsigned long version; // 008 - uint16_t bootcount; // 00C - uint16_t cfg_crc; // 00E + uint16_t bootcount; // 00C + uint16_t cfg_crc; // 00E SysBitfield flag; // 010 int16_t save_data; // 014 int8_t timezone; // 016 diff --git a/sonoff/settings.ino b/sonoff/settings.ino index dcebe4512..70ab8afc9 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -460,13 +460,17 @@ void SettingsLoad(void) settings_location = 0; uint32_t flash_location = SETTINGS_LOCATION +1; + uint16_t cfg_holder = 0; for (uint8_t i = 0; i < CFG_ROTATES; i++) { flash_location--; ESP.flashRead(flash_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); bool valid = false; if (Settings.version > 0x06000000) { - valid = (Settings.cfg_crc == GetSettingsCrc()); + bool almost_valid = (Settings.cfg_crc == GetSettingsCrc()); + // Sometimes CRC on pages below FB, overwritten by OTA, is fine but Settings are still invalid. So check cfg_holder too + if (almost_valid && (0 == cfg_holder)) { cfg_holder = Settings.cfg_holder; } // At FB always active cfg_holder + valid = (cfg_holder == Settings.cfg_holder); } else { ESP.flashRead((flash_location -1) * SPI_FLASH_SEC_SIZE, (uint32*)&_SettingsH, sizeof(SYSCFGH)); valid = (Settings.cfg_holder == _SettingsH.cfg_holder); @@ -485,7 +489,7 @@ void SettingsLoad(void) } if (settings_location > 0) { ESP.flashRead(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); - AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_CONFIG D_LOADED_FROM_FLASH_AT " %X, " D_COUNT " %d"), settings_location, Settings.save_flag); + AddLog_P2(LOG_LEVEL_NONE, PSTR(D_LOG_CONFIG D_LOADED_FROM_FLASH_AT " %X, " D_COUNT " %lu"), settings_location, Settings.save_flag); } #ifndef FIRMWARE_MINIMAL diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 68c28a9d0..3a8dc0eb8 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,6 +20,6 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -const uint32_t VERSION = 0x06050003; +const uint32_t VERSION = 0x06050004; #endif // _SONOFF_VERSION_H_ diff --git a/sonoff/xdrv_09_timers.ino b/sonoff/xdrv_09_timers.ino index e9f7e6c53..36941b9f1 100644 --- a/sonoff/xdrv_09_timers.ino +++ b/sonoff/xdrv_09_timers.ino @@ -620,7 +620,12 @@ const char HTTP_TIMER_SCRIPT5[] PROGMEM = "function it(){" // Initialize elements and select first tab "var b,i,o,s;" "pt=eb('t0').value.split(',').map(Number);" // Get parameters from hidden area to array - "s='';for(i=0;i<16;i++){b='';if(0==i){b=\" id='dP'\";}s+=\"\"}" + "s='';" + "for(i=0;i<%d;i++){" + "b='';" + "if(0==i){b=\" id='dP'\";}" + "s+=\"\"" + "}" "eb('bt').innerHTML=s;" // Create tabs "if(%d>0){" // Create Output and Action drop down boxes "eb('oa').innerHTML=\"" D_TIMER_OUTPUT " " D_TIMER_ACTION " \";" @@ -705,7 +710,7 @@ void HandleTimerConfiguration(void) #endif // USE_SUNRISE WSContentSend_P(HTTP_TIMER_SCRIPT3, devices_present); WSContentSend_P(HTTP_TIMER_SCRIPT4, devices_present); - WSContentSend_P(HTTP_TIMER_SCRIPT5, devices_present); + WSContentSend_P(HTTP_TIMER_SCRIPT5, MAX_TIMERS, devices_present); WSContentSend_P(HTTP_TIMER_SCRIPT6, devices_present); WSContentSendStyle_P(HTTP_TIMER_STYLE); WSContentSend_P(HTTP_FORM_TIMER1, (Settings.flag3.timers_enable) ? " checked" : ""); From 2fd15c463370a68612aaf8c9b2e56689365bb209 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 2 Apr 2019 20:26:30 +0200 Subject: [PATCH 47/81] Fix WifiManager Pop Up when no SSID is configured (#5575) Fix WifiManager Pop Up when no SSID is configured (#5575) --- sonoff/support.ino | 7 +++---- sonoff/xdrv_01_webserver.ino | 1 + 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sonoff/support.ino b/sonoff/support.ino index cffcb4690..f060a551b 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -207,9 +207,8 @@ char* ulltoa(unsigned long long value, char *str, int radix) int i = 0; int n = 0; -/* - if (radix < 2 || radix > 36) { radix = 10; } -*/ +// if (radix < 2 || radix > 36) { radix = 10; } + do { n = value % radix; digits[i++] = (n < 10) ? (char)n+'0' : (char)n-10+'A'; @@ -396,7 +395,7 @@ bool ValidIpAddress(const char* str) { const char* p = str; - while (*p && ( (*p == '.') || (*p >= '0') || (*p <= '9') )) { p++; } + while (*p && ((*p == '.') || ((*p >= '0') && (*p <= '9')))) { p++; } return (*p == '\0'); } diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 76cdae534..771a010b1 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -2148,6 +2148,7 @@ void HandleNotFound(void) /* Redirect to captive portal if we got a request for another domain. Return true in that case so the page handler do not try to handle the request again. */ bool CaptivePortal(void) { + // Possible hostHeader: connectivitycheck.gstatic.com or 192.168.4.1 if ((WifiIsInManagerMode()) && !ValidIpAddress(WebServer->hostHeader().c_str())) { AddLog_P(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_REDIRECTED)); From 531c4fe44e5d3f0ea6b1acb9012cfabefc461e08 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 2 Apr 2019 20:53:17 +0200 Subject: [PATCH 48/81] Disable unused code Disable unused code --- sonoff/settings.ino | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/sonoff/settings.ino b/sonoff/settings.ino index 70ab8afc9..1dd8f02b0 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -176,8 +176,10 @@ const uint32_t SETTINGS_LOCATION = SPIFFS_END; // No need for SPIFFS as it uses const uint8_t CFG_ROTATES = 8; // Number of flash sectors used (handles uploads) /*********************************************************************************************\ - * EEPROM support based on EEPROM library and tuned for Tasmota + * Optional EEPROM support based on EEPROM library and tuned for Tasmota \*********************************************************************************************/ +//#define USE_EEPROM +#ifdef USE_EEPROM uint32_t eeprom_sector = SPIFFS_END; uint8_t* eeprom_data = 0; @@ -305,7 +307,7 @@ void EepromEnd(void) eeprom_size = 0; eeprom_dirty = false; } - +#endif // USE_EEPROM /********************************************************************************************/ uint16_t settings_crc = 0; @@ -372,7 +374,9 @@ void SettingsSaveAll(void) Settings.power = 0; } XsnsCall(FUNC_SAVE_BEFORE_RESTART); +#ifdef USE_EEPROM EepromCommit(); +#endif SettingsSave(0); } @@ -415,6 +419,7 @@ void SettingsSave(uint8_t rotate) Settings.cfg_size = sizeof(SYSCFG); Settings.cfg_crc = GetSettingsCrc(); +#ifdef USE_EEPROM if (SPIFFS_END == settings_location) { uint8_t* flash_buffer; flash_buffer = new uint8_t[SPI_FLASH_SEC_SIZE]; @@ -432,6 +437,10 @@ void SettingsSave(uint8_t rotate) ESP.flashEraseSector(settings_location); ESP.flashWrite(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); } +#else + ESP.flashEraseSector(settings_location); + ESP.flashWrite(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG)); +#endif // USE_EEPROM if (!stop_flash_rotate && rotate) { for (uint8_t i = 1; i < CFG_ROTATES; i++) { From 43bc2a31a37c8d649f42c3bc5509eb909c116be2 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Tue, 2 Apr 2019 21:41:52 -0300 Subject: [PATCH 49/81] Fixed Display Bug in KNX webmenu for Phys Address --- sonoff/xdrv_11_knx.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/xdrv_11_knx.ino b/sonoff/xdrv_11_knx.ino index c4111bae3..ee7e8b291 100644 --- a/sonoff/xdrv_11_knx.ino +++ b/sonoff/xdrv_11_knx.ino @@ -880,6 +880,7 @@ void HandleKNXConfiguration(void) "}" "}")); WSContentSendStyle(); + KNX_physs_addr.value = Settings.knx_physsical_addr; WSContentSend_P(HTTP_FORM_KNX, KNX_physs_addr.pa.area, KNX_physs_addr.pa.line, KNX_physs_addr.pa.member); if ( Settings.flag.knx_enabled ) { WSContentSend_P(PSTR(" checked")); } WSContentSend_P(HTTP_FORM_KNX1); From bf33e8fcd7f4ac3325f5c5c0796d8fe65dc3a835 Mon Sep 17 00:00:00 2001 From: Adrian Scillato <35405447+ascillato@users.noreply.github.com> Date: Tue, 2 Apr 2019 21:44:01 -0300 Subject: [PATCH 50/81] Update _changelog.ino --- sonoff/_changelog.ino | 1 + 1 file changed, 1 insertion(+) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index abbbc40ae..e21c7409a 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,6 +1,7 @@ /* 6.5.0.4 20190402 * Fix Configure Timer Web GUI (#5568) * Add validation check when loading settings from flash + * Fixed Display Bug in KNX webmenu for Physical Address * * 6.5.0.3 20190328 * Add command Sensor20 1..255 to change Nova Fitness SDS01 working period in minutes (#5452) From 2c286c43f13ce1a531f6cfed75c1566257fb952c Mon Sep 17 00:00:00 2001 From: Yury Sannikov Date: Tue, 2 Apr 2019 21:16:50 -0400 Subject: [PATCH 51/81] Fix Sensor15 command crash due to the wrong memory specifier --- sonoff/xsns_15_mhz19.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xsns_15_mhz19.ino b/sonoff/xsns_15_mhz19.ino index 00f272a55..5978ba058 100644 --- a/sonoff/xsns_15_mhz19.ino +++ b/sonoff/xsns_15_mhz19.ino @@ -71,8 +71,8 @@ TasmotaSerial *MhzSerial; const char kMhzModels[] PROGMEM = "|B"; -const char ABC_ENABLED[] PROGMEM = "ABC is Enabled"; -const char ABC_DISABLED[] PROGMEM = "ABC is Enabled"; +const char ABC_ENABLED[] = "ABC is Enabled"; +const char ABC_DISABLED[] = "ABC is Disabled"; enum MhzCommands { MHZ_CMND_READPPM, MHZ_CMND_ABCENABLE, MHZ_CMND_ABCDISABLE, MHZ_CMND_ZEROPOINT, MHZ_CMND_RESET, MHZ_CMND_RANGE_1000, MHZ_CMND_RANGE_2000, MHZ_CMND_RANGE_3000, MHZ_CMND_RANGE_5000 }; const uint8_t kMhzCommands[][4] PROGMEM = { From f455b738a5124b17883d74d11a8aefb29616a831 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Wed, 3 Apr 2019 10:28:13 +0200 Subject: [PATCH 52/81] QFix for core 2.3.0 compile error on strtoull QFix for core 2.3.0 compile error on strtoull --- sonoff/support.ino | 83 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/sonoff/support.ino b/sonoff/support.ino index f060a551b..388ebacfc 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -123,6 +123,89 @@ size_t strcspn(const char *str1, const char *str2) } return ret; } + +/* + * Convert a string to an unsigned long long integer. + * + * Assumes that the upper and lower case + * alphabets and digits are each contiguous. + * https://opensource.apple.com/source/Libc/Libc-583/stdlib/FreeBSD/strtoull.c + */ + +#ifndef __LONG_LONG_MAX__ +#define __LONG_LONG_MAX__ 9223372036854775807LL +#endif +#undef ULLONG_MAX +#define ULLONG_MAX (__LONG_LONG_MAX__ * 2ULL + 1) + +unsigned long long strtoull(const char *__restrict nptr, char **__restrict endptr, int base) +{ + const char *s; + unsigned long long acc; + char c; + unsigned long long cutoff; + int neg, any, cutlim; + + /* + * See strtoq for comments as to the logic used. + */ + s = nptr; + do { + c = *s++; + } while (isspace((unsigned char)c)); + if (c == '-') { + neg = 1; + c = *s++; + } else { + neg = 0; + if (c == '+') + c = *s++; + } + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + acc = any = 0; + if (base < 2 || base > 36) + goto noconv; + + cutoff = ULLONG_MAX / base; + cutlim = ULLONG_MAX % base; + for ( ; ; c = *s++) { + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'Z') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'z') + c -= 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = ULLONG_MAX; + } else if (!any) { +noconv: + uint8_t dummy = 0; + } else if (neg) + acc = -acc; + if (endptr != nullptr) + *endptr = (char *)(any ? s - 1 : nptr); + return (acc); +} + #endif // ARDUINO_ESP8266_RELEASE_2_3_0 // Get span until single character in string From ce4e9b0e30101b5d571772e1b7ef97d0c7023eaf Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Thu, 4 Apr 2019 17:52:14 +0200 Subject: [PATCH 53/81] Add stable strtoull to core 2.3.0 Add stable strtoull to core 2.3.0 --- sonoff/support.ino | 134 +++++++++++++++++++++------------------------ 1 file changed, 61 insertions(+), 73 deletions(-) diff --git a/sonoff/support.ino b/sonoff/support.ino index 388ebacfc..1a222686c 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -108,7 +108,7 @@ void* memchr(const void* ptr, int value, size_t num) return 0; } -// http://clc-wiki.net/wiki/C_standard_library:string.h:strspn +// http://clc-wiki.net/wiki/C_standard_library:string.h:strcspn // Get span until any character in string size_t strcspn(const char *str1, const char *str2) { @@ -124,88 +124,76 @@ size_t strcspn(const char *str1, const char *str2) return ret; } -/* - * Convert a string to an unsigned long long integer. - * - * Assumes that the upper and lower case - * alphabets and digits are each contiguous. - * https://opensource.apple.com/source/Libc/Libc-583/stdlib/FreeBSD/strtoull.c - */ - +// https://opensource.apple.com/source/Libc/Libc-583/stdlib/FreeBSD/strtoull.c +// Convert a string to an unsigned long long integer #ifndef __LONG_LONG_MAX__ #define __LONG_LONG_MAX__ 9223372036854775807LL #endif -#undef ULLONG_MAX +#ifndef ULLONG_MAX #define ULLONG_MAX (__LONG_LONG_MAX__ * 2ULL + 1) +#endif unsigned long long strtoull(const char *__restrict nptr, char **__restrict endptr, int base) { - const char *s; - unsigned long long acc; - char c; - unsigned long long cutoff; - int neg, any, cutlim; + const char *s = nptr; + char c; + do { c = *s++; } while (isspace((unsigned char)c)); // Trim leading spaces - /* - * See strtoq for comments as to the logic used. - */ - s = nptr; - do { - c = *s++; - } while (isspace((unsigned char)c)); - if (c == '-') { - neg = 1; - c = *s++; - } else { - neg = 0; - if (c == '+') - c = *s++; - } - if ((base == 0 || base == 16) && - c == '0' && (*s == 'x' || *s == 'X')) { - c = s[1]; - s += 2; - base = 16; - } - if (base == 0) - base = c == '0' ? 8 : 10; - acc = any = 0; - if (base < 2 || base > 36) - goto noconv; + int neg = 0; + if (c == '-') { // Set minus flag and/or skip sign + neg = 1; + c = *s++; + } else { + if (c == '+') { + c = *s++; + } + } - cutoff = ULLONG_MAX / base; - cutlim = ULLONG_MAX % base; - for ( ; ; c = *s++) { - if (c >= '0' && c <= '9') - c -= '0'; - else if (c >= 'A' && c <= 'Z') - c -= 'A' - 10; - else if (c >= 'a' && c <= 'z') - c -= 'a' - 10; - else - break; - if (c >= base) - break; - if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) - any = -1; - else { - any = 1; - acc *= base; - acc += c; - } - } - if (any < 0) { - acc = ULLONG_MAX; - } else if (!any) { -noconv: - uint8_t dummy = 0; - } else if (neg) - acc = -acc; - if (endptr != nullptr) - *endptr = (char *)(any ? s - 1 : nptr); - return (acc); + if ((base == 0 || base == 16) && (c == '0') && (*s == 'x' || *s == 'X')) { // Set Hexadecimal + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) { base = (c == '0') ? 8 : 10; } // Set Octal or Decimal + + unsigned long long acc = 0; + int any = 0; + if (base > 1 && base < 37) { + unsigned long long cutoff = ULLONG_MAX / base; + int cutlim = ULLONG_MAX % base; + for ( ; ; c = *s++) { + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'Z') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'z') + c -= 'a' - 10; + else + break; + + if (c >= base) + break; + + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = ULLONG_MAX; // Range error + } + else if (any && neg) { + acc = -acc; + } + } + + if (endptr != nullptr) { *endptr = (char *)(any ? s - 1 : nptr); } + + return acc; } - #endif // ARDUINO_ESP8266_RELEASE_2_3_0 // Get span until single character in string From 82ef09b684fd62935f8fba7e82280724e909e56e Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Fri, 5 Apr 2019 08:41:26 +0200 Subject: [PATCH 54/81] Make MI Desk Lamp default off Mi Desk Lamp can be activated in my_user_config.h by setting uncommenting //#define ROTARY_V1 --- sonoff/my_user_config.h | 1 + sonoff/sonoff.ino | 4 ++++ sonoff/sonoff_template.h | 4 ++++ sonoff/support_rotary.ino | 6 ++++-- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 5ba994a4b..6e62e3031 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -369,6 +369,7 @@ #define TUYA_DIMMER_ID 0 // Default dimmer Id #define USE_ARMTRONIX_DIMMERS // Add support for Armtronix Dimmers (+1k4 code) #define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer +//#define ROTARY_V1 // Add support for MI Desk Lamp //#define USE_AZ7798 // Add support for AZ-Instrument 7798 CO2 datalogger (+1k6 code) //#define USE_PN532_HSU // Add support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem) // #define USE_PN532_CAUSE_EVENTS // Cause event execution for PN532_UID= and PN532_DATA=[if defined] (+ 30 bytes code) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index e85a26af2..c53510ada 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -2507,7 +2507,9 @@ void GpioInit(void) ButtonInit(); SwitchInit(); +#ifdef ROTARY_V1 RotaryInit(); +#endif #ifdef USE_WS2812 if (!light_type && (pin[GPIO_WS2812] < 99)) { // RGB led @@ -2700,7 +2702,9 @@ void loop(void) ButtonLoop(); SwitchLoop(); +#ifdef ROTARY_V1 RotaryLoop(); +#endif if (TimeReached(state_50msecond)) { SetNextTimeInterval(state_50msecond, 50); diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index b50c2184b..fbe5cd931 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -583,10 +583,12 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_SM16716_DAT, // SM16716 DATA GPIO_SM16716_SEL, // SM16716 SELECT #endif // USE_SM16716 +#ifdef ROTARY_V1 GPIO_ROT1A, // Rotary switch1 A Pin GPIO_ROT1B, // Rotary switch1 B Pin GPIO_ROT2A, // Rotary switch2 A Pin GPIO_ROT2B, // Rotary switch2 B Pin +#endif GPIO_ARIRFRCV, // AliLux RF Receive input #ifdef USE_HRE GPIO_HRE_CLOCK, @@ -656,7 +658,9 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { ARILUX_LC11, ZENGGE_ZF_WF017, HUAFAN_SS, +#ifdef ROTARY_V1 MI_DESK_LAMP, +#endif KMC_70011, AILIGHT, // Light Bulbs PHILIPS, diff --git a/sonoff/support_rotary.ino b/sonoff/support_rotary.ino index db88d8378..c04889a3f 100644 --- a/sonoff/support_rotary.ino +++ b/sonoff/support_rotary.ino @@ -17,8 +17,7 @@ along with this program. If not, see . */ -#define ROTARY_V1 -#ifdef ROTARY_V1 + /*********************************************************************************************\ * Rotary support \*********************************************************************************************/ @@ -31,6 +30,9 @@ uint8_t rotary_last_position = 128; uint8_t interrupts_in_use = 0; uint8_t rotary_changed = 0; +//#define ROTARY_V1 +#ifdef ROTARY_V1 + /********************************************************************************************/ void update_position(void) From 5e1cbcf94fc10f338b1d95258a0b7019df8d5e79 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 5 Apr 2019 15:27:06 +0200 Subject: [PATCH 55/81] Make MI Desk Lamp optional Make MI Desk Lamp optional --- sonoff/my_user_config.h | 2 +- sonoff/sonoff.ino | 59 +++++++++++++++++++----------------- sonoff/sonoff_template.h | 8 ++--- sonoff/support.ino | 10 ++++++ sonoff/xdrv_01_webserver.ino | 4 +-- 5 files changed, 48 insertions(+), 35 deletions(-) diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 6e62e3031..407a25c13 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -369,7 +369,7 @@ #define TUYA_DIMMER_ID 0 // Default dimmer Id #define USE_ARMTRONIX_DIMMERS // Add support for Armtronix Dimmers (+1k4 code) #define USE_PS_16_DZ // Add support for PS-16-DZ Dimmer -//#define ROTARY_V1 // Add support for MI Desk Lamp +//#define ROTARY_V1 // Add support for MI Desk Lamp //#define USE_AZ7798 // Add support for AZ-Instrument 7798 CO2 datalogger (+1k6 code) //#define USE_PN532_HSU // Add support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem) // #define USE_PN532_CAUSE_EVENTS // Cause event execution for PN532_UID= and PN532_DATA=[if defined] (+ 30 bytes code) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index c53510ada..d87aba99b 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -874,35 +874,40 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) } else if (CMND_MODULE == command_code) { if ((payload >= 0) && (payload <= MAXMODULE)) { - if (0 == payload) { payload = 256; } - payload--; - Settings.last_module = Settings.module; - Settings.module = payload; - SetModuleType(); - if (Settings.last_module != payload) { - for (uint8_t i = 0; i < sizeof(Settings.my_gp); i++) { - Settings.my_gp.io[i] = GPIO_NONE; - } + bool present = false; + if (0 == payload) { + payload = 255; + present = true; + } else { + payload--; + present = ValidModule(payload); + } + if (present) { + Settings.last_module = Settings.module; + Settings.module = payload; + SetModuleType(); + if (Settings.last_module != payload) { + for (uint8_t i = 0; i < sizeof(Settings.my_gp); i++) { + Settings.my_gp.io[i] = GPIO_NONE; + } + } + restart_flag = 2; } - restart_flag = 2; } Response_P(S_JSON_COMMAND_NVALUE_SVALUE, command, ModuleNr(), ModuleName().c_str()); } else if (CMND_MODULES == command_code) { - for (uint8_t i = 0; i <= MAXMODULE; i++) { + uint8_t midx = USER_MODULE; + for (uint8_t i = 0; i <= sizeof(kModuleNiceList); i++) { + if (i > 0) { midx = pgm_read_byte(kModuleNiceList + i -1); } if (!jsflg) { Response_P(PSTR("{\"" D_CMND_MODULES "%d\":["), lines); } else { ResponseAppend_P(PSTR(",")); } jsflg = true; - uint8_t j = i; - if (0 == i) { j = USER_MODULE; } else { j--; } - -// ResponseAppend_P(PSTR("\"%d (%s)\""), i, AnyModuleName(j).c_str()); -// if ((strlen(mqtt_data) > (LOGSZ - TOPSZ)) || (i == MAXMODULE)) { - - if ((ResponseAppend_P(PSTR("\"%d (%s)\""), i, AnyModuleName(j).c_str()) > (LOGSZ - TOPSZ)) || (i == MAXMODULE)) { + uint8_t j = i ? midx +1 : 0; + if ((ResponseAppend_P(PSTR("\"%d (%s)\""), j, AnyModuleName(midx).c_str()) > (LOGSZ - TOPSZ)) || (i == sizeof(kModuleNiceList))) { ResponseAppend_P(PSTR("]}")); MqttPublishPrefixTopic_P(RESULT_OR_STAT, type); jsflg = false; @@ -957,10 +962,6 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) ResponseAppend_P(PSTR(",")); } jsflg = true; - -// ResponseAppend_P(PSTR("\"%d (%s)\""), midx, GetTextIndexed(stemp1, sizeof(stemp1), midx, kSensorNames)); -// if ((strlen(mqtt_data) > (LOGSZ - TOPSZ)) || (i == sizeof(kGpioNiceList) -1)) { - if ((ResponseAppend_P(PSTR("\"%d (%s)\""), midx, GetTextIndexed(stemp1, sizeof(stemp1), midx, kSensorNames)) > (LOGSZ - TOPSZ)) || (i == sizeof(kGpioNiceList) -1)) { ResponseAppend_P(PSTR("]}")); MqttPublishPrefixTopic_P(RESULT_OR_STAT, type); @@ -2324,9 +2325,11 @@ void GpioInit(void) { uint8_t mpin; - if ((Settings.module >= MAXMODULE) && (Settings.module < USER_MODULE)) { - Settings.module = MODULE; - Settings.last_module = MODULE; + if (!ValidModule(Settings.module)) { + uint8_t module = MODULE; + if (!ValidModule(MODULE)) { module = SONOFF_BASIC; } + Settings.module = module; + Settings.last_module = module; } SetModuleType(); @@ -2509,7 +2512,7 @@ void GpioInit(void) SwitchInit(); #ifdef ROTARY_V1 RotaryInit(); -#endif +#endif #ifdef USE_WS2812 if (!light_type && (pin[GPIO_WS2812] < 99)) { // RGB led @@ -2702,9 +2705,9 @@ void loop(void) ButtonLoop(); SwitchLoop(); -#ifdef ROTARY_V1 +#ifdef ROTARY_V1 RotaryLoop(); -#endif +#endif if (TimeReached(state_50msecond)) { SetNextTimeInterval(state_50msecond, 50); diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index fbe5cd931..1461e0370 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -588,15 +588,15 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_ROT1B, // Rotary switch1 B Pin GPIO_ROT2A, // Rotary switch2 A Pin GPIO_ROT2B, // Rotary switch2 B Pin -#endif +#endif GPIO_ARIRFRCV, // AliLux RF Receive input #ifdef USE_HRE GPIO_HRE_CLOCK, GPIO_HRE_DATA -#endif +#endif }; -const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { +const uint8_t kModuleNiceList[] PROGMEM = { SONOFF_BASIC, // Sonoff Relay Devices SONOFF_RF, SONOFF_TH, @@ -660,7 +660,7 @@ const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = { HUAFAN_SS, #ifdef ROTARY_V1 MI_DESK_LAMP, -#endif +#endif KMC_70011, AILIGHT, // Light Bulbs PHILIPS, diff --git a/sonoff/support.ino b/sonoff/support.ino index 1a222686c..d9fe3ed7a 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -846,6 +846,16 @@ uint8_t ModuleNr() return (USER_MODULE == Settings.module) ? 0 : Settings.module +1; } +bool ValidModule(uint8_t index) +{ + for (uint8_t i = 0; i < sizeof(kModuleNiceList); i++) { + if (index == pgm_read_byte(kModuleNiceList + i)) { + return true; + } + } + return false; +} + String AnyModuleName(uint8_t index) { if (USER_MODULE == index) { diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 771a010b1..33391287f 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -1038,7 +1038,7 @@ void HandleTemplateConfiguration(void) if (WebServer->hasArg("m")) { WSContentBegin(200, CT_PLAIN); - for (uint8_t i = 0; i < MAXMODULE; i++) { // "}2'%d'>%s (%d)}3" - "}2'0'>Sonoff Basic (1)}3" + for (uint8_t i = 0; i < sizeof(kModuleNiceList); i++) { // "}2'%d'>%s (%d)}3" - "}2'0'>Sonoff Basic (1)}3" uint8_t midx = pgm_read_byte(kModuleNiceList + i); WSContentSend_P(HTTP_MODULE_TEMPLATE_REPLACE, midx, AnyModuleName(midx).c_str(), midx +1); } @@ -1159,7 +1159,7 @@ void HandleModuleConfiguration(void) if (WebServer->hasArg("m")) { WSContentBegin(200, CT_PLAIN); uint8_t vidx = 0; - for (uint8_t i = 0; i <= MAXMODULE; i++) { // "}2'%d'>%s (%d)}3" - "}2'255'>UserTemplate (0)}3" - "}2'0'>Sonoff Basic (1)}3" + for (uint8_t i = 0; i <= sizeof(kModuleNiceList); i++) { // "}2'%d'>%s (%d)}3" - "}2'255'>UserTemplate (0)}3" - "}2'0'>Sonoff Basic (1)}3" if (0 == i) { midx = USER_MODULE; vidx = 0; From c673ea17287104e3dc49e0510b8561f53aff18c9 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 5 Apr 2019 15:41:01 +0200 Subject: [PATCH 56/81] Make MI Desk Lamp optional Make MI Desk Lamp optional --- sonoff/sonoff.ino | 7 +++++-- sonoff/support.ino | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index d87aba99b..741743618 100755 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -978,8 +978,11 @@ void MqttDataHandler(char* topic, uint8_t* data, unsigned int data_len) if (strstr(dataBuf, "{") == nullptr) { // If no JSON it must be parameter if ((payload > 0) && (payload <= MAXMODULE)) { - ModuleDefault(payload -1); // Copy template module - if (USER_MODULE == Settings.module) { restart_flag = 2; } + payload--; + if (ValidModule(payload)) { + ModuleDefault(payload); // Copy template module + if (USER_MODULE == Settings.module) { restart_flag = 2; } + } } else if (0 == payload) { // Copy current template to user template if (Settings.module != USER_MODULE) { diff --git a/sonoff/support.ino b/sonoff/support.ino index d9fe3ed7a..51c895905 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -1023,8 +1023,8 @@ bool JsonTemplate(const char* dataBuf) } if (obj[D_JSON_BASE].success()) { uint8_t base = obj[D_JSON_BASE]; - if ((0 == base) || (base >= MAXMODULE)) { base = 17; } else { base--; } - Settings.user_template_base = base; // Default WEMOS + if ((0 == base) || !ValidModule(base -1)) { base = 18; } + Settings.user_template_base = base -1; // Default WEMOS } return true; } From 03f76a4a9779156543a7727549a6c2e795f1e16e Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Fri, 5 Apr 2019 17:46:26 +0200 Subject: [PATCH 57/81] Tune templates Tune templates --- sonoff/sonoff_template.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 1461e0370..947ee2667 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -466,7 +466,9 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_DHT11, // DHT11 GPIO_DHT22, // DHT21, DHT22, AM2301, AM2302, AM2321 GPIO_SI7021, // iTead SI7021 +#if defined(USE_DS18B20) || defined(USE_DS18x20) || defined(USE_DS18x20_LEGACY) GPIO_DSB, // Single wire DS18B20 or DS18S20 +#endif #ifdef USE_WS2812 GPIO_WS2812, // WS2812 Led string #endif @@ -589,7 +591,9 @@ const uint8_t kGpioNiceList[] PROGMEM = { GPIO_ROT2A, // Rotary switch2 A Pin GPIO_ROT2B, // Rotary switch2 B Pin #endif +#ifdef USE_ARILUX_RF GPIO_ARIRFRCV, // AliLux RF Receive input +#endif #ifdef USE_HRE GPIO_HRE_CLOCK, GPIO_HRE_DATA @@ -648,9 +652,15 @@ const uint8_t kModuleNiceList[] PROGMEM = { OBI2, MANZOKU_EU_4, ESP_SWITCH, // Switch Devices +#ifdef USE_TUYA_DIMMER TUYA_DIMMER, // Dimmer Devices +#endif +#ifdef USE_ARMTRONIX_DIMMERS ARMTRONIX_DIMMERS, +#endif +#ifdef USE_PS_16_DZ PS_16_DZ, +#endif H801, // Light Devices MAGICHOME, ARILUX_LC01, From 148192b80dad2dbad2aee7a60d3678a3bf633a59 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 6 Apr 2019 13:39:59 +0200 Subject: [PATCH 58/81] Attempt to fix MQTT reconnects Attempt to fix MQTT reconnects --- sonoff/xdrv_02_mqtt.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index b7daa1f34..28f32c183 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -822,7 +822,7 @@ bool Xdrv02(uint8_t function) if (Settings.flag.mqtt_enabled) { switch (function) { - case FUNC_LOOP: + case FUNC_EVERY_100_MSECOND: // https://github.com/knolleary/pubsubclient/issues/556 if (MqttIsConnected()) { MqttClient.loop(); } break; #ifdef USE_WEBSERVER From 756400de195a5d5d979583b44c9bdc2db2525432 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 6 Apr 2019 15:22:25 +0200 Subject: [PATCH 59/81] Attempt to fix MQTT reconnects while keeping good response Attempt to fix MQTT reconnects while keeping good response --- sonoff/xdrv_02_mqtt.ino | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sonoff/xdrv_02_mqtt.ino b/sonoff/xdrv_02_mqtt.ino index 28f32c183..8ef49a54a 100644 --- a/sonoff/xdrv_02_mqtt.ino +++ b/sonoff/xdrv_02_mqtt.ino @@ -822,8 +822,8 @@ bool Xdrv02(uint8_t function) if (Settings.flag.mqtt_enabled) { switch (function) { - case FUNC_EVERY_100_MSECOND: // https://github.com/knolleary/pubsubclient/issues/556 - if (MqttIsConnected()) { MqttClient.loop(); } + case FUNC_EVERY_50_MSECOND: // https://github.com/knolleary/pubsubclient/issues/556 + MqttClient.loop(); break; #ifdef USE_WEBSERVER case FUNC_WEB_ADD_BUTTON: From 43a61b3e249dbea13eebe10c94fb2651921040e0 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Sat, 6 Apr 2019 18:25:26 +0200 Subject: [PATCH 60/81] 6.5.0.5 Add compile time GUI color options 6.5.0.5 20190406 * Add compile time GUI color options (#5586) --- sonoff/_changelog.ino | 5 ++- sonoff/my_user_config.h | 26 +++++++++++++++ sonoff/sonoff_version.h | 2 +- sonoff/xdrv_01_webserver.ino | 65 ++++++++++++++++++++++++++++-------- sonoff/xdrv_09_timers.ino | 19 +++++++++-- 5 files changed, 98 insertions(+), 19 deletions(-) diff --git a/sonoff/_changelog.ino b/sonoff/_changelog.ino index e21c7409a..95d065ccb 100644 --- a/sonoff/_changelog.ino +++ b/sonoff/_changelog.ino @@ -1,4 +1,7 @@ -/* 6.5.0.4 20190402 +/* 6.5.0.5 20190406 + * Add compile time GUI color options (#5586) + * + * 6.5.0.4 20190402 * Fix Configure Timer Web GUI (#5568) * Add validation check when loading settings from flash * Fixed Display Bug in KNX webmenu for Physical Address diff --git a/sonoff/my_user_config.h b/sonoff/my_user_config.h index 407a25c13..97a43836f 100644 --- a/sonoff/my_user_config.h +++ b/sonoff/my_user_config.h @@ -257,6 +257,32 @@ #define WEB_USERNAME "admin" // Web server Admin mode user name #define USE_EMULATION // Enable Belkin WeMo and Hue Bridge emulation for Alexa (+16k code, +2k mem) +// Black text on white/greyish background (default) + #define COLOR_TEXT "#000" // Global text color - Black + #define COLOR_BACKGROUND "#fff" // Global background color - White + #define COLOR_FORM "#f2f2f2" // Form background color - Greyish + +// White text on black/greyish background (alternative) +// #define COLOR_TEXT "#fff" // Global text color - White +// #define COLOR_BACKGROUND "#000" // Global background color - Black +// #define COLOR_FORM "#4f4f4f" // Form background color - Greyish + + #define COLOR_TEXT_WARNING "red" // Warning text color - Red + #define COLOR_TEXT_SUCCESS "green" // Success text color - Green + + #define COLOR_BUTTON_TEXT "#fff" // Button text color - White + #define COLOR_BUTTON "#1fa3ec" // Button color - Blueish + #define COLOR_BUTTON_HOVER "#0e70a4" // Button color when hovered over - Darker blueish + #define COLOR_BUTTON_RESET "#d43535" // Restart/Reset/Delete button color - Redish + #define COLOR_BUTTON_RESET_HOVER "#931f1f" // Restart/Reset/Delete button color when hovered over - Darker redish + #define COLOR_BUTTON_SAVE "#47c266" // Save button color - Greenish + #define COLOR_BUTTON_SAVE_HOVER "#5aaf6f" // Save button color when hovered over - Darker greenish + + #define COLOR_TIMER_TAB_TEXT "#fff" // Config timer tab text color - White + #define COLOR_TIMER_TAB_BACKGROUND "#999" // Config timer tab background color - Light grey + #define COLOR_TIMER_ACTIVE_TAB_TEXT "#000" // Config timer active tab text color - Black + #define COLOR_TIMER_ACTIVE_TAB_BG "transparent" // Config timer active tab text color - Transparent (= COLOR_FORM) + // -- mDNS ---------------------------------------- #define USE_DISCOVERY // Enable mDNS for the following services (+8k code, +0.3k mem) #define WEBSERVER_ADVERTISE // Provide access to webserver by name .local/ diff --git a/sonoff/sonoff_version.h b/sonoff/sonoff_version.h index 3a8dc0eb8..c43d2d6d3 100644 --- a/sonoff/sonoff_version.h +++ b/sonoff/sonoff_version.h @@ -20,6 +20,6 @@ #ifndef _SONOFF_VERSION_H_ #define _SONOFF_VERSION_H_ -const uint32_t VERSION = 0x06050004; +const uint32_t VERSION = 0x06050005; #endif // _SONOFF_VERSION_H_ diff --git a/sonoff/xdrv_01_webserver.ino b/sonoff/xdrv_01_webserver.ino index 33391287f..ff5672093 100644 --- a/sonoff/xdrv_01_webserver.ino +++ b/sonoff/xdrv_01_webserver.ino @@ -31,6 +31,43 @@ #define WIFI_SOFT_AP_CHANNEL 1 // Soft Access Point Channel number between 1 and 11 as used by SmartConfig web GUI #endif +#ifndef COLOR_TEXT_WARNING +#define COLOR_TEXT_WARNING "red" // Warning text color - Red +#endif +#ifndef COLOR_TEXT_SUCCESS +#define COLOR_TEXT_SUCCESS "green" // Success text color - Green +#endif +#ifndef COLOR_TEXT +#define COLOR_TEXT "#000" // Global text color - Black +#endif +#ifndef COLOR_BACKGROUND +#define COLOR_BACKGROUND "#fff" // Global background color - White +#endif +#ifndef COLOR_FORM +#define COLOR_FORM "#f2f2f2" // Form background color - Greyish +#endif +#ifndef COLOR_BUTTON_TEXT +#define COLOR_BUTTON_TEXT "#fff" // Button text color - White +#endif +#ifndef COLOR_BUTTON +#define COLOR_BUTTON "#1fa3ec" // Button color - Blueish +#endif +#ifndef COLOR_BUTTON_HOVER +#define COLOR_BUTTON_HOVER "#0e70a4" // Button color when hovered over - Darker blueish +#endif +#ifndef COLOR_BUTTON_RESET +#define COLOR_BUTTON_RESET "#d43535" // Restart/Reset/Delete button color - Redish +#endif +#ifndef COLOR_BUTTON_RESET_HOVER +#define COLOR_BUTTON_RESET_HOVER "#931f1f" // Restart/Reset/Delete button color when hovered over - Darker redish +#endif +#ifndef COLOR_BUTTON_SAVE +#define COLOR_BUTTON_SAVE "#47c266" // Save button color - Greenish +#endif +#ifndef COLOR_BUTTON_SAVE_HOVER +#define COLOR_BUTTON_SAVE_HOVER "#5aaf6f" // Save button color when hovered over - Darker greenish +#endif + const uint16_t CHUNKED_BUFFER_SIZE = 400; // Chunk buffer size (should be smaller than half mqtt_date size) const uint16_t HTTP_REFRESH_TIME = 2345; // milliseconds @@ -239,21 +276,21 @@ const char HTTP_HEAD_STYLE1[] PROGMEM = "