Skip to content

Commit 8907050

Browse files
committed
Fix device renaming on role change
Plus tidy up signals by moving them to const.py
1 parent 8efe500 commit 8907050

File tree

8 files changed

+145
-96
lines changed

8 files changed

+145
-96
lines changed

custom_components/powersensor/PowersensorDiscoveryService.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@
66
from homeassistant.helpers.dispatcher import async_dispatcher_send
77
import homeassistant.components.zeroconf
88

9-
from .const import DOMAIN
9+
from .const import (
10+
ZEROCONF_ADD_PLUG_SIGNAL,
11+
ZEROCONF_REMOVE_PLUG_SIGNAL,
12+
ZEROCONF_UPDATE_PLUG_SIGNAL,
13+
)
1014

1115
import logging
1216
_LOGGER = logging.getLogger(__name__)
@@ -30,7 +34,7 @@ def add_service(self, zc, type_, name):
3034
)
3135

3236
async def _async_service_add(self, *args):
33-
async_dispatcher_send(self._hass, f"{DOMAIN}_zeroconf_add_plug", *args)
37+
async_dispatcher_send(self._hass, ZEROCONF_ADD_PLUG_SIGNAL, *args)
3438

3539

3640
async def _async_delayed_remove(self, name):
@@ -68,7 +72,7 @@ def remove_service(self, zc, type_, name):
6872
)
6973

7074
async def _async_service_remove(self, *args):
71-
async_dispatcher_send(self._hass, f"{DOMAIN}_zeroconf_remove_plug", *args)
75+
async_dispatcher_send(self._hass, ZEROCONF_REMOVE_PLUG_SIGNAL, *args)
7276

7377
def update_service(self, zc, type_, name):
7478
self.cancel_any_pending_removal(name, "request to update")
@@ -81,7 +85,7 @@ def update_service(self, zc, type_, name):
8185

8286
async def _async_service_update(self, *args):
8387
# remove from pending tasks if update received
84-
async_dispatcher_send(self._hass, f"{DOMAIN}_zeroconf_update_plug", *args)
88+
async_dispatcher_send(self._hass, ZEROCONF_UPDATE_PLUG_SIGNAL, *args)
8589

8690
async def _async_get_service_info(self, zc, type_, name):
8791
try:
@@ -160,4 +164,4 @@ async def stop(self):
160164
self.zc = None
161165

162166
self.browser = None
163-
self.listener = None
167+
self.listener = None

custom_components/powersensor/PowersensorEntity.py

Lines changed: 37 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,18 @@
1111
from homeassistant.util.dt import utcnow
1212
from .PlugMeasurements import PlugMeasurements
1313
from .SensorMeasurements import SensorMeasurements
14-
from .const import DOMAIN, POWER_SENSOR_UPDATE_SIGNAL
14+
from .const import DATA_UPDATE_SIGNAL_FMT_MAC_EVENT, DOMAIN, ROLE_UPDATE_SIGNAL
1515

1616
import logging
1717
_LOGGER = logging.getLogger(__name__)
1818

1919
class PowersensorEntity(SensorEntity):
2020
"""Powersensor Plug Class--designed to handle all measurements of the plug--perhaps less expressive"""
21-
def __init__(self, hass: HomeAssistant, mac : str,
21+
def __init__(self, hass: HomeAssistant, mac: str, role: str,
2222
input_config: dict[Union[SensorMeasurements|PlugMeasurements], dict],
2323
measurement_type: SensorMeasurements|PlugMeasurements, timeout_seconds: int = 60):
2424
"""Initialize the sensor."""
25-
self.role = None
25+
self._role = role
2626
self._has_recently_received_update_message = False
2727
self._attr_native_value = 0.0
2828
self._hass = hass
@@ -44,7 +44,7 @@ def __init__(self, hass: HomeAssistant, mac : str,
4444
self._attr_entity_category = config.get('category', None)
4545
self._attr_state_class = config.get('state_class', None)
4646

47-
self._signal = f"{POWER_SENSOR_UPDATE_SIGNAL}_{self._mac}_{config['event']}"
47+
self._signal = DATA_UPDATE_SIGNAL_FMT_MAC_EVENT % (mac, config['event'])
4848
self._message_key = config.get('message_key', None)
4949
self._message_callback = config.get('callback', None)
5050

@@ -81,6 +81,11 @@ async def async_added_to_hass(self) -> None:
8181
self._signal,
8282
self._handle_update
8383
))
84+
self.async_on_remove(async_dispatcher_connect(
85+
self._hass,
86+
ROLE_UPDATE_SIGNAL,
87+
self._handle_role_update
88+
))
8489

8590
async def async_will_remove_from_hass(self):
8691
"""Clean up."""
@@ -91,27 +96,12 @@ def _rename_based_on_role(self):
9196
return False
9297

9398
@callback
94-
def _handle_update(self, event, message):
95-
"""handle pushed data."""
96-
97-
# event is not presently used, but is passed to maintain flexibility for future development
98-
99-
name_updated = False
100-
self._has_recently_received_update_message = True
99+
def _handle_role_update(self, mac: str, role: str):
100+
if self._mac != mac or self._role == role:
101+
return
101102

102-
role = message.get('role', None)
103-
if role is not None and role != self.role:
104-
self.role = role
105-
name_updated = self._rename_based_on_role()
106-
async_dispatcher_send(self._hass, f"{DOMAIN}_update_role", self._mac, role)
107-
108-
109-
if self._message_key in message.keys():
110-
if self._message_callback:
111-
self._attr_native_value = self._message_callback( message[self._message_key])
112-
else:
113-
self._attr_native_value = message[self._message_key]
114-
self._schedule_unavailable()
103+
self._role = role
104+
name_updated = self._rename_based_on_role()
115105

116106
if name_updated:
117107
device_registry = dr.async_get(self._hass)
@@ -131,5 +121,27 @@ def _handle_update(self, event, message):
131121
self.entity_id,
132122
name = self._attr_name
133123
)
134-
self.async_write_ha_state()
135124

125+
self.async_write_ha_state()
126+
127+
@callback
128+
def _handle_update(self, event, message):
129+
"""handle pushed data."""
130+
131+
# event is not presently used, but is passed to maintain flexibility for future development
132+
133+
name_updated = False
134+
self._has_recently_received_update_message = True
135+
136+
role = message.get('role', None)
137+
if role is not None and role != self._role:
138+
async_dispatcher_send(self._hass, ROLE_UPDATE_SIGNAL, self._mac, role)
139+
140+
if self._message_key in message.keys():
141+
if self._message_callback:
142+
self._attr_native_value = self._message_callback( message[self._message_key])
143+
else:
144+
self._attr_native_value = message[self._message_key]
145+
self._schedule_unavailable()
146+
147+
self.async_write_ha_state()

custom_components/powersensor/PowersensorMessageDispatcher.py

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,18 @@
99
from powersensor_local import PlugApi, VirtualHousehold
1010

1111
from custom_components.powersensor.AsyncSet import AsyncSet
12-
from custom_components.powersensor.const import POWER_SENSOR_UPDATE_SIGNAL, DOMAIN
12+
from custom_components.powersensor.const import (
13+
CREATE_PLUG_SIGNAL,
14+
CREATE_SENSOR_SIGNAL,
15+
DATA_UPDATE_SIGNAL_FMT_MAC_EVENT,
16+
PLUG_ADDED_TO_HA_SIGNAL,
17+
SENSOR_ADDED_TO_HA_SIGNAL,
18+
SOLAR_ADDED_TO_VHH_SIGNAL,
19+
SOLAR_SENSOR_DETECTED_SIGNAL,
20+
ZEROCONF_ADD_PLUG_SIGNAL,
21+
ZEROCONF_REMOVE_PLUG_SIGNAL,
22+
ZEROCONF_UPDATE_PLUG_SIGNAL,
23+
)
1324

1425
_LOGGER = logging.getLogger(__name__)
1526
class PowersensorMessageDispatcher:
@@ -30,22 +41,22 @@ def __init__(self, hass: HomeAssistant, entry: ConfigEntry, vhh: VirtualHousehol
3041
self._solar_request_limit = datetime.timedelta(seconds = 10)
3142
self._unsubscribe_from_signals = [
3243
async_dispatcher_connect(self._hass,
33-
f"{DOMAIN}_sensor_added_to_homeassistant",
44+
SENSOR_ADDED_TO_HA_SIGNAL,
3445
self._acknowledge_sensor_added_to_homeassistant),
3546
async_dispatcher_connect(self._hass,
36-
f"{DOMAIN}_zeroconf_add_plug",
47+
ZEROCONF_ADD_PLUG_SIGNAL,
3748
self._plug_added),
3849
async_dispatcher_connect(self._hass,
39-
f"{DOMAIN}_zeroconf_update_plug",
50+
ZEROCONF_UPDATE_PLUG_SIGNAL,
4051
self._plug_updated),
4152
async_dispatcher_connect(self._hass,
42-
f"{DOMAIN}_zeroconf_remove_plug",
53+
ZEROCONF_REMOVE_PLUG_SIGNAL,
4354
self._schedule_plug_removal),
4455
async_dispatcher_connect(self._hass,
45-
f"{DOMAIN}_plug_added_to_homeassistant",
56+
PLUG_ADDED_TO_HA_SIGNAL,
4657
self._acknowledge_plug_added_to_homeassistant),
4758
async_dispatcher_connect(self._hass,
48-
f"{DOMAIN}_solar_added_to_virtual_household",
59+
SOLAR_ADDED_TO_VHH_SIGNAL,
4960
self._acknowledge_solar_added_to_virtual_household),
5061
]
5162

@@ -78,7 +89,7 @@ async def _monitor_plug_queue(self):
7889
for mac_address, host, port, name in queue_snapshot:
7990
#@todo: maybe better to query the entity registry?
8091
if not self._plug_has_been_seen(mac_address, name):
81-
async_dispatcher_send(self._hass, f"{DOMAIN}_create_plug",
92+
async_dispatcher_send(self._hass, CREATE_PLUG_SIGNAL,
8293
mac_address, host, port, name)
8394
elif mac_address in self._known_plugs and not mac_address in self.plugs:
8495
_LOGGER.info(f"Plug with mac {mac_address} is known, but API is missing."
@@ -173,7 +184,7 @@ async def handle_message(self, event: str, message: dict):
173184
if mac not in self.sensors:
174185
if role is not None:
175186
self.on_start_sensor_queue[mac] = role
176-
async_dispatcher_send(self._hass, f"{DOMAIN}_create_sensor", mac, role)
187+
async_dispatcher_send(self._hass, CREATE_SENSOR_SIGNAL, mac, role)
177188

178189
# Feed the household calculations
179190
if event == 'average_power':
@@ -187,10 +198,13 @@ async def handle_message(self, event: str, message: dict):
187198
if self._last_request_to_notify_about_solar + self._solar_request_limit <new_time:
188199
self._last_request_to_notify_about_solar = new_time
189200
_LOGGER.debug("Notifying integration that solar is present.")
190-
async_dispatcher_send(self._hass, f"{DOMAIN}_solar_sensor_detected")
191-
async_dispatcher_send(self._hass, f"{POWER_SENSOR_UPDATE_SIGNAL}_{mac}_{event}", event, message)
201+
async_dispatcher_send(self._hass, SOLAR_SENSOR_DETECTED_SIGNAL)
202+
async_dispatcher_send(self._hass,
203+
DATA_UPDATE_SIGNAL_FMT_MAC_EVENT % (mac, event), event, message)
192204
if role is not None:
193-
async_dispatcher_send(self._hass, f"{POWER_SENSOR_UPDATE_SIGNAL}_{mac}_role", 'role', { 'role': role })
205+
async_dispatcher_send(
206+
self._hass, DATA_UPDATE_SIGNAL_FMT_MAC_EVENT % (mac, role),
207+
'role', { 'role': role })
194208

195209
async def disconnect(self):
196210
for _ in range(len(self.plugs)):

custom_components/powersensor/PowersensorPlugEntity.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,9 @@
7979

8080
class PowersensorPlugEntity(PowersensorEntity):
8181
"""Powersensor Plug Class--designed to handle all measurements of the plug--perhaps less expressive"""
82-
def __init__(self, hass: HomeAssistant, mac_address: str, measurement_type: PlugMeasurements):
82+
def __init__(self, hass: HomeAssistant, mac_address: str, role: str, measurement_type: PlugMeasurements):
8383
"""Initialize the sensor."""
84-
super().__init__(hass, mac_address, _config, measurement_type)
84+
super().__init__(hass, mac_address, role, _config, measurement_type)
8585
self._model = f"PowersensorPlug"
8686
self.measurement_type = measurement_type
8787
config = _config[measurement_type]

custom_components/powersensor/PowersensorSensorEntity.py

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -51,44 +51,43 @@
5151

5252
class PowersensorSensorEntity(PowersensorEntity):
5353
"""Powersensor Plug Class--designed to handle all measurements of the plug--perhaps less expressive"""
54-
def __init__(self, hass: HomeAssistant, mac : str,
54+
def __init__(self, hass: HomeAssistant, mac: str, role: str,
5555
measurement_type: SensorMeasurements):
5656
"""Initialize the sensor."""
57-
super().__init__(hass, mac, _config, measurement_type)
57+
super().__init__(hass, mac, role, _config, measurement_type)
5858
self._model = f"PowersensorSensor"
5959
self.measurement_type = measurement_type
6060
config = _config[measurement_type]
6161
self._measurement_name = config['name']
6262
self._device_name = self._default_device_name()
6363
self._attr_name = f"{self._device_name} {self._measurement_name}"
64-
self._rename_based_on_role()
6564

6665
@property
6766
def device_info(self) -> DeviceInfo:
6867
return {
6968
'identifiers': {(DOMAIN, self._mac)},
7069
'manufacturer': "Powersensor",
7170
'model': self._model,
72-
'name': self._device_name ,
71+
'name': self._device_name,
7372
}
7473

7574
def _ensure_matching_prefix(self):
7675
if not self._attr_name.startswith(self._device_name):
7776
self._attr_name = f"{self._device_name} {self._measurement_name }"
7877

79-
def _rename_based_on_role(self):
80-
if self._device_name == self._default_device_name():
81-
if self.role =='house-net' or self.role == "water" or self.role == "solar":
82-
role2name = {
83-
"house-net": "Powersensor Mains Sensor ⚡",
84-
"solar": "Powersensor Solar Sensor ⚡",
85-
"water": "Powersensor Water Sensor 💧",
86-
}
87-
self._device_name = role2name[self.role]
88-
self._ensure_matching_prefix()
89-
return True
90-
return False
91-
92-
def _default_device_name(self):
93-
return SENSOR_NAME_FORMAT % self._mac
78+
def _rename_based_on_role(self) -> bool:
79+
expected_name = self._default_device_name()
80+
if self._device_name != expected_name:
81+
self._device_name = expected_name
82+
self._ensure_matching_prefix()
83+
return True
84+
else:
85+
return False
9486

87+
def _default_device_name(self) -> str:
88+
role2name = {
89+
"house-net": "Powersensor Mains Sensor ⚡",
90+
"solar": "Powersensor Solar Sensor ⚡",
91+
"water": "Powersensor Water Sensor 💧",
92+
}
93+
return role2name[self._role] if self._role in [ "house-net", "water", "solar" ] else SENSOR_NAME_FORMAT % self._mac

custom_components/powersensor/config_flow.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from homeassistant.helpers.service_info import zeroconf
1010
from homeassistant.helpers.selector import selector
1111

12-
from .const import DEFAULT_PORT, DOMAIN, SENSOR_NAME_FORMAT
12+
from .const import DEFAULT_PORT, DOMAIN, ROLE_UPDATE_SIGNAL, SENSOR_NAME_FORMAT
1313

1414
def _extract_device_name(discovery_info) -> str:
1515
"""Extract a user-friendly device name from zeroconf info."""
@@ -65,7 +65,7 @@ async def async_step_reconfigure(self, user_input: dict | None = None)->FlowResu
6565
if role == unknown:
6666
role = None
6767
_LOGGER.debug(f"Applying {role} to {mac}")
68-
async_dispatcher_send(self.hass, f"{DOMAIN}_update_role", mac, role)
68+
async_dispatcher_send(self.hass, ROLE_UPDATE_SIGNAL, mac, role)
6969
return self.async_abort(reason="Roles successfully applied!")
7070

7171
sensor_roles = {}

custom_components/powersensor/const.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,18 @@
44
DEFAULT_NAME = "Powersensor"
55
DEFAULT_PORT = 49476
66
DEFAULT_SCAN_INTERVAL = 30
7-
POWER_SENSOR_UPDATE_SIGNAL = f"{DOMAIN}_sensor"
7+
8+
CREATE_PLUG_SIGNAL = f"{DOMAIN}_create_plug"
9+
CREATE_SENSOR_SIGNAL = f"{DOMAIN}_create_sensor"
10+
DATA_UPDATE_SIGNAL_FMT_MAC_EVENT = f"{DOMAIN}_data_update_%s_%s"
11+
ROLE_UPDATE_SIGNAL = f"{DOMAIN}_update_role"
12+
PLUG_ADDED_TO_HA_SIGNAL = f"{DOMAIN}_plug_added_to_homeassistant"
13+
SENSOR_ADDED_TO_HA_SIGNAL = f"{DOMAIN}_sensor_added_to_homeassistant"
14+
SOLAR_SENSOR_DETECTED_SIGNAL = f"{DOMAIN}_solar_sensor_detected"
15+
SOLAR_ADDED_TO_VHH_SIGNAL = f"{DOMAIN}_solar_added_to_virtual_household"
16+
ZEROCONF_ADD_PLUG_SIGNAL = f"{DOMAIN}_zeroconf_add_plug"
17+
ZEROCONF_REMOVE_PLUG_SIGNAL = f"{DOMAIN}_zeroconf_remove_plug"
18+
ZEROCONF_UPDATE_PLUG_SIGNAL = f"{DOMAIN}_zeroconf_update_plug"
19+
820

921
SENSOR_NAME_FORMAT = "Powersensor Sensor (ID: %s) ⚡"

0 commit comments

Comments
 (0)