mirror of https://github.com/arendst/Tasmota.git
parent
42cb47de92
commit
0017a6304a
|
@ -152,6 +152,7 @@ People helping to keep the show on the road:
|
||||||
- Raymond Mouthaan for managing Wemos Wiki information
|
- Raymond Mouthaan for managing Wemos Wiki information
|
||||||
- Norbert Richter for his decode-config.py tool
|
- Norbert Richter for his decode-config.py tool
|
||||||
- Andre Thomas for providing [thehackbox](http://thehackbox.org/tasmota/) OTA support and daily development builds
|
- Andre Thomas for providing [thehackbox](http://thehackbox.org/tasmota/) OTA support and daily development builds
|
||||||
|
- Joel Stein and digiblur for their Tuya research and driver
|
||||||
- Frogmore42 and Jason2866 for providing many issue answers
|
- Frogmore42 and Jason2866 for providing many issue answers
|
||||||
- Many more providing Tips, Pocs or PRs
|
- Many more providing Tips, Pocs or PRs
|
||||||
|
|
||||||
|
|
|
@ -125,6 +125,7 @@ Version 6.3.0 20181030
|
||||||
* Change energy monitoring using energy sensor driver modules
|
* Change energy monitoring using energy sensor driver modules
|
||||||
* Change Webserver page handler for easier extension (thx to Adrian Scillato)
|
* Change Webserver page handler for easier extension (thx to Adrian Scillato)
|
||||||
* Change pinmode for no-pullup defined switches to pullup when configured as switchmode PUSHBUTTON (=3 and up) (#3896)
|
* Change pinmode for no-pullup defined switches to pullup when configured as switchmode PUSHBUTTON (=3 and up) (#3896)
|
||||||
|
* Change default OTA Url to http://thehackbox.org/tasmota/release/sonoff.bin (#4170)
|
||||||
* Remove support for MQTT Client esp-mqtt-arduino by #define MQTT_LIBRARY_TYPE MQTT_ESPMQTTARDUINO
|
* Remove support for MQTT Client esp-mqtt-arduino by #define MQTT_LIBRARY_TYPE MQTT_ESPMQTTARDUINO
|
||||||
* Remove commands PowerCal, VoltageCal and CurrentCal as more functionality is provided by commands PowerSet, VoltageSet and CurrentSet
|
* Remove commands PowerCal, VoltageCal and CurrentCal as more functionality is provided by commands PowerSet, VoltageSet and CurrentSet
|
||||||
* Remove restart after ntpserver change and force NTP re-sync (#3890)
|
* Remove restart after ntpserver change and force NTP re-sync (#3890)
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
* Change energy monitoring using energy sensor driver modules
|
* Change energy monitoring using energy sensor driver modules
|
||||||
* Change Webserver page handler for easier extension (thx to Adrian Scillato)
|
* Change Webserver page handler for easier extension (thx to Adrian Scillato)
|
||||||
* Change pinmode for no-pullup defined switches to pullup when configured as switchmode PUSHBUTTON (=3 and up) (#3896)
|
* Change pinmode for no-pullup defined switches to pullup when configured as switchmode PUSHBUTTON (=3 and up) (#3896)
|
||||||
|
* Change default OTA Url to http://thehackbox.org/tasmota/release/sonoff.bin (#4170)
|
||||||
* Remove support for MQTT Client esp-mqtt-arduino by #define MQTT_LIBRARY_TYPE MQTT_ESPMQTTARDUINO
|
* Remove support for MQTT Client esp-mqtt-arduino by #define MQTT_LIBRARY_TYPE MQTT_ESPMQTTARDUINO
|
||||||
* Remove commands PowerCal, VoltageCal and CurrentCal as more functionality is provided by commands PowerSet, VoltageSet and CurrentSet
|
* Remove commands PowerCal, VoltageCal and CurrentCal as more functionality is provided by commands PowerSet, VoltageSet and CurrentSet
|
||||||
* Remove restart after ntpserver change and force NTP re-sync (#3890)
|
* Remove restart after ntpserver change and force NTP re-sync (#3890)
|
||||||
|
|
|
@ -527,6 +527,8 @@
|
||||||
#define D_SENSOR_TX20_TX "TX20"
|
#define D_SENSOR_TX20_TX "TX20"
|
||||||
#define D_SENSOR_RFSEND "RFSend"
|
#define D_SENSOR_RFSEND "RFSend"
|
||||||
#define D_SENSOR_RFRECV "RFrecv"
|
#define D_SENSOR_RFRECV "RFrecv"
|
||||||
|
#define D_SENSOR_TUYA_TX "Tuya Tx"
|
||||||
|
#define D_SENSOR_TUYA_RX "Tuya Rx"
|
||||||
|
|
||||||
// Units
|
// Units
|
||||||
#define D_UNIT_AMPERE "A"
|
#define D_UNIT_AMPERE "A"
|
||||||
|
|
|
@ -527,6 +527,8 @@
|
||||||
#define D_SENSOR_TX20_TX "TX20"
|
#define D_SENSOR_TX20_TX "TX20"
|
||||||
#define D_SENSOR_RFSEND "RFSend"
|
#define D_SENSOR_RFSEND "RFSend"
|
||||||
#define D_SENSOR_RFRECV "RFrecv"
|
#define D_SENSOR_RFRECV "RFrecv"
|
||||||
|
#define D_SENSOR_TUYA_TX "Tuya Tx"
|
||||||
|
#define D_SENSOR_TUYA_RX "Tuya Rx"
|
||||||
|
|
||||||
// Units
|
// Units
|
||||||
#define D_UNIT_AMPERE "A"
|
#define D_UNIT_AMPERE "A"
|
||||||
|
|
|
@ -527,6 +527,8 @@
|
||||||
#define D_SENSOR_TX20_TX "TX20"
|
#define D_SENSOR_TX20_TX "TX20"
|
||||||
#define D_SENSOR_RFSEND "RFSend"
|
#define D_SENSOR_RFSEND "RFSend"
|
||||||
#define D_SENSOR_RFRECV "RFrecv"
|
#define D_SENSOR_RFRECV "RFrecv"
|
||||||
|
#define D_SENSOR_TUYA_TX "Tuya Tx"
|
||||||
|
#define D_SENSOR_TUYA_RX "Tuya Rx"
|
||||||
|
|
||||||
// Units
|
// Units
|
||||||
#define D_UNIT_AMPERE "A"
|
#define D_UNIT_AMPERE "A"
|
||||||
|
|
|
@ -527,6 +527,8 @@
|
||||||
#define D_SENSOR_TX20_TX "TX20"
|
#define D_SENSOR_TX20_TX "TX20"
|
||||||
#define D_SENSOR_RFSEND "RFSend"
|
#define D_SENSOR_RFSEND "RFSend"
|
||||||
#define D_SENSOR_RFRECV "RFrecv"
|
#define D_SENSOR_RFRECV "RFrecv"
|
||||||
|
#define D_SENSOR_TUYA_TX "Tuya Tx"
|
||||||
|
#define D_SENSOR_TUYA_RX "Tuya Rx"
|
||||||
|
|
||||||
// Units
|
// Units
|
||||||
#define D_UNIT_AMPERE "A"
|
#define D_UNIT_AMPERE "A"
|
||||||
|
|
|
@ -527,6 +527,8 @@
|
||||||
#define D_SENSOR_TX20_TX "TX20"
|
#define D_SENSOR_TX20_TX "TX20"
|
||||||
#define D_SENSOR_RFSEND "RFSend"
|
#define D_SENSOR_RFSEND "RFSend"
|
||||||
#define D_SENSOR_RFRECV "RFrecv"
|
#define D_SENSOR_RFRECV "RFrecv"
|
||||||
|
#define D_SENSOR_TUYA_TX "Tuya Tx"
|
||||||
|
#define D_SENSOR_TUYA_RX "Tuya Rx"
|
||||||
|
|
||||||
// Units
|
// Units
|
||||||
#define D_UNIT_AMPERE "A"
|
#define D_UNIT_AMPERE "A"
|
||||||
|
|
|
@ -527,6 +527,8 @@
|
||||||
#define D_SENSOR_TX20_TX "TX20"
|
#define D_SENSOR_TX20_TX "TX20"
|
||||||
#define D_SENSOR_RFSEND "RFSend"
|
#define D_SENSOR_RFSEND "RFSend"
|
||||||
#define D_SENSOR_RFRECV "RFrecv"
|
#define D_SENSOR_RFRECV "RFrecv"
|
||||||
|
#define D_SENSOR_TUYA_TX "Tuya Tx"
|
||||||
|
#define D_SENSOR_TUYA_RX "Tuya Rx"
|
||||||
|
|
||||||
// Units
|
// Units
|
||||||
#define D_UNIT_AMPERE "A"
|
#define D_UNIT_AMPERE "A"
|
||||||
|
|
|
@ -527,6 +527,8 @@
|
||||||
#define D_SENSOR_TX20_TX "TX20"
|
#define D_SENSOR_TX20_TX "TX20"
|
||||||
#define D_SENSOR_RFSEND "RFSend"
|
#define D_SENSOR_RFSEND "RFSend"
|
||||||
#define D_SENSOR_RFRECV "RFrecv"
|
#define D_SENSOR_RFRECV "RFrecv"
|
||||||
|
#define D_SENSOR_TUYA_TX "Tuya Tx"
|
||||||
|
#define D_SENSOR_TUYA_RX "Tuya Rx"
|
||||||
|
|
||||||
// Units
|
// Units
|
||||||
#define D_UNIT_AMPERE "A"
|
#define D_UNIT_AMPERE "A"
|
||||||
|
|
|
@ -527,6 +527,8 @@
|
||||||
#define D_SENSOR_TX20_TX "TX20"
|
#define D_SENSOR_TX20_TX "TX20"
|
||||||
#define D_SENSOR_RFSEND "RFSend"
|
#define D_SENSOR_RFSEND "RFSend"
|
||||||
#define D_SENSOR_RFRECV "RFrecv"
|
#define D_SENSOR_RFRECV "RFrecv"
|
||||||
|
#define D_SENSOR_TUYA_TX "Tuya Tx"
|
||||||
|
#define D_SENSOR_TUYA_RX "Tuya Rx"
|
||||||
|
|
||||||
// Units
|
// Units
|
||||||
#define D_UNIT_AMPERE "A"
|
#define D_UNIT_AMPERE "A"
|
||||||
|
|
|
@ -527,6 +527,8 @@
|
||||||
#define D_SENSOR_TX20_TX "TX20"
|
#define D_SENSOR_TX20_TX "TX20"
|
||||||
#define D_SENSOR_RFSEND "RFSend"
|
#define D_SENSOR_RFSEND "RFSend"
|
||||||
#define D_SENSOR_RFRECV "RFrecv"
|
#define D_SENSOR_RFRECV "RFrecv"
|
||||||
|
#define D_SENSOR_TUYA_TX "Tuya Tx"
|
||||||
|
#define D_SENSOR_TUYA_RX "Tuya Rx"
|
||||||
|
|
||||||
// Units
|
// Units
|
||||||
#define D_UNIT_AMPERE "A"
|
#define D_UNIT_AMPERE "A"
|
||||||
|
|
|
@ -527,6 +527,8 @@
|
||||||
#define D_SENSOR_TX20_TX "TX20"
|
#define D_SENSOR_TX20_TX "TX20"
|
||||||
#define D_SENSOR_RFSEND "RFSend"
|
#define D_SENSOR_RFSEND "RFSend"
|
||||||
#define D_SENSOR_RFRECV "RFrecv"
|
#define D_SENSOR_RFRECV "RFrecv"
|
||||||
|
#define D_SENSOR_TUYA_TX "Tuya Tx"
|
||||||
|
#define D_SENSOR_TUYA_RX "Tuya Rx"
|
||||||
|
|
||||||
// Units
|
// Units
|
||||||
#define D_UNIT_AMPERE "A"
|
#define D_UNIT_AMPERE "A"
|
||||||
|
|
|
@ -527,6 +527,8 @@
|
||||||
#define D_SENSOR_TX20_TX "TX20"
|
#define D_SENSOR_TX20_TX "TX20"
|
||||||
#define D_SENSOR_RFSEND "RFSend"
|
#define D_SENSOR_RFSEND "RFSend"
|
||||||
#define D_SENSOR_RFRECV "RFrecv"
|
#define D_SENSOR_RFRECV "RFrecv"
|
||||||
|
#define D_SENSOR_TUYA_TX "Tuya Tx"
|
||||||
|
#define D_SENSOR_TUYA_RX "Tuya Rx"
|
||||||
|
|
||||||
// Units
|
// Units
|
||||||
#define D_UNIT_AMPERE "A"
|
#define D_UNIT_AMPERE "A"
|
||||||
|
|
|
@ -527,6 +527,8 @@
|
||||||
#define D_SENSOR_TX20_TX "TX20"
|
#define D_SENSOR_TX20_TX "TX20"
|
||||||
#define D_SENSOR_RFSEND "RFSend"
|
#define D_SENSOR_RFSEND "RFSend"
|
||||||
#define D_SENSOR_RFRECV "RFrecv"
|
#define D_SENSOR_RFRECV "RFrecv"
|
||||||
|
#define D_SENSOR_TUYA_TX "Tuya Tx"
|
||||||
|
#define D_SENSOR_TUYA_RX "Tuya Rx"
|
||||||
|
|
||||||
// Units
|
// Units
|
||||||
#define D_UNIT_AMPERE "A"
|
#define D_UNIT_AMPERE "A"
|
||||||
|
|
|
@ -527,6 +527,8 @@
|
||||||
#define D_SENSOR_TX20_TX "TX20"
|
#define D_SENSOR_TX20_TX "TX20"
|
||||||
#define D_SENSOR_RFSEND "RFSend"
|
#define D_SENSOR_RFSEND "RFSend"
|
||||||
#define D_SENSOR_RFRECV "RFrecv"
|
#define D_SENSOR_RFRECV "RFrecv"
|
||||||
|
#define D_SENSOR_TUYA_TX "Tuya Tx"
|
||||||
|
#define D_SENSOR_TUYA_RX "Tuya Rx"
|
||||||
|
|
||||||
// Units
|
// Units
|
||||||
#define D_UNIT_AMPERE "A"
|
#define D_UNIT_AMPERE "A"
|
||||||
|
|
|
@ -527,6 +527,8 @@
|
||||||
#define D_SENSOR_TX20_TX "TX20"
|
#define D_SENSOR_TX20_TX "TX20"
|
||||||
#define D_SENSOR_RFSEND "RFSend"
|
#define D_SENSOR_RFSEND "RFSend"
|
||||||
#define D_SENSOR_RFRECV "RFrecv"
|
#define D_SENSOR_RFRECV "RFrecv"
|
||||||
|
#define D_SENSOR_TUYA_TX "Tuya Tx"
|
||||||
|
#define D_SENSOR_TUYA_RX "Tuya Rx"
|
||||||
|
|
||||||
// Units
|
// Units
|
||||||
#define D_UNIT_AMPERE "A"
|
#define D_UNIT_AMPERE "A"
|
||||||
|
|
|
@ -527,6 +527,8 @@
|
||||||
#define D_SENSOR_TX20_TX "TX20"
|
#define D_SENSOR_TX20_TX "TX20"
|
||||||
#define D_SENSOR_RFSEND "RFSend"
|
#define D_SENSOR_RFSEND "RFSend"
|
||||||
#define D_SENSOR_RFRECV "RFrecv"
|
#define D_SENSOR_RFRECV "RFrecv"
|
||||||
|
#define D_SENSOR_TUYA_TX "Tuya Tx"
|
||||||
|
#define D_SENSOR_TUYA_RX "Tuya Rx"
|
||||||
|
|
||||||
// Units
|
// Units
|
||||||
#define D_UNIT_AMPERE "А"
|
#define D_UNIT_AMPERE "А"
|
||||||
|
|
|
@ -527,6 +527,8 @@
|
||||||
#define D_SENSOR_TX20_TX "TX20"
|
#define D_SENSOR_TX20_TX "TX20"
|
||||||
#define D_SENSOR_RFSEND "RFSend"
|
#define D_SENSOR_RFSEND "RFSend"
|
||||||
#define D_SENSOR_RFRECV "RFrecv"
|
#define D_SENSOR_RFRECV "RFrecv"
|
||||||
|
#define D_SENSOR_TUYA_TX "Tuya Tx"
|
||||||
|
#define D_SENSOR_TUYA_RX "Tuya Rx"
|
||||||
|
|
||||||
// Units
|
// Units
|
||||||
#define D_UNIT_AMPERE "A"
|
#define D_UNIT_AMPERE "A"
|
||||||
|
|
|
@ -527,6 +527,8 @@
|
||||||
#define D_SENSOR_TX20_TX "TX20"
|
#define D_SENSOR_TX20_TX "TX20"
|
||||||
#define D_SENSOR_RFSEND "RFSend"
|
#define D_SENSOR_RFSEND "RFSend"
|
||||||
#define D_SENSOR_RFRECV "RFrecv"
|
#define D_SENSOR_RFRECV "RFrecv"
|
||||||
|
#define D_SENSOR_TUYA_TX "Tuya Tx"
|
||||||
|
#define D_SENSOR_TUYA_RX "Tuya Rx"
|
||||||
|
|
||||||
// Units
|
// Units
|
||||||
#define D_UNIT_AMPERE "А"
|
#define D_UNIT_AMPERE "А"
|
||||||
|
|
|
@ -527,6 +527,8 @@
|
||||||
#define D_SENSOR_TX20_TX "TX20"
|
#define D_SENSOR_TX20_TX "TX20"
|
||||||
#define D_SENSOR_RFSEND "RFSend"
|
#define D_SENSOR_RFSEND "RFSend"
|
||||||
#define D_SENSOR_RFRECV "RFrecv"
|
#define D_SENSOR_RFRECV "RFrecv"
|
||||||
|
#define D_SENSOR_TUYA_TX "Tuya Tx"
|
||||||
|
#define D_SENSOR_TUYA_RX "Tuya Rx"
|
||||||
|
|
||||||
// Units
|
// Units
|
||||||
#define D_UNIT_AMPERE "安"
|
#define D_UNIT_AMPERE "安"
|
||||||
|
|
|
@ -527,6 +527,8 @@
|
||||||
#define D_SENSOR_TX20_TX "TX20"
|
#define D_SENSOR_TX20_TX "TX20"
|
||||||
#define D_SENSOR_RFSEND "RFSend"
|
#define D_SENSOR_RFSEND "RFSend"
|
||||||
#define D_SENSOR_RFRECV "RFrecv"
|
#define D_SENSOR_RFRECV "RFrecv"
|
||||||
|
#define D_SENSOR_TUYA_TX "Tuya Tx"
|
||||||
|
#define D_SENSOR_TUYA_RX "Tuya Rx"
|
||||||
|
|
||||||
// Units
|
// Units
|
||||||
#define D_UNIT_AMPERE "安"
|
#define D_UNIT_AMPERE "安"
|
||||||
|
|
|
@ -79,7 +79,7 @@
|
||||||
#define WEB_LOG_LEVEL LOG_LEVEL_INFO // [WebLog] (LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE)
|
#define WEB_LOG_LEVEL LOG_LEVEL_INFO // [WebLog] (LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE)
|
||||||
|
|
||||||
// -- Ota -----------------------------------------
|
// -- Ota -----------------------------------------
|
||||||
#define OTA_URL "http://sonoff.maddox.co.uk/tasmota/sonoff.bin" // [OtaUrl]
|
#define OTA_URL "http://thehackbox.org/tasmota/release/sonoff.bin" // [OtaUrl]
|
||||||
|
|
||||||
// -- MQTT ----------------------------------------
|
// -- MQTT ----------------------------------------
|
||||||
#define MQTT_USE 1 // [SetOption3] Select default MQTT use (0 = Off, 1 = On)
|
#define MQTT_USE 1 // [SetOption3] Select default MQTT use (0 = Off, 1 = On)
|
||||||
|
|
|
@ -128,9 +128,11 @@ enum UserSelectablePins {
|
||||||
GPIO_SDS0X1_TX, // Nova Fitness SDS011 Serial interface
|
GPIO_SDS0X1_TX, // Nova Fitness SDS011 Serial interface
|
||||||
GPIO_HX711_SCK, // HX711 Load Cell clock
|
GPIO_HX711_SCK, // HX711 Load Cell clock
|
||||||
GPIO_HX711_DAT, // HX711 Load Cell data
|
GPIO_HX711_DAT, // HX711 Load Cell data
|
||||||
GPIO_TX20_TXD_BLACK, // TX20 Transmission Pin
|
GPIO_TX20_TXD_BLACK, // TX20 Transmission Pin
|
||||||
GPIO_RFSEND, // RF transmitter
|
GPIO_RFSEND, // RF transmitter
|
||||||
GPIO_RFRECV, // RF receiver
|
GPIO_RFRECV, // RF receiver
|
||||||
|
GPIO_TUYA_TX, // Tuya Serial interface
|
||||||
|
GPIO_TUYA_RX, // Tuya Serial interface
|
||||||
GPIO_SENSOR_END };
|
GPIO_SENSOR_END };
|
||||||
|
|
||||||
// Programmer selectable GPIO functionality offset by user selectable GPIOs
|
// Programmer selectable GPIO functionality offset by user selectable GPIOs
|
||||||
|
@ -187,7 +189,8 @@ const char kSensorNames[] PROGMEM =
|
||||||
D_SENSOR_DFR562 "|" D_SENSOR_SDS0X1_TX "|"
|
D_SENSOR_DFR562 "|" D_SENSOR_SDS0X1_TX "|"
|
||||||
D_SENSOR_HX711_SCK "|" D_SENSOR_HX711_DAT "|"
|
D_SENSOR_HX711_SCK "|" D_SENSOR_HX711_DAT "|"
|
||||||
D_SENSOR_TX20_TX "|"
|
D_SENSOR_TX20_TX "|"
|
||||||
D_SENSOR_RFSEND "|" D_SENSOR_RFRECV;
|
D_SENSOR_RFSEND "|" D_SENSOR_RFRECV "|"
|
||||||
|
D_SENSOR_TUYA_TX "|" D_SENSOR_TUYA_RX;
|
||||||
|
|
||||||
/********************************************************************************************/
|
/********************************************************************************************/
|
||||||
|
|
||||||
|
@ -371,7 +374,9 @@ const uint8_t kGpioNiceList[GPIO_SENSOR_END] PROGMEM = {
|
||||||
GPIO_SDM630_RX, // SDM630 Serial interface
|
GPIO_SDM630_RX, // SDM630 Serial interface
|
||||||
GPIO_PMS5003, // Plantower PMS5003 Serial interface
|
GPIO_PMS5003, // Plantower PMS5003 Serial interface
|
||||||
GPIO_TX20_TXD_BLACK, // TX20 Transmission Pin
|
GPIO_TX20_TXD_BLACK, // TX20 Transmission Pin
|
||||||
GPIO_MP3_DFR562 // RB-DFR-562, DFPlayer Mini MP3 Player Serial interface
|
GPIO_MP3_DFR562, // RB-DFR-562, DFPlayer Mini MP3 Player Serial interface
|
||||||
|
GPIO_TUYA_TX, // Tuya Serial interface
|
||||||
|
GPIO_TUYA_RX // Tuya Serial interface
|
||||||
};
|
};
|
||||||
|
|
||||||
const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = {
|
const uint8_t kModuleNiceList[MAXMODULE] PROGMEM = {
|
||||||
|
@ -1150,9 +1155,9 @@ const mytmplt kModules[MAXMODULE] PROGMEM = {
|
||||||
{ "Tuya Dimmer", // Tuya Dimmer (ESP8266 w/ separate MCU dimmer)
|
{ "Tuya Dimmer", // Tuya Dimmer (ESP8266 w/ separate MCU dimmer)
|
||||||
// https://www.amazon.com/gp/product/B07CTNSZZ8/ref=oh_aui_detailpage_o00_s00?ie=UTF8&psc=1
|
// https://www.amazon.com/gp/product/B07CTNSZZ8/ref=oh_aui_detailpage_o00_s00?ie=UTF8&psc=1
|
||||||
GPIO_KEY1, // Virtual Button (controlled by MCU)
|
GPIO_KEY1, // Virtual Button (controlled by MCU)
|
||||||
GPIO_TXD, // GPIO01 MCU serial control
|
GPIO_USER, // GPIO01 MCU serial control
|
||||||
GPIO_USER,
|
GPIO_USER,
|
||||||
GPIO_RXD, // GPIO03 MCU serial control
|
GPIO_USER, // GPIO03 MCU serial control
|
||||||
GPIO_USER,
|
GPIO_USER,
|
||||||
GPIO_USER,
|
GPIO_USER,
|
||||||
0, 0, 0, 0, 0, 0, // Flash connection
|
0, 0, 0, 0, 0, 0, // Flash connection
|
||||||
|
|
|
@ -20,8 +20,13 @@
|
||||||
#ifdef USE_TUYA_DIMMER
|
#ifdef USE_TUYA_DIMMER
|
||||||
|
|
||||||
#ifndef TUYA_DIMMER_ID
|
#ifndef TUYA_DIMMER_ID
|
||||||
#define TUYA_DIMMER_ID 3
|
#define TUYA_DIMMER_ID 3
|
||||||
#endif
|
#endif
|
||||||
|
#define TUYA_BUFFER_SIZE 256
|
||||||
|
|
||||||
|
#include <TasmotaSerial.h>
|
||||||
|
|
||||||
|
TasmotaSerial *TuyaSerial = nullptr;
|
||||||
|
|
||||||
uint8_t tuya_new_dim = 0; // Tuya dimmer value temp
|
uint8_t tuya_new_dim = 0; // Tuya dimmer value temp
|
||||||
boolean tuya_ignore_dim = false; // Flag to skip serial send to prevent looping when processing inbound states from the faceplate interaction
|
boolean tuya_ignore_dim = false; // Flag to skip serial send to prevent looping when processing inbound states from the faceplate interaction
|
||||||
|
@ -29,6 +34,9 @@ uint8_t tuya_cmd_status = 0; // Current status of serial-read
|
||||||
uint8_t tuya_cmd_checksum = 0; // Checksum of tuya command
|
uint8_t tuya_cmd_checksum = 0; // Checksum of tuya command
|
||||||
uint8_t tuya_data_len = 0; // Data lenght of command
|
uint8_t tuya_data_len = 0; // Data lenght of command
|
||||||
|
|
||||||
|
char tuya_buffer[TUYA_BUFFER_SIZE]; // Serial receive buffer
|
||||||
|
int tuya_byte_counter = 0; // Index in serial receive buffer
|
||||||
|
|
||||||
boolean TuyaSetPower()
|
boolean TuyaSetPower()
|
||||||
{
|
{
|
||||||
boolean status = false;
|
boolean status = false;
|
||||||
|
@ -36,24 +44,24 @@ boolean TuyaSetPower()
|
||||||
uint8_t rpower = XdrvMailbox.index;
|
uint8_t rpower = XdrvMailbox.index;
|
||||||
int16_t source = XdrvMailbox.payload;
|
int16_t source = XdrvMailbox.payload;
|
||||||
|
|
||||||
if (source != SRC_SWITCH ) { // ignore to prevent loop from pushing state from faceplate interaction
|
if (source != SRC_SWITCH && TuyaSerial) { // ignore to prevent loop from pushing state from faceplate interaction
|
||||||
|
|
||||||
snprintf_P(log_data, sizeof(log_data), PSTR("TYA: SetDevicePower.rpower=%d"), rpower);
|
snprintf_P(log_data, sizeof(log_data), PSTR("TYA: SetDevicePower.rpower=%d"), rpower);
|
||||||
AddLog(LOG_LEVEL_DEBUG);
|
AddLog(LOG_LEVEL_DEBUG);
|
||||||
|
|
||||||
Serial.write(0x55); // Tuya header 55AA
|
TuyaSerial->write((uint8_t)0x55); // Tuya header 55AA
|
||||||
Serial.write(0xAA);
|
TuyaSerial->write((uint8_t)0xAA);
|
||||||
Serial.write(0x00); // version 00
|
TuyaSerial->write((uint8_t)0x00); // version 00
|
||||||
Serial.write(0x06); // Tuya command 06
|
TuyaSerial->write((uint8_t)0x06); // Tuya command 06
|
||||||
Serial.write(0x00);
|
TuyaSerial->write((uint8_t)0x00);
|
||||||
Serial.write(0x05); // following data length 0x05
|
TuyaSerial->write((uint8_t)0x05); // following data length 0x05
|
||||||
Serial.write(0x01); // relay number 1,2,3
|
TuyaSerial->write((uint8_t)0x01); // relay number 1,2,3
|
||||||
Serial.write(0x01);
|
TuyaSerial->write((uint8_t)0x01);
|
||||||
Serial.write(0x00);
|
TuyaSerial->write((uint8_t)0x00);
|
||||||
Serial.write(0x01);
|
TuyaSerial->write((uint8_t)0x01);
|
||||||
Serial.write(rpower); // status
|
TuyaSerial->write((uint8_t)rpower); // status
|
||||||
Serial.write(0x0D + rpower); // checksum sum of all bytes in packet mod 256
|
TuyaSerial->write((uint8_t)0x0D + rpower); // checksum sum of all bytes in packet mod 256
|
||||||
Serial.flush();
|
TuyaSerial->flush();
|
||||||
|
|
||||||
status = true;
|
status = true;
|
||||||
}
|
}
|
||||||
|
@ -62,26 +70,26 @@ boolean TuyaSetPower()
|
||||||
|
|
||||||
void LightSerialDuty(uint8_t duty)
|
void LightSerialDuty(uint8_t duty)
|
||||||
{
|
{
|
||||||
if (duty > 0 && !tuya_ignore_dim ) {
|
if (duty > 0 && !tuya_ignore_dim && TuyaSerial) {
|
||||||
if (duty < 25) {
|
if (duty < 25) {
|
||||||
duty = 25; // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself
|
duty = 25; // dimming acts odd below 25(10%) - this mirrors the threshold set on the faceplate itself
|
||||||
}
|
}
|
||||||
Serial.write(0x55); // Tuya header 55AA
|
TuyaSerial->write((uint8_t)0x55); // Tuya header 55AA
|
||||||
Serial.write(0xAA);
|
TuyaSerial->write((uint8_t)0xAA);
|
||||||
Serial.write(0x00); // version 00
|
TuyaSerial->write((uint8_t)0x00); // version 00
|
||||||
Serial.write(0x06); // Tuya command 06 - send order
|
TuyaSerial->write((uint8_t)0x06); // Tuya command 06 - send order
|
||||||
Serial.write(0x00);
|
TuyaSerial->write((uint8_t)0x00);
|
||||||
Serial.write(0x08); // following data length 0x08
|
TuyaSerial->write((uint8_t)0x08); // following data length 0x08
|
||||||
Serial.write(Settings.param[P_TUYA_DIMMER_ID]); // dimmer id
|
TuyaSerial->write((uint8_t)Settings.param[P_TUYA_DIMMER_ID]); // dimmer id
|
||||||
Serial.write(0x02); // type=value
|
TuyaSerial->write((uint8_t)0x02); // type=value
|
||||||
Serial.write(0x00); // length hi
|
TuyaSerial->write((uint8_t)0x00); // length hi
|
||||||
Serial.write(0x04); // length low
|
TuyaSerial->write((uint8_t)0x04); // length low
|
||||||
Serial.write(0x00); //
|
TuyaSerial->write((uint8_t)0x00); //
|
||||||
Serial.write(0x00); //
|
TuyaSerial->write((uint8_t)0x00); //
|
||||||
Serial.write(0x00); //
|
TuyaSerial->write((uint8_t)0x00); //
|
||||||
Serial.write( duty ); // dim value (0-255)
|
TuyaSerial->write((uint8_t) duty ); // dim value (0-255)
|
||||||
Serial.write( byte(Settings.param[P_TUYA_DIMMER_ID] + 19 + duty) ); // checksum:sum of all bytes in packet mod 256
|
TuyaSerial->write((uint8_t) byte(Settings.param[P_TUYA_DIMMER_ID] + 19 + duty) ); // checksum:sum of all bytes in packet mod 256
|
||||||
Serial.flush();
|
TuyaSerial->flush();
|
||||||
|
|
||||||
snprintf_P(log_data, sizeof(log_data), PSTR( "TYA: Send Serial Packet Dim Value=%d (id=%d)"), duty, Settings.param[P_TUYA_DIMMER_ID]);
|
snprintf_P(log_data, sizeof(log_data), PSTR( "TYA: Send Serial Packet Dim Value=%d (id=%d)"), duty, Settings.param[P_TUYA_DIMMER_ID]);
|
||||||
AddLog(LOG_LEVEL_DEBUG);
|
AddLog(LOG_LEVEL_DEBUG);
|
||||||
|
@ -99,27 +107,27 @@ void TuyaPacketProcess()
|
||||||
{
|
{
|
||||||
char scmnd[20];
|
char scmnd[20];
|
||||||
|
|
||||||
snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Packet Size=%d"), serial_in_byte_counter);
|
snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Packet Size=%d"), tuya_byte_counter);
|
||||||
AddLog(LOG_LEVEL_DEBUG);
|
AddLog(LOG_LEVEL_DEBUG);
|
||||||
|
|
||||||
if (serial_in_byte_counter == 7 && serial_in_buffer[3] == 14 ) { // heartbeat packet
|
if (tuya_byte_counter == 7 && tuya_buffer[3] == 14 ) { // heartbeat packet
|
||||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Heartbeat"));
|
AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: Heartbeat"));
|
||||||
}
|
}
|
||||||
else if (serial_in_byte_counter == 12 && serial_in_buffer[3] == 7 && serial_in_buffer[5] == 5) { // on/off packet
|
else if (tuya_byte_counter == 12 && tuya_buffer[3] == 7 && tuya_buffer[5] == 5) { // on/off packet
|
||||||
|
|
||||||
snprintf_P(log_data, sizeof(log_data),PSTR("TYA: Rcvd - %s State"),serial_in_buffer[10]?"On":"Off");
|
snprintf_P(log_data, sizeof(log_data),PSTR("TYA: Rcvd - %s State"),tuya_buffer[10]?"On":"Off");
|
||||||
AddLog(LOG_LEVEL_DEBUG);
|
AddLog(LOG_LEVEL_DEBUG);
|
||||||
|
|
||||||
if((power || Settings.light_dimmer > 0) && (power != serial_in_buffer[10])) {
|
if((power || Settings.light_dimmer > 0) && (power != tuya_buffer[10])) {
|
||||||
ExecuteCommandPower(1, serial_in_buffer[10], SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction
|
ExecuteCommandPower(1, tuya_buffer[10], SRC_SWITCH); // send SRC_SWITCH? to use as flag to prevent loop from inbound states from faceplate interaction
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (serial_in_byte_counter == 15 && serial_in_buffer[3] == 7 && serial_in_buffer[5] == 8) { // dim packet
|
else if (tuya_byte_counter == 15 && tuya_buffer[3] == 7 && tuya_buffer[5] == 8) { // dim packet
|
||||||
|
|
||||||
snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Rcvd Dim State=%d"), serial_in_buffer[13]);
|
snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Rcvd Dim State=%d"), tuya_buffer[13]);
|
||||||
AddLog(LOG_LEVEL_DEBUG);
|
AddLog(LOG_LEVEL_DEBUG);
|
||||||
|
|
||||||
tuya_new_dim = round(serial_in_buffer[13] * (100. / 255.));
|
tuya_new_dim = round(tuya_buffer[13] * (100. / 255.));
|
||||||
if((power) && (tuya_new_dim > 0) && (abs(tuya_new_dim - Settings.light_dimmer) > 2)) {
|
if((power) && (tuya_new_dim > 0) && (abs(tuya_new_dim - Settings.light_dimmer) > 2)) {
|
||||||
|
|
||||||
snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Send CMND_DIMMER=%d"), tuya_new_dim );
|
snprintf_P(log_data, sizeof(log_data), PSTR("TYA: Send CMND_DIMMER=%d"), tuya_new_dim );
|
||||||
|
@ -134,7 +142,7 @@ void TuyaPacketProcess()
|
||||||
ExecuteCommand(scmnd, SRC_SWITCH);
|
ExecuteCommand(scmnd, SRC_SWITCH);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (serial_in_byte_counter == 8 && serial_in_buffer[3] == 5 && serial_in_buffer[5] == 1 && serial_in_buffer[7] == 5 ) { // reset WiFi settings packet - to do: reset red MCU LED after WiFi is up
|
else if (tuya_byte_counter == 8 && tuya_buffer[3] == 5 && tuya_buffer[5] == 1 && tuya_buffer[7] == 5 ) { // reset WiFi settings packet - to do: reset red MCU LED after WiFi is up
|
||||||
|
|
||||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: WiFi Reset Rcvd"));
|
AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: WiFi Reset Rcvd"));
|
||||||
|
|
||||||
|
@ -145,16 +153,16 @@ void TuyaPacketProcess()
|
||||||
|
|
||||||
void TuyaSerialInput()
|
void TuyaSerialInput()
|
||||||
{
|
{
|
||||||
while (Serial.available()) {
|
while (TuyaSerial->available()) {
|
||||||
yield();
|
yield();
|
||||||
serial_in_byte = Serial.read();
|
byte serial_in_byte = TuyaSerial->read();
|
||||||
|
|
||||||
//snprintf_P(log_data, sizeof(log_data), PSTR("TYA: serial_in_byte %d, tuya_cmd_status %d, tuya_cmd_checksum %d, tuya_data_len %d, serial_in_byte_counter %d"), serial_in_byte, tuya_cmd_status, tuya_cmd_checksum, tuya_data_len, serial_in_byte_counter);
|
//snprintf_P(log_data, sizeof(log_data), PSTR("TYA: serial_in_byte %d, tuya_cmd_status %d, tuya_cmd_checksum %d, tuya_data_len %d, tuya_byte_counter %d"), serial_in_byte, tuya_cmd_status, tuya_cmd_checksum, tuya_data_len, tuya_byte_counter);
|
||||||
//AddLog(LOG_LEVEL_DEBUG);
|
//AddLog(LOG_LEVEL_DEBUG);
|
||||||
|
|
||||||
if (serial_in_byte == 0x55) { // Start TUYA Packet
|
if (serial_in_byte == 0x55) { // Start TUYA Packet
|
||||||
tuya_cmd_status = 1;
|
tuya_cmd_status = 1;
|
||||||
serial_in_buffer[serial_in_byte_counter++] = serial_in_byte;
|
tuya_buffer[tuya_byte_counter++] = serial_in_byte;
|
||||||
tuya_cmd_checksum += serial_in_byte;
|
tuya_cmd_checksum += serial_in_byte;
|
||||||
}
|
}
|
||||||
else if (tuya_cmd_status == 1 && serial_in_byte == 0xAA){ // Only packtes with header 0x55AA are valid
|
else if (tuya_cmd_status == 1 && serial_in_byte == 0xAA){ // Only packtes with header 0x55AA are valid
|
||||||
|
@ -162,40 +170,40 @@ void TuyaSerialInput()
|
||||||
|
|
||||||
AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: 0x55AA Packet Start"));
|
AddLog_P(LOG_LEVEL_DEBUG, PSTR("TYA: 0x55AA Packet Start"));
|
||||||
|
|
||||||
serial_in_byte_counter = 0;
|
tuya_byte_counter = 0;
|
||||||
serial_in_buffer[serial_in_byte_counter++] = 0x55;
|
tuya_buffer[tuya_byte_counter++] = 0x55;
|
||||||
serial_in_buffer[serial_in_byte_counter++] = 0xAA;
|
tuya_buffer[tuya_byte_counter++] = 0xAA;
|
||||||
tuya_cmd_checksum = 0xFF;
|
tuya_cmd_checksum = 0xFF;
|
||||||
}
|
}
|
||||||
else if (tuya_cmd_status == 2){
|
else if (tuya_cmd_status == 2){
|
||||||
if(serial_in_byte_counter == 5){ // Get length of data
|
if(tuya_byte_counter == 5){ // Get length of data
|
||||||
tuya_cmd_status = 3;
|
tuya_cmd_status = 3;
|
||||||
tuya_data_len = serial_in_byte;
|
tuya_data_len = serial_in_byte;
|
||||||
}
|
}
|
||||||
tuya_cmd_checksum += serial_in_byte;
|
tuya_cmd_checksum += serial_in_byte;
|
||||||
serial_in_buffer[serial_in_byte_counter++] = serial_in_byte;
|
tuya_buffer[tuya_byte_counter++] = serial_in_byte;
|
||||||
}
|
}
|
||||||
else if ((tuya_cmd_status == 3) && (serial_in_byte_counter == (6 + tuya_data_len)) && (tuya_cmd_checksum == serial_in_byte)){ // Compare checksum and process packet
|
else if ((tuya_cmd_status == 3) && (tuya_byte_counter == (6 + tuya_data_len)) && (tuya_cmd_checksum == serial_in_byte)){ // Compare checksum and process packet
|
||||||
serial_in_buffer[serial_in_byte_counter++] = serial_in_byte;
|
tuya_buffer[tuya_byte_counter++] = serial_in_byte;
|
||||||
|
|
||||||
snprintf_P(log_data, sizeof(log_data), PSTR("TYA: 0x55 Packet End: \""));
|
snprintf_P(log_data, sizeof(log_data), PSTR("TYA: 0x55 Packet End: \""));
|
||||||
for (int i = 0; i < serial_in_byte_counter; i++) {
|
for (int i = 0; i < tuya_byte_counter; i++) {
|
||||||
snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, serial_in_buffer[i]);
|
snprintf_P(log_data, sizeof(log_data), PSTR("%s%02x"), log_data, tuya_buffer[i]);
|
||||||
}
|
}
|
||||||
snprintf_P(log_data, sizeof(log_data), PSTR("%s\""), log_data);
|
snprintf_P(log_data, sizeof(log_data), PSTR("%s\""), log_data);
|
||||||
AddLog(LOG_LEVEL_DEBUG);
|
AddLog(LOG_LEVEL_DEBUG);
|
||||||
|
|
||||||
TuyaPacketProcess();
|
TuyaPacketProcess();
|
||||||
serial_in_byte_counter = 0;
|
tuya_byte_counter = 0;
|
||||||
tuya_cmd_status = 0;
|
tuya_cmd_status = 0;
|
||||||
tuya_cmd_checksum = 0;
|
tuya_cmd_checksum = 0;
|
||||||
tuya_data_len = 0;
|
tuya_data_len = 0;
|
||||||
} // read additional packets from TUYA
|
} // read additional packets from TUYA
|
||||||
else if(serial_in_byte_counter < INPUT_BUFFER_SIZE -1) { // add char to string if it still fits
|
else if(tuya_byte_counter < TUYA_BUFFER_SIZE -1) { // add char to string if it still fits
|
||||||
serial_in_buffer[serial_in_byte_counter++] = serial_in_byte;
|
tuya_buffer[tuya_byte_counter++] = serial_in_byte;
|
||||||
tuya_cmd_checksum += serial_in_byte;
|
tuya_cmd_checksum += serial_in_byte;
|
||||||
} else {
|
} else {
|
||||||
serial_in_byte_counter = 0;
|
tuya_byte_counter = 0;
|
||||||
tuya_cmd_status = 0;
|
tuya_cmd_status = 0;
|
||||||
tuya_cmd_checksum = 0;
|
tuya_cmd_checksum = 0;
|
||||||
tuya_data_len = 0;
|
tuya_data_len = 0;
|
||||||
|
@ -205,7 +213,10 @@ void TuyaSerialInput()
|
||||||
|
|
||||||
boolean TuyaModuleSelected()
|
boolean TuyaModuleSelected()
|
||||||
{
|
{
|
||||||
baudrate = 9600;
|
if (!(pin[GPIO_TUYA_RX] < 99) || !(pin[GPIO_TUYA_TX] < 99)) { // fallback to hardware-serial if not explicitly selected
|
||||||
|
pin[GPIO_TUYA_RX] = 1;
|
||||||
|
pin[GPIO_TUYA_TX] = 3;
|
||||||
|
}
|
||||||
light_type = LT_SERIAL;
|
light_type = LT_SERIAL;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -215,20 +226,23 @@ void TuyaInit()
|
||||||
if (!Settings.param[P_TUYA_DIMMER_ID]) {
|
if (!Settings.param[P_TUYA_DIMMER_ID]) {
|
||||||
Settings.param[P_TUYA_DIMMER_ID] = TUYA_DIMMER_ID;
|
Settings.param[P_TUYA_DIMMER_ID] = TUYA_DIMMER_ID;
|
||||||
}
|
}
|
||||||
Serial.setDebugOutput(false);
|
TuyaSerial = new TasmotaSerial(pin[GPIO_TUYA_RX], pin[GPIO_TUYA_TX], 1);
|
||||||
ClaimSerial();
|
if (TuyaSerial->begin(9600)) {
|
||||||
|
if (TuyaSerial->hardwareSerial()) { ClaimSerial(); }
|
||||||
|
|
||||||
// Get current status of MCU
|
// Get current status of MCU
|
||||||
snprintf_P(log_data, sizeof(log_data), "TYA: Request MCU state");
|
snprintf_P(log_data, sizeof(log_data), "TYA: Request MCU state");
|
||||||
AddLog(LOG_LEVEL_DEBUG);
|
AddLog(LOG_LEVEL_DEBUG);
|
||||||
Serial.write(0x55); // header 55AA
|
|
||||||
Serial.write(0xAA);
|
TuyaSerial->write((uint8_t)0x55); // header 55AA
|
||||||
Serial.write(0x00); // version 00
|
TuyaSerial->write((uint8_t)0xAA);
|
||||||
Serial.write(0x08); // command 08 - get status
|
TuyaSerial->write((uint8_t)0x00); // version 00
|
||||||
Serial.write(0x00);
|
TuyaSerial->write((uint8_t)0x08); // command 08 - get status
|
||||||
Serial.write(0x00); // following data length 0x00
|
TuyaSerial->write((uint8_t)0x00);
|
||||||
Serial.write(0x07); // checksum:sum of all bytes in packet mod 256
|
TuyaSerial->write((uint8_t)0x00); // following data length 0x00
|
||||||
Serial.flush();
|
TuyaSerial->write((uint8_t)0x07); // checksum:sum of all bytes in packet mod 256
|
||||||
|
TuyaSerial->flush();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean TuyaButtonPressed()
|
boolean TuyaButtonPressed()
|
||||||
|
@ -266,7 +280,7 @@ boolean Xdrv16(byte function)
|
||||||
TuyaInit();
|
TuyaInit();
|
||||||
break;
|
break;
|
||||||
case FUNC_LOOP:
|
case FUNC_LOOP:
|
||||||
TuyaSerialInput();
|
if (TuyaSerial) { TuyaSerialInput(); }
|
||||||
break;
|
break;
|
||||||
case FUNC_SET_DEVICE_POWER:
|
case FUNC_SET_DEVICE_POWER:
|
||||||
result = TuyaSetPower();
|
result = TuyaSetPower();
|
||||||
|
|
|
@ -664,7 +664,7 @@ void HueLights(String *path)
|
||||||
response = "[";
|
response = "[";
|
||||||
|
|
||||||
StaticJsonBuffer<400> jsonBuffer;
|
StaticJsonBuffer<400> jsonBuffer;
|
||||||
JsonObject &hue_json = jsonBuffer.parseObject(WebServer->arg((WebServer->args())-1));
|
JsonObject &hue_json = jsonBuffer.parseObject(WebServer->arg("1"));
|
||||||
if (hue_json.containsKey("on")) {
|
if (hue_json.containsKey("on")) {
|
||||||
|
|
||||||
response += FPSTR(HUE_LIGHT_RESPONSE_JSON);
|
response += FPSTR(HUE_LIGHT_RESPONSE_JSON);
|
||||||
|
|
|
@ -0,0 +1,230 @@
|
||||||
|
<h1 id="decode-config-py">decode-config.py</h1>
|
||||||
|
<p><em>decode-config.py</em> backup and restore Sonoff-Tasmota configuration.</p>
|
||||||
|
<p>Comparing backup files created by <em>decode-config.py</em> and *.dmp files created by Tasmota "Backup/Restore Configuration": </p>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th> </th>
|
||||||
|
<th style="text-align:center">decode-config.py<br />*.json file</th>
|
||||||
|
<th style="text-align:center">Sonoff-Tasmota<br />*.dmp file</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Encrypted</td>
|
||||||
|
<td style="text-align:center">No</td>
|
||||||
|
<td style="text-align:center">Yes</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Readable</td>
|
||||||
|
<td style="text-align:center">Yes</td>
|
||||||
|
<td style="text-align:center">No</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Simply editable</td>
|
||||||
|
<td style="text-align:center">Yes</td>
|
||||||
|
<td style="text-align:center">No</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Simply batch processing</td>
|
||||||
|
<td style="text-align:center">Yes</td>
|
||||||
|
<td style="text-align:center">No</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p><em>decode-config.py</em> handles Tasmota configurations for release version since 5.10.0 up to now.</p>
|
||||||
|
<h1 id="content">Content</h1>
|
||||||
|
<ul>
|
||||||
|
<li><a href="decode-config.html#prerequisite">Prerequisite</a></li>
|
||||||
|
<li><a href="decode-config.html#file-types">File Types</a><ul>
|
||||||
|
<li><a href="decode-config.html#-dmp-file-format">.dmp File Format</a></li>
|
||||||
|
<li><a href="decode-config.html#-json-file-format">.json File Format</a></li>
|
||||||
|
<li><a href="decode-config.html#-bin-file-format">.bin File Format</a><ul>
|
||||||
|
<li><a href="decode-config.html#file-extensions">File extensions</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li><a href="decode-config.html#usage">Usage</a><ul>
|
||||||
|
<li><a href="decode-config.html#basics">Basics</a></li>
|
||||||
|
<li><a href="decode-config.html#save-backup-file">Save backup file</a></li>
|
||||||
|
<li><a href="decode-config.html#restore-backup-file">Restore backup file</a></li>
|
||||||
|
<li><a href="decode-config.html#configuration-file">Configuration file</a></li>
|
||||||
|
<li><a href="decode-config.html#more-program-arguments">More program arguments</a></li>
|
||||||
|
<li><a href="decode-config.html#examples">Examples</a><ul>
|
||||||
|
<li><a href="decode-config.html#config-file">Config file</a></li>
|
||||||
|
<li><a href="decode-config.html#using-tasmota-binary-configuration-files">Using Tasmota binary configuration files</a></li>
|
||||||
|
<li><a href="decode-config.html#use-batch-processing">Use batch processing</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<h2 id="prerequisite">Prerequisite</h2>
|
||||||
|
<ul>
|
||||||
|
<li><a href="https://en.wikipedia.org/wiki/Python_(programming_language">Python</a>)<br>This program is written in <a href="https://en.wikipedia.org/wiki/Python_(programming_language">Python</a>) so you need to install a python environment (for details see <a href="https://docs.python.org/2.7/using/index.html">Python Setup and Usage</a>)</li>
|
||||||
|
<li><a href="https://github.com/arendst/Sonoff-Tasmota">Sonoff-Tasmota</a> <a href="https://github.com/arendst/Sonoff-Tasmota/releases">Firmware</a> with enabled Web-Server<br>To backup or restore configurations from/to a Sonoff-Tasmota device you need a firmare with enabled web-server in admin mode (command <a href="https://github.com/arendst/Sonoff-Tasmota/wiki/Commands#wifi">WebServer 2</a>).
|
||||||
|
<br />Only self compiled firmware may do not have a web-server sod if you use your own compiled firmware be aware to enable the web-server, otherwise you can only use the <code>--file</code> parameter as source.</li>
|
||||||
|
</ul>
|
||||||
|
<h2 id="file-types">File Types</h2>
|
||||||
|
<p><em>decode-config.py</em> can handle the following backup file types: </p>
|
||||||
|
<h3 id="-dmp-format">.dmp Format</h3>
|
||||||
|
<p>Configuration data as used by Tasmota "Backup/Restore Configuration" web interface.<br>This format is binary and encrypted.</p>
|
||||||
|
<h3 id="-json-format">.json Format</h3>
|
||||||
|
<p>Configuration data in <a href="http://www.json.org/">JSON</a>-format.<br>This format is decrypted, human readable and editable and can also be used for the <code>--restore-file</code> command.<br>This file will becreated by <em>decode-config.py</em> using <code>--backup-file</code> with <code>--backup-type json</code> parameter (default).</p>
|
||||||
|
<h3 id="-bin-format">.bin Format</h3>
|
||||||
|
<p>Configuration data in binary format.<br>This format is binary decryptet, editable (e.g. using a hex editor) and can also be used for <code>--restore-file</code> command.<br>It will be created by <em>decode-config.py</em> using <code>--backup-file</code> with <code>--backup-type bin</code>.<br>Note:<br>This file is 4 byte longer than an original .dmp file due to an prefix header at the beginning. The file data starting at address position 4 are containing the same as the <strong>struct SYSCFG</strong> from Tasmota <a href="https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/settings.h">settings.h</a> in decrypted format.</p>
|
||||||
|
<h4 id="file-extensions">File extensions</h4>
|
||||||
|
<p><em>decode-config.py</em> uses auto extension as default for backup filenames; you don't need to append extensions to your backup file, it will be selected based on <code>--backup-type</code> argument.<br>If you want using your own extension use the <code>--no-extension</code> argument.</p>
|
||||||
|
<h2 id="usage">Usage</h2>
|
||||||
|
<p>After download don't forget to set exec flag under linux with <code>chmod +x decode-config.py</code> or call the program using <code>python decode-config.py...</code>.</p>
|
||||||
|
<h3 id="basics">Basics</h3>
|
||||||
|
<p>At least pass a source where you want to read the configuration data from using <code>-f <filename></code> or <code>-d <host></code>:</p>
|
||||||
|
<p>The source can be either </p>
|
||||||
|
<ul>
|
||||||
|
<li>a Tasmota device hostname or IP by passing it using the <code>-d <host></code> arg</li>
|
||||||
|
<li>or a previously stored Tasmota *.dmp<code>configuration file by passing the filename using</code>-f <filename>` arg</li>
|
||||||
|
</ul>
|
||||||
|
<p>Example: </p>
|
||||||
|
<pre><code>decode-config<span class="hljs-selector-class">.py</span> -d sonoff-<span class="hljs-number">4281</span>
|
||||||
|
</code></pre><p>will output a human readable configuration in <a href="http://www.json.org/">JSON</a>-format:</p>
|
||||||
|
<pre><code>{
|
||||||
|
<span class="hljs-string">"altitude"</span>: <span class="hljs-number">112</span>,
|
||||||
|
<span class="hljs-string">"baudrate"</span>: <span class="hljs-number">115200</span>,
|
||||||
|
<span class="hljs-string">"blinkcount"</span>: <span class="hljs-number">10</span>,
|
||||||
|
<span class="hljs-string">"blinktime"</span>: <span class="hljs-number">10</span>,
|
||||||
|
...
|
||||||
|
<span class="hljs-string">"ws_width"</span>: [
|
||||||
|
<span class="hljs-number">1</span>,
|
||||||
|
<span class="hljs-number">3</span>,
|
||||||
|
<span class="hljs-number">5</span>
|
||||||
|
]
|
||||||
|
}
|
||||||
|
</code></pre><h3 id="save-backup-file">Save backup file</h3>
|
||||||
|
<p>To save the output as backup file <code>--backup-file <filename></code>, you can use placeholder for Version, Friendlyname and Hostname: </p>
|
||||||
|
<pre><code><span class="hljs-selector-tag">decode-config</span><span class="hljs-selector-class">.py</span> <span class="hljs-selector-tag">-d</span> <span class="hljs-selector-tag">sonoff-4281</span> <span class="hljs-selector-tag">--backup-file</span> <span class="hljs-selector-tag">Config_</span>@<span class="hljs-keyword">f_</span>@<span class="hljs-keyword">v</span>
|
||||||
|
</code></pre><p>If you have setup a WebPassword within Tasmota, use</p>
|
||||||
|
<pre><code>decode-config<span class="hljs-selector-class">.py</span> -d sonoff-<span class="hljs-number">4281</span> -<span class="hljs-selector-tag">p</span> <yourpassword> --backup-file Config_@f_@v
|
||||||
|
</code></pre><p>will create a file like <code>Config_Sonoff_x.x.x.json</code>. Because it is in JSON format, you can read and edit the file with any raw text editor.</p>
|
||||||
|
<h3 id="restore-backup-file">Restore backup file</h3>
|
||||||
|
<p>Reading back a saved (and possible changed) backup file use the <code>--restore-file <filename></code> arg. This will read the (changed) configuration data from this file and send it back to the source device or filename.</p>
|
||||||
|
<p>To restore the previously save backup file <code>Config_Sonoff_6.2.1.json</code> to device <code>sonoff-4281</code> use: </p>
|
||||||
|
<pre><code><span class="hljs-selector-tag">decode-config</span><span class="hljs-selector-class">.py</span> <span class="hljs-selector-tag">-d</span> <span class="hljs-selector-tag">sonoff-4281</span> <span class="hljs-selector-tag">--restore-file</span> <span class="hljs-selector-tag">Config_Sonoff_6</span><span class="hljs-selector-class">.2</span><span class="hljs-selector-class">.1</span><span class="hljs-selector-class">.json</span>
|
||||||
|
</code></pre><p>with password set by WebPassword:</p>
|
||||||
|
<pre><code><span class="hljs-selector-tag">decode-config</span><span class="hljs-selector-class">.py</span> <span class="hljs-selector-tag">-d</span> <span class="hljs-selector-tag">sonoff-4281</span> <span class="hljs-selector-tag">-p</span> <<span class="hljs-selector-tag">yourpassword</span>> <span class="hljs-selector-tag">--restore-file</span> <span class="hljs-selector-tag">Config_Sonoff_6</span><span class="hljs-selector-class">.2</span><span class="hljs-selector-class">.1</span><span class="hljs-selector-class">.json</span>
|
||||||
|
</code></pre><h3 id="configuration-file">Configuration file</h3>
|
||||||
|
<p>Each argument that start with <code>--</code> (eg. <code>--file</code>) can also be set in a config file (specified via -c). Config file syntax allows: key=value, flag=true, stuff=[a,b,c] (for details, see syntax at <a href="https://pypi.org/project/ConfigArgParse/">https://pypi.org/project/ConfigArgParse</a>).</p>
|
||||||
|
<p>If an argument is specified in more than one place, then commandline values override config file values which override defaults. This is usefull if you always use the same argument or a basic set of arguments.</p>
|
||||||
|
<p>The http authentication credentials <code>--username</code> and <code>--password</code> is predestinated to store it in a file instead using it on your command line as argument:</p>
|
||||||
|
<p>e.g. my.conf:</p>
|
||||||
|
<pre><code><span class="hljs-section">[source]</span>
|
||||||
|
<span class="hljs-attr">username</span> = admin
|
||||||
|
<span class="hljs-attr">password</span> = myPaszxwo!z
|
||||||
|
</code></pre><p>To make a backup file from example above you can now pass the config file instead using the password on command line:</p>
|
||||||
|
<pre><code><span class="hljs-selector-tag">decode-config</span><span class="hljs-selector-class">.py</span> <span class="hljs-selector-tag">-d</span> <span class="hljs-selector-tag">sonoff-4281</span> <span class="hljs-selector-tag">-c</span> <span class="hljs-selector-tag">my</span><span class="hljs-selector-class">.conf</span> <span class="hljs-selector-tag">--backup-file</span> <span class="hljs-selector-tag">Config_</span>@<span class="hljs-keyword">f_</span>@<span class="hljs-keyword">v</span>
|
||||||
|
</code></pre><h3 id="more-program-arguments">More program arguments</h3>
|
||||||
|
<p>For better reading your porgram arguments each short written arg (minus sign <code>-</code>) has a corresponding readable long version (two minus signs <code>--</code>), eg. <code>--device</code> for <code>-d</code> or <code>--file</code> for <code>-f</code> (note: not even all <code>--</code> arg has a corresponding <code>-</code> one).</p>
|
||||||
|
<p>A short list of possible program args is displayed using <code>-h</code> or <code>--help</code>.</p>
|
||||||
|
<p>For advanced help use <code>-H</code> or <code>--full-help</code>:</p>
|
||||||
|
<pre><code>usage: decode-config.py [-f <filename>] [-d <host>] [-P <<span class="hljs-keyword">port</span>>]
|
||||||
|
[-u <username>] [-p <password>] [-i <filename>]
|
||||||
|
[-o <filename>] [-F json|bin|dmp] [-E] [-e]
|
||||||
|
[<span class="hljs-comment">--json-indent <indent>] [--json-compact]</span>
|
||||||
|
[<span class="hljs-comment">--json-hide-pw] [--json-unhide-pw] [-h] [-H] [-v]</span>
|
||||||
|
[-V] [-c <filename>] [<span class="hljs-comment">--ignore-warnings]</span>
|
||||||
|
|
||||||
|
Backup/Restore Sonoff-Tasmota <span class="hljs-keyword">configuration</span> data. Args that start <span class="hljs-keyword">with</span> '<span class="hljs-comment">--'</span>
|
||||||
|
(eg. -f) can also be set <span class="hljs-keyword">in</span> a config <span class="hljs-keyword">file</span> (specified via -c). Config <span class="hljs-keyword">file</span>
|
||||||
|
syntax allows: key=value, flag=<span class="hljs-literal">true</span>, stuff=[a,b,c] (<span class="hljs-keyword">for</span> details, see syntax at
|
||||||
|
https://goo.gl/R74nmi). <span class="hljs-keyword">If</span> an arg <span class="hljs-keyword">is</span> specified <span class="hljs-keyword">in</span> more than one place, <span class="hljs-keyword">then</span>
|
||||||
|
commandline values override config <span class="hljs-keyword">file</span> values which override defaults.
|
||||||
|
|
||||||
|
optional arguments:
|
||||||
|
-c, <span class="hljs-comment">--config <filename></span>
|
||||||
|
program config <span class="hljs-keyword">file</span> - can be used <span class="hljs-keyword">to</span> set <span class="hljs-keyword">default</span>
|
||||||
|
command args (<span class="hljs-keyword">default</span>: None)
|
||||||
|
<span class="hljs-comment">--ignore-warnings do not exit on warnings. Not recommended, used by your</span>
|
||||||
|
own responsibility!
|
||||||
|
|
||||||
|
Source:
|
||||||
|
Read/Write Tasmota <span class="hljs-keyword">configuration</span> from/<span class="hljs-keyword">to</span>
|
||||||
|
|
||||||
|
-f, <span class="hljs-comment">--file, --tasmota-file <filename></span>
|
||||||
|
<span class="hljs-keyword">file</span> <span class="hljs-keyword">to</span> retrieve/write Tasmota <span class="hljs-keyword">configuration</span> from/<span class="hljs-keyword">to</span>
|
||||||
|
(<span class="hljs-keyword">default</span>: None)'
|
||||||
|
-d, <span class="hljs-comment">--device, --host <host></span>
|
||||||
|
hostname <span class="hljs-keyword">or</span> IP address <span class="hljs-keyword">to</span> retrieve/send Tasmota
|
||||||
|
<span class="hljs-keyword">configuration</span> from/<span class="hljs-keyword">to</span> (<span class="hljs-keyword">default</span>: None)
|
||||||
|
-P, <span class="hljs-comment">--port <port> TCP/IP port number to use for the host connection</span>
|
||||||
|
(<span class="hljs-keyword">default</span>: <span class="hljs-number">80</span>)
|
||||||
|
-u, <span class="hljs-comment">--username <username></span>
|
||||||
|
host HTTP <span class="hljs-keyword">access</span> username (<span class="hljs-keyword">default</span>: admin)
|
||||||
|
-p, <span class="hljs-comment">--password <password></span>
|
||||||
|
host HTTP <span class="hljs-keyword">access</span> password (<span class="hljs-keyword">default</span>: None)
|
||||||
|
|
||||||
|
Backup/Restore:
|
||||||
|
Backup/Restore <span class="hljs-keyword">configuration</span> <span class="hljs-keyword">file</span> specification
|
||||||
|
|
||||||
|
-i, <span class="hljs-comment">--restore-file <filename></span>
|
||||||
|
<span class="hljs-keyword">file</span> <span class="hljs-keyword">to</span> restore <span class="hljs-keyword">configuration</span> from (<span class="hljs-keyword">default</span>: None).
|
||||||
|
Replacements: @v=firmware version, @f=device friendly
|
||||||
|
name, @h=device hostname
|
||||||
|
-o, <span class="hljs-comment">--backup-file <filename></span>
|
||||||
|
<span class="hljs-keyword">file</span> <span class="hljs-keyword">to</span> backup <span class="hljs-keyword">configuration</span> <span class="hljs-keyword">to</span> (<span class="hljs-keyword">default</span>: None).
|
||||||
|
Replacements: @v=firmware version, @f=device friendly
|
||||||
|
name, @h=device hostname
|
||||||
|
-F, <span class="hljs-comment">--backup-type json|bin|dmp</span>
|
||||||
|
backup filetype (<span class="hljs-keyword">default</span>: <span class="hljs-symbol">'json</span>')
|
||||||
|
-E, <span class="hljs-comment">--extension append filetype extension for -i and -o filename</span>
|
||||||
|
(<span class="hljs-keyword">default</span>)
|
||||||
|
-e, <span class="hljs-comment">--no-extension do not append filetype extension, use -i and -o</span>
|
||||||
|
filename as passed
|
||||||
|
|
||||||
|
JSON:
|
||||||
|
JSON backup format specification
|
||||||
|
|
||||||
|
<span class="hljs-comment">--json-indent <indent></span>
|
||||||
|
pretty-printed JSON output using indent level
|
||||||
|
(<span class="hljs-keyword">default</span>: <span class="hljs-symbol">'None</span>'). -<span class="hljs-number">1</span> disables indent.
|
||||||
|
<span class="hljs-comment">--json-compact compact JSON output by eliminate whitespace</span>
|
||||||
|
<span class="hljs-comment">--json-hide-pw hide passwords (default)</span>
|
||||||
|
<span class="hljs-comment">--json-unhide-pw unhide passwords</span>
|
||||||
|
|
||||||
|
Info:
|
||||||
|
additional information
|
||||||
|
|
||||||
|
-h, <span class="hljs-comment">--help show usage help message and exit</span>
|
||||||
|
-H, <span class="hljs-comment">--full-help show full help message and exit</span>
|
||||||
|
-v, <span class="hljs-comment">--verbose produce more output about what the program does</span>
|
||||||
|
-V, <span class="hljs-comment">--version show program's version number and exit</span>
|
||||||
|
|
||||||
|
Either argument -d <host> <span class="hljs-keyword">or</span> -f <filename> must be given.
|
||||||
|
</code></pre><h3 id="examples">Examples</h3>
|
||||||
|
<p>The most of the examples are for linux command line. Under Windows call the program using <code>python decode-config.py ...</code>.</p>
|
||||||
|
<h4 id="config-file">Config file</h4>
|
||||||
|
<p>Note: The example contains .ini style sections <code>[...]</code>. Sections are always treated as comment and serves as clarity only.
|
||||||
|
For further details of config file syntax see <a href="https://pypi.org/project/ConfigArgParse/">https://pypi.org/project/ConfigArgParse</a>.</p>
|
||||||
|
<p><em>my.conf</em></p>
|
||||||
|
<pre><code><span class="hljs-string">[Source]</span>
|
||||||
|
username = admin
|
||||||
|
password = myPaszxwo!z
|
||||||
|
|
||||||
|
<span class="hljs-string">[JSON]</span>
|
||||||
|
json-indent <span class="hljs-number">2</span>
|
||||||
|
</code></pre><h4 id="using-tasmota-binary-configuration-files">Using Tasmota binary configuration files</h4>
|
||||||
|
<ol>
|
||||||
|
<li><p>Restore a Tasmota configuration file</p>
|
||||||
|
<p> <code>decode-config.py -c my.conf -d sonoff --restore-file Config_Sonoff_6.2.1.dmp</code></p>
|
||||||
|
</li>
|
||||||
|
<li><p>Backup device using Tasmota configuration compatible format</p>
|
||||||
|
<p>a) use file extension to choice the file format</p>
|
||||||
|
<p> <code>decode-config.py -c my.conf -d sonoff --backup-file Config_@f_@v.dmp</code></p>
|
||||||
|
<p>b) use args to choice the file format</p>
|
||||||
|
<p> <code>decode-config.py -c my.conf -d sonoff --backup-type dmp --backup-file Config_@f_@v</code></p>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
<h4 id="use-batch-processing">Use batch processing</h4>
|
||||||
|
<pre><code><span class="hljs-keyword">for</span> device <span class="hljs-keyword">in</span> sonoff1 sonoff2 sonoff3; <span class="hljs-keyword">do</span> ./decode-config.py -c my.conf -d <span class="hljs-variable">$device</span> -o Config<span class="hljs-number">_</span><span class="hljs-variable">@f_</span><span class="hljs-variable">@v</span>
|
||||||
|
</code></pre><p>or under windows</p>
|
||||||
|
<pre><code><span class="hljs-keyword">for</span> device <span class="hljs-keyword">in</span> (sonoff1 sonoff2 sonoff3) <span class="hljs-keyword">do</span> <span class="hljs-keyword">python</span> decode-config.py -c my.conf -d %device -o Config_@f_@v
|
||||||
|
</code></pre><p>will produce JSON configuration files for host sonoff1, sonoff2 and sonoff3 using friendly name and Tasmota firmware version for backup filenames.</p>
|
|
@ -0,0 +1,253 @@
|
||||||
|
# decode-config.py
|
||||||
|
_decode-config.py_ backup and restore Sonoff-Tasmota configuration.
|
||||||
|
|
||||||
|
Comparing backup files created by *decode-config.py* and *.dmp files created by Tasmota "Backup/Restore Configuration":
|
||||||
|
|
||||||
|
| | decode-config.py<br />*.json file | Sonoff-Tasmota<br />*.dmp file |
|
||||||
|
|-------------------------|:-------------------------------:|:-----------------------------------:|
|
||||||
|
| Encrypted | No | Yes |
|
||||||
|
| Readable | Yes | No |
|
||||||
|
| Simply editable | Yes | No |
|
||||||
|
| Simply batch processing | Yes | No |
|
||||||
|
|
||||||
|
_decode-config.py_ handles Tasmota configurations for release version since 5.10.0 up to now.
|
||||||
|
|
||||||
|
# Content
|
||||||
|
* [Prerequisite](decode-config.md#prerequisite)
|
||||||
|
* [File Types](decode-config.md#file-types)
|
||||||
|
* [.dmp File Format](decode-config.md#-dmp-file-format)
|
||||||
|
* [.json File Format](decode-config.md#-json-file-format)
|
||||||
|
* [.bin File Format](decode-config.md#-bin-file-format)
|
||||||
|
* [File extensions](decode-config.md#file-extensions)
|
||||||
|
* [Usage](decode-config.md#usage)
|
||||||
|
* [Basics](decode-config.md#basics)
|
||||||
|
* [Save backup file](decode-config.md#save-backup-file)
|
||||||
|
* [Restore backup file](decode-config.md#restore-backup-file)
|
||||||
|
* [Configuration file](decode-config.md#configuration-file)
|
||||||
|
* [More program arguments](decode-config.md#more-program-arguments)
|
||||||
|
* [Examples](decode-config.md#examples)
|
||||||
|
* [Config file](decode-config.md#config-file)
|
||||||
|
* [Using Tasmota binary configuration files](decode-config.md#using-tasmota-binary-configuration-files)
|
||||||
|
* [Use batch processing](decode-config.md#use-batch-processing)
|
||||||
|
|
||||||
|
## Prerequisite
|
||||||
|
* [Python](https://en.wikipedia.org/wiki/Python_(programming_language))
|
||||||
|
This program is written in [Python](https://en.wikipedia.org/wiki/Python_(programming_language)) so you need to install a python environment (for details see [Python Setup and Usage](https://docs.python.org/2.7/using/index.html))
|
||||||
|
* [Sonoff-Tasmota](https://github.com/arendst/Sonoff-Tasmota) [Firmware](https://github.com/arendst/Sonoff-Tasmota/releases) with enabled Web-Server
|
||||||
|
To backup or restore configurations from/to a Sonoff-Tasmota device you need a firmare with enabled web-server in admin mode (command [WebServer 2](https://github.com/arendst/Sonoff-Tasmota/wiki/Commands#wifi)).
|
||||||
|
<br />Only self compiled firmware may do not have a web-server sod if you use your own compiled firmware be aware to enable the web-server, otherwise you can only use the `--file` parameter as source.
|
||||||
|
|
||||||
|
## File Types
|
||||||
|
_decode-config.py_ can handle the following backup file types:
|
||||||
|
### .dmp Format
|
||||||
|
Configuration data as used by Tasmota "Backup/Restore Configuration" web interface.
|
||||||
|
This format is binary and encrypted.
|
||||||
|
### .json Format
|
||||||
|
Configuration data in [JSON](http://www.json.org/)-format.
|
||||||
|
This format is decrypted, human readable and editable and can also be used for the `--restore-file` command.
|
||||||
|
This file will becreated by _decode-config.py_ using `--backup-file` with `--backup-type json` parameter (default).
|
||||||
|
### .bin Format
|
||||||
|
Configuration data in binary format.
|
||||||
|
This format is binary decryptet, editable (e.g. using a hex editor) and can also be used for `--restore-file` command.
|
||||||
|
It will be created by _decode-config.py_ using `--backup-file` with `--backup-type bin`.
|
||||||
|
Note:
|
||||||
|
This file is 4 byte longer than an original .dmp file due to an prefix header at the beginning. The file data starting at address position 4 are containing the same as the **struct SYSCFG** from Tasmota [settings.h](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/settings.h) in decrypted format.
|
||||||
|
|
||||||
|
#### File extensions
|
||||||
|
_decode-config.py_ uses auto extension as default for backup filenames; you don't need to append extensions to your backup file, it will be selected based on `--backup-type` argument.
|
||||||
|
If you want using your own extension use the `--no-extension` argument.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
After download don't forget to set exec flag under linux with `chmod +x decode-config.py` or call the program using `python decode-config.py...`.
|
||||||
|
|
||||||
|
### Basics
|
||||||
|
At least pass a source where you want to read the configuration data from using `-f <filename>` or `-d <host>`:
|
||||||
|
|
||||||
|
The source can be either
|
||||||
|
* a Tasmota device hostname or IP by passing it using the `-d <host>` arg
|
||||||
|
* or a previously stored Tasmota *.dmp` configuration file by passing the filename using `-f <filename>` arg
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
decode-config.py -d sonoff-4281
|
||||||
|
|
||||||
|
will output a human readable configuration in [JSON](http://www.json.org/)-format:
|
||||||
|
|
||||||
|
{
|
||||||
|
"altitude": 112,
|
||||||
|
"baudrate": 115200,
|
||||||
|
"blinkcount": 10,
|
||||||
|
"blinktime": 10,
|
||||||
|
...
|
||||||
|
"ws_width": [
|
||||||
|
1,
|
||||||
|
3,
|
||||||
|
5
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
### Save backup file
|
||||||
|
To save the output as backup file `--backup-file <filename>`, you can use placeholder for Version, Friendlyname and Hostname:
|
||||||
|
|
||||||
|
decode-config.py -d sonoff-4281 --backup-file Config_@f_@v
|
||||||
|
|
||||||
|
If you have setup a WebPassword within Tasmota, use
|
||||||
|
|
||||||
|
decode-config.py -d sonoff-4281 -p <yourpassword> --backup-file Config_@f_@v
|
||||||
|
|
||||||
|
will create a file like `Config_Sonoff_x.x.x.json`. Because it is in JSON format, you can read and edit the file with any raw text editor.
|
||||||
|
|
||||||
|
### Restore backup file
|
||||||
|
Reading back a saved (and possible changed) backup file use the `--restore-file <filename>` arg. This will read the (changed) configuration data from this file and send it back to the source device or filename.
|
||||||
|
|
||||||
|
To restore the previously save backup file `Config_Sonoff_6.2.1.json` to device `sonoff-4281` use:
|
||||||
|
|
||||||
|
decode-config.py -d sonoff-4281 --restore-file Config_Sonoff_6.2.1.json
|
||||||
|
|
||||||
|
with password set by WebPassword:
|
||||||
|
|
||||||
|
decode-config.py -d sonoff-4281 -p <yourpassword> --restore-file Config_Sonoff_6.2.1.json
|
||||||
|
|
||||||
|
### Configuration file
|
||||||
|
Each argument that start with `--` (eg. `--file`) can also be set in a config file (specified via -c). Config file syntax allows: key=value, flag=true, stuff=[a,b,c] (for details, see syntax at [https://pypi.org/project/ConfigArgParse](https://pypi.org/project/ConfigArgParse/)).
|
||||||
|
|
||||||
|
If an argument is specified in more than one place, then commandline values override config file values which override defaults. This is usefull if you always use the same argument or a basic set of arguments.
|
||||||
|
|
||||||
|
The http authentication credentials `--username` and `--password` is predestinated to store it in a file instead using it on your command line as argument:
|
||||||
|
|
||||||
|
e.g. my.conf:
|
||||||
|
|
||||||
|
[source]
|
||||||
|
username = admin
|
||||||
|
password = myPaszxwo!z
|
||||||
|
|
||||||
|
To make a backup file from example above you can now pass the config file instead using the password on command line:
|
||||||
|
|
||||||
|
decode-config.py -d sonoff-4281 -c my.conf --backup-file Config_@f_@v
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### More program arguments
|
||||||
|
For better reading your porgram arguments each short written arg (minus sign `-`) has a corresponding readable long version (two minus signs `--`), eg. `--device` for `-d` or `--file` for `-f` (note: not even all `--` arg has a corresponding `-` one).
|
||||||
|
|
||||||
|
A short list of possible program args is displayed using `-h` or `--help`.
|
||||||
|
|
||||||
|
For advanced help use `-H` or `--full-help`:
|
||||||
|
|
||||||
|
usage: decode-config.py [-f <filename>] [-d <host>] [-P <port>]
|
||||||
|
[-u <username>] [-p <password>] [-i <filename>]
|
||||||
|
[-o <filename>] [-F json|bin|dmp] [-E] [-e]
|
||||||
|
[--json-indent <indent>] [--json-compact]
|
||||||
|
[--json-hide-pw] [--json-unhide-pw] [-h] [-H] [-v]
|
||||||
|
[-V] [-c <filename>] [--ignore-warnings]
|
||||||
|
|
||||||
|
Backup/Restore Sonoff-Tasmota configuration data. Args that start with '--'
|
||||||
|
(eg. -f) can also be set in a config file (specified via -c). Config file
|
||||||
|
syntax allows: key=value, flag=true, stuff=[a,b,c] (for details, see syntax at
|
||||||
|
https://goo.gl/R74nmi). If an arg is specified in more than one place, then
|
||||||
|
commandline values override config file values which override defaults.
|
||||||
|
|
||||||
|
optional arguments:
|
||||||
|
-c, --config <filename>
|
||||||
|
program config file - can be used to set default
|
||||||
|
command args (default: None)
|
||||||
|
--ignore-warnings do not exit on warnings. Not recommended, used by your
|
||||||
|
own responsibility!
|
||||||
|
|
||||||
|
Source:
|
||||||
|
Read/Write Tasmota configuration from/to
|
||||||
|
|
||||||
|
-f, --file, --tasmota-file <filename>
|
||||||
|
file to retrieve/write Tasmota configuration from/to
|
||||||
|
(default: None)'
|
||||||
|
-d, --device, --host <host>
|
||||||
|
hostname or IP address to retrieve/send Tasmota
|
||||||
|
configuration from/to (default: None)
|
||||||
|
-P, --port <port> TCP/IP port number to use for the host connection
|
||||||
|
(default: 80)
|
||||||
|
-u, --username <username>
|
||||||
|
host HTTP access username (default: admin)
|
||||||
|
-p, --password <password>
|
||||||
|
host HTTP access password (default: None)
|
||||||
|
|
||||||
|
Backup/Restore:
|
||||||
|
Backup/Restore configuration file specification
|
||||||
|
|
||||||
|
-i, --restore-file <filename>
|
||||||
|
file to restore configuration from (default: None).
|
||||||
|
Replacements: @v=firmware version, @f=device friendly
|
||||||
|
name, @h=device hostname
|
||||||
|
-o, --backup-file <filename>
|
||||||
|
file to backup configuration to (default: None).
|
||||||
|
Replacements: @v=firmware version, @f=device friendly
|
||||||
|
name, @h=device hostname
|
||||||
|
-F, --backup-type json|bin|dmp
|
||||||
|
backup filetype (default: 'json')
|
||||||
|
-E, --extension append filetype extension for -i and -o filename
|
||||||
|
(default)
|
||||||
|
-e, --no-extension do not append filetype extension, use -i and -o
|
||||||
|
filename as passed
|
||||||
|
|
||||||
|
JSON:
|
||||||
|
JSON backup format specification
|
||||||
|
|
||||||
|
--json-indent <indent>
|
||||||
|
pretty-printed JSON output using indent level
|
||||||
|
(default: 'None'). -1 disables indent.
|
||||||
|
--json-compact compact JSON output by eliminate whitespace
|
||||||
|
--json-hide-pw hide passwords (default)
|
||||||
|
--json-unhide-pw unhide passwords
|
||||||
|
|
||||||
|
Info:
|
||||||
|
additional information
|
||||||
|
|
||||||
|
-h, --help show usage help message and exit
|
||||||
|
-H, --full-help show full help message and exit
|
||||||
|
-v, --verbose produce more output about what the program does
|
||||||
|
-V, --version show program's version number and exit
|
||||||
|
|
||||||
|
Either argument -d <host> or -f <filename> must be given.
|
||||||
|
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
The most of the examples are for linux command line. Under Windows call the program using `python decode-config.py ...`.
|
||||||
|
|
||||||
|
#### Config file
|
||||||
|
Note: The example contains .ini style sections `[...]`. Sections are always treated as comment and serves as clarity only.
|
||||||
|
For further details of config file syntax see [https://pypi.org/project/ConfigArgParse](https://pypi.org/project/ConfigArgParse/).
|
||||||
|
|
||||||
|
*my.conf*
|
||||||
|
|
||||||
|
[Source]
|
||||||
|
username = admin
|
||||||
|
password = myPaszxwo!z
|
||||||
|
|
||||||
|
[JSON]
|
||||||
|
json-indent 2
|
||||||
|
|
||||||
|
#### Using Tasmota binary configuration files
|
||||||
|
|
||||||
|
1. Restore a Tasmota configuration file
|
||||||
|
|
||||||
|
`decode-config.py -c my.conf -d sonoff --restore-file Config_Sonoff_6.2.1.dmp`
|
||||||
|
|
||||||
|
2. Backup device using Tasmota configuration compatible format
|
||||||
|
|
||||||
|
a) use file extension to choice the file format
|
||||||
|
|
||||||
|
`decode-config.py -c my.conf -d sonoff --backup-file Config_@f_@v.dmp`
|
||||||
|
|
||||||
|
b) use args to choice the file format
|
||||||
|
|
||||||
|
`decode-config.py -c my.conf -d sonoff --backup-type dmp --backup-file Config_@f_@v`
|
||||||
|
|
||||||
|
#### Use batch processing
|
||||||
|
|
||||||
|
for device in sonoff1 sonoff2 sonoff3; do ./decode-config.py -c my.conf -d $device -o Config_@f_@v
|
||||||
|
|
||||||
|
or under windows
|
||||||
|
|
||||||
|
for device in (sonoff1 sonoff2 sonoff3) do python decode-config.py -c my.conf -d %device -o Config_@f_@v
|
||||||
|
|
||||||
|
will produce JSON configuration files for host sonoff1, sonoff2 and sonoff3 using friendly name and Tasmota firmware version for backup filenames.
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue