mirror of https://github.com/arendst/Tasmota.git
Merge branch 'arendst:development' into development
This commit is contained in:
commit
f72dce2f06
|
@ -39,6 +39,10 @@ jobs:
|
|||
- tasmota32-lvgl
|
||||
- tasmota32c3
|
||||
- tasmota32solo1
|
||||
- tasmota32-safemode
|
||||
- tasmota32c3-safemode
|
||||
- tasmota32s2-safemode
|
||||
- tasmota32s3-safemode
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
|
@ -117,7 +121,9 @@ jobs:
|
|||
[ ! -f ./mv_firmware/firmware/tasmota32-core2.* ] || mv ./mv_firmware/firmware/tasmota32-core2.* ./firmware/tasmota32/
|
||||
[ ! -f ./mv_firmware/firmware/tasmota32-bluetooth.* ] || mv ./mv_firmware/firmware/tasmota32-bluetooth.* ./firmware/tasmota32/
|
||||
[ ! -f ./mv_firmware/firmware/tasmota32c3*.* ] || mv ./mv_firmware/firmware/tasmota32c3*.* ./firmware/tasmota32/
|
||||
[ ! -f ./mv_firmware/firmware/tasmota32* ] || mv ./mv_firmware/firmware/tasmota32* ./firmware/tasmota32/languages/
|
||||
[ ! -f ./mv_firmware/firmware/tasmota32-safemode* ] || mv ./mv_firmware/firmware/tasmota32-safemode* ./firmware/tasmota32/
|
||||
[ ! -f ./mv_firmware/firmware/tasmota32-* ] || mv ./mv_firmware/firmware/tasmota32-* ./firmware/tasmota32/languages/
|
||||
[ ! -f ./mv_firmware/firmware/tasmota32* ] || mv ./mv_firmware/firmware/tasmota32* ./firmware/tasmota32/
|
||||
[ ! -f ./mv_firmware/firmware/* ] || mv ./mv_firmware/firmware/* ./firmware/tasmota/languages/
|
||||
- name: Display files to transfer
|
||||
run: ls -R ./*
|
||||
|
|
|
@ -43,6 +43,10 @@ jobs:
|
|||
- tasmota32s2
|
||||
- tasmota32c3
|
||||
- tasmota32solo1
|
||||
- tasmota32-safemode
|
||||
- tasmota32c3-safemode
|
||||
- tasmota32s2-safemode
|
||||
- tasmota32s3-safemode
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Python
|
||||
|
|
|
@ -12,6 +12,7 @@ jobs:
|
|||
|
||||
copy_change:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'arendst/Tasmota'
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Push I2CDevices.md to https://github.com/Tasmota/docs
|
||||
|
|
|
@ -216,6 +216,7 @@ Note: `minimal` variant is not listed as it shouldn't be used outside of the [up
|
|||
| USE_HRE | - | - / x | - | x | - | - |
|
||||
| USE_A4988_STEPPER | - | - / - | - | - | - | - |
|
||||
| USE_NEOPOOL | - | - / - | - | - | - | - |
|
||||
| USE_FLOWRATEMETER | - | - / - | - | - | - | - |
|
||||
| | | | | | | |
|
||||
| Feature or Sensor | l | t | k | s | i | d | Remarks
|
||||
| USE_DISPLAY | - | - / - | - | - | - | x |
|
||||
|
|
|
@ -11,6 +11,7 @@ All notable changes to this project will be documented in this file.
|
|||
- Command ``EnergyExportActive<phase>`` to (p)reset energy export active for supported devices. Currently ADE7880 only (#13515)
|
||||
- Sonoff SPM delayed SetPowerOnState (#13447)
|
||||
- Command ``SetOption139 0/1`` to switch between pressure unit "mmHg" (0) or "inHg" (1) when ``SO24 1`` (#15350)
|
||||
- Support for flowrate meters like YF-DN50 and similary
|
||||
|
||||
### Changed
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
![Tasmota logo](/tools/logo/TASMOTA_FullLogo_Vector.svg)
|
||||
|
||||
Alternative firmware for [ESP8266](https://en.wikipedia.org/wiki/ESP8266) and [ESP32](https://en.wikipedia.org/wiki/ESP32) based devices with **easy configuration using webUI, OTA updates, automation using timers or rules, expandability and entirely local control over MQTT, HTTP, Serial or KNX**.
|
||||
_Written for PlatformIO with limited support for Arduino IDE._
|
||||
_Written for PlatformIO._
|
||||
|
||||
[![GitHub version](https://img.shields.io/github/release/arendst/Tasmota.svg)](http://ota.tasmota.com/tasmota/release)
|
||||
[![GitHub download](https://img.shields.io/github/downloads/arendst/Tasmota/total.svg)](https://github.com/arendst/Tasmota/releases/latest)
|
||||
|
|
|
@ -30,8 +30,8 @@
|
|||
"arduino": {
|
||||
"flash_extra_images": [
|
||||
[
|
||||
"0x2E0000",
|
||||
"variants/tasmota/tasmota32-minicustom.bin"
|
||||
"0x10000",
|
||||
"variants/tasmota/tasmota32-safemode.bin"
|
||||
]
|
||||
]
|
||||
},
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
{
|
||||
"build": {
|
||||
"arduino":{
|
||||
"ldscript": "esp32c3_out.ld"
|
||||
},
|
||||
"core": "esp32",
|
||||
"extra_flags": "-DARDUINO_USB_MODE=1 -DARDUINO_USB_CDC_ON_BOOT=0 -DESP32_4M -DESP32C3",
|
||||
"f_cpu": "160000000L",
|
||||
"f_flash": "80000000L",
|
||||
"flash_mode": "dout",
|
||||
"mcu": "esp32c3",
|
||||
"variant": "esp32c3",
|
||||
"partitions": "esp32_partition_app2880k_spiffs320k.csv"
|
||||
},
|
||||
"connectivity": [
|
||||
"wifi"
|
||||
],
|
||||
"debug": {
|
||||
"openocd_target": "esp32c3.cfg"
|
||||
},
|
||||
"frameworks": [
|
||||
"arduino",
|
||||
"espidf"
|
||||
],
|
||||
"name": "Espressif Generic ESP32-C3 4M Flash, Tasmota 2880k Code/OTA, 320k FS",
|
||||
"upload": {
|
||||
"arduino": {
|
||||
"flash_extra_images": [
|
||||
[
|
||||
"0x10000",
|
||||
"variants/tasmota/tasmota32c3-safemode.bin"
|
||||
]
|
||||
]
|
||||
},
|
||||
"flash_size": "4MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 4194304,
|
||||
"require_upload_port": true,
|
||||
"speed": 460800
|
||||
},
|
||||
"url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32c3/hw-reference/esp32c3/user-guide-devkitm-1.html",
|
||||
"vendor": "Espressif"
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
{
|
||||
"build": {
|
||||
"arduino":{
|
||||
"ldscript": "esp32s2_out.ld"
|
||||
},
|
||||
"core": "esp32",
|
||||
"extra_flags": "-DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 -DESP32_4M -DESP32S2",
|
||||
"f_cpu": "240000000L",
|
||||
"f_flash": "80000000L",
|
||||
"flash_mode": "dout",
|
||||
"mcu": "esp32s2",
|
||||
"variant": "esp32s2",
|
||||
"partitions": "esp32_partition_app2880k_spiffs320k.csv"
|
||||
},
|
||||
"connectivity": [
|
||||
"wifi"
|
||||
],
|
||||
"debug": {
|
||||
"openocd_target": "esp32s2.cfg"
|
||||
},
|
||||
"frameworks": [
|
||||
"espidf",
|
||||
"arduino"
|
||||
],
|
||||
"name": "Espressif Generic ESP32-S2 4M Flash, Tasmota 2880k Code/OTA, 320k FS",
|
||||
"upload": {
|
||||
"arduino": {
|
||||
"flash_extra_images": [
|
||||
[
|
||||
"0x10000",
|
||||
"variants/tasmota/tasmota32s2-safemode.bin"
|
||||
]
|
||||
]
|
||||
},
|
||||
"flash_size": "4MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 4194304,
|
||||
"require_upload_port": true,
|
||||
"speed": 460800
|
||||
},
|
||||
"url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/hw-reference/esp32s2/user-guide-saola-1-v1.2.html",
|
||||
"vendor": "Espressif"
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
{
|
||||
"build": {
|
||||
"arduino":{
|
||||
"ldscript": "esp32s3_out.ld",
|
||||
"memory_type": "qspi_qspi"
|
||||
},
|
||||
"core": "esp32",
|
||||
"extra_flags": "-DBOARD_HAS_PSRAM -DARDUINO_USB_MODE=0 -DARDUINO_USB_CDC_ON_BOOT=0 -DARDUINO_USB_MSC_ON_BOOT=0 -DARDUINO_USB_DFU_ON_BOOT=0 -DESP32_4M -DESP32S3",
|
||||
"f_cpu": "240000000L",
|
||||
"f_flash": "80000000L",
|
||||
"flash_mode": "dio",
|
||||
"mcu": "esp32s3",
|
||||
"variant": "esp32s3",
|
||||
"partitions": "esp32_partition_app2880k_spiffs320k.csv"
|
||||
},
|
||||
"connectivity": [
|
||||
"wifi",
|
||||
"bluetooth",
|
||||
"ethernet"
|
||||
],
|
||||
"debug": {
|
||||
"openocd_target": "esp32s3.cfg"
|
||||
},
|
||||
"frameworks": [
|
||||
"espidf",
|
||||
"arduino"
|
||||
],
|
||||
"name": "Espressif Generic ESP32-S3 4M Flash, Tasmota 2880k Code/OTA, 320k FS",
|
||||
"upload": {
|
||||
"arduino": {
|
||||
"flash_extra_images": [
|
||||
[
|
||||
"0x10000",
|
||||
"variants/tasmota/tasmota32s3-safemode.bin"
|
||||
]
|
||||
]
|
||||
},
|
||||
"flash_size": "4MB",
|
||||
"maximum_ram_size": 327680,
|
||||
"maximum_size": 4194304,
|
||||
"require_upload_port": true,
|
||||
"speed": 460800
|
||||
},
|
||||
"url": "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/hw-reference/esp32s3/",
|
||||
"vendor": "Espressif"
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
# Name, Type, SubType, Offset, Size, Flags
|
||||
nvs, data, nvs, 0x9000, 0x5000,
|
||||
otadata, data, ota, 0xe000, 0x2000,
|
||||
app0, app, ota_0, 0x10000, 0x2D0000,
|
||||
factory, app, factory, 0x2E0000,0xD0000,
|
||||
factory, app, factory, 0x10000, 0xD0000,
|
||||
app0, app, ota_0, 0xE0000, 0x2D0000,
|
||||
spiffs, data, spiffs, 0x3B0000,0x50000,
|
||||
|
|
|
|
@ -46,6 +46,8 @@ be_extern_native_module(hue_ntv);
|
|||
be_extern_native_module(hue_bridge);
|
||||
be_extern_native_module(uuid);
|
||||
be_extern_native_module(animate);
|
||||
be_extern_native_module(partition_core);
|
||||
be_extern_native_module(crc);
|
||||
#ifdef USE_LVGL
|
||||
be_extern_native_module(lv);
|
||||
be_extern_native_module(lv_extra);
|
||||
|
@ -146,6 +148,8 @@ BERRY_LOCAL const bntvmodule* const be_module_table[] = {
|
|||
&be_native_module(webserver),
|
||||
#endif // USE_WEBSERVER
|
||||
&be_native_module(flash),
|
||||
&be_native_module(partition_core),
|
||||
&be_native_module(crc),
|
||||
|
||||
/* user-defined modules register end */
|
||||
NULL /* do not remove */
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
extern const bcstring be_const_str_;
|
||||
extern const bcstring be_const_str_00;
|
||||
extern const bcstring be_const_str_AA50;
|
||||
extern const bcstring be_const_str_AES_GCM;
|
||||
extern const bcstring be_const_str_ALIGN_BOTTOM_MID;
|
||||
extern const bcstring be_const_str_ALIGN_LEFT_MID;
|
||||
|
@ -16,12 +18,13 @@ extern const bcstring be_const_str_Auto_X2Dconfiguration;
|
|||
extern const bcstring be_const_str_BECDFE;
|
||||
extern const bcstring be_const_str_BLE;
|
||||
extern const bcstring be_const_str_BRY_X3A_X20ERROR_X2C_X20bad_X20json_X3A_X20;
|
||||
extern const bcstring be_const_str_BRY_X3A_X20Exception_X3E_X20_X27;
|
||||
extern const bcstring be_const_str_BRY_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s;
|
||||
extern const bcstring be_const_str_BRY_X3A_X20argument_X20must_X20be_X20a_X20function;
|
||||
extern const bcstring be_const_str_BRY_X3A_X20bytecode_X20has_X20wrong_X20version_X20_X27_X25s_X27_X20_X28_X25i_X29;
|
||||
extern const bcstring be_const_str_BRY_X3A_X20corrupt_X20bytecode_X20_X27_X25s_X27;
|
||||
extern const bcstring be_const_str_BRY_X3A_X20could_X20not_X20save_X20compiled_X20file_X20_X25s_X20_X28_X25s_X29;
|
||||
extern const bcstring be_const_str_BRY_X3A_X20failed_X20to_X20load_X20_X27_X25s_X27_X20_X28_X25s_X29;
|
||||
extern const bcstring be_const_str_BRY_X3A_X20failed_X20to_X20load_X20_X27_X25s_X27_X20_X28_X25s_X20_X2D_X20_X25s_X29;
|
||||
extern const bcstring be_const_str_BRY_X3A_X20failed_X20to_X20load_X20_persist_X2Ejson;
|
||||
extern const bcstring be_const_str_BRY_X3A_X20failed_X20to_X20load_X20compiled_X20_X27_X25s_X27_X20_X28_X25s_X29;
|
||||
extern const bcstring be_const_str_BRY_X3A_X20failed_X20to_X20run_X20compiled_X20code_X20_X27_X25s_X27_X20_X2D_X20_X25s;
|
||||
|
@ -50,12 +53,14 @@ extern const bcstring be_const_str_COLOR_BLACK;
|
|||
extern const bcstring be_const_str_COLOR_WHITE;
|
||||
extern const bcstring be_const_str_CT;
|
||||
extern const bcstring be_const_str_DIMMER;
|
||||
extern const bcstring be_const_str_EBEBFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
|
||||
extern const bcstring be_const_str_EC_C25519;
|
||||
extern const bcstring be_const_str_EVENT_DELETE;
|
||||
extern const bcstring be_const_str_EVENT_DRAW_MAIN;
|
||||
extern const bcstring be_const_str_EVENT_DRAW_PART_BEGIN;
|
||||
extern const bcstring be_const_str_EVENT_DRAW_PART_END;
|
||||
extern const bcstring be_const_str_EXTERNAL_I2S;
|
||||
extern const bcstring be_const_str_FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
|
||||
extern const bcstring be_const_str_False;
|
||||
extern const bcstring be_const_str_GET;
|
||||
extern const bcstring be_const_str_HTTP_GET;
|
||||
|
@ -64,17 +69,22 @@ extern const bcstring be_const_str_I2C_Driver;
|
|||
extern const bcstring be_const_str_I2C_X3A;
|
||||
extern const bcstring be_const_str_INTERNAL_DAC;
|
||||
extern const bcstring be_const_str_INTERNAL_PDM;
|
||||
extern const bcstring be_const_str_Invalid_X20ota_X20partition_X20number;
|
||||
extern const bcstring be_const_str_LVG_X3A_X20call_X20to_X20unsupported_X20callback;
|
||||
extern const bcstring be_const_str_Leds;
|
||||
extern const bcstring be_const_str_MAX_RMT;
|
||||
extern const bcstring be_const_str_MD5;
|
||||
extern const bcstring be_const_str_MI32;
|
||||
extern const bcstring be_const_str_No_X20SPIFFS_X20partition_X20found;
|
||||
extern const bcstring be_const_str_None;
|
||||
extern const bcstring be_const_str_OPTION_A;
|
||||
extern const bcstring be_const_str_OneWire;
|
||||
extern const bcstring be_const_str_PART_MAIN;
|
||||
extern const bcstring be_const_str_POST;
|
||||
extern const bcstring be_const_str_Parameter_X20error;
|
||||
extern const bcstring be_const_str_Partition;
|
||||
extern const bcstring be_const_str_Partition_info;
|
||||
extern const bcstring be_const_str_Partition_otadata;
|
||||
extern const bcstring be_const_str_RELAY;
|
||||
extern const bcstring be_const_str_RES_OK;
|
||||
extern const bcstring be_const_str_RGB;
|
||||
|
@ -111,6 +121,7 @@ extern const bcstring be_const_str_TAP_X3A_X20Loaded_X20Tasmota_X20App_X20_X27_X
|
|||
extern const bcstring be_const_str_TASMOTA;
|
||||
extern const bcstring be_const_str_Tasmota;
|
||||
extern const bcstring be_const_str_Tele;
|
||||
extern const bcstring be_const_str_Too_X20many_X20partiition_X20slots;
|
||||
extern const bcstring be_const_str_Trigger;
|
||||
extern const bcstring be_const_str_True;
|
||||
extern const bcstring be_const_str_Unknown;
|
||||
|
@ -120,7 +131,10 @@ extern const bcstring be_const_str_WS2812_GRB;
|
|||
extern const bcstring be_const_str_Wire;
|
||||
extern const bcstring be_const_str__;
|
||||
extern const bcstring be_const_str__X0A;
|
||||
extern const bcstring be_const_str__X0A_X29_X3E;
|
||||
extern const bcstring be_const_str__X20;
|
||||
extern const bcstring be_const_str__X20_X20;
|
||||
extern const bcstring be_const_str__X20_X28;
|
||||
extern const bcstring be_const_str__X21_X3D;
|
||||
extern const bcstring be_const_str__X21_X3D_X3D;
|
||||
extern const bcstring be_const_str__X22;
|
||||
|
@ -138,7 +152,9 @@ extern const bcstring be_const_str__X2508x_X2D_X2504x_X2D_X2504x_X2D_X2504x_X2D_
|
|||
extern const bcstring be_const_str__X25s_X2Eautoconf;
|
||||
extern const bcstring be_const_str__X26lt_X3BError_X3A_X20apply_X20new_X20or_X20remove_X26gt_X3B;
|
||||
extern const bcstring be_const_str__X26lt_X3BNone_X26gt_X3B;
|
||||
extern const bcstring be_const_str__X27_X20_X2D_X20;
|
||||
extern const bcstring be_const_str__X28_X29;
|
||||
extern const bcstring be_const_str__X29;
|
||||
extern const bcstring be_const_str__X2A;
|
||||
extern const bcstring be_const_str__X2B;
|
||||
extern const bcstring be_const_str__X2C;
|
||||
|
@ -172,6 +188,9 @@ extern const bcstring be_const_str__X3C_X3D;
|
|||
extern const bcstring be_const_str__X3Cbutton_X20name_X3D_X27reapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3ERe_X2Dapply_X20current_X20configuration_X3C_X2Fbutton_X3E;
|
||||
extern const bcstring be_const_str__X3Cbutton_X20name_X3D_X27zipapply_X27_X20class_X3D_X27button_X20bgrn_X27_X3EApply_X20configuration_X3C_X2Fbutton_X3E;
|
||||
extern const bcstring be_const_str__X3Cfieldset_X3E_X3Cstyle_X3E_X2Ebdis_X7Bbackground_X3A_X23888_X3B_X7D_X2Ebdis_X3Ahover_X7Bbackground_X3A_X23888_X3B_X7D_X3C_X2Fstyle_X3E;
|
||||
extern const bcstring be_const_str__X3Cinstance_X3A_X20Partition_X28_X5B_X0A;
|
||||
extern const bcstring be_const_str__X3Cinstance_X3A_X20Partition_info_X28_X25d_X25s_X2C_X25d_X25s_X2C0x_X2508X_X2C0x_X2508X_X2C_X27_X25s_X27_X2C0x_X25X_X29_X3E;
|
||||
extern const bcstring be_const_str__X3Cinstance_X3A_X20Partition_otadata_X28ota_active_X3A_X25d_X2C_X20ota_seq_X3D_X5B_X25d_X2C_X25d_X5D_X2C_X20ota_max_X3D_X25d_X29_X3E;
|
||||
extern const bcstring be_const_str__X3Cinstance_X3A_X20_X25s_X28_X25s_X2C_X20_X25s_X2C_X20_X25s_X29;
|
||||
extern const bcstring be_const_str__X3Clabel_X3EChoose_X20a_X20device_X20configuration_X3A_X3C_X2Flabel_X3E_X3Cbr_X3E;
|
||||
extern const bcstring be_const_str__X3Clambda_X3E;
|
||||
|
@ -195,6 +214,7 @@ extern const bcstring be_const_str__X3E_X3D;
|
|||
extern const bcstring be_const_str__X3F;
|
||||
extern const bcstring be_const_str__X5B;
|
||||
extern const bcstring be_const_str__X5D;
|
||||
extern const bcstring be_const_str__X5D_X2C_X0A_X20_X20;
|
||||
extern const bcstring be_const_str__X7B;
|
||||
extern const bcstring be_const_str__X7B_X7D;
|
||||
extern const bcstring be_const_str__X7Bs_X7DBatt_X20Current_X7Bm_X7D_X25_X2E1f_X20mA_X7Be_X7D;
|
||||
|
@ -238,12 +258,15 @@ extern const bcstring be_const_str__rules;
|
|||
extern const bcstring be_const_str__settings_def;
|
||||
extern const bcstring be_const_str__settings_ptr;
|
||||
extern const bcstring be_const_str__splash;
|
||||
extern const bcstring be_const_str__subscribe;
|
||||
extern const bcstring be_const_str__t;
|
||||
extern const bcstring be_const_str__timers;
|
||||
extern const bcstring be_const_str__validate;
|
||||
extern const bcstring be_const_str__write;
|
||||
extern const bcstring be_const_str_a;
|
||||
extern const bcstring be_const_str_abs;
|
||||
extern const bcstring be_const_str_acos;
|
||||
extern const bcstring be_const_str_active_otadata;
|
||||
extern const bcstring be_const_str_add;
|
||||
extern const bcstring be_const_str_add_anim;
|
||||
extern const bcstring be_const_str_add_cb_event_closure;
|
||||
|
@ -264,6 +287,7 @@ extern const bcstring be_const_str_allocated;
|
|||
extern const bcstring be_const_str_alternate;
|
||||
extern const bcstring be_const_str_animate;
|
||||
extern const bcstring be_const_str_animators;
|
||||
extern const bcstring be_const_str_app;
|
||||
extern const bcstring be_const_str_arc_dsc;
|
||||
extern const bcstring be_const_str_arch;
|
||||
extern const bcstring be_const_str_area;
|
||||
|
@ -353,11 +377,17 @@ extern const bcstring be_const_str_content_stop;
|
|||
extern const bcstring be_const_str_continue;
|
||||
extern const bcstring be_const_str_coord_arr;
|
||||
extern const bcstring be_const_str_copy;
|
||||
extern const bcstring be_const_str_coredump;
|
||||
extern const bcstring be_const_str_cos;
|
||||
extern const bcstring be_const_str_cosh;
|
||||
extern const bcstring be_const_str_couldn_X27t_X20not_X20initialize_X20noepixelbus;
|
||||
extern const bcstring be_const_str_count;
|
||||
extern const bcstring be_const_str_counters;
|
||||
extern const bcstring be_const_str_crc;
|
||||
extern const bcstring be_const_str_crc16;
|
||||
extern const bcstring be_const_str_crc32;
|
||||
extern const bcstring be_const_str_crc32_ota_seq;
|
||||
extern const bcstring be_const_str_crc8;
|
||||
extern const bcstring be_const_str_create_custom_widget;
|
||||
extern const bcstring be_const_str_create_matrix;
|
||||
extern const bcstring be_const_str_create_segment;
|
||||
|
@ -366,6 +396,7 @@ extern const bcstring be_const_str_ctor;
|
|||
extern const bcstring be_const_str_ctypes_bytes;
|
||||
extern const bcstring be_const_str_ctypes_bytes_dyn;
|
||||
extern const bcstring be_const_str_dac_voltage;
|
||||
extern const bcstring be_const_str_data;
|
||||
extern const bcstring be_const_str_day;
|
||||
extern const bcstring be_const_str_debug;
|
||||
extern const bcstring be_const_str_decode;
|
||||
|
@ -403,6 +434,7 @@ extern const bcstring be_const_str_driver_name;
|
|||
extern const bcstring be_const_str_dump;
|
||||
extern const bcstring be_const_str_duration;
|
||||
extern const bcstring be_const_str_editable;
|
||||
extern const bcstring be_const_str_efuse_em;
|
||||
extern const bcstring be_const_str_elements_X20must_X20be_X20a_X20lv_point;
|
||||
extern const bcstring be_const_str_elif;
|
||||
extern const bcstring be_const_str_else;
|
||||
|
@ -413,6 +445,7 @@ extern const bcstring be_const_str_energy_struct;
|
|||
extern const bcstring be_const_str_engine;
|
||||
extern const bcstring be_const_str_erase;
|
||||
extern const bcstring be_const_str_escape;
|
||||
extern const bcstring be_const_str_esphttpd;
|
||||
extern const bcstring be_const_str_eth;
|
||||
extern const bcstring be_const_str_event;
|
||||
extern const bcstring be_const_str_event_cb;
|
||||
|
@ -428,9 +461,11 @@ extern const bcstring be_const_str_exec_tele;
|
|||
extern const bcstring be_const_str_exists;
|
||||
extern const bcstring be_const_str_exp;
|
||||
extern const bcstring be_const_str_f;
|
||||
extern const bcstring be_const_str_factory;
|
||||
extern const bcstring be_const_str_false;
|
||||
extern const bcstring be_const_str_fast_loop;
|
||||
extern const bcstring be_const_str_fast_loop_enabled;
|
||||
extern const bcstring be_const_str_fat;
|
||||
extern const bcstring be_const_str_file;
|
||||
extern const bcstring be_const_str_file_X20extension_X20is_X20not_X20_X27_X2Ebe_X27_X20or_X20_X27_X2Ebec_X27;
|
||||
extern const bcstring be_const_str_files;
|
||||
|
@ -438,6 +473,8 @@ extern const bcstring be_const_str_find;
|
|||
extern const bcstring be_const_str_find_key_i;
|
||||
extern const bcstring be_const_str_find_op;
|
||||
extern const bcstring be_const_str_finish;
|
||||
extern const bcstring be_const_str_flags;
|
||||
extern const bcstring be_const_str_flash;
|
||||
extern const bcstring be_const_str_floor;
|
||||
extern const bcstring be_const_str_flush;
|
||||
extern const bcstring be_const_str_font_embedded;
|
||||
|
@ -460,6 +497,7 @@ extern const bcstring be_const_str_gc;
|
|||
extern const bcstring be_const_str_gen_cb;
|
||||
extern const bcstring be_const_str_get;
|
||||
extern const bcstring be_const_str_get_MAC;
|
||||
extern const bcstring be_const_str_get_active;
|
||||
extern const bcstring be_const_str_get_alternate;
|
||||
extern const bcstring be_const_str_get_aps_voltage;
|
||||
extern const bcstring be_const_str_get_bat_charge_current;
|
||||
|
@ -476,12 +514,14 @@ extern const bcstring be_const_str_get_event_cb;
|
|||
extern const bcstring be_const_str_get_free_heap;
|
||||
extern const bcstring be_const_str_get_height;
|
||||
extern const bcstring be_const_str_get_hor_res;
|
||||
extern const bcstring be_const_str_get_image_size;
|
||||
extern const bcstring be_const_str_get_input_power_status;
|
||||
extern const bcstring be_const_str_get_light;
|
||||
extern const bcstring be_const_str_get_log;
|
||||
extern const bcstring be_const_str_get_name;
|
||||
extern const bcstring be_const_str_get_object_from_ptr;
|
||||
extern const bcstring be_const_str_get_option;
|
||||
extern const bcstring be_const_str_get_ota_slot;
|
||||
extern const bcstring be_const_str_get_percentage;
|
||||
extern const bcstring be_const_str_get_pixel_color;
|
||||
extern const bcstring be_const_str_get_power;
|
||||
|
@ -540,12 +580,17 @@ extern const bcstring be_const_str_int64;
|
|||
extern const bcstring be_const_str_internal_error;
|
||||
extern const bcstring be_const_str_introspect;
|
||||
extern const bcstring be_const_str_invalid_X20GPIO_X20number;
|
||||
extern const bcstring be_const_str_invalid_X20magic_X20number_X20_X2502X;
|
||||
extern const bcstring be_const_str_invalidate;
|
||||
extern const bcstring be_const_str_invalidate_spiffs;
|
||||
extern const bcstring be_const_str_io_error;
|
||||
extern const bcstring be_const_str_ip;
|
||||
extern const bcstring be_const_str_is_dirty;
|
||||
extern const bcstring be_const_str_is_factory;
|
||||
extern const bcstring be_const_str_is_first_time;
|
||||
extern const bcstring be_const_str_is_ota;
|
||||
extern const bcstring be_const_str_is_running;
|
||||
extern const bcstring be_const_str_is_spiffs;
|
||||
extern const bcstring be_const_str_isinstance;
|
||||
extern const bcstring be_const_str_ismethod;
|
||||
extern const bcstring be_const_str_isnan;
|
||||
|
@ -575,6 +620,7 @@ extern const bcstring be_const_str_list_handlers;
|
|||
extern const bcstring be_const_str_listdir;
|
||||
extern const bcstring be_const_str_load;
|
||||
extern const bcstring be_const_str_load_freetype_font;
|
||||
extern const bcstring be_const_str_load_otadata;
|
||||
extern const bcstring be_const_str_load_templates;
|
||||
extern const bcstring be_const_str_local;
|
||||
extern const bcstring be_const_str_log;
|
||||
|
@ -610,6 +656,8 @@ extern const bcstring be_const_str_manuf;
|
|||
extern const bcstring be_const_str_map;
|
||||
extern const bcstring be_const_str_math;
|
||||
extern const bcstring be_const_str_matrix;
|
||||
extern const bcstring be_const_str_maxota;
|
||||
extern const bcstring be_const_str_md5;
|
||||
extern const bcstring be_const_str_member;
|
||||
extern const bcstring be_const_str_members;
|
||||
extern const bcstring be_const_str_memory;
|
||||
|
@ -621,6 +669,9 @@ extern const bcstring be_const_str_model;
|
|||
extern const bcstring be_const_str_module;
|
||||
extern const bcstring be_const_str_month;
|
||||
extern const bcstring be_const_str_montserrat_font;
|
||||
extern const bcstring be_const_str_mqtt;
|
||||
extern const bcstring be_const_str_mqtt_data;
|
||||
extern const bcstring be_const_str_mqtt_listener;
|
||||
extern const bcstring be_const_str_name;
|
||||
extern const bcstring be_const_str_nan;
|
||||
extern const bcstring be_const_str_next;
|
||||
|
@ -631,6 +682,8 @@ extern const bcstring be_const_str_no_X20more_X20RMT_X20channel_X20available;
|
|||
extern const bcstring be_const_str_now;
|
||||
extern const bcstring be_const_str_null_cb;
|
||||
extern const bcstring be_const_str_number;
|
||||
extern const bcstring be_const_str_nvs;
|
||||
extern const bcstring be_const_str_nvskeys;
|
||||
extern const bcstring be_const_str_o;
|
||||
extern const bcstring be_const_str_obj;
|
||||
extern const bcstring be_const_str_obj_class_create_obj;
|
||||
|
@ -641,12 +694,17 @@ extern const bcstring be_const_str_on;
|
|||
extern const bcstring be_const_str_onsubmit_X3D_X27return_X20confirm_X28_X22This_X20will_X20cause_X20a_X20restart_X2E_X22_X29_X3B_X27_X3E;
|
||||
extern const bcstring be_const_str_onsubmit_X3D_X27return_X20confirm_X28_X22This_X20will_X20change_X20the_X20current_X20configuration_X20and_X20cause_X20a_X20restart_X2E_X22_X29_X3B_X27_X3E;
|
||||
extern const bcstring be_const_str_open;
|
||||
extern const bcstring be_const_str_ota;
|
||||
extern const bcstring be_const_str_ota_max;
|
||||
extern const bcstring be_const_str_otadata;
|
||||
extern const bcstring be_const_str_out_X20of_X20range;
|
||||
extern const bcstring be_const_str_p1;
|
||||
extern const bcstring be_const_str_p2;
|
||||
extern const bcstring be_const_str_page_autoconf_ctl;
|
||||
extern const bcstring be_const_str_page_autoconf_mgr;
|
||||
extern const bcstring be_const_str_param;
|
||||
extern const bcstring be_const_str_parse;
|
||||
extern const bcstring be_const_str_partition_core;
|
||||
extern const bcstring be_const_str_path;
|
||||
extern const bcstring be_const_str_pc;
|
||||
extern const bcstring be_const_str_pc_abs;
|
||||
|
@ -655,6 +713,7 @@ extern const bcstring be_const_str_pct;
|
|||
extern const bcstring be_const_str_percentage;
|
||||
extern const bcstring be_const_str_persist;
|
||||
extern const bcstring be_const_str_persist_X2E_p_X20is_X20not_X20a_X20map;
|
||||
extern const bcstring be_const_str_phy;
|
||||
extern const bcstring be_const_str_pi;
|
||||
extern const bcstring be_const_str_pin;
|
||||
extern const bcstring be_const_str_pin_mode;
|
||||
|
@ -683,6 +742,7 @@ extern const bcstring be_const_str_rad;
|
|||
extern const bcstring be_const_str_raise;
|
||||
extern const bcstring be_const_str_rand;
|
||||
extern const bcstring be_const_str_range;
|
||||
extern const bcstring be_const_str_raw;
|
||||
extern const bcstring be_const_str_read;
|
||||
extern const bcstring be_const_str_read12;
|
||||
extern const bcstring be_const_str_read13;
|
||||
|
@ -710,6 +770,7 @@ extern const bcstring be_const_str_remove_driver;
|
|||
extern const bcstring be_const_str_remove_light;
|
||||
extern const bcstring be_const_str_remove_rule;
|
||||
extern const bcstring be_const_str_remove_timer;
|
||||
extern const bcstring be_const_str_remove_trailing_zeroes;
|
||||
extern const bcstring be_const_str_reset;
|
||||
extern const bcstring be_const_str_reset_search;
|
||||
extern const bcstring be_const_str_resize;
|
||||
|
@ -724,6 +785,7 @@ extern const bcstring be_const_str_return;
|
|||
extern const bcstring be_const_str_return_X20code_X3D_X25i;
|
||||
extern const bcstring be_const_str_reverse;
|
||||
extern const bcstring be_const_str_reverse_gamma10;
|
||||
extern const bcstring be_const_str_rollback;
|
||||
extern const bcstring be_const_str_rotate;
|
||||
extern const bcstring be_const_str_round_end;
|
||||
extern const bcstring be_const_str_round_start;
|
||||
|
@ -748,9 +810,12 @@ extern const bcstring be_const_str_seg7_font;
|
|||
extern const bcstring be_const_str_select;
|
||||
extern const bcstring be_const_str_send;
|
||||
extern const bcstring be_const_str_send_multicast;
|
||||
extern const bcstring be_const_str_seq0;
|
||||
extern const bcstring be_const_str_seq1;
|
||||
extern const bcstring be_const_str_serial;
|
||||
extern const bcstring be_const_str_set;
|
||||
extern const bcstring be_const_str_set_MAC;
|
||||
extern const bcstring be_const_str_set_active;
|
||||
extern const bcstring be_const_str_set_align;
|
||||
extern const bcstring be_const_str_set_alternate;
|
||||
extern const bcstring be_const_str_set_auth;
|
||||
|
@ -776,6 +841,7 @@ extern const bcstring be_const_str_set_light;
|
|||
extern const bcstring be_const_str_set_matrix_pixel_color;
|
||||
extern const bcstring be_const_str_set_mode_ct;
|
||||
extern const bcstring be_const_str_set_mode_rgb;
|
||||
extern const bcstring be_const_str_set_ota_max;
|
||||
extern const bcstring be_const_str_set_percentage;
|
||||
extern const bcstring be_const_str_set_pixel_color;
|
||||
extern const bcstring be_const_str_set_power;
|
||||
|
@ -824,7 +890,9 @@ extern const bcstring be_const_str_sin;
|
|||
extern const bcstring be_const_str_sinh;
|
||||
extern const bcstring be_const_str_size;
|
||||
extern const bcstring be_const_str_skip;
|
||||
extern const bcstring be_const_str_slots;
|
||||
extern const bcstring be_const_str_solidified;
|
||||
extern const bcstring be_const_str_spiffs;
|
||||
extern const bcstring be_const_str_splash;
|
||||
extern const bcstring be_const_str_splash_init;
|
||||
extern const bcstring be_const_str_splash_remove;
|
||||
|
@ -844,8 +912,10 @@ extern const bcstring be_const_str_strip;
|
|||
extern const bcstring be_const_str_strptime;
|
||||
extern const bcstring be_const_str_style_prop_arr;
|
||||
extern const bcstring be_const_str_subscribe;
|
||||
extern const bcstring be_const_str_subtype;
|
||||
extern const bcstring be_const_str_success;
|
||||
extern const bcstring be_const_str_super;
|
||||
extern const bcstring be_const_str_switch_factory;
|
||||
extern const bcstring be_const_str_sys;
|
||||
extern const bcstring be_const_str_tag;
|
||||
extern const bcstring be_const_str_tan;
|
||||
|
@ -858,6 +928,7 @@ extern const bcstring be_const_str_tasmota_X2Eset_light_X28_X29_X20is_X20depreca
|
|||
extern const bcstring be_const_str_tasmota_log_reader;
|
||||
extern const bcstring be_const_str_tcpclient;
|
||||
extern const bcstring be_const_str_tele;
|
||||
extern const bcstring be_const_str_test;
|
||||
extern const bcstring be_const_str_the_X20second_X20argument_X20is_X20not_X20a_X20function;
|
||||
extern const bcstring be_const_str_time_dump;
|
||||
extern const bcstring be_const_str_time_reached;
|
||||
|
@ -870,6 +941,7 @@ extern const bcstring be_const_str_toint;
|
|||
extern const bcstring be_const_str_tolower;
|
||||
extern const bcstring be_const_str_tomap;
|
||||
extern const bcstring be_const_str_top;
|
||||
extern const bcstring be_const_str_topic;
|
||||
extern const bcstring be_const_str_toptr;
|
||||
extern const bcstring be_const_str_tostring;
|
||||
extern const bcstring be_const_str_touch_update;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,19 @@
|
|||
#include "be_constobj.h"
|
||||
|
||||
static be_define_const_map_slots(m_libcrc_map) {
|
||||
{ be_const_key(crc32, 1), be_const_ctype_func(c_crc32) },
|
||||
{ be_const_key(crc8, 2), be_const_ctype_func(c_crc8) },
|
||||
{ be_const_key(crc16, -1), be_const_ctype_func(c_crc16) },
|
||||
};
|
||||
|
||||
static be_define_const_map(
|
||||
m_libcrc_map,
|
||||
3
|
||||
);
|
||||
|
||||
static be_define_const_module(
|
||||
m_libcrc,
|
||||
"crc"
|
||||
);
|
||||
|
||||
BE_EXPORT_VARIABLE be_define_const_native_module(crc);
|
|
@ -1,14 +1,15 @@
|
|||
#include "be_constobj.h"
|
||||
|
||||
static be_define_const_map_slots(m_libflash_map) {
|
||||
{ be_const_key(read, -1), be_const_func(p_flash_read) },
|
||||
{ be_const_key(erase, -1), be_const_func(p_flash_erase) },
|
||||
{ be_const_key(write, -1), be_const_func(p_flash_write) },
|
||||
{ be_const_key(factory, 2), be_const_ctype_func(p_factory) },
|
||||
{ be_const_key(erase, 3), be_const_func(p_flash_erase) },
|
||||
{ be_const_key(read, -1), be_const_func(p_flash_read) },
|
||||
};
|
||||
|
||||
static be_define_const_map(
|
||||
m_libflash_map,
|
||||
3
|
||||
4
|
||||
);
|
||||
|
||||
static be_define_const_module(
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
#include "be_constobj.h"
|
||||
|
||||
static be_define_const_map_slots(m_libmqtt_map) {
|
||||
{ be_const_key(unsubscribe, -1), be_const_ctype_func(be_mqtt_unsubscribe) },
|
||||
{ be_const_key(subscribe, -1), be_const_ctype_func(be_mqtt_subscribe) },
|
||||
{ be_const_key(publish, 1), be_const_func(be_mqtt_publish) },
|
||||
{ be_const_key(publish, -1), be_const_func(be_mqtt_publish) },
|
||||
{ be_const_key(_subscribe, -1), be_const_ctype_func(be_mqtt_subscribe) },
|
||||
{ be_const_key(unsubscribe, 1), be_const_ctype_func(be_mqtt_unsubscribe) },
|
||||
{ be_const_key(subscribe, -1), be_const_closure(subscribe_closure) },
|
||||
};
|
||||
|
||||
static be_define_const_map(
|
||||
m_libmqtt_map,
|
||||
3
|
||||
4
|
||||
);
|
||||
|
||||
static be_define_const_module(
|
||||
|
|
|
@ -511,7 +511,7 @@ static void m_solidify_subclass(bvm *vm, bbool str_literal, bclass *cl, int buil
|
|||
size_t id_len = toidentifier_length(class_name);
|
||||
char id_buf[id_len];
|
||||
toidentifier(id_buf, class_name);
|
||||
logfmt(" &be_const_str_%s,\n", id_buf);
|
||||
logfmt(" (bstring*) &be_const_str_%s\n", id_buf);
|
||||
} else {
|
||||
size_t id_len = toliteral_length(class_name);
|
||||
char id_buf[id_len];
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
/********************************************************************
|
||||
* Berry module `webserver`
|
||||
*
|
||||
* To use: `import webserver`
|
||||
*
|
||||
* Allows to respond to HTTP request
|
||||
*******************************************************************/
|
||||
#include "be_constobj.h"
|
||||
#include "be_mapping.h"
|
||||
|
||||
#include "rom/crc.h"
|
||||
|
||||
uint32_t c_crc32(uint32_t crc, const uint8_t* buf, size_t size) {
|
||||
return crc32_le(crc, buf, size);
|
||||
}
|
||||
BE_FUNC_CTYPE_DECLARE(c_crc32, "i", "i(bytes)~")
|
||||
|
||||
uint32_t c_crc16(uint32_t crc, const uint8_t* buf, size_t size) {
|
||||
return crc16_le(crc, buf, size);
|
||||
}
|
||||
BE_FUNC_CTYPE_DECLARE(c_crc16, "i", "i(bytes)~")
|
||||
|
||||
uint32_t c_crc8(uint32_t crc, const uint8_t* buf, size_t size) {
|
||||
return crc8_le(crc, buf, size);
|
||||
}
|
||||
BE_FUNC_CTYPE_DECLARE(c_crc8, "i", "i(bytes)~")
|
||||
|
||||
// const uint32_t crc32_tab[] = {
|
||||
// 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
||||
// 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||
// 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
||||
// 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
// 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
||||
// 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||
// 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
|
||||
// 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
// 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
||||
// 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
// 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
|
||||
// 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
// 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
|
||||
// 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||
// 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||
// 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
// 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
|
||||
// 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||
// 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
|
||||
// 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
// 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
||||
// 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||
// 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
|
||||
// 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
// 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
||||
// 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||
// 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
||||
// 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
// 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
|
||||
// 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
// 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
|
||||
// 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
// 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
||||
// 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||
// 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||
// 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
// 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
|
||||
// 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||
// 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
||||
// 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
// 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
|
||||
// 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
// 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
||||
// };
|
||||
|
||||
// uint32_t c_crc32(uint32_t crc, const uint8_t *p, size_t size) {
|
||||
// crc ^= ~0U;
|
||||
// while (size--)
|
||||
// crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
|
||||
// return crc ^ ~0U;
|
||||
// }
|
||||
|
||||
/* @const_object_info_begin
|
||||
module crc (scope: global) {
|
||||
crc32, ctype_func(c_crc32)
|
||||
crc16, ctype_func(c_crc16)
|
||||
crc8, ctype_func(c_crc8)
|
||||
}
|
||||
@const_object_info_end */
|
||||
#include "be_fixed_crc.h"
|
|
@ -6,6 +6,18 @@
|
|||
* Allows to respond to HTTP request
|
||||
*******************************************************************/
|
||||
#include "be_constobj.h"
|
||||
#include "be_mapping.h"
|
||||
|
||||
#include "esp_partition.h"
|
||||
|
||||
// Forces the next restart to use the `factory` partition if any is present
|
||||
void p_factory(void) {
|
||||
const esp_partition_t *otadata_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
|
||||
if (otadata_partition) {
|
||||
esp_partition_erase_range(otadata_partition, 0, SPI_FLASH_SEC_SIZE * 2);
|
||||
}
|
||||
}
|
||||
BE_FUNC_CTYPE_DECLARE(p_factory, "", "");
|
||||
|
||||
extern int p_flash_read(bvm *vm);
|
||||
extern int p_flash_write(bvm *vm);
|
||||
|
@ -16,6 +28,8 @@ module flash (scope: global) {
|
|||
read, func(p_flash_read)
|
||||
write, func(p_flash_write)
|
||||
erase, func(p_flash_erase)
|
||||
|
||||
factory, ctype_func(p_factory)
|
||||
}
|
||||
@const_object_info_end */
|
||||
#include "be_fixed_flash.h"
|
||||
|
|
|
@ -0,0 +1,288 @@
|
|||
/********************************************************************
|
||||
* Berry module `mqtt`
|
||||
*
|
||||
*******************************************************************/
|
||||
|
||||
#include "be_constobj.h"
|
||||
#include "be_mapping.h"
|
||||
|
||||
/* Embedded code */
|
||||
|
||||
/*
|
||||
|
||||
def subscribe(topic, closure)
|
||||
class mqtt_listener
|
||||
var topic
|
||||
var closure
|
||||
|
||||
def init(topic, closure)
|
||||
import string
|
||||
self.topic = string.split(topic, '/')
|
||||
self.closure = closure
|
||||
tasmota.add_driver(self)
|
||||
end
|
||||
|
||||
def mqtt_data(topic, idx, payload_s, payload_b)
|
||||
# check if the topic matches the patter
|
||||
import string
|
||||
var topic_elts = string.split(topic, '/')
|
||||
var topic_sz = size(topic_elts)
|
||||
var pat = self.topic
|
||||
var pat_sz = size(pat)
|
||||
var i = 0
|
||||
while i < pat_sz
|
||||
var pat_elt = pat[i]
|
||||
|
||||
if pat_elt == '#'
|
||||
# joker, munch whatever is left
|
||||
# '#' is supposed to be the last character of the topic (we don't check it)
|
||||
break
|
||||
elif i >= topic_sz
|
||||
# the topic is too short - no match
|
||||
return false
|
||||
elif pat_elt == '+'
|
||||
# pass
|
||||
elif pat_elt != topic_elts[i]
|
||||
# topic element are different - no match
|
||||
return false
|
||||
end
|
||||
|
||||
i += 1
|
||||
end
|
||||
|
||||
if i >= pat_sz && pat_sz != topic_sz
|
||||
# the topic is too long and the pattern did not finish with '#' - no match
|
||||
return false
|
||||
end
|
||||
|
||||
var cl = self.closure
|
||||
var ret = cl(topic, idx, payload_s, payload_b)
|
||||
if ret == nil ret = true end # return true if the return value is forgotten
|
||||
return ret
|
||||
end
|
||||
end
|
||||
|
||||
import mqtt
|
||||
mqtt._subscribe(topic)
|
||||
if type(closure) == 'function'
|
||||
tasmota.check_not_method(closure)
|
||||
mqtt_listener(topic, closure)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: mqtt_data
|
||||
********************************************************************/
|
||||
be_local_closure(mqtt_listener_mqtt_data, /* name */
|
||||
be_nested_proto(
|
||||
17, /* nstack */
|
||||
5, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[ 9]) { /* constants */
|
||||
/* K0 */ be_nested_str(string),
|
||||
/* K1 */ be_nested_str(split),
|
||||
/* K2 */ be_nested_str(_X2F),
|
||||
/* K3 */ be_nested_str(topic),
|
||||
/* K4 */ be_const_int(0),
|
||||
/* K5 */ be_nested_str(_X23),
|
||||
/* K6 */ be_nested_str(_X2B),
|
||||
/* K7 */ be_const_int(1),
|
||||
/* K8 */ be_nested_str(closure),
|
||||
}),
|
||||
&be_const_str_mqtt_data,
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[53]) { /* code */
|
||||
0xA4160000, // 0000 IMPORT R5 K0
|
||||
0x8C180B01, // 0001 GETMET R6 R5 K1
|
||||
0x5C200200, // 0002 MOVE R8 R1
|
||||
0x58240002, // 0003 LDCONST R9 K2
|
||||
0x7C180600, // 0004 CALL R6 3
|
||||
0x601C000C, // 0005 GETGBL R7 G12
|
||||
0x5C200C00, // 0006 MOVE R8 R6
|
||||
0x7C1C0200, // 0007 CALL R7 1
|
||||
0x88200103, // 0008 GETMBR R8 R0 K3
|
||||
0x6024000C, // 0009 GETGBL R9 G12
|
||||
0x5C281000, // 000A MOVE R10 R8
|
||||
0x7C240200, // 000B CALL R9 1
|
||||
0x58280004, // 000C LDCONST R10 K4
|
||||
0x142C1409, // 000D LT R11 R10 R9
|
||||
0x782E0013, // 000E JMPF R11 #0023
|
||||
0x942C100A, // 000F GETIDX R11 R8 R10
|
||||
0x1C301705, // 0010 EQ R12 R11 K5
|
||||
0x78320001, // 0011 JMPF R12 #0014
|
||||
0x7002000F, // 0012 JMP #0023
|
||||
0x7002000C, // 0013 JMP #0021
|
||||
0x28301407, // 0014 GE R12 R10 R7
|
||||
0x78320002, // 0015 JMPF R12 #0019
|
||||
0x50300000, // 0016 LDBOOL R12 0 0
|
||||
0x80041800, // 0017 RET 1 R12
|
||||
0x70020007, // 0018 JMP #0021
|
||||
0x1C301706, // 0019 EQ R12 R11 K6
|
||||
0x78320000, // 001A JMPF R12 #001C
|
||||
0x70020004, // 001B JMP #0021
|
||||
0x94300C0A, // 001C GETIDX R12 R6 R10
|
||||
0x2030160C, // 001D NE R12 R11 R12
|
||||
0x78320001, // 001E JMPF R12 #0021
|
||||
0x50300000, // 001F LDBOOL R12 0 0
|
||||
0x80041800, // 0020 RET 1 R12
|
||||
0x00281507, // 0021 ADD R10 R10 K7
|
||||
0x7001FFE9, // 0022 JMP #000D
|
||||
0x282C1409, // 0023 GE R11 R10 R9
|
||||
0x782E0003, // 0024 JMPF R11 #0029
|
||||
0x202C1207, // 0025 NE R11 R9 R7
|
||||
0x782E0001, // 0026 JMPF R11 #0029
|
||||
0x502C0000, // 0027 LDBOOL R11 0 0
|
||||
0x80041600, // 0028 RET 1 R11
|
||||
0x882C0108, // 0029 GETMBR R11 R0 K8
|
||||
0x5C301600, // 002A MOVE R12 R11
|
||||
0x5C340200, // 002B MOVE R13 R1
|
||||
0x5C380400, // 002C MOVE R14 R2
|
||||
0x5C3C0600, // 002D MOVE R15 R3
|
||||
0x5C400800, // 002E MOVE R16 R4
|
||||
0x7C300800, // 002F CALL R12 4
|
||||
0x4C340000, // 0030 LDNIL R13
|
||||
0x1C34180D, // 0031 EQ R13 R12 R13
|
||||
0x78360000, // 0032 JMPF R13 #0034
|
||||
0x50300200, // 0033 LDBOOL R12 1 0
|
||||
0x80041800, // 0034 RET 1 R12
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: init
|
||||
********************************************************************/
|
||||
be_local_closure(mqtt_listener_init, /* name */
|
||||
be_nested_proto(
|
||||
8, /* nstack */
|
||||
3, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[ 7]) { /* constants */
|
||||
/* K0 */ be_nested_str(string),
|
||||
/* K1 */ be_nested_str(topic),
|
||||
/* K2 */ be_nested_str(split),
|
||||
/* K3 */ be_nested_str(_X2F),
|
||||
/* K4 */ be_nested_str(closure),
|
||||
/* K5 */ be_nested_str(tasmota),
|
||||
/* K6 */ be_nested_str(add_driver),
|
||||
}),
|
||||
&be_const_str_init,
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[12]) { /* code */
|
||||
0xA40E0000, // 0000 IMPORT R3 K0
|
||||
0x8C100702, // 0001 GETMET R4 R3 K2
|
||||
0x5C180200, // 0002 MOVE R6 R1
|
||||
0x581C0003, // 0003 LDCONST R7 K3
|
||||
0x7C100600, // 0004 CALL R4 3
|
||||
0x90020204, // 0005 SETMBR R0 K1 R4
|
||||
0x90020802, // 0006 SETMBR R0 K4 R2
|
||||
0xB8120A00, // 0007 GETNGBL R4 K5
|
||||
0x8C100906, // 0008 GETMET R4 R4 K6
|
||||
0x5C180000, // 0009 MOVE R6 R0
|
||||
0x7C100400, // 000A CALL R4 2
|
||||
0x80000000, // 000B RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
/********************************************************************
|
||||
** Solidified class: mqtt_listener
|
||||
********************************************************************/
|
||||
be_local_class(mqtt_listener,
|
||||
2,
|
||||
NULL,
|
||||
be_nested_map(4,
|
||||
( (struct bmapnode*) &(const bmapnode[]) {
|
||||
{ be_const_key(topic, 1), be_const_var(0) },
|
||||
{ be_const_key(mqtt_data, -1), be_const_closure(mqtt_listener_mqtt_data_closure) },
|
||||
{ be_const_key(closure, -1), be_const_var(1) },
|
||||
{ be_const_key(init, -1), be_const_closure(mqtt_listener_init_closure) },
|
||||
})),
|
||||
(bstring*) &be_const_str_mqtt_listener
|
||||
);
|
||||
|
||||
/********************************************************************
|
||||
** Solidified function: subscribe
|
||||
********************************************************************/
|
||||
be_local_closure(subscribe, /* name */
|
||||
be_nested_proto(
|
||||
7, /* nstack */
|
||||
2, /* argc */
|
||||
0, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[ 6]) { /* constants */
|
||||
/* K0 */ be_const_class(be_class_mqtt_listener),
|
||||
/* K1 */ be_nested_str(mqtt),
|
||||
/* K2 */ be_nested_str(_subscribe),
|
||||
/* K3 */ be_nested_str(function),
|
||||
/* K4 */ be_nested_str(tasmota),
|
||||
/* K5 */ be_nested_str(check_not_method),
|
||||
}),
|
||||
&be_const_str_subscribe,
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[20]) { /* code */
|
||||
0x58080000, // 0000 LDCONST R2 K0
|
||||
0xB4000000, // 0001 CLASS K0
|
||||
0xA40E0200, // 0002 IMPORT R3 K1
|
||||
0x8C100702, // 0003 GETMET R4 R3 K2
|
||||
0x5C180000, // 0004 MOVE R6 R0
|
||||
0x7C100400, // 0005 CALL R4 2
|
||||
0x60100004, // 0006 GETGBL R4 G4
|
||||
0x5C140200, // 0007 MOVE R5 R1
|
||||
0x7C100200, // 0008 CALL R4 1
|
||||
0x1C100903, // 0009 EQ R4 R4 K3
|
||||
0x78120007, // 000A JMPF R4 #0013
|
||||
0xB8120800, // 000B GETNGBL R4 K4
|
||||
0x8C100905, // 000C GETMET R4 R4 K5
|
||||
0x5C180200, // 000D MOVE R6 R1
|
||||
0x7C100400, // 000E CALL R4 2
|
||||
0x5C100400, // 000F MOVE R4 R2
|
||||
0x5C140000, // 0010 MOVE R5 R0
|
||||
0x5C180200, // 0011 MOVE R6 R1
|
||||
0x7C100400, // 0012 CALL R4 2
|
||||
0x80000000, // 0013 RET 0
|
||||
})
|
||||
)
|
||||
);
|
||||
/*******************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
extern int be_mqtt_publish(bvm *vm);
|
||||
|
||||
extern void be_mqtt_subscribe(const char* topic); BE_FUNC_CTYPE_DECLARE(be_mqtt_subscribe, "", "s")
|
||||
extern void be_mqtt_unsubscribe(const char* topic); BE_FUNC_CTYPE_DECLARE(be_mqtt_unsubscribe, "", "s")
|
||||
|
||||
/* @const_object_info_begin
|
||||
module mqtt (scope: global) {
|
||||
publish, func(be_mqtt_publish)
|
||||
subscribe, closure(subscribe_closure)
|
||||
_subscribe, ctype_func(be_mqtt_subscribe)
|
||||
unsubscribe, ctype_func(be_mqtt_unsubscribe)
|
||||
}
|
||||
@const_object_info_end */
|
||||
#include "be_fixed_mqtt.h"
|
|
@ -1,21 +0,0 @@
|
|||
/********************************************************************
|
||||
* Berry module `mqtt`
|
||||
*
|
||||
*******************************************************************/
|
||||
|
||||
#include "be_constobj.h"
|
||||
#include "be_mapping.h"
|
||||
|
||||
extern int be_mqtt_publish(bvm *vm);
|
||||
|
||||
extern void be_mqtt_subscribe(const char* topic); BE_FUNC_CTYPE_DECLARE(be_mqtt_subscribe, "", "s")
|
||||
extern void be_mqtt_unsubscribe(const char* topic); BE_FUNC_CTYPE_DECLARE(be_mqtt_unsubscribe, "", "s")
|
||||
|
||||
/* @const_object_info_begin
|
||||
module mqtt (scope: global) {
|
||||
publish, func(be_mqtt_publish)
|
||||
subscribe, ctype_func(be_mqtt_subscribe)
|
||||
unsubscribe, ctype_func(be_mqtt_unsubscribe)
|
||||
}
|
||||
@const_object_info_end */
|
||||
#include "be_fixed_mqtt.h"
|
File diff suppressed because it is too large
Load Diff
|
@ -741,7 +741,7 @@ be_local_closure(Tasmota_add_fast_loop, /* name */
|
|||
********************************************************************/
|
||||
be_local_closure(Tasmota_event, /* name */
|
||||
be_nested_proto(
|
||||
20, /* nstack */
|
||||
21, /* nstack */
|
||||
6, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
|
@ -749,37 +749,38 @@ be_local_closure(Tasmota_event, /* name */
|
|||
0, /* has sup protos */
|
||||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[26]) { /* constants */
|
||||
( &(const bvalue[27]) { /* constants */
|
||||
/* K0 */ be_nested_str(introspect),
|
||||
/* K1 */ be_nested_str(string),
|
||||
/* K2 */ be_nested_str(every_50ms),
|
||||
/* K3 */ be_nested_str(run_deferred),
|
||||
/* K4 */ be_nested_str(every_250ms),
|
||||
/* K5 */ be_nested_str(run_cron),
|
||||
/* K6 */ be_nested_str(cmd),
|
||||
/* K7 */ be_nested_str(exec_cmd),
|
||||
/* K8 */ be_nested_str(tele),
|
||||
/* K9 */ be_nested_str(exec_tele),
|
||||
/* K10 */ be_nested_str(rule),
|
||||
/* K11 */ be_nested_str(exec_rules),
|
||||
/* K12 */ be_nested_str(gc),
|
||||
/* K13 */ be_nested_str(_drivers),
|
||||
/* K14 */ be_const_int(0),
|
||||
/* K15 */ be_nested_str(get),
|
||||
/* K16 */ be_nested_str(function),
|
||||
/* K17 */ be_nested_str(format),
|
||||
/* K18 */ be_nested_str(BRY_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s),
|
||||
/* K19 */ be_nested_str(_debug_present),
|
||||
/* K20 */ be_nested_str(debug),
|
||||
/* K21 */ be_nested_str(traceback),
|
||||
/* K22 */ be_const_int(1),
|
||||
/* K23 */ be_nested_str(save_before_restart),
|
||||
/* K24 */ be_nested_str(persist),
|
||||
/* K25 */ be_nested_str(save),
|
||||
/* K6 */ be_nested_str(mqtt_data),
|
||||
/* K7 */ be_nested_str(cmd),
|
||||
/* K8 */ be_nested_str(exec_cmd),
|
||||
/* K9 */ be_nested_str(tele),
|
||||
/* K10 */ be_nested_str(exec_tele),
|
||||
/* K11 */ be_nested_str(rule),
|
||||
/* K12 */ be_nested_str(exec_rules),
|
||||
/* K13 */ be_nested_str(gc),
|
||||
/* K14 */ be_nested_str(_drivers),
|
||||
/* K15 */ be_const_int(0),
|
||||
/* K16 */ be_nested_str(get),
|
||||
/* K17 */ be_nested_str(function),
|
||||
/* K18 */ be_nested_str(format),
|
||||
/* K19 */ be_nested_str(BRY_X3A_X20Exception_X3E_X20_X27_X25s_X27_X20_X2D_X20_X25s),
|
||||
/* K20 */ be_nested_str(_debug_present),
|
||||
/* K21 */ be_nested_str(debug),
|
||||
/* K22 */ be_nested_str(traceback),
|
||||
/* K23 */ be_const_int(1),
|
||||
/* K24 */ be_nested_str(save_before_restart),
|
||||
/* K25 */ be_nested_str(persist),
|
||||
/* K26 */ be_nested_str(save),
|
||||
}),
|
||||
&be_const_str_event,
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[97]) { /* code */
|
||||
( &(const binstruction[109]) { /* code */
|
||||
0xA41A0000, // 0000 IMPORT R6 K0
|
||||
0xA41E0200, // 0001 IMPORT R7 K1
|
||||
0x1C200302, // 0002 EQ R8 R1 K2
|
||||
|
@ -791,92 +792,104 @@ be_local_closure(Tasmota_event, /* name */
|
|||
0x8C200105, // 0008 GETMET R8 R0 K5
|
||||
0x7C200200, // 0009 CALL R8 1
|
||||
0x50200000, // 000A LDBOOL R8 0 0
|
||||
0x1C240306, // 000B EQ R9 R1 K6
|
||||
0x78260006, // 000C JMPF R9 #0014
|
||||
0x8C240107, // 000D GETMET R9 R0 K7
|
||||
0x5C2C0400, // 000E MOVE R11 R2
|
||||
0x5C300600, // 000F MOVE R12 R3
|
||||
0x5C340800, // 0010 MOVE R13 R4
|
||||
0x7C240800, // 0011 CALL R9 4
|
||||
0x80041200, // 0012 RET 1 R9
|
||||
0x70020046, // 0013 JMP #005B
|
||||
0x1C240308, // 0014 EQ R9 R1 K8
|
||||
0x78260004, // 0015 JMPF R9 #001B
|
||||
0x8C240109, // 0016 GETMET R9 R0 K9
|
||||
0x5C2C0800, // 0017 MOVE R11 R4
|
||||
0x7C240400, // 0018 CALL R9 2
|
||||
0x80041200, // 0019 RET 1 R9
|
||||
0x7002003F, // 001A JMP #005B
|
||||
0x1C24030A, // 001B EQ R9 R1 K10
|
||||
0x78260004, // 001C JMPF R9 #0022
|
||||
0x8C24010B, // 001D GETMET R9 R0 K11
|
||||
0x5C2C0800, // 001E MOVE R11 R4
|
||||
0x7C240400, // 001F CALL R9 2
|
||||
0x80041200, // 0020 RET 1 R9
|
||||
0x70020038, // 0021 JMP #005B
|
||||
0x1C24030C, // 0022 EQ R9 R1 K12
|
||||
0x78260003, // 0023 JMPF R9 #0028
|
||||
0x8C24010C, // 0024 GETMET R9 R0 K12
|
||||
0x7C240200, // 0025 CALL R9 1
|
||||
0x80041200, // 0026 RET 1 R9
|
||||
0x70020032, // 0027 JMP #005B
|
||||
0x8824010D, // 0028 GETMBR R9 R0 K13
|
||||
0x78260030, // 0029 JMPF R9 #005B
|
||||
0x5824000E, // 002A LDCONST R9 K14
|
||||
0x6028000C, // 002B GETGBL R10 G12
|
||||
0x882C010D, // 002C GETMBR R11 R0 K13
|
||||
0x7C280200, // 002D CALL R10 1
|
||||
0x1428120A, // 002E LT R10 R9 R10
|
||||
0x782A002A, // 002F JMPF R10 #005B
|
||||
0x8828010D, // 0030 GETMBR R10 R0 K13
|
||||
0x94281409, // 0031 GETIDX R10 R10 R9
|
||||
0x8C2C0D0F, // 0032 GETMET R11 R6 K15
|
||||
0x5C341400, // 0033 MOVE R13 R10
|
||||
0x5C380200, // 0034 MOVE R14 R1
|
||||
0x7C2C0600, // 0035 CALL R11 3
|
||||
0x60300004, // 0036 GETGBL R12 G4
|
||||
0x5C341600, // 0037 MOVE R13 R11
|
||||
0x7C300200, // 0038 CALL R12 1
|
||||
0x1C301910, // 0039 EQ R12 R12 K16
|
||||
0x7832001D, // 003A JMPF R12 #0059
|
||||
0xA802000C, // 003B EXBLK 0 #0049
|
||||
0x5C301600, // 003C MOVE R12 R11
|
||||
0x5C341400, // 003D MOVE R13 R10
|
||||
0x5C380400, // 003E MOVE R14 R2
|
||||
0x5C3C0600, // 003F MOVE R15 R3
|
||||
0x5C400800, // 0040 MOVE R16 R4
|
||||
0x5C440A00, // 0041 MOVE R17 R5
|
||||
0x7C300A00, // 0042 CALL R12 5
|
||||
0x5C201800, // 0043 MOVE R8 R12
|
||||
0x78220001, // 0044 JMPF R8 #0047
|
||||
0xA8040001, // 0045 EXBLK 1 1
|
||||
0x70020013, // 0046 JMP #005B
|
||||
0xA8040001, // 0047 EXBLK 1 1
|
||||
0x7002000F, // 0048 JMP #0059
|
||||
0xAC300002, // 0049 CATCH R12 0 2
|
||||
0x7002000C, // 004A JMP #0058
|
||||
0x60380001, // 004B GETGBL R14 G1
|
||||
0x8C3C0F11, // 004C GETMET R15 R7 K17
|
||||
0x58440012, // 004D LDCONST R17 K18
|
||||
0x5C481800, // 004E MOVE R18 R12
|
||||
0x5C4C1A00, // 004F MOVE R19 R13
|
||||
0x7C3C0800, // 0050 CALL R15 4
|
||||
0x7C380200, // 0051 CALL R14 1
|
||||
0x88380113, // 0052 GETMBR R14 R0 K19
|
||||
0x783A0002, // 0053 JMPF R14 #0057
|
||||
0xA43A2800, // 0054 IMPORT R14 K20
|
||||
0x8C3C1D15, // 0055 GETMET R15 R14 K21
|
||||
0x7C3C0200, // 0056 CALL R15 1
|
||||
0x70020000, // 0057 JMP #0059
|
||||
0xB0080000, // 0058 RAISE 2 R0 R0
|
||||
0x00241316, // 0059 ADD R9 R9 K22
|
||||
0x7001FFCF, // 005A JMP #002B
|
||||
0x1C240317, // 005B EQ R9 R1 K23
|
||||
0x78260002, // 005C JMPF R9 #0060
|
||||
0xA4263000, // 005D IMPORT R9 K24
|
||||
0x8C281319, // 005E GETMET R10 R9 K25
|
||||
0x7C280200, // 005F CALL R10 1
|
||||
0x80041000, // 0060 RET 1 R8
|
||||
0x50240000, // 000B LDBOOL R9 0 0
|
||||
0x1C280306, // 000C EQ R10 R1 K6
|
||||
0x782A0000, // 000D JMPF R10 #000F
|
||||
0x50240200, // 000E LDBOOL R9 1 0
|
||||
0x1C280307, // 000F EQ R10 R1 K7
|
||||
0x782A0006, // 0010 JMPF R10 #0018
|
||||
0x8C280108, // 0011 GETMET R10 R0 K8
|
||||
0x5C300400, // 0012 MOVE R12 R2
|
||||
0x5C340600, // 0013 MOVE R13 R3
|
||||
0x5C380800, // 0014 MOVE R14 R4
|
||||
0x7C280800, // 0015 CALL R10 4
|
||||
0x80041400, // 0016 RET 1 R10
|
||||
0x7002004E, // 0017 JMP #0067
|
||||
0x1C280309, // 0018 EQ R10 R1 K9
|
||||
0x782A0004, // 0019 JMPF R10 #001F
|
||||
0x8C28010A, // 001A GETMET R10 R0 K10
|
||||
0x5C300800, // 001B MOVE R12 R4
|
||||
0x7C280400, // 001C CALL R10 2
|
||||
0x80041400, // 001D RET 1 R10
|
||||
0x70020047, // 001E JMP #0067
|
||||
0x1C28030B, // 001F EQ R10 R1 K11
|
||||
0x782A0007, // 0020 JMPF R10 #0029
|
||||
0x8C28010C, // 0021 GETMET R10 R0 K12
|
||||
0x5C300800, // 0022 MOVE R12 R4
|
||||
0x60340017, // 0023 GETGBL R13 G23
|
||||
0x5C380600, // 0024 MOVE R14 R3
|
||||
0x7C340200, // 0025 CALL R13 1
|
||||
0x7C280600, // 0026 CALL R10 3
|
||||
0x80041400, // 0027 RET 1 R10
|
||||
0x7002003D, // 0028 JMP #0067
|
||||
0x1C28030D, // 0029 EQ R10 R1 K13
|
||||
0x782A0003, // 002A JMPF R10 #002F
|
||||
0x8C28010D, // 002B GETMET R10 R0 K13
|
||||
0x7C280200, // 002C CALL R10 1
|
||||
0x80041400, // 002D RET 1 R10
|
||||
0x70020037, // 002E JMP #0067
|
||||
0x8828010E, // 002F GETMBR R10 R0 K14
|
||||
0x782A0035, // 0030 JMPF R10 #0067
|
||||
0x5828000F, // 0031 LDCONST R10 K15
|
||||
0x602C000C, // 0032 GETGBL R11 G12
|
||||
0x8830010E, // 0033 GETMBR R12 R0 K14
|
||||
0x7C2C0200, // 0034 CALL R11 1
|
||||
0x142C140B, // 0035 LT R11 R10 R11
|
||||
0x782E002F, // 0036 JMPF R11 #0067
|
||||
0x882C010E, // 0037 GETMBR R11 R0 K14
|
||||
0x942C160A, // 0038 GETIDX R11 R11 R10
|
||||
0x8C300D10, // 0039 GETMET R12 R6 K16
|
||||
0x5C381600, // 003A MOVE R14 R11
|
||||
0x5C3C0200, // 003B MOVE R15 R1
|
||||
0x7C300600, // 003C CALL R12 3
|
||||
0x60340004, // 003D GETGBL R13 G4
|
||||
0x5C381800, // 003E MOVE R14 R12
|
||||
0x7C340200, // 003F CALL R13 1
|
||||
0x1C341B11, // 0040 EQ R13 R13 K17
|
||||
0x78360022, // 0041 JMPF R13 #0065
|
||||
0xA8020011, // 0042 EXBLK 0 #0055
|
||||
0x5C341800, // 0043 MOVE R13 R12
|
||||
0x5C381600, // 0044 MOVE R14 R11
|
||||
0x5C3C0400, // 0045 MOVE R15 R2
|
||||
0x5C400600, // 0046 MOVE R16 R3
|
||||
0x5C440800, // 0047 MOVE R17 R4
|
||||
0x5C480A00, // 0048 MOVE R18 R5
|
||||
0x7C340A00, // 0049 CALL R13 5
|
||||
0x74360001, // 004A JMPT R13 #004D
|
||||
0x74220000, // 004B JMPT R8 #004D
|
||||
0x50200001, // 004C LDBOOL R8 0 1
|
||||
0x50200200, // 004D LDBOOL R8 1 0
|
||||
0x78220003, // 004E JMPF R8 #0053
|
||||
0x5C341200, // 004F MOVE R13 R9
|
||||
0x74360001, // 0050 JMPT R13 #0053
|
||||
0xA8040001, // 0051 EXBLK 1 1
|
||||
0x70020013, // 0052 JMP #0067
|
||||
0xA8040001, // 0053 EXBLK 1 1
|
||||
0x7002000F, // 0054 JMP #0065
|
||||
0xAC340002, // 0055 CATCH R13 0 2
|
||||
0x7002000C, // 0056 JMP #0064
|
||||
0x603C0001, // 0057 GETGBL R15 G1
|
||||
0x8C400F12, // 0058 GETMET R16 R7 K18
|
||||
0x58480013, // 0059 LDCONST R18 K19
|
||||
0x5C4C1A00, // 005A MOVE R19 R13
|
||||
0x5C501C00, // 005B MOVE R20 R14
|
||||
0x7C400800, // 005C CALL R16 4
|
||||
0x7C3C0200, // 005D CALL R15 1
|
||||
0x883C0114, // 005E GETMBR R15 R0 K20
|
||||
0x783E0002, // 005F JMPF R15 #0063
|
||||
0xA43E2A00, // 0060 IMPORT R15 K21
|
||||
0x8C401F16, // 0061 GETMET R16 R15 K22
|
||||
0x7C400200, // 0062 CALL R16 1
|
||||
0x70020000, // 0063 JMP #0065
|
||||
0xB0080000, // 0064 RAISE 2 R0 R0
|
||||
0x00281517, // 0065 ADD R10 R10 K23
|
||||
0x7001FFCA, // 0066 JMP #0032
|
||||
0x1C280318, // 0067 EQ R10 R1 K24
|
||||
0x782A0002, // 0068 JMPF R10 #006C
|
||||
0xA42A3200, // 0069 IMPORT R10 K25
|
||||
0x8C2C151A, // 006A GETMET R11 R10 K26
|
||||
0x7C2C0200, // 006B CALL R11 1
|
||||
0x80041000, // 006C RET 1 R8
|
||||
})
|
||||
)
|
||||
);
|
||||
|
@ -1365,7 +1378,7 @@ be_local_closure(Tasmota_load, /* name */
|
|||
})
|
||||
),
|
||||
be_nested_proto(
|
||||
9, /* nstack */
|
||||
11, /* nstack */
|
||||
1, /* argc */
|
||||
0, /* varg */
|
||||
0, /* has upvals */
|
||||
|
@ -1377,11 +1390,11 @@ be_local_closure(Tasmota_load, /* name */
|
|||
/* K0 */ be_nested_str(file),
|
||||
/* K1 */ be_nested_str(string),
|
||||
/* K2 */ be_nested_str(format),
|
||||
/* K3 */ be_nested_str(BRY_X3A_X20failed_X20to_X20load_X20_X27_X25s_X27_X20_X28_X25s_X29),
|
||||
/* K3 */ be_nested_str(BRY_X3A_X20failed_X20to_X20load_X20_X27_X25s_X27_X20_X28_X25s_X20_X2D_X20_X25s_X29),
|
||||
}),
|
||||
&be_const_str_try_compile,
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[23]) { /* code */
|
||||
( &(const binstruction[24]) { /* code */
|
||||
0xA8020007, // 0000 EXBLK 0 #0009
|
||||
0x6004000D, // 0001 GETGBL R1 G13
|
||||
0x5C080000, // 0002 MOVE R2 R0
|
||||
|
@ -1390,21 +1403,22 @@ be_local_closure(Tasmota_load, /* name */
|
|||
0xA8040001, // 0005 EXBLK 1 1
|
||||
0x80040200, // 0006 RET 1 R1
|
||||
0xA8040001, // 0007 EXBLK 1 1
|
||||
0x7002000B, // 0008 JMP #0015
|
||||
0xAC040001, // 0009 CATCH R1 0 1
|
||||
0x70020008, // 000A JMP #0014
|
||||
0xA40A0200, // 000B IMPORT R2 K1
|
||||
0x600C0001, // 000C GETGBL R3 G1
|
||||
0x8C100502, // 000D GETMET R4 R2 K2
|
||||
0x58180003, // 000E LDCONST R6 K3
|
||||
0x5C1C0000, // 000F MOVE R7 R0
|
||||
0x5C200200, // 0010 MOVE R8 R1
|
||||
0x7C100800, // 0011 CALL R4 4
|
||||
0x7C0C0200, // 0012 CALL R3 1
|
||||
0x70020000, // 0013 JMP #0015
|
||||
0xB0080000, // 0014 RAISE 2 R0 R0
|
||||
0x4C040000, // 0015 LDNIL R1
|
||||
0x80040200, // 0016 RET 1 R1
|
||||
0x7002000C, // 0008 JMP #0016
|
||||
0xAC040002, // 0009 CATCH R1 0 2
|
||||
0x70020009, // 000A JMP #0015
|
||||
0xA40E0200, // 000B IMPORT R3 K1
|
||||
0x60100001, // 000C GETGBL R4 G1
|
||||
0x8C140702, // 000D GETMET R5 R3 K2
|
||||
0x581C0003, // 000E LDCONST R7 K3
|
||||
0x5C200000, // 000F MOVE R8 R0
|
||||
0x5C240200, // 0010 MOVE R9 R1
|
||||
0x5C280400, // 0011 MOVE R10 R2
|
||||
0x7C140A00, // 0012 CALL R5 5
|
||||
0x7C100200, // 0013 CALL R4 1
|
||||
0x70020000, // 0014 JMP #0016
|
||||
0xB0080000, // 0015 RAISE 2 R0 R0
|
||||
0x4C040000, // 0016 LDNIL R1
|
||||
0x80040200, // 0017 RET 1 R1
|
||||
})
|
||||
),
|
||||
be_nested_proto(
|
||||
|
@ -1724,7 +1738,7 @@ be_local_closure(Tasmota_chars_in_string, /* name */
|
|||
********************************************************************/
|
||||
be_local_closure(Tasmota_cmd, /* name */
|
||||
be_nested_proto(
|
||||
5, /* nstack */
|
||||
6, /* nstack */
|
||||
2, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
|
@ -1739,20 +1753,20 @@ be_local_closure(Tasmota_cmd, /* name */
|
|||
&be_const_str_cmd,
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[14]) { /* code */
|
||||
0x50080200, // 0000 LDBOOL R2 1 0
|
||||
0x90020002, // 0001 SETMBR R0 K0 R2
|
||||
0x8C080101, // 0002 GETMET R2 R0 K1
|
||||
0x5C100200, // 0003 MOVE R4 R1
|
||||
0x7C080400, // 0004 CALL R2 2
|
||||
0x4C080000, // 0005 LDNIL R2
|
||||
0x880C0100, // 0006 GETMBR R3 R0 K0
|
||||
0x50100200, // 0007 LDBOOL R4 1 0
|
||||
0x200C0604, // 0008 NE R3 R3 R4
|
||||
0x780E0000, // 0009 JMPF R3 #000B
|
||||
0x88080100, // 000A GETMBR R2 R0 K0
|
||||
0x4C0C0000, // 000B LDNIL R3
|
||||
0x90020003, // 000C SETMBR R0 K0 R3
|
||||
0x80040400, // 000D RET 1 R2
|
||||
0x88080100, // 0000 GETMBR R2 R0 K0
|
||||
0x500C0200, // 0001 LDBOOL R3 1 0
|
||||
0x90020003, // 0002 SETMBR R0 K0 R3
|
||||
0x8C0C0101, // 0003 GETMET R3 R0 K1
|
||||
0x5C140200, // 0004 MOVE R5 R1
|
||||
0x7C0C0400, // 0005 CALL R3 2
|
||||
0x4C0C0000, // 0006 LDNIL R3
|
||||
0x88100100, // 0007 GETMBR R4 R0 K0
|
||||
0x50140200, // 0008 LDBOOL R5 1 0
|
||||
0x20100805, // 0009 NE R4 R4 R5
|
||||
0x78120000, // 000A JMPF R4 #000C
|
||||
0x880C0100, // 000B GETMBR R3 R0 K0
|
||||
0x90020002, // 000C SETMBR R0 K0 R2
|
||||
0x80040600, // 000D RET 1 R3
|
||||
})
|
||||
)
|
||||
);
|
||||
|
@ -1866,8 +1880,8 @@ be_local_closure(Tasmota_add_rule, /* name */
|
|||
********************************************************************/
|
||||
be_local_closure(Tasmota_exec_rules, /* name */
|
||||
be_nested_proto(
|
||||
12, /* nstack */
|
||||
2, /* argc */
|
||||
14, /* nstack */
|
||||
3, /* argc */
|
||||
2, /* varg */
|
||||
0, /* has upvals */
|
||||
NULL, /* no upvals */
|
||||
|
@ -1875,8 +1889,8 @@ be_local_closure(Tasmota_exec_rules, /* name */
|
|||
NULL, /* no sub protos */
|
||||
1, /* has constants */
|
||||
( &(const bvalue[12]) { /* constants */
|
||||
/* K0 */ be_nested_str(_rules),
|
||||
/* K1 */ be_nested_str(cmd_res),
|
||||
/* K0 */ be_nested_str(cmd_res),
|
||||
/* K1 */ be_nested_str(_rules),
|
||||
/* K2 */ be_nested_str(json),
|
||||
/* K3 */ be_nested_str(load),
|
||||
/* K4 */ be_nested_str(log),
|
||||
|
@ -1890,55 +1904,57 @@ be_local_closure(Tasmota_exec_rules, /* name */
|
|||
}),
|
||||
&be_const_str_exec_rules,
|
||||
&be_const_str_solidified,
|
||||
( &(const binstruction[48]) { /* code */
|
||||
0x88080100, // 0000 GETMBR R2 R0 K0
|
||||
0x740A0003, // 0001 JMPT R2 #0006
|
||||
0x88080101, // 0002 GETMBR R2 R0 K1
|
||||
0x4C0C0000, // 0003 LDNIL R3
|
||||
0x20080403, // 0004 NE R2 R2 R3
|
||||
0x780A0027, // 0005 JMPF R2 #002E
|
||||
0xA40A0400, // 0006 IMPORT R2 K2
|
||||
0x8C0C0503, // 0007 GETMET R3 R2 K3
|
||||
0x5C140200, // 0008 MOVE R5 R1
|
||||
0x7C0C0400, // 0009 CALL R3 2
|
||||
0x50100000, // 000A LDBOOL R4 0 0
|
||||
0x4C140000, // 000B LDNIL R5
|
||||
0x1C140605, // 000C EQ R5 R3 R5
|
||||
0x78160004, // 000D JMPF R5 #0013
|
||||
0x8C140104, // 000E GETMET R5 R0 K4
|
||||
0x001E0A01, // 000F ADD R7 K5 R1
|
||||
0x58200006, // 0010 LDCONST R8 K6
|
||||
0x7C140600, // 0011 CALL R5 3
|
||||
0x5C0C0200, // 0012 MOVE R3 R1
|
||||
0x88140101, // 0013 GETMBR R5 R0 K1
|
||||
0x4C180000, // 0014 LDNIL R6
|
||||
0x20140A06, // 0015 NE R5 R5 R6
|
||||
0x78160000, // 0016 JMPF R5 #0018
|
||||
0x90020203, // 0017 SETMBR R0 K1 R3
|
||||
0x88140100, // 0018 GETMBR R5 R0 K0
|
||||
0x78160012, // 0019 JMPF R5 #002D
|
||||
0x58140007, // 001A LDCONST R5 K7
|
||||
0x6018000C, // 001B GETGBL R6 G12
|
||||
0x881C0100, // 001C GETMBR R7 R0 K0
|
||||
0x7C180200, // 001D CALL R6 1
|
||||
0x14180A06, // 001E LT R6 R5 R6
|
||||
0x781A000C, // 001F JMPF R6 #002D
|
||||
0x88180100, // 0020 GETMBR R6 R0 K0
|
||||
0x94180C05, // 0021 GETIDX R6 R6 R5
|
||||
0x8C1C0108, // 0022 GETMET R7 R0 K8
|
||||
0x5C240600, // 0023 MOVE R9 R3
|
||||
0x88280D09, // 0024 GETMBR R10 R6 K9
|
||||
0x882C0D0A, // 0025 GETMBR R11 R6 K10
|
||||
0x7C1C0800, // 0026 CALL R7 4
|
||||
0x741E0001, // 0027 JMPT R7 #002A
|
||||
0x74120000, // 0028 JMPT R4 #002A
|
||||
0x50100001, // 0029 LDBOOL R4 0 1
|
||||
0x50100200, // 002A LDBOOL R4 1 0
|
||||
0x00140B0B, // 002B ADD R5 R5 K11
|
||||
0x7001FFED, // 002C JMP #001B
|
||||
0x80040800, // 002D RET 1 R4
|
||||
0x50080000, // 002E LDBOOL R2 0 0
|
||||
0x80040400, // 002F RET 1 R2
|
||||
( &(const binstruction[50]) { /* code */
|
||||
0x880C0100, // 0000 GETMBR R3 R0 K0
|
||||
0x88100101, // 0001 GETMBR R4 R0 K1
|
||||
0x74120002, // 0002 JMPT R4 #0006
|
||||
0x4C100000, // 0003 LDNIL R4
|
||||
0x20100604, // 0004 NE R4 R3 R4
|
||||
0x78120029, // 0005 JMPF R4 #0030
|
||||
0xA4120400, // 0006 IMPORT R4 K2
|
||||
0x4C140000, // 0007 LDNIL R5
|
||||
0x90020005, // 0008 SETMBR R0 K0 R5
|
||||
0x50140000, // 0009 LDBOOL R5 0 0
|
||||
0x8C180903, // 000A GETMET R6 R4 K3
|
||||
0x5C200200, // 000B MOVE R8 R1
|
||||
0x7C180400, // 000C CALL R6 2
|
||||
0x4C1C0000, // 000D LDNIL R7
|
||||
0x1C1C0C07, // 000E EQ R7 R6 R7
|
||||
0x781E0004, // 000F JMPF R7 #0015
|
||||
0x8C1C0104, // 0010 GETMET R7 R0 K4
|
||||
0x00260A01, // 0011 ADD R9 K5 R1
|
||||
0x58280006, // 0012 LDCONST R10 K6
|
||||
0x7C1C0600, // 0013 CALL R7 3
|
||||
0x5C180200, // 0014 MOVE R6 R1
|
||||
0x780A0014, // 0015 JMPF R2 #002B
|
||||
0x881C0101, // 0016 GETMBR R7 R0 K1
|
||||
0x781E0012, // 0017 JMPF R7 #002B
|
||||
0x581C0007, // 0018 LDCONST R7 K7
|
||||
0x6020000C, // 0019 GETGBL R8 G12
|
||||
0x88240101, // 001A GETMBR R9 R0 K1
|
||||
0x7C200200, // 001B CALL R8 1
|
||||
0x14200E08, // 001C LT R8 R7 R8
|
||||
0x7822000C, // 001D JMPF R8 #002B
|
||||
0x88200101, // 001E GETMBR R8 R0 K1
|
||||
0x94201007, // 001F GETIDX R8 R8 R7
|
||||
0x8C240108, // 0020 GETMET R9 R0 K8
|
||||
0x5C2C0C00, // 0021 MOVE R11 R6
|
||||
0x88301109, // 0022 GETMBR R12 R8 K9
|
||||
0x8834110A, // 0023 GETMBR R13 R8 K10
|
||||
0x7C240800, // 0024 CALL R9 4
|
||||
0x74260001, // 0025 JMPT R9 #0028
|
||||
0x74160000, // 0026 JMPT R5 #0028
|
||||
0x50140001, // 0027 LDBOOL R5 0 1
|
||||
0x50140200, // 0028 LDBOOL R5 1 0
|
||||
0x001C0F0B, // 0029 ADD R7 R7 K11
|
||||
0x7001FFED, // 002A JMP #0019
|
||||
0x4C1C0000, // 002B LDNIL R7
|
||||
0x201C0607, // 002C NE R7 R3 R7
|
||||
0x781E0000, // 002D JMPF R7 #002F
|
||||
0x90020006, // 002E SETMBR R0 K0 R6
|
||||
0x80040A00, // 002F RET 1 R5
|
||||
0x50100000, // 0030 LDBOOL R4 0 0
|
||||
0x80040800, // 0031 RET 1 R4
|
||||
})
|
||||
)
|
||||
);
|
||||
|
|
|
@ -199,21 +199,22 @@ class Tasmota
|
|||
|
||||
# Run rules, i.e. check each individual rule
|
||||
# Returns true if at least one rule matched, false if none
|
||||
def exec_rules(ev_json)
|
||||
if self._rules || self.cmd_res != nil # if there is a rule handler, or we record rule results
|
||||
# `exec_rule` is true, then run the rule, else just record value
|
||||
def exec_rules(ev_json, exec_rule)
|
||||
var save_cmd_res = self.cmd_res # save initial state (for reentrance)
|
||||
if self._rules || save_cmd_res != nil # if there is a rule handler, or we record rule results
|
||||
import json
|
||||
var ev = json.load(ev_json) # returns nil if invalid JSON
|
||||
|
||||
self.cmd_res = nil # disable sunsequent recording of results
|
||||
var ret = false
|
||||
|
||||
var ev = json.load(ev_json) # returns nil if invalid JSON
|
||||
if ev == nil
|
||||
self.log('BRY: ERROR, bad json: '+ev_json, 3)
|
||||
ev = ev_json # revert to string
|
||||
end
|
||||
# record the rule payload for tasmota.cmd()
|
||||
if self.cmd_res != nil
|
||||
self.cmd_res = ev
|
||||
end
|
||||
# try all rule handlers
|
||||
if self._rules
|
||||
if exec_rule && self._rules
|
||||
var i = 0
|
||||
while i < size(self._rules)
|
||||
var tr = self._rules[i]
|
||||
|
@ -221,6 +222,12 @@ class Tasmota
|
|||
i += 1
|
||||
end
|
||||
end
|
||||
|
||||
# record the rule payload for tasmota.cmd()
|
||||
if save_cmd_res != nil
|
||||
self.cmd_res = ev
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
return false
|
||||
|
@ -373,9 +380,9 @@ class Tasmota
|
|||
if self._ccmd
|
||||
import json
|
||||
var payload_json = json.load(payload)
|
||||
var cmd_found = self.find_key_i(self._ccmd, cmd)
|
||||
var cmd_found = self.find_key_i(self._ccmd, cmd) # name of the command as registered (case insensitive search)
|
||||
if cmd_found != nil
|
||||
self.resolvecmnd(cmd_found) # set the command name in XdrvMailbox.command
|
||||
self.resolvecmnd(cmd_found) # set the command name in XdrvMailbox.command as it was registered first
|
||||
self._ccmd[cmd_found](cmd_found, idx, payload, payload_json)
|
||||
return true
|
||||
end
|
||||
|
@ -464,9 +471,9 @@ class Tasmota
|
|||
try
|
||||
var compiled = compile(f_name, 'file')
|
||||
return compiled
|
||||
except .. as e
|
||||
except .. as e, m
|
||||
import string
|
||||
print(string.format('BRY: failed to load \'%s\' (%s)',f_name,e))
|
||||
print(string.format('BRY: failed to load \'%s\' (%s - %s)',f_name,e,m))
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
@ -633,20 +640,25 @@ class Tasmota
|
|||
end
|
||||
|
||||
var done = false
|
||||
var keep_going = false # if true, we continue dispatch event if done == true (for mqtt_data)
|
||||
|
||||
if event_type == 'mqtt_data'
|
||||
keep_going = true
|
||||
end
|
||||
|
||||
if event_type=='cmd' return self.exec_cmd(cmd, idx, payload)
|
||||
elif event_type=='tele' return self.exec_tele(payload)
|
||||
elif event_type=='rule' return self.exec_rules(payload)
|
||||
elif event_type=='rule' return self.exec_rules(payload, bool(idx))
|
||||
elif event_type=='gc' return self.gc()
|
||||
elif self._drivers
|
||||
var i = 0
|
||||
while i < size(self._drivers)
|
||||
#for d:self._drivers
|
||||
var d = self._drivers[i]
|
||||
var f = introspect.get(d, event_type) # try to match a function or method with the same name
|
||||
if type(f) == 'function'
|
||||
try
|
||||
done = f(d, cmd, idx, payload, raw)
|
||||
if done break end
|
||||
done = f(d, cmd, idx, payload, raw) || done
|
||||
if done && !keep_going break end
|
||||
except .. as e,m
|
||||
print(string.format("BRY: Exception> '%s' - %s", e, m))
|
||||
if self._debug_present
|
||||
|
@ -690,6 +702,7 @@ class Tasmota
|
|||
|
||||
# cmd high-level function
|
||||
def cmd(command)
|
||||
var save_cmd_res = self.cmd_res # restore value on exit (for reentrant)
|
||||
self.cmd_res = true # signal buffer capture
|
||||
|
||||
self._cmd(command)
|
||||
|
@ -698,7 +711,7 @@ class Tasmota
|
|||
if self.cmd_res != true # unchanged
|
||||
ret = self.cmd_res
|
||||
end
|
||||
self.cmd_res = nil # clear buffer
|
||||
self.cmd_res = save_cmd_res # restore previous state
|
||||
|
||||
return ret
|
||||
end
|
||||
|
|
|
@ -0,0 +1,519 @@
|
|||
#######################################################################
|
||||
# Partition manager for ESP32 - ESP32C3 - ESP32S2
|
||||
#
|
||||
# use : `import partition_core`
|
||||
#
|
||||
# To solidify:
|
||||
#-
|
||||
import solidify load("partition_core.be") solidify.dump(partition_core)
|
||||
-#
|
||||
# Provides low-level objects and a Web UI
|
||||
#######################################################################
|
||||
|
||||
var partition_core = module('partition_core')
|
||||
|
||||
#######################################################################
|
||||
# Class for a partition table entry
|
||||
#
|
||||
# typedef struct {
|
||||
# uint16_t magic;
|
||||
# uint8_t type;
|
||||
# uint8_t subtype;
|
||||
# uint32_t offset;
|
||||
# uint32_t size;
|
||||
# uint8_t label[16];
|
||||
# uint32_t flags;
|
||||
# } esp_partition_info_t_simplified;
|
||||
#
|
||||
#######################################################################
|
||||
class Partition_info
|
||||
var type
|
||||
var subtype
|
||||
var start
|
||||
var size
|
||||
var label
|
||||
var flags
|
||||
|
||||
#- remove trailing NULL chars from a bytes buffer before converting to string -#
|
||||
#- Berry strings can contain NULL, but this messes up C-Berry interface -#
|
||||
static def remove_trailing_zeroes(b)
|
||||
var sz = size(b)
|
||||
var i = 0
|
||||
while i < sz
|
||||
if b[-1-i] != 0 break end
|
||||
i += 1
|
||||
end
|
||||
if i > 0
|
||||
b.resize(size(b)-i)
|
||||
end
|
||||
return b
|
||||
end
|
||||
|
||||
# Init the Parition information structure, either from a bytes() buffer or an empty if no buffer is provided
|
||||
def init(raw)
|
||||
self.type = 0
|
||||
self.subtype = 0
|
||||
self.start = 0
|
||||
self.size = 0
|
||||
self.label = ''
|
||||
self.flags = 0
|
||||
|
||||
if !issubclass(bytes, raw) # no payload, empty partition information
|
||||
return
|
||||
end
|
||||
|
||||
#- we have a payload, parse it -#
|
||||
var magic = raw.get(0,2)
|
||||
if magic == 0x50AA #- partition entry -#
|
||||
|
||||
self.type = raw.get(2,1)
|
||||
self.subtype = raw.get(3,1)
|
||||
self.start = raw.get(4,4)
|
||||
self.size = raw.get(8,4)
|
||||
self.label = self.remove_trailing_zeroes(raw[12..27]).asstring()
|
||||
self.flags = raw.get(28,4)
|
||||
|
||||
# elif magic == 0xEBEB #- MD5 -#
|
||||
else
|
||||
import string
|
||||
raise "internal_error", string.format("invalid magic number %02X", magic)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# check if the parition is an OTA partition
|
||||
# if yes, return OTA number (starting at 0)
|
||||
# if no, return nil
|
||||
def is_ota()
|
||||
var sub_type = self.subtype
|
||||
if self.type == 0 && (sub_type >= 0x10 && sub_type < 0x20)
|
||||
return sub_type - 0x10
|
||||
end
|
||||
end
|
||||
|
||||
# check if factory 'safeboot' partition
|
||||
def is_factory()
|
||||
return self.type == 0 && self.subtype == 0
|
||||
end
|
||||
|
||||
# check if the parition is a SPIFFS partition
|
||||
# returns bool
|
||||
def is_spiffs()
|
||||
return self.type == 1 && self.subtype == 130
|
||||
end
|
||||
|
||||
# get the actual image size give of the partition
|
||||
# returns -1 if the partition is not an app ota partition
|
||||
def get_image_size()
|
||||
import flash
|
||||
if self.is_ota() == nil && !self.is_factory() return -1 end
|
||||
try
|
||||
var addr = self.start
|
||||
var magic_byte = flash.read(addr, 1).get(0, 1)
|
||||
if magic_byte != 0xE9 return -1 end
|
||||
|
||||
var seg_count = flash.read(addr+1, 1).get(0, 1)
|
||||
# print("Segment count", seg_count)
|
||||
|
||||
var seg_offset = addr + 0x20 # sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) = 24 + 8
|
||||
|
||||
var seg_num = 0
|
||||
while seg_num < seg_count
|
||||
# print(string.format("Reading 0x%08X", seg_offset))
|
||||
var segment_header = flash.read(seg_offset - 8, 8)
|
||||
var seg_start_addr = segment_header.get(0, 4)
|
||||
var seg_size = segment_header.get(4,4)
|
||||
# print(string.format("Segment %i: flash_offset=0x%08X start_addr=0x%08X size=0x%08X", seg_num, seg_offset, seg_start_addr, seg_size))
|
||||
|
||||
seg_offset += seg_size + 8 # add segment_length + sizeof(esp_image_segment_header_t)
|
||||
|
||||
seg_num += 1
|
||||
end
|
||||
var total_size = seg_offset - addr + 1 # add 1KB for safety
|
||||
|
||||
# print(string.format("Total size = %i KB", total_size/1024))
|
||||
|
||||
return total_size
|
||||
except .. as e, m
|
||||
tasmota.log("BRY: Exception> '" + e + "' - " + m, 2)
|
||||
return -1
|
||||
end
|
||||
end
|
||||
|
||||
# Human readable version of Partition information
|
||||
# this method is not included in the solidified version to save space,
|
||||
# it is included only in the optional application `tapp` version
|
||||
def tostring()
|
||||
import string
|
||||
var type_s = ""
|
||||
var subtype_s = ""
|
||||
if self.type == 0 type_s = "app"
|
||||
if self.subtype == 0 subtype_s = "factory"
|
||||
elif self.subtype >= 0x10 && self.subtype < 0x20 subtype_s = "ota" + str(self.subtype - 0x10)
|
||||
elif self.subtype == 0x20 subtype_s = "test"
|
||||
end
|
||||
elif self.type == 1 type_s = "data"
|
||||
if self.subtype == 0x00 subtype_s = "otadata"
|
||||
elif self.subtype == 0x01 subtype_s = "phy"
|
||||
elif self.subtype == 0x02 subtype_s = "nvs"
|
||||
elif self.subtype == 0x03 subtype_s = "coredump"
|
||||
elif self.subtype == 0x04 subtype_s = "nvskeys"
|
||||
elif self.subtype == 0x05 subtype_s = "efuse_em"
|
||||
elif self.subtype == 0x80 subtype_s = "esphttpd"
|
||||
elif self.subtype == 0x81 subtype_s = "fat"
|
||||
elif self.subtype == 0x82 subtype_s = "spiffs"
|
||||
end
|
||||
end
|
||||
|
||||
# reformat strings
|
||||
if type_s != "" type_s = " (" + type_s + ")" end
|
||||
if subtype_s != "" subtype_s = " (" + subtype_s + ")" end
|
||||
return string.format("<instance: Partition_info(%d%s,%d%s,0x%08X,0x%08X,'%s',0x%X)>",
|
||||
self.type, type_s,
|
||||
self.subtype, subtype_s,
|
||||
self.start, self.size,
|
||||
self.label, self.flags)
|
||||
end
|
||||
|
||||
def tobytes()
|
||||
#- convert to raw bytes -#
|
||||
var b = bytes('AA50') #- set magic number -#
|
||||
b.resize(32).resize(2) #- pre-reserve 32 bytes -#
|
||||
b.add(self.type, 1)
|
||||
b.add(self.subtype, 1)
|
||||
b.add(self.start, 4)
|
||||
b.add(self.size, 4)
|
||||
var label = bytes().fromstring(self.label)
|
||||
label.resize(16)
|
||||
b = b + label
|
||||
b.add(self.flags, 4)
|
||||
return b
|
||||
end
|
||||
|
||||
end
|
||||
partition_core.Partition_info = Partition_info
|
||||
|
||||
#-------------------------------------------------------------
|
||||
- OTA Data
|
||||
-
|
||||
- Selection of the active OTA partition
|
||||
-
|
||||
typedef struct {
|
||||
uint32_t ota_seq;
|
||||
uint8_t seq_label[20];
|
||||
uint32_t ota_state;
|
||||
uint32_t crc; /* CRC32 of ota_seq field only */
|
||||
} esp_ota_select_entry_t;
|
||||
|
||||
- Excerp from esp_ota_ops.c
|
||||
esp32_idf use two sector for store information about which partition is running
|
||||
it defined the two sector as ota data partition,two structure esp_ota_select_entry_t is saved in the two sector
|
||||
named data in first sector as otadata[0], second sector data as otadata[1]
|
||||
e.g.
|
||||
if otadata[0].ota_seq == otadata[1].ota_seq == 0xFFFFFFFF,means ota info partition is in init status
|
||||
so it will boot factory application(if there is),if there's no factory application,it will boot ota[0] application
|
||||
if otadata[0].ota_seq != 0 and otadata[1].ota_seq != 0,it will choose a max seq ,and get value of max_seq%max_ota_app_number
|
||||
and boot a subtype (mask 0x0F) value is (max_seq - 1)%max_ota_app_number,so if want switch to run ota[x],can use next formulas.
|
||||
for example, if otadata[0].ota_seq = 4, otadata[1].ota_seq = 5, and there are 8 ota application,
|
||||
current running is (5-1)%8 = 4,running ota[4],so if we want to switch to run ota[7],
|
||||
we should add otadata[0].ota_seq (is 4) to 4 ,(8-1)%8=7,then it will boot ota[7]
|
||||
if A=(B - C)%D
|
||||
then B=(A + C)%D + D*n ,n= (0,1,2...)
|
||||
so current ota app sub type id is x , dest bin subtype is y,total ota app count is n
|
||||
seq will add (x + n*1 + 1 - seq)%n
|
||||
-------------------------------------------------------------#
|
||||
class Partition_otadata
|
||||
var maxota #- number of highest OTA partition, default 1 (double ota0/ota1) -#
|
||||
var offset #- offset of the otadata partition (0x2000 in length), default 0xE000 -#
|
||||
var active_otadata #- which otadata block is active, 0 or 1, i.e. 0xE000 or 0xF000 -#
|
||||
var seq0 #- ota_seq of first block -#
|
||||
var seq1 #- ota_seq of second block -#
|
||||
|
||||
#- crc32 for ota_seq as 32 bits unsigned, with init vector -1 -#
|
||||
static def crc32_ota_seq(seq)
|
||||
import crc
|
||||
return crc.crc32(0xFFFFFFFF, bytes().add(seq, 4))
|
||||
end
|
||||
|
||||
#---------------------------------------------------------------------#
|
||||
# Rest of the class
|
||||
#---------------------------------------------------------------------#
|
||||
def init(maxota, offset)
|
||||
self.maxota = maxota
|
||||
if self.maxota == nil self.maxota = 1 end
|
||||
self.offset = offset
|
||||
if self.offset == nil self.offset = 0xE000 end
|
||||
self.active_otadata = 0
|
||||
self.load()
|
||||
end
|
||||
|
||||
#- update ota_max, needs to recompute everything -#
|
||||
def set_ota_max(n)
|
||||
self.maxota = n
|
||||
end
|
||||
|
||||
# change the active OTA partition
|
||||
def set_active(n)
|
||||
var seq_max = 0 #- current highest seq number -#
|
||||
var block_act = 0 #- block number containing the highest seq number -#
|
||||
|
||||
if self.seq0 != nil
|
||||
seq_max = self.seq0
|
||||
block_act = 0
|
||||
end
|
||||
if self.seq1 != nil && self.seq1 > seq_max
|
||||
seq_max = self.seq1
|
||||
block_act = 1
|
||||
end
|
||||
|
||||
#- compute the next sequence number -#
|
||||
var actual_ota = (seq_max - 1) % (self.maxota + 1)
|
||||
if actual_ota != n #- change only if different -#
|
||||
if n > actual_ota seq_max += n - actual_ota
|
||||
else seq_max += (self.maxota + 1) - actual_ota + n
|
||||
end
|
||||
|
||||
#- update internal structure -#
|
||||
if block_act == 1 #- current block is 1, so update block 0 -#
|
||||
self.seq0 = seq_max
|
||||
else #- or write to block 1 -#
|
||||
self.seq1 = seq_max
|
||||
end
|
||||
self._validate()
|
||||
end
|
||||
end
|
||||
|
||||
#- load otadata from SPI Flash -#
|
||||
def load()
|
||||
import flash
|
||||
var otadata0 = flash.read(0xE000, 32)
|
||||
var otadata1 = flash.read(0xF000, 32)
|
||||
self.seq0 = otadata0.get(0, 4) #- ota_seq for block 1 -#
|
||||
self.seq1 = otadata1.get(0, 4) #- ota_seq for block 2 -#
|
||||
var valid0 = otadata0.get(28, 4) == self.crc32_ota_seq(self.seq0) #- is CRC32 valid? -#
|
||||
var valid1 = otadata1.get(28, 4) == self.crc32_ota_seq(self.seq1) #- is CRC32 valid? -#
|
||||
if !valid0 self.seq0 = nil end
|
||||
if !valid1 self.seq1 = nil end
|
||||
|
||||
self._validate()
|
||||
end
|
||||
|
||||
#- internally used, validate data -#
|
||||
def _validate()
|
||||
self.active_otadata = 0 #- if none is valid, default to OTA0 -#
|
||||
if self.seq0 != nil
|
||||
self.active_otadata = (self.seq0 - 1) % (self.maxota + 1)
|
||||
end
|
||||
if self.seq1 != nil && (self.seq0 == nil || self.seq1 > self.seq0)
|
||||
self.active_otadata = (self.seq1 - 1) % (self.maxota + 1)
|
||||
end
|
||||
end
|
||||
|
||||
# Save partition information to SPI Flash
|
||||
def save()
|
||||
import flash
|
||||
#- check the block number to save, 0 or 1. Choose the highest ota_seq -#
|
||||
var block_to_save = -1 #- invalid -#
|
||||
var seq_to_save = -1 #- invalid value -#
|
||||
|
||||
# check seq0
|
||||
if self.seq0 != nil
|
||||
seq_to_save = self.seq0
|
||||
block_to_save = 0
|
||||
end
|
||||
if (self.seq1 != nil) && (self.seq1 > seq_to_save)
|
||||
seq_to_save = self.seq1
|
||||
block_to_save = 1
|
||||
end
|
||||
# if none was good
|
||||
if block_to_save < 0 block_to_save = 0 end
|
||||
if seq_to_save < 0 seq_to_save = 1 end
|
||||
|
||||
var offset_to_save = self.offset + 0x1000 * block_to_save #- default 0xE000 or 0xF000 -#
|
||||
|
||||
var bytes_to_save = bytes()
|
||||
bytes_to_save.add(seq_to_save, 4)
|
||||
bytes_to_save += bytes("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
|
||||
bytes_to_save.add(self.crc32_ota_seq(seq_to_save), 4)
|
||||
|
||||
#- erase flash area and write -#
|
||||
flash.erase(offset_to_save, 0x1000)
|
||||
flash.write(offset_to_save, bytes_to_save)
|
||||
end
|
||||
|
||||
# Produce a human-readable representation of the object with relevant information
|
||||
def tostring()
|
||||
import string
|
||||
return string.format("<instance: Partition_otadata(ota_active:%d, ota_seq=[%d,%d], ota_max=%d)>",
|
||||
self.active_otadata, self.seq0, self.seq1, self.maxota)
|
||||
end
|
||||
end
|
||||
partition_core.Partition_otadata = Partition_otadata
|
||||
|
||||
#-------------------------------------------------------------
|
||||
- Class for a partition table entry
|
||||
-------------------------------------------------------------#
|
||||
class Partition
|
||||
var raw #- raw bytes of the partition table in flash -#
|
||||
var md5 #- md5 hash of partition list -#
|
||||
var slots
|
||||
var otadata #- instance of Partition_otadata() -#
|
||||
|
||||
def init()
|
||||
self.slots = []
|
||||
self.load()
|
||||
self.parse()
|
||||
self.load_otadata()
|
||||
end
|
||||
|
||||
# Load partition information from SPI Flash
|
||||
def load()
|
||||
import flash
|
||||
self.raw = flash.read(0x8000,0x1000)
|
||||
end
|
||||
|
||||
#- parse the raw bytes to a structured list of partition items -#
|
||||
def parse()
|
||||
for i:0..94 # there are maximum 95 slots + md5 (0xC00)
|
||||
var item_raw = self.raw[i*32..(i+1)*32-1]
|
||||
var magic = item_raw.get(0,2)
|
||||
if magic == 0x50AA #- partition entry -#
|
||||
var slot = partition_core.Partition_info(item_raw)
|
||||
self.slots.push(slot)
|
||||
elif magic == 0xEBEB #- MD5 -#
|
||||
self.md5 = self.raw[i*32+16..i*33-1]
|
||||
break
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def get_ota_slot(n)
|
||||
for slot: self.slots
|
||||
if slot.is_ota() == n return slot end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
#- compute the highest ota<x> partition -#
|
||||
def ota_max()
|
||||
var ota_max = 0
|
||||
for slot:self.slots
|
||||
if slot.type == 0 && (slot.subtype >= 0x10 && slot.subtype < 0x20)
|
||||
var ota_num = slot.subtype - 0x10
|
||||
if ota_num > ota_max ota_max = ota_num end
|
||||
end
|
||||
end
|
||||
return ota_max
|
||||
end
|
||||
|
||||
def load_otadata()
|
||||
#- look for otadata partition offset, and max_ota -#
|
||||
var otadata_offset = 0xE000 #- default value -#
|
||||
var ota_max = self.ota_max()
|
||||
for slot:self.slots
|
||||
if slot.type == 1 && slot.subtype == 0 #- otadata -#
|
||||
otadata_offset = slot.start
|
||||
end
|
||||
end
|
||||
|
||||
self.otadata = partition_core.Partition_otadata(ota_max, otadata_offset)
|
||||
end
|
||||
|
||||
# get the active OTA app partition number
|
||||
def get_active()
|
||||
return self.otadata.active_otadata
|
||||
end
|
||||
|
||||
#- change the active partition -#
|
||||
def set_active(n)
|
||||
if n < 0 || n > self.ota_max() raise "value_error", "Invalid ota partition number" end
|
||||
self.otadata.set_ota_max(self.ota_max()) #- update ota_max if it changed -#
|
||||
self.otadata.set_active(n)
|
||||
end
|
||||
|
||||
# Human readable version of Partition information
|
||||
# this method is not included in the solidified version to save space,
|
||||
# it is included only in the optional application `tapp` version
|
||||
#- convert to human readble -#
|
||||
def tostring()
|
||||
var ret = "<instance: Partition([\n"
|
||||
for slot: self.slots
|
||||
ret += " "
|
||||
ret += slot.tostring()
|
||||
ret += "\n"
|
||||
end
|
||||
ret += "],\n "
|
||||
ret += self.otadata.tostring()
|
||||
ret += "\n)>"
|
||||
return ret
|
||||
end
|
||||
|
||||
#- convert the slots to raw bytes, ready to falsh to parition page -#
|
||||
def tobytes()
|
||||
if size(self.slots) > 95 raise "value_error", "Too many partiition slots" end
|
||||
var b = bytes()
|
||||
for slot: self.slots
|
||||
b += slot.tobytes()
|
||||
end
|
||||
#- compute MD5 -#
|
||||
var md5 = MD5()
|
||||
md5.update(b)
|
||||
#- add the last segment -#
|
||||
b += bytes("EBEBFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
|
||||
b += md5.finish()
|
||||
#- complete -#
|
||||
return b
|
||||
end
|
||||
|
||||
#- write back to flash -#
|
||||
def save()
|
||||
import flash
|
||||
var b = self.tobytes()
|
||||
#- erase flash area and write -#
|
||||
flash.erase(0x8000, 0x1000)
|
||||
flash.write(0x8000, b)
|
||||
self.otadata.save()
|
||||
end
|
||||
|
||||
#- invalidate SPIFFS partition to force format at next boot -#
|
||||
#- we simply erase the first byte of the first 2 blocks in the SPIFFS partition -#
|
||||
def invalidate_spiffs()
|
||||
import flash
|
||||
#- we expect the SPIFFS partition to be the last one -#
|
||||
var spiffs = self.slots[-1]
|
||||
if !spiffs.is_spiffs() raise 'value_error', 'No SPIFFS partition found' end
|
||||
|
||||
var b = bytes("00") #- flash memory: we can turn bits from '1' to '0' -#
|
||||
flash.write(spiffs.start , b) #- block #0 -#
|
||||
flash.write(spiffs.start + 0x1000, b) #- block #1 -#
|
||||
end
|
||||
|
||||
# switch to safeboot `factory` partition
|
||||
def switch_factory()
|
||||
import flash
|
||||
flash.rollback()
|
||||
end
|
||||
end
|
||||
partition_core.Partition = Partition
|
||||
|
||||
# init method to force the global `partition_core` is defined even if the import is done within a function
|
||||
def init(m)
|
||||
import global
|
||||
global.partition_core = m
|
||||
return m
|
||||
end
|
||||
partition_core.init = init
|
||||
|
||||
return partition_core
|
||||
|
||||
#- Example
|
||||
|
||||
import partition_core
|
||||
|
||||
# read
|
||||
p = partition_core.Partition()
|
||||
print(p)
|
||||
|
||||
-#
|
|
@ -1,20 +0,0 @@
|
|||
import os
|
||||
import shutil
|
||||
from os.path import join
|
||||
from SCons.Script import DefaultEnvironment
|
||||
|
||||
env = DefaultEnvironment()
|
||||
platform = env.PioPlatform()
|
||||
|
||||
FRAMEWORK_DIR = platform.get_package_dir("framework-arduinoespressif32")
|
||||
|
||||
safemode_dir = join(env["PROJECT_DIR"], "safemode")
|
||||
variants_dir = join(FRAMEWORK_DIR, "variants", "tasmota")
|
||||
|
||||
if env["PIOPLATFORM"] == "espressif32":
|
||||
if os.path.exists(safemode_dir):
|
||||
# print("safemode.bin dir exists")
|
||||
if os.path.exists(variants_dir):
|
||||
# print("variants/tasmota exists")
|
||||
shutil.rmtree(variants_dir)
|
||||
shutil.copytree(safemode_dir, variants_dir)
|
|
@ -18,25 +18,78 @@
|
|||
|
||||
Import("env")
|
||||
|
||||
env = DefaultEnvironment()
|
||||
platform = env.PioPlatform()
|
||||
|
||||
from genericpath import exists
|
||||
import os
|
||||
import sys
|
||||
from os.path import join
|
||||
import csv
|
||||
import requests
|
||||
import shutil
|
||||
|
||||
sys.path.append(join(platform.get_package_dir("tool-esptoolpy")))
|
||||
import esptool
|
||||
|
||||
FRAMEWORK_DIR = platform.get_package_dir("framework-arduinoespressif32")
|
||||
variants_dir = join(FRAMEWORK_DIR, "variants", "tasmota")
|
||||
|
||||
def esp32_fetch_safemode_bin(chip):
|
||||
safemode_fw_url = "https://github.com/arendst/Tasmota-firmware/raw/main/firmware/tasmota32/tasmota" + chip[3:] + "-safemode.bin"
|
||||
safemode_fw_name = join(variants_dir,"tasmota" + chip[3:] + "-safemode.bin")
|
||||
if(exists(safemode_fw_name)):
|
||||
print("Safemode binary already in place.")
|
||||
return
|
||||
print("Will download safemode binary from URL:")
|
||||
print(safemode_fw_url)
|
||||
response = requests.get(safemode_fw_url)
|
||||
open(safemode_fw_name, "wb").write(response.content)
|
||||
print("Safemode binary written to variants dir.")
|
||||
|
||||
def esp32_copy_new_safemode_bin(chip,new_local_safemode_fw):
|
||||
print("Copy new local safemode firmware to variants dir -> using it for further flashing operations")
|
||||
safemode_fw_name = join(variants_dir,"tasmota" + chip[3:] + "-safemode.bin")
|
||||
if os.path.exists(variants_dir):
|
||||
shutil.copy(new_local_safemode_fw, safemode_fw_name)
|
||||
|
||||
def esp32_create_combined_bin(source, target, env):
|
||||
#print("Generating combined binary for serial flashing")
|
||||
|
||||
# The offset from begin of the file where the app0 partition starts
|
||||
# This is defined in the partition .csv file
|
||||
app_offset = 0x10000
|
||||
factory_offset = -1 # error code value
|
||||
app_offset = 0x10000 # default value for "old" scheme
|
||||
spiffs_offset = -1 # error code value
|
||||
with open(env.BoardConfig().get("build.partitions")) as csv_file:
|
||||
print("Read partitions from ",env.BoardConfig().get("build.partitions"))
|
||||
csv_reader = csv.reader(csv_file, delimiter=',')
|
||||
line_count = 0
|
||||
for row in csv_reader:
|
||||
if line_count == 0:
|
||||
print(f'{", ".join(row)}')
|
||||
line_count += 1
|
||||
else:
|
||||
print(f'{row[0]} {row[1]} {row[2]} {row[3]} {row[4]}')
|
||||
line_count += 1
|
||||
if(row[0] == 'app0'):
|
||||
app_offset = int(row[3],base=16)
|
||||
# elif(row[0] == 'factory'):
|
||||
# factory_offset = int(row[3],base=16)
|
||||
# elif(row[0] == 'spiffs'):
|
||||
# spiffs_offset = int(row[3],base=16)
|
||||
|
||||
|
||||
new_file_name = env.subst("$BUILD_DIR/${PROGNAME}.factory.bin")
|
||||
sections = env.subst(env.get("FLASH_EXTRA_IMAGES"))
|
||||
firmware_name = env.subst("$BUILD_DIR/${PROGNAME}.bin")
|
||||
chip = env.get("BOARD_MCU")
|
||||
if not os.path.exists(variants_dir):
|
||||
os.makedirs(variants_dir)
|
||||
if("safemode" in firmware_name):
|
||||
esp32_copy_new_safemode_bin(chip,firmware_name)
|
||||
else:
|
||||
esp32_fetch_safemode_bin(chip)
|
||||
flash_size = env.BoardConfig().get("upload.flash_size")
|
||||
cmd = [
|
||||
"--chip",
|
||||
|
@ -54,8 +107,12 @@ def esp32_create_combined_bin(source, target, env):
|
|||
print(f" - {sect_adr} | {sect_file}")
|
||||
cmd += [sect_adr, sect_file]
|
||||
|
||||
# "main" firmware to app0 - mandatory, except we just built a new safemode bin locally
|
||||
if("safemode" not in firmware_name):
|
||||
print(f" - {hex(app_offset)} | {firmware_name}")
|
||||
cmd += [hex(app_offset), firmware_name]
|
||||
else:
|
||||
print("Upload new safemode binary only")
|
||||
|
||||
#print('Using esptool.py arguments: %s' % ' '.join(cmd))
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@ build_flags = ${esp_defaults.build_flags}
|
|||
-Wl,--wrap=panicHandler -Wl,--wrap=xt_unhandled_exception
|
||||
-Wl,--wrap=_Z11analogWritehi ; `analogWrite(unsigned char, int)` use the Tasmota version of analogWrite for deeper integration and phase control
|
||||
extra_scripts = pre:pio-tools/add_c_flags.py
|
||||
pre:pio-tools/copy_safemode.py
|
||||
post:pio-tools/post_esp32.py
|
||||
${esp_defaults.extra_scripts}
|
||||
|
||||
|
|
|
@ -116,6 +116,54 @@ lib_ignore =
|
|||
Micro-RTSP
|
||||
epdiy
|
||||
|
||||
[env:tasmota32-safemode]
|
||||
extends = env:tasmota32_base
|
||||
board = esp32_4M_2APP
|
||||
build_flags = ${env:tasmota32_base.build_flags} -DFIRMWARE_SAFEMODE
|
||||
lib_extra_dirs = lib/lib_ssl, lib/libesp32
|
||||
lib_ignore =
|
||||
TTGO TWatch Library
|
||||
NimBLE-Arduino
|
||||
Micro-RTSP
|
||||
epdiy
|
||||
|
||||
[env:tasmota32s2-safemode]
|
||||
extends = env:tasmota32_base
|
||||
board = esp32s2_2APP
|
||||
build_flags = ${env:tasmota32_base.build_flags} -DFIRMWARE_SAFEMODE
|
||||
lib_extra_dirs = lib/lib_ssl, lib/libesp32
|
||||
lib_ignore =
|
||||
TTGO TWatch Library
|
||||
NimBLE-Arduino
|
||||
Micro-RTSP
|
||||
epdiy
|
||||
|
||||
[env:tasmota32s3-safemode]
|
||||
extends = env:tasmota32_base
|
||||
board = esp32s3_2APP
|
||||
build_flags = ${env:tasmota32_base.build_flags} -DFIRMWARE_SAFEMODE
|
||||
lib_extra_dirs = lib/lib_ssl, lib/libesp32
|
||||
lib_ignore =
|
||||
TTGO TWatch Library
|
||||
NimBLE-Arduino
|
||||
Micro-RTSP
|
||||
epdiy
|
||||
|
||||
[env:tasmota32c3-safemode]
|
||||
extends = env:tasmota32_base
|
||||
board = esp32c3_2APP
|
||||
build_unflags = ${env:tasmota32_base.build_unflags}
|
||||
-flto
|
||||
-mtarget-align
|
||||
build_flags = ${env:tasmota32_base.build_flags} -DFIRMWARE_SAFEMODE
|
||||
-fno-lto
|
||||
lib_extra_dirs = lib/lib_ssl, lib/libesp32
|
||||
lib_ignore =
|
||||
TTGO TWatch Library
|
||||
NimBLE-Arduino
|
||||
Micro-RTSP
|
||||
epdiy
|
||||
|
||||
[env:tasmota32-AF]
|
||||
extends = env:tasmota32_base
|
||||
build_flags = ${env:tasmota32_base.build_flags} -DMY_LANGUAGE=af_AF -DFIRMWARE_TASMOTA32
|
||||
|
|
Binary file not shown.
|
@ -73,6 +73,7 @@ const be_const_member_t lv_gpio_constants[] = {
|
|||
{ "ETH_PHY_POWER", (int32_t) GPIO_ETH_PHY_POWER },
|
||||
{ "EXS_ENABLE", (int32_t) GPIO_EXS_ENABLE },
|
||||
{ "FALLING", FALLING },
|
||||
{ "FLOWRATEMETER_SIGNAL", (int32_t) GPIO_FLOWRATEMETER_IN },
|
||||
{ "FTC532", (int32_t) GPIO_FTC532 },
|
||||
{ "GPS_RX", (int32_t) GPIO_GPS_RX },
|
||||
{ "GPS_TX", (int32_t) GPIO_GPS_TX },
|
||||
|
@ -147,6 +148,7 @@ const be_const_member_t lv_gpio_constants[] = {
|
|||
{ "MIEL_HVAC_RX", (int32_t) GPIO_MIEL_HVAC_RX },
|
||||
{ "MIEL_HVAC_TX", (int32_t) GPIO_MIEL_HVAC_TX },
|
||||
{ "MP3_DFR562", (int32_t) GPIO_MP3_DFR562 },
|
||||
{ "MS01", (int32_t) GPIO_MS01 },
|
||||
{ "NEOPOOL_RX", (int32_t) GPIO_NEOPOOL_RX },
|
||||
{ "NEOPOOL_TX", (int32_t) GPIO_NEOPOOL_TX },
|
||||
{ "NONE", (int32_t) GPIO_NONE },
|
||||
|
@ -200,6 +202,12 @@ const be_const_member_t lv_gpio_constants[] = {
|
|||
{ "SBR_RX", (int32_t) GPIO_SBR_RX },
|
||||
{ "SBR_TX", (int32_t) GPIO_SBR_TX },
|
||||
{ "SDCARD_CS", (int32_t) GPIO_SDCARD_CS },
|
||||
{ "SDIO_CLK", (int32_t) GPIO_SDIO_CLK },
|
||||
{ "SDIO_CMD", (int32_t) GPIO_SDIO_CMD },
|
||||
{ "SDIO_D0", (int32_t) GPIO_SDIO_D0 },
|
||||
{ "SDIO_D1", (int32_t) GPIO_SDIO_D1 },
|
||||
{ "SDIO_D2", (int32_t) GPIO_SDIO_D2 },
|
||||
{ "SDIO_D3", (int32_t) GPIO_SDIO_D3 },
|
||||
{ "SDM120_RX", (int32_t) GPIO_SDM120_RX },
|
||||
{ "SDM120_TX", (int32_t) GPIO_SDM120_TX },
|
||||
{ "SDM230_RX", (int32_t) GPIO_SDM230_RX },
|
||||
|
|
|
@ -22,154 +22,27 @@ var partition = module('partition')
|
|||
# } esp_partition_info_t_simplified;
|
||||
#
|
||||
#######################################################################
|
||||
class Partition_info
|
||||
var type
|
||||
var subtype
|
||||
var start
|
||||
var size
|
||||
var label
|
||||
var flags
|
||||
|
||||
#- remove trailing NULL chars from a buffer before converting to string -#
|
||||
#- Berry strings can contain NULL, but this messes up C-Berry interface -#
|
||||
static def remove_trailing_zeroes(b)
|
||||
while size(b) > 0
|
||||
if b[-1] == 0 b.resize(size(b)-1)
|
||||
else break end
|
||||
end
|
||||
return b
|
||||
end
|
||||
|
||||
#
|
||||
def init(raw)
|
||||
if raw == nil || !issubclass(bytes, raw) # no payload, empty partition information
|
||||
self.type = 0
|
||||
self.subtype = 0
|
||||
self.start = 0
|
||||
self.size = 0
|
||||
self.label = ''
|
||||
self.flags = 0
|
||||
return
|
||||
end
|
||||
|
||||
#- we have a payload, parse it -#
|
||||
var magic = raw.get(0,2)
|
||||
if magic == 0x50AA #- partition entry -#
|
||||
|
||||
self.type = raw.get(2,1)
|
||||
self.subtype = raw.get(3,1)
|
||||
self.start = raw.get(4,4)
|
||||
self.size = raw.get(8,4)
|
||||
self.label = self.remove_trailing_zeroes(raw[12..27]).asstring()
|
||||
self.flags = raw.get(28,4)
|
||||
|
||||
elif magic == 0xEBEB #- MD5 -#
|
||||
else
|
||||
import string
|
||||
raise "internal_error", string.format("invalid magic number %02X", magic)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# check if the parition is an OTA partition
|
||||
# if yes, return OTA number (starting at 0)
|
||||
# if no, return nil
|
||||
def is_ota()
|
||||
if self.type == 0 && (self.subtype >= 0x10 && self.subtype < 0x20)
|
||||
return self.subtype - 0x10
|
||||
end
|
||||
end
|
||||
|
||||
# check if the parition is a SPIFFS partition
|
||||
# returns bool
|
||||
def is_spiffs()
|
||||
return self.type == 1 && self.subtype == 130
|
||||
end
|
||||
|
||||
# get the actual image size give of the partition
|
||||
# returns -1 if the partition is not an app ota partition
|
||||
def get_image_size()
|
||||
import flash
|
||||
if self.is_ota() == nil return -1 end
|
||||
try
|
||||
var addr = self.start
|
||||
var magic_byte = flash.read(addr, 1).get(0, 1)
|
||||
if magic_byte != 0xE9 return -1 end
|
||||
|
||||
var seg_count = flash.read(addr+1, 1).get(0, 1)
|
||||
# print("Segment count", seg_count)
|
||||
|
||||
var seg_offset = addr + 0x20 # sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) = 24 + 8
|
||||
|
||||
for seg_num:0..seg_count-1
|
||||
# print(string.format("Reading 0x%08X", seg_offset))
|
||||
var segment_header = flash.read(seg_offset - 8, 8)
|
||||
var seg_start_addr = segment_header.get(0, 4)
|
||||
var seg_size = segment_header.get(4,4)
|
||||
# print(string.format("Segment %i: flash_offset=0x%08X start_addr=0x%08X size=0x%08X", seg_num, seg_offset, seg_start_addr, seg_size))
|
||||
|
||||
seg_offset += seg_size + 8 # add segment_length + sizeof(esp_image_segment_header_t)
|
||||
end
|
||||
var total_size = seg_offset - addr + 1 # add 1KB for safety
|
||||
|
||||
# print(string.format("Total size = %i KB", total_size/1024))
|
||||
|
||||
return total_size
|
||||
except .. as e, m
|
||||
print("BRY: Exception> '" + e + "' - " + m)
|
||||
return -1
|
||||
end
|
||||
end
|
||||
|
||||
def tostring()
|
||||
import string
|
||||
var type_s = ""
|
||||
var subtype_s = ""
|
||||
if self.type == 0 type_s = "app"
|
||||
if self.subtype == 0 subtype_s = "factory"
|
||||
elif self.subtype >= 0x10 && self.subtype < 0x20 subtype_s = "ota" + str(self.subtype - 0x10)
|
||||
elif self.subtype == 0x20 subtype_s = "test"
|
||||
end
|
||||
elif self.type == 1 type_s = "data"
|
||||
if self.subtype == 0x00 subtype_s = "otadata"
|
||||
elif self.subtype == 0x01 subtype_s = "phy"
|
||||
elif self.subtype == 0x02 subtype_s = "nvs"
|
||||
elif self.subtype == 0x03 subtype_s = "coredump"
|
||||
elif self.subtype == 0x04 subtype_s = "nvskeys"
|
||||
elif self.subtype == 0x05 subtype_s = "efuse_em"
|
||||
elif self.subtype == 0x80 subtype_s = "esphttpd"
|
||||
elif self.subtype == 0x81 subtype_s = "fat"
|
||||
elif self.subtype == 0x82 subtype_s = "spiffs"
|
||||
end
|
||||
end
|
||||
|
||||
#- reformat strings -#
|
||||
if type_s != "" type_s = " (" + type_s + ")" end
|
||||
if subtype_s != "" subtype_s = " (" + subtype_s + ")" end
|
||||
return string.format("<instance: Partition_info(%d%s,%d%s,0x%08X,0x%08X,'%s',0x%X)>",
|
||||
self.type, type_s,
|
||||
self.subtype, subtype_s,
|
||||
self.start, self.size,
|
||||
self.label, self.flags)
|
||||
end
|
||||
|
||||
def tobytes()
|
||||
#- convert to raw bytes -#
|
||||
var b = bytes('AA50') #- set magic number -#
|
||||
b.resize(32).resize(2) #- pre-reserve 32 bytes -#
|
||||
b.add(self.type, 1)
|
||||
b.add(self.subtype, 1)
|
||||
b.add(self.start, 4)
|
||||
b.add(self.size, 4)
|
||||
var label = bytes().fromstring(self.label)
|
||||
label.resize(16)
|
||||
b = b + label
|
||||
b.add(self.flags, 4)
|
||||
return b
|
||||
end
|
||||
|
||||
end
|
||||
partition.Partition_info = Partition_info
|
||||
# class Partition_info
|
||||
#
|
||||
# def init(raw)
|
||||
#
|
||||
# # check if the parition is an OTA partition
|
||||
# # if yes, return OTA number (starting at 0)
|
||||
# # if no, return nil
|
||||
# def is_ota()
|
||||
#
|
||||
# # # check if the parition is a SPIFFS partition
|
||||
# # returns bool
|
||||
# def is_spiffs()
|
||||
#
|
||||
# # get the actual image size give of the partition
|
||||
# # returns -1 if the partition is not an app ota partition
|
||||
# def get_image_size()
|
||||
#
|
||||
# def tostring()
|
||||
#
|
||||
# def tobytes()
|
||||
#end
|
||||
|
||||
#-------------------------------------------------------------
|
||||
- OTA Data
|
||||
|
@ -200,302 +73,77 @@ partition.Partition_info = Partition_info
|
|||
so current ota app sub type id is x , dest bin subtype is y,total ota app count is n
|
||||
seq will add (x + n*1 + 1 - seq)%n
|
||||
-------------------------------------------------------------#
|
||||
class Partition_otadata
|
||||
var maxota #- number of highest OTA partition, default 1 (double ota0/ota1) -#
|
||||
var offset #- offset of the otadata partition (0x2000 in length), default 0xE000 -#
|
||||
var active_otadata #- which otadata block is active, 0 or 1, i.e. 0xE000 or 0xF000 -#
|
||||
var seq0 #- ota_seq of first block -#
|
||||
var seq1 #- ota_seq of second block -#
|
||||
|
||||
#-------------------------------------------------------------
|
||||
- Simple CRC32 imple
|
||||
-
|
||||
- adapted from Python https://rosettacode.org/wiki/CRC-32#Python
|
||||
-------------------------------------------------------------#
|
||||
static def crc32_create_table()
|
||||
var a = []
|
||||
for i:0..255
|
||||
var k = i
|
||||
for j:0..7
|
||||
if k & 1
|
||||
k = (k >> 1) & 0x7FFFFFFF
|
||||
k ^= 0xedb88320
|
||||
else
|
||||
k = (k >> 1) & 0x7FFFFFFF
|
||||
end
|
||||
end
|
||||
a.push(k)
|
||||
end
|
||||
return a
|
||||
end
|
||||
static crc32_table = Partition_otadata.crc32_create_table()
|
||||
|
||||
static def crc32_update(buf, crc)
|
||||
crc ^= 0xffffffff
|
||||
for k:0..size(buf)-1
|
||||
crc = (crc >> 8 & 0x00FFFFFF) ^ Partition_otadata.crc32_table[(crc & 0xff) ^ buf[k]]
|
||||
end
|
||||
return crc ^ 0xffffffff
|
||||
end
|
||||
|
||||
#- crc32 for ota_seq as 32 bits unsigned, with init vector -1 -#
|
||||
static def crc32_ota_seq(seq)
|
||||
return Partition_otadata.crc32_update(bytes().add(seq, 4), 0xFFFFFFFF)
|
||||
end
|
||||
|
||||
#---------------------------------------------------------------------#
|
||||
# Rest of the class
|
||||
#---------------------------------------------------------------------#
|
||||
def init(maxota, offset)
|
||||
self.maxota = maxota
|
||||
if self.maxota == nil self.maxota = 1 end
|
||||
self.offset = offset
|
||||
if self.offset == nil self.offset = 0xE000 end
|
||||
self.active_otadata = 0
|
||||
self.load()
|
||||
end
|
||||
|
||||
#- update ota_max, needs to recompute everything -#
|
||||
def set_ota_max(n)
|
||||
self.maxota = n
|
||||
end
|
||||
|
||||
# change the active OTA partition
|
||||
def set_active(n)
|
||||
var seq_max = 0 #- current highest seq number -#
|
||||
var block_act = 0 #- block number containing the highest seq number -#
|
||||
|
||||
if self.seq0 != nil
|
||||
seq_max = self.seq0
|
||||
block_act = 0
|
||||
end
|
||||
if self.seq1 != nil && self.seq1 > seq_max
|
||||
seq_max = self.seq1
|
||||
block_act = 1
|
||||
end
|
||||
|
||||
#- compute the next sequence number -#
|
||||
var actual_ota = (seq_max - 1) % (self.maxota + 1)
|
||||
if actual_ota != n #- change only if different -#
|
||||
if n > actual_ota seq_max += n - actual_ota
|
||||
else seq_max += (self.maxota + 1) - actual_ota + n
|
||||
end
|
||||
|
||||
#- update internal structure -#
|
||||
if block_act == 1 #- current block is 1, so update block 0 -#
|
||||
self.seq0 = seq_max
|
||||
else #- or write to block 1 -#
|
||||
self.seq1 = seq_max
|
||||
end
|
||||
self._validate()
|
||||
end
|
||||
end
|
||||
|
||||
#- load otadata from SPI Flash -#
|
||||
def load()
|
||||
import flash
|
||||
var otadata0 = flash.read(0xE000, 32)
|
||||
var otadata1 = flash.read(0xF000, 32)
|
||||
self.seq0 = otadata0.get(0, 4) #- ota_seq for block 1 -#
|
||||
self.seq1 = otadata1.get(0, 4) #- ota_seq for block 2 -#
|
||||
var valid0 = otadata0.get(28, 4) == self.crc32_ota_seq(self.seq0) #- is CRC32 valid? -#
|
||||
var valid1 = otadata1.get(28, 4) == self.crc32_ota_seq(self.seq1) #- is CRC32 valid? -#
|
||||
if !valid0 self.seq0 = nil end
|
||||
if !valid1 self.seq1 = nil end
|
||||
|
||||
self._validate()
|
||||
end
|
||||
|
||||
#- internally used, validate data -#
|
||||
def _validate()
|
||||
self.active_otadata = 0 #- if none is valid, default to OTA0 -#
|
||||
if self.seq0 != nil
|
||||
self.active_otadata = (self.seq0 - 1) % (self.maxota + 1)
|
||||
end
|
||||
if self.seq1 != nil && (self.seq0 == nil || self.seq1 > self.seq0)
|
||||
self.active_otadata = (self.seq1 - 1) % (self.maxota + 1)
|
||||
end
|
||||
end
|
||||
|
||||
# Save partition information to SPI Flash
|
||||
def save()
|
||||
import flash
|
||||
#- check the block number to save, 0 or 1. Choose the highest ota_seq -#
|
||||
var block_to_save = -1 #- invalid -#
|
||||
var seq_to_save = -1 #- invalid value -#
|
||||
|
||||
# check seq0
|
||||
if self.seq0 != nil
|
||||
seq_to_save = self.seq0
|
||||
block_to_save = 0
|
||||
end
|
||||
if (self.seq1 != nil) && (self.seq1 > seq_to_save)
|
||||
seq_to_save = self.seq1
|
||||
block_to_save = 1
|
||||
end
|
||||
# if none was good
|
||||
if block_to_save < 0 block_to_save = 0 end
|
||||
if seq_to_save < 0 seq_to_save = 1 end
|
||||
|
||||
var offset_to_save = self.offset + 0x1000 * block_to_save #- default 0xE000 or 0xF000 -#
|
||||
|
||||
var bytes_to_save = bytes()
|
||||
bytes_to_save.add(seq_to_save, 4)
|
||||
bytes_to_save += bytes("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
|
||||
bytes_to_save.add(self.crc32_ota_seq(seq_to_save), 4)
|
||||
|
||||
#- erase flash area and write -#
|
||||
flash.erase(offset_to_save, 0x1000)
|
||||
flash.write(offset_to_save, bytes_to_save)
|
||||
end
|
||||
|
||||
# Produce a human-readable representation of the object with relevant information
|
||||
def tostring()
|
||||
import string
|
||||
return string.format("<instance: Partition_otadata(ota_active:%d, ota_seq=[%d,%d], ota_max=%d)>",
|
||||
self.active_otadata, self.seq0, self.seq1, self.maxota)
|
||||
end
|
||||
end
|
||||
partition.Partition_otadata = Partition_otadata
|
||||
# class Partition_otadata
|
||||
# var maxota #- number of highest OTA partition, default 1 (double ota0/ota1) -#
|
||||
# var offset #- offset of the otadata partition (0x2000 in length), default 0xE000 -#
|
||||
# var active_otadata #- which otadata block is active, 0 or 1, i.e. 0xE000 or 0xF000 -#
|
||||
# var seq0 #- ota_seq of first block -#
|
||||
# var seq1 #- ota_seq of second block -#
|
||||
#
|
||||
# #- crc32 for ota_seq as 32 bits unsigned, with init vector -1 -#
|
||||
# static def crc32_ota_seq(seq)
|
||||
#
|
||||
# #---------------------------------------------------------------------#
|
||||
# # Rest of the class
|
||||
# #---------------------------------------------------------------------#
|
||||
# def init(maxota, offset)
|
||||
#
|
||||
# #- update ota_max, needs to recompute everything -#
|
||||
# def set_ota_max(n)
|
||||
#
|
||||
# # change the active OTA partition
|
||||
# def set_active(n)
|
||||
#
|
||||
# #- load otadata from SPI Flash -#
|
||||
# def load()
|
||||
#
|
||||
# # Save partition information to SPI Flash
|
||||
# def save()
|
||||
#
|
||||
# # Produce a human-readable representation of the object with relevant information
|
||||
# def tostring()
|
||||
#end
|
||||
|
||||
#-------------------------------------------------------------
|
||||
- Class for a partition table entry
|
||||
-------------------------------------------------------------#
|
||||
class Partition
|
||||
var raw #- raw bytes of the partition table in flash -#
|
||||
var md5 #- md5 hash of partition list -#
|
||||
var slots
|
||||
var otadata #- instance of Partition_otadata() -#
|
||||
|
||||
def init()
|
||||
self.slots = []
|
||||
self.load()
|
||||
self.parse()
|
||||
self.load_otadata()
|
||||
end
|
||||
|
||||
# Load partition information from SPI Flash
|
||||
def load()
|
||||
import flash
|
||||
self.raw = flash.read(0x8000,0x1000)
|
||||
end
|
||||
|
||||
#- parse the raw bytes to a structured list of partition items -#
|
||||
def parse()
|
||||
for i:0..94 # there are maximum 95 slots + md5 (0xC00)
|
||||
var item_raw = self.raw[i*32..(i+1)*32-1]
|
||||
var magic = item_raw.get(0,2)
|
||||
if magic == 0x50AA #- partition entry -#
|
||||
var slot = Partition_info(item_raw)
|
||||
self.slots.push(slot)
|
||||
elif magic == 0xEBEB #- MD5 -#
|
||||
self.md5 = self.raw[i*32+16..i*33-1]
|
||||
break
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def get_ota_slot(n)
|
||||
for slot: self.slots
|
||||
if slot.is_ota() == n return slot end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
#- compute the highest ota<x> partition -#
|
||||
def ota_max()
|
||||
var ota_max = 0
|
||||
for slot:self.slots
|
||||
if slot.type == 0 && (slot.subtype >= 0x10 && slot.subtype < 0x20)
|
||||
var ota_num = slot.subtype - 0x10
|
||||
if ota_num > ota_max ota_max = ota_num end
|
||||
end
|
||||
end
|
||||
return ota_max
|
||||
end
|
||||
|
||||
def load_otadata()
|
||||
#- look for otadata partition offset, and max_ota -#
|
||||
var otadata_offset = 0xE000 #- default value -#
|
||||
var ota_max = self.ota_max()
|
||||
for slot:self.slots
|
||||
if slot.type == 1 && slot.subtype == 0 #- otadata -#
|
||||
otadata_offset = slot.start
|
||||
end
|
||||
end
|
||||
|
||||
self.otadata = Partition_otadata(ota_max, otadata_offset)
|
||||
end
|
||||
|
||||
# get the active OTA app partition number
|
||||
def get_active()
|
||||
return self.otadata.active_otadata
|
||||
end
|
||||
|
||||
#- change the active partition -#
|
||||
def set_active(n)
|
||||
if n < 0 || n > self.ota_max() raise "value_error", "Invalid ota partition number" end
|
||||
self.otadata.set_ota_max(self.ota_max()) #- update ota_max if it changed -#
|
||||
self.otadata.set_active(n)
|
||||
end
|
||||
|
||||
#- convert to human readble -#
|
||||
def tostring()
|
||||
var ret = "<instance: Partition([\n"
|
||||
for slot: self.slots
|
||||
ret += " "
|
||||
ret += slot.tostring()
|
||||
ret += "\n"
|
||||
end
|
||||
ret += "],\n "
|
||||
ret += self.otadata.tostring()
|
||||
ret += "\n)>"
|
||||
return ret
|
||||
end
|
||||
|
||||
#- convert the slots to raw bytes, ready to falsh to parition page -#
|
||||
def tobytes()
|
||||
if size(self.slots) > 95 raise "value_error", "Too many partiition slots" end
|
||||
var b = bytes()
|
||||
for slot: self.slots
|
||||
b += slot.tobytes()
|
||||
end
|
||||
#- compute MD5 -#
|
||||
var md5 = MD5()
|
||||
md5.update(b)
|
||||
#- add the last segment -#
|
||||
b += bytes("EBEBFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
|
||||
b += md5.finish()
|
||||
#- complete -#
|
||||
return b
|
||||
end
|
||||
|
||||
#- write back to flash -#
|
||||
def save()
|
||||
import flash
|
||||
var b = self.tobytes()
|
||||
#- erase flash area and write -#
|
||||
flash.erase(0x8000, 0x1000)
|
||||
flash.write(0x8000, b)
|
||||
self.otadata.save()
|
||||
end
|
||||
|
||||
#- invalidate SPIFFS partition to force format at next boot -#
|
||||
#- we simply erase the first byte of the first 2 blocks in the SPIFFS partition -#
|
||||
def invalidate_spiffs()
|
||||
import flash
|
||||
#- we expect the SPIFFS partition to be the last one -#
|
||||
var spiffs = self.slots[-1]
|
||||
if !spiffs.is_spiffs() raise 'value_error', 'No SPIFFS partition found' end
|
||||
|
||||
var b = bytes("00") #- flash memory: we can turn bits from '1' to '0' -#
|
||||
flash.write(spiffs.start , b) #- block #0 -#
|
||||
flash.write(spiffs.start + 0x1000, b) #- block #1 -#
|
||||
end
|
||||
end
|
||||
partition.Partition = Partition
|
||||
#class Partition
|
||||
# var raw #- raw bytes of the partition table in flash -#
|
||||
# var md5 #- md5 hash of partition list -#
|
||||
# var slots
|
||||
# var otadata #- instance of Partition_otadata() -#
|
||||
#
|
||||
# def init()
|
||||
#
|
||||
# # Load partition information from SPI Flash
|
||||
# def load()
|
||||
#
|
||||
# def get_ota_slot(n)
|
||||
#
|
||||
# #- compute the highest ota<x> partition -#
|
||||
# def ota_max()
|
||||
#
|
||||
# def load_otadata()
|
||||
#
|
||||
# # get the active OTA app partition number
|
||||
# def get_active()
|
||||
#
|
||||
# #- change the active partition -#
|
||||
# def set_active(n)
|
||||
#
|
||||
# #- convert to human readble -#
|
||||
# def tostring()
|
||||
#
|
||||
# #- convert the slots to raw bytes, ready to falsh to parition page -#
|
||||
# def tobytes()
|
||||
#
|
||||
# #- write back to flash -#
|
||||
# def save()
|
||||
#
|
||||
# #- invalidate SPIFFS partition to force format at next boot -#
|
||||
# #- we simply erase the first byte of the first 2 blocks in the SPIFFS partition -#
|
||||
# def invalidate_spiffs()
|
||||
#end
|
||||
|
||||
#################################################################################
|
||||
# Partition_manager_UI
|
||||
|
@ -517,7 +165,7 @@ class Partition_manager_UI
|
|||
#- ---------------------------------------------------------------------- -#
|
||||
# Show a single OTA Partition
|
||||
#- ---------------------------------------------------------------------- -#
|
||||
def page_show_partition(slot, active, ota_num)
|
||||
def page_show_partition(slot, active, ota_num, maxota)
|
||||
import webserver
|
||||
import string
|
||||
#- define `bdis` style for gray disabled buttons -#
|
||||
|
@ -535,6 +183,7 @@ class Partition_manager_UI
|
|||
webserver.content_send("<p><b>Used</b>: unknown</p>")
|
||||
webserver.content_send("<p><b>Free</b>: unknown</p>")
|
||||
end
|
||||
if maxota != nil && maxota > 0
|
||||
if !active && used > 0
|
||||
webserver.content_send("<p><form id=setactive style='display: block;' action='/part_mgr' method='post' ")
|
||||
webserver.content_send("onsubmit='return confirm(\"This will change the active partition and cause a restart.\");'>")
|
||||
|
@ -551,6 +200,7 @@ class Partition_manager_UI
|
|||
end
|
||||
webserver.content_send("</form></p>")
|
||||
end
|
||||
end
|
||||
|
||||
webserver.content_send("<p></p></fieldset><p></p>")
|
||||
end
|
||||
|
@ -591,7 +241,9 @@ class Partition_manager_UI
|
|||
var ota_num = slot.is_ota()
|
||||
if ota_num != nil
|
||||
# we have an OTA partition
|
||||
self.page_show_partition(slot, ota_num == p.otadata.active_otadata, ota_num)
|
||||
self.page_show_partition(slot, ota_num == p.otadata.active_otadata, ota_num, p.otadata.maxota)
|
||||
elif slot.is_factory()
|
||||
self.page_show_partition(slot, false, nil, nil)
|
||||
elif slot.is_spiffs()
|
||||
var flash_size = tasmota.memory()['flash'] * 1024
|
||||
var used_size = (slot.start + slot.size)
|
||||
|
@ -647,8 +299,9 @@ class Partition_manager_UI
|
|||
def page_part_mgr()
|
||||
import webserver
|
||||
import string
|
||||
import partition_core
|
||||
if !webserver.check_privileged_access() return nil end
|
||||
var p = partition.Partition()
|
||||
var p = partition_core.Partition()
|
||||
|
||||
webserver.content_start("Partition Manager") #- title of the web page -#
|
||||
webserver.content_send_style() #- send standard Tasmota styles -#
|
||||
|
@ -659,9 +312,11 @@ class Partition_manager_UI
|
|||
self.page_show_partitions(p)
|
||||
webserver.content_send("<p></p></fieldset><p></p>")
|
||||
|
||||
if p.otadata.maxota > 0
|
||||
webserver.content_send("<fieldset><legend><b> Re-partition</b></legend><p></p>")
|
||||
self.page_show_repartition_asym(p)
|
||||
webserver.content_send("<p></p></fieldset><p></p>")
|
||||
end
|
||||
|
||||
webserver.content_button(webserver.BUTTON_MANAGEMENT) #- button back to management page -#
|
||||
webserver.content_stop() #- end of web page -#
|
||||
|
@ -673,10 +328,11 @@ class Partition_manager_UI
|
|||
def page_part_ctl()
|
||||
import webserver
|
||||
import string
|
||||
import partition_core
|
||||
if !webserver.check_privileged_access() return nil end
|
||||
|
||||
#- check that the partition is valid -#
|
||||
var p = partition.Partition()
|
||||
var p = partition_core.Partition()
|
||||
|
||||
try
|
||||
#---------------------------------------------------------------------#
|
||||
|
@ -847,6 +503,7 @@ partition.Partition_manager_UI = Partition_manager_UI
|
|||
|
||||
#- create and register driver in Tasmota -#
|
||||
if tasmota
|
||||
import partition_core
|
||||
var partition_manager_ui = partition.Partition_manager_UI()
|
||||
tasmota.add_driver(partition_manager_ui)
|
||||
## can be removed if put in 'autoexec.bat'
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// compressed by tools/unishox/compress-html-uncompressed.py
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
const size_t HTTP_HEAD_LAST_SCRIPT_SIZE = 355;
|
||||
const size_t HTTP_HEAD_LAST_SCRIPT_SIZE = 346;
|
||||
const char HTTP_HEAD_LAST_SCRIPT_COMPRESSED[] PROGMEM = "\x30\x2F\x83\xAD\xCE\x46\xB1\x0E\xE9\xDE\x3D\xA6\x77\xF5\x47\xC3\x8C\xEA\x2D\x3E"
|
||||
"\x09\x81\x8B\x1A\xFA\x8E\x86\xA1\x6F\xE6\x45\xE6\x13\x0E\xB3\xE5\x61\x04\x77\x4F"
|
||||
"\xBD\xE1\x82\xE8\xEA\x1C\x2E\xAB\x38\xEA\xA6\x6C\xAB\xFB\xB3\xAB\xCC\x26\x1D\x1F"
|
||||
|
@ -13,7 +13,6 @@ const char HTTP_HEAD_LAST_SCRIPT_COMPRESSED[] PROGMEM = "\x30\x2F\x83\xAD\xCE\x4
|
|||
"\x04\x1C\x87\x44\x3E\xCF\x7C\xF3\x04\x7C\xB0\xF0\x7B\xA8\xED\x9D\xB3\xC1\xEE\x3D"
|
||||
"\xC0\x89\xC1\x77\x8C\x1D\xDF\x03\x02\xE0\xBC\xE8\x28\xC0\x2F\x70\x2C\x74\xF5\x19"
|
||||
"\x04\xCE\x82\x6F\x86\x05\x66\x47\xCF\x1D\xA3\xEC\x70\x58\x19\xA1\xF6\x79\x9F\x7D"
|
||||
"\x9C\xCF\xB0\x43\xD7\x47\xC2\x3B\xA6\xB1\x0E\xF1\xE0\xF4\x3B\x3C\x1F\xF4\x65\x1F"
|
||||
"\x86";
|
||||
"\x9C\xCF\xB0\x43\xD7\x47\xC2\x3B\xA6\xB1\x0E\xF1\xE0";
|
||||
|
||||
#define HTTP_HEAD_LAST_SCRIPT Decompress(HTTP_HEAD_LAST_SCRIPT_COMPRESSED,HTTP_HEAD_LAST_SCRIPT_SIZE).c_str()
|
|
@ -0,0 +1,40 @@
|
|||
/////////////////////////////////////////////////////////////////////
|
||||
// compressed by tools/unishox/compress-html-uncompressed.py
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
const size_t HTTP_HEAD_LAST_SCRIPT32_SIZE = 989;
|
||||
const char HTTP_HEAD_LAST_SCRIPT32_COMPRESSED[] PROGMEM = "\x30\x2F\x83\xAD\xCE\x46\xB1\x0E\xE9\xDE\x3D\xA6\x77\xF5\x47\xC3\x8C\xEA\x2D\x3E"
|
||||
"\x09\x81\x8B\x1A\xFA\x8E\x86\xA1\x6F\xE6\x45\xE6\x13\x0E\xB3\xE5\x61\x04\x77\x4F"
|
||||
"\xBD\xE1\x82\xE8\xEA\x1C\x2E\xAB\x38\xEA\xA6\x6C\xAB\xFB\xB3\xAB\xCC\x26\x1D\x1F"
|
||||
"\x67\x78\xF0\x3E\x2B\x42\x67\x77\x4E\x81\x3E\x1E\xA1\x47\xE1\xF2\x8E\xF1\xED\xD3"
|
||||
"\x07\x77\x4F\x7A\x8F\x7C\xEF\x1E\xDD\x3D\xEA\x3D\xF3\xDE\x3E\xFA\xC6\xB3\xEC\xF7"
|
||||
"\xCF\x87\x77\x4F\x7A\x8F\x7C\xE8\x2A\x2B\xFC\x57\x55\xFD\x1C\x2E\x99\xDD\x3E\xF4"
|
||||
"\x43\xEC\xEF\x1F\xA3\xF4\x77\x4F\xE0\x27\x57\xEB\x1A\xCF\xB3\xBC\x77\x8E\xF1\xDA"
|
||||
"\x04\x1C\x87\x44\x3E\xCF\x7C\xF3\x04\x7C\xB0\xF0\x7B\xA8\xED\x9D\xB3\xC1\xEE\x3D"
|
||||
"\xC0\x89\xC1\x77\x8C\x1D\xDF\x03\x02\xE0\xBC\xE8\x28\xC0\x2F\x70\x2C\x74\xF5\x19"
|
||||
"\x04\xCE\x82\x6F\x86\x05\x66\x47\xCF\x1D\xA3\xEC\x70\x58\x19\xA1\xF6\x79\x9F\x7D"
|
||||
"\x9C\xCF\xB0\x43\xD7\x47\xC2\x3B\xA6\xB1\x0E\xF1\xE0\x11\x76\x41\x67\x76\x8E\xF1"
|
||||
"\xED\x63\x8E\xE9\xF6\x60\xE5\x9F\x67\x78\x81\x2B\x21\x04\x2C\x5D\x8E\x3B\xA7\xD9"
|
||||
"\x83\x94\x40\x9B\x68\x10\x73\xD3\xC5\x1D\x0C\x67\xC6\x9D\x3C\x2C\x70\xDD\xA3\xBA"
|
||||
"\x77\x8F\x2A\x01\x8B\xC2\x08\xB1\x81\x1D\xDA\x04\x1E\x10\xBC\x11\xF0\x10\x70\x43"
|
||||
"\xDE\x3E\xC5\x9C\xA3\xEC\xF7\xCE\x84\x63\x42\x7E\x3D\xE3\x8C\xF7\xCE\x85\xE0\xB4"
|
||||
"\x36\x77\x4E\x33\xAA\x1D\xE3\xC1\x19\xDF\xD7\xC4\x3E\x73\x1F\x44\x63\x42\x65\xF7"
|
||||
"\x62\x3F\x9D\xD3\xBC\x78\xF8\x87\x4C\xE0\xB2\xC4\x3E\x1D\xD3\xBC\x7C\x3F\x0F\x69"
|
||||
"\x9D\xFD\x0E\x1C\x7C\xE6\x3E\x88\x5E\xF5\x1C\xF9\x15\xFF\xF6\x64\x77\x7E\x21\xD3"
|
||||
"\xEF\xC2\xC2\xA3\xBC\x78\xD3\x07\x74\x70\xE0\x42\xE2\x14\xF8\x7C\x39\x0F\xD1\xFA"
|
||||
"\x21\xC3\x8F\x78\xE3\x3D\xF3\xE1\xF1\x91\xB0\x99\xC4\x77\x8F\x69\x18\x0E\x8E\xED"
|
||||
"\x1D\xE3\xC1\xEE\x61\x79\x9E\xD0\x4C\xE0\x60\xF0\x7B\x8F\x1F\x10\xE9\xF7\x62\x15"
|
||||
"\xF8\xAF\xFF\xB3\x22\x1C\x2C\xC1\x87\xF3\xBB\xE0\x8E\xF1\xE3\xEE\x85\xFF\x91\x8B"
|
||||
"\x0B\xCC\xF0\x7B\x81\x17\x8A\x2A\x01\x41\xCB\x8F\x69\x9D\xFD\x1B\x0F\x9C\xC7\xD1"
|
||||
"\x1B\x08\x69\x04\x42\xAA\x86\x17\xD9\xA8\x5B\xF5\x1D\xD3\xBC\x78\x36\x1D\x30\x63"
|
||||
"\xE3\xBA\x7D\x90\xF1\x32\xA3\xEC\xEA\x3E\xCE\xC1\x67\x30\xED\x10\xB3\x98\x7C\x23"
|
||||
"\x01\xD1\xFA\xB1\x9A\x7C\x3E\xCE\xAA\xF8\xB6\x77\x8F\x06\xC3\xA6\x77\xDD\x88\x65"
|
||||
"\xEA\xBA\x61\x8A\xBE\x1E\x60\x83\xC2\x76\x98\x3B\xA6\xC3\xA7\xDD\x88\x64\x5E\xAB"
|
||||
"\xA6\x7C\x3E\x1C\xC3\xF4\x7E\x88\xD8\x74\xF5\x5D\x0B\xF1\xF0\xF8\x72\x9B\x20\x42"
|
||||
"\xE3\x2A\x01\xF8\x6C\x3A\x7D\xF8\x66\x77\x99\x53\x36\x51\xE3\x4C\x1D\xDF\x1F\x0F"
|
||||
"\x87\xD9\x8B\x0B\xCC\xFB\x3B\xDE\x74\x55\xA3\x5E\x0B\xA3\xBA\x77\x4E\xF1\xF0\xFC"
|
||||
"\x04\x4E\x19\x4E\xA3\x9C\xDB\x3B\xC4\x08\x78\x4D\x7C\x5B\x3E\xCE\xF7\x85\x82\x27"
|
||||
"\x10\x08\x16\x75\xA3\x8C\xEF\x1E\xD2\x05\x4C\xD4\xE5\x36\xC8\x10\x78\xB0\x36\x1D"
|
||||
"\x3C\xF8\x43\xBA\x77\x8F\x07\xB8\xF4\x3B\x3C\x1F\xF4\x65\x1F\x86";
|
||||
|
||||
#define HTTP_HEAD_LAST_SCRIPT32 Decompress(HTTP_HEAD_LAST_SCRIPT32_COMPRESSED,HTTP_HEAD_LAST_SCRIPT32_SIZE).c_str()
|
|
@ -18,4 +18,4 @@ const char HTTP_HEAD_LAST_SCRIPT[] PROGMEM =
|
|||
"}"
|
||||
"}"
|
||||
"wl(jd);" // Add name='' to any id='' in input,button,textarea,select
|
||||
"</script>";
|
||||
;
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
const char HTTP_HEAD_LAST_SCRIPT32[] PROGMEM =
|
||||
"function jd(){" // Add label name='' based on provided id=''
|
||||
"var t=0,i=document.querySelectorAll('input,button,textarea,select');"
|
||||
"while(i.length>=t){"
|
||||
"if(i[t]){"
|
||||
"i[t]['name']=(i[t].hasAttribute('id')&&(!i[t].hasAttribute('name')))?i[t]['id']:i[t]['name'];"
|
||||
"}"
|
||||
"t++;"
|
||||
"}"
|
||||
"}"
|
||||
"function sf(s){"
|
||||
"var t=0,i=document.querySelectorAll('.hf');"
|
||||
"while(i.length>=t){"
|
||||
"if(i[t]){"
|
||||
"i[t].style.display=s?'block':'none';"
|
||||
"}"
|
||||
"t++;"
|
||||
"}"
|
||||
"}"
|
||||
"wl(jd);" // Add name='' to any id='' in input,button,textarea,select
|
||||
// experimental
|
||||
"function su(t){"
|
||||
// "console.log('su()');"
|
||||
"eb('f3').style.display='none';"
|
||||
"eb('f2').style.display='block';"
|
||||
"t.form.submit();"
|
||||
"}"
|
||||
"function upl(t){" // check file's first byte to decide next step
|
||||
"var sl=t.form['u2'].files[0].slice(0,1);" // load only first byte of file
|
||||
// "console.log(sl);"
|
||||
// "console.log(sl.length);"
|
||||
"var rd=new FileReader();"
|
||||
"rd.onload=()=>{"
|
||||
// "console.log(\"rd.onload\");"
|
||||
"var bb=new Uint8Array(rd.result);"
|
||||
// "console.log(bb[0]);"
|
||||
// "console.log(bb.length);"
|
||||
"if(bb.length==1&&bb[0]==0xE9){"
|
||||
"fct(t);" // upload via factory
|
||||
"}else{"
|
||||
"t.form.submit();" // normal upload
|
||||
"};"
|
||||
"};"
|
||||
"rd.readAsArrayBuffer(sl);"
|
||||
"return false;"
|
||||
"};"
|
||||
|
||||
"function fct(t){"
|
||||
"var x=new XMLHttpRequest();"
|
||||
"x.open('GET','/u4?u4=fct&api=',true);"
|
||||
"x.onreadystatechange=()=>{"
|
||||
// "console.log('x.readyState=%%i x.status=%%i',x.readyState,x.status);"
|
||||
"if(x.readyState==4&&x.status==200){"
|
||||
"var s=x.responseText;"
|
||||
// "console.log('responseText:'+s);"
|
||||
"if(s=='false')setTimeout(()=>{fct(t);},6000);"
|
||||
"if(s=='true')su(t);"
|
||||
"}else if(x.readyState==4&&x.status==0){"
|
||||
"setTimeout(()=>{fct(t);},2000);" // retry in 2 seconds
|
||||
"};"
|
||||
"};"
|
||||
"x.send();"
|
||||
// "console.log('after send');"
|
||||
"}"
|
||||
"</script>";
|
|
@ -372,6 +372,7 @@
|
|||
#define D_OTA_URL "OTA Url"
|
||||
#define D_START_UPGRADE "Begin opgradering"
|
||||
#define D_UPGRADE_BY_FILE_UPLOAD "Gradeer op volgens lêeroplaai"
|
||||
#define D_UPLOAD_FACTORY "Switching to safeboot partition"
|
||||
#define D_UPLOAD_STARTED "Oplaai begin"
|
||||
#define D_UPGRADE_STARTED "Opgradering is begin"
|
||||
#define D_UPLOAD_DONE "Oplaai gedoen"
|
||||
|
@ -866,6 +867,7 @@
|
|||
#define D_GPIO_SHIFT595_SER "74x595 SER"
|
||||
#define D_SENSOR_CM11_TX "CM110x TX"
|
||||
#define D_SENSOR_CM11_RX "CM110x RX"
|
||||
#define D_SENSOR_FLOWRATEMETER "Flowrate"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -913,6 +915,8 @@
|
|||
#define D_UNIT_WATT "W"
|
||||
#define D_UNIT_WATTHOUR "Wh"
|
||||
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
|
||||
#define D_UNIT_LITER_PER_MINUTE "l/min"
|
||||
#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
|
||||
|
||||
#define D_NEW_ADDRESS "Setting address to"
|
||||
#define D_OUT_OF_RANGE "Out of Range"
|
||||
|
@ -1054,6 +1058,9 @@
|
|||
#define D_FP_PASSVERIFY "Wagwoord geverifieer" // 0x21 Verify the fingerprint passed
|
||||
#define D_FP_UNKNOWNERROR "Fout" // Any other error
|
||||
|
||||
// xsns_96_flowratemeter.ino
|
||||
#define D_FLOWRATEMETER_NAME "Flowmeter"
|
||||
|
||||
// xsns_83_neopool.ino
|
||||
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
|
||||
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
|
||||
|
|
|
@ -372,6 +372,7 @@
|
|||
#define D_OTA_URL "Адрес на сървър за OTA"
|
||||
#define D_START_UPGRADE "Начало на обновяване"
|
||||
#define D_UPGRADE_BY_FILE_UPLOAD "Обновяване от файл"
|
||||
#define D_UPLOAD_FACTORY "Switching to safeboot partition"
|
||||
#define D_UPLOAD_STARTED "Качване"
|
||||
#define D_UPGRADE_STARTED "Обновяване"
|
||||
#define D_UPLOAD_DONE "Качването завърши"
|
||||
|
@ -866,6 +867,7 @@
|
|||
#define D_GPIO_SHIFT595_SER "74x595 SER"
|
||||
#define D_SENSOR_CM11_TX "CM110x TX"
|
||||
#define D_SENSOR_CM11_RX "CM110x RX"
|
||||
#define D_SENSOR_FLOWRATEMETER "Flowrate"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -913,6 +915,8 @@
|
|||
#define D_UNIT_WATT "W"
|
||||
#define D_UNIT_WATTHOUR "Wh"
|
||||
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
|
||||
#define D_UNIT_LITER_PER_MINUTE "l/min"
|
||||
#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
|
||||
|
||||
#define D_NEW_ADDRESS "Setting address to"
|
||||
#define D_OUT_OF_RANGE "Out of Range"
|
||||
|
@ -1054,6 +1058,9 @@
|
|||
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
|
||||
#define D_FP_UNKNOWNERROR "Грешка" // Any other error
|
||||
|
||||
// xsns_96_flowratemeter.ino
|
||||
#define D_FLOWRATEMETER_NAME "Flowrate"
|
||||
|
||||
// xsns_83_neopool.ino
|
||||
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
|
||||
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
|
||||
|
|
|
@ -372,6 +372,7 @@
|
|||
#define D_OTA_URL "URL OTA"
|
||||
#define D_START_UPGRADE "Start aktualizace"
|
||||
#define D_UPGRADE_BY_FILE_UPLOAD "Aktualizace nahráním souboru"
|
||||
#define D_UPLOAD_FACTORY "Switching to safeboot partition"
|
||||
#define D_UPLOAD_STARTED "Nahrávání zahájeno"
|
||||
#define D_UPGRADE_STARTED "Zahájení aktualizace"
|
||||
#define D_UPLOAD_DONE "Nahrávání ukončeno"
|
||||
|
@ -866,6 +867,7 @@
|
|||
#define D_GPIO_SHIFT595_SER "74x595 SER"
|
||||
#define D_SENSOR_CM11_TX "CM110x TX"
|
||||
#define D_SENSOR_CM11_RX "CM110x RX"
|
||||
#define D_SENSOR_FLOWRATEMETER "Flowrate"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -913,6 +915,8 @@
|
|||
#define D_UNIT_WATT "W"
|
||||
#define D_UNIT_WATTHOUR "Wh"
|
||||
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
|
||||
#define D_UNIT_LITER_PER_MINUTE "l/min"
|
||||
#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
|
||||
|
||||
#define D_NEW_ADDRESS "Setting address to"
|
||||
#define D_OUT_OF_RANGE "Out of Range"
|
||||
|
@ -1054,6 +1058,9 @@
|
|||
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
|
||||
#define D_FP_UNKNOWNERROR "Error" // Any other error
|
||||
|
||||
// xsns_96_flowratemeter.ino
|
||||
#define D_FLOWRATEMETER_NAME "Flowrate"
|
||||
|
||||
// xsns_83_neopool.ino
|
||||
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
|
||||
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
|
||||
|
|
|
@ -372,6 +372,7 @@
|
|||
#define D_OTA_URL "OTA-URL"
|
||||
#define D_START_UPGRADE "Update starten"
|
||||
#define D_UPGRADE_BY_FILE_UPLOAD "Update Datei hochladen"
|
||||
#define D_UPLOAD_FACTORY "Switching to safeboot partition"
|
||||
#define D_UPLOAD_STARTED "Upload gestartet"
|
||||
#define D_UPGRADE_STARTED "Update gestartet"
|
||||
#define D_UPLOAD_DONE "Upload abgeschlossen"
|
||||
|
@ -866,6 +867,7 @@
|
|||
#define D_GPIO_SHIFT595_SER "74x595 SER"
|
||||
#define D_SENSOR_CM11_TX "CM110x TX"
|
||||
#define D_SENSOR_CM11_RX "CM110x RX"
|
||||
#define D_SENSOR_FLOWRATEMETER "Flowrate"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -913,6 +915,8 @@
|
|||
#define D_UNIT_WATT "W"
|
||||
#define D_UNIT_WATTHOUR "Wh"
|
||||
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
|
||||
#define D_UNIT_LITER_PER_MINUTE "l/min"
|
||||
#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
|
||||
|
||||
#define D_NEW_ADDRESS "Neue Adresse"
|
||||
#define D_OUT_OF_RANGE "Außerhalb Bereich"
|
||||
|
@ -1054,6 +1058,9 @@
|
|||
#define D_FP_PASSVERIFY "Übereinstimmung" // 0x21 Verify the fingerprint passed
|
||||
#define D_FP_UNKNOWNERROR "Fehler" // Any other error
|
||||
|
||||
// xsns_96_flowratemeter.ino
|
||||
#define D_FLOWRATEMETER_NAME "Durchflussmesser"
|
||||
|
||||
// xsns_83_neopool.ino
|
||||
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
|
||||
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
|
||||
|
|
|
@ -372,6 +372,7 @@
|
|||
#define D_OTA_URL "OTA URL"
|
||||
#define D_START_UPGRADE "Εκκίνηση αναβάθμισης"
|
||||
#define D_UPGRADE_BY_FILE_UPLOAD "Αναβάθμιση με μεταφόρτωση αρχείου"
|
||||
#define D_UPLOAD_FACTORY "Switching to safeboot partition"
|
||||
#define D_UPLOAD_STARTED "Η μεταφόρτωση ξεκίνησε"
|
||||
#define D_UPGRADE_STARTED "Η αναβάθμιση ξεκίνησε"
|
||||
#define D_UPLOAD_DONE "Η μεταφόρτωση ολοκληρώθηκε"
|
||||
|
@ -866,6 +867,7 @@
|
|||
#define D_GPIO_SHIFT595_SER "74x595 SER"
|
||||
#define D_SENSOR_CM11_TX "CM110x TX"
|
||||
#define D_SENSOR_CM11_RX "CM110x RX"
|
||||
#define D_SENSOR_FLOWRATEMETER "Flowrate"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -913,6 +915,8 @@
|
|||
#define D_UNIT_WATT "W"
|
||||
#define D_UNIT_WATTHOUR "Wh"
|
||||
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
|
||||
#define D_UNIT_LITER_PER_MINUTE "l/min"
|
||||
#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
|
||||
|
||||
#define D_NEW_ADDRESS "Setting address to"
|
||||
#define D_OUT_OF_RANGE "Out of Range"
|
||||
|
@ -1054,6 +1058,9 @@
|
|||
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
|
||||
#define D_FP_UNKNOWNERROR "Error" // Any other error
|
||||
|
||||
// xsns_96_flowratemeter.ino
|
||||
#define D_FLOWRATEMETER_NAME "Flowrate"
|
||||
|
||||
// xsns_83_neopool.ino
|
||||
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
|
||||
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
|
||||
|
|
|
@ -372,6 +372,7 @@
|
|||
#define D_OTA_URL "OTA Url"
|
||||
#define D_START_UPGRADE "Start upgrade"
|
||||
#define D_UPGRADE_BY_FILE_UPLOAD "Upgrade by file upload"
|
||||
#define D_UPLOAD_FACTORY "Switching to safeboot partition"
|
||||
#define D_UPLOAD_STARTED "Upload started"
|
||||
#define D_UPGRADE_STARTED "Upgrade started"
|
||||
#define D_UPLOAD_DONE "Upload done"
|
||||
|
@ -866,6 +867,7 @@
|
|||
#define D_GPIO_SHIFT595_SER "74x595 SER"
|
||||
#define D_SENSOR_CM11_TX "CM110x TX"
|
||||
#define D_SENSOR_CM11_RX "CM110x RX"
|
||||
#define D_SENSOR_FLOWRATEMETER "Flowrate"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -913,6 +915,8 @@
|
|||
#define D_UNIT_WATT "W"
|
||||
#define D_UNIT_WATTHOUR "Wh"
|
||||
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
|
||||
#define D_UNIT_LITER_PER_MINUTE "l/min"
|
||||
#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
|
||||
|
||||
#define D_NEW_ADDRESS "Setting address to"
|
||||
#define D_OUT_OF_RANGE "Out of Range"
|
||||
|
@ -1054,6 +1058,9 @@
|
|||
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
|
||||
#define D_FP_UNKNOWNERROR "Error" // Any other error
|
||||
|
||||
// xsns_96_flowratemeter.ino
|
||||
#define D_FLOWRATEMETER_NAME "Flowrate"
|
||||
|
||||
// xsns_83_neopool.ino
|
||||
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
|
||||
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
|
||||
|
|
|
@ -372,6 +372,7 @@
|
|||
#define D_OTA_URL "OTA Url"
|
||||
#define D_START_UPGRADE "Comenzar actualización"
|
||||
#define D_UPGRADE_BY_FILE_UPLOAD "Actualizar cargando archivo bin"
|
||||
#define D_UPLOAD_FACTORY "Switching to safeboot partition"
|
||||
#define D_UPLOAD_STARTED "Cargando archivo"
|
||||
#define D_UPGRADE_STARTED "Actualización iniciada"
|
||||
#define D_UPLOAD_DONE "Carga finalizada"
|
||||
|
@ -866,6 +867,7 @@
|
|||
#define D_GPIO_SHIFT595_SER "74x595 SER"
|
||||
#define D_SENSOR_CM11_TX "CM110x TX"
|
||||
#define D_SENSOR_CM11_RX "CM110x RX"
|
||||
#define D_SENSOR_FLOWRATEMETER "Flowrate"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -913,6 +915,8 @@
|
|||
#define D_UNIT_WATT "W"
|
||||
#define D_UNIT_WATTHOUR "Wh"
|
||||
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
|
||||
#define D_UNIT_LITER_PER_MINUTE "l/min"
|
||||
#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
|
||||
|
||||
#define D_NEW_ADDRESS "Cambiando dirección a"
|
||||
#define D_OUT_OF_RANGE "Fuera de Rango"
|
||||
|
@ -1054,6 +1058,9 @@
|
|||
#define D_FP_PASSVERIFY "Clave Correcta" // 0x21 Verify the fingerprint passed
|
||||
#define D_FP_UNKNOWNERROR "Error" // Any other error
|
||||
|
||||
// xsns_96_flowratemeter.ino
|
||||
#define D_FLOWRATEMETER_NAME "Flowrate"
|
||||
|
||||
// xsns_83_neopool.ino
|
||||
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
|
||||
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
|
||||
|
|
|
@ -372,6 +372,7 @@
|
|||
#define D_OTA_URL "URL OTA"
|
||||
#define D_START_UPGRADE "Lancer la mise à jour"
|
||||
#define D_UPGRADE_BY_FILE_UPLOAD "Mise à jour par téléchargement fichier"
|
||||
#define D_UPLOAD_FACTORY "Switching to safeboot partition"
|
||||
#define D_UPLOAD_STARTED "Téléchargement lancé"
|
||||
#define D_UPGRADE_STARTED "Mise à jour lancée"
|
||||
#define D_UPLOAD_DONE "Téléchargement terminé"
|
||||
|
@ -866,6 +867,7 @@
|
|||
#define D_GPIO_SHIFT595_SER "74x595 SER"
|
||||
#define D_SENSOR_CM11_TX "CM110x TX"
|
||||
#define D_SENSOR_CM11_RX "CM110x RX"
|
||||
#define D_SENSOR_FLOWRATEMETER "Flowrate"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -913,6 +915,8 @@
|
|||
#define D_UNIT_WATT "W"
|
||||
#define D_UNIT_WATTHOUR "Wh"
|
||||
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
|
||||
#define D_UNIT_LITER_PER_MINUTE "l/min"
|
||||
#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
|
||||
|
||||
#define D_NEW_ADDRESS "Positionner l'adresse à"
|
||||
#define D_OUT_OF_RANGE "Hors limites"
|
||||
|
@ -1054,6 +1058,9 @@
|
|||
#define D_FP_PASSVERIFY "Mot-de-passe vérifié" // 0x21 Verify the fingerprint passed
|
||||
#define D_FP_UNKNOWNERROR "Erreur" // Any other error
|
||||
|
||||
// xsns_96_flowratemeter.ino
|
||||
#define D_FLOWRATEMETER_NAME "Flowrate"
|
||||
|
||||
// xsns_83_neopool.ino
|
||||
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
|
||||
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
|
||||
|
|
|
@ -372,6 +372,7 @@
|
|||
#define D_OTA_URL "OTA Url"
|
||||
#define D_START_UPGRADE "Begjin upgrade"
|
||||
#define D_UPGRADE_BY_FILE_UPLOAD "Upgrade op bestân upload"
|
||||
#define D_UPLOAD_FACTORY "Switching to safeboot partition"
|
||||
#define D_UPLOAD_STARTED "Upload begon"
|
||||
#define D_UPGRADE_STARTED "Upgrade begon"
|
||||
#define D_UPLOAD_DONE "Upload dien"
|
||||
|
@ -866,6 +867,7 @@
|
|||
#define D_GPIO_SHIFT595_SER "74x595 SER"
|
||||
#define D_SENSOR_CM11_TX "CM110x TX"
|
||||
#define D_SENSOR_CM11_RX "CM110x RX"
|
||||
#define D_SENSOR_FLOWRATEMETER "Flowrate"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -913,6 +915,8 @@
|
|||
#define D_UNIT_WATT "W"
|
||||
#define D_UNIT_WATTHOUR "Wh"
|
||||
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
|
||||
#define D_UNIT_LITER_PER_MINUTE "l/min"
|
||||
#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
|
||||
|
||||
#define D_NEW_ADDRESS "Setting address to"
|
||||
#define D_OUT_OF_RANGE "Out of Range"
|
||||
|
@ -1054,6 +1058,9 @@
|
|||
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
|
||||
#define D_FP_UNKNOWNERROR "Error" // Any other error
|
||||
|
||||
// xsns_96_flowratemeter.ino
|
||||
#define D_FLOWRATEMETER_NAME "Flowrate"
|
||||
|
||||
// xsns_83_neopool.ino
|
||||
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
|
||||
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
|
||||
|
|
|
@ -372,6 +372,7 @@
|
|||
#define D_OTA_URL "OTA כתובת"
|
||||
#define D_START_UPGRADE "התחל בשדרוג"
|
||||
#define D_UPGRADE_BY_FILE_UPLOAD "שדרוג דרך קובץ נכשל"
|
||||
#define D_UPLOAD_FACTORY "Switching to safeboot partition"
|
||||
#define D_UPLOAD_STARTED "העלאה מתחילה"
|
||||
#define D_UPGRADE_STARTED "שדרוג מתחיל"
|
||||
#define D_UPLOAD_DONE "העלאה הסתיימה"
|
||||
|
@ -866,6 +867,7 @@
|
|||
#define D_GPIO_SHIFT595_SER "74x595 SER"
|
||||
#define D_SENSOR_CM11_TX "CM110x TX"
|
||||
#define D_SENSOR_CM11_RX "CM110x RX"
|
||||
#define D_SENSOR_FLOWRATEMETER "Flowrate"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -913,6 +915,8 @@
|
|||
#define D_UNIT_WATT "W"
|
||||
#define D_UNIT_WATTHOUR "Wh"
|
||||
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
|
||||
#define D_UNIT_LITER_PER_MINUTE "l/min"
|
||||
#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
|
||||
|
||||
#define D_NEW_ADDRESS "Setting address to"
|
||||
#define D_OUT_OF_RANGE "Out of Range"
|
||||
|
@ -1054,6 +1058,9 @@
|
|||
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
|
||||
#define D_FP_UNKNOWNERROR "Error" // Any other error
|
||||
|
||||
// xsns_96_flowratemeter.ino
|
||||
#define D_FLOWRATEMETER_NAME "Flowrate"
|
||||
|
||||
// xsns_83_neopool.ino
|
||||
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
|
||||
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
|
||||
|
|
|
@ -372,6 +372,7 @@
|
|||
#define D_OTA_URL "OTA URL"
|
||||
#define D_START_UPGRADE "Frissítés"
|
||||
#define D_UPGRADE_BY_FILE_UPLOAD "Frissítés helyi fájllal"
|
||||
#define D_UPLOAD_FACTORY "Switching to safeboot partition"
|
||||
#define D_UPLOAD_STARTED "Feltöltés elindítva"
|
||||
#define D_UPGRADE_STARTED "Frissítés elindítva"
|
||||
#define D_UPLOAD_DONE "Feltöltés kész"
|
||||
|
@ -866,6 +867,7 @@
|
|||
#define D_GPIO_SHIFT595_SER "74x595 SER"
|
||||
#define D_SENSOR_CM11_TX "CM110x TX"
|
||||
#define D_SENSOR_CM11_RX "CM110x RX"
|
||||
#define D_SENSOR_FLOWRATEMETER "Flowrate"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -913,6 +915,8 @@
|
|||
#define D_UNIT_WATT "W"
|
||||
#define D_UNIT_WATTHOUR "Wh"
|
||||
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
|
||||
#define D_UNIT_LITER_PER_MINUTE "l/min"
|
||||
#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
|
||||
|
||||
#define D_NEW_ADDRESS "Setting address to"
|
||||
#define D_OUT_OF_RANGE "Out of Range"
|
||||
|
@ -1054,6 +1058,9 @@
|
|||
#define D_FP_PASSVERIFY "Jelszó ellenőrizve" // 0x21 Verify the fingerprint passed
|
||||
#define D_FP_UNKNOWNERROR "Hiba" // Any other error
|
||||
|
||||
// xsns_96_flowratemeter.ino
|
||||
#define D_FLOWRATEMETER_NAME "Flowrate"
|
||||
|
||||
// xsns_83_neopool.ino
|
||||
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
|
||||
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
|
||||
|
|
|
@ -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 v11.0.0.7 - Last update 19.04.2022
|
||||
* Updated until v9.4.0.1 - Last update 03.05.2022
|
||||
\*********************************************************************/
|
||||
|
||||
#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
|
||||
|
@ -372,6 +372,7 @@
|
|||
#define D_OTA_URL "URL OTA"
|
||||
#define D_START_UPGRADE "Esegui aggiornamento"
|
||||
#define D_UPGRADE_BY_FILE_UPLOAD "Aggiornamento tramite file locale"
|
||||
#define D_UPLOAD_FACTORY "Passaggio a partizione avvio sicuro"
|
||||
#define D_UPLOAD_STARTED "Caricamento..."
|
||||
#define D_UPGRADE_STARTED "Aggiornamento..."
|
||||
#define D_UPLOAD_DONE "Caricamento completato"
|
||||
|
@ -866,6 +867,7 @@
|
|||
#define D_GPIO_SHIFT595_SER "74x595 - SER"
|
||||
#define D_SENSOR_CM11_TX "CM110x - TX"
|
||||
#define D_SENSOR_CM11_RX "CM110x - RX"
|
||||
#define D_SENSOR_FLOWRATEMETER "Portata"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -913,6 +915,8 @@
|
|||
#define D_UNIT_WATT "W"
|
||||
#define D_UNIT_WATTHOUR "Wh"
|
||||
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
|
||||
#define D_UNIT_LITER_PER_MINUTE "l/min"
|
||||
#define D_UNIT_CUBICMETER_PER_HOUR "m³/ora"
|
||||
|
||||
#define D_NEW_ADDRESS "Imposta indirizzo a"
|
||||
#define D_OUT_OF_RANGE "Fuori intervallo"
|
||||
|
@ -1054,6 +1058,9 @@
|
|||
#define D_FP_PASSVERIFY "Password verificata" // 0x21 Verify the fingerprint passed
|
||||
#define D_FP_UNKNOWNERROR "Errore" // Any other error
|
||||
|
||||
// xsns_96_flowratemeter.ino
|
||||
#define D_FLOWRATEMETER_NAME "Portata"
|
||||
|
||||
// xsns_83_neopool.ino
|
||||
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
|
||||
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
|
||||
|
|
|
@ -372,6 +372,7 @@
|
|||
#define D_OTA_URL "OTA Url"
|
||||
#define D_START_UPGRADE "업그레이드 시작"
|
||||
#define D_UPGRADE_BY_FILE_UPLOAD "파일에서 업로드해 업그레이드"
|
||||
#define D_UPLOAD_FACTORY "Switching to safeboot partition"
|
||||
#define D_UPLOAD_STARTED "업로드 시작됨"
|
||||
#define D_UPGRADE_STARTED "업그레이드 시작됨"
|
||||
#define D_UPLOAD_DONE "업그레이드 완료"
|
||||
|
@ -866,6 +867,7 @@
|
|||
#define D_GPIO_SHIFT595_SER "74x595 SER"
|
||||
#define D_SENSOR_CM11_TX "CM110x TX"
|
||||
#define D_SENSOR_CM11_RX "CM110x RX"
|
||||
#define D_SENSOR_FLOWRATEMETER "Flowrate"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -913,6 +915,8 @@
|
|||
#define D_UNIT_WATT "W"
|
||||
#define D_UNIT_WATTHOUR "Wh"
|
||||
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
|
||||
#define D_UNIT_LITER_PER_MINUTE "l/min"
|
||||
#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
|
||||
|
||||
#define D_NEW_ADDRESS "Setting address to"
|
||||
#define D_OUT_OF_RANGE "Out of Range"
|
||||
|
@ -1054,6 +1058,9 @@
|
|||
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
|
||||
#define D_FP_UNKNOWNERROR "Error" // Any other error
|
||||
|
||||
// xsns_96_flowratemeter.ino
|
||||
#define D_FLOWRATEMETER_NAME "Flowrate"
|
||||
|
||||
// xsns_83_neopool.ino
|
||||
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
|
||||
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
|
||||
|
|
|
@ -372,6 +372,7 @@
|
|||
#define D_OTA_URL "OTA Url"
|
||||
#define D_START_UPGRADE "Start opwaarderen"
|
||||
#define D_UPGRADE_BY_FILE_UPLOAD "Opwaarderen dmv verzenden bestand"
|
||||
#define D_UPLOAD_FACTORY "Switching to safeboot partition"
|
||||
#define D_UPLOAD_STARTED "Verzending gestart"
|
||||
#define D_UPGRADE_STARTED "Opwaarderen gestart"
|
||||
#define D_UPLOAD_DONE "Opwaarderen klaar"
|
||||
|
@ -866,6 +867,7 @@
|
|||
#define D_GPIO_SHIFT595_SER "74x595 SER"
|
||||
#define D_SENSOR_CM11_TX "CM110x TX"
|
||||
#define D_SENSOR_CM11_RX "CM110x RX"
|
||||
#define D_SENSOR_FLOWRATEMETER "Flowrate"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -913,6 +915,8 @@
|
|||
#define D_UNIT_WATT "W"
|
||||
#define D_UNIT_WATTHOUR "Wh"
|
||||
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
|
||||
#define D_UNIT_LITER_PER_MINUTE "l/min"
|
||||
#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
|
||||
|
||||
#define D_NEW_ADDRESS "Nieuw adres"
|
||||
#define D_OUT_OF_RANGE "Buiten beriek"
|
||||
|
@ -1054,6 +1058,9 @@
|
|||
#define D_FP_PASSVERIFY "Wachtwoord herkend" // 0x21 Verify the fingerprint passed
|
||||
#define D_FP_UNKNOWNERROR "Fout" // Any other error
|
||||
|
||||
// xsns_96_flowratemeter.ino
|
||||
#define D_FLOWRATEMETER_NAME "Flowrate"
|
||||
|
||||
// xsns_83_neopool.ino
|
||||
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
|
||||
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
|
||||
|
|
|
@ -372,6 +372,7 @@
|
|||
#define D_OTA_URL "Adres serwera"
|
||||
#define D_START_UPGRADE "Aktualizuj"
|
||||
#define D_UPGRADE_BY_FILE_UPLOAD "Aktualizacja z pliku"
|
||||
#define D_UPLOAD_FACTORY "Switching to safeboot partition"
|
||||
#define D_UPLOAD_STARTED "Wgrywanie rozpoczęte"
|
||||
#define D_UPGRADE_STARTED "Aktualizacja rozpoczęta"
|
||||
#define D_UPLOAD_DONE "Wgrywanie zakończone"
|
||||
|
@ -866,6 +867,7 @@
|
|||
#define D_GPIO_SHIFT595_SER "74x595 SER"
|
||||
#define D_SENSOR_CM11_TX "CM110x TX"
|
||||
#define D_SENSOR_CM11_RX "CM110x RX"
|
||||
#define D_SENSOR_FLOWRATEMETER "Flowrate"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -913,6 +915,8 @@
|
|||
#define D_UNIT_WATT "W"
|
||||
#define D_UNIT_WATTHOUR "Wh"
|
||||
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
|
||||
#define D_UNIT_LITER_PER_MINUTE "l/min"
|
||||
#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
|
||||
|
||||
#define D_NEW_ADDRESS "Ustawiam adres na"
|
||||
#define D_OUT_OF_RANGE "Poza zakresem"
|
||||
|
@ -1054,6 +1058,9 @@
|
|||
#define D_FP_PASSVERIFY "Zweryfikowano poprawnie" // 0x21 Verify the fingerprint passed
|
||||
#define D_FP_UNKNOWNERROR "Błąd" // Any other error
|
||||
|
||||
// xsns_96_flowratemeter.ino
|
||||
#define D_FLOWRATEMETER_NAME "Flowrate"
|
||||
|
||||
// xsns_83_neopool.ino
|
||||
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
|
||||
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
|
||||
|
|
|
@ -372,6 +372,7 @@
|
|||
#define D_OTA_URL "OTA URL"
|
||||
#define D_START_UPGRADE "Iniciar atualização"
|
||||
#define D_UPGRADE_BY_FILE_UPLOAD "Atualização por arquivo local"
|
||||
#define D_UPLOAD_FACTORY "Switching to safeboot partition"
|
||||
#define D_UPLOAD_STARTED "Início do envio"
|
||||
#define D_UPGRADE_STARTED "Atualização iniciada"
|
||||
#define D_UPLOAD_DONE "Atualização finalizada"
|
||||
|
@ -866,6 +867,7 @@
|
|||
#define D_GPIO_SHIFT595_SER "74x595 SER"
|
||||
#define D_SENSOR_CM11_TX "CM110x TX"
|
||||
#define D_SENSOR_CM11_RX "CM110x RX"
|
||||
#define D_SENSOR_FLOWRATEMETER "Flowrate"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -913,6 +915,8 @@
|
|||
#define D_UNIT_WATT "W"
|
||||
#define D_UNIT_WATTHOUR "W/h"
|
||||
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
|
||||
#define D_UNIT_LITER_PER_MINUTE "l/min"
|
||||
#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
|
||||
|
||||
#define D_NEW_ADDRESS "Mudança de endereço para"
|
||||
#define D_OUT_OF_RANGE "Fora de Alcance"
|
||||
|
@ -1054,6 +1058,9 @@
|
|||
#define D_FP_PASSVERIFY "Senha verificada" // 0x21 Verify the fingerprint passed
|
||||
#define D_FP_UNKNOWNERROR "Erro" // Any other error
|
||||
|
||||
// xsns_96_flowratemeter.ino
|
||||
#define D_FLOWRATEMETER_NAME "Flowrate"
|
||||
|
||||
// xsns_83_neopool.ino
|
||||
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
|
||||
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
|
||||
|
|
|
@ -372,6 +372,7 @@
|
|||
#define D_OTA_URL "Url OTA"
|
||||
#define D_START_UPGRADE "Iniciar atualização"
|
||||
#define D_UPGRADE_BY_FILE_UPLOAD "Atualizar por envio de ficheiro"
|
||||
#define D_UPLOAD_FACTORY "Switching to safeboot partition"
|
||||
#define D_UPLOAD_STARTED "Envio Iniciado"
|
||||
#define D_UPGRADE_STARTED "Atualização Iniciada"
|
||||
#define D_UPLOAD_DONE "Atualização Finalizada"
|
||||
|
@ -866,6 +867,7 @@
|
|||
#define D_GPIO_SHIFT595_SER "74x595 SER"
|
||||
#define D_SENSOR_CM11_TX "CM110x TX"
|
||||
#define D_SENSOR_CM11_RX "CM110x RX"
|
||||
#define D_SENSOR_FLOWRATEMETER "Flowrate"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -913,6 +915,8 @@
|
|||
#define D_UNIT_WATT "W"
|
||||
#define D_UNIT_WATTHOUR "Wh"
|
||||
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
|
||||
#define D_UNIT_LITER_PER_MINUTE "l/min"
|
||||
#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
|
||||
|
||||
#define D_NEW_ADDRESS "Mudança de endereço para"
|
||||
#define D_OUT_OF_RANGE "Fora de Alcance"
|
||||
|
@ -1054,6 +1058,9 @@
|
|||
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
|
||||
#define D_FP_UNKNOWNERROR "Error" // Any other error
|
||||
|
||||
// xsns_96_flowratemeter.ino
|
||||
#define D_FLOWRATEMETER_NAME "Flowrate"
|
||||
|
||||
// xsns_83_neopool.ino
|
||||
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
|
||||
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
|
||||
|
|
|
@ -372,6 +372,7 @@
|
|||
#define D_OTA_URL "OTA Url"
|
||||
#define D_START_UPGRADE "Porneste actualizare"
|
||||
#define D_UPGRADE_BY_FILE_UPLOAD "Actualizare prin încărcare fișier"
|
||||
#define D_UPLOAD_FACTORY "Switching to safeboot partition"
|
||||
#define D_UPLOAD_STARTED "Încărcare începută"
|
||||
#define D_UPGRADE_STARTED "Actualizare începută"
|
||||
#define D_UPLOAD_DONE "Încărcare terminată"
|
||||
|
@ -866,6 +867,7 @@
|
|||
#define D_GPIO_SHIFT595_SER "74x595 SER"
|
||||
#define D_SENSOR_CM11_TX "CM110x TX"
|
||||
#define D_SENSOR_CM11_RX "CM110x RX"
|
||||
#define D_SENSOR_FLOWRATEMETER "Flowrate"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -913,6 +915,8 @@
|
|||
#define D_UNIT_WATT "W"
|
||||
#define D_UNIT_WATTHOUR "Wh"
|
||||
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
|
||||
#define D_UNIT_LITER_PER_MINUTE "l/min"
|
||||
#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
|
||||
|
||||
#define D_NEW_ADDRESS "Setting address to"
|
||||
#define D_OUT_OF_RANGE "Out of Range"
|
||||
|
@ -1054,6 +1058,9 @@
|
|||
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
|
||||
#define D_FP_UNKNOWNERROR "Error" // Any other error
|
||||
|
||||
// xsns_96_flowratemeter.ino
|
||||
#define D_FLOWRATEMETER_NAME "Flowrate"
|
||||
|
||||
// xsns_83_neopool.ino
|
||||
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
|
||||
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
|
||||
|
|
|
@ -372,6 +372,7 @@
|
|||
#define D_OTA_URL "OTA Url"
|
||||
#define D_START_UPGRADE "Начать обновление"
|
||||
#define D_UPGRADE_BY_FILE_UPLOAD "Обновление путем загрузки файлов"
|
||||
#define D_UPLOAD_FACTORY "Switching to safeboot partition"
|
||||
#define D_UPLOAD_STARTED "Загрузка началась"
|
||||
#define D_UPGRADE_STARTED "Обновление началось"
|
||||
#define D_UPLOAD_DONE "Загрузка завершена"
|
||||
|
@ -866,6 +867,7 @@
|
|||
#define D_GPIO_SHIFT595_SER "74x595 SER"
|
||||
#define D_SENSOR_CM11_TX "CM110x TX"
|
||||
#define D_SENSOR_CM11_RX "CM110x RX"
|
||||
#define D_SENSOR_FLOWRATEMETER "Flowrate"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "А"
|
||||
|
@ -913,6 +915,8 @@
|
|||
#define D_UNIT_WATT "Вт"
|
||||
#define D_UNIT_WATTHOUR "ВтЧ"
|
||||
#define D_UNIT_WATT_METER_QUADRAT "Вт/м²"
|
||||
#define D_UNIT_LITER_PER_MINUTE "l/min"
|
||||
#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
|
||||
|
||||
#define D_NEW_ADDRESS "Setting address to"
|
||||
#define D_OUT_OF_RANGE "Out of Range"
|
||||
|
@ -1054,6 +1058,9 @@
|
|||
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
|
||||
#define D_FP_UNKNOWNERROR "Error" // Any other error
|
||||
|
||||
// xsns_96_flowratemeter.ino
|
||||
#define D_FLOWRATEMETER_NAME "Flowrate"
|
||||
|
||||
// xsns_83_neopool.ino
|
||||
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
|
||||
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
|
||||
|
|
|
@ -372,6 +372,7 @@
|
|||
#define D_OTA_URL "URL OTA"
|
||||
#define D_START_UPGRADE "Spustiť aktualizáciu"
|
||||
#define D_UPGRADE_BY_FILE_UPLOAD "Aktualizácia nahraním súboru"
|
||||
#define D_UPLOAD_FACTORY "Switching to safeboot partition"
|
||||
#define D_UPLOAD_STARTED "Nahrávanie spustené"
|
||||
#define D_UPGRADE_STARTED "Aktualizácia spustená"
|
||||
#define D_UPLOAD_DONE "Nahrávanie ukončené"
|
||||
|
@ -866,6 +867,7 @@
|
|||
#define D_GPIO_SHIFT595_SER "74x595 SER"
|
||||
#define D_SENSOR_CM11_TX "CM110x TX"
|
||||
#define D_SENSOR_CM11_RX "CM110x RX"
|
||||
#define D_SENSOR_FLOWRATEMETER "Flowrate"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -913,6 +915,8 @@
|
|||
#define D_UNIT_WATT "W"
|
||||
#define D_UNIT_WATTHOUR "Wh"
|
||||
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
|
||||
#define D_UNIT_LITER_PER_MINUTE "l/min"
|
||||
#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
|
||||
|
||||
#define D_NEW_ADDRESS "Setting address to"
|
||||
#define D_OUT_OF_RANGE "Out of Range"
|
||||
|
@ -1054,6 +1058,9 @@
|
|||
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
|
||||
#define D_FP_UNKNOWNERROR "Error" // Any other error
|
||||
|
||||
// xsns_96_flowratemeter.ino
|
||||
#define D_FLOWRATEMETER_NAME "Flowrate"
|
||||
|
||||
// xsns_83_neopool.ino
|
||||
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
|
||||
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
|
||||
|
|
|
@ -372,6 +372,7 @@
|
|||
#define D_OTA_URL "OTA Url"
|
||||
#define D_START_UPGRADE "Starta uppdatering"
|
||||
#define D_UPGRADE_BY_FILE_UPLOAD "Uppgradering via filuppladdning"
|
||||
#define D_UPLOAD_FACTORY "Switching to safeboot partition"
|
||||
#define D_UPLOAD_STARTED "Uppladdning startad"
|
||||
#define D_UPGRADE_STARTED "Uppgradeing startad"
|
||||
#define D_UPLOAD_DONE "Uppladdning klar"
|
||||
|
@ -866,6 +867,7 @@
|
|||
#define D_GPIO_SHIFT595_SER "74x595 SER"
|
||||
#define D_SENSOR_CM11_TX "CM110x TX"
|
||||
#define D_SENSOR_CM11_RX "CM110x RX"
|
||||
#define D_SENSOR_FLOWRATEMETER "Flowrate"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -913,6 +915,8 @@
|
|||
#define D_UNIT_WATT "W"
|
||||
#define D_UNIT_WATTHOUR "Wh"
|
||||
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
|
||||
#define D_UNIT_LITER_PER_MINUTE "l/min"
|
||||
#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
|
||||
|
||||
#define D_NEW_ADDRESS "Setting address to"
|
||||
#define D_OUT_OF_RANGE "Out of Range"
|
||||
|
@ -1054,6 +1058,9 @@
|
|||
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
|
||||
#define D_FP_UNKNOWNERROR "Error" // Any other error
|
||||
|
||||
// xsns_96_flowratemeter.ino
|
||||
#define D_FLOWRATEMETER_NAME "Flowrate"
|
||||
|
||||
// xsns_83_neopool.ino
|
||||
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
|
||||
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
|
||||
|
|
|
@ -372,6 +372,7 @@
|
|||
#define D_OTA_URL "OTA Url"
|
||||
#define D_START_UPGRADE "Yükseltmeyi başlat"
|
||||
#define D_UPGRADE_BY_FILE_UPLOAD "Dosya kullanrak yükset"
|
||||
#define D_UPLOAD_FACTORY "Switching to safeboot partition"
|
||||
#define D_UPLOAD_STARTED "Yükleme başlatıldı"
|
||||
#define D_UPGRADE_STARTED "YÜkestlme başlatıldı"
|
||||
#define D_UPLOAD_DONE "Yükleme Tamamlandı"
|
||||
|
@ -866,6 +867,7 @@
|
|||
#define D_GPIO_SHIFT595_SER "74x595 SER"
|
||||
#define D_SENSOR_CM11_TX "CM110x TX"
|
||||
#define D_SENSOR_CM11_RX "CM110x RX"
|
||||
#define D_SENSOR_FLOWRATEMETER "Flowrate"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -913,6 +915,8 @@
|
|||
#define D_UNIT_WATT "W"
|
||||
#define D_UNIT_WATTHOUR "Wh"
|
||||
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
|
||||
#define D_UNIT_LITER_PER_MINUTE "l/min"
|
||||
#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
|
||||
|
||||
#define D_NEW_ADDRESS "Setting address to"
|
||||
#define D_OUT_OF_RANGE "Out of Range"
|
||||
|
@ -1054,6 +1058,9 @@
|
|||
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
|
||||
#define D_FP_UNKNOWNERROR "Error" // Any other error
|
||||
|
||||
// xsns_96_flowratemeter.ino
|
||||
#define D_FLOWRATEMETER_NAME "Flowrate"
|
||||
|
||||
// xsns_83_neopool.ino
|
||||
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
|
||||
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
|
||||
|
|
|
@ -372,6 +372,7 @@
|
|||
#define D_OTA_URL "OTA URL"
|
||||
#define D_START_UPGRADE "Почати оновлення"
|
||||
#define D_UPGRADE_BY_FILE_UPLOAD "Оновлення шляхом завантаження файлів"
|
||||
#define D_UPLOAD_FACTORY "Switching to safeboot partition"
|
||||
#define D_UPLOAD_STARTED "Завантаження почалось"
|
||||
#define D_UPGRADE_STARTED "Оновлення почалось"
|
||||
#define D_UPLOAD_DONE "Завантаження завершено"
|
||||
|
@ -866,6 +867,7 @@
|
|||
#define D_GPIO_SHIFT595_SER "74x595 SER"
|
||||
#define D_SENSOR_CM11_TX "CM110x TX"
|
||||
#define D_SENSOR_CM11_RX "CM110x RX"
|
||||
#define D_SENSOR_FLOWRATEMETER "Flowrate"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "А"
|
||||
|
@ -913,6 +915,8 @@
|
|||
#define D_UNIT_WATT "Вт"
|
||||
#define D_UNIT_WATTHOUR "Вт/г"
|
||||
#define D_UNIT_WATT_METER_QUADRAT "Вт/м²"
|
||||
#define D_UNIT_LITER_PER_MINUTE "l/min"
|
||||
#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
|
||||
|
||||
#define D_NEW_ADDRESS "Setting address to"
|
||||
#define D_OUT_OF_RANGE "Out of Range"
|
||||
|
@ -1054,6 +1058,9 @@
|
|||
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
|
||||
#define D_FP_UNKNOWNERROR "Error" // Any other error
|
||||
|
||||
// xsns_96_flowratemeter.ino
|
||||
#define D_FLOWRATEMETER_NAME "Flowrate"
|
||||
|
||||
// xsns_83_neopool.ino
|
||||
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
|
||||
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
|
||||
|
|
|
@ -372,6 +372,7 @@
|
|||
#define D_OTA_URL "Đường dẫn OTA"
|
||||
#define D_START_UPGRADE "Bắt đầu nâng cấp"
|
||||
#define D_UPGRADE_BY_FILE_UPLOAD "Nâng cấp thông qua tải lên tệp"
|
||||
#define D_UPLOAD_FACTORY "Switching to safeboot partition"
|
||||
#define D_UPLOAD_STARTED "Bắt đầu tải lên"
|
||||
#define D_UPGRADE_STARTED "Bắt đầu nâng cấp"
|
||||
#define D_UPLOAD_DONE "Hoàn thành tải tệp"
|
||||
|
@ -866,6 +867,7 @@
|
|||
#define D_GPIO_SHIFT595_SER "74x595 SER"
|
||||
#define D_SENSOR_CM11_TX "CM110x TX"
|
||||
#define D_SENSOR_CM11_RX "CM110x RX"
|
||||
#define D_SENSOR_FLOWRATEMETER "Flowrate"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -913,6 +915,8 @@
|
|||
#define D_UNIT_WATT "W"
|
||||
#define D_UNIT_WATTHOUR "Wh"
|
||||
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
|
||||
#define D_UNIT_LITER_PER_MINUTE "l/min"
|
||||
#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
|
||||
|
||||
#define D_NEW_ADDRESS "Setting address to"
|
||||
#define D_OUT_OF_RANGE "Out of Range"
|
||||
|
@ -1054,6 +1058,9 @@
|
|||
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
|
||||
#define D_FP_UNKNOWNERROR "Error" // Any other error
|
||||
|
||||
// xsns_96_flowratemeter.ino
|
||||
#define D_FLOWRATEMETER_NAME "Flowrate"
|
||||
|
||||
// xsns_83_neopool.ino
|
||||
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
|
||||
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
|
||||
|
|
|
@ -372,6 +372,7 @@
|
|||
#define D_OTA_URL "OTA 地址"
|
||||
#define D_START_UPGRADE "开始升级"
|
||||
#define D_UPGRADE_BY_FILE_UPLOAD "通过文件升级"
|
||||
#define D_UPLOAD_FACTORY "Switching to safeboot partition"
|
||||
#define D_UPLOAD_STARTED "开始上传"
|
||||
#define D_UPGRADE_STARTED "开始升级"
|
||||
#define D_UPLOAD_DONE "上传完成"
|
||||
|
@ -866,6 +867,7 @@
|
|||
#define D_GPIO_SHIFT595_SER "74x595 SER"
|
||||
#define D_SENSOR_CM11_TX "CM110x TX"
|
||||
#define D_SENSOR_CM11_RX "CM110x RX"
|
||||
#define D_SENSOR_FLOWRATEMETER "Flowrate"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "A"
|
||||
|
@ -913,6 +915,8 @@
|
|||
#define D_UNIT_WATT "W"
|
||||
#define D_UNIT_WATTHOUR "Wh"
|
||||
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
|
||||
#define D_UNIT_LITER_PER_MINUTE "l/min"
|
||||
#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
|
||||
|
||||
#define D_NEW_ADDRESS "Setting address to"
|
||||
#define D_OUT_OF_RANGE "Out of Range"
|
||||
|
@ -1054,6 +1058,9 @@
|
|||
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
|
||||
#define D_FP_UNKNOWNERROR "Error" // Any other error
|
||||
|
||||
// xsns_96_flowratemeter.ino
|
||||
#define D_FLOWRATEMETER_NAME "Flowrate"
|
||||
|
||||
// xsns_83_neopool.ino
|
||||
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
|
||||
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
|
||||
|
|
|
@ -372,6 +372,7 @@
|
|||
#define D_OTA_URL "OTA網址"
|
||||
#define D_START_UPGRADE "開始升級"
|
||||
#define D_UPGRADE_BY_FILE_UPLOAD "透過檔案升級"
|
||||
#define D_UPLOAD_FACTORY "Switching to safeboot partition"
|
||||
#define D_UPLOAD_STARTED "已開始上傳"
|
||||
#define D_UPGRADE_STARTED "已開始升級"
|
||||
#define D_UPLOAD_DONE "已上傳完成"
|
||||
|
@ -866,6 +867,7 @@
|
|||
#define D_GPIO_SHIFT595_SER "74x595 SER"
|
||||
#define D_SENSOR_CM11_TX "CM110x TX"
|
||||
#define D_SENSOR_CM11_RX "CM110x RX"
|
||||
#define D_SENSOR_FLOWRATEMETER "Flowrate"
|
||||
|
||||
// Units
|
||||
#define D_UNIT_AMPERE "安培"
|
||||
|
@ -913,6 +915,8 @@
|
|||
#define D_UNIT_WATT "瓦特"
|
||||
#define D_UNIT_WATTHOUR "瓦小時"
|
||||
#define D_UNIT_WATT_METER_QUADRAT "W/m²"
|
||||
#define D_UNIT_LITER_PER_MINUTE "l/min"
|
||||
#define D_UNIT_CUBICMETER_PER_HOUR "m³/h"
|
||||
|
||||
#define D_NEW_ADDRESS "Setting address to"
|
||||
#define D_OUT_OF_RANGE "Out of Range"
|
||||
|
@ -1054,6 +1058,9 @@
|
|||
#define D_FP_PASSVERIFY "Password verified" // 0x21 Verify the fingerprint passed
|
||||
#define D_FP_UNKNOWNERROR "Error" // Any other error
|
||||
|
||||
// xsns_96_flowratemeter.ino
|
||||
#define D_FLOWRATEMETER_NAME "Flowrate"
|
||||
|
||||
// xsns_83_neopool.ino
|
||||
#define D_NEOPOOL_MACH_NONE "NeoPool" // Machine names
|
||||
#define D_NEOPOOL_MACH_HIDROLIFE "Hidrolife"
|
||||
|
|
|
@ -948,6 +948,8 @@
|
|||
//#define USE_NEOPOOL // Add support for Sugar Valley NeoPool Controller - also known under brands Hidrolife, Aquascenic, Oxilife, Bionet, Hidroniser, UVScenic, Station, Brilix, Bayrol and Hay (+6k flash, +60 mem)
|
||||
// #define NEOPOOL_MODBUS_ADDRESS 1 // Any modbus address
|
||||
|
||||
//#define FLOWRATEMETER // Add support for water flow meter YF-DN50 and similary (+1k7 code)
|
||||
|
||||
// -- Thermostat control ----------------------------
|
||||
//#define USE_THERMOSTAT // Add support for Thermostat
|
||||
#define THERMOSTAT_CONTROLLER_OUTPUTS 1 // Number of outputs to be controlled independently
|
||||
|
|
|
@ -366,7 +366,7 @@ typedef union {
|
|||
uint8_t data;
|
||||
struct {
|
||||
uint8_t spare0 : 1;
|
||||
uint8_t spare1 : 1;
|
||||
uint8_t flowratemeter_unit : 1; // Sensor96 9,x - unit l/min (0) or m³/h (1)
|
||||
uint8_t bh1750_2_resolution : 2;
|
||||
uint8_t bh1750_1_resolution : 2; // Sensor10 1,2,3
|
||||
uint8_t hx711_json_weight_change : 1; // Sensor34 8,x - Enable JSON message on weight change
|
||||
|
@ -794,10 +794,10 @@ typedef struct {
|
|||
uint8_t tcp_config; // F5F
|
||||
uint8_t light_step_pixels; // F60
|
||||
|
||||
uint8_t free_f61[27]; // F61 - Decrement if adding new Setting variables just above and below
|
||||
uint8_t free_f61[23]; // F61 - Decrement if adding new Setting variables just above and below
|
||||
|
||||
// Only 32 bit boundary variables below
|
||||
|
||||
uint16_t flowratemeter_calibration[2];// F78
|
||||
int32_t energy_kWhexport_ph[3]; // F7C
|
||||
uint32_t eth_ipv4_address[5]; // F88
|
||||
uint32_t energy_kWhtotal; // F9C
|
||||
|
|
|
@ -295,14 +295,37 @@ extern "C" {
|
|||
#include "rom/spi_flash.h"
|
||||
#endif
|
||||
|
||||
bool EspSingleOtaPartition(void) {
|
||||
return (1 == esp_ota_get_app_partition_count());
|
||||
}
|
||||
|
||||
bool EspRunningFactoryPartition(void) {
|
||||
const esp_partition_t *cur_part = esp_ota_get_running_partition();
|
||||
return (cur_part->type == 0 && cur_part->subtype == 0);
|
||||
}
|
||||
|
||||
void EspPrepRestartToSafeMode(void) {
|
||||
// esp_ota_mark_app_invalid_rollback_and_reboot(); // Doesn't work 20220501
|
||||
const esp_partition_t *otadata_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
|
||||
if (otadata_partition) {
|
||||
esp_partition_erase_range(otadata_partition, 0, SPI_FLASH_SEC_SIZE * 2);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t EspFlashBaseAddress(void) {
|
||||
if (EspSingleOtaPartition()) { // Only one partition so start at end of sketch
|
||||
const esp_partition_t *running = esp_ota_get_running_partition();
|
||||
if (!running) { return 0; }
|
||||
return running->address + ESP_getSketchSize();
|
||||
} else { // Select other partition
|
||||
const esp_partition_t* partition = esp_ota_get_next_update_partition(nullptr);
|
||||
if (!partition) { return 0; }
|
||||
return partition->address; // For tasmota 0x00010000 or 0x00200000
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t EspFlashBaseEndAddress(void) {
|
||||
const esp_partition_t* partition = esp_ota_get_next_update_partition(nullptr);
|
||||
const esp_partition_t* partition = (EspSingleOtaPartition()) ? esp_ota_get_running_partition() : esp_ota_get_next_update_partition(nullptr);
|
||||
if (!partition) { return 0; }
|
||||
return partition->address + partition->size; // For tasmota 0x00200000 or 0x003F0000
|
||||
}
|
||||
|
@ -664,7 +687,7 @@ typedef struct {
|
|||
if (rev3) { return F("ESP32-PICO-V3"); } // Max 240MHz, Dual core, LGA 7*7, ESP32-PICO-V3-ZERO, ESP32-PICO-V3-ZERO-DevKit
|
||||
else { return F("ESP32-PICO-D4"); } // Max 240MHz, Dual core, LGA 7*7, 4MB embedded flash, ESP32-PICO-KIT
|
||||
case 6: return F("ESP32-PICO-V3-02"); // Max 240MHz, Dual core, LGA 7*7, 8MB embedded flash, 2MB embedded PSRAM, ESP32-PICO-MINI-02, ESP32-PICO-DevKitM-2
|
||||
case 7: return F("ESP32-D0WDR2-V3"); // Max 240MHz, Dual core, QFN 5*5, ESP32-WROOM-32E, ESP32_WROVER-E, ESP32-DevKitC?
|
||||
case 7: return F("ESP32-D0WDR2-V3"); // Max 240MHz, Dual core, QFN 5*5, ESP32-WROOM-32E, ESP32_WROVER-E, ESP32-DevKitC
|
||||
}
|
||||
#endif // CONFIG_IDF_TARGET_ESP32
|
||||
return F("ESP32");
|
||||
|
@ -672,16 +695,23 @@ typedef struct {
|
|||
else if (2 == chip_model) { // ESP32-S2
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S2
|
||||
/* esptool:
|
||||
def get_pkg_version(self):
|
||||
def get_flash_version(self):
|
||||
num_word = 3
|
||||
block1_addr = self.EFUSE_BASE + 0x044
|
||||
word3 = self.read_reg(block1_addr + (4 * num_word))
|
||||
pkg_version = (word3 >> 21) & 0x0F
|
||||
return pkg_version
|
||||
|
||||
def get_psram_version(self):
|
||||
num_word = 3
|
||||
block1_addr = self.EFUSE_BASE + 0x044
|
||||
word3 = self.read_reg(block1_addr + (4 * num_word))
|
||||
pkg_version = (word3 >> 28) & 0x0F
|
||||
return pkg_version
|
||||
*/
|
||||
uint32_t chip_ver = REG_GET_FIELD(EFUSE_RD_MAC_SPI_SYS_3_REG, EFUSE_PKG_VERSION);
|
||||
uint32_t pkg_version = chip_ver & 0x7;
|
||||
// uint32_t pkg_version = esp_efuse_get_pkg_ver();
|
||||
uint32_t chip_ver = REG_GET_FIELD(EFUSE_RD_MAC_SPI_SYS_3_REG, EFUSE_FLASH_VERSION);
|
||||
uint32_t psram_ver = REG_GET_FIELD(EFUSE_RD_MAC_SPI_SYS_3_REG, EFUSE_PSRAM_VERSION);
|
||||
uint32_t pkg_version = (chip_ver & 0xF) + ((psram_ver & 0xF) * 100);
|
||||
|
||||
// AddLog(LOG_LEVEL_DEBUG_MORE, PSTR("HDW: ESP32 Model %d, Revision %d, Core %d, Package %d"), chip_info.model, chip_revision, chip_info.cores, chip_ver);
|
||||
|
||||
|
@ -690,6 +720,8 @@ typedef struct {
|
|||
case 1: return F("ESP32-S2FH2"); // Max 240MHz, Single core, QFN 7*7, 2MB embedded flash, ESP32-S2-MINI-1, ESP32-S2-DevKitM-1
|
||||
case 2: return F("ESP32-S2FH4"); // Max 240MHz, Single core, QFN 7*7, 4MB embedded flash
|
||||
case 3: return F("ESP32-S2FN4R2"); // Max 240MHz, Single core, QFN 7*7, 4MB embedded flash, 2MB embedded PSRAM, , ESP32-S2-MINI-1U, ESP32-S2-DevKitM-1U
|
||||
case 100: return F("ESP32-S2R2");
|
||||
case 102: return F("ESP32-S2FNR2"); // Max 240MHz, Single core, QFN 7*7, 4MB embedded flash, 2MB embedded PSRAM, , Lolin S2 mini
|
||||
}
|
||||
#endif // CONFIG_IDF_TARGET_ESP32S2
|
||||
return F("ESP32-S2");
|
||||
|
|
|
@ -806,7 +806,9 @@ void ResponseAppendFeatures(void)
|
|||
#ifdef USE_IMPROV
|
||||
feature8 |= 0x04000000; // xdrv_62_improv.ino
|
||||
#endif
|
||||
// feature8 |= 0x08000000;
|
||||
#ifdef USE_FLOWRATEMETER
|
||||
feature8 |= 0x08000000; // xsns_96_flowratemeter.ino
|
||||
#endif
|
||||
|
||||
// feature8 |= 0x10000000;
|
||||
// feature8 |= 0x20000000;
|
||||
|
|
|
@ -1242,6 +1242,19 @@ void Every250mSeconds(void)
|
|||
}
|
||||
}
|
||||
#endif // ESP8266
|
||||
|
||||
#ifdef ESP32
|
||||
#ifndef FIRMWARE_MINIMAL
|
||||
if (EspSingleOtaPartition()) {
|
||||
RtcSettings.ota_loader = 1; // Try safemode image next
|
||||
SettingsSaveAll();
|
||||
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_APPLICATION D_RESTARTING));
|
||||
EspPrepRestartToSafeMode();
|
||||
EspRestart();
|
||||
}
|
||||
#endif // FIRMWARE_MINIMAL
|
||||
#endif // ESP32
|
||||
|
||||
char version[50];
|
||||
snprintf_P(version, sizeof(version), PSTR("%s%s"), TasmotaGlobal.version, TasmotaGlobal.image_name);
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_UPLOAD "%s %s"), full_ota_url, version);
|
||||
|
|
|
@ -617,8 +617,7 @@ void WifiConnect(void)
|
|||
#endif // WIFI_RF_PRE_INIT
|
||||
}
|
||||
|
||||
void WifiShutdown(bool option = false)
|
||||
{
|
||||
void WifiShutdown(bool option) {
|
||||
// option = false - Legacy disconnect also used by DeepSleep
|
||||
// option = true - Disconnect with SDK wifi calibrate sector erase when WIFI_FORCE_RF_CAL_ERASE enabled
|
||||
delay(100); // Allow time for message xfer - disabled v6.1.0b
|
||||
|
|
|
@ -418,7 +418,7 @@ enum SettingsTextIndex { SET_OTAURL,
|
|||
#endif // ESP32
|
||||
SET_SHD_PARAM,
|
||||
SET_RGX_SSID, SET_RGX_PASSWORD,
|
||||
SET_INFLUXDB_HOST, SET_INFLUXDB_PORT, SET_INFLUXDB_ORG, SET_INFLUXDB_TOKEN, SET_INFLUXDB_BUCKET,
|
||||
SET_INFLUXDB_HOST, SET_INFLUXDB_PORT, SET_INFLUXDB_ORG, SET_INFLUXDB_TOKEN, SET_INFLUXDB_BUCKET, SET_INFLUXDB_RP,
|
||||
SET_MAX };
|
||||
|
||||
enum SpiInterfaces { SPI_NONE, SPI_MOSI, SPI_MISO, SPI_MOSI_MISO };
|
||||
|
|
|
@ -22,6 +22,150 @@
|
|||
|
||||
#ifdef ESP32
|
||||
|
||||
/*********************************************************************************************\
|
||||
* [tasmota32x-safemode.bin]
|
||||
* Provide an image with useful supported sensors enabled
|
||||
\*********************************************************************************************/
|
||||
|
||||
#ifdef FIRMWARE_SAFEMODE
|
||||
#define FIRMWARE_MINIMAL
|
||||
|
||||
#undef CODE_IMAGE_STR
|
||||
#define CODE_IMAGE_STR "safemode"
|
||||
|
||||
#define USE_TLS
|
||||
#define USE_WEBSERVER
|
||||
#define USE_WEBCLIENT
|
||||
#define USE_WEBCLIENT_HTTPS
|
||||
|
||||
#undef USE_UFILESYS
|
||||
#undef GUI_TRASH_FILE
|
||||
#undef GUI_EDIT_FILE
|
||||
#undef USE_PING
|
||||
#undef USE_AUTOCONF
|
||||
#undef USE_BERRY
|
||||
|
||||
#undef FIRMWARE_LITE // Disable tasmota-lite with no sensors
|
||||
#undef FIRMWARE_SENSORS // Disable tasmota-sensors with useful sensors enabled
|
||||
#undef FIRMWARE_KNX_NO_EMULATION // Disable tasmota-knx with KNX but without Emulation
|
||||
#undef FIRMWARE_DISPLAYS // Disable tasmota-display with display drivers enabled
|
||||
#undef FIRMWARE_IR // Disable tasmota-ir with IR full protocols activated
|
||||
#undef FIRMWARE_WEBCAM
|
||||
#undef FIRMWARE_BLUETOOTH
|
||||
#undef FIRMWARE_LVGL
|
||||
#undef FIRMWARE_TASMOTA32
|
||||
|
||||
#undef USE_IMPROV // Disable support for IMPROV serial protocol as used by esp-web-tools (+2k code)
|
||||
#undef USE_TASMESH // Disable Tasmota Mesh using ESP-NOW (+11k code)
|
||||
#undef USE_ARDUINO_OTA // Disable support for Arduino OTA
|
||||
#undef USE_INFLUXDB // Disable influxdb support (+5k code)
|
||||
#undef USE_DOMOTICZ // Disable Domoticz
|
||||
#undef USE_HOME_ASSISTANT // Disable Home Assistant
|
||||
#undef USE_TASMOTA_DISCOVERY // Disable Tasmota Discovery support (+2k code)
|
||||
#undef USE_TELEGRAM // Disable support for Telegram protocol (+49k code, +7.0k mem and +4.8k additional during connection handshake)
|
||||
//#undef USE_MQTT_TLS // Disable TLS support won't work as the MQTTHost is not set
|
||||
#undef USE_KNX // Disable KNX IP Protocol Support
|
||||
//#undef USE_WEBSERVER // Disable Webserver
|
||||
#undef USE_ENHANCED_GUI_WIFI_SCAN // Disable wifi scan output with BSSID (+0k5 code)
|
||||
#undef USE_WEBSEND_RESPONSE // Disable command WebSend response message (+1k code)
|
||||
#undef USE_EMULATION // Disable Wemo or Hue emulation
|
||||
#undef USE_EMULATION_HUE // Disable Hue Bridge emulation for Alexa (+14k code, +2k mem common)
|
||||
#undef USE_EMULATION_WEMO // Disable Belkin WeMo emulation for Alexa (+6k code, +2k mem common)
|
||||
#undef USE_CUSTOM // Disable Custom features
|
||||
#undef USE_DISCOVERY // Disable Discovery services for both MQTT and web server
|
||||
#undef USE_TIMERS // Disable support for up to 16 timers
|
||||
#undef USE_TIMERS_WEB // Disable support for timer webpage
|
||||
#undef USE_SUNRISE // Disable support for Sunrise and sunset tools
|
||||
#undef USE_PING // Disable Ping command (+2k code)
|
||||
#undef USE_UNISHOX_COMPRESSION // Disable support for string compression in Rules or Scripts
|
||||
#undef USE_RULES // Disable support for rules
|
||||
#undef USE_SCRIPT // Disable support for script
|
||||
|
||||
// -- Optional modules ----------------------------
|
||||
#undef ROTARY_V1 // Disable support for MI Desk Lamp
|
||||
#undef USE_SONOFF_RF // Disable support for Sonoff Rf Bridge (+3k2 code)
|
||||
#undef USE_RF_FLASH // Disable support for flashing the EFM8BB1 chip on the Sonoff RF Bridge. C2CK must be connected to GPIO4, C2D to GPIO5 on the PCB
|
||||
#undef USE_SONOFF_SC // Disable support for Sonoff Sc (+1k1 code)
|
||||
#undef USE_TUYA_MCU // Disable support for Tuya Serial MCU
|
||||
#undef USE_ARMTRONIX_DIMMERS // Disable support for Armtronix Dimmers (+1k4 code)
|
||||
#undef USE_PS_16_DZ // Disable support for PS-16-DZ Dimmer and Sonoff L1 (+2k code)
|
||||
#undef USE_SONOFF_IFAN // Disable support for Sonoff iFan02 and iFan03 (+2k code)
|
||||
#undef USE_BUZZER // Disable support for a buzzer (+0k6 code)
|
||||
#undef USE_ARILUX_RF // Disable support for Arilux RF remote controller
|
||||
#undef USE_SHUTTER // Disable Shutter support for up to 4 shutter with different motortypes (+6k code)
|
||||
#undef USE_DEEPSLEEP // Disable support for deepsleep (+1k code)
|
||||
#undef USE_EXS_DIMMER // Disable support for EX-Store WiFi Dimmer
|
||||
#undef USE_HOTPLUG // Disable support for HotPlug
|
||||
#undef USE_DEVICE_GROUPS // Disable support for device groups (+3k5 code)
|
||||
#undef USE_PWM_DIMMER // Disable support for MJ-SD01/acenx/NTONPOWER PWM dimmers (+4k5 code)
|
||||
#undef USE_PWM_DIMMER_REMOTE // Disbale support for remote switches to PWM Dimmer
|
||||
#undef USE_KEELOQ // Disable support for Jarolift rollers by Keeloq algorithm (+4k5 code)
|
||||
#undef USE_SONOFF_D1 // Disable support for Sonoff D1 Dimmer (+0k7 code)
|
||||
#undef USE_SHELLY_DIMMER // Disable support for Shelly Dimmer (+3k code)
|
||||
|
||||
// -- Optional light modules ----------------------
|
||||
#undef USE_LIGHT // Disable support for lights
|
||||
|
||||
#undef USE_COUNTER // Disable counters
|
||||
#define USE_ADC_VCC // Display Vcc in Power status. Disable for use as Analog input on selected devices
|
||||
#undef USE_DS18x20 // Disable DS18x20 sensor
|
||||
|
||||
#undef USE_I2C // Disable all I2C sensors and devices
|
||||
#undef USE_SPI // Disable all SPI devices
|
||||
#undef USE_DISPLAY // Disable Display support
|
||||
|
||||
#undef USE_MHZ19 // Disable support for MH-Z19 CO2 sensor
|
||||
#undef USE_SENSEAIR // Disable support for SenseAir K30, K70 and S8 CO2 sensor
|
||||
#undef USE_PMS5003 // Disable support for PMS5003 and PMS7003 particle concentration sensor
|
||||
#undef USE_NOVA_SDS // Disable support for SDS011 and SDS021 particle concentration sensor
|
||||
#undef USE_HPMA // Disable support for Honeywell HPMA115S0 particle concentration sensor
|
||||
#undef USE_SR04 // Disable support for HC-SR04 ultrasonic devices (+1k code)
|
||||
#undef USE_DYP // Disable support for DYP ME-007 ultrasonic distance sensor, serial port version (+0k5 code)
|
||||
#undef USE_SERIAL_BRIDGE // Disable support for software Serial Bridge
|
||||
#undef USE_TCP_BRIDGE // DIsable support for Serial to TCP bridge (+1.3k code)
|
||||
#undef USE_MP3_PLAYER // Disable DFPlayer Mini MP3 Player RB-DFR-562 commands: play, volume and stop
|
||||
#undef USE_AZ7798 // Disable support for AZ-Instrument 7798 CO2 datalogger
|
||||
#undef USE_PN532_HSU // Disable support for PN532 using HSU (Serial) interface (+1k8 code, 140 bytes mem)
|
||||
#undef USE_ZIGBEE // Disable serial communication with Zigbee CC2530 flashed with ZNP
|
||||
#undef USE_RDM6300 // Disable support for RDM6300 125kHz RFID Reader (+0k8)
|
||||
#undef USE_IBEACON // Disable support for bluetooth LE passive scan of ibeacon devices (uses HM17 module)
|
||||
#undef USE_GPS // Disable support for GPS and NTP Server for becoming Stratus 1 Time Source (+ 3.1kb flash, +132 bytes RAM)
|
||||
#undef USE_HM10 // (ESP8266 only) Disable support for HM-10 as a BLE-bridge for the LYWSD03 (+5k1 code)
|
||||
#undef USE_BLE_ESP32 // (ESP32 only) Disable support for native BLE on ESP32 - use new driver
|
||||
#undef USE_MI_ESP32 // (ESP32 only) Disable support for ESP32 as a BLE-bridge (+9k2 mem, +292k flash)
|
||||
#undef USE_HRXL // Disable support for MaxBotix HRXL-MaxSonar ultrasonic range finders (+0k7)
|
||||
#undef USE_TASMOTA_CLIENT // Disable support for Arduino Uno/Pro Mini via serial interface including flashing (+2k3 code, 44 mem)
|
||||
#undef USE_OPENTHERM // Disable support for OpenTherm (+15k code)
|
||||
#undef USE_MIEL_HVAC // Disable support for Mitsubishi Electric HVAC serial interface (+5k code)
|
||||
#undef USE_PROJECTOR_CTRL // Disable support for LCD/DLP Projector serial control interface
|
||||
#undef USE_AS608 // Disable support for AS608 optical and R503 capacitive fingerprint sensor (+3k4 code)
|
||||
#undef USE_TFMINIPLUS // Disable support for TFmini Plus (TFmini, TFmini-S) LiDAR modules via UART interface (+0k8)
|
||||
#undef USE_HRG15 // Disable support for Hydreon RG-15 Solid State Rain sensor (+1k5 code)
|
||||
#undef USE_VINDRIKTNING // Disable support for IKEA VINDRIKTNING particle concentration sensor (+0k6 code)
|
||||
|
||||
#undef USE_ENERGY_SENSOR // Disable energy sensors
|
||||
|
||||
#undef USE_DHT // Disable support for DHT11, AM2301 (DHT21, DHT22, AM2302, AM2321) and SI7021 Temperature and Humidity sensor
|
||||
#undef USE_MAX31855 // Disable MAX31855 K-Type thermocouple sensor using softSPI
|
||||
#undef USE_MAX31865 // Disable support for MAX31865 RTD sensors using softSPI
|
||||
#undef USE_LMT01 // Disable support for TI LMT01 temperature sensor, count pulses on single GPIO (+0k5 code)
|
||||
#undef USE_IR_REMOTE // Disable IR driver
|
||||
#undef USE_TM1638 // Disable support for TM1638 switches copying Switch1 .. Switch8
|
||||
#undef USE_HX711 // Disable support for HX711 load cell
|
||||
#undef USE_TX20_WIND_SENSOR // Disable support for La Crosse TX20 anemometer
|
||||
#undef USE_TX23_WIND_SENSOR // Disable support for La Crosse TX23 anemometer
|
||||
#undef USE_WINDMETER // Disable support for analog anemometer (+2k2 code)
|
||||
#undef USE_RC_SWITCH // Disable support for RF transceiver using library RcSwitch
|
||||
#undef USE_RF_SENSOR // Disable support for RF sensor receiver (434MHz or 868MHz) (+0k8 code)
|
||||
#undef USE_HRE // Disable support for Badger HR-E Water Meter (+1k4 code)
|
||||
#undef USE_A4988_STEPPER // Disable support for A4988_Stepper
|
||||
#undef USE_THERMOSTAT // Disable support for Thermostat
|
||||
#undef USE_PROMETHEUS // Disable support for https://prometheus.io/ metrics exporting over HTTP /metrics endpoint
|
||||
#undef DEBUG_THEO // Disable debug code
|
||||
#undef USE_DEBUG_DRIVER // Disable debug code
|
||||
#undef USE_AC_ZERO_CROSS_DIMMER // Disable support for AC_ZERO_CROSS_DIMMER
|
||||
#endif // FIRMWARE_SAFEMODE
|
||||
|
||||
/*********************************************************************************************\
|
||||
* [tasmota32-webcam.bin]
|
||||
* Provide an image with useful supported sensors enabled
|
||||
|
|
|
@ -38,6 +38,7 @@ extern "C" {
|
|||
void KNX_CB_Action(message_t const &msg, void *arg);
|
||||
#endif // USE_KNX
|
||||
|
||||
void WifiShutdown(bool option = false);
|
||||
void DomoticzTempHumPressureSensor(float temp, float hum, float baro = -1);
|
||||
char* ToHex_P(const unsigned char * in, size_t insz, char * out, size_t outsz, char inbetween = '\0');
|
||||
extern "C" void custom_crash_callback(struct rst_info * rst_info, uint32_t stack, uint32_t stack_end);
|
||||
|
|
|
@ -187,6 +187,7 @@ enum UserSelectablePins {
|
|||
GPIO_RESET, // Generic reset
|
||||
GPIO_MS01, // Sonoff MS01 Moisture Sensor 1wire interface
|
||||
GPIO_SDIO_CMD, GPIO_SDIO_CLK, GPIO_SDIO_D0, GPIO_SDIO_D1, GPIO_SDIO_D2, GPIO_SDIO_D3, // SD Card SDIO interface, including 1-bit and 4-bit modes
|
||||
GPIO_FLOWRATEMETER_IN, // Flowrate Meter
|
||||
GPIO_SENSOR_END };
|
||||
|
||||
enum ProgramSelectablePins {
|
||||
|
@ -418,12 +419,14 @@ const char kSensorNames[] PROGMEM =
|
|||
D_SENSOR_SDIO_D1 "|"
|
||||
D_SENSOR_SDIO_D2 "|"
|
||||
D_SENSOR_SDIO_D3 "|"
|
||||
D_SENSOR_FLOWRATEMETER "|"
|
||||
;
|
||||
|
||||
const char kSensorNamesFixed[] PROGMEM =
|
||||
D_SENSOR_USER;
|
||||
|
||||
#define MAX_MAX31865S 6
|
||||
#define MAX_FLOWRATEMETER 2
|
||||
#define MAX_A4988_MSS 3
|
||||
#define MAX_WEBCAM_DATA 8
|
||||
#define MAX_WEBCAM_HSD 3
|
||||
|
@ -973,6 +976,11 @@ const uint16_t kGpioNiceList[] PROGMEM = {
|
|||
AGPIO(GPIO_CM11_TXD), // CM110x Serial interface
|
||||
AGPIO(GPIO_CM11_RXD), // CM110x Serial interface
|
||||
#endif
|
||||
|
||||
#if defined(USE_FLOWRATEMETER)
|
||||
AGPIO(GPIO_FLOWRATEMETER_IN) + MAX_FLOWRATEMETER, // Flow meter Pin
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------------------------*\
|
||||
* ESP32 specifics
|
||||
\*-------------------------------------------------------------------------------------------*/
|
||||
|
|
|
@ -209,10 +209,12 @@ const char HTTP_SCRIPT_INFO_END[] PROGMEM =
|
|||
|
||||
#ifdef USE_UNISHOX_COMPRESSION
|
||||
#include "./html_compressed/HTTP_HEAD_LAST_SCRIPT.h"
|
||||
#include "./html_compressed/HTTP_HEAD_LAST_SCRIPT32.h"
|
||||
#include "./html_compressed/HTTP_HEAD_STYLE1.h"
|
||||
#include "./html_compressed/HTTP_HEAD_STYLE2.h"
|
||||
#else
|
||||
#include "./html_uncompressed/HTTP_HEAD_LAST_SCRIPT.h"
|
||||
#include "./html_uncompressed/HTTP_HEAD_LAST_SCRIPT32.h"
|
||||
#include "./html_uncompressed/HTTP_HEAD_STYLE1.h"
|
||||
#include "./html_uncompressed/HTTP_HEAD_STYLE2.h"
|
||||
#endif
|
||||
|
@ -241,7 +243,11 @@ const char HTTP_HEAD_STYLE3[] PROGMEM =
|
|||
"<body>"
|
||||
"<div style='text-align:left;display:inline-block;color:#%06x;min-width:340px;'>" // COLOR_TEXT
|
||||
#ifdef FIRMWARE_MINIMAL
|
||||
#ifdef FIRMWARE_SAFEMODE
|
||||
"<div style='text-align:center;color:#%06x;'><h3>SafeMode</h3></div>" // COLOR_TEXT_SUCCESS
|
||||
#else
|
||||
"<div style='text-align:center;color:#%06x;'><h3>" D_MINIMAL_FIRMWARE_PLEASE_UPGRADE "</h3></div>" // COLOR_TEXT_WARNING
|
||||
#endif
|
||||
#endif
|
||||
"<div style='text-align:center;color:#%06x;'><noscript>" D_NOSCRIPT "<br></noscript>" // COLOR_TITLE
|
||||
/*
|
||||
|
@ -352,7 +358,17 @@ const char HTTP_FORM_RST_UPG[] PROGMEM =
|
|||
"<br><button type='submit' onclick='eb(\"f1\").style.display=\"none\";eb(\"f2\").style.display=\"block\";this.form.submit();'>" D_START " %s</button></form>"
|
||||
"</fieldset>"
|
||||
"</div>"
|
||||
"<div id='f2' style='display:none;text-align:center;'><b>" D_UPLOAD_STARTED " ...</b></div>";
|
||||
"<div id='f2' style='display:none;text-align:center;'><b>" D_UPLOAD_STARTED "...</b></div>";
|
||||
|
||||
// upload via factory partition
|
||||
const char HTTP_FORM_RST_UPG_FCT[] PROGMEM =
|
||||
"<form method='post' action='u2' enctype='multipart/form-data'>"
|
||||
"<br><input type='file' name='u2'><br>"
|
||||
"<br><button type='submit' onclick='eb(\"f1\").style.display=\"none\";eb(\"f3\").style.display=\"block\";return upl(this);'>" D_START " %s</button></form>"
|
||||
"</fieldset>"
|
||||
"</div>"
|
||||
"<div id='f3' style='display:none;text-align:center;'><b>" D_UPLOAD_FACTORY "...</b></div>"
|
||||
"<div id='f2' style='display:none;text-align:center;'><b>" D_UPLOAD_STARTED "...</b></div>";
|
||||
|
||||
const char HTTP_FORM_CMND[] PROGMEM =
|
||||
"<br><textarea readonly id='t1' cols='340' wrap='off'></textarea><br><br>"
|
||||
|
@ -523,6 +539,9 @@ const WebServerDispatch_t WebServerDispatch[] PROGMEM = {
|
|||
{ "u1", HTTP_ANY, HandleUpgradeFirmwareStart }, // OTA
|
||||
{ "u2", HTTP_OPTIONS, HandlePreflightRequest },
|
||||
{ "u3", HTTP_ANY, HandleUploadDone },
|
||||
#ifdef ESP32
|
||||
{ "u4", HTTP_GET, HandleSwitchFactory },
|
||||
#endif // ESP32
|
||||
{ "mn", HTTP_GET, HandleManagement },
|
||||
{ "cs", HTTP_GET, HandleConsole },
|
||||
{ "cs", HTTP_OPTIONS, HandlePreflightRequest },
|
||||
|
@ -841,7 +860,11 @@ void WSContentSendStyle_P(const char* formatP, ...) {
|
|||
WSContentSend_P(HTTP_SCRIPT_COUNTER);
|
||||
}
|
||||
}
|
||||
#ifdef ESP32
|
||||
WSContentSend_P(HTTP_HEAD_LAST_SCRIPT32);
|
||||
#else
|
||||
WSContentSend_P(HTTP_HEAD_LAST_SCRIPT);
|
||||
#endif
|
||||
|
||||
WSContentSend_P(HTTP_HEAD_STYLE1, WebColor(COL_FORM), WebColor(COL_INPUT), WebColor(COL_INPUT_TEXT), WebColor(COL_INPUT),
|
||||
WebColor(COL_INPUT_TEXT), WebColor(COL_CONSOLE), WebColor(COL_CONSOLE_TEXT), WebColor(COL_BACKGROUND));
|
||||
|
@ -860,7 +883,11 @@ void WSContentSendStyle_P(const char* formatP, ...) {
|
|||
}
|
||||
WSContentSend_P(HTTP_HEAD_STYLE3, WebColor(COL_TEXT),
|
||||
#ifdef FIRMWARE_MINIMAL
|
||||
#ifdef FIRMWARE_SAFEMODE
|
||||
WebColor(COL_TEXT_SUCCESS),
|
||||
#else
|
||||
WebColor(COL_TEXT_WARNING),
|
||||
#endif
|
||||
#endif
|
||||
WebColor(COL_TITLE),
|
||||
(Web.initial_config) ? "" : ModuleName().c_str(), SettingsText(SET_DEVICENAME));
|
||||
|
@ -2283,7 +2310,15 @@ void HandleRestoreConfiguration(void)
|
|||
WSContentStart_P(PSTR(D_RESTORE_CONFIGURATION));
|
||||
WSContentSendStyle();
|
||||
WSContentSend_P(HTTP_FORM_RST);
|
||||
#ifdef ESP32
|
||||
if (EspSingleOtaPartition() && !EspRunningFactoryPartition()) {
|
||||
WSContentSend_P(HTTP_FORM_RST_UPG_FCT, PSTR(D_RESTORE));
|
||||
} else {
|
||||
WSContentSend_P(HTTP_FORM_RST_UPG, PSTR(D_RESTORE));
|
||||
}
|
||||
#else
|
||||
WSContentSend_P(HTTP_FORM_RST_UPG, PSTR(D_RESTORE));
|
||||
#endif
|
||||
if (WifiIsInManagerMode()) {
|
||||
WSContentSpaceButton(BUTTON_MAIN);
|
||||
} else {
|
||||
|
@ -2508,7 +2543,15 @@ void HandleUpgradeFirmware(void) {
|
|||
WSContentStart_P(PSTR(D_FIRMWARE_UPGRADE));
|
||||
WSContentSendStyle();
|
||||
WSContentSend_P(HTTP_FORM_UPG, SettingsText(SET_OTAURL));
|
||||
#ifdef ESP32
|
||||
if (EspSingleOtaPartition() && !EspRunningFactoryPartition()) {
|
||||
WSContentSend_P(HTTP_FORM_RST_UPG_FCT, PSTR(D_UPGRADE));
|
||||
} else {
|
||||
WSContentSend_P(HTTP_FORM_RST_UPG, PSTR(D_UPGRADE));
|
||||
}
|
||||
#else
|
||||
WSContentSend_P(HTTP_FORM_RST_UPG, PSTR(D_UPGRADE));
|
||||
#endif
|
||||
WSContentSpaceButton(BUTTON_MAIN);
|
||||
WSContentStop();
|
||||
|
||||
|
@ -2884,6 +2927,80 @@ void HandlePreflightRequest(void)
|
|||
|
||||
/*-------------------------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef ESP32
|
||||
// Check if we are in single-mode OTA, if so restart to factory mode
|
||||
//
|
||||
// Parameter `u4` is either `fct` or `ota` to switch to factory or ota
|
||||
//
|
||||
// The page can return the followinf (code 200)
|
||||
// `false`: the current partition is not the target, but a restart to factory is triggered (polling required)
|
||||
// `true`: the current partition is the one required
|
||||
// `none`: there is no factory partition
|
||||
|
||||
// return a simple status page as text/plain code 200
|
||||
static void WSReturnSimpleString(const char *msg) {
|
||||
if (nullptr == msg) { msg = ""; }
|
||||
Webserver->client().flush();
|
||||
WSHeaderSend();
|
||||
Webserver->send(200, "text/plain", msg);
|
||||
}
|
||||
|
||||
void HandleSwitchFactory(void)
|
||||
{
|
||||
if (!HttpCheckPriviledgedAccess()) { return; }
|
||||
|
||||
char tmp1[8];
|
||||
WebGetArg(PSTR("u4"), tmp1, sizeof(tmp1));
|
||||
|
||||
bool switch_factory = false; // trigger a restart to factory partition?
|
||||
bool switch_ota = false; // switch back to OTA partition
|
||||
bool single_ota = false;
|
||||
bool api_mode = Webserver->hasArg("api"); // api-mode, returns `true`, `false` or `none`
|
||||
|
||||
// switch to factory ?
|
||||
if (EspSingleOtaPartition()) {
|
||||
single_ota = true;
|
||||
if (strcmp("fct", tmp1) == 0 && !EspRunningFactoryPartition()) {
|
||||
switch_factory = true;
|
||||
}
|
||||
// switch to OTA
|
||||
else if (strcmp("ota", tmp1) == 0 && EspRunningFactoryPartition()) {
|
||||
switch_ota = true;
|
||||
}
|
||||
}
|
||||
|
||||
// apply the change in flash and return result
|
||||
if (switch_factory || switch_ota) {
|
||||
SettingsSaveAll();
|
||||
if (switch_factory) {
|
||||
EspPrepRestartToSafeMode();
|
||||
} else {
|
||||
const esp_partition_t* partition = esp_ota_get_next_update_partition(nullptr);
|
||||
esp_ota_set_boot_partition(partition);
|
||||
}
|
||||
|
||||
if (api_mode) {
|
||||
WSReturnSimpleString("false");
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR(D_LOG_HTTP D_RESTART));
|
||||
EspRestart();
|
||||
} else {
|
||||
WebRestart(0);
|
||||
}
|
||||
} else {
|
||||
if (api_mode) {
|
||||
// return `none` or `true`
|
||||
WSReturnSimpleString(EspSingleOtaPartition() ? "true" : "none");
|
||||
} else {
|
||||
Webserver->sendHeader("Location", "/", true);
|
||||
Webserver->send(302, "text/plain", "");
|
||||
}
|
||||
}
|
||||
Web.upload_file_type = UPL_TASMOTA;
|
||||
}
|
||||
#endif // ESP32
|
||||
|
||||
/*-------------------------------------------------------------------------------------------*/
|
||||
|
||||
void HandleHttpCommand(void)
|
||||
{
|
||||
if (!HttpCheckPriviledgedAccess(false)) { return; }
|
||||
|
|
|
@ -70,20 +70,20 @@ extern "C" {
|
|||
int32_t l_publish(struct bvm *vm) {
|
||||
return be_mqtt_publish(vm, true);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t be_mqtt_publish(struct bvm *vm) {
|
||||
int32_t be_mqtt_publish(struct bvm *vm) {
|
||||
return be_mqtt_publish(vm, false);
|
||||
}
|
||||
}
|
||||
|
||||
void be_mqtt_subscribe(const char* topic) {
|
||||
void be_mqtt_subscribe(const char* topic) {
|
||||
if (!topic) { return; }
|
||||
MqttSubscribe(topic);
|
||||
}
|
||||
}
|
||||
|
||||
void be_mqtt_unsubscribe(const char* topic) {
|
||||
void be_mqtt_unsubscribe(const char* topic) {
|
||||
if (!topic) { return; }
|
||||
MqttUnsubscribe(topic);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // USE_BERRY
|
||||
|
|
|
@ -381,7 +381,7 @@ extern "C" {
|
|||
if (top == 2 && be_isstring(vm, 2)) {
|
||||
const char *msg = be_tostring(vm, 2);
|
||||
strlcpy(XdrvMailbox.command, msg, CMDSZ);
|
||||
be_return_nil(vm); // Return nil when something goes wrong
|
||||
be_return_nil(vm);
|
||||
}
|
||||
be_raise(vm, kTypeError, nullptr);
|
||||
}
|
||||
|
@ -394,7 +394,7 @@ extern "C" {
|
|||
const char *msg = be_tostring(vm, 2);
|
||||
be_pop(vm, top); // avoid Error be_top is non zero message
|
||||
ResponseAppend_P(PSTR("%s"), msg);
|
||||
be_return_nil(vm); // Return nil when something goes wrong
|
||||
be_return_nil(vm);
|
||||
}
|
||||
be_raise(vm, kTypeError, nullptr);
|
||||
}
|
||||
|
|
|
@ -75,6 +75,10 @@ const char berry_prog[] =
|
|||
|
||||
"import tapp "
|
||||
|
||||
#ifdef USE_BERRY_DEBUG
|
||||
"import debug "
|
||||
"import solidify "
|
||||
#endif
|
||||
;
|
||||
|
||||
#endif // USE_BERRY
|
||||
|
|
|
@ -108,12 +108,14 @@ extern "C" {
|
|||
|
||||
// If event == nullptr, then take XdrvMailbox.data
|
||||
bool callBerryRule(const char *event, bool teleperiod) {
|
||||
if (berry.rules_busy) { return false; }
|
||||
bool save_rules_busy = berry.rules_busy;
|
||||
bool exec_rule = !save_rules_busy; // true if the rule is executed, false if we only record the value
|
||||
// if (berry.rules_busy) { return false; }
|
||||
berry.rules_busy = true;
|
||||
char * json_event = XdrvMailbox.data;
|
||||
bool serviced = false;
|
||||
serviced = callBerryEventDispatcher(teleperiod ? "tele" : "rule", nullptr, 0, event ? event : XdrvMailbox.data);
|
||||
berry.rules_busy = false;
|
||||
serviced = callBerryEventDispatcher(teleperiod ? "tele" : "rule", nullptr, exec_rule, event ? event : XdrvMailbox.data);
|
||||
berry.rules_busy = save_rules_busy;
|
||||
return serviced; // TODO event not handled
|
||||
}
|
||||
|
||||
|
|
|
@ -39,8 +39,7 @@
|
|||
* IfxToken - Set Influxdb v2 and token
|
||||
* IfxPeriod - Set Influxdb period. If not set (or 0), use Teleperiod
|
||||
* IfxSensor - Set Influxdb sensor logging off (0) or on (1)
|
||||
*
|
||||
* Set influxdb update interval with command teleperiod
|
||||
* IfxRP - Set Influxdb retention policy
|
||||
*
|
||||
* The following triggers result in automatic influxdb numeric feeds without appended time:
|
||||
* - this driver initiated state message
|
||||
|
@ -73,6 +72,9 @@
|
|||
#ifndef INFLUXDB_BUCKET
|
||||
#define INFLUXDB_BUCKET "db" // [IfxDatabase, IfxBucket] Influxdb v1 database or v2 bucket
|
||||
#endif
|
||||
#ifndef INFLUXDB_RP
|
||||
#define INFLUXDB_RP "" // [IfxRP] Influxdb v1 retention policy (blank is default, usually autogen infinite)
|
||||
#endif
|
||||
|
||||
static const char UninitializedMessage[] PROGMEM = "Unconfigured instance";
|
||||
// This cannot be put to PROGMEM due to the way how it is used
|
||||
|
@ -132,6 +134,10 @@ bool InfluxDbParameterInit(void) {
|
|||
IFDB._writeUrl += "/write?db=";
|
||||
IFDB._writeUrl += UrlEncode(SettingsText(SET_INFLUXDB_BUCKET));
|
||||
IFDB._writeUrl += InfluxDbAuth();
|
||||
if (strlen(SettingsText(SET_INFLUXDB_RP)) != 0) {
|
||||
IFDB._writeUrl += "&rp=";
|
||||
IFDB._writeUrl += UrlEncode(SettingsText(SET_INFLUXDB_RP));
|
||||
}
|
||||
}
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("IFX: Url %s"), IFDB._writeUrl.c_str());
|
||||
|
||||
|
@ -427,6 +433,7 @@ void InfluxDbLoop(void) {
|
|||
#define D_CMND_INFLUXDBBUCKET "Bucket"
|
||||
#define D_CMND_INFLUXDBPERIOD "Period"
|
||||
#define D_CMND_INFLUXDBSENSOR "Sensor"
|
||||
#define D_CMND_INFLUXDBRP "RP"
|
||||
|
||||
const char kInfluxDbCommands[] PROGMEM = D_PRFX_INFLUXDB "|" // Prefix
|
||||
"|" D_CMND_INFLUXDBLOG "|"
|
||||
|
@ -434,7 +441,7 @@ const char kInfluxDbCommands[] PROGMEM = D_PRFX_INFLUXDB "|" // Prefix
|
|||
D_CMND_INFLUXDBUSER "|" D_CMND_INFLUXDBORG "|"
|
||||
D_CMND_INFLUXDBPASSWORD "|" D_CMND_INFLUXDBTOKEN "|"
|
||||
D_CMND_INFLUXDBDATABASE "|" D_CMND_INFLUXDBBUCKET "|"
|
||||
D_CMND_INFLUXDBPERIOD "|" D_CMND_INFLUXDBSENSOR;
|
||||
D_CMND_INFLUXDBPERIOD "|" D_CMND_INFLUXDBSENSOR "|" D_CMND_INFLUXDBRP;
|
||||
|
||||
void (* const InfluxCommand[])(void) PROGMEM = {
|
||||
&CmndInfluxDbState, &CmndInfluxDbLog,
|
||||
|
@ -442,7 +449,7 @@ void (* const InfluxCommand[])(void) PROGMEM = {
|
|||
&CmndInfluxDbUser, &CmndInfluxDbUser,
|
||||
&CmndInfluxDbPassword, &CmndInfluxDbPassword,
|
||||
&CmndInfluxDbDatabase, &CmndInfluxDbDatabase,
|
||||
&CmndInfluxDbPeriod, &CmndInfluxDbSensor };
|
||||
&CmndInfluxDbPeriod, &CmndInfluxDbSensor, &CmndInfluxDbRP };
|
||||
|
||||
void InfluxDbReinit(void) {
|
||||
IFDB.init = false;
|
||||
|
@ -532,6 +539,14 @@ void CmndInfluxDbDatabase(void) {
|
|||
ResponseCmndChar(SettingsText(SET_INFLUXDB_BUCKET));
|
||||
}
|
||||
|
||||
void CmndInfluxDbRP(void) {
|
||||
if (XdrvMailbox.data_len > 0) {
|
||||
SettingsUpdateText(SET_INFLUXDB_RP, (SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? PSTR(INFLUXDB_RP) : XdrvMailbox.data);
|
||||
InfluxDbReinit();
|
||||
}
|
||||
ResponseCmndChar(SettingsText(SET_INFLUXDB_RP));
|
||||
}
|
||||
|
||||
void CmndInfluxDbPeriod(void) {
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload < 3601)) {
|
||||
Settings->influxdb_period = XdrvMailbox.payload;
|
||||
|
@ -559,6 +574,7 @@ bool Xdrv59(uint8_t function) {
|
|||
SettingsUpdateText(SET_INFLUXDB_ORG, PSTR(INFLUXDB_ORG));
|
||||
SettingsUpdateText(SET_INFLUXDB_TOKEN, PSTR(INFLUXDB_TOKEN));
|
||||
SettingsUpdateText(SET_INFLUXDB_BUCKET, PSTR(INFLUXDB_BUCKET));
|
||||
SettingsUpdateText(SET_INFLUXDB_RP, PSTR(INFLUXDB_RP));
|
||||
Settings->sbflag1.influxdb_default = 1;
|
||||
}
|
||||
} else if (FUNC_COMMAND == function) {
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
#define SOLAXX1_SPEED 9600 // default solax rs485 speed
|
||||
#endif
|
||||
|
||||
#define SOLAXX1_READCONFIG // enable to read inverters config; disable to save codespace (3k1)
|
||||
|
||||
#define INVERTER_ADDRESS 0x0A
|
||||
|
||||
#define D_SOLAX_X1 "SolaxX1"
|
||||
|
@ -44,10 +46,12 @@ const char kSolaxError[] PROGMEM =
|
|||
D_SOLAX_ERROR_0 "|" D_SOLAX_ERROR_1 "|" D_SOLAX_ERROR_2 "|" D_SOLAX_ERROR_3 "|" D_SOLAX_ERROR_4 "|" D_SOLAX_ERROR_5 "|"
|
||||
D_SOLAX_ERROR_6 "|" D_SOLAX_ERROR_7 "|" D_SOLAX_ERROR_8;
|
||||
|
||||
#ifdef SOLAXX1_READCONFIG
|
||||
const char kSolaxSafetyType[] PROGMEM =
|
||||
"VDE0126|ARN4105|AS4777_AU|G98/1|C10/11|OVE/ONORME8001|EN50438_NL|EN50438_DK|CEB|CEI021|NRS097_2_1|"
|
||||
"VDE0126_Gr_Is|UTE_C15_712|IEC61727|G99/1|VDE0126_Gr_Co|France_VFR2014|C15_712_is_50|C15_712_is_60|"
|
||||
"AS4777_NZ|RD1699|Chile|EN50438_Ireland|Philippines|Czech_PPDS|Czech_50438";
|
||||
#endif // SOLAXX1_READCONFIG
|
||||
|
||||
union {
|
||||
uint32_t ErrMessage;
|
||||
|
@ -333,11 +337,12 @@ void solaxX1_250MSecond(void) // Every 250 milliseconds
|
|||
return;
|
||||
} // end received "Response for query (ID data)"
|
||||
|
||||
#ifdef SOLAXX1_READCONFIG
|
||||
if (DataRead[6] == 0x11 && DataRead[7] == 0x84) { // received "Response for query (config data)"
|
||||
if (solaxX1_global.Command_QueryConfig) {
|
||||
// This values are displayed as they were received from the inverter. They are not interpreted in any way.
|
||||
TempFloat = ((DataRead[9] << 8) | DataRead[10]) * 0.1f;
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("SX1: new wVpvStart: %1_f V (Inverter launch voltage threshold)"), &TempFloat);
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("SX1: wVpvStart: %1_f V (Inverter launch voltage threshold)"), &TempFloat);
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("SX1: wTimeStart: %d sec (launch wait time)"), (DataRead[11] << 8) | DataRead[12]);
|
||||
TempFloat = ((DataRead[13] << 8) | DataRead[14]) * 0.1f;
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("SX1: wVacMinProtect: %1_f V (allowed minimum grid voltage)"), &TempFloat);
|
||||
|
@ -400,6 +405,7 @@ void solaxX1_250MSecond(void) // Every 250 milliseconds
|
|||
DEBUG_SENSOR_LOG(PSTR("SX1: received config data"));
|
||||
return;
|
||||
} // end received "Response for query (config data)"
|
||||
#endif // SOLAXX1_READCONFIG
|
||||
|
||||
if (DataRead[6] == 0x10 && DataRead[7] == 0x80) { // received "register request"
|
||||
solaxX1_global.QueryData_count = 5; // give time for next query
|
||||
|
@ -489,9 +495,14 @@ bool SolaxX1_cmd(void)
|
|||
AddLog(LOG_LEVEL_INFO, PSTR("SX1: ReadIDinfo sent..."));
|
||||
return true;
|
||||
} else if (!strcasecmp(XdrvMailbox.data, "ReadConfig")) {
|
||||
#ifdef SOLAXX1_READCONFIG
|
||||
solaxX1_global.Command_QueryConfig = true;
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("SX1: ReadConfig sent..."));
|
||||
return true;
|
||||
#else
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("SX1: Command not available. Please set compiler directive '#define SOLAXX1_READCONFIG'."));
|
||||
return false;
|
||||
#endif // SOLAXX1_READCONFIG
|
||||
}
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("SX1: Unknown command: \"%s\""),XdrvMailbox.data);
|
||||
return false;
|
||||
|
@ -510,7 +521,7 @@ const char HTTP_SNS_solaxX1_DATA2[] PROGMEM =
|
|||
"{s}" D_SOLAX_X1 " " D_PV2_POWER "{m}%s " D_UNIT_WATT "{e}";
|
||||
#endif
|
||||
const char HTTP_SNS_solaxX1_DATA3[] PROGMEM =
|
||||
"{s}" D_SOLAX_X1 " " D_UPTIME "{m}%s " D_UNIT_HOUR "{e}"
|
||||
"{s}" D_SOLAX_X1 " " D_UPTIME "{m}%d " D_UNIT_HOUR "{e}"
|
||||
"{s}" D_SOLAX_X1 " " D_STATUS "{m}%s"
|
||||
"{s}" D_SOLAX_X1 " " D_ERROR "{m}%s"
|
||||
"{s}" D_SOLAX_X1 " Inverter SN{m}%s";
|
||||
|
@ -534,8 +545,6 @@ void solaxX1_Show(bool json)
|
|||
char pv2_power[33];
|
||||
dtostrfd(solaxX1.dc2_power, Settings->flag2.wattage_resolution, pv2_power);
|
||||
#endif
|
||||
char runtime[33];
|
||||
dtostrfd(solaxX1.runtime_total, 0, runtime);
|
||||
char status[33];
|
||||
GetTextIndexed(status, sizeof(status), solaxX1.runMode + 1, kSolaxMode);
|
||||
|
||||
|
@ -546,8 +555,8 @@ void solaxX1_Show(bool json)
|
|||
ResponseAppend_P(PSTR(",\"" D_JSON_PV2_VOLTAGE "\":%s,\"" D_JSON_PV2_CURRENT "\":%s,\"" D_JSON_PV2_POWER "\":%s"),
|
||||
pv2_voltage, pv2_current, pv2_power);
|
||||
#endif
|
||||
ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%d,\"" D_JSON_RUNTIME "\":%s,\"" D_JSON_STATUS "\":\"%s\",\"" D_JSON_ERROR "\":%d"),
|
||||
solaxX1.temperature, runtime, status, solaxX1.errorCode);
|
||||
ResponseAppend_P(PSTR(",\"" D_JSON_TEMPERATURE "\":%d,\"" D_JSON_RUNTIME "\":%d,\"" D_JSON_STATUS "\":\"%s\",\"" D_JSON_ERROR "\":%d"),
|
||||
solaxX1.temperature, solaxX1.runtime_total, status, solaxX1.errorCode);
|
||||
|
||||
#ifdef USE_DOMOTICZ
|
||||
// Avoid bad temperature report at beginning of the day (spikes of 1200 celsius degrees)
|
||||
|
@ -562,7 +571,7 @@ void solaxX1_Show(bool json)
|
|||
#endif
|
||||
WSContentSend_Temp(D_SOLAX_X1, solaxX1.temperature);
|
||||
char errorCodeString[33];
|
||||
WSContentSend_PD(HTTP_SNS_solaxX1_DATA3, runtime, status,
|
||||
WSContentSend_PD(HTTP_SNS_solaxX1_DATA3, solaxX1.runtime_total, status,
|
||||
GetTextIndexed(errorCodeString, sizeof(errorCodeString), solaxX1_ParseErrorCode(solaxX1.errorCode), kSolaxError),
|
||||
solaxX1.SerialNumber);
|
||||
#endif // USE_WEBSERVER
|
||||
|
|
|
@ -0,0 +1,268 @@
|
|||
/*
|
||||
xsns_96_flowratemeter.ino - flowratemeter support for Tasmota
|
||||
- up to two flowratemeter YF-DN50 and similary
|
||||
- flow rate frequencies f = 1 Hz up to 5 kHz
|
||||
- uses the FreqRes resolution
|
||||
|
||||
Copyright (C) 2022 Norbert Richter
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_FLOWRATEMETER
|
||||
|
||||
#define XSNS_96 96
|
||||
|
||||
|
||||
|
||||
#define FLOWRATEMETER_WEIGHT_AVG_SAMPLE 20 // number of samples for smooth weigted average
|
||||
#define FLOWRATEMETER_MIN_FREQ 1 // Hz
|
||||
|
||||
#define D_JSON_FLOWRATEMETER_RATE "Rate"
|
||||
#define D_JSON_FLOWRATEMETER_VALUE "Value"
|
||||
#define D_JSON_FLOWRATEMETER_UNIT "Unit"
|
||||
#define D_JSON_FLOWRATEMETER_VALUE_AVG "average"
|
||||
#define D_JSON_FLOWRATEMETER_VALUE_RAW "raw"
|
||||
|
||||
|
||||
|
||||
#ifdef USE_WEBSERVER
|
||||
const char HTTP_SNS_FLOWRATEMETER[] PROGMEM =
|
||||
"{s}" D_FLOWRATEMETER_NAME "-%d{m}%*_f %s{e}"
|
||||
;
|
||||
#endif // USE_WEBSERVER
|
||||
|
||||
|
||||
int32_t flowratemeter_period[MAX_FLOWRATEMETER] = {0};
|
||||
float flowratemeter_period_avg[MAX_FLOWRATEMETER] = {0};
|
||||
uint32_t flowratemeter_count[MAX_FLOWRATEMETER] = {0};
|
||||
volatile uint32_t flowratemeter_last_irq[MAX_FLOWRATEMETER] = {0};
|
||||
|
||||
bool flowratemeter_valuesread = false;
|
||||
bool flowratemeter_raw_value = false;
|
||||
|
||||
|
||||
|
||||
void IRAM_ATTR FlowRateMeterIR(uint16_t irq)
|
||||
{
|
||||
uint32_t time = micros();
|
||||
#if defined(ESP8266)
|
||||
uint32_t gpio_status = GPIO_REG_READ(GPIO_STATUS_ADDRESS);
|
||||
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, gpio_status);
|
||||
#endif
|
||||
if (irq < MAX_FLOWRATEMETER) {
|
||||
if ((time - flowratemeter_last_irq[irq]) < (1000000 / FLOWRATEMETER_MIN_FREQ)) {
|
||||
flowratemeter_period[irq] = time - flowratemeter_last_irq[irq];
|
||||
} else {
|
||||
flowratemeter_period[irq] = 0;
|
||||
}
|
||||
flowratemeter_valuesread = true;
|
||||
flowratemeter_last_irq[irq] = time;
|
||||
}
|
||||
}
|
||||
// GPIO_STATUS is always 0 (?), so can only determine the IR source using this way
|
||||
void IRAM_ATTR FlowRateMeter1IR(void)
|
||||
{
|
||||
FlowRateMeterIR(0);
|
||||
}
|
||||
void IRAM_ATTR FlowRateMeter2IR(void)
|
||||
{
|
||||
FlowRateMeterIR(1);
|
||||
}
|
||||
|
||||
void FlowRateMeterRead(void)
|
||||
{
|
||||
for (uint32_t i = 0; i < MAX_FLOWRATEMETER; i++) {
|
||||
if ((micros() - flowratemeter_last_irq[i]) >= (1000000 / FLOWRATEMETER_MIN_FREQ)) {
|
||||
flowratemeter_period[i] = 0;
|
||||
flowratemeter_period_avg[i] = 0;
|
||||
}
|
||||
|
||||
// exponentially weighted average
|
||||
if (flowratemeter_count[i] <= FLOWRATEMETER_WEIGHT_AVG_SAMPLE) {
|
||||
flowratemeter_count[i]++;
|
||||
}
|
||||
flowratemeter_period_avg[i] -= flowratemeter_period_avg[i] / flowratemeter_count[i];
|
||||
flowratemeter_period_avg[i] += float(flowratemeter_period[i]) / flowratemeter_count[i];
|
||||
}
|
||||
}
|
||||
|
||||
void FlowRateMeterInit(void)
|
||||
{
|
||||
void (* irq_service[MAX_FLOWRATEMETER])(void)= {FlowRateMeter1IR, FlowRateMeter2IR};
|
||||
|
||||
flowratemeter_valuesread = false;
|
||||
for (uint32_t i = 0; i < MAX_FLOWRATEMETER; i++) {
|
||||
pinMode(Pin(GPIO_FLOWRATEMETER_IN, i), INPUT);
|
||||
attachInterrupt(Pin(GPIO_FLOWRATEMETER_IN, i), irq_service[i], RISING);
|
||||
}
|
||||
}
|
||||
|
||||
void FlowRateMeterShow(bool json)
|
||||
{
|
||||
if (json) {
|
||||
ResponseAppend_P(PSTR(",\"" D_FLOWRATEMETER_NAME "\":{\"" D_JSON_FLOWRATEMETER_RATE "\":["));
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < MAX_FLOWRATEMETER; i++) {
|
||||
float flowratemeter_rate_avg_float = 0;
|
||||
|
||||
if (flowratemeter_period[i]) {
|
||||
flowratemeter_rate_avg_float =
|
||||
((Settings->SensorBits1.flowratemeter_unit ? (1000000.0 / 1000.0) : (1000000 / 60.0)) / 2.0)
|
||||
/ (flowratemeter_raw_value ? flowratemeter_period[i] : flowratemeter_period_avg[i])
|
||||
* (Settings->flowratemeter_calibration[i] ? (float)Settings->flowratemeter_calibration[i] : 1000.0);
|
||||
}
|
||||
|
||||
if (PinUsed(GPIO_FLOWRATEMETER_IN, i)) {
|
||||
if (json) {
|
||||
ResponseAppend_P(PSTR("%s%*_f"),
|
||||
i ? PSTR(",") : PSTR(""),
|
||||
Settings->flag2.frequency_resolution, &flowratemeter_rate_avg_float
|
||||
);
|
||||
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
WSContentSend_PD(HTTP_SNS_FLOWRATEMETER,
|
||||
i+1,
|
||||
Settings->flag2.frequency_resolution, &flowratemeter_rate_avg_float,
|
||||
Settings->SensorBits1.flowratemeter_unit ? D_UNIT_CUBICMETER_PER_HOUR : D_UNIT_LITER_PER_MINUTE
|
||||
);
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
}
|
||||
if (json) {
|
||||
ResponseAppend_P(PSTR("],\"" D_JSON_FLOWRATEMETER_VALUE "\":\"%s\""),
|
||||
flowratemeter_raw_value ? PSTR(D_JSON_FLOWRATEMETER_VALUE_RAW) : PSTR(D_JSON_FLOWRATEMETER_VALUE_AVG)
|
||||
);
|
||||
ResponseAppend_P(PSTR(",\"" D_JSON_FLOWRATEMETER_UNIT "\":\"%s\"}"),
|
||||
Settings->SensorBits1.flowratemeter_unit ? PSTR(D_UNIT_CUBICMETER_PER_HOUR) : PSTR(D_UNIT_LITER_PER_MINUTE)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Supported commands for Sensor96:
|
||||
*
|
||||
* Sensor96 - Show current settings
|
||||
* Sensor96 0 0|1 - Show flow value in l/min (0) or m³/h (1)
|
||||
* Sensor96 1 <correction-factor> - Set sensor 1 factor (x 1000) - to set to 0.2 enter 'Sensor96 1 200'
|
||||
* Sensor96 2 <correction-factor> - Set sensor 2 factor (x 1000)
|
||||
* Sensor96 9 0|1 - Value mode: Switch between displaying avg(0) / raw(1) readings (not permanently)
|
||||
*
|
||||
* Flowmeter calibration:
|
||||
* - get the current displayed flow rate (D)
|
||||
* - get the current <correction-factor> (c)
|
||||
* - measure the real flow rate (M)
|
||||
* - new <correction-factor> = M / (c * D)
|
||||
*
|
||||
* Example:
|
||||
* - displayed flow rate = 254.39 l/min (D)
|
||||
* - current <correction-factor> = 1.0 (c)
|
||||
* - real flow rate = 83.42 l/min (M)
|
||||
*
|
||||
* new <correction-factor> = M / (c * D) = 83.42 / (1 * 254.39) = 0.328
|
||||
* Cmd: Sensor96 x 328
|
||||
\*********************************************************************************************/
|
||||
bool FlowRateMeterCommand(void) {
|
||||
bool show_parms = true;
|
||||
char argument[XdrvMailbox.data_len];
|
||||
|
||||
long value = 0;
|
||||
for (uint32_t ca = 0; ca < XdrvMailbox.data_len; ca++) {
|
||||
if ((' ' == XdrvMailbox.data[ca]) || ('=' == XdrvMailbox.data[ca])) { XdrvMailbox.data[ca] = ','; }
|
||||
}
|
||||
bool any_value = (strchr(XdrvMailbox.data, ',') != nullptr);
|
||||
if (any_value) {
|
||||
value = strtol(ArgV(argument, 2), nullptr, 10);
|
||||
}
|
||||
|
||||
switch (XdrvMailbox.payload) {
|
||||
case 0: // Unit
|
||||
if (any_value) {
|
||||
Settings->SensorBits1.flowratemeter_unit = value & 1;
|
||||
ResponseCmndNumber(value & 1);
|
||||
show_parms = false;
|
||||
}
|
||||
break;
|
||||
case 1: // Sensor calibration value
|
||||
case 2:
|
||||
if (any_value) {
|
||||
Settings->flowratemeter_calibration[XdrvMailbox.payload - 1] = value;
|
||||
ResponseCmndNumber(value);
|
||||
show_parms = false;
|
||||
}
|
||||
break;
|
||||
case 9: // avg/raw values
|
||||
if (any_value) {
|
||||
flowratemeter_raw_value = value & 1;
|
||||
ResponseCmndNumber(value & 1);
|
||||
show_parms = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (show_parms) {
|
||||
Response_P(PSTR("{\"Sensor%d\":{\"" D_JSON_POWERFACTOR "\":["), XSNS_96);
|
||||
for (uint32_t i = 0; i < MAX_FLOWRATEMETER; i++) {
|
||||
float flowratemeter_factor = Settings->flowratemeter_calibration[i] ? (float)Settings->flowratemeter_calibration[i] / 1000 : 1;
|
||||
ResponseAppend_P(PSTR("%s%3_f"), i ? PSTR(",") : PSTR(""), &flowratemeter_factor);
|
||||
}
|
||||
ResponseAppend_P(PSTR("],\"" D_JSON_FLOWRATEMETER_VALUE "\":\"%s\""),
|
||||
flowratemeter_raw_value ? PSTR(D_JSON_FLOWRATEMETER_VALUE_RAW) : PSTR(D_JSON_FLOWRATEMETER_VALUE_AVG)
|
||||
);
|
||||
ResponseAppend_P(PSTR(",\"" D_JSON_FLOWRATEMETER_UNIT "\":\"%s\"}}"),
|
||||
Settings->SensorBits1.flowratemeter_unit ? PSTR(D_UNIT_CUBICMETER_PER_HOUR) : PSTR(D_UNIT_LITER_PER_MINUTE)
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
bool Xsns96(uint8_t function)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if (PinUsed(GPIO_FLOWRATEMETER_IN, GPIO_ANY)) {
|
||||
switch (function) {
|
||||
case FUNC_INIT:
|
||||
FlowRateMeterInit();
|
||||
break;
|
||||
case FUNC_EVERY_250_MSECOND:
|
||||
FlowRateMeterRead();
|
||||
break;
|
||||
case FUNC_COMMAND_SENSOR:
|
||||
if (XSNS_96 == XdrvMailbox.index) {
|
||||
result = FlowRateMeterCommand();
|
||||
}
|
||||
break;
|
||||
case FUNC_JSON_APPEND:
|
||||
FlowRateMeterShow(true);
|
||||
break;
|
||||
#ifdef USE_WEBSERVER
|
||||
case FUNC_WEB_SENSOR:
|
||||
FlowRateMeterShow(false);
|
||||
break;
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_FLOWRATEMETER
|
|
@ -298,5 +298,14 @@ BL6523_TX = GPIO_BL6523_TX
|
|||
BL6523_RX = GPIO_BL6523_RX
|
||||
ADE7880_IRQ = GPIO_ADE7880_IRQ
|
||||
RESET = GPIO_RESET
|
||||
MS01 = GPIO_MS01
|
||||
SDIO_CMD = GPIO_SDIO_CMD
|
||||
SDIO_CLK = GPIO_SDIO_CLK
|
||||
SDIO_D0 = GPIO_SDIO_D0
|
||||
SDIO_D1 = GPIO_SDIO_D1
|
||||
SDIO_D2 = GPIO_SDIO_D2
|
||||
SDIO_D3 = GPIO_SDIO_D3
|
||||
|
||||
FLOWRATEMETER_SIGNAL = GPIO_FLOWRATEMETER_IN
|
||||
|
||||
SENSOR_END = GPIO_SENSOR_END
|
||||
|
|
Loading…
Reference in New Issue