Repository navigation
Conversation
Reads CTC's BMS register list over Modbus TCP: outdoor, flow, return, radiator, heat-pump in/out and hot-water temperatures, compressor speed and status, immersion heater power, and the heat curve settings. The controller does not answer an address it lacks, so only registers in the i250 column are read, each bounded to three failed polls. A sensor that is not fitted reads 0 or -999.9 and is reported as absent. There is no register for the compressor's electrical input, so no hp_power_w. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: hannesb90 <bruhn90@gmail.com>
miravoss26
left a comment
There was a problem hiding this comment.
Adds a read-only CTC EcoZenith i250/i255 Modbus TCP driver (metrics only, no meter, no writes) plus manifest, harness and pytest tests.
- Security: nothing found. No secrets, no new dependencies, no new hosts beyond the configured pump IP. Control registers are only listed in a trailing comment.
- Low,
ctc_ecozenith.luatank read: the header says only documented i250 registers are read, butprobe_read(REG_TANK, 3)also reads 62275, which the comment admits is not in the i250 column. You measured that the pump gives no reply for an address it lacks, so one missing register would make the whole 3-register read fail and drop the DHW top temp too. It works on your i255; worth a note in the header, or two single reads, in case another firmware behaves differently. - Nit:
s16(rps[1]) / 10and the immersion lines assumedecode_i16never returns nil. Fine for number input, no action needed. - Note: no CI checks are attached to this PR, so I could not see a green run.
Safe to merge from my read once CI has run. A human should confirm the register choice.
The lower tank setpoint (62274) and DHW top temperature (62276) were read as one three-register block, which also asked for 62275 (DHW lower), not in the i250 column. The controller gives no reply for an address it lacks, so on one without 62275 the whole read would fail and take the DHW top temperature with it. They are now two single reads, so every read is a documented i250 register, as the header says. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: hannesb90 <bruhn90@gmail.com>
|
Thanks. bce65e4 reads 62274 and 62276 singly, so no read spans 62275 any more and every read is an i250 register, as the header says. A harness case makes a read that spans 62275 fail, as the controller would without it, and checks that both values still come through; the old three-register read fails that case. Not re-run on the i255 yet. On the nit: |
miravoss26
left a comment
There was a problem hiding this comment.
New read-only Lua driver for the CTC EcoZenith i250/i255 over Modbus TCP, plus CHANGELOG, devices.yaml and SUPPORT_STATUS rows.
- Metrics only, never a meter, so no sign conversion and no double-counting against the grid meter. Declared
read_only = true, no control registers used. Good. probe_readbounding (give up after 3 failures per address, pcall around the read) is the right call for a device that times out on unknown addresses.- Units look right: kW x 100 to W for immersion, 0.1 factors elsewhere, open-sensor -999.9 and not-fitted 0 handled separately.
- Minor:
hp_poll_okis tied to the 16-register block only. If that block is given up on after 3 failures it reports 0 permanently while the single-register reads keep working. Probably fine as a health signal, but say so in a comment if intended. - Minor:
verification_noteshonestly says it has not yet been run as an FTW driver on the pump. Keep statusexperimentaluntil it has. - No secrets, no new network destinations (host comes from config).
Safe to merge from my read.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thanks. c1d7267 adds a comment at |
…ntil restart On the i255 every read failed for a while after FTW started, and the driver then left all of them alone until restart while the pump answered again. A register that misses three polls is now skipped for 1, 2, 4 ... polls, at most 20 (10 min), and read again. A harness case makes the main block fail for six polls, then answer, and checks the values come back. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Seen on hardware: after FTW restarted, every read failed for a while (most likely another client held the controller's connection), and the give-up rule then left all 14 reads alone until restart while the pump was answering again. a9d55ed backs off instead: a register that misses three polls is skipped for 1, 2, 4 ... polls, at most 20 (10 min), and then read again. A new harness case fails the main block for six polls, lets it answer, and checks the values come back. It fails on the old code. The absent-register probe now shows |
…res are 62007, the heating system 1 flow setpoint, is in the block already read and is now hp_flow_setpoint_c. Checked against the display: 62011 is the flow after the mixing valve and 62006 'Radiator Water' is the tank water it draws from. Also documents that the controller serves one Modbus client at a time, and a curve-adjustment write (61517) that moved the flow setpoint 1:1. index.yaml is regenerated for this and the two earlier driver changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
697f4d5 adds |
miravoss26
left a comment
There was a problem hiding this comment.
Read-only CTC EcoZenith i250/i255 driver over Modbus TCP, metrics only.
- Security screen: clean. Holding-register reads only (
host.modbus_read), no writes, no new network destinations, no secrets. - The per-register back-off (3 failures, then skip 1/2/4.. polls capped at 20) is a sensible answer to the timeout-per-missing-register problem, and never giving up permanently matches the observed behaviour when another client holds the connection.
- Sentinel handling (-999.9 open sensor, 0 for unfitted room/tank sensors) reads correct. Question: the 0.1 kW immersion registers (62168/62169) are metrics here, not a power stream — intended, so they don't count in site balance?
Safe to merge from my read (CI/harness not run by me).
Summary
A new read-only driver for the CTC EcoZenith i250/i255 heat pump controller
over Modbus TCP, using CTC's published BMS register list. Toward srcfl/ftw#520:
a CTC pump today reaches FTW only through the read-only MyUplink cloud driver.
It emits metrics only, never a meter, so no sign conversion is involved:
outdoor, flow, return, radiator, heat-pump in/out and hot-water temperatures,
compressor RPS and status code, immersion heater power (kW converted to W),
the heat curve's room setting, inclination and adjustment, and the room
temperature when a room sensor is fitted. Metric names follow the existing
heat pump drivers (
hp_outdoor_temp_c,hp_indoor_temp_c,hp_hw_top_temp_c,hp_inlet_temp_c,hp_outlet_temp_c).Driver evidence
ctc_ecozenith0.1.0, community tier.editions, both in
upstream_docs. Function code 3, offset 0, the listednumber is the wire address.
drivers.NewLuaDriverwithmodbus.Dial, the production client) against the pump for two polls:163 ms and 102 ms, no errors, 19 metrics, display software logged.
make test-driver ID=ctc_ecozenithandmake checkpass.absent-register-report: every address settles.invented-number-report:nothing invented.
plus a fitted room sensor, a running heater, negative and 0.0 °C outdoor
readings, an open sensor, and the main block not answering.
undocumented address gets no reply and no Modbus exception, only a
timeout, and the next connection may be reset. So only registers in the
i250 column of CTC's list are read, each through a three-strike
probe_read.-999.9 when open. Both count as absent for the room and the hot-water
tank, where 0.0 °C is not a real reading. Outdoor 0.0 °C is kept.
hp_power_w. CTC lists no register for the compressor'selectrical input. The current registers are the house's incoming phases
from the controller's own current transformers, which are not fitted on
the test site. Estimating power from RPS would be a guess.
gives no table for it.
i250 itself are untested.
Safety
Control evidence
required: not applicable, read-only.The driver ends with a comment listing CTC's 1000-series control registers,
unused here. CTC states they reset unless rewritten every 5 minutes, and on
restart. That is a device-side lease, relevant to a later, separately
reviewed control change.
Checks
Signed-off-by.make test-driver ID=ctc_ecozenithmake check(run on a Raspberry Pi 4, after unshallowing the clone,which the history check needs)
🤖 Generated with Claude Code