Summary card and badges for people, devices and status (with python script and custom card)

Features:

  • Summarize a given list of groups (people, devices in use, devices offline, etc) and show count, names and state last changed.
  • “Easy” to setup what and when to show: in the first lines you can configure the groups, conditions, pictures, etc.
  • Display in badges and in a custom state card (with multilines, each line with formatting options like red for erros).
  • Display the devices status (like based in a group with devices that should be alawys on). The badge picure it will dynamically change (all devices on = ok, 1 device off = alert, 2+ devices off = critical)
  • Display the current profile if isn’t the normal (uses the profile package, but it will works without it).
  • Display the alarm clock: disabled or the next alarm, weekday or weekend (uses the alarmclock package, but it will works without it).
  • Automatic refresh when a script is called or a switch is changed (without the need to specified the entities).
  • Debug flag.
  • Working with 0.59 (breaking changes).

summary

summary2

My repo: https://github.com/maattdiy/home-assistant-config

Related files for this:
python_scripts/summary.py (main logic).
config/packages/summary.yaml (triggers)
www/custom_ui/state-card-value_only.html (custom state card to show only value, not caption)

Related packages used in summary script:
config/packages/alarmclock.yaml
config/packages/profiles.yaml

Related topics:
Display only text in card (custom state card)
Count people that are home (summary ideas development)

13 Likes

@Mariusthvdb answering here in the new topic:

Now can be done :slight_smile: In groups_badge_pic, set the images to match the count, like “ok|bug|critical”

To do that replace the line
fname = groups_desc[idx] if debug else ’ ’
by
fname = groups_desc[idx]

About where and when call the script to refresh:
The best way that I found, for now, is this. It will call on switch change or script. For all the rest, there is a 1 minute interval update, that seems reasonable.

HI @mviezzer!
Things are developing!

Had a bit of a build around, and heres what i have now, starting to look, and behave, good:


Im using a different method for updating the summary. Although i like your method for refreshing at each state change in switch or script, i do have a lot of switches that are not in this summary, so refreshing the summary for that would be overkill, as it would for several other scripts.
Ive managed to change the automation for the family to work as i want it to, and have the other 2 groups setup via global automations that still need some work.
I think some of the relay in action had to do wth the router settings, from which the automation takes its state changes. so further tweaking will focus on that.

let mea sk please: how do i show a badge when no device is in use, and showing a 0, or maybe a picture. As is is now, the badge doesn’t show, and im nt confident yet thats because nothing is on, or that the script or system isn’t working correctly. Having a badge show up with the 0, would prove its right.

Cheers,.

o, and many thanks!
Marius

Please help
Error when restart home assistant:
the following components and platforms could not be set up python script

After follow your step which involved the alarm clock weekday and weekend. the alarm clock work fine and I change the service from the automation.
The summary card and badges for people,devices and status won’t work due to problem with I don’t know regarding components and platforms could not be setup up python_script.

hi,

the setup is rather complex and involving several packages, scripts and automations, groups and python scripts…

you’d have to be more precise as to what you have installed and errors you get in the logs, for us to be able to help.
also be sure to update to the latest versions of the Hassio and custom-ui.

cheers,
Marius

the error is
“the following components and platforms could not be set up python_script”
In configuration.yaml.
python_script:
frontend:
themes: !include_dir_merge_named themes/
extra_html_url:
- /local/custom_ui/state-card-custom-ui.html
extra_html_url_es5:
- /local/custom_ui/state-card-custom-ui-es5.html
-/local/custom_ui/state-card-value_only.html
The rest files involved which is in .yaml work fine.
One of the geo_code.py in my custom_components to display the street address work fine. I don’t have to put python_script: in configuration.yaml

My HA version is 0.59.2 on Hassbian
Home assistant can start normally but the mention of the error is
“the following components and platforms could not be set up python_script”

If I don’t put python_script: in configuration.yaml (Couldn’t find python_script/summary)
If I put python_script: in configuration.yaml (the following components and platforms could not be set up : python-script)

input_select.ha_mode: cannot display in frontend. I already in group put won’t show.

@mviezzer
hi Markus,
why did this happen again:
Error executing script: list index out of range
Traceback (most recent call last):
File “/usr/lib/python3.6/site-packages/homeassistant/components/python_script.py”, line 166, in execute
exec(compiled.code, restricted_globals, local)
File “summary.py”, line 88, in
File “/usr/lib/python3.6/site-packages/RestrictedPython/Eval.py”, line 35, in default_guarded_getitem
return ob[index]
IndexError: list index out of range

im experimenting with different groups in the devices_on place, but am not sure what i am/am-not allowed to use there.

if it still is the fact that each group would need the same number of elements, tis is a major annoyance … if have only 4 daughters, and many more audio and video devices :wink:

seriously, could we find a solution for this?

this is about the line picture = list[groups_count[idx]] below:

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()

            # Check for picture X index/count
            if (picture != ''):
                list = picture.split('|')
                if (len(list) in [1, groups_count[idx]]):
                    picture = list[len(list)-1]
                else:
                    picture = list[groups_count[idx]]

                if (picture != ''):
                    picture = '/local/badges/{}.png'.format(picture)

i am using 3 groups of 6 items (had to be the same number of items, right ?) What does the error mean related to these numbers?

Cheers,
Marius

I would like to say thank you very much to Mr. Mviezzer and all of the replied in the board.
Finally, I got it work and done without error loading component python_script:
The badge didn’t show up but I know it working correctly and the Summary Card don’t show.
May I ask about the badges. what the
Entity ID this would be ? Thus I can put in a group and show to the frontend.

Sorry, for my broken english.

in the info show:
Error executing script: ‘NoneType’ object is not subscriptable
4:45 PM components/python_script.py (ERROR)
Unable to find service python_script/activity
4:45 PM core.py (WARNING)

just to be sure of correct construction:
these: home-assistant-config/config/packages/activity.yaml at master · maattdiy/home-assistant-config · GitHub aren’t necessary anymore then are they, since they do the same?

About the last_command : it should also pickup mode-selection changes should it? in my setup it won’t (think it did before) and i get this dreaded error, which i cant get away with, please have another look for me will you:

Error executing script: 'NoneType' object is not callable
Traceback (most recent call last):
  File "/usr/lib/python3.6/site-packages/homeassistant/components/python_script.py", line 166, in execute
    exec(compiled.code, restricted_globals, local)
  File "last_cmd.py", line 18, in <module>
TypeError: 'NoneType' object is not callable

last_command code:

# Get params
event = data.get('event')
# logger.error("LAST CMD: " + str(event))
# Sample: <Event call_service[L]: service_data=, service_call_id=78356624-86, service=mp_playpause, domain=script>

# Find the script name.
pos_start = event.find('service=')+8
pos_end = event.find(',', pos_start)

# Get the state object (script) from the name
entity_id = 'script.' + event[pos_start:pos_end]
state = hass.states.get(entity_id)
dt = datetime.datetime.now() #state.attributes.get('last_triggered')
time = "%02d:%02d" % (dt.hour, dt.minute)

# Ignore some names
msg = state.name
if (msg == 'None' or msg.startswith('Set ')):
    msg = ''

if (msg != '') :
    # Sensor update
    hass.states.set('sensor.last_command', '{} - {}'.format(time, msg), {
        'custom_ui_state_card': 'state-card-value_only'
    })

been a while…

had to reshuffle automations and scripts that where in the packages. Some of them weren’t triggered system wide, so i took them out and put them in the main hierarchy.
Also, the mode-triggers weren’t fired for showing the developer card/groups, and i had to write these little scripts for that.
Of course i forgot that one needs an automation to make things happen, so here goes. Of utmost basic-ness, but working just fine:
Automation:

        - alias: Ha Mode selection 
          id: '1511601478201'
          trigger:
            platform: state
            entity_id: input_select.ha_mode
          action:
            service_template: >
              {% if is_state ('input_select.ha_mode','Normal') %} script.mode_normal
              {% elif is_state ('input_select.ha_mode', 'Full house') %} script.mode_full_house
              {% elif is_state ('input_select.ha_mode','Kiosk') %} script.mode_kiosk
              {% elif is_state ('input_select.ha_mode', 'Developer') %} script.mode_developer
              {% endif %}

The mode selectors:

##########################################################################################
# Mode selection
##########################################################################################


# Mode Developer
mode_developer:
  alias: Developer mode selected
  sequence:
    - service: input_select.select_option
      data:
        entity_id: input_select.ha_mode
        option: Developer
    - service: group.set_visibility
      entity_id: group.developer
      data:
        visible: True


# Mode Normal. Called in Startup (packages/ha_triggers.yaml)
mode_normal:
  alias: Normal mode selected
  sequence:
    - service: input_select.select_option
      data:
        entity_id: input_select.ha_mode
        option: Normal
    - service: group.set_visibility
      entity_id: group.developer
      data:
        visible: False

# Mode Kiosk
mode_kiosk:
  alias: Kiosk mode selected
  sequence:
    - service: input_select.select_option
      data:
        entity_id: input_select.ha_mode
        option: Kiosk
    - service: notify.ios_telefoonmhb
      data:
        message: "Wow: Kiosk-mode selected!"
    - service: group.set_visibility
      entity_id: group.developer
      data:
        visible: False
#https://domain.duckdns.org/kiosk/group.home_monitoring
# to be built from here

mode_full_house:
  alias: Full house mode selected
  sequence:
    - service: input_select.select_option
      data:
        entity_id: input_select.ha_mode
        option: Full house
    - service: notify.ios_telefoonmhb
      data:
        message: "Full house-mode selected, turn on the vents!"
    - service: group.set_visibility
      entity_id: group.developer
      data:
        visible: False
# to be built from here

Doing fine now!
Messaging makes sure the scripts are fired.

refining to do:

  • finding a way to show 0 off-liners in the summary, preferably in green.

  • working out how to fire the command line https://domain.duckdns.org/kiosk/group.home_monitoring and load kiosk mode

  • working out if dev-mode can not only show groups, but also parts in the left panel. Or, erased differently, only show those parts in dev-mode :wink:

  • working out how to change a mode (input_select) based upon a sensor:
    example: (climate above 900ppm-> Mode Full house

  • lots more.

NO bugs to show, but counter works perfectly, showing thumbs (0), Bug (1) and X (more) off liners.
Cool, happy camper here.
Cheers,
Marius

@mviezzer First of all, thanks for sharing your config!

I’ve been trying to do the same (only more simplistic) for a while now and I just can’t get the content to show up in the frontend. I’ve got no idea what I’m doing wrong, but I must be missing something.

Alright, so I have a more simplistic summary (more like your earlier version). Below is everything I added to the config to make this work (or at least tried to):

python_scripts/summary.py:

lights_count = 0
content = ""

for entity in hass.states.entity_ids('light'):
    light = hass.states.get(entity)

    if (light.state == 'on'):
        lights_count = lights_count + 1

if lights_count == 1:
    content = "1 light is on.\n"
elif lights_count > 1:
    content = "{} lights are on.\n".format(lights_count)
else:
    content = "All lights are off.\n"

hass.states.set('sensor.summary', '', {
  'custom_ui_state_card': 'state-card-text',
  'text': content
})

Configuration for the frontend (as you can see I’m also using Custom UI, which is working fine):

javascript_version: es5

extra_html_url:
  - /local/custom_ui/state-card-custom-ui.html
  - /local/custom_ui/state-card-text.html
extra_html_url_es5:
  - /local/custom_ui/state-card-custom-ui-es5.html
  - /local/custom_ui/state-card-text.html

www/custom_ui/state-card-text.html:

<dom-module id="state-card-text">
  <template>

    <style is="custom-style" include="iron-flex iron-flex-alignment"></style>
    <style>
      .state {
        @apply(--paper-font-body1);
        color: var(--primary-text-color);
        margin-left: 8px;
        text-align: left;
        line-height: 20px;
      }
    </style>

    <template is="dom-repeat" items="[[computeStateDisplay(stateObj)]]">
      <div class="state">[[computeItem(item)]]</div>
    </template>

  </template>
</dom-module>

<script>
Polymer({
  is: 'state-card-text',

  properties: {
    hass: { type: Object },
    stateObj: { type: Object },
  },

  computeStateDisplay: function (stateObj) {
    var text = stateObj.attributes.text;

    if (text == null) { text = stateObj.state };
    return text.split("\n")
  },

  computeItem: function (item) {
    return item.trim();
  },

});
</script>

In my default view I have the following configured:

default_view:
  view: yes
  icon: mdi:home-assistant
  entities:
    - sun.sun
    - group.custom

custom:
  name: Custom
  entities:
    - sensor.summary

And this is my automation to call the Python script:

- alias: Trigger on script event
  initial_state: 'on'
  trigger:
    - platform: event
      event_type: call_service
      event_data:
        domain: script
  action:
    - delay: '00:00:02'
    - service: python_script.summary

- alias: Trigger on light event
  initial_state: 'on'
  trigger:
    - platform: event
      event_type: call_service
      event_data:
        domain: light
  action:
    - delay: '00:00:02'
    - service: python_script.summary

- alias: Time interval updates
  initial_state: 'on'
  trigger:
    - platform: time
      minutes: '/1'
      seconds: 00
  action:
    - service: python_script.summary

This is the result:

state-card

As you can see, it doesn’t show up in the custom state card, but when I click on the state card it opens up the following popup window and the content does show up in there:

state-card-popup

Also, on the States page in the Developer Tools section the sensor.summary is updated constantly. Either because of the interval updates or the script / light updates, the text attribute is correctly updated.

What am I missing? I would love to get some help from you or someone else on this. Any help is appreciated.

Hi, if shows up in popup and not in card, it’s a cache issue. Try force refresh or incognito mode.

Sorry for delay, didn’t play around last days… work stuff…
Nice progress @Mariusthvdb :slight_smile:

The activity is only necessary for the the input_select and group definition

I updated the last_cmd to prevent this error.

So far I was only able to show/hide groups. Let me know if you have any news on that.

I updated the summary and card to do that.
Now you can set the description if count = 0 in groups_desc = [‘!Nobody in home’, ‘’, ‘+The system is ok’]
The new + prefix make it green. The ! prefix make it red.

summary3

I tried to force refresh, but that didn’t work. After a couple of reboots (because of changes in other parts of Home Assistant) it did finally show up in the frontend.

There is still one thing that I don’t get. It is now showing up in Chrome on my Mac and also on my iPhone (in a browser), but it won’t show up in the iPhone app. Do you also have this problem by any change? I first thought it also might be a cache issue, so I closed and opened the iOS app a couple of times and even rebooted my phone. Its still not showing up.

Edit: I’m now wondering whether the iOS app is using the webview (which should work) or has its own implementation, which should not be able to use custom state cards at all, but since the Custom UI state cards are working it’s probably a cache issue as well.

cool, no worries, had tons of things changed, and a bit of work also :wink:

I see, ive changed along. Still, i’ve learned that whenever its reporting these errors, it’s not this script that is at fault, but other, mostly syntactical, errors elsewhere in the setup. So never ignore them. Sometimes they go 3 layers down, to syntax in the scripts and automations…

Yes! exactly what i was looking for. Ive changed the state card only and summary but get this:

12
‘system ok’ is already there, but apparently (see the +) the state card isn’t correct or correctly read somehow. Can’t see the error myself, can you?:

<style>
      .normal {
        @apply(--paper-font-body1);
        color: var(--primary-text-color);
        margin-left: 8px;
        text-align: left;
        line-height: 20px;
      }
      .bold {
        @apply(--paper-font-body1);
        color: var(--primary-text-color);
        font-style: italic;
        margin-left: 8px;
        text-align: left;
        line-height: 20px;
      }
      .red {
        @apply(--paper-font-body1);
        color: var(--google-red-500);
        margin-left: 8px;
        text-align: left;
        line-height: 20px;
      }
      .green {
        @apply(--paper-font-body1);
        color: var(--google-green-500);
        margin-left: 8px;
        text-align: left;
        line-height: 20px;
      }
    </style>

  computeItem: function (item) {
      var value = item.trim();

      switch(value.substring(0,1)) {
      case "*":
      case "!":
      case "+":
          return value.substring(1);
      default:
          return value;
      }
  },

  computeClass: function (item) {
      switch(item.trim().substring(0,1)) {
      case "*": return "bold";
      case "!": return "red";
      case "+": return "green";
      default:  return "normal";
      }

Going on, i would prefer 3 enhancements of this Summary card.

  • show the time of last mode selection: “Developer mode was selected at: 08.00 am” I tried to edit the script but only get errors back ;-))( . also, the Card moves the ‘at:’ a line down, and not behind the mode selection…
    if not hidden:
    mode_desc = '{}*{} mode was activated\n at: '.format(summary, state.state)
  • secondly, id love to have the activity selection on the card also, is that still a possibility? Or would the full summary.py need rewriting. I really feel it would create the complete dashboard we’re after. Show the 2 selection criteria, with their respective states, times, errors and numbers!

Ive tried it with the activity sensor added to the group card, but don’t like the view. Also, it takes out the badge of the View/Tab above, and i really love to keep those 5 badges there.

0950
26

  • Lastly: not sure if this is supposed to be this way, but clicking the Summary card, we get a silly detailed view:

State unknown, and the content is shown twice, not sure if the ‘text’ solution for the 251 character issue is acting as its supposed to?

Have a check:

As always: thanks a bunch and keep developing! )o, and sharing of course, learning here, as we go along)

Cheers,
Marius

Do a force refresh or clear the cache, should work.

Use the input_select (input_select.activity) instead the sensor in the group…

IDK why is showing twice. The text is working as show as attribute. The State will be Unknow indeed because the 255 limitation in state.

I’ll check on that.

it does!
24

not sure if i understand you correctly, but if i do that it shows the input selector… not the selected activity,
ive put them together for quick reference:

dashboard:
  name: Dashboard
  icon: mdi:view-dashboard
  entities:  
    - input_select.ha_mode
    - sensor.mode_badge
    - input_select.activity
    - sensor.activity_badge
    - sensor.last_command

54

Also: it takes the badge out of the top page, where i want to keep it being displayed.
So, I am looking for displaying selected activity and time on the Summary card, just like the Mode. This doesn’t seem to do it just yet. 5 badges (sensors) in plain view, and the result of these 5 sensors on the summary card…

Could you confirm please it does in your setup aswell? so im certain the script and HA are working correctly.

Thanks!
Marius

HI @thmry,

What your describing is very similar to the issues i had when upgrading the Custom-ui. One has to be very precise depending on the various versions, in the settings of its configuration. Not sure if the latest .60 update to Home Assistant made any breaking issues, but you might want to check @andrey 's pages again to be sure https://github.com/andrey-git/home-assistant-custom-ui/blob/master/docs/installing.md

The app is a separate thing as far as i understand it. In my case, it shows, and keeps showing, pictures i changed weeks ago. There’s no force refresh in the app unless the refresh icon does that, ( i think it only reloads…not sure) Even after deleting and reinstalling the app completely the old pictures keep showing up…

Cheers,
Marius