Repository navigation
feat!: add airing, and deliver commands by comparing desired and reported state - #7
Merged
Merged
Conversation
…rted state
A room can now be aired for 15, 30 or 60 minutes: off is sent, and at the end
or on "Heat again" the room gets back its mode and target. End times and held
targets are saved to a file, so they survive a restart.
The controller now keeps what a room should be doing apart from what its
thermostat reports. Run is the only place that publishes or saves, and repeats a
command until a report confirms it. This replaces the send lock, the flush
goroutine and the rollback code, and closes the gap where a command could be
resent after a reconnect without still being wanted.
BREAKING CHANGE: POST /api/rooms/{id}/target returns 202 instead of 204, and 502
is gone. Whether a target arrived shows in targetState in the room list.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Commands use QoS 0, because paho resends QoS 1 messages after a reconnect and a late off can undo a restore. The previous commit wrongly said this gap was closed. The controller already repeats commands until they're confirmed. - State is saved before a command goes out, so a crash can't leave a room off with no record. - A report can't confirm a restore while one from before an unconfirmed off could still arrive, and only confirms a target that was sent. - A corrupt state file is moved aside and reported through the health check. - A thermostat stuck at the frost value no longer holds a target forever. - "Heat again" also turns on a thermostat that is off with no record. - The last on mode is saved, and two rooms can't share a thermostat. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
All state is now in memory: no state file, Store interface or PVC. A restart during airing forgets it, so that room stays off until someone taps "Heat again", and a target waiting to be sent is lost. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts: # README.md
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.
Why
The last acceptance criterion: "window open / airing, don't heat" from the phone. The independent architecture review recommended reshaping the controller first, because airing needs retries, timeouts and restore after a restart.
What
openapi.yaml):POSTandDELETE /api/rooms/{id}/airing;RoomgainstargetState,airingState,airingUntil,lastSeenandcommandFailed;RoomListgainsconnected. Breaking:POST .../targetreturns 202, and 502 is gone.internal/controller: desired state separate from reported state, withroom.decidechoosing the command andController.Runthe only place that publishes or saves. Commands repeat until a report confirms them.heating_control_room_airing{room}andheating_control_room_command_failed{room}.config.clientIdis new.Additions beyond the agreed design:
targetStatealso hasfailed, there's a separatecommandFailedfield, and off and heat-again keep retrying every 5 minutes after the first 5 minutes rather than stopping, because stopping would mean heating with the window open or a cold room.Review fixes are in: QoS 0 for commands, a restore or target only confirmed when that can't be a stale report, and
DELETE .../airingalso turning on a thermostat that is off with no airing.How to validate
go test -race, golangci-lint andhelm lintpass locally. Tests drive time by hand through airing, retries and knob flips.Risk
A bug here could leave a room off or heat with a window open. The TRV's frost protection stays active as a floor, and "Heat again" works on any TRV that is off. The stuck-off alert comes in the next smart-home PR. Any pod restart during airing, including a release, leaves that room off until someone taps "Heat again". On a rollback to 0.1.0, which has no such button, the room has to be turned back on at the TRV or through MQTT.
Rollback
Set the chart back to
0.1.0in smart-home. If a room is airing, first tap "Heat again".🤖 Generated with Claude Code