System Monitoring - How does yours look?

Hey klogg,

I would love to see the code for that specific card you showed with the System Information.
Looks great!

That’s better we’ll done what do you use for Docker stat’s?

That picture was only the top three elements but this is all of it just in case it’s interesting. As always much of it has been borrowed or adapted from others.

Here you go…

      - type: entities
        show_header_toggle: false
        entities:

          - type: custom:secondaryinfo-entity-row
            entity: sensor.system_uptime
            secondary_info: "Since: [[ sensor.last_boot_date_time ]]"
            icon: mdi:desktop-classic

          - entity: sensor.ha_uptime
            icon: mdi:home-assistant

          - type: custom:multiple-entity-row
            entity: sensor.installed_version
            name: HA Installed Version
            icon: mdi:home-assistant
            state_header: Current
            entities:
              - entity: sensor.latest_available_version
                name: Latest
            style: |
              :host {
                {% if states(config.entity).split('.')[1] != states('sensor.latest_available_version').split('.')[1] %}
                  color: rgb(255, 165, 0);
                  --paper-item-icon-color: rgb(255, 165, 0);
                {% endif %};
              }

          - entity: sensor.supervisor_updates
            name: Addon Updates
            icon: mdi:cart-plus
            tap_action:
              action: navigate
              navigation_path: /hassio/dashboard
            style: |
              :host {
                {% if states(config.entity) != '0' %}
                  color: rgb(255, 165, 0);
                  --paper-item-icon-color: rgb(255, 165, 0);
                {% endif %};
              }
            

          - entity: sensor.hacs
            name: HACS
            tap_action:
              action: navigate
              navigation_path: /hacs/installed
            style: |
              :host {
                {% if states(config.entity) != '0' %}
                  color: rgb(255, 165, 0);
                  --paper-item-icon-color: rgb(255, 165, 0);
                {% endif %};
              }

          - entity: sensor.home_assistant_log
            tap_action:
              action: url
              url_path: http://192.168.1.25:8123/developer-tools/logs
            style: |
              :host {
                {% if states(config.entity) >= '0.5' %}
                  color: rgb(255, 165, 0);
                  --paper-item-icon-color: rgb(255, 165, 0);
                {% endif %};
              }


          - entity: sensor.home_assistant_v2_db
            icon: mdi:database
          
          - type: custom:secondaryinfo-entity-row
            entity: sensor.nuc_model
            secondary_info: "Board Name: [[ sensor.nuc_board_name ]]"
            icon: mdi:desktop-classic

          - type: custom:secondaryinfo-entity-row
            entity: sensor.bios_vendor
            secondary_info: "Version: [[ sensor.nuc_bios_version ]]"
            icon: mdi:desktop-classic

          # - entity: sensor.linux_version
          #   icon: mdi:desktop-classic

          - entity: sensor.tasmota_current_version
            name: Tasmota Latest Version
            icon: mdi:alpha-t-box-outline

          - type: custom:bar-card
            columns: 2
            entities:
              - entity: sensor.processor_use
                name: CPU
                icon: mdi:chip
              - entity: sensor.memory_use_percent
                name: RAM
                icon: mdi:memory
              - entity: sensor.cpu_temp
                name: Temp
                icon: mdi:thermometer
              - entity: sensor.disk_use_percent
                name: Disk
                icon: mdi:harddisk
            severity:
              - from: 0
                to: 60
                color: green
              - from: 61
                to: 80
                color: orange
              - from: 81
                to: 100
                color: red
            positions:
              indicator: 'off'
            style: |-
              bar-card-title {
                text-shadow: 1px 1px 5px black;
              }
              bar-card-value {
                text-shadow: 1px 1px 5px black;
              } 

9 Likes

Both… Thanks

OK, well the system info card is in the post above yours.

The title is created with a template and it has many configuration options (and I have only coded for one header level so far because I only ever use one!). To get a simple header as I have done, use this:

      - !include
        - templates/titles.yaml
        - title: SYSTEM
          font_family: Oswald
# lovelace_gen

{% set margin_top = margin_top | default('-0.5em') %}
{% set margin_left = margin_left | default('-0.5em') %}
{% set margin_bottom = margin_bottom | default('-0.5em') %}
{% set background_color = background_color | default('transparent') %}
{% set font_family = font_family | default('var(--primary-font-family)') %}
{% set font_size = font_size | default('20px') %}
{% set color = color | default('auto') %}
{% set padding_left = padding_left | default('0.5em') %}
{% set border_left_color = border_left_color | default('rgba(255, 155, 0)') %}
{% set border_left = border_left | default('3px solid') %}
{% set box_shadow = box_shadow | default('none') %}

# Define header level
{% set header_level = header_level | default('2') %}
{% set mapper = {'1':'#','2':'##','3':'###','4':'####','5':'#####','6':'######'} %}
{% set header_level = mapper[header_level] %}

type: markdown
style: |
  ha-card {
    margin-top: {{ margin_top }};
    margin-left: {{ margin_left }};
    margin-bottom: {{ margin_bottom }};
    background-color: {{ background_color }};
    box-shadow: {{ box_shadow }};
  }
  h2 {
    font-family: {{ font_family }};
    font-size: {{ font_size }};
    font-weight: 100;
    color: {{ color }};
    padding-left: {{ padding_left }};
    border-left: {{ border_left }} {{border_left_color}};
  }
content: >
  {{ header_level }} {{ title }}

If you don’t want a template, hopefully you’ll be able to work out how to hard code it for your use.

Or this should work:

type: markdown
style: |
  ha-card {
    margin: -0.5;
    background-color: transparent;
    box-shadow: none;
    font-size: 20px;
    font-weight: 100;
    padding-left: 0.5em;
    border-left: 3px solid;
  }
content: >
  SYSTEM
2 Likes

I’m using docker Monitor:

1 Like

this is failing for me can I can how you configured it?

Try this

homeassistant:
  customize:
    package.node_anchors:
      settings: &settings
        switch: true
        sensors:
          - status
          - uptime
          - image
          - cpu_percentage_usage
          - memory_usage
          - memory_percentage_usage
          - network_total_up
          - network_total_down

docker_monitor:
  hosts:
    - url: tcp://192.168.1.61:2375
      name: vmTBSH01
      event: false
      containers:
        duplicati:
         <<: *settings

Are you also running Home Assistant in a container?
If so, you need to give access to the socket. Add the following volume to your home assistant container:


 -v /var/run/docker.sock:/var/run/docker.sock

I just use bash scripts to return docker stats in JSON format and use command line sensors to get them into HA myself, less fuss for me.

Are you able to share some of your scripts and sensors as I’m struggling with the docker monitor component?

I recently reworked them into MQTT sensors, basicly it’s dumping docker stats into MQTT sensors and i pull them from there.

Would still appreciate anything you can share as I’m stuck on getting this to work?

Sure thing first off I have bash scripts on my docker hosts:

#!/bin/bash

mqttbroker=[redacted]
mqttuser=[redacted]
mqttpwd=[redacted]

data=`docker stats --no-stream --format '"{{.Name}}": {{json .}},'`
data=${data%?}
data=`echo \{ ${data} \} | jq '.'`

for row in $(echo $data | jq '.[].Name'); do
        text=$(echo $data | jq ".$row" | tr -d %)
        state=$(echo "{\"value\": \"Ok\"}" | jq '.')
        container=$(echo $row | tr -d \")
        mosquitto_pub -h $mqttbroker -u $mqttuser -P $mqttpwd -t docker/$container/state -m "$state" -r
        mosquitto_pub -h $mqttbroker -u $mqttuser -P $mqttpwd -t docker/$container/attributes -m "$text" -r
done

# echo $data

Then I have an automation fire off:

- alias: Update Docker Stats
  trigger:
  - platform: homeassistant
    event: start
  - platform: time_pattern
    seconds: '/30'
  action:
  - service: shell_command.update_dh2
  - service: shell_command.update_dh

Those shell commands are here:
(note: I use ssh keys so passwords are not needed to execute remote commands)

update_dh2: 'ssh root@[redacted] /root/docker_stats.sh'
update_dh: 'ssh root@[redacted] /root/docker_stats.sh'

Then my MQTT sensors:

# Docker MQTT Sensors
- platform: mqtt
  name: docker_zoneminder
  state_topic: "docker/zoneminder3/state"
  json_attributes_topic: "docker/zoneminder3/attributes"
  value_template: "{{ value_json.value }}"

- platform: mqtt
  name: docker_mariadb
  state_topic: "docker/mariadb/state"
  json_attributes_topic: "docker/mariadb/attributes"
  value_template: "{{ value_json.value }}"

- platform: mqtt
  name: docker_portainer
  state_topic: "docker/portainer/state"
  json_attributes_topic: "docker/portainer/attributes"
  value_template: "{{ value_json.value }}"

I have them display like so:

First the decluttering card bit:

decluttering_templates:
  docker_entity_template:
    card:
      entities:
        - entity: '[[entity]]'
          icon: 'mdi:server'
          name: Status
        - attribute: NetIO
          entity: '[[entity]]'
          icon: 'mdi:ethernet'
          name: Network In/Out
          type: attribute
        - attribute: MemUsage
          entity: '[[entity]]'
          icon: 'mdi:memory'
          name: Memory Usage
          type: attribute
        - entities:
            - attribute: CPUPerc
              decimal: '2'
              entity: '[[entity]]'
              height: 25px
              icon: 'mdi:cpu-64-bit'
              max: '100'
              min: '0'
              name: CPU Usage
              severity:
                - color: var(--label-badge-green)
                  from: '0'
                  to: '40'
                - color: orange
                  from: '40'
                  to: '65'
                - color: var(--label-badge-red)
                  from: '65'
                  to: '100'
              unit_of_measurement: '%'
          entity_row: true
          style: |-
            bar-card-name {
              font-weight: bold; 
              text-shadow: 2px 2px 2px black;
            }
            bar-card-value {
              font-weight: bold;   
              text-shadow: 2px 2px 2px black;
            } 
              animation:
                state: 'on'    
          type: 'custom:bar-card'
        - entities:
            - attribute: MemPerc
              decimal: '2'
              entity: '[[entity]]'
              height: 25px
              icon: 'mdi:memory'
              max: '100'
              min: '0'
              name: Memory Used
              severity:
                - color: var(--label-badge-green)
                  from: '0'
                  to: '40'
                - color: orange
                  from: '40'
                  to: '65'
                - color: var(--label-badge-red)
                  from: '65'
                  to: '100'
              unit_of_measurement: '%'
          entity_row: true
          style: |-
            bar-card-name {
              font-weight: bold; 
              text-shadow: 2px 2px 2px black;
            }
            bar-card-value {
              font-weight: bold;   
              text-shadow: 2px 2px 2px black;
            } 
              animation:
                state: 'on'
          type: 'custom:bar-card'
      title: '[[name]]'
      type: entities

And now the actual card:

template: docker_entity_template
type: 'custom:decluttering-card'
variables:
  - entity: sensor.docker_zoneminder
  - name: ZoneMinder

rinse and repeat the cards.

4 Likes

This is amazing, thanks so much!

1 Like

Just a side note, the usage of mqtt over using the REST API in HA was due to future planning on moving my venv setup to a docker instance that way I don’t have to modify the bash scripts.

Maybe a silly question but why do you have two shell commands? dh and dh2?

2 servers running docker

@klogg do you mind sharing how you build your supervisor_updates sensor?
Would be interested! Thanks

There is a whole thread on this here so it is not my own work and there is a lot more there than I use. I suggest you take a look :slight_smile:

#============
#=== Sensors
#============
sensor:
  # Sensor to track available updates for supervisor & addons
  - platform: command_line
    name: Supervisor updates
    command: 'curl http://supervisor/supervisor/info -H "Authorization: Bearer $(printenv SUPERVISOR_TOKEN)" | jq ''{"newest_version":.data.version_latest,"current_version":.data.version,"addons":[.data.addons[] | select(.version != .installed)]}'''
    value_template: "{{ value_json.addons | length }}"
    json_attributes:
      - newest_version
      - current_version
      - addons

  # Sensors to track updates to other core components (audio, dns and CLI)
  - platform: command_line
    name: Updater Audio
    command: 'curl http://supervisor/audio/info -H "Authorization: Bearer $(printenv SUPERVISOR_TOKEN)" | jq ''{"newest_version":.data.version_latest,"current_version":.data.version}'''
    value_template: "{% if value_json.newest_version != value_json.current_version %}on{% else %}off{% endif %}"
    json_attributes:
      - newest_version
      - current_version

  - platform: command_line
    name: Updater DNS
    command: 'curl http://supervisor/dns/info -H "Authorization: Bearer $(printenv SUPERVISOR_TOKEN)" | jq ''{"newest_version":.data.version_latest,"current_version":.data.version}'''
    value_template: "{% if value_json.newest_version != value_json.current_version %}on{% else %}off{% endif %}"
    json_attributes:
      - newest_version
      - current_version

  - platform: command_line
    name: Updater CLI
    command: 'curl http://supervisor/cli/info -H "Authorization: Bearer $(printenv SUPERVISOR_TOKEN)" | jq ''{"newest_version":.data.version_latest,"current_version":.data.version}'''
    value_template: "{% if value_json.newest_version != value_json.current_version %}on{% else %}off{% endif %}"
    json_attributes:
      - newest_version
      - current_version

  # Alternate updater sensor for core since binary_sensor.updater is very slow to recognize updates
  - platform: command_line
    name: Updater Core
    command: 'curl http://supervisor/core/info -H "Authorization: Bearer $(printenv SUPERVISOR_TOKEN)" | jq ''{"newest_version":.data.version_latest,"current_version":.data.version}'''
    value_template: "{% if value_json.newest_version != value_json.current_version %}on{% else %}off{% endif %}"
    json_attributes:
      - newest_version
      - current_version


#===================
#=== Binary Sensors
#===================
binary_sensor:
  - platform: template
    sensors:
      # True if there's an update available for supervisor
      updater_supervisor:
        friendly_name: 'Updater - Supervisor'
        device_class: problem
        entity_id:
          - sensor.supervisor_updates
        value_template: "{{ state_attr('sensor.supervisor_updates', 'current_version') != state_attr('sensor.supervisor_updates', 'newest_version') }}"
        availability_template: "{{ (states('sensor.supervisor_updates') | int(-1)) > -1 }}"

      # True if there's updates available for any HACS components
      updater_hacs:
        friendly_name: 'Updater - HACS'
        device_class: problem
        entity_id:
          - sensor.hacs
        value_template: "{{ states('sensor.hacs') | int > 0 }}"

      # True if there's updates available for any addons
      updater_addons:
        friendly_name: 'Updater - Addons'
        device_class: problem
        entity_id:
          - sensor.supervisor_updates
        value_template: "{{ states('sensor.supervisor_updates') | int > 0 }}"

2 Likes