4.0.8 20170321
* Fix entering non-numeric webpassword
* Force selection between TLS or Webserver due to memory restraint
(#240)
* Allow entering empty string using "0" for selected commands (#242)
* Fix exception when posting commands to web console containing % (#250)
This commit is contained in:
arendst 2017-03-21 16:17:28 +01:00
parent 742a87df8a
commit 99b7474ac4
7 changed files with 56 additions and 37 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 **4.0.7** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/_releasenotes.ino) for change information.
Current version is **4.0.8** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/_releasenotes.ino) for change information.
- This version provides all (Sonoff) modules in one file and starts up with Sonoff Basic.
- Once uploaded select module using the configuration webpage or the commands ```Modules``` and ```Module```.

Binary file not shown.

View File

@ -1,4 +1,10 @@
/* 4.0.7 20170319
/* 4.0.8 20170321
* Fix entering non-numeric webpassword
* Force selection between TLS or Webserver due to memory restraint (#240)
* Allow entering empty string using "0" for selected commands (#242)
* Fix exception when posting commands to web console containing % (#250)
*
* 4.0.7 20170319
* Increased Sonoff Led PWM frequency from 432 to 1000
* Fix possible watch dog reboot after changing module type on web page
* Fix reporting of GPIO usage from web page

View File

@ -145,11 +145,17 @@ struct SYSCFG {
uint16_t hlw_mkwh; // MaxEnergy
uint16_t hlw_mkwhs; // MaxEnergyStart
// 3.0.6
uint16_t ex_pulsetime; // Not used since 4.0.4
// 3.1.1
uint8_t poweronstate;
// 3.1.6
uint16_t blinktime;
uint16_t blinkcount;
// 3.2.4
uint16_t ws_pixels;
uint8_t ws_red;
uint8_t ws_green;
@ -162,18 +168,22 @@ struct SYSCFG {
uint8_t ws_width;
uint16_t ws_wakeup;
// 3.2.5
char friendlyname[4][33];
// 3.2.8
char switch_topic[33];
byte mqtt_switch_retain;
uint8_t mqtt_enabled;
// 3.2.12
uint8_t sleep;
// 3.9.3
uint16_t domoticz_switch_idx[4];
uint16_t domoticz_sensor_idx[12];
uint8_t module;
mytmplt my_module;
uint16_t led_pixels;
uint8_t led_color[5];
uint8_t led_table;
@ -184,13 +194,20 @@ struct SYSCFG {
uint8_t led_width;
uint16_t led_wakeup;
// 3.9.7
uint8_t emulation;
// 3.9.20
char web_password[33];
// 3.9.21
uint8_t switchmode[4];
// 4.0.4
char ntp_server[3][33];
uint16_t pulsetime[MAX_PULSETIMERS];
// 4.0.7
uint16_t pwmvalue[5];
} sysCfg;

View File

@ -12,9 +12,9 @@
//#define ALLOW_MIGRATE_TO_V3
#ifdef ALLOW_MIGRATE_TO_V3
#define VERSION 0x03091E00 // 3.9.30
#define VERSION 0x03091F00 // 3.9.31
#else
#define VERSION 0x04000700 // 4.0.7
#define VERSION 0x04000800 // 4.0.8
#endif // ALLOW_MIGRATE_TO_V3
enum log_t {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL};
@ -115,7 +115,7 @@ enum emul_t {EMUL_NONE, EMUL_WEMO, EMUL_HUE, EMUL_MAX};
#define MAX_PULSETIMERS 4 // Max number of supported pulse timers
#define WS2812_MAX_LEDS 256 // Max number of LEDs
#define PWM_RANGE 1023 // 127..1023 but as Color is addressed by 8 bits it should be 255 for my code
#define PWM_RANGE 1023 // 255..1023 needs to be devisible by 256
#define PWM_FREQ 1000 // 100..1000 Hz led refresh
#define MAX_POWER_HOLD 10 // Time in SECONDS to allow max agreed power (Pow)
@ -132,11 +132,7 @@ enum emul_t {EMUL_NONE, EMUL_WEMO, EMUL_HUE, EMUL_MAX};
#define INPUT_BUFFER_SIZE 100 // Max number of characters in serial buffer
#define TOPSZ 60 // Max number of characters in topic string
#define LOGSZ 128 // Max number of characters in log string
#ifdef USE_MQTT_TLS
#define MAX_LOG_LINES 10 // Max number of lines in weblog
#else
#define MAX_LOG_LINES 20 // Max number of lines in weblog
#endif
#define MAX_LOG_LINES 20 // Max number of lines in weblog
#define APP_BAUDRATE 115200 // Default serial baudrate
#define MAX_STATUS 11 // Max number of status lines
@ -144,8 +140,8 @@ enum emul_t {EMUL_NONE, EMUL_WEMO, EMUL_HUE, EMUL_MAX};
enum butt_t {PRESSED, NOT_PRESSED};
#include "support.h" // Global support
#include <PubSubClient.h> // MQTT
#include <PubSubClient.h> // MQTT
#define MESSZ 360 // Max number of characters in JSON message string (4 x DS18x20 sensors)
#if (MQTT_MAX_PACKET_SIZE -TOPSZ -7) < MESSZ // If the max message size is too small, throw an error at compile time
// See pubsubclient.c line 359
@ -620,7 +616,7 @@ boolean mqtt_command(boolean grpflg, char *type, uint16_t index, char *dataBuf,
#ifdef USE_MQTT_TLS
else if (!strcmp(type,"MQTTFINGERPRINT")) {
if ((data_len > 0) && (data_len < sizeof(sysCfg.mqtt_fingerprint))) {
strlcpy(sysCfg.mqtt_fingerprint, (payload == 1) ? MQTT_FINGERPRINT : dataBuf, sizeof(sysCfg.mqtt_fingerprint));
strlcpy(sysCfg.mqtt_fingerprint, (!strcmp(dataBuf,"0")) ? "" : (payload == 1) ? MQTT_FINGERPRINT : dataBuf, sizeof(sysCfg.mqtt_fingerprint));
restartflag = 2;
}
snprintf_P(svalue, ssvalue, PSTR("{\"MqttFingerprint\":\"%s\"}"), sysCfg.mqtt_fingerprint);
@ -635,14 +631,14 @@ boolean mqtt_command(boolean grpflg, char *type, uint16_t index, char *dataBuf,
}
else if (!strcmp(type,"MQTTUSER")) {
if ((data_len > 0) && (data_len < sizeof(sysCfg.mqtt_user))) {
strlcpy(sysCfg.mqtt_user, (payload == 1) ? MQTT_USER : dataBuf, sizeof(sysCfg.mqtt_user));
strlcpy(sysCfg.mqtt_user, (!strcmp(dataBuf,"0")) ? "" : (payload == 1) ? MQTT_USER : dataBuf, sizeof(sysCfg.mqtt_user));
restartflag = 2;
}
snprintf_P(svalue, ssvalue, PSTR("[\"MqttUser\":\"%s\"}"), sysCfg.mqtt_user);
}
else if (!strcmp(type,"MQTTPASSWORD")) {
if ((data_len > 0) && (data_len < sizeof(sysCfg.mqtt_pwd))) {
strlcpy(sysCfg.mqtt_pwd, (payload == 1) ? MQTT_PASS : dataBuf, sizeof(sysCfg.mqtt_pwd));
strlcpy(sysCfg.mqtt_pwd, (!strcmp(dataBuf,"0")) ? "" : (payload == 1) ? MQTT_PASS : dataBuf, sizeof(sysCfg.mqtt_pwd));
restartflag = 2;
}
snprintf_P(svalue, ssvalue, PSTR("{\"MqttPassword\":\"%s\"}"), sysCfg.mqtt_pwd);
@ -672,7 +668,7 @@ boolean mqtt_command(boolean grpflg, char *type, uint16_t index, char *dataBuf,
for(i = 0; i <= data_len; i++)
if ((dataBuf[i] == '/') || (dataBuf[i] == '+') || (dataBuf[i] == '#') || (dataBuf[i] == ' ')) dataBuf[i] = '_';
if (!strcmp(dataBuf, MQTTClient)) payload = 1;
strlcpy(sysCfg.button_topic, (payload == 1) ? sysCfg.mqtt_topic : dataBuf, sizeof(sysCfg.button_topic));
strlcpy(sysCfg.button_topic, (!strcmp(dataBuf,"0")) ? "" : (payload == 1) ? sysCfg.mqtt_topic : dataBuf, sizeof(sysCfg.button_topic));
}
snprintf_P(svalue, ssvalue, PSTR("{\"ButtonTopic\":\"%s\"}"), sysCfg.button_topic);
}
@ -681,7 +677,7 @@ boolean mqtt_command(boolean grpflg, char *type, uint16_t index, char *dataBuf,
for(i = 0; i <= data_len; i++)
if ((dataBuf[i] == '/') || (dataBuf[i] == '+') || (dataBuf[i] == '#') || (dataBuf[i] == ' ')) dataBuf[i] = '_';
if (!strcmp(dataBuf, MQTTClient)) payload = 1;
strlcpy(sysCfg.switch_topic, (payload == 1) ? sysCfg.mqtt_topic : dataBuf, sizeof(sysCfg.switch_topic));
strlcpy(sysCfg.switch_topic, (!strcmp(dataBuf,"0")) ? "" : (payload == 1) ? sysCfg.mqtt_topic : dataBuf, sizeof(sysCfg.switch_topic));
}
snprintf_P(svalue, ssvalue, PSTR("{\"SwitchTopic\":\"%s\"}"), sysCfg.switch_topic);
}
@ -1038,7 +1034,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
}
else if (!strcmp(type,"NTPSERVER") && (index > 0) && (index <= 3)) {
if ((data_len > 0) && (data_len < sizeof(sysCfg.ntp_server[0]))) {
strlcpy(sysCfg.ntp_server[index -1], (payload == 1) ? (index==1)?NTP_SERVER1:(index==2)?NTP_SERVER2:NTP_SERVER3 : dataBuf, sizeof(sysCfg.ntp_server[0]));
strlcpy(sysCfg.ntp_server[index -1], (!strcmp(dataBuf,"0")) ? "" : (payload == 1) ? (index==1)?NTP_SERVER1:(index==2)?NTP_SERVER2:NTP_SERVER3 : dataBuf, sizeof(sysCfg.ntp_server[0]));
for (i = 0; i < strlen(sysCfg.ntp_server[index -1]); i++) if (sysCfg.ntp_server[index -1][i] == ',') sysCfg.ntp_server[index -1][i] = '.';
restartflag = 2;
}
@ -1128,11 +1124,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
}
else if (!strcmp(type,"WEBPASSWORD")) {
if ((data_len > 0) && (data_len < sizeof(sysCfg.web_password))) {
if (payload == 0) {
sysCfg.web_password[0] = 0; // No password
} else {
strlcpy(sysCfg.web_password, (payload == 1) ? WEB_PASSWORD : dataBuf, sizeof(sysCfg.web_password));
}
strlcpy(sysCfg.web_password, (!strcmp(dataBuf,"0")) ? "" : (payload == 1) ? WEB_PASSWORD : dataBuf, sizeof(sysCfg.web_password));
}
snprintf_P(svalue, sizeof(svalue), PSTR("{\"WebPassword\":\"%s\"}"), sysCfg.web_password);
}
@ -1757,7 +1749,7 @@ void stateloop()
} else {
flag = (multipress == 1);
}
if (flag && sysCfg.mqtt_enabled && mqttClient.connected() && strcmp(sysCfg.button_topic, "0")) {
if (flag && sysCfg.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
} else {
if ((multipress == 1) || (multipress == 2)) {
@ -1780,7 +1772,7 @@ void stateloop()
for (byte i = 1; i < Maxdevice; i++) if (pin[GPIO_KEY1 +i] < 99) {
button = digitalRead(pin[GPIO_KEY1 +i]);
if ((button == PRESSED) && (lastbutton[i] == NOT_PRESSED)) {
if (sysCfg.mqtt_enabled && mqttClient.connected() && strcmp(sysCfg.button_topic, "0")) {
if (sysCfg.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
@ -1789,7 +1781,6 @@ void stateloop()
lastbutton[i] = button;
}
// for (byte i = 0; i < Maxdevice; i++) if (pin[GPIO_SWT1 +i] < 99) {
for (byte i = 0; i < 4; i++) if (pin[GPIO_SWT1 +i] < 99) {
button = digitalRead(pin[GPIO_SWT1 +i]);
if (button != lastwallswitch[i]) {
@ -1811,7 +1802,7 @@ void stateloop()
if ((button == NOT_PRESSED) && (lastwallswitch[i] == PRESSED)) switchflag = 2; // Toggle with releasing pushbutton from Gnd
}
if (switchflag < 3) {
if (sysCfg.mqtt_enabled && mqttClient.connected() && strcmp(sysCfg.switch_topic,"0")) {
if (sysCfg.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)

View File

@ -157,6 +157,10 @@
* No user configurable items below
\*********************************************************************************************/
#if defined(USE_MQTT_TLS) && defined(USE_WEBSERVER)
#error "Select either USE_MQTT_TLS or USE_WEBSERVER as there is just not enough memory to play with"
#endif
#if (ARDUINO < 10610)
#error "This software is supported with Arduino IDE starting from 1.6.10 and ESP8266 Release 2.3.0"
#endif

View File

@ -103,7 +103,8 @@ const char HTTP_SCRIPT_CONSOL[] PROGMEM =
"t=document.getElementById('t1');"
"if(p==1){"
"c=document.getElementById('c1');"
"o='&c1='+c.value;"
// "o='&c1='+c.value;"
"o='&c1='+encodeURI(c.value);"
"c.value='';"
"t.scrollTop=sn;"
"}"
@ -691,8 +692,8 @@ void handleMqtt()
page.replace("{m1}", sysCfg.mqtt_host);
page.replace("{m2}", String(sysCfg.mqtt_port));
page.replace("{m3}", sysCfg.mqtt_client);
page.replace("{m4}", sysCfg.mqtt_user);
page.replace("{m5}", sysCfg.mqtt_pwd);
page.replace("{m4}", (sysCfg.mqtt_user[0] == '\0')?"0":sysCfg.mqtt_user);
page.replace("{m5}", (sysCfg.mqtt_pwd[0] == '\0')?"0":sysCfg.mqtt_pwd);
page.replace("{m6}", sysCfg.mqtt_topic);
page += FPSTR(HTTP_FORM_END);
page += FPSTR(HTTP_BTN_CONF);
@ -829,8 +830,8 @@ void handleSave()
strlcpy(sysCfg.mqtt_host, (!strlen(webServer->arg("mh").c_str())) ? MQTT_HOST : webServer->arg("mh").c_str(), sizeof(sysCfg.mqtt_host));
sysCfg.mqtt_port = (!strlen(webServer->arg("ml").c_str())) ? MQTT_PORT : atoi(webServer->arg("ml").c_str());
strlcpy(sysCfg.mqtt_client, (!strlen(webServer->arg("mc").c_str())) ? MQTT_CLIENT_ID : webServer->arg("mc").c_str(), sizeof(sysCfg.mqtt_client));
strlcpy(sysCfg.mqtt_user, (!strlen(webServer->arg("mu").c_str())) ? MQTT_USER : webServer->arg("mu").c_str(), sizeof(sysCfg.mqtt_user));
strlcpy(sysCfg.mqtt_pwd, (!strlen(webServer->arg("mp").c_str())) ? MQTT_PASS : webServer->arg("mp").c_str(), sizeof(sysCfg.mqtt_pwd));
strlcpy(sysCfg.mqtt_user, (!strlen(webServer->arg("mu").c_str())) ? MQTT_USER : (!strcmp(webServer->arg("mu").c_str(),"0")) ? "" : webServer->arg("mu").c_str(), sizeof(sysCfg.mqtt_user));
strlcpy(sysCfg.mqtt_pwd, (!strlen(webServer->arg("mp").c_str())) ? MQTT_PASS : (!strcmp(webServer->arg("mp").c_str(),"0")) ? "" : webServer->arg("mp").c_str(), sizeof(sysCfg.mqtt_pwd));
strlcpy(sysCfg.mqtt_topic, (!strlen(webServer->arg("mt").c_str())) ? MQTT_TOPIC : webServer->arg("mt").c_str(), sizeof(sysCfg.mqtt_topic));
snprintf_P(log, sizeof(log), PSTR("HTTP: MQTT Host %s, Port %d, Client %s, User %s, Password %s, Topic %s"),
sysCfg.mqtt_host, sysCfg.mqtt_port, sysCfg.mqtt_client, sysCfg.mqtt_user, sysCfg.mqtt_pwd, sysCfg.mqtt_topic);
@ -855,8 +856,7 @@ void handleSave()
break;
#endif // USE_DOMOTICZ
case 5:
strlcpy(sysCfg.web_password, (!strlen(webServer->arg("p1").c_str())) ? WEB_PASSWORD : webServer->arg("p1").c_str(), sizeof(sysCfg.web_password));
if (sysCfg.web_password[0] == '0') sysCfg.web_password[0] = '\0';
strlcpy(sysCfg.web_password, (!strlen(webServer->arg("p1").c_str())) ? WEB_PASSWORD : (!strcmp(webServer->arg("p1").c_str(),"0")) ? "" : webServer->arg("p1").c_str(), sizeof(sysCfg.web_password));
sysCfg.mqtt_enabled = webServer->hasArg("b1");
#ifdef USE_EMULATION
sysCfg.emulation = (!strlen(webServer->arg("b2").c_str())) ? 0 : atoi(webServer->arg("b2").c_str());
@ -1152,7 +1152,8 @@ void handleCmnd()
if (valid) {
byte curridx = logidx;
if (strlen(webServer->arg("cmnd").c_str())) {
snprintf_P(svalue, sizeof(svalue), webServer->arg("cmnd").c_str());
// snprintf_P(svalue, sizeof(svalue), webServer->arg("cmnd").c_str());
snprintf_P(svalue, sizeof(svalue), PSTR("%s"), webServer->arg("cmnd").c_str());
byte syslog_now = syslog_level;
syslog_level = 0; // Disable UDP syslog to not trigger hardware WDT
do_cmnd(svalue);
@ -1211,7 +1212,7 @@ void handleAjax()
byte cflg = 1, counter = 99;
if (strlen(webServer->arg("c1").c_str())) {
snprintf_P(svalue, sizeof(svalue), webServer->arg("c1").c_str());
snprintf_P(svalue, sizeof(svalue), PSTR("%s"), webServer->arg("c1").c_str());
snprintf_P(log, sizeof(log), PSTR("CMND: %s"), svalue);
addLog(LOG_LEVEL_INFO, log);
byte syslog_now = syslog_level;