diff --git a/README.md b/README.md index 3868392..dc15eea 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,9 @@ A small web page to adjust the heating per room from a phone on the home network The service keeps no saved state, so a restart during airing forgets it: **that room stays off until someone taps "Heat again"**. A target waiting to be sent is lost too. The thermostat's own frost protection still applies. - A target changed during airing is applied when it ends. -- A thermostat leaving off during airing gets off once more. If it leaves off again, someone is at the radiator, so airing ends. +- A thermostat leaving off during airing gets off once more. If it leaves off again, someone is at the radiator, so airing ends. So turning it on by hand during airing takes two tries. - Commands repeat until the thermostat confirms them, every 30 s for about 5 minutes. A target then gives up and shows the thermostat's value. Off and heat-again keep trying every 5 minutes and show a problem on the page, because giving up would mean heating with the window open or a cold room. -- A thermostat that is off with no airing is left alone, because it can turn itself off and come back. The page offers "Heat again" for it. +- A thermostat that is off with no airing is left alone, because someone may have turned it off on purpose. The page offers "Heat again" for it. ## Requirements diff --git a/internal/controller/controller.go b/internal/controller/controller.go index 45faf11..7531ec3 100644 --- a/internal/controller/controller.go +++ b/internal/controller/controller.go @@ -8,7 +8,7 @@ // All state is in memory. After a restart a room that was airing stays off until // someone taps "Heat again" on the page. // -// Four behaviours of the Sonoff TRVZB shape this code. They were measured on a +// Three behaviours of the Sonoff TRVZB shape this code. They were measured on a // real device (firmware 1.3.0): // - In system_mode off it reports its frost protection temperature as the // setpoint, and briefly keeps reporting it after going back to heat. That @@ -16,9 +16,10 @@ // - Writing a setpoint while it is off switches it back to heat, so a target // changed during that time is held until it can be sent. // - After a write it can still send a few reports with the old setpoint. -// - It can go off on its own and return by itself, so "off" doesn't mean this -// program turned it off. A room is only turned back on if this program turned -// it off, or someone asks for it. +// +// Someone can also turn a thermostat off by hand, so "off" doesn't mean this +// program turned it off. A room is only turned back on if this program turned it +// off, or someone asks for it. package controller import ( diff --git a/internal/controller/controller_test.go b/internal/controller/controller_test.go index 692aa95..61f7ae8 100644 --- a/internal/controller/controller_test.go +++ b/internal/controller/controller_test.go @@ -552,8 +552,8 @@ func TestAiringRestoresTheModeFromBefore(t *testing.T) { } } -// The thermostat is already in its own pause, so off isn't the mode to restore. -func TestAiringDuringAThermostatPauseRestoresHeat(t *testing.T) { +// The thermostat was already off, so off isn't the mode to restore. +func TestAiringWhileAlreadyOffRestoresHeat(t *testing.T) { h := newHarness(t) h.report("heat", 20) h.report("off", 7) @@ -564,7 +564,7 @@ func TestAiringDuringAThermostatPauseRestoresHeat(t *testing.T) { t.Fatalf("state = %s, want active", got) } - // Its pause ends, and off goes out again. + // It leaves off, and off goes out again. h.report("heat", 7) h.wantKinds("off") h.report("off", 7) @@ -682,7 +682,7 @@ func TestLostRestoreKeepsGoing(t *testing.T) { } } -// The thermostat can go off by itself, so only a tap turns it back on. +// Someone may have turned it off on purpose, so only a tap turns it back on. func TestRoomThatIsOffIsLeftAlone(t *testing.T) { h := newHarness(t) h.report("off", 7) diff --git a/internal/controller/room.go b/internal/controller/room.go index 3227818..36efa64 100644 --- a/internal/controller/room.go +++ b/internal/controller/room.go @@ -17,8 +17,9 @@ const ( // giving up would leave it heating with the window open, or cold. slowRetryInterval = 5 * time.Minute // maxFlips is how often a thermostat may leave off during airing. The first - // time could be its own pause ending, so off is sent again. The second time - // someone at the radiator wants heat, so airing ends. + // time off is sent again, because a single report could have another cause, + // such as the TRV's open window detection ending if that's turned on. The + // second time someone at the radiator wants heat, so airing ends. maxFlips = 2 // settleTime is how long a thermostat back from off gets to restore its own // setpoint. After that a setpoint at the frost value is simply what it's set to.