『瀚思彼岸』» 智能家居技术论坛

 找回密码
 立即注册
查看: 2770|回复: 15

[技术探讨] 无需定制硬件的红外风扇完美集成方法

[复制链接]

4

主题

48

帖子

747

积分

高级会员

Rank: 4

积分
747
金钱
699
HASS币
0
发表于 2024-6-1 02:32:13 | 显示全部楼层 |阅读模式
本帖最后由 myhades 于 2024-7-23 11:26 编辑

[2027.07.23更新] 稍微改了下自动化和发送的脚本,建议更新;同时加入了应对dyson风扇3年后关机摇头的通病的缓解措施,即手动关闭摇头后再关机。

几年前因为好看买了个Dyson AM-07风扇,发现完全没有办法接入HA,因为不能用智能插座直接开关(断电后通电风扇不会打开),个人也不能接受纯红外发射这种没有状态的接入,所以一直放弃。
后来想到,如果风扇的 10(风速档位)*2(摇头开关)+1(关)=21种状态各自有不重叠的功率区间的话,通过一个带功率计的插座就能获取风扇的所有状态,加上一个万能遥控器就完成了控制和状态反馈。
这样就不需要额外买esp板子(+搭电路/画板子/打壳子),然后写固件做基于红外收发的状态获取和控制,这样做了反馈也不准确,因为可能存在红外漏收/漏发,也不能获取风扇自身状态的改变(如直接用本体上的按键操作)。

我实现了以下机制:
  1. 通过三组数据来记录风扇状态,分别对应【操作状态】/【假定状态】/【读取状态】来实现的读写。(在第四步有说明)
  2. 读取状态通过多次匹配进行确认,例如功率计报告的状态在连续 n_1 (+1) 次相同才被视为正确状态。
  3. 通过低标准匹配次数+写后容忍来平衡反馈速度和反馈状态准确率。
  4. 风扇的操作通过失败重试确保完成,即给定一个新状态后(比如设置了新的风速)在没有超过重试限度 n_2 前尽可能获取状态并重试,保证完成状态更改(这一点尤其重要,比如自动触发的离家需要确保风扇关闭)。
  5. 会保存假定状态,下次启动风扇无需等待状态获取即可进行风速更改/摇头更改操作,因为会在上次关机前的状态基础上发送更改指令(这个要求风扇有记忆行为)。

以上保证了稳定的状态获取,以及没有间隙要求的随意设定风扇的能力,我认为可以叫做完美接入了。
在红外没有漏发漏收的话,没有多余发送行为,具体机制请看自动化和脚本设定。

总结就是,想要完美的集成一个非智能风扇的条件如下:

  1. 风扇支持红外控制,且各个档位有稳定的不重叠的功率区间
  2. 一个带功率计的智能插座(我手上这个米家的wifi插座local polling间距最小10s,足够用了)
  3. 一个wifi红外遥控器(比如一般的万能遥控器)
  4. 有耐心实现本文,自动化和脚本不能用现成的!!!本文更多提供思路,需要有一定英文基础阅读文档+大概看懂配置然后自己替换不少东西才能用(之后空了可以做一个只需要填入对应配置的版本)

现在最大的缺点就是为了状态正确牺牲了一点回馈速度,但这很大程度上取决于插座状态的轮询速度。
按照我的默认配置(默认1次匹配+启用写后容忍+最大2次失败重试+200ms操作间隙),使用博联和米家wifi插座,操作后确认状态改变的时间在5-60秒,不操作得到一个正确的状态更新时间在20-40秒。
同时这种方案不能用于睡眠/自然风模式,因为风速不定会导致功率不稳定。
有很多地方可能还需要在说明一下,自动化和脚本也有些小问题,之后慢慢修补吧,我也是才用这个方案。

最后免责声明,实现这个没查任何资料和帖子,自动化和脚本都是我自己的写,如果已经有相同思路的帖子这个就当个补充/验证吧,等之后空了想写一版英文的在Community,所以烦请不用搬运。
如果看到这还有兴趣的话就可以接着做了。

{第一步} 首先需要确保你的风扇功率区间不重叠,我说的区间指的是由于风扇本身功率不稳定或是由于功率计误差带来的功率波动范围,对于直流风扇和大部分插座这两点应该问题不大。
测量的话比较简单,切换所有可能模式的组合,等稳定后记录功率计读数,看看是否有功率特别相近或者不稳定的模式(例如dyson的2-3档不好区分),然后建立区间,比如2w,5w,7w就建0-3.5,3.5-6.5,6.5-9以此类推。
同用Dyson AM-07的朋友可以用我的数据:
功率区间 风速 摇头
00.00-02.33 0 off
02.33-04.88 1 off
04.88-06.15 2 off
06.15-07.46 1 on
07.46-08.27 2 on
08.27-09.67 3 off
09.67-11.16 3 on
11.16-12.63 4 off
12.63-14.96 4 on
14.96-17.23 5 off
17.23-19.10 5 on
19.10-21.06 6 off
21.06-23.54 6 on
23.54-25.95 7 off
25.95-28.84 7 on
28.84-31.77 8 off
31.77-35.19 8 on
35.19-38.61 9 off
38.61-42.71 9 on
42.71-46.96 10 off
46.96-60.00 10 on


{第二步} 建立如下helpers,同时创建一个Template Fan(就是一个带风速/摇头控制的风扇实体),具体需要增减哪些helper取决于你风扇支持的功能以及该功能是否能被功率区分出来,我这的例子就是电源+风速+摇头开关:
名字 类型 目的
{Dyson} Power Toggle (input_boolean) 电源开关
{Dyson} Oscillate Toggle (input_boolean) 摇头开关
{Dyson} Speed Number (input_number) 速度档位(此处根据风扇情况设定,步长为1,注意最小请设为1而不是0)
Living Room - Dyson IO Select (input_select) 所有控制数据的集合

然后在HA配置文件里添加Template Fan设置(非必须,但是这样就可以优雅的控制并接入homekit),下为我的示例配置,请根据自己风扇进行更改,官方文档在这
注意由于我的dyson只记忆速度而不记忆摇头状态,所以我的turn_off有做相应处理。Again,根据自己风扇情况改。
fan:
  - platform: template
    fans:
      dyson_tower_fan:
        friendly_name: "Dyson Tower"
        unique_id: dyson_tower_fan_template_fan

        value_template: "{{ states('input_boolean.dyson_power') }}"
        turn_on:
          - service: input_boolean.turn_on
            target:
              entity_id: input_boolean.dyson_power
        turn_off:
          - service: input_boolean.turn_off
            target:
              entity_id:
                - input_boolean.dyson_power
                - input_boolean.dyson_oscillate

        percentage_template: >
          {{ states('input_number.dyson_speed')|int(default=0)*10 if is_state('input_boolean.dyson_power', 'on') else 0 }}
        speed_count: 10
        set_percentage:
          - service: input_boolean.turn_{{ 'on' if percentage > 0 else 'off' }}
            target:
              entity_id: input_boolean.dyson_power
          - service: input_number.set_value
            target:
              entity_id: input_number.dyson_speed
            data:
              value: >-
                {% set new=(percentage/10)|int(default=1) %}
                {% set current=states('input_number.dyson_speed')|int(default=1) %}

                {{ new if percentage > 0 else current }}

        oscillating_template: "{{ states('input_boolean.dyson_oscillate')=='on' }}"
        set_oscillating:
          - service: input_boolean.turn_{{ 'on' if oscillating else 'off' }}
            target:
                entity_id: input_boolean.dyson_oscillate

        availability_template: >-
            {{
                states('sensor.chuangmi_212a01_8866_electric_power')|float(default=-1)!=-1 and
                states('remote.bo_lian_rm4c_mini') not in ['unavailable','unknown',None]
            }}


{第三步} 首先请安装依赖的小脚本
建立以下两个脚本(以下仅供参考,不能直接使用,请替换对应的实体/配置)

【1.写命令脚本】需要注意替换的有IO helper的entity_id,即我这里的"input_select.living_room_dyson_io",
"interval_ms" 请设置自己万能遥控器和接收设备能用的最小值,不改的话默认200ms,
对应的操作请改为发射对应命令的服务,红外怎么学习和发射就不涵盖了。
alias: "{Dyson} Send Command"
sequence:
  - variables:
      operate_power: "{{state_attr('input_select.living_room_dyson_io','operate_power')}}"
      operate_speed: >-
        {{state_attr('input_select.living_room_dyson_io','operate_speed')|int(default=5)}}
      operate_oscillate: "{{state_attr('input_select.living_room_dyson_io','operate_oscillate')}}"
      supposed_power: "{{state_attr('input_select.living_room_dyson_io','supposed_power')}}"
      supposed_speed: >-
        {{state_attr('input_select.living_room_dyson_io','supposed_speed')|int(default=5)}}
      supposed_oscillate: "{{state_attr('input_select.living_room_dyson_io','supposed_oscillate')}}"
      interval_ms: 350
  - delay:
      hours: 0
      minutes: 0
      seconds: 0
      milliseconds: "{{ interval_ms|int(default=1000) }}"
  - if:
      - condition: template
        value_template: |-
          {{ 
            operate_oscillate != supposed_oscillate and
            (supposed_power=="on" or operate_power=="on")
          }}
    then:
      - service: python_script.set_state
        data:
          entity_id: input_select.living_room_dyson_io
          supposed_oscillate: "{{operate_oscillate}}"
      - service: remote.send_command
        target:
          entity_id:
            - remote.bo_lian_rm4c_mini
        data:
          command: oscillate_toggle
          device: dyson_tower_fan
      - delay:
          hours: 0
          minutes: 0
          seconds: 0
          milliseconds: "{{ interval_ms|int(default=1000) }}"
  - if:
      - condition: template
        value_template: "{{ operate_power != supposed_power}}"
    then:
      - service: python_script.set_state
        data:
          entity_id: input_select.living_room_dyson_io
          supposed_power: "{{operate_power}}"
      - service: remote.send_command
        target:
          entity_id:
            - remote.bo_lian_rm4c_mini
        data:
          command: power_toggle
          device: dyson_tower_fan
      - if:
          - condition: template
            value_template: "{{ supposed_power==\"off\" }}"
        then:
          - service: python_script.set_state
            data:
              entity_id: input_select.living_room_dyson_io
              supposed_oscillate: "off"
      - delay:
          hours: 0
          minutes: 0
          seconds: 0
          milliseconds: "{{ interval_ms|int(default=1000) }}"
  - if:
      - condition: template
        value_template: "{{ operate_power==\"on\" }}"
    then:
      - choose:
          - conditions:
              - condition: template
                value_template: "{{ operate_speed > supposed_speed }}"
            sequence:
              - repeat:
                  count: "{{ operate_speed - supposed_speed }}"
                  sequence:
                    - service: python_script.set_state
                      data:
                        entity_id: input_select.living_room_dyson_io
                        supposed_speed: >-
                          {{state_attr('input_select.living_room_dyson_io','supposed_speed')|int(default=1)+1}}
                    - service: remote.send_command
                      target:
                        entity_id:
                          - remote.bo_lian_rm4c_mini
                      data:
                        command: speed_up
                        device: dyson_tower_fan
                    - delay:
                        hours: 0
                        minutes: 0
                        seconds: 0
                        milliseconds: "{{ interval_ms|int(default=1000) }}"
          - conditions:
              - condition: template
                value_template: "{{ operate_speed < supposed_speed }}"
            sequence:
              - repeat:
                  count: "{{ supposed_speed - operate_speed }}"
                  sequence:
                    - service: python_script.set_state
                      data:
                        entity_id: input_select.living_room_dyson_io
                        supposed_speed: >-
                          {{state_attr('input_select.living_room_dyson_io','supposed_speed')|int(default=1)-1}}
                    - service: remote.send_command
                      target:
                        entity_id:
                          - remote.bo_lian_rm4c_mini
                      data:
                        command: speed_down
                        device: dyson_tower_fan
                    - delay:
                        hours: 0
                        minutes: 0
                        seconds: 0
                        milliseconds: "{{ interval_ms|int(default=1000) }}"
  - service: python_script.set_state
    data:
      entity_id: input_select.living_room_dyson_io
      try_count: >-
        {{state_attr('input_select.living_room_dyson_io','try_count')|int(default=0)+1}}
mode: restart
icon: fapro:dyson-fan


【2. 读状态脚本】这个要自己把功率列表和对应的状态按这个格式贴上去,然后改下helper的entity_id
alias: "{Dyson} Read"
sequence:
  - variables:
      readings: >-
        {% set fan_presets = {
          '00.00-02.33': (0, 'off'),
          '02.33-04.88': (1, 'off'),
          '04.88-06.15': (2, 'off'),
          '06.15-07.46': (1, 'on'),
          '07.46-08.27': (2, 'on'),
          '08.27-09.67': (3, 'off'),
          '09.67-11.16': (3, 'on'),
          '11.16-12.63': (4, 'off'),
          '12.63-14.96': (4, 'on'),
          '14.96-17.23': (5, 'off'),
          '17.23-19.10': (5, 'on'),
          '19.10-21.06': (6, 'off'),
          '21.06-23.54': (6, 'on'),
          '23.54-25.95': (7, 'off'),
          '25.95-28.84': (7, 'on'),
          '28.84-31.77': (8, 'off'),
          '31.77-35.19': (8, 'on'),
          '35.19-38.61': (9, 'off'),
          '38.61-42.71': (9, 'on'),
          '42.71-46.96': (10, 'off'),
          '46.96-60.00': (10, 'on')
        } %}

        {% set power = fan_power | float(default=0) %} {% set
        fan_ns=namespace(power='off', speed=-1, oscillate='off') %}

        {% for range, settings in fan_presets.items() %}
          {% set lower = range.split('-')[0] | float(default=-1) %}
          {% set upper = range.split('-')[1] | float(default=-1) %}
          {% if lower <= power < upper %}
            {% set fan_ns.speed = settings[0] %}
            {% set fan_ns.oscillate = settings[1] %}
          {% endif %}
        {% endfor %}

        {% if fan_ns.speed!=0 %}
          {% set fan_ns.power='on' %}
        {% endif %}

        {% set data={ 
          "power": fan_ns.power,
          "speed": fan_ns.speed,
          "oscillate": fan_ns.oscillate
        } %}

        {{data}}
  - service: python_script.set_state
    data:
      entity_id: input_select.living_room_dyson_io
      read_power: "{{ readings.power }}"
      read_speed: "{{ readings.speed }}"
      read_oscillate: "{{ readings.oscillate }}"
      reading_match_count: |-
        {% set status_match=(
          readings.power==state_attr('input_select.living_room_dyson_io','read_power') and
          readings.speed==state_attr('input_select.living_room_dyson_io','read_speed') and
          readings.oscillate==state_attr('input_select.living_room_dyson_io','read_oscillate')
        ) %}  {% if status_match %}
          {% set new_count=state_attr('input_select.living_room_dyson_io','reading_match_count')|int(default=0)+1 %}
        {% else %}
          {% set new_count=0 %}
        {% endif %}

        {{ min(match_count_threshold, new_count) }}
mode: single
icon: fapro:dyson-fan


{第四步} 建立以下自动化(以下仅供参考,不能直接使用,请替换对应的实体/配置)
定义的配置解释:
变量名 数值 解释
match_count_threshold 1 正常读取匹配次数要求
max_try_count 2 失败重发最大尝试次数
after_write_tolerance false 写后容忍开关,即才进行发送后多等待一轮匹配
tolerance_s 180 容忍时长(秒),不要太小了不然状态可能无法写回

要注意改的包括:
1) 功率获取方式,就我这里的"sensor.chuangmi_212a01_8866_electric_power"
2) 改所有helper的entity_id
3) [Deprecated] 改用于遥控和插座设备是否在线判断的entity_id

三组数据的IO逻辑:
[md]

假定状态

  1. 写入:
    • 由稳定的读取状态写入
    • 与步进发送信号完全同步,每发送一个指令对应更新假定状态

读取状态

  1. 写入:
    • 由获取到的实时功率写入
  2. 写出:(读数稳定且无操作时)
    • 写出到操作状态和假定状态中

操作状态

  1. 写入:
    • 由稳定读数写入
    • 用户操作写入
  2. 写出:
    • 用户操作写入后触发步进发送信号
alias: "[Device] Living Room - Dyson Tower Fan"
description: ""
trigger:
  - platform: state
    entity_id:
      - sensor.chuangmi_212a01_8866_electric_power
    id: POWER_READING
  - platform: state
    entity_id:
      - sensor.chuangmi_212a01_8866_electric_power
    id: STABLE_READING
    for:
      hours: 0
      minutes: 0
      seconds: 35
    not_to:
      - unavailable
      - unknown
      - None
  - platform: state
    entity_id:
      - input_boolean.dyson_oscillate
      - input_boolean.dyson_power
      - input_number.dyson_speed
    id: USER_OPERATE
  - platform: state
    entity_id:
      - input_select.living_room_dyson_io
    attribute: reading_match_count
    id: READING_MATCH_COUNT
condition:
  - condition: or
    conditions:
      - condition: and
        conditions:
          - condition: trigger
            id:
              - POWER_READING
              - STABLE_READING
          - condition: template
            value_template: |-
              {{ 
                states('script.dyson_send_command')!='on' and
                (now()|as_timestamp-state_attr('input_select.living_room_dyson_io','last_operation')|as_timestamp(default=0))&gt;2
              }}
      - condition: and
        conditions:
          - condition: trigger
            id:
              - USER_OPERATE
          - condition: template
            value_template: |-
              {{
                state_attr('input_select.living_room_dyson_io','last_write_back')|as_timestamp(default=0)!=0 and
                (now()|as_timestamp-state_attr('input_select.living_room_dyson_io','last_write_back')|as_timestamp(default=0))&gt;3
              }}
      - condition: trigger
        id:
          - READING_MATCH_COUNT
action:
  - variables:
      match_count_threshold: 1
      max_try_count: 2
      after_write_tolerance: false
      tolerance_s: 180
  - variables:
      extra_count: &gt;-
        {% set
        last_start=(now()|as_timestamp-state_attr('input_select.living_room_dyson_io','last_operation')|as_timestamp(default=0))
        %} {% set
        last_finish=(now()|as_timestamp-state_attr('script.dyson_send_command','last_triggered')|as_timestamp(default=0))
        %} {{ 1 if min(last_start, last_finish)&lt;tolerance_s and
        after_write_tolerance else 0 }}
      device_online: &gt;-
        {% set
        measure_online=states('sensor.chuangmi_212a01_8866_electric_power')|float(default=-1)!=-1
        %} {% set remote_online=states('remote.bo_lian_rm4c_mini') not in
        ['unavailable','unknown',None] %}

        {{ measure_online and remote_online }}
  - if:
      - condition: trigger
        id:
          - POWER_READING
    then:
      - service: python_script.set_state
        data:
          entity_id: input_select.living_room_dyson_io
          last_read: "{{ now() }}"
      - service: script.dyson_read
        data:
          fan_power: &gt;-
            {{
            states('sensor.chuangmi_212a01_8866_electric_power')|float(default=-1)
            }}
          match_count_threshold: "{{ match_count_threshold+extra_count }}"
  - if:
      - condition: trigger
        id:
          - USER_OPERATE
    then:
      - service: python_script.set_state
        data:
          entity_id: input_select.living_room_dyson_io
          state: set
          during_attempt: true
          last_operation: "{{ now() }}"
          reading_match_count: 0
          try_count: 0
          operate_power: "{{ states('input_boolean.dyson_power') }}"
          operate_speed: "{{ states('input_number.dyson_speed')|int(default=1) }}"
          operate_oscillate: "{{ states('input_boolean.dyson_oscillate') }}"
      - service: script.turn_on
        metadata: {}
        data: {}
        target:
          entity_id: script.dyson_send_command
  - if:
      - condition: trigger
        id:
          - READING_MATCH_COUNT
      - condition: template
        value_template: &gt;-
          {{state_attr('input_select.living_room_dyson_io','reading_match_count')|int(default=0)&gt;=(match_count_threshold+extra_count)}}
    then:
      - if:
          - condition: template
            value_template: &gt;-
              {{
              state_attr('input_select.living_room_dyson_io','read_power')=='on'
              }}
        then:
          - if:
              - condition: template
                value_template: |-
                  {{
                    (state_attr('input_select.living_room_dyson_io','operate_power')!=state_attr('input_select.living_room_dyson_io','read_power') or
                    state_attr('input_select.living_room_dyson_io','operate_speed')!=state_attr('input_select.living_room_dyson_io','read_speed') or
                    state_attr('input_select.living_room_dyson_io','operate_oscillate')!=state_attr('input_select.living_room_dyson_io','read_oscillate')) and
                    state_attr('input_select.living_room_dyson_io','try_count')|int(default=99)&lt;max_try_count and
                    state_attr('input_select.living_room_dyson_io','during_attempt')==true
                  }}
            then:
              - service: python_script.set_state
                data:
                  entity_id: input_select.living_room_dyson_io
                  state: set
                  last_operation: "{{ now() }}"
                  reading_match_count: 0
                  supposed_power: &gt;-
                    {{
                    state_attr('input_select.living_room_dyson_io','read_power')
                    }}
                  supposed_speed: &gt;-
                    {{
                    state_attr('input_select.living_room_dyson_io','read_speed')
                    }}
                  supposed_oscillate: &gt;-
                    {{
                    state_attr('input_select.living_room_dyson_io','read_oscillate')
                    }}
              - service: script.turn_on
                metadata: {}
                data: {}
                target:
                  entity_id: script.dyson_send_command
            else:
              - service: python_script.set_state
                data:
                  entity_id: input_select.living_room_dyson_io
                  state: read
                  during_attempt: false
                  last_write_back: "{{now()}}"
                  operate_power: &gt;-
                    {{
                    state_attr('input_select.living_room_dyson_io','read_power')
                    }}
                  operate_speed: &gt;-
                    {{
                    state_attr('input_select.living_room_dyson_io','read_speed')
                    }}
                  operate_oscillate: &gt;-
                    {{
                    state_attr('input_select.living_room_dyson_io','read_oscillate')
                    }}
                  supposed_power: &gt;-
                    {{
                    state_attr('input_select.living_room_dyson_io','read_power')
                    }}
                  supposed_speed: &gt;-
                    {{
                    state_attr('input_select.living_room_dyson_io','read_speed')
                    }}
                  supposed_oscillate: &gt;-
                    {{
                    state_attr('input_select.living_room_dyson_io','read_oscillate')
                    }}
              - delay:
                  hours: 0
                  minutes: 0
                  seconds: 0
                  milliseconds: 100
              - parallel:
                  - service: python_script.set_state
                    data:
                      entity_id: input_boolean.dyson_power
                      state: &gt;-
                        {{
                        state_attr('input_select.living_room_dyson_io','read_power')
                        }}
                  - service: python_script.set_state
                    data:
                      entity_id: input_number.dyson_speed
                      state: |-
                        {{
                          state_attr('input_select.living_room_dyson_io','read_speed')|float(default=1.0)
                        }}
                  - service: python_script.set_state
                    data:
                      entity_id: input_boolean.dyson_oscillate
                      state: &gt;-
                        {{
                        state_attr('input_select.living_room_dyson_io','read_oscillate')
                        }}
        else:
          - if:
              - condition: template
                value_template: |-
                  {{
                    state_attr('input_select.living_room_dyson_io','operate_power')!=state_attr('input_select.living_room_dyson_io','read_power') and
                    state_attr('input_select.living_room_dyson_io','try_count')|int(default=99)&lt;max_try_count and
                    state_attr('input_select.living_room_dyson_io','during_attempt')==true
                  }}
            then:
              - service: python_script.set_state
                data:
                  entity_id: input_select.living_room_dyson_io
                  state: set
                  last_operation: "{{ now() }}"
                  reading_match_count: 0
                  supposed_power: &gt;-
                    {{
                    state_attr('input_select.living_room_dyson_io','read_power')
                    }}
                  supposed_oscillate: &gt;-
                    {{
                    state_attr('input_select.living_room_dyson_io','read_oscillate')
                    }}
              - service: script.turn_on
                metadata: {}
                data: {}
                target:
                  entity_id: script.dyson_send_command
            else:
              - service: python_script.set_state
                data:
                  entity_id: input_select.living_room_dyson_io
                  state: read
                  during_attempt: false
                  last_write_back: "{{now()}}"
                  operate_power: &gt;-
                    {{
                    state_attr('input_select.living_room_dyson_io','read_power')
                    }}
                  operate_oscillate: &gt;-
                    {{
                    state_attr('input_select.living_room_dyson_io','read_oscillate')
                    }}
                  supposed_power: &gt;-
                    {{
                    state_attr('input_select.living_room_dyson_io','read_power')
                    }}
                  supposed_oscillate: &gt;-
                    {{
                    state_attr('input_select.living_room_dyson_io','read_oscillate')
                    }}
              - delay:
                  hours: 0
                  minutes: 0
                  seconds: 0
                  milliseconds: 100
              - service: python_script.set_state
                data:
                  entity_id: input_boolean.dyson_power
                  state: &gt;-
                    {{
                    state_attr('input_select.living_room_dyson_io','read_power')
                    }}
              - service: python_script.set_state
                data:
                  entity_id: input_boolean.dyson_oscillate
                  state: &gt;-
                    {{
                    state_attr('input_select.living_room_dyson_io','read_oscillate')
                    }}
mode: parallel
max: 3


最后补充个小细节,这个Dyson塔扇图标是我自己画的,我上传在这,请自取。
dyson-fan.zip (1.21 KB, 下载次数: 4)

用了这个插件可以上传自己的.svg矢量图标,具体安装和怎么用请参考Repo。



Home Assistant 效果图:
Screenshot 2024-06-03 225857.png Screenshot 2024-06-03 225804.png

HomeKit 效果图:

IMG_9120.PNG

游客,如果您要查看本帖隐藏内容请回复























评分

参与人数 2金钱 +17 收起 理由
隔壁的王叔叔 + 12 条条大路通罗马,感谢分享
kei81131 + 5 高手,这是高手!

查看全部评分

回复

使用道具 举报

0

主题

12

帖子

86

积分

注册会员

Rank: 2

积分
86
金钱
74
HASS币
0
发表于 2024-6-1 07:48:49 | 显示全部楼层
支持作者,
回复

使用道具 举报

24

主题

579

帖子

2679

积分

金牌会员

Rank: 6Rank: 6

积分
2679
金钱
2100
HASS币
0
发表于 2024-6-1 16:53:16 | 显示全部楼层
看上去比搞个板子还硬核
回复

使用道具 举报

4

主题

48

帖子

747

积分

高级会员

Rank: 4

积分
747
金钱
699
HASS币
0
 楼主| 发表于 2024-6-1 18:48:21 | 显示全部楼层
kjjuhfv 发表于 2024-6-1 16:53
看上去比搞个板子还硬核

没有哈哈,只是想讲清楚但是语言能力有限就搞成这样了
回复

使用道具 举报

1

主题

70

帖子

460

积分

中级会员

Rank: 3Rank: 3

积分
460
金钱
390
HASS币
0
发表于 2024-6-3 18:18:52 | 显示全部楼层
太有耐心了,一点一点测试,不过估计大多数人都像我一样“卧槽这么复杂,我还是塞进去个板子吧”
回复

使用道具 举报

19

主题

187

帖子

1198

积分

金牌会员

Rank: 6Rank: 6

积分
1198
金钱
1011
HASS币
0
发表于 2024-6-3 20:58:36 | 显示全部楼层
一模一样的方案。。用的小米的wifi插座和小爱同学,但是更新有点慢还是差点意思,感觉还能优化下,不过大佬牛逼多了,我是思路一样,但是用nodered处理流,用开关来表示档位。。。。
回复

使用道具 举报

4

主题

48

帖子

747

积分

高级会员

Rank: 4

积分
747
金钱
699
HASS币
0
 楼主| 发表于 2024-6-3 23:16:40 | 显示全部楼层
yikliu 发表于 2024-6-3 20:58
一模一样的方案。。用的小米的wifi插座和小爱同学,但是更新有点慢还是差点意思,感觉还能优化下,不过大佬 ...

稍微修了下,现在速度很快,而且我那个博联rm4c mini处理也没有我最开始想象中的漏收漏发情况,从1-10档三四秒就搞定了,根本不需要重试hh。
顺便我把我用的图标也传上来了,你可以看下。
回复

使用道具 举报

5

主题

79

帖子

870

积分

高级会员

Rank: 4

积分
870
金钱
791
HASS币
0
发表于 2024-6-4 09:12:25 | 显示全部楼层
有点意思,感谢楼主分享思路
回复

使用道具 举报

4

主题

48

帖子

747

积分

高级会员

Rank: 4

积分
747
金钱
699
HASS币
0
 楼主| 发表于 2024-6-4 13:14:20 | 显示全部楼层
scibs 发表于 2024-6-4 10:04
我觉得在nodered里写流程再自动发现至ha,这样更方便

没有实质区别,你想怎么打包都可以,我提供的是控制和反馈的思路
回复

使用道具 举报

0

主题

21

帖子

98

积分

注册会员

Rank: 2

积分
98
金钱
77
HASS币
0
发表于 2024-6-4 23:32:21 | 显示全部楼层
楼主厉害,学习学习。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Hassbian

GMT+8, 2024-11-21 21:29 , Processed in 2.160137 second(s), 36 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表