Compare commits

..

139 Commits

Author SHA1 Message Date
Theo Arends
015fa1da89 Add command JsonPP <command>|backlog <command>;... to enable JSON PP only once 2025-04-19 16:56:15 +02:00
Theo Arends
a11e269ca0 Fix Xmodem send over serial 2025-04-19 12:54:53 +02:00
Theo Arends
2831bbfd18 Update changelogs 2025-04-18 10:36:42 +02:00
bovirus
92b3f7d37c
Italian language update (#23309) 2025-04-18 10:26:10 +02:00
s-hadinger
a2d1915692
Base64 split implementation in separate file (#23313) 2025-04-17 22:38:04 +02:00
s-hadinger
082170374c
Berry string literals containing NULL are truncated (#23312) 2025-04-17 22:12:35 +02:00
s-hadinger
c2628c95f3
Berry 'bytes().asstring()' now truncates a string if buffer contains NULL (#23311) 2025-04-17 21:51:03 +02:00
Theo Arends
2bc5f682b0 Add command JsonPP 0..7 to enable (>0) JSON Pretty Print on user interfaces and set number of indents 2025-04-17 15:55:05 +02:00
Theo Arends
cea46bb660 Bump version v14.6.0.1 2025-04-16 14:02:56 +02:00
Theo Arends
b67231483a Update TEMPLATES.md 2025-04-16 11:46:06 +02:00
Theo Arends
e6918d8b9c Fix ESP8266 IPv6 compilation 2025-04-16 11:35:06 +02:00
s-hadinger
7ea95ec6b2
Show network interface priority in 'Status 5' debug logging (#23302) 2025-04-15 13:21:14 +02:00
Theo Arends
8921a42f79 Add filesystem command `UfsList[2]` 2025-04-15 12:35:55 +02:00
Theo Arends
c8181e3290 Fix PZEM GUI address display 2025-04-14 16:13:59 +02:00
Theo Arends
117e503aaa Add PZEM_AC device address in JSON and GUI (#23268) 2025-04-14 15:24:02 +02:00
Theo Arends
3baa110f9d Add support for XMODEM over serial and telnet if enabled with #define USE_XYZMODEM 2025-04-14 13:54:05 +02:00
Theo Arends
a4096ab049 Update changelogs 2025-04-14 10:54:53 +02:00
Theo Arends
83118b9e05 Update changelogs 2025-04-14 10:52:54 +02:00
protectivedad
3a28938b91
HLK-LD2402 Update for firmware 3.3.5+ (#23281)
* Many changes for the newest firmware 3.3.5

added comments and debug lines
added new autogain function (fw 3.3.5+)
changed variables for consistency
ended configuration mode on error
fixed improper JSON response messages
changed timings for new firmware
consolidated post configuration processsing

* code size reduction
updated size extimates

* reworked to reduce code and memory usage

---------

Co-authored-by: Anthony Sepa <protectivedad@gmail.com>
2025-04-14 10:44:00 +02:00
s-hadinger
68f019cf43
HASPmota default theme is now Tasmota-style (#23288) 2025-04-13 23:23:51 +02:00
s-hadinger
4707cc068f
HASPmota added 'y2_min' and 'y2_max' to control the second series of 'chart' (#23287) 2025-04-13 21:54:43 +02:00
valentin richard
0604fac3bc
fix(zigbee): fix convertTuyaSpecificCluster datapoint parser -> support multiple data points in the same payload. (#23247)
Co-authored-by: valentin <email@example.com>
2025-04-12 19:12:32 +02:00
gemu
c12974366b
Sml update (#23267)
* rename nthll 64

* fix nthll 64
2025-04-11 15:16:05 +02:00
sfromis
cced48d824
Update uDisplay.h (#23273)
RGB565 value for pink was same as magenta. This is obviously wrong, hence correcting to the "pink" value from the docs.

While I'm far from certain about the "right" shading of color nuances, the correction does "reasonably pink" in my eyes (on a ST7789), and assuming that the value from the docs was sourced from something relevant to the small displays used with Tasmota, I consider the change to be at least a move in the right direction.

Still, the corrected value (FF80C0 in RGB888) does have the name "tea rose" when using HTML color codes as a reference, but "some people" may have more interest in long discussions like what pink "really" is.
2025-04-11 15:15:35 +02:00
Theo Arends
1a8903578f Update changelogs 2025-04-11 15:11:38 +02:00
Jason2866
230ce2c539
Platform 2025.04.30 Tasmota Arduino Core 3.1.3.250411 based on IDF 5.3.2.250403 (#23280) 2025-04-11 13:06:26 +02:00
Norbert
6b7606c958
Fix spelling (#23278) 2025-04-11 08:54:44 +02:00
jetpax
cfe1cee4d3
Replace brotli compressed file serving with gzip (#23274)
* Replace brotli compressed file serving with gzip as it is better supported

* Add HTTP_POST support
2025-04-10 23:12:37 +02:00
s-hadinger
2999eed8b9
Berry 'readline' when a line is exactly 98 characters (#23276) 2025-04-10 22:57:03 +02:00
Theo Arends
3f82228905 Fix MIEL_HVAC temperature saving 9k code size in addition (#23271) 2025-04-10 11:32:43 +02:00
s-hadinger
7ddf8abf90
Ensure AlpineJS is in PROGMEM (#23264) 2025-04-07 19:49:19 +02:00
Theo Arends
215b37bf69 Add Alpine.js 2.8.2 support (#23259) 2025-04-07 14:42:35 +02:00
Theo Arends
342bb2cb7b Update changelogs 2025-04-07 10:28:55 +02:00
s-hadinger
2096411be6
Fix esp_idf_http to make strings 'weak' (#23256) 2025-04-06 22:51:38 +02:00
jetpax
929582b1af
Expose esp_http_server to Berry (#23206)
* Expose esp_http_server to Berry

* Fix conditional build defines

* Fix Berry returns, dangling pointer

* Use correct Berry returns

* Remove debug code

* cleanup

* add BERRY to conditionals to avoid confusion
2025-04-06 22:27:48 +02:00
Thomas Büngener
4ed48feaa2
SML: CRC for binary SML (#23205)
* SML: CRC for binary SML parsing

* switch algos

* improve errormessage on buffer overflow

* move crc variable to their own struct

* Use Flag bit to disable CRC, auto-detect algorithm,
data in own struct
debug log

* configure and enable/disable via special option "=soC,bufsz,mode", mode 16 autodetect.

* fix 15 vs 0xF

* remove benchmark code

* fix typo in comment

* Byteflip for CRC
2025-04-05 11:22:22 +02:00
Theo Arends
c121dbcd4a Update changelogs 2025-04-05 11:21:03 +02:00
s-hadinger
e8baea464f
TLS increase timeout and fix crash (#23249) 2025-04-05 00:04:36 +02:00
Theo Arends
2bf67b96a6 Prep XYZModem support on Serial/USB and telnet 2025-04-01 23:15:28 +02:00
s-hadinger
0cb6a8ba24
Fix typo (#23232) 2025-04-01 23:10:30 +02:00
Theo Arends
39494f1287 Update changelogs 2025-04-01 23:10:08 +02:00
Qowy
90c690e67a
fix DIMMER ! to use correct dim value (#23196) 2025-04-01 22:57:58 +02:00
s-hadinger
08f20b9404
Smoothen light gamma curve when using Fade (#23230) 2025-04-01 22:51:56 +02:00
Theo Arends
dfabe8cc0f Update change logs 2025-03-31 11:49:57 +02:00
protectivedad
b43d360d37
fixes for ina226 driver (#23197)
adjust current/voltage timing to be consistent
fix missing comma in json

Co-authored-by: Anthony Sepa <protectivedad@gmail.com>
2025-03-31 11:45:59 +02:00
Theo Arends
2f7793ddcf Fix Zigbee XModem wait loop 2025-03-29 16:37:48 +01:00
Theo Arends
3c70b728ac Fix ESP32 compile without webserver 2025-03-28 13:58:22 +01:00
Theo Arends
289120ee92 Fix telnet buffer overrun detection 2025-03-28 12:16:32 +01:00
s-hadinger
b77b622fbe
Berry bytes add 3 (#23200)
* Berry bytes add with 3 bytes

* add changelog
2025-03-27 22:55:42 +01:00
s-hadinger
a47e6f1496
Berry avoid bootloop when Berry is disabled (#23199) 2025-03-27 21:08:32 +01:00
Theo Arends
74757ee7da Fix telnet response if seriallog is 0 2025-03-27 17:27:48 +01:00
Qowy
ea2baee3b8
fix fadeGammaReverse is applied to the time variable (#23194) 2025-03-27 10:17:43 +01:00
s-hadinger
f4bb9d98b6
HASPmota improve parsing (#23192) 2025-03-26 22:34:12 +01:00
Theo Arends
87b95f798a Extend command GPIO with different display options and allowing updating of module GPIO's in one go 2025-03-26 16:43:13 +01:00
Theo Arends
da4dc56b16 Bump version v14.5.0.3 2025-03-25 17:04:44 +01:00
Theo Arends
714ad233e0 Changed output of commands GPIO and GPIOs swapped 2025-03-25 16:53:26 +01:00
protectivedad
2da631e442
missing edits for last commit (#23185)
Co-authored-by: Anthony Sepa <protectivedad@gmail.com>
2025-03-25 15:22:27 +01:00
Theo Arends
6f47f23f7a Add terminate telnet session with command exit or quit 2025-03-25 13:47:41 +01:00
Theo Arends
69fca99ac1 Add telnet compile options 2025-03-25 11:19:53 +01:00
Theo Arends
a3b564f4f3 Keep telnet output while serial logging was disabled 2025-03-24 12:16:35 +01:00
Theo Arends
52f3306f15 Disable telnet output colors on command TelnetColor 0 2025-03-24 12:04:01 +01:00
Theo Arends
9d6640a42e Change command TelnetColor 0 to disable color codes from output 2025-03-24 10:57:48 +01:00
Theo Arends
307e1d9c29 Fix telnet line length regression 2025-03-23 22:36:42 +01:00
Theo Arends
f71ca3e0a2 Fix ESP32 telnet response 2025-03-23 17:34:44 +01:00
Theo Arends
a3d86eebf0 Telnet more functional bling bling 2025-03-23 13:23:03 +01:00
s-hadinger
f331a64ac3
HASPmota autostart when pages.jsonl exists (#23181) 2025-03-22 23:23:57 +01:00
Theo Arends
caac9f1257 Reduce telnet stack usage fixing ESP8266 exceptions 2025-03-22 17:33:27 +01:00
Theo Arends
b47a1bc1e2 Fix telnet async input 2025-03-22 12:04:02 +01:00
Qowy
9e3ad52356
fix wrong comment in xdrv_79_esp32_ble.ino (#23171) 2025-03-22 10:30:20 +01:00
protectivedad
38ceafe789
upgrades and fixes for HLK-LD2402 driver (#23164)
Co-authored-by: Anthony Sepa <protectivedad@gmail.com>
2025-03-22 10:28:15 +01:00
Theo Arends
ddc1439edf Fix webcam updatestats 2025-03-22 10:23:15 +01:00
DavidPletcher
3827bca3cc
remove malformed clutter from webcam status0 JSON response (#23177)
A regression was added in commit 01154e949, which prepends
clutter to the status0 JSON status message.

Example:
```
$ curl 'http://webcam/cm?cmnd=Status0' -u admin:password ; echo
{s}Webcam Frame rate{m}0 FPS{e}{"Status":{"Module":0,"DeviceName":"...
```

The response is not properly formatted JSON and breaks client software.

The problem occurs because a new case statement was added for the
purpose of injecting webcam stats into the JSON status message, but
a break statement is missing and execution falls through to the
following case, which prepends garbage to the output buffer.

With this one-line fix in place, the output is properly formatted:
```
$ curl 'http://tahoe-front-door-cam/cm?cmnd=Status0' -u admin:password ; echo
{"Status":{"Module":0,"DeviceName":"
```

Note that the prior case for FUNC_EVERY_SECOND is also missing a break
statement. That looks wrong to me but it's unrelated to fixing this
issue and I'm inclined to punt that concern to others who are more
familiar with this code.
2025-03-22 08:18:01 +01:00
Theo Arends
8183a9ed3b Add telnet bling bling 2025-03-21 23:41:01 +01:00
Theo Arends
00e2d1d430 Fix filelog and save some bytes 2025-03-21 17:29:04 +01:00
Theo Arends
863c6d1214 Fix telnet regression 2025-03-21 16:49:25 +01:00
Theo Arends
73cace5274 Add telnet graceful close 2025-03-21 16:38:26 +01:00
aronk
1ada6da6b8
[MI BLE] added support for alternative version of LYWSD02MMC (#23169)
* [MI BLE] added support for alternative version of LYWSD02MMC

* Bumped MI32_VERSION to 0.9.2.5
2025-03-21 14:30:17 +01:00
Theo Arends
fbb752d8c2 Add Telnet server using command Telnet <0|1|port>[,<IP filter>] 2025-03-20 23:11:30 +01:00
Theo Arends
fb6640b91f Fix ESP32 receive incomplete serial data over 128 bytes (#23156) 2025-03-18 15:12:30 +01:00
s-hadinger
c0d15de965
Berry 're.dump()' (#23162) 2025-03-17 21:34:59 +01:00
Theo Arends
3764e88ed2 Merge branch 'development' of https://github.com/arendst/Tasmota into development 2025-03-17 14:06:02 +01:00
Theo Arends
0ea1f8e632 Change RCSwitch RCSWITCH_SEPARATION_LIMIT from 4100 to 3600 2025-03-17 14:05:38 +01:00
Jason2866
234c5ea170
check fw size against partition (#23160) 2025-03-17 13:59:25 +01:00
s-hadinger
ce92723c41
Berry update from upstream (#23159) 2025-03-17 08:27:03 +01:00
s-hadinger
e1f7ee26fa
Matter prepare for ICD cluster (#23158) 2025-03-16 22:38:36 +01:00
s-hadinger
a97d306a16
Berry include changes in 're' to HASPmota (#23153) 2025-03-15 18:58:21 +01:00
Theo Arends
508992258f Update changelogs 2025-03-14 11:39:59 +01:00
s-hadinger
1b51aef911
Berry now accepts 'bytes()' as precompiled patterns, added 're.compilebytes()' (#23149) 2025-03-13 23:38:55 +01:00
s-hadinger
6486ba3b26
Fix typo of be_set_ctype_func_hanlder (#23147) 2025-03-13 17:49:28 +01:00
Bartosz Nitka
9b4eb64caa
Fix unused ret_code2 in xdrv_52_9_berry (#23146) 2025-03-13 17:22:21 +01:00
bovirus
6d376a079e
Italian language update (#23144) 2025-03-12 19:00:50 +01:00
protectivedad
69c3863b14
HLK-LD2402 fix for missing '|' (#23142)
Signed-off-by: Anthony Sepa <protectivedad@gmail.com>
Co-authored-by: Anthony Sepa <protectivedad@gmail.com>
2025-03-12 15:26:02 +01:00
Theo Arends
ac8236abe1 Update changelogs 2025-03-12 11:31:00 +01:00
s-hadinger
16e9d105ba
Update flasher for Sonoff ZBBridge Pro (#23136) 2025-03-11 23:04:51 +01:00
protectivedad
f3ae3bec4b
Added support for hlk-ld2402 tasmota_xsns_sensor (#23133)
This is based on the xsns_102_ld2410s.ino.

* Available commands:
* LD2402_Status 0|1|2 - showing parameters|sensor readings|firmware info
* LD2402_ReRead - reread common, motion and micro threshold parameters from device
* LD2402_SetCommon 7-100,0-65535 - set common: maximum distance, disappearance delay
* LD2402_SetMotion n,n1..n16 - set motion threshold values (16)
* LD2402_SetMicro n,n1..n16 - set micro threshold values (16)
* LD2402_Mode 0/1 - set device output mode 0-normal, 1-engineering
* LD2402_AutoUpdate 3.0,2.0,3.0 - start autoupdate trigger,keep,micro magnification factor
* LD2402_Follow 0/n - reports every n seconds

Signed-off-by: Anthony Sepa <protectivedad@gmail.com>
Co-authored-by: Anthony Sepa <protectivedad@gmail.com>
2025-03-11 17:03:54 +01:00
Theo Arends
cae4551762 Fix ESP32 compilation V9240 2025-03-11 15:12:02 +01:00
Theo Arends
007608914c Support Vango Technologies V924x ultralow power, single-phase, power measurement (#23127) 2025-03-11 14:57:11 +01:00
Ivan Chopa
758ba17dde
Added V9240 energy metering chip driver (#23127)
* Add V9240 driver

* Addendum to previous commit

* Add driver code similar to the prototype

* they are talking to each other

* Added implementation of calibration commands

* continued work of calibration

* Maybe it works.

* Post-merger control

* Change driver number 34 to 25

* Correction of other comments

* Removed  duplicate code

* Adjusting the calibration procedure according to the behavior stated here. To the extent possible.
https://tasmota.github.io/docs/Power-Monitoring-Calibration/#calibration-procedure

* Removed added trailing whitespaces

* Fixing several small issues.
2025-03-11 14:28:07 +01:00
Giuliano
08fae4bcd6
typo fix (#23122) 2025-03-11 11:32:00 +01:00
s-hadinger
f305113d6d
Removed USE_WEBCLIENT and default USE_WEBCLIENT_HTTPS (#23132) 2025-03-10 22:37:27 +01:00
Marius Bezuidenhout
7b8d2fe93d
BMS additional features (#23125)
* Added more data from BMS

* Updated mcp2515 code
2025-03-09 16:27:10 +01:00
Giuliano
714435be1c
Remove misleading comment (#23124) 2025-03-09 13:42:44 +01:00
Theo Arends
e3eb47078f Fix ESP32 intermittent exception on WiFi AP cannot be reached (#23115) 2025-03-08 15:19:45 +01:00
Jason2866
a0c8ac4f80
enable FTP for all esp8266 >= 4MB (not only for 4MB variant) (#23120) 2025-03-08 13:07:58 +01:00
Jason2866
c926b4b3a6
enable wifi sleep for c3 (#23117) 2025-03-07 14:43:31 +01:00
s-hadinger
3f93d2deee
Berry remove 'Leds.create_matrix' from the standard library waiting for reimplementation (#23114) 2025-03-06 23:11:16 +01:00
s-hadinger
06aa356bc3
Berry load files in '/.extensions/' then in '/' (#23113) 2025-03-06 21:15:59 +01:00
Theo Arends
58632d67db Update changelogs 2025-03-06 16:17:54 +01:00
s-hadinger
e26a2cdac9
Berry prevent 'import' from hiding a solidified class (#23112) 2025-03-06 14:45:34 +01:00
Jason2866
72535db185
prep Hybrid: add Hybrid compile examples (#22474) 2025-03-05 14:27:47 +01:00
Theo Arends
f2bf8b96e7 Increase rcswitch H/L changes to 64 bits 2025-03-05 12:32:07 +01:00
Theo Arends
549ca6e32f ESP32 enable webcam version 2 (#18732) 2025-03-04 10:16:13 +01:00
Theo Arends
72520e0743 Bump version v14.5.0.2 2025-03-02 16:17:07 +01:00
Jason2866
aed82dc8b2
Platform 20250330 (#23088)
* Platform 2025.03.30 Tasmota Arduino Core 3.1.3.250302 based on IDF 5.3.2.250228

* Arduino core 3.1.3.250302
2025-03-02 16:04:56 +01:00
gemu
2e35a2ab93
some fixes and formatting (#23084) 2025-03-01 15:11:35 +01:00
Jason2866
3c171c1ed8
Compile lib NeopixelBus only for esp8266 (#23077)
* force mode strict for pixels lib
* Use lib NeoPixelBus only for esp8266
2025-02-27 12:15:20 +01:00
Theo Arends
481f2cd8e1 Update changelogs 2025-02-26 17:22:13 +01:00
s-hadinger
9a98db9773
Berry 'global.undef()' to undefine a global variable (#23073) 2025-02-26 15:30:04 +01:00
s-hadinger
e92e411040
Berry minor fixes to remove warnings (#23071) 2025-02-25 22:28:13 +01:00
s-hadinger
aecba92da4
Update be_mapping_utils.c, add final newline to avoid compilation warning 2025-02-25 21:14:09 +01:00
zzdovydas
4ee4b5908f
Fix LT Language (#22971) (#23064) 2025-02-25 11:19:43 +01:00
Theo Arends
3f74bc83e5 Update changelogs / gpioviewer / wizmote 2025-02-24 15:23:59 +01:00
Theo Arends
fd0501035d Update changelogs 2025-02-24 14:51:29 +01:00
s-hadinger
670fab7ead
Berry 'introspect.solidified()' to know if a Berry object is solidified in Flash or in RAM (#23063)
* Berry 'introspect.isconst()' to know if a Berry object is solidified or in RAM

* change to solidified

* fix typo
2025-02-24 14:05:58 +01:00
s-hadinger
375864b23b
Berry 'tasmota.when_network_up()' and simplified Matter using it (#23057) 2025-02-23 19:19:42 +01:00
Jason2866
788ac574ac
remove tagging gemu2015 for every opened bug report 2025-02-23 14:27:42 +01:00
Theo Arends
5aa7d08c91 Fix too many zeros in RCSwitch received data regression from v14.4.1.4 (#23050) 2025-02-23 13:54:39 +01:00
Theo Arends
b4c61325cb Add optional WizMote commission 2025-02-22 18:12:36 +01:00
Theo Arends
d10eafc500 Update changelogs 2025-02-22 15:22:20 +01:00
Theo Arends
90ebff552d Update changelogs 2025-02-22 15:01:37 +01:00
s-hadinger
0c26698ba6
Leds Panel add checkbox to enable/disable the feature (#23048) 2025-02-22 12:33:34 +01:00
s-hadinger
1db796c40f
LVGL Mirroring add checkbox to enable/disable the feature (#23047) 2025-02-22 12:00:36 +01:00
s-hadinger
b8459eb685
LVGL Berry fix lvgl_berry_fix_lv_style_prop_arr (#23042) 2025-02-21 09:15:03 +01:00
Giuliano Zaro
b1f3d6268d
Allow acl in mqtt when client certificate is in use (#22998)
* Allow acl in mqtt

Acl in mqtt needs user name if 'use_identity_as_username' is not true. It also seems that login in mqtt don't accept an user with an empty password, then reenabled both

* Add new define for mosquitto

Keep compatibility with AWS_IOT

* Better approach to custom client certificate

Don't duplicate defined check. Let USE_MQTT_AWS_IOT automatically set USE_MQTT_CLIENT_CERT and use latter in all code

* with mosquitto user and password may be empty

When mosquitto 'use_identity_as_username' option is enabled password and user are not used
2025-02-20 22:51:52 +01:00
s-hadinger
7a4d8a5fb1
LVGL experimental mirroring of display on Web UI (#23041) 2025-02-20 21:45:45 +01:00
s-hadinger
0ab5548615
LVGL, prepare for HASPmota theme, change: no-grow when clicked, DPI set to 160 (#23040) 2025-02-20 21:13:35 +01:00
s-hadinger
1af1057e66
Berry experimental driver for AXP2101 for M5Core2v1.1 (#23039) 2025-02-20 20:40:53 +01:00
Jason2866
039960153a
typo C3 not C2 2025-02-20 15:01:37 +01:00
Theo Arends
b4c1cd654f Bump version v14.5.0.1 2025-02-18 16:14:27 +01:00
190 changed files with 22964 additions and 11139 deletions

View File

@ -32,7 +32,7 @@ _Make sure your have performed every step and checked the applicable boxes befor
- [ ] Searched the problem in [discussions](https://github.com/arendst/Tasmota/discussions)
- [ ] Searched the problem in the [docs](https://tasmota.github.io/docs/FAQ)
- [ ] Searched the problem in the [chat](https://discord.gg/Ks2Kzd4)
- [ ] Problem is not scripter related, in this case open a discussion and tag @gemu2015
- [ ] Problem is not scripter related, in this case open a discussion and tag gemu2015
- [ ] Device used (e.g., Sonoff Basic): _____
- [ ] Tasmota binary firmware version number used: _____
- [ ] Pre-compiled

View File

@ -7,7 +7,7 @@
- [ ] Only relevant files were touched
- [ ] Only one feature/fix was added per PR and the code change compiles without warnings
- [ ] The code change is tested and works with Tasmota core ESP8266 V.2.7.8
- [ ] The code change is tested and works with Tasmota core ESP32 V.3.1.1.250203
- [ ] The code change is tested and works with Tasmota core ESP32 V.3.1.3.250411
- [ ] I accept the [CLA](https://github.com/arendst/Tasmota/blob/development/CONTRIBUTING.md#contributor-license-agreement-cla).
_NOTE: The code change must pass CI tests. **Your PR cannot be merged unless tests pass**_

View File

@ -1,234 +1,234 @@
name: Build_firmware_master
on:
workflow_dispatch: # Start a workflow
push:
branches: master
paths-ignore:
- '.github/**' # Ignore changes towards the .github directory
- '**.md' # Do no build if *.md files changes
# Ensures that only one deploy task per branch/environment will run at a time.
concurrency:
group: environment-${{ github.ref }}
cancel-in-progress: true
jobs:
safeboot-images:
runs-on: ubuntu-latest
if: github.repository == 'arendst/Tasmota'
continue-on-error: true
strategy:
matrix:
variant:
- tasmota32-safeboot
- tasmota32solo1-safeboot
- tasmota32c2-safeboot
- tasmota32c3-safeboot
- tasmota32c3ser-safeboot
- tasmota32s2-safeboot
- tasmota32s2cdc-safeboot
- tasmota32s3-safeboot
- tasmota32s3ser-safeboot
- tasmota32c6-safeboot
- tasmota32c6ser-safeboot
steps:
- uses: actions/checkout@v4
with:
ref: master
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Install dependencies
run: |
pip install wheel
pip install -U platformio
cp ./platformio_override_sample.ini ./platformio_override.ini
- name: Add "release" to footer
run: |
sed -i -e "s/TASMOTA_SHA_SHORT/TASMOTA_SHA_SHORT release-/g" ./tasmota/include/tasmota_version.h
- name: Run PlatformIO
run: platformio run -e ${{ matrix.variant }}
- name: Upload safeboot firmware artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.variant }}
path: ./build_output
base-images:
runs-on: ubuntu-latest
if: github.repository == 'arendst/Tasmota'
continue-on-error: true
strategy:
matrix:
variant:
- tasmota
- tasmota-4M
- tasmota-minimal
- tasmota-display
- tasmota-ir
- tasmota-knx
- tasmota-lite
- tasmota-sensors
- tasmota-zbbridge
- tasmota-zigbee
steps:
- uses: actions/checkout@v4
with:
ref: master
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Install dependencies
run: |
pip install wheel
pip install -U platformio
cp ./platformio_override_sample.ini ./platformio_override.ini
- name: Add "release" to footer
run: |
sed -i -e "s/TASMOTA_SHA_SHORT/TASMOTA_SHA_SHORT release-/g" ./tasmota/include/tasmota_version.h
- name: Run PlatformIO
run: platformio run -e ${{ matrix.variant }}
- name: Upload firmware artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.variant }}
path: ./build_output
base32-images:
needs: safeboot-images
runs-on: ubuntu-latest
if: github.repository == 'arendst/Tasmota'
continue-on-error: true
strategy:
matrix:
variant:
- tasmota32
- tasmota32-zbbrdgpro
- tasmota32-webcam
- tasmota32-bluetooth
- tasmota32-nspanel
- tasmota32-display
- tasmota32-ir
- tasmota32-lvgl
- tasmota32c2
- tasmota32c3
- tasmota32c6
- tasmota32s2
- tasmota32s2cdc
- tasmota32s3
- tasmota32solo1
steps:
- uses: actions/checkout@v4
with:
ref: master
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Install dependencies
run: |
pip install wheel
pip install -U platformio
cp ./platformio_override_sample.ini ./platformio_override.ini
- name: Download safeboot firmwares
uses: actions/download-artifact@v4
with:
pattern: tasmota32*
path: ./temp
- name: Move safeboot files
run: |
mkdir -p ./firmware/firmware
find ./temp -type f -exec cp -t ./firmware/firmware {} +
- name: Add "release" to footer
run: |
sed -i -e "s/TASMOTA_SHA_SHORT/TASMOTA_SHA_SHORT release-/g" ./tasmota/include/tasmota_version.h
- name: Run PlatformIO
run: platformio run -e ${{ matrix.variant }}
- name: Upload firmware artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.variant }}
path: ./build_output
language-images:
needs: safeboot-images
runs-on: ubuntu-latest
if: github.repository == 'arendst/Tasmota'
continue-on-error: true
strategy:
matrix:
variant: [ tasmota, tasmota32 ]
language: [ AD, AF, BG, BR, CN, CZ, DE, ES, FR, FY, GR, HE, HU, IT, KO, LT, NL, PL, PT, RO, RU, SE, SK, TR, TW, UK, VN ]
steps:
- uses: actions/checkout@v4
with:
ref: master
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Install dependencies
run: |
pip install wheel
pip install -U platformio
cp ./platformio_override_sample.ini ./platformio_override.ini
- name: Download safeboot firmwares
uses: actions/download-artifact@v4
with:
pattern: tasmota32*
path: ./temp
- name: Move safeboot files
run: |
mkdir -p ./firmware/firmware
find ./temp -type f -exec cp -t ./firmware/firmware {} +
- name: Add "release" to footer
run: |
sed -i -e "s/TASMOTA_SHA_SHORT/TASMOTA_SHA_SHORT release-/g" ./tasmota/include/tasmota_version.h
- name: Run PlatformIO
run: platformio run -e ${{ matrix.variant }}-${{ matrix.language }}
- name: Upload language firmware artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.variant }}-${{ matrix.language }}
path: ./build_output
Release:
needs: [base-images, base32-images, language-images]
runs-on: ubuntu-latest
continue-on-error: true
steps:
- uses: actions/checkout@v4
- name: Download all Tasmota artifacts
uses: actions/download-artifact@v4
with:
pattern: tasmota*
path: ./temp
- name: Move files
run: |
mkdir -p ./release
find ./temp -type f -exec cp -t ./release {} +
- name: Display structure of downloaded files
run: ls -R ./release/
- name: Release
uses: jason2866/action-gh-release@v1.2
#if: startsWith(github.ref, 'refs/tags/')
with:
tag_name: ${{ github.run_number }}
files: |
./release/tasmota*
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Start_final_copy:
needs: Release
runs-on: ubuntu-latest
steps:
- name: Dispatch workflow in arendst/Tasmota-firmware
run: |
curl -X POST https://api.github.com/repos/arendst/Tasmota-firmware/actions/workflows/fetch_deploy.yml/dispatches \
-H 'Accept: application/vnd.github.everest-preview+json' \
-u ${{ secrets.API_TOKEN_GITHUB }} \
--data '{"ref": "gh_actions"}'
name: Build_firmware_master
on:
workflow_dispatch: # Start a workflow
push:
branches: master
paths-ignore:
- '.github/**' # Ignore changes towards the .github directory
- '**.md' # Do no build if *.md files changes
# Ensures that only one deploy task per branch/environment will run at a time.
concurrency:
group: environment-${{ github.ref }}
cancel-in-progress: true
jobs:
safeboot-images:
runs-on: ubuntu-latest
if: github.repository == 'arendst/Tasmota'
continue-on-error: true
strategy:
matrix:
variant:
- tasmota32-safeboot
- tasmota32solo1-safeboot
- tasmota32c2-safeboot
- tasmota32c3-safeboot
- tasmota32c3ser-safeboot
- tasmota32s2-safeboot
- tasmota32s2cdc-safeboot
- tasmota32s3-safeboot
- tasmota32s3ser-safeboot
- tasmota32c6-safeboot
- tasmota32c6ser-safeboot
steps:
- uses: actions/checkout@v4
with:
ref: master
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Install dependencies
run: |
pip install wheel
pip install -U platformio
cp ./platformio_override_sample.ini ./platformio_override.ini
- name: Add "release" to footer
run: |
sed -i -e "s/TASMOTA_SHA_SHORT/TASMOTA_SHA_SHORT release-/g" ./tasmota/include/tasmota_version.h
- name: Run PlatformIO
run: platformio run -e ${{ matrix.variant }}
- name: Upload safeboot firmware artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.variant }}
path: ./build_output
base-images:
runs-on: ubuntu-latest
if: github.repository == 'arendst/Tasmota'
continue-on-error: true
strategy:
matrix:
variant:
- tasmota
- tasmota-4M
- tasmota-minimal
- tasmota-display
- tasmota-ir
- tasmota-knx
- tasmota-lite
- tasmota-sensors
- tasmota-zbbridge
- tasmota-zigbee
steps:
- uses: actions/checkout@v4
with:
ref: master
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Install dependencies
run: |
pip install wheel
pip install -U platformio
cp ./platformio_override_sample.ini ./platformio_override.ini
- name: Add "release" to footer
run: |
sed -i -e "s/TASMOTA_SHA_SHORT/TASMOTA_SHA_SHORT release-/g" ./tasmota/include/tasmota_version.h
- name: Run PlatformIO
run: platformio run -e ${{ matrix.variant }}
- name: Upload firmware artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.variant }}
path: ./build_output
base32-images:
needs: safeboot-images
runs-on: ubuntu-latest
if: github.repository == 'arendst/Tasmota'
continue-on-error: true
strategy:
matrix:
variant:
- tasmota32
- tasmota32-zbbrdgpro
- tasmota32-webcam
- tasmota32-bluetooth
- tasmota32-nspanel
- tasmota32-display
- tasmota32-ir
- tasmota32-lvgl
- tasmota32c2
- tasmota32c3
- tasmota32c6
- tasmota32s2
- tasmota32s2cdc
- tasmota32s3
- tasmota32solo1
steps:
- uses: actions/checkout@v4
with:
ref: master
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Install dependencies
run: |
pip install wheel
pip install -U platformio
cp ./platformio_override_sample.ini ./platformio_override.ini
- name: Download safeboot firmwares
uses: actions/download-artifact@v4
with:
pattern: tasmota32*
path: ./temp
- name: Move safeboot files
run: |
mkdir -p ./firmware/firmware
find ./temp -type f -exec cp -t ./firmware/firmware {} +
- name: Add "release" to footer
run: |
sed -i -e "s/TASMOTA_SHA_SHORT/TASMOTA_SHA_SHORT release-/g" ./tasmota/include/tasmota_version.h
- name: Run PlatformIO
run: platformio run -e ${{ matrix.variant }}
- name: Upload firmware artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.variant }}
path: ./build_output
language-images:
needs: safeboot-images
runs-on: ubuntu-latest
if: github.repository == 'arendst/Tasmota'
continue-on-error: true
strategy:
matrix:
variant: [ tasmota, tasmota32 ]
language: [ AD, AF, BG, BR, CN, CZ, DE, ES, FR, FY, GR, HE, HU, IT, KO, LT, NL, PL, PT, RO, RU, SE, SK, TR, TW, UK, VN ]
steps:
- uses: actions/checkout@v4
with:
ref: master
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Install dependencies
run: |
pip install wheel
pip install -U platformio
cp ./platformio_override_sample.ini ./platformio_override.ini
- name: Download safeboot firmwares
uses: actions/download-artifact@v4
with:
pattern: tasmota32*
path: ./temp
- name: Move safeboot files
run: |
mkdir -p ./firmware/firmware
find ./temp -type f -exec cp -t ./firmware/firmware {} +
- name: Add "release" to footer
run: |
sed -i -e "s/TASMOTA_SHA_SHORT/TASMOTA_SHA_SHORT release-/g" ./tasmota/include/tasmota_version.h
- name: Run PlatformIO
run: platformio run -e ${{ matrix.variant }}-${{ matrix.language }}
- name: Upload language firmware artifacts
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.variant }}-${{ matrix.language }}
path: ./build_output
Release:
needs: [base-images, base32-images, language-images]
runs-on: ubuntu-latest
continue-on-error: true
steps:
- uses: actions/checkout@v4
- name: Download all Tasmota artifacts
uses: actions/download-artifact@v4
with:
pattern: tasmota*
path: ./temp
- name: Move files
run: |
mkdir -p ./release
find ./temp -type f -exec cp -t ./release {} +
- name: Display structure of downloaded files
run: ls -R ./release/
- name: Release
uses: jason2866/action-gh-release@v1.2
#if: startsWith(github.ref, 'refs/tags/')
with:
tag_name: ${{ github.run_number }}
files: |
./release/tasmota*
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Start_final_copy:
needs: Release
runs-on: ubuntu-latest
steps:
- name: Dispatch workflow in arendst/Tasmota-firmware
run: |
curl -X POST https://api.github.com/repos/arendst/Tasmota-firmware/actions/workflows/fetch_deploy.yml/dispatches \
-H 'Accept: application/vnd.github.everest-preview+json' \
-u ${{ secrets.API_TOKEN_GITHUB }} \
--data '{"ref": "gh_actions"}'

3
.gitignore vendored
View File

@ -49,6 +49,9 @@ lib/libesp32/berry/berry
*.bak
*.code-workspace
## IntelliJ ######
.idea
## Python virtual environments for Platformio ##
venv
.venv

View File

@ -14,10 +14,13 @@ Note: the `minimal` variant is not listed as it shouldn't be used outside of the
| USE_HOME_ASSISTANT | - | - / - | - | - | - | - |
| USE_TASMOTA_DISCOVERY | x | x / x | x | x | x | x |
| USE_MQTT_TLS\* | - | - / x | - | - | - | - |
| USE_MQTT_CLIENT_CERT | - | - / - | - | - | - | - |
| USE_MQTT_AWS_IOT | - | - / - | - | - | - | - |
| USE_4K_RSA | - | - / - | - | - | - | - |
| USE_TELEGRAM | - | - / - | - | - | - | - |
| USE_KNX | - | - / x | x | - | - | - |
| USE_TELNET | - | - / - | - | - | - | - |
| USE_XYZMODEM | - | - / - | - | - | - | - |
| USE_WEBSERVER | x | x / x | x | x | x | x |
| USE_WEBSEND_RESPONSE | - | - / - | - | - | - | - |
| USE_EMULATION_HUE | x | x / x | - | x | - | - |
@ -228,7 +231,9 @@ Note: the `minimal` variant is not listed as it shouldn't be used outside of the
| USE_MIEL_HVAC | - | - / - | - | - | - | - |
| USE_PROJECTOR_CTRL | - | - / - | - | - | - | - |
| USE_AS608 | - | - / - | - | - | - | - |
| USE_LD2402 | - | - / - | - | - | - | - |
| USE_LD2410 | - | - / - | - | - | - | - |
| USE_LD2410S | - | - / - | - | - | - | - |
| USE_GM861 | - | - / - | - | - | - | - |
| USE_TCP_BRIDGE | - | - / - | - | - | - | - | zbbridge / zbbrdgpro |
| USE_HC8 | - | - / - | - | - | - | - |

View File

@ -1,8 +1,101 @@
# Changelog
All notable changes to this project will be documented in this file.
## [Unreleased] - Development
## [14.6.0.1]
### Added
- Command `JsonPP 0..7` to enable (>0) JSON Pretty Print on user interfaces and set number of indents
- Command `JsonPP <command>|backlog <command>;...` to enable JSON PP only once
### Breaking Changed
### Changed
### Fixed
- Berry `bytes().asstring()` now truncates a string if buffer contains NULL (#23311)
- Berry string literals containing NULL are truncated (#23312)
### Removed
## [Released]
## [14.6.0] 20250416
- Release Ryan
## [14.5.0.3] 20250416
### Added
- Extend command `GPIO` with different display options and allowing updating of module GPIO's in one go
- Berry `bytes.add()` now accepts 3-bytes values (#23200)
- Berry expose `esp_http_server` for websockets (#23206)
- AlpineJS 2.8.2 - optional for now (#23259)
- Support for XMODEM over serial and telnet if enabled with `#define USE_XYZMODEM`
- PZEM_AC device address in JSON and GUI (#23268)
- Filesystem command ``UfsList[2]``
- ESP32 show network interface priority in `Status 5` debug logging (#23302)
### Breaking Changed
- HASPmota added `y2_min` and `y2_max` to control the second series of `chart` (#23287)
- HASPmota default theme is now Tasmota-style (#23288)
### Changed
- Output of commands `GPIO` and `GPIOs` swapped
- Smoothen light gamma curve when using `Fade` (#23230)
- ESP32 Platform from 2025.03.30 to 2025.04.30, Framework (Arduino Core) from v3.1.3.250302 to v3.1.3.250411 and IDF from v5.3.2.250228 to 5.3.2.250403 (#23280)
- HLK-LD2402 updates for firmware 3.3.5+ (#23281)
### Fixed
- INA226 driver fixes (#23197)
- TLS increase timeout and fix crash (#23249)
- Berry `readline` when a line is exactly 98 characters (#23276)
## [14.5.0.2] 20250325
### Added
- Berry load `.tapp` files in `/.extensions/` then in `/` (#23113)
- Support Vango Technologies V924x ultralow power, single-phase, power measurement (#23127)
- Support for HLK-LD2402 24GHz smart wave motion sensor (#23133)
- Matter prepare for ICD cluster (#23158)
- Berry `re.dump()` (#23162)
- Support for Telnet server using command `Telnet <0|1|port>[,<IP filter>]` if enabled with `#define USE_TELNET`
- HASPmota autostart when `pages.jsonl` exists (#23181)
### Breaking Changed
- Berry remove `Leds.create_matrix` from the standard library waiting for reimplementation (#23114)
### Changed
- ESP32 Platform from 2025.02.30 to 2025.03.30, Framework (Arduino Core) from v3.1.1.250203 to v3.1.3.250302 and IDF from v5.3.2.250120 to 5.3.2.250228 (#23088)
- ESP32 enable webcam version 2 (#18732)
- ESP8266 enable FTP for >= 4MB variants (#23120)
- Berry update flasher for Sonoff ZBBridge Pro (#23136)
- Berry `re` now accepts `bytes()` as precompiled patterns, added `re.compilebytes()` (#23149)
- RCSwitch `RCSWITCH_SEPARATION_LIMIT` from 4100 to 3600
### Fixed
- Berry prevent `import` from hiding a solidified class (#23112)
- ESP32-C3 WiFi sleep (#23096)
- ESP32 intermittent exception on WiFi AP cannot be reached (#23115)
- ESP32 receive incomplete serial data over 128 bytes (#23156)
## [14.5.0.1] 20250302
### Added
- Berry experimental driver for AXP2101 for M5Core2v1.1 (#23039)
- LVGL experimental mirroring of display on Web UI (#23041)
- Allow acl in mqtt when client certificate is in use with `#define USE_MQTT_CLIENT_CERT` (#22998)
- Berry `tasmota.when_network_up()` and simplified Matter using it (#23057)
- Berry `introspect.solidified()` to know if a Berry object is solidified or in RAM (#23063)
- Berry `global.undef()` to undefine a global variable (#23073)
### Changed
- LVGL, prepare for HASPmota theme, change: no-grow when clicked, DPI set to 160 (#23040)
- LVGL Mirroring add checkbox to enable/disable the feature (in the iterim for a better solution) (#23047)
- Leds Panel add checkbox to enable/disable the feature (in the iterim for a better solution) (#23048)
- GPIOViewer from v1.6.1 to v1.6.2 (No functional change)
### Fixed
- Too many zeros in RCSwitch received data regression from v14.4.1.4 (#23050)
## [14.5.0] 20250219
- Release Ruth

View File

@ -89,8 +89,9 @@ In addition to @arendst the following code is mainly owned by:
| xdrv_75_dali | @eeak, @arendst
| xdrv_76_serial_i2c | @s-hadinger
| xdrv_77_wizmote | @arendst
| xdrv_78 |
| xdrv_78_telnet | @arendst
| xdrv_79_esp32_ble | @staars, @btsimonh
| xdrv_80 |
| xdrv_81_esp32_webcam | @gemu, @philrich
| xdrv_82_esp32_ethernet | @arendst
| xdrv_83_esp32_watch | @gemu
@ -105,6 +106,7 @@ In addition to @arendst the following code is mainly owned by:
| xdrv_93_ |
| xdrv_94_ |
| |
| xdrv_120_xyzmodem | @arendst
| xdrv_121_gpioviewer | @arendst
| xdrv_122_file_settings_demo | @arendst
| xdrv_122_file_json_settings_demo | @arendst

View File

@ -18,7 +18,7 @@ See [CHANGELOG.md](https://github.com/arendst/Tasmota/blob/development/CHANGELOG
## Development
[![Dev Version](https://img.shields.io/badge/development%20version-v14.5.x.x-blue.svg)](https://github.com/arendst/Tasmota)
[![Dev Version](https://img.shields.io/badge/development%20version-v14.6.x.x-blue.svg)](https://github.com/arendst/Tasmota)
[![Download Dev](https://img.shields.io/badge/download-development-yellow.svg)](http://ota.tasmota.com/tasmota/)
[![Tasmota CI](https://github.com/arendst/Tasmota/workflows/Tasmota%20CI/badge.svg)](https://github.com/arendst/Tasmota/actions?query=workflow%3A%22Tasmota+CI%22)
[![Tasmota ESP32 CI](https://github.com/arendst/Tasmota/workflows/Tasmota%20ESP32%20CI/badge.svg)](https://github.com/arendst/Tasmota/actions?query=workflow%3A%22Tasmota+ESP32+CI%22)

View File

@ -31,7 +31,7 @@ Firmware binaries can be downloaded from http://ota.tasmota.com/tasmota/release/
## Development
[![Dev Version](https://img.shields.io/badge/development%20version-v14.5.x.x-blue.svg)](https://github.com/arendst/Tasmota)
[![Dev Version](https://img.shields.io/badge/development%20version-v14.6.x.x-blue.svg)](https://github.com/arendst/Tasmota)
[![Download Dev](https://img.shields.io/badge/download-development-yellow.svg)](http://ota.tasmota.com/tasmota/)
[![Tasmota CI](https://github.com/arendst/Tasmota/actions/workflows/build_all_the_things.yml/badge.svg)](https://github.com/arendst/Tasmota/actions/workflows/build_all_the_things.yml)
[![Build_development](https://github.com/arendst/Tasmota/actions/workflows/Tasmota_build_devel.yml/badge.svg)](https://github.com/arendst/Tasmota/actions/workflows/Tasmota_build_devel.yml)

View File

@ -36,9 +36,9 @@ While fallback or downgrading is common practice it was never supported due to S
This release will be supported from ESP8266/Arduino library Core version **2.7.8** due to reported security and stability issues on previous Core version. This will also support gzipped binaries.
This release will be supported from ESP32/Arduino library Core version **v3.1.1.250203**.
This release will be supported from ESP32/Arduino library Core version **v3.1.3.250411**.
Support of ESP8266 Core versions before 2.7.8 and ESP32 Core versions before v3.1.1.250203 have been removed.
Support of ESP8266 Core versions before 2.7.8 and ESP32 Core versions before v3.1.3.250411 have been removed.
## Support of TLS
@ -75,12 +75,12 @@ Latest released binaries can be downloaded from
- http://ota.tasmota.com/tasmota/release
Historical binaries can be downloaded from
- http://ota.tasmota.com/tasmota/release-14.5.0
- http://ota.tasmota.com/tasmota/release-14.6.0
The latter links can be used for OTA upgrades too like ``OtaUrl http://ota.tasmota.com/tasmota/release/tasmota.bin.gz``
### ESP32, ESP32-C2, ESP32-C3, ESP32-C6, ESP32-S2 and ESP32-S3 based
The following binary downloads have been compiled with ESP32/Arduino library core version **v3.1.1.250203**.
The following binary downloads have been compiled with ESP32/Arduino library core version **v3.1.3.250411**.
- **tasmota32.bin** = The Tasmota version with most drivers including additional sensors and KNX for 4M+ flash. **RECOMMENDED RELEASE BINARY**
- **tasmota32solo1.bin** = The Tasmota version with most drivers including additional sensors and KNX for single core ESP32 and 4M+ flash.
@ -88,7 +88,7 @@ The following binary downloads have been compiled with ESP32/Arduino library cor
- **tasmota32s2cdc.bin** = The Tasmota version with most drivers including additional sensors and KNX for ESP32-S2 with serial over embedded USB CDC only and 4M+ flash.
- **tasmota32s3.bin** = The Tasmota version with most drivers including additional sensors and KNX for ESP32-S3 with USB HWCDC and fallback to serial and 4M+ flash.
- **tasmota32c2.bin** = The Tasmota version with most drivers including additional sensors and KNX for ESP32-C2 with serial and 4M+ flash.
- **tasmota32c3.bin** = The Tasmota version with most drivers including additional sensors and KNX for ESP32-C2 with USB HWCDC and fallback to serial and 4M+ flash.
- **tasmota32c3.bin** = The Tasmota version with most drivers including additional sensors and KNX for ESP32-C3 with USB HWCDC and fallback to serial and 4M+ flash.
- **tasmota32c6.bin** = The Tasmota version with most drivers including additional sensors and KNX for ESP32-C6 with USB HWCDC and fallback to serial and 4M+ flash.
- **tasmota32-AD.bin** to **tasmota32-VN.bin** = The Tasmota version in different languages for 4M+ flash.
- **tasmota32-bluetooth.bin** = The Bluetooth version adds BLE support for 4M+ flash.
@ -104,7 +104,7 @@ Latest released binaries can be downloaded from
- https://ota.tasmota.com/tasmota32/release
Historical binaries can be downloaded from
- https://ota.tasmota.com/tasmota32/release-14.5.0
- https://ota.tasmota.com/tasmota32/release-14.6.0
The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasmota.com/tasmota32/release/tasmota32.bin``
@ -114,76 +114,17 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm
[Complete list](BUILDS.md) of available feature and sensors.
## Changelog v14.5.0 Ruth
## Changelog v14.6.0.1
### Added
- Command `SetOption163 1` to disable display of Device name in GUI header
- Command `FileLog 0..4` to enable logging to filesystem using up to 16 rotating log files of 100kB (`#define FILE_LOG_SIZE 100`)
- Command `FileLog 10..14` to enable logging to filesystem using up to 16 log files of 100kB (`#define FILE_LOG_SIZE 100`)
- Command I2sLoop [#22807](https://github.com/arendst/Tasmota/issues/22807)
- Support for Lithuanian language translations by zzdovydas [#22971](https://github.com/arendst/Tasmota/issues/22971)
- Support for PCF85063 RTC [#22727](https://github.com/arendst/Tasmota/issues/22727)
- Support for Senseair S88 CO2 sensor [#22733](https://github.com/arendst/Tasmota/issues/22733)
- Support for C8-CO2-5K CO2 sensor [#22905](https://github.com/arendst/Tasmota/issues/22905)
- Support for ESP32 Two-Wire Automotive Interface (TWAI) or Controller Area Network (CAN) busses
- `#define FIX_JSON_HEXADECIMAL` to change JSON hexadecimal value "FF5F78" into "0xFF5F78" [#22919](https://github.com/arendst/Tasmota/issues/22919)
- Support for RC-switch decoding of 64-bit received data
- Support for WiZ Smart Remote using `#define USE_WIZMOTE` and command `SetOption164 1`
- `MqttTLS` field in `Status 6` to indicate if the MQTT connection is encrypted [#22995](https://github.com/arendst/Tasmota/issues/22995)
- Formatter `%_U` for `ext_snprintf_P()` to print uint64_t variable as decimal equivalent to `%llu`
- GPS driver select baudrate using GPIO GPS_RX1 (9600bps), GPS_RX2 (19200bps) or GPS_RX3 (38400bps) [#22869](https://github.com/arendst/Tasmota/issues/22869)
- I2S AAC support for web radio [#22787](https://github.com/arendst/Tasmota/issues/22787)
- I2S Opus stream and file support for opus/aac [#22795](https://github.com/arendst/Tasmota/issues/22795)
- ESP32 command `PixelType` to change the WS2812 color order and channel number [#22876](https://github.com/arendst/Tasmota/issues/22876)
- ESP32 TasmotaLED change dynamically the number of pixels [#22754](https://github.com/arendst/Tasmota/issues/22754)
- ESP32 expand `Pixels` with reverse, height and alternate [#22755](https://github.com/arendst/Tasmota/issues/22755)
- Display template for Waveshare ESP32-C6 LCD 1.47 [#22863](https://github.com/arendst/Tasmota/issues/22863)
- Berry `animate.crenel` primitive [#22673](https://github.com/arendst/Tasmota/issues/22673)
- Berry `tasmota.int(v, min, max)` function [#22723](https://github.com/arendst/Tasmota/issues/22723)
- Berry `bytes().appendhex()` [#22767](https://github.com/arendst/Tasmota/issues/22767)
- Berry `serial.read()` read only `n` bytes [#22835](https://github.com/arendst/Tasmota/issues/22835)
- Berry `tasmota.global.tele_period` and `tasmota.settings.tele_period` [#22865](https://github.com/arendst/Tasmota/issues/22865)
- Berry `tasmota.settings` entries for PixelType [#22912](https://github.com/arendst/Tasmota/issues/22912)
- Berry `tasmota.add_rule_once` and auto-remove rules with same pattern and id [#22900](https://github.com/arendst/Tasmota/issues/22900)
- Berry driver for M5Stack 8encoder [#22724](https://github.com/arendst/Tasmota/issues/22724)
- Berry driver for AXP2102 and M5CoreS3 [#22878](https://github.com/arendst/Tasmota/issues/22878)
- Berry driver for PN532 NFC/Mifare reader [#22899](https://github.com/arendst/Tasmota/issues/22899)
- Berry example for HeatFan WiFi Controller
- Berry WS2812 real-time Leds panel as app [#22788](https://github.com/arendst/Tasmota/issues/22788)
- Berry scroll to Leds_matrix [#22693](https://github.com/arendst/Tasmota/issues/22693)
- Berry unicode encoding to string parsing [#22713](https://github.com/arendst/Tasmota/issues/22713)
- Berry light_pixels values to `tasmota.settings` [#22762](https://github.com/arendst/Tasmota/issues/22762)
- Berry `tasmota.defer()` [#22976](https://github.com/arendst/Tasmota/issues/22976)
- Berry `bytes().appendb64()` [#22767](https://github.com/arendst/Tasmota/issues/22767)
- LVLG/HASPmota add color names from OpenHASP [#22879](https://github.com/arendst/Tasmota/issues/22879)
- LVGL `lv.set_paint_cb()` to register a callback when screen is refreshed [#22909](https://github.com/arendst/Tasmota/issues/22909)
- HASPmota support for `buttonmatrix` events [#22898](https://github.com/arendst/Tasmota/issues/22898)
- Command `JsonPP 0..7` to enable (>0) JSON Pretty Print on user interfaces and set number of indents
- Command `JsonPP <command>|backlog <command>;...` to enable JSON PP only once
### Breaking Changed
### Changed
- ESP32 Platform from 2024.12.30 to 2025.02.30, Framework (Arduino Core) from v3.1.0.241206 to v3.1.1.250203 and IDF to 5.3.2 [#22943](https://github.com/arendst/Tasmota/issues/22943)
- GPIOViewer from v1.5.6 to v1.6.1 (No functional change)
- Postpone save_data during light animation when fade is Off
- Allow negative values for AdcParam/AdcGpio INPUT, TEMP and RANGE parameters [#22809](https://github.com/arendst/Tasmota/issues/22809)
- Command `Pixels` has backwards compatible arguments fixing #22755 [#22791](https://github.com/arendst/Tasmota/issues/22791)
- ESP32 disable PSRAM check (and on restart some relay toggles) with `#define DISABLE_PSRAMCHECK true` [#21266](https://github.com/arendst/Tasmota/issues/21266)
- ESP32 Webcam resolution changes since v14.4.0 [#22901](https://github.com/arendst/Tasmota/issues/22901)
- Berry `gpio.pin_mode` frees PWM on pin
- Berry bit-shift operators to `int64` [#22709](https://github.com/arendst/Tasmota/issues/22709)
- Berry callback now passes 5 arguments instead of 4 (in line with documentation) [#22908](https://github.com/arendst/Tasmota/issues/22908)
- HASPmota use 'roboto.ttf' for automatic sizing of default font [#22697](https://github.com/arendst/Tasmota/issues/22697)
- HASPmota add 'tag' attribute for free-form JSON [#22698](https://github.com/arendst/Tasmota/issues/22698)
- HASPmota support for `tabview` [#22707](https://github.com/arendst/Tasmota/issues/22707)
### Fixed
- Shutter discovery message regression from v14.4.1 [#22730](https://github.com/arendst/Tasmota/issues/22730)
- LoraWan decoding of Dragino LDS02 and MerryIoT DW10 [#22880](https://github.com/arendst/Tasmota/issues/22880)
- ESP32 TasMesh broker MAC address all zeros [#23005](https://github.com/arendst/Tasmota/issues/23005)
- ESP32-Cx compilation fails on Windows [#22832](https://github.com/arendst/Tasmota/issues/22832)
- Wrong RMT channels for ESP32S3, now depends on `soc_caps.h` [#23021](https://github.com/arendst/Tasmota/issues/23021)
- Sonoff SPM `PowerOnState` overrules `SSPMPowerOnState` in mixed 4Relay setup with 4Relay version 1.0.0
- Webcam compilation with `define USE_WEBCAM` but without `define ENABLE_RTSPSERVER` [#22686](https://github.com/arendst/Tasmota/issues/22686)
- Berry Zigbee fix wrong attributes [#22684](https://github.com/arendst/Tasmota/issues/22684)
- Berry walrus operator [#22685](https://github.com/arendst/Tasmota/issues/22685)
- Berry parser error in rare case [#22997](https://github.com/arendst/Tasmota/issues/22997)
- LVGL updated `Antiburn.tapp` [#22699](https://github.com/arendst/Tasmota/issues/22699)
- HASPmota exception when clicking on a checkbox [#23022](https://github.com/arendst/Tasmota/issues/23022)
- Matter Air Quality sensor [#22708](https://github.com/arendst/Tasmota/issues/22708)
- Berry `bytes().asstring()` now truncates a string if buffer contains NULL [#23311](https://github.com/arendst/Tasmota/issues/23311)
- Berry string literals containing NULL are truncated [#23312](https://github.com/arendst/Tasmota/issues/23312)
### Removed

View File

@ -5,7 +5,7 @@
# Templates
Find below the available templates as of February 2025. More template information can be found in the [Tasmota Device Templates Repository](http://blakadder.github.io/templates)
Find below the available templates as of April 2025. More template information can be found in the [Tasmota Device Templates Repository](http://blakadder.github.io/templates)
## Adapter Board
```
@ -2280,6 +2280,7 @@ Athom 8Ch Inching/Self-locking 10A {"NAME":"Athom 8CH Relay Board","GPIO":[0,0,
Claudy 5V {"NAME":"CLAUDY","GPIO":[0,0,225,0,0,0,0,0,0,0,0,224,0,0],"FLAG":0,"BASE":18}
Devantech 8x16A {"NAME":"ESP32LR88","GPIO":[0,0,231,0,32,35,0,0,229,230,228,0,33,34,36,37,0,38,39,544,0,225,226,227,0,0,0,0,0,224,3232,3200,0,0,0,0],"FLAG":0,"BASE":1}
Dingtian 16 Channel {"NAME":"Dingtian DT-R008","GPIO":[1,9408,1,9440,1,1,1,1,1,9760,9729,9856,9792,1,1,1,0,1,1,1,0,1,1,1,0,0,0,0,9824,9952,1,1,1,0,0,1],"FLAG":0,"BASE":1}
Dingtian 2 Channel {"NAME":"Dingtian DT-R002","GPIO":[5536,9408,225,9440,0,0,0,0,0,9952,0,0,224,0,5600,0,0,0,0,5568,0,0,0,0,0,0,0,0,576,0,0,0,160,0,0,161],"FLAG":0,"BASE":1}
Dingtian 32 Channel {"NAME":"Dingtian DT-R008","GPIO":[1,9408,1,9440,1,1,1,1,1,9760,9731,9856,9792,1,1,1,0,1,1,1,0,1,1,1,0,0,0,0,9824,9952,1,1,1,0,0,1],"FLAG":0,"BASE":1}
Dingtian 4 Channel {"NAME":"Dingtian DT-R004","GPIO":[0,9408,225,9440,0,0,0,0,227,9952,0,0,224,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,226,162,0,163,160,0,0,161],"FLAG":0,"BASE":1}
Dingtian 8 Channel {"NAME":"Dingtian DT-R008","GPIO":[1,9408,1,9440,1,1,1,1,1,9760,9728,9856,9792,1,1,1,0,1,1,1,0,1,1,1,0,0,0,0,9824,9952,1,1,1,0,0,1],"FLAG":0,"BASE":1}
@ -2455,7 +2456,6 @@ Connect SmartHome 3 Gang Wall Switch () {"NAME":"CSH-SWTCH3","GPIO":[0,0,288,0,
Csmart US-B2 {"NAME":"Csmart US-B2","GPIO":[0,544,0,33,32,0,0,0,0,225,224,0,0,0],"FLAG":0,"BASE":18}
Delock WLAN EASY-USB {"NAME":"Delock 11828","GPIO":[0,0,0,32,0,0,0,0,0,576,224,0,0,0],"FLAG":0,"BASE":53}
Deta 1 Gang {"NAME":"Deta 1G Switch","GPIO":[0,0,0,0,544,0,0,0,0,224,0,0,64,0],"FLAG":0,"BASE":18}
Deta 2 Gang {"NAME":"DETA 2G Switch","GPIO":[0,0,0,0,544,0,0,0,65,224,225,0,64,0],"FLAG":0,"BASE":18}
Deta 3 Gang {"NAME":"DETA 3G Switch","GPIO":[544,0,0,66,65,224,0,0,226,0,225,0,64,0],"FLAG":0,"BASE":18}
Deta 4 Gang {"NAME":"Deta 4G Switch","GPIO":[576,0,0,34,33,224,0,0,226,35,225,227,32,0],"FLAG":0,"BASE":18}
DETA Mechanism {"NAME":"Deta 6014HA","GPIO":[0,0,0,0,0,0,0,0,320,0,32,0,224,0],"FLAG":0,"BASE":18}

View File

@ -168,6 +168,12 @@ void TasmotaSerial::Esp32Begin(void) {
if (m_speed <= 9600) {
// At 9600, 10 chars are ~10ms
uart_set_rx_full_threshold(m_uart, 10);
} else {
// At 19200, 120 chars are ~60ms
// At 76800, 120 chars are ~15ms
uart_set_rx_full_threshold(m_uart, 120);
}
/*
} else if (m_speed < 115200) {
// At 19200, 120 chars are ~60ms
// At 76800, 120 chars are ~15ms
@ -180,6 +186,7 @@ void TasmotaSerial::Esp32Begin(void) {
// At even higher speeds set 75% of the buffer
uart_set_rx_full_threshold(m_uart, serial_buffer_size * 3 / 4);
}
*/
// For bitrate below 115200, set the Rx time out to 6 chars instead of the default 10
if (m_speed < 115200) {
// At 76800 the timeout is ~1ms

View File

@ -0,0 +1,128 @@
/**
* Base64 encoding and decoding of strings. Uses '+' for 62, '/' for 63, '=' for padding
*/
#include "base64.hpp"
unsigned char binary_to_base64(unsigned char v) {
// Capital letters - 'A' is ascii 65 and base64 0
if(v < 26) return v + 'A';
// Lowercase letters - 'a' is ascii 97 and base64 26
if(v < 52) return v + 71;
// Digits - '0' is ascii 48 and base64 52
if(v < 62) return v - 4;
// '+' is ascii 43 and base64 62
if(v == 62) return '+';
// '/' is ascii 47 and base64 63
if(v == 63) return '/';
return 64;
}
unsigned char base64_to_binary(unsigned char c) {
// Capital letters - 'A' is ascii 65 and base64 0
if('A' <= c && c <= 'Z') return c - 'A';
// Lowercase letters - 'a' is ascii 97 and base64 26
if('a' <= c && c <= 'z') return c - 71;
// Digits - '0' is ascii 48 and base64 52
if('0' <= c && c <= '9') return c + 4;
// '+' is ascii 43 and base64 62
if(c == '+') return 62;
// '/' is ascii 47 and base64 63
if(c == '/') return 63;
return 255;
}
unsigned int encode_base64_length(unsigned int input_length) {
return (input_length + 2)/3*4;
}
unsigned int decode_base64_length(unsigned char input[]) {
unsigned char *start = input;
while(base64_to_binary(input[0]) < 64) {
++input;
}
unsigned int input_length = input - start;
unsigned int output_length = input_length/4*3;
switch(input_length % 4) {
default: return output_length;
case 2: return output_length + 1;
case 3: return output_length + 2;
}
}
unsigned int encode_base64(unsigned char input[], unsigned int input_length, unsigned char output[]) {
unsigned int full_sets = input_length/3;
// While there are still full sets of 24 bits...
for(unsigned int i = 0; i < full_sets; ++i) {
output[0] = binary_to_base64( input[0] >> 2);
output[1] = binary_to_base64((input[0] & 0x03) << 4 | input[1] >> 4);
output[2] = binary_to_base64((input[1] & 0x0F) << 2 | input[2] >> 6);
output[3] = binary_to_base64( input[2] & 0x3F);
input += 3;
output += 4;
}
switch(input_length % 3) {
case 0:
output[0] = '\0';
break;
case 1:
output[0] = binary_to_base64( input[0] >> 2);
output[1] = binary_to_base64((input[0] & 0x03) << 4);
output[2] = '=';
output[3] = '=';
output[4] = '\0';
break;
case 2:
output[0] = binary_to_base64( input[0] >> 2);
output[1] = binary_to_base64((input[0] & 0x03) << 4 | input[1] >> 4);
output[2] = binary_to_base64((input[1] & 0x0F) << 2);
output[3] = '=';
output[4] = '\0';
break;
}
return encode_base64_length(input_length);
}
unsigned int decode_base64(unsigned char input[], unsigned char output[]) {
unsigned int output_length = decode_base64_length(input);
// While there are still full sets of 24 bits...
for(unsigned int i = 2; i < output_length; i += 3) {
output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4;
output[1] = base64_to_binary(input[1]) << 4 | base64_to_binary(input[2]) >> 2;
output[2] = base64_to_binary(input[2]) << 6 | base64_to_binary(input[3]);
input += 4;
output += 3;
}
switch(output_length % 3) {
case 1:
output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4;
break;
case 2:
output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4;
output[1] = base64_to_binary(input[1]) << 4 | base64_to_binary(input[2]) >> 2;
break;
}
return output_length;
}

View File

@ -69,127 +69,4 @@ unsigned int encode_base64(unsigned char input[], unsigned int input_length, uns
*/
unsigned int decode_base64(unsigned char input[], unsigned char output[]);
unsigned char binary_to_base64(unsigned char v) {
// Capital letters - 'A' is ascii 65 and base64 0
if(v < 26) return v + 'A';
// Lowercase letters - 'a' is ascii 97 and base64 26
if(v < 52) return v + 71;
// Digits - '0' is ascii 48 and base64 52
if(v < 62) return v - 4;
// '+' is ascii 43 and base64 62
if(v == 62) return '+';
// '/' is ascii 47 and base64 63
if(v == 63) return '/';
return 64;
}
unsigned char base64_to_binary(unsigned char c) {
// Capital letters - 'A' is ascii 65 and base64 0
if('A' <= c && c <= 'Z') return c - 'A';
// Lowercase letters - 'a' is ascii 97 and base64 26
if('a' <= c && c <= 'z') return c - 71;
// Digits - '0' is ascii 48 and base64 52
if('0' <= c && c <= '9') return c + 4;
// '+' is ascii 43 and base64 62
if(c == '+') return 62;
// '/' is ascii 47 and base64 63
if(c == '/') return 63;
return 255;
}
unsigned int encode_base64_length(unsigned int input_length) {
return (input_length + 2)/3*4;
}
unsigned int decode_base64_length(unsigned char input[]) {
unsigned char *start = input;
while(base64_to_binary(input[0]) < 64) {
++input;
}
unsigned int input_length = input - start;
unsigned int output_length = input_length/4*3;
switch(input_length % 4) {
default: return output_length;
case 2: return output_length + 1;
case 3: return output_length + 2;
}
}
unsigned int encode_base64(unsigned char input[], unsigned int input_length, unsigned char output[]) {
unsigned int full_sets = input_length/3;
// While there are still full sets of 24 bits...
for(unsigned int i = 0; i < full_sets; ++i) {
output[0] = binary_to_base64( input[0] >> 2);
output[1] = binary_to_base64((input[0] & 0x03) << 4 | input[1] >> 4);
output[2] = binary_to_base64((input[1] & 0x0F) << 2 | input[2] >> 6);
output[3] = binary_to_base64( input[2] & 0x3F);
input += 3;
output += 4;
}
switch(input_length % 3) {
case 0:
output[0] = '\0';
break;
case 1:
output[0] = binary_to_base64( input[0] >> 2);
output[1] = binary_to_base64((input[0] & 0x03) << 4);
output[2] = '=';
output[3] = '=';
output[4] = '\0';
break;
case 2:
output[0] = binary_to_base64( input[0] >> 2);
output[1] = binary_to_base64((input[0] & 0x03) << 4 | input[1] >> 4);
output[2] = binary_to_base64((input[1] & 0x0F) << 2);
output[3] = '=';
output[4] = '\0';
break;
}
return encode_base64_length(input_length);
}
unsigned int decode_base64(unsigned char input[], unsigned char output[]) {
unsigned int output_length = decode_base64_length(input);
// While there are still full sets of 24 bits...
for(unsigned int i = 2; i < output_length; i += 3) {
output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4;
output[1] = base64_to_binary(input[1]) << 4 | base64_to_binary(input[2]) >> 2;
output[2] = base64_to_binary(input[2]) << 6 | base64_to_binary(input[3]);
input += 4;
output += 3;
}
switch(output_length % 3) {
case 1:
output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4;
break;
case 2:
output[0] = base64_to_binary(input[0]) << 2 | base64_to_binary(input[1]) >> 4;
output[1] = base64_to_binary(input[1]) << 4 | base64_to_binary(input[2]) >> 2;
break;
}
return output_length;
}
#endif // ifndef

View File

@ -9,11 +9,7 @@
},
"version": "2.6.7",
"frameworks": "arduino",
"platforms": "*",
"dependencies": [
{
"name": "SPI"
}
]
"libCompatMode": "strict",
"platforms": ["espressif8266"]
}

View File

@ -11,6 +11,7 @@
"url": "https://github.com/arendst/Tasmota/lib/lib_basic/TasmotaLED"
},
"frameworks": "arduino",
"libCompatMode": "strict",
"platforms": [
"espressif32"
]

View File

@ -97,7 +97,7 @@ enum uColorType { uCOLOR_BW, uCOLOR_COLOR };
#define UDISP_WHITE 0xFFFF /* 255, 255, 255 */
#define UDISP_ORANGE 0xFD20 /* 255, 165, 0 */
#define UDISP_GREENYELLOW 0xAFE5 /* 173, 255, 47 */
#define UDISP_PINK 0xF81F
#define UDISP_PINK 0xFc18 /* 255, 128, 192 */
#ifdef ESP8266
#define PIN_OUT_SET 0x60000304

View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2016 Frank
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,56 @@
FastCRC
=======
Fast CRC Arduino library
Up to 30 times faster than crc16.h (_avr_libc)
- uses the on-chip hardware for Teensy 3.0 / 3.1 / 3.2 / 3.5 / 3.6
- uses fast table-algorithms for other chips
List of supported CRC calculations:
-
7 BIT:
CRC7
(poly=0x09 init=0x00 refin=false refout=false xorout=0x00 check=0x75)
MultiMediaCard interface
8 BIT:
SMBUS
(poly=0x07 init=0x00 refin=false refout=false xorout=0x00 check=0xf4)
MAXIM
(poly=0x31 init=0x00 refin=true refout=true xorout=0x00 check=0xa1)
16 BIT:
KERMIT (Alias CRC-16/CCITT, CRC-16/CCITT-TRUE, CRC-CCITT)
(poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 check=0x2189
Attention: sometimes you'll find byteswapped presentation of result in other implementations)
CCITT-FALSE
(poly=0x1021 init=0xffff refin=false refout=false xorout=0x0000 check=0x29b1)
MCRF4XX
(poly=0x1021 init=0xffff refin=true refout=true xorout=0x0000 check=0x6f91)
MODBUS
(poly=0x8005 init=0xffff refin=true refout=true xorout=0x0000 check=0x4b37)
XMODEM (Alias ZMODEM, CRC-16/ACORN)
(poly=0x1021 init=0x0000 refin=false refout=false xorout=0x0000 check=0x31c3)
X25 (Alias CRC-16/IBM-SDLC, CRC-16/ISO-HDLC, CRC-B)
(poly=0x1021 init=0xffff refin=true refout=true xorout=0xffff check=0x906e)
32 BIT:
CRC32, CRC-32/ADCCP, PKZIP, ETHERNET, 802.3
(poly=0x04c11db7 init=0xffffffff refin=true refout=true xorout=0xffffffff check=0xcbf43926)
CKSUM, CRC-32/POSIX
(poly=0x04c11db7 init=0x00000000 refin=false refout=false xorout=0xffffffff check=0x765e7680)

View File

@ -0,0 +1,59 @@
#######################################
# Syntax Coloring Map For FastCRC
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
FastCRC7 KEYWORD1
FastCRC8 KEYWORD1
FastCRC14 KEYWORD1
FastCRC16 KEYWORD1
FastCRC32 KEYWORD1
CRC7 KEYWORD1
CRC8 KEYWORD1
CRC14 KEYWORD1
CRC16 KEYWORD1
CRC32 KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
crc7 KEYWORD2
crc7_upd KEYWORD2
ccitt KEYWORD2
ccitt_upd KEYWORD2
kermit KEYWORD2
kermit_upd KEYWORD2
mcrf4xx KEYWORD2
mcrf4xx_upd KEYWORD2
modbus KEYWORD2
modbus_upd KEYWORD2
xmodem KEYWORD2
xmodem_upd KEYWORD2
x25 KEYWORD2
x25_upd KEYWORD2
update KEYWORD2
update_upd KEYWORD2
generic KEYWORD2
crc32 KEYWORD2
crc32_upd KEYWORD2
cksum KEYWORD2
cksum_upd KEYWORD2
darc KEYWORD2
darc_upd KEYWORD2
gsm KEYWORD2
gsm_upd KEYWORD2
eloran KEYWORD2
eloran_upd KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
CRC_FLAG_NOREFLECT LITERAL1
CRC_FLAG_REFLECT LITERAL1
CRC_FLAG_XOR LITERAL1
CRC_FLAG_NOREFLECT_8 LITERAL1
CRC_FLAG_REFLECT_SWAP LITERAL1

View File

@ -0,0 +1,26 @@
{
"name": "FastCRC",
"keywords": "CRC7, CRC8, CRC16, CRC32",
"description": "Fast CRC routines for Arduino and PC (Teensy 3.x: CRC in hardware)",
"exclude": [
"examples",
"examples_PC"
],
"repository":
{
"type": "git",
"url": "https://github.com/FrankBoesing/FastCRC"
},
"authors":
[
{
"name": "Frank Bösing",
"email": "f.boesing@gmx.de",
"url": "https://github.com/FrankBoesing/FastCRC",
"maintainer": true
}
],
"version": "1.44",
"frameworks": "arduino",
"platforms": "*"
}

View File

@ -0,0 +1,10 @@
name=FastCRC
version=1.44
author=Frank Bösing
maintainer=Frank Boesing<f.boesing@gmx.de>
sentence=Fast CRC routines
paragraph=
category=Data Processing
url=https://github.com/FrankBoesing/FastCRC
architectures=*
#dot_a_linkage=true

View File

@ -0,0 +1,189 @@
/* FastCRC library code is placed under the MIT license
* Copyright (c) 2014 - 2021 Frank Bösing
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
// Teensy 3.0, Teensy 3.1:
// See K20P64M72SF1RM.pdf (Kinetis), Pages 638 - 641 for documentation of CRC Device
// See KINETIS_4N30D.pdf for Errata (Errata ID 2776)
//
// So, ALL HW-calculations are done as 32 bit.
//
//
//
// Thanks to:
// - Catalogue of parametrised CRC algorithms, CRC RevEng
// http://reveng.sourceforge.net/crc-catalogue/
//
// - Danjel McGougan (CRC-Table-Generator)
//
// Set this to 0 for smaller 32BIT-CRC-Tables:
#if !defined(CRC_BIGTABLES)
#define CRC_BIGTABLES 1
#endif
#if !defined(FastCRC_h)
#define FastCRC_h
#if defined(ARDUINO)
#include <Arduino.h>
#endif
#include <inttypes.h>
// ================= DEFINES ===================
#if defined(KINETISK)
#define CRC_SW 0
#define CRC_FLAG_NOREFLECT (((1<<31) | (1<<30)) | ((0<<29) | (0<<28))) //refin=false refout=false
#define CRC_FLAG_REFLECT (((1<<31) | (0<<30)) | ((1<<29) | (0<<28))) //Reflect in- and outgoing bytes (refin=true refout=true)
#define CRC_FLAG_XOR (1<<26) //Perform XOR on result
#define CRC_FLAG_NOREFLECT_8 (0) //For 8-Bit CRC
#define CRC_FLAG_REFLECT_SWAP (((1<<31) | (0<<30)) | ((0<<29) | (1<<28))) //For 16-Bit CRC (byteswap)
#else
#define CRC_SW 1
#endif
// ================= 7-BIT CRC ===================
class FastCRC7
{
public:
FastCRC7();
uint8_t crc7(const uint8_t *data, const size_t datalen); // (MultiMediaCard interface)
uint8_t crc7_upd(const uint8_t *data, const size_t datalen); // Call for subsequent calculations with previous seed.
#if !CRC_SW
uint8_t generic(const uint8_t polyom, const uint8_t seed, const uint32_t flags, const uint8_t *data, const size_t datalen); //Not available in non-hw-variant (not T3.x)
#endif
private:
#if CRC_SW
uint8_t seed;
#else
uint8_t update(const uint8_t *data, const size_t datalen);
#endif
};
// ================= 8-BIT CRC ===================
class FastCRC8
{
public:
FastCRC8();
uint8_t smbus(const uint8_t *data, const size_t datalen); // Alias CRC-8
uint8_t maxim(const uint8_t *data, const size_t datalen); // Equivalent to _crc_ibutton_update() in crc16.h from avr_libc
uint8_t smbus_upd(const uint8_t *data, size_t datalen); // Call for subsequent calculations with previous seed.
uint8_t maxim_upd(const uint8_t *data, size_t datalen); // Call for subsequent calculations with previous seed.
#if !CRC_SW
uint8_t generic(const uint8_t polyom, const uint8_t seed, const uint32_t flags, const uint8_t *data, const size_t datalen); //Not available in non-hw-variant (not T3.x)
#endif
private:
#if CRC_SW
uint8_t seed;
#else
uint8_t update(const uint8_t *data, const size_t datalen);
#endif
};
// ================= 14-BIT CRC ===================
class FastCRC14
{
public:
#if !CRC_SW //NO Software-implemenation so far
FastCRC14();
uint16_t darc(const uint8_t *data, const size_t datalen);
uint16_t gsm(const uint8_t *data, const size_t datalen);
uint16_t eloran(const uint8_t *data, const size_t datalen);
uint16_t ft4(const uint8_t *data, const size_t datalen);
uint16_t darc_upd(const uint8_t *data, size_t len);
uint16_t gsm_upd(const uint8_t *data, size_t len);
uint16_t eloran_upd(const uint8_t *data, size_t len);
uint16_t ft4_upd(const uint8_t *data, size_t len);
#endif
#if !CRC_SW
uint16_t generic(const uint16_t polyom, const uint16_t seed, const uint32_t flags, const uint8_t *data, const size_t datalen); //Not available in non-hw-variant (not T3.x)
#endif
private:
#if CRC_SW
uint16_t seed;
#else
uint16_t update(const uint8_t *data, const size_t datalen);
#endif
};
// ================= 16-BIT CRC ===================
class FastCRC16
{
public:
FastCRC16();
uint16_t ccitt(const uint8_t *data, const size_t datalen); // Alias "false CCITT"
uint16_t mcrf4xx(const uint8_t *data,const size_t datalen); // Equivalent to _crc_ccitt_update() in crc16.h from avr_libc
uint16_t kermit(const uint8_t *data, const size_t datalen); // Alias CRC-16/CCITT, CRC-16/CCITT-TRUE, CRC-CCITT
uint16_t modbus(const uint8_t *data, const size_t datalen); // Equivalent to _crc_16_update() in crc16.h from avr_libc
uint16_t xmodem(const uint8_t *data, const size_t datalen); // Alias ZMODEM, CRC-16/ACORN
uint16_t x25(const uint8_t *data, const size_t datalen); // Alias CRC-16/IBM-SDLC, CRC-16/ISO-HDLC, CRC-B
uint16_t ccitt_upd(const uint8_t *data, size_t len); // Call for subsequent calculations with previous seed
uint16_t mcrf4xx_upd(const uint8_t *data, size_t len); // Call for subsequent calculations with previous seed
uint16_t kermit_upd(const uint8_t *data, size_t len); // Call for subsequent calculations with previous seed
uint16_t modbus_upd(const uint8_t *data, size_t len); // Call for subsequent calculations with previous seed
uint16_t xmodem_upd(const uint8_t *data, size_t len); // Call for subsequent calculations with previous seed
uint16_t x25_upd(const uint8_t *data, size_t len); // Call for subsequent calculations with previous seed
#if !CRC_SW
uint16_t generic(const uint16_t polyom, const uint16_t seed, const uint32_t flags, const uint8_t *data, const size_t datalen); //Not available in non-hw-variant (not T3.x)
#endif
private:
#if CRC_SW
uint16_t seed;
#else
uint16_t update(const uint8_t *data, const size_t datalen);
#endif
};
// ================= 32-BIT CRC ===================
class FastCRC32
{
public:
FastCRC32();
uint32_t crc32(const uint8_t *data, const size_t datalen); // Alias CRC-32/ADCCP, PKZIP, Ethernet, 802.3
uint32_t cksum(const uint8_t *data, const size_t datalen); // Alias CRC-32/POSIX
uint32_t crc32_upd(const uint8_t *data, size_t len); // Call for subsequent calculations with previous seed
uint32_t cksum_upd(const uint8_t *data, size_t len); // Call for subsequent calculations with previous seed
#if !CRC_SW
uint32_t generic(const uint32_t polyom, const uint32_t seed, const uint32_t flags, const uint8_t *data, const size_t datalen); //Not available in non-hw-variant (not T3.x)
#endif
private:
#if CRC_SW
uint32_t seed;
#else
uint32_t update(const uint8_t *data, const size_t datalen);
#endif
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,567 @@
/* FastCRC library code is placed under the MIT license
* Copyright (c) 2014 - 2021 Frank Bösing
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
//
// HW-calculations are 32BIT
//
// Thanks to:
// - Catalogue of parametrised CRC algorithms, CRC RevEng
// http://reveng.sourceforge.net/crc-catalogue/
//
// - Danjel McGougan (CRC-Table-Generator)
//
#if defined(ARDUINO)
#include <Arduino.h>
#endif
#if defined(KINETISK)
#include "mk20dx128.h"
#include "FastCRC.h"
// ===============================================
typedef struct {
union {
uint32_t CRC; //CRC Data register
struct {
uint16_t CRC16;
uint16_t CRC16_1;
};
struct {
uint8_t CRC8;
uint8_t CRC8_1;
uint8_t CRC8_2;
uint8_t CRC8_3;
};
};
uint32_t GPOLY; //CRC Polynomial register
uint32_t CTRL; //CRC Control register
} CRC_T;
static volatile CRC_T * const rCRC = (CRC_T *)0x40032000;
#define CRC_CTRL_WAS 25 // Write CRC Data Register As Seed(1) / Data(0)
#define CRC_CTRL_TCRC 24 // Width of CRC protocol (0=16 BIT, 1=32 BIT)
#define CRC_CTRL_TOTR1 29 // TOTR[1]
// ================= 7-BIT CRC ===================
/** Constructor
* Enables CRC-clock
*/
FastCRC7::FastCRC7(){
SIM_SCGC6 |= SIM_SCGC6_CRC;
}
/** CRC 7
* MultiMediaCard interface
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
uint8_t FastCRC7::crc7(const uint8_t *data, const size_t datalen)
{
// poly=0x09 init=0x00 refin=false refout=false xorout=0x00 check=0x75
return (generic(0x09, 0, CRC_FLAG_NOREFLECT, data, datalen));
}
/** Update
* Call for subsequent calculations with previous seed
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
uint8_t FastCRC7::update(const uint8_t *data, const size_t datalen)
{
const uint8_t *src = data;
const uint8_t *target = src + datalen;
while (((uintptr_t)src & 0x03) != 0 && (src < target)) {
rCRC->CRC8_3 = *src++; //Write 8 BIT
}
while (src <= target-4) {
rCRC->CRC = *( uint32_t *)src; //Write 32 BIT
src += 4;
}
while (src < target) {
rCRC->CRC8_3 = *src++; //Write 8 Bit
}
//TODO: Check handling of CRC_CTRL_TOTR1 for other CRC7s
/*
if (rCRC->CTRL & (1<<CRC_CTRL_TOTR1))
return rCRC->CRC8 >> 1;
else
*/
return rCRC->CRC8_3 >> 1;
}
/** generic function for all 7-Bit CRCs
* @param polynom Polynom
* @param seed Seed
* @param flags Flags
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
uint8_t FastCRC7::generic(const uint8_t polynom, const uint8_t seed, const uint32_t flags, const uint8_t *data,const size_t datalen)
{
rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC) | (1<<CRC_CTRL_WAS); // 32Bit Mode, Prepare to write seed(25)
rCRC->GPOLY = ((uint32_t)polynom)<<(24 + 1); // Set polynom
rCRC->CRC = ((uint32_t)seed<<(24 + 1)); // Write seed
rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC); // Clear WAS Bit - prepare to write data
return update(data, datalen);
}
uint8_t FastCRC7::crc7_upd(const uint8_t *data, size_t datalen){return update(data, datalen);}
// ================= 8-BIT CRC ===================
/** Constructor
* Enables CRC-clock
*/
FastCRC8::FastCRC8(){
SIM_SCGC6 |= SIM_SCGC6_CRC;
}
/** SMBUS CRC
* aka CRC-8
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
uint8_t FastCRC8::smbus(const uint8_t *data, const size_t datalen)
{
// poly=0x07 init=0x00 refin=false refout=false xorout=0x00 check=0xf4
return generic(0x07, 0, CRC_FLAG_NOREFLECT, data, datalen);
}
/** MAXIM 8-Bit CRC
* equivalent to _crc_ibutton_update() in crc16.h from avr_libc
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
uint8_t FastCRC8::maxim(const uint8_t *data, const size_t datalen)
{
// poly=0x31 init=0x00 refin=true refout=true xorout=0x00 check=0xa1
return generic(0x31, 0, CRC_FLAG_REFLECT, data, datalen);
}
/** Update
* Call for subsequent calculations with previous seed
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
uint8_t FastCRC8::update(const uint8_t *data, const size_t datalen)
{
const uint8_t *src = data;
const uint8_t *target = src + datalen;
while (((uintptr_t)src & 0x03) != 0 && (src < target)) {
rCRC->CRC8_3 = *src++; //Write 8 BIT
}
while (src <= target-4) {
rCRC->CRC = *( uint32_t *)src; //Write 32 BIT
src += 4;
}
while (src < target) {
rCRC->CRC8_3 = *src++; //Write 8 Bit
}
if (rCRC->CTRL & (1<<CRC_CTRL_TOTR1))
return rCRC->CRC8;
else
return rCRC->CRC8_3;
}
/** generic function for all 8-Bit CRCs
* @param polynom Polynom
* @param seed Seed
* @param flags Flags
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
uint8_t FastCRC8::generic(const uint8_t polynom, const uint8_t seed, const uint32_t flags, const uint8_t *data,const size_t datalen)
{
rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC) | (1<<CRC_CTRL_WAS); // 32Bit Mode, Prepare to write seed(25)
rCRC->GPOLY = ((uint32_t)polynom)<<24; // Set polynom
rCRC->CRC = ((uint32_t)seed<<24); // Write seed
rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC); // Clear WAS Bit - prepare to write data
return update(data, datalen);
}
uint8_t FastCRC8::smbus_upd(const uint8_t *data, size_t datalen){return update(data, datalen);}
uint8_t FastCRC8::maxim_upd(const uint8_t *data, size_t datalen){return update(data, datalen);}
// ================= 14-BIT CRC ===================
/** Constructor
* Enables CRC-clock
*/
FastCRC14::FastCRC14(){
SIM_SCGC6 |= SIM_SCGC6_CRC;
}
/** CRC-14/DARC
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
uint16_t FastCRC14::darc(const uint8_t *data,const size_t datalen)
{
// poly=0x0805 init=0x0000 refin=true refout=true xorout=0x0000 check=0x082d residue=0x0000
return generic(0x0805, 0x0000, CRC_FLAG_REFLECT, data, datalen);
}
/** CRC-14/GSM
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
uint16_t FastCRC14::gsm(const uint8_t *data,const size_t datalen)
{
// poly=0x202d init=0x0000 refin=false refout=false xorout=0x3fff check=0x30ae residue=0x031e
return generic(0x202d, 0x0000, CRC_FLAG_NOREFLECT | CRC_FLAG_XOR, data, datalen);
}
/** CRC-14/ELORAN
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
uint16_t FastCRC14::eloran(const uint8_t *data,const size_t datalen)
{
// poly=0x60b1 init=0x0000 refin=false refout=false xorout=0x0000 check=0x38d1
return generic(0x60b1, 0x0, CRC_FLAG_NOREFLECT , data, datalen);
}
/** CRC-14/ft4 : TODO
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
/*
uint16_t FastCRC14::ft4(const uint8_t *data,const size_t datalen)
{
return generic(, , , data, datalen);
}
*/
/** Update
* Call for subsequent calculations with previous seed
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
uint16_t FastCRC14::update(const uint8_t *data, const size_t datalen)
{
const uint8_t *src = data;
const uint8_t *target = src + datalen;
while (((uintptr_t)src & 0x03) !=0 && (src < target)) {
rCRC->CRC8_3 = *src++; //Write 8 BIT
}
while (src <= target-4) {
rCRC->CRC = *( uint32_t *)src; //Write 32 BIT
src += 4;
}
while (src < target) {
rCRC->CRC8_3 = *src++; //Write 8 Bit
}
if (rCRC->CTRL & (1<<CRC_CTRL_TOTR1))
return rCRC->CRC16;
else
return rCRC->CRC >> (32 - 14);
}
/** generic function for all 14-Bit CRCs
* @param polynom Polynom
* @param seed Seed
* @param flags Flags
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
uint16_t FastCRC14::generic(const uint16_t polynom, const uint16_t seed, const uint32_t flags, const uint8_t *data, const size_t datalen)
{
rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC) | (1<<CRC_CTRL_WAS);// 32-Bit Mode, prepare to write seed(25)
rCRC->GPOLY = ((uint32_t)polynom) << (32 - 14); // set polynom
rCRC->CRC = ((uint32_t)seed << (32 - 14) ); // this is the seed
rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC); // Clear WAS Bit - prepare to write data
return update(data, datalen);
}
uint16_t FastCRC14::darc_upd(const uint8_t *data, size_t len) {return update(data, len);}
uint16_t FastCRC14::gsm_upd(const uint8_t *data, size_t len) {return update(data, len);}
uint16_t FastCRC14::eloran_upd(const uint8_t *data, size_t len) {return update(data, len);}
//uint16_t FastCRC14::ft4(const uint8_t *data, size_t len) {return update(data, len);}
// ================= 16-BIT CRC ===================
/** Constructor
* Enables CRC-clock
*/
FastCRC16::FastCRC16(){
SIM_SCGC6 |= SIM_SCGC6_CRC;
}
/** CCITT
* Alias "false CCITT"
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
uint16_t FastCRC16::ccitt(const uint8_t *data,const size_t datalen)
{
// poly=0x1021 init=0xffff refin=false refout=false xorout=0x0000 check=0x29b1
return generic(0x1021, 0XFFFF, CRC_FLAG_NOREFLECT, data, datalen);
}
/** MCRF4XX
* equivalent to _crc_ccitt_update() in crc16.h from avr_libc
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
uint16_t FastCRC16::mcrf4xx(const uint8_t *data,const size_t datalen)
{
// poly=0x1021 init=0xffff refin=true refout=true xorout=0x0000 check=0x6f91
return generic(0x1021, 0XFFFF, CRC_FLAG_REFLECT , data, datalen);
}
/** MODBUS
* equivalent to _crc_16_update() in crc16.h from avr_libc
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
uint16_t FastCRC16::modbus(const uint8_t *data, const size_t datalen)
{
// poly=0x8005 init=0xffff refin=true refout=true xorout=0x0000 check=0x4b37
return generic(0x8005, 0XFFFF, CRC_FLAG_REFLECT, data, datalen);
}
/** KERMIT
* Alias CRC-16/CCITT, CRC-16/CCITT-TRUE, CRC-CCITT
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
uint16_t FastCRC16::kermit(const uint8_t *data, const size_t datalen)
{
// poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 check=0x2189
// sometimes byteswapped presentation of result
return generic(0x1021, 0x00, CRC_FLAG_REFLECT, data, datalen);
}
/** XMODEM
* Alias ZMODEM, CRC-16/ACORN
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
uint16_t FastCRC16::xmodem(const uint8_t *data, const size_t datalen)
{
//width=16 poly=0x1021 init=0x0000 refin=false refout=false xorout=0x0000 check=0x31c3
return generic(0x1021, 0, CRC_FLAG_NOREFLECT, data, datalen);
}
/** X25
* Alias CRC-16/IBM-SDLC, CRC-16/ISO-HDLC, CRC-B
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
uint16_t FastCRC16::x25(const uint8_t *data, const size_t datalen)
{
// poly=0x1021 init=0xffff refin=true refout=true xorout=0xffff check=0x906e
return generic(0x1021, 0XFFFF, CRC_FLAG_REFLECT | CRC_FLAG_XOR, data, datalen);
}
/** Update
* Call for subsequent calculations with previous seed
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
uint16_t FastCRC16::update(const uint8_t *data, const size_t datalen)
{
const uint8_t *src = data;
const uint8_t *target = src + datalen;
while (((uintptr_t)src & 0x03) !=0 && (src < target)) {
rCRC->CRC8_3 = *src++; //Write 8 BIT
}
while (src <= target-4) {
rCRC->CRC = *( uint32_t *)src; //Write 32 BIT
src += 4;
}
while (src < target) {
rCRC->CRC8_3 = *src++; //Write 8 Bit
}
if (rCRC->CTRL & (1<<CRC_CTRL_TOTR1))
return rCRC->CRC16;
else
return rCRC->CRC16_1;
}
/** generic function for all 16-Bit CRCs
* @param polynom Polynom
* @param seed Seed
* @param flags Flags
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
uint16_t FastCRC16::generic(const uint16_t polynom, const uint16_t seed, const uint32_t flags, const uint8_t *data, const size_t datalen)
{
rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC) | (1<<CRC_CTRL_WAS);// 32-Bit Mode, prepare to write seed(25)
rCRC->GPOLY = ((uint32_t)polynom)<<16; // set polynom
rCRC->CRC = ((uint32_t)seed<<16); // this is the seed
rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC); // Clear WAS Bit - prepare to write data
return update(data, datalen);
}
uint16_t FastCRC16::ccitt_upd(const uint8_t *data, size_t len) {return update(data, len);}
uint16_t FastCRC16::mcrf4xx_upd(const uint8_t *data, size_t len){return update(data, len);}
uint16_t FastCRC16::kermit_upd(const uint8_t *data, size_t len) {return update(data, len);}
uint16_t FastCRC16::modbus_upd(const uint8_t *data, size_t len) {return update(data, len);}
uint16_t FastCRC16::xmodem_upd(const uint8_t *data, size_t len) {return update(data, len);}
uint16_t FastCRC16::x25_upd(const uint8_t *data, size_t len) {return update(data, len);}
// ================= 32-BIT CRC ===================
/** Constructor
* Enables CRC-clock
*/
FastCRC32::FastCRC32(){
SIM_SCGC6 |= SIM_SCGC6_CRC;
}
/** CRC32
* Alias CRC-32/ADCCP, PKZIP, Ethernet, 802.3
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
uint32_t FastCRC32::crc32(const uint8_t *data, const size_t datalen)
{
// poly=0x04c11db7 init=0xffffffff refin=true refout=true xorout=0xffffffff check=0xcbf43926
return generic(0x04C11DB7L, 0XFFFFFFFFL, CRC_FLAG_REFLECT | CRC_FLAG_XOR, data, datalen);
}
/** CKSUM
* Alias CRC-32/POSIX
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
uint32_t FastCRC32::cksum(const uint8_t *data, const size_t datalen)
{
// width=32 poly=0x04c11db7 init=0x00000000 refin=false refout=false xorout=0xffffffff check=0x765e7680
return generic(0x04C11DB7L, 0, CRC_FLAG_NOREFLECT | CRC_FLAG_XOR, data, datalen);
}
/** Update
* Call for subsequent calculations with previous seed
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
//#pragma GCC diagnostic ignored "-Wpointer-arith"
uint32_t FastCRC32::update(const uint8_t *data, const size_t datalen)
{
const uint8_t *src = data;
const uint8_t *target = src + datalen;
while (((uintptr_t)src & 0x03) != 0 && (src < target)) {
rCRC->CRC8_3 = *src++; //Write 8 BIT
}
while (src <= target-4) {
rCRC->CRC = *( uint32_t *)src; //Write 32 BIT
src += 4;
}
while (src < target) {
rCRC->CRC8_3 = *src++; //Write 8 Bit
}
return rCRC->CRC;
}
/** generic function for all 32-Bit CRCs
* @param polynom Polynom
* @param seed Seed
* @param flags Flags
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
uint32_t FastCRC32::generic(const uint32_t polynom, const uint32_t seed, const uint32_t flags, const uint8_t *data, const size_t datalen)
{
rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC) | (1<<CRC_CTRL_WAS); // 32Bit Mode, prepare to write seed(25)
rCRC->GPOLY = polynom; // Set polynom
rCRC->CRC = seed; // This is the seed
rCRC->CTRL = flags | (1<<CRC_CTRL_TCRC); // Clear WAS Bit - prepare to write data
return update(data, datalen);
}
uint32_t FastCRC32::crc32_upd(const uint8_t *data, size_t len){return update(data, len);}
uint32_t FastCRC32::cksum_upd(const uint8_t *data, size_t len){return update(data, len);}
#endif // #if defined(KINETISK)

View File

@ -0,0 +1,541 @@
/* FastCRC library code is placed under the MIT license
* Copyright (c) 2014 - 2021 Frank Bösing
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
//
// Thanks to:
// - Catalogue of parametrised CRC algorithms, CRC RevEng
// http://reveng.sourceforge.net/crc-catalogue/
//
// - Danjel McGougan (CRC-Table-Generator)
//
#if defined(ARDUINO)
#include <Arduino.h>
#endif
#if !defined(KINETISK)
#if !defined(ARDUINO)
#define PROGMEM
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
#define pgm_read_word(addr) ({ \
typeof(addr) _addr = (addr); \
*(const unsigned short *)(_addr); \
})
#define pgm_read_dword(addr) ({ \
typeof(addr) _addr = (addr); \
*(const unsigned long *)(_addr); \
})
#endif
#include "FastCRC.h"
#include "FastCRC_tables.h"
static inline
uint32_t REV16( uint32_t value)
{
return (value >> 8) | ((value & 0xff) << 8);
}
static inline
uint32_t REV32( uint32_t value)
{
value = (value >> 16) | ((value & 0xffff) << 16);
return ((value >> 8) & 0xff00ff) | ((value & 0xff00ff) << 8);
}
// ================= 7-BIT CRC ===================
/** Constructor
*/
FastCRC7::FastCRC7(){}
/** SMBUS CRC
* aka CRC-8
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
uint8_t FastCRC7::crc7_upd(const uint8_t *data, size_t datalen)
{
uint8_t crc = seed;
if (datalen) do {
crc = pgm_read_byte(&crc_table_crc7[crc ^ *data]);
data++;
} while (--datalen);
seed = crc;
return crc >> 1;
}
uint8_t FastCRC7::crc7(const uint8_t *data, const size_t datalen)
{
// poly=0x09 init=0x00 refin=false refout=false xorout=0x00 check=0x75
seed = 0x00;
return crc7_upd(data, datalen);
}
// ================= 8-BIT CRC ===================
/** Constructor
*/
FastCRC8::FastCRC8(){}
/** SMBUS CRC
* aka CRC-8
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
uint8_t FastCRC8::smbus_upd(const uint8_t *data, size_t datalen)
{
uint8_t crc = seed;
if (datalen) do {
crc = pgm_read_byte(&crc_table_smbus[crc ^ *data]);
data++;
} while (--datalen);
seed = crc;
return crc;
}
uint8_t FastCRC8::smbus(const uint8_t *data, const size_t datalen)
{
// poly=0x07 init=0x00 refin=false refout=false xorout=0x00 check=0xf4
seed = 0x00;
return smbus_upd(data, datalen);
}
/** MAXIM 8-Bit CRC
* equivalent to _crc_ibutton_update() in crc16.h from avr_libc
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
uint8_t FastCRC8::maxim_upd(const uint8_t *data, size_t datalen)
{
uint8_t crc = seed;
if (datalen) do {
crc = pgm_read_byte(&crc_table_maxim[crc ^ *data]);
data++;
} while (--datalen);
seed = crc;
return crc;
}
uint8_t FastCRC8::maxim(const uint8_t *data, const size_t datalen)
{
// poly=0x31 init=0x00 refin=true refout=true xorout=0x00 check=0xa1
seed = 0x00;
return maxim_upd(data, datalen);
}
// ================= 16-BIT CRC ===================
/** Constructor
*/
FastCRC16::FastCRC16(){}
#define crc_n4(crc, data, table) crc ^= data; \
crc = pgm_read_word(&table[(crc & 0xff) + 0x300]) ^ \
pgm_read_word(&table[((crc >> 8) & 0xff) + 0x200]) ^ \
pgm_read_word(&table[((data >> 16) & 0xff) + 0x100]) ^ \
pgm_read_word(&table[data >> 24]);
/** CCITT
* Alias "false CCITT"
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
uint16_t FastCRC16::ccitt_upd(const uint8_t *data, size_t len)
{
uint16_t crc = seed;
while (((uintptr_t)data & 3) && len) {
crc = (crc >> 8) ^ pgm_read_word(&crc_table_ccitt[(crc & 0xff) ^ *data++]);
len--;
}
while (len >= 16) {
len -= 16;
crc_n4(crc, ((uint32_t *)data)[0], crc_table_ccitt);
crc_n4(crc, ((uint32_t *)data)[1], crc_table_ccitt);
crc_n4(crc, ((uint32_t *)data)[2], crc_table_ccitt);
crc_n4(crc, ((uint32_t *)data)[3], crc_table_ccitt);
data += 16;
}
while (len--) {
crc = (crc >> 8) ^ pgm_read_word(&crc_table_ccitt[(crc & 0xff) ^ *data++]);
}
seed = crc;
crc = REV16(crc);
return crc;
}
uint16_t FastCRC16::ccitt(const uint8_t *data,const size_t datalen)
{
// poly=0x1021 init=0xffff refin=false refout=false xorout=0x0000 check=0x29b1
seed = 0xffff;
return ccitt_upd(data, datalen);
}
/** MCRF4XX
* equivalent to _crc_ccitt_update() in crc16.h from avr_libc
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
uint16_t FastCRC16::mcrf4xx_upd(const uint8_t *data, size_t len)
{
uint16_t crc = seed;
while (((uintptr_t)data & 3) && len) {
crc = (crc >> 8) ^ pgm_read_word(&crc_table_mcrf4xx[(crc & 0xff) ^ *data++]);
len--;
}
while (len >= 16) {
len -= 16;
crc_n4(crc, ((uint32_t *)data)[0], crc_table_mcrf4xx);
crc_n4(crc, ((uint32_t *)data)[1], crc_table_mcrf4xx);
crc_n4(crc, ((uint32_t *)data)[2], crc_table_mcrf4xx);
crc_n4(crc, ((uint32_t *)data)[3], crc_table_mcrf4xx);
data += 16;
}
while (len--) {
crc = (crc >> 8) ^ pgm_read_word(&crc_table_mcrf4xx[(crc & 0xff) ^ *data++]);
}
seed = crc;
return crc;
}
uint16_t FastCRC16::mcrf4xx(const uint8_t *data,const size_t datalen)
{
// poly=0x1021 init=0xffff refin=true refout=true xorout=0x0000 check=0x6f91
seed = 0xffff;
return mcrf4xx_upd(data, datalen);
}
/** MODBUS
* equivalent to _crc_16_update() in crc16.h from avr_libc
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
uint16_t FastCRC16::modbus_upd(const uint8_t *data, size_t len)
{
uint16_t crc = seed;
while (((uintptr_t)data & 3) && len) {
crc = (crc >> 8) ^ pgm_read_word(&crc_table_modbus[(crc & 0xff) ^ *data++]);
len--;
}
while (len >= 16) {
len -= 16;
crc_n4(crc, ((uint32_t *)data)[0], crc_table_modbus);
crc_n4(crc, ((uint32_t *)data)[1], crc_table_modbus);
crc_n4(crc, ((uint32_t *)data)[2], crc_table_modbus);
crc_n4(crc, ((uint32_t *)data)[3], crc_table_modbus);
data += 16;
}
while (len--) {
crc = (crc >> 8) ^ pgm_read_word(&crc_table_modbus[(crc & 0xff) ^ *data++]);
}
seed = crc;
return crc;
}
uint16_t FastCRC16::modbus(const uint8_t *data, const size_t datalen)
{
// poly=0x8005 init=0xffff refin=true refout=true xorout=0x0000 check=0x4b37
seed = 0xffff;
return modbus_upd(data, datalen);
}
/** KERMIT
* Alias CRC-16/CCITT, CRC-16/CCITT-TRUE, CRC-CCITT
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
uint16_t FastCRC16::kermit_upd(const uint8_t *data, size_t len)
{
uint16_t crc = seed;
while (((uintptr_t)data & 3) && len) {
crc = (crc >> 8) ^ pgm_read_word(&crc_table_kermit[(crc & 0xff) ^ *data++]);
len--;
}
while (len >= 16) {
len -= 16;
crc_n4(crc, ((uint32_t *)data)[0], crc_table_kermit);
crc_n4(crc, ((uint32_t *)data)[1], crc_table_kermit);
crc_n4(crc, ((uint32_t *)data)[2], crc_table_kermit);
crc_n4(crc, ((uint32_t *)data)[3], crc_table_kermit);
data += 16;
}
while (len--) {
crc = (crc >> 8) ^ pgm_read_word(&crc_table_kermit[(crc & 0xff) ^ *data++]);
}
seed = crc;
return crc;
}
uint16_t FastCRC16::kermit(const uint8_t *data, const size_t datalen)
{
// poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 check=0x2189
// sometimes byteswapped presentation of result
seed = 0x0000;
return kermit_upd(data, datalen);
}
/** XMODEM
* Alias ZMODEM, CRC-16/ACORN
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
uint16_t FastCRC16::xmodem_upd(const uint8_t *data, size_t len)
{
uint16_t crc = seed;
while (((uintptr_t)data & 3) && len) {
crc = (crc >> 8) ^ pgm_read_word(&crc_table_xmodem[(crc & 0xff) ^ *data++]);
len--;
}
while (len >= 16) {
len -= 16;
crc_n4(crc, ((uint32_t *)data)[0], crc_table_xmodem);
crc_n4(crc, ((uint32_t *)data)[1], crc_table_xmodem);
crc_n4(crc, ((uint32_t *)data)[2], crc_table_xmodem);
crc_n4(crc, ((uint32_t *)data)[3], crc_table_xmodem);
data += 16;
}
while (len--) {
crc = (crc >> 8) ^ pgm_read_word(&crc_table_xmodem[(crc & 0xff) ^ *data++]);
}
seed = crc;
crc = REV16(crc);
return crc;
}
uint16_t FastCRC16::xmodem(const uint8_t *data, const size_t datalen)
{
//width=16 poly=0x1021 init=0x0000 refin=false refout=false xorout=0x0000 check=0x31c3
seed = 0x0000;
return xmodem_upd(data, datalen);
}
/** X25
* Alias CRC-16/IBM-SDLC, CRC-16/ISO-HDLC, CRC-B
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
uint16_t FastCRC16::x25_upd(const uint8_t *data, size_t len)
{
uint16_t crc = seed;
while (((uintptr_t)data & 3) && len) {
crc = (crc >> 8) ^ pgm_read_word(&crc_table_x25[(crc & 0xff) ^ *data++]);
len--;
}
while (len >= 16) {
len -= 16;
crc_n4(crc, ((uint32_t *)data)[0], crc_table_x25);
crc_n4(crc, ((uint32_t *)data)[1], crc_table_x25);
crc_n4(crc, ((uint32_t *)data)[2], crc_table_x25);
crc_n4(crc, ((uint32_t *)data)[3], crc_table_x25);
data += 16;
}
while (len--) {
crc = (crc >> 8) ^ pgm_read_word(&crc_table_x25[(crc & 0xff) ^ *data++]);
}
seed = crc;
crc = ~crc;
return crc;
}
uint16_t FastCRC16::x25(const uint8_t *data, const size_t datalen)
{
// poly=0x1021 init=0xffff refin=true refout=true xorout=0xffff check=0x906e
seed = 0xffff;
return x25_upd(data, datalen);
}
// ================= 32-BIT CRC ===================
/** Constructor
*/
FastCRC32::FastCRC32(){}
#define crc_n4d(crc, data, table) crc ^= data; \
crc = pgm_read_dword(&table[(crc & 0xff) + 0x300]) ^ \
pgm_read_dword(&table[((crc >> 8) & 0xff) + 0x200]) ^ \
pgm_read_dword(&table[((crc >> 16) & 0xff) + 0x100]) ^ \
pgm_read_dword(&table[(crc >> 24) & 0xff]);
#define crcsm_n4d(crc, data, table) crc ^= data; \
crc = (crc >> 8) ^ pgm_read_dword(&table[crc & 0xff]); \
crc = (crc >> 8) ^ pgm_read_dword(&table[crc & 0xff]); \
crc = (crc >> 8) ^ pgm_read_dword(&table[crc & 0xff]); \
crc = (crc >> 8) ^ pgm_read_dword(&table[crc & 0xff]);
/** CRC32
* Alias CRC-32/ADCCP, PKZIP, Ethernet, 802.3
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
#if CRC_BIGTABLES
#define CRC_TABLE_CRC32 crc_table_crc32_big
#else
#define CRC_TABLE_CRC32 crc_table_crc32
#endif
uint32_t FastCRC32::crc32_upd(const uint8_t *data, size_t len)
{
uint32_t crc = seed;
while (((uintptr_t)data & 3) && len) {
crc = (crc >> 8) ^ pgm_read_dword(&CRC_TABLE_CRC32[(crc & 0xff) ^ *data++]);
len--;
}
while (len >= 16) {
len -= 16;
#if CRC_BIGTABLES
crc_n4d(crc, ((uint32_t *)data)[0], CRC_TABLE_CRC32);
crc_n4d(crc, ((uint32_t *)data)[1], CRC_TABLE_CRC32);
crc_n4d(crc, ((uint32_t *)data)[2], CRC_TABLE_CRC32);
crc_n4d(crc, ((uint32_t *)data)[3], CRC_TABLE_CRC32);
#else
crcsm_n4d(crc, ((uint32_t *)data)[0], CRC_TABLE_CRC32);
crcsm_n4d(crc, ((uint32_t *)data)[1], CRC_TABLE_CRC32);
crcsm_n4d(crc, ((uint32_t *)data)[2], CRC_TABLE_CRC32);
crcsm_n4d(crc, ((uint32_t *)data)[3], CRC_TABLE_CRC32);
#endif
data += 16;
}
while (len--) {
crc = (crc >> 8) ^ pgm_read_dword(&CRC_TABLE_CRC32[(crc & 0xff) ^ *data++]);
}
seed = crc;
crc = ~crc;
return crc;
}
uint32_t FastCRC32::crc32(const uint8_t *data, const size_t datalen)
{
// poly=0x04c11db7 init=0xffffffff refin=true refout=true xorout=0xffffffff check=0xcbf43926
seed = 0xffffffff;
return crc32_upd(data, datalen);
}
/** CKSUM
* Alias CRC-32/POSIX
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
#if CRC_BIGTABLES
#define CRC_TABLE_CKSUM crc_table_cksum_big
#else
#define CRC_TABLE_CKSUM crc_table_cksum
#endif
uint32_t FastCRC32::cksum_upd(const uint8_t *data, size_t len)
{
uint32_t crc = seed;
while (((uintptr_t)data & 3) && len) {
crc = (crc >> 8) ^ pgm_read_dword(&CRC_TABLE_CKSUM[(crc & 0xff) ^ *data++]);
len--;
}
while (len >= 16) {
len -= 16;
#if CRC_BIGTABLES
crc_n4d(crc, ((uint32_t *)data)[0], CRC_TABLE_CKSUM);
crc_n4d(crc, ((uint32_t *)data)[1], CRC_TABLE_CKSUM);
crc_n4d(crc, ((uint32_t *)data)[2], CRC_TABLE_CKSUM);
crc_n4d(crc, ((uint32_t *)data)[3], CRC_TABLE_CKSUM);
#else
crcsm_n4d(crc, ((uint32_t *)data)[0], CRC_TABLE_CKSUM);
crcsm_n4d(crc, ((uint32_t *)data)[1], CRC_TABLE_CKSUM);
crcsm_n4d(crc, ((uint32_t *)data)[2], CRC_TABLE_CKSUM);
crcsm_n4d(crc, ((uint32_t *)data)[3], CRC_TABLE_CKSUM);
#endif
data += 16;
}
while (len--) {
crc = (crc >> 8) ^ pgm_read_dword(&CRC_TABLE_CKSUM[(crc & 0xff) ^ *data++]);
}
seed = crc;
crc = ~REV32(crc);
return crc;
}
uint32_t FastCRC32::cksum(const uint8_t *data, const size_t datalen)
{
// width=32 poly=0x04c11db7 init=0x00000000 refin=false refout=false xorout=0xffffffff check=0x765e7680
seed = 0x00;
return cksum_upd(data, datalen);
}
#endif // #if !defined(KINETISK)

View File

@ -6,7 +6,7 @@
#include "DataParsers.h"
#include "DataParser.h"
#include "Cosem.h"
#include "ntohll.h"
#include "ntohll_ams.h"
#define BUF_SIZE_HAN (1280)

View File

@ -1,5 +1,5 @@
#include "ntohll.h"
#include "ntohll_ams.h"
uint64_t ntohll(uint64_t x) {
uint64_t ntohll_ams(uint64_t x) {
return (((uint64_t)ntohl((uint32_t)x)) << 32) + ntohl(x >> 32);
}

View File

@ -3,6 +3,6 @@
#include "lwip/def.h"
uint64_t ntohll(uint64_t x);
uint64_t ntohll_ams(uint64_t x);
#endif

View File

@ -59,13 +59,14 @@
// Number of maximum high/Low changes per packet.
// We can handle up to 36 bit * 2 H/L changes per bit + 2 for sync
// Для keeloq нужно увеличить RCSWITCH_MAX_CHANGES до 23+1+66*2+1=157
#define RCSWITCH_MAX_CHANGES 75 // default 75 - longest protocol that requires this buffer size is 38/nexus
//#define RCSWITCH_MAX_CHANGES 75 // default 75 - longest protocol that requires this buffer size is 38/nexus
#define RCSWITCH_MAX_CHANGES 131 // default 75 - Supports 64 too
// separationLimit: minimum microseconds between received codes, closer codes are ignored.
// according to discussion on issue #14 it might be more suitable to set the separation
// limit to the same time as the 'low' part of the sync signal for the current protocol.
// should be set to the minimum value of pulselength * the sync signal
#define RCSWITCH_SEPARATION_LIMIT 4100
#define RCSWITCH_SEPARATION_LIMIT 3600
class RCSwitch {

View File

@ -44,7 +44,7 @@ uint32_t *stack_thunk_light_save = NULL; /* Saved A1 while in BearSSL */
uint32_t stack_thunk_light_refcnt = 0;
//#define _stackSize (5600/4)
#if defined(USE_MQTT_AWS_IOT) || defined(USE_MQTT_AWS_IOT_LIGHT) || defined(USE_MQTT_AZURE_IOT)
#if defined(USE_MQTT_CLIENT_CERT) || defined(USE_MQTT_AWS_IOT_LIGHT) || defined(USE_MQTT_AZURE_IOT)
#define _stackSize (5300/4) // using a light version of bearssl we can save 300 bytes
#else
#define _stackSize (4800/4) // no private key, we can reduce a little, max observed 4300

View File

@ -303,7 +303,9 @@ int WiFiClientSecure_light::connect(IPAddress ip, uint16_t port, int32_t timeout
setLastError(ERR_TCP_CONNECT);
return 0;
}
return _connectSSL(_domain.isEmpty() ? nullptr : _domain.c_str());
bool success = _connectSSL(_domain.isEmpty() ? nullptr : _domain.c_str());
if (!success) { stop(); }
return success;
}
#else // ESP32
int WiFiClientSecure_light::connect(IPAddress ip, uint16_t port) {
@ -313,7 +315,9 @@ int WiFiClientSecure_light::connect(IPAddress ip, uint16_t port) {
setLastError(ERR_TCP_CONNECT);
return 0;
}
return _connectSSL(_domain.isEmpty() ? nullptr : _domain.c_str());
bool success = _connectSSL(_domain.isEmpty() ? nullptr : _domain.c_str());
if (!success) { stop(); }
return success;
}
#endif
@ -570,6 +574,7 @@ int WiFiClientSecure_light::_run_until(unsigned target, bool blocking) {
if (((int32_t)(millis() - (t + this->_loopTimeout)) >= 0)){
DEBUG_BSSL("_run_until: Timeout\n");
setLastError(ERR_TLS_TIMEOUT);
return -1;
}
@ -994,16 +999,16 @@ bool WiFiClientSecure_light::_connectSSL(const char* hostName) {
br_ssl_engine_set_buffers_bidi(_eng, _iobuf_in.get(), _iobuf_in_size, _iobuf_out.get(), _iobuf_out_size);
// ============================================================
// allocate Private key if needed, only if USE_MQTT_AWS_IOT
// allocate Private key if needed, only if USE_MQTT_CLIENT_CERT
LOG_HEAP_SIZE("_connectSSL before PrivKey allocation");
#ifdef USE_MQTT_AWS_IOT
#if defined(USE_MQTT_CLIENT_CERT)
// ============================================================
// Set the EC Private Key, only USE_MQTT_AWS_IOT
// Set the EC Private Key, only USE_MQTT_CLIENT_CERT
// limited to P256 curve
br_ssl_client_set_single_ec(_sc.get(), _chain_P, 1,
_sk_ec_P, _allowed_usages,
_cert_issuer_key_type, &br_ec_p256_m15, br_ecdsa_sign_asn1_get_default());
#endif // USE_MQTT_AWS_IOT
#endif // USE_MQTT_CLIENT_CERT
// ============================================================
// Start TLS connection, ALL

View File

@ -137,7 +137,7 @@ class WiFiClientSecure_light : public WiFiClient {
}
private:
uint32_t _loopTimeout=5000;
uint32_t _loopTimeout=10000;
void _clear();
bool _ctx_present;
std::shared_ptr<br_ssl_client_context> _sc;
@ -192,7 +192,8 @@ class WiFiClientSecure_light : public WiFiClient {
#define ERR_CANT_RESOLVE_IP -1001
#define ERR_TCP_CONNECT -1002
// #define ERR_MISSING_EC_KEY -1003 // deprecated, AWS IoT is not called if the private key is not present
#define ERR_MISSING_CA -1004
// #define ERR_MISSING_CA -1004 // deprecated
#define ERR_TLS_TIMEOUT -1005
// For reference, BearSSL error codes:
// #define BR_ERR_OK 0

View File

@ -40,6 +40,17 @@ be_extern_native_module(gpio);
be_extern_native_module(display);
be_extern_native_module(energy);
be_extern_native_module(webserver);
#ifdef USE_BERRY_HTTPSERVER
be_extern_native_module(httpserver);
#ifdef USE_BERRY_WSSERVER
be_extern_native_module(wsserver);
#endif // USE_BERRY_WSSERVER
#ifdef USE_BERRY_WEBFILES
be_extern_native_module(webfiles);
#endif // USE_BERRY_WEBFILES
#endif // USE_BERRY_HTTPSERVER
be_extern_native_module(flash);
be_extern_native_module(path);
be_extern_native_module(unishox);
@ -170,6 +181,15 @@ BERRY_LOCAL const bntvmodule_t* const be_module_table[] = {
#ifdef USE_WEBSERVER
&be_native_module(webserver),
#endif // USE_WEBSERVER
#ifdef USE_BERRY_HTTPSERVER
&be_native_module(httpserver),
#ifdef USE_BERRY_WSSERVER
&be_native_module(wsserver),
#endif // USE_BERRY_WSSERVER
#ifdef USE_BERRY_WEBFILES
&be_native_module(webfiles),
#endif // USE_BERRY_WEBFILES
#endif // USE_BERRY_HTTPSERVER
#ifdef USE_ZIGBEE
&be_native_module(zigbee),
&be_native_module(matter_zigbee),
@ -283,7 +303,6 @@ BERRY_LOCAL bclass_array be_class_table = {
&be_native_class(AXP2102),
#endif // USE_I2C
&be_native_class(md5),
#ifdef USE_WEBCLIENT
&be_native_class(udp),
&be_native_class(webclient),
&be_native_class(tcpclient),
@ -291,7 +310,6 @@ BERRY_LOCAL bclass_array be_class_table = {
#ifdef USE_BERRY_DEBUG
&be_native_class(webserver_async), // include only when USE_BERRY_DEBUG is enabled
#endif // USE_BERRY_DEBUG
#endif // USE_WEBCLIENT
#ifdef USE_BERRY_TCPSERVER
&be_native_class(tcpserver),
#endif // USE_BERRY_TCPSERVER

View File

@ -64,6 +64,25 @@ int be_re_compile(bvm *vm) {
be_raise(vm, "type_error", NULL);
}
// Native functions be_const_func()
// Berry: `re.compilebytes(pattern:string) -> instance(bytes)`
int be_re_compilebytes(bvm *vm) {
int32_t argc = be_top(vm); // Get the number of arguments
if (argc >= 1 && be_isstring(vm, 1)) {
const char * regex_str = be_tostring(vm, 1);
int sz = re1_5_sizecode(regex_str);
if (sz < 0) {
be_raise(vm, "internal_error", "error in regex");
}
be_pushbytes(vm, NULL, sizeof(ByteProg) + sz);
ByteProg *code = (ByteProg*) be_tobytes(vm, -1, NULL);
re1_5_compilecode(code, regex_str);
be_return(vm);
}
be_raise(vm, "type_error", NULL);
}
// pushes either a list if matched, else `nil`
// return index of next offset, or -1 if not found
const char *be_re_match_search_run(bvm *vm, ByteProg *code, const char *hay, bbool is_anchored, bbool size_only) {
@ -99,9 +118,10 @@ const char *be_re_match_search_run(bvm *vm, ByteProg *code, const char *hay, bbo
int be_re_match_search(bvm *vm, bbool is_anchored, bbool size_only) {
int32_t argc = be_top(vm); // Get the number of arguments
if (argc >= 2 && be_isstring(vm, 1) && be_isstring(vm, 2)) {
const char * regex_str = be_tostring(vm, 1);
if (argc >= 2 && (be_isstring(vm, 1) || be_isbytes(vm, 1)) && be_isstring(vm, 2)) {
const char * hay = be_tostring(vm, 2);
ByteProg *code = NULL;
int32_t offset = 0;
if (argc >= 3 && be_isint(vm, 3)) {
offset = be_toint(vm, 3);
@ -111,22 +131,31 @@ int be_re_match_search(bvm *vm, bbool is_anchored, bbool size_only) {
if (offset >= hay_len) { be_return_nil(vm); } // any match of empty string returns nil, this catches implicitly when hay_len == 0
hay += offset; // shift to offset
int sz = re1_5_sizecode(regex_str);
if (sz < 0) {
be_raise(vm, "internal_error", "error in regex");
}
if (be_isstring(vm, 1)) {
const char * regex_str = be_tostring(vm, 1);
int sz = re1_5_sizecode(regex_str);
if (sz < 0) {
be_raise(vm, "internal_error", "error in regex");
}
ByteProg *code = be_os_malloc(sizeof(ByteProg) + sz);
if (code == NULL) {
be_throw(vm, BE_MALLOC_FAIL); /* lack of heap space */
}
int ret = re1_5_compilecode(code, regex_str);
if (ret != 0) {
be_os_free(code);
be_raise(vm, "internal_error", "error in regex");
code = be_os_malloc(sizeof(ByteProg) + sz);
if (code == NULL) {
be_throw(vm, BE_MALLOC_FAIL); /* lack of heap space */
}
int ret = re1_5_compilecode(code, regex_str);
if (ret != 0) {
be_os_free(code);
be_raise(vm, "internal_error", "error in regex");
}
} else {
code = (ByteProg *) be_tobytes(vm, 1, NULL);
}
// do the match
be_re_match_search_run(vm, code, hay, is_anchored, size_only);
be_os_free(code);
// cleanup
if (be_isstring(vm, 1)) {
be_os_free(code);
}
be_return(vm);
}
be_raise(vm, "type_error", NULL);
@ -134,26 +163,32 @@ int be_re_match_search(bvm *vm, bbool is_anchored, bbool size_only) {
int be_re_match_search_all(bvm *vm, bbool is_anchored) {
int32_t argc = be_top(vm); // Get the number of arguments
if (argc >= 2 && be_isstring(vm, 1) && be_isstring(vm, 2)) {
const char * regex_str = be_tostring(vm, 1);
if (argc >= 2 && (be_isstring(vm, 1) || be_isbytes(vm, 1)) && be_isstring(vm, 2)) {
const char * hay = be_tostring(vm, 2);
ByteProg *code = NULL;
int limit = -1;
if (argc >= 3) {
limit = be_toint(vm, 3);
}
int sz = re1_5_sizecode(regex_str);
if (sz < 0) {
be_raise(vm, "internal_error", "error in regex");
}
ByteProg *code = be_os_malloc(sizeof(ByteProg) + sz);
if (code == NULL) {
be_throw(vm, BE_MALLOC_FAIL); /* lack of heap space */
}
int ret = re1_5_compilecode(code, regex_str);
if (ret != 0) {
be_os_free(code);
be_raise(vm, "internal_error", "error in regex");
if (be_isstring(vm, 1)) {
const char * regex_str = be_tostring(vm, 1);
int sz = re1_5_sizecode(regex_str);
if (sz < 0) {
be_raise(vm, "internal_error", "error in regex");
}
code = be_os_malloc(sizeof(ByteProg) + sz);
if (code == NULL) {
be_throw(vm, BE_MALLOC_FAIL); /* lack of heap space */
}
int ret = re1_5_compilecode(code, regex_str);
if (ret != 0) {
be_os_free(code);
be_raise(vm, "internal_error", "error in regex");
}
} else {
code = (ByteProg *) be_tobytes(vm, 1, NULL);
}
be_newobject(vm, "list");
@ -165,7 +200,10 @@ int be_re_match_search_all(bvm *vm, bbool is_anchored) {
be_pop(vm, 1);
}
be_pop(vm, 1);
be_os_free(code);
// cleanup
if (be_isstring(vm, 1)) {
be_os_free(code);
}
be_return(vm);
}
be_raise(vm, "type_error", NULL);
@ -193,6 +231,21 @@ int be_re_search_all(bvm *vm) {
return be_re_match_search_all(vm, bfalse);
}
// Berry: `re.dump(b:bytes) -> nil``
int be_re_dump(bvm *vm) {
#ifdef USE_BERRY_DEBUG
int32_t argc = be_top(vm); // Get the number of arguments
if (argc >= 1 && be_isbytes(vm, 1)) {
ByteProg *code = (ByteProg*) be_tobytes(vm, 1, NULL);
re1_5_dumpcode(code);
be_return_nil(vm);
}
be_raise(vm, "type_error", NULL);
#else // USE_BERRY_DEBUG
be_return_nil(vm);
#endif
}
// Berry: `re_pattern.search(s:string [, offset:int]) -> list(string)`
int re_pattern_search(bvm *vm) {
int32_t argc = be_top(vm); // Get the number of arguments
@ -329,29 +382,36 @@ int re_pattern_split(bvm *vm) {
// Berry: `re.split(pattern:string, s:string [, split_limit:int]) -> list(string)`
int be_re_split(bvm *vm) {
int32_t argc = be_top(vm); // Get the number of arguments
if (argc >= 2 && be_isstring(vm, 1) && be_isstring(vm, 2)) {
const char * regex_str = be_tostring(vm, 1);
if (argc >= 2 && (be_isstring(vm, 1) || be_isbytes(vm, 1)) && be_isstring(vm, 2)) {
const char * hay = be_tostring(vm, 2);
ByteProg *code = NULL;
int split_limit = -1;
if (argc >= 3) {
split_limit = be_toint(vm, 3);
}
int sz = re1_5_sizecode(regex_str);
if (sz < 0) {
be_raise(vm, "internal_error", "error in regex");
}
if (be_isstring(vm, 1)) {
const char * regex_str = be_tostring(vm, 1);
int sz = re1_5_sizecode(regex_str);
if (sz < 0) {
be_raise(vm, "internal_error", "error in regex");
}
ByteProg *code = be_os_malloc(sizeof(ByteProg) + sz);
if (code == NULL) {
be_throw(vm, BE_MALLOC_FAIL); /* lack of heap space */
code = be_os_malloc(sizeof(ByteProg) + sz);
if (code == NULL) {
be_throw(vm, BE_MALLOC_FAIL); /* lack of heap space */
}
int ret = re1_5_compilecode(code, regex_str);
if (ret != 0) {
be_os_free(code);
be_raise(vm, "internal_error", "error in regex");
}
} else {
code = (ByteProg *) be_tobytes(vm, 1, NULL);
}
int ret = re1_5_compilecode(code, regex_str);
if (ret != 0) {
int ret = re_pattern_split_run(vm, code, hay, split_limit);
if (be_isstring(vm, 1)) {
be_os_free(code);
be_raise(vm, "internal_error", "error in regex");
}
ret = re_pattern_split_run(vm, code, hay, split_limit);
be_os_free(code);
return ret;
}
be_raise(vm, "type_error", NULL);
@ -363,12 +423,14 @@ int be_re_split(bvm *vm) {
@const_object_info_begin
module re (scope: global) {
compile, func(be_re_compile)
compilebytes, func(be_re_compilebytes)
search, func(be_re_search)
searchall, func(be_re_search_all)
match, func(be_re_match)
match2, func(be_re_match2)
matchall, func(be_re_match_all)
split, func(be_re_split)
dump, func(be_re_dump)
}
@const_object_info_end

View File

@ -405,7 +405,7 @@ int main(int argc, char *argv[])
{
int res;
bvm *vm = be_vm_new(); /* create a virtual machine instance */
be_set_ctype_func_hanlder(vm, be_call_ctype_func);
be_set_ctype_func_handler(vm, be_call_ctype_func);
res = analysis_args(vm, argc, argv);
be_vm_delete(vm); /* free all objects and vm */
return res;

View File

@ -82,8 +82,8 @@ BERRY_API void be_regfunc(bvm *vm, const char *name, bntvfunc f)
bstring *s = be_newstr(vm, name);
#if !BE_USE_PRECOMPILED_OBJECT
int idx = be_builtin_find(vm, s);
be_assert(idx == -1);
if (idx == -1) { /* new function */
be_assert(idx < 0);
if (idx < 0) { /* new function */
idx = be_builtin_new(vm, s);
#else
int idx = be_global_find(vm, s);
@ -102,8 +102,8 @@ BERRY_API void be_regclass(bvm *vm, const char *name, const bnfuncinfo *lib)
bstring *s = be_newstr(vm, name);
#if !BE_USE_PRECOMPILED_OBJECT
int idx = be_builtin_find(vm, s);
be_assert(idx == -1);
if (idx == -1) { /* new function */
be_assert(idx < 0);
if (idx < 0) { /* new function */
idx = be_builtin_new(vm, s);
#else
int idx = be_global_find(vm, s);
@ -599,7 +599,7 @@ BERRY_API bbool be_getglobal(bvm *vm, const char *name)
{
int idx = be_global_find(vm, be_newstr(vm, name));
bvalue *top = be_incrtop(vm);
if (idx > -1) {
if (idx >= 0) {
*top = *be_global_var(vm, idx);
return btrue;
}

View File

@ -258,6 +258,26 @@ static size_t buf_add2_be(buf_impl* attr, const uint16_t data) // append 16 bits
return attr->len;
}
static size_t buf_add3_le(buf_impl* attr, const uint32_t data) // append 32 bits value
{
if (attr->len < attr->size - 2) { // do we have room for 4 bytes
attr->bufptr[attr->len++] = data;
attr->bufptr[attr->len++] = data >> 8;
attr->bufptr[attr->len++] = data >> 16;
}
return attr->len;
}
size_t buf_add3_be(buf_impl* attr, const uint32_t data) // append 32 bits value
{
if (attr->len < attr->size - 2) { // do we have room for 4 bytes
attr->bufptr[attr->len++] = data >> 16;
attr->bufptr[attr->len++] = data >> 8;
attr->bufptr[attr->len++] = data;
}
return attr->len;
}
static size_t buf_add4_le(buf_impl* attr, const uint32_t data) // append 32 bits value
{
if (attr->len < attr->size - 3) { // do we have room for 4 bytes
@ -786,7 +806,8 @@ static int m_asstring(bvm *vm)
{
buf_impl attr = bytes_check_data(vm, 0);
check_ptr(vm, &attr);
be_pushnstring(vm, (const char*) attr.bufptr, attr.len);
size_t safe_len = strnlen((const char*) attr.bufptr, attr.len);
be_pushnstring(vm, (const char*) attr.bufptr, safe_len);
be_return(vm);
}
@ -838,10 +859,12 @@ static int m_add(bvm *vm)
case -1: /* fallback below */
case 1: buf_add1(&attr, v); break;
case 2: buf_add2_le(&attr, v); break;
case 3: buf_add3_le(&attr, v); break;
case 4: buf_add4_le(&attr, v); break;
case -2: buf_add2_be(&attr, v); break;
case -3: buf_add3_be(&attr, v); break;
case -4: buf_add4_be(&attr, v); break;
default: be_raise(vm, "type_error", "size must be -4, -2, -1, 0, 1, 2 or 4.");
default: be_raise(vm, "type_error", "size must be between -4 and 4.");
}
be_pop(vm, argc - 1);
m_write_attributes(vm, 1, &attr); /* update attributes */

View File

@ -354,9 +354,6 @@ const bntvmodule_t be_native_module(_module) = { \
#else
// #define be_define_const_bytes(_name, ...) \
// const uint8_t be_const_bin_##_name[] = { __VA_ARGS__ }
#define be_define_const_str_weak(_name, _s, _len) \
const bcstring be_const_str_##_name = { \
NULL, \

View File

@ -234,7 +234,9 @@ int be_nfunc_open(bvm *vm)
{ "flush", i_flush },
{ "close", i_close },
{ "deinit", i_close },
#if BE_USE_BYTECODE_SAVER
{ "savecode", i_savecode },
#endif
{ NULL, NULL }
};
fname = argc >= 1 && be_isstring(vm, 1) ? be_tostring(vm, 1) : NULL;

View File

@ -27,10 +27,14 @@ static void dump_map_keys(bvm *vm, bmap *map)
bmapiter iter = be_map_iter();
while ((node = be_map_next(map, &iter)) != NULL) {
if (var_isstr(&node->key)) {
bstring *s = var_tostr(&node->key);
be_pushstring(vm, str(s));
be_data_push(vm, -2);
be_pop(vm, 1);
/* check if the global was not undefined/removed */
int idx = var_toidx(&node->value);
if (idx >= 0) { /* the key is present in global, and the index is valid */
bstring *s = var_tostr(&node->key);
be_pushstring(vm, str(s));
be_data_push(vm, -2);
be_pop(vm, 1);
}
}
}
}
@ -49,7 +53,7 @@ static int m_contains(bvm *vm)
if (top >= 1 && be_isstring(vm, 1)) {
const char * name = be_tostring(vm, 1);
int idx = be_global_find(vm, be_newstr(vm, name));
be_pushbool(vm, idx > -1);
be_pushbool(vm, idx >= 0);
be_return(vm);
}
be_return_nil(vm);
@ -76,12 +80,25 @@ static int m_setglobal(bvm *vm)
be_return_nil(vm);
}
/* Remove a global variable from global scope */
/* Internally the global name cannot be removed but it's value is replaced with BE_NONE */
/* and global function pretend that BE_NONE is equivalent to the name being absent */
static int m_undef(bvm *vm)
{
int top = be_top(vm);
if (top >= 1 && be_isstring(vm, 1)) {
be_global_undef(vm, be_newstr(vm, be_tostring(vm, 1)));
}
be_return_nil(vm);
}
#if !BE_USE_PRECOMPILED_OBJECT
be_native_module_attr_table(global) {
be_native_module_function("()", m_globals),
be_native_module_function("contains", m_contains),
be_native_module_function("member", m_findglobal),
be_native_module_function("setmember", m_setglobal),
be_native_module_function("undef", m_undef),
};
be_define_native_module(global, NULL);
@ -92,6 +109,7 @@ module global (scope: global, depend: BE_USE_GLOBAL_MODULE) {
contains, func(m_contains)
member, func(m_findglobal)
setmember, func(m_setglobal)
undef, func(m_undef)
}
@const_object_info_end */
#include "../generate/be_fixed_global.h"

View File

@ -137,6 +137,20 @@ static int m_toptr(bvm *vm)
be_return_nil(vm);
}
static int m_solidified(bvm *vm)
{
int top = be_top(vm);
if (top >= 1) {
bvalue *v = be_indexof(vm, 1);
if (var_basetype(v) >= BE_FUNCTION || var_type(v) == BE_COMPTR) {
bbool isconst = gc_isconst((bgcobject*)var_toobj(v));
be_pushbool(vm, isconst);
be_return(vm);
}
}
be_return_nil(vm);
}
static int m_fromptr(bvm *vm)
{
int top = be_top(vm);
@ -245,6 +259,7 @@ be_native_module_attr_table(introspect) {
be_native_module_function("toptr", m_toptr),
be_native_module_function("fromptr", m_fromptr),
be_native_module_function("solidified", m_solidified),
be_native_module_function("name", m_name),
@ -266,6 +281,7 @@ module introspect (scope: global, depend: BE_USE_INTROSPECT_MODULE) {
toptr, func(m_toptr)
fromptr, func(m_fromptr)
solidified, func(m_solidified)
name, func(m_name)

View File

@ -284,7 +284,8 @@ static void tr_string(blexer *lexer)
break;
}
}
lexer->buf.len = dst - lexbuf(lexer);
size_t len = dst - lexbuf(lexer);
lexer->buf.len = strnlen(lexbuf(lexer), len);
}
static int skip_newline(blexer *lexer)

View File

@ -40,10 +40,15 @@
#elif defined(_MSC_VER)
#define popcount(v) __popcnt(v)
// Find a free slot in the space bitmask
// Find the least significant 1-bit in x and return its 1-based index.
static int ffs(unsigned x)
{
unsigned long i;
return _BitScanForward(&i, x) ? i : 0;
// NOTE: _BitScanForward is 0-based, see:
// https://learn.microsoft.com/en-us/cpp/intrinsics/bitscanforward-bitscanforward64?view=msvc-170
// _BitScanForward(&index, 12) populates index with 2
return _BitScanForward(&i, x) ? i + 1 : 0;
}
#else
/* https://github.com/hcs0/Hackers-Delight/blob/master/pop.c.txt - count number of 1-bits */

View File

@ -324,8 +324,8 @@ static void end_func(bparser *parser)
proto->codesize = finfo->pc;
proto->ktab = be_vector_release(vm, &finfo->kvec);
proto->nconst = be_vector_count(&finfo->kvec);
proto->nproto = be_vector_count(&finfo->pvec);
proto->ptab = be_vector_release(vm, &finfo->pvec);
proto->nproto = be_vector_count(&finfo->pvec);
#if BE_USE_MEM_ALIGNED
proto->code = be_move_to_aligned(vm, proto->code, proto->codesize * sizeof(binstruction)); /* move `code` to 4-bytes aligned memory region */
proto->ktab = be_move_to_aligned(vm, proto->ktab, proto->nconst * sizeof(bvalue)); /* move `ktab` to 4-bytes aligned memory region */
@ -488,7 +488,10 @@ static void new_var(bparser *parser, bstring *name, bexpdesc *var)
var->v.idx = new_localvar(parser, name); /* if local, contains the index in current local var list */
} else {
init_exp(var, ETGLOBAL, 0);
var->v.idx = be_global_new(parser->vm, name);
var->v.idx = be_global_find(parser->vm, name);
if (var->v.idx < 0) {
var->v.idx = be_global_new(parser->vm, name);
}
if (var->v.idx > (int)IBx_MASK) {
push_error(parser,
"too many global variables (in '%s')", str(name));

View File

@ -67,19 +67,39 @@ static int global_find(bvm *vm, bstring *name)
{
bvalue *res = be_map_findstr(vm, global(vm).vtab, name);
if (res) {
return var_toidx(res) + be_builtin_count(vm);
int idx = var_toidx(res);
if (idx >= 0) {
return idx + be_builtin_count(vm);
} else {
return idx; /* the global does not exist (-1) or was underfined (< -1)*/
}
}
return -1; /* not found */
}
bbool be_global_undef(bvm *vm, bstring *name)
{
int idx = global_find(vm, name);
if (idx >= 0) {
bvalue *desc = be_map_findstr(vm, global(vm).vtab, name);
int index = var_toidx(desc);
var_setint(desc, -index - 2); /* negate the index to mark it as undefined */
bvalue* val = be_vector_at(&global(vm).vlist, index);
var_setnil(val);
return btrue;
}
return bfalse;
}
int be_global_find(bvm *vm, bstring *name)
{
int res = global_find(vm, name);
int res = global_find(vm, name); /* returns negative if not found, -1 if does not exist, < -1 if existed but undefined */
if (res < 0) {
res = be_builtin_find(vm, name);
res = be_builtin_find(vm, name); /* returns -1 if not found */
}
if (res < 0) {
res = global_native_class_find(vm, name);
res = global_native_class_find(vm, name); /* returns -1 if not found */
}
return res;
}
@ -97,11 +117,18 @@ static int global_new_anonymous(bvm *vm)
int be_global_new(bvm *vm, bstring *name)
{
int idx = global_find(vm, name);
if (idx == -1) {
if (idx < 0) {
bvalue *desc;
idx = global_new_anonymous(vm);
desc = be_map_insertstr(vm, global(vm).vtab, name, NULL);
var_setint(desc, idx);
if (idx == -1) {
idx = global_new_anonymous(vm);
desc = be_map_insertstr(vm, global(vm).vtab, name, NULL);
var_setint(desc, idx);
} else {
/* the global exists but was undefined */
idx = -idx - 2;
desc = be_map_findstr(vm, global(vm).vtab, name);
var_setint(desc, idx);
}
idx += be_builtin_count(vm);
}
return idx;

View File

@ -20,6 +20,7 @@ void be_globalvar_init(bvm *vm);
void be_globalvar_deinit(bvm *vm);
int be_global_find(bvm *vm, bstring *name);
int be_global_new(bvm *vm, bstring *name);
bbool be_global_undef(bvm *vm, bstring *name);
bvalue* be_global_var(bvm *vm, int index);
void be_global_release_space(bvm *vm);
int be_builtin_find(bvm *vm, bstring *name);

View File

@ -591,7 +591,7 @@ newframe: /* a new call frame */
if (var_isstr(b)) {
bstring *name = var_tostr(b);
int idx = be_global_find(vm, name);
if (idx > -1) {
if (idx >= 0) {
*v = *be_global_var(vm, idx);
} else {
vm_error(vm, "attribute_error", "'%s' undeclared", str(name));
@ -1408,7 +1408,7 @@ BERRY_API void be_set_obs_micros(bvm *vm, bmicrosfnct micros)
vm->microsfnct = micros;
}
BERRY_API void be_set_ctype_func_hanlder(bvm *vm, bctypefunc handler)
BERRY_API void be_set_ctype_func_handler(bvm *vm, bctypefunc handler)
{
vm->ctypefunc = handler;
}

View File

@ -2168,14 +2168,14 @@ BERRY_API void be_set_obs_micros(bvm *vm, bmicrosfnct micros);
/**
* @fn void be_set_ctype_func_hanlder(bvm*, bctypefunc)
* @fn void be_set_ctype_func_handler(bvm*, bctypefunc)
* @note Observability hook
* @brief (???)
*
* @param vm virtual machine instance
* @param handler
*/
BERRY_API void be_set_ctype_func_hanlder(bvm *vm, bctypefunc handler);
BERRY_API void be_set_ctype_func_handler(bvm *vm, bctypefunc handler);
/**
* @fn bctypefunc be_get_ctype_func_hanlder(bvm*)

View File

@ -53,6 +53,11 @@ b.add(0x12345678, -2)
assert(str(b) == "bytes('2278785678563412785678')")
b.add(0x12345678, -4)
assert(str(b) == "bytes('227878567856341278567812345678')")
b.add(0xAABBCC, 3)
assert(str(b) == "bytes('227878567856341278567812345678CCBBAA')")
b.add(0x998877, -3)
assert(str(b) == "bytes('227878567856341278567812345678CCBBAA998877')")
#- get -#
b=bytes("000102030405")
@ -349,3 +354,9 @@ assert(b.appendb64(c, 2) == bytes("AABBCC49673D3D"))
b = bytes("AABBCC")
assert(bytes().fromstring(bytes("11").tob64()) == bytes('45513D3D'))
assert(b.appendb64(c, 1, 1) == bytes("AABBCC45513D3D"))
#- asstring truncates if NULL is present -#
s=bytes("414243").asstring()
assert(size(s) == 3)
s=bytes("410000").asstring()
assert(size(s) == 1)

View File

@ -84,3 +84,6 @@ var malformed_numbers = [
for i : malformed_numbers
test_source(i, 'malformed number')
end
#- ensure that string literal with NULL character is truncated -#
assert(size('aa\000bb\000cc') == 2)

View File

@ -0,0 +1,52 @@
# test regex from re1.5
import re
# standard use of lib
assert(re.search("a.*?b(z+)", "zaaaabbbccbbzzzee") == ['aaaabbbccbbzzz', 'zzz'])
assert(re.searchall('<([a-zA-Z]+)>', '<abc> yeah <xyz>') == [['<abc>', 'abc'], ['<xyz>', 'xyz']])
assert(re.match("a.*?b(z+)", "aaaabbbccbbzzzee") == ['aaaabbbccbbzzz', 'zzz'])
assert(re.match2("a.*?b(z+)", "aaaabbbccbbzzzee") == [14, 'zzz'])
assert(re.matchall('<([a-zA-Z]+)>', '<abc> yeah <xyz>') == [['<abc>', 'abc']])
assert(re.matchall('<([a-zA-Z]+)>', '<abc><xyz>') == [['<abc>', 'abc'], ['<xyz>', 'xyz']])
assert(re.split('/', "foo/bar//baz") == ['foo', 'bar', '', 'baz'])
# pre-compile
var rr
rr = re.compile("a.*?b(z+)")
assert(rr.search("zaaaabbbccbbzzzee") == ['aaaabbbccbbzzz', 'zzz'])
rr = re.compile('<([a-zA-Z]+)>')
assert(rr.searchall('<abc> yeah <xyz>') == [['<abc>', 'abc'], ['<xyz>', 'xyz']])
rr = re.compile("a.*?b(z+)")
assert(rr.match("aaaabbbccbbzzzee") == ['aaaabbbccbbzzz', 'zzz'])
assert(rr.match2("aaaabbbccbbzzzee") == [14, 'zzz'])
rr = re.compile('<([a-zA-Z]+)>')
assert(rr.matchall('<abc> yeah <xyz>') == [['<abc>', 'abc']])
assert(rr.matchall('<abc><xyz>') == [['<abc>', 'abc'], ['<xyz>', 'xyz']])
rr = re.compile('/')
assert(rr.split("foo/bar//baz") == ['foo', 'bar', '', 'baz'])
# compile to bytes
var rb
rb = re.compilebytes("a.*?b(z+)")
assert(re.search(rb, "zaaaabbbccbbzzzee") == ['aaaabbbccbbzzz', 'zzz'])
assert(rb == bytes('1B0000000F0000000100000062030260FB7E00016162030260FB01627E02017A62FC7E037E017F'))
rb = re.compilebytes('<([a-zA-Z]+)>')
assert(re.searchall(rb, '<abc> yeah <xyz>') == [['<abc>', 'abc'], ['<xyz>', 'xyz']])
assert(rb == bytes('1A0000000C0000000100000062030260FB7E00013C7E020302617A415A62F87E03013E7E017F'))
rb = re.compilebytes("a.*?b(z+)")
assert(re.match(rb, "aaaabbbccbbzzzee") == ['aaaabbbccbbzzz', 'zzz'])
assert(re.match2(rb, "aaaabbbccbbzzzee") == [14, 'zzz'])
assert(rb == bytes('1B0000000F0000000100000062030260FB7E00016162030260FB01627E02017A62FC7E037E017F'))
rb = re.compilebytes('<([a-zA-Z]+)>')
assert(re.matchall(rb, '<abc> yeah <xyz>') == [['<abc>', 'abc']])
assert(re.matchall(rb, '<abc><xyz>') == [['<abc>', 'abc'], ['<xyz>', 'xyz']])
assert(rb == bytes('1A0000000C0000000100000062030260FB7E00013C7E020302617A415A62F87E03013E7E017F'))
rb = re.compilebytes('/')
assert(re.split(rb, "foo/bar//baz") == ['foo', 'bar', '', 'baz'])
assert(rb == bytes('0C000000070000000000000062030260FB7E00012F7E017F'))

View File

@ -11,25 +11,25 @@
#include "be_mem.h"
static void int64_toa(int64_t num, uint8_t* str) {
uint64_t sum = num;
uint64_t sum = num;
if (num < 0) {
sum = -num;
str[0] = '-';
str++;
}
int len = 0;
do {
int len = 0;
do {
str[len++] = '0' + sum % 10LL;
sum /= 10LL;
} while (sum);
str[len] = '\0';
sum /= 10LL;
} while (sum);
str[len] = '\0';
/* strrev */
int i, j;
for (i = 0, j = len - 1; i < j; i++, j--){
uint8_t a = str[i];
str[i] = str[j];
str[j] = a;
}
for (i = 0, j = len - 1; i < j; i++, j--){
uint8_t a = str[i];
str[i] = str[j];
str[j] = a;
}
}
/* constructor*/
@ -320,15 +320,15 @@ be_local_closure(toint64, /* name */
&be_const_str_toint64,
&be_const_str_solidified,
( &(const binstruction[ 9]) { /* code */
0x4C040000, // 0000 LDNIL R1
0x1C040001, // 0001 EQ R1 R0 R1
0x78060001, // 0002 JMPF R1 #0005
0x4C040000, // 0003 LDNIL R1
0x80040200, // 0004 RET 1 R1
0xB8060000, // 0005 GETNGBL R1 K0
0x5C080000, // 0006 MOVE R2 R0
0x7C040200, // 0007 CALL R1 1
0x80040200, // 0008 RET 1 R1
0x4C040000, // 0000 LDNIL R1
0x1C040001, // 0001 EQ R1 R0 R1
0x78060001, // 0002 JMPF R1 #0005
0x4C040000, // 0003 LDNIL R1
0x80040200, // 0004 RET 1 R1
0xB8060000, // 0005 GETNGBL R1 K0
0x5C080000, // 0006 MOVE R2 R0
0x7C040200, // 0007 CALL R1 1
0x80040200, // 0008 RET 1 R1
})
)
);

View File

@ -171,7 +171,7 @@ You need to register the ctype function handler at the launch of the Berry VM:
void berry_launch(boid)
{
bvm *vm = be_vm_new(); /* Construct a VM */
be_set_ctype_func_hanlder(berry.vm, be_call_ctype_func); /* register the ctype function handler */
be_set_ctype_func_handler(berry.vm, be_call_ctype_func); /* register the ctype function handler */
}
```

View File

@ -27,26 +27,26 @@ static int call_berry_cb(int num, int v0, int v1, int v2, int v3, int v4);
#define BERRY_CB(n) int berry_cb_##n(int v0, int v1, int v2, int v3, int v4) { return call_berry_cb(n, v0, v1, v2, v3, v4); }
// list the callbacks
BERRY_CB(0);
BERRY_CB(1);
BERRY_CB(2);
BERRY_CB(3);
BERRY_CB(4);
BERRY_CB(5);
BERRY_CB(6);
BERRY_CB(7);
BERRY_CB(8);
BERRY_CB(9);
BERRY_CB(10);
BERRY_CB(11);
BERRY_CB(12);
BERRY_CB(13);
BERRY_CB(14);
BERRY_CB(15);
BERRY_CB(16);
BERRY_CB(17);
BERRY_CB(18);
BERRY_CB(19);
BERRY_CB(0)
BERRY_CB(1)
BERRY_CB(2)
BERRY_CB(3)
BERRY_CB(4)
BERRY_CB(5)
BERRY_CB(6)
BERRY_CB(7)
BERRY_CB(8)
BERRY_CB(9)
BERRY_CB(10)
BERRY_CB(11)
BERRY_CB(12)
BERRY_CB(13)
BERRY_CB(14)
BERRY_CB(15)
BERRY_CB(16)
BERRY_CB(17)
BERRY_CB(18)
BERRY_CB(19)
// array of callbacks
static const berry_callback_t berry_callback_array[BE_MAX_CB] = {

View File

@ -145,4 +145,4 @@ int be_map_bin_search(const char * needle, const void * table, size_t elt_size,
} else {
return -1;
}
}
}

View File

@ -87,9 +87,18 @@ matter.inspect = inspect
#
# Build a consolidated map of all the `CLUSTERS` static vars
# from the inheritance hierarchy
#
# `cl` can be a the class to get the superclass, or a `map`
#@ solidify:matter.consolidate_clusters,weak
def consolidate_clusters(cl, m)
var cl_parent = (super(cl) != nil) ? super(cl).CLUSTERS : {}
var cl_parent
if cl == nil
cl_parent = {}
elif type(cl) == 'class'
cl_parent = (super(cl) != nil) ? super(cl).CLUSTERS : {}
elif type(cl) == 'instance'
cl_parent = cl
end
var ret = {}
# clone cl_parent
for k: cl_parent.keys()

View File

@ -48,6 +48,7 @@ class Matter_Plugin
# `FEATURE_MAPS` contains any non-zero value per cluster, if not present default to `0`
static var FEATURE_MAPS = { # feature map per cluster
0x0031: 0x04, # Put Eth for now which should work for any on-network
# 0x0046: 0x04, # LITS: LongIdleTimeSupport
0x0102: 1 + 4, # Lift + PA_LF
0x0202: 2, # Fan: Auto
}
@ -77,6 +78,7 @@ class Matter_Plugin
# 0x0040: 1, # Initial Release
# 0x0041: 1, # Initial Release
# 0x0042: 1, # Initial Release
# 0x0046: 3, # ICD v3
# 0x005B: 1, # Initial Release
# 0x005C: 1, # Initial Release
0x0101: 7, # Added support for European door locks (unbolt feature)
@ -283,20 +285,20 @@ matter_device.events.dump()
return self.endpoint
end
def get_cluster_list_sorted()
return self.device.k2l(self.CLUSTERS)
return self.device.k2l(self.get_clusters())
end
def contains_cluster(cluster)
return self.CLUSTERS.contains(cluster)
return self.get_clusters().contains(cluster)
end
# def get_attribute_list(cluster)
# return self.clusters.find(cluster, [])
# end
# returns as a constant bytes of 16-bit ints, big endian
def get_attribute_list_bytes(cluster)
return self.CLUSTERS.find(cluster, nil)
return self.get_clusters().find(cluster, nil)
end
def contains_attribute(cluster, attribute)
var attr_list = self.CLUSTERS.find(cluster)
var attr_list = self.get_clusters().find(cluster)
# log(f"MTR: contains_attribute {cluster=} {attribute=} {attr_list=}")
if attr_list != nil
var idx = 0

View File

@ -43,16 +43,42 @@ class Matter_Plugin_Root : Matter_Plugin
0x003E: [0,1,2,3,4,5], # Node Operational Credentials Cluster 11.17 p.704
0x003F: [] # Group Key Management Cluster 11.2 p.572
})
# static var CLUSTERS_ICD = matter.consolidate_clusters(_class.CLUSTERS, {
# 0x0046: [0,1,2] # ICD Management Cluster
# })
static var TYPES = { 0x0016: 1 } # Root node
# # ICD options
# var icd_idle, icd_active, icd_threshold
#############################################################
# Constructor
def init(device, endpoint, config)
super(self).init(device, endpoint, config)
# # check if we have ICD parameters
# self.icd_idle = config.find("icd_idle", nil)
# if (self.icd_idle != nil)
# self.icd_active = config.find("icd_active", 5000) # default 5s
# self.icd_threshold = config.find("icd_threshold", 300) # default 300ms
# end
# publish mandatory events
self.publish_event(0x0028, 0x00, matter.EVENT_CRITICAL, matter.TLV.Matter_TLV_item().set(matter.TLV.U4, tasmota.version())) # Event StartUp - Software Version
self.publish_event(0x0033, 0x03, matter.EVENT_CRITICAL, matter.TLV.Matter_TLV_item().set(matter.TLV.U1, 1)) # Event BootReason - PowerOnReboot - TODO if we need to refine
end
#############################################################
# consolidate_clusters
#
# Build a consolidated map of all the `CLUSTERS` static vars
# from the inheritance hierarchy
# def get_clusters()
# if (self.icd_idle == nil)
# return self.CLUSTERS
# else
# return self.CLUSTERS_ICD
# end
# end
#############################################################
# read an attribute
#
@ -323,6 +349,17 @@ class Matter_Plugin_Root : Matter_Plugin
return pl
end
# ====================================================================================================
# elif cluster == 0x0046 # ========== ICD Management Cluster ==========
# if attribute == 0x0000 # ---------- IdleModeDuration / uint32 (seconds) ----------
# return tlv_solo.set_or_nil(TLV.U4, self.icd_idle)
# elif attribute == 0x0001 # ---------- ActiveModeDuration / uint32 (milliseconds) ----------
# return tlv_solo.set_or_nil(TLV.U4, self.icd_active)
# elif attribute == 0x0002 # ---------- ActiveModeThreshold / uint16 (milliseconds) ----------
# return tlv_solo.set_or_nil(TLV.U2, self.icd_threshold)
# end
end
return super(self).read_attribute(session, ctx, tlv_solo)
end

View File

@ -40,7 +40,7 @@ class Matter_Autoconf
var plugins = self.device.plugins
# start with mandatory endpoint 0 for root node
plugins.push(matter.Plugin_Root(self.device, 0, {}))
plugins.push(matter.Plugin_Root(self.device, 0, config.find("0", {})))
log("MTR: Configuring endpoints", 2)
log(format("MTR: endpoint = %5i type:%s%s", 0, 'root', ''), 2)

View File

@ -110,18 +110,7 @@ class Matter_Commissioning
self.commissioning_L = L
self.commissioning_admin_fabric = admin_fabric
if tasmota.wifi()['up'] || tasmota.eth()['up']
self.mdns_announce_PASE()
else
tasmota.add_rule("Wifi#Connected", def ()
self.mdns_announce_PASE()
tasmota.remove_rule("Wifi#Connected", "mdns_announce_PASE")
end, "mdns_announce_PASE")
tasmota.add_rule("Eth#Connected", def ()
self.mdns_announce_PASE()
tasmota.remove_rule("Eth#Connected", "mdns_announce_PASE")
end, "mdns_announce_PASE")
end
tasmota.when_network_up(def () self.mdns_announce_PASE() end)
end
#############################################################
@ -236,23 +225,16 @@ class Matter_Commissioning
# When the announce is active, `hostname_wifi` and `hostname_eth`
# are defined
def start_mdns_announce_hostnames()
if tasmota.wifi()['up']
self._mdns_announce_hostname(false)
else
tasmota.add_rule("Wifi#Connected", def ()
self._mdns_announce_hostname(false)
tasmota.remove_rule("Wifi#Connected", "matter_mdns_host")
end, "matter_mdns_host")
end
tasmota.when_network_up(def ()
if tasmota.eth()['up']
self._mdns_announce_hostname(true)
else
tasmota.add_rule("Eth#Connected", def ()
self._mdns_announce_hostname(true)
tasmota.remove_rule("Eth#Connected", "matter_mdns_host")
end, "matter_mdns_host")
end
if tasmota.wifi('up')
self._mdns_announce_hostname(false)
end
if tasmota.eth('up')
self._mdns_announce_hostname(true)
end
end)
end
#############################################################

View File

@ -27,7 +27,7 @@ class Matter_Device
static var PRODUCT_ID = 0x8000
static var FILENAME = "_matter_device.json"
static var EP = 2 # first available endpoint number for devices
var started # is the Matter Device started (configured, mDNS and UDPServer started)
var started # is the Matter Device started (configured, mDNS and UDPServer started) - 'nil' means that we wait for Wifi to connect, 'false' means that the start is scheduled but not yet triggered
var plugins # list of plugins instances
var plugins_persist # true if plugins configuration needs to be saved
static var plugins_classes = matter.plugins_classes # map of registered classes by type name
@ -68,7 +68,6 @@ class Matter_Device
end # abort if SetOption 151 is not set
matter.profiler = matter.Profiler()
self.started = false
self.tick = 0
self.plugins = []
self.plugins_persist = false # plugins need to saved only when the first fabric is associated
@ -86,35 +85,22 @@ class Matter_Device
self.zigbee = self.init_zigbee()
self.ui = matter.UI(self, true)
tasmota.when_network_up(def () self.start() end) # start when network is connected
self.commissioning.init_basic_commissioning()
tasmota.add_driver(self)
self.register_commands()
end
#############################################################
# Check if the network just started
def check_network()
if self.started return end # abort if already started
if tasmota.wifi()['up'] || tasmota.eth()['up']
self.start()
end
end
#############################################################
# Start Matter device server when the first network is coming up
def start()
if self.started return end # abort if already started
# autoconfigure other plugins if needed
self.autoconf_device()
self._start_udp(self.UDP_PORT)
self.commissioning.start_mdns_announce_hostnames()
self.started = true
end
#####################################################################
@ -251,7 +237,6 @@ class Matter_Device
# dispatch every 50ms
# ticks
def every_50ms()
self.check_network()
self.tick += 1
self.message_handler.every_50ms()
end
@ -747,11 +732,7 @@ class Matter_Device
var keys = []
for k: self.plugins_config.keys() keys.push(int(k)) end
for ep: keys
if ep == 0
log("MTR: invalid entry with ep '0'", 2)
self.plugins_config.remove(str(ep))
dirty = true
elif ep == matter.AGGREGATOR_ENDPOINT
if ep == matter.AGGREGATOR_ENDPOINT
dirty = true
log(f"MTR: endpoint {ep} collides wit aggregator, relocating to {self.next_ep}", 2)
self.plugins_config[str(self.next_ep)] = self.plugins_config[str(ep)]

View File

@ -257,204 +257,227 @@ be_local_closure(module_matter_consolidate_clusters, /* name */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[13]) { /* constants */
/* K0 */ be_nested_str_weak(CLUSTERS),
/* K1 */ be_nested_str_weak(keys),
/* K2 */ be_const_int(2),
/* K3 */ be_const_int(0),
/* K4 */ be_nested_str_weak(push),
/* K5 */ be_nested_str_weak(get),
/* K6 */ be_const_int(1),
/* K7 */ be_nested_str_weak(stop_iteration),
/* K8 */ be_nested_str_weak(contains),
/* K9 */ be_nested_str_weak(find),
/* K10 */ be_nested_str_weak(matter),
/* K11 */ be_nested_str_weak(sort),
/* K12 */ be_nested_str_weak(add),
( &(const bvalue[15]) { /* constants */
/* K0 */ be_nested_str_weak(class),
/* K1 */ be_nested_str_weak(CLUSTERS),
/* K2 */ be_nested_str_weak(instance),
/* K3 */ be_nested_str_weak(keys),
/* K4 */ be_const_int(2),
/* K5 */ be_const_int(0),
/* K6 */ be_nested_str_weak(push),
/* K7 */ be_nested_str_weak(get),
/* K8 */ be_const_int(1),
/* K9 */ be_nested_str_weak(stop_iteration),
/* K10 */ be_nested_str_weak(contains),
/* K11 */ be_nested_str_weak(find),
/* K12 */ be_nested_str_weak(matter),
/* K13 */ be_nested_str_weak(sort),
/* K14 */ be_nested_str_weak(add),
}),
be_str_weak(consolidate_clusters),
&be_const_str_solidified,
( &(const binstruction[180]) { /* code */
0x60080003, // 0000 GETGBL R2 G3
0x5C0C0000, // 0001 MOVE R3 R0
0x7C080200, // 0002 CALL R2 1
0x4C0C0000, // 0003 LDNIL R3
0x20080403, // 0004 NE R2 R2 R3
0x780A0004, // 0005 JMPF R2 #000B
0x60080003, // 0006 GETGBL R2 G3
0x5C0C0000, // 0007 MOVE R3 R0
0x7C080200, // 0008 CALL R2 1
0x88080500, // 0009 GETMBR R2 R2 K0
0x70020001, // 000A JMP #000D
0x60080013, // 000B GETGBL R2 G19
0x7C080000, // 000C CALL R2 0
0x600C0013, // 000D GETGBL R3 G19
0x7C0C0000, // 000E CALL R3 0
0x60100010, // 000F GETGBL R4 G16
0x8C140501, // 0010 GETMET R5 R2 K1
0x7C140200, // 0011 CALL R5 1
0x7C100200, // 0012 CALL R4 1
0xA802001A, // 0013 EXBLK 0 #002F
0x5C140800, // 0014 MOVE R5 R4
0x7C140000, // 0015 CALL R5 0
0x60180012, // 0016 GETGBL R6 G18
0x7C180000, // 0017 CALL R6 0
0x941C0405, // 0018 GETIDX R7 R2 R5
0x4C200000, // 0019 LDNIL R8
0x20200E08, // 001A NE R8 R7 R8
0x78220004, // 001B JMPF R8 #0021
0x6020000C, // 001C GETGBL R8 G12
0x5C240E00, // 001D MOVE R9 R7
0x7C200200, // 001E CALL R8 1
0x0C201102, // 001F DIV R8 R8 K2
0x70020000, // 0020 JMP #0022
0x58200003, // 0021 LDCONST R8 K3
0x58240003, // 0022 LDCONST R9 K3
0x14281208, // 0023 LT R10 R9 R8
0x782A0007, // 0024 JMPF R10 #002D
0x8C280D04, // 0025 GETMET R10 R6 K4
0x8C300F05, // 0026 GETMET R12 R7 K5
0x08381302, // 0027 MUL R14 R9 K2
0x543DFFFD, // 0028 LDINT R15 -2
0x7C300600, // 0029 CALL R12 3
0x7C280400, // 002A CALL R10 2
0x00241306, // 002B ADD R9 R9 K6
0x7001FFF5, // 002C JMP #0023
0x980C0A06, // 002D SETIDX R3 R5 R6
0x7001FFE4, // 002E JMP #0014
0x58100007, // 002F LDCONST R4 K7
0xAC100200, // 0030 CATCH R4 1 0
0xB0080000, // 0031 RAISE 2 R0 R0
0x60100010, // 0032 GETGBL R4 G16
0x8C140301, // 0033 GETMET R5 R1 K1
0x7C140200, // 0034 CALL R5 1
0x7C100200, // 0035 CALL R4 1
0xA802001E, // 0036 EXBLK 0 #0056
0x5C140800, // 0037 MOVE R5 R4
0x7C140000, // 0038 CALL R5 0
0x8C180708, // 0039 GETMET R6 R3 K8
0x5C200A00, // 003A MOVE R8 R5
0x7C180400, // 003B CALL R6 2
0x741A0002, // 003C JMPT R6 #0040
0x60180012, // 003D GETGBL R6 G18
0x7C180000, // 003E CALL R6 0
0x980C0A06, // 003F SETIDX R3 R5 R6
0x60180010, // 0040 GETGBL R6 G16
0x941C0205, // 0041 GETIDX R7 R1 R5
0x7C180200, // 0042 CALL R6 1
0xA802000D, // 0043 EXBLK 0 #0052
0x5C1C0C00, // 0044 MOVE R7 R6
0x7C1C0000, // 0045 CALL R7 0
0x94200605, // 0046 GETIDX R8 R3 R5
0x8C201109, // 0047 GETMET R8 R8 K9
0x5C280E00, // 0048 MOVE R10 R7
0x7C200400, // 0049 CALL R8 2
0x4C240000, // 004A LDNIL R9
0x1C201009, // 004B EQ R8 R8 R9
0x78220003, // 004C JMPF R8 #0051
0x94200605, // 004D GETIDX R8 R3 R5
0x8C201104, // 004E GETMET R8 R8 K4
0x5C280E00, // 004F MOVE R10 R7
0x7C200400, // 0050 CALL R8 2
0x7001FFF1, // 0051 JMP #0044
0x58180007, // 0052 LDCONST R6 K7
0xAC180200, // 0053 CATCH R6 1 0
0xB0080000, // 0054 RAISE 2 R0 R0
0x7001FFE0, // 0055 JMP #0037
0x58100007, // 0056 LDCONST R4 K7
0xAC100200, // 0057 CATCH R4 1 0
0xB0080000, // 0058 RAISE 2 R0 R0
0x60100012, // 0059 GETGBL R4 G18
0x7C100000, // 005A CALL R4 0
0x5416FFF7, // 005B LDINT R5 65528
0x40140805, // 005C CONNECT R5 R4 R5
0x5416FFF8, // 005D LDINT R5 65529
0x40140805, // 005E CONNECT R5 R4 R5
0x5416FFF9, // 005F LDINT R5 65530
0x40140805, // 0060 CONNECT R5 R4 R5
0x5416FFFA, // 0061 LDINT R5 65531
0x40140805, // 0062 CONNECT R5 R4 R5
0x5416FFFB, // 0063 LDINT R5 65532
0x40140805, // 0064 CONNECT R5 R4 R5
0x5416FFFC, // 0065 LDINT R5 65533
0x40140805, // 0066 CONNECT R5 R4 R5
0x60140010, // 0067 GETGBL R5 G16
0x8C180301, // 0068 GETMET R6 R1 K1
0x7C180200, // 0069 CALL R6 1
0x7C140200, // 006A CALL R5 1
0xA8020017, // 006B EXBLK 0 #0084
0x5C180A00, // 006C MOVE R6 R5
0x7C180000, // 006D CALL R6 0
0x601C0010, // 006E GETGBL R7 G16
0x5C200800, // 006F MOVE R8 R4
0x7C1C0200, // 0070 CALL R7 1
0xA802000D, // 0071 EXBLK 0 #0080
0x5C200E00, // 0072 MOVE R8 R7
0x7C200000, // 0073 CALL R8 0
0x94240606, // 0074 GETIDX R9 R3 R6
0x8C241309, // 0075 GETMET R9 R9 K9
0x5C2C1000, // 0076 MOVE R11 R8
0x7C240400, // 0077 CALL R9 2
0x4C280000, // 0078 LDNIL R10
0x1C24120A, // 0079 EQ R9 R9 R10
0x78260003, // 007A JMPF R9 #007F
0x94240606, // 007B GETIDX R9 R3 R6
0x8C241304, // 007C GETMET R9 R9 K4
0x5C2C1000, // 007D MOVE R11 R8
0x7C240400, // 007E CALL R9 2
0x7001FFF1, // 007F JMP #0072
0x581C0007, // 0080 LDCONST R7 K7
0xAC1C0200, // 0081 CATCH R7 1 0
0xB0080000, // 0082 RAISE 2 R0 R0
0x7001FFE7, // 0083 JMP #006C
0x58140007, // 0084 LDCONST R5 K7
0xAC140200, // 0085 CATCH R5 1 0
0xB0080000, // 0086 RAISE 2 R0 R0
0x60140010, // 0087 GETGBL R5 G16
0x8C180701, // 0088 GETMET R6 R3 K1
0x7C180200, // 0089 CALL R6 1
0x7C140200, // 008A CALL R5 1
0xA8020008, // 008B EXBLK 0 #0095
0x5C180A00, // 008C MOVE R6 R5
0x7C180000, // 008D CALL R6 0
0x941C0606, // 008E GETIDX R7 R3 R6
0xB8221400, // 008F GETNGBL R8 K10
0x8C20110B, // 0090 GETMET R8 R8 K11
0x5C280E00, // 0091 MOVE R10 R7
0x7C200400, // 0092 CALL R8 2
0x980C0C08, // 0093 SETIDX R3 R6 R8
0x7001FFF6, // 0094 JMP #008C
0x58140007, // 0095 LDCONST R5 K7
0xAC140200, // 0096 CATCH R5 1 0
( &(const binstruction[201]) { /* code */
0x4C080000, // 0000 LDNIL R2
0x4C0C0000, // 0001 LDNIL R3
0x1C0C0003, // 0002 EQ R3 R0 R3
0x780E0003, // 0003 JMPF R3 #0008
0x600C0013, // 0004 GETGBL R3 G19
0x7C0C0000, // 0005 CALL R3 0
0x5C080600, // 0006 MOVE R2 R3
0x70020019, // 0007 JMP #0022
0x600C0004, // 0008 GETGBL R3 G4
0x5C100000, // 0009 MOVE R4 R0
0x7C0C0200, // 000A CALL R3 1
0x1C0C0700, // 000B EQ R3 R3 K0
0x780E000E, // 000C JMPF R3 #001C
0x600C0003, // 000D GETGBL R3 G3
0x5C100000, // 000E MOVE R4 R0
0x7C0C0200, // 000F CALL R3 1
0x4C100000, // 0010 LDNIL R4
0x200C0604, // 0011 NE R3 R3 R4
0x780E0004, // 0012 JMPF R3 #0018
0x600C0003, // 0013 GETGBL R3 G3
0x5C100000, // 0014 MOVE R4 R0
0x7C0C0200, // 0015 CALL R3 1
0x880C0701, // 0016 GETMBR R3 R3 K1
0x70020001, // 0017 JMP #001A
0x600C0013, // 0018 GETGBL R3 G19
0x7C0C0000, // 0019 CALL R3 0
0x5C080600, // 001A MOVE R2 R3
0x70020005, // 001B JMP #0022
0x600C0004, // 001C GETGBL R3 G4
0x5C100000, // 001D MOVE R4 R0
0x7C0C0200, // 001E CALL R3 1
0x1C0C0702, // 001F EQ R3 R3 K2
0x780E0000, // 0020 JMPF R3 #0022
0x5C080000, // 0021 MOVE R2 R0
0x600C0013, // 0022 GETGBL R3 G19
0x7C0C0000, // 0023 CALL R3 0
0x60100010, // 0024 GETGBL R4 G16
0x8C140503, // 0025 GETMET R5 R2 K3
0x7C140200, // 0026 CALL R5 1
0x7C100200, // 0027 CALL R4 1
0xA802001A, // 0028 EXBLK 0 #0044
0x5C140800, // 0029 MOVE R5 R4
0x7C140000, // 002A CALL R5 0
0x60180012, // 002B GETGBL R6 G18
0x7C180000, // 002C CALL R6 0
0x941C0405, // 002D GETIDX R7 R2 R5
0x4C200000, // 002E LDNIL R8
0x20200E08, // 002F NE R8 R7 R8
0x78220004, // 0030 JMPF R8 #0036
0x6020000C, // 0031 GETGBL R8 G12
0x5C240E00, // 0032 MOVE R9 R7
0x7C200200, // 0033 CALL R8 1
0x0C201104, // 0034 DIV R8 R8 K4
0x70020000, // 0035 JMP #0037
0x58200005, // 0036 LDCONST R8 K5
0x58240005, // 0037 LDCONST R9 K5
0x14281208, // 0038 LT R10 R9 R8
0x782A0007, // 0039 JMPF R10 #0042
0x8C280D06, // 003A GETMET R10 R6 K6
0x8C300F07, // 003B GETMET R12 R7 K7
0x08381304, // 003C MUL R14 R9 K4
0x543DFFFD, // 003D LDINT R15 -2
0x7C300600, // 003E CALL R12 3
0x7C280400, // 003F CALL R10 2
0x00241308, // 0040 ADD R9 R9 K8
0x7001FFF5, // 0041 JMP #0038
0x980C0A06, // 0042 SETIDX R3 R5 R6
0x7001FFE4, // 0043 JMP #0029
0x58100009, // 0044 LDCONST R4 K9
0xAC100200, // 0045 CATCH R4 1 0
0xB0080000, // 0046 RAISE 2 R0 R0
0x60100010, // 0047 GETGBL R4 G16
0x8C140303, // 0048 GETMET R5 R1 K3
0x7C140200, // 0049 CALL R5 1
0x7C100200, // 004A CALL R4 1
0xA802001E, // 004B EXBLK 0 #006B
0x5C140800, // 004C MOVE R5 R4
0x7C140000, // 004D CALL R5 0
0x8C18070A, // 004E GETMET R6 R3 K10
0x5C200A00, // 004F MOVE R8 R5
0x7C180400, // 0050 CALL R6 2
0x741A0002, // 0051 JMPT R6 #0055
0x60180012, // 0052 GETGBL R6 G18
0x7C180000, // 0053 CALL R6 0
0x980C0A06, // 0054 SETIDX R3 R5 R6
0x60180010, // 0055 GETGBL R6 G16
0x941C0205, // 0056 GETIDX R7 R1 R5
0x7C180200, // 0057 CALL R6 1
0xA802000D, // 0058 EXBLK 0 #0067
0x5C1C0C00, // 0059 MOVE R7 R6
0x7C1C0000, // 005A CALL R7 0
0x94200605, // 005B GETIDX R8 R3 R5
0x8C20110B, // 005C GETMET R8 R8 K11
0x5C280E00, // 005D MOVE R10 R7
0x7C200400, // 005E CALL R8 2
0x4C240000, // 005F LDNIL R9
0x1C201009, // 0060 EQ R8 R8 R9
0x78220003, // 0061 JMPF R8 #0066
0x94200605, // 0062 GETIDX R8 R3 R5
0x8C201106, // 0063 GETMET R8 R8 K6
0x5C280E00, // 0064 MOVE R10 R7
0x7C200400, // 0065 CALL R8 2
0x7001FFF1, // 0066 JMP #0059
0x58180009, // 0067 LDCONST R6 K9
0xAC180200, // 0068 CATCH R6 1 0
0xB0080000, // 0069 RAISE 2 R0 R0
0x7001FFE0, // 006A JMP #004C
0x58100009, // 006B LDCONST R4 K9
0xAC100200, // 006C CATCH R4 1 0
0xB0080000, // 006D RAISE 2 R0 R0
0x60100012, // 006E GETGBL R4 G18
0x7C100000, // 006F CALL R4 0
0x5416FFF7, // 0070 LDINT R5 65528
0x40140805, // 0071 CONNECT R5 R4 R5
0x5416FFF8, // 0072 LDINT R5 65529
0x40140805, // 0073 CONNECT R5 R4 R5
0x5416FFF9, // 0074 LDINT R5 65530
0x40140805, // 0075 CONNECT R5 R4 R5
0x5416FFFA, // 0076 LDINT R5 65531
0x40140805, // 0077 CONNECT R5 R4 R5
0x5416FFFB, // 0078 LDINT R5 65532
0x40140805, // 0079 CONNECT R5 R4 R5
0x5416FFFC, // 007A LDINT R5 65533
0x40140805, // 007B CONNECT R5 R4 R5
0x60140010, // 007C GETGBL R5 G16
0x8C180303, // 007D GETMET R6 R1 K3
0x7C180200, // 007E CALL R6 1
0x7C140200, // 007F CALL R5 1
0xA8020017, // 0080 EXBLK 0 #0099
0x5C180A00, // 0081 MOVE R6 R5
0x7C180000, // 0082 CALL R6 0
0x601C0010, // 0083 GETGBL R7 G16
0x5C200800, // 0084 MOVE R8 R4
0x7C1C0200, // 0085 CALL R7 1
0xA802000D, // 0086 EXBLK 0 #0095
0x5C200E00, // 0087 MOVE R8 R7
0x7C200000, // 0088 CALL R8 0
0x94240606, // 0089 GETIDX R9 R3 R6
0x8C24130B, // 008A GETMET R9 R9 K11
0x5C2C1000, // 008B MOVE R11 R8
0x7C240400, // 008C CALL R9 2
0x4C280000, // 008D LDNIL R10
0x1C24120A, // 008E EQ R9 R9 R10
0x78260003, // 008F JMPF R9 #0094
0x94240606, // 0090 GETIDX R9 R3 R6
0x8C241306, // 0091 GETMET R9 R9 K6
0x5C2C1000, // 0092 MOVE R11 R8
0x7C240400, // 0093 CALL R9 2
0x7001FFF1, // 0094 JMP #0087
0x581C0009, // 0095 LDCONST R7 K9
0xAC1C0200, // 0096 CATCH R7 1 0
0xB0080000, // 0097 RAISE 2 R0 R0
0x60140010, // 0098 GETGBL R5 G16
0x8C180701, // 0099 GETMET R6 R3 K1
0x7C180200, // 009A CALL R6 1
0x7C140200, // 009B CALL R5 1
0xA8020012, // 009C EXBLK 0 #00B0
0x5C180A00, // 009D MOVE R6 R5
0x7C180000, // 009E CALL R6 0
0x941C0606, // 009F GETIDX R7 R3 R6
0x60200015, // 00A0 GETGBL R8 G21
0x7C200000, // 00A1 CALL R8 0
0x58240003, // 00A2 LDCONST R9 K3
0x6028000C, // 00A3 GETGBL R10 G12
0x5C2C0E00, // 00A4 MOVE R11 R7
0x7C280200, // 00A5 CALL R10 1
0x1428120A, // 00A6 LT R10 R9 R10
0x782A0005, // 00A7 JMPF R10 #00AE
0x8C28110C, // 00A8 GETMET R10 R8 K12
0x94300E09, // 00A9 GETIDX R12 R7 R9
0x5435FFFD, // 00AA LDINT R13 -2
0x7C280600, // 00AB CALL R10 3
0x00241306, // 00AC ADD R9 R9 K6
0x7001FFF4, // 00AD JMP #00A3
0x980C0C08, // 00AE SETIDX R3 R6 R8
0x7001FFEC, // 00AF JMP #009D
0x58140007, // 00B0 LDCONST R5 K7
0xAC140200, // 00B1 CATCH R5 1 0
0xB0080000, // 00B2 RAISE 2 R0 R0
0x80040600, // 00B3 RET 1 R3
0x7001FFE7, // 0098 JMP #0081
0x58140009, // 0099 LDCONST R5 K9
0xAC140200, // 009A CATCH R5 1 0
0xB0080000, // 009B RAISE 2 R0 R0
0x60140010, // 009C GETGBL R5 G16
0x8C180703, // 009D GETMET R6 R3 K3
0x7C180200, // 009E CALL R6 1
0x7C140200, // 009F CALL R5 1
0xA8020008, // 00A0 EXBLK 0 #00AA
0x5C180A00, // 00A1 MOVE R6 R5
0x7C180000, // 00A2 CALL R6 0
0x941C0606, // 00A3 GETIDX R7 R3 R6
0xB8221800, // 00A4 GETNGBL R8 K12
0x8C20110D, // 00A5 GETMET R8 R8 K13
0x5C280E00, // 00A6 MOVE R10 R7
0x7C200400, // 00A7 CALL R8 2
0x980C0C08, // 00A8 SETIDX R3 R6 R8
0x7001FFF6, // 00A9 JMP #00A1
0x58140009, // 00AA LDCONST R5 K9
0xAC140200, // 00AB CATCH R5 1 0
0xB0080000, // 00AC RAISE 2 R0 R0
0x60140010, // 00AD GETGBL R5 G16
0x8C180703, // 00AE GETMET R6 R3 K3
0x7C180200, // 00AF CALL R6 1
0x7C140200, // 00B0 CALL R5 1
0xA8020012, // 00B1 EXBLK 0 #00C5
0x5C180A00, // 00B2 MOVE R6 R5
0x7C180000, // 00B3 CALL R6 0
0x941C0606, // 00B4 GETIDX R7 R3 R6
0x60200015, // 00B5 GETGBL R8 G21
0x7C200000, // 00B6 CALL R8 0
0x58240005, // 00B7 LDCONST R9 K5
0x6028000C, // 00B8 GETGBL R10 G12
0x5C2C0E00, // 00B9 MOVE R11 R7
0x7C280200, // 00BA CALL R10 1
0x1428120A, // 00BB LT R10 R9 R10
0x782A0005, // 00BC JMPF R10 #00C3
0x8C28110E, // 00BD GETMET R10 R8 K14
0x94300E09, // 00BE GETIDX R12 R7 R9
0x5435FFFD, // 00BF LDINT R13 -2
0x7C280600, // 00C0 CALL R10 3
0x00241308, // 00C1 ADD R9 R9 K8
0x7001FFF4, // 00C2 JMP #00B8
0x980C0C08, // 00C3 SETIDX R3 R6 R8
0x7001FFEC, // 00C4 JMP #00B2
0x58140009, // 00C5 LDCONST R5 K9
0xAC140200, // 00C6 CATCH R5 1 0
0xB0080000, // 00C7 RAISE 2 R0 R0
0x80040600, // 00C8 RET 1 R3
})
)
);

View File

@ -4,8 +4,8 @@
\********************************************************************/
#include "be_constobj.h"
extern const bclass be_class_Matter_Plugin;
// compact class 'Matter_Plugin' ktab size: 65, total: 108 (saved 344 bytes)
static const bvalue be_ktab_class_Matter_Plugin[65] = {
// compact class 'Matter_Plugin' ktab size: 66, total: 108 (saved 336 bytes)
static const bvalue be_ktab_class_Matter_Plugin[66] = {
/* K0 */ be_nested_str_weak(json),
/* K1 */ be_nested_str_weak(node_label),
/* K2 */ be_nested_str_weak(_X2C_X22Name_X22_X3A_X25s),
@ -21,7 +21,7 @@ static const bvalue be_ktab_class_Matter_Plugin[65] = {
/* K12 */ be_nested_str_weak(message_handler),
/* K13 */ be_nested_str_weak(im),
/* K14 */ be_nested_str_weak(send_ack_now),
/* K15 */ be_nested_str_weak(CLUSTERS),
/* K15 */ be_nested_str_weak(get_clusters),
/* K16 */ be_nested_str_weak(find),
/* K17 */ be_nested_str_weak(attribute_updated),
/* K18 */ be_nested_str_weak(update_next),
@ -53,24 +53,25 @@ static const bvalue be_ktab_class_Matter_Plugin[65] = {
/* K44 */ be_nested_str_weak(_X25s_X2C_X25s_X3A_X25s),
/* K45 */ be_nested_str_weak(publish_command),
/* K46 */ be_nested_str_weak(MtrReceived),
/* K47 */ be_nested_str_weak(contains),
/* K48 */ be_nested_str_weak(TLV),
/* K49 */ be_nested_str_weak(cluster),
/* K50 */ be_nested_str_weak(attribute),
/* K51 */ be_nested_str_weak(Matter_TLV_array),
/* K52 */ be_nested_str_weak(TYPES),
/* K53 */ be_nested_str_weak(keys),
/* K54 */ be_nested_str_weak(add_struct),
/* K55 */ be_nested_str_weak(add_TLV),
/* K56 */ be_nested_str_weak(U2),
/* K57 */ be_nested_str_weak(stop_iteration),
/* K58 */ be_nested_str_weak(get_cluster_list_sorted),
/* K59 */ be_nested_str_weak(U4),
/* K60 */ be_const_int(3),
/* K61 */ be_nested_str_weak(set),
/* K62 */ be_nested_str_weak(get_attribute_list_bytes),
/* K63 */ be_nested_str_weak(FEATURE_MAPS),
/* K64 */ be_nested_str_weak(CLUSTER_REVISIONS),
/* K47 */ be_nested_str_weak(CLUSTERS),
/* K48 */ be_nested_str_weak(contains),
/* K49 */ be_nested_str_weak(TLV),
/* K50 */ be_nested_str_weak(cluster),
/* K51 */ be_nested_str_weak(attribute),
/* K52 */ be_nested_str_weak(Matter_TLV_array),
/* K53 */ be_nested_str_weak(TYPES),
/* K54 */ be_nested_str_weak(keys),
/* K55 */ be_nested_str_weak(add_struct),
/* K56 */ be_nested_str_weak(add_TLV),
/* K57 */ be_nested_str_weak(U2),
/* K58 */ be_nested_str_weak(stop_iteration),
/* K59 */ be_nested_str_weak(get_cluster_list_sorted),
/* K60 */ be_nested_str_weak(U4),
/* K61 */ be_const_int(3),
/* K62 */ be_nested_str_weak(set),
/* K63 */ be_nested_str_weak(get_attribute_list_bytes),
/* K64 */ be_nested_str_weak(FEATURE_MAPS),
/* K65 */ be_nested_str_weak(CLUSTER_REVISIONS),
};
@ -210,13 +211,14 @@ be_local_closure(class_Matter_Plugin_get_attribute_list_bytes, /* name */
&be_ktab_class_Matter_Plugin, /* shared constants */
be_str_weak(get_attribute_list_bytes),
&be_const_str_solidified,
( &(const binstruction[ 6]) { /* code */
0x8808010F, // 0000 GETMBR R2 R0 K15
0x8C080510, // 0001 GETMET R2 R2 K16
0x5C100200, // 0002 MOVE R4 R1
0x4C140000, // 0003 LDNIL R5
0x7C080600, // 0004 CALL R2 3
0x80040400, // 0005 RET 1 R2
( &(const binstruction[ 7]) { /* code */
0x8C08010F, // 0000 GETMET R2 R0 K15
0x7C080200, // 0001 CALL R2 1
0x8C080510, // 0002 GETMET R2 R2 K16
0x5C100200, // 0003 MOVE R4 R1
0x4C140000, // 0004 LDNIL R5
0x7C080600, // 0005 CALL R2 3
0x80040400, // 0006 RET 1 R2
})
)
);
@ -612,7 +614,7 @@ be_local_closure(class_Matter_Plugin_consolidate_update_commands, /* name */
********************************************************************/
be_local_closure(class_Matter_Plugin_get_cluster_list_sorted, /* name */
be_nested_proto(
4, /* nstack */
5, /* nstack */
1, /* argc */
10, /* varg */
0, /* has upvals */
@ -623,12 +625,13 @@ be_local_closure(class_Matter_Plugin_get_cluster_list_sorted, /* name */
&be_ktab_class_Matter_Plugin, /* shared constants */
be_str_weak(get_cluster_list_sorted),
&be_const_str_solidified,
( &(const binstruction[ 5]) { /* code */
( &(const binstruction[ 6]) { /* code */
0x88040109, // 0000 GETMBR R1 R0 K9
0x8C040320, // 0001 GETMET R1 R1 K32
0x880C010F, // 0002 GETMBR R3 R0 K15
0x7C040400, // 0003 CALL R1 2
0x80040200, // 0004 RET 1 R1
0x8C0C010F, // 0002 GETMET R3 R0 K15
0x7C0C0200, // 0003 CALL R3 1
0x7C040400, // 0004 CALL R1 2
0x80040200, // 0005 RET 1 R1
})
)
);
@ -820,33 +823,34 @@ be_local_closure(class_Matter_Plugin_contains_attribute, /* name */
&be_ktab_class_Matter_Plugin, /* shared constants */
be_str_weak(contains_attribute),
&be_const_str_solidified,
( &(const binstruction[26]) { /* code */
0x880C010F, // 0000 GETMBR R3 R0 K15
0x8C0C0710, // 0001 GETMET R3 R3 K16
0x5C140200, // 0002 MOVE R5 R1
0x7C0C0400, // 0003 CALL R3 2
0x4C100000, // 0004 LDNIL R4
0x20100604, // 0005 NE R4 R3 R4
0x78120010, // 0006 JMPF R4 #0018
0x58100023, // 0007 LDCONST R4 K35
0x6014000C, // 0008 GETGBL R5 G12
0x5C180600, // 0009 MOVE R6 R3
0x7C140200, // 000A CALL R5 1
0x0C140B24, // 000B DIV R5 R5 K36
0x14180805, // 000C LT R6 R4 R5
0x781A0009, // 000D JMPF R6 #0018
0x8C180725, // 000E GETMET R6 R3 K37
0x08200924, // 000F MUL R8 R4 K36
0x5425FFFD, // 0010 LDINT R9 -2
0x7C180600, // 0011 CALL R6 3
0x1C180C02, // 0012 EQ R6 R6 R2
0x781A0001, // 0013 JMPF R6 #0016
0x50180200, // 0014 LDBOOL R6 1 0
0x80040C00, // 0015 RET 1 R6
0x00100926, // 0016 ADD R4 R4 K38
0x7001FFF3, // 0017 JMP #000C
0x50100000, // 0018 LDBOOL R4 0 0
0x80040800, // 0019 RET 1 R4
( &(const binstruction[27]) { /* code */
0x8C0C010F, // 0000 GETMET R3 R0 K15
0x7C0C0200, // 0001 CALL R3 1
0x8C0C0710, // 0002 GETMET R3 R3 K16
0x5C140200, // 0003 MOVE R5 R1
0x7C0C0400, // 0004 CALL R3 2
0x4C100000, // 0005 LDNIL R4
0x20100604, // 0006 NE R4 R3 R4
0x78120010, // 0007 JMPF R4 #0019
0x58100023, // 0008 LDCONST R4 K35
0x6014000C, // 0009 GETGBL R5 G12
0x5C180600, // 000A MOVE R6 R3
0x7C140200, // 000B CALL R5 1
0x0C140B24, // 000C DIV R5 R5 K36
0x14180805, // 000D LT R6 R4 R5
0x781A0009, // 000E JMPF R6 #0019
0x8C180725, // 000F GETMET R6 R3 K37
0x08200924, // 0010 MUL R8 R4 K36
0x5425FFFD, // 0011 LDINT R9 -2
0x7C180600, // 0012 CALL R6 3
0x1C180C02, // 0013 EQ R6 R6 R2
0x781A0001, // 0014 JMPF R6 #0017
0x50180200, // 0015 LDBOOL R6 1 0
0x80040C00, // 0016 RET 1 R6
0x00100926, // 0017 ADD R4 R4 K38
0x7001FFF3, // 0018 JMP #000D
0x50100000, // 0019 LDBOOL R4 0 0
0x80040800, // 001A RET 1 R4
})
)
);
@ -1086,7 +1090,7 @@ be_local_closure(class_Matter_Plugin_get_clusters, /* name */
be_str_weak(get_clusters),
&be_const_str_solidified,
( &(const binstruction[ 2]) { /* code */
0x8804010F, // 0000 GETMBR R1 R0 K15
0x8804012F, // 0000 GETMBR R1 R0 K47
0x80040200, // 0001 RET 1 R1
})
)
@ -1110,12 +1114,13 @@ be_local_closure(class_Matter_Plugin_contains_cluster, /* name */
&be_ktab_class_Matter_Plugin, /* shared constants */
be_str_weak(contains_cluster),
&be_const_str_solidified,
( &(const binstruction[ 5]) { /* code */
0x8808010F, // 0000 GETMBR R2 R0 K15
0x8C08052F, // 0001 GETMET R2 R2 K47
0x5C100200, // 0002 MOVE R4 R1
0x7C080400, // 0003 CALL R2 2
0x80040400, // 0004 RET 1 R2
( &(const binstruction[ 6]) { /* code */
0x8C08010F, // 0000 GETMET R2 R0 K15
0x7C080200, // 0001 CALL R2 1
0x8C080530, // 0002 GETMET R2 R2 K48
0x5C100200, // 0003 MOVE R4 R1
0x7C080400, // 0004 CALL R2 2
0x80040400, // 0005 RET 1 R2
})
)
);
@ -1140,81 +1145,81 @@ be_local_closure(class_Matter_Plugin_read_attribute, /* name */
&be_const_str_solidified,
( &(const binstruction[169]) { /* code */
0xB8122600, // 0000 GETNGBL R4 K19
0x88100930, // 0001 GETMBR R4 R4 K48
0x88140531, // 0002 GETMBR R5 R2 K49
0x88180532, // 0003 GETMBR R6 R2 K50
0x88100931, // 0001 GETMBR R4 R4 K49
0x88140532, // 0002 GETMBR R5 R2 K50
0x88180533, // 0003 GETMBR R6 R2 K51
0x541E001C, // 0004 LDINT R7 29
0x1C1C0A07, // 0005 EQ R7 R5 R7
0x781E0050, // 0006 JMPF R7 #0058
0x1C1C0D23, // 0007 EQ R7 R6 K35
0x781E001B, // 0008 JMPF R7 #0025
0x8C1C0933, // 0009 GETMET R7 R4 K51
0x8C1C0934, // 0009 GETMET R7 R4 K52
0x7C1C0200, // 000A CALL R7 1
0x88200134, // 000B GETMBR R8 R0 K52
0x88200135, // 000B GETMBR R8 R0 K53
0x60240010, // 000C GETGBL R9 G16
0x8C281135, // 000D GETMET R10 R8 K53
0x8C281136, // 000D GETMET R10 R8 K54
0x7C280200, // 000E CALL R10 1
0x7C240200, // 000F CALL R9 1
0xA802000E, // 0010 EXBLK 0 #0020
0x5C281200, // 0011 MOVE R10 R9
0x7C280000, // 0012 CALL R10 0
0x8C2C0F36, // 0013 GETMET R11 R7 K54
0x8C2C0F37, // 0013 GETMET R11 R7 K55
0x7C2C0200, // 0014 CALL R11 1
0x8C301737, // 0015 GETMET R12 R11 K55
0x8C301738, // 0015 GETMET R12 R11 K56
0x58380023, // 0016 LDCONST R14 K35
0x883C0938, // 0017 GETMBR R15 R4 K56
0x883C0939, // 0017 GETMBR R15 R4 K57
0x5C401400, // 0018 MOVE R16 R10
0x7C300800, // 0019 CALL R12 4
0x8C301737, // 001A GETMET R12 R11 K55
0x8C301738, // 001A GETMET R12 R11 K56
0x58380026, // 001B LDCONST R14 K38
0x883C0938, // 001C GETMBR R15 R4 K56
0x883C0939, // 001C GETMBR R15 R4 K57
0x9440100A, // 001D GETIDX R16 R8 R10
0x7C300800, // 001E CALL R12 4
0x7001FFF0, // 001F JMP #0011
0x58240039, // 0020 LDCONST R9 K57
0x5824003A, // 0020 LDCONST R9 K58
0xAC240200, // 0021 CATCH R9 1 0
0xB0080000, // 0022 RAISE 2 R0 R0
0x80040E00, // 0023 RET 1 R7
0x70020032, // 0024 JMP #0058
0x1C1C0D26, // 0025 EQ R7 R6 K38
0x781E0013, // 0026 JMPF R7 #003B
0x8C1C0933, // 0027 GETMET R7 R4 K51
0x8C1C0934, // 0027 GETMET R7 R4 K52
0x7C1C0200, // 0028 CALL R7 1
0x60200010, // 0029 GETGBL R8 G16
0x8C24013A, // 002A GETMET R9 R0 K58
0x8C24013B, // 002A GETMET R9 R0 K59
0x7C240200, // 002B CALL R9 1
0x7C200200, // 002C CALL R8 1
0xA8020007, // 002D EXBLK 0 #0036
0x5C241000, // 002E MOVE R9 R8
0x7C240000, // 002F CALL R9 0
0x8C280F37, // 0030 GETMET R10 R7 K55
0x8C280F38, // 0030 GETMET R10 R7 K56
0x4C300000, // 0031 LDNIL R12
0x8834093B, // 0032 GETMBR R13 R4 K59
0x8834093C, // 0032 GETMBR R13 R4 K60
0x5C381200, // 0033 MOVE R14 R9
0x7C280800, // 0034 CALL R10 4
0x7001FFF7, // 0035 JMP #002E
0x58200039, // 0036 LDCONST R8 K57
0x5820003A, // 0036 LDCONST R8 K58
0xAC200200, // 0037 CATCH R8 1 0
0xB0080000, // 0038 RAISE 2 R0 R0
0x80040E00, // 0039 RET 1 R7
0x7002001C, // 003A JMP #0058
0x1C1C0D24, // 003B EQ R7 R6 K36
0x781E0003, // 003C JMPF R7 #0041
0x8C1C0933, // 003D GETMET R7 R4 K51
0x8C1C0934, // 003D GETMET R7 R4 K52
0x7C1C0200, // 003E CALL R7 1
0x80040E00, // 003F RET 1 R7
0x70020016, // 0040 JMP #0058
0x1C1C0D3C, // 0041 EQ R7 R6 K60
0x1C1C0D3D, // 0041 EQ R7 R6 K61
0x781E0003, // 0042 JMPF R7 #0047
0x8C1C0933, // 0043 GETMET R7 R4 K51
0x8C1C0934, // 0043 GETMET R7 R4 K52
0x7C1C0200, // 0044 CALL R7 1
0x80040E00, // 0045 RET 1 R7
0x70020010, // 0046 JMP #0058
0x541EFFFB, // 0047 LDINT R7 65532
0x1C1C0C07, // 0048 EQ R7 R6 R7
0x781E0005, // 0049 JMPF R7 #0050
0x8C1C073D, // 004A GETMET R7 R3 K61
0x8824093B, // 004B GETMBR R9 R4 K59
0x8C1C073E, // 004A GETMET R7 R3 K62
0x8824093C, // 004B GETMBR R9 R4 K60
0x58280023, // 004C LDCONST R10 K35
0x7C1C0600, // 004D CALL R7 3
0x80040E00, // 004E RET 1 R7
@ -1222,24 +1227,24 @@ be_local_closure(class_Matter_Plugin_read_attribute, /* name */
0x541EFFFC, // 0050 LDINT R7 65533
0x1C1C0C07, // 0051 EQ R7 R6 R7
0x781E0004, // 0052 JMPF R7 #0058
0x8C1C073D, // 0053 GETMET R7 R3 K61
0x8824093B, // 0054 GETMBR R9 R4 K59
0x8C1C073E, // 0053 GETMET R7 R3 K62
0x8824093C, // 0054 GETMBR R9 R4 K60
0x58280026, // 0055 LDCONST R10 K38
0x7C1C0600, // 0056 CALL R7 3
0x80040E00, // 0057 RET 1 R7
0x541EFFF7, // 0058 LDINT R7 65528
0x1C1C0C07, // 0059 EQ R7 R6 R7
0x781E0003, // 005A JMPF R7 #005F
0x8C1C0933, // 005B GETMET R7 R4 K51
0x8C1C0934, // 005B GETMET R7 R4 K52
0x7C1C0200, // 005C CALL R7 1
0x80040E00, // 005D RET 1 R7
0x70020047, // 005E JMP #00A7
0x541EFFFA, // 005F LDINT R7 65531
0x1C1C0C07, // 0060 EQ R7 R6 R7
0x781E001B, // 0061 JMPF R7 #007E
0x8C1C0933, // 0062 GETMET R7 R4 K51
0x8C1C0934, // 0062 GETMET R7 R4 K52
0x7C1C0200, // 0063 CALL R7 1
0x8C20013E, // 0064 GETMET R8 R0 K62
0x8C20013F, // 0064 GETMET R8 R0 K63
0x5C280A00, // 0065 MOVE R10 R5
0x7C200400, // 0066 CALL R8 2
0x4C240000, // 0067 LDNIL R9
@ -1253,9 +1258,9 @@ be_local_closure(class_Matter_Plugin_read_attribute, /* name */
0x58280023, // 006F LDCONST R10 K35
0x142C1409, // 0070 LT R11 R10 R9
0x782E0009, // 0071 JMPF R11 #007C
0x8C2C0F37, // 0072 GETMET R11 R7 K55
0x8C2C0F38, // 0072 GETMET R11 R7 K56
0x4C340000, // 0073 LDNIL R13
0x88380938, // 0074 GETMBR R14 R4 K56
0x88380939, // 0074 GETMBR R14 R4 K57
0x8C3C1125, // 0075 GETMET R15 R8 K37
0x08441524, // 0076 MUL R17 R10 K36
0x5449FFFD, // 0077 LDINT R18 -2
@ -1268,27 +1273,27 @@ be_local_closure(class_Matter_Plugin_read_attribute, /* name */
0x541EFFF9, // 007E LDINT R7 65530
0x1C1C0C07, // 007F EQ R7 R6 R7
0x781E0003, // 0080 JMPF R7 #0085
0x8C1C0933, // 0081 GETMET R7 R4 K51
0x8C1C0934, // 0081 GETMET R7 R4 K52
0x7C1C0200, // 0082 CALL R7 1
0x80040E00, // 0083 RET 1 R7
0x70020021, // 0084 JMP #00A7
0x541EFFF8, // 0085 LDINT R7 65529
0x1C1C0C07, // 0086 EQ R7 R6 R7
0x781E0003, // 0087 JMPF R7 #008C
0x8C1C0933, // 0088 GETMET R7 R4 K51
0x8C1C0934, // 0088 GETMET R7 R4 K52
0x7C1C0200, // 0089 CALL R7 1
0x80040E00, // 008A RET 1 R7
0x7002001A, // 008B JMP #00A7
0x541EFFFB, // 008C LDINT R7 65532
0x1C1C0C07, // 008D EQ R7 R6 R7
0x781E000A, // 008E JMPF R7 #009A
0x881C013F, // 008F GETMBR R7 R0 K63
0x881C0140, // 008F GETMBR R7 R0 K64
0x8C1C0F10, // 0090 GETMET R7 R7 K16
0x5C240A00, // 0091 MOVE R9 R5
0x58280023, // 0092 LDCONST R10 K35
0x7C1C0600, // 0093 CALL R7 3
0x8C20073D, // 0094 GETMET R8 R3 K61
0x8828093B, // 0095 GETMBR R10 R4 K59
0x8C20073E, // 0094 GETMET R8 R3 K62
0x8828093C, // 0095 GETMBR R10 R4 K60
0x5C2C0E00, // 0096 MOVE R11 R7
0x7C200600, // 0097 CALL R8 3
0x80041000, // 0098 RET 1 R8
@ -1296,13 +1301,13 @@ be_local_closure(class_Matter_Plugin_read_attribute, /* name */
0x541EFFFC, // 009A LDINT R7 65533
0x1C1C0C07, // 009B EQ R7 R6 R7
0x781E0009, // 009C JMPF R7 #00A7
0x881C0140, // 009D GETMBR R7 R0 K64
0x881C0141, // 009D GETMBR R7 R0 K65
0x8C1C0F10, // 009E GETMET R7 R7 K16
0x5C240A00, // 009F MOVE R9 R5
0x58280026, // 00A0 LDCONST R10 K38
0x7C1C0600, // 00A1 CALL R7 3
0x8C20073D, // 00A2 GETMET R8 R3 K61
0x8828093B, // 00A3 GETMBR R10 R4 K59
0x8C20073E, // 00A2 GETMET R8 R3 K62
0x8828093C, // 00A3 GETMBR R10 R4 K60
0x5C2C0E00, // 00A4 MOVE R11 R7
0x7C200600, // 00A5 CALL R8 3
0x80041000, // 00A6 RET 1 R8

View File

@ -3,8 +3,8 @@
* Generated code, don't edit *
\********************************************************************/
#include "be_constobj.h"
// compact class 'Matter_Autoconf' ktab size: 73, total: 90 (saved 136 bytes)
static const bvalue be_ktab_class_Matter_Autoconf[73] = {
// compact class 'Matter_Autoconf' ktab size: 74, total: 91 (saved 136 bytes)
static const bvalue be_ktab_class_Matter_Autoconf[74] = {
/* K0 */ be_nested_str_weak(device),
/* K1 */ be_nested_str_weak(k2l_num),
/* K2 */ be_nested_str_weak(plugins),
@ -12,72 +12,73 @@ static const bvalue be_ktab_class_Matter_Autoconf[73] = {
/* K4 */ be_nested_str_weak(matter),
/* K5 */ be_nested_str_weak(Plugin_Root),
/* K6 */ be_const_int(0),
/* K7 */ be_nested_str_weak(log),
/* K8 */ be_nested_str_weak(MTR_X3A_X20Configuring_X20endpoints),
/* K9 */ be_const_int(2),
/* K10 */ be_nested_str_weak(MTR_X3A_X20_X20_X20endpoint_X20_X3D_X20_X255i_X20type_X3A_X25s_X25s),
/* K11 */ be_nested_str_weak(root),
/* K12 */ be_nested_str_weak(),
/* K13 */ be_nested_str_weak(Plugin_Aggregator),
/* K14 */ be_nested_str_weak(AGGREGATOR_ENDPOINT),
/* K15 */ be_nested_str_weak(aggregator),
/* K16 */ be_nested_str_weak(find),
/* K17 */ be_nested_str_weak(type),
/* K18 */ be_nested_str_weak(MTR_X3A_X20no_X20class_X20name_X2C_X20skipping),
/* K19 */ be_const_int(3),
/* K20 */ be_nested_str_weak(MTR_X3A_X20only_X20one_X20root_X20node_X20allowed),
/* K21 */ be_nested_str_weak(plugins_classes),
/* K22 */ be_nested_str_weak(MTR_X3A_X20unknown_X20class_X20name_X20_X27),
/* K23 */ be_nested_str_weak(_X27_X20skipping),
/* K24 */ be_nested_str_weak(conf_to_log),
/* K25 */ be_nested_str_weak(MTR_X3A_X20Exception),
/* K26 */ be_nested_str_weak(_X7C),
/* K27 */ be_nested_str_weak(stop_iteration),
/* K28 */ be_nested_str_weak(tasmota),
/* K29 */ be_nested_str_weak(publish_result),
/* K30 */ be_nested_str_weak(_X7B_X22Matter_X22_X3A_X7B_X22Initialized_X22_X3A1_X7D_X7D),
/* K31 */ be_nested_str_weak(Matter),
/* K32 */ be_nested_str_weak(json),
/* K33 */ be_nested_str_weak(START_ENDPOINT),
/* K34 */ be_nested_str_weak(light),
/* K35 */ be_nested_str_weak(get),
/* K36 */ be_nested_str_weak(channels),
/* K37 */ be_const_int(1),
/* K38 */ be_nested_str_weak(light1),
/* K39 */ be_nested_str_weak(light2),
/* K40 */ be_nested_str_weak(light3),
/* K41 */ be_nested_str_weak(cmd),
/* K42 */ be_nested_str_weak(Status_X2013),
/* K43 */ be_nested_str_weak(MTR_X3A_X20Status_X2013_X20_X3D_X20),
/* K44 */ be_nested_str_weak(contains),
/* K45 */ be_nested_str_weak(StatusSHT),
/* K46 */ be_nested_str_weak(SHT),
/* K47 */ be_nested_str_weak(MTR_X3A_X20_X27_X25s_X27_X20_X3D_X20_X25s),
/* K48 */ be_nested_str_weak(Relay1),
/* K49 */ be_nested_str_weak(Relay2),
/* K50 */ be_nested_str_weak(MTR_X3A_X20relay1_X3D_X25s_X20relay2_X3D_X25s),
/* K51 */ be_nested_str_weak(TiltConfig),
/* K52 */ be_nested_str_weak(shutter_X2Btilt),
/* K53 */ be_nested_str_weak(shutter),
/* K54 */ be_nested_str_weak(get_power),
/* K55 */ be_nested_str_weak(relay),
/* K56 */ be_nested_str_weak(load),
/* K57 */ be_nested_str_weak(read_sensors),
/* K58 */ be_nested_str_weak(autoconf_sensors_list),
/* K59 */ be_nested_str_weak(k2l),
/* K60 */ be_nested_str_weak(Temperature),
/* K61 */ be_nested_str_weak(_X23Temperature),
/* K62 */ be_nested_str_weak(temperature),
/* K63 */ be_nested_str_weak(filter),
/* K64 */ be_nested_str_weak(Pressure),
/* K65 */ be_nested_str_weak(_X23Pressure),
/* K66 */ be_nested_str_weak(pressure),
/* K67 */ be_nested_str_weak(Illuminance),
/* K68 */ be_nested_str_weak(_X23Illuminance),
/* K69 */ be_nested_str_weak(illuminance),
/* K70 */ be_nested_str_weak(Humidity),
/* K71 */ be_nested_str_weak(_X23Humidity),
/* K72 */ be_nested_str_weak(humidity),
/* K7 */ be_nested_str_weak(find),
/* K8 */ be_nested_str_weak(0),
/* K9 */ be_nested_str_weak(log),
/* K10 */ be_nested_str_weak(MTR_X3A_X20Configuring_X20endpoints),
/* K11 */ be_const_int(2),
/* K12 */ be_nested_str_weak(MTR_X3A_X20_X20_X20endpoint_X20_X3D_X20_X255i_X20type_X3A_X25s_X25s),
/* K13 */ be_nested_str_weak(root),
/* K14 */ be_nested_str_weak(),
/* K15 */ be_nested_str_weak(Plugin_Aggregator),
/* K16 */ be_nested_str_weak(AGGREGATOR_ENDPOINT),
/* K17 */ be_nested_str_weak(aggregator),
/* K18 */ be_nested_str_weak(type),
/* K19 */ be_nested_str_weak(MTR_X3A_X20no_X20class_X20name_X2C_X20skipping),
/* K20 */ be_const_int(3),
/* K21 */ be_nested_str_weak(MTR_X3A_X20only_X20one_X20root_X20node_X20allowed),
/* K22 */ be_nested_str_weak(plugins_classes),
/* K23 */ be_nested_str_weak(MTR_X3A_X20unknown_X20class_X20name_X20_X27),
/* K24 */ be_nested_str_weak(_X27_X20skipping),
/* K25 */ be_nested_str_weak(conf_to_log),
/* K26 */ be_nested_str_weak(MTR_X3A_X20Exception),
/* K27 */ be_nested_str_weak(_X7C),
/* K28 */ be_nested_str_weak(stop_iteration),
/* K29 */ be_nested_str_weak(tasmota),
/* K30 */ be_nested_str_weak(publish_result),
/* K31 */ be_nested_str_weak(_X7B_X22Matter_X22_X3A_X7B_X22Initialized_X22_X3A1_X7D_X7D),
/* K32 */ be_nested_str_weak(Matter),
/* K33 */ be_nested_str_weak(json),
/* K34 */ be_nested_str_weak(START_ENDPOINT),
/* K35 */ be_nested_str_weak(light),
/* K36 */ be_nested_str_weak(get),
/* K37 */ be_nested_str_weak(channels),
/* K38 */ be_const_int(1),
/* K39 */ be_nested_str_weak(light1),
/* K40 */ be_nested_str_weak(light2),
/* K41 */ be_nested_str_weak(light3),
/* K42 */ be_nested_str_weak(cmd),
/* K43 */ be_nested_str_weak(Status_X2013),
/* K44 */ be_nested_str_weak(MTR_X3A_X20Status_X2013_X20_X3D_X20),
/* K45 */ be_nested_str_weak(contains),
/* K46 */ be_nested_str_weak(StatusSHT),
/* K47 */ be_nested_str_weak(SHT),
/* K48 */ be_nested_str_weak(MTR_X3A_X20_X27_X25s_X27_X20_X3D_X20_X25s),
/* K49 */ be_nested_str_weak(Relay1),
/* K50 */ be_nested_str_weak(Relay2),
/* K51 */ be_nested_str_weak(MTR_X3A_X20relay1_X3D_X25s_X20relay2_X3D_X25s),
/* K52 */ be_nested_str_weak(TiltConfig),
/* K53 */ be_nested_str_weak(shutter_X2Btilt),
/* K54 */ be_nested_str_weak(shutter),
/* K55 */ be_nested_str_weak(get_power),
/* K56 */ be_nested_str_weak(relay),
/* K57 */ be_nested_str_weak(load),
/* K58 */ be_nested_str_weak(read_sensors),
/* K59 */ be_nested_str_weak(autoconf_sensors_list),
/* K60 */ be_nested_str_weak(k2l),
/* K61 */ be_nested_str_weak(Temperature),
/* K62 */ be_nested_str_weak(_X23Temperature),
/* K63 */ be_nested_str_weak(temperature),
/* K64 */ be_nested_str_weak(filter),
/* K65 */ be_nested_str_weak(Pressure),
/* K66 */ be_nested_str_weak(_X23Pressure),
/* K67 */ be_nested_str_weak(pressure),
/* K68 */ be_nested_str_weak(Illuminance),
/* K69 */ be_nested_str_weak(_X23Illuminance),
/* K70 */ be_nested_str_weak(illuminance),
/* K71 */ be_nested_str_weak(Humidity),
/* K72 */ be_nested_str_weak(_X23Humidity),
/* K73 */ be_nested_str_weak(humidity),
};
@ -99,7 +100,7 @@ be_local_closure(class_Matter_Autoconf_instantiate_plugins_from_config, /* nam
&be_ktab_class_Matter_Autoconf, /* shared constants */
be_str_weak(instantiate_plugins_from_config),
&be_const_str_solidified,
( &(const binstruction[148]) { /* code */
( &(const binstruction[151]) { /* code */
0x88080100, // 0000 GETMBR R2 R0 K0
0x8C080501, // 0001 GETMET R2 R2 K1
0x5C100200, // 0002 MOVE R4 R1
@ -111,143 +112,146 @@ be_local_closure(class_Matter_Autoconf_instantiate_plugins_from_config, /* nam
0x8C180D05, // 0008 GETMET R6 R6 K5
0x88200100, // 0009 GETMBR R8 R0 K0
0x58240006, // 000A LDCONST R9 K6
0x60280013, // 000B GETGBL R10 G19
0x7C280000, // 000C CALL R10 0
0x7C180800, // 000D CALL R6 4
0x7C100400, // 000E CALL R4 2
0xB8120E00, // 000F GETNGBL R4 K7
0x58140008, // 0010 LDCONST R5 K8
0x58180009, // 0011 LDCONST R6 K9
0x7C100400, // 0012 CALL R4 2
0xB8120E00, // 0013 GETNGBL R4 K7
0x60140018, // 0014 GETGBL R5 G24
0x5818000A, // 0015 LDCONST R6 K10
0x581C0006, // 0016 LDCONST R7 K6
0x5820000B, // 0017 LDCONST R8 K11
0x5824000C, // 0018 LDCONST R9 K12
0x7C140800, // 0019 CALL R5 4
0x58180009, // 001A LDCONST R6 K9
0x7C100400, // 001B CALL R4 2
0x8C100703, // 001C GETMET R4 R3 K3
0xB81A0800, // 001D GETNGBL R6 K4
0x8C180D0D, // 001E GETMET R6 R6 K13
0x88200100, // 001F GETMBR R8 R0 K0
0xB8260800, // 0020 GETNGBL R9 K4
0x8824130E, // 0021 GETMBR R9 R9 K14
0x60280013, // 0022 GETGBL R10 G19
0x7C280000, // 0023 CALL R10 0
0x7C180800, // 0024 CALL R6 4
0x7C100400, // 0025 CALL R4 2
0xB8120E00, // 0026 GETNGBL R4 K7
0x60140018, // 0027 GETGBL R5 G24
0x5818000A, // 0028 LDCONST R6 K10
0xB81E0800, // 0029 GETNGBL R7 K4
0x881C0F0E, // 002A GETMBR R7 R7 K14
0x5820000F, // 002B LDCONST R8 K15
0x5824000C, // 002C LDCONST R9 K12
0x7C140800, // 002D CALL R5 4
0x58180009, // 002E LDCONST R6 K9
0x7C100400, // 002F CALL R4 2
0x60100010, // 0030 GETGBL R4 G16
0x5C140400, // 0031 MOVE R5 R2
0x7C100200, // 0032 CALL R4 1
0xA8020056, // 0033 EXBLK 0 #008B
0x5C140800, // 0034 MOVE R5 R4
0x7C140000, // 0035 CALL R5 0
0x1C180B06, // 0036 EQ R6 R5 K6
0x781A0000, // 0037 JMPF R6 #0039
0x7001FFFA, // 0038 JMP #0034
0xA802003F, // 0039 EXBLK 0 #007A
0x60180008, // 003A GETGBL R6 G8
0x5C1C0A00, // 003B MOVE R7 R5
0x7C180200, // 003C CALL R6 1
0x94180206, // 003D GETIDX R6 R1 R6
0x8C1C0D10, // 003E GETMET R7 R6 K16
0x58240011, // 003F LDCONST R9 K17
0x7C1C0400, // 0040 CALL R7 2
0x4C200000, // 0041 LDNIL R8
0x1C200E08, // 0042 EQ R8 R7 R8
0x78220005, // 0043 JMPF R8 #004A
0xB8220E00, // 0044 GETNGBL R8 K7
0x58240012, // 0045 LDCONST R9 K18
0x58280013, // 0046 LDCONST R10 K19
0x7C200400, // 0047 CALL R8 2
0xA8040001, // 0048 EXBLK 1 1
0x7001FFE9, // 0049 JMP #0034
0x1C200F0B, // 004A EQ R8 R7 K11
0x78220005, // 004B JMPF R8 #0052
0xB8220E00, // 004C GETNGBL R8 K7
0x58240014, // 004D LDCONST R9 K20
0x58280013, // 004E LDCONST R10 K19
0x7C200400, // 004F CALL R8 2
0xA8040001, // 0050 EXBLK 1 1
0x7001FFE1, // 0051 JMP #0034
0x88200100, // 0052 GETMBR R8 R0 K0
0x88201115, // 0053 GETMBR R8 R8 K21
0x8C201110, // 0054 GETMET R8 R8 K16
0x5C280E00, // 0055 MOVE R10 R7
0x7C200400, // 0056 CALL R8 2
0x4C240000, // 0057 LDNIL R9
0x1C241009, // 0058 EQ R9 R8 R9
0x78260009, // 0059 JMPF R9 #0064
0xB8260E00, // 005A GETNGBL R9 K7
0x60280008, // 005B GETGBL R10 G8
0x5C2C0E00, // 005C MOVE R11 R7
0x7C280200, // 005D CALL R10 1
0x002A2C0A, // 005E ADD R10 K22 R10
0x00281517, // 005F ADD R10 R10 K23
0x582C0009, // 0060 LDCONST R11 K9
0x7C240400, // 0061 CALL R9 2
0xA8040001, // 0062 EXBLK 1 1
0x7001FFCF, // 0063 JMP #0034
0x5C241000, // 0064 MOVE R9 R8
0x88280100, // 0065 GETMBR R10 R0 K0
0x5C2C0A00, // 0066 MOVE R11 R5
0x5C300C00, // 0067 MOVE R12 R6
0x7C240600, // 0068 CALL R9 3
0x8C280703, // 0069 GETMET R10 R3 K3
0x5C301200, // 006A MOVE R12 R9
0x7C280400, // 006B CALL R10 2
0xB82A0E00, // 006C GETNGBL R10 K7
0x602C0018, // 006D GETGBL R11 G24
0x5830000A, // 006E LDCONST R12 K10
0x5C340A00, // 006F MOVE R13 R5
0x5C380E00, // 0070 MOVE R14 R7
0x883C0100, // 0071 GETMBR R15 R0 K0
0x8C3C1F18, // 0072 GETMET R15 R15 K24
0x5C440C00, // 0073 MOVE R17 R6
0x7C3C0400, // 0074 CALL R15 2
0x7C2C0800, // 0075 CALL R11 4
0x58300009, // 0076 LDCONST R12 K9
0x7C280400, // 0077 CALL R10 2
0xA8040001, // 0078 EXBLK 1 1
0x7002000F, // 0079 JMP #008A
0xAC180002, // 007A CATCH R6 0 2
0x7002000C, // 007B JMP #0089
0xB8220E00, // 007C GETNGBL R8 K7
0x60240008, // 007D GETGBL R9 G8
0x5C280C00, // 007E MOVE R10 R6
0x7C240200, // 007F CALL R9 1
0x00263209, // 0080 ADD R9 K25 R9
0x0024131A, // 0081 ADD R9 R9 K26
0x60280008, // 0082 GETGBL R10 G8
0x5C2C0E00, // 0083 MOVE R11 R7
0x7C280200, // 0084 CALL R10 1
0x0024120A, // 0085 ADD R9 R9 R10
0x58280009, // 0086 LDCONST R10 K9
0x7C200400, // 0087 CALL R8 2
0x70020000, // 0088 JMP #008A
0xB0080000, // 0089 RAISE 2 R0 R0
0x7001FFA8, // 008A JMP #0034
0x5810001B, // 008B LDCONST R4 K27
0xAC100200, // 008C CATCH R4 1 0
0xB0080000, // 008D RAISE 2 R0 R0
0xB8123800, // 008E GETNGBL R4 K28
0x8C10091D, // 008F GETMET R4 R4 K29
0x5818001E, // 0090 LDCONST R6 K30
0x581C001F, // 0091 LDCONST R7 K31
0x7C100600, // 0092 CALL R4 3
0x80000000, // 0093 RET 0
0x8C280307, // 000B GETMET R10 R1 K7
0x58300008, // 000C LDCONST R12 K8
0x60340013, // 000D GETGBL R13 G19
0x7C340000, // 000E CALL R13 0
0x7C280600, // 000F CALL R10 3
0x7C180800, // 0010 CALL R6 4
0x7C100400, // 0011 CALL R4 2
0xB8121200, // 0012 GETNGBL R4 K9
0x5814000A, // 0013 LDCONST R5 K10
0x5818000B, // 0014 LDCONST R6 K11
0x7C100400, // 0015 CALL R4 2
0xB8121200, // 0016 GETNGBL R4 K9
0x60140018, // 0017 GETGBL R5 G24
0x5818000C, // 0018 LDCONST R6 K12
0x581C0006, // 0019 LDCONST R7 K6
0x5820000D, // 001A LDCONST R8 K13
0x5824000E, // 001B LDCONST R9 K14
0x7C140800, // 001C CALL R5 4
0x5818000B, // 001D LDCONST R6 K11
0x7C100400, // 001E CALL R4 2
0x8C100703, // 001F GETMET R4 R3 K3
0xB81A0800, // 0020 GETNGBL R6 K4
0x8C180D0F, // 0021 GETMET R6 R6 K15
0x88200100, // 0022 GETMBR R8 R0 K0
0xB8260800, // 0023 GETNGBL R9 K4
0x88241310, // 0024 GETMBR R9 R9 K16
0x60280013, // 0025 GETGBL R10 G19
0x7C280000, // 0026 CALL R10 0
0x7C180800, // 0027 CALL R6 4
0x7C100400, // 0028 CALL R4 2
0xB8121200, // 0029 GETNGBL R4 K9
0x60140018, // 002A GETGBL R5 G24
0x5818000C, // 002B LDCONST R6 K12
0xB81E0800, // 002C GETNGBL R7 K4
0x881C0F10, // 002D GETMBR R7 R7 K16
0x58200011, // 002E LDCONST R8 K17
0x5824000E, // 002F LDCONST R9 K14
0x7C140800, // 0030 CALL R5 4
0x5818000B, // 0031 LDCONST R6 K11
0x7C100400, // 0032 CALL R4 2
0x60100010, // 0033 GETGBL R4 G16
0x5C140400, // 0034 MOVE R5 R2
0x7C100200, // 0035 CALL R4 1
0xA8020056, // 0036 EXBLK 0 #008E
0x5C140800, // 0037 MOVE R5 R4
0x7C140000, // 0038 CALL R5 0
0x1C180B06, // 0039 EQ R6 R5 K6
0x781A0000, // 003A JMPF R6 #003C
0x7001FFFA, // 003B JMP #0037
0xA802003F, // 003C EXBLK 0 #007D
0x60180008, // 003D GETGBL R6 G8
0x5C1C0A00, // 003E MOVE R7 R5
0x7C180200, // 003F CALL R6 1
0x94180206, // 0040 GETIDX R6 R1 R6
0x8C1C0D07, // 0041 GETMET R7 R6 K7
0x58240012, // 0042 LDCONST R9 K18
0x7C1C0400, // 0043 CALL R7 2
0x4C200000, // 0044 LDNIL R8
0x1C200E08, // 0045 EQ R8 R7 R8
0x78220005, // 0046 JMPF R8 #004D
0xB8221200, // 0047 GETNGBL R8 K9
0x58240013, // 0048 LDCONST R9 K19
0x58280014, // 0049 LDCONST R10 K20
0x7C200400, // 004A CALL R8 2
0xA8040001, // 004B EXBLK 1 1
0x7001FFE9, // 004C JMP #0037
0x1C200F0D, // 004D EQ R8 R7 K13
0x78220005, // 004E JMPF R8 #0055
0xB8221200, // 004F GETNGBL R8 K9
0x58240015, // 0050 LDCONST R9 K21
0x58280014, // 0051 LDCONST R10 K20
0x7C200400, // 0052 CALL R8 2
0xA8040001, // 0053 EXBLK 1 1
0x7001FFE1, // 0054 JMP #0037
0x88200100, // 0055 GETMBR R8 R0 K0
0x88201116, // 0056 GETMBR R8 R8 K22
0x8C201107, // 0057 GETMET R8 R8 K7
0x5C280E00, // 0058 MOVE R10 R7
0x7C200400, // 0059 CALL R8 2
0x4C240000, // 005A LDNIL R9
0x1C241009, // 005B EQ R9 R8 R9
0x78260009, // 005C JMPF R9 #0067
0xB8261200, // 005D GETNGBL R9 K9
0x60280008, // 005E GETGBL R10 G8
0x5C2C0E00, // 005F MOVE R11 R7
0x7C280200, // 0060 CALL R10 1
0x002A2E0A, // 0061 ADD R10 K23 R10
0x00281518, // 0062 ADD R10 R10 K24
0x582C000B, // 0063 LDCONST R11 K11
0x7C240400, // 0064 CALL R9 2
0xA8040001, // 0065 EXBLK 1 1
0x7001FFCF, // 0066 JMP #0037
0x5C241000, // 0067 MOVE R9 R8
0x88280100, // 0068 GETMBR R10 R0 K0
0x5C2C0A00, // 0069 MOVE R11 R5
0x5C300C00, // 006A MOVE R12 R6
0x7C240600, // 006B CALL R9 3
0x8C280703, // 006C GETMET R10 R3 K3
0x5C301200, // 006D MOVE R12 R9
0x7C280400, // 006E CALL R10 2
0xB82A1200, // 006F GETNGBL R10 K9
0x602C0018, // 0070 GETGBL R11 G24
0x5830000C, // 0071 LDCONST R12 K12
0x5C340A00, // 0072 MOVE R13 R5
0x5C380E00, // 0073 MOVE R14 R7
0x883C0100, // 0074 GETMBR R15 R0 K0
0x8C3C1F19, // 0075 GETMET R15 R15 K25
0x5C440C00, // 0076 MOVE R17 R6
0x7C3C0400, // 0077 CALL R15 2
0x7C2C0800, // 0078 CALL R11 4
0x5830000B, // 0079 LDCONST R12 K11
0x7C280400, // 007A CALL R10 2
0xA8040001, // 007B EXBLK 1 1
0x7002000F, // 007C JMP #008D
0xAC180002, // 007D CATCH R6 0 2
0x7002000C, // 007E JMP #008C
0xB8221200, // 007F GETNGBL R8 K9
0x60240008, // 0080 GETGBL R9 G8
0x5C280C00, // 0081 MOVE R10 R6
0x7C240200, // 0082 CALL R9 1
0x00263409, // 0083 ADD R9 K26 R9
0x0024131B, // 0084 ADD R9 R9 K27
0x60280008, // 0085 GETGBL R10 G8
0x5C2C0E00, // 0086 MOVE R11 R7
0x7C280200, // 0087 CALL R10 1
0x0024120A, // 0088 ADD R9 R9 R10
0x5828000B, // 0089 LDCONST R10 K11
0x7C200400, // 008A CALL R8 2
0x70020000, // 008B JMP #008D
0xB0080000, // 008C RAISE 2 R0 R0
0x7001FFA8, // 008D JMP #0037
0x5810001C, // 008E LDCONST R4 K28
0xAC100200, // 008F CATCH R4 1 0
0xB0080000, // 0090 RAISE 2 R0 R0
0xB8123A00, // 0091 GETNGBL R4 K29
0x8C10091E, // 0092 GETMET R4 R4 K30
0x5818001F, // 0093 LDCONST R6 K31
0x581C0020, // 0094 LDCONST R7 K32
0x7C100600, // 0095 CALL R4 3
0x80000000, // 0096 RET 0
})
)
);
@ -271,41 +275,41 @@ be_local_closure(class_Matter_Autoconf_autoconf_device_map, /* name */
be_str_weak(autoconf_device_map),
&be_const_str_solidified,
( &(const binstruction[262]) { /* code */
0xA4064000, // 0000 IMPORT R1 K32
0xA4064200, // 0000 IMPORT R1 K33
0x60080013, // 0001 GETGBL R2 G19
0x7C080000, // 0002 CALL R2 0
0xB80E0800, // 0003 GETNGBL R3 K4
0x880C0721, // 0004 GETMBR R3 R3 K33
0x880C0722, // 0004 GETMBR R3 R3 K34
0x58100006, // 0005 LDCONST R4 K6
0xA4164400, // 0006 IMPORT R5 K34
0x8C180B23, // 0007 GETMET R6 R5 K35
0xA4164600, // 0006 IMPORT R5 K35
0x8C180B24, // 0007 GETMET R6 R5 K36
0x58200006, // 0008 LDCONST R8 K6
0x7C180400, // 0009 CALL R6 2
0x4C1C0000, // 000A LDNIL R7
0x201C0C07, // 000B NE R7 R6 R7
0x781E0066, // 000C JMPF R7 #0074
0x601C000C, // 000D GETGBL R7 G12
0x8C200D10, // 000E GETMET R8 R6 K16
0x58280024, // 000F LDCONST R10 K36
0x582C000C, // 0010 LDCONST R11 K12
0x8C200D07, // 000E GETMET R8 R6 K7
0x58280025, // 000F LDCONST R10 K37
0x582C000E, // 0010 LDCONST R11 K14
0x7C200600, // 0011 CALL R8 3
0x7C1C0200, // 0012 CALL R7 1
0x58100025, // 0013 LDCONST R4 K37
0x58100026, // 0013 LDCONST R4 K38
0x24200F06, // 0014 GT R8 R7 K6
0x7822005D, // 0015 JMPF R8 #0074
0x1C200F25, // 0016 EQ R8 R7 K37
0x1C200F26, // 0016 EQ R8 R7 K38
0x7822001E, // 0017 JMPF R8 #0037
0x60200008, // 0018 GETGBL R8 G8
0x5C240600, // 0019 MOVE R9 R3
0x7C200200, // 001A CALL R8 1
0x60240013, // 001B GETGBL R9 G19
0x7C240000, // 001C CALL R9 0
0x98262326, // 001D SETIDX R9 K17 K38
0x98262527, // 001D SETIDX R9 K18 K39
0x98081009, // 001E SETIDX R2 R8 R9
0x000C0725, // 001F ADD R3 R3 K37
0x58200025, // 0020 LDCONST R8 K37
0x000C0726, // 001F ADD R3 R3 K38
0x58200026, // 0020 LDCONST R8 K38
0x4C240000, // 0021 LDNIL R9
0x8C280B23, // 0022 GETMET R10 R5 K35
0x8C280B24, // 0022 GETMET R10 R5 K36
0x5C301000, // 0023 MOVE R12 R8
0x7C280400, // 0024 CALL R10 2
0x5C241400, // 0025 MOVE R9 R10
@ -317,152 +321,152 @@ be_local_closure(class_Matter_Autoconf_autoconf_device_map, /* name */
0x7C280200, // 002B CALL R10 1
0x602C0013, // 002C GETGBL R11 G19
0x7C2C0000, // 002D CALL R11 0
0x982E2326, // 002E SETIDX R11 K17 K38
0x00301125, // 002F ADD R12 R8 K37
0x982E440C, // 0030 SETIDX R11 K34 R12
0x982E2527, // 002E SETIDX R11 K18 K39
0x00301126, // 002F ADD R12 R8 K38
0x982E460C, // 0030 SETIDX R11 K35 R12
0x9808140B, // 0031 SETIDX R2 R10 R11
0x000C0725, // 0032 ADD R3 R3 K37
0x00100925, // 0033 ADD R4 R4 K37
0x00201125, // 0034 ADD R8 R8 K37
0x000C0726, // 0032 ADD R3 R3 K38
0x00100926, // 0033 ADD R4 R4 K38
0x00201126, // 0034 ADD R8 R8 K38
0x7001FFEB, // 0035 JMP #0022
0x7002003C, // 0036 JMP #0074
0x1C200F09, // 0037 EQ R8 R7 K9
0x1C200F0B, // 0037 EQ R8 R7 K11
0x78220008, // 0038 JMPF R8 #0042
0x60200008, // 0039 GETGBL R8 G8
0x5C240600, // 003A MOVE R9 R3
0x7C200200, // 003B CALL R8 1
0x60240013, // 003C GETGBL R9 G19
0x7C240000, // 003D CALL R9 0
0x98262327, // 003E SETIDX R9 K17 K39
0x98262528, // 003E SETIDX R9 K18 K40
0x98081009, // 003F SETIDX R2 R8 R9
0x000C0725, // 0040 ADD R3 R3 K37
0x000C0726, // 0040 ADD R3 R3 K38
0x70020031, // 0041 JMP #0074
0x1C200F13, // 0042 EQ R8 R7 K19
0x1C200F14, // 0042 EQ R8 R7 K20
0x7822002B, // 0043 JMPF R8 #0070
0x60200008, // 0044 GETGBL R8 G8
0x5C240600, // 0045 MOVE R9 R3
0x7C200200, // 0046 CALL R8 1
0x60240013, // 0047 GETGBL R9 G19
0x7C240000, // 0048 CALL R9 0
0x98262328, // 0049 SETIDX R9 K17 K40
0x98262529, // 0049 SETIDX R9 K18 K41
0x98081009, // 004A SETIDX R2 R8 R9
0x000C0725, // 004B ADD R3 R3 K37
0x8C200B23, // 004C GETMET R8 R5 K35
0x58280025, // 004D LDCONST R10 K37
0x000C0726, // 004B ADD R3 R3 K38
0x8C200B24, // 004C GETMET R8 R5 K36
0x58280026, // 004D LDCONST R10 K38
0x7C200400, // 004E CALL R8 2
0x4C240000, // 004F LDNIL R9
0x20241009, // 0050 NE R9 R8 R9
0x7826001C, // 0051 JMPF R9 #006F
0x6024000C, // 0052 GETGBL R9 G12
0x8C281110, // 0053 GETMET R10 R8 K16
0x58300024, // 0054 LDCONST R12 K36
0x5834000C, // 0055 LDCONST R13 K12
0x8C281107, // 0053 GETMET R10 R8 K7
0x58300025, // 0054 LDCONST R12 K37
0x5834000E, // 0055 LDCONST R13 K14
0x7C280600, // 0056 CALL R10 3
0x7C240200, // 0057 CALL R9 1
0x1C281325, // 0058 EQ R10 R9 K37
0x1C281326, // 0058 EQ R10 R9 K38
0x782A0009, // 0059 JMPF R10 #0064
0x60280008, // 005A GETGBL R10 G8
0x5C2C0600, // 005B MOVE R11 R3
0x7C280200, // 005C CALL R10 1
0x602C0013, // 005D GETGBL R11 G19
0x7C2C0000, // 005E CALL R11 0
0x982E2326, // 005F SETIDX R11 K17 K38
0x982E2527, // 005F SETIDX R11 K18 K39
0x9808140B, // 0060 SETIDX R2 R10 R11
0x000C0725, // 0061 ADD R3 R3 K37
0x00100925, // 0062 ADD R4 R4 K37
0x000C0726, // 0061 ADD R3 R3 K38
0x00100926, // 0062 ADD R4 R4 K38
0x7002000A, // 0063 JMP #006F
0x1C281309, // 0064 EQ R10 R9 K9
0x1C28130B, // 0064 EQ R10 R9 K11
0x782A0008, // 0065 JMPF R10 #006F
0x60280008, // 0066 GETGBL R10 G8
0x5C2C0600, // 0067 MOVE R11 R3
0x7C280200, // 0068 CALL R10 1
0x602C0013, // 0069 GETGBL R11 G19
0x7C2C0000, // 006A CALL R11 0
0x982E2327, // 006B SETIDX R11 K17 K39
0x982E2528, // 006B SETIDX R11 K18 K40
0x9808140B, // 006C SETIDX R2 R10 R11
0x000C0725, // 006D ADD R3 R3 K37
0x00100925, // 006E ADD R4 R4 K37
0x000C0726, // 006D ADD R3 R3 K38
0x00100926, // 006E ADD R4 R4 K38
0x70020003, // 006F JMP #0074
0x54220003, // 0070 LDINT R8 4
0x1C200E08, // 0071 EQ R8 R7 R8
0x78220000, // 0072 JMPF R8 #0074
0x7001FFFF, // 0073 JMP #0074
0xB81E3800, // 0074 GETNGBL R7 K28
0x8C1C0F29, // 0075 GETMET R7 R7 K41
0x5824002A, // 0076 LDCONST R9 K42
0xB81E3A00, // 0074 GETNGBL R7 K29
0x8C1C0F2A, // 0075 GETMET R7 R7 K42
0x5824002B, // 0076 LDCONST R9 K43
0x50280200, // 0077 LDBOOL R10 1 0
0x7C1C0600, // 0078 CALL R7 3
0x60200012, // 0079 GETGBL R8 G18
0x7C200000, // 007A CALL R8 0
0xB8260E00, // 007B GETNGBL R9 K7
0xB8261200, // 007B GETNGBL R9 K9
0x60280008, // 007C GETGBL R10 G8
0x5C2C0E00, // 007D MOVE R11 R7
0x7C280200, // 007E CALL R10 1
0x002A560A, // 007F ADD R10 K43 R10
0x582C0013, // 0080 LDCONST R11 K19
0x002A580A, // 007F ADD R10 K44 R10
0x582C0014, // 0080 LDCONST R11 K20
0x7C240400, // 0081 CALL R9 2
0x4C240000, // 0082 LDNIL R9
0x20240E09, // 0083 NE R9 R7 R9
0x7826004D, // 0084 JMPF R9 #00D3
0x8C240F2C, // 0085 GETMET R9 R7 K44
0x582C002D, // 0086 LDCONST R11 K45
0x8C240F2D, // 0085 GETMET R9 R7 K45
0x582C002E, // 0086 LDCONST R11 K46
0x7C240400, // 0087 CALL R9 2
0x78260049, // 0088 JMPF R9 #00D3
0x941C0F2D, // 0089 GETIDX R7 R7 K45
0x941C0F2E, // 0089 GETIDX R7 R7 K46
0x58240006, // 008A LDCONST R9 K6
0x50280200, // 008B LDBOOL R10 1 0
0x782A0045, // 008C JMPF R10 #00D3
0x60280008, // 008D GETGBL R10 G8
0x5C2C1200, // 008E MOVE R11 R9
0x7C280200, // 008F CALL R10 1
0x002A5C0A, // 0090 ADD R10 K46 R10
0x8C2C0F2C, // 0091 GETMET R11 R7 K44
0x002A5E0A, // 0090 ADD R10 K47 R10
0x8C2C0F2D, // 0091 GETMET R11 R7 K45
0x5C341400, // 0092 MOVE R13 R10
0x7C2C0400, // 0093 CALL R11 2
0x742E0000, // 0094 JMPT R11 #0096
0x7002003C, // 0095 JMP #00D3
0x942C0E0A, // 0096 GETIDX R11 R7 R10
0xB8320E00, // 0097 GETNGBL R12 K7
0xB8321200, // 0097 GETNGBL R12 K9
0x60340018, // 0098 GETGBL R13 G24
0x5838002F, // 0099 LDCONST R14 K47
0x58380030, // 0099 LDCONST R14 K48
0x5C3C1400, // 009A MOVE R15 R10
0x60400008, // 009B GETGBL R16 G8
0x5C441600, // 009C MOVE R17 R11
0x7C400200, // 009D CALL R16 1
0x7C340600, // 009E CALL R13 3
0x58380013, // 009F LDCONST R14 K19
0x58380014, // 009F LDCONST R14 K20
0x7C300400, // 00A0 CALL R12 2
0x8C301710, // 00A1 GETMET R12 R11 K16
0x58380030, // 00A2 LDCONST R14 K48
0x8C301707, // 00A1 GETMET R12 R11 K7
0x58380031, // 00A2 LDCONST R14 K49
0x543DFFFE, // 00A3 LDINT R15 -1
0x7C300600, // 00A4 CALL R12 3
0x8C341710, // 00A5 GETMET R13 R11 K16
0x583C0031, // 00A6 LDCONST R15 K49
0x8C341707, // 00A5 GETMET R13 R11 K7
0x583C0032, // 00A6 LDCONST R15 K50
0x5441FFFE, // 00A7 LDINT R16 -1
0x7C340600, // 00A8 CALL R13 3
0x24381906, // 00A9 GT R14 R12 K6
0x783A0002, // 00AA JMPF R14 #00AE
0x8C381103, // 00AB GETMET R14 R8 K3
0x04401925, // 00AC SUB R16 R12 K37
0x04401926, // 00AC SUB R16 R12 K38
0x7C380400, // 00AD CALL R14 2
0x24381B06, // 00AE GT R14 R13 K6
0x783A0002, // 00AF JMPF R14 #00B3
0x8C381103, // 00B0 GETMET R14 R8 K3
0x04401B25, // 00B1 SUB R16 R13 K37
0x04401B26, // 00B1 SUB R16 R13 K38
0x7C380400, // 00B2 CALL R14 2
0xB83A0E00, // 00B3 GETNGBL R14 K7
0xB83A1200, // 00B3 GETNGBL R14 K9
0x603C0018, // 00B4 GETGBL R15 G24
0x58400032, // 00B5 LDCONST R16 K50
0x58400033, // 00B5 LDCONST R16 K51
0x5C441800, // 00B6 MOVE R17 R12
0x5C481A00, // 00B7 MOVE R18 R13
0x7C3C0600, // 00B8 CALL R15 3
0x58400013, // 00B9 LDCONST R16 K19
0x58400014, // 00B9 LDCONST R16 K20
0x7C380400, // 00BA CALL R14 2
0x8C381710, // 00BB GETMET R14 R11 K16
0x58400033, // 00BC LDCONST R16 K51
0x8C381707, // 00BB GETMET R14 R11 K7
0x58400034, // 00BC LDCONST R16 K52
0x7C380400, // 00BD CALL R14 2
0x783A0002, // 00BE JMPF R14 #00C2
0x943C1D09, // 00BF GETIDX R15 R14 K9
0x943C1D0B, // 00BF GETIDX R15 R14 K11
0x243C1F06, // 00C0 GT R15 R15 K6
0x743E0000, // 00C1 JMPT R15 #00C3
0x503C0001, // 00C2 LDBOOL R15 0 1
@ -473,25 +477,25 @@ be_local_closure(class_Matter_Autoconf_autoconf_device_map, /* name */
0x60440013, // 00C7 GETGBL R17 G19
0x7C440000, // 00C8 CALL R17 0
0x783E0001, // 00C9 JMPF R15 #00CC
0x58480034, // 00CA LDCONST R18 K52
0x58480035, // 00CA LDCONST R18 K53
0x70020000, // 00CB JMP #00CD
0x58480035, // 00CC LDCONST R18 K53
0x98462212, // 00CD SETIDX R17 K17 R18
0x98466A09, // 00CE SETIDX R17 K53 R9
0x58480036, // 00CC LDCONST R18 K54
0x98462412, // 00CD SETIDX R17 K18 R18
0x98466C09, // 00CE SETIDX R17 K54 R9
0x98082011, // 00CF SETIDX R2 R16 R17
0x000C0725, // 00D0 ADD R3 R3 K37
0x00241325, // 00D1 ADD R9 R9 K37
0x000C0726, // 00D0 ADD R3 R3 K38
0x00241326, // 00D1 ADD R9 R9 K38
0x7001FFB7, // 00D2 JMP #008B
0x6024000C, // 00D3 GETGBL R9 G12
0xB82A3800, // 00D4 GETNGBL R10 K28
0x8C281536, // 00D5 GETMET R10 R10 K54
0xB82A3A00, // 00D4 GETNGBL R10 K29
0x8C281537, // 00D5 GETMET R10 R10 K55
0x7C280200, // 00D6 CALL R10 1
0x7C240200, // 00D7 CALL R9 1
0x58280006, // 00D8 LDCONST R10 K6
0x04241204, // 00D9 SUB R9 R9 R4
0x142C1409, // 00DA LT R11 R10 R9
0x782E0011, // 00DB JMPF R11 #00EE
0x8C2C1110, // 00DC GETMET R11 R8 K16
0x8C2C1107, // 00DC GETMET R11 R8 K7
0x5C341400, // 00DD MOVE R13 R10
0x7C2C0400, // 00DE CALL R11 2
0x4C300000, // 00DF LDNIL R12
@ -502,19 +506,19 @@ be_local_closure(class_Matter_Autoconf_autoconf_device_map, /* name */
0x7C2C0200, // 00E4 CALL R11 1
0x60300013, // 00E5 GETGBL R12 G19
0x7C300000, // 00E6 CALL R12 0
0x98322337, // 00E7 SETIDX R12 K17 K55
0x00341525, // 00E8 ADD R13 R10 K37
0x98326E0D, // 00E9 SETIDX R12 K55 R13
0x98322538, // 00E7 SETIDX R12 K18 K56
0x00341526, // 00E8 ADD R13 R10 K38
0x9832700D, // 00E9 SETIDX R12 K56 R13
0x9808160C, // 00EA SETIDX R2 R11 R12
0x000C0725, // 00EB ADD R3 R3 K37
0x00281525, // 00EC ADD R10 R10 K37
0x000C0726, // 00EB ADD R3 R3 K38
0x00281526, // 00EC ADD R10 R10 K38
0x7001FFEB, // 00ED JMP #00DA
0x8C2C0338, // 00EE GETMET R11 R1 K56
0xB8363800, // 00EF GETNGBL R13 K28
0x8C341B39, // 00F0 GETMET R13 R13 K57
0x8C2C0339, // 00EE GETMET R11 R1 K57
0xB8363A00, // 00EF GETNGBL R13 K29
0x8C341B3A, // 00F0 GETMET R13 R13 K58
0x7C340200, // 00F1 CALL R13 1
0x7C2C0400, // 00F2 CALL R11 2
0x8C30013A, // 00F3 GETMET R12 R0 K58
0x8C30013B, // 00F3 GETMET R12 R0 K59
0x5C381600, // 00F4 MOVE R14 R11
0x7C300400, // 00F5 CALL R12 2
0x60340010, // 00F6 GETGBL R13 G16
@ -527,9 +531,9 @@ be_local_closure(class_Matter_Autoconf_autoconf_device_map, /* name */
0x5C400600, // 00FD MOVE R16 R3
0x7C3C0200, // 00FE CALL R15 1
0x98081E0E, // 00FF SETIDX R2 R15 R14
0x000C0725, // 0100 ADD R3 R3 K37
0x000C0726, // 0100 ADD R3 R3 K38
0x7001FFF7, // 0101 JMP #00FA
0x5834001B, // 0102 LDCONST R13 K27
0x5834001C, // 0102 LDCONST R13 K28
0xAC340200, // 0103 CATCH R13 1 0
0xB0080000, // 0104 RAISE 2 R0 R0
0x80040400, // 0105 RET 1 R2
@ -582,7 +586,7 @@ be_local_closure(class_Matter_Autoconf_autoconf_sensors_list, /* name */
&be_const_str_solidified,
( &(const binstruction[121]) { /* code */
0x88080100, // 0000 GETMBR R2 R0 K0
0x8808053B, // 0001 GETMBR R2 R2 K59
0x8808053C, // 0001 GETMBR R2 R2 K60
0x600C0012, // 0002 GETGBL R3 G18
0x7C0C0000, // 0003 CALL R3 0
0x60100010, // 0004 GETGBL R4 G16
@ -599,19 +603,19 @@ be_local_closure(class_Matter_Autoconf_autoconf_sensors_list, /* name */
0x60240013, // 000F GETGBL R9 G19
0x7C1C0400, // 0010 CALL R7 2
0x781E000A, // 0011 JMPF R7 #001D
0x8C1C0D2C, // 0012 GETMET R7 R6 K44
0x5824003C, // 0013 LDCONST R9 K60
0x8C1C0D2D, // 0012 GETMET R7 R6 K45
0x5824003D, // 0013 LDCONST R9 K61
0x7C1C0400, // 0014 CALL R7 2
0x781E0006, // 0015 JMPF R7 #001D
0x001C0B3D, // 0016 ADD R7 R5 K61
0x001C0B3E, // 0016 ADD R7 R5 K62
0x8C200703, // 0017 GETMET R8 R3 K3
0x60280013, // 0018 GETGBL R10 G19
0x7C280000, // 0019 CALL R10 0
0x982A233E, // 001A SETIDX R10 K17 K62
0x982A7E07, // 001B SETIDX R10 K63 R7
0x982A253F, // 001A SETIDX R10 K18 K63
0x982A8007, // 001B SETIDX R10 K64 R7
0x7C200400, // 001C CALL R8 2
0x7001FFEB, // 001D JMP #000A
0x5810001B, // 001E LDCONST R4 K27
0x5810001C, // 001E LDCONST R4 K28
0xAC100200, // 001F CATCH R4 1 0
0xB0080000, // 0020 RAISE 2 R0 R0
0x60100010, // 0021 GETGBL R4 G16
@ -628,19 +632,19 @@ be_local_closure(class_Matter_Autoconf_autoconf_sensors_list, /* name */
0x60240013, // 002C GETGBL R9 G19
0x7C1C0400, // 002D CALL R7 2
0x781E000A, // 002E JMPF R7 #003A
0x8C1C0D2C, // 002F GETMET R7 R6 K44
0x58240040, // 0030 LDCONST R9 K64
0x8C1C0D2D, // 002F GETMET R7 R6 K45
0x58240041, // 0030 LDCONST R9 K65
0x7C1C0400, // 0031 CALL R7 2
0x781E0006, // 0032 JMPF R7 #003A
0x001C0B41, // 0033 ADD R7 R5 K65
0x001C0B42, // 0033 ADD R7 R5 K66
0x8C200703, // 0034 GETMET R8 R3 K3
0x60280013, // 0035 GETGBL R10 G19
0x7C280000, // 0036 CALL R10 0
0x982A2342, // 0037 SETIDX R10 K17 K66
0x982A7E07, // 0038 SETIDX R10 K63 R7
0x982A2543, // 0037 SETIDX R10 K18 K67
0x982A8007, // 0038 SETIDX R10 K64 R7
0x7C200400, // 0039 CALL R8 2
0x7001FFEB, // 003A JMP #0027
0x5810001B, // 003B LDCONST R4 K27
0x5810001C, // 003B LDCONST R4 K28
0xAC100200, // 003C CATCH R4 1 0
0xB0080000, // 003D RAISE 2 R0 R0
0x60100010, // 003E GETGBL R4 G16
@ -657,19 +661,19 @@ be_local_closure(class_Matter_Autoconf_autoconf_sensors_list, /* name */
0x60240013, // 0049 GETGBL R9 G19
0x7C1C0400, // 004A CALL R7 2
0x781E000A, // 004B JMPF R7 #0057
0x8C1C0D2C, // 004C GETMET R7 R6 K44
0x58240043, // 004D LDCONST R9 K67
0x8C1C0D2D, // 004C GETMET R7 R6 K45
0x58240044, // 004D LDCONST R9 K68
0x7C1C0400, // 004E CALL R7 2
0x781E0006, // 004F JMPF R7 #0057
0x001C0B44, // 0050 ADD R7 R5 K68
0x001C0B45, // 0050 ADD R7 R5 K69
0x8C200703, // 0051 GETMET R8 R3 K3
0x60280013, // 0052 GETGBL R10 G19
0x7C280000, // 0053 CALL R10 0
0x982A2345, // 0054 SETIDX R10 K17 K69
0x982A7E07, // 0055 SETIDX R10 K63 R7
0x982A2546, // 0054 SETIDX R10 K18 K70
0x982A8007, // 0055 SETIDX R10 K64 R7
0x7C200400, // 0056 CALL R8 2
0x7001FFEB, // 0057 JMP #0044
0x5810001B, // 0058 LDCONST R4 K27
0x5810001C, // 0058 LDCONST R4 K28
0xAC100200, // 0059 CATCH R4 1 0
0xB0080000, // 005A RAISE 2 R0 R0
0x60100010, // 005B GETGBL R4 G16
@ -686,19 +690,19 @@ be_local_closure(class_Matter_Autoconf_autoconf_sensors_list, /* name */
0x60240013, // 0066 GETGBL R9 G19
0x7C1C0400, // 0067 CALL R7 2
0x781E000A, // 0068 JMPF R7 #0074
0x8C1C0D2C, // 0069 GETMET R7 R6 K44
0x58240046, // 006A LDCONST R9 K70
0x8C1C0D2D, // 0069 GETMET R7 R6 K45
0x58240047, // 006A LDCONST R9 K71
0x7C1C0400, // 006B CALL R7 2
0x781E0006, // 006C JMPF R7 #0074
0x001C0B47, // 006D ADD R7 R5 K71
0x001C0B48, // 006D ADD R7 R5 K72
0x8C200703, // 006E GETMET R8 R3 K3
0x60280013, // 006F GETGBL R10 G19
0x7C280000, // 0070 CALL R10 0
0x982A2348, // 0071 SETIDX R10 K17 K72
0x982A7E07, // 0072 SETIDX R10 K63 R7
0x982A2549, // 0071 SETIDX R10 K18 K73
0x982A8007, // 0072 SETIDX R10 K64 R7
0x7C200400, // 0073 CALL R8 2
0x7001FFEB, // 0074 JMP #0061
0x5810001B, // 0075 LDCONST R4 K27
0x5810001C, // 0075 LDCONST R4 K28
0xAC100200, // 0076 CATCH R4 1 0
0xB0080000, // 0077 RAISE 2 R0 R0
0x80040600, // 0078 RET 1 R3

View File

@ -3,8 +3,8 @@
* Generated code, don't edit *
\********************************************************************/
#include "be_constobj.h"
// compact class 'Matter_Commissioning' ktab size: 132, total: 272 (saved 1120 bytes)
static const bvalue be_ktab_class_Matter_Commissioning[132] = {
// compact class 'Matter_Commissioning' ktab size: 127, total: 259 (saved 1056 bytes)
static const bvalue be_ktab_class_Matter_Commissioning[127] = {
/* K0 */ be_nested_str_weak(device),
/* K1 */ be_nested_str_weak(sessions),
/* K2 */ be_nested_str_weak(active_fabrics),
@ -128,15 +128,10 @@ static const bvalue be_ktab_class_Matter_Commissioning[132] = {
/* K120 */ be_nested_str_weak(_CM1),
/* K121 */ be_nested_str_weak(MTR_X3A_X20starting_X20mDNS_X20on_X20_X25s_X20_X27_X25s_X27_X20ptr_X20to_X20_X60_X25s_X2Elocal_X60),
/* K122 */ be_nested_str_weak(millis),
/* K123 */ be_nested_str_weak(mdns_announce_PASE),
/* K124 */ be_nested_str_weak(add_rule),
/* K125 */ be_nested_str_weak(Wifi_X23Connected),
/* K126 */ be_nested_str_weak(Eth_X23Connected),
/* K127 */ be_nested_str_weak(_mdns_announce_hostname),
/* K128 */ be_nested_str_weak(matter_mdns_host),
/* K129 */ be_nested_str_weak(get_fabric),
/* K130 */ be_nested_str_weak(get_admin_vendor_name),
/* K131 */ be_nested_str_weak(MTR_X3A_X20_X2D_X2D_X2D_X20Commissioning_X20complete_X20for_X20Fabric_X20_X27_X25s_X27_X20_X28Vendor_X20_X25s_X29_X20_X2D_X2D_X2D),
/* K123 */ be_nested_str_weak(when_network_up),
/* K124 */ be_nested_str_weak(get_fabric),
/* K125 */ be_nested_str_weak(get_admin_vendor_name),
/* K126 */ be_nested_str_weak(MTR_X3A_X20_X2D_X2D_X2D_X20Commissioning_X20complete_X20for_X20Fabric_X20_X27_X25s_X27_X20_X28Vendor_X20_X25s_X29_X20_X2D_X2D_X2D),
};
@ -1551,15 +1546,15 @@ be_local_closure(class_Matter_Commissioning_mdns_announce_PASE, /* name */
********************************************************************/
be_local_closure(class_Matter_Commissioning_start_basic_commissioning, /* name */
be_nested_proto(
13, /* nstack */
11, /* nstack */
8, /* argc */
10, /* varg */
0, /* has upvals */
NULL, /* no upvals */
1, /* has sup protos */
( &(const struct bproto*[ 2]) {
( &(const struct bproto*[ 1]) {
be_nested_proto(
4, /* nstack */
2, /* nstack */
0, /* argc */
0, /* varg */
1, /* has upvals */
@ -1569,55 +1564,16 @@ be_local_closure(class_Matter_Commissioning_start_basic_commissioning, /* name
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 4]) { /* constants */
( &(const bvalue[ 1]) { /* constants */
/* K0 */ be_nested_str_weak(mdns_announce_PASE),
/* K1 */ be_nested_str_weak(tasmota),
/* K2 */ be_nested_str_weak(remove_rule),
/* K3 */ be_nested_str_weak(Wifi_X23Connected),
}),
be_str_weak(_anonymous_),
&be_const_str_solidified,
( &(const binstruction[ 9]) { /* code */
( &(const binstruction[ 4]) { /* code */
0x68000000, // 0000 GETUPV R0 U0
0x8C000100, // 0001 GETMET R0 R0 K0
0x7C000200, // 0002 CALL R0 1
0xB8020200, // 0003 GETNGBL R0 K1
0x8C000102, // 0004 GETMET R0 R0 K2
0x58080003, // 0005 LDCONST R2 K3
0x580C0000, // 0006 LDCONST R3 K0
0x7C000600, // 0007 CALL R0 3
0x80000000, // 0008 RET 0
})
),
be_nested_proto(
4, /* nstack */
0, /* argc */
0, /* varg */
1, /* has upvals */
( &(const bupvaldesc[ 1]) { /* upvals */
be_local_const_upval(1, 0),
}),
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 4]) { /* constants */
/* K0 */ be_nested_str_weak(mdns_announce_PASE),
/* K1 */ be_nested_str_weak(tasmota),
/* K2 */ be_nested_str_weak(remove_rule),
/* K3 */ be_nested_str_weak(Eth_X23Connected),
}),
be_str_weak(_anonymous_),
&be_const_str_solidified,
( &(const binstruction[ 9]) { /* code */
0x68000000, // 0000 GETUPV R0 U0
0x8C000100, // 0001 GETMET R0 R0 K0
0x7C000200, // 0002 CALL R0 1
0xB8020200, // 0003 GETNGBL R0 K1
0x8C000102, // 0004 GETMET R0 R0 K2
0x58080003, // 0005 LDCONST R2 K3
0x580C0000, // 0006 LDCONST R3 K0
0x7C000600, // 0007 CALL R0 3
0x80000000, // 0008 RET 0
0x80000000, // 0003 RET 0
})
),
}),
@ -1625,7 +1581,7 @@ be_local_closure(class_Matter_Commissioning_start_basic_commissioning, /* name
&be_ktab_class_Matter_Commissioning, /* shared constants */
be_str_weak(start_basic_commissioning),
&be_const_str_solidified,
( &(const binstruction[40]) { /* code */
( &(const binstruction[19]) { /* code */
0xB8221000, // 0000 GETNGBL R8 K8
0x8C20117A, // 0001 GETMET R8 R8 K122
0x7C200200, // 0002 CALL R8 1
@ -1640,32 +1596,11 @@ be_local_closure(class_Matter_Commissioning_start_basic_commissioning, /* name
0x90022406, // 000B SETMBR R0 K18 R6
0x90022607, // 000C SETMBR R0 K19 R7
0xB8221000, // 000D GETNGBL R8 K8
0x8C201131, // 000E GETMET R8 R8 K49
0x7C200200, // 000F CALL R8 1
0x9420113E, // 0010 GETIDX R8 R8 K62
0x74220004, // 0011 JMPT R8 #0017
0xB8221000, // 0012 GETNGBL R8 K8
0x8C20112C, // 0013 GETMET R8 R8 K44
0x7C200200, // 0014 CALL R8 1
0x9420113E, // 0015 GETIDX R8 R8 K62
0x78220002, // 0016 JMPF R8 #001A
0x8C20017B, // 0017 GETMET R8 R0 K123
0x7C200200, // 0018 CALL R8 1
0x7002000B, // 0019 JMP #0026
0xB8221000, // 001A GETNGBL R8 K8
0x8C20117C, // 001B GETMET R8 R8 K124
0x5828007D, // 001C LDCONST R10 K125
0x842C0000, // 001D CLOSURE R11 P0
0x5830007B, // 001E LDCONST R12 K123
0x7C200800, // 001F CALL R8 4
0xB8221000, // 0020 GETNGBL R8 K8
0x8C20117C, // 0021 GETMET R8 R8 K124
0x5828007E, // 0022 LDCONST R10 K126
0x842C0001, // 0023 CLOSURE R11 P1
0x5830007B, // 0024 LDCONST R12 K123
0x7C200800, // 0025 CALL R8 4
0xA0000000, // 0026 CLOSE R0
0x80000000, // 0027 RET 0
0x8C20117B, // 000E GETMET R8 R8 K123
0x84280000, // 000F CLOSURE R10 P0
0x7C200400, // 0010 CALL R8 2
0xA0000000, // 0011 CLOSE R0
0x80000000, // 0012 RET 0
})
)
);
@ -1677,15 +1612,15 @@ be_local_closure(class_Matter_Commissioning_start_basic_commissioning, /* name
********************************************************************/
be_local_closure(class_Matter_Commissioning_start_mdns_announce_hostnames, /* name */
be_nested_proto(
6, /* nstack */
4, /* nstack */
1, /* argc */
10, /* varg */
0, /* has upvals */
NULL, /* no upvals */
1, /* has sup protos */
( &(const struct bproto*[ 2]) {
( &(const struct bproto*[ 1]) {
be_nested_proto(
4, /* nstack */
3, /* nstack */
0, /* argc */
0, /* varg */
1, /* has upvals */
@ -1696,58 +1631,34 @@ be_local_closure(class_Matter_Commissioning_start_mdns_announce_hostnames, /*
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 5]) { /* constants */
/* K0 */ be_nested_str_weak(_mdns_announce_hostname),
/* K1 */ be_nested_str_weak(tasmota),
/* K2 */ be_nested_str_weak(remove_rule),
/* K3 */ be_nested_str_weak(Wifi_X23Connected),
/* K4 */ be_nested_str_weak(matter_mdns_host),
/* K0 */ be_nested_str_weak(tasmota),
/* K1 */ be_nested_str_weak(wifi),
/* K2 */ be_nested_str_weak(up),
/* K3 */ be_nested_str_weak(_mdns_announce_hostname),
/* K4 */ be_nested_str_weak(eth),
}),
be_str_weak(_anonymous_),
&be_const_str_solidified,
( &(const binstruction[10]) { /* code */
0x68000000, // 0000 GETUPV R0 U0
0x8C000100, // 0001 GETMET R0 R0 K0
0x50080000, // 0002 LDBOOL R2 0 0
( &(const binstruction[19]) { /* code */
0xB8020000, // 0000 GETNGBL R0 K0
0x8C000101, // 0001 GETMET R0 R0 K1
0x58080002, // 0002 LDCONST R2 K2
0x7C000400, // 0003 CALL R0 2
0xB8020200, // 0004 GETNGBL R0 K1
0x8C000102, // 0005 GETMET R0 R0 K2
0x58080003, // 0006 LDCONST R2 K3
0x580C0004, // 0007 LDCONST R3 K4
0x7C000600, // 0008 CALL R0 3
0x80000000, // 0009 RET 0
})
),
be_nested_proto(
4, /* nstack */
0, /* argc */
0, /* varg */
1, /* has upvals */
( &(const bupvaldesc[ 1]) { /* upvals */
be_local_const_upval(1, 0),
}),
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 5]) { /* constants */
/* K0 */ be_nested_str_weak(_mdns_announce_hostname),
/* K1 */ be_nested_str_weak(tasmota),
/* K2 */ be_nested_str_weak(remove_rule),
/* K3 */ be_nested_str_weak(Eth_X23Connected),
/* K4 */ be_nested_str_weak(matter_mdns_host),
}),
be_str_weak(_anonymous_),
&be_const_str_solidified,
( &(const binstruction[10]) { /* code */
0x68000000, // 0000 GETUPV R0 U0
0x8C000100, // 0001 GETMET R0 R0 K0
0x50080200, // 0002 LDBOOL R2 1 0
0x7C000400, // 0003 CALL R0 2
0xB8020200, // 0004 GETNGBL R0 K1
0x8C000102, // 0005 GETMET R0 R0 K2
0x58080003, // 0006 LDCONST R2 K3
0x580C0004, // 0007 LDCONST R3 K4
0x7C000600, // 0008 CALL R0 3
0x80000000, // 0009 RET 0
0x78020003, // 0004 JMPF R0 #0009
0x68000000, // 0005 GETUPV R0 U0
0x8C000103, // 0006 GETMET R0 R0 K3
0x50080000, // 0007 LDBOOL R2 0 0
0x7C000400, // 0008 CALL R0 2
0xB8020000, // 0009 GETNGBL R0 K0
0x8C000104, // 000A GETMET R0 R0 K4
0x58080002, // 000B LDCONST R2 K2
0x7C000400, // 000C CALL R0 2
0x78020003, // 000D JMPF R0 #0012
0x68000000, // 000E GETUPV R0 U0
0x8C000103, // 000F GETMET R0 R0 K3
0x50080200, // 0010 LDBOOL R2 1 0
0x7C000400, // 0011 CALL R0 2
0x80000000, // 0012 RET 0
})
),
}),
@ -1755,39 +1666,13 @@ be_local_closure(class_Matter_Commissioning_start_mdns_announce_hostnames, /*
&be_ktab_class_Matter_Commissioning, /* shared constants */
be_str_weak(start_mdns_announce_hostnames),
&be_const_str_solidified,
( &(const binstruction[32]) { /* code */
( &(const binstruction[ 6]) { /* code */
0xB8061000, // 0000 GETNGBL R1 K8
0x8C040331, // 0001 GETMET R1 R1 K49
0x7C040200, // 0002 CALL R1 1
0x9404033E, // 0003 GETIDX R1 R1 K62
0x78060003, // 0004 JMPF R1 #0009
0x8C04017F, // 0005 GETMET R1 R0 K127
0x500C0000, // 0006 LDBOOL R3 0 0
0x7C040400, // 0007 CALL R1 2
0x70020005, // 0008 JMP #000F
0xB8061000, // 0009 GETNGBL R1 K8
0x8C04037C, // 000A GETMET R1 R1 K124
0x580C007D, // 000B LDCONST R3 K125
0x84100000, // 000C CLOSURE R4 P0
0x58140080, // 000D LDCONST R5 K128
0x7C040800, // 000E CALL R1 4
0xB8061000, // 000F GETNGBL R1 K8
0x8C04032C, // 0010 GETMET R1 R1 K44
0x7C040200, // 0011 CALL R1 1
0x9404033E, // 0012 GETIDX R1 R1 K62
0x78060003, // 0013 JMPF R1 #0018
0x8C04017F, // 0014 GETMET R1 R0 K127
0x500C0200, // 0015 LDBOOL R3 1 0
0x7C040400, // 0016 CALL R1 2
0x70020005, // 0017 JMP #001E
0xB8061000, // 0018 GETNGBL R1 K8
0x8C04037C, // 0019 GETMET R1 R1 K124
0x580C007E, // 001A LDCONST R3 K126
0x84100001, // 001B CLOSURE R4 P1
0x58140080, // 001C LDCONST R5 K128
0x7C040800, // 001D CALL R1 4
0xA0000000, // 001E CLOSE R0
0x80000000, // 001F RET 0
0x8C04037B, // 0001 GETMET R1 R1 K123
0x840C0000, // 0002 CLOSURE R3 P0
0x7C040400, // 0003 CALL R1 2
0xA0000000, // 0004 CLOSE R0
0x80000000, // 0005 RET 0
})
)
);
@ -1872,7 +1757,7 @@ be_local_closure(class_Matter_Commissioning_start_commissioning_complete, /* n
be_str_weak(start_commissioning_complete),
&be_const_str_solidified,
( &(const binstruction[23]) { /* code */
0x8C080381, // 0000 GETMET R2 R1 K129
0x8C08037C, // 0000 GETMET R2 R1 K124
0x7C080200, // 0001 CALL R2 1
0x8C0C0504, // 0002 GETMET R3 R2 K4
0x7C0C0200, // 0003 CALL R3 1
@ -1882,11 +1767,11 @@ be_local_closure(class_Matter_Commissioning_start_commissioning_complete, /* n
0x7C0C0200, // 0007 CALL R3 1
0x8C0C073B, // 0008 GETMET R3 R3 K59
0x7C0C0200, // 0009 CALL R3 1
0x8C100582, // 000A GETMET R4 R2 K130
0x8C10057D, // 000A GETMET R4 R2 K125
0x7C100200, // 000B CALL R4 1
0xB8164A00, // 000C GETNGBL R5 K37
0x60180018, // 000D GETGBL R6 G24
0x581C0083, // 000E LDCONST R7 K131
0x581C007E, // 000E LDCONST R7 K126
0x5C200600, // 000F MOVE R8 R3
0x5C240800, // 0010 MOVE R9 R4
0x7C180600, // 0011 CALL R6 3

View File

@ -0,0 +1,897 @@
/*
be_httpserver_lib.c - HTTP server support for Berry using ESP-IDF HTTP server
Copyright (C) 2025 Jonathan E. Peace
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_BERRY_HTTPSERVER
#include <stddef.h> // For NULL, size_t
#include <stdbool.h> // For bool, true, false
#include <string.h> // For string functions
#include <stdlib.h> // For malloc/free
// ESP-IDF includes
#define LOG_LOCAL_LEVEL ESP_LOG_INFO
#include "esp_log.h"
#include "esp_http_server.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
// Berry includes
#include "be_mapping.h"
#include "be_exec.h"
#include "be_vm.h"
#include "be_gc.h"
// External function declarations
httpd_handle_t be_httpserver_get_handle(void);
void be_httpserver_set_disconnect_handler(httpd_close_func_t handler);
bool httpserver_has_queue(void);
// Message types for queue
typedef enum {
HTTP_MSG_WEBSOCKET = 1,
HTTP_MSG_FILE = 2,
HTTP_MSG_WEB = 3
} http_msg_type_t;
// Message structure for queue
typedef struct {
http_msg_type_t type;
int client_id;
void *data;
size_t data_len;
void *user_data;
bvalue func; // Berry function value for web handlers
httpd_req_t *req; // HTTP request handle for async processing
} http_queue_msg_t;
// Forward declarations for internal functions
void be_httpserver_process_websocket_msg(bvm *vm, int client_id, const char *data, size_t len);
bool httpserver_queue_message(http_msg_type_t type, int client_id, const void *data, size_t data_len, void *user_data);
bool httpserver_queue_web_request(int handler_id, httpd_req_t *req, bvalue func);
// Logger tag
static const char *TAG = "HTTPSERVER";
// Global queue for handling messages in the main task context
static QueueHandle_t http_msg_queue = NULL;
static SemaphoreHandle_t http_queue_mutex = NULL;
static bool http_queue_initialized = false;
// Maximum number of HTTP handlers
#define HTTP_HANDLER_MAX 5
// Handler storage
typedef struct {
bool active; // Whether this handler is in use
bvm *vm; // Berry VM instance
bvalue func; // Berry function to call for requests
} http_handler_t;
static http_handler_t http_handlers[HTTP_HANDLER_MAX];
// Maximum concurrent HTTP server connections
#define HTTPD_MAX_CONNECTIONS 8
// Handle to HTTP server
static httpd_handle_t http_server = NULL;
// Disconnect handler for WebSocket connections
static httpd_close_func_t http_server_disconn_handler = NULL;
// Current HTTP request being processed (for Berry access)
static httpd_req_t *current_request = NULL;
// Connection tracking
static struct {
int count;
SemaphoreHandle_t mutex;
} connection_tracking = {0, NULL};
// Connection cleanup function
// CONTEXT: ESP-IDF HTTP Server Task
// Called automatically by ESP-IDF when a client disconnects
static void http_connection_cleanup(void *arg) {
if (xSemaphoreTake(connection_tracking.mutex, pdMS_TO_TICKS(100)) == pdTRUE) {
connection_tracking.count--;
xSemaphoreGive(connection_tracking.mutex);
// Call WebSocket disconnect handler if registered
if (http_server_disconn_handler) {
// arg is the socket file descriptor in this context
http_server_disconn_handler(NULL, (int)(intptr_t)arg);
}
}
}
// WebSocket message processing function
// CONTEXT: Main Tasmota Task (Berry VM Context)
// This function runs in the main task when processing queued WebSocket messages
void be_httpserver_process_websocket_msg(bvm *vm, int client_id, const char *data, size_t data_len) {
// Log message details safely (handling NULL data for connect events)
if (data) {
ESP_LOGD(TAG, "Processing WebSocket message in main task context: client=%d, data='%s', len=%d",
client_id, data, (int)data_len);
} else {
ESP_LOGD(TAG, "Processing WebSocket event in main task context: client=%d", client_id);
}
// Forward to the WebSocket handler in be_wsserver_lib.c
be_wsserver_handle_message(vm, client_id, data, data_len);
}
// File request processing function
static void be_httpserver_process_file_request(bvm *vm, void *user_data) {
ESP_LOGI(TAG, "Processing file request (placeholder)");
// Placeholder for file handling - to be extended as needed
}
// Initialize the message queue
static bool init_http_queue() {
if (!http_queue_initialized) {
http_msg_queue = xQueueCreate(10, sizeof(http_queue_msg_t));
http_queue_mutex = xSemaphoreCreateMutex();
if (http_msg_queue != NULL && http_queue_mutex != NULL) {
http_queue_initialized = true;
ESP_LOGI(TAG, "HTTP queue initialized");
return true;
} else {
ESP_LOGE(TAG, "Failed to create HTTP queue");
return false;
}
}
return true;
}
// Queue a message for processing in the main task
// CONTEXT: Any Task (typically ESP-IDF HTTP Server Task)
// This function is called to queue messages for processing in the main task
// TRANSITION: Current Task → Main Tasmota Task
bool httpserver_queue_message(http_msg_type_t type, int client_id, const void *data, size_t data_len, void *user_data) {
if (!http_queue_initialized) {
ESP_LOGE(TAG, "Queue not initialized");
return false;
}
if (!data && data_len > 0) {
ESP_LOGE(TAG, "Invalid data pointer with non-zero length");
return false;
}
// Take mutex to protect queue
if (xSemaphoreTake(http_queue_mutex, pdMS_TO_TICKS(100)) != pdTRUE) {
ESP_LOGE(TAG, "Failed to take mutex");
return false;
}
// Create a message to queue
http_queue_msg_t msg = {0};;
msg.type = type;
msg.client_id = client_id;
msg.user_data = user_data;
// Special case for HTTP_MSG_WEB is handled by httpserver_queue_web_request
if (type == HTTP_MSG_WEB) {
ESP_LOGE(TAG, "HTTP_MSG_WEB must use httpserver_queue_web_request");
xSemaphoreGive(http_queue_mutex);
return false;
}
// For other message types, copy the data if needed
if (data_len > 0) {
char *data_copy = malloc(data_len + 1);
if (!data_copy) {
ESP_LOGE(TAG, "Failed to allocate memory for data copy");
xSemaphoreGive(http_queue_mutex);
return false;
}
memcpy(data_copy, data, data_len);
data_copy[data_len] = '\0'; // Ensure null termination
msg.data = data_copy;
msg.data_len = data_len;
}
// Queue the message
if (xQueueSend(http_msg_queue, &msg, 0) != pdTRUE) {
// Queue is full, free the data if we allocated it
if (msg.data) {
free(msg.data);
}
ESP_LOGE(TAG, "Failed to queue message - queue is full");
xSemaphoreGive(http_queue_mutex);
return false;
}
// Message successfully queued
ESP_LOGD(TAG, "Message queued successfully (type %d, client %d)", type, client_id);
ESP_LOGD(TAG, "DIAGNOSTIC: Queue has %d messages waiting", uxQueueMessagesWaiting(http_msg_queue));
if (msg.data) {
ESP_LOGD(TAG, "QUEUE ITEM: type=%d, client=%d, data_len=%d, data_ptr=%p, user_data=%p",
msg.type, msg.client_id, (int)msg.data_len, msg.data, msg.user_data);
ESP_LOGD(TAG, "QUEUE DATA: '%s'", msg.data);
}
xSemaphoreGive(http_queue_mutex);
return true;
}
// Specialized function for queuing HTTP web requests with a Berry function
bool httpserver_queue_web_request(int handler_id, httpd_req_t *req, bvalue func) {
if (!http_queue_initialized) {
ESP_LOGE(TAG, "Queue not initialized");
return false;
}
if (!req) {
ESP_LOGE(TAG, "NULL request for web request");
return false;
}
// Create a copy of the request that we can process asynchronously
httpd_req_t *req_copy = NULL;
esp_err_t err = httpd_req_async_handler_begin(req, &req_copy);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Failed to create async request: %d", err);
return false;
}
// Take mutex to protect queue
if (xSemaphoreTake(http_queue_mutex, pdMS_TO_TICKS(100)) != pdTRUE) {
ESP_LOGE(TAG, "Failed to take mutex");
// Release the request copy since we won't be using it
httpd_req_async_handler_complete(req_copy);
return false;
}
// Create a message to queue
http_queue_msg_t msg = {0};
msg.type = HTTP_MSG_WEB;
msg.client_id = handler_id;
msg.user_data = NULL;
msg.func = func; // Store the function reference
msg.req = req_copy; // Store the COPY of the request handle
// Queue the message
if (xQueueSend(http_msg_queue, &msg, 0) != pdTRUE) {
// Queue is full
ESP_LOGE(TAG, "Failed to queue web request - queue is full");
// Release the request copy since we won't be using it
httpd_req_async_handler_complete(req_copy);
xSemaphoreGive(http_queue_mutex);
return false;
}
// Message successfully queued
ESP_LOGD(TAG, "HTTP request queued successfully (type %d, handler %d)", msg.type, msg.client_id);
ESP_LOGD(TAG, "DIAGNOSTIC: Queue has %d messages waiting", uxQueueMessagesWaiting(http_msg_queue));
ESP_LOGD(TAG, "QUEUE ITEM: type=%d, client=%d, data_len=%d, data_ptr=%p, user_data=%p, req=%p",
msg.type, msg.client_id, (int)msg.data_len, msg.data, msg.user_data, msg.req);
xSemaphoreGive(http_queue_mutex);
return true;
}
// ------------------------------------------------------------------------
// Web request processing function
// CONTEXT: Main Tasmota Task (Berry VM Context)
// This function processes queued web requests in the main task context
// ------------------------------------------------------------------------
void be_httpserver_process_web_request(bvm *vm, http_queue_msg_t *msg) {
ESP_LOGD(TAG, "Processing web request: msg=%p", msg);
if (!msg) {
ESP_LOGE(TAG, "Web request has NULL message handle");
return;
}
ESP_LOGD(TAG, "Request details: req=%p, client_id=%d", msg->req, msg->client_id);
if (!msg->req) {
ESP_LOGE(TAG, "Web request has NULL request handle");
return;
}
// Get handler ID (passed in client_id field)
int handler_id = msg->client_id;
if (handler_id < 0 || handler_id >= HTTP_HANDLER_MAX || !http_handlers[handler_id].active) {
ESP_LOGE(TAG, "Invalid handler ID from queue: %d", handler_id);
httpd_resp_set_status(msg->req, "500 Internal Server Error");
httpd_resp_sendstr(msg->req, "Invalid handler ID");
httpd_req_async_handler_complete(msg->req);
return;
}
ESP_LOGI(TAG, "Processing web request for URI: %s with handler %d", msg->req->uri, handler_id);
// Get the Berry VM and handler function
bvm *handler_vm = http_handlers[handler_id].vm;
if (handler_vm == NULL) {
ESP_LOGE(TAG, "Berry VM is NULL for handler %d", handler_id);
httpd_resp_set_status(msg->req, "500 Internal Server Error");
httpd_resp_sendstr(msg->req, "VM error");
httpd_req_async_handler_complete(msg->req);
return;
}
ESP_LOGI(TAG, "STACK: Before pushing function, stack top = %d", be_top(handler_vm));
// Push the function stored in the message
be_pushnil(handler_vm);
bvalue *top = be_indexof(handler_vm, -1);
*top = msg->func;
current_request = msg->req;
// Push URI as argument
be_pushstring(handler_vm, current_request->uri);
// Check if this is a POST request and handle POST data
int arg_count = 1; // Start with 1 for the URI
if (current_request->method == HTTP_POST) {
ESP_LOGI(TAG, "Processing POST request data");
// Get content length
int content_len = current_request->content_len;
ESP_LOGI(TAG, "POST content length: %d", content_len);
if (content_len > 0) {
// Allocate buffer for POST data
char *post_data = malloc(content_len + 1);
if (post_data) {
// Read POST data
int received = httpd_req_recv(current_request, post_data, content_len);
if (received > 0) {
// Null-terminate the data
post_data[received] = '\0';
ESP_LOGI(TAG, "Received POST data: %s", post_data);
// Push POST data as second argument
be_pushstring(handler_vm, post_data);
arg_count = 2; // Now we have 2 arguments
} else {
ESP_LOGW(TAG, "Failed to read POST data, received: %d", received);
// Push nil as second argument
be_pushnil(handler_vm);
arg_count = 2;
}
free(post_data);
} else {
ESP_LOGE(TAG, "Failed to allocate memory for POST data");
// Push nil as second argument
be_pushnil(handler_vm);
arg_count = 2;
}
} else {
// No content, push empty string as second argument
be_pushstring(handler_vm, "");
arg_count = 2;
}
}
// Call the Berry function
int result = be_pcall(handler_vm, arg_count);
// Log stack state after call
ESP_LOGI(TAG, "STACK: After be_pcall, stack top = %d, result = %d", be_top(handler_vm), result);
// Check for errors
if (result != 0) {
const char *err_msg = be_tostring(handler_vm, -1);
ESP_LOGE(TAG, "Berry handler error: %s", err_msg);
// Send error response
httpd_resp_set_status(msg->req, "500 Internal Server Error");
httpd_resp_sendstr(msg->req, (char*)err_msg);
be_error_pop_all(handler_vm); // Clear entire stack on error
} else {
// Get return value
const char *response = be_tostring(handler_vm, -1);
ESP_LOGI(TAG, "Request processed. Response: %s", response ? response : "(null)");
// Send success response if httpserver.send() wasn't used
if (response != NULL) {
httpd_resp_set_type(msg->req, "text/html");
httpd_resp_sendstr(msg->req, response);
}
// Pop the argument (which has been replaced by the return value)
be_pop(handler_vm, 1);
}
// Clear current_request AFTER all processing is done
current_request = NULL;
// Complete the async request - ALWAYS call this to release the request
httpd_req_async_handler_complete(msg->req);
// Pop the function if we didn't encounter an error
if (result == 0) {
// Pop the function
be_pop(handler_vm, 1); // Pop the function reference
} else {
ESP_LOGE(TAG, "Function parsing error: %d", result);
}
// Log final stack state
ESP_LOGI(TAG, "STACK: Final state, stack top = %d", be_top(handler_vm));
}
// ------------------------------------------------------------------------
// Berry mapped C function to process queued messages
// CONTEXT: Main Tasmota Task (Berry VM Context)
// This function is registered to fast_loop() by the Berry app and is called
// periodically to process queued HTTP/WebSocket messages from the ESP-IDF HTTP server
// ------------------------------------------------------------------------
static int w_httpserver_process_queue(bvm *vm) {
if (!http_msg_queue) {
be_pushnil(vm);
be_return(vm);
}
// Count of messages processed in this call
int processed = 0;
// Process up to 5 messages in a single call to avoid blocking
for (int i = 0; i < 5; i++) {
// Take mutex before accessing queue
if (xSemaphoreTake(http_queue_mutex, 0) != pdTRUE) {
ESP_LOGW(TAG, "Failed to take mutex, will retry");
break;
}
// Process one message from the queue
http_queue_msg_t msg;
if (xQueueReceive(http_msg_queue, &msg, 0) == pdTRUE) {
// Release mutex while processing message
xSemaphoreGive(http_queue_mutex);
// Count this message
processed++;
// Diagnostic logging for queue state
ESP_LOGD(TAG, "QUEUE ITEM: type=%d, client=%d, data_len=%d, data_ptr=%p, user_data=%p, req=%p",
msg.type, msg.client_id, msg.data_len, msg.data, msg.user_data, msg.req);
// Process message based on type
switch (msg.type) {
case HTTP_MSG_WEBSOCKET:
if (msg.data) {
ESP_LOGD(TAG, "QUEUE DATA: '%.*s'", msg.data_len, (char*)msg.data);
} else {
ESP_LOGD(TAG, "QUEUE DATA: '' (connect/disconnect event)");
}
be_httpserver_process_websocket_msg(vm, msg.client_id, msg.data, msg.data_len);
// Free the data buffer we allocated
if (msg.data) {
free(msg.data);
}
break;
case HTTP_MSG_FILE:
ESP_LOGI(TAG, "Processing file request");
be_httpserver_process_file_request(vm, msg.user_data);
// user_data is not allocated by us, so don't free it
break;
case HTTP_MSG_WEB:
ESP_LOGD(TAG, "Processing web request from queue");
if (msg.req == NULL) {
ESP_LOGE(TAG, "CRITICAL ERROR: HTTP request pointer is NULL, skipping processing");
break;
}
be_httpserver_process_web_request(vm, &msg);
break;
default:
ESP_LOGW(TAG, "Unknown message type: %d", msg.type);
// Free data if it was allocated
if (msg.data) {
free(msg.data);
}
// If it's a request that wasn't processed, complete it
if (msg.req) {
httpd_req_async_handler_complete(msg.req);
}
break;
}
} else {
// No messages in queue
xSemaphoreGive(http_queue_mutex);
break;
}
}
// Return the number of messages processed
be_pushint(vm, processed);
be_return(vm);
}
// ------------------------------------------------------------------------
// HTTP Handler implementation
// ------------------------------------------------------------------------
// Forward declaration for handler implementation
static esp_err_t berry_http_handler_impl(httpd_req_t *req, int handler_id);
// Macro to create handler functions for each supported endpoint
#define HTTP_HANDLER_FUNC(n) \
static esp_err_t berry_http_handler_##n(httpd_req_t *req) { \
return berry_http_handler_impl(req, n); \
}
// Generate handler functions
HTTP_HANDLER_FUNC(0)
HTTP_HANDLER_FUNC(1)
HTTP_HANDLER_FUNC(2)
HTTP_HANDLER_FUNC(3)
HTTP_HANDLER_FUNC(4)
// Array of handler function pointers
typedef esp_err_t (*http_handler_func_t)(httpd_req_t *req);
static const http_handler_func_t berry_handlers[HTTP_HANDLER_MAX] = {
berry_http_handler_0,
berry_http_handler_1,
berry_http_handler_2,
berry_http_handler_3,
berry_http_handler_4
};
// Implementation of HTTP handler dispatched by each numbered handler
static esp_err_t berry_http_handler_impl(httpd_req_t *req, int handler_id) {
if (handler_id < 0 || handler_id >= HTTP_HANDLER_MAX || !http_handlers[handler_id].active) {
ESP_LOGE(TAG, "Invalid or inactive handler ID: %d", handler_id);
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Invalid handler");
httpd_req_async_handler_complete(req);
return ESP_FAIL;
}
// Store current request for access in Berry functions
current_request = req;
// Get the Berry VM and handler function
bvm *vm = http_handlers[handler_id].vm;
if (vm == NULL) {
ESP_LOGE(TAG, "Berry VM is NULL for handler %d", handler_id);
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "VM error");
current_request = NULL;
httpd_req_async_handler_complete(req);
return ESP_FAIL;
}
// Log initial stack state
ESP_LOGI(TAG, "HANDLER: Initial stack top = %d", be_top(vm));
// Queue message for processing in main task if available
if (httpserver_has_queue()) {
ESP_LOGI(TAG, "Queueing request for %s", req->uri);
// Queue the request with the stored function value
if (!httpserver_queue_web_request(handler_id, req, http_handlers[handler_id].func)) {
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to queue message");
current_request = NULL;
httpd_req_async_handler_complete(req);
return ESP_FAIL;
}
// Note: We don't send a response here - that will be done asynchronously
current_request = NULL;
// Log final stack state
ESP_LOGI(TAG, "HANDLER: Final stack top = %d", be_top(vm));
return ESP_OK;
}
// If no queue, we'll process directly with caution
ESP_LOGW(TAG, "Processing request directly - this may be unsafe!");
// Start the async handler
httpd_req_t *async_req = NULL;
esp_err_t ret = httpd_req_async_handler_begin(req, &async_req);
if (ret != ESP_OK || async_req == NULL) {
ESP_LOGE(TAG, "Failed to start async handler");
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to start async handler");
current_request = NULL;
httpd_req_async_handler_complete(req);
return ESP_FAIL;
}
// Get the initial stack size
int top = be_top(vm);
// Push the handler function directly onto the stack (copy from stored value)
be_pushnil(vm); // Push a temporary placeholder
bvalue *top_ptr = be_indexof(vm, -1);
*top_ptr = http_handlers[handler_id].func; // Replace placeholder with stored function
// Push the URI string (argument) onto the stack
be_pushstring(vm, req->uri);
// Call the handler function with the URI as single argument
if (be_pcall(vm, 1) != 0) {
const char *err_msg = be_tostring(vm, -1);
ESP_LOGE(TAG, "Berry error: %s", err_msg ? err_msg : "unknown error");
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Handler call failed");
be_error_pop_all(vm); // Special case - clears entire stack on error
current_request = NULL;
httpd_req_async_handler_complete(req);
return ESP_FAIL;
}
// Get the response string
const char *response = be_tostring(vm, -1);
if (response == NULL) {
ESP_LOGE(TAG, "Handler returned nil response");
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Handler returned nil response");
be_error_pop_all(vm); // Special case - clears entire stack on error
current_request = NULL;
httpd_req_async_handler_complete(req);
return ESP_FAIL;
}
// Send the response
httpd_resp_set_type(req, "text/html");
httpd_resp_sendstr(req, response);
// Clean up
be_pop(vm, 1); // Pop return value
be_pop(vm, 1); // Pop function
current_request = NULL;
// Complete the async handler
httpd_req_async_handler_complete(async_req);
return ESP_OK;
}
// ------------------------------------------------------------------------
// Berry API Implementation
// ------------------------------------------------------------------------
// Start the HTTP server
static int w_httpserver_start(bvm *vm) {
int top = be_top(vm);
if (http_server != NULL) {
be_pushbool(vm, true); // Server already running
be_return (vm);
}
// Initialize connection tracking
connection_tracking.mutex = xSemaphoreCreateMutex();
if (!connection_tracking.mutex) {
ESP_LOGE(TAG, "Failed to create connection tracking mutex");
be_pushbool(vm, false);
be_return (vm);
}
// Configure the server
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
config.stack_size = 8192;
config.max_uri_handlers = HTTP_HANDLER_MAX;
config.max_open_sockets = HTTPD_MAX_CONNECTIONS;
config.lru_purge_enable = true; // Enable LRU purging of connections
config.uri_match_fn = httpd_uri_match_wildcard; // Enable wildcard URI matching
// Handle port parameter if provided
if (top > 0 && be_isint(vm, 1)) {
config.server_port = be_toint(vm, 1);
}
ESP_LOGI(TAG, "Starting HTTP server on port %d", config.server_port);
esp_err_t ret = httpd_start(&http_server, &config);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to start HTTP server: %d", ret);
vSemaphoreDelete(connection_tracking.mutex);
be_pushbool(vm, false);
be_return (vm);
}
ESP_LOGI(TAG, "HTTP server started successfully");
// Initialize the queue for thread-safe message passing
init_http_queue();
be_pushbool(vm, true);
be_return (vm);
}
// Register a URI handler
static int w_httpserver_on(bvm *vm) {
int top = be_top(vm);
httpd_method_t http_method = HTTP_GET; // Default method
if (top < 2 || http_server == NULL) {
be_raise(vm, "value_error", top < 2 ? "Missing arguments" : "Server not started");
be_return(vm);
}
if (!be_isstring(vm, 1) || !be_isfunction(vm, 2)) {
be_raise(vm, "type_error", "String and function required");
be_return(vm);
}
// Check for optional method argument
if (top >= 3) {
if (!be_isstring(vm, 3)) {
be_raise(vm, "type_error", "Method must be a string");
be_return(vm);
}
const char *method_str = be_tostring(vm, 3);
if (strcasecmp(method_str, "POST") == 0) {
http_method = HTTP_POST;
} else if (strcasecmp(method_str, "GET") != 0) {
be_raise(vm, "value_error", "Method must be 'GET' or 'POST'");
be_return(vm);
}
}
const char *uri = be_tostring(vm, 1);
ESP_LOGI(TAG, "Registering handler for URI: %s, Method: %s", uri,
http_method == HTTP_GET ? "GET" : "POST");
// Find a free handler slot
int slot = -1;
for (int i = 0; i < HTTP_HANDLER_MAX; i++) {
if (!http_handlers[i].active) {
slot = i;
break;
}
}
if (slot < 0) {
be_raise(vm, "runtime_error", "No more handler slots available");
be_return(vm);
}
// Store handler info
http_handlers[slot].vm = vm;
http_handlers[slot].active = true;
// Store the function reference
be_pushvalue(vm, 2);
bvalue *v = be_indexof(vm, -1);
http_handlers[slot].func = *v;
be_pop(vm, 1);
// Register the handler with ESP-IDF HTTP server
httpd_uri_t http_uri = {
.uri = uri,
.method = http_method,
.handler = berry_handlers[slot],
.user_ctx = NULL
};
esp_err_t ret = httpd_register_uri_handler(http_server, &http_uri);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to register URI handler: %d", ret);
http_handlers[slot].active = false;
be_pushbool(vm, false);
be_return (vm);
}
// Return the handler slot
be_pushint(vm, slot);
be_return (vm);
}
// Stop the HTTP server
static int w_httpserver_stop(bvm *vm) {
if (http_server == NULL) {
be_pushbool(vm, false); // Server not running
be_return (vm);
}
// Clean up handler registrations
for (int i = 0; i < HTTP_HANDLER_MAX; i++) {
if (http_handlers[i].active) {
http_handlers[i].active = false;
// Potentially unregister URI handlers here if needed
}
}
// Stop the server
esp_err_t ret = httpd_stop(http_server);
http_server = NULL;
// Clean up connection tracking
if (connection_tracking.mutex) {
vSemaphoreDelete(connection_tracking.mutex);
connection_tracking.mutex = NULL;
}
be_pushbool(vm, ret == ESP_OK);
be_return (vm);
}
// Simple wrapper around httpd_resp_sendstr
static int w_httpserver_send(bvm *vm) {
int argc = be_top(vm);
if (argc >= 1 && be_isstring(vm, 1)) {
const char* content = be_tostring(vm, 1);
// Get the current request from the async message
httpd_req_t* req = current_request;
if (!req) {
be_raisef(vm, "request_error", "No active request");
// Note: Don't call httpd_req_async_handler_complete here as there's no valid request
return 0;
}
// Send the response
esp_err_t ret = httpd_resp_sendstr(req, content);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to send response: %d", ret);
// Don't complete the handler here - let the main handler do it
be_pushbool(vm, false);
be_return (vm);
}
be_pushbool(vm, true);
be_return (vm);
}
be_return_nil(vm);
}
// Set WebSocket disconnect handler
void be_httpserver_set_disconnect_handler(httpd_close_func_t handler) {
http_server_disconn_handler = handler;
}
// Get HTTP server handle
httpd_handle_t be_httpserver_get_handle(void) {
return http_server;
}
// Function to check if message queue is available (referenced by wsserver)
bool httpserver_has_queue() {
return http_queue_initialized;
}
/* @const_object_info_begin
module httpserver (scope: global, strings: weak) {
start, func(w_httpserver_start)
on, func(w_httpserver_on)
send, func(w_httpserver_send)
stop, func(w_httpserver_stop)
process_queue, func(w_httpserver_process_queue)
}
@const_object_info_end */
#include "be_fixed_httpserver.h"
#endif // USE_BERRY_HTTPSERVER

View File

@ -315,11 +315,11 @@ char* be_fgets(void *hfile, void *buffer, int size)
uint8_t * buf = (uint8_t*) buffer;
if (hfile != nullptr && buffer != nullptr && size > 0) {
File * f_ptr = (File*) hfile;
int ret = f_ptr->readBytesUntil('\n', buf, size - 2);
// Serial.printf("be_fgets ret=%d\n", ret);
int ret = f_ptr->readBytesUntil('\n', buf, size - 1);
// Serial.printf("be_fgets size=%d ret=%d\n", size, ret);
if (ret >= 0) {
buf[ret] = 0; // add string terminator
if (ret > 0 && ret < size - 2) {
if (ret < size - 1) {
buf[ret] = '\n';
buf[ret+1] = 0;
}

View File

@ -90,6 +90,7 @@ class be_class_tasmota (scope: global, name: Tasmota) {
_crons, var // list of active crons
_ccmd, var // list of active Tasmota commands implemented in Berry
_drivers, var // list of active drivers
_wnu, var // list of closures to call when network is connected
wire1, var // Tasmota I2C Wire1
wire2, var // Tasmota I2C Wire2
cmd_res, var // store the command result, nil if disables, true if capture enabled, contains return value
@ -106,7 +107,7 @@ class be_class_tasmota (scope: global, name: Tasmota) {
init, closure(class_Tasmota_init_closure)
get_free_heap, func(l_getFreeHeap)
arch, func(l_arch)
arch, static_func(l_arch)
publish, func(be_mqtt_publish)
publish_result, func(l_publish_result)
publish_rule, func(l_publish_rule)
@ -183,6 +184,8 @@ class be_class_tasmota (scope: global, name: Tasmota) {
exec_cmd, closure(class_Tasmota_exec_cmd_closure)
gc, closure(class_Tasmota_gc_closure)
event, closure(class_Tasmota_event_closure)
when_network_up, closure(class_Tasmota_when_network_up_closure)
run_network_up, closure(class_Tasmota_run_network_up_closure)
add_driver, closure(class_Tasmota_add_driver_closure)
remove_driver, closure(class_Tasmota_remove_driver_closure)
load, closure(class_Tasmota_load_closure)

View File

@ -6,8 +6,6 @@
*******************************************************************/
#include "be_constobj.h"
#ifdef USE_WEBCLIENT
extern int wc_tcp_init(bvm *vm);
extern int wc_tcp_deinit(bvm *vm);
@ -44,5 +42,3 @@ class be_class_tcpclient (scope: global, name: tcpclient) {
readbytes, func(wc_tcp_readbytes)
}
@const_object_info_end */
#endif // USE_WEBCLIENT

View File

@ -5,8 +5,6 @@
*******************************************************************/
#include "be_constobj.h"
#ifdef USE_WEBCLIENT
extern int wc_tcpasync_init(bvm *vm);
extern int wc_tcpasync_deinit(bvm *vm);
@ -42,5 +40,3 @@ class be_class_tcpclientasync (scope: global, name: tcpclientasync) {
readbytes, func(wc_tcpasync_readbytes)
}
@const_object_info_end */
#endif // USE_WEBCLIENT

View File

@ -7,8 +7,6 @@
#include "be_constobj.h"
#include "be_mapping.h"
#ifdef USE_WEBCLIENT
extern int be_udp_read(struct bvm *vm);
extern void *be_udp_init_ntv(void);
@ -53,5 +51,3 @@ class be_class_udp (scope: global, name: udp) {
close, ctype_func(be_udp_stop_ntv)
}
@const_object_info_end */
#endif // USE_WEBCLIENT

View File

@ -6,8 +6,6 @@
*******************************************************************/
#include "be_constobj.h"
#ifdef USE_WEBCLIENT
extern int wc_init(bvm *vm);
extern int wc_deinit(bvm *vm);
extern int wc_urlencode(bvm *vm);
@ -72,5 +70,3 @@ class be_class_webclient (scope: global, name: webclient) {
get_bytes, func(wc_getbytes)
}
@const_object_info_end */
#endif // USE_WEBCLIENT

View File

@ -0,0 +1,400 @@
/*
be_webfiles_lib.c - Static file server for Berry using ESP-IDF HTTP server
Copyright (C) 2025 Jonathan E. Peace
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_BERRY_WEBFILES
#ifndef LOG_LOCAL_LEVEL
#define LOG_LOCAL_LEVEL ESP_LOG_INFO
#endif
#include "be_constobj.h"
#include "be_mapping.h"
// ESP-IDF includes
#include "esp_log.h"
#include "esp_http_server.h"
#include "esp_vfs.h"
// External Berry/Tasmota includes
extern httpd_handle_t be_httpserver_get_handle(void);
extern bool httpserver_queue_message(int type, int client_id,
const char* data, size_t len, void* user_data);
// Tag for logging
static const char *TAG = "WEBFILES";
// Default base path for files
static char base_path[64] = "/files";
// URI prefix for the file server
static char uri_prefix[32] = "/";
// Maximum file path length
#define FILE_PATH_MAX 128
// Scratch buffer size for file transfer
#define SCRATCH_BUFSIZE 4096 // 4KB scratch buffer for chunks
// Static buffer for file sending - fixed allocation
static char scratch_buffer[SCRATCH_BUFSIZE];
// MIME Type Mapping
static const struct {
const char *extension;
const char *mimetype;
} mime_types[] = {
{".html", "text/html"},
{".htm", "text/html"},
{".js", "application/javascript"},
{".mjs", "application/javascript"}, // ES modules
{".css", "text/css"},
{".png", "image/png"},
{".jpg", "image/jpeg"},
{".jpeg", "image/jpeg"},
{".gif", "image/gif"},
{".ico", "image/x-icon"},
{".svg", "image/svg+xml"},
{".json", "application/json"},
{".txt", "text/plain"},
{".md", "text/markdown"},
{".wasm", "application/wasm"}, // WebAssembly
{".map", "application/json"}, // Source maps
{".woff", "font/woff"},
{".woff2", "font/woff2"},
{".ttf", "font/ttf"},
{".otf", "font/otf"},
{".bin", "application/octet-stream"},
{NULL, NULL}
};
// Get MIME type based on file extension
static const char* get_mime_type(const char *path) {
const char *ext = strrchr(path, '.');
if (!ext) return "text/plain";
for (int i = 0; mime_types[i].extension; i++) {
if (strcasecmp(mime_types[i].extension, ext) == 0) {
return mime_types[i].mimetype;
}
}
return "text/plain";
}
// Build full path including base path
static const char* get_full_path(char *dest, const char *uri, size_t destsize) {
size_t base_len = strlen(base_path);
size_t prefix_len = strlen(uri_prefix);
size_t uri_len = strlen(uri);
// Handle query parameters and fragments in URI
const char *query = strchr(uri, '?');
if (query) {
uri_len = query - uri;
}
const char *fragment = strchr(uri, '#');
if (fragment && (!query || fragment < query)) {
uri_len = fragment - uri;
}
// Skip the URI prefix to get the relative path
const char *relative_path = uri;
if (prefix_len > 1 && strncmp(uri, uri_prefix, prefix_len) == 0) {
relative_path = uri + prefix_len - 1; // -1 because we want to keep the leading slash
uri_len -= (prefix_len - 1);
}
// Check if path will fit in destination buffer
if (base_len + uri_len + 1 > destsize) {
ESP_LOGE(TAG, "Path too long");
return NULL;
}
// Construct full path
strcpy(dest, base_path);
if (base_len > 0 && base_path[base_len-1] == '/' && relative_path[0] == '/') {
// Avoid double slash
strlcpy(dest + base_len, relative_path + 1, uri_len);
} else {
strlcpy(dest + base_len, relative_path, uri_len + 1);
}
return dest;
}
// Set content type based on file extension
static void set_content_type_from_file(httpd_req_t *req, const char *filepath) {
const char* mime_type = get_mime_type(filepath);
httpd_resp_set_type(req, mime_type);
// Set Cache-Control header for static assets
// Don't cache HTML, but cache other static assets
if (strstr(mime_type, "text/html") == NULL) {
// Cache for 1 hour (3600 seconds)
httpd_resp_set_hdr(req, "Cache-Control", "max-age=3600");
} else {
// Don't cache HTML content
httpd_resp_set_hdr(req, "Cache-Control", "no-cache");
}
// Add CORS headers for development convenience
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
}
//checks if a .html, .css, or .js file exists with a .br suffix and serve that Brotli-compressed version instead
static esp_err_t webfiles_handler(httpd_req_t *req) {
char filepath[FILE_PATH_MAX];
char compressed_filepath[FILE_PATH_MAX];
FILE *file = NULL;
struct stat file_stat;
bool use_compression = false;
const char* compression_type = NULL; // Only Gzip for now
// Process any URL query parameters if needed
char *query = strchr(req->uri, '?');
if (query) {
ESP_LOGI(TAG, "Request has query params: %s", query);
*query = '\0'; // Temporarily terminate URI at the query string for path resolution
}
// Get the full file path from the URI
if (get_full_path(filepath, req->uri, sizeof(filepath)) == NULL) {
ESP_LOGE(TAG, "Failed to get file path for URI: %s", req->uri);
httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "File not found");
return ESP_FAIL;
}
// Restore query string if we modified it
if (query) *query = '?';
ESP_LOGI(TAG, "Requested file: %s", filepath);
// Check if file is .html, .css, .js, or .svg and if a compressed version exists
const char *ext = strrchr(filepath, '.');
if (ext && (strcasecmp(ext, ".html") == 0 || strcasecmp(ext, ".css") == 0 ||
strcasecmp(ext, ".js") == 0 || strcasecmp(ext, ".svg") == 0)) {
// Check what compression formats the client supports
char accept_encoding[64] = {0};
if (httpd_req_get_hdr_value_str(req, "Accept-Encoding", accept_encoding, sizeof(accept_encoding)) == ESP_OK) {
ESP_LOGI(TAG, "Client supports compression: %s", accept_encoding);
if (!use_compression && strstr(accept_encoding, "gzip") != NULL) {
// Construct Gzip filepath
snprintf(compressed_filepath, sizeof(compressed_filepath), "%s.gz", filepath);
if (stat(compressed_filepath, &file_stat) == 0 && S_ISREG(file_stat.st_mode)) {
use_compression = true;
compression_type = "gzip";
strcpy(filepath, compressed_filepath); // Use the .gz file
ESP_LOGI(TAG, "Found Gzip version: %s", filepath);
}
}
}
}
// Check if file exists
if (stat(filepath, &file_stat) != 0) {
ESP_LOGE(TAG, "File does not exist: %s", filepath);
httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "File not found");
return ESP_FAIL;
}
// Check if it's a regular file
if (!S_ISREG(file_stat.st_mode)) {
ESP_LOGE(TAG, "Not a regular file: %s", filepath);
httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "Not a file");
return ESP_FAIL;
}
// Open the file for reading
file = fopen(filepath, "r");
if (!file) {
ESP_LOGE(TAG, "Failed to open file: %s", filepath);
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to open file");
return ESP_FAIL;
}
// Set content type based on file extension (use original path for MIME type if compressed)
char original_filepath[FILE_PATH_MAX];
if (use_compression) {
// Strip compression extension for MIME type detection
strcpy(original_filepath, filepath);
char* dot_pos = strrchr(original_filepath, '.');
if (dot_pos) {
*dot_pos = '\0'; // Remove compression extension
}
set_content_type_from_file(req, original_filepath);
} else {
set_content_type_from_file(req, filepath);
}
// Set compression headers if applicable
if (use_compression) {
httpd_resp_set_hdr(req, "Content-Encoding", compression_type);
httpd_resp_set_hdr(req, "Vary", "Accept-Encoding");
}
// Send file in chunks for efficiency
size_t chunk_size;
size_t total_sent = 0;
while ((chunk_size = fread(scratch_buffer, 1, SCRATCH_BUFSIZE, file)) > 0) {
if (httpd_resp_send_chunk(req, scratch_buffer, chunk_size) != ESP_OK) {
ESP_LOGE(TAG, "File send failed");
fclose(file);
httpd_resp_send_chunk(req, NULL, 0);
return ESP_FAIL;
}
total_sent += chunk_size;
}
// Close file
fclose(file);
// Finish the HTTP response
httpd_resp_send_chunk(req, NULL, 0);
ESP_LOGI(TAG, "File sent successfully (%d bytes, %s)", (int)total_sent, use_compression ? compression_type : "uncompressed");
return ESP_OK;
}
/****************************************************************
* Berry Interface Functions
****************************************************************/
// webfiles.serve(base_path, uri_prefix) -> bool
// Serve files from base_path at uri_prefix
static int w_webfiles_serve(bvm *vm) {
int initial_top = be_top(vm);
if (be_top(vm) >= 2 && be_isstring(vm, 1) && be_isstring(vm, 2)) {
const char* path = be_tostring(vm, 1);
const char* prefix = be_tostring(vm, 2);
ESP_LOGI(TAG, "Setting up file server with base path: %s, uri prefix: %s", path, prefix);
struct stat st;
if (stat(path, &st) != 0 || !S_ISDIR(st.st_mode)) {
ESP_LOGE(TAG, "Input path is not a valid directory: %s", path);
be_pushbool(vm, false);
// Clean up stack before returning
while (be_top(vm) > initial_top) {
be_pop(vm, 1);
}
be_return (vm); // Return directly
}
httpd_handle_t server = be_httpserver_get_handle();
if (!server) {
ESP_LOGE(TAG, "HTTP server not running");
be_pushbool(vm, false);
while (be_top(vm) > initial_top) {
be_pop(vm, 1);
}
be_return (vm);
}
strlcpy(base_path, path, sizeof(base_path));
strlcpy(uri_prefix, prefix, sizeof(uri_prefix));
// Use a static buffer for the URI pattern
static char registered_uri_pattern[64]; // ADD static keyword
// Ensure it's null-terminated even if snprintf truncates
registered_uri_pattern[sizeof(registered_uri_pattern) - 1] = '\0';
snprintf(registered_uri_pattern, sizeof(registered_uri_pattern), "%s*", prefix);
ESP_LOGI(TAG, "Registering URI handler with pattern: %s", registered_uri_pattern);
httpd_uri_t uri_handler = {
// Point to the static buffer
.uri = registered_uri_pattern, // Use the static buffer
.method = HTTP_GET,
.handler = webfiles_handler,
.is_websocket = false,
.user_ctx = NULL
};
esp_err_t ret = httpd_register_uri_handler(server, &uri_handler);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to register URI handler: %d", ret);
be_pushbool(vm, false);
be_pop(vm, be_top(vm) - initial_top);
be_return (vm);
}
be_pushbool(vm, true);
be_pop(vm, be_top(vm) - initial_top);
be_return (vm);
}
be_pushbool(vm, false);
be_pop(vm, be_top(vm) - initial_top);
be_return (vm);
}
// webfiles.serve_file(file_path, uri) -> bool
// Serve a specific file at a specific URI
static int w_webfiles_serve_file(bvm *vm) {
int initial_top = be_top(vm);
if (be_top(vm) >= 2 && be_isstring(vm, 1) && be_isstring(vm, 2)) {
const char* file_path = be_tostring(vm, 1);
const char* uri = be_tostring(vm, 2);
// Check if file exists
struct stat file_stat;
if (stat(file_path, &file_stat) == -1) {
ESP_LOGE(TAG, "File not found: %s", file_path);
be_pushbool(vm, false);
be_pop(vm, be_top(vm) - initial_top);
be_return (vm);
}
// TODO: Implement custom handler for specific files
// This would require keeping track of file mappings
ESP_LOGW(TAG, "serve_file not yet implemented");
be_pushbool(vm, false);
be_pop(vm, be_top(vm) - initial_top);
be_return (vm);
}
be_pushbool(vm, false);
be_pop(vm, be_top(vm) - initial_top);
be_return (vm);
}
// Module definition
/* @const_object_info_begin
module webfiles (scope: global, strings: weak) {
serve, func(w_webfiles_serve)
serve_file, func(w_webfiles_serve_file)
// MIME type constants
MIME_HTML, str("text/html")
MIME_JS, str("application/javascript")
MIME_CSS, str("text/css")
MIME_JSON, str("application/json")
MIME_TEXT, str("text/plain")
MIME_BINARY, str("application/octet-stream")
}
@const_object_info_end */
#include "be_fixed_webfiles.h"
#endif // USE_BERRY_WEBFILES

File diff suppressed because it is too large Load Diff

View File

@ -158,18 +158,6 @@ class Leds : Leds_ntv
def get_gamma()
return self.gamma
end
# def rotate_left(rot, first, last)
# self.call_native(20, rot, first, last)
# end
# def rotate_right(rot, first, last)
# self.call_native(21, rot, first, last)
# end
# def shift_left(rot, first, last)
# self.call_native(22, rot, first, last)
# end
# def shift_right(rot, first, last)
# self.call_native(22, rot, first, last)
# end
# apply gamma and bri
def to_gamma(rgb, bri)
@ -252,217 +240,6 @@ class Leds : Leds_ntv
end
def create_matrix(w, h, offset)
offset = int(offset)
w = int(w)
h = int(h)
if offset == nil offset = 0 end
if w * h + offset > self.leds || h < 0 || w < 0 || offset < 0
raise "value_error", "out of range"
end
# inner class
class Leds_matrix
var strip
var offset
var h, w
var alternate # are rows in alternate mode (even/odd are reversed)
var pix_buffer
var pix_size
def init(strip, w, h, offset)
self.strip = strip
self.offset = offset
self.h = h
self.w = w
self.alternate = false
self.pix_buffer = self.strip.pixels_buffer()
self.pix_size = self.strip.pixel_size()
end
def clear()
self.clear_to(0x000000)
self.show()
end
def begin()
# do nothing, already being handled by physical strip
end
def show(force)
# don't trigger on segment, you will need to trigger on full strip instead
if bool(force) || (self.offset == 0 && self.w * self.h == self.strip.leds)
self.strip.show()
self.pix_buffer = self.strip.pixels_buffer(self.pix_buffer) # update buffer after show()
end
end
def can_show()
return self.strip.can_show()
end
def is_dirty() ## DEPRECATED
return self.strip.is_dirty()
end
def dirty() ## DEPRECATED
self.strip.dirty()
end
def pixels_buffer()
return self.strip.pixels_buffer()
end
def pixel_size()
return self.pix_size
end
def pixel_count()
return self.w * self.h
end
def pixel_offset()
return self.offset
end
def clear_to(col, bri)
if (bri == nil) bri = self.strip.bri end
self.strip.call_native(9, self.strip.to_gamma(col, bri), self.offset, self.w * self.h)
end
def set_pixel_color(idx, col, bri)
if (bri == nil) bri = self.strip.bri end
self.strip.set_pixel_color(idx + self.offset, col, bri)
end
def get_pixel_color(idx)
return self.strip.get_pixel_color(idx + self.offseta)
end
# setbytes(row, bytes)
# sets the raw bytes for `row`, copying at most 3 or 4 x col bytes
def set_bytes(row, buf, offset, len)
var h_bytes = self.h * self.pix_size
if (len > h_bytes) len = h_bytes end
var offset_in_matrix = (self.offset + row) * h_bytes
self.pix_buffer.setbytes(offset_in_matrix, buf, offset, len)
end
# Leds_matrix specific
def set_alternate(alt)
self.alternate = alt
end
def get_alternate()
return self.alternate
end
def set_matrix_pixel_color(x, y, col, bri)
if (bri == nil) bri = self.strip.bri end
if self.alternate && (y & 0x1)
# reversed line
self.strip.set_pixel_color(x * self.w + self.h - y - 1 + self.offset, col, bri)
else
self.strip.set_pixel_color(x * self.w + y + self.offset, col, bri)
end
end
def scroll(direction, outshift, inshift) # 0 - up, 1 - left, 2 - down, 3 - right ; outshift mandatory, inshift optional
var buf = self.pix_buffer
var h = self.h
var sz = self.w * 3 # row size in bytes
var pos
if direction%2 == 0 #up/down
if direction == 0 #up
outshift.setbytes(0,(buf[0..sz-1]).reverse(0,nil,3))
var line = 0
while line < (h-1)
pos = 0
var offset_dst = line * sz
var offset_src = ((line+2) * sz) - 3
while pos < sz
var dst = pos + offset_dst
var src = offset_src - pos
buf[dst] = buf[src]
buf[dst+1] = buf[src+1]
buf[dst+2] = buf[src+2]
pos += 3
end
line += 1
end
var lastline = inshift ? inshift : outshift
if h%2 == 1
lastline.reverse(0,nil,3)
end
buf.setbytes((h-1) * sz, lastline)
else # down
outshift.setbytes(0,(buf[size(buf)-sz..]).reverse(0,nil,3))
var line = h - 1
while line > 0
buf.setbytes(line * sz,(buf[(line-1) * sz..line * sz-1]).reverse(0,nil,3))
line -= 1
end
var lastline = inshift ? inshift : outshift
if h%2 == 1
lastline.reverse(0,nil,3)
end
buf.setbytes(0, lastline)
end
else # left/right
var line = 0
var step = 3
if direction == 3 # right
step *= -1
end
while line < h
pos = line * sz
if step > 0
var line_end = pos + sz - step
outshift[(line * 3)] = buf[pos]
outshift[(line * 3) + 1] = buf[pos+1]
outshift[(line * 3) + 2] = buf[pos+2]
while pos < line_end
buf[pos] = buf[pos+3]
buf[pos+1] = buf[pos+4]
buf[pos+2] = buf[pos+5]
pos += step
end
if inshift == nil
buf[line_end] = outshift[(line * 3)]
buf[line_end+1] = outshift[(line * 3) + 1]
buf[line_end+2] = outshift[(line * 3) + 2]
else
buf[line_end] = inshift[(line * 3)]
buf[line_end+1] = inshift[(line * 3) + 1]
buf[line_end+2] = inshift[(line * 3) + 2]
end
else
var line_end = pos
pos = pos + sz + step
outshift[(line * 3)] = buf[pos]
outshift[(line * 3) + 1] = buf[pos+1]
outshift[(line * 3) + 2] = buf[pos+2]
while pos > line_end
buf[pos] = buf[pos-3]
buf[pos+1] = buf[pos-2]
buf[pos+2] = buf[pos-1]
pos += step
end
if inshift == nil
buf[line_end] = outshift[(line * 3)]
buf[line_end+1] = outshift[(line * 3) + 1]
buf[line_end+2] = outshift[(line * 3) + 2]
else
buf[line_end] = inshift[(line * 3)]
buf[line_end+1] = inshift[(line * 3) + 1]
buf[line_end+2] = inshift[(line * 3) + 2]
end
end
step *= -1
line += 1
end
end
end
end
return Leds_matrix(self, w, h, offset)
end
static def matrix(w, h, gpio, rmt)
var strip = Leds(w * h, gpio, rmt)
var matrix = strip.create_matrix(w, h, 0)
return matrix
end
end
@ -483,26 +260,3 @@ end
anim()
-#
#-
var s = Leds(25, gpio.pin(gpio.WS2812, 1)).create_matrix(5, 5)
s.set_alternate(true)
s.clear_to(0x400000)
s.show()
x = 0
y = 0
def anim()
s.clear_to(0x400000)
s.set_matrix_pixel_color(x, y, 0x004000)
s.show()
y = (y + 1) % 5
if y == 0
x = (x + 1) % 5
end
tasmota.set_timer(200, anim)
end
anim()
-#

View File

@ -8,29 +8,34 @@ tapp_module.init = def (m)
class Tapp
# we make sure the instance is registered as a driver to receive the "autoexec" event
def init()
tasmota.add_driver(self)
end
def autoexec()
# Takes a list of files, and run any tapp file's autoexec.be
static def autoexec_dir(dir_name)
import path
import string
var dir = path.listdir("/")
for d: dir
if string.find(d, ".tapp") > 0
tasmota.log(format("TAP: Loaded Tasmota App '%s'", d), 2)
tasmota.load(d + "#autoexec.be")
for d: path.listdir(dir_name)
if string.endswith(d, ".tapp")
log(f"TAP: Loaded Tasmota App '{dir_name}{d}'", 2)
tasmota.load(dir_name + d + "#autoexec.be")
end
end
end
# react to the "autoexec" event that is triggered at first tick when Berry starts
# Note: this is alled before the file "/autoexec.be" is loaded
#
# We run all `*.tapp` that are located in "/.extensions/" and in "/" in this order
def autoexec()
self.autoexec_dir("/.extensions/")
self.autoexec_dir("/")
end
end
return Tapp() # return an instance of this class
end
# aa = autoconf_module.init(autoconf_module)
# import webserver
# webserver.on('/ac2', / -> aa.page_autoconf_mgr(), webserver.HTTP_GET)
return tapp_module

View File

@ -13,6 +13,7 @@ class Tasmota
var _crons
var _ccmd
var _drivers
var _wnu # when_connected: list of closures to call when network is connected, or nil
var wire1
var wire2
var cmd_res # store the command result, nil if disables, true if capture enabled, contains return value
@ -723,9 +724,45 @@ class Tasmota
end
end
# add a closure to the list to be called when network is connected
# or call immediately if network is already up
def when_network_up(cl)
self.check_not_method(cl)
var is_connected = tasmota.wifi()['up'] || tasmota.eth()['up']
if is_connected
cl() # call closure
else
if (self._wnu == nil)
self._wnu = [ cl ] # create list
else
self._wnu.push(cl) # append to list
end
end
end
# run all pending closures when network is up
def run_network_up()
if (self._wnu == nil) return end
var is_connected = tasmota.wifi()['up'] || tasmota.eth()['up']
if is_connected
# run all closures in a safe loop
while (size(self._wnu) > 0)
var cl = self._wnu[0]
self._wnu.remove(0) # failsafe, remove first to avoid an infinite loop if call fails
try
cl()
except .. as e,m
print(format("BRY: Exception> run_network_up '%s' - %s", e, m))
end
end
self._wnu = nil # all done, clear list
end
end
def event(event_type, cmd, idx, payload, raw)
import introspect
if event_type=='every_50ms'
if (self._wnu) self.run_network_up() end # capture when network becomes connected
self.run_timers()
end #- first run deferred events -#

View File

@ -238,7 +238,10 @@ class webserver_async
# pre: self.buf_in is not empty
# post: self.buf_in has made progress (smaller or '')
def parse_http_req_line()
var m = global._re_http_srv.match2(self.buf_in, self.buf_in_offset)
import re
# print("parse_http_req_line", "self.buf_in=", self.buf_in)
var m = re.match2(self.server.re_http_srv, self.buf_in, self.buf_in_offset)
# print(f"{m=}")
# Ex: "GET / HTTP/1.1\r\n"
if m
var offset = m[0]
@ -261,16 +264,18 @@ class webserver_async
#############################################################
# parse incoming headers
def parse_http_headers()
import re
while true
# print("parse_http_headers", "self.buf_in_offset=", self.buf_in_offset)
var m = global._re_http_srv_header.match2(self.buf_in, self.buf_in_offset)
# print("m=", m)
var m = re.match2(self.server.re_http_srv_header, self.buf_in, self.buf_in_offset)
# print(f"{m=}")
# Ex: [32, 'Content-Type', 'application/json']
if m
self.event_http_header(m[1], m[2])
self.buf_in_offset += m[0]
else # no more headers
var m2 = global._re_http_srv_body.match2(self.buf_in, self.buf_in_offset)
var m2 = re.match2(self.server.re_http_srv_body, self.buf_in, self.buf_in_offset)
# print(f"{m2=}")
if m2
# end of headers
# we keep \r\n which is used by pattern
@ -519,9 +524,16 @@ class webserver_async
var p1 # temporary object bytes() to avoid reallocation
# static var TIMEOUT = 1000 # default timeout: 1000ms
#############################################################
# pre-compile REGEX
#
# static var HTTP_REQ = "^(\\w+) (\\S+) HTTP\\/(\\d\\.\\d)\r\n"
# static var HTTP_HEADER_REGEX = "([A-Za-z0-9-]+): (.*?)\r\n" # extract a header with its 2 parts
# static var HTTP_BODY_REGEX = "\r\n" # end of headers
static var re_http_srv = re.compilebytes("^(\\w+) (\\S+) HTTP\\/(\\d\\.\\d)\r\n")
static var re_http_srv_header = re.compilebytes("([A-Za-z0-9-]+): (.*?)\r\n")
static var re_http_srv_body = re.compilebytes("\r\n")
#############################################################
# init
@ -535,27 +547,12 @@ class webserver_async
self.cors = false
self.p1 = bytes(100) # reserve 100 bytes by default
# TODO what about max_clients ?
self.compile_re()
# register cb
tasmota.add_driver(self)
self.fastloop_cb = def () self.loop() end
tasmota.add_fast_loop(self.fastloop_cb)
end
#############################################################
# compile once for all the regex
def compile_re()
import re
if !global.contains("_re_http_srv")
# global._re_http_srv = re.compile(self.HTTP_REQ)
# global._re_http_srv_header = re.compile(self.HTTP_HEADER_REGEX)
# global._re_http_srv_body = re.compile(self.HTTP_BODY_REGEX)
global._re_http_srv = re.compile("^(\\w+) (\\S+) HTTP\\/(\\d\\.\\d)\r\n")
global._re_http_srv_header = re.compile("([A-Za-z0-9-]+): (.*?)\r\n")
global._re_http_srv_body = re.compile("\r\n")
end
end
#############################################################
# enable or disable chunked mode (enabled by default)
def set_chunked(chunked)

File diff suppressed because it is too large Load Diff

View File

@ -3,23 +3,26 @@
* Generated code, don't edit *
\********************************************************************/
#include "be_constobj.h"
// compact class 'Tapp' ktab size: 15, total: 16 (saved 8 bytes)
static const bvalue be_ktab_class_Tapp[15] = {
extern const bclass be_class_Tapp;
// compact class 'Tapp' ktab size: 17, total: 18 (saved 8 bytes)
static const bvalue be_ktab_class_Tapp[17] = {
/* K0 */ be_nested_str(tasmota),
/* K1 */ be_nested_str(add_driver),
/* K2 */ be_nested_str(path),
/* K3 */ be_nested_str(string),
/* K4 */ be_nested_str(listdir),
/* K5 */ be_nested_str(_X2F),
/* K6 */ be_nested_str(find),
/* K7 */ be_nested_str(_X2Etapp),
/* K8 */ be_const_int(0),
/* K9 */ be_nested_str(log),
/* K10 */ be_nested_str(TAP_X3A_X20Loaded_X20Tasmota_X20App_X20_X27_X25s_X27),
/* K11 */ be_const_int(2),
/* K12 */ be_nested_str(load),
/* K13 */ be_nested_str(_X23autoexec_X2Ebe),
/* K14 */ be_nested_str(stop_iteration),
/* K2 */ be_nested_str(autoexec_dir),
/* K3 */ be_nested_str(_X2F_X2Eextensions_X2F),
/* K4 */ be_nested_str(_X2F),
/* K5 */ be_const_class(be_class_Tapp),
/* K6 */ be_nested_str(path),
/* K7 */ be_nested_str(string),
/* K8 */ be_nested_str(listdir),
/* K9 */ be_nested_str(endswith),
/* K10 */ be_nested_str(_X2Etapp),
/* K11 */ be_nested_str(log),
/* K12 */ be_nested_str(TAP_X3A_X20Loaded_X20Tasmota_X20App_X20_X27_X25s_X25s_X27),
/* K13 */ be_const_int(2),
/* K14 */ be_nested_str(load),
/* K15 */ be_nested_str(_X23autoexec_X2Ebe),
/* K16 */ be_nested_str(stop_iteration),
};
@ -58,7 +61,7 @@ be_local_closure(class_Tapp_init, /* name */
********************************************************************/
be_local_closure(class_Tapp_autoexec, /* name */
be_nested_proto(
11, /* nstack */
4, /* nstack */
1, /* argc */
10, /* varg */
0, /* has upvals */
@ -69,38 +72,68 @@ be_local_closure(class_Tapp_autoexec, /* name */
&be_ktab_class_Tapp, /* shared constants */
&be_const_str_autoexec,
&be_const_str_solidified,
( &(const binstruction[ 7]) { /* code */
0x8C040102, // 0000 GETMET R1 R0 K2
0x580C0003, // 0001 LDCONST R3 K3
0x7C040400, // 0002 CALL R1 2
0x8C040102, // 0003 GETMET R1 R0 K2
0x580C0004, // 0004 LDCONST R3 K4
0x7C040400, // 0005 CALL R1 2
0x80000000, // 0006 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: autoexec_dir
********************************************************************/
be_local_closure(class_Tapp_autoexec_dir, /* name */
be_nested_proto(
11, /* nstack */
1, /* argc */
12, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
&be_ktab_class_Tapp, /* shared constants */
&be_const_str_autoexec_dir,
&be_const_str_solidified,
( &(const binstruction[34]) { /* code */
0xA4060400, // 0000 IMPORT R1 K2
0xA40A0600, // 0001 IMPORT R2 K3
0x8C0C0304, // 0002 GETMET R3 R1 K4
0x58140005, // 0003 LDCONST R5 K5
0x7C0C0400, // 0004 CALL R3 2
0x60100010, // 0005 GETGBL R4 G16
0x5C140600, // 0006 MOVE R5 R3
0x58040005, // 0000 LDCONST R1 K5
0xA40A0C00, // 0001 IMPORT R2 K6
0xA40E0E00, // 0002 IMPORT R3 K7
0x60100010, // 0003 GETGBL R4 G16
0x8C140508, // 0004 GETMET R5 R2 K8
0x5C1C0000, // 0005 MOVE R7 R0
0x7C140400, // 0006 CALL R5 2
0x7C100200, // 0007 CALL R4 1
0xA8020014, // 0008 EXBLK 0 #001E
0x5C140800, // 0009 MOVE R5 R4
0x7C140000, // 000A CALL R5 0
0x8C180506, // 000B GETMET R6 R2 K6
0x8C180709, // 000B GETMET R6 R3 K9
0x5C200A00, // 000C MOVE R8 R5
0x58240007, // 000D LDCONST R9 K7
0x5824000A, // 000D LDCONST R9 K10
0x7C180600, // 000E CALL R6 3
0x24180D08, // 000F GT R6 R6 K8
0x781A000B, // 0010 JMPF R6 #001D
0xB81A0000, // 0011 GETNGBL R6 K0
0x8C180D09, // 0012 GETMET R6 R6 K9
0x60200018, // 0013 GETGBL R8 G24
0x5824000A, // 0014 LDCONST R9 K10
0x5C280A00, // 0015 MOVE R10 R5
0x7C200400, // 0016 CALL R8 2
0x5824000B, // 0017 LDCONST R9 K11
0x7C180600, // 0018 CALL R6 3
0xB81A0000, // 0019 GETNGBL R6 K0
0x8C180D0C, // 001A GETMET R6 R6 K12
0x00200B0D, // 001B ADD R8 R5 K13
0x781A000C, // 000F JMPF R6 #001D
0xB81A1600, // 0010 GETNGBL R6 K11
0x601C0018, // 0011 GETGBL R7 G24
0x5820000C, // 0012 LDCONST R8 K12
0x5C240000, // 0013 MOVE R9 R0
0x5C280A00, // 0014 MOVE R10 R5
0x7C1C0600, // 0015 CALL R7 3
0x5820000D, // 0016 LDCONST R8 K13
0x7C180400, // 0017 CALL R6 2
0xB81A0000, // 0018 GETNGBL R6 K0
0x8C180D0E, // 0019 GETMET R6 R6 K14
0x00200005, // 001A ADD R8 R0 R5
0x0020110F, // 001B ADD R8 R8 K15
0x7C180400, // 001C CALL R6 2
0x7001FFEA, // 001D JMP #0009
0x5810000E, // 001E LDCONST R4 K14
0x58100010, // 001E LDCONST R4 K16
0xAC100200, // 001F CATCH R4 1 0
0xB0080000, // 0020 RAISE 2 R0 R0
0x80000000, // 0021 RET 0
@ -116,10 +149,11 @@ be_local_closure(class_Tapp_autoexec, /* name */
be_local_class(Tapp,
0,
NULL,
be_nested_map(2,
be_nested_map(3,
( (struct bmapnode*) &(const bmapnode[]) {
{ be_const_key(init, -1), be_const_closure(class_Tapp_init_closure) },
{ be_const_key(autoexec, -1), be_const_closure(class_Tapp_autoexec_closure) },
{ be_const_key(init, 0), be_const_closure(class_Tapp_init_closure) },
{ be_const_key(autoexec_dir, -1), be_const_static_closure(class_Tapp_autoexec_dir_closure) },
})),
(bstring*) &be_const_str_Tapp
);

View File

@ -4,62 +4,82 @@
#include "re1.5.h"
// TASMOTA SPECIFIC
#ifndef INST_BUF_SIZE
#define INST_BUF_SIZE 96
#endif
void be_writebuffer(const char *buffer, size_t length);
#define be_writestring(s) be_writebuffer((s), strlen(s))
#define logbuf(...) snprintf(__lbuf, sizeof(__lbuf), __VA_ARGS__)
#define logfmt(...) \
do { \
char __lbuf[INST_BUF_SIZE]; \
logbuf(__VA_ARGS__); \
be_writestring(__lbuf); \
} while (0)
// all `printf` replaced with `logfmt`
void re1_5_dumpcode(ByteProg *prog)
{
int pc = 0;
char *code = prog->insts;
while (pc < prog->bytelen) {
printf("%2d: ", pc);
logfmt("%2d: ", pc);
switch(code[pc++]) {
default:
assert(0);
// re1_5_fatal("printprog");
case Split:
printf("split %d (%d)\n", pc + (signed char)code[pc] + 1, (signed char)code[pc]);
logfmt("split %d (%d)\n", pc + (signed char)code[pc] + 1, (signed char)code[pc]);
pc++;
break;
case RSplit:
printf("rsplit %d (%d)\n", pc + (signed char)code[pc] + 1, (signed char)code[pc]);
logfmt("rsplit %d (%d)\n", pc + (signed char)code[pc] + 1, (signed char)code[pc]);
pc++;
break;
case Jmp:
printf("jmp %d (%d)\n", pc + (signed char)code[pc] + 1, (signed char)code[pc]);
logfmt("jmp %d (%d)\n", pc + (signed char)code[pc] + 1, (signed char)code[pc]);
pc++;
break;
case Char:
printf("char %c\n", code[pc++]);
logfmt("char %c\n", code[pc++]);
break;
case Any:
printf("any\n");
logfmt("any\n");
break;
case Class:
case ClassNot: {
int num = code[pc];
printf("class%s %d", (code[pc - 1] == ClassNot ? "not" : ""), num);
logfmt("class%s %d", (code[pc - 1] == ClassNot ? "not" : ""), num);
pc++;
while (num--) {
printf(" 0x%02x-0x%02x", code[pc], code[pc + 1]);
logfmt(" 0x%02x-0x%02x", code[pc], code[pc + 1]);
pc += 2;
}
printf("\n");
logfmt("\n");
break;
}
case NamedClass:
printf("namedclass %c\n", code[pc++]);
logfmt("namedclass %c\n", code[pc++]);
break;
case Match:
printf("match\n");
logfmt("match\n");
break;
case Save:
printf("save %d\n", (unsigned char)code[pc++]);
logfmt("save %d\n", (unsigned char)code[pc++]);
break;
case Bol:
printf("assert bol\n");
logfmt("assert bol\n");
break;
case Eol:
printf("assert eol\n");
logfmt("assert eol\n");
break;
}
}
printf("Bytes: %d, insts: %d\n", prog->bytelen, prog->len);
logfmt("Bytes: %d, insts: %d\n", prog->bytelen, prog->len);
}

File diff suppressed because it is too large Load Diff

View File

@ -40,8 +40,7 @@ typedef enum {
* @param font pointer to a font to use.
* @return a pointer to reference this theme later
*/
lv_theme_t * lv_theme_haspmota_init(lv_display_t * disp, lv_color_t color_primary, lv_color_t color_secondary, bool dark, const lv_font_t * font);
lv_theme_t * lv_theme_haspmota_init(lv_display_t * disp, lv_color_t * colors, const lv_font_t * font_small, const lv_font_t * font_normal, const lv_font_t * font_large);
bool lv_theme_haspmota_is_inited(void);
/**********************

View File

@ -152,7 +152,7 @@ theme_get_font_large|lv.obj|lv.font|[lv_theme_get_font_large](https://docs.lvgl.
theme_get_font_normal|lv.obj|lv.font|[lv_theme_get_font_normal](https://docs.lvgl.io/9.0/search.html?q=lv_theme_get_font_normal)
theme_get_font_small|lv.obj|lv.font|[lv_theme_get_font_small](https://docs.lvgl.io/9.0/search.html?q=lv_theme_get_font_small)
theme_get_from_obj|lv.obj|lv.theme|[lv_theme_get_from_obj](https://docs.lvgl.io/9.0/search.html?q=lv_theme_get_from_obj)
theme_haspmota_init|lv.display, lv.color, lv.color, bool, lv.font|lv.theme|[lv_theme_haspmota_init](https://docs.lvgl.io/9.0/search.html?q=lv_theme_haspmota_init)
theme_haspmota_init|lv.display, lv.color_arr, lv.font, lv.font, lv.font|lv.theme|[lv_theme_haspmota_init](https://docs.lvgl.io/9.0/search.html?q=lv_theme_haspmota_init)
theme_haspmota_is_inited||bool|[lv_theme_haspmota_is_inited](https://docs.lvgl.io/9.0/search.html?q=lv_theme_haspmota_is_inited)
theme_set_parent|lv.theme, lv.theme||[lv_theme_set_parent](https://docs.lvgl.io/9.0/search.html?q=lv_theme_set_parent)
timer_create|\<closure\>, int, \<any\>|lv.timer|[lv_timer_create](https://docs.lvgl.io/9.0/search.html?q=lv_timer_create)

View File

@ -174,7 +174,7 @@ const be_ntv_func_def_t lv_func[] = {
{ "theme_get_font_normal", { (const void*) &lv_theme_get_font_normal, "lv.font", "(lv.obj)" } },
{ "theme_get_font_small", { (const void*) &lv_theme_get_font_small, "lv.font", "(lv.obj)" } },
{ "theme_get_from_obj", { (const void*) &lv_theme_get_from_obj, "lv.theme", "(lv.obj)" } },
{ "theme_haspmota_init", { (const void*) &lv_theme_haspmota_init, "lv.theme", "(lv.display)(lv.color)(lv.color)b(lv.font)" } },
{ "theme_haspmota_init", { (const void*) &lv_theme_haspmota_init, "lv.theme", "(lv.display)(lv.color_arr)(lv.font)(lv.font)(lv.font)" } },
{ "theme_haspmota_is_inited", { (const void*) &lv_theme_haspmota_is_inited, "b", "" } },
{ "theme_set_parent", { (const void*) &lv_theme_set_parent, "", "(lv.theme)(lv.theme)" } },
{ "timer_create", { (const void*) &lv_timer_create, "lv.timer", "^lv_timer_cb^i." } },

View File

@ -1491,7 +1491,7 @@ lv_obj_t * lv_tileview_get_tile_active(lv_obj_t * obj)
// ../../lvgl/src/widgets/win/lv_win.h
// ../../LVGL_assets/src/lv_theme_haspmota.h
lv_theme_t * lv_theme_haspmota_init(lv_display_t * disp, lv_color_t color_primary, lv_color_t color_secondary, bool dark, const lv_font_t * font)
lv_theme_t * lv_theme_haspmota_init(lv_display_t * disp, lv_color_t * colors, const lv_font_t * font_small, const lv_font_t * font_normal, const lv_font_t * font_large)
bool lv_theme_haspmota_is_inited(void)
// ../src/lv_berry.h

View File

@ -112,14 +112,32 @@ end
class lv_style_prop_arr : bytes
def init(l)
if type(l) != 'instance' || !isinstance(l, list) raise "value_error", "argument must be a list" end
super(self).init(size(l) * 4)
super(self).init(size(l))
for e: l
self.add(int(e), 4)
self.add(int(e))
end
end
end
class lv_color_arr : bytes
def init(l)
if type(l) != 'instance' || !isinstance(l, list) raise "value_error", "argument must be a list" end
super(self).init(size(l) * 3)
for e: l
self.add(int(e), 3)
end
end
def item(n)
return lv.color(self.get(n * 3, 3))
end
def setitem(n, v)
self.set(n * 3, int(v), 3)
end
end
class lv_str_arr : bytes
var l # keep a copy of the list because we want the pointer to strings to remain valid
def init(l)
@ -138,6 +156,7 @@ lv_extra.lv_int_arr = lv_int_arr
lv_extra.lv_point_arr = lv_point_arr
lv_extra.lv_style_prop_arr = lv_style_prop_arr
lv_extra.lv_str_arr = lv_str_arr
lv_extra.lv_color_arr = lv_color_arr
lv_extra.init = def (m)
import global
@ -151,6 +170,7 @@ lv_extra.init = def (m)
lv.point_arr = m.lv_point_arr
lv.style_prop_arr = m.lv_style_prop_arr
lv.str_arr = m.lv_str_arr
lv.color_arr = m.lv_color_arr
return m
end
@ -170,4 +190,4 @@ p2.x = 3
p2.y = 4
print(lv_point_arr([p1, p2]))
-#
-#

View File

@ -4,84 +4,6 @@
\********************************************************************/
#include "be_constobj.h"
extern const bclass be_class_lv_str_arr;
/********************************************************************
** Solidified function: init
********************************************************************/
be_local_closure(class_lv_str_arr_init, /* name */
be_nested_proto(
11, /* nstack */
2, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 6]) { /* constants */
/* K0 */ be_nested_str_weak(l),
/* K1 */ be_nested_str_weak(init),
/* K2 */ be_nested_str_weak(introspect),
/* K3 */ be_nested_str_weak(add),
/* K4 */ be_nested_str_weak(toptr),
/* K5 */ be_nested_str_weak(stop_iteration),
}),
be_str_weak(init),
&be_const_str_solidified,
( &(const binstruction[31]) { /* code */
0x90020001, // 0000 SETMBR R0 K0 R1
0x60080003, // 0001 GETGBL R2 G3
0x5C0C0000, // 0002 MOVE R3 R0
0x7C080200, // 0003 CALL R2 1
0x8C080501, // 0004 GETMET R2 R2 K1
0x6010000C, // 0005 GETGBL R4 G12
0x5C140200, // 0006 MOVE R5 R1
0x7C100200, // 0007 CALL R4 1
0x54160003, // 0008 LDINT R5 4
0x08100805, // 0009 MUL R4 R4 R5
0x7C080400, // 000A CALL R2 2
0xA40A0400, // 000B IMPORT R2 K2
0x600C0010, // 000C GETGBL R3 G16
0x5C100200, // 000D MOVE R4 R1
0x7C0C0200, // 000E CALL R3 1
0xA802000A, // 000F EXBLK 0 #001B
0x5C100600, // 0010 MOVE R4 R3
0x7C100000, // 0011 CALL R4 0
0x8C140103, // 0012 GETMET R5 R0 K3
0x601C0009, // 0013 GETGBL R7 G9
0x8C200504, // 0014 GETMET R8 R2 K4
0x5C280800, // 0015 MOVE R10 R4
0x7C200400, // 0016 CALL R8 2
0x7C1C0200, // 0017 CALL R7 1
0x54220003, // 0018 LDINT R8 4
0x7C140600, // 0019 CALL R5 3
0x7001FFF4, // 001A JMP #0010
0x580C0005, // 001B LDCONST R3 K5
0xAC0C0200, // 001C CATCH R3 1 0
0xB0080000, // 001D RAISE 2 R0 R0
0x80000000, // 001E RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified class: lv_str_arr
********************************************************************/
extern const bclass be_class_bytes;
be_local_class(lv_str_arr,
1,
&be_class_bytes,
be_nested_map(2,
( (struct bmapnode*) &(const bmapnode[]) {
{ be_const_key_weak(init, -1), be_const_closure(class_lv_str_arr_init_closure) },
{ be_const_key_weak(l, 0), be_const_var(0) },
})),
be_str_weak(lv_str_arr)
);
extern const bclass be_class_lv_int_arr;
/********************************************************************
@ -355,88 +277,41 @@ be_local_class(lv_point_arr,
})),
be_str_weak(lv_point_arr)
);
/********************************************************************
** Solidified function: _anonymous_
********************************************************************/
be_local_closure(_anonymous_, /* name */
be_nested_proto(
4, /* nstack */
1, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[12]) { /* constants */
/* K0 */ be_nested_str_weak(global),
/* K1 */ be_nested_str_weak(lv),
/* K2 */ be_nested_str_weak(lv_coord_arr),
/* K3 */ be_nested_str_weak(lv_int_arr),
/* K4 */ be_nested_str_weak(lv_point_arr),
/* K5 */ be_nested_str_weak(coord_arr),
/* K6 */ be_nested_str_weak(int_arr),
/* K7 */ be_nested_str_weak(point_arr),
/* K8 */ be_nested_str_weak(style_prop_arr),
/* K9 */ be_nested_str_weak(lv_style_prop_arr),
/* K10 */ be_nested_str_weak(str_arr),
/* K11 */ be_nested_str_weak(lv_str_arr),
}),
be_str_weak(_anonymous_),
&be_const_str_solidified,
( &(const binstruction[19]) { /* code */
0xA4060000, // 0000 IMPORT R1 K0
0x88080301, // 0001 GETMBR R2 R1 K1
0x880C0102, // 0002 GETMBR R3 R0 K2
0x900A0403, // 0003 SETMBR R2 K2 R3
0x880C0103, // 0004 GETMBR R3 R0 K3
0x900A0603, // 0005 SETMBR R2 K3 R3
0x880C0104, // 0006 GETMBR R3 R0 K4
0x900A0803, // 0007 SETMBR R2 K4 R3
0x880C0102, // 0008 GETMBR R3 R0 K2
0x900A0A03, // 0009 SETMBR R2 K5 R3
0x880C0103, // 000A GETMBR R3 R0 K3
0x900A0C03, // 000B SETMBR R2 K6 R3
0x880C0104, // 000C GETMBR R3 R0 K4
0x900A0E03, // 000D SETMBR R2 K7 R3
0x880C0109, // 000E GETMBR R3 R0 K9
0x900A1003, // 000F SETMBR R2 K8 R3
0x880C010B, // 0010 GETMBR R3 R0 K11
0x900A1403, // 0011 SETMBR R2 K10 R3
0x80040000, // 0012 RET 1 R0
})
)
);
/*******************************************************************/
// compact class 'lv_color_arr' ktab size: 11, total: 13 (saved 16 bytes)
static const bvalue be_ktab_class_lv_color_arr[11] = {
/* K0 */ be_nested_str_weak(instance),
/* K1 */ be_nested_str_weak(value_error),
/* K2 */ be_nested_str_weak(argument_X20must_X20be_X20a_X20list),
/* K3 */ be_nested_str_weak(init),
/* K4 */ be_const_int(3),
/* K5 */ be_nested_str_weak(add),
/* K6 */ be_nested_str_weak(stop_iteration),
/* K7 */ be_nested_str_weak(lv),
/* K8 */ be_nested_str_weak(color),
/* K9 */ be_nested_str_weak(get),
/* K10 */ be_nested_str_weak(set),
};
extern const bclass be_class_lv_style_prop_arr;
extern const bclass be_class_lv_color_arr;
/********************************************************************
** Solidified function: init
********************************************************************/
be_local_closure(class_lv_style_prop_arr_init, /* name */
be_local_closure(class_lv_color_arr_init, /* name */
be_nested_proto(
8, /* nstack */
2, /* argc */
2, /* varg */
10, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 6]) { /* constants */
/* K0 */ be_nested_str_weak(instance),
/* K1 */ be_nested_str_weak(value_error),
/* K2 */ be_nested_str_weak(argument_X20must_X20be_X20a_X20list),
/* K3 */ be_nested_str_weak(init),
/* K4 */ be_nested_str_weak(add),
/* K5 */ be_nested_str_weak(stop_iteration),
}),
&be_ktab_class_lv_color_arr, /* shared constants */
be_str_weak(init),
&be_const_str_solidified,
( &(const binstruction[38]) { /* code */
( &(const binstruction[37]) { /* code */
0x60080004, // 0000 GETGBL R2 G4
0x5C0C0200, // 0001 MOVE R3 R1
0x7C080200, // 0002 CALL R2 1
@ -455,26 +330,25 @@ be_local_closure(class_lv_style_prop_arr_init, /* name */
0x6010000C, // 000F GETGBL R4 G12
0x5C140200, // 0010 MOVE R5 R1
0x7C100200, // 0011 CALL R4 1
0x54160003, // 0012 LDINT R5 4
0x08100805, // 0013 MUL R4 R4 R5
0x7C080400, // 0014 CALL R2 2
0x60080010, // 0015 GETGBL R2 G16
0x5C0C0200, // 0016 MOVE R3 R1
0x7C080200, // 0017 CALL R2 1
0xA8020008, // 0018 EXBLK 0 #0022
0x5C0C0400, // 0019 MOVE R3 R2
0x7C0C0000, // 001A CALL R3 0
0x8C100104, // 001B GETMET R4 R0 K4
0x60180009, // 001C GETGBL R6 G9
0x5C1C0600, // 001D MOVE R7 R3
0x7C180200, // 001E CALL R6 1
0x541E0003, // 001F LDINT R7 4
0x7C100600, // 0020 CALL R4 3
0x7001FFF6, // 0021 JMP #0019
0x58080005, // 0022 LDCONST R2 K5
0xAC080200, // 0023 CATCH R2 1 0
0xB0080000, // 0024 RAISE 2 R0 R0
0x80000000, // 0025 RET 0
0x08100904, // 0012 MUL R4 R4 K4
0x7C080400, // 0013 CALL R2 2
0x60080010, // 0014 GETGBL R2 G16
0x5C0C0200, // 0015 MOVE R3 R1
0x7C080200, // 0016 CALL R2 1
0xA8020008, // 0017 EXBLK 0 #0021
0x5C0C0400, // 0018 MOVE R3 R2
0x7C0C0000, // 0019 CALL R3 0
0x8C100105, // 001A GETMET R4 R0 K5
0x60180009, // 001B GETGBL R6 G9
0x5C1C0600, // 001C MOVE R7 R3
0x7C180200, // 001D CALL R6 1
0x581C0004, // 001E LDCONST R7 K4
0x7C100600, // 001F CALL R4 3
0x7001FFF6, // 0020 JMP #0018
0x58080006, // 0021 LDCONST R2 K6
0xAC080200, // 0022 CATCH R2 1 0
0xB0080000, // 0023 RAISE 2 R0 R0
0x80000000, // 0024 RET 0
})
)
);
@ -482,19 +356,142 @@ be_local_closure(class_lv_style_prop_arr_init, /* name */
/********************************************************************
** Solidified class: lv_style_prop_arr
** Solidified function: item
********************************************************************/
be_local_closure(class_lv_color_arr_item, /* name */
be_nested_proto(
8, /* nstack */
2, /* argc */
10, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
&be_ktab_class_lv_color_arr, /* shared constants */
be_str_weak(item),
&be_const_str_solidified,
( &(const binstruction[ 8]) { /* code */
0xB80A0E00, // 0000 GETNGBL R2 K7
0x8C080508, // 0001 GETMET R2 R2 K8
0x8C100109, // 0002 GETMET R4 R0 K9
0x08180304, // 0003 MUL R6 R1 K4
0x581C0004, // 0004 LDCONST R7 K4
0x7C100600, // 0005 CALL R4 3
0x7C080400, // 0006 CALL R2 2
0x80040400, // 0007 RET 1 R2
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified function: setitem
********************************************************************/
be_local_closure(class_lv_color_arr_setitem, /* name */
be_nested_proto(
8, /* nstack */
3, /* argc */
10, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
&be_ktab_class_lv_color_arr, /* shared constants */
be_str_weak(setitem),
&be_const_str_solidified,
( &(const binstruction[ 8]) { /* code */
0x8C0C010A, // 0000 GETMET R3 R0 K10
0x08140304, // 0001 MUL R5 R1 K4
0x60180009, // 0002 GETGBL R6 G9
0x5C1C0400, // 0003 MOVE R7 R2
0x7C180200, // 0004 CALL R6 1
0x581C0004, // 0005 LDCONST R7 K4
0x7C0C0800, // 0006 CALL R3 4
0x80000000, // 0007 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified class: lv_color_arr
********************************************************************/
extern const bclass be_class_bytes;
be_local_class(lv_style_prop_arr,
be_local_class(lv_color_arr,
0,
&be_class_bytes,
be_nested_map(1,
be_nested_map(3,
( (struct bmapnode*) &(const bmapnode[]) {
{ be_const_key_weak(init, -1), be_const_closure(class_lv_style_prop_arr_init_closure) },
{ be_const_key_weak(init, -1), be_const_closure(class_lv_color_arr_init_closure) },
{ be_const_key_weak(item, -1), be_const_closure(class_lv_color_arr_item_closure) },
{ be_const_key_weak(setitem, -1), be_const_closure(class_lv_color_arr_setitem_closure) },
})),
be_str_weak(lv_style_prop_arr)
be_str_weak(lv_color_arr)
);
/********************************************************************
** Solidified function: _anonymous_
********************************************************************/
be_local_closure(_anonymous_, /* name */
be_nested_proto(
4, /* nstack */
1, /* argc */
0, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[14]) { /* constants */
/* K0 */ be_nested_str_weak(global),
/* K1 */ be_nested_str_weak(lv),
/* K2 */ be_nested_str_weak(lv_coord_arr),
/* K3 */ be_nested_str_weak(lv_int_arr),
/* K4 */ be_nested_str_weak(lv_point_arr),
/* K5 */ be_nested_str_weak(coord_arr),
/* K6 */ be_nested_str_weak(int_arr),
/* K7 */ be_nested_str_weak(point_arr),
/* K8 */ be_nested_str_weak(style_prop_arr),
/* K9 */ be_nested_str_weak(lv_style_prop_arr),
/* K10 */ be_nested_str_weak(str_arr),
/* K11 */ be_nested_str_weak(lv_str_arr),
/* K12 */ be_nested_str_weak(color_arr),
/* K13 */ be_nested_str_weak(lv_color_arr),
}),
be_str_weak(_anonymous_),
&be_const_str_solidified,
( &(const binstruction[21]) { /* code */
0xA4060000, // 0000 IMPORT R1 K0
0x88080301, // 0001 GETMBR R2 R1 K1
0x880C0102, // 0002 GETMBR R3 R0 K2
0x900A0403, // 0003 SETMBR R2 K2 R3
0x880C0103, // 0004 GETMBR R3 R0 K3
0x900A0603, // 0005 SETMBR R2 K3 R3
0x880C0104, // 0006 GETMBR R3 R0 K4
0x900A0803, // 0007 SETMBR R2 K4 R3
0x880C0102, // 0008 GETMBR R3 R0 K2
0x900A0A03, // 0009 SETMBR R2 K5 R3
0x880C0103, // 000A GETMBR R3 R0 K3
0x900A0C03, // 000B SETMBR R2 K6 R3
0x880C0104, // 000C GETMBR R3 R0 K4
0x900A0E03, // 000D SETMBR R2 K7 R3
0x880C0109, // 000E GETMBR R3 R0 K9
0x900A1003, // 000F SETMBR R2 K8 R3
0x880C010B, // 0010 GETMBR R3 R0 K11
0x900A1403, // 0011 SETMBR R2 K10 R3
0x880C010D, // 0012 GETMBR R3 R0 K13
0x900A1803, // 0013 SETMBR R2 K12 R3
0x80040000, // 0014 RET 1 R0
})
)
);
/*******************************************************************/
extern const bclass be_class_lv_coord_arr;
/********************************************************************
@ -666,19 +663,179 @@ be_local_class(lv_coord_arr,
be_str_weak(lv_coord_arr)
);
extern const bclass be_class_lv_style_prop_arr;
/********************************************************************
** Solidified function: init
********************************************************************/
be_local_closure(class_lv_style_prop_arr_init, /* name */
be_nested_proto(
8, /* nstack */
2, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 6]) { /* constants */
/* K0 */ be_nested_str_weak(instance),
/* K1 */ be_nested_str_weak(value_error),
/* K2 */ be_nested_str_weak(argument_X20must_X20be_X20a_X20list),
/* K3 */ be_nested_str_weak(init),
/* K4 */ be_nested_str_weak(add),
/* K5 */ be_nested_str_weak(stop_iteration),
}),
be_str_weak(init),
&be_const_str_solidified,
( &(const binstruction[35]) { /* code */
0x60080004, // 0000 GETGBL R2 G4
0x5C0C0200, // 0001 MOVE R3 R1
0x7C080200, // 0002 CALL R2 1
0x20080500, // 0003 NE R2 R2 K0
0x740A0004, // 0004 JMPT R2 #000A
0x6008000F, // 0005 GETGBL R2 G15
0x5C0C0200, // 0006 MOVE R3 R1
0x60100012, // 0007 GETGBL R4 G18
0x7C080400, // 0008 CALL R2 2
0x740A0000, // 0009 JMPT R2 #000B
0xB0060302, // 000A RAISE 1 K1 K2
0x60080003, // 000B GETGBL R2 G3
0x5C0C0000, // 000C MOVE R3 R0
0x7C080200, // 000D CALL R2 1
0x8C080503, // 000E GETMET R2 R2 K3
0x6010000C, // 000F GETGBL R4 G12
0x5C140200, // 0010 MOVE R5 R1
0x7C100200, // 0011 CALL R4 1
0x7C080400, // 0012 CALL R2 2
0x60080010, // 0013 GETGBL R2 G16
0x5C0C0200, // 0014 MOVE R3 R1
0x7C080200, // 0015 CALL R2 1
0xA8020007, // 0016 EXBLK 0 #001F
0x5C0C0400, // 0017 MOVE R3 R2
0x7C0C0000, // 0018 CALL R3 0
0x8C100104, // 0019 GETMET R4 R0 K4
0x60180009, // 001A GETGBL R6 G9
0x5C1C0600, // 001B MOVE R7 R3
0x7C180200, // 001C CALL R6 1
0x7C100400, // 001D CALL R4 2
0x7001FFF7, // 001E JMP #0017
0x58080005, // 001F LDCONST R2 K5
0xAC080200, // 0020 CATCH R2 1 0
0xB0080000, // 0021 RAISE 2 R0 R0
0x80000000, // 0022 RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified class: lv_style_prop_arr
********************************************************************/
extern const bclass be_class_bytes;
be_local_class(lv_style_prop_arr,
0,
&be_class_bytes,
be_nested_map(1,
( (struct bmapnode*) &(const bmapnode[]) {
{ be_const_key_weak(init, -1), be_const_closure(class_lv_style_prop_arr_init_closure) },
})),
be_str_weak(lv_style_prop_arr)
);
extern const bclass be_class_lv_str_arr;
/********************************************************************
** Solidified function: init
********************************************************************/
be_local_closure(class_lv_str_arr_init, /* name */
be_nested_proto(
11, /* nstack */
2, /* argc */
2, /* varg */
0, /* has upvals */
NULL, /* no upvals */
0, /* has sup protos */
NULL, /* no sub protos */
1, /* has constants */
( &(const bvalue[ 6]) { /* constants */
/* K0 */ be_nested_str_weak(l),
/* K1 */ be_nested_str_weak(init),
/* K2 */ be_nested_str_weak(introspect),
/* K3 */ be_nested_str_weak(add),
/* K4 */ be_nested_str_weak(toptr),
/* K5 */ be_nested_str_weak(stop_iteration),
}),
be_str_weak(init),
&be_const_str_solidified,
( &(const binstruction[31]) { /* code */
0x90020001, // 0000 SETMBR R0 K0 R1
0x60080003, // 0001 GETGBL R2 G3
0x5C0C0000, // 0002 MOVE R3 R0
0x7C080200, // 0003 CALL R2 1
0x8C080501, // 0004 GETMET R2 R2 K1
0x6010000C, // 0005 GETGBL R4 G12
0x5C140200, // 0006 MOVE R5 R1
0x7C100200, // 0007 CALL R4 1
0x54160003, // 0008 LDINT R5 4
0x08100805, // 0009 MUL R4 R4 R5
0x7C080400, // 000A CALL R2 2
0xA40A0400, // 000B IMPORT R2 K2
0x600C0010, // 000C GETGBL R3 G16
0x5C100200, // 000D MOVE R4 R1
0x7C0C0200, // 000E CALL R3 1
0xA802000A, // 000F EXBLK 0 #001B
0x5C100600, // 0010 MOVE R4 R3
0x7C100000, // 0011 CALL R4 0
0x8C140103, // 0012 GETMET R5 R0 K3
0x601C0009, // 0013 GETGBL R7 G9
0x8C200504, // 0014 GETMET R8 R2 K4
0x5C280800, // 0015 MOVE R10 R4
0x7C200400, // 0016 CALL R8 2
0x7C1C0200, // 0017 CALL R7 1
0x54220003, // 0018 LDINT R8 4
0x7C140600, // 0019 CALL R5 3
0x7001FFF4, // 001A JMP #0010
0x580C0005, // 001B LDCONST R3 K5
0xAC0C0200, // 001C CATCH R3 1 0
0xB0080000, // 001D RAISE 2 R0 R0
0x80000000, // 001E RET 0
})
)
);
/*******************************************************************/
/********************************************************************
** Solidified class: lv_str_arr
********************************************************************/
extern const bclass be_class_bytes;
be_local_class(lv_str_arr,
1,
&be_class_bytes,
be_nested_map(2,
( (struct bmapnode*) &(const bmapnode[]) {
{ be_const_key_weak(init, -1), be_const_closure(class_lv_str_arr_init_closure) },
{ be_const_key_weak(l, 0), be_const_var(0) },
})),
be_str_weak(lv_str_arr)
);
/********************************************************************
** Solidified module: lv_extra
********************************************************************/
be_local_module(lv_extra,
"lv_extra",
be_nested_map(6,
be_nested_map(7,
( (struct bmapnode*) &(const bmapnode[]) {
{ be_const_key_weak(lv_coord_arr, 4), be_const_class(be_class_lv_coord_arr) },
{ be_const_key_weak(lv_int_arr, -1), be_const_class(be_class_lv_int_arr) },
{ be_const_key_weak(lv_style_prop_arr, 4), be_const_class(be_class_lv_style_prop_arr) },
{ be_const_key_weak(lv_str_arr, -1), be_const_class(be_class_lv_str_arr) },
{ be_const_key_weak(lv_coord_arr, -1), be_const_class(be_class_lv_coord_arr) },
{ be_const_key_weak(lv_int_arr, 0), be_const_class(be_class_lv_int_arr) },
{ be_const_key_weak(lv_point_arr, -1), be_const_class(be_class_lv_point_arr) },
{ be_const_key_weak(init, -1), be_const_closure(_anonymous__closure) },
{ be_const_key_weak(lv_style_prop_arr, -1), be_const_class(be_class_lv_style_prop_arr) },
{ be_const_key_weak(lv_str_arr, 0), be_const_class(be_class_lv_str_arr) },
{ be_const_key_weak(lv_color_arr, 2), be_const_class(be_class_lv_color_arr) },
}))
);
BE_EXPORT_VARIABLE be_define_const_native_module(lv_extra);

View File

@ -383,6 +383,7 @@ class type_mapper_class:
"int32_t *": "lv_int_arr",
"int32_t []": "lv_int_arr",
"uint32_t *": "lv_int_arr",
"lv_color_t *": "lv_color_arr",
# "float *": "lv_float_arr",
# layouts
"lv_flex_align_t": "i",

View File

@ -2360,6 +2360,7 @@ class lvh_chart : lvh_obj
var _ser1, _ser2
# y_min/y_max contain the main range for y. Since LVGL does not have getters, we need to memorize on our side the lates tvalues
var _y_min, _y_max
var _y2_min, _y2_max
# h_div/v_div contain the horizontal and vertical divisions, we need to memorize values because both are set from same API
var _h_div, _v_div
@ -2367,6 +2368,8 @@ class lvh_chart : lvh_obj
# default values from LVGL are 0..100
self._y_min = 0
self._y_max = 100
self._y2_min = 0
self._y2_max = 100
# default values
#define LV_CHART_HDIV_DEF 3
#define LV_CHART_VDIV_DEF 5
@ -2376,7 +2379,7 @@ class lvh_chart : lvh_obj
self._lv_obj.set_update_mode(lv.CHART_UPDATE_MODE_SHIFT)
self._ser1 = self._lv_obj.add_series(lv.color(0xEE4444), lv.CHART_AXIS_PRIMARY_Y)
self._ser2 = self._lv_obj.add_series(lv.color(0x44EE44), lv.CHART_AXIS_PRIMARY_Y)
self._ser2 = self._lv_obj.add_series(lv.color(0x44EE44), lv.CHART_AXIS_SECONDARY_Y)
end
def add_point(v)
@ -2399,6 +2402,12 @@ class lvh_chart : lvh_obj
def get_y_max()
return self._y_max
end
def get_y2_min()
return self._y2_min
end
def get_y2_max()
return self._y2_max
end
def set_y_min(_y_min)
self._y_min = _y_min
self._lv_obj.set_range(lv.CHART_AXIS_PRIMARY_Y, self._y_min, self._y_max)
@ -2407,6 +2416,14 @@ class lvh_chart : lvh_obj
self._y_max = _y_max
self._lv_obj.set_range(lv.CHART_AXIS_PRIMARY_Y, self._y_min, self._y_max)
end
def set_y2_min(_y2_min)
self._y2_min = _y2_min
self._lv_obj.set_range(lv.CHART_AXIS_SECONDARY_Y, self._y2_min, self._y2_max)
end
def set_y2_max(_y2_max)
self._y2_max = _y2_max
self._lv_obj.set_range(lv.CHART_AXIS_SECONDARY_Y, self._y2_min, self._y2_max)
end
def set_series1_color(color)
self._lv_obj.set_series_color(self._ser1, self.parse_color(color))
@ -2601,8 +2618,6 @@ class lvh_page
self._lv_scr = lv.layer_top() # top layer, visible over all screens
else
self._lv_scr = lv.obj(0) # allocate a new screen
var bg_color = lv.scr_act().get_style_bg_color(0 #- lv.PART_MAIN | lv.STATE_DEFAULT -#) # bg_color of default screen
self._lv_scr.set_style_bg_color(bg_color, 0 #- lv.PART_MAIN | lv.STATE_DEFAULT -#) # set white background
end
# page object is also stored in the object map at id `0` as instance of `lvg_scr`
@ -2784,10 +2799,10 @@ end
# main class controller, meant to be a singleton and the only externally used class
class HASPmota
var dark # (bool) use dark theme?
var started # (bool) is HASPmota already started?
var hres, vres # (int) resolution
var scr # (lv_obj) default LVGL screen
var r16 # (lv_font) robotocondensed fonts size 16
var r12, r16, r24 # (lv_font) robotocondensed fonts size 12, 16 and 24
# haspmota objects
var lvh_pages # (list of lvg_page) list of pages
var lvh_page_cur_idx # (int) current page index number
@ -2840,12 +2855,12 @@ class HASPmota
# special cases
static lvh_chart = lvh_chart
static def_templ_name = "pages.jsonl" # default template name
static var PAGES_JSONL = "pages.jsonl" # default template name
def init()
self.fix_lv_version()
import re
self.re_page_target = re.compile("p\\d+")
self.re_page_target = re.compilebytes("p\\d+")
# nothing to put here up to now
end
@ -2860,35 +2875,72 @@ class HASPmota
#====================================================================
# init
#
# arg1: (bool) use dark theme if `true`
# Opt1: no arguments
# load "pages.jsonl"
# Opt2:
# arg1: (string) use it as template name
#
# Opt3:
# arg1: (bool) set dark mode (deprecated)
# arg2: (string) use it as template name
#
# implicitly loads `pages.jsonl` from file-system // TODO allow to specicify file name
#====================================================================
def start(dark, templ_name)
def start(arg1, arg2)
if (self.started) return end
var templ_name
if type(arg1) == 'string'
templ_name = arg1
elif type(arg2) == 'string'
templ_name = arg2
else
templ_name = self.PAGES_JSONL # use default PAGES.JSONL
end
import path
if templ_name == nil templ_name = self.def_templ_name end
if !path.exists(templ_name)
raise "io_erorr", "file '" + templ_name + "' not found"
end
# start lv if not already started. It does no harm to call lv.start() if LVGL was already started
lv.start()
self.dark = bool(dark)
self.hres = lv.get_hor_res() # ex: 320
self.vres = lv.get_ver_res() # ex: 240
self.scr = lv.scr_act() # LVGL default screean object
try
self.r12 = lv.font_embedded("robotocondensed", 12) # TODO what if does not exist
except ..
self.r12 = lv.font_embedded("montserrat", 10) # TODO what if does not exist
end
try
self.r16 = lv.font_embedded("robotocondensed", 16) # TODO what if does not exist
except ..
self.r16 = lv.font_embedded("montserrat", 14) # TODO what if does not exist
end
try
self.r24 = lv.font_embedded("robotocondensed", 24) # TODO what if does not exist
except ..
self.r24 = lv.font_embedded("montserrat", 20) # TODO what if does not exist
end
# set the theme for HASPmota
var th2 = lv.theme_haspmota_init(0, lv.color(0xFF00FF), lv.color(0x303030), self.dark, self.r16)
var primary_color = self.lvh_root.parse_color(tasmota.webcolor(10 #-COL_BUTTON-#))
var secondary_color = self.lvh_root.parse_color(tasmota.webcolor(11 #-COL_BUTTON_HOVER-#))
var color_scr = self.lvh_root.parse_color(tasmota.webcolor(1 #-COL_BACKGROUND-#))
var color_text = self.lvh_root.parse_color(tasmota.webcolor(9 #-COL_BUTTON_TEXT-#))
var color_card = self.lvh_root.parse_color(tasmota.webcolor(2 #-COL_FORM-#))
var color_grey = self.lvh_root.parse_color(tasmota.webcolor(2 #-COL_FORM-#))
var color_reset = self.lvh_root.parse_color(tasmota.webcolor(12 #-COL_BUTTON_RESET-#))
var color_reset_hover = self.lvh_root.parse_color(tasmota.webcolor(13 #-COL_BUTTON_RESET_HOVER-#))
var color_save = self.lvh_root.parse_color(tasmota.webcolor(14 #-COL_BUTTON_SAVE-#))
var color_save_hover = self.lvh_root.parse_color(tasmota.webcolor(15 #-COL_BUTTON_SAVE_HOVER-#))
var colors = lv.color_arr([primary_color, secondary_color, color_scr, color_text, color_card, color_grey,
color_reset, color_reset_hover, color_save, color_save_hover])
var th2 = lv.theme_haspmota_init(0, colors,
self.r12, self.r16, self.r24)
self.scr.get_disp().set_theme(th2)
self.scr.set_style_bg_color(self.dark ? lv.color(0x000000) : lv.color(0xFFFFFF),0) # set background to white
# apply theme to layer_top, but keep it transparent
lv.theme_apply(lv.layer_top())
lv.layer_top().set_style_bg_opa(0,0)
@ -2896,6 +2948,7 @@ class HASPmota
self.lvh_pages = {}
# load from JSONL
self._load(templ_name)
self.started = true
end
#################################################################################
@ -2948,21 +3001,20 @@ class HASPmota
import string
import json
var f = open(templ_name,"r")
var f_content = f.read()
f.close()
var jsonl = string.split(f_content, "\n")
f = nil # allow deallocation
f_content = nil
var f = open(templ_name)
# parse each line
while size(jsonl) > 0
var jline = json.load(jsonl[0])
while f.tell() < f.size() # while we're not at the end of the file
var line = f.readline()
# if size is '1', the line is considered as empty because it's a '\n' character
if (size(line) <= 1) || (line[0] == '#') # skip empty lines and lines starting with '#'
continue
end
var jline = json.load(line)
if type(jline) == 'instance'
if tasmota.loglevel(4)
tasmota.log(f"HSP: parsing line '{jsonl[0]}'", 4)
tasmota.log(f"HSP: parsing line '{line}'", 4)
end
self.parse_page(jline) # parse page first to create any page related objects, may change self.lvh_page_cur_idx_parsing
# objects are created in the current page
@ -2972,14 +3024,13 @@ class HASPmota
self.parse_obj(jline, self.lvh_pages[self.lvh_page_cur_idx_parsing]) # then parse object within this page
else
# check if it's invalid json
if size(string.tr(jsonl[0], " \t", "")) > 0
tasmota.log(f"HSP: invalid JSON line '{jsonl[0]}'", 2)
if size(string.tr(line, " \t", "")) > 0
tasmota.log(f"HSP: invalid JSON line '{line}'", 2)
end
end
jline = nil
jsonl.remove(0)
end
jsonl = nil # make all of it freeable
f.close()
# current page is always 1 when we start
var pages_sorted = self.pages_list_sorted(nil) # nil for full list
@ -3094,6 +3145,7 @@ class HASPmota
# Returns: the target page object if changed, or `nil` if still on same page
#====================================================================
def page_show(action, anim, duration)
import re
# resolve between page numbers
# p1 is either a number or nil (stored value)
# p2 is the default value
@ -3129,7 +3181,7 @@ class HASPmota
if (to_page == cur_page.id())
to_page = to_page_resolve(int(cur_page.next), sorted_pages_list[1], sorted_pages_list)
end
elif self.re_page_target.match(action)
elif re.match(self.re_page_target, action)
# action is supposed to be `p<number>` format
to_page = to_page_resolve(int(action[1..-1]), nil #-default to nil-#, sorted_pages_list)
end

View File

@ -26,7 +26,7 @@ platform = env.PioPlatform()
from genericpath import exists
import os
import sys
from os.path import join
from os.path import join, getsize
import csv
import requests
import shutil
@ -272,6 +272,13 @@ def esp32_create_combined_bin(source, target, env):
"--flash_size",
flash_size,
]
# platformio estimates the flash space used to store the firmware.
# the estimation is inaccurate. perform a final check on the firmware
# size by comparing it against the partition size.
max_size = env.BoardConfig().get("upload.maximum_size", 1)
fw_size = getsize(firmware_name)
if (fw_size > max_size):
raise Exception(Fore.RED + "firmware binary too large: %d > %d" % (fw_size, max_size))
print(" Offset | File")
for section in sections:

View File

@ -81,7 +81,7 @@ lib_ignore = ${esp32_defaults.lib_ignore}
ccronexpr
[core32]
platform = https://github.com/tasmota/platform-espressif32/releases/download/2025.02.30/platform-espressif32.zip
platform = https://github.com/tasmota/platform-espressif32/releases/download/2025.04.30/platform-espressif32.zip
platform_packages =
build_unflags = ${esp32_defaults.build_unflags}
build_flags = ${esp32_defaults.build_flags}

View File

@ -67,6 +67,88 @@ build_flags = ${env:tasmota32_base.build_flags}
-DUSE_LVGL_OPENHASP
-DOTA_URL='""'
[env:tasmota32-WPA3_SAE]
; Arduino libs with WiFi Enterprise support
extends = env:tasmota32_base
build_flags = ${env:tasmota32_base.build_flags}
-DFIRMWARE_TASMOTA32
-DOTA_URL='""'
lib_ignore = Micro-RTSP
custom_sdkconfig = CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT=y
CONFIG_WIFI_AUTH_WPA2_ENTERPRISE=y
CONFIG_WIFI_AUTH_WPA3_ENTERPRISE=y
CONFIG_WIFI_AUTH_WPA2_WPA3_ENTERPRISE=y
CONFIG_ESP_WIFI_ENABLE_WPA3_SAE=y
CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_STA=y
[env:tasmota32s3-qio_opi_per]
; device needs >= 8MB Flash!! Hybrid compile for max. performance when using Displays
extends = env:tasmota32_base
board = esp32s3-qio_opi_120
board_build.partitions = partitions/esp32_partition_app3904k_fs3392k.csv
board_upload.flash_size = 8MB
board_upload.maximum_size = 8388608
build_unflags = ${env:tasmota32_base.build_unflags}
-Os
-ffunction-sections
build_flags = ${env:tasmota32_base.build_flags}
-Ofast
-mtext-section-literals
-DUSE_BERRY_ULP
-DFIRMWARE_LVGL
-DUSE_LVGL_OPENHASP
-DOTA_URL='""'
custom_sdkconfig = '# CONFIG_COMPILER_OPTIMIZATION_SIZE is not set'
CONFIG_COMPILER_OPTIMIZATION_PERF=y
'# CONFIG_ESP_DEBUG_INCLUDE_OCD_STUB_BINS is not set'
'# CONFIG_LWIP_PPP_SUPPORT is not set'
'# SPI_FLASH_ENABLE_ENCRYPTED_READ_WRITE is not set'
CONFIG_SPIRAM_MODE_OCT=y
CONFIG_SPIRAM_SPEED_120M=y
CONFIG_SPIRAM_IGNORE_NOTFOUND=y
'# CONFIG_SPIRAM_MEMTEST is not set'
CONFIG_LCD_RGB_ISR_IRAM_SAFE=y
CONFIG_GDMA_CTRL_FUNC_IN_IRAM=y
CONFIG_I2S_ISR_IRAM_SAFE=y
CONFIG_GDMA_ISR_IRAM_SAFE=y
CONFIG_SPIRAM_XIP_FROM_PSRAM=y
CONFIG_SPIRAM_FETCH_INSTRUCTIONS=y
CONFIG_SPIRAM_RODATA=y
CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y
CONFIG_ESP32S3_DATA_CACHE_64KB=y
CONFIG_ESP32S3_DATA_CACHE_LINE_64B=y
[env:tasmota32c2-no-NAPT]
; Hybrid compile: No IDF BT support, disabled PPP, Ethernet and NAPT
extends = env:tasmota32_base
board = esp32c2
build_flags = ${env:tasmota32_base.build_flags}
-DFIRMWARE_TASMOTA32
-DOTA_URL='"http://ota.tasmota.com/tasmota32/release/tasmota32c2.bin"'
lib_ignore = ${env:tasmota32_base.lib_ignore}
Micro-RTSP
custom_sdkconfig =
'# CONFIG_BT_ENABLED is not set'
'# CONFIG_BT_NIMBLE_ENABLED is not set'
'# CONFIG_BT_CONTROLLER_ENABLED is not set'
CONFIG_BT_CONTROLLER_DISABLED=y
'# CONFIG_LWIP_IP_FORWARD is not set'
'# CONFIG_LWIP_IPV4_NAPT is not set'
'# CONFIG_LWIP_IPV4_NAPT_PORTMAP is not set'
'# CONFIG_ETH_ENABLED is not set'
'# CONFIG_ETH_USE_SPI_ETHERNET is not set'
'# CONFIG_ETH_TRANSMIT_MUTEX is not set'
'# CONFIG_ETH_SPI_ETHERNET_DM9051 is not set'
'# CONFIG_ETH_SPI_ETHERNET_W5500 is not set'
'# CONFIG_ETH_SPI_ETHERNET_KSZ8851SNL is not set'
'# CONFIG_LWIP_PPP_SUPPORT is not set'
; disable not needed IDF managed components for Arduino libs compile
custom_component_remove = espressif/esp_hosted
espressif/esp_wifi_remote
espressif/esp_modem
; add IDF component from espressif registry for Arduino libs compile
custom_component_add = espressif/esp-dsp @ ^1.5.2
[env:tasmota32s3-opi_opi]
extends = env:tasmota32_base
board = esp32s3-opi_opi

View File

@ -0,0 +1,64 @@
#-------------------------------------------------------------
- Specialized driver for AXP2102 of M5Core2v1_1
-------------------------------------------------------------#
class AXP2102_M5Core2v1_1 : AXP2102
def init()
super(self).init()
if self.wire
# From https://github.com/m5stack/M5Unified/blob/b8cfec7fed046242da7f7b8024a4e92004a51ff7/src/utility/Power_Class.cpp#L351-L360
# for Core2 v1.1
# static constexpr std::uint8_t reg_data_array[] =
# { 0x27, 0x00 // PowerKey Hold=1sec / PowerOff=4sec
# , 0x10, 0x30 // PMU common config (internal off-discharge enable)
# , 0x12, 0x00 // BATFET disable
# , 0x68, 0x01 // Battery detection enabled.
# , 0x69, 0x13 // CHGLED setting
# , 0x99, 0x00 // DLDO1 set 0.5v (vibration motor)
# , 0x30, 0x0F // ADC enabled (for voltage measurement)
# // , 0x18, 0x0E
# };
self.write8(0x90, 0xBE) # LDOS ON/OFF control 0
self.write8(0x92, 0x00) # ALDO1 off
self.write8(0x93, 33 -5) # ALDO2 on, set to 3.3v // AXP_ILI9342C_RTS
self.write8(0x94, 0x00) # ALDO3 on, set to 0.5V // AXP_SPK_EN off
self.write8(0x95, 33 -5) # ALDO4 on, set to 3.3v // AXP_ILI9342C_POWER
self.write8(0x96, 0x00) # BLDO1 on, set to 0.5V // AXP_ILI9342C_BL off
self.write8(0x99, 0x00) # DLDO1 on, set to 0.5V // AXP_VIB off
self.write8(0x27, 0x00) # PowerKey Hold=1sec // PowerOff=4sec
self.write8(0x22, 0x06) # PWROFF_EN behavior
self.write8(0x10, 0x30) # PMU common config
self.write8(0x12, 0x00) # BATFET disabled
self.write8(0x68, 0x01) # Battery detection enabled
self.write8(0x69, 0x13) # CHGLED setting
self.write8(0x30, 0x0F) # ADC enabled (for voltage measurement)
tasmota.add_driver(self)
end
end
# set LCD backlight voltage on BLDO1
def set_lcd_voltage(voltage)
if (voltage < 2500) voltage = 2500 end
if (voltage > 3300) voltage = 3300 end
self.set_ldo_voltage(4, voltage) # 4=BLD01
end
# Speaker enable
def set_speaker_enable(state)
self.set_ldo_voltage(2, state ? 3300 : 0) # 2 = ALDO3
end
# Dimmer in percentage
def set_displaydimmer(x)
var v = tasmota.scale_uint(x, 0, 100, 2500, 3300)
self.set_lcd_voltage(v)
end
# respond to display events
def display(cmd, idx, payload, raw)
if cmd == "dim" || cmd == "power"
self.set_displaydimmer(idx)
end
end
end
return AXP2102_M5Core2v1_1()

View File

@ -333,6 +333,8 @@ const be_const_member_t lv_gpio_constants[] = {
{ "TUYA_TX", (int32_t) GPIO_TUYA_TX },
{ "TX2X_TXD_BLACK", (int32_t) GPIO_TX2X_TXD_BLACK },
{ "TXD", (int32_t) GPIO_TXD },
{ "V9240_RX", (int32_t) GPIO_V9240_RX },
{ "V9240_TX", (int32_t) GPIO_V9240_TX },
{ "VINDRIKTNING_RX", (int32_t) GPIO_VINDRIKTNING_RX },
{ "VL53LXX_XSHUT1", (int32_t) GPIO_VL53LXX_XSHUT1 },
{ "WE517_RX", (int32_t) GPIO_WE517_RX },

Some files were not shown because too many files have changed in this diff Show More