Simple sensor scripting - addon, platform or appdeamon - SOLVED

hi,

After switching to hass.io I still struggle a bit. I used to have a sensor - file based template that was reading the number of free bicycles at my railstation.

I had a python script that read a webpage and created an easy readable json to the file template sensor and voila: magic!

Now, the options are a bit overwhelming and I admit I’ve only tested the first one;

  • addon: retrieving the html and saving it to my addon data folder works, however cat data command says the file does not exist. When I go into the container through ssh I can cat the downloaded file and it has the information I expected. (I still need to extract the value and mosquitto_pub it to my sensor)

  • platform: way too complacated for now I’m afraid

  • appdeamon: there is documentation available so it might be an option.

Which would be the simplest route to tackle this one? I haven’t even started scheduling it every half hour.

Thx!
Jhh

Wouldn’t be much work to use one of these from the sound of it:

hi,

Python scripts was a good suggestion - in fact it is what I was almost using. Put my scripts in the python_scripts folder but forgot to put in python: in configuration.yaml file and ended up using them as shell_command.

In the end it looks like that was the way to go anyway as module import is not supported in scripts so I’m stuck again.

Thx!
Jhh

Custom components aren’t too much extra work so long as you are comfortable with object oriented programming.
Cheers

You can also try my (quite new and not polished) python executor addon. I use it to poll value from one wire sensors with pyownet and send the values to influxdb. Before hassio I had the same script triggered by cron, I have added a loop (while True) with a time.sleep(300) to poll the sensor every 5 minutes.

The right approach would have be to create a component to speak with a owserver, but this was quick.

1 Like

bestlibre,

That is exactly what I tried to do - if someone else comes up with it as well it suddenly sounds like a better idea.

Installed the addon and copied the script and it does print the values I expect it to retrieve in the log. Remaining challenge is to send them to a sensor. File or MQTT seem an option, as I can’t write to the shared folder MQTT is a sensible route.

I cannot work out how to convince it to install paho-mqtt - it should go in as a requirement I suppose but I’ve tried colons, comma’s but no joy. Would you mind giving a hint as how that should be passed as an option?

btw - I’m a happy customer of your Grafana/influxdb also - much appreciated have a question on that one also but won’t pollute the thread.

Thx!
Jhh

Do you have any logs? Normally you just need to set the modules as a list of strings.

I have specified the dependency as:

{
  "code": "/share/sensor.py",
  "requirements": [
    "paho-mqtt"
  ]
}

It behaves a bit strange now and then, if you edit the options and you hit save and then you hit save on the network section without changing anything you’ll see the old version of the options appearing.

The log says:

starting version 3.2.2
You must provide a DEST_DIR
Usage: virtualenv [OPTIONS] DEST_DIR
Options:
  --version             show program's version number and exit
  -h, --help            show this help message and exit
  ...

The script itself it pretty straightforward:

import urllib, re

Base_URL = 'https://www.blue-bike.be/nl/rt-out/ajax/227'
WebSock = urllib.urlopen(Base_URL) # Opens a 'Socket' to URL
WebHTML = WebSock.read() # Reads Contents of URL and saves to Variable
WebSock.close() # Closes connection to url

try:
    found = re.compile('strong.u003E(.*?) ./ (.*?).u003C', re.I).findall(WebHTML)
    print (found[0][0]) # Number of bicycles available
    print (found[0][1]) # Number of bicycles 

  if len(found) > 0:
    print ('found')
  except:
    pass

In the end I only need the free number of bicycles so MQTTing the first value to an MQTT sensor would be the way tho get that in Home Assistant.

Final to-do would be to put the script in a loop or cron its execution.

Thx!
Jhh

Thanks for the logs/ There is a bug on my run.sh script. It will be fix shortly.

Not sure if your remark applies to v 0.1.1 or 0.1.0 - tried to install the update and got:

17-09-22 18:27:19 INFO (SyncWorker_1) [hassio.dock.interface] Pull image bestlibre/armhf-python-exec tag 0.1.1.
17-09-22 18:27:20 ERROR (SyncWorker_1) [hassio.dock.interface] Can't install bestlibre/armhf-python-exec:0.1.1 -> 404 Client Error: Not Found ("manifest for bestlibre/armhf-python-exec:0.1.1 not found").

No idea what that means? Do you prefer feedback on github or in here?

Jhh

Travis build was not triggered. It should start soon.

I’m on my phone, so reaction can be delayed and not always fully successful.

Think this is the most painless way to grab a webpage, extract a number and show it as a sensor in Home Assistant:

install Python Ecexutor from bestlibre with following option setting:

{
  "code": "/share/sensor.py",
  "requirements": [
    "paho-mqtt"
  ],
 "clean": false
}

edit: addon requires new parameter ‘clean’

assume you have samba add-on also and throw sensor.py in the folder shared, it should look like:

import urllib, urllib2, re, time
import paho.mqtt.client as mqtt

while True:

    Base_URL = 'https://www.blue-bike.be/nl/rt-out/ajax/227'
    WebSock = urllib.urlopen(Base_URL)
    WebHTML = WebSock.read() 
    WebSock.close() 

    try:
        found = re.compile('strong.u003E(.*?) ./ (.*?).u003C', re.I).findall(WebHTML)
        mqttc = mqtt.Client("python_sensor")
        mqttc.connect("your mqtt ip", 1883)
        mqttc.publish("home/bluebike", found[0][0])
        mqttc.close

    except:
        pass

    time.sleep(1800)

this will run every half hour and fetch the bluebike web page - the regex retrieves 2 values: available number of bicycles out of total number. I only send the first value to the sensor.

The sensor in configuration.yaml looks like:

- platform: mqtt
  state_topic: "home/bluebike"
  name: Velos
  unit_of_measurement: "bicycles"

Ideally you should have TLS and password enabled for MQTT - this is for a local mosquitto server that allows anonymous access.

Python Executor is very friendly for beginners - whatever you print in your python code will show up in the addon logs.

Thanks bestlibre for providing Python Executor.

ps - I’m not a programmer so code snippets are copied and pasted in and by accident it works.

Jhh

I recently tried to access owserver running on hass.io in the same way you are, but to publish the values to a mqtt broker. Would you mind sharing your setup?

This the code I use :

#!/usr/bin/env python3

import pyownet
import influxdb
import logging
import requests

import asyncio

import time


logger = logging.getLogger(__name__)


name_map = {'28XXXXXXXX': 'name1', '28YYYYYYY': 'name2'}

vmin = -55
vmax = 125


async def sensor_report(owproxy, s_id):
    address = owproxy.read('{}address'.format(s_id)).decode()
    value = float(owproxy.read('{}temperature'.format(s_id)).decode())
    if vmin < value < vmax:
        return {'uuid': address, 'value': value, 'ts': int(time.time())}
    else:
        logger.warning("Value not in range : {}".format(value))
        return None


async def reports_to_influxdb(reports):
    points = [{'measurement': "°C",
               'tags': {'uuid': report.get('uuid'), 'device': 'chip',
                        'name': name_map.get(report.get('uuid'), 'not_set')},
               'time': report.get('ts'),
               'fields': { 'value': report.get('value')}}
              for report in reports if report is not None]
    logger.debug(points)
    influx = influxdb.InfluxDBClient(host='addon_53caca22_influxdb', port=8086, username='lilili',
                                     password='BLALALALA', database='archive',
                                     ssl=False, verify_ssl=False)
    try:
        influx.write_points(points, time_precision='s')
    except influxdb.exceptions.InfluxDBServerError as ie:
        logger.error('InfluxDb error: %s' % ie)


async def sensors():
    pr = pyownet.protocol.proxy("addon_53caca22_owserver")
    while True:
        reports = []
        for s in pr.dir():
            if s is not None:
                m = await sensor_report(pr, s) 
                reports.append(m)
        await reports_to_influxdb(reports)
        await asyncio.sleep(300)
    


if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    asyncio.ensure_future(sensors())
    loop.run_forever()
1 Like

Hi

You can feed the the HASS directly using the REST API like this:

import requests as req

headers = {'Authorization': 'Bearer !secret', 'content-type': 'application/json'}
url = 'https://servername.duckdns.org/api/states/sensor.router_uptime'
data = '{"state": "'+str(uptime)+'", "attributes": {"unit_of_measurement": "hours", "icon": "mdi:clock-start", "friendly_name": "Router Uptime"}}'
response = req.post(url, headers=headers, data=data)

I hope this solution is not arrived too late.

Bye
T

1 Like