|
26 | 26 | HVAC_MODE_DICT_REVERSE, |
27 | 27 | MULTI_PARAMETER_ERROR_MSG, |
28 | 28 | NO_STATE_ERROR_MSG, |
| 29 | + ROOM_TEMPERATURE_PUSH_PARAM, |
29 | 30 | SESSION_NOT_INITIALIZED_ERROR_MSG, |
30 | 31 | TEMPERATURE_RANGE_ERROR_MSG, |
31 | 32 | VERSION_ERROR_MSG, |
@@ -493,6 +494,73 @@ async def info(self) -> Info: |
493 | 494 | data = dict(zip(params["list"], list(data.values()), strict=True)) |
494 | 495 | return Info.from_dict(data) |
495 | 496 |
|
| 497 | + async def push_temperature(self, room_temperature: str) -> None: |
| 498 | + """Push room temperature to the heating system through BSB-Lan. |
| 499 | +
|
| 500 | + This functionality is useful for heating systems without a built-in |
| 501 | + thermostat, allowing external temperature sensors to provide room |
| 502 | + temperature data to the heating system. |
| 503 | +
|
| 504 | + Args: |
| 505 | + room_temperature (str): The current room temperature to push to |
| 506 | + the heating system. |
| 507 | +
|
| 508 | + """ |
| 509 | + # Only initialize temperature range if not already done |
| 510 | + if not self._temperature_range_initialized: |
| 511 | + await self._initialize_temperature_range() |
| 512 | + |
| 513 | + # Validate the room temperature |
| 514 | + self._validate_room_temperature(room_temperature) |
| 515 | + |
| 516 | + # Prepare and set the temperature push state |
| 517 | + state = self._prepare_temperature_push_state(room_temperature) |
| 518 | + await self._set_thermostat_state(state) |
| 519 | + |
| 520 | + def _prepare_temperature_push_state(self, room_temperature: str) -> dict[str, Any]: |
| 521 | + """Prepare the temperature push state for setting. |
| 522 | +
|
| 523 | + Args: |
| 524 | + room_temperature (str): The room temperature to push. |
| 525 | +
|
| 526 | + Returns: |
| 527 | + dict[str, Any]: The prepared state for temperature push. |
| 528 | +
|
| 529 | + """ |
| 530 | + return { |
| 531 | + "Parameter": ROOM_TEMPERATURE_PUSH_PARAM, |
| 532 | + "Value": room_temperature, |
| 533 | + "Type": "1", |
| 534 | + } |
| 535 | + |
| 536 | + def _validate_room_temperature(self, room_temperature: str) -> None: |
| 537 | + """Validate the room temperature for pushing. |
| 538 | +
|
| 539 | + Args: |
| 540 | + room_temperature (str): The room temperature to validate. |
| 541 | +
|
| 542 | + Raises: |
| 543 | + BSBLANError: If the temperature range is not initialized. |
| 544 | + BSBLANInvalidParameterError: If the room temperature is invalid. |
| 545 | +
|
| 546 | + """ |
| 547 | + if self._min_temp is None or self._max_temp is None: |
| 548 | + raise BSBLANError(TEMPERATURE_RANGE_ERROR_MSG) |
| 549 | + |
| 550 | + try: |
| 551 | + temp = float(room_temperature) |
| 552 | + # Room temperature can be outside the thermostat range, |
| 553 | + # but should be within reasonable bounds (-50°C to 100°C or -58°F to 212°F) |
| 554 | + if self._temperature_unit == "°F": |
| 555 | + min_bound, max_bound = -58.0, 212.0 |
| 556 | + else: |
| 557 | + min_bound, max_bound = -50.0, 100.0 |
| 558 | + |
| 559 | + if not (min_bound <= temp <= max_bound): |
| 560 | + raise BSBLANInvalidParameterError(room_temperature) |
| 561 | + except ValueError as err: |
| 562 | + raise BSBLANInvalidParameterError(room_temperature) from err |
| 563 | + |
496 | 564 | async def thermostat( |
497 | 565 | self, |
498 | 566 | target_temperature: str | None = None, |
|
0 commit comments