sure, id be glad to.
What im trying to figure out is which causes what: the automation is triggered by changes in the lights, which also happens when the hue lights become unavailable and back again. so a possible loop of events.
Only happening on the Hue lights. Half of the lights are Tradfri, and there is zero issue there. They are checked by the same 2 scripts and same automations.
Hope this helps.
please see below:
whats_on.py:
##########################################################################################
# Whats_on.py, previously known as Anything_on...
#
# interrelated with the Summary.py, which doesn't show the entities per badge (yet)
# modified and customized by https://community.home-assistant.io/u/Mariusthvdb/summary
# big hand in Python by https://community.home-assistant.io/u/petro/summary
# tbd: timezone correction a bit of a challenge, solved with a little hack (=2)
##########################################################################################
familyEntities = 'group.family'
switchEntities = 'group.iungo_switch_switches_template'
lightEntities = 'group.all_lights_only'
applianceEntities = 'group.iungo_switch_appliances_template'
filteredLightEntities = [ entity_id for entity_id in lightEntities if ' ' not in entity_id ]
def CountMyEntities(hass, entity_list, entity_state):
cnt = 0
# using a full list: for entity_id in entity_list:
# using groups in a [list] : for group_entity in entity_list:
# for entity_id in hass.states.get(group_entity).attributes['entity_id']:
for entity_id in hass.states.get(entity_list).attributes['entity_id']:
state = hass.states.get(entity_id)
if state.state == entity_state:
cnt = cnt + 1
return cnt
familyHome = CountMyEntities(hass, familyEntities, 'home')
switchesOn = CountMyEntities(hass, switchEntities, 'on')
appliancesOn = CountMyEntities(hass, applianceEntities, 'on')
lightsOn = CountMyEntities(hass, lightEntities, 'on') #if needed, use filteredLightEntities
totalOn = switchesOn + lightsOn + appliancesOn
whichIcon = 'mdi:lightbulb-on-outline' if totalOn else 'mdi:lightbulb-outline'
status = 'on' if totalOn else 'off' # will evaluate "off" if totalOn == 0.
hass.states.set('input_boolean.whats_on', status, {
'friendly_name': "What's On?",
'icon': whichIcon,
'family_home': familyHome,
'lights_on': lightsOn,
'switches_on': switchesOn,
'appliances_on': appliancesOn,
'total_on': totalOn,
'extra_data_template':'{total_on} on'
})
##########################################################################################
# Lights:
# Badges images: /config/www/lights
##########################################################################################
lights_on = []
#show only lights, not light groups
#excluded = ['light.custom_group_for_group','light.custom_group_for_lights_2']
#total_lights_on = hass.states.get('input_boolean.whats_on').attributes.get('lights_on')
state = hass.states.get('automation.sense_lights_change')
if state:
total_on = hass.states.get('input_boolean.whats_on').attributes.get('lights_on')
for entity_id in hass.states.get(lightEntities).attributes['entity_id']:
dt = state.last_updated + datetime.timedelta(hours=2)
time = '%02d:%02d' % (dt.hour, dt.minute)
if hass.states.get(entity_id).state is 'on': #and entity_id not in excluded
lights_on.append(hass.states.get(entity_id).attributes['friendly_name'])
if len(lights_on) > 0:
picture = '/local/lights/hue_pl.png'
message = ', '.join(lights_on)
sensor_message = 'Lights on: ' + message
lights_desc = '=- Lights on: {} -- {} since {}'.format(total_on, message,time)
uom = 'Lights'
if len(lights_on) == 1:
uom = 'Light'
else:
picture = '/local/lights/bulboff.png'
message= ''
sensor_message= 'No lights on'
uom = 'Lights'
sensor_lights_desc = '{}'.format(sensor_message)
hass.states.set('sensor.lights_badge', total_on, {
# 'custom_ui_state_card': 'state-card-value_only',
'text': sensor_message,
'unit_of_measurement': uom,
'friendly_name': time,
'entity_picture': picture
})
##########################################################################################
# Switches:
# Badges images: /config/www/buttons
##########################################################################################
switches_on = []
#total_switches_on = hass.states.get('input_boolean.whats_on').attributes.get('switches_on')
state = hass.states.get('automation.sense_switches_change')
if state:
total_on = hass.states.get('input_boolean.whats_on').attributes.get('switches_on')
for entity_id in hass.states.get(switchEntities).attributes['entity_id']:
dt = state.last_updated + datetime.timedelta(hours=2)
time = '%02d:%02d' % (dt.hour, dt.minute)
if hass.states.get(entity_id).state is 'on':
switches_on.append(hass.states.get(entity_id).attributes['friendly_name'])
if len(switches_on) > 0:
picture = '/local/buttons/button_power_on.png'
message = ', '.join(switches_on)
sensor_message = 'Switches on: ' + message
switches_desc = '#- Switches on: {} -- {} since {}'.format(total_on, message,time)
uom = 'Switches'
if len(switches_on) == 1:
uom = 'Switch'
else:
picture = '/local/buttons/button_power_off.png'
message= ''
sensor_message= 'No switches on'
uom = 'Switches'
sensor_switches_desc = '{}'.format(sensor_message)
hass.states.set('sensor.switches_badge', total_on, {
# 'custom_ui_state_card': 'state-card-value_only',
'text': sensor_message,
'unit_of_measurement': uom,
'friendly_name': time,
'entity_picture': picture
})
##########################################################################################
# Appliances:
# Badges images: /config/www/buttons
##########################################################################################
#appliancesGroup = 'group.iungo_switch_appliances_template'
appliances_on = []
#total_appliances_on = hass.states.get('input_boolean.whats_on').attributes.get('appliances_on')
state = hass.states.get('automation.sense_appliances_change')
if state:
total_on = hass.states.get('input_boolean.whats_on').attributes.get('appliances_on')
for entity_id in hass.states.get(applianceEntities).attributes['entity_id']:
dt = state.last_updated + datetime.timedelta(hours=2)
time = '%02d:%02d' % (dt.hour, dt.minute)
if hass.states.get(entity_id).state is 'on':
appliances_on.append(hass.states.get(entity_id).attributes['friendly_name'])
if len(appliances_on) > 0:
picture = '/local/buttons/button_power_on.png'
message = ', '.join(appliances_on)
sensor_message = 'Appliances on: ' + message
uom = 'Appliances'
if len(appliances_on) == 1:
uom = 'Appliance'
else:
picture = '/local/buttons/button_power_off.png'
message= ''
sensor_message= 'No appliances on'
appliances_desc = '!|-> No appliances on since {}'.format(time)
uom = 'Appliances'
sensor_appliances_desc = '{}'.format(sensor_message)
hass.states.set('sensor.appliances_badge', total_on, {
# 'custom_ui_state_card': 'state-card-value_only',
'text': sensor_message,
'unit_of_measurement': uom,
'friendly_name': time,
'entity_picture': picture
})
summary.py (slightly bigger):
##########################################################################################
# Resources:
# https://github.com/maattdiy/home-assistant-config @Mviezzer
# https://home-assistant.io/components/python_script/
# https://home-assistant.io/docs/configuration/state_object/
# modified and customized by https://community.home-assistant.io/u/Mariusthvdb/summary
# big hand in Python by https://community.home-assistant.io/u/petro/summary
##########################################################################################
debug = False
if debug:
event = data.get('event')
logger.error("\n\nSUMMARY: " + str(event))
show_badges = True
show_card = True
##########################################################################################
# Group count
# Groups config:
# Entities summary by group name
# groups = need to have same max member_count
# groups_format = # Message prefix
# groups_filter = # Filter to list
# groups_badge = # Badge 'belt' (unit_of_measurement)
# groups_badge_pic = # none, one, or a list of pictures (picture position = match the count)
# groups_min_show = # Mininum count to show
# groups_theme = # Theme template
# groups_desc = # Can set the default description, for use in case count = 0
# themes build up or down according to counted value
##########################################################################################
group_count = 0
group_desc = ''
summary = ''
idx = 0
dt_prevstate = None
on ='black_badge|red_badge|yellow_badge|grey_badge|blue_badge|orange_badge|brown_badge|purple_badge|green_badge'
off ='green_badge|purple_badge|brown_badge|orange_badge|blue_badge|grey_badge|yellow_badge|red_badge|black_badge'
groups = ['group.family',
'group.hubs_binary_pinged',
'group.critical_devices_state',
'group.media_player_media',
'group.device_tracker_media',
'group.all_lights_only',
'group.iungo_switch_switches_template',
'group.iungo_switch_appliances_template',
'group.binary_sensors_active_template']
groups_format = ['+- Home: {} -- {}',
'!|-> Offline: {} -- {}',
'!|-> Status - Critical device offline: {} -- {}',
'#- Playing: {} -- {}',
'#- Tracked: {} -- {}',
'=- Lights on: {} -- {}',
'#- Switches on: {} -- {}',
'#- Appliances on: {} -- {}',
'+- Active: {} -- {}']
groups_filter = ['home',
'off|idle|not_home',
'off|idle|unknown|not_home',
'home|playing|on',
'home|playing|on',
'on',
'on',
'on',
'on'] # was: 'home|playing|on'
groups_badge = ['Home','Hubs','Status','Play','Track','Lamps','Switch','Appli','Active']
groups_badge_pic = ['','ok|bug|critical','ok|bug|critical','','','','','','']
groups_min_show = [0,0,0,0,0,0,0,0,0]
groups_theme = [on,off,off,on,on,on,on,on,on]
groups_desc = ['!|-> Nobody home since ',
'+- Hubs: all online',
'+- Status: all online',
'%|-> Nothing playing',
'%|-> Nothing tracked',
'!|-> No lights on since ',
'!|-> No switches on since ',
'!|-> No appliances on since ',
'%|-> No Appliances active since ']
groups_count = [0, 0, 0, 0, 0, 0, 0, 0, 0]
for group in groups:
group_count = 0
group_desc = ''
for entity_id in hass.states.get(group).attributes['entity_id']:
state = hass.states.get(entity_id)
filter = groups_filter[idx]
if (state.state in filter.split('|') or debug):
dt = state.last_updated + datetime.timedelta(hours= 2)
time = '%02d:%02d' % (dt.hour, dt.minute)
ch = state.last_changed + datetime.timedelta(hours= 2)
ch_time = '%02d:%02d' % (dt.hour, dt.minute)
# If state changed in the past days show the date too
if dt.date() < datetime.datetime.now().date():
time = '{} {}'.format('%02d/%02d' % (dt.day, dt.month), time)
group_count = group_count + 1
group_desc = '{} {} ({}), '.format( group_desc, state.name, time)
else:
if (dt_prevstate is None):
dt_prevstate = state.last_changed
else:
if (not state.last_changed is None):
if (state.last_changed > dt_prevstate):
dt_prevstate = state.last_changed
# Final format for this group
if (group_count >= groups_min_show[idx]):
if (group_count == 0):
group_desc = groups_desc[idx]
# If there is none 'On/Home' state in group, show since
if (group_desc.find(' since ') > 0): #if (group_desc != ''):
dt = dt_prevstate + datetime.timedelta(hours= 2)
group_desc = '{} {}'.format(group_desc, '%02d:%02d' % (dt.hour, dt.minute))
else:
group_desc = groups_format[idx].format(group_count, group_desc[:-2])
groups_desc[idx] = group_desc
groups_count[idx] = group_count
idx = idx + 1
##########################################################################################
# Badges updates
##########################################################################################
idx = 0
if show_badges:
for badge in groups_badge:
if (badge != ''):
entity_id = 'sensor.{}_badge'.format(badge.replace(' ', '').lower());
hidden = False if (groups_count[idx] >= groups_min_show[idx] or debug) else True
fname = groups_desc[idx] if debug else ' '
picture = groups_badge_pic[idx].replace(' ', '').lower()
themelist = groups_theme[idx].split('|')
if len(themelist) > 1:
try:
theme = themelist[groups_count[idx]]
except IndexError:
theme = 'green_badge' # Oops, error badge.1 ;-))
else:
theme = 'black_badge' # this will be the default theme
# Check for picture X index/count
if (picture != ''):
picturelist = picture.split('|')
if (len(picturelist) in [1, groups_count[idx]]):
picture = picturelist[-1] #was mylist[len(mylist)-1]
else:
picture = picturelist[groups_count[idx]]
if (picture != ''):
picture = '/local/badges/{}.png'.format(picture)
hass.states.set(entity_id, groups_count[idx], {
'friendly_name': fname,
'unit_of_measurement': badge,
'entity_picture': picture,
'templates': { 'theme': theme }
})
idx = idx + 1
##########################################################################################
# Alarm clock
# https://github.com/maattdiy/home-assistant-config/blob/master/config/packages/alarmclock.yaml
##########################################################################################
alarms_prefix = ['alarmclock_wd', 'alarmclock_we']
alarms_wfilter = [range(1,6), range(6,8)]
alarms_desc = ''
mydict = {'hidden':hidden}
for entity_id, filter in zip(alarms_prefix, alarms_wfilter):
state = hass.states.get('input_boolean.{}_enabled'.format(entity_id))
if state:
if state.state is 'on' and datetime.datetime.now().isoweekday() in filter:
state = hass.states.get('sensor.{}_time_template'.format(entity_id))
alarms_desc = '{}{}, '.format(alarms_desc, state.state)
if (alarms_desc == ''):
mydict['entity_picture'] = '/local/badges/alarm_off.png'
mydict['friendly_name'] = 'Relax'
mydict['unit_of_measurement'] = 'Off'
mydict['theme'] = 'grey_badge'
alarms_desc = '%- Alarm clock is not set, relax'
else:
mydict['entity_picture'] = '/local/badges/alarm.png'
mydict['friendly_name'] = alarms_desc[:-2]
mydict['unit_of_measurement'] = 'On'
mydict['theme'] = 'orange_badge'
alarms_desc = '/- Alarm clock set at ' + alarms_desc[:-2]
hass.states.set('sensor.alarms_badge', '', mydict)
##########################################################################################
# Mode:
# Inspired by: https://github.com/maattdiy/home-assistant-config/blob/master/config/packages/profiles.yaml
# https://github.com/maattdiy/home-assistant-config/blob/master/config/packages/developer.yaml
# Badges images: /config/www/modes
##########################################################################################
mode_desc = ''
## Get Mode description
state = hass.states.get('input_select.mode')
if state:
dt = state.last_changed + datetime.timedelta(hours= 2)
time = "%02d:%02d" % (dt.hour, dt.minute)
mode_desc = '{}*- {} mode selected at: {}\n'.format(summary, state.state, time)
hass.states.set('sensor.mode_badge',state.state, {
'entity_picture': '/local/modes/{''}.png'.format(state.state.replace(' ','').lower()),
'friendly_name': time,
'unit_of_measurement': 'Mode'
})
##########################################################################################
# Activity:
# Badges images: /config/www/activities
##########################################################################################
activity_desc = ''
## Get Activity description
state = hass.states.get('input_select.activity')
if state:
dt = state.last_changed + datetime.timedelta(hours= 2)
time = "%02d:%02d" % (dt.hour, dt.minute)
activity_desc = '{}$- {} activity selected at: {}\n'.format(summary, state.state, time)
hass.states.set('sensor.activity_badge', state.state, {
'friendly_name': time,
'entity_picture': '/local/activities/{' '}.png'.format(state.state.replace(' ','').lower()),
'unit_of_measurement': 'Act'
})
##########################################################################################
# Summary update
# Custom card: /custom_ui/state-card-value_only.html
##########################################################################################
for group_desc in groups_desc:
if group_desc != '' and not group_desc.endswith(': '):
summary = '{}{}\n'.format(summary, group_desc)
# Add to final summary
summary = '*============== Status ============\n' \
'{}\n' \
'*============= Settings ===========\n' \
'{}\n' \
'*============== Modes =============\n' \
'{}\n' \
'{}' \
.format(summary,
alarms_desc,
activity_desc,
mode_desc)
if show_card:
hass.states.set('sensor.summary', '', {
'custom_ui_state_card': 'state-card-value_only',
'text': summary
})
##########################################################################################
# Codes for text_colors declared in
# Custom card: /custom_ui/state-card-value_only.html
# changed to use below customizing options:
##########################################################################################
# case "*": return "bold";
# case "/": return "italic";
# case "!": return "red";
# case "+": return "green";
# case "=": return "yellow";
# case "%": return "grey";
# case "$": return "brown";
# case "#": return "blue";
# default: return "normal";