Skip to content

Commit 1936d96

Browse files
committed
Quick fix for the last commit
1 parent 7194c80 commit 1936d96

3 files changed

Lines changed: 97 additions & 71 deletions

File tree

custom_components/petlibro/helpers/unit_entities.py

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@
77
from homeassistant.config_entries import ConfigEntry
88
from homeassistant.exceptions import HomeAssistantError
99
from homeassistant.helpers.entity_registry import (
10-
async_get as get_entity_registry,
11-
RegistryEntryDisabler,
10+
async_get as get_entity_registry,
11+
RegistryEntryDisabler,
1212
RegistryEntryHider
1313
)
1414

@@ -32,7 +32,7 @@ class Unit_Entities:
3232
An example of a unit entity is the sensor 'today_feeding_quantity_weight', which syncronises with
3333
Petlibro Feeder units to display feed quantities in the user's configured feed weight.
3434
"""
35-
35+
3636
def __init__(self, *, hass: HomeAssistant, config_entry: ConfigEntry, hub: PetLibroHub):
3737
"""Initialise the Unit_Entities class."""
3838
self.hass = hass
@@ -42,9 +42,9 @@ def __init__(self, *, hass: HomeAssistant, config_entry: ConfigEntry, hub: PetLi
4242
self.member = self.hub.member
4343
self.entity_registry = get_entity_registry(self.hass)
4444
self._sync_task = None
45-
45+
4646
async def sync_manual_feed_entity_visibility(
47-
self, /, feed_unit: Unit | None = UNDEFINED, include_portions: bool = True,
47+
self, /, feed_unit: Unit | None = UNDEFINED, include_portions: bool = True,
4848
) -> bool:
4949
"""Enable/disable and hide/unhide manual feed entities based on compatibility.
5050
@@ -58,61 +58,61 @@ async def sync_manual_feed_entity_visibility(
5858

5959
numbers = self.hub.manual_feed_unique_ids.get(Platform.NUMBER)
6060
selects = self.hub.manual_feed_unique_ids.get(Platform.SELECT)
61-
61+
6262
if len(numbers) != len(selects):
63-
raise HomeAssistantError(
63+
_LOGGER.error(
6464
"Not all Number entities have an equivalent Select entity, or vice versa. "
65-
f"Please open an issue at {GITHUB}/issues if the problem persists.\n"
66-
f"Number entities: {numbers}\nSelect entities: {selects}"
65+
"Please open an issue at %s/issues if the problem persists.\n"
66+
"Number entities: %s\nSelect entities: %s", GITHUB, numbers, selects
6767
)
6868
elif not (numbers and selects):
6969
# No entities to update
7070
return False
7171

7272
feed_unit = self.member.feedUnitType if feed_unit is UNDEFINED else feed_unit
7373
set_as_portion = self.entry.options.get(MANUAL_FEED_PORTIONS) if include_portions else False
74-
75-
def incompatible(platform: Platform) -> bool:
74+
75+
def incompatible(platform: Platform) -> bool:
7676
match platform:
7777
case Platform.SELECT: return feed_unit != Unit.CUPS or set_as_portion
7878
case Platform.NUMBER: return feed_unit == Unit.CUPS and not set_as_portion
7979
case _: raise ValueError(f"Unsupported platform: {platform}")
80-
80+
8181
for platform, unique_ids in self.hub.manual_feed_unique_ids.items():
8282
entity_ids = []
8383
not_found = []
84-
84+
8585
for unique_id in unique_ids:
8686
if entity_id := self.entity_registry.async_get_entity_id(platform, DOMAIN, unique_id):
8787
entity_ids.append(entity_id)
8888
else:
8989
not_found.append(unique_id)
90-
90+
9191
if not_found:
9292
_LOGGER.warning("Manual feed entities not found for %s: %s", platform, not_found)
93-
93+
9494
if not entity_ids:
9595
continue
96-
96+
9797
incompat = incompatible(platform)
98-
disable = RegistryEntryDisabler.CONFIG_ENTRY if incompat else None
98+
disable = RegistryEntryDisabler.INTEGRATION if incompat else None
9999
hide = RegistryEntryHider.INTEGRATION if incompat else None
100-
100+
101101
action = "Hiding/disabling incompatible" if incompat else "Unhiding/enabling compatible"
102102
_LOGGER.debug("%s entities for %s: %s", action, platform, entity_ids)
103103

104-
104+
105105
for entity_id in entity_ids:
106106
self.entity_registry.async_update_entity(entity_id, disabled_by=disable, hidden_by=hide)
107-
107+
108108
return True
109-
109+
110110
@callback
111111
def schedule_manual_feed_sync(self) -> None:
112112
"""Debounce manual feed entity visibility sync calls to avoid redundant calls."""
113113
if not self._sync_task or self._sync_task.done():
114114
self._sync_task = self.hass.async_create_task(self._run_manual_feed_sync())
115-
115+
116116
async def _run_manual_feed_sync(self) -> None:
117117
"""Run the sync_manual_feed_entity_visibility method with default args and reload if needed."""
118118
reload_needed = await self.sync_manual_feed_entity_visibility()
@@ -123,21 +123,21 @@ async def update_sensor_entity_units(
123123
self, /, new_units: dict[API|str, Unit] = UNDEFINED, update_all_units: bool = False
124124
) -> bool:
125125
"""Update all sensor entity units which use Petlibro's feed, weight or water units based on account settings.
126-
126+
127127
Behavior:
128128
- If `new_units` is UNDEFINED, defaults to all three of the member's current unit types.
129129
- If `update_all_units` is True, updates all sensor entity units, and will default \
130130
to the member's current unit type for any not provided in `new_units`.
131131
- Returns True if the integration needs to be reloaded.
132132
"""
133-
133+
134134
if new_units is UNDEFINED:
135135
update_all_units = True
136136
new_units = {}
137137

138138
if not (new_units or update_all_units):
139139
return False
140-
140+
141141
reload_needed = False
142142

143143
for unit_type, unit_classes in self.hub.unit_sensor_unique_ids.items():
@@ -177,10 +177,10 @@ async def update_sensor_entity_units(
177177
entity_id, target_unit.symbol, precision,
178178
)
179179
self.entity_registry.async_update_entity_options(entity_id, Platform.SENSOR, options)
180-
180+
181181
if (
182182
unit_type is API.FEED_UNIT
183-
and Unit.CUPS in (unit, self.member.feedUnitType)
183+
and Unit.CUPS in (unit, self.member.feedUnitType)
184184
and not self.entry.options.get(MANUAL_FEED_PORTIONS)
185185
) or update_all_units:
186186
try:

custom_components/petlibro/number.py

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ class PetLibroNumberEntityDescription(NumberEntityDescription, PetLibroEntityDes
5656
device_class: Optional[NumberDeviceClass] = None
5757
entity_registry_visible_default_fn: Callable[[PetLibroNumberEntity], bool | None] = lambda _: None
5858
entity_registry_enabled_default_fn: Callable[[PetLibroNumberEntity], bool | None] = lambda _: None
59+
available_fn: Callable[[PetLibroNumberEntity], bool | None] = lambda _: None
5960
petlibro_unit: APIKey | str | None = None
6061

6162
class PetLibroNumberEntity(PetLibroEntity[_DeviceT], NumberEntity):
@@ -65,7 +66,7 @@ class PetLibroNumberEntity(PetLibroEntity[_DeviceT], NumberEntity):
6566
def __init__(self, device, hub, description):
6667
"""Initialize the number."""
6768
super().__init__(device, hub, description)
68-
69+
6970
if (unit_type := self.entity_description.petlibro_unit) and unit_type == APIKey.FEED_UNIT:
7071
self.hub.manual_feed_unique_ids[Platform.NUMBER].append(self._attr_unique_id)
7172

@@ -125,31 +126,38 @@ def native_step(self) -> float | None:
125126
if (native_step := self.entity_description.native_step_fn(self)) is not None:
126127
return native_step
127128
return super().native_step
128-
129+
130+
@property
131+
def available(self) -> bool:
132+
"""Return True if entity is available."""
133+
if (available := self.entity_description.available_fn(self)) is not None:
134+
return available
135+
return super().available
136+
129137
@property
130138
def entity_registry_visible_default(self) -> bool:
131139
"""Return if the entity should be visible when first added."""
132140
if (visible_default := self.entity_description.entity_registry_visible_default_fn(self)) is not None:
133141
return visible_default
134142
return super().entity_registry_visible_default
135-
143+
136144
@property
137145
def entity_registry_enabled_default(self) -> bool:
138146
"""Return if the entity should be enabled when first added."""
139147
if (enabled_default := self.entity_description.entity_registry_enabled_default_fn(self)) is not None:
140148
return enabled_default
141149
return super().entity_registry_enabled_default
142-
150+
143151
@property
144152
def portions_enabled(self) -> bool:
145-
"""Return True if portions are enabled for setting manual feed."""
153+
"""Return True if portions are enabled for setting manual feed."""
146154
return self.hub.entry.options.get(MANUAL_FEED_PORTIONS, False)
147-
155+
148156
@property
149157
def enable_for_manual_feed(self) -> bool:
150-
"""Return True if the platform should be enabled for setting manual feed."""
158+
"""Return True if the platform should be enabled for setting manual feed."""
151159
return self.member.feedUnitType is not Unit.CUPS or self.portions_enabled
152-
160+
153161
@callback
154162
def _handle_coordinator_update(self) -> None:
155163
"""Handle updated data from the coordinator."""
@@ -161,7 +169,7 @@ def _handle_coordinator_update(self) -> None:
161169

162170
if self.enabled:
163171
super()._handle_coordinator_update()
164-
172+
165173

166174
DEVICE_NUMBER_MAP: dict[type[Device], list[PetLibroNumberEntityDescription]] = {
167175
Feeder: [],
@@ -173,16 +181,17 @@ def _handle_coordinator_update(self) -> None:
173181
icon="mdi:scale",
174182
mode=NumberMode.SLIDER,
175183
native_unit_of_measurement_fn=lambda s: s.member.feedUnitType.symbol if not s.portions_enabled else "portions",
176-
native_max_value_fn=lambda s: Unit.round(s.member.feedUnitType.factor * MAX_FEED_PORTIONS, s.member.feedUnitType)
184+
native_max_value_fn=lambda s: Unit.round(s.member.feedUnitType.factor * MAX_FEED_PORTIONS, s.member.feedUnitType)
177185
if not s.portions_enabled else MAX_FEED_PORTIONS,
178186
native_min_value_fn=lambda s: round(s.member.feedUnitType.factor, 16) if not s.portions_enabled else 1,
179187
native_step_fn=lambda s: s.member.feedUnitType.factor if not s.portions_enabled else 1,
180-
method=lambda s, d, v: d.set_manual_feed_quantity(Unit.convert_feed(v, s.member.feedUnitType, None)
188+
method=lambda s, d, v: d.set_manual_feed_quantity(Unit.convert_feed(v, s.member.feedUnitType, None)
181189
if not s.portions_enabled else v),
182-
value_fn=lambda s, d: Unit.convert_feed(d.manual_feed_quantity, None, s.member.feedUnitType, True)
190+
value_fn=lambda s, d: Unit.convert_feed(d.manual_feed_quantity, None, s.member.feedUnitType, True)
183191
if not s.portions_enabled else d.manual_feed_quantity,
184192
entity_registry_visible_default_fn=lambda self: self.enable_for_manual_feed,
185193
entity_registry_enabled_default_fn=lambda self: self.enable_for_manual_feed,
194+
available_fn=lambda self: self.enable_for_manual_feed,
186195
petlibro_unit=APIKey.FEED_UNIT,
187196
),
188197
],
@@ -194,16 +203,17 @@ def _handle_coordinator_update(self) -> None:
194203
icon="mdi:scale",
195204
mode=NumberMode.SLIDER,
196205
native_unit_of_measurement_fn=lambda s: s.member.feedUnitType.symbol if not s.portions_enabled else "portions",
197-
native_max_value_fn=lambda s: Unit.round(s.member.feedUnitType.factor * MAX_FEED_PORTIONS, s.member.feedUnitType)
206+
native_max_value_fn=lambda s: Unit.round(s.member.feedUnitType.factor * MAX_FEED_PORTIONS, s.member.feedUnitType)
198207
if not s.portions_enabled else MAX_FEED_PORTIONS,
199208
native_min_value_fn=lambda s: round(s.member.feedUnitType.factor, 16) if not s.portions_enabled else 1,
200209
native_step_fn=lambda s: s.member.feedUnitType.factor if not s.portions_enabled else 1,
201-
method=lambda s, d, v: d.set_manual_feed_quantity(Unit.convert_feed(v, s.member.feedUnitType, None)
210+
method=lambda s, d, v: d.set_manual_feed_quantity(Unit.convert_feed(v, s.member.feedUnitType, None)
202211
if not s.portions_enabled else v),
203-
value_fn=lambda s, d: Unit.convert_feed(d.manual_feed_quantity, None, s.member.feedUnitType, True)
212+
value_fn=lambda s, d: Unit.convert_feed(d.manual_feed_quantity, None, s.member.feedUnitType, True)
204213
if not s.portions_enabled else d.manual_feed_quantity,
205214
entity_registry_visible_default_fn=lambda self: self.enable_for_manual_feed,
206215
entity_registry_enabled_default_fn=lambda self: self.enable_for_manual_feed,
216+
available_fn=lambda self: self.enable_for_manual_feed,
207217
petlibro_unit=APIKey.FEED_UNIT,
208218
),
209219
PetLibroNumberEntityDescription[GranarySmartFeeder](
@@ -228,16 +238,17 @@ def _handle_coordinator_update(self) -> None:
228238
icon="mdi:scale",
229239
mode=NumberMode.SLIDER,
230240
native_unit_of_measurement_fn=lambda s: s.member.feedUnitType.symbol if not s.portions_enabled else "portions",
231-
native_max_value_fn=lambda s: Unit.round(s.member.feedUnitType.factor * MAX_FEED_PORTIONS, s.member.feedUnitType)
241+
native_max_value_fn=lambda s: Unit.round(s.member.feedUnitType.factor * MAX_FEED_PORTIONS, s.member.feedUnitType)
232242
if not s.portions_enabled else MAX_FEED_PORTIONS,
233243
native_min_value_fn=lambda s: round(s.member.feedUnitType.factor, 16) if not s.portions_enabled else 1,
234244
native_step_fn=lambda s: s.member.feedUnitType.factor if not s.portions_enabled else 1,
235-
method=lambda s, d, v: d.set_manual_feed_quantity(Unit.convert_feed(v, s.member.feedUnitType, None)
245+
method=lambda s, d, v: d.set_manual_feed_quantity(Unit.convert_feed(v, s.member.feedUnitType, None)
236246
if not s.portions_enabled else v),
237-
value_fn=lambda s, d: Unit.convert_feed(d.manual_feed_quantity, None, s.member.feedUnitType, True)
247+
value_fn=lambda s, d: Unit.convert_feed(d.manual_feed_quantity, None, s.member.feedUnitType, True)
238248
if not s.portions_enabled else d.manual_feed_quantity,
239249
entity_registry_visible_default_fn=lambda self: self.enable_for_manual_feed,
240250
entity_registry_enabled_default_fn=lambda self: self.enable_for_manual_feed,
251+
available_fn=lambda self: self.enable_for_manual_feed,
241252
petlibro_unit=APIKey.FEED_UNIT,
242253
),
243254
],
@@ -286,16 +297,17 @@ def _handle_coordinator_update(self) -> None:
286297
icon="mdi:scale",
287298
mode=NumberMode.SLIDER,
288299
native_unit_of_measurement_fn=lambda s: s.member.feedUnitType.symbol if not s.portions_enabled else "portions",
289-
native_max_value_fn=lambda s: Unit.round(s.member.feedUnitType.factor * MAX_FEED_PORTIONS, s.member.feedUnitType)
300+
native_max_value_fn=lambda s: Unit.round(s.member.feedUnitType.factor * MAX_FEED_PORTIONS, s.member.feedUnitType)
290301
if not s.portions_enabled else MAX_FEED_PORTIONS,
291302
native_min_value_fn=lambda s: round(s.member.feedUnitType.factor, 16) if not s.portions_enabled else 1,
292303
native_step_fn=lambda s: s.member.feedUnitType.factor if not s.portions_enabled else 1,
293-
method=lambda s, d, v: d.set_manual_feed_quantity(Unit.convert_feed(v, s.member.feedUnitType, None)
304+
method=lambda s, d, v: d.set_manual_feed_quantity(Unit.convert_feed(v, s.member.feedUnitType, None)
294305
if not s.portions_enabled else v),
295-
value_fn=lambda s, d: Unit.convert_feed(d.manual_feed_quantity, None, s.member.feedUnitType, True)
306+
value_fn=lambda s, d: Unit.convert_feed(d.manual_feed_quantity, None, s.member.feedUnitType, True)
296307
if not s.portions_enabled else d.manual_feed_quantity,
297308
entity_registry_visible_default_fn=lambda self: self.enable_for_manual_feed,
298309
entity_registry_enabled_default_fn=lambda self: self.enable_for_manual_feed,
310+
available_fn=lambda self: self.enable_for_manual_feed,
299311
petlibro_unit=APIKey.FEED_UNIT,
300312
),
301313
],
@@ -308,16 +320,17 @@ def _handle_coordinator_update(self) -> None:
308320
icon="mdi:scale",
309321
mode=NumberMode.SLIDER,
310322
native_unit_of_measurement_fn=lambda s: s.member.feedUnitType.symbol if not s.portions_enabled else "portions",
311-
native_max_value_fn=lambda s: Unit.round(s.member.feedUnitType.factor * MAX_FEED_PORTIONS, s.member.feedUnitType)
323+
native_max_value_fn=lambda s: Unit.round(s.member.feedUnitType.factor * MAX_FEED_PORTIONS, s.member.feedUnitType)
312324
if not s.portions_enabled else MAX_FEED_PORTIONS,
313325
native_min_value_fn=lambda s: round(s.member.feedUnitType.factor, 16) if not s.portions_enabled else 1,
314326
native_step_fn=lambda s: s.member.feedUnitType.factor if not s.portions_enabled else 1,
315-
method=lambda s, d, v: d.set_manual_feed_quantity(Unit.convert_feed(v, s.member.feedUnitType, None)
327+
method=lambda s, d, v: d.set_manual_feed_quantity(Unit.convert_feed(v, s.member.feedUnitType, None)
316328
if not s.portions_enabled else v),
317-
value_fn=lambda s, d: Unit.convert_feed(d.manual_feed_quantity, None, s.member.feedUnitType, True)
329+
value_fn=lambda s, d: Unit.convert_feed(d.manual_feed_quantity, None, s.member.feedUnitType, True)
318330
if not s.portions_enabled else d.manual_feed_quantity,
319331
entity_registry_visible_default_fn=lambda self: self.enable_for_manual_feed,
320332
entity_registry_enabled_default_fn=lambda self: self.enable_for_manual_feed,
333+
available_fn=lambda self: self.enable_for_manual_feed,
321334
petlibro_unit=APIKey.FEED_UNIT,
322335
),
323336
PetLibroNumberEntityDescription[SpaceSmartFeeder](

0 commit comments

Comments
 (0)