5.1.7 20170616
* Prep removal of SetOptions alternatives
* Restore webpage upgrade error messages removed in 5.1.5
* Add hold button functionality to buttons 2 to 4
* Add command SetOption32 1..100 to set Key Hold Time from 0.1 seconds
to 10 seconds (#200)
* Allow slashes in Topic, GroupTopic, ButtonTopic and SwitchTopic (#507)
* Changed webpage form actions from post to get and use relative path
url (#434, #522)
This commit is contained in:
arendst 2017-06-16 14:33:49 +02:00
parent 98d06e8809
commit d763fd52eb
8 changed files with 185 additions and 121 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.6** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/_releasenotes.ino) for change information.
Current version is **5.1.7** - 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,12 @@
/* 5.1.6 20170606
/* 5.1.7 20170616
* Prep removal of SetOptions alternatives
* Restore webpage upgrade error messages removed in 5.1.5
* Add hold button functionality to buttons 2 to 4
* Add command SetOption32 1..100 to set Key Hold Time from 0.1 seconds to 10 seconds (#200)
* Allow slashes in Topic, GroupTopic, ButtonTopic and SwitchTopic (#507)
* Changed webpage form actions from post to get and use relative path url (#434, #522)
*
* 5.1.6 20170606
* Shrink code
* Removed online configuration of Domoticz In and Domoticz Out MQTT strings
* Removed commands DomoticzInTopic and DomoticzOutTopic

View File

@ -17,13 +17,15 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define PARAM8_SIZE 23 // Number of param bytes
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 mqtt_enabled : 1;
uint32_t mqtt_enabled : 1; // bit 3
uint32_t mqtt_response : 1; // bit 4
uint32_t mqtt_power_retain : 1;
uint32_t mqtt_button_retain : 1;
@ -93,9 +95,8 @@ struct SYSCFG {
uint8_t power;
uint8_t ledstate;
uint8_t ex_switchmode; // Not used since 3.9.21
char ex_domoticz_in_topic[22]; // Not used since 5.1.6
uint8_t param[PARAM8_SIZE]; // was domoticz_in_topic until 5.1.6
char state_text[4][11]; // was domoticz_out_topic until 5.1.6
uint16_t domoticz_update_timer;

View File

@ -456,6 +456,10 @@ void CFG_DefaultSet2()
// 5.0.6
sysCfg.mqtt_retry = MQTT_RETRY_SECS;
// 5.1.7
sysCfg.param[P_HOLD_TIME] = KEY_HOLD_TIME; // Default 4 seconds hold time
}
/********************************************************************************************/
@ -589,7 +593,7 @@ void CFG_Delta()
strlcpy(sysCfg.web_password, WEB_PASSWORD, sizeof(sysCfg.web_password));
}
if (sysCfg.version < 0x03091500) {
for (byte i = 0; i < 4; i++) sysCfg.switchmode[i] = sysCfg.ex_switchmode;
for (byte i = 0; i < 4; i++) sysCfg.switchmode[i] = SWITCH_MODE;
}
if (sysCfg.version < 0x04000200) {
sysCfg.ex_button_restrict = 0;
@ -650,6 +654,9 @@ void CFG_Delta()
memcpy(sysCfg.state_text, sysCfg.ex_state_text, 33);
strlcpy(sysCfg.state_text[3], MQTT_CMND_HOLD, sizeof(sysCfg.state_text[3]));
}
if (sysCfg.version < 0x05010700) {
sysCfg.param[P_HOLD_TIME] = KEY_HOLD_TIME; // Default 4 seconds hold time
}
sysCfg.version = VERSION;
}

View File

@ -24,7 +24,7 @@
- Select IDE Tools - Flash size: "1M (no SPIFFS)"
====================================================*/
#define VERSION 0x05010600 // 5.1.6
#define VERSION 0x05010700 // 5.1.7
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};
@ -148,7 +148,8 @@ enum emul_t {EMUL_NONE, EMUL_WEMO, EMUL_HUE, EMUL_MAX};
#define APP_BAUDRATE 115200 // Default serial baudrate
#define MAX_STATUS 11 // Max number of status lines
enum butt_t {PRESSED, NOT_PRESSED};
enum butt_t {PRESSED, NOT_PRESSED};
enum opt_t {P_HOLD_TIME, P_MAX_PARAM8}; // Index in sysCfg.param
#include "support.h" // Global support
@ -274,11 +275,11 @@ int blinks = 201; // Number of LED blinks
uint8_t blinkstate = 0; // LED state
uint8_t lastbutton[4] = { NOT_PRESSED, NOT_PRESSED, NOT_PRESSED, NOT_PRESSED }; // Last button states
uint8_t holdcount = 0; // Timer recording button hold
uint8_t holdbutton[4] = { 0 }; // Timer for 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 holdwallswitch[4] = { 0 }; // Timer for wallswitch push button hold
uint8_t blockgpio0 = 4; // Block GPIO0 for 4 seconds after poweron to workaround Wemos D1 RTS circuit
mytmplt my_module; // Active copy of GPIOs
@ -660,12 +661,6 @@ boolean mqtt_command(boolean grpflg, char *type, uint16_t index, char *dataBuf,
}
snprintf_P(svalue, ssvalue, PSTR("{\"MqttRetry\":%d}"), sysCfg.mqtt_retry);
}
else if (!strcmp_P(type,PSTR("MQTTRESPONSE"))) {
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 <= 4)) {
if ((data_len > 0) && (data_len < sizeof(sysCfg.state_text[0]))) {
for(i = 0; i <= data_len; i++) {
@ -709,13 +704,7 @@ boolean mqtt_command(boolean grpflg, char *type, uint16_t index, char *dataBuf,
}
else if (!strcmp_P(type,PSTR("FULLTOPIC"))) {
if ((data_len > 0) && (data_len < sizeof(sysCfg.mqtt_fulltopic))) {
for (i = 0; i <= data_len; i++) {
if ((dataBuf[i] == '+') || (dataBuf[i] == '#') || (dataBuf[i] == ' ')) {
for (byte j = i; j <= data_len; j++) {
dataBuf[j] = dataBuf[j +1];
}
}
}
mqttfy(1, dataBuf);
if (!strcmp(dataBuf, MQTTClient)) {
payload = 1;
}
@ -730,11 +719,7 @@ boolean mqtt_command(boolean grpflg, char *type, uint16_t index, char *dataBuf,
}
else if (!strcmp_P(type,PSTR("PREFIX")) && (index > 0) && (index <= 3)) {
if ((data_len > 0) && (data_len < sizeof(sysCfg.mqtt_prefix[0]))) {
for(i = 0; i <= data_len; i++) {
if ((dataBuf[i] == '+') || (dataBuf[i] == '#') || (dataBuf[i] == ' ')) {
dataBuf[i] = '_';
}
}
mqttfy(0, dataBuf);
strlcpy(sysCfg.mqtt_prefix[index -1], (1 == payload) ? (1==index)?SUB_PREFIX:(2==index)?PUB_PREFIX:PUB_PREFIX2 : dataBuf, sizeof(sysCfg.mqtt_prefix[0]));
// if (sysCfg.mqtt_prefix[index -1][strlen(sysCfg.mqtt_prefix[index -1])] == '/') sysCfg.mqtt_prefix[index -1][strlen(sysCfg.mqtt_prefix[index -1])] = 0;
restartflag = 2;
@ -743,11 +728,7 @@ boolean mqtt_command(boolean grpflg, char *type, uint16_t index, char *dataBuf,
}
else if (!strcmp_P(type,PSTR("GROUPTOPIC"))) {
if ((data_len > 0) && (data_len < sizeof(sysCfg.mqtt_grptopic))) {
for(i = 0; i <= data_len; i++) {
if ((dataBuf[i] == '/') || (dataBuf[i] == '+') || (dataBuf[i] == '#')) {
dataBuf[i] = '_';
}
}
mqttfy(0, dataBuf);
if (!strcmp(dataBuf, MQTTClient)) {
payload = 1;
}
@ -758,11 +739,7 @@ boolean mqtt_command(boolean grpflg, char *type, uint16_t index, char *dataBuf,
}
else if (!grpflg && !strcmp_P(type,PSTR("TOPIC"))) {
if ((data_len > 0) && (data_len < sizeof(sysCfg.mqtt_topic))) {
for(i = 0; i <= data_len; i++) {
if ((dataBuf[i] == '/') || (dataBuf[i] == '+') || (dataBuf[i] == '#') || (dataBuf[i] == ' ')) {
dataBuf[i] = '_';
}
}
mqttfy(0, dataBuf);
if (!strcmp(dataBuf, MQTTClient)) {
payload = 1;
}
@ -777,11 +754,7 @@ boolean mqtt_command(boolean grpflg, char *type, uint16_t index, char *dataBuf,
}
else if (!grpflg && !strcmp_P(type,PSTR("BUTTONTOPIC"))) {
if ((data_len > 0) && (data_len < sizeof(sysCfg.button_topic))) {
for(i = 0; i <= data_len; i++) {
if ((dataBuf[i] == '/') || (dataBuf[i] == '+') || (dataBuf[i] == '#') || (dataBuf[i] == ' ')) {
dataBuf[i] = '_';
}
}
mqttfy(0, dataBuf);
if (!strcmp(dataBuf, MQTTClient)) {
payload = 1;
}
@ -791,11 +764,7 @@ boolean mqtt_command(boolean grpflg, char *type, uint16_t index, char *dataBuf,
}
else if (!grpflg && !strcmp_P(type,PSTR("SWITCHTOPIC"))) {
if ((data_len > 0) && (data_len < sizeof(sysCfg.switch_topic))) {
for(i = 0; i <= data_len; i++) {
if ((dataBuf[i] == '/') || (dataBuf[i] == '+') || (dataBuf[i] == '#') || (dataBuf[i] == ' ')) {
dataBuf[i] = '_';
}
}
mqttfy(0, dataBuf);
if (!strcmp(dataBuf, MQTTClient)) {
payload = 1;
}
@ -832,12 +801,8 @@ boolean mqtt_command(boolean grpflg, char *type, uint16_t index, char *dataBuf,
if (!payload) {
for(i = 1; i <= Maxdevice; i++) { // Clear MQTT retain in broker
snprintf_P(stemp2, sizeof(stemp2), PSTR("%d"), i);
snprintf_P(scommand, sizeof(scommand), PSTR("POWER%s"), (Maxdevice > 1) ? stemp2 : "");
getTopic_P(stemp1, 1, sysCfg.mqtt_topic, scommand);
// snprintf_P(stemp1, sizeof(stemp1), PSTR("%s/%s/POWER%s"), sysCfg.mqtt_prefix[1], sysCfg.mqtt_topic, (Maxdevice > 1) ? stemp2 : "");
mqtt_publish(stemp1, "", sysCfg.flag.mqtt_power_retain);
}
}
@ -893,6 +858,8 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
char *p;
char *mtopic = NULL;
char *type = NULL;
byte otype = 0;
byte ptype = 0;
uint16_t i = 0;
uint16_t grpflg = 0;
uint16_t index;
@ -915,7 +882,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
#endif // USE_DOMOTICZ
grpflg = (strstr(topicBuf, sysCfg.mqtt_grptopic) != NULL);
type = strrchr(topicBuf, '/') +1;
type = strrchr(topicBuf, '/') +1; // Last part of received topic is always the command (type)
index = 1;
if (type != NULL) {
@ -939,7 +906,6 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
grpflg, index, type, dataBuf, dataBufUc);
addLog(LOG_LEVEL_DEBUG, svalue);
// snprintf_P(stopic, sizeof(stopic), PSTR("%s/%s/RESULT"), PUB_PREFIX, sysCfg.mqtt_topic);
if (type != NULL) {
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Command\":\"Error\"}"));
if (sysCfg.ledstate &0x02) {
@ -949,9 +915,9 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
if (!strcmp(dataBufUc,"?")) {
data_len = 0;
}
int16_t payload = -1;
int16_t payload = -1; // No payload
if (data_len && isdigit(dataBuf[0])) {
payload = atoi(dataBuf); // -32766 - 32767
payload = atoi(dataBuf); // -32766 - 32767
}
uint16_t payload16 = atoi(dataBuf); // 0 - 65535
@ -1041,21 +1007,47 @@ 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 <= 11)) {
if ((payload >= 0) && (payload <= 1)) {
switch (index) {
case 0: // savestate
case 1: // button_restrict
case 2: // value_units
case 4: // mqtt_response
case 8: // temperature_conversion
case 10: // mqtt_offline
case 11: // button_swap
bitWrite(sysCfg.flag.data, index, payload);
else if (!strcmp_P(type,PSTR("SETOPTION")) && ((index >= 0) && (index <= 11)) || ((index > 31) && (index <= P_MAX_PARAM8 +31))) {
if (index <= 31) {
ptype = 0; // SetOption0 .. 31
} else {
ptype = 1; // SetOption32 ..
index = index -32;
}
if (payload >= 0) {
if (0 == ptype) { // SetOption0 .. 31
if (payload <= 1) {
switch (index) {
case 3: // mqtt
restartflag = 2;
case 0: // savestate
case 1: // button_restrict
case 2: // value_units
case 4: // mqtt_response
case 8: // temperature_conversion
case 10: // mqtt_offline
case 11: // button_swap
bitWrite(sysCfg.flag.data, index, payload);
}
}
}
else { // SetOption32 ..
switch (index) {
case P_HOLD_TIME:
if ((payload >= 1) && (payload <= 100)) {
sysCfg.param[P_HOLD_TIME] = payload;
}
break;
}
}
}
snprintf_P(svalue, sizeof(svalue), PSTR("{\"SetOption%d\":\"%s\"}"), index, getStateText(bitRead(sysCfg.flag.data, index)));
if (ptype) {
snprintf_P(stemp1, sizeof(stemp1), PSTR("%d"), sysCfg.param[index]);
}
snprintf_P(svalue, sizeof(svalue), PSTR("{\"SetOption%d\":\"%s\"}"), (ptype) ? index +32 : index, (ptype) ? stemp1 : getStateText(bitRead(sysCfg.flag.data, index)));
}
// To be removed in near future
else if (!strcmp_P(type,PSTR("SAVESTATE"))) {
if ((payload >= 0) && (payload <= 1)) {
sysCfg.flag.savestate = payload;
@ -1074,6 +1066,12 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
}
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Units\":\"%s\"}"), getStateText(sysCfg.flag.value_units));
}
else if (!strcmp_P(type,PSTR("TEMPUNIT"))) {
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("MQTT"))) {
if ((payload >= 0) && (payload <= 1)) {
sysCfg.flag.mqtt_enabled = payload;
@ -1081,12 +1079,14 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
}
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Mqtt\":\"%s\"}"), getStateText(sysCfg.flag.mqtt_enabled));
}
else if (!strcmp_P(type,PSTR("TEMPUNIT"))) {
else if (!strcmp_P(type,PSTR("MQTTRESPONSE"))) {
if ((payload >= 0) && (payload <= 1)) {
sysCfg.flag.temperature_conversion = payload;
sysCfg.flag.mqtt_response = payload;
}
snprintf_P(svalue, sizeof(svalue), PSTR("{\"TempUnit\":\"%s\"}"), (sysCfg.flag.temperature_conversion) ? "Fahrenheit" : "Celsius");
snprintf_P(svalue, sizeof(svalue), PSTR("{\"MqttResponse\":\"%s\"}"), getStateText(sysCfg.flag.mqtt_response));
}
// Until here
else if (!strcmp_P(type,PSTR("TEMPRES"))) {
if ((payload >= 0) && (payload <= 3)) {
sysCfg.flag.temperature_resolution = payload;
@ -2059,7 +2059,7 @@ void stateloop()
addLog(LOG_LEVEL_DEBUG, log);
button = PRESSED;
if (0xF500 == ButtonCode) {
holdcount = (STATES *4) -1;
holdbutton[0] = (STATES *4) -1;
}
ButtonCode = 0;
} else {
@ -2079,10 +2079,10 @@ void stateloop()
}
lastbutton[0] = button;
if (NOT_PRESSED == button) {
holdcount = 0;
holdbutton[0] = 0;
} else {
holdcount++;
if (KEY_HOLD_TIME == holdcount) { // 4 seconds button hold
holdbutton[0]++;
if (holdbutton[0] == sysCfg.param[P_HOLD_TIME]) { // 4 seconds button hold
multipress = 0;
if (!sysCfg.flag.button_restrict) { // no restriction (OPTION
snprintf_P(scmnd, sizeof(scmnd), PSTR("reset 1"));
@ -2095,7 +2095,7 @@ void stateloop()
if (multiwindow) {
multiwindow--;
} else {
if ((!restartflag) && (!holdcount) && (multipress > 0) && (multipress < MAX_BUTTON_COMMANDS +3)) {
if ((!restartflag) && (!holdbutton[0]) && (multipress > 0) && (multipress < MAX_BUTTON_COMMANDS +3)) {
if ((SONOFF_DUAL == sysCfg.module) || (CH4 == sysCfg.module)) {
flag = ((1 == multipress) || (2 == multipress));
} else {
@ -2124,12 +2124,32 @@ void stateloop()
for (byte i = 1; i < Maxdevice; i++) {
if (pin[GPIO_KEY1 +i] < 99) {
if (holdbutton[i]) {
holdbutton[i]--;
if (0 == holdbutton[i]) {
send_button_power(0, i +1, 3); // Execute command via MQTT
}
}
button = digitalRead(pin[GPIO_KEY1 +i]);
/*
if ((PRESSED == button) && (NOT_PRESSED == lastbutton[i])) {
if (!send_button_power(0, i +1, 2)) { // Execute command via MQTT
do_cmnd_power(i +1, 2); // Execute command internally
}
}
*/
if ((PRESSED == button) && (NOT_PRESSED == lastbutton[i])) {
holdbutton[i] = sysCfg.param[P_HOLD_TIME];
}
if ((NOT_PRESSED == button) && (PRESSED == lastbutton[i]) && (holdbutton[i])) {
holdbutton[i] = 0;
if (!send_button_power(0, i +1, 2)) { // Execute command via MQTT
do_cmnd_power(i +1, 2); // Execute command internally
}
}
lastbutton[i] = button;
}
}
@ -2137,9 +2157,9 @@ void stateloop()
for (byte i = 0; i < 4; i++) {
if (pin[GPIO_SWT1 +i] < 99) {
if (wallswitchtimer[i]) {
wallswitchtimer[i]--;
if (0 == wallswitchtimer[i]) {
if (holdwallswitch[i]) {
holdwallswitch[i]--;
if (0 == holdwallswitch[i]) {
send_button_power(1, i +1, 3); // Execute command via MQTT
}
}
@ -2159,30 +2179,30 @@ void stateloop()
break;
case PUSHBUTTON:
if ((PRESSED == button) && (NOT_PRESSED == lastwallswitch[i])) {
switchflag = 2; // Toggle with pushbutton to Gnd
switchflag = 2; // Toggle with pushbutton to Gnd
}
break;
case PUSHBUTTON_INV:
if ((NOT_PRESSED == button) && (PRESSED == lastwallswitch[i])) {
switchflag = 2; // Toggle with releasing pushbutton from Gnd
switchflag = 2; // Toggle with releasing pushbutton from Gnd
}
break;
case PUSHBUTTONHOLD:
if ((PRESSED == button) && (NOT_PRESSED == lastwallswitch[i])) {
wallswitchtimer[i] = KEY_HOLD_TIME;
holdwallswitch[i] = sysCfg.param[P_HOLD_TIME];
}
if ((NOT_PRESSED == button) && (PRESSED == lastwallswitch[i]) && (wallswitchtimer[i])) {
wallswitchtimer[i] = 0;
switchflag = 2; // Toggle with pushbutton to Gnd
if ((NOT_PRESSED == button) && (PRESSED == lastwallswitch[i]) && (holdwallswitch[i])) {
holdwallswitch[i] = 0;
switchflag = 2; // Toggle with pushbutton to Gnd
}
break;
case PUSHBUTTONHOLD_INV:
if ((NOT_PRESSED == button) && (PRESSED == lastwallswitch[i])) {
wallswitchtimer[i] = KEY_HOLD_TIME;
holdwallswitch[i] = sysCfg.param[P_HOLD_TIME];
}
if ((PRESSED == button) && (NOT_PRESSED == lastwallswitch[i]) && (wallswitchtimer[i])) {
wallswitchtimer[i] = 0;
switchflag = 2; // Toggle with pushbutton to Gnd
if ((PRESSED == button) && (NOT_PRESSED == lastwallswitch[i]) && (holdwallswitch[i])) {
holdwallswitch[i] = 0;
switchflag = 2; // Toggle with pushbutton to Gnd
}
break;
}

View File

@ -166,6 +166,29 @@ boolean parseIP(uint32_t* addr, const char* str)
return (3 == i);
}
void mqttfy(byte option, char* str)
{
// option 0 = replace by underscore
// option 1 = delete character
uint16_t i = 0;
while (str[i] > 0) {
// if ((str[i] == '/') || (str[i] == '+') || (str[i] == '#') || (str[i] == ' ')) {
if ((str[i] == '+') || (str[i] == '#') || (str[i] == ' ')) {
if (option) {
uint16_t j = i;
while (str[j] > 0) {
str[j] = str[j +1];
j++;
}
i--;
} else {
str[i] = '_';
}
}
i++;
}
}
/*********************************************************************************************\
* Wifi
\*********************************************************************************************/

View File

@ -141,7 +141,7 @@
#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 KEY_HOLD_TIME 40 // Number of 0.1 seconds to hold Button or external Pushbutton before sending HOLD message
#define KEY_HOLD_TIME 40 // [SetOption32] 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

View File

@ -135,33 +135,33 @@ const char HTTP_SCRIPT_MODULE[] PROGMEM =
const char HTTP_MSG_RSTRT[] PROGMEM =
"<br/><div style='text-align:center;'>Device will restart in a few seconds</div><br/>";
const char HTTP_BTN_MENU1[] PROGMEM =
"<br/><form action='/cn' method='post'><button>Configuration</button></form>"
"<br/><form action='/in' method='post'><button>Information</button></form>"
"<br/><form action='/up' method='post'><button>Firmware upgrade</button></form>"
"<br/><form action='/cs' method='post'><button>Console</button></form>";
"<br/><form action='cn' method='get'><button>Configuration</button></form>"
"<br/><form action='in' method='get'><button>Information</button></form>"
"<br/><form action='up' method='get'><button>Firmware upgrade</button></form>"
"<br/><form action='cs' method='get'><button>Console</button></form>";
const char HTTP_BTN_RSTRT[] PROGMEM =
"<br/><form action='/rb' method='post' onsubmit='return confirm(\"Confirm Restart\");'><button>Restart</button></form>";
"<br/><form action='rb' method='get' onsubmit='return confirm(\"Confirm Restart\");'><button>Restart</button></form>";
const char HTTP_BTN_MENU2[] PROGMEM =
"<br/><form action='/md' method='post'><button>Configure Module</button></form>"
"<br/><form action='/w0' method='post'><button>Configure WiFi</button></form>";
"<br/><form action='md' method='get'><button>Configure Module</button></form>"
"<br/><form action='w0' method='get'><button>Configure WiFi</button></form>";
const char HTTP_BTN_MENU3[] PROGMEM =
"<br/><form action='/mq' method='post'><button>Configure MQTT</button></form>"
"<br/><form action='mq' method='get'><button>Configure MQTT</button></form>"
#ifdef USE_DOMOTICZ
"<br/><form action='/dm' method='post'><button>Configure Domoticz</button></form>"
"<br/><form action='dm' method='get'><button>Configure Domoticz</button></form>"
#endif // USE_DOMOTICZ
"";
const char HTTP_BTN_MENU4[] PROGMEM =
"<br/><form action='/lg' method='post'><button>Configure Logging</button></form>"
"<br/><form action='/co' method='post'><button>Configure Other</button></form>"
"<br/><form action='/rt' method='post' onsubmit='return confirm(\"Confirm Reset Configuration\");'><button>Reset Configuration</button></form>"
"<br/><form action='/dl' method='post'><button>Backup Configuration</button></form>"
"<br/><form action='/rs' method='post'><button>Restore Configuration</button></form>";
"<br/><form action='lg' method='get'><button>Configure Logging</button></form>"
"<br/><form action='co' method='get'><button>Configure Other</button></form>"
"<br/><form action='rt' method='get' onsubmit='return confirm(\"Confirm Reset Configuration\");'><button>Reset Configuration</button></form>"
"<br/><form action='dl' method='get'><button>Backup Configuration</button></form>"
"<br/><form action='rs' method='get'><button>Restore Configuration</button></form>";
const char HTTP_BTN_MAIN[] PROGMEM =
"<br/><br/><form action='/' method='post'><button>Main menu</button></form>";
"<br/><br/><form action='.' method='get'><button>Main menu</button></form>";
const char HTTP_BTN_CONF[] PROGMEM =
"<br/><br/><form action='/cn' method='post'><button>Configuration menu</button></form>";
"<br/><br/><form action='cn' method='get'><button>Configuration menu</button></form>";
const char HTTP_FORM_MODULE[] PROGMEM =
"<fieldset><legend><b>&nbsp;Module parameters&nbsp;</b></legend><form method='post' action='sv'>"
"<fieldset><legend><b>&nbsp;Module parameters&nbsp;</b></legend><form method='get' action='sv'>"
"<input id='w' name='w' value='6' hidden><input id='r' name='r' value='1' hidden>"
"<br/><b>Module type</b> ({mt})<br/><select id='mt' name='mt'>";
const char HTTP_LNK_ITEM[] PROGMEM =
@ -169,7 +169,7 @@ const char HTTP_LNK_ITEM[] PROGMEM =
const char HTTP_LNK_SCAN[] PROGMEM =
"<div><a href='/w1'>Scan for wifi networks</a></div><br/>";
const char HTTP_FORM_WIFI[] PROGMEM =
"<fieldset><legend><b>&nbsp;Wifi parameters&nbsp;</b></legend><form method='post' action='sv'>"
"<fieldset><legend><b>&nbsp;Wifi parameters&nbsp;</b></legend><form method='get' action='sv'>"
"<input id='w' name='w' value='1' hidden><input id='r' name='r' value='1' hidden>"
"<br/><b>AP1 SSId</b> (" STA_SSID1 ")<br/><input id='s1' name='s1' length=32 placeholder='" STA_SSID1 "' value='{s1}'><br/>"
"<br/><b>AP1 Password</b></br><input id='p1' name='p1' length=64 type='password' placeholder='" STA_PASS1 "' value='{p1}'><br/>"
@ -177,7 +177,7 @@ const char HTTP_FORM_WIFI[] PROGMEM =
"<br/><b>AP2 Password</b></br><input id='p2' name='p2' length=64 type='password' placeholder='" STA_PASS2 "' value='{p2}'><br/>"
"<br/><b>Hostname</b> (" WIFI_HOSTNAME ")<br/><input id='h' name='h' length=32 placeholder='" WIFI_HOSTNAME" ' value='{h1}'><br/>";
const char HTTP_FORM_MQTT[] PROGMEM =
"<fieldset><legend><b>&nbsp;MQTT parameters&nbsp;</b></legend><form method='post' action='sv'>"
"<fieldset><legend><b>&nbsp;MQTT parameters&nbsp;</b></legend><form method='get' action='sv'>"
"<input id='w' name='w' value='2' hidden><input id='r' name='r' value='1' hidden>"
"<br/><b>Host</b> (" MQTT_HOST ")<br/><input id='mh' name='mh' length=32 placeholder='" MQTT_HOST" ' value='{m1}'><br/>"
"<br/><b>Port</b> (" STR(MQTT_PORT) ")<br/><input id='ml' name='ml' length=5 placeholder='" STR(MQTT_PORT) "' value='{m2}'><br/>"
@ -187,7 +187,7 @@ const char HTTP_FORM_MQTT[] PROGMEM =
"<br/><b>Topic</b> = %topic% (" MQTT_TOPIC ")<br/><input id='mt' name='mt' length=32 placeholder='" MQTT_TOPIC" ' value='{m6}'><br/>"
"<br/><b>Full Topic</b> (" MQTT_FULLTOPIC ")<br/><input id='mf' name='mf' length=80 placeholder='" MQTT_FULLTOPIC" ' value='{m7}'><br/>";
const char HTTP_FORM_LOG1[] PROGMEM =
"<fieldset><legend><b>&nbsp;Logging parameters&nbsp;</b></legend><form method='post' action='sv'>"
"<fieldset><legend><b>&nbsp;Logging parameters&nbsp;</b></legend><form method='get' action='sv'>"
"<input id='w' name='w' value='3' hidden><input id='r' name='r' value='0' hidden>";
const char HTTP_FORM_LOG2[] PROGMEM =
"<br/><b>{b0}log level</b> ({b1})<br/><select id='{b2}' name='{b2}'>"
@ -202,7 +202,7 @@ const char HTTP_FORM_LOG3[] PROGMEM =
"<br/><b>Syslog port</b> (" STR(SYS_LOG_PORT) ")<br/><input id='lp' name='lp' length=5 placeholder='" STR(SYS_LOG_PORT) "' value='{l3}'><br/>"
"<br/><b>Telemetric period</b> (" STR(TELE_PERIOD) ")<br/><input id='lt' name='lt' length=4 placeholder='" STR(TELE_PERIOD) "' value='{l4}'><br/>";
const char HTTP_FORM_OTHER[] PROGMEM =
"<fieldset><legend><b>&nbsp;Other parameters&nbsp;</b></legend><form method='post' action='sv'>"
"<fieldset><legend><b>&nbsp;Other parameters&nbsp;</b></legend><form method='get' action='sv'>"
"<input id='w' name='w' value='5' hidden><input id='r' name='r' value='1' hidden>"
"<br/><b>Web Admin Password</b><br/><input id='p1' name='p1' length=32 type='password' placeholder='" WEB_PASSWORD "' value='{p1}'><br/>"
"<br/><input style='width:10%;float:left' id='b1' name='b1' type='checkbox'{r1}><b>MQTT enable</b><br/>";
@ -222,7 +222,7 @@ const char HTTP_FORM_RST[] PROGMEM =
const char HTTP_FORM_UPG[] PROGMEM =
"<div id='f1' name='f1' style='display:block;'>"
"<fieldset><legend><b>&nbsp;Upgrade by web server&nbsp;</b></legend>"
"<form method='post' action='u1'>"
"<form method='get' action='u1'>"
"<br/>OTA Url<br/><input id='o' name='o' length=80 placeholder='OTA_URL' value='{o1}'><br/>"
"<br/><button type='submit'>Start upgrade</button></form>"
"</fieldset><br/><br/>"
@ -929,7 +929,9 @@ void handleSave()
break;
case 2:
strlcpy(stemp, (!strlen(webServer->arg("mt").c_str())) ? MQTT_TOPIC : webServer->arg("mt").c_str(), sizeof(stemp));
mqttfy(0, stemp);
strlcpy(stemp2, (!strlen(webServer->arg("mf").c_str())) ? MQTT_FULLTOPIC : webServer->arg("mf").c_str(), sizeof(stemp2));
mqttfy(1,stemp2);
if ((strcmp(stemp, sysCfg.mqtt_topic)) || (strcmp(stemp2, sysCfg.mqtt_fulltopic))) {
mqtt_publish_topic_P(2, PSTR("LWT"), (sysCfg.flag.mqtt_offline) ? "Offline" : "", true); // Offline or remove previous retained topic
}
@ -1126,18 +1128,18 @@ void handleUploadDone()
page += F("<div style='text-align:center;'><b>Upload ");
if (_uploaderror) {
page += F("<font color='red'>failed</font></b><br/><br/>");
if (!_uploadfiletype && Update.hasError()) {
StreamString str;
Update.printError(str);
snprintf_P(error, sizeof(error), str.c_str());
} else {
snprintf_P(error, sizeof(error), PSTR("Upload error code %d"), _uploaderror);
}
switch (_uploaderror) {
case 1: strcpy_P(error, PSTR("No file selected")); break;
case 2: strcpy_P(error, PSTR("Not enough space")); break;
case 3: strcpy_P(error, PSTR("Magic byte is not 0xE9")); break;
case 4: strcpy_P(error, PSTR("IDE flash size larger than device flash size")); break;
case 5: strcpy_P(error, PSTR("Upload buffer miscompare")); break;
case 6: strcpy_P(error, PSTR("Upload failed. Enable logging 3")); break;
case 7: strcpy_P(error, PSTR("Upload aborted")); break;
case 8: strcpy_P(error, PSTR("Invalid configuration file")); break;
case 9: strcpy_P(error, PSTR("Configuration file too large")); break;
case 8: strcpy_P(error, PSTR("File invalid")); break;
case 9: strcpy_P(error, PSTR("File too large")); break;
default:
snprintf_P(error, sizeof(error), PSTR("Upload error code %d"), _uploaderror);
}
page += error;
snprintf_P(log, sizeof(log), PSTR("Upload: %s"), error);
@ -1249,6 +1251,9 @@ void handleUploadLoop()
}
if (!_uploadfiletype) {
if (!Update.end(true)) { // true to set the size to the current progress
if (_serialoutput) {
Update.printError(Serial);
}
_uploaderror = 6;
return;
}