From 8c151414fd42dcc7391ded4ede342188afd3012d Mon Sep 17 00:00:00 2001 From: Fredrik Ahlgren Date: Fri, 31 Jul 2026 12:13:42 +0200 Subject: [PATCH] feat(heishamon): report electrical power, and the outdoor temperature under its canonical name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit FTW's heating view discovers a heat pump by the hp_power_w metric and shows nothing at all without it — no chart, no reading, no entry. So a driver verified against real hardware in June had no page in the product it was written for. hp_power_w now comes from main/Heat_Power_Consumption, which config power_topic overrides for a Heishamon build that names the topic differently. It is emitted only once that topic has arrived, so a wrong name costs the power reading and leaves every other metric alone. hp_outside_temp_c becomes hp_outdoor_temp_c, the name nibe_local and myuplink report and the one the view charts. Nothing read the old name. History under it stays where it is and stops growing. The DRIVER version said 0.4.0 while the manifest said 0.5.0; make bump-driver takes both to 0.6.0. The example config's MQTT password looked real enough to be one, and is now a placeholder. Co-Authored-By: Claude Opus 5 Signed-off-by: Fredrik Ahlgren --- CHANGELOG.md | 5 +++++ SUPPORT_STATUS.md | 4 ++-- devices.yaml | 2 +- drivers/lua/heishamon.lua | 28 +++++++++++++++++++++++----- index.yaml | 6 +++--- manifests/heishamon.yaml | 6 +++--- support-status.json | 2 +- 7 files changed, 38 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e9191e..f33de4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ Driver versions follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html ## [Unreleased] +### Added +- **heishamon** 0.6.0 — **the pump now reports its electrical draw, and its outdoor temperature under the name every other heat pump uses.** FTW's heating view finds a heat pump by `hp_power_w` and finds nothing else if that metric is absent, so a working, hardware-verified driver had no page at all: not a chart, not a reading, not an entry. It emits `hp_power_w` from `main/Heat_Power_Consumption`, which `power_topic` overrides for a Heishamon build that names it differently, and only once that topic has arrived — a wrong name costs the power reading and nothing else. `hp_outside_temp_c` becomes `hp_outdoor_temp_c`, which is what nibe_local and myuplink report and what the view charts; the old name was read by nobody. Existing history under the old key stays where it is and stops growing +- The Lua `DRIVER` version said 0.4.0 while the manifest said 0.5.0. Both now say 0.6.0. The drift was invisible because nothing compares them outside `make bump-driver` +- The example config carried what reads like a real MQTT password. It is now a placeholder + ### Fixed - **sungrow** 1.5.6 — **the zero-power refusal is restored. 1.5.4 was wrong, on a premise that did not survive reading the driver.** The case for waving zero through was that it hands the device back to itself, so refusing it could strand an inverter in a forced state. Neither half holds. `set_battery_idle` writes EMS mode **2** — forced — with command `0xCC` and setpoint 0: it pins the battery at zero under the host's control rather than releasing it. The release is `driver_default_mode`, which FTW reaches through `SendDefault` on shutdown, lease expiry and the watchdog, never through `driver_command`, and which no guard touches. So refusing withholds nothing that is not reachable by a route that cannot refuse — while accepting put mode 2 and a setpoint back on an SG inverter that implements neither, and reported success, because the read-back that would catch it fails on that device too. That is the SG12RT bug through the one action nobody guarded - The two sungrow copies disagree about what zero writes — the catalog driver forces idle at mode 2, the FTW v2 target hands the inverter back at mode 0 and clears the lease — and they use different register maps throughout. That belongs to the register-map review `packages/v1/sungrow/PILOT.md` already requires before the v2 target ships; its `verification_status` is `experimental` and the signed package builds from `targets/ftw-observe.lua`, so nothing there reaches hardware today. Recorded because untested drift between these two files is how Pixii's 40288 came back diff --git a/SUPPORT_STATUS.md b/SUPPORT_STATUS.md index c577b4b..f2ec3c2 100644 --- a/SUPPORT_STATUS.md +++ b/SUPPORT_STATUS.md @@ -68,8 +68,8 @@ Catalog source is not proof that a target can install or run a driver. | growatt | 2.1.1 | blixt-l1 | not_assessed | — | — | not_recorded | — | not_assessed | no | | hardybarth | 1.0.1 | ftw-core | not_assessed | — | — | not_recorded | — | not_assessed | no | | hardybarth | 1.0.1 | blixt-l1 | not_assessed | — | — | not_recorded | — | not_assessed | no | -| heishamon | 0.5.0 | ftw-core | not_assessed | — | — | not_recorded | — | not_assessed | no | -| heishamon | 0.5.0 | blixt-l1 | not_assessed | — | — | not_recorded | — | not_assessed | no | +| heishamon | 0.6.0 | ftw-core | not_assessed | — | — | not_recorded | — | not_assessed | no | +| heishamon | 0.6.0 | blixt-l1 | not_assessed | — | — | not_recorded | — | not_assessed | no | | hello | 1.1.2 | ftw-core | not_assessed | — | — | not_recorded | — | not_assessed | no | | hello | 1.1.2 | blixt-l1 | not_assessed | — | — | not_recorded | — | not_assessed | no | | huawei | 2.1.1 | ftw-core | not_assessed | — | — | not_recorded | — | not_assessed | no | diff --git a/devices.yaml b/devices.yaml index a2d101b..3d4d04d 100644 --- a/devices.yaml +++ b/devices.yaml @@ -1015,7 +1015,7 @@ manufacturers: protocols: - protocol: mqtt driver: "heishamon" - version: "0.5.0" + version: "0.6.0" ders: [heatpump] control: true firmware_versions: "" diff --git a/drivers/lua/heishamon.lua b/drivers/lua/heishamon.lua index 2318aa5..c8919a2 100644 --- a/drivers/lua/heishamon.lua +++ b/drivers/lua/heishamon.lua @@ -18,12 +18,19 @@ -- host: core-mosquitto -- port: 1883 -- username: mqtt-user --- password: 42wenkel +-- password: -- config: -- base_topic: panasonic_heat_pump -- min_offset: -3 -- max_offset: 3 -- safe_offset: 0 +-- power_topic: Heat_Power_Consumption +-- +-- power_topic names the main/ topic carrying the pump's electrical draw in W. +-- Heishamon publishes it as Heat_Power_Consumption (TOP21) on the builds this +-- driver has been run against; set it if your build names it differently. The +-- driver emits hp_power_w only once that topic has arrived, so a wrong name +-- costs the power reading and nothing else. DRIVER = { host_api_min = 1, @@ -31,7 +38,7 @@ DRIVER = { id = "heishamon", name = "Panasonic Aquarea (Heishamon)", manufacturer = "Panasonic", - version = "0.4.0", + version = "0.6.0", protocols = { "mqtt" }, capabilities = { "heatpump" }, description = "Panasonic Aquarea H/J/K/L/M-series heat pump via Heishamon MQTT bridge. Controls Zone 1 heat curve offset (Z1_Heat_Request_Temp) in range -3..+3 °C.", @@ -52,6 +59,7 @@ local outlet_temp = nil local inlet_temp = nil local target_temp = nil local z1_offset = nil +local power_w = nil local last_msg_ts = 0 local STALE_AFTER_MS = 60000 @@ -60,6 +68,7 @@ local base_topic = "panasonic_heat_pump" local min_offset = -3 local max_offset = 3 local safe_offset = 0 +local power_topic = "Heat_Power_Consumption" ---------------------------------------------------------------------------- -- Lifecycle @@ -73,6 +82,7 @@ function driver_init(config) if config.min_offset then min_offset = tonumber(config.min_offset) or -3 end if config.max_offset then max_offset = tonumber(config.max_offset) or 3 end if config.safe_offset then safe_offset = tonumber(config.safe_offset) or 0 end + if config.power_topic then power_topic = config.power_topic end end -- Subscribe broadly to all Heishamon topics @@ -85,7 +95,8 @@ function driver_init(config) host.log("info", "Heishamon: initialized, base_topic=" .. base_topic .. " offset_range=[" .. min_offset .. ".." .. max_offset .. "]" - .. " safe_offset=" .. safe_offset) + .. " safe_offset=" .. safe_offset + .. " power_topic=" .. power_topic) end function driver_poll() @@ -111,6 +122,9 @@ function driver_poll() elseif msg.topic == base_topic .. "/main/Z1_Heat_Request_Temp" then z1_offset = val last_msg_ts = now + elseif msg.topic == base_topic .. "/main/" .. power_topic then + power_w = val + last_msg_ts = now end end end @@ -124,14 +138,18 @@ function driver_poll() inlet_temp = nil target_temp = nil z1_offset = nil + power_w = nil end - -- Emit metrics - if outside_temp ~= nil then host.emit_metric("hp_outside_temp_c", outside_temp, "°C") end + -- Emit metrics. Names are the ones FTW's heating view reads: it finds a + -- heat pump by hp_power_w and charts the outdoor temperature under + -- hp_outdoor_temp_c, the same names nibe_local and myuplink report. + if outside_temp ~= nil then host.emit_metric("hp_outdoor_temp_c", outside_temp, "°C") end if outlet_temp ~= nil then host.emit_metric("hp_outlet_temp_c", outlet_temp, "°C") end if inlet_temp ~= nil then host.emit_metric("hp_inlet_temp_c", inlet_temp, "°C") end if target_temp ~= nil then host.emit_metric("hp_target_temp_c", target_temp, "°C") end if z1_offset ~= nil then host.emit_metric("hp_z1_heat_offset", z1_offset, "°C") end + if power_w ~= nil then host.emit_metric("hp_power_w", power_w, "W") end return 5000 end diff --git a/index.yaml b/index.yaml index acaa556..0ac8c86 100644 --- a/index.yaml +++ b/index.yaml @@ -257,13 +257,13 @@ drivers: size_bytes: 2193 sha256: "517e086af899dc511c86b00460cd8ce052a8d4973edee8b018e5824d4b550d6e" - name: "heishamon" - version: "0.5.0" + version: "0.6.0" tier: core protocol: mqtt ders: [heatpump] control: true - size_bytes: 6973 - sha256: "01a8bc73689715531cfc0f21963c045b2144fa54715690949b44a578ee821a88" + size_bytes: 8065 + sha256: "410f947f4eca8c4ab1436604c1cdc879a94057b7f9e345fb7cc8c07e70517dc9" - name: "hello" version: "1.1.2" tier: community diff --git a/manifests/heishamon.yaml b/manifests/heishamon.yaml index 85d0263..7ec4162 100644 --- a/manifests/heishamon.yaml +++ b/manifests/heishamon.yaml @@ -1,5 +1,5 @@ name: "heishamon" -version: "0.5.0" +version: "0.6.0" tier: core author: "Sourceful Labs AB" protocol: mqtt @@ -14,9 +14,9 @@ tested_devices: notes: "Panasonic Aquarea H/J/K/L/M-series heat pump via Heishamon MQTT bridge. Controls Zone 1 heat curve offset (Z1_Heat_Request_Temp) in range -3..+3 °C." min_driver_version: "0.4.0" min_host_version: "2.0.0" -size_bytes: 6973 +size_bytes: 8065 dkb_id: "heishamon" -sha256: "01a8bc73689715531cfc0f21963c045b2144fa54715690949b44a578ee821a88" +sha256: "410f947f4eca8c4ab1436604c1cdc879a94057b7f9e345fb7cc8c07e70517dc9" signature: "" bytecode_sha256: "" diff --git a/support-status.json b/support-status.json index 90368a2..f5bd6ed 100644 --- a/support-status.json +++ b/support-status.json @@ -898,7 +898,7 @@ }, { "catalog_source": true, - "catalog_version": "0.5.0", + "catalog_version": "0.6.0", "driver_id": "heishamon", "package_id": null, "targets": {