mirror of https://github.com/arendst/Tasmota.git
v5.2.3
5.2.3 20170630 * Change Sonoff Led color conversion code * Fix SetOption12 handling * Simplify auto configuration upgrade * Add option Upgrade <version_number> to only upgrade to any higher version (Old PR #213) * Change FallbackTopic to cmnd/<MQTTClient>/<command> <parameter> bypassing FullTopic and Prefix (#538)
This commit is contained in:
parent
e914053041
commit
ee883bdcb8
|
@ -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.2.2** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/_releasenotes.ino) for change information.
|
||||
Current version is **5.2.3** - 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 ****
|
||||
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
/* 5.2.2 20170625
|
||||
/* 5.2.3 20170630
|
||||
* Change Sonoff Led color conversion code
|
||||
* Fix SetOption12 handling
|
||||
* Simplify auto configuration upgrade
|
||||
* Add option Upgrade <version_number> to only upgrade to any higher version (Old PR #213)
|
||||
* Change FallbackTopic to cmnd/<MQTTClient>/<command> <parameter> bypassing FullTopic and Prefix (#538)
|
||||
*
|
||||
* 5.2.2 20170625
|
||||
* Add configuration SaveAddress to Status 1 and Information Page
|
||||
* Change Sonoff Led Color conversion from AtoH to strtol
|
||||
* Fix possible wrong uploads due to configuration overwrites (#542)
|
||||
|
|
|
@ -200,15 +200,26 @@ uint32_t CFG_Address()
|
|||
return _cfgLocation * SPI_FLASH_SEC_SIZE;
|
||||
}
|
||||
|
||||
void CFG_Save(byte no_rotate)
|
||||
void CFG_Save(byte rotate)
|
||||
{
|
||||
/* Save configuration in eeprom or one of 7 slots below
|
||||
*
|
||||
* rotate 0 = Save in next flash slot
|
||||
* rotate 1 = Save only in eeprom flash slot until SetOption12 0 or restart
|
||||
* rotate 2 = Save in eeprom flash slot and continue depending on stop_flash_rotate
|
||||
* stop_flash_rotate 0 = Allow flash slot rotation (SetOption12 0)
|
||||
* stop_flash_rotate 1 = Allow only eeprom flash slot use (SetOption12 1)
|
||||
*/
|
||||
char log[LOGSZ];
|
||||
|
||||
#ifndef BE_MINIMAL
|
||||
if ((getHash() != _cfgHash) || no_rotate) {
|
||||
if (no_rotate) {
|
||||
if ((getHash() != _cfgHash) || rotate) {
|
||||
if (1 == rotate) {
|
||||
stop_flash_rotate = 1; // Disable flash rotate from now on
|
||||
}
|
||||
if (2 == rotate) {
|
||||
_cfgLocation = CFG_LOCATION +1;
|
||||
}
|
||||
if (stop_flash_rotate) {
|
||||
_cfgLocation = CFG_LOCATION;
|
||||
} else {
|
||||
|
@ -222,7 +233,7 @@ void CFG_Save(byte no_rotate)
|
|||
spi_flash_erase_sector(_cfgLocation);
|
||||
spi_flash_write(_cfgLocation * SPI_FLASH_SEC_SIZE, (uint32*)&sysCfg, sizeof(SYSCFG));
|
||||
interrupts();
|
||||
if (!stop_flash_rotate && no_rotate) {
|
||||
if (!stop_flash_rotate && rotate) {
|
||||
for (byte i = 1; i < CFG_ROTATES; i++) {
|
||||
noInterrupts();
|
||||
spi_flash_erase_sector(_cfgLocation -i); // Delete previous configurations by resetting to 0xFF
|
||||
|
@ -240,6 +251,8 @@ void CFG_Save(byte no_rotate)
|
|||
|
||||
void CFG_Load()
|
||||
{
|
||||
/* Load configuration from eeprom or one of 7 slots below if first load does not stop_flash_rotate
|
||||
*/
|
||||
char log[LOGSZ];
|
||||
|
||||
struct SYSCFGH {
|
||||
|
@ -258,7 +271,7 @@ void CFG_Load()
|
|||
// snprintf_P(log, sizeof(log), PSTR("Cnfg: Check at %X with count %d and holder %X"), _cfgLocation -1, _sysCfgH.saveFlag, _sysCfgH.cfg_holder);
|
||||
// addLog(LOG_LEVEL_DEBUG, log);
|
||||
|
||||
if (sysCfg.flag.stop_flash_rotate || (sysCfg.cfg_holder != _sysCfgH.cfg_holder) || (sysCfg.saveFlag > _sysCfgH.saveFlag)) {
|
||||
if (((sysCfg.version > 0x05000200) && sysCfg.flag.stop_flash_rotate) || (sysCfg.cfg_holder != _sysCfgH.cfg_holder) || (sysCfg.saveFlag > _sysCfgH.saveFlag)) {
|
||||
break;
|
||||
}
|
||||
delay(1);
|
||||
|
@ -271,8 +284,9 @@ void CFG_Load()
|
|||
}
|
||||
*/
|
||||
if (sysCfg.cfg_holder != CFG_HOLDER) {
|
||||
/*
|
||||
// Auto upgrade
|
||||
if ((sysCfg.version < 0x04020000) || (sysCfg.version > 0x06000000)) {
|
||||
if ((sysCfg.version < 0x04020000) || (sysCfg.version > VERSION)) {
|
||||
noInterrupts();
|
||||
spi_flash_read((CFG_LOCATION_3) * SPI_FLASH_SEC_SIZE, (uint32*)&sysCfg, sizeof(SYSCFG));
|
||||
spi_flash_read((CFG_LOCATION_3 + 1) * SPI_FLASH_SEC_SIZE, (uint32*)&_sysCfgH, sizeof(SYSCFGH));
|
||||
|
@ -287,6 +301,17 @@ void CFG_Load()
|
|||
} else {
|
||||
CFG_Default();
|
||||
}
|
||||
*/
|
||||
// Auto upgrade
|
||||
noInterrupts();
|
||||
spi_flash_read((CFG_LOCATION_3) * SPI_FLASH_SEC_SIZE, (uint32*)&sysCfg, sizeof(SYSCFG));
|
||||
spi_flash_read((CFG_LOCATION_3 + 1) * SPI_FLASH_SEC_SIZE, (uint32*)&_sysCfgH, sizeof(SYSCFGH));
|
||||
if (sysCfg.saveFlag < _sysCfgH.saveFlag)
|
||||
spi_flash_read((CFG_LOCATION_3 + 1) * SPI_FLASH_SEC_SIZE, (uint32*)&sysCfg, sizeof(SYSCFG));
|
||||
interrupts();
|
||||
if ((sysCfg.cfg_holder != CFG_HOLDER) || (sysCfg.version >= 0x04020000)) {
|
||||
CFG_Default();
|
||||
}
|
||||
}
|
||||
|
||||
_cfgHash = getHash();
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
- Select IDE Tools - Flash size: "1M (no SPIFFS)"
|
||||
====================================================*/
|
||||
|
||||
#define VERSION 0x05020200 // 5.2.2
|
||||
#define VERSION 0x05020300 // 5.2.3
|
||||
|
||||
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};
|
||||
|
@ -230,6 +230,7 @@ char Version[16]; // Version string from VERSION define
|
|||
char Hostname[33]; // Composed Wifi hostname
|
||||
char MQTTClient[33]; // Composed MQTT Clientname
|
||||
uint8_t mqttcounter = 0; // MQTT connection retry counter
|
||||
uint8_t fallbacktopic = 0; // Use Topic or FallbackTopic
|
||||
unsigned long timerxs = 0; // State loop timer
|
||||
int state = 0; // State per second flag
|
||||
int mqttflag = 2; // MQTT connection messages flag
|
||||
|
@ -328,19 +329,26 @@ void getClient(char* output, const char* input, byte size)
|
|||
void getTopic_P(char *stopic, byte prefix, char *topic, const char* subtopic)
|
||||
{
|
||||
char romram[CMDSZ];
|
||||
String fulltopic;
|
||||
|
||||
snprintf_P(romram, sizeof(romram), subtopic);
|
||||
String fulltopic = sysCfg.mqtt_fulltopic;
|
||||
if ((0 == prefix) && (-1 == fulltopic.indexOf(F(MQTT_TOKEN_PREFIX)))) {
|
||||
fulltopic += F("/" MQTT_TOKEN_PREFIX); // Need prefix for commands to handle mqtt topic loops
|
||||
}
|
||||
for (byte i = 0; i < 3; i++) {
|
||||
if ('\0' == sysCfg.mqtt_prefix[i][0]) {
|
||||
snprintf_P(sysCfg.mqtt_prefix[i], sizeof(sysCfg.mqtt_prefix[i]), PREFIXES[i]);
|
||||
if (fallbacktopic) {
|
||||
fulltopic = FPSTR(PREFIXES[prefix]);
|
||||
fulltopic += F("/");
|
||||
fulltopic += MQTTClient;
|
||||
} else {
|
||||
fulltopic = sysCfg.mqtt_fulltopic;
|
||||
if ((0 == prefix) && (-1 == fulltopic.indexOf(F(MQTT_TOKEN_PREFIX)))) {
|
||||
fulltopic += F("/" MQTT_TOKEN_PREFIX); // Need prefix for commands to handle mqtt topic loops
|
||||
}
|
||||
for (byte i = 0; i < 3; i++) {
|
||||
if ('\0' == sysCfg.mqtt_prefix[i][0]) {
|
||||
snprintf_P(sysCfg.mqtt_prefix[i], sizeof(sysCfg.mqtt_prefix[i]), PREFIXES[i]);
|
||||
}
|
||||
}
|
||||
fulltopic.replace(F(MQTT_TOKEN_PREFIX), sysCfg.mqtt_prefix[prefix]);
|
||||
fulltopic.replace(F(MQTT_TOKEN_TOPIC), topic);
|
||||
}
|
||||
fulltopic.replace(F(MQTT_TOKEN_PREFIX), sysCfg.mqtt_prefix[prefix]);
|
||||
fulltopic.replace(F(MQTT_TOKEN_TOPIC), topic);
|
||||
fulltopic.replace(F("#"), "");
|
||||
fulltopic.replace(F("//"), "/");
|
||||
if (!fulltopic.endsWith("/")) {
|
||||
|
@ -536,7 +544,9 @@ void mqtt_connected()
|
|||
getTopic_P(stopic, 0, sysCfg.mqtt_grptopic, PSTR("#"));
|
||||
mqttClient.subscribe(stopic);
|
||||
mqttClient.loop(); // Solve LmacRxBlk:1 messages
|
||||
fallbacktopic = 1;
|
||||
getTopic_P(stopic, 0, MQTTClient, PSTR("#"));
|
||||
fallbacktopic = 0;
|
||||
mqttClient.subscribe(stopic);
|
||||
mqttClient.loop(); // Solve LmacRxBlk:1 messages
|
||||
}
|
||||
|
@ -883,6 +893,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
|
|||
#endif // USE_DOMOTICZ
|
||||
|
||||
grpflg = (strstr(topicBuf, sysCfg.mqtt_grptopic) != NULL);
|
||||
fallbacktopic = (strstr(topicBuf, MQTTClient) != NULL);
|
||||
type = strrchr(topicBuf, '/') +1; // Last part of received topic is always the command (type)
|
||||
|
||||
index = 1;
|
||||
|
@ -948,6 +959,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
|
|||
payload = 9;
|
||||
}
|
||||
do_cmnd_power(index, payload);
|
||||
fallbacktopic = 0;
|
||||
return;
|
||||
}
|
||||
else if (!strcmp_P(type,PSTR("STATUS"))) {
|
||||
|
@ -955,6 +967,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
|
|||
payload = 99;
|
||||
}
|
||||
publish_status(payload);
|
||||
fallbacktopic = 0;
|
||||
return;
|
||||
}
|
||||
else if ((sysCfg.module != MOTOR) && !strcmp_P(type,PSTR("POWERONSTATE"))) {
|
||||
|
@ -1035,7 +1048,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
|
|||
}
|
||||
if (12 == index) { // stop_flash_rotate
|
||||
stop_flash_rotate = payload;
|
||||
CFG_Save(stop_flash_rotate);
|
||||
CFG_Save(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1275,11 +1288,15 @@ 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 (1 == payload) {
|
||||
// Check if the payload is numerically 1, and had no trailing chars.
|
||||
// e.g. "1foo" or "1.2.3" could fool us.
|
||||
// Check if the version we have been asked to upgrade to is higher than our current version.
|
||||
// We also need at least 3 chars to make a valid version number string.
|
||||
if (((1 == data_len) && (1 == payload)) || ((data_len >= 3) && newerVersion(dataBuf))) {
|
||||
otaflag = 3;
|
||||
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Upgrade\":\"Version %s from %s\"}"), Version, sysCfg.otaUrl);
|
||||
} else {
|
||||
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Upgrade\":\"Option 1 to upgrade\"}"));
|
||||
snprintf_P(svalue, sizeof(svalue), PSTR("{\"Upgrade\":\"Option 1 or >%s to upgrade\"}"), Version);
|
||||
}
|
||||
}
|
||||
else if (!strcmp_P(type,PSTR("OTAURL"))) {
|
||||
|
@ -1573,6 +1590,7 @@ void mqttDataCb(char* topic, byte* data, unsigned int data_len)
|
|||
if (svalue[0] != '\0') {
|
||||
mqtt_publish_topic_P(5, type, svalue);
|
||||
}
|
||||
fallbacktopic = 0;
|
||||
}
|
||||
|
||||
/********************************************************************************************/
|
||||
|
|
|
@ -189,6 +189,50 @@ void mqttfy(byte option, char* str)
|
|||
}
|
||||
}
|
||||
|
||||
// Function to parse & check if version_str is newer than our currently installed version.
|
||||
bool newerVersion(char* version_str)
|
||||
{
|
||||
uint32_t version = 0;
|
||||
uint8_t i = 0;
|
||||
char *str_ptr;
|
||||
char* version_dup = strdup(version_str); // Duplicate the version_str as strtok_r will modify it.
|
||||
|
||||
if (!version_dup) {
|
||||
return false; // Bail if we can't duplicate. Assume bad.
|
||||
}
|
||||
// Loop through the version string, splitting on '.' seperators.
|
||||
for (char *str = strtok_r(version_dup, ".", &str_ptr); str && i < sizeof(VERSION); str = strtok_r(NULL, ".", &str_ptr), i++) {
|
||||
int field = atoi(str);
|
||||
// The fields in a version string can only range from 0-255.
|
||||
if ((field < 0) || (field > 255)) {
|
||||
free(version_dup);
|
||||
return false;
|
||||
}
|
||||
// Shuffle the accumulated bytes across, and add the new byte.
|
||||
version = (version << 8) + field;
|
||||
// Check alpha delimiter after 1.2.3 only
|
||||
if ((2 == i) && isalpha(str[strlen(str)-1])) {
|
||||
field = str[strlen(str)-1] & 0x1f;
|
||||
version = (version << 8) + field;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
free(version_dup); // We no longer need this.
|
||||
// A version string should have 2-4 fields. e.g. 1.2, 1.2.3, or 1.2.3a (= 1.2.3.1).
|
||||
// If not, then don't consider it a valid version string.
|
||||
if ((i < 2) || (i > sizeof(VERSION))) {
|
||||
return false;
|
||||
}
|
||||
// Keep shifting the parsed version until we hit the maximum number of tokens.
|
||||
// VERSION stores the major number of the version in the most significant byte of the uint32_t.
|
||||
while (i < sizeof(VERSION)) {
|
||||
version <<= 8;
|
||||
i++;
|
||||
}
|
||||
// Now we should have a fully constructed version number in uint32_t form.
|
||||
return (version > VERSION);
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Wifi
|
||||
\*********************************************************************************************/
|
||||
|
|
|
@ -152,19 +152,15 @@ boolean sl_command(char *type, uint16_t index, char *dataBufUc, uint16_t data_le
|
|||
{
|
||||
boolean serviced = true;
|
||||
boolean coldim = false;
|
||||
char *p;
|
||||
|
||||
if (!strcmp_P(type,PSTR("COLOR"))) {
|
||||
uint8_t my_color[5];
|
||||
uint8_t my_color[2];
|
||||
char *p;
|
||||
if (4 == data_len) {
|
||||
char ccold[3], cwarm[3];
|
||||
memcpy(ccold, dataBufUc, 2);
|
||||
ccold[2] = '\0';
|
||||
memcpy(cwarm, dataBufUc + 2, 2);
|
||||
cwarm[2] = '\0';
|
||||
my_color[0] = strtol(ccold, &p, 16);
|
||||
my_color[1] = strtol(cwarm, &p, 16);
|
||||
uint16_t temp = my_color[0];
|
||||
uint16_t temp = strtol(dataBufUc, &p, 16);
|
||||
my_color[1] = temp & 0xFF; // Warm
|
||||
temp >>= 8;
|
||||
my_color[0] = temp & 0xFF; // Cold
|
||||
if (temp < my_color[1]) {
|
||||
temp = my_color[1];
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue