Unifi more polish on entity description (#112281)

* Make has_entity_name default value True

* Remove previously missed event_is_on and event_to_subscribe

* Provide default value for allowed_fn and supported_fn

* Provide default value for name_fn

* Provide default value for available_fn

* Add doc strings to required functions

* Fix some missed renames from variations of controller to hub
This commit is contained in:
Robert Svensson 2024-03-09 09:19:38 +01:00 committed by GitHub
parent f2879e6f39
commit 19e54debba
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 27 additions and 77 deletions

View file

@ -69,33 +69,26 @@ ENTITY_DESCRIPTIONS: tuple[UnifiButtonEntityDescription, ...] = (
UnifiButtonEntityDescription[Devices, Device](
key="Device restart",
entity_category=EntityCategory.CONFIG,
has_entity_name=True,
device_class=ButtonDeviceClass.RESTART,
allowed_fn=lambda hub, obj_id: True,
api_handler_fn=lambda api: api.devices,
available_fn=async_device_available_fn,
control_fn=async_restart_device_control_fn,
device_info_fn=async_device_device_info_fn,
name_fn=lambda _: "Restart",
object_fn=lambda api, obj_id: api.devices[obj_id],
supported_fn=lambda hub, obj_id: True,
unique_id_fn=lambda hub, obj_id: f"device_restart-{obj_id}",
),
UnifiButtonEntityDescription[Ports, Port](
key="PoE power cycle",
entity_category=EntityCategory.CONFIG,
has_entity_name=True,
device_class=ButtonDeviceClass.RESTART,
allowed_fn=lambda hub, obj_id: True,
api_handler_fn=lambda api: api.ports,
available_fn=async_device_available_fn,
control_fn=async_power_cycle_port_control_fn,
device_info_fn=async_device_device_info_fn,
event_is_on=None,
event_to_subscribe=None,
name_fn=lambda port: f"{port.name} Power Cycle",
object_fn=lambda api, obj_id: api.ports[obj_id],
supported_fn=lambda hub, obj_id: hub.api.ports[obj_id].port_poe,
supported_fn=lambda hub, obj_id: bool(hub.api.ports[obj_id].port_poe),
unique_id_fn=lambda hub, obj_id: f"power_cycle-{obj_id}",
),
)

View file

@ -149,10 +149,8 @@ class UnifiTrackerEntityDescription(UnifiEntityDescription[HandlerT, ApiItemT]):
ENTITY_DESCRIPTIONS: tuple[UnifiTrackerEntityDescription, ...] = (
UnifiTrackerEntityDescription[Clients, Client](
key="Client device scanner",
has_entity_name=True,
allowed_fn=async_client_allowed_fn,
api_handler_fn=lambda api: api.clients,
available_fn=lambda hub, obj_id: hub.available,
device_info_fn=lambda api, obj_id: None,
event_is_on=(WIRED_CONNECTION + WIRELESS_CONNECTION),
event_to_subscribe=(
@ -165,23 +163,20 @@ ENTITY_DESCRIPTIONS: tuple[UnifiTrackerEntityDescription, ...] = (
is_connected_fn=async_client_is_connected_fn,
name_fn=lambda client: client.name or client.hostname,
object_fn=lambda api, obj_id: api.clients[obj_id],
supported_fn=lambda hub, obj_id: True,
unique_id_fn=lambda hub, obj_id: f"{hub.site}-{obj_id}",
ip_address_fn=lambda api, obj_id: api.clients[obj_id].ip,
hostname_fn=lambda api, obj_id: api.clients[obj_id].hostname,
),
UnifiTrackerEntityDescription[Devices, Device](
key="Device scanner",
has_entity_name=True,
allowed_fn=lambda hub, obj_id: hub.config.option_track_devices,
api_handler_fn=lambda api: api.devices,
available_fn=async_device_available_fn,
device_info_fn=lambda api, obj_id: None,
heartbeat_timedelta_fn=async_device_heartbeat_timedelta_fn,
is_connected_fn=lambda ctrlr, obj_id: ctrlr.api.devices[obj_id].state == 1,
is_connected_fn=lambda hub, obj_id: hub.api.devices[obj_id].state == 1,
name_fn=lambda device: device.name or device.model,
object_fn=lambda api, obj_id: api.devices[obj_id],
supported_fn=lambda hub, obj_id: True,
unique_id_fn=lambda hub, obj_id: obj_id,
ip_address_fn=lambda api, obj_id: api.devices[obj_id].ip,
hostname_fn=lambda api, obj_id: None,

View file

@ -98,16 +98,28 @@ def async_client_device_info_fn(hub: UnifiHub, obj_id: str) -> DeviceInfo:
class UnifiEntityDescription(EntityDescription, Generic[HandlerT, ApiItemT]):
"""UniFi Entity Description."""
allowed_fn: Callable[[UnifiHub, str], bool]
api_handler_fn: Callable[[aiounifi.Controller], HandlerT]
available_fn: Callable[[UnifiHub, str], bool]
"""Provide api_handler from api."""
device_info_fn: Callable[[UnifiHub, str], DeviceInfo | None]
name_fn: Callable[[ApiItemT], str | None]
"""Provide device info object based on hub and obj_id."""
object_fn: Callable[[aiounifi.Controller, str], ApiItemT]
supported_fn: Callable[[UnifiHub, str], bool | None]
"""Retrieve object based on api and obj_id."""
unique_id_fn: Callable[[UnifiHub, str], str]
"""Provide a unique ID based on hub and obj_id."""
# Optional
# Optional functions
allowed_fn: Callable[[UnifiHub, str], bool] = lambda hub, obj_id: True
"""Determine if config entry options allow creation of entity."""
available_fn: Callable[[UnifiHub, str], bool] = lambda hub, obj_id: hub.available
"""Determine if entity is available, default is if connection is working."""
name_fn: Callable[[ApiItemT], str | None] = lambda obj: None
"""Entity name function, can be used to extend entity name beyond device name."""
supported_fn: Callable[[UnifiHub, str], bool] = lambda hub, obj_id: True
"""Determine if UniFi object supports providing relevant data for entity."""
# Optional constants
has_entity_name = True # Part of EntityDescription
"""Has entity name defaults to true."""
event_is_on: tuple[EventKey, ...] | None = None
"""Which UniFi events should be used to consider state 'on'."""
event_to_subscribe: tuple[EventKey, ...] | None = None

View file

@ -50,15 +50,12 @@ ENTITY_DESCRIPTIONS: tuple[UnifiImageEntityDescription, ...] = (
UnifiImageEntityDescription[Wlans, Wlan](
key="WLAN QR Code",
entity_category=EntityCategory.DIAGNOSTIC,
has_entity_name=True,
entity_registry_enabled_default=False,
allowed_fn=lambda hub, obj_id: True,
api_handler_fn=lambda api: api.wlans,
available_fn=async_wlan_available_fn,
device_info_fn=async_wlan_device_info_fn,
name_fn=lambda wlan: "QR Code",
object_fn=lambda api, obj_id: api.wlans[obj_id],
supported_fn=lambda hub, obj_id: True,
unique_id_fn=lambda hub, obj_id: f"qr_code-{obj_id}",
image_fn=async_wlan_qr_code_image_fn,
value_fn=lambda obj: obj.x_passphrase,

View file

@ -186,10 +186,8 @@ ENTITY_DESCRIPTIONS: tuple[UnifiSensorEntityDescription, ...] = (
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfDataRate.MEGABYTES_PER_SECOND,
icon="mdi:upload",
has_entity_name=True,
allowed_fn=async_bandwidth_sensor_allowed_fn,
api_handler_fn=lambda api: api.clients,
available_fn=lambda hub, _: hub.available,
device_info_fn=async_client_device_info_fn,
is_connected_fn=async_client_is_connected_fn,
name_fn=lambda _: "RX",
@ -205,10 +203,8 @@ ENTITY_DESCRIPTIONS: tuple[UnifiSensorEntityDescription, ...] = (
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfDataRate.MEGABYTES_PER_SECOND,
icon="mdi:download",
has_entity_name=True,
allowed_fn=async_bandwidth_sensor_allowed_fn,
api_handler_fn=lambda api: api.clients,
available_fn=lambda hub, _: hub.available,
device_info_fn=async_client_device_info_fn,
is_connected_fn=async_client_is_connected_fn,
name_fn=lambda _: "TX",
@ -222,15 +218,13 @@ ENTITY_DESCRIPTIONS: tuple[UnifiSensorEntityDescription, ...] = (
device_class=SensorDeviceClass.POWER,
entity_category=EntityCategory.DIAGNOSTIC,
native_unit_of_measurement=UnitOfPower.WATT,
has_entity_name=True,
entity_registry_enabled_default=False,
allowed_fn=lambda hub, obj_id: True,
api_handler_fn=lambda api: api.ports,
available_fn=async_device_available_fn,
device_info_fn=async_device_device_info_fn,
name_fn=lambda port: f"{port.name} PoE Power",
object_fn=lambda api, obj_id: api.ports[obj_id],
supported_fn=lambda hub, obj_id: hub.api.ports[obj_id].port_poe,
supported_fn=lambda hub, obj_id: bool(hub.api.ports[obj_id].port_poe),
unique_id_fn=lambda hub, obj_id: f"poe_power-{obj_id}",
value_fn=lambda _, obj: obj.poe_power if obj.poe_mode != "off" else "0",
),
@ -238,11 +232,9 @@ ENTITY_DESCRIPTIONS: tuple[UnifiSensorEntityDescription, ...] = (
key="Client uptime",
device_class=SensorDeviceClass.TIMESTAMP,
entity_category=EntityCategory.DIAGNOSTIC,
has_entity_name=True,
entity_registry_enabled_default=False,
allowed_fn=async_uptime_sensor_allowed_fn,
api_handler_fn=lambda api: api.clients,
available_fn=lambda hub, obj_id: hub.available,
device_info_fn=async_client_device_info_fn,
name_fn=lambda client: "Uptime",
object_fn=lambda api, obj_id: api.clients[obj_id],
@ -253,16 +245,12 @@ ENTITY_DESCRIPTIONS: tuple[UnifiSensorEntityDescription, ...] = (
UnifiSensorEntityDescription[Wlans, Wlan](
key="WLAN clients",
entity_category=EntityCategory.DIAGNOSTIC,
has_entity_name=True,
state_class=SensorStateClass.MEASUREMENT,
allowed_fn=lambda hub, obj_id: True,
api_handler_fn=lambda api: api.wlans,
available_fn=async_wlan_available_fn,
device_info_fn=async_wlan_device_info_fn,
name_fn=lambda wlan: None,
object_fn=lambda api, obj_id: api.wlans[obj_id],
should_poll=True,
supported_fn=lambda hub, obj_id: True,
unique_id_fn=lambda hub, obj_id: f"wlan_clients-{obj_id}",
value_fn=async_wlan_client_value_fn,
),
@ -271,8 +259,6 @@ ENTITY_DESCRIPTIONS: tuple[UnifiSensorEntityDescription, ...] = (
device_class=SensorDeviceClass.POWER,
entity_category=EntityCategory.DIAGNOSTIC,
native_unit_of_measurement=UnitOfPower.WATT,
has_entity_name=True,
allowed_fn=lambda hub, obj_id: True,
api_handler_fn=lambda api: api.outlets,
available_fn=async_device_available_fn,
device_info_fn=async_device_device_info_fn,
@ -289,8 +275,6 @@ ENTITY_DESCRIPTIONS: tuple[UnifiSensorEntityDescription, ...] = (
entity_category=EntityCategory.DIAGNOSTIC,
native_unit_of_measurement=UnitOfPower.WATT,
suggested_display_precision=1,
has_entity_name=True,
allowed_fn=lambda hub, obj_id: True,
api_handler_fn=lambda api: api.devices,
available_fn=async_device_available_fn,
device_info_fn=async_device_device_info_fn,
@ -306,8 +290,6 @@ ENTITY_DESCRIPTIONS: tuple[UnifiSensorEntityDescription, ...] = (
entity_category=EntityCategory.DIAGNOSTIC,
native_unit_of_measurement=UnitOfPower.WATT,
suggested_display_precision=1,
has_entity_name=True,
allowed_fn=lambda hub, obj_id: True,
api_handler_fn=lambda api: api.devices,
available_fn=async_device_available_fn,
device_info_fn=async_device_device_info_fn,
@ -321,14 +303,11 @@ ENTITY_DESCRIPTIONS: tuple[UnifiSensorEntityDescription, ...] = (
key="Device uptime",
device_class=SensorDeviceClass.TIMESTAMP,
entity_category=EntityCategory.DIAGNOSTIC,
has_entity_name=True,
allowed_fn=lambda hub, obj_id: True,
api_handler_fn=lambda api: api.devices,
available_fn=async_device_available_fn,
device_info_fn=async_device_device_info_fn,
name_fn=lambda device: "Uptime",
object_fn=lambda api, obj_id: api.devices[obj_id],
supported_fn=lambda hub, obj_id: True,
unique_id_fn=lambda hub, obj_id: f"device_uptime-{obj_id}",
value_fn=async_device_uptime_value_fn,
value_changed_fn=async_device_uptime_value_changed_fn,
@ -338,29 +317,24 @@ ENTITY_DESCRIPTIONS: tuple[UnifiSensorEntityDescription, ...] = (
device_class=SensorDeviceClass.TEMPERATURE,
entity_category=EntityCategory.DIAGNOSTIC,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
has_entity_name=True,
allowed_fn=lambda hub, obj_id: True,
api_handler_fn=lambda api: api.devices,
available_fn=async_device_available_fn,
device_info_fn=async_device_device_info_fn,
name_fn=lambda device: "Temperature",
object_fn=lambda api, obj_id: api.devices[obj_id],
supported_fn=lambda ctrlr, obj_id: ctrlr.api.devices[obj_id].has_temperature,
supported_fn=lambda hub, obj_id: hub.api.devices[obj_id].has_temperature,
unique_id_fn=lambda hub, obj_id: f"device_temperature-{obj_id}",
value_fn=lambda ctrlr, device: device.general_temperature,
value_fn=lambda hub, device: device.general_temperature,
),
UnifiSensorEntityDescription[Devices, Device](
key="Device State",
device_class=SensorDeviceClass.ENUM,
entity_category=EntityCategory.DIAGNOSTIC,
has_entity_name=True,
allowed_fn=lambda hub, obj_id: True,
api_handler_fn=lambda api: api.devices,
available_fn=async_device_available_fn,
device_info_fn=async_device_device_info_fn,
name_fn=lambda device: "State",
object_fn=lambda api, obj_id: api.devices[obj_id],
supported_fn=lambda hub, obj_id: True,
unique_id_fn=lambda hub, obj_id: f"device_state-{obj_id}",
value_fn=async_device_state_value_fn,
options=list(DEVICE_STATES.values()),

View file

@ -126,7 +126,7 @@ async def async_dpi_group_control_fn(hub: UnifiHub, obj_id: str, target: bool) -
@callback
def async_outlet_supports_switching_fn(hub: UnifiHub, obj_id: str) -> bool:
def async_outlet_switching_supported_fn(hub: UnifiHub, obj_id: str) -> bool:
"""Determine if an outlet supports switching."""
outlet = hub.api.outlets[obj_id]
return outlet.has_relay or outlet.caps in (1, 3)
@ -184,43 +184,37 @@ ENTITY_DESCRIPTIONS: tuple[UnifiSwitchEntityDescription, ...] = (
key="Block client",
device_class=SwitchDeviceClass.SWITCH,
entity_category=EntityCategory.CONFIG,
has_entity_name=True,
icon="mdi:ethernet",
allowed_fn=async_block_client_allowed_fn,
api_handler_fn=lambda api: api.clients,
available_fn=lambda hub, obj_id: hub.available,
control_fn=async_block_client_control_fn,
device_info_fn=async_client_device_info_fn,
event_is_on=CLIENT_UNBLOCKED,
event_to_subscribe=CLIENT_BLOCKED + CLIENT_UNBLOCKED,
is_on_fn=lambda hub, client: not client.blocked,
name_fn=lambda client: None,
object_fn=lambda api, obj_id: api.clients[obj_id],
only_event_for_state_change=True,
supported_fn=lambda hub, obj_id: True,
unique_id_fn=lambda hub, obj_id: f"block-{obj_id}",
),
UnifiSwitchEntityDescription[DPIRestrictionGroups, DPIRestrictionGroup](
key="DPI restriction",
has_entity_name=False,
entity_category=EntityCategory.CONFIG,
icon="mdi:network",
allowed_fn=lambda hub, obj_id: hub.config.option_dpi_restrictions,
api_handler_fn=lambda api: api.dpi_groups,
available_fn=lambda hub, obj_id: hub.available,
control_fn=async_dpi_group_control_fn,
custom_subscribe=lambda api: api.dpi_apps.subscribe,
device_info_fn=async_dpi_group_device_info_fn,
is_on_fn=async_dpi_group_is_on_fn,
name_fn=lambda group: group.name,
object_fn=lambda api, obj_id: api.dpi_groups[obj_id],
supported_fn=lambda c, obj_id: bool(c.api.dpi_groups[obj_id].dpiapp_ids),
supported_fn=lambda hub, obj_id: bool(hub.api.dpi_groups[obj_id].dpiapp_ids),
unique_id_fn=lambda hub, obj_id: obj_id,
),
UnifiSwitchEntityDescription[Outlets, Outlet](
key="Outlet control",
device_class=SwitchDeviceClass.OUTLET,
has_entity_name=True,
allowed_fn=lambda hub, obj_id: True,
api_handler_fn=lambda api: api.outlets,
available_fn=async_device_available_fn,
control_fn=async_outlet_control_fn,
@ -228,34 +222,28 @@ ENTITY_DESCRIPTIONS: tuple[UnifiSwitchEntityDescription, ...] = (
is_on_fn=lambda hub, outlet: outlet.relay_state,
name_fn=lambda outlet: outlet.name,
object_fn=lambda api, obj_id: api.outlets[obj_id],
supported_fn=async_outlet_supports_switching_fn,
supported_fn=async_outlet_switching_supported_fn,
unique_id_fn=lambda hub, obj_id: f"outlet-{obj_id}",
),
UnifiSwitchEntityDescription[PortForwarding, PortForward](
key="Port forward control",
device_class=SwitchDeviceClass.SWITCH,
entity_category=EntityCategory.CONFIG,
has_entity_name=True,
icon="mdi:upload-network",
allowed_fn=lambda hub, obj_id: True,
api_handler_fn=lambda api: api.port_forwarding,
available_fn=lambda hub, obj_id: hub.available,
control_fn=async_port_forward_control_fn,
device_info_fn=async_port_forward_device_info_fn,
is_on_fn=lambda hub, port_forward: port_forward.enabled,
name_fn=lambda port_forward: f"{port_forward.name}",
object_fn=lambda api, obj_id: api.port_forwarding[obj_id],
supported_fn=lambda hub, obj_id: True,
unique_id_fn=lambda hub, obj_id: f"port_forward-{obj_id}",
),
UnifiSwitchEntityDescription[Ports, Port](
key="PoE port control",
device_class=SwitchDeviceClass.OUTLET,
entity_category=EntityCategory.CONFIG,
has_entity_name=True,
entity_registry_enabled_default=False,
icon="mdi:ethernet",
allowed_fn=lambda hub, obj_id: True,
api_handler_fn=lambda api: api.ports,
available_fn=async_device_available_fn,
control_fn=async_poe_port_control_fn,
@ -263,24 +251,19 @@ ENTITY_DESCRIPTIONS: tuple[UnifiSwitchEntityDescription, ...] = (
is_on_fn=lambda hub, port: port.poe_mode != "off",
name_fn=lambda port: f"{port.name} PoE",
object_fn=lambda api, obj_id: api.ports[obj_id],
supported_fn=lambda hub, obj_id: hub.api.ports[obj_id].port_poe,
supported_fn=lambda hub, obj_id: bool(hub.api.ports[obj_id].port_poe),
unique_id_fn=lambda hub, obj_id: f"poe-{obj_id}",
),
UnifiSwitchEntityDescription[Wlans, Wlan](
key="WLAN control",
device_class=SwitchDeviceClass.SWITCH,
entity_category=EntityCategory.CONFIG,
has_entity_name=True,
icon="mdi:wifi-check",
allowed_fn=lambda hub, obj_id: True,
api_handler_fn=lambda api: api.wlans,
available_fn=lambda hub, _: hub.available,
control_fn=async_wlan_control_fn,
device_info_fn=async_wlan_device_info_fn,
is_on_fn=lambda hub, wlan: wlan.enabled,
name_fn=lambda wlan: None,
object_fn=lambda api, obj_id: api.wlans[obj_id],
supported_fn=lambda hub, obj_id: True,
unique_id_fn=lambda hub, obj_id: f"wlan-{obj_id}",
),
)

View file

@ -55,16 +55,12 @@ ENTITY_DESCRIPTIONS: tuple[UnifiUpdateEntityDescription, ...] = (
UnifiUpdateEntityDescription[Devices, Device](
key="Upgrade device",
device_class=UpdateDeviceClass.FIRMWARE,
has_entity_name=True,
allowed_fn=lambda hub, obj_id: True,
api_handler_fn=lambda api: api.devices,
available_fn=async_device_available_fn,
control_fn=async_device_control_fn,
device_info_fn=async_device_device_info_fn,
name_fn=lambda device: None,
object_fn=lambda api, obj_id: api.devices[obj_id],
state_fn=lambda api, device: device.state == 4,
supported_fn=lambda hub, obj_id: True,
unique_id_fn=lambda hub, obj_id: f"device_update-{obj_id}",
),
)