Python_script to save and restore switches and lights

I also have Z-Wave devices but none are lights :frowning: I’m using Phillips Hue lights and was hoping this would be the magic bullet to restore their previous state during restarts (or a reboot due to power outage.)

Appreciate the feedback though!

Just a follow-up in case someone with Hue lights wanted to achieve what I was looking to do here, the persistence script/package from @dale3h worked for me. The lights don’t go off when I restart HA - this is a different use-case than what @pnbruckner is doing just so nobody confuses it.

Can you provide a link to a post or something that explains what you’re referring to, in case someone else has the same issue as you and would want to know what you did?

What I was trying to accomplish was that a light’s state would be saved between restarts/reboots. In the case of your z-wave lights, this seems implied whereas with my Hue lights, this didn’t happen. Further investigation showed that it was actually an automation I had which checks if anyone is home, if not, turn them off. Since HA starts with this data being unknown, the lights were being turned off during restart. The structures I use to hold this data is input_select which the script below will save which allows me to have the lights turn off when nobody is home but still keep the light state. I ended up adding the lights themselves to it as well:

EDIT: MQTT is required

2 Likes

For anyone curious this is how I got it working dynamically so I could use the same script in many automations

Automation:

- alias: 'Rainy Day'
  trigger:
    - platform: state
      entity_id: sensor.dark_sky_precip
      to: 'rain'
    - platform: state
      entity_id: sensor.dark_sky_precip
      to: 'sleet'
    - platform: state
      entity_id: sensor.dark_sky_precip
      to: 'snow'
  condition:
    - condition: state
      entity_id: input_boolean.shane_present
      state: 'on'
    - condition: time
      after: '07:00:00'
      before: '23:00:00'
  action:
    - service: script.save_lights
      data:
        store_name: 'rain_store'
        entity_ids: 'light.er_living_room, light.er_master_bedroom, light.er_spare_bedroom, light.spare_bedroom_closet, light.spare_bathroom, light.mast_bedroom_closet'
    - service: scene.turn_on
      entity_id: scene.rainy_day

Script:

save_lights:
  alias: Save light state
  sequence:
    - service: python_script.light_store
      data_template:
        store_name: "{{ store_name }}"
        entity_id: "{{ entity_ids }}"

restore_lights:
  alias: Restore light state
  sequence:
    - service: python_script.light_store
      data_template:
        store_name: "{{ store_name }}"
        operation: restore
2 Likes

Great work! Works superb for me. I only hope to have it built-in in hass. ) thank you @pnbruckner
4

1 Like

Script updated to handle more than one type of color attribute. If a light has a white_value attribute save and restore that. If not but it has a color_temp attribute, save and restore that. If it doesn’t have either of those but has hs_color, then save and restore that.

Note that when turning on a light, if profile, color_name, rgb_color or xy_color are used, they will get converted to hs_color and that is what will be used. And when the state of the light is updated, although only hs_color is used internally, in addition to hs_color the light component will also add equivalent rgb_color and xy_color attributes to the light.

For color temperature, if kelvin is used when turning on a light it will get converted to color_temp, which is what will be added as an attribute.

The method of choosing which attribute to save and restore was based on the above, as well as the fact that some light platforms seem to support both hs_color and color_temp, although they don’t report the correct hs_color. Note that color_temp can always be converted to an equivalent hs_color, but the reverse is not true (since color temperature is a small subset of all colors.)

The script works great!
I can’t restore colors to my yeelight, but I think this is not an script issue, but something with yeelight. I can change the order:

# Save only one of these attributes, in order of precedence.
COLOR_ATTRS = [ATTR_WHITE_VALUE, ATTR_COLOR_TEMP, ATTR_HS_COLOR]

to

# Save only one of these attributes, in order of precedence.
COLOR_ATTRS = [ATTR_WHITE_VALUE, ATTR_HS_COLOR, ATTR_COLOR_TEMP]

and ATTR_HS_COLOR is saved instead of the ATTR_COLOR_TEMP
But it is not restored. I will investigate…
I am also not able to send any color settings to my yeelights using the developer tools and call service, so this is something different. Thank you for linking to this article.

1 Like

FYI, I’m planning to make this script installable/updateable via custom_updater. That custom component was designed for custom cards and custom components, but I think it will work with python_scripts, too. :slight_smile:

1 Like

I changed it a little bit to store xy_color but not hs_color, because it works better with xy_color on my yeelight lamps:

# hs_color issues on yeelight, trying xy_color, works better:
ATTR_XY_COLOR = 'xy_color'
# Save only one of these attributes, in order of precedence.
# Original:
# COLOR_ATTRS = [ATTR_WHITE_VALUE, ATTR_COLOR_TEMP, ATTR_HS_COLOR]
# Germo: this works on yeelight:
COLOR_ATTRS = [ATTR_WHITE_VALUE, ATTR_XY_COLOR, ATTR_HS_COLOR, ATTR_COLOR_TEMP]

But there are still some issues:
sometimes not the right color is saved, sometimes the off state is saved but not restored,
The script looks right (the implemented logic), but it looks like there is a cache and sometimes data to be saved is not from the real current state but something different, a little bit older.
And the off state saved but sometimes is not restored. The logic is clear and it should work. it also looks like it needs to be to exist a little bit longer. If I restore to fast then nothing is restored. Maybe this the way how the State Machine is working?

For now I tested it on one light, but nearly all my lights are in light groups. Why you wrote this will not work as required?

Don’t know what to tell you. When you call light.turn_on with xy_color, the light component converts that to hs_color, which is what is used to actually turn on the light. You can see that here. And when a light’s state is written to the state machine, the hs_color is converted to xy_color and rgb_color, and all three are show as attributes. You can see that here. So I don’t see any reason why having the script save & restore xy_color instead of hs_color should work any better.

If your light is not showing it’s state correctly, and/or is not responding properly to the light.turn_on service, you should probably figure out why. This script is just using those standard features and expects them to work.

I’m not following what you’re trying to say here. Could you clarify?

I think you are right, the issue is not with hs or xy color. I will change back to your default.

I think the issue could be related to the fact, that I use Aqara switches and cubes in the Mi app for automation and that sometimes there could be a delay when hass.io knows the states. Automation in my Mi app are older then my hass.io installation, which now has an age of 1 week. I could move these automations from the mi app to hass.io and have them in one place. And then hass.io always should know the right state.

Regarding light groups: it looks like they are working with this script. Why they should not? I did not understand what kind of issues you expect. You wrote about issues on light groups nearly in the beginning of this thread.

I think the issue with not correct saving and restoring could be the following:
On yeelight bulbs I can change color_temp OR color, and depending on the last attrtibute I changed the real state of the bulb is different for the same setting of attribut values: hass.io has no information which of these 2 alternative settings is currrently applied, color_temp (white) or color. And when I want to save and restore the real previous state, then this will never be possible: If I save and restore color_temp, I will lost information about the color, if I save and restore color information, I will lost information about the color_temp. I would need the information which attributes are the “leading” attributes, but this information is not available.

Because most time the bulbs should be white I will revert to your original script, color_temp will be saved and restored, but I will not be able to restore a color.

There are multiple problems with trying to use a light group with this script. The main one is it is a combination of the status of the lights it contains. So if you restore a light, then restore the light group, restoring the light group will very likely change the light to something different. (The easiest example is if the light contains two lights, and one was on and one was off. In this case the light group would be on, and would change the light that was off to on.) With just one light in a light group I suppose this wouldn’t be a problem. But I would think most light groups would have more than one light, otherwise why use a group?

If the light supports both, then I would think it should only report which one was last used. Or, at least, if color (i.e., hs_color, xy_color, rgb_color, etc.) was used, and that color cannot be represented by color temperature, then it shouldn’t report color_temp, because if it did, it would be lying. This is because all color temperatures can be converted to color, but not vice versa. So, it should only report both color and color temperature if they agree. And if they do, then it doesn’t matter which is used to save/restore.

regarding light groups: I am using them because I have lamps containing 3 or 4 bulbs and I want them to have the same state. That’s why restoring one state to all of them is exactly what I am looking for :slight_smile:
I understand that light groups can be used different. And then there could be issues as you described.

Regarding color_temp and color: it looks like changing the color_temp will convert in the “right” color. So saving and storing color should also work and should also restore the color_temp.

I will start to move automation from MI home app into hass.io. Then they should better match, when I use cubes or switches to change light attributes.

Thanks again for your support!

Support has been added to install/update this python_script using the Custom Updater. See Light Store doc page for more details.

3 Likes

To add support for custom_updater a variable named __version__ was added. Unfortunately this is apparently not allowed in python_scripts, because it caused it to fail. An issue has been opened with custom_updater. Until this is resolved do not try to use the new version of this light_store.py script. (I’ll revert the change for now.)

@pnbruckner:
A big thank you for your work. This is one of a couple of your components I use and it works brilliantly.

I was just wondering if there is a way to use a “transition” when restoring states.

As an example, if the lights are dimmed/turned off for a movie, then restored to previous state, is it possible for the lights to more gently transition back to their original state?

Again, thank you for all your work.

I don’t think all lights support the transition turn_on parameter, but you could try changing:

                if component == 'light' and turn_on and old_state.attributes:
                    service_data.update(old_state.attributes)

to something like:

                if component == 'light' and turn_on:
                    service_data['transition'] = 3
                    if old_state.attributes:
                        service_data.update(old_state.attributes)

Thanks @pnbruckner.
I am pretty green with Python but I will have a little play with it.
My Zwave and Philips hue lights all support transitions when done in YAML and manually in services, so hoping it will work out :slight_smile: