Merge branch 'dev' into dev2

This commit is contained in:
MichaelDvP
2024-02-23 08:56:43 +01:00
12 changed files with 798 additions and 737 deletions

1
.gitignore vendored
View File

@@ -38,6 +38,7 @@ stats.html
!.yarn/versions
yarn.lock
interface/analyse.html
interface/vite.config.ts.timestamp*
# scripts
test.sh

View File

@@ -44,3 +44,4 @@
- small changes to the API for analog and temperature sensors
- Length of mqtt Broker adress [#1619](https://github.com/emsesp/EMS-ESP32/issues/1619)
- C++ optimizations - see <https://github.com/emsesp/EMS-ESP32/pull/1615>
- Send MQTT heartbeat immediately after connection [#1628](https://github.com/emsesp/EMS-ESP32/issues/1628)

View File

@@ -31,8 +31,8 @@
"@table-library/react-table-library": "4.1.7",
"@types/imagemin": "^8.0.5",
"@types/lodash-es": "^4.17.12",
"@types/node": "^20.11.19",
"@types/react": "^18.2.56",
"@types/node": "^20.11.20",
"@types/react": "^18.2.57",
"@types/react-dom": "^18.2.19",
"@types/react-router-dom": "^5.3.3",
"alova": "^2.17.0",
@@ -54,8 +54,8 @@
"devDependencies": {
"@preact/compat": "^17.1.2",
"@preact/preset-vite": "^2.8.1",
"@typescript-eslint/eslint-plugin": "^7.0.1",
"@typescript-eslint/parser": "^7.0.1",
"@typescript-eslint/eslint-plugin": "^7.0.2",
"@typescript-eslint/parser": "^7.0.2",
"concurrently": "^8.2.2",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
@@ -66,11 +66,11 @@
"eslint-plugin-prettier": "alpha",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"preact": "^10.19.5",
"preact": "^10.19.6",
"prettier": "^3.2.5",
"rollup-plugin-visualizer": "^5.12.0",
"terser": "^5.27.1",
"vite": "^5.1.3",
"terser": "^5.27.2",
"vite": "^5.1.4",
"vite-plugin-imagemin": "^0.6.1",
"vite-tsconfig-paths": "^4.3.1"
},

View File

@@ -1590,12 +1590,12 @@ __metadata:
languageName: node
linkType: hard
"@types/node@npm:^20.11.19":
version: 20.11.19
resolution: "@types/node@npm:20.11.19"
"@types/node@npm:^20.11.20":
version: 20.11.20
resolution: "@types/node@npm:20.11.20"
dependencies:
undici-types: "npm:~5.26.4"
checksum: 10/c7f4705d6c84aa21679ad180c33c13ca9567f650e66e14bcee77c7c43d14619c7cd3b4d7b2458947143030b7b1930180efa6d12d999b45366abff9fed7a17472
checksum: 10/ff449bdc94810dadb54e0f77dd587c6505ef79ffa5a208c16eb29b223365b188f4c935a3abaf0906a01d05257c3da1f72465594a841d35bcf7b6deac7a6938fb
languageName: node
linkType: hard
@@ -1670,14 +1670,14 @@ __metadata:
languageName: node
linkType: hard
"@types/react@npm:^18.2.56":
version: 18.2.56
resolution: "@types/react@npm:18.2.56"
"@types/react@npm:^18.2.57":
version: 18.2.57
resolution: "@types/react@npm:18.2.57"
dependencies:
"@types/prop-types": "npm:*"
"@types/scheduler": "npm:*"
csstype: "npm:^3.0.2"
checksum: 10/de0df184f2b80e8724d79eead47f23e43e91a68c0712a5d989db3f1242f2c24179cf8e26520b5a141396b55f4928ce9a6c3a3a121a98eca8e82973920209f06c
checksum: 10/beee45a8ee48862fb5101f6ebdd89ccc20c5a6df29dcd2315560bc3b57ea3af8d09a8e9bb1c58063a70f9010e0d2c7bd300819438e2ca62810285c3d7275ab5a
languageName: node
linkType: hard
@@ -1713,15 +1713,15 @@ __metadata:
languageName: node
linkType: hard
"@typescript-eslint/eslint-plugin@npm:^7.0.1":
version: 7.0.1
resolution: "@typescript-eslint/eslint-plugin@npm:7.0.1"
"@typescript-eslint/eslint-plugin@npm:^7.0.2":
version: 7.0.2
resolution: "@typescript-eslint/eslint-plugin@npm:7.0.2"
dependencies:
"@eslint-community/regexpp": "npm:^4.5.1"
"@typescript-eslint/scope-manager": "npm:7.0.1"
"@typescript-eslint/type-utils": "npm:7.0.1"
"@typescript-eslint/utils": "npm:7.0.1"
"@typescript-eslint/visitor-keys": "npm:7.0.1"
"@typescript-eslint/scope-manager": "npm:7.0.2"
"@typescript-eslint/type-utils": "npm:7.0.2"
"@typescript-eslint/utils": "npm:7.0.2"
"@typescript-eslint/visitor-keys": "npm:7.0.2"
debug: "npm:^4.3.4"
graphemer: "npm:^1.4.0"
ignore: "npm:^5.2.4"
@@ -1734,44 +1734,44 @@ __metadata:
peerDependenciesMeta:
typescript:
optional: true
checksum: 10/0862e8ec8677fcea794394fc9eab8dba11043c08452722790e0d296d4ee84713180676e1e3135be4203ace7bb73933c94159255cb9190c7bc13bf7f03a361915
checksum: 10/430b2f7ca36ee73dc75c1d677088709f3c9d5bbb4fffa3cfbe1b7d63979ee397f7a4a2a1386e05a04991500fa0ab0dd5272e8603a2b20f42e4bf590603500858
languageName: node
linkType: hard
"@typescript-eslint/parser@npm:^7.0.1":
version: 7.0.1
resolution: "@typescript-eslint/parser@npm:7.0.1"
"@typescript-eslint/parser@npm:^7.0.2":
version: 7.0.2
resolution: "@typescript-eslint/parser@npm:7.0.2"
dependencies:
"@typescript-eslint/scope-manager": "npm:7.0.1"
"@typescript-eslint/types": "npm:7.0.1"
"@typescript-eslint/typescript-estree": "npm:7.0.1"
"@typescript-eslint/visitor-keys": "npm:7.0.1"
"@typescript-eslint/scope-manager": "npm:7.0.2"
"@typescript-eslint/types": "npm:7.0.2"
"@typescript-eslint/typescript-estree": "npm:7.0.2"
"@typescript-eslint/visitor-keys": "npm:7.0.2"
debug: "npm:^4.3.4"
peerDependencies:
eslint: ^8.56.0
peerDependenciesMeta:
typescript:
optional: true
checksum: 10/b4ba1743ab730268a1924139f072e4a0a56959526fb6377e1b3964518b6c6851733ae446a44d29fed1cb96669e2913cca524895ce77a6205aaed8bda00e8cd5d
checksum: 10/18d6e1bda64013f7d66164164c57a10390f7979db55b265062ae9337e11e0921bffca10870e252cd0bd198f79ffa2e87a652e57110e5b1b4cc738453154c205c
languageName: node
linkType: hard
"@typescript-eslint/scope-manager@npm:7.0.1":
version: 7.0.1
resolution: "@typescript-eslint/scope-manager@npm:7.0.1"
"@typescript-eslint/scope-manager@npm:7.0.2":
version: 7.0.2
resolution: "@typescript-eslint/scope-manager@npm:7.0.2"
dependencies:
"@typescript-eslint/types": "npm:7.0.1"
"@typescript-eslint/visitor-keys": "npm:7.0.1"
checksum: 10/dade6055bb853adb54de795cc3da5ab8550236d4186f108573fdb02e636ab7fc4300a55b506698ced4087ca43b143a5593931cb3195ab4790470b456d9ff8846
"@typescript-eslint/types": "npm:7.0.2"
"@typescript-eslint/visitor-keys": "npm:7.0.2"
checksum: 10/773ea6e61f741777e69a469641f3db0d3c2301c0102667825fb235ed5a65c95f6d6b31b19e734b9a215acc0c7c576c65497635b8d5928eeddb58653ceb13d2d5
languageName: node
linkType: hard
"@typescript-eslint/type-utils@npm:7.0.1":
version: 7.0.1
resolution: "@typescript-eslint/type-utils@npm:7.0.1"
"@typescript-eslint/type-utils@npm:7.0.2":
version: 7.0.2
resolution: "@typescript-eslint/type-utils@npm:7.0.2"
dependencies:
"@typescript-eslint/typescript-estree": "npm:7.0.1"
"@typescript-eslint/utils": "npm:7.0.1"
"@typescript-eslint/typescript-estree": "npm:7.0.2"
"@typescript-eslint/utils": "npm:7.0.2"
debug: "npm:^4.3.4"
ts-api-utils: "npm:^1.0.1"
peerDependencies:
@@ -1779,23 +1779,23 @@ __metadata:
peerDependenciesMeta:
typescript:
optional: true
checksum: 10/cf20a3c0e56121ac62467e48121e135798db6d2999bd4f96ed44edc39f2597812d12b1bd6a378adec54d6c5e7db75fa5f98a27ce399792a2c8a5bbd3649952f7
checksum: 10/63bf19c9f5bbcb0f3e127f509d85dc49be4e5e51781d78f58c96786089e7c909b25d35d0248a6a758e2f7d5b5223d2262c2d597ab71f226af6beb499ae950645
languageName: node
linkType: hard
"@typescript-eslint/types@npm:7.0.1":
version: 7.0.1
resolution: "@typescript-eslint/types@npm:7.0.1"
checksum: 10/c08b2d34bab2a877a45a1e4c2923f50d03022b682b7aaba929ae2a9a5ad32db0e46265544a6616ccb98654b434250621be0e282fc5b21b8ccaf6b78741d68f67
"@typescript-eslint/types@npm:7.0.2":
version: 7.0.2
resolution: "@typescript-eslint/types@npm:7.0.2"
checksum: 10/2cba8a0355cc7357db142fa597d02cf39e1d1cb0ec87c80e91daaa2b87f2a794d2649def9d7b2aa435691c3810d2cbd4cdc21668b19b991863f0d54d4a22da82
languageName: node
linkType: hard
"@typescript-eslint/typescript-estree@npm:7.0.1":
version: 7.0.1
resolution: "@typescript-eslint/typescript-estree@npm:7.0.1"
"@typescript-eslint/typescript-estree@npm:7.0.2":
version: 7.0.2
resolution: "@typescript-eslint/typescript-estree@npm:7.0.2"
dependencies:
"@typescript-eslint/types": "npm:7.0.1"
"@typescript-eslint/visitor-keys": "npm:7.0.1"
"@typescript-eslint/types": "npm:7.0.2"
"@typescript-eslint/visitor-keys": "npm:7.0.2"
debug: "npm:^4.3.4"
globby: "npm:^11.1.0"
is-glob: "npm:^4.0.3"
@@ -1805,34 +1805,34 @@ __metadata:
peerDependenciesMeta:
typescript:
optional: true
checksum: 10/b0b0adc84502d1ffcf3a0024179e0f2780be5f8b0a18328db46d430efc4e38a7965656b4392dd47d6176bbb1ee200aec6dd8581c39b606e260750574358cde9f
checksum: 10/307080e29c22fc69f0ce7ab7101e1629e05f45a9e541c250e03d06b61336ab0ccb5f0a7354ee3da4e38d5cade4dd2fb7bb396cd7cbe74c2c4b3e29706a70abcc
languageName: node
linkType: hard
"@typescript-eslint/utils@npm:7.0.1":
version: 7.0.1
resolution: "@typescript-eslint/utils@npm:7.0.1"
"@typescript-eslint/utils@npm:7.0.2":
version: 7.0.2
resolution: "@typescript-eslint/utils@npm:7.0.2"
dependencies:
"@eslint-community/eslint-utils": "npm:^4.4.0"
"@types/json-schema": "npm:^7.0.12"
"@types/semver": "npm:^7.5.0"
"@typescript-eslint/scope-manager": "npm:7.0.1"
"@typescript-eslint/types": "npm:7.0.1"
"@typescript-eslint/typescript-estree": "npm:7.0.1"
"@typescript-eslint/scope-manager": "npm:7.0.2"
"@typescript-eslint/types": "npm:7.0.2"
"@typescript-eslint/typescript-estree": "npm:7.0.2"
semver: "npm:^7.5.4"
peerDependencies:
eslint: ^8.56.0
checksum: 10/b7e0cb2994f73b3f416684dc175d4e1da5f8306d6c81abbad2f219fa3e4f29154063a3c9568e4a1f879a38b79c62250e596e4ed7265f7bd1ed9b3db806cb92b7
checksum: 10/e68bac777419cd529371f7f29f534efaeca130c90ed9723bfc7aac451d61ca3fc4ebd310e2c015e29e8dc7be4734ae46258ca8755897d7f5e3bb502660d5372f
languageName: node
linkType: hard
"@typescript-eslint/visitor-keys@npm:7.0.1":
version: 7.0.1
resolution: "@typescript-eslint/visitor-keys@npm:7.0.1"
"@typescript-eslint/visitor-keys@npm:7.0.2":
version: 7.0.2
resolution: "@typescript-eslint/visitor-keys@npm:7.0.2"
dependencies:
"@typescript-eslint/types": "npm:7.0.1"
"@typescript-eslint/types": "npm:7.0.2"
eslint-visitor-keys: "npm:^3.4.1"
checksum: 10/915c5b19302a4c76e843cd2d04a9a2b11907e658d7018c8b55c338b090d9115d3719809aa05b8af130cc1b216c77626d210c20f705b732e83d04ceae0c112f6b
checksum: 10/da6c1b0729af99216cde3a65d4e91584a81fc6c9dff7ba291089f01bf7262de375f58c4c4246e5fbc29f51258db7725d9c830f82ccbd1cda812fd13c51480cda
languageName: node
linkType: hard
@@ -1858,12 +1858,12 @@ __metadata:
"@table-library/react-table-library": "npm:4.1.7"
"@types/imagemin": "npm:^8.0.5"
"@types/lodash-es": "npm:^4.17.12"
"@types/node": "npm:^20.11.19"
"@types/react": "npm:^18.2.56"
"@types/node": "npm:^20.11.20"
"@types/react": "npm:^18.2.57"
"@types/react-dom": "npm:^18.2.19"
"@types/react-router-dom": "npm:^5.3.3"
"@typescript-eslint/eslint-plugin": "npm:^7.0.1"
"@typescript-eslint/parser": "npm:^7.0.1"
"@typescript-eslint/eslint-plugin": "npm:^7.0.2"
"@typescript-eslint/parser": "npm:^7.0.2"
alova: "npm:^2.17.0"
async-validator: "npm:^4.2.5"
concurrently: "npm:^8.2.2"
@@ -1880,7 +1880,7 @@ __metadata:
jwt-decode: "npm:^4.0.0"
lodash-es: "npm:^4.17.21"
mime-types: "npm:^2.1.35"
preact: "npm:^10.19.5"
preact: "npm:^10.19.6"
prettier: "npm:^3.2.5"
react: "npm:latest"
react-dom: "npm:latest"
@@ -1890,10 +1890,10 @@ __metadata:
react-toastify: "npm:^10.0.4"
rollup-plugin-visualizer: "npm:^5.12.0"
sockette: "npm:^2.0.6"
terser: "npm:^5.27.1"
terser: "npm:^5.27.2"
typesafe-i18n: "npm:^5.26.2"
typescript: "npm:^5.3.3"
vite: "npm:^5.1.3"
vite: "npm:^5.1.4"
vite-plugin-imagemin: "npm:^0.6.1"
vite-tsconfig-paths: "npm:^4.3.1"
languageName: unknown
@@ -7021,10 +7021,10 @@ __metadata:
languageName: node
linkType: hard
"preact@npm:^10.19.5":
version: 10.19.5
resolution: "preact@npm:10.19.5"
checksum: 10/9c4c716361d7793f6c8ae475db7bbed7ef4affd4ac8eaf6ff9afd8d1218a0ae55918635b5d8842a3c8eecd22728e24f0af681c710d0ada6d81424dd991665cde
"preact@npm:^10.19.6":
version: 10.19.6
resolution: "preact@npm:10.19.6"
checksum: 10/851c7d91e6899a40fdeae0ef9a792bf3217ed8365ce96f4c5630048c82b44c637fd4c0d8a4b0c3e1c8e74e243600dd9c5787520da07552d33a06c957779b4167
languageName: node
linkType: hard
@@ -8312,9 +8312,9 @@ __metadata:
languageName: node
linkType: hard
"terser@npm:^5.27.1":
version: 5.27.1
resolution: "terser@npm:5.27.1"
"terser@npm:^5.27.2":
version: 5.27.2
resolution: "terser@npm:5.27.2"
dependencies:
"@jridgewell/source-map": "npm:^0.3.3"
acorn: "npm:^8.8.2"
@@ -8322,7 +8322,7 @@ __metadata:
source-map-support: "npm:~0.5.20"
bin:
terser: bin/terser
checksum: 10/4b5c8c65548071ae09dc1d9fd64616262876229897eaac9f95cf2e44908a1f4a25d7837c2a38caef1a523cf1cf67d254e74a846e9a854d289c0ad3664d581c3c
checksum: 10/589f1112d6cd7653f6e2d4a38970e97a160de01cddb214dc924aa330c22b8c3635067a47db1233e060e613e380b979ca336c3211b17507ea13b0adff10ecbd40
languageName: node
linkType: hard
@@ -8738,9 +8738,9 @@ __metadata:
languageName: node
linkType: hard
"vite@npm:^5.1.3":
version: 5.1.3
resolution: "vite@npm:5.1.3"
"vite@npm:^5.1.4":
version: 5.1.4
resolution: "vite@npm:5.1.4"
dependencies:
esbuild: "npm:^0.19.3"
fsevents: "npm:~2.3.3"
@@ -8774,7 +8774,7 @@ __metadata:
optional: true
bin:
vite: bin/vite.js
checksum: 10/6ba2223157e2cc2fa62dff9004ccba20fc409c6baf7354c64ed0f8e4bcd853092d08d06ec4dec37143e794a96e061879a870d85bad4f1eb9ee5c6d0a13cef30f
checksum: 10/e9003b853f0784260f4fe7ce0190124b347fd8fd6bf889a07080facd0d9a9667eaff4022eddb1ba3f0283ef69d15d77f84bca832082e48874a7a62e7f6d66b08
languageName: node
linkType: hard

File diff suppressed because it is too large Load Diff

View File

@@ -29,15 +29,15 @@
#ifndef LIBRETINY
#include "sdkconfig.h"
extern "C" {
#include "freertos/semphr.h"
#include "lwip/pbuf.h"
#include "lwip/ip_addr.h"
#include "lwip/ip6_addr.h"
#include "freertos/semphr.h"
#include "lwip/pbuf.h"
#include "lwip/ip_addr.h"
#include "lwip/ip6_addr.h"
}
#else
extern "C" {
#include <semphr.h>
#include <lwip/pbuf.h>
#include <semphr.h>
#include <lwip/pbuf.h>
}
#define CONFIG_ASYNC_TCP_RUNNING_CORE -1 //any available core
#define CONFIG_ASYNC_TCP_USE_WDT 0
@@ -46,11 +46,20 @@ extern "C" {
//If core is not defined, then we are running in Arduino or PIO
#ifndef CONFIG_ASYNC_TCP_RUNNING_CORE
#define CONFIG_ASYNC_TCP_RUNNING_CORE -1 //any available core
#define CONFIG_ASYNC_TCP_USE_WDT 1 //if enabled, adds between 33us and 200us per event
#define CONFIG_ASYNC_TCP_USE_WDT 0 //if enabled, adds between 33us and 200us per event
#endif
#ifndef CONFIG_ASYNC_TCP_TASK_PRIORITY
#define CONFIG_ASYNC_TCP_TASK_PRIORITY 5
#endif
#ifndef CONFIG_ASYNC_TCP_STACK_SIZE
#define CONFIG_ASYNC_TCP_STACK_SIZE 8192 * 2
#define CONFIG_ASYNC_TCP_STACK_SIZE 5120
#endif
#ifndef CONFIG_ASYNC_TCP_QUEUE
#define CONFIG_ASYNC_TCP_QUEUE 128
#endif
class AsyncClient;
@@ -59,132 +68,136 @@ class AsyncClient;
#define ASYNC_WRITE_FLAG_COPY 0x01 //will allocate new buffer to hold the data while sending (else will hold reference to the data given)
#define ASYNC_WRITE_FLAG_MORE 0x02 //will not send PSH flag, meaning that there should be more data to be sent before the application should react.
typedef std::function<void(void*, AsyncClient*)> AcConnectHandler;
typedef std::function<void(void*, AsyncClient*, size_t len, uint32_t time)> AcAckHandler;
typedef std::function<void(void*, AsyncClient*, int8_t error)> AcErrorHandler;
typedef std::function<void(void*, AsyncClient*, void *data, size_t len)> AcDataHandler;
typedef std::function<void(void*, AsyncClient*, struct pbuf *pb)> AcPacketHandler;
typedef std::function<void(void*, AsyncClient*, uint32_t time)> AcTimeoutHandler;
typedef std::function<void(void *, AsyncClient *)> AcConnectHandler;
typedef std::function<void(void *, AsyncClient *, size_t len, uint32_t time)> AcAckHandler;
typedef std::function<void(void *, AsyncClient *, int8_t error)> AcErrorHandler;
typedef std::function<void(void *, AsyncClient *, void * data, size_t len)> AcDataHandler;
typedef std::function<void(void *, AsyncClient *, struct pbuf * pb)> AcPacketHandler;
typedef std::function<void(void *, AsyncClient *, uint32_t time)> AcTimeoutHandler;
struct tcp_pcb;
struct ip_addr;
class AsyncClient {
public:
AsyncClient(tcp_pcb* pcb = 0);
AsyncClient(tcp_pcb * pcb = 0);
~AsyncClient();
AsyncClient & operator=(const AsyncClient &other);
AsyncClient & operator+=(const AsyncClient &other);
AsyncClient & operator=(const AsyncClient & other);
AsyncClient & operator+=(const AsyncClient & other);
bool operator==(const AsyncClient &other);
bool operator==(const AsyncClient & other);
bool operator!=(const AsyncClient &other) {
return !(*this == other);
bool operator!=(const AsyncClient & other) {
return !(*this == other);
}
bool connect(IPAddress ip, uint16_t port);
bool connect(IPv6Address ip, uint16_t port);
bool connect(const char *host, uint16_t port);
void close(bool now = false);
void stop();
bool connect(IPAddress ip, uint16_t port);
bool connect(IPv6Address ip, uint16_t port);
bool connect(const char * host, uint16_t port);
void close(bool now = false);
void stop();
int8_t abort();
bool free();
bool free();
bool canSend();//ack is not pending
size_t space();//space available in the TCP window
size_t add(const char* data, size_t size, uint8_t apiflags=ASYNC_WRITE_FLAG_COPY);//add for sending
bool send();//send all data added with the method above
bool canSend(); //ack is not pending
size_t space(); //space available in the TCP window
size_t add(const char * data, size_t size, uint8_t apiflags = ASYNC_WRITE_FLAG_COPY); //add for sending
bool send(); //send all data added with the method above
//write equals add()+send()
size_t write(const char* data);
size_t write(const char* data, size_t size, uint8_t apiflags=ASYNC_WRITE_FLAG_COPY); //only when canSend() == true
size_t write(const char * data);
size_t write(const char * data, size_t size, uint8_t apiflags = ASYNC_WRITE_FLAG_COPY); //only when canSend() == true
uint8_t state();
bool connecting();
bool connected();
bool disconnecting();
bool disconnected();
bool freeable();//disconnected or disconnecting
bool connecting();
bool connected();
bool disconnecting();
bool disconnected();
bool freeable(); //disconnected or disconnecting
uint16_t getMss();
uint32_t getRxTimeout();
void setRxTimeout(uint32_t timeout);//no RX data timeout for the connection in seconds
void setRxTimeout(uint32_t timeout); //no RX data timeout for the connection in seconds
uint32_t getAckTimeout();
void setAckTimeout(uint32_t timeout);//no ACK timeout for the last sent packet in milliseconds
void setAckTimeout(uint32_t timeout); //no ACK timeout for the last sent packet in milliseconds
void setNoDelay(bool nodelay);
bool getNoDelay();
uint32_t getRemoteAddress();
uint32_t getRemoteAddress();
ip6_addr_t getRemoteAddress6();
uint16_t getRemotePort();
uint32_t getLocalAddress();
uint16_t getRemotePort();
uint32_t getLocalAddress();
ip6_addr_t getLocalAddress6();
uint16_t getLocalPort();
uint16_t getLocalPort();
//compatibility
IPAddress remoteIP();
IPAddress remoteIP();
IPv6Address remoteIP6();
uint16_t remotePort();
IPAddress localIP();
uint16_t remotePort();
IPAddress localIP();
IPv6Address localIP6();
uint16_t localPort();
uint16_t localPort();
void onConnect(AcConnectHandler cb, void* arg = 0); //on successful connect
void onDisconnect(AcConnectHandler cb, void* arg = 0); //disconnected
void onAck(AcAckHandler cb, void* arg = 0); //ack received
void onError(AcErrorHandler cb, void* arg = 0); //unsuccessful connect or error
void onData(AcDataHandler cb, void* arg = 0); //data received (called if onPacket is not used)
void onPacket(AcPacketHandler cb, void* arg = 0); //data received
void onTimeout(AcTimeoutHandler cb, void* arg = 0); //ack timeout
void onPoll(AcConnectHandler cb, void* arg = 0); //every 125ms when connected
void onConnect(AcConnectHandler cb, void * arg = 0); //on successful connect
void onDisconnect(AcConnectHandler cb, void * arg = 0); //disconnected
void onAck(AcAckHandler cb, void * arg = 0); //ack received
void onError(AcErrorHandler cb, void * arg = 0); //unsuccessful connect or error
void onData(AcDataHandler cb, void * arg = 0); //data received (called if onPacket is not used)
void onPacket(AcPacketHandler cb, void * arg = 0); //data received
void onTimeout(AcTimeoutHandler cb, void * arg = 0); //ack timeout
void onPoll(AcConnectHandler cb, void * arg = 0); //every 125ms when connected
void ackPacket(struct pbuf * pb);//ack pbuf from onPacket
size_t ack(size_t len); //ack data that you have not acked using the method below
void ackLater(){ _ack_pcb = false; } //will not ack the current packet. Call from onData
void ackPacket(struct pbuf * pb); //ack pbuf from onPacket
size_t ack(size_t len); //ack data that you have not acked using the method below
void ackLater() {
_ack_pcb = false;
} //will not ack the current packet. Call from onData
const char * errorToString(int8_t error);
const char * stateToString();
//Do not use any of the functions below!
static int8_t _s_poll(void *arg, struct tcp_pcb *tpcb);
static int8_t _s_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *pb, int8_t err);
static int8_t _s_fin(void *arg, struct tcp_pcb *tpcb, int8_t err);
static int8_t _s_lwip_fin(void *arg, struct tcp_pcb *tpcb, int8_t err);
static void _s_error(void *arg, int8_t err);
static int8_t _s_sent(void *arg, struct tcp_pcb *tpcb, uint16_t len);
static int8_t _s_connected(void* arg, void* tpcb, int8_t err);
static void _s_dns_found(const char *name, struct ip_addr *ipaddr, void *arg);
static int8_t _s_poll(void * arg, struct tcp_pcb * tpcb);
static int8_t _s_recv(void * arg, struct tcp_pcb * tpcb, struct pbuf * pb, int8_t err);
static int8_t _s_fin(void * arg, struct tcp_pcb * tpcb, int8_t err);
static int8_t _s_lwip_fin(void * arg, struct tcp_pcb * tpcb, int8_t err);
static void _s_error(void * arg, int8_t err);
static int8_t _s_sent(void * arg, struct tcp_pcb * tpcb, uint16_t len);
static int8_t _s_connected(void * arg, void * tpcb, int8_t err);
static void _s_dns_found(const char * name, struct ip_addr * ipaddr, void * arg);
int8_t _recv(tcp_pcb* pcb, pbuf* pb, int8_t err);
tcp_pcb * pcb(){ return _pcb; }
int8_t _recv(tcp_pcb * pcb, pbuf * pb, int8_t err);
tcp_pcb * pcb() {
return _pcb;
}
protected:
bool _connect(ip_addr_t addr, uint16_t port);
tcp_pcb* _pcb;
int8_t _closed_slot;
tcp_pcb * _pcb;
int8_t _closed_slot;
AcConnectHandler _connect_cb;
void* _connect_cb_arg;
void * _connect_cb_arg;
AcConnectHandler _discard_cb;
void* _discard_cb_arg;
AcAckHandler _sent_cb;
void* _sent_cb_arg;
AcErrorHandler _error_cb;
void* _error_cb_arg;
AcDataHandler _recv_cb;
void* _recv_cb_arg;
AcPacketHandler _pb_cb;
void* _pb_cb_arg;
void * _discard_cb_arg;
AcAckHandler _sent_cb;
void * _sent_cb_arg;
AcErrorHandler _error_cb;
void * _error_cb_arg;
AcDataHandler _recv_cb;
void * _recv_cb_arg;
AcPacketHandler _pb_cb;
void * _pb_cb_arg;
AcTimeoutHandler _timeout_cb;
void* _timeout_cb_arg;
void * _timeout_cb_arg;
AcConnectHandler _poll_cb;
void* _poll_cb_arg;
void * _poll_cb_arg;
bool _ack_pcb;
bool _ack_pcb;
uint32_t _tx_last_packet;
uint32_t _rx_ack_len;
uint32_t _rx_last_packet;
@@ -194,19 +207,19 @@ class AsyncClient {
uint16_t _connect_port;
int8_t _close();
void _free_closed_slot();
void _allocate_closed_slot();
int8_t _connected(void* pcb, int8_t err);
void _error(int8_t err);
int8_t _poll(tcp_pcb* pcb);
int8_t _sent(tcp_pcb* pcb, uint16_t len);
int8_t _fin(tcp_pcb* pcb, int8_t err);
int8_t _lwip_fin(tcp_pcb* pcb, int8_t err);
void _dns_found(struct ip_addr *ipaddr);
void _free_closed_slot();
void _allocate_closed_slot();
int8_t _connected(void * pcb, int8_t err);
void _error(int8_t err);
int8_t _poll(tcp_pcb * pcb);
int8_t _sent(tcp_pcb * pcb, uint16_t len);
int8_t _fin(tcp_pcb * pcb, int8_t err);
int8_t _lwip_fin(tcp_pcb * pcb, int8_t err);
void _dns_found(struct ip_addr * ipaddr);
public:
AsyncClient* prev;
AsyncClient* next;
AsyncClient * prev;
AsyncClient * next;
};
class AsyncServer {
@@ -215,30 +228,30 @@ class AsyncServer {
AsyncServer(IPv6Address addr, uint16_t port);
AsyncServer(uint16_t port);
~AsyncServer();
void onClient(AcConnectHandler cb, void* arg);
void begin();
void end();
void setNoDelay(bool nodelay);
bool getNoDelay();
void onClient(AcConnectHandler cb, void * arg);
void begin();
void end();
void setNoDelay(bool nodelay);
bool getNoDelay();
uint8_t status();
//Do not use any of the functions below!
static int8_t _s_accept(void *arg, tcp_pcb* newpcb, int8_t err);
static int8_t _s_accepted(void *arg, AsyncClient* client);
static int8_t _s_accept(void * arg, tcp_pcb * newpcb, int8_t err);
static int8_t _s_accepted(void * arg, AsyncClient * client);
protected:
uint16_t _port;
bool _bind4 = false;
bool _bind6 = false;
IPAddress _addr;
IPv6Address _addr6;
bool _noDelay;
tcp_pcb* _pcb;
uint16_t _port;
bool _bind4 = false;
bool _bind6 = false;
IPAddress _addr;
IPv6Address _addr6;
bool _noDelay;
tcp_pcb * _pcb;
AcConnectHandler _connect_cb;
void* _connect_cb_arg;
void * _connect_cb_arg;
int8_t _accept(tcp_pcb* newpcb, int8_t err);
int8_t _accepted(AsyncClient* client);
int8_t _accept(tcp_pcb * newpcb, int8_t err);
int8_t _accepted(AsyncClient * client);
};

View File

@@ -316,12 +316,11 @@ void NetworkSettingsService::WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info)
break;
case ARDUINO_EVENT_ETH_START:
ETH.setHostname(emsesp::EMSESP::system_.hostname().c_str());
// configure for static IP
if (_state.staticIPConfig) {
ETH.config(_state.localIP, _state.gatewayIP, _state.subnetMask, _state.dnsIP1, _state.dnsIP2);
}
ETH.setHostname(emsesp::EMSESP::system_.hostname().c_str());
break;
case ARDUINO_EVENT_ETH_GOT_IP:

View File

@@ -2,8 +2,8 @@
; override any settings with your own local ones in pio_local.ini
[platformio]
; default_envs = esp32_4M
default_envs = lolin_s3
default_envs = esp32_4M
; default_envs = lolin_s3
; default_envs = esp32_16M
; default_envs = standalone
@@ -32,7 +32,6 @@ build_flags =
-D ARDUINOJSON_USE_DOUBLE=0
-D ARDUINOTRACE_ENABLE=0
-D CONFIG_ETH_ENABLED
-D CONFIG_UART_ISR_IN_IRAM
-D CONFIG_ASYNC_TCP_STACK_SIZE=8192
unbuild_flags =
@@ -49,12 +48,11 @@ extra_scripts =
scripts/rename_fw.py
[espressi32_base_tasmota]
; use Tasmota's library which removes some libs (like mbedtsl) and increases available heap
; platform = https://github.com/tasmota/platform-espressif32.git ; latest development
; latest release with WiFi_secure.h, Arduino 2.0.14
; use Tasmota's library which removes some unused libs (like mbedtsl, so no WiFi_secure.h) and increases available heap
; Tasmota Arduino Core 2.0.14 with IPv6 support, based on IDF 4.4.6
platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.01.01/platform-espressif32.zip
; latest Arduino 3.0/IDF 5.1.(alpha 3):
; platform = https://github.com/tasmota/platform-espressif32/releases/download/2023.12.10/platform-espressif32.zip
; Tasmota Arduino Core 3.0.0-alpha based on IDF v5.1.2
; platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.02.10/platform-espressif32.zip
framework = arduino
board_build.filesystem = littlefs
build_flags =

View File

@@ -1575,7 +1575,7 @@ void EMSdevice::publish_all_values() {
// For each value in the device create the json object pair and add it to given json
// return false if empty
// this is used to create the MQTT payloads, Console messages and Web API calls
// this is used to create the MQTT payloads, Console messages and Web API call responses
bool EMSdevice::generate_values(JsonObject output, const uint8_t tag_filter, const bool nested, const uint8_t output_target) {
bool has_values = false; // to see if we've added a value. it's faster than doing a json.size() at the end
uint8_t old_tag = 255; // NAN
@@ -1711,8 +1711,8 @@ bool EMSdevice::generate_values(JsonObject output, const uint8_t tag_filter, con
}
}
// commenting out - we don't want Commands in MQTT or Console
// else if (dv.type == DeviceValueType::CMD && output_target != EMSdevice::OUTPUT_TARGET::MQTT) {
// commenting out as we don't want Commands in Console ('show values')
// else if (dv.type == DeviceValueType::CMD && output_target != EMSdevice::OUTPUT_TARGET::MQTT) {
// json[name] = "";
// }
@@ -1762,7 +1762,7 @@ void EMSdevice::mqtt_ha_entity_config_create() {
}
}
if (!dv.has_state(DeviceValueState::DV_HA_CONFIG_CREATED) && (dv.type != DeviceValueType::CMD) && dv.has_state(DeviceValueState::DV_ACTIVE)
if (!dv.has_state(DeviceValueState::DV_HA_CONFIG_CREATED) && dv.has_state(DeviceValueState::DV_ACTIVE)
&& !dv.has_state(DeviceValueState::DV_API_MQTT_EXCLUDE)) {
// create_device_config is only done once for the EMS device. It can added to any entity, so we take the first
if (Mqtt::publish_ha_sensor_config(dv, name(), brand_to_char(), false, create_device_config)) {

View File

@@ -523,7 +523,7 @@ void Mqtt::on_connect() {
resubscribe();
// publish to the last will topic (see Mqtt::start() function) to say we're alive
queue_publish_retain("status", "online", true); // with retain on
queue_publish_retain("status", "online", false); // with retain off
// mqtt_publish_fails_ = 0; // reset fail count to 0
}
@@ -893,6 +893,7 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
readonly_sensors = false;
break;
case DeviceValueType::ENUM:
case DeviceValueType::CMD: // hardcoded commands are always ENUMS
// select - https://www.home-assistant.io/integrations/select.mqtt
snprintf(topic, sizeof(topic), "select/%s", config_topic);
readonly_sensors = false;
@@ -942,8 +943,8 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
}
doc["cmd_t"] = command_topic;
// extend for enums, add options
if (type == DeviceValueType::ENUM) {
// extend for enums and also commands, add options
if ((type == DeviceValueType::ENUM) || (type == DeviceValueType::CMD)) {
JsonArray option_list = doc["ops"].to<JsonArray>();
if (EMSESP::system_.enum_format() == ENUM_FORMAT_INDEX) {
// use index numbers
@@ -958,7 +959,6 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
}
snprintf(sample_val, sizeof(sample_val), "'%s'", Helpers::translated_word(options[0]));
}
} else if (type != DeviceValueType::STRING && type != DeviceValueType::BOOL) {
// For numeric's add the range
doc["mode"] = "box"; // auto, slider or box
@@ -994,11 +994,6 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
}
}
// state topic
char stat_t[MQTT_TOPIC_MAX_SIZE];
snprintf(stat_t, sizeof(stat_t), "%s/%s", Mqtt::base().c_str(), tag_to_topic(device_type, tag).c_str());
doc["stat_t"] = stat_t;
// friendly name = <tag> <name>
char ha_name[70];
char * F_name = strdup(fullname);
@@ -1012,38 +1007,49 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
free(F_name); // very important!
doc["name"] = ha_name;
// value template
// if its nested mqtt format then use the appended entity name, otherwise take the original name
char val_obj[100];
char val_cond[200];
if (is_nested() && tag >= DeviceValueTAG::TAG_HC1) {
snprintf(val_obj, sizeof(val_obj), "value_json.%s.%s", EMSdevice::tag_to_mqtt(tag), entity);
snprintf(val_cond, sizeof(val_cond), "value_json.%s is defined and %s is defined", EMSdevice::tag_to_mqtt(tag), val_obj);
} else {
snprintf(val_obj, sizeof(val_obj), "value_json.%s", entity);
snprintf(val_cond, sizeof(val_cond), "%s is defined", val_obj);
}
// special case to handle booleans
// applies to both Binary Sensor (read only) and a Switch (for a command)
// has no unit of measure or icon
if (type == DeviceValueType::BOOL) {
if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) {
doc["pl_on"] = true;
doc["pl_off"] = false;
snprintf(sample_val, sizeof(sample_val), "false");
} else if (EMSESP::system_.bool_format() == BOOL_FORMAT_10) {
doc["pl_on"] = 1;
doc["pl_off"] = 0;
// not needed for commands
if (type != DeviceValueType::CMD) {
// state topic, except for commands
char stat_t[MQTT_TOPIC_MAX_SIZE];
snprintf(stat_t, sizeof(stat_t), "%s/%s", Mqtt::base().c_str(), tag_to_topic(device_type, tag).c_str());
doc["stat_t"] = stat_t;
// value template
// if its nested mqtt format then use the appended entity name, otherwise take the original name
char val_obj[100];
char val_cond[200];
if (is_nested() && tag >= DeviceValueTAG::TAG_HC1) {
snprintf(val_obj, sizeof(val_obj), "value_json.%s.%s", EMSdevice::tag_to_mqtt(tag), entity);
snprintf(val_cond, sizeof(val_cond), "value_json.%s is defined and %s is defined", EMSdevice::tag_to_mqtt(tag), val_obj);
} else {
char result[12];
doc["pl_on"] = Helpers::render_boolean(result, true);
doc["pl_off"] = Helpers::render_boolean(result, false);
snprintf(sample_val, sizeof(sample_val), "'%s'", Helpers::render_boolean(result, false));
snprintf(val_obj, sizeof(val_obj), "value_json.%s", entity);
snprintf(val_cond, sizeof(val_cond), "%s is defined", val_obj);
}
}
doc["val_tpl"] = (std::string) "{{" + val_obj + " if " + val_cond + " else " + sample_val + "}}";
// special case to handle booleans
// applies to both Binary Sensor (read only) and a Switch (for a command)
// has no unit of measure or icon
if (type == DeviceValueType::BOOL) {
if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) {
doc["pl_on"] = true;
doc["pl_off"] = false;
snprintf(sample_val, sizeof(sample_val), "false");
} else if (EMSESP::system_.bool_format() == BOOL_FORMAT_10) {
doc["pl_on"] = 1;
doc["pl_off"] = 0;
} else {
char result[12];
doc["pl_on"] = Helpers::render_boolean(result, true);
doc["pl_off"] = Helpers::render_boolean(result, false);
snprintf(sample_val, sizeof(sample_val), "'%s'", Helpers::render_boolean(result, false));
}
}
doc["val_tpl"] = (std::string) "{{" + val_obj + " if " + val_cond + " else " + sample_val + "}}";
// add the dev json object to the end, not for commands
add_ha_sections_to_doc(nullptr, stat_t, doc, false, val_cond); // no name, since the "dev" has already been adde
}
// Add the state class, device class and sometimes the icon. Used only for read-only sensors like Sensor and Binary Sensor
if (readonly_sensors) {
@@ -1052,12 +1058,10 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
if (device_type == EMSdevice::DeviceType::SYSTEM) {
doc["ent_cat"] = "diagnostic";
}
add_ha_uom(doc.as<JsonObject>(), type, uom, entity); // add the UoM, device and state class
}
doc["dev"] = dev_json; // add the dev json object to the end
add_ha_sections_to_doc(nullptr, stat_t, doc, false, val_cond); // no name, since the "dev" has already been added
doc["dev"] = dev_json;
return queue_ha(topic, doc.as<JsonObject>());
}

View File

@@ -591,7 +591,6 @@ void System::send_info_mqtt() {
doc["hostname"] = WiFi.getHostname();
doc["SSID"] = WiFi.SSID();
doc["BSSID"] = WiFi.BSSIDstr();
doc["RSSI"] = WiFi.RSSI();
doc["MAC"] = WiFi.macAddress();
doc["IPv4 address"] = uuid::printable_to_string(WiFi.localIP()) + "/" + uuid::printable_to_string(WiFi.subnetMask());
doc["IPv4 gateway"] = uuid::printable_to_string(WiFi.gatewayIP());
@@ -606,13 +605,19 @@ void System::send_info_mqtt() {
// create the json for heartbeat
void System::heartbeat_json(JsonObject output) {
uint8_t bus_status = EMSESP::bus_status();
if (bus_status == EMSESP::BUS_STATUS_TX_ERRORS) {
switch (EMSESP::bus_status()) {
case EMSESP::BUS_STATUS_OFFLINE:
output["bus_status"] = "connecting"; // EMS-ESP is booting...
break;
case EMSESP::BUS_STATUS_TX_ERRORS:
output["bus_status"] = "txerror";
} else if (bus_status == EMSESP::BUS_STATUS_CONNECTED) {
break;
case EMSESP::BUS_STATUS_CONNECTED:
output["bus_status"] = "connected";
} else {
break;
default:
output["bus_status"] = "disconnected";
break;
}
output["uptime"] = uuid::log::format_timestamp_ms(uuid::get_uptime_ms(), 3);
@@ -736,6 +741,9 @@ void System::system_check() {
static uint8_t last_healthcheck_ = 0;
if (healthcheck_ != last_healthcheck_) {
last_healthcheck_ = healthcheck_;
EMSESP::system_.send_heartbeat(); // send MQTT heartbeat immediately when connected
// see if we're better now
if (healthcheck_ == 0) {
// everything is healthy, show LED permanently on or off depending on setting

View File

@@ -1 +1 @@
#define EMSESP_APP_VERSION "3.6.5-test.14"
#define EMSESP_APP_VERSION "3.6.5-test.15"