Skip to content

Commit 6b6553d

Browse files
aturriedenhaus
andauthored
Miele time sensors 2/3 - Provide consistent behavior with appliance status (home-assistant#146053)
Co-authored-by: Robert Resch <[email protected]>
1 parent 0865d3f commit 6b6553d

File tree

4 files changed

+35
-21
lines changed

4 files changed

+35
-21
lines changed

homeassistant/components/miele/icons.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
"default": "mdi:tray-full"
4646
},
4747
"elapsed_time": {
48-
"default": "mdi:timelapse"
48+
"default": "mdi:timer-outline"
4949
},
5050
"start_time": {
5151
"default": "mdi:clock-start"

homeassistant/components/miele/sensor.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,7 @@ class MieleSensorDefinition:
364364
key="state_remaining_time",
365365
translation_key="remaining_time",
366366
value_fn=lambda value: _convert_duration(value.state_remaining_time),
367+
end_value_fn=lambda last_value: 0,
367368
device_class=SensorDeviceClass.DURATION,
368369
native_unit_of_measurement=UnitOfTime.MINUTES,
369370
entity_category=EntityCategory.DIAGNOSTIC,
@@ -417,6 +418,7 @@ class MieleSensorDefinition:
417418
key="state_start_time",
418419
translation_key="start_time",
419420
value_fn=lambda value: _convert_duration(value.state_start_time),
421+
end_value_fn=lambda last_value: None,
420422
native_unit_of_measurement=UnitOfTime.MINUTES,
421423
device_class=SensorDeviceClass.DURATION,
422424
entity_category=EntityCategory.DIAGNOSTIC,
@@ -614,6 +616,8 @@ def _get_entity_class(definition: MieleSensorDefinition) -> type[MieleSensor]:
614616
"state_program_phase": MielePhaseSensor,
615617
"state_plate_step": MielePlateSensor,
616618
"state_elapsed_time": MieleTimeSensor,
619+
"state_remaining_time": MieleTimeSensor,
620+
"state_start_time": MieleTimeSensor,
617621
}.get(definition.description.key, MieleSensor)
618622

619623
def _is_entity_registered(unique_id: str) -> bool:
@@ -769,7 +773,7 @@ async def async_added_to_hass(self) -> None:
769773
"""When entity is added to hass."""
770774
await super().async_added_to_hass()
771775

772-
# recover last value from cache
776+
# recover last value from cache when adding entity
773777
last_value = await self.async_get_last_state()
774778
if last_value and last_value.state != STATE_UNKNOWN:
775779
self._last_value = last_value.state
@@ -779,6 +783,16 @@ def native_value(self) -> StateType:
779783
"""Return the state of the sensor."""
780784
return self._last_value
781785

786+
def _update_last_value(self) -> None:
787+
"""Update the last value of the sensor."""
788+
self._last_value = self.entity_description.value_fn(self.device)
789+
790+
@callback
791+
def _handle_coordinator_update(self) -> None:
792+
"""Handle updated data from the coordinator."""
793+
self._update_last_value()
794+
super()._handle_coordinator_update()
795+
782796

783797
class MielePlateSensor(MieleSensor):
784798
"""Representation of a Sensor."""
@@ -886,9 +900,8 @@ def options(self) -> list[str]:
886900
class MieleTimeSensor(MieleRestorableSensor):
887901
"""Representation of time sensors keeping state from cache."""
888902

889-
@callback
890-
def _handle_coordinator_update(self) -> None:
891-
"""Handle updated data from the coordinator."""
903+
def _update_last_value(self) -> None:
904+
"""Update the last value of the sensor."""
892905

893906
current_value = self.entity_description.value_fn(self.device)
894907
current_status = StateStatus(self.device.state_status)
@@ -911,5 +924,3 @@ def _handle_coordinator_update(self) -> None:
911924
# otherwise, cache value and return it
912925
else:
913926
self._last_value = current_value
914-
915-
super()._handle_coordinator_update()

tests/components/miele/snapshots/test_sensor.ambr

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3417,7 +3417,7 @@
34173417
'last_changed': <ANY>,
34183418
'last_reported': <ANY>,
34193419
'last_updated': <ANY>,
3420-
'state': '5',
3420+
'state': 'unknown',
34213421
})
34223422
# ---
34233423
# name: test_sensor_states[platforms0][sensor.oven_start_in-entry]
@@ -3473,7 +3473,7 @@
34733473
'last_changed': <ANY>,
34743474
'last_reported': <ANY>,
34753475
'last_updated': <ANY>,
3476-
'state': '0.0',
3476+
'state': 'unknown',
34773477
})
34783478
# ---
34793479
# name: test_sensor_states[platforms0][sensor.oven_target_temperature-entry]
@@ -4312,7 +4312,7 @@
43124312
'last_changed': <ANY>,
43134313
'last_reported': <ANY>,
43144314
'last_updated': <ANY>,
4315-
'state': '0',
4315+
'state': 'unknown',
43164316
})
43174317
# ---
43184318
# name: test_sensor_states[platforms0][sensor.washing_machine_spin_speed-entry]
@@ -4417,7 +4417,7 @@
44174417
'last_changed': <ANY>,
44184418
'last_reported': <ANY>,
44194419
'last_updated': <ANY>,
4420-
'state': '0.0',
4420+
'state': 'unknown',
44214421
})
44224422
# ---
44234423
# name: test_sensor_states[platforms0][sensor.washing_machine_target_temperature-entry]
@@ -6458,7 +6458,7 @@
64586458
'last_changed': <ANY>,
64596459
'last_reported': <ANY>,
64606460
'last_updated': <ANY>,
6461-
'state': '0',
6461+
'state': 'unknown',
64626462
})
64636463
# ---
64646464
# name: test_sensor_states_api_push[platforms0][sensor.washing_machine_spin_speed-entry]
@@ -6563,7 +6563,7 @@
65636563
'last_changed': <ANY>,
65646564
'last_reported': <ANY>,
65656565
'last_updated': <ANY>,
6566-
'state': '0.0',
6566+
'state': 'unknown',
65676567
})
65686568
# ---
65696569
# name: test_sensor_states_api_push[platforms0][sensor.washing_machine_target_temperature-entry]
@@ -7099,6 +7099,6 @@
70997099
'last_changed': <ANY>,
71007100
'last_reported': <ANY>,
71017101
'last_updated': <ANY>,
7102-
'state': '0',
7102+
'state': 'unknown',
71037103
})
71047104
# ---

tests/components/miele/test_sensor.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,8 @@ async def test_laundry_wash_scenario(
311311
hass, "sensor.washing_machine_target_temperature", "unknown", step
312312
)
313313
check_sensor_state(hass, "sensor.washing_machine_spin_speed", "unknown", step)
314-
check_sensor_state(hass, "sensor.washing_machine_remaining_time", "0", step)
314+
# OFF -> remaining forced to unknown
315+
check_sensor_state(hass, "sensor.washing_machine_remaining_time", "unknown", step)
315316
# OFF -> elapsed forced to unknown (some devices continue reporting last value of last cycle)
316317
check_sensor_state(hass, "sensor.washing_machine_elapsed_time", "unknown", step)
317318

@@ -347,8 +348,8 @@ async def test_laundry_wash_scenario(
347348
check_sensor_state(hass, "sensor.washing_machine_program_phase", "main_wash", step)
348349
check_sensor_state(hass, "sensor.washing_machine_target_temperature", "30.0", step)
349350
check_sensor_state(hass, "sensor.washing_machine_spin_speed", "1200", step)
351+
# IN_USE -> elapsed, remaining time from API (normal case)
350352
check_sensor_state(hass, "sensor.washing_machine_remaining_time", "105", step)
351-
# IN_USE -> elapsed time from API (normal case)
352353
check_sensor_state(hass, "sensor.washing_machine_elapsed_time", "12", step)
353354

354355
# Simulate rinse hold phase
@@ -373,8 +374,8 @@ async def test_laundry_wash_scenario(
373374
check_sensor_state(hass, "sensor.washing_machine_program_phase", "rinse_hold", step)
374375
check_sensor_state(hass, "sensor.washing_machine_target_temperature", "30.0", step)
375376
check_sensor_state(hass, "sensor.washing_machine_spin_speed", "1200", step)
377+
# RINSE HOLD -> elapsed, remaining time from API (normal case)
376378
check_sensor_state(hass, "sensor.washing_machine_remaining_time", "8", step)
377-
# RINSE HOLD -> elapsed time from API (normal case)
378379
check_sensor_state(hass, "sensor.washing_machine_elapsed_time", "109", step)
379380

380381
# Simulate program ended
@@ -401,6 +402,7 @@ async def test_laundry_wash_scenario(
401402
)
402403
check_sensor_state(hass, "sensor.washing_machine_target_temperature", "30.0", step)
403404
check_sensor_state(hass, "sensor.washing_machine_spin_speed", "1200", step)
405+
# PROGRAM_ENDED -> remaining time forced to 0
404406
check_sensor_state(hass, "sensor.washing_machine_remaining_time", "0", step)
405407
# PROGRAM_ENDED -> elapsed time kept from last program (some devices immediately go to 0)
406408
check_sensor_state(hass, "sensor.washing_machine_elapsed_time", "109", step)
@@ -433,8 +435,8 @@ async def test_laundry_wash_scenario(
433435
)
434436
check_sensor_state(hass, "sensor.washing_machine_target_temperature", "40.0", step)
435437
check_sensor_state(hass, "sensor.washing_machine_spin_speed", "1200", step)
438+
# PROGRAMMED -> elapsed, remaining time from API (normal case)
436439
check_sensor_state(hass, "sensor.washing_machine_remaining_time", "119", step)
437-
# PROGRAMMED -> elapsed time from API (normal case)
438440
check_sensor_state(hass, "sensor.washing_machine_elapsed_time", "0", step)
439441

440442

@@ -457,8 +459,8 @@ async def test_laundry_dry_scenario(
457459
check_sensor_state(hass, "sensor.tumble_dryer_program", "no_program", step)
458460
check_sensor_state(hass, "sensor.tumble_dryer_program_phase", "not_running", step)
459461
check_sensor_state(hass, "sensor.tumble_dryer_drying_step", "unknown", step)
460-
check_sensor_state(hass, "sensor.tumble_dryer_remaining_time", "0", step)
461-
# OFF -> elapsed forced to unknown (some devices continue reporting last value of last cycle)
462+
# OFF -> elapsed, remaining forced to unknown (some devices continue reporting last value of last cycle)
463+
check_sensor_state(hass, "sensor.tumble_dryer_remaining_time", "unknown", step)
462464
check_sensor_state(hass, "sensor.tumble_dryer_elapsed_time", "unknown", step)
463465

464466
# Simulate program started
@@ -486,8 +488,8 @@ async def test_laundry_dry_scenario(
486488
check_sensor_state(hass, "sensor.tumble_dryer_program", "minimum_iron", step)
487489
check_sensor_state(hass, "sensor.tumble_dryer_program_phase", "drying", step)
488490
check_sensor_state(hass, "sensor.tumble_dryer_drying_step", "normal", step)
491+
# IN_USE -> elapsed, remaining time from API (normal case)
489492
check_sensor_state(hass, "sensor.tumble_dryer_remaining_time", "49", step)
490-
# IN_USE -> elapsed time from API (normal case)
491493
check_sensor_state(hass, "sensor.tumble_dryer_elapsed_time", "20", step)
492494

493495
# Simulate program end
@@ -511,6 +513,7 @@ async def test_laundry_dry_scenario(
511513
check_sensor_state(hass, "sensor.tumble_dryer_program", "minimum_iron", step)
512514
check_sensor_state(hass, "sensor.tumble_dryer_program_phase", "finished", step)
513515
check_sensor_state(hass, "sensor.tumble_dryer_drying_step", "normal", step)
516+
# PROGRAM_ENDED -> remaining time forced to 0
514517
check_sensor_state(hass, "sensor.tumble_dryer_remaining_time", "0", step)
515518
# PROGRAM_ENDED -> elapsed time kept from last program (some devices immediately go to 0)
516519
check_sensor_state(hass, "sensor.tumble_dryer_elapsed_time", "20", step)

0 commit comments

Comments
 (0)