juham-automation 0.0.17__py3-none-any.whl → 0.0.19__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- juham_automation/automation/hotwateroptimizer.py +70 -31
- {juham_automation-0.0.17.dist-info → juham_automation-0.0.19.dist-info}/METADATA +1 -1
- {juham_automation-0.0.17.dist-info → juham_automation-0.0.19.dist-info}/RECORD +7 -7
- {juham_automation-0.0.17.dist-info → juham_automation-0.0.19.dist-info}/WHEEL +0 -0
- {juham_automation-0.0.17.dist-info → juham_automation-0.0.19.dist-info}/entry_points.txt +0 -0
- {juham_automation-0.0.17.dist-info → juham_automation-0.0.19.dist-info}/licenses/LICENSE.rst +0 -0
- {juham_automation-0.0.17.dist-info → juham_automation-0.0.19.dist-info}/top_level.txt +0 -0
@@ -176,41 +176,64 @@ class HotWaterOptimizer(Juham):
|
|
176
176
|
self.debug(f"Forecast sorted for the next {str(len(ranked_hours))} hours")
|
177
177
|
return ranked_hours
|
178
178
|
|
179
|
+
def on_spot(self, m: list[dict[str, Any]], ts_quantized: float) -> None:
|
180
|
+
"""Handle the spot prices.
|
181
|
+
|
182
|
+
Args:
|
183
|
+
list[dict[str, Any]]: list of spot prices
|
184
|
+
ts_quantized (float): current time
|
185
|
+
"""
|
186
|
+
self.ranked_spot_prices = self.sort_by_rank(m, ts_quantized)
|
187
|
+
|
188
|
+
def on_forecast(
|
189
|
+
self, forecast: list[dict[str, Any]], ts_utc_quantized: float
|
190
|
+
) -> None:
|
191
|
+
"""Handle the solar forecast.
|
192
|
+
|
193
|
+
Args:
|
194
|
+
m (list[dict[str, Any]]): list of forecast prices
|
195
|
+
ts_quantized (float): current time
|
196
|
+
"""
|
197
|
+
# reject forecasts that don't have solarenergy key
|
198
|
+
for f in forecast:
|
199
|
+
if not "solarenergy" in f:
|
200
|
+
return
|
201
|
+
|
202
|
+
self.ranked_solarpower = self.sort_by_power(forecast, ts_utc_quantized)
|
203
|
+
self.debug(
|
204
|
+
f"Solar energy forecast received and ranked for {len(self.ranked_solarpower)} hours"
|
205
|
+
)
|
206
|
+
self.power_plan = [] # reset power plan, it depends on forecast
|
207
|
+
|
208
|
+
def on_power(self, m: dict[str, Any], ts: float) -> None:
|
209
|
+
"""Handle the power consumption. Read the current power balance and accumulate
|
210
|
+
to the net energy balance to reflect the energy produced (or consumed) within the
|
211
|
+
current time slot.
|
212
|
+
Args:
|
213
|
+
m (dict[str, Any]): power consumption message
|
214
|
+
ts (float): current time
|
215
|
+
"""
|
216
|
+
self.net_energy_power = m["power"]
|
217
|
+
balance: float = (ts - self.net_energy_balance_ts) * self.net_energy_power
|
218
|
+
self.net_energy_balance = self.net_energy_balance + balance
|
219
|
+
self.net_energy_balance_ts = ts
|
220
|
+
|
179
221
|
@override
|
180
222
|
def on_message(self, client: object, userdata: Any, msg: MqttMsg) -> None:
|
181
223
|
m = None
|
182
224
|
ts: float = timestamp()
|
183
225
|
ts_utc_quantized: float = quantize(3600, ts - 3600)
|
184
226
|
if msg.topic == self.topic_spot:
|
185
|
-
self.
|
186
|
-
json.loads(msg.payload.decode()), ts_utc_quantized
|
187
|
-
)
|
188
|
-
self.debug(
|
189
|
-
f"Spot prices received and ranked for {len(self.ranked_spot_prices)} hours"
|
190
|
-
)
|
191
|
-
self.power_plan = [] # reset power plan, it depends on spot prices
|
227
|
+
self.on_spot(json.loads(msg.payload.decode()), ts_utc_quantized)
|
192
228
|
return
|
193
229
|
elif msg.topic == self.topic_forecast:
|
194
|
-
|
195
|
-
# reject messages that don't have solarenergy forecast
|
196
|
-
|
197
|
-
for f in forecast:
|
198
|
-
if not "solarenergy" in f:
|
199
|
-
return
|
200
|
-
|
201
|
-
self.ranked_solarpower = self.sort_by_power(forecast, ts_utc_quantized)
|
202
|
-
self.debug(
|
203
|
-
f"Solar energy forecast received and ranked for {len(self.ranked_solarpower)} hours"
|
204
|
-
)
|
205
|
-
self.power_plan = [] # reset power plan, it depends on forecast
|
230
|
+
self.on_forecast(json.loads(msg.payload.decode()), ts_utc_quantized)
|
206
231
|
return
|
207
232
|
elif msg.topic == self.topic_temperature:
|
208
233
|
m = json.loads(msg.payload.decode())
|
209
234
|
self.current_temperature = m["temperature"]
|
210
235
|
elif msg.topic == self.topic_in_net_energy_balance:
|
211
|
-
|
212
|
-
self.net_energy_balance = m["energy"]
|
213
|
-
self.net_energy_power = m["power"]
|
236
|
+
self.on_power(json.loads(msg.payload.decode()), ts)
|
214
237
|
elif msg.topic == self.topic_in_powerconsumption:
|
215
238
|
m = json.loads(msg.payload.decode())
|
216
239
|
self.current_power = m["real_total"]
|
@@ -220,7 +243,10 @@ class HotWaterOptimizer(Juham):
|
|
220
243
|
self.on_powerplan(ts)
|
221
244
|
|
222
245
|
def on_powerplan(self, ts_utc_now: float) -> None:
|
223
|
-
"""Apply power plan.
|
246
|
+
"""Apply the power plan. Check if the relay needs to be switched on or off.
|
247
|
+
The relay is switched on if the current temperature is below the maximum
|
248
|
+
temperature and the current time is within the heating plan. The relay is switched off
|
249
|
+
if the current temperature is above the maximum temperature or the current time is outside.
|
224
250
|
|
225
251
|
Args:
|
226
252
|
ts_utc_now (float): utc time
|
@@ -313,22 +339,33 @@ class HotWaterOptimizer(Juham):
|
|
313
339
|
|
314
340
|
# don't bother to switch the relay on for small intervals, to avoid
|
315
341
|
# wearing contactors out
|
316
|
-
if
|
342
|
+
if (
|
343
|
+
not self.net_energy_balancing_mode
|
344
|
+
and remaining_ts < self.operation_threshold
|
345
|
+
):
|
317
346
|
print(
|
318
347
|
f"Skipping balance, remaining time {remaining_ts}s < {self.operation_threshold}s"
|
319
348
|
)
|
320
349
|
return False
|
350
|
+
elif remaining_ts <= 0:
|
351
|
+
self.net_energy_balancing_rc = False # heating off
|
352
|
+
self.info(
|
353
|
+
f"End of the balancing interval reached, disabled with {self.net_energy_balance/3600}kWh left"
|
354
|
+
)
|
355
|
+
self.net_energy_balance = 0.0
|
356
|
+
self.net_energy_balance_ts = ts
|
357
|
+
return False
|
321
358
|
|
322
|
-
# check if the balance is sufficient for heating the
|
323
|
-
# if yes then switch heating on
|
324
|
-
needed_energy =
|
359
|
+
# check if the balance is sufficient for heating the remainin interval
|
360
|
+
# if yes then switch heating on
|
361
|
+
needed_energy = self.radiator_power * remaining_ts
|
325
362
|
elapsed_interval = ts - self.net_energy_balance_ts
|
326
363
|
print(
|
327
|
-
f"Needed energy {int(needed_energy)}
|
364
|
+
f"Needed energy {int(needed_energy)/3600}kWh, current balance {int(self.net_energy_balance/3600)}kWh"
|
328
365
|
)
|
329
366
|
|
330
367
|
if (
|
331
|
-
self.net_energy_balance
|
368
|
+
self.net_energy_balance >= needed_energy
|
332
369
|
) and not self.net_energy_balancing_rc:
|
333
370
|
self.net_energy_balance_ts = ts
|
334
371
|
self.net_energy_balancing_rc = True # heat
|
@@ -338,7 +375,7 @@ class HotWaterOptimizer(Juham):
|
|
338
375
|
# check if we have reach the end of the interval, or consumed all the energy
|
339
376
|
# of the current slot. If so switch the energy balancer mode off
|
340
377
|
if (
|
341
|
-
elapsed_interval > self.energy_balancing_interval
|
378
|
+
elapsed_interval > self.energy_balancing_interval
|
342
379
|
or self.net_energy_balance < 0
|
343
380
|
):
|
344
381
|
self.net_energy_balancing_rc = False # heating off
|
@@ -346,7 +383,9 @@ class HotWaterOptimizer(Juham):
|
|
346
383
|
return self.net_energy_balancing_rc
|
347
384
|
|
348
385
|
def consider_heating(self, ts: float) -> int:
|
349
|
-
"""Consider whether the target boiler needs heating.
|
386
|
+
"""Consider whether the target boiler needs heating. Check first if the solar
|
387
|
+
energy is enough to heat the water the remaining time in the current slot.
|
388
|
+
If not, follow the predefined heating plan computed earlier based on the cheapest spot prices.
|
350
389
|
|
351
390
|
Args:
|
352
391
|
ts (float): current UTC time
|
@@ -3,7 +3,7 @@ juham_automation/japp.py,sha256=zD5ulfIcaSzwbVKjHv2tdXpw79fpw97B7P-v-ncY6e4,1520
|
|
3
3
|
juham_automation/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
4
4
|
juham_automation/automation/__init__.py,sha256=73Mw0jkipeMCoUtpREHJPATfKe368ZyNeqfbjamBx_Q,481
|
5
5
|
juham_automation/automation/energycostcalculator.py,sha256=7GGKLv5JpHAY3XVjbkboXuQBk-whpWkBwNuQ68Tv4Pc,11091
|
6
|
-
juham_automation/automation/hotwateroptimizer.py,sha256=
|
6
|
+
juham_automation/automation/hotwateroptimizer.py,sha256=ImbbfSBQMQXGVneAo8ldN1Dcjyjow75qhLZ1kbqhQzQ,24999
|
7
7
|
juham_automation/automation/powermeter_simulator.py,sha256=0g0gOD9WTqxUj9IbENkea_33JrJ2sZDSQVtmxVUHcD8,4688
|
8
8
|
juham_automation/automation/spothintafi.py,sha256=XnL2zIPx_XaP_1E8ksuYEUemtHP7N6tLlSv2LEBQyXQ,4471
|
9
9
|
juham_automation/automation/watercirculator.py,sha256=d7PQFNajtVafizS_y2R_6GWhm_GYb8uV4-QScz1Sggo,6569
|
@@ -15,9 +15,9 @@ juham_automation/ts/log_ts.py,sha256=DPfeJhbSMQChY37mjAxEmE73Ys3dxUvNsN78PSuBm9Y
|
|
15
15
|
juham_automation/ts/power_ts.py,sha256=esNbtH1xklyUaf0YJQ2wDuxTAV3SnEfx-FtiBGPaSVA,1448
|
16
16
|
juham_automation/ts/powermeter_ts.py,sha256=zSATxZAzz1KJeU1wFK8CP86iySWnHil89mridz7WHos,2421
|
17
17
|
juham_automation/ts/powerplan_ts.py,sha256=-Lhc7v5Cj7USy2MfmyUEusXSox9UbEoDtYGReDEt3cw,1527
|
18
|
-
juham_automation-0.0.
|
19
|
-
juham_automation-0.0.
|
20
|
-
juham_automation-0.0.
|
21
|
-
juham_automation-0.0.
|
22
|
-
juham_automation-0.0.
|
23
|
-
juham_automation-0.0.
|
18
|
+
juham_automation-0.0.19.dist-info/licenses/LICENSE.rst,sha256=D3SSbUrv10lpAZ91lTMCQAke-MXMvrjFDsDyM3vEKJI,1114
|
19
|
+
juham_automation-0.0.19.dist-info/METADATA,sha256=zjFtQzp9U-30OuXPZHRoyWSgewTKr5tdM9dGceg3ICY,4733
|
20
|
+
juham_automation-0.0.19.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
21
|
+
juham_automation-0.0.19.dist-info/entry_points.txt,sha256=di8tXChhP8B_98bQ44u-1zkOha2kZCoJpCAXxTgoSw8,491
|
22
|
+
juham_automation-0.0.19.dist-info/top_level.txt,sha256=jfohvtocvX_gfT21AhJk7Iay5ZiQsS3HzrDjF7S4Qp0,17
|
23
|
+
juham_automation-0.0.19.dist-info/RECORD,,
|
File without changes
|
File without changes
|
{juham_automation-0.0.17.dist-info → juham_automation-0.0.19.dist-info}/licenses/LICENSE.rst
RENAMED
File without changes
|
File without changes
|