diff --git a/README.md b/README.md index 7e4765b90..576b8d641 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ## Sonoff-Tasmota Provide ESP8266 based Sonoff by [iTead Studio](https://www.itead.cc/) and ElectroDragon IoT Relay with Serial, Web and MQTT control allowing 'Over the Air' or OTA firmware updates using Arduino IDE. -Current version is **4.1.0** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/_releasenotes.ino) for change information. +Current version is **4.1.1** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/_releasenotes.ino) for change information. - This version provides all (Sonoff) modules in one file and starts up with Sonoff Basic. - Once uploaded select module using the configuration webpage or the commands ```Modules``` and ```Module```. diff --git a/api/arduino/sonoff-minimal.ino.bin b/api/arduino/sonoff-minimal.ino.bin index 18dcf1b0a..c6521482c 100644 Binary files a/api/arduino/sonoff-minimal.ino.bin and b/api/arduino/sonoff-minimal.ino.bin differ diff --git a/api/arduino/sonoff.ino.bin b/api/arduino/sonoff.ino.bin index e51b7fb5e..dcb2b7dae 100644 Binary files a/api/arduino/sonoff.ino.bin and b/api/arduino/sonoff.ino.bin differ diff --git a/sonoff/_releasenotes.ino b/sonoff/_releasenotes.ino index 0a64af3f5..dfc95579d 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,4 +1,20 @@ -/* 4.1.0 20170325 +/* 4.1.1 20170329 + * Fix default Telemetry for command Prefix3 + * Fix webserver Module parameters for disabled select + * Fix sensor status for enabled switches + * Remove Light as alternative for Power (save code space) + * Remove migration option from pre V3 (code cleanup) + * Remove unofficial SPIFFS support (code cleanup) + * Remove command list when unknown command is entered (save code space) + * Rename Status11 json from StatusPWR to unique StatusSTS + * Rename command Gateway to IPAddres2, Subnetmask to IPAddress3 and DnsServer to IPAddress4 (save code space) + * Add Command MqttResponse to select either command or RESULT topic as response (#258) + * Add command StateText1 to StateText3 to assign MQTT_STATUS_OFF, MQTT_STATUS_ON and MQTT_CMND_TOGGLE respectively (#286) + * Remove restart after IPAddress changes (#292) + * Add support for MAX31850 in xsns_ds18x20.ino (#295) + * Fix possible uptime update misses (#302) + * + * 4.1.0 20170325 * Change static IP addresses in user_config.h from list (using commas) to string (using dots) * Unify display result of commands Modules, Module and Gpios * Rewrite Module selection web page to bring size down from 18651 to 4319 bytes (!) (#234, #240) diff --git a/sonoff/settings.h b/sonoff/settings.h index 0921305b9..1f8d02985 100644 --- a/sonoff/settings.h +++ b/sonoff/settings.h @@ -2,76 +2,6 @@ * Config settings \*********************************************************************************************/ -#ifdef ALLOW_MIGRATE_TO_V3 -struct SYSCFG2 { // Version 2.x (old) - unsigned long cfg_holder; - unsigned long saveFlag; - unsigned long version; - byte seriallog_level; - byte syslog_level; - char syslog_host[32]; - char sta_ssid1[32]; - char sta_pwd1[64]; - char otaUrl[80]; - char mqtt_host[32]; - char mqtt_grptopic[32]; - char mqtt_topic[32]; - char mqtt_topic2[32]; - char mqtt_subtopic[32]; - int8_t timezone; - uint8_t power; - uint8_t ledstate; - uint16_t mqtt_port; - char mqtt_client[33]; - char mqtt_user[33]; - char mqtt_pwd[33]; - uint8_t webserver; - unsigned long bootcount; - char hostname[33]; - uint16_t syslog_port; - byte weblog_level; - uint16_t tele_period; - uint8_t sta_config; - int16_t savedata; - byte model; - byte mqtt_retain; - byte savestate; - unsigned long hlw_pcal; - unsigned long hlw_ucal; - unsigned long hlw_ical; - unsigned long hlw_kWhyesterday; - byte value_units; - uint16_t hlw_pmin; - uint16_t hlw_pmax; - uint16_t hlw_umin; - uint16_t hlw_umax; - uint16_t hlw_imin; - uint16_t hlw_imax; - uint16_t hlw_mpl; // MaxPowerLimit - uint16_t hlw_mplh; // MaxPowerLimitHold - uint16_t hlw_mplw; // MaxPowerLimitWindow - uint16_t hlw_mspl; // MaxSafePowerLimit - uint16_t hlw_msplh; // MaxSafePowerLimitHold - uint16_t hlw_msplw; // MaxSafePowerLimitWindow - uint16_t hlw_mkwh; // MaxEnergy - uint16_t hlw_mkwhs; // MaxEnergyStart - char domoticz_in_topic[33]; - char domoticz_out_topic[33]; - uint16_t domoticz_update_timer; - unsigned long domoticz_relay_idx[4]; - unsigned long domoticz_key_idx[4]; - byte message_format; // Not used since 3.2.6a - unsigned long hlw_kWhtoday; - uint16_t hlw_kWhdoy; - uint8_t switchmode; - char mqtt_fingerprint[60]; - byte sta_active; - char sta_ssid2[33]; - char sta_pwd2[65]; - -} sysCfg2; -#endif // ALLOW_MIGRATE_TO_V3 - struct SYSCFG { unsigned long cfg_holder; unsigned long saveFlag; @@ -80,7 +10,7 @@ struct SYSCFG { byte migflg; // Not used since 3.9.1 int16_t savedata; byte savestate; - byte model; // Not used since 3.9.1 + byte mqtt_response; // was model until 3.9.1 int8_t timezone; char otaUrl[101]; @@ -108,7 +38,7 @@ struct SYSCFG { char mqtt_topic[33]; char button_topic[33]; char mqtt_grptopic[33]; - char mqtt_subtopic[33]; + char state_text[3][11]; // was ex_mqtt_subtopic[33] until 4.1.1 byte mqtt_button_retain; byte mqtt_power_retain; byte value_units; @@ -212,7 +142,6 @@ struct SYSCFG { uint16_t pwmvalue[5]; // 4.0.9 -// uint8_t ip_address[4][4]; uint32_t ip_address[4]; } sysCfg; diff --git a/sonoff/settings.ino b/sonoff/settings.ino index b249d0e6e..036a3b238 100644 --- a/sonoff/settings.ino +++ b/sonoff/settings.ino @@ -114,12 +114,6 @@ extern "C" { #define SPIFFS_START ((uint32_t)&_SPIFFS_start - 0x40200000) / SPI_FLASH_SEC_SIZE #define SPIFFS_END ((uint32_t)&_SPIFFS_end - 0x40200000) / SPI_FLASH_SEC_SIZE -#ifdef ALLOW_MIGRATE_TO_V3 - // Version 2.x config - #define SPIFFS_CONFIG2 "/config.ini" - #define CFG_LOCATION2 SPIFFS_END - 2 -#endif // ALLOW_MIGRATE_TO_V3 - // Version 3.x config #define SPIFFS_CONFIG "/cfg.ini" #define CFG_LOCATION SPIFFS_END - 4 @@ -182,24 +176,10 @@ void CFG_Save() { char log[LOGSZ]; +#ifndef BE_MINIMAL if ((getHash() != _cfgHash) && (spiffsPresent())) { if (!spiffsflag) { -#ifdef USE_SPIFFS - sysCfg.saveFlag++; - File f = SPIFFS.open(SPIFFS_CONFIG, "r+"); - if (f) { - uint8_t *bytes = (uint8_t*)&sysCfg; - for (int i = 0; i < sizeof(SYSCFG); i++) f.write(bytes[i]); - f.close(); - snprintf_P(log, sizeof(log), PSTR("Config: Saved configuration (%d bytes) to spiffs count %d"), sizeof(SYSCFG), sysCfg.saveFlag); - addLog(LOG_LEVEL_DEBUG, log); - } else { - addLog_P(LOG_LEVEL_ERROR, PSTR("Config: ERROR - Saving configuration failed")); - } - } else { -#endif // USE_SPIFFS noInterrupts(); -// if (sysCfg.module != SONOFF_LED) noInterrupts(); if (sysCfg.saveFlag == 0) { // Handle default and rollover spi_flash_erase_sector(CFG_LOCATION + (sysCfg.saveFlag &1)); spi_flash_write((CFG_LOCATION + (sysCfg.saveFlag &1)) * SPI_FLASH_SEC_SIZE, (uint32*)&sysCfg, sizeof(SYSCFG)); @@ -208,12 +188,12 @@ void CFG_Save() spi_flash_erase_sector(CFG_LOCATION + (sysCfg.saveFlag &1)); spi_flash_write((CFG_LOCATION + (sysCfg.saveFlag &1)) * SPI_FLASH_SEC_SIZE, (uint32*)&sysCfg, sizeof(SYSCFG)); interrupts(); -// if (sysCfg.module != SONOFF_LED) interrupts(); snprintf_P(log, sizeof(log), PSTR("Config: Saved configuration (%d bytes) to flash at %X and count %d"), sizeof(SYSCFG), CFG_LOCATION + (sysCfg.saveFlag &1), sysCfg.saveFlag); addLog(LOG_LEVEL_DEBUG, log); } _cfgHash = getHash(); } +#endif // BE_MINIMAL RTC_Save(); } @@ -223,19 +203,6 @@ void CFG_Load() if (spiffsPresent()) { if (!spiffsflag) { -#ifdef USE_SPIFFS - File f = SPIFFS.open(SPIFFS_CONFIG, "r+"); - if (f) { - uint8_t *bytes = (uint8_t*)&sysCfg; - for (int i = 0; i < sizeof(SYSCFG); i++) bytes[i] = f.read(); - f.close(); - snprintf_P(log, sizeof(log), PSTR("Config: Loaded configuration from spiffs count %d"), sysCfg.saveFlag); - addLog(LOG_LEVEL_DEBUG, log); - } else { - addLog_P(LOG_LEVEL_ERROR, PSTR("Config: ERROR - Loading configuration failed")); - } - } else { -#endif // USE_SPIFFS struct SYSCFGH { unsigned long cfg_holder; unsigned long saveFlag; @@ -251,70 +218,12 @@ void CFG_Load() addLog(LOG_LEVEL_DEBUG, log); } } -#ifdef ALLOW_MIGRATE_TO_V3 -// snprintf_P(log, sizeof(log), PSTR("Config: Check 1 for migration (%08X)"), sysCfg.version); -// addLog(LOG_LEVEL_NONE, log); - if (sysCfg.cfg_holder != CFG_HOLDER) { - if ((sysCfg.version < 0x03000000) || (sysCfg.version > 0x73000000)) { - CFG_Migrate(); // Config may be present with versions below 3.0.0 - } else { - CFG_Default(); - } - } -#else if (sysCfg.cfg_holder != CFG_HOLDER) CFG_Default(); -#endif // ALLOW_MIGRATE_TO_V3 _cfgHash = getHash(); RTC_Load(); } -#ifdef ALLOW_MIGRATE_TO_V3 -void CFG_Migrate() -{ - char log[LOGSZ]; - - if (spiffsPresent()) { - if (!spiffsflag) { -#ifdef USE_SPIFFS - File f = SPIFFS.open(SPIFFS_CONFIG2, "r+"); - if (f) { - uint8_t *bytes = (uint8_t*)&sysCfg2; - for (int i = 0; i < sizeof(SYSCFG2); i++) bytes[i] = f.read(); - f.close(); - snprintf_P(log, sizeof(log), PSTR("Config: Loaded previous configuration from spiffs count %d"), sysCfg2.saveFlag); - addLog(LOG_LEVEL_DEBUG, log); - } else { - addLog_P(LOG_LEVEL_ERROR, PSTR("Config: ERROR - Loading previous configuration failed")); - } - } else { -#endif // USE_SPIFFS - struct SYSCFGH { - unsigned long cfg_holder; - unsigned long saveFlag; - } _sysCfgH; - - noInterrupts(); - spi_flash_read((CFG_LOCATION2) * SPI_FLASH_SEC_SIZE, (uint32*)&sysCfg2, sizeof(SYSCFG2)); - spi_flash_read((CFG_LOCATION2 + 1) * SPI_FLASH_SEC_SIZE, (uint32*)&_sysCfgH, sizeof(SYSCFGH)); - if (sysCfg2.saveFlag < _sysCfgH.saveFlag) - spi_flash_read((CFG_LOCATION2 + 1) * SPI_FLASH_SEC_SIZE, (uint32*)&sysCfg2, sizeof(SYSCFG2)); - interrupts(); - snprintf_P(log, sizeof(log), PSTR("Config: Loaded previous configuration from flash at %X and count %d"), CFG_LOCATION2 + (sysCfg2.saveFlag &1), sysCfg2.saveFlag); - addLog(LOG_LEVEL_DEBUG, log); - } - } -// snprintf_P(log, sizeof(log), PSTR("Config: Check 2 for migration (%08X)"), sysCfg2.version); -// addLog(LOG_LEVEL_NONE, log); - if ((sysCfg2.version > 0x01000000) && (sysCfg2.version < 0x03000000)) { - CFG_Migrate_Part2(); // Config is present between version 1.0.0 and 3.0.0 - } else { - CFG_Default(); - } - _cfgHash = getHash(); -} -#endif // ALLOW_MIGRATE_TO_V3 - void CFG_Erase() { char log[LOGSZ]; @@ -371,37 +280,6 @@ void CFG_Dump() } } -#ifdef USE_SPIFFS -void initSpiffs() -{ - spiffsflag = 0; - if (!spiffsPresent()) { - spiffsflag = 1; - } else { - if (!SPIFFS.begin()) { - addLog_P(LOG_LEVEL_ERROR, PSTR("SPIFFS: WARNING - Failed to mount file system. Will use flash")); - spiffsflag = 2; - } else { - addLog_P(LOG_LEVEL_DEBUG, PSTR("SPIFFS: Mount successful")); - File f = SPIFFS.open(SPIFFS_CONFIG, "r"); - if (!f) { - addLog_P(LOG_LEVEL_DEBUG, PSTR("SPIFFS: Formatting...")); - SPIFFS.format(); - addLog_P(LOG_LEVEL_DEBUG, PSTR("SPIFFS: Formatted")); - File f = SPIFFS.open(SPIFFS_CONFIG, "w"); - if (f) { - for (int i = 0; i < sizeof(SYSCFG); i++) f.write(0); - f.close(); - } else { - addLog_P(LOG_LEVEL_ERROR, PSTR("SPIFFS: WARNING - Failed to init config file. Will use flash")); - spiffsflag = 3; - } - } - } - } -} -#endif // USE_SPIFFS - /********************************************************************************************/ void CFG_DefaultSet1() @@ -418,7 +296,6 @@ void CFG_DefaultSet2() { sysCfg.savedata = SAVE_DATA; sysCfg.savestate = SAVE_STATE; -// sysCfg.model = 0; sysCfg.timezone = APP_TIMEZONE; strlcpy(sysCfg.otaUrl, OTA_URL, sizeof(sysCfg.otaUrl)); @@ -445,7 +322,6 @@ void CFG_DefaultSet2() strlcpy(sysCfg.mqtt_topic, MQTT_TOPIC, sizeof(sysCfg.mqtt_topic)); strlcpy(sysCfg.button_topic, "0", sizeof(sysCfg.button_topic)); strlcpy(sysCfg.mqtt_grptopic, MQTT_GRPTOPIC, sizeof(sysCfg.mqtt_grptopic)); - strlcpy(sysCfg.mqtt_subtopic, MQTT_SUBTOPIC, sizeof(sysCfg.mqtt_subtopic)); sysCfg.mqtt_button_retain = MQTT_BUTTON_RETAIN; sysCfg.mqtt_power_retain = MQTT_POWER_RETAIN; sysCfg.value_units = 0; @@ -515,6 +391,10 @@ void CFG_DefaultSet2() // 4.0.9 CFG_DefaultSet_4_0_9(); + + // 4.1.1 + CFG_DefaultSet_4_1_1(); + } void CFG_DefaultSet_3_2_4() @@ -574,6 +454,14 @@ void CFG_DefaultSet_4_0_9() parseIP(&sysCfg.ip_address[3], WIFI_DNS); } +void CFG_DefaultSet_4_1_1() +{ + sysCfg.mqtt_response = 0; + strlcpy(sysCfg.state_text[0], MQTT_STATUS_OFF, sizeof(sysCfg.state_text[0])); + strlcpy(sysCfg.state_text[1], MQTT_STATUS_ON, sizeof(sysCfg.state_text[1])); + strlcpy(sysCfg.state_text[2], MQTT_CMND_TOGGLE, sizeof(sysCfg.state_text[2])); +} + void CFG_Default() { addLog_P(LOG_LEVEL_NONE, PSTR("Config: Use default configuration")); @@ -582,117 +470,6 @@ void CFG_Default() CFG_Save(); } -#ifdef ALLOW_MIGRATE_TO_V3 -void CFG_Migrate_Part2() -{ - addLog_P(LOG_LEVEL_NONE, PSTR("Config: Migrating configuration")); - CFG_DefaultSet1(); - CFG_DefaultSet2(); - - sysCfg.seriallog_level = sysCfg2.seriallog_level; - sysCfg.syslog_level = sysCfg2.syslog_level; - strlcpy(sysCfg.syslog_host, sysCfg2.syslog_host, sizeof(sysCfg.syslog_host)); - strlcpy(sysCfg.sta_ssid[0], sysCfg2.sta_ssid1, sizeof(sysCfg.sta_ssid[0])); - strlcpy(sysCfg.sta_pwd[0], sysCfg2.sta_pwd1, sizeof(sysCfg.sta_pwd[0])); - strlcpy(sysCfg.otaUrl, sysCfg2.otaUrl, sizeof(sysCfg.otaUrl)); - strlcpy(sysCfg.mqtt_host, sysCfg2.mqtt_host, sizeof(sysCfg.mqtt_host)); - strlcpy(sysCfg.mqtt_grptopic, sysCfg2.mqtt_grptopic, sizeof(sysCfg.mqtt_grptopic)); - strlcpy(sysCfg.mqtt_topic, sysCfg2.mqtt_topic, sizeof(sysCfg.mqtt_topic)); - strlcpy(sysCfg.button_topic, sysCfg2.mqtt_topic2, sizeof(sysCfg.button_topic)); - strlcpy(sysCfg.mqtt_subtopic, sysCfg2.mqtt_subtopic, sizeof(sysCfg.mqtt_subtopic)); - sysCfg.timezone = sysCfg2.timezone; - sysCfg.power = sysCfg2.power; - if (sysCfg2.version >= 0x01000D00) { // 1.0.13 - sysCfg.ledstate = sysCfg2.ledstate; - } - if (sysCfg2.version >= 0x01001600) { // 1.0.22 - sysCfg.mqtt_port = sysCfg2.mqtt_port; - strlcpy(sysCfg.mqtt_client, sysCfg2.mqtt_client, sizeof(sysCfg.mqtt_client)); - strlcpy(sysCfg.mqtt_user, sysCfg2.mqtt_user, sizeof(sysCfg.mqtt_user)); - strlcpy(sysCfg.mqtt_pwd, sysCfg2.mqtt_pwd, sizeof(sysCfg.mqtt_pwd)); - strlcpy(sysCfg.friendlyname[0], sysCfg2.mqtt_client, sizeof(sysCfg.friendlyname[0])); - } - if (sysCfg2.version >= 0x01001700) { // 1.0.23 - sysCfg.webserver = sysCfg2.webserver; - } - if (sysCfg2.version >= 0x01001A00) { // 1.0.26 - sysCfg.bootcount = sysCfg2.bootcount; - strlcpy(sysCfg.hostname, sysCfg2.hostname, sizeof(sysCfg.hostname)); - sysCfg.syslog_port = sysCfg2.syslog_port; - } - if (sysCfg2.version >= 0x01001B00) { // 1.0.27 - sysCfg.weblog_level = sysCfg2.weblog_level; - } - if (sysCfg2.version >= 0x01001C00) { // 1.0.28 - sysCfg.tele_period = sysCfg2.tele_period; - if ((sysCfg.tele_period > 0) && (sysCfg.tele_period < 10)) sysCfg.tele_period = 10; // Do not allow periods < 10 seconds - } - if (sysCfg2.version >= 0x01002000) { // 1.0.32 - sysCfg.sta_config = sysCfg2.sta_config; - } - if (sysCfg2.version >= 0x01002300) { // 1.0.35 - sysCfg.savedata = sysCfg2.savedata; - } - if (sysCfg2.version >= 0x02000000) { // 2.0.0 - sysCfg.model = sysCfg2.model; - } - if (sysCfg2.version >= 0x02000300) { // 2.0.3 - sysCfg.mqtt_button_retain = sysCfg2.mqtt_retain; - sysCfg.savestate = sysCfg2.savestate; - } - if (sysCfg2.version >= 0x02000500) { // 2.0.5 - sysCfg.hlw_pcal = sysCfg2.hlw_pcal; - sysCfg.hlw_ucal = sysCfg2.hlw_ucal; - sysCfg.hlw_ical = sysCfg2.hlw_ical; - sysCfg.hlw_kWhyesterday = sysCfg2.hlw_kWhyesterday; - sysCfg.value_units = sysCfg2.value_units; - } - if (sysCfg2.version >= 0x02000600) { // 2.0.6 - sysCfg.hlw_pmin = sysCfg2.hlw_pmin; - sysCfg.hlw_pmax = sysCfg2.hlw_pmax; - sysCfg.hlw_umin = sysCfg2.hlw_umin; - sysCfg.hlw_umax = sysCfg2.hlw_umax; - sysCfg.hlw_imin = sysCfg2.hlw_imin; - sysCfg.hlw_imax = sysCfg2.hlw_imax; - } - if (sysCfg2.version >= 0x02000700) { // 2.0.7 -// sysCfg.message_format = 0; - strlcpy(sysCfg.domoticz_in_topic, sysCfg2.domoticz_in_topic, sizeof(sysCfg.domoticz_in_topic)); - strlcpy(sysCfg.domoticz_out_topic, sysCfg2.domoticz_out_topic, sizeof(sysCfg.domoticz_out_topic)); - sysCfg.domoticz_update_timer = sysCfg2.domoticz_update_timer; - for (byte i = 0; i < 4; i++) { - sysCfg.domoticz_relay_idx[i] = sysCfg2.domoticz_relay_idx[i]; - sysCfg.domoticz_key_idx[i] = sysCfg2.domoticz_key_idx[i]; - } - - sysCfg.hlw_mpl = sysCfg2.hlw_mpl; // MaxPowerLimit - sysCfg.hlw_mplh = sysCfg2.hlw_mplh; - sysCfg.hlw_mplw = sysCfg2.hlw_mplw; - sysCfg.hlw_mspl = sysCfg2.hlw_mspl; // MaxSafePowerLimit - sysCfg.hlw_msplh = sysCfg2.hlw_msplh; - sysCfg.hlw_msplw = sysCfg2.hlw_msplw; - sysCfg.hlw_mkwh = sysCfg2.hlw_mkwh; // MaxEnergy - sysCfg.hlw_mkwhs = sysCfg2.hlw_mkwhs; // MaxEnergyStart - } - if (sysCfg2.version >= 0x02001000) { // 2.0.16 - sysCfg.hlw_kWhtoday = sysCfg2.hlw_kWhtoday; - sysCfg.hlw_kWhdoy = sysCfg2.hlw_kWhdoy; - } - if (sysCfg2.version >= 0x02001200) { // 2.0.18 - sysCfg.switchmode[0] = sysCfg2.switchmode; - } - if (sysCfg2.version >= 0x02010000) { // 2.1.0 - strlcpy(sysCfg.mqtt_fingerprint, sysCfg2.mqtt_fingerprint, sizeof(sysCfg.mqtt_fingerprint)); - } - if (sysCfg2.version >= 0x02010200) { // 2.1.2 - sysCfg.sta_active = sysCfg2.sta_active; - strlcpy(sysCfg.sta_ssid[1], sysCfg2.sta_ssid2, sizeof(sysCfg.sta_ssid[1])); - strlcpy(sysCfg.sta_pwd[1], sysCfg2.sta_pwd2, sizeof(sysCfg.sta_pwd[1])); - } - CFG_Save(); -} -#endif // ALLOW_MIGRATE_TO_V3 - /********************************************************************************************/ void CFG_Delta() @@ -753,6 +530,9 @@ void CFG_Delta() if (sysCfg.version < 0x04000804) { CFG_DefaultSet_4_0_9(); } + if (sysCfg.version < 0x04010100) { + CFG_DefaultSet_4_1_1(); + } sysCfg.version = VERSION; } } diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index ed8db6723..fb9658d84 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -10,12 +10,7 @@ * ==================================================== */ -//#define ALLOW_MIGRATE_TO_V3 -#ifdef ALLOW_MIGRATE_TO_V3 - #define VERSION 0x03092000 // 3.9.32 -#else - #define VERSION 0x04010000 // 4.1.0 -#endif // ALLOW_MIGRATE_TO_V3 +#define VERSION 0x04010100 // 4.1.1 enum log_t {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL}; enum week_t {Last, First, Second, Third, Fourth}; @@ -31,12 +26,6 @@ enum emul_t {EMUL_NONE, EMUL_WEMO, EMUL_HUE, EMUL_MAX}; #include "user_config.h" #include "user_config_override.h" -/*********************************************************************************************\ - * Enable feature by removing leading // or disable feature by adding leading // -\*********************************************************************************************/ - -//#define USE_SPIFFS // Switch persistent configuration from flash to spiffs (+24k code, +0.6k mem) - /*********************************************************************************************\ * No user configurable items below \*********************************************************************************************/ @@ -108,7 +97,6 @@ enum emul_t {EMUL_NONE, EMUL_WEMO, EMUL_HUE, EMUL_MAX}; #define HLW_UREF_PULSE 1950 // was 1666us = 600Hz = 220V #define HLW_IREF_PULSE 3500 // was 1666us = 600Hz = 4.545A -#define MQTT_SUBTOPIC "POWER" // Default MQTT subtopic (POWER or LIGHT) #define MQTT_RETRY_SECS 10 // Seconds to retry MQTT connection #define APP_POWER 0 // Default saved power state Off #define MAX_DEVICE 1 // Max number of devices @@ -164,9 +152,6 @@ enum butt_t {PRESSED, NOT_PRESSED}; #ifdef USE_DISCOVERY #include // MQTT, Webserver #endif // USE_DISCOVERY -#ifdef USE_SPIFFS - #include // Config -#endif // USE_SPIFFS #ifdef USE_I2C #include // I2C support library #endif // USE_I2C @@ -232,6 +217,7 @@ byte otaretry = OTA_ATTEMPTS; // OTA retry counter int restartflag = 0; // Sonoff restart flag int wificheckflag = WIFI_RESTART; // Wifi state flag int uptime = 0; // Current uptime in hours +boolean uptime_flg = true; // Signal latest uptime int tele_period = 0; // Tele period timer String Log[MAX_LOG_LINES]; // Web log buffer byte logidx = 0; // Index in Web log buffer @@ -407,6 +393,12 @@ void json2legacy(char* stopic, char* svalue) } } +char* getStateText(byte state) +{ + if (state > 2) state = 1; + return sysCfg.state_text[state]; +} + /********************************************************************************************/ void mqtt_publish_sec(const char* topic, const char* data, boolean retained) @@ -448,7 +440,8 @@ void mqtt_publish_topic_P(uint8_t prefix, const char* subtopic, const char* data { char romram[16], stopic[TOPSZ]; - snprintf_P(romram, sizeof(romram), subtopic); + snprintf_P(romram, sizeof(romram), ((prefix > 3) && !sysCfg.mqtt_response) ? PSTR("RESULT") : subtopic); + prefix &= 1; snprintf_P(stopic, sizeof(stopic), PSTR("%s/%s/%s"), sysCfg.mqtt_prefix[prefix +1], sysCfg.mqtt_topic, romram); mqtt_publish(stopic, data); } @@ -459,9 +452,10 @@ void mqtt_publishPowerState(byte device) if ((device < 1) || (device > Maxdevice)) device = 1; snprintf_P(sdevice, sizeof(sdevice), PSTR("%d"), device); - snprintf_P(stopic, sizeof(stopic), PSTR("%s/%s/RESULT"), sysCfg.mqtt_prefix[1], sysCfg.mqtt_topic); - snprintf_P(svalue, sizeof(svalue), PSTR("{\"%s%s\":\"%s\"}"), - sysCfg.mqtt_subtopic, (Maxdevice > 1) ? sdevice : "", (power & (0x01 << (device -1))) ? MQTT_STATUS_ON : MQTT_STATUS_OFF); + snprintf_P(stopic, sizeof(stopic), PSTR("%s/%s/%s"), + sysCfg.mqtt_prefix[1], sysCfg.mqtt_topic, (sysCfg.mqtt_response)?"POWER":"RESULT"); + snprintf_P(svalue, sizeof(svalue), PSTR("{\"POWER%s\":\"%s\"}"), + (Maxdevice > 1) ? sdevice : "", getStateText(bitRead(power, device -1))); mqtt_publish(stopic, svalue); json2legacy(stopic, svalue); mqtt_publish(stopic, svalue, sysCfg.mqtt_power_retain); @@ -473,9 +467,9 @@ void mqtt_publishPowerBlinkState(byte device) if ((device < 1) || (device > Maxdevice)) device = 1; snprintf_P(sdevice, sizeof(sdevice), PSTR("%d"), device); - snprintf_P(svalue, sizeof(svalue), PSTR("{\"%s%s\":\"BLINK %s\"}"), - sysCfg.mqtt_subtopic, (Maxdevice > 1) ? sdevice : "", (blink_mask & (0x01 << (device -1))) ? MQTT_STATUS_ON : MQTT_STATUS_OFF); - mqtt_publish_topic_P(0, PSTR("RESULT"), svalue); + snprintf_P(svalue, sizeof(svalue), PSTR("{\"POWER%s\":\"BLINK %s\"}"), + (Maxdevice > 1) ? sdevice : "", getStateText(bitRead(blink_mask, device -1))); + mqtt_publish_topic_P(4, PSTR("POWER"), svalue); } void mqtt_connected() @@ -610,6 +604,19 @@ boolean mqtt_command(boolean grpflg, char *type, uint16_t index, char *dataBuf, } snprintf_P(svalue, ssvalue, PSTR("{\"MqttPort\":%d}"), sysCfg.mqtt_port); } + else if (!strcmp(type,"MQTTRESPONSE")) { + if ((data_len > 0) && (payload >= 0) && (payload <= 1)) { + sysCfg.mqtt_response = payload; + } + snprintf_P(svalue, ssvalue, PSTR("{\"MqttResponse\":\"%s\"}"), getStateText(sysCfg.mqtt_response)); + } + else if (!strcmp(type,"STATETEXT") && (index > 0) && (index <= 3)) { + if ((data_len > 0) && (data_len < sizeof(sysCfg.state_text[0]))) { + for(i = 0; i <= data_len; i++) if (dataBuf[i] == ' ') dataBuf[i] = '_'; + strlcpy(sysCfg.state_text[index -1], (payload == 1) ? (index==1)?MQTT_STATUS_OFF:(index==2)?MQTT_STATUS_ON:MQTT_CMND_TOGGLE : dataBuf, sizeof(sysCfg.state_text[0])); + } + snprintf_P(svalue, ssvalue, PSTR("{\"StateText%d\":\"%s\"}"), index, getStateText(index -1)); + } #ifdef USE_MQTT_TLS else if (!strcmp(type,"MQTTFINGERPRINT")) { if ((data_len > 0) && (data_len < sizeof(sysCfg.mqtt_fingerprint))) { @@ -645,7 +652,7 @@ boolean mqtt_command(boolean grpflg, char *type, uint16_t index, char *dataBuf, for(i = 0; i <= data_len; i++) // if ((dataBuf[i] == '/') || (dataBuf[i] == '+') || (dataBuf[i] == '#') || (dataBuf[i] == ' ')) dataBuf[i] = '_'; if ((dataBuf[i] == '+') || (dataBuf[i] == '#') || (dataBuf[i] == ' ')) dataBuf[i] = '_'; - strlcpy(sysCfg.mqtt_prefix[index -1], (payload == 1) ? (index==1)?SUB_PREFIX:(index==2)?PUB_PREFIX:PUB_PREFIX : dataBuf, sizeof(sysCfg.mqtt_prefix[0])); + strlcpy(sysCfg.mqtt_prefix[index -1], (payload == 1) ? (index==1)?SUB_PREFIX:(index==2)?PUB_PREFIX:PUB_PREFIX2 : dataBuf, sizeof(sysCfg.mqtt_prefix[0])); // if (sysCfg.mqtt_prefix[index -1][strlen(sysCfg.mqtt_prefix[index -1])] == '/') sysCfg.mqtt_prefix[index -1][strlen(sysCfg.mqtt_prefix[index -1])] = 0; restartflag = 2; } @@ -699,7 +706,7 @@ boolean mqtt_command(boolean grpflg, char *type, uint16_t index, char *dataBuf, } sysCfg.mqtt_button_retain = payload; } - snprintf_P(svalue, ssvalue, PSTR("{\"ButtonRetain\":\"%s\"}"), (sysCfg.mqtt_button_retain) ? MQTT_STATUS_ON : MQTT_STATUS_OFF); + snprintf_P(svalue, ssvalue, PSTR("{\"ButtonRetain\":\"%s\"}"), getStateText(sysCfg.mqtt_button_retain)); } else if (!strcmp(type,"SWITCHRETAIN")) { if ((data_len > 0) && (payload >= 0) && (payload <= 1)) { @@ -711,23 +718,20 @@ boolean mqtt_command(boolean grpflg, char *type, uint16_t index, char *dataBuf, } sysCfg.mqtt_switch_retain = payload; } - snprintf_P(svalue, ssvalue, PSTR("{\"SwitchRetain\":\"%s\"}"), (sysCfg.mqtt_switch_retain) ? MQTT_STATUS_ON : MQTT_STATUS_OFF); + snprintf_P(svalue, ssvalue, PSTR("{\"SwitchRetain\":\"%s\"}"), getStateText(sysCfg.mqtt_switch_retain)); } - else if (!strcmp(type,"POWERRETAIN") || !strcmp(type,"LIGHTRETAIN")) { + else if (!strcmp(type,"POWERRETAIN")) { if ((data_len > 0) && (payload >= 0) && (payload <= 1)) { if (!payload) { for(i = 1; i <= Maxdevice; i++) { // Clear MQTT retain in broker snprintf_P(stemp2, sizeof(stemp2), PSTR("%d"), i); snprintf_P(stemp1, sizeof(stemp1), PSTR("%s/%s/POWER%s"), sysCfg.mqtt_prefix[1], sysCfg.mqtt_topic, (Maxdevice > 1) ? stemp2 : ""); mqtt_publish(stemp1, "", sysCfg.mqtt_power_retain); - snprintf_P(stemp1, sizeof(stemp1), PSTR("%s/%s/LIGHT%s"), sysCfg.mqtt_prefix[1], sysCfg.mqtt_topic, (Maxdevice > 1) ? stemp2 : ""); - mqtt_publish(stemp1, "", sysCfg.mqtt_power_retain); } } sysCfg.mqtt_power_retain = payload; } - snprintf_P(stemp1, sizeof(stemp1), PSTR("%s"), (!strcmp(sysCfg.mqtt_subtopic,"POWER")) ? "Power" : "Light"); - snprintf_P(svalue, ssvalue, PSTR("{\"%sRetain\":\"%s\"}"), stemp1, (sysCfg.mqtt_power_retain) ? MQTT_STATUS_ON : MQTT_STATUS_OFF); + snprintf_P(svalue, ssvalue, PSTR("{\"PowerRetain\":\"%s\"}"), getStateText(sysCfg.mqtt_power_retain)); } #ifdef USE_DOMOTICZ else if (domoticz_command(type, index, dataBuf, data_len, payload, svalue, ssvalue)) { @@ -815,8 +819,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) if (!strcmp(dataBufUc,"BLINK")) payload = 3; if (!strcmp(dataBufUc,"BLINKOFF")) payload = 4; - if ((!strcmp(type,"POWER") || !strcmp(type,"LIGHT")) && (index > 0) && (index <= Maxdevice)) { - snprintf_P(sysCfg.mqtt_subtopic, sizeof(sysCfg.mqtt_subtopic), PSTR("%s"), type); + if (!strcmp(type,"POWER") && (index > 0) && (index <= Maxdevice)) { if ((data_len == 0) || (payload > 4)) payload = 9; do_cmnd_power(index, payload); return; @@ -864,32 +867,32 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) if (sysCfg.savestate) sysCfg.power = power; CFG_Save(); if (sysCfg.savedata > 1) snprintf_P(stemp1, sizeof(stemp1), PSTR("Every %d seconds"), sysCfg.savedata); - snprintf_P(svalue, sizeof(svalue), PSTR("{\"SaveData\":\"%s\"}"), (sysCfg.savedata) ? (sysCfg.savedata > 1) ? stemp1 : MQTT_STATUS_ON : MQTT_STATUS_OFF); + snprintf_P(svalue, sizeof(svalue), PSTR("{\"SaveData\":\"%s\"}"), (sysCfg.savedata > 1) ? stemp1 : getStateText(sysCfg.savedata)); } else if (!strcmp(type,"SAVESTATE")) { if ((data_len > 0) && (payload >= 0) && (payload <= 1)) { sysCfg.savestate = payload; } - snprintf_P(svalue, sizeof(svalue), PSTR("{\"SaveState\":\"%s\"}"), (sysCfg.savestate) ? MQTT_STATUS_ON : MQTT_STATUS_OFF); + snprintf_P(svalue, sizeof(svalue), PSTR("{\"SaveState\":\"%s\"}"), getStateText(sysCfg.savestate)); } else if (!strcmp(type,"BUTTONRESTRICT")) { if ((data_len > 0) && (payload >= 0) && (payload <= 1)) { sysCfg.button_restrict = payload; } - snprintf_P(svalue, sizeof(svalue), PSTR("{\"ButtonRestrict\":\"%s\"}"), (sysCfg.button_restrict) ? MQTT_STATUS_ON : MQTT_STATUS_OFF); + snprintf_P(svalue, sizeof(svalue), PSTR("{\"ButtonRestrict\":\"%s\"}"), getStateText(sysCfg.button_restrict)); } else if (!strcmp(type,"UNITS")) { if ((data_len > 0) && (payload >= 0) && (payload <= 1)) { sysCfg.value_units = payload; } - snprintf_P(svalue, sizeof(svalue), PSTR("{\"Units\":\"%s\"}"), (sysCfg.value_units) ? MQTT_STATUS_ON : MQTT_STATUS_OFF); + snprintf_P(svalue, sizeof(svalue), PSTR("{\"Units\":\"%s\"}"), getStateText(sysCfg.value_units)); } else if (!strcmp(type,"MQTT")) { if ((data_len > 0) && (payload >= 0) && (payload <= 1)) { sysCfg.mqtt_enabled = payload; restartflag = 2; } - snprintf_P(svalue, sizeof(svalue), PSTR("{\"Mqtt\":\"%s\"}"), (sysCfg.mqtt_enabled) ? MQTT_STATUS_ON : MQTT_STATUS_OFF); + snprintf_P(svalue, sizeof(svalue), PSTR("{\"Mqtt\":\"%s\"}"), getStateText(sysCfg.mqtt_enabled)); } else if (!strcmp(type,"MODULE")) { if ((data_len > 0) && (payload > 0) && (payload <= MAXMODULE)) { @@ -912,7 +915,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) snprintf_P(svalue, sizeof(svalue), PSTR("%s%d (%s)"), svalue, i +1, stemp1); } snprintf_P(svalue, sizeof(svalue), PSTR("%s\"}"), svalue); - mqtt_publish_topic_P(0, PSTR("RESULT"), svalue); + mqtt_publish_topic_P(4, type, svalue); snprintf_P(svalue, sizeof(svalue), PSTR("{\"Modules2\":\""), svalue); jsflg = 0; for (byte i = MAXMODULE /2; i < MAXMODULE; i++) { @@ -959,7 +962,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) snprintf_P(svalue, sizeof(svalue), PSTR("%s%d (%s)"), svalue, i, stemp1); } snprintf_P(svalue, sizeof(svalue), PSTR("%s\"}"), svalue); - mqtt_publish_topic_P(0, PSTR("RESULT"), svalue); + mqtt_publish_topic_P(4, type, svalue); snprintf_P(svalue, sizeof(svalue), PSTR("{\"GPIOs2\":\""), svalue); jsflg = 0; for (byte i = GPIO_SENSOR_END /2; i < GPIO_SENSOR_END; i++) { @@ -1041,33 +1044,13 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) } snprintf_P(svalue, sizeof(svalue), PSTR("{\"LogPort\":%d}"), sysCfg.syslog_port); } - else if (!strcmp(type,"IPADDRESS")) { + else if (!strcmp(type,"IPADDRESS") && (index > 0) && (index <= 4)) { if (parseIP(&address, dataBuf)) { - sysCfg.ip_address[0] = address; - restartflag = 2; + sysCfg.ip_address[index -1] = address; +// restartflag = 2; } - snprintf_P(svalue, sizeof(svalue), PSTR("{\"IPAddress\":\"%s (%s)\"}"), IPAddress(sysCfg.ip_address[0]).toString().c_str(), WiFi.localIP().toString().c_str()); - } - else if (!strcmp(type,"GATEWAY")) { - if (parseIP(&address, dataBuf)) { - sysCfg.ip_address[1] = address; - restartflag = 2; - } - snprintf_P(svalue, sizeof(svalue), PSTR("{\"Gateway\":\"%s\"}"), IPAddress(sysCfg.ip_address[1]).toString().c_str()); - } - else if (!strcmp(type,"SUBNETMASK")) { - if (parseIP(&address, dataBuf)) { - sysCfg.ip_address[2] = address; - restartflag = 2; - } - snprintf_P(svalue, sizeof(svalue), PSTR("{\"Subnetmask\":\"%s\"}"), IPAddress(sysCfg.ip_address[2]).toString().c_str()); - } - else if (!strcmp(type,"DNSSERVER")) { - if (parseIP(&address, dataBuf)) { - sysCfg.ip_address[3] = address; - restartflag = 2; - } - snprintf_P(svalue, sizeof(svalue), PSTR("{\"DnsServer\":\"%s\"}"), IPAddress(sysCfg.ip_address[3]).toString().c_str()); + snprintf_P(stemp1, sizeof(stemp1), PSTR(" (%s)"), WiFi.localIP().toString().c_str()); + snprintf_P(svalue, sizeof(svalue), PSTR("{\"IPAddress%d\":\"%s%s\"}"), index, IPAddress(sysCfg.ip_address[index -1]).toString().c_str(), (index == 1) ? stemp1:""); } else if (!strcmp(type,"NTPSERVER") && (index > 0) && (index <= 3)) { if ((data_len > 0) && (data_len < sizeof(sysCfg.ntp_server[0]))) { @@ -1156,7 +1139,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) snprintf_P(svalue, sizeof(svalue), PSTR("{\"Webserver\":\"Active for %s on %s with IP address %s\"}"), (sysCfg.webserver == 2) ? "ADMIN" : "USER", Hostname, WiFi.localIP().toString().c_str()); } else { - snprintf_P(svalue, sizeof(svalue), PSTR("{\"Webserver\":\"%s\"}"), MQTT_STATUS_OFF); + snprintf_P(svalue, sizeof(svalue), PSTR("{\"Webserver\":\"%s\"}"), getStateText(0)); } } else if (!strcmp(type,"WEBPASSWORD")) { @@ -1238,7 +1221,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) blinks = 0; setLed(sysCfg.ledstate &8); } - snprintf_P(svalue, sizeof(svalue), PSTR("{\"LedPower\":\"%s\"}"), (sysCfg.ledstate &8) ? MQTT_STATUS_ON : MQTT_STATUS_OFF); + snprintf_P(svalue, sizeof(svalue), PSTR("{\"LedPower\":\"%s\"}"), getStateText(bitRead(sysCfg.ledstate, 3))); } else if (!strcmp(type,"LEDSTATE")) { if ((data_len > 0) && (payload >= 0) && (payload < MAX_LED_OPTION)) { @@ -1284,17 +1267,14 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) } if (type == NULL) { blinks = 201; - snprintf_P(svalue, sizeof(svalue), PSTR("{\"Commands1\":\"Status, SaveData, SaveSate, Sleep, Upgrade, Otaurl, Restart, Reset, WifiConfig, Seriallog, Syslog, LogHost, LogPort, SSId1, SSId2, Password1, Password2, AP%s\"}"), (!grpflg) ? ", Hostname, Module, Modules, GPIO, GPIOs" : ""); +/* + snprintf_P(svalue, sizeof(svalue), PSTR("{\"Commands1\":\"Status, SaveData, SaveSate, Sleep, Upgrade, Otaurl, Restart, Reset, WifiConfig, Seriallog, Syslog, LogHost, LogPort, SSId, Password, AP, IPAddres, NTPServer, Hostname, Module, Modules, GPIO, GPIOs\"}")); mqtt_publish_topic_P(0, PSTR("COMMANDS1"), svalue); - if (sysCfg.mqtt_enabled) { - snprintf_P(svalue, sizeof(svalue), PSTR("{\"Commands2\":\"Mqtt, MqttHost, MqttPort, MqttUser, MqttPassword%s, GroupTopic, Units, Timezone, LedState, LedPower, TelePeriod\"}"), (!grpflg) ? ", MqttClient, Topic, ButtonTopic, ButtonRetain, SwitchTopic, SwitchRetain, PowerRetain" : ""); - } else { - snprintf_P(svalue, sizeof(svalue), PSTR("{\"Commands2\":\"Mqtt, Units, Timezone, LedState, LedPower, TelePeriod\"}"), (!grpflg) ? ", MqttClient" : ""); - } + snprintf_P(svalue, sizeof(svalue), PSTR("{\"Commands2\":\"Mqtt, MqttResponse, MqttHost, MqttPort, MqttUser, MqttPassword, MqttClient, Topic, GroupTopic, ButtonTopic, ButtonRetain, SwitchTopic, SwitchRetain, PowerRetain, Units, Timezone, LedState, LedPower, TelePeriod\"}")); mqtt_publish_topic_P(0, PSTR("COMMANDS2"), svalue); - snprintf_P(svalue, sizeof(svalue), PSTR("{\"Commands3\":\"%s%s, PulseTime, BlinkTime, BlinkCount, ButtonRestrict, NtpServer"), (Maxdevice == 1) ? "Power, Light" : "Power1, Power2, Light1 Light2", (sysCfg.module != MOTOR) ? ", PowerOnState" : ""); + snprintf_P(svalue, sizeof(svalue), PSTR("{\"Commands3\":\"Power%s, PulseTime, BlinkTime, BlinkCount, ButtonRestrict"), (sysCfg.module != MOTOR) ? ", PowerOnState" : ""); #ifdef USE_WEBSERVER snprintf_P(svalue, sizeof(svalue), PSTR("%s, Weblog, Webserver, WebPassword, Emulation"), svalue); #endif @@ -1322,8 +1302,11 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) hlw_commands(svalue, sizeof(svalue)); mqtt_publish_topic_P(0, PSTR("COMMANDS5"), svalue); } +*/ + snprintf_P(svalue, sizeof(svalue), PSTR("{\"Command\":\"Invalid command\"}")); + mqtt_publish_topic_P(0, PSTR("COMMAND"), svalue); } else { - mqtt_publish_topic_P(0, PSTR("RESULT"), svalue); + mqtt_publish_topic_P(4, type, svalue); } } @@ -1338,8 +1321,8 @@ void send_button_power(byte key, byte device, byte state) if (!key && (device > Maxdevice)) device = 1; snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), device); - snprintf_P(stopic, sizeof(stopic), PSTR("%s/%s/%s%s"), - sysCfg.mqtt_prefix[0], (key) ? sysCfg.switch_topic : sysCfg.button_topic, sysCfg.mqtt_subtopic, (key || (Maxdevice > 1)) ? stemp1 : ""); + snprintf_P(stopic, sizeof(stopic), PSTR("%s/%s/POWER%s"), + sysCfg.mqtt_prefix[0], (key) ? sysCfg.switch_topic : sysCfg.button_topic, (key || (Maxdevice > 1)) ? stemp1 : ""); if (state == 3) { svalue[0] = '\0'; @@ -1347,7 +1330,7 @@ void send_button_power(byte key, byte device, byte state) if (!strcmp(sysCfg.mqtt_topic,(key) ? sysCfg.switch_topic : sysCfg.button_topic) && (state == 2)) { state = ~(power >> (device -1)) & 0x01; } - snprintf_P(svalue, sizeof(svalue), PSTR("%s"), (state) ? (state == 2) ? MQTT_CMND_TOGGLE : MQTT_STATUS_ON : MQTT_STATUS_OFF); + snprintf_P(svalue, sizeof(svalue), PSTR("%s"), getStateText(state)); } #ifdef USE_DOMOTICZ if (!(domoticz_button(key, device, state, strlen(svalue)))) { @@ -1456,8 +1439,8 @@ void publish_status(uint8_t payload) if ((!hlw_flg) && ((payload == 8) || (payload == 9))) payload = 99; if ((payload == 0) || (payload == 99)) { - snprintf_P(svalue, sizeof(svalue), PSTR("{\"Status\":{\"Module\":%d, \"FriendlyName\":\"%s\", \"Topic\":\"%s\", \"ButtonTopic\":\"%s\", \"Subtopic\":\"%s\", \"Power\":%d, \"PowerOnState\":%d, \"LedState\":%d, \"SaveData\":%d, \"SaveState\":%d, \"ButtonRetain\":%d, \"PowerRetain\":%d}}"), - sysCfg.module +1, sysCfg.friendlyname[0], sysCfg.mqtt_topic, sysCfg.button_topic, sysCfg.mqtt_subtopic, power, sysCfg.poweronstate, sysCfg.ledstate, sysCfg.savedata, sysCfg.savestate, sysCfg.mqtt_button_retain, sysCfg.mqtt_power_retain); + snprintf_P(svalue, sizeof(svalue), PSTR("{\"Status\":{\"Module\":%d, \"FriendlyName\":\"%s\", \"Topic\":\"%s\", \"ButtonTopic\":\"%s\", \"Power\":%d, \"PowerOnState\":%d, \"LedState\":%d, \"SaveData\":%d, \"SaveState\":%d, \"ButtonRetain\":%d, \"PowerRetain\":%d}}"), + sysCfg.module +1, sysCfg.friendlyname[0], sysCfg.mqtt_topic, sysCfg.button_topic, power, sysCfg.poweronstate, sysCfg.ledstate, sysCfg.savedata, sysCfg.savestate, sysCfg.mqtt_button_retain, sysCfg.mqtt_power_retain); mqtt_publish_topic_P(option, PSTR("STATUS"), svalue); } @@ -1529,7 +1512,7 @@ void publish_status(uint8_t payload) } if ((payload == 0) || (payload == 11)) { - snprintf_P(svalue, sizeof(svalue), PSTR("{\"StatusPWR\":")); + snprintf_P(svalue, sizeof(svalue), PSTR("{\"StatusSTS\":")); state_mqttPresent(svalue, sizeof(svalue)); snprintf_P(svalue, sizeof(svalue), PSTR("%s}"), svalue); mqtt_publish_topic_P(option, PSTR("STATUS11"), svalue); @@ -1548,11 +1531,11 @@ void state_mqttPresent(char* svalue, uint16_t ssvalue) #endif for (byte i = 0; i < Maxdevice; i++) { if (Maxdevice == 1) { // Legacy - snprintf_P(svalue, ssvalue, PSTR("%s, \"%s\":"), svalue, sysCfg.mqtt_subtopic); + snprintf_P(svalue, ssvalue, PSTR("%s, \"POWER\":"), svalue); } else { - snprintf_P(svalue, ssvalue, PSTR("%s, \"%s%d\":"), svalue, sysCfg.mqtt_subtopic, i +1); + snprintf_P(svalue, ssvalue, PSTR("%s, \"POWER%d\":"), svalue, i +1); } - snprintf_P(svalue, ssvalue, PSTR("%s\"%s\""), svalue, (power & (0x01 << i)) ? MQTT_STATUS_ON : MQTT_STATUS_OFF); + snprintf_P(svalue, ssvalue, PSTR("%s\"%s\""), svalue, getStateText(bitRead(power, i))); } snprintf_P(svalue, ssvalue, PSTR("%s, \"Wifi\":{\"AP\":%d, \"SSID\":\"%s\", \"RSSI\":%d}}"), svalue, sysCfg.sta_active +1, sysCfg.sta_ssid[sysCfg.sta_active], WIFI_getRSSIasQuality(WiFi.RSSI())); @@ -1563,9 +1546,9 @@ void sensors_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson) snprintf_P(svalue, ssvalue, PSTR("%s{\"Time\":\"%s\""), svalue, getDateTime().c_str()); for (byte i = 0; i < 4; i++) { if (pin[GPIO_SWT1 +i] < 99) { - byte swm = ((sysCfg.switchmode[i] == FOLLOW_INV)||(sysCfg.switchmode[i] == PUSHBUTTON_INV)); - snprintf_P(svalue, ssvalue, PSTR("%s, \"Switch%d\":\"%s\""), - svalue, i +1, (lastwallswitch[i]) ? (swm) ? MQTT_STATUS_ON : MQTT_STATUS_OFF : (swm) ? MQTT_STATUS_OFF : MQTT_STATUS_ON); + boolean swm = ((sysCfg.switchmode[i] == FOLLOW_INV)||(sysCfg.switchmode[i] == PUSHBUTTON_INV)); + snprintf_P(svalue, ssvalue, PSTR("%s, \"Switch%d\":\"%s\""), svalue, i +1, getStateText(swm ^ lastwallswitch[i])); + *djson = 1; } } #ifndef USE_ADC_VCC @@ -1693,11 +1676,13 @@ void every_second() if (hlw_flg) hlw_margin_chk(); - if ((rtcTime.Minute == 2) && (rtcTime.Second == 30)) { + if ((rtcTime.Minute == 2) && uptime_flg) { + uptime_flg = false; uptime++; snprintf_P(svalue, sizeof(svalue), PSTR("{\"Time\":\"%s\", \"Uptime\":%d}"), getDateTime().c_str(), uptime); mqtt_publish_topic_P(1, PSTR("UPTIME"), svalue); } + if ((rtcTime.Minute == 3) && !uptime_flg) uptime_flg = true; } void stateloop() @@ -2154,9 +2139,6 @@ void setup() } if (!spiffsPresent()) addLog_P(LOG_LEVEL_ERROR, PSTR("SPIFFS: ERROR - No spiffs present. Please reflash with at least 16K SPIFFS")); -#ifdef USE_SPIFFS - initSpiffs(); -#endif CFG_Load(); CFG_Delta(); diff --git a/sonoff/user_config.h b/sonoff/user_config.h index 66b898c9f..e3796e06f 100644 --- a/sonoff/user_config.h +++ b/sonoff/user_config.h @@ -17,10 +17,10 @@ #define SAVE_STATE 1 // [SaveState] Save changed power state to Flash (0 = disable, 1 = enable) // -- Wifi ---------------------------------------- -#define WIFI_IP_ADDRESS "0.0.0.0" // [IpAddress] Set to 0.0.0.0 for using DHCP or IP address -#define WIFI_GATEWAY "192.168.2.254" // {Gateway] If not using DHCP set Gateway IP address -#define WIFI_SUBNETMASK "255.255.255.0" // [Subnetmask] If not using DHCP set Network mask -#define WIFI_DNS "192.168.2.27" // [DnsServer] If not using DHCP set DNS IP address (might be equal to WIFI_GATEWAY) +#define WIFI_IP_ADDRESS "0.0.0.0" // [IpAddress1] Set to 0.0.0.0 for using DHCP or IP address +#define WIFI_GATEWAY "192.168.2.254" // {IpAddress2] If not using DHCP set Gateway IP address +#define WIFI_SUBNETMASK "255.255.255.0" // [IpAddress3] If not using DHCP set Network mask +#define WIFI_DNS "192.168.2.27" // [IpAddress4] If not using DHCP set DNS IP address (might be equal to WIFI_GATEWAY) #define STA_SSID1 "indebuurt1" // [Ssid1] Wifi SSID #define STA_PASS1 "VnsqrtnrsddbrN" // [Password1] Wifi password @@ -69,9 +69,9 @@ #define MQTT_POWER_RETAIN 0 // [PowerRetain] Power status message may send retain flag (0 = off, 1 = on) #define MQTT_SWITCH_RETAIN 0 // [SwitchRetain] Switch may send retain flag (0 = off, 1 = on) -#define MQTT_STATUS_OFF "OFF" // Command or Status result when turned off (needs to be a string like "0" or "Off") -#define MQTT_STATUS_ON "ON" // Command or Status result when turned on (needs to be a string like "1" or "On") -#define MQTT_CMND_TOGGLE "TOGGLE" // Command to send when toggling (needs to be a string like "2" or "Toggle") +#define MQTT_STATUS_OFF "OFF" // [StateText1] Command or Status result when turned off (needs to be a string like "0" or "Off") +#define MQTT_STATUS_ON "ON" // [StateText2] Command or Status result when turned on (needs to be a string like "1" or "On") +#define MQTT_CMND_TOGGLE "TOGGLE" // [StateText3] Command to send when toggling (needs to be a string like "2" or "Toggle") // -- MQTT - Telemetry ---------------------------- #define TELE_PERIOD 300 // [TelePeriod] Telemetry (0 = disable, 10 - 3600 seconds) @@ -137,7 +137,7 @@ #define USE_HTU // Add I2C code for HTU21/SI7013/SI7020/SI7021 sensor #define USE_SHT // Add I2C emulating code for SHT1X sensor -#define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k code, 0.3k mem) +#define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+3k code, 0.3k mem) #define USE_WS2812 // WS2812 Led string using library NeoPixelBus (+8k code, +1k mem) - Disable by // #define USE_WS2812_CTYPE 1 // WS2812 Color type (0 - RGB, 1 - GRB) diff --git a/sonoff/webserver.ino b/sonoff/webserver.ino index 60f7afbc0..fa230f5c6 100644 --- a/sonoff/webserver.ino +++ b/sonoff/webserver.ino @@ -130,6 +130,14 @@ const char HTTP_SCRIPT_CONSOL[] PROGMEM = "return false;" "}" ""; +const char HTTP_SCRIPT_MODULE[] PROGMEM = + "var os;" + "function sk(s,g){" + "var o=os.replace(\"value='\"+s+\"'\",\"selected value='\"+s+\"'\");" + "document.getElementById('g'+g).innerHTML=o;" + "}" + "function sl(){" + "var o0=\""; const char HTTP_LNK_STYLE[] PROGMEM = ".q{float:right;width:64px;text-align:right;}" ".l{background:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAALVBMVEX///8EBwfBwsLw8PAzNjaCg4NTVVUjJiZDRUUUFxdiZGSho6O" @@ -521,6 +529,16 @@ void handleConfig() boolean inModule(byte val, uint8_t *arr) { if (!val) return false; // None +#ifndef USE_I2C + if (val == GPIO_I2C_SCL) return true; + if (val == GPIO_I2C_SDA) return true; +#endif +#ifndef USE_WS2812 + if (val == GPIO_WS2812) return true; +#endif +#ifndef USE_IR_REMOTE + if (val == GPIO_IRSEND) return true; +#endif for (byte i = 0; i < MAX_GPIO_PIN; i++) { if (arr[i] == val) return true; } @@ -551,12 +569,14 @@ void handleModule() mytmplt cmodule; memcpy_P(&cmodule, &modules[sysCfg.module], sizeof(cmodule)); - String func = F("var os;function sk(s,g){var o=os.replace(\"value='\"+s+\"'\",\"selected value='\"+s+\"'\");document.getElementById('g'+g).innerHTML=o;}function sl(){var o0=\""); + + String func = FPSTR(HTTP_SCRIPT_MODULE); for (byte j = 0; j < GPIO_SENSOR_END; j++) { - snprintf_P(stemp, sizeof(stemp), sensors[j]); - snprintf_P(line, sizeof(line), PSTR("%s'%d'>%02d %s-2"), - (inModule(j, cmodule.gp.io))?"%02d %s-2"), j, j, stemp); + func += line; + } } func += F("\";os=o0.replace(/-1/g,\"