feat: 添加 HA 管理面板功能
- config_flow.py: 新增人员管理步骤(async_step_manage/list/create) 支持在 HA 配置 -> 选项 中查看人员列表、创建和删除 - __init__.py: 新增 3 个 WebSocket API 命令(list/create/delete) 前端可通过 HA WebSocket 直接调用 - blueprints/face_detection_automation.yaml: 自动化蓝图 支持人脸检测/搜索 + 通知推送 - manifest.json: 版本号 2.2.0 用户现可通过 HA 界面对人员进行可视化管理
This commit is contained in:
+111
-2
@@ -4,12 +4,16 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import base64
|
||||
import logging
|
||||
from typing import Any, Dict
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.exceptions import ConfigEntryNotReady
|
||||
from homeassistant.exceptions import ConfigEntryNotReady, HomeAssistantError
|
||||
|
||||
from homeassistant.components import websocket_api
|
||||
from homeassistant.components.camera import async_get_image
|
||||
|
||||
from .const import (
|
||||
CONF_PERSON_GROUP_ID,
|
||||
@@ -69,7 +73,12 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
# 4. 注册服务
|
||||
await async_setup_services(hass)
|
||||
|
||||
# 5. 前向设置平台(sensor)
|
||||
# 5. 注册 WebSocket API 命令
|
||||
websocket_api.async_register_command(hass, ws_list_persons)
|
||||
websocket_api.async_register_command(hass, ws_create_person)
|
||||
websocket_api.async_register_command(hass, ws_delete_person)
|
||||
|
||||
# 6. 前向设置平台(sensor)
|
||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||
|
||||
# 6. 配置项更新时自动重新加载平台
|
||||
@@ -118,3 +127,103 @@ async def async_remove_entry(hass: HomeAssistant, entry: ConfigEntry) -> None:
|
||||
await hass.async_add_executor_job(data["client"].close)
|
||||
except Exception: # noqa: BLE001
|
||||
pass
|
||||
|
||||
|
||||
# --- WebSocket API ---------------------------------------------------------
|
||||
|
||||
|
||||
@websocket_api.websocket_command({
|
||||
"type": "tencent_face_recognition/list_persons",
|
||||
})
|
||||
@websocket_api.async_response
|
||||
async def ws_list_persons(
|
||||
hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg: Dict[str, Any]
|
||||
) -> None:
|
||||
"""列出所有人员。"""
|
||||
entry_data = None
|
||||
for data in hass.data.get(DOMAIN, {}).values():
|
||||
if isinstance(data, dict) and "client" in data:
|
||||
entry_data = data
|
||||
break
|
||||
if not entry_data:
|
||||
connection.send_error(msg["id"], "not_found", "未找到配置")
|
||||
return
|
||||
|
||||
client: TencentCloudClient = entry_data["client"]
|
||||
group_id = entry_data.get("person_group_id", "Hass")
|
||||
try:
|
||||
result = await hass.async_add_executor_job(client.get_person_list_all, group_id)
|
||||
connection.send_result(msg["id"], result)
|
||||
except Exception as ex:
|
||||
_LOGGER.error("列出人员失败: %s", ex)
|
||||
connection.send_error(msg["id"], "api_error", str(ex))
|
||||
|
||||
|
||||
@websocket_api.websocket_command({
|
||||
"type": "tencent_face_recognition/create_person",
|
||||
"data": {
|
||||
"person_id": str,
|
||||
"person_name": str,
|
||||
"camera_entity_id": str,
|
||||
},
|
||||
})
|
||||
@websocket_api.async_response
|
||||
async def ws_create_person(
|
||||
hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg: Dict[str, Any]
|
||||
) -> None:
|
||||
"""通过摄像头创建人员。"""
|
||||
entry_data = None
|
||||
for data in hass.data.get(DOMAIN, {}).values():
|
||||
if isinstance(data, dict) and "client" in data:
|
||||
entry_data = data
|
||||
break
|
||||
if not entry_data:
|
||||
connection.send_error(msg["id"], "not_found", "未找到配置")
|
||||
return
|
||||
|
||||
client: TencentCloudClient = entry_data["client"]
|
||||
group_id = entry_data.get("person_group_id", "Hass")
|
||||
person_id = msg["data"]["person_id"]
|
||||
person_name = msg["data"]["person_name"]
|
||||
camera_entity_id = msg["data"]["camera_entity_id"]
|
||||
|
||||
try:
|
||||
image = await async_get_image(hass, camera_entity_id)
|
||||
image_base64 = base64.b64encode(image.content).decode("utf-8")
|
||||
result = await hass.async_add_executor_job(
|
||||
client.create_person,
|
||||
person_id, person_name, group_id,
|
||||
None, None, None, image_base64,
|
||||
)
|
||||
connection.send_result(msg["id"], result)
|
||||
except Exception as ex:
|
||||
_LOGGER.error("创建人员失败: %s", ex)
|
||||
connection.send_error(msg["id"], "api_error", str(ex))
|
||||
|
||||
|
||||
@websocket_api.websocket_command({
|
||||
"type": "tencent_face_recognition/delete_person",
|
||||
"data": {"person_id": str},
|
||||
})
|
||||
@websocket_api.async_response
|
||||
async def ws_delete_person(
|
||||
hass: HomeAssistant, connection: websocket_api.ActiveConnection, msg: Dict[str, Any]
|
||||
) -> None:
|
||||
"""删除人员。"""
|
||||
entry_data = None
|
||||
for data in hass.data.get(DOMAIN, {}).values():
|
||||
if isinstance(data, dict) and "client" in data:
|
||||
entry_data = data
|
||||
break
|
||||
if not entry_data:
|
||||
connection.send_error(msg["id"], "not_found", "未找到配置")
|
||||
return
|
||||
|
||||
client: TencentCloudClient = entry_data["client"]
|
||||
person_id = msg["data"]["person_id"]
|
||||
try:
|
||||
result = await hass.async_add_executor_job(client.delete_person, person_id)
|
||||
connection.send_result(msg["id"], result)
|
||||
except Exception as ex:
|
||||
_LOGGER.error("删除人员失败: %s", ex)
|
||||
connection.send_error(msg["id"], "api_error", str(ex))
|
||||
|
||||
Reference in New Issue
Block a user