mirror of
https://github.com/home-assistant/core.git
synced 2025-04-24 01:08:12 +00:00
Add get_user_keyring_info service to UniFi Protect integration (#133138)
Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
parent
0f1835139f
commit
6c70586f7e
@ -83,3 +83,10 @@ EVENT_TYPE_FINGERPRINT_IDENTIFIED: Final = "identified"
|
||||
EVENT_TYPE_FINGERPRINT_NOT_IDENTIFIED: Final = "not_identified"
|
||||
EVENT_TYPE_NFC_SCANNED: Final = "scanned"
|
||||
EVENT_TYPE_DOORBELL_RING: Final = "ring"
|
||||
|
||||
KEYRINGS_ULP_ID: Final = "ulp_id"
|
||||
KEYRINGS_USER_STATUS: Final = "user_status"
|
||||
KEYRINGS_USER_FULL_NAME: Final = "full_name"
|
||||
KEYRINGS_KEY_TYPE: Final = "key_type"
|
||||
KEYRINGS_KEY_TYPE_ID_FINGERPRINT: Final = "fingerprint_id"
|
||||
KEYRINGS_KEY_TYPE_ID_NFC: Final = "nfc_id"
|
||||
|
@ -11,6 +11,9 @@
|
||||
},
|
||||
"remove_privacy_zone": {
|
||||
"service": "mdi:eye-minus"
|
||||
},
|
||||
"get_user_keyring_info": {
|
||||
"service": "mdi:key-chain"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,13 @@ import voluptuous as vol
|
||||
|
||||
from homeassistant.components.binary_sensor import BinarySensorDeviceClass
|
||||
from homeassistant.const import ATTR_DEVICE_ID, ATTR_NAME, Platform
|
||||
from homeassistant.core import HomeAssistant, ServiceCall, callback
|
||||
from homeassistant.core import (
|
||||
HomeAssistant,
|
||||
ServiceCall,
|
||||
ServiceResponse,
|
||||
SupportsResponse,
|
||||
callback,
|
||||
)
|
||||
from homeassistant.exceptions import HomeAssistantError, ServiceValidationError
|
||||
from homeassistant.helpers import (
|
||||
config_validation as cv,
|
||||
@ -21,9 +27,19 @@ from homeassistant.helpers import (
|
||||
entity_registry as er,
|
||||
)
|
||||
from homeassistant.helpers.service import async_extract_referenced_entity_ids
|
||||
from homeassistant.util.json import JsonValueType
|
||||
from homeassistant.util.read_only_dict import ReadOnlyDict
|
||||
|
||||
from .const import ATTR_MESSAGE, DOMAIN
|
||||
from .const import (
|
||||
ATTR_MESSAGE,
|
||||
DOMAIN,
|
||||
KEYRINGS_KEY_TYPE,
|
||||
KEYRINGS_KEY_TYPE_ID_FINGERPRINT,
|
||||
KEYRINGS_KEY_TYPE_ID_NFC,
|
||||
KEYRINGS_ULP_ID,
|
||||
KEYRINGS_USER_FULL_NAME,
|
||||
KEYRINGS_USER_STATUS,
|
||||
)
|
||||
from .data import async_ufp_instance_for_config_entry_ids
|
||||
|
||||
SERVICE_ADD_DOORBELL_TEXT = "add_doorbell_text"
|
||||
@ -31,12 +47,14 @@ SERVICE_REMOVE_DOORBELL_TEXT = "remove_doorbell_text"
|
||||
SERVICE_SET_PRIVACY_ZONE = "set_privacy_zone"
|
||||
SERVICE_REMOVE_PRIVACY_ZONE = "remove_privacy_zone"
|
||||
SERVICE_SET_CHIME_PAIRED = "set_chime_paired_doorbells"
|
||||
SERVICE_GET_USER_KEYRING_INFO = "get_user_keyring_info"
|
||||
|
||||
ALL_GLOBAL_SERIVCES = [
|
||||
SERVICE_ADD_DOORBELL_TEXT,
|
||||
SERVICE_REMOVE_DOORBELL_TEXT,
|
||||
SERVICE_SET_CHIME_PAIRED,
|
||||
SERVICE_REMOVE_PRIVACY_ZONE,
|
||||
SERVICE_GET_USER_KEYRING_INFO,
|
||||
]
|
||||
|
||||
DOORBELL_TEXT_SCHEMA = vol.All(
|
||||
@ -69,6 +87,15 @@ REMOVE_PRIVACY_ZONE_SCHEMA = vol.All(
|
||||
cv.has_at_least_one_key(ATTR_DEVICE_ID),
|
||||
)
|
||||
|
||||
GET_USER_KEYRING_INFO_SCHEMA = vol.All(
|
||||
vol.Schema(
|
||||
{
|
||||
**cv.ENTITY_SERVICE_FIELDS,
|
||||
},
|
||||
),
|
||||
cv.has_at_least_one_key(ATTR_DEVICE_ID),
|
||||
)
|
||||
|
||||
|
||||
@callback
|
||||
def _async_get_ufp_instance(hass: HomeAssistant, device_id: str) -> ProtectApiClient:
|
||||
@ -205,26 +232,70 @@ async def set_chime_paired_doorbells(call: ServiceCall) -> None:
|
||||
await chime.save_device(data_before_changed)
|
||||
|
||||
|
||||
async def get_user_keyring_info(call: ServiceCall) -> ServiceResponse:
|
||||
"""Get the user keyring info."""
|
||||
camera = _async_get_ufp_camera(call)
|
||||
ulp_users = camera.api.bootstrap.ulp_users.as_list()
|
||||
user_keyrings: list[JsonValueType] = [
|
||||
{
|
||||
KEYRINGS_USER_FULL_NAME: user.full_name,
|
||||
KEYRINGS_USER_STATUS: user.status,
|
||||
KEYRINGS_ULP_ID: user.ulp_id,
|
||||
"keys": [
|
||||
{
|
||||
KEYRINGS_KEY_TYPE: key.registry_type,
|
||||
**(
|
||||
{KEYRINGS_KEY_TYPE_ID_FINGERPRINT: key.registry_id}
|
||||
if key.registry_type == "fingerprint"
|
||||
else {}
|
||||
),
|
||||
**(
|
||||
{KEYRINGS_KEY_TYPE_ID_NFC: key.registry_id}
|
||||
if key.registry_type == "nfc"
|
||||
else {}
|
||||
),
|
||||
}
|
||||
for key in camera.api.bootstrap.keyrings.as_list()
|
||||
if key.ulp_user == user.ulp_id
|
||||
],
|
||||
}
|
||||
for user in ulp_users
|
||||
]
|
||||
|
||||
response: ServiceResponse = {"users": user_keyrings}
|
||||
return response
|
||||
|
||||
|
||||
SERVICES = [
|
||||
(
|
||||
SERVICE_ADD_DOORBELL_TEXT,
|
||||
add_doorbell_text,
|
||||
DOORBELL_TEXT_SCHEMA,
|
||||
SupportsResponse.NONE,
|
||||
),
|
||||
(
|
||||
SERVICE_REMOVE_DOORBELL_TEXT,
|
||||
remove_doorbell_text,
|
||||
DOORBELL_TEXT_SCHEMA,
|
||||
SupportsResponse.NONE,
|
||||
),
|
||||
(
|
||||
SERVICE_SET_CHIME_PAIRED,
|
||||
set_chime_paired_doorbells,
|
||||
CHIME_PAIRED_SCHEMA,
|
||||
SupportsResponse.NONE,
|
||||
),
|
||||
(
|
||||
SERVICE_REMOVE_PRIVACY_ZONE,
|
||||
remove_privacy_zone,
|
||||
REMOVE_PRIVACY_ZONE_SCHEMA,
|
||||
SupportsResponse.NONE,
|
||||
),
|
||||
(
|
||||
SERVICE_GET_USER_KEYRING_INFO,
|
||||
get_user_keyring_info,
|
||||
GET_USER_KEYRING_INFO_SCHEMA,
|
||||
SupportsResponse.ONLY,
|
||||
),
|
||||
]
|
||||
|
||||
@ -232,5 +303,7 @@ SERVICES = [
|
||||
def async_setup_services(hass: HomeAssistant) -> None:
|
||||
"""Set up the global UniFi Protect services."""
|
||||
|
||||
for name, method, schema in SERVICES:
|
||||
hass.services.async_register(DOMAIN, name, method, schema=schema)
|
||||
for name, method, schema, supports_response in SERVICES:
|
||||
hass.services.async_register(
|
||||
DOMAIN, name, method, schema=schema, supports_response=supports_response
|
||||
)
|
||||
|
@ -53,3 +53,10 @@ remove_privacy_zone:
|
||||
required: true
|
||||
selector:
|
||||
text:
|
||||
get_user_keyring_info:
|
||||
fields:
|
||||
device_id:
|
||||
required: true
|
||||
selector:
|
||||
device:
|
||||
integration: unifiprotect
|
||||
|
@ -225,6 +225,16 @@
|
||||
"description": "The name of the zone to remove."
|
||||
}
|
||||
}
|
||||
},
|
||||
"get_user_keyring_info": {
|
||||
"name": "Retrieve Keyring Details for Users",
|
||||
"description": "Fetch a detailed list of users with NFC and fingerprint associations for automations.",
|
||||
"fields": {
|
||||
"device_id": {
|
||||
"name": "UniFi Protect NVR",
|
||||
"description": "Any device from the UniFi Protect instance you want to retrieve keyring details. This is useful for systems with multiple Protect instances."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,9 +9,19 @@ from uiprotect.data import Camera, Chime, Color, Light, ModelType
|
||||
from uiprotect.data.devices import CameraZone
|
||||
from uiprotect.exceptions import BadRequest
|
||||
|
||||
from homeassistant.components.unifiprotect.const import ATTR_MESSAGE, DOMAIN
|
||||
from homeassistant.components.unifiprotect.const import (
|
||||
ATTR_MESSAGE,
|
||||
DOMAIN,
|
||||
KEYRINGS_KEY_TYPE,
|
||||
KEYRINGS_KEY_TYPE_ID_FINGERPRINT,
|
||||
KEYRINGS_KEY_TYPE_ID_NFC,
|
||||
KEYRINGS_ULP_ID,
|
||||
KEYRINGS_USER_FULL_NAME,
|
||||
KEYRINGS_USER_STATUS,
|
||||
)
|
||||
from homeassistant.components.unifiprotect.services import (
|
||||
SERVICE_ADD_DOORBELL_TEXT,
|
||||
SERVICE_GET_USER_KEYRING_INFO,
|
||||
SERVICE_REMOVE_DOORBELL_TEXT,
|
||||
SERVICE_REMOVE_PRIVACY_ZONE,
|
||||
SERVICE_SET_CHIME_PAIRED,
|
||||
@ -249,3 +259,59 @@ async def test_remove_privacy_zone(
|
||||
)
|
||||
ufp.api.update_device.assert_called()
|
||||
assert not doorbell.privacy_zones
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_doorbell_user(
|
||||
hass: HomeAssistant,
|
||||
entity_registry: er.EntityRegistry,
|
||||
ufp: MockUFPFixture,
|
||||
doorbell: Camera,
|
||||
) -> None:
|
||||
"""Test get_doorbell_user service."""
|
||||
|
||||
ulp_user = Mock(full_name="Test User", status="active", ulp_id="user_ulp_id")
|
||||
keyring = Mock(
|
||||
registry_type="nfc",
|
||||
registry_id="123456",
|
||||
ulp_user="user_ulp_id",
|
||||
)
|
||||
keyring_2 = Mock(
|
||||
registry_type="fingerprint",
|
||||
registry_id="2",
|
||||
ulp_user="user_ulp_id",
|
||||
)
|
||||
ufp.api.bootstrap.ulp_users.as_list = Mock(return_value=[ulp_user])
|
||||
ufp.api.bootstrap.keyrings.as_list = Mock(return_value=[keyring, keyring_2])
|
||||
|
||||
await init_entry(hass, ufp, [doorbell])
|
||||
|
||||
camera_entry = entity_registry.async_get("binary_sensor.test_camera_doorbell")
|
||||
|
||||
response = await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_GET_USER_KEYRING_INFO,
|
||||
{ATTR_DEVICE_ID: camera_entry.device_id},
|
||||
blocking=True,
|
||||
return_response=True,
|
||||
)
|
||||
|
||||
assert response == {
|
||||
"users": [
|
||||
{
|
||||
KEYRINGS_USER_FULL_NAME: "Test User",
|
||||
"keys": [
|
||||
{
|
||||
KEYRINGS_KEY_TYPE: "nfc",
|
||||
KEYRINGS_KEY_TYPE_ID_NFC: "123456",
|
||||
},
|
||||
{
|
||||
KEYRINGS_KEY_TYPE_ID_FINGERPRINT: "2",
|
||||
KEYRINGS_KEY_TYPE: "fingerprint",
|
||||
},
|
||||
],
|
||||
KEYRINGS_USER_STATUS: "active",
|
||||
KEYRINGS_ULP_ID: "user_ulp_id",
|
||||
},
|
||||
],
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user