Merge branch 'development' of https://github.com/arendst/Sonoff-Tasmota into colorpicker

This commit is contained in:
Staars 2019-11-21 16:16:34 +01:00
commit a1dc8465bb
39 changed files with 608 additions and 1219 deletions

2
.gitignore vendored
View File

@ -12,6 +12,8 @@ tasmota/user_config_override.h
build
firmware.map
firmware.asm
tasmota*.bin
tasmota*.map
## Visual Studio Code specific ######
.vscode

View File

@ -163,7 +163,7 @@ The following binary downloads have been compiled with ESP8266/Arduino library c
| USE_BUZZER | - | - | x | x | x | - | - |
| USE_ARILUX_RF | - | - | x | x | x | - | - |
| USE_SHUTTER | - | - | - | - | - | - | - |
| USE_DEEPSLEEP | - | - | - | - | - | - | - |
| USE_DEEPSLEEP | - | - | x | - | x | - | - |
| USE_EXS_DIMMER | - | - | x | x | - | - | - |
| | | | | | | | |
| Feature or Sensor | minimal | basic | tasmota | knx | sensors | ir | display | Remarks
@ -276,11 +276,11 @@ The following binary downloads have been compiled with ESP8266/Arduino library c
- Remove update support for versions before 6.0
- Remove driver xsns_12_ads1115_i2cdev replaced by xsns_12_ads1115
- Remove most IR protocols from non dedicated IR firmware except NEC, RC5 and RC6
- Change repository name from Sonoff-Tasmota to Tasmota and all code references from Sonoff to Tasmota
- Change default GUI to dark theme
- Change ArduinoSlave to TasmotaSlave
- Change IRremoteESP8266 library to v2.7.0
- Change supported IR protocols in non dedicated IR firmware to NEC, RC5 and RC6 only
- Change supported PCF8574 I2C address range to 0x20 - 0x26 allowing other I2C devices with address 0x27 to be used at the same time
- Change supported PCF8574A I2C address range to 0x39 - 0x3F allowing other I2C devices with address 0x38 to be used at the same time
- Change supported MCP230xx I2C address range to 0x20 - 0x26 allowing other I2C devices with address 0x27 to be used at the same time
@ -291,12 +291,13 @@ The following binary downloads have been compiled with ESP8266/Arduino library c
- Add support for Honeywell I2C HIH series Humidity and Temperetaure sensor (#6808)
- Add support for Honeywell HPMA115S0 particle concentration sensor by David Hunt (#6843)
- Add support for I2C sensor TLS2591 Light Intensity sensor (#6873)
- Add command ``WebColor19`` to control color of Module and Name (#6811)
- Add command ``SetOption73 0/1`` to re-enable HTTP Cross-Origin Resource Sharing (CORS) now default disabled (#6767)
- Add command ``SetOption74 0/1`` to enable DS18x20 internal pull-up and remove define DS18B20_INTERNAL_PULLUP (#6795)
- Add command ``SetOption75 0/1`` to switch between grouptopic (0) using fulltopic replacing %topic% or (1) is cmnd/\<grouptopic\> (#6779)
- Add command ``SetOption76 0/1`` to enable incrementing bootcount when deepsleep is enabled (#6930)
- Add command ``I2cDriver`` for I2C driver runtime control using document I2CDEVICES.md
- Add command ``TempOffset -12.6 .. 12.6`` to set global temperature sensor offset (#6958)
- Add command ``WebColor19`` to control color of Module and Name (#6811)
- Add command ``WifiPower 0 .. 20.5`` to set Wifi Output Power which will be default set to 17dBm
- Add frequency to ADE7953 energy monitor as used in Shelly 2.5 by ljakob (#6778)
- Add hide Alexa objects with friendlyname starting with '$' (#6722, #6762)

View File

@ -127,7 +127,7 @@ boolean PubSubClient::connect(const char *id, const char *user, const char *pass
if (_client->connected()) {
result = 1;
} else {
if (domain != NULL) {
if (domain.length() != 0) {
result = _client->connect(this->domain.c_str(), this->port);
} else {
result = _client->connect(this->ip, this->port);
@ -321,9 +321,10 @@ boolean PubSubClient::loop() {
} else {
buffer[0] = MQTTPINGREQ;
buffer[1] = 0;
_client->write(buffer,2);
lastOutActivity = t;
lastInActivity = t;
if (_client->write(buffer,2) != 0) {
lastOutActivity = t;
lastInActivity = t;
}
pingOutstanding = true;
}
}
@ -351,9 +352,9 @@ boolean PubSubClient::loop() {
buffer[1] = 2;
buffer[2] = (msgId >> 8);
buffer[3] = (msgId & 0xFF);
_client->write(buffer,4);
lastOutActivity = t;
if (_client->write(buffer,4) != 0) {
lastOutActivity = t;
}
} else {
payload = buffer+llen+3+tl;
callback(topic,payload,len-llen-3-tl);
@ -456,11 +457,12 @@ boolean PubSubClient::publish_P(const char* topic, const uint8_t* payload, unsig
for (i=0;i<plength;i++) {
rc += _client->write((char)pgm_read_byte_near(payload + i));
}
lastOutActivity = millis();
if (rc > 0) {
lastOutActivity = millis();
}
// Header (1 byte) + llen + identifier (2 bytes) + topic len + payload len
const int expectedLength = 1 + llen + 2 + tlen + plength;
const unsigned int expectedLength = 1 + llen + 2 + tlen + plength;
return (rc == expectedLength);
}
@ -475,7 +477,9 @@ boolean PubSubClient::beginPublish(const char* topic, unsigned int plength, bool
}
size_t hlen = buildHeader(header, buffer, plength+length-MQTT_MAX_HEADER_SIZE);
uint16_t rc = _client->write(buffer+(MQTT_MAX_HEADER_SIZE-hlen),length-(MQTT_MAX_HEADER_SIZE-hlen));
lastOutActivity = millis();
if (rc > 0) {
lastOutActivity = millis();
}
return (rc == (length-(MQTT_MAX_HEADER_SIZE-hlen)));
}
return false;
@ -486,19 +490,27 @@ int PubSubClient::endPublish() {
}
size_t PubSubClient::write(uint8_t data) {
lastOutActivity = millis();
if (_client == nullptr) {
return 0;
lastOutActivity = millis();
return 0;
}
return _client->write(data);
size_t rc = _client->write(data);
if (rc != 0) {
lastOutActivity = millis();
}
return rc;
}
size_t PubSubClient::write(const uint8_t *buffer, size_t size) {
lastOutActivity = millis();
if (_client == nullptr) {
return 0;
lastOutActivity = millis();
return 0;
}
return _client->write(buffer,size);
size_t rc = _client->write(buffer,size);
if (rc != 0) {
lastOutActivity = millis();
}
return rc;
}
size_t PubSubClient::buildHeader(uint8_t header, uint8_t* buf, uint16_t length) {
@ -544,7 +556,9 @@ boolean PubSubClient::write(uint8_t header, uint8_t* buf, uint16_t length) {
return result;
#else
rc = _client->write(buf+(MQTT_MAX_HEADER_SIZE-hlen),length+hlen);
lastOutActivity = millis();
if (rc != 0) {
lastOutActivity = millis();
}
return (rc == hlen+length);
#endif
}
@ -623,22 +637,19 @@ uint16_t PubSubClient::writeString(const char* string, uint8_t* buf, uint16_t po
boolean PubSubClient::connected() {
boolean rc;
if (_client == NULL ) {
rc = false;
} else {
rc = (int)_client->connected();
if (!rc) {
if (this->_state == MQTT_CONNECTED) {
this->_state = MQTT_CONNECTION_LOST;
_client->flush();
_client->stop();
}
} else {
return this->_state == MQTT_CONNECTED;
}
this->_state = MQTT_DISCONNECTED;
return false;
}
return rc;
if (_client->connected() == 0) {
bool lastStateConnected = this->_state == MQTT_CONNECTED;
this->disconnect();
if (lastStateConnected) {
this->_state = MQTT_CONNECTION_LOST;
}
return false;
}
return this->_state == MQTT_CONNECTED;
}
PubSubClient& PubSubClient::setServer(uint8_t * ip, uint16_t port) {

View File

@ -127,12 +127,12 @@ build_flags = ${esp82xx_defaults.build_flags}
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221
; NONOSDK22x_190313
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313
; NONOSDK22x_190703
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703
; NONOSDK22x_191024
; NONOSDK22x_190703 = 2.2.2-dev(38a443e) (Tasmota default)
-DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703
; NONOSDK22x_191024 = 2.2.2-dev(5ab15d1)
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024
; NONOSDK22x_191105 (Tasmota default)
-DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105
; NONOSDK22x_191105 = 2.2.2-dev(bb83b9b)
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105
; NONOSDK3V0 (known issues)
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3
; lwIP 1.4
@ -173,12 +173,12 @@ build_flags = ${esp82xx_defaults.build_flags}
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221
; NONOSDK22x_190313
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313
; NONOSDK22x_190703
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703
; NONOSDK22x_191024
; NONOSDK22x_190703 = 2.2.2-dev(38a443e) (Tasmota default)
-DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703
; NONOSDK22x_191024 = 2.2.2-dev(5ab15d1)
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024
; NONOSDK22x_191105 (Tasmota default)
-DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105
; NONOSDK22x_191105 = 2.2.2-dev(bb83b9b)
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105
; NONOSDK3V0 (known issues)
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3
; lwIP 1.4

View File

@ -1,755 +0,0 @@
**Script Language for Tasmota**
As an alternative to rules. (about 17k flash size, variable ram size)
In submenu Configuration =\> edit script
1535 bytes max script size (uses rules buffer)
to enable:
\#define USE_SCRIPT
\#undef USE_RULES
Up to 50 variables (45 numeric and 5 strings, maybe changed by #define)
Freely definable variable names (all names are intentionally case sensitive)
Nested if,then,else up to a level of 8
Math operators **+,-,\*,/,%,&,|,^**
all operators may be used in the op= form e.g. **+=**
Left right evaluation with optional brackets
all numbers are float
e.g. temp=hum\*(100/37.5)+temp-(timer\*hum%10)
no spaces allowed between math operations
Comparison operators **==,!=,\>,\>=,<,<=**
**and** , **or** support
hexadecimal numbers are supported with prefix 0x
strings support **+** and **+=** operators
string comparison **==,!=**
max string size = 19 chars (default, can be increased or decreased by optional >D parameter)
**Comments** start with **;**
**Sections** defined:
>**\>D ssize**
ssize = optional max stringsize (default=19)
define and init variables here, must be the first section, no other code allowed
**p:**vname specifies permanent vars (the number of permanent vars is limited by tasmota rules space (50 bytes)
numeric var=4 bytes, string var=lenght of string+1)
**t:**vname specifies countdown timers, if >0 they are decremented in seconds until zero is reached. see example below
**i:**vname specifies auto increment counters if >=0 (in seconds)
**m:**vname specifies a median filter variable with 5 entries (for elimination of outliers)
**M:**vname specifies a moving average filter variable with 8 entries (for smoothing data)
(max 5 filters in total m+M) optional another filter lenght (1..127) can be given after the definition.
filter vars can be accessed also in indexed mode vname[x] (index = 1...N, index 0 returns current array index pointer)
by this filter vars can be used as arrays
>all variable names length taken together may not exceed 256 characters, so keep variable names as short as possible.
memory is dynamically allocated as a result of the D section.
copying a string to a number or reverse is supported
>**\>B**
executed on BOOT time and script save
>**\>T**
executed on teleperiod time (**SENSOR** and **STATE**), get tele vars only in this section
remark: json variable names (like all others) may not contain math operators like - , you should set setoption64 1 to replace - with underscore
>**\>F**
executed every 100 ms
>**\>S**
executed every second
>**\>E**
executed e.g. on power change and mqtt **RESULT**
>**\>R**
executed on restart, p vars are saved automatically after this call
special variables (read only):
>**upsecs** = seconds since start
**uptime** = minutes since start
**time** = minutes since midnight
**sunrise** = sunrise minutes since midnight
**sunset** = sunset minutes since midnight
**tper** = teleperiod (may be set also)
**tstamp** = timestamp (local date and time)
**topic** = mqtt topic
**gtopic** = mqtt group topic
**prefixn** = prefix n = 1-3
**pwr[x]** = tasmota power state (x = 1-N)
**pc[x]** = tasmota pulse counter value (x = 1-4)
**tbut[x]** = touch screen button state (x = 1-N)
**sw[x]** = tasmota switch state (x = 1-N)
>**pin[x]** = gpio pin level (x = 0-16)
**pn[x]** = pin number for sensor code x, 99 if none
**pd[x]** = defined sensor for gpio pin nr x none=999
**gtmp** = global temperature
**ghum** = global humidity
**gprs** = global pressure
**pow(x y)** = calculates the power of x^y
**med(n x)** = calculates a 5 value median filter of x (2 filters possible n=0,1)
**int(x)** = gets the integer part of x (like floor)
**hn(x)** = converts x (0..255) to a hex nibble string
**st(svar c n)** = stringtoken gets the n th substring of svar separated by c
**sl(svar)** = gets the length of a string
**sb(svar p n)** = gets a substring from svar at position p (if p<0 counts from end) and length n
**s(x)** = explicit conversion from number x to string
**mqtts** = state of mqtt disconnected=0, connected>0
**wifis** = state of wifi disconnected=0, connected>0
>**hours** = hours
**mins** = mins
**secs** = seconds
**day** = day of month
**wday** = day of week
**month** = month
**year** = year
these variables are cleared after reading true
>**chg[var]** = true if a variables value was changed (numeric vars only)
**upd[var]** = true if a variable was updated
**boot** = true on BOOT
**tinit** = true on time init
**tset** = true on time set
**mqttc** = true on mqtt connect
**mqttd** = true on mqtt disconnect
**wific** = true on wifi connect
**wifid** = true on wifi disconnect
system vars (for debugging)
>**stack** = stack size
**heap** = heap size
**ram** = used ram size
**slen** = script length
**micros** = running microseconds
**millis** = running milliseconds
**loglvl** = loglevel of script cmds, may be set also
remarks:
if you define a variable with the same name as a special
variable that special variable is discarded
**Tasmota** cmds start with **=\>**
within cmds you can replace text with variables with **%varname%**
a single percent sign must be given as **%%**
**->** is equivalent but doesnt send mqtt or any weblog (silent execute, usefull to reduce traffic)
**special** cmds:
>**print** or **=\>print** prints to info log for debugging
to save code space nearly no error messages are provided. However it is taken care of that at least it should not crash on syntax errors.
if a variable does not exist a **???** is given on commands
if a **SENSOR** or **STATUS** or **RESULT** message or a var does not exist the destination variable is NOT updated.
2 possibilities for conditionals:
>**if** a==b
**and** x==y
**or** k==i
**then** => do this
**else** => do that
**endif**
OR
>**if** a==b
**and** x==y
**or** k==i **{**
=> do this
**} else {**
=> do that
**}**
you may NOT mix both methods
also possible e.g.
>if var1-var2==var3*var4
then
remarks:
the last closing bracket must be on a single line
the condition may be enclosed in brackets
and on the same line conditions may be bracketed e.g. if ((a==b) and ((c==d) or (c==e)) and (s!="x"))
>**break** exits a section or terminates a for next loop
**dpx** sets decimal precision to x (0-9)
**svars** save permanent vars
**delay(x)** pauses x milliseconds (should be as short as possible)
**spin(x m)** set gpio pin x (0-16) to value m (0,1) only the last bit is used, so even values set the pin to zero and uneven values set the pin to 1
**spinm(x m)** set pin mode gpio pin x (0-16) to mode m (input=0,output=1,input with pullup=2)
**ws2812(array)** copies an array (defined with m:name) to the WS2812 LED chain the array should be defined as long as the number of pixels. the color is coded as 24 bit RGB
**hsvrgb(h s v)** converts hue (0-360), saturation (0-100) and value (0-100) to RGB color
>**#name** names a subroutine, subroutines are called with **=#name**
**#name(param)** names a subroutines with a parameter is called with **=#name(param)**
subroutines end with the next '#' or '>' line or break, may be nested
params can be numbers or strings and on mismatch are converted
**=(svar)** executes a script in a string variable (dynamic or self modifying code)
>**for var from to inc**
**next**
specifies a for next loop, (loop count must not be less then 1)
>**switch x**
**case a**
**case b**
**ends**
specifies a switch case selector (numeric or string)
**sd card support**
enable by CARD_CS = gpio pin of card chip select (+ 10k flash)
\#define USE_SCRIPT_FATFS CARD_CS
sd card uses standard hardware spi gpios: mosi,miso,sclk
max 4 files open at a time
allows for e.g. logging sensors to a tab delimited file and then download (see example below)
the download of files may be executed in a kind of "multitasking" when bit 7 of loglvl is set (128+loglevel)
without multitasking 150kb/s (all processes are stopped during download), with multitasking 50kb/s (other tasmota processes are running)
script itself is also stored on sdcard with a default size of 4096 chars
enable sd card directory support (+ 1,2k flash)
\#define SDCARD_DIR
shows a web sdcard directory (submeu of scripter) where you can
upload and download files to/from sd card
>**fr=fo("fname" m)** open file fname, mode 0=read, 1=write (returns file reference (0-3) or -1 for error)
**res=fw("text" fr)** writes text to (the end of) file fr, returns number of bytes written
**res=fr(svar fr)** reads a string into svar, returns bytes read (string is read until delimiter \t \n \r or eof)
**fc(fr)** close file
**ff(fr)** flush file, writes cached data and updates directory
**fd("fname")** delete file fname
**flx(fname)** create download link for file (x=1 or 2) fname = file name of file to download
**fsm** return 1 if filesystem is mounted, (valid sd card found)
extended commands (+0,9k flash)
\#define USE_SCRIPT_FATFS_EXT
>**fmd("fname")** make directory fname
>**frd("fname")** remove directory fname
>**fx("fname")** check if file fname exists
>**fe("fname")** execute script fname (max 2048 bytes, script file must start with '>' char on the 1. line)
**konsole script cmds**
>**script 1 or 0** switch script on or off
**script >cmdline** executes the script cmdline
can be used e.g. to set variables e.g. **script >mintmp=15**
more then one line may be executed seperated by a semicolon e.g. **script >mintmp=15;maxtemp=40**
script itself cant be set because the size would not fit the mqtt buffers
**subscribe,unsubscribe**
>if \#defined SUPPORT_MQTT_EVENT command subscribe and unsubscribe are supported. in contrast to rules no event is generated but the event name specifies a variable defined in D section and this variable is automatically set on transmission of the subscribed item
**summary of optional defines**
>\#define USE_SCRIPT_FATFS CS_PIN : enables SD card support (on spi bus) also enables 4k script buffer
\#define USE_SCRIPT_FATFS_EXT : enables additional FS commands
\#define SDCARD_DIR : enables support for WEBUI for SD card directory up and download
\#define USE_24C256 : enables use of 24C256 i2c eeprom to expand script buffer (defaults to 4k)
\#define SUPPORT_MQTT_EVENT : enables support for subscribe unsubscribe
\#define USE_TOUCH_BUTTONS : enable virtual touch button support with touch displays
***example script***
meant to show some of the possibilities
(actually this code ist too large)
**\>D**
; define all vars here
p:mintmp=10 (p:means permanent)
p:maxtmp=30
t:timer1=30 (t:means countdown timer)
t:mt=0
i:count=0 (i:means auto counter)
hello=&quot;hello world&quot;
string=&quot;xxx&quot;
url=&quot;[192.168.178.86]&quot;
hum=0
temp=0
timer=0
dimmer=0
sw=0
rssi=0
param=0
col=&quot;&quot;
ocol=&quot;&quot;
chan1=0
chan2=0
chan3=0
ahum=0
atemp=0
tcnt=0
hour=0
state=1
m:med5=0
M:movav=0
; define array with 10 entries
m:array=0 10
**\>B**
string=hello+"how are you?"
=\>print BOOT executed
=\>print %hello%
=\>mp3track 1
; list gpio pin definitions
for cnt 0 16 1
tmp=pd[cnt]
=>print %cnt% = %tmp%
next
; get gpio pin for relais 1
tmp=pn[21]
=>print relais 1 is on pin %tmp%
; pulse relais over raw gpio
spin(tmp 1)
delay(100)
spin(tmp 0)
; raw pin level
=>print level of gpio1 %pin[1]%
; pulse over tasmota cmd
=>power 1
delay(100)
=>power 0
**\>T**
hum=BME280#Humidity
temp=BME280#Temperature
rssi=Wifi#RSSI
string=SleepMode
; add to median filter
median=temp
; add to moving average filter
movav=hum
; show filtered results
=>print %median% %movav%
if chg[rssi]>0
then =>print rssi changed to %rssi%
endif
if temp\>30
and hum\>70
then =\>print damn hot!
endif
**\>S**
; every second but not completely reliable time here
; use upsecs and uptime or best t: for reliable timers
; arrays
array[1]=4
array[2]=5
tmp=array[1]+array[2]
; call subrountines with parameters
=#sub1("hallo")
=#sub2(999)
; stop timer after expired
if timer1==0
then timer1=-1
=>print timer1 expired
endif
; auto counter with restart
if count>=10
then =>print 10 seconds over
count=0
endif
if upsecs%5==0
then =\>print %upsecs% (every 5 seconds)
endif
; not recommended for reliable timers
timer+=1
if timer\>=5
then =\>print 5 seconds over (may be)
timer=0
endif
dimmer+=1
if dimmer\>100
then dimmer=0
endif
=\>dimmer %dimmer%
=\>WebSend %url% dimmer %dimmer%
; show on display
dp0
=\>displaytext [c1l1f1s2p20] dimmer=%dimmer%
=\>print %upsecs% %uptime% %time% %sunrise% %sunset% %tstamp%
if time\>sunset
and time< sunrise
then
; night time
if pwr[1]==0
then =\>power1 1
endif
else
; day time
if pwr[1]\>0
then =\>power1 0
endif
endif
; clr display on boot
if boot\>0
then =\>displaytext [z]
endif
; frost warning
if temp<0
and mt<=0
then =#sendmail("frost alert")
; alarm only every 5 minutes
mt=300
=>mp3track 2
endif
; var has been updated
if upd[hello]>0
then =>print %hello%
endif
; send to Thingspeak every 60 seconds
; average data in between
if upsecs%60==0
then
ahum/=tcnt
atemp/=tcnt
=>Websend [184.106.153.149:80]/update?key=PYUZMVWCICBW492&field1=%atemp%&field2=%ahum%
tcnt=0
atemp=0
ahum=0
else
ahum+=hum
atemp+=temp
tcnt+=1
endif
hour=int(time/60)
if chg[hour]>0
then
; exactly every hour
=>print full hour reached
endif
if time>5 {
=>print more then 5 minutes after midnight
} else {
=>print less then 5 minutes after midnight
}
; publish abs hum every teleperiod time
if mqtts>0
and upsecs%tper==0
then
; calc abs humidity
tmp=pow(2.718281828 (17.67\*temp)/(temp+243.5))
tmp=(6.112\*tmp\*hum\*18.01534)/((273.15+temp)\*8.31447215)
; publish median filtered value
=>Publish tele/%topic%/SENSOR {"Script":{"abshum":%med(0 tmp)%}}
endif
;switch case state machine
switch state
case 1
=>print state=%state% , start
state+=1
case 2
=>print state=%state%
state+=1
case 3
=>print state=%state% , reset
state=1
ends
; subroutines
\#sub1(string)
=>print sub1: %string%
\#sub2(param)
=>print sub2: %param%
\#sendmail(string)
=>sendmail [smtp.gmail.com:465:user:passwd:<sender@gmail.de>:<rec@gmail.de>:alarm] %string%
**\>E**
=\>print event executed!
; get HSBColor 1. component
tmp=st(HSBColor , 1)
; check if switch changed state
sw=sw[1]
if chg[sw]>0
then =\>power1 %sw%
endif
hello=&quot;event occured&quot;
; check for Color change (Color is a string)
col=Color
; color change needs 2 string vars
if col!=ocol
then ocol=col
=>print color changed %col%
endif
; or check change of color channels
chan1=Channel[1]
chan2=Channel[2]
chan3=Channel[3]
if chg[chan1]>0
or chg[chan2]>0
or chg[chan3]>0
then => color has changed
endif
; compose color string for red
col=hn(255)+hn(0)+hn(0)
=>color %col%
**\>R**
=\>print restarting now
**a log sensor example**
; define all vars here
; reserve large strings
**\>D** 48
hum=0
temp=0
fr=0
res=0
; moving average for 60 seconds
M:mhum=0 60
M:mtemp=0 60
str=""
**\>B**
; set sensor file download link
fl1("slog.txt")
; delete file in case we want to start fresh
;fd("slog.txt")
; list all files in root directory
fr=fo("/" 0)
for cnt 1 20 1
res=fr(str fr)
if res>0
then
=>print %cnt% : %str%
else
break
endif
next
fc(fr)
**\>T**
; get sensor values
temp=BME280#Temperature
hum=BME280#Humidity
**\>S**
; average sensor values every second
mhum=hum
mtemp=temp
; write average to sensor log every minute
if upsecs%60==0
then
; open file for write
fr=fo("slog.txt" 1)
; compose string for tab delimited file entry
str=s(upsecs)+"\t"+s(mhum)+"\t"+s(mtemp)+"\n"
; write string to log file
res=fw(str fr)
; close file
fc(fr)
endif
**\>R**
**a real example**
epaper 29 with sgp30 and bme280
some vars are set from iobroker
DisplayText substituted to save script space
**\>D**
hum=0
temp=0
press=0
ahum=0
tvoc=0
eco2=0
zwz=0
wr1=0
wr2=0
wr3=0
otmp=0
pwl=0
tmp=0
DT="DisplayText"
; preset units in case they are not available
punit="hPa"
tunit="C"
**\>B**
;reset auto draw
=>%DT% [zD0]
;clr display and draw a frame
=>%DT% [x0y20h296x0y40h296]
**\>T**
; get tele vars
temp=BME280#Temperature
hum=BME280#Humidity
press=BME280#Pressure
tvoc=SGP30#TVOC
eco2=SGP30#eCO2
ahum=SGP30#aHumidity
tunit=TempUnit
punit=PressureUnit
**\>S**
// update display every teleperiod time
if upsecs%tper==0
then
dp2
=>%DT% [f1p7x0y5]%temp% %tunit%
=>%DT% [p5x70y5]%hum% %%[x250y5t]
=>%DT% [p11x140y5]%press% %punit%
=>%DT% [p10x30y25]TVOC: %tvoc% ppb
=>%DT% [p10x160y25]eCO2: %eco2% ppm
=>%DT% [p10c26l5]ahum: %ahum% g^m3
dp0
=>%DT% [p25c1l5]WR 1 (Dach) : %wr1% W
=>%DT% [p25c1l6]WR 2 (Garage): %-wr3% W
=>%DT% [p25c1l7]WR 3 (Garten): %-wr2% W
=>%DT% [p25c1l8]Aussentemperatur: %otmp% C
=>%DT% [x170y95r120:30f2p6x185y100] %pwl% %%
; now update screen
=>%DT% [d]
endif
**\>E**
**\>R**
**another real example**
ILI 9488 color LCD Display shows various energy graphs
display switches on and off with proximity sensor
BMP280 and vl5310x
some vars are set from iobroker
**>D**
temp=0
press=0
zwz=0
wr1=0
wr2=0
wr3=0
otmp=0
pwl=0
tmp=0
dist=0
DT="DisplayText"
punit="hPa"
tunit="C"
hour=0
**>B**
=>%DT% [z]
// define 2 graphs, 2. has 3 tracks
=>%DT% [zCi1G2656:5:20:400:80:1440:-5000:5000:3Ci7f3x410y20]+5000 W[x410y95]-5000 W [Ci7f1x70y3] Zweirichtungsz~80hler - 24 Stunden
=>%DT% [Ci1G2657:5:120:400:80:1440:0:5000:3Ci7f3x410y120]+5000 W[x410y195]0 W [Ci7f1x70y103] Wechselrichter 1-3 - 24 Stunden
=>%DT% [Ci1G2658:5:120:400:80:1440:0:5000:16][Ci1G2659:5:120:400:80:1440:0:5000:5]
=>%DT% [f1s1b0:260:260:100:50:2:11:4:2:Rel 1:b1:370:260:100:50:2:11:4:2:Dsp off:]
=>mp3volume 100
=>mp3track 4
**>T**
; get some tele vars
temp=BMP280#Temperature
press=BMP280#Pressure
tunit=TempUnit
punit=PressureUnit
dist=VL53L0X#Distance
; check proximity sensor to switch display on/off
; to prevent burn in
if dist>300
then
if pwr[2]>0
then
=>power2 0
endif
else
if pwr[2]==0
then
=>power2 1
endif
endif
**>S**
; update graph every teleperiod
if upsecs%tper==0
then
dp2
=>%DT% [f1Ci3x40y260w30Ci1]
=>%DT% [Ci7x120y220t]
=>%DT% [Ci7x180y220T]
=>%DT% [Ci7p8x120y240]%temp% %tunit%
=>%DT% [Ci7x120y260]%press% %punit%
=>%DT% [Ci7x120y280]%dist% mm
dp0
=>%DT% [g0:%zwz%g1:%wr1%g2:%-wr2%g3:%-wr3%]
if zwz>0
then
=>%DT% [p-8x410y55Ci2Bi0]%zwz% W
else
=>%DT% [p-8x410y55Ci3Bi0]%zwz% W
endif
=>%DT% [p-8x410y140Ci3Bi0]%wr1% W
=>%DT% [p-8x410y155Ci16Bi0]%-wr2% W
=>%DT% [p-8x410y170Ci5Bi0]%-wr3% W
endif
; chime every full hour
hour=int(time/60)
if chg[hour]>0
then =>mp3track 4
endif
**>E**
**>R**

View File

@ -1,4 +1,11 @@
/*********************************************************************************************\
* 7.0.0.5 20191118
* Fix boot loop regression
* Add command TempOffset -12.6 .. 12.6 to set global temperature sensor offset (#6958)
* Fix check deepsleep for valid values in Settings (#6961)
* Fix Wifi instability when light is on, due to sleep=0 (#6961, #6608)
* Add hardware detection to be overruled with SetOption51 (#6969)
*
* 7.0.0.4 20191108
* Add command WifiPower 0 .. 20.5 to set Wifi Output Power which will be default set to 17dBm
* Change supported PCF8574 I2C address range to 0x20 - 0x26 allowing other I2C devices with address 0x27 to be used at the same time

View File

@ -290,6 +290,7 @@
#define D_JSON_GPIO "GPIO"
#define D_JSON_FLAG "FLAG"
#define D_JSON_BASE "BASE"
#define D_CMND_TEMPOFFSET "TempOffset"
// Commands xdrv_01_mqtt.ino
#define D_CMND_MQTTLOG "MqttLog"

View File

@ -57,13 +57,13 @@
#define D_AS "jak"
#define D_AUTO "AUTO"
#define D_BLINK "Miganie"
#define D_BLINKOFF "MiganieWył"
#define D_BOOT_COUNT "Licznik uruchomienia"
#define D_BLINKOFF "Miganie - Wył."
#define D_BOOT_COUNT "Licznik restartów"
#define D_BRIGHTLIGHT "Jasny"
#define D_BSSID "BSSId"
#define D_BUTTON "Przycisk"
#define D_BY "by" // Written by me
#define D_BYTES "Bajtow"
#define D_BYTES "Bajtów"
#define D_CELSIUS "Celsiusza"
#define D_CHANNEL "Kanał"
#define D_CO2 "Dwutlenku węgla"
@ -73,7 +73,7 @@
#define D_CONNECTED "Połączony"
#define D_COUNT "Licz"
#define D_COUNTER "Licznik"
#define D_CURRENT "Bieżący" // As in Voltage and Current
#define D_CURRENT "Prąd" // As in Voltage and Current
#define D_DATA "Data"
#define D_DARKLIGHT "Ciemny"
#define D_DEBUG "Debug"
@ -84,18 +84,18 @@
#define D_DST_TIME "DST"
#define D_ECO2 "eCO2"
#define D_EMULATION "Emulacja"
#define D_ENABLED "Otwarty"
#define D_ERASE "Nadpisz"
#define D_ENABLED "Załączony"
#define D_ERASE "Wyczyść"
#define D_ERROR "Błąd"
#define D_FAHRENHEIT "Fahrenheita"
#define D_FAHRENHEIT "Fahrenheit"
#define D_FAILED "Błędny"
#define D_FALLBACK "Awaryjny"
#define D_FALLBACK_TOPIC "Zastępczy temat"
#define D_FALLBACK_TOPIC "Temat zastępczy"
#define D_FALSE "Fałsz"
#define D_FILE "Plik"
#define D_FLOW_RATE "Flow rate"
#define D_FLOW_RATE "Przepływ"
#define D_FREE_MEMORY "Wolna pamięć"
#define D_FREQUENCY "Frequency"
#define D_FREQUENCY "Częstotliwość"
#define D_GAS "Gas"
#define D_GATEWAY "Brama"
#define D_GROUP "Grupa"
@ -103,7 +103,7 @@
#define D_HOSTNAME "Nazwa serwera"
#define D_HUMIDITY "Wilgotność"
#define D_ILLUMINANCE "Oświetlenie"
#define D_IMMEDIATE "Natychmiastowe" // Button immediate
#define D_IMMEDIATE "Natychmiastowy" // Button immediate
#define D_INDEX "Indeks"
#define D_INFO "Informacja"
#define D_INFRARED "Podczerwień"
@ -113,27 +113,27 @@
#define D_LWT "LWT"
#define D_MODULE "Moduł"
#define D_MQTT "MQTT"
#define D_MULTI_PRESS "wielokrotne-naciśnięcie"
#define D_NOISE "Hałas"
#define D_MULTI_PRESS "Wielokrotne naciśnięcie"
#define D_NOISE "Szum"
#define D_NONE "Brak"
#define D_OFF "Wyłączony"
#define D_OFFLINE "Nieaktywny"
#define D_OK "Ok"
#define D_ON "Włączony"
#define D_ON "Załączony"
#define D_ONLINE "Aktywny"
#define D_PASSWORD "Hasło"
#define D_PORT "Port"
#define D_POWER_FACTOR "Współczynik mocy"
#define D_POWER_FACTOR "Cosinus fi"
#define D_POWERUSAGE "Moc"
#define D_POWERUSAGE_ACTIVE "Czynna Moc"
#define D_POWERUSAGE_APPARENT "Pozorna Moc"
#define D_POWERUSAGE_REACTIVE "Reaktywna Moc"
#define D_POWERUSAGE_ACTIVE "Moc czynna"
#define D_POWERUSAGE_APPARENT "Moc pozorna"
#define D_POWERUSAGE_REACTIVE "Moc bierna"
#define D_PRESSURE "Ciśnienie"
#define D_PRESSUREATSEALEVEL "Ciśnienie na poziomie morza"
#define D_PROGRAM_FLASH_SIZE "Wielkość programu flash"
#define D_PROGRAM_SIZE "Wielkość programu"
#define D_PROJECT "Projekt"
#define D_RAIN "Rain"
#define D_RAIN "Deszcz"
#define D_RECEIVED "Otrzymany"
#define D_RESTART "Restart"
#define D_RESTARTING "Restartowanie"
@ -148,8 +148,8 @@
#define D_STD_TIME "STD"
#define D_STOP "Stop"
#define D_SUBNET_MASK "Maska podsieci"
#define D_SUBSCRIBE_TO "Subskrybuj do"
#define D_UNSUBSCRIBE_FROM "Unsubscribe from"
#define D_SUBSCRIBE_TO "Subskrybuj"
#define D_UNSUBSCRIBE_FROM "Nie subskrybuj"
#define D_SUCCESSFUL "Powodzenie"
#define D_SUNRISE "Wschód słońca"
#define D_SUNSET "Zachód słońca"
@ -157,7 +157,7 @@
#define D_TO "do"
#define D_TOGGLE "Przełącz"
#define D_TOPIC "Temat"
#define D_TOTAL_USAGE "Total Usage"
#define D_TOTAL_USAGE "Całkowite użycie"
#define D_TRANSMIT "Wyślij"
#define D_TRUE "Prawda"
#define D_TVOC "TVOC"
@ -166,21 +166,21 @@
#define D_UPTIME "Czas pracy"
#define D_USER "Użytkownik"
#define D_UTC_TIME "UTC"
#define D_UV_INDEX "UV Index"
#define D_UV_INDEX "Index UV"
#define D_UV_INDEX_1 "Niski"
#define D_UV_INDEX_2 "Średni"
#define D_UV_INDEX_3 "Wysoki"
#define D_UV_INDEX_4 "Niebezpieczny"
#define D_UV_INDEX_5 "BurnL1/2"
#define D_UV_INDEX_6 "BurnL3"
#define D_UV_INDEX_5 "Burn L1/2"
#define D_UV_INDEX_6 "Burn L3"
#define D_UV_INDEX_7 "OoR"
#define D_UV_LEVEL "Poziom UV"
#define D_UV_POWER "UV Power"
#define D_UV_POWER "Moc UV"
#define D_VERSION "Wersja"
#define D_VOLTAGE "Napięcie"
#define D_WEIGHT "Weight"
#define D_WARMLIGHT "Nagrzanie"
#define D_WEB_SERVER "Web Serwer"
#define D_WEIGHT "Waga"
#define D_WARMLIGHT "Temperatura światła"
#define D_WEB_SERVER "Serwer Web"
// tasmota.ino
#define D_WARNING_MINIMAL_VERSION "UWAGA Ta wersja nie obsługuje zapisu ustawień"
@ -192,21 +192,21 @@
#define D_SET_BAUDRATE_TO "Ustaw szybkość transmisji na"
#define D_RECEIVED_TOPIC "Otrzymany temat"
#define D_DATA_SIZE "Wielkość danych"
#define D_ANALOG_INPUT "Wej_analogowe"
#define D_ANALOG_INPUT "Wejście analogowe"
// support.ino
#define D_OSWATCH "osWatch"
#define D_BLOCKED_LOOP "Pętla zablokowana"
#define D_WPS_FAILED_WITH_STATUS "Błąd WPSconfig ze statusem"
#define D_WPS_FAILED_WITH_STATUS "Błąd konfiguracji WPS ze statusem"
#define D_ACTIVE_FOR_3_MINUTES "aktywny 3 minuty"
#define D_FAILED_TO_START "nie udało się uruchomić"
#define D_PATCH_ISSUE_2186 "Błąd łatki 2186"
#define D_PATCH_ISSUE_2186 "Błąd poprawki 2186"
#define D_CONNECTING_TO_AP "Łączenie z AP"
#define D_IN_MODE "w trybie"
#define D_CONNECT_FAILED_NO_IP_ADDRESS "Połączenie nie powiodło sie, ponieważ nie otrzymano adresu IP"
#define D_CONNECT_FAILED_AP_NOT_REACHED "Połączenie nie powiodło sie jako AP nie można osiągnać"
#define D_CONNECT_FAILED_WRONG_PASSWORD "Połączenie nie powiodło sie z nieprawidlowym hasłem dostepu AP"
#define D_CONNECT_FAILED_AP_TIMEOUT "Nie udało się nawiązac połączenia, limit czasu AP przekroczony"
#define D_CONNECT_FAILED_NO_IP_ADDRESS "Połączenie nie powiodło się, ponieważ nie otrzymano adresu IP."
#define D_CONNECT_FAILED_AP_NOT_REACHED "Połączenie nie powiodło się, AP nie osiągalny."
#define D_CONNECT_FAILED_WRONG_PASSWORD "Połączenie nie powiodło się, nieprawidlowe hasło."
#define D_CONNECT_FAILED_AP_TIMEOUT "Nie udało się nawiązac połączenia, limit czasu przekroczony."
#define D_ATTEMPTING_CONNECTION "Próba połączenia..."
#define D_CHECKING_CONNECTION "Sprawdzanie połączenia..."
#define D_QUERY_DONE "Wykonano zapytanie. Znaleziono uslugi MQTT"
@ -215,10 +215,10 @@
#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host nie znaleziony"
// settings.ino
#define D_SAVED_TO_FLASH_AT "Zapisane do pamięci flash w"
#define D_LOADED_FROM_FLASH_AT "Wczytane z pamięci flash z"
#define D_SAVED_TO_FLASH_AT "Zapisano do pamięci flash w"
#define D_LOADED_FROM_FLASH_AT "Wczytano z pamięci flash w"
#define D_USE_DEFAULTS "Użyj domyślnych"
#define D_ERASED_SECTOR "Wymazany sektor"
#define D_ERASED_SECTOR "Sektor wymazany"
// xdrv_02_webserver.ino
#define D_NOSCRIPT "Aby korzystać z Tasmota, włącz obsługę JavaScript"
@ -235,19 +235,19 @@
#define D_RESTART_IN "Zrestartuj"
#define D_SECONDS "sekund"
#define D_DEVICE_WILL_RESTART "Urządzenie zrestartuje sie za kilka sekund"
#define D_BUTTON_TOGGLE "Przełącznik"
#define D_BUTTON_TOGGLE "Załącz/Wyłącz"
#define D_CONFIGURATION "Konfiguracja"
#define D_INFORMATION "Informacje"
#define D_FIRMWARE_UPGRADE "Aktualizacja oprogramowania"
#define D_CONSOLE "Konsola"
#define D_CONFIRM_RESTART "Potwierdź restart"
#define D_CONFIGURE_MODULE "Konfiguruj moduł"
#define D_CONFIGURE_WIFI "Konfiguruj WiFi"
#define D_CONFIGURE_MQTT "Konfiguruj MQTT"
#define D_CONFIGURE_DOMOTICZ "Konfiguruj Domoticz"
#define D_CONFIGURE_LOGGING "Konfiguruj zapis dziennika"
#define D_CONFIGURE_OTHER "Konfiguruj inne"
#define D_CONFIGURE_MODULE "Konfiguracja modułu"
#define D_CONFIGURE_WIFI "Konfiguracja WiFi"
#define D_CONFIGURE_MQTT "Konfiguracja MQTT"
#define D_CONFIGURE_DOMOTICZ "Konfiguracja Domoticza"
#define D_CONFIGURE_LOGGING "Konfiguracja dziennika"
#define D_CONFIGURE_OTHER "Konfiguracja innych"
#define D_CONFIRM_RESET_CONFIGURATION "Potwierdź reset ustawień"
#define D_RESET_CONFIGURATION "Reset ustawień"
#define D_BACKUP_CONFIGURATION "Kopia ustawień"
@ -256,18 +256,18 @@
#define D_MODULE_PARAMETERS "Parametry modułu"
#define D_MODULE_TYPE "Typ modułu"
#define D_PULLUP_ENABLE "No Button/Switch pull-up"
#define D_PULLUP_ENABLE "Przełącznik pull-up"
#define D_ADC "ADC"
#define D_GPIO "GPIO"
#define D_SERIAL_IN "Serial In"
#define D_SERIAL_OUT "Serial Out"
#define D_SERIAL_IN "Wejście rs"
#define D_SERIAL_OUT "Wyjście rs"
#define D_WIFI_PARAMETERS "Parametry WiFi"
#define D_WIFI_PARAMETERS "Parametry sieci WiFi"
#define D_SCAN_FOR_WIFI_NETWORKS "Skanuj sieci WiFi"
#define D_SCAN_DONE "Skan wykonany"
#define D_SCAN_DONE "Skanowanie wykonane"
#define D_NO_NETWORKS_FOUND "Nie znaleziono sieci"
#define D_REFRESH_TO_SCAN_AGAIN "Odswież aby ponownie zeskanowac"
#define D_DUPLICATE_ACCESSPOINT "Kopiuj AP"
#define D_REFRESH_TO_SCAN_AGAIN "Odswież aby ponownie wyszukać sieci WiFi"
#define D_DUPLICATE_ACCESSPOINT "Powiel AP"
#define D_SKIPPING_LOW_QUALITY "Pominięto z powodu niskiej jakości sygnału"
#define D_RSSI "RSSI"
#define D_WEP "WEP"
@ -283,11 +283,11 @@
#define D_FULL_TOPIC "Pełny temat"
#define D_LOGGING_PARAMETERS "Opcje dziennika"
#define D_SERIAL_LOG_LEVEL "Serial poziom dziennika"
#define D_MQTT_LOG_LEVEL "Mqtt log level"
#define D_WEB_LOG_LEVEL "Web poziom dziennika"
#define D_SYS_LOG_LEVEL "System poziom dziennika"
#define D_MORE_DEBUG "Więcej informacji debug"
#define D_SERIAL_LOG_LEVEL "Serial - poziom dziennika"
#define D_MQTT_LOG_LEVEL "Mqtt - poziom dziennika"
#define D_WEB_LOG_LEVEL "Web - poziom dziennika"
#define D_SYS_LOG_LEVEL "System - poziom dziennika"
#define D_MORE_DEBUG "Więcej informacji dziennika"
#define D_SYSLOG_HOST "Syslog host"
#define D_SYSLOG_PORT "Syslog port"
#define D_TELEMETRY_PERIOD "Okres telemetrii"
@ -295,15 +295,15 @@
#define D_OTHER_PARAMETERS "Inne parametry"
#define D_TEMPLATE "Szablon"
#define D_ACTIVATE "Aktywuj"
#define D_WEB_ADMIN_PASSWORD "Hasło administratora Web"
#define D_WEB_ADMIN_PASSWORD "Hasło administratora"
#define D_MQTT_ENABLE "MQTT aktywne"
#define D_FRIENDLY_NAME "Twoja nazwa"
#define D_BELKIN_WEMO "Belkin WeMo"
#define D_HUE_BRIDGE "Hue Bridge"
#define D_SINGLE_DEVICE "pojedyncze urządzenie"
#define D_MULTI_DEVICE "wiele urządzeń"
#define D_HUE_BRIDGE "Mostek Hue"
#define D_SINGLE_DEVICE "pojedyńcze urządzenie"
#define D_MULTI_DEVICE "multi urządzenie"
#define D_CONFIGURE_TEMPLATE "Konfiguruj szablon"
#define D_CONFIGURE_TEMPLATE "Konfiguracja szablonu"
#define D_TEMPLATE_PARAMETERS "Parametry szablonu"
#define D_TEMPLATE_NAME "Nazwa"
#define D_BASE_TYPE "Na bazie"
@ -317,11 +317,11 @@
#define D_BUILD_DATE_AND_TIME "Dzień i godzina kompilacji"
#define D_CORE_AND_SDK_VERSION "Wersja Core/SDK"
#define D_FLASH_WRITE_COUNT "Liczba zapisów do pamięci"
#define D_MAC_ADDRESS "Adres Mac"
#define D_MAC_ADDRESS "Adres MAC"
#define D_MQTT_HOST "Host MQTT"
#define D_MQTT_PORT "Port MQTT"
#define D_MQTT_CLIENT "Klient MQTT"
#define D_MQTT_USER "Uzytkownik MQTT"
#define D_MQTT_USER "Użytkownik MQTT"
#define D_MQTT_TOPIC "Temat MQTT"
#define D_MQTT_GROUP_TOPIC "Temat grupy MQTT"
#define D_MQTT_FULL_TOPIC "Pełen temat MQTT"
@ -329,21 +329,21 @@
#define D_MDNS_ADVERTISE "Rozgłaszanie mDNS"
#define D_ESP_CHIP_ID "ID ukladu ESP"
#define D_FLASH_CHIP_ID "ID układu pamięci flash"
#define D_FLASH_CHIP_SIZE "Rozmiar flash"
#define D_FREE_PROGRAM_SPACE "Wolne miejsce programu"
#define D_FLASH_CHIP_SIZE "Rozmiar pamięci flash"
#define D_FREE_PROGRAM_SPACE "Wolna pamięć programu"
#define D_UPGRADE_BY_WEBSERVER "Aktualizacja z serwera Web"
#define D_OTA_URL "URL OTA"
#define D_OTA_URL "URL serwera"
#define D_START_UPGRADE "Start aktualizacji"
#define D_UPGRADE_BY_FILE_UPLOAD "Aktualizacja poprzez wgranie pliku"
#define D_UPGRADE_BY_FILE_UPLOAD "Aktualizacja z pliku"
#define D_UPLOAD_STARTED "Wgrywanie rozpoczęte"
#define D_UPGRADE_STARTED "Aktualizacja rozpoczęta"
#define D_UPLOAD_DONE "Wgrywanie zakończone"
#define D_UPLOAD_ERR_1 "Nie wybrano pliku"
#define D_UPLOAD_ERR_2 "Niewystarczająca ilość miejsca"
#define D_UPLOAD_ERR_3 "Magiczny bajt jest inny niz 0xE9"
#define D_UPLOAD_ERR_4 "Rozmiar programu jest większy niż rzeczywisty rozmiar pamieci flash"
#define D_UPLOAD_ERR_5 "Wgrywanie, bufor niezgodnosci stanu porównywanych bitow"
#define D_UPLOAD_ERR_4 "Rozmiar programu jest większy niż rzeczywisty rozmiar pamięci flash"
#define D_UPLOAD_ERR_5 "Wgrywanie, bufor niezgodności stanu porównywanych bitow"
#define D_UPLOAD_ERR_6 "Błąd wgrywania. Uruchomiono zapis do dziennika na poziomie 3"
#define D_UPLOAD_ERR_7 "Wgrywanie przerwane"
#define D_UPLOAD_ERR_8 "Błędny plik"
@ -355,116 +355,116 @@
#define D_UPLOAD_ERROR_CODE "Błąd wgrywania"
#define D_ENTER_COMMAND "Wprowadź polecenie"
#define D_ENABLE_WEBLOG_FOR_RESPONSE "Włącz poziom 2 zapisu Weblog, jeśli oczekiwana jest odpowiedź"
#define D_ENABLE_WEBLOG_FOR_RESPONSE "Włącz poziom 2 zapisu dziennika, jeśli oczekiwana jest odpowiedź"
#define D_NEED_USER_AND_PASSWORD "Wymagany użytkownik=<username>&hasło=<password>"
// xdrv_01_mqtt.ino
#define D_FINGERPRINT "Weryfikuj odcisk TLS..."
#define D_TLS_CONNECT_FAILED_TO "Nieudane połączenie TLS do"
#define D_RETRY_IN "Spróbuj ponownie"
#define D_VERIFIED "Zweryfikowano odcisku"
#define D_VERIFIED "Zweryfikowano odcisk"
#define D_INSECURE "Nieprawidłowe połączenie z powodu błędnego odcisku TLS"
#define D_CONNECT_FAILED_TO "Nie udało się nawiązać połączenia"
// xplg_wemohue.ino
#define D_MULTICAST_DISABLED "Multicast jest wyłączony"
#define D_MULTICAST_REJOINED "Multicast (re)dołączony"
#define D_MULTICAST_JOIN_FAILED "Multicast nie powiodło się"
#define D_MULTICAST_DISABLED "Multicast wyłączony"
#define D_MULTICAST_REJOINED "Multicast dołączony"
#define D_MULTICAST_JOIN_FAILED "Podłączenie Multicast nie powiodło się"
#define D_FAILED_TO_SEND_RESPONSE "Nie udało się wysłać odpowiedzi"
#define D_WEMO "WeMo"
#define D_WEMO_BASIC_EVENT "WeMo podstawowe zdarzenie"
#define D_WEMO_EVENT_SERVICE "WeMo zdarzenie service"
#define D_WEMO_META_SERVICE "WeMo meta service"
#define D_WEMO_SETUP "WeMo setup"
#define D_WEMO_BASIC_EVENT "Zdarzenie WeNo"
#define D_WEMO_EVENT_SERVICE "Zdarzenie serwisowe WeMo"
#define D_WEMO_META_SERVICE "Meta dane serwisowe WeMo"
#define D_WEMO_SETUP "Ustawienia WeMo"
#define D_RESPONSE_SENT "Odpowiedź wysłana"
#define D_HUE "Hue"
#define D_HUE_BRIDGE_SETUP "Hue setup"
#define D_HUE_API_NOT_IMPLEMENTED "Hue API nie zaimplementowane"
#define D_HUE_API "Hue API"
#define D_HUE_POST_ARGS "Hue POST args"
#define D_HUE_BRIDGE_SETUP "Ustawienia Hue"
#define D_HUE_API_NOT_IMPLEMENTED "Api Hue nie zaimplementowane"
#define D_HUE_API "API Hue"
#define D_HUE_POST_ARGS "POST argument Hue"
#define D_3_RESPONSE_PACKETS_SENT "3 pakiety odpowiedzi wysyłane"
// xdrv_07_domoticz.ino
#define D_DOMOTICZ_PARAMETERS "Parametry Domoticz"
#define D_DOMOTICZ_IDX "Idx"
#define D_DOMOTICZ_KEY_IDX "Key idx"
#define D_DOMOTICZ_SWITCH_IDX "Przełącznik idx"
#define D_DOMOTICZ_SENSOR_IDX "Sensor idx"
#define D_DOMOTICZ_TEMP "Temp"
#define D_DOMOTICZ_TEMP_HUM "Temp,Wilg"
#define D_DOMOTICZ_TEMP_HUM_BARO "Temp,Wilg,Cis"
#define D_DOMOTICZ_POWER_ENERGY "Moc,Energia"
#define D_DOMOTICZ_ILLUMINANCE "Oświetl."
#define D_DOMOTICZ_COUNT "Licznik/PM1"
#define D_DOMOTICZ_VOLTAGE "Napięcie/PM2,5"
#define D_DOMOTICZ_CURRENT "Prąd/PM10"
#define D_DOMOTICZ_AIRQUALITY "AirQuality"
#define D_DOMOTICZ_P1_SMART_METER "P1SmartMeter"
#define D_DOMOTICZ_SWITCH_IDX "Przełącznik Idx"
#define D_DOMOTICZ_SENSOR_IDX "Sensor Idx"
#define D_DOMOTICZ_TEMP "Temperatura"
#define D_DOMOTICZ_TEMP_HUM "Temperatura, Wilgotność"
#define D_DOMOTICZ_TEMP_HUM_BARO "Temperatura, Wilgotność, Ciśnienie"
#define D_DOMOTICZ_POWER_ENERGY "Moc, Energia"
#define D_DOMOTICZ_ILLUMINANCE "Oświetlenie"
#define D_DOMOTICZ_COUNT "Licznik"
#define D_DOMOTICZ_VOLTAGE "Napięcie"
#define D_DOMOTICZ_CURRENT "Prąd"
#define D_DOMOTICZ_AIRQUALITY "Jakość powietrza"
#define D_DOMOTICZ_P1_SMART_METER "Miernik P1"
#define D_DOMOTICZ_UPDATE_TIMER "Zaktualizuj czasomierz"
// xdrv_09_timers.ino
#define D_CONFIGURE_TIMER "Konfiguruj harmonogram"
#define D_TIMER_PARAMETERS "Parametry harmonogramów"
#define D_TIMER_ENABLE "Włącz Harmonogramy"
#define D_CONFIGURE_TIMER "Konfiguracja harmonogramu"
#define D_TIMER_PARAMETERS "Parametry harmonogramu"
#define D_TIMER_ENABLE "Włącz harmonogram"
#define D_TIMER_ARM "Włącz"
#define D_TIMER_TIME "Według godziny"
#define D_TIMER_TIME "Czas"
#define D_TIMER_DAYS "Dni"
#define D_TIMER_REPEAT "Powtarzaj"
#define D_TIMER_OUTPUT "Wyjście"
#define D_TIMER_ACTION "Akcja"
// xdrv_10_knx.ino
#define D_CONFIGURE_KNX "Konfiguruj KNX"
#define D_CONFIGURE_KNX "Konfiguracja KNX"
#define D_KNX_PARAMETERS "Parametry KNX"
#define D_KNX_GENERAL_CONFIG "Ogólne"
#define D_KNX_PHYSICAL_ADDRESS "Adres Fizyczny"
#define D_KNX_PHYSICAL_ADDRESS_NOTE "( Musi być unikalny w sieci KNX )"
#define D_KNX_GENERAL_CONFIG "Konfiguracja ogólna"
#define D_KNX_PHYSICAL_ADDRESS "Adres fizyczny"
#define D_KNX_PHYSICAL_ADDRESS_NOTE "(Musi być unikalny w sieci KNX)"
#define D_KNX_ENABLE "Włącz KNX"
#define D_KNX_GROUP_ADDRESS_TO_WRITE "Dane do wysłania do adresów grupowych"
#define D_KNX_GROUP_ADDRESS_TO_WRITE "Adresy grupowe do zapisu"
#define D_ADD "Dodaj"
#define D_DELETE "Usuń"
#define D_REPLY "Odpowiedz"
#define D_KNX_GROUP_ADDRESS_TO_READ "Adresy grupowe do odbioru danych z"
#define D_RECEIVED_FROM "Otrzymane od"
#define D_KNX_GROUP_ADDRESS_TO_READ "Adresy grupowe do odbioru"
#define D_RECEIVED_FROM "Odebrane od"
#define D_KNX_COMMAND_WRITE "Zapisz"
#define D_KNX_COMMAND_READ "Czytaj"
#define D_KNX_COMMAND_OTHER "Inne"
#define D_SENT_TO "wysłane do"
#define D_KNX_COMMAND_OTHER "Inna komenda"
#define D_SENT_TO "Wysłane do"
#define D_KNX_WARNING "Adres grupy (0/0/0) jest zarezerwowany i nie można go użyć."
#define D_KNX_ENHANCEMENT "Usprawnienie Komunikacji"
#define D_KNX_ENHANCEMENT "Rozszerzenia KNX"
#define D_KNX_TX_SLOT "KNX TX"
#define D_KNX_RX_SLOT "KNX RX"
// xdrv_03_energy.ino
#define D_ENERGY_TODAY "Energia Dzisiaj"
#define D_ENERGY_YESTERDAY "Energia Wczoraj"
#define D_ENERGY_TOTAL "Energia suma"
#define D_ENERGY_TODAY "Energia dzisiaj"
#define D_ENERGY_YESTERDAY "Energia wczoraj"
#define D_ENERGY_TOTAL "Energia całkowita"
// xdrv_27_shutter.ino
#define D_OPEN "Open"
#define D_CLOSE "Close"
#define D_DOMOTICZ_SHUTTER "Shutter"
#define D_OPEN "Otwórz"
#define D_CLOSE "Zamknij"
#define D_DOMOTICZ_SHUTTER "Roleta"
// xdrv_28_pcf8574.ino
#define D_CONFIGURE_PCF8574 "Configure PCF8574"
#define D_PCF8574_PARAMETERS "PCF8574 parameters"
#define D_INVERT_PORTS "Invert Ports"
#define D_DEVICE "Device"
#define D_DEVICE_INPUT "Input"
#define D_DEVICE_OUTPUT "Output"
#define D_CONFIGURE_PCF8574 "Konfiguracja PCF8574"
#define D_PCF8574_PARAMETERS "Parametry PCF8574"
#define D_INVERT_PORTS "Odwrócone porty"
#define D_DEVICE "Urządzenie"
#define D_DEVICE_INPUT "Wejście"
#define D_DEVICE_OUTPUT "Wyjście"
// xsns_05_ds18b20.ino
#define D_SENSOR_BUSY "Czujnik DS18x20 zajęty"
#define D_SENSOR_CRC_ERROR "Czujnik DS18x20 błąd CRC"
#define D_SENSORS_FOUND "Znaleziono Czujnik DS18x20"
#define D_SENSORS_FOUND "Znaleziono czujnik DS18x20"
// xsns_06_dht.ino
#define D_TIMEOUT_WAITING_FOR "Trwa oczekiwanie"
#define D_START_SIGNAL_LOW "sygnał startowy niski"
#define D_START_SIGNAL_HIGH "sygnał startowy wysoki"
#define D_PULSE "pulse"
#define D_PULSE "Impuls"
#define D_CHECKSUM_FAILURE "Błędna suma kontrolna"
// xsns_07_sht1x.ino
@ -486,12 +486,12 @@
// xsns_34_hx711.ino
#define D_HX_CAL_REMOVE "Usuń wagę"
#define D_HX_CAL_REFERENCE "Załaduj masę referencyjną"
#define D_HX_CAL_REFERENCE "Załaduj wagę referencyjną"
#define D_HX_CAL_DONE "Skalibrowany"
#define D_HX_CAL_FAIL "Błąd Kalibracji"
#define D_RESET_HX711 "Zresetuj Skalę"
#define D_CONFIGURE_HX711 "Skonfiguruj Skalę"
#define D_HX711_PARAMETERS "Parametry Skali"
#define D_HX_CAL_FAIL "Błąd kalibracji"
#define D_RESET_HX711 "Zresetuj skalę"
#define D_CONFIGURE_HX711 "Skonfiguruj skalę"
#define D_HX711_PARAMETERS "Parametry skali"
#define D_ITEM_WEIGHT "Waga przedmiotu"
#define D_REFERENCE_WEIGHT "Waga referencyjna"
#define D_CALIBRATE "Skalibruj"
@ -509,7 +509,7 @@
// tasmota_template.h - keep them as short as possible to be able to fit them in GUI drop down box
#define D_SENSOR_NONE "Brak"
#define D_SENSOR_USER "User"
#define D_SENSOR_USER "Użytkownik"
#define D_SENSOR_DHT11 "DHT11"
#define D_SENSOR_AM2301 "AM2301"
#define D_SENSOR_SI7021 "SI7021"
@ -517,15 +517,15 @@
#define D_SENSOR_I2C_SCL "I2C SCL"
#define D_SENSOR_I2C_SDA "I2C SDA"
#define D_SENSOR_WS2812 "WS2812"
#define D_SENSOR_DFR562 "MP3 Player"
#define D_SENSOR_DFR562 "Odtearzacz MP3"
#define D_SENSOR_IRSEND "IRsend"
#define D_SENSOR_SWITCH "Przela" // Suffix "1"
#define D_SENSOR_BUTTON "Przyci" // Suffix "1"
#define D_SENSOR_RELAY "Przek" // Suffix "1i"
#define D_SENSOR_SWITCH "Przełącznik" // Suffix "1"
#define D_SENSOR_BUTTON "Przycisk" // Suffix "1"
#define D_SENSOR_RELAY "Przekaźnik" // Suffix "1i"
#define D_SENSOR_LED "Led" // Suffix "1i"
#define D_SENSOR_LED_LINK "LedLink" // Suffix "i"
#define D_SENSOR_PWM "PWM" // Suffix "1"
#define D_SENSOR_COUNTER "Liczni" // Suffix "1"
#define D_SENSOR_COUNTER "Licznik" // Suffix "1"
#define D_SENSOR_IRRECV "IRrecv"
#define D_SENSOR_MHZ_RX "MHZ Rx"
#define D_SENSOR_MHZ_TX "MHZ Tx"
@ -623,8 +623,8 @@
#define D_SENSOR_DDSU666_RX "DDSU666 Rx"
#define D_SENSOR_SM2135_CLK "SM2135 Clk"
#define D_SENSOR_SM2135_DAT "SM2135 Dat"
#define D_SENSOR_DEEPSLEEP "DeepSleep"
#define D_SENSOR_EXS_ENABLE "EXS Enable"
#define D_SENSOR_DEEPSLEEP "Głęboko uśpiony"
#define D_SENSOR_EXS_ENABLE "Załącz EXS"
#define D_SENSOR_SLAVE_TX "Slave TX"
#define D_SENSOR_SLAVE_RX "Slave RX"
#define D_SENSOR_SLAVE_RESET "Slave RST"
@ -664,37 +664,37 @@
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
//SDM220
#define D_PHASE_ANGLE "Phase Angle"
#define D_IMPORT_ACTIVE "Import Active"
#define D_EXPORT_ACTIVE "Export Active"
#define D_IMPORT_REACTIVE "Import Reactive"
#define D_EXPORT_REACTIVE "Export Reactive"
#define D_TOTAL_REACTIVE "Total Reactive"
#define D_PHASE_ANGLE "Przesunięcie faz"
#define D_IMPORT_ACTIVE "Czynna pobrana"
#define D_EXPORT_ACTIVE "Czynna oddana"
#define D_IMPORT_REACTIVE "Bierna pobrana"
#define D_EXPORT_REACTIVE "Bierna oddana"
#define D_TOTAL_REACTIVE "Całkowita bierna"
#define D_UNIT_KWARH "kVArh"
#define D_UNIT_ANGLE "Deg"
//SOLAXX1
#define D_PV1_VOLTAGE "PV1 Voltage"
#define D_PV1_CURRENT "PV1 Current"
#define D_PV1_POWER "PV1 Power"
#define D_PV2_VOLTAGE "PV2 Voltage"
#define D_PV2_CURRENT "PV2 Current"
#define D_PV2_POWER "PV2 Power"
#define D_SOLAR_POWER "Solar Power"
#define D_INVERTER_POWER "Inverter Power"
#define D_PV1_VOLTAGE "Napięcie PV1"
#define D_PV1_CURRENT "Prąd PV1"
#define D_PV1_POWER "Moc PV1 "
#define D_PV2_VOLTAGE "Napięcie PV2"
#define D_PV2_CURRENT "Prąd PV2"
#define D_PV2_POWER "Moc PV2"
#define D_SOLAR_POWER "Moc PV"
#define D_INVERTER_POWER "Moc invertera"
#define D_STATUS "Status"
#define D_WAITING "Waiting"
#define D_CHECKING "Checking"
#define D_WORKING "Working"
#define D_FAILURE "Failure"
#define D_SOLAX_ERROR_0 "No Error Code"
#define D_SOLAX_ERROR_1 "Grid Lost Fault"
#define D_SOLAX_ERROR_2 "Grid Voltage Fault"
#define D_SOLAX_ERROR_3 "Grid Frequency Fault"
#define D_SOLAX_ERROR_4 "Pv Voltage Fault"
#define D_SOLAX_ERROR_5 "Isolation Fault"
#define D_SOLAX_ERROR_6 "Over Temperature Fault"
#define D_SOLAX_ERROR_7 "Fan Fault"
#define D_SOLAX_ERROR_8 "Other Device Fault"
#define D_WAITING "Oczekiwanie"
#define D_CHECKING "Sprawdzanie"
#define D_WORKING "Praca"
#define D_FAILURE "Błąd"
#define D_SOLAX_ERROR_0 "Błąd - brak kodu"
#define D_SOLAX_ERROR_1 "Błąd - utrata sieci"
#define D_SOLAX_ERROR_2 "Błąd - napięcie sieci"
#define D_SOLAX_ERROR_3 "Błąd - częstotliwość sieci"
#define D_SOLAX_ERROR_4 "Błąd - napięcie PV"
#define D_SOLAX_ERROR_5 "Błąd - usterka izolacji"
#define D_SOLAX_ERROR_6 "Błąd - przegrzanie"
#define D_SOLAX_ERROR_7 "Błąd - wentylator"
#define D_SOLAX_ERROR_8 "Błąd - inne urządzenie"
#endif // _LANGUAGE_PL_PL_D_H_

View File

@ -434,8 +434,9 @@ struct SYSCFG {
uint32_t deepsleep; // E94
uint16_t energy_power_delta; // E98
uint8_t shutter_motordelay[MAX_SHUTTERS]; // E9A
int8_t temp_comp; // E9E
uint8_t free_e9e[2]; // E9E
uint8_t free_e9f[1]; // E9F
uint8_t web_color2[2][3]; // EA0 - Needs to be on integer / 3 distance from web_color

View File

@ -314,7 +314,9 @@ void SetFlashModeDout(void)
if (ESP.flashRead(address, (uint32_t*)_buffer, FLASH_SECTOR_SIZE)) {
if (_buffer[2] != 3) { // DOUT
_buffer[2] = 3;
if (ESP.flashEraseSector(address / FLASH_SECTOR_SIZE)) ESP.flashWrite(address, (uint32_t*)_buffer, FLASH_SECTOR_SIZE);
if (ESP.flashEraseSector(address / FLASH_SECTOR_SIZE)) {
ESP.flashWrite(address, (uint32_t*)_buffer, FLASH_SECTOR_SIZE);
}
}
}
delete[] _buffer;
@ -401,7 +403,7 @@ void UpdateQuickPowerCycle(bool update)
if (update && ((pc_register & 0xFFFFFFF0) == 0xFFA55AB0)) {
uint32_t counter = ((pc_register & 0xF) << 1) & 0xF;
if (0 == counter) { // 4 power cycles in a row
SettingsErase(2); // Quickly reset all settings including QuickPowerCycle flag
SettingsErase(3); // Quickly reset all settings including QuickPowerCycle flag
EspRestart(); // And restart
} else {
pc_register = 0xFFA55AB0 | counter;
@ -412,8 +414,9 @@ void UpdateQuickPowerCycle(bool update)
else if (pc_register != 0xFFA55ABF) {
pc_register = 0xFFA55ABF;
// Assume flash is default all ones and setting a bit to zero does not need an erase
ESP.flashEraseSector(pc_location);
ESP.flashWrite(pc_location * SPI_FLASH_SEC_SIZE, (uint32*)&pc_register, sizeof(pc_register));
if (ESP.flashEraseSector(pc_location)) {
ESP.flashWrite(pc_location * SPI_FLASH_SEC_SIZE, (uint32*)&pc_register, sizeof(pc_register));
}
AddLog_P2(LOG_LEVEL_DEBUG, PSTR("QPC: Reset"));
}
}
@ -464,8 +467,9 @@ void SettingsSave(uint8_t rotate)
Settings.cfg_crc = GetSettingsCrc(); // Keep for backward compatibility in case of fall-back just after upgrade
Settings.cfg_crc32 = GetSettingsCrc32();
ESP.flashEraseSector(settings_location);
ESP.flashWrite(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG));
if (ESP.flashEraseSector(settings_location)) {
ESP.flashWrite(settings_location * SPI_FLASH_SEC_SIZE, (uint32*)&Settings, sizeof(SYSCFG));
}
if (!stop_flash_rotate && rotate) {
for (uint32_t i = 1; i < CFG_ROTATES; i++) {
@ -571,29 +575,30 @@ void SettingsErase(uint8_t type)
0 = Erase from program end until end of flash as seen by SDK
1 = Erase 16k SDK parameter area near end of flash as seen by SDK (0x0xFCxxx - 0x0xFFFFF) solving possible wifi errors
2 = Erase Tasmota settings (0x0xF3xxx - 0x0xFBFFF)
2 = Erase Tasmota parameter area (0x0xF3xxx - 0x0xFBFFF)
3 = Erase Tasmota and SDK parameter area (0x0F3xxx - 0x0FFFFF)
*/
#ifndef FIRMWARE_MINIMAL
// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("SDK: Flash size 0x%08X"), flashchip->chip_size);
uint32_t _sectorStart = (ESP.getSketchSize() / SPI_FLASH_SEC_SIZE) + 1;
uint32_t _sectorEnd = ESP.getFlashChipRealSize() / SPI_FLASH_SEC_SIZE;
// uint32_t _sectorEnd = ESP.getFlashChipSize() / SPI_FLASH_SEC_SIZE;
uint32_t _sectorEnd = ESP.getFlashChipRealSize() / SPI_FLASH_SEC_SIZE; // Flash size as reported by hardware
if (1 == type) {
// source Esp.cpp and core_esp8266_phy.cpp
_sectorStart = (ESP.getFlashChipSize() / SPI_FLASH_SEC_SIZE) - 4;
_sectorStart = (ESP.getFlashChipSize() / SPI_FLASH_SEC_SIZE) - 4; // SDK parameter area
}
else if (2 == type) {
_sectorStart = SETTINGS_LOCATION - CFG_ROTATES; // Tasmota parameter area (0x0F3xxx - 0x0FBFFF)
_sectorStart = SETTINGS_LOCATION - CFG_ROTATES; // Tasmota parameter area (0x0F3xxx - 0x0FBFFF)
_sectorEnd = SETTINGS_LOCATION +1;
}
else if (3 == type) {
_sectorStart = SETTINGS_LOCATION - CFG_ROTATES; // Tasmota and SDK parameter area (0x0F3xxx - 0x0FFFFF)
_sectorEnd = ESP.getFlashChipSize() / SPI_FLASH_SEC_SIZE; // Flash size as seen by SDK
}
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_ERASE " %d " D_UNIT_SECTORS), _sectorEnd - _sectorStart);
// EspErase(_sectorStart, _sectorEnd); // Arduino core and SDK - erases flash as seen by SDK
EsptoolErase(_sectorStart, _sectorEnd); // Esptool - erases flash completely
// EspErase(_sectorStart, _sectorEnd); // Arduino core and SDK - erases flash as seen by SDK
EsptoolErase(_sectorStart, _sectorEnd); // Esptool - erases flash completely
#endif // FIRMWARE_MINIMAL
}

View File

@ -20,6 +20,10 @@
IPAddress syslog_host_addr; // Syslog host IP address
uint32_t syslog_host_hash = 0; // Syslog host name hash
extern "C" {
extern struct rst_info resetInfo;
}
/*********************************************************************************************\
* Watchdog extension (https://github.com/esp8266/Arduino/issues/1532)
\*********************************************************************************************/
@ -72,6 +76,26 @@ void OsWatchLoop(void)
// while(1) delay(1000); // this will trigger the os watch
}
bool OsWatchBlockedLoop(void)
{
return oswatch_blocked_loop;
}
uint32_t ResetReason(void)
{
/*
user_interface.h
REASON_DEFAULT_RST = 0, // "Power on" normal startup by power on
REASON_WDT_RST = 1, // "Hardware Watchdog" hardware watch dog reset
REASON_EXCEPTION_RST = 2, // "Exception" exception reset, GPIO status wont change
REASON_SOFT_WDT_RST = 3, // "Software Watchdog" software watch dog reset, GPIO status wont change
REASON_SOFT_RESTART = 4, // "Software/System restart" software restart ,system_restart , GPIO status wont change
REASON_DEEP_SLEEP_AWAKE = 5, // "Deep-Sleep Wake" wake up from deep-sleep
REASON_EXT_SYS_RST = 6 // "External System" external system reset
*/
return resetInfo.reason;
}
String GetResetReason(void)
{
if (oswatch_blocked_loop) {
@ -83,9 +107,10 @@ String GetResetReason(void)
}
}
bool OsWatchBlockedLoop(void)
String GetResetReasonInfo(void)
{
return oswatch_blocked_loop;
// "Fatal exception:0 flag:2 (EXCEPTION) epc1:0x704022a7 epc2:0x00000000 epc3:0x00000000 excvaddr:0x00000000 depc:0x00000000"
return (ResetReason() == REASON_EXCEPTION_RST) ? ESP.getResetInfo() : GetResetReason();
}
/*********************************************************************************************\
@ -371,7 +396,7 @@ char* NoAlNumToUnderscore(char* dest, const char* source)
return dest;
}
char IndexSeparator()
char IndexSeparator(void)
{
/*
// 20 bytes more costly !?!
@ -394,7 +419,7 @@ void SetShortcutDefault(void)
}
}
uint8_t Shortcut()
uint8_t Shortcut(void)
{
uint8_t result = 10;
@ -496,7 +521,7 @@ char* GetPowerDevice(char* dest, uint32_t idx, size_t size)
return GetPowerDevice(dest, idx, size, 0);
}
String GetDeviceHardware(void)
bool IsEsp8285(void)
{
// esptool.py get_efuses
uint32_t efuse1 = *(uint32_t*)(0x3FF00050);
@ -504,10 +529,22 @@ String GetDeviceHardware(void)
// uint32_t efuse3 = *(uint32_t*)(0x3FF00058);
// uint32_t efuse4 = *(uint32_t*)(0x3FF0005C);
// AddLog_P2(LOG_LEVEL_DEBUG, PSTR("FUS: efuses 0x%08X 0x%08X, name %s"), efuse1, efuse2);
bool is_8285 = ( (efuse1 & (1 << 4)) || (efuse2 & (1 << 16)) );
return String((is_8285) ? F("ESP8285") : F("ESP8266EX"));
if (is_8285 && (ESP.getFlashChipRealSize() > 1048576)) {
is_8285 = false; // ESP8285 can only have 1M flash
}
return is_8285;
}
String GetDeviceHardware(void)
{
char buff[10];
if (IsEsp8285()) {
strcpy_P(buff, PSTR("ESP8285"));
} else {
strcpy_P(buff, PSTR("ESP8266EX"));
}
return String(buff);
}
float ConvertTemp(float c)
@ -520,6 +557,7 @@ float ConvertTemp(float c)
if (!isnan(c) && Settings.flag.temperature_conversion) { // SetOption8 - Switch between Celsius or Fahrenheit
result = c * 1.8 + 32; // Fahrenheit
}
result = result + (0.1 * Settings.temp_comp);
return result;
}
@ -530,6 +568,7 @@ float ConvertTempToCelsius(float c)
if (!isnan(c) && Settings.flag.temperature_conversion) { // SetOption8 - Switch between Celsius or Fahrenheit
result = (c - 32) / 1.8; // Celsius
}
result = result + (0.1 * Settings.temp_comp);
return result;
}
@ -899,7 +938,7 @@ int ResponseJsonEndEnd(void)
* GPIO Module and Template management
\*********************************************************************************************/
uint8_t ModuleNr()
uint8_t ModuleNr(void)
{
// 0 = User module (255)
// 1 up = Template module 0 up
@ -931,7 +970,7 @@ String AnyModuleName(uint32_t index)
}
}
String ModuleName()
String ModuleName(void)
{
return AnyModuleName(Settings.module);
}
@ -963,7 +1002,7 @@ void ModuleGpios(myio *gp)
// AddLogBuffer(LOG_LEVEL_DEBUG, (uint8_t *)gp, sizeof(myio));
}
gpio_flag ModuleFlag()
gpio_flag ModuleFlag(void)
{
gpio_flag flag;
@ -983,7 +1022,7 @@ void ModuleDefault(uint32_t module)
memcpy_P(&Settings.user_template, &kModules[module], sizeof(mytmplt));
}
void SetModuleType()
void SetModuleType(void)
{
my_module_type = (USER_MODULE == Settings.module) ? Settings.user_template_base : Settings.module;
}
@ -998,11 +1037,14 @@ uint8_t ValidPin(uint32_t pin, uint32_t gpio)
uint8_t result = gpio;
if (FlashPin(pin)) {
result = GPIO_NONE; // Disable flash pins GPIO6, GPIO7, GPIO8 and GPIO11
result = GPIO_NONE; // Disable flash pins GPIO6, GPIO7, GPIO8 and GPIO11
}
if ((WEMOS == Settings.module) && (!Settings.flag3.user_esp8285_enable)) { // SetOption51 - Enable ESP8285 user GPIO's
if ((pin == 9) || (pin == 10)) { result = GPIO_NONE; } // Disable possible flash GPIO9 and GPIO10
if (!IsEsp8285() && !Settings.flag3.user_esp8285_enable) { // SetOption51 - Enable ESP8285 user GPIO's
if ((pin == 9) || (pin == 10)) {
result = GPIO_NONE; // Disable possible flash GPIO9 and GPIO10
}
}
return result;
}
@ -1011,7 +1053,7 @@ bool ValidGPIO(uint32_t pin, uint32_t gpio)
return (GPIO_USER == ValidPin(pin, gpio)); // Only allow GPIO_USER pins
}
bool ValidAdc()
bool ValidAdc(void)
{
gpio_flag flag = ModuleFlag();
uint32_t template_adc0 = flag.data &15;
@ -1111,7 +1153,7 @@ bool JsonTemplate(const char* dataBuf)
return true;
}
void TemplateJson()
void TemplateJson(void)
{
Response_P(PSTR("{\"" D_JSON_NAME "\":\"%s\",\"" D_JSON_GPIO "\":["), Settings.user_template.name);
for (uint32_t i = 0; i < sizeof(Settings.user_template.gp); i++) {

View File

@ -26,7 +26,7 @@ const char kTasmotaCommands[] PROGMEM = "|" // No prefix
D_CMND_BUTTONDEBOUNCE "|" D_CMND_SWITCHDEBOUNCE "|" D_CMND_SYSLOG "|" D_CMND_LOGHOST "|" D_CMND_LOGPORT "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE "|"
D_CMND_SERIALDELIMITER "|" D_CMND_IPADDRESS "|" D_CMND_NTPSERVER "|" D_CMND_AP "|" D_CMND_SSID "|" D_CMND_PASSWORD "|" D_CMND_HOSTNAME "|" D_CMND_WIFICONFIG "|"
D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" D_CMND_INTERLOCK "|" D_CMND_TELEPERIOD "|" D_CMND_RESET "|" D_CMND_TIME "|" D_CMND_TIMEZONE "|" D_CMND_TIMESTD "|"
D_CMND_TIMEDST "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" D_CMND_LEDMASK "|" D_CMND_WIFIPOWER "|"
D_CMND_TIMEDST "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" D_CMND_LEDMASK "|" D_CMND_WIFIPOWER "|" D_CMND_TEMPOFFSET "|"
#ifdef USE_I2C
D_CMND_I2CSCAN "|" D_CMND_I2CDRIVER "|"
#endif
@ -41,7 +41,7 @@ void (* const TasmotaCommand[])(void) PROGMEM = {
&CmndButtonDebounce, &CmndSwitchDebounce, &CmndSyslog, &CmndLoghost, &CmndLogport, &CmndSerialSend, &CmndBaudrate,
&CmndSerialDelimiter, &CmndIpAddress, &CmndNtpServer, &CmndAp, &CmndSsid, &CmndPassword, &CmndHostname, &CmndWifiConfig,
&CmndFriendlyname, &CmndSwitchMode, &CmndInterlock, &CmndTeleperiod, &CmndReset, &CmndTime, &CmndTimezone, &CmndTimeStd,
&CmndTimeDst, &CmndAltitude, &CmndLedPower, &CmndLedState, &CmndLedMask, &CmndWifiPower,
&CmndTimeDst, &CmndAltitude, &CmndLedPower, &CmndLedState, &CmndLedMask, &CmndWifiPower, &CmndTempOffset,
#ifdef USE_I2C
&CmndI2cScan, CmndI2cDriver,
#endif
@ -57,6 +57,13 @@ void ResponseCmndNumber(int value)
Response_P(S_JSON_COMMAND_NVALUE, XdrvMailbox.command, value);
}
void ResponseCmndFloat(float value, uint32_t decimals)
{
char stemp1[TOPSZ];
dtostrfd(value, decimals, stemp1);
Response_P(S_JSON_COMMAND_XVALUE, XdrvMailbox.command, stemp1); // Return float value without quotes
}
void ResponseCmndIdxNumber(int value)
{
Response_P(S_JSON_COMMAND_INDEX_NVALUE, XdrvMailbox.command, XdrvMailbox.index, value);
@ -362,7 +369,7 @@ void CmndStatus(void)
D_JSON_RESTARTREASON "\":\"%s\",\"" D_JSON_UPTIME "\":\"%s\",\"" D_JSON_STARTUPUTC "\":\"%s\",\"" D_CMND_SLEEP "\":%d,\""
D_JSON_CONFIG_HOLDER "\":%d,\"" D_JSON_BOOTCOUNT "\":%d,\"" D_JSON_SAVECOUNT "\":%d,\"" D_JSON_SAVEADDRESS "\":\"%X\"}}"),
baudrate, Settings.mqtt_grptopic, Settings.ota_url,
GetResetReason().c_str(), GetUptime().c_str(), GetDateAndTime(DT_RESTART).c_str(), Settings.sleep,
GetResetReasonInfo().c_str(), GetUptime().c_str(), GetDateAndTime(DT_RESTART).c_str(), Settings.sleep,
Settings.cfg_holder, Settings.bootcount, Settings.save_flag, GetSettingsAddress());
MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "1"));
}
@ -496,6 +503,17 @@ void CmndState(void)
#endif // USE_HOME_ASSISTANT
}
void CmndTempOffset(void)
{
if (XdrvMailbox.data_len > 0) {
int value = (int)(CharToFloat(XdrvMailbox.data) * 10);
if ((value > -127) && (value < 127)) {
Settings.temp_comp = value;
}
}
ResponseCmndFloat((float)(Settings.temp_comp) / 10, 1);
}
void CmndSleep(void)
{
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 251)) {
@ -1540,9 +1558,7 @@ void CmndWifiPower(void)
}
WifiSetOutputPower();
}
char stemp1[TOPSZ];
dtostrfd((float)(Settings.wifi_output_power) / 10, 1, stemp1);
Response_P(S_JSON_COMMAND_XVALUE, XdrvMailbox.command, stemp1); // Return float value without quotes
ResponseCmndFloat((float)(Settings.wifi_output_power) / 10, 1);
}
#ifdef USE_I2C

View File

@ -22,8 +22,6 @@
* Functions not available in core 2.3.0
\*********************************************************************************************/
// Functions not available in 2.3.0
// http://clc-wiki.net/wiki/C_standard_library:string.h:memchr
void* memchr(const void* ptr, int value, size_t num)
{
@ -137,6 +135,15 @@ unsigned long long strtoull(const char *__restrict nptr, char **__restrict endpt
return acc;
}
#endif // ARDUINO_ESP8266_RELEASE_2_3_0
#if defined(ARDUINO_ESP8266_RELEASE_2_3_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_0) || defined(ARDUINO_ESP8266_RELEASE_2_4_1) || defined(ARDUINO_ESP8266_RELEASE_2_4_2) || defined(ARDUINO_ESP8266_RELEASE_2_5_0) || defined(ARDUINO_ESP8266_RELEASE_2_5_1) || defined(ARDUINO_ESP8266_RELEASE_2_5_2)
/*********************************************************************************************\
* Functions not available in core before 2.6.0
\*********************************************************************************************/
// https://github.com/arendst/Tasmota/issues/6856#issuecomment-554258914
void* memmove_P(void *dest, const void *src, size_t n)
{
@ -147,7 +154,4 @@ void* memmove_P(void *dest, const void *src, size_t n)
}
}
#endif // ARDUINO_ESP8266_RELEASE_2_3_0
/*********************************************************************************************\
*
\*********************************************************************************************/
#endif // ARDUINO_ESP8266_RELEASE < 2_6_0

View File

@ -217,7 +217,7 @@ void WifiBegin(uint8_t flag, uint8_t channel)
#endif // LWIP_IPV6=1
}
void WifiBeginAfterScan()
void WifiBeginAfterScan(void)
{
static int8_t best_network_db;
@ -314,12 +314,12 @@ void WifiBeginAfterScan()
}
}
uint16_t WifiLinkCount()
uint16_t WifiLinkCount(void)
{
return Wifi.link_count;
}
String WifiDowntime()
String WifiDowntime(void)
{
return GetDuration(Wifi.downtime);
}
@ -615,7 +615,6 @@ void WifiShutdown(void)
void EspRestart(void)
{
WifiShutdown();
RtcRebootReset();
// ESP.restart(); // This results in exception 3 on restarts on core 2.3.0
ESP.reset();
}

View File

@ -100,7 +100,6 @@ const uint16_t PWM_MAX = 4000; // [PWM_MAX] Maximum frequency - Def
const uint16_t PWM_MIN = 100; // [PWM_MIN] Minimum frequency - Default: 100
// For Dimmers use double of your mains AC frequecy (100 for 50Hz and 120 for 60Hz)
// For Controlling Servos use 50 and also set PWM_FREQ as 50 (DO NOT USE THESE VALUES FOR DIMMERS)
//#define PWM_LIGHTSCHEME0_IGNORE_SLEEP // Do not change sleep value for LightAnimate() scheme 0
const uint16_t MAX_POWER_HOLD = 10; // Time in SECONDS to allow max agreed power
const uint16_t MAX_POWER_WINDOW = 30; // Time in SECONDS to disable allow max agreed power

View File

@ -1500,10 +1500,6 @@ void GpioInit(void)
XdrvCall(FUNC_PRE_INIT);
}
extern "C" {
extern struct rst_info resetInfo;
}
void setup(void)
{
global_state.data = 3; // Init global state (wifi_down, mqtt_down) to solve possible network issues
@ -1582,7 +1578,7 @@ void setup(void)
Settings.module = SONOFF_BASIC; // Reset module to Sonoff Basic
// Settings.last_module = SONOFF_BASIC;
}
AddLog_P2(LOG_LEVEL_DEBUG, PSTR(D_LOG_APPLICATION D_LOG_SOME_SETTINGS_RESET " (%d)"), RtcReboot.fast_reboot_count);
AddLog_P2(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_LOG_SOME_SETTINGS_RESET " (%d)"), RtcReboot.fast_reboot_count);
}
}
@ -1605,7 +1601,7 @@ void setup(void)
if (POWER_ALL_ALWAYS_ON == Settings.poweronstate) {
SetDevicePower(1, SRC_RESTART);
} else {
if ((resetInfo.reason == REASON_DEFAULT_RST) || (resetInfo.reason == REASON_EXT_SYS_RST)) {
if ((ResetReason() == REASON_DEFAULT_RST) || (ResetReason() == REASON_EXT_SYS_RST)) {
switch (Settings.poweronstate) {
case POWER_ALL_OFF:
case POWER_ALL_OFF_PULSETIME_ON:
@ -1665,7 +1661,7 @@ void setup(void)
XsnsCall(FUNC_INIT);
}
static void BacklogLoop()
void BacklogLoop(void)
{
if (TimeReached(backlog_delay)) {
if (!BACKLOG_EMPTY && !backlog_mutex) {

View File

@ -96,7 +96,7 @@ char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, c
#define USE_BUZZER // Add support for a buzzer (+0k6 code)
#define USE_ARILUX_RF // Add support for Arilux RF remote controller (+0k8 code, 252 iram (non 2.3.0))
//#define USE_SHUTTER // Add Shutter support for up to 4 shutter with different motortypes (+6k code)
//#define USE_DEEPSLEEP // Add support for deepsleep (+1k code)
#define USE_DEEPSLEEP // Add support for deepsleep (+1k code)
#define USE_EXS_DIMMER // Add support for EX-Store WiFi Dimmer
// -- Optional light modules ----------------------

View File

@ -20,6 +20,6 @@
#ifndef _TASMOTA_VERSION_H_
#define _TASMOTA_VERSION_H_
const uint32_t VERSION = 0x07000004;
const uint32_t VERSION = 0x07000005;
#endif // _TASMOTA_VERSION_H_

View File

@ -733,7 +733,7 @@ void _WSContentSend(const String& content) // Low level sendContent for a
DEBUG_CORE_LOG(PSTR("WEB: Chunk size %d"), len);
}
void WSContentFlush()
void WSContentFlush(void)
{
if (Web.chunk_buffer.length() > 0) {
_WSContentSend(Web.chunk_buffer); // Flush chunk buffer

View File

@ -468,7 +468,7 @@ void MqttPublishPowerState(uint32_t device)
#endif // USE_SONOFF_IFAN
}
void MqttPublishAllPowerState()
void MqttPublishAllPowerState(void)
{
for (uint32_t i = 1; i <= devices_present; i++) {
MqttPublishPowerState(i);
@ -493,7 +493,7 @@ void MqttPublishPowerBlinkState(uint32_t device)
/*********************************************************************************************/
uint16_t MqttConnectCount()
uint16_t MqttConnectCount(void)
{
return Mqtt.connect_count;
}
@ -555,7 +555,7 @@ void MqttConnected(void)
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "2"));
}
#endif // USE_WEBSERVER
Response_P(PSTR("{\"" D_JSON_RESTARTREASON "\":\"%s\"}"), (GetResetReason() == "Exception") ? ESP.getResetInfo().c_str() : GetResetReason().c_str());
Response_P(PSTR("{\"" D_JSON_RESTARTREASON "\":\"%s\"}"), GetResetReasonInfo().c_str());
MqttPublishPrefixTopic_P(TELE, PSTR(D_RSLT_INFO "3"));
MqttPublishAllPowerState();
if (Settings.tele_period) {
@ -1134,7 +1134,9 @@ void CmndTlsKey(void) {
memcpy(spi_buffer + tls_obj_store_offset + entry->start, bin_buf, entry->len);
}
TlsWriteSpiBuffer(spi_buffer);
if (ESP.flashEraseSector(tls_spi_start_sector)) {
ESP.flashWrite(tls_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) spi_buffer, SPI_FLASH_SEC_SIZE);
}
free(spi_buffer);
free(bin_buf);
}
@ -1146,26 +1148,6 @@ void CmndTlsKey(void) {
}
}
extern "C" {
#include "spi_flash.h"
}
void TlsWriteSpiBuffer(uint8_t *buf) {
bool ret = false;
SpiFlashOpResult res;
noInterrupts();
res = spi_flash_erase_sector(tls_spi_start_sector);
if (SPI_FLASH_RESULT_OK == res) {
res = spi_flash_write(tls_spi_start_sector * SPI_FLASH_SEC_SIZE, (uint32_t*) buf, SPI_FLASH_SEC_SIZE);
if (SPI_FLASH_RESULT_OK == res) {
ret = true;
}
}
interrupts();
}
#ifdef DEBUG_DUMP_TLS
// Dump TLS Flash data - don't activate in production to protect your private keys
uint32_t bswap32(uint32_t x) {

View File

@ -430,7 +430,7 @@ void EnergyMqttShow(void)
}
#endif // USE_ENERGY_MARGIN_DETECTION
void EnergyEverySecond()
void EnergyEverySecond(void)
{
// Overtemp check
if (global_update) {

View File

@ -1621,11 +1621,11 @@ void LightAnimate(void)
}
}
else {
#ifdef PWM_LIGHTSCHEME0_IGNORE_SLEEP
sleep = (LS_POWER == Settings.light_scheme) ? Settings.sleep : 0; // If no animation then use sleep as is
#else
sleep = 0;
#endif // PWM_LIGHTSCHEME0_IGNORE_SLEEP
if (Settings.sleep > 10) {
sleep = 10; // set a minimal value of 50 milliseconds to ensure that animations are smooth
} else {
sleep = Settings.sleep; // or keep the current sleep if it's lower than 50
}
switch (Settings.light_scheme) {
case LS_POWER:
light_controller.calcLevels();

View File

@ -66,7 +66,7 @@ IRrecv *irrecv = nullptr;
unsigned long ir_lasttime = 0;
void IrReceiveUpdateThreshold()
void IrReceiveUpdateThreshold(void)
{
if (irrecv != nullptr) {
if (Settings.param[P_IR_UNKNOW_THRESHOLD] < 6) { Settings.param[P_IR_UNKNOW_THRESHOLD] = 6; }

View File

@ -92,7 +92,7 @@ IRrecv *irrecv = nullptr;
unsigned long ir_lasttime = 0;
void IrReceiveUpdateThreshold()
void IrReceiveUpdateThreshold(void)
{
if (irrecv != nullptr) {
if (Settings.param[P_IR_UNKNOW_THRESHOLD] < 6) { Settings.param[P_IR_UNKNOW_THRESHOLD] = 6; }

View File

@ -80,7 +80,7 @@ int DomoticzRssiQuality(void)
}
#ifdef USE_SONOFF_IFAN
void MqttPublishDomoticzFanState()
void MqttPublishDomoticzFanState(void)
{
if (Settings.flag.mqtt_enabled && Settings.domoticz_relay_idx[1]) { // SetOption3 - Enable MQTT
char svalue[8]; // Fanspeed value
@ -94,7 +94,7 @@ void MqttPublishDomoticzFanState()
}
}
void DomoticzUpdateFanState()
void DomoticzUpdateFanState(void)
{
if (domoticz_update_flag) {
MqttPublishDomoticzFanState();

View File

@ -497,9 +497,7 @@ void CmndLongitude(void)
if (XdrvMailbox.data_len) {
Settings.longitude = (int)(CharToFloat(XdrvMailbox.data) *1000000);
}
char lbuff[33];
dtostrfd(((float)Settings.longitude) /1000000, 6, lbuff);
ResponseCmndChar(lbuff);
ResponseCmndFloat((float)(Settings.longitude) /1000000, 6);
}
void CmndLatitude(void)
@ -507,9 +505,7 @@ void CmndLatitude(void)
if (XdrvMailbox.data_len) {
Settings.latitude = (int)(CharToFloat(XdrvMailbox.data) *1000000);
}
char lbuff[33];
dtostrfd(((float)Settings.latitude) /1000000, 6, lbuff);
ResponseCmndChar(lbuff);
ResponseCmndFloat((float)(Settings.latitude) /1000000, 6);
}
#endif // USE_SUNRISE

View File

@ -1226,7 +1226,7 @@ float evaluateExpression(const char * expression, unsigned int len)
#endif // USE_EXPRESSION
#ifdef SUPPORT_IF_STATEMENT
void CmndIf()
void CmndIf(void)
{
if (XdrvMailbox.data_len > 0) {
char parameters[XdrvMailbox.data_len+1];

View File

@ -43,7 +43,7 @@ bool ifan_restart_flag = true;
/*********************************************************************************************/
bool IsModuleIfan()
bool IsModuleIfan(void)
{
return ((SONOFF_IFAN02 == my_module_type) || (SONOFF_IFAN03 == my_module_type));
}

View File

@ -72,7 +72,7 @@ void Pcf8574SwitchRelay(void)
}
}
void Pcf8574Init()
void Pcf8574Init(void)
{
uint8_t pcf8574_address = PCF8574_ADDR1;
while ((Pcf8574.max_devices < MAX_PCF8574) && (pcf8574_address < PCF8574_ADDR2 +8)) {
@ -178,7 +178,7 @@ void HandlePcf8574(void)
WSContentStop();
}
void Pcf8574SaveSettings()
void Pcf8574SaveSettings(void)
{
char stemp[7];
char tmp[100];

View File

@ -30,12 +30,14 @@
#define XDRV_29 29
#define MAX_DEEPSLEEP_CYCLE 3600 // Maximum time for a deepsleep
#define MIN_DEEPSLEEP_TIME 5
#define D_PRFX_DEEPSLEEP "DeepSleep"
#define D_CMND_DEEPSLEEP_TIME "Time"
const uint32_t DEEPSLEEP_MAX = 10 * 366 * 24 * 60 * 60; // Allow max 10 years sleep
const uint32_t DEEPSLEEP_MAX_CYCLE = 60 * 60; // Maximum time for a deepsleep as defined by chip hardware
const uint32_t DEEPSLEEP_MIN_TIME = 5; // Allow 5 seconds skew
const uint32_t DEEPSLEEP_START_COUNTDOWN = 4; // Allow 4 seconds to update web console before deepsleep
const char kDeepsleepCommands[] PROGMEM = D_PRFX_DEEPSLEEP "|"
D_CMND_DEEPSLEEP_TIME ;
@ -47,28 +49,29 @@ uint8_t deepsleep_flag = 0;
bool DeepSleepEnabled(void)
{
if (Settings.deepsleep < 10) {
return false;
if ((Settings.deepsleep < 10) || (Settings.deepsleep > DEEPSLEEP_MAX)) {
Settings.deepsleep = 0; // Issue #6961
return false; // Disabled
}
if (pin[GPIO_DEEPSLEEP] < 99) {
pinMode(pin[GPIO_DEEPSLEEP], INPUT_PULLUP);
return (digitalRead(pin[GPIO_DEEPSLEEP])); // Disable DeepSleep if user holds pin GPIO_DEEPSLEEP low
return (digitalRead(pin[GPIO_DEEPSLEEP])); // Disable DeepSleep if user holds pin GPIO_DEEPSLEEP low
}
return true;
return true; // Enabled
}
void DeepSleepInit(void)
void DeepSleepReInit(void)
{
if (DeepSleepEnabled()) {
RtcRebootReset();
if ((RtcSettings.ultradeepsleep > MAX_DEEPSLEEP_CYCLE) && (RtcSettings.ultradeepsleep < 1700000000)) {
if ((ResetReason() == REASON_DEEP_SLEEP_AWAKE) && DeepSleepEnabled()) {
if ((RtcSettings.ultradeepsleep > DEEPSLEEP_MAX_CYCLE) && (RtcSettings.ultradeepsleep < 1700000000)) {
// Go back to sleep after 60 minutes if requested deepsleep has not been reached
RtcSettings.ultradeepsleep = RtcSettings.ultradeepsleep - MAX_DEEPSLEEP_CYCLE;
RtcSettings.ultradeepsleep = RtcSettings.ultradeepsleep - DEEPSLEEP_MAX_CYCLE;
AddLog_P2(LOG_LEVEL_ERROR, PSTR("DSL: Remain DeepSleep %d"), RtcSettings.ultradeepsleep);
RtcSettingsSave();
ESP.deepSleep(100 * RtcSettings.deepsleep_slip * (MAX_DEEPSLEEP_CYCLE < RtcSettings.ultradeepsleep ? MAX_DEEPSLEEP_CYCLE : RtcSettings.ultradeepsleep), WAKE_RF_DEFAULT);
RtcRebootReset();
ESP.deepSleep(100 * RtcSettings.deepsleep_slip * (DEEPSLEEP_MAX_CYCLE < RtcSettings.ultradeepsleep ? DEEPSLEEP_MAX_CYCLE : RtcSettings.ultradeepsleep), WAKE_RF_DEFAULT);
yield();
// Sleeping
}
@ -77,7 +80,7 @@ void DeepSleepInit(void)
RtcSettings.ultradeepsleep = 0;
}
void DeepSleepCheck(void)
void DeepSleepPrepare(void)
{
// Deepsleep_slip is ideally 10.000 == 100%
// Typically the device has up to 4% slip. Anything else is a wrong setting in the deepsleep_slip
@ -87,8 +90,7 @@ void DeepSleepCheck(void)
(RtcSettings.deepsleep_slip < 9000) ||
(RtcSettings.deepsleep_slip > 11000) ||
(RtcSettings.nextwakeup > (UtcTime() + Settings.deepsleep))) {
AddLog_P2(LOG_LEVEL_ERROR, PSTR("DSL: Reset wrong settings wakeup: %ld, slip %ld"),
RtcSettings.nextwakeup, RtcSettings.deepsleep_slip );
AddLog_P2(LOG_LEVEL_ERROR, PSTR("DSL: Reset wrong settings wakeup: %ld, slip %ld"), RtcSettings.nextwakeup, RtcSettings.deepsleep_slip );
RtcSettings.nextwakeup = 0;
RtcSettings.deepsleep_slip = 10000;
}
@ -109,15 +111,15 @@ void DeepSleepCheck(void)
// It may happen that wakeup in just <5 seconds in future
// In this case also add deepsleep to nextwakeup
if (RtcSettings.nextwakeup <= (UtcTime() - MIN_DEEPSLEEP_TIME)) {
if (RtcSettings.nextwakeup <= (UtcTime() - DEEPSLEEP_MIN_TIME)) {
// ensure nextwakeup is at least in the future
RtcSettings.nextwakeup += (((UtcTime() + MIN_DEEPSLEEP_TIME - RtcSettings.nextwakeup) / Settings.deepsleep) + 1) * Settings.deepsleep;
RtcSettings.nextwakeup += (((UtcTime() + DEEPSLEEP_MIN_TIME - RtcSettings.nextwakeup) / Settings.deepsleep) + 1) * Settings.deepsleep;
}
String dt = GetDT(RtcSettings.nextwakeup + LocalTime() - UtcTime()); // 2017-03-07T11:08:02
// Limit sleeptime to MAX_DEEPSLEEP_CYCLE
// uint32_t deepsleep_sleeptime = MAX_DEEPSLEEP_CYCLE < (RtcSettings.nextwakeup - UtcTime()) ? (uint32_t)MAX_DEEPSLEEP_CYCLE : RtcSettings.nextwakeup - UtcTime();
deepsleep_sleeptime = tmin((uint32_t)MAX_DEEPSLEEP_CYCLE ,RtcSettings.nextwakeup - UtcTime());
// Limit sleeptime to DEEPSLEEP_MAX_CYCLE
// uint32_t deepsleep_sleeptime = DEEPSLEEP_MAX_CYCLE < (RtcSettings.nextwakeup - UtcTime()) ? (uint32_t)DEEPSLEEP_MAX_CYCLE : RtcSettings.nextwakeup - UtcTime();
deepsleep_sleeptime = tmin((uint32_t)DEEPSLEEP_MAX_CYCLE ,RtcSettings.nextwakeup - UtcTime());
// stat/tasmota/STATUS = {"DeepSleep":{"Time":"2019-11-12T21:33:45","Epoch":1573590825}}
Response_P(PSTR("{\"" D_PRFX_DEEPSLEEP "\":{\"" D_JSON_TIME "\":\"%s\",\"Epoch\":%d}}"), (char*)dt.c_str(), RtcSettings.nextwakeup);
@ -144,9 +146,9 @@ void DeepSleepEverySecond(void)
if (!deepsleep_flag) { return; }
if (DeepSleepEnabled()) {
if (4 == deepsleep_flag) { // Allow 4 seconds to update web console before deepsleep
if (DEEPSLEEP_START_COUNTDOWN == deepsleep_flag) { // Allow 4 seconds to update web console before deepsleep
SettingsSaveAll();
DeepSleepCheck();
DeepSleepPrepare();
}
deepsleep_flag--;
if (deepsleep_flag <= 0) {
@ -164,10 +166,10 @@ void DeepSleepEverySecond(void)
void CmndDeepsleepTime(void)
{
if ((0 == XdrvMailbox.payload) ||
((XdrvMailbox.payload > 10) && (XdrvMailbox.payload < (10 * 366 * 24 * 60 * 60)))) { // Allow max 10 years sleep
((XdrvMailbox.payload > 10) && (XdrvMailbox.payload < DEEPSLEEP_MAX))) {
Settings.deepsleep = XdrvMailbox.payload;
RtcSettings.nextwakeup = 0;
deepsleep_flag = (0 == XdrvMailbox.payload) ? 0 : 4;
deepsleep_flag = (0 == XdrvMailbox.payload) ? 0 : DEEPSLEEP_START_COUNTDOWN;
if (deepsleep_flag) {
if (!Settings.tele_period) {
Settings.tele_period = TELE_PERIOD; // Need teleperiod to go back to sleep
@ -190,15 +192,15 @@ bool Xdrv29(uint8_t function)
DeepSleepEverySecond();
break;
case FUNC_AFTER_TELEPERIOD:
if (!deepsleep_flag) {
deepsleep_flag = 4; // Start deepsleep in 4 seconds
if (DeepSleepEnabled() && !deepsleep_flag) {
deepsleep_flag = DEEPSLEEP_START_COUNTDOWN; // Start deepsleep in 4 seconds
}
break;
case FUNC_COMMAND:
result = DecodeCommand(kDeepsleepCommands, DeepsleepCommand);
break;
case FUNC_PRE_INIT:
DeepSleepInit();
DeepSleepReInit();
break;
}
return result;

View File

@ -75,7 +75,10 @@ const char kDebugCommands[] PROGMEM = "|" // No prefix
D_CMND_EXCEPTION "|"
#endif
D_CMND_FLASHDUMP "|" D_CMND_FLASHMODE "|" D_CMND_FREEMEM"|" D_CMND_HELP "|" D_CMND_RTCDUMP "|" D_CMND_SETSENSOR "|"
D_CMND_I2CWRITE "|" D_CMND_I2CREAD "|" D_CMND_I2CSTRETCH "|" D_CMND_I2CCLOCK ;
#ifdef USE_I2C
D_CMND_I2CWRITE "|" D_CMND_I2CREAD "|" D_CMND_I2CSTRETCH "|" D_CMND_I2CCLOCK
#endif
;
void (* const DebugCommand[])(void) PROGMEM = {
&CmndCfgDump, &CmndCfgPeek, &CmndCfgPoke,
@ -90,7 +93,10 @@ void (* const DebugCommand[])(void) PROGMEM = {
&CmndException,
#endif
&CmndFlashDump, &CmndFlashMode, &CmndFreemem, &CmndHelp, &CmndRtcDump, &CmndSetSensor,
&CmndI2cWrite, &CmndI2cRead, &CmndI2cStretch, &CmndI2cClock };
#ifdef USE_I2C
&CmndI2cWrite, &CmndI2cRead, &CmndI2cStretch, &CmndI2cClock
#endif
};
uint32_t CPU_loops = 0;
uint32_t CPU_last_millis = 0;
@ -575,6 +581,7 @@ void CmndFlashDump(void)
ResponseCmndDone();
}
#ifdef USE_I2C
void CmndI2cWrite(void)
{
// I2cWrite <address>,<data>..
@ -652,6 +659,7 @@ void CmndI2cClock(void)
}
ResponseCmndDone();
}
#endif // USE_I2C
/*********************************************************************************************\
* Interface

View File

@ -47,7 +47,7 @@ extern uint8_t *buffer;
/*********************************************************************************************/
void SSD1306InitDriver()
void SSD1306InitDriver(void)
{
if (!Settings.display_model) {
if (I2cSetDevice(OLED_ADDRESS1)) {

View File

@ -185,7 +185,7 @@ void Ade7953GetData(void)
}
}
void Ade7953EnergyEverySecond()
void Ade7953EnergyEverySecond(void)
{
if (Ade7953.init_step) {
if (1 == Ade7953.init_step) {

View File

@ -201,7 +201,7 @@ uint16_t solaxX1_calculateCRC(uint8_t *bExternTxPackage, uint8_t bLen)
return wChkSum;
}
void solaxX1_SendInverterAddress()
void solaxX1_SendInverterAddress(void)
{
source[0] = 0x00;
destination[0] = 0x00;
@ -213,7 +213,7 @@ void solaxX1_SendInverterAddress()
solaxX1_RS485Send(24);
}
void solaxX1_QueryLiveData()
void solaxX1_QueryLiveData(void)
{
source[0] = 0x01;
destination[0] = 0x00;

View File

@ -101,7 +101,7 @@ void AdcEvery250ms(void)
}
#endif // USE_RULES
uint16_t AdcGetLux()
uint16_t AdcGetLux(void)
{
int adc = AdcRead(2);
// Source: https://www.allaboutcircuits.com/projects/design-a-luxmeter-using-a-light-dependent-resistor/

View File

@ -90,7 +90,7 @@ bool HxIsReady(uint16_t timeout)
return (digitalRead(Hx.pin_dout) == LOW);
}
long HxRead()
long HxRead(void)
{
if (!HxIsReady(HX_TIMEOUT)) { return -1; }
@ -241,7 +241,7 @@ bool HxCommand(void)
/*********************************************************************************************/
long HxWeight()
long HxWeight(void)
{
return (Hx.calibrate_step < HX_CAL_FAIL) ? Hx.weight : 0;
}
@ -371,7 +371,7 @@ void HxEvery100mSecond(void)
}
}
void HxSaveBeforeRestart()
void HxSaveBeforeRestart(void)
{
Settings.energy_frequency_calibration = Hx.weight;
Hx.sample_count = HX_SAMPLES +1; // Stop updating Hx.weight

View File

@ -6,7 +6,7 @@
<li>can restore previously backup and changed <a href="http://www.json.org/">JSON</a>-format files,</li>
<li>is able to create Tasmota compatible command list with related config parameter</li>
</ul>
<p>Comparing backup files created by <em>decode-config.py</em> and *.dmp files created by Tasmota &quot;Backup/Restore Configuration&quot;: </p>
<p>Comparing backup files created by <em>decode-config.py</em> and *.dmp files created by Tasmota &quot;Backup/Restore Configuration&quot;:</p>
<table>
<thead>
<tr>
@ -75,23 +75,39 @@
</ul>
<h2 id="prerequisite">Prerequisite</h2>
<ul>
<li><p><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 working python environment (for details see <a href="https://docs.python.org/2.7/using/index.html">Python Setup and Usage</a>)</p>
</li>
<li><p><a href="https://github.com/arendst/Tasmota">Tasmota</a> <a href="https://github.com/arendst/Tasmota/releases">Firmware</a> with Web-Server enabled:</p>
<ul>
<li>This program is written in <a href="https://en.wikipedia.org/wiki/Python_(programming_language">Python</a>) so you need to install a working python environment for your operating system.</li>
</ul>
<h3 id="linux">Linux</h3>
<pre><code>sudo apt-<span class="hljs-built_in">get</span> install python python-pip libcurl4-openssl-<span class="hljs-built_in">dev</span> libssl-<span class="hljs-built_in">dev</span>
</code></pre><pre><code>pip <span class="hljs-keyword">install</span> pycurl configargparse
</code></pre><h3 id="windows-10">Windows 10</h3>
<p>Install <a href="https://www.python.org/download/releases/2.7/">Python 2.7</a> then install dependencies. For PyCurl you need to <a href="https://www.lfd.uci.edu/~gohlke/pythonlibs/#pycurl">download pycurl7.43.0.3cp27cp27mwin_amd64.whl</a> for Windows 10 64bit.</p>
<pre><code>pip install pycurl<span class="hljs-number">-7.43</span><span class="hljs-number">.0</span><span class="hljs-number">.3</span>-cp27-cp27m-win_amd64.whl configargparse
<span class="hljs-comment">// run the command from the folder where you downloaded the file</span>
pip install configargparse
</code></pre><ul>
<li><a href="https://github.com/arendst/Tasmota">Tasmota</a> <a href="https://github.com/arendst/Tasmota/releases">Firmware</a> with Web-Server enabled:<ul>
<li>To backup or restore configurations from or to a Tasmota device you need a firmare with enabled web-server in admin mode (command <a href="https://github.com/arendst/Tasmota/wiki/Commands#wifi">WebServer 2</a>). This is the Tasmota default.</li>
<li>If using your own compiled firmware be aware to enable the web-server (<code>#define USE_WEBSERVER</code> and <code>#define WEB_SERVER 2</code>).</li>
</ul>
</li>
</ul>
<h2 id="file-types">File Types</h2>
<p><em>decode-config.py</em> can handle the following backup file types: </p>
<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 &quot;Backup/Restore Configuration&quot; web interface.<br>This format is binary and encrypted.</p>
<p>Configuration data as used by Tasmota &quot;Backup/Restore Configuration&quot; web interface.
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> parameter.<br>This file will be created by <em>decode-config.py</em> using the <code>--backup-file</code> with <code>--backup-type json</code> parameter, this is the default.</p>
<p>Configuration data in <a href="http://www.json.org/">JSON</a>-format.
This format is decrypted, human readable and editable and can also be used for the <code>--restore-file</code> parameter.
This file will be created by <em>decode-config.py</em> using the <code>--backup-file</code> with <code>--backup-type json</code> parameter, this is the 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>The .bin file contains the same information as the original .dmp file from Tasmota &quot;Backup/Restore Configuration&quot; but it is decrpted and 4 byte longer than an original (it is a prefix header at the beginning). .bin file data starting at address 4 contains the same as the <strong>struct SYSCFG</strong> from Tasmota <a href="https://github.com/arendst/Tasmota/blob/master/sonoff/settings.h">settings.h</a> in decrypted format.</p>
<p>Configuration data in binary format.
This format is binary decryptet, editable (e.g. using a hex editor) and can also be used for <code>--restore-file</code> command.
It will be created by <em>decode-config.py</em> using <code>--backup-file</code> with <code>--backup-type bin</code>.
Note:
The .bin file contains the same information as the original .dmp file from Tasmota &quot;Backup/Restore Configuration&quot; but it is decrpted and 4 byte longer than an original (it is a prefix header at the beginning). .bin file data starting at address 4 contains the same as the <strong>struct SYSCFG</strong> from Tasmota <a href="https://github.com/arendst/Tasmota/blob/master/tasmota/settings.h">settings.h</a> in decrypted format.</p>
<h4 id="file-extensions">File extensions</h4>
<p>You don&#39;t need to append exensions for your file name as <em>decode-config.py</em> uses auto extension as default. The extension will be choose based on file contents and <code>--backup-type</code> parameter.
If you do not want using auto extensions use the <code>--no-extension</code> parameter.</p>
@ -99,13 +115,13 @@ If you do not want using auto extensions use the <code>--no-extension</code> par
<p>After download don&#39;t forget to set the executable 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 &lt;filename&gt;</code> or <code>-d &lt;host&gt;</code>:</p>
<p>The source can be either </p>
<p>The source can be either</p>
<ul>
<li>a Tasmota device hostname or IP using the <code>-d &lt;host&gt;</code> parameter</li>
<li>a Tasmota <code>*.dmp</code> configuration file using <code>-f &lt;filename&gt;</code> parameter</li>
</ul>
<p>Example: </p>
<pre><code>decode-config<span class="hljs-selector-class">.py</span> -d sonoff-<span class="hljs-number">4281</span>
<p>Example:</p>
<pre><code>decode-config<span class="hljs-selector-class">.py</span> -d tasmota-<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>,
@ -120,24 +136,24 @@ If you do not want using auto extensions use the <code>--no-extension</code> par
]
}
</code></pre><h3 id="save-backup-file">Save backup file</h3>
<p>To save the output as backup file use <code>--backup-file &lt;filename&gt;</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>
<p>To save the output as backup file use <code>--backup-file &lt;filename&gt;</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">tasmota-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> &lt;yourpassword&gt; --backup-file Config_@f_@v
</code></pre><p>will create a file like <code>Config_Sonoff_6.4.0.json</code> (the part <code>Sonoff</code> and <code>6.4.0</code> will choosen related to your device configuration). Because the default backup file format is JSON, you can read and change it with any raw text editor.</p>
<pre><code>decode-config<span class="hljs-selector-class">.py</span> -d tasmota-<span class="hljs-number">4281</span> -<span class="hljs-selector-tag">p</span> &lt;yourpassword&gt; --backup-file Config_@f_@v
</code></pre><p>will create a file like <code>Config_Tasmota_6.4.0.json</code> (the part <code>Tasmota</code> and <code>6.4.0</code> will choosen related to your device configuration). Because the default backup file format is JSON, you can read and change it 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 &lt;filename&gt;</code> parameter. 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>
<p>To restore the previously save backup file <code>Config_Tasmota_6.2.1.json</code> to device <code>tasmota-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">tasmota-4281</span> <span class="hljs-selector-tag">--restore-file</span> <span class="hljs-selector-tag">Config_Tasmota_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> &lt;<span class="hljs-selector-tag">yourpassword</span>&gt; <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>
<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">tasmota-4281</span> <span class="hljs-selector-tag">-p</span> &lt;<span class="hljs-selector-tag">yourpassword</span>&gt; <span class="hljs-selector-tag">--restore-file</span> <span class="hljs-selector-tag">Config_Tasmota_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="output-to-screen">Output to screen</h3>
<p>To force screen output use the <code>--output</code> parameter.</p>
<p>Output to screen is default enabled when calling the program with a source parameter (-f or -d) but without any backup or restore parameter.</p>
<h4 id="json-output">JSON output</h4>
<p>The default output format is <a href="decode-config.md#-json-format">JSON</a>. You can force JSON output using the <code>--output-format json</code> parameter.</p>
<p>Example:</p>
<pre><code>decode-config.py -d sonoff<span class="hljs-number">-4281</span> -c my.conf -x <span class="hljs-symbol">Wifi</span> --output-format json
<pre><code>decode-config.py -d tasmota<span class="hljs-number">-4281</span> -c my.conf -x <span class="hljs-symbol">Wifi</span> --output-format json
{
...
@ -171,7 +187,7 @@ If you do not want using auto extensions use the <code>--no-extension</code> par
<h4 id="tasmota-command-output">Tasmota command output</h4>
<p><em>decode-config.py</em> is able to translate the configuration data to (most all) Tasmota commands. To output your configuration as Tasmota commands use <code>--output-format cmnd</code> or <code>--output-format command</code>.</p>
<p>Example:</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">-g</span> <span class="hljs-selector-tag">Wifi</span> <span class="hljs-selector-tag">--output-format</span> <span class="hljs-selector-tag">cmnd</span>
<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">tasmota-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">-g</span> <span class="hljs-selector-tag">Wifi</span> <span class="hljs-selector-tag">--output-format</span> <span class="hljs-selector-tag">cmnd</span>
# <span class="hljs-selector-tag">Wifi</span>:
<span class="hljs-selector-tag">AP</span> 0
@ -192,11 +208,11 @@ If you do not want using auto extensions use the <code>--no-extension</code> par
<span class="hljs-selector-tag">WifiConfig</span> 5
</code></pre><p>Note: A few very specific module commands like MPC230xx, KNX and some Display commands are not supported. These are still available by JSON output.</p>
<h3 id="filter-data">Filter data</h3>
<p>The huge number of Tasmota configuration data can be overstrained and confusing, so the most of the configuration data are grouped into categories. </p>
<p>With <em>decode-config.py</em> the following categories are available: <code>Display</code>, <code>Domoticz</code>, <code>Internal</code>, <code>KNX</code>, <code>Led</code>, <code>Logging</code>, <code>MCP230xx</code>, <code>MQTT</code>, <code>Main</code>, <code>Management</code>, <code>Pow</code>, <code>Sensor</code>, <code>Serial</code>, <code>SetOption</code>, <code>SonoffRF</code>, <code>System</code>, <code>Timers</code>, <code>Wifi</code></p>
<p>The huge number of Tasmota configuration data can be overstrained and confusing, so the most of the configuration data are grouped into categories.</p>
<p>With <em>decode-config.py</em> the following categories are available: <code>Display</code>, <code>Domoticz</code>, <code>Internal</code>, <code>KNX</code>, <code>Led</code>, <code>Logging</code>, <code>MCP230xx</code>, <code>MQTT</code>, <code>Main</code>, <code>Management</code>, <code>Pow</code>, <code>Sensor</code>, <code>Serial</code>, <code>SetOption</code>, <code>RF</code>, <code>System</code>, <code>Timers</code>, <code>Wifi</code></p>
<p>These are similary to the categories on <a href="Tasmota Command Wiki">https://github.com/arendst/Tasmota/wiki/Commands</a>.</p>
<p>To filter outputs to a subset of groups use the <code>-g</code> or <code>--group</code> arg concatenating the grooup you want, e. g.</p>
<pre><code>decode-config<span class="hljs-selector-class">.py</span> -d sonoff-<span class="hljs-number">4281</span> -c my<span class="hljs-selector-class">.conf</span> --output-format cmnd --group Main MQTT Management Wifi
<pre><code>decode-config<span class="hljs-selector-class">.py</span> -d tasmota-<span class="hljs-number">4281</span> -c my<span class="hljs-selector-class">.conf</span> --output-format cmnd --group Main MQTT Management Wifi
</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>
@ -206,7 +222,7 @@ If you do not want using auto extensions use the <code>--no-extension</code> par
<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>
<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">tasmota-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 each short written arg (minus sign <code>-</code>) has a corresponding 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>
@ -219,7 +235,7 @@ If you do not want using auto extensions use the <code>--no-extension</code> par
[--cmnd-indent &lt;indent&gt;] [--cmnd-groups]
[--cmnd-nogroups] [--cmnd-<span class="hljs-keyword">sort</span>] [--cmnd-unsort]
[-c &lt;filename&gt;] [-S] [-T json|cmnd|command]
[-g {Control,Devices,Display,Domoticz,Internal,KNX,Light,MQTT,Management,Power,Rules,Sensor,Serial,SetOption,SonoffRF,System,Timer,Wifi} [{Control,Devices,Display,Domoticz,Internal,KNX,Light,MQTT,Management,Power,Rules,Sensor,Serial,SetOption,SonoffRF,System,Timer,Wifi} ...]]
[-<span class="hljs-keyword">g</span> {Control,Devices,<span class="hljs-keyword">Display</span>,Domoticz,Internal,Knx,Light,Management,Mqtt,Power,Rf,Rules,Sensor,Serial,Setoption,Shutter,System,<span class="hljs-keyword">Timer</span>,Wifi} [{Control,Devices,<span class="hljs-keyword">Display</span>,Domoticz,Internal,Knx,Light,Management,Mqtt,Power,Rf,Rules,Sensor,Serial,Setoption,Shutter,System,<span class="hljs-keyword">Timer</span>,Wifi} ...]]
[--ignore-warnings] [-<span class="hljs-keyword">h</span>] [-<span class="hljs-keyword">H</span>] [-v] [-V]
Backup/<span class="hljs-keyword">Restore</span> Tasmota configuration data. <span class="hljs-keyword">Args</span> that start with '--'
@ -299,7 +315,7 @@ Common:
(default <span class="hljs-keyword">do</span> not output <span class="hljs-keyword">on</span> backup or <span class="hljs-keyword">restore</span> usage)
-T, --output-<span class="hljs-keyword">format</span> json|cmnd|command
<span class="hljs-keyword">display</span> output <span class="hljs-keyword">format</span> (default: 'json')
-g, --group {Control,Devices,Display,Domoticz,Internal,Knx,Light,Management,Mqtt,Power,Rules,Sensor,Serial,Setoption,Shutter,Sonoffrf,System,Timer,Wifi}
-<span class="hljs-keyword">g</span>, --group {Control,Devices,<span class="hljs-keyword">Display</span>,Domoticz,Internal,Knx,Light,Management,Mqtt,Power,Rf,Rules,Sensor,Serial,Setoption,Shutter,System,<span class="hljs-keyword">Timer</span>,Wifi}
limit data processing to command groups (default <span class="hljs-keyword">no</span>
filter)
--ignore-warnings <span class="hljs-keyword">do</span> not <span class="hljs-keyword">exit</span> <span class="hljs-keyword">on</span> warnings. Not recommended, used <span class="hljs-keyword">by</span> your
@ -331,26 +347,29 @@ 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>
<p> <code>decode-config.py -c my.conf -d tasmota --restore-file Config_Tasmota_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> <code>decode-config.py -c my.conf -d tasmota --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>
<p> <code>decode-config.py -c my.conf -d tasmota --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>
<pre><code><span class="hljs-keyword">for</span> device <span class="hljs-keyword">in</span> tasmota1 tasmota2 tasmota3; <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>
<pre><code><span class="hljs-keyword">for</span> device <span class="hljs-keyword">in</span> (tasmota1 tasmota2 tasmota3) <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 tasmota1, tasmota2 and tasmota3 using friendly name and Tasmota firmware version for backup filenames.</p>
<h2 id="notes">Notes</h2>
<p>Some general notes:</p>
<ul>
<li>Filename replacement macros <strong>@h</strong> and <strong>@H</strong>:<ul>
<li><strong>@h</strong><br>The <strong>@h</strong> replacement macro uses the hostname configured with the Tasomta Wifi <code>Hostname &lt;host&gt;</code> command (defaults to <code>%s-%04d</code>). It will not use the network hostname of your device because this is not available when working with files only (e.g. <code>--file &lt;filename&gt;</code> as source).<br>To prevent having a useless % in your filename, <strong>@h</strong> will not replaced by configuration data hostname if this contains &#39;%&#39; characters.</li>
<li><strong>@H</strong><br>If you want to use the network hostname within your filename, use the <strong>@H</strong> replacement macro instead - but be aware this will only replaced if you are using a network device as source (<code>-d</code>, <code>--device</code>, <code>--host</code>); it will not work when using a file as source (<code>-f</code>, <code>--file</code>)</li>
<li><strong>@h</strong>
The <strong>@h</strong> replacement macro uses the hostname configured with the Tasomta Wifi <code>Hostname &lt;host&gt;</code> command (defaults to <code>%s-%04d</code>). It will not use the network hostname of your device because this is not available when working with files only (e.g. <code>--file &lt;filename&gt;</code> as source).
To prevent having a useless % in your filename, <strong>@h</strong> will not replaced by configuration data hostname if this contains &#39;%&#39; characters.</li>
<li><strong>@H</strong>
If you want to use the network hostname within your filename, use the <strong>@H</strong> replacement macro instead - but be aware this will only replaced if you are using a network device as source (<code>-d</code>, <code>--device</code>, <code>--host</code>); it will not work when using a file as source (<code>-f</code>, <code>--file</code>)</li>
</ul>
</li>
</ul>

View File

@ -211,7 +211,7 @@ Note: A few very specific module commands like MPC230xx, KNX and some Display co
### Filter data
The huge number of Tasmota configuration data can be overstrained and confusing, so the most of the configuration data are grouped into categories.
With _decode-config.py_ the following categories are available: `Display`, `Domoticz`, `Internal`, `KNX`, `Led`, `Logging`, `MCP230xx`, `MQTT`, `Main`, `Management`, `Pow`, `Sensor`, `Serial`, `SetOption`, `SonoffRF`, `System`, `Timers`, `Wifi`
With _decode-config.py_ the following categories are available: `Display`, `Domoticz`, `Internal`, `KNX`, `Led`, `Logging`, `MCP230xx`, `MQTT`, `Main`, `Management`, `Pow`, `Sensor`, `Serial`, `SetOption`, `RF`, `System`, `Timers`, `Wifi`
These are similary to the categories on [https://github.com/arendst/Tasmota/wiki/Commands](Tasmota Command Wiki).
@ -254,7 +254,7 @@ For advanced help use `-H` or `--full-help`:
[--cmnd-indent <indent>] [--cmnd-groups]
[--cmnd-nogroups] [--cmnd-sort] [--cmnd-unsort]
[-c <filename>] [-S] [-T json|cmnd|command]
[-g {Control,Devices,Display,Domoticz,Internal,Knx,Light,Management,Mqtt,Power,Rules,Sensor,Serial,Setoption,Shutter,Sonoffrf,System,Timer,Wifi} [{Control,Devices,Display,Domoticz,Internal,Knx,Light,Management,Mqtt,Power,Rules,Sensor,Serial,Setoption,Shutter,Sonoffrf,System,Timer,Wifi} ...]]
[-g {Control,Devices,Display,Domoticz,Internal,Knx,Light,Management,Mqtt,Power,Rf,Rules,Sensor,Serial,Setoption,Shutter,System,Timer,Wifi} [{Control,Devices,Display,Domoticz,Internal,Knx,Light,Management,Mqtt,Power,Rf,Rules,Sensor,Serial,Setoption,Shutter,System,Timer,Wifi} ...]]
[--ignore-warnings] [-h] [-H] [-v] [-V]
Backup/Restore Tasmota configuration data. Args that start with '--'
@ -334,7 +334,7 @@ For advanced help use `-H` or `--full-help`:
(default do not output on backup or restore usage)
-T, --output-format json|cmnd|command
display output format (default: 'json')
-g, --group {Control,Devices,Display,Domoticz,Internal,Knx,Light,Management,Mqtt,Power,Rules,Sensor,Serial,Setoption,Shutter,Sonoffrf,System,Timer,Wifi}
-g, --group {Control,Devices,Display,Domoticz,Internal,Knx,Light,Management,Mqtt,Power,Rf,Rules,Sensor,Serial,Setoption,Shutter,System,Timer,Wifi}
limit data processing to command groups (default no
filter)
--ignore-warnings do not exit on warnings. Not recommended, used by your

View File

@ -1,6 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
VER = '2.3.0036'
from __future__ import print_function
VER = '2.4.0037'
"""
decode-config.py - Backup/Restore Tasmota configuration data
@ -43,7 +44,7 @@ Usage: decode-config.py [-f <filename>] [-d <host>] [-P <port>]
[--cmnd-indent <indent>] [--cmnd-groups]
[--cmnd-nogroups] [--cmnd-sort] [--cmnd-unsort]
[-c <filename>] [-S] [-T json|cmnd|command]
[-g {Control,Devices,Display,Domoticz,Internal,Knx,Light,Management,Mqtt,Power,Rules,Sensor,Serial,Setoption,Shutter,Sonoffrf,System,Timer,Wifi} [{Control,Devices,Display,Domoticz,Internal,Knx,Light,Management,Mqtt,Power,Rules,Sensor,Serial,Setoption,Shutter,Sonoffrf,System,Timer,Wifi} ...]]
[-g {Control,Devices,Display,Domoticz,Internal,Knx,Light,Management,Mqtt,Power,Rules,Sensor,Serial,Setoption,Shutter,Rf,System,Timer,Wifi} [{Control,Devices,Display,Domoticz,Internal,Knx,Light,Management,Mqtt,Power,Rules,Sensor,Serial,Setoption,Shutter,Rf,System,Timer,Wifi} ...]]
[--ignore-warnings] [-h] [-H] [-v] [-V]
Backup/Restore Tasmota configuration data. Args that start with '--'
@ -123,7 +124,7 @@ Usage: decode-config.py [-f <filename>] [-d <host>] [-P <port>]
(default do not output on backup or restore usage)
-T, --output-format json|cmnd|command
display output format (default: 'json')
-g, --group {Control,Devices,Display,Domoticz,Internal,Knx,Light,Management,Mqtt,Power,Rules,Sensor,Serial,Setoption,Shutter,Sonoffrf,System,Timer,Wifi}
-g, --group {Control,Devices,Display,Domoticz,Internal,Knx,Light,Management,Mqtt,Power,Rules,Sensor,Serial,Setoption,Shutter,Rf,System,Timer,Wifi}
limit data processing to command groups (default no
filter)
--ignore-warnings do not exit on warnings. Not recommended, used by your
@ -184,7 +185,7 @@ import io
import sys, platform
def ModuleImportError(module):
er = str(module)
print >> sys.stderr, "{}. Try 'pip install {}' to install it".format(er,er.split(' ')[len(er.split(' '))-1])
print('{}, try "pip install {}"'.format(er,er.split(' ')[len(er.split(' '))-1]), file=sys.stderr)
sys.exit(ExitCode.MODULE_NOT_FOUND)
try:
from datetime import datetime
@ -198,8 +199,11 @@ try:
import json
import configargparse
import pycurl
import urllib2
except ImportError, e:
if sys.version_info.major==2:
import urllib2
else:
import urllib
except ImportError as e:
ModuleImportError(e)
# ======================================================================
@ -276,7 +280,7 @@ Settings dictionary describes the config file fields definition:
defines the use of data at <addrdef>
format is defined in 'struct module format string'
see
https://docs.python.org/2.7/library/struct.html#format-strings
https://docs.python.org/3.8/library/struct.html#format-strings
<setting>: <setting>
A dictionary describes a (sub)setting dictonary
and can recursively define another <setting>
@ -556,7 +560,7 @@ Setting_5_10_0 = {
'pulse_counter_type4': ('<H', (0x5D0,1,3), (None, None, ('Sensor', '"CounterType4 {}".format($)')) ),
}, 0x5D0, (None, None, ('Sensor', None)), (None, None) ),
'pulse_counter_debounce': ('<H', 0x5D2, (None, '0 <= $ <= 3200', ('Sensor', '"CounterDebounce {}".format($)')) ),
'rf_code': ('B', 0x5D4, ([17,9],None, ('SonoffRF', None)), '"0x{:02x}".format($)'),
'rf_code': ('B', 0x5D4, ([17,9],None, ('Rf', None)), '"0x{:02x}".format($)'),
}
# ======================================================================
Setting_5_11_0 = copy.deepcopy(Setting_5_10_0)
@ -1043,8 +1047,8 @@ Setting_6_6_0_14.update ({
'mqttlog_level': ('B', 0x1E7, (None, None, ('Management', '"MqttLog {}".format($)')) ),
'pcf8574_config': ('B', 0xE88, ([8], None, ('Devices', None)) ),
'shutter_accuracy': ('B', 0x1E6, (None, None, ('Shutter', None)) ),
'shutter_opentime': ('<H', 0xE40, ([4], None, ('Shutter', '"ShutterOpenDuration{} {:.1f}".format(#,$/10)')) ),
'shutter_closetime': ('<H', 0xE48, ([4], None, ('Shutter', '"ShutterCloseDuration{} {:.1f}".format(#,$/10)')) ),
'shutter_opentime': ('<H', 0xE40, ([4], None, ('Shutter', '"ShutterOpenDuration{} {:.1f}".format(#,$/10.0)')) ),
'shutter_closetime': ('<H', 0xE48, ([4], None, ('Shutter', '"ShutterCloseDuration{} {:.1f}".format(#,$/10.0)')) ),
'shuttercoeff': ('<H', 0xE50, ([5,4],None, ('Shutter', None)) ),
'shutter_invert': ('B', 0xE78, ([4], None, ('Shutter', '"ShutterInvert{} {}".format(#,$)')) ),
'shutter_set50percent': ('B', 0xE7C, ([4], None, ('Shutter', '"ShutterSetHalfway{} {}".format(#,$)')) ),
@ -1081,7 +1085,55 @@ Setting_6_6_0_20.update ({
'energy_power_delta': ('<H', 0xE98, (None, '0 <= $ < 32000', ('Power', '"PowerDelta {}".format($)')) ),
})
# ======================================================================
Setting_6_6_0_21 = copy.deepcopy(Setting_6_6_0_20)
Setting_6_6_0_21['flag'][0].pop('value_units',None)
Setting_6_6_0_21['flag3'][0].pop('tuya_dimmer_range_255',None)
Setting_6_6_0_21['flag3'][0].update ({
'tuya_serial_mqtt_publish': ('<L', (0x3A0,1,16), (None, None, ('SetOption', '"SetOption66 {}".format($)')) ),
})
# ======================================================================
Setting_7_0_0_1 = copy.deepcopy(Setting_6_6_0_21)
Setting_7_0_0_1.pop('register8',None)
Setting_7_0_0_1.update ({
'shutter_motordelay': ('B', 0xE9A, ([4], None, ('Shutter', '"ShutterMotorDelay{} {:.1f}".format(#,$/20.0)')) ),
'flag4': ('<L', 0x1E0, (None, None, ('System', None)), '"0x{:08x}".format($)' ),
})
Setting_7_0_0_1['flag3'][0].update ({
'cors_enabled': ('<L', (0x3A0,1,23), (None, None, ('SetOption', '"SetOption73 {}".format($)')) ),
'ds18x20_internal_pullup': ('<L', (0x3A0,1,24), (None, None, ('SetOption', '"SetOption74 {}".format($)')) ),
'grouptopic_mode': ('<L', (0x3A0,1,25), (None, None, ('SetOption', '"SetOption75 {}".format($)')) ),
})
# ======================================================================
Setting_7_0_0_2 = copy.deepcopy(Setting_7_0_0_1)
Setting_7_0_0_2.update ({
'web_color2': ('3B', 0xEA0, ([1], None, ('Wifi', '"WebColor{} {}{:06x}".format(#+18,chr(35),int($,0))')), '"0x{:06x}".format($)' ),
})
# ======================================================================
Setting_7_0_0_3 = copy.deepcopy(Setting_7_0_0_2)
Setting_7_0_0_3.update ({
'i2c_drivers': ('<L', 0xFEC, ([3], None, ('Management', None)),'"0x{:08x}".format($)' ),
})
# ======================================================================
Setting_7_0_0_4 = copy.deepcopy(Setting_7_0_0_3)
Setting_7_0_0_4.update ({
'wifi_output_power': ('B', 0x1E5, (None, None, ('Wifi', '"WifiPower {:.1f}".format($/10.0)')) ),
})
Setting_7_0_0_4['flag3'][0].update ({
'bootcount_update': ('<L', (0x3A0,1,26), (None, None, ('SetOption', '"SetOption76 {}".format($)')) ),
})
# ======================================================================
Setting_7_0_0_5 = copy.deepcopy(Setting_7_0_0_4)
Setting_7_0_0_5.update ({
'temp_comp': ('b', 0xE9E, (None, None, ('Sensor', '"TempOffset {:.1f}".format($/10.0)')) ),
})
# ======================================================================
Settings = [
(0x7000005,0x1000, Setting_7_0_0_5),
(0x7000004,0x1000, Setting_7_0_0_4),
(0x7000003,0x1000, Setting_7_0_0_3),
(0x7000002,0x1000, Setting_7_0_0_2),
(0x7000001,0x1000, Setting_7_0_0_1),
(0x6060015,0x1000, Setting_6_6_0_21),
(0x6060014,0x1000, Setting_6_6_0_20),
(0x6060012,0x1000, Setting_6_6_0_18),
(0x606000F,0x1000, Setting_6_6_0_15),
@ -1162,13 +1214,14 @@ def message(msg, type_=None, status=None, line=None):
@param status:
status number
"""
print >> sys.stderr, '{styp}{sdelimiter}{sstatus}{slineno}{scolon}{smgs}'.format(\
styp=type_ if type_ is not None else '',
sdelimiter=' ' if status is not None and status > 0 and type_ is not None else '',
sstatus=status if status is not None and status > 0 else '',
scolon=': ' if type_ is not None or line is not None else '',
smgs=msg,
slineno=' (@{:04d})'.format(line) if line is not None else '')
print('{styp}{sdelimiter}{sstatus}{slineno}{scolon}{smgs}'.format(\
styp=type_ if type_ is not None else '',
sdelimiter=' ' if status is not None and status > 0 and type_ is not None else '',
sstatus=status if status is not None and status > 0 else '',
scolon=': ' if type_ is not None or line is not None else '',
smgs=msg,
slineno=' (@{:04d})'.format(line) if line is not None else '')
, file=sys.stderr)
def exit(status=0, msg="end", type_=LogType.ERROR, src=None, doexit=True, line=None):
@ -1200,11 +1253,11 @@ def ShortHelp(doexit=True):
@param doexit:
sys.exit with OK if True
"""
print parser.description
print(parser.description)
print
parser.print_usage()
print
print "For advanced help use '{prog} -H' or '{prog} --full-help'".format(prog=os.path.basename(sys.argv[0]))
print("For advanced help use '{prog} -H' or '{prog} --full-help'".format(prog=os.path.basename(sys.argv[0])))
if doexit:
sys.exit(ExitCode.OK)
@ -1554,8 +1607,8 @@ def LoadTasmotaConfig(filename):
try:
with open(filename, "rb") as tasmotafile:
encode_cfg = tasmotafile.read()
except Exception, e:
exit(e[0], "'{}' {}".format(filename, e[1]),line=inspect.getlineno(inspect.currentframe()))
except Exception as e:
exit(e.args[0], "'{}' {}".format(filename, e[1]),line=inspect.getlineno(inspect.currentframe()))
return encode_cfg
@ -1597,8 +1650,8 @@ def TasmotaGet(cmnd, host, port, username=DEFAULTS['source']['username'], passwo
c.perform()
responsecode = c.getinfo(c.RESPONSE_CODE)
response = header.response()
except Exception, e:
exit(e[0], e[1],line=inspect.getlineno(inspect.currentframe()))
except Exception as e:
exit(e.args[0], e.args[1], line=inspect.getlineno(inspect.currentframe()))
finally:
c.close()
@ -1727,8 +1780,8 @@ def PushTasmotaConfig(encode_cfg, host, port, username=DEFAULTS['source']['usern
try:
c.perform()
responsecode = c.getinfo(c.RESPONSE_CODE)
except Exception, e:
return e[0], e[1]
except Exception as e:
return e.args[0], e.args[1]
c.close()
@ -1839,7 +1892,7 @@ def GetFieldDef(fielddef, fields="format_, addrdef, baseaddr, bits, bitshift, da
# calling with nothing is wrong
if fielddef is None:
print >> sys.stderr, '<fielddef> is None'
print('<fielddef> is None', file=sys.stderr)
raise SyntaxError('<fielddef> error')
# get top level items
@ -1850,7 +1903,7 @@ def GetFieldDef(fielddef, fields="format_, addrdef, baseaddr, bits, bitshift, da
# converter present
format_, addrdef, datadef, converter = fielddef
else:
print >> sys.stderr, 'wrong <fielddef> {} length ({}) in setting'.format(fielddef, len(fielddef))
print('wrong <fielddef> {} length ({}) in setting'.format(fielddef, len(fielddef)), file=sys.stderr)
raise SyntaxError('<fielddef> error')
# ignore calls with 'root' setting
@ -1858,7 +1911,7 @@ def GetFieldDef(fielddef, fields="format_, addrdef, baseaddr, bits, bitshift, da
return eval(fields)
if not isinstance(format_, (unicode,str,dict)):
print >> sys.stderr, 'wrong <format> {} type {} in <fielddef> {}'.format(format_, type(format_), fielddef)
print('wrong <format> {} type {} in <fielddef> {}'.format(format_, type(format_), fielddef), file=sys.stderr)
raise SyntaxError('<fielddef> error')
# extract addrdef items
@ -1868,16 +1921,16 @@ def GetFieldDef(fielddef, fields="format_, addrdef, baseaddr, bits, bitshift, da
# baseaddr bit definition
baseaddr, bits, bitshift = baseaddr
if not isinstance(bits, int):
print >> sys.stderr, '<bits> must be defined as integer in <fielddef> {}'.format(bits, fielddef)
print('<bits> must be defined as integer in <fielddef> {}'.format(bits, fielddef), file=sys.stderr)
raise SyntaxError('<fielddef> error')
if not isinstance(bitshift, int):
print >> sys.stderr, '<bitshift> must be defined as integer in <fielddef> {}'.format(bitshift, fielddef)
print('<bitshift> must be defined as integer in <fielddef> {}'.format(bitshift, fielddef), file=sys.stderr)
raise SyntaxError('<fielddef> error')
else:
print >> sys.stderr, 'wrong <addrdef> {} length ({}) in <fielddef> {}'.format(addrdef, len(addrdef), fielddef)
print('wrong <addrdef> {} length ({}) in <fielddef> {}'.format(addrdef, len(addrdef), fielddef), file=sys.stderr)
raise SyntaxError('<fielddef> error')
if not isinstance(baseaddr, int):
print >> sys.stderr, '<baseaddr> must be defined as integer in <fielddef> {}'.format(baseaddr, fielddef)
print('<baseaddr> must be defined as integer in <fielddef> {}'.format(baseaddr, fielddef), file=sys.stderr)
raise SyntaxError('<fielddef> error')
# extract datadef items
@ -1893,27 +1946,27 @@ def GetFieldDef(fielddef, fields="format_, addrdef, baseaddr, bits, bitshift, da
if isinstance(cmd, (tuple)) and len(cmd) == 2:
group, tasmotacmnd = cmd
if group is not None and not isinstance(group, (str, unicode)):
print >> sys.stderr, 'wrong <group> {} in <fielddef> {}'.format(group, fielddef)
print('wrong <group> {} in <fielddef> {}'.format(group, fielddef), file=sys.stderr)
raise SyntaxError('<fielddef> error')
if tasmotacmnd is isinstance(tasmotacmnd, tuple):
tasmotacmnds = tasmotacmnd
for tasmotacmnd in tasmotacmnds:
if tasmotacmnd is not None and not callable(tasmotacmnd) and not isinstance(tasmotacmnd, (str, unicode)):
print >> sys.stderr, 'wrong <tasmotacmnd> {} in <fielddef> {}'.format(tasmotacmnd, fielddef)
print('wrong <tasmotacmnd> {} in <fielddef> {}'.format(tasmotacmnd, fielddef), file=sys.stderr)
raise SyntaxError('<fielddef> error')
else:
if tasmotacmnd is not None and not callable(tasmotacmnd) and not isinstance(tasmotacmnd, (str, unicode)):
print >> sys.stderr, 'wrong <tasmotacmnd> {} in <fielddef> {}'.format(tasmotacmnd, fielddef)
print('wrong <tasmotacmnd> {} in <fielddef> {}'.format(tasmotacmnd, fielddef), file=sys.stderr)
raise SyntaxError('<fielddef> error')
else:
print >> sys.stderr, 'wrong <cmd> {} length ({}) in <fielddef> {}'.format(cmd, len(cmd), fielddef)
print('wrong <cmd> {} length ({}) in <fielddef> {}'.format(cmd, len(cmd), fielddef), file=sys.stderr)
raise SyntaxError('<fielddef> error')
else:
print >> sys.stderr, 'wrong <datadef> {} length ({}) in <fielddef> {}'.format(datadef, len(datadef), fielddef)
print('wrong <datadef> {} length ({}) in <fielddef> {}'.format(datadef, len(datadef), fielddef), file=sys.stderr)
raise SyntaxError('<fielddef> error')
if validate is not None and (not isinstance(validate, (unicode,str)) and not callable(validate)):
print >> sys.stderr, 'wrong <validate> {} type {} in <fielddef> {}'.format(validate, type(validate), fielddef)
print('wrong <validate> {} type {} in <fielddef> {}'.format(validate, type(validate), fielddef), file=sys.stderr)
raise SyntaxError('<fielddef> error')
# convert single int into one-dimensional list
@ -1921,7 +1974,7 @@ def GetFieldDef(fielddef, fields="format_, addrdef, baseaddr, bits, bitshift, da
arraydef = [arraydef]
if arraydef is not None and not isinstance(arraydef, (list)):
print >> sys.stderr, 'wrong <arraydef> {} type {} in <fielddef> {}'.format(arraydef, type(arraydef), fielddef)
print('wrong <arraydef> {} type {} in <fielddef> {}'.format(arraydef, type(arraydef), fielddef), file=sys.stderr)
raise SyntaxError('<fielddef> error')
# get read/write converter items
@ -1931,13 +1984,13 @@ def GetFieldDef(fielddef, fields="format_, addrdef, baseaddr, bits, bitshift, da
# converter has read/write converter
readconverter, writeconverter = converter
if readconverter is not None and not isinstance(readconverter, (str,unicode)) and not callable(readconverter):
print >> sys.stderr, 'wrong <readconverter> {} type {} in <fielddef> {}'.format(readconverter, type(readconverter), fielddef)
print('wrong <readconverter> {} type {} in <fielddef> {}'.format(readconverter, type(readconverter), fielddef), file=sys.stderr)
raise SyntaxError('<fielddef> error')
if writeconverter is not None and (not isinstance(writeconverter, (bool,str,unicode)) and not callable(writeconverter)):
print >> sys.stderr, 'wrong <writeconverter> {} type {} in <fielddef> {}'.format(writeconverter, type(writeconverter), fielddef)
print('wrong <writeconverter> {} type {} in <fielddef> {}'.format(writeconverter, type(writeconverter), fielddef), file=sys.stderr)
raise SyntaxError('<fielddef> error')
else:
print >> sys.stderr, 'wrong <converter> {} length ({}) in <fielddef> {}'.format(converter, len(converter), fielddef)
print('wrong <converter> {} length ({}) in <fielddef> {}'.format(converter, len(converter), fielddef), file=sys.stderr)
raise SyntaxError('<fielddef> error')
@ -1975,8 +2028,8 @@ def ReadWriteConverter(value, fielddef, read=True, raw=False):
return eval(conv.replace('$','value'))
elif callable(conv): # use as format function
return conv(value)
except Exception, e:
exit(e[0], e[1], type_=LogType.WARNING, line=inspect.getlineno(inspect.currentframe()))
except Exception as e:
exit(e.args[0], e.args[1], type_=LogType.WARNING, line=inspect.getlineno(inspect.currentframe()))
return value
@ -2294,7 +2347,7 @@ def SetFieldValue(fielddef, dobj, addr, value):
formatcnt = GetFormatCount(format_)
singletype, bitsize = GetFormatType(format_)
if args.debug >= 2:
print >> sys.stderr, "SetFieldValue(): fielddef {}, addr 0x{:04x} value {} formatcnt {} singletype {} bitsize {} ".format(fielddef,addr,value,formatcnt,singletype,bitsize)
print("SetFieldValue(): fielddef {}, addr 0x{:04x} value {} formatcnt {} singletype {} bitsize {} ".format(fielddef,addr,value,formatcnt,singletype,bitsize), file=sys.stderr)
if not format_[-1:].lower() in ['s','p']:
addr += (bitsize / 8) * formatcnt
for _ in range(0, formatcnt):
@ -2305,7 +2358,7 @@ def SetFieldValue(fielddef, dobj, addr, value):
if isinstance(value,int) and value < 0 and val > maxsigned:
val = ((maxunsigned+1)-val) * (-1)
if args.debug >= 3:
print >> sys.stderr, "SetFieldValue(): Single type - fielddef {}, addr 0x{:04x} value {} singletype {} bitsize {}".format(fielddef,addr,val,singletype,bitsize)
print("SetFieldValue(): Single type - fielddef {}, addr 0x{:04x} value {} singletype {} bitsize {}".format(fielddef,addr,val,singletype,bitsize), file=sys.stderr)
try:
struct.pack_into(singletype, dobj, addr, val)
except struct.error as e:
@ -2317,7 +2370,7 @@ def SetFieldValue(fielddef, dobj, addr, value):
value >>= bitsize
else:
if args.debug >= 3:
print >> sys.stderr, "SetFieldValue(): String type - fielddef {}, addr 0x{:04x} value {} format_ {}".format(fielddef,addr,value,format_)
print("SetFieldValue(): String type - fielddef {}, addr 0x{:04x} value {} format_ {}".format(fielddef,addr,value,format_), file=sys.stderr)
try:
struct.pack_into(format_, dobj, addr, value)
except struct.error as e:
@ -2427,7 +2480,7 @@ def SetField(dobj, fieldname, fielddef, restore, addroffset=0, filename=""):
# do not write readonly values
if writeconverter is False:
if args.debug >= 2:
print >> sys.stderr, "SetField(): Readonly '{}' using '{}'/{}{} @{} skipped".format(fieldname, format_, arraydef, bits, hex(baseaddr+addroffset))
print("SetField(): Readonly '{}' using '{}'/{}{} @{} skipped".format(fieldname, format_, arraydef, bits, hex(baseaddr+addroffset)), file=sys.stderr)
return dobj
# <arraydef> contains a list
@ -2465,16 +2518,16 @@ def SetField(dobj, fieldname, fielddef, restore, addroffset=0, filename=""):
if format_[-1:] in ['c']:
try:
value = ReadWriteConverter(restore.encode(STR_ENCODING)[0], fielddef, read=False)
except Exception, e:
exit(e[0], e[1], type_=LogType.WARNING, line=inspect.getlineno(inspect.currentframe()))
except Exception as e:
exit(e.args[0], e.args[1], type_=LogType.WARNING, line=inspect.getlineno(inspect.currentframe()))
valid = False
# bool
elif format_[-1:] in ['?']:
try:
value = ReadWriteConverter(bool(restore), fielddef, read=False)
except Exception, e:
exit(e[0], e[1], type_=LogType.WARNING, line=inspect.getlineno(inspect.currentframe()))
except Exception as e:
exit(e.args[0], e.args[1], type_=LogType.WARNING, line=inspect.getlineno(inspect.currentframe()))
valid = False
# integer
@ -2560,7 +2613,7 @@ def SetField(dobj, fieldname, fielddef, restore, addroffset=0, filename=""):
if args.debug >= 2:
sbits = " {} bits shift {}".format(bits, bitshift) if bits else ""
strvalue = "{} [{}]".format(_value, hex(value)) if isinstance(_value, int) else _value
print >> sys.stderr, "SetField(): Set '{}' using '{}'/{}{} @{} to {}".format(fieldname, format_, arraydef, sbits, hex(baseaddr+addroffset), strvalue)
print("SetField(): Set '{}' using '{}'/{}{} @{} to {}".format(fieldname, format_, arraydef, sbits, hex(baseaddr+addroffset), strvalue), file=sys.stderr)
if fieldname != 'cfg_crc' and fieldname != '_':
prevvalue = GetFieldValue(fielddef, dobj, baseaddr+addroffset)
dobj = SetFieldValue(fielddef, dobj, baseaddr+addroffset, value)
@ -2569,7 +2622,7 @@ def SetField(dobj, fieldname, fielddef, restore, addroffset=0, filename=""):
message("Value for '{}' changed from {} to {}".format(fieldname, prevvalue, curvalue), type_=LogType.INFO)
else:
if args.debug >= 2:
print >> sys.stderr, "SetField(): Special field '{}' using '{}'/{}{} @{} skipped".format(fieldname, format_, arraydef, bits, hex(baseaddr+addroffset))
print("SetField(): Special field '{}' using '{}'/{}{} @{} skipped".format(fieldname, format_, arraydef, bits, hex(baseaddr+addroffset)), file=sys.stderr)
else:
sformat = "file '{sfile}' - {{'{sname}': {svalue}}} ({serror})"+errformat
exit(ExitCode.RESTORE_DATA_ERROR, sformat.format(sfile=filename, sname=fieldname, serror=err, svalue=_value, smin=min_, smax=max_), type_=LogType.WARNING, doexit=not args.ignorewarning)
@ -2871,8 +2924,8 @@ def Backup(backupfile, backupfileformat, encode_cfg, decode_cfg, configmapping):
try:
with open(backup_filename, "wb") as backupfp:
backupfp.write(encode_cfg)
except Exception, e:
exit(e[0], "'{}' {}".format(backup_filename, e[1]),line=inspect.getlineno(inspect.currentframe()))
except Exception as e:
exit(e.args[0], "'{}' {}".format(backup_filename, e[1]),line=inspect.getlineno(inspect.currentframe()))
# binary format
elif backupfileformat.lower() == FileType.BIN.lower():
@ -2884,8 +2937,8 @@ def Backup(backupfile, backupfileformat, encode_cfg, decode_cfg, configmapping):
with open(backup_filename, "wb") as backupfp:
backupfp.write(struct.pack('<L',BINARYFILE_MAGIC))
backupfp.write(decode_cfg)
except Exception, e:
exit(e[0], "'{}' {}".format(backup_filename, e[1]),line=inspect.getlineno(inspect.currentframe()))
except Exception as e:
exit(e.args[0], "'{}' {}".format(backup_filename, e[1]),line=inspect.getlineno(inspect.currentframe()))
# JSON format
elif backupfileformat.lower() == FileType.JSON.lower():
@ -2896,8 +2949,8 @@ def Backup(backupfile, backupfileformat, encode_cfg, decode_cfg, configmapping):
try:
with open(backup_filename, "w") as backupfp:
json.dump(configmapping, backupfp, sort_keys=args.jsonsort, indent=None if args.jsonindent < 0 else args.jsonindent, separators=(',', ':') if args.jsoncompact else (', ', ': ') )
except Exception, e:
exit(e[0], "'{}' {}".format(backup_filename, e[1]),line=inspect.getlineno(inspect.currentframe()))
except Exception as e:
exit(e.args[0], "'{}' {}".format(backup_filename, e[1]),line=inspect.getlineno(inspect.currentframe()))
if args.verbose:
srctype = 'device'
@ -2940,8 +2993,8 @@ def Restore(restorefile, backupfileformat, encode_cfg, decode_cfg, configmapping
try:
with open(restorefilename, "rb") as restorefp:
new_encode_cfg = restorefp.read()
except Exception, e:
exit(e[0], "'{}' {}".format(restorefilename, e[1]),line=inspect.getlineno(inspect.currentframe()))
except Exception as e:
exit(e.args[0], "'{}' {}".format(restorefilename, e[1]),line=inspect.getlineno(inspect.currentframe()))
elif filetype == FileType.BIN:
if args.verbose:
@ -2949,8 +3002,8 @@ def Restore(restorefile, backupfileformat, encode_cfg, decode_cfg, configmapping
try:
with open(restorefilename, "rb") as restorefp:
restorebin = restorefp.read()
except Exception, e:
exit(e[0], "'{}' {}".format(restorefilename, e[1]),line=inspect.getlineno(inspect.currentframe()))
except Exception as e:
exit(e.args[0], "'{}' {}".format(restorefilename, e[1]),line=inspect.getlineno(inspect.currentframe()))
header = struct.unpack_from('<L', restorebin, 0)[0]
if header == BINARYFILE_MAGIC:
decode_cfg = restorebin[4:] # remove header from encrypted config file
@ -3004,8 +3057,8 @@ def Restore(restorefile, backupfileformat, encode_cfg, decode_cfg, configmapping
try:
with open(args.tasmotafile, "wb") as outputfile:
outputfile.write(new_encode_cfg)
except Exception, e:
exit(e[0], "'{}' {}".format(args.tasmotafile, e[1]),line=inspect.getlineno(inspect.currentframe()))
except Exception as e:
exit(e.args[0], "'{}' {}".format(args.tasmotafile, e[1]),line=inspect.getlineno(inspect.currentframe()))
if args.verbose:
message("Restore successful to file '{}' using restore file '{}'".format(args.tasmotafile, restorefilename), type_=LogType.INFO)
@ -3026,10 +3079,10 @@ def OutputTasmotaCmnds(tasmotacmnds):
def OutputTasmotaSubCmnds(cmnds):
if args.cmndsort:
for cmnd in sorted(cmnds, key = lambda cmnd:[int(c) if c.isdigit() else c for c in re.split('(\d+)', cmnd)]):
print "{}{}".format(" "*args.cmndindent, cmnd)
print("{}{}".format(" "*args.cmndindent, cmnd))
else:
for cmnd in cmnds:
print "{}{}".format(" "*args.cmndindent, cmnd)
print("{}{}".format(" "*args.cmndindent, cmnd))
groups = GetGroupList(Settings[0][2])
@ -3038,7 +3091,7 @@ def OutputTasmotaCmnds(tasmotacmnds):
if group.title() in (groupname.title() for groupname in tasmotacmnds):
cmnds = tasmotacmnds[group]
print
print "# {}:".format(group)
print("# {}:".format(group))
OutputTasmotaSubCmnds(cmnds)
else:
@ -3245,10 +3298,10 @@ def ParseArgs():
args = parser.parse_args()
if args.debug >= 1:
print >> sys.stderr, parser.format_values()
print >> sys.stderr, "Settings:"
print(parser.format_values(), file=sys.stderr)
print("Settings:", file=sys.stderr)
for k in args.__dict__:
print >> sys.stderr, " "+str(k), "= ",eval('args.{}'.format(k))
print(" "+str(k), "= ",eval('args.{}'.format(k)), file=sys.stderr)
return args
@ -3280,7 +3333,7 @@ if __name__ == "__main__":
# no config source given
ShortHelp(False)
print
print parser.epilog
print(parser.epilog)
sys.exit(ExitCode.OK)
if len(encode_cfg) == 0:
@ -3309,7 +3362,7 @@ if __name__ == "__main__":
# json screen output
if (args.backupfile is None and args.restorefile is None) or args.output:
if args.outputformat == 'json':
print json.dumps(configmapping, sort_keys=args.jsonsort, indent=None if args.jsonindent<0 else args.jsonindent, separators=(',', ':') if args.jsoncompact else (', ', ': ') )
print(json.dumps(configmapping, sort_keys=args.jsonsort, indent=None if args.jsonindent<0 else args.jsonindent, separators=(',', ':') if args.jsoncompact else (', ', ': ') ))
if args.outputformat == 'cmnd' or args.outputformat == 'command':
tasmotacmnds = Mapping2Cmnd(decode_cfg, configmapping)