What ways are available for communication between AppDaemon and Home Assistant

I have used the excellent @ReneTode examples to make my first python app. It contained just six pieces of data for which it was not a problem to pass them through as attributes in the self.set_state() method.

Now I have made an HTML parser for the Hard Disk Sentinel XML report which has about 50 parameters. I have formated them nicely as a json.dumps(). The list is of variable length +/-6 for each additional hard disk. I would like to be able to keep them connected and organized during the transport.

Is there a way to send them as JSON to HA, and group them visually in Lovelace, or is sending each one individually as an attribute really the only way? I wouldn’t either want 50 sensors for all that data, but it would be nice to have a sensor with attributes for each disk and a sensor with attributes for system data.

HD Sentinel is a excellent little tool for windows that predicts the failure of spinning drives on windows machines, and I use it on all of mine. It publishes a report on its webserver and I have made a scraper that collects vital data from that report. The idea is to use one instance for each computer on the network.

Currently, it looks like this

import appdaemon.plugins.hass.hassapi as hass
import time
import requests
import urllib.request
import re
import json

from datetime import datetime, timedelta
from socket import timeout
from bs4 import BeautifulSoup

class HDS_192_168_0_3(hass.Hass):
  
  def initialize(self):
    
    self.get_values(self)

  def get_values(self, kwargs):
      
    self.url = 'http://192.168.0.3:61220/xml'
    self.sensorname = "sensor.hds_192_168_0_3"
    self.friendly_name = "HD Sentinel IP: 192.168.0.3"
    
    try:
      response = requests.get(self.url, timeout=10)
    
    except:
      self.log("Servis nije dostupan")
      return
    
    soup = BeautifulSoup(response.text, 'html.parser')

    sentinel_ver = soup.hard_disk_sentinel.application_information.installed_version.text

    comp_info = soup.hard_disk_sentinel.computer_information

    comp_name = comp_info.computer_name.text
    uptime = comp_info.system_uptime.text
    up_since = comp_info.system_up_since.text

    sys_info = soup.hard_disk_sentinel.system_information

    win_version = sys_info.windows_version.text
    memory = sys_info.physical_memory_size.text
    graphics = sys_info.display_adapter.text

    disks = soup.hard_disk_sentinel
    diskcount = 0
    diskdata = []

    for disk in disks.find_all(re.compile("^physical_disk_information_disk..")):
      diskdata.append(disk.hard_disk_model_id.text)
      diskdata.append(disk.total_size.text)
      diskdata.append(disk.logical_drive_s.text)
      diskdata.append(disk.current_temperature.text)
      diskdata.append(disk.power_on_time.text)
      diskdata.append(disk.health.text)
      diskdata.append(disk.performance.text)

      diskcount += 1
    
    diskinfo = {}

    i = 0
    j = 0

    for i in range (diskcount) :
    
      diskname = "Disk "+str(i)
      diskinfo [diskname] = {"Model ID": diskdata[(0+i+j)],
                             "Total size": diskdata[(1+i+j)],
                             "Logical drives": diskdata[(2+i+j)],
                             "Current temperature": diskdata[(3+i+j)],
                             "Power-on time": diskdata[(4+i+j)],
                             "Health": diskdata[(5+i+j)],
                             "Performance": diskdata[(6+i+j)]}
      i += 1
      j += 6

    full_info = {}

    full_info = {"Sentinel version": sentinel_ver,
                 "Computer name": comp_name,
                 "Uptime": uptime,
                 "Up since": up_since,
                 "Windows version": win_version,
                 "Memory": memory,
                 "Graphics": graphics,
                 "Disks": diskinfo}
                 

#t = type (comp_info)
#v = (sentinel_ver, comp_name, uptime, up_since, win_version, memory, graphics)
#print (diskcount)
#print (diskdata)
#print (diskinfo)
#print (full_info)
#print (diskname)

#    print (json.dumps(full_info, indent=2, default=str))
    jsonout = json.dumps(full_info, indent=2, default=str)
    timenow = datetime.now()
    
    self.set_state(self.sensorname, state = timenow.strftime('%d.%m.%Y %H:%M:%S'), attributes = {"HD Sentinel Report": full_info})
    
    update_time = timenow + timedelta(minutes = 1)
    
    self.run_at(self.get_values, update_time)

i never work with lovelace, so i cant help you in that area.
but from AD to HA you can send it in any way you like.

you can make 2 sensors that both contain 1 attribute that has all values as json, but normally you just want to send every value as a seperate attribute, so then make 2 sensors that have the attributes you want. (as you do now)

i dont understand where your problem is.
you know how to create a sensor with attributes, as your code shows, and from what i read is that what you want.

i advise to come to the AD discord AppDaemon
i am mostly there (as well as others) so we can discuss there how you could reach your goal.

Thank you for the answer.

i dont understand where your problem is.

I have been thinking about that since you wrote the answer, and I concluded, I am missing some granularity. I think the best would be to divide received data into one sensor for general information about the machine and one for each of the disks, so each sensor won’t have more than 6-7 attributes and it will be easier to to present them. Because, now with this setup I have a huge list of about 50 rows.

you know how to create a sensor with attributes, as your code shows, and from what i read is that what you want.

That’s actually just copy/paste of your code. My only contact with Python a BeautifulSoup tutorial and your AD docs at github. Do you have any example where you create multiple sensors in the same app? I think I can use that to add the desired level of granularity and control.

Also, somewhere you have mentioned that input variables (like url) can be defined in yaml and accessed from AD. If you have an example for that too, it would be most appreciated.

I have joined the discord channel as SaleB#4190, so if it is more convenient for you, you can answer there.

as soon as you got time, just ask your questions on discord and we will respond as soon as possible.

about creating multiple sensors thats actually pretty simple.

this line creates the sensor:

    self.set_state(self.sensorname, state = timenow.strftime('%d.%m.%Y %H:%M:%S'), attributes = {"HD Sentinel Report": full_info})

you can use that as much as you like, so you can use

    self.set_state(self.sensorname1, state = "anything you like", attributes = any_dict)
    self.set_state(self.sensorname2, state = "something else", attributes = any_other_dict)
    self.set_state(self.sensorname3, state = "another value", attributes = third_dict)

all you need is to create 3 dicts in the code before it instead of 1.

thats actually basic AD, that you can find in

the principle is:

  • put a value in yaml like url: “some_url”
  • in the code use self.args[“url”] to get that value.

the value can be anything you like so a string, boolean, integer, float, list or a dict.

1 Like