Skip to content

Commit 49033b3

Browse files
committed
Add device role as diagnostic entity
1 parent 0654110 commit 49033b3

File tree

8 files changed

+83
-26
lines changed

8 files changed

+83
-26
lines changed

custom_components/powersensor/PlugMeasurements.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ class PlugMeasurements(Enum):
77
ACTIVE_CURRENT = 4
88
REACTIVE_CURRENT = 5
99
SUMMATION_ENERGY = 6
10+
ROLE = 7

custom_components/powersensor/PowersensorEntity.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from homeassistant.helpers.device_registry import DeviceInfo
77
from homeassistant.helpers import device_registry as dr
88
from homeassistant.helpers import entity_registry as er
9-
from homeassistant.helpers.dispatcher import async_dispatcher_connect
9+
from homeassistant.helpers.dispatcher import async_dispatcher_connect, async_dispatcher_send
1010
from homeassistant.helpers.event import async_track_point_in_utc_time
1111
from homeassistant.util.dt import utcnow
1212
from .PlugMeasurements import PlugMeasurements
@@ -36,15 +36,15 @@ def __init__(self, hass: HomeAssistant, mac : str,
3636
self.measurement_type = measurement_type
3737
config = input_config[measurement_type]
3838
self._attr_unique_id = f"powersensor_{mac}_{measurement_type}"
39-
self._attr_device_class = config["device_class"]
40-
self._attr_native_unit_of_measurement = config["unit"]
39+
self._attr_device_class = config.get("device_class", None)
40+
self._attr_native_unit_of_measurement = config.get("unit", None)
4141
self._attr_device_info = self.device_info
42-
self._attr_suggested_display_precision = config["precision"]
43-
self._attr_entity_registry_visible_default = config['visible'] if 'visible' in config.keys() else True
42+
self._attr_suggested_display_precision = config.get("precision", None)
43+
self._attr_entity_registry_visible_default = config.get('visible', True)
44+
self._attr_entity_category = config.get('category', None)
45+
self._attr_state_class = config.get('state_class', None)
4446

4547
self._signal = f"{POWER_SENSOR_UPDATE_SIGNAL}_{self._mac}_{config['event']}"
46-
if 'state_class' in config.keys():
47-
self._attr_state_class = config['state_class']
4848
self._message_key = config.get('message_key', None)
4949
self._message_callback = config.get('callback', None)
5050

@@ -98,10 +98,11 @@ def _handle_update(self, event, message):
9898

9999
name_updated = False
100100
self._has_recently_received_update_message = True
101-
if not self.role:
102-
if 'role' in message.keys():
103-
self.role = message['role']
104-
name_updated = self._rename_based_on_role()
101+
role = message.get('role', None)
102+
if role is not None and role != self.role:
103+
self.role = role
104+
name_updated = self._rename_based_on_role()
105+
async_dispatcher_send(self._hass, f"{DOMAIN}_update_role", self._mac, role)
105106

106107

107108
if self._message_key in message.keys():

custom_components/powersensor/PowersensorMessageDispatcher.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,8 @@ async def handle_message(self, event: str, message: dict):
185185
_LOGGER.debug("Notifying integration that solar is present.")
186186
async_dispatcher_send(self._hass, f"{DOMAIN}_solar_sensor_detected")
187187
async_dispatcher_send(self._hass, f"{POWER_SENSOR_UPDATE_SIGNAL}_{mac}_{event}", event, message)
188+
if role is not None:
189+
async_dispatcher_send(self._hass, f"{POWER_SENSOR_UPDATE_SIGNAL}_{mac}_role", 'role', { 'role': role })
188190

189191
async def disconnect(self):
190192
for _ in range(len(self.plugs)):

custom_components/powersensor/PowersensorPlugEntity.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import logging
22

33
from homeassistant.components.sensor import SensorDeviceClass, SensorStateClass
4-
from homeassistant.const import UnitOfPower, UnitOfElectricPotential, UnitOfElectricCurrent, UnitOfEnergy
4+
from homeassistant.const import EntityCategory, UnitOfPower, UnitOfElectricPotential, UnitOfElectricCurrent, UnitOfEnergy
55
from homeassistant.core import HomeAssistant
66
from homeassistant.helpers.device_registry import DeviceInfo
77

@@ -67,6 +67,12 @@
6767
'message_key': 'summation_joules',
6868
'callback' : lambda v : v/3600000.0
6969
},
70+
PlugMeasurements.ROLE: {
71+
'name': 'Device Role',
72+
'category': EntityCategory.DIAGNOSTIC,
73+
'event': 'role',
74+
'message_key': 'role',
75+
},
7076
}
7177

7278

custom_components/powersensor/PowersensorSensorEntity.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from homeassistant.components.sensor import SensorDeviceClass, SensorStateClass
2-
from homeassistant.const import UnitOfPower, UnitOfEnergy, PERCENTAGE
2+
from homeassistant.const import EntityCategory, UnitOfPower, UnitOfEnergy, PERCENTAGE
33
from homeassistant.core import HomeAssistant
44
from homeassistant.helpers.device_registry import DeviceInfo
55

@@ -39,7 +39,13 @@
3939
'event': 'summation_energy',
4040
'message_key': 'summation_joules',
4141
'callback': lambda v: v / 3600000.0
42-
}
42+
},
43+
SensorMeasurements.ROLE: {
44+
'name': 'Device Role',
45+
'category': EntityCategory.DIAGNOSTIC,
46+
'event': 'role',
47+
'message_key': 'role',
48+
},
4349
}
4450

4551
class PowersensorSensorEntity(PowersensorEntity):

custom_components/powersensor/SensorMeasurements.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ class SensorMeasurements(Enum):
55
Battery =1
66
WATTS = 2
77
SUMMATION_ENERGY = 3
8+
ROLE = 4

custom_components/powersensor/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
# mac =,
2727
# host =,
2828
# port =,
29+
# role =,
2930
# }
3031
# with_solar =,
3132
# }

custom_components/powersensor/sensor.py

Lines changed: 51 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
"""Sensor platform for the integration."""
22
from __future__ import annotations
33

4+
import copy
45
import logging
56

67
from homeassistant.config_entries import ConfigEntry
@@ -15,7 +16,7 @@
1516
from .PowersensorPlugEntity import PowersensorPlugEntity
1617
from .PowersensorSensorEntity import PowersensorSensorEntity
1718
from .SensorMeasurements import SensorMeasurements
18-
from .const import DOMAIN
19+
from .const import POWER_SENSOR_UPDATE_SIGNAL, DOMAIN
1920
_LOGGER = logging.getLogger(__name__)
2021

2122

@@ -30,22 +31,60 @@ async def async_setup_entry(
3031

3132

3233
async def create_plug(plug_mac_address: str):
33-
this_plug_sensors = [PowersensorPlugEntity(hass, plug_mac_address, PlugMeasurements.WATTS),
34-
PowersensorPlugEntity(hass, plug_mac_address, PlugMeasurements.VOLTAGE),
35-
PowersensorPlugEntity(hass, plug_mac_address, PlugMeasurements.APPARENT_CURRENT),
36-
PowersensorPlugEntity(hass, plug_mac_address, PlugMeasurements.ACTIVE_CURRENT),
37-
PowersensorPlugEntity(hass, plug_mac_address, PlugMeasurements.REACTIVE_CURRENT),
38-
PowersensorPlugEntity(hass, plug_mac_address, PlugMeasurements.SUMMATION_ENERGY)]
34+
this_plug_sensors = [
35+
PowersensorPlugEntity(hass, plug_mac_address, PlugMeasurements.WATTS),
36+
PowersensorPlugEntity(hass, plug_mac_address, PlugMeasurements.VOLTAGE),
37+
PowersensorPlugEntity(hass, plug_mac_address, PlugMeasurements.APPARENT_CURRENT),
38+
PowersensorPlugEntity(hass, plug_mac_address, PlugMeasurements.ACTIVE_CURRENT),
39+
PowersensorPlugEntity(hass, plug_mac_address, PlugMeasurements.REACTIVE_CURRENT),
40+
PowersensorPlugEntity(hass, plug_mac_address, PlugMeasurements.SUMMATION_ENERGY),
41+
PowersensorPlugEntity(hass, plug_mac_address, PlugMeasurements.ROLE),
42+
]
3943

4044
async_add_entities(this_plug_sensors, True)
4145

4246
for plug_mac in dispatcher.plugs.keys():
4347
await create_plug(plug_mac)
4448

49+
50+
# Role update support
51+
async def handle_role_update(mac_address: str, new_role: str):
52+
persist_entry = False
53+
new_data = copy.deepcopy({ **entry.data })
54+
55+
if new_role is not None:
56+
devices = new_data['devices']
57+
if mac_address in devices.keys():
58+
info = devices[mac_address]
59+
have_role = True if 'role' in info.keys() else False
60+
old_role = info['role'] if have_role else None
61+
if (not have_role) or (have_role and info['role'] != new_role):
62+
_LOGGER.debug(f"Updating role for {mac_address} from {old_role} to {new_role}")
63+
info['role'] = new_role
64+
persist_entry = True
65+
66+
if new_role == 'solar':
67+
new_data['with_solar'] = True # Remember for next time we start
68+
persist_entry = True
69+
70+
if persist_entry:
71+
hass.config_entries.async_update_entry(entry, data=new_data)
72+
73+
# These events are sent by the entities when their cached role updates
74+
entry.async_on_unload(
75+
async_dispatcher_connect(
76+
hass, f"{DOMAIN}_update_role", handle_role_update
77+
)
78+
)
79+
80+
81+
# Automatic plug discovery
4582
async def handle_discovered_plug(plug_mac_address: str, host: str, port: int, name: str):
4683
await create_plug(plug_mac_address)
4784
async_dispatcher_send(hass, f"{DOMAIN}_plug_added_to_homeassistant",
4885
plug_mac_address, host, port, name)
86+
async_dispatcher_send(hass, f"{DOMAIN}_update_role",
87+
plug_mac_address, "appliance") # default role
4988

5089
entry.async_on_unload(
5190
async_dispatcher_connect(
@@ -54,19 +93,19 @@ async def handle_discovered_plug(plug_mac_address: str, host: str, port: int, na
5493
)
5594
await dispatcher.process_plug_queue()
5695

57-
async def handle_discovered_sensor(sensor_mac: str, sensor_role: str):
58-
if sensor_role == 'solar':
59-
new_data = { **entry.data }
60-
new_data['with_solar'] = True # Remember for next time we start
61-
hass.config_entries.async_update_entry(entry, data=new_data)
6296

97+
# Automatic sensor discovery
98+
async def handle_discovered_sensor(sensor_mac: str, sensor_role: str):
6399
new_sensors = [
64100
PowersensorSensorEntity(hass, sensor_mac, SensorMeasurements.Battery),
65101
PowersensorSensorEntity(hass, sensor_mac, SensorMeasurements.WATTS),
66102
PowersensorSensorEntity(hass, sensor_mac, SensorMeasurements.SUMMATION_ENERGY),
103+
PowersensorSensorEntity(hass, sensor_mac, SensorMeasurements.ROLE),
67104
]
68105
async_add_entities(new_sensors, True)
69106
async_dispatcher_send(hass, f"{DOMAIN}_sensor_added_to_homeassistant", sensor_mac, sensor_role)
107+
# Trigger initial entity role update
108+
async_dispatcher_send(hass, f"{POWER_SENSOR_UPDATE_SIGNAL}_{sensor_mac}_role", 'role', { 'role': sensor_role })
70109

71110
entry.async_on_unload(
72111
async_dispatcher_connect(

0 commit comments

Comments
 (0)