Sympapaのスマートホーム日記

スマートなんとかはスマートじゃない方法でつくられている

Home Assistant: 照度センサーで照明の電源状態を同期させる

Sympapaです。

我が家のキッチンとリビングの照明はどちらも赤外線リモコンの付いたシーリング照明です。
これらの照明をオンオフする手段として主に使用しているのは、1)照明付属のリモコンで操作、2)Google Homeで音声操作、3)物理ボタンリモートスイッチで操作(Home Assistantによる)、4)家のコントロールパネルで操作(Home Assistantによる)、5)人感センサーによる操作(Home Assistantによる)です。
これらをシステム的に見ると、1)照明付属のリモコンからオンオフする、2)Google Homeからオンオフする、3)Home Assistantからオンオフする、の3つの経路があります。


そして、Google HomeやHome Assistantから照明をオンオフするためにスマートIRリモコン: Nature Remoを使用しています。
Home AssisatantのLightエンティティを使用し、Home AssistantからローカルAPIでNature RemoへIR信号を飛ばす指示を出して照明をコントロールしているのですが、素晴しいことにHome AssisatantのLightエンティティはGoogle Homeに「照明」として登録できる(照明デバイスとして認識される)ので、この時点でGoogle Home上の照明オンオフ状態とHome Assistant上の照明オンオフ状態は同期してくれます。
しかし照明付属のリモコンからオンオフした場合は当たり前だけど同期できません。
図に書くとこんな風になってます。
f:id:sympapa:20220219084439p:plain


Home AssistantのフロントエンドUIを使った家のコントロールパネル上にも照明のスイッチがあり、照明がオンの時にアイコンの色が赤色に変わるようにしているのですが、前述のとおり照明付属のリモコンからオンオフした場合にはHome Assistantに照明のオンオフ状態が同期されないのでアイコンの色も同期されません。


今回は、照度センサーを使ってシーリング照明の電源オンオフ状態を取得することで、照明付属のリモコンからオンオフした場合にもHome Assistantと同期されるようにしたいと思います。

■使用する照度センサー

今回使用する照度センサーはXiaomiのlight sensor GZCGQ01LMです。
今回は照明のオンオフを照度で検出しHome Assistantと同期させるので、照度の変化を素早くレポートしてくれる照度センサーを使用する必要があります。
しかし、多くの照度センサーの照度のレポート間隔は分単位だったりするため照度センサーの選定には注意が必要です。
Xiaomiのlight sensor GZCGQ01LMの照度のレポート頻度は照度の変化があまり無い時には30秒間隔ですが、照度が大幅に変化した時は5秒間隔でレポートしてくれます。但し、照度が大幅に変化した時も実際にはその次の次か更にその次のレポートに結果が反映される感じなので、実際には5秒~15秒のタイムラグがあると考えておいた方が良さそうですが、まぁ許容範囲だろうということでこれを選びました。
このあたりの詳細は、前回のXiaomiのlight sensor GZCGQ01LMのレビューを参照ください。
sympapa.hatenablog.com

■とりあえず今回のゴール

今回のゴールは以下のとおりです。

  • 照明付属のリモコンから操作した時も照明のオンオフがHome Assistantと同期されるようにする。
  • Home AssistantやGoogle Homeからの操作ではNature RemoからIR信号を発射する必要があるが、照明付属のリモコンから操作して照明のオンオフがHome Assistantと同期された場合はNature RemoからIR信号を発射しないようにする。
  • 家のコントロールパネル上の照明の電源ボタンに表示されたアイコンの色は、どの操作方法でオンオフしてもオンの時には赤色、オフの時には黒色に変わるようにする。
  • 家のコントロールパネル上の電源ボタンを押して照明をオンオフした場合は、アイコンの色が即変わるようにする。(従来と同じ挙動)
  • その他、Google HomeおよびHome Assistantから照明がオンオフされた場合も、家のコントロールパネル上のアイコンの色が即変わるようにする。(従来と同じ挙動)

■シーリング照明に照度センサーをくっつける

まずはシーリング照明に照度センサーを仕込みます。
周囲が明るい時でも暗い時でも、照明がオンの時とオフの時を照度で線引き出来なくてはいけないので、極力、周囲の明るさの影響を受けずに照明の明るさを拾えそうな位置に設置しました。
とりあえずこんな感じで貼り付けて照度をみながら調整することにしましたが、どうにもならなければ周囲の照度の影響を受けないようにカバーを作らなくてはいけませんね。

■Home Assisatantで同期させる

Home AssistantやGoogle Homeからの操作ではNature RemoからIR信号を発射する必要がありますが、照明付属のリモコンから操作して照明のオンオフがHome Assistantと同期された場合はNature RemoからIR信号を発射しないようにしたいので、そこをどうするか悩みました。
考えた結果、以前から使用しているlightはそのままにしておき、新たに照明のオンオフ状態を保持するためだけのダミースイッチを作ることにしました。
lightがオンオフされた場合はNature Remoから照明をオンオフするIR信号が発射されますが、更にダミースイッチをオンオフするようにします。
照度センサーの照度によって照明のオンオフを検出した場合には、IR信号が発射しないよう直接ダミースイッチをオンオフさせます。
家のコントロールパネル上の照明のボタンは、表示はダミースイッチの状態とし、押した時のアクションはlightをオンオフするようにします。
図に書くとこんな感じです。
f:id:sympapa:20220219173155p:plain

1.ダミースイッチを作る
configuration.yaml上でダミースイッチ"switch.light_kitchen_for_display"を作ります。
"light.light_kitchen"は以前から使っていたlightでオンオフによりrest_commandでNature Remoに赤外線信号を発射させるコマンドを送ります。

input_boolean:
  light_kitchen:
    name: light_kitchen
  light_kitchen_for_display:
    name: light_kitchen_for_display

light:
  - platform: template
    lights:
      light_kitchen:
        value_template: "{{ states('input_boolean.light_kitchen') }}"
        turn_on:
          - service: input_boolean.turn_on
            entity_id: input_boolean.light_kitchen
          - service: rest_command.light_kitchen_on
        turn_off:
          - service: input_boolean.turn_off
            entity_id: input_boolean.light_kitchen
          - service: rest_command.light_kitchen_off

switch:
  - platform: template
    switches:
        light_kitchen_for_display:
        value_template: "{{ states('input_boolean.light_kitchen_for_display') }}"
        turn_on:
          - service: input_boolean.turn_on
            entity_id: input_boolean.light_kitchen_for_display
        turn_off:
          - service: input_boolean.turn_off
 
rest_command:
  light_kitchen_on:
    url: 'http://192.168.11.x/messages' ←Nature RemoのIPアドレス
    method: POST
    headers:
      Accept: 'application/json'
      Content-Type: 'application/json'
      X-Requested-With: 'curl'
      Expect: ''
    payload: '{"format":"us","freq":38,"data":[3117,1571,334,(略),336]}'

  light_kitchen_off:
    url: 'http://192.168.11.x/messages' ←Nature RemoのIPアドレス
    method: POST
    headers:
      Accept: 'application/json'
      Content-Type: 'application/json'
      X-Requested-With: 'curl'
      Expect: ''
    payload: '{"format":"us","freq":38,"data":[3118,1556,326,(略),316]}'



2.照度センサーの照度変化によってダミースイッチをオンオフするオートメーションを作る
照度が1001以上になったらダミースイッチ"switch.light_kitchen_for_display"をオンにし、1000以下になったらオフにするオートメーションを作ります。

alias: light_kitchen_get_power_status_by_light_sensor
description: ''
trigger:
  - type: illuminance
    platform: device
    device_id: 照度センサーのデバイスID
    entity_id: sensor.xiaomi_light_sensor_3_illuminance_lux
    domain: sensor
    above: 1001
    for:
      hours: 0
      minutes: 0
      seconds: 1
  - type: illuminance
    platform: device
    device_id: 照度センサーのデバイスID
    entity_id: sensor.xiaomi_light_sensor_3_illuminance_lux
    domain: sensor
    below: 1000
    for:
      hours: 0
      minutes: 0
      seconds: 1
condition: []
action:
  - choose:
      - conditions:
          - type: is_illuminance
            condition: device
            device_id: 照度センサーのデバイスID
            entity_id: sensor.xiaomi_light_sensor_3_illuminance_lux
            domain: sensor
            above: 1001
        sequence:
          - service: switch.turn_on
            data: {}
            target:
              entity_id:
                - switch.light_kitchen_for_display
      - conditions:
          - type: is_illuminance
            condition: device
            device_id: 照度センサーのデバイスID
            entity_id: sensor.xiaomi_light_sensor_3_illuminance_lux
            domain: sensor
            below: 1000
        sequence:
          - service: switch.turn_off
            target:
              entity_id:
                - switch.light_kitchen_for_display
            data: {}
    default: []
mode: single



3.lightがオンオフされたらダミースイッチをオンオフするオートメーションを作る
lightと連動させるだけなのでオートメーションじゃなくてもいいんですが、configuration.yamlに書くのが面倒だったので手抜きです(笑)
照度センサーのタイムラグによる不整合を考慮し、その20秒後に照度センサーからの照度に合わせてダミースイッチをオンオフし整合するようにします。

alias: light_kitchen_change_power_status_by_switch_entity
description: ''
trigger:
  - platform: state
    entity_id: light.light_kitchen
condition: []
action:
  - choose:
      - conditions:
          - condition: state
            entity_id: light.light_kitchen
            state: 'on'
        sequence:
          - service: switch.turn_on
            data: {}
            target:
              entity_id:
                - switch.light_kitchen_for_display
      - conditions:
          - condition: state
            entity_id: light.light_kitchen
            state: 'off'
        sequence:
          - service: switch.turn_off
            target:
              entity_id:
                - switch.light_kitchen_for_display
            data: {}
    default: []
  - delay:
      hours: 0
      minutes: 0
      seconds: 20
      milliseconds: 0
  - choose:
      - conditions:
          - type: is_illuminance
            condition: device
            device_id: 照度センサーのデバイスID
            entity_id: sensor.xiaomi_light_sensor_3_illuminance_lux
            domain: sensor
            above: 1001
          - condition: state
            entity_id: switch.light_kitchen_for_display
            state: 'off'
        sequence:
          - service: switch.turn_on
            data: {}
            target:
              entity_id: switch.light_kitchen_for_display
      - conditions:
          - type: is_illuminance
            condition: device
            device_id: 照度センサーのデバイスID
            entity_id: sensor.xiaomi_light_sensor_3_illuminance_lux
            domain: sensor
            below: 1000
          - condition: state
            entity_id: switch.light_living_for_display
            state: 'on'
        sequence:
          - service: switch.turn_off
            data: {}
            target:
              entity_id: switch.light_kitchen_for_display
    default: []
mode: restart



4.家のコントロールパネルのボタンに割り当てるスクリプトを作る
家のコントロールパネル上のボタンを押した時に発動させるスクリプトです。
ダミースイッチがオフの時にはlightをオンにし、ダミースイッチがオンの時にはlightをオフにします。

alias: light_kitchen_switch_for_button
sequence:
  - choose:
      - conditions:
          - condition: state
            entity_id: switch.light_kitchen_for_display
            state: 'off'
        sequence:
          - service: light.turn_on
            data: {}
            target:
              entity_id: light.light_kitchen
          - service: switch.turn_on
            data: {}
            target:
              entity_id:
                - switch.light_kitchen_for_display
      - conditions:
          - condition: state
            entity_id: switch.light_kitchen_for_display
            state: 'on'
        sequence:
          - service: light.turn_off
            data: {}
            target:
              entity_id: light.light_kitchen
          - service: switch.turn_off
            data: {}
            target:
              entity_id:
                - switch.light_kitchen_for_display
    default: []  
mode: restart



5.家のコントロールパネルの設定
ボタンカードを設置しますが、エンティティにはダミースイッチ"switch.light_kitchen_for_display"を割り当てます。
タップ時のアクションには「サービスの呼び出し」で4.で作成したスクリプトを割り当てます。

■まとめ

これで照明の付属リモコンで操作してもHome Assistantに同期されるようになりました。最大15秒くらいのタイムラグがありますがまぁ同時させること自体は家族も99%気づかない自己満足の世界ですし十分許容範囲でしょう。
テレビも照明もオンオフ状態を同期できるようになったのであとはエアコンですね。エアコンはオンオフ同期方法はアイディアがありますが、そもそも運転モードや設定温度が同期できないとあまり意味がないのでちょっとビミョーですね。

それでは。