Skip to content

Commit 5774fef

Browse files
authored
Fix status priority for suspended-ev and suspended-evse (#56)
* Update `Pod.connected` to correctly support `suspended-evse` * 55: Fix status priorities for suspended-ev and suspended-evse In order to address #55 I have re-worked how 'new' statuses are handled. Also adds additional tests for the integration. * Rev version
1 parent fb14c9d commit 5774fef

File tree

6 files changed

+163
-17
lines changed

6 files changed

+163
-17
lines changed

custom_components/pod_point/coordinator.py

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -340,8 +340,8 @@ async def __async_group_pods(
340340
return (new_pods, new_pods_by_id)
341341

342342
async def __async_refresh_firmware(
343-
self, new_pods: List[Pod], new_pods_by_id: Dict[str, List[Pod]]
344-
) -> Dict[str, List[Pod]]:
343+
self, new_pods: List[Pod], new_pods_by_id: Dict[str, Pod]
344+
) -> Dict[str, Pod]:
345345
_LOGGER.debug("=== FIRMWARE STATUS UPDATE ===")
346346

347347
for pod in new_pods:
@@ -367,8 +367,8 @@ async def __async_refresh_firmware(
367367
return new_pods_by_id
368368

369369
async def __async_update_pod_connection_status(
370-
self, new_pods_by_id: Dict[str, List[Pod]]
371-
) -> Dict[str, List[Pod]]:
370+
self, new_pods_by_id: Dict[str, Pod]
371+
) -> Dict[str, Pod]:
372372
_LOGGER.debug("=== POD CONNECTION STATUS UPDATE ===")
373373

374374
# flat_pods = [item for row in new_pods_by_id.values() for item in row]
@@ -381,16 +381,8 @@ async def __async_update_pod_connection_status(
381381
pod.last_message_at = connectivity_status.last_message_at
382382
pod.charging_state = connectivity_status.charging_state
383383

384-
pod.statuses.append(
385-
Pod.Status(
386-
99,
387-
connectivity_status.charging_state,
388-
connectivity_status.charging_state,
389-
connectivity_status.charging_state,
390-
"A",
391-
1,
392-
)
393-
)
384+
if pod.charging_state is not None:
385+
pod.charging_state = pod.charging_state.lower().replace("_", "-")
394386

395387
new_pods_by_id[pod.unit_id] = pod
396388

custom_components/pod_point/entity.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,14 @@ def __update_attrs(self):
8585
should_be_charging = is_charging_state and (
8686
is_override_charge_mode or is_manual_charge_mode
8787
)
88+
should_be_suspended_ev = (
89+
is_charging_state
90+
and (pod.charging_state == ATTR_STATE_SUSPENDED_EV)
91+
)
92+
should_be_suspended_evse = (
93+
is_charging_state
94+
and (pod.charging_state == ATTR_STATE_SUSPENDED_EVSE)
95+
)
8896
should_be_pending = (
8997
self.coordinator.last_message_at is not None
9098
and self.pod.last_message_at is not None
@@ -105,6 +113,14 @@ def __update_attrs(self):
105113
if should_be_charging:
106114
state = ATTR_STATE_CHARGING
107115

116+
# Pod should be suspended evse if pod is charging and connectivity status is suspended evse
117+
if should_be_suspended_evse:
118+
state = ATTR_STATE_SUSPENDED_EVSE
119+
120+
# Pod should be suspended ev if pod is charging and connectivity status is suspended ev
121+
if should_be_suspended_ev:
122+
state = ATTR_STATE_SUSPENDED_EV
123+
108124
# Should this pod be pending?
109125
if should_be_pending:
110126
state = ATTR_STATE_PENDING

custom_components/pod_point/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -570,5 +570,5 @@
570570
"aiodiscover",
571571
"scapy"
572572
],
573-
"version": "2.0.0"
573+
"version": "2.0.2"
574574
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
"""Version of the Pod Point integration"""
22

3-
__version__ = "2.0.0"
3+
__version__ = "2.0.2"

tests/test_binary_sensor.py

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
"""Test pod_point binary sensors."""
2+
3+
from typing import List, Union
4+
from unittest.mock import Mock, call, patch
5+
6+
from homeassistant.components.binary_sensor import (
7+
BinarySensorDeviceClass,
8+
BinarySensorEntity,
9+
)
10+
from homeassistant.helpers.entity import EntityCategory
11+
import pytest
12+
from pytest_homeassistant_custom_component.common import MockConfigEntry
13+
14+
from custom_components.pod_point import async_setup_entry
15+
from custom_components.pod_point.const import (
16+
ATTR_CONNECTION_STATE_ONLINE,
17+
DOMAIN, ATTR_STATE,
18+
)
19+
from custom_components.pod_point.binary_sensor import (
20+
PodPointCableConnectionSensor,
21+
PodPointCloudConnectionSensor,
22+
async_setup_entry,
23+
)
24+
from podpointclient.connectivity_status import ConnectivityStatus, Evse
25+
26+
from .const import MOCK_CONFIG
27+
from .fixtures import CONNECTIVITY_STATUS_COMPLETE_FIXTURE
28+
from .test_coordinator import subject_with_data as coordinator_with_data
29+
30+
31+
async def setup_sensors(hass) -> List[BinarySensorEntity]:
32+
"""Setup sensors within the test environment"""
33+
coordinator = await coordinator_with_data(hass)
34+
35+
# Create a mock entry so we don't have to go through config flow
36+
config_entry = MockConfigEntry(domain=DOMAIN, data=MOCK_CONFIG, entry_id="test")
37+
38+
hass.data[DOMAIN] = {}
39+
hass.data[DOMAIN][config_entry.entry_id] = coordinator
40+
41+
mock = Mock()
42+
43+
await async_setup_entry(hass, config_entry, mock)
44+
45+
print(mock.call_args_list)
46+
sensors: List[Union(PodPointCableConnectionSensor, PodPointCloudConnectionSensor)] = (
47+
mock.call_args_list[0][0][0]
48+
)
49+
50+
return (config_entry, sensors)
51+
52+
53+
@pytest.mark.asyncio
54+
async def test_sensor_creation(hass, bypass_get_data):
55+
"""Test that the expected number of sensors is created"""
56+
57+
(_, sensors) = await setup_sensors(hass)
58+
59+
assert 2 == len(sensors)
60+
61+
62+
@pytest.mark.asyncio
63+
async def test_cloud_connection_sensor(hass, bypass_get_data):
64+
"""Tests for pod status sensor."""
65+
(_, sensors) = await setup_sensors(hass)
66+
67+
[_, status] = sensors
68+
69+
assert BinarySensorDeviceClass.CONNECTIVITY == status.device_class
70+
assert EntityCategory.DIAGNOSTIC == status.entity_category
71+
assert "pod_point_12234_PSL-123456_cloud_connection" == status.unique_id
72+
assert "Cloud Connection" == status.name
73+
74+
status.pod.connectivity_status = ConnectivityStatus(CONNECTIVITY_STATUS_COMPLETE_FIXTURE)
75+
assert status.is_on is True
76+
assert "mdi:cloud-check-variant" == status.icon
77+
78+
status.pod.connectivity_status.evses[0].connectivity_state.connectivity_status = "FOO"
79+
assert status.is_on is False
80+
assert "mdi:cloud-off" == status.icon
81+
82+
83+
@pytest.mark.asyncio
84+
async def test_cable_connection_sensor(hass, bypass_get_data):
85+
"""Tests for pod status sensor."""
86+
(_, sensors) = await setup_sensors(hass)
87+
88+
[status, _] = sensors
89+
90+
assert BinarySensorDeviceClass.PLUG == status.device_class
91+
assert "pod_point_12234_PSL-123456_cable_status" == status.unique_id
92+
assert "Cable Status" == status.name
93+
94+
status.extra_attrs[ATTR_STATE] = "charging"
95+
assert status.is_on is True
96+
97+
status.extra_attrs[ATTR_STATE] = "available"
98+
assert status.is_on is False
99+
100+
status.extra_attrs[ATTR_STATE] = "connected-waiting-for-schedule"
101+
assert status.is_on is True
102+
103+
status.extra_attrs[ATTR_STATE] = "suspended-evse"
104+
assert status.is_on is True
105+
106+
status.extra_attrs[ATTR_STATE] = "suspended-ev"
107+
assert status.is_on is True
108+
109+
status.extra_attrs[ATTR_STATE] = "foo"
110+
assert status.is_on is False
111+

tests/test_entity.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
"""Test pod_point switch."""
22

33
# import asyncio
4-
from datetime import datetime
4+
from datetime import datetime, timedelta
55
from email.utils import encode_rfc2231
66
from typing import List
77
from unittest.mock import Mock, call, patch
8+
import pytz
89

910
# import aiohttp
1011
from homeassistant.components import switch
@@ -318,6 +319,32 @@ async def test_pod_point_entity(hass, bypass_get_data):
318319
entity.pod.model.name = None
319320
assert None == entity.image
320321

322+
# Test states for ev and evse suspended
323+
assert "charging" == entity.state
324+
entity.pod.charging_state = "suspended-ev"
325+
entity._PodPointEntity__update_attrs()
326+
assert entity.state == "suspended-ev"
327+
328+
entity.pod.charging_state = "suspended-evse"
329+
entity._PodPointEntity__update_attrs()
330+
assert entity.state == "suspended-evse"
331+
332+
entity.pod.statuses[0].key_name = 'available'
333+
entity.pod.charging_state = "suspended-evse"
334+
entity._PodPointEntity__update_attrs()
335+
assert entity.state == "available"
336+
337+
entity.pod.statuses[0].key_name = 'out-of-service'
338+
entity.pod.charging_state = "suspended-evse"
339+
entity._PodPointEntity__update_attrs()
340+
assert entity.state == "out-of-service"
341+
342+
# Test pending status
343+
entity.coordinator.last_message_at = datetime.now(tz=pytz.utc)
344+
entity.pod.last_message_at = datetime.now(tz=pytz.utc) - timedelta(minutes=5)
345+
entity._PodPointEntity__update_attrs()
346+
assert entity.state == "pending"
347+
321348

322349
@pytest.mark.asyncio
323350
async def test_compare_state(hass, bypass_get_data):

0 commit comments

Comments
 (0)