2017-01-28 13:41:01 +00:00
/*
2017-05-13 12:02:10 +01:00
sonoff . ino - Sonoff - Tasmota firmware for iTead Sonoff , Wemos and NodeMCU hardware
2017-12-22 13:55:24 +00:00
Copyright ( C ) 2018 Theo Arends
2017-05-13 12:02:10 +01:00
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 < http : //www.gnu.org/licenses/>.
*/
2017-05-17 21:49:22 +01:00
/*====================================================
2017-05-13 12:02:10 +01:00
Prerequisites :
- Change libraries / PubSubClient / src / PubSubClient . h
2018-01-18 15:19:28 +00:00
# define MQTT_MAX_PACKET_SIZE 1000
2017-07-15 14:07:30 +01:00
- Select IDE Tools - Flash Mode : " DOUT "
- Select IDE Tools - Flash Size : " 1M (no SPIFFS) "
2017-05-17 21:49:22 +01:00
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
2017-01-28 13:41:01 +00:00
2018-01-27 16:52:48 +00:00
# define VERSION 0x050B0107 // 5.11.1g
2017-01-28 13:41:01 +00:00
2017-10-18 17:22:34 +01:00
// Location specific includes
2018-01-26 14:21:57 +00:00
# include <core_version.h> // Arduino_Esp8266 version information (ARDUINO_ESP8266_RELEASE and ARDUINO_ESP8266_RELEASE_2_3_0)
2018-01-24 16:31:20 +00:00
# include "sonoff.h" // Enumeration used in user_config.h
2017-10-18 17:22:34 +01:00
# include "user_config.h" // Fixed user configurable options
# include "user_config_override.h" // Configuration overrides for user_config.h
# include "i18n.h" // Language support configured by user_config.h
# include "sonoff_template.h" // Hardware configuration
# include "sonoff_post.h" // Configuration overrides for all previous includes
2017-03-03 11:35:23 +00:00
2017-10-18 17:22:34 +01:00
// Libraries
2017-03-21 15:17:28 +00:00
# include <PubSubClient.h> // MQTT
2018-01-18 15:19:28 +00:00
2017-09-13 13:19:34 +01:00
// Max message size calculated by PubSubClient is (MQTT_MAX_PACKET_SIZE < 5 + 2 + strlen(topic) + plength)
2018-01-18 15:19:28 +00:00
# if (MQTT_MAX_PACKET_SIZE -TOPSZ -7) < MIN_MESSZ // If the max message size is too small, throw an error at compile time. See PubSubClient.cpp line 359
# error "MQTT_MAX_PACKET_SIZE is too small in libraries / PubSubClient / src / PubSubClient.h, increase it to at least 1000"
2017-03-03 11:35:23 +00:00
# endif
2018-01-18 15:19:28 +00:00
2017-12-16 14:51:45 +00:00
# include <Ticker.h> // RTC, Energy, OSWatch
2017-01-28 13:41:01 +00:00
# include <ESP8266WiFi.h> // MQTT, Ota, WifiManager
# include <ESP8266HTTPClient.h> // MQTT, Ota
# include <ESP8266httpUpdate.h> // Ota
2017-06-04 16:40:27 +01:00
# include <StreamString.h> // Webserver, Updater
2017-02-17 16:18:41 +00:00
# include <ArduinoJson.h> // WemoHue, IRremote, Domoticz
2017-01-28 13:41:01 +00:00
# ifdef USE_WEBSERVER
# include <ESP8266WebServer.h> // WifiManager, Webserver
# include <DNSServer.h> // WifiManager
# endif // USE_WEBSERVER
# ifdef USE_DISCOVERY
# include <ESP8266mDNS.h> // MQTT, Webserver
# endif // USE_DISCOVERY
# ifdef USE_I2C
# include <Wire.h> // I2C support library
# endif // USE_I2C
2017-07-15 14:07:30 +01:00
# ifdef USE_SPI
2017-05-10 13:19:36 +01:00
# include <SPI.h> // SPI support, TFT
2017-04-29 13:40:53 +01:00
# endif // USE_SPI
2017-10-18 17:22:34 +01:00
// Structs
2017-02-19 16:49:17 +00:00
# include "settings.h"
2017-01-28 13:41:01 +00:00
2017-10-29 17:18:46 +00:00
enum TasmotaCommands {
2018-01-20 11:12:39 +00:00
CMND_BACKLOG , CMND_DELAY , CMND_POWER , CMND_STATUS , CMND_STATE , CMND_POWERONSTATE , CMND_PULSETIME ,
2018-01-24 16:31:20 +00:00
CMND_BLINKTIME , CMND_BLINKCOUNT , CMND_SENSOR , CMND_SAVEDATA , CMND_SETOPTION , CMND_TEMPERATURE_RESOLUTION , CMND_HUMIDITY_RESOLUTION ,
2017-11-11 11:33:30 +00:00
CMND_PRESSURE_RESOLUTION , CMND_POWER_RESOLUTION , CMND_VOLTAGE_RESOLUTION , CMND_CURRENT_RESOLUTION , CMND_ENERGY_RESOLUTION , CMND_MODULE , CMND_MODULES ,
2017-10-29 17:18:46 +00:00
CMND_GPIO , CMND_GPIOS , CMND_PWM , CMND_PWMFREQUENCY , CMND_PWMRANGE , CMND_COUNTER , CMND_COUNTERTYPE ,
CMND_COUNTERDEBOUNCE , CMND_SLEEP , CMND_UPGRADE , CMND_UPLOAD , CMND_OTAURL , CMND_SERIALLOG , CMND_SYSLOG ,
CMND_LOGHOST , CMND_LOGPORT , CMND_IPADDRESS , CMND_NTPSERVER , CMND_AP , CMND_SSID , CMND_PASSWORD , CMND_HOSTNAME ,
CMND_WIFICONFIG , CMND_FRIENDLYNAME , CMND_SWITCHMODE , CMND_WEBSERVER , CMND_WEBPASSWORD , CMND_WEBLOG , CMND_EMULATION ,
CMND_TELEPERIOD , CMND_RESTART , CMND_RESET , CMND_TIMEZONE , CMND_ALTITUDE , CMND_LEDPOWER , CMND_LEDSTATE ,
2018-01-24 16:31:20 +00:00
CMND_CFGDUMP , CMND_I2CSCAN , CMND_EXCEPTION } ;
2017-10-29 17:18:46 +00:00
const char kTasmotaCommands [ ] PROGMEM =
2018-01-20 11:12:39 +00:00
D_CMND_BACKLOG " | " D_CMND_DELAY " | " D_CMND_POWER " | " D_CMND_STATUS " | " D_CMND_STATE " | " D_CMND_POWERONSTATE " | " D_CMND_PULSETIME " | "
2018-01-24 16:31:20 +00:00
D_CMND_BLINKTIME " | " D_CMND_BLINKCOUNT " | " D_CMND_SENSOR " | " D_CMND_SAVEDATA " | " D_CMND_SETOPTION " | " D_CMND_TEMPERATURE_RESOLUTION " | " D_CMND_HUMIDITY_RESOLUTION " | "
2017-11-11 11:33:30 +00:00
D_CMND_PRESSURE_RESOLUTION " | " D_CMND_POWER_RESOLUTION " | " D_CMND_VOLTAGE_RESOLUTION " | " D_CMND_CURRENT_RESOLUTION " | " D_CMND_ENERGY_RESOLUTION " | " D_CMND_MODULE " | " D_CMND_MODULES " | "
2017-10-29 17:18:46 +00:00
D_CMND_GPIO " | " D_CMND_GPIOS " | " D_CMND_PWM " | " D_CMND_PWMFREQUENCY " | " D_CMND_PWMRANGE " | " D_CMND_COUNTER " | " D_CMND_COUNTERTYPE " | "
D_CMND_COUNTERDEBOUNCE " | " D_CMND_SLEEP " | " D_CMND_UPGRADE " | " D_CMND_UPLOAD " | " D_CMND_OTAURL " | " D_CMND_SERIALLOG " | " D_CMND_SYSLOG " | "
D_CMND_LOGHOST " | " D_CMND_LOGPORT " | " D_CMND_IPADDRESS " | " D_CMND_NTPSERVER " | " D_CMND_AP " | " D_CMND_SSID " | " D_CMND_PASSWORD " | " D_CMND_HOSTNAME " | "
D_CMND_WIFICONFIG " | " D_CMND_FRIENDLYNAME " | " D_CMND_SWITCHMODE " | " D_CMND_WEBSERVER " | " D_CMND_WEBPASSWORD " | " D_CMND_WEBLOG " | " D_CMND_EMULATION " | "
D_CMND_TELEPERIOD " | " D_CMND_RESTART " | " D_CMND_RESET " | " D_CMND_TIMEZONE " | " D_CMND_ALTITUDE " | " D_CMND_LEDPOWER " | " D_CMND_LEDSTATE " | "
2018-01-24 16:31:20 +00:00
D_CMND_CFGDUMP " | " D_CMND_I2CSCAN
2017-10-29 17:18:46 +00:00
# ifdef DEBUG_THEO
" | " D_CMND_EXCEPTION
# endif
;
enum MqttCommands {
CMND_MQTTHOST , CMND_MQTTPORT , CMND_MQTTRETRY , CMND_STATETEXT , CMND_MQTTFINGERPRINT , CMND_MQTTCLIENT ,
CMND_MQTTUSER , CMND_MQTTPASSWORD , CMND_FULLTOPIC , CMND_PREFIX , CMND_GROUPTOPIC , CMND_TOPIC ,
CMND_BUTTONTOPIC , CMND_SWITCHTOPIC , CMND_BUTTONRETAIN , CMND_SWITCHRETAIN , CMND_POWERRETAIN , CMND_SENSORRETAIN } ;
const char kMqttCommands [ ] PROGMEM =
D_CMND_MQTTHOST " | " D_CMND_MQTTPORT " | " D_CMND_MQTTRETRY " | " D_CMND_STATETEXT " | " D_CMND_MQTTFINGERPRINT " | " D_CMND_MQTTCLIENT " | "
D_CMND_MQTTUSER " | " D_CMND_MQTTPASSWORD " | " D_CMND_FULLTOPIC " | " D_CMND_PREFIX " | " D_CMND_GROUPTOPIC " | " D_CMND_TOPIC " | "
D_CMND_BUTTONTOPIC " | " D_CMND_SWITCHTOPIC " | " D_CMND_BUTTONRETAIN " | " D_CMND_SWITCHRETAIN " | " D_CMND_POWERRETAIN " | " D_CMND_SENSORRETAIN ;
const char kOptionOff [ ] PROGMEM = " OFF| " D_OFF " | " D_FALSE " | " D_STOP " | " D_CELSIUS ;
const char kOptionOn [ ] PROGMEM = " ON| " D_ON " | " D_TRUE " | " D_START " | " D_FAHRENHEIT " | " D_USER ;
const char kOptionToggle [ ] PROGMEM = " TOGGLE| " D_TOGGLE " | " D_ADMIN ;
const char kOptionBlink [ ] PROGMEM = " BLINK| " D_BLINK ;
const char kOptionBlinkOff [ ] PROGMEM = " BLINKOFF| " D_BLINKOFF ;
2017-10-18 17:22:34 +01:00
// Global variables
int baudrate = APP_BAUDRATE ; // Serial interface baud rate
byte serial_in_byte ; // Received byte
int serial_in_byte_counter = 0 ; // Index in receive buffer
byte dual_hex_code = 0 ; // Sonoff dual input flag
uint16_t dual_button_code = 0 ; // Sonoff dual received code
int16_t save_data_counter ; // Counter and flag for config save to Flash
uint8_t mqtt_retry_counter = 0 ; // MQTT connection retry counter
uint8_t fallback_topic_flag = 0 ; // Use Topic or FallbackTopic
unsigned long state_loop_timer = 0 ; // State loop timer
int state = 0 ; // State per second flag
int mqtt_connection_flag = 2 ; // MQTT connection messages flag
int ota_state_flag = 0 ; // OTA state flag
int ota_result = 0 ; // OTA result
byte ota_retry_counter = OTA_ATTEMPTS ; // OTA retry counter
2018-01-10 13:10:25 +00:00
char * ota_url ; // OTA url string
2017-10-18 17:22:34 +01:00
int restart_flag = 0 ; // Sonoff restart flag
int wifi_state_flag = WIFI_RESTART ; // Wifi state flag
int uptime = 0 ; // Current uptime in hours
boolean latest_uptime_flag = true ; // Signal latest uptime
int tele_period = 0 ; // Tele period timer
byte web_log_index = 0 ; // Index in Web log buffer
byte reset_web_log_flag = 0 ; // Reset web console log
byte devices_present = 0 ; // Max number of devices supported
int status_update_timer = 0 ; // Refresh initial status
2017-03-12 17:36:33 +00:00
uint16_t pulse_timer [ MAX_PULSETIMERS ] = { 0 } ; // Power off timer
2017-10-18 17:22:34 +01:00
uint16_t blink_timer = 0 ; // Power cycle timer
uint16_t blink_counter = 0 ; // Number of blink cycles
power_t blink_power ; // Blink power state
power_t blink_mask = 0 ; // Blink relay active mask
power_t blink_powersave ; // Blink start power save state
uint16_t mqtt_cmnd_publish = 0 ; // ignore flag for publish command
power_t latching_power = 0 ; // Power state at latching start
uint8_t latching_relay_pulse = 0 ; // Latching relay pulse timer
uint8_t backlog_index = 0 ; // Command backlog index
uint8_t backlog_pointer = 0 ; // Command backlog pointer
uint8_t backlog_mutex = 0 ; // Command backlog pending
uint16_t backlog_delay = 0 ; // Command backlog delay
uint8_t interlock_mutex = 0 ; // Interlock power command pending
2017-01-28 13:41:01 +00:00
# ifdef USE_MQTT_TLS
2017-10-18 17:22:34 +01:00
WiFiClientSecure EspClient ; // Wifi Secure Client
2017-01-28 13:41:01 +00:00
# else
2017-10-18 17:22:34 +01:00
WiFiClient EspClient ; // Wifi Client
2017-01-28 13:41:01 +00:00
# endif
2017-10-18 17:22:34 +01:00
PubSubClient MqttClient ( EspClient ) ; // MQTT Client
WiFiUDP PortUdp ; // UDP Syslog and Alexa
power_t power = 0 ; // Current copy of Settings.power
byte syslog_level ; // Current copy of Settings.syslog_level
uint16_t syslog_timer = 0 ; // Timer to re-enable syslog_level
byte seriallog_level ; // Current copy of Settings.seriallog_level
uint16_t seriallog_timer = 0 ; // Timer to disable Seriallog
uint8_t sleep ; // Current copy of Settings.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 blockgpio0 = 4 ; // Block GPIO0 for 4 seconds after poweron to workaround Wemos D1 RTS circuit
uint8_t lastbutton [ MAX_KEYS ] = { NOT_PRESSED , NOT_PRESSED , NOT_PRESSED , NOT_PRESSED } ; // Last button states
2017-10-12 10:29:40 +01:00
uint8_t holdbutton [ MAX_KEYS ] = { 0 } ; // Timer for button hold
uint8_t multiwindow [ MAX_KEYS ] = { 0 } ; // Max time between button presses to record press count
uint8_t multipress [ MAX_KEYS ] = { 0 } ; // Number of button presses within multiwindow
2017-10-18 17:22:34 +01:00
uint8_t lastwallswitch [ MAX_SWITCHES ] ; // Last wall switch states
2017-10-10 14:40:02 +01:00
uint8_t holdwallswitch [ MAX_SWITCHES ] = { 0 } ; // Timer for wallswitch push button hold
2017-01-28 13:41:01 +00:00
2017-10-18 17:22:34 +01:00
mytmplt my_module ; // Active copy of Module name and GPIOs
uint8_t pin [ GPIO_MAX ] ; // Possible pin configurations
power_t rel_inverted = 0 ; // Relay inverted flag (1 = (0 = On, 1 = Off))
uint8_t led_inverted = 0 ; // LED inverted flag (1 = (0 = On, 1 = Off))
uint8_t pwm_inverted = 0 ; // PWM inverted flag (1 = inverted)
uint8_t dht_flg = 0 ; // DHT configured
2017-12-17 15:08:39 +00:00
uint8_t energy_flg = 1 ; // Energy monitor configured
2017-10-18 17:22:34 +01:00
uint8_t i2c_flg = 0 ; // I2C configured
uint8_t spi_flg = 0 ; // SPI configured
uint8_t light_type = 0 ; // Light types
boolean mdns_begun = false ;
2018-01-10 13:10:25 +00:00
char my_version [ 33 ] ; // Composed version string
2017-10-18 17:22:34 +01:00
char my_hostname [ 33 ] ; // Composed Wifi hostname
char mqtt_client [ 33 ] ; // Composed MQTT Clientname
char serial_in_buffer [ INPUT_BUFFER_SIZE + 2 ] ; // Receive buffer
2018-01-18 15:19:28 +00:00
char mqtt_data [ MESSZ ] ; // MQTT publish buffer and web page ajax buffer
char log_data [ LOGSZ ] ; // Logging
2017-10-18 17:22:34 +01:00
String web_log [ MAX_LOG_LINES ] ; // Web log buffer
String backlog [ MAX_BACKLOG ] ; // Command backlog
2017-09-13 13:19:34 +01:00
2017-01-28 13:41:01 +00:00
/********************************************************************************************/
2017-10-18 17:22:34 +01:00
void GetMqttClient ( char * output , const char * input , byte size )
2017-01-28 13:41:01 +00:00
{
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 ( ) ) ;
}
}
}
2017-04-25 17:24:42 +01:00
if ( ! digits ) {
strlcpy ( output , input , size ) ;
}
2017-01-28 13:41:01 +00:00
}
2017-10-18 17:22:34 +01:00
void GetTopic_P ( char * stopic , byte prefix , char * topic , const char * subtopic )
2017-05-10 13:19:36 +01:00
{
2018-01-18 15:19:28 +00:00
/* prefix 0 = Cmnd
prefix 1 = Stat
prefix 2 = Tele
*/
2017-05-10 13:19:36 +01:00
char romram [ CMDSZ ] ;
2017-06-30 16:54:19 +01:00
String fulltopic ;
2017-09-02 13:37:02 +01:00
2017-05-10 13:19:36 +01:00
snprintf_P ( romram , sizeof ( romram ) , subtopic ) ;
2017-10-18 17:22:34 +01:00
if ( fallback_topic_flag ) {
fulltopic = FPSTR ( kPrefixes [ prefix ] ) ;
2017-06-30 16:54:19 +01:00
fulltopic + = F ( " / " ) ;
2017-10-18 17:22:34 +01:00
fulltopic + = mqtt_client ;
2017-06-30 16:54:19 +01:00
} else {
2017-10-18 17:22:34 +01:00
fulltopic = Settings . mqtt_fulltopic ;
2017-06-30 16:54:19 +01:00
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 + + ) {
2017-10-18 17:22:34 +01:00
if ( ' \0 ' = = Settings . mqtt_prefix [ i ] [ 0 ] ) {
snprintf_P ( Settings . mqtt_prefix [ i ] , sizeof ( Settings . mqtt_prefix [ i ] ) , kPrefixes [ i ] ) ;
2017-06-30 16:54:19 +01:00
}
2017-05-10 13:19:36 +01:00
}
2017-10-18 17:22:34 +01:00
fulltopic . replace ( F ( MQTT_TOKEN_PREFIX ) , Settings . mqtt_prefix [ prefix ] ) ;
2017-06-30 16:54:19 +01:00
fulltopic . replace ( F ( MQTT_TOKEN_TOPIC ) , topic ) ;
2017-05-10 13:19:36 +01:00
}
fulltopic . replace ( F ( " # " ) , " " ) ;
fulltopic . replace ( F ( " // " ) , " / " ) ;
if ( ! fulltopic . endsWith ( " / " ) ) {
fulltopic + = " / " ;
}
snprintf_P ( stopic , TOPSZ , PSTR ( " %s%s " ) , fulltopic . c_str ( ) , romram ) ;
}
2017-10-18 17:22:34 +01:00
char * GetStateText ( byte state )
2017-05-10 13:19:36 +01:00
{
2017-06-06 22:23:23 +01:00
if ( state > 3 ) {
2017-05-10 13:19:36 +01:00
state = 1 ;
}
2017-10-18 17:22:34 +01:00
return Settings . state_text [ state ] ;
2017-05-10 13:19:36 +01:00
}
/********************************************************************************************/
2017-10-18 17:22:34 +01:00
void SetLatchingRelay ( power_t power , uint8_t state )
2017-02-13 16:25:46 +00:00
{
power & = 1 ;
2017-04-25 17:24:42 +01:00
if ( 2 = = state ) { // Reset relay
2017-02-13 16:25:46 +00:00
state = 0 ;
2017-02-14 13:27:08 +00:00
latching_power = power ;
latching_relay_pulse = 0 ;
2017-02-13 16:25:46 +00:00
}
2017-02-14 13:27:08 +00:00
else if ( state & & ! latching_relay_pulse ) { // Set port power to On
2017-02-13 16:25:46 +00:00
latching_power = power ;
2017-10-18 17:22:34 +01:00
latching_relay_pulse = 2 ; // max 200mS (initiated by stateloop())
2017-02-13 16:25:46 +00:00
}
2017-04-25 17:24:42 +01:00
if ( pin [ GPIO_REL1 + latching_power ] < 99 ) {
2017-10-10 14:40:02 +01:00
digitalWrite ( pin [ GPIO_REL1 + latching_power ] , bitRead ( rel_inverted , latching_power ) ? ! state : state ) ;
2017-04-25 17:24:42 +01:00
}
2017-02-13 16:25:46 +00:00
}
2017-10-18 17:22:34 +01:00
void SetDevicePower ( power_t rpower )
2017-01-28 13:41:01 +00:00
{
2017-02-13 16:25:46 +00:00
uint8_t state ;
2017-05-05 16:57:05 +01:00
2018-01-24 16:31:20 +00:00
if ( POWER_ALL_ALWAYS_ON = = Settings . poweronstate ) { // All on and stay on
2017-10-18 17:22:34 +01:00
power = ( 1 < < devices_present ) - 1 ;
2017-05-05 16:57:05 +01:00
rpower = power ;
}
2017-10-18 17:22:34 +01:00
if ( Settings . flag . interlock ) { // Allow only one or no relay set
2017-10-10 14:40:02 +01:00
power_t mask = 1 ;
2017-08-18 11:55:08 +01:00
uint8_t count = 0 ;
2017-10-18 17:22:34 +01:00
for ( byte i = 0 ; i < devices_present ; i + + ) {
2017-08-18 11:55:08 +01:00
if ( rpower & mask ) {
count + + ;
}
mask < < = 1 ;
}
if ( count > 1 ) {
power = 0 ;
rpower = 0 ;
}
}
2018-01-05 11:26:19 +00:00
2018-01-20 11:12:39 +00:00
XdrvSetPower ( rpower ) ;
2018-01-05 11:26:19 +00:00
2017-10-18 17:22:34 +01:00
if ( ( SONOFF_DUAL = = Settings . module ) | | ( CH4 = = Settings . module ) ) {
2017-01-28 13:41:01 +00:00
Serial . write ( 0xA0 ) ;
Serial . write ( 0x04 ) ;
2017-10-10 14:40:02 +01:00
Serial . write ( rpower & 0xFF ) ;
2017-01-28 13:41:01 +00:00
Serial . write ( 0xA1 ) ;
Serial . write ( ' \n ' ) ;
Serial . flush ( ) ;
2017-02-13 16:25:46 +00:00
}
2017-10-18 17:22:34 +01:00
else if ( EXS_RELAY = = Settings . module ) {
SetLatchingRelay ( rpower , 1 ) ;
2017-02-13 16:25:46 +00:00
}
else {
2017-10-18 17:22:34 +01:00
for ( byte i = 0 ; i < devices_present ; i + + ) {
2017-10-14 10:26:49 +01:00
state = rpower & 1 ;
if ( ( i < MAX_RELAYS ) & & ( pin [ GPIO_REL1 + i ] < 99 ) ) {
digitalWrite ( pin [ GPIO_REL1 + i ] , bitRead ( rel_inverted , i ) ? ! state : state ) ;
}
rpower > > = 1 ;
}
2017-01-28 13:41:01 +00:00
}
}
2017-10-18 17:22:34 +01:00
void SetLedPower ( uint8_t state )
2017-01-28 13:41:01 +00:00
{
2017-04-25 17:24:42 +01:00
if ( state ) {
state = 1 ;
}
2017-10-10 14:40:02 +01:00
digitalWrite ( pin [ GPIO_LED1 ] , ( bitRead ( led_inverted , 0 ) ) ? ! state : state ) ;
2017-01-28 13:41:01 +00:00
}
2017-02-18 17:08:55 +00:00
/********************************************************************************************/
2017-10-18 17:22:34 +01:00
void MqttSubscribe ( char * topic )
2017-09-26 14:10:58 +01:00
{
snprintf_P ( log_data , sizeof ( log_data ) , PSTR ( D_LOG_MQTT D_SUBSCRIBE_TO " %s " ) , topic ) ;
2017-10-18 17:22:34 +01:00
AddLog ( LOG_LEVEL_DEBUG ) ;
MqttClient . subscribe ( topic ) ;
MqttClient . loop ( ) ; // Solve LmacRxBlk:1 messages
2017-09-26 14:10:58 +01:00
}
2017-10-18 17:22:34 +01:00
void MqttPublishDirect ( const char * topic , boolean retained )
2017-01-28 13:41:01 +00:00
{
2018-01-18 15:19:28 +00:00
char sretained [ CMDSZ ] ;
char slog_type [ 10 ] ;
sretained [ 0 ] = ' \0 ' ;
snprintf_P ( slog_type , sizeof ( slog_type ) , PSTR ( D_LOG_RESULT ) ) ;
2017-10-18 17:22:34 +01:00
if ( Settings . flag . mqtt_enabled ) {
if ( MqttClient . publish ( topic , mqtt_data , retained ) ) {
2018-01-18 15:19:28 +00:00
snprintf_P ( slog_type , sizeof ( slog_type ) , PSTR ( D_LOG_MQTT ) ) ;
if ( retained ) {
snprintf_P ( sretained , sizeof ( sretained ) , PSTR ( " ( " D_RETAINED " ) " ) ) ;
}
2017-01-28 13:41:01 +00:00
}
}
2018-01-18 15:19:28 +00:00
snprintf_P ( log_data , sizeof ( log_data ) , PSTR ( " %s%s = %s " ) , slog_type , ( Settings . flag . mqtt_enabled ) ? topic : strrchr ( topic , ' / ' ) + 1 , mqtt_data ) ;
if ( strlen ( log_data ) > = ( sizeof ( log_data ) - strlen ( sretained ) - 1 ) ) {
log_data [ sizeof ( log_data ) - strlen ( sretained ) - 5 ] = ' \0 ' ;
snprintf_P ( log_data , sizeof ( log_data ) , PSTR ( " %s ... " ) , log_data ) ;
}
snprintf_P ( log_data , sizeof ( log_data ) , PSTR ( " %s%s " ) , log_data , sretained ) ;
2017-10-18 17:22:34 +01:00
AddLog ( LOG_LEVEL_INFO ) ;
if ( Settings . ledstate & 0x04 ) {
2017-04-25 17:24:42 +01:00
blinks + + ;
}
2017-01-28 13:41:01 +00:00
}
2017-10-18 17:22:34 +01:00
void MqttPublish ( const char * topic , boolean retained )
2017-01-28 13:41:01 +00:00
{
char * me ;
2017-10-18 17:22:34 +01:00
if ( ! strcmp ( Settings . mqtt_prefix [ 0 ] , Settings . mqtt_prefix [ 1 ] ) ) {
me = strstr ( topic , Settings . mqtt_prefix [ 0 ] ) ;
2017-04-25 17:24:42 +01:00
if ( me = = topic ) {
mqtt_cmnd_publish + = 8 ;
}
2017-01-28 13:41:01 +00:00
}
2017-10-18 17:22:34 +01:00
MqttPublishDirect ( topic , retained ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-18 17:22:34 +01:00
void MqttPublish ( const char * topic )
2017-01-28 13:41:01 +00:00
{
2017-10-18 17:22:34 +01:00
MqttPublish ( topic , false ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-18 17:22:34 +01:00
void MqttPublishPrefixTopic_P ( uint8_t prefix , const char * subtopic , boolean retained )
2017-02-04 16:09:54 +00:00
{
2017-05-10 13:19:36 +01:00
/* 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
*/
2018-01-13 14:53:02 +00:00
char romram [ 33 ] ;
2017-09-02 13:37:02 +01:00
char stopic [ TOPSZ ] ;
2017-02-04 16:09:54 +00:00
2017-10-18 17:22:34 +01:00
snprintf_P ( romram , sizeof ( romram ) , ( ( prefix > 3 ) & & ! Settings . flag . mqtt_response ) ? S_RSLT_RESULT : subtopic ) ;
2017-09-02 13:37:02 +01:00
for ( byte i = 0 ; i < strlen ( romram ) ; i + + ) {
romram [ i ] = toupper ( romram [ i ] ) ;
}
2017-05-10 13:19:36 +01:00
prefix & = 3 ;
2017-10-18 17:22:34 +01:00
GetTopic_P ( stopic , prefix , Settings . mqtt_topic , romram ) ;
MqttPublish ( stopic , retained ) ;
2017-05-04 12:58:26 +01:00
}
2017-10-18 17:22:34 +01:00
void MqttPublishPrefixTopic_P ( uint8_t prefix , const char * subtopic )
2017-05-04 12:58:26 +01:00
{
2017-10-18 17:22:34 +01:00
MqttPublishPrefixTopic_P ( prefix , subtopic , false ) ;
2017-02-04 16:09:54 +00:00
}
2017-10-18 17:22:34 +01:00
void MqttPublishPowerState ( byte device )
2017-01-28 13:41:01 +00:00
{
2017-04-25 17:24:42 +01:00
char stopic [ TOPSZ ] ;
2018-01-13 14:53:02 +00:00
char scommand [ 33 ] ;
2017-01-28 13:41:01 +00:00
2017-10-18 17:22:34 +01:00
if ( ( device < 1 ) | | ( device > devices_present ) ) {
2017-04-25 17:24:42 +01:00
device = 1 ;
}
2017-10-18 17:22:34 +01:00
GetPowerDevice ( scommand , device , sizeof ( scommand ) ) ;
2018-01-18 15:19:28 +00:00
GetTopic_P ( stopic , STAT , Settings . mqtt_topic , ( Settings . flag . mqtt_response ) ? scommand : S_RSLT_RESULT ) ;
2017-11-11 11:33:30 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_SVALUE , scommand , GetStateText ( bitRead ( power , device - 1 ) ) ) ;
2017-10-18 17:22:34 +01:00
MqttPublish ( stopic ) ;
2017-09-02 13:37:02 +01:00
2018-01-18 15:19:28 +00:00
GetTopic_P ( stopic , STAT , Settings . mqtt_topic , scommand ) ;
2017-10-18 17:22:34 +01:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , GetStateText ( bitRead ( power , device - 1 ) ) ) ;
MqttPublish ( stopic , Settings . flag . mqtt_power_retain ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-18 17:22:34 +01:00
void MqttPublishPowerBlinkState ( byte device )
2017-01-28 13:41:01 +00:00
{
2018-01-13 14:53:02 +00:00
char scommand [ 33 ] ;
2017-01-28 13:41:01 +00:00
2017-10-18 17:22:34 +01:00
if ( ( device < 1 ) | | ( device > devices_present ) ) {
2017-04-25 17:24:42 +01:00
device = 1 ;
}
2018-01-06 16:34:42 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " { \" %s \" : \" " D_JSON_BLINK " %s \" } " ) ,
2017-10-18 17:22:34 +01:00
GetPowerDevice ( scommand , device , sizeof ( scommand ) ) , GetStateText ( bitRead ( blink_mask , device - 1 ) ) ) ;
2017-09-02 13:37:02 +01:00
2018-01-18 15:19:28 +00:00
MqttPublishPrefixTopic_P ( RESULT_OR_STAT , S_RSLT_POWER ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-18 17:22:34 +01:00
void MqttConnected ( )
2017-01-28 13:41:01 +00:00
{
2017-04-25 17:24:42 +01:00
char stopic [ TOPSZ ] ;
2017-01-28 13:41:01 +00:00
2017-10-18 17:22:34 +01:00
if ( Settings . flag . mqtt_enabled ) {
2017-02-04 16:09:54 +00:00
// Satisfy iobroker (#299)
2017-09-13 13:19:34 +01:00
mqtt_data [ 0 ] = ' \0 ' ;
2018-01-18 15:19:28 +00:00
MqttPublishPrefixTopic_P ( CMND , S_RSLT_POWER ) ;
2017-10-18 17:22:34 +01:00
2018-01-18 15:19:28 +00:00
GetTopic_P ( stopic , CMND , Settings . mqtt_topic , PSTR ( " # " ) ) ;
2017-10-18 17:22:34 +01:00
MqttSubscribe ( stopic ) ;
if ( strstr ( Settings . mqtt_fulltopic , MQTT_TOKEN_TOPIC ) ! = NULL ) {
2018-01-18 15:19:28 +00:00
GetTopic_P ( stopic , CMND , Settings . mqtt_grptopic , PSTR ( " # " ) ) ;
2017-10-18 17:22:34 +01:00
MqttSubscribe ( stopic ) ;
fallback_topic_flag = 1 ;
2018-01-18 15:19:28 +00:00
GetTopic_P ( stopic , CMND , mqtt_client , PSTR ( " # " ) ) ;
2017-10-18 17:22:34 +01:00
fallback_topic_flag = 0 ;
MqttSubscribe ( stopic ) ;
2017-05-10 13:19:36 +01:00
}
2018-01-05 11:26:19 +00:00
XdrvCall ( FUNC_MQTT_SUBSCRIBE ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-18 17:22:34 +01:00
if ( mqtt_connection_flag ) {
2018-01-10 13:10:25 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " { \" " D_CMND_MODULE " \" : \" %s \" , \" " D_JSON_VERSION " \" : \" %s \" , \" " D_JSON_FALLBACKTOPIC " \" : \" %s \" , \" " D_CMND_GROUPTOPIC " \" : \" %s \" } " ) ,
my_module . name , my_version , mqtt_client , Settings . mqtt_grptopic ) ;
2018-01-18 15:19:28 +00:00
MqttPublishPrefixTopic_P ( TELE , PSTR ( D_RSLT_INFO " 1 " ) ) ;
2017-01-28 13:41:01 +00:00
# ifdef USE_WEBSERVER
2017-10-18 17:22:34 +01:00
if ( Settings . webserver ) {
2018-01-06 16:34:42 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " { \" " D_JSON_WEBSERVER_MODE " \" : \" %s \" , \" " D_CMND_HOSTNAME " \" : \" %s \" , \" " D_CMND_IPADDRESS " \" : \" %s \" } " ) ,
2017-10-18 17:22:34 +01:00
( 2 = = Settings . webserver ) ? D_ADMIN : D_USER , my_hostname , WiFi . localIP ( ) . toString ( ) . c_str ( ) ) ;
2018-01-18 15:19:28 +00:00
MqttPublishPrefixTopic_P ( TELE , PSTR ( D_RSLT_INFO " 2 " ) ) ;
2017-01-28 13:41:01 +00:00
}
# endif // USE_WEBSERVER
2018-01-06 16:34:42 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " { \" " D_JSON_RESTARTREASON " \" : \" %s \" } " ) ,
2017-10-18 17:22:34 +01:00
( GetResetReason ( ) = = " Exception " ) ? ESP . getResetInfo ( ) . c_str ( ) : GetResetReason ( ) . c_str ( ) ) ;
2018-01-18 15:19:28 +00:00
MqttPublishPrefixTopic_P ( TELE , PSTR ( D_RSLT_INFO " 3 " ) ) ;
2017-10-18 17:22:34 +01:00
if ( Settings . tele_period ) {
tele_period = Settings . tele_period - 9 ;
2017-04-25 17:24:42 +01:00
}
2017-01-28 13:41:01 +00:00
status_update_timer = 2 ;
2018-01-18 15:19:28 +00:00
XdrvCall ( FUNC_MQTT_INIT ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-18 17:22:34 +01:00
mqtt_connection_flag = 0 ;
2017-01-28 13:41:01 +00:00
}
2017-10-18 17:22:34 +01:00
void MqttReconnect ( )
2017-01-28 13:41:01 +00:00
{
2017-04-25 17:24:42 +01:00
char stopic [ TOPSZ ] ;
2017-01-28 13:41:01 +00:00
2017-10-18 17:22:34 +01:00
mqtt_retry_counter = Settings . mqtt_retry ;
2017-01-28 13:41:01 +00:00
2017-10-18 17:22:34 +01:00
if ( ! Settings . flag . mqtt_enabled ) {
MqttConnected ( ) ;
2017-01-28 13:41:01 +00:00
return ;
}
2017-01-29 20:36:12 +00:00
# ifdef USE_EMULATION
2017-10-18 17:22:34 +01:00
UdpDisconnect ( ) ;
2017-01-29 20:36:12 +00:00
# endif // USE_EMULATION
2017-10-18 17:22:34 +01:00
if ( mqtt_connection_flag > 1 ) {
2017-01-28 13:41:01 +00:00
# ifdef USE_MQTT_TLS
2017-10-18 17:22:34 +01:00
AddLog_P ( LOG_LEVEL_INFO , S_LOG_MQTT , PSTR ( D_FINGERPRINT ) ) ;
if ( ! EspClient . connect ( Settings . mqtt_host , Settings . mqtt_port ) ) {
2017-09-13 13:19:34 +01:00
snprintf_P ( log_data , sizeof ( log_data ) , PSTR ( D_LOG_MQTT D_TLS_CONNECT_FAILED_TO " %s:%d. " D_RETRY_IN " %d " D_UNIT_SECOND ) ,
2017-10-18 17:22:34 +01:00
Settings . mqtt_host , Settings . mqtt_port , mqtt_retry_counter ) ;
AddLog ( LOG_LEVEL_DEBUG ) ;
2017-01-28 13:41:01 +00:00
return ;
}
2017-10-18 17:22:34 +01:00
if ( EspClient . verify ( Settings . mqtt_fingerprint , Settings . mqtt_host ) ) {
AddLog_P ( LOG_LEVEL_INFO , S_LOG_MQTT , PSTR ( D_VERIFIED ) ) ;
2017-01-28 13:41:01 +00:00
} else {
2017-10-18 17:22:34 +01:00
AddLog_P ( LOG_LEVEL_DEBUG , S_LOG_MQTT , PSTR ( D_INSECURE ) ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-18 17:22:34 +01:00
EspClient . stop ( ) ;
2017-10-10 14:40:02 +01:00
yield ( ) ;
2017-01-28 13:41:01 +00:00
# endif // USE_MQTT_TLS
2017-10-18 17:22:34 +01:00
MqttClient . setCallback ( MqttDataCallback ) ;
mqtt_connection_flag = 1 ;
mqtt_retry_counter = 1 ;
2017-01-28 13:41:01 +00:00
return ;
}
2017-10-18 17:22:34 +01:00
AddLog_P ( LOG_LEVEL_INFO , S_LOG_MQTT , PSTR ( D_ATTEMPTING_CONNECTION ) ) ;
2017-01-28 13:41:01 +00:00
# ifndef USE_MQTT_TLS
# ifdef USE_DISCOVERY
# ifdef MQTT_HOST_DISCOVERY
2017-10-18 17:22:34 +01:00
if ( ! strlen ( Settings . mqtt_host ) ) {
MdnsDiscoverMqttServer ( ) ;
}
2017-01-28 13:41:01 +00:00
# endif // MQTT_HOST_DISCOVERY
# endif // USE_DISCOVERY
# endif // USE_MQTT_TLS
2017-10-18 17:22:34 +01:00
MqttClient . setServer ( Settings . mqtt_host , Settings . mqtt_port ) ;
2017-05-08 12:21:45 +01:00
2018-01-18 15:19:28 +00:00
GetTopic_P ( stopic , TELE , Settings . mqtt_topic , S_LWT ) ;
2017-09-13 13:19:34 +01:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_OFFLINE ) ;
2017-10-18 17:22:34 +01:00
char * mqtt_user = NULL ;
char * mqtt_pwd = NULL ;
if ( strlen ( Settings . mqtt_user ) > 0 ) {
mqtt_user = Settings . mqtt_user ;
}
if ( strlen ( Settings . mqtt_pwd ) > 0 ) {
mqtt_pwd = Settings . mqtt_pwd ;
}
if ( MqttClient . connect ( mqtt_client , mqtt_user , mqtt_pwd , stopic , 1 , true , mqtt_data ) ) {
AddLog_P ( LOG_LEVEL_INFO , S_LOG_MQTT , PSTR ( D_CONNECTED ) ) ;
mqtt_retry_counter = 0 ;
2017-09-13 13:19:34 +01:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( D_ONLINE ) ) ;
2017-10-18 17:22:34 +01:00
MqttPublish ( stopic , true ) ;
MqttConnected ( ) ;
2017-01-28 13:41:01 +00:00
} else {
2017-09-13 13:19:34 +01:00
snprintf_P ( log_data , sizeof ( log_data ) , PSTR ( D_LOG_MQTT D_CONNECT_FAILED_TO " %s:%d, rc %d. " D_RETRY_IN " %d " D_UNIT_SECOND ) ,
2017-10-18 17:22:34 +01:00
Settings . mqtt_host , Settings . mqtt_port , MqttClient . state ( ) , mqtt_retry_counter ) ; //status codes are documented here http://pubsubclient.knolleary.net/api.html#state
AddLog ( LOG_LEVEL_INFO ) ;
2017-01-28 13:41:01 +00:00
}
}
2017-02-19 16:49:17 +00:00
/********************************************************************************************/
2017-10-18 17:22:34 +01:00
boolean MqttCommand ( boolean grpflg , char * type , uint16_t index , char * dataBuf , uint16_t data_len , int16_t payload , uint16_t payload16 )
2017-03-08 15:20:45 +00:00
{
2017-10-29 17:18:46 +00:00
char command [ CMDSZ ] ;
2017-03-08 15:20:45 +00:00
boolean serviced = true ;
2017-04-25 17:24:42 +01:00
char stemp1 [ TOPSZ ] ;
char stemp2 [ 10 ] ;
2017-05-08 12:21:45 +01:00
char scommand [ CMDSZ ] ;
2017-03-08 15:20:45 +00:00
uint16_t i ;
2017-09-02 13:37:02 +01:00
2017-10-29 17:18:46 +00:00
int command_code = GetCommandCode ( command , sizeof ( command ) , type , kMqttCommands ) ;
if ( CMND_MQTTHOST = = command_code ) {
2017-10-18 17:22:34 +01:00
if ( ( data_len > 0 ) & & ( data_len < sizeof ( Settings . mqtt_host ) ) ) {
strlcpy ( Settings . mqtt_host , ( ! strcmp ( dataBuf , " 0 " ) ) ? " " : ( 1 = = payload ) ? MQTT_HOST : dataBuf , sizeof ( Settings . mqtt_host ) ) ;
restart_flag = 2 ;
2017-03-08 15:20:45 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_SVALUE , command , Settings . mqtt_host ) ;
2017-03-08 15:20:45 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_MQTTPORT = = command_code ) {
2017-09-12 09:19:16 +01:00
if ( payload16 > 0 ) {
2017-10-18 17:22:34 +01:00
Settings . mqtt_port = ( 1 = = payload16 ) ? MQTT_PORT : payload16 ;
restart_flag = 2 ;
2017-03-08 15:20:45 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_NVALUE , command , Settings . mqtt_port ) ;
2017-03-08 15:20:45 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_MQTTRETRY = = command_code ) {
2017-06-06 22:23:23 +01:00
if ( ( payload > = MQTT_RETRY_SECS ) & & ( payload < 32001 ) ) {
2017-10-18 17:22:34 +01:00
Settings . mqtt_retry = payload ;
mqtt_retry_counter = Settings . mqtt_retry ;
2017-05-10 13:19:36 +01:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_NVALUE , command , Settings . mqtt_retry ) ;
2017-05-10 13:19:36 +01:00
}
2017-10-29 17:18:46 +00:00
else if ( ( CMND_STATETEXT = = command_code ) & & ( index > 0 ) & & ( index < = 4 ) ) {
2017-10-18 17:22:34 +01:00
if ( ( data_len > 0 ) & & ( data_len < sizeof ( Settings . state_text [ 0 ] ) ) ) {
2017-04-25 17:24:42 +01:00
for ( i = 0 ; i < = data_len ; i + + ) {
if ( dataBuf [ i ] = = ' ' ) {
dataBuf [ i ] = ' _ ' ;
}
}
2017-10-18 17:22:34 +01:00
strlcpy ( Settings . state_text [ index - 1 ] , dataBuf , sizeof ( Settings . state_text [ 0 ] ) ) ;
2017-03-29 17:42:05 +01:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_INDEX_SVALUE , command , index , GetStateText ( index - 1 ) ) ;
2017-03-29 17:42:05 +01:00
}
2017-03-08 15:20:45 +00:00
# ifdef USE_MQTT_TLS
2017-10-29 17:18:46 +00:00
else if ( CMND_MQTTFINGERPRINT = = command_code ) {
2017-10-18 17:22:34 +01:00
if ( ( data_len > 0 ) & & ( data_len < sizeof ( Settings . mqtt_fingerprint ) ) ) {
strlcpy ( Settings . mqtt_fingerprint , ( ! strcmp ( dataBuf , " 0 " ) ) ? " " : ( 1 = = payload ) ? MQTT_FINGERPRINT : dataBuf , sizeof ( Settings . mqtt_fingerprint ) ) ;
restart_flag = 2 ;
2017-03-08 15:20:45 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_SVALUE , command , Settings . mqtt_fingerprint ) ;
2017-03-08 15:20:45 +00:00
}
# endif
2017-10-29 17:18:46 +00:00
else if ( ( CMND_MQTTCLIENT = = command_code ) & & ! grpflg ) {
2017-10-18 17:22:34 +01:00
if ( ( data_len > 0 ) & & ( data_len < sizeof ( Settings . mqtt_client ) ) ) {
strlcpy ( Settings . mqtt_client , ( 1 = = payload ) ? MQTT_CLIENT_ID : dataBuf , sizeof ( Settings . mqtt_client ) ) ;
restart_flag = 2 ;
2017-03-08 15:20:45 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_SVALUE , command , Settings . mqtt_client ) ;
2017-03-08 15:20:45 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_MQTTUSER = = command_code ) {
2017-10-18 17:22:34 +01:00
if ( ( data_len > 0 ) & & ( data_len < sizeof ( Settings . mqtt_user ) ) ) {
strlcpy ( Settings . mqtt_user , ( ! strcmp ( dataBuf , " 0 " ) ) ? " " : ( 1 = = payload ) ? MQTT_USER : dataBuf , sizeof ( Settings . mqtt_user ) ) ;
restart_flag = 2 ;
2017-03-08 15:20:45 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_SVALUE , command , Settings . mqtt_user ) ;
2017-03-08 15:20:45 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_MQTTPASSWORD = = command_code ) {
2017-10-18 17:22:34 +01:00
if ( ( data_len > 0 ) & & ( data_len < sizeof ( Settings . mqtt_pwd ) ) ) {
strlcpy ( Settings . mqtt_pwd , ( ! strcmp ( dataBuf , " 0 " ) ) ? " " : ( 1 = = payload ) ? MQTT_PASS : dataBuf , sizeof ( Settings . mqtt_pwd ) ) ;
restart_flag = 2 ;
2017-03-08 15:20:45 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_SVALUE , command , Settings . mqtt_pwd ) ;
2017-03-08 15:20:45 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_FULLTOPIC = = command_code ) {
2017-10-18 17:22:34 +01:00
if ( ( data_len > 0 ) & & ( data_len < sizeof ( Settings . mqtt_fulltopic ) ) ) {
MakeValidMqtt ( 1 , dataBuf ) ;
if ( ! strcmp ( dataBuf , mqtt_client ) ) {
2017-05-08 12:21:45 +01:00
payload = 1 ;
}
2017-05-13 12:02:10 +01:00
strlcpy ( stemp1 , ( 1 = = payload ) ? MQTT_FULLTOPIC : dataBuf , sizeof ( stemp1 ) ) ;
2017-10-18 17:22:34 +01:00
if ( strcmp ( stemp1 , Settings . mqtt_fulltopic ) ) {
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , ( Settings . flag . mqtt_offline ) ? S_OFFLINE : " " ) ;
2018-01-18 15:19:28 +00:00
MqttPublishPrefixTopic_P ( TELE , PSTR ( D_LWT ) , true ) ; // Offline or remove previous retained topic
2017-10-18 17:22:34 +01:00
strlcpy ( Settings . mqtt_fulltopic , stemp1 , sizeof ( Settings . mqtt_fulltopic ) ) ;
restart_flag = 2 ;
2017-05-13 12:02:10 +01:00
}
2017-05-08 12:21:45 +01:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_SVALUE , command , Settings . mqtt_fulltopic ) ;
2017-05-08 12:21:45 +01:00
}
2017-10-29 17:18:46 +00:00
else if ( ( CMND_PREFIX = = command_code ) & & ( index > 0 ) & & ( index < = 3 ) ) {
2017-10-18 17:22:34 +01:00
if ( ( data_len > 0 ) & & ( data_len < sizeof ( Settings . mqtt_prefix [ 0 ] ) ) ) {
MakeValidMqtt ( 0 , dataBuf ) ;
strlcpy ( Settings . mqtt_prefix [ index - 1 ] , ( 1 = = payload ) ? ( 1 = = index ) ? SUB_PREFIX : ( 2 = = index ) ? PUB_PREFIX : PUB_PREFIX2 : dataBuf , sizeof ( Settings . mqtt_prefix [ 0 ] ) ) ;
// if (Settings.mqtt_prefix[index -1][strlen(Settings.mqtt_prefix[index -1])] == '/') Settings.mqtt_prefix[index -1][strlen(Settings.mqtt_prefix[index -1])] = 0;
restart_flag = 2 ;
2017-03-25 16:24:11 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_INDEX_SVALUE , command , index , Settings . mqtt_prefix [ index - 1 ] ) ;
2017-03-25 16:24:11 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_GROUPTOPIC = = command_code ) {
2017-10-18 17:22:34 +01:00
if ( ( data_len > 0 ) & & ( data_len < sizeof ( Settings . mqtt_grptopic ) ) ) {
MakeValidMqtt ( 0 , dataBuf ) ;
if ( ! strcmp ( dataBuf , mqtt_client ) ) {
2017-04-25 17:24:42 +01:00
payload = 1 ;
}
2017-10-18 17:22:34 +01:00
strlcpy ( Settings . mqtt_grptopic , ( 1 = = payload ) ? MQTT_GRPTOPIC : dataBuf , sizeof ( Settings . mqtt_grptopic ) ) ;
restart_flag = 2 ;
2017-03-08 15:20:45 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_SVALUE , command , Settings . mqtt_grptopic ) ;
2017-03-08 15:20:45 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( ( CMND_TOPIC = = command_code ) & & ! grpflg ) {
2017-10-18 17:22:34 +01:00
if ( ( data_len > 0 ) & & ( data_len < sizeof ( Settings . mqtt_topic ) ) ) {
MakeValidMqtt ( 0 , dataBuf ) ;
if ( ! strcmp ( dataBuf , mqtt_client ) ) {
2017-04-25 17:24:42 +01:00
payload = 1 ;
}
2017-05-11 16:47:34 +01:00
strlcpy ( stemp1 , ( 1 = = payload ) ? MQTT_TOPIC : dataBuf , sizeof ( stemp1 ) ) ;
2017-10-18 17:22:34 +01:00
if ( strcmp ( stemp1 , Settings . mqtt_topic ) ) {
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , ( Settings . flag . mqtt_offline ) ? S_OFFLINE : " " ) ;
2018-01-18 15:19:28 +00:00
MqttPublishPrefixTopic_P ( TELE , PSTR ( D_LWT ) , true ) ; // Offline or remove previous retained topic
2017-10-18 17:22:34 +01:00
strlcpy ( Settings . mqtt_topic , stemp1 , sizeof ( Settings . mqtt_topic ) ) ;
restart_flag = 2 ;
2017-05-11 16:47:34 +01:00
}
2017-03-08 15:20:45 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_SVALUE , command , Settings . mqtt_topic ) ;
2017-03-08 15:20:45 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( ( CMND_BUTTONTOPIC = = command_code ) & & ! grpflg ) {
2017-10-18 17:22:34 +01:00
if ( ( data_len > 0 ) & & ( data_len < sizeof ( Settings . button_topic ) ) ) {
MakeValidMqtt ( 0 , dataBuf ) ;
if ( ! strcmp ( dataBuf , mqtt_client ) ) {
2017-04-25 17:24:42 +01:00
payload = 1 ;
}
2017-10-18 17:22:34 +01:00
strlcpy ( Settings . button_topic , ( ! strcmp ( dataBuf , " 0 " ) ) ? " " : ( 1 = = payload ) ? Settings . mqtt_topic : dataBuf , sizeof ( Settings . button_topic ) ) ;
2017-03-08 15:20:45 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_SVALUE , command , Settings . button_topic ) ;
2017-03-08 15:20:45 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_SWITCHTOPIC = = command_code ) {
2017-10-18 17:22:34 +01:00
if ( ( data_len > 0 ) & & ( data_len < sizeof ( Settings . switch_topic ) ) ) {
MakeValidMqtt ( 0 , dataBuf ) ;
if ( ! strcmp ( dataBuf , mqtt_client ) ) {
2017-04-25 17:24:42 +01:00
payload = 1 ;
}
2017-10-18 17:22:34 +01:00
strlcpy ( Settings . switch_topic , ( ! strcmp ( dataBuf , " 0 " ) ) ? " " : ( 1 = = payload ) ? Settings . mqtt_topic : dataBuf , sizeof ( Settings . switch_topic ) ) ;
2017-03-08 15:20:45 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_SVALUE , command , Settings . switch_topic ) ;
2017-03-08 15:20:45 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_BUTTONRETAIN = = command_code ) {
2017-06-06 22:23:23 +01:00
if ( ( payload > = 0 ) & & ( payload < = 1 ) ) {
2017-10-18 17:22:34 +01:00
strlcpy ( Settings . button_topic , Settings . mqtt_topic , sizeof ( Settings . button_topic ) ) ;
2017-03-08 15:20:45 +00:00
if ( ! payload ) {
2017-10-14 10:26:49 +01:00
for ( i = 1 ; i < = MAX_KEYS ; i + + ) {
2017-06-06 22:23:23 +01:00
send_button_power ( 0 , i , 9 ) ; // Clear MQTT retain in broker
2017-03-08 15:20:45 +00:00
}
}
2017-10-18 17:22:34 +01:00
Settings . flag . mqtt_button_retain = payload ;
2017-03-08 15:20:45 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_SVALUE , command , GetStateText ( Settings . flag . mqtt_button_retain ) ) ;
2017-03-08 15:20:45 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_SWITCHRETAIN = = command_code ) {
2017-06-06 22:23:23 +01:00
if ( ( payload > = 0 ) & & ( payload < = 1 ) ) {
2017-10-18 17:22:34 +01:00
strlcpy ( Settings . button_topic , Settings . mqtt_topic , sizeof ( Settings . button_topic ) ) ;
2017-03-08 15:20:45 +00:00
if ( ! payload ) {
2017-10-10 14:40:02 +01:00
for ( i = 1 ; i < = MAX_SWITCHES ; i + + ) {
2017-06-06 22:23:23 +01:00
send_button_power ( 1 , i , 9 ) ; // Clear MQTT retain in broker
2017-03-08 15:20:45 +00:00
}
}
2017-10-18 17:22:34 +01:00
Settings . flag . mqtt_switch_retain = payload ;
2017-03-08 15:20:45 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_SVALUE , command , GetStateText ( Settings . flag . mqtt_switch_retain ) ) ;
2017-03-08 15:20:45 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_POWERRETAIN = = command_code ) {
2017-06-06 22:23:23 +01:00
if ( ( payload > = 0 ) & & ( payload < = 1 ) ) {
2017-03-08 15:20:45 +00:00
if ( ! payload ) {
2017-10-18 17:22:34 +01:00
for ( i = 1 ; i < = devices_present ; i + + ) { // Clear MQTT retain in broker
2018-01-18 15:19:28 +00:00
GetTopic_P ( stemp1 , STAT , Settings . mqtt_topic , GetPowerDevice ( scommand , i , sizeof ( scommand ) ) ) ;
2017-09-13 13:19:34 +01:00
mqtt_data [ 0 ] = ' \0 ' ;
2017-10-18 17:22:34 +01:00
MqttPublish ( stemp1 , Settings . flag . mqtt_power_retain ) ;
2017-03-08 15:20:45 +00:00
}
}
2017-10-18 17:22:34 +01:00
Settings . flag . mqtt_power_retain = payload ;
2017-03-08 15:20:45 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_SVALUE , command , GetStateText ( Settings . flag . mqtt_power_retain ) ) ;
2017-03-08 15:20:45 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_SENSORRETAIN = = command_code ) {
2017-06-06 22:23:23 +01:00
if ( ( payload > = 0 ) & & ( payload < = 1 ) ) {
2017-05-04 12:58:26 +01:00
if ( ! payload ) {
2017-09-13 13:19:34 +01:00
mqtt_data [ 0 ] = ' \0 ' ;
2018-01-18 15:19:28 +00:00
MqttPublishPrefixTopic_P ( TELE , PSTR ( D_RSLT_SENSOR ) , Settings . flag . mqtt_sensor_retain ) ;
MqttPublishPrefixTopic_P ( TELE , PSTR ( D_RSLT_ENERGY ) , Settings . flag . mqtt_sensor_retain ) ;
2017-05-04 12:58:26 +01:00
}
2017-10-18 17:22:34 +01:00
Settings . flag . mqtt_sensor_retain = payload ;
2017-05-04 12:58:26 +01:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_SVALUE , command , GetStateText ( Settings . flag . mqtt_sensor_retain ) ) ;
2017-05-04 12:58:26 +01:00
}
2018-01-05 11:26:19 +00:00
else serviced = false ;
2017-03-08 15:20:45 +00:00
return serviced ;
}
/********************************************************************************************/
2017-10-18 17:22:34 +01:00
void MqttDataCallback ( char * topic , byte * data , unsigned int data_len )
2017-01-28 13:41:01 +00:00
{
char * str ;
2017-10-18 17:22:34 +01:00
if ( ! strcmp ( Settings . mqtt_prefix [ 0 ] , Settings . mqtt_prefix [ 1 ] ) ) {
str = strstr ( topic , Settings . mqtt_prefix [ 0 ] ) ;
2017-01-28 13:41:01 +00:00
if ( ( str = = topic ) & & mqtt_cmnd_publish ) {
2017-04-25 17:24:42 +01:00
if ( mqtt_cmnd_publish > 8 ) {
2017-09-02 13:37:02 +01:00
mqtt_cmnd_publish - = 8 ;
2017-04-25 17:24:42 +01:00
} else {
mqtt_cmnd_publish = 0 ;
}
2017-01-28 13:41:01 +00:00
return ;
}
}
2017-04-25 17:24:42 +01:00
char topicBuf [ TOPSZ ] ;
char dataBuf [ data_len + 1 ] ;
2017-10-29 17:18:46 +00:00
char command [ CMDSZ ] ;
2017-04-25 17:24:42 +01:00
char stemp1 [ TOPSZ ] ;
char * p ;
char * mtopic = NULL ;
char * type = NULL ;
2017-06-16 13:33:49 +01:00
byte otype = 0 ;
byte ptype = 0 ;
2017-09-14 14:35:38 +01:00
byte jsflg = 0 ;
byte lines = 1 ;
2017-04-25 17:24:42 +01:00
uint16_t i = 0 ;
uint16_t grpflg = 0 ;
uint16_t index ;
2017-03-25 16:24:11 +00:00
uint32_t address ;
2017-01-28 13:41:01 +00:00
strncpy ( topicBuf , topic , sizeof ( topicBuf ) ) ;
2017-09-08 11:57:08 +01:00
for ( i = 0 ; i < data_len ; i + + ) {
if ( ! isspace ( data [ i ] ) ) {
break ;
}
}
data_len - = i ;
memcpy ( dataBuf , data + i , sizeof ( dataBuf ) ) ;
2017-01-28 13:41:01 +00:00
dataBuf [ sizeof ( dataBuf ) - 1 ] = 0 ;
2017-09-13 13:19:34 +01:00
snprintf_P ( log_data , sizeof ( log_data ) , PSTR ( D_LOG_RESULT D_RECEIVED_TOPIC " %s, " D_DATA_SIZE " %d, " D_DATA " %s " ) ,
2017-09-02 13:37:02 +01:00
topicBuf , data_len , dataBuf ) ;
2017-10-18 17:22:34 +01:00
AddLog ( LOG_LEVEL_DEBUG_MORE ) ;
2017-01-28 13:41:01 +00:00
// if (LOG_LEVEL_DEBUG_MORE <= seriallog_level) Serial.println(dataBuf);
2018-01-05 11:26:19 +00:00
if ( XdrvMqttData ( topicBuf , sizeof ( topicBuf ) , dataBuf , sizeof ( dataBuf ) ) ) {
return ;
2017-01-28 13:41:01 +00:00
}
2017-10-18 17:22:34 +01:00
grpflg = ( strstr ( topicBuf , Settings . mqtt_grptopic ) ! = NULL ) ;
fallback_topic_flag = ( strstr ( topicBuf , mqtt_client ) ! = NULL ) ;
2017-06-16 13:33:49 +01:00
type = strrchr ( topicBuf , ' / ' ) + 1 ; // Last part of received topic is always the command (type)
2017-01-28 13:41:01 +00:00
index = 1 ;
if ( type ! = NULL ) {
2017-04-25 17:24:42 +01:00
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 ) ;
}
2017-01-28 13:41:01 +00:00
type [ i ] = ' \0 ' ;
}
2017-09-16 16:34:03 +01:00
snprintf_P ( log_data , sizeof ( log_data ) , PSTR ( D_LOG_RESULT D_GROUP " %d, " D_INDEX " %d, " D_COMMAND " %s, " D_DATA " %s " ) ,
grpflg , index , type , dataBuf ) ;
2017-10-18 17:22:34 +01:00
AddLog ( LOG_LEVEL_DEBUG ) ;
2017-01-28 13:41:01 +00:00
if ( type ! = NULL ) {
2018-01-06 16:34:42 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " { \" " D_JSON_COMMAND " \" : \" " D_JSON_ERROR " \" } " ) ) ;
2017-10-18 17:22:34 +01:00
if ( Settings . ledstate & 0x02 ) {
2017-04-25 17:24:42 +01:00
blinks + + ;
}
2017-01-28 13:41:01 +00:00
2017-09-16 16:34:03 +01:00
if ( ! strcmp ( dataBuf , " ? " ) ) {
2017-04-25 17:24:42 +01:00
data_len = 0 ;
}
2017-06-25 22:01:41 +01:00
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
2017-06-06 22:23:23 +01:00
}
2017-11-24 16:26:20 +00:00
backlog_delay = MIN_BACKLOG_DELAY ; // Reset backlog delay
2017-06-06 22:23:23 +01:00
2017-10-29 17:18:46 +00:00
if ( ( GetCommandCode ( command , sizeof ( command ) , dataBuf , kOptionOff ) > = 0 ) | | ! strcasecmp ( dataBuf , Settings . state_text [ 0 ] ) ) {
2017-04-25 17:24:42 +01:00
payload = 0 ;
}
2017-10-29 17:18:46 +00:00
if ( ( GetCommandCode ( command , sizeof ( command ) , dataBuf , kOptionOn ) > = 0 ) | | ! strcasecmp ( dataBuf , Settings . state_text [ 1 ] ) ) {
2017-04-25 17:24:42 +01:00
payload = 1 ;
}
2017-10-29 17:18:46 +00:00
if ( ( GetCommandCode ( command , sizeof ( command ) , dataBuf , kOptionToggle ) > = 0 ) | | ! strcasecmp ( dataBuf , Settings . state_text [ 2 ] ) ) {
2017-04-25 17:24:42 +01:00
payload = 2 ;
}
2017-10-29 17:18:46 +00:00
if ( GetCommandCode ( command , sizeof ( command ) , dataBuf , kOptionBlink ) > = 0 ) {
2017-04-25 17:24:42 +01:00
payload = 3 ;
}
2017-10-29 17:18:46 +00:00
if ( GetCommandCode ( command , sizeof ( command ) , dataBuf , kOptionBlinkOff ) > = 0 ) {
2017-04-25 17:24:42 +01:00
payload = 4 ;
}
2017-01-28 13:41:01 +00:00
2017-09-13 13:19:34 +01:00
// snprintf_P(log_data, sizeof(log_data), PSTR("RSLT: Payload %d, Payload16 %d"), payload, payload16);
2017-10-18 17:22:34 +01:00
// AddLog(LOG_LEVEL_DEBUG);
2017-06-06 22:23:23 +01:00
2017-10-29 17:18:46 +00:00
int command_code = GetCommandCode ( command , sizeof ( command ) , type , kTasmotaCommands ) ;
if ( CMND_BACKLOG = = command_code ) {
2017-07-15 14:07:30 +01:00
if ( data_len ) {
char * blcommand = strtok ( dataBuf , " ; " ) ;
while ( blcommand ! = NULL ) {
2017-10-18 17:22:34 +01:00
backlog [ backlog_index ] = String ( blcommand ) ;
backlog_index + + ;
2017-07-15 14:07:30 +01:00
/*
2017-10-18 17:22:34 +01:00
if ( backlog_index > = MAX_BACKLOG ) {
backlog_index = 0 ;
2017-07-15 14:07:30 +01:00
}
*/
2017-10-18 17:22:34 +01:00
backlog_index & = 0xF ;
2017-07-15 14:07:30 +01:00
blcommand = strtok ( NULL , " ; " ) ;
}
2018-01-06 16:34:42 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_SVALUE , command , D_JSON_APPENDED ) ;
2017-07-15 14:07:30 +01:00
} else {
2017-10-18 17:22:34 +01:00
uint8_t blflag = ( backlog_pointer = = backlog_index ) ;
backlog_pointer = backlog_index ;
2018-01-06 16:34:42 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_SVALUE , command , blflag ? D_JSON_EMPTY : D_JSON_ABORTED ) ;
2017-07-15 14:07:30 +01:00
}
}
2017-10-29 17:18:46 +00:00
else if ( CMND_DELAY = = command_code ) {
2017-07-15 14:07:30 +01:00
if ( ( payload > = MIN_BACKLOG_DELAY ) & & ( payload < = 3600 ) ) {
2017-10-18 17:22:34 +01:00
backlog_delay = payload ;
2017-07-15 14:07:30 +01:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_NVALUE , command , backlog_delay ) ;
2017-07-15 14:07:30 +01:00
}
2017-10-29 17:18:46 +00:00
else if ( ( CMND_POWER = = command_code ) & & ( index > 0 ) & & ( index < = devices_present ) ) {
2017-06-06 22:23:23 +01:00
if ( ( payload < 0 ) | | ( payload > 4 ) ) {
2017-04-25 17:24:42 +01:00
payload = 9 ;
}
2017-10-18 17:22:34 +01:00
ExecuteCommandPower ( index , payload ) ;
fallback_topic_flag = 0 ;
2017-01-28 13:41:01 +00:00
return ;
}
2017-10-29 17:18:46 +00:00
else if ( CMND_STATUS = = command_code ) {
2017-06-06 22:23:23 +01:00
if ( ( payload < 0 ) | | ( payload > MAX_STATUS ) ) {
2017-04-25 17:24:42 +01:00
payload = 99 ;
}
2017-10-18 17:22:34 +01:00
PublishStatus ( payload ) ;
fallback_topic_flag = 0 ;
2017-01-28 13:41:01 +00:00
return ;
}
2018-01-20 11:12:39 +00:00
else if ( CMND_STATE = = command_code ) {
mqtt_data [ 0 ] = ' \0 ' ;
MqttShowState ( ) ;
}
2017-10-29 17:18:46 +00:00
else if ( ( CMND_POWERONSTATE = = command_code ) & & ( Settings . module ! = MOTOR ) ) {
2017-08-18 11:55:08 +01:00
/* 0 = Keep relays off after power on
2018-01-13 14:53:02 +00:00
* 1 = Turn relays on after power on , if PulseTime set wait for PulseTime seconds , and turn relays off
2017-08-18 11:55:08 +01:00
* 2 = Toggle relays after power on
* 3 = Set relays to last saved state after power on
* 4 = Turn relays on and disable any relay control ( used for Sonoff Pow to always measure power )
2018-01-13 14:53:02 +00:00
* 5 = Keep relays off after power on , if PulseTime set wait for PulseTime seconds , and turn relays on
2017-08-18 11:55:08 +01:00
*/
2018-01-24 16:31:20 +00:00
if ( ( payload > = POWER_ALL_OFF ) & & ( payload < = POWER_ALL_OFF_PULSETIME_ON ) ) {
2017-10-18 17:22:34 +01:00
Settings . poweronstate = payload ;
2018-01-24 16:31:20 +00:00
if ( POWER_ALL_ALWAYS_ON = = Settings . poweronstate ) {
2017-10-18 17:22:34 +01:00
for ( byte i = 1 ; i < = devices_present ; i + + ) {
2018-01-24 16:31:20 +00:00
ExecuteCommandPower ( i , POWER_ON ) ;
2017-05-05 16:57:05 +01:00
}
}
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_NVALUE , command , Settings . poweronstate ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( ( CMND_PULSETIME = = command_code ) & & ( index > 0 ) & & ( index < = MAX_PULSETIMERS ) ) {
2017-01-28 13:41:01 +00:00
if ( data_len > 0 ) {
2017-10-18 17:22:34 +01:00
Settings . pulse_timer [ index - 1 ] = payload16 ; // 0 - 65535
2017-03-12 17:36:33 +00:00
pulse_timer [ index - 1 ] = 0 ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_INDEX_NVALUE , command , index , Settings . pulse_timer [ index - 1 ] ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_BLINKTIME = = command_code ) {
2017-06-06 22:23:23 +01:00
if ( ( payload > 2 ) & & ( payload < = 3600 ) ) {
2017-10-18 17:22:34 +01:00
Settings . blinktime = payload ;
2017-04-25 17:24:42 +01:00
if ( blink_timer ) {
2017-10-18 17:22:34 +01:00
blink_timer = Settings . blinktime ;
2017-04-25 17:24:42 +01:00
}
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_NVALUE , command , Settings . blinktime ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_BLINKCOUNT = = command_code ) {
2017-01-28 13:41:01 +00:00
if ( data_len > 0 ) {
2017-10-18 17:22:34 +01:00
Settings . blinkcount = payload16 ; // 0 - 65535
2017-04-25 17:24:42 +01:00
if ( blink_counter ) {
2017-10-18 17:22:34 +01:00
blink_counter = Settings . blinkcount * 2 ;
2017-04-25 17:24:42 +01:00
}
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_NVALUE , command , Settings . blinkcount ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_SAVEDATA = = command_code ) {
2017-06-06 22:23:23 +01:00
if ( ( payload > = 0 ) & & ( payload < = 3600 ) ) {
2017-10-18 17:22:34 +01:00
Settings . save_data = payload ;
save_data_counter = Settings . save_data ;
2017-01-28 13:41:01 +00:00
}
2017-11-21 15:06:51 +00:00
SettingsSaveAll ( ) ;
2017-10-18 17:22:34 +01:00
if ( Settings . save_data > 1 ) {
2018-01-06 16:34:42 +00:00
snprintf_P ( stemp1 , sizeof ( stemp1 ) , PSTR ( D_JSON_EVERY " %d " D_UNIT_SECOND ) , Settings . save_data ) ;
2017-04-25 17:24:42 +01:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_SVALUE , command , ( Settings . save_data > 1 ) ? stemp1 : GetStateText ( Settings . save_data ) ) ;
2017-01-28 13:41:01 +00:00
}
2018-01-24 16:31:20 +00:00
else if ( CMND_SENSOR = = command_code ) {
XdrvMailbox . topic = command ;
XdrvMailbox . index = index ;
XdrvMailbox . payload = payload ;
XdrvMailbox . data_len = data_len ;
XdrvMailbox . data = dataBuf ;
XsnsCall ( FUNC_COMMAND ) ;
// if (!XsnsCall(FUNC_COMMAND)) {
// type = NULL;
// }
}
2018-01-13 14:53:02 +00:00
else if ( ( CMND_SETOPTION = = command_code ) & & ( ( index > = 0 ) & & ( index < = 19 ) ) | | ( ( index > 31 ) & & ( index < = P_MAX_PARAM8 + 31 ) ) ) {
2017-06-16 13:33:49 +01:00
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
2017-10-01 13:32:36 +01:00
case 15 : // pwm_control
2018-01-13 14:53:02 +00:00
case 19 : // hass_discovery
2017-10-18 17:22:34 +01:00
restart_flag = 2 ;
case 0 : // save_state
2017-06-16 13:33:49 +01:00
case 1 : // button_restrict
case 2 : // value_units
case 4 : // mqtt_response
case 8 : // temperature_conversion
case 10 : // mqtt_offline
case 11 : // button_swap
2017-06-19 21:54:49 +01:00
case 12 : // stop_flash_rotate
2017-07-25 17:05:47 +01:00
case 13 : // button_single
2017-08-18 11:55:08 +01:00
case 14 : // interlock
2017-10-23 11:18:15 +01:00
case 16 : // ws_clock_reverse
case 17 : // decimal_text
2017-12-27 13:10:55 +00:00
case 18 : // light_signal
2018-01-27 16:52:48 +00:00
case 20 : // not_power_linked
2017-10-18 17:22:34 +01:00
bitWrite ( Settings . flag . data , index , payload ) ;
2017-06-16 13:33:49 +01:00
}
2017-06-25 22:01:41 +01:00
if ( 12 = = index ) { // stop_flash_rotate
stop_flash_rotate = payload ;
2017-10-18 17:22:34 +01:00
SettingsSave ( 2 ) ;
2017-06-19 21:54:49 +01:00
}
2017-06-16 13:33:49 +01:00
}
2017-05-11 16:47:34 +01:00
}
2017-06-16 13:33:49 +01:00
else { // SetOption32 ..
switch ( index ) {
case P_HOLD_TIME :
if ( ( payload > = 1 ) & & ( payload < = 100 ) ) {
2017-10-18 17:22:34 +01:00
Settings . param [ P_HOLD_TIME ] = payload ;
2017-06-16 13:33:49 +01:00
}
break ;
2017-06-19 21:54:49 +01:00
case P_MAX_POWER_RETRY :
if ( ( payload > = 1 ) & & ( payload < = 250 ) ) {
2017-10-18 17:22:34 +01:00
Settings . param [ P_MAX_POWER_RETRY ] = payload ;
2017-06-19 21:54:49 +01:00
}
break ;
2017-06-16 13:33:49 +01:00
}
}
}
if ( ptype ) {
2017-10-18 17:22:34 +01:00
snprintf_P ( stemp1 , sizeof ( stemp1 ) , PSTR ( " %d " ) , Settings . param [ index ] ) ;
2017-05-11 16:47:34 +01:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_INDEX_SVALUE , command , ( ptype ) ? index + 32 : index , ( ptype ) ? stemp1 : GetStateText ( bitRead ( Settings . flag . data , index ) ) ) ;
2017-05-11 16:47:34 +01:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_TEMPERATURE_RESOLUTION = = command_code ) {
2017-06-06 22:23:23 +01:00
if ( ( payload > = 0 ) & & ( payload < = 3 ) ) {
2017-11-11 11:33:30 +00:00
Settings . flag2 . temperature_resolution = payload ;
2017-05-03 17:19:13 +01:00
}
2017-11-11 11:33:30 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_NVALUE , command , Settings . flag2 . temperature_resolution ) ;
2017-05-03 17:19:13 +01:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_HUMIDITY_RESOLUTION = = command_code ) {
2017-06-06 22:23:23 +01:00
if ( ( payload > = 0 ) & & ( payload < = 3 ) ) {
2017-11-11 11:33:30 +00:00
Settings . flag2 . humidity_resolution = payload ;
2017-05-03 17:19:13 +01:00
}
2017-11-11 11:33:30 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_NVALUE , command , Settings . flag2 . humidity_resolution ) ;
2017-05-03 17:19:13 +01:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_PRESSURE_RESOLUTION = = command_code ) {
2017-06-06 22:23:23 +01:00
if ( ( payload > = 0 ) & & ( payload < = 3 ) ) {
2017-11-11 11:33:30 +00:00
Settings . flag2 . pressure_resolution = payload ;
2017-05-03 17:19:13 +01:00
}
2017-11-11 11:33:30 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_NVALUE , command , Settings . flag2 . pressure_resolution ) ;
2017-05-03 17:19:13 +01:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_POWER_RESOLUTION = = command_code ) {
2017-11-11 11:33:30 +00:00
if ( ( payload > = 0 ) & & ( payload < = 3 ) ) {
Settings . flag2 . wattage_resolution = payload ;
2017-08-20 10:40:50 +01:00
}
2017-11-11 11:33:30 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_NVALUE , command , Settings . flag2 . wattage_resolution ) ;
2017-08-20 10:40:50 +01:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_VOLTAGE_RESOLUTION = = command_code ) {
2017-11-11 11:33:30 +00:00
if ( ( payload > = 0 ) & & ( payload < = 3 ) ) {
Settings . flag2 . voltage_resolution = payload ;
}
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_NVALUE , command , Settings . flag2 . voltage_resolution ) ;
}
else if ( CMND_CURRENT_RESOLUTION = = command_code ) {
if ( ( payload > = 0 ) & & ( payload < = 3 ) ) {
Settings . flag2 . current_resolution = payload ;
2017-08-05 14:11:50 +01:00
}
2017-11-11 11:33:30 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_NVALUE , command , Settings . flag2 . current_resolution ) ;
2017-08-05 14:11:50 +01:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_ENERGY_RESOLUTION = = command_code ) {
2017-06-06 22:23:23 +01:00
if ( ( payload > = 0 ) & & ( payload < = 5 ) ) {
2017-11-11 11:33:30 +00:00
Settings . flag2 . energy_resolution = payload ;
2017-05-03 17:19:13 +01:00
}
2017-11-11 11:33:30 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_NVALUE , command , Settings . flag2 . energy_resolution ) ;
2017-03-08 15:20:45 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_MODULE = = command_code ) {
2017-06-06 22:23:23 +01:00
if ( ( payload > 0 ) & & ( payload < = MAXMODULE ) ) {
2017-03-19 17:19:08 +00:00
payload - - ;
2017-11-15 22:07:45 +00:00
Settings . last_module = Settings . module ;
2017-10-18 17:22:34 +01:00
Settings . module = payload ;
2017-11-15 22:07:45 +00:00
if ( Settings . last_module ! = payload ) {
2017-04-25 17:24:42 +01:00
for ( byte i = 0 ; i < MAX_GPIO_PIN ; i + + ) {
2017-10-18 17:22:34 +01:00
Settings . my_gp . io [ i ] = 0 ;
2017-04-25 17:24:42 +01:00
}
2017-04-03 15:38:15 +01:00
}
2017-10-18 17:22:34 +01:00
restart_flag = 2 ;
2017-01-28 13:41:01 +00:00
}
2017-10-18 17:22:34 +01:00
snprintf_P ( stemp1 , sizeof ( stemp1 ) , kModules [ Settings . module ] . name ) ;
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_NVALUE_SVALUE , command , Settings . module + 1 , stemp1 ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_MODULES = = command_code ) {
2017-09-14 14:35:38 +01:00
for ( byte i = 0 ; i < MAXMODULE ; i + + ) {
if ( ! jsflg ) {
2017-12-18 17:20:28 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " { \" " D_CMND_MODULES " %d \" :[ " ) , lines ) ;
2017-09-14 14:35:38 +01:00
} else {
2017-11-11 11:33:30 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " %s, " ) , mqtt_data ) ;
2017-04-25 17:24:42 +01:00
}
2017-01-28 13:41:01 +00:00
jsflg = 1 ;
2017-10-18 17:22:34 +01:00
snprintf_P ( stemp1 , sizeof ( stemp1 ) , kModules [ i ] . name ) ;
2017-12-18 17:20:28 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " %s \" %d (%s) \" " ) , mqtt_data , i + 1 , stemp1 ) ;
2018-01-18 15:19:28 +00:00
if ( ( strlen ( mqtt_data ) > ( LOGSZ - TOPSZ ) ) | | ( i = = MAXMODULE - 1 ) ) {
2017-12-18 17:20:28 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " %s]} " ) , mqtt_data ) ;
2018-01-18 15:19:28 +00:00
MqttPublishPrefixTopic_P ( RESULT_OR_STAT , type ) ;
2017-09-14 14:35:38 +01:00
jsflg = 0 ;
lines + + ;
2017-04-25 17:24:42 +01:00
}
2017-01-28 13:41:01 +00:00
}
2017-09-14 14:35:38 +01:00
mqtt_data [ 0 ] = ' \0 ' ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( ( CMND_GPIO = = command_code ) & & ( index < MAX_GPIO_PIN ) ) {
2017-01-28 13:41:01 +00:00
mytmplt cmodule ;
2017-10-18 17:22:34 +01:00
memcpy_P ( & cmodule , & kModules [ Settings . module ] , sizeof ( cmodule ) ) ;
2017-06-06 22:23:23 +01:00
if ( ( GPIO_USER = = cmodule . gp . io [ index ] ) & & ( payload > = 0 ) & & ( payload < GPIO_SENSOR_END ) ) {
2017-01-28 13:41:01 +00:00
for ( byte i = 0 ; i < MAX_GPIO_PIN ; i + + ) {
2017-10-18 17:22:34 +01:00
if ( ( GPIO_USER = = cmodule . gp . io [ i ] ) & & ( Settings . my_gp . io [ i ] = = payload ) ) {
Settings . my_gp . io [ i ] = 0 ;
2017-04-25 17:24:42 +01:00
}
2017-01-28 13:41:01 +00:00
}
2017-10-18 17:22:34 +01:00
Settings . my_gp . io [ index ] = payload ;
restart_flag = 2 ;
2017-01-28 13:41:01 +00:00
}
2017-09-13 13:19:34 +01:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " { " ) ) ;
2017-01-28 13:41:01 +00:00
byte jsflg = 0 ;
for ( byte i = 0 ; i < MAX_GPIO_PIN ; i + + ) {
2017-04-25 17:24:42 +01:00
if ( GPIO_USER = = cmodule . gp . io [ i ] ) {
if ( jsflg ) {
2017-11-11 11:33:30 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " %s, " ) , mqtt_data ) ;
2017-04-25 17:24:42 +01:00
}
2017-01-28 13:41:01 +00:00
jsflg = 1 ;
2017-10-18 17:22:34 +01:00
snprintf_P ( stemp1 , sizeof ( stemp1 ) , kSensors [ Settings . my_gp . io [ i ] ] ) ;
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " %s \" " D_CMND_GPIO " %d \" : \" %d (%s) \" " ) , mqtt_data , i , Settings . my_gp . io [ i ] , stemp1 ) ;
2017-01-28 13:41:01 +00:00
}
}
if ( jsflg ) {
2017-09-13 13:19:34 +01:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " %s} " ) , mqtt_data ) ;
2017-01-28 13:41:01 +00:00
} else {
2018-01-06 16:34:42 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_SVALUE , command , D_JSON_NOT_SUPPORTED ) ;
2017-01-28 13:41:01 +00:00
}
}
2017-10-29 17:18:46 +00:00
else if ( CMND_GPIOS = = command_code ) {
2017-09-14 14:35:38 +01:00
for ( byte i = 0 ; i < GPIO_SENSOR_END ; i + + ) {
if ( ! jsflg ) {
2017-12-18 17:20:28 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " { \" " D_CMND_GPIOS " %d \" :[ " ) , lines ) ;
2017-09-14 14:35:38 +01:00
} else {
2017-11-11 11:33:30 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " %s, " ) , mqtt_data ) ;
2017-04-25 17:24:42 +01:00
}
2017-03-09 16:48:04 +00:00
jsflg = 1 ;
2017-10-18 17:22:34 +01:00
snprintf_P ( stemp1 , sizeof ( stemp1 ) , kSensors [ i ] ) ;
2017-12-18 17:20:28 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " %s \" %d (%s) \" " ) , mqtt_data , i , stemp1 ) ;
2018-01-18 15:19:28 +00:00
if ( ( strlen ( mqtt_data ) > ( LOGSZ - TOPSZ ) ) | | ( i = = GPIO_SENSOR_END - 1 ) ) {
2017-12-18 17:20:28 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " %s]} " ) , mqtt_data ) ;
2018-01-18 15:19:28 +00:00
MqttPublishPrefixTopic_P ( RESULT_OR_STAT , type ) ;
2017-09-14 14:35:38 +01:00
jsflg = 0 ;
lines + + ;
2017-04-25 17:24:42 +01:00
}
2017-01-28 13:41:01 +00:00
}
2017-09-14 14:35:38 +01:00
mqtt_data [ 0 ] = ' \0 ' ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( ( CMND_PWM = = command_code ) & & ! light_type & & ( index > 0 ) & & ( index < = MAX_PWMS ) ) {
2017-10-18 17:22:34 +01:00
if ( ( payload > = 0 ) & & ( payload < = Settings . pwm_range ) & & ( pin [ GPIO_PWM1 + index - 1 ] < 99 ) ) {
Settings . pwm_value [ index - 1 ] = payload ;
analogWrite ( pin [ GPIO_PWM1 + index - 1 ] , bitRead ( pwm_inverted , index - 1 ) ? Settings . pwm_range - payload : payload ) ;
2017-03-19 17:19:08 +00:00
}
2017-09-13 13:19:34 +01:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " { \" " D_CMND_PWM " \" :{ " ) ) ;
2017-03-19 17:19:08 +00:00
bool first = true ;
2017-10-10 14:40:02 +01:00
for ( byte i = 0 ; i < MAX_PWMS ; i + + ) {
2017-03-19 17:19:08 +00:00
if ( pin [ GPIO_PWM1 + i ] < 99 ) {
2017-11-11 11:33:30 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " %s%s \" " D_CMND_PWM " %d \" :%d " ) , mqtt_data , first ? " " : " , " , i + 1 , Settings . pwm_value [ i ] ) ;
2017-03-19 17:19:08 +00:00
first = false ;
}
}
2017-09-13 13:19:34 +01:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " %s}} " ) , mqtt_data ) ;
2017-03-19 17:19:08 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_PWMFREQUENCY = = command_code ) {
2017-10-18 17:22:34 +01:00
if ( ( 1 = = payload ) | | ( ( payload > = 100 ) & & ( payload < = 4000 ) ) ) {
Settings . pwm_frequency = ( 1 = = payload ) ? PWM_FREQ : payload ;
analogWriteFreq ( Settings . pwm_frequency ) ; // Default is 1000 (core_esp8266_wiring_pwm.c)
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_NVALUE , command , Settings . pwm_frequency ) ;
2017-10-18 17:22:34 +01:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_PWMRANGE = = command_code ) {
2017-10-18 17:22:34 +01:00
if ( ( 1 = = payload ) | | ( ( payload > 254 ) & & ( payload < 1024 ) ) ) {
Settings . pwm_range = ( 1 = = payload ) ? PWM_RANGE : payload ;
for ( byte i ; i < MAX_PWMS ; i + + ) {
if ( Settings . pwm_value [ i ] > Settings . pwm_range ) {
Settings . pwm_value [ i ] = Settings . pwm_range ;
}
}
analogWriteRange ( Settings . pwm_range ) ; // Default is 1023 (Arduino.h)
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_NVALUE , command , Settings . pwm_range ) ;
2017-10-18 17:22:34 +01:00
}
2017-10-29 17:18:46 +00:00
else if ( ( CMND_COUNTER = = command_code ) & & ( index > 0 ) & & ( index < = MAX_COUNTERS ) ) {
2017-05-17 21:49:22 +01:00
if ( ( data_len > 0 ) & & ( pin [ GPIO_CNTR1 + index - 1 ] < 99 ) ) {
2017-10-18 17:22:34 +01:00
RtcSettings . pulse_counter [ index - 1 ] = payload16 ;
Settings . pulse_counter [ index - 1 ] = payload16 ;
2017-05-17 21:49:22 +01:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_INDEX_NVALUE , command , index , RtcSettings . pulse_counter [ index - 1 ] ) ;
2017-05-17 21:49:22 +01:00
}
2017-10-29 17:18:46 +00:00
else if ( ( CMND_COUNTERTYPE = = command_code ) & & ( index > 0 ) & & ( index < = MAX_COUNTERS ) ) {
2017-06-06 22:23:23 +01:00
if ( ( payload > = 0 ) & & ( payload < = 1 ) & & ( pin [ GPIO_CNTR1 + index - 1 ] < 99 ) ) {
2017-10-18 17:22:34 +01:00
bitWrite ( Settings . pulse_counter_type , index - 1 , payload & 1 ) ;
RtcSettings . pulse_counter [ index - 1 ] = 0 ;
Settings . pulse_counter [ index - 1 ] = 0 ;
2017-05-17 21:49:22 +01:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_INDEX_NVALUE , command , index , bitRead ( Settings . pulse_counter_type , index - 1 ) ) ;
2017-05-17 21:49:22 +01:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_COUNTERDEBOUNCE = = command_code ) {
2017-06-19 21:54:49 +01:00
if ( ( data_len > 0 ) & & ( payload16 < 32001 ) ) {
2017-10-18 17:22:34 +01:00
Settings . pulse_counter_debounce = payload16 ;
2017-05-17 21:49:22 +01:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_NVALUE , command , Settings . pulse_counter_debounce ) ;
2017-05-17 21:49:22 +01:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_SLEEP = = command_code ) {
2017-06-06 22:23:23 +01:00
if ( ( payload > = 0 ) & & ( payload < 251 ) ) {
2017-10-18 17:22:34 +01:00
if ( ( ! Settings . sleep & & payload ) | | ( Settings . sleep & & ! payload ) ) {
restart_flag = 2 ;
2017-04-25 17:24:42 +01:00
}
2017-10-18 17:22:34 +01:00
Settings . sleep = payload ;
2017-01-29 13:52:31 +00:00
sleep = payload ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_NVALUE_UNIT_NVALUE_UNIT , command , sleep , ( Settings . flag . value_units ) ? " " D_UNIT_MILLISECOND : " " , Settings . sleep , ( Settings . flag . value_units ) ? " " D_UNIT_MILLISECOND : " " ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( ( CMND_UPGRADE = = command_code ) | | ( CMND_UPLOAD = = command_code ) ) {
2017-06-30 16:54:19 +01:00
// 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.
2017-10-18 17:22:34 +01:00
if ( ( ( 1 = = data_len ) & & ( 1 = = payload ) ) | | ( ( data_len > = 3 ) & & NewerVersion ( dataBuf ) ) ) {
ota_state_flag = 3 ;
2018-01-10 13:10:25 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , " { \" %s \" : \" " D_JSON_VERSION " %s " D_JSON_FROM " %s \" } " , command , my_version , Settings . ota_url ) ;
2017-01-28 13:41:01 +00:00
} else {
2018-01-10 13:10:25 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , " { \" %s \" : \" " D_JSON_ONE_OR_GT " \" } " , command , my_version ) ;
2017-01-28 13:41:01 +00:00
}
}
2017-10-29 17:18:46 +00:00
else if ( CMND_OTAURL = = command_code ) {
2017-10-18 17:22:34 +01:00
if ( ( data_len > 0 ) & & ( data_len < sizeof ( Settings . ota_url ) ) )
strlcpy ( Settings . ota_url , ( 1 = = payload ) ? OTA_URL : dataBuf , sizeof ( Settings . ota_url ) ) ;
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_SVALUE , command , Settings . ota_url ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_SERIALLOG = = command_code ) {
2017-06-06 22:23:23 +01:00
if ( ( payload > = LOG_LEVEL_NONE ) & & ( payload < = LOG_LEVEL_ALL ) ) {
2017-10-18 17:22:34 +01:00
Settings . seriallog_level = payload ;
2017-01-28 13:41:01 +00:00
seriallog_level = payload ;
seriallog_timer = 0 ;
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE , command , Settings . seriallog_level , seriallog_level ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_SYSLOG = = command_code ) {
2017-06-06 22:23:23 +01:00
if ( ( payload > = LOG_LEVEL_NONE ) & & ( payload < = LOG_LEVEL_ALL ) ) {
2017-10-18 17:22:34 +01:00
Settings . syslog_level = payload ;
2017-11-11 11:33:30 +00:00
syslog_level = ( Settings . flag2 . emulation ) ? 0 : payload ;
2017-01-28 13:41:01 +00:00
syslog_timer = 0 ;
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_NVALUE_ACTIVE_NVALUE , command , Settings . syslog_level , syslog_level ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_LOGHOST = = command_code ) {
2017-10-18 17:22:34 +01:00
if ( ( data_len > 0 ) & & ( data_len < sizeof ( Settings . syslog_host ) ) ) {
strlcpy ( Settings . syslog_host , ( 1 = = payload ) ? SYS_LOG_HOST : dataBuf , sizeof ( Settings . syslog_host ) ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_SVALUE , command , Settings . syslog_host ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_LOGPORT = = command_code ) {
2017-09-12 09:19:16 +01:00
if ( payload16 > 0 ) {
2017-10-18 17:22:34 +01:00
Settings . syslog_port = ( 1 = = payload16 ) ? SYS_LOG_PORT : payload16 ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_NVALUE , command , Settings . syslog_port ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( ( CMND_IPADDRESS = = command_code ) & & ( index > 0 ) & & ( index < = 4 ) ) {
2017-10-18 17:22:34 +01:00
if ( ParseIp ( & address , dataBuf ) ) {
Settings . ip_address [ index - 1 ] = address ;
// restart_flag = 2;
2017-03-25 16:24:11 +00:00
}
2017-03-29 17:42:05 +01:00
snprintf_P ( stemp1 , sizeof ( stemp1 ) , PSTR ( " (%s) " ) , WiFi . localIP ( ) . toString ( ) . c_str ( ) ) ;
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_INDEX_SVALUE_SVALUE , command , index , IPAddress ( Settings . ip_address [ index - 1 ] ) . toString ( ) . c_str ( ) , ( 1 = = index ) ? stemp1 : " " ) ;
2017-03-25 16:24:11 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( ( CMND_NTPSERVER = = command_code ) & & ( index > 0 ) & & ( index < = 3 ) ) {
2017-10-18 17:22:34 +01:00
if ( ( data_len > 0 ) & & ( data_len < sizeof ( Settings . ntp_server [ 0 ] ) ) ) {
strlcpy ( Settings . ntp_server [ index - 1 ] , ( ! strcmp ( dataBuf , " 0 " ) ) ? " " : ( 1 = = payload ) ? ( 1 = = index ) ? NTP_SERVER1 : ( 2 = = index ) ? NTP_SERVER2 : NTP_SERVER3 : dataBuf , sizeof ( Settings . ntp_server [ 0 ] ) ) ;
for ( i = 0 ; i < strlen ( Settings . ntp_server [ index - 1 ] ) ; i + + ) {
if ( Settings . ntp_server [ index - 1 ] [ i ] = = ' , ' ) {
Settings . ntp_server [ index - 1 ] [ i ] = ' . ' ;
2017-04-25 17:24:42 +01:00
}
}
2017-10-18 17:22:34 +01:00
restart_flag = 2 ;
2017-03-12 17:36:33 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_INDEX_SVALUE , command , index , Settings . ntp_server [ index - 1 ] ) ;
2017-03-12 17:36:33 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_AP = = command_code ) {
2017-06-06 22:23:23 +01:00
if ( ( payload > = 0 ) & & ( payload < = 2 ) ) {
2017-01-28 13:41:01 +00:00
switch ( payload ) {
case 0 : // Toggle
2017-10-18 17:22:34 +01:00
Settings . sta_active ^ = 1 ;
2017-01-28 13:41:01 +00:00
break ;
case 1 : // AP1
case 2 : // AP2
2017-10-18 17:22:34 +01:00
Settings . sta_active = payload - 1 ;
2017-01-28 13:41:01 +00:00
}
2017-10-18 17:22:34 +01:00
restart_flag = 2 ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_NVALUE_SVALUE , command , Settings . sta_active + 1 , Settings . sta_ssid [ Settings . sta_active ] ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( ( CMND_SSID = = command_code ) & & ( index > 0 ) & & ( index < = 2 ) ) {
2017-10-18 17:22:34 +01:00
if ( ( data_len > 0 ) & & ( data_len < sizeof ( Settings . sta_ssid [ 0 ] ) ) ) {
strlcpy ( Settings . sta_ssid [ index - 1 ] , ( 1 = = payload ) ? ( 1 = = index ) ? STA_SSID1 : STA_SSID2 : dataBuf , sizeof ( Settings . sta_ssid [ 0 ] ) ) ;
Settings . sta_active = index - 1 ;
restart_flag = 2 ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_INDEX_SVALUE , command , index , Settings . sta_ssid [ index - 1 ] ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( ( CMND_PASSWORD = = command_code ) & & ( index > 0 ) & & ( index < = 2 ) ) {
2017-10-18 17:22:34 +01:00
if ( ( data_len > 0 ) & & ( data_len < sizeof ( Settings . sta_pwd [ 0 ] ) ) ) {
strlcpy ( Settings . sta_pwd [ index - 1 ] , ( 1 = = payload ) ? ( 1 = = index ) ? STA_PASS1 : STA_PASS2 : dataBuf , sizeof ( Settings . sta_pwd [ 0 ] ) ) ;
Settings . sta_active = index - 1 ;
restart_flag = 2 ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_INDEX_SVALUE , command , index , Settings . sta_pwd [ index - 1 ] ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( ( CMND_HOSTNAME = = command_code ) & & ! grpflg ) {
2017-10-18 17:22:34 +01:00
if ( ( data_len > 0 ) & & ( data_len < sizeof ( Settings . hostname ) ) ) {
strlcpy ( Settings . hostname , ( 1 = = payload ) ? WIFI_HOSTNAME : dataBuf , sizeof ( Settings . hostname ) ) ;
if ( strstr ( Settings . hostname , " % " ) ) {
strlcpy ( Settings . hostname , WIFI_HOSTNAME , sizeof ( Settings . hostname ) ) ;
2017-04-25 17:24:42 +01:00
}
2017-10-18 17:22:34 +01:00
restart_flag = 2 ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_SVALUE , command , Settings . hostname ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_WIFICONFIG = = command_code ) {
2017-06-06 22:23:23 +01:00
if ( ( payload > = WIFI_RESTART ) & & ( payload < MAX_WIFI_OPTION ) ) {
2017-10-18 17:22:34 +01:00
Settings . sta_config = payload ;
wifi_state_flag = Settings . sta_config ;
snprintf_P ( stemp1 , sizeof ( stemp1 ) , kWifiConfig [ Settings . sta_config ] ) ;
2018-01-06 16:34:42 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " { \" " D_CMND_WIFICONFIG " \" : \" %s " D_JSON_SELECTED " \" } " ) , stemp1 ) ;
2017-10-18 17:22:34 +01:00
if ( WifiState ( ) ! = WIFI_RESTART ) {
2017-09-13 13:19:34 +01:00
// snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s after restart"), mqtt_data);
2017-10-18 17:22:34 +01:00
restart_flag = 2 ;
2017-01-28 13:41:01 +00:00
}
} else {
2017-10-18 17:22:34 +01:00
snprintf_P ( stemp1 , sizeof ( stemp1 ) , kWifiConfig [ Settings . sta_config ] ) ;
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_NVALUE_SVALUE , command , Settings . sta_config , stemp1 ) ;
2017-01-28 13:41:01 +00:00
}
}
2017-10-29 17:18:46 +00:00
else if ( ( CMND_FRIENDLYNAME = = command_code ) & & ( index > 0 ) & & ( index < = 4 ) ) {
2017-10-18 17:22:34 +01:00
if ( ( data_len > 0 ) & & ( data_len < sizeof ( Settings . friendlyname [ 0 ] ) ) ) {
2017-04-25 17:24:42 +01:00
if ( 1 = = index ) {
2017-01-29 20:36:12 +00:00
snprintf_P ( stemp1 , sizeof ( stemp1 ) , PSTR ( FRIENDLY_NAME ) ) ;
} else {
snprintf_P ( stemp1 , sizeof ( stemp1 ) , PSTR ( FRIENDLY_NAME " %d " ) , index ) ;
}
2017-10-18 17:22:34 +01:00
strlcpy ( Settings . friendlyname [ index - 1 ] , ( 1 = = payload ) ? stemp1 : dataBuf , sizeof ( Settings . friendlyname [ index - 1 ] ) ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_INDEX_SVALUE , command , index , Settings . friendlyname [ index - 1 ] ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( ( CMND_SWITCHMODE = = command_code ) & & ( index > 0 ) & & ( index < = MAX_SWITCHES ) ) {
2017-06-06 22:23:23 +01:00
if ( ( payload > = 0 ) & & ( payload < MAX_SWITCH_OPTION ) ) {
2017-10-18 17:22:34 +01:00
Settings . switchmode [ index - 1 ] = payload ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_INDEX_NVALUE , command , index , Settings . switchmode [ index - 1 ] ) ;
2017-01-28 13:41:01 +00:00
}
# ifdef USE_WEBSERVER
2017-10-29 17:18:46 +00:00
else if ( CMND_WEBSERVER = = command_code ) {
2017-06-06 22:23:23 +01:00
if ( ( payload > = 0 ) & & ( payload < = 2 ) ) {
2017-10-18 17:22:34 +01:00
Settings . webserver = payload ;
2017-01-28 13:41:01 +00:00
}
2017-10-18 17:22:34 +01:00
if ( Settings . webserver ) {
2018-01-06 16:34:42 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " { \" " D_CMND_WEBSERVER " \" : \" " D_JSON_ACTIVE_FOR " %s " D_JSON_ON_DEVICE " %s " D_JSON_WITH_IP_ADDRESS " %s \" } " ) ,
2017-10-18 17:22:34 +01:00
( 2 = = Settings . webserver ) ? D_ADMIN : D_USER , my_hostname , WiFi . localIP ( ) . toString ( ) . c_str ( ) ) ;
2017-01-28 13:41:01 +00:00
} else {
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_SVALUE , command , GetStateText ( 0 ) ) ;
2017-01-28 13:41:01 +00:00
}
}
2017-10-29 17:18:46 +00:00
else if ( CMND_WEBPASSWORD = = command_code ) {
2017-10-18 17:22:34 +01:00
if ( ( data_len > 0 ) & & ( data_len < sizeof ( Settings . web_password ) ) ) {
strlcpy ( Settings . web_password , ( ! strcmp ( dataBuf , " 0 " ) ) ? " " : ( 1 = = payload ) ? WEB_PASSWORD : dataBuf , sizeof ( Settings . web_password ) ) ;
2017-02-21 17:14:33 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_SVALUE , command , Settings . web_password ) ;
2017-02-21 17:14:33 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_WEBLOG = = command_code ) {
2017-06-06 22:23:23 +01:00
if ( ( payload > = LOG_LEVEL_NONE ) & & ( payload < = LOG_LEVEL_ALL ) ) {
2017-10-18 17:22:34 +01:00
Settings . weblog_level = payload ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_NVALUE , command , Settings . weblog_level ) ;
2017-01-28 13:41:01 +00:00
}
2017-01-29 20:36:12 +00:00
# ifdef USE_EMULATION
2017-10-29 17:18:46 +00:00
else if ( CMND_EMULATION = = command_code ) {
2017-09-26 14:10:58 +01:00
if ( ( payload > = EMUL_NONE ) & & ( payload < EMUL_MAX ) ) {
2017-11-11 11:33:30 +00:00
Settings . flag2 . emulation = payload ;
2017-10-18 17:22:34 +01:00
restart_flag = 2 ;
2017-01-29 20:36:12 +00:00
}
2017-11-11 11:33:30 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_NVALUE , command , Settings . flag2 . emulation ) ;
2017-01-29 20:36:12 +00:00
}
# endif // USE_EMULATION
2017-01-28 13:41:01 +00:00
# endif // USE_WEBSERVER
2017-10-29 17:18:46 +00:00
else if ( CMND_TELEPERIOD = = command_code ) {
2017-06-06 22:23:23 +01:00
if ( ( payload > = 0 ) & & ( payload < 3601 ) ) {
2017-10-18 17:22:34 +01:00
Settings . tele_period = ( 1 = = payload ) ? TELE_PERIOD : payload ;
if ( ( Settings . tele_period > 0 ) & & ( Settings . tele_period < 10 ) ) {
Settings . tele_period = 10 ; // Do not allow periods < 10 seconds
2017-04-25 17:24:42 +01:00
}
2017-10-18 17:22:34 +01:00
tele_period = Settings . tele_period ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_NVALUE_UNIT , command , Settings . tele_period , ( Settings . flag . value_units ) ? " " D_UNIT_SECOND : " " ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_RESTART = = command_code ) {
2017-01-28 13:41:01 +00:00
switch ( payload ) {
case 1 :
2017-10-18 17:22:34 +01:00
restart_flag = 2 ;
2018-01-06 16:34:42 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_SVALUE , command , D_JSON_RESTARTING ) ;
2017-01-28 13:41:01 +00:00
break ;
case 99 :
2017-10-18 17:22:34 +01:00
AddLog_P ( LOG_LEVEL_INFO , PSTR ( D_LOG_APPLICATION D_RESTARTING ) ) ;
2017-01-28 13:41:01 +00:00
ESP . restart ( ) ;
break ;
default :
2018-01-06 16:34:42 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_SVALUE , command , D_JSON_ONE_TO_RESTART ) ;
2017-01-28 13:41:01 +00:00
}
}
2017-10-29 17:18:46 +00:00
else if ( CMND_RESET = = command_code ) {
2017-01-28 13:41:01 +00:00
switch ( payload ) {
case 1 :
2017-10-18 17:22:34 +01:00
restart_flag = 211 ;
2018-01-06 16:34:42 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_SVALUE , command , D_JSON_RESET_AND_RESTARTING ) ;
2017-01-28 13:41:01 +00:00
break ;
case 2 :
2017-10-18 17:22:34 +01:00
restart_flag = 212 ;
2018-01-06 16:34:42 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " { \" " D_CMND_RESET " \" : \" " D_JSON_ERASE " , " D_JSON_RESET_AND_RESTARTING " \" } " ) ) ;
2017-01-28 13:41:01 +00:00
break ;
default :
2018-01-06 16:34:42 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_SVALUE , command , D_JSON_ONE_TO_RESET ) ;
2017-01-28 13:41:01 +00:00
}
}
2017-10-29 17:18:46 +00:00
else if ( CMND_TIMEZONE = = command_code ) {
2017-10-05 13:10:42 +01:00
if ( ( data_len > 0 ) & & ( ( ( payload > = - 13 ) & & ( payload < = 13 ) ) | | ( 99 = = payload ) ) ) {
2017-10-18 17:22:34 +01:00
Settings . timezone = payload ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_NVALUE , command , Settings . timezone ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_ALTITUDE = = command_code ) {
2017-10-08 15:51:05 +01:00
if ( ( data_len > 0 ) & & ( ( payload > = - 30000 ) & & ( payload < = 30000 ) ) ) {
2017-10-18 17:22:34 +01:00
Settings . altitude = payload ;
2017-10-08 15:51:05 +01:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_NVALUE , command , Settings . altitude ) ;
2017-10-08 15:51:05 +01:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_LEDPOWER = = command_code ) {
2017-06-06 22:23:23 +01:00
if ( ( payload > = 0 ) & & ( payload < = 2 ) ) {
2017-10-18 17:22:34 +01:00
Settings . ledstate & = 8 ;
2017-01-28 13:41:01 +00:00
switch ( payload ) {
case 0 : // Off
case 1 : // On
2017-10-18 17:22:34 +01:00
Settings . ledstate = payload < < 3 ;
2017-01-28 13:41:01 +00:00
break ;
case 2 : // Toggle
2017-10-18 17:22:34 +01:00
Settings . ledstate ^ = 8 ;
2017-01-28 13:41:01 +00:00
break ;
}
blinks = 0 ;
2017-10-18 17:22:34 +01:00
SetLedPower ( Settings . ledstate & 8 ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_SVALUE , command , GetStateText ( bitRead ( Settings . ledstate , 3 ) ) ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_LEDSTATE = = command_code ) {
2017-06-06 22:23:23 +01:00
if ( ( payload > = 0 ) & & ( payload < MAX_LED_OPTION ) ) {
2017-10-18 17:22:34 +01:00
Settings . ledstate = payload ;
if ( ! Settings . ledstate ) {
SetLedPower ( 0 ) ;
2017-04-25 17:24:42 +01:00
}
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_NVALUE , command , Settings . ledstate ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-29 17:18:46 +00:00
else if ( CMND_CFGDUMP = = command_code ) {
2017-10-18 17:22:34 +01:00
SettingsDump ( dataBuf ) ;
2017-12-29 13:35:05 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_SVALUE , command , D_JSON_DONE ) ;
2017-01-28 13:41:01 +00:00
}
2017-11-11 11:33:30 +00:00
# ifdef USE_I2C
else if ( ( CMND_I2CSCAN = = command_code ) & & i2c_flg ) {
I2cScan ( mqtt_data , sizeof ( mqtt_data ) ) ;
}
# endif // USE_I2C
2017-10-18 17:22:34 +01:00
else if ( Settings . flag . mqtt_enabled & & MqttCommand ( grpflg , type , index , dataBuf , data_len , payload , payload16 ) ) {
2017-01-28 15:31:11 +00:00
// Serviced
2017-01-28 13:41:01 +00:00
}
2018-01-05 11:26:19 +00:00
else if ( XdrvCommand ( type , index , dataBuf , data_len , payload ) ) {
2017-02-14 13:27:08 +00:00
// Serviced
}
2017-02-28 15:01:48 +00:00
# ifdef DEBUG_THEO
2017-10-29 17:18:46 +00:00
else if ( CMND_EXCEPTION = = command_code ) {
2017-04-25 17:24:42 +01:00
if ( data_len > 0 ) {
2017-10-18 17:22:34 +01:00
ExceptionTest ( payload ) ;
2017-04-25 17:24:42 +01:00
}
2017-12-29 13:35:05 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , S_JSON_COMMAND_SVALUE , command , D_JSON_DONE ) ;
2017-02-28 15:01:48 +00:00
}
# endif // DEBUG_THEO
2017-01-28 13:41:01 +00:00
else {
type = NULL ;
}
}
if ( type = = NULL ) {
blinks = 201 ;
2018-01-06 16:34:42 +00:00
snprintf_P ( topicBuf , sizeof ( topicBuf ) , PSTR ( D_JSON_COMMAND ) ) ;
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " { \" " D_JSON_COMMAND " \" : \" " D_JSON_UNKNOWN " \" } " ) ) ;
2017-04-03 15:38:15 +01:00
type = ( char * ) topicBuf ;
2017-01-28 13:41:01 +00:00
}
2017-09-13 13:19:34 +01:00
if ( mqtt_data [ 0 ] ! = ' \0 ' ) {
2018-01-18 15:19:28 +00:00
MqttPublishPrefixTopic_P ( RESULT_OR_STAT , type ) ;
2017-05-17 21:49:22 +01:00
}
2017-10-18 17:22:34 +01:00
fallback_topic_flag = 0 ;
2017-01-28 13:41:01 +00:00
}
/********************************************************************************************/
2017-06-06 22:23:23 +01:00
boolean send_button_power ( byte key , byte device , byte state )
2017-01-28 13:41:01 +00:00
{
// key 0 = button_topic
// key 1 = switch_topic
2017-06-06 22:23:23 +01:00
// state 0 = off
// state 1 = on
// state 2 = toggle
// state 3 = hold
// state 9 = clear retain flag
2017-01-28 13:41:01 +00:00
2017-04-25 17:24:42 +01:00
char stopic [ TOPSZ ] ;
2017-05-08 12:21:45 +01:00
char scommand [ CMDSZ ] ;
2017-04-25 17:24:42 +01:00
char stemp1 [ 10 ] ;
2017-06-06 22:23:23 +01:00
boolean result = false ;
2017-01-28 13:41:01 +00:00
2017-10-18 17:22:34 +01:00
char * key_topic = ( key ) ? Settings . switch_topic : Settings . button_topic ;
if ( Settings . flag . mqtt_enabled & & MqttClient . connected ( ) & & ( strlen ( key_topic ) ! = 0 ) & & strcmp ( key_topic , " 0 " ) ) {
if ( ! key & & ( device > devices_present ) ) {
2017-06-06 22:23:23 +01:00
device = 1 ;
}
2018-01-18 15:19:28 +00:00
GetTopic_P ( stopic , CMND , key_topic , GetPowerDevice ( scommand , device , sizeof ( scommand ) , key ) ) ;
2017-06-06 22:23:23 +01:00
if ( 9 = = state ) {
2017-09-13 13:19:34 +01:00
mqtt_data [ 0 ] = ' \0 ' ;
2017-06-06 22:23:23 +01:00
} else {
2017-10-18 17:22:34 +01:00
if ( ( ! strcmp ( Settings . mqtt_topic , key_topic ) | | ! strcmp ( Settings . mqtt_grptopic , key_topic ) ) & & ( 2 = = state ) ) {
2017-10-10 14:40:02 +01:00
state = ~ ( power > > ( device - 1 ) ) & 1 ;
2017-06-06 22:23:23 +01:00
}
2017-10-18 17:22:34 +01:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , GetStateText ( state ) ) ;
2017-01-28 13:41:01 +00:00
}
# ifdef USE_DOMOTICZ
2017-10-18 17:22:34 +01:00
if ( ! ( DomoticzButton ( key , device , state , strlen ( mqtt_data ) ) ) ) {
MqttPublishDirect ( stopic , ( key ) ? Settings . flag . mqtt_switch_retain : Settings . flag . mqtt_button_retain ) ;
2017-06-06 22:23:23 +01:00
}
2017-01-28 13:41:01 +00:00
# else
2017-10-18 17:22:34 +01:00
MqttPublishDirect ( stopic , ( key ) ? Settings . flag . mqtt_switch_retain : Settings . flag . mqtt_button_retain ) ;
2017-01-28 13:41:01 +00:00
# endif // USE_DOMOTICZ
2017-06-06 22:23:23 +01:00
result = true ;
}
return result ;
2017-01-28 13:41:01 +00:00
}
2017-10-18 17:22:34 +01:00
void ExecuteCommandPower ( byte device , byte state )
2017-01-28 13:41:01 +00:00
{
// device = Relay number 1 and up
// state 0 = Relay Off
2017-10-18 17:22:34 +01:00
// state 1 = Relay On (turn off after Settings.pulse_timer * 100 mSec if enabled)
2017-01-28 13:41:01 +00:00
// state 2 = Toggle relay
// state 3 = Blink relay
// state 4 = Stop blinking relay
2017-07-15 14:07:30 +01:00
// state 6 = Relay Off and no publishPowerState
// state 7 = Relay On and no publishPowerState
2017-01-28 13:41:01 +00:00
// state 9 = Show power state
2017-10-18 17:22:34 +01:00
uint8_t publish_power = 1 ;
2018-01-24 16:31:20 +00:00
if ( ( POWER_OFF_NO_STATE = = state ) | | ( POWER_ON_NO_STATE = = state ) ) {
2017-07-15 14:07:30 +01:00
state & = 1 ;
2017-10-18 17:22:34 +01:00
publish_power = 0 ;
2017-07-15 14:07:30 +01:00
}
2017-10-18 17:22:34 +01:00
if ( ( device < 1 ) | | ( device > devices_present ) ) {
2017-04-25 17:24:42 +01:00
device = 1 ;
}
2017-10-10 14:40:02 +01:00
if ( device < = MAX_PULSETIMERS ) {
pulse_timer [ ( device - 1 ) ] = 0 ;
}
power_t mask = 1 < < ( device - 1 ) ;
2018-01-24 16:31:20 +00:00
if ( state < = POWER_TOGGLE ) {
2017-01-28 13:41:01 +00:00
if ( ( blink_mask & mask ) ) {
2017-10-10 14:40:02 +01:00
blink_mask & = ( POWER_MASK ^ mask ) ; // Clear device mask
2017-10-18 17:22:34 +01:00
MqttPublishPowerBlinkState ( device ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-18 17:22:34 +01:00
if ( Settings . flag . interlock & & ! interlock_mutex ) { // Clear all but masked relay
interlock_mutex = 1 ;
for ( byte i = 0 ; i < devices_present ; i + + ) {
2017-10-10 14:40:02 +01:00
power_t imask = 1 < < i ;
2017-08-18 11:55:08 +01:00
if ( ( power & imask ) & & ( mask ! = imask ) ) {
2018-01-24 16:31:20 +00:00
ExecuteCommandPower ( i + 1 , POWER_OFF ) ;
2017-08-18 11:55:08 +01:00
}
}
2017-10-18 17:22:34 +01:00
interlock_mutex = 0 ;
2017-08-18 11:55:08 +01:00
}
2017-01-28 13:41:01 +00:00
switch ( state ) {
2018-01-24 16:31:20 +00:00
case POWER_OFF : {
2017-10-10 14:40:02 +01:00
power & = ( POWER_MASK ^ mask ) ;
2017-01-28 13:41:01 +00:00
break ; }
2018-01-24 16:31:20 +00:00
case POWER_ON :
2017-01-28 13:41:01 +00:00
power | = mask ;
break ;
2018-01-24 16:31:20 +00:00
case POWER_TOGGLE :
2017-01-28 13:41:01 +00:00
power ^ = mask ;
}
2017-10-18 17:22:34 +01:00
SetDevicePower ( power ) ;
2017-01-28 13:41:01 +00:00
# ifdef USE_DOMOTICZ
2017-10-18 17:22:34 +01:00
DomoticzUpdatePowerState ( device ) ;
2017-01-28 13:41:01 +00:00
# endif // USE_DOMOTICZ
2017-10-10 14:40:02 +01:00
if ( device < = MAX_PULSETIMERS ) {
2018-01-13 14:53:02 +00:00
// pulse_timer[(device -1)] = (power & mask) ? Settings.pulse_timer[(device -1)] : 0;
2018-01-24 16:31:20 +00:00
pulse_timer [ ( device - 1 ) ] = ( ( ( POWER_ALL_OFF_PULSETIME_ON = = Settings . poweronstate ) ? ~ power : power ) & mask ) ? Settings . pulse_timer [ ( device - 1 ) ] : 0 ;
2017-10-10 14:40:02 +01:00
}
2017-01-28 13:41:01 +00:00
}
2018-01-24 16:31:20 +00:00
else if ( POWER_BLINK = = state ) {
2017-01-28 13:41:01 +00:00
if ( ! ( blink_mask & mask ) ) {
2017-10-10 14:40:02 +01:00
blink_powersave = ( blink_powersave & ( POWER_MASK ^ mask ) ) | ( power & mask ) ; // Save state
2017-01-28 13:41:01 +00:00
blink_power = ( power > > ( device - 1 ) ) & 1 ; // Prep to Toggle
}
blink_timer = 1 ;
2017-10-18 17:22:34 +01:00
blink_counter = ( ( ! Settings . blinkcount ) ? 64000 : ( Settings . blinkcount * 2 ) ) + 1 ;
2017-01-28 13:41:01 +00:00
blink_mask | = mask ; // Set device mask
2017-10-18 17:22:34 +01:00
MqttPublishPowerBlinkState ( device ) ;
2017-01-28 13:41:01 +00:00
return ;
}
2018-01-24 16:31:20 +00:00
else if ( POWER_BLINK_STOP = = state ) {
2017-01-28 13:41:01 +00:00
byte flag = ( blink_mask & mask ) ;
2017-10-10 14:40:02 +01:00
blink_mask & = ( POWER_MASK ^ mask ) ; // Clear device mask
2017-10-18 17:22:34 +01:00
MqttPublishPowerBlinkState ( device ) ;
2017-04-25 17:24:42 +01:00
if ( flag ) {
2017-10-18 17:22:34 +01:00
ExecuteCommandPower ( device , ( blink_powersave > > ( device - 1 ) ) & 1 ) ; // Restore state
2017-04-25 17:24:42 +01:00
}
2017-01-28 13:41:01 +00:00
return ;
}
2017-10-18 17:22:34 +01:00
if ( publish_power ) {
MqttPublishPowerState ( device ) ;
2017-07-15 14:07:30 +01:00
}
2017-01-28 13:41:01 +00:00
}
2017-10-18 17:22:34 +01:00
void StopAllPowerBlink ( )
2017-01-28 13:41:01 +00:00
{
2017-10-10 14:40:02 +01:00
power_t mask ;
2017-01-28 13:41:01 +00:00
2017-10-18 17:22:34 +01:00
for ( byte i = 1 ; i < = devices_present ; i + + ) {
2017-10-10 14:40:02 +01:00
mask = 1 < < ( i - 1 ) ;
2017-01-28 13:41:01 +00:00
if ( blink_mask & mask ) {
2017-10-10 14:40:02 +01:00
blink_mask & = ( POWER_MASK ^ mask ) ; // Clear device mask
2017-10-18 17:22:34 +01:00
MqttPublishPowerBlinkState ( i ) ;
ExecuteCommandPower ( i , ( blink_powersave > > ( i - 1 ) ) & 1 ) ; // Restore state
2017-01-28 13:41:01 +00:00
}
}
}
2017-10-18 17:22:34 +01:00
void ExecuteCommand ( char * cmnd )
2017-01-28 13:41:01 +00:00
{
2017-05-08 12:21:45 +01:00
char stopic [ CMDSZ ] ;
2017-07-15 14:07:30 +01:00
char svalue [ INPUT_BUFFER_SIZE ] ;
2017-01-28 13:41:01 +00:00
char * start ;
char * token ;
token = strtok ( cmnd , " " ) ;
if ( token ! = NULL ) {
start = strrchr ( token , ' / ' ) ; // Skip possible cmnd/sonoff/ preamble
2017-04-25 17:24:42 +01:00
if ( start ) {
2017-05-08 12:21:45 +01:00
token = start + 1 ;
2017-04-25 17:24:42 +01:00
}
2017-01-28 13:41:01 +00:00
}
2017-05-11 16:47:34 +01:00
snprintf_P ( stopic , sizeof ( stopic ) , PSTR ( " /%s " ) , ( token = = NULL ) ? " " : token ) ;
2017-01-28 13:41:01 +00:00
token = strtok ( NULL , " " ) ;
2017-09-26 14:10:58 +01:00
// snprintf_P(svalue, sizeof(svalue), (token == NULL) ? "" : token); // Fails with command FullTopic home/%prefix%/%topic% as it processes %p of %prefix%
strlcpy ( svalue , ( token = = NULL ) ? " " : token , sizeof ( svalue ) ) ; // Fixed 5.8.0b
2017-10-18 17:22:34 +01:00
MqttDataCallback ( stopic , ( byte * ) svalue , strlen ( svalue ) ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-18 17:22:34 +01:00
void PublishStatus ( uint8_t payload )
2017-01-28 13:41:01 +00:00
{
2017-05-10 13:19:36 +01:00
uint8_t option = 1 ;
2017-01-28 13:41:01 +00:00
// Workaround MQTT - TCP/IP stack queueing when SUB_PREFIX = PUB_PREFIX
2017-10-18 17:22:34 +01:00
if ( ! strcmp ( Settings . mqtt_prefix [ 0 ] , Settings . mqtt_prefix [ 1 ] ) & & ( ! payload ) ) {
2017-05-10 13:19:36 +01:00
option + + ;
}
2017-01-28 13:41:01 +00:00
2017-10-18 17:22:34 +01:00
if ( ( ! Settings . flag . mqtt_enabled ) & & ( 6 = = payload ) ) {
2017-04-25 17:24:42 +01:00
payload = 99 ;
}
2017-12-16 14:51:45 +00:00
if ( ! energy_flg & & ( 9 = = payload ) ) {
2017-04-25 17:24:42 +01:00
payload = 99 ;
}
2017-01-28 13:41:01 +00:00
2017-04-25 17:24:42 +01:00
if ( ( 0 = = payload ) | | ( 99 = = payload ) ) {
2018-01-06 16:34:42 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " { \" " D_CMND_STATUS " \" :{ \" " D_CMND_MODULE " \" :%d, \" " D_CMND_FRIENDLYNAME " \" : \" %s \" , \" " D_CMND_TOPIC " \" : \" %s \" , \" " D_CMND_BUTTONTOPIC " \" : \" %s \" , \" " D_CMND_POWER " \" :%d, \" " D_CMND_POWERONSTATE " \" :%d, \" " D_CMND_LEDSTATE " \" :%d, \" " D_CMND_SAVEDATA " \" :%d, \" " D_JSON_SAVESTATE " \" :%d, \" " D_CMND_BUTTONRETAIN " \" :%d, \" " D_CMND_POWERRETAIN " \" :%d}} " ) ,
2017-10-18 17:22:34 +01:00
Settings . module + 1 , Settings . friendlyname [ 0 ] , Settings . mqtt_topic , Settings . button_topic , power , Settings . poweronstate , Settings . ledstate , Settings . save_data , Settings . flag . save_state , Settings . flag . mqtt_button_retain , Settings . flag . mqtt_power_retain ) ;
MqttPublishPrefixTopic_P ( option , PSTR ( D_CMND_STATUS ) ) ;
2017-01-28 13:41:01 +00:00
}
2017-04-25 17:24:42 +01:00
if ( ( 0 = = payload ) | | ( 1 = = payload ) ) {
2018-01-06 16:34:42 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " { \" " D_CMND_STATUS D_STATUS1_PARAMETER " \" :{ \" " D_JSON_BAUDRATE " \" :%d, \" " D_CMND_GROUPTOPIC " \" : \" %s \" , \" " D_CMND_OTAURL " \" : \" %s \" , \" " D_JSON_UPTIME " \" :%d, \" " D_CMND_SLEEP " \" :%d, \" " D_JSON_BOOTCOUNT " \" :%d, \" " D_JSON_SAVECOUNT " \" :%d, \" " D_JSON_SAVEADDRESS " \" : \" %X \" }} " ) ,
2017-10-18 17:22:34 +01:00
baudrate , Settings . mqtt_grptopic , Settings . ota_url , uptime , Settings . sleep , Settings . bootcount , Settings . save_flag , GetSettingsAddress ( ) ) ;
MqttPublishPrefixTopic_P ( option , PSTR ( D_CMND_STATUS " 1 " ) ) ;
2017-01-28 13:41:01 +00:00
}
2017-04-25 17:24:42 +01:00
if ( ( 0 = = payload ) | | ( 2 = = payload ) ) {
2018-01-10 13:10:25 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " { \" " D_CMND_STATUS D_STATUS2_FIRMWARE " \" :{ \" " D_JSON_VERSION " \" : \" %s \" , \" " D_JSON_BUILDDATETIME " \" : \" %s \" , \" " D_JSON_BOOTVERSION " \" :%d, \" " D_JSON_COREVERSION " \" : \" " ARDUINO_ESP8266_RELEASE " \" , \" " D_JSON_SDKVERSION " \" : \" %s \" }} " ) ,
my_version , GetBuildDateAndTime ( ) . c_str ( ) , ESP . getBootVersion ( ) , ESP . getSdkVersion ( ) ) ;
2017-10-18 17:22:34 +01:00
MqttPublishPrefixTopic_P ( option , PSTR ( D_CMND_STATUS " 2 " ) ) ;
2017-01-28 13:41:01 +00:00
}
2017-04-25 17:24:42 +01:00
if ( ( 0 = = payload ) | | ( 3 = = payload ) ) {
2017-11-11 11:33:30 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " { \" " D_CMND_STATUS D_STATUS3_LOGGING " \" :{ \" " D_CMND_SERIALLOG " \" :%d, \" " D_CMND_WEBLOG " \" :%d, \" " D_CMND_SYSLOG " \" :%d, \" " D_CMND_LOGHOST " \" : \" %s \" , \" " D_CMND_LOGPORT " \" :%d, \" " D_CMND_SSID " 1 \" : \" %s \" , \" " D_CMND_SSID " 2 \" : \" %s \" , \" " D_CMND_TELEPERIOD " \" :%d, \" " D_CMND_SETOPTION " \" : \" %08X \" }} " ) ,
2017-10-18 17:22:34 +01:00
Settings . seriallog_level , Settings . weblog_level , Settings . syslog_level , Settings . syslog_host , Settings . syslog_port , Settings . sta_ssid [ 0 ] , Settings . sta_ssid [ 1 ] , Settings . tele_period , Settings . flag . data ) ;
MqttPublishPrefixTopic_P ( option , PSTR ( D_CMND_STATUS " 3 " ) ) ;
2017-01-28 13:41:01 +00:00
}
2017-04-25 17:24:42 +01:00
if ( ( 0 = = payload ) | | ( 4 = = payload ) ) {
2018-01-06 16:34:42 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " { \" " D_CMND_STATUS D_STATUS4_MEMORY " \" :{ \" " D_JSON_PROGRAMSIZE " \" :%d, \" " D_JSON_FREEMEMORY " \" :%d, \" " D_JSON_HEAPSIZE " \" :%d, \" " D_JSON_PROGRAMFLASHSIZE " \" :%d, \" " D_JSON_FLASHSIZE " \" :%d, \" " D_JSON_FLASHMODE " \" :%d}} " ) ,
2017-04-25 17:24:42 +01:00
ESP . getSketchSize ( ) / 1024 , ESP . getFreeSketchSpace ( ) / 1024 , ESP . getFreeHeap ( ) / 1024 , ESP . getFlashChipSize ( ) / 1024 , ESP . getFlashChipRealSize ( ) / 1024 , ESP . getFlashChipMode ( ) ) ;
2017-10-18 17:22:34 +01:00
MqttPublishPrefixTopic_P ( option , PSTR ( D_CMND_STATUS " 4 " ) ) ;
2017-01-28 13:41:01 +00:00
}
2017-04-25 17:24:42 +01:00
if ( ( 0 = = payload ) | | ( 5 = = payload ) ) {
2018-01-06 16:34:42 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " { \" " D_CMND_STATUS D_STATUS5_NETWORK " \" :{ \" " D_CMND_HOSTNAME " \" : \" %s \" , \" " D_CMND_IPADDRESS " \" : \" %s \" , \" " D_JSON_GATEWAY " \" : \" %s \" , \" " D_JSON_SUBNETMASK " \" : \" %s \" , \" " D_JSON_DNSSERVER " \" : \" %s \" , \" " D_JSON_MAC " \" : \" %s \" , \" " D_CMND_WEBSERVER " \" :%d, \" " D_CMND_WIFICONFIG " \" :%d}} " ) ,
2017-10-18 17:22:34 +01:00
my_hostname , WiFi . localIP ( ) . toString ( ) . c_str ( ) , IPAddress ( Settings . ip_address [ 1 ] ) . toString ( ) . c_str ( ) , IPAddress ( Settings . ip_address [ 2 ] ) . toString ( ) . c_str ( ) , IPAddress ( Settings . ip_address [ 3 ] ) . toString ( ) . c_str ( ) ,
WiFi . macAddress ( ) . c_str ( ) , Settings . webserver , Settings . sta_config ) ;
MqttPublishPrefixTopic_P ( option , PSTR ( D_CMND_STATUS " 5 " ) ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-18 17:22:34 +01:00
if ( ( ( 0 = = payload ) | | ( 6 = = payload ) ) & & Settings . flag . mqtt_enabled ) {
2018-01-06 16:34:42 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " { \" " D_CMND_STATUS D_STATUS6_MQTT " \" :{ \" " D_CMND_MQTTHOST " \" : \" %s \" , \" " D_CMND_MQTTPORT " \" :%d, \" " D_CMND_MQTTCLIENT D_JSON_MASK " \" : \" %s \" , \" " D_CMND_MQTTCLIENT " \" : \" %s \" , \" " D_CMND_MQTTUSER " \" : \" %s \" , \" MAX_PACKET_SIZE \" :%d, \" KEEPALIVE \" :%d}} " ) ,
2017-10-18 17:22:34 +01:00
Settings . mqtt_host , Settings . mqtt_port , Settings . mqtt_client , mqtt_client , Settings . mqtt_user , MQTT_MAX_PACKET_SIZE , MQTT_KEEPALIVE ) ;
MqttPublishPrefixTopic_P ( option , PSTR ( D_CMND_STATUS " 6 " ) ) ;
2017-01-28 13:41:01 +00:00
}
2017-04-25 17:24:42 +01:00
if ( ( 0 = = payload ) | | ( 7 = = payload ) ) {
2018-01-06 16:34:42 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " { \" " D_CMND_STATUS D_STATUS7_TIME " \" :{ \" " D_JSON_UTC_TIME " \" : \" %s \" , \" " D_JSON_LOCAL_TIME " \" : \" %s \" , \" " D_JSON_STARTDST " \" : \" %s \" , \" " D_JSON_ENDDST " \" : \" %s \" , \" " D_CMND_TIMEZONE " \" :%d}} " ) ,
2017-10-18 17:22:34 +01:00
GetTime ( 0 ) . c_str ( ) , GetTime ( 1 ) . c_str ( ) , GetTime ( 2 ) . c_str ( ) , GetTime ( 3 ) . c_str ( ) , Settings . timezone ) ;
MqttPublishPrefixTopic_P ( option , PSTR ( D_CMND_STATUS " 7 " ) ) ;
2017-02-04 16:09:54 +00:00
}
2017-12-16 14:51:45 +00:00
if ( energy_flg ) {
2017-04-25 17:24:42 +01:00
if ( ( 0 = = payload ) | | ( 9 = = payload ) ) {
2017-11-11 11:33:30 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " { \" " D_CMND_STATUS D_STATUS9_MARGIN " \" :{ \" " D_CMND_POWERLOW " \" :%d, \" " D_CMND_POWERHIGH " \" :%d, \" " D_CMND_VOLTAGELOW " \" :%d, \" " D_CMND_VOLTAGEHIGH " \" :%d, \" " D_CMND_CURRENTLOW " \" :%d, \" " D_CMND_CURRENTHIGH " \" :%d}} " ) ,
2017-12-16 14:51:45 +00:00
Settings . energy_min_power , Settings . energy_max_power , Settings . energy_min_voltage , Settings . energy_max_voltage , Settings . energy_min_current , Settings . energy_max_current ) ;
2017-10-18 17:22:34 +01:00
MqttPublishPrefixTopic_P ( option , PSTR ( D_CMND_STATUS " 9 " ) ) ;
2017-02-04 16:09:54 +00:00
}
}
2017-12-16 14:51:45 +00:00
if ( ( 0 = = payload ) | | ( 8 = = payload ) | | ( 10 = = payload ) ) {
2017-09-13 13:19:34 +01:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " { \" " D_CMND_STATUS D_STATUS10_SENSOR " \" : " ) ) ;
2017-11-03 17:07:25 +00:00
MqttShowSensor ( ) ;
2017-09-13 13:19:34 +01:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " %s} " ) , mqtt_data ) ;
2017-12-16 14:51:45 +00:00
if ( 8 = = payload ) {
MqttPublishPrefixTopic_P ( option , PSTR ( D_CMND_STATUS " 8 " ) ) ;
} else {
MqttPublishPrefixTopic_P ( option , PSTR ( D_CMND_STATUS " 10 " ) ) ;
}
2017-01-28 13:41:01 +00:00
}
2017-03-14 17:03:25 +00:00
2017-04-25 17:24:42 +01:00
if ( ( 0 = = payload ) | | ( 11 = = payload ) ) {
2017-09-13 13:19:34 +01:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " { \" " D_CMND_STATUS D_STATUS11_STATUS " \" : " ) ) ;
2017-10-18 17:22:34 +01:00
MqttShowState ( ) ;
2017-09-13 13:19:34 +01:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " %s} " ) , mqtt_data ) ;
2017-10-18 17:22:34 +01:00
MqttPublishPrefixTopic_P ( option , PSTR ( D_CMND_STATUS " 11 " ) ) ;
2017-03-14 17:03:25 +00:00
}
2017-09-02 13:37:02 +01:00
2017-03-14 17:03:25 +00:00
}
2017-10-18 17:22:34 +01:00
void MqttShowState ( )
2017-03-14 17:03:25 +00:00
{
2018-01-13 14:53:02 +00:00
char stemp1 [ 33 ] ;
2017-09-02 13:37:02 +01:00
2018-01-06 16:34:42 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " %s{ \" " D_JSON_TIME " \" : \" %s \" , \" " D_JSON_UPTIME " \" :%d " ) , mqtt_data , GetDateAndTime ( ) . c_str ( ) , uptime ) ;
2017-03-14 17:03:25 +00:00
# ifdef USE_ADC_VCC
2017-09-02 13:37:02 +01:00
dtostrfd ( ( double ) ESP . getVcc ( ) / 1000 , 3 , stemp1 ) ;
2018-01-06 16:34:42 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " %s, \" " D_JSON_VCC " \" :%s " ) , mqtt_data , stemp1 ) ;
2017-09-02 13:37:02 +01:00
# endif
2018-01-20 11:12:39 +00:00
2017-10-18 17:22:34 +01:00
for ( byte i = 0 ; i < devices_present ; i + + ) {
2018-01-20 11:12:39 +00:00
if ( i = = light_device - 1 ) {
LightState ( 1 ) ;
} else {
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " %s, \" %s \" : \" %s \" " ) , mqtt_data , GetPowerDevice ( stemp1 , i + 1 , sizeof ( stemp1 ) ) , GetStateText ( bitRead ( power , i ) ) ) ;
}
2017-03-14 17:03:25 +00:00
}
2018-01-20 11:12:39 +00:00
2018-01-06 16:34:42 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " %s, \" " D_JSON_WIFI " \" :{ \" " D_JSON_AP " \" :%d, \" " D_JSON_SSID " \" : \" %s \" , \" " D_JSON_RSSI " \" :%d, \" " D_JSON_APMAC_ADDRESS " \" : \" %s \" }} " ) ,
2017-10-18 17:22:34 +01:00
mqtt_data , Settings . sta_active + 1 , Settings . sta_ssid [ Settings . sta_active ] , WifiGetRssiAsQuality ( WiFi . RSSI ( ) ) , WiFi . BSSIDstr ( ) . c_str ( ) ) ;
2017-02-04 16:09:54 +00:00
}
2017-11-03 17:07:25 +00:00
boolean MqttShowSensor ( )
2017-02-04 16:09:54 +00:00
{
2018-01-06 16:34:42 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " %s{ \" " D_JSON_TIME " \" : \" %s \" " ) , mqtt_data , GetDateAndTime ( ) . c_str ( ) ) ;
2017-11-04 15:36:51 +00:00
int json_data_start = strlen ( mqtt_data ) ;
2017-10-12 13:09:19 +01:00
for ( byte i = 0 ; i < MAX_SWITCHES ; i + + ) {
2017-03-19 17:19:08 +00:00
if ( pin [ GPIO_SWT1 + i ] < 99 ) {
2017-10-18 17:22:34 +01:00
boolean swm = ( ( FOLLOW_INV = = Settings . switchmode [ i ] ) | | ( PUSHBUTTON_INV = = Settings . switchmode [ i ] ) | | ( PUSHBUTTONHOLD_INV = = Settings . switchmode [ i ] ) ) ;
2018-01-06 16:34:42 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " %s, \" " D_JSON_SWITCH " %d \" : \" %s \" " ) , mqtt_data , i + 1 , GetStateText ( swm ^ lastwallswitch [ i ] ) ) ;
2017-03-19 17:19:08 +00:00
}
}
2017-12-25 16:41:12 +00:00
XsnsCall ( FUNC_JSON_APPEND ) ;
2017-11-04 15:36:51 +00:00
boolean json_data_available = ( strlen ( mqtt_data ) - json_data_start ) ;
2018-01-24 16:31:20 +00:00
if ( strstr_P ( mqtt_data , PSTR ( D_JSON_TEMPERATURE ) ) ) {
2018-01-06 16:34:42 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " %s, \" " D_JSON_TEMPERATURE_UNIT " \" : \" %c \" " ) , mqtt_data , TempUnit ( ) ) ;
2017-05-03 17:19:13 +01:00
}
2017-09-13 13:19:34 +01:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " %s} " ) , mqtt_data ) ;
2018-01-05 11:26:19 +00:00
if ( json_data_available ) {
XdrvCall ( FUNC_SHOW_SENSOR ) ;
}
2017-11-03 17:07:25 +00:00
return json_data_available ;
2017-01-28 13:41:01 +00:00
}
/********************************************************************************************/
2017-10-18 17:22:34 +01:00
void PerformEverySecond ( )
2017-01-28 13:41:01 +00:00
{
2017-05-04 12:58:26 +01:00
if ( blockgpio0 ) {
blockgpio0 - - ;
}
2017-04-25 17:24:42 +01:00
for ( byte i = 0 ; i < MAX_PULSETIMERS ; i + + ) {
if ( pulse_timer [ i ] > 111 ) {
pulse_timer [ i ] - - ;
}
}
2017-01-28 13:41:01 +00:00
if ( seriallog_timer ) {
seriallog_timer - - ;
if ( ! seriallog_timer ) {
if ( seriallog_level ) {
2017-10-18 17:22:34 +01:00
AddLog_P ( LOG_LEVEL_INFO , PSTR ( D_LOG_APPLICATION D_SERIAL_LOGGING_DISABLED ) ) ;
2017-01-28 13:41:01 +00:00
}
seriallog_level = 0 ;
}
}
if ( syslog_timer ) { // Restore syslog level
syslog_timer - - ;
if ( ! syslog_timer ) {
2017-11-11 11:33:30 +00:00
syslog_level = ( Settings . flag2 . emulation ) ? 0 : Settings . syslog_level ;
2017-10-18 17:22:34 +01:00
if ( Settings . syslog_level ) {
AddLog_P ( LOG_LEVEL_INFO , PSTR ( D_LOG_APPLICATION D_SYSLOG_LOGGING_REENABLED ) ) ; // Might trigger disable again (on purpose)
2017-01-28 13:41:01 +00:00
}
}
}
if ( status_update_timer ) {
status_update_timer - - ;
if ( ! status_update_timer ) {
2017-10-18 17:22:34 +01:00
for ( byte i = 1 ; i < = devices_present ; i + + ) {
MqttPublishPowerState ( i ) ;
2017-04-25 17:24:42 +01:00
}
2017-01-28 13:41:01 +00:00
}
}
2017-10-18 17:22:34 +01:00
if ( Settings . tele_period ) {
2017-01-28 13:41:01 +00:00
tele_period + + ;
2017-10-18 17:22:34 +01:00
if ( tele_period = = Settings . tele_period - 1 ) {
2017-12-25 16:41:12 +00:00
XsnsCall ( FUNC_PREP_BEFORE_TELEPERIOD ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-18 17:22:34 +01:00
if ( tele_period > = Settings . tele_period ) {
2017-01-28 13:41:01 +00:00
tele_period = 0 ;
2017-09-13 13:19:34 +01:00
mqtt_data [ 0 ] = ' \0 ' ;
2017-10-18 17:22:34 +01:00
MqttShowState ( ) ;
2018-01-18 15:19:28 +00:00
MqttPublishPrefixTopic_P ( TELE , PSTR ( D_RSLT_STATE ) ) ;
2017-01-28 13:41:01 +00:00
2017-09-13 13:19:34 +01:00
mqtt_data [ 0 ] = ' \0 ' ;
2017-11-03 17:07:25 +00:00
if ( MqttShowSensor ( ) ) {
2018-01-18 15:19:28 +00:00
MqttPublishPrefixTopic_P ( TELE , PSTR ( D_RSLT_SENSOR ) , Settings . flag . mqtt_sensor_retain ) ;
2017-04-25 17:24:42 +01:00
}
2018-01-05 11:26:19 +00:00
2017-01-28 13:41:01 +00:00
}
}
2018-01-05 11:26:19 +00:00
XdrvCall ( FUNC_EVERY_SECOND ) ;
2017-12-25 16:41:12 +00:00
XsnsCall ( FUNC_EVERY_SECOND ) ;
2017-01-28 13:41:01 +00:00
2017-10-18 17:22:34 +01:00
if ( ( 2 = = RtcTime . minute ) & & latest_uptime_flag ) {
latest_uptime_flag = false ;
2017-01-28 13:41:01 +00:00
uptime + + ;
2018-01-06 16:34:42 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " { \" " D_JSON_TIME " \" : \" %s \" , \" " D_JSON_UPTIME " \" :%d} " ) , GetDateAndTime ( ) . c_str ( ) , uptime ) ;
2018-01-18 15:19:28 +00:00
MqttPublishPrefixTopic_P ( TELE , PSTR ( D_RSLT_UPTIME ) ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-18 17:22:34 +01:00
if ( ( 3 = = RtcTime . minute ) & & ! latest_uptime_flag ) {
latest_uptime_flag = true ;
2017-04-25 17:24:42 +01:00
}
2017-01-28 13:41:01 +00:00
}
2017-07-25 17:05:47 +01:00
/*********************************************************************************************\
* Button handler with single press only or multi - press and hold on all buttons
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2017-10-18 17:22:34 +01:00
void ButtonHandler ( )
2017-01-28 13:41:01 +00:00
{
2017-04-25 17:24:42 +01:00
uint8_t button = NOT_PRESSED ;
2017-10-18 17:22:34 +01:00
uint8_t button_present = 0 ;
2017-04-25 17:24:42 +01:00
char scmnd [ 20 ] ;
2017-02-13 16:25:46 +00:00
2017-10-18 17:22:34 +01:00
uint8_t maxdev = ( devices_present > MAX_KEYS ) ? MAX_KEYS : devices_present ;
2017-10-12 10:29:40 +01:00
for ( byte i = 0 ; i < maxdev ; i + + ) {
2017-07-30 16:55:37 +01:00
button = NOT_PRESSED ;
2017-10-18 17:22:34 +01:00
button_present = 0 ;
2017-07-25 17:05:47 +01:00
2017-10-18 17:22:34 +01:00
if ( ! i & & ( ( SONOFF_DUAL = = Settings . module ) | | ( CH4 = = Settings . module ) ) ) {
button_present = 1 ;
if ( dual_button_code ) {
snprintf_P ( log_data , sizeof ( log_data ) , PSTR ( D_LOG_APPLICATION D_BUTTON " " D_CODE " %04X " ) , dual_button_code ) ;
AddLog ( LOG_LEVEL_DEBUG ) ;
2017-07-25 17:05:47 +01:00
button = PRESSED ;
2017-12-02 11:40:33 +00:00
if ( 0xF500 = = dual_button_code ) { // Button hold
2017-10-18 17:22:34 +01:00
holdbutton [ i ] = ( Settings . param [ P_HOLD_TIME ] * ( STATES / 10 ) ) - 1 ;
2017-07-25 17:05:47 +01:00
}
2017-10-18 17:22:34 +01:00
dual_button_code = 0 ;
2017-04-25 17:24:42 +01:00
}
2017-01-28 13:41:01 +00:00
} else {
2017-07-25 17:05:47 +01:00
if ( ( pin [ GPIO_KEY1 + i ] < 99 ) & & ! blockgpio0 ) {
2017-10-18 17:22:34 +01:00
button_present = 1 ;
2017-07-25 17:05:47 +01:00
button = digitalRead ( pin [ GPIO_KEY1 + i ] ) ;
2017-06-06 22:23:23 +01:00
}
2017-01-28 13:41:01 +00:00
}
2017-07-25 17:05:47 +01:00
2017-10-18 17:22:34 +01:00
if ( button_present ) {
if ( SONOFF_4CHPRO = = Settings . module ) {
2017-07-25 17:05:47 +01:00
if ( holdbutton [ i ] ) {
holdbutton [ i ] - - ;
}
2017-10-18 17:22:34 +01:00
boolean button_pressed = false ;
2017-07-25 17:05:47 +01:00
if ( ( PRESSED = = button ) & & ( NOT_PRESSED = = lastbutton [ i ] ) ) {
2017-09-13 13:19:34 +01:00
snprintf_P ( log_data , sizeof ( log_data ) , PSTR ( D_LOG_APPLICATION D_BUTTON " %d " D_LEVEL_10 ) , i + 1 ) ;
2017-10-18 17:22:34 +01:00
AddLog ( LOG_LEVEL_DEBUG ) ;
2017-07-25 17:05:47 +01:00
holdbutton [ i ] = STATES ;
2017-10-18 17:22:34 +01:00
button_pressed = true ;
2017-07-25 17:05:47 +01:00
}
if ( ( NOT_PRESSED = = button ) & & ( PRESSED = = lastbutton [ i ] ) ) {
2017-09-13 13:19:34 +01:00
snprintf_P ( log_data , sizeof ( log_data ) , PSTR ( D_LOG_APPLICATION D_BUTTON " %d " D_LEVEL_01 ) , i + 1 ) ;
2017-10-18 17:22:34 +01:00
AddLog ( LOG_LEVEL_DEBUG ) ;
2017-12-02 11:40:33 +00:00
if ( ! holdbutton [ i ] ) { // Do not allow within 1 second
2017-10-18 17:22:34 +01:00
button_pressed = true ;
2017-07-25 17:05:47 +01:00
}
}
2017-10-18 17:22:34 +01:00
if ( button_pressed ) {
2017-12-02 11:40:33 +00:00
if ( ! send_button_power ( 0 , i + 1 , 2 ) ) { // Execute Toggle command via MQTT if ButtonTopic is set
2018-01-24 16:31:20 +00:00
ExecuteCommandPower ( i + 1 , POWER_TOGGLE ) ; // Execute Toggle command internally
2017-07-25 17:05:47 +01:00
}
}
2017-03-08 15:20:45 +00:00
} else {
2017-07-25 17:05:47 +01:00
if ( ( PRESSED = = button ) & & ( NOT_PRESSED = = lastbutton [ i ] ) ) {
2017-12-02 11:40:33 +00:00
if ( Settings . flag . button_single ) { // Allow only single button press for immediate action
2017-09-13 13:19:34 +01:00
snprintf_P ( log_data , sizeof ( log_data ) , PSTR ( D_LOG_APPLICATION D_BUTTON " %d " D_IMMEDIATE ) , i + 1 ) ;
2017-10-18 17:22:34 +01:00
AddLog ( LOG_LEVEL_DEBUG ) ;
2017-12-02 11:40:33 +00:00
if ( ! send_button_power ( 0 , i + 1 , 2 ) ) { // Execute Toggle command via MQTT if ButtonTopic is set
2018-01-24 16:31:20 +00:00
ExecuteCommandPower ( i + 1 , POWER_TOGGLE ) ; // Execute Toggle command internally
2017-07-25 17:05:47 +01:00
}
2017-01-28 13:41:01 +00:00
} else {
2017-07-25 17:05:47 +01:00
multipress [ i ] = ( multiwindow [ i ] ) ? multipress [ i ] + 1 : 1 ;
2017-09-13 13:19:34 +01:00
snprintf_P ( log_data , sizeof ( log_data ) , PSTR ( D_LOG_APPLICATION D_BUTTON " %d " D_MULTI_PRESS " %d " ) , i + 1 , multipress [ i ] ) ;
2017-10-18 17:22:34 +01:00
AddLog ( LOG_LEVEL_DEBUG ) ;
2017-12-02 11:40:33 +00:00
multiwindow [ i ] = STATES / 2 ; // 0.5 second multi press window
2017-01-28 13:41:01 +00:00
}
2017-07-25 17:05:47 +01:00
blinks = 201 ;
}
2017-09-02 13:37:02 +01:00
2017-07-25 17:05:47 +01:00
if ( NOT_PRESSED = = button ) {
holdbutton [ i ] = 0 ;
2017-01-28 13:41:01 +00:00
} else {
2017-07-25 17:05:47 +01:00
holdbutton [ i ] + + ;
2017-12-02 11:40:33 +00:00
if ( Settings . flag . button_single ) { // Allow only single button press for immediate action
2017-10-18 17:22:34 +01:00
if ( holdbutton [ i ] = = Settings . param [ P_HOLD_TIME ] * ( STATES / 10 ) * 4 ) { // Button hold for four times longer
// Settings.flag.button_single = 0;
2017-09-02 13:37:02 +01:00
snprintf_P ( scmnd , sizeof ( scmnd ) , PSTR ( D_CMND_SETOPTION " 13 0 " ) ) ; // Disable single press only
2017-10-18 17:22:34 +01:00
ExecuteCommand ( scmnd ) ;
2017-07-25 17:05:47 +01:00
}
} else {
2017-12-02 11:40:33 +00:00
if ( holdbutton [ i ] = = Settings . param [ P_HOLD_TIME ] * ( STATES / 10 ) ) { // Button hold
2017-07-25 17:05:47 +01:00
multipress [ i ] = 0 ;
2017-12-02 11:40:33 +00:00
if ( ! Settings . flag . button_restrict ) { // No button restriction
2017-09-02 13:37:02 +01:00
snprintf_P ( scmnd , sizeof ( scmnd ) , PSTR ( D_CMND_RESET " 1 " ) ) ;
2017-10-18 17:22:34 +01:00
ExecuteCommand ( scmnd ) ;
2017-07-25 17:05:47 +01:00
} else {
2017-12-02 11:40:33 +00:00
send_button_power ( 0 , i + 1 , 3 ) ; // Execute Hold command via MQTT if ButtonTopic is set
2017-07-25 17:05:47 +01:00
}
}
2017-03-08 15:20:45 +00:00
}
2017-01-28 13:41:01 +00:00
}
2017-12-02 11:40:33 +00:00
if ( ! Settings . flag . button_single ) { // Allow multi-press
2017-07-25 17:05:47 +01:00
if ( multiwindow [ i ] ) {
multiwindow [ i ] - - ;
} else {
2017-10-18 17:22:34 +01:00
if ( ! restart_flag & & ! holdbutton [ i ] & & ( multipress [ i ] > 0 ) & & ( multipress [ i ] < MAX_BUTTON_COMMANDS + 3 ) ) {
boolean single_press = false ;
2017-12-02 11:40:33 +00:00
if ( multipress [ i ] < 3 ) { // Single or Double press
if ( ( SONOFF_DUAL_R2 = = Settings . module ) | | ( SONOFF_DUAL = = Settings . module ) | | ( CH4 = = Settings . module ) ) {
2017-10-18 17:22:34 +01:00
single_press = true ;
2017-07-25 17:05:47 +01:00
} else {
2017-10-18 17:22:34 +01:00
single_press = ( Settings . flag . button_swap + 1 = = multipress [ i ] ) ;
2017-07-25 17:05:47 +01:00
multipress [ i ] = 1 ;
}
}
2017-10-18 17:22:34 +01:00
if ( single_press & & send_button_power ( 0 , i + multipress [ i ] , 2 ) ) { // Execute Toggle command via MQTT if ButtonTopic is set
2017-07-25 17:05:47 +01:00
// Success
} else {
2017-12-02 11:40:33 +00:00
if ( multipress [ i ] < 3 ) { // Single or Double press
if ( WifiState ( ) ) { // WPSconfig, Smartconfig or Wifimanager active
2017-10-18 17:22:34 +01:00
restart_flag = 1 ;
2017-07-25 17:05:47 +01:00
} else {
2018-01-24 16:31:20 +00:00
ExecuteCommandPower ( i + multipress [ i ] , POWER_TOGGLE ) ; // Execute Toggle command internally
2017-07-25 17:05:47 +01:00
}
2017-12-02 11:40:33 +00:00
} else { // 3 - 7 press
2017-10-18 17:22:34 +01:00
if ( ! Settings . flag . button_restrict ) {
snprintf_P ( scmnd , sizeof ( scmnd ) , kCommands [ multipress [ i ] - 3 ] ) ;
ExecuteCommand ( scmnd ) ;
2017-07-25 17:05:47 +01:00
}
}
}
multipress [ i ] = 0 ;
}
}
2017-04-25 17:24:42 +01:00
}
2017-01-28 13:41:01 +00:00
}
}
2017-07-30 16:55:37 +01:00
lastbutton [ i ] = button ;
2017-01-28 13:41:01 +00:00
}
2017-07-25 17:05:47 +01:00
}
/*********************************************************************************************\
* Switch handler
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2017-10-18 17:22:34 +01:00
void SwitchHandler ( )
2017-07-25 17:05:47 +01:00
{
uint8_t button = NOT_PRESSED ;
uint8_t switchflag ;
2017-01-28 13:41:01 +00:00
2017-10-10 14:40:02 +01:00
for ( byte i = 0 ; i < MAX_SWITCHES ; i + + ) {
2017-04-25 17:24:42 +01:00
if ( pin [ GPIO_SWT1 + i ] < 99 ) {
2017-06-06 22:23:23 +01:00
2017-06-16 13:33:49 +01:00
if ( holdwallswitch [ i ] ) {
holdwallswitch [ i ] - - ;
if ( 0 = = holdwallswitch [ i ] ) {
2017-07-25 17:05:47 +01:00
send_button_power ( 1 , i + 1 , 3 ) ; // Execute command via MQTT
2017-06-06 22:23:23 +01:00
}
}
2017-09-02 13:37:02 +01:00
2017-04-25 17:24:42 +01:00
button = digitalRead ( pin [ GPIO_SWT1 + i ] ) ;
if ( button ! = lastwallswitch [ i ] ) {
switchflag = 3 ;
2017-10-18 17:22:34 +01:00
switch ( Settings . switchmode [ i ] ) {
2017-04-25 17:24:42 +01:00
case TOGGLE :
2017-10-10 14:40:02 +01:00
switchflag = 2 ; // Toggle
2017-04-25 17:24:42 +01:00
break ;
case FOLLOW :
2017-10-10 14:40:02 +01:00
switchflag = button & 1 ; // Follow wall switch state
2017-04-25 17:24:42 +01:00
break ;
case FOLLOW_INV :
2017-10-10 14:40:02 +01:00
switchflag = ~ button & 1 ; // Follow inverted wall switch state
2017-04-25 17:24:42 +01:00
break ;
case PUSHBUTTON :
if ( ( PRESSED = = button ) & & ( NOT_PRESSED = = lastwallswitch [ i ] ) ) {
2017-06-16 13:33:49 +01:00
switchflag = 2 ; // Toggle with pushbutton to Gnd
2017-04-25 17:24:42 +01:00
}
break ;
case PUSHBUTTON_INV :
if ( ( NOT_PRESSED = = button ) & & ( PRESSED = = lastwallswitch [ i ] ) ) {
2017-06-16 13:33:49 +01:00
switchflag = 2 ; // Toggle with releasing pushbutton from Gnd
2017-04-25 17:24:42 +01:00
}
2017-06-06 22:23:23 +01:00
break ;
2017-11-22 14:34:07 +00:00
case PUSHBUTTON_TOGGLE :
if ( button ! = lastwallswitch [ i ] ) {
switchflag = 2 ; // Toggle with any pushbutton change
}
break ;
2017-06-06 22:23:23 +01:00
case PUSHBUTTONHOLD :
if ( ( PRESSED = = button ) & & ( NOT_PRESSED = = lastwallswitch [ i ] ) ) {
2017-10-18 17:22:34 +01:00
holdwallswitch [ i ] = Settings . param [ P_HOLD_TIME ] * ( STATES / 10 ) ;
2017-06-06 22:23:23 +01:00
}
2017-06-16 13:33:49 +01:00
if ( ( NOT_PRESSED = = button ) & & ( PRESSED = = lastwallswitch [ i ] ) & & ( holdwallswitch [ i ] ) ) {
holdwallswitch [ i ] = 0 ;
switchflag = 2 ; // Toggle with pushbutton to Gnd
2017-06-06 22:23:23 +01:00
}
break ;
case PUSHBUTTONHOLD_INV :
if ( ( NOT_PRESSED = = button ) & & ( PRESSED = = lastwallswitch [ i ] ) ) {
2017-10-18 17:22:34 +01:00
holdwallswitch [ i ] = Settings . param [ P_HOLD_TIME ] * ( STATES / 10 ) ;
2017-06-06 22:23:23 +01:00
}
2017-06-16 13:33:49 +01:00
if ( ( PRESSED = = button ) & & ( NOT_PRESSED = = lastwallswitch [ i ] ) & & ( holdwallswitch [ i ] ) ) {
holdwallswitch [ i ] = 0 ;
switchflag = 2 ; // Toggle with pushbutton to Gnd
2017-06-06 22:23:23 +01:00
}
break ;
2017-01-28 13:41:01 +00:00
}
2017-09-02 13:37:02 +01:00
2017-04-25 17:24:42 +01:00
if ( switchflag < 3 ) {
2017-06-06 22:23:23 +01:00
if ( ! send_button_power ( 1 , i + 1 , switchflag ) ) { // Execute command via MQTT
2018-01-24 16:31:20 +00:00
ExecuteCommandPower ( i + 1 , switchflag ) ; // Execute command internally (if i < devices_present)
2017-04-25 17:24:42 +01:00
}
}
2017-09-02 13:37:02 +01:00
2017-04-25 17:24:42 +01:00
lastwallswitch [ i ] = button ;
2017-01-28 13:41:01 +00:00
}
}
}
2017-07-25 17:05:47 +01:00
}
/*********************************************************************************************\
* State loop
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2017-10-18 17:22:34 +01:00
void StateLoop ( )
2017-07-25 17:05:47 +01:00
{
2017-10-10 14:40:02 +01:00
power_t power_now ;
2017-07-25 17:05:47 +01:00
2017-10-18 17:22:34 +01:00
state_loop_timer = millis ( ) + ( 1000 / STATES ) ;
2017-07-25 17:05:47 +01:00
state + + ;
/*-------------------------------------------------------------------------------------------*\
* Every second
\ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
if ( STATES = = state ) {
state = 0 ;
2017-10-18 17:22:34 +01:00
PerformEverySecond ( ) ;
2017-07-25 17:05:47 +01:00
}
/*-------------------------------------------------------------------------------------------*\
* Every 0.1 second
\ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
if ( ! ( state % ( STATES / 10 ) ) ) {
if ( mqtt_cmnd_publish ) {
mqtt_cmnd_publish - - ; // Clean up
}
2017-09-02 13:37:02 +01:00
2017-07-25 17:05:47 +01:00
if ( latching_relay_pulse ) {
latching_relay_pulse - - ;
if ( ! latching_relay_pulse ) {
2017-10-18 17:22:34 +01:00
SetLatchingRelay ( 0 , 0 ) ;
2017-07-25 17:05:47 +01:00
}
}
for ( byte i = 0 ; i < MAX_PULSETIMERS ; i + + ) {
if ( ( pulse_timer [ i ] > 0 ) & & ( pulse_timer [ i ] < 112 ) ) {
pulse_timer [ i ] - - ;
if ( ! pulse_timer [ i ] ) {
2018-01-24 16:31:20 +00:00
// ExecuteCommandPower(i +1, POWER_OFF);
ExecuteCommandPower ( i + 1 , ( POWER_ALL_OFF_PULSETIME_ON = = Settings . poweronstate ) ? POWER_ON : POWER_OFF ) ;
2017-07-25 17:05:47 +01:00
}
}
}
if ( blink_mask ) {
blink_timer - - ;
if ( ! blink_timer ) {
2017-10-18 17:22:34 +01:00
blink_timer = Settings . blinktime ;
2017-07-25 17:05:47 +01:00
blink_counter - - ;
if ( ! blink_counter ) {
2017-10-18 17:22:34 +01:00
StopAllPowerBlink ( ) ;
2017-07-25 17:05:47 +01:00
} else {
blink_power ^ = 1 ;
2017-10-10 14:40:02 +01:00
power_now = ( power & ( POWER_MASK ^ blink_mask ) ) | ( ( blink_power ) ? blink_mask : 0 ) ;
2017-10-18 17:22:34 +01:00
SetDevicePower ( power_now ) ;
2017-07-25 17:05:47 +01:00
}
}
}
// Backlog
2017-10-18 17:22:34 +01:00
if ( backlog_delay ) {
backlog_delay - - ;
}
if ( ( backlog_pointer ! = backlog_index ) & & ! backlog_delay & & ! backlog_mutex ) {
backlog_mutex = 1 ;
ExecuteCommand ( ( char * ) backlog [ backlog_pointer ] . c_str ( ) ) ;
backlog_mutex = 0 ;
backlog_pointer + + ;
2017-07-25 17:05:47 +01:00
/*
2017-10-18 17:22:34 +01:00
if ( backlog_pointer > = MAX_BACKLOG ) {
backlog_pointer = 0 ;
2017-07-25 17:05:47 +01:00
}
*/
2017-10-18 17:22:34 +01:00
backlog_pointer & = 0xF ;
2017-07-25 17:05:47 +01:00
}
}
/*-------------------------------------------------------------------------------------------*\
* Every 0.05 second
\ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2017-10-18 17:22:34 +01:00
ButtonHandler ( ) ;
SwitchHandler ( ) ;
2017-07-25 17:05:47 +01:00
2018-01-05 11:26:19 +00:00
XdrvCall ( FUNC_EVERY_50_MSECOND ) ;
2017-12-25 16:41:12 +00:00
XsnsCall ( FUNC_EVERY_50_MSECOND ) ;
2017-07-25 17:05:47 +01:00
/*-------------------------------------------------------------------------------------------*\
* Every 0.2 second
\ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2017-01-28 13:41:01 +00:00
if ( ! ( state % ( ( STATES / 10 ) * 2 ) ) ) {
2017-10-18 17:22:34 +01:00
if ( blinks | | restart_flag | | ota_state_flag ) {
if ( restart_flag | | ota_state_flag ) {
2017-01-28 13:41:01 +00:00
blinkstate = 1 ; // Stay lit
} else {
blinkstate ^ = 1 ; // Blink
}
2017-10-18 17:22:34 +01:00
if ( ( ! ( Settings . ledstate & 0x08 ) ) & & ( ( Settings . ledstate & 0x06 ) | | ( blinks > 200 ) | | ( blinkstate ) ) ) {
SetLedPower ( blinkstate ) ;
2017-01-28 13:41:01 +00:00
}
if ( ! blinkstate ) {
blinks - - ;
2017-04-25 17:24:42 +01:00
if ( 200 = = blinks ) {
blinks = 0 ;
}
2017-01-28 13:41:01 +00:00
}
} else {
2017-10-18 17:22:34 +01:00
if ( Settings . ledstate & 1 ) {
2017-08-18 09:40:21 +01:00
boolean tstate = power ;
2017-10-18 17:22:34 +01:00
if ( ( SONOFF_TOUCH = = Settings . module ) | | ( SONOFF_T11 = = Settings . module ) | | ( SONOFF_T12 = = Settings . module ) | | ( SONOFF_T13 = = Settings . module ) ) {
2017-08-18 09:40:21 +01:00
tstate = ( ! power ) ? 1 : 0 ;
}
2017-10-18 17:22:34 +01:00
SetLedPower ( tstate ) ;
2017-04-25 17:24:42 +01:00
}
2017-01-28 13:41:01 +00:00
}
}
2017-07-25 17:05:47 +01:00
/*-------------------------------------------------------------------------------------------*\
* Every second at 0.2 second interval
\ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2017-07-15 14:07:30 +01:00
2017-01-28 13:41:01 +00:00
switch ( state ) {
case ( STATES / 10 ) * 2 :
2017-10-18 17:22:34 +01:00
if ( ota_state_flag & & ( backlog_pointer = = backlog_index ) ) {
ota_state_flag - - ;
if ( 2 = = ota_state_flag ) {
2018-01-10 13:10:25 +00:00
ota_url = Settings . ota_url ;
RtcSettings . ota_loader = 0 ; // Try requested image first
2017-10-18 17:22:34 +01:00
ota_retry_counter = OTA_ATTEMPTS ;
2017-01-28 13:41:01 +00:00
ESPhttpUpdate . rebootOnUpdate ( false ) ;
2017-10-18 17:22:34 +01:00
SettingsSave ( 1 ) ; // Free flash for OTA update
2017-02-24 17:17:48 +00:00
}
2017-10-18 17:22:34 +01:00
if ( ota_state_flag < = 0 ) {
2017-02-24 17:17:48 +00:00
# ifdef USE_WEBSERVER
2017-10-18 17:22:34 +01:00
if ( Settings . webserver ) {
StopWebserver ( ) ;
2017-04-25 17:24:42 +01:00
}
2017-02-24 17:17:48 +00:00
# endif // USE_WEBSERVER
2017-11-24 16:26:20 +00:00
# ifdef USE_ARILUX_RF
AriluxRfDisable ( ) ; // Prevent restart exception on Arilux Interrupt routine
# endif // USE_ARILUX_RF
2017-10-18 17:22:34 +01:00
ota_state_flag = 92 ;
ota_result = 0 ;
ota_retry_counter - - ;
if ( ota_retry_counter ) {
2018-01-10 13:10:25 +00:00
# ifndef BE_MINIMAL
if ( RtcSettings . ota_loader ) {
char * pch = strrchr ( Settings . ota_url , ' - ' ) ; // Change from filename-DE.bin into filename-minimal.bin
char * ech = strrchr ( Settings . ota_url , ' . ' ) ; // Change from filename.bin into filename-minimal.bin
if ( ! pch ) {
pch = ech ;
}
if ( pch ) {
strlcpy ( mqtt_data , Settings . ota_url , pch - Settings . ota_url + 1 ) ;
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( " %s- " D_JSON_MINIMAL " %s " ) , mqtt_data , ech ) ; // Minimal filename must be filename-minimal
ota_url = mqtt_data ; // Try minimal image
}
}
# endif // BE_MINIMAL
snprintf_P ( log_data , sizeof ( log_data ) , PSTR ( D_LOG_UPLOAD " %s " ) , ota_url ) ;
AddLog ( LOG_LEVEL_DEBUG ) ;
ota_result = ( HTTP_UPDATE_FAILED ! = ESPhttpUpdate . update ( ota_url ) ) ;
2017-10-18 17:22:34 +01:00
if ( ! ota_result ) {
2018-01-10 13:10:25 +00:00
# ifndef BE_MINIMAL
int ota_error = ESPhttpUpdate . getLastError ( ) ;
// snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_UPLOAD "Ota error %d"), ota_error);
// AddLog(LOG_LEVEL_DEBUG);
if ( ( HTTP_UE_TOO_LESS_SPACE = = ota_error ) | | ( HTTP_UE_BIN_FOR_WRONG_FLASH = = ota_error ) ) {
RtcSettings . ota_loader = 1 ; // Try minimal image next
}
# endif // BE_MINIMAL
2017-11-24 16:26:20 +00:00
ota_state_flag = 2 ; // Upgrade failed - retry
2017-04-25 17:24:42 +01:00
}
2017-01-28 13:41:01 +00:00
}
}
2017-11-24 16:26:20 +00:00
if ( 90 = = ota_state_flag ) { // Allow MQTT to reconnect
2017-10-18 17:22:34 +01:00
ota_state_flag = 0 ;
if ( ota_result ) {
2017-11-24 16:26:20 +00:00
SetFlashModeDout ( ) ; // Force DOUT for both ESP8266 and ESP8285
2018-01-06 16:34:42 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( D_JSON_SUCCESSFUL " . " D_JSON_RESTARTING ) ) ;
2017-01-28 13:41:01 +00:00
} else {
2018-01-06 16:34:42 +00:00
snprintf_P ( mqtt_data , sizeof ( mqtt_data ) , PSTR ( D_JSON_FAILED " %s " ) , ESPhttpUpdate . getLastErrorString ( ) . c_str ( ) ) ;
2017-01-28 13:41:01 +00:00
}
2017-11-24 16:26:20 +00:00
restart_flag = 2 ; // Restart anyway to keep memory clean webserver
2018-01-18 15:19:28 +00:00
MqttPublishPrefixTopic_P ( STAT , PSTR ( D_CMND_UPGRADE ) ) ;
2017-01-28 13:41:01 +00:00
}
}
break ;
case ( STATES / 10 ) * 4 :
2017-10-18 17:22:34 +01:00
if ( MidnightNow ( ) ) {
CounterSaveState ( ) ;
2017-05-17 21:49:22 +01:00
}
2017-10-18 17:22:34 +01:00
if ( save_data_counter & & ( backlog_pointer = = backlog_index ) ) {
save_data_counter - - ;
if ( save_data_counter < = 0 ) {
if ( Settings . flag . save_state ) {
2017-10-10 14:40:02 +01:00
power_t mask = POWER_MASK ;
2017-04-25 17:24:42 +01:00
for ( byte i = 0 ; i < MAX_PULSETIMERS ; i + + ) {
2017-10-18 17:22:34 +01:00
if ( ( Settings . pulse_timer [ i ] > 0 ) & & ( Settings . pulse_timer [ i ] < 30 ) ) { // 3 seconds
2017-04-25 17:24:42 +01:00
mask & = ~ ( 1 < < i ) ;
}
}
2017-10-18 17:22:34 +01:00
if ( ! ( ( Settings . power & mask ) = = ( power & mask ) ) ) {
Settings . power = power ;
2017-04-25 17:24:42 +01:00
}
2017-10-04 16:29:49 +01:00
} else {
2017-10-18 17:22:34 +01:00
Settings . power = 0 ;
2017-01-28 13:41:01 +00:00
}
2017-10-18 17:22:34 +01:00
SettingsSave ( 0 ) ;
save_data_counter = Settings . save_data ;
2017-01-28 13:41:01 +00:00
}
}
2017-10-18 17:22:34 +01:00
if ( restart_flag & & ( backlog_pointer = = backlog_index ) ) {
if ( 212 = = restart_flag ) {
SettingsErase ( ) ;
2017-11-21 15:06:51 +00:00
restart_flag - - ;
}
if ( 211 = = restart_flag ) {
2017-10-18 17:22:34 +01:00
SettingsDefault ( ) ;
restart_flag = 2 ;
2017-01-28 13:41:01 +00:00
}
2017-11-21 15:06:51 +00:00
SettingsSaveAll ( ) ;
2017-10-18 17:22:34 +01:00
restart_flag - - ;
if ( restart_flag < = 0 ) {
AddLog_P ( LOG_LEVEL_INFO , PSTR ( D_LOG_APPLICATION D_RESTARTING ) ) ;
2017-01-28 13:41:01 +00:00
ESP . restart ( ) ;
}
}
break ;
case ( STATES / 10 ) * 6 :
2017-10-18 17:22:34 +01:00
WifiCheck ( wifi_state_flag ) ;
wifi_state_flag = WIFI_RESTART ;
2017-01-28 13:41:01 +00:00
break ;
case ( STATES / 10 ) * 8 :
2017-04-25 17:24:42 +01:00
if ( WL_CONNECTED = = WiFi . status ( ) ) {
2017-10-18 17:22:34 +01:00
if ( Settings . flag . mqtt_enabled ) {
if ( ! MqttClient . connected ( ) ) {
if ( ! mqtt_retry_counter ) {
MqttReconnect ( ) ;
2017-01-28 13:41:01 +00:00
} else {
2017-10-18 17:22:34 +01:00
mqtt_retry_counter - - ;
2017-01-28 13:41:01 +00:00
}
}
} else {
2017-10-18 17:22:34 +01:00
if ( ! mqtt_retry_counter ) {
MqttReconnect ( ) ;
2017-01-28 13:41:01 +00:00
}
}
}
break ;
}
}
2017-04-10 16:25:31 +01:00
/********************************************************************************************/
2017-10-18 17:22:34 +01:00
void SerialInput ( )
2017-01-28 13:41:01 +00:00
{
while ( Serial . available ( ) ) {
yield ( ) ;
2017-10-18 17:22:34 +01:00
serial_in_byte = Serial . read ( ) ;
2017-01-28 13:41:01 +00:00
2017-07-30 16:55:37 +01:00
/*-------------------------------------------------------------------------------------------*\
2017-12-03 13:06:15 +00:00
* Sonoff dual and ch4 19200 baud serial interface
2017-07-30 16:55:37 +01:00
\ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2017-12-03 13:06:15 +00:00
if ( ( SONOFF_DUAL = = Settings . module ) | | ( CH4 = = Settings . module ) ) {
2017-10-18 17:22:34 +01:00
if ( dual_hex_code ) {
2017-12-03 13:06:15 +00:00
dual_hex_code - - ;
if ( dual_hex_code ) {
dual_button_code = ( dual_button_code < < 8 ) | serial_in_byte ;
serial_in_byte = 0 ;
} else {
if ( serial_in_byte ! = 0xA1 ) {
dual_button_code = 0 ; // 0xA1 - End of Sonoff dual button code
}
2017-04-25 17:24:42 +01:00
}
2017-01-28 13:41:01 +00:00
}
2017-12-03 13:06:15 +00:00
if ( 0xA0 = = serial_in_byte ) { // 0xA0 - Start of Sonoff dual button code
serial_in_byte = 0 ;
dual_button_code = 0 ;
dual_hex_code = 3 ;
}
2017-01-28 13:41:01 +00:00
}
2017-07-30 16:55:37 +01:00
/*-------------------------------------------------------------------------------------------*\
* Sonoff bridge 19200 baud serial interface
\ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2017-12-03 13:06:15 +00:00
if ( SONOFF_BRIDGE = = Settings . module ) {
if ( SonoffBridgeSerialInput ( ) ) {
serial_in_byte_counter = 0 ;
Serial . flush ( ) ;
return ;
}
2017-07-30 16:55:37 +01:00
}
/*-------------------------------------------------------------------------------------------*/
2017-10-18 17:22:34 +01:00
if ( serial_in_byte > 127 ) { // binary data...
serial_in_byte_counter = 0 ;
2017-01-28 13:41:01 +00:00
Serial . flush ( ) ;
return ;
}
2017-10-18 17:22:34 +01:00
if ( isprint ( serial_in_byte ) ) {
if ( serial_in_byte_counter < INPUT_BUFFER_SIZE ) { // add char to string if it still fits
serial_in_buffer [ serial_in_byte_counter + + ] = serial_in_byte ;
2017-01-28 13:41:01 +00:00
} else {
2017-10-18 17:22:34 +01:00
serial_in_byte_counter = 0 ;
2017-01-28 13:41:01 +00:00
}
}
2017-04-10 16:25:31 +01:00
2017-09-16 16:34:03 +01:00
/*-------------------------------------------------------------------------------------------*\
* Sonoff SC 19200 baud serial interface
\ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2017-10-18 17:22:34 +01:00
if ( serial_in_byte = = ' \x1B ' ) { // Sonoff SC status from ATMEGA328P
serial_in_buffer [ serial_in_byte_counter ] = 0 ; // serial data completed
SonoffScSerialInput ( serial_in_buffer ) ;
serial_in_byte_counter = 0 ;
2017-04-10 16:25:31 +01:00
Serial . flush ( ) ;
return ;
}
2017-09-16 16:34:03 +01:00
/*-------------------------------------------------------------------------------------------*/
2017-10-18 17:22:34 +01:00
else if ( serial_in_byte = = ' \n ' ) {
serial_in_buffer [ serial_in_byte_counter ] = 0 ; // serial data completed
seriallog_level = ( Settings . seriallog_level < LOG_LEVEL_INFO ) ? LOG_LEVEL_INFO : Settings . seriallog_level ;
snprintf_P ( log_data , sizeof ( log_data ) , PSTR ( D_LOG_COMMAND " %s " ) , serial_in_buffer ) ;
AddLog ( LOG_LEVEL_INFO ) ;
ExecuteCommand ( serial_in_buffer ) ;
serial_in_byte_counter = 0 ;
2017-01-28 13:41:01 +00:00
Serial . flush ( ) ;
return ;
}
}
}
/********************************************************************************************/
2017-10-18 17:22:34 +01:00
void GpioInit ( )
2017-01-28 13:41:01 +00:00
{
uint8_t mpin ;
mytmplt def_module ;
2017-10-18 17:22:34 +01:00
if ( ! Settings . module | | ( Settings . module > = MAXMODULE ) ) {
Settings . module = MODULE ;
2017-11-15 22:07:45 +00:00
Settings . last_module = MODULE ;
2017-04-25 17:24:42 +01:00
}
2017-01-28 13:41:01 +00:00
2017-10-18 17:22:34 +01:00
memcpy_P ( & def_module , & kModules [ Settings . module ] , sizeof ( def_module ) ) ;
2017-01-28 13:41:01 +00:00
strlcpy ( my_module . name , def_module . name , sizeof ( my_module . name ) ) ;
for ( byte i = 0 ; i < MAX_GPIO_PIN ; i + + ) {
2017-10-18 17:22:34 +01:00
if ( Settings . my_gp . io [ i ] > GPIO_NONE ) {
my_module . gp . io [ i ] = Settings . my_gp . io [ i ] ;
2017-04-25 17:24:42 +01:00
}
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 ] ;
}
2017-01-28 13:41:01 +00:00
}
2017-02-11 14:06:23 +00:00
2017-04-25 17:24:42 +01:00
for ( byte i = 0 ; i < GPIO_MAX ; i + + ) {
pin [ i ] = 99 ;
}
2017-01-28 13:41:01 +00:00
for ( byte i = 0 ; i < MAX_GPIO_PIN ; i + + ) {
mpin = my_module . gp . io [ i ] ;
2017-09-13 13:19:34 +01:00
// snprintf_P(log_data, sizeof(log_data), PSTR("DBG: gpio pin %d, mpin %d"), i, mpin);
2017-10-18 17:22:34 +01:00
// AddLog(LOG_LEVEL_DEBUG);
2017-09-02 13:37:02 +01:00
2017-01-28 13:41:01 +00:00
if ( mpin ) {
2017-10-10 14:40:02 +01:00
if ( ( mpin > = GPIO_REL1_INV ) & & ( mpin < ( GPIO_REL1_INV + MAX_RELAYS ) ) ) {
bitSet ( rel_inverted , mpin - GPIO_REL1_INV ) ;
2017-10-05 12:28:31 +01:00
mpin - = ( GPIO_REL1_INV - GPIO_REL1 ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-10 14:40:02 +01:00
else if ( ( mpin > = GPIO_LED1_INV ) & & ( mpin < ( GPIO_LED1_INV + MAX_LEDS ) ) ) {
bitSet ( led_inverted , mpin - GPIO_LED1_INV ) ;
2017-10-05 12:28:31 +01:00
mpin - = ( GPIO_LED1_INV - GPIO_LED1 ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-10 14:40:02 +01:00
else if ( ( mpin > = GPIO_PWM1_INV ) & & ( mpin < ( GPIO_PWM1_INV + MAX_PWMS ) ) ) {
bitSet ( pwm_inverted , mpin - GPIO_PWM1_INV ) ;
2017-10-05 12:28:31 +01:00
mpin - = ( GPIO_PWM1_INV - GPIO_PWM1 ) ;
2017-10-04 16:29:49 +01:00
}
2017-09-02 13:37:02 +01:00
# ifdef USE_DHT
2017-12-03 13:06:15 +00:00
else if ( ( mpin > = GPIO_DHT11 ) & & ( mpin < = GPIO_SI7021 ) ) {
2017-10-18 17:22:34 +01:00
if ( DhtSetup ( i , mpin ) ) {
2017-05-03 17:19:13 +01:00
dht_flg = 1 ;
mpin = GPIO_DHT11 ;
} else {
mpin = 0 ;
}
2017-01-28 13:41:01 +00:00
}
2017-09-02 13:37:02 +01:00
# endif // USE_DHT
2017-05-03 17:19:13 +01:00
}
if ( mpin ) {
2017-01-28 13:41:01 +00:00
pin [ mpin ] = i ;
}
}
2017-04-25 17:24:42 +01:00
if ( 2 = = pin [ GPIO_TXD ] ) {
Serial . set_tx ( 2 ) ;
}
2017-03-25 16:24:11 +00:00
2017-10-18 17:22:34 +01:00
analogWriteRange ( Settings . pwm_range ) ; // Default is 1023 (Arduino.h)
analogWriteFreq ( Settings . pwm_frequency ) ; // Default is 1000 (core_esp8266_wiring_pwm.c)
2017-03-19 17:19:08 +00:00
2018-01-05 11:26:19 +00:00
# ifdef USE_SPI
spi_flg = ( ( ( ( pin [ GPIO_SPI_CS ] < 99 ) & & ( pin [ GPIO_SPI_CS ] > 14 ) ) | | ( pin [ GPIO_SPI_CS ] < 12 ) ) | | ( ( ( pin [ GPIO_SPI_DC ] < 99 ) & & ( pin [ GPIO_SPI_DC ] > 14 ) ) | | ( pin [ GPIO_SPI_DC ] < 12 ) ) ) ;
if ( spi_flg ) {
for ( byte i = 0 ; i < GPIO_MAX ; i + + ) {
if ( ( pin [ i ] > = 12 ) & & ( pin [ i ] < = 14 ) ) {
pin [ i ] = 99 ;
}
}
my_module . gp . io [ 12 ] = GPIO_SPI_MISO ;
pin [ GPIO_SPI_MISO ] = 12 ;
my_module . gp . io [ 13 ] = GPIO_SPI_MOSI ;
pin [ GPIO_SPI_MOSI ] = 13 ;
my_module . gp . io [ 14 ] = GPIO_SPI_CLK ;
pin [ GPIO_SPI_CLK ] = 14 ;
}
# endif // USE_SPI
2017-10-10 14:40:02 +01:00
# 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
2017-10-18 17:22:34 +01:00
devices_present = 1 ;
2017-12-25 16:41:12 +00:00
light_type = LT_BASIC ; // Use basic PWM control if SetOption15 = 0
2017-10-18 17:22:34 +01:00
if ( Settings . flag . pwm_control ) {
2017-10-10 14:40:02 +01:00
for ( byte i = 0 ; i < MAX_PWMS ; i + + ) {
2017-10-01 13:32:36 +01:00
if ( pin [ GPIO_PWM1 + i ] < 99 ) {
2017-10-18 17:22:34 +01:00
light_type + + ; // Use Dimmer/Color control for all PWM as SetOption15 = 1
2017-10-01 13:32:36 +01:00
}
}
}
2017-12-25 16:41:12 +00:00
2017-10-18 17:22:34 +01:00
if ( SONOFF_BRIDGE = = Settings . module ) {
baudrate = 19200 ;
2017-07-30 16:55:37 +01:00
}
2017-12-25 16:41:12 +00:00
2017-10-18 17:22:34 +01:00
if ( SONOFF_DUAL = = Settings . module ) {
devices_present = 2 ;
baudrate = 19200 ;
2017-01-28 13:41:01 +00:00
}
2017-10-18 17:22:34 +01:00
else if ( CH4 = = Settings . module ) {
devices_present = 4 ;
baudrate = 19200 ;
2017-02-13 16:25:46 +00:00
}
2017-10-18 17:22:34 +01:00
else if ( SONOFF_SC = = Settings . module ) {
devices_present = 0 ;
baudrate = 19200 ;
2017-04-10 16:25:31 +01:00
}
2017-10-18 17:22:34 +01:00
else if ( SONOFF_BN = = Settings . module ) { // PWM Single color led (White)
2017-10-25 13:27:30 +01:00
light_type = LT_PWM1 ;
2017-07-03 10:45:15 +01:00
}
2017-10-18 17:22:34 +01:00
else if ( SONOFF_LED = = Settings . module ) { // PWM Dual color led (White warm and cold)
2017-10-25 13:27:30 +01:00
light_type = LT_PWM2 ;
2017-02-13 16:25:46 +00:00
}
2017-10-18 17:22:34 +01:00
else if ( AILIGHT = = Settings . module ) { // RGBW led
2017-10-25 13:27:30 +01:00
light_type = LT_RGBW ;
2017-08-13 14:31:49 +01:00
}
2017-10-18 17:22:34 +01:00
else if ( SONOFF_B1 = = Settings . module ) { // RGBWC led
2017-10-25 13:27:30 +01:00
light_type = LT_RGBWC ;
2017-08-12 16:55:20 +01:00
}
2017-02-13 16:25:46 +00:00
else {
2017-10-18 17:22:34 +01:00
if ( ! light_type ) {
devices_present = 0 ;
2017-10-05 12:28:31 +01:00
}
2017-10-10 14:40:02 +01:00
for ( byte i = 0 ; i < MAX_RELAYS ; i + + ) {
2017-02-28 15:01:48 +00:00
if ( pin [ GPIO_REL1 + i ] < 99 ) {
pinMode ( pin [ GPIO_REL1 + i ] , OUTPUT ) ;
2017-10-18 17:22:34 +01:00
devices_present + + ;
2017-02-28 15:01:48 +00:00
}
2017-01-28 13:41:01 +00:00
}
}
2017-12-25 16:41:12 +00:00
2017-10-12 10:29:40 +01:00
for ( byte i = 0 ; i < MAX_KEYS ; i + + ) {
2017-07-30 16:55:37 +01:00
if ( pin [ GPIO_KEY1 + i ] < 99 ) {
2017-09-10 14:51:44 +01:00
pinMode ( pin [ GPIO_KEY1 + i ] , ( 16 = = pin [ GPIO_KEY1 + i ] ) ? INPUT_PULLDOWN_16 : INPUT_PULLUP ) ;
2017-07-30 16:55:37 +01:00
}
2017-10-10 14:40:02 +01:00
}
for ( byte i = 0 ; i < MAX_LEDS ; i + + ) {
2017-01-28 13:41:01 +00:00
if ( pin [ GPIO_LED1 + i ] < 99 ) {
pinMode ( pin [ GPIO_LED1 + i ] , OUTPUT ) ;
2017-10-10 14:40:02 +01:00
digitalWrite ( pin [ GPIO_LED1 + i ] , bitRead ( led_inverted , i ) ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-10 14:40:02 +01:00
}
for ( byte i = 0 ; i < MAX_SWITCHES ; i + + ) {
2017-01-28 13:41:01 +00:00
if ( pin [ GPIO_SWT1 + i ] < 99 ) {
2017-09-10 14:51:44 +01:00
pinMode ( pin [ GPIO_SWT1 + i ] , ( 16 = = pin [ GPIO_SWT1 + i ] ) ? INPUT_PULLDOWN_16 : INPUT_PULLUP ) ;
2017-01-28 13:41:01 +00:00
lastwallswitch [ i ] = digitalRead ( pin [ GPIO_SWT1 + i ] ) ; // set global now so doesn't change the saved power state on first switch check
}
}
2017-09-02 13:37:02 +01:00
2017-09-16 16:34:03 +01:00
# ifdef USE_WS2812
2017-10-18 17:22:34 +01:00
if ( ! light_type & & ( pin [ GPIO_WS2812 ] < 99 ) ) { // RGB led
devices_present + + ;
2017-10-25 13:27:30 +01:00
light_type = LT_WS2812 ;
2017-09-16 16:34:03 +01:00
}
# endif // USE_WS2812
2018-01-05 11:26:19 +00:00
if ( ! light_type ) {
2017-12-25 16:41:12 +00:00
for ( byte i = 0 ; i < MAX_PWMS ; i + + ) { // Basic PWM control only
2017-10-05 12:28:31 +01:00
if ( pin [ GPIO_PWM1 + i ] < 99 ) {
pinMode ( pin [ GPIO_PWM1 + i ] , OUTPUT ) ;
2017-10-18 17:22:34 +01:00
analogWrite ( pin [ GPIO_PWM1 + i ] , bitRead ( pwm_inverted , i ) ? Settings . pwm_range - Settings . pwm_value [ i ] : Settings . pwm_value [ i ] ) ;
2017-10-05 12:28:31 +01:00
}
2017-03-19 17:19:08 +00:00
}
}
2017-05-17 21:49:22 +01:00
2017-10-18 17:22:34 +01:00
if ( EXS_RELAY = = Settings . module ) {
SetLatchingRelay ( 0 , 2 ) ;
SetLatchingRelay ( 1 , 2 ) ;
2017-02-13 16:25:46 +00:00
}
2017-10-18 17:22:34 +01:00
SetLedPower ( Settings . ledstate & 8 ) ;
2017-01-28 13:41:01 +00:00
2018-01-24 16:31:20 +00:00
XdrvCall ( FUNC_INIT ) ;
2017-01-28 13:41:01 +00:00
}
2017-04-29 13:40:53 +01:00
extern " C " {
extern struct rst_info resetInfo ;
}
2017-01-28 13:41:01 +00:00
void setup ( )
{
byte idx ;
2017-10-18 17:22:34 +01:00
Serial . begin ( baudrate ) ;
2017-01-28 13:41:01 +00:00
delay ( 10 ) ;
Serial . println ( ) ;
seriallog_level = LOG_LEVEL_INFO ; // Allow specific serial messages until config loaded
2018-01-10 13:10:25 +00:00
snprintf_P ( my_version , sizeof ( my_version ) , PSTR ( " %d.%d.%d " ) , VERSION > > 24 & 0xff , VERSION > > 16 & 0xff , VERSION > > 8 & 0xff ) ;
if ( VERSION & 0x1f ) {
idx = strlen ( my_version ) ;
my_version [ idx ] = 96 + ( VERSION & 0x1f ) ;
my_version [ idx + 1 ] = 0 ;
}
# ifdef BE_MINIMAL
snprintf_P ( my_version , sizeof ( my_version ) , PSTR ( " %s- " D_JSON_MINIMAL ) , my_version ) ;
# endif // BE_MINIMAL
2017-10-18 17:22:34 +01:00
SettingsLoad ( ) ;
SettingsDelta ( ) ;
2017-01-28 13:41:01 +00:00
2017-10-18 17:22:34 +01:00
OsWatchInit ( ) ;
2017-02-28 15:01:48 +00:00
2017-10-18 17:22:34 +01:00
seriallog_level = Settings . seriallog_level ;
2017-08-24 10:09:52 +01:00
seriallog_timer = SERIALLOG_TIMER ;
2017-03-05 14:07:30 +00:00
# ifndef USE_EMULATION
2017-11-11 11:33:30 +00:00
Settings . flag2 . emulation = 0 ;
2017-03-05 14:07:30 +00:00
# endif // USE_EMULATION
2017-11-11 11:33:30 +00:00
syslog_level = ( Settings . flag2 . emulation ) ? 0 : Settings . syslog_level ;
2017-10-18 17:22:34 +01:00
stop_flash_rotate = Settings . flag . stop_flash_rotate ;
save_data_counter = Settings . save_data ;
sleep = Settings . sleep ;
2017-01-28 13:41:01 +00:00
2017-10-18 17:22:34 +01:00
Settings . bootcount + + ;
snprintf_P ( log_data , sizeof ( log_data ) , PSTR ( D_LOG_APPLICATION D_BOOT_COUNT " %d " ) , Settings . bootcount ) ;
AddLog ( LOG_LEVEL_DEBUG ) ;
2017-08-24 10:09:52 +01:00
2017-10-18 17:22:34 +01:00
GpioInit ( ) ;
2017-01-28 13:41:01 +00:00
2017-12-04 16:25:06 +00:00
SetSerialBaudrate ( baudrate ) ;
2017-01-28 13:41:01 +00:00
2017-10-18 17:22:34 +01:00
if ( strstr ( Settings . hostname , " % " ) ) {
strlcpy ( Settings . hostname , WIFI_HOSTNAME , sizeof ( Settings . hostname ) ) ;
snprintf_P ( my_hostname , sizeof ( my_hostname ) - 1 , Settings . hostname , Settings . mqtt_topic , ESP . getChipId ( ) & 0x1FFF ) ;
2017-01-28 13:41:01 +00:00
} else {
2017-10-18 17:22:34 +01:00
snprintf_P ( my_hostname , sizeof ( my_hostname ) - 1 , Settings . hostname ) ;
2017-01-28 13:41:01 +00:00
}
2017-10-18 17:22:34 +01:00
WifiConnect ( ) ;
2017-01-28 13:41:01 +00:00
2017-10-18 17:22:34 +01:00
GetMqttClient ( mqtt_client , Settings . mqtt_client , sizeof ( mqtt_client ) ) ;
2017-01-28 13:41:01 +00:00
2017-10-18 17:22:34 +01:00
if ( MOTOR = = Settings . module ) {
2018-01-24 16:31:20 +00:00
Settings . poweronstate = POWER_ALL_ON ; // Needs always on else in limbo!
2017-04-25 17:24:42 +01:00
}
2018-01-24 16:31:20 +00:00
if ( POWER_ALL_ALWAYS_ON = = Settings . poweronstate ) {
2017-10-18 17:22:34 +01:00
SetDevicePower ( 1 ) ;
2017-05-05 16:57:05 +01:00
} else {
if ( ( resetInfo . reason = = REASON_DEFAULT_RST ) | | ( resetInfo . reason = = REASON_EXT_SYS_RST ) ) {
2017-10-18 17:22:34 +01:00
switch ( Settings . poweronstate ) {
2018-01-24 16:31:20 +00:00
case POWER_ALL_OFF :
case POWER_ALL_OFF_PULSETIME_ON :
2017-05-05 16:57:05 +01:00
power = 0 ;
2017-10-18 17:22:34 +01:00
SetDevicePower ( power ) ;
2017-05-05 16:57:05 +01:00
break ;
2018-01-24 16:31:20 +00:00
case POWER_ALL_ON : // All on
2017-10-18 17:22:34 +01:00
power = ( 1 < < devices_present ) - 1 ;
SetDevicePower ( power ) ;
2017-05-05 16:57:05 +01:00
break ;
2018-01-24 16:31:20 +00:00
case POWER_ALL_SAVED_TOGGLE :
2017-10-18 17:22:34 +01:00
power = Settings . power & ( ( 1 < < devices_present ) - 1 ) ^ POWER_MASK ;
if ( Settings . flag . save_state ) {
SetDevicePower ( power ) ;
2017-05-05 16:57:05 +01:00
}
break ;
2018-01-24 16:31:20 +00:00
case POWER_ALL_SAVED :
2017-10-18 17:22:34 +01:00
power = Settings . power & ( ( 1 < < devices_present ) - 1 ) ;
if ( Settings . flag . save_state ) {
SetDevicePower ( power ) ;
2017-05-05 16:57:05 +01:00
}
break ;
2017-04-25 17:24:42 +01:00
}
2017-05-05 16:57:05 +01:00
} else {
2017-10-18 17:22:34 +01:00
power = Settings . power & ( ( 1 < < devices_present ) - 1 ) ;
if ( Settings . flag . save_state ) {
SetDevicePower ( power ) ;
2017-04-25 17:24:42 +01:00
}
2017-01-28 13:41:01 +00:00
}
}
2017-08-29 15:35:45 +01:00
2017-10-14 10:26:49 +01:00
// Issue #526 and #909
2017-10-18 17:22:34 +01:00
for ( byte i = 0 ; i < devices_present ; i + + ) {
2017-10-14 10:26:49 +01:00
if ( ( i < MAX_RELAYS ) & & ( pin [ GPIO_REL1 + i ] < 99 ) ) {
bitWrite ( power , i , digitalRead ( pin [ GPIO_REL1 + i ] ) ^ bitRead ( rel_inverted , i ) ) ;
2017-08-29 15:35:45 +01:00
}
2018-01-24 16:31:20 +00:00
if ( ( i < MAX_PULSETIMERS ) & & ( bitRead ( power , i ) | | ( POWER_ALL_OFF_PULSETIME_ON = = Settings . poweronstate ) ) ) {
2017-10-18 17:22:34 +01:00
pulse_timer [ i ] = Settings . pulse_timer [ i ] ;
2017-10-12 13:09:19 +01:00
}
}
2017-09-02 13:37:02 +01:00
2017-01-28 13:41:01 +00:00
blink_powersave = power ;
2018-01-10 13:10:25 +00:00
snprintf_P ( log_data , sizeof ( log_data ) , PSTR ( D_PROJECT " %s %s ( " D_CMND_TOPIC " %s, " D_FALLBACK " %s, " D_CMND_GROUPTOPIC " %s) " D_VERSION " %s " ) ,
PROJECT , Settings . friendlyname [ 0 ] , Settings . mqtt_topic , mqtt_client , Settings . mqtt_grptopic , my_version ) ;
AddLog ( LOG_LEVEL_INFO ) ;
# ifdef BE_MINIMAL
snprintf_P ( log_data , sizeof ( log_data ) , PSTR ( D_WARNING_MINIMAL_VERSION ) ) ;
2017-10-18 17:22:34 +01:00
AddLog ( LOG_LEVEL_INFO ) ;
2018-01-10 13:10:25 +00:00
# endif // BE_MINIMAL
2017-12-01 14:59:53 +00:00
RtcInit ( ) ;
2018-01-24 16:31:20 +00:00
XsnsCall ( FUNC_INIT ) ;
2017-01-28 13:41:01 +00:00
}
void loop ( )
{
2017-10-18 17:22:34 +01:00
OsWatchLoop ( ) ;
2017-09-02 13:37:02 +01:00
2017-01-28 13:41:01 +00:00
# ifdef USE_WEBSERVER
2017-10-18 17:22:34 +01:00
PollDnsWebserver ( ) ;
2017-01-28 13:41:01 +00:00
# endif // USE_WEBSERVER
2017-01-29 20:36:12 +00:00
# ifdef USE_EMULATION
2017-11-11 11:33:30 +00:00
if ( Settings . flag2 . emulation ) {
2017-10-18 17:22:34 +01:00
PollUdp ( ) ;
2017-04-25 17:24:42 +01:00
}
2017-01-29 20:36:12 +00:00
# endif // USE_EMULATION
2017-01-28 13:41:01 +00:00
2017-10-18 17:22:34 +01:00
if ( millis ( ) > = state_loop_timer ) {
StateLoop ( ) ;
2017-04-25 17:24:42 +01:00
}
2017-10-18 17:22:34 +01:00
if ( Settings . flag . mqtt_enabled ) {
MqttClient . loop ( ) ;
2017-04-25 17:24:42 +01:00
}
if ( Serial . available ( ) ) {
2017-10-18 17:22:34 +01:00
SerialInput ( ) ;
2017-04-25 17:24:42 +01:00
}
2017-01-28 13:41:01 +00:00
2017-01-29 13:52:31 +00:00
// yield(); // yield == delay(0), delay contains yield, auto yield in loop
delay ( sleep ) ; // https://github.com/esp8266/Arduino/issues/2021
2017-08-08 15:08:08 +01:00
}