diff --git a/README.md b/README.md index 681caed8f..7fdfadb54 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 **3.9.18** - See ```sonoff/_releasenotes.ino``` for change information. +Current version is **3.9.19** - See ```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.ino.bin b/api/arduino/sonoff.ino.bin index cbce9d36f..391f562b6 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 99e30fbf8..23df798ff 100644 --- a/sonoff/_releasenotes.ino +++ b/sonoff/_releasenotes.ino @@ -1,4 +1,8 @@ -/* 3.9.18 20170218 +/* 3.9.19 20170219 + * Sonoff Led: Made GPIO04, 05 and 15 available for user + * Sonoff Led: Add commands Fade, Speed, WakupDuration, Wakeup and LedTable + * + * 3.9.18 20170218 * Fix ledstate 0 to turn off led * Fix Sonoff Led dimmer range (#16) * Change Sonoff Led command Dimmer to act on both cold and warm color diff --git a/sonoff/settings.h b/sonoff/settings.h new file mode 100644 index 000000000..049cb3410 --- /dev/null +++ b/sonoff/settings.h @@ -0,0 +1,188 @@ +/*********************************************************************************************\ + * Config settings +\*********************************************************************************************/ + +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; + +struct SYSCFG { + unsigned long cfg_holder; + unsigned long saveFlag; + unsigned long version; + unsigned long bootcount; + byte migflg; + int16_t savedata; + byte savestate; + byte model; + int8_t timezone; + char otaUrl[101]; + char ex_friendlyname[33]; // Not used since 3.2.5 - see below + + byte serial_enable; + byte seriallog_level; + uint8_t sta_config; + byte sta_active; + char sta_ssid[2][33]; + char sta_pwd[2][65]; + char hostname[33]; + char syslog_host[33]; + uint16_t syslog_port; + byte syslog_level; + uint8_t webserver; + byte weblog_level; + + char mqtt_fingerprint[60]; + char mqtt_host[33]; + uint16_t mqtt_port; + char mqtt_client[33]; + char mqtt_user[33]; + char mqtt_pwd[33]; + char mqtt_topic[33]; + char button_topic[33]; + char mqtt_grptopic[33]; + char mqtt_subtopic[33]; + byte mqtt_button_retain; + byte mqtt_power_retain; + byte value_units; + byte message_format; // Not used since 3.2.6a + uint16_t tele_period; + + uint8_t power; + uint8_t ledstate; + uint8_t switchmode; + + 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]; + + unsigned long hlw_pcal; + unsigned long hlw_ucal; + unsigned long hlw_ical; + unsigned long hlw_kWhtoday; + unsigned long hlw_kWhyesterday; + uint16_t hlw_kWhdoy; + 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 + + uint16_t pulsetime; + uint8_t poweronstate; + uint16_t blinktime; + uint16_t blinkcount; + + uint16_t ws_pixels; + uint8_t ws_red; + uint8_t ws_green; + uint8_t ws_blue; + uint8_t ws_ledtable; + uint8_t ws_dimmer; + uint8_t ws_fade; + uint8_t ws_speed; + uint8_t ws_scheme; + uint8_t ws_width; + uint16_t ws_wakeup; + + char friendlyname[4][33]; + char switch_topic[33]; + byte mqtt_switch_retain; + uint8_t mqtt_enabled; + uint8_t sleep; + + uint16_t domoticz_switch_idx[4]; + uint16_t domoticz_sensor_idx[12]; + + uint8_t module; + mytmplt my_module; + + uint16_t led_pixels; + uint8_t led_color[5]; + uint8_t led_table; + uint8_t led_dimmer[3]; + uint8_t led_fade; + uint8_t led_speed; + uint8_t led_scheme; + uint8_t led_width; + uint16_t led_wakeup; + + uint8_t emulation; + +} sysCfg; + diff --git a/sonoff/settings.ino b/sonoff/settings.ino new file mode 100644 index 000000000..61f8f4e65 --- /dev/null +++ b/sonoff/settings.ino @@ -0,0 +1,632 @@ +/* +Copyright (c) 2017 Theo Arends. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/*********************************************************************************************\ + * Config - Flash or Spiffs +\*********************************************************************************************/ + +extern "C" { +#include "spi_flash.h" +} +#include "eboot_command.h" + +#define SPIFFS_START ((uint32_t)&_SPIFFS_start - 0x40200000) / SPI_FLASH_SEC_SIZE +#define SPIFFS_END ((uint32_t)&_SPIFFS_end - 0x40200000) / SPI_FLASH_SEC_SIZE + +// Version 2.x config +#define SPIFFS_CONFIG2 "/config.ini" +#define CFG_LOCATION2 SPIFFS_END - 2 + +// Version 3.x config +#define SPIFFS_CONFIG "/cfg.ini" +#define CFG_LOCATION SPIFFS_END - 4 + +uint32_t _cfgHash = 0; +int spiffsflag = 0; + +/********************************************************************************************/ +/* + * Based on cores/esp8266/Updater.cpp + */ +void setFlashChipMode(byte option, byte mode) +{ + char log[LOGSZ]; + uint8_t *_buffer; + uint32_t address; + + if (option) { + eboot_command ebcmd; + eboot_command_read(&ebcmd); + address = ebcmd.args[0]; + } else { + address = 0; + } + _buffer = new uint8_t[FLASH_SECTOR_SIZE]; + if (spi_flash_read(address, (uint32_t*)_buffer, FLASH_SECTOR_SIZE) == SPI_FLASH_RESULT_OK) { + if (_buffer[2] != mode) { + _buffer[2] = mode &3; + noInterrupts(); + if (spi_flash_erase_sector(address / FLASH_SECTOR_SIZE) == SPI_FLASH_RESULT_OK) { + spi_flash_write(address, (uint32_t*)_buffer, FLASH_SECTOR_SIZE); + } + interrupts(); + snprintf_P(log, sizeof(log), PSTR("FLSH: Updated Flash Chip Mode to %d"), (option) ? mode : ESP.getFlashChipMode()); + addLog(LOG_LEVEL_DEBUG, log); + } + } + delete[] _buffer; +} + +boolean spiffsPresent() +{ + return (SPIFFS_END - SPIFFS_START); +} + +uint32_t getHash() +{ + uint32_t hash = 0; + uint8_t *bytes = (uint8_t*)&sysCfg; + + for (uint16_t i = 0; i < sizeof(SYSCFG); i++) hash += bytes[i]*(i+1); + return hash; +} + +/*********************************************************************************************\ + * Config Save - Save parameters to Flash or Spiffs ONLY if any parameter has changed +\*********************************************************************************************/ + +void CFG_Save() +{ + char log[LOGSZ]; + + 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 + 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)); + } + sysCfg.saveFlag++; + 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)); + 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(); + } +} + +void CFG_Load() +{ + char log[LOGSZ]; + + 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; + } _sysCfgH; + + noInterrupts(); + spi_flash_read((CFG_LOCATION) * SPI_FLASH_SEC_SIZE, (uint32*)&sysCfg, sizeof(SYSCFG)); + spi_flash_read((CFG_LOCATION + 1) * SPI_FLASH_SEC_SIZE, (uint32*)&_sysCfgH, sizeof(SYSCFGH)); + if (sysCfg.saveFlag < _sysCfgH.saveFlag) + spi_flash_read((CFG_LOCATION + 1) * SPI_FLASH_SEC_SIZE, (uint32*)&sysCfg, sizeof(SYSCFG)); + interrupts(); + snprintf_P(log, sizeof(log), PSTR("Config: Loaded configuration from flash at %X and count %d"), CFG_LOCATION + (sysCfg.saveFlag &1), sysCfg.saveFlag); + addLog(LOG_LEVEL_DEBUG, log); + } + } +// 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(); + } + } + _cfgHash = getHash(); +} + +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(); +} + +void CFG_Erase() +{ + char log[LOGSZ]; + SpiFlashOpResult result; + + uint32_t _sectorStart = (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 1; + uint32_t _sectorEnd = ESP.getFlashChipRealSize() / SPI_FLASH_SEC_SIZE; + boolean _serialoutput = (LOG_LEVEL_DEBUG_MORE <= seriallog_level); + + snprintf_P(log, sizeof(log), PSTR("Config: Erasing %d flash sectors"), _sectorEnd - _sectorStart); + addLog(LOG_LEVEL_DEBUG, log); + + for (uint32_t _sector = _sectorStart; _sector < _sectorEnd; _sector++) { + noInterrupts(); + result = spi_flash_erase_sector(_sector); + interrupts(); + if (_serialoutput) { + Serial.print(F("Flash: Erased sector ")); + Serial.print(_sector); + if (result == SPI_FLASH_RESULT_OK) { + Serial.println(F(" OK")); + } else { + Serial.println(F(" Error")); + } + delay(10); + } + } +} + +void CFG_Dump() +{ + #define CFG_COLS 16 + + char log[LOGSZ]; + uint16_t idx, maxrow, row, col; + + uint8_t *buffer = (uint8_t *) &sysCfg; + maxrow = ((sizeof(SYSCFG)+CFG_COLS)/CFG_COLS); + + for (row = 0; row < maxrow; row++) { + idx = row * CFG_COLS; + snprintf_P(log, sizeof(log), PSTR("%04X:"), idx); + for (col = 0; col < CFG_COLS; col++) { + if (!(col%4)) snprintf_P(log, sizeof(log), PSTR("%s "), log); + snprintf_P(log, sizeof(log), PSTR("%s %02X"), log, buffer[idx + col]); + } + snprintf_P(log, sizeof(log), PSTR("%s |"), log); + for (col = 0; col < CFG_COLS; col++) { +// if (!(col%4)) snprintf_P(log, sizeof(log), PSTR("%s "), log); + snprintf_P(log, sizeof(log), PSTR("%s%c"), log, ((buffer[idx + col] > 0x20) && (buffer[idx + col] < 0x7F)) ? (char)buffer[idx + col] : ' '); + } + snprintf_P(log, sizeof(log), PSTR("%s|"), log); + addLog(LOG_LEVEL_INFO, log); + } +} + +#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() +{ + memset(&sysCfg, 0x00, sizeof(SYSCFG)); + + sysCfg.cfg_holder = CFG_HOLDER; + sysCfg.saveFlag = 0; + sysCfg.version = VERSION; + sysCfg.bootcount = 0; +} + +void CFG_DefaultSet2() +{ + sysCfg.migflg = 0xA5; + sysCfg.savedata = SAVE_DATA; + sysCfg.savestate = SAVE_STATE; + sysCfg.module = MODULE; + sysCfg.model = 0; + sysCfg.timezone = APP_TIMEZONE; + strlcpy(sysCfg.otaUrl, OTA_URL, sizeof(sysCfg.otaUrl)); + strlcpy(sysCfg.ex_friendlyname, FRIENDLY_NAME, sizeof(sysCfg.ex_friendlyname)); + + sysCfg.seriallog_level = SERIAL_LOG_LEVEL; + sysCfg.sta_active = 0; + strlcpy(sysCfg.sta_ssid[0], STA_SSID1, sizeof(sysCfg.sta_ssid[0])); + strlcpy(sysCfg.sta_pwd[0], STA_PASS1, sizeof(sysCfg.sta_pwd[0])); + strlcpy(sysCfg.sta_ssid[1], STA_SSID2, sizeof(sysCfg.sta_ssid[1])); + strlcpy(sysCfg.sta_pwd[1], STA_PASS2, sizeof(sysCfg.sta_pwd[1])); + strlcpy(sysCfg.hostname, WIFI_HOSTNAME, sizeof(sysCfg.hostname)); + sysCfg.sta_config = WIFI_CONFIG_TOOL; + strlcpy(sysCfg.syslog_host, SYS_LOG_HOST, sizeof(sysCfg.syslog_host)); + sysCfg.syslog_port = SYS_LOG_PORT; + sysCfg.syslog_level = SYS_LOG_LEVEL; + sysCfg.webserver = WEB_SERVER; + sysCfg.weblog_level = WEB_LOG_LEVEL; + + strlcpy(sysCfg.mqtt_fingerprint, MQTT_FINGERPRINT, sizeof(sysCfg.mqtt_fingerprint)); + strlcpy(sysCfg.mqtt_host, MQTT_HOST, sizeof(sysCfg.mqtt_host)); + sysCfg.mqtt_port = MQTT_PORT; + strlcpy(sysCfg.mqtt_client, MQTT_CLIENT_ID, sizeof(sysCfg.mqtt_client)); + strlcpy(sysCfg.mqtt_user, MQTT_USER, sizeof(sysCfg.mqtt_user)); + strlcpy(sysCfg.mqtt_pwd, MQTT_PASS, sizeof(sysCfg.mqtt_pwd)); + 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 = VALUE_UNITS; + sysCfg.message_format = 0; + sysCfg.tele_period = TELE_PERIOD; + + sysCfg.power = APP_POWER; + sysCfg.poweronstate = APP_POWERON_STATE; + sysCfg.pulsetime = APP_PULSETIME; + sysCfg.ledstate = APP_LEDSTATE; + sysCfg.switchmode = SWITCH_MODE; + sysCfg.blinktime = APP_BLINKTIME; + sysCfg.blinkcount = APP_BLINKCOUNT; + sysCfg.sleep = APP_SLEEP; + + strlcpy(sysCfg.domoticz_in_topic, DOMOTICZ_IN_TOPIC, sizeof(sysCfg.domoticz_in_topic)); + strlcpy(sysCfg.domoticz_out_topic, DOMOTICZ_OUT_TOPIC, sizeof(sysCfg.domoticz_out_topic)); + sysCfg.domoticz_update_timer = DOMOTICZ_UPDATE_TIMER; + for (byte i = 0; i < 4; i++) { + sysCfg.domoticz_relay_idx[i] = 0; + sysCfg.domoticz_key_idx[i] = 0; + sysCfg.domoticz_switch_idx[i] = 0; + } + for (byte i = 0; i < 12; i++) sysCfg.domoticz_sensor_idx[i] = 0; + + sysCfg.hlw_pcal = HLW_PREF_PULSE; + sysCfg.hlw_ucal = HLW_UREF_PULSE; + sysCfg.hlw_ical = HLW_IREF_PULSE; + sysCfg.hlw_kWhtoday = 0; + sysCfg.hlw_kWhyesterday = 0; + sysCfg.hlw_kWhdoy = 0; + sysCfg.hlw_pmin = 0; + sysCfg.hlw_pmax = 0; + sysCfg.hlw_umin = 0; + sysCfg.hlw_umax = 0; + sysCfg.hlw_imin = 0; + sysCfg.hlw_imax = 0; + sysCfg.hlw_mpl = 0; // MaxPowerLimit + sysCfg.hlw_mplh = MAX_POWER_HOLD; + sysCfg.hlw_mplw = MAX_POWER_WINDOW; + sysCfg.hlw_mspl = 0; // MaxSafePowerLimit + sysCfg.hlw_msplh = SAFE_POWER_HOLD; + sysCfg.hlw_msplw = SAFE_POWER_WINDOW; + sysCfg.hlw_mkwh = 0; // MaxEnergy + sysCfg.hlw_mkwhs = 0; // MaxEnergyStart + + sysCfg.ws_pixels = WS2812_LEDS; + sysCfg.ws_red = 255; + sysCfg.ws_green = 0; + sysCfg.ws_blue = 0; + sysCfg.ws_ledtable = 0; + sysCfg.ws_dimmer = 8; + sysCfg.ws_fade = 0; + sysCfg.ws_speed = 1; + sysCfg.ws_scheme = 0; + sysCfg.ws_width = 1; + sysCfg.ws_wakeup = 0; + + strlcpy(sysCfg.friendlyname[0], FRIENDLY_NAME, sizeof(sysCfg.friendlyname[0])); + strlcpy(sysCfg.friendlyname[1], FRIENDLY_NAME"2", sizeof(sysCfg.friendlyname[1])); + strlcpy(sysCfg.friendlyname[2], FRIENDLY_NAME"3", sizeof(sysCfg.friendlyname[2])); + strlcpy(sysCfg.friendlyname[3], FRIENDLY_NAME"4", sizeof(sysCfg.friendlyname[3])); + + for (byte i = 0; i < MAX_GPIO_PIN; i++) sysCfg.my_module.gp.io[i] = 0; + + sysCfg.led_pixels = 0; + for (byte i = 0; i < 5; i++) sysCfg.led_color[i] = 255; + sysCfg.led_table = 0; + for (byte i = 0; i < 3; i++) sysCfg.led_dimmer[i] = 10; + sysCfg.led_fade = 0; + sysCfg.led_speed = 0; + sysCfg.led_scheme = 0; + sysCfg.led_width = 0; + sysCfg.led_wakeup = 0; + + strlcpy(sysCfg.switch_topic, "0", sizeof(sysCfg.switch_topic)); + sysCfg.mqtt_switch_retain = MQTT_SWITCH_RETAIN; + sysCfg.mqtt_enabled = MQTT_USE; + + sysCfg.emulation = EMULATION; + +} + +void CFG_Default() +{ + addLog_P(LOG_LEVEL_NONE, PSTR("Config: Use default configuration")); + CFG_DefaultSet1(); + CFG_DefaultSet2(); + CFG_Save(); +} + +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.ex_friendlyname, sysCfg2.mqtt_client, sizeof(sysCfg.ex_friendlyname)); + } + 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 = 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(); +} + +/********************************************************************************************/ + +void CFG_Delta() +{ + if (sysCfg.version != VERSION) { // Fix version dependent changes + if (sysCfg.version < 0x03000600) { // 3.0.6 - Add parameter + sysCfg.pulsetime = APP_PULSETIME; + } + if (sysCfg.version < 0x03010100) { // 3.1.1 - Add parameter + sysCfg.poweronstate = APP_POWERON_STATE; + } + if (sysCfg.version < 0x03010200) { // 3.1.2 - Add parameter + if (sysCfg.poweronstate == 2) sysCfg.poweronstate = 3; + } + if (sysCfg.version < 0x03010600) { // 3.1.6 - Add parameter + sysCfg.blinktime = APP_BLINKTIME; + sysCfg.blinkcount = APP_BLINKCOUNT; + } + if (sysCfg.version < 0x03011000) { // 3.1.16 - Add parameter + getClient(sysCfg.ex_friendlyname, sysCfg.mqtt_client, sizeof(sysCfg.ex_friendlyname)); + } + if (sysCfg.version < 0x03020400) { // 3.2.4 - Add parameter + sysCfg.ws_pixels = WS2812_LEDS; + sysCfg.ws_red = 255; + sysCfg.ws_green = 0; + sysCfg.ws_blue = 0; + sysCfg.ws_ledtable = 0; + sysCfg.ws_dimmer = 8; + sysCfg.ws_fade = 0; + sysCfg.ws_speed = 1; + sysCfg.ws_scheme = 0; + sysCfg.ws_width = 1; + sysCfg.ws_wakeup = 0; + } + if (sysCfg.version < 0x03020500) { // 3.2.5 - Add parameter + strlcpy(sysCfg.friendlyname[0], sysCfg.ex_friendlyname, sizeof(sysCfg.friendlyname[0])); + strlcpy(sysCfg.friendlyname[1], FRIENDLY_NAME"2", sizeof(sysCfg.friendlyname[1])); + strlcpy(sysCfg.friendlyname[2], FRIENDLY_NAME"3", sizeof(sysCfg.friendlyname[2])); + strlcpy(sysCfg.friendlyname[3], FRIENDLY_NAME"4", sizeof(sysCfg.friendlyname[3])); + } + if (sysCfg.version < 0x03020800) { // 3.2.8 - Add parameter + strlcpy(sysCfg.switch_topic, sysCfg.button_topic, sizeof(sysCfg.switch_topic)); + sysCfg.mqtt_switch_retain = MQTT_SWITCH_RETAIN; + sysCfg.mqtt_enabled = MQTT_USE; + } + if (sysCfg.version < 0x03020C00) { // 3.2.12 - Add parameter + sysCfg.sleep = APP_SLEEP; + } + if (sysCfg.version < 0x03090204) { // 3.9.2d - Add parameter + for (byte i = 0; i < 4; i++) sysCfg.domoticz_switch_idx[i] = 0; + for (byte i = 0; i < 12; i++) sysCfg.domoticz_sensor_idx[i] = 0; + + sysCfg.module = MODULE; + for (byte i = 0; i < MAX_GPIO_PIN; i++) sysCfg.my_module.gp.io[i] = 0; + + sysCfg.led_pixels = 0; + for (byte i = 0; i < 5; i++) sysCfg.led_color[i] = 255; + sysCfg.led_table = 0; + for (byte i = 0; i < 3; i++) sysCfg.led_dimmer[i] = 10; + sysCfg.led_fade = 0; + sysCfg.led_speed = 0; + sysCfg.led_scheme = 0; + sysCfg.led_width = 0; + sysCfg.led_wakeup = 0; + } + if (sysCfg.version < 0x03090700) { // 3.9.7 - Add parameter + sysCfg.emulation = EMULATION; + } + + sysCfg.version = VERSION; + } +} + diff --git a/sonoff/sonoff.ino b/sonoff/sonoff.ino index cb85376b4..318f3f633 100644 --- a/sonoff/sonoff.ino +++ b/sonoff/sonoff.ino @@ -10,7 +10,7 @@ * ==================================================== */ -#define VERSION 0x03091200 // 3.9.18 +#define VERSION 0x03091300 // 3.9.19 //#define BE_MINIMAL // Compile a minimal version if upgrade memory gets tight (still 404k) // To be used as step 1. Next step is compile and use desired version @@ -155,6 +155,7 @@ enum butt_t {PRESSED, NOT_PRESSED}; #ifdef USE_I2C #include // I2C support library #endif // USE_I2C +#include "settings.h" typedef void (*rtcCallback)(); @@ -171,190 +172,6 @@ const char commands[MAX_BUTTON_COMMANDS][14] PROGMEM = { const char wificfg[5][12] PROGMEM = { "Restart", "Smartconfig", "Wifimanager", "WPSconfig", "Retry" }; -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; - -struct SYSCFG { - unsigned long cfg_holder; - unsigned long saveFlag; - unsigned long version; - unsigned long bootcount; - byte migflg; - int16_t savedata; - byte savestate; - byte model; - int8_t timezone; - char otaUrl[101]; - char ex_friendlyname[33]; // Not used since 3.2.5 - see below - - byte serial_enable; - byte seriallog_level; - uint8_t sta_config; - byte sta_active; - char sta_ssid[2][33]; - char sta_pwd[2][65]; - char hostname[33]; - char syslog_host[33]; - uint16_t syslog_port; - byte syslog_level; - uint8_t webserver; - byte weblog_level; - - char mqtt_fingerprint[60]; - char mqtt_host[33]; - uint16_t mqtt_port; - char mqtt_client[33]; - char mqtt_user[33]; - char mqtt_pwd[33]; - char mqtt_topic[33]; - char button_topic[33]; - char mqtt_grptopic[33]; - char mqtt_subtopic[33]; - byte mqtt_button_retain; - byte mqtt_power_retain; - byte value_units; - byte message_format; // Not used since 3.2.6a - uint16_t tele_period; - - uint8_t power; - uint8_t ledstate; - uint8_t switchmode; - - 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]; - - unsigned long hlw_pcal; - unsigned long hlw_ucal; - unsigned long hlw_ical; - unsigned long hlw_kWhtoday; - unsigned long hlw_kWhyesterday; - uint16_t hlw_kWhdoy; - 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 - - uint16_t pulsetime; - uint8_t poweronstate; - uint16_t blinktime; - uint16_t blinkcount; - - uint16_t ws_pixels; - uint8_t ws_red; - uint8_t ws_green; - uint8_t ws_blue; - uint8_t ws_ledtable; - uint8_t ws_dimmer; - uint8_t ws_fade; - uint8_t ws_speed; - uint8_t ws_scheme; - uint8_t ws_width; - uint16_t ws_wakeup; - - char friendlyname[4][33]; - char switch_topic[33]; - byte mqtt_switch_retain; - uint8_t mqtt_enabled; - uint8_t sleep; - - uint16_t domoticz_switch_idx[4]; - uint16_t domoticz_sensor_idx[12]; - - uint8_t module; - mytmplt my_module; - - uint16_t led_pixels; - uint8_t led_color[5]; - uint8_t led_table; - uint8_t led_dimmer[3]; - uint8_t led_fade; - uint8_t led_speed; - uint8_t led_scheme; - uint8_t led_width; - uint16_t led_wakeup; - - uint8_t emulation; - -} sysCfg; - struct TIME_T { uint8_t Second; uint8_t Minute; @@ -451,324 +268,6 @@ boolean mDNSbegun = false; /********************************************************************************************/ -void CFG_DefaultSet1() -{ - memset(&sysCfg, 0x00, sizeof(SYSCFG)); - - sysCfg.cfg_holder = CFG_HOLDER; - sysCfg.saveFlag = 0; - sysCfg.version = VERSION; - sysCfg.bootcount = 0; -} - -void CFG_DefaultSet2() -{ - sysCfg.migflg = 0xA5; - sysCfg.savedata = SAVE_DATA; - sysCfg.savestate = SAVE_STATE; - sysCfg.module = MODULE; - sysCfg.model = 0; - sysCfg.timezone = APP_TIMEZONE; - strlcpy(sysCfg.otaUrl, OTA_URL, sizeof(sysCfg.otaUrl)); - strlcpy(sysCfg.ex_friendlyname, FRIENDLY_NAME, sizeof(sysCfg.ex_friendlyname)); - - sysCfg.seriallog_level = SERIAL_LOG_LEVEL; - sysCfg.sta_active = 0; - strlcpy(sysCfg.sta_ssid[0], STA_SSID1, sizeof(sysCfg.sta_ssid[0])); - strlcpy(sysCfg.sta_pwd[0], STA_PASS1, sizeof(sysCfg.sta_pwd[0])); - strlcpy(sysCfg.sta_ssid[1], STA_SSID2, sizeof(sysCfg.sta_ssid[1])); - strlcpy(sysCfg.sta_pwd[1], STA_PASS2, sizeof(sysCfg.sta_pwd[1])); - strlcpy(sysCfg.hostname, WIFI_HOSTNAME, sizeof(sysCfg.hostname)); - sysCfg.sta_config = WIFI_CONFIG_TOOL; - strlcpy(sysCfg.syslog_host, SYS_LOG_HOST, sizeof(sysCfg.syslog_host)); - sysCfg.syslog_port = SYS_LOG_PORT; - sysCfg.syslog_level = SYS_LOG_LEVEL; - sysCfg.webserver = WEB_SERVER; - sysCfg.weblog_level = WEB_LOG_LEVEL; - - strlcpy(sysCfg.mqtt_fingerprint, MQTT_FINGERPRINT, sizeof(sysCfg.mqtt_fingerprint)); - strlcpy(sysCfg.mqtt_host, MQTT_HOST, sizeof(sysCfg.mqtt_host)); - sysCfg.mqtt_port = MQTT_PORT; - strlcpy(sysCfg.mqtt_client, MQTT_CLIENT_ID, sizeof(sysCfg.mqtt_client)); - strlcpy(sysCfg.mqtt_user, MQTT_USER, sizeof(sysCfg.mqtt_user)); - strlcpy(sysCfg.mqtt_pwd, MQTT_PASS, sizeof(sysCfg.mqtt_pwd)); - 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 = VALUE_UNITS; - sysCfg.message_format = 0; - sysCfg.tele_period = TELE_PERIOD; - - sysCfg.power = APP_POWER; - sysCfg.poweronstate = APP_POWERON_STATE; - sysCfg.pulsetime = APP_PULSETIME; - sysCfg.ledstate = APP_LEDSTATE; - sysCfg.switchmode = SWITCH_MODE; - sysCfg.blinktime = APP_BLINKTIME; - sysCfg.blinkcount = APP_BLINKCOUNT; - sysCfg.sleep = APP_SLEEP; - - strlcpy(sysCfg.domoticz_in_topic, DOMOTICZ_IN_TOPIC, sizeof(sysCfg.domoticz_in_topic)); - strlcpy(sysCfg.domoticz_out_topic, DOMOTICZ_OUT_TOPIC, sizeof(sysCfg.domoticz_out_topic)); - sysCfg.domoticz_update_timer = DOMOTICZ_UPDATE_TIMER; - for (byte i = 0; i < 4; i++) { - sysCfg.domoticz_relay_idx[i] = 0; - sysCfg.domoticz_key_idx[i] = 0; - sysCfg.domoticz_switch_idx[i] = 0; - } - for (byte i = 0; i < 12; i++) sysCfg.domoticz_sensor_idx[i] = 0; - - sysCfg.hlw_pcal = HLW_PREF_PULSE; - sysCfg.hlw_ucal = HLW_UREF_PULSE; - sysCfg.hlw_ical = HLW_IREF_PULSE; - sysCfg.hlw_kWhtoday = 0; - sysCfg.hlw_kWhyesterday = 0; - sysCfg.hlw_kWhdoy = 0; - sysCfg.hlw_pmin = 0; - sysCfg.hlw_pmax = 0; - sysCfg.hlw_umin = 0; - sysCfg.hlw_umax = 0; - sysCfg.hlw_imin = 0; - sysCfg.hlw_imax = 0; - sysCfg.hlw_mpl = 0; // MaxPowerLimit - sysCfg.hlw_mplh = MAX_POWER_HOLD; - sysCfg.hlw_mplw = MAX_POWER_WINDOW; - sysCfg.hlw_mspl = 0; // MaxSafePowerLimit - sysCfg.hlw_msplh = SAFE_POWER_HOLD; - sysCfg.hlw_msplw = SAFE_POWER_WINDOW; - sysCfg.hlw_mkwh = 0; // MaxEnergy - sysCfg.hlw_mkwhs = 0; // MaxEnergyStart - - sysCfg.ws_pixels = WS2812_LEDS; - sysCfg.ws_red = 255; - sysCfg.ws_green = 0; - sysCfg.ws_blue = 0; - sysCfg.ws_ledtable = 0; - sysCfg.ws_dimmer = 8; - sysCfg.ws_fade = 0; - sysCfg.ws_speed = 1; - sysCfg.ws_scheme = 0; - sysCfg.ws_width = 1; - sysCfg.ws_wakeup = 0; - - strlcpy(sysCfg.friendlyname[0], FRIENDLY_NAME, sizeof(sysCfg.friendlyname[0])); - strlcpy(sysCfg.friendlyname[1], FRIENDLY_NAME"2", sizeof(sysCfg.friendlyname[1])); - strlcpy(sysCfg.friendlyname[2], FRIENDLY_NAME"3", sizeof(sysCfg.friendlyname[2])); - strlcpy(sysCfg.friendlyname[3], FRIENDLY_NAME"4", sizeof(sysCfg.friendlyname[3])); - - for (byte i = 0; i < MAX_GPIO_PIN; i++) sysCfg.my_module.gp.io[i] = 0; - - sysCfg.led_pixels = 0; - for (byte i = 0; i < 5; i++) sysCfg.led_color[i] = 255; - sysCfg.led_table = 0; - for (byte i = 0; i < 3; i++) sysCfg.led_dimmer[i] = 10; - sysCfg.led_fade = 0; - sysCfg.led_speed = 0; - sysCfg.led_scheme = 0; - sysCfg.led_width = 0; - sysCfg.led_wakeup = 0; - - strlcpy(sysCfg.switch_topic, "0", sizeof(sysCfg.switch_topic)); - sysCfg.mqtt_switch_retain = MQTT_SWITCH_RETAIN; - sysCfg.mqtt_enabled = MQTT_USE; - - sysCfg.emulation = EMULATION; - -} - -void CFG_Default() -{ - addLog_P(LOG_LEVEL_NONE, PSTR("Config: Use default configuration")); - CFG_DefaultSet1(); - CFG_DefaultSet2(); - CFG_Save(); -} - -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.ex_friendlyname, sysCfg2.mqtt_client, sizeof(sysCfg.ex_friendlyname)); - } - 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 = 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(); -} - -void CFG_Delta() -{ - if (sysCfg.version != VERSION) { // Fix version dependent changes - if (sysCfg.version < 0x03000600) { // 3.0.6 - Add parameter - sysCfg.pulsetime = APP_PULSETIME; - } - if (sysCfg.version < 0x03010100) { // 3.1.1 - Add parameter - sysCfg.poweronstate = APP_POWERON_STATE; - } - if (sysCfg.version < 0x03010200) { // 3.1.2 - Add parameter - if (sysCfg.poweronstate == 2) sysCfg.poweronstate = 3; - } - if (sysCfg.version < 0x03010600) { // 3.1.6 - Add parameter - sysCfg.blinktime = APP_BLINKTIME; - sysCfg.blinkcount = APP_BLINKCOUNT; - } - if (sysCfg.version < 0x03011000) { // 3.1.16 - Add parameter - getClient(sysCfg.ex_friendlyname, sysCfg.mqtt_client, sizeof(sysCfg.ex_friendlyname)); - } - if (sysCfg.version < 0x03020400) { // 3.2.4 - Add parameter - sysCfg.ws_pixels = WS2812_LEDS; - sysCfg.ws_red = 255; - sysCfg.ws_green = 0; - sysCfg.ws_blue = 0; - sysCfg.ws_ledtable = 0; - sysCfg.ws_dimmer = 8; - sysCfg.ws_fade = 0; - sysCfg.ws_speed = 1; - sysCfg.ws_scheme = 0; - sysCfg.ws_width = 1; - sysCfg.ws_wakeup = 0; - } - if (sysCfg.version < 0x03020500) { // 3.2.5 - Add parameter - strlcpy(sysCfg.friendlyname[0], sysCfg.ex_friendlyname, sizeof(sysCfg.friendlyname[0])); - strlcpy(sysCfg.friendlyname[1], FRIENDLY_NAME"2", sizeof(sysCfg.friendlyname[1])); - strlcpy(sysCfg.friendlyname[2], FRIENDLY_NAME"3", sizeof(sysCfg.friendlyname[2])); - strlcpy(sysCfg.friendlyname[3], FRIENDLY_NAME"4", sizeof(sysCfg.friendlyname[3])); - } - if (sysCfg.version < 0x03020800) { // 3.2.8 - Add parameter - strlcpy(sysCfg.switch_topic, sysCfg.button_topic, sizeof(sysCfg.switch_topic)); - sysCfg.mqtt_switch_retain = MQTT_SWITCH_RETAIN; - sysCfg.mqtt_enabled = MQTT_USE; - } - if (sysCfg.version < 0x03020C00) { // 3.2.12 - Add parameter - sysCfg.sleep = APP_SLEEP; - } - if (sysCfg.version < 0x03090204) { // 3.9.2d - Add parameter - for (byte i = 0; i < 4; i++) sysCfg.domoticz_switch_idx[i] = 0; - for (byte i = 0; i < 12; i++) sysCfg.domoticz_sensor_idx[i] = 0; - - sysCfg.module = MODULE; - for (byte i = 0; i < MAX_GPIO_PIN; i++) sysCfg.my_module.gp.io[i] = 0; - - sysCfg.led_pixels = 0; - for (byte i = 0; i < 5; i++) sysCfg.led_color[i] = 255; - sysCfg.led_table = 0; - for (byte i = 0; i < 3; i++) sysCfg.led_dimmer[i] = 10; - sysCfg.led_fade = 0; - sysCfg.led_speed = 0; - sysCfg.led_scheme = 0; - sysCfg.led_width = 0; - sysCfg.led_wakeup = 0; - } - if (sysCfg.version < 0x03090700) { // 3.9.7 - Add parameter - sysCfg.emulation = EMULATION; - } - - sysCfg.version = VERSION; - } -} - -/********************************************************************************************/ - void getClient(char* output, const char* input, byte size) { char *token; @@ -821,7 +320,7 @@ void setRelay(uint8_t power) Serial.flush(); } else if (sysCfg.module == SONOFF_LED) { - sl_setColor(power &1); + sl_setPower(power &1); } else if (sysCfg.module == EXS_RELAY) { setLatchingRelay(power, 1); @@ -844,68 +343,6 @@ void setLed(uint8_t state) /********************************************************************************************/ -void sl_setDim(uint8_t *my_color) -{ - float newDim, fmyCld, fmyWrm, fmyRed, fmyGrn, fmyBlu; - - newDim = 100 / (float)sysCfg.led_dimmer[0]; - fmyCld = (float)sysCfg.led_color[0] / newDim; - fmyWrm = (float)sysCfg.led_color[1] / newDim; - fmyRed = (float)sysCfg.led_color[2] / newDim; - fmyGrn = (float)sysCfg.led_color[3] / newDim; - fmyBlu = (float)sysCfg.led_color[4] / newDim; - my_color[0] = (uint8_t)fmyCld; - my_color[1] = (uint8_t)fmyWrm; - my_color[2] = (uint8_t)fmyRed; - my_color[3] = (uint8_t)fmyGrn; - my_color[4] = (uint8_t)fmyBlu; -} - -void sl_setColor(byte type) -{ -// 0 = Off -// 1 = On -// 2 = Dim cold/warm -// 3 = Dim color - - uint8_t my_color[5]; - - sl_setDim(my_color); - if (type == 0) { - for (byte i = 0; i < 5; i++) { - if (pin[GPIO_PWM0 +i] < 99) analogWrite(pin[GPIO_PWM0 +i], 0); - } - } - else if (type == 1) { - for (byte i = 0; i < 5; i++) { - if (pin[GPIO_PWM0 +i] < 99) analogWrite(pin[GPIO_PWM0 +i], my_color[i]); - } - } - else if (type == 2) { // Cold/Warm - for (byte i = 0; i < 2; i++) { - if (pin[GPIO_PWM0 +i] < 99) analogWrite(pin[GPIO_PWM0 +i], my_color[i]); - } - } - else if (type == 3) { // Color - for (byte i = 2; i < 5; i++) { - if (pin[GPIO_PWM0 +i] < 99) analogWrite(pin[GPIO_PWM0 +i], my_color[i]); - } - } -} - -void sl_blank(byte state) -{ - if (sysCfg.module == SONOFF_LED) { - if (state) { - if (power &1) sl_setColor(1); - } else { - sl_setColor(0); - } - } -} - -/********************************************************************************************/ - void json2legacy(char* stopic, char* svalue) { char *p, *token; @@ -951,24 +388,6 @@ void json2legacy(char* stopic, char* svalue) } } -uint32_t Atoh(char *s) -{ - uint32_t value = 0, digit; - int8_t c; - - while((c = *s++)){ - if('0' <= c && c <= '9') - digit = c - '0'; - else if('A' <= c && c <= 'F') - digit = c - 'A' + 10; - else if('a' <= c && c<= 'f') - digit = c - 'a' + 10; - else break; - value = (value << 4) | digit; - } - return value; -} - /********************************************************************************************/ void mqtt_publish_sec(const char* topic, const char* data, boolean retained) @@ -1150,6 +569,8 @@ void mqtt_reconnect() } } +/********************************************************************************************/ + void mqttDataCb(char* topic, byte* data, unsigned int data_len) { char *str; @@ -1262,53 +683,9 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) } snprintf_P(svalue, sizeof(svalue), PSTR("{\"BlinkCount\":%d}"), sysCfg.blinkcount); } - -/*** Sonoff Led Commands *********************************************************************/ - - else if ((sysCfg.module == SONOFF_LED) && !strcmp(type,"COLOR")) { - uint8_t my_color[5]; - if (data_len == 4) { - char ccold[3], cwarm[3]; - memcpy(ccold, dataBufUc, 2); - ccold[2] = '\0'; - memcpy(cwarm, dataBufUc + 2, 2); - cwarm[2] = '\0'; - my_color[0] = Atoh(ccold); - my_color[1] = Atoh(cwarm); - uint16_t temp = my_color[0]; - if (temp < my_color[1]) temp = my_color[1]; - float mDim = (float)temp / 2.55; - sysCfg.led_dimmer[0] = (uint8_t)mDim; - float newDim = 100 / mDim; - float fmyCold = (float)my_color[0] * newDim; - float fmyWarm = (float)my_color[1] * newDim; - sysCfg.led_color[0] = (uint8_t)fmyCold; - sysCfg.led_color[1] = (uint8_t)fmyWarm; - power = 1; -#ifdef USE_DOMOTICZ - mqtt_publishDomoticzPowerState(index); -#endif // USE_DOMOTICZ - sl_setColor(2); - } - sl_setDim(my_color); - uint16_t color = (uint16_t)my_color[0] << 8; - color += (uint16_t)my_color[1]; - snprintf_P(svalue, sizeof(svalue), PSTR("{\"Color\":\"%04X\"}"), color); + else if ((sysCfg.module == SONOFF_LED) && sl_command(type, index, dataBufUc, data_len, payload, svalue, sizeof(svalue))) { + // Serviced } - else if ((sysCfg.module == SONOFF_LED) && !strcmp(type,"DIMMER")) { - if ((data_len > 0) && (payload >= 0) && (payload <= 100)) { - sysCfg.led_dimmer[0] = payload; - power = 1; -#ifdef USE_DOMOTICZ - mqtt_publishDomoticzPowerState(index); -#endif // USE_DOMOTICZ - sl_setColor(2); - } - snprintf_P(svalue, sizeof(svalue), PSTR("{\"Dimmer\":%d}"), sysCfg.led_dimmer[0]); - } - -/*********************************************************************************************/ - else if (!strcmp(type,"SAVEDATA")) { if ((data_len > 0) && (payload >= 0) && (payload <= 3600)) { sysCfg.savedata = payload; @@ -1803,8 +1180,9 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len) #ifdef USE_I2C if (i2c_flg) snprintf_P(svalue, sizeof(svalue), PSTR("%s, I2CScan"), svalue); #endif // USE_I2C + if (sysCfg.module == SONOFF_LED) snprintf_P(svalue, sizeof(svalue), PSTR("%s, Color, Dimmer, Fade, Speed, Wakeup, WakeupDuration, LedTable"), svalue); #ifdef USE_WS2812 - if (pin[GPIO_WS2812] < 99) snprintf_P(svalue, sizeof(svalue), PSTR("%s, Pixels, Led, Color, Dimmer, Scheme, Fade, Speed, Width, Wakeup, LedTable"), svalue); + if (pin[GPIO_WS2812] < 99) snprintf_P(svalue, sizeof(svalue), PSTR("%s, Color, Dimmer, Fade, Speed, Wakeup, LedTable, Pixels, Led, Width, Scheme"), svalue); #endif #ifdef USE_IR_REMOTE if (pin[GPIO_IRSEND] < 99) snprintf_P(svalue, sizeof(svalue), PSTR("%s, IRSend"), svalue); @@ -2211,6 +1589,8 @@ void stateloop() } } + if (sysCfg.module == SONOFF_LED) sl_animate(); + #ifdef USE_WS2812 if (pin[GPIO_WS2812] < 99) ws2812_animate(); #endif // USE_WS2812 @@ -2343,7 +1723,7 @@ void stateloop() if (otaflag <= 0) { otaflag = 12; ESPhttpUpdate.rebootOnUpdate(false); - sl_blank(0); + sl_blank(1); // Try multiple times to get the update, in case we have a transient issue. // e.g. Someone issued "cmnd/sonoffs/update 1" and all the devices // are hammering the OTAURL. @@ -2361,7 +1741,7 @@ void stateloop() snprintf_P(svalue, sizeof(svalue), PSTR("Successful. Restarting")); restartflag = 2; } else { - sl_blank(1); + sl_blank(0); snprintf_P(svalue, sizeof(svalue), PSTR("Failed %s"), ESPhttpUpdate.getLastErrorString().c_str()); } mqtt_publish_topic_P(0, PSTR("UPGRADE"), svalue); @@ -2536,11 +1916,8 @@ void GPIO_init() Baudrate = 19200; } else if (sysCfg.module == SONOFF_LED) { - analogWriteRange(255); // Default is 1023 (Arduino.h) - analogWriteFreq(200); // Default is 1000 (core_esp8266_wiring_pwm.c) - Try to lower flicker - for (byte i = 0; i < 5; i++) { - if (pin[GPIO_PWM0 +i] < 99) pinMode(pin[GPIO_PWM0 +i], OUTPUT); - } + pin[GPIO_WS2812] = 99; // I do not allow both Sonoff Led AND WS2812 led + sl_init(); } else { for (byte i = 0; i < 4; i++) { diff --git a/sonoff/sonoff_template.h b/sonoff/sonoff_template.h index 34b9bac74..b8c0f64b1 100644 --- a/sonoff/sonoff_template.h +++ b/sonoff/sonoff_template.h @@ -212,13 +212,13 @@ const mytmplt modules[MAXMODULE] PROGMEM = { { "Sonoff LED", // Sonoff LED GPIO_KEY1, // GPIO00 Button 0, 0, 0, - GPIO_PWM3, // GPIO04 Green light - GPIO_PWM2, // GPIO05 Red light + GPIO_USER, // GPIO04 Optional sensor (PWM3 Green) + GPIO_USER, // GPIO05 Optional sensor (PWM2 Red) 0, 0, 0, 0, 0, 0, GPIO_PWM0, // GPIO12 Cold light GPIO_LED1_INV, // GPIO13 Blue Led (0 = On, 1 = Off) GPIO_PWM1, // GPIO14 Warm light - GPIO_PWM4, // GPIO15 Blue light + GPIO_USER, // GPIO15 Optional sensor (PWM4 Blue) 0 }, { "1 Channel", // 1 Channel Inching/Latching Relay diff --git a/sonoff/support.ino b/sonoff/support.ino index d8e6ed707..a13c74447 100644 --- a/sonoff/support.ino +++ b/sonoff/support.ino @@ -23,292 +23,6 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/*********************************************************************************************\ - * Config - Flash or Spiffs -\*********************************************************************************************/ - -extern "C" { -#include "spi_flash.h" -} - -#define SPIFFS_START ((uint32_t)&_SPIFFS_start - 0x40200000) / SPI_FLASH_SEC_SIZE -#define SPIFFS_END ((uint32_t)&_SPIFFS_end - 0x40200000) / SPI_FLASH_SEC_SIZE - -// Version 2.x config -#define SPIFFS_CONFIG2 "/config.ini" -#define CFG_LOCATION2 SPIFFS_END - 2 - -// Version 3.x config -#define SPIFFS_CONFIG "/cfg.ini" -#define CFG_LOCATION SPIFFS_END - 4 - -uint32_t _cfgHash = 0; -int spiffsflag = 0; - -boolean spiffsPresent() -{ - return (SPIFFS_END - SPIFFS_START); -} - -uint32_t getHash() -{ - uint32_t hash = 0; - uint8_t *bytes = (uint8_t*)&sysCfg; - - for (uint16_t i = 0; i < sizeof(SYSCFG); i++) hash += bytes[i]*(i+1); - return hash; -} - -/*********************************************************************************************\ - * Config Save - Save parameters to Flash or Spiffs ONLY if any parameter has changed -\*********************************************************************************************/ -void CFG_Save() -{ - char log[LOGSZ]; - - 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 - 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)); - } - sysCfg.saveFlag++; - 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)); - 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(); - } -} - -void CFG_Load() -{ - char log[LOGSZ]; - - 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; - } _sysCfgH; - - noInterrupts(); - spi_flash_read((CFG_LOCATION) * SPI_FLASH_SEC_SIZE, (uint32*)&sysCfg, sizeof(SYSCFG)); - spi_flash_read((CFG_LOCATION + 1) * SPI_FLASH_SEC_SIZE, (uint32*)&_sysCfgH, sizeof(SYSCFGH)); - if (sysCfg.saveFlag < _sysCfgH.saveFlag) - spi_flash_read((CFG_LOCATION + 1) * SPI_FLASH_SEC_SIZE, (uint32*)&sysCfg, sizeof(SYSCFG)); - interrupts(); - snprintf_P(log, sizeof(log), PSTR("Config: Loaded configuration from flash at %X and count %d"), CFG_LOCATION + (sysCfg.saveFlag &1), sysCfg.saveFlag); - addLog(LOG_LEVEL_DEBUG, log); - } - } -// 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(); - } - } - _cfgHash = getHash(); -} - -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(); -} - -void CFG_Erase() -{ - char log[LOGSZ]; - SpiFlashOpResult result; - - uint32_t _sectorStart = (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 1; - uint32_t _sectorEnd = ESP.getFlashChipRealSize() / SPI_FLASH_SEC_SIZE; - boolean _serialoutput = (LOG_LEVEL_DEBUG_MORE <= seriallog_level); - - snprintf_P(log, sizeof(log), PSTR("Config: Erasing %d flash sectors"), _sectorEnd - _sectorStart); - addLog(LOG_LEVEL_DEBUG, log); - - for (uint32_t _sector = _sectorStart; _sector < _sectorEnd; _sector++) { - noInterrupts(); - result = spi_flash_erase_sector(_sector); - interrupts(); - if (_serialoutput) { - Serial.print(F("Flash: Erased sector ")); - Serial.print(_sector); - if (result == SPI_FLASH_RESULT_OK) { - Serial.println(F(" OK")); - } else { - Serial.println(F(" Error")); - } - delay(10); - } - } -} - -void CFG_Dump() -{ - #define CFG_COLS 16 - - char log[LOGSZ]; - uint16_t idx, maxrow, row, col; - - uint8_t *buffer = (uint8_t *) &sysCfg; - maxrow = ((sizeof(SYSCFG)+CFG_COLS)/CFG_COLS); - - for (row = 0; row < maxrow; row++) { - idx = row * CFG_COLS; - snprintf_P(log, sizeof(log), PSTR("%04X:"), idx); - for (col = 0; col < CFG_COLS; col++) { - if (!(col%4)) snprintf_P(log, sizeof(log), PSTR("%s "), log); - snprintf_P(log, sizeof(log), PSTR("%s %02X"), log, buffer[idx + col]); - } - snprintf_P(log, sizeof(log), PSTR("%s |"), log); - for (col = 0; col < CFG_COLS; col++) { -// if (!(col%4)) snprintf_P(log, sizeof(log), PSTR("%s "), log); - snprintf_P(log, sizeof(log), PSTR("%s%c"), log, ((buffer[idx + col] > 0x20) && (buffer[idx + col] < 0x7F)) ? (char)buffer[idx + col] : ' '); - } - snprintf_P(log, sizeof(log), PSTR("%s|"), log); - addLog(LOG_LEVEL_INFO, log); - } -} - -#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 - -#include "eboot_command.h" - -/* - * Based on cores/esp8266/Updater.cpp - */ -void setFlashChipMode(byte option, byte mode) -{ - char log[LOGSZ]; - uint8_t *_buffer; - uint32_t address; - - if (option) { - eboot_command ebcmd; - eboot_command_read(&ebcmd); - address = ebcmd.args[0]; - } else { - address = 0; - } - _buffer = new uint8_t[FLASH_SECTOR_SIZE]; - if (spi_flash_read(address, (uint32_t*)_buffer, FLASH_SECTOR_SIZE) == SPI_FLASH_RESULT_OK) { - if (_buffer[2] != mode) { - _buffer[2] = mode &3; - noInterrupts(); - if (spi_flash_erase_sector(address / FLASH_SECTOR_SIZE) == SPI_FLASH_RESULT_OK) { - spi_flash_write(address, (uint32_t*)_buffer, FLASH_SECTOR_SIZE); - } - interrupts(); - snprintf_P(log, sizeof(log), PSTR("FLSH: Updated Flash Chip Mode to %d"), (option) ? mode : ESP.getFlashChipMode()); - addLog(LOG_LEVEL_DEBUG, log); - } - } - delete[] _buffer; -} - /*********************************************************************************************\ * Wifi \*********************************************************************************************/ diff --git a/sonoff/webserver.ino b/sonoff/webserver.ino index f70f59891..25080590c 100644 --- a/sonoff/webserver.ino +++ b/sonoff/webserver.ino @@ -1054,7 +1054,7 @@ void handleUploadDone() } snprintf_P(log, sizeof(log), PSTR("Upload: Error - %s"), error.c_str()); addLog(LOG_LEVEL_DEBUG, log); - sl_blank(1); + sl_blank(0); } else { page += F("successful

Device will restart in a few seconds"); restartflag = 2; @@ -1099,7 +1099,7 @@ void handleUploadLoop() return; } } - sl_blank(0); + sl_blank(1); _colcount = 0; } else if (!_uploaderror && (upload.status == UPLOAD_FILE_WRITE)) { if (upload.totalSize == 0) diff --git a/sonoff/xdrv_ir_send.ino b/sonoff/xdrv_ir_send.ino index 3b26c6818..f0177d297 100644 --- a/sonoff/xdrv_ir_send.ino +++ b/sonoff/xdrv_ir_send.ino @@ -47,7 +47,7 @@ void ir_send_init(void) { "protocol": "SAMSUNG", "bits": 32, "data": 551502015 } */ -boolean ir_send_command(char *type, uint16_t index, char *dataBuf, uint16_t data_len, int16_t payload, char *svalue, uint16_t ssvalue) +boolean ir_send_command(char *type, uint16_t index, char *dataBufUc, uint16_t data_len, int16_t payload, char *svalue, uint16_t ssvalue) { boolean serviced = true; boolean error = false; @@ -58,7 +58,7 @@ boolean ir_send_command(char *type, uint16_t index, char *dataBuf, uint16_t data if (!strcmp(type,"IRSEND")) { if (data_len) { StaticJsonBuffer<128> jsonBuf; - JsonObject &ir_json = jsonBuf.parseObject(dataBuf); + JsonObject &ir_json = jsonBuf.parseObject(dataBufUc); if (!ir_json.success()) { snprintf_P(svalue, ssvalue, PSTR("{\"IRSend\":\"Invalid JSON\"}")); // JSON decode failed } else { diff --git a/sonoff/xdrv_snfled.ino b/sonoff/xdrv_snfled.ino new file mode 100644 index 000000000..56ea47059 --- /dev/null +++ b/sonoff/xdrv_snfled.ino @@ -0,0 +1,278 @@ +/* +Copyright (c) 2017 Theo Arends. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +*/ + +/*********************************************************************************************\ + * Sonoff Led +\*********************************************************************************************/ + +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, + 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, + 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 12, 12, 12, 13, 13, 14, + 14, 15, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 22, + 22, 23, 23, 24, 25, 25, 26, 26, 27, 28, 28, 29, 30, 30, 31, 32, + 33, 33, 34, 35, 36, 36, 37, 38, 39, 40, 40, 41, 42, 43, 44, 45, + 46, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 67, 68, 69, 70, 71, 72, 73, 75, 76, 77, 78, + 80, 81, 82, 83, 85, 86, 87, 89, 90, 91, 93, 94, 95, 97, 98, 99, + 101,102,104,105,107,108,110,111,113,114,116,117,119,121,122,124, + 125,127,129,130,132,134,135,137,139,141,142,144,146,148,150,151, + 153,155,157,159,161,163,165,166,168,170,172,174,176,178,180,182, + 184,186,189,191,193,195,197,199,201,204,206,208,210,212,215,217, + 219,221,224,226,228,231,233,235,238,240,243,245,248,250,253,255 }; + +uint8_t sl_dcolor[2], sl_tcolor[2], sl_lcolor[2]; + +uint8_t sl_power; +uint8_t sl_blankv; +uint8_t sl_any; +uint8_t sl_wakeupActive = 0; +uint8_t sl_wakeupDimmer = 0; +uint16_t sl_wakeupCntr = 0; + +uint32_t Atoh(char *s) +{ + uint32_t value = 0, digit; + int8_t c; + + while((c = *s++)){ + if('0' <= c && c <= '9') + digit = c - '0'; + else if('A' <= c && c <= 'F') + digit = c - 'A' + 10; + else if('a' <= c && c<= 'f') + digit = c - 'a' + 10; + else break; + value = (value << 4) | digit; + } + return value; +} + +void sl_setDim(uint8_t myDimmer) +{ + float newDim, fmyCld, fmyWrm; + + newDim = 100 / (float)myDimmer; + fmyCld = (float)sysCfg.led_color[0] / newDim; + fmyWrm = (float)sysCfg.led_color[1] / newDim; + sl_dcolor[0] = (uint8_t)fmyCld; + sl_dcolor[1] = (uint8_t)fmyWrm; +} + +/********************************************************************************************/ + +void sl_init(void) +{ + analogWriteRange(255); // Default is 1023 (Arduino.h) + analogWriteFreq(200); // Default is 1000 (core_esp8266_wiring_pwm.c) - Try to lower flicker + sl_blankv = 0; + sl_power = 0; + sl_any = 0; + sl_wakeupActive = 0; +} + +void sl_blank(byte state) +/* + * Called by interrupt disabling routines like OTA or web upload + * state = 0: No blank + * 1: Blank led to solve flicker + */ +{ + if (sysCfg.module == SONOFF_LED) { + sl_blankv = state; + sl_wakeupActive = 0; + sl_animate(); + } +} + +void sl_setPower(uint8_t power) +{ + sl_blankv = 0; + sl_power = power &1; + sl_wakeupActive = 0; + sl_animate(); +} + +void sl_animate() +{ + char svalue[MESSZ]; + uint8_t fadeValue; + + if ((sl_power == 0) || sl_blankv) { // Power Off + sl_tcolor[0] = 0; + sl_tcolor[1] = 0; + } + else { + if (!sl_wakeupActive) { // Power On + sl_setDim(sysCfg.led_dimmer[0]); + if (sysCfg.led_fade == 0) { + sl_tcolor[0] = sl_dcolor[0]; + sl_tcolor[1] = sl_dcolor[1]; + } else { + if ((sl_tcolor[0] != sl_dcolor[0]) || (sl_tcolor[1] != sl_dcolor[1])) { + if (sl_tcolor[0] < sl_dcolor[0]) sl_tcolor[0] += ((sl_dcolor[0] - sl_tcolor[0]) >> sysCfg.led_speed) +1; + if (sl_tcolor[1] < sl_dcolor[1]) sl_tcolor[1] += ((sl_dcolor[1] - sl_tcolor[1]) >> sysCfg.led_speed) +1; + if (sl_tcolor[0] > sl_dcolor[0]) sl_tcolor[0] -= ((sl_tcolor[0] - sl_dcolor[0]) >> sysCfg.led_speed) +1; + if (sl_tcolor[1] > sl_dcolor[1]) sl_tcolor[1] -= ((sl_tcolor[1] - sl_dcolor[1]) >> sysCfg.led_speed) +1; + } + } + } else { // Power On using wak up duration + if (sl_wakeupActive == 1) { + sl_wakeupActive = 2; + sl_tcolor[0] = 0; + sl_tcolor[1] = 0; + sl_wakeupCntr = 0; + sl_wakeupDimmer = 0; + } + sl_wakeupCntr++; + if (sl_wakeupCntr > ((sysCfg.led_wakeup * STATES) / sysCfg.led_dimmer[0])) { + sl_wakeupCntr = 0; + sl_wakeupDimmer++; + if (sl_wakeupDimmer <= sysCfg.led_dimmer[0]) { + sl_setDim(sl_wakeupDimmer); + sl_tcolor[0] = sl_dcolor[0]; + sl_tcolor[1] = sl_dcolor[1]; + } else { + snprintf_P(svalue, sizeof(svalue), PSTR("{\"Wakeup\":\"Done\"}")); + mqtt_publish_topic_P(1, PSTR("WAKEUP"), svalue); + sl_wakeupActive = 0; + } + } + } + } + if ((sl_lcolor[0] != sl_tcolor[0]) || (sl_lcolor[1] != sl_tcolor[1]) || sl_any) { + sl_any = 0; + sl_lcolor[0] = sl_tcolor[0]; + sl_lcolor[1] = sl_tcolor[1]; + for (byte i = 0; i < 2; i++) { + if (pin[GPIO_PWM0 +i] < 99) { + analogWrite(pin[GPIO_PWM0 +i], (sysCfg.led_table) ? ledTable[sl_lcolor[i]] : sl_lcolor[i]); + } + } + } +} + +/*********************************************************************************************\ + * Commands +\*********************************************************************************************/ + +boolean sl_command(char *type, uint16_t index, char *dataBufUc, uint16_t data_len, int16_t payload, char *svalue, uint16_t ssvalue) +{ + boolean serviced = true; + + if (!strcmp(type,"COLOR")) { + uint8_t my_color[5]; + if (data_len == 4) { + char ccold[3], cwarm[3]; + memcpy(ccold, dataBufUc, 2); + ccold[2] = '\0'; + memcpy(cwarm, dataBufUc + 2, 2); + cwarm[2] = '\0'; + my_color[0] = Atoh(ccold); + my_color[1] = Atoh(cwarm); + uint16_t temp = my_color[0]; + if (temp < my_color[1]) temp = my_color[1]; + float mDim = (float)temp / 2.55; + sysCfg.led_dimmer[0] = (uint8_t)mDim; + float newDim = 100 / mDim; + float fmyCold = (float)my_color[0] * newDim; + float fmyWarm = (float)my_color[1] * newDim; + sysCfg.led_color[0] = (uint8_t)fmyCold; + sysCfg.led_color[1] = (uint8_t)fmyWarm; + do_cmnd_power(index, 1); +#ifdef USE_DOMOTICZ + mqtt_publishDomoticzPowerState(index); +#endif // USE_DOMOTICZ + } + sl_setDim(sysCfg.led_dimmer[0]); + uint16_t color = (uint16_t)sl_dcolor[0] << 8; + color += (uint16_t)sl_dcolor[1]; + snprintf_P(svalue, ssvalue, PSTR("{\"Color\":\"%04X\"}"), color); + } + else if (!strcmp(type,"DIMMER")) { + if ((data_len > 0) && (payload >= 0) && (payload <= 100)) { + sysCfg.led_dimmer[0] = payload; + do_cmnd_power(index, 1); +#ifdef USE_DOMOTICZ + mqtt_publishDomoticzPowerState(index); +#endif // USE_DOMOTICZ + } + snprintf_P(svalue, ssvalue, PSTR("{\"Dimmer\":%d}"), sysCfg.led_dimmer[0]); + } + else if (!strcmp(type,"LEDTABLE")) { + if ((data_len > 0) && (payload >= 0) && (payload <= 2)) { + switch (payload) { + case 0: // Off + case 1: // On + sysCfg.led_table = payload; + break; + case 2: // Toggle + sysCfg.led_table ^= 1; + break; + } + sl_any = 1; + } + snprintf_P(svalue, ssvalue, PSTR("{\"LedTable\":\"%s\"}"), (sysCfg.led_table) ? MQTT_STATUS_ON : MQTT_STATUS_OFF); + } + else if (!strcmp(type,"FADE")) { + if ((data_len > 0) && (payload >= 0) && (payload <= 2)) { + switch (payload) { + case 0: // Off + case 1: // On + sysCfg.led_fade = payload; + break; + case 2: // Toggle + sysCfg.led_fade ^= 1; + break; + } + } + snprintf_P(svalue, ssvalue, PSTR("{\"Fade\":\"%s\"}"), (sysCfg.led_fade) ? MQTT_STATUS_ON : MQTT_STATUS_OFF); + } + else if (!strcmp(type,"SPEED")) { // 1 - fast, 8 - slow + if ((data_len > 0) && (payload > 0) && (payload <= 8)) { + sysCfg.led_speed = payload; + } + snprintf_P(svalue, ssvalue, PSTR("{\"Speed\":%d}"), sysCfg.led_speed); + } + else if (!strcmp(type,"WAKEUPDURATION")) { + if ((data_len > 0) && (payload > 0) && (payload < 3601)) { + sysCfg.led_wakeup = payload; + sl_wakeupActive = 0; + } + snprintf_P(svalue, ssvalue, PSTR("{\"WakeUpDuration\":%d}"), sysCfg.led_wakeup); + } + else if (!strcmp(type,"WAKEUP")) { + do_cmnd_power(index, 1); + sl_wakeupActive = 1; + snprintf_P(svalue, ssvalue, PSTR("{\"Wakeup\":\"Started\"}")); + } + else { + serviced = false; // Unknown command + } + return serviced; +} + diff --git a/sonoff/xdrv_ws2812.ino b/sonoff/xdrv_ws2812.ino index d1f3c94f7..0f6efd765 100644 --- a/sonoff/xdrv_ws2812.ino +++ b/sonoff/xdrv_ws2812.ino @@ -90,7 +90,7 @@ uint8_t speedValues[6] = { 10, // Slow 6, // Fast 2 }; // Fastest - +/* 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, @@ -108,7 +108,7 @@ uint8_t ledTable[] = { 153,155,157,159,161,163,165,166,168,170,172,174,176,178,180,182, 184,186,189,191,193,195,197,199,201,204,206,208,210,212,215,217, 219,221,224,226,228,231,233,235,238,240,243,245,248,250,253,255 }; - +*/ uint8_t lany = 0; RgbColor dcolor, tcolor, lcolor;