mirror of
https://github.com/arendst/Tasmota.git
synced 2025-04-19 20:37:20 +00:00
Compare commits
9 Commits
v14.6.0
...
developmen
Author | SHA1 | Date | |
---|---|---|---|
![]() |
015fa1da89 | ||
![]() |
a11e269ca0 | ||
![]() |
2831bbfd18 | ||
![]() |
92b3f7d37c | ||
![]() |
a2d1915692 | ||
![]() |
082170374c | ||
![]() |
c2628c95f3 | ||
![]() |
2bc5f682b0 | ||
![]() |
cea46bb660 |
29
CHANGELOG.md
29
CHANGELOG.md
@ -3,7 +3,29 @@ All notable changes to this project will be documented in this file.
|
||||
|
||||
## [Unreleased] - Development
|
||||
|
||||
## [14.5.0.3]
|
||||
## [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)
|
||||
@ -29,9 +51,6 @@ All notable changes to this project will be documented in this file.
|
||||
- TLS increase timeout and fix crash (#23249)
|
||||
- Berry `readline` when a line is exactly 98 characters (#23276)
|
||||
|
||||
### Removed
|
||||
|
||||
|
||||
## [14.5.0.2] 20250325
|
||||
### Added
|
||||
- Berry load `.tapp` files in `/.extensions/` then in `/` (#23113)
|
||||
@ -77,8 +96,6 @@ All notable changes to this project will be documented in this file.
|
||||
### Fixed
|
||||
- Too many zeros in RCSwitch received data regression from v14.4.1.4 (#23050)
|
||||
|
||||
## [Released]
|
||||
|
||||
## [14.5.0] 20250219
|
||||
- Release Ruth
|
||||
|
||||
|
@ -18,7 +18,7 @@ See [CHANGELOG.md](https://github.com/arendst/Tasmota/blob/development/CHANGELOG
|
||||
|
||||
## Development
|
||||
|
||||
[](https://github.com/arendst/Tasmota)
|
||||
[](https://github.com/arendst/Tasmota)
|
||||
[](http://ota.tasmota.com/tasmota/)
|
||||
[](https://github.com/arendst/Tasmota/actions?query=workflow%3A%22Tasmota+CI%22)
|
||||
[](https://github.com/arendst/Tasmota/actions?query=workflow%3A%22Tasmota+ESP32+CI%22)
|
||||
|
@ -31,7 +31,7 @@ Firmware binaries can be downloaded from http://ota.tasmota.com/tasmota/release/
|
||||
|
||||
## Development
|
||||
|
||||
[](https://github.com/arendst/Tasmota)
|
||||
[](https://github.com/arendst/Tasmota)
|
||||
[](http://ota.tasmota.com/tasmota/)
|
||||
[](https://github.com/arendst/Tasmota/actions/workflows/build_all_the_things.yml)
|
||||
[](https://github.com/arendst/Tasmota/actions/workflows/Tasmota_build_devel.yml)
|
||||
|
@ -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.
|
||||
@ -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,58 +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.3
|
||||
## Changelog v14.6.0.1
|
||||
### Added
|
||||
- Filesystem command ``UfsList[2]``
|
||||
- Extend command `GPIO` with different display options and allowing updating of module GPIO's in one go
|
||||
- Support Vango Technologies V924x ultralow power, single-phase, power measurement [#23127](https://github.com/arendst/Tasmota/issues/23127)
|
||||
- Support for HLK-LD2402 24GHz smart wave motion sensor [#23133](https://github.com/arendst/Tasmota/issues/23133)
|
||||
- Support for Telnet server using command `Telnet <0|1|port>[,<IP filter>]` if enabled with `#define USE_TELNET`
|
||||
- Support for XMODEM over serial and telnet if enabled with `#define USE_XYZMODEM`
|
||||
- PZEM_AC device address in JSON and GUI [#23268](https://github.com/arendst/Tasmota/issues/23268)
|
||||
- Allow acl in mqtt when client certificate is in use with `#define USE_MQTT_CLIENT_CERT` [#22998](https://github.com/arendst/Tasmota/issues/22998)
|
||||
- AlpineJS 2.8.2 - optional for now [#23259](https://github.com/arendst/Tasmota/issues/23259)
|
||||
- ESP32 show network interface priority in `Status 5` debug logging [#23302](https://github.com/arendst/Tasmota/issues/23302)
|
||||
- Berry experimental driver for AXP2101 for M5Core2v1.1 [#23039](https://github.com/arendst/Tasmota/issues/23039)
|
||||
- Berry `tasmota.when_network_up()` and simplified Matter using it [#23057](https://github.com/arendst/Tasmota/issues/23057)
|
||||
- Berry `introspect.solidified()` to know if a Berry object is solidified or in RAM [#23063](https://github.com/arendst/Tasmota/issues/23063)
|
||||
- Berry `global.undef()` to undefine a global variable [#23073](https://github.com/arendst/Tasmota/issues/23073)
|
||||
- Berry load `.tapp` files in `/.extensions/` then in `/` [#23113](https://github.com/arendst/Tasmota/issues/23113)
|
||||
- Berry `re.dump()` [#23162](https://github.com/arendst/Tasmota/issues/23162)
|
||||
- Berry `bytes.add()` now accepts 3-bytes values [#23200](https://github.com/arendst/Tasmota/issues/23200)
|
||||
- Berry expose `esp_http_server` for websockets [#23206](https://github.com/arendst/Tasmota/issues/23206)
|
||||
- Matter prepare for ICD cluster [#23158](https://github.com/arendst/Tasmota/issues/23158)
|
||||
- LVGL experimental mirroring of display on Web UI [#23041](https://github.com/arendst/Tasmota/issues/23041)
|
||||
- HASPmota autostart when `pages.jsonl` exists [#23181](https://github.com/arendst/Tasmota/issues/23181)
|
||||
- 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
|
||||
- Berry remove `Leds.create_matrix` from the standard library waiting for reimplementation [#23114](https://github.com/arendst/Tasmota/issues/23114)
|
||||
- HASPmota added `y2_min` and `y2_max` to control the second series of `chart` [#23287](https://github.com/arendst/Tasmota/issues/23287)
|
||||
- HASPmota default theme is now Tasmota-style [#23288](https://github.com/arendst/Tasmota/issues/23288)
|
||||
|
||||
### Changed
|
||||
- ESP32 Platform from 2025.02.30 to 2025.04.30, Framework (Arduino Core) from v3.1.1.250203 to v3.1.3.250411 and IDF from v5.3.2.250120 to 5.3.2.250403 [#23280](https://github.com/arendst/Tasmota/issues/23280)
|
||||
- Output of commands `GPIO` and `GPIOs` swapped
|
||||
- Smoothen light gamma curve when using `Fade` [#23230](https://github.com/arendst/Tasmota/issues/23230)
|
||||
- RCSwitch `RCSWITCH_SEPARATION_LIMIT` from 4100 to 3600
|
||||
- GPIOViewer from v1.6.1 to v1.6.2 (No functional change)
|
||||
- HLK-LD2402 updates for firmware 3.3.5+ [#23281](https://github.com/arendst/Tasmota/issues/23281)
|
||||
- ESP8266 enable FTP for >= 4MB variants [#23120](https://github.com/arendst/Tasmota/issues/23120)
|
||||
- ESP32 enable webcam version 2 [#18732](https://github.com/arendst/Tasmota/issues/18732)
|
||||
- Berry update flasher for Sonoff ZBBridge Pro [#23136](https://github.com/arendst/Tasmota/issues/23136)
|
||||
- Berry `re` now accepts `bytes()` as precompiled patterns, added `re.compilebytes()` [#23149](https://github.com/arendst/Tasmota/issues/23149)
|
||||
- LVGL, prepare for HASPmota theme, change: no-grow when clicked, DPI set to 160 [#23040](https://github.com/arendst/Tasmota/issues/23040)
|
||||
- LVGL Mirroring add checkbox to enable/disable the feature (in the iterim for a better solution) [#23047](https://github.com/arendst/Tasmota/issues/23047)
|
||||
- Leds Panel add checkbox to enable/disable the feature (in the iterim for a better solution) [#23048](https://github.com/arendst/Tasmota/issues/23048)
|
||||
|
||||
### Fixed
|
||||
- Too many zeros in RCSwitch received data regression from v14.4.1.4 [#23050](https://github.com/arendst/Tasmota/issues/23050)
|
||||
- INA226 driver fixes [#23197](https://github.com/arendst/Tasmota/issues/23197)
|
||||
- TLS increase timeout and fix crash [#23249](https://github.com/arendst/Tasmota/issues/23249)
|
||||
- ESP32 receive incomplete serial data over 128 bytes [#23156](https://github.com/arendst/Tasmota/issues/23156)
|
||||
- ESP32 intermittent exception on WiFi AP cannot be reached [#23115](https://github.com/arendst/Tasmota/issues/23115)
|
||||
- ESP32-C3 WiFi sleep [#23096](https://github.com/arendst/Tasmota/issues/23096)
|
||||
- Berry prevent `import` from hiding a solidified class [#23112](https://github.com/arendst/Tasmota/issues/23112)
|
||||
- Berry `readline` when a line is exactly 98 characters [#23276](https://github.com/arendst/Tasmota/issues/23276)
|
||||
- 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
|
||||
|
128
lib/default/base64-1.1.1/src/base64.cpp
Normal file
128
lib/default/base64-1.1.1/src/base64.cpp
Normal 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;
|
||||
}
|
@ -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
|
||||
|
@ -806,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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -354,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)
|
||||
|
@ -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)
|
||||
|
@ -272,6 +272,7 @@
|
||||
// Commands tasmota.ino
|
||||
#define D_CMND_BACKLOG "Backlog"
|
||||
#define D_CMND_JSON "Json"
|
||||
#define D_CMND_JSON_PP "JsonPP"
|
||||
#define D_CMND_DELAY "Delay"
|
||||
#define D_CMND_NODELAY "NoDelay"
|
||||
#define D_CMND_STATUS "Status"
|
||||
|
@ -16,9 +16,10 @@ class TASCONSOLE {
|
||||
virtual void begin(uint32_t) = 0;
|
||||
virtual void flush() = 0;
|
||||
virtual size_t println() = 0;
|
||||
virtual size_t print(char *) = 0;
|
||||
virtual size_t printf(const char*, char *, const char*&, const char*&, const char*&) = 0;
|
||||
virtual size_t printf(char *) = 0;
|
||||
virtual size_t println(const char*) = 0;
|
||||
virtual size_t print(char*) = 0;
|
||||
virtual size_t printf(const char*, char*, const char*&, const char*&, const char*&) = 0;
|
||||
virtual size_t printf(char*) = 0;
|
||||
virtual size_t read() = 0;
|
||||
virtual size_t write(uint8_t) = 0;
|
||||
virtual size_t write(const uint8_t *buf, size_t size) = 0;
|
||||
@ -49,7 +50,11 @@ public:
|
||||
return object->println();
|
||||
}
|
||||
|
||||
size_t print(char * string) {
|
||||
size_t println(const char *string) {
|
||||
return object->println(string);
|
||||
}
|
||||
|
||||
size_t print(char *string) {
|
||||
return object->print(string);
|
||||
}
|
||||
|
||||
@ -96,10 +101,15 @@ public:
|
||||
object.flush();
|
||||
}
|
||||
|
||||
size_t println() override {
|
||||
size_t println() override {
|
||||
return object.println();
|
||||
}
|
||||
size_t print(char * string) override {
|
||||
|
||||
size_t println(const char *string) override {
|
||||
return object.println(string);
|
||||
}
|
||||
|
||||
size_t print(char *string) override {
|
||||
return object.print(string);
|
||||
}
|
||||
|
||||
|
@ -252,9 +252,7 @@ typedef union {
|
||||
uint32_t spare13 : 1; // bit 13
|
||||
uint32_t spare14 : 1; // bit 14
|
||||
uint32_t spare15 : 1; // bit 15
|
||||
uint32_t spare16 : 1; // bit 16
|
||||
uint32_t spare17 : 1; // bit 17
|
||||
uint32_t spare18 : 1; // bit 18
|
||||
uint32_t json_pretty_print : 3; // bit 16.18 (v14.6.0.1) - JSON pretty print log data no or indent
|
||||
uint32_t dali_group_sliders : 5; // bit 19.23 (v14.3.0.3) - (DALI) Number of group sliders 0 to 16
|
||||
uint32_t FTP_Mode : 2; // bit 24/25
|
||||
uint32_t tariff_forced : 2; // bit 26/27 (v12.4.0.2) - Energy forced tariff : 0=tariff change on time, 1|2=tariff forced
|
||||
|
@ -22,6 +22,6 @@
|
||||
|
||||
#define TASMOTA_SHA_SHORT // Filled by Github sed
|
||||
|
||||
const uint32_t TASMOTA_VERSION = 0x0E050003; // 14.5.0.3
|
||||
const uint32_t TASMOTA_VERSION = 0x0E060001; // 14.6.0.1
|
||||
|
||||
#endif // _TASMOTA_VERSION_H_
|
||||
|
@ -28,7 +28,7 @@
|
||||
* Use online command StateText to translate ON, OFF, HOLD and TOGGLE.
|
||||
* Use online command Prefix to translate cmnd, stat and tele.
|
||||
*
|
||||
* Updated until v9.4.0.1 - Last update 12.03.2025
|
||||
* Updated until v9.4.0.1 - Last update 17.04.2025
|
||||
\*********************************************************************/
|
||||
|
||||
#define LANGUAGE_MODULE_NAME // Enable to display "Module Generic" (ie Spanish), Disable to display "Generic Module" (ie English)
|
||||
@ -52,7 +52,7 @@
|
||||
|
||||
// Common
|
||||
#define D_ABSOLUTE_HUMIDITY "Umidità ass"
|
||||
#define D_ADDRESS "Address"
|
||||
#define D_ADDRESS "Indirizzo"
|
||||
#define D_ADMIN "Admin"
|
||||
#define D_AIR_QUALITY "Qualità dell'aria"
|
||||
#define D_AP "AP" // Access Point
|
||||
|
@ -2611,6 +2611,95 @@ bool GetLog(uint32_t req_loglevel, uint32_t* index_p, char** entry_pp, size_t* l
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LogDataJsonPrettyPrint(const char *log_line, uint32_t log_data_len, std::function<void(const char*, uint32_t)> println) {
|
||||
// log_line:
|
||||
// 14:49:36.123 MQTT: stat/wemos5/RESULT = {"POWER":"OFF"}
|
||||
// 14:30:16.749-172/38 MQT: tele/atomlite3/INFO3 = {"Info3":{"RestartReason":"Vbat power on reset","BootCount":74}}
|
||||
|
||||
if (!Settings->mbflag2.json_pretty_print) { return false; } // [JsonPP] Number of indents
|
||||
char *bch = (char*)memchr(log_line, '{', log_data_len);
|
||||
if (!bch) { return false; } // No JSON data
|
||||
|
||||
uint32_t pos_brace = bch - log_line;
|
||||
uint32_t cnt_brace = 0; // {}
|
||||
uint32_t len_mxtime = strchr(log_line, ' ') - log_line +2;
|
||||
uint32_t pos_value_pair = pos_brace;
|
||||
uint32_t cnt_bracket = 0; // []
|
||||
uint32_t cnt_Indent = 0; // indent
|
||||
bool quotes = false; // ""
|
||||
bool bracket_comma = false;
|
||||
bool pls_print = false;
|
||||
for (uint32_t i = pos_brace; i < log_data_len; i++) {
|
||||
char curchar = log_line[i];
|
||||
char nxtchar = log_line[i +1];
|
||||
cnt_Indent = cnt_brace + cnt_bracket;
|
||||
if (curchar == '{') {
|
||||
cnt_brace++;
|
||||
pls_print = true;
|
||||
}
|
||||
else if (cnt_brace) {
|
||||
if (nxtchar == '}') {
|
||||
pls_print = true;
|
||||
}
|
||||
if (curchar == '}') {
|
||||
cnt_brace--;
|
||||
if (cnt_brace) {
|
||||
if (nxtchar != ',') {
|
||||
pls_print = true;
|
||||
cnt_Indent = cnt_brace + cnt_bracket;
|
||||
}
|
||||
} else {
|
||||
pls_print = true;
|
||||
cnt_Indent = 0;
|
||||
}
|
||||
}
|
||||
else if (curchar == '[') {
|
||||
cnt_bracket++;
|
||||
if (nxtchar == '[') {
|
||||
pls_print = true;
|
||||
}
|
||||
}
|
||||
else if (curchar == ']') {
|
||||
cnt_bracket--;
|
||||
if (nxtchar == ',') {
|
||||
bracket_comma = true;
|
||||
}
|
||||
else {
|
||||
pls_print = true;
|
||||
if ((nxtchar == ']') || (nxtchar == '}')) {
|
||||
cnt_Indent = cnt_brace + cnt_bracket;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (curchar == '"') {
|
||||
quotes ^= 1;
|
||||
}
|
||||
else if (curchar == ',') {
|
||||
if (!quotes && (!cnt_bracket || bracket_comma)) {
|
||||
bracket_comma = false;
|
||||
pls_print = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pls_print) {
|
||||
pls_print = false;
|
||||
uint32_t len_id = (pos_brace == i) ? pos_brace +1 : len_mxtime;
|
||||
uint32_t len_indent = cnt_Indent * Settings->mbflag2.json_pretty_print;
|
||||
uint32_t len_value_pair = (i - pos_value_pair) +1;
|
||||
uint32_t len_full = len_id + len_indent + len_value_pair +1;
|
||||
|
||||
char line[len_full]; // Known max value pair size is 152
|
||||
strlcpy(line, log_line, len_id); // Repeat mxtime
|
||||
sprintf(line, "%s%*s", line, len_indent, ""); // Add space indent
|
||||
strncat(line, log_line + pos_value_pair, len_value_pair);
|
||||
println(line, strlen(line)); // Callback for output
|
||||
pos_value_pair = i +1;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t HighestLogLevel(void) {
|
||||
uint32_t highest_loglevel = TasmotaGlobal.seriallog_level;
|
||||
if (Settings->seriallog_level > highest_loglevel) { highest_loglevel = Settings->seriallog_level; }
|
||||
@ -2660,7 +2749,9 @@ void AddLogData(uint32_t loglevel, const char* log_data, const char* log_data_pa
|
||||
|
||||
if ((loglevel <= TasmotaGlobal.seriallog_level) &&
|
||||
(TasmotaGlobal.masterlog_level <= TasmotaGlobal.seriallog_level)) {
|
||||
TasConsole.printf("%s%s%s%s\r\n", mxtime, log_data, log_data_payload, log_data_retained);
|
||||
if (!Settings->mbflag2.json_pretty_print || !strchr(log_data_payload, '{')) {
|
||||
TasConsole.printf("%s%s%s%s\r\n", mxtime, log_data, log_data_payload, log_data_retained);
|
||||
}
|
||||
}
|
||||
|
||||
if (!TasmotaGlobal.log_buffer) { return; } // Leave now if there is no buffer available
|
||||
@ -2707,6 +2798,14 @@ void AddLogData(uint32_t loglevel, const char* log_data, const char* log_data_pa
|
||||
|
||||
// These calls fail to show initial logging
|
||||
log_line += 2; // Skip log_buffer_pointer and loglevel
|
||||
// 14:49:36.123 MQTT: stat/wemos5/RESULT = {"POWER":"OFF"}
|
||||
// 14:30:16.749-172/38 MQT: tele/atomlite3/INFO3 = {"Info3":{"RestartReason":"Vbat power on reset","BootCount":74}}
|
||||
|
||||
if ((loglevel <= TasmotaGlobal.seriallog_level) &&
|
||||
(TasmotaGlobal.masterlog_level <= TasmotaGlobal.seriallog_level)) {
|
||||
LogDataJsonPrettyPrint(log_line, log_data_len, TasConsoleLDJsonPPCb);
|
||||
}
|
||||
|
||||
#ifdef USE_SERIAL_BRIDGE
|
||||
if (loglevel <= TasmotaGlobal.seriallog_level) {
|
||||
SerialBridgeWrite(log_line, log_data_len);
|
||||
@ -2723,6 +2822,10 @@ void AddLogData(uint32_t loglevel, const char* log_data, const char* log_data_pa
|
||||
}
|
||||
}
|
||||
|
||||
void TasConsoleLDJsonPPCb(const char* line, uint32_t len) {
|
||||
TasConsole.println(line);
|
||||
}
|
||||
|
||||
void AddLog(uint32_t loglevel, PGM_P formatP, ...) {
|
||||
#ifdef ESP32
|
||||
if (xPortInIsrContext()) {
|
||||
|
@ -29,18 +29,18 @@ const char kTasmotaCommands[] PROGMEM = "|" // No prefix
|
||||
D_CMND_VOLTAGE_RESOLUTION "|" D_CMND_FREQUENCY_RESOLUTION "|" D_CMND_CURRENT_RESOLUTION "|" D_CMND_ENERGY_RESOLUTION "|" D_CMND_WEIGHT_RESOLUTION "|"
|
||||
D_CMND_MODULE "|" D_CMND_MODULES "|" D_CMND_GPIO "|" D_CMND_GPIOREAD "|" D_CMND_GPIOS "|" D_CMND_TEMPLATE "|" D_CMND_PWM "|" D_CMND_PWMFREQUENCY "|" D_CMND_PWMRANGE "|"
|
||||
D_CMND_BUTTONDEBOUNCE "|" D_CMND_SWITCHDEBOUNCE "|" D_CMND_SYSLOG "|" D_CMND_LOGHOST "|" D_CMND_LOGPORT "|"
|
||||
#ifdef USE_UFILESYS
|
||||
D_CMND_FILELOG "|"
|
||||
#endif // USE_UFILESYS
|
||||
D_CMND_SERIALBUFFER "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE "|" D_CMND_SERIALCONFIG "|" D_CMND_SERIALDELIMITER "|"
|
||||
D_CMND_IPADDRESS "|" D_CMND_NTPSERVER "|" D_CMND_AP "|" D_CMND_SSID "|" D_CMND_PASSWORD "|" D_CMND_HOSTNAME "|" D_CMND_WIFICONFIG "|" D_CMND_WIFI "|" D_CMND_DNSTIMEOUT "|"
|
||||
D_CMND_DEVICENAME "|" D_CMND_FN "|" D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" D_CMND_INTERLOCK "|" D_CMND_TELEPERIOD "|" D_CMND_RESET "|" D_CMND_TIME "|" D_CMND_TIMEZONE "|" D_CMND_TIMESTD "|"
|
||||
D_CMND_TIMEDST "|" D_CMND_ALTITUDE "|" D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" D_CMND_LEDMASK "|" D_CMND_LEDPWM_ON "|" D_CMND_LEDPWM_OFF "|" D_CMND_LEDPWM_MODE "|"
|
||||
D_CMND_WIFIPOWER "|" D_CMND_TEMPOFFSET "|" D_CMND_HUMOFFSET "|" D_CMND_SPEEDUNIT "|" D_CMND_GLOBAL_TEMP "|" D_CMND_GLOBAL_HUM"|" D_CMND_GLOBAL_PRESS "|" D_CMND_SWITCHTEXT "|" D_CMND_WIFISCAN "|" D_CMND_WIFITEST "|"
|
||||
D_CMND_ZIGBEE_BATTPERCENT "|"
|
||||
D_CMND_DEVICENAME "|" D_CMND_FN "|" D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" D_CMND_INTERLOCK "|" D_CMND_TELEPERIOD "|" D_CMND_RESET "|"
|
||||
D_CMND_TIME "|" D_CMND_TIMEZONE "|" D_CMND_TIMESTD "|" D_CMND_TIMEDST "|" D_CMND_ALTITUDE "|"
|
||||
D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" D_CMND_LEDMASK "|" D_CMND_LEDPWM_ON "|" D_CMND_LEDPWM_OFF "|" D_CMND_LEDPWM_MODE "|"
|
||||
D_CMND_WIFIPOWER "|" D_CMND_TEMPOFFSET "|" D_CMND_HUMOFFSET "|" D_CMND_SPEEDUNIT "|" D_CMND_GLOBAL_TEMP "|" D_CMND_GLOBAL_HUM"|" D_CMND_GLOBAL_PRESS "|" D_CMND_SWITCHTEXT "|"
|
||||
D_CMND_WIFISCAN "|" D_CMND_WIFITEST "|" D_CMND_ZIGBEE_BATTPERCENT "|"
|
||||
|
||||
#ifdef USE_I2C
|
||||
D_CMND_I2CSCAN "|" D_CMND_I2CDRIVER "|"
|
||||
#endif
|
||||
|
||||
#ifdef USE_DEVICE_GROUPS
|
||||
D_CMND_DEVGROUP_NAME "|"
|
||||
#ifdef USE_DEVICE_GROUPS_SEND
|
||||
@ -48,14 +48,20 @@ const char kTasmotaCommands[] PROGMEM = "|" // No prefix
|
||||
#endif // USE_DEVICE_GROUPS_SEND
|
||||
D_CMND_DEVGROUP_SHARE "|" D_CMND_DEVGROUPSTATUS "|" D_CMND_DEVGROUP_TIE "|"
|
||||
#endif // USE_DEVICE_GROUPS
|
||||
D_CMND_SETSENSOR "|" D_CMND_SENSOR "|" D_CMND_DRIVER "|" D_CMND_JSON
|
||||
|
||||
#ifdef USE_UFILESYS
|
||||
D_CMND_FILELOG "|"
|
||||
#endif // USE_UFILESYS
|
||||
|
||||
#ifdef ESP32
|
||||
"|Info|"
|
||||
"|Info|"
|
||||
#if defined(SOC_TOUCH_VERSION_1) || defined(SOC_TOUCH_VERSION_2)
|
||||
D_CMND_TOUCH_CAL "|" D_CMND_TOUCH_THRES "|"
|
||||
#endif // ESP32 SOC_TOUCH_VERSION_1 or SOC_TOUCH_VERSION_2
|
||||
D_CMND_CPU_FREQUENCY
|
||||
#endif // ESP32
|
||||
|
||||
D_CMND_SETSENSOR "|" D_CMND_SENSOR "|" D_CMND_DRIVER "|" D_CMND_JSON "|" D_CMND_JSON_PP
|
||||
#endif //FIRMWARE_MINIMAL
|
||||
;
|
||||
|
||||
@ -72,18 +78,18 @@ void (* const TasmotaCommand[])(void) PROGMEM = {
|
||||
&CmndVoltageResolution, &CmndFrequencyResolution, &CmndCurrentResolution, &CmndEnergyResolution, &CmndWeightResolution,
|
||||
&CmndModule, &CmndModules, &CmndGpio, &CmndGpioRead, &CmndGpios, &CmndTemplate, &CmndPwm, &CmndPwmfrequency, &CmndPwmrange,
|
||||
&CmndButtonDebounce, &CmndSwitchDebounce, &CmndSyslog, &CmndLoghost, &CmndLogport,
|
||||
#ifdef USE_UFILESYS
|
||||
&CmndFilelog,
|
||||
#endif // USE_UFILESYS
|
||||
&CmndSerialBuffer, &CmndSerialSend, &CmndBaudrate, &CmndSerialConfig, &CmndSerialDelimiter,
|
||||
&CmndIpAddress, &CmndNtpServer, &CmndAp, &CmndSsid, &CmndPassword, &CmndHostname, &CmndWifiConfig, &CmndWifi, &CmndDnsTimeout,
|
||||
&CmndDevicename, &CmndFriendlyname, &CmndFriendlyname, &CmndSwitchMode, &CmndInterlock, &CmndTeleperiod, &CmndReset, &CmndTime, &CmndTimezone, &CmndTimeStd,
|
||||
&CmndTimeDst, &CmndAltitude, &CmndLedPower, &CmndLedState, &CmndLedMask, &CmndLedPwmOn, &CmndLedPwmOff, &CmndLedPwmMode,
|
||||
&CmndWifiPower, &CmndTempOffset, &CmndHumOffset, &CmndSpeedUnit, &CmndGlobalTemp, &CmndGlobalHum, &CmndGlobalPress, &CmndSwitchText, &CmndWifiScan, &CmndWifiTest,
|
||||
&CmndBatteryPercent,
|
||||
&CmndDevicename, &CmndFriendlyname, &CmndFriendlyname, &CmndSwitchMode, &CmndInterlock, &CmndTeleperiod, &CmndReset,
|
||||
&CmndTime, &CmndTimezone, &CmndTimeStd, &CmndTimeDst, &CmndAltitude,
|
||||
&CmndLedPower, &CmndLedState, &CmndLedMask, &CmndLedPwmOn, &CmndLedPwmOff, &CmndLedPwmMode,
|
||||
&CmndWifiPower, &CmndTempOffset, &CmndHumOffset, &CmndSpeedUnit, &CmndGlobalTemp, &CmndGlobalHum, &CmndGlobalPress, &CmndSwitchText,
|
||||
&CmndWifiScan, &CmndWifiTest, &CmndBatteryPercent,
|
||||
|
||||
#ifdef USE_I2C
|
||||
&CmndI2cScan, &CmndI2cDriver,
|
||||
#endif
|
||||
|
||||
#ifdef USE_DEVICE_GROUPS
|
||||
&CmndDevGroupName,
|
||||
#ifdef USE_DEVICE_GROUPS_SEND
|
||||
@ -91,14 +97,20 @@ void (* const TasmotaCommand[])(void) PROGMEM = {
|
||||
#endif // USE_DEVICE_GROUPS_SEND
|
||||
&CmndDevGroupShare, &CmndDevGroupStatus, &CmndDevGroupTie,
|
||||
#endif // USE_DEVICE_GROUPS
|
||||
&CmndSetSensor, &CmndSensor, &CmndDriver, &CmndJson
|
||||
|
||||
#ifdef USE_UFILESYS
|
||||
&CmndFilelog,
|
||||
#endif // USE_UFILESYS
|
||||
|
||||
#ifdef ESP32
|
||||
, &CmndInfo,
|
||||
&CmndInfo,
|
||||
#if defined(SOC_TOUCH_VERSION_1) || defined(SOC_TOUCH_VERSION_2)
|
||||
&CmndTouchCal, &CmndTouchThres,
|
||||
#endif // ESP32 SOC_TOUCH_VERSION_1 or SOC_TOUCH_VERSION_2
|
||||
&CmndCpuFrequency
|
||||
&CmndCpuFrequency,
|
||||
#endif // ESP32
|
||||
|
||||
&CmndSetSensor, &CmndSensor, &CmndDriver, &CmndJson, &CmndJsonPP
|
||||
#endif //FIRMWARE_MINIMAL
|
||||
};
|
||||
|
||||
@ -652,6 +664,35 @@ void CmndDelay(void) {
|
||||
ResponseCmndNumber(bl_delay);
|
||||
}
|
||||
|
||||
void CmndJsonPP(void) {
|
||||
// JsonPP 0 - Disable JSON Pretty Print
|
||||
// JsonPP 1..7 - Enable JSON Pretty Print with 1..7 indent spaces
|
||||
// JsonPP <command> - If not enabled, enable JSON PP with 1 indent, execute command and restore JsonPP
|
||||
// JsonPP Backlog <command>;... - If not enabled, enable JSON PP with 1 indent, execute command and restore JsonPP
|
||||
if ((XdrvMailbox.payload >= 0) && (XdrvMailbox.payload <= 7)) {
|
||||
Settings->mbflag2.json_pretty_print = XdrvMailbox.payload;
|
||||
}
|
||||
else if (XdrvMailbox.data_len) {
|
||||
uint32_t last_json_pretty_print = Settings->mbflag2.json_pretty_print;
|
||||
if (0 == Settings->mbflag2.json_pretty_print) {
|
||||
Settings->mbflag2.json_pretty_print = 1; // Default 1 indent if not set
|
||||
}
|
||||
bool backlog = (strchr(XdrvMailbox.data, ';') != nullptr);
|
||||
String cmnds = XdrvMailbox.data;
|
||||
if (!last_json_pretty_print && backlog) {
|
||||
cmnds += ";_JsonPP ";
|
||||
cmnds += last_json_pretty_print; // Restore JsonPP after execution of backlog commands
|
||||
}
|
||||
ExecuteCommand((char*)cmnds.c_str(), SRC_IGNORE);
|
||||
if (!last_json_pretty_print && !backlog) { // Restore JsonPP after execution of single command
|
||||
Settings->mbflag2.json_pretty_print = last_json_pretty_print;
|
||||
}
|
||||
ResponseClear();
|
||||
return;
|
||||
}
|
||||
ResponseCmndNumber(Settings->mbflag2.json_pretty_print);
|
||||
}
|
||||
|
||||
void CmndPower(void)
|
||||
{
|
||||
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= TasmotaGlobal.devices_present)) {
|
||||
|
@ -500,6 +500,7 @@ struct WEB {
|
||||
bool upload_services_stopped = false;
|
||||
bool reset_web_log_flag = false; // Reset web console log
|
||||
bool initial_config = false;
|
||||
bool cflg;
|
||||
} Web;
|
||||
|
||||
/*********************************************************************************************/
|
||||
@ -3737,18 +3738,24 @@ void HandleConsoleRefresh(void) {
|
||||
index = 0;
|
||||
Web.reset_web_log_flag = true;
|
||||
}
|
||||
bool cflg = (index);
|
||||
Web.cflg = (index);
|
||||
char* line;
|
||||
size_t len;
|
||||
while (GetLog(Settings->weblog_level, &index, &line, &len)) {
|
||||
if (cflg) { WSContentSend_P(PSTR("\n")); }
|
||||
WSContentSend(line, len -1);
|
||||
cflg = true;
|
||||
if (!LogDataJsonPrettyPrint(line, len -1, WSContentSendLDJsonPPCb)) {
|
||||
WSContentSendLDJsonPPCb(line, len -1);
|
||||
}
|
||||
}
|
||||
WSContentSend_P(PSTR("}1"));
|
||||
WSContentEnd();
|
||||
}
|
||||
|
||||
void WSContentSendLDJsonPPCb(const char* line, uint32_t len) {
|
||||
if (Web.cflg) { WSContentSend_P(PSTR("\n")); }
|
||||
WSContentSend(line, len);
|
||||
Web.cflg = true;
|
||||
}
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
void HandleNotFound(void) {
|
||||
|
@ -65,8 +65,9 @@ enum XTrim1aModes { XYZT_NONE, XYZT_TRIM, XYZT_AUTO };
|
||||
enum XReceiveModes { XYZD_NONE, XYZD_SOH, XYZD_BLK1, XYZD_BLK2, XYZD_DATA };
|
||||
|
||||
enum XYZFileSteps { XYZM_IDLE,
|
||||
XYZM_SEND, XYZM_SEOT, XYZM_ACKT, XYZM_COMPLETE, XYZM_ERROR, XYZM_DONE,
|
||||
XYZM_RECEIVE, XYZM_RCV_START, XYZM_RCV_EOT };
|
||||
XYZM_SEND, XYZM_SND_ACK,
|
||||
XYZM_RECEIVE, XYZM_RCV_START, XYZM_RCV_EOT,
|
||||
XYZM_ERROR, XYZM_DONE };
|
||||
|
||||
enum XReceiveStates { XYZS_OK, XYZS_TIMEOUT, XYZS_EOT, XYZS_CAN, XYZS_OTHER, XYZS_CHECKSUM, XYZS_PACKET, XYZS_FILE };
|
||||
|
||||
@ -712,8 +713,7 @@ void XModemSendStart(void) {
|
||||
XYZFile.step = XYZM_SEND;
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("XMD: Send started"));
|
||||
} else {
|
||||
XYZFile.step = XYZM_SEOT;
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("XMD: Send aborted"));
|
||||
XYZModemInit();
|
||||
}
|
||||
}
|
||||
|
||||
@ -738,8 +738,8 @@ bool XYZModemLoop(void) {
|
||||
// *** Send
|
||||
case XYZM_SEND: { // *** Handle file send using XModem - upload
|
||||
if (XYZModemFileAvailable()) {
|
||||
if (XYZFile.byte_counter && !(XYZFile.byte_counter % 10240)) { // Show progress every 10kB
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("XMD: Progress %d kB"), XYZFile.byte_counter / 1024);
|
||||
if (XYZFile.byte_counter && !(XYZFile.byte_counter % 10240)) { // Show progress every 10KB
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("XMD: Progress %d KB"), XYZFile.byte_counter / 1024);
|
||||
}
|
||||
if (!XYZModemSend(XYZModem.packet_no)) {
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("XMD: Packet %d send failed"), XYZModem.packet_no);
|
||||
@ -748,21 +748,16 @@ bool XYZModemLoop(void) {
|
||||
}
|
||||
XYZModem.packet_no++;
|
||||
} else {
|
||||
XYZFile.step = XYZM_SEOT;
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("XMD: Send %d bytes"), XYZFile.size);
|
||||
// Once the last block is ACKed by the target, the transfer should be finalized by an
|
||||
// EOT (ASCII 0x04) packet from the source. This packet is confirmed via XModem ACK
|
||||
// from the target.
|
||||
XYZModemWrite(XYZM_EOT); // *** Send EOT
|
||||
XYZModem.timeout = millis() + (30 * 1000); // Allow 30 seconds to receive EOT ACK
|
||||
XYZFile.step = XYZM_SND_ACK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case XYZM_SEOT: { // *** Send EOT and wait for ACK
|
||||
// Once the last block is ACKed by the target, the transfer should be finalized by an
|
||||
// EOT (ASCII 0x04) packet from the source. This packet is confirmed via XModem ACK
|
||||
// from the target.
|
||||
XYZModemWrite(XYZM_EOT);
|
||||
XYZModem.timeout = millis() + (30 * 1000); // Allow 30 seconds to receive EOT ACK
|
||||
XYZFile.step = XYZM_ACKT;
|
||||
break;
|
||||
}
|
||||
case XYZM_ACKT: { // *** Send EOT and wait for ACK
|
||||
case XYZM_SND_ACK: { // *** Wait for ACK
|
||||
// The ACK for the last XModem data packet may take much longer (1-3 seconds) than prior
|
||||
// data packets to be received.
|
||||
if (millis() > XYZModem.timeout) {
|
||||
@ -778,9 +773,8 @@ bool XYZModemLoop(void) {
|
||||
return true;
|
||||
}
|
||||
else if (XYZM_ACK == xmodem_ack) {
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("XMD: Successful"));
|
||||
XYZModem.timeout = millis() + (30 * 1000); // Allow 30 seconds
|
||||
XYZFile.byte_counter = 0;
|
||||
// !!! Send an AddLog here as it previously would interfere with XModem protocol !!!
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("XMD: Send %d bytes succesful"), XYZFile.size);
|
||||
XYZFile.step = XYZM_DONE;
|
||||
}
|
||||
}
|
||||
@ -807,16 +801,15 @@ bool XYZModemLoop(void) {
|
||||
break;
|
||||
}
|
||||
case XYZM_RCV_START: {
|
||||
if (XYZFile.byte_counter && !(XYZFile.byte_counter % 10240)) { // Show progress every 10kB
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("XMD: Progress %d kB"), XYZFile.byte_counter / 1024);
|
||||
if (XYZFile.byte_counter && !(XYZFile.byte_counter % 10240)) { // Show progress every 10KB
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("XMD: Progress %d KB"), XYZFile.byte_counter / 1024);
|
||||
}
|
||||
int result = XYZModemReceive(XYZModem.packet_no);
|
||||
if (result) {
|
||||
switch (result) {
|
||||
case XYZS_EOT: {
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("XMD: Received %d bytes"), XYZFile.byte_counter);
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("XMD: Successful"));
|
||||
XYZModemFileWriteEot(1);
|
||||
AddLog(LOG_LEVEL_INFO, PSTR("XMD: Received %d bytes succesful"), XYZFile.byte_counter);
|
||||
XYZFile.step = XYZM_DONE;
|
||||
break;
|
||||
}
|
||||
@ -875,17 +868,6 @@ bool XYZModemLoop(void) {
|
||||
break;
|
||||
}
|
||||
// *** Finish
|
||||
case XYZM_COMPLETE: { // *** Wait for send complete
|
||||
if (millis() > XYZModem.timeout) {
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("XMD: Timeout"));
|
||||
XYZFile.step = XYZM_ERROR;
|
||||
return true;
|
||||
} else {
|
||||
XYZFile.state = XYZM_COMPLETE;
|
||||
XYZFile.step = XYZM_DONE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case XYZM_ERROR:
|
||||
XYZFile.state = XYZM_ERROR;
|
||||
AddLog(LOG_LEVEL_DEBUG, PSTR("XMD: Failed"));
|
||||
|
@ -97,6 +97,25 @@ void TelnetWriteColor(uint32_t color) {
|
||||
}
|
||||
}
|
||||
|
||||
void TelnetLDJsonPPCb(const char* line, uint32_t len) {
|
||||
uint32_t textcolor = Telnet.color[Telnet.prompt];
|
||||
uint32_t diffcolor = textcolor;
|
||||
if ((textcolor >= 30) && (textcolor <= 37)) {
|
||||
diffcolor += 60; // Highlight color
|
||||
}
|
||||
else if ((textcolor >= 90) && (textcolor <= 97)) {
|
||||
diffcolor -= 60; // Lowlight color
|
||||
}
|
||||
char* time_end = (char*)memchr(line, ' ', len); // Find first word (usually 14:49:36.123-017)
|
||||
uint32_t time_len = time_end - line;
|
||||
TelnetWriteColor(diffcolor);
|
||||
Telnet.client.write(line, time_len);
|
||||
TelnetWriteColor(textcolor);
|
||||
Telnet.client.write(time_end, len - time_len);
|
||||
TelnetWriteColor(0);
|
||||
Telnet.client.println();
|
||||
}
|
||||
|
||||
void TelnetWrite(char *line, uint32_t len) {
|
||||
if (Telnet.client) {
|
||||
if (3 == Telnet.prompt) { // Print linefeed for non-requested data
|
||||
@ -104,22 +123,10 @@ void TelnetWrite(char *line, uint32_t len) {
|
||||
Telnet.client.println();
|
||||
}
|
||||
// line = 14:49:36.123-017 MQTT: stat/wemos5/RESULT = {"POWER":"OFF"}
|
||||
uint32_t textcolor = Telnet.color[Telnet.prompt];
|
||||
uint32_t diffcolor = textcolor;
|
||||
if ((textcolor >= 30) && (textcolor <= 37)) {
|
||||
diffcolor += 60; // Highlight color
|
||||
|
||||
if (!LogDataJsonPrettyPrint(line, len, TelnetLDJsonPPCb)) {
|
||||
TelnetLDJsonPPCb(line, len);
|
||||
}
|
||||
else if ((textcolor >= 90) && (textcolor <= 97)) {
|
||||
diffcolor -= 60; // Lowlight color
|
||||
}
|
||||
char* time_end = (char*)memchr(line, ' ', len); // Find first word (usually 14:49:36.123-017)
|
||||
uint32_t time_len = time_end - line;
|
||||
TelnetWriteColor(diffcolor);
|
||||
Telnet.client.write(line, time_len);
|
||||
TelnetWriteColor(textcolor);
|
||||
Telnet.client.write(time_end, len - time_len);
|
||||
TelnetWriteColor(0);
|
||||
Telnet.client.println();
|
||||
}
|
||||
}
|
||||
|
||||
@ -182,10 +189,24 @@ void TelnetLoop(void) {
|
||||
}
|
||||
|
||||
// Input keyboard data
|
||||
bool telnet_iac = false;
|
||||
while (Telnet.client.available()) {
|
||||
yield();
|
||||
uint8_t in_byte = Telnet.client.read();
|
||||
|
||||
if (telnet_iac) {
|
||||
telnet_iac = false;
|
||||
if (in_byte != 0xFF) {
|
||||
// Process telnet Interpret as Command (IAC) codes
|
||||
AddLog(LOG_LEVEL_DEBUG_MORE, PSTR(D_LOG_TELNET "IAC %d"), in_byte);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (0xFF == in_byte) { // Telnet Interpret as Command (IAC)
|
||||
telnet_iac = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef USE_XYZMODEM
|
||||
if (XYZModemWifiClientStart(&Telnet.client, in_byte)) { return; }
|
||||
#endif // USE_XYZMODEM
|
||||
|
Loading…
x
Reference in New Issue
Block a user