HABApp - Easy automation with openHAB

habapp
Tags: #<Tag:0x00007f014818dda0>

(Sebastian) #1

Hello,

since I started with it has always been puzzling to me how hard it is to write automation rules in openHAB.
Things got a little bit better with the jsr223 integration and I think @steve1 contributed some great ideas.
But with openHAB2 and the new API things got worse again and unfortunately even after long hours I did not manage to migrate my jython rules. Also jython has lots of drawbacks and is syntactically python2.
I even tried HomeAssistant because and even though it has lots of pros thanks to the great Z-Wave work of @chris I am back on the openHAB track (if someone is interested I can write a small comparison of openHAB and HomeAssistant).
But whilst trying HomeAssistant I managed to get some fresh ideas and point of views and I still really wanted to create my rules in Python.

This is why created HABApp.

It is a multithreaded, asyncIO based automation framework which allows easy and fast creation of rules.
HABApp connects to openHAB through the Rest-API and therefore allows quick and seamless integration and transition.
This approach has the great benefit that any python library can be easy loaded and integrated into the automation rules.

Installation
Installation is very easy. Just create a python virtual environment and install HABApp through pip.
I have created a small description on the PyPI site.

Usage
Creating rules is easy. Just derive a class from HABApp.rule. Use the self.listen_event function to register function calls when items change or receive updates. All interaction is done through the HABApp.Rule class and thus available through self.
Example:

import HABApp
from HABApp.openhab.events.item_events import ItemStateEvent

class MyRule(HABApp.Rule):
    def __init__(self):
        super().__init__()

        # Subscribe to ItemStateEvent for item TestSwitchTOGGLE
        self.listen_event( 'TestSwitchTOGGLE', self.cb, ItemStateEvent)

    def cb(self, event):
        print( f'CALLBACK: {event}')
        assert isinstance(event, ItemStateEvent)
        self.post_Update('MyOtherItem', 'test')

MyRule()

The following functions are currently implemented:

# Listen for events
self.listen_event(item_name, callback, None)
self.listen_event(item_name, callback, even_type)

# Interact with openhab
self.post_Update(item_name, value)
self.send_Command(item_name, value)
self.item_exists(item_name)
self.item_state(item_name)
self.item_create(item_type, item_name)
self.remove_item(item_name)

# Time intervalls
self.run_every( date_time, interval, callback)
self.run_on_day_of_week(time, ['Mon,Tue'], callback)
self.run_on_workdays(time, callback)
self.run_on_weekends(time, callback)
self.run_daily(callback)
self.run_hourly(callback)
self.run_minutely(callback)
self.run_at(date_time, callback)
self.run_soon(callback)

# get another rule by name
self.get_rule(rule_name)

HABApp is currently still in beta, but I think this approach is interesting to more people.
It would be nice if I could get some feedback on the idea in general and on the current implementation status.


OH2/ESH DMX binding
(Psyciknz) #2

Are you thinking of making a gui based rules editor that is similar to the home assistant one?

I also have feet In Both camps, it came to the conclusion it was easier to run both, and use the mqtt event bus to send and receive event from openHAB to ha, so that if you liked their automations you could write them in ha and operate oh items.


(Sebastian) #3

No - this is out of scope for me. There are already several very nice solutions for this (e.g. NodeRed).
Also if you look at the example it is just a simple class definition - it’s just five lines to get started.
What I might do is the ability to subscribe to MQTT and process/publish the events just like openHAB events.
This would provide some more flexibility.


(Sebastian) #4

I added the possibility to connect to an MQTT broker directly in HABApp:

import HABApp
from HABApp.core.events import ValueChangeEvent, ValueUpdateEvent

# MQTT example
class MyMQTTRule(HABApp.Rule):
    def __init__(self):
        super().__init__()

        # Subscribe to topic but only process changes
        self.listen_event( 'test/topic1', self.cb, ValueChangeEvent)

    def cb(self, event):
        assert isinstance(event, ValueChangeEvent)
        self.mqtt_publish( 'test/topic2', event.value + 1)

MyMQTTRule()

(Nicholas Waterton) #5

This looks really nice,

I have quite a few python servers all reading item states and forwarding then to various other devices, both into and out of OH.

They used to use websockets, until that was dropped, now they use complicated requests to get data from/to the REST interface.

One interface first discovers all items, then uses streaming to get updates and push the results as json to an iPad used as an interface.

All of this stuff would have been much easier with this library.

Suggestion, add a way of getting items and groups from OH, so that you can automate item discovery. Otherwise you constantly have to update item names in two locations (OH and HABapp application).

It’s fairly easy to do via REST, but parsing the massive dictionary you get back is a bit of a task.

I have 3 or 4 applications where I could use this immediately. I normally use mqtt because the REST interface is a pain. This looks like it may ease the pain.

If it uses asyncio, what version of python do you need (I use 3.6), and is it Thread safe?

Great work by the way. I will try this out tomorrow, I have a use for it right now!


(Sebastian) #6

Hi, first of all beware this is currently beta. Things might still change.
Currently HABApp requires Python 3.6 so you should be good to go.
Maybe it would be easier for you to get an MQTT server running so you can communicate between all your devices? HABApp works seamlessly with them.

This is already done and you can access the local cache with

self.item_exists(item_name)
self.item_state(item_name)

If I understand you correctly you want to subscribe to all changes so you can forward them.
I could add a function which just returns all items. You could use this to listen to all updates.
What do you think?

What do you mean with thread safe?


(Sebastian) #7

Hi,

while migrating my rules I found some bugs when creating invalid rules.
Bugfix is already available (0.0.5)


(Sebastian) #8

I have uploaded Version 0.1.1 which includes a couple of fixes and improvements.

Having migrated almost all of my rules I have to say I am very happy.
HABApp is really fast and easy on the system (< 35 MB RAM usage).
But most importantly writing rules is fun again! :slight_smile:

It would be really nice If someone else could try it out - I’d really love some feedback!


(Morten P) #9

Is this meant to be an equivalent to Appdaemon in the Home Assistant world? My house is primarily z wave based, so I have often thought about trying out Openhab again, but I am pretty happy with appdaemon.

Perhaps a bit off topic, but how is you impression of the difference of the two systems and what makes z wave better on openhab in your opinion?


(Sebastian) #10

That’s exactly what it is! Although I tried to make it better (of course :wink: ).
The nice thing is that openhab runs Z-Wave under any OS, so you can just shut down your HassIO instance and boot openhab on your main computer and try stuff out. Once you are done you plug the z-wave stick back into your HassIO instance and everything is back to the way it was.
That’s actually how I do my migraion from openhab1 at the moment :slight_smile:

Z-Wave on openhab just runs - no need to fuddle around with openzwave, entity configuration. For Z-Wave to work I had very long restart times, I don’t have with openhab. Also inclusion/exclusion of devices and setting device configuration is much easier. Having to rename the automatically created entities was a pain, too. The energy consumption of devices did often not work, since the “senser_multilevel” instead “meter_w” command class is required. Also the automatically created entities did not always work properly (I have a heating controller that did not work with Hass).
Since it is possible to do textual configuration of the devices and things the Z-Wave configuration is persistent and nice again (although not as mighty as in openhab1).