Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion custom_components/span_panel/lock.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,11 +133,17 @@ def _apply(self, evse: SpanEvseSnapshot) -> None:

@property
def available(self) -> bool:
"""False while the panel is offline: a control that cannot reach the panel is not a control."""
"""False while the panel is offline, or the charger no longer offers its lock.

A control that cannot reach the panel is not a control, and neither is one
whose charger has left the snapshot or stopped declaring the lock settable.
"""
if not self._transport_available:
return False
if self.coordinator.panel_offline:
return False
if self._evse().lock_control is None:
return False
return super().available

async def async_lock(self, **kwargs: Any) -> None:
Expand Down
19 changes: 19 additions & 0 deletions tests/test_evse_lock.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,3 +126,22 @@ async def test_the_lock_is_unavailable_while_the_panel_is_offline(hass: HomeAssi
lock.coordinator.panel_offline = True

assert lock.available is False


@pytest.mark.parametrize("withdrawn", ["charger_gone", "lock_not_settable"])
async def test_the_lock_is_withdrawn_when_the_charger_stops_offering_it(
hass: HomeAssistant, withdrawn: str
) -> None:
snapshot = _snapshot()
(lock,) = await _created(hass, snapshot)
lock.coordinator.panel_offline = False
assert lock.available is True

evse = dict(snapshot.evse)
if withdrawn == "charger_gone":
del evse[SETTABLE]
else:
evse[SETTABLE] = replace(evse[SETTABLE], lock_control=None)
lock.coordinator.data = replace(snapshot, evse=evse)

assert lock.available is False
Loading