feat: add per-room temperature thresholds

Issue: #487
User-Visible: yes
This commit is contained in:
Matysh
2026-09-08 10:44:13 +03:00
parent d2d9b1ac5d
commit e2751062dc
73 changed files with 1465 additions and 864 deletions
+6
View File
@@ -855,6 +855,7 @@ def _plan_only_source() -> tuple[dict[str, Any], dict[str, Any]]:
"area": "living-area",
"settings": {
"fill_mode": "custom", "custom_fill": {"c": "#123456", "a": 0.4},
"temp_min": 18.5, "temp_max": 24,
"temp_source": "sensor.room_temp", "hum_source": "sensor.room_humidity",
"future_room_binding": "sensor.secret",
},
@@ -907,6 +908,7 @@ def test_plan_only_export_projects_geometry_and_round_trips_room_labels(tmp_path
assert "area" not in room and "future_room" not in room
assert room["settings"] == {
"fill_mode": "custom", "custom_fill": {"c": "#123456", "a": 0.4},
"temp_min": 18.5, "temp_max": 24,
}
opening = exported["openings"][0]
assert opening["flip_h"] is True
@@ -973,6 +975,10 @@ def test_ordinary_space_export_is_unchanged_when_plan_only_is_false(tmp_path: Pa
assert implicit == explicit
assert "plan_only" not in implicit["transfer"]
assert implicit["payload"]["config"]["markers"]
settings = implicit["payload"]["config"]["spaces"][0]["rooms"][0]["settings"]
assert settings["temp_min"] == 18.5
assert settings["temp_max"] == 24
assert settings["future_room_binding"] == "sensor.secret"
assert set(implicit["payload"]["layout"]) == {
key for key, pos in layout.items() if pos.get("s") == "ground"
}
+15
View File
@@ -1010,6 +1010,21 @@ def test_custom_fill_color_and_alpha_are_strict_on_space_and_room():
v.SPACE_SCHEMA(room_bad)
def test_room_temperature_thresholds_are_optional_strict_finite_numbers():
room = {
"id": "r1", "name": "R", "x": 0.1, "y": 0.1, "w": 0.2, "h": 0.2,
"settings": {"fill_mode": "temp", "temp_min": 0, "temp_max": 24.5},
}
assert v.ROOM_SCHEMA(room)["settings"]["temp_min"] == 0.0
for key in ("temp_min", "temp_max"):
nullable = {**room, "settings": {**room["settings"], key: None}}
assert v.ROOM_SCHEMA(nullable)["settings"][key] is None
for bad in (True, "20", float("nan"), float("inf")):
invalid = {**room, "settings": {**room["settings"], key: bad}}
with pytest.raises(vol.Invalid):
v.ROOM_SCHEMA(invalid)
def test_independent_glow_fields_and_legacy_tokens_are_accepted():
# Current UI writes two independent fields; old dashboard bundles remain
# valid writers of the legacy enum forever.