diff --git a/sonoff.ino b/sonoff.ino
deleted file mode 100644
index 0bfbf591a..000000000
--- a/sonoff.ino
+++ /dev/null
@@ -1,2871 +0,0 @@
-/*
- sonoff.ino - Sonoff-Tasmota firmware for iTead Sonoff, Wemos and NodeMCU hardware
-
- Copyright (C) 2017 Theo Arends
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see .
-*/
-/*====================================================
- Prerequisites:
- - Change libraries/PubSubClient/src/PubSubClient.h
- #define MQTT_MAX_PACKET_SIZE 512
-
- - Select IDE Tools - Flash Mode: "DOUT"
- - Select IDE Tools - Flash Size: "1M (no SPIFFS)"
- ====================================================*/
-
-#define VERSION 0x05050102 // 5.5.1b
-
-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};
-enum dow_t {Sun=1, Mon, Tue, Wed, Thu, Fri, Sat};
-enum month_t {Jan=1, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec};
-enum wifi_t {WIFI_RESTART, WIFI_SMARTCONFIG, WIFI_MANAGER, WIFI_WPSCONFIG, WIFI_RETRY, MAX_WIFI_OPTION};
-enum swtch_t {TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, MAX_SWITCH_OPTION};
-enum led_t {LED_OFF, LED_POWER, LED_MQTTSUB, LED_POWER_MQTTSUB, LED_MQTTPUB, LED_POWER_MQTTPUB, LED_MQTT, LED_POWER_MQTT, MAX_LED_OPTION};
-enum emul_t {EMUL_NONE, EMUL_WEMO, EMUL_HUE, EMUL_MAX};
-
-#include "sonoff_template.h"
-
-#include "user_config.h"
-#include "user_config_override.h"
-
-/*********************************************************************************************\
- * No user configurable items below
-\*********************************************************************************************/
-
-#define MODULE SONOFF_BASIC // [Module] Select default model
-
-#define USE_DHT // Default DHT11 sensor needs no external library
-#ifndef USE_DS18x20
-#define USE_DS18B20 // Default DS18B20 sensor needs no external library
-#endif
-//#define DEBUG_THEO // Add debug code
-
-#ifdef BE_MINIMAL
-#ifdef USE_MQTT_TLS
-#undef USE_MQTT_TLS // Disable TLS support won't work as the MQTTHost is not set
-#endif
-#ifdef USE_DISCOVERY
-#undef USE_DISCOVERY // Disable Discovery services for both MQTT and web server
-#endif
-#ifdef USE_DOMOTICZ
-#undef USE_DOMOTICZ // Disable Domoticz
-#endif
-//#ifdef USE_WEBSERVER
-//#undef USE_WEBSERVER // Disable Webserver
-//#endif
-#ifdef USE_EMULATION
-#undef USE_EMULATION // Disable Wemo or Hue emulation
-#endif
-#ifdef USE_DS18x20
-#undef USE_DS18x20 // Disable DS18x20 sensor
-#endif
-#ifdef USE_I2C
-#undef USE_I2C // Disable all I2C sensors
-#endif
-#ifdef USE_WS2812
-#undef USE_WS2812 // Disable WS2812 Led string
-#endif
-#ifdef USE_DS18B20
-#undef USE_DS18B20 // Disable internal DS18B20 sensor
-#endif
-#ifdef USE_DHT
-#undef USE_DHT // Disable internal DHT sensor
-#endif
-#ifdef USE_IR_REMOTE
-#undef USE_IR_REMOTE // Disable IR driver
-#endif
-#ifdef DEBUG_THEO
-#undef DEBUG_THEO // Disable debug code
-#endif
-#endif // BE_MINIMAL
-
-#ifndef SWITCH_MODE
-#define SWITCH_MODE TOGGLE // TOGGLE, FOLLOW or FOLLOW_INV (the wall switch state)
-#endif
-
-#ifndef MQTT_FINGERPRINT
-#define MQTT_FINGERPRINT "A5 02 FF 13 99 9F 8B 39 8E F1 83 4F 11 23 65 0B 32 36 FC 07"
-#endif
-
-#ifndef WS2812_LEDS
-#define WS2812_LEDS 30 // [Pixels] Number of LEDs
-#endif
-
-#define MQTT_TOKEN_PREFIX "%prefix%" // To be substituted by mqtt_prefix[x]
-#define MQTT_TOKEN_TOPIC "%topic%" // To be substituted by mqtt_topic, mqtt_grptopic, mqtt_buttontopic, mqtt_switchtopic
-
-#define WIFI_HOSTNAME "%s-%04d" // Expands to -
-#define CONFIG_FILE_SIGN 0xA5 // Configuration file signature
-#define CONFIG_FILE_XOR 0x5A // Configuration file xor (0 = No Xor)
-
-#define HLW_PREF_PULSE 12530 // was 4975us = 201Hz = 1000W
-#define HLW_UREF_PULSE 1950 // was 1666us = 600Hz = 220V
-#define HLW_IREF_PULSE 3500 // was 1666us = 600Hz = 4.545A
-
-#define MQTT_RETRY_SECS 10 // Minimum seconds to retry MQTT connection
-#define APP_POWER 0 // Default saved power state Off
-#define MAX_COUNTERS 4 // Max number of counter sensors
-#define MAX_PULSETIMERS 4 // Max number of supported pulse timers
-#define WS2812_MAX_LEDS 512 // Max number of LEDs
-
-#define PWM_RANGE 1023 // 255..1023 needs to be devisible by 256
-//#define PWM_FREQ 1000 // 100..1000 Hz led refresh
-//#define PWM_FREQ 910 // 100..1000 Hz led refresh (iTead value)
-#define PWM_FREQ 880 // 100..1000 Hz led refresh (BN-SZ01 value)
-
-#define MAX_POWER_HOLD 10 // Time in SECONDS to allow max agreed power (Pow)
-#define MAX_POWER_WINDOW 30 // Time in SECONDS to disable allow max agreed power (Pow)
-#define SAFE_POWER_HOLD 10 // Time in SECONDS to allow max unit safe power (Pow)
-#define SAFE_POWER_WINDOW 30 // Time in MINUTES to disable allow max unit safe power (Pow)
-#define MAX_POWER_RETRY 5 // Retry count allowing agreed power limit overflow (Pow)
-
-#define STATES 20 // State loops per second
-#define SYSLOG_TIMER 600 // Seconds to restore syslog_level
-#define SERIALLOG_TIMER 600 // Seconds to disable SerialLog
-#define OTA_ATTEMPTS 10 // Number of times to try fetching the new firmware
-
-#define INPUT_BUFFER_SIZE 250 // Max number of characters in (serial) command buffer
-#define CMDSZ 20 // Max number of characters in command
-#define TOPSZ 100 // Max number of characters in topic string
-#define LOGSZ 128 // Max number of characters in log string
-#ifdef USE_MQTT_TLS
- #define MAX_LOG_LINES 10 // Max number of lines in weblog
-#else
- #define MAX_LOG_LINES 20 // Max number of lines in weblog
-#endif
-#define MAX_BACKLOG 16 // Max number of commands in backlog (chk blogidx and blogptr code)
-#define MIN_BACKLOG_DELAY 2 // Minimal backlog delay in 0.1 seconds
-
-#define APP_BAUDRATE 115200 // Default serial baudrate
-#define MAX_STATUS 11 // Max number of status lines
-
-enum butt_t {PRESSED, NOT_PRESSED};
-enum opt_t {P_HOLD_TIME, P_MAX_POWER_RETRY, P_MAX_PARAM8}; // Index in sysCfg.param
-
-#include "support.h" // Global support
-
-#include // MQTT
-#ifndef MESSZ
- #define MESSZ 368 // Max number of characters in JSON message string (4 x DS18x20 sensors)
-#endif
-#if (MQTT_MAX_PACKET_SIZE -TOPSZ -7) < MESSZ // If the max message size is too small, throw an error at compile time
- // See pubsubclient.c line 359
- #error "MQTT_MAX_PACKET_SIZE is too small in libraries/PubSubClient/src/PubSubClient.h, increase it to at least 475"
-#endif
-
-#include // RTC, HLW8012, OSWatch
-#include // MQTT, Ota, WifiManager
-#include // MQTT, Ota
-#include // Ota
-#include // Webserver, Updater
-#include // WemoHue, IRremote, Domoticz
-#ifdef USE_WEBSERVER
- #include // WifiManager, Webserver
- #include // WifiManager
-#endif // USE_WEBSERVER
-#ifdef USE_DISCOVERY
- #include // MQTT, Webserver
-#endif // USE_DISCOVERY
-#ifdef USE_I2C
- #include // I2C support library
-#endif // USE_I2C
-#ifdef USE_SPI
- #include // SPI support, TFT
-#endif // USE_SPI
-#include "settings.h"
-
-#define MAX_BUTTON_COMMANDS 5 // Max number of button commands supported
-const char commands[MAX_BUTTON_COMMANDS][14] PROGMEM = {
- {"wificonfig 1"}, // Press button three times
- {"wificonfig 2"}, // Press button four times
- {"wificonfig 3"}, // Press button five times
- {"restart 1"}, // Press button six times
- {"upgrade 1"}}; // Press button seven times
-
-const char wificfg[5][12] PROGMEM = { "Restart", "Smartconfig", "Wifimanager", "WPSconfig", "Retry" };
-const char PREFIXES[3][5] PROGMEM = { "cmnd", "stat", "tele" };
-
-struct TIME_T {
- uint8_t Second;
- uint8_t Minute;
- uint8_t Hour;
- uint8_t Wday; // day of week, sunday is day 1
- uint8_t Day;
- uint8_t Month;
- char MonthName[4];
- uint16_t DayOfYear;
- uint16_t Year;
- unsigned long Valid;
-} rtcTime;
-
-struct TimeChangeRule
-{
- uint8_t week; // 1=First, 2=Second, 3=Third, 4=Fourth, or 0=Last week of the month
- uint8_t dow; // day of week, 1=Sun, 2=Mon, ... 7=Sat
- uint8_t month; // 1=Jan, 2=Feb, ... 12=Dec
- uint8_t hour; // 0-23
- int offset; // offset from UTC in minutes
-};
-
-TimeChangeRule myDST = { TIME_DST }; // Daylight Saving Time
-TimeChangeRule mySTD = { TIME_STD }; // Standard Time
-
-int Baudrate = APP_BAUDRATE; // Serial interface baud rate
-byte SerialInByte; // Received byte
-int SerialInByteCounter = 0; // Index in receive buffer
-char serialInBuf[INPUT_BUFFER_SIZE + 2]; // Receive buffer
-byte Hexcode = 0; // Sonoff dual input flag
-uint16_t ButtonCode = 0; // Sonoff dual received code
-int16_t savedatacounter; // Counter and flag for config save to Flash
-char Version[16]; // Version string from VERSION define
-char Hostname[33]; // Composed Wifi hostname
-char MQTTClient[33]; // Composed MQTT Clientname
-uint8_t mqttcounter = 0; // MQTT connection retry counter
-uint8_t fallbacktopic = 0; // Use Topic or FallbackTopic
-unsigned long timerxs = 0; // State loop timer
-int state = 0; // State per second flag
-int mqttflag = 2; // MQTT connection messages flag
-int otaflag = 0; // OTA state flag
-int otaok = 0; // OTA result
-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
-byte logajaxflg = 0; // Reset web console log
-byte Maxdevice = 0; // Max number of devices supported
-int status_update_timer = 0; // Refresh initial status
-uint16_t pulse_timer[MAX_PULSETIMERS] = { 0 }; // Power off timer
-uint16_t blink_timer = 0; // Power cycle timer
-uint16_t blink_counter = 0; // Number of blink cycles
-uint8_t blink_power; // Blink power state
-uint8_t blink_mask = 0; // Blink relay active mask
-uint8_t blink_powersave; // Blink start power save state
-uint16_t mqtt_cmnd_publish = 0; // ignore flag for publish command
-uint8_t latching_power = 0; // Power state at latching start
-uint8_t latching_relay_pulse = 0; // Latching relay pulse timer
-String Backlog[MAX_BACKLOG]; // Command backlog
-uint8_t blogidx = 0; // Command backlog index
-uint8_t blogptr = 0; // Command backlog pointer
-uint8_t blogmutex = 0; // Command backlog pending
-uint16_t blogdelay = 0; // Command backlog delay
-
-#ifdef USE_MQTT_TLS
- WiFiClientSecure espClient; // Wifi Secure Client
-#else
- WiFiClient espClient; // Wifi Client
-#endif
-PubSubClient mqttClient(espClient); // MQTT Client
-WiFiUDP portUDP; // UDP Syslog and Alexa
-
-uint8_t power; // Current copy of sysCfg.power
-byte syslog_level; // Current copy of sysCfg.syslog_level
-uint16_t syslog_timer = 0; // Timer to re-enable syslog_level
-byte seriallog_level; // Current copy of sysCfg.seriallog_level
-uint16_t seriallog_timer = 0; // Timer to disable Seriallog
-uint8_t sleep; // Current copy of sysCfg.sleep
-uint8_t stop_flash_rotate = 0; // Allow flash configuration rotation
-
-int blinks = 201; // Number of LED blinks
-uint8_t blinkstate = 0; // LED state
-
-uint8_t lastbutton[4] = { NOT_PRESSED, NOT_PRESSED, NOT_PRESSED, NOT_PRESSED }; // Last button states
-uint8_t holdbutton[4] = { 0 }; // Timer for button hold
-uint8_t multiwindow[4] = { 0 }; // Max time between button presses to record press count
-uint8_t multipress[4] = { 0 }; // Number of button presses within multiwindow
-uint8_t lastwallswitch[4]; // Last wall switch states
-uint8_t holdwallswitch[4] = { 0 }; // Timer for wallswitch push button hold
-uint8_t blockgpio0 = 4; // Block GPIO0 for 4 seconds after poweron to workaround Wemos D1 RTS circuit
-
-mytmplt my_module; // Active copy of GPIOs
-uint8_t pin[GPIO_MAX]; // Possible pin configurations
-uint8_t rel_inverted[4] = { 0 }; // Relay inverted flag (1 = (0 = On, 1 = Off))
-uint8_t led_inverted[4] = { 0 }; // LED inverted flag (1 = (0 = On, 1 = Off))
-uint8_t swt_flg = 0; // Any external switch configured
-uint8_t dht_flg = 0; // DHT configured
-uint8_t hlw_flg = 0; // Power monitor configured
-uint8_t i2c_flg = 0; // I2C configured
-uint8_t spi_flg = 0; // SPI configured
-uint8_t pwm_flg = 0; // PWM configured
-uint8_t sfl_flg = 0; // Sonoff Led flag (0 = No led, 1 = BN-SZ01, 2 = Sonoff Led)
-uint8_t pwm_idxoffset = 0; // Allowed PWM command offset (change for Sonoff Led)
-
-boolean mDNSbegun = false;
-
-/********************************************************************************************/
-
-void getClient(char* output, const char* input, byte size)
-{
- char *token;
- uint8_t digits = 0;
-
- if (strstr(input, "%")) {
- strlcpy(output, input, size);
- token = strtok(output, "%");
- if (strstr(input, "%") == input) {
- output[0] = '\0';
- } else {
- token = strtok(NULL, "");
- }
- if (token != NULL) {
- digits = atoi(token);
- if (digits) {
- snprintf_P(output, size, PSTR("%s%c0%dX"), output, '%', digits);
- snprintf_P(output, size, output, ESP.getChipId());
- }
- }
- }
- if (!digits) {
- strlcpy(output, input, size);
- }
-}
-
-void getTopic_P(char *stopic, byte prefix, char *topic, const char* subtopic)
-{
- char romram[CMDSZ];
- String fulltopic;
-
- snprintf_P(romram, sizeof(romram), subtopic);
- if (fallbacktopic) {
- fulltopic = FPSTR(PREFIXES[prefix]);
- fulltopic += F("/");
- fulltopic += MQTTClient;
- } else {
- fulltopic = sysCfg.mqtt_fulltopic;
- if ((0 == prefix) && (-1 == fulltopic.indexOf(F(MQTT_TOKEN_PREFIX)))) {
- fulltopic += F("/" MQTT_TOKEN_PREFIX); // Need prefix for commands to handle mqtt topic loops
- }
- for (byte i = 0; i < 3; i++) {
- if ('\0' == sysCfg.mqtt_prefix[i][0]) {
- snprintf_P(sysCfg.mqtt_prefix[i], sizeof(sysCfg.mqtt_prefix[i]), PREFIXES[i]);
- }
- }
- fulltopic.replace(F(MQTT_TOKEN_PREFIX), sysCfg.mqtt_prefix[prefix]);
- fulltopic.replace(F(MQTT_TOKEN_TOPIC), topic);
- }
- fulltopic.replace(F("#"), "");
- fulltopic.replace(F("//"), "/");
- if (!fulltopic.endsWith("/")) {
- fulltopic += "/";
- }
- snprintf_P(stopic, TOPSZ, PSTR("%s%s"), fulltopic.c_str(), romram);
-}
-
-char* getStateText(byte state)
-{
- if (state > 3) {
- state = 1;
- }
- return sysCfg.state_text[state];
-}
-
-/********************************************************************************************/
-
-void setLatchingRelay(uint8_t power, uint8_t state)
-{
- power &= 1;
- if (2 == state) { // Reset relay
- state = 0;
- latching_power = power;
- latching_relay_pulse = 0;
- }
- else if (state && !latching_relay_pulse) { // Set port power to On
- latching_power = power;
- latching_relay_pulse = 2; // max 200mS (initiated by stateloop())
- }
- if (pin[GPIO_REL1 +latching_power] < 99) {
- digitalWrite(pin[GPIO_REL1 +latching_power], rel_inverted[latching_power] ? !state : state);
- }
-}
-
-void setRelay(uint8_t rpower)
-{
- uint8_t state;
-
- if (4 == sysCfg.poweronstate) { // All on and stay on
- power = (1 << Maxdevice) -1;
- rpower = power;
- }
- if ((SONOFF_DUAL == sysCfg.module) || (CH4 == sysCfg.module)) {
- Serial.write(0xA0);
- Serial.write(0x04);
- Serial.write(rpower);
- Serial.write(0xA1);
- Serial.write('\n');
- Serial.flush();
- }
- else if (sfl_flg) {
- sl_setPower(rpower &1);
- }
- else if (EXS_RELAY == sysCfg.module) {
- setLatchingRelay(rpower, 1);
- }
- else {
- for (byte i = 0; i < Maxdevice; i++) {
- state = rpower &1;
- if (pin[GPIO_REL1 +i] < 99) {
- digitalWrite(pin[GPIO_REL1 +i], rel_inverted[i] ? !state : state);
- }
- rpower >>= 1;
- }
- }
- hlw_setPowerSteadyCounter(2);
-}
-
-void setLed(uint8_t state)
-{
- if (state) {
- state = 1;
- }
- digitalWrite(pin[GPIO_LED1], (led_inverted[0]) ? !state : state);
-}
-
-/********************************************************************************************/
-
-void mqtt_publish_sec(const char* topic, const char* data, boolean retained)
-{
- char log[TOPSZ + MESSZ];
-
- if (sysCfg.flag.mqtt_enabled) {
- if (mqttClient.publish(topic, data, retained)) {
- snprintf_P(log, sizeof(log), PSTR("MQTT: %s = %s%s"), topic, data, (retained) ? " (retained)" : "");
-// mqttClient.loop(); // Do not use here! Will block previous publishes
- } else {
- snprintf_P(log, sizeof(log), PSTR("RSLT: %s = %s"), topic, data);
- }
- } else {
- snprintf_P(log, sizeof(log), PSTR("RSLT: %s = %s"), strrchr(topic,'/')+1, data);
- }
-
- addLog(LOG_LEVEL_INFO, log);
- if (sysCfg.ledstate &0x04) {
- blinks++;
- }
-}
-
-void mqtt_publish(const char* topic, const char* data, boolean retained)
-{
- char *me;
-
- if (!strcmp(sysCfg.mqtt_prefix[0],sysCfg.mqtt_prefix[1])) {
- me = strstr(topic,sysCfg.mqtt_prefix[0]);
- if (me == topic) {
- mqtt_cmnd_publish += 8;
- }
- }
- mqtt_publish_sec(topic, data, retained);
-}
-
-void mqtt_publish(const char* topic, const char* data)
-{
- mqtt_publish(topic, data, false);
-}
-
-void mqtt_publish_topic_P(uint8_t prefix, const char* subtopic, const char* data, boolean retained)
-{
-/* prefix 0 = cmnd using subtopic
- * prefix 1 = stat using subtopic
- * prefix 2 = tele using subtopic
- * prefix 4 = cmnd using subtopic or RESULT
- * prefix 5 = stat using subtopic or RESULT
- * prefix 6 = tele using subtopic or RESULT
- */
- char romram[16];
- char stopic[TOPSZ];
-
- snprintf_P(romram, sizeof(romram), ((prefix > 3) && !sysCfg.flag.mqtt_response) ? PSTR("RESULT") : subtopic);
- prefix &= 3;
- getTopic_P(stopic, prefix, sysCfg.mqtt_topic, romram);
- mqtt_publish(stopic, data, retained);
-}
-
-void mqtt_publish_topic_P(uint8_t prefix, const char* subtopic, const char* data)
-{
- mqtt_publish_topic_P(prefix, subtopic, data, false);
-}
-
-void mqtt_publishPowerState(byte device)
-{
- char stopic[TOPSZ];
- char sdevice[10];
- char scommand[10];
- char svalue[64]; // was MESSZ
-
- if ((device < 1) || (device > Maxdevice)) {
- device = 1;
- }
- snprintf_P(sdevice, sizeof(sdevice), PSTR("%d"), device);
- snprintf_P(scommand, sizeof(scommand), PSTR("POWER%s"), (Maxdevice > 1) ? sdevice : "");
-
- getTopic_P(stopic, 1, sysCfg.mqtt_topic, (sysCfg.flag.mqtt_response)?"POWER":"RESULT");
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"%s\":\"%s\"}"), scommand, getStateText(bitRead(power, device -1)));
- mqtt_publish(stopic, svalue);
-
- getTopic_P(stopic, 1, sysCfg.mqtt_topic, scommand);
- snprintf_P(svalue, sizeof(svalue), PSTR("%s"), getStateText(bitRead(power, device -1)));
- mqtt_publish(stopic, svalue, sysCfg.flag.mqtt_power_retain);
-}
-
-void mqtt_publishPowerBlinkState(byte device)
-{
- char sdevice[10];
- char svalue[64]; // was MESSZ
-
- if ((device < 1) || (device > Maxdevice)) {
- device = 1;
- }
- snprintf_P(sdevice, sizeof(sdevice), PSTR("%d"), device);
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"POWER%s\":\"BLINK %s\"}"),
- (Maxdevice > 1) ? sdevice : "", getStateText(bitRead(blink_mask, device -1)));
- mqtt_publish_topic_P(5, PSTR("POWER"), svalue);
-}
-
-void mqtt_connected()
-{
- char stopic[TOPSZ];
- char svalue[128]; // was MESSZ
-
- if (sysCfg.flag.mqtt_enabled) {
-
- // Satisfy iobroker (#299)
- svalue[0] = '\0';
- mqtt_publish_topic_P(0, PSTR("POWER"), svalue);
-
- getTopic_P(stopic, 0, sysCfg.mqtt_topic, PSTR("#"));
- mqttClient.subscribe(stopic);
- mqttClient.loop(); // Solve LmacRxBlk:1 messages
- if (strstr(sysCfg.mqtt_fulltopic, MQTT_TOKEN_TOPIC) != NULL) {
- getTopic_P(stopic, 0, sysCfg.mqtt_grptopic, PSTR("#"));
- mqttClient.subscribe(stopic);
- mqttClient.loop(); // Solve LmacRxBlk:1 messages
- fallbacktopic = 1;
- getTopic_P(stopic, 0, MQTTClient, PSTR("#"));
- fallbacktopic = 0;
- mqttClient.subscribe(stopic);
- mqttClient.loop(); // Solve LmacRxBlk:1 messages
- }
-#ifdef USE_DOMOTICZ
- domoticz_mqttSubscribe();
-#endif // USE_DOMOTICZ
- }
-
- if (mqttflag) {
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Module\":\"%s\", \"Version\":\"%s\", \"FallbackTopic\":\"%s\", \"GroupTopic\":\"%s\"}"),
- my_module.name, Version, MQTTClient, sysCfg.mqtt_grptopic);
- mqtt_publish_topic_P(2, PSTR("INFO1"), svalue);
-#ifdef USE_WEBSERVER
- if (sysCfg.webserver) {
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"WebserverMode\":\"%s\", \"Hostname\":\"%s\", \"IPaddress\":\"%s\"}"),
- (2 == sysCfg.webserver) ? "Admin" : "User", Hostname, WiFi.localIP().toString().c_str());
- mqtt_publish_topic_P(2, PSTR("INFO2"), svalue);
- }
-#endif // USE_WEBSERVER
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Started\":\"%s\"}"),
- (getResetReason() == "Exception") ? ESP.getResetInfo().c_str() : getResetReason().c_str());
- mqtt_publish_topic_P(2, PSTR("INFO3"), svalue);
- if (sysCfg.tele_period) {
- tele_period = sysCfg.tele_period -9;
- }
- status_update_timer = 2;
-#ifdef USE_DOMOTICZ
- domoticz_setUpdateTimer(2);
-#endif // USE_DOMOTICZ
- }
- mqttflag = 0;
-}
-
-void mqtt_reconnect()
-{
- char stopic[TOPSZ];
- char svalue[TOPSZ];
- char log[LOGSZ];
-
- mqttcounter = sysCfg.mqtt_retry;
-
- if (!sysCfg.flag.mqtt_enabled) {
- mqtt_connected();
- return;
- }
-#ifdef USE_EMULATION
- UDP_Disconnect();
-#endif // USE_EMULATION
- if (mqttflag > 1) {
-#ifdef USE_MQTT_TLS
- addLog_P(LOG_LEVEL_INFO, PSTR("MQTT: Verify TLS fingerprint..."));
- if (!espClient.connect(sysCfg.mqtt_host, sysCfg.mqtt_port)) {
- snprintf_P(log, sizeof(log), PSTR("MQTT: TLS Connect FAILED to %s:%d. Retry in %d seconds"),
- sysCfg.mqtt_host, sysCfg.mqtt_port, mqttcounter);
- addLog(LOG_LEVEL_DEBUG, log);
- return;
- }
- if (espClient.verify(sysCfg.mqtt_fingerprint, sysCfg.mqtt_host)) {
- addLog_P(LOG_LEVEL_INFO, PSTR("MQTT: Verified"));
- } else {
- addLog_P(LOG_LEVEL_DEBUG, PSTR("MQTT: Insecure connection due to invalid Fingerprint"));
- }
-#endif // USE_MQTT_TLS
- mqttClient.setCallback(mqttDataCb);
- mqttflag = 1;
- mqttcounter = 1;
- return;
- }
-
- addLog_P(LOG_LEVEL_INFO, PSTR("MQTT: Attempting connection..."));
-#ifndef USE_MQTT_TLS
-#ifdef USE_DISCOVERY
-#ifdef MQTT_HOST_DISCOVERY
- mdns_discoverMQTTServer();
-#endif // MQTT_HOST_DISCOVERY
-#endif // USE_DISCOVERY
-#endif // USE_MQTT_TLS
- mqttClient.setServer(sysCfg.mqtt_host, sysCfg.mqtt_port);
-
- getTopic_P(stopic, 2, sysCfg.mqtt_topic, PSTR("LWT"));
- snprintf_P(svalue, sizeof(svalue), PSTR("Offline"));
- if (mqttClient.connect(MQTTClient, sysCfg.mqtt_user, sysCfg.mqtt_pwd, stopic, 1, true, svalue)) {
- addLog_P(LOG_LEVEL_INFO, PSTR("MQTT: Connected"));
- mqttcounter = 0;
- snprintf_P(svalue, sizeof(svalue), PSTR("Online"));
- mqtt_publish(stopic, svalue, true);
- mqtt_connected();
- } else {
- snprintf_P(log, sizeof(log), PSTR("MQTT: Connect FAILED to %s:%d, rc %d. Retry in %d seconds"),
- sysCfg.mqtt_host, sysCfg.mqtt_port, mqttClient.state(), mqttcounter); //status codes are documented here http://pubsubclient.knolleary.net/api.html#state
- addLog(LOG_LEVEL_INFO, log);
- }
-}
-
-/********************************************************************************************/
-
-boolean mqtt_command(boolean grpflg, char *type, uint16_t index, char *dataBuf, uint16_t data_len, int16_t payload, char *svalue, uint16_t ssvalue)
-{
- boolean serviced = true;
- char stemp1[TOPSZ];
- char stemp2[10];
- char scommand[CMDSZ];
- uint16_t i;
-
- if (!strcmp_P(type,PSTR("MQTTHOST"))) {
- if ((data_len > 0) && (data_len < sizeof(sysCfg.mqtt_host))) {
- strlcpy(sysCfg.mqtt_host, (1 == payload) ? MQTT_HOST : dataBuf, sizeof(sysCfg.mqtt_host));
- restartflag = 2;
- }
- snprintf_P(svalue, ssvalue, PSTR("{\"MqttHost\",\"%s\"}"), sysCfg.mqtt_host);
- }
- else if (!strcmp_P(type,PSTR("MQTTPORT"))) {
- if ((payload > 0) && (payload < 32766)) {
- sysCfg.mqtt_port = (1 == payload) ? MQTT_PORT : payload;
- restartflag = 2;
- }
- snprintf_P(svalue, ssvalue, PSTR("{\"MqttPort\":%d}"), sysCfg.mqtt_port);
- }
- else if (!strcmp_P(type,PSTR("MQTTRETRY"))) {
- if ((payload >= MQTT_RETRY_SECS) && (payload < 32001)) {
- sysCfg.mqtt_retry = payload;
- mqttcounter = sysCfg.mqtt_retry;
- }
- snprintf_P(svalue, ssvalue, PSTR("{\"MqttRetry\":%d}"), sysCfg.mqtt_retry);
- }
- else if (!strcmp_P(type,PSTR("STATETEXT")) && (index > 0) && (index <= 4)) {
- 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], 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_P(type,PSTR("MQTTFINGERPRINT"))) {
- if ((data_len > 0) && (data_len < sizeof(sysCfg.mqtt_fingerprint))) {
- strlcpy(sysCfg.mqtt_fingerprint, (!strcmp(dataBuf,"0")) ? "" : (1 == payload) ? MQTT_FINGERPRINT : dataBuf, sizeof(sysCfg.mqtt_fingerprint));
- restartflag = 2;
- }
- snprintf_P(svalue, ssvalue, PSTR("{\"MqttFingerprint\":\"%s\"}"), sysCfg.mqtt_fingerprint);
- }
-#endif
- else if (!grpflg && !strcmp_P(type,PSTR("MQTTCLIENT"))) {
- if ((data_len > 0) && (data_len < sizeof(sysCfg.mqtt_client))) {
- strlcpy(sysCfg.mqtt_client, (1 == payload) ? MQTT_CLIENT_ID : dataBuf, sizeof(sysCfg.mqtt_client));
- restartflag = 2;
- }
- snprintf_P(svalue, ssvalue, PSTR("{\"MqttClient\":\"%s\"}"), sysCfg.mqtt_client);
- }
- else if (!strcmp_P(type,PSTR("MQTTUSER"))) {
- if ((data_len > 0) && (data_len < sizeof(sysCfg.mqtt_user))) {
- strlcpy(sysCfg.mqtt_user, (!strcmp(dataBuf,"0")) ? "" : (1 == payload) ? MQTT_USER : dataBuf, sizeof(sysCfg.mqtt_user));
- restartflag = 2;
- }
- snprintf_P(svalue, ssvalue, PSTR("[\"MqttUser\":\"%s\"}"), sysCfg.mqtt_user);
- }
- else if (!strcmp_P(type,PSTR("MQTTPASSWORD"))) {
- if ((data_len > 0) && (data_len < sizeof(sysCfg.mqtt_pwd))) {
- strlcpy(sysCfg.mqtt_pwd, (!strcmp(dataBuf,"0")) ? "" : (1 == payload) ? MQTT_PASS : dataBuf, sizeof(sysCfg.mqtt_pwd));
- restartflag = 2;
- }
- snprintf_P(svalue, ssvalue, PSTR("{\"MqttPassword\":\"%s\"}"), sysCfg.mqtt_pwd);
- }
- else if (!strcmp_P(type,PSTR("FULLTOPIC"))) {
- if ((data_len > 0) && (data_len < sizeof(sysCfg.mqtt_fulltopic))) {
- mqttfy(1, dataBuf);
- if (!strcmp(dataBuf, MQTTClient)) {
- payload = 1;
- }
- strlcpy(stemp1, (1 == payload) ? MQTT_FULLTOPIC : dataBuf, sizeof(stemp1));
- if (strcmp(stemp1, sysCfg.mqtt_fulltopic)) {
- mqtt_publish_topic_P(2, PSTR("LWT"), (sysCfg.flag.mqtt_offline) ? "Offline" : "", true); // Offline or remove previous retained topic
- strlcpy(sysCfg.mqtt_fulltopic, stemp1, sizeof(sysCfg.mqtt_fulltopic));
- restartflag = 2;
- }
- }
- snprintf_P(svalue, ssvalue, PSTR("{\"FullTopic\":\"%s\"}"), sysCfg.mqtt_fulltopic);
- }
- else if (!strcmp_P(type,PSTR("PREFIX")) && (index > 0) && (index <= 3)) {
- if ((data_len > 0) && (data_len < sizeof(sysCfg.mqtt_prefix[0]))) {
- mqttfy(0, dataBuf);
- strlcpy(sysCfg.mqtt_prefix[index -1], (1 == payload) ? (1==index)?SUB_PREFIX:(2==index)?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;
- }
- snprintf_P(svalue, ssvalue, PSTR("{\"Prefix%d\":\"%s\"}"), index, sysCfg.mqtt_prefix[index -1]);
- }
- else if (!strcmp_P(type,PSTR("GROUPTOPIC"))) {
- if ((data_len > 0) && (data_len < sizeof(sysCfg.mqtt_grptopic))) {
- mqttfy(0, dataBuf);
- if (!strcmp(dataBuf, MQTTClient)) {
- payload = 1;
- }
- strlcpy(sysCfg.mqtt_grptopic, (1 == payload) ? MQTT_GRPTOPIC : dataBuf, sizeof(sysCfg.mqtt_grptopic));
- restartflag = 2;
- }
- snprintf_P(svalue, ssvalue, PSTR("{\"GroupTopic\":\"%s\"}"), sysCfg.mqtt_grptopic);
- }
- else if (!grpflg && !strcmp_P(type,PSTR("TOPIC"))) {
- if ((data_len > 0) && (data_len < sizeof(sysCfg.mqtt_topic))) {
- mqttfy(0, dataBuf);
- if (!strcmp(dataBuf, MQTTClient)) {
- payload = 1;
- }
- strlcpy(stemp1, (1 == payload) ? MQTT_TOPIC : dataBuf, sizeof(stemp1));
- if (strcmp(stemp1, sysCfg.mqtt_topic)) {
- mqtt_publish_topic_P(2, PSTR("LWT"), (sysCfg.flag.mqtt_offline) ? "Offline" : "", true); // Offline or remove previous retained topic
- strlcpy(sysCfg.mqtt_topic, stemp1, sizeof(sysCfg.mqtt_topic));
- restartflag = 2;
- }
- }
- snprintf_P(svalue, ssvalue, PSTR("{\"Topic\":\"%s\"}"), sysCfg.mqtt_topic);
- }
- else if (!grpflg && !strcmp_P(type,PSTR("BUTTONTOPIC"))) {
- if ((data_len > 0) && (data_len < sizeof(sysCfg.button_topic))) {
- mqttfy(0, dataBuf);
- if (!strcmp(dataBuf, MQTTClient)) {
- payload = 1;
- }
- strlcpy(sysCfg.button_topic, (!strcmp(dataBuf,"0")) ? "" : (1 == payload) ? sysCfg.mqtt_topic : dataBuf, sizeof(sysCfg.button_topic));
- }
- snprintf_P(svalue, ssvalue, PSTR("{\"ButtonTopic\":\"%s\"}"), sysCfg.button_topic);
- }
- else if (!grpflg && !strcmp_P(type,PSTR("SWITCHTOPIC"))) {
- if ((data_len > 0) && (data_len < sizeof(sysCfg.switch_topic))) {
- mqttfy(0, dataBuf);
- if (!strcmp(dataBuf, MQTTClient)) {
- payload = 1;
- }
- strlcpy(sysCfg.switch_topic, (!strcmp(dataBuf,"0")) ? "" : (1 == payload) ? sysCfg.mqtt_topic : dataBuf, sizeof(sysCfg.switch_topic));
- }
- snprintf_P(svalue, ssvalue, PSTR("{\"SwitchTopic\":\"%s\"}"), sysCfg.switch_topic);
- }
- else if (!strcmp_P(type,PSTR("BUTTONRETAIN"))) {
- if ((payload >= 0) && (payload <= 1)) {
- strlcpy(sysCfg.button_topic, sysCfg.mqtt_topic, sizeof(sysCfg.button_topic));
- if (!payload) {
- for(i = 1; i <= Maxdevice; i++) {
- send_button_power(0, i, 9); // Clear MQTT retain in broker
- }
- }
- sysCfg.flag.mqtt_button_retain = payload;
- }
- snprintf_P(svalue, ssvalue, PSTR("{\"ButtonRetain\":\"%s\"}"), getStateText(sysCfg.flag.mqtt_button_retain));
- }
- else if (!strcmp_P(type,PSTR("SWITCHRETAIN"))) {
- if ((payload >= 0) && (payload <= 1)) {
- strlcpy(sysCfg.button_topic, sysCfg.mqtt_topic, sizeof(sysCfg.button_topic));
- if (!payload) {
- for(i = 1; i <= 4; i++) {
- send_button_power(1, i, 9); // Clear MQTT retain in broker
- }
- }
- sysCfg.flag.mqtt_switch_retain = payload;
- }
- snprintf_P(svalue, ssvalue, PSTR("{\"SwitchRetain\":\"%s\"}"), getStateText(sysCfg.flag.mqtt_switch_retain));
- }
- else if (!strcmp_P(type,PSTR("POWERRETAIN"))) {
- if ((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(scommand, sizeof(scommand), PSTR("POWER%s"), (Maxdevice > 1) ? stemp2 : "");
- getTopic_P(stemp1, 1, sysCfg.mqtt_topic, scommand);
- mqtt_publish(stemp1, "", sysCfg.flag.mqtt_power_retain);
- }
- }
- sysCfg.flag.mqtt_power_retain = payload;
- }
- snprintf_P(svalue, ssvalue, PSTR("{\"PowerRetain\":\"%s\"}"), getStateText(sysCfg.flag.mqtt_power_retain));
- }
- else if (!strcmp_P(type,PSTR("SENSORRETAIN"))) {
- if ((payload >= 0) && (payload <= 1)) {
- if (!payload) {
- svalue[0] = '\0';
- mqtt_publish_topic_P(2, PSTR("SENSOR"), svalue, sysCfg.flag.mqtt_sensor_retain);
- }
- sysCfg.flag.mqtt_sensor_retain = payload;
- }
- snprintf_P(svalue, ssvalue, PSTR("{\"SensorRetain\":\"%s\"}"), getStateText(sysCfg.flag.mqtt_sensor_retain));
- }
-
-#ifdef USE_DOMOTICZ
- else if (domoticz_command(type, index, dataBuf, data_len, payload, svalue, ssvalue)) {
- // Serviced
- }
-#endif // USE_DOMOTICZ
- else {
- serviced = false;
- }
- return serviced;
-}
-
-/********************************************************************************************/
-
-void mqttDataCb(char* topic, byte* data, unsigned int data_len)
-{
- char *str;
-
- if (!strcmp(sysCfg.mqtt_prefix[0],sysCfg.mqtt_prefix[1])) {
- str = strstr(topic,sysCfg.mqtt_prefix[0]);
- if ((str == topic) && mqtt_cmnd_publish) {
- if (mqtt_cmnd_publish > 8) {
- mqtt_cmnd_publish -= 8;
- } else {
- mqtt_cmnd_publish = 0;
- }
- return;
- }
- }
-
- char topicBuf[TOPSZ];
- char dataBuf[data_len+1];
- char dataBufUc[128];
- char svalue[MESSZ];
- char stemp1[TOPSZ];
- char *p;
- char *mtopic = NULL;
- char *type = NULL;
- byte otype = 0;
- byte ptype = 0;
- uint16_t i = 0;
- uint16_t grpflg = 0;
- uint16_t index;
- uint32_t address;
-
- strncpy(topicBuf, topic, sizeof(topicBuf));
- memcpy(dataBuf, data, sizeof(dataBuf));
- dataBuf[sizeof(dataBuf)-1] = 0;
-
- snprintf_P(svalue, sizeof(svalue), PSTR("RSLT: Receive topic %s, data size %d, data %s"), topicBuf, data_len, dataBuf);
- addLog(LOG_LEVEL_DEBUG_MORE, svalue);
-// if (LOG_LEVEL_DEBUG_MORE <= seriallog_level) Serial.println(dataBuf);
-
-#ifdef USE_DOMOTICZ
- if (sysCfg.flag.mqtt_enabled) {
- if (domoticz_mqttData(topicBuf, sizeof(topicBuf), dataBuf, sizeof(dataBuf))) {
- return;
- }
- }
-#endif // USE_DOMOTICZ
-
- grpflg = (strstr(topicBuf, sysCfg.mqtt_grptopic) != NULL);
- fallbacktopic = (strstr(topicBuf, MQTTClient) != NULL);
- type = strrchr(topicBuf, '/') +1; // Last part of received topic is always the command (type)
-
- index = 1;
- if (type != NULL) {
- for (i = 0; i < strlen(type); i++) {
- type[i] = toupper(type[i]);
- }
- while (isdigit(type[i-1])) {
- i--;
- }
- if (i < strlen(type)) {
- index = atoi(type +i);
- }
- type[i] = '\0';
- }
-
- for (i = 0; i <= sizeof(dataBufUc); i++) {
- dataBufUc[i] = toupper(dataBuf[i]);
- }
-
- snprintf_P(svalue, sizeof(svalue), PSTR("RSLT: DataCb Group %d, Index %d, Type %s, Data %s (%s)"),
- grpflg, index, type, dataBuf, dataBufUc);
- addLog(LOG_LEVEL_DEBUG, svalue);
-
- if (type != NULL) {
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Command\":\"Error\"}"));
- if (sysCfg.ledstate &0x02) {
- blinks++;
- }
-
- if (!strcmp(dataBufUc,"?")) {
- data_len = 0;
- }
- int16_t payload = -99; // No payload
- uint16_t payload16 = 0;
- long lnum = strtol(dataBuf, &p, 10);
- if (p != dataBuf) {
- payload = (int16_t) lnum; // -32766 - 32767
- payload16 = (uint16_t) lnum; // 0 - 65535
- }
- blogdelay = MIN_BACKLOG_DELAY; // Reset backlog delay
-
- if (!strcmp_P(dataBufUc,PSTR("OFF")) || !strcmp_P(dataBufUc,PSTR("FALSE")) || !strcmp_P(dataBufUc,PSTR("STOP")) || !strcmp_P(dataBufUc,PSTR("CELSIUS"))) {
- payload = 0;
- }
- if (!strcmp_P(dataBufUc,PSTR("ON")) || !strcmp_P(dataBufUc,PSTR("TRUE")) || !strcmp_P(dataBufUc,PSTR("START")) || !strcmp_P(dataBufUc,PSTR("FAHRENHEIT")) || !strcmp_P(dataBufUc,PSTR("USER"))) {
- payload = 1;
- }
- if (!strcmp_P(dataBufUc,PSTR("TOGGLE")) || !strcmp_P(dataBufUc,PSTR("ADMIN"))) {
- payload = 2;
- }
- if (!strcmp_P(dataBufUc,PSTR("BLINK"))) {
- payload = 3;
- }
- if (!strcmp_P(dataBufUc,PSTR("BLINKOFF"))) {
- payload = 4;
- }
-
-// snprintf_P(svalue, sizeof(svalue), PSTR("RSLT: Payload %d, Payload16 %d"), payload, payload16);
-// addLog(LOG_LEVEL_DEBUG, svalue);
-
- if (!strcmp_P(type,PSTR("BACKLOG"))) {
- if (data_len) {
- char *blcommand = strtok(dataBuf, ";");
- while (blcommand != NULL) {
- Backlog[blogidx] = String(blcommand);
- blogidx++;
-/*
- if (blogidx >= MAX_BACKLOG) {
- blogidx = 0;
- }
-*/
- blogidx &= 0xF;
- blcommand = strtok(NULL, ";");
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Backlog\":\"Appended\"}"));
- } else {
- uint8_t blflag = (blogptr == blogidx);
- blogptr = blogidx;
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Backlog\":\"%s\"}"), blflag ? "Empty" : "Aborted");
- }
- }
- else if (!strcmp_P(type,PSTR("DELAY"))) {
- if ((payload >= MIN_BACKLOG_DELAY) && (payload <= 3600)) {
- blogdelay = payload;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Delay\":%d}"), blogdelay);
- }
- else if (!strcmp_P(type,PSTR("POWER")) && (index > 0) && (index <= Maxdevice)) {
- if ((payload < 0) || (payload > 4)) {
- payload = 9;
- }
- do_cmnd_power(index, payload);
- fallbacktopic = 0;
- return;
- }
- else if (!strcmp_P(type,PSTR("STATUS"))) {
- if ((payload < 0) || (payload > MAX_STATUS)) {
- payload = 99;
- }
- publish_status(payload);
- fallbacktopic = 0;
- return;
- }
- else if ((sysCfg.module != MOTOR) && !strcmp_P(type,PSTR("POWERONSTATE"))) {
- if ((payload >= 0) && (payload <= 4)) {
- sysCfg.poweronstate = payload;
- if (4 == sysCfg.poweronstate) {
- for (byte i = 1; i <= Maxdevice; i++) {
- do_cmnd_power(i, 1);
- }
- }
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"PowerOnState\":%d}"), sysCfg.poweronstate);
- }
- else if (!strcmp_P(type,PSTR("PULSETIME")) && (index > 0) && (index <= MAX_PULSETIMERS)) {
- if (data_len > 0) {
- sysCfg.pulsetime[index -1] = payload16; // 0 - 65535
- pulse_timer[index -1] = 0;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"PulseTime%d\":%d}"), index, sysCfg.pulsetime[index -1]);
- }
- else if (!strcmp_P(type,PSTR("BLINKTIME"))) {
- if ((payload > 2) && (payload <= 3600)) {
- sysCfg.blinktime = payload;
- if (blink_timer) {
- blink_timer = sysCfg.blinktime;
- }
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"BlinkTime\":%d}"), sysCfg.blinktime);
- }
- else if (!strcmp_P(type,PSTR("BLINKCOUNT"))) {
- if (data_len > 0) {
- sysCfg.blinkcount = payload16; // 0 - 65535
- if (blink_counter) {
- blink_counter = sysCfg.blinkcount *2;
- }
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"BlinkCount\":%d}"), sysCfg.blinkcount);
- }
- else if (sfl_flg && sl_command(type, index, dataBufUc, data_len, payload, svalue, sizeof(svalue))) {
- // Serviced
- }
- else if (!strcmp_P(type,PSTR("SAVEDATA"))) {
- if ((payload >= 0) && (payload <= 3600)) {
- sysCfg.savedata = payload;
- savedatacounter = sysCfg.savedata;
- }
- if (sysCfg.flag.savestate) {
- sysCfg.power = power;
- }
- CFG_Save(0);
- 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 > 1) ? stemp1 : getStateText(sysCfg.savedata));
- }
- else if (!strcmp_P(type,PSTR("SETOPTION")) && ((index >= 0) && (index <= 13)) || ((index > 31) && (index <= P_MAX_PARAM8 +31))) {
- if (index <= 31) {
- ptype = 0; // SetOption0 .. 31
- } else {
- ptype = 1; // SetOption32 ..
- index = index -32;
- }
- if (payload >= 0) {
- if (0 == ptype) { // SetOption0 .. 31
- if (payload <= 1) {
- switch (index) {
- case 3: // mqtt
- restartflag = 2;
- case 0: // savestate
- case 1: // button_restrict
- case 2: // value_units
- case 4: // mqtt_response
- case 8: // temperature_conversion
- case 10: // mqtt_offline
- case 11: // button_swap
- case 12: // stop_flash_rotate
- case 13: // button_single
- bitWrite(sysCfg.flag.data, index, payload);
- }
- if (12 == index) { // stop_flash_rotate
- stop_flash_rotate = payload;
- CFG_Save(2);
- }
- }
- }
- else { // SetOption32 ..
- switch (index) {
- case P_HOLD_TIME:
- if ((payload >= 1) && (payload <= 100)) {
- sysCfg.param[P_HOLD_TIME] = payload;
- }
- break;
- case P_MAX_POWER_RETRY:
- if ((payload >= 1) && (payload <= 250)) {
- sysCfg.param[P_MAX_POWER_RETRY] = payload;
- }
- break;
- }
- }
- }
- if (ptype) {
- snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), sysCfg.param[index]);
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"SetOption%d\":\"%s\"}"), (ptype) ? index +32 : index, (ptype) ? stemp1 : getStateText(bitRead(sysCfg.flag.data, index)));
- }
- else if (!strcmp_P(type,PSTR("TEMPRES"))) {
- if ((payload >= 0) && (payload <= 3)) {
- sysCfg.flag.temperature_resolution = payload;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"TempRes\":%d}"), sysCfg.flag.temperature_resolution);
- }
- else if (!strcmp_P(type,PSTR("HUMRES"))) {
- if ((payload >= 0) && (payload <= 3)) {
- sysCfg.flag.humidity_resolution = payload;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"HumRes\":%d}"), sysCfg.flag.humidity_resolution);
- }
- else if (!strcmp_P(type,PSTR("PRESSRES"))) {
- if ((payload >= 0) && (payload <= 3)) {
- sysCfg.flag.pressure_resolution = payload;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"PressRes\":%d}"), sysCfg.flag.pressure_resolution);
- }
- else if (!strcmp_P(type,PSTR("VOLTRES"))) {
- if ((payload >= 0) && (payload <= 1)) {
- sysCfg.flag.voltage_resolution = payload;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"VoltRes\":%d}"), sysCfg.flag.voltage_resolution);
- }
- else if (!strcmp_P(type,PSTR("ENERGYRES"))) {
- if ((payload >= 0) && (payload <= 5)) {
- sysCfg.flag.energy_resolution = payload;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"EnergyRes\":%d}"), sysCfg.flag.energy_resolution);
- }
- else if (!strcmp_P(type,PSTR("MODULE"))) {
- if ((payload > 0) && (payload <= MAXMODULE)) {
- payload--;
- byte new_modflg = (sysCfg.module != payload);
- sysCfg.module = payload;
- if (new_modflg) {
- for (byte i = 0; i < MAX_GPIO_PIN; i++) {
- sysCfg.my_module.gp.io[i] = 0;
- }
- }
- restartflag = 2;
- }
- snprintf_P(stemp1, sizeof(stemp1), modules[sysCfg.module].name);
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Module\":\"%d (%s)\"}"), sysCfg.module +1, stemp1);
- }
- else if (!strcmp_P(type,PSTR("MODULES"))) {
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Modules1\":\""), svalue);
- byte jsflg = 0;
- for (byte i = 0; i < MAXMODULE /2; i++) {
- if (jsflg) {
- snprintf_P(svalue, sizeof(svalue), PSTR("%s, "), svalue);
- }
- jsflg = 1;
- snprintf_P(stemp1, sizeof(stemp1), modules[i].name);
- 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(5, type, svalue);
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Modules2\":\""), svalue);
- jsflg = 0;
- for (byte i = MAXMODULE /2; i < MAXMODULE; i++) {
- if (jsflg) {
- snprintf_P(svalue, sizeof(svalue), PSTR("%s, "), svalue);
- }
- jsflg = 1;
- snprintf_P(stemp1, sizeof(stemp1), modules[i].name);
- snprintf_P(svalue, sizeof(svalue), PSTR("%s%d (%s)"), svalue, i +1, stemp1);
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("%s\"}"), svalue);
- }
- else if (!strcmp_P(type,PSTR("GPIO")) && (index < MAX_GPIO_PIN)) {
- mytmplt cmodule;
- memcpy_P(&cmodule, &modules[sysCfg.module], sizeof(cmodule));
- if ((GPIO_USER == cmodule.gp.io[index]) && (payload >= 0) && (payload < GPIO_SENSOR_END)) {
- for (byte i = 0; i < MAX_GPIO_PIN; i++) {
- if ((GPIO_USER == cmodule.gp.io[i]) && (sysCfg.my_module.gp.io[i] == payload)) {
- sysCfg.my_module.gp.io[i] = 0;
- }
- }
- sysCfg.my_module.gp.io[index] = payload;
- restartflag = 2;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{"), svalue);
- byte jsflg = 0;
- for (byte i = 0; i < MAX_GPIO_PIN; i++) {
- if (GPIO_USER == cmodule.gp.io[i]) {
- if (jsflg) {
- snprintf_P(svalue, sizeof(svalue), PSTR("%s, "), svalue);
- }
- jsflg = 1;
- snprintf_P(stemp1, sizeof(stemp1), sensors[sysCfg.my_module.gp.io[i]]);
- snprintf_P(svalue, sizeof(svalue), PSTR("%s\"GPIO%d\":%d (%s)"), svalue, i, sysCfg.my_module.gp.io[i], stemp1);
- }
- }
- if (jsflg) {
- snprintf_P(svalue, sizeof(svalue), PSTR("%s}"), svalue);
- } else {
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"GPIO\":\"Not supported\"}"));
- }
- }
- else if (!strcmp_P(type,PSTR("GPIOS"))) {
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"GPIOs1\":\""), svalue);
- byte jsflg = 0;
- for (byte i = 0; i < GPIO_SENSOR_END /2; i++) {
- if (jsflg) {
- snprintf_P(svalue, sizeof(svalue), PSTR("%s, "), svalue);
- }
- jsflg = 1;
- snprintf_P(stemp1, sizeof(stemp1), sensors[i]);
- snprintf_P(svalue, sizeof(svalue), PSTR("%s%d (%s)"), svalue, i, stemp1);
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("%s\"}"), svalue);
- mqtt_publish_topic_P(5, type, svalue);
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"GPIOs2\":\""), svalue);
- jsflg = 0;
- for (byte i = GPIO_SENSOR_END /2; i < GPIO_SENSOR_END; i++) {
- if (jsflg) {
- snprintf_P(svalue, sizeof(svalue), PSTR("%s, "), svalue);
- }
- jsflg = 1;
- snprintf_P(stemp1, sizeof(stemp1), sensors[i]);
- snprintf_P(svalue, sizeof(svalue), PSTR("%s%d (%s)"), svalue, i, stemp1);
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("%s\"}"), svalue);
- }
- else if (!strcmp_P(type,PSTR("PWM")) && (index > pwm_idxoffset) && (index <= 5)) {
- if ((payload >= 0) && (payload <= PWM_RANGE) && (pin[GPIO_PWM1 + index -1] < 99)) {
- sysCfg.pwmvalue[index -1] = payload;
- analogWrite(pin[GPIO_PWM1 + index -1], payload);
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"PWM\":{"));
- bool first = true;
- for (byte i = 0; i < 5; i++) {
- if(pin[GPIO_PWM1 + i] < 99) {
- snprintf_P(svalue, sizeof(svalue), PSTR("%s%s\"PWM%d\":%d"), svalue, first ? "" : ", ", i+1, sysCfg.pwmvalue[i]);
- first = false;
- }
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("%s}}"),svalue);
- }
- else if (!strcmp_P(type,PSTR("COUNTER")) && (index > 0) && (index <= MAX_COUNTERS)) {
- if ((data_len > 0) && (pin[GPIO_CNTR1 + index -1] < 99)) {
- rtcMem.pCounter[index -1] = payload16;
- sysCfg.pCounter[index -1] = payload16;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Counter%d\":%d}"), index, rtcMem.pCounter[index -1]);
- }
- else if (!strcmp_P(type,PSTR("COUNTERTYPE")) && (index > 0) && (index <= MAX_COUNTERS)) {
- if ((payload >= 0) && (payload <= 1) && (pin[GPIO_CNTR1 + index -1] < 99)) {
- bitWrite(sysCfg.pCounterType, index -1, payload &1);
- rtcMem.pCounter[index -1] = 0;
- sysCfg.pCounter[index -1] = 0;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"CounterType%d\":%d}"), index, bitRead(sysCfg.pCounterType, index -1));
- }
- else if (!strcmp_P(type,PSTR("COUNTERDEBOUNCE"))) {
- if ((data_len > 0) && (payload16 < 32001)) {
- sysCfg.pCounterDebounce = payload16;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"CounterDebounce\":%d}"), sysCfg.pCounterDebounce);
- }
- else if (!strcmp_P(type,PSTR("SLEEP"))) {
- if ((payload >= 0) && (payload < 251)) {
- if ((!sysCfg.sleep && payload) || (sysCfg.sleep && !payload)) {
- restartflag = 2;
- }
- sysCfg.sleep = payload;
- sleep = payload;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Sleep\":\"%d%s (%d%s)\"}"), sleep, (sysCfg.flag.value_units) ? " mS" : "", sysCfg.sleep, (sysCfg.flag.value_units) ? " mS" : "");
- }
- else if (!strcmp_P(type,PSTR("UPGRADE")) || !strcmp_P(type,PSTR("UPLOAD"))) {
- // Check if the payload is numerically 1, and had no trailing chars.
- // e.g. "1foo" or "1.2.3" could fool us.
- // Check if the version we have been asked to upgrade to is higher than our current version.
- // We also need at least 3 chars to make a valid version number string.
- if (((1 == data_len) && (1 == payload)) || ((data_len >= 3) && newerVersion(dataBuf))) {
- otaflag = 3;
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Upgrade\":\"Version %s from %s\"}"), Version, sysCfg.otaUrl);
- } else {
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Upgrade\":\"Option 1 or >%s to upgrade\"}"), Version);
- }
- }
- else if (!strcmp_P(type,PSTR("OTAURL"))) {
- if ((data_len > 0) && (data_len < sizeof(sysCfg.otaUrl)))
- strlcpy(sysCfg.otaUrl, (1 == payload) ? OTA_URL : dataBuf, sizeof(sysCfg.otaUrl));
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"OtaUrl\":\"%s\"}"), sysCfg.otaUrl);
- }
- else if (!strcmp_P(type,PSTR("SERIALLOG"))) {
- if ((payload >= LOG_LEVEL_NONE) && (payload <= LOG_LEVEL_ALL)) {
- sysCfg.seriallog_level = payload;
- seriallog_level = payload;
- seriallog_timer = 0;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"SerialLog\":\"%d (Active %d)\"}"), sysCfg.seriallog_level, seriallog_level);
- }
- else if (!strcmp_P(type,PSTR("SYSLOG"))) {
- if ((payload >= LOG_LEVEL_NONE) && (payload <= LOG_LEVEL_ALL)) {
- sysCfg.syslog_level = payload;
- syslog_level = (sysCfg.flag.emulation) ? 0 : payload;
- syslog_timer = 0;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"SysLog\":\"%d (Active %d)\"}"), sysCfg.syslog_level, syslog_level);
- }
- else if (!strcmp_P(type,PSTR("LOGHOST"))) {
- if ((data_len > 0) && (data_len < sizeof(sysCfg.syslog_host))) {
- strlcpy(sysCfg.syslog_host, (1 == payload) ? SYS_LOG_HOST : dataBuf, sizeof(sysCfg.syslog_host));
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"LogHost\":\"%s\"}"), sysCfg.syslog_host);
- }
- else if (!strcmp_P(type,PSTR("LOGPORT"))) {
- if ((payload > 0) && (payload < 32766)) {
- sysCfg.syslog_port = (1 == payload) ? SYS_LOG_PORT : payload;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"LogPort\":%d}"), sysCfg.syslog_port);
- }
- else if (!strcmp_P(type,PSTR("IPADDRESS")) && (index > 0) && (index <= 4)) {
- if (parseIP(&address, dataBuf)) {
- sysCfg.ip_address[index -1] = address;
-// restartflag = 2;
- }
- 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(), (1 == index) ? stemp1:"");
- }
- else if (!strcmp_P(type,PSTR("NTPSERVER")) && (index > 0) && (index <= 3)) {
- if ((data_len > 0) && (data_len < sizeof(sysCfg.ntp_server[0]))) {
- strlcpy(sysCfg.ntp_server[index -1], (!strcmp(dataBuf,"0")) ? "" : (1 == payload) ? (1==index)?NTP_SERVER1:(2==index)?NTP_SERVER2:NTP_SERVER3 : dataBuf, sizeof(sysCfg.ntp_server[0]));
- for (i = 0; i < strlen(sysCfg.ntp_server[index -1]); i++) {
- if (sysCfg.ntp_server[index -1][i] == ',') {
- sysCfg.ntp_server[index -1][i] = '.';
- }
- }
- restartflag = 2;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"NtpServer%d\":\"%s\"}"), index, sysCfg.ntp_server[index -1]);
- }
- else if (!strcmp_P(type,PSTR("AP"))) {
- if ((payload >= 0) && (payload <= 2)) {
- switch (payload) {
- case 0: // Toggle
- sysCfg.sta_active ^= 1;
- break;
- case 1: // AP1
- case 2: // AP2
- sysCfg.sta_active = payload -1;
- }
- restartflag = 2;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Ap\":\"%d (%s)\"}"), sysCfg.sta_active +1, sysCfg.sta_ssid[sysCfg.sta_active]);
- }
- else if (!strcmp_P(type,PSTR("SSID")) && (index > 0) && (index <= 2)) {
- if ((data_len > 0) && (data_len < sizeof(sysCfg.sta_ssid[0]))) {
- strlcpy(sysCfg.sta_ssid[index -1], (1 == payload) ? (1 == index) ? STA_SSID1 : STA_SSID2 : dataBuf, sizeof(sysCfg.sta_ssid[0]));
- sysCfg.sta_active = 0;
- restartflag = 2;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"SSid%d\":\"%s\"}"), index, sysCfg.sta_ssid[index -1]);
- }
- else if (!strcmp_P(type,PSTR("PASSWORD")) && (index > 0) && (index <= 2)) {
- if ((data_len > 0) && (data_len < sizeof(sysCfg.sta_pwd[0]))) {
- strlcpy(sysCfg.sta_pwd[index -1], (1 == payload) ? (1 == index) ? STA_PASS1 : STA_PASS2 : dataBuf, sizeof(sysCfg.sta_pwd[0]));
- sysCfg.sta_active = 0;
- restartflag = 2;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Password%d\":\"%s\"}"), index, sysCfg.sta_pwd[index -1]);
- }
- else if (!grpflg && !strcmp_P(type,PSTR("HOSTNAME"))) {
- if ((data_len > 0) && (data_len < sizeof(sysCfg.hostname))) {
- strlcpy(sysCfg.hostname, (1 == payload) ? WIFI_HOSTNAME : dataBuf, sizeof(sysCfg.hostname));
- if (strstr(sysCfg.hostname,"%")) {
- strlcpy(sysCfg.hostname, WIFI_HOSTNAME, sizeof(sysCfg.hostname));
- }
- restartflag = 2;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Hostname\":\"%s\"}"), sysCfg.hostname);
- }
- else if (!strcmp_P(type,PSTR("WIFICONFIG"))) {
- if ((payload >= WIFI_RESTART) && (payload < MAX_WIFI_OPTION)) {
- sysCfg.sta_config = payload;
- wificheckflag = sysCfg.sta_config;
- snprintf_P(stemp1, sizeof(stemp1), wificfg[sysCfg.sta_config]);
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"WifiConfig\":\"%s selected\"}"), stemp1);
- if (WIFI_State() != WIFI_RESTART) {
-// snprintf_P(svalue, sizeof(svalue), PSTR("%s after restart"), svalue);
- restartflag = 2;
- }
- } else {
- snprintf_P(stemp1, sizeof(stemp1), wificfg[sysCfg.sta_config]);
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"WifiConfig\":\"%d (%s)\"}"), sysCfg.sta_config, stemp1);
- }
- }
- else if (!strcmp_P(type,PSTR("FRIENDLYNAME")) && (index > 0) && (index <= 4)) {
- if ((data_len > 0) && (data_len < sizeof(sysCfg.friendlyname[0]))) {
- if (1 == index) {
- snprintf_P(stemp1, sizeof(stemp1), PSTR(FRIENDLY_NAME));
- } else {
- snprintf_P(stemp1, sizeof(stemp1), PSTR(FRIENDLY_NAME "%d"), index);
- }
- strlcpy(sysCfg.friendlyname[index -1], (1 == payload) ? stemp1 : dataBuf, sizeof(sysCfg.friendlyname[index -1]));
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"FriendlyName%d\":\"%s\"}"), index, sysCfg.friendlyname[index -1]);
- }
- else if (swt_flg && !strcmp_P(type,PSTR("SWITCHMODE")) && (index > 0) && (index <= 4)) {
- if ((payload >= 0) && (payload < MAX_SWITCH_OPTION)) {
- sysCfg.switchmode[index -1] = payload;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"SwitchMode%d\":%d}"), index, sysCfg.switchmode[index-1]);
- }
-#ifdef USE_WEBSERVER
- else if (!strcmp_P(type,PSTR("WEBSERVER"))) {
- if ((payload >= 0) && (payload <= 2)) {
- sysCfg.webserver = payload;
- }
- if (sysCfg.webserver) {
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Webserver\":\"Active for %s on %s with IP address %s\"}"),
- (2 == sysCfg.webserver) ? "ADMIN" : "USER", Hostname, WiFi.localIP().toString().c_str());
- } else {
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Webserver\":\"%s\"}"), getStateText(0));
- }
- }
- else if (!strcmp_P(type,PSTR("WEBPASSWORD"))) {
- if ((data_len > 0) && (data_len < sizeof(sysCfg.web_password))) {
- strlcpy(sysCfg.web_password, (!strcmp(dataBuf,"0")) ? "" : (1 == payload) ? WEB_PASSWORD : dataBuf, sizeof(sysCfg.web_password));
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"WebPassword\":\"%s\"}"), sysCfg.web_password);
- }
- else if (!strcmp_P(type,PSTR("WEBLOG"))) {
- if ((payload >= LOG_LEVEL_NONE) && (payload <= LOG_LEVEL_ALL)) {
- sysCfg.weblog_level = payload;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"WebLog\":%d}"), sysCfg.weblog_level);
- }
-#ifdef USE_EMULATION
- else if (!strcmp_P(type,PSTR("EMULATION"))) {
- if ((payload >= 0) && (payload <= 2)) {
- sysCfg.flag.emulation = payload;
- restartflag = 2;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Emulation\":%d}"), sysCfg.flag.emulation);
- }
-#endif // USE_EMULATION
-#endif // USE_WEBSERVER
- else if (!strcmp_P(type,PSTR("TELEPERIOD"))) {
- if ((payload >= 0) && (payload < 3601)) {
- sysCfg.tele_period = (1 == payload) ? TELE_PERIOD : payload;
- if ((sysCfg.tele_period > 0) && (sysCfg.tele_period < 10)) {
- sysCfg.tele_period = 10; // Do not allow periods < 10 seconds
- }
- tele_period = sysCfg.tele_period;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"TelePeriod\":\"%d%s\"}"), sysCfg.tele_period, (sysCfg.flag.value_units) ? " Sec" : "");
- }
- else if (!strcmp_P(type,PSTR("RESTART"))) {
- switch (payload) {
- case 1:
- restartflag = 2;
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Restart\":\"Restarting\"}"));
- break;
- case 99:
- addLog_P(LOG_LEVEL_INFO, PSTR("APP: Restarting"));
- ESP.restart();
- break;
- default:
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Restart\":\"1 to restart\"}"));
- }
- }
- else if (!strcmp_P(type,PSTR("RESET"))) {
- switch (payload) {
- case 1:
- restartflag = 211;
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Reset\":\"Reset and Restarting\"}"));
- break;
- case 2:
- restartflag = 212;
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Reset\":\"Erase, Reset and Restarting\"}"));
- break;
- default:
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Reset\":\"1 to reset\"}"));
- }
- }
- else if (!strcmp_P(type,PSTR("TIMEZONE"))) {
- if ((data_len > 0) && (((payload >= -12) && (payload <= 12)) || (99 == payload))) {
- sysCfg.timezone = payload;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Timezone\":%d}"), sysCfg.timezone);
- }
- else if (!strcmp_P(type,PSTR("LEDPOWER"))) {
- if ((payload >= 0) && (payload <= 2)) {
- sysCfg.ledstate &= 8;
- switch (payload) {
- case 0: // Off
- case 1: // On
- sysCfg.ledstate = payload << 3;
- break;
- case 2: // Toggle
- sysCfg.ledstate ^= 8;
- break;
- }
- blinks = 0;
- setLed(sysCfg.ledstate &8);
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"LedPower\":\"%s\"}"), getStateText(bitRead(sysCfg.ledstate, 3)));
- }
- else if (!strcmp_P(type,PSTR("LEDSTATE"))) {
- if ((payload >= 0) && (payload < MAX_LED_OPTION)) {
- sysCfg.ledstate = payload;
- if (!sysCfg.ledstate) {
- setLed(0);
- }
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"LedState\":%d}"), sysCfg.ledstate);
- }
- else if (!strcmp_P(type,PSTR("CFGDUMP"))) {
- CFG_Dump(dataBuf);
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"CfgDump\":\"Done\"}"));
- }
- else if (sysCfg.flag.mqtt_enabled && mqtt_command(grpflg, type, index, dataBuf, data_len, payload, svalue, sizeof(svalue))) {
- // Serviced
- }
- else if (hlw_flg && hlw_command(type, index, dataBuf, data_len, payload, svalue, sizeof(svalue))) {
- // Serviced
- }
- else if ((SONOFF_BRIDGE == sysCfg.module) && sb_command(type, index, dataBuf, data_len, payload, svalue, sizeof(svalue))) {
- // Serviced
- }
-#ifdef USE_I2C
- else if (i2c_flg && !strcmp_P(type,PSTR("I2CSCAN"))) {
- i2c_scan(svalue, sizeof(svalue));
- }
-#endif // USE_I2C
-#ifdef USE_WS2812
- else if ((pin[GPIO_WS2812] < 99) && ws2812_command(type, index, dataBuf, data_len, payload, svalue, sizeof(svalue))) {
- // Serviced
- }
-#endif // USE_WS2812
-#ifdef USE_IR_REMOTE
- else if ((pin[GPIO_IRSEND] < 99) && ir_send_command(type, index, dataBufUc, data_len, payload, svalue, sizeof(svalue))) {
- // Serviced
- }
-#endif // USE_IR_REMOTE
-#ifdef DEBUG_THEO
- else if (!strcmp_P(type,PSTR("EXCEPTION"))) {
- if (data_len > 0) {
- exception_tst(payload);
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Exception\":\"Triggered\"}"));
- }
-#endif // DEBUG_THEO
- else {
- type = NULL;
- }
- }
- if (type == NULL) {
- blinks = 201;
- snprintf_P(topicBuf, sizeof(topicBuf), PSTR("COMMAND"));
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Command\":\"Unknown\"}"));
- type = (char*)topicBuf;
- }
- if (svalue[0] != '\0') {
- mqtt_publish_topic_P(5, type, svalue);
- }
- fallbacktopic = 0;
-}
-
-/********************************************************************************************/
-
-boolean send_button_power(byte key, byte device, byte state)
-{
-// key 0 = button_topic
-// key 1 = switch_topic
-// state 0 = off
-// state 1 = on
-// state 2 = toggle
-// state 3 = hold
-// state 9 = clear retain flag
-
- char stopic[TOPSZ];
- char scommand[CMDSZ];
- char svalue[TOPSZ];
- char stemp1[10];
- boolean result = false;
-
- char *key_topic = (key) ? sysCfg.switch_topic : sysCfg.button_topic;
- if (sysCfg.flag.mqtt_enabled && mqttClient.connected() && (strlen(key_topic) != 0) && strcmp(key_topic, "0")) {
- if (!key && (device > Maxdevice)) {
- device = 1;
- }
- snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), device);
- snprintf_P(scommand, sizeof(scommand), PSTR("POWER%s"), (key || (Maxdevice > 1)) ? stemp1 : "");
- getTopic_P(stopic, 0, key_topic, scommand);
-
- if (9 == state) {
- svalue[0] = '\0';
- } else {
- if ((!strcmp(sysCfg.mqtt_topic, key_topic) || !strcmp(sysCfg.mqtt_grptopic, key_topic)) && (2 == state)) {
- state = ~(power >> (device -1)) & 0x01;
- }
- snprintf_P(svalue, sizeof(svalue), PSTR("%s"), getStateText(state));
- }
-#ifdef USE_DOMOTICZ
- if (!(domoticz_button(key, device, state, strlen(svalue)))) {
- mqtt_publish_sec(stopic, svalue, (key) ? sysCfg.flag.mqtt_switch_retain : sysCfg.flag.mqtt_button_retain);
- }
-#else
- mqtt_publish_sec(stopic, svalue, (key) ? sysCfg.flag.mqtt_switch_retain : sysCfg.flag.mqtt_button_retain);
-#endif // USE_DOMOTICZ
- result = true;
- }
- return result;
-}
-
-void do_cmnd_power(byte device, byte state)
-{
-// device = Relay number 1 and up
-// state 0 = Relay Off
-// state 1 = Relay On (turn off after sysCfg.pulsetime * 100 mSec if enabled)
-// state 2 = Toggle relay
-// state 3 = Blink relay
-// state 4 = Stop blinking relay
-// state 6 = Relay Off and no publishPowerState
-// state 7 = Relay On and no publishPowerState
-// state 9 = Show power state
-
- uint8_t publishPower = 1;
- if ((6 == state) || (7 == state)) {
- state &= 1;
- publishPower = 0;
- }
- if ((device < 1) || (device > Maxdevice)) {
- device = 1;
- }
- byte mask = 0x01 << (device -1);
- pulse_timer[(device -1)&3] = 0;
- if (state <= 2) {
- if ((blink_mask & mask)) {
- blink_mask &= (0xFF ^ mask); // Clear device mask
- mqtt_publishPowerBlinkState(device);
- }
- switch (state) {
- case 0: { // Off
- power &= (0xFF ^ mask);
- break; }
- case 1: // On
- power |= mask;
- break;
- case 2: // Toggle
- power ^= mask;
- }
- setRelay(power);
-#ifdef USE_DOMOTICZ
- domoticz_updatePowerState(device);
-#endif // USE_DOMOTICZ
- pulse_timer[(device -1)&3] = (power & mask) ? sysCfg.pulsetime[(device -1)&3] : 0;
- }
- else if (3 == state) { // Blink
- if (!(blink_mask & mask)) {
- blink_powersave = (blink_powersave & (0xFF ^ mask)) | (power & mask); // Save state
- blink_power = (power >> (device -1))&1; // Prep to Toggle
- }
- blink_timer = 1;
- blink_counter = ((!sysCfg.blinkcount) ? 64000 : (sysCfg.blinkcount *2)) +1;
- blink_mask |= mask; // Set device mask
- mqtt_publishPowerBlinkState(device);
- return;
- }
- else if (4 == state) { // No Blink
- byte flag = (blink_mask & mask);
- blink_mask &= (0xFF ^ mask); // Clear device mask
- mqtt_publishPowerBlinkState(device);
- if (flag) {
- do_cmnd_power(device, (blink_powersave >> (device -1))&1); // Restore state
- }
- return;
- }
- if (publishPower) {
- mqtt_publishPowerState(device);
- }
-}
-
-void stop_all_power_blink()
-{
- byte mask;
-
- for (byte i = 1; i <= Maxdevice; i++) {
- mask = 0x01 << (i -1);
- if (blink_mask & mask) {
- blink_mask &= (0xFF ^ mask); // Clear device mask
- mqtt_publishPowerBlinkState(i);
- do_cmnd_power(i, (blink_powersave >> (i -1))&1); // Restore state
- }
- }
-}
-
-void do_cmnd(char *cmnd)
-{
- char stopic[CMDSZ];
- char svalue[INPUT_BUFFER_SIZE];
- char *start;
- char *token;
-
- token = strtok(cmnd, " ");
- if (token != NULL) {
- start = strrchr(token, '/'); // Skip possible cmnd/sonoff/ preamble
- if (start) {
- token = start +1;
- }
- }
- snprintf_P(stopic, sizeof(stopic), PSTR("/%s"), (token == NULL) ? "" : token);
- token = strtok(NULL, "");
- snprintf_P(svalue, sizeof(svalue), PSTR("%s"), (token == NULL) ? "" : token);
- mqttDataCb(stopic, (byte*)svalue, strlen(svalue));
-}
-
-void publish_status(uint8_t payload)
-{
- char svalue[MESSZ];
- uint8_t option = 1;
-
- // Workaround MQTT - TCP/IP stack queueing when SUB_PREFIX = PUB_PREFIX
- if (!strcmp(sysCfg.mqtt_prefix[0],sysCfg.mqtt_prefix[1]) && (!payload)) {
- option++;
- }
-
- if ((!sysCfg.flag.mqtt_enabled) && (6 == payload)) {
- payload = 99;
- }
- if ((!hlw_flg) && ((8 == payload) || (9 == payload))) {
- payload = 99;
- }
-
- if ((0 == payload) || (99 == payload)) {
- 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.flag.savestate, sysCfg.flag.mqtt_button_retain, sysCfg.flag.mqtt_power_retain);
- mqtt_publish_topic_P(option, PSTR("STATUS"), svalue);
- }
-
- if ((0 == payload) || (1 == payload)) {
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"StatusPRM\":{\"Baudrate\":%d, \"GroupTopic\":\"%s\", \"OtaUrl\":\"%s\", \"Uptime\":%d, \"Sleep\":%d, \"BootCount\":%d, \"SaveCount\":%d, \"SaveAddress\":\"%X\"}}"),
- Baudrate, sysCfg.mqtt_grptopic, sysCfg.otaUrl, uptime, sysCfg.sleep, sysCfg.bootcount, sysCfg.saveFlag, CFG_Address());
- mqtt_publish_topic_P(option, PSTR("STATUS1"), svalue);
- }
-
- if ((0 == payload) || (2 == payload)) {
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"StatusFWR\":{\"Program\":\"%s\", \"BuildDateTime\":\"%s\", \"Boot\":%d, \"Core\":\"%s\", \"SDK\":\"%s\"}}"),
- Version, getBuildDateTime().c_str(), ESP.getBootVersion(), ESP.getCoreVersion().c_str(), ESP.getSdkVersion());
- mqtt_publish_topic_P(option, PSTR("STATUS2"), svalue);
- }
-
- if ((0 == payload) || (3 == payload)) {
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"StatusLOG\":{\"Seriallog\":%d, \"Weblog\":%d, \"Syslog\":%d, \"LogHost\":\"%s\", \"SSId1\":\"%s\", \"SSId2\":\"%s\", \"TelePeriod\":%d, \"Option\":\"%08X\"}}"),
- sysCfg.seriallog_level, sysCfg.weblog_level, sysCfg.syslog_level, sysCfg.syslog_host, sysCfg.sta_ssid[0], sysCfg.sta_ssid[1], sysCfg.tele_period, sysCfg.flag.data);
- mqtt_publish_topic_P(option, PSTR("STATUS3"), svalue);
- }
-
- if ((0 == payload) || (4 == payload)) {
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"StatusMEM\":{\"ProgramSize\":%d, \"Free\":%d, \"Heap\":%d, \"ProgramFlashSize\":%d, \"FlashSize\":%d, \"FlashMode\":%d}}"),
- ESP.getSketchSize()/1024, ESP.getFreeSketchSpace()/1024, ESP.getFreeHeap()/1024, ESP.getFlashChipSize()/1024, ESP.getFlashChipRealSize()/1024, ESP.getFlashChipMode());
- mqtt_publish_topic_P(option, PSTR("STATUS4"), svalue);
- }
-
- if ((0 == payload) || (5 == payload)) {
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"StatusNET\":{\"Hostname\":\"%s\", \"IPaddress\":\"%s\", \"Gateway\":\"%s\", \"Subnetmask\":\"%s\", \"DNSServer\":\"%s\", \"Mac\":\"%s\", \"Webserver\":%d, \"WifiConfig\":%d}}"),
- Hostname, WiFi.localIP().toString().c_str(), IPAddress(sysCfg.ip_address[1]).toString().c_str(), IPAddress(sysCfg.ip_address[2]).toString().c_str(), IPAddress(sysCfg.ip_address[3]).toString().c_str(),
- WiFi.macAddress().c_str(), sysCfg.webserver, sysCfg.sta_config);
- mqtt_publish_topic_P(option, PSTR("STATUS5"), svalue);
- }
-
- if (((0 == payload) || (6 == payload)) && sysCfg.flag.mqtt_enabled) {
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"StatusMQT\":{\"Host\":\"%s\", \"Port\":%d, \"ClientMask\":\"%s\", \"Client\":\"%s\", \"User\":\"%s\", \"MAX_PACKET_SIZE\":%d, \"KEEPALIVE\":%d}}"),
- sysCfg.mqtt_host, sysCfg.mqtt_port, sysCfg.mqtt_client, MQTTClient, sysCfg.mqtt_user, MQTT_MAX_PACKET_SIZE, MQTT_KEEPALIVE);
- mqtt_publish_topic_P(option, PSTR("STATUS6"), svalue);
- }
-
- if ((0 == payload) || (7 == payload)) {
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"StatusTIM\":{\"UTC\":\"%s\", \"Local\":\"%s\", \"StartDST\":\"%s\", \"EndDST\":\"%s\", \"Timezone\":%d}}"),
- rtc_time(0).c_str(), rtc_time(1).c_str(), rtc_time(2).c_str(), rtc_time(3).c_str(), sysCfg.timezone);
- mqtt_publish_topic_P(option, PSTR("STATUS7"), svalue);
- }
-
- if (hlw_flg) {
- if ((0 == payload) || (8 == payload)) {
- hlw_mqttStatus(svalue, sizeof(svalue));
- mqtt_publish_topic_P(option, PSTR("STATUS8"), svalue);
- }
-
- if ((0 == payload) || (9 == payload)) {
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"StatusPTH\":{\"PowerLow\":%d, \"PowerHigh\":%d, \"VoltageLow\":%d, \"VoltageHigh\":%d, \"CurrentLow\":%d, \"CurrentHigh\":%d}}"),
- sysCfg.hlw_pmin, sysCfg.hlw_pmax, sysCfg.hlw_umin, sysCfg.hlw_umax, sysCfg.hlw_imin, sysCfg.hlw_imax);
- mqtt_publish_topic_P(option, PSTR("STATUS9"), svalue);
- }
- }
-
- if ((0 == payload) || (10 == payload)) {
- uint8_t djson = 0;
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"StatusSNS\":"));
- sensors_mqttPresent(svalue, sizeof(svalue), &djson);
- snprintf_P(svalue, sizeof(svalue), PSTR("%s}"), svalue);
- mqtt_publish_topic_P(option, PSTR("STATUS10"), svalue);
- }
-
- if ((0 == payload) || (11 == payload)) {
- 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);
- }
-
-}
-
-void state_mqttPresent(char* svalue, uint16_t ssvalue)
-{
- char stemp1[8];
-
- snprintf_P(svalue, ssvalue, PSTR("%s{\"Time\":\"%s\", \"Uptime\":%d"), svalue, getDateTime().c_str(), uptime);
-#ifdef USE_ADC_VCC
- dtostrf((double)ESP.getVcc()/1000, 1, 3, stemp1);
- snprintf_P(svalue, ssvalue, PSTR("%s, \"Vcc\":%s"), svalue, stemp1);
-#endif
- for (byte i = 0; i < Maxdevice; i++) {
- if (1 == Maxdevice) { // Legacy
- snprintf_P(svalue, ssvalue, PSTR("%s, \"POWER\":"), svalue);
- } else {
- snprintf_P(svalue, ssvalue, PSTR("%s, \"POWER%d\":"), svalue, i +1);
- }
- 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, \"APMac\":\"%s\"}}"),
- svalue, sysCfg.sta_active +1, sysCfg.sta_ssid[sysCfg.sta_active], WIFI_getRSSIasQuality(WiFi.RSSI()), WiFi.BSSIDstr().c_str());
-}
-
-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) {
- boolean swm = ((FOLLOW_INV == sysCfg.switchmode[i]) || (PUSHBUTTON_INV == sysCfg.switchmode[i]) || (PUSHBUTTONHOLD_INV == sysCfg.switchmode[i]));
- snprintf_P(svalue, ssvalue, PSTR("%s, \"Switch%d\":\"%s\""), svalue, i +1, getStateText(swm ^ lastwallswitch[i]));
- *djson = 1;
- }
- }
- counter_mqttPresent(svalue, ssvalue, djson);
-#ifndef USE_ADC_VCC
- if (pin[GPIO_ADC0] < 99) {
- uint16_t alr = 0;
- for (byte i = 0; i < 32; i++) {
- alr += analogRead(A0);
- delay(1);
- }
- snprintf_P(svalue, ssvalue, PSTR("%s, \"AnalogInput0\":%d"), svalue, alr >> 5);
- *djson = 1;
- }
-#endif
- if (SONOFF_SC == sysCfg.module) {
- sc_mqttPresent(svalue, ssvalue, djson);
- }
- if (pin[GPIO_DSB] < 99) {
-#ifdef USE_DS18B20
- dsb_mqttPresent(svalue, ssvalue, djson);
-#endif // USE_DS18B20
-#ifdef USE_DS18x20
- ds18x20_mqttPresent(svalue, ssvalue, djson);
-#endif // USE_DS18x20
- }
-#ifdef USE_DHT
- if (dht_flg) {
- dht_mqttPresent(svalue, ssvalue, djson);
- }
-#endif // USE_DHT
-#ifdef USE_I2C
- if (i2c_flg) {
-#ifdef USE_SHT
- sht_mqttPresent(svalue, ssvalue, djson);
-#endif // USE_SHT
-#ifdef USE_HTU
- htu_mqttPresent(svalue, ssvalue, djson);
-#endif // USE_HTU
-#ifdef USE_BMP
- bmp_mqttPresent(svalue, ssvalue, djson);
-#endif // USE_BMP
-#ifdef USE_BH1750
- bh1750_mqttPresent(svalue, ssvalue, djson);
-#endif // USE_BH1750
- }
-#endif // USE_I2C
- if (strstr_P(svalue, PSTR("Temperature"))) {
- snprintf_P(svalue, ssvalue, PSTR("%s, \"TempUnit\":\"%c\""), svalue, tempUnit());
- }
- snprintf_P(svalue, ssvalue, PSTR("%s}"), svalue);
-}
-
-/********************************************************************************************/
-
-void every_second()
-{
- char svalue[MESSZ];
-
- if (blockgpio0) {
- blockgpio0--;
- }
-
- for (byte i = 0; i < MAX_PULSETIMERS; i++) {
- if (pulse_timer[i] > 111) {
- pulse_timer[i]--;
- }
- }
-
- if (seriallog_timer) {
- seriallog_timer--;
- if (!seriallog_timer) {
- if (seriallog_level) {
- addLog_P(LOG_LEVEL_INFO, PSTR("APP: Serial logging disabled"));
- }
- seriallog_level = 0;
- }
- }
-
- if (syslog_timer) { // Restore syslog level
- syslog_timer--;
- if (!syslog_timer) {
- syslog_level = (sysCfg.flag.emulation) ? 0 : sysCfg.syslog_level;
- if (sysCfg.syslog_level) {
- addLog_P(LOG_LEVEL_INFO, PSTR("SYSL: Syslog logging re-enabled")); // Might trigger disable again (on purpose)
- }
- }
- }
-
-#ifdef USE_DOMOTICZ
- domoticz_mqttUpdate();
-#endif // USE_DOMOTICZ
-
- if (status_update_timer) {
- status_update_timer--;
- if (!status_update_timer) {
- for (byte i = 1; i <= Maxdevice; i++) {
- mqtt_publishPowerState(i);
- }
- }
- }
-
- if (sysCfg.tele_period) {
- tele_period++;
- if (tele_period == sysCfg.tele_period -1) {
- if (pin[GPIO_DSB] < 99) {
-#ifdef USE_DS18B20
- dsb_readTempPrep();
-#endif // USE_DS18B20
-#ifdef USE_DS18x20
- ds18x20_search(); // Check for changes in sensors number
- ds18x20_convert(); // Start Conversion, takes up to one second
-#endif // USE_DS18x20
- }
-#ifdef USE_DHT
- if (dht_flg) {
- dht_readPrep();
- }
-#endif // USE_DHT
-#ifdef USE_I2C
- if (i2c_flg) {
-#ifdef USE_SHT
- sht_detect();
-#endif // USE_SHT
-#ifdef USE_HTU
- htu_detect();
-#endif // USE_HTU
-#ifdef USE_BMP
- bmp_detect();
-#endif // USE_BMP
-#ifdef USE_BH1750
- bh1750_detect();
-#endif // USE_BH1750
- }
-#endif // USE_I2C
- }
- if (tele_period >= sysCfg.tele_period) {
- tele_period = 0;
-
- svalue[0] = '\0';
- state_mqttPresent(svalue, sizeof(svalue));
- mqtt_publish_topic_P(2, PSTR("STATE"), svalue);
-
- uint8_t djson = 0;
- svalue[0] = '\0';
- sensors_mqttPresent(svalue, sizeof(svalue), &djson);
- if (djson) {
- mqtt_publish_topic_P(2, PSTR("SENSOR"), svalue, sysCfg.flag.mqtt_sensor_retain);
- }
-
- if (hlw_flg) {
- hlw_mqttPresent();
- }
- }
- }
-
- if (hlw_flg) {
- hlw_margin_chk();
- }
-
- if ((2 == rtcTime.Minute) && uptime_flg) {
- uptime_flg = false;
- uptime++;
- snprintf_P(svalue, sizeof(svalue), PSTR("{\"Time\":\"%s\", \"Uptime\":%d}"), getDateTime().c_str(), uptime);
- mqtt_publish_topic_P(2, PSTR("UPTIME"), svalue);
- }
- if ((3 == rtcTime.Minute) && !uptime_flg) {
- uptime_flg = true;
- }
-}
-
-/*********************************************************************************************\
- * Button handler with single press only or multi-press and hold on all buttons
-\*********************************************************************************************/
-
-void button_handler()
-{
- uint8_t button = NOT_PRESSED;
- uint8_t butt_present = 0;
- uint8_t flag = 0;
- char scmnd[20];
- char log[LOGSZ];
-
- for (byte i = 0; i < Maxdevice; i++) {
- button = NOT_PRESSED;
- butt_present = 0;
-
- if (!i && ((SONOFF_DUAL == sysCfg.module) || (CH4 == sysCfg.module))) {
- butt_present = 1;
- if (ButtonCode) {
- snprintf_P(log, sizeof(log), PSTR("APP: Button code %04X"), ButtonCode);
- addLog(LOG_LEVEL_DEBUG, log);
- button = PRESSED;
- if (0xF500 == ButtonCode) { // Button hold
- holdbutton[i] = (sysCfg.param[P_HOLD_TIME] * (STATES / 10)) -1;
- }
- ButtonCode = 0;
- }
- } else {
- if ((pin[GPIO_KEY1 +i] < 99) && !blockgpio0) {
- butt_present = 1;
- button = digitalRead(pin[GPIO_KEY1 +i]);
- }
- }
-
- if (butt_present) {
- if (SONOFF_4CHPRO == sysCfg.module) {
- if (holdbutton[i]) {
- holdbutton[i]--;
- }
- flag = 0;
- if ((PRESSED == button) && (NOT_PRESSED == lastbutton[i])) {
- snprintf_P(log, sizeof(log), PSTR("APP: Button %d level 1-0"), i +1);
- addLog(LOG_LEVEL_DEBUG, log);
- holdbutton[i] = STATES;
- flag = 1;
- }
- if ((NOT_PRESSED == button) && (PRESSED == lastbutton[i])) {
- snprintf_P(log, sizeof(log), PSTR("APP: Button %d level 0-1"), i +1);
- addLog(LOG_LEVEL_DEBUG, log);
- if (!holdbutton[i]) { // Do not allow within 1 second
- flag = 1;
- }
- }
- if (flag) {
- if (!send_button_power(0, i +1, 2)) { // Execute Toggle command via MQTT if ButtonTopic is set
- do_cmnd_power(i +1, 2); // Execute Toggle command internally
- }
- }
- } else {
- if ((PRESSED == button) && (NOT_PRESSED == lastbutton[i])) {
- if (sysCfg.flag.button_single) { // Allow only single button press for immediate action
- snprintf_P(log, sizeof(log), PSTR("APP: Button %d immediate"), i +1);
- if (!send_button_power(0, i +1, 2)) { // Execute Toggle command via MQTT if ButtonTopic is set
- do_cmnd_power(i +1, 2); // Execute Toggle command internally
- }
- } else {
- multipress[i] = (multiwindow[i]) ? multipress[i] +1 : 1;
- snprintf_P(log, sizeof(log), PSTR("APP: Button %d multi-press %d"), i +1, multipress[i]);
- multiwindow[i] = STATES /2; // 0.5 second multi press window
- }
- addLog(LOG_LEVEL_DEBUG, log);
- blinks = 201;
- }
-
- if (NOT_PRESSED == button) {
- holdbutton[i] = 0;
- } else {
- holdbutton[i]++;
- if (sysCfg.flag.button_single) { // Allow only single button press for immediate action
- if (holdbutton[i] == sysCfg.param[P_HOLD_TIME] * (STATES / 10) * 4) { // Button hold for four times longer
-// sysCfg.flag.button_single = 0;
- snprintf_P(scmnd, sizeof(scmnd), PSTR("setoption13 0")); // Disable single press only
- do_cmnd(scmnd);
- }
- } else {
- if (holdbutton[i] == sysCfg.param[P_HOLD_TIME] * (STATES / 10)) { // Button hold
- multipress[i] = 0;
- if (!sysCfg.flag.button_restrict) { // No button restriction
- snprintf_P(scmnd, sizeof(scmnd), PSTR("reset 1"));
- do_cmnd(scmnd);
- } else {
- send_button_power(0, i +1, 3); // Execute Hold command via MQTT if ButtonTopic is set
- }
- }
- }
- }
-
- if (!sysCfg.flag.button_single) { // Allow multi-press
- if (multiwindow[i]) {
- multiwindow[i]--;
- } else {
- if (!restartflag && !holdbutton[i] && (multipress[i] > 0) && (multipress[i] < MAX_BUTTON_COMMANDS +3)) {
- flag = 0;
- if (multipress[i] < 3) { // Single or Double press
- if ((SONOFF_DUAL == sysCfg.module) || (CH4 == sysCfg.module)) {
- flag = 1;
- } else {
- flag = (sysCfg.flag.button_swap +1 == multipress[i]);
- multipress[i] = 1;
- }
- }
- if (flag && send_button_power(0, i + multipress[i], 2)) { // Execute Toggle command via MQTT if ButtonTopic is set
- // Success
- } else {
- if (multipress[i] < 3) { // Single or Double press
- if (WIFI_State()) { // WPSconfig, Smartconfig or Wifimanager active
- restartflag = 1;
- } else {
- do_cmnd_power(i + multipress[i], 2); // Execute Toggle command internally
- }
- } else { // 3 - 7 press
- if (!sysCfg.flag.button_restrict) {
- snprintf_P(scmnd, sizeof(scmnd), commands[multipress[i] -3]);
- do_cmnd(scmnd);
- }
- }
- }
- multipress[i] = 0;
- }
- }
- }
- }
- }
- lastbutton[i] = button;
- }
-}
-
-/*********************************************************************************************\
- * Switch handler
-\*********************************************************************************************/
-
-void switch_handler()
-{
- uint8_t button = NOT_PRESSED;
- uint8_t switchflag;
-
- for (byte i = 0; i < 4; i++) {
- if (pin[GPIO_SWT1 +i] < 99) {
-
- if (holdwallswitch[i]) {
- holdwallswitch[i]--;
- if (0 == holdwallswitch[i]) {
- send_button_power(1, i +1, 3); // Execute command via MQTT
- }
- }
-
- button = digitalRead(pin[GPIO_SWT1 +i]);
- if (button != lastwallswitch[i]) {
- switchflag = 3;
- switch (sysCfg.switchmode[i]) {
- case TOGGLE:
- switchflag = 2; // Toggle
- break;
- case FOLLOW:
- switchflag = button & 0x01; // Follow wall switch state
- break;
- case FOLLOW_INV:
- switchflag = ~button & 0x01; // Follow inverted wall switch state
- break;
- case PUSHBUTTON:
- if ((PRESSED == button) && (NOT_PRESSED == lastwallswitch[i])) {
- switchflag = 2; // Toggle with pushbutton to Gnd
- }
- break;
- case PUSHBUTTON_INV:
- if ((NOT_PRESSED == button) && (PRESSED == lastwallswitch[i])) {
- switchflag = 2; // Toggle with releasing pushbutton from Gnd
- }
- break;
- case PUSHBUTTONHOLD:
- if ((PRESSED == button) && (NOT_PRESSED == lastwallswitch[i])) {
- holdwallswitch[i] = sysCfg.param[P_HOLD_TIME] * (STATES / 10);
- }
- if ((NOT_PRESSED == button) && (PRESSED == lastwallswitch[i]) && (holdwallswitch[i])) {
- holdwallswitch[i] = 0;
- switchflag = 2; // Toggle with pushbutton to Gnd
- }
- break;
- case PUSHBUTTONHOLD_INV:
- if ((NOT_PRESSED == button) && (PRESSED == lastwallswitch[i])) {
- holdwallswitch[i] = sysCfg.param[P_HOLD_TIME] * (STATES / 10);
- }
- if ((PRESSED == button) && (NOT_PRESSED == lastwallswitch[i]) && (holdwallswitch[i])) {
- holdwallswitch[i] = 0;
- switchflag = 2; // Toggle with pushbutton to Gnd
- }
- break;
- }
-
- if (switchflag < 3) {
- if (!send_button_power(1, i +1, switchflag)) { // Execute command via MQTT
- do_cmnd_power(i +1, switchflag); // Execute command internally (if i < Maxdevice)
- }
- }
-
- lastwallswitch[i] = button;
- }
- }
- }
-}
-
-/*********************************************************************************************\
- * State loop
-\*********************************************************************************************/
-
-void stateloop()
-{
- uint8_t power_now;
- char log[LOGSZ];
- char svalue[80]; // was MESSZ
-
- timerxs = millis() + (1000 / STATES);
- state++;
-
-/*-------------------------------------------------------------------------------------------*\
- * Every second
-\*-------------------------------------------------------------------------------------------*/
-
- if (STATES == state) {
- state = 0;
- every_second();
- }
-
-/*-------------------------------------------------------------------------------------------*\
- * Every 0.1 second
-\*-------------------------------------------------------------------------------------------*/
-
- if (!(state % (STATES/10))) {
-
- if (mqtt_cmnd_publish) {
- mqtt_cmnd_publish--; // Clean up
- }
-
- if (latching_relay_pulse) {
- latching_relay_pulse--;
- if (!latching_relay_pulse) {
- setLatchingRelay(0, 0);
- }
- }
-
- for (byte i = 0; i < MAX_PULSETIMERS; i++) {
- if ((pulse_timer[i] > 0) && (pulse_timer[i] < 112)) {
- pulse_timer[i]--;
- if (!pulse_timer[i]) {
- do_cmnd_power(i +1, 0);
- }
- }
- }
-
- if (blink_mask) {
- blink_timer--;
- if (!blink_timer) {
- blink_timer = sysCfg.blinktime;
- blink_counter--;
- if (!blink_counter) {
- stop_all_power_blink();
- } else {
- blink_power ^= 1;
- power_now = (power & (0xFF ^ blink_mask)) | ((blink_power) ? blink_mask : 0);
- setRelay(power_now);
- }
- }
- }
-
- // Backlog
- if (blogdelay) {
- blogdelay--;
- }
- if ((blogptr != blogidx) && !blogdelay && !blogmutex) {
- blogmutex = 1;
- do_cmnd((char*)Backlog[blogptr].c_str());
- blogmutex = 0;
- blogptr++;
-/*
- if (blogptr >= MAX_BACKLOG) {
- blogptr = 0;
- }
-*/
- blogptr &= 0xF;
- }
- }
-
-/*-------------------------------------------------------------------------------------------*\
- * Every 0.05 second
-\*-------------------------------------------------------------------------------------------*/
-
- button_handler();
- switch_handler();
-
- if (sfl_flg) { // Sonoff BN-SZ01 or Sonoff Led
- sl_animate();
- }
-
-#ifdef USE_WS2812
- if (pin[GPIO_WS2812] < 99) {
- ws2812_animate();
- }
-#endif // USE_WS2812
-
-/*-------------------------------------------------------------------------------------------*\
- * Every 0.2 second
-\*-------------------------------------------------------------------------------------------*/
-
- if (!(state % ((STATES/10)*2))) {
- if (blinks || restartflag || otaflag) {
- if (restartflag || otaflag) {
- blinkstate = 1; // Stay lit
- } else {
- blinkstate ^= 1; // Blink
- }
- if ((!(sysCfg.ledstate &0x08)) && ((sysCfg.ledstate &0x06) || (blinks > 200) || (blinkstate))) {
- setLed(blinkstate);
- }
- if (!blinkstate) {
- blinks--;
- if (200 == blinks) {
- blinks = 0;
- }
- }
- } else {
- if (sysCfg.ledstate &0x01) {
- setLed((SONOFF_TOUCH == sysCfg.module) ? (power ^1) : power);
- }
- }
- }
-
-/*-------------------------------------------------------------------------------------------*\
- * Every second at 0.2 second interval
-\*-------------------------------------------------------------------------------------------*/
-
- switch (state) {
- case (STATES/10)*2:
- if (otaflag && (blogptr == blogidx)) {
- otaflag--;
- if (2 == otaflag) {
- otaretry = OTA_ATTEMPTS;
- ESPhttpUpdate.rebootOnUpdate(false);
- CFG_Save(1); // Free flash for OTA update
- }
- if (otaflag <= 0) {
-#ifdef USE_WEBSERVER
- if (sysCfg.webserver) {
- stopWebserver();
- }
-#endif // USE_WEBSERVER
- otaflag = 92;
- otaok = 0;
- otaretry--;
- if (otaretry) {
-// snprintf_P(log, sizeof(log), PSTR("OTA: Attempt %d"), OTA_ATTEMPTS - otaretry);
-// addLog(LOG_LEVEL_INFO, log);
- otaok = (HTTP_UPDATE_FAILED != ESPhttpUpdate.update(sysCfg.otaUrl));
- if (!otaok) {
- otaflag = 2;
- }
- }
- }
- if (90 == otaflag) { // Allow MQTT to reconnect
- otaflag = 0;
- if (otaok) {
- setFlashModeDout(); // Force DOUT for both ESP8266 and ESP8285
- snprintf_P(svalue, sizeof(svalue), PSTR("Successful. Restarting"));
- } else {
- snprintf_P(svalue, sizeof(svalue), PSTR("Failed %s"), ESPhttpUpdate.getLastErrorString().c_str());
- }
- restartflag = 2; // Restart anyway to keep memory clean webserver
- mqtt_publish_topic_P(1, PSTR("UPGRADE"), svalue);
- }
- }
- break;
- case (STATES/10)*4:
- if (rtc_midnight_now()) {
- counter_savestate();
- }
- if (savedatacounter && (blogptr == blogidx)) {
- savedatacounter--;
- if (savedatacounter <= 0) {
- if (sysCfg.flag.savestate) {
- byte mask = 0xFF;
- for (byte i = 0; i < MAX_PULSETIMERS; i++) {
- if ((sysCfg.pulsetime[i] > 0) && (sysCfg.pulsetime[i] < 30)) {
- mask &= ~(1 << i);
- }
- }
- if (!((sysCfg.power &mask) == (power &mask))) {
- sysCfg.power = power;
- }
- }
- CFG_Save(0);
- savedatacounter = sysCfg.savedata;
- }
- }
- if (restartflag && (blogptr == blogidx)) {
- if (211 == restartflag) {
- CFG_Default();
- restartflag = 2;
- }
- if (212 == restartflag) {
- CFG_Erase();
- CFG_Default();
- restartflag = 2;
- }
- if (sysCfg.flag.savestate) {
- sysCfg.power = power;
- }
- if (hlw_flg) {
- hlw_savestate();
- }
- counter_savestate();
- CFG_Save(0);
- restartflag--;
- if (restartflag <= 0) {
- addLog_P(LOG_LEVEL_INFO, PSTR("APP: Restarting"));
- ESP.restart();
- }
- }
- break;
- case (STATES/10)*6:
- WIFI_Check(wificheckflag);
- wificheckflag = WIFI_RESTART;
- break;
- case (STATES/10)*8:
- if (WL_CONNECTED == WiFi.status()) {
- if (sysCfg.flag.mqtt_enabled) {
- if (!mqttClient.connected()) {
- if (!mqttcounter) {
- mqtt_reconnect();
- } else {
- mqttcounter--;
- }
- }
- } else {
- if (!mqttcounter) {
- mqtt_reconnect();
- }
- }
- }
- break;
- }
-}
-
-/********************************************************************************************/
-
-void serial()
-{
- char log[LOGSZ];
-
- while (Serial.available()) {
- yield();
- SerialInByte = Serial.read();
-
-/*-------------------------------------------------------------------------------------------*\
- * Sonoff dual 19200 baud serial interface
-\*-------------------------------------------------------------------------------------------*/
-
- if (Hexcode) {
- Hexcode--;
- if (Hexcode) {
- ButtonCode = (ButtonCode << 8) | SerialInByte;
- SerialInByte = 0;
- } else {
- if (SerialInByte != 0xA1) {
- ButtonCode = 0; // 0xA1 - End of Sonoff dual button code
- }
- }
- }
- if (0xA0 == SerialInByte) { // 0xA0 - Start of Sonoff dual button code
- SerialInByte = 0;
- ButtonCode = 0;
- Hexcode = 3;
- }
-
-/*-------------------------------------------------------------------------------------------*\
- * Sonoff bridge 19200 baud serial interface
-\*-------------------------------------------------------------------------------------------*/
-
- if (sb_serial()) {
- SerialInByteCounter = 0;
- Serial.flush();
- return;
- }
-
-/*-------------------------------------------------------------------------------------------*/
-
- if (SerialInByte > 127) { // binary data...
- SerialInByteCounter = 0;
- Serial.flush();
- return;
- }
- if (isprint(SerialInByte)) {
- if (SerialInByteCounter < INPUT_BUFFER_SIZE) { // add char to string if it still fits
- serialInBuf[SerialInByteCounter++] = SerialInByte;
- } else {
- SerialInByteCounter = 0;
- }
- }
-
- if (SerialInByte == '\x1B') { // Sonoff SC status from ATMEGA328P
- serialInBuf[SerialInByteCounter] = 0; // serial data completed
- sc_rcvstat(serialInBuf);
- SerialInByteCounter = 0;
- Serial.flush();
- return;
- }
- else if (SerialInByte == '\n') {
- serialInBuf[SerialInByteCounter] = 0; // serial data completed
- seriallog_level = (sysCfg.seriallog_level < LOG_LEVEL_INFO) ? LOG_LEVEL_INFO : sysCfg.seriallog_level;
- snprintf_P(log, sizeof(log), PSTR("CMND: %s"), serialInBuf);
- addLog(LOG_LEVEL_INFO, log);
- do_cmnd(serialInBuf);
- SerialInByteCounter = 0;
- Serial.flush();
- return;
- }
- }
-}
-
-/********************************************************************************************/
-
-void GPIO_init()
-{
- char log[LOGSZ];
- uint8_t mpin;
- mytmplt def_module;
-
- if (!sysCfg.module || (sysCfg.module >= MAXMODULE)) {
- sysCfg.module = MODULE;
- }
-
- memcpy_P(&def_module, &modules[sysCfg.module], sizeof(def_module));
-// sysCfg.my_module.flag = def_module.flag;
- strlcpy(my_module.name, def_module.name, sizeof(my_module.name));
- for (byte i = 0; i < MAX_GPIO_PIN; i++) {
- if (sysCfg.my_module.gp.io[i] > GPIO_NONE) {
- my_module.gp.io[i] = sysCfg.my_module.gp.io[i];
- }
- if ((def_module.gp.io[i] > GPIO_NONE) && (def_module.gp.io[i] < GPIO_USER)) {
- my_module.gp.io[i] = def_module.gp.io[i];
- }
- }
-
- for (byte i = 0; i < GPIO_MAX; i++) {
- pin[i] = 99;
- }
- for (byte i = 0; i < MAX_GPIO_PIN; i++) {
- mpin = my_module.gp.io[i];
-
-// snprintf_P(log, sizeof(log), PSTR("DBG: gpio pin %d, mpin %d"), i, mpin);
-// addLog(LOG_LEVEL_DEBUG, log);
-
- if (mpin) {
- if ((mpin >= GPIO_REL1_INV) && (mpin <= GPIO_REL4_INV)) {
- rel_inverted[mpin - GPIO_REL1_INV] = 1;
- mpin -= 4;
- }
- else if ((mpin >= GPIO_LED1_INV) && (mpin <= GPIO_LED4_INV)) {
- led_inverted[mpin - GPIO_LED1_INV] = 1;
- mpin -= 4;
- }
-#ifdef USE_DHT
- else if ((mpin >= GPIO_DHT11) && (mpin <= GPIO_DHT22)) {
- if (dht_setup(i, mpin)) {
- dht_flg = 1;
- mpin = GPIO_DHT11;
- } else {
- mpin = 0;
- }
- }
-#endif // USE_DHT
- }
- if (mpin) {
- pin[mpin] = i;
- }
- }
-
- if (2 == pin[GPIO_TXD]) {
- Serial.set_tx(2);
- }
-
- analogWriteRange(PWM_RANGE); // Default is 1023 (Arduino.h)
- analogWriteFreq(PWM_FREQ); // Default is 1000 (core_esp8266_wiring_pwm.c)
-
- Maxdevice = 1;
- if (SONOFF_BRIDGE == sysCfg.module) {
- Baudrate = 19200;
- }
- if (SONOFF_DUAL == sysCfg.module) {
- Maxdevice = 2;
- Baudrate = 19200;
- }
- else if (CH4 == sysCfg.module) {
- Maxdevice = 4;
- Baudrate = 19200;
- }
- else if (SONOFF_SC == sysCfg.module) {
- Maxdevice = 0;
- Baudrate = 19200;
- }
- else if (SONOFF_BN == sysCfg.module) {
- sfl_flg = 1;
- }
- else if (SONOFF_LED == sysCfg.module) {
- sfl_flg = 2;
- }
- else {
- Maxdevice = 0;
- for (byte i = 0; i < 4; i++) {
- if (pin[GPIO_REL1 +i] < 99) {
- pinMode(pin[GPIO_REL1 +i], OUTPUT);
- Maxdevice++;
- }
-// if (pin[GPIO_KEY1 +i] < 99) {
-// pinMode(pin[GPIO_KEY1 +i], INPUT_PULLUP);
-// }
- }
- }
- for (byte i = 0; i < 4; i++) {
- if (pin[GPIO_KEY1 +i] < 99) {
- pinMode(pin[GPIO_KEY1 +i], INPUT_PULLUP);
- }
- if (pin[GPIO_LED1 +i] < 99) {
- pinMode(pin[GPIO_LED1 +i], OUTPUT);
- digitalWrite(pin[GPIO_LED1 +i], led_inverted[i]);
- }
- if (pin[GPIO_SWT1 +i] < 99) {
- swt_flg = 1;
- pinMode(pin[GPIO_SWT1 +i], INPUT_PULLUP);
- lastwallswitch[i] = digitalRead(pin[GPIO_SWT1 +i]); // set global now so doesn't change the saved power state on first switch check
- }
- }
-
- if (sfl_flg) { // Sonoff Led or BN-SZ01
- pwm_idxoffset = sfl_flg; // 1 for BN-SZ01, 2 for Sonoff Led
- pin[GPIO_WS2812] = 99; // I do not allow both Sonoff Led AND WS2812 led
- if (!my_module.gp.io[4]) {
- pinMode(4, OUTPUT); // Stop floating outputs
- digitalWrite(4, LOW);
- }
- if (!my_module.gp.io[5]) {
- pinMode(5, OUTPUT); // Stop floating outputs
- digitalWrite(5, LOW);
- }
- if (!my_module.gp.io[14]) {
- pinMode(14, OUTPUT); // Stop floating outputs
- digitalWrite(14, LOW);
- }
- sl_init();
- }
- for (byte i = pwm_idxoffset; i < 5; i++) {
- if (pin[GPIO_PWM1 +i] < 99) {
- pwm_flg = 1;
- pinMode(pin[GPIO_PWM1 +i], OUTPUT);
- analogWrite(pin[GPIO_PWM1 +i], sysCfg.pwmvalue[i]);
- }
- }
-
- if (EXS_RELAY == sysCfg.module) {
- setLatchingRelay(0,2);
- setLatchingRelay(1,2);
- }
- setLed(sysCfg.ledstate &8);
-
-#ifdef USE_WS2812
- if (pin[GPIO_WS2812] < 99) {
- Maxdevice++;
- ws2812_init(Maxdevice);
- }
-#endif // USE_WS2812
-
-#ifdef USE_IR_REMOTE
- if (pin[GPIO_IRSEND] < 99) {
- ir_send_init();
- }
-#endif // USE_IR_REMOTE
-
- counter_init();
-
- hlw_flg = ((pin[GPIO_HLW_SEL] < 99) && (pin[GPIO_HLW_CF1] < 99) && (pin[GPIO_HLW_CF] < 99));
- if (hlw_flg) {
- hlw_init();
- }
-
-#ifdef USE_DHT
- if (dht_flg) {
- dht_init();
- }
-#endif // USE_DHT
-
-#ifdef USE_DS18x20
- if (pin[GPIO_DSB] < 99) {
- ds18x20_init();
- }
-#endif // USE_DS18x20
-
-#ifdef USE_I2C
- i2c_flg = ((pin[GPIO_I2C_SCL] < 99) && (pin[GPIO_I2C_SDA] < 99));
- if (i2c_flg) {
- Wire.begin(pin[GPIO_I2C_SDA], pin[GPIO_I2C_SCL]);
- }
-#endif // USE_I2C
-}
-
-extern "C" {
-extern struct rst_info resetInfo;
-}
-
-void setup()
-{
- char log[LOGSZ];
- byte idx;
-
- Serial.begin(Baudrate);
- delay(10);
- Serial.println();
- seriallog_level = LOG_LEVEL_INFO; // Allow specific serial messages until config loaded
-
- snprintf_P(Version, sizeof(Version), PSTR("%d.%d.%d"), VERSION >> 24 & 0xff, VERSION >> 16 & 0xff, VERSION >> 8 & 0xff);
- if (VERSION & 0x1f) {
- idx = strlen(Version);
- Version[idx] = 96 + (VERSION & 0x1f);
- Version[idx +1] = 0;
- }
- CFG_Load();
- CFG_Delta();
-
- osw_init();
-
- sysCfg.bootcount++;
- snprintf_P(log, sizeof(log), PSTR("APP: Bootcount %d"), sysCfg.bootcount);
- addLog(LOG_LEVEL_DEBUG, log);
- stop_flash_rotate = sysCfg.flag.stop_flash_rotate;
- savedatacounter = sysCfg.savedata;
- seriallog_timer = SERIALLOG_TIMER;
- seriallog_level = sysCfg.seriallog_level;
-#ifndef USE_EMULATION
- sysCfg.flag.emulation = 0;
-#endif // USE_EMULATION
- syslog_level = (sysCfg.flag.emulation) ? 0 : sysCfg.syslog_level;
- sleep = sysCfg.sleep;
-
- GPIO_init();
-
- if (Serial.baudRate() != Baudrate) {
- if (seriallog_level) {
- snprintf_P(log, sizeof(log), PSTR("APP: Set baudrate to %d"), Baudrate);
- addLog(LOG_LEVEL_INFO, log);
- }
- delay(100);
- Serial.flush();
- Serial.begin(Baudrate);
- delay(10);
- Serial.println();
- }
-
- if (strstr(sysCfg.hostname, "%")) {
- strlcpy(sysCfg.hostname, WIFI_HOSTNAME, sizeof(sysCfg.hostname));
- snprintf_P(Hostname, sizeof(Hostname)-1, sysCfg.hostname, sysCfg.mqtt_topic, ESP.getChipId() & 0x1FFF);
- } else {
- snprintf_P(Hostname, sizeof(Hostname)-1, sysCfg.hostname);
- }
- WIFI_Connect();
-
- getClient(MQTTClient, sysCfg.mqtt_client, sizeof(MQTTClient));
-
- if (MOTOR == sysCfg.module) {
- sysCfg.poweronstate = 1; // Needs always on else in limbo!
- }
- if (4 == sysCfg.poweronstate) { // Allways on
- setRelay(power);
- } else {
- if ((resetInfo.reason == REASON_DEFAULT_RST) || (resetInfo.reason == REASON_EXT_SYS_RST)) {
- switch (sysCfg.poweronstate) {
- case 0: // All off
- power = 0;
- setRelay(power);
- break;
- case 1: // All on
- power = (1 << Maxdevice) -1;
- setRelay(power);
- break;
- case 2: // All saved state toggle
- power = sysCfg.power & ((1 << Maxdevice) -1) ^ 0xFF;
- if (sysCfg.flag.savestate) {
- setRelay(power);
- }
- break;
- case 3: // All saved state
- power = sysCfg.power & ((1 << Maxdevice) -1);
- if (sysCfg.flag.savestate) {
- setRelay(power);
- }
- break;
- }
- } else {
- power = sysCfg.power & ((1 << Maxdevice) -1);
- if (sysCfg.flag.savestate) {
- setRelay(power);
- }
- }
- }
- blink_powersave = power;
-
- if (SONOFF_SC == sysCfg.module) {
- sc_init();
- }
-
- rtc_init();
-
- snprintf_P(log, sizeof(log), PSTR("APP: Project %s %s (Topic %s, Fallback %s, GroupTopic %s) Version %s"),
- PROJECT, sysCfg.friendlyname[0], sysCfg.mqtt_topic, MQTTClient, sysCfg.mqtt_grptopic, Version);
- addLog(LOG_LEVEL_INFO, log);
-}
-
-void loop()
-{
- osw_loop();
-
-#ifdef USE_WEBSERVER
- pollDnsWeb();
-#endif // USE_WEBSERVER
-
-#ifdef USE_EMULATION
- if (sysCfg.flag.emulation) {
- pollUDP();
- }
-#endif // USE_EMULATION
-
- if (millis() >= timerxs) {
- stateloop();
- }
- if (sysCfg.flag.mqtt_enabled) {
- mqttClient.loop();
- }
- if (Serial.available()){
- serial();
- }
-
-// yield(); // yield == delay(0), delay contains yield, auto yield in loop
- delay(sleep); // https://github.com/esp8266/Arduino/issues/2021
-}