Maak een smarthome-dashboard met UIFlow
M5Stack ontwikkelt ESP32-microcontrollerbordjes met behuizing en scherm die je zo in je woonkamer zou kunnen zetten. Het zijn de ideale producten om een dashboard voor je smarthome van te maken. Met UIFlow is dat ook vrij eenvoudig te programmeren, op een grafische manier. Zo hoef je geen kaas gegeten te hebben van programmeercode.
UIFlow is een grafische ontwikkelomgeving voor de producten van M5Stack, ESP32-microcontrollerbordjes met behuizing en scherm. Met UIFlow kun je op een visuele manier een programma opbouwen door blokjes te verslepen, zonder dat je een letter programmeercode hoeft te schrijven. Ook de grafische interface op het scherm kun je zo eenvoudig met drag-and-drop instellen. Op deze manier maken we in deze masterclass een dashboard voor je smarthome.
Hardwarekeuze
UIFlow ondersteunt alleen de hardware van M5Stack, maar gen willekeurig ESP32-microcontrollerbordjes. Het voordeel is dat de drivers van hun eigen producten allemaal ingebouwd zijn. Voor onze toepassing van een smarthome-dashboard kies je een van de M5Stack-producten met ingebouwd scherm.
Ga je voor een klassiek tft-scherm, dan kom je uit bij de M5Stack Core2 of de voorganger M5Stack Core. De Core2 heeft een aanraakscherm, zodat je je slimme producten ook eenvoudig kunt bedienen via het scherm. De Core heeft geen aanraakscherm, maar wel drie fysieke knoppen onder het scherm, waarmee je ook acties in je smarthome kunt aansturen.
Gaat je voorkeur uit naar een e-ink-scherm, dan heeft M5Stack de Core Ink (1,54 inch) en de M5Paper (4,7 inch). Dit laatste product heeft een aanraakscherm met een hoge resolutie van 960 bij 540 pixels, terwijl de Core Ink aan te sturen is via een knop aan de zijkant. Beide e-ink-apparaten zijn voorzien van een batterij en een magneet. Daardoor kun je ze eenvoudig tegen je koelkast of een ander metalen voorwerp bevestigen.
UIFlow-firmware installeren
We gaan aan de slag met de Core Ink om de binnen- en buitentemperatuur van ons huis op het e-paperscherm te tonen. Die lezen we via MQTT in. Onder Windows en macOS moet je eerst nog een driver downloaden voor de USB-naar-UART-chip van het apparaatje. Afhankelijk van het model is dat de CP210x of de CH910x. De drivers zijn ook in de downloadsectie van de website van M5Stack te vinden. De Linux-kernel heeft die drivers al ingebouwd.
Na de installatie van de driver (voor de Core Ink is dat de CP2104) heb je ook nog de software nodig om de UIFlow-firmware op je apparaatje te installeren. Dat is M5Burner, en ook deze software vind je op de downloadpagina van M5Stack, zowel voor Windows als macOS en Linux. In M5Burner kies je links je apparaat en rechts klik je bij UIFlow op Download.
Verbind nu je Core Ink via de usb-kabel met je computer en klik op Burn om de firmware naar je apparaat te schrijven. In het volgende venster vul je de SSID en het wachtwoord in van het wifi-netwerk waarmee je het apparaat wilt verbinden, en klik je op Next. Daarna kies je de juiste seriële poort en snelheid, en klik je op Start.
UIFlow verkennen
Wanneer de firmware op je apparaatje staat, verbindt het met je wifi-netwerk en toont het een API-sleutel. Bezoek nu de website van UIFlow, vul daar de API-sleutel van je apparaat in en klik op het model Core Ink. Bevestig met OK. Daarna krijg je links een voorstelling van je Core Ink te zien, in het midden een balk met blokjes in allerlei categorieën, en rechts je ‘code’ in Blockly, die initieel alleen uit een blokje Setup bestaat.
Als eerste test kun je een tekst op het scherm van je Core Ink tonen. Sleep uit de zijbalk helemaal links een Label naar het midden van het scherm van je Core Ink. Klik in het midden op UI, op Label en dan op Label label0 show "Hello M5". Dat blokje verschijnt dan op het canvas rechts. Klik het vast onder het blokje Setup. Klik dan onder UI op Screen, vervolgens op Set screen show en klik dit vast onder het vorige blokje. Klik dan helemaal onderaan op Run. Je code wordt nu op de Core Ink uitgevoerd.
En als je op Download klikt, wordt de code definitief als firmware op het bordje geschreven, zodat die na een herstart ook nog blijft draaien. Om je code dan te laten starten in plaats van de UIFlow-programmeermodus, moet je eerst in M5Burner bij UIFlow op Configurate klikken, je poort kiezen en dan bij Start Mode voor App Mode kiezen en op Save klikken. Wil je daarna je apparaatje weer programmeren, zet dit dan terug op Internet Mode.
Verbinden met MQTT
Om van de Core Ink een dashboard voor je smarthome te maken, hebben we een manier nodig om aan de data van bijvoorbeeld sensoren te komen. Dat doen we met MQTT. We gaan er hier vanuit dat je al een MQTT-broker zoals Mosquitto hebt draaien op een Raspberry Pi, bijvoorbeeld als add-on in Home Assistant. Houd de gegevens van je MQTT-broker bij de hand.
Klik in UIFlow op Advanced / MQTT en dan op het blok dat begint met set client id. Vul een unieke client ID in en dan de gegevens voor de server, zoals de hostname, het poortnummer, de gebruikersnaam en het wachtwoord. Verwijder het blokje van het label door erop te klikken en op Delete te drukken. Klik het MQTT-blok dan onder de Setup vast, voeg daaronder nog een blokje mqtt start toe en daaronder Set screen show. Als je deze code op je Core Ink draait, zou je in de logs van Mosquitto iets moeten zien als:
"New client connected from 192.168.0.215:58048 as Core Ink (p2, c1, k300, u'home')."
MQTT-onderwerp
We willen nu dat de Core Ink een sensorwaarde toont die binnenkomt op een specifiek MQTT-onderwerp. Dat doe je door een blokje Advanced / MQTT / mqtt subscribe toe te voegen. Dit klik je niet aan de rest van je blokjes vast, maar staat los daarvan. Vul het MQTT-onderwerp tussen de aanhalingstekens in.
Binnen dit blokje vind je de gegevens die op het gegeven MQTT-onderwerp worden ontvangen in de variabele topic_data. We gaan die waarde eerst in een variabele steken. Klik op Variables / Create variable, noem die bijvoorbeeld buitentemperatuur en klik op OK. Sleep Set buitentemperatuur to in het MQTT-blokje en plak daarachter het blokje Advanced / MQTT / get topic_data.
Temperatuur tonen
Dan rest ons nu nog om de temperatuur te tonen in een label. Omdat we met een e-ink-scherm werken mogen we het scherm niet te snel na elkaar verversen. Dat is de reden waarom we niet in het blok mqtt subscribe onmiddellijk de temperatuur op het scherm tonen, want sommige sensoren sturen elke seconde een nieuwe waarde via MQTT.
Daarom maken we een lus aan die elke minuut het label aanpast. Sleep de lus uit Event / Loop achter mqtt start en verwijder het blokje Set screen show dat er eerst stond. Voeg in de lus het blokje UI / Label / Label show toe. Vervang het blokje met de standaardtekst "Hello M5" door het blokje Variables / buitentemperatuur. Voeg dan het blokje Screen / Set screen show onder het label toe en daaronder Timer / Wait 1 s. Vervang de 1 door 60 voor een update elke minuut.
Meerdere interface-elementen
We zijn begonnen met één label, maar we willen uiteraard meerdere sensorwaardes tonen. Gelukkig kun je de interface eenvoudig uitbreiden. Sleep uit de linkerzijbalk een Title, drie keer een Label en één keer een Line naar het scherm van de Core Ink. Je hebt nu vier labels: twee voor sensorwaardes en twee voor een begeleidende tekst. Met de lijn delen we het scherm op in twee vakken.
Sleep naar elke hoek van het scherm (linksboven, rechtsboven, linksonder en rechtsonder) een label. De exacte locatie pas je dadelijk aan. Klik dan op de lijn. Vul achtereenvolgens voor X1, Y1, X2 en Y2 de coördinaten 0, 110, 200 en 110 in. Dat levert een horizontale lijn op die ongeveer het midden van het scherm van 200 bij 200 pixels doorkruist. Klik op het kruisje om de eigenschappen van de lijn te verlaten.
Tekst aanpassen
Klik op elk van de labels om hun eigenschappen aan te passen. Het label linksboven geef je de tekst Buiten en lettertype DejaVuSans 18. Het label rechtsboven geef je hetzelfde lettertype. Het label linksonder geef je de tekst Binnen en ook hetzelfde lettertype. Dit lettertype ken je ook aan het label rechtsonder toe. De tekst van de labels rechtsboven en rechtsonder maakt niet uit: die gaat ons programma vervangen door de sensorwaardes. Ook bij de titel laten we de tekst door het programma aanpassen.
Laten we eerst de tekst van de titel aanpassen naar de huidige tijd. Daarvoor ga je naar Advanced / NTP en sleep je het blokje getiteld Init ntptime with host "cn.pool.ntp.org" and timezone 8 naar je canvas. Plaats het tussen Setup en de initialisatie van MQTT. Verander de host naar een server die zich dichterbij bevindt, zoals nl.pool.ntp.org, en verander de tijdzone naar 2. Sleep dan uit UI / Title het blokje Title title0 show "Title" en vervang de aanduiding "Title" door het blokje Get date format with "-" and time format with ":" uit Advanced / NTP. Sleep dan dit titelblokje binnen je lus, vóór het blokje dat je label toont.
JSON inlezen
Als je nu nog de buitentemperatuur op het juiste label toont en deze code op je Core Ink draait, krijg je in de titelbalk de huidige datum en tijd te zien, en in het bovenste gedeelte de buitentemperatuur. Nu kunnen we in het onderste gedeelte nog een andere temperatuur tonen als we daarvoor een extra variabele aanmaken die we in een ander mqtt-subscribe-blok een waarde geven. Dat blok kan ook complexer zijn, bijvoorbeeld als de MQTT-boodschap in JSON-formaat is (zie ook het kader ‘JSON’).
Maak daarvoor twee variabelen aan: één om de JSON-string in op te slaan (binnenjson), en één om de binnentemperatuur in op te slaan (binnentemperatuur). Voeg dan in een nieuw blok mqtt subscribe met het juiste MQTT-onderwerp het blok Variables / Set binnenjson to toe en vul het ontbrekende slot met JSON / loads json. In het ontbrekende slot van dit laatste plaats je Advanced / MQTT / get topic_data. Op deze manier lees je de MQTT-boodschap als JSON-structuur in en zet je die om naar een ‘map’ die je aan de variabele binnenjson toekent.
Waardes uit JSON halen
Voeg na dit blok dat de JSON-structuur inleest een blok Variables / set binnentemperatuur to toe en vul het ontbrekende slot met Map / get key … in map …. Na get key voeg je Text / " " toe en daar vul je de sleutel in waarin de temperatuurwaarde zit, zoals tempc. Na in map voeg je Variables / binnenjson toe.
Deze opdracht haalt dus de waarde van de sleutel tempc uit de map die de JSON-structuur bevat en kent deze toe aan de variabele met de binnentemperatuur. Als je nu in je lus ook de binnentemperatuur aan het juiste label toekent, zal je apparaatje elke minuut niet alleen de buitentemperatuur maar ook de binnentemperatuur updaten. Vergeet overigens niet je code op te slaan met het icoontje bovenaan rechts, zodat je hem later opnieuw kunt inladen en aanpassen.
JSON
JSON (JavaScript Object Notation) is een dataformaat dat zowel voor software als voor mensen eenvoudig is om aan te maken en te lezen. Er zijn twee basiscomponenten in JSON. De eerste is de collectie van paren naam/waarde. Zo’n JSON-code ziet er bijvoorbeeld als volgt uit: {"id":"16:2A:04:CE:19:72","rssi":-52}. Die heeft dus de naam id met waarde 16:2A:04:CE:19:72 en de naam rssi met waarde -52. De tweede basiscomponent is de lijst van waardes. Een waarde in een collectie kan immers ook een lijst van waardes zijn, die tussen rechte haken staat. Zo heeft het volgende voorbeeld de naam identifiers als waarde een lijst met drie strings: {"identifiers":["56847C365278","41CED86E4798","216B02CA25A5"]} Wil je meer weten over de exacte regels voor JSON-data, bekijk dan de website van JSON (www.json.org).
Meer blokjes
In deze masterclass hebben we maar een beperkt aantal blokjes geïntroduceerd om een eenvoudig dashboard voor je smarthome te maken. Maar UIFlow heeft nog veel meer types blokjes met allerlei mogelijkheden. Zo vind je onder Event de mogelijkheid om op het drukken op de knoppen van je Core Ink te reageren. Zo zou je een bericht naar je MQTT-broker kunnen verzenden (Advanced / MQTT / publish topic) als je de knop aan de zijkant naar boven of onder drukt.
En in de categorie Hardware krijg je dan weer toegang tot allerlei hardwarefunctionaliteit. Je spreekt hier de luidspreker aan, leds, batterij, GPIO-pinnen, UART, I²C, wifi enzovoort, afhankelijk van het model van je M5Stack-apparaat. En als je units en hats op je apparaat hebt aangesloten, vind je die functionaliteit in de gelijknamige categorieën.
Programmeren in blokjes
Onder Advanced vind je ook de mogelijkheid om een http-aanvraag te doen. Je geeft daarbij een methode, url, headers en data op en vult de blokjes in die bepalen wat er gebeurt bij het slagen of falen van de aanvraag. Je kunt ook meer low-level netwerkcommunicatie uitvoeren door een UDP-server of UDP-client op te zetten.
Ook van de echte programmeerconcepten hebben we nog niet veel getoond. Er zijn allerlei blokjes voor wiskundige berekeningen, diverse soorten lussen en vergelijkingen. Je kunt ook teksten manipuleren en met lijsten werken. En je kunt zelfs een functie in een afzonderlijk blok definiëren, die je dan in andere blokjes kunt oproepen. Blockly geeft je dus krachtige grafische programmeermogelijkheden.
MicroPython
Ook krachtig aan UIFlow is dat je Blockly-code onderliggend in MicroPython wordt omgezet, een lichtgewichtversie van de programmeertaal Python voor microcontrollers. Als je bovenaan op Python klikt, krijg je de MicroPython-code te zien die overeenkomt met je blokkenconstructie in Blockly. Klik je daarna op Blockly, dan krijg je weer je blokken te zien.
Tip: bestel ook de cursus Programmeren in Python!
Soms zul je misschien ook externe hardware willen aansturen die niet door UIFlow wordt ondersteund, of andere functionaliteit gebruiken die niet is voorzien. Dan kun je in Blockly onder Advanced / Execute een blokje Execute code toevoegen. Hierin typ je dan MicroPython-code. Die wordt dan rechtstreeks op die plaats uitgevoerd, wat je ook zult zien als je de Python-versie van je programma bekijkt.
Meer inzicht in het energieverbruik van je slimme huis? Bestel dan een energiemeter bij Bol.com.