mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 15:59:52 +03:00
Compare commits
52 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0f6ad533f6 | ||
|
|
4ae68fc3fd | ||
|
|
b97a9e3e5b | ||
|
|
e79e104837 | ||
|
|
7851e83162 | ||
|
|
389f0bd2e8 | ||
|
|
a4bbbb460a | ||
|
|
d01697a065 | ||
|
|
a027d17a7d | ||
|
|
a27787d0d5 | ||
|
|
24baf844fd | ||
|
|
6f125b7fbb | ||
|
|
51b00cb280 | ||
|
|
31ffa8483e | ||
|
|
e7cbd97662 | ||
|
|
0b0ca1efd1 | ||
|
|
4518396833 | ||
|
|
8de6448b74 | ||
|
|
6f1b65e70b | ||
|
|
b93890440a | ||
|
|
7cee4916a2 | ||
|
|
3e7b9a7dd9 | ||
|
|
069c63b55a | ||
|
|
e9bd1d4b81 | ||
|
|
1fa1ee5b24 | ||
|
|
8800b88f62 | ||
|
|
fd6df7279b | ||
|
|
0dceb25569 | ||
|
|
96d5324945 | ||
|
|
971df73f13 | ||
|
|
24a4cb85ff | ||
|
|
7f9582d01a | ||
|
|
dfa5e23e90 | ||
|
|
016e18002c | ||
|
|
e0b89ae3ed | ||
|
|
ff1cf12e0c | ||
|
|
2f44beccc2 | ||
|
|
558e48f671 | ||
|
|
e60048f5fb | ||
|
|
6ad1dd1a77 | ||
|
|
daad2ffe6c | ||
|
|
a9caadaf5e | ||
|
|
0d8d750e46 | ||
|
|
7a394c8e89 | ||
|
|
bcf83616f8 | ||
|
|
32bf13ca9a | ||
|
|
608500e417 | ||
|
|
bfe498758c | ||
|
|
bb6e2b9336 | ||
|
|
d0166f7f12 | ||
|
|
6a1bc00f04 | ||
|
|
bee4b3970d |
61
.github/ISSUE_TEMPLATE/bug_report.md
vendored
61
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,35 +1,50 @@
|
|||||||
---
|
---
|
||||||
name: Bug report
|
name: Problem Report
|
||||||
about: Create a report to help us improve
|
about: Create a Report to help us improve
|
||||||
title: ''
|
|
||||||
labels: bug
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
*Before creating a new issue please check that you have:*
|
<!-- Thanks for reporting a problem for this project. READ THIS FIRST:
|
||||||
|
|
||||||
* *searched the existing [issues](https://github.com/emsesp/EMS-ESP32/issues) (both open and closed)*
|
Please DO NOT OPEN AN ISSUE if your EMS-ESP version is not the latest from the dev branch, please update your device before submitting your issue. Your problem might already be solved. The latest precompiled binaries of EMS-ESP can be downloaded from https://github.com/emsesp/EMS-ESP32/releases/tag/latest
|
||||||
* *searched the [documentation help section](https://emsesp.github.io/docs)*
|
|
||||||
|
|
||||||
*Completing this template will help developers and contributors to address the issue. Try to be as specific and extensive as possible. If the information provided is not enough the issue will likely be closed.*
|
Please take a few minutes to complete the requested information below.
|
||||||
|
|
||||||
*You can now remove this line and the above ones. Text in italic is meant to be replaced by your own words. If any of the sections below are not relevant to the issue (for instance, the screenshots) then you can delete them.*
|
-->
|
||||||
|
|
||||||
**Bug description**
|
### PROBLEM DESCRIPTION
|
||||||
*A clear and concise description of what the bug is. Mention which EMS-ESP version you're using.*
|
|
||||||
|
|
||||||
**Steps to reproduce**
|
_A clear and concise description of what the problem is._
|
||||||
*Steps to reproduce the behavior.*
|
|
||||||
|
|
||||||
**Expected behavior**
|
### REQUESTED INFORMATION
|
||||||
*A clear and concise description of what you expected to happen.*
|
|
||||||
|
|
||||||
**Screenshots**
|
_Make sure your have performed every step and checked the applicable boxes before submitting your issue. Thank you!_
|
||||||
*If applicable, add screenshots to help explain your problem.*
|
|
||||||
|
|
||||||
**Device information**
|
- [ ] Searched the problem in [issues](https://github.com/emsesp/EMS-ESP32/issues)
|
||||||
*Copy-paste here the information as it is outputted by the device. You can get this information by from http://ems-esp.local/api/system*
|
- [ ] Searched the problem in [discussions](https://github.com/emsesp/EMS-ESP32/discussions)
|
||||||
|
- [ ] Searched the problem in the [docs](https://emsesp.github.io/docs/Troubleshooting/)
|
||||||
|
- [ ] Searched the problem in the [chat](https://discord.gg/3J3GgnzpyT)
|
||||||
|
- [ ] Provide the output of http://ems-esp.local/api/system :
|
||||||
|
|
||||||
**Additional context**
|
```lua
|
||||||
*Add any other context about the problem here.*
|
System information output here:
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### TO REPRODUCE
|
||||||
|
|
||||||
|
_Steps to reproduce the behavior:_
|
||||||
|
|
||||||
|
### EXPECTED BEHAVIOUR
|
||||||
|
|
||||||
|
_A clear and concise description of what you expected to happen._
|
||||||
|
|
||||||
|
### SCREENSHOTS
|
||||||
|
|
||||||
|
_If applicable, add screenshots to help explain your problem._
|
||||||
|
|
||||||
|
### ADDITIONAL CONTEXT
|
||||||
|
|
||||||
|
_Add any other context about the problem here._
|
||||||
|
|
||||||
|
**(Please, remember to close the issue when the problem has been addressed)**
|
||||||
|
|||||||
11
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
11
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
blank_issues_enabled: false
|
||||||
|
contact_links:
|
||||||
|
- name: EMS-ESP Docs
|
||||||
|
url: https://emsesp.github.io/docs/
|
||||||
|
about: All the information related to EMS-ESP.
|
||||||
|
- name: EMS-ESP Discussions and Support
|
||||||
|
url: https://github.com/emsesp/EMS-ESP32/discussions
|
||||||
|
about: EMS-ESP usage Questions, Feature Requests and Projects.
|
||||||
|
- name: EMS-ESP Users Chat
|
||||||
|
url: https://discord.gg/3J3GgnzpyT
|
||||||
|
about: Chat for feedback, questions and troubleshooting.
|
||||||
26
.github/ISSUE_TEMPLATE/feature_request.md
vendored
26
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@@ -1,26 +0,0 @@
|
|||||||
---
|
|
||||||
name: Feature request
|
|
||||||
about: Suggest an idea for this project
|
|
||||||
title: ''
|
|
||||||
labels: enhancement
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
*Before creating a new feature request please check that you have searched the existing [issues](https://github.com/emsesp/EMS-ESP32/issues) (both open and closed)*
|
|
||||||
|
|
||||||
*Completing this template will help developers and contributors evaluating the feature. If the information provided is not enough the issue will likely be closed.*
|
|
||||||
|
|
||||||
*You can now remove this line and the above ones. Text in italic is meant to be replaced by your own words. If any of the sections below are not relevant to the request then you can delete them.*
|
|
||||||
|
|
||||||
**Is your feature request related to a problem? Please describe.**
|
|
||||||
*A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]*
|
|
||||||
|
|
||||||
**Describe the solution you'd like**
|
|
||||||
*A clear and concise description of what you want to happen.*
|
|
||||||
|
|
||||||
**Describe alternatives you've considered**
|
|
||||||
*A clear and concise description of any alternative solutions or features you've considered.*
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
*Add any other context or screenshots about the feature request here.*
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
---
|
|
||||||
name: Questions & Troubleshooting
|
|
||||||
about: Anything not a bug or feature request
|
|
||||||
title: ''
|
|
||||||
labels: question
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
*Before creating a new issue please check that you have:*
|
|
||||||
|
|
||||||
* *searched the existing [issues](https://github.com/emsesp/EMS-ESP32/issues) (both open and closed)*
|
|
||||||
* *searched the [documentation help section](https://emsesp.github.io/docs)*
|
|
||||||
|
|
||||||
*Completing this template will help developers and contributors help you. Try to be as specific and extensive as possible. If the information provided is not enough the issue will likely be closed.*
|
|
||||||
|
|
||||||
*You can now remove this line and the above ones. Text in italic is meant to be replaced by your own words. If any of the sections below are not relevant to the issue (for instance, the screenshots) then you can delete them.*
|
|
||||||
|
|
||||||
**Question**
|
|
||||||
*A clear and concise description of what the problem/doubt is.*
|
|
||||||
|
|
||||||
**Screenshots**
|
|
||||||
*If applicable, add screenshots to help explain your problem.*
|
|
||||||
|
|
||||||
**Device information**
|
|
||||||
*Copy-paste here the information as it is outputted by the device. You can get this information from http://ems-esp.local/api/system*
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
*Add any other context about the problem here.*
|
|
||||||
62
CHANGELOG.md
62
CHANGELOG.md
@@ -5,6 +5,68 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
# [3.5.0] February 6 2023
|
||||||
|
|
||||||
|
## **IMPORTANT! BREAKING CHANGES**
|
||||||
|
|
||||||
|
- When upgrading to v3.5 for the first time from v3.4 on a BBQKees Gateway board you will need to use the [EMS-EPS Flasher](https://github.com/emsesp/EMS-ESP-Flasher/releases) to correctly re-partition the flash. Make sure you backup the settings and customizations from the WebUI (System->Upload/Download) and restore after the upgrade.
|
||||||
|
- Support for multiple EMS-ESPs [#759] has been added as an optional setting for MQTT. When enabled, which is now the default, all MQTT Discovery Entity IDs will include the MQTT base name and the shortname of the EMS-ESP device entity. For example what was previously `sensor.boiler_actual_boiler_temperature` will now become `sensor.ems_esp_boiler_boiltemp`. If you still want to use the old format and retain the history and script compatibility in Home Assistant then set this back to the old format.
|
||||||
|
|
||||||
|
## Added
|
||||||
|
|
||||||
|
- Translations in Web UI and all device entity names (DE, NL, SV, PL, NO, FR) [#22](https://github.com/emsesp/EMS-ESP32/issues/22)
|
||||||
|
- Add support for Lolin C3 mini [#620](https://github.com/emsesp/EMS-ESP32/pull/620)
|
||||||
|
- Add support for ESP32-S2 [#667](https://github.com/emsesp/EMS-ESP32/pull/667)
|
||||||
|
- Add devices: Greenstar 30Ri boiler, Junkers FW500 thermostat, Buderus BC30 controller
|
||||||
|
- Add program memory info
|
||||||
|
- Add mqtt queue and connection infos
|
||||||
|
- Adapt min/max if ems-value is not in this range
|
||||||
|
- Add heat pump settings for inputs and limits [#600](https://github.com/emsesp/EMS-ESP32/issues/600)
|
||||||
|
- Add hybrid heatpump [#500](https://github.com/emsesp/EMS-ESP32/issues/500)
|
||||||
|
- Add translated tags
|
||||||
|
- Add min/max to customization table [#686](https://github.com/emsesp/EMS-ESP32/issues/686)
|
||||||
|
- Add MD5 check [#637](https://github.com/emsesp/EMS-ESP32/issues/637)
|
||||||
|
- Add more bus-ids [#673](https://github.com/emsesp/EMS-ESP32/issues/673)
|
||||||
|
- Use HA connectivity device class for Status, added boot time [#751](https://github.com/emsesp/EMS-ESP32/issues/751)
|
||||||
|
- Add commands for analog sensors outputs
|
||||||
|
- Support for multiple EMS-ESPs with MQTT and HA [[#759](https://github.com/emsesp/EMS-ESP32/issues/759)]
|
||||||
|
- Settings for heatpump silent mode and additional heater [[#802](https://github.com/emsesp/EMS-ESP32/issues/802)] [[#803](https://github.com/emsesp/EMS-ESP32/issues/803)]
|
||||||
|
- Zone module MZ100 [#826](https://github.com/emsesp/EMS-ESP32/issues/826)
|
||||||
|
- Default MQTT hostname is blank [#829](https://github.com/emsesp/EMS-ESP32/issues/829)
|
||||||
|
- wwCurFlow for ems+ devices [#829](https://github.com/emsesp/EMS-ESP32/issues/829)
|
||||||
|
- Add Rego 3000, TR120RF thermostats [#917](https://github.com/emsesp/EMS-ESP32/issues/917)
|
||||||
|
- Add config for ESP32-S3
|
||||||
|
- Add heatpump silent mode and other entities [#896](https://github.com/emsesp/EMS-ESP32/issues/896)
|
||||||
|
- Allow reboot to other partition (factory or asymetric OTA)
|
||||||
|
- Blacklist entities to remove from memory [#891](https://github.com/emsesp/EMS-ESP32/issues/891)
|
||||||
|
- Add boiler pump operating mode [#944](https://github.com/emsesp/EMS-ESP32/issues/944)
|
||||||
|
|
||||||
|
## Fixed
|
||||||
|
|
||||||
|
- Factory Reset not working [#628](https://github.com/emsesp/EMS-ESP32/issues/628)
|
||||||
|
- Valid 4 byte values [#820](https://github.com/emsesp/EMS-ESP32/issues/820)
|
||||||
|
- Commands for multiple thermostats [#826](https://github.com/emsesp/EMS-ESP32/issues/826)
|
||||||
|
- API queries for multiple devices [#865](https://github.com/emsesp/EMS-ESP32/issues/865)
|
||||||
|
- Console crash when using call with command `hcx` only. [#841](https://github.com/emsesp/EMS-ESP32/issues/841)
|
||||||
|
- `heatingPump2Mod` was wrong, changed to absBurnPow [[#908](https://github.com/emsesp/EMS-ESP32/issues/908)
|
||||||
|
- Rounding of web input values
|
||||||
|
- Analog sensor with single gpio number [#915](https://github.com/emsesp/EMS-ESP32/issues/915)
|
||||||
|
- HA dallas and analog configs: remove/rebuild on change [#888](https://github.com/emsesp/EMS-ESP32/issues/888)
|
||||||
|
- Modes and set seltemp for RC30 and RC20 [#932](https://github.com/emsesp/EMS-ESP32/issues/932)
|
||||||
|
|
||||||
|
## Changed
|
||||||
|
|
||||||
|
- Discovery in HomeAssistant don't work with custom base topic. [#596](https://github.com/emsesp/EMS-ESP32/issues/596) Base topic containing `/` are changed to `_`
|
||||||
|
- RF room temperature sensor are shown as thermostat
|
||||||
|
- Render mqtt float json values with trailing zero
|
||||||
|
- Removed flash strings, to increase available heap memory
|
||||||
|
- Reload page after restart button is pressed
|
||||||
|
- Analog/dallas values command as list like ems-devices
|
||||||
|
- Analog/dallas HA-entities based on id
|
||||||
|
- MQTT Base is a mandatory field. Removed MQTT topic length from settings
|
||||||
|
- HA duration class for time entities [[#822](https://github.com/emsesp/EMS-ESP32/issues/822)
|
||||||
|
- AM200 alternative heatsource as class heatsource [[#857](https://github.com/emsesp/EMS-ESP32/issues/857)
|
||||||
|
|
||||||
# [3.4.2] September 18 2022
|
# [3.4.2] September 18 2022
|
||||||
|
|
||||||
## Added
|
## Added
|
||||||
|
|||||||
@@ -1,63 +1,20 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
# [3.5.0]
|
# [3.5.1]
|
||||||
|
|
||||||
## **IMPORTANT! BREAKING CHANGES**
|
|
||||||
|
|
||||||
- When upgrading to v3.5 for the first time from v3.4 on a BBQKees Gateway board you will need to use the [EMS-EPS Flasher](https://github.com/emsesp/EMS-ESP-Flasher/releases) to correctly re-partition the flash. Make sure you backup the settings and customizations from the WebUI (System->Upload/Download) and restore after the upgrade.
|
|
||||||
- Support for multiple EMS-ESPs [#759] has been added as an optional setting for MQTT. When enabled, which is now the default, all MQTT Discovery Entity IDs will include the MQTT base name and the shortname of the EMS-ESP device entity. For example what was previously `sensor.boiler_actual_boiler_temperature` will now become `sensor.ems_esp_boiler_boiltemp`. If you still want to use the old format and retain the history and script compatibility in Home Assistant then set this back to the old format.
|
|
||||||
|
|
||||||
## Added
|
## Added
|
||||||
|
|
||||||
- Translations in Web UI and all device entity names (DE, NL, SV, PL, NO, FR) [#22](https://github.com/emsesp/EMS-ESP32/issues/22)
|
- Detect old Tado thermostat, device-id 0x19, no entities
|
||||||
- Add support for Lolin C3 mini [#620](https://github.com/emsesp/EMS-ESP32/pull/620)
|
- Some more HM200 entities [#500](https://github.com/emsesp/EMS-ESP32/issues/500)
|
||||||
- Add support for ESP32-S2 [#667](https://github.com/emsesp/EMS-ESP32/pull/667)
|
- Add entity to force heating off (for systems without thermostat) [#951](https://github.com/emsesp/EMS-ESP32/issues/951)
|
||||||
- Add devices: Greenstar 30Ri boiler, Junkers FW500 thermostat, Buderus BC30 controller
|
|
||||||
- Add program memory info
|
|
||||||
- Add mqtt queue and connection infos
|
|
||||||
- Adapt min/max if ems-value is not in this range
|
|
||||||
- Add heat pump settings for inputs and limits [#600](https://github.com/emsesp/EMS-ESP32/issues/600)
|
|
||||||
- Add hybrid heatpump [#500](https://github.com/emsesp/EMS-ESP32/issues/500)
|
|
||||||
- Add translated tags
|
|
||||||
- Add min/max to customization table [#686](https://github.com/emsesp/EMS-ESP32/issues/686)
|
|
||||||
- Add MD5 check [#637](https://github.com/emsesp/EMS-ESP32/issues/637)
|
|
||||||
- Add more bus-ids [#673](https://github.com/emsesp/EMS-ESP32/issues/673)
|
|
||||||
- Use HA connectivity device class for Status, added boot time [#751](https://github.com/emsesp/EMS-ESP32/issues/751)
|
|
||||||
- Add commands for analog sensors outputs
|
|
||||||
- Support for multiple EMS-ESPs with MQTT and HA [[#759](https://github.com/emsesp/EMS-ESP32/issues/759)]
|
|
||||||
- Settings for heatpump silent mode and additional heater [[#802](https://github.com/emsesp/EMS-ESP32/issues/802)] [[#803](https://github.com/emsesp/EMS-ESP32/issues/803)]
|
|
||||||
- Zone module MZ100 [#826](https://github.com/emsesp/EMS-ESP32/issues/826)
|
|
||||||
- Default MQTT hostname is blank [#829](https://github.com/emsesp/EMS-ESP32/issues/829)
|
|
||||||
- wwCurFlow for ems+ devices [#829](https://github.com/emsesp/EMS-ESP32/issues/829)
|
|
||||||
- Add Rego 3000, TR120RF thermostats [#917](https://github.com/emsesp/EMS-ESP32/issues/917)
|
|
||||||
- Add config for ESP32-S3
|
|
||||||
- Add heatpump silent mode and other entities [#896](https://github.com/emsesp/EMS-ESP32/issues/896)
|
|
||||||
- Allow reboot to other partition (factory or asymetric OTA)
|
|
||||||
- Blacklist entities to remove from memory [#891](https://github.com/emsesp/EMS-ESP32/issues/891)
|
|
||||||
- Add boiler pump operating mode [#944](https://github.com/emsesp/EMS-ESP32/issues/944)
|
|
||||||
|
|
||||||
## Fixed
|
## Fixed
|
||||||
|
|
||||||
- Factory Reset not working [#628](https://github.com/emsesp/EMS-ESP32/issues/628)
|
- HA-discovery for analog sensor commands [#1035](https://github.com/emsesp/EMS-ESP32/issues/1035)
|
||||||
- Valid 4 byte values [#820](https://github.com/emsesp/EMS-ESP32/issues/820)
|
|
||||||
- Commands for multiple thermostats [#826](https://github.com/emsesp/EMS-ESP32/issues/826)
|
|
||||||
- API queries for multiple devices [#865](https://github.com/emsesp/EMS-ESP32/issues/865)
|
|
||||||
- Console crash when using call with command `hcx` only. [#841](https://github.com/emsesp/EMS-ESP32/issues/841)
|
|
||||||
- `heatingPump2Mod` was wrong, changed to absBurnPow [[#908](https://github.com/emsesp/EMS-ESP32/issues/908)
|
|
||||||
- Rounding of web input values
|
|
||||||
- Analog sensor with single gpio number [#915](https://github.com/emsesp/EMS-ESP32/issues/915)
|
|
||||||
- HA dallas and analog configs: remove/rebuild on change [#888](https://github.com/emsesp/EMS-ESP32/issues/888)
|
|
||||||
- Modes and set seltemp for RC30 and RC20 [#932](https://github.com/emsesp/EMS-ESP32/issues/932)
|
|
||||||
|
|
||||||
## Changed
|
## Changed
|
||||||
|
|
||||||
- Discovery in HomeAssistant don't work with custom base topic. [#596](https://github.com/emsesp/EMS-ESP32/issues/596) Base topic containing `/` are changed to `_`
|
- Use byte 0 for detection RC30 active heatingcircuit [#786](https://github.com/emsesp/EMS-ESP32/issues/786)
|
||||||
- RF room temperature sensor are shown as thermostat
|
- Write repeated selflowtemp if tx-queue is empty without verify [#954](https://github.com/emsesp/EMS-ESP32/issues/954)
|
||||||
- Render mqtt float json values with trailing zero
|
- HA discovery recreate after disconnect by device [#1067](https://github.com/emsesp/EMS-ESP32/issues/1067)
|
||||||
- Removed flash strings, to increase available heap memory
|
- File upload: check flash size (overflow) instead of filesize
|
||||||
- Reload page after restart button is pressed
|
|
||||||
- Analog/dallas values command as list like ems-devices
|
|
||||||
- Analog/dallas HA-entities based on id
|
|
||||||
- MQTT Base is a mandatory field. Removed MQTT topic length from settings
|
|
||||||
- HA duration class for time entities [[#822](https://github.com/emsesp/EMS-ESP32/issues/822)
|
|
||||||
- AM200 alternative heatsource as class heatsource [[#857](https://github.com/emsesp/EMS-ESP32/issues/857)
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"adapter": "react",
|
"adapter": "react",
|
||||||
"baseLocale": "pl",
|
"baseLocale": "pl",
|
||||||
"$schema": "https://unpkg.com/typesafe-i18n@5.24.0/schema/typesafe-i18n.json"
|
"$schema": "https://unpkg.com/typesafe-i18n@5.24.1/schema/typesafe-i18n.json"
|
||||||
}
|
}
|
||||||
14210
interface/package-lock.json
generated
14210
interface/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -4,19 +4,19 @@
|
|||||||
"private": true,
|
"private": true,
|
||||||
"proxy": "http://localhost:3080",
|
"proxy": "http://localhost:3080",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.10.5",
|
"@emotion/react": "^11.10.6",
|
||||||
"@emotion/styled": "^11.10.5",
|
"@emotion/styled": "^11.10.6",
|
||||||
"@msgpack/msgpack": "^2.8.0",
|
"@msgpack/msgpack": "^2.8.0",
|
||||||
"@mui/icons-material": "^5.11.0",
|
"@mui/icons-material": "^5.11.9",
|
||||||
"@mui/material": "^5.11.7",
|
"@mui/material": "^5.11.10",
|
||||||
"@table-library/react-table-library": "4.0.24",
|
"@table-library/react-table-library": "4.0.26",
|
||||||
"@types/lodash": "^4.14.191",
|
"@types/lodash": "^4.14.191",
|
||||||
"@types/node": "^18.11.19",
|
"@types/node": "^18.14.0",
|
||||||
"@types/react": "^18.0.27",
|
"@types/react": "^18.0.28",
|
||||||
"@types/react-dom": "^18.0.10",
|
"@types/react-dom": "^18.0.11",
|
||||||
"@types/react-router-dom": "^5.3.3",
|
"@types/react-router-dom": "^5.3.3",
|
||||||
"async-validator": "^4.2.5",
|
"async-validator": "^4.2.5",
|
||||||
"axios": "^1.3.2",
|
"axios": "^1.3.4",
|
||||||
"jwt-decode": "^3.1.2",
|
"jwt-decode": "^3.1.2",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"notistack": "^2.0.8",
|
"notistack": "^2.0.8",
|
||||||
@@ -28,7 +28,7 @@
|
|||||||
"react-router-dom": "^6.8.1",
|
"react-router-dom": "^6.8.1",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"sockette": "^2.0.6",
|
"sockette": "^2.0.6",
|
||||||
"typesafe-i18n": "^5.24.0",
|
"typesafe-i18n": "^5.24.1",
|
||||||
"typescript": "^4.9.5"
|
"typescript": "^4.9.5"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -73,7 +73,6 @@ const SystemLog: FC = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const [errorMessage, setErrorMessage] = useState<string>();
|
const [errorMessage, setErrorMessage] = useState<string>();
|
||||||
const [reconnectTimeout, setReconnectTimeout] = useState<NodeJS.Timeout>();
|
|
||||||
const [logEntries, setLogEntries] = useState<LogEntries>({ events: [] });
|
const [logEntries, setLogEntries] = useState<LogEntries>({ events: [] });
|
||||||
const [lastIndex, setLastIndex] = useState<number>(0);
|
const [lastIndex, setLastIndex] = useState<number>(0);
|
||||||
|
|
||||||
@@ -162,7 +161,7 @@ const SystemLog: FC = () => {
|
|||||||
|
|
||||||
const fetchLog = useCallback(async () => {
|
const fetchLog = useCallback(async () => {
|
||||||
try {
|
try {
|
||||||
setLogEntries((await SystemApi.readLogEntries()).data);
|
await SystemApi.readLogEntries();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setErrorMessage(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
setErrorMessage(extractErrorMessage(error, LL.PROBLEM_LOADING()));
|
||||||
}
|
}
|
||||||
@@ -176,20 +175,14 @@ const SystemLog: FC = () => {
|
|||||||
const es = new EventSource(addAccessTokenParameter(LOG_EVENTSOURCE_URL));
|
const es = new EventSource(addAccessTokenParameter(LOG_EVENTSOURCE_URL));
|
||||||
es.onmessage = onMessage;
|
es.onmessage = onMessage;
|
||||||
es.onerror = () => {
|
es.onerror = () => {
|
||||||
if (reconnectTimeout) {
|
|
||||||
es.close();
|
es.close();
|
||||||
setReconnectTimeout(setTimeout(reloadPage, 1000));
|
reloadPage();
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
es.close();
|
es.close();
|
||||||
if (reconnectTimeout) {
|
|
||||||
clearTimeout(reconnectTimeout);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
}, [reconnectTimeout]);
|
}, []);
|
||||||
|
|
||||||
const content = () => {
|
const content = () => {
|
||||||
if (!data) {
|
if (!data) {
|
||||||
|
|||||||
@@ -127,6 +127,7 @@ const de: Translation = {
|
|||||||
BYPASS_TOKEN: 'Zugriffstoken-Autorisierung bei API-Aufrufen umgehen',
|
BYPASS_TOKEN: 'Zugriffstoken-Autorisierung bei API-Aufrufen umgehen',
|
||||||
READONLY: 'Nur-Lese-Modus aktivieren (blockiert alle ausgehenden EMS Tx Write-Befehle)',
|
READONLY: 'Nur-Lese-Modus aktivieren (blockiert alle ausgehenden EMS Tx Write-Befehle)',
|
||||||
UNDERCLOCK_CPU: 'CPU-Geschwindigkeit untertakten',
|
UNDERCLOCK_CPU: 'CPU-Geschwindigkeit untertakten',
|
||||||
|
HEATINGOFF: 'Boiler Start mit Heizung ausgeschaltet',
|
||||||
ENABLE_SHOWER_TIMER: 'Duschtimer aktivieren',
|
ENABLE_SHOWER_TIMER: 'Duschtimer aktivieren',
|
||||||
ENABLE_SHOWER_ALERT: 'Duschalarm aktivieren',
|
ENABLE_SHOWER_ALERT: 'Duschalarm aktivieren',
|
||||||
TRIGGER_TIME: 'Auslösezeit',
|
TRIGGER_TIME: 'Auslösezeit',
|
||||||
|
|||||||
@@ -127,6 +127,7 @@ const en: Translation = {
|
|||||||
BYPASS_TOKEN: 'Bypass Access Token authorization on API calls',
|
BYPASS_TOKEN: 'Bypass Access Token authorization on API calls',
|
||||||
READONLY: 'Enable read-only mode (blocks all outgoing EMS Tx Write commands)',
|
READONLY: 'Enable read-only mode (blocks all outgoing EMS Tx Write commands)',
|
||||||
UNDERCLOCK_CPU: 'Underclock CPU speed',
|
UNDERCLOCK_CPU: 'Underclock CPU speed',
|
||||||
|
HEATINGOFF: 'Start boiler with forced heating off',
|
||||||
ENABLE_SHOWER_TIMER: 'Enable Shower Timer',
|
ENABLE_SHOWER_TIMER: 'Enable Shower Timer',
|
||||||
ENABLE_SHOWER_ALERT: 'Enable Shower Alert',
|
ENABLE_SHOWER_ALERT: 'Enable Shower Alert',
|
||||||
TRIGGER_TIME: 'Trigger Time',
|
TRIGGER_TIME: 'Trigger Time',
|
||||||
|
|||||||
@@ -127,6 +127,7 @@ const fr: Translation = {
|
|||||||
BYPASS_TOKEN: 'Contourner l\'autorisation du jeton d\'accès sur les appels API',
|
BYPASS_TOKEN: 'Contourner l\'autorisation du jeton d\'accès sur les appels API',
|
||||||
READONLY: 'Activer le mode lecture uniquement (bloque toutes les commandes EMS sortantes en écriture Tx)',
|
READONLY: 'Activer le mode lecture uniquement (bloque toutes les commandes EMS sortantes en écriture Tx)',
|
||||||
UNDERCLOCK_CPU: 'Underclock du CPU',
|
UNDERCLOCK_CPU: 'Underclock du CPU',
|
||||||
|
HEATINGOFF: 'Start boiler with forced heating off',
|
||||||
ENABLE_SHOWER_TIMER: 'Activer la minuterie de la douche',
|
ENABLE_SHOWER_TIMER: 'Activer la minuterie de la douche',
|
||||||
ENABLE_SHOWER_ALERT: 'Activer les alertes de durée de douche',
|
ENABLE_SHOWER_ALERT: 'Activer les alertes de durée de douche',
|
||||||
TRIGGER_TIME: 'Durée avant déclenchement',
|
TRIGGER_TIME: 'Durée avant déclenchement',
|
||||||
|
|||||||
@@ -127,6 +127,7 @@ const nl: Translation = {
|
|||||||
BYPASS_TOKEN: 'API Access Token authenticatie uitschakelen',
|
BYPASS_TOKEN: 'API Access Token authenticatie uitschakelen',
|
||||||
READONLY: 'Activeer read-only modus (blokkeert alle outgaande EMS Tx schrijf commandos)',
|
READONLY: 'Activeer read-only modus (blokkeert alle outgaande EMS Tx schrijf commandos)',
|
||||||
UNDERCLOCK_CPU: 'Underclock CPU snelheid',
|
UNDERCLOCK_CPU: 'Underclock CPU snelheid',
|
||||||
|
HEATINGOFF: 'Start boiler with forced heating off',
|
||||||
ENABLE_SHOWER_TIMER: 'Activeer Douche Timer (tijdmeting)',
|
ENABLE_SHOWER_TIMER: 'Activeer Douche Timer (tijdmeting)',
|
||||||
ENABLE_SHOWER_ALERT: 'Activeer Douchemelding',
|
ENABLE_SHOWER_ALERT: 'Activeer Douchemelding',
|
||||||
TRIGGER_TIME: 'Trigger tijd',
|
TRIGGER_TIME: 'Trigger tijd',
|
||||||
|
|||||||
@@ -127,6 +127,7 @@ const no: Translation = {
|
|||||||
BYPASS_TOKEN: 'Utelat Aksess Token authorisering av API kall',
|
BYPASS_TOKEN: 'Utelat Aksess Token authorisering av API kall',
|
||||||
READONLY: 'Aktiver read-only modus (blokker all EMS Tx Skriving)',
|
READONLY: 'Aktiver read-only modus (blokker all EMS Tx Skriving)',
|
||||||
UNDERCLOCK_CPU: 'Underklokking av prosessorhastighet',
|
UNDERCLOCK_CPU: 'Underklokking av prosessorhastighet',
|
||||||
|
HEATINGOFF: 'Start boiler with forced heating off',
|
||||||
ENABLE_SHOWER_TIMER: 'Aktiver Dusjtimer',
|
ENABLE_SHOWER_TIMER: 'Aktiver Dusjtimer',
|
||||||
ENABLE_SHOWER_ALERT: 'Aktiver Dusj-varsling',
|
ENABLE_SHOWER_ALERT: 'Aktiver Dusj-varsling',
|
||||||
TRIGGER_TIME: 'Aktiveringstid',
|
TRIGGER_TIME: 'Aktiveringstid',
|
||||||
|
|||||||
@@ -127,6 +127,7 @@ const pl: BaseTranslation = {
|
|||||||
BYPASS_TOKEN: 'Pomiń autoryzację tokenem w wywołaniach API',
|
BYPASS_TOKEN: 'Pomiń autoryzację tokenem w wywołaniach API',
|
||||||
READONLY: 'Tryb pracy "tylko do odczytu" (blokuje wszystkie komendy zapisu na magistralę EMS)',
|
READONLY: 'Tryb pracy "tylko do odczytu" (blokuje wszystkie komendy zapisu na magistralę EMS)',
|
||||||
UNDERCLOCK_CPU: 'Obniż taktowanie CPU',
|
UNDERCLOCK_CPU: 'Obniż taktowanie CPU',
|
||||||
|
HEATINGOFF: 'Start boiler with forced heating off',
|
||||||
ENABLE_SHOWER_TIMER: 'Aktywuj minutnik prysznica',
|
ENABLE_SHOWER_TIMER: 'Aktywuj minutnik prysznica',
|
||||||
ENABLE_SHOWER_ALERT: 'Aktywuj alarm prysznica',
|
ENABLE_SHOWER_ALERT: 'Aktywuj alarm prysznica',
|
||||||
TRIGGER_TIME: 'Wyzwalaj po czasie',
|
TRIGGER_TIME: 'Wyzwalaj po czasie',
|
||||||
@@ -157,7 +158,7 @@ const pl: BaseTranslation = {
|
|||||||
CUSTOMIZATIONS_HELP_3: 'zablokuj akcje zapisu',
|
CUSTOMIZATIONS_HELP_3: 'zablokuj akcje zapisu',
|
||||||
CUSTOMIZATIONS_HELP_4: 'wyklucz z MQTT i API',
|
CUSTOMIZATIONS_HELP_4: 'wyklucz z MQTT i API',
|
||||||
CUSTOMIZATIONS_HELP_5: 'ukryj na pulpicie',
|
CUSTOMIZATIONS_HELP_5: 'ukryj na pulpicie',
|
||||||
CUSTOMIZATIONS_HELP_6: 'remove from memory',
|
CUSTOMIZATIONS_HELP_6: 'usuń z pamięci',
|
||||||
SELECT_DEVICE: 'wybierz urządzenie',
|
SELECT_DEVICE: 'wybierz urządzenie',
|
||||||
SET_ALL: 'Ustaw wszystko jako',
|
SET_ALL: 'Ustaw wszystko jako',
|
||||||
OPTIONS: 'Opcje',
|
OPTIONS: 'Opcje',
|
||||||
@@ -202,7 +203,7 @@ const pl: BaseTranslation = {
|
|||||||
CPU_FREQ: 'Taktowanie CPU',
|
CPU_FREQ: 'Taktowanie CPU',
|
||||||
HEAP: 'HEAP (wolne / maksymalny przydział)',
|
HEAP: 'HEAP (wolne / maksymalny przydział)',
|
||||||
PSRAM: 'PSRAM (rozmiar / wolne)',
|
PSRAM: 'PSRAM (rozmiar / wolne)',
|
||||||
FLASH: 'Flash (rozmiar / taktowanie)',
|
FLASH: 'FLASH (rozmiar / taktowanie)',
|
||||||
APPSIZE: 'Aplikacja (wykorzystane / wolne)',
|
APPSIZE: 'Aplikacja (wykorzystane / wolne)',
|
||||||
FILESYSTEM: 'System plików (wykorzystane / wolne)',
|
FILESYSTEM: 'System plików (wykorzystane / wolne)',
|
||||||
BUFFER_SIZE: 'Maksymalna pojemność bufora (ilość wpisów)',
|
BUFFER_SIZE: 'Maksymalna pojemność bufora (ilość wpisów)',
|
||||||
|
|||||||
@@ -127,6 +127,7 @@ const sv: Translation = {
|
|||||||
BYPASS_TOKEN: 'Inaktivera Token-autensiering för API-anrop',
|
BYPASS_TOKEN: 'Inaktivera Token-autensiering för API-anrop',
|
||||||
READONLY: 'Aktivera read-only (blockerar alla utgående skrivkommandon mot EMS-bussen)',
|
READONLY: 'Aktivera read-only (blockerar alla utgående skrivkommandon mot EMS-bussen)',
|
||||||
UNDERCLOCK_CPU: 'Nedklocka Processorhastighet',
|
UNDERCLOCK_CPU: 'Nedklocka Processorhastighet',
|
||||||
|
HEATINGOFF: 'Start boiler with forced heating off',
|
||||||
ENABLE_SHOWER_TIMER: 'Aktivera Dusch-timer',
|
ENABLE_SHOWER_TIMER: 'Aktivera Dusch-timer',
|
||||||
ENABLE_SHOWER_ALERT: 'Aktivera Dusch-varning',
|
ENABLE_SHOWER_ALERT: 'Aktivera Dusch-varning',
|
||||||
TRIGGER_TIME: 'Aktiveringstid',
|
TRIGGER_TIME: 'Aktiveringstid',
|
||||||
|
|||||||
@@ -650,7 +650,7 @@ const DashboardData: FC = () => {
|
|||||||
<DialogContent dividers>
|
<DialogContent dividers>
|
||||||
<List dense={true}>
|
<List dense={true}>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<ListItemText primary={LL.TYPE()} secondary={coreData.devices[deviceDialog].t} />
|
<ListItemText primary={LL.TYPE()} secondary={coreData.devices[deviceDialog].tn} />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem>
|
<ListItem>
|
||||||
<ListItemText primary={LL.NAME(0)} secondary={coreData.devices[deviceDialog].n} />
|
<ListItemText primary={LL.NAME(0)} secondary={coreData.devices[deviceDialog].n} />
|
||||||
|
|||||||
@@ -408,6 +408,11 @@ const SettingsApplication: FC = () => {
|
|||||||
label={LL.UNDERCLOCK_CPU()}
|
label={LL.UNDERCLOCK_CPU()}
|
||||||
disabled={saving}
|
disabled={saving}
|
||||||
/>
|
/>
|
||||||
|
<BlockFormControlLabel
|
||||||
|
control={<Checkbox checked={data.boiler_heatingoff} onChange={updateFormValue} name="boiler_heatingoff" />}
|
||||||
|
label={LL.HEATINGOFF()}
|
||||||
|
disabled={saving}
|
||||||
|
/>
|
||||||
<Grid container spacing={0} direction="row" justifyContent="flex-start" alignItems="flex-start">
|
<Grid container spacing={0} direction="row" justifyContent="flex-start" alignItems="flex-start">
|
||||||
<BlockFormControlLabel
|
<BlockFormControlLabel
|
||||||
control={<Checkbox checked={data.shower_timer} onChange={updateFormValue} name="shower_timer" />}
|
control={<Checkbox checked={data.shower_timer} onChange={updateFormValue} name="shower_timer" />}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ export interface Settings {
|
|||||||
syslog_mark_interval: number;
|
syslog_mark_interval: number;
|
||||||
syslog_host: string;
|
syslog_host: string;
|
||||||
syslog_port: number;
|
syslog_port: number;
|
||||||
|
boiler_heatingoff: boolean;
|
||||||
shower_timer: boolean;
|
shower_timer: boolean;
|
||||||
shower_alert: boolean;
|
shower_alert: boolean;
|
||||||
shower_alert_coldshot: number;
|
shower_alert_coldshot: number;
|
||||||
|
|||||||
@@ -71,13 +71,13 @@ void UploadFileService::handleUpload(AsyncWebServerRequest * request, const Stri
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||||
if (len > 12 && (data[0] != 0xE9 || data[12] != 3)) {
|
if (len > 12 && (data[0] != 0xE9 || data[12] != 9)) {
|
||||||
handleError(request, 503); // service unavailable
|
handleError(request, 503); // service unavailable
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// it's firmware - initialize the ArduinoOTA updater
|
// it's firmware - initialize the ArduinoOTA updater
|
||||||
if (Update.begin(fsize)) {
|
if (Update.begin()) {
|
||||||
if (strlen(md5) == 32) {
|
if (strlen(md5) == 32) {
|
||||||
Update.setMD5(md5);
|
Update.setMD5(md5);
|
||||||
md5[0] = '\0';
|
md5[0] = '\0';
|
||||||
|
|||||||
8
mock-api/package-lock.json
generated
8
mock-api/package-lock.json
generated
@@ -14,7 +14,7 @@
|
|||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
"express-sse": "^0.5.3",
|
"express-sse": "^0.5.3",
|
||||||
"nodemon": "^2.0.20",
|
"nodemon": "^2.0.20",
|
||||||
"ws": "^8.12.0"
|
"ws": "^8.12.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@msgpack/msgpack": {
|
"node_modules/@msgpack/msgpack": {
|
||||||
@@ -1015,9 +1015,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ws": {
|
"node_modules/ws": {
|
||||||
"version": "8.12.0",
|
"version": "8.12.1",
|
||||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.12.0.tgz",
|
"resolved": "https://registry.npmjs.org/ws/-/ws-8.12.1.tgz",
|
||||||
"integrity": "sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==",
|
"integrity": "sha512-1qo+M9Ba+xNhPB+YTWUlK6M17brTut5EXbcBaMRN5pH5dFrXz7lzz1ChFSUq3bOUl8yEvSenhHmYUNJxFzdJew==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=10.0.0"
|
"node": ">=10.0.0"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -16,6 +16,6 @@
|
|||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
"express-sse": "^0.5.3",
|
"express-sse": "^0.5.3",
|
||||||
"nodemon": "^2.0.20",
|
"nodemon": "^2.0.20",
|
||||||
"ws": "^8.12.0"
|
"ws": "^8.12.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ void AnalogSensor::reload() {
|
|||||||
analog_enabled_ = true; // for local offline testing
|
analog_enabled_ = true; // for local offline testing
|
||||||
#endif
|
#endif
|
||||||
for (auto sensor : sensors_) {
|
for (auto sensor : sensors_) {
|
||||||
remove_ha_topic(sensor.gpio());
|
remove_ha_topic(sensor.type(), sensor.gpio());
|
||||||
sensor.ha_registered = false;
|
sensor.ha_registered = false;
|
||||||
}
|
}
|
||||||
if (!analog_enabled_) {
|
if (!analog_enabled_) {
|
||||||
@@ -333,7 +333,7 @@ bool AnalogSensor::update(uint8_t gpio, const std::string & name, double offset,
|
|||||||
|
|
||||||
// if the sensor exists and we're using HA, delete the old HA record
|
// if the sensor exists and we're using HA, delete the old HA record
|
||||||
if (found_sensor && Mqtt::ha_enabled()) {
|
if (found_sensor && Mqtt::ha_enabled()) {
|
||||||
remove_ha_topic(gpio); // the GPIO
|
remove_ha_topic(type, gpio); // the GPIO
|
||||||
}
|
}
|
||||||
|
|
||||||
// we didn't find it, it's new, so create and store it
|
// we didn't find it, it's new, so create and store it
|
||||||
@@ -384,7 +384,7 @@ void AnalogSensor::publish_sensor(const Sensor & sensor) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// send empty config topic to remove the entry from HA
|
// send empty config topic to remove the entry from HA
|
||||||
void AnalogSensor::remove_ha_topic(const uint8_t gpio) const {
|
void AnalogSensor::remove_ha_topic(const int8_t type, const uint8_t gpio) const {
|
||||||
if (!Mqtt::ha_enabled()) {
|
if (!Mqtt::ha_enabled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -392,7 +392,21 @@ void AnalogSensor::remove_ha_topic(const uint8_t gpio) const {
|
|||||||
LOG_DEBUG("Removing HA config for analog sensor GPIO %02d", gpio);
|
LOG_DEBUG("Removing HA config for analog sensor GPIO %02d", gpio);
|
||||||
#endif
|
#endif
|
||||||
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
if (type == AnalogType::DIGITAL_OUT && gpio != 25 && gpio != 26) {
|
||||||
|
#else
|
||||||
|
if (type == AnalogType::DIGITAL_OUT)
|
||||||
|
#endif
|
||||||
|
snprintf(topic, sizeof(topic), "switch/%s/analogsensor_%02d/config", Mqtt::basename().c_str(), gpio);
|
||||||
|
} else if (type == AnalogType::DIGITAL_OUT) { // DAC
|
||||||
|
snprintf(topic, sizeof(topic), "number/%s/analogsensor_%02d/config", Mqtt::basename().c_str(), gpio);
|
||||||
|
} else if (type >= AnalogType::PWM_0) {
|
||||||
|
snprintf(topic, sizeof(topic), "number/%s/analogsensor_%02d/config", Mqtt::basename().c_str(), gpio);
|
||||||
|
} else if (type == AnalogType::DIGITAL_IN) {
|
||||||
|
snprintf(topic, sizeof(topic), "binary_sensor/%s/analogsensor_%02d/config", Mqtt::basename().c_str(), gpio);
|
||||||
|
} else {
|
||||||
snprintf(topic, sizeof(topic), "sensor/%s/analogsensor_%02d/config", Mqtt::basename().c_str(), gpio);
|
snprintf(topic, sizeof(topic), "sensor/%s/analogsensor_%02d/config", Mqtt::basename().c_str(), gpio);
|
||||||
|
}
|
||||||
Mqtt::publish_ha(topic);
|
Mqtt::publish_ha(topic);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -447,13 +461,16 @@ void AnalogSensor::publish_values(const bool force) {
|
|||||||
snprintf(stat_t, sizeof(stat_t), "%s/analogsensor_data", Mqtt::base().c_str()); // use base path
|
snprintf(stat_t, sizeof(stat_t), "%s/analogsensor_data", Mqtt::base().c_str()); // use base path
|
||||||
config["stat_t"] = stat_t;
|
config["stat_t"] = stat_t;
|
||||||
|
|
||||||
char str[50];
|
char val_obj[50];
|
||||||
|
char val_cond[65];
|
||||||
if (Mqtt::is_nested()) {
|
if (Mqtt::is_nested()) {
|
||||||
snprintf(str, sizeof(str), "{{value_json['%02d'].value}}", sensor.gpio());
|
snprintf(val_obj, sizeof(val_obj), "value_json['%02d'].value", sensor.gpio());
|
||||||
|
snprintf(val_cond, sizeof(val_cond), "value_json['%02d'] is defined", sensor.gpio());
|
||||||
} else {
|
} else {
|
||||||
snprintf(str, sizeof(str), "{{value_json['%s']}", sensor.name().c_str());
|
snprintf(val_obj, sizeof(val_obj), "value_json['%s']", sensor.name().c_str());
|
||||||
|
snprintf(val_cond, sizeof(val_cond), "%s is defined", val_obj);
|
||||||
}
|
}
|
||||||
config["val_tpl"] = str;
|
config["val_tpl"] = (std::string) "{{" + val_obj + " if " + val_cond + "}}";
|
||||||
|
|
||||||
char uniq_s[70];
|
char uniq_s[70];
|
||||||
if (Mqtt::entity_format() == 2) {
|
if (Mqtt::entity_format() == 2) {
|
||||||
@@ -462,22 +479,76 @@ void AnalogSensor::publish_values(const bool force) {
|
|||||||
snprintf(uniq_s, sizeof(uniq_s), "analogsensor_%02d", sensor.gpio());
|
snprintf(uniq_s, sizeof(uniq_s), "analogsensor_%02d", sensor.gpio());
|
||||||
}
|
}
|
||||||
|
|
||||||
config["object_id"] = uniq_s;
|
config["obj_id"] = uniq_s;
|
||||||
config["uniq_id"] = uniq_s; // same as object_id
|
config["uniq_id"] = uniq_s; // same as object_id
|
||||||
|
|
||||||
snprintf(str, sizeof(str), "%s", sensor.name().c_str());
|
char name[50];
|
||||||
config["name"] = str;
|
snprintf(name, sizeof(name), "%s", sensor.name().c_str());
|
||||||
|
config["name"] = name;
|
||||||
|
|
||||||
if (sensor.uom() != DeviceValueUOM::NONE) {
|
if (sensor.uom() != DeviceValueUOM::NONE) {
|
||||||
config["unit_of_meas"] = EMSdevice::uom_to_string(sensor.uom());
|
config["unit_of_meas"] = EMSdevice::uom_to_string(sensor.uom());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
||||||
|
|
||||||
|
// Set commands for some analog types
|
||||||
|
char command_topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
|
if (sensor.type() == AnalogType::DIGITAL_OUT && sensor.gpio() != 25 && sensor.gpio() != 26) {
|
||||||
|
#else
|
||||||
|
if (sensor.type() == AnalogType::DIGITAL_OUT)
|
||||||
|
#endif
|
||||||
|
snprintf(topic, sizeof(topic), "switch/%s/analogsensor_%02d/config", Mqtt::basename().c_str(), sensor.gpio());
|
||||||
|
snprintf(command_topic, sizeof(command_topic), "%s/analogsensor/%s", Mqtt::basename().c_str(), sensor.name().c_str());
|
||||||
|
config["cmd_t"] = command_topic;
|
||||||
|
if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) {
|
||||||
|
config["pl_on"] = true;
|
||||||
|
config["pl_off"] = false;
|
||||||
|
} else if (EMSESP::system_.bool_format() == BOOL_FORMAT_10) {
|
||||||
|
config["pl_on"] = 1;
|
||||||
|
config["pl_off"] = 0;
|
||||||
|
} else {
|
||||||
|
char result[12];
|
||||||
|
config["pl_on"] = Helpers::render_boolean(result, true);
|
||||||
|
config["pl_off"] = Helpers::render_boolean(result, false);
|
||||||
|
}
|
||||||
|
} else if (sensor.type() == AnalogType::DIGITAL_OUT) { // DAC
|
||||||
|
snprintf(topic, sizeof(topic), "number/%s/analogsensor_%02d/config", Mqtt::basename().c_str(), sensor.gpio());
|
||||||
|
snprintf(command_topic, sizeof(command_topic), "%s/analogsensor/%s", Mqtt::basename().c_str(), sensor.name().c_str());
|
||||||
|
config["cmd_t"] = command_topic;
|
||||||
|
config["min"] = 0;
|
||||||
|
config["max"] = 255;
|
||||||
|
config["mode"] = "box"; // auto, slider or box
|
||||||
|
config["step"] = 1;
|
||||||
|
} else if (sensor.type() >= AnalogType::PWM_0) {
|
||||||
|
snprintf(topic, sizeof(topic), "number/%s/analogsensor_%02d/config", Mqtt::basename().c_str(), sensor.gpio());
|
||||||
|
snprintf(command_topic, sizeof(command_topic), "%s/analogsensor/%s", Mqtt::basename().c_str(), sensor.name().c_str());
|
||||||
|
config["cmd_t"] = command_topic;
|
||||||
|
config["min"] = 0;
|
||||||
|
config["max"] = 100;
|
||||||
|
config["mode"] = "box"; // auto, slider or box
|
||||||
|
config["step"] = 0.1;
|
||||||
|
} else if (sensor.type() == AnalogType::COUNTER) {
|
||||||
|
snprintf(topic, sizeof(topic), "sensor/%s/analogsensor_%02d/config", Mqtt::basename().c_str(), sensor.gpio());
|
||||||
|
snprintf(command_topic, sizeof(command_topic), "%s/analogsensor/%s", Mqtt::basename().c_str(), sensor.name().c_str());
|
||||||
|
config["cmd_t"] = command_topic;
|
||||||
|
config["stat_cla"] = "total_increasing";
|
||||||
|
// config["mode"] = "box"; // auto, slider or box
|
||||||
|
// config["step"] = sensor.factor();
|
||||||
|
} else if (sensor.type() == AnalogType::DIGITAL_IN) {
|
||||||
|
snprintf(topic, sizeof(topic), "binary_sensor/%s/analogsensor_%02d/config", Mqtt::basename().c_str(), sensor.gpio());
|
||||||
|
} else {
|
||||||
|
snprintf(topic, sizeof(topic), "sensor/%s/analogsensor_%02d/config", Mqtt::basename().c_str(), sensor.gpio());
|
||||||
|
config["stat_cla"] = "measurement";
|
||||||
|
}
|
||||||
|
|
||||||
JsonObject dev = config.createNestedObject("dev");
|
JsonObject dev = config.createNestedObject("dev");
|
||||||
JsonArray ids = dev.createNestedArray("ids");
|
JsonArray ids = dev.createNestedArray("ids");
|
||||||
ids.add("ems-esp");
|
ids.add("ems-esp");
|
||||||
|
|
||||||
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
// add "availability" section
|
||||||
snprintf(topic, sizeof(topic), "sensor/%s/analogsensor_%02d/config", Mqtt::basename().c_str(), sensor.gpio());
|
Mqtt::add_avty_to_doc(stat_t, config.as<JsonObject>(), val_cond);
|
||||||
|
|
||||||
Mqtt::publish_ha(topic, config.as<JsonObject>());
|
Mqtt::publish_ha(topic, config.as<JsonObject>());
|
||||||
|
|
||||||
|
|||||||
@@ -170,7 +170,7 @@ class AnalogSensor {
|
|||||||
|
|
||||||
static uuid::log::Logger logger_;
|
static uuid::log::Logger logger_;
|
||||||
|
|
||||||
void remove_ha_topic(const uint8_t id) const;
|
void remove_ha_topic(const int8_t type, const uint8_t id) const;
|
||||||
bool command_setvalue(const char * value, const int8_t gpio);
|
bool command_setvalue(const char * value, const int8_t gpio);
|
||||||
void measure();
|
void measure();
|
||||||
bool command_info(const char * value, const int8_t id, JsonObject & output) const;
|
bool command_info(const char * value, const int8_t id, JsonObject & output) const;
|
||||||
|
|||||||
@@ -514,13 +514,16 @@ void DallasSensor::publish_values(const bool force) {
|
|||||||
|
|
||||||
config["unit_of_meas"] = EMSdevice::uom_to_string(DeviceValueUOM::DEGREES);
|
config["unit_of_meas"] = EMSdevice::uom_to_string(DeviceValueUOM::DEGREES);
|
||||||
|
|
||||||
char str[50];
|
char val_obj[50];
|
||||||
|
char val_cond[65];
|
||||||
if (Mqtt::is_nested()) {
|
if (Mqtt::is_nested()) {
|
||||||
snprintf(str, sizeof(str), "{{value_json['%s'].temp}}", sensor.id().c_str());
|
snprintf(val_obj, sizeof(val_obj), "value_json['%s'].temp", sensor.id().c_str());
|
||||||
|
snprintf(val_cond, sizeof(val_cond), "value_json['%s'] is defined", sensor.id().c_str());
|
||||||
} else {
|
} else {
|
||||||
snprintf(str, sizeof(str), "{{value_json['%s']}}", sensor.name().c_str());
|
snprintf(val_obj, sizeof(val_obj), "value_json['%s']", sensor.name().c_str());
|
||||||
|
snprintf(val_cond, sizeof(val_cond), "%s is defined", val_obj);
|
||||||
}
|
}
|
||||||
config["val_tpl"] = str;
|
config["val_tpl"] = (std::string) "{{" + val_obj + " if " + val_cond + "}}";
|
||||||
|
|
||||||
char uniq_s[70];
|
char uniq_s[70];
|
||||||
if (Mqtt::entity_format() == 2) {
|
if (Mqtt::entity_format() == 2) {
|
||||||
@@ -529,16 +532,20 @@ void DallasSensor::publish_values(const bool force) {
|
|||||||
snprintf(uniq_s, sizeof(uniq_s), "dallassensor_%s", sensor.id().c_str());
|
snprintf(uniq_s, sizeof(uniq_s), "dallassensor_%s", sensor.id().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
config["object_id"] = uniq_s;
|
config["obj_id"] = uniq_s;
|
||||||
config["uniq_id"] = uniq_s; // same as object_id
|
config["uniq_id"] = uniq_s; // same as object_id
|
||||||
|
|
||||||
snprintf(str, sizeof(str), "%s", sensor.name().c_str());
|
char name[50];
|
||||||
config["name"] = str;
|
snprintf(name, sizeof(name), "%s", sensor.name().c_str());
|
||||||
|
config["name"] = name;
|
||||||
|
|
||||||
JsonObject dev = config.createNestedObject("dev");
|
JsonObject dev = config.createNestedObject("dev");
|
||||||
JsonArray ids = dev.createNestedArray("ids");
|
JsonArray ids = dev.createNestedArray("ids");
|
||||||
ids.add("ems-esp");
|
ids.add("ems-esp");
|
||||||
|
|
||||||
|
// add "availability" section
|
||||||
|
Mqtt::add_avty_to_doc(stat_t, config.as<JsonObject>(), val_cond);
|
||||||
|
|
||||||
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
||||||
// use '_' as HA doesn't like '-' in the topic name
|
// use '_' as HA doesn't like '-' in the topic name
|
||||||
std::string sensorid = sensor.id();
|
std::string sensorid = sensor.id();
|
||||||
|
|||||||
@@ -61,6 +61,10 @@
|
|||||||
#define EMSESP_DEFAULT_TRACELOG_RAW false
|
#define EMSESP_DEFAULT_TRACELOG_RAW false
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef EMSESP_DEFAULT_BOILER_HEATINGOFF
|
||||||
|
#define EMSESP_DEFAULT_BOILER_HEATINGOFF false
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef EMSESP_DEFAULT_SHOWER_TIMER
|
#ifndef EMSESP_DEFAULT_SHOWER_TIMER
|
||||||
#define EMSESP_DEFAULT_SHOWER_TIMER false
|
#define EMSESP_DEFAULT_SHOWER_TIMER false
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -48,6 +48,7 @@
|
|||||||
{208, DeviceType::BOILER, "Logamax Plus/GB192/Condens GC9000/Greenstar ErP", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{208, DeviceType::BOILER, "Logamax Plus/GB192/Condens GC9000/Greenstar ErP", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{210, DeviceType::BOILER, "Cascade MC400", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{210, DeviceType::BOILER, "Cascade MC400", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{211, DeviceType::BOILER, "EasyControl Adapter", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{211, DeviceType::BOILER, "EasyControl Adapter", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
|
{219, DeviceType::BOILER, "Greenstar HIU", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
{234, DeviceType::BOILER, "Logamax Plus GB122/Condense 2300", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
{234, DeviceType::BOILER, "Logamax Plus GB122/Condense 2300", DeviceFlags::EMS_DEVICE_FLAG_NONE},
|
||||||
|
|
||||||
// Controllers - 0x09 / 0x10 / 0x50
|
// Controllers - 0x09 / 0x10 / 0x50
|
||||||
|
|||||||
@@ -100,7 +100,12 @@ Boiler::Boiler(uint8_t device_type, int8_t device_id, uint8_t product_id, const
|
|||||||
// reset is a command uses a dummy variable which is always zero, shown as blank, but provides command enum options
|
// reset is a command uses a dummy variable which is always zero, shown as blank, but provides command enum options
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &reset_, DeviceValueType::CMD, FL_(enum_reset), FL_(reset), DeviceValueUOM::NONE, MAKE_CF_CB(set_reset));
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &reset_, DeviceValueType::CMD, FL_(enum_reset), FL_(reset), DeviceValueUOM::NONE, MAKE_CF_CB(set_reset));
|
||||||
has_update(reset_, 0);
|
has_update(reset_, 0);
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
|
&forceHeatingOff_,
|
||||||
|
DeviceValueType::BOOL,
|
||||||
|
FL_(forceHeatingOff),
|
||||||
|
DeviceValueUOM::NONE,
|
||||||
|
MAKE_CF_CB(set_forceHeatingOff));
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &heatingActive_, DeviceValueType::BOOL, FL_(heatingActive), DeviceValueUOM::NONE);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &heatingActive_, DeviceValueType::BOOL, FL_(heatingActive), DeviceValueUOM::NONE);
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &tapwaterActive_, DeviceValueType::BOOL, FL_(tapwaterActive), DeviceValueUOM::NONE);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &tapwaterActive_, DeviceValueType::BOOL, FL_(tapwaterActive), DeviceValueUOM::NONE);
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &selFlowTemp_, DeviceValueType::UINT, FL_(selFlowTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_flow_temp));
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &selFlowTemp_, DeviceValueType::UINT, FL_(selFlowTemp), DeviceValueUOM::DEGREES, MAKE_CF_CB(set_flow_temp));
|
||||||
@@ -875,6 +880,11 @@ void Boiler::check_active(const bool force) {
|
|||||||
Mqtt::publish(F_(tapwater_active), Helpers::render_boolean(s, b));
|
Mqtt::publish(F_(tapwater_active), Helpers::render_boolean(s, b));
|
||||||
EMSESP::tap_water_active(b); // let EMS-ESP know, used in the Shower class
|
EMSESP::tap_water_active(b); // let EMS-ESP know, used in the Shower class
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Helpers::hasValue(forceHeatingOff_, EMS_VALUE_BOOL)) {
|
||||||
|
EMSESP::webSettingsService.read([&](WebSettings & settings) { forceHeatingOff_ = (settings.boiler_heatingoff || selFlowTemp_ == 0) ? 1 : 0; });
|
||||||
|
has_update(&forceHeatingOff_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x18
|
// 0x18
|
||||||
@@ -1075,6 +1085,11 @@ void Boiler::process_UBAMonitorSlow(std::shared_ptr<const Telegram> telegram) {
|
|||||||
has_update(telegram, burn2WorkMin_, 16, 3); // force to 3 bytes
|
has_update(telegram, burn2WorkMin_, 16, 3); // force to 3 bytes
|
||||||
has_update(telegram, heatWorkMin_, 19, 3); // force to 3 bytes
|
has_update(telegram, heatWorkMin_, 19, 3); // force to 3 bytes
|
||||||
has_update(telegram, heatStarts_, 22, 3); // force to 3 bytes
|
has_update(telegram, heatStarts_, 22, 3); // force to 3 bytes
|
||||||
|
|
||||||
|
if (forceHeatingOff_ == EMS_VALUE_BOOL_ON && telegram->dest == 0) {
|
||||||
|
uint8_t data[] = {0, 0, 0, 0};
|
||||||
|
write_command(EMS_TYPE_UBASetPoints, 0, data, sizeof(data), 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1105,6 +1120,11 @@ void Boiler::process_UBAMonitorSlowPlus(std::shared_ptr<const Telegram> telegram
|
|||||||
has_update(telegram, heatStarts_, 22, 3); // force to 3 bytes
|
has_update(telegram, heatStarts_, 22, 3); // force to 3 bytes
|
||||||
has_update(telegram, heatingPumpMod_, 25);
|
has_update(telegram, heatingPumpMod_, 25);
|
||||||
// temperature measurements at 4, see #620
|
// temperature measurements at 4, see #620
|
||||||
|
|
||||||
|
if (forceHeatingOff_ == EMS_VALUE_BOOL_ON && telegram->dest == 0) {
|
||||||
|
uint8_t data[] = {0, 0, 0, 0};
|
||||||
|
write_command(EMS_TYPE_UBASetPoints, 0, data, sizeof(data), 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1711,7 +1731,9 @@ bool Boiler::set_flow_temp(const char * value, const int8_t id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// no write/verify if there is no change, see https://github.com/emsesp/EMS-ESP32/issues/654
|
// no write/verify if there is no change, see https://github.com/emsesp/EMS-ESP32/issues/654
|
||||||
|
// put it to end of tx-queue
|
||||||
if (v == selFlowTemp_) {
|
if (v == selFlowTemp_) {
|
||||||
|
EMSESP::txservice_.add(Telegram::Operation::TX_WRITE, device_id(), EMS_TYPE_UBASetPoints, 0, (uint8_t *) &v, 1, 0, false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2574,4 +2596,17 @@ bool Boiler::set_wwAltOpPrio(const char * value, const int8_t id) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Boiler::set_forceHeatingOff(const char * value, const int8_t id) {
|
||||||
|
bool v;
|
||||||
|
if (Helpers::value2bool(value, v)) {
|
||||||
|
has_update(forceHeatingOff_, v);
|
||||||
|
if (!v && Helpers::hasValue(heatingTemp_)) {
|
||||||
|
uint8_t data[] = {heatingTemp_, (Helpers::hasValue(burnMaxPower_) ? burnMaxPower_ : (uint8_t)100), (Helpers::hasValue(pumpModMax_) ? pumpModMax_ : (uint8_t)0), 0};
|
||||||
|
write_command(EMS_TYPE_UBASetPoints, 0, data, sizeof(data), 0);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace emsesp
|
} // namespace emsesp
|
||||||
|
|||||||
@@ -87,7 +87,6 @@ class Boiler : public EMSdevice {
|
|||||||
uint32_t wwWorkM_; // DHW minutes
|
uint32_t wwWorkM_; // DHW minutes
|
||||||
int8_t wwHystOn_;
|
int8_t wwHystOn_;
|
||||||
int8_t wwHystOff_;
|
int8_t wwHystOff_;
|
||||||
uint8_t wwTapActivated_; // maintenance-mode to switch DHW off
|
|
||||||
uint16_t wwMixerTemp_; // mixing temperature
|
uint16_t wwMixerTemp_; // mixing temperature
|
||||||
uint16_t wwCylMiddleTemp_; // Cyl middle temperature (TS3)
|
uint16_t wwCylMiddleTemp_; // Cyl middle temperature (TS3)
|
||||||
uint16_t wwSolarTemp_;
|
uint16_t wwSolarTemp_;
|
||||||
@@ -95,6 +94,11 @@ class Boiler : public EMSdevice {
|
|||||||
uint8_t wwAltOpPrioHeat_; // alternating operation, prioritise heat time
|
uint8_t wwAltOpPrioHeat_; // alternating operation, prioritise heat time
|
||||||
uint8_t wwAltOpPrioWw_; // alternating operation, prioritise dhw time
|
uint8_t wwAltOpPrioWw_; // alternating operation, prioritise dhw time
|
||||||
|
|
||||||
|
// special function
|
||||||
|
uint8_t forceHeatingOff_;
|
||||||
|
uint8_t wwTapActivated_; // maintenance-mode to switch DHW off
|
||||||
|
|
||||||
|
|
||||||
// main
|
// main
|
||||||
uint8_t reset_; // for reset command
|
uint8_t reset_; // for reset command
|
||||||
uint8_t heatingActive_; // Central heating is on/off
|
uint8_t heatingActive_; // Central heating is on/off
|
||||||
@@ -447,6 +451,8 @@ class Boiler : public EMSdevice {
|
|||||||
inline bool set_wwAltOpPrioWw(const char * value, const int8_t id) {
|
inline bool set_wwAltOpPrioWw(const char * value, const int8_t id) {
|
||||||
return set_wwAltOpPrio(value, 3);
|
return set_wwAltOpPrio(value, 3);
|
||||||
}
|
}
|
||||||
|
bool set_forceHeatingOff(const char * value, const int8_t id);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
bool set_hybridStrategy(const char * value, const int8_t id);
|
bool set_hybridStrategy(const char * value, const int8_t id);
|
||||||
bool set_switchOverTemp(const char * value, const int8_t id);
|
bool set_switchOverTemp(const char * value, const int8_t id);
|
||||||
|
|||||||
@@ -32,14 +32,25 @@ Heatpump::Heatpump(uint8_t device_type, uint8_t device_id, uint8_t product_id, c
|
|||||||
register_telegram_type(0x999, "HPFunctionTest", true, MAKE_PF_CB(process_HPFunctionTest));
|
register_telegram_type(0x999, "HPFunctionTest", true, MAKE_PF_CB(process_HPFunctionTest));
|
||||||
register_telegram_type(0x9A0, "HPTemperature", false, MAKE_PF_CB(process_HPTemperature));
|
register_telegram_type(0x9A0, "HPTemperature", false, MAKE_PF_CB(process_HPTemperature));
|
||||||
register_telegram_type(0x99B, "HPFlowTemp", false, MAKE_PF_CB(process_HPFlowTemp));
|
register_telegram_type(0x99B, "HPFlowTemp", false, MAKE_PF_CB(process_HPFlowTemp));
|
||||||
|
register_telegram_type(0x99C, "HPComp", false, MAKE_PF_CB(process_HPComp));
|
||||||
|
|
||||||
// device values
|
// device values
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &airHumidity_, DeviceValueType::UINT, FL_(airHumidity), DeviceValueUOM::PERCENT);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &airHumidity_, DeviceValueType::UINT, FL_(airHumidity), DeviceValueUOM::PERCENT);
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &dewTemperature_, DeviceValueType::UINT, FL_(dewTemperature), DeviceValueUOM::DEGREES);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &dewTemperature_, DeviceValueType::UINT, FL_(dewTemperature), DeviceValueUOM::DEGREES);
|
||||||
|
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &flowTemp_, DeviceValueType::UINT, FL_(curFlowTemp), DeviceValueUOM::DEGREES);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &retTemp_, DeviceValueType::UINT, FL_(retTemp), DeviceValueUOM::DEGREES);
|
&flowTemp_,
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &sysRetTemp_, DeviceValueType::UINT, FL_(sysRetTemp), DeviceValueUOM::DEGREES);
|
DeviceValueType::SHORT,
|
||||||
|
DeviceValueNumOp::DV_NUMOP_DIV10,
|
||||||
|
FL_(curFlowTemp),
|
||||||
|
DeviceValueUOM::DEGREES);
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &retTemp_, DeviceValueType::SHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(retTemp), DeviceValueUOM::DEGREES);
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
|
&sysRetTemp_,
|
||||||
|
DeviceValueType::SHORT,
|
||||||
|
DeviceValueNumOp::DV_NUMOP_DIV10,
|
||||||
|
FL_(sysRetTemp),
|
||||||
|
DeviceValueUOM::DEGREES);
|
||||||
|
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &hpTa4_, DeviceValueType::SHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(hpTa4), DeviceValueUOM::DEGREES);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &hpTa4_, DeviceValueType::SHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(hpTa4), DeviceValueUOM::DEGREES);
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &hpTr1_, DeviceValueType::SHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(hpTr1), DeviceValueUOM::DEGREES);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &hpTr1_, DeviceValueType::SHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(hpTr1), DeviceValueUOM::DEGREES);
|
||||||
@@ -51,6 +62,9 @@ Heatpump::Heatpump(uint8_t device_type, uint8_t device_id, uint8_t product_id, c
|
|||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &hpJr0_, DeviceValueType::SHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(hpPl1), DeviceValueUOM::DEGREES);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &hpJr0_, DeviceValueType::SHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(hpPl1), DeviceValueUOM::DEGREES);
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &hpJr1_, DeviceValueType::SHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(hpPh1), DeviceValueUOM::DEGREES);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &hpJr1_, DeviceValueType::SHORT, DeviceValueNumOp::DV_NUMOP_DIV10, FL_(hpPh1), DeviceValueUOM::DEGREES);
|
||||||
|
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &heatingPumpMod_, DeviceValueType::UINT, FL_(heatingPumpMod), DeviceValueUOM::PERCENT);
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &hpCompSpd_, DeviceValueType::UINT, FL_(hpCompSpd), DeviceValueUOM::PERCENT);
|
||||||
|
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
&controlStrategy_,
|
&controlStrategy_,
|
||||||
DeviceValueType::ENUM,
|
DeviceValueType::ENUM,
|
||||||
@@ -177,6 +191,7 @@ void Heatpump::process_HPFlowTemp(std::shared_ptr<const Telegram> telegram) {
|
|||||||
has_update(telegram, flowTemp_, 4);
|
has_update(telegram, flowTemp_, 4);
|
||||||
has_update(telegram, retTemp_, 6);
|
has_update(telegram, retTemp_, 6);
|
||||||
has_update(telegram, sysRetTemp_, 14);
|
has_update(telegram, sysRetTemp_, 14);
|
||||||
|
has_update(telegram, heatingPumpMod_, 19);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x0998 HPSettings
|
// 0x0998 HPSettings
|
||||||
@@ -193,6 +208,14 @@ void Heatpump::process_HPSettings(std::shared_ptr<const Telegram> telegram) {
|
|||||||
has_update(telegram, switchOverTemp_, 14);
|
has_update(telegram, switchOverTemp_, 14);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 0x099C HPComp
|
||||||
|
// Broadcast (0x099C), data: 00 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 76 00 00
|
||||||
|
// data: 00 2B 00 03 04 13 00 00 00 00 00 02 02 02 (offset 24)
|
||||||
|
void Heatpump::process_HPComp(std::shared_ptr<const Telegram> telegram) {
|
||||||
|
has_update(telegram, hpCompSpd_, 51);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 0x999 HPFunctionTest
|
||||||
void Heatpump::process_HPFunctionTest(std::shared_ptr<const Telegram> telegram) {
|
void Heatpump::process_HPFunctionTest(std::shared_ptr<const Telegram> telegram) {
|
||||||
has_update(telegram, airPurgeMode_, 0);
|
has_update(telegram, airPurgeMode_, 0);
|
||||||
has_update(telegram, heatPumpOutput_, 2);
|
has_update(telegram, heatPumpOutput_, 2);
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ class Heatpump : public EMSdevice {
|
|||||||
uint8_t energyPriceEl_;
|
uint8_t energyPriceEl_;
|
||||||
uint8_t energyPricePV_;
|
uint8_t energyPricePV_;
|
||||||
int8_t switchOverTemp_;
|
int8_t switchOverTemp_;
|
||||||
|
uint8_t heatingPumpMod_;
|
||||||
|
uint8_t hpCompSpd_;
|
||||||
|
|
||||||
// Function test
|
// Function test
|
||||||
uint8_t airPurgeMode_;
|
uint8_t airPurgeMode_;
|
||||||
@@ -51,9 +53,9 @@ class Heatpump : public EMSdevice {
|
|||||||
uint8_t heatCable_;
|
uint8_t heatCable_;
|
||||||
|
|
||||||
// HM200 temperature
|
// HM200 temperature
|
||||||
int16_t flowTemp_;
|
int16_t flowTemp_; // TH1
|
||||||
int16_t retTemp_;
|
int16_t retTemp_; // TH2
|
||||||
int16_t sysRetTemp_;
|
int16_t sysRetTemp_; // TH3
|
||||||
int16_t hpTc3_; // condenser temp.
|
int16_t hpTc3_; // condenser temp.
|
||||||
int16_t hpTr1_; // compressor temp.
|
int16_t hpTr1_; // compressor temp.
|
||||||
int16_t hpTr3_; // cond. temp. heating
|
int16_t hpTr3_; // cond. temp. heating
|
||||||
@@ -71,6 +73,8 @@ class Heatpump : public EMSdevice {
|
|||||||
void process_HPFunctionTest(std::shared_ptr<const Telegram> telegram);
|
void process_HPFunctionTest(std::shared_ptr<const Telegram> telegram);
|
||||||
void process_HPTemperature(std::shared_ptr<const Telegram> telegram);
|
void process_HPTemperature(std::shared_ptr<const Telegram> telegram);
|
||||||
void process_HPFlowTemp(std::shared_ptr<const Telegram> telegram);
|
void process_HPFlowTemp(std::shared_ptr<const Telegram> telegram);
|
||||||
|
void process_HPComp(std::shared_ptr<const Telegram> telegram);
|
||||||
|
|
||||||
bool set_controlStrategy(const char * value, const int8_t id);
|
bool set_controlStrategy(const char * value, const int8_t id);
|
||||||
bool set_lowNoiseMode(const char * value, const int8_t id);
|
bool set_lowNoiseMode(const char * value, const int8_t id);
|
||||||
bool set_lowNoiseStart(const char * value, const int8_t id);
|
bool set_lowNoiseStart(const char * value, const int8_t id);
|
||||||
|
|||||||
@@ -317,6 +317,7 @@ Solar::Solar(uint8_t device_type, uint8_t device_id, uint8_t product_id, const c
|
|||||||
DeviceValueUOM::DEGREES);
|
DeviceValueUOM::DEGREES);
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &cylPumpMod_, DeviceValueType::UINT, FL_(cylPumpMod), DeviceValueUOM::PERCENT);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &cylPumpMod_, DeviceValueType::UINT, FL_(cylPumpMod), DeviceValueUOM::PERCENT);
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &valveStatus_, DeviceValueType::BOOL, FL_(valveStatus), DeviceValueUOM::NONE);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &valveStatus_, DeviceValueType::BOOL, FL_(valveStatus), DeviceValueUOM::NONE);
|
||||||
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &vs1Status_, DeviceValueType::BOOL, FL_(vs1Status), DeviceValueUOM::NONE);
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &cylHeated_, DeviceValueType::BOOL, FL_(cylHeated), DeviceValueUOM::NONE);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &cylHeated_, DeviceValueType::BOOL, FL_(cylHeated), DeviceValueUOM::NONE);
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &collectorShutdown_, DeviceValueType::BOOL, FL_(collectorShutdown), DeviceValueUOM::NONE);
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA, &collectorShutdown_, DeviceValueType::BOOL, FL_(collectorShutdown), DeviceValueUOM::NONE);
|
||||||
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
register_device_value(DeviceValueTAG::TAG_DEVICE_DATA,
|
||||||
@@ -820,6 +821,7 @@ void Solar::process_SM100Status(std::shared_ptr<const Telegram> telegram) {
|
|||||||
* byte 10 = PS1 Solar circuit pump for collector array 1: test=b0001(1), on=b0100(4) and off=b0011(3)
|
* byte 10 = PS1 Solar circuit pump for collector array 1: test=b0001(1), on=b0100(4) and off=b0011(3)
|
||||||
*/
|
*/
|
||||||
void Solar::process_SM100Status2(std::shared_ptr<const Telegram> telegram) {
|
void Solar::process_SM100Status2(std::shared_ptr<const Telegram> telegram) {
|
||||||
|
has_bitupdate(telegram, vs1Status_, 0, 2); // on if bit 2 set
|
||||||
has_bitupdate(telegram, valveStatus_, 4, 2); // on if bit 2 set
|
has_bitupdate(telegram, valveStatus_, 4, 2); // on if bit 2 set
|
||||||
has_bitupdate(telegram, solarPump_, 10, 2); // on if bit 2 set
|
has_bitupdate(telegram, solarPump_, 10, 2); // on if bit 2 set
|
||||||
has_bitupdate(telegram, solarPump2_, 1, 2); // on if bit 2 set
|
has_bitupdate(telegram, solarPump2_, 1, 2); // on if bit 2 set
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ class Solar : public EMSdevice {
|
|||||||
uint8_t solarPump2Mod_; // PS4: modulation solar pump
|
uint8_t solarPump2Mod_; // PS4: modulation solar pump
|
||||||
uint8_t m1Valve_; // M1: heat assistance valve
|
uint8_t m1Valve_; // M1: heat assistance valve
|
||||||
uint8_t m1Power_; // M1: heat assistance valve
|
uint8_t m1Power_; // M1: heat assistance valve
|
||||||
|
uint8_t vs1Status_; // VS1: status
|
||||||
|
|
||||||
// 0x363 heat counter
|
// 0x363 heat counter
|
||||||
uint16_t heatCntFlowTemp_;
|
uint16_t heatCntFlowTemp_;
|
||||||
|
|||||||
@@ -1192,14 +1192,9 @@ void Thermostat::process_RC30Temp(std::shared_ptr<const Telegram> telegram) {
|
|||||||
|
|
||||||
// type 0x3E (HC1), 0x48 (HC2), 0x52 (HC3), 0x5C (HC4) - data from the RC35 thermostat (0x10) - 16 bytes
|
// type 0x3E (HC1), 0x48 (HC2), 0x52 (HC3), 0x5C (HC4) - data from the RC35 thermostat (0x10) - 16 bytes
|
||||||
void Thermostat::process_RC35Monitor(std::shared_ptr<const Telegram> telegram) {
|
void Thermostat::process_RC35Monitor(std::shared_ptr<const Telegram> telegram) {
|
||||||
// exit if the 15th byte (second from last) is 0x00, which I think is calculated flow setpoint temperature
|
// Check if heatingciruit is active, see https://github.com/emsesp/EMS-ESP32/issues/786
|
||||||
// with weather controlled RC35s this value is >=5, otherwise can be zero and our setpoint temps will be incorrect
|
uint16_t active = 0;
|
||||||
// see https://github.com/emsesp/EMS-ESP/issues/373#issuecomment-627907301
|
if (!telegram->read_value(active, 3)) {
|
||||||
if (telegram->offset > 0 || telegram->message_length < 15) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (telegram->message_data[14] == 0x00) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1642,22 +1642,6 @@ bool EMSdevice::generate_values(JsonObject & output, const uint8_t tag_filter, c
|
|||||||
return has_values;
|
return has_values;
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove the Home Assistant configs for each device value/entity if its not visible or active or marked as read-only
|
|
||||||
// this is called when an MQTT publish is done via an EMS Device in emsesp.cpp::publish_device_values()
|
|
||||||
void EMSdevice::mqtt_ha_entity_config_remove() {
|
|
||||||
for (auto & dv : devicevalues_) {
|
|
||||||
if (dv.has_state(DeviceValueState::DV_HA_CONFIG_CREATED)
|
|
||||||
&& ((dv.has_state(DeviceValueState::DV_API_MQTT_EXCLUDE)) || (!dv.has_state(DeviceValueState::DV_ACTIVE)))) {
|
|
||||||
dv.remove_state(DeviceValueState::DV_HA_CONFIG_CREATED);
|
|
||||||
if (dv.short_name == FL_(climate)[0]) {
|
|
||||||
Mqtt::publish_ha_climate_config(dv.tag, false, true); // delete topic (remove = true)
|
|
||||||
} else {
|
|
||||||
Mqtt::publish_ha_sensor_config(dv, "", "", true); // delete topic (remove = true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// create the Home Assistant configs for each device value / entity
|
// create the Home Assistant configs for each device value / entity
|
||||||
// this is called when an MQTT publish is done via an EMS Device in emsesp.cpp::publish_device_values()
|
// this is called when an MQTT publish is done via an EMS Device in emsesp.cpp::publish_device_values()
|
||||||
void EMSdevice::mqtt_ha_entity_config_create() {
|
void EMSdevice::mqtt_ha_entity_config_create() {
|
||||||
@@ -1686,6 +1670,9 @@ void EMSdevice::mqtt_ha_entity_config_create() {
|
|||||||
dv.add_state(DeviceValueState::DV_HA_CONFIG_CREATED);
|
dv.add_state(DeviceValueState::DV_HA_CONFIG_CREATED);
|
||||||
create_device_config = false; // only create the main config once
|
create_device_config = false; // only create the main config once
|
||||||
}
|
}
|
||||||
|
if (ESP.getFreeHeap() < (65 * 1024)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ha_config_done(!create_device_config);
|
ha_config_done(!create_device_config);
|
||||||
@@ -1694,7 +1681,6 @@ void EMSdevice::mqtt_ha_entity_config_create() {
|
|||||||
// remove all config topics in HA
|
// remove all config topics in HA
|
||||||
void EMSdevice::ha_config_clear() {
|
void EMSdevice::ha_config_clear() {
|
||||||
for (auto & dv : devicevalues_) {
|
for (auto & dv : devicevalues_) {
|
||||||
Mqtt::publish_ha_sensor_config(dv, "", "", true); // delete topic (remove = true)
|
|
||||||
dv.remove_state(DeviceValueState::DV_HA_CONFIG_CREATED);
|
dv.remove_state(DeviceValueState::DV_HA_CONFIG_CREATED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -289,7 +289,6 @@ class EMSdevice {
|
|||||||
void publish_all_values();
|
void publish_all_values();
|
||||||
|
|
||||||
void mqtt_ha_entity_config_create();
|
void mqtt_ha_entity_config_create();
|
||||||
void mqtt_ha_entity_config_remove();
|
|
||||||
|
|
||||||
std::string telegram_type_name(std::shared_ptr<const Telegram> telegram) const;
|
std::string telegram_type_name(std::shared_ptr<const Telegram> telegram) const;
|
||||||
|
|
||||||
@@ -306,13 +305,6 @@ class EMSdevice {
|
|||||||
ha_config_done_ = v;
|
ha_config_done_ = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ha_config_firstrun() const {
|
|
||||||
return ha_config_firstrun_;
|
|
||||||
}
|
|
||||||
void ha_config_firstrun(const bool v) {
|
|
||||||
ha_config_firstrun_ = v;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum Brand : uint8_t {
|
enum Brand : uint8_t {
|
||||||
NO_BRAND = 0, // 0
|
NO_BRAND = 0, // 0
|
||||||
BOSCH, // 1
|
BOSCH, // 1
|
||||||
@@ -366,6 +358,7 @@ class EMSdevice {
|
|||||||
static constexpr uint8_t EMS_DEVICE_ID_RFSENSOR = 0x40; // RF sensor only sending, no reply
|
static constexpr uint8_t EMS_DEVICE_ID_RFSENSOR = 0x40; // RF sensor only sending, no reply
|
||||||
static constexpr uint8_t EMS_DEVICE_ID_RFBASE = 0x50;
|
static constexpr uint8_t EMS_DEVICE_ID_RFBASE = 0x50;
|
||||||
static constexpr uint8_t EMS_DEVICE_ID_ROOMTHERMOSTAT = 0x17; // TADO using this with no version reply
|
static constexpr uint8_t EMS_DEVICE_ID_ROOMTHERMOSTAT = 0x17; // TADO using this with no version reply
|
||||||
|
static constexpr uint8_t EMS_DEVICE_ID_TADO_OLD = 0x19; // TADO using this with no broadcast and version
|
||||||
|
|
||||||
// generic type IDs
|
// generic type IDs
|
||||||
static constexpr uint16_t EMS_TYPE_VERSION = 0x02; // type ID for Version information. Generic across all EMS devices.
|
static constexpr uint16_t EMS_TYPE_VERSION = 0x02; // type ID for Version information. Generic across all EMS devices.
|
||||||
@@ -431,7 +424,6 @@ class EMSdevice {
|
|||||||
|
|
||||||
bool ha_config_done_ = false;
|
bool ha_config_done_ = false;
|
||||||
bool has_update_ = false;
|
bool has_update_ = false;
|
||||||
bool ha_config_firstrun_ = true; // this means a first setup of HA is needed after a restart
|
|
||||||
|
|
||||||
struct TelegramFunction {
|
struct TelegramFunction {
|
||||||
uint16_t telegram_type_id_; // it's type_id
|
uint16_t telegram_type_id_; // it's type_id
|
||||||
|
|||||||
@@ -535,24 +535,6 @@ void EMSESP::publish_device_values(uint8_t device_type) {
|
|||||||
bool nested = (Mqtt::is_nested());
|
bool nested = (Mqtt::is_nested());
|
||||||
|
|
||||||
// group by device type
|
// group by device type
|
||||||
if (Mqtt::ha_enabled()) {
|
|
||||||
for (const auto & emsdevice : emsdevices) {
|
|
||||||
if (emsdevice && (emsdevice->device_type() == device_type)) {
|
|
||||||
// specially for MQTT Discovery
|
|
||||||
// we may have some RETAINED /config topics that reference fields in the data payloads that no longer exist
|
|
||||||
// remove them immediately to prevent HA from complaining
|
|
||||||
// we need to do this first before the data payload is published, and only done once!
|
|
||||||
if (emsdevice->ha_config_firstrun()) {
|
|
||||||
emsdevice->ha_config_clear();
|
|
||||||
emsdevice->ha_config_firstrun(false);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
// see if we need to delete and /config topics before adding the payloads
|
|
||||||
emsdevice->mqtt_ha_entity_config_remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (uint8_t tag = DeviceValueTAG::TAG_BOILER_DATA_WW; tag <= DeviceValueTAG::TAG_HS16; tag++) {
|
for (uint8_t tag = DeviceValueTAG::TAG_BOILER_DATA_WW; tag <= DeviceValueTAG::TAG_HS16; tag++) {
|
||||||
JsonObject json_hc = json;
|
JsonObject json_hc = json;
|
||||||
bool nest_created = false;
|
bool nest_created = false;
|
||||||
@@ -1057,7 +1039,7 @@ bool EMSESP::add_device(const uint8_t device_id, const uint8_t product_id, const
|
|||||||
// see: https://github.com/emsesp/EMS-ESP32/issues/103#issuecomment-911717342 and https://github.com/emsesp/EMS-ESP32/issues/624
|
// see: https://github.com/emsesp/EMS-ESP32/issues/103#issuecomment-911717342 and https://github.com/emsesp/EMS-ESP32/issues/624
|
||||||
name = "RF room temperature sensor";
|
name = "RF room temperature sensor";
|
||||||
device_type = DeviceType::THERMOSTAT;
|
device_type = DeviceType::THERMOSTAT;
|
||||||
} else if (device_id == EMSdevice::EMS_DEVICE_ID_ROOMTHERMOSTAT) {
|
} else if (device_id == EMSdevice::EMS_DEVICE_ID_ROOMTHERMOSTAT || device_id == EMSdevice::EMS_DEVICE_ID_TADO_OLD) {
|
||||||
name = "Generic thermostat";
|
name = "Generic thermostat";
|
||||||
device_type = DeviceType::THERMOSTAT;
|
device_type = DeviceType::THERMOSTAT;
|
||||||
flags = DeviceFlags::EMS_DEVICE_FLAG_RC10 | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE;
|
flags = DeviceFlags::EMS_DEVICE_FLAG_RC10 | DeviceFlags::EMS_DEVICE_FLAG_NO_WRITE;
|
||||||
|
|||||||
@@ -291,7 +291,7 @@ MAKE_PSTR_ENUM(enum_modetype5, FL_(off), FL_(on))
|
|||||||
|
|
||||||
MAKE_PSTR_ENUM(enum_reducemode, FL_(nofrost), FL_(reduce), FL_(room), FL_(outdoor))
|
MAKE_PSTR_ENUM(enum_reducemode, FL_(nofrost), FL_(reduce), FL_(room), FL_(outdoor))
|
||||||
MAKE_PSTR_ENUM(enum_reducemode1, FL_(outdoor), FL_(room), FL_(reduce)) // RC310 values: 1-3
|
MAKE_PSTR_ENUM(enum_reducemode1, FL_(outdoor), FL_(room), FL_(reduce)) // RC310 values: 1-3
|
||||||
MAKE_PSTR_ENUM(enum_nofrostmode, FL_(off), FL_(room), FL_(outdoor))
|
MAKE_PSTR_ENUM(enum_nofrostmode, FL_(off), FL_(outdoor), FL_(room))
|
||||||
MAKE_PSTR_ENUM(enum_nofrostmode1, FL_(room), FL_(outdoor), FL_(room_outdoor))
|
MAKE_PSTR_ENUM(enum_nofrostmode1, FL_(room), FL_(outdoor), FL_(room_outdoor))
|
||||||
|
|
||||||
MAKE_PSTR_ENUM(enum_controlmode, FL_(off), FL_(optimized), FL_(simple), FL_(mpc), FL_(room), FL_(power), FL_(constant))
|
MAKE_PSTR_ENUM(enum_controlmode, FL_(off), FL_(optimized), FL_(simple), FL_(mpc), FL_(room), FL_(power), FL_(constant))
|
||||||
|
|||||||
@@ -269,6 +269,7 @@ MAKE_PSTR_LIST(cyl2, "cyl 2", "Zyl_2", "Cil 2", "Cyl 2", "cyl 2", "cyl 2", "cyl
|
|||||||
|
|
||||||
// Entity translations
|
// Entity translations
|
||||||
// Boiler
|
// Boiler
|
||||||
|
MAKE_PSTR_LIST(forceHeatingOff, "heatingoff", "force heating off", "Heizen abschalten", "", "", "", "", "")
|
||||||
MAKE_PSTR_LIST(wwtapactivated, "wwtapactivated", "turn on/off", "Durchlauferhitzer aktiv", "zet aan/uit", "på/av", "system przygotowywania", "slå på/av", "ecs activée")
|
MAKE_PSTR_LIST(wwtapactivated, "wwtapactivated", "turn on/off", "Durchlauferhitzer aktiv", "zet aan/uit", "på/av", "system przygotowywania", "slå på/av", "ecs activée")
|
||||||
MAKE_PSTR_LIST(reset, "reset", "Reset", "Reset", "Reset", "Nollställ", "kasowanie komunikatu", "nullstill", "reset")
|
MAKE_PSTR_LIST(reset, "reset", "Reset", "Reset", "Reset", "Nollställ", "kasowanie komunikatu", "nullstill", "reset")
|
||||||
MAKE_PSTR_LIST(oilPreHeat, "oilpreheat", "oil preheating", "Ölvorwärmung", "Olie voorverwarming", "Förvärmning olja", "podgrzewanie oleju", "oljeforvarming", "préchauffage de l'huile")
|
MAKE_PSTR_LIST(oilPreHeat, "oilpreheat", "oil preheating", "Ölvorwärmung", "Olie voorverwarming", "Förvärmning olja", "podgrzewanie oleju", "oljeforvarming", "préchauffage de l'huile")
|
||||||
@@ -683,6 +684,7 @@ MAKE_PSTR_LIST(solarPump, "solarpump", "pump (PS1)", "Pumpe (PS1)", "Pomp (PS1)"
|
|||||||
MAKE_PSTR_LIST(solarPump2, "solarpump2", "pump 2 (PS4)", "Pumpe 2 (PS4)", "Pomp 2 (PS4)", "Pump 2 (PS4)", "pompa solarna 2 (PS4)", "solpumpe 2 (PS4)", "pompe 2 (PS4)")
|
MAKE_PSTR_LIST(solarPump2, "solarpump2", "pump 2 (PS4)", "Pumpe 2 (PS4)", "Pomp 2 (PS4)", "Pump 2 (PS4)", "pompa solarna 2 (PS4)", "solpumpe 2 (PS4)", "pompe 2 (PS4)")
|
||||||
MAKE_PSTR_LIST(solarPump2Mod, "solarpump2mod", "pump 2 modulation (PS4)", "Pumpe 2 Modulation (PS4)", "Modulatie pomp 2 (PS4)", "Pump 2 Modulering (PS4)", "modulacja pompy solarnej 2 (PS4)", "solpumpe2modulering (PS4)", "modulation pompe solaire 2 (PS4)")
|
MAKE_PSTR_LIST(solarPump2Mod, "solarpump2mod", "pump 2 modulation (PS4)", "Pumpe 2 Modulation (PS4)", "Modulatie pomp 2 (PS4)", "Pump 2 Modulering (PS4)", "modulacja pompy solarnej 2 (PS4)", "solpumpe2modulering (PS4)", "modulation pompe solaire 2 (PS4)")
|
||||||
MAKE_PSTR_LIST(valveStatus, "valvestatus", "valve status", "Ventilstatus", "Klepstatus", "Ventilstatus", "stan zaworu", "ventilstatus", "statut valve")
|
MAKE_PSTR_LIST(valveStatus, "valvestatus", "valve status", "Ventilstatus", "Klepstatus", "Ventilstatus", "stan zaworu", "ventilstatus", "statut valve")
|
||||||
|
MAKE_PSTR_LIST(vs1Status, "vs1status", "valve status VS1", "Ventilstatus VS1", "Klepstatus VS1", "Ventilstatus VS1", "stan zaworu VS1", "ventilstatus VS1", "statut valve VS1")
|
||||||
MAKE_PSTR_LIST(cylHeated, "cylheated", "cyl heated", "Speichertemperatur erreicht", "Boilertemperatuur behaald", "Värmepanna Uppvärmd", "zasobnik został nagrzany", "bereder oppvarmt", "cylindre chauffé")
|
MAKE_PSTR_LIST(cylHeated, "cylheated", "cyl heated", "Speichertemperatur erreicht", "Boilertemperatuur behaald", "Värmepanna Uppvärmd", "zasobnik został nagrzany", "bereder oppvarmt", "cylindre chauffé")
|
||||||
MAKE_PSTR_LIST(collectorShutdown, "collectorshutdown", "collector shutdown", "Kollektorabschaltung", "Collector afschakeling", "Kollektor Avstängning", "wyłączenie kolektora", "kollektor stengt", "arrêt collecteur")
|
MAKE_PSTR_LIST(collectorShutdown, "collectorshutdown", "collector shutdown", "Kollektorabschaltung", "Collector afschakeling", "Kollektor Avstängning", "wyłączenie kolektora", "kollektor stengt", "arrêt collecteur")
|
||||||
MAKE_PSTR_LIST(pumpWorkTime, "pumpworktime", "pump working time", "Pumpenlaufzeit", "Pomplooptijd", "Pump Drifttid", "czas pracy pompy", "driftstid pumpe", "durée fonctionnement pompe")
|
MAKE_PSTR_LIST(pumpWorkTime, "pumpworktime", "pump working time", "Pumpenlaufzeit", "Pomplooptijd", "Pump Drifttid", "czas pracy pompy", "driftstid pumpe", "durée fonctionnement pompe")
|
||||||
|
|||||||
103
src/mqtt.cpp
103
src/mqtt.cpp
@@ -685,7 +685,7 @@ std::shared_ptr<const MqttMessage> Mqtt::queue_message(const uint8_t operation,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// if the queue is full, make room but removing the last one
|
// if the queue is full, make room but removing the last one
|
||||||
if (mqtt_messages_.size() >= MAX_MQTT_MESSAGES) {
|
if (mqtt_messages_.size() >= MAX_MQTT_MESSAGES || ESP.getFreeHeap() < (60 * 1024)) {
|
||||||
mqtt_messages_.pop_front();
|
mqtt_messages_.pop_front();
|
||||||
LOG_WARNING("Queue overflow, removing one message");
|
LOG_WARNING("Queue overflow, removing one message");
|
||||||
mqtt_publish_fails_++;
|
mqtt_publish_fails_++;
|
||||||
@@ -815,8 +815,8 @@ void Mqtt::process_queue() {
|
|||||||
#if defined(EMSESP_DEBUG)
|
#if defined(EMSESP_DEBUG)
|
||||||
LOG_DEBUG("[DEBUG] Waiting for QOS-ACK");
|
LOG_DEBUG("[DEBUG] Waiting for QOS-ACK");
|
||||||
#endif
|
#endif
|
||||||
// if we don't get the ack within 10 minutes, republish with new packet_id
|
// if we don't get the ack within 10 seconds, republish with new packet_id
|
||||||
if (uuid::get_uptime_sec() - last_publish_queue_ < 600) {
|
if (uuid::get_uptime_sec() - last_publish_queue_ < 10) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1074,6 +1074,8 @@ void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
|
|||||||
const char * sc_ha = "stat_cla"; // state class
|
const char * sc_ha = "stat_cla"; // state class
|
||||||
const char * uom_ha = "unit_of_meas"; // unit of measure
|
const char * uom_ha = "unit_of_meas"; // unit of measure
|
||||||
|
|
||||||
|
char sample_val[30] = "0"; // sample, correct(!) entity value, used only to prevent warning/error in HA if real value is not published yet
|
||||||
|
|
||||||
// handle commands, which are device entities that are writable
|
// handle commands, which are device entities that are writable
|
||||||
// we add the command topic parameter
|
// we add the command topic parameter
|
||||||
// note: there is no way to handle strings in HA so datetimes (e.g. set_datetime, set_holiday, set_wwswitchtime etc) are excluded
|
// note: there is no way to handle strings in HA so datetimes (e.g. set_datetime, set_holiday, set_wwswitchtime etc) are excluded
|
||||||
@@ -1093,6 +1095,7 @@ void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
|
|||||||
for (uint8_t i = 0; i < options_size; i++) {
|
for (uint8_t i = 0; i < options_size; i++) {
|
||||||
option_list.add(Helpers::translated_word(options[i]));
|
option_list.add(Helpers::translated_word(options[i]));
|
||||||
}
|
}
|
||||||
|
snprintf(sample_val, sizeof(sample_val), "'%s'", Helpers::translated_word(options[0]));
|
||||||
} else if (type != DeviceValueType::STRING && type != DeviceValueType::BOOL) {
|
} else if (type != DeviceValueType::STRING && type != DeviceValueType::BOOL) {
|
||||||
// Must be Numeric....
|
// Must be Numeric....
|
||||||
doc["mode"] = "box"; // auto, slider or box
|
doc["mode"] = "box"; // auto, slider or box
|
||||||
@@ -1109,6 +1112,7 @@ void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
|
|||||||
if (dv_set_min != 0 || dv_set_max != 0) {
|
if (dv_set_min != 0 || dv_set_max != 0) {
|
||||||
doc["min"] = dv_set_min;
|
doc["min"] = dv_set_min;
|
||||||
doc["max"] = dv_set_max;
|
doc["max"] = dv_set_max;
|
||||||
|
snprintf(sample_val, sizeof(sample_val), "%i", dv_set_min);
|
||||||
}
|
}
|
||||||
|
|
||||||
// set icons
|
// set icons
|
||||||
@@ -1146,17 +1150,15 @@ void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
|
|||||||
|
|
||||||
// value template
|
// value template
|
||||||
// if its nested mqtt format then use the appended entity name, otherwise take the original name
|
// if its nested mqtt format then use the appended entity name, otherwise take the original name
|
||||||
char val_tpl[75];
|
char val_obj[100];
|
||||||
if (is_nested()) {
|
char val_cond[200];
|
||||||
if (tag >= DeviceValueTAG::TAG_HC1) {
|
if (is_nested() && tag >= DeviceValueTAG::TAG_HC1) {
|
||||||
snprintf(val_tpl, sizeof(val_tpl), "{{value_json.%s.%s}}", EMSdevice::tag_to_mqtt(tag).c_str(), entity);
|
snprintf(val_obj, sizeof(val_obj), "value_json.%s.%s", EMSdevice::tag_to_mqtt(tag).c_str(), entity);
|
||||||
|
snprintf(val_cond, sizeof(val_cond), "value_json.%s is defined and %s is defined", EMSdevice::tag_to_mqtt(tag).c_str(), val_obj);
|
||||||
} else {
|
} else {
|
||||||
snprintf(val_tpl, sizeof(val_tpl), "{{value_json.%s}}", entity);
|
snprintf(val_obj, sizeof(val_obj), "value_json.%s", entity);
|
||||||
|
snprintf(val_cond, sizeof(val_cond), "%s is defined", val_obj);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
snprintf(val_tpl, sizeof(val_tpl), "{{value_json.%s}}", entity);
|
|
||||||
}
|
|
||||||
doc["val_tpl"] = val_tpl;
|
|
||||||
|
|
||||||
// special case to handle booleans
|
// special case to handle booleans
|
||||||
// applies to both Binary Sensor (read only) and a Switch (for a command)
|
// applies to both Binary Sensor (read only) and a Switch (for a command)
|
||||||
@@ -1165,6 +1167,7 @@ void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
|
|||||||
if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) {
|
if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) {
|
||||||
doc["pl_on"] = true;
|
doc["pl_on"] = true;
|
||||||
doc["pl_off"] = false;
|
doc["pl_off"] = false;
|
||||||
|
snprintf(sample_val, sizeof(sample_val), "false");
|
||||||
} else if (EMSESP::system_.bool_format() == BOOL_FORMAT_10) {
|
} else if (EMSESP::system_.bool_format() == BOOL_FORMAT_10) {
|
||||||
doc["pl_on"] = 1;
|
doc["pl_on"] = 1;
|
||||||
doc["pl_off"] = 0;
|
doc["pl_off"] = 0;
|
||||||
@@ -1172,6 +1175,7 @@ void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
|
|||||||
char result[12];
|
char result[12];
|
||||||
doc["pl_on"] = Helpers::render_boolean(result, true);
|
doc["pl_on"] = Helpers::render_boolean(result, true);
|
||||||
doc["pl_off"] = Helpers::render_boolean(result, false);
|
doc["pl_off"] = Helpers::render_boolean(result, false);
|
||||||
|
snprintf(sample_val, sizeof(sample_val), "'%s'", Helpers::render_boolean(result, false));
|
||||||
}
|
}
|
||||||
doc[sc_ha] = F_(measurement); //do we want this???
|
doc[sc_ha] = F_(measurement); //do we want this???
|
||||||
} else {
|
} else {
|
||||||
@@ -1189,6 +1193,8 @@ void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
doc["val_tpl"] = (std::string) "{{" + val_obj + " if " + val_cond + " else " + sample_val + "}}";
|
||||||
|
|
||||||
// this next section is adding the state class, device class and sometimes the icon
|
// this next section is adding the state class, device class and sometimes the icon
|
||||||
// used for Sensor and Binary Sensor Entities in HA
|
// used for Sensor and Binary Sensor Entities in HA
|
||||||
if (set_ha_classes) {
|
if (set_ha_classes) {
|
||||||
@@ -1284,6 +1290,9 @@ void Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
|
|||||||
// add the dev json object to the end
|
// add the dev json object to the end
|
||||||
doc["dev"] = dev_json;
|
doc["dev"] = dev_json;
|
||||||
|
|
||||||
|
// add "availability" section
|
||||||
|
add_avty_to_doc(stat_t, doc.as<JsonObject>(), val_cond);
|
||||||
|
|
||||||
publish_ha(topic, doc.as<JsonObject>());
|
publish_ha(topic, doc.as<JsonObject>());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1295,6 +1304,9 @@ void Mqtt::publish_ha_climate_config(const uint8_t tag, const bool has_roomtemp,
|
|||||||
char hc_mode_s[30];
|
char hc_mode_s[30];
|
||||||
char seltemp_s[30];
|
char seltemp_s[30];
|
||||||
char currtemp_s[30];
|
char currtemp_s[30];
|
||||||
|
char hc_mode_cond[80];
|
||||||
|
char seltemp_cond[80];
|
||||||
|
char currtemp_cond[170];
|
||||||
char mode_str_tpl[400];
|
char mode_str_tpl[400];
|
||||||
char name_s[10];
|
char name_s[10];
|
||||||
char uniq_id_s[60];
|
char uniq_id_s[60];
|
||||||
@@ -1312,24 +1324,31 @@ void Mqtt::publish_ha_climate_config(const uint8_t tag, const bool has_roomtemp,
|
|||||||
if (Mqtt::is_nested()) {
|
if (Mqtt::is_nested()) {
|
||||||
// nested format
|
// nested format
|
||||||
snprintf(hc_mode_s, sizeof(hc_mode_s), "value_json.hc%d.mode", hc_num);
|
snprintf(hc_mode_s, sizeof(hc_mode_s), "value_json.hc%d.mode", hc_num);
|
||||||
snprintf(seltemp_s, sizeof(seltemp_s), "{{value_json.hc%d.seltemp}}", hc_num);
|
snprintf(hc_mode_cond, sizeof(hc_mode_cond), "value_json.hc%d is undefined or %s is undefined", hc_num, hc_mode_s);
|
||||||
|
snprintf(seltemp_s, sizeof(seltemp_s), "value_json.hc%d.seltemp", hc_num);
|
||||||
|
snprintf(seltemp_cond, sizeof(seltemp_cond), "value_json.hc%d is defined and %s is defined", hc_num, seltemp_s);
|
||||||
if (has_roomtemp) {
|
if (has_roomtemp) {
|
||||||
snprintf(currtemp_s, sizeof(currtemp_s), "{{value_json.hc%d.currtemp}}", hc_num);
|
snprintf(currtemp_s, sizeof(currtemp_s), "value_json.hc%d.currtemp", hc_num);
|
||||||
|
snprintf(currtemp_cond, sizeof(currtemp_cond), "value_json.hc%d is defined and %s is defined", hc_num, currtemp_s);
|
||||||
}
|
}
|
||||||
snprintf(topic_t, sizeof(topic_t), "~/%s", Mqtt::tag_to_topic(EMSdevice::DeviceType::THERMOSTAT, DeviceValueTAG::TAG_NONE).c_str());
|
snprintf(topic_t, sizeof(topic_t), "~/%s", Mqtt::tag_to_topic(EMSdevice::DeviceType::THERMOSTAT, DeviceValueTAG::TAG_NONE).c_str());
|
||||||
} else {
|
} else {
|
||||||
// single format
|
// single format
|
||||||
snprintf(hc_mode_s, sizeof(hc_mode_s), "value_json.mode");
|
snprintf(hc_mode_s, sizeof(hc_mode_s), "value_json.mode");
|
||||||
snprintf(seltemp_s, sizeof(seltemp_s), "{{value_json.seltemp}}");
|
snprintf(hc_mode_cond, sizeof(hc_mode_cond), "%s is undefined", hc_mode_s);
|
||||||
|
snprintf(seltemp_s, sizeof(seltemp_s), "value_json.seltemp");
|
||||||
|
snprintf(seltemp_cond, sizeof(seltemp_cond), "%s is defined", seltemp_s);
|
||||||
if (has_roomtemp) {
|
if (has_roomtemp) {
|
||||||
snprintf(currtemp_s, sizeof(currtemp_s), "{{value_json.currtemp}}");
|
snprintf(currtemp_s, sizeof(currtemp_s), "value_json.currtemp");
|
||||||
|
snprintf(currtemp_cond, sizeof(currtemp_cond), "%s is defined", currtemp_s);
|
||||||
}
|
}
|
||||||
snprintf(topic_t, sizeof(topic_t), "~/%s", Mqtt::tag_to_topic(EMSdevice::DeviceType::THERMOSTAT, DeviceValueTAG::TAG_HC1 + hc_num - 1).c_str());
|
snprintf(topic_t, sizeof(topic_t), "~/%s", Mqtt::tag_to_topic(EMSdevice::DeviceType::THERMOSTAT, DeviceValueTAG::TAG_HC1 + hc_num - 1).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(mode_str_tpl,
|
snprintf(mode_str_tpl,
|
||||||
sizeof(mode_str_tpl),
|
sizeof(mode_str_tpl),
|
||||||
"{%%if %s=='manual'%%}heat{%%elif %s=='day'%%}heat{%%elif %s=='night'%%}off{%%elif %s=='off'%%}off{%%else%%}auto{%%endif%%}",
|
"{%%if %s%%}off{%%elif %s=='manual'%%}heat{%%elif %s=='day'%%}heat{%%elif %s=='night'%%}off{%%elif %s=='off'%%}off{%%else%%}auto{%%endif%%}",
|
||||||
|
hc_mode_cond,
|
||||||
hc_mode_s,
|
hc_mode_s,
|
||||||
hc_mode_s,
|
hc_mode_s,
|
||||||
hc_mode_s,
|
hc_mode_s,
|
||||||
@@ -1346,7 +1365,7 @@ void Mqtt::publish_ha_climate_config(const uint8_t tag, const bool has_roomtemp,
|
|||||||
snprintf(temp_cmd_s, sizeof(temp_cmd_s), "~/thermostat/hc%d/seltemp", hc_num);
|
snprintf(temp_cmd_s, sizeof(temp_cmd_s), "~/thermostat/hc%d/seltemp", hc_num);
|
||||||
snprintf(mode_cmd_s, sizeof(temp_cmd_s), "~/thermostat/hc%d/mode", hc_num);
|
snprintf(mode_cmd_s, sizeof(temp_cmd_s), "~/thermostat/hc%d/mode", hc_num);
|
||||||
|
|
||||||
StaticJsonDocument<EMSESP_JSON_SIZE_HA_CONFIG> doc;
|
StaticJsonDocument<EMSESP_JSON_SIZE_HA_CONFIG + 512> doc;
|
||||||
|
|
||||||
doc["~"] = mqtt_base_;
|
doc["~"] = mqtt_base_;
|
||||||
doc["uniq_id"] = uniq_id_s;
|
doc["uniq_id"] = uniq_id_s;
|
||||||
@@ -1356,12 +1375,10 @@ void Mqtt::publish_ha_climate_config(const uint8_t tag, const bool has_roomtemp,
|
|||||||
doc["mode_stat_tpl"] = mode_str_tpl;
|
doc["mode_stat_tpl"] = mode_str_tpl;
|
||||||
doc["temp_cmd_t"] = temp_cmd_s;
|
doc["temp_cmd_t"] = temp_cmd_s;
|
||||||
doc["temp_stat_t"] = topic_t;
|
doc["temp_stat_t"] = topic_t;
|
||||||
doc["temp_stat_tpl"] = seltemp_s;
|
doc["temp_stat_tpl"] = (std::string) "{{" + seltemp_s + " if " + seltemp_cond + " else 0}}";
|
||||||
doc["mode_cmd_t"] = mode_cmd_s;
|
|
||||||
|
|
||||||
if (has_roomtemp) {
|
if (has_roomtemp) {
|
||||||
doc["curr_temp_t"] = topic_t;
|
doc["curr_temp_t"] = topic_t;
|
||||||
doc["curr_temp_tpl"] = currtemp_s;
|
doc["curr_temp_tpl"] = (std::string) "{{" + currtemp_s + " if " + currtemp_cond + " else 0}}";
|
||||||
}
|
}
|
||||||
|
|
||||||
doc["min_temp"] = Helpers::render_value(min_s, min, 0, EMSESP::system_.fahrenheit() ? 2 : 0);
|
doc["min_temp"] = Helpers::render_value(min_s, min, 0, EMSESP::system_.fahrenheit() ? 2 : 0);
|
||||||
@@ -1369,8 +1386,8 @@ void Mqtt::publish_ha_climate_config(const uint8_t tag, const bool has_roomtemp,
|
|||||||
doc["temp_step"] = "0.5";
|
doc["temp_step"] = "0.5";
|
||||||
|
|
||||||
// the HA climate component only responds to auto, heat and off
|
// the HA climate component only responds to auto, heat and off
|
||||||
|
doc["mode_cmd_t"] = mode_cmd_s;
|
||||||
JsonArray modes = doc.createNestedArray("modes");
|
JsonArray modes = doc.createNestedArray("modes");
|
||||||
|
|
||||||
modes.add("auto");
|
modes.add("auto");
|
||||||
modes.add("heat");
|
modes.add("heat");
|
||||||
modes.add("off");
|
modes.add("off");
|
||||||
@@ -1379,6 +1396,9 @@ void Mqtt::publish_ha_climate_config(const uint8_t tag, const bool has_roomtemp,
|
|||||||
JsonArray ids = dev.createNestedArray("ids");
|
JsonArray ids = dev.createNestedArray("ids");
|
||||||
ids.add("ems-esp-thermostat");
|
ids.add("ems-esp-thermostat");
|
||||||
|
|
||||||
|
// add "availability" section
|
||||||
|
add_avty_to_doc(topic_t, doc.as<JsonObject>(), seltemp_cond, has_roomtemp ? currtemp_cond : nullptr, hc_mode_cond);
|
||||||
|
|
||||||
publish_ha(topic, doc.as<JsonObject>()); // publish the config payload with retain flag
|
publish_ha(topic, doc.as<JsonObject>()); // publish the config payload with retain flag
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1401,4 +1421,41 @@ std::string Mqtt::tag_to_topic(uint8_t device_type, uint8_t tag) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// adds "availability" section to HA Discovery config
|
||||||
|
void Mqtt::add_avty_to_doc(const char * state_t, const JsonObject & doc, const char * cond1, const char * cond2, const char * negcond) {
|
||||||
|
const char * tpl_draft = "{{'online' if %s else 'offline'}}";
|
||||||
|
char tpl[150];
|
||||||
|
JsonArray avty = doc.createNestedArray("avty");
|
||||||
|
|
||||||
|
StaticJsonDocument<512> avty_json;
|
||||||
|
|
||||||
|
snprintf(tpl, sizeof(tpl), "%s/status", mqtt_base_.c_str());
|
||||||
|
avty_json["t"] = tpl;
|
||||||
|
snprintf(tpl, sizeof(tpl), tpl_draft, "value == 'online'");
|
||||||
|
avty_json["val_tpl"] = tpl;
|
||||||
|
avty.add(avty_json);
|
||||||
|
avty_json.clear();
|
||||||
|
|
||||||
|
avty_json["t"] = state_t;
|
||||||
|
snprintf(tpl, sizeof(tpl), tpl_draft, cond1 == nullptr ? "value is defined" : cond1);
|
||||||
|
avty_json["val_tpl"] = tpl;
|
||||||
|
avty.add(avty_json);
|
||||||
|
if (cond2 != nullptr) {
|
||||||
|
avty_json.clear();
|
||||||
|
avty_json["t"] = state_t;
|
||||||
|
snprintf(tpl, sizeof(tpl), tpl_draft, cond2);
|
||||||
|
avty_json["val_tpl"] = tpl;
|
||||||
|
avty.add(avty_json);
|
||||||
|
}
|
||||||
|
if (negcond != nullptr) {
|
||||||
|
avty_json.clear();
|
||||||
|
avty_json["t"] = state_t;
|
||||||
|
snprintf(tpl, sizeof(tpl), "{{'offline' if %s else 'online'}}", negcond);
|
||||||
|
avty_json["val_tpl"] = tpl;
|
||||||
|
avty.add(avty_json);
|
||||||
|
}
|
||||||
|
|
||||||
|
doc["avty_mode"] = "all";
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace emsesp
|
} // namespace emsesp
|
||||||
|
|||||||
@@ -240,6 +240,9 @@ class Mqtt {
|
|||||||
|
|
||||||
static std::string tag_to_topic(uint8_t device_type, uint8_t tag);
|
static std::string tag_to_topic(uint8_t device_type, uint8_t tag);
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_avty_to_doc(const char * state_t, const JsonObject & doc, const char * cond1 = nullptr, const char * cond2 = nullptr, const char * negcond = nullptr);
|
||||||
|
|
||||||
struct QueuedMqttMessage {
|
struct QueuedMqttMessage {
|
||||||
const uint32_t id_;
|
const uint32_t id_;
|
||||||
const std::shared_ptr<const MqttMessage> content_;
|
const std::shared_ptr<const MqttMessage> content_;
|
||||||
|
|||||||
@@ -168,8 +168,8 @@ void Shower::set_shower_state(bool state, bool force) {
|
|||||||
doc["stat_t"] = stat_t;
|
doc["stat_t"] = stat_t;
|
||||||
|
|
||||||
if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) {
|
if (EMSESP::system_.bool_format() == BOOL_FORMAT_TRUEFALSE) {
|
||||||
doc["pl_on"] = true;
|
doc["pl_on"] = "true";
|
||||||
doc["pl_off"] = false;
|
doc["pl_off"] = "false";
|
||||||
} else if (EMSESP::system_.bool_format() == BOOL_FORMAT_10) {
|
} else if (EMSESP::system_.bool_format() == BOOL_FORMAT_10) {
|
||||||
doc["pl_on"] = 1;
|
doc["pl_on"] = 1;
|
||||||
doc["pl_off"] = 0;
|
doc["pl_off"] = 0;
|
||||||
@@ -183,6 +183,9 @@ void Shower::set_shower_state(bool state, bool force) {
|
|||||||
JsonArray ids = dev.createNestedArray("ids");
|
JsonArray ids = dev.createNestedArray("ids");
|
||||||
ids.add("ems-esp");
|
ids.add("ems-esp");
|
||||||
|
|
||||||
|
// add "availability" section
|
||||||
|
Mqtt::add_avty_to_doc(stat_t, doc.as<JsonObject>());
|
||||||
|
|
||||||
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
|
||||||
snprintf(topic, sizeof(topic), "binary_sensor/%s/shower_active/config", Mqtt::basename().c_str());
|
snprintf(topic, sizeof(topic), "binary_sensor/%s/shower_active/config", Mqtt::basename().c_str());
|
||||||
Mqtt::publish_ha(topic, doc.as<JsonObject>()); // publish the config payload with retain flag
|
Mqtt::publish_ha(topic, doc.as<JsonObject>()); // publish the config payload with retain flag
|
||||||
|
|||||||
@@ -659,7 +659,6 @@ void System::network_init(bool refresh) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
last_system_check_ = 0; // force the LED to go from fast flash to pulse
|
last_system_check_ = 0; // force the LED to go from fast flash to pulse
|
||||||
send_heartbeat();
|
|
||||||
|
|
||||||
if (phy_type_ == PHY_type::PHY_TYPE_NONE) {
|
if (phy_type_ == PHY_type::PHY_TYPE_NONE) {
|
||||||
return;
|
return;
|
||||||
@@ -715,7 +714,6 @@ void System::system_check() {
|
|||||||
digitalWrite(led_gpio_, hide_led_ ? !LED_ON : LED_ON);
|
digitalWrite(led_gpio_, hide_led_ ? !LED_ON : LED_ON);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
send_heartbeat();
|
|
||||||
} else {
|
} else {
|
||||||
// turn off LED so we're ready to the flashes
|
// turn off LED so we're ready to the flashes
|
||||||
if (led_gpio_) {
|
if (led_gpio_) {
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
#define EMSESP_APP_VERSION "3.5.0-dev.18"
|
#define EMSESP_APP_VERSION "3.5.2-patch.0"
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ void WebLogService::operator<<(std::shared_ptr<uuid::log::Message> message) {
|
|||||||
log_messages_.pop_front();
|
log_messages_.pop_front();
|
||||||
}
|
}
|
||||||
|
|
||||||
log_messages_.emplace_back(log_message_id_++, std::move(message));
|
log_messages_.emplace_back(++log_message_id_, std::move(message));
|
||||||
|
|
||||||
EMSESP::esp8266React.getNTPSettingsService()->read([&](NTPSettings & settings) {
|
EMSESP::esp8266React.getNTPSettingsService()->read([&](NTPSettings & settings) {
|
||||||
if (!settings.enabled || (time(nullptr) < 1500000000L)) {
|
if (!settings.enabled || (time(nullptr) < 1500000000L)) {
|
||||||
@@ -191,7 +191,7 @@ char * WebLogService::messagetime(char * out, const uint64_t t, const size_t buf
|
|||||||
|
|
||||||
// send to web eventsource
|
// send to web eventsource
|
||||||
void WebLogService::transmit(const QueuedLogMessage & message) {
|
void WebLogService::transmit(const QueuedLogMessage & message) {
|
||||||
auto jsonDocument = DynamicJsonDocument(EMSESP_JSON_SIZE_MEDIUM);
|
StaticJsonDocument<EMSESP_JSON_SIZE_MEDIUM> jsonDocument;
|
||||||
JsonObject logEvent = jsonDocument.to<JsonObject>();
|
JsonObject logEvent = jsonDocument.to<JsonObject>();
|
||||||
char time_string[25];
|
char time_string[25];
|
||||||
|
|
||||||
@@ -212,33 +212,10 @@ void WebLogService::transmit(const QueuedLogMessage & message) {
|
|||||||
|
|
||||||
// send the complete log buffer to the API, not filtering on log level
|
// send the complete log buffer to the API, not filtering on log level
|
||||||
void WebLogService::fetchLog(AsyncWebServerRequest * request) {
|
void WebLogService::fetchLog(AsyncWebServerRequest * request) {
|
||||||
// auto * response = new MsgpackAsyncJsonResponse(false, EMSESP_JSON_SIZE_LARGE_DYN + 192 * log_messages_.size());
|
log_message_id_tail_ = 0;
|
||||||
size_t buffer = EMSESP_JSON_SIZE_XLARGE_DYN + 192 * log_messages_.size();
|
request->send(200);
|
||||||
auto * response = new MsgpackAsyncJsonResponse(false, buffer);
|
|
||||||
while (!response->getSize()) {
|
|
||||||
delete response;
|
|
||||||
buffer -= 1024;
|
|
||||||
response = new MsgpackAsyncJsonResponse(false, buffer);
|
|
||||||
}
|
}
|
||||||
JsonObject root = response->getRoot();
|
|
||||||
JsonArray log = root.createNestedArray("events");
|
|
||||||
|
|
||||||
log_message_id_tail_ = log_messages_.back().id_;
|
|
||||||
last_transmit_ = uuid::get_uptime_ms();
|
|
||||||
for (const auto & message : log_messages_) {
|
|
||||||
JsonObject logEvent = log.createNestedObject();
|
|
||||||
char time_string[25];
|
|
||||||
|
|
||||||
logEvent["t"] = messagetime(time_string, message.content_->uptime_ms, sizeof(time_string));
|
|
||||||
logEvent["l"] = message.content_->level;
|
|
||||||
logEvent["i"] = message.id_;
|
|
||||||
logEvent["n"] = message.content_->name;
|
|
||||||
logEvent["m"] = message.content_->text;
|
|
||||||
}
|
|
||||||
log_message_id_tail_ = log_messages_.back().id_;
|
|
||||||
response->setLength();
|
|
||||||
request->send(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// sets the values like level after a POST
|
// sets the values like level after a POST
|
||||||
void WebLogService::setValues(AsyncWebServerRequest * request, JsonVariant & json) {
|
void WebLogService::setValues(AsyncWebServerRequest * request, JsonVariant & json) {
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ void WebSettings::read(WebSettings & settings, JsonObject & root) {
|
|||||||
root["syslog_mark_interval"] = settings.syslog_mark_interval;
|
root["syslog_mark_interval"] = settings.syslog_mark_interval;
|
||||||
root["syslog_host"] = settings.syslog_host;
|
root["syslog_host"] = settings.syslog_host;
|
||||||
root["syslog_port"] = settings.syslog_port;
|
root["syslog_port"] = settings.syslog_port;
|
||||||
|
root["boiler_heatingoff"] = settings.boiler_heatingoff;
|
||||||
root["shower_timer"] = settings.shower_timer;
|
root["shower_timer"] = settings.shower_timer;
|
||||||
root["shower_alert"] = settings.shower_alert;
|
root["shower_alert"] = settings.shower_alert;
|
||||||
root["shower_alert_coldshot"] = settings.shower_alert_coldshot;
|
root["shower_alert_coldshot"] = settings.shower_alert_coldshot;
|
||||||
@@ -240,38 +241,40 @@ StateUpdateResult WebSettings::update(JsonObject & root, WebSettings & settings)
|
|||||||
settings.low_clock = root["low_clock"] | false;
|
settings.low_clock = root["low_clock"] | false;
|
||||||
check_flag(prev, settings.low_clock, ChangeFlags::RESTART);
|
check_flag(prev, settings.low_clock, ChangeFlags::RESTART);
|
||||||
|
|
||||||
String old_local = settings.locale;
|
|
||||||
settings.locale = root["locale"] | EMSESP_DEFAULT_LOCALE;
|
|
||||||
EMSESP::system_.locale(settings.locale);
|
|
||||||
#ifndef EMSESP_STANDALONE
|
|
||||||
if (!old_local.equals(settings.locale)) {
|
|
||||||
add_flags(ChangeFlags::RESTART); // force restart
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// these may need mqtt restart to rebuild HA discovery topics
|
// these may need mqtt restart to rebuild HA discovery topics
|
||||||
//
|
//
|
||||||
prev = settings.bool_format;
|
prev = settings.bool_format;
|
||||||
settings.bool_format = root["bool_format"] | EMSESP_DEFAULT_BOOL_FORMAT;
|
settings.bool_format = root["bool_format"] | EMSESP_DEFAULT_BOOL_FORMAT;
|
||||||
EMSESP::system_.bool_format(settings.bool_format);
|
EMSESP::system_.bool_format(settings.bool_format);
|
||||||
if (Mqtt::ha_enabled())
|
if (Mqtt::ha_enabled()) {
|
||||||
check_flag(prev, settings.bool_format, ChangeFlags::MQTT);
|
check_flag(prev, settings.bool_format, ChangeFlags::MQTT);
|
||||||
|
}
|
||||||
|
|
||||||
prev = settings.enum_format;
|
prev = settings.enum_format;
|
||||||
settings.enum_format = root["enum_format"] | EMSESP_DEFAULT_ENUM_FORMAT;
|
settings.enum_format = root["enum_format"] | EMSESP_DEFAULT_ENUM_FORMAT;
|
||||||
EMSESP::system_.enum_format(settings.enum_format);
|
EMSESP::system_.enum_format(settings.enum_format);
|
||||||
if (Mqtt::ha_enabled())
|
if (Mqtt::ha_enabled()) {
|
||||||
check_flag(prev, settings.enum_format, ChangeFlags::MQTT);
|
check_flag(prev, settings.enum_format, ChangeFlags::MQTT);
|
||||||
|
}
|
||||||
|
|
||||||
|
String old_locale = settings.locale;
|
||||||
|
settings.locale = root["locale"] | EMSESP_DEFAULT_LOCALE;
|
||||||
|
EMSESP::system_.locale(settings.locale);
|
||||||
|
if (Mqtt::ha_enabled() && !old_locale.equals(settings.locale)) {
|
||||||
|
add_flags(ChangeFlags::MQTT);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// without checks or necessary restarts...
|
// without checks or necessary restarts...
|
||||||
//
|
//
|
||||||
|
|
||||||
settings.trace_raw = root["trace_raw"] | EMSESP_DEFAULT_TRACELOG_RAW;
|
settings.trace_raw = root["trace_raw"] | EMSESP_DEFAULT_TRACELOG_RAW;
|
||||||
EMSESP::trace_raw(settings.trace_raw);
|
EMSESP::trace_raw(settings.trace_raw);
|
||||||
|
|
||||||
settings.notoken_api = root["notoken_api"] | EMSESP_DEFAULT_NOTOKEN_API;
|
settings.notoken_api = root["notoken_api"] | EMSESP_DEFAULT_NOTOKEN_API;
|
||||||
settings.solar_maxflow = root["solar_maxflow"] | EMSESP_DEFAULT_SOLAR_MAXFLOW;
|
settings.solar_maxflow = root["solar_maxflow"] | EMSESP_DEFAULT_SOLAR_MAXFLOW;
|
||||||
|
settings.boiler_heatingoff = root["boiler_heatingoff"] | EMSESP_DEFAULT_BOILER_HEATINGOFF;
|
||||||
|
|
||||||
settings.fahrenheit = root["fahrenheit"] | false;
|
settings.fahrenheit = root["fahrenheit"] | false;
|
||||||
EMSESP::system_.fahrenheit(settings.fahrenheit);
|
EMSESP::system_.fahrenheit(settings.fahrenheit);
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ class WebSettings {
|
|||||||
String locale;
|
String locale;
|
||||||
uint8_t tx_mode;
|
uint8_t tx_mode;
|
||||||
uint8_t ems_bus_id;
|
uint8_t ems_bus_id;
|
||||||
|
bool boiler_heatingoff;
|
||||||
bool shower_timer;
|
bool shower_timer;
|
||||||
bool shower_alert;
|
bool shower_alert;
|
||||||
uint8_t shower_alert_trigger;
|
uint8_t shower_alert_trigger;
|
||||||
|
|||||||
Reference in New Issue
Block a user