【插件】智能音箱接入Home Assistant整合Plus

之前把Home Assistant调试环境给弄好了,有点膨胀就把先前aihome插件的智能音箱网关代码进行全部重构2次。好吧,其实只是想实现不用重启可以更新设备信息就行了,中途又有点想法就就停不下来了,真的是费脑费力。不过成果还是满意的,引入一个设备信息管理层以实现配置信息的标准化,同时将基础的业务流程代码独立出来,初步实现可以通过配置的方式来扩展对音箱指令的解析支持,也算是搭建了一个粗略的框架整合接入了三个音箱平台。


0.插件说明

新插件更名为HAVSC(Home Assistant Voice Control Skill),同步更改音箱平台技能名称(不影响旧版aihome插件使用),启用新版本需要重新配置设备信息,新版本特点如下:

  • 独立配置文件,支持重载文件而无需重启HA
  • 大幅度简化配置
  • 增加指令扩展性

1.使用说明

1.1.APP的技能方式接入

使用官方APP技能,配合havcs服务可实现免公网IP接入。

  • 下载havcs插件,放置到HA自定义插件目录,最终路径结构为{HA配置目录}/custom_components/havcs/__init__.py
  • 前往页面注册账号,获取AppKey和AppSecret(先登录再生成,生成后记得保存)。
  • 音箱APP->搜索’havcs’技能->关联账号->输入注册的账号信息登录。
  • 配置Home Assistant

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    # {HA配置目录}/configuration.yaml                 
    havcs:
    platform: # 音箱平台服务网关,至少启用一个
    - aligenie # 天猫精灵
    - dueros # 小度
    - jdwhale # 叮咚
    skill:
    bind_device: True # 是否启动时更新设备绑定信息。不设置默认True(叮咚音箱才有效)>>*新版本加入<<>
    sync_device: False # 是否主动上报设备状态。不设置默认False(小度音箱才有效)
    # mqtt相关设置,启用http代理服务及APP技能服务才生效
    setting:
    app_key: your_app_key # 注册账号获取的AppKey
    app_secret: your_app_secret # 注册账号获取的AppSecret
    entity_key: your_entity_key # 加密entity_id的key,自定义16个字符
    device_config: full_path # 设备配置文件路径(完整路径)。不设置默认{HA配置目录}/havcs.yaml >>*新版本加入<<
  • 配置设备信息(详见第2章节)

    1
    2
    3
    4
    5
    6
    7
    # 配置文件整体结构(默认文件路径:{HA配置目录}/havcs.yaml)
    设备1的entity_id:
    属性1:
    属性2:
    设备2的entity_id:
    属性1:
    属性2:
    1
    2
    3
    4
    # 单设备样例
    light.demo:
    havcs_device_name: 主卧灯
    havcs_zone: 主卧
  • 更新音箱平台设备信息

    • 先重载本地信息:调用服务(HA web->开发者工具->服务->调用havcs.reload)或者重启HA
    • 叮咚:重载本地信息会触发上报(bind_device配置为True)。
    • 天猫精灵:在APP中重新绑定触发更新。
    • 小度:执行“发现设备”指令触发更新。

1.2.自建技能方式接入

  • 音箱技能配置略
  • 配置Home Assistant

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # {HA配置目录}/configuration.yaml                 
    havcs:
    platform: # 音箱平台服务网关,至少启用一个
    - aligenie # 天猫精灵
    - dueros # 小度
    - jdwhale # 叮咚
    http:
    ha_url: https://localhost:8123 # HA所在主机/容器IP地址,不设置则默认识别
    expire_in_hours: 24 # token超时时间,单位小时,不设置则默认24h
    device_config: full_path # 设备配置文件路径(完整路径)。不设置默认{HA配置目录}/havcs.yaml >>*新版本加入<<
  • 配置设备信息及更新音箱平台设备信息同上章节

  • 新版注意事项及实践建议
    • uri调整:/aihome_auth -> /havcs_auth/aihome_service -> /havcs_service
    • 相关服务地址使用https及443端口(建议使用nginx或apache反向代理,本地可以保留http访问),https证书使用腾讯云、阿里云或者Let’s Encrypt等兼容性好的,并注意有效期。
    • 先确认本地uri可访问(插件正常启动),再测试确认服务地址的可访问(手机直接访问网址,405代表网络通)。

2.设备信息属性说明

在{HA配置目录}/havcs.yaml(或自定义文件)配置设备信息,用于生成音箱平台的设备(绑定设备)。

  • 设备统一使用属性进行配置,属性列表如下:
属性名 描述 取值 样例 备注
havcs_visable 设备可见性 [‘aligenie’, ‘dueros’, ‘jdwhale’] [‘aligenie’, ‘dueros’] 设置该属性则设备只对指定平台可见;如不设置,对所有平台可见
havcs_device_name 设备名称 *天猫精灵限制 客厅灯 必填,建议“房间”+“设备类型”可以兼容三个平台使用
havcs_zone 设备位置 *天猫精灵限制 客厅 天猫精灵必填,其它可不用指定
havcs_device_type 设备类型 light /switch /sensor /input_boolean light 一般不用指定
havcs_attributes 属性 [‘temperature’, ‘brightness’, ‘humidity’, ‘pm25’, ‘co2’, ‘power_state’] [‘power_state’] 一般不用指定
havcs_actions 支持操作 [‘turn_on’, ‘turn_off’, ‘timing_turn_on’, ‘timing_turn_off’, ‘query_temperature’, ‘query_humidity’, ‘increase_brightness’, ‘decrease_brightness’] [‘turn_on’, ‘turn_off’] 一般不用指定
havcs_related_sensors 传感器设备专用,关联真实传感器 sensor/group列表 [‘sensor.demo’, ‘group.demo’] 支持设置group,会搜索加入该分组下的sensor

2.1 特殊设备配置说明

对input_boolean类型的配置方式进行了扩展,实现指定指令调用自定义的service。

  • 新增一个input_boolean实体

    1
    2
    3
    #{HA配置目录}/configuration.yaml
    input_boolean:
    call_service:
  • 自定义虚拟input_boolean的属性,在havcs_actions属性中设置对应的service指令(只能设置turn_on/turn_off/timing_turn_on/timing_turn_off/increase_brightness/decrease_brightness,对应打开/关闭/延时打开/延时关闭/调高亮度/调低亮度指令)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    #{HA配置目录}/havcs.yaml
    input_boolean.call_service:
    havcs_device_name: 客厅灯
    havcs_zone: 客厅
    havcs_device_type: light # 模拟灯设备
    havcs_attributes: ['power_state']
    #↓↓↓指令根据实际需要配置↓↓↓
    havcs_actions:
    # service指令格式:[domain, service_name, service_data(json字符串)],具体内容需参见相应组件的服务定义。
    # 注意,参数变更为数组以支持多条指令,单条指令也别忘了加-
    turn_on:
    - ['common_timer', 'set', '{"entity_id":"switch.demo","duration":"01:00:00","operation":"off"}'] # 打开命令
    - ['input_boolean', 'turn_on', '{}'] # 同步打开状态
    turn_off:
    - ['common_timer', 'cancel', '{"entity_id":"switch.demo"}'] # 关闭命令
    - ['input_boolean', 'turn_off', '{}'] # 同步关闭状态
    timing_turn_on: # 延时打开指令(小度音箱)
    - ['指令1']
    - ['指令2']
    timing_turn_off: # 延时关闭指令(小度音箱)
    - ['指令1']
    - ['指令2']
    increase_brightness:
    - ['指令1']
    - ['指令2']
    decrease_brightness:
    - ['指令1']
    - ['指令2']

    INFO:调自动化(automation.turn_on)、调脚本(scrpit.turn_on)、调红外指令(climate.xiaomi_miio_send_command)等会比较适合。
    INFO:天猫精灵无法自定义名称,不太适合使用。


3.完成度

目前完成度有些低,后续再继续测试完善吧。

  • 图例:✓ 支持,- 不支持,* 待测试
  • switch/cover
操作 描述 aligenie dueros jdwhale
turn_on 打开
turn_off 关闭
timing_turn_on 延时打开 - -
timing_turn_off 延时关闭 - -
  • light
操作 描述 aligenie dueros jdwhale
turn_on 打开
turn_off 关闭
timing_turn_on 延时打开 - -
timing_turn_off 延时关闭 - -
set_brightness 设置亮度 * * *
increase_brightness 调高亮度
decrease_brightness 调低亮度
set_color 设置颜色 * *
  • sensor
操作 描述 aligenie dueros jdwhale
query_temperature 查询温度
query_humidity 查询湿度
  • inpu_boolean
操作 描述 aligenie dueros jdwhale
turn_on 打开
turn_off 关闭
timing_turn_on 延时打开 - -
timing_turn_off 延时关闭 - -
increase_brightness 调高亮度
decrease_brightness 调低亮度

4.控制指令说明

  • 叮咚

    • 打开/关闭

      1
      2
      3
      4
      #打开/关闭
      #用途:一般为电源控制
      #语义:打开/关闭{设备名称}
      #例子:打开主卧灯
    • 查询状态

      1
      2
      3
      4
      #打开/关闭
      #用途:查询设备状态
      #语义:查询{设备名称}的{状态/xx状态}
      #例子:查询主卧传感器的状态;查询主卧传感器的温度;查询主卧灯的电源状态

    INFO:传感器信息需要挂靠到具体设备上进行查询。一般来说温度、湿度需要挂靠到空气净化器类型上。

  • 天猫精灵

    • 打开/关闭
      1
      2
      3
      4
      5
      #打开/关闭
      #用途:一般为电源控制
      #语义:打开/关闭{房间名}的{设备类型/别名}
      #例子:打开主卧的灯。
      #备注:{房间名}、{设备类型/别名}需要指定,均为枚举值

    INFO:优先匹配“位置(可为空)+别名”:例如有台灯、灯两个设备,“打开台灯”则精确匹配台灯;然后匹配“位置(可为空)+设备类型”,例如有一个台灯设备,“打开吸顶灯”、“打开床头灯”等都可控制。指令不带位置,如设备别名多个匹配,询问设备位置;当有相同匹配,一起执行。

    • 查询状态
      1
      2
      3
      4
      #打开/关闭
      #用途:查询设备状态
      #语义:查询{房间名}{设备类型/别名}的{状态/xx状态}
      #例子:查询主卧传感器的状态;查询主卧传感器的温度

    INFO:查询传感器好像有个bug:查询所有状态不能正常播报;查询单个状态,发送的指令是查询所有状态的指令。

  • 小度

    • 打开/关闭
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      #打开/关闭
      #用途:一般为电源控制
      #语义:打开/关闭{设备名称}
      #例子:打开主卧灯
      ```
      - 查询状态
      ```yaml
      #打开/关闭
      #用途:查询设备状态
      #语义:查询{设备名称}的{xx状态}/{设备名称}查询{xx状态}
      #例子:查询主卧传感器的温度/主卧传感器查询温度

    INFO:只能查询单一状态。


4.调试说明

  • 把havcs插件日志级别提高,过滤其它插件输出日志,方便观察日志输出,调试后注意恢复
    1
    2
    3
    4
    5
    # [HA配置目录]/configuration.yaml
    logger:
    default: error # 提高所有组件的默认级别,调试完后改回info(预设)
    logs: # 设定指定组件的级别,debug有更详细的输出
    custom_components.havcs: debug

5.小结

  • 有了统一的设备信息定义,后续可以考虑做设备管理页面。