Make per-sensor weights visible and labelled in the zone form
Sensor weights already existed, but only as a second step after saving
a zone with two or more sensors, with fields labelled by raw keys such
as weight__sensor.living_a, so they were easy to miss.
The zone form now says that choosing two or more sensors leads to a
sensor-weight step. That step uses numbered fields ("Sensor 1 weight",
English and Romanian) and its description lists which sensor is which
by friendly name. Editing a multi-sensor zone shows the saved weights.
Stored data is unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
2bddc74d37
commit
9bb64e79ca
5 files changed
+58
-15
No files matched your search
@@ -302,14 +302,23 @@ class ZoneSubentryFlow(config_entries.ConfigSubentryFlow):
|
||||
return await self._zone_form("reconfigure", user_input, existing, existing[ZONE_KEY])
|
||||
|
||||
async def async_step_sensor_weights(self, user_input: dict[str, Any] | None = None):
|
||||
"""One weight per sensor; fields are numbered so they have translated labels."""
|
||||
sensors = self._draft[ZONE_SENSORS]
|
||||
if user_input is not None:
|
||||
self._draft[ZONE_SENSOR_WEIGHTS] = {s: float(user_input[f"weight__{s}"]) for s in sensors}
|
||||
self._draft[ZONE_SENSOR_WEIGHTS] = {
|
||||
s: float(user_input[f"sensor_weight_{i}"]) for i, s in enumerate(sensors, 1)}
|
||||
return self._finish()
|
||||
weights = self._draft.get(ZONE_SENSOR_WEIGHTS) or {}
|
||||
return self.async_show_form(step_id="sensor_weights", data_schema=vol.Schema({
|
||||
vol.Required(f"weight__{s}", default=weights.get(s, 1.0)): _number(*SENSOR_WEIGHT_RANGE, 0.1)
|
||||
for s in sensors}))
|
||||
names = []
|
||||
for i, sensor in enumerate(sensors, 1):
|
||||
state = self.hass.states.get(sensor)
|
||||
names.append(f"{i}. {state.name if state else sensor} ({sensor})")
|
||||
return self.async_show_form(
|
||||
step_id="sensor_weights",
|
||||
data_schema=vol.Schema({
|
||||
vol.Required(f"sensor_weight_{i}", default=weights.get(s, 1.0)): _number(*SENSOR_WEIGHT_RANGE, 0.1)
|
||||
for i, s in enumerate(sensors, 1)}),
|
||||
description_placeholders={"sensors": "\n".join(names)})
|
||||
|
||||
def _finish(self):
|
||||
data = {key: self._draft[key] for key in (
|
||||
|
||||
@@ -143,7 +143,7 @@
|
||||
"step": {
|
||||
"user": {
|
||||
"title": "Thermal zone",
|
||||
"description": "A room or area of the apartment. Sensor weights combine several sensors in one room; the comfort weight says how much the zone matters to the MPC. Neither changes the zone's learned thermal properties.",
|
||||
"description": "A room or area of the apartment. Sensor weights combine several sensors in one room; the comfort weight says how much the zone matters to the MPC. Neither changes the zone's learned thermal properties. If you choose two or more sensors, the next step asks for each sensor's weight.",
|
||||
"data": {
|
||||
"name": "Name",
|
||||
"sensors": "Temperature sensors",
|
||||
@@ -159,11 +159,19 @@
|
||||
},
|
||||
"sensor_weights": {
|
||||
"title": "Sensor weights",
|
||||
"description": "How much each sensor counts in the zone temperature (0.1–10)."
|
||||
"description": "How much each sensor counts in the zone temperature (0.1–10). Equal weights give the plain average.\n\n{sensors}",
|
||||
"data": {
|
||||
"sensor_weight_1": "Sensor 1 weight",
|
||||
"sensor_weight_2": "Sensor 2 weight",
|
||||
"sensor_weight_3": "Sensor 3 weight",
|
||||
"sensor_weight_4": "Sensor 4 weight",
|
||||
"sensor_weight_5": "Sensor 5 weight",
|
||||
"sensor_weight_6": "Sensor 6 weight"
|
||||
}
|
||||
},
|
||||
"reconfigure": {
|
||||
"title": "Thermal zone",
|
||||
"description": "A room or area of the apartment. Sensor weights combine several sensors in one room; the comfort weight says how much the zone matters to the MPC. Neither changes the zone's learned thermal properties.",
|
||||
"description": "A room or area of the apartment. Sensor weights combine several sensors in one room; the comfort weight says how much the zone matters to the MPC. Neither changes the zone's learned thermal properties. If you choose two or more sensors, the next step asks for each sensor's weight.",
|
||||
"data": {
|
||||
"name": "Name",
|
||||
"sensors": "Temperature sensors",
|
||||
|
||||
@@ -143,7 +143,7 @@
|
||||
"step": {
|
||||
"user": {
|
||||
"title": "Thermal zone",
|
||||
"description": "A room or area of the apartment. Sensor weights combine several sensors in one room; the comfort weight says how much the zone matters to the MPC. Neither changes the zone's learned thermal properties.",
|
||||
"description": "A room or area of the apartment. Sensor weights combine several sensors in one room; the comfort weight says how much the zone matters to the MPC. Neither changes the zone's learned thermal properties. If you choose two or more sensors, the next step asks for each sensor's weight.",
|
||||
"data": {
|
||||
"name": "Name",
|
||||
"sensors": "Temperature sensors",
|
||||
@@ -159,11 +159,19 @@
|
||||
},
|
||||
"sensor_weights": {
|
||||
"title": "Sensor weights",
|
||||
"description": "How much each sensor counts in the zone temperature (0.1–10)."
|
||||
"description": "How much each sensor counts in the zone temperature (0.1–10). Equal weights give the plain average.\n\n{sensors}",
|
||||
"data": {
|
||||
"sensor_weight_1": "Sensor 1 weight",
|
||||
"sensor_weight_2": "Sensor 2 weight",
|
||||
"sensor_weight_3": "Sensor 3 weight",
|
||||
"sensor_weight_4": "Sensor 4 weight",
|
||||
"sensor_weight_5": "Sensor 5 weight",
|
||||
"sensor_weight_6": "Sensor 6 weight"
|
||||
}
|
||||
},
|
||||
"reconfigure": {
|
||||
"title": "Thermal zone",
|
||||
"description": "A room or area of the apartment. Sensor weights combine several sensors in one room; the comfort weight says how much the zone matters to the MPC. Neither changes the zone's learned thermal properties.",
|
||||
"description": "A room or area of the apartment. Sensor weights combine several sensors in one room; the comfort weight says how much the zone matters to the MPC. Neither changes the zone's learned thermal properties. If you choose two or more sensors, the next step asks for each sensor's weight.",
|
||||
"data": {
|
||||
"name": "Name",
|
||||
"sensors": "Temperature sensors",
|
||||
|
||||
@@ -143,7 +143,7 @@
|
||||
"step": {
|
||||
"user": {
|
||||
"title": "Zonă termică",
|
||||
"description": "O cameră sau o zonă a apartamentului. Ponderile senzorilor combină mai mulți senzori din aceeași cameră; ponderea de confort spune cât de importantă este zona pentru MPC. Niciuna nu modifică proprietățile termice învățate ale zonei.",
|
||||
"description": "O cameră sau o zonă a apartamentului. Ponderile senzorilor combină mai mulți senzori din aceeași cameră; ponderea de confort spune cât de importantă este zona pentru MPC. Niciuna nu modifică proprietățile termice învățate ale zonei. Dacă alegi doi sau mai mulți senzori, pasul următor cere ponderea fiecărui senzor.",
|
||||
"data": {
|
||||
"name": "Nume",
|
||||
"sensors": "Senzori de temperatură",
|
||||
@@ -159,11 +159,19 @@
|
||||
},
|
||||
"sensor_weights": {
|
||||
"title": "Ponderile senzorilor",
|
||||
"description": "Cât contează fiecare senzor în temperatura zonei (0,1–10)."
|
||||
"description": "Cât contează fiecare senzor în temperatura zonei (0,1–10). Ponderi egale dau media simplă.\n\n{sensors}",
|
||||
"data": {
|
||||
"sensor_weight_1": "Ponderea senzorului 1",
|
||||
"sensor_weight_2": "Ponderea senzorului 2",
|
||||
"sensor_weight_3": "Ponderea senzorului 3",
|
||||
"sensor_weight_4": "Ponderea senzorului 4",
|
||||
"sensor_weight_5": "Ponderea senzorului 5",
|
||||
"sensor_weight_6": "Ponderea senzorului 6"
|
||||
}
|
||||
},
|
||||
"reconfigure": {
|
||||
"title": "Zonă termică",
|
||||
"description": "O cameră sau o zonă a apartamentului. Ponderile senzorilor combină mai mulți senzori din aceeași cameră; ponderea de confort spune cât de importantă este zona pentru MPC. Niciuna nu modifică proprietățile termice învățate ale zonei.",
|
||||
"description": "O cameră sau o zonă a apartamentului. Ponderile senzorilor combină mai mulți senzori din aceeași cameră; ponderea de confort spune cât de importantă este zona pentru MPC. Niciuna nu modifică proprietățile termice învățate ale zonei. Dacă alegi doi sau mai mulți senzori, pasul următor cere ponderea fiecărui senzor.",
|
||||
"data": {
|
||||
"name": "Nume",
|
||||
"sensors": "Senzori de temperatură",
|
||||
|
||||
@@ -132,8 +132,11 @@ async def test_zone_subentry_add_edit_and_validation(hass, entry, inputs):
|
||||
"name": " Living ", "sensors": ["sensor.living_a", "sensor.living_b"], "comfort_weight": 2,
|
||||
"target_offset": 0.5, "neighbors": ["sensor.room"]})
|
||||
assert result["step_id"] == "sensor_weights"
|
||||
result = await flows.async_configure(result["flow_id"], {
|
||||
"weight__sensor.living_a": 3, "weight__sensor.living_b": 1})
|
||||
# Numbered, translated fields; the description says which sensor is which.
|
||||
assert [str(key) for key in result["data_schema"].schema] == ["sensor_weight_1", "sensor_weight_2"]
|
||||
assert result["description_placeholders"]["sensors"].splitlines() == [
|
||||
"1. living a (sensor.living_a)", "2. living b (sensor.living_b)"] # HA name fallback
|
||||
result = await flows.async_configure(result["flow_id"], {"sensor_weight_1": 3, "sensor_weight_2": 1})
|
||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||
await hass.async_block_till_done()
|
||||
living = next(sub for sub in zones_of(entry).values() if sub.title == "Living")
|
||||
@@ -149,6 +152,13 @@ async def test_zone_subentry_add_edit_and_validation(hass, entry, inputs):
|
||||
result = await flows.async_configure(result["flow_id"], {
|
||||
"name": "Living", "sensors": ["sensor.living_a"], "comfort_weight": 1, "target_offset": 0})
|
||||
assert result["type"] is FlowResultType.ABORT and result["reason"] == "reconfigure_successful"
|
||||
# Editing a multi-sensor zone shows the saved sensor weights.
|
||||
result = await flows.async_init((entry.entry_id, "zone"), context={
|
||||
"source": SOURCE_RECONFIGURE, "subentry_id": living.subentry_id})
|
||||
result = await flows.async_configure(result["flow_id"], {
|
||||
"name": "Living", "sensors": ["sensor.living_a", "sensor.living_b"], "comfort_weight": 1, "target_offset": 0})
|
||||
assert result["data_schema"]({})["sensor_weight_1"] == 1.0
|
||||
flows.async_abort(result["flow_id"])
|
||||
await hass.async_block_till_done()
|
||||
assert entry.subentries[living.subentry_id].data["key"] == key
|
||||
assert hass.data[DOMAIN][entry.entry_id].zones[key].sensors == ("sensor.living_a",)
|
||||
|
||||
Reference in new issue
Block a user