Artikel Domotica met een Rapsberry Pi en klikaanklikuit

Domotica thuisproject

Een beschrijving van een domotica project dat draait op een Raspberry Pi 3, is geschreven in Kotlin, op afstand bediend kan worden met een iPhone, communiceert met onder andere klikaanklikuit via een RFXCOM en wordt gebouwd en gedeployed in een CI/CD straat die draait in Docker op een Synology NAS. O ja, sinds kort wordt ook de slimme meter uitgelezen en op een LCD display getoond, in prometheus opgeslagen en met grafana getoond.

Hoe het begon

Ik maak al lang gebruik van klikaanklikuit, radiografische afstandsbediening op 433 Mhz, om apparaten, vooral lampen, aan en uit te zetten (of te dimmen). Het bestaat uit zenders en ontvangers. Zenders sturen commando's naar de ontvangers die reageren als het commando voor hen bestemd is. Of een commando bestemd is voor een ontvanger wordt bepaald door het adres dat meegegeven wordt in het commando, elke ontvanger luistert naar één of meerdere adressen. Commando's zijn bijvoorbeeld: aan, aan op 50%, of uit.

In 2011 ben ik verhuisd naar een nieuw huis dat 's avonds erg donker is bij de voordeur waardoor het sleutelgat erg moeilijk te vinden is. Om in het donker beter zicht te hebben heb ik daar verlichting gemaakt die aan en uit gaat via een bewegingssensor van klikaanklikuit. Dus als je in het donker aan komt lopen gaat de verlichting aan, het sleutelgat is makkelijk te vinden en na enige tijd gaat de verlichting weer uit. De bewegingssensor is de zender, die detecteert beweging, en stuurt een 'aan' commando naar de ontvanger, die de verlichting aan zet. Na enige (instelbare) tijd stuurt de beweginssensor ook het 'uit' commando. Het 'uit' commando wordt altijd verstuurd na de ingestelde tijd, ook als er in die tijd nog beweging is geweest.

Voordeur donker Voordeur in het donker

Voordeur met licht Voordeur met licht

'Enige tijd' is maximaal instelbaar op vier minuten. Dat is lang genoeg om je sleutel te zoeken en binnen te komen, maar te kort als je de auto aan het uitladen bent of met iemand bij de voordeur aan het praten. De verlichting gaat dan uit en het duurt even voordat de zender weer een 'aan' commando stuurt als gevolg van beweging. Om een langere tijdsduur tussen 'aan' en 'uit' te kunnen instellen heb ik een Raspberry Pi 3 met RFXCOM tussen de zender en ontvanger gezet en software geschreven die het volgende doet:

  • de zender (klikaanklikuit bewegingssensor) stuurt een 'aan' commando naar de Raspberry Pi via de RFXCOM (het adres in het commando is niet meer dat van de ontvanger),
  • wanneer de Raspberry Pi een 'aan' commando van de zender ontvangt dan stuurt hij een 'aan' commando naar de ontvanger (de verlichting) via de RFXCOM en start een timer van 30 minuten,
  • na 15 seconden (de minimaal instelbare tijd) stuurt de zender een 'uit' commando naar de Raspberry Pi,
  • de Raspberry Pi negeert het 'uit' commando van de zender,
  • wanneer de timer afloopt, stuurt de Raspberry Pi een 'uit' commando naar de ontvanger,
  • als de Raspberry Pi, voor afloop van de timer, een 'aan' commando ontvangt van de zender dan wordt de timer gereset naar 30 minuten.

Nu blijft de verlichting aan totdat er 30 minuten lang geen beweging is gedetecteerd, in plaats van altijd uit na vier minuten.

In de loop der tijd is er steeds meer toegevoegd en tegenwoordig kan ik ook:

  • lampen bedienen vanaf de iPhone via de Opdrachten applicatie,
  • slimme meter uitlezen,
    • gegevens tonen op een LCD-display,
    • gegevens opslaan in prometheus (open source monitoring systeem),
    • gegevens tonen met behulp van grafana (metrics visualisatie),
  • MAC-adressen in het netwerk scannen om te kijken wie er thuis is (smartphone mac-adres).

De hardware

Klikaanklikuit

Klikaanklikuit is te koop in diverse bouwmarkten en elektronica winkels.

Raspberry Pi 3

De Raspberry Pi 3 is een goedkope singleboardcomputer gebaseerd op een ARM-processor. Hij heeft een hdmi aansluiting, netwerk aansluiting, 4 USB-aansluitingen, wifi en bluetooth.

RFXCOM

De RFXCOM is een 433 Mhz zender/ontvanger die via USB aangesloten wordt op een computer. Hij kan klikaanklikuit commando's versturen en ontvangen en ook signalen sturen/ontvangen van veel andere zenders/ontvangers die werken op 433 Mhz, bijvoorbeeld weerstations.

RFXCOM hardware RFXCOM hardware

Raspberry Pi 3 zonder SD-kaart

Omdat de Raspberry Pi SD-kaart gevoelig is voor corruptie van het bestandssysteem bij onverwacht uitschakelen heb ik besloten om de Raspberry Pi 3 te draaien zonder SD-kaart. Hij start op en draait vanaf het netwerk. Hiervoor is wel een vaste netwerk kabel nodig, dit kan niet via wifi. Opstarten en draaien gaat met behulp van een Synology NAS die een tftp server en nfs server draait. De tftp server zorgt dat de Raspberry Pi bij het starten informatie krijgt waardoor hij kan opstarten en weet waar hij na het opstarten mee verder moet gaan (bootcode). De nfs server bevat het file systeem voor de Raspberry Pi (wat anders op de SD-kaart zou staan).

Een ander voordeel van deze setup is dat de backup van de Raspberry Pi installatie makkelijk via de NAS geregeld kan worden.

De software

De software is geschreven in Kotlin, omdat ik daar meer ervaring mee wilde opdoen, en ontworpen met behulp van DDD (Domain Driven Design), ook om daarmee meer ervaring op te doen (hoe deel je een applicatie op in domeinen en hoe geef je die weer in de source code).

Domotica software 2

Message processor

Het hoofddomein werkt met messages. Een message is een map van key/values waarbij een key de betekenis van een value aangeeft.

Het hoofddomein is een message processor: een message gaat de processor in en er komen nul of meer messages uit als resultaat. De messages die er uit komen kunnen weer naar de input gaan of naar andere (output) domeinen, afhankelijk van het type van de uitgaande message.

Messages worden verwerkt met regels. Bij elke message worden de regels gezocht die van toepassing zijn (aan de hand van de keys/values in de message) op die message en elke regel produceert nul of meer uitgaande messages afhankelijk van de inkomende message.

Een regel kan ook state bewaren, bijvoorbeeld of de verlichting aan staat en hoe laat die weer uitgezet moet worden. Die state kan later door dezelfde regel of andere regels gebruikt worden.

Inputs

Klikaanklikuit via RFXCOM

Klikaanklikuit commando's komen van de RFXCOM driver in de RFXCOM input die er messages van maakt die de message processor kan verwerken. In de message staat onder andere het commando en het adres aan wie het commando is gestuurd. Voor verschillende commando's en adressen kunnem verschillende regels ingesteld worden.

Timer

Een 1 minute-timer die elke minuut een message stuurt met daarin het huidige tijdstip. Regels die afhankelijk zijn van een tijdstip kunnen hierop reageren (bijvoorbeeld het uitzetten van de verlichting bij de voordeur na 30 minuten inactiviteit).

P1 lezer

In 2020 werd mijn gas- en elektriciteitsmeter vervangen door een slimme meter. Die heeft een uitgang waarop hij gegevens publiceert over de meterstanden en het verbruik. De P1 lezer zet de slimme meter gegevens om in een message die de message processor kan verwerken.

Slimme meter, RP3 en LCD in de meterkast Slimme meter en raspberry pi 3 met LCD display in de meterkast.

MAC adres scanner

Ik wilde kunnen zien of er wel of niet iemand thuis is. Daarvoor dient de MAC-scanner. Die scant alle MAC-adressen op het netwerk en weet dan welke apparaten er zijn aangesloten. Als één of meer adressen van een mobiele telefoon is dan is er waarschijnlijk iemand thuis.

De MAC-scanner zet de aanwezige MAC-adressen in een message die de message processor kan verwerken. De message processor zelf zet die weer om in messages die aangeven of een mac-adres is toegevoegd of verwijderd.

HTTP-endpoints

Een HTTP-endpoint dat JSON-data omzet naar messages die de message processor kan verwerken. Op een iPhone zijn scripts gemaakt in de Opdrachten app die JSON naar het endpoint kunnen sturen. Door in de JSON de juiste keys/values te plaatsen kan een RFXCOM commando worden gestuurd.

Het HTTP-endpoint kan ook op andere manieren aangestuurd worden, bijvoorbeeld door een Angular app.

Outputs

Klikaanklikuit via RFXCOM

De RFXCOM-output maakt van uitgaande messages, die bestemd zijn voor de RFXCOM, een RFXCOM-commando dat naar de RFXCOM-driver gaat. Hiermee kan bijvoorbeeld verlichting aan/uit gezet worden.

LCD display

Ik wilde de slimme meter gegevens graag real-time kunnen zien. Bij Ali Express kun je goedkoop een LCD display voor de Raspberry Pi kopen. De message processor zet de slimme meter message om naar meerdere display messages (voor de verschillende gegevens) en de LCD display output zet die op het LCD display.

Nu staan alleen de slimme meter gegevens nog op het LCD display, maar in de toekomst moeten daar ook statussen van klikaanklikuit bij komen te staan (verlichting die aan staat, deuren die open staan, en dergelijke) en degenen die thuis zijn (waarvan de telefoon thuis is).

LCD display

HTTP-endpoints

Een HTTP-endpoint dat wordt gebruikt door prometheus. Hierop worden gegevens gepubliceerd die opgeslagen worden in prometheus. De gegevens in prometheus worden door grafana getoond in grafieken.

Grafieken in grafana

De buildstraat

De applicatie bestaat uit verschillende libraries en een hoofdprogramma die in aparte projecten in git zijn opgeslagen. Elk project, ook het hoofdprogramma, wordt gebouwd met gradle en heeft als resultaat artifact een jar-file. De jar-file van het hoofdprogramma wordt gedeployed naar de Raspberry Pi 3 en daar gestart.

De buildstraat bestaat uit:

  • git, voor het bewaren van alle project sources,
  • Jenkins, voor het bouwen van de projecten en publiceren van de artifacten, en deployen naar de Raspberry Pi 3,
  • Nexus, voor het bewaren van gepubliceerde artifacten.

Git draait op de Synology NAS, Jenkins en Nexus draaien in een docker container op de Synology NAS.

Zodra nieuwe sources naar git worden gepushed wordt het bijbehorende project in Jenkins gebouwd doordat in git een hook is gemaakt die het Jenkins project triggert. Als het Jenkins project succesvol bouwt wordt het resultaat artifact opgeslagen in Nexus zodat het later door andere projecten gebruikt kan worden.

Als het hoofdprogramma door Jenkins is gebouwd wordt het resultaat artifact, samen met een start script en een installatie script, naar de Raspberry Pi 3 gedeployed, geïnstalleerd en gestart. Een eventueel al draaiend hoofdprogramma wordt eerst gestopt.

iPhone opdrachten

De opdrachten app op de iPhone kan POST requests sturen naar een https-endpoint. Door in de body van de request de juiste codes te zetten kunnen onder andere klikaanklikuit codes verstuurd worden.

Opdrachten app

Toekomstige uitbreidingen

In de toekomst wil ik nog:

  • Codes verplaatsen naar configuratie. Nu zijn, onder andere, mac-adressen en klikaanklikuit commandos hard gecodeerd, dit moet configurabel worden,
  • LCD display inhoud kunnen tonen op een web pagina zodat ik niet steeds in de meterkast hoef te kijken,
  • Iets doen met de MAC adres registraties bijvoorbeeld kijken of ik wegga of thuiskom en aan de hand daarvan iets doen (zie ook volgende punt),
  • klikaanklikuit deursensoren integreren in de applicatie (verlichting gaat automatisch aan/uit als ik thuiskom of wegga in het donker)
  • klikaanklikuit deurbel integreren, de bel gaat niet alleen als er op de bel wordt gedrukt maar ook als de voordeur of achterdeur onverwacht open gaat of te lang open staat,
  • Verlichting automatisch aan/uit tijdens vakanties,
  • temperatuur sensoren toevoegen (en misschien ook andere weersensoren) en aan de hand daarvan een eigen weersvoorspelling maken,
  • ...