119 lines
4.8 KiB
Python
119 lines
4.8 KiB
Python
VERSION = '1.2.0'
|
|
|
|
DOMAIN = 'light_store'
|
|
|
|
ATTR_OPERATION = 'operation'
|
|
ATTR_OP_SAVE = 'save'
|
|
ATTR_OP_RESTORE = 'restore'
|
|
ATTR_OVERWRITE = 'overwrite'
|
|
|
|
ATTR_STORE_NAME = 'store_name'
|
|
ATTR_ENTITY_ID = 'entity_id'
|
|
|
|
# Select light attributes to save/restore.
|
|
ATTR_BRIGHTNESS = "brightness"
|
|
ATTR_EFFECT = "effect"
|
|
ATTR_WHITE_VALUE = "white_value"
|
|
ATTR_COLOR_TEMP = "color_temp"
|
|
ATTR_HS_COLOR = "hs_color"
|
|
# Save any of these attributes.
|
|
GEN_ATTRS = [ATTR_BRIGHTNESS, ATTR_EFFECT]
|
|
# Save only one of these attributes, in order of precedence.
|
|
COLOR_ATTRS = [ATTR_WHITE_VALUE, ATTR_COLOR_TEMP, ATTR_HS_COLOR]
|
|
|
|
def store_entity_id(store_name, entity_id):
|
|
return '{}.{}'.format(store_name, entity_id.replace('.', '_'))
|
|
|
|
# Get operation (default to save.)
|
|
operation = data.get(ATTR_OPERATION, ATTR_OP_SAVE)
|
|
if operation not in [ATTR_OP_SAVE, ATTR_OP_RESTORE]:
|
|
logger.error('Invalid operation. Expected {} or {}, got: {}'.format(
|
|
ATTR_OP_SAVE, ATTR_OP_RESTORE, operation))
|
|
else:
|
|
# Get optional store name (default to DOMAIN.)
|
|
store_name = data.get(ATTR_STORE_NAME, DOMAIN)
|
|
|
|
# Get optional overwrite parameter (only applies to saving.)
|
|
overwrite = data.get(ATTR_OVERWRITE, True)
|
|
|
|
# Get optional list (or comma separated string) of switches & lights to
|
|
# save/restore.
|
|
entity_id = data.get(ATTR_ENTITY_ID)
|
|
if isinstance(entity_id, str):
|
|
entity_id = [e.strip() for e in entity_id.split(',')]
|
|
|
|
# Replace any group entities with their contents.
|
|
# Repeat until no groups left in list.
|
|
expanded_a_group = True
|
|
while entity_id and expanded_a_group:
|
|
expanded_a_group = False
|
|
for e in entity_id:
|
|
if e.startswith('group.'):
|
|
entity_id.remove(e)
|
|
g = hass.states.get(e)
|
|
if g and 'entity_id' in g.attributes:
|
|
entity_id.extend(g.attributes['entity_id'])
|
|
expanded_a_group = True
|
|
|
|
# Get lists of switches and lights that actually exist,
|
|
# and list of entities that were previously saved.
|
|
entity_ids = (hass.states.entity_ids('switch') +
|
|
hass.states.entity_ids('light'))
|
|
saved = hass.states.entity_ids(store_name)
|
|
# When restoring, limit to existing entities that were saved.
|
|
if operation == ATTR_OP_RESTORE:
|
|
saved_entity_ids = []
|
|
for e in entity_ids:
|
|
if store_entity_id(store_name, e) in saved:
|
|
saved_entity_ids.append(e)
|
|
entity_ids = saved_entity_ids
|
|
|
|
# If a list of entities was specified, further limit to just those.
|
|
# Otherwise, save all existing switches and lights, or restore
|
|
# all existing switches and lights that were previously saved.
|
|
if entity_id:
|
|
entity_ids = tuple(set(entity_ids).intersection(set(entity_id)))
|
|
|
|
if operation == ATTR_OP_SAVE:
|
|
# Only save if not already saved, or if overwite is True.
|
|
if not saved or overwrite:
|
|
# Clear out any previously saved states.
|
|
for entity_id in saved:
|
|
hass.states.remove(entity_id)
|
|
|
|
# Save selected switches and lights to store.
|
|
for entity_id in entity_ids:
|
|
cur_state = hass.states.get(entity_id)
|
|
if cur_state is None:
|
|
logger.error('Could not get state of {}.'.format(entity_id))
|
|
else:
|
|
attributes = {}
|
|
if entity_id.startswith('light.') and cur_state.state == 'on':
|
|
for attr in GEN_ATTRS:
|
|
if attr in cur_state.attributes:
|
|
attributes[attr] = cur_state.attributes[attr]
|
|
for attr in COLOR_ATTRS:
|
|
if attr in cur_state.attributes:
|
|
attributes[attr] = cur_state.attributes[attr]
|
|
break
|
|
hass.states.set(store_entity_id(store_name, entity_id),
|
|
cur_state.state, attributes)
|
|
else:
|
|
# Restore selected switches and lights from store.
|
|
for entity_id in entity_ids:
|
|
old_state = hass.states.get(store_entity_id(store_name, entity_id))
|
|
if old_state is None:
|
|
logger.error('No saved state for {}.'.format(entity_id))
|
|
else:
|
|
turn_on = old_state.state == 'on'
|
|
service_data = {'entity_id': entity_id}
|
|
component = entity_id.split('.')[0]
|
|
if component == 'light' and turn_on and old_state.attributes:
|
|
service_data.update(old_state.attributes)
|
|
hass.services.call(component,
|
|
'turn_on' if turn_on else 'turn_off',
|
|
service_data)
|
|
|
|
# Remove saved states now that we're done with them.
|
|
for entity_id in saved:
|
|
hass.states.remove(entity_id) |