Merge branch 'development' into release-7.1

This commit is contained in:
Theo Arends 2019-11-23 11:31:25 +01:00
commit 2757fcabd7
9 changed files with 261 additions and 318 deletions

View File

@ -6,6 +6,6 @@
- [ ] The pull request is done against the latest dev branch
- [ ] Only relevant files were touched
- [ ] Only one feature/fix was added per PR.
- [ ] The code change is tested and works on core 2.6
- [ ] The code change is tested and works on core 2.6.1
- [ ] The code change pass travis tests. **Your PR cannot be merged unless tests pass**
- [ ] I accept the [CLA](https://github.com/arendst/Tasmota/blob/development/CONTRIBUTING.md#contributor-license-agreement-cla).

View File

@ -99,8 +99,6 @@ extra_scripts = pio/strip-floats.py
[core_active]
; Select one core set for platform and build_flags
;platform = ${core_2_6_0.platform}
;build_flags = ${core_2_6_0.build_flags}
platform = ${core_2_6_1.platform}
build_flags = ${core_2_6_1.build_flags}
;platform = ${core_stage.platform}
@ -114,60 +112,13 @@ build_flags = ${core_2_6_1.build_flags}
build_flags = -D NDEBUG
-mtarget-align
-Wl,-Map,firmware.map
[core_2_6_0]
; *** Esp8266 core for Arduino version 2.6.0 (for Windows, most Linux variants and Mac)
; *** custom setup until the core 2.6.0 version is official released from PlatformIO crew
platform = https://github.com/Jason2866/platform-espressif8266.git#core_2_6_0
build_flags = ${esp82xx_defaults.build_flags}
-Wl,-Teagle.flash.1m.ld
-O2
-DBEARSSL_SSL_BASIC
; NONOSDK221
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221
; NONOSDK22x_190313
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313
; 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 = 2.2.2-dev(bb83b9b)
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105
; NONOSDK3V0 (known issues)
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3
; lwIP 1.4
; -DPIO_FRAMEWORK_ARDUINO_LWIP_HIGHER_BANDWIDTH
; lwIP 2 - Low Memory
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY
; lwIP 2 - Higher Bandwidth
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH
; lwIP 2 - Higher Bandwidth Low Memory no Features
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY_LOW_FLASH
; lwIP 2 - Higher Bandwidth no Features (Tasmota default)
-DPIO_FRAMEWORK_ARDUINO_LWIP2_HIGHER_BANDWIDTH_LOW_FLASH
; lwIP 2 - Higher Bandwidth IPv6 (use ONLY if you need IPv6, experimental!)
; -DPIO_FRAMEWORK_ARDUINO_LWIP2_IPV6_HIGHER_BANDWIDTH
; VTABLES in Flash (Tasmota default)
-DVTABLES_IN_FLASH
; VTABLES in Heap
; -DVTABLES_IN_DRAM
; VTABLES in IRAM
; -DVTABLES_IN_IRAM
; enable one option set -> No exception recommended
; No exception code in firmware
-fno-exceptions
-lstdc++
; Exception code in firmware /needs much space! 90k
; -fexceptions
; -lstdc++-exc
[core_2_6_1]
; *** Esp8266 core for Arduino version 2.6.1 (for Windows, most Linux variants and Mac)
; *** custom setup until the core 2.6.0 version is official released from PlatformIO crew
; *** custom setup until the core 2.6.1 version is official released from PlatformIO crew
platform = https://github.com/Jason2866/platform-espressif8266.git#core_2_6_1
build_flags = ${esp82xx_defaults.build_flags}
-Wl,-Teagle.flash.1m.ld
-O2
-DBEARSSL_SSL_BASIC
; NONOSDK221
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK221
@ -220,9 +171,9 @@ build_flags = ${esp82xx_defaults.build_flags}
; NONOSDK22x_190313
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313
; NONOSDK22x_190703 (Tasmota default)
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703
-DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703
; NONOSDK22x_191024
-DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024
; NONOSDK22x_191105
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105
; NONOSDK3V0 (known issues)
@ -263,11 +214,11 @@ build_flags = ${esp82xx_defaults.build_flags}
; NONOSDK22x_190313
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190313
; NONOSDK22x_190703
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703
-DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_190703
; NONOSDK22x_191024
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191024
; NONOSDK22x_191105
-DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK22x_191105
; NONOSDK3V0 (known issues)
; -DPIO_FRAMEWORK_ARDUINO_ESPRESSIF_SDK3
; lwIP 1.4

View File

@ -1,4 +1,7 @@
/*********************************************************************************************\
* 7.0.0.6 20191122
* Add colorpicker to WebUI by Christian Staars (#6984)
*
* 7.0.0.5 20191118
* Fix boot loop regression
* Add command TempOffset -12.6 .. 12.6 to set global temperature sensor offset (#6958)

View File

@ -28,7 +28,7 @@
* Use online command StateText to translate ON, OFF, HOLD and TOGGLE.
* Use online command Prefix to translate cmnd, stat and tele.
*
* Updated until v7.0.0.3
* Updated until v7.0.0.5
\*********************************************************************/
#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
@ -75,7 +75,7 @@
#define D_COUNTER "Contador"
#define D_CURRENT "Corriente" // As in Voltage and Current
#define D_DATA "Datos"
#define D_DARKLIGHT "Oscura"
#define D_DARKLIGHT "Oscuro"
#define D_DEBUG "Debug"
#define D_DISABLED "Deshabilitado"
#define D_DISTANCE "Distancia"

View File

@ -64,10 +64,10 @@
#define D_BUTTON "Przycisk"
#define D_BY "by" // Written by me
#define D_BYTES "Bajtów"
#define D_CELSIUS "Celsiusza"
#define D_CELSIUS "Celsiusz"
#define D_CHANNEL "Kanał"
#define D_CO2 "Dwutlenku węgla"
#define D_CODE "kod" // Button code
#define D_CO2 "Dwutlenek węgla"
#define D_CODE "Kod" // Button code
#define D_COLDLIGHT "Zimny"
#define D_COMMAND "Komenda"
#define D_CONNECTED "Połączony"
@ -77,11 +77,11 @@
#define D_DATA "Data"
#define D_DARKLIGHT "Ciemny"
#define D_DEBUG "Debug"
#define D_DISABLED "Zablokowany"
#define D_DISABLED "Wyłączony"
#define D_DISTANCE "Odległość"
#define D_DNS_SERVER "Serwer DNS"
#define D_DONE "Wykonane"
#define D_DST_TIME "DST"
#define D_DST_TIME "Czas DST"
#define D_ECO2 "eCO2"
#define D_EMULATION "Emulacja"
#define D_ENABLED "Załączony"
@ -102,7 +102,7 @@
#define D_HOST "Serwer"
#define D_HOSTNAME "Nazwa serwera"
#define D_HUMIDITY "Wilgotność"
#define D_ILLUMINANCE "Oświetlenie"
#define D_ILLUMINANCE "Podświetlanie"
#define D_IMMEDIATE "Natychmiastowy" // Button immediate
#define D_INDEX "Indeks"
#define D_INFO "Informacja"
@ -130,8 +130,8 @@
#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_PROGRAM_FLASH_SIZE "Rozmiar programu flash"
#define D_PROGRAM_SIZE "Rozmiar programu"
#define D_PROJECT "Projekt"
#define D_RAIN "Deszcz"
#define D_RECEIVED "Otrzymany"
@ -203,15 +203,15 @@
#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 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_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"
#define D_QUERY_DONE "Zapytanie wykonane"
#define D_MQTT_SERVICE_FOUND "Usługa MQTT została znaleziona"
#define D_FOUND_AT "znalezione w"
#define D_FOUND_AT "znaleziono w"
#define D_SYSLOG_HOST_NOT_FOUND "Syslog Host nie znaleziony"
// settings.ino
@ -233,7 +233,7 @@
#define D_TRYING_TO_CONNECT "Próbuję połączyć urzadzenie z siecią"
#define D_RESTART_IN "Zrestartuj"
#define D_SECONDS "sekund"
#define D_SECONDS "Sekund"
#define D_DEVICE_WILL_RESTART "Urządzenie zrestartuje sie za kilka sekund"
#define D_BUTTON_TOGGLE "Załącz/Wyłącz"
#define D_CONFIGURATION "Konfiguracja"
@ -247,7 +247,7 @@
#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_CONFIGURE_OTHER "Inne konfiguracje"
#define D_CONFIRM_RESET_CONFIGURATION "Potwierdź reset ustawień"
#define D_RESET_CONFIGURATION "Reset ustawień"
#define D_BACKUP_CONFIGURATION "Kopia ustawień"
@ -255,7 +255,7 @@
#define D_MAIN_MENU "Menu główne"
#define D_MODULE_PARAMETERS "Parametry modułu"
#define D_MODULE_TYPE "Typ modułu"
#define D_MODULE_TYPE "Typ"
#define D_PULLUP_ENABLE "Przełącznik pull-up"
#define D_ADC "ADC"
#define D_GPIO "GPIO"
@ -263,30 +263,30 @@
#define D_SERIAL_OUT "Wyjście rs"
#define D_WIFI_PARAMETERS "Parametry sieci WiFi"
#define D_SCAN_FOR_WIFI_NETWORKS "Skanuj sieci WiFi"
#define D_SCAN_FOR_WIFI_NETWORKS "Skanuj sieci"
#define D_SCAN_DONE "Skanowanie wykonane"
#define D_NO_NETWORKS_FOUND "Nie znaleziono sieci"
#define D_REFRESH_TO_SCAN_AGAIN "Odswież aby ponownie wyszukać sieci WiFi"
#define D_DUPLICATE_ACCESSPOINT "Powiel AP"
#define D_REFRESH_TO_SCAN_AGAIN "Odśwież aby ponownie wyszukać sieci"
#define D_DUPLICATE_ACCESSPOINT "Duplikuj"
#define D_SKIPPING_LOW_QUALITY "Pominięto z powodu niskiej jakości sygnału"
#define D_RSSI "RSSI"
#define D_WEP "WEP"
#define D_WPA_PSK "WPA PSK"
#define D_WPA2_PSK "WPA2 PSK"
#define D_AP1_SSID "AP1 SSID"
#define D_AP1_PASSWORD "Hasło AP1"
#define D_AP2_SSID "AP2 SSID"
#define D_AP2_PASSWORD "Hasło AP2"
#define D_AP1_SSID "Nazwa 1"
#define D_AP1_PASSWORD "Hasło 1"
#define D_AP2_SSID "Nazwa 2"
#define D_AP2_PASSWORD "Hasło 2"
#define D_MQTT_PARAMETERS "Parametry MQTT"
#define D_CLIENT "Klient"
#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 - poziom dziennika"
#define D_WEB_LOG_LEVEL "Web - poziom dziennika"
#define D_SYS_LOG_LEVEL "System - poziom dziennika"
#define D_SERIAL_LOG_LEVEL "Serial - poziom"
#define D_MQTT_LOG_LEVEL "Mqtt - poziom"
#define D_WEB_LOG_LEVEL "Web - poziom"
#define D_SYS_LOG_LEVEL "System - poziom"
#define D_MORE_DEBUG "Więcej informacji dziennika"
#define D_SYSLOG_HOST "Syslog host"
#define D_SYSLOG_PORT "Syslog port"
@ -296,8 +296,8 @@
#define D_TEMPLATE "Szablon"
#define D_ACTIVATE "Aktywuj"
#define D_WEB_ADMIN_PASSWORD "Hasło administratora"
#define D_MQTT_ENABLE "MQTT aktywne"
#define D_FRIENDLY_NAME "Twoja nazwa"
#define D_MQTT_ENABLE "Załącz MQTT"
#define D_FRIENDLY_NAME "Nazwa"
#define D_BELKIN_WEMO "Belkin WeMo"
#define D_HUE_BRIDGE "Mostek Hue"
#define D_SINGLE_DEVICE "pojedyńcze urządzenie"
@ -313,28 +313,28 @@
#define D_CONFIGURATION_SAVED "Ustawienia zapisane"
#define D_CONFIGURATION_RESET "Ustawienia zresetowane"
#define D_PROGRAM_VERSION "Wersja programu"
#define D_BUILD_DATE_AND_TIME "Dzień i godzina kompilacji"
#define D_PROGRAM_VERSION "Wersja oprogramowania"
#define D_BUILD_DATE_AND_TIME "Data 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_MQTT_HOST "Host MQTT"
#define D_MQTT_PORT "Port MQTT"
#define D_MQTT_CLIENT "Klient 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"
#define D_MQTT_HOST "Host"
#define D_MQTT_PORT "Port"
#define D_MQTT_CLIENT "Klient"
#define D_MQTT_USER "Użytkownik"
#define D_MQTT_TOPIC "Temat"
#define D_MQTT_GROUP_TOPIC "Temat grupy"
#define D_MQTT_FULL_TOPIC "Pełny temat"
#define D_MDNS_DISCOVERY "Wykrywanie mDNS"
#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_ID "ID pamięci flash"
#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 serwera"
#define D_START_UPGRADE "Start aktualizacji"
#define D_OTA_URL "Adres serwera"
#define D_START_UPGRADE "Aktualizuj"
#define D_UPGRADE_BY_FILE_UPLOAD "Aktualizacja z pliku"
#define D_UPLOAD_STARTED "Wgrywanie rozpoczęte"
#define D_UPGRADE_STARTED "Aktualizacja rozpoczęta"
@ -373,23 +373,23 @@
#define D_FAILED_TO_SEND_RESPONSE "Nie udało się wysłać odpowiedzi"
#define D_WEMO "WeMo"
#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_BASIC_EVENT "Zdarzenie podstawowe"
#define D_WEMO_EVENT_SERVICE "Zdarzenie serwisowe"
#define D_WEMO_META_SERVICE "Meta dane serwisowe"
#define D_WEMO_SETUP "Ustawienia WeMo"
#define D_RESPONSE_SENT "Odpowiedź wysłana"
#define D_RESPONSE_SENT "Wyślij odpowiedź"
#define D_HUE "Hue"
#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_HUE_API_NOT_IMPLEMENTED "Api nie zaimplementowane"
#define D_HUE_API "API"
#define D_HUE_POST_ARGS "POST argument"
#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_KEY_IDX "Klucz Idx"
#define D_DOMOTICZ_SWITCH_IDX "Przełącznik Idx"
#define D_DOMOTICZ_SENSOR_IDX "Sensor Idx"
#define D_DOMOTICZ_TEMP "Temperatura"
@ -402,13 +402,13 @@
#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"
#define D_DOMOTICZ_UPDATE_TIMER "Aktualizacja zegara"
// xdrv_09_timers.ino
#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_ENABLE "Załącz harmonogram"
#define D_TIMER_ARM "Załącz"
#define D_TIMER_TIME "Czas"
#define D_TIMER_DAYS "Dni"
#define D_TIMER_REPEAT "Powtarzaj"
@ -421,7 +421,7 @@
#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_ENABLE "Załącz"
#define D_KNX_GROUP_ADDRESS_TO_WRITE "Adresy grupowe do zapisu"
#define D_ADD "Dodaj"
#define D_DELETE "Usuń"
@ -431,11 +431,11 @@
#define D_KNX_COMMAND_WRITE "Zapisz"
#define D_KNX_COMMAND_READ "Czytaj"
#define D_KNX_COMMAND_OTHER "Inna komenda"
#define D_SENT_TO "Wysłane do"
#define D_SENT_TO "Wyślij do"
#define D_KNX_WARNING "Adres grupy (0/0/0) jest zarezerwowany i nie można go użyć."
#define D_KNX_ENHANCEMENT "Rozszerzenia KNX"
#define D_KNX_TX_SLOT "KNX TX"
#define D_KNX_RX_SLOT "KNX RX"
#define D_KNX_ENHANCEMENT "Rozszerzenia"
#define D_KNX_TX_SLOT "Gniazdo TX"
#define D_KNX_RX_SLOT "Gniazdo RX"
// xdrv_03_energy.ino
#define D_ENERGY_TODAY "Energia dzisiaj"
@ -450,20 +450,20 @@
// xdrv_28_pcf8574.ino
#define D_CONFIGURE_PCF8574 "Konfiguracja PCF8574"
#define D_PCF8574_PARAMETERS "Parametry PCF8574"
#define D_INVERT_PORTS "Odwrócone porty"
#define D_INVERT_PORTS "Porty odwrócone"
#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_SENSOR_BUSY "Czujnik zajęty"
#define D_SENSOR_CRC_ERROR "Błąd CRC czujnika"
#define D_SENSORS_FOUND "Znaleziono czujnik"
// 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_START_SIGNAL_LOW "Sygnał startowy niski"
#define D_START_SIGNAL_HIGH "Sygnał startowy wysoki"
#define D_PULSE "Impuls"
#define D_CHECKSUM_FAILURE "Błędna suma kontrolna"
@ -498,10 +498,10 @@
#define D_CALIBRATION "Kalibrowanie"
//xsns_35_tx20.ino
#define D_TX20_WIND_DIRECTION "Kierunek wiatru"
#define D_TX20_WIND_SPEED "Prędkość wiatru"
#define D_TX20_WIND_SPEED_AVG "Średnia prędkość wiatru"
#define D_TX20_WIND_SPEED_MAX "Maksymalna prędkość wiatru"
#define D_TX20_WIND_DIRECTION "Kierunek"
#define D_TX20_WIND_SPEED "Prędkość"
#define D_TX20_WIND_SPEED_AVG "Średnia prędkość"
#define D_TX20_WIND_SPEED_MAX "Maksymalna prędkość"
#define D_TX20_NORTH "N"
#define D_TX20_EAST "E"
#define D_TX20_SOUTH "S"
@ -523,7 +523,7 @@
#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_LED_LINK "Led link" // Suffix "i"
#define D_SENSOR_PWM "PWM" // Suffix "1"
#define D_SENSOR_COUNTER "Licznik" // Suffix "1"
#define D_SENSOR_IRRECV "IRrecv"
@ -540,7 +540,7 @@
#define D_SENSOR_SPI_MISO "SPI MISO"
#define D_SENSOR_SPI_MOSI "SPI MOSI"
#define D_SENSOR_SPI_CLK "SPI CLK"
#define D_SENSOR_BACKLIGHT "Backlight"
#define D_SENSOR_BACKLIGHT "Podświetlanie"
#define D_SENSOR_PMS5003 "PMS5003"
#define D_SENSOR_SDS0X1_RX "SDS0X1 Rx"
#define D_SENSOR_SDS0X1_TX "SDS0X1 Tx"
@ -669,7 +669,7 @@
#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_TOTAL_REACTIVE "Bierna całkowita"
#define D_UNIT_KWARH "kVArh"
#define D_UNIT_ANGLE "Deg"

View File

@ -373,10 +373,13 @@ void RtcSecond(void)
{
TIME_T tmpTime;
if (!Rtc.user_time_entry) {
if ((Rtc.ntp_sync_minute > 59) && (RtcTime.minute > 2)) Rtc.ntp_sync_minute = 1; // If sync prepare for a new cycle
if (!Rtc.user_time_entry && !global_state.wifi_down) {
uint8_t uptime_minute = (uptime / 60) % 60; // 0 .. 59
if ((Rtc.ntp_sync_minute > 59) && (uptime_minute > 2)) {
Rtc.ntp_sync_minute = 1; // If sync prepare for a new cycle
}
uint8_t offset = (uptime < 30) ? RtcTime.second : (((ESP.getChipId() & 0xF) * 3) + 3) ; // First try ASAP to sync. If fails try once every 60 seconds based on chip id
if (!global_state.wifi_down && (((offset == RtcTime.second) && ((RtcTime.year < 2016) || (Rtc.ntp_sync_minute == RtcTime.minute))) || ntp_force_sync)) {
if ( (((offset == RtcTime.second) && ( (RtcTime.year < 2016) || (Rtc.ntp_sync_minute == uptime_minute))) || ntp_force_sync ) ) {
Rtc.ntp_time = sntp_get_current_timestamp();
if (Rtc.ntp_time > START_VALID_TIME) { // Fix NTP bug in core 2.4.1/SDK 2.2.1 (returns Thu Jan 01 08:00:10 1970 after power on)
ntp_force_sync = false;
@ -405,7 +408,8 @@ void RtcSecond(void)
}
}
}
Rtc.utc_time++;
Rtc.utc_time++; // Increment every second
Rtc.local_time = Rtc.utc_time;
if (Rtc.local_time > START_VALID_TIME) { // 2016-01-01
int16_t timezone_minutes = Settings.timezone_minutes;
@ -434,8 +438,8 @@ void RtcSecond(void)
Rtc.time_timezone /= 60;
if (!Settings.energy_kWhtotal_time) { Settings.energy_kWhtotal_time = Rtc.local_time; }
}
BreakTime(Rtc.local_time, RtcTime);
BreakTime(Rtc.local_time, RtcTime);
if (RtcTime.valid) {
if (!Rtc.midnight) {
Rtc.midnight = Rtc.local_time - (RtcTime.hour * 3600) - (RtcTime.minute * 60) - RtcTime.second;

View File

@ -163,6 +163,10 @@ const char HTTP_SCRIPT_ROOT[] PROGMEM =
"la('&'+v+i+'='+p);"
"}"
#endif // USE_JAVASCRIPT_ES6
"function ld(v,p){"
"eb('s').style.backgroundImage='linear-gradient(to right,grey,hsl('+p+',100%%,50%%))';"
"la('&'+v+'='+p);"
"}"
"wl(la);";
@ -354,7 +358,8 @@ const char HTTP_HEAD_STYLE2[] PROGMEM =
".bgrn:hover{background:#%06x;}" // COLOR_BUTTON_SAVE_HOVER
"a{color:#%06x;text-decoration:none;}" // COLOR_BUTTON
".p{float:left;text-align:left;}"
".q{float:right;text-align:right;}";
".q{float:right;text-align:right;}"
".r{border-radius:0.3em;padding:2px;margin:6px 2px;}";
const char HTTP_HEAD_STYLE3[] PROGMEM =
"</style>"
@ -372,12 +377,17 @@ const char HTTP_HEAD_STYLE3[] PROGMEM =
#endif
"<h2>%s</h2>";
const char HTTP_MSG_SLIDER1[] PROGMEM =
"<div><span class='p'>%s</span><span class='q'>%s</span></div>"
"<div><input type='range' min='%d' max='%d' value='%d' onchange='lb(\"%c\", value)'></div>";
const char HTTP_MSG_SLIDER2[] PROGMEM =
"<div><span class='p'>%s</span><span class='q'>%s</span></div>"
"<div><input type='range' min='%d' max='%d' value='%d' onchange='lc(\"%c\", %d, value)'></div>";
const char HTTP_MSG_SLIDER_GRADIENT[] PROGMEM =
"<div id='%s' class='r' style='background-image:linear-gradient(to right,%s,%s);'><input type='range' min='%d' max='%d' value='%d' onchange='lb(\"%c\",value)'></div>";
const char HTTP_MSG_SLIDER_HUE[] PROGMEM =
"<div class='r' style='background-image:linear-gradient(to right,#800,#f00 5%%,#ff0 20%%,#0f0 35%%,#0ff 50%%,#00f 65%%,#f0f 80%%,#f00 95%%,#800);'>"
"<input type='range' min='1' max='359' value='%d' onchange='ld(\"u\",value)'></div>";
const char HTTP_MSG_SLIDER_CHANNEL[] PROGMEM =
"<div class='r' style='background-image:linear-gradient(to right,#000,%s);'><input type='range' min='1' max='100' value='%d' onchange='lc(\"d\",%d,value)'></div>";
const char HTTP_MSG_SLIDER_SHUTTER[] PROGMEM =
"<div><span class='p'>" D_CLOSE "</span><span class='q'>" D_OPEN "</span></div>"
"<div><input type='range' min='0' max='100' value='%d' onchange='lc(\"u\",%d,value)'></div>";
const char HTTP_MSG_RSTRT[] PROGMEM =
"<br><div style='text-align:center;'>" D_DEVICE_WILL_RESTART "</div><br>";
@ -510,6 +520,7 @@ const char kUploadErrors[] PROGMEM =
"|" D_UPLOAD_ERR_10 "|" D_UPLOAD_ERR_11 "|" D_UPLOAD_ERR_12 "|" D_UPLOAD_ERR_13
#endif
;
const char kChannelColors[] PROGMEM = "#f00|#0f0|#00f|#fff|#ff0"; // Red, Green, Blue, ColdWhite, WarmWhite
const uint16_t DNS_PORT = 53;
enum HttpOptions {HTTP_OFF, HTTP_USER, HTTP_ADMIN, HTTP_MANAGER, HTTP_MANAGER_RESET_ONLY};
@ -951,6 +962,8 @@ void HandleWifiLogin(void)
WSContentStop();
}
void HandleRoot(void)
{
if (CaptivePortal()) { return; } // If captive portal redirect instead of displaying the page.
@ -982,7 +995,7 @@ void HandleRoot(void)
AddLog_P(LOG_LEVEL_DEBUG, S_LOG_HTTP, S_MAIN_MENU);
char stemp[5];
char stemp[10];
WSContentStart_P(S_MAIN_MENU);
#ifdef USE_SCRIPT_WEB_DISPLAY
@ -996,31 +1009,38 @@ void HandleRoot(void)
if (devices_present) {
#ifdef USE_LIGHT
if (light_type) {
uint8_t light_subtype = light_type &7;
if (!Settings.flag3.pwm_multi_channels) { // SetOption68 0 - Enable multi-channels PWM instead of Color PWM
if ((LST_COLDWARM == (light_type &7)) || (LST_RGBWC == (light_type &7))) {
if ((LST_COLDWARM == light_subtype) || (LST_RGBWC == light_subtype)) {
// Cold - Warm &t related to lb("t", value) and WebGetArg("t", tmp, sizeof(tmp));
WSContentSend_P(HTTP_MSG_SLIDER1, F(D_COLDLIGHT), F(D_WARMLIGHT),
153, 500, LightGetColorTemp(), 't');
WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, "a", "#fff", "#ff0", 153, 500, LightGetColorTemp(), 't'); // White to Yellow
}
if (light_subtype > 2) {
uint16_t hue;
uint8_t sat;
uint8_t bri;
LightGetHSB(&hue, &sat, &bri);
WSContentSend_P(HTTP_MSG_SLIDER_HUE, hue); // Hue
snprintf_P(stemp, sizeof(stemp), PSTR("#%02X%02X%02X"), Settings.light_color[0], Settings.light_color[1], Settings.light_color[2]);
// Saturation "s" related to eb('s').style.backgroundImage='linear-gradient(to right,grey,hsl('+p+',100%%,50%%))';
WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, "s", "grey", stemp, 1, 100, changeUIntScale(sat, 0, 255, 0, 100), 'n');
}
// Dark - Bright &d related to lb("d", value) and WebGetArg("d", tmp, sizeof(tmp));
WSContentSend_P(HTTP_MSG_SLIDER1, F(D_DARKLIGHT), F(D_BRIGHTLIGHT),
1, 100, Settings.light_dimmer, 'd');
WSContentSend_P(HTTP_MSG_SLIDER_GRADIENT, "b", "#000", "#fff", 1, 100, Settings.light_dimmer, 'd'); // Black to White
} else { // Settings.flag3.pwm_multi_channels - SetOption68 1 - Enable multi-channels PWM instead of Color PWM
uint32_t pwm_channels = (light_type & 7) > LST_MAX ? LST_MAX : (light_type & 7);
uint32_t pwm_channels = light_subtype > LST_MAX ? LST_MAX : light_subtype;
for (uint32_t i = 0; i < pwm_channels; i++) {
snprintf_P(stemp, sizeof(stemp), PSTR("c%d"), i);
WSContentSend_P(HTTP_MSG_SLIDER2, stemp, FPSTR("100%"),
1, 100,
changeUIntScale(Settings.light_color[i], 0, 255, 0, 100), 'd', i+1);
uint8_t index = (pwm_channels < 3) ? i +3 : i;
WSContentSend_P(HTTP_MSG_SLIDER_CHANNEL, GetTextIndexed(stemp, sizeof(stemp), index, kChannelColors),
changeUIntScale(Settings.light_color[i], 0, 255, 0, 100), i+1); // Dark to Light
}
} // Settings.flag3.pwm_multi_channels
}
#endif
#endif // USE_LIGHT
#ifdef USE_SHUTTER
if (Settings.flag3.shutter_mode) { // SetOption80 - Enable shutter support
for (uint32_t i = 0; i < shutters_present; i++) {
WSContentSend_P(HTTP_MSG_SLIDER2, F(D_CLOSE), F(D_OPEN),
0, 100, Settings.shutter_position[i], 'u', i+1);
WSContentSend_P(HTTP_MSG_SLIDER_SHUTTER, Settings.shutter_position[i], i+1);
}
}
#endif // USE_SHUTTER
@ -1136,6 +1156,16 @@ bool HandleRootStatusRefresh(void)
snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_COLORTEMPERATURE " %s"), tmp);
ExecuteWebCommand(svalue, SRC_WEBGUI);
}
WebGetArg("u", tmp, sizeof(tmp)); // 0 - 359 Hue value
if (strlen(tmp)) {
snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_HSBCOLOR "1 %s"), tmp);
ExecuteWebCommand(svalue, SRC_WEBGUI);
}
WebGetArg("n", tmp, sizeof(tmp)); // 0 - 99 Saturation value
if (strlen(tmp)) {
snprintf_P(svalue, sizeof(svalue), PSTR(D_CMND_HSBCOLOR "2 %s"), tmp);
ExecuteWebCommand(svalue, SRC_WEBGUI);
}
#ifdef USE_SHUTTER
for (uint32_t j = 1; j <= shutters_present; j++) {
snprintf_P(webindex, sizeof(webindex), PSTR("u%d"), j);

View File

@ -1241,6 +1241,10 @@ void LightSetDimmer(uint8_t dimmer) {
light_controller.changeDimmer(dimmer);
}
uint32_t LightGetHSB(uint16_t *hue,uint8_t *sat, uint8_t *bri) {
light_state.getHSB(hue, sat, bri);
}
// If SetOption68 is set, get the brightness for a specific device
uint8_t LightGetBri(uint8_t device) {
uint8_t bri = 254; // default value if relay

View File

@ -1,7 +1,8 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import print_function
VER = '2.4.0037'
from past.builtins import long
VER = '2.4.0039'
"""
decode-config.py - Backup/Restore Tasmota configuration data
@ -23,8 +24,8 @@ VER = '2.4.0037'
Requirements:
- Python
- pip install json pycurl urllib2 configargparse
- Python 2.x:
pip install json requests urllib2 configargparse
Instructions:
@ -198,7 +199,7 @@ try:
import inspect
import json
import configargparse
import pycurl
import requests
if sys.version_info.major==2:
import urllib2
else:
@ -1246,6 +1247,38 @@ def exit(status=0, msg="end", type_=LogType.ERROR, src=None, doexit=True, line=N
sys.exit(exitcode)
def debug(args):
"""
Get debug level
@param args:
configargparse.parse_args() result
@return:
debug level
"""
return 0 if args.debug is None else args.debug
def instance(type_):
"""
Creates Python2/3 compatible isinstance test type(s)
@param args:
Python3 instance type
@return:
Python2/3 compatible isinstance type(s)
"""
newtype = type_
if sys.version_info.major==2:
if type_==str:
newtype = (str,unicode)
elif isinstance(type_, tuple) and str in type_:
newtype = newtype + (unicode,)
return newtype
def ShortHelp(doexit=True):
"""
Show short help (usage) only - ued by own -h handling
@ -1262,36 +1295,6 @@ def ShortHelp(doexit=True):
sys.exit(ExitCode.OK)
class HTTPHeader:
"""
pycurl helper class retrieving the request header
"""
def __init__(self):
self.contents = ''
def clear(self):
self.contents = ''
def store(self, _buffer):
self.contents = "{}{}".format(self.contents, _buffer)
def response(self):
header = str(self.contents).split('\n')
if len(header) > 0:
return header[0].rstrip()
return ''
def contenttype(self):
for item in str(self.contents).split('\n'):
ditem = item.split(":")
if ditem[0].strip().lower() == 'content-type' and len(ditem) > 1:
return ditem[1].strip()
return ''
def __str__(self):
return self.contents
class CustomHelpFormatter(configargparse.HelpFormatter):
"""
Class for customizing the help output
@ -1337,9 +1340,6 @@ def GetTemplateSizes():
"""
Get all possible template sizes as list
@param version:
<int> version number from read binary data to search for
@return:
template sizes as list []
"""
@ -1472,7 +1472,7 @@ def GetVersionStr(version):
@return:
version string
"""
if isinstance(version, (unicode,str)):
if isinstance(version, instance(str)):
version = int(version, 0)
major = ((version>>24) & 0xff)
minor = ((version>>16) & 0xff)
@ -1629,43 +1629,21 @@ def TasmotaGet(cmnd, host, port, username=DEFAULTS['source']['username'], passwo
@return:
binary config data (encrypted) or None on error
"""
body = None
# read config direct from device via http
c = pycurl.Curl()
buffer = io.BytesIO()
c.setopt(c.WRITEDATA, buffer)
header = HTTPHeader()
c.setopt(c.HEADERFUNCTION, header.store)
c.setopt(c.FOLLOWLOCATION, True)
c.setopt(c.URL, MakeUrl(host, port, cmnd))
url = MakeUrl(host, port, cmnd)
auth = None
if username is not None and password is not None:
c.setopt(c.HTTPAUTH, c.HTTPAUTH_BASIC)
c.setopt(c.USERPWD, username + ':' + password)
c.setopt(c.HTTPGET, True)
c.setopt(c.VERBOSE, False)
auth = (username, password)
res = requests.get(url, auth=auth)
responsecode = 200
try:
c.perform()
responsecode = c.getinfo(c.RESPONSE_CODE)
response = header.response()
except Exception as e:
exit(e.args[0], e.args[1], line=inspect.getlineno(inspect.currentframe()))
finally:
c.close()
if not res.ok:
exit(res.status_code, "Error on http GET request for {} - {}".format(url,res.reason), line=inspect.getlineno(inspect.currentframe()))
if responsecode >= 400:
exit(responsecode, 'HTTP result: {}'.format(header.response()),line=inspect.getlineno(inspect.currentframe()))
elif contenttype is not None and header.contenttype()!=contenttype:
if contenttype is not None and res.headers['Content-Type']!=contenttype:
exit(ExitCode.DOWNLOAD_CONFIG_ERROR, "Device did not response properly, may be Tasmota webserver admin mode is disabled (WebServer 2)",line=inspect.getlineno(inspect.currentframe()))
try:
body = buffer.getvalue()
except:
pass
return responsecode, body
return res.status_code, res.content
def GetTasmotaHostname(host, port, username=DEFAULTS['source']['username'], password=None):
@ -1741,7 +1719,7 @@ def PushTasmotaConfig(encode_cfg, host, port, username=DEFAULTS['source']['usern
errorcode, errorstring
errorcode=0 if success, otherwise http response or exception code
"""
if isinstance(encode_cfg, bytearray):
if isinstance(encode_cfg, (bytes,bytearray)):
encode_cfg = str(encode_cfg)
# get restore config page first to set internal Tasmota vars
@ -1749,48 +1727,21 @@ def PushTasmotaConfig(encode_cfg, host, port, username=DEFAULTS['source']['usern
if body is None:
return responsecode, "ERROR"
# post data
c = pycurl.Curl()
header = HTTPHeader()
buffer_ = io.BytesIO()
c.setopt(c.HEADERFUNCTION, header.store)
c.setopt(c.WRITEFUNCTION, lambda x: None)
c.setopt(c.WRITEDATA, buffer_)
c.setopt(c.POST, 1)
c.setopt(c.URL, MakeUrl(host, port, 'u2'))
# ~ # post data
url = MakeUrl(host, port, "u2")
auth = None
if username is not None and password is not None:
c.setopt(c.HTTPAUTH, c.HTTPAUTH_BASIC)
c.setopt(c.USERPWD, username + ':' + password)
try:
isfile = os.path.isfile(encode_cfg)
except:
isfile = False
if isfile:
c.setopt(c.HTTPPOST, [("file", (c.FORM_FILE, encode_cfg))])
else:
# use as binary data
c.setopt(c.HTTPPOST, [
('fileupload', (
c.FORM_BUFFER, '{sprog}_v{sver}.dmp'.format(sprog=os.path.basename(sys.argv[0]), sver=VER),
c.FORM_BUFFERPTR, encode_cfg
)),
])
auth = (username, password)
files = {'u2':('{sprog}_v{sver}.dmp'.format(sprog=os.path.basename(sys.argv[0]), sver=VER), encode_cfg)}
res = requests.post(url, auth=auth, files=files)
responsecode = 200
try:
c.perform()
responsecode = c.getinfo(c.RESPONSE_CODE)
except Exception as e:
return e.args[0], e.args[1]
if not res.ok:
exit(res.status_code, "Error on http POST request for {} - {}".format(url,res.reason), line=inspect.getlineno(inspect.currentframe()))
c.close()
if res.headers['Content-Type']!='text/html':
exit(ExitCode.DOWNLOAD_CONFIG_ERROR, "Device did not response properly, may be Tasmota webserver admin mode is disabled (WebServer 2)",line=inspect.getlineno(inspect.currentframe()))
if responsecode >= 400:
return responsecode, header.response()
elif header.contenttype() != 'text/html':
return ExitCode.UPLOAD_CONFIG_ERROR, "Device did not response properly, may be Tasmota webserver admin mode is disabled (WebServer 2)"
body = buffer_.getvalue()
body = res.content
findUpload = body.find("Upload")
if findUpload < 0:
@ -1818,7 +1769,7 @@ def DecryptEncrypt(obj):
@return:
decrypted configuration (if obj contains encrypted data)
"""
if isinstance(obj, bytearray):
if isinstance(obj, (bytes,bytearray)):
obj = str(obj)
dobj = obj[0:2]
for i in range(2, len(obj)):
@ -1837,7 +1788,7 @@ def GetSettingsCrc(dobj):
2 byte unsigned integer crc value
"""
if isinstance(dobj, bytearray):
if isinstance(dobj, (bytes,bytearray)):
dobj = str(dobj)
version, size, setting = GetTemplateSetting(dobj)
if version < 0x06060007 or version > 0x0606000A:
@ -1862,7 +1813,7 @@ def GetSettingsCrc32(dobj):
4 byte unsigned integer crc value
"""
if isinstance(dobj, bytearray):
if isinstance(dobj, (bytes,bytearray)):
dobj = str(dobj)
crc = 0
for i in range(0, len(dobj)-4):
@ -1907,35 +1858,35 @@ def GetFieldDef(fielddef, fields="format_, addrdef, baseaddr, bits, bitshift, da
raise SyntaxError('<fielddef> error')
# ignore calls with 'root' setting
if isinstance(format_, dict) and baseaddr is None and datadef is None:
if isinstance(format_, instance(dict)) and baseaddr is None and datadef is None:
return eval(fields)
if not isinstance(format_, (unicode,str,dict)):
if not isinstance(format_, instance((str,dict))):
print('wrong <format> {} type {} in <fielddef> {}'.format(format_, type(format_), fielddef), file=sys.stderr)
raise SyntaxError('<fielddef> error')
# extract addrdef items
baseaddr = addrdef
if isinstance(baseaddr, (list,tuple)):
if isinstance(baseaddr, instance((list,tuple))):
if len(baseaddr) == 3:
# baseaddr bit definition
baseaddr, bits, bitshift = baseaddr
if not isinstance(bits, int):
if not isinstance(bits, instance(int)):
print('<bits> must be defined as integer in <fielddef> {}'.format(bits, fielddef), file=sys.stderr)
raise SyntaxError('<fielddef> error')
if not isinstance(bitshift, int):
if not isinstance(bitshift, instance(int)):
print('<bitshift> must be defined as integer in <fielddef> {}'.format(bitshift, fielddef), file=sys.stderr)
raise SyntaxError('<fielddef> error')
else:
print('wrong <addrdef> {} length ({}) in <fielddef> {}'.format(addrdef, len(addrdef), fielddef), file=sys.stderr)
raise SyntaxError('<fielddef> error')
if not isinstance(baseaddr, int):
if not isinstance(baseaddr, instance(int)):
print('<baseaddr> must be defined as integer in <fielddef> {}'.format(baseaddr, fielddef), file=sys.stderr)
raise SyntaxError('<fielddef> error')
# extract datadef items
arraydef = datadef
if isinstance(datadef, (tuple)):
if isinstance(datadef, instance((tuple))):
if len(datadef) == 2:
# datadef has a validator
arraydef, validate = datadef
@ -1943,19 +1894,19 @@ def GetFieldDef(fielddef, fields="format_, addrdef, baseaddr, bits, bitshift, da
# datadef has a validator and cmd set
arraydef, validate, cmd = datadef
# cmd must be a tuple with 2 objects
if isinstance(cmd, (tuple)) and len(cmd) == 2:
if isinstance(cmd, instance((tuple))) and len(cmd) == 2:
group, tasmotacmnd = cmd
if group is not None and not isinstance(group, (str, unicode)):
if group is not None and not isinstance(group, instance(str)):
print('wrong <group> {} in <fielddef> {}'.format(group, fielddef), file=sys.stderr)
raise SyntaxError('<fielddef> error')
if tasmotacmnd is isinstance(tasmotacmnd, tuple):
if tasmotacmnd is isinstance(tasmotacmnd, instance(tuple)):
tasmotacmnds = tasmotacmnd
for tasmotacmnd in tasmotacmnds:
if tasmotacmnd is not None and not callable(tasmotacmnd) and not isinstance(tasmotacmnd, (str, unicode)):
if tasmotacmnd is not None and not callable(tasmotacmnd) and not isinstance(tasmotacmnd, instance(str)):
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)):
if tasmotacmnd is not None and not callable(tasmotacmnd) and not isinstance(tasmotacmnd, instance(str)):
print('wrong <tasmotacmnd> {} in <fielddef> {}'.format(tasmotacmnd, fielddef), file=sys.stderr)
raise SyntaxError('<fielddef> error')
else:
@ -1965,28 +1916,28 @@ def GetFieldDef(fielddef, fields="format_, addrdef, baseaddr, bits, bitshift, da
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)):
if validate is not None and (not isinstance(validate, instance(str)) and not callable(validate)):
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
if isinstance(arraydef, int):
if isinstance(arraydef, instance(int)):
arraydef = [arraydef]
if arraydef is not None and not isinstance(arraydef, (list)):
if arraydef is not None and not isinstance(arraydef, instance((list))):
print('wrong <arraydef> {} type {} in <fielddef> {}'.format(arraydef, type(arraydef), fielddef), file=sys.stderr)
raise SyntaxError('<fielddef> error')
# get read/write converter items
readconverter = converter
if isinstance(converter, (tuple)):
if isinstance(converter, instance((tuple))):
if len(converter) == 2:
# converter has read/write converter
readconverter, writeconverter = converter
if readconverter is not None and not isinstance(readconverter, (str,unicode)) and not callable(readconverter):
if readconverter is not None and not isinstance(readconverter, instance(str)) and not callable(readconverter):
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)):
if writeconverter is not None and (not isinstance(writeconverter, instance((bool,str))) and not callable(writeconverter)):
print('wrong <writeconverter> {} type {} in <fielddef> {}'.format(writeconverter, type(writeconverter), fielddef), file=sys.stderr)
raise SyntaxError('<fielddef> error')
else:
@ -2024,7 +1975,7 @@ def ReadWriteConverter(value, fielddef, read=True, raw=False):
if not raw and converter is not None:
conv = readconverter if read else writeconverter
try:
if isinstance(conv, str): # evaluate strings
if isinstance(conv, instance(str)): # evaluate strings
return eval(conv.replace('$','value'))
elif callable(conv): # use as format function
return conv(value)
@ -2061,7 +2012,7 @@ def CmndConverter(valuemapping, value, idx, fielddef):
if tasmotacmnd is not None and (callable(tasmotacmnd) or len(tasmotacmnd) > 0):
if idx is not None:
idx += 1
if isinstance(tasmotacmnd, str): # evaluate strings
if isinstance(tasmotacmnd, instance(str)): # evaluate strings
if idx is not None:
evalstr = tasmotacmnd.replace('$','value').replace('#','idx').replace('@','valuemapping')
else:
@ -2100,7 +2051,7 @@ def ValidateValue(value, fielddef):
valid = True
try:
if isinstance(validate, str): # evaluate strings
if isinstance(validate, instance(str)): # evaluate strings
valid = eval(validate.replace('$','value'))
elif callable(validate): # use as format function
valid = validate(value)
@ -2121,7 +2072,7 @@ def GetFormatCount(format_):
prefix count or 1 if not specified
"""
if isinstance(format_, str):
if isinstance(format_, instance(str)):
match = re.search("\s*(\d+)", format_)
if match:
return int(match.group(0))
@ -2142,7 +2093,7 @@ def GetFormatType(format_):
formattype = format_
bitsize = 0
if isinstance(format_, str):
if isinstance(format_, instance(str)):
match = re.search("\s*(\D+)", format_)
if match:
formattype = match.group(0)
@ -2204,7 +2155,7 @@ def GetFieldLength(fielddef):
format_, addrdef, arraydef = GetFieldDef(fielddef, fields='format_, addrdef, arraydef')
# <arraydef> contains a integer list
if isinstance(arraydef, list) and len(arraydef) > 0:
if isinstance(arraydef, instance(list)) and len(arraydef) > 0:
# arraydef contains a list
# calc size recursive by sum of all elements
for i in range(0, arraydef[0]):
@ -2215,7 +2166,7 @@ def GetFieldLength(fielddef):
else:
length += GetFieldLength( (format_, addrdef, None) )
elif isinstance(format_, dict):
elif isinstance(format_, instance(dict)):
# -> iterate through format
addr = None
setting = format_
@ -2227,7 +2178,7 @@ def GetFieldLength(fielddef):
length += _len
# a simple value
elif isinstance(format_, str):
elif isinstance(format_, instance(str)):
length = struct.calcsize(format_)
return length
@ -2253,7 +2204,7 @@ def GetSubfieldDef(fielddef):
arraydef = None
# create new datadef
if isinstance(datadef, tuple):
if isinstance(datadef, instance(tuple)):
if cmd is not None:
datadef = (arraydef, validate, cmd)
else:
@ -2346,7 +2297,7 @@ def SetFieldValue(fielddef, dobj, addr, value):
format_, bits, bitshift = GetFieldDef(fielddef, fields='format_, bits, bitshift')
formatcnt = GetFormatCount(format_)
singletype, bitsize = GetFormatType(format_)
if args.debug >= 2:
if debug(args) >= 2:
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
@ -2355,9 +2306,9 @@ def SetFieldValue(fielddef, dobj, addr, value):
maxunsigned = ((2**bitsize) - 1)
maxsigned = ((2**bitsize)>>1)-1
val = value & maxunsigned
if isinstance(value,int) and value < 0 and val > maxsigned:
if isinstance(value,instance(int)) and value < 0 and val > maxsigned:
val = ((maxunsigned+1)-val) * (-1)
if args.debug >= 3:
if debug(args) >= 3:
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)
@ -2369,7 +2320,7 @@ def SetFieldValue(fielddef, dobj, addr, value):
line=inspect.getlineno(inspect.currentframe()))
value >>= bitsize
else:
if args.debug >= 3:
if debug(args) >= 3:
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)
@ -2402,7 +2353,7 @@ def GetField(dobj, fieldname, fielddef, raw=False, addroffset=0):
field mapping
"""
if isinstance(dobj, bytearray):
if isinstance(dobj, instance((bytes,bytearray))):
dobj = str(dobj)
valuemapping = None
@ -2415,7 +2366,7 @@ def GetField(dobj, fieldname, fielddef, raw=False, addroffset=0):
return valuemapping
# <arraydef> contains a integer list
if isinstance(arraydef, list) and len(arraydef) > 0:
if isinstance(arraydef, instance(list)) and len(arraydef) > 0:
valuemapping = []
offset = 0
for i in range(0, arraydef[0]):
@ -2427,7 +2378,7 @@ def GetField(dobj, fieldname, fielddef, raw=False, addroffset=0):
offset += length
# <format> contains a dict
elif isinstance(format_, dict):
elif isinstance(format_, instance(dict)):
mapping_value = {}
# -> iterate through format
for name in format_:
@ -2439,7 +2390,7 @@ def GetField(dobj, fieldname, fielddef, raw=False, addroffset=0):
valuemapping = copy.deepcopy(mapping_value)
# a simple value
elif isinstance(format_, (str, bool, int, float, long)):
elif isinstance(format_, instance((str, bool, int, float, long))):
if GetFieldLength(fielddef) != 0:
valuemapping = ReadWriteConverter(GetFieldValue(fielddef, dobj, baseaddr+addroffset), fielddef, read=True, raw=raw)
@ -2479,12 +2430,12 @@ def SetField(dobj, fieldname, fielddef, restore, addroffset=0, filename=""):
# do not write readonly values
if writeconverter is False:
if args.debug >= 2:
if debug(args) >= 2:
print("SetField(): Readonly '{}' using '{}'/{}{} @{} skipped".format(fieldname, format_, arraydef, bits, hex(baseaddr+addroffset)), file=sys.stderr)
return dobj
# <arraydef> contains a list
if isinstance(arraydef, list) and len(arraydef) > 0:
if isinstance(arraydef, instance(list)) and len(arraydef) > 0:
offset = 0
if len(restore) > arraydef[0]:
exit(ExitCode.RESTORE_DATA_ERROR, "file '{sfile}', array '{sname}[{selem}]' exceeds max number of elements [{smax}]".format(sfile=filename, sname=fieldname, selem=len(restore), smax=arraydef[0]), type_=LogType.WARNING, doexit=not args.ignorewarning, line=inspect.getlineno(inspect.currentframe()))
@ -2499,13 +2450,13 @@ def SetField(dobj, fieldname, fielddef, restore, addroffset=0, filename=""):
offset += length
# <format> contains a dict
elif isinstance(format_, dict):
elif isinstance(format_, instance(dict)):
for name in format_: # -> iterate through format
if name in restore:
dobj = SetField(dobj, name, format_[name], restore[name], addroffset=addroffset, filename=filename)
# a simple value
elif isinstance(format_, (str, bool, int, float, long)):
elif isinstance(format_, instance((str, bool, int, float, long))):
valid = True
err = ""
errformat = ""
@ -2533,7 +2484,7 @@ def SetField(dobj, fieldname, fielddef, restore, addroffset=0, filename=""):
# integer
elif format_[-1:] in ['b','B','h','H','i','I','l','L','q','Q','P']:
value = ReadWriteConverter(restore, fielddef, read=False)
if isinstance(value, (str, unicode)):
if isinstance(value, instance(str)):
value = int(value, 0)
else:
value = int(value)
@ -2605,14 +2556,14 @@ def SetField(dobj, fieldname, fielddef, restore, addroffset=0, filename=""):
# copy value before possible change below
_value = value
if isinstance(_value, (str, unicode)):
if isinstance(_value, instance(str)):
_value = "'{}'".format(_value)
if valid:
if not skip:
if args.debug >= 2:
if debug(args) >= 2:
sbits = " {} bits shift {}".format(bits, bitshift) if bits else ""
strvalue = "{} [{}]".format(_value, hex(value)) if isinstance(_value, int) else _value
strvalue = "{} [{}]".format(_value, hex(value)) if isinstance(_value, instance(int)) else _value
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)
@ -2621,7 +2572,7 @@ def SetField(dobj, fieldname, fielddef, restore, addroffset=0, filename=""):
if prevvalue != curvalue and args.verbose:
message("Value for '{}' changed from {} to {}".format(fieldname, prevvalue, curvalue), type_=LogType.INFO)
else:
if args.debug >= 2:
if debug(args) >= 2:
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
@ -2662,7 +2613,7 @@ def SetCmnd(cmnds, fieldname, fielddef, valuemapping, mappedvalue, addroffset=0,
return cmnds
# <arraydef> contains a list
if isinstance(arraydef, list) and len(arraydef) > 0:
if isinstance(arraydef, instance(list)) and len(arraydef) > 0:
offset = 0
if len(mappedvalue) > arraydef[0]:
exit(ExitCode.RESTORE_DATA_ERROR, "array '{sname}[{selem}]' exceeds max number of elements [{smax}]".format(sname=fieldname, selem=len(mappedvalue), smax=arraydef[0]), type_=LogType.WARNING, doexit=not args.ignorewarning, line=inspect.getlineno(inspect.currentframe()))
@ -2677,23 +2628,23 @@ def SetCmnd(cmnds, fieldname, fielddef, valuemapping, mappedvalue, addroffset=0,
offset += length
# <format> contains a dict
elif isinstance(format_, dict):
elif isinstance(format_, instance(dict)):
for name in format_: # -> iterate through format
if name in mappedvalue:
cmnds = SetCmnd(cmnds, name, format_[name], valuemapping, mappedvalue[name], addroffset=addroffset, idx=idx)
# a simple value
elif isinstance(format_, (str, bool, int, float, long)):
elif isinstance(format_, instance((str, bool, int, float, long))):
if group is not None:
group = group.title();
if isinstance(tasmotacmnd, tuple):
if isinstance(tasmotacmnd, instance(tuple)):
tasmotacmnds = tasmotacmnd
for tasmotacmnd in tasmotacmnds:
cmnd = CmndConverter(valuemapping, mappedvalue, idx, fielddef)
if group is not None and cmnd is not None:
if group not in cmnds:
cmnds[group] = []
if isinstance(cmnd, list):
if isinstance(cmnd, instance(list)):
for c in cmnd:
cmnds[group].append(c)
else:
@ -2703,7 +2654,7 @@ def SetCmnd(cmnds, fieldname, fielddef, valuemapping, mappedvalue, addroffset=0,
if group is not None and cmnd is not None:
if group not in cmnds:
cmnds[group] = []
if isinstance(cmnd, list):
if isinstance(cmnd, instance(list)):
for c in cmnd:
cmnds[group].append(c)
else:
@ -2722,7 +2673,7 @@ def Bin2Mapping(decode_cfg):
@return:
valuemapping data as mapping dictionary
"""
if isinstance(decode_cfg, bytearray):
if isinstance(decode_cfg, instance((bytes,bytearray))):
decode_cfg = str(decode_cfg)
# get binary header and template to use
@ -2814,7 +2765,7 @@ def Mapping2Bin(decode_cfg, jsonconfig, filename=""):
@return:
changed binary config data (decrypted) or None on error
"""
if isinstance(decode_cfg, str):
if isinstance(decode_cfg, instance(str)):
decode_cfg = bytearray(decode_cfg)
@ -2864,7 +2815,7 @@ def Mapping2Cmnd(decode_cfg, valuemapping, filename=""):
@return:
Tasmota command mapping {group: [cmnd <,cmnd <,...>>]}
"""
if isinstance(decode_cfg, str):
if isinstance(decode_cfg, instance(str)):
decode_cfg = bytearray(decode_cfg)
# get binary header data to use the correct version template from device
@ -3297,7 +3248,7 @@ def ParseArgs():
args = parser.parse_args()
if args.debug >= 1:
if debug(args) >= 1:
print(parser.format_values(), file=sys.stderr)
print("Settings:", file=sys.stderr)
for k in args.__dict__: