mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2026-05-09 15:35:51 +00:00
Compare commits
20 Commits
d18e5b1f14
...
dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
017a7de639 | ||
|
|
7b61429a02 | ||
|
|
fed15f0f96 | ||
|
|
ad5d13168b | ||
|
|
ae5beccb9d | ||
|
|
764c660b14 | ||
|
|
ca0f32b087 | ||
|
|
8ad91de54a | ||
|
|
58da157272 | ||
|
|
b5014bf9ac | ||
|
|
14351436a7 | ||
|
|
469d412951 | ||
|
|
6edbac86e2 | ||
|
|
db2be70d66 | ||
|
|
c36f231990 | ||
|
|
26102121e1 | ||
|
|
8e64c6303e | ||
|
|
74c76eb90b | ||
|
|
daffdcf58e | ||
|
|
4bc4fa903f |
@@ -12,15 +12,16 @@ For more details go to [emsesp.org](https://emsesp.org/).
|
|||||||
- prometheus metrics for temperature/analog/scheduler/custom [#2962](https://github.com/emsesp/EMS-ESP32/issues/2962)
|
- prometheus metrics for temperature/analog/scheduler/custom [#2962](https://github.com/emsesp/EMS-ESP32/issues/2962)
|
||||||
- boiler pumpkick [#2965](https://github.com/emsesp/EMS-ESP32/discussions/2965)
|
- boiler pumpkick [#2965](https://github.com/emsesp/EMS-ESP32/discussions/2965)
|
||||||
- heatpump reset [#2933](https://github.com/emsesp/EMS-ESP32/issues/2933)
|
- heatpump reset [#2933](https://github.com/emsesp/EMS-ESP32/issues/2933)
|
||||||
- e-mail notification using ReadyMail Client
|
|
||||||
- 2.nd freshwater module (dhw4, dhw5) [#2991](https://github.com/emsesp/EMS-ESP32/issues/2991)
|
- 2.nd freshwater module (dhw4, dhw5) [#2991](https://github.com/emsesp/EMS-ESP32/issues/2991)
|
||||||
- full system backup and restore
|
- full system backup and restore
|
||||||
|
- auto-logic to set ht3/ems+ tx-mode
|
||||||
|
|
||||||
## Fixed
|
## Fixed
|
||||||
|
|
||||||
- SRC climate creation [#2936](https://github.com/emsesp/EMS-ESP32/issues/2936) and [#2960](https://github.com/emsesp/EMS-ESP32/issues/2960)
|
- SRC climate creation [#2936](https://github.com/emsesp/EMS-ESP32/issues/2936) and [#2960](https://github.com/emsesp/EMS-ESP32/issues/2960)
|
||||||
- missing translations [#3015](https://github.com/emsesp/EMS-ESP32/issues/3015)
|
- missing translations [#3015](https://github.com/emsesp/EMS-ESP32/issues/3015)
|
||||||
- custom entities check fetch length
|
- custom entities check fetch length
|
||||||
|
- modbus initialization [#3064](https://github.com/emsesp/EMS-ESP32/issues/3064)
|
||||||
|
|
||||||
## Changed
|
## Changed
|
||||||
|
|
||||||
@@ -32,8 +33,8 @@ For more details go to [emsesp.org](https://emsesp.org/).
|
|||||||
- support `minflowtemp` and `baseflowtemp` [#2969](https://github.com/emsesp/EMS-ESP32/discussions/2969)
|
- support `minflowtemp` and `baseflowtemp` [#2969](https://github.com/emsesp/EMS-ESP32/discussions/2969)
|
||||||
- update version if it is 00.00 in first read [#2981](https://github.com/emsesp/EMS-ESP32/issues/2981)
|
- update version if it is 00.00 in first read [#2981](https://github.com/emsesp/EMS-ESP32/issues/2981)
|
||||||
- device class for % values [#2980](https://github.com/emsesp/EMS-ESP32/issues/2980)
|
- device class for % values [#2980](https://github.com/emsesp/EMS-ESP32/issues/2980)
|
||||||
- use tasmota core 2026.03.30
|
|
||||||
- secure mqtt uses ESP_SSLClient
|
|
||||||
- fetch telegrams: set length to fetch [#3017](https://github.com/emsesp/EMS-ESP32/issues/3017)
|
- fetch telegrams: set length to fetch [#3017](https://github.com/emsesp/EMS-ESP32/issues/3017)
|
||||||
- move http client from stack to heap
|
- move http client from stack to heap
|
||||||
- heap optimizations [#3021](https://github.com/emsesp/EMS-ESP32/discussions/3021)
|
- heap optimizations [#3021](https://github.com/emsesp/EMS-ESP32/discussions/3021)
|
||||||
|
- check and read 0x470 as summer2_typeids[0] only if received [#2686](https://github.com/emsesp/EMS-ESP32/issues/2686), [#3055](https://github.com/emsesp/EMS-ESP32/issues/3055)
|
||||||
|
- default bus-id: gateway1(0x49), tx-mode: auto
|
||||||
|
|||||||
2
Makefile
2
Makefile
@@ -47,7 +47,7 @@ MAKEFLAGS += -j$(JOBS) -l$(shell echo $$(($(JOBS) * 2)))
|
|||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
TARGET := emsesp
|
TARGET := emsesp
|
||||||
BUILD := build
|
BUILD := build
|
||||||
SOURCES := src/core src/devices src/web src/test lib_standalone lib/espMqttClient/src lib/espMqttClient/src/* lib/ArduinoJson/src lib/uuid-common/src lib/uuid-console/src lib/uuid-log/src lib/PButton
|
SOURCES := src/core src/devices src/web src/test lib_standalone lib/espMqttClient/src lib/espMqttClient/src/* lib/ArduinoJson/src lib/uuid-common/src lib/uuid-console/src lib/uuid-log/src lib/PButton
|
||||||
INCLUDES := src/core src/devices src/web src/test lib_standalone lib/* lib/espMqttClient/src lib/espMqttClient/src/Transport lib/ArduinoJson/src lib/uuid-common/src lib/uuid-console/src lib/uuid-log/src lib/uuid-telnet/src lib/uuid-syslog/src
|
INCLUDES := src/core src/devices src/web src/test lib_standalone lib/* lib/espMqttClient/src lib/espMqttClient/src/Transport lib/ArduinoJson/src lib/uuid-common/src lib/uuid-console/src lib/uuid-log/src lib/uuid-telnet/src lib/uuid-syslog/src
|
||||||
LIBRARIES :=
|
LIBRARIES :=
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
},
|
},
|
||||||
"core": "esp32",
|
"core": "esp32",
|
||||||
"extra_flags": [
|
"extra_flags": [
|
||||||
"-DNO_TLS_SUPPORT",
|
"-DTASMOTA_SDK",
|
||||||
"-DARDUINO_LOLIN_C3_MINI",
|
"-DARDUINO_LOLIN_C3_MINI",
|
||||||
"-DARDUINO_USB_MODE=1",
|
"-DARDUINO_USB_MODE=1",
|
||||||
"-DARDUINO_USB_CDC_ON_BOOT=1"
|
"-DARDUINO_USB_CDC_ON_BOOT=1"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
"core": "esp32",
|
"core": "esp32",
|
||||||
"extra_flags": [
|
"extra_flags": [
|
||||||
"-DBOARD_HAS_PSRAM",
|
"-DBOARD_HAS_PSRAM",
|
||||||
"-DNO_TLS_SUPPORT",
|
"-DTASMOTA_SDK",
|
||||||
"-DARDUINO_USB_CDC_ON_BOOT=1",
|
"-DARDUINO_USB_CDC_ON_BOOT=1",
|
||||||
"-DARDUINO_USB_MODE=0"
|
"-DARDUINO_USB_MODE=0"
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
"arduino",
|
"arduino",
|
||||||
"espidf"
|
"espidf"
|
||||||
],
|
],
|
||||||
"name": "Tasmota ESP32-S3 32M Flash OPI PSRAM, 4608KB Code/OTA, 2MB FS",
|
"name": "Espressif ESP32-S3 32M Flash OPI PSRAM, 4608KB Code/OTA, 2MB FS",
|
||||||
"upload": {
|
"upload": {
|
||||||
"flash_size": "32MB",
|
"flash_size": "32MB",
|
||||||
"maximum_ram_size": 327680,
|
"maximum_ram_size": 327680,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"build": {
|
"build": {
|
||||||
"core": "esp32",
|
"core": "esp32",
|
||||||
"extra_flags": "-DNO_TLS_SUPPORT",
|
"extra_flags": "-DTASMOTA_SDK",
|
||||||
"f_cpu": "240000000L",
|
"f_cpu": "240000000L",
|
||||||
"f_flash": "40000000L",
|
"f_flash": "40000000L",
|
||||||
"flash_mode": "dio",
|
"flash_mode": "dio",
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
"arduino",
|
"arduino",
|
||||||
"espidf"
|
"espidf"
|
||||||
],
|
],
|
||||||
"name": "Tasmota ESP32 16M Flash, 4608KB Code/OTA, 2MB FS",
|
"name": "Espressif ESP32 16M Flash, 4608KB Code/OTA, 2MB FS",
|
||||||
"upload": {
|
"upload": {
|
||||||
"flash_size": "16MB",
|
"flash_size": "16MB",
|
||||||
"maximum_ram_size": 327680,
|
"maximum_ram_size": 327680,
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
"arduino",
|
"arduino",
|
||||||
"espidf"
|
"espidf"
|
||||||
],
|
],
|
||||||
"name": "Tasmota ESP32 16M Flash DIO PSRAM, 4608KB Code/OTA, 2MB FS",
|
"name": "Espressif ESP32 16M Flash DIO PSRAM, 4608KB Code/OTA, 2MB FS",
|
||||||
"upload": {
|
"upload": {
|
||||||
"flash_size": "16MB",
|
"flash_size": "16MB",
|
||||||
"maximum_ram_size": 327680,
|
"maximum_ram_size": 327680,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"build": {
|
"build": {
|
||||||
"core": "esp32",
|
"core": "esp32",
|
||||||
"extra_flags": "-DNO_TLS_SUPPORT",
|
"extra_flags": "-DTASMOTA_SDK",
|
||||||
"f_cpu": "240000000L",
|
"f_cpu": "240000000L",
|
||||||
"f_flash": "40000000L",
|
"f_flash": "40000000L",
|
||||||
"flash_mode": "dio",
|
"flash_mode": "dio",
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
"build": {
|
"build": {
|
||||||
"core": "esp32",
|
"core": "esp32",
|
||||||
"extra_flags": [
|
"extra_flags": [
|
||||||
"-DNO_TLS_SUPPORT",
|
|
||||||
"-DARDUINO_XIAO_ESP32C6",
|
"-DARDUINO_XIAO_ESP32C6",
|
||||||
"-DARDUINO_USB_MODE=1",
|
"-DARDUINO_USB_MODE=1",
|
||||||
"-DARDUINO_USB_CDC_ON_BOOT=1"
|
"-DARDUINO_USB_CDC_ON_BOOT=1"
|
||||||
|
|||||||
@@ -112,10 +112,10 @@ telegram_type_id,name,is_fetched
|
|||||||
0x02A0,RC300Curves,
|
0x02A0,RC300Curves,
|
||||||
0x02A1,RC300Curves,
|
0x02A1,RC300Curves,
|
||||||
0x02A2,RC300Curves,
|
0x02A2,RC300Curves,
|
||||||
0x02A5,RC300Monitor,fetched
|
0x02A5,RC300Monitor,
|
||||||
0x02A6,CRFMonitor,
|
0x02A6,RC300Monitor,
|
||||||
0x02A7,RC300Monitor,
|
0x02A7,RC300Monitor,
|
||||||
0x02A8,CRFMonitor,
|
0x02A8,RC300Monitor,
|
||||||
0x02A9,RC300Monitor,
|
0x02A9,RC300Monitor,
|
||||||
0x02AA,RC300Monitor,
|
0x02AA,RC300Monitor,
|
||||||
0x02AB,RC300Monitor,
|
0x02AB,RC300Monitor,
|
||||||
@@ -171,6 +171,7 @@ telegram_type_id,name,is_fetched
|
|||||||
0x0468,HPSet,
|
0x0468,HPSet,
|
||||||
0x0469,HPSet,
|
0x0469,HPSet,
|
||||||
0x046A,HPSet,
|
0x046A,HPSet,
|
||||||
|
0x0470,RC300Summer2,fetched
|
||||||
0x0471,RC300Summer2,
|
0x0471,RC300Summer2,
|
||||||
0x0472,RC300Summer2,
|
0x0472,RC300Summer2,
|
||||||
0x0473,RC300Summer2,
|
0x0473,RC300Summer2,
|
||||||
|
|||||||
|
@@ -26,11 +26,11 @@
|
|||||||
"@alova/adapter-xhr": "2.3.1",
|
"@alova/adapter-xhr": "2.3.1",
|
||||||
"@emotion/react": "^11.14.0",
|
"@emotion/react": "^11.14.0",
|
||||||
"@emotion/styled": "^11.14.1",
|
"@emotion/styled": "^11.14.1",
|
||||||
"@mui/icons-material": "^9.0.0",
|
"@mui/icons-material": "^9.0.1",
|
||||||
"@mui/material": "^9.0.0",
|
"@mui/material": "^9.0.1",
|
||||||
"@preact/compat": "^18.3.2",
|
"@preact/compat": "^18.3.2",
|
||||||
"@table-library/react-table-library": "4.1.15",
|
"@table-library/react-table-library": "4.1.15",
|
||||||
"alova": "^3.5.1",
|
"alova": "3.5.1",
|
||||||
"async-validator": "^4.2.5",
|
"async-validator": "^4.2.5",
|
||||||
"etag": "^1.8.1",
|
"etag": "^1.8.1",
|
||||||
"formidable": "^3.5.4",
|
"formidable": "^3.5.4",
|
||||||
@@ -38,10 +38,10 @@
|
|||||||
"magic-string": "^0.30.21",
|
"magic-string": "^0.30.21",
|
||||||
"mime-types": "^3.0.2",
|
"mime-types": "^3.0.2",
|
||||||
"preact": "^10.29.1",
|
"preact": "^10.29.1",
|
||||||
"react": "^19.2.5",
|
"react": "^19.2.6",
|
||||||
"react-dom": "^19.2.5",
|
"react-dom": "^19.2.6",
|
||||||
"react-icons": "^5.6.0",
|
"react-icons": "^5.6.0",
|
||||||
"react-router": "^7.14.2",
|
"react-router": "^7.15.0",
|
||||||
"react-toastify": "^11.1.0",
|
"react-toastify": "^11.1.0",
|
||||||
"typesafe-i18n": "^5.27.1",
|
"typesafe-i18n": "^5.27.1",
|
||||||
"typescript": "^6.0.3"
|
"typescript": "^6.0.3"
|
||||||
@@ -55,16 +55,17 @@
|
|||||||
"@types/node": "^25.6.0",
|
"@types/node": "^25.6.0",
|
||||||
"@types/react": "^19.2.14",
|
"@types/react": "^19.2.14",
|
||||||
"@types/react-dom": "^19.2.3",
|
"@types/react-dom": "^19.2.3",
|
||||||
"axe-core": "^4.11.3",
|
"axe-core": "^4.11.4",
|
||||||
"concurrently": "^9.2.1",
|
"concurrently": "^9.2.1",
|
||||||
"eslint": "^10.2.1",
|
"eslint": "^10.3.0",
|
||||||
"eslint-config-prettier": "^10.1.8",
|
"eslint-config-prettier": "^10.1.8",
|
||||||
"prettier": "^3.8.3",
|
"prettier": "^3.8.3",
|
||||||
"rollup-plugin-visualizer": "^7.0.1",
|
"rollup-plugin-visualizer": "^7.0.1",
|
||||||
"terser": "^5.46.1",
|
"terser": "^5.47.0",
|
||||||
"typescript-eslint": "^8.59.0",
|
"typescript-eslint": "^8.59.2",
|
||||||
"vite": "^8.0.9",
|
"vite": "^8.0.11",
|
||||||
"vite-plugin-imagemin": "^0.6.1"
|
"vite-plugin-imagemin": "^0.6.1",
|
||||||
|
"vite-tsconfig-paths": "^6.1.1"
|
||||||
},
|
},
|
||||||
"packageManager": "pnpm@10.33.1+sha512.05ba3c1d5d1c18f68df06470d74055e62d41fc110a0c660db1b2dfb2785327f04cf0f68345d4609bc52089e7fa0343c31593b2f9594e2c5d5da426230acc9820"
|
"packageManager": "pnpm@10.33.4"
|
||||||
}
|
}
|
||||||
|
|||||||
763
interface/pnpm-lock.yaml
generated
763
interface/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -43,16 +43,6 @@ export interface Settings {
|
|||||||
modbus_port: number;
|
modbus_port: number;
|
||||||
modbus_max_clients: number;
|
modbus_max_clients: number;
|
||||||
modbus_timeout: number;
|
modbus_timeout: number;
|
||||||
email_enabled: boolean;
|
|
||||||
email_ssl?: boolean;
|
|
||||||
email_starttls?: boolean;
|
|
||||||
email_server: string;
|
|
||||||
email_port: number;
|
|
||||||
email_login: string;
|
|
||||||
email_pass: string;
|
|
||||||
email_sender: string;
|
|
||||||
email_recp: string;
|
|
||||||
email_subject: string;
|
|
||||||
developer_mode: boolean;
|
developer_mode: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import {
|
|||||||
FormLoader,
|
FormLoader,
|
||||||
MessageBox,
|
MessageBox,
|
||||||
SectionContent,
|
SectionContent,
|
||||||
ValidatedPasswordField,
|
|
||||||
ValidatedTextField,
|
ValidatedTextField,
|
||||||
useLayoutTitle
|
useLayoutTitle
|
||||||
} from 'components';
|
} from 'components';
|
||||||
@@ -352,156 +351,6 @@ const ApplicationSettings = () => {
|
|||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
)}
|
)}
|
||||||
<Typography color="secondary">eMail</Typography>
|
|
||||||
<BlockFormControlLabel
|
|
||||||
control={
|
|
||||||
<Checkbox
|
|
||||||
checked={data.email_enabled}
|
|
||||||
onChange={updateFormValue}
|
|
||||||
name="email_enabled"
|
|
||||||
disabled={!hardwareData.psram}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
label={
|
|
||||||
<Typography color={!hardwareData.psram ? 'grey' : 'default'}>
|
|
||||||
Enable eMail notification
|
|
||||||
{!hardwareData.psram && (
|
|
||||||
<Typography variant="caption">
|
|
||||||
({LL.IS_REQUIRED('PSRAM')})
|
|
||||||
</Typography>
|
|
||||||
)}
|
|
||||||
</Typography>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
{data.email_enabled && (
|
|
||||||
<>
|
|
||||||
<Grid
|
|
||||||
container
|
|
||||||
spacing={2}
|
|
||||||
direction="row"
|
|
||||||
justifyContent="flex-start"
|
|
||||||
alignItems="flex-start"
|
|
||||||
>
|
|
||||||
<Grid>
|
|
||||||
<ValidatedTextField
|
|
||||||
fieldErrors={fieldErrors || {}}
|
|
||||||
name="email_server"
|
|
||||||
label="SMTP Server"
|
|
||||||
variant="outlined"
|
|
||||||
value={data.email_server}
|
|
||||||
onChange={updateFormValue}
|
|
||||||
margin="normal"
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid>
|
|
||||||
<ValidatedTextField
|
|
||||||
fieldErrors={fieldErrors || {}}
|
|
||||||
sx={{ width: '12ch' }}
|
|
||||||
name="email_port"
|
|
||||||
variant="outlined"
|
|
||||||
label="Port"
|
|
||||||
value={numberValue(data.email_port)}
|
|
||||||
type="number"
|
|
||||||
onChange={updateFormValue}
|
|
||||||
margin="normal"
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid size={4} mt={!data.email_ssl && !data.email_starttls ? 0 : 3}>
|
|
||||||
{!data.email_starttls && (
|
|
||||||
<BlockFormControlLabel
|
|
||||||
sx={{ width: '12ch' }}
|
|
||||||
control={
|
|
||||||
<Checkbox
|
|
||||||
checked={data.email_ssl}
|
|
||||||
onChange={updateFormValue}
|
|
||||||
name="email_ssl"
|
|
||||||
disabled={
|
|
||||||
data.email_starttls || data.email_ssl === undefined
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
label="SSL/TLS"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{!data.email_ssl && (
|
|
||||||
<BlockFormControlLabel
|
|
||||||
sx={{ width: '12ch' }}
|
|
||||||
control={
|
|
||||||
<Checkbox
|
|
||||||
checked={data.email_starttls}
|
|
||||||
onChange={updateFormValue}
|
|
||||||
name="email_starttls"
|
|
||||||
disabled={
|
|
||||||
data.email_ssl || data.email_starttls === undefined
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
label="STARTTLS"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
<Grid container spacing={2} rowSpacing={0}>
|
|
||||||
<Grid>
|
|
||||||
<ValidatedTextField
|
|
||||||
fieldErrors={fieldErrors || {}}
|
|
||||||
name="email_login"
|
|
||||||
label="Login"
|
|
||||||
variant="outlined"
|
|
||||||
value={data.email_login}
|
|
||||||
onChange={updateFormValue}
|
|
||||||
margin="normal"
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid>
|
|
||||||
<ValidatedPasswordField
|
|
||||||
fieldErrors={fieldErrors || {}}
|
|
||||||
name="email_pass"
|
|
||||||
label="Password"
|
|
||||||
variant="outlined"
|
|
||||||
value={data.email_pass}
|
|
||||||
onChange={updateFormValue}
|
|
||||||
margin="normal"
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
<Grid container spacing={2} rowSpacing={0}>
|
|
||||||
<Grid>
|
|
||||||
<ValidatedTextField
|
|
||||||
fieldErrors={fieldErrors || {}}
|
|
||||||
name="email_sender"
|
|
||||||
label="From"
|
|
||||||
variant="outlined"
|
|
||||||
value={data.email_sender}
|
|
||||||
onChange={updateFormValue}
|
|
||||||
margin="normal"
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid>
|
|
||||||
<ValidatedTextField
|
|
||||||
fieldErrors={fieldErrors || {}}
|
|
||||||
name="email_recp"
|
|
||||||
label="To"
|
|
||||||
variant="outlined"
|
|
||||||
value={data.email_recp}
|
|
||||||
onChange={updateFormValue}
|
|
||||||
margin="normal"
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
<Grid>
|
|
||||||
<ValidatedTextField
|
|
||||||
fieldErrors={fieldErrors || {}}
|
|
||||||
name="email_subject"
|
|
||||||
label="Subject"
|
|
||||||
variant="outlined"
|
|
||||||
value={data.email_subject}
|
|
||||||
onChange={updateFormValue}
|
|
||||||
margin="normal"
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
<Typography sx={{ pb: 1, pt: 2 }} variant="h6" color="primary">
|
<Typography sx={{ pb: 1, pt: 2 }} variant="h6" color="primary">
|
||||||
{LL.SENSORS()}
|
{LL.SENSORS()}
|
||||||
</Typography>
|
</Typography>
|
||||||
@@ -828,6 +677,7 @@ const ApplicationSettings = () => {
|
|||||||
<MenuItem value={2}>EMS+</MenuItem>
|
<MenuItem value={2}>EMS+</MenuItem>
|
||||||
<MenuItem value={3}>HT3</MenuItem>
|
<MenuItem value={3}>HT3</MenuItem>
|
||||||
<MenuItem value={4}>{LL.HARDWARE()}</MenuItem>
|
<MenuItem value={4}>{LL.HARDWARE()}</MenuItem>
|
||||||
|
<MenuItem value={5}>Auto</MenuItem>
|
||||||
</TextField>
|
</TextField>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid>
|
<Grid>
|
||||||
|
|||||||
@@ -315,13 +315,22 @@ const InstallDialog = memo(
|
|||||||
fetchDevVersion ? latestDevVersion?.name : latestVersion?.name
|
fetchDevVersion ? latestDevVersion?.name : latestVersion?.name
|
||||||
)}
|
)}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
{upgradeImportantMessageType === 1 && LL.UPGRADE_IMPORTANT_MESSAGES_1()}
|
|
||||||
{upgradeImportantMessageType === 2 && LL.UPGRADE_IMPORTANT_MESSAGES_2()}
|
{upgradeImportantMessageType === 2 && LL.UPGRADE_IMPORTANT_MESSAGES_2()}
|
||||||
|
{upgradeImportantMessageType === 1 && (
|
||||||
|
<>
|
||||||
|
{LL.UPGRADE_IMPORTANT_MESSAGES_1()}
|
||||||
|
<Typography sx={{ mt: 2 }}>
|
||||||
|
<Link to="/settings/downloadUpload" style={{ color: 'lightblue' }}>
|
||||||
|
{LL.DOWNLOAD_SYSTEM_BACKUP()}
|
||||||
|
</Link>
|
||||||
|
</Typography>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
<Typography sx={{ mt: 2 }}>
|
<Typography sx={{ mt: 2 }}>
|
||||||
<Link
|
<Link
|
||||||
target="_blank"
|
|
||||||
to="https://docs.emsesp.org/FAQ#upgrading-the-firmware"
|
to="https://docs.emsesp.org/FAQ#upgrading-the-firmware"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
style={{ color: 'lightblue' }}
|
style={{ color: 'lightblue' }}
|
||||||
>
|
>
|
||||||
{LL.ONLINE_HELP()}
|
{LL.ONLINE_HELP()}
|
||||||
|
|||||||
@@ -49,10 +49,6 @@ the LICENSE file.
|
|||||||
#define EMC_CLIENTID_LENGTH 23 + 1
|
#define EMC_CLIENTID_LENGTH 23 + 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef EMSESP_MQTT_STACKSIZE
|
|
||||||
#define EMC_TASK_STACK_SIZE EMSESP_MQTT_STACKSIZE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef EMC_TASK_STACK_SIZE
|
#ifndef EMC_TASK_STACK_SIZE
|
||||||
#define EMC_TASK_STACK_SIZE 5120
|
#define EMC_TASK_STACK_SIZE 5120
|
||||||
#endif
|
#endif
|
||||||
@@ -70,10 +66,14 @@ the LICENSE file.
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if EMC_USE_MEMPOOL
|
#if EMC_USE_MEMPOOL
|
||||||
#ifndef EMC_NUM_POOL_ELEMENTS
|
#ifndef EMC_NUM_POOL_ELEMENTS
|
||||||
#define EMC_NUM_POOL_ELEMENTS 32
|
#define EMC_NUM_POOL_ELEMENTS 32
|
||||||
#endif
|
#endif
|
||||||
#ifndef EMC_SIZE_POOL_ELEMENTS
|
#ifndef EMC_SIZE_POOL_ELEMENTS
|
||||||
#define EMC_SIZE_POOL_ELEMENTS 128
|
#define EMC_SIZE_POOL_ELEMENTS 128
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef TASMOTA_SDK
|
||||||
|
#define EMC_CLIENT_SECURE
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -62,11 +62,7 @@ MqttClient::MqttClient(espMqttClientTypes::UseInternalTask useInternalTask, uint
|
|||||||
_xSemaphore = xSemaphoreCreateMutex();
|
_xSemaphore = xSemaphoreCreateMutex();
|
||||||
EMC_SEMAPHORE_GIVE(); // release before first use
|
EMC_SEMAPHORE_GIVE(); // release before first use
|
||||||
if (_useInternalTask == espMqttClientTypes::UseInternalTask::YES) {
|
if (_useInternalTask == espMqttClientTypes::UseInternalTask::YES) {
|
||||||
if (core > 1) {
|
xTaskCreatePinnedToCore((TaskFunction_t)_loop, "mqttclient", EMC_TASK_STACK_SIZE, this, priority, &_taskHandle, core);
|
||||||
xTaskCreate((TaskFunction_t)_loop, "mqttclient", EMC_TASK_STACK_SIZE, this, priority, &_taskHandle);
|
|
||||||
} else {
|
|
||||||
xTaskCreatePinnedToCore((TaskFunction_t)_loop, "mqttclient", EMC_TASK_STACK_SIZE, this, priority, &_taskHandle, core);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
(void) useInternalTask;
|
(void) useInternalTask;
|
||||||
@@ -74,7 +70,6 @@ MqttClient::MqttClient(espMqttClientTypes::UseInternalTask useInternalTask, uint
|
|||||||
(void) core;
|
(void) core;
|
||||||
#endif
|
#endif
|
||||||
_clientId = _generatedClientId;
|
_clientId = _generatedClientId;
|
||||||
_core = core;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MqttClient::~MqttClient() {
|
MqttClient::~MqttClient() {
|
||||||
|
|||||||
@@ -69,16 +69,6 @@ class MqttClient {
|
|||||||
const char* getClientId() const;
|
const char* getClientId() const;
|
||||||
size_t queueSize(); // No const because of mutex
|
size_t queueSize(); // No const because of mutex
|
||||||
void loop();
|
void loop();
|
||||||
uint32_t stack() {
|
|
||||||
#ifndef EMSESP_STANDALONE
|
|
||||||
return uxTaskGetStackHighWaterMark(_taskHandle);
|
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
uint8_t core() {
|
|
||||||
return _core;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
explicit MqttClient(espMqttClientTypes::UseInternalTask useInternalTask, uint8_t priority = 1, uint8_t core = 1);
|
explicit MqttClient(espMqttClientTypes::UseInternalTask useInternalTask, uint8_t priority = 1, uint8_t core = 1);
|
||||||
@@ -108,7 +98,6 @@ class MqttClient {
|
|||||||
uint8_t _willQos;
|
uint8_t _willQos;
|
||||||
bool _willRetain;
|
bool _willRetain;
|
||||||
uint32_t _timeout;
|
uint32_t _timeout;
|
||||||
uint8_t _core;
|
|
||||||
|
|
||||||
// state is protected to allow state changes by the transport system, defined in child classes
|
// state is protected to allow state changes by the transport system, defined in child classes
|
||||||
// eg. to allow AsyncTCP
|
// eg. to allow AsyncTCP
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ the LICENSE file.
|
|||||||
|
|
||||||
#include "ClientPosix.h"
|
#include "ClientPosix.h"
|
||||||
|
|
||||||
#if defined(__linux__) || defined(__APPLE__)
|
#if defined(__linux__)
|
||||||
|
|
||||||
namespace espMqttClientInternals {
|
namespace espMqttClientInternals {
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ the LICENSE file.
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#if defined(__linux__) || defined(__APPLE__)
|
#if defined(__linux__)
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|||||||
@@ -6,65 +6,66 @@ For a copy, see <https://opensource.org/licenses/MIT> or
|
|||||||
the LICENSE file.
|
the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef NO_TLS_SUPPORT
|
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
|
||||||
|
|
||||||
#include "ClientSecureSync.h"
|
#include "ClientSecureSync.h"
|
||||||
#include <lwip/sockets.h>
|
#include <lwip/sockets.h> // socket options
|
||||||
#include "../Config.h"
|
|
||||||
|
|
||||||
namespace espMqttClientInternals {
|
namespace espMqttClientInternals {
|
||||||
|
|
||||||
ClientSecureSync::ClientSecureSync()
|
ClientSecureSync::ClientSecureSync()
|
||||||
: client() {
|
: client() {
|
||||||
client.setClient(&basic_client, true);
|
// empty
|
||||||
client.setBufferSizes(EMC_RX_BUFFER_SIZE, EMC_TX_BUFFER_SIZE);
|
|
||||||
client.setSessionTimeout(120); // Set the timeout in seconds (>=120 seconds)
|
|
||||||
}
|
|
||||||
|
|
||||||
ClientSecureSync::~ClientSecureSync() {
|
|
||||||
stop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClientSecureSync::connect(IPAddress ip, uint16_t port) {
|
bool ClientSecureSync::connect(IPAddress ip, uint16_t port) {
|
||||||
bool ret = client.connect(ip, port); // implicit conversion of return code int --> bool
|
bool ret = client.connect(ip, port); // implicit conversion of return code int --> bool
|
||||||
if (ret) {
|
if (ret) {
|
||||||
// Set TCP option directly to bypass lack of working setNoDelay for WiFiClientSecure
|
#if defined(ARDUINO_ARCH_ESP8266)
|
||||||
int val = true;
|
client.setNoDelay(true);
|
||||||
basic_client.setSocketOption(IPPROTO_TCP, TCP_NODELAY, &val, sizeof(int));
|
#elif defined(ARDUINO_ARCH_ESP32)
|
||||||
}
|
// Set TCP option directly to bypass lack of working setNoDelay for WiFiClientSecure
|
||||||
return ret;
|
int val = true;
|
||||||
|
client.setSocketOption(IPPROTO_TCP, TCP_NODELAY, &val, sizeof(int));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClientSecureSync::connect(const char * host, uint16_t port) {
|
bool ClientSecureSync::connect(const char* host, uint16_t port) {
|
||||||
bool ret = client.connect(host, port); // implicit conversion of return code int --> bool
|
bool ret = client.connect(host, port); // implicit conversion of return code int --> bool
|
||||||
if (ret) {
|
if (ret) {
|
||||||
// Set TCP option directly to bypass lack of working setNoDelay for WiFiClientSecure
|
#if defined(ARDUINO_ARCH_ESP8266)
|
||||||
int val = true;
|
client.setNoDelay(true);
|
||||||
basic_client.setSocketOption(IPPROTO_TCP, TCP_NODELAY, &val, sizeof(int));
|
#elif defined(ARDUINO_ARCH_ESP32)
|
||||||
}
|
// Set TCP option directly to bypass lack of working setNoDelay for WiFiClientSecure
|
||||||
return ret;
|
int val = true;
|
||||||
|
client.setSocketOption(IPPROTO_TCP, TCP_NODELAY, &val, sizeof(int));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ClientSecureSync::write(const uint8_t * buf, size_t size) {
|
size_t ClientSecureSync::write(const uint8_t* buf, size_t size) {
|
||||||
return client.write(buf, size);
|
return client.write(buf, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ClientSecureSync::read(uint8_t * buf, size_t size) {
|
int ClientSecureSync::read(uint8_t* buf, size_t size) {
|
||||||
return client.read(buf, size);
|
return client.read(buf, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientSecureSync::stop() {
|
void ClientSecureSync::stop() {
|
||||||
client.stop();
|
client.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClientSecureSync::connected() {
|
bool ClientSecureSync::connected() {
|
||||||
return client.connected();
|
return client.connected();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ClientSecureSync::disconnected() {
|
bool ClientSecureSync::disconnected() {
|
||||||
return !client.connected();
|
return !client.connected();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace espMqttClientInternals
|
} // namespace espMqttClientInternals
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -8,11 +8,15 @@ the LICENSE file.
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifndef NO_TLS_SUPPORT
|
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
|
||||||
|
|
||||||
// #include "esp_tls.h"
|
// Added for EMS-ESP
|
||||||
|
#include "../Config.h"
|
||||||
|
#if defined(EMC_CLIENT_SECURE)
|
||||||
|
#include <WiFiClientSecure.h> // includes IPAddress
|
||||||
|
#else
|
||||||
#include <WiFiClient.h>
|
#include <WiFiClient.h>
|
||||||
#include <ESP_SSLClient.h>
|
#endif
|
||||||
#include "Transport.h"
|
#include "Transport.h"
|
||||||
|
|
||||||
namespace espMqttClientInternals {
|
namespace espMqttClientInternals {
|
||||||
@@ -20,7 +24,6 @@ namespace espMqttClientInternals {
|
|||||||
class ClientSecureSync : public Transport {
|
class ClientSecureSync : public Transport {
|
||||||
public:
|
public:
|
||||||
ClientSecureSync();
|
ClientSecureSync();
|
||||||
~ClientSecureSync();
|
|
||||||
bool connect(IPAddress ip, uint16_t port) override;
|
bool connect(IPAddress ip, uint16_t port) override;
|
||||||
bool connect(const char * host, uint16_t port) override;
|
bool connect(const char * host, uint16_t port) override;
|
||||||
size_t write(const uint8_t * buf, size_t size) override;
|
size_t write(const uint8_t * buf, size_t size) override;
|
||||||
@@ -28,9 +31,12 @@ class ClientSecureSync : public Transport {
|
|||||||
void stop() override;
|
void stop() override;
|
||||||
bool connected() override;
|
bool connected() override;
|
||||||
bool disconnected() override;
|
bool disconnected() override;
|
||||||
|
// added for EMS-ESP
|
||||||
WiFiClient basic_client;
|
#if defined(EMC_CLIENT_SECURE)
|
||||||
ESP_SSLClient client;
|
WiFiClientSecure client;
|
||||||
|
#else
|
||||||
|
WiFiClient client;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace espMqttClientInternals
|
} // namespace espMqttClientInternals
|
||||||
|
|||||||
@@ -8,6 +8,50 @@ the LICENSE file.
|
|||||||
|
|
||||||
#include "espMqttClient.h"
|
#include "espMqttClient.h"
|
||||||
|
|
||||||
|
#if defined(ARDUINO_ARCH_ESP8266)
|
||||||
|
espMqttClient::espMqttClient()
|
||||||
|
: MqttClientSetup(espMqttClientTypes::UseInternalTask::NO)
|
||||||
|
, _client() {
|
||||||
|
_transport = &_client;
|
||||||
|
}
|
||||||
|
|
||||||
|
espMqttClientSecure::espMqttClientSecure()
|
||||||
|
: MqttClientSetup(espMqttClientTypes::UseInternalTask::NO)
|
||||||
|
, _client() {
|
||||||
|
_transport = &_client;
|
||||||
|
}
|
||||||
|
|
||||||
|
espMqttClientSecure & espMqttClientSecure::setInsecure() {
|
||||||
|
_client.client.setInsecure();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
espMqttClientSecure & espMqttClientSecure::setFingerprint(const uint8_t fingerprint[20]) {
|
||||||
|
_client.client.setFingerprint(fingerprint);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
espMqttClientSecure & espMqttClientSecure::setTrustAnchors(const X509List * ta) {
|
||||||
|
_client.client.setTrustAnchors(ta);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
espMqttClientSecure & espMqttClientSecure::setClientRSACert(const X509List * cert, const PrivateKey * sk) {
|
||||||
|
_client.client.setClientRSACert(cert, sk);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
espMqttClientSecure & espMqttClientSecure::setClientECCert(const X509List * cert, const PrivateKey * sk, unsigned allowed_usages, unsigned cert_issuer_key_type) {
|
||||||
|
_client.client.setClientECCert(cert, sk, allowed_usages, cert_issuer_key_type);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
espMqttClientSecure & espMqttClientSecure::setCertStore(CertStoreBase * certStore) {
|
||||||
|
_client.client.setCertStore(certStore);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(ARDUINO_ARCH_ESP32)
|
#if defined(ARDUINO_ARCH_ESP32)
|
||||||
espMqttClient::espMqttClient(espMqttClientTypes::UseInternalTask useInternalTask)
|
espMqttClient::espMqttClient(espMqttClientTypes::UseInternalTask useInternalTask)
|
||||||
: MqttClientSetup(useInternalTask)
|
: MqttClientSetup(useInternalTask)
|
||||||
@@ -34,45 +78,51 @@ espMqttClientSecure::espMqttClientSecure(uint8_t priority, uint8_t core)
|
|||||||
}
|
}
|
||||||
|
|
||||||
espMqttClientSecure & espMqttClientSecure::setInsecure() {
|
espMqttClientSecure & espMqttClientSecure::setInsecure() {
|
||||||
#ifndef NO_TLS_SUPPORT
|
#if defined(EMC_CLIENT_SECURE)
|
||||||
_client.client.setInsecure();
|
_client.client.setInsecure();
|
||||||
#endif
|
#endif
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
espMqttClientSecure & espMqttClientSecure::setCACert(const char * rootCA) {
|
espMqttClientSecure & espMqttClientSecure::setCACert(const char * rootCA) {
|
||||||
#ifndef NO_TLS_SUPPORT
|
#if defined(EMC_CLIENT_SECURE)
|
||||||
_client.client.setCACert(rootCA);
|
_client.client.setCACert(rootCA);
|
||||||
#endif
|
#endif
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
espMqttClientSecure & espMqttClientSecure::setCertificate(const char * clientCa) {
|
espMqttClientSecure & espMqttClientSecure::setCertificate(const char * clientCa) {
|
||||||
#ifndef NO_TLS_SUPPORT
|
#if defined(EMC_CLIENT_SECURE)
|
||||||
_client.client.setCertificate(clientCa);
|
_client.client.setCertificate(clientCa);
|
||||||
#endif
|
#endif
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
espMqttClientSecure & espMqttClientSecure::setPrivateKey(const char * privateKey) {
|
espMqttClientSecure & espMqttClientSecure::setPrivateKey(const char * privateKey) {
|
||||||
#ifndef NO_TLS_SUPPORT
|
#if defined(EMC_CLIENT_SECURE)
|
||||||
_client.client.setPrivateKey(privateKey);
|
_client.client.setPrivateKey(privateKey);
|
||||||
#endif
|
#endif
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
espMqttClientSecure & espMqttClientSecure::setPreSharedKey(const char * pskIdent, const char * psKey) {
|
espMqttClientSecure & espMqttClientSecure::setPreSharedKey(const char * pskIdent, const char * psKey) {
|
||||||
#ifndef NO_TLS_SUPPORT
|
#if defined(EMC_CLIENT_SECURE)
|
||||||
|
_client.client.setPreSharedKey(pskIdent, psKey);
|
||||||
#endif
|
#endif
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__linux__) || defined(__APPLE__)
|
#if defined(__linux__)
|
||||||
espMqttClient::espMqttClient()
|
espMqttClient::espMqttClient()
|
||||||
: MqttClientSetup(espMqttClientTypes::UseInternalTask::NO)
|
: MqttClientSetup(espMqttClientTypes::UseInternalTask::NO)
|
||||||
, _client() {
|
, _client() {
|
||||||
_transport = &_client;
|
_transport = &_client;
|
||||||
}
|
}
|
||||||
|
#elif defined(_WIN32) || defined(__APPLE__)
|
||||||
|
// Windows
|
||||||
|
espMqttClient::espMqttClient()
|
||||||
|
: MqttClientSetup(espMqttClientTypes::UseInternalTask::NO) {
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ the LICENSE file.
|
|||||||
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
|
#if defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
|
||||||
#include "Transport/ClientSync.h"
|
#include "Transport/ClientSync.h"
|
||||||
#include "Transport/ClientSecureSync.h"
|
#include "Transport/ClientSecureSync.h"
|
||||||
#elif defined(__linux__) || defined(__APPLE__)
|
#elif defined(__linux__)
|
||||||
#include "Transport/ClientPosix.h"
|
#include "Transport/ClientPosix.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -65,16 +65,10 @@ class espMqttClientSecure : public MqttClientSetup<espMqttClientSecure> {
|
|||||||
espMqttClientSecure & setPreSharedKey(const char * pskIdent, const char * psKey);
|
espMqttClientSecure & setPreSharedKey(const char * pskIdent, const char * psKey);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
#ifndef NO_TLS_SUPPORT
|
|
||||||
espMqttClientInternals::ClientSecureSync _client;
|
espMqttClientInternals::ClientSecureSync _client;
|
||||||
#else
|
|
||||||
espMqttClientInternals::ClientSync _client;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#elif defined(__linux__)
|
||||||
|
|
||||||
#if defined(__linux__) || defined(__APPLE__)
|
|
||||||
class espMqttClient : public MqttClientSetup<espMqttClient> {
|
class espMqttClient : public MqttClientSetup<espMqttClient> {
|
||||||
public:
|
public:
|
||||||
espMqttClient();
|
espMqttClient();
|
||||||
@@ -82,4 +76,10 @@ class espMqttClient : public MqttClientSetup<espMqttClient> {
|
|||||||
protected:
|
protected:
|
||||||
espMqttClientInternals::ClientPosix _client;
|
espMqttClientInternals::ClientPosix _client;
|
||||||
};
|
};
|
||||||
|
#elif defined(_WIN32) || defined(__APPLE__)
|
||||||
|
class espMqttClient : public MqttClientSetup<espMqttClient> {
|
||||||
|
public:
|
||||||
|
espMqttClient();
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -22,10 +22,11 @@
|
|||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
|
|
||||||
#define EMS_TXMODE_OFF 0
|
#define EMS_TXMODE_OFF 0
|
||||||
#define EMS_TXMODE_DEFAULT 1
|
#define EMS_TXMODE_EMS 1
|
||||||
#define EMS_TXMODE_EMSPLUS 2
|
#define EMS_TXMODE_EMSPLUS 2
|
||||||
#define EMS_TXMODE_HT3 3
|
#define EMS_TXMODE_HT3 3
|
||||||
#define EMS_TXMODE_HW 4
|
#define EMS_TXMODE_HW 4
|
||||||
|
#define EMS_TXMODE_AUTO 5
|
||||||
|
|
||||||
namespace emsesp {
|
namespace emsesp {
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ extra_configs =
|
|||||||
pio_local.ini
|
pio_local.ini
|
||||||
|
|
||||||
[common]
|
[common]
|
||||||
core_build_flags = -std=gnu++20 -O3 -flto=auto -Wno-type-limits -Wall -Wextra -Wno-unused-parameter -Wno-unused-variable -Wno-format -Wno-missing-field-initializers
|
core_build_flags = -std=gnu++2a -O3 -flto=auto -Wno-type-limits -Wall -Wextra -Wno-unused-parameter -Wno-unused-variable -Wno-format -Wno-missing-field-initializers
|
||||||
core_unbuild_flags = -std=gnu++11 -std=gnu++14 -std=gnu++17 -fno-lto
|
core_unbuild_flags = -std=gnu++11 -std=gnu++14 -std=gnu++17 -fno-lto
|
||||||
|
|
||||||
my_build_flags =
|
my_build_flags =
|
||||||
@@ -53,21 +53,13 @@ build_flags =
|
|||||||
unbuild_flags =
|
unbuild_flags =
|
||||||
${common.core_unbuild_flags}
|
${common.core_unbuild_flags}
|
||||||
|
|
||||||
; 4MB Flash variants
|
|
||||||
[espressif32_base_4M]
|
|
||||||
framework = arduino
|
|
||||||
board_build.partitions = partitions/esp32_partition_4M.csv
|
|
||||||
board_upload.flash_size = 4MB
|
|
||||||
board_build.app_partition_name = app0
|
|
||||||
platform = https://github.com/tasmota/platform-espressif32/releases/download/2026.04.50/platform-espressif32.zip ; Platform 2026.04.50 Tasmota Arduino Core 3.3.8 based on IDF 5.5.4.260407
|
|
||||||
|
|
||||||
; 16MB Flash variants
|
; 16MB Flash variants
|
||||||
[espressif32_base_16M]
|
[espressif32_base_16M]
|
||||||
framework = arduino
|
framework = arduino
|
||||||
board_build.partitions = partitions/esp32_partition_16M.csv
|
board_build.partitions = partitions/esp32_partition_16M.csv
|
||||||
board_upload.flash_size = 16MB
|
board_upload.flash_size = 16MB
|
||||||
board_build.app_partition_name = app0
|
board_build.app_partition_name = app0
|
||||||
platform = https://github.com/tasmota/platform-espressif32/releases/download/2026.04.50/platform-espressif32.zip ; Platform 2026.04.50 Tasmota Arduino Core 3.3.8 based on IDF 5.5.4.260407
|
platform = espressif32@7.0.0 ; Arduino Core 2.0.17 / IDF 4.4.7
|
||||||
|
|
||||||
; 32MB Flash variants
|
; 32MB Flash variants
|
||||||
[espressif32_base_32M]
|
[espressif32_base_32M]
|
||||||
@@ -75,7 +67,29 @@ framework = arduino
|
|||||||
board_build.partitions = partitions/esp32_partition_32M.csv
|
board_build.partitions = partitions/esp32_partition_32M.csv
|
||||||
board_upload.flash_size = 32MB
|
board_upload.flash_size = 32MB
|
||||||
board_build.app_partition_name = app0
|
board_build.app_partition_name = app0
|
||||||
platform = https://github.com/tasmota/platform-espressif32/releases/download/2026.04.50/platform-espressif32.zip ; Platform 2026.04.50 Tasmota Arduino Core 3.3.8 based on IDF 5.5.4.260407
|
platform = espressif32@7.0.0 ; Arduino Core 2.0.17 / IDF 4.4.7
|
||||||
|
|
||||||
|
; use Tasmota's library for 4MB Flash variants.
|
||||||
|
; Removes libs (like mbedtsl, so no WiFi_secure.h) to increase available heap
|
||||||
|
[espressif32_base_T_4M]
|
||||||
|
framework = arduino
|
||||||
|
board_build.partitions = partitions/esp32_partition_4M.csv
|
||||||
|
board_upload.flash_size = 4MB
|
||||||
|
board_build.app_partition_name = app0
|
||||||
|
platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.06.00/platform-espressif32.zip ; Arduino Core 2.0.18 with IPv6 support, based on IDF 4.4.8
|
||||||
|
; Tasmota Arduino Core 3.1.3.250302 based on IDF 5.3.2.250228
|
||||||
|
; platform = https://github.com/tasmota/platform-espressif32/releases/download/2025.03.30/platform-espressif32.zip
|
||||||
|
|
||||||
|
; use Tasmota's library for 16MB Flash variants.
|
||||||
|
; Removes libs (like mbedtsl, so no WiFi_secure.h) to increase available heap
|
||||||
|
[espressif32_base_T_16M]
|
||||||
|
framework = arduino
|
||||||
|
board_build.partitions = partitions/esp32_partition_16M.csv
|
||||||
|
board_upload.flash_size = 16MB
|
||||||
|
board_build.app_partition_name = app0
|
||||||
|
platform = https://github.com/tasmota/platform-espressif32/releases/download/2024.06.00/platform-espressif32.zip ; Arduino Core 2.0.18 with IPv6 support, based on IDF 4.4.8
|
||||||
|
; Tasmota Arduino Core 3.1.3.250302 based on IDF 5.3.2.250228
|
||||||
|
; platform = https://github.com/tasmota/platform-espressif32/releases/download/2025.03.30/platform-espressif32.zip
|
||||||
|
|
||||||
[env]
|
[env]
|
||||||
build_flags =
|
build_flags =
|
||||||
@@ -91,9 +105,7 @@ board_build.filesystem = littlefs
|
|||||||
lib_deps =
|
lib_deps =
|
||||||
bblanchon/ArduinoJson @ 7.4.3
|
bblanchon/ArduinoJson @ 7.4.3
|
||||||
ESP32Async/AsyncTCP @ 3.4.10
|
ESP32Async/AsyncTCP @ 3.4.10
|
||||||
ESP32Async/ESPAsyncWebServer @ 3.10.3
|
ESP32Async/ESPAsyncWebServer @ 3.11.0
|
||||||
https://github.com/mobizt/ReadyMail.git @ 0.4.0
|
|
||||||
https://github.com/mobizt/ESP_SSLClient.git @ 3.1.3
|
|
||||||
; https://github.com/emsesp/EMS-ESP-Modules.git @ 1.0.8
|
; https://github.com/emsesp/EMS-ESP-Modules.git @ 1.0.8
|
||||||
|
|
||||||
; builds the web interface only, not the firmware
|
; builds the web interface only, not the firmware
|
||||||
@@ -106,17 +118,18 @@ build_src_filter = -<*>
|
|||||||
|
|
||||||
;
|
;
|
||||||
; Builds for different board types
|
; Builds for different board types
|
||||||
|
; We use Tasmota for boards without PSRAM as this framework has mbedtls removed to save memory.
|
||||||
; If you're building for a single target environment, we recommend creating a pio_local.ini (see example file)
|
; If you're building for a single target environment, we recommend creating a pio_local.ini (see example file)
|
||||||
;
|
;
|
||||||
|
|
||||||
[env:s_4M]
|
[env:s_4M]
|
||||||
; 4MB ESP32 - no SSL, no PSRAM - like a BBQKees older S32 and E32 models
|
; 4MB ESP32 - no SSL, no PSRAM - like a BBQKees older S32 and E32 models - uses Tasmota
|
||||||
extends = espressif32_base_4M
|
extends = espressif32_base_T_4M
|
||||||
board = s_4M
|
board = s_4M
|
||||||
|
|
||||||
[env:s_16M]
|
[env:s_16M]
|
||||||
; 16MB ESP32 - no PSRAM - like a BBQKees later S32 V2 models
|
; 16MB ESP32 - no PSRAM - like a BBQKees later S32 V2 models - uses Tasmota
|
||||||
extends = espressif32_base_16M
|
extends = espressif32_base_T_16M
|
||||||
board = s_16M
|
board = s_16M
|
||||||
|
|
||||||
[env:s_16M_P]
|
[env:s_16M_P]
|
||||||
@@ -135,30 +148,24 @@ extends = espressif32_base_32M
|
|||||||
board = s3_32M_P
|
board = s3_32M_P
|
||||||
|
|
||||||
[env:s2_4M_P]
|
[env:s2_4M_P]
|
||||||
; based on lolin_s2_mini 4MB with 2MB PSRAM
|
; based on lolin_s2_mini 4MB with 2MB PSRAM - uses Tasmota
|
||||||
extends = espressif32_base_4M
|
extends = espressif32_base_T_4M
|
||||||
board = s2_4M_P
|
board = s2_4M_P
|
||||||
|
|
||||||
[env:c3_mini_4M]
|
[env:c3_mini_4M]
|
||||||
; based on lolin_c3_mini 4MB, no PSRAM
|
; based on lolin_c3_mini 4MB, no PSRAM - uses Tasmota
|
||||||
extends = espressif32_base_4M
|
extends = espressif32_base_T_4M
|
||||||
board = c3_mini_4M
|
board = c3_mini_4M
|
||||||
|
|
||||||
; lolin C3 mini v1 needs special wifi initialization
|
; lolin C3 mini v1 needs special wifi initialization
|
||||||
; https://www.wemos.cc/en/latest/c3/c3_mini_1_0_0.html#about-wifi
|
; https://www.wemos.cc/en/latest/c3/c3_mini_1_0_0.html#about-wifi
|
||||||
[env:c3_miniv1_4M]
|
[env:c3_miniv1_4M]
|
||||||
extends = espressif32_base_4M
|
extends = espressif32_base_T_4M
|
||||||
board = c3_mini_4M
|
board = c3_mini_4M
|
||||||
build_flags =
|
build_flags =
|
||||||
${common.build_flags}
|
${common.build_flags}
|
||||||
-DBOARD_C3_MINI_V1
|
-DBOARD_C3_MINI_V1
|
||||||
|
|
||||||
; XIAO ESP32C - 512KB SRAM & 4MB Flash - https://wiki.seeedstudio.com/xiao_esp32c6_getting_started/
|
|
||||||
[env:c6_xiao_4M]
|
|
||||||
extends = espressif32_base_4M
|
|
||||||
board_build.app_partition_name = app0
|
|
||||||
board = seeed_xiao_esp32c6
|
|
||||||
|
|
||||||
; foundation for building and testing natively, standalone without an ESP32
|
; foundation for building and testing natively, standalone without an ESP32
|
||||||
; use the `standalone` environment instead of `native` for testing
|
; use the `standalone` environment instead of `native` for testing
|
||||||
[env:native]
|
[env:native]
|
||||||
@@ -168,8 +175,7 @@ build_flags =
|
|||||||
build_src_flags =
|
build_src_flags =
|
||||||
-DEMSESP_STANDALONE -DEMSESP_TEST
|
-DEMSESP_STANDALONE -DEMSESP_TEST
|
||||||
-DARDUINOJSON_ENABLE_ARDUINO_STRING=1
|
-DARDUINOJSON_ENABLE_ARDUINO_STRING=1
|
||||||
-DNO_TLS_SUPPORT
|
-std=gnu++2a -Og -ggdb
|
||||||
-std=gnu++20 -Og -ggdb
|
|
||||||
-Wall -Wextra
|
-Wall -Wextra
|
||||||
-Wno-unused-parameter -Wno-sign-compare -Wno-missing-braces
|
-Wno-unused-parameter -Wno-sign-compare -Wno-missing-braces
|
||||||
-Wno-vla-cxx-extension -Wno-tautological-constant-out-of-range-compare
|
-Wno-vla-cxx-extension -Wno-tautological-constant-out-of-range-compare
|
||||||
@@ -207,9 +213,8 @@ build_src_flags =
|
|||||||
-DEMSESP_STANDALONE -DEMSESP_TEST
|
-DEMSESP_STANDALONE -DEMSESP_TEST
|
||||||
-DEMSESP_UNITY
|
-DEMSESP_UNITY
|
||||||
-DARDUINOJSON_ENABLE_ARDUINO_STRING=1
|
-DARDUINOJSON_ENABLE_ARDUINO_STRING=1
|
||||||
-DNO_TLS_SUPPORT
|
|
||||||
-DEMSESP_DEFAULT_LOCALE=\"en\" -DEMSESP_DEFAULT_BOARD_PROFILE=\"S32\"
|
-DEMSESP_DEFAULT_LOCALE=\"en\" -DEMSESP_DEFAULT_BOARD_PROFILE=\"S32\"
|
||||||
-std=gnu++20 -Og -ggdb
|
-std=gnu++2a -Og -ggdb
|
||||||
-Wall -Wextra
|
-Wall -Wextra
|
||||||
-Wno-unused-parameter -Wno-sign-compare -Wno-missing-braces
|
-Wno-unused-parameter -Wno-sign-compare -Wno-missing-braces
|
||||||
-Wno-vla-cxx-extension -Wno-tautological-constant-out-of-range-compare
|
-Wno-vla-cxx-extension -Wno-tautological-constant-out-of-range-compare
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ APSettingsService::APSettingsService(AsyncWebServer * server, FS * fs, SecurityM
|
|||||||
, _reconfigureAp(false)
|
, _reconfigureAp(false)
|
||||||
, _connected(0) {
|
, _connected(0) {
|
||||||
addUpdateHandler([this] { reconfigureAP(); }, false);
|
addUpdateHandler([this] { reconfigureAP(); }, false);
|
||||||
|
WiFi.onEvent([this](WiFiEvent_t event, WiFiEventInfo_t info) { WiFiEvent(event); });
|
||||||
}
|
}
|
||||||
|
|
||||||
void APSettingsService::begin() {
|
void APSettingsService::begin() {
|
||||||
@@ -18,27 +19,39 @@ void APSettingsService::begin() {
|
|||||||
// reconfigureAP();
|
// reconfigureAP();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// wait 10 sec on STA disconnect before starting AP
|
||||||
|
void APSettingsService::WiFiEvent(WiFiEvent_t event) {
|
||||||
|
const uint8_t was_connected = _connected;
|
||||||
|
switch (event) {
|
||||||
|
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
|
||||||
|
_connected &= ~1U;
|
||||||
|
break;
|
||||||
|
case ARDUINO_EVENT_ETH_DISCONNECTED:
|
||||||
|
_connected &= ~2U;
|
||||||
|
break;
|
||||||
|
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
|
||||||
|
case ARDUINO_EVENT_WIFI_STA_GOT_IP6:
|
||||||
|
_connected |= 1U;
|
||||||
|
break;
|
||||||
|
case ARDUINO_EVENT_ETH_GOT_IP:
|
||||||
|
case ARDUINO_EVENT_ETH_GOT_IP6:
|
||||||
|
_connected |= 2U;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// wait 10 sec before starting AP
|
||||||
|
if (was_connected && !_connected) {
|
||||||
|
_lastManaged = uuid::get_uptime();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void APSettingsService::reconfigureAP() {
|
void APSettingsService::reconfigureAP() {
|
||||||
_lastManaged = uuid::get_uptime() - MANAGE_NETWORK_DELAY;
|
_lastManaged = uuid::get_uptime() - MANAGE_NETWORK_DELAY;
|
||||||
_reconfigureAp = true;
|
_reconfigureAp = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void APSettingsService::loop() {
|
void APSettingsService::loop() {
|
||||||
const uint8_t was_connected = _connected;
|
|
||||||
if (WiFi.isConnected()) {
|
|
||||||
_connected |= 1U;
|
|
||||||
} else {
|
|
||||||
_connected &= ~1U;
|
|
||||||
}
|
|
||||||
if (ETH.connected()) {
|
|
||||||
_connected |= 2U;
|
|
||||||
} else {
|
|
||||||
_connected &= ~2U;
|
|
||||||
}
|
|
||||||
// wait 10 sec before starting AP
|
|
||||||
if (was_connected && !_connected) {
|
|
||||||
_lastManaged = uuid::get_uptime();
|
|
||||||
}
|
|
||||||
const unsigned long currentMillis = uuid::get_uptime();
|
const unsigned long currentMillis = uuid::get_uptime();
|
||||||
if ((currentMillis - _lastManaged) >= MANAGE_NETWORK_DELAY) {
|
if ((currentMillis - _lastManaged) >= MANAGE_NETWORK_DELAY) {
|
||||||
_lastManaged = currentMillis;
|
_lastManaged = currentMillis;
|
||||||
@@ -63,7 +76,11 @@ void APSettingsService::manageAP() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void APSettingsService::startAP() {
|
void APSettingsService::startAP() {
|
||||||
|
#if ESP_IDF_VERSION_MAJOR < 5
|
||||||
|
WiFi.softAPenableIpV6(); // force IPV6, same as for WiFi - fixes https://github.com/emsesp/EMS-ESP32/issues/1922
|
||||||
|
#else
|
||||||
WiFi.softAPenableIPv6(); // force IPV6, same as for WiFi - fixes https://github.com/emsesp/EMS-ESP32/issues/1922
|
WiFi.softAPenableIPv6(); // force IPV6, same as for WiFi - fixes https://github.com/emsesp/EMS-ESP32/issues/1922
|
||||||
|
#endif
|
||||||
WiFi.softAPConfig(_state.localIP, _state.gatewayIP, _state.subnetMask);
|
WiFi.softAPConfig(_state.localIP, _state.gatewayIP, _state.subnetMask);
|
||||||
esp_wifi_set_bandwidth(static_cast<wifi_interface_t>(ESP_IF_WIFI_AP), WIFI_BW_HT20);
|
esp_wifi_set_bandwidth(static_cast<wifi_interface_t>(ESP_IF_WIFI_AP), WIFI_BW_HT20);
|
||||||
WiFi.softAP(_state.ssid.c_str(), _state.password.c_str(), _state.channel, _state.ssidHidden, _state.maxClients);
|
WiFi.softAP(_state.ssid.c_str(), _state.password.c_str(), _state.channel, _state.ssidHidden, _state.maxClients);
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ class APSettingsService : public StatefulService<APSettings> {
|
|||||||
void startAP();
|
void startAP();
|
||||||
void stopAP();
|
void stopAP();
|
||||||
void handleDNS();
|
void handleDNS();
|
||||||
|
void WiFiEvent(WiFiEvent_t event);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
static constexpr const char CACHE_CONTROL[] = "public,max-age=60";
|
static constexpr const char CACHE_CONTROL[] = "public,max-age=60";
|
||||||
|
|
||||||
// Single static-content handler serving all assets embedded in WWWData.h
|
// Single static-content handler serving all assets embedded in WWWData.h.
|
||||||
class StaticContentHandler : public AsyncWebHandler {
|
class StaticContentHandler : public AsyncWebHandler {
|
||||||
public:
|
public:
|
||||||
bool canHandle(AsyncWebServerRequest * request) const override {
|
bool canHandle(AsyncWebServerRequest * request) const override {
|
||||||
@@ -15,7 +15,8 @@ class StaticContentHandler : public AsyncWebHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void handleRequest(AsyncWebServerRequest * request) override {
|
void handleRequest(AsyncWebServerRequest * request) override {
|
||||||
// OPTIONS is handled generically - the server-level CORS headers are attached via DefaultHeaders in ESP32React::begin().
|
// OPTIONS is handled generically - the server-level CORS headers are
|
||||||
|
// attached via DefaultHeaders in ESP32React::begin().
|
||||||
if (request->method() == HTTP_OPTIONS) {
|
if (request->method() == HTTP_OPTIONS) {
|
||||||
request->send(200);
|
request->send(200);
|
||||||
return;
|
return;
|
||||||
@@ -56,7 +57,8 @@ class StaticContentHandler : public AsyncWebHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns the /index.html asset, used as the SPA fallback for any GET
|
// Returns the /index.html asset, used as the SPA fallback for any GET
|
||||||
// that didn't match an embedded asset (React Router handles routing on the client side).
|
// that didn't match an embedded asset (React Router handles routing on
|
||||||
|
// the client side).
|
||||||
static const WWWAsset * index_asset() {
|
static const WWWAsset * index_asset() {
|
||||||
static const WWWAsset * cached = nullptr;
|
static const WWWAsset * cached = nullptr;
|
||||||
if (cached == nullptr) {
|
if (cached == nullptr) {
|
||||||
@@ -104,5 +106,4 @@ void ESP32React::loop() {
|
|||||||
_networkSettingsService.loop();
|
_networkSettingsService.loop();
|
||||||
_apSettingsService.loop();
|
_apSettingsService.loop();
|
||||||
_mqttSettingsService.loop();
|
_mqttSettingsService.loop();
|
||||||
_ntpSettingsService.loop();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ MqttSettingsService::MqttSettingsService(AsyncWebServer * server, FS * fs, Secur
|
|||||||
, _disconnectedAt(0)
|
, _disconnectedAt(0)
|
||||||
, _disconnectReason(espMqttClientTypes::DisconnectReason::TCP_DISCONNECTED)
|
, _disconnectReason(espMqttClientTypes::DisconnectReason::TCP_DISCONNECTED)
|
||||||
, _mqttClient(nullptr) {
|
, _mqttClient(nullptr) {
|
||||||
|
WiFi.onEvent([this](WiFiEvent_t event, WiFiEventInfo_t info) { WiFiEvent(event); });
|
||||||
addUpdateHandler([this] { onConfigUpdated(); }, false);
|
addUpdateHandler([this] { onConfigUpdated(); }, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,7 +29,6 @@ MqttSettingsService::~MqttSettingsService() {
|
|||||||
void MqttSettingsService::begin() {
|
void MqttSettingsService::begin() {
|
||||||
_fsPersistence.readFromFS();
|
_fsPersistence.readFromFS();
|
||||||
startClient();
|
startClient();
|
||||||
_reconfigureMqtt = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MqttSettingsService::startClient() {
|
void MqttSettingsService::startClient() {
|
||||||
@@ -41,7 +41,7 @@ void MqttSettingsService::startClient() {
|
|||||||
delete _mqttClient;
|
delete _mqttClient;
|
||||||
_mqttClient = nullptr;
|
_mqttClient = nullptr;
|
||||||
}
|
}
|
||||||
#ifndef NO_TLS_SUPPORT
|
#ifndef TASMOTA_SDK
|
||||||
if (_state.enableTLS) {
|
if (_state.enableTLS) {
|
||||||
isSecure = true;
|
isSecure = true;
|
||||||
if (emsesp::EMSESP::system_.PSram() == 0) {
|
if (emsesp::EMSESP::system_.PSram() == 0) {
|
||||||
@@ -79,10 +79,6 @@ void MqttSettingsService::startClient() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MqttSettingsService::loop() {
|
void MqttSettingsService::loop() {
|
||||||
if (_state.enabled && _mqttClient && _mqttClient->connected() && !emsesp::EMSESP::system_.network_connected()) {
|
|
||||||
// emsesp::EMSESP::logger().info("Network connection dropped, stopping MQTT client");
|
|
||||||
_mqttClient->disconnect(true);
|
|
||||||
}
|
|
||||||
if (_reconfigureMqtt || (_disconnectedAt && static_cast<uint32_t>(uuid::get_uptime() - _disconnectedAt) >= MQTT_RECONNECTION_DELAY)) {
|
if (_reconfigureMqtt || (_disconnectedAt && static_cast<uint32_t>(uuid::get_uptime() - _disconnectedAt) >= MQTT_RECONNECTION_DELAY)) {
|
||||||
// reconfigure MQTT client
|
// reconfigure MQTT client
|
||||||
_disconnectedAt = configureMqtt() ? 0 : uuid::get_uptime();
|
_disconnectedAt = configureMqtt() ? 0 : uuid::get_uptime();
|
||||||
@@ -146,6 +142,28 @@ void MqttSettingsService::onConfigUpdated() {
|
|||||||
emsesp::EMSESP::mqtt_.start(); // reload EMS-ESP MQTT settings
|
emsesp::EMSESP::mqtt_.start(); // reload EMS-ESP MQTT settings
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MqttSettingsService::WiFiEvent(WiFiEvent_t event) {
|
||||||
|
switch (event) {
|
||||||
|
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
|
||||||
|
case ARDUINO_EVENT_ETH_GOT_IP:
|
||||||
|
case ARDUINO_EVENT_ETH_GOT_IP6:
|
||||||
|
case ARDUINO_EVENT_WIFI_STA_GOT_IP6:
|
||||||
|
if (_state.enabled && !_mqttClient->connected()) {
|
||||||
|
onConfigUpdated();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
|
||||||
|
case ARDUINO_EVENT_ETH_DISCONNECTED:
|
||||||
|
if (_state.enabled) {
|
||||||
|
_mqttClient->disconnect(true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool MqttSettingsService::configureMqtt() {
|
bool MqttSettingsService::configureMqtt() {
|
||||||
// disconnect if already connected
|
// disconnect if already connected
|
||||||
if (_mqttClient->connected()) {
|
if (_mqttClient->connected()) {
|
||||||
@@ -164,13 +182,17 @@ bool MqttSettingsService::configureMqtt() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_reconfigureMqtt = false;
|
_reconfigureMqtt = false;
|
||||||
#ifndef NO_TLS_SUPPORT
|
#ifndef TASMOTA_SDK
|
||||||
if (_state.enableTLS) {
|
if (_state.enableTLS) {
|
||||||
if (_state.rootCA == "insecure") {
|
if (_state.rootCA == "insecure") {
|
||||||
|
#if defined(EMSESP_DEBUG)
|
||||||
emsesp::EMSESP::logger().debug("Start insecure MQTT");
|
emsesp::EMSESP::logger().debug("Start insecure MQTT");
|
||||||
|
#endif
|
||||||
static_cast<espMqttClientSecure *>(_mqttClient)->setInsecure();
|
static_cast<espMqttClientSecure *>(_mqttClient)->setInsecure();
|
||||||
} else {
|
} else {
|
||||||
|
#if defined(EMSESP_DEBUG)
|
||||||
emsesp::EMSESP::logger().debug("Start secure MQTT with rootCA");
|
emsesp::EMSESP::logger().debug("Start secure MQTT with rootCA");
|
||||||
|
#endif
|
||||||
String certificate = "-----BEGIN CERTIFICATE-----\n" + _state.rootCA + "\n-----END CERTIFICATE-----\n";
|
String certificate = "-----BEGIN CERTIFICATE-----\n" + _state.rootCA + "\n-----END CERTIFICATE-----\n";
|
||||||
static_cast<espMqttClientSecure *>(_mqttClient)->setCACert(certificate.c_str());
|
static_cast<espMqttClientSecure *>(_mqttClient)->setCACert(certificate.c_str());
|
||||||
}
|
}
|
||||||
@@ -201,7 +223,7 @@ bool MqttSettingsService::configureMqtt() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MqttSettings::read(MqttSettings & settings, JsonObject root) {
|
void MqttSettings::read(MqttSettings & settings, JsonObject root) {
|
||||||
#ifndef NO_TLS_SUPPORT
|
#ifndef TASMOTA_SDK
|
||||||
root["enableTLS"] = settings.enableTLS;
|
root["enableTLS"] = settings.enableTLS;
|
||||||
root["rootCA"] = settings.rootCA;
|
root["rootCA"] = settings.rootCA;
|
||||||
#endif
|
#endif
|
||||||
@@ -240,7 +262,7 @@ StateUpdateResult MqttSettings::update(JsonObject root, MqttSettings & settings)
|
|||||||
MqttSettings newSettings;
|
MqttSettings newSettings;
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
|
||||||
#ifndef NO_TLS_SUPPORT
|
#ifndef TASMOTA_SDK
|
||||||
newSettings.enableTLS = root["enableTLS"];
|
newSettings.enableTLS = root["enableTLS"];
|
||||||
newSettings.rootCA = root["rootCA"] | "";
|
newSettings.rootCA = root["rootCA"] | "";
|
||||||
#else
|
#else
|
||||||
@@ -371,7 +393,7 @@ StateUpdateResult MqttSettings::update(JsonObject root, MqttSettings & settings)
|
|||||||
emsesp::EMSESP::mqtt_.set_publish_time_heartbeat(newSettings.publish_time_heartbeat);
|
emsesp::EMSESP::mqtt_.set_publish_time_heartbeat(newSettings.publish_time_heartbeat);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NO_TLS_SUPPORT
|
#ifndef TASMOTA_SDK
|
||||||
// strip down to certificate only
|
// strip down to certificate only
|
||||||
newSettings.rootCA.replace("\r", "");
|
newSettings.rootCA.replace("\r", "");
|
||||||
newSettings.rootCA.replace("\n", "");
|
newSettings.rootCA.replace("\n", "");
|
||||||
|
|||||||
@@ -134,6 +134,7 @@ class MqttSettingsService : public StatefulService<MqttSettings> {
|
|||||||
// the MQTT client instance
|
// the MQTT client instance
|
||||||
MqttClient * _mqttClient;
|
MqttClient * _mqttClient;
|
||||||
|
|
||||||
|
void WiFiEvent(WiFiEvent_t event);
|
||||||
void onMqttConnect(bool sessionPresent);
|
void onMqttConnect(bool sessionPresent);
|
||||||
void onMqttDisconnect(espMqttClientTypes::DisconnectReason reason);
|
void onMqttDisconnect(espMqttClientTypes::DisconnectReason reason);
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -11,17 +11,36 @@ NTPSettingsService::NTPSettingsService(AsyncWebServer * server, FS * fs, Securit
|
|||||||
configureTime(request, json);
|
configureTime(request, json);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
WiFi.onEvent([this](WiFiEvent_t event, WiFiEventInfo_t info) { WiFiEvent(event); });
|
||||||
addUpdateHandler([this] { configureNTP(); }, false);
|
addUpdateHandler([this] { configureNTP(); }, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NTPSettingsService::begin() {
|
void NTPSettingsService::begin() {
|
||||||
_fsPersistence.readFromFS();
|
_fsPersistence.readFromFS();
|
||||||
|
configureNTP();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NTPSettingsService::loop() {
|
// handles both WiFI and Ethernet
|
||||||
if (_connected != emsesp::EMSESP::system_.network_connected()) {
|
void NTPSettingsService::WiFiEvent(WiFiEvent_t event) {
|
||||||
_connected = emsesp::EMSESP::system_.network_connected();
|
switch (event) {
|
||||||
|
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
|
||||||
|
case ARDUINO_EVENT_ETH_DISCONNECTED:
|
||||||
|
if (_connected && emsesp::EMSESP::system_.ntp_connected()) {
|
||||||
|
emsesp::EMSESP::logger().info("WiFi connection dropped, stopping NTP");
|
||||||
|
_connected = false;
|
||||||
|
configureNTP();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
|
||||||
|
case ARDUINO_EVENT_ETH_GOT_IP:
|
||||||
|
// emsesp::EMSESP::logger().info("Got IP address, starting NTP synchronization");
|
||||||
|
_connected = true;
|
||||||
configureNTP();
|
configureNTP();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,9 +55,7 @@ void NTPSettingsService::configureNTP() {
|
|||||||
} else {
|
} else {
|
||||||
setenv("TZ", _state.tzFormat.c_str(), 1);
|
setenv("TZ", _state.tzFormat.c_str(), 1);
|
||||||
tzset();
|
tzset();
|
||||||
if (esp_sntp_enabled()) {
|
esp_sntp_stop();
|
||||||
esp_sntp_stop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,12 +68,7 @@ void NTPSettingsService::configureTime(AsyncWebServerRequest * request, JsonVari
|
|||||||
tm.tm_isdst = -1; // not set by strptime, tells mktime to determine daylightsaving
|
tm.tm_isdst = -1; // not set by strptime, tells mktime to determine daylightsaving
|
||||||
time_t time = mktime(&tm);
|
time_t time = mktime(&tm);
|
||||||
struct timeval now = {.tv_sec = time, .tv_usec = {}};
|
struct timeval now = {.tv_sec = time, .tv_usec = {}};
|
||||||
#if CONFIG_IDF_TARGET_ESP32C3
|
|
||||||
// settimeofday and adjtime() does not work, unknown how to set time
|
|
||||||
emsesp::EMSESP::logger().warning("manual clock setting not possible");
|
|
||||||
#else
|
|
||||||
settimeofday(&now, nullptr);
|
settimeofday(&now, nullptr);
|
||||||
#endif
|
|
||||||
AsyncWebServerResponse * response = request->beginResponse(200);
|
AsyncWebServerResponse * response = request->beginResponse(200);
|
||||||
request->send(response);
|
request->send(response);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ class NTPSettingsService : public StatefulService<NTPSettings> {
|
|||||||
NTPSettingsService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager);
|
NTPSettingsService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager);
|
||||||
|
|
||||||
void begin();
|
void begin();
|
||||||
void loop();
|
|
||||||
static void ntp_received(struct timeval * tv);
|
static void ntp_received(struct timeval * tv);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -52,6 +51,7 @@ class NTPSettingsService : public StatefulService<NTPSettings> {
|
|||||||
FSPersistence<NTPSettings> _fsPersistence;
|
FSPersistence<NTPSettings> _fsPersistence;
|
||||||
volatile bool _connected;
|
volatile bool _connected;
|
||||||
|
|
||||||
|
void WiFiEvent(WiFiEvent_t event);
|
||||||
void configureNTP();
|
void configureNTP();
|
||||||
void configureTime(AsyncWebServerRequest * request, JsonVariant json);
|
void configureTime(AsyncWebServerRequest * request, JsonVariant json);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ NetworkSettingsService::NetworkSettingsService(AsyncWebServer * server, FS * fs,
|
|||||||
, _stopping(false) {
|
, _stopping(false) {
|
||||||
addUpdateHandler([this] { reconfigureWiFiConnection(); }, false);
|
addUpdateHandler([this] { reconfigureWiFiConnection(); }, false);
|
||||||
// Eth is also bound to the WifiGeneric event handler
|
// Eth is also bound to the WifiGeneric event handler
|
||||||
// Network.onEvent([this](arduino_event_id_t event, arduino_event_info_t info) { WiFiEvent(event, info); });
|
WiFi.onEvent([this](WiFiEvent_t event, WiFiEventInfo_t info) { WiFiEvent(event, info); });
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool formatBssid(const String & bssid, uint8_t (&mac)[6]) {
|
static bool formatBssid(const String & bssid, uint8_t (&mac)[6]) {
|
||||||
@@ -34,8 +34,8 @@ void NetworkSettingsService::begin() {
|
|||||||
WiFi.persistent(false);
|
WiFi.persistent(false);
|
||||||
WiFi.setAutoReconnect(false);
|
WiFi.setAutoReconnect(false);
|
||||||
|
|
||||||
WiFi.mode(WIFI_STA);
|
WiFi.mode(WIFI_MODE_MAX);
|
||||||
WiFi.mode(WIFI_OFF);
|
WiFi.mode(WIFI_MODE_NULL);
|
||||||
|
|
||||||
// scan settings give connect issues since arduino 2.0.14 and arduino 3.x.x with some wifi systems
|
// scan settings give connect issues since arduino 2.0.14 and arduino 3.x.x with some wifi systems
|
||||||
// WiFi.setScanMethod(WIFI_ALL_CHANNEL_SCAN); // default is FAST_SCAN
|
// WiFi.setScanMethod(WIFI_ALL_CHANNEL_SCAN); // default is FAST_SCAN
|
||||||
@@ -62,124 +62,28 @@ void NetworkSettingsService::loop() {
|
|||||||
_lastConnectionAttempt = currentMillis;
|
_lastConnectionAttempt = currentMillis;
|
||||||
manageSTA();
|
manageSTA();
|
||||||
}
|
}
|
||||||
static uint8_t connect = 0;
|
|
||||||
enum uint8_t {
|
|
||||||
CONNECT_IDLE = 0,
|
|
||||||
CONNECT_WAIT_ETH,
|
|
||||||
CONNECT_WAIT_IP4,
|
|
||||||
CONNECT_WAIT_ETH_IP4,
|
|
||||||
CONNECT_WAIT_IP6,
|
|
||||||
CONNECT_WAIT_ETH_IP6,
|
|
||||||
CONNECT_ETH_ACTIVE,
|
|
||||||
CONNECT_WIFI_ACTIVE
|
|
||||||
};
|
|
||||||
switch (connect) {
|
|
||||||
default:
|
|
||||||
connect = CONNECT_IDLE;
|
|
||||||
break;
|
|
||||||
case CONNECT_IDLE:
|
|
||||||
if (ETH.started() && _state.ssid.length() == 0) {
|
|
||||||
emsesp::EMSESP::logger().info("ETH started");
|
|
||||||
ETH.setHostname(emsesp::EMSESP::system_.hostname().c_str());
|
|
||||||
ETH.enableIPv6(true);
|
|
||||||
if (_state.staticIPConfig) {
|
|
||||||
ETH.config(_state.localIP, _state.gatewayIP, _state.subnetMask, _state.dnsIP1, _state.dnsIP2);
|
|
||||||
}
|
|
||||||
connect = CONNECT_WAIT_ETH;
|
|
||||||
}
|
|
||||||
if (WiFi.isConnected()) {
|
|
||||||
emsesp::EMSESP::logger().info("Wifi connected");
|
|
||||||
if (_state.tx_power == 0) {
|
|
||||||
setWiFiPowerOnRSSI();
|
|
||||||
}
|
|
||||||
mDNS_start();
|
|
||||||
emsesp::EMSESP::system_.has_ipv6(true);
|
|
||||||
connect = CONNECT_WAIT_IP4;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CONNECT_WAIT_ETH:
|
|
||||||
if (ETH.connected()) {
|
|
||||||
emsesp::EMSESP::logger().info("ETH connected");
|
|
||||||
emsesp::EMSESP::system_.ethernet_connected(true);
|
|
||||||
mDNS_start();
|
|
||||||
emsesp::EMSESP::system_.has_ipv6(true);
|
|
||||||
connect = CONNECT_WAIT_ETH_IP4;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CONNECT_WAIT_ETH_IP4:
|
|
||||||
if (ETH.hasIP()) {
|
|
||||||
emsesp::EMSESP::logger().info("ETH IPv4: %s", ETH.localIP().toString().c_str());
|
|
||||||
connect = CONNECT_WAIT_ETH_IP6;
|
|
||||||
}
|
|
||||||
if (!ETH.connected()) {
|
|
||||||
connect = CONNECT_ETH_ACTIVE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CONNECT_WAIT_ETH_IP6:
|
|
||||||
if (ETH.hasLinkLocalIPv6() && ETH.hasGlobalIPv6()) {
|
|
||||||
emsesp::EMSESP::system_.has_ipv6(true);
|
|
||||||
connect = CONNECT_ETH_ACTIVE;
|
|
||||||
}
|
|
||||||
if (!ETH.connected()) {
|
|
||||||
connect = CONNECT_ETH_ACTIVE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CONNECT_ETH_ACTIVE:
|
|
||||||
if (!ETH.connected()) {
|
|
||||||
emsesp::EMSESP::logger().info("ETH disconnected");
|
|
||||||
emsesp::EMSESP::system_.ethernet_connected(false);
|
|
||||||
emsesp::EMSESP::system_.has_ipv6(false);
|
|
||||||
connect = CONNECT_IDLE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CONNECT_WAIT_IP4:
|
|
||||||
if (!WiFi.localIP().toString().isEmpty()) {
|
|
||||||
emsesp::EMSESP::logger().info("Wifi IPv4: %s", WiFi.localIP().toString().c_str());
|
|
||||||
connect = CONNECT_WAIT_IP6;
|
|
||||||
}
|
|
||||||
if (!WiFi.isConnected()) {
|
|
||||||
connect = CONNECT_ETH_ACTIVE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CONNECT_WAIT_IP6:
|
|
||||||
if (WiFi.linkLocalIPv6().toString() != "::" && WiFi.globalIPv6().toString() != "::") {
|
|
||||||
emsesp::EMSESP::logger().info("Wifi IPv6: %s, %s", WiFi.linkLocalIPv6().toString().c_str(), WiFi.globalIPv6().toString().c_str());
|
|
||||||
emsesp::EMSESP::system_.has_ipv6(true);
|
|
||||||
connect = CONNECT_WIFI_ACTIVE;
|
|
||||||
}
|
|
||||||
if (!WiFi.isConnected()) {
|
|
||||||
connect = CONNECT_WIFI_ACTIVE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case CONNECT_WIFI_ACTIVE:
|
|
||||||
if (!WiFi.isConnected()) {
|
|
||||||
emsesp::EMSESP::logger().info("WiFi disconnected");
|
|
||||||
if (_stopping) {
|
|
||||||
_lastConnectionAttempt = 0;
|
|
||||||
_stopping = false;
|
|
||||||
}
|
|
||||||
emsesp::EMSESP::system_.has_ipv6(false);
|
|
||||||
connect = CONNECT_IDLE;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NetworkSettingsService::manageSTA() {
|
void NetworkSettingsService::manageSTA() {
|
||||||
// Abort if already connected, or if we have no SSID
|
// Abort if already connected, or if we have no SSID
|
||||||
if (WiFi.isConnected() || _state.ssid.length() == 0) {
|
if (WiFi.isConnected() || _state.ssid.length() == 0) {
|
||||||
|
#if ESP_IDF_VERSION_MAJOR >= 5
|
||||||
|
if (_state.ssid.length() == 0) {
|
||||||
|
ETH.enableIPv6(true);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect or reconnect as required
|
// Connect or reconnect as required
|
||||||
if ((WiFi.getMode() & WIFI_STA) == 0) {
|
if ((WiFi.getMode() & WIFI_STA) == 0) {
|
||||||
WiFi.setHostname(_state.hostname.c_str()); // updates shared default_hostname buffer
|
#if ESP_IDF_VERSION_MAJOR >= 5
|
||||||
WiFi.enableSTA(true); // creates the STA netif
|
|
||||||
WiFi.STA.setHostname(_state.hostname.c_str()); // pushes to esp_netif_set_hostname
|
|
||||||
WiFi.enableIPv6(true);
|
WiFi.enableIPv6(true);
|
||||||
|
#endif
|
||||||
if (_state.staticIPConfig) {
|
if (_state.staticIPConfig) {
|
||||||
WiFi.config(_state.localIP, _state.gatewayIP, _state.subnetMask, _state.dnsIP1, _state.dnsIP2); // configure for static IP
|
WiFi.config(_state.localIP, _state.gatewayIP, _state.subnetMask, _state.dnsIP1, _state.dnsIP2); // configure for static IP
|
||||||
}
|
}
|
||||||
|
WiFi.setHostname(_state.hostname.c_str()); // set hostname
|
||||||
|
|
||||||
// www.esp32.com/viewtopic.php?t=12055
|
// www.esp32.com/viewtopic.php?t=12055
|
||||||
if (_state.bandwidth20) {
|
if (_state.bandwidth20) {
|
||||||
@@ -389,7 +293,7 @@ const char * NetworkSettingsService::disconnectReason(uint8_t code) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handles both WiFI and Ethernet
|
// handles both WiFI and Ethernet
|
||||||
void NetworkSettingsService::WiFiEvent(arduino_event_id_t event, arduino_event_info_t info) {
|
void NetworkSettingsService::WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
@@ -401,7 +305,7 @@ void NetworkSettingsService::WiFiEvent(arduino_event_id_t event, arduino_event_i
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
|
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
|
||||||
connectcount_ = connectcount_ + 1; // count the number of WiFi reconnects
|
connectcount_++; // count the number of WiFi reconnects
|
||||||
emsesp::EMSESP::logger().warning("WiFi disconnected (#%d). Reason: %s (%d)",
|
emsesp::EMSESP::logger().warning("WiFi disconnected (#%d). Reason: %s (%d)",
|
||||||
connectcount_,
|
connectcount_,
|
||||||
disconnectReason(info.wifi_sta_disconnected.reason),
|
disconnectReason(info.wifi_sta_disconnected.reason),
|
||||||
@@ -421,11 +325,11 @@ void NetworkSettingsService::WiFiEvent(arduino_event_id_t event, arduino_event_i
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case ARDUINO_EVENT_ETH_START:
|
case ARDUINO_EVENT_ETH_START:
|
||||||
// apply hostname FIRST so DHCP DISCOVER carries the correct name
|
// configure for static IP
|
||||||
ETH.setHostname(emsesp::EMSESP::system_.hostname().c_str());
|
|
||||||
if (_state.staticIPConfig) {
|
if (_state.staticIPConfig) {
|
||||||
ETH.config(_state.localIP, _state.gatewayIP, _state.subnetMask, _state.dnsIP1, _state.dnsIP2);
|
ETH.config(_state.localIP, _state.gatewayIP, _state.subnetMask, _state.dnsIP1, _state.dnsIP2);
|
||||||
}
|
}
|
||||||
|
ETH.setHostname(emsesp::EMSESP::system_.hostname().c_str());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ARDUINO_EVENT_ETH_GOT_IP:
|
case ARDUINO_EVENT_ETH_GOT_IP:
|
||||||
@@ -456,15 +360,25 @@ void NetworkSettingsService::WiFiEvent(arduino_event_id_t event, arduino_event_i
|
|||||||
if (_state.tx_power == 0) {
|
if (_state.tx_power == 0) {
|
||||||
setWiFiPowerOnRSSI();
|
setWiFiPowerOnRSSI();
|
||||||
}
|
}
|
||||||
|
#if ESP_IDF_VERSION_MAJOR < 5
|
||||||
|
WiFi.enableIpV6(); // force ipv6
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ARDUINO_EVENT_ETH_CONNECTED:
|
case ARDUINO_EVENT_ETH_CONNECTED:
|
||||||
|
#if ESP_IDF_VERSION_MAJOR < 5
|
||||||
|
ETH.enableIpV6(); // force ipv6
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// IPv6 specific - WiFi/Eth
|
// IPv6 specific - WiFi/Eth
|
||||||
case ARDUINO_EVENT_WIFI_STA_GOT_IP6:
|
case ARDUINO_EVENT_WIFI_STA_GOT_IP6:
|
||||||
case ARDUINO_EVENT_ETH_GOT_IP6: {
|
case ARDUINO_EVENT_ETH_GOT_IP6: {
|
||||||
auto ip6 = IPAddress(IPv6, (uint8_t *)info.got_ip6.ip6_info.ip.addr, 0).toString();
|
#if !TASMOTA_SDK && ESP_IDF_VERSION_MAJOR < 5
|
||||||
|
auto ip6 = IPv6Address((uint8_t *)info.got_ip6.ip6_info.ip.addr).toString();
|
||||||
|
#else
|
||||||
|
auto ip6 = IPAddress(IPv6, (uint8_t *)info.got_ip6.ip6_info.ip.addr, 0).toString();
|
||||||
|
#endif
|
||||||
const char * link = event == ARDUINO_EVENT_ETH_GOT_IP6 ? "Eth" : "WiFi";
|
const char * link = event == ARDUINO_EVENT_ETH_GOT_IP6 ? "Eth" : "WiFi";
|
||||||
if (ip6.startsWith("fe80")) {
|
if (ip6.startsWith("fe80")) {
|
||||||
emsesp::EMSESP::logger().info("IPv6 (%s) local: %s", link, ip6.c_str());
|
emsesp::EMSESP::logger().info("IPv6 (%s) local: %s", link, ip6.c_str());
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ class NetworkSettingsService : public StatefulService<NetworkSettings> {
|
|||||||
|
|
||||||
volatile uint16_t connectcount_ = 0; // number of wifi reconnects
|
volatile uint16_t connectcount_ = 0; // number of wifi reconnects
|
||||||
|
|
||||||
void WiFiEvent(arduino_event_id_t event, arduino_event_info_t info);
|
void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info);
|
||||||
void mDNS_start() const;
|
void mDNS_start() const;
|
||||||
const char * disconnectReason(uint8_t code);
|
const char * disconnectReason(uint8_t code);
|
||||||
void reconfigureWiFiConnection();
|
void reconfigureWiFiConnection();
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <emsesp.h>
|
#include <emsesp.h>
|
||||||
|
|
||||||
#ifdef NO_TLS_SUPPORT
|
#ifdef TASMOTA_SDK
|
||||||
#include "lwip/dns.h"
|
#include "lwip/dns.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -31,13 +31,22 @@ void NetworkStatus::networkStatus(AsyncWebServerRequest * request) {
|
|||||||
// for both connections show ethernet
|
// for both connections show ethernet
|
||||||
if (ethernet_connected) {
|
if (ethernet_connected) {
|
||||||
// Ethernet
|
// Ethernet
|
||||||
root["local_ip"] = ETH.localIP().toString();
|
root["local_ip"] = ETH.localIP().toString();
|
||||||
root["local_ipv6"] = ETH.linkLocalIPv6().toString();
|
#if ESP_IDF_VERSION_MAJOR < 5
|
||||||
|
root["local_ipv6"] = ETH.localIPv6().toString();
|
||||||
|
#else
|
||||||
|
root["local_ipv6"] = ETH.linkLocalIPv6().toString();
|
||||||
|
#endif
|
||||||
root["mac_address"] = ETH.macAddress();
|
root["mac_address"] = ETH.macAddress();
|
||||||
root["subnet_mask"] = ETH.subnetMask().toString();
|
root["subnet_mask"] = ETH.subnetMask().toString();
|
||||||
root["gateway_ip"] = ETH.gatewayIP().toString();
|
root["gateway_ip"] = ETH.gatewayIP().toString();
|
||||||
IPAddress dnsIP1 = ETH.dnsIP(0);
|
#ifdef TASMOTA_SDK
|
||||||
IPAddress dnsIP2 = ETH.dnsIP(1);
|
IPAddress dnsIP1 = IPAddress(dns_getserver(0));
|
||||||
|
IPAddress dnsIP2 = IPAddress(dns_getserver(1));
|
||||||
|
#else
|
||||||
|
IPAddress dnsIP1 = ETH.dnsIP(0);
|
||||||
|
IPAddress dnsIP2 = ETH.dnsIP(1);
|
||||||
|
#endif
|
||||||
if (IPUtils::isSet(dnsIP1)) {
|
if (IPUtils::isSet(dnsIP1)) {
|
||||||
root["dns_ip_1"] = dnsIP1.toString();
|
root["dns_ip_1"] = dnsIP1.toString();
|
||||||
}
|
}
|
||||||
@@ -45,8 +54,12 @@ void NetworkStatus::networkStatus(AsyncWebServerRequest * request) {
|
|||||||
root["dns_ip_2"] = dnsIP2.toString();
|
root["dns_ip_2"] = dnsIP2.toString();
|
||||||
}
|
}
|
||||||
} else if (wifi_status == WL_CONNECTED) {
|
} else if (wifi_status == WL_CONNECTED) {
|
||||||
root["local_ip"] = WiFi.localIP().toString();
|
root["local_ip"] = WiFi.localIP().toString();
|
||||||
root["local_ipv6"] = WiFi.linkLocalIPv6().toString();
|
#if ESP_IDF_VERSION_MAJOR < 5
|
||||||
|
root["local_ipv6"] = WiFi.localIPv6().toString();
|
||||||
|
#else
|
||||||
|
root["local_ipv6"] = WiFi.linkLocalIPv6().toString();
|
||||||
|
#endif
|
||||||
root["mac_address"] = WiFi.macAddress();
|
root["mac_address"] = WiFi.macAddress();
|
||||||
root["rssi"] = WiFi.RSSI();
|
root["rssi"] = WiFi.RSSI();
|
||||||
root["ssid"] = WiFi.SSID();
|
root["ssid"] = WiFi.SSID();
|
||||||
@@ -58,8 +71,14 @@ void NetworkStatus::networkStatus(AsyncWebServerRequest * request) {
|
|||||||
if (WiFi.gatewayIP() != INADDR_NONE) {
|
if (WiFi.gatewayIP() != INADDR_NONE) {
|
||||||
root["gateway_ip"] = WiFi.gatewayIP().toString();
|
root["gateway_ip"] = WiFi.gatewayIP().toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef TASMOTA_SDK
|
||||||
|
IPAddress dnsIP1 = IPAddress(dns_getserver(0));
|
||||||
|
IPAddress dnsIP2 = IPAddress(dns_getserver(1));
|
||||||
|
#else
|
||||||
IPAddress dnsIP1 = WiFi.dnsIP(0);
|
IPAddress dnsIP1 = WiFi.dnsIP(0);
|
||||||
IPAddress dnsIP2 = WiFi.dnsIP(1);
|
IPAddress dnsIP2 = WiFi.dnsIP(1);
|
||||||
|
#endif
|
||||||
if (dnsIP1 != INADDR_NONE) {
|
if (dnsIP1 != INADDR_NONE) {
|
||||||
root["dns_ip_1"] = dnsIP1.toString();
|
root["dns_ip_1"] = dnsIP1.toString();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -347,13 +347,23 @@ void AnalogSensor::reload(bool get_nvs) {
|
|||||||
sensor.polltime_ = sensor.value() != 0 ? uuid::get_uptime() + (sensor.factor() * 1000) : 0;
|
sensor.polltime_ = sensor.value() != 0 ? uuid::get_uptime() + (sensor.factor() * 1000) : 0;
|
||||||
} else if (sensor.type() >= AnalogType::PWM_0 && sensor.type() <= AnalogType::PWM_2) {
|
} else if (sensor.type() >= AnalogType::PWM_0 && sensor.type() <= AnalogType::PWM_2) {
|
||||||
LOG_DEBUG("PWM output on GPIO %02d", sensor.gpio());
|
LOG_DEBUG("PWM output on GPIO %02d", sensor.gpio());
|
||||||
|
#if ESP_IDF_VERSION_MAJOR >= 5
|
||||||
ledcAttach(sensor.gpio(), sensor.factor(), 13);
|
ledcAttach(sensor.gpio(), sensor.factor(), 13);
|
||||||
|
#else
|
||||||
|
uint8_t channel = sensor.type() - AnalogType::PWM_0;
|
||||||
|
ledcSetup(channel, sensor.factor(), 13);
|
||||||
|
ledcAttachPin(sensor.gpio(), channel);
|
||||||
|
#endif
|
||||||
if (sensor.offset() > 100) {
|
if (sensor.offset() > 100) {
|
||||||
sensor.set_offset(100);
|
sensor.set_offset(100);
|
||||||
} else if (sensor.offset() < 0) {
|
} else if (sensor.offset() < 0) {
|
||||||
sensor.set_offset(0);
|
sensor.set_offset(0);
|
||||||
}
|
}
|
||||||
|
#if ESP_IDF_VERSION_MAJOR >= 5
|
||||||
ledcWrite(sensor.gpio(), (uint32_t)(sensor.offset() * 8191 / 100));
|
ledcWrite(sensor.gpio(), (uint32_t)(sensor.offset() * 8191 / 100));
|
||||||
|
#else
|
||||||
|
ledcWrite(channel, (uint32_t)(sensor.offset() * 8191 / 100));
|
||||||
|
#endif
|
||||||
sensor.set_value(sensor.offset());
|
sensor.set_value(sensor.offset());
|
||||||
sensor.set_uom(DeviceValueUOM::PERCENT);
|
sensor.set_uom(DeviceValueUOM::PERCENT);
|
||||||
publish_sensor(sensor);
|
publish_sensor(sensor);
|
||||||
@@ -1031,7 +1041,12 @@ bool AnalogSensor::command_setvalue(const char * value, const int8_t gpio) {
|
|||||||
}
|
}
|
||||||
sensor.set_offset(val);
|
sensor.set_offset(val);
|
||||||
sensor.set_value(val);
|
sensor.set_value(val);
|
||||||
|
#if ESP_IDF_VERSION_MAJOR >= 5
|
||||||
ledcWrite(sensor.gpio(), (uint32_t)(sensor.offset() * 8191 / 100));
|
ledcWrite(sensor.gpio(), (uint32_t)(sensor.offset() * 8191 / 100));
|
||||||
|
#else
|
||||||
|
uint8_t channel = sensor.type() - AnalogType::PWM_0;
|
||||||
|
ledcWrite(channel, (uint32_t)(val * 8191 / 100));
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,11 +26,11 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef EMSESP_DEFAULT_TX_MODE
|
#ifndef EMSESP_DEFAULT_TX_MODE
|
||||||
#define EMSESP_DEFAULT_TX_MODE 1 // EMS1.0
|
#define EMSESP_DEFAULT_TX_MODE 5 // Auto
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef EMSESP_DEFAULT_EMS_BUS_ID
|
#ifndef EMSESP_DEFAULT_EMS_BUS_ID
|
||||||
#define EMSESP_DEFAULT_EMS_BUS_ID 0x0B // service key
|
#define EMSESP_DEFAULT_EMS_BUS_ID 0x49 // gateway 2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef EMSESP_DEFAULT_SYSLOG_ENABLED
|
#ifndef EMSESP_DEFAULT_SYSLOG_ENABLED
|
||||||
@@ -285,8 +285,6 @@ enum {
|
|||||||
#define EMSESP_PLATFORM "ESP32S3"
|
#define EMSESP_PLATFORM "ESP32S3"
|
||||||
#elif CONFIG_IDF_TARGET_ESP32 || EMSESP_STANDALONE
|
#elif CONFIG_IDF_TARGET_ESP32 || EMSESP_STANDALONE
|
||||||
#define EMSESP_PLATFORM "ESP32"
|
#define EMSESP_PLATFORM "ESP32"
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
|
||||||
#define EMSESP_PLATFORM "ESP32C6"
|
|
||||||
#else
|
#else
|
||||||
#error Target CONFIG_IDF_TARGET is not supported
|
#error Target CONFIG_IDF_TARGET is not supported
|
||||||
#endif
|
#endif
|
||||||
@@ -295,9 +293,12 @@ enum {
|
|||||||
#ifndef STRINGIZE
|
#ifndef STRINGIZE
|
||||||
#define STRINGIZE(s) #s
|
#define STRINGIZE(s) #s
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef TASMOTA_SDK
|
||||||
#define ARDUINO_VERSION_STR(major, minor, patch) "Tasmota Arduino v" STRINGIZE(major) "." STRINGIZE(minor) "." STRINGIZE(patch)
|
#define ARDUINO_VERSION_STR(major, minor, patch) "Tasmota Arduino v" STRINGIZE(major) "." STRINGIZE(minor) "." STRINGIZE(patch)
|
||||||
|
#else
|
||||||
|
#define ARDUINO_VERSION_STR(major, minor, patch) "ESP32 Arduino v" STRINGIZE(major) "." STRINGIZE(minor) "." STRINGIZE(patch)
|
||||||
|
#endif
|
||||||
#define ARDUINO_VERSION ARDUINO_VERSION_STR(ESP_ARDUINO_VERSION_MAJOR, ESP_ARDUINO_VERSION_MINOR, ESP_ARDUINO_VERSION_PATCH)
|
#define ARDUINO_VERSION ARDUINO_VERSION_STR(ESP_ARDUINO_VERSION_MAJOR, ESP_ARDUINO_VERSION_MINOR, ESP_ARDUINO_VERSION_PATCH)
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -448,6 +448,14 @@ class EMSdevice {
|
|||||||
static constexpr uint8_t EMS_DEVICE_ID_DHW2 = 0x29; // MM100 module as water station
|
static constexpr uint8_t EMS_DEVICE_ID_DHW2 = 0x29; // MM100 module as water station
|
||||||
static constexpr uint8_t EMS_DEVICE_ID_DHW8 = 0x2F; // last DHW module id?
|
static constexpr uint8_t EMS_DEVICE_ID_DHW8 = 0x2F; // last DHW module id?
|
||||||
static constexpr uint8_t EMS_DEVICE_ID_IPM_DHW = 0x41; // IPM module as water station
|
static constexpr uint8_t EMS_DEVICE_ID_IPM_DHW = 0x41; // IPM module as water station
|
||||||
|
static constexpr uint8_t EMS_DEVICE_ID_GATEWAY1 = 0x48; // KM200, MX300, MX400
|
||||||
|
static constexpr uint8_t EMS_DEVICE_ID_GATEWAY2 = 0x49;
|
||||||
|
static constexpr uint8_t EMS_DEVICE_ID_GATEWAY3 = 0x4A;
|
||||||
|
static constexpr uint8_t EMS_DEVICE_ID_GATEWAY4 = 0x4B;
|
||||||
|
static constexpr uint8_t EMS_DEVICE_ID_GATEWAY5 = 0x4C;
|
||||||
|
static constexpr uint8_t EMS_DEVICE_ID_GATEWAY6 = 0x4D;
|
||||||
|
static constexpr uint8_t EMS_DEVICE_ID_GATEWAY7 = 0x4E;
|
||||||
|
static constexpr uint8_t EMS_DEVICE_ID_GATEWAY8 = 0x4F;
|
||||||
|
|
||||||
// generic type IDs
|
// generic type IDs
|
||||||
static constexpr uint16_t EMS_TYPE_NAME = 0x01; // device config for ems devices, name ascii on offset 27ff for ems+
|
static constexpr uint16_t EMS_TYPE_NAME = 0x01; // device config for ems devices, name ascii on offset 27ff for ems+
|
||||||
|
|||||||
@@ -1727,8 +1727,6 @@ void EMSESP::start() {
|
|||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
if (factory_settings) {
|
if (factory_settings) {
|
||||||
LOG_WARNING("No settings found on filesystem. Using factory settings.");
|
LOG_WARNING("No settings found on filesystem. Using factory settings.");
|
||||||
// make sure OTAdata is updated with core3 format
|
|
||||||
esp_ota_set_boot_partition(esp_ota_get_running_partition());
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -380,15 +380,11 @@ std::string commands(std::string & expr, bool quotes) {
|
|||||||
if (return_code != CommandRet::OK && return_code != CommandRet::NO_VALUE) {
|
if (return_code != CommandRet::OK && return_code != CommandRet::NO_VALUE) {
|
||||||
return expr = "";
|
return expr = "";
|
||||||
}
|
}
|
||||||
std::string data;
|
|
||||||
if (output["api_data"].is<std::string>()) {
|
std::string data = output["api_data"] | "";
|
||||||
data = output["api_data"].as<std::string>();
|
if (!isnum(data) && quotes) {
|
||||||
if (!isnum(data) && quotes) {
|
data.insert(data.begin(), '"');
|
||||||
data.insert(data.begin(), '"');
|
data.insert(data.end(), '"');
|
||||||
data.insert(data.end(), '"');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
serializeJson(output, data);
|
|
||||||
}
|
}
|
||||||
expr.replace(f, l, data);
|
expr.replace(f, l, data);
|
||||||
e = f + data.length();
|
e = f + data.length();
|
||||||
@@ -704,7 +700,8 @@ std::string compute(const std::string & expr) {
|
|||||||
std::string cmd = expr_new.substr(f, e - f).c_str();
|
std::string cmd = expr_new.substr(f, e - f).c_str();
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
if (DeserializationError::Ok == deserializeJson(doc, cmd)) {
|
if (DeserializationError::Ok == deserializeJson(doc, cmd)) {
|
||||||
std::string url, header_s, value_s, method_s, key_s, keys_s;
|
HTTPClient * http = new HTTPClient;
|
||||||
|
std::string url, header_s, value_s, method_s, key_s, keys_s;
|
||||||
// search keys lower case
|
// search keys lower case
|
||||||
for (JsonPair p : doc.as<JsonObject>()) {
|
for (JsonPair p : doc.as<JsonObject>()) {
|
||||||
if (Helpers::toLower(p.key().c_str()) == "url") {
|
if (Helpers::toLower(p.key().c_str()) == "url") {
|
||||||
@@ -723,150 +720,58 @@ std::string compute(const std::string & expr) {
|
|||||||
keys_s = p.key().c_str();
|
keys_s = p.key().c_str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool content_set = false;
|
if (http->begin(url.c_str())) {
|
||||||
std::string value = doc[value_s] | "";
|
int httpResult = 0;
|
||||||
std::string method = doc[method_s] | "GET";
|
for (JsonPair p : doc[header_s].as<JsonObject>()) {
|
||||||
if (value.length()) {
|
http->addHeader(p.key().c_str(), p.value().as<std::string>().c_str());
|
||||||
method = "POST";
|
|
||||||
}
|
|
||||||
std::string result;
|
|
||||||
int httpResult = 0;
|
|
||||||
#ifndef NO_TLS_SUPPORT
|
|
||||||
if (Helpers::toLower(url.c_str()).starts_with("https://")) {
|
|
||||||
WiFiClient * basic_client = new WiFiClient;
|
|
||||||
ESP_SSLClient * ssl_client = new ESP_SSLClient;
|
|
||||||
ssl_client->setInsecure(); // with root CA we should set here: ssl_client->setCACert(rootCACert);
|
|
||||||
ssl_client->setBufferSizes(1024, 1024);
|
|
||||||
ssl_client->setSessionTimeout(120); // Set the timeout in seconds (>=120 seconds)
|
|
||||||
url.replace(0, 8, "");
|
|
||||||
std::string host = url;
|
|
||||||
auto index = url.find_first_of('/');
|
|
||||||
if (index != std::string::npos) {
|
|
||||||
host = url.substr(0, index);
|
|
||||||
url.replace(0, index, "");
|
|
||||||
}
|
}
|
||||||
/*
|
std::string value = doc[value_s] | "";
|
||||||
index = host.find_first_of('@');
|
std::string method = doc[method_s] | "get";
|
||||||
std::string auth;
|
|
||||||
if (index != std::string::npos) {
|
// if there is data, force a POST
|
||||||
auth = base64::encode(host.substr(0, index));
|
if (value.length() || Helpers::toLower(method) == "post") {
|
||||||
host.replace(0, index, "");
|
if (value.find_first_of('{') != std::string::npos) {
|
||||||
|
http->addHeader(asyncsrv::T_Content_Type, asyncsrv::T_application_json, false); // auto-set to JSON
|
||||||
|
}
|
||||||
|
httpResult = http->POST(value.c_str());
|
||||||
|
} else {
|
||||||
|
httpResult = http->GET(); // normal GET
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
ssl_client->setClient(basic_client);
|
if (httpResult > 0) {
|
||||||
if (ssl_client->connect(host.c_str(), 443)) {
|
std::string result = http->getString().c_str();
|
||||||
if (value.length() || Helpers::toLower(method) == "post") {
|
std::string key = doc[key_s] | "";
|
||||||
ssl_client->print("POST ");
|
JsonDocument keys_doc; // JsonDocument to hold "keys" after doc is parsed with HTTP body
|
||||||
ssl_client->print(url.c_str());
|
if (doc[keys_s].is<JsonArray>()) {
|
||||||
ssl_client->println(" HTTP/1.1");
|
keys_doc.set(doc[keys_s].as<JsonArray>());
|
||||||
ssl_client->print("Host: ");
|
}
|
||||||
ssl_client->println(host.c_str());
|
JsonArray keys = keys_doc.as<JsonArray>();
|
||||||
for (JsonPair p : doc[header_s].as<JsonObject>()) {
|
|
||||||
content_set |= (emsesp::Helpers::toLower(p.key().c_str()) == "content-type");
|
if (key.length() || !keys.isNull()) {
|
||||||
ssl_client->print(p.key().c_str());
|
doc.clear();
|
||||||
ssl_client->print(": ");
|
if (DeserializationError::Ok == deserializeJson(doc, result)) {
|
||||||
ssl_client->println(p.value().as<std::string>().c_str());
|
if (key.length()) {
|
||||||
}
|
result = doc[key.c_str()].as<std::string>();
|
||||||
if (!content_set) {
|
|
||||||
ssl_client->print("Content-Type: ");
|
|
||||||
if (value.starts_with('{')) {
|
|
||||||
ssl_client->println(asyncsrv::T_application_json);
|
|
||||||
} else {
|
} else {
|
||||||
ssl_client->println(asyncsrv::T_text_plain);
|
JsonVariant json = doc.as<JsonVariant>();
|
||||||
|
for (JsonVariant keys_key : keys) {
|
||||||
|
if (keys_key.is<std::string>() && json.is<JsonObject>()) {
|
||||||
|
json = json[keys_key.as<std::string>()].as<JsonVariant>();
|
||||||
|
} else if (keys_key.is<int>() && json.is<JsonArray>()) {
|
||||||
|
json = json[keys_key.as<int>()].as<JsonVariant>();
|
||||||
|
} else {
|
||||||
|
break; // type mismatch
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = json.as<std::string>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ssl_client->print("Content-Length: ");
|
|
||||||
ssl_client->println(value.length());
|
|
||||||
ssl_client->println("Connection: close");
|
|
||||||
ssl_client->print("\r\n");
|
|
||||||
ssl_client->print(value.c_str());
|
|
||||||
} else {
|
|
||||||
ssl_client->print("GET ");
|
|
||||||
ssl_client->print(url.c_str());
|
|
||||||
ssl_client->println(" HTTP/1.1");
|
|
||||||
ssl_client->print("Host: ");
|
|
||||||
ssl_client->println(host.c_str());
|
|
||||||
for (JsonPair p : doc[header_s].as<JsonObject>()) {
|
|
||||||
ssl_client->print(p.key().c_str());
|
|
||||||
ssl_client->print(": ");
|
|
||||||
ssl_client->println(p.value().as<std::string>().c_str());
|
|
||||||
}
|
|
||||||
ssl_client->println("Connection: close");
|
|
||||||
}
|
|
||||||
auto ms = millis();
|
|
||||||
while (!ssl_client->available() && millis() - ms < 3000) {
|
|
||||||
delay(0);
|
|
||||||
}
|
|
||||||
while (ssl_client->available()) {
|
|
||||||
result += (char)ssl_client->read();
|
|
||||||
}
|
|
||||||
ssl_client->stop();
|
|
||||||
index = result.find_first_of(' ');
|
|
||||||
if (index != std::string::npos) {
|
|
||||||
httpResult = stoi(result.substr(index + 1, 3));
|
|
||||||
}
|
|
||||||
index = result.find("\r\n\r\n");
|
|
||||||
if (index != std::string::npos) {
|
|
||||||
result.replace(0, index + 4, "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete ssl_client;
|
|
||||||
delete basic_client;
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
if (Helpers::toLower(url.c_str()).starts_with("http://")) {
|
|
||||||
HTTPClient * http = new HTTPClient;
|
|
||||||
if (http->begin(url.c_str())) {
|
|
||||||
for (JsonPair p : doc[header_s].as<JsonObject>()) {
|
|
||||||
http->addHeader(p.key().c_str(), p.value().as<std::string>().c_str());
|
|
||||||
content_set |= (emsesp::Helpers::toLower(p.key().c_str()) == "content-type");
|
|
||||||
}
|
|
||||||
if (value.length() || Helpers::toLower(method) == "post") {
|
|
||||||
if (!content_set) {
|
|
||||||
http->addHeader("Content-Type", value.starts_with('{') ? asyncsrv::T_application_json : asyncsrv::T_text_plain);
|
|
||||||
}
|
|
||||||
httpResult = http->POST(value.c_str());
|
|
||||||
} else {
|
|
||||||
httpResult = http->GET(); // normal GET
|
|
||||||
}
|
|
||||||
if (httpResult > 0) {
|
|
||||||
result = http->getString().c_str();
|
|
||||||
}
|
}
|
||||||
|
expr_new.replace(f, e - f, result.c_str());
|
||||||
}
|
}
|
||||||
http->end();
|
http->end();
|
||||||
delete http;
|
delete http;
|
||||||
}
|
}
|
||||||
if (httpResult == 200) {
|
|
||||||
std::string key = doc[key_s] | "";
|
|
||||||
JsonDocument keys_doc; // JsonDocument to hold "keys" after doc is parsed with HTTP body
|
|
||||||
if (doc[keys_s].is<JsonArray>()) {
|
|
||||||
keys_doc.set(doc[keys_s].as<JsonArray>());
|
|
||||||
}
|
|
||||||
JsonArray keys = keys_doc.as<JsonArray>();
|
|
||||||
if (key.length() || !keys.isNull()) {
|
|
||||||
doc.clear();
|
|
||||||
if (DeserializationError::Ok == deserializeJson(doc, result)) {
|
|
||||||
if (key.length()) {
|
|
||||||
result = doc[key.c_str()].as<std::string>();
|
|
||||||
} else {
|
|
||||||
JsonVariant json = doc.as<JsonVariant>();
|
|
||||||
for (JsonVariant keys_key : keys) {
|
|
||||||
if (keys_key.is<std::string>() && json.is<JsonObject>()) {
|
|
||||||
json = json[keys_key.as<std::string>()].as<JsonVariant>();
|
|
||||||
} else if (keys_key.is<int>() && json.is<JsonArray>()) {
|
|
||||||
json = json[keys_key.as<int>()].as<JsonVariant>();
|
|
||||||
} else {
|
|
||||||
break; // type mismatch
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result = json.as<std::string>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
expr_new.replace(f, e - f, result);
|
|
||||||
} else if (httpResult != 0) {
|
|
||||||
EMSESP::logger().warning("URL command failed with https code: %d, response: %s", httpResult, result.c_str());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
f = expr_new.find_first_of('{', e);
|
f = expr_new.find_first_of('{', e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,15 +37,6 @@
|
|||||||
#include "../test/test.h"
|
#include "../test/test.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef NO_TLS_SUPPORT
|
|
||||||
#define ENABLE_SMTP
|
|
||||||
#define USE_ESP_SSLCLIENT
|
|
||||||
#define READYCLIENT_SSL_CLIENT ESP_SSLClient
|
|
||||||
#define READYCLIENT_TYPE_1 // TYPE 1 when using ESP_SSLClient
|
|
||||||
#include <ESP_SSLClient.h>
|
|
||||||
#include <ReadyMail.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace emsesp {
|
namespace emsesp {
|
||||||
|
|
||||||
// Languages supported. Note: the order is important
|
// Languages supported. Note: the order is important
|
||||||
@@ -114,115 +105,6 @@ bool System::command_send(const char * value, const int8_t id) {
|
|||||||
return EMSESP::txservice_.send_raw(value); // ignore id
|
return EMSESP::txservice_.send_raw(value); // ignore id
|
||||||
}
|
}
|
||||||
|
|
||||||
bool System::command_sendmail(const char * value, const int8_t id) {
|
|
||||||
bool enabled = false;
|
|
||||||
bool ssl, starttls;
|
|
||||||
uint16_t port;
|
|
||||||
String server, login, pass, sender, recp, subject;
|
|
||||||
EMSESP::webSettingsService.read([&](WebSettings & settings) {
|
|
||||||
enabled = settings.email_enabled;
|
|
||||||
ssl = settings.email_ssl;
|
|
||||||
starttls = settings.email_starttls;
|
|
||||||
server = settings.email_server;
|
|
||||||
port = settings.email_port;
|
|
||||||
login = settings.email_login;
|
|
||||||
pass = settings.email_pass;
|
|
||||||
sender = settings.email_sender;
|
|
||||||
recp = settings.email_recp;
|
|
||||||
subject = settings.email_subject;
|
|
||||||
});
|
|
||||||
if (!enabled) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
LOG_DEBUG("Command sendmail port %d%s called with '%s'", port, ssl ? " (SSL)" : starttls ? " (STARTTLS)" : "", value);
|
|
||||||
// LOG_DEBUG("Command sendmail port %d called with '%s'", port, value);
|
|
||||||
bool success = false;
|
|
||||||
|
|
||||||
#ifndef NO_TLS_SUPPORT
|
|
||||||
WiFiClient * basic_client = new WiFiClient;
|
|
||||||
ESP_SSLClient * ssl_client = new ESP_SSLClient;
|
|
||||||
ReadyClient * r_client = new ReadyClient(*ssl_client);
|
|
||||||
SMTPClient * smtp = new SMTPClient(*r_client);
|
|
||||||
|
|
||||||
ssl_client->setClient(basic_client);
|
|
||||||
ssl_client->setInsecure();
|
|
||||||
ssl_client->setBufferSizes(1024, 1024);
|
|
||||||
r_client->addPort(port, starttls ? readymail_protocol_tls : ssl ? readymail_protocol_ssl : readymail_protocol_plain_text);
|
|
||||||
|
|
||||||
// smtp->connect(server, port, sendmailCallback);
|
|
||||||
smtp->connect(server, port);
|
|
||||||
if (!smtp->isConnected()) {
|
|
||||||
LOG_ERROR("Sendmail connection error");
|
|
||||||
delete smtp;
|
|
||||||
delete r_client;
|
|
||||||
delete ssl_client;
|
|
||||||
delete basic_client;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// LOG_INFO("authenticate %s:%s", login.c_str(), pass.c_str());
|
|
||||||
smtp->authenticate(login, pass, readymail_auth_password);
|
|
||||||
if (!smtp->isAuthenticated()) {
|
|
||||||
LOG_ERROR("Sendmail authenticate error");
|
|
||||||
delete smtp;
|
|
||||||
delete r_client;
|
|
||||||
delete ssl_client;
|
|
||||||
delete basic_client;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
JsonDocument doc;
|
|
||||||
String body = value;
|
|
||||||
if (body.length()) {
|
|
||||||
auto error = deserializeJson(doc, (const char *)value);
|
|
||||||
if (!error && doc.as<JsonObject>().size() >= 0) {
|
|
||||||
subject = doc["subject"] | subject;
|
|
||||||
recp = doc["to"] | recp;
|
|
||||||
sender = doc["from"] | sender;
|
|
||||||
body = doc["body"] | body;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SMTPMessage & msg = smtp->getMessage();
|
|
||||||
msg.headers.add(rfc822_subject, subject);
|
|
||||||
msg.headers.add(rfc822_from, sender);
|
|
||||||
msg.headers.add(rfc822_to, recp);
|
|
||||||
|
|
||||||
// Use addCustom to add custom header e.g. Importance and Priority.
|
|
||||||
// msg.headers.addCustom("Importance", PRIORITY);
|
|
||||||
// msg.headers.addCustom("X-MSMail-Priority", PRIORITY);
|
|
||||||
// msg.headers.addCustom("X-Priority", PRIORITY_NUM);
|
|
||||||
EMSESP::webSchedulerService.computed_value.clear();
|
|
||||||
EMSESP::webSchedulerService.raw_value = body.c_str();
|
|
||||||
for (uint16_t wait = 0; wait < 2000 && !EMSESP::webSchedulerService.raw_value.empty(); wait++) {
|
|
||||||
delay(1);
|
|
||||||
}
|
|
||||||
if (!EMSESP::webSchedulerService.computed_value.empty()) {
|
|
||||||
body = EMSESP::webSchedulerService.computed_value.c_str();
|
|
||||||
EMSESP::webSchedulerService.computed_value.clear();
|
|
||||||
EMSESP::webSchedulerService.computed_value.shrink_to_fit(); // free allocated memory
|
|
||||||
}
|
|
||||||
msg.text.body(body);
|
|
||||||
|
|
||||||
// bodyText.replace("\r\n", "<br>\r\n");
|
|
||||||
// msg.html.body("<html><body><div style=\"color:#cc0066;\">" + bodyText + "</div></body></html>");
|
|
||||||
// msg.html.transferEncoding("base64");
|
|
||||||
|
|
||||||
// With embedFile function, the html message will send as attachment.
|
|
||||||
// if (EMBED_MESSAGE)
|
|
||||||
// msg.html.embedFile(true, "msg.html", embed_message_type_attachment);
|
|
||||||
|
|
||||||
msg.timestamp = time(nullptr);
|
|
||||||
|
|
||||||
success = smtp->send(msg);
|
|
||||||
|
|
||||||
delete smtp;
|
|
||||||
delete r_client;
|
|
||||||
delete ssl_client;
|
|
||||||
delete basic_client;
|
|
||||||
#endif
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
// return string of languages and count
|
// return string of languages and count
|
||||||
std::string System::languages_string() {
|
std::string System::languages_string() {
|
||||||
std::string languages_string = std::to_string(NUM_LANGUAGES) + " languages (";
|
std::string languages_string = std::to_string(NUM_LANGUAGES) + " languages (";
|
||||||
@@ -355,8 +237,7 @@ bool System::command_message(const char * value, const int8_t id, JsonObject out
|
|||||||
LOG_INFO("Message: %s", EMSESP::webSchedulerService.computed_value.c_str()); // send to log
|
LOG_INFO("Message: %s", EMSESP::webSchedulerService.computed_value.c_str()); // send to log
|
||||||
Mqtt::queue_publish(F_(message), EMSESP::webSchedulerService.computed_value); // send to MQTT if enabled
|
Mqtt::queue_publish(F_(message), EMSESP::webSchedulerService.computed_value); // send to MQTT if enabled
|
||||||
output["api_data"] = EMSESP::webSchedulerService.computed_value; // send to API
|
output["api_data"] = EMSESP::webSchedulerService.computed_value; // send to API
|
||||||
EMSESP::webSchedulerService.computed_value.clear();
|
|
||||||
EMSESP::webSchedulerService.computed_value.shrink_to_fit();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -580,6 +461,7 @@ void System::system_restart(const char * partitionname) {
|
|||||||
|
|
||||||
Mqtt::disconnect(); // gracefully disconnect MQTT, needed for QOS1
|
Mqtt::disconnect(); // gracefully disconnect MQTT, needed for QOS1
|
||||||
EMSuart::stop(); // stop UART so there is no interference
|
EMSuart::stop(); // stop UART so there is no interference
|
||||||
|
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
delay(1000); // wait 1 second
|
delay(1000); // wait 1 second
|
||||||
ESP.restart(); // ka-boom! - this is the only place where the ESP32 restart is called
|
ESP.restart(); // ka-boom! - this is the only place where the ESP32 restart is called
|
||||||
@@ -644,6 +526,29 @@ void System::syslog_init() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// start or reconfigure modbus
|
||||||
|
void System::modbus_init() {
|
||||||
|
EMSESP::webSettingsService.read([&](WebSettings & settings) {
|
||||||
|
if (settings.modbus_enabled) {
|
||||||
|
if (EMSESP::modbus_ == nullptr) {
|
||||||
|
EMSESP::modbus_ = new Modbus;
|
||||||
|
EMSESP::modbus_->start(1, settings.modbus_port, settings.modbus_max_clients, settings.modbus_timeout * 1000);
|
||||||
|
} else if (settings.modbus_port != modbus_port_ || settings.modbus_max_clients != modbus_max_clients_ || settings.modbus_timeout != modbus_timeout_) {
|
||||||
|
EMSESP::modbus_->stop();
|
||||||
|
EMSESP::modbus_->start(1, settings.modbus_port, settings.modbus_max_clients, settings.modbus_timeout * 1000);
|
||||||
|
}
|
||||||
|
} else if (EMSESP::modbus_ != nullptr) {
|
||||||
|
EMSESP::modbus_->stop();
|
||||||
|
delete EMSESP::modbus_;
|
||||||
|
EMSESP::modbus_ = nullptr;
|
||||||
|
}
|
||||||
|
modbus_enabled_ = settings.modbus_enabled;
|
||||||
|
modbus_port_ = settings.modbus_port;
|
||||||
|
modbus_max_clients_ = settings.modbus_max_clients;
|
||||||
|
modbus_timeout_ = settings.modbus_timeout;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// read specific major system settings to store locally for faster access
|
// read specific major system settings to store locally for faster access
|
||||||
void System::store_settings(WebSettings & settings) {
|
void System::store_settings(WebSettings & settings) {
|
||||||
version_ = settings.version;
|
version_ = settings.version;
|
||||||
@@ -681,24 +586,6 @@ void System::store_settings(WebSettings & settings) {
|
|||||||
|
|
||||||
locale_ = settings.locale;
|
locale_ = settings.locale;
|
||||||
developer_mode_ = settings.developer_mode;
|
developer_mode_ = settings.developer_mode;
|
||||||
// start services
|
|
||||||
if (settings.modbus_enabled) {
|
|
||||||
if (EMSESP::modbus_ == nullptr) {
|
|
||||||
EMSESP::modbus_ = new Modbus;
|
|
||||||
EMSESP::modbus_->start(1, settings.modbus_port, settings.modbus_max_clients, settings.modbus_timeout * 1000);
|
|
||||||
} else if (settings.modbus_port != modbus_port_ || settings.modbus_max_clients != modbus_max_clients_ || settings.modbus_timeout != modbus_timeout_) {
|
|
||||||
EMSESP::modbus_->stop();
|
|
||||||
EMSESP::modbus_->start(1, settings.modbus_port, settings.modbus_max_clients, settings.modbus_timeout * 1000);
|
|
||||||
}
|
|
||||||
} else if (EMSESP::modbus_ != nullptr) {
|
|
||||||
EMSESP::modbus_->stop();
|
|
||||||
delete EMSESP::modbus_;
|
|
||||||
EMSESP::modbus_ = nullptr;
|
|
||||||
}
|
|
||||||
modbus_enabled_ = settings.modbus_enabled;
|
|
||||||
modbus_port_ = settings.modbus_port;
|
|
||||||
modbus_max_clients_ = settings.modbus_max_clients;
|
|
||||||
modbus_timeout_ = settings.modbus_timeout;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Starts up core services
|
// Starts up core services
|
||||||
@@ -722,11 +609,20 @@ void System::start() {
|
|||||||
appfree_ = esp_ota_get_running_partition()->size / 1024 - appused_;
|
appfree_ = esp_ota_get_running_partition()->size / 1024 - appused_;
|
||||||
refreshHeapMem(); // refresh free heap and max alloc heap
|
refreshHeapMem(); // refresh free heap and max alloc heap
|
||||||
#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2
|
#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
#if ESP_IDF_VERSION_MAJOR < 5
|
||||||
|
temp_sensor_config_t temp_sensor = TSENS_CONFIG_DEFAULT();
|
||||||
|
temp_sensor_get_config(&temp_sensor);
|
||||||
|
temp_sensor.dac_offset = TSENS_DAC_DEFAULT; // DEFAULT: range:-10℃ ~ 80℃, error < 1℃.
|
||||||
|
temp_sensor_set_config(temp_sensor);
|
||||||
|
temp_sensor_start();
|
||||||
|
temp_sensor_read_celsius(&temperature_);
|
||||||
|
#else
|
||||||
temperature_sensor_config_t temp_sensor_config = TEMPERATURE_SENSOR_CONFIG_DEFAULT(-10, 80);
|
temperature_sensor_config_t temp_sensor_config = TEMPERATURE_SENSOR_CONFIG_DEFAULT(-10, 80);
|
||||||
temperature_sensor_install(&temp_sensor_config, &temperature_handle_);
|
temperature_sensor_install(&temp_sensor_config, &temperature_handle_);
|
||||||
temperature_sensor_enable(temperature_handle_);
|
temperature_sensor_enable(temperature_handle_);
|
||||||
temperature_sensor_get_celsius(temperature_handle_, &temperature_);
|
temperature_sensor_get_celsius(temperature_handle_, &temperature_);
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
EMSESP::esp32React.getNetworkSettingsService()->read([&](NetworkSettings & networkSettings) {
|
EMSESP::esp32React.getNetworkSettingsService()->read([&](NetworkSettings & networkSettings) {
|
||||||
@@ -739,6 +635,7 @@ void System::start() {
|
|||||||
network_init(); // network
|
network_init(); // network
|
||||||
uart_init(); // start UART
|
uart_init(); // start UART
|
||||||
syslog_init(); // start syslog
|
syslog_init(); // start syslog
|
||||||
|
modbus_init(); // start modbus
|
||||||
}
|
}
|
||||||
|
|
||||||
// button single click
|
// button single click
|
||||||
@@ -947,9 +844,16 @@ void System::send_info_mqtt() {
|
|||||||
doc["IPv4 gateway"] = uuid::printable_to_string(WiFi.gatewayIP());
|
doc["IPv4 gateway"] = uuid::printable_to_string(WiFi.gatewayIP());
|
||||||
doc["IPv4 nameserver"] = uuid::printable_to_string(WiFi.dnsIP());
|
doc["IPv4 nameserver"] = uuid::printable_to_string(WiFi.dnsIP());
|
||||||
|
|
||||||
|
#if ESP_IDF_VERSION_MAJOR < 5
|
||||||
|
if (WiFi.localIPv6().toString() != "0000:0000:0000:0000:0000:0000:0000:0000" && WiFi.localIPv6().toString() != "::") {
|
||||||
|
doc["IPv6 address"] = uuid::printable_to_string(WiFi.localIPv6());
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (WiFi.linkLocalIPv6().toString() != "0000:0000:0000:0000:0000:0000:0000:0000" && WiFi.linkLocalIPv6().toString() != "::") {
|
if (WiFi.linkLocalIPv6().toString() != "0000:0000:0000:0000:0000:0000:0000:0000" && WiFi.linkLocalIPv6().toString() != "::") {
|
||||||
doc["IPv6 address"] = uuid::printable_to_string(WiFi.linkLocalIPv6());
|
doc["IPv6 address"] = uuid::printable_to_string(WiFi.linkLocalIPv6());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
Mqtt::queue_publish_retain(F_(info), doc.as<JsonObject>()); // topic called "info" and it's Retained
|
Mqtt::queue_publish_retain(F_(info), doc.as<JsonObject>()); // topic called "info" and it's Retained
|
||||||
@@ -1058,11 +962,12 @@ void System::network_init() {
|
|||||||
delay(500);
|
delay(500);
|
||||||
digitalWrite(eth_power_, HIGH);
|
digitalWrite(eth_power_, HIGH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ESP_IDF_VERSION_MAJOR < 5
|
||||||
|
eth_present_ = ETH.begin(phy_addr, power, mdc, mdio, type, clock_mode);
|
||||||
|
#else
|
||||||
eth_present_ = ETH.begin(type, phy_addr, mdc, mdio, power, clock_mode);
|
eth_present_ = ETH.begin(type, phy_addr, mdc, mdio, power, clock_mode);
|
||||||
if (eth_present_) {
|
#endif
|
||||||
// Push hostname to the ETH netif immediately after it's created
|
|
||||||
ETH.setHostname(hostname_.c_str());
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1074,9 +979,13 @@ void System::system_check() {
|
|||||||
|
|
||||||
#ifndef EMSESP_STANDALONE
|
#ifndef EMSESP_STANDALONE
|
||||||
#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2
|
#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
#if ESP_IDF_VERSION_MAJOR < 5
|
||||||
|
temp_sensor_read_celsius(&temperature_);
|
||||||
|
#else
|
||||||
temperature_sensor_get_celsius(temperature_handle_, &temperature_);
|
temperature_sensor_get_celsius(temperature_handle_, &temperature_);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef EMSESP_PINGTEST
|
#ifdef EMSESP_PINGTEST
|
||||||
static uint64_t ping_count = 0;
|
static uint64_t ping_count = 0;
|
||||||
@@ -1128,7 +1037,6 @@ void System::commands_init() {
|
|||||||
Command::add(EMSdevice::DeviceType::SYSTEM, F_(read), System::command_read, FL_(read_cmd), CommandFlag::ADMIN_ONLY);
|
Command::add(EMSdevice::DeviceType::SYSTEM, F_(read), System::command_read, FL_(read_cmd), CommandFlag::ADMIN_ONLY);
|
||||||
Command::add(EMSdevice::DeviceType::SYSTEM, F_(send), System::command_send, FL_(send_cmd), CommandFlag::ADMIN_ONLY);
|
Command::add(EMSdevice::DeviceType::SYSTEM, F_(send), System::command_send, FL_(send_cmd), CommandFlag::ADMIN_ONLY);
|
||||||
Command::add(EMSdevice::DeviceType::SYSTEM, F_(fetch), System::command_fetch, FL_(fetch_cmd), CommandFlag::ADMIN_ONLY);
|
Command::add(EMSdevice::DeviceType::SYSTEM, F_(fetch), System::command_fetch, FL_(fetch_cmd), CommandFlag::ADMIN_ONLY);
|
||||||
Command::add(EMSdevice::DeviceType::SYSTEM, F_(sendmail), System::command_sendmail, FL_(sendmail_cmd), CommandFlag::ADMIN_ONLY);
|
|
||||||
Command::add(EMSdevice::DeviceType::SYSTEM, F_(restart), System::command_restart, FL_(restart_cmd), CommandFlag::ADMIN_ONLY);
|
Command::add(EMSdevice::DeviceType::SYSTEM, F_(restart), System::command_restart, FL_(restart_cmd), CommandFlag::ADMIN_ONLY);
|
||||||
Command::add(EMSdevice::DeviceType::SYSTEM, F_(format), System::command_format, FL_(format_cmd), CommandFlag::ADMIN_ONLY);
|
Command::add(EMSdevice::DeviceType::SYSTEM, F_(format), System::command_format, FL_(format_cmd), CommandFlag::ADMIN_ONLY);
|
||||||
Command::add(EMSdevice::DeviceType::SYSTEM, F_(txpause), System::command_txpause, FL_(txpause_cmd), CommandFlag::ADMIN_ONLY);
|
Command::add(EMSdevice::DeviceType::SYSTEM, F_(txpause), System::command_txpause, FL_(txpause_cmd), CommandFlag::ADMIN_ONLY);
|
||||||
@@ -1377,9 +1285,16 @@ void System::show_system(uuid::console::Shell & shell) {
|
|||||||
shell.printfln(" IPv4 address: %s/%s", uuid::printable_to_string(WiFi.localIP()).c_str(), uuid::printable_to_string(WiFi.subnetMask()).c_str());
|
shell.printfln(" IPv4 address: %s/%s", uuid::printable_to_string(WiFi.localIP()).c_str(), uuid::printable_to_string(WiFi.subnetMask()).c_str());
|
||||||
shell.printfln(" IPv4 gateway: %s", uuid::printable_to_string(WiFi.gatewayIP()).c_str());
|
shell.printfln(" IPv4 gateway: %s", uuid::printable_to_string(WiFi.gatewayIP()).c_str());
|
||||||
shell.printfln(" IPv4 nameserver: %s", uuid::printable_to_string(WiFi.dnsIP()).c_str());
|
shell.printfln(" IPv4 nameserver: %s", uuid::printable_to_string(WiFi.dnsIP()).c_str());
|
||||||
|
#if ESP_IDF_VERSION_MAJOR < 5
|
||||||
|
if (WiFi.localIPv6().toString() != "0000:0000:0000:0000:0000:0000:0000:0000" && WiFi.localIPv6().toString() != "::") {
|
||||||
|
shell.printfln(" IPv6 address: %s", uuid::printable_to_string(WiFi.localIPv6()).c_str());
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (WiFi.linkLocalIPv6().toString() != "0000:0000:0000:0000:0000:0000:0000:0000" && WiFi.linkLocalIPv6().toString() != "::") {
|
if (WiFi.linkLocalIPv6().toString() != "0000:0000:0000:0000:0000:0000:0000:0000" && WiFi.linkLocalIPv6().toString() != "::") {
|
||||||
shell.printfln(" IPv6 address: %s", uuid::printable_to_string(WiFi.linkLocalIPv6()).c_str());
|
shell.printfln(" IPv6 address: %s", uuid::printable_to_string(WiFi.linkLocalIPv6()).c_str());
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WL_CONNECT_FAILED:
|
case WL_CONNECT_FAILED:
|
||||||
@@ -1410,9 +1325,15 @@ void System::show_system(uuid::console::Shell & shell) {
|
|||||||
shell.printfln(" IPv4 address: %s/%s", uuid::printable_to_string(ETH.localIP()).c_str(), uuid::printable_to_string(ETH.subnetMask()).c_str());
|
shell.printfln(" IPv4 address: %s/%s", uuid::printable_to_string(ETH.localIP()).c_str(), uuid::printable_to_string(ETH.subnetMask()).c_str());
|
||||||
shell.printfln(" IPv4 gateway: %s", uuid::printable_to_string(ETH.gatewayIP()).c_str());
|
shell.printfln(" IPv4 gateway: %s", uuid::printable_to_string(ETH.gatewayIP()).c_str());
|
||||||
shell.printfln(" IPv4 nameserver: %s", uuid::printable_to_string(ETH.dnsIP()).c_str());
|
shell.printfln(" IPv4 nameserver: %s", uuid::printable_to_string(ETH.dnsIP()).c_str());
|
||||||
|
#if ESP_IDF_VERSION_MAJOR < 5
|
||||||
|
if (ETH.localIPv6().toString() != "0000:0000:0000:0000:0000:0000:0000:0000" && ETH.localIPv6().toString() != "::") {
|
||||||
|
shell.printfln(" IPv6 address: %s", uuid::printable_to_string(ETH.localIPv6()).c_str());
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (ETH.linkLocalIPv6().toString() != "0000:0000:0000:0000:0000:0000:0000:0000" && ETH.linkLocalIPv6().toString() != "::") {
|
if (ETH.linkLocalIPv6().toString() != "0000:0000:0000:0000:0000:0000:0000:0000" && ETH.linkLocalIPv6().toString() != "::") {
|
||||||
shell.printfln(" IPv6 address: %s", uuid::printable_to_string(ETH.linkLocalIPv6()).c_str());
|
shell.printfln(" IPv6 address: %s", uuid::printable_to_string(ETH.linkLocalIPv6()).c_str());
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
shell.println();
|
shell.println();
|
||||||
|
|
||||||
@@ -1434,10 +1355,10 @@ void System::show_system(uuid::console::Shell & shell) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
shell.println();
|
shell.println();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// see if there is a restore of an older settings file that needs to be applied
|
// see if there is a restore of an older settings file that needs to be applied
|
||||||
// note there can be only one file at a time
|
// note there can be only one file at a time
|
||||||
bool System::check_restore() {
|
bool System::check_restore() {
|
||||||
@@ -1737,8 +1658,8 @@ bool System::check_upgrade() {
|
|||||||
return false; // no reboot required
|
return false; // no reboot required
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef EMSESP_STANDALONE
|
|
||||||
// map each config filename to its human-readable section key
|
// map each config filename to its human-readable section key
|
||||||
|
#ifndef EMSESP_STANDALONE
|
||||||
static const std::pair<const char *, const char *> SECTION_MAP[] = {
|
static const std::pair<const char *, const char *> SECTION_MAP[] = {
|
||||||
{NETWORK_SETTINGS_FILE, "Network"},
|
{NETWORK_SETTINGS_FILE, "Network"},
|
||||||
{AP_SETTINGS_FILE, "AP"},
|
{AP_SETTINGS_FILE, "AP"},
|
||||||
@@ -1853,16 +1774,27 @@ void System::exportSystemBackup(JsonObject output) {
|
|||||||
|
|
||||||
const char * nvs_part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, "nvs1") ? "nvs1" : "nvs"; // nvs1 is on 16MBs
|
const char * nvs_part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, "nvs1") ? "nvs1" : "nvs"; // nvs1 is on 16MBs
|
||||||
nvs_iterator_t it = nullptr;
|
nvs_iterator_t it = nullptr;
|
||||||
esp_err_t err = nvs_entry_find(nvs_part, "ems-esp", NVS_TYPE_ANY, &it);
|
#if ESP_IDF_VERSION_MAJOR < 5
|
||||||
|
it = nvs_entry_find(nvs_part, "ems-esp", NVS_TYPE_ANY);
|
||||||
|
if (it == nullptr) {
|
||||||
|
#else
|
||||||
|
esp_err_t err = nvs_entry_find(nvs_part, "ems-esp", NVS_TYPE_ANY, &it);
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
|
#endif
|
||||||
LOG_ERROR("Failed to find NVS entry for %s", nvs_part);
|
LOG_ERROR("Failed to find NVS entry for %s", nvs_part);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonArray entries = node["nvs"].to<JsonArray>();
|
JsonArray entries = node["nvs"].to<JsonArray>();
|
||||||
|
#if ESP_IDF_VERSION_MAJOR < 5
|
||||||
|
while (it != nullptr) {
|
||||||
|
nvs_entry_info_t info;
|
||||||
|
nvs_entry_info(it, &info);
|
||||||
|
#else
|
||||||
while (err == ESP_OK) {
|
while (err == ESP_OK) {
|
||||||
nvs_entry_info_t info;
|
nvs_entry_info_t info;
|
||||||
nvs_entry_info(it, &info);
|
nvs_entry_info(it, &info);
|
||||||
|
#endif
|
||||||
JsonObject entry = entries.add<JsonObject>();
|
JsonObject entry = entries.add<JsonObject>();
|
||||||
entry["type"] = info.type;
|
entry["type"] = info.type;
|
||||||
entry["key"] = info.key;
|
entry["key"] = info.key;
|
||||||
@@ -1897,8 +1829,14 @@ void System::exportSystemBackup(JsonObject output) {
|
|||||||
entry["value"] = EMSESP::nvs_.getString(info.key);
|
entry["value"] = EMSESP::nvs_.getString(info.key);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if ESP_IDF_VERSION_MAJOR < 5
|
||||||
|
it = nvs_entry_next(it);
|
||||||
|
}
|
||||||
|
#else
|
||||||
err = nvs_entry_next(&it);
|
err = nvs_entry_next(&it);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (it != nullptr) {
|
if (it != nullptr) {
|
||||||
nvs_release_iterator(it);
|
nvs_release_iterator(it);
|
||||||
@@ -2700,12 +2638,12 @@ bool System::command_info(const char * value, const int8_t id, JsonObject output
|
|||||||
node["maxWebLogBuffer"] = settings.weblog_buffer;
|
node["maxWebLogBuffer"] = settings.weblog_buffer;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#if defined(EMSESP_UNITY)
|
#if defined(EMSESP_UNITY)
|
||||||
node["webLogBuffer"] = 0;
|
node["webLogBuffer"] = 0;
|
||||||
#else
|
#else
|
||||||
node["webLogBuffer"] = EMSESP::webLogService.num_log_messages();
|
node["webLogBuffer"] = EMSESP::webLogService.num_log_messages();
|
||||||
#endif
|
#endif
|
||||||
*/
|
*/
|
||||||
node["modbusEnabled"] = settings.modbus_enabled;
|
node["modbusEnabled"] = settings.modbus_enabled;
|
||||||
node["forceHeatingOff"] = settings.boiler_heatingoff;
|
node["forceHeatingOff"] = settings.boiler_heatingoff;
|
||||||
node["developerMode"] = settings.developer_mode;
|
node["developerMode"] = settings.developer_mode;
|
||||||
@@ -3396,10 +3334,6 @@ void System::set_valid_system_gpios() {
|
|||||||
} else {
|
} else {
|
||||||
valid_system_gpios_ = string_range_to_vector("0-39", "6-11, 20, 24, 28-31");
|
valid_system_gpios_ = string_range_to_vector("0-39", "6-11, 20, 24, 28-31");
|
||||||
}
|
}
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
|
||||||
// https://docs.espressif.com/projects/esp-idf/en/v5.5.3/esp32c6/api-reference/peripherals/gpio.html
|
|
||||||
// 24-30 used for flash, 12-13 USB, 16-17 uart0
|
|
||||||
valid_system_gpios_ = string_range_to_vector("0-30", "12-13, 16-17, 24-30");
|
|
||||||
#elif defined(EMSESP_STANDALONE)
|
#elif defined(EMSESP_STANDALONE)
|
||||||
valid_system_gpios_ = string_range_to_vector("0-39");
|
valid_system_gpios_ = string_range_to_vector("0-39");
|
||||||
#endif
|
#endif
|
||||||
@@ -3449,6 +3383,24 @@ void System::remove_gpio(uint8_t pin, bool also_system) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// remove a gpio that has 0 for disable
|
||||||
|
void System::remove_optional_gpio(uint8_t pin) {
|
||||||
|
if (pin) {
|
||||||
|
remove_gpio(pin, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set unused gpios to default state input high-Z
|
||||||
|
void System::reset_unused_gpios() {
|
||||||
|
for (const auto & pin : valid_system_gpios_) {
|
||||||
|
auto it = std::find_if(used_gpios_.begin(), used_gpios_.end(), [pin](const GpioUsage & usage) { return usage.pin == pin; });
|
||||||
|
if (it == used_gpios_.end()) {
|
||||||
|
LOG_DEBUG("reset pin %d", pin);
|
||||||
|
pinMode(pin, INPUT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// return a list of GPIO's available for use
|
// return a list of GPIO's available for use
|
||||||
std::vector<uint8_t> System::available_gpios() {
|
std::vector<uint8_t> System::available_gpios() {
|
||||||
std::vector<uint8_t> gpios;
|
std::vector<uint8_t> gpios;
|
||||||
|
|||||||
@@ -37,7 +37,11 @@
|
|||||||
#include <uuid/log.h>
|
#include <uuid/log.h>
|
||||||
#include <PButton.h>
|
#include <PButton.h>
|
||||||
|
|
||||||
|
#if ESP_ARDUINO_VERSION_MAJOR < 3
|
||||||
|
#define EMSESP_RGB_WRITE neopixelWrite
|
||||||
|
#else
|
||||||
#define EMSESP_RGB_WRITE rgbLedWrite
|
#define EMSESP_RGB_WRITE rgbLedWrite
|
||||||
|
#endif
|
||||||
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
// there is no official API available on the original ESP32
|
// there is no official API available on the original ESP32
|
||||||
@@ -45,8 +49,12 @@ extern "C" {
|
|||||||
uint8_t temprature_sens_read();
|
uint8_t temprature_sens_read();
|
||||||
}
|
}
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2
|
#elif CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
#if ESP_IDF_VERSION_MAJOR < 5
|
||||||
|
#include "driver/temp_sensor.h"
|
||||||
|
#else
|
||||||
#include "driver/temperature_sensor.h"
|
#include "driver/temperature_sensor.h"
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
using uuid::console::Shell;
|
using uuid::console::Shell;
|
||||||
|
|
||||||
@@ -95,7 +103,6 @@ class System {
|
|||||||
static bool command_info(const char * value, const int8_t id, JsonObject output);
|
static bool command_info(const char * value, const int8_t id, JsonObject output);
|
||||||
static bool command_response(const char * value, const int8_t id, JsonObject output);
|
static bool command_response(const char * value, const int8_t id, JsonObject output);
|
||||||
static bool command_service(const char * cmd, const char * value);
|
static bool command_service(const char * cmd, const char * value);
|
||||||
static bool command_sendmail(const char * value, const int8_t id);
|
|
||||||
static bool command_txpause(const char * value, const int8_t id);
|
static bool command_txpause(const char * value, const int8_t id);
|
||||||
|
|
||||||
static bool get_value_info(JsonObject root, const char * cmd);
|
static bool get_value_info(JsonObject root, const char * cmd);
|
||||||
@@ -115,6 +122,7 @@ class System {
|
|||||||
void show_mem(const char * note);
|
void show_mem(const char * note);
|
||||||
void store_settings(class WebSettings & settings);
|
void store_settings(class WebSettings & settings);
|
||||||
void syslog_init();
|
void syslog_init();
|
||||||
|
void modbus_init();
|
||||||
bool check_upgrade();
|
bool check_upgrade();
|
||||||
bool check_restore();
|
bool check_restore();
|
||||||
void heartbeat_json(JsonObject output);
|
void heartbeat_json(JsonObject output);
|
||||||
@@ -369,6 +377,8 @@ class System {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void remove_gpio(uint8_t pin, bool also_system = false); // remove a gpio from both valid (optional) and used lists
|
static void remove_gpio(uint8_t pin, bool also_system = false); // remove a gpio from both valid (optional) and used lists
|
||||||
|
static void remove_optional_gpio(uint8_t pin);
|
||||||
|
static void reset_unused_gpios();
|
||||||
|
|
||||||
// Partition info map: partition name -> {version, size, install_date}
|
// Partition info map: partition name -> {version, size, install_date}
|
||||||
std::map<std::string, PartitionInfo, std::less<>, AllocatorPSRAM<std::pair<const std::string, PartitionInfo>>> partition_info_;
|
std::map<std::string, PartitionInfo, std::less<>, AllocatorPSRAM<std::pair<const std::string, PartitionInfo>>> partition_info_;
|
||||||
@@ -495,7 +505,9 @@ class System {
|
|||||||
uint32_t appfree_;
|
uint32_t appfree_;
|
||||||
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2
|
#if CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2
|
||||||
|
#if ESP_IDF_VERSION_MAJOR >= 5
|
||||||
temperature_sensor_handle_t temperature_handle_ = NULL;
|
temperature_sensor_handle_t temperature_handle_ = NULL;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
float temperature_ = 0;
|
float temperature_ = 0;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ uint8_t EMSbus::ems_mask_ = EMS_MASK_UNSET; // unset so its triggered
|
|||||||
uint8_t EMSbus::ems_bus_id_ = EMSESP_DEFAULT_EMS_BUS_ID;
|
uint8_t EMSbus::ems_bus_id_ = EMSESP_DEFAULT_EMS_BUS_ID;
|
||||||
uint8_t EMSbus::tx_mode_ = EMSESP_DEFAULT_TX_MODE;
|
uint8_t EMSbus::tx_mode_ = EMSESP_DEFAULT_TX_MODE;
|
||||||
uint8_t EMSbus::tx_state_ = Telegram::Operation::NONE;
|
uint8_t EMSbus::tx_state_ = Telegram::Operation::NONE;
|
||||||
|
bool EMSbus::isEMS2_ = false;
|
||||||
|
|
||||||
uuid::log::Logger EMSbus::logger_{F_(telegram), uuid::log::Facility::CONSOLE};
|
uuid::log::Logger EMSbus::logger_{F_(telegram), uuid::log::Facility::CONSOLE};
|
||||||
|
|
||||||
@@ -206,7 +207,9 @@ void RxService::add(uint8_t * data, uint8_t length) {
|
|||||||
message_data = data + 6;
|
message_data = data + 6;
|
||||||
message_length = length - 7;
|
message_length = length - 7;
|
||||||
}
|
}
|
||||||
|
if (type_id > 0x0FF && message_length > 1) { // used for auto tx_mode
|
||||||
|
set_ems2();
|
||||||
|
}
|
||||||
// if we're watching and "raw" print out actual telegram as bytes to the console
|
// if we're watching and "raw" print out actual telegram as bytes to the console
|
||||||
// including the CRC at the end
|
// including the CRC at the end
|
||||||
if (EMSESP::watch() == EMSESP::Watch::WATCH_RAW) {
|
if (EMSESP::watch() == EMSESP::Watch::WATCH_RAW) {
|
||||||
|
|||||||
@@ -159,16 +159,23 @@ class EMSbus {
|
|||||||
public:
|
public:
|
||||||
static uuid::log::Logger logger_;
|
static uuid::log::Logger logger_;
|
||||||
|
|
||||||
static constexpr uint8_t EMS_MASK_UNSET = 0xFF; // EMS bus type (budrus/junkers) hasn't been detected yet
|
static constexpr uint8_t EMS_MASK_UNSET = 0xFF; // EMS bus type (budrus/junkers) hasn't been detected yet
|
||||||
static constexpr uint8_t EMS_MASK_HT3 = 0x80; // EMS bus type Junkers/HT3
|
static constexpr uint8_t EMS_MASK_HT3 = 0x80; // EMS bus type Junkers/HT3
|
||||||
static constexpr uint8_t EMS_MASK_BUDERUS = 0xFF; // EMS bus type Buderus
|
static constexpr uint8_t EMS_MASK_BUDERUS = 0xFF; // EMS bus type Buderus
|
||||||
static constexpr uint8_t EMS_TX_ERROR_LIMIT = 10; // % limit of failed Tx read/write attempts before showing a warning
|
static constexpr uint8_t EMS_TX_ERROR_LIMIT = 10; // % limit of failed Tx read/write attempts before showing a warning
|
||||||
static constexpr uint8_t EMS_POLL_MATCH_LIMIT = 3; // consecutive poll matches needed before declaring bus connected
|
|
||||||
|
|
||||||
static bool is_ht3() {
|
static bool is_ht3() {
|
||||||
return (ems_mask_ == EMS_MASK_HT3);
|
return (ems_mask_ == EMS_MASK_HT3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool is_ems2() {
|
||||||
|
return isEMS2_;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_ems2() {
|
||||||
|
isEMS2_ = true;;
|
||||||
|
}
|
||||||
|
|
||||||
static uint8_t ems_mask() {
|
static uint8_t ems_mask() {
|
||||||
return ems_mask_;
|
return ems_mask_;
|
||||||
}
|
}
|
||||||
@@ -211,6 +218,7 @@ class EMSbus {
|
|||||||
if (!last_bus_activity_) {
|
if (!last_bus_activity_) {
|
||||||
bus_uptime_start_ = timestamp;
|
bus_uptime_start_ = timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
last_bus_activity_ = timestamp;
|
last_bus_activity_ = timestamp;
|
||||||
bus_connected_ = true;
|
bus_connected_ = true;
|
||||||
}
|
}
|
||||||
@@ -242,6 +250,7 @@ class EMSbus {
|
|||||||
static uint8_t ems_bus_id_; // the bus id, which configurable and stored in settings
|
static uint8_t ems_bus_id_; // the bus id, which configurable and stored in settings
|
||||||
static uint8_t tx_mode_; // local copy of the tx mode
|
static uint8_t tx_mode_; // local copy of the tx mode
|
||||||
static uint8_t tx_state_; // state of the Tx line (NONE or waiting on a TX_READ or TX_WRITE)
|
static uint8_t tx_state_; // state of the Tx line (NONE or waiting on a TX_READ or TX_WRITE)
|
||||||
|
static bool isEMS2_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RxService : public EMSbus {
|
class RxService : public EMSbus {
|
||||||
|
|||||||
@@ -39,11 +39,11 @@ Connect::Connect(uint8_t device_type, uint8_t device_id, uint8_t product_id, con
|
|||||||
DeviceValueUOM::DEGREES);
|
DeviceValueUOM::DEGREES);
|
||||||
// Roomthermostats
|
// Roomthermostats
|
||||||
for (uint8_t i = 0; i < 16; i++) {
|
for (uint8_t i = 0; i < 16; i++) {
|
||||||
register_telegram_type(0x0BDD + i, "Room", false, MAKE_PF_CB(process_roomThermostat)); // broadcasted
|
register_telegram_type(0x0BDD + i, "Room", false, MAKE_PF_CB(process_roomThermostat)); // broadcasted
|
||||||
register_telegram_type(0x0B3D + i, "Roomname", false, MAKE_PF_CB(process_roomThermostatName), 100); // fetch for active circuits
|
register_telegram_type(0x0B3D + i, "Roomname", false, MAKE_PF_CB(process_roomThermostatName), 100); // fetch for active circuits
|
||||||
register_telegram_type(0x0BB5 + i, "Roomsettings", false, MAKE_PF_CB(process_roomThermostatSettings), 8); // fetch for active circuits
|
register_telegram_type(0x0BB5 + i, "Roomsettings", false, MAKE_PF_CB(process_roomThermostatSettings), 8); // fetch for active circuits
|
||||||
register_telegram_type(0x1230 + i, "Roomparams", false, MAKE_PF_CB(process_roomThermostatParam)); // fetch for active circuits
|
register_telegram_type(0x1230 + i, "Roomparams", false, MAKE_PF_CB(process_roomThermostatParam)); // fetch for active circuits
|
||||||
register_telegram_type(0x1244 + i, "Roomdata", false, MAKE_PF_CB(process_roomThermostatData)); // broadcasted
|
register_telegram_type(0x1244 + i, "Roomdata", false, MAKE_PF_CB(process_roomThermostatData)); // broadcasted
|
||||||
}
|
}
|
||||||
register_telegram_type(0xDB65, "Roomschedule", true, MAKE_PF_CB(process_roomSchedule));
|
register_telegram_type(0xDB65, "Roomschedule", true, MAKE_PF_CB(process_roomSchedule));
|
||||||
// 0x2040, broadcast 36 bytes:
|
// 0x2040, broadcast 36 bytes:
|
||||||
|
|||||||
@@ -166,14 +166,14 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
|
|||||||
set2_typeids = {0x0421, 0x0422, 0x0423, 0x0424};
|
set2_typeids = {0x0421, 0x0422, 0x0423, 0x0424};
|
||||||
summer_typeids = {0x02AF, 0x02B0, 0x02B1, 0x02B2, 0x02B3, 0x02B4, 0x02B5, 0x02B6};
|
summer_typeids = {0x02AF, 0x02B0, 0x02B1, 0x02B2, 0x02B3, 0x02B4, 0x02B5, 0x02B6};
|
||||||
curve_typeids = {0x029B, 0x029C, 0x029D, 0x029E, 0x029F, 0x02A0, 0x02A1, 0x02A2};
|
curve_typeids = {0x029B, 0x029C, 0x029D, 0x029E, 0x029F, 0x02A0, 0x02A1, 0x02A2};
|
||||||
summer2_typeids = {0x0470, 0x0471, 0x0472, 0x0473, 0x0474, 0x0475, 0x0476, 0x0477, 0x0478};
|
summer2_typeids = {0x0471, 0x0472, 0x0473, 0x0474, 0x0475, 0x0476, 0x0477, 0x0478};
|
||||||
hp_typeids = {0x0467, 0x0468, 0x0469, 0x046A};
|
hp_typeids = {0x0467, 0x0468, 0x0469, 0x046A};
|
||||||
hpmode_typeids = {0x0291, 0x0292, 0x0293, 0x0294};
|
hpmode_typeids = {0x0291, 0x0292, 0x0293, 0x0294};
|
||||||
const size_t monitor_size = monitor_typeids.size();
|
const size_t monitor_size = monitor_typeids.size();
|
||||||
for (uint8_t i = 0; i < monitor_size; i++) {
|
for (uint8_t i = 0; i < monitor_size; i++) {
|
||||||
register_telegram_type(monitor_typeids[i], "RC300Monitor", false, MAKE_PF_CB(process_RC300Monitor), 33);
|
register_telegram_type(monitor_typeids[i], "RC300Monitor", false, MAKE_PF_CB(process_RC300Monitor), 33);
|
||||||
register_telegram_type(set_typeids[i], "RC300Set", false, MAKE_PF_CB(process_RC300Set), 29);
|
register_telegram_type(set_typeids[i], "RC300Set", false, MAKE_PF_CB(process_RC300Set), 29);
|
||||||
register_telegram_type(summer_typeids[i], "RC300Summer", false, MAKE_PF_CB(process_RC300Summer), 13);
|
register_telegram_type(summer_typeids[i], "RC300Summer", false, MAKE_PF_CB(process_RC300Summer), 14);
|
||||||
register_telegram_type(curve_typeids[i], "RC300Curves", false, MAKE_PF_CB(process_RC300Curve), 9);
|
register_telegram_type(curve_typeids[i], "RC300Curves", false, MAKE_PF_CB(process_RC300Curve), 9);
|
||||||
register_telegram_type(summer2_typeids[i], "RC300Summer2", false, MAKE_PF_CB(process_RC300Summer2), 8);
|
register_telegram_type(summer2_typeids[i], "RC300Summer2", false, MAKE_PF_CB(process_RC300Summer2), 8);
|
||||||
}
|
}
|
||||||
@@ -207,6 +207,7 @@ Thermostat::Thermostat(uint8_t device_type, uint8_t device_id, uint8_t product_i
|
|||||||
register_telegram_type(0x16E, "Absent", true, MAKE_PF_CB(process_Absent), 1);
|
register_telegram_type(0x16E, "Absent", true, MAKE_PF_CB(process_Absent), 1);
|
||||||
register_telegram_type(0xBF, "ErrorMessage", false, MAKE_PF_CB(process_ErrorMessageBF));
|
register_telegram_type(0xBF, "ErrorMessage", false, MAKE_PF_CB(process_ErrorMessageBF));
|
||||||
register_telegram_type(0xC0, "RCErrorMessage", false, MAKE_PF_CB(process_RCErrorMessage2));
|
register_telegram_type(0xC0, "RCErrorMessage", false, MAKE_PF_CB(process_RCErrorMessage2));
|
||||||
|
register_telegram_type(0x470, "RC300Summer2", true, MAKE_PF_CB(process_RC300Summer2), 8);
|
||||||
EMSESP::send_read_request(0xC0, device_id, 0, 20); // read last errorcode on start (only published on errors)
|
EMSESP::send_read_request(0xC0, device_id, 0, 20); // read last errorcode on start (only published on errors)
|
||||||
|
|
||||||
// JUNKERS/HT3
|
// JUNKERS/HT3
|
||||||
@@ -1268,7 +1269,13 @@ void Thermostat::process_RC300Summer(std::shared_ptr<const Telegram> telegram) {
|
|||||||
void Thermostat::process_RC300Summer2(std::shared_ptr<const Telegram> telegram) {
|
void Thermostat::process_RC300Summer2(std::shared_ptr<const Telegram> telegram) {
|
||||||
auto hc = heating_circuit(telegram);
|
auto hc = heating_circuit(telegram);
|
||||||
if (hc == nullptr) {
|
if (hc == nullptr) {
|
||||||
return;
|
// telegram 0x470 see https://github.com/emsesp/EMS-ESP32/issues/2686
|
||||||
|
if (telegram->type_id == 0x470 && telegram->message_length > 2) {
|
||||||
|
hc = heating_circuit(1);
|
||||||
|
summer2_typeids[0] = 0x470;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (hc->statusbyte & 1) {
|
if (hc->statusbyte & 1) {
|
||||||
has_update(telegram, hc->summersetmode, 0);
|
has_update(telegram, hc->summersetmode, 0);
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
#define EMSESP_APP_VERSION "3.9.0-dev.0"
|
#define EMSESP_APP_VERSION "3.8.2-dev.22"
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ bool Test::test(const std::string & cmd, int8_t id1, int8_t id2) {
|
|||||||
uart_telegram({0x08, 0x98, 0x33, 0x00, 0x23, 0x24});
|
uart_telegram({0x08, 0x98, 0x33, 0x00, 0x23, 0x24});
|
||||||
|
|
||||||
// Boiler -> Me, UBAParameterWW(0x33), telegram: 08 0B 33 00 08 FF 34 FB 00 28 00 00 46 00 FF FF 00 (#data=13)
|
// Boiler -> Me, UBAParameterWW(0x33), telegram: 08 0B 33 00 08 FF 34 FB 00 28 00 00 46 00 FF FF 00 (#data=13)
|
||||||
uart_telegram({0x08, 0x0B, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00});
|
uart_telegram({0x08, 0x49, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00});
|
||||||
|
|
||||||
// Thermostat RCPLUSStatusMessage_HC1(0x01A5)
|
// Thermostat RCPLUSStatusMessage_HC1(0x01A5)
|
||||||
uart_telegram({0x98, 0x00, 0xFF, 0x00, 0x01, 0xA5, 0x00, 0xCF, 0x21, 0x2E, 0x00, 0x00, 0x2E, 0x24,
|
uart_telegram({0x98, 0x00, 0xFF, 0x00, 0x01, 0xA5, 0x00, 0xCF, 0x21, 0x2E, 0x00, 0x00, 0x2E, 0x24,
|
||||||
@@ -89,7 +89,7 @@ bool Test::test(const std::string & cmd, int8_t id1, int8_t id2) {
|
|||||||
|
|
||||||
add_device(0x08, 219); // Greenstar HIU/Logamax kompakt WS170
|
add_device(0x08, 219); // Greenstar HIU/Logamax kompakt WS170
|
||||||
|
|
||||||
// [emsesp] boiler(0x08) -W-> Me(0x0B), UBAMonitorFastPlus(0xE4), data: 00 01 35 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00 (offset 6)
|
// [emsesp] boiler(0x08) -W-> Me(0x49), UBAMonitorFastPlus(0xE4), data: 00 01 35 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 80 00 (offset 6)
|
||||||
uart_telegram({0x08, 0x00, 0xE4, 0x00, //
|
uart_telegram({0x08, 0x00, 0xE4, 0x00, //
|
||||||
00, 01, 0x35, 00, 00, 00, 00, 00, 00, 00, 00, 0x80, 00, 00, 00, 00, 00, 00, 00, 0x80, 00});
|
00, 01, 0x35, 00, 00, 00, 00, 00, 00, 00, 00, 0x80, 00, 00, 00, 00, 00, 00, 00, 0x80, 00});
|
||||||
|
|
||||||
@@ -112,7 +112,7 @@ bool Test::test(const std::string & cmd, int8_t id1, int8_t id2) {
|
|||||||
uart_telegram({0x08, 0x90, 0x33, 0x00, 0x23, 0x24});
|
uart_telegram({0x08, 0x90, 0x33, 0x00, 0x23, 0x24});
|
||||||
|
|
||||||
// Boiler -> Me, UBAParameterWW(0x33), telegram: 08 0B 33 00 08 FF 34 FB 00 28 00 00 46 00 FF FF 00 (#data=13)
|
// Boiler -> Me, UBAParameterWW(0x33), telegram: 08 0B 33 00 08 FF 34 FB 00 28 00 00 46 00 FF FF 00 (#data=13)
|
||||||
uart_telegram({0x08, 0x0B, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00});
|
uart_telegram({0x08, 0x49, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00});
|
||||||
|
|
||||||
// Thermostat 0x2A5 for HC1
|
// Thermostat 0x2A5 for HC1
|
||||||
uart_telegram({0x10, 00, 0xFF, 00, 01, 0xA5, 0x80, 00, 01, 0x30, 0x28, 00, 0x30, 0x28, 01, 0x54,
|
uart_telegram({0x10, 00, 0xFF, 00, 01, 0xA5, 0x80, 00, 01, 0x30, 0x28, 00, 0x30, 0x28, 01, 0x54,
|
||||||
@@ -144,7 +144,7 @@ bool Test::test(const std::string & cmd, int8_t id1, int8_t id2) {
|
|||||||
uart_telegram({0x08, 0x90, 0x33, 0x00, 0x23, 0x24});
|
uart_telegram({0x08, 0x90, 0x33, 0x00, 0x23, 0x24});
|
||||||
|
|
||||||
// Boiler -> Me, UBAParameterWW(0x33), telegram: 08 0B 33 00 08 FF 34 FB 00 28 00 00 46 00 FF FF 00 (#data=13)
|
// Boiler -> Me, UBAParameterWW(0x33), telegram: 08 0B 33 00 08 FF 34 FB 00 28 00 00 46 00 FF FF 00 (#data=13)
|
||||||
uart_telegram({0x08, 0x0B, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00});
|
uart_telegram({0x08, 0x49, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00});
|
||||||
|
|
||||||
// Thermostat 0x2A5 for HC1
|
// Thermostat 0x2A5 for HC1
|
||||||
uart_telegram({0x10, 00, 0xFF, 00, 01, 0xA5, 0x80, 00, 01, 0x30, 0x28, 00, 0x30, 0x28, 01, 0x54,
|
uart_telegram({0x10, 00, 0xFF, 00, 01, 0xA5, 0x80, 00, 01, 0x30, 0x28, 00, 0x30, 0x28, 01, 0x54,
|
||||||
@@ -160,7 +160,7 @@ bool Test::test(const std::string & cmd, int8_t id1, int8_t id2) {
|
|||||||
EMSESP::logger().notice("Adding a Gateway...");
|
EMSESP::logger().notice("Adding a Gateway...");
|
||||||
|
|
||||||
// add 0x48 KM200, via a version command
|
// add 0x48 KM200, via a version command
|
||||||
rx_telegram({0x48, 0x0B, 0x02, 0x00, 0xBD, 0x04, 0x06, 00, 00, 00, 00, 00, 00, 00});
|
rx_telegram({0x48, 0x49, 0x02, 0x00, 0xBD, 0x04, 0x06, 00, 00, 00, 00, 00, 00, 00});
|
||||||
|
|
||||||
// Boiler(0x08) -> All(0x00), UBADevices(0x07), data: 09 01 00 00 00 00 00 00 01 00 00 00 00
|
// Boiler(0x08) -> All(0x00), UBADevices(0x07), data: 09 01 00 00 00 00 00 00 01 00 00 00 00
|
||||||
// check: make sure 0x48 is not detected again !
|
// check: make sure 0x48 is not detected again !
|
||||||
@@ -203,14 +203,14 @@ bool Test::test(const std::string & cmd, int8_t id1, int8_t id2) {
|
|||||||
add_device(0x08, 123); // Nefit Trendline
|
add_device(0x08, 123); // Nefit Trendline
|
||||||
|
|
||||||
// UBAuptime
|
// UBAuptime
|
||||||
uart_telegram({0x08, 0x0B, 0x14, 00, 0x3C, 0x1F, 0xAC, 0x70});
|
uart_telegram({0x08, 0x49, 0x14, 00, 0x3C, 0x1F, 0xAC, 0x70});
|
||||||
|
|
||||||
// Boiler -> Me, UBAMonitorFast(0x18), telegram: 08 00 18 00 00 02 5A 73 3D 0A 10 65 40 02 1A 80 00 01 E1 01 76 0E 3D 48 00 C9 44 02 00 (#data=25)
|
// Boiler -> Me, UBAMonitorFast(0x18), telegram: 08 00 18 00 00 02 5A 73 3D 0A 10 65 40 02 1A 80 00 01 E1 01 76 0E 3D 48 00 C9 44 02 00 (#data=25)
|
||||||
uart_telegram({0x08, 0x00, 0x18, 0x00, 0x00, 0x02, 0x5A, 0x73, 0x3D, 0x0A, 0x10, 0x65, 0x40, 0x02, 0x1A,
|
uart_telegram({0x08, 0x00, 0x18, 0x00, 0x00, 0x02, 0x5A, 0x73, 0x3D, 0x0A, 0x10, 0x65, 0x40, 0x02, 0x1A,
|
||||||
0x80, 0x00, 0x01, 0xE1, 0x01, 0x76, 0x0E, 0x3D, 0x48, 0x00, 0xC9, 0x44, 0x02, 0x00});
|
0x80, 0x00, 0x01, 0xE1, 0x01, 0x76, 0x0E, 0x3D, 0x48, 0x00, 0xC9, 0x44, 0x02, 0x00});
|
||||||
|
|
||||||
// Boiler -> Me, UBAParameterWW(0x33), telegram: 08 0B 33 00 08 FF 34 FB 00 28 00 00 46 00 FF FF 00 (#data=13)
|
// Boiler -> Me, UBAParameterWW(0x33), telegram: 08 0B 33 00 08 FF 34 FB 00 28 00 00 46 00 FF FF 00 (#data=13)
|
||||||
uart_telegram({0x08, 0x0B, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00});
|
uart_telegram({0x08, 0x49, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -234,10 +234,10 @@ bool Test::test(const std::string & cmd, int8_t id1, int8_t id2) {
|
|||||||
add_device(0x30, 163); // SM100
|
add_device(0x30, 163); // SM100
|
||||||
|
|
||||||
// SM100Monitor - type 0x0362 EMS+ - for SM100 and SM200
|
// SM100Monitor - type 0x0362 EMS+ - for SM100 and SM200
|
||||||
uart_telegram({0xB0, 0x0B, 0xFF, 00, 0x02, 0x62, 00, 0x44, 0x02, 0x7A, 0x80, 00, 0x80, 0x00, 0x80, 00,
|
uart_telegram({0xB0, 0x49, 0xFF, 00, 0x02, 0x62, 00, 0x44, 0x02, 0x7A, 0x80, 00, 0x80, 0x00, 0x80, 00,
|
||||||
0x80, 00, 0x80, 00, 0x80, 00, 00, 0x7C, 0x80, 00, 0x80, 00, 0x80, 00, 0x80});
|
0x80, 00, 0x80, 00, 0x80, 00, 00, 0x7C, 0x80, 00, 0x80, 00, 0x80, 00, 0x80});
|
||||||
|
|
||||||
uart_telegram({0xB0, 0x0B, 0xFF, 0x00, 0x02, 0x62, 0x01, 0x44, 0x03, 0x30, 0x80, 00, 0x80, 00, 0x80, 00,
|
uart_telegram({0xB0, 0x49, 0xFF, 0x00, 0x02, 0x62, 0x01, 0x44, 0x03, 0x30, 0x80, 00, 0x80, 00, 0x80, 00,
|
||||||
0x80, 00, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 0x33});
|
0x80, 00, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 0x33});
|
||||||
|
|
||||||
uart_telegram({0xB0, 00, 0xFF, 0x18, 02, 0x62, 0x80, 00, 0xB8});
|
uart_telegram({0xB0, 00, 0xFF, 0x18, 02, 0x62, 0x80, 00, 0xB8});
|
||||||
@@ -580,7 +580,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
|||||||
add_device(0x09, 206); // Nefit Excellent HR30 Controller
|
add_device(0x09, 206); // Nefit Excellent HR30 Controller
|
||||||
|
|
||||||
// UBAuptime
|
// UBAuptime
|
||||||
uart_telegram({0x08, 0x0B, 0x14, 00, 0x3C, 0x1F, 0xAC, 0x70});
|
uart_telegram({0x08, 0x49, 0x14, 00, 0x3C, 0x1F, 0xAC, 0x70});
|
||||||
ok = true;
|
ok = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -588,10 +588,10 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
|||||||
EMSESP::logger().notice("Testing 620...");
|
EMSESP::logger().notice("Testing 620...");
|
||||||
|
|
||||||
// Version Controller
|
// Version Controller
|
||||||
uart_telegram({0x09, 0x0B, 0x02, 0x00, 0x5F, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00});
|
uart_telegram({0x09, 0x49, 0x02, 0x00, 0x5F, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00});
|
||||||
|
|
||||||
// Version Boiler
|
// Version Boiler
|
||||||
uart_telegram({0x08, 0x0B, 0x02, 0x00, 0x5F, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00});
|
uart_telegram({0x08, 0x49, 0x02, 0x00, 0x5F, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00});
|
||||||
ok = true;
|
ok = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -607,7 +607,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
|||||||
|
|
||||||
// simulate getting version information back from an unknown device
|
// simulate getting version information back from an unknown device
|
||||||
// note there is no brand (byte 9)
|
// note there is no brand (byte 9)
|
||||||
rx_telegram({0x09, 0x0B, 0x02, 0x00, 0x59, 0x09, 0x0a});
|
rx_telegram({0x09, 0x49, 0x02, 0x00, 0x59, 0x09, 0x0a});
|
||||||
|
|
||||||
shell.invoke_command("show devices");
|
shell.invoke_command("show devices");
|
||||||
shell.invoke_command("call system report");
|
shell.invoke_command("call system report");
|
||||||
@@ -618,7 +618,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
|||||||
shell.printfln("Testing unknown2...");
|
shell.printfln("Testing unknown2...");
|
||||||
|
|
||||||
// simulate getting version information back from an unknown device
|
// simulate getting version information back from an unknown device
|
||||||
rx_telegram({0x09, 0x0B, 0x02, 0x00, 0x5A, 0x01, 0x02}); // productID is 90 which doesn't exist
|
rx_telegram({0x09, 0x49, 0x02, 0x00, 0x5A, 0x01, 0x02}); // productID is 90 which doesn't exist
|
||||||
ok = true;
|
ok = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -815,9 +815,9 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
|||||||
// test("thermostat");
|
// test("thermostat");
|
||||||
|
|
||||||
// 0xC2
|
// 0xC2
|
||||||
// [emsesp] Boiler(0x08) -> Me(0x0B), UBAErrorMessage3(0xC2), data: 08 AC 00 10 31 48 30 31 15 80 95 0B 0E 10 38 00 7F FF FF FF 08 AC 00 10 09 41 30
|
// [emsesp] Boiler(0x08) -> Me(0x49), UBAErrorMessage3(0xC2), data: 08 AC 00 10 31 48 30 31 15 80 95 0B 0E 10 38 00 7F FF FF FF 08 AC 00 10 09 41 30
|
||||||
uart_telegram(
|
uart_telegram(
|
||||||
{0x08, 0x0B, 0xC2, 0, 0x08, 0xAC, 00, 0x10, 0x31, 0x48, 0x30, 0x31, 0x15, 0x80, 0x95, 0x0B, 0x0E, 0x10, 0x38, 00, 0x7F, 0xFF, 0xFF, 0xFF});
|
{0x08, 0x49, 0xC2, 0, 0x08, 0xAC, 00, 0x10, 0x31, 0x48, 0x30, 0x31, 0x15, 0x80, 0x95, 0x0B, 0x0E, 0x10, 0x38, 00, 0x7F, 0xFF, 0xFF, 0xFF});
|
||||||
|
|
||||||
// shell.invoke_command("show values");
|
// shell.invoke_command("show values");
|
||||||
|
|
||||||
@@ -1042,7 +1042,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
|||||||
// Boiler -> Me, UBAParameterWW(0x33)
|
// Boiler -> Me, UBAParameterWW(0x33)
|
||||||
// wwseltemp = goes from 52 degrees (0x34) to void (0xFF)
|
// wwseltemp = goes from 52 degrees (0x34) to void (0xFF)
|
||||||
// it should delete the HA config topic homeassistant/sensor/ems-esp/boiler_wwseltemp/config
|
// it should delete the HA config topic homeassistant/sensor/ems-esp/boiler_wwseltemp/config
|
||||||
uart_telegram({0x08, 0x0B, 0x33, 0x00, 0x08, 0xFF, 0xFF, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00});
|
uart_telegram({0x08, 0x49, 0x33, 0x00, 0x08, 0xFF, 0xFF, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00});
|
||||||
|
|
||||||
shell.invoke_command("call boiler wwseltemp");
|
shell.invoke_command("call boiler wwseltemp");
|
||||||
shell.invoke_command("call system publish");
|
shell.invoke_command("call system publish");
|
||||||
@@ -1795,7 +1795,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
|||||||
add_device(0x18, 202); // Bosch TC100 - https://github.com/emsesp/EMS-ESP/issues/474
|
add_device(0x18, 202); // Bosch TC100 - https://github.com/emsesp/EMS-ESP/issues/474
|
||||||
|
|
||||||
// 0x0A
|
// 0x0A
|
||||||
uart_telegram({0x98, 0x0B, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
uart_telegram({0x98, 0x49, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00});
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00});
|
||||||
ok = true;
|
ok = true;
|
||||||
}
|
}
|
||||||
@@ -1829,10 +1829,10 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
|||||||
|
|
||||||
// SM100Monitor - type 0x0362 EMS+ - for SM100 and SM200
|
// SM100Monitor - type 0x0362 EMS+ - for SM100 and SM200
|
||||||
// B0 0B FF 00 02 62 00 44 02 7A 80 00 80 00 80 00 80 00 80 00 80 00 00 7C 80 00 80 00 80 00 80
|
// B0 0B FF 00 02 62 00 44 02 7A 80 00 80 00 80 00 80 00 80 00 80 00 00 7C 80 00 80 00 80 00 80
|
||||||
rx_telegram({0xB0, 0x0B, 0xFF, 00, 0x02, 0x62, 00, 0x44, 0x02, 0x7A, 0x80, 00, 0x80, 0x00, 0x80, 00,
|
rx_telegram({0xB0, 0x49, 0xFF, 00, 0x02, 0x62, 00, 0x44, 0x02, 0x7A, 0x80, 00, 0x80, 0x00, 0x80, 00,
|
||||||
0x80, 00, 0x80, 00, 0x80, 00, 00, 0x7C, 0x80, 00, 0x80, 00, 0x80, 00, 0x80});
|
0x80, 00, 0x80, 00, 0x80, 00, 00, 0x7C, 0x80, 00, 0x80, 00, 0x80, 00, 0x80});
|
||||||
|
|
||||||
rx_telegram({0xB0, 0x0B, 0xFF, 0x00, 0x02, 0x62, 0x01, 0x44, 0x03, 0x30, 0x80, 00, 0x80, 00, 0x80, 00,
|
rx_telegram({0xB0, 0x49, 0xFF, 0x00, 0x02, 0x62, 0x01, 0x44, 0x03, 0x30, 0x80, 00, 0x80, 00, 0x80, 00,
|
||||||
0x80, 00, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 0x33});
|
0x80, 00, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 00, 0x80, 0x33});
|
||||||
|
|
||||||
rx_telegram({0xB0, 00, 0xFF, 0x18, 02, 0x62, 0x80, 00, 0xB8});
|
rx_telegram({0xB0, 00, 0xFF, 0x18, 02, 0x62, 0x80, 00, 0xB8});
|
||||||
@@ -1936,7 +1936,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
|||||||
if (command == "rx2") {
|
if (command == "rx2") {
|
||||||
shell.printfln("Testing Rx2...");
|
shell.printfln("Testing Rx2...");
|
||||||
for (uint8_t i = 0; i < 30; i++) {
|
for (uint8_t i = 0; i < 30; i++) {
|
||||||
uart_telegram({0x08, 0x0B, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00});
|
uart_telegram({0x08, 0x49, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00});
|
||||||
ok = true;
|
ok = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1953,23 +1953,23 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
|||||||
uart_telegram({0x08, 0x97, 0x33, 0x00, 0x23, 0x24});
|
uart_telegram({0x08, 0x97, 0x33, 0x00, 0x23, 0x24});
|
||||||
|
|
||||||
// Boiler -> Me, UBAParameterWW(0x33), telegram: 08 0B 33 00 08 FF 34 FB 00 28 00 00 46 00 FF FF 00 (#data=13)
|
// Boiler -> Me, UBAParameterWW(0x33), telegram: 08 0B 33 00 08 FF 34 FB 00 28 00 00 46 00 FF FF 00 (#data=13)
|
||||||
uart_telegram({0x08, 0x0B, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00});
|
uart_telegram({0x08, 0x49, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00});
|
||||||
|
|
||||||
// Thermostat -> Me, RC20StatusMessage(0x91), telegram: 17 0B 91 05 44 45 46 47 (#data=4)
|
// Thermostat -> Me, RC20StatusMessage(0x91), telegram: 17 0B 91 05 44 45 46 47 (#data=4)
|
||||||
uart_telegram({0x17, 0x0B, 0x91, 0x05, 0x44, 0x45, 0x46, 0x47});
|
uart_telegram({0x17, 0x49, 0x91, 0x05, 0x44, 0x45, 0x46, 0x47});
|
||||||
|
|
||||||
// bad CRC - corrupt telegram - CRC should be 0x8E
|
// bad CRC - corrupt telegram - CRC should be 0x8E
|
||||||
uint8_t t5[] = {0x17, 0x0B, 0x91, 0x05, 0x44, 0x45, 0x46, 0x47, 0x99};
|
uint8_t t5[] = {0x17, 0x49, 0x91, 0x05, 0x44, 0x45, 0x46, 0x47, 0x99};
|
||||||
EMSESP::rxservice_.add(t5, sizeof(t5));
|
EMSESP::rxservice_.add(t5, sizeof(t5));
|
||||||
|
|
||||||
// simulating a Tx record
|
// simulating a Tx record
|
||||||
uart_telegram({0x0B, 0x88, 0x07, 0x00, 0x20});
|
uart_telegram({0x49, 0x88, 0x07, 0x00, 0x20});
|
||||||
|
|
||||||
// Version Boiler
|
// Version Boiler
|
||||||
uart_telegram({0x08, 0x0B, 0x02, 0x00, 0x7B, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04});
|
uart_telegram({0x08, 0x49, 0x02, 0x00, 0x7B, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04});
|
||||||
|
|
||||||
// Version Thermostat, device_id 0x11
|
// Version Thermostat, device_id 0x11
|
||||||
uart_telegram({0x11, 0x0B, 0x02, 0x00, 0x4D, 0x03, 0x03});
|
uart_telegram({0x11, 0x49, 0x02, 0x00, 0x4D, 0x03, 0x03});
|
||||||
|
|
||||||
// Thermostat -> all, telegram: 10 00 FF 00 01 A5 00 D7 21 00 00 00 00 30 01 84 01 01 03 01 84 01 F1 00 00 11 01 00 08 63 00
|
// Thermostat -> all, telegram: 10 00 FF 00 01 A5 00 D7 21 00 00 00 00 30 01 84 01 01 03 01 84 01 F1 00 00 11 01 00 08 63 00
|
||||||
// 0x1A5 test ems+
|
// 0x1A5 test ems+
|
||||||
@@ -1987,7 +1987,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
|||||||
uart_telegram({0x17, 0x08, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00});
|
uart_telegram({0x17, 0x08, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00});
|
||||||
|
|
||||||
// Thermostat -> Me, RC20Set(0xA8), telegram: 17 0B A8 00 01 00 FF F6 01 06 00 01 0D 01 00 FF FF 01 02 02 02 00 00 05 1F 05 1F 02 0E 00 FF (#data=27)
|
// Thermostat -> Me, RC20Set(0xA8), telegram: 17 0B A8 00 01 00 FF F6 01 06 00 01 0D 01 00 FF FF 01 02 02 02 00 00 05 1F 05 1F 02 0E 00 FF (#data=27)
|
||||||
uart_telegram({0x17, 0x0B, 0xA8, 0x00, 0x01, 0x00, 0xFF, 0xF6, 0x01, 0x06, 0x00, 0x01, 0x0D, 0x01, 0x00, 0xFF,
|
uart_telegram({0x17, 0x49, 0xA8, 0x00, 0x01, 0x00, 0xFF, 0xF6, 0x01, 0x06, 0x00, 0x01, 0x0D, 0x01, 0x00, 0xFF,
|
||||||
0xFF, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x05, 0x1F, 0x05, 0x1F, 0x02, 0x0E, 0x00, 0xFF});
|
0xFF, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x05, 0x1F, 0x05, 0x1F, 0x02, 0x0E, 0x00, 0xFF});
|
||||||
|
|
||||||
// Boiler(0x08) -> All(0x00), UBAMonitorWW(0x34), data: 36 01 A5 80 00 21 00 00 01 00 01 3E 8D 03 77 91 00 80 00
|
// Boiler(0x08) -> All(0x00), UBAMonitorWW(0x34), data: 36 01 A5 80 00 21 00 00 01 00 01 3E 8D 03 77 91 00 80 00
|
||||||
@@ -2021,7 +2021,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
|||||||
EMSESP::send_write_request(0x91, 0x17, 0x00, t18, sizeof(t18), 0x00);
|
EMSESP::send_write_request(0x91, 0x17, 0x00, t18, sizeof(t18), 0x00);
|
||||||
|
|
||||||
// TX - send EMS+
|
// TX - send EMS+
|
||||||
const uint8_t t13[] = {0x90, 0x0B, 0xFF, 00, 01, 0xBA, 00, 0x2E, 0x2A, 0x26, 0x1E, 0x03,
|
const uint8_t t13[] = {0x90, 0x49, 0xFF, 00, 01, 0xBA, 00, 0x2E, 0x2A, 0x26, 0x1E, 0x03,
|
||||||
00, 0xFF, 0xFF, 05, 0x2A, 01, 0xE1, 0x20, 0x01, 0x0F, 05, 0x2A};
|
00, 0xFF, 0xFF, 05, 0x2A, 01, 0xE1, 0x20, 0x01, 0x0F, 05, 0x2A};
|
||||||
EMSESP::txservice_.add(Telegram::Operation::TX_RAW, t13, sizeof(t13), 0);
|
EMSESP::txservice_.add(Telegram::Operation::TX_RAW, t13, sizeof(t13), 0);
|
||||||
|
|
||||||
@@ -2145,7 +2145,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
|||||||
uart_telegram({0x08, 0x98, 0x33, 0x00, 0x23, 0x24});
|
uart_telegram({0x08, 0x98, 0x33, 0x00, 0x23, 0x24});
|
||||||
|
|
||||||
// Boiler -> Me, UBAParameterWW(0x33), telegram: 08 0B 33 00 08 FF 34 FB 00 28 00 00 46 00 FF FF 00 (#data=13)
|
// Boiler -> Me, UBAParameterWW(0x33), telegram: 08 0B 33 00 08 FF 34 FB 00 28 00 00 46 00 FF FF 00 (#data=13)
|
||||||
uart_telegram({0x08, 0x0B, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00});
|
uart_telegram({0x08, 0x49, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00});
|
||||||
|
|
||||||
// add a thermostat
|
// add a thermostat
|
||||||
add_device(0x18, 157); // Bosch CR100
|
add_device(0x18, 157); // Bosch CR100
|
||||||
@@ -2487,7 +2487,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
|||||||
if (command == "rx3") {
|
if (command == "rx3") {
|
||||||
shell.printfln("Testing rx3...");
|
shell.printfln("Testing rx3...");
|
||||||
|
|
||||||
uart_telegram({0x21, 0x0B, 0xFF, 0x00});
|
uart_telegram({0x21, 0x49, 0xFF, 0x00});
|
||||||
ok = true;
|
ok = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2495,7 +2495,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
|
|||||||
if (command == "tx2") {
|
if (command == "tx2") {
|
||||||
shell.printfln("Testing tx2...");
|
shell.printfln("Testing tx2...");
|
||||||
|
|
||||||
uint8_t t[] = {0x0B, 0x88, 0x18, 0x00, 0x20, 0xD4}; // including CRC
|
uint8_t t[] = {0x49, 0x88, 0x18, 0x00, 0x20, 0xD4}; // including CRC
|
||||||
EMSuart::transmit(t, sizeof(t));
|
EMSuart::transmit(t, sizeof(t));
|
||||||
ok = true;
|
ok = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ uint32_t inverse_mask = 0;
|
|||||||
// receive task, wait for break and call incoming_telegram
|
// receive task, wait for break and call incoming_telegram
|
||||||
void EMSuart::uart_event_task(void * pvParameters) {
|
void EMSuart::uart_event_task(void * pvParameters) {
|
||||||
uart_event_t event;
|
uart_event_t event;
|
||||||
uint8_t telegram[UART_HW_FIFO_LEN(EMSUART_NUM) + 1]; // same size as in driver_install
|
uint8_t telegram[UART_FIFO_LEN + 1]; // same size as in driver_install
|
||||||
uint8_t length = 0;
|
uint8_t length = 0;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
@@ -66,23 +66,18 @@ void EMSuart::uart_event_task(void * pvParameters) {
|
|||||||
// initialize UART driver
|
// initialize UART driver
|
||||||
void EMSuart::start(const uint8_t tx_mode, const uint8_t rx_gpio, const uint8_t tx_gpio) {
|
void EMSuart::start(const uint8_t tx_mode, const uint8_t rx_gpio, const uint8_t tx_gpio) {
|
||||||
if (tx_mode_ == EMS_TXMODE_INIT) {
|
if (tx_mode_ == EMS_TXMODE_INIT) {
|
||||||
#if CONFIG_IDF_TARGET_ESP32C6
|
|
||||||
uart_config_t uart_config = {.baud_rate = EMSUART_BAUD,
|
|
||||||
.data_bits = UART_DATA_8_BITS,
|
|
||||||
.parity = UART_PARITY_DISABLE,
|
|
||||||
.stop_bits = UART_STOP_BITS_1,
|
|
||||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
|
||||||
.rx_flow_ctrl_thresh = 0};
|
|
||||||
#else
|
|
||||||
uart_config_t uart_config = {.baud_rate = EMSUART_BAUD,
|
uart_config_t uart_config = {.baud_rate = EMSUART_BAUD,
|
||||||
.data_bits = UART_DATA_8_BITS,
|
.data_bits = UART_DATA_8_BITS,
|
||||||
.parity = UART_PARITY_DISABLE,
|
.parity = UART_PARITY_DISABLE,
|
||||||
.stop_bits = UART_STOP_BITS_1,
|
.stop_bits = UART_STOP_BITS_1,
|
||||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||||
.rx_flow_ctrl_thresh = 0,
|
.rx_flow_ctrl_thresh = 0,
|
||||||
.source_clk = UART_SCLK_APB,
|
.source_clk = UART_SCLK_APB
|
||||||
.flags = {0}};
|
#if ESP_ARDUINO_VERSION_MAJOR >= 3
|
||||||
|
,
|
||||||
|
.flags = {0}
|
||||||
#endif
|
#endif
|
||||||
|
};
|
||||||
#if defined(EMSUART_RX_INVERT)
|
#if defined(EMSUART_RX_INVERT)
|
||||||
inverse_mask |= UART_SIGNAL_RXD_INV;
|
inverse_mask |= UART_SIGNAL_RXD_INV;
|
||||||
#endif
|
#endif
|
||||||
@@ -92,12 +87,7 @@ void EMSuart::start(const uint8_t tx_mode, const uint8_t rx_gpio, const uint8_t
|
|||||||
uart_param_config(EMSUART_NUM, &uart_config);
|
uart_param_config(EMSUART_NUM, &uart_config);
|
||||||
uart_set_pin(EMSUART_NUM, tx_gpio, rx_gpio, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
|
uart_set_pin(EMSUART_NUM, tx_gpio, rx_gpio, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
|
||||||
uart_set_line_inverse(EMSUART_NUM, inverse_mask);
|
uart_set_line_inverse(EMSUART_NUM, inverse_mask);
|
||||||
uart_driver_install(EMSUART_NUM,
|
uart_driver_install(EMSUART_NUM, UART_FIFO_LEN + 1, 0, UART_FIFO_LEN + 3, &uart_queue, 0); // buffer must be > fifo, queue can hold data+break+overflow message
|
||||||
UART_HW_FIFO_LEN(EMSUART_NUM) + 1,
|
|
||||||
0,
|
|
||||||
UART_HW_FIFO_LEN(EMSUART_NUM) + 3,
|
|
||||||
&uart_queue,
|
|
||||||
0); // buffer must be > fifo, queue can hold data+break+overflow message
|
|
||||||
uart_set_rx_full_threshold(EMSUART_NUM, 1);
|
uart_set_rx_full_threshold(EMSUART_NUM, 1);
|
||||||
uart_set_rx_timeout(EMSUART_NUM, 0); // disable
|
uart_set_rx_timeout(EMSUART_NUM, 0); // disable
|
||||||
|
|
||||||
@@ -159,8 +149,10 @@ uint8_t EMSuart::transmit(const uint8_t * buf, const uint8_t len) {
|
|||||||
return EMS_TX_STATUS_OK;
|
return EMS_TX_STATUS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto tx_mode = tx_mode_ != EMS_TXMODE_AUTO ? tx_mode_ : EMSbus::is_ht3() ? EMS_TXMODE_HT3 : EMSbus::is_ems2() ? EMS_TXMODE_EMSPLUS : EMS_TXMODE_EMS;
|
||||||
|
|
||||||
// TXMODE is EMS+ with long delay
|
// TXMODE is EMS+ with long delay
|
||||||
if (tx_mode_ == EMS_TXMODE_EMSPLUS) {
|
if (tx_mode == EMS_TXMODE_EMSPLUS) {
|
||||||
for (uint8_t i = 0; i < len; i++) {
|
for (uint8_t i = 0; i < len; i++) {
|
||||||
uart_write_bytes(EMSUART_NUM, &buf[i], 1);
|
uart_write_bytes(EMSUART_NUM, &buf[i], 1);
|
||||||
delayMicroseconds(EMSUART_TX_WAIT_PLUS);
|
delayMicroseconds(EMSUART_TX_WAIT_PLUS);
|
||||||
@@ -170,7 +162,7 @@ uint8_t EMSuart::transmit(const uint8_t * buf, const uint8_t len) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TXMODE is HT3 with 7 bittimes delay
|
// TXMODE is HT3 with 7 bittimes delay
|
||||||
if (tx_mode_ == EMS_TXMODE_HT3) {
|
if (tx_mode == EMS_TXMODE_HT3) {
|
||||||
for (uint8_t i = 0; i < len; i++) {
|
for (uint8_t i = 0; i < len; i++) {
|
||||||
uart_write_bytes(EMSUART_NUM, &buf[i], 1);
|
uart_write_bytes(EMSUART_NUM, &buf[i], 1);
|
||||||
delayMicroseconds(EMSUART_TX_WAIT_HT3);
|
delayMicroseconds(EMSUART_TX_WAIT_HT3);
|
||||||
|
|||||||
@@ -42,10 +42,11 @@
|
|||||||
|
|
||||||
#define EMS_TXMODE_INIT 0xFF
|
#define EMS_TXMODE_INIT 0xFF
|
||||||
#define EMS_TXMODE_OFF 0
|
#define EMS_TXMODE_OFF 0
|
||||||
#define EMS_TXMODE_DEFAULT 1
|
#define EMS_TXMODE_EMS 1
|
||||||
#define EMS_TXMODE_EMSPLUS 2
|
#define EMS_TXMODE_EMSPLUS 2
|
||||||
#define EMS_TXMODE_HT3 3
|
#define EMS_TXMODE_HT3 3
|
||||||
#define EMS_TXMODE_HW 4
|
#define EMS_TXMODE_HW 4
|
||||||
|
#define EMS_TXMODE_AUTO 5
|
||||||
|
|
||||||
// LEGACY
|
// LEGACY
|
||||||
#define EMSUART_TX_BIT_TIME 104 // bit time @9600 baud
|
#define EMSUART_TX_BIT_TIME 104 // bit time @9600 baud
|
||||||
|
|||||||
@@ -166,7 +166,9 @@ StateUpdateResult WebCustomEntity::update(JsonObject root, WebCustomEntity & web
|
|||||||
bool WebCustomEntityService::command_setvalue(const char * value, const int8_t id, const char * name) {
|
bool WebCustomEntityService::command_setvalue(const char * value, const int8_t id, const char * name) {
|
||||||
// don't write if there is no value, to prevent setting an empty value by mistake when parsing attributes
|
// don't write if there is no value, to prevent setting an empty value by mistake when parsing attributes
|
||||||
if (!strlen(value)) {
|
if (!strlen(value)) {
|
||||||
|
#if defined(EMSESP_DEBUG)
|
||||||
EMSESP::logger().debug("can't set empty value!");
|
EMSESP::logger().debug("can't set empty value!");
|
||||||
|
#endif
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -54,10 +54,10 @@ void WebCustomization::read(WebCustomization & customizations, JsonObject root)
|
|||||||
JsonArray sensorsJson = root["ts"].to<JsonArray>();
|
JsonArray sensorsJson = root["ts"].to<JsonArray>();
|
||||||
for (const SensorCustomization & sensor : customizations.sensorCustomizations) {
|
for (const SensorCustomization & sensor : customizations.sensorCustomizations) {
|
||||||
JsonObject sensorJson = sensorsJson.add<JsonObject>();
|
JsonObject sensorJson = sensorsJson.add<JsonObject>();
|
||||||
sensorJson["id"] = (const char *)sensor.id; // ID of dallas temperature sensor chip
|
sensorJson["id"] = (const char *)sensor.id; // ID of chip
|
||||||
sensorJson["name"] = (const char *)sensor.name; // n
|
sensorJson["name"] = (const char *)sensor.name; // n
|
||||||
sensorJson["offset"] = sensor.offset; // o
|
sensorJson["offset"] = sensor.offset; // o
|
||||||
sensorJson["is_system"] = sensor.is_system; // s for gateway_temperature
|
sensorJson["is_system"] = sensor.is_system; // s for core_voltage, supply_voltage
|
||||||
}
|
}
|
||||||
|
|
||||||
// Analog Sensor customization
|
// Analog Sensor customization
|
||||||
|
|||||||
@@ -352,6 +352,7 @@ bool WebSchedulerService::command(const char * name, const std::string & command
|
|||||||
// parse json
|
// parse json
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
if (deserializeJson(doc, cmd) == DeserializationError::Ok) {
|
if (deserializeJson(doc, cmd) == DeserializationError::Ok) {
|
||||||
|
HTTPClient * http = new HTTPClient;
|
||||||
std::string url = doc["url"] | "";
|
std::string url = doc["url"] | "";
|
||||||
// for a GET with parameters replace commands with values
|
// for a GET with parameters replace commands with values
|
||||||
// don't search the complete url, it may contain a devicename in path
|
// don't search the complete url, it may contain a devicename in path
|
||||||
@@ -362,139 +363,40 @@ bool WebSchedulerService::command(const char * name, const std::string & command
|
|||||||
commands(s, false);
|
commands(s, false);
|
||||||
url.replace(q + 1, l, s);
|
url.replace(q + 1, l, s);
|
||||||
}
|
}
|
||||||
std::string value = doc["value"] | data; // extract value if its in the command, or take the data
|
if (http->begin(url.c_str())) {
|
||||||
std::string method = doc["method"] | "GET"; // default GET
|
// add any given headers
|
||||||
commands(value, false);
|
for (JsonPair p : doc["header"].as<JsonObject>()) {
|
||||||
if (value.length()) {
|
http->addHeader(p.key().c_str(), p.value().as<String>().c_str());
|
||||||
method = "POST";
|
|
||||||
}
|
|
||||||
std::string result;
|
|
||||||
int httpResult = 0;
|
|
||||||
#ifndef NO_TLS_SUPPORT
|
|
||||||
if (Helpers::toLower(url.c_str()).starts_with("https://")) {
|
|
||||||
WiFiClient * basic_client = new WiFiClient;
|
|
||||||
ESP_SSLClient * ssl_client = new ESP_SSLClient;
|
|
||||||
ssl_client->setInsecure(); // with root CA we should set here: ssl_client->setCACert(rootCACert);
|
|
||||||
ssl_client->setBufferSizes(1024, 1024);
|
|
||||||
ssl_client->setSessionTimeout(120); // Set the timeout in seconds (>=120 seconds)
|
|
||||||
url.replace(0, 8, "");
|
|
||||||
std::string host = url;
|
|
||||||
auto index = url.find_first_of('/');
|
|
||||||
if (index != std::string::npos) {
|
|
||||||
host = url.substr(0, index);
|
|
||||||
url.replace(0, index, "");
|
|
||||||
}
|
}
|
||||||
// EMSESP::logger().debug("Host: %s, URL: %s", host.c_str(), url.c_str());
|
std::string value = doc["value"] | data.c_str(); // extract value if its in the command, or take the data
|
||||||
ssl_client->setClient(basic_client);
|
std::string method = doc["method"] | "GET"; // default GET
|
||||||
if (ssl_client->connect(host.c_str(), 443)) {
|
|
||||||
if (value.length() || Helpers::toLower(method) == "post") {
|
commands(value, false);
|
||||||
// EMSESP::logger().debug("POST %s HTTP/1.1", url.c_str());
|
// if there is data, force a POST
|
||||||
ssl_client->print("POST ");
|
int httpResult = 0;
|
||||||
ssl_client->print(url.c_str());
|
if (value.length() || method == "post") { // we have all lowercase
|
||||||
ssl_client->println(" HTTP/1.1");
|
if (value.find_first_of('{') != std::string::npos) {
|
||||||
ssl_client->print("Host: ");
|
http->addHeader(asyncsrv::T_Content_Type, asyncsrv::T_application_json, false); // auto-set to JSON
|
||||||
ssl_client->println(host.c_str());
|
|
||||||
bool content_set = false;
|
|
||||||
for (JsonPair p : doc["header"].as<JsonObject>()) {
|
|
||||||
content_set |= (emsesp::Helpers::toLower(p.key().c_str()) == "content-type");
|
|
||||||
ssl_client->print(p.key().c_str());
|
|
||||||
ssl_client->print(": ");
|
|
||||||
ssl_client->println(p.value().as<std::string>().c_str());
|
|
||||||
}
|
|
||||||
if (!content_set) {
|
|
||||||
ssl_client->print("Content-Type: ");
|
|
||||||
if (value.starts_with('{')) {
|
|
||||||
ssl_client->println(asyncsrv::T_application_json);
|
|
||||||
} else {
|
|
||||||
ssl_client->println(asyncsrv::T_text_plain);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ssl_client->print("Content-Length: ");
|
|
||||||
ssl_client->println(value.length());
|
|
||||||
ssl_client->println("Connection: close");
|
|
||||||
ssl_client->print("\r\n");
|
|
||||||
ssl_client->print(value.c_str());
|
|
||||||
} else {
|
|
||||||
// EMSESP::logger().debug("GET %s HTTP/1.1", url.c_str());
|
|
||||||
ssl_client->print("GET ");
|
|
||||||
ssl_client->print(url.c_str());
|
|
||||||
ssl_client->println(" HTTP/1.1");
|
|
||||||
ssl_client->print("Host: ");
|
|
||||||
ssl_client->println(host.c_str());
|
|
||||||
for (JsonPair p : doc["header"].as<JsonObject>()) {
|
|
||||||
ssl_client->print(p.key().c_str());
|
|
||||||
ssl_client->print(": ");
|
|
||||||
ssl_client->println(p.value().as<std::string>().c_str());
|
|
||||||
}
|
|
||||||
ssl_client->println("Connection: close");
|
|
||||||
}
|
|
||||||
auto ms = millis();
|
|
||||||
while (ssl_client->connected() && !ssl_client->available() && millis() - ms < 3000) {
|
|
||||||
delay(0);
|
|
||||||
}
|
|
||||||
while (ssl_client->available()) {
|
|
||||||
result += (char)ssl_client->read();
|
|
||||||
}
|
|
||||||
ssl_client->stop();
|
|
||||||
// EMSESP::logger().debug("HTTPS response: %s", result.c_str());
|
|
||||||
index = result.find_first_of(' ');
|
|
||||||
if (index != std::string::npos) {
|
|
||||||
httpResult = stoi(result.substr(index + 1, 3));
|
|
||||||
// EMSESP::logger().debug("HTTPS code: %i", httpResult);
|
|
||||||
}
|
|
||||||
index = result.find("\r\n\r\n");
|
|
||||||
if (index != std::string::npos) {
|
|
||||||
result.replace(0, index + 4, "");
|
|
||||||
// EMSESP::logger().debug("HTTPS response: %s", result.c_str());
|
|
||||||
}
|
}
|
||||||
|
httpResult = http->POST(value.c_str());
|
||||||
} else {
|
} else {
|
||||||
EMSESP::logger().warning("HTTPS connection failed");
|
httpResult = http->GET(); // normal GET
|
||||||
}
|
|
||||||
delete ssl_client;
|
|
||||||
delete basic_client;
|
|
||||||
// check HTTP return code
|
|
||||||
if (httpResult != 200) {
|
|
||||||
EMSESP::logger().warning("Schedule '%s': URL command failed with http code %d", name, httpResult);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
if (Helpers::toLower(url.c_str()).starts_with("http://")) {
|
|
||||||
HTTPClient * http = new HTTPClient;
|
|
||||||
if (http->begin(url.c_str())) {
|
|
||||||
bool content_set = false;
|
|
||||||
for (JsonPair p : doc["header"].as<JsonObject>()) {
|
|
||||||
http->addHeader(p.key().c_str(), p.value().as<std::string>().c_str());
|
|
||||||
content_set |= p.key() == "content-type";
|
|
||||||
}
|
|
||||||
// if there is data, force a POST
|
|
||||||
if (Helpers::toLower(method) == "post") { // we have all lowercase
|
|
||||||
if (!content_set) {
|
|
||||||
// http->addHeader("Content-Type", value.find_first_of('{') != std::string::npos ? "application/json" : "text/plain");
|
|
||||||
if (value.starts_with('{')) {
|
|
||||||
http->addHeader(asyncsrv::T_Content_Type, asyncsrv::T_application_json, false); // auto-set to JSON
|
|
||||||
} else {
|
|
||||||
http->addHeader(asyncsrv::T_Content_Type, asyncsrv::T_text_plain, false); // auto-set to JSON
|
|
||||||
}
|
|
||||||
}
|
|
||||||
httpResult = http->POST(value.c_str());
|
|
||||||
} else {
|
|
||||||
httpResult = http->GET(); // normal GET
|
|
||||||
if (httpResult > 0) {
|
|
||||||
result = http->getString().c_str();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
http->end();
|
http->end();
|
||||||
delete http;
|
delete http;
|
||||||
|
|
||||||
// check HTTP return code
|
// check HTTP return code
|
||||||
if (httpResult != 200) {
|
if (httpResult != 200) {
|
||||||
EMSESP::logger().warning("Schedule '%s': URL command failed with http code %d", name, httpResult);
|
char error[100];
|
||||||
|
snprintf(error, sizeof(error), "Schedule %s: URL command failed with http code %d", name, httpResult);
|
||||||
|
EMSESP::logger().warning(error);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#if defined(EMSESP_DEBUG)
|
#if defined(EMSESP_DEBUG)
|
||||||
EMSESP::logger().debug("Schedule %s: URL '%s' command successful with http code %d", name, url.c_str(), httpResult);
|
char msg[100];
|
||||||
|
snprintf(msg, sizeof(msg), "Schedule %s: URL command successful with http code %d", name, httpResult);
|
||||||
|
EMSESP::logger().debug(msg);
|
||||||
#endif
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -563,7 +465,9 @@ void WebSchedulerService::condition() {
|
|||||||
} else if (match.length() == 1 && match[0] == '0' && scheduleItem.retry_cnt == 1) {
|
} else if (match.length() == 1 && match[0] == '0' && scheduleItem.retry_cnt == 1) {
|
||||||
scheduleItem.retry_cnt = 0xFF;
|
scheduleItem.retry_cnt = 0xFF;
|
||||||
} else if (match.length() != 1) { // the match is not boolean
|
} else if (match.length() != 1) { // the match is not boolean
|
||||||
|
#if defined(EMSESP_DEBUG)
|
||||||
EMSESP::logger().debug("condition result: %s", match.c_str());
|
EMSESP::logger().debug("condition result: %s", match.c_str());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
namespace emsesp {
|
namespace emsesp {
|
||||||
|
|
||||||
uint8_t WebSettings::flags_ = 0;
|
uint16_t WebSettings::flags_ = 0;
|
||||||
|
|
||||||
WebSettingsService::WebSettingsService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager)
|
WebSettingsService::WebSettingsService(AsyncWebServer * server, FS * fs, SecurityManager * securityManager)
|
||||||
: _httpEndpoint(WebSettings::read, WebSettings::update, this, server, EMSESP_SETTINGS_SERVICE_PATH, securityManager)
|
: _httpEndpoint(WebSettings::read, WebSettings::update, this, server, EMSESP_SETTINGS_SERVICE_PATH, securityManager)
|
||||||
@@ -83,20 +83,6 @@ void WebSettings::read(WebSettings & settings, JsonObject root) {
|
|||||||
root["modbus_max_clients"] = settings.modbus_max_clients;
|
root["modbus_max_clients"] = settings.modbus_max_clients;
|
||||||
root["modbus_timeout"] = settings.modbus_timeout;
|
root["modbus_timeout"] = settings.modbus_timeout;
|
||||||
root["developer_mode"] = settings.developer_mode;
|
root["developer_mode"] = settings.developer_mode;
|
||||||
#ifndef NO_TLS_SUPPORT
|
|
||||||
root["email_enabled"] = settings.email_enabled;
|
|
||||||
#else
|
|
||||||
root["email_enabled"] = false;
|
|
||||||
#endif
|
|
||||||
root["email_ssl"] = settings.email_ssl;
|
|
||||||
root["email_starttls"] = settings.email_starttls;
|
|
||||||
root["email_server"] = settings.email_server;
|
|
||||||
root["email_port"] = settings.email_port;
|
|
||||||
root["email_login"] = settings.email_login;
|
|
||||||
root["email_pass"] = settings.email_pass;
|
|
||||||
root["email_sender"] = settings.email_sender;
|
|
||||||
root["email_recp"] = settings.email_recp;
|
|
||||||
root["email_subject"] = settings.email_subject;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// call on initialization and also when settings are updated/saved via web or console
|
// call on initialization and also when settings are updated/saved via web or console
|
||||||
@@ -128,11 +114,11 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) {
|
|||||||
reset_flags();
|
reset_flags();
|
||||||
|
|
||||||
// before loading new board profile free old gpios from used list to allow remapping
|
// before loading new board profile free old gpios from used list to allow remapping
|
||||||
EMSESP::system_.remove_gpio(original_settings.led_gpio);
|
EMSESP::system_.remove_optional_gpio(original_settings.led_gpio);
|
||||||
EMSESP::system_.remove_gpio(original_settings.dallas_gpio);
|
EMSESP::system_.remove_optional_gpio(original_settings.dallas_gpio);
|
||||||
EMSESP::system_.remove_gpio(original_settings.pbutton_gpio);
|
EMSESP::system_.remove_gpio(original_settings.pbutton_gpio);
|
||||||
EMSESP::system_.remove_gpio(original_settings.rx_gpio);
|
EMSESP::system_.remove_optional_gpio(original_settings.rx_gpio);
|
||||||
EMSESP::system_.remove_gpio(original_settings.tx_gpio);
|
EMSESP::system_.remove_optional_gpio(original_settings.tx_gpio);
|
||||||
|
|
||||||
// see if the user has changed the board profile
|
// see if the user has changed the board profile
|
||||||
// this will set: led_gpio, dallas_gpio, rx_gpio, tx_gpio, pbutton_gpio, phy_type, eth_power, eth_phy_addr, eth_clock_mode, led_type
|
// this will set: led_gpio, dallas_gpio, rx_gpio, tx_gpio, pbutton_gpio, phy_type, eth_power, eth_phy_addr, eth_clock_mode, led_type
|
||||||
@@ -256,10 +242,14 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) {
|
|||||||
check_flag(original_settings.low_clock, settings.low_clock, ChangeFlags::RESTART);
|
check_flag(original_settings.low_clock, settings.low_clock, ChangeFlags::RESTART);
|
||||||
|
|
||||||
// Modbus settings
|
// Modbus settings
|
||||||
settings.modbus_enabled = root["modbus_enabled"] | EMSESP_DEFAULT_MODBUS_ENABLED;
|
settings.modbus_enabled = root["modbus_enabled"] | EMSESP_DEFAULT_MODBUS_ENABLED;
|
||||||
settings.modbus_port = root["modbus_port"] | EMSESP_DEFAULT_MODBUS_PORT;
|
check_flag(original_settings.modbus_enabled, settings.modbus_enabled, ChangeFlags::MODBUS);
|
||||||
|
settings.modbus_port = root["modbus_port"] | EMSESP_DEFAULT_MODBUS_PORT;
|
||||||
|
check_flag(original_settings.modbus_port, settings.modbus_port, ChangeFlags::MODBUS);
|
||||||
settings.modbus_max_clients = root["modbus_max_clients"] | EMSESP_DEFAULT_MODBUS_MAX_CLIENTS;
|
settings.modbus_max_clients = root["modbus_max_clients"] | EMSESP_DEFAULT_MODBUS_MAX_CLIENTS;
|
||||||
settings.modbus_timeout = root["modbus_timeout"] | EMSESP_DEFAULT_MODBUS_TIMEOUT;
|
check_flag(original_settings.modbus_max_clients, settings.modbus_max_clients, ChangeFlags::MODBUS);
|
||||||
|
settings.modbus_timeout = root["modbus_timeout"] | EMSESP_DEFAULT_MODBUS_TIMEOUT;
|
||||||
|
check_flag(original_settings.modbus_timeout, settings.modbus_timeout, ChangeFlags::MODBUS);
|
||||||
|
|
||||||
//
|
//
|
||||||
// these may need mqtt restart to rebuild HA discovery topics
|
// these may need mqtt restart to rebuild HA discovery topics
|
||||||
@@ -310,20 +300,6 @@ StateUpdateResult WebSettings::update(JsonObject root, WebSettings & settings) {
|
|||||||
settings.weblog_level = root["weblog_level"] | EMSESP_DEFAULT_WEBLOG_LEVEL;
|
settings.weblog_level = root["weblog_level"] | EMSESP_DEFAULT_WEBLOG_LEVEL;
|
||||||
settings.weblog_compact = root["weblog_compact"] | EMSESP_DEFAULT_WEBLOG_COMPACT;
|
settings.weblog_compact = root["weblog_compact"] | EMSESP_DEFAULT_WEBLOG_COMPACT;
|
||||||
|
|
||||||
settings.email_enabled = root["email_enabled"] | FACTORY_EMAIL_ENABLE;
|
|
||||||
settings.email_ssl = root["email_ssl"] | FACTORY_EMAIL_SSL;
|
|
||||||
settings.email_starttls = root["email_starttls"] | FACTORY_EMAIL_STARTTLS;
|
|
||||||
settings.email_server = root["email_server"] | FACTORY_EMAIL_SERVER;
|
|
||||||
settings.email_port = root["email_port"] | FACTORY_EMAIL_PORT;
|
|
||||||
settings.email_login = root["email_login"] | FACTORY_EMAIL_LOGIN;
|
|
||||||
settings.email_pass = root["email_pass"] | FACTORY_EMAIL_PASSWORD;
|
|
||||||
settings.email_sender = root["email_sender"] | FACTORY_EMAIL_FROM;
|
|
||||||
settings.email_recp = root["email_recp"] | FACTORY_EMAIL_TO;
|
|
||||||
settings.email_subject = root["email_subject"] | FACTORY_EMAIL_SUBJECT;
|
|
||||||
|
|
||||||
if (settings.email_ssl && settings.email_starttls) {
|
|
||||||
settings.email_ssl = false;
|
|
||||||
}
|
|
||||||
// if no psram limit weblog buffer to 25 messages
|
// if no psram limit weblog buffer to 25 messages
|
||||||
if (EMSESP::system_.PSram() > 0) {
|
if (EMSESP::system_.PSram() > 0) {
|
||||||
settings.weblog_buffer = root["weblog_buffer"] | EMSESP_DEFAULT_WEBLOG_BUFFER;
|
settings.weblog_buffer = root["weblog_buffer"] | EMSESP_DEFAULT_WEBLOG_BUFFER;
|
||||||
@@ -396,7 +372,11 @@ void WebSettingsService::onUpdate() {
|
|||||||
Mqtt::reset_mqtt(); // reload MQTT, init HA etc
|
Mqtt::reset_mqtt(); // reload MQTT, init HA etc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (WebSettings::has_flags(WebSettings::ChangeFlags::MODBUS)) {
|
||||||
|
EMSESP::system_.modbus_init();
|
||||||
|
}
|
||||||
WebSettings::reset_flags();
|
WebSettings::reset_flags();
|
||||||
|
EMSESP::system_.reset_unused_gpios();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebSettingsService::begin() {
|
void WebSettingsService::begin() {
|
||||||
@@ -482,14 +462,23 @@ void WebSettings::set_board_profile(WebSettings & settings) {
|
|||||||
#if CONFIG_IDF_TARGET_ESP32
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
// check for no PSRAM, could be a E32 or S32?
|
// check for no PSRAM, could be a E32 or S32?
|
||||||
if (!ESP.getPsramSize()) {
|
if (!ESP.getPsramSize()) {
|
||||||
|
#if ESP_ARDUINO_VERSION_MAJOR < 3
|
||||||
|
if (ETH.begin(1, 16, 23, 18, ETH_PHY_LAN8720, ETH_CLOCK_GPIO0_IN)) {
|
||||||
|
#else
|
||||||
if (ETH.begin(ETH_PHY_LAN8720, 1, 23, 18, 16, ETH_CLOCK_GPIO0_IN)) {
|
if (ETH.begin(ETH_PHY_LAN8720, 1, 23, 18, 16, ETH_CLOCK_GPIO0_IN)) {
|
||||||
|
#endif
|
||||||
settings.board_profile = "E32"; // Ethernet without PSRAM
|
settings.board_profile = "E32"; // Ethernet without PSRAM
|
||||||
} else {
|
} else {
|
||||||
settings.board_profile = "S32"; // ESP32 standard WiFi without PSRAM
|
settings.board_profile = "S32"; // ESP32 standard WiFi without PSRAM
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// check for boards with PSRAM, could be a E32V2 otherwise default back to the S32
|
// check for boards with PSRAM, could be a E32V2 otherwise default back to the S32
|
||||||
|
#if ESP_ARDUINO_VERSION_MAJOR < 3
|
||||||
|
if (ETH.begin(0, 15, 23, 18, ETH_PHY_LAN8720, ETH_CLOCK_GPIO0_OUT)) {
|
||||||
|
#else
|
||||||
if (ETH.begin(ETH_PHY_LAN8720, 0, 23, 18, 15, ETH_CLOCK_GPIO0_OUT)) {
|
if (ETH.begin(ETH_PHY_LAN8720, 0, 23, 18, 15, ETH_CLOCK_GPIO0_OUT)) {
|
||||||
|
#endif
|
||||||
|
|
||||||
if (analogReadMilliVolts(39) > 700) { // core voltage > 2.6V
|
if (analogReadMilliVolts(39) > 700) { // core voltage > 2.6V
|
||||||
settings.board_profile = "E32V2_2"; // Ethernet, PSRAM, internal sensors
|
settings.board_profile = "E32V2_2"; // Ethernet, PSRAM, internal sensors
|
||||||
} else {
|
} else {
|
||||||
@@ -538,7 +527,7 @@ void WebSettings::set_board_profile(WebSettings & settings) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// returns true if the value was changed
|
// returns true if the value was changed
|
||||||
bool WebSettings::check_flag(int prev_v, int new_v, uint8_t flag) {
|
bool WebSettings::check_flag(int prev_v, int new_v, uint16_t flag) {
|
||||||
if (prev_v != new_v) {
|
if (prev_v != new_v) {
|
||||||
add_flags(flag);
|
add_flags(flag);
|
||||||
#if defined(EMSESP_DEBUG)
|
#if defined(EMSESP_DEBUG)
|
||||||
@@ -549,11 +538,11 @@ bool WebSettings::check_flag(int prev_v, int new_v, uint8_t flag) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebSettings::add_flags(uint8_t flags) {
|
void WebSettings::add_flags(uint16_t flags) {
|
||||||
flags_ |= flags;
|
flags_ |= flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WebSettings::has_flags(uint8_t flags) {
|
bool WebSettings::has_flags(uint16_t flags) {
|
||||||
return (flags_ & flags) == flags;
|
return (flags_ & flags) == flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -561,7 +550,7 @@ void WebSettings::reset_flags() {
|
|||||||
flags_ = ChangeFlags::NONE;
|
flags_ = ChangeFlags::NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t WebSettings::get_flags() {
|
uint16_t WebSettings::get_flags() {
|
||||||
return flags_;
|
return flags_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,36 +26,6 @@
|
|||||||
#define EMSESP_SETTINGS_SERVICE_PATH "/rest/settings"
|
#define EMSESP_SETTINGS_SERVICE_PATH "/rest/settings"
|
||||||
#define EMSESP_BOARD_PROFILE_SERVICE_PATH "/rest/boardProfile"
|
#define EMSESP_BOARD_PROFILE_SERVICE_PATH "/rest/boardProfile"
|
||||||
|
|
||||||
#ifndef FACTORY_EMAIL_ENABLE
|
|
||||||
#define FACTORY_EMAIL_ENABLE false
|
|
||||||
#endif
|
|
||||||
#ifndef FACTORY_EMAIL_SSL
|
|
||||||
#define FACTORY_EMAIL_SSL false
|
|
||||||
#endif
|
|
||||||
#ifndef FACTORY_EMAIL_STARTTLS
|
|
||||||
#define FACTORY_EMAIL_STARTTLS true
|
|
||||||
#endif
|
|
||||||
#ifndef FACTORY_EMAIL_PORT
|
|
||||||
#define FACTORY_EMAIL_PORT 587
|
|
||||||
#endif
|
|
||||||
#ifndef FACTORY_EMAIL_SERVER
|
|
||||||
#define FACTORY_EMAIL_SERVER "smtp.example.net"
|
|
||||||
#endif
|
|
||||||
#ifndef FACTORY_EMAIL_LOGIN
|
|
||||||
#define FACTORY_EMAIL_LOGIN ""
|
|
||||||
#endif
|
|
||||||
#ifndef FACTORY_EMAIL_PASSWORD
|
|
||||||
#define FACTORY_EMAIL_PASSWORD ""
|
|
||||||
#endif
|
|
||||||
#ifndef FACTORY_EMAIL_FROM
|
|
||||||
#define FACTORY_EMAIL_FROM "ems-esp@example.net"
|
|
||||||
#endif
|
|
||||||
#ifndef FACTORY_EMAIL_TO
|
|
||||||
#define FACTORY_EMAIL_TO ""
|
|
||||||
#endif
|
|
||||||
#ifndef FACTORY_EMAIL_SUBJECT
|
|
||||||
#define FACTORY_EMAIL_SUBJECT "ems-esp notification"
|
|
||||||
#endif
|
|
||||||
namespace emsesp {
|
namespace emsesp {
|
||||||
|
|
||||||
class WebSettings {
|
class WebSettings {
|
||||||
@@ -107,16 +77,6 @@ class WebSettings {
|
|||||||
uint16_t modbus_port;
|
uint16_t modbus_port;
|
||||||
uint8_t modbus_max_clients;
|
uint8_t modbus_max_clients;
|
||||||
uint32_t modbus_timeout;
|
uint32_t modbus_timeout;
|
||||||
bool email_enabled;
|
|
||||||
bool email_ssl;
|
|
||||||
bool email_starttls;
|
|
||||||
String email_server;
|
|
||||||
uint16_t email_port;
|
|
||||||
String email_login;
|
|
||||||
String email_pass;
|
|
||||||
String email_sender;
|
|
||||||
String email_recp;
|
|
||||||
String email_subject;
|
|
||||||
|
|
||||||
uint8_t phy_type;
|
uint8_t phy_type;
|
||||||
int8_t eth_power; // -1 means disabled
|
int8_t eth_power; // -1 means disabled
|
||||||
@@ -128,7 +88,7 @@ class WebSettings {
|
|||||||
static void read(WebSettings & settings, JsonObject root);
|
static void read(WebSettings & settings, JsonObject root);
|
||||||
static StateUpdateResult update(JsonObject root, WebSettings & settings);
|
static StateUpdateResult update(JsonObject root, WebSettings & settings);
|
||||||
|
|
||||||
enum ChangeFlags : uint8_t {
|
enum ChangeFlags : uint16_t {
|
||||||
NONE = 0,
|
NONE = 0,
|
||||||
UART = (1 << 0), // 1 - uart
|
UART = (1 << 0), // 1 - uart
|
||||||
SYSLOG = (1 << 1), // 2 - syslog
|
SYSLOG = (1 << 1), // 2 - syslog
|
||||||
@@ -138,19 +98,20 @@ class WebSettings {
|
|||||||
LED = (1 << 5), // 32 - led
|
LED = (1 << 5), // 32 - led
|
||||||
BUTTON = (1 << 6), // 64 - button
|
BUTTON = (1 << 6), // 64 - button
|
||||||
MQTT = (1 << 7), // 128 - mqtt
|
MQTT = (1 << 7), // 128 - mqtt
|
||||||
RESTART = 0xFF // 255 - restart request (all changes)
|
MODBUS = (1 << 8), // 256 - modbus
|
||||||
|
RESTART = 0xFFFF // restart request (all changes)
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool check_flag(int prev_v, int new_v, uint8_t flag);
|
static bool check_flag(int prev_v, int new_v, uint16_t flag);
|
||||||
static void add_flags(uint8_t flags);
|
static void add_flags(uint16_t flags);
|
||||||
static bool has_flags(uint8_t flags);
|
static bool has_flags(uint16_t flags);
|
||||||
static void reset_flags();
|
static void reset_flags();
|
||||||
static uint8_t get_flags();
|
static uint16_t get_flags();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void set_board_profile(WebSettings & settings);
|
static void set_board_profile(WebSettings & settings);
|
||||||
|
|
||||||
static uint8_t flags_;
|
static uint16_t flags_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WebSettingsService : public StatefulService<WebSettings> {
|
class WebSettingsService : public StatefulService<WebSettings> {
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ void uart_telegram(const char * rx_data) {
|
|||||||
|
|
||||||
// add an EMS device and register it
|
// add an EMS device and register it
|
||||||
void add_device(uint8_t device_id, uint8_t product_id) {
|
void add_device(uint8_t device_id, uint8_t product_id) {
|
||||||
uart_telegram({device_id, 0x0B, EMSdevice::EMS_TYPE_VERSION, 0, product_id, 1, 0});
|
uart_telegram({device_id, 0x49, EMSdevice::EMS_TYPE_VERSION, 0, product_id, 1, 0});
|
||||||
}
|
}
|
||||||
|
|
||||||
// add our EMS test devices
|
// add our EMS test devices
|
||||||
@@ -143,14 +143,14 @@ void add_devices() {
|
|||||||
add_device(0x08, 123); // Nefit Trendline
|
add_device(0x08, 123); // Nefit Trendline
|
||||||
|
|
||||||
// UBAuptime
|
// UBAuptime
|
||||||
uart_telegram({0x08, 0x0B, 0x14, 00, 0x3C, 0x1F, 0xAC, 0x70});
|
uart_telegram({0x08, 0x49, 0x14, 00, 0x3C, 0x1F, 0xAC, 0x70});
|
||||||
|
|
||||||
// Boiler -> Me, UBAMonitorFast(0x18), telegram: 08 00 18 00 00 02 5A 73 3D 0A 10 65 40 02 1A 80 00 01 E1 01 76 0E 3D 48 00 C9 44 02 00 (#data=25)
|
// Boiler -> Me, UBAMonitorFast(0x18), telegram: 08 00 18 00 00 02 5A 73 3D 0A 10 65 40 02 1A 80 00 01 E1 01 76 0E 3D 48 00 C9 44 02 00 (#data=25)
|
||||||
uart_telegram({0x08, 0x00, 0x18, 0x00, 0x00, 0x02, 0x5A, 0x73, 0x3D, 0x0A, 0x10, 0x65, 0x40, 0x02, 0x1A,
|
uart_telegram({0x08, 0x00, 0x18, 0x00, 0x00, 0x02, 0x5A, 0x73, 0x3D, 0x0A, 0x10, 0x65, 0x40, 0x02, 0x1A,
|
||||||
0x80, 0x00, 0x01, 0xE1, 0x01, 0x76, 0x0E, 0x3D, 0x48, 0x00, 0xC9, 0x44, 0x02, 0x00});
|
0x80, 0x00, 0x01, 0xE1, 0x01, 0x76, 0x0E, 0x3D, 0x48, 0x00, 0xC9, 0x44, 0x02, 0x00});
|
||||||
|
|
||||||
// Boiler -> Me, UBAParameterWW(0x33), telegram: 08 0B 33 00 08 FF 34 FB 00 28 00 00 46 00 FF FF 00 (#data=13)
|
// Boiler -> Me, UBAParameterWW(0x33), telegram: 08 49 33 00 08 FF 34 FB 00 28 00 00 46 00 FF FF 00 (#data=13)
|
||||||
uart_telegram({0x08, 0x0B, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00});
|
uart_telegram({0x08, 0x49, 0x33, 0x00, 0x08, 0xFF, 0x34, 0xFB, 0x00, 0x28, 0x00, 0x00, 0x46, 0x00, 0xFF, 0xFF, 0x00});
|
||||||
|
|
||||||
//
|
//
|
||||||
// thermostat
|
// thermostat
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ void test_23() {
|
|||||||
"\"temperatureSensorReads\":0,\"temperatureSensorFails\":0},\"analog\":{\"enabled\":true,\"analogSensors\":5,\"analogSensorReads\":0,"
|
"\"temperatureSensorReads\":0,\"temperatureSensorFails\":0},\"analog\":{\"enabled\":true,\"analogSensors\":5,\"analogSensorReads\":0,"
|
||||||
"\"analogSensorFails\":0},\"api\":{\"APICalls\":0,\"APIFails\":0},\"bus\":{\"busStatus\":\"connected\",\"busProtocol\":\"Buderus\","
|
"\"analogSensorFails\":0},\"api\":{\"APICalls\":0,\"APIFails\":0},\"bus\":{\"busStatus\":\"connected\",\"busProtocol\":\"Buderus\","
|
||||||
"\"busTelegramsReceived\":8,\"busReads\":0,\"busWrites\":0,\"busIncompleteTelegrams\":0,\"busReadsFailed\":0,\"busWritesFailed\":0,"
|
"\"busTelegramsReceived\":8,\"busReads\":0,\"busWrites\":0,\"busIncompleteTelegrams\":0,\"busReadsFailed\":0,\"busWritesFailed\":0,"
|
||||||
"\"busRxLineQuality\":100,\"busTxLineQuality\":100},\"settings\":{\"boardProfile\":\"S32\",\"locale\":\"en\",\"txMode\":1,\"emsBusID\":11,"
|
"\"busRxLineQuality\":100,\"busTxLineQuality\":100},\"settings\":{\"boardProfile\":\"S32\",\"locale\":\"en\",\"txMode\":5,\"emsBusID\":73,"
|
||||||
"\"showerTimer\":false,\"showerMinDuration\":180,\"showerAlert\":false,\"hideLed\":false,\"noTokenApi\":false,\"readonlyMode\":false,\"fahrenheit\":"
|
"\"showerTimer\":false,\"showerMinDuration\":180,\"showerAlert\":false,\"hideLed\":false,\"noTokenApi\":false,\"readonlyMode\":false,\"fahrenheit\":"
|
||||||
"false,\"dallasParasite\":false,\"boolFormat\":1,\"boolDashboard\":1,\"enumFormat\":1,\"analogEnabled\":true,\"telnetEnabled\":true,"
|
"false,\"dallasParasite\":false,\"boolFormat\":1,\"boolDashboard\":1,\"enumFormat\":1,\"analogEnabled\":true,\"telnetEnabled\":true,"
|
||||||
"\"maxWebLogBuffer\":25,\"modbusEnabled\":false,\"forceHeatingOff\":false,\"developerMode\":false},\"devices\":[{\"type\":\"boiler\",\"name\":\"My "
|
"\"maxWebLogBuffer\":25,\"modbusEnabled\":false,\"forceHeatingOff\":false,\"developerMode\":false},\"devices\":[{\"type\":\"boiler\",\"name\":\"My "
|
||||||
@@ -259,7 +259,7 @@ void test_24() {
|
|||||||
"\"temperatureSensorReads\":0,\"temperatureSensorFails\":0},\"analog\":{\"enabled\":true,\"analogSensors\":5,\"analogSensorReads\":0,"
|
"\"temperatureSensorReads\":0,\"temperatureSensorFails\":0},\"analog\":{\"enabled\":true,\"analogSensors\":5,\"analogSensorReads\":0,"
|
||||||
"\"analogSensorFails\":0},\"api\":{\"APICalls\":0,\"APIFails\":0},\"bus\":{\"busStatus\":\"connected\",\"busProtocol\":\"Buderus\","
|
"\"analogSensorFails\":0},\"api\":{\"APICalls\":0,\"APIFails\":0},\"bus\":{\"busStatus\":\"connected\",\"busProtocol\":\"Buderus\","
|
||||||
"\"busTelegramsReceived\":8,\"busReads\":0,\"busWrites\":0,\"busIncompleteTelegrams\":0,\"busReadsFailed\":0,\"busWritesFailed\":0,"
|
"\"busTelegramsReceived\":8,\"busReads\":0,\"busWrites\":0,\"busIncompleteTelegrams\":0,\"busReadsFailed\":0,\"busWritesFailed\":0,"
|
||||||
"\"busRxLineQuality\":100,\"busTxLineQuality\":100},\"settings\":{\"boardProfile\":\"S32\",\"locale\":\"en\",\"txMode\":1,\"emsBusID\":11,"
|
"\"busRxLineQuality\":100,\"busTxLineQuality\":100},\"settings\":{\"boardProfile\":\"S32\",\"locale\":\"en\",\"txMode\":5,\"emsBusID\":73,"
|
||||||
"\"showerTimer\":false,\"showerMinDuration\":180,\"showerAlert\":false,\"hideLed\":false,\"noTokenApi\":false,\"readonlyMode\":false,\"fahrenheit\":"
|
"\"showerTimer\":false,\"showerMinDuration\":180,\"showerAlert\":false,\"hideLed\":false,\"noTokenApi\":false,\"readonlyMode\":false,\"fahrenheit\":"
|
||||||
"false,\"dallasParasite\":false,\"boolFormat\":1,\"boolDashboard\":1,\"enumFormat\":1,\"analogEnabled\":true,\"telnetEnabled\":true,"
|
"false,\"dallasParasite\":false,\"boolFormat\":1,\"boolDashboard\":1,\"enumFormat\":1,\"analogEnabled\":true,\"telnetEnabled\":true,"
|
||||||
"\"maxWebLogBuffer\":25,\"modbusEnabled\":false,\"forceHeatingOff\":false,\"developerMode\":false},\"devices\":[{\"type\":\"boiler\",\"name\":\"My "
|
"\"maxWebLogBuffer\":25,\"modbusEnabled\":false,\"forceHeatingOff\":false,\"developerMode\":false},\"devices\":[{\"type\":\"boiler\",\"name\":\"My "
|
||||||
@@ -330,8 +330,8 @@ void test_25() {
|
|||||||
"gauge\\nemsesp_bus_buswritesfailed 0\\n# HELP emsesp_bus_busrxlinequality busRxLineQuality\\n# TYPE emsesp_bus_busrxlinequality "
|
"gauge\\nemsesp_bus_buswritesfailed 0\\n# HELP emsesp_bus_busrxlinequality busRxLineQuality\\n# TYPE emsesp_bus_busrxlinequality "
|
||||||
"gauge\\nemsesp_bus_busrxlinequality 100\\n# HELP emsesp_bus_bustxlinequality busTxLineQuality\\n# TYPE emsesp_bus_bustxlinequality "
|
"gauge\\nemsesp_bus_busrxlinequality 100\\n# HELP emsesp_bus_bustxlinequality busTxLineQuality\\n# TYPE emsesp_bus_bustxlinequality "
|
||||||
"gauge\\nemsesp_bus_bustxlinequality 100\\n# HELP emsesp_bus_info info\\n# TYPE emsesp_bus_info gauge\\nemsesp_bus_info{busstatus=\\\"connected\\\", "
|
"gauge\\nemsesp_bus_bustxlinequality 100\\n# HELP emsesp_bus_info info\\n# TYPE emsesp_bus_info gauge\\nemsesp_bus_info{busstatus=\\\"connected\\\", "
|
||||||
"busprotocol=\\\"Buderus\\\"} 1\\n# HELP emsesp_settings_txmode txMode\\n# TYPE emsesp_settings_txmode gauge\\nemsesp_settings_txmode 1\\n# HELP "
|
"busprotocol=\\\"Buderus\\\"} 1\\n# HELP emsesp_settings_txmode txMode\\n# TYPE emsesp_settings_txmode gauge\\nemsesp_settings_txmode 5\\n# HELP "
|
||||||
"emsesp_settings_emsbusid emsBusID\\n# TYPE emsesp_settings_emsbusid gauge\\nemsesp_settings_emsbusid 11\\n# HELP emsesp_settings_showertimer "
|
"emsesp_settings_emsbusid emsBusID\\n# TYPE emsesp_settings_emsbusid gauge\\nemsesp_settings_emsbusid 73\\n# HELP emsesp_settings_showertimer "
|
||||||
"showerTimer\\n# TYPE emsesp_settings_showertimer gauge\\nemsesp_settings_showertimer 0\\n# HELP emsesp_settings_showerminduration "
|
"showerTimer\\n# TYPE emsesp_settings_showertimer gauge\\nemsesp_settings_showertimer 0\\n# HELP emsesp_settings_showerminduration "
|
||||||
"showerMinDuration\\n# TYPE emsesp_settings_showerminduration gauge\\nemsesp_settings_showerminduration 180\\n# HELP emsesp_settings_showeralert "
|
"showerMinDuration\\n# TYPE emsesp_settings_showerminduration gauge\\nemsesp_settings_showerminduration 180\\n# HELP emsesp_settings_showeralert "
|
||||||
"showerAlert\\n# TYPE emsesp_settings_showeralert gauge\\nemsesp_settings_showeralert 0\\n# HELP emsesp_settings_hideled hideLed\\n# TYPE "
|
"showerAlert\\n# TYPE emsesp_settings_showeralert gauge\\nemsesp_settings_showeralert 0\\n# HELP emsesp_settings_hideled hideLed\\n# TYPE "
|
||||||
|
|||||||
Reference in New Issue
Block a user