feat: 升级至v2.0.0,新增人员/人脸管理服务与摄像头支持
- 新增 create_person、delete_person、create_face、delete_face 服务 - 支持通过摄像头实体获取图片 (camera_entity_id 参数) - 添加配置选项支持,可通过 Options Flow 修改配置 - 传感器采用 CoordinatorEntity 模式,优化数据更新机制 - 改进重试逻辑与错误处理 - 重构代码结构,清理冗余代码
This commit is contained in:
+305
-85
@@ -6,6 +6,7 @@ from typing import Dict, Any, List, Optional
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
|
||||
from .const import (
|
||||
@@ -13,25 +14,39 @@ from .const import (
|
||||
SERVICE_FACE_SEARCH,
|
||||
SERVICE_DETECT_FACE,
|
||||
SERVICE_GET_FACE_ATTRIBUTES,
|
||||
SERVICE_CREATE_PERSON,
|
||||
SERVICE_DELETE_PERSON,
|
||||
SERVICE_CREATE_FACE,
|
||||
SERVICE_DELETE_FACE,
|
||||
ATTR_IMAGE_URL,
|
||||
ATTR_IMAGE_FILE,
|
||||
ATTR_IMAGE_PATH,
|
||||
ATTR_CAMERA_ENTITY_ID,
|
||||
ATTR_CONFIG_ENTRY_ID,
|
||||
ATTR_GROUP_ID,
|
||||
ATTR_MAX_FACE_NUM,
|
||||
ATTR_MIN_FACE_SIZE,
|
||||
ATTR_MAX_USER_NUM,
|
||||
ATTR_QUALITY_CONTROL,
|
||||
ATTR_NEED_ROTATE_CHECK,
|
||||
ATTR_FACE_MATCH_THRESHOLD,
|
||||
ATTR_PERSON_ID,
|
||||
ATTR_PERSON_NAME,
|
||||
ATTR_GENDER,
|
||||
ATTR_FACE_ID,
|
||||
ATTR_PERSON_TAG,
|
||||
EVENT_FACE_DETECTED,
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
# 人脸搜索服务参数
|
||||
FACE_SEARCH_SCHEMA = vol.Schema({
|
||||
vol.Required('group_id'): cv.string,
|
||||
vol.Required(ATTR_GROUP_ID): cv.string,
|
||||
vol.Optional(ATTR_IMAGE_URL): cv.string,
|
||||
vol.Optional(ATTR_IMAGE_PATH): cv.string,
|
||||
vol.Optional(ATTR_IMAGE_FILE): cv.string,
|
||||
vol.Optional(ATTR_CAMERA_ENTITY_ID): cv.string,
|
||||
vol.Optional(ATTR_CONFIG_ENTRY_ID): cv.string,
|
||||
vol.Optional(ATTR_MAX_FACE_NUM, default=1): cv.positive_int,
|
||||
vol.Optional(ATTR_MIN_FACE_SIZE, default=34): cv.positive_int,
|
||||
vol.Optional(ATTR_MAX_USER_NUM, default=5): cv.positive_int,
|
||||
@@ -40,31 +55,72 @@ FACE_SEARCH_SCHEMA = vol.Schema({
|
||||
vol.Optional(ATTR_FACE_MATCH_THRESHOLD, default=60.0): vol.Range(min=0, max=100),
|
||||
})
|
||||
|
||||
# 人脸检测服务参数
|
||||
DETECT_FACE_SCHEMA = vol.Schema({
|
||||
vol.Optional(ATTR_IMAGE_URL): cv.string,
|
||||
vol.Optional(ATTR_IMAGE_PATH): cv.string,
|
||||
vol.Optional(ATTR_IMAGE_FILE): cv.string,
|
||||
vol.Optional(ATTR_CAMERA_ENTITY_ID): cv.string,
|
||||
vol.Optional(ATTR_CONFIG_ENTRY_ID): cv.string,
|
||||
vol.Optional(ATTR_MAX_FACE_NUM, default=1): cv.positive_int,
|
||||
vol.Optional(ATTR_MIN_FACE_SIZE, default=34): cv.positive_int,
|
||||
vol.Optional(ATTR_NEED_ROTATE_CHECK, default=1): vol.In([0, 1]),
|
||||
})
|
||||
|
||||
# 获取人脸属性服务参数
|
||||
GET_FACE_ATTRIBUTES_SCHEMA = vol.Schema({
|
||||
vol.Optional(ATTR_IMAGE_URL): cv.string,
|
||||
vol.Optional(ATTR_IMAGE_PATH): cv.string,
|
||||
vol.Optional(ATTR_IMAGE_FILE): cv.string,
|
||||
vol.Optional(ATTR_CAMERA_ENTITY_ID): cv.string,
|
||||
vol.Optional(ATTR_CONFIG_ENTRY_ID): cv.string,
|
||||
vol.Optional(ATTR_MAX_FACE_NUM, default=1): cv.positive_int,
|
||||
vol.Optional(ATTR_NEED_ROTATE_CHECK, default=1): vol.In([0, 1]),
|
||||
})
|
||||
|
||||
CREATE_PERSON_SCHEMA = vol.Schema({
|
||||
vol.Required(ATTR_PERSON_ID): cv.string,
|
||||
vol.Required(ATTR_PERSON_NAME): cv.string,
|
||||
vol.Required(ATTR_GROUP_ID): cv.string,
|
||||
vol.Optional(ATTR_IMAGE_URL): cv.string,
|
||||
vol.Optional(ATTR_IMAGE_PATH): cv.string,
|
||||
vol.Optional(ATTR_IMAGE_FILE): cv.string,
|
||||
vol.Optional(ATTR_CAMERA_ENTITY_ID): cv.string,
|
||||
vol.Optional(ATTR_CONFIG_ENTRY_ID): cv.string,
|
||||
vol.Optional(ATTR_GENDER): vol.In([0, 1]),
|
||||
vol.Optional(ATTR_PERSON_TAG): cv.string,
|
||||
vol.Optional(ATTR_QUALITY_CONTROL, default=1): vol.In([0, 1]),
|
||||
vol.Optional(ATTR_NEED_ROTATE_CHECK, default=1): vol.In([0, 1]),
|
||||
})
|
||||
|
||||
DELETE_PERSON_SCHEMA = vol.Schema({
|
||||
vol.Required(ATTR_PERSON_ID): cv.string,
|
||||
vol.Optional(ATTR_CONFIG_ENTRY_ID): cv.string,
|
||||
})
|
||||
|
||||
CREATE_FACE_SCHEMA = vol.Schema({
|
||||
vol.Required(ATTR_PERSON_ID): cv.string,
|
||||
vol.Optional(ATTR_IMAGE_URL): cv.string,
|
||||
vol.Optional(ATTR_IMAGE_PATH): cv.string,
|
||||
vol.Optional(ATTR_IMAGE_FILE): cv.string,
|
||||
vol.Optional(ATTR_CAMERA_ENTITY_ID): cv.string,
|
||||
vol.Optional(ATTR_CONFIG_ENTRY_ID): cv.string,
|
||||
vol.Optional(ATTR_QUALITY_CONTROL, default=1): vol.In([0, 1]),
|
||||
vol.Optional(ATTR_NEED_ROTATE_CHECK, default=1): vol.In([0, 1]),
|
||||
})
|
||||
|
||||
DELETE_FACE_SCHEMA = vol.Schema({
|
||||
vol.Required(ATTR_PERSON_ID): cv.string,
|
||||
vol.Required(ATTR_FACE_ID): cv.string,
|
||||
vol.Optional(ATTR_CONFIG_ENTRY_ID): cv.string,
|
||||
})
|
||||
|
||||
|
||||
async def async_setup_services(hass: HomeAssistant) -> None:
|
||||
"""设置服务"""
|
||||
if hass.services.has_service(DOMAIN, SERVICE_FACE_SEARCH):
|
||||
return
|
||||
|
||||
_LOGGER.info("设置腾讯云人脸识别服务")
|
||||
|
||||
# 注册人脸搜索服务
|
||||
hass.services.async_register(
|
||||
DOMAIN,
|
||||
SERVICE_FACE_SEARCH,
|
||||
@@ -73,60 +129,108 @@ async def async_setup_services(hass: HomeAssistant) -> None:
|
||||
supports_response=True
|
||||
)
|
||||
|
||||
# 注册人脸检测服务
|
||||
hass.services.async_register(
|
||||
DOMAIN,
|
||||
SERVICE_DETECT_FACE,
|
||||
async_detect_face_service,
|
||||
schema=DETECT_FACE_SCHEMA
|
||||
schema=DETECT_FACE_SCHEMA,
|
||||
supports_response=True
|
||||
)
|
||||
|
||||
# 注册获取人脸属性服务
|
||||
hass.services.async_register(
|
||||
DOMAIN,
|
||||
SERVICE_GET_FACE_ATTRIBUTES,
|
||||
async_get_face_attributes_service,
|
||||
schema=GET_FACE_ATTRIBUTES_SCHEMA
|
||||
schema=GET_FACE_ATTRIBUTES_SCHEMA,
|
||||
supports_response=True
|
||||
)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN,
|
||||
SERVICE_CREATE_PERSON,
|
||||
async_create_person_service,
|
||||
schema=CREATE_PERSON_SCHEMA,
|
||||
supports_response=True
|
||||
)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN,
|
||||
SERVICE_DELETE_PERSON,
|
||||
async_delete_person_service,
|
||||
schema=DELETE_PERSON_SCHEMA,
|
||||
supports_response=True
|
||||
)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN,
|
||||
SERVICE_CREATE_FACE,
|
||||
async_create_face_service,
|
||||
schema=CREATE_FACE_SCHEMA,
|
||||
supports_response=True
|
||||
)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN,
|
||||
SERVICE_DELETE_FACE,
|
||||
async_delete_face_service,
|
||||
schema=DELETE_FACE_SCHEMA,
|
||||
supports_response=True
|
||||
)
|
||||
|
||||
|
||||
async def async_unload_services(hass: HomeAssistant) -> None:
|
||||
"""卸载服务"""
|
||||
if any(hass.config_entries.async_entries(DOMAIN)):
|
||||
return
|
||||
|
||||
_LOGGER.info("卸载腾讯云人脸识别服务")
|
||||
|
||||
# 注销所有服务
|
||||
hass.services.async_remove(DOMAIN, SERVICE_FACE_SEARCH)
|
||||
hass.services.async_remove(DOMAIN, SERVICE_DETECT_FACE)
|
||||
hass.services.async_remove(DOMAIN, SERVICE_GET_FACE_ATTRIBUTES)
|
||||
for service_name in [
|
||||
SERVICE_FACE_SEARCH,
|
||||
SERVICE_DETECT_FACE,
|
||||
SERVICE_GET_FACE_ATTRIBUTES,
|
||||
SERVICE_CREATE_PERSON,
|
||||
SERVICE_DELETE_PERSON,
|
||||
SERVICE_CREATE_FACE,
|
||||
SERVICE_DELETE_FACE,
|
||||
]:
|
||||
hass.services.async_remove(DOMAIN, service_name)
|
||||
|
||||
|
||||
def _get_entry_data(hass: HomeAssistant, config_entry_id: str = None):
|
||||
"""获取配置项数据,支持多配置条目"""
|
||||
domain_data = hass.data.get(DOMAIN, {})
|
||||
if config_entry_id:
|
||||
data = domain_data.get(config_entry_id)
|
||||
if data and isinstance(data, dict) and "face_recognition" in data:
|
||||
return data
|
||||
return None
|
||||
|
||||
for entry_id, data in domain_data.items():
|
||||
if isinstance(data, dict) and "face_recognition" in data:
|
||||
return data
|
||||
return None
|
||||
|
||||
|
||||
async def async_face_search_service(call: ServiceCall) -> Dict[str, Any]:
|
||||
"""人脸搜索服务"""
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
|
||||
hass = call.hass
|
||||
data = call.data
|
||||
|
||||
# 获取配置项
|
||||
config_entry = _get_config_entry(hass)
|
||||
if not config_entry:
|
||||
entry_data = _get_entry_data(hass, data.get(ATTR_CONFIG_ENTRY_ID))
|
||||
if not entry_data:
|
||||
raise HomeAssistantError("未找到腾讯云人脸识别配置")
|
||||
|
||||
# 获取插件实例
|
||||
entry_data = _get_entry_data(hass)
|
||||
if not entry_data:
|
||||
raise HomeAssistantError("腾讯云人脸识别插件未正确初始化")
|
||||
|
||||
face_recognition = entry_data.get("face_recognition")
|
||||
if not face_recognition:
|
||||
raise HomeAssistantError("腾讯云人脸识别插件未正确初始化")
|
||||
|
||||
# 调用人脸搜索功能
|
||||
try:
|
||||
group_id = data.get('group_id')
|
||||
group_id = data.get(ATTR_GROUP_ID)
|
||||
image_url = data.get(ATTR_IMAGE_URL)
|
||||
image_path = data.get(ATTR_IMAGE_PATH)
|
||||
image_file = data.get(ATTR_IMAGE_FILE)
|
||||
camera_entity_id = data.get(ATTR_CAMERA_ENTITY_ID)
|
||||
max_face_num = data.get(ATTR_MAX_FACE_NUM, 1)
|
||||
min_face_size = data.get(ATTR_MIN_FACE_SIZE, 34)
|
||||
max_user_num = data.get(ATTR_MAX_USER_NUM, 5)
|
||||
@@ -138,6 +242,7 @@ async def async_face_search_service(call: ServiceCall) -> Dict[str, Any]:
|
||||
image_url=image_url,
|
||||
image_path=image_path,
|
||||
image_file=image_file,
|
||||
camera_entity_id=camera_entity_id,
|
||||
group_ids=[group_id],
|
||||
max_face_num=max_face_num,
|
||||
min_face_size=min_face_size,
|
||||
@@ -147,47 +252,45 @@ async def async_face_search_service(call: ServiceCall) -> Dict[str, Any]:
|
||||
face_match_threshold=face_match_threshold
|
||||
)
|
||||
|
||||
# 直接返回结果,包含状态和错误信息
|
||||
if result.get("success", False):
|
||||
for face in result.get("faces", []):
|
||||
for candidate in face.get("candidates", []):
|
||||
hass.bus.async_fire(EVENT_FACE_DETECTED, {
|
||||
ATTR_PERSON_ID: candidate.get("person_id"),
|
||||
ATTR_PERSON_NAME: candidate.get("person_name"),
|
||||
"score": candidate.get("score"),
|
||||
ATTR_PERSON_TAG: candidate.get("person_tag"),
|
||||
ATTR_GROUP_ID: group_id,
|
||||
ATTR_CAMERA_ENTITY_ID: camera_entity_id,
|
||||
})
|
||||
|
||||
return result
|
||||
|
||||
except HomeAssistantError:
|
||||
raise
|
||||
except Exception as ex:
|
||||
_LOGGER.error("人脸搜索服务调用失败: %s", ex)
|
||||
# 返回错误信息,而不是抛出异常
|
||||
return {
|
||||
"success": False,
|
||||
"faces": [],
|
||||
"error": str(ex),
|
||||
"error_code": "service_error",
|
||||
"error_message": str(ex)
|
||||
}
|
||||
raise HomeAssistantError(f"人脸搜索服务调用失败: {ex}")
|
||||
|
||||
|
||||
async def async_detect_face_service(call: ServiceCall) -> Dict[str, Any]:
|
||||
"""人脸检测服务"""
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
|
||||
hass = call.hass
|
||||
data = call.data
|
||||
|
||||
# 获取配置项
|
||||
config_entry = _get_config_entry(hass)
|
||||
if not config_entry:
|
||||
entry_data = _get_entry_data(hass, data.get(ATTR_CONFIG_ENTRY_ID))
|
||||
if not entry_data:
|
||||
raise HomeAssistantError("未找到腾讯云人脸识别配置")
|
||||
|
||||
# 获取插件实例
|
||||
entry_data = _get_entry_data(hass)
|
||||
if not entry_data:
|
||||
raise HomeAssistantError("腾讯云人脸识别插件未正确初始化")
|
||||
|
||||
face_recognition = entry_data.get("face_recognition")
|
||||
if not face_recognition:
|
||||
raise HomeAssistantError("腾讯云人脸识别插件未正确初始化")
|
||||
|
||||
# 调用人脸检测功能
|
||||
try:
|
||||
image_url = data.get(ATTR_IMAGE_URL)
|
||||
image_path = data.get(ATTR_IMAGE_PATH)
|
||||
image_file = data.get(ATTR_IMAGE_FILE)
|
||||
camera_entity_id = data.get(ATTR_CAMERA_ENTITY_ID)
|
||||
max_face_num = data.get(ATTR_MAX_FACE_NUM, 1)
|
||||
min_face_size = data.get(ATTR_MIN_FACE_SIZE, 34)
|
||||
need_rotate_check = data.get(ATTR_NEED_ROTATE_CHECK, 1)
|
||||
@@ -196,52 +299,43 @@ async def async_detect_face_service(call: ServiceCall) -> Dict[str, Any]:
|
||||
image_url=image_url,
|
||||
image_path=image_path,
|
||||
image_file=image_file,
|
||||
camera_entity_id=camera_entity_id,
|
||||
max_face_num=max_face_num,
|
||||
min_face_size=min_face_size,
|
||||
need_rotate_check=need_rotate_check
|
||||
)
|
||||
|
||||
# 直接返回结果,包含状态和错误信息
|
||||
if not result.get("success", False):
|
||||
error_msg = result.get("error_message", result.get("error", "未知错误"))
|
||||
raise HomeAssistantError(f"人脸检测失败: {error_msg}")
|
||||
|
||||
return result
|
||||
|
||||
except HomeAssistantError:
|
||||
raise
|
||||
except Exception as ex:
|
||||
_LOGGER.error("人脸检测服务调用失败: %s", ex)
|
||||
# 返回错误信息,而不是抛出异常
|
||||
return {
|
||||
"success": False,
|
||||
"faces": [],
|
||||
"error": str(ex),
|
||||
"error_code": "service_error",
|
||||
"error_message": str(ex)
|
||||
}
|
||||
raise HomeAssistantError(f"人脸检测服务调用失败: {ex}")
|
||||
|
||||
|
||||
async def async_get_face_attributes_service(call: ServiceCall) -> Dict[str, Any]:
|
||||
"""获取人脸属性服务"""
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
|
||||
hass = call.hass
|
||||
data = call.data
|
||||
|
||||
# 获取配置项
|
||||
config_entry = _get_config_entry(hass)
|
||||
if not config_entry:
|
||||
entry_data = _get_entry_data(hass, data.get(ATTR_CONFIG_ENTRY_ID))
|
||||
if not entry_data:
|
||||
raise HomeAssistantError("未找到腾讯云人脸识别配置")
|
||||
|
||||
# 获取插件实例
|
||||
entry_data = _get_entry_data(hass)
|
||||
if not entry_data:
|
||||
raise HomeAssistantError("腾讯云人脸识别插件未正确初始化")
|
||||
|
||||
face_recognition = entry_data.get("face_recognition")
|
||||
if not face_recognition:
|
||||
raise HomeAssistantError("腾讯云人脸识别插件未正确初始化")
|
||||
|
||||
# 调用获取人脸属性功能
|
||||
try:
|
||||
image_url = data.get(ATTR_IMAGE_URL)
|
||||
image_path = data.get(ATTR_IMAGE_PATH)
|
||||
image_file = data.get(ATTR_IMAGE_FILE)
|
||||
camera_entity_id = data.get(ATTR_CAMERA_ENTITY_ID)
|
||||
max_face_num = data.get(ATTR_MAX_FACE_NUM, 1)
|
||||
need_rotate_check = data.get(ATTR_NEED_ROTATE_CHECK, 1)
|
||||
|
||||
@@ -249,34 +343,160 @@ async def async_get_face_attributes_service(call: ServiceCall) -> Dict[str, Any]
|
||||
image_url=image_url,
|
||||
image_path=image_path,
|
||||
image_file=image_file,
|
||||
camera_entity_id=camera_entity_id,
|
||||
max_face_num=max_face_num,
|
||||
need_rotate_check=need_rotate_check
|
||||
)
|
||||
|
||||
# 直接返回结果,包含状态和错误信息
|
||||
if not result.get("success", False):
|
||||
error_msg = result.get("error_message", result.get("error", "未知错误"))
|
||||
raise HomeAssistantError(f"获取人脸属性失败: {error_msg}")
|
||||
|
||||
return result
|
||||
|
||||
except HomeAssistantError:
|
||||
raise
|
||||
except Exception as ex:
|
||||
_LOGGER.error("获取人脸属性服务调用失败: %s", ex)
|
||||
# 返回错误信息,而不是抛出异常
|
||||
return {
|
||||
"success": False,
|
||||
"faces": [],
|
||||
"error": str(ex),
|
||||
"error_code": "service_error",
|
||||
"error_message": str(ex)
|
||||
}
|
||||
raise HomeAssistantError(f"获取人脸属性服务调用失败: {ex}")
|
||||
|
||||
|
||||
def _get_config_entry(hass: HomeAssistant):
|
||||
"""获取配置项"""
|
||||
for entry in hass.config_entries.async_entries(DOMAIN):
|
||||
return entry
|
||||
return None
|
||||
async def async_create_person_service(call: ServiceCall) -> Dict[str, Any]:
|
||||
"""创建人员服务"""
|
||||
hass = call.hass
|
||||
data = call.data
|
||||
|
||||
def _get_entry_data(hass: HomeAssistant):
|
||||
"""获取配置项数据"""
|
||||
for entry_id, data in hass.data.get(DOMAIN, {}).items():
|
||||
if isinstance(data, dict) and "face_recognition" in data:
|
||||
return data
|
||||
return None
|
||||
entry_data = _get_entry_data(hass, data.get(ATTR_CONFIG_ENTRY_ID))
|
||||
if not entry_data:
|
||||
raise HomeAssistantError("未找到腾讯云人脸识别配置")
|
||||
|
||||
face_recognition = entry_data.get("face_recognition")
|
||||
if not face_recognition:
|
||||
raise HomeAssistantError("腾讯云人脸识别插件未正确初始化")
|
||||
|
||||
try:
|
||||
result = await face_recognition.async_create_person(
|
||||
person_id=data.get(ATTR_PERSON_ID),
|
||||
person_name=data.get(ATTR_PERSON_NAME),
|
||||
group_id=data.get(ATTR_GROUP_ID),
|
||||
image_url=data.get(ATTR_IMAGE_URL),
|
||||
image_path=data.get(ATTR_IMAGE_PATH),
|
||||
image_file=data.get(ATTR_IMAGE_FILE),
|
||||
camera_entity_id=data.get(ATTR_CAMERA_ENTITY_ID),
|
||||
gender=data.get(ATTR_GENDER),
|
||||
person_tag=data.get(ATTR_PERSON_TAG),
|
||||
quality_control=data.get(ATTR_QUALITY_CONTROL, 1),
|
||||
need_rotate_check=data.get(ATTR_NEED_ROTATE_CHECK, 1),
|
||||
)
|
||||
|
||||
if not result.get("success", False):
|
||||
error_msg = result.get("error_message", result.get("error", "未知错误"))
|
||||
raise HomeAssistantError(f"创建人员失败: {error_msg}")
|
||||
|
||||
return result
|
||||
|
||||
except HomeAssistantError:
|
||||
raise
|
||||
except Exception as ex:
|
||||
_LOGGER.error("创建人员服务调用失败: %s", ex)
|
||||
raise HomeAssistantError(f"创建人员服务调用失败: {ex}")
|
||||
|
||||
|
||||
async def async_delete_person_service(call: ServiceCall) -> Dict[str, Any]:
|
||||
"""删除人员服务"""
|
||||
hass = call.hass
|
||||
data = call.data
|
||||
|
||||
entry_data = _get_entry_data(hass, data.get(ATTR_CONFIG_ENTRY_ID))
|
||||
if not entry_data:
|
||||
raise HomeAssistantError("未找到腾讯云人脸识别配置")
|
||||
|
||||
face_recognition = entry_data.get("face_recognition")
|
||||
if not face_recognition:
|
||||
raise HomeAssistantError("腾讯云人脸识别插件未正确初始化")
|
||||
|
||||
try:
|
||||
result = await face_recognition.async_delete_person(
|
||||
person_id=data.get(ATTR_PERSON_ID),
|
||||
)
|
||||
|
||||
if not result.get("success", False):
|
||||
error_msg = result.get("error_message", result.get("error", "未知错误"))
|
||||
raise HomeAssistantError(f"删除人员失败: {error_msg}")
|
||||
|
||||
return result
|
||||
|
||||
except HomeAssistantError:
|
||||
raise
|
||||
except Exception as ex:
|
||||
_LOGGER.error("删除人员服务调用失败: %s", ex)
|
||||
raise HomeAssistantError(f"删除人员服务调用失败: {ex}")
|
||||
|
||||
|
||||
async def async_create_face_service(call: ServiceCall) -> Dict[str, Any]:
|
||||
"""注册人脸服务"""
|
||||
hass = call.hass
|
||||
data = call.data
|
||||
|
||||
entry_data = _get_entry_data(hass, data.get(ATTR_CONFIG_ENTRY_ID))
|
||||
if not entry_data:
|
||||
raise HomeAssistantError("未找到腾讯云人脸识别配置")
|
||||
|
||||
face_recognition = entry_data.get("face_recognition")
|
||||
if not face_recognition:
|
||||
raise HomeAssistantError("腾讯云人脸识别插件未正确初始化")
|
||||
|
||||
try:
|
||||
result = await face_recognition.async_create_face(
|
||||
person_id=data.get(ATTR_PERSON_ID),
|
||||
image_url=data.get(ATTR_IMAGE_URL),
|
||||
image_path=data.get(ATTR_IMAGE_PATH),
|
||||
image_file=data.get(ATTR_IMAGE_FILE),
|
||||
camera_entity_id=data.get(ATTR_CAMERA_ENTITY_ID),
|
||||
quality_control=data.get(ATTR_QUALITY_CONTROL, 1),
|
||||
need_rotate_check=data.get(ATTR_NEED_ROTATE_CHECK, 1),
|
||||
)
|
||||
|
||||
if not result.get("success", False):
|
||||
error_msg = result.get("error_message", result.get("error", "未知错误"))
|
||||
raise HomeAssistantError(f"注册人脸失败: {error_msg}")
|
||||
|
||||
return result
|
||||
|
||||
except HomeAssistantError:
|
||||
raise
|
||||
except Exception as ex:
|
||||
_LOGGER.error("注册人脸服务调用失败: %s", ex)
|
||||
raise HomeAssistantError(f"注册人脸服务调用失败: {ex}")
|
||||
|
||||
|
||||
async def async_delete_face_service(call: ServiceCall) -> Dict[str, Any]:
|
||||
"""删除人脸服务"""
|
||||
hass = call.hass
|
||||
data = call.data
|
||||
|
||||
entry_data = _get_entry_data(hass, data.get(ATTR_CONFIG_ENTRY_ID))
|
||||
if not entry_data:
|
||||
raise HomeAssistantError("未找到腾讯云人脸识别配置")
|
||||
|
||||
face_recognition = entry_data.get("face_recognition")
|
||||
if not face_recognition:
|
||||
raise HomeAssistantError("腾讯云人脸识别插件未正确初始化")
|
||||
|
||||
try:
|
||||
result = await face_recognition.async_delete_face(
|
||||
person_id=data.get(ATTR_PERSON_ID),
|
||||
face_id=data.get(ATTR_FACE_ID),
|
||||
)
|
||||
|
||||
if not result.get("success", False):
|
||||
error_msg = result.get("error_message", result.get("error", "未知错误"))
|
||||
raise HomeAssistantError(f"删除人脸失败: {error_msg}")
|
||||
|
||||
return result
|
||||
|
||||
except HomeAssistantError:
|
||||
raise
|
||||
except Exception as ex:
|
||||
_LOGGER.error("删除人脸服务调用失败: %s", ex)
|
||||
raise HomeAssistantError(f"删除人脸服务调用失败: {ex}")
|
||||
|
||||
Reference in New Issue
Block a user