星路

追寻那一缕星光,在漆黑夜晚前行

0%

【插件】小米(绿米)网关转发代理

小米(绿米)网关局域网通信协议中,网关采用UDP组播方式上报终端设备心跳及状态。目前家里有一些米家的设备,通过绿米的空调伴侣网关接入HA。由于docker对网络隔离,容器在桥接模式下是无法收到宿主机的组播包,查找过文档没找到能映射组播端口的方法。所以自从Home Assistant迁移到docker环境运行后,只能设置容器网络为host模式来解决这个问题,但一来容器间无法用容器名互访影响统一编排管理,二来容器共享主机网络也有一定安全隐患,所以做了这个,测试下来效果不错。


0. 插件说明

  • 概述
    • 原理很简单,在局域网主机使用agent采集UDP组播消息,封装为TCP发送给Home Assistant插件,插件再还原为UDP组播消息发送到容器本身网络空间。
    • 小米(绿米)网关[UDP组播] —> 局域网主机(agent)[TCP] —> HA容器(本插件)[UDP组播] —> HA容器(xiaomi_aqara网关插件)
  • 下载地址

1.环境

  • Ubuntu 20.04(部署采集程序)
  • Docker 19.03.15
  • Home Assistant 2021.5.4

2.使用说明

2.1 启用Home Assistant插件

假设Home Assistant宿主机为192.168.1.100,映射服务端口为4321

  • 下载HA插件,xiaomi_gateway_proxy目录放置在{HA配置目录}/custom_components/下。
  • HA配置启用xiaomi_gateway_proxy插件。
    1
    2
    3
    # 在 configuration.yaml 添加
    xiaomi_gateway_proxy:
    port: 4321 # 通信端口,不指定默认4321
  • docker宿主机将插件通信端口映射出来。
    1
    2
    # docker run方式,增加-p 参数
    docker run -p 4321:4321/tcp [省略...]
    1
    2
    3
    4
    5
    6
    7
    # docker-compose方式,增加ports设置
    [省略...]
    services:
    homeassistant:
    [省略...]
    ports:
    - 4321:4321/tcp

    INFO:插件作为服务端,提供服务端口给采集程序连接。

2.2 部署采集程序

在和网关同一局域网的机器上部署,采集程序需要python环境运行,一般linux系统已经自带。如果使用windows部署,可编写bat放到计划任务启动执行,具体方法自行搜索。

  • 下载xiaomi_gateway_proxy_agent.py,假设放置在/opt/homeassistant下。

  • 启动采集程序,脚本目录、HA宿主机ip、HA插件服务映射端口根据实际调整

    1
    python3 /opt/homeassistant/xiaomi_gateway_proxy_agent.py --host 192.168.1.100 --port 4321 >/dev/null 2>&1 &

    INO:建议先不加>/dev/null 2>&1 &参数,在前台运行看下输出是否有异常。

  • 启用开机启动服务(有些linux已启用,可跳过该步骤)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    touch /etc/rc.local
    chmod +x /etc/rc.local
    cat /lib/systemd/system/rc-local.service | grep Install || \
    cat >> /lib/systemd/system/rc-local.service << EOF
    [Install]
    WantedBy=multi-user.target
    Alias=rc-local.service
    EOF
    systemctl enable rc-local.service

    INO:不同版本linux有差异,具体请自行搜索。

  • 编辑/etc/rc.local添加启动脚本

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #!/bin/sh
    # 脚本目录、HA宿主机ip、HA插件服务映射端口根据实际调整

    # python2版本使用这个
    # python /opt/homeassistant/xiaomi_gateway_proxy_agent.py --host 192.168.1.100 --port 4321 >/dev/null 2>&1 &

    # python3版本使用这个
    python3 /opt/homeassistant/xiaomi_gateway_proxy_agent.py --host 192.168.1.100 --port 4321 >/dev/null 2>&1 &

    # 新建的文件不能忽略这个
    exit 0

3. 小结

  • HA的网关插件需要提取组播通信包的源IP信息,一开始使用udxpy作为采集客户端,发现无法传递源IP信息,所以写了python版本的采集程序。
  • 设想过另一种解决方案是将宿主机和容器做IP隧道直接转发UDP组播,感觉实现比较复杂暂没深入研究。