basnijholt / adaptive-lighting

Adaptive Lighting custom component for Home Assistant
https://basnijholt.github.io/adaptive-lighting/
Apache License 2.0
1.97k stars 141 forks source link

Possible for AL to update the color of a Hue Scene? #271

Open GollyJer opened 2 years ago

GollyJer commented 2 years ago

Hi, I have a full Philips Hue setup with Lutron Aurora switches and Hue motion detector "switches". Home Assistant doesn't work great for controlling the lights with these switches.

It is also jarring to mix AL with Hue controlled switches because they come on at whatever their last setting was and then AL eventually updates the light.

I've been trying to think of workarounds that would allow the use of Hue Hub as the hardware controller but immediately turn on the lights to the current AL level.

The only idea I currently have leads to this question...

Is possible to have AL update the settings of a Hue scene at the same rate it updates the lights? This way all the switches and motion detectors could set their "when turned on" to the scene being updated with AL.

gderber commented 2 years ago

While I'd love it if the integration could do it natively, I am not sure how.

It is currently possible to do this from Home Assistant. I thought about simply linking a How-to I quickly wrote in my configuration file, but decided that link could change so I am re-posting here.

You can find my configuration at: https://github.com/hearthminion/homeassistant_config

This is only in the development branch, under packages/lighting/

Eventually the development branch will merge into the main branch, and the development branch will be eliminated.

How to Update HomeAssistant Scene on Hue Bridge.

Note I configured my lighting setup and automations entirely in yaml.

Variables

hue_bridge: IP address or Hostname for Hue bridge, eg '192.168.92.5' or 'hue.example.com'

hue_application_key

The hue application key used for authentication to the bridge.

You can find this in your home-assistant config inside the storage directory. eg: /srv/homeassistant/config/.storage/ The file to read through is core.config_entries. You are looking for a section that looks like:

{
  "entry_id": "0123456789abcd",
  "version": 1,
  "domain": "hue",
  "title": "Hue Bridge",
  "data": {
    "host": "{{ hue_bridge }}",
    "api_key": "{{ hue_application_key }}",
    "api_version": 2
  },
...
}

The line with api_key is your hue_application_key.

In this example the key is stored as a secret in secrets.yaml as 'hue_username'

Create HomeAssistant Scene on Hue Bridge.

Use the Hue App. Create a scene to be managed by Home Assistant. I personally named mine 'HomeAssistant'.

Identify Scenes and Light bulbs

curl --insecure -H 'hue-application-key: {{ hue_application_key }} ' -X GET 'https://{{ hue_bridge }}/clip/v2/resource/scene' | jq > scenes.json

Will save your scenes to scenes.json

Identify Lights

curl --insecure -H 'hue-application-key: {{ hue_application_key }} ' -X GET 'https://{{ hue_bridge }}/clip/v2/resource/light' | jq > lights.json

Will save your lights to lights.json

Note: you do not really need the lights.json file. It is useful for verifying the light you have selected in your scene is the correct one.

Edit your Home Assistant Configuration

Create rest_command integration

rest_command:
  light_update_den_scene:
    url: "https://{{ hue_bridge }}/clip/v2/resource/scene/{{ scene_id }}"
    method: put
    headers:
      hue-application-key: "{{ username }}"
    payload: '{
          "id":"{{ scene_id }}",
          "actions":[
          {
          "action":{ {{ color }},{{ brightness }},{{ on_state }} },
          "target":{"rid": "02186fdb-4ea0-440a-80ad-c0d9adc69527","rtype":"light"}
          },
          {
          "action":{ {{ color }},{{ brightness }},{{ on_state }} },
          "target":{"rid": "f8aca0e4-1a6c-4cac-9d08-ecf09cbdf5d6","rtype":"light"}
          },
          {
          "action":{ {{ color }},{{ brightness }},{{ on_state }} },
          "target":{"rid": "4294ad46-44e2-4df9-974e-d28c65fb308a","rtype":"light"}
      }
      ]
     }'
    verify_ssl: false
   content_type: "application/json"

Each light bulb in the scene will require an action. The rid you will get from scenes.json, by looking for the light bulb associated with the scene to be updated.

Create script to call the rest commands.

I did this because I have one scene per light fixture, and one scene per room to be edited. This means there are over 30+ scenes in my configuration to be modified every time the script is run. To prevent the hue hub from being overwhelmed with requests all at once, I use a script that runs the rest command sequentially with 1 second between each call.

In addition, by using a script, I can send variables to the rest command to make the rest command more versatile, for updating in other scenarios.

script:
  light_update_scene_homeassistant:
    alias: "[Light] Update Home Assistant Scenes"
    mode: single
    sequence:

      - service: rest_command.light_update_den_scene
        data:
          scene_id: "0fad44f3-9093-4f05-86e9-4aeb8467b4fc"
          username: !secret hue_username
          color: '"color_temperature":{ "mirek":{{ states("sensor.global_dummy_light_color_temperature") | int(367) }} }'
          brightness: '"dimming":{ "brightness": {{ states("sensor.global_dummy_light_brightness") | int(100) }} }'
          on_state: '"on":{"on":true}'

      - alias: "Wait 1s"
        delay: 1

      - service: rest_command.light_update_den_scene
        data:
          scene_id: "a77ec553-6f7f-4187-a42b-fac3e50c3e33"
          username: !secret hue_username
          color: '"color_temperature":{ "mirek":{{ states("sensor.global_dummy_light_color_temperature") | int(367) }} }'
          brightness: '"dimming":{ "brightness": {{ states("sensor.global_dummy_light_brightness") | int(100) }} }'
          on_state: '"on":{"on":true}'

      - alias: "Wait 1s"
        delay: 1

...

You'll get the scene_id from scenes.json. Look through the file to identify the scene_id for the scene you wish Home Assistant to update.

Create Global Adaptive Lighting Entity

This entity is always on. I created this because if the entities are switched off, their attributes are not available for scripting. I wanted an entity that was guaranteed to always be on.

adaptive_lighting:
  - name: "Global: Dummy Light"
    initial_transition: 1
    min_color_temp: 2000
    max_color_temp: 6500

Create template sensors

This may be redundant, You can theoretically use the state attributes directly in the above script.

template:
  - sensor:
      - unique_id: "0639ee4e-55ff-41af-a903-ff6db2660b1e"
        name: "Global Dummy Light Brightness"
        state: >-
          {% if state_attr("switch.adaptive_lighting_global_dummy_light", "brightness_pct") == None or
          is_state_attr("switch.adaptive_lighting_global_dummy_light", "brightness_pct", "unknown") or
          is_state_attr("switch.adaptive_lighting_global_dummy_light", "brightness_pct", "off") %}
            100
          {% else %}
            {{ state_attr("switch.adaptive_lighting_global_dummy_light", "brightness_pct") | int(100) }}
          {% endif %}
        unit_of_measurement: "%"

      - unique_id: "0e8a672a-9db0-40bd-9727-d0b206802b80"
        name: "Global Dummy Light Color Temperature"
        state: >-
          {% if state_attr("switch.adaptive_lighting_global_dummy_light", "color_temp_mired") == None or
          is_state_attr("switch.adaptive_lighting_global_dummy_light", "color_temp_mired", "unknown") or
          is_state_attr("switch.adaptive_lighting_global_dummy_light", "color_temp_mired", "off") %}
              367
          {% else %}
            {{ state_attr("switch.adaptive_lighting_global_dummy_light", "color_temp_mired") | int(367) }}
          {% endif %}
        state_class: measurement

In this case I manually set the unique_id using uuidgen -r, this is not required. Some of this code may be redundant.

Create automation to run the update script

  - id: "b9267e40-af1c-4f92-bb98-e6839787cc97"
    alias: "[Light] Update HomeAssistant Scene on Hue Bridges (Circadian)"
    description: ""
    initial_state: false
    trigger:
      - platform: time_pattern
        minutes: "/5"
    condition: []
    action:
      - service: script.turn_on
        data: {}
        target:
          entity_id: script.light_update_scene_homeassistant
    mode: single

Hope this helps. There is probably a more efficient way of doing this. This is still a heavy work in progress for me.

[edit] Add automation example

th3w1zard1 commented 1 year ago

As a new contributor here I'd love to help implement this, but unfortunately I still don't understand the problem. Adaptive-lighting is natively designed to adapt any lights that are going off -> on, and only with take_over_control: true will it stop adapting after the next light.turn_on

This issue is a duplicate of all the ones posted here on the v2 roadmap: https://github.com/basnijholt/adaptive-lighting/discussions/291#discussioncomment-2886261

Is it not possible with hue scenes to call light.turn_on twice? Once to turn the lights on, and again to set it to whatever scene you want? I apologize if I'm misunderstanding the problem.

th3w1zard1 commented 1 year ago

@GollyJer

gderber commented 1 year ago

As I said in my post above, I don't think this is possible with adaptive lighting.

For Adaptive Lighting to be able to do this, it would need to know Hue's internal UUID for every bulb and every scene. In addition it would need to know which bulbs belong to each scene.

What I provided above is a way that someone can update their scenes using information from adaptive lighting, and other Home Assistant components.

th3w1zard1 commented 1 year ago

@gderber at the very least, adaptive-lighting should be able to fire a manually controlled event when a hue scene is fired. I'd very much like to know if that manual control is being fired correctly before closing this issue.

The bulb's state (on/off, color, brightness, rgb info) is updated in Home Assistant regardless of what hue is doing with its UUID's or whatever.

EDIT: It sounds like OP is expecting the bulb to adapt when a hue scene changes? I'm confused why that's a desired feature. Usually if you set a scene you don't want anything changing it.

basnijholt commented 1 year ago

I am implementing an option adapt_only_on_bare_turn_on which instantly triggers manual_control when turning on with brightness or color in PR https://github.com/basnijholt/adaptive-lighting/pull/709.

Enabling this will make sure AL doesn't take over when setting a Home Assistant scene. However, I believe there is no way to detect whether a Hue scene has been set?

Where do you set this scene? From HA or from the Hue app?

gderber commented 1 year ago

@basnijholt

The process is a real pain.

  1. I had to create the scene in the hue app.

  2. I had went to my home assistant config/.storage folder, and opened core.config_entries to get the hue application key.

  3. From there, I had to grab the scene Id by using a direct API call to download all light and scene definitions.

    curl -H hue-application-key: "{{ hue_application_key }}" https://{{ hue_hub_ip_address }}/clip/v2/resource/lights > lights.json
    curl -H hue-application-key: "{{ hue_application_key }}" https://{{ hue_hub_ip_address }}/clip/v2/resource/scene > scenes.json
  4. Then I went though the output line by line to identify the correct scene id for each scene that I wanted Home Assistant to update.

  5. I then created a home assistant rest_command for each scene with scene and light ids, and used a variable for the color temperature.

  6. I then created a Home Assistant script to call the rest_commands setting the color_temp variable to the color_temp specified by adaptive lighting.

  7. Finally I created an automation to run that script every 5 minutes.

More detailed process is above. https://github.com/basnijholt/adaptive-lighting/issues/271#issuecomment-1080961638

The only way I can see AL doing this, is if AL can somehow get the scene ids and light ids from the home assistant .storage/* files.

I've actually reached the point where I now use ansible to keep track of light and scene ids, and use it to update various input_text entities.

Bottom line, it might be possible for AL to update the hue scenes automatically. I expect it will be very difficult to do so.

As far as detecting when a hue scene has been activated, maybe there is a way, but so far the only one I can think of is to create a binary sensor that turns "on" when the light color temp and brightness match the desired scene definition. Watching 'hue_event' under HA Dev Tools doesn't produce anything when a scene is activated from Hue.

I think the best thing to do for this, is to provide a "Howto" guide in the AL documenation (use my comment from above as a template).

basnijholt commented 1 year ago

@gderber, wow! That is a truly awful workaround 😅

I will leave this issue open but I don't think I will get to this anytime soon.

gderber commented 1 year ago

@basnijholt It really is.

The hard part is in identifying the correct scene_ids and the light_ids associated with that scene to update. If you can find a way to get adaptive lighting to do that, the scene_ids and light_ids are available in core.entity_registry (But the scenes do not show what light_ids are associated with it), the rest I would expect to be easy. It's an API call setting the light color_temp for the specified scene.

gderber commented 1 year ago

@basnijholt A better idea might be for the ability to modify scenes added to Home Assistant itself. I'd expect that it'd probably be easier for them to track which light ids are associated with each scene.

That'd have the added benefit of allowing people to modify scenes to states that aren't dependent on AL. Then AL could simply "piggy back" off the upstream solution for this.

basnijholt commented 1 year ago

What is special about Hue scenes BTW? Why not use HA scenes?

GollyJer commented 1 year ago

For me, it would be an easier way to manage switches and motion detectors in Hue. Like, right now I don't know how to get my motion detector-controlled lights, controlled via Hue but visible in HA, to use AL. If AL was updating the scene the motion detector uses when the light comes on it would be pretty cool. Same for the Lutron Aurora switches.

It also allows for a form of redundancy. If HA goes down but everything is still connected to Hue, we can still control things from the Hue app.

gderber commented 1 year ago

The same for me.

I use hue switches, lutron Aurora switches, and eventually I plan on adding hue motion sensors, for turning on and off my lights. I absolutely hate the idea of getting my phone out for turning on the lights. I don't even like using the hue app for that. Also, for anyone else in the house, using an hue switch isn't much of a change from what they would do normally to turn on a light. I don't need to teach them how to use HA, or install the hue app on their phone (visitors).

Trying to use switches in the hue ecosystem for turning on and off lights to reduce a potential point of failure. I don't want to not be able to turn on the lights because home assistant crashed. I try to configure everything "smart" home related considering "what could go wrong?" And doing as much as I can to mitigate those problems.

So by updating the hue scene I can get the best of both worlds. I can use hue to turn on the lights, and because the scene is updated regularly, it comes on the the correct color temp and brightness based on AL status. And if/when HA crashes, I simply lose AL.

basnijholt commented 1 year ago

OK I see, thanks for explaining 😄

I imagine this is kind of an edge-case.

For me it is hard to write functionality for this because I do not have a Hue hub set up to test.

I will happily accept a well written PR though.

BenoitAnastay commented 8 months ago

I wrote this for another integration, I do use an old hue API and havent updated since APIv2 update but it keep working the intended way.

Maybe we can write something similar for this integration, I would like to switch to your integration but hue scenes following the adaptative lighting value is a must have for me since I toggle my lights to a scene from my wall switches

https://github.com/claytonjn/hass-circadian_lighting/pull/195/files

basnijholt commented 8 months ago

[Copy pasting this message in a few recent open issues]

I just wanted to take a moment to express my heartfelt thanks to everyone that is active in this repo. Your contributions, from answering questions to addressing issues, have been invaluable. It's amazing to see how supportive and helpful our community is!

Adaptive Lighting is all about enhancing your living spaces with smart, sunlight-responsive lighting. We've had quite a few discussions and open issues recently, and I see this as a positive sign of our community's engagement and growth. If you come across anything in the documentation that's unclear or if you have suggestions for improvement, please don't hesitate to share!. Your feedback is crucial for making Adaptive Lighting better for everyone.

On a personal note, I've recently welcomed twin boys into my family, which has been an incredible and life-changing experience. As you can imagine, my time is now more limited, and while I'm doing my best to keep up with the project, there may be delays in my responses. I appreciate your understanding and patience during this time.

Rest assured, I'm fully committed to addressing any bugs, especially those related to new Home Assistant updates, as swiftly as possible. I understand that many issues may stem from hardware limitations or misunderstandings about things like Zigbee groups. Your continued support and collaboration in helping each other out not only strengthen our community but also enhance the Adaptive Lighting experience for all.

Thank you once again for your understanding, patience, and support. Let's keep our houses well lit and adaptive for maximal enjoyment of life! 🌞🏠🌙