Test power spikes, calm wind and restart of the new model layers
A single 5-minute +700 W spike moves the room's thermal response by at most 0.2 kW and leaves the baseline at the persistent load. In calm air the wind terms vanish while natural ventilation remains. Extended and ventilation coefficients and heat-source baselines survive a restart unchanged (no hour of baseline re-learning), and enabling an extra ventilation term later keeps everything learned for the others. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b1577a0c78
commit
e62798dc4f
3 files changed
+45
No files matched your search
@@ -1033,3 +1033,36 @@ class BoundaryTests(unittest.IsolatedAsyncioTestCase):
|
||||
for zone, other in (('living', 'bed'), ('bed', 'living')):
|
||||
with self.subTest(zone=zone):
|
||||
self.assertLess(c.extended[zone].coefficient(f'couple:{other}'), 0.002)
|
||||
|
||||
async def test_new_model_layers_survive_a_restart(self):
|
||||
self.c = self.bedroom_with_window()
|
||||
self.c.entry.subentries['h'] = types.SimpleNamespace(subentry_id='h', subentry_type='heat_source', data={
|
||||
'key': 'ups', 'name': 'UPS', 'sensor': 'sensor.ups_power', 'zone': 'bed'})
|
||||
self.set_state('sensor.ups_power', '200', unit_of_measurement='W')
|
||||
self.c = coordinator.HeatingMPCCoordinator(self.hass, self.entry)
|
||||
for k in range(20):
|
||||
self.fresh('sensor.room', 'sensor.outside', 'sensor.wind', 'sensor.wind_dir', 'sensor.ups_power')
|
||||
if k == 18:
|
||||
self.open_window('on', 240)
|
||||
await self.sample()
|
||||
extended, vent = self.c.extended['bed'], self.c.ventilation['bed']
|
||||
self.assertGreater(extended.count, 0)
|
||||
self.assertGreater(vent.count, 0)
|
||||
payload = self.c._store.async_save.call_args.args[0]
|
||||
restored = coordinator.HeatingMPCCoordinator(self.hass, self.entry)
|
||||
restored._store.async_load.return_value = payload
|
||||
await restored.async_restore_model()
|
||||
self.assertEqual((restored.extended['bed'].theta, restored.extended['bed'].count), (extended.theta, extended.count))
|
||||
self.assertEqual((restored.ventilation['bed'].theta, restored.ventilation['bed'].count), (vent.theta, vent.count))
|
||||
self.assertEqual(restored._heat_sources._baselines['ups'].value(), 200) # no hour of re-learning
|
||||
# Adding a feature keeps what was learned for the others.
|
||||
self.entry.data['ventilation_cross'] = True
|
||||
self.entry.subentries['z2'] = types.SimpleNamespace(subentry_id='z2', subentry_type='zone', data={
|
||||
'key': 'living', 'name': 'Living', 'sensors': ['sensor.living']})
|
||||
self.entry.subentries['w2'] = types.SimpleNamespace(subentry_id='w2', subentry_type='window', data={
|
||||
'key': 'living_window', 'name': 'Living window', 'sensor': 'binary_sensor.living_window', 'zone': 'living'})
|
||||
grown = coordinator.HeatingMPCCoordinator(self.hass, self.entry)
|
||||
grown._store.async_load.return_value = payload
|
||||
await grown.async_restore_model()
|
||||
self.assertEqual(grown.ventilation['bed'].features[-1], 'vent_cross')
|
||||
self.assertEqual(grown.ventilation['bed'].theta[:-1], vent.theta)
|
||||
Reference in new issue
Block a user