Ontdek openHAB 2 – Verbeter je smart home met je Java skills

Als je thuis wat domotica hebt geïnstalleerd, dan is de kans groot dat je daarbij ook een centrale server hebt draaien, waarmee je alle systemen met elkaar kunt laten praten. Er zijn ondertussen veel applicaties beschikbaar die deze rol kunnen vervullen, bijvoorbeeld Domoticz (C++), Home Assistant (Python) en FHEM (Perl). Maar bij een Javaan gaat het hart natuurlijk sneller kloppen als die server in Java is geschreven. Dan kom je uit bij openHAB, waarvan sinds begin dit jaar versie 2 beschikbaar is. Voor een introductie op openHAB verwijs ik je graag naar het prima intro artikel “OpenHAB voor je Intranet of Things” van Jeroen Hendricksen in Java Magazine 2016-3 (uiteraard ook online te lezen, zie referenties onderaan). In dit artikel gaan we dieper in op wat de verbeteringen in openHAB 2 zijn en hoe je je Java skills kunt gebruiken om je eigen smart home ervaring nog verder te verbeteren.

Erik Mulder

 

Nieuwe features in openHAB 2

Een belangrijk verschil met openHAB 1 is de introductie van het concept ‘Thing’. Een Thing representeert, zoals het woord al zegt, een ding uit de ‘echte’ wereld. Elk Thing biedt één of meerdere ‘Channels’ om data van op te vragen en/of naar te versturen. Bijvoorbeeld een Hue lamp heeft een Channel ‘Color’ waar je de huidige kleur aan kunt opvragen of een andere kleur aan kunt geven. Maar ook een smart switch (aan/uit), je telefoon (beschikbaar op netwerk), en bijvoorbeeld de stand van de zon (graden boven/onder de horizon) kunnen een Thing met bijbehorende Channels zijn. Met dit voorbeeld zou je als de zon onder gaat je smart switch kunnen bedienen om het licht aan te doen, behalve als je telefoon niet aangemeld is op het lokale netwerk (oftewel: je niet thuis bent).

Het concept ‘Item’ uit openHAB 1 bestaat nog steeds, maar is niet meer direct gekoppeld aan de fysieke wereld. Je moet daarvoor de state van een Item laten synchroniseren met één van de Channels van een Thing via een ‘Link’, zie figuur 1. Maar je kunt ook een geheel virtueel Item maken dat bijvoorbeeld reageert op de veranderingen in één of meer andere Items. Deze ontkoppeling geeft je veel meer vrijheid om complexere logica te maken in openHAB 2.

 

Figuur 1: De concepten van openHAB 2: abstract (boven) en een voorbeeld (onder)

 

Een laatste nieuwe feature die het noemen waard is gaat over de UI. Naast de Classic UI (geïnspireerd op een oude iOS versie) is er nu ook de nieuwe, frisse Basic UI (gebaseerd op Material Design Lite). Maar belangrijker nog is de introductie van de Paper UI, die je in staat stelt openHAB in je browser te configureren. Things worden waar mogelijk automatisch ‘discovered’ en ook het aanmaken en linken van Items kun je in de Paper UI regelen, zie figuur 2. Zelfs rules kun je (deels) grafisch in elkaar klikken met de experimentele Rule Engine. Dus als je een redelijke straight-forward setup hebt, hoef je met openHAB 2 helemaal niet meer handmatig de configuratie files met hun foutgevoelige syntax te editen! Het enige nadeel is dat de grafisch gedefinieerde configuratie op een andere plek op disk wordt opgeslagen dan je handmatige configuratie. Dus als je beide gebruikt, heb je minder makkelijk een totaaloverzicht.

 

Figuur 2: Grafisch configureren van Things en Items in de Paper UI

 

Uitbreiden

Maar wat nou als je juist wel een ingewikkelde setup hebt of wilt, bijvoorbeeld een script met complexe logica of het koppelen van niet standaard apparaten of eigen hobby projecten? Ook dat kan met openHAB 2. En hier komt het natuurlijk goed van pas dat het systeem in Java gebouwd is, want dat is ook de taal die we kunnen gebruiken om het uit te breiden. Hieronder zullen we twee mogelijke uitbreidingen nader bespreken: het schrijven van Rules en het implementeren van een custom Binding.

 

Rules

Met Rules kun je je smart home ook echt ‘smart’ maken. Ze werken nog grotendeels hetzelfde als in openHAB 1, namelijk via *.rules configuratie files die je zelf schrijft. Je kunt hiervoor een willekeurige text editor gebruiken, maar er is nu ook Eclipse SmartHome Designer, die je syntax highlighting en context support geeft. De syntax van de Rules is gebaseerd op XTend, een sterk op Java gebaseerde script-achtige taal, waarin je heel compact, leesbaar en expressief code kunt schrijven. Een simpel voorbeeld van een Rule is het aan en uitzetten van een lamp op basis van een bepaalde trigger. Zo heb ik zelf de lamp in de voorraadkast van mijn kelder gekoppeld aan een KlikAanKlikUit deursensor, zie listing 1. Toevallig kan ik hier handig direct de sensor state gebruiken als argument voor sendCommand, omdat beide werken met de enum waarden ON en OFF.

 

rule “Door Sensor – Basement Closet”

when

  Item Door_Sensor__Basement_Closet changed

then

  Hue_Light__Basement_Closet__White.sendCommand(

      Door_Sensor__Basement_Closet.state)

end

Listing 1: Rule voor de koppeling van een deursensor en een lamp

 

Als Javaan ziet deze code er niet direct heel herkenbaar uit, maar hier is dan ook sprake van een simpele rule-when-then-end constructie zonder verdere scripting. De lange namen met de vele underscores zijn mijn persoonlijke keuze voor de identifiers van Items. Deze zijn impliciet in al je Rules beschikbaar als ‘variabelen’ waar je properties van kunt opvragen (zoals hier ‘state’) en methodes op kunt aanroepen (zoals hier ‘sendCommand’).

Een ingewikkelder voorbeeld vind je in listing 2. Hiermee kunnen mijn kinderen thuis de zogenaamde ‘disco’ starten. Dit komt neer op elke seconde alle lampen in de woonkamer een willekeurige kleur geven. Ik heb dit tevens gekoppeld aan Amazon Alexa, zodat ze met een simpel “Alexa, disco on” zelf de lichteffecten met bijbehorende muziek kunnen starten. Uiteraard te overrulen door een volwassene.

import java.util.*

rule “Disco”

when

  Item Disco_Timer received command OFF

then

  val rnd = new Random

  val lights = Arrays.asList(Hue_Light_1, Hue_Light_2, Hue_Light_3)

  for (light : lights) {

    val color = HSBType.fromRGB(

        rnd.nextInt(255), rnd.nextInt(255), rnd.nextInt(255))

    light.sendCommand(color)

  }

  Disco_Timer.sendCommand(ON)

end

Listing 2: Rule voor een disco effect met Hue lampen (lamp Item namen ingekort, initiële timer trigger weggelaten)

 

Naast de lamp Items wordt er in deze Rule ook gebruik gemaakt van abstracte Items, die niet direct aan een fysiek ding gekoppeld zijn. In dit geval een timer, waarmee we de disco effecten kunnen herhalen. Je mag bij het uitvoeren van een Rule script namelijk niet in een (oneindige) lus blijven hangen. Verder herkennen we nu wel duidelijk Java code in het script gedeelte. We maken onder andere gebruik van het Collections framework en de Random class. Binnen de code van de Rules kun je eigenlijk alles doen wat ook in een normaal Java programma mogelijk is. En eerlijk gezegd vind ik de XTend syntax en sterke type inference nog makkelijker en simpeler ook.

Je kunt je voorstellen dat je op deze manier met openHAB 2 en je Java skills veel leuke en interessante Rules kunt maken, waarmee je allerlei onderdelen van je smart home met elkaar kunt verbinden. Enkele voorbeelden: je slimme deurbel uitzetten als je kinderen slapen, automatisch bepaalde apparaten uitzetten als er niemand thuis is of een compleet ochtend ‘wake up’ script voor de lampen, gordijnen, koffiemachine, etc.

 

Custom binding

Een concept van openHAB dat we nog niet hebben genoemd is een ‘Binding’. Een Binding is een implementatie van de verbinding tussen openHAB en een apparaat of service. De grote hardware fabrikanten hebben allemaal een Binding voor hun eigen apparaten, zoals Philips, Samsung, Miele, Sonos, etc. Het kan echter ook een Binding naar een service zijn, zoals Yahoo Weather, NTP of zelfs voor het gebruik van het MQTT protocol. Veel van de Bindings zijn forward compatible of omgeschreven van openHAB 1 naar openHAB 2.

Op dit moment zijn er al ruim 200 Bindings beschikbaar, waarmee je waarschijnlijk de meeste van je slimme apparaten wel kunt koppelen. Maar misschien heb je een wat obscuur slim apparaat in huis of wil je een ‘dom’ apparaat graag zelf slim maken. Of heb je zelf een leuk hobby projectje gemaakt met een Raspberry Pi, zoals een planten bewatering systeem of lichtkrant LED display. Meestal kun je deze apparaten en systemen prima los bedienen met een app of API call, maar een smart home wordt pas echt leuk als je al je slimme onderdelen kunt laten samenwerken. En aangezien openHAB 2 het punt is waarop alles samenkomt, is het wellicht een idee om zelf een Binding te schrijven om jouw apparaat of systeem eenvoudig te kunnen gebruiken in de openHAB UI en Rules. Het kan tevens een mooie bijdrage zijn aan de openHAB community om je Binding te delen.

Het volledig uitwerken van een custom Binding gaat voor nu te ver, maar we zullen hier een voorzet geven van hoe dat ongeveer in zijn werk gaat. Je start met het genereren van een skeleton project op basis van de Binding naam (zie referentie Custom Bindings onderaan). De kern van een Binding is het vertalen van een event uit het Eclipse SmartHome framework naar het externe systeem en vice versa. Jouw apparaat of systeem moet je representeren als één of meerdere Things. Naast wat XML configuratie voor de naam, omschrijving, beschikbare Channels, etc. van deze Things moet je per Thing een implementatie van de ThingHandler interface maken, zie listing 3.

 

@Override

public void handleCommand(ChannelUID channelUID, Command command) {

    if (command instanceof RefreshType) {

        switch (channelUID.getId()) {

            case CHANNEL_TEMPERATURE:

                updateState(channelUID, getTemperature());

                break;

            case CHANNEL_HUMIDITY:

                […]

        }

    }

}

Listing 3: Een voorbeeld implementatie van de ThingHandler voor een weerservice

 

Aangezien we hier in een Java context zitten, kun je bij de verdere implementatie volledig gebruik maken van je favoriete Java packages en gewenste dependencies. Als je de Binding ook aan de rest van de community beschikbaar wilt stellen, moet je wel enkele coding en documentatie guidelines in acht nemen en mag je Binding geen proprietary code of dependencies bevatten.

Als je de Binding implementatie volledig afgerond en gedeployed hebt, kun je het apparaat of systeem via de vertrouwde openHAB UI en Rules integreren met de rest van je smart home.

 

Eclipse SmartHome

Als je echt van customizen houdt, kun je zelfs nog verder gaan en openHAB zelf aanpassen of uitbreiden. Alles is open source en op basis van het Eclipse SmartHome framework, dat meer dan genoeg handvatten biedt voor uitbreiding. Je zou hierbij bijvoorbeeld kunnen denken aan een custom UI control panel of het integreren van externe systemen die niet binnen het Binding concept passen.

 

Conclusie

Wat mij betreft is openHAB 2 een zeer geslaagde opvolger, waarbij met het onderscheid tussen een Thing en een Item veel extra flexibiliteit is toegevoegd. Ook is de drempel om met openHAB te beginnen flink verlaagt, doordat je de meeste configuratie nu gewoon via een web interface kunt doen. Daarnaast is het voor jou als Java developer erg prettig dat je bij Rules en uitbreidingen je Java skills kunt gebruiken om je wildste smart home fantasieën te realiseren!

 

Referenties

OpenHAB voor je Intranet of Things – https://nljug.org/databasejava/openhab-voor-je-intranet-things/

Grafische Rule Engine – http://docs.openhab.org/configuration/rules-ng.html

Eclipse SmartHome Designer – http://docs.openhab.org/installation/designer.html

XTend – http://www.eclipse.org/xtend/

Custom Bindings – http://docs.openhab.org/developers/development/bindings.html