Installing the HADashboard on Home Assistant

After having used Home Assistant  for a few weeks I wondered whether these was a “nicer” front end or dashboard.  A bit of Googling and I found this…. https://www.home-assistant.io/docs/ecosystem/hadashboard/.

This takes you to the install for Appdaemon here https://appdaemon.readthedocs.io/en/stable/DASHBOARD_INSTALL.html.  This then directs you to the install site here https://www.home-assistant.io/docs/configuration/packages/.

Installing Appdaemon

The instructions are pretty clear to start with.

1.  Install appdaemon using pip3 ($ sudo pip3 install appdaemon)

but then it gets a little confusing (well to me) as it starts discussing development builds etc and then goes down to running the app and indicates a link to /home/homeassistant/conf.
Well on checking I do not have that directory.

So you then need to go back to the 2nd link I posted above. https://appdaemon.readthedocs.io/en/stable/DASHBOARD_INSTALL.html and look firther down the are some instructions in a different section called configuration.  https://appdaemon.readthedocs.io/en/stable/CONFIGURE.html follow the instructions there.

  1.  Set up a new directory /home/homeassistant/conf
  2. Create appdaemon.yaml and populate this
  3. Go to Home Assistant and create a Long Lived Access Token.  The instructions on how to do this are on the same page but at the bottom
  4. Update the appdaemon.yaml with this token
  5. Skips over the section on Filters (I guess in the future I may come back to this)
  6. MQTT is added
  7. Test App added

Back to the installation instructions and changes made to get the service starting at boot time.

  • $ sudo nano /etc/systemd/system/appdaemon@appdaemon.service
  • Create the file replacing the user bit %I and the <full path to config directory>
[Unit]
Description=AppDaemon
After=home-assistant@homeassistant.service
[Service]
Type=simple
User=%I
ExecStart=/usr/local/bin/appdaemon -c <full path to config directory>
[Install]
WantedBy=multi-user.target
  • $ sudo systemctl daemon-reload
  • $ sudo systemctl enable appdaemon@appdaemon.service –now
  • $ sudosystemctl start appdaemon@appdaemon.service

Installing the Dashboard

Now back here https://appdaemon.readthedocs.io/en/stable/DASHBOARD_INSTALL.html.

The appdaemon.yaml file need updating again.  This time with

hadashboard:  
dash_url: http://192.168.1.20:5050
dash_ssl_certificate: /etc/letsencrypt/live/somehost/fullchain.pem
dash_ssl_key: /etc/letsencrypt/live/somehost/privkey.pem
dash_password: !secret dash_password
dashboard_dir: /home/homeassistant/conf/dashboards

Add a new directory /home/homeassistant/conf/dashboards and create a new file hello.dash and add this to it:

 

##
## Main arguments, all optional
##
title: Hello Panel
widget_dimensions: [120, 120]
widget_margins: [5, 5]
columns: 8

label:
    widget_type: label
    text: Hello World

layout:
    - label(2x2)

You can now navigate to the url e.g. http://192.168.1.20:5050.

Owl Intuition, logging to Mosquitto and Home Assistant

So thanks to Google again and the Home Assistant wiki I now have the Owl Intuition Solar readings being sent to Mosquitto and used as a series of sensors in Home Assistant.

Starting point was this wiki entry and the entry by jchasey. https://community.home-assistant.io/t/owl-intuition-pv-home-assistant/18157/3.

The python script was amended to take solar reading and not hot_water and heating.

import socket
import struct
import json
from xml.etree import ElementTree as ET

OWL_PORT = 22600
OWL_GROUP = "224.192.32.19"

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind((OWL_GROUP, OWL_PORT))
mreq = struct.pack("=4sl", socket.inet_aton(OWL_GROUP), socket.INADDR_ANY)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)

while True:
    # Collect the XML multicast message
    xml, addr = sock.recvfrom(1024)
    # Parse the XML string
    root = ET.fromstring(xml)

    # print (root)

    # Only process those messages we are interested in

    if root.tag == 'electricity':
      timestamp_value = 0
      timestamp = root.find('timestamp')
      if timestamp is not None:
           timestamp_value = int(timestamp.text)
           #print ("time", timestamp_value)
        
      signal_rssi_value = 0
      signal_lqi_value = 0
      signal = root.find('signal')
      if signal is not None:
        signal_rssi_value = int(signal.attrib["rssi"])
        signal_lqi_value = int(signal.attrib["lqi"])
        #print ("rssi", signal_rssi_value)
        #print ("lqi", signal_lqi_value)

      battery_value = 0.0
      battery = root.find('battery')
      if battery is not None:
        battery_value = float(battery.attrib["level"].rstrip("%"))
        #print ("battery value", battery_value)

      for chan in root.iter('chan'):
        #print (chan.attrib)
        
        chanid = chan.get('id')
        #print ("chandid", chanid)
        if chanid == "0":
          current_now = 0.0
          current = chan.find('curr')
          if current is not None:
              current_now = float(current.text)
              #print ("current now", current_now)
          current_day = 0.0
          current = chan.find('day')
          if current is not None:
              current_day = float(current.text)
              #print ("current day", current_day)

        if chanid == "1":
          solar_now = 0.0
          solar = chan.find('curr')
          if solar is not None:
              solar_now = float(solar.text)
              #print ("solar now", solar_now)
          solar_day = 0.0
          solar = chan.find('day')
          if solar is not None:
              solar_day = float(solar.text)
              #print ("solar day", solar_day)

    if root.tag == 'solar':
        solar_exported = 0.0
        solar = root.find('day/exported')
        if solar is not None:
            solar_exported = float(solar.text)
            #print ("solar export", solar_exported)
            print (json.dumps({'type': root.tag, \
                       'timestamp': timestamp_value, \
                       'battery_level': battery_value, \
                       'current_now': current_now, \
                       'current_day': current_day,\
                       'solar_now': solar_now,\
                       'solar_day': solar_day,\
                       'solar_exported': solar_exported}))
            

I then added a shell script to run the python.  This was placed into /usr/local/bin with permission at 0400.

#!/bin/sh
#
# owl_mcast2mqtt.sh
#
# Publish json output of the owl_mcast2json script to MQTT 
#
export LANG=C
PATH="/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin"

MQTT_HOST="ip.address.0.0"
MQTT_PORT="8883"
MQTT_USER="xxx"
MQTT_PASS="xxx"

echo "OWL Network Multicast 2 MQTT"

python3 -u /usr/owlintuition/owl.py | while read line
do
	MQTT_TOPIC="tele/home/mcast/$(echo $line | jq --raw-output '.type')"
	# Publish the json to the appropriate topic
	echo $line | mosquitto_pub -h $MQTT_HOST -p $MQTT_PORT -u $MQTT_USER -P $MQTT_PASS -i OWL_MCast -r -l -t $MQTT_TOPIC
done

A service was then created and enabled.

[Unit]
Description=OWL MQTT store
After=suspend.target

[Service]
User=root
Type=oneshot
ExecStart=/usr/local/bin/owl_mcast2mqtt.sh
TimeoutSec=0
StandardOutput=syslog

[Install]
WantedBy=suspend.target

Strangely after a power cut all the above “disappeared”.

Mosquito needed reinstalling – link here https://www.switchdoc.com/2018/02/tutorial-installing-and-testing-mosquitto-mqtt-on-raspberry-pi/

jq needed installing – link here https://stedolan.github.io/jq/download/

This is a useful reminder for getting scripts working – https://www.raspberrypi.org/forums/viewtopic.php?t=197513