HomeAssistant自定义组件学习-【一】

该文章已生成可运行项目,

#环境准备#

按官方的步骤准备就可以,我是在Windows下使用VS Code开发的,安装了WSL(使用模板创建组件需要在WSL环境下完成)

官方链接:https://developers.home-assistant.io/docs/development_environment

#生成代码#

环境准备好后,在项目根目录下使用命令:

python3 -m script.scaffold integration

创建组件后会自动生成几个文件:__init__.py,const.py,config_flow.py和mainfest.json、string.json。

研究中盛官方给的工具软件测试,可以确定是可以自动发现设备的,所以组件整体思路就是,选择组件后,就自动发现网络上的设备,然后自动生成对应IO数量的灯和开关实体,不需要通过界面让用户输入其他数据,很简单的一个逻辑吧,但是实现硬是搞了我两个月(期间有一个月被搞得头大,没心思搞,玩了一个月吃鸡!),主要原因是不知道组件的执行流程,从哪个函数方法调用,配置的数据存储在哪里,怎么保存自己需要的数据,后面才发现,根本不需要考虑这些,直接干就完了。下面进入正题:

mainfest.json、string.json这两个Json文件暂时不需要去碰,因为不需要去做界面(估计做窗帘组件的时候需要去弄)。看__init__.py和config_flow.py两个文件:


from __future__ import annotations

from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant

from .const import PLATFORMS

# TODO Create ConfigEntry type alias with API object
# TODO Rename type alias and update all entry annotations
# type NovoConfigEntry = ConfigEntry[0xF843]  # noqa: F821


# TODO Update entry annotation
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
    """Set up Novo from a config entry."""

    # TODO 1. Create API instance
    # TODO 2. Validate the API connection (and authentication)
    # TODO 3. Store an API object for your platforms to access
    # entry.runtime_data = MyAPI(...)

    await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)

    return True


# TODO Update entry annotation
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
    """Unload a config entry."""
    return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)

以上是自动生成的__init__.py的文件内容,查看文档,说的是加载组件的时候,就会调用async_setup_entry方法,如果创建组件的时候选择了自动发现设备,就会调用config_flow.py文件中的:async def _async_has_devices(hass: HomeAssistant) -> bool:,那发现设备的代码放在这两个地方都是可以的。

PS:后续测试发现,代码调用是有顺序的,顺序是:

Config_flow.py->__init__.py->PLATFORMS中顺序调用async_setup_entry

#实现设备代码#

决定把发现代码放在__init__.py中。

#自动发现设备#

设备发现代码是通过Wireshark抓网络包分析自动发现设备过程,使用UDP协议,向网络中的5002端口发送约定的字符串:

{"cmd":"search","vendor":"www.coltsmart.com","product":"MJ-ExSx","keyword":"FF010102"}

设备就会回复自己的信息,通过回复的信息中的IP地址和端口(返回的信息是json数据,直接使用json进行分析就可以了),我们就可以建立通讯了。完整代码:


# 扫描发现设备
def discover(ip_address=None) -> dict[int, ZhongshengConfig]:
    """扫描发现设备."""
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
    sock.settimeout(5)
    found_devices: dict[int, ZhongshengConfig] = {}
    if ip_address is None:
        addrs = enum_all_broadcast()
    else:
        addrs = [ip_address]
    for addr in addrs:
        try:
            sock.sendto(BROADCAST_MSG, (addr, BROADCAST_PORT))
        except Exception:  # noqa: BLE001
            _LOGGER.warning(f"Can't access network {addr}")  # noqa: G004
    while True:
        try:
            data, addr = sock.recvfrom(512)
            _LOGGER.debug(f"Received response from {addr}: {data.hex(' ')}")  # noqa: G004
            json_dic = json.loads(data)
            if json_dic["id"] != "":
                # 查询返回
                dev: ZhongshengConfig
                d_id: int = int(json_dic["id"])
                if d_id in found_devices:
                    dev = found_devices[d_id]
                else:
                    dev = ZhongshengConfig()
                dev.load_data(data)
                found_devices[d_id] = dev
        except TimeoutError:
            break
        except OSError as e:
            _LOGGER.error(f"Socket error: {e!r}")  # noqa: G004
    return found_devices

因为设备会返回好几组数据,所以这里需要对数据进行合并,即这段代码:

本文章已经生成可运行项目
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值