Compare commits

...
6 Commits
Author SHA1 Message Date
Proddy 13c32192ff Merge pull request #3323 from proddy/dev
fix HA discovery not refreshed when entity customization is cleared
2026-10-27 22:10:34 +01:00
proddy 63935c4748 fix HA discovery not refreshed when entity customization is cleared 2026-10-27 22:09:16 +01:00
Proddy 33df92fdba Merge branch 'emsesp:dev' into dev 2026-10-26 21:25:21 +01:00
Proddy 8f7049b47a Merge pull request #3316 from neonll/fix/c6-default-board-pins 2026-10-24 10:00:26 +02:00
Alexander DandClaude Opus 5.5 e1db103470 fix: give ESP32-C6 valid default GPIOs on first start
The C6 autodetect picked the CUSTOM profile, but load_board_profile() has
no entry for it, so Rx, Tx and the button stayed at the placeholder 99.
The startup settings load then failed the GPIO check and fell back to an
empty settings object (blank Board Profile, Tx Mode and Bus ID), and every
Application settings save returned 400 until valid pins were sent together
with CUSTOM through the API.

Start a C6 without a profile as CUSTOM with pins for the Seeed XIAO
ESP32-C6 (the c6_xiao_4M build): Rx GPIO20 (D9), Tx GPIO19 (D8), button
GPIO9 (BOOT), no LED, no Dallas sensor.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-23 19:39:06 +00:00
proddy 6dbb53e5af add off to RC300/RC310 nofrostmode #3311 2026-10-21 23:27:01 +02:00
16 changed files with 420 additions and 410 deletions
+6
View File
@@ -5,6 +5,12 @@ 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/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [3.9.0] Unreleased
## Fixed
- RC300/RC310 `nofrostmode` missing `off` state [#3311](https://github.com/emsesp/EMS-ESP32/issues/3311)
## [3.8.6] 24 September 2026
## Added
+1
View File
@@ -31,6 +31,7 @@ This release is based on the latest Espressif/Arduino core version 3. It brings
## Fixed
- ESP32-C6 boards without a board profile got invalid GPIOs (99), so on every start the settings were rejected and fell back to empty values (blank Board Profile, EMS Tx Mode and Bus ID), and saving any Application setting failed with a 400 error. A new C6 now starts with the CUSTOM profile and pins for the Seeed XIAO ESP32-C6: Rx GPIO20 (D9), Tx GPIO19 (D8), button GPIO9
- heat-pump operating state (`hpoperatingstate`: heating/off/cooling) is published for every heating circuit. On BC400/UI800 it was only filled for hc1, because hc2 never answers telegram 0x472 while the state is still broadcast in 0x2A6 offset 20 [#3097](https://github.com/emsesp/EMS-ESP32/issues/3097)
- restart from the WebUI (Restart button, firmware/settings upload) only happened while the browser tab stayed open. If the tab was closed the restart was silently dropped after 5 minutes, leaving a new firmware uninstalled. EMS-ESP now restarts on its own if the WebUI hasn't picked up the pending restart within 10 seconds
- a firmware upload from a script or `curl` was accepted (`md5_ok`) but EMS-ESP didn't restart into it: the client closing the connection after the upload was treated as an aborted upload, which cancelled the pending restart
+5 -5
View File
@@ -4084,7 +4084,7 @@ device name,device type,product id,shortname,fullname,type [options...] \| (min/
"UI800, BC400",thermostat,4,hc1.roominfluence,room influence,uint8 (>=0<=0),C,true,number.thermostat_hc1_room_influence,number.thermostat_hc1_roominfluence,7,1,1,14,1
"UI800, BC400",thermostat,4,hc1.roominflfactor,room influence factor,uint8 (>=0<=0), ,true,number.thermostat_hc1_room_influence_factor,number.thermostat_hc1_roominflfactor,7,1,1/10,15,1
"UI800, BC400",thermostat,4,hc1.curroominfl,current room influence,int16,C,false,sensor.thermostat_hc1_current_room_influence,sensor.thermostat_hc1_curroominfl,7,1,1/10,16,1
"UI800, BC400",thermostat,4,hc1.nofrostmode,nofrost mode,enum [room\|outdoor\|room outdoor] (>=0<=0), ,true,select.thermostat_hc1_nofrost_mode,select.thermostat_hc1_nofrostmode,7,1,1,17,1
"UI800, BC400",thermostat,4,hc1.nofrostmode,nofrost mode,enum [off\|room\|outdoor\|room outdoor] (>=0<=0), ,true,select.thermostat_hc1_nofrost_mode,select.thermostat_hc1_nofrostmode,7,1,1,17,1
"UI800, BC400",thermostat,4,hc1.nofrosttemp,nofrost temperature,int8 (>=0<=0),C,true,number.thermostat_hc1_nofrost_temperature,number.thermostat_hc1_nofrosttemp,7,1,1,18,1
"UI800, BC400",thermostat,4,hc1.targetflowtemp,target flow temperature,uint8,C,false,sensor.thermostat_hc1_target_flow_temperature,sensor.thermostat_hc1_targetflowtemp,7,1,1,19,1
"UI800, BC400",thermostat,4,hc1.heatingtype,heating type,enum [off\|radiator\|convector\|floor] (>=0<=0), ,true,select.thermostat_hc1_heating_type,select.thermostat_hc1_heatingtype,7,1,1,20,1
@@ -4476,7 +4476,7 @@ device name,device type,product id,shortname,fullname,type [options...] \| (min/
"RC200, CW100, CR120, CR50",thermostat,157,hc1.roominfluence,room influence,uint8 (>=0<=0),C,true,number.thermostat_hc1_room_influence,number.thermostat_hc1_roominfluence,7,1,1,14,1
"RC200, CW100, CR120, CR50",thermostat,157,hc1.roominflfactor,room influence factor,uint8 (>=0<=0), ,true,number.thermostat_hc1_room_influence_factor,number.thermostat_hc1_roominflfactor,7,1,1/10,15,1
"RC200, CW100, CR120, CR50",thermostat,157,hc1.curroominfl,current room influence,int16,C,false,sensor.thermostat_hc1_current_room_influence,sensor.thermostat_hc1_curroominfl,7,1,1/10,16,1
"RC200, CW100, CR120, CR50",thermostat,157,hc1.nofrostmode,nofrost mode,enum [room\|outdoor\|room outdoor] (>=0<=0), ,true,select.thermostat_hc1_nofrost_mode,select.thermostat_hc1_nofrostmode,7,1,1,17,1
"RC200, CW100, CR120, CR50",thermostat,157,hc1.nofrostmode,nofrost mode,enum [off\|room\|outdoor\|room outdoor] (>=0<=0), ,true,select.thermostat_hc1_nofrost_mode,select.thermostat_hc1_nofrostmode,7,1,1,17,1
"RC200, CW100, CR120, CR50",thermostat,157,hc1.nofrosttemp,nofrost temperature,int8 (>=0<=0),C,true,number.thermostat_hc1_nofrost_temperature,number.thermostat_hc1_nofrosttemp,7,1,1,18,1
"RC200, CW100, CR120, CR50",thermostat,157,hc1.targetflowtemp,target flow temperature,uint8,C,false,sensor.thermostat_hc1_target_flow_temperature,sensor.thermostat_hc1_targetflowtemp,7,1,1,19,1
"RC200, CW100, CR120, CR50",thermostat,157,hc1.heatingtype,heating type,enum [off\|radiator\|convector\|floor] (>=0<=0), ,true,select.thermostat_hc1_heating_type,select.thermostat_hc1_heatingtype,7,1,1,20,1
@@ -4571,7 +4571,7 @@ device name,device type,product id,shortname,fullname,type [options...] \| (min/
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.roominfluence,room influence,uint8 (>=0<=0),C,true,number.thermostat_hc1_room_influence,number.thermostat_hc1_roominfluence,7,1,1,14,1
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.roominflfactor,room influence factor,uint8 (>=0<=0), ,true,number.thermostat_hc1_room_influence_factor,number.thermostat_hc1_roominflfactor,7,1,1/10,15,1
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.curroominfl,current room influence,int16,C,false,sensor.thermostat_hc1_current_room_influence,sensor.thermostat_hc1_curroominfl,7,1,1/10,16,1
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.nofrostmode,nofrost mode,enum [room\|outdoor\|room outdoor] (>=0<=0), ,true,select.thermostat_hc1_nofrost_mode,select.thermostat_hc1_nofrostmode,7,1,1,17,1
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.nofrostmode,nofrost mode,enum [off\|room\|outdoor\|room outdoor] (>=0<=0), ,true,select.thermostat_hc1_nofrost_mode,select.thermostat_hc1_nofrostmode,7,1,1,17,1
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.nofrosttemp,nofrost temperature,int8 (>=0<=0),C,true,number.thermostat_hc1_nofrost_temperature,number.thermostat_hc1_nofrosttemp,7,1,1,18,1
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.targetflowtemp,target flow temperature,uint8,C,false,sensor.thermostat_hc1_target_flow_temperature,sensor.thermostat_hc1_targetflowtemp,7,1,1,19,1
"RC3*0, Moduline 3000/1010H, CW400, Sense II, HPC410",thermostat,158,hc1.heatingtype,heating type,enum [off\|radiator\|convector\|floor] (>=0<=0), ,true,select.thermostat_hc1_heating_type,select.thermostat_hc1_heatingtype,7,1,1,20,1
@@ -4677,7 +4677,7 @@ device name,device type,product id,shortname,fullname,type [options...] \| (min/
"Rego 2000/3000",thermostat,172,hc1.roominfluence,room influence,uint8 (>=0<=0),C,true,number.thermostat_hc1_room_influence,number.thermostat_hc1_roominfluence,7,1,1,14,1
"Rego 2000/3000",thermostat,172,hc1.roominflfactor,room influence factor,uint8 (>=0<=0), ,true,number.thermostat_hc1_room_influence_factor,number.thermostat_hc1_roominflfactor,7,1,1/10,15,1
"Rego 2000/3000",thermostat,172,hc1.curroominfl,current room influence,int16,C,false,sensor.thermostat_hc1_current_room_influence,sensor.thermostat_hc1_curroominfl,7,1,1/10,16,1
"Rego 2000/3000",thermostat,172,hc1.nofrostmode,nofrost mode,enum [room\|outdoor\|room outdoor] (>=0<=0), ,true,select.thermostat_hc1_nofrost_mode,select.thermostat_hc1_nofrostmode,7,1,1,17,1
"Rego 2000/3000",thermostat,172,hc1.nofrostmode,nofrost mode,enum [off\|room\|outdoor\|room outdoor] (>=0<=0), ,true,select.thermostat_hc1_nofrost_mode,select.thermostat_hc1_nofrostmode,7,1,1,17,1
"Rego 2000/3000",thermostat,172,hc1.nofrosttemp,nofrost temperature,int8 (>=0<=0),C,true,number.thermostat_hc1_nofrost_temperature,number.thermostat_hc1_nofrosttemp,7,1,1,18,1
"Rego 2000/3000",thermostat,172,hc1.targetflowtemp,target flow temperature,uint8,C,false,sensor.thermostat_hc1_target_flow_temperature,sensor.thermostat_hc1_targetflowtemp,7,1,1,19,1
"Rego 2000/3000",thermostat,172,hc1.heatingtype,heating type,enum [off\|radiator\|convector\|floor] (>=0<=0), ,true,select.thermostat_hc1_heating_type,select.thermostat_hc1_heatingtype,7,1,1,20,1
@@ -4809,7 +4809,7 @@ device name,device type,product id,shortname,fullname,type [options...] \| (min/
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.roominfluence,room influence,uint8 (>=0<=0),C,true,number.thermostat_hc1_room_influence,number.thermostat_hc1_roominfluence,7,1,1,14,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.roominflfactor,room influence factor,uint8 (>=0<=0), ,true,number.thermostat_hc1_room_influence_factor,number.thermostat_hc1_roominflfactor,7,1,1/10,15,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.curroominfl,current room influence,int16,C,false,sensor.thermostat_hc1_current_room_influence,sensor.thermostat_hc1_curroominfl,7,1,1/10,16,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.nofrostmode,nofrost mode,enum [room\|outdoor\|room outdoor] (>=0<=0), ,true,select.thermostat_hc1_nofrost_mode,select.thermostat_hc1_nofrostmode,7,1,1,17,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.nofrostmode,nofrost mode,enum [off\|room\|outdoor\|room outdoor] (>=0<=0), ,true,select.thermostat_hc1_nofrost_mode,select.thermostat_hc1_nofrostmode,7,1,1,17,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.nofrosttemp,nofrost temperature,int8 (>=0<=0),C,true,number.thermostat_hc1_nofrost_temperature,number.thermostat_hc1_nofrosttemp,7,1,1,18,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.targetflowtemp,target flow temperature,uint8,C,false,sensor.thermostat_hc1_target_flow_temperature,sensor.thermostat_hc1_targetflowtemp,7,1,1,19,1
"Rego 3000, UI800, Logamatic BC400",thermostat,253,hc1.heatingtype,heating type,enum [off\|radiator\|convector\|floor] (>=0<=0), ,true,select.thermostat_hc1_heating_type,select.thermostat_hc1_heatingtype,7,1,1,20,1
Can't render this file because it is too large.
+4 -4
View File
@@ -33,7 +33,7 @@
"@table-library/react-table-library": "4.1.15",
"alova": "^3.5.5",
"jwt-decode": "^4.0.0",
"preact": "^11.0.1",
"preact": "^11.0.2",
"react": "^19.3.1",
"react-dom": "^19.3.1",
"react-icons": "^5.7.0",
@@ -56,9 +56,9 @@
"rollup-plugin-visualizer": "^7.1.1",
"terser": "^5.51.2",
"typescript": "^6.0.3",
"typescript-eslint": "^8.72.0",
"vite": "^8.3.4",
"typescript-eslint": "^8.72.1",
"vite": "^8.3.5",
"vite-plugin-imagemin": "^0.6.1"
},
"packageManager": "pnpm@12.14.0"
"packageManager": "pnpm@12.15.0"
}
+294 -294
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -17,5 +17,5 @@
"@trivago/prettier-plugin-sort-imports": "^6.0.2",
"prettier": "^3.9.10"
},
"packageManager": "pnpm@12.14.0"
"packageManager": "pnpm@12.15.0"
}
+81 -81
View File
@@ -7,153 +7,153 @@ importers:
configDependencies: {}
packageManagerDependencies:
pnpm:
specifier: 12.14.0
version: 12.14.0
specifier: 12.15.0
version: 12.15.0
packages:
'@pnpm/exe.android-arm64@12.14.0':
resolution: {integrity: sha512-+iSh7x21C3A2hqc+Z0ZmbKTcn6YNlzrXM142PsnQH/dLj0DYxFzoBvc6XAnL/yfQ5nnH2ebBiRj/zVxr61fZbQ==}
'@pnpm/exe.android-arm64@12.15.0':
resolution: {integrity: sha512-eVCqmscY70LGvgRzu3mi8IBWBFGix+a6mNZoWmXxESsBdeiKEF9xQSuaeel10yn+zI7TXy2jlI63vFLzETk+aQ==}
cpu: [arm64]
os: [android]
'@pnpm/exe.android-x64@12.14.0':
resolution: {integrity: sha512-qT+0LqEr2wBVaxcG2T8cX/R8SSRz2Rvpp8nRR4fh8tnGUZRch87gFmsHUAoSQh7w6j1h0qTjrA384j4xi8frvw==}
'@pnpm/exe.android-x64@12.15.0':
resolution: {integrity: sha512-Gx/WbkFcdUFUg8g8AShezcS9EiQxfYvdAm2hfKLO8sfJmJvKOCt5fzlgHWDzmGhoclibgW+tUGZ/KF4F4wOTCA==}
cpu: [x64]
os: [android]
'@pnpm/exe.darwin-arm64@12.14.0':
resolution: {integrity: sha512-tnrdUB8ecJoehuKKqi1YHCBVl61xtJ9XVGcx5EviC6fWO4DeGI8GtXrjvJxDBM3nuVjJeWistgsUp/N142x4sw==}
'@pnpm/exe.darwin-arm64@12.15.0':
resolution: {integrity: sha512-N0ZykiDWCvqSBJvt71j7cSoBR993FqvYZFtmpCtqvW3pguiI+NAgraLPA5OTwu5mV+/d8hYpVcPktJA3xFDLtA==}
cpu: [arm64]
os: [darwin]
'@pnpm/exe.darwin-x64@12.14.0':
resolution: {integrity: sha512-vlBfGkruqQRsEHTW43cPwpYd7QlbIJ//cvpAdb3bVXkI8SgTPoXhCnc05m+ZNiPrrEkBsX/t7KHw9aXpkzPm3Q==}
'@pnpm/exe.darwin-x64@12.15.0':
resolution: {integrity: sha512-7Ntr2HlBUxzwWOg7NwDxCbRW/3vXuqKO+hcXm+w3SBi9rrHY53li1wLqWVT7Gjxd+lVEHM1QJZo6WJEGFU8C6A==}
cpu: [x64]
os: [darwin]
'@pnpm/exe.freebsd-x64@12.14.0':
resolution: {integrity: sha512-Qg5rxBrGYl6Tfso+EyygPf84fY1Fzy55E/0or+iuYKtnf0vc0MlHJfVIlT7pBukMRntQHRik7hUi0Z4s7AlJsw==}
'@pnpm/exe.freebsd-x64@12.15.0':
resolution: {integrity: sha512-btOiyL7fL7W4uQGH0aqFai2TNC3IoKcZ7gNHBVbEFZt2dWrnrD0SufL3iGs3fLlmb4OtuU35uf4Zpr9V9Jh9mA==}
cpu: [x64]
os: [freebsd]
'@pnpm/exe.linux-arm64-musl@12.14.0':
resolution: {integrity: sha512-DRIe4yQkXBGA/PhVJdzlbnllxBdAtnMMvTVLLcGpsK5FvJz9kxD2Hyxtn68ovmNkVX06f6p45cQwfm3wx2jn1A==}
'@pnpm/exe.linux-arm64-musl@12.15.0':
resolution: {integrity: sha512-pNC38k+O+90FOjbPNSnw0E7apq1PKTmz3fFe1amn+lys/U5kL++uzir8bRiho8ONcyA3d9EU7wdqcY0DKkj+JA==}
cpu: [arm64]
os: [linux]
libc: [musl]
'@pnpm/exe.linux-arm64@12.14.0':
resolution: {integrity: sha512-7joGShZ44Nk3WpNU+60JoOPjCXlgxhJAq11S2UiVtwCUDgTer1yTPPfxGW8pxaD6046actYLIYDbZNlubHWs0A==}
'@pnpm/exe.linux-arm64@12.15.0':
resolution: {integrity: sha512-qML/8aCXslh8td/w4U+HJNqUcZ2+m6EfTbWScIzZRmyPsRFN+xB4LP1U/hymxc1iSJiKtG56HJx2fvUErWFIGw==}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@pnpm/exe.linux-ppc64@12.14.0':
resolution: {integrity: sha512-gSoryn7ySdXd//gjgf3MvvA8ZerJayaSbuMZMtAWq4vb2/wlVEgpl0Kvqt54y58TRj533Qjq2txKgnxd4JyoAQ==}
'@pnpm/exe.linux-ppc64@12.15.0':
resolution: {integrity: sha512-tjRDUUl7RCJ6T/6eoNPxOqkwU4Mzi5RtTXmSAxujyz37OTwwsMU7Ps087Zk4gHcUvRSeyF40ZFsew3vtE+nmUA==}
cpu: [ppc64]
os: [linux]
libc: [glibc]
'@pnpm/exe.linux-riscv64@12.14.0':
resolution: {integrity: sha512-EMjew1H9WqQ7pL+tYqCPwiuB+0PeCiJRV7fyWeuFw0wwYUajFBjcaPO3IGAVu9sdmJDU+e+HYv/Zey6aKae0Vw==}
'@pnpm/exe.linux-riscv64@12.15.0':
resolution: {integrity: sha512-bF1uBWEfbwaeryz6lIiaJ8AWD082otZfvzGX5l+6LZRpRwUEpJHUsJrORaYP5/cNMv5ZR2p6TvvcJcQzwtDzmw==}
cpu: [riscv64]
os: [linux]
libc: [glibc]
'@pnpm/exe.linux-s390x@12.14.0':
resolution: {integrity: sha512-shYOj/SFoXD35fHe0pWr2JofwSXulC0BnEIXLj2QokDi0EF//AfKsui35yKIkTEl+s2VJybc3PO4iJNhKIj5Qw==}
'@pnpm/exe.linux-s390x@12.15.0':
resolution: {integrity: sha512-zKMhIzsexYMToeLmqV5jPsvV/f9vwsJb2kUH2NFYzalbxImeBrlA4kL7GwF8gD4pagV6jYYcJb8RjbZIdjHptg==}
cpu: [s390x]
os: [linux]
libc: [glibc]
'@pnpm/exe.linux-x64-musl@12.14.0':
resolution: {integrity: sha512-btZiZ2Ot0llKK1ndSfA5i3IRX7/S0VrmzseNH/BJ4c+Cady+S81H6vvU1zByggHMyqQhC8OgxO5PiIY7D9bH0Q==}
'@pnpm/exe.linux-x64-musl@12.15.0':
resolution: {integrity: sha512-A9J0Jg0Rdx+qQU4qXtwyST5tto9IOu1zi4fDk35nbc6DWahggbcKtFvZPKFwL2qgUXGXOX//hXv6z/sp6emO8A==}
cpu: [x64]
os: [linux]
libc: [musl]
'@pnpm/exe.linux-x64@12.14.0':
resolution: {integrity: sha512-F6K8e/jWxiuEYJaQtRRUG9ynBSTEHa+t7Lf86MKuOO5UA7WVVMbi+oB8nY6iKW++ncWS2yG6T9faXZGxqNsfoQ==}
'@pnpm/exe.linux-x64@12.15.0':
resolution: {integrity: sha512-yc+QlZR+9+nr29J4fRzhMoapgxTBDndq/+peyoq1XUufnQFnfbXUMFudDIKzHi545linGqmOmXfn0NoufNgcOg==}
cpu: [x64]
os: [linux]
libc: [glibc]
'@pnpm/exe.win32-arm64@12.14.0':
resolution: {integrity: sha512-DOjlkVB6TtTKeAAe0hNZXn5S7YqESmo1Z6SGbR4BZNQ4isRg31XVHjX2RFTbY8gnZq68IwzyLmPqlEjMmYxofg==}
'@pnpm/exe.win32-arm64@12.15.0':
resolution: {integrity: sha512-fPXZxuY1VclkOga9bc53qNCXcegfeoBR8+Ue+AospDwKzuGGSHll0oDxkLfkmpjyRqpe7bH5DyQPYp/xSMaIVA==}
cpu: [arm64]
os: [win32]
'@pnpm/exe.win32-x64@12.14.0':
resolution: {integrity: sha512-/LSX6mew/sLf08XqcjemuklNKf1K/Ftpgj4//hK/HKzI2dKbmxDB27a/2OaQ5a0O3/3OFzlssXDziZsi+yVBwQ==}
'@pnpm/exe.win32-x64@12.15.0':
resolution: {integrity: sha512-nrd+Tp1We1DGj4DGG5Bea9lZNh9y1PjlLBdEwdInS4D0h0UIDtM7JaGGGDJhNzIwcHASyihWI7HLV+dtG+fhYg==}
cpu: [x64]
os: [win32]
pnpm@12.14.0:
resolution: {integrity: sha512-wYum2HmT09Fky16JSPMrLAbuhUSH4GzY2GeBNC+z5btGNDZwNHEehoArqpw3vqkGzhkprQjXCITJfYAd8TOJpg==}
engines: {node: '>=18.*'}
pnpm@12.15.0:
resolution: {integrity: sha512-s5UdbW/0qfE9x89WzSjSuOs328ycaOUuHhGRhz6p+CoBcoerULqtxczElPA2xnwOR+sTYIwvo29HcRth6hKOYQ==}
engines: {node: '>=18'}
hasBin: true
snapshots:
'@pnpm/exe.android-arm64@12.14.0':
'@pnpm/exe.android-arm64@12.15.0':
optional: true
'@pnpm/exe.android-x64@12.14.0':
'@pnpm/exe.android-x64@12.15.0':
optional: true
'@pnpm/exe.darwin-arm64@12.14.0':
'@pnpm/exe.darwin-arm64@12.15.0':
optional: true
'@pnpm/exe.darwin-x64@12.14.0':
'@pnpm/exe.darwin-x64@12.15.0':
optional: true
'@pnpm/exe.freebsd-x64@12.14.0':
'@pnpm/exe.freebsd-x64@12.15.0':
optional: true
'@pnpm/exe.linux-arm64-musl@12.14.0':
'@pnpm/exe.linux-arm64-musl@12.15.0':
optional: true
'@pnpm/exe.linux-arm64@12.14.0':
'@pnpm/exe.linux-arm64@12.15.0':
optional: true
'@pnpm/exe.linux-ppc64@12.14.0':
'@pnpm/exe.linux-ppc64@12.15.0':
optional: true
'@pnpm/exe.linux-riscv64@12.14.0':
'@pnpm/exe.linux-riscv64@12.15.0':
optional: true
'@pnpm/exe.linux-s390x@12.14.0':
'@pnpm/exe.linux-s390x@12.15.0':
optional: true
'@pnpm/exe.linux-x64-musl@12.14.0':
'@pnpm/exe.linux-x64-musl@12.15.0':
optional: true
'@pnpm/exe.linux-x64@12.14.0':
'@pnpm/exe.linux-x64@12.15.0':
optional: true
'@pnpm/exe.win32-arm64@12.14.0':
'@pnpm/exe.win32-arm64@12.15.0':
optional: true
'@pnpm/exe.win32-x64@12.14.0':
'@pnpm/exe.win32-x64@12.15.0':
optional: true
pnpm@12.14.0:
pnpm@12.15.0:
optionalDependencies:
'@pnpm/exe.android-arm64': 12.14.0
'@pnpm/exe.android-x64': 12.14.0
'@pnpm/exe.darwin-arm64': 12.14.0
'@pnpm/exe.darwin-x64': 12.14.0
'@pnpm/exe.freebsd-x64': 12.14.0
'@pnpm/exe.linux-arm64': 12.14.0
'@pnpm/exe.linux-arm64-musl': 12.14.0
'@pnpm/exe.linux-ppc64': 12.14.0
'@pnpm/exe.linux-riscv64': 12.14.0
'@pnpm/exe.linux-s390x': 12.14.0
'@pnpm/exe.linux-x64': 12.14.0
'@pnpm/exe.linux-x64-musl': 12.14.0
'@pnpm/exe.win32-arm64': 12.14.0
'@pnpm/exe.win32-x64': 12.14.0
'@pnpm/exe.android-arm64': 12.15.0
'@pnpm/exe.android-x64': 12.15.0
'@pnpm/exe.darwin-arm64': 12.15.0
'@pnpm/exe.darwin-x64': 12.15.0
'@pnpm/exe.freebsd-x64': 12.15.0
'@pnpm/exe.linux-arm64': 12.15.0
'@pnpm/exe.linux-arm64-musl': 12.15.0
'@pnpm/exe.linux-ppc64': 12.15.0
'@pnpm/exe.linux-riscv64': 12.15.0
'@pnpm/exe.linux-s390x': 12.15.0
'@pnpm/exe.linux-x64': 12.15.0
'@pnpm/exe.linux-x64-musl': 12.15.0
'@pnpm/exe.win32-arm64': 12.15.0
'@pnpm/exe.win32-x64': 12.15.0
---
lockfileVersion: '9.0'
@@ -194,16 +194,16 @@ packages:
resolution: {integrity: sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==}
engines: {node: '>=6.9.0'}
'@babel/helper-string-parser@7.29.7':
resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==}
'@babel/helper-string-parser@7.29.11':
resolution: {integrity: sha512-snZbO7MEDOof+hvNa97EjEY7qD7h2kwvQr5AJC3ZhQudKW5dnej6k3kP9NQV88hJwaS8vDqRLFo9rivLEhle2g==}
engines: {node: '>=6.9.0'}
'@babel/helper-validator-identifier@7.29.7':
resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==}
engines: {node: '>=6.9.0'}
'@babel/parser@7.29.9':
resolution: {integrity: sha512-CjXrNHTnvqBVqHgdBysY3vk2T8tpJHb5/RMeHJBTyVa9xgugCB0CJTx/3oO8RV2QRQP391RWpB7D6hLjm8V9uA==}
'@babel/parser@7.29.11':
resolution: {integrity: sha512-OZ6+oaK7GMyg3IfCpj8JOmn8n+w2rJbDT0LLfVDTLb1ZFeKDh3AiNELgCMUw175IJHSkLl74hG0M0VLsvx+gag==}
engines: {node: '>=6.0.0'}
hasBin: true
@@ -215,8 +215,8 @@ packages:
resolution: {integrity: sha512-B3lYAs2nkKskbgQ1nfy8Ma9ao9Q1rntTAQHrzzyDuj+TSO+X3le6PfWwqDvodsb+OumE10eMFfuMCTQSQ5iuIQ==}
engines: {node: '>=6.9.0'}
'@babel/types@7.29.8':
resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==}
'@babel/types@7.29.11':
resolution: {integrity: sha512-WCsemW40Cpc6gouC1SrY6PBaZ+oLRlEVY9XBvZBI7il/HyUrb2nJ505wE1MHEFyDZNnrWDEuy4jL50WVHfTTSQ==}
engines: {node: '>=6.9.0'}
'@jridgewell/gen-mapping@0.3.13':
@@ -318,43 +318,43 @@ snapshots:
'@babel/generator@7.29.8':
dependencies:
'@babel/parser': 7.29.9
'@babel/types': 7.29.8
'@babel/parser': 7.29.11
'@babel/types': 7.29.11
'@jridgewell/gen-mapping': 0.3.13
'@jridgewell/trace-mapping': 0.3.31
jsesc: 3.1.0
'@babel/helper-globals@7.29.7': {}
'@babel/helper-string-parser@7.29.7': {}
'@babel/helper-string-parser@7.29.11': {}
'@babel/helper-validator-identifier@7.29.7': {}
'@babel/parser@7.29.9':
'@babel/parser@7.29.11':
dependencies:
'@babel/types': 7.29.8
'@babel/types': 7.29.11
'@babel/template@7.29.7':
dependencies:
'@babel/code-frame': 7.29.7
'@babel/parser': 7.29.9
'@babel/types': 7.29.8
'@babel/parser': 7.29.11
'@babel/types': 7.29.11
'@babel/traverse@7.29.10':
dependencies:
'@babel/code-frame': 7.29.7
'@babel/generator': 7.29.8
'@babel/helper-globals': 7.29.7
'@babel/parser': 7.29.9
'@babel/parser': 7.29.11
'@babel/template': 7.29.7
'@babel/types': 7.29.8
'@babel/types': 7.29.11
debug: 4.4.3
transitivePeerDependencies:
- supports-color
'@babel/types@7.29.8':
'@babel/types@7.29.11':
dependencies:
'@babel/helper-string-parser': 7.29.7
'@babel/helper-string-parser': 7.29.11
'@babel/helper-validator-identifier': 7.29.7
'@jridgewell/gen-mapping@0.3.13':
@@ -376,9 +376,9 @@ snapshots:
'@trivago/prettier-plugin-sort-imports@6.0.2(prettier@3.9.10)':
dependencies:
'@babel/generator': 7.29.8
'@babel/parser': 7.29.9
'@babel/parser': 7.29.11
'@babel/traverse': 7.29.10
'@babel/types': 7.29.8
'@babel/types': 7.29.11
javascript-natural-sort: 0.7.1
lodash-es: 4.18.1
minimatch: 9.0.9
+1 -1
View File
@@ -3820,7 +3820,7 @@ const emsesp_devicedata_10 = {
u: 0,
id: '00hc1 nofrost mode',
c: 'hc1/nofrostmode',
l: ['room', 'outdoor', 'room outdoor']
l: ['off', 'room', 'outdoor', 'room outdoor']
},
{
v: 2,
+2 -1
View File
@@ -1357,4 +1357,5 @@ recognises
POWERON
crashtest
otadata
merase
merase
Seeed
+8 -11
View File
@@ -1337,13 +1337,14 @@ void EMSdevice::setCustomizationEntity(const std::string & entity_id) {
if (entity_name == shortname) {
// check the masks
uint8_t current_mask = dv.state >> 4;
uint8_t new_mask = Helpers::hextoint(entity_id.substr(0, 2).c_str()); // first character contains mask flags
bool had_limit = dv.custom_fullname().find('>') != std::string::npos || dv.custom_fullname().find('<') != std::string::npos;
uint8_t current_mask = dv.state >> 4;
uint8_t new_mask = Helpers::hextoint(entity_id.substr(0, 2).c_str()); // first character contains mask flags
bool had_limit = dv.custom_fullname().find('>') != std::string::npos || dv.custom_fullname().find('<') != std::string::npos;
std::string new_custom_name = has_custom_name ? entity_id.substr(custom_name_pos + 1) : std::string{};
// if it's a new mask, reconfigure HA
if (Mqtt::ha_enabled() && (has_custom_name || ((current_mask ^ new_mask) & (DeviceValueState::DV_READONLY >> 4)))) {
// remove ha config on change of dv_readonly flag
// reconfigure HA on a new name or limits (also when cleared), or a change of the dv_readonly flag
if (Mqtt::ha_enabled()
&& (has_custom_name || new_custom_name != dv.custom_fullname() || ((current_mask ^ new_mask) & (DeviceValueState::DV_READONLY >> 4)))) {
dv.remove_state(DeviceValueState::DV_HA_CONFIG_CREATED);
Mqtt::publish_ha_sensor_config_dv(dv, "", "", "", true); // delete topic (remove = true)
}
@@ -1352,11 +1353,7 @@ void EMSdevice::setCustomizationEntity(const std::string & entity_id) {
dv.state = ((dv.state & 0x0F) | (new_mask << 4)); // set state high bits to flag
// set the custom name if it has one, or clear it
if (has_custom_name) {
dv.set_custom_fullname(entity_id.substr(custom_name_pos + 1));
} else {
dv.set_custom_fullname("");
}
dv.set_custom_fullname(new_custom_name);
// Climate discovery reads its own min/max. selRoomTemp keeps the register limits.
// A custom range is copied across; clearing it restores the limits haclimate was registered with (5..30).
+7 -7
View File
@@ -1803,12 +1803,10 @@ void EMSESP::incoming_telegram(uint8_t * data, const uint8_t length) {
#endif
// check for poll to us, if so send top message from Tx queue immediately and quit
#ifdef EMSESP_GATEWAY_TX_HOLD
// while the gateway is syncing, don't Tx anything (including Roomctrl) — only ack our own poll
// so the master keeps us in 0x07 and the gateway doesn't see the device list change
// while the gateway is syncing, mute ALL Tx including poll ACKs (#3094 19d).
// 19c still A21'd with ACK-only traffic; this tests whether that was enough to break HomeCom.
// risk: master may drop us from 0x07 while held — expect that in the log/status.
if (gateway_tx_hold()) {
if (poll_id == EMSbus::ems_bus_id()) {
txservice_.send_poll();
}
return;
}
#endif
@@ -1870,7 +1868,9 @@ void EMSESP::scheduled_fetch_values() {
void EMSESP::gateway_note_activity() {
uint32_t now = uuid::get_uptime();
if (gateway_last_seen_ && (now - gateway_last_seen_ > GATEWAY_SILENCE_MS)) {
LOG_INFO("Gateway 0x%02X returned after %lu s silence, holding Tx", EMSdevice::EMS_DEVICE_ID_GATEWAY1, (unsigned long)((now - gateway_last_seen_) / 1000));
LOG_INFO("Gateway 0x%02X returned after %lu s silence, holding Tx (incl. poll ACK)",
EMSdevice::EMS_DEVICE_ID_GATEWAY1,
(unsigned long)((now - gateway_last_seen_) / 1000));
if (!gateway_hold_until_) {
gateway_hold_start_ = now;
gateway_hold_max_log_ = 0;
@@ -1925,7 +1925,7 @@ void EMSESP::gateway_tx_hold_start() {
if (!gateway_hold_until_) {
gateway_hold_start_ = now;
gateway_hold_max_log_ = 0;
LOG_INFO("Gateway 0x%02X is busy, holding Tx", EMSdevice::EMS_DEVICE_ID_GATEWAY1);
LOG_INFO("Gateway 0x%02X is busy, holding Tx (incl. poll ACK)", EMSdevice::EMS_DEVICE_ID_GATEWAY1);
}
gateway_hold_until_ = (now + GATEWAY_HOLD_TIME) | 1; // 0 means no hold
+1 -1
View File
@@ -297,7 +297,7 @@ class EMSESP {
static constexpr uint8_t EMS_WAIT_KM_TIMEOUT = 60; // wait one minute
#ifdef EMSESP_GATEWAY_TX_HOLD
// hold our Tx while a gateway (K30RF/KM200 on 0x48) is doing its startup sync, see issue #3094
// hold our Tx (and poll ACKs, since 19d) while a gateway (K30RF/KM200 on 0x48) is syncing — see #3094
// a startup sync is 55-250 read requests/min to other devices, normal operation is <10/min
static void gateway_rx_check(const uint8_t * data, const uint8_t length);
static void gateway_note_activity(); // poll or telegram from 0x48 — re-arm hold if it was silent
+1 -1
View File
@@ -368,7 +368,7 @@ MAKE_ENUM(enum_modetype5, FL_(off), FL_(on))
MAKE_ENUM(enum_reducemode, FL_(nofrost), FL_(reduce), FL_(room), FL_(outdoor))
MAKE_ENUM(enum_reducemode1, FL_(outdoor), FL_(room), FL_(reduce)) // RC310 values: 1-3
MAKE_ENUM(enum_nofrostmode, FL_(off), FL_(outdoor), FL_(room))
MAKE_ENUM(enum_nofrostmode1, FL_(room), FL_(outdoor), FL_(room_outdoor))
MAKE_ENUM(enum_nofrostmode1, FL_(off), FL_(room), FL_(outdoor), FL_(room_outdoor)) // RC300/RC310: 0-3
MAKE_ENUM(enum_controlmode, FL_(optimized), FL_(simple), FL_(na), FL_(room), FL_(power))
MAKE_ENUM(enum_controlmode1, FL_(weather_compensated), FL_(outside_basepoint), FL_(na), FL_(room), FL_(power), FL_(constant)) // RC310 1-4
+2 -2
View File
@@ -1393,7 +1393,7 @@ void Thermostat::process_RC300Curve(const std::shared_ptr<const Telegram> & tele
has_enumupdate(telegram, hc->controlmode, 0, 1); // 1-weather_compensated, 2-outside_footpoint,3-n/a, 4-room -- RC310
has_update(telegram, hc->heatingtype, 1); // 1=radiator, 2=convector, 3=floor
has_update(telegram, hc->switchonoptimization, 4);
has_enumupdate(telegram, hc->nofrostmode, 5, 1); // 1-room, 2-outdoor, 3- room & outdoor
has_update(telegram, hc->nofrostmode, 5); // 0-off, 1-room, 2-outdoor, 3-room & outdoor
has_update(telegram, hc->nofrosttemp, 6);
if (hc->heatingtype < 3) {
@@ -3925,7 +3925,7 @@ bool Thermostat::set_nofrostmode(const char * value, const int8_t id) {
uint8_t set;
if (isRC300() || model() == EMSdevice::EMS_DEVICE_FLAG_RC100) {
if (Helpers::value2enum(value, set, FL_(enum_nofrostmode1))) {
write_command(curve_typeids[hc->hc()], 5, set + 1, curve_typeids[hc->hc()]);
write_command(curve_typeids[hc->hc()], 5, set, curve_typeids[hc->hc()]);
return true;
}
} else {
+1 -1
View File
@@ -1 +1 @@
#define EMSESP_APP_VERSION "3.9.0-dev.20"
#define EMSESP_APP_VERSION "3.9.0-dev.21"
+5
View File
@@ -525,7 +525,12 @@ void WebSettings::set_board_profile(WebSettings & settings) {
#elif CONFIG_IDF_TARGET_ESP32S3
settings.board_profile = "S32S3"; // BBQKees Gateway S3
#elif CONFIG_IDF_TARGET_ESP32C6
// there is no C6 board profile, so start as CUSTOM with pins that suit the Seeed XIAO ESP32-C6 (the c6_xiao_4M build).
// load_board_profile() has no entry for CUSTOM, so without these the GPIOs stay at 99, every settings update
// fails the GPIO check and the settings fall back to empty values.
// Rx D9 (GPIO20), Tx D8 (GPIO19), button BOOT (GPIO9), no LED (the onboard LED on GPIO15 is active low), no Dallas
settings.board_profile = "CUSTOM";
data = {0, 0, 20, 19, 9, PHY_type::PHY_TYPE_NONE, 0, 0, 0, 0};
#endif
// apply the new board profile setting
System::load_board_profile(data, settings.board_profile.c_str());