You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 23:20:27