5.1.6 20170606
* Shrink code
* Removed online configuration of Domoticz In and Domoticz Out MQTT
strings
* Removed commands DomoticzInTopic and DomoticzOutTopic
* Add define KEY_HOLD_TIME to configure button hold threshold before
sending MQTT Hold message
* Add command StateText4 to configure button MQTT Hold text (=
MQTT_CMND_HOLD)
* Add command SetOption11 0|1 to swap pushbutton single and double press
functionality (#200)
* Add command SwitchMode<x> 5 (PUSHBUTTONHOLD) and 6
(PUSHBUTTONHOLD_INV) (#489)
This commit is contained in:
arendst 2017-06-06 23:23:23 +02:00
parent 0f103db4c6
commit 98d06e8809
10 changed files with 252 additions and 208 deletions

View File

@ -1,7 +1,7 @@
## Sonoff-Tasmota
Provide ESP8266 based Sonoff by [iTead Studio](https://www.itead.cc/) and ElectroDragon IoT Relay with Serial, Web and MQTT control allowing 'Over the Air' or OTA firmware updates using Arduino IDE.
Current version is **5.1.5** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/_releasenotes.ino) for change information.
Current version is **5.1.6** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/_releasenotes.ino) for change information.
### **** ATTENTION Version 5.x.x specific information ****

View File

@ -1,4 +1,13 @@
/* 5.1.5 20170604
/* 5.1.6 20170606
* Shrink code
* Removed online configuration of Domoticz In and Domoticz Out MQTT strings
* Removed commands DomoticzInTopic and DomoticzOutTopic
* Add define KEY_HOLD_TIME to configure button hold threshold before sending MQTT Hold message
* Add command StateText4 to configure button MQTT Hold text (= MQTT_CMND_HOLD)
* Add command SetOption11 0|1 to swap pushbutton single and double press functionality (#200)
* Add command SwitchMode<x> 5 (PUSHBUTTONHOLD) and 6 (PUSHBUTTONHOLD_INV) (#489)
*
* 5.1.5 20170604
* Shrink code in preparation to ESP8266-Arduino 2.4.0-rc1
* Add effect parameter to HUE Device (#464)
*
@ -14,7 +23,7 @@
* 5.1.2 20170519
* Fix Counter/Timer JSON message and update Counter/Timer on webpage
* Fix WS2812 Domoticz related regression issues
*
*
* 5.1.1 20170517
* Allow command FullTopic in group mode
* Prepare for more use of RTC memory

View File

@ -17,21 +17,21 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
typedef union { // Restricted by MISRA-C Rule 18.4 but so usefull...
uint32_t data; // Allow bit manipulation using SetOption
typedef union { // Restricted by MISRA-C Rule 18.4 but so usefull...
uint32_t data; // Allow bit manipulation using SetOption
struct {
uint32_t savestate : 1; // bit 0
uint32_t button_restrict : 1; // bit 1
uint32_t value_units : 1; // bit 2
uint32_t savestate : 1; // bit 0
uint32_t button_restrict : 1; // bit 1
uint32_t value_units : 1; // bit 2
uint32_t mqtt_enabled : 1;
uint32_t mqtt_response : 1; // bit 4
uint32_t mqtt_response : 1; // bit 4
uint32_t mqtt_power_retain : 1;
uint32_t mqtt_button_retain : 1;
uint32_t mqtt_switch_retain : 1;
uint32_t temperature_conversion : 1; // bit 8
uint32_t temperature_conversion : 1; // bit 8
uint32_t mqtt_sensor_retain : 1;
uint32_t mqtt_offline : 1; // bit 10
uint32_t spare11 : 1;
uint32_t mqtt_offline : 1; // bit 10
uint32_t button_swap : 1; // bit 11 (v5.1.6)
uint32_t spare12 : 1;
uint32_t spare13 : 1;
uint32_t spare14 : 1;
@ -54,15 +54,15 @@ struct SYSCFG {
unsigned long saveFlag;
unsigned long version;
unsigned long bootcount;
sysBitfield flag; // Add flag since 5.0.2
sysBitfield flag; // Add flag since 5.0.2
int16_t savedata;
int8_t timezone;
char otaUrl[101];
char mqtt_prefix[3][11]; // was ex_friendlyname[33] until 3.2.5
char mqtt_prefix[3][11]; // was ex_friendlyname[33] until 3.2.5
byte serial_enable; // Not used (ever)
byte serial_enable; // Not used (ever)
byte seriallog_level;
uint8_t sta_config;
byte sta_active;
@ -84,19 +84,20 @@ struct SYSCFG {
char mqtt_topic[33];
char button_topic[33];
char mqtt_grptopic[33];
char state_text[3][11]; // was ex_mqtt_subtopic[33] until 4.1.1
byte ex_mqtt_button_retain; // Not used since 5.0.2
byte ex_mqtt_power_retain; // Not used since 5.0.2
byte ex_value_units; // Not used since 5.0.2
byte ex_button_restrict; // Not used since 5.0.2
char ex_state_text[3][11]; // was state_text until 5.1.6, was ex_mqtt_subtopic[33] until 4.1.1
byte ex_mqtt_button_retain; // Not used since 5.0.2
byte ex_mqtt_power_retain; // Not used since 5.0.2
byte ex_value_units; // Not used since 5.0.2
byte ex_button_restrict; // Not used since 5.0.2
uint16_t tele_period;
uint8_t power;
uint8_t ledstate;
uint8_t ex_switchmode; // Not used since 3.9.21
uint8_t ex_switchmode; // Not used since 3.9.21
char domoticz_in_topic[33];
char domoticz_out_topic[33];
char ex_domoticz_in_topic[22]; // Not used since 5.1.6
char state_text[4][11]; // was domoticz_out_topic until 5.1.6
uint16_t domoticz_update_timer;
unsigned long domoticz_relay_idx[4];
unsigned long domoticz_key_idx[4];
@ -123,7 +124,7 @@ struct SYSCFG {
uint16_t hlw_mkwhs; // MaxEnergyStart
// 3.0.6
uint16_t mqtt_retry; // was ex_pulsetime until 4.0.4
uint16_t mqtt_retry; // was ex_pulsetime until 4.0.4
// 3.1.1
uint8_t poweronstate;
@ -150,8 +151,8 @@ struct SYSCFG {
// 3.2.8
char switch_topic[33];
byte ex_mqtt_switch_retain; // Not used since 5.0.2
uint8_t ex_mqtt_enabled; // Not used since 5.0.2
byte ex_mqtt_switch_retain; // Not used since 5.0.2
uint8_t ex_mqtt_enabled; // Not used since 5.0.2
// 3.2.12
uint8_t sleep;
@ -172,7 +173,7 @@ struct SYSCFG {
uint16_t led_wakeup;
// 3.9.7
uint8_t ex_emulation; // Not used since 5.0.2
uint8_t ex_emulation; // Not used since 5.0.2
// 3.9.20
char web_password[33];

View File

@ -386,8 +386,6 @@ void CFG_DefaultSet2()
sysCfg.blinkcount = APP_BLINKCOUNT;
sysCfg.sleep = APP_SLEEP;
strlcpy(sysCfg.domoticz_in_topic, DOMOTICZ_IN_TOPIC, sizeof(sysCfg.domoticz_in_topic));
strlcpy(sysCfg.domoticz_out_topic, DOMOTICZ_OUT_TOPIC, sizeof(sysCfg.domoticz_out_topic));
sysCfg.domoticz_update_timer = DOMOTICZ_UPDATE_TIMER;
for (byte i = 0; i < 4; i++) {
sysCfg.switchmode[i] = SWITCH_MODE;
@ -443,7 +441,7 @@ void CFG_DefaultSet2()
// 4.0.9
CFG_DefaultSet_4_0_9();
// 4.1.1
// 4.1.1 + 5.1.6
CFG_DefaultSet_4_1_1();
// 5.0.2
@ -540,6 +538,7 @@ void CFG_DefaultSet_4_1_1()
strlcpy(sysCfg.state_text[0], MQTT_STATUS_OFF, sizeof(sysCfg.state_text[0]));
strlcpy(sysCfg.state_text[1], MQTT_STATUS_ON, sizeof(sysCfg.state_text[1]));
strlcpy(sysCfg.state_text[2], MQTT_CMND_TOGGLE, sizeof(sysCfg.state_text[2]));
strlcpy(sysCfg.state_text[3], MQTT_CMND_HOLD, sizeof(sysCfg.state_text[3])); // v5.1.6
}
void CFG_DefaultSet_5_0_2()
@ -647,6 +646,11 @@ void CFG_Delta()
rtcMem.pCounter[i] = 0;
}
}
if (sysCfg.version < 0x05010600) {
memcpy(sysCfg.state_text, sysCfg.ex_state_text, 33);
strlcpy(sysCfg.state_text[3], MQTT_CMND_HOLD, sizeof(sysCfg.state_text[3]));
}
sysCfg.version = VERSION;
}
}

View File

@ -24,14 +24,14 @@
- Select IDE Tools - Flash size: "1M (no SPIFFS)"
====================================================*/
#define VERSION 0x05010500 // 5.1.5
#define VERSION 0x05010600 // 5.1.6
enum log_t {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL};
enum week_t {Last, First, Second, Third, Fourth};
enum dow_t {Sun=1, Mon, Tue, Wed, Thu, Fri, Sat};
enum month_t {Jan=1, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec};
enum wifi_t {WIFI_RESTART, WIFI_SMARTCONFIG, WIFI_MANAGER, WIFI_WPSCONFIG, WIFI_RETRY, MAX_WIFI_OPTION};
enum swtch_t {TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, MAX_SWITCH_OPTION};
enum swtch_t {TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD, PUSHBUTTONHOLD_INV, MAX_SWITCH_OPTION};
enum led_t {LED_OFF, LED_POWER, LED_MQTTSUB, LED_POWER_MQTTSUB, LED_MQTTPUB, LED_POWER_MQTTPUB, LED_MQTT, LED_POWER_MQTT, MAX_LED_OPTION};
enum emul_t {EMUL_NONE, EMUL_WEMO, EMUL_HUE, EMUL_MAX};
@ -278,6 +278,7 @@ uint8_t holdcount = 0; // Timer recording button hold
uint8_t multiwindow = 0; // Max time between button presses to record press count
uint8_t multipress = 0; // Number of button presses within multiwindow
uint8_t lastwallswitch[4]; // Last wall switch states
uint8_t wallswitchtimer[4] = { 0 }; // Timer for wallswitch push button hold
uint8_t blockgpio0 = 4; // Block GPIO0 for 4 seconds after poweron to workaround Wemos D1 RTS circuit
mytmplt my_module; // Active copy of GPIOs
@ -348,7 +349,7 @@ void getTopic_P(char *stopic, byte prefix, char *topic, const char* subtopic)
char* getStateText(byte state)
{
if (state > 2) {
if (state > 3) {
state = 1;
}
return sysCfg.state_text[state];
@ -646,26 +647,26 @@ boolean mqtt_command(boolean grpflg, char *type, uint16_t index, char *dataBuf,
snprintf_P(svalue, ssvalue, PSTR("{\"MqttHost\",\"%s\"}"), sysCfg.mqtt_host);
}
else if (!strcmp_P(type,PSTR("MQTTPORT"))) {
if ((data_len > 0) && (payload > 0) && (payload < 32766)) {
if ((payload > 0) && (payload < 32766)) {
sysCfg.mqtt_port = (1 == payload) ? MQTT_PORT : payload;
restartflag = 2;
}
snprintf_P(svalue, ssvalue, PSTR("{\"MqttPort\":%d}"), sysCfg.mqtt_port);
}
else if (!strcmp_P(type,PSTR("MQTTRETRY"))) {
if ((data_len > 0) && (payload >= MQTT_RETRY_SECS) && (payload < 32001)) {
if ((payload >= MQTT_RETRY_SECS) && (payload < 32001)) {
sysCfg.mqtt_retry = payload;
mqttcounter = sysCfg.mqtt_retry;
}
snprintf_P(svalue, ssvalue, PSTR("{\"MqttRetry\":%d}"), sysCfg.mqtt_retry);
}
else if (!strcmp_P(type,PSTR("MQTTRESPONSE"))) {
if ((data_len > 0) && (payload >= 0) && (payload <= 1)) {
if ((payload >= 0) && (payload <= 1)) {
sysCfg.flag.mqtt_response = payload;
}
snprintf_P(svalue, ssvalue, PSTR("{\"MqttResponse\":\"%s\"}"), getStateText(sysCfg.flag.mqtt_response));
}
else if (!strcmp_P(type,PSTR("STATETEXT")) && (index > 0) && (index <= 3)) {
else if (!strcmp_P(type,PSTR("STATETEXT")) && (index > 0) && (index <= 4)) {
if ((data_len > 0) && (data_len < sizeof(sysCfg.state_text[0]))) {
for(i = 0; i <= data_len; i++) {
if (dataBuf[i] == ' ') {
@ -803,11 +804,11 @@ boolean mqtt_command(boolean grpflg, char *type, uint16_t index, char *dataBuf,
snprintf_P(svalue, ssvalue, PSTR("{\"SwitchTopic\":\"%s\"}"), sysCfg.switch_topic);
}
else if (!strcmp_P(type,PSTR("BUTTONRETAIN"))) {
if ((data_len > 0) && (payload >= 0) && (payload <= 1)) {
if ((payload >= 0) && (payload <= 1)) {
strlcpy(sysCfg.button_topic, sysCfg.mqtt_topic, sizeof(sysCfg.button_topic));
if (!payload) {
for(i = 1; i <= Maxdevice; i++) {
send_button_power(0, i, 3); // Clear MQTT retain in broker
send_button_power(0, i, 9); // Clear MQTT retain in broker
}
}
sysCfg.flag.mqtt_button_retain = payload;
@ -815,11 +816,11 @@ boolean mqtt_command(boolean grpflg, char *type, uint16_t index, char *dataBuf,
snprintf_P(svalue, ssvalue, PSTR("{\"ButtonRetain\":\"%s\"}"), getStateText(sysCfg.flag.mqtt_button_retain));
}
else if (!strcmp_P(type,PSTR("SWITCHRETAIN"))) {
if ((data_len > 0) && (payload >= 0) && (payload <= 1)) {
if ((payload >= 0) && (payload <= 1)) {
strlcpy(sysCfg.button_topic, sysCfg.mqtt_topic, sizeof(sysCfg.button_topic));
if (!payload) {
for(i = 1; i <= 4; i++) {
send_button_power(1, i, 3); // Clear MQTT retain in broker
send_button_power(1, i, 9); // Clear MQTT retain in broker
}
}
sysCfg.flag.mqtt_switch_retain = payload;
@ -827,7 +828,7 @@ boolean mqtt_command(boolean grpflg, char *type, uint16_t index, char *dataBuf,
snprintf_P(svalue, ssvalue, PSTR("{\"SwitchRetain\":\"%s\"}"), getStateText(sysCfg.flag.mqtt_switch_retain));
}
else if (!strcmp_P(type,PSTR("POWERRETAIN"))) {
if ((data_len > 0) && (payload >= 0) && (payload <= 1)) {
if ((payload >= 0) && (payload <= 1)) {
if (!payload) {
for(i = 1; i <= Maxdevice; i++) { // Clear MQTT retain in broker
snprintf_P(stemp2, sizeof(stemp2), PSTR("%d"), i);
@ -845,7 +846,7 @@ boolean mqtt_command(boolean grpflg, char *type, uint16_t index, char *dataBuf,
snprintf_P(svalue, ssvalue, PSTR("{\"PowerRetain\":\"%s\"}"), getStateText(sysCfg.flag.mqtt_power_retain));
}
else if (!strcmp_P(type,PSTR("SENSORRETAIN"))) {
if ((data_len > 0) && (payload >= 0) && (payload <= 1)) {
if ((payload >= 0) && (payload <= 1)) {
if (!payload) {
svalue[0] = '\0';
mqtt_publish_topic_P(2, PSTR("SENSOR"), svalue, sysCfg.flag.mqtt_sensor_retain);
@ -948,8 +949,12 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
if (!strcmp(dataBufUc,"?")) {
data_len = 0;
}
int16_t payload = atoi(dataBuf); // -32766 - 32767
int16_t payload = -1;
if (data_len && isdigit(dataBuf[0])) {
payload = atoi(dataBuf); // -32766 - 32767
}
uint16_t payload16 = atoi(dataBuf); // 0 - 65535
if (!strcmp_P(dataBufUc,PSTR("OFF")) || !strcmp_P(dataBufUc,PSTR("FALSE")) || !strcmp_P(dataBufUc,PSTR("STOP")) || !strcmp_P(dataBufUc,PSTR("CELSIUS"))) {
payload = 0;
}
@ -966,25 +971,28 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
payload = 4;
}
// snprintf_P(svalue, sizeof(svalue), PSTR("RSLT: Payload %d, Payload16 %d"), payload, payload16);
// addLog(LOG_LEVEL_DEBUG, svalue);
if (!strcmp_P(type,PSTR("POWER")) && (index > 0) && (index <= Maxdevice)) {
if ((0 == data_len) || (payload > 4)) {
if ((payload < 0) || (payload > 4)) {
payload = 9;
}
do_cmnd_power(index, payload);
return;
}
else if (!strcmp_P(type,PSTR("STATUS"))) {
if ((0 == data_len) || (payload < 0) || (payload > MAX_STATUS)) {
if ((payload < 0) || (payload > MAX_STATUS)) {
payload = 99;
}
publish_status(payload);
return;
}
else if ((sysCfg.module != MOTOR) && !strcmp_P(type,PSTR("POWERONSTATE"))) {
if ((data_len > 0) && (payload >= 0) && (payload <= 4)) {
if ((payload >= 0) && (payload <= 4)) {
sysCfg.poweronstate = payload;
if (4 == sysCfg.poweronstate) {
for(byte i = 1; i <= Maxdevice; i++) {
for (byte i = 1; i <= Maxdevice; i++) {
do_cmnd_power(i, 1);
}
}
@ -999,7 +1007,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
snprintf_P(svalue, sizeof(svalue), PSTR("{\"PulseTime%d\":%d}"), index, sysCfg.pulsetime[index -1]);
}
else if (!strcmp_P(type,PSTR("BLINKTIME"))) {
if ((data_len > 0) && (payload > 2) && (payload <= 3600)) {
if ((payload > 2) && (payload <= 3600)) {
sysCfg.blinktime = payload;
if (blink_timer) {
blink_timer = sysCfg.blinktime;
@ -1020,7 +1028,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
// Serviced
}
else if (!strcmp_P(type,PSTR("SAVEDATA"))) {
if ((data_len > 0) && (payload >= 0) && (payload <= 3600)) {
if ((payload >= 0) && (payload <= 3600)) {
sysCfg.savedata = payload;
savedatacounter = sysCfg.savedata;
}
@ -1033,8 +1041,8 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
}
snprintf_P(svalue, sizeof(svalue), PSTR("{\"SaveData\":\"%s\"}"), (sysCfg.savedata > 1) ? stemp1 : getStateText(sysCfg.savedata));
}
else if (!strcmp_P(type,PSTR("SETOPTION")) && (index >= 0) && (index <= 10)) {
if ((data_len > 0) && (payload >= 0) && (payload <= 1)) {
else if (!strcmp_P(type,PSTR("SETOPTION")) && (index >= 0) && (index <= 11)) {
if ((payload >= 0) && (payload <= 1)) {
switch (index) {
case 0: // savestate
case 1: // button_restrict
@ -1042,68 +1050,69 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
case 4: // mqtt_response
case 8: // temperature_conversion
case 10: // mqtt_offline
case 11: // button_swap
bitWrite(sysCfg.flag.data, index, payload);
}
}
snprintf_P(svalue, sizeof(svalue), PSTR("{\"SetOption%d\":\"%s\"}"), index, getStateText(bitRead(sysCfg.flag.data, index)));
}
else if (!strcmp_P(type,PSTR("SAVESTATE"))) {
if ((data_len > 0) && (payload >= 0) && (payload <= 1)) {
if ((payload >= 0) && (payload <= 1)) {
sysCfg.flag.savestate = payload;
}
snprintf_P(svalue, sizeof(svalue), PSTR("{\"SaveState\":\"%s\"}"), getStateText(sysCfg.flag.savestate));
}
else if (!strcmp_P(type,PSTR("BUTTONRESTRICT"))) {
if ((data_len > 0) && (payload >= 0) && (payload <= 1)) {
if ((payload >= 0) && (payload <= 1)) {
sysCfg.flag.button_restrict = payload;
}
snprintf_P(svalue, sizeof(svalue), PSTR("{\"ButtonRestrict\":\"%s\"}"), getStateText(sysCfg.flag.button_restrict));
}
else if (!strcmp_P(type,PSTR("UNITS"))) {
if ((data_len > 0) && (payload >= 0) && (payload <= 1)) {
if ((payload >= 0) && (payload <= 1)) {
sysCfg.flag.value_units = payload;
}
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Units\":\"%s\"}"), getStateText(sysCfg.flag.value_units));
}
else if (!strcmp_P(type,PSTR("MQTT"))) {
if ((data_len > 0) && (payload >= 0) && (payload <= 1)) {
if ((payload >= 0) && (payload <= 1)) {
sysCfg.flag.mqtt_enabled = payload;
restartflag = 2;
}
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Mqtt\":\"%s\"}"), getStateText(sysCfg.flag.mqtt_enabled));
}
else if (!strcmp_P(type,PSTR("TEMPUNIT"))) {
if ((data_len > 0) && (payload >= 0) && (payload <= 1)) {
if ((payload >= 0) && (payload <= 1)) {
sysCfg.flag.temperature_conversion = payload;
}
snprintf_P(svalue, sizeof(svalue), PSTR("{\"TempUnit\":\"%s\"}"), (sysCfg.flag.temperature_conversion) ? "Fahrenheit" : "Celsius");
}
else if (!strcmp_P(type,PSTR("TEMPRES"))) {
if ((data_len > 0) && (payload >= 0) && (payload <= 3)) {
if ((payload >= 0) && (payload <= 3)) {
sysCfg.flag.temperature_resolution = payload;
}
snprintf_P(svalue, sizeof(svalue), PSTR("{\"TempRes\":%d}"), sysCfg.flag.temperature_resolution);
}
else if (!strcmp_P(type,PSTR("HUMRES"))) {
if ((data_len > 0) && (payload >= 0) && (payload <= 3)) {
if ((payload >= 0) && (payload <= 3)) {
sysCfg.flag.humidity_resolution = payload;
}
snprintf_P(svalue, sizeof(svalue), PSTR("{\"HumRes\":%d}"), sysCfg.flag.humidity_resolution);
}
else if (!strcmp_P(type,PSTR("PRESSRES"))) {
if ((data_len > 0) && (payload >= 0) && (payload <= 3)) {
if ((payload >= 0) && (payload <= 3)) {
sysCfg.flag.pressure_resolution = payload;
}
snprintf_P(svalue, sizeof(svalue), PSTR("{\"PressRes\":%d}"), sysCfg.flag.pressure_resolution);
}
else if (!strcmp_P(type,PSTR("ENERGYRES"))) {
if ((data_len > 0) && (payload >= 0) && (payload <= 5)) {
if ((payload >= 0) && (payload <= 5)) {
sysCfg.flag.energy_resolution = payload;
}
snprintf_P(svalue, sizeof(svalue), PSTR("{\"EnergyRes\":%d}"), sysCfg.flag.energy_resolution);
}
else if (!strcmp_P(type,PSTR("MODULE"))) {
if ((data_len > 0) && (payload > 0) && (payload <= MAXMODULE)) {
if ((payload > 0) && (payload <= MAXMODULE)) {
payload--;
byte new_modflg = (sysCfg.module != payload);
sysCfg.module = payload;
@ -1146,7 +1155,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
else if (!strcmp_P(type,PSTR("GPIO")) && (index < MAX_GPIO_PIN)) {
mytmplt cmodule;
memcpy_P(&cmodule, &modules[sysCfg.module], sizeof(cmodule));
if ((data_len > 0) && (GPIO_USER == cmodule.gp.io[index]) && (payload >= 0) && (payload < GPIO_SENSOR_END)) {
if ((GPIO_USER == cmodule.gp.io[index]) && (payload >= 0) && (payload < GPIO_SENSOR_END)) {
for (byte i = 0; i < MAX_GPIO_PIN; i++) {
if ((GPIO_USER == cmodule.gp.io[i]) && (sysCfg.my_module.gp.io[i] == payload)) {
sysCfg.my_module.gp.io[i] = 0;
@ -1199,7 +1208,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
snprintf_P(svalue, sizeof(svalue), PSTR("%s\"}"), svalue);
}
else if (!strcmp_P(type,PSTR("PWM")) && (index > pwm_idxoffset) && (index <= 5)) {
if ((data_len > 0) && (payload >= 0) && (payload <= PWM_RANGE) && (pin[GPIO_PWM1 + index -1] < 99)) {
if ((payload >= 0) && (payload <= PWM_RANGE) && (pin[GPIO_PWM1 + index -1] < 99)) {
sysCfg.pwmvalue[index -1] = payload;
analogWrite(pin[GPIO_PWM1 + index -1], payload);
}
@ -1221,7 +1230,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Counter%d\":%d}"), index, rtcMem.pCounter[index -1]);
}
else if (!strcmp_P(type,PSTR("COUNTERTYPE")) && (index > 0) && (index <= MAX_COUNTERS)) {
if ((data_len > 0) && (payload >= 0) && (payload <= 1) && (pin[GPIO_CNTR1 + index -1] < 99)) {
if ((payload >= 0) && (payload <= 1) && (pin[GPIO_CNTR1 + index -1] < 99)) {
bitWrite(sysCfg.pCounterType, index -1, payload &1);
rtcMem.pCounter[index -1] = 0;
sysCfg.pCounter[index -1] = 0;
@ -1235,7 +1244,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
snprintf_P(svalue, sizeof(svalue), PSTR("{\"CounterDebounce\":%d}"), sysCfg.pCounterDebounce);
}
else if (!strcmp_P(type,PSTR("SLEEP"))) {
if ((data_len > 0) && (payload >= 0) && (payload < 251)) {
if ((payload >= 0) && (payload < 251)) {
if ((!sysCfg.sleep && payload) || (sysCfg.sleep && !payload)) {
restartflag = 2;
}
@ -1245,7 +1254,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Sleep\":\"%d%s (%d%s)\"}"), sleep, (sysCfg.flag.value_units) ? " mS" : "", sysCfg.sleep, (sysCfg.flag.value_units) ? " mS" : "");
}
else if (!strcmp_P(type,PSTR("FLASHMODE"))) { // 0 = QIO, 1 = QOUT, 2 = DIO, 3 = DOUT
if ((data_len > 0) && (payload >= 0) && (payload <= 3)) {
if ((payload >= 0) && (payload <= 3)) {
if (ESP.getFlashChipMode() != payload) {
setFlashMode(0, payload &3);
}
@ -1253,7 +1262,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
snprintf_P(svalue, sizeof(svalue), PSTR("{\"FlashMode\":%d}"), ESP.getFlashChipMode());
}
else if (!strcmp_P(type,PSTR("UPGRADE")) || !strcmp_P(type,PSTR("UPLOAD"))) {
if ((data_len > 0) && (1 == payload)) {
if (1 == payload) {
otaflag = 3;
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Upgrade\":\"Version %s from %s\"}"), Version, sysCfg.otaUrl);
} else {
@ -1266,7 +1275,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
snprintf_P(svalue, sizeof(svalue), PSTR("{\"OtaUrl\":\"%s\"}"), sysCfg.otaUrl);
}
else if (!strcmp_P(type,PSTR("SERIALLOG"))) {
if ((data_len > 0) && (payload >= LOG_LEVEL_NONE) && (payload <= LOG_LEVEL_ALL)) {
if ((payload >= LOG_LEVEL_NONE) && (payload <= LOG_LEVEL_ALL)) {
sysCfg.seriallog_level = payload;
seriallog_level = payload;
seriallog_timer = 0;
@ -1274,7 +1283,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
snprintf_P(svalue, sizeof(svalue), PSTR("{\"SerialLog\":\"%d (Active %d)\"}"), sysCfg.seriallog_level, seriallog_level);
}
else if (!strcmp_P(type,PSTR("SYSLOG"))) {
if ((data_len > 0) && (payload >= LOG_LEVEL_NONE) && (payload <= LOG_LEVEL_ALL)) {
if ((payload >= LOG_LEVEL_NONE) && (payload <= LOG_LEVEL_ALL)) {
sysCfg.syslog_level = payload;
syslog_level = (sysCfg.flag.emulation) ? 0 : payload;
syslog_timer = 0;
@ -1288,7 +1297,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
snprintf_P(svalue, sizeof(svalue), PSTR("{\"LogHost\":\"%s\"}"), sysCfg.syslog_host);
}
else if (!strcmp_P(type,PSTR("LOGPORT"))) {
if ((data_len > 0) && (payload > 0) && (payload < 32766)) {
if ((payload > 0) && (payload < 32766)) {
sysCfg.syslog_port = (1 == payload) ? SYS_LOG_PORT : payload;
}
snprintf_P(svalue, sizeof(svalue), PSTR("{\"LogPort\":%d}"), sysCfg.syslog_port);
@ -1314,7 +1323,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
snprintf_P(svalue, sizeof(svalue), PSTR("{\"NtpServer%d\":\"%s\"}"), index, sysCfg.ntp_server[index -1]);
}
else if (!strcmp_P(type,PSTR("AP"))) {
if ((data_len > 0) && (payload >= 0) && (payload <= 2)) {
if ((payload >= 0) && (payload <= 2)) {
switch (payload) {
case 0: // Toggle
sysCfg.sta_active ^= 1;
@ -1354,7 +1363,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Hostname\":\"%s\"}"), sysCfg.hostname);
}
else if (!strcmp_P(type,PSTR("WIFICONFIG"))) {
if ((data_len > 0) && (payload >= WIFI_RESTART) && (payload < MAX_WIFI_OPTION)) {
if ((payload >= WIFI_RESTART) && (payload < MAX_WIFI_OPTION)) {
sysCfg.sta_config = payload;
wificheckflag = sysCfg.sta_config;
snprintf_P(stemp1, sizeof(stemp1), wificfg[sysCfg.sta_config]);
@ -1380,14 +1389,14 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
snprintf_P(svalue, sizeof(svalue), PSTR("{\"FriendlyName%d\":\"%s\"}"), index, sysCfg.friendlyname[index -1]);
}
else if (swt_flg && !strcmp_P(type,PSTR("SWITCHMODE")) && (index > 0) && (index <= 4)) {
if ((data_len > 0) && (payload >= 0) && (payload < MAX_SWITCH_OPTION)) {
if ((payload >= 0) && (payload < MAX_SWITCH_OPTION)) {
sysCfg.switchmode[index -1] = payload;
}
snprintf_P(svalue, sizeof(svalue), PSTR("{\"SwitchMode%d\":%d}"), index, sysCfg.switchmode[index-1]);
}
#ifdef USE_WEBSERVER
else if (!strcmp_P(type,PSTR("WEBSERVER"))) {
if ((data_len > 0) && (payload >= 0) && (payload <= 2)) {
if ((payload >= 0) && (payload <= 2)) {
sysCfg.webserver = payload;
}
if (sysCfg.webserver) {
@ -1404,14 +1413,14 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
snprintf_P(svalue, sizeof(svalue), PSTR("{\"WebPassword\":\"%s\"}"), sysCfg.web_password);
}
else if (!strcmp_P(type,PSTR("WEBLOG"))) {
if ((data_len > 0) && (payload >= LOG_LEVEL_NONE) && (payload <= LOG_LEVEL_ALL)) {
if ((payload >= LOG_LEVEL_NONE) && (payload <= LOG_LEVEL_ALL)) {
sysCfg.weblog_level = payload;
}
snprintf_P(svalue, sizeof(svalue), PSTR("{\"WebLog\":%d}"), sysCfg.weblog_level);
}
#ifdef USE_EMULATION
else if (!strcmp_P(type,PSTR("EMULATION"))) {
if ((data_len > 0) && (payload >= 0) && (payload <= 2)) {
if ((payload >= 0) && (payload <= 2)) {
sysCfg.flag.emulation = payload;
restartflag = 2;
}
@ -1420,7 +1429,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
#endif // USE_EMULATION
#endif // USE_WEBSERVER
else if (!strcmp_P(type,PSTR("TELEPERIOD"))) {
if ((data_len > 0) && (payload >= 0) && (payload < 3601)) {
if ((payload >= 0) && (payload < 3601)) {
sysCfg.tele_period = (1 == payload) ? TELE_PERIOD : payload;
if ((sysCfg.tele_period > 0) && (sysCfg.tele_period < 10)) {
sysCfg.tele_period = 10; // Do not allow periods < 10 seconds
@ -1464,7 +1473,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Timezone\":%d}"), sysCfg.timezone);
}
else if (!strcmp_P(type,PSTR("LEDPOWER"))) {
if ((data_len > 0) && (payload >= 0) && (payload <= 2)) {
if ((payload >= 0) && (payload <= 2)) {
sysCfg.ledstate &= 8;
switch (payload) {
case 0: // Off
@ -1481,7 +1490,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
snprintf_P(svalue, sizeof(svalue), PSTR("{\"LedPower\":\"%s\"}"), getStateText(bitRead(sysCfg.ledstate, 3)));
}
else if (!strcmp_P(type,PSTR("LEDSTATE"))) {
if ((data_len > 0) && (payload >= 0) && (payload < MAX_LED_OPTION)) {
if ((payload >= 0) && (payload < MAX_LED_OPTION)) {
sysCfg.ledstate = payload;
if (!sysCfg.ledstate) {
setLed(0);
@ -1555,38 +1564,49 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
/********************************************************************************************/
void send_button_power(byte key, byte device, byte state)
boolean send_button_power(byte key, byte device, byte state)
{
// key 0 = button_topic
// key 1 = switch_topic
// state 0 = off
// state 1 = on
// state 2 = toggle
// state 3 = hold
// state 9 = clear retain flag
char stopic[TOPSZ];
char scommand[CMDSZ];
char svalue[TOPSZ];
char stemp1[10];
boolean result = false;
if (!key && (device > Maxdevice)) {
device = 1;
}
snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), device);
snprintf_P(scommand, sizeof(scommand), PSTR("POWER%s"), (key || (Maxdevice > 1)) ? stemp1 : "");
getTopic_P(stopic, 0, (key) ? sysCfg.switch_topic : sysCfg.button_topic, scommand);
if (3 == state) {
svalue[0] = '\0';
} else {
if (!strcmp(sysCfg.mqtt_topic,(key) ? sysCfg.switch_topic : sysCfg.button_topic) && (2 == state)) {
state = ~(power >> (device -1)) & 0x01;
char *key_topic = (key) ? sysCfg.switch_topic : sysCfg.button_topic;
if (sysCfg.flag.mqtt_enabled && mqttClient.connected() && (strlen(key_topic) != 0) && strcmp(key_topic, "0")) {
if (!key && (device > Maxdevice)) {
device = 1;
}
snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), device);
snprintf_P(scommand, sizeof(scommand), PSTR("POWER%s"), (key || (Maxdevice > 1)) ? stemp1 : "");
getTopic_P(stopic, 0, key_topic, scommand);
if (9 == state) {
svalue[0] = '\0';
} else {
if (!strcmp(sysCfg.mqtt_topic, key_topic) && (2 == state)) {
state = ~(power >> (device -1)) & 0x01;
}
snprintf_P(svalue, sizeof(svalue), PSTR("%s"), getStateText(state));
}
snprintf_P(svalue, sizeof(svalue), PSTR("%s"), getStateText(state));
}
#ifdef USE_DOMOTICZ
if (!(domoticz_button(key, device, state, strlen(svalue)))) {
mqtt_publish_sec(stopic, svalue, (key) ? sysCfg.flag.mqtt_switch_retain : sysCfg.flag.mqtt_button_retain);
}
if (!(domoticz_button(key, device, state, strlen(svalue)))) {
mqtt_publish_sec(stopic, svalue, (key) ? sysCfg.flag.mqtt_switch_retain : sysCfg.flag.mqtt_button_retain);
}
#else
mqtt_publish_sec(stopic, svalue, (key) ? sysCfg.flag.mqtt_switch_retain : sysCfg.flag.mqtt_button_retain);
mqtt_publish_sec(stopic, svalue, (key) ? sysCfg.flag.mqtt_switch_retain : sysCfg.flag.mqtt_button_retain);
#endif // USE_DOMOTICZ
result = true;
}
return result;
}
void do_cmnd_power(byte device, byte state)
@ -1804,7 +1824,7 @@ void sensors_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson)
snprintf_P(svalue, ssvalue, PSTR("%s{\"Time\":\"%s\""), svalue, getDateTime().c_str());
for (byte i = 0; i < 4; i++) {
if (pin[GPIO_SWT1 +i] < 99) {
boolean swm = ((FOLLOW_INV == sysCfg.switchmode[i]) || (PUSHBUTTON_INV == sysCfg.switchmode[i]));
boolean swm = ((FOLLOW_INV == sysCfg.switchmode[i]) || (PUSHBUTTON_INV == sysCfg.switchmode[i]) || (PUSHBUTTONHOLD_INV == sysCfg.switchmode[i]));
snprintf_P(svalue, ssvalue, PSTR("%s, \"Switch%d\":\"%s\""), svalue, i +1, getStateText(swm ^ lastwallswitch[i]));
*djson = 1;
}
@ -2062,10 +2082,14 @@ void stateloop()
holdcount = 0;
} else {
holdcount++;
if (!sysCfg.flag.button_restrict && ((STATES *4) == holdcount)) { // 4 seconds button hold
snprintf_P(scmnd, sizeof(scmnd), PSTR("reset 1"));
if (KEY_HOLD_TIME == holdcount) { // 4 seconds button hold
multipress = 0;
do_cmnd(scmnd);
if (!sysCfg.flag.button_restrict) { // no restriction (OPTION
snprintf_P(scmnd, sizeof(scmnd), PSTR("reset 1"));
do_cmnd(scmnd);
} else {
send_button_power(0, 1, 3); // Execute command via MQTT
}
}
}
if (multiwindow) {
@ -2075,10 +2099,11 @@ void stateloop()
if ((SONOFF_DUAL == sysCfg.module) || (CH4 == sysCfg.module)) {
flag = ((1 == multipress) || (2 == multipress));
} else {
flag = (1 == multipress);
// flag = (1 == multipress);
flag = (sysCfg.flag.button_swap +1 == multipress);
}
if (flag && sysCfg.flag.mqtt_enabled && mqttClient.connected() && (strlen(sysCfg.button_topic) != 0) && strcmp(sysCfg.button_topic, "0")) {
send_button_power(0, multipress, 2); // Execute command via MQTT using ButtonTopic to sync external clients
if (flag && send_button_power(0, multipress, 2)) { // Execute command via MQTT using ButtonTopic to sync external clients
// Success
} else {
if ((1 == multipress) || (2 == multipress)) {
if (WIFI_State()) { // WPSconfig, Smartconfig or Wifimanager active
@ -2101,10 +2126,8 @@ void stateloop()
if (pin[GPIO_KEY1 +i] < 99) {
button = digitalRead(pin[GPIO_KEY1 +i]);
if ((PRESSED == button) && (NOT_PRESSED == lastbutton[i])) {
if (sysCfg.flag.mqtt_enabled && mqttClient.connected() && (strlen(sysCfg.button_topic) != 0) && strcmp(sysCfg.button_topic, "0")) {
send_button_power(0, i +1, 2); // Execute commend via MQTT
} else {
do_cmnd_power(i +1, 2); // Execute command internally
if (!send_button_power(0, i +1, 2)) { // Execute command via MQTT
do_cmnd_power(i +1, 2); // Execute command internally
}
}
lastbutton[i] = button;
@ -2113,6 +2136,14 @@ void stateloop()
for (byte i = 0; i < 4; i++) {
if (pin[GPIO_SWT1 +i] < 99) {
if (wallswitchtimer[i]) {
wallswitchtimer[i]--;
if (0 == wallswitchtimer[i]) {
send_button_power(1, i +1, 3); // Execute command via MQTT
}
}
button = digitalRead(pin[GPIO_SWT1 +i]);
if (button != lastwallswitch[i]) {
switchflag = 3;
@ -2135,14 +2166,33 @@ void stateloop()
if ((NOT_PRESSED == button) && (PRESSED == lastwallswitch[i])) {
switchflag = 2; // Toggle with releasing pushbutton from Gnd
}
break;
case PUSHBUTTONHOLD:
if ((PRESSED == button) && (NOT_PRESSED == lastwallswitch[i])) {
wallswitchtimer[i] = KEY_HOLD_TIME;
}
if ((NOT_PRESSED == button) && (PRESSED == lastwallswitch[i]) && (wallswitchtimer[i])) {
wallswitchtimer[i] = 0;
switchflag = 2; // Toggle with pushbutton to Gnd
}
break;
case PUSHBUTTONHOLD_INV:
if ((NOT_PRESSED == button) && (PRESSED == lastwallswitch[i])) {
wallswitchtimer[i] = KEY_HOLD_TIME;
}
if ((PRESSED == button) && (NOT_PRESSED == lastwallswitch[i]) && (wallswitchtimer[i])) {
wallswitchtimer[i] = 0;
switchflag = 2; // Toggle with pushbutton to Gnd
}
break;
}
if (switchflag < 3) {
if (sysCfg.flag.mqtt_enabled && mqttClient.connected() && (strlen(sysCfg.switch_topic) != 0) && strcmp(sysCfg.switch_topic, "0")) {
send_button_power(1, i +1, switchflag); // Execute commend via MQTT
} else {
do_cmnd_power(i +1, switchflag); // Execute command internally (if i < Maxdevice)
if (!send_button_power(1, i +1, switchflag)) { // Execute command via MQTT
do_cmnd_power(i +1, switchflag); // Execute command internally (if i < Maxdevice)
}
}
lastwallswitch[i] = button;
}
}

View File

@ -81,6 +81,7 @@
#define MQTT_STATUS_OFF "OFF" // [StateText1] Command or Status result when turned off (needs to be a string like "0" or "Off")
#define MQTT_STATUS_ON "ON" // [StateText2] Command or Status result when turned on (needs to be a string like "1" or "On")
#define MQTT_CMND_TOGGLE "TOGGLE" // [StateText3] Command to send when toggling (needs to be a string like "2" or "Toggle")
#define MQTT_CMND_HOLD "HOLD" // [StateText4] Command to send when button is kept down for over KEY_HOLD_TIME * 0.1 seconds (needs to be a string like "HOLD")
// -- MQTT topics ---------------------------------
//#define MQTT_FULLTOPIC "tasmota/bedroom/%topic%/%prefix%/" // Up to max 80 characers
@ -101,8 +102,8 @@
// -- MQTT - Domoticz -----------------------------
#define USE_DOMOTICZ // Enable Domoticz (+7k code, +0.3k mem) - Disable by //
#define DOMOTICZ_IN_TOPIC "domoticz/in" // [DomoticzInTopic]
#define DOMOTICZ_OUT_TOPIC "domoticz/out" // [DomoticzOutTopic]
#define DOMOTICZ_IN_TOPIC "domoticz/in" // Domoticz Input Topic
#define DOMOTICZ_OUT_TOPIC "domoticz/out" // Domoticz Output Topic
#define DOMOTICZ_UPDATE_TIMER 0 // [DomoticzUpdateTimer] Send relay status (0 = disable, 1 - 3600 seconds) (Optional)
// -- HTTP ----------------------------------------
@ -140,7 +141,8 @@
#define APP_BLINKCOUNT 10 // [BlinkCount] Number of blinks (0 = 32000)
#define APP_SLEEP 0 // [Sleep] Sleep time to lower energy consumption (0 = Off, 1 - 250 mSec)
#define SWITCH_MODE TOGGLE // [SwitchMode] TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON or PUSHBUTTON_INV (the wall switch state)
#define KEY_HOLD_TIME 40 // Number of 0.1 seconds to hold Button or external Pushbutton before sending HOLD message
#define SWITCH_MODE TOGGLE // [SwitchMode] TOGGLE, FOLLOW, FOLLOW_INV, PUSHBUTTON, PUSHBUTTON_INV, PUSHBUTTONHOLD or PUSHBUTTONHOLD_INV (the wall switch state)
#define WS2812_LEDS 30 // [Pixels] Number of WS2812 LEDs to start with
#define TEMP_CONVERSION 0 // [TempUnit] Return temperature in (0 = Celsius or 1 = Fahrenheit)

View File

@ -25,16 +25,14 @@
const char HTTP_FORM_DOMOTICZ[] PROGMEM =
"<fieldset><legend><b>&nbsp;Domoticz parameters&nbsp;</b></legend><form method='post' action='sv'>"
"<input id='w' name='w' value='4' hidden><input id='r' name='r' value='1' hidden>"
"<br/><table style='width:97%'>"
"<tr><td><b>In topic</b> (" DOMOTICZ_IN_TOPIC ")</td><td style='width:30%'><input id='it' name='it' length=32 placeholder='" DOMOTICZ_IN_TOPIC "' value='{d1}'></td></tr>"
"<tr><td><b>Out topic</b> (" DOMOTICZ_OUT_TOPIC ")</td><td><input id='ot' name='ot' length=32 placeholder='" DOMOTICZ_OUT_TOPIC "' value='{d2}'></td></tr>";
"<br/><table style='width:97%'>";
const char HTTP_FORM_DOMOTICZ_RELAY[] PROGMEM =
"<tr><td><b>Idx {1</b></td></td><td><input id='r{1' name='r{1' length=8 placeholder='0' value='{2'></td></tr>"
"<tr><td><b>Idx {1</b></td></td><td width='20%'><input id='r{1' name='r{1' length=8 placeholder='0' value='{2'></td></tr>"
"<tr><td><b>Key idx {1</b></td><td><input id='k{1' name='k{1' length=8 placeholder='0' value='{3'></td></tr>";
const char HTTP_FORM_DOMOTICZ_SWITCH[] PROGMEM =
"<tr><td><b>Switch idx {1</b></td><td><input id='s{1' name='s{1' length=8 placeholder='0' value='{4'></td></tr>";
"<tr><td><b>Switch idx {1</b></td><td width='20%'><input id='s{1' name='s{1' length=8 placeholder='0' value='{4'></td></tr>";
const char HTTP_FORM_DOMOTICZ_SENSOR[] PROGMEM =
"<tr><td><b>Sensor idx {1</b> - {2</td><td><input id='l{1' name='l{1' length=8 placeholder='0' value='{5'></td></tr>";
"<tr><td><b>Sensor idx {1</b> - {2</td><td width='20%'><input id='l{1' name='l{1' length=8 placeholder='0' value='{5'></td></tr>";
const char HTTP_FORM_DOMOTICZ_TIMER[] PROGMEM =
"<tr><td><b>Update timer</b> (" STR(DOMOTICZ_UPDATE_TIMER) ")</td><td><input id='ut' name='ut' length=32 placeholder='" STR(DOMOTICZ_UPDATE_TIMER) "' value='{6'</td></tr>";
#endif // USE_WEBSERVER
@ -42,6 +40,9 @@ const char HTTP_FORM_DOMOTICZ_TIMER[] PROGMEM =
const char domoticz_sensors[DOMOTICZ_MAX_SENSORS][14] PROGMEM =
{ "Temp", "Temp,Hum", "Temp,Hum,Baro", "Power,Energy", "Illuminance", "Count" };
char domoticz_in_topic[] = DOMOTICZ_IN_TOPIC;
char domoticz_out_topic[] = DOMOTICZ_OUT_TOPIC;
boolean domoticz_subscribe = false;
int domoticz_update_timer = 0;
byte domoticz_update_flag = 1;
@ -50,7 +51,7 @@ void mqtt_publishDomoticzPowerState(byte device)
{
char svalue[64]; // was MESSZ
if (sysCfg.domoticz_relay_idx[device -1] && (strlen(sysCfg.domoticz_in_topic) != 0)) {
if (sysCfg.domoticz_relay_idx[device -1]) {
if ((device < 1) || (device > Maxdevice)) {
device = 1;
}
@ -58,16 +59,16 @@ void mqtt_publishDomoticzPowerState(byte device)
if (SONOFF_LED == sysCfg.module) {
snprintf_P(svalue, sizeof(svalue), PSTR("{\"idx\":%d,\"nvalue\":2,\"svalue\":\"%d\"}"),
sysCfg.domoticz_relay_idx[device -1], sysCfg.led_dimmer[device -1]);
mqtt_publish(sysCfg.domoticz_in_topic, svalue);
mqtt_publish(domoticz_in_topic, svalue);
}
else if ((Maxdevice == device) && (pin[GPIO_WS2812] < 99)) {
snprintf_P(svalue, sizeof(svalue), PSTR("{\"idx\":%d,\"nvalue\":2,\"svalue\":\"%d\"}"),
sysCfg.domoticz_relay_idx[device -1], sysCfg.ws_dimmer);
mqtt_publish(sysCfg.domoticz_in_topic, svalue);
mqtt_publish(domoticz_in_topic, svalue);
}
snprintf_P(svalue, sizeof(svalue), PSTR("{\"idx\":%d,\"nvalue\":%d,\"svalue\":\"\"}"),
sysCfg.domoticz_relay_idx[device -1], (power & (0x01 << (device -1))) ? 1 : 0);
mqtt_publish(sysCfg.domoticz_in_topic, svalue);
mqtt_publish(domoticz_in_topic, svalue);
}
}
@ -104,9 +105,9 @@ void domoticz_mqttSubscribe()
domoticz_subscribe = true;
}
}
if (domoticz_subscribe && (strlen(sysCfg.domoticz_out_topic) != 0)) {
if (domoticz_subscribe) {
char stopic[TOPSZ];
snprintf_P(stopic, sizeof(stopic), PSTR("%s/#"), sysCfg.domoticz_out_topic); // domoticz topic
snprintf_P(stopic, sizeof(stopic), PSTR("%s/#"), domoticz_out_topic); // domoticz topic
mqttClient.subscribe(stopic);
mqttClient.loop(); // Solve LmacRxBlk:1 messages
}
@ -144,7 +145,7 @@ boolean domoticz_mqttData(char *topicBuf, uint16_t stopicBuf, char *dataBuf, uin
int16_t found = 0;
domoticz_update_flag = 1;
if (!strncmp(topicBuf, sysCfg.domoticz_out_topic, strlen(sysCfg.domoticz_out_topic)) != 0) {
if (!strncmp(topicBuf, domoticz_out_topic, strlen(domoticz_out_topic)) != 0) {
if (sdataBuf < 20) {
return 1;
}
@ -210,47 +211,33 @@ boolean domoticz_command(const char *type, uint16_t index, char *dataBuf, uint16
boolean serviced = true;
if (!strncmp_P(type,PSTR("DOMOTICZ"),8)) {
if (!strcmp_P(type +8,PSTR("INTOPIC"))) {
if ((data_len > 0) && (data_len < sizeof(sysCfg.domoticz_in_topic))) {
strlcpy(sysCfg.domoticz_in_topic, (1 == payload) ? DOMOTICZ_IN_TOPIC : dataBuf, sizeof(sysCfg.domoticz_in_topic));
restartflag = 2;
}
snprintf_P(svalue, ssvalue, PSTR("{\"DomoticzInTopic\":\"%s\"}"), sysCfg.domoticz_in_topic);
}
else if (!strcmp_P(type +8,PSTR("OUTTOPIC"))) {
if ((data_len > 0) && (data_len < sizeof(sysCfg.domoticz_out_topic))) {
strlcpy(sysCfg.domoticz_out_topic, (1 == payload) ? DOMOTICZ_OUT_TOPIC : dataBuf, sizeof(sysCfg.domoticz_out_topic));
restartflag = 2;
}
snprintf_P(svalue, ssvalue, PSTR("{\"DomoticzOutTopic\":\"%s\"}"), sysCfg.domoticz_out_topic);
}
else if (!strcmp_P(type +8,PSTR("IDX")) && (index > 0) && (index <= Maxdevice)) {
if ((data_len > 0) && (payload >= 0)) {
if (!strcmp_P(type +8,PSTR("IDX")) && (index > 0) && (index <= Maxdevice)) {
if (payload >= 0) {
sysCfg.domoticz_relay_idx[index -1] = payload;
restartflag = 2;
}
snprintf_P(svalue, ssvalue, PSTR("{\"DomoticzIdx%d\":%d}"), index, sysCfg.domoticz_relay_idx[index -1]);
}
else if (!strcmp_P(type +8,PSTR("KEYIDX")) && (index > 0) && (index <= Maxdevice)) {
if ((data_len > 0) && (payload >= 0)) {
if (payload >= 0) {
sysCfg.domoticz_key_idx[index -1] = payload;
}
snprintf_P(svalue, ssvalue, PSTR("{\"DomoticzKeyIdx%d\":%d}"), index, sysCfg.domoticz_key_idx[index -1]);
}
else if (!strcmp_P(type +8,PSTR("SWITCHIDX")) && (index > 0) && (index <= Maxdevice)) {
if ((data_len > 0) && (payload >= 0)) {
if (payload >= 0) {
sysCfg.domoticz_switch_idx[index -1] = payload;
}
snprintf_P(svalue, ssvalue, PSTR("{\"DomoticzSwitchIdx%d\":%d}"), index, sysCfg.domoticz_key_idx[index -1]);
}
else if (!strcmp_P(type +8,PSTR("SENSORIDX")) && (index > 0) && (index <= DOMOTICZ_MAX_SENSORS)) {
if ((data_len > 0) && (payload >= 0)) {
if (payload >= 0) {
sysCfg.domoticz_sensor_idx[index -1] = payload;
}
snprintf_P(svalue, ssvalue, PSTR("{\"DomoticzSensorIdx%d\":%d}"), index, sysCfg.domoticz_sensor_idx[index -1]);
}
else if (!strcmp_P(type +8,PSTR("UPDATETIMER"))) {
if ((data_len > 0) && (payload >= 0) && (payload < 3601)) {
if ((payload >= 0) && (payload < 3601)) {
sysCfg.domoticz_update_timer = payload;
}
snprintf_P(svalue, ssvalue, PSTR("{\"DomoticzUpdateTimer\":%d}"), sysCfg.domoticz_update_timer);
@ -268,7 +255,7 @@ boolean domoticz_button(byte key, byte device, byte state, byte svalflg)
snprintf_P(svalue, sizeof(svalue), PSTR("{\"command\":\"switchlight\",\"idx\":%d,\"switchcmd\":\"%s\"}"),
(key) ? sysCfg.domoticz_switch_idx[device -1] : sysCfg.domoticz_key_idx[device -1], (state) ? (2 == state) ? "Toggle" : "On" : "Off");
mqtt_publish(sysCfg.domoticz_in_topic, svalue);
mqtt_publish(domoticz_in_topic, svalue);
return 1;
} else {
return 0;
@ -289,10 +276,10 @@ void dom_sensor(byte idx, char *data)
{
char dmess[64];
if (sysCfg.domoticz_sensor_idx[idx] && (strlen(sysCfg.domoticz_in_topic) != 0)) {
if (sysCfg.domoticz_sensor_idx[idx]) {
snprintf_P(dmess, sizeof(dmess), PSTR("{\"idx\":%d,\"nvalue\":0,\"svalue\":\"%s\"}"),
sysCfg.domoticz_sensor_idx[idx], data);
mqtt_publish(sysCfg.domoticz_in_topic, dmess);
mqtt_publish(domoticz_in_topic, dmess);
}
}
@ -354,8 +341,6 @@ void handleDomoticz()
String page = FPSTR(HTTP_HEAD);
page.replace("{v}", "Configure Domoticz");
page += FPSTR(HTTP_FORM_DOMOTICZ);
page.replace("{d1}", String(sysCfg.domoticz_in_topic));
page.replace("{d2}", String(sysCfg.domoticz_out_topic));
for (int i = 0; i < 4; i++) {
if (i < Maxdevice) {
page += FPSTR(HTTP_FORM_DOMOTICZ_RELAY);
@ -387,8 +372,6 @@ void domoticz_saveSettings()
{
char log[LOGSZ], stemp[20];
strlcpy(sysCfg.domoticz_in_topic, (!strlen(webServer->arg("it").c_str())) ? DOMOTICZ_IN_TOPIC : webServer->arg("it").c_str(), sizeof(sysCfg.domoticz_in_topic));
strlcpy(sysCfg.domoticz_out_topic, (!strlen(webServer->arg("ot").c_str())) ? DOMOTICZ_OUT_TOPIC : webServer->arg("ot").c_str(), sizeof(sysCfg.domoticz_out_topic));
for (byte i = 0; i < 4; i++) {
snprintf_P(stemp, sizeof(stemp), PSTR("r%d"), i +1);
sysCfg.domoticz_relay_idx[i] = (!strlen(webServer->arg(stemp).c_str())) ? 0 : atoi(webServer->arg(stemp).c_str());
@ -402,8 +385,7 @@ void domoticz_saveSettings()
sysCfg.domoticz_sensor_idx[i] = (!strlen(webServer->arg(stemp).c_str())) ? 0 : atoi(webServer->arg(stemp).c_str());
}
sysCfg.domoticz_update_timer = (!strlen(webServer->arg("ut").c_str())) ? DOMOTICZ_UPDATE_TIMER : atoi(webServer->arg("ut").c_str());
snprintf_P(log, sizeof(log), PSTR("HTTP: Domoticz in %s, out %s, idx %d, %d, %d, %d, update timer %d"),
sysCfg.domoticz_in_topic, sysCfg.domoticz_out_topic,
snprintf_P(log, sizeof(log), PSTR("HTTP: Domoticz idx %d, %d, %d, %d, update timer %d"),
sysCfg.domoticz_relay_idx[0], sysCfg.domoticz_relay_idx[1], sysCfg.domoticz_relay_idx[2], sysCfg.domoticz_relay_idx[3],
sysCfg.domoticz_update_timer);
addLog(LOG_LEVEL_INFO, log);

View File

@ -207,7 +207,7 @@ boolean sl_command(char *type, uint16_t index, char *dataBufUc, uint16_t data_le
}
}
else if (!strcmp_P(type,PSTR("DIMMER"))) {
if ((data_len > 0) && (payload >= 0) && (payload <= 100)) {
if ((payload >= 0) && (payload <= 100)) {
sysCfg.led_dimmer[0] = payload;
coldim = true;
} else {
@ -215,7 +215,7 @@ boolean sl_command(char *type, uint16_t index, char *dataBufUc, uint16_t data_le
}
}
else if (!strcmp_P(type,PSTR("LEDTABLE"))) {
if ((data_len > 0) && (payload >= 0) && (payload <= 2)) {
if ((payload >= 0) && (payload <= 2)) {
switch (payload) {
case 0: // Off
case 1: // On
@ -230,27 +230,25 @@ boolean sl_command(char *type, uint16_t index, char *dataBufUc, uint16_t data_le
snprintf_P(svalue, ssvalue, PSTR("{\"LedTable\":\"%s\"}"), getStateText(sysCfg.led_table));
}
else if (!strcmp_P(type,PSTR("FADE"))) {
if ((data_len > 0) && (payload >= 0) && (payload <= 2)) {
switch (payload) {
case 0: // Off
case 1: // On
sysCfg.led_fade = payload;
break;
case 2: // Toggle
sysCfg.led_fade ^= 1;
break;
}
switch (payload) {
case 0: // Off
case 1: // On
sysCfg.led_fade = payload;
break;
case 2: // Toggle
sysCfg.led_fade ^= 1;
break;
}
snprintf_P(svalue, ssvalue, PSTR("{\"Fade\":\"%s\"}"), getStateText(sysCfg.led_fade));
}
else if (!strcmp_P(type,PSTR("SPEED"))) { // 1 - fast, 8 - slow
if ((data_len > 0) && (payload > 0) && (payload <= 8)) {
if ((payload > 0) && (payload <= 8)) {
sysCfg.led_speed = payload;
}
snprintf_P(svalue, ssvalue, PSTR("{\"Speed\":%d}"), sysCfg.led_speed);
}
else if (!strcmp_P(type,PSTR("WAKEUPDURATION"))) {
if ((data_len > 0) && (payload > 0) && (payload < 3601)) {
if ((payload > 0) && (payload < 3601)) {
sysCfg.led_wakeup = payload;
sl_wakeupActive = 0;
}

View File

@ -529,7 +529,7 @@ boolean ws2812_command(char *type, uint16_t index, char *dataBuf, uint16_t data_
boolean serviced = true;
if (!strcmp_P(type,PSTR("PIXELS"))) {
if ((data_len > 0) && (payload > 0) && (payload <= WS2812_MAX_LEDS)) {
if ((payload > 0) && (payload <= WS2812_MAX_LEDS)) {
sysCfg.ws_pixels = payload;
ws2812_pixels();
}
@ -549,7 +549,7 @@ boolean ws2812_command(char *type, uint16_t index, char *dataBuf, uint16_t data_
ws2812_getColor(0, svalue, ssvalue);
}
else if (!strcmp_P(type,PSTR("DIMMER"))) {
if ((data_len > 0) && (payload >= 0) && (payload <= 100)) {
if ((payload >= 0) && (payload <= 100)) {
sysCfg.ws_dimmer = payload;
bitSet(power, ws_bit);
#ifdef USE_DOMOTICZ
@ -560,7 +560,7 @@ boolean ws2812_command(char *type, uint16_t index, char *dataBuf, uint16_t data_
snprintf_P(svalue, ssvalue, PSTR("{\"Dimmer\":%d}"), sysCfg.ws_dimmer);
}
else if (!strcmp_P(type,PSTR("LEDTABLE"))) {
if ((data_len > 0) && (payload >= 0) && (payload <= 2)) {
if ((payload >= 0) && (payload <= 2)) {
switch (payload) {
case 0: // Off
case 1: // On
@ -575,33 +575,31 @@ boolean ws2812_command(char *type, uint16_t index, char *dataBuf, uint16_t data_
snprintf_P(svalue, ssvalue, PSTR("{\"LedTable\":\"%s\"}"), getStateText(sysCfg.ws_ledtable));
}
else if (!strcmp_P(type,PSTR("FADE"))) {
if ((data_len > 0) && (payload >= 0) && (payload <= 2)) {
switch (payload) {
case 0: // Off
case 1: // On
sysCfg.ws_fade = payload;
break;
case 2: // Toggle
sysCfg.ws_fade ^= 1;
break;
}
switch (payload) {
case 0: // Off
case 1: // On
sysCfg.ws_fade = payload;
break;
case 2: // Toggle
sysCfg.ws_fade ^= 1;
break;
}
snprintf_P(svalue, ssvalue, PSTR("{\"Fade\":\"%s\"}"), getStateText(sysCfg.ws_fade));
}
else if (!strcmp_P(type,PSTR("SPEED"))) { // 1 - fast, 5 - slow
if ((data_len > 0) && (payload > 0) && (payload <= 5)) {
if ((payload > 0) && (payload <= 5)) {
sysCfg.ws_speed = payload;
}
snprintf_P(svalue, ssvalue, PSTR("{\"Speed\":%d}"), sysCfg.ws_speed);
}
else if (!strcmp_P(type,PSTR("WIDTH"))) {
if ((data_len > 0) && (payload >= 0) && (payload <= 4)) {
if ((payload >= 0) && (payload <= 4)) {
sysCfg.ws_width = payload;
}
snprintf_P(svalue, ssvalue, PSTR("{\"Width\":%d}"), sysCfg.ws_width);
}
else if (!strcmp_P(type,PSTR("WAKEUP"))) {
if ((data_len > 0) && (payload > 0) && (payload < 3601)) {
if ((payload > 0) && (payload < 3601)) {
sysCfg.ws_wakeup = payload;
if (1 == sysCfg.ws_scheme) {
sysCfg.ws_scheme = 0;
@ -610,7 +608,7 @@ boolean ws2812_command(char *type, uint16_t index, char *dataBuf, uint16_t data_
snprintf_P(svalue, ssvalue, PSTR("{\"WakeUp\":%d}"), sysCfg.ws_wakeup);
}
else if (!strcmp_P(type,PSTR("SCHEME"))) {
if ((data_len > 0) && (payload >= 0) && (payload <= 9)) {
if ((payload >= 0) && (payload <= 9)) {
sysCfg.ws_scheme = payload;
if (1 == sysCfg.ws_scheme) {
ws2812_resetWakupState();

View File

@ -439,43 +439,43 @@ boolean hlw_command(char *type, uint16_t index, char *dataBuf, uint16_t data_len
boolean serviced = true;
if (!strcmp_P(type,PSTR("POWERLOW"))) {
if ((data_len > 0) && (payload >= 0) && (payload < 3601)) {
if ((payload >= 0) && (payload < 3601)) {
sysCfg.hlw_pmin = payload;
}
snprintf_P(svalue, ssvalue, PSTR("{\"PowerLow\":\"%d%s\"}"), sysCfg.hlw_pmin, (sysCfg.flag.value_units) ? " W" : "");
}
else if (!strcmp_P(type,PSTR("POWERHIGH"))) {
if ((data_len > 0) && (payload >= 0) && (payload < 3601)) {
if ((payload >= 0) && (payload < 3601)) {
sysCfg.hlw_pmax = payload;
}
snprintf_P(svalue, ssvalue, PSTR("{\"PowerHigh\":\"%d%s\"}"), sysCfg.hlw_pmax, (sysCfg.flag.value_units) ? " W" : "");
}
else if (!strcmp_P(type,PSTR("VOLTAGELOW"))) {
if ((data_len > 0) && (payload >= 0) && (payload < 501)) {
if ((payload >= 0) && (payload < 501)) {
sysCfg.hlw_umin = payload;
}
snprintf_P(svalue, ssvalue, PSTR("{\"VoltageLow\":\"%d%s\"}"), sysCfg.hlw_umin, (sysCfg.flag.value_units) ? " V" : "");
}
else if (!strcmp_P(type,PSTR("VOLTAGEHIGH"))) {
if ((data_len > 0) && (payload >= 0) && (payload < 501)) {
if ((payload >= 0) && (payload < 501)) {
sysCfg.hlw_umax = payload;
}
snprintf_P(svalue, ssvalue, PSTR("[\"VoltageHigh\":\"%d%s\"}"), sysCfg.hlw_umax, (sysCfg.flag.value_units) ? " V" : "");
}
else if (!strcmp_P(type,PSTR("CURRENTLOW"))) {
if ((data_len > 0) && (payload >= 0) && (payload < 16001)) {
if ((payload >= 0) && (payload < 16001)) {
sysCfg.hlw_imin = payload;
}
snprintf_P(svalue, ssvalue, PSTR("{\"CurrentLow\":\"%d%s\"}"), sysCfg.hlw_imin, (sysCfg.flag.value_units) ? " mA" : "");
}
else if (!strcmp_P(type,PSTR("CURRENTHIGH"))) {
if ((data_len > 0) && (payload >= 0) && (payload < 16001)) {
if ((payload >= 0) && (payload < 16001)) {
sysCfg.hlw_imax = payload;
}
snprintf_P(svalue, ssvalue, PSTR("{\"CurrentHigh\":\"%d%s\"}"), sysCfg.hlw_imax, (sysCfg.flag.value_units) ? " mA" : "");
}
else if (!strcmp_P(type,PSTR("ENERGYRESET"))) {
if ((data_len > 0) && (payload >= 1) && (payload <= 3)) {
if ((payload >= 1) && (payload <= 3)) {
switch (payload) {
case 1:
hlw_kWhtoday = 0;
@ -500,69 +500,69 @@ boolean hlw_command(char *type, uint16_t index, char *dataBuf, uint16_t data_len
snprintf_P(svalue, ssvalue, PSTR("{\"EnergyReset\":{\"Total\":%s, \"Yesterday\":%s, \"Today\":%s}}"), stemp2, stemp0, stemp1);
}
else if (!strcmp_P(type,PSTR("HLWPCAL"))) {
if ((data_len > 0) && (payload > 0) && (payload < 32001)) {
if ((payload > 0) && (payload < 32001)) {
sysCfg.hlw_pcal = (payload > 9999) ? payload : HLW_PREF_PULSE; // 12530
}
snprintf_P(svalue, ssvalue, PSTR("(\"HlwPcal\":\"%d%s\"}"), sysCfg.hlw_pcal, (sysCfg.flag.value_units) ? " uS" : "");
}
else if (!strcmp_P(type,PSTR("HLWUCAL"))) {
if ((data_len > 0) && (payload > 0) && (payload < 32001)) {
if ((payload > 0) && (payload < 32001)) {
sysCfg.hlw_ucal = (payload > 999) ? payload : HLW_UREF_PULSE; // 1950
}
snprintf_P(svalue, ssvalue, PSTR("{\"HlwUcal\":\"%d%s\"}"), sysCfg.hlw_ucal, (sysCfg.flag.value_units) ? " uS" : "");
}
else if (!strcmp_P(type,PSTR("HLWICAL"))) {
if ((data_len > 0) && (payload > 0) && (payload < 32001)) {
if ((payload > 0) && (payload < 32001)) {
sysCfg.hlw_ical = (payload > 2499) ? payload : HLW_IREF_PULSE; // 3500
}
snprintf_P(svalue, ssvalue, PSTR("{\"HlwIcal\":\"%d%s\"}"), sysCfg.hlw_ical, (sysCfg.flag.value_units) ? " uS" : "");
}
#if FEATURE_POWER_LIMIT
else if (!strcmp_P(type,PSTR("MAXPOWER"))) {
if ((data_len > 0) && (payload >= 0) && (payload < 3601)) {
if ((payload >= 0) && (payload < 3601)) {
sysCfg.hlw_mpl = payload;
}
snprintf_P(svalue, ssvalue, PSTR("{\"MaxPower\":\"%d%s\"}"), sysCfg.hlw_mpl, (sysCfg.flag.value_units) ? " W" : "");
}
else if (!strcmp_P(type,PSTR("MAXPOWERHOLD"))) {
if ((data_len > 0) && (payload >= 0) && (payload < 3601)) {
if ((payload >= 0) && (payload < 3601)) {
sysCfg.hlw_mplh = (1 == payload) ? MAX_POWER_HOLD : payload;
}
snprintf_P(svalue, ssvalue, PSTR("{\"MaxPowerHold\":\"%d%s\"}"), sysCfg.hlw_mplh, (sysCfg.flag.value_units) ? " Sec" : "");
}
else if (!strcmp_P(type,PSTR("MAXPOWERWINDOW"))) {
if ((data_len > 0) && (payload >= 0) && (payload < 3601)) {
if ((payload >= 0) && (payload < 3601)) {
sysCfg.hlw_mplw = (1 == payload) ? MAX_POWER_WINDOW : payload;
}
snprintf_P(svalue, ssvalue, PSTR("{\"MaxPowerWindow\":\"%d%s\"}"), sysCfg.hlw_mplw, (sysCfg.flag.value_units) ? " Sec" : "");
}
else if (!strcmp_P(type,PSTR("SAFEPOWER"))) {
if ((data_len > 0) && (payload >= 0) && (payload < 3601)) {
if ((payload >= 0) && (payload < 3601)) {
sysCfg.hlw_mspl = payload;
}
snprintf_P(svalue, ssvalue, PSTR("{\"SafePower\":\"%d%s\"}"), sysCfg.hlw_mspl, (sysCfg.flag.value_units) ? " W" : "");
}
else if (!strcmp_P(type,PSTR("SAFEPOWERHOLD"))) {
if ((data_len > 0) && (payload >= 0) && (payload < 3601)) {
if ((payload >= 0) && (payload < 3601)) {
sysCfg.hlw_msplh = (1 == payload) ? SAFE_POWER_HOLD : payload;
}
snprintf_P(svalue, ssvalue, PSTR("{\"SafePowerHold\":\"%d%s\"}"), sysCfg.hlw_msplh, (sysCfg.flag.value_units) ? " Sec" : "");
}
else if (!strcmp_P(type,PSTR("SAFEPOWERWINDOW"))) {
if ((data_len > 0) && (payload >= 0) && (payload < 1440)) {
if ((payload >= 0) && (payload < 1440)) {
sysCfg.hlw_msplw = (1 == payload) ? SAFE_POWER_WINDOW : payload;
}
snprintf_P(svalue, ssvalue, PSTR("{\"SafePowerWindow\":\"%d%s\"}"), sysCfg.hlw_msplw, (sysCfg.flag.value_units) ? " Min" : "");
}
else if (!strcmp_P(type,PSTR("MAXENERGY"))) {
if ((data_len > 0) && (payload >= 0) && (payload < 3601)) {
if ((payload >= 0) && (payload < 3601)) {
sysCfg.hlw_mkwh = payload;
hlw_mkwh_state = 3;
}
snprintf_P(svalue, ssvalue, PSTR("{\"MaxEnergy\":\"%d%s\"}"), sysCfg.hlw_mkwh, (sysCfg.flag.value_units) ? " Wh" : "");
}
else if (!strcmp_P(type,PSTR("MAXENERGYSTART"))) {
if ((data_len > 0) && (payload >= 0) && (payload < 24)) {
if ((payload >= 0) && (payload < 24)) {
sysCfg.hlw_mkwhs = payload;
}
snprintf_P(svalue, ssvalue, PSTR("{\"MaxEnergyStart\":\"%d%s\"}"), sysCfg.hlw_mkwhs, (sysCfg.flag.value_units) ? " Hr" : "");