Skip to content

Commit 9f19ec4

Browse files
committed
Address Copilot review on PR #1503
- Fix StaticState field comments (min_temp/max_temp are PPS-only; 714/1014 and 716/1016 map to protective/comfort setpoints) - Make temp-range source selection skip inactive values (value=None) so it falls back correctly when a setpoint returns '---' - Pick example Temperature Unit from first available attribute - Relabel example 'Max Temperature' to 'Comfort Setpoint Max' - Set mock setpoint attrs explicitly for deterministic tests
1 parent 8c003eb commit 9f19ec4

4 files changed

Lines changed: 49 additions & 8 deletions

File tree

examples/control.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,22 @@ def print_device_info(device: Device, info: Info) -> None:
192192
print_attributes("Device Information", attributes)
193193

194194

195+
def _first_temperature_attribute(static_state: StaticState) -> Any:
196+
"""Return the first available temperature attribute for unit detection."""
197+
for attribute in (
198+
static_state.heating_protective_setpoint,
199+
static_state.temp_reduced_setpoint,
200+
static_state.comfort_setpoint_max,
201+
static_state.min_temp,
202+
static_state.max_temp,
203+
static_state.cooling_comfort_setpoint_min,
204+
static_state.cooling_reduced_setpoint,
205+
):
206+
if attribute is not None:
207+
return attribute
208+
return None
209+
210+
195211
def print_static_state(static_state: StaticState) -> None:
196212
"""Print static state information, including heating and cooling bounds.
197213
@@ -203,7 +219,7 @@ def print_static_state(static_state: StaticState) -> None:
203219
"Reduced Setpoint (eco/night)": get_attribute(
204220
static_state.temp_reduced_setpoint
205221
),
206-
"Max Temperature (heating)": get_attribute(static_state.comfort_setpoint_max),
222+
"Comfort Setpoint Max": get_attribute(static_state.comfort_setpoint_max),
207223
"Heating Protective Setpoint": get_attribute(
208224
static_state.heating_protective_setpoint
209225
),
@@ -214,7 +230,7 @@ def print_static_state(static_state: StaticState) -> None:
214230
static_state.cooling_reduced_setpoint
215231
),
216232
"Temperature Unit": get_attribute(
217-
static_state.heating_protective_setpoint, "unit"
233+
_first_temperature_attribute(static_state), "unit"
218234
),
219235
}
220236
print_attributes("Static State", attributes)

src/bsblan/bsblan.py

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -633,8 +633,19 @@ async def _fetch_temperature_range(
633633

634634
# Prefer heating_protective_setpoint (714/1014) as the true lower bound
635635
# for standard circuits. Fall back to min_temp for PPS circuits (15006)
636-
# which have no separate protective setpoint.
637-
min_source = static_values.heating_protective_setpoint or static_values.min_temp
636+
# which have no separate protective setpoint. Skip sources whose value is
637+
# inactive (BSB-LAN may return "---" which becomes value=None).
638+
min_source = next(
639+
(
640+
source
641+
for source in (
642+
static_values.heating_protective_setpoint,
643+
static_values.min_temp,
644+
)
645+
if source is not None and source.value is not None
646+
),
647+
None,
648+
)
638649
if min_source is not None:
639650
temp_range["min"] = min_source.value
640651
logger.debug(
@@ -645,8 +656,18 @@ async def _fetch_temperature_range(
645656

646657
# Prefer comfort_setpoint_max (716/1016) as the upper bound for standard
647658
# circuits. Fall back to max_temp for PPS circuits (15007) which expose
648-
# only a generic max.
649-
max_source = static_values.comfort_setpoint_max or static_values.max_temp
659+
# only a generic max. Skip sources whose value is inactive.
660+
max_source = next(
661+
(
662+
source
663+
for source in (
664+
static_values.comfort_setpoint_max,
665+
static_values.max_temp,
666+
)
667+
if source is not None and source.value is not None
668+
),
669+
None,
670+
)
650671
if max_source is not None:
651672
temp_range["max"] = max_source.value
652673
logger.debug(

src/bsblan/models.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -481,11 +481,13 @@ class StaticState(BaseModel):
481481

482482
# 712/1012: room temperature reduced (eco/night) setpoint
483483
temp_reduced_setpoint: EntityInfo[float] | None = None
484-
# 714/1014: frost-protection lower bound; also used by PPS as min_temp (15006)
484+
# PPS-only lower bound (15006)
485485
min_temp: EntityInfo[float] | None = None
486-
# 716/1016: comfort setpoint max upper bound; PPS uses max_temp (15007)
486+
# 716/1016: comfort setpoint max upper bound
487487
comfort_setpoint_max: EntityInfo[float] | None = None
488+
# PPS-only upper bound (15007)
488489
max_temp: EntityInfo[float] | None = None
490+
# 714/1014: frost-protection lower bound
489491
heating_protective_setpoint: EntityInfo[float] | None = None
490492
cooling_comfort_setpoint_min: EntityInfo[float] | None = None
491493
cooling_reduced_setpoint: EntityInfo[float] | None = None

tests/test_temperature_validation.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ async def test_temperature_range_min_temp_not_available(monkeypatch: Any) -> Non
157157
static_values_mock = AsyncMock()
158158
static_values_mock.return_value.heating_protective_setpoint = None
159159
static_values_mock.return_value.min_temp = None
160+
static_values_mock.return_value.comfort_setpoint_max = None
160161
static_values_mock.return_value.max_temp = AsyncMock()
161162
static_values_mock.return_value.max_temp.value = "30"
162163
monkeypatch.setattr(client, "static_values", static_values_mock)
@@ -190,6 +191,7 @@ async def test_temperature_range_max_temp_not_available(monkeypatch: Any) -> Non
190191

191192
# Mock static_values to return data without max_temp
192193
static_values_mock = AsyncMock()
194+
static_values_mock.return_value.heating_protective_setpoint = None
193195
static_values_mock.return_value.min_temp = AsyncMock()
194196
static_values_mock.return_value.min_temp.value = "10"
195197
static_values_mock.return_value.comfort_setpoint_max = None

0 commit comments

Comments
 (0)