Repository navigation
Conversation
A control may now declare asset, strategy, zone and write timings in the
thermal contract's vocabulary, and a driver may list the metrics that are
a heat store's temperature. /api/drivers/{name} exposes both. Nothing
plans for or sends a heat command because of them; this is the
declaration step of the proposal in srcfl#1994.
A string control may declare a closed set of options, which the control
API now enforces. A misdeclared thermal field drops the control, as an
unrenderable declaration already does. nestedBlock now requires the whole
field name, so temp_sensors is not read as sensors.
Refs srcfl#520
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: hannesb90 <bruhn90@gmail.com>
This was referenced Nov 10, 2026
The owner's answer on srcfl#1994: planned control needs the device to fall back on its own through a device-side timed hold; otherwise planned values stay a small step from the device default. A control may now declare device_hold_max_s, and a number input its default, so Core can own that lease rule. A zero or non-numeric hold, or a default outside min..max or on a non-number input, drops the control. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: hannesb90 <bruhn90@gmail.com>
6 tasks done
TestWatchedPathsCoverImports fails once drivers imports thermal, since a change there would skip the rig. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem and result
Step 1 of the proposal in #1994 (ADR 0012), toward #520. Core cannot tell
what a declared control does to heat, or which metric is a room's or a
tank's temperature, so nothing can reason about heat devices without knowing
them by name. This adds that declaration, and only that.
asset(space_heat,dhw,cooling,buffer),strategy(curve_offset,setpoint,on_off,discrete_mode),zone,min_interval_s, and foron_offonly,min_on_sandmin_off_s. Thevocabulary is the existing
thermalpackage's;on_offis added there.device_hold_max_s: the device itself keeps a commanded value at most thatlong and then returns to its own regulation, so it falls back even if FTW
stops. A number input may declare its
default, the value the device runsat by itself, which "a small step from the device default" is measured
from. A zero or non-numeric hold, or a default outside
min..maxor on anon-number input, drops the control.
sensors = { { metric, asset, zone } }, naming metricsit already emits.
options.POST /api/drivers/{name}/controlnow refuses a value outside them with a 400, without sending it.
GET /api/drivers/{name}returnscontrols[].thermal,controls[].input.optionsandsensors, each omitted when not declared.Scope and safety
Nothing plans for, schedules or sends a heat command because of these
fields. The operator control path is unchanged apart from the options check.
That covers a strategy that does not fit the input type, an unknown asset,
a half declaration, or a timing that is negative, fractional, over a week
or written as a string. A later planner should never trust a wrong
strategy, or miss a compressor's minimum off time because it was a string.
A malformed sensor is dropped on its own.
exactly as before, and its JSON has no
thermalkey. The bundled catalogtest still passes.
nestedBlockmatched a name anywhere, sotemp_sensors = {would have been read assensors, andmy_controlsascontrols. It now requires the whole name.web/heating.js; this PRdoes not.
Verification
Run on a Raspberry Pi 4 (linux/arm64), Go 1.26.10, against
masterat7350a3ewith the pinned drivers fetched:The full
make verifydid not run locally; CI covers it. No hardware isinvolved, because no device behaviour changes.
Checklist
🤖 Generated with Claude Code