HomeAssistant自定义API返回AssertionError的问题排查
问题描述
我创建了一个基于HomeAssistantView的POST API,该API读取存储JSON内容的core.entity_registry文件,根据请求传入的device_id筛选关联实体。代码实现如下:
class EntityBasedOnDeviceId(HomeAssistantView): """API that will read the entity registry file and read the entities corresponding to a device ID""" url = URL_API_ENTITY_BASED_ON_DEVICEID name = "api: entity_based_on_deviceId" async def post(self, request): """Returning the content of the file core.entity_registry in response""" json_data = await request.json() device_id = json_data["device_id"] file_object = open("/home/vvdn/core/config/.storage/core.entity_registry", "r") content = file_object.read() content = json.loads(content) device_entities = {"entities": []} for entity in content["data"]["entities"]: print("\n hello \n", entity['device_id']) if entity["device_id"] is None: print("Yes working is None") if entity["device_id"] is not None: print("yes device_id is not None") if entity["device_id"] == device_id: device_entities["entities"].append(entity) return device_entities
读取的core.entity_registry文件内容示例如下:
{ "version": 1, "minor_version": 8, "key": "core.entity_registry", "data": { "entities": [ { "area_id": null, "capabilities": {}, "config_entry_id": "b9ea169ebb460d3365262535b9550e5c", "device_class": null, "device_id": "b7d5c082a6b80d874653fae7d6d7ca10", "disabled_by": null, "entity_category": null, "entity_id": "media_player.tv", "hidden_by": null, "icon": null, "id": "ac35c115166f6a2409dbc87c2f6fa508", "has_entity_name": true, "name": null, "options": {}, "original_device_class": null, "original_icon": null, "original_name": null, "platform": "cast", "supported_features": 131968, "unique_id": "bf2da007-c30c-45a7-ef5a-7951d86cfb59", "unit_of_measurement": null }, { "area_id": null, "capabilities": null, "config_entry_id": null, "device_class": null, "device_id": null, "disabled_by": null, "entity_category": null, "entity_id": "person.kapil", "hidden_by": null, "icon": null, "id": "eb5382f464532d63ae88d80b3d865f8f", "has_entity_name": false, "name": null, "options": {}, "original_device_class": null, "original_icon": null, "original_name": "Kapil", "platform": "person", "supported_features": 0, "unique_id": "kapil", "unit_of_measurement": null } ] } }
调用API时触发如下错误:
2022-09-20 16:01:23.855 ERROR (MainThread) [aiohttp.server] Error handling request Traceback (most recent call last): File "/home/vvdn/core/venv/lib/python3.10/site-packages/aiohttp/web_protocol.py", line 435, in _handle_request resp = await request_handler(request) File "/home/vvdn/core/venv/lib/python3.10/site-packages/aiohttp/web_app.py", line 504, in _handle resp = await handler(request) File "/home/vvdn/core/venv/lib/python3.10/site-packages/aiohttp/web_middlewares.py", line 117, in impl return await handler(request) File "/home/vvdn/core/homeassistant/components/http/security_filter.py", line 60, in security_filter_middleware return await handler(request) File "/home/vvdn/core/homeassistant/components/http/forwarded.py", line 100, in forwarded_middleware return await handler(request) File "/home/vvdn/core/homeassistant/components/http/request_context.py", line 28, in request_context_middleware return await handler(request) File "/home/vvdn/core/homeassistant/components/http/ban.py", line 82, in ban_middleware return await handler(request) File "/home/vvdn/core/homeassistant/components/http/auth.py", line 236, in auth_middleware return await handler(request) File "/home/vvdn/core/homeassistant/components/http/view.py", line 160, in handle assert ( AssertionError: Result should be None, string, bytes or StreamResponse. Got: {'entities': [{'area_id': None, 'capabilities': {}, 'config_entry_id': 'b9ea169ebb460d3365262535b9550e5c', 'device_class': None, 'device_id': 'b7d5c082a6b80d874653fae7d6d7ca10', 'disabled_by': None, 'entity_category': None, 'entity_id': 'media_player.tv', 'hidden_by': None, 'icon': None, 'id': 'ac35c115166f6a2409dbc87c2f6fa508', 'has_entity_name': True, 'name': None, 'options': {}, 'original_device_class': None, 'original_icon': None, 'original_name': None, 'platform': 'cast', 'supported_features': 131968, 'unique_id': 'bf2da007-c30c-45a7-ef5a-7951d86cfb59', 'unit_of_measurement': None}]}
错误原因
报错信息明确指出问题:HomeAssistantView的请求处理方法不能直接返回Python字典,它要求返回结果必须是None、字符串、字节或者StreamResponse类型对象,你直接返回device_entities字典不符合要求。
修正方案
1. 核心修复:使用json_response返回正确格式
HomeAssistantView提供了json_response()方法,可将Python字典转换为符合要求的JSON响应对象,修改post方法最后一行:
return self.json_response(device_entities)
2. 额外优化建议
- 避免直接操作注册表文件:Home Assistant内置了实体注册表API,通过
request.app["hass"].helpers.entity_registry.async_get()获取注册表,比手动读取文件更安全、更符合规范。 - 文件操作使用
with语句:若必须手动读取文件,用with语句可自动关闭文件,避免资源泄漏:with open("/home/vvdn/core/config/.storage/core.entity_registry", "r") as file_object: content = file_object.read() - 简化筛选逻辑:用列表推导式简化实体筛选代码:
device_entities = { "entities": [ entity for entity in content["data"]["entities"] if entity.get("device_id") == device_id ] }
修正后的完整代码
class EntityBasedOnDeviceId(HomeAssistantView): """API that will read the entity registry file and read the entities corresponding to a device ID""" url = URL_API_ENTITY_BASED_ON_DEVICEID name = "api: entity_based_on_deviceId" async def post(self, request): """Returning entities corresponding to the given device ID""" json_data = await request.json() device_id = json_data["device_id"] # 使用Home Assistant内置API获取实体注册表(推荐方式) entity_registry = await request.app["hass"].helpers.entity_registry.async_get() device_entities = { "entities": [ entity for entity in entity_registry.entities.values() if entity.device_id == device_id ] } return self.json_response(device_entities)
内容的提问来源于stack exchange,提问作者Kapil Sharma
相关产品推荐
相关产品推荐

