MQTT — viestintäkerros

Tämä on kahdeksas osa sarjasta joka dokumentoi EnergyHub-järjestelmän rakentamisen vanhaan rintamamiestaloon. Edellisessä osassa käytiin läpi hinta ja sulakkeet — kaksi keskeisintä rajoitetta jotka ohjaavat energiapäätöksiä. Tässä osassa tarkastellaan sitä mikä pitää kaikki kerrokset yhdessä: MQTT-viestintäkerros.
Kenttälaitteet kommunikoivat Home Assistantin kanssa omilla protokollillaan — Sungrow-invertteri Modbus TCP:llä, Thermia-lämpöpumppu Modbus RTU:lla, P1-mittari omalla rajapinnallaan. Mutta ylempien kerrosten — Home Assistantin ja Node-REDin — välinen viestintä tarvitsi oman väylän. Vaihtoehtoina olisi ollut suorat API-kutsut, tietokantakyselyt tai jaettu muisti. EnergyHubissa valittiin MQTT.
Valinta ei ole sattuma. MQTT on suunniteltu juuri tähän: hajautettuun, epäluotettavaan ympäristöön jossa komponentit käynnistyvät ja sammuvat eri tahtiin, yhteydet katkeavat ja palautuvat, ja jokaisen komponentin pitää selviytyä itsenäisesti myös silloin kun muut eivät vastaa.
Mitä MQTT on ja miksi se toimii tässä
MQTT on kevyt julkaise/tilaa-protokolla. Lähettäjä julkaisee viestin brokerille tiettyyn topiciin — vastaanottajat jotka ovat tilanneet kyseisen topicin saavat viestin. Lähettäjä ja vastaanottaja eivät tiedä toisistaan. Ne tietävät vain topicin.
Tämä löyhä kytkentä on keskeinen ominaisuus. Home Assistant ei lähetä komentoa suoraan Node-REDille — se julkaisee mittauksen MQTT-brokerille. Node-RED lukee sen kun haluaa. Jos Node-RED on poissa käynnissä puoli tuntia ja palaa takaisin, se lukee viimeisimmän retain-viestin ja jatkaa siitä. HA:n ei tarvitse tietää kuka viestin kuluttaa.
Sama toimii toiseen suuntaan. Node-RED julkaisee komennon energyhub/command/ev/allowed: true — HA kuuntelee topicia ja reagoi. Node-RED ei kutsu HA:n API:a suoraan. Se ei tiedä miten HA on konfiguroitu tai mitä automaatiota siellä pyörii.
EnergyHubissa MQTT-brokeri on Mosquitto, joka pyörii samalla Lenovo ThinkCentrellä Docker-kontissa. Se on yksinkertainen, luotettava ja tarkoitukseen sopiva.
Topicrakenne — neljä suuntaa
EnergyHubin MQTT-topicit on jaettu neljään kategoriaan jotka kuvaavat tiedon kulkusuunnan ja tarkoituksen:
energyhub/telemetry/ HA → Node-RED mittaukset, hinnat, lämpötilat
energyhub/command/ Node-RED → HA ohjauskomennot laitteille
energyhub/system/ molemmat suunnat järjestelmätilan viestit
energyhub/observability/ Node-RED → kaikki päätösloki auditointia varten
Telemetria on HA:n julkaisemaa dataa. Se sisältää kaiken mitä Node-RED tarvitsee päätöksentekoon: verkkotehon, vaihevirrat, aurinkotuotannon, spot-hinnan, lämpöpumpun lämpötilat, capability-flagit ja operating moodin. Telemetria lähtee minuutin välein, vaihevirrat 10 sekunnin välein Safety Guardiania varten.
Komennot ovat Node-REDin päätöksiä. Ne kulkevat aina samaan suuntaan — Node-REDistä HA:lle. HA ei tee omia optimointipäätöksiä, se vain toteuttaa komennot.
Järjestelmäviestit ovat poikkeustapauksia: safety trip, moodinvaihto, watchdog-signaalit. Nämä voivat kulkea molempiin suuntiin ja niillä on korkein prioriteetti.
Observability on päätösloki — ei ohjausta, ei komentoja. Jokainen Node-REDin päätös kirjataan tähän topiciin syineen. InfluxDB tallentaa ne ja Grafana visualisoi.
Ilman observabilityä automaatio näyttää satunnaiselta. Päätös tapahtui joskus, jossain YAML:ssa, jollain ehdolla. Observability tekee päätöksestä jäljitettävän: ”Tiistaina klo 14:05 EV-lataus estettiin koska peak_protection oli aktiivinen ja L1-vaihe oli 23,8 ampeeria.” Tämä on se kerros joka erottaa hallittavan järjestelmän hallitsemattomasta.
Retain — viimeinen tunnettu totuus
Retain on MQTT:n tärkeimpiä ominaisuuksia hajautetussa järjestelmässä. Kun viesti julkaistaan retain-lipulla, broker tallentaa sen. Uusi tilaaja saa sen heti liittyessään — vaikka alkuperäinen julkaisija olisi sammunut tunteja sitten.
EnergyHubissa retain-politiikka on tarkoin harkittu:
| Topic | Retain | Syy |
|---|---|---|
energyhub/telemetry/* | ❌ ei | Mittaus on tuore tai sitä ei ole — vanha arvo ei saa jäädä elämään brokeriin |
energyhub/system/capabilities | ✅ kyllä | Operating mode ja capability-tila säilyvät uudelleenkäynnistyksen yli |
energyhub/command/* | ❌ ei | Komento on hetkellinen — vanha komento ei saa toistua |
energyhub/system/safety_trip | ✅ kyllä | Turvatila säilyy kunnes se eksplisiittisesti nollataan |
energyhub/observability/* | ❌ ei | Lokidata ei tarvitse persistenssiä brokkerissa |
Retain-viestit ovat EnergyHubin muisti — mutta vain järjestelmätilan osalta. Kun Node-RED käynnistyy uudelleen huollon jälkeen, se ei aloita tyhjältä pöydältä tilan osalta: se lukee capabilities- ja safety_trip-topicit retain-viesteistä ja tietää heti missä moodissa ollaan ja onko turvatila päällä. Mittaukset se sen sijaan odottaa tuoreina — ensimmäinen telemetriasykli täydentää kuvan sekunneissa.
Tässä on nimittäin sudenkuoppa, joka tekee telemetrian retainista vaarallisen: retain-viesti voi jäädä brokeriin väärässä tilassa. Jos vanha mittaus jäisi retain-viestiksi, uusi tilaaja saisi sen heti — eikä voisi tietää onko se sekunnin vai tunnin vanha. Siksi mittaukset eivät ole retained. Sama ilmiö koskee tilatietoa, mutta siellä se on hallittu: jos safety_trip julkaistiin true-arvolla mutta järjestelmä ei koskaan nollaa sitä, se jää retain-viestiksi joka toistuu jokaiselle uudelle tilaajalle. EnergyHubissa opittiin tämä kantapään kautta — Safety Guardian laukaisi turvatilan, mutta retain-viesti jäi true:ksi vaikka tilanne oli jo ohitse. Ratkaisu: turvatilan nollaus on eksplisiittinen toimenpide, ei automaattinen.
QoS — kuinka tärkeä viesti on
MQTT:ssä on kolme palvelutasoa:
QoS 0 — lähetä ja unohda. Ei kuittausta, ei uudelleenlähetystä. Viesti voi kadota.
QoS 1 — toimita vähintään kerran. Broker kuittaa vastaanoton. Viesti voi tulla useammin kuin kerran.
QoS 2 — toimita täsmälleen kerran. Neljän viestin kättely, korkein luotettavuus.
EnergyHubissa QoS-valinta on tarkoituksellinen:
- Telemetria: QoS 0. Jos yksi minuuttimittaus katoaa, seuraava tulee pian. Parempi nopeus kuin varmuus.
- Komennot: QoS 1. Komento menee perille vähintään kerran. Jos se tulee vahingossa kahdesti, ei haittaa — ”salli EV-lataus” kahdesti tuottaa saman lopputuloksen kuin kerran.
- Safety trip: QoS 1. Turvatilan viesti on kriittinen ja sen pitää mennä perille. QoS 2 olisi teknisesti puhtain valinta, mutta käytännössä kotijärjestelmässä QoS 1 yhdistettynä retain-lippuun ja tilapohjaiseen logiikkaan on riittävä — ja yksinkertaisempi.
MQTT ja vikasietoisuus
MQTT:n löyhä kytkentä tekee järjestelmästä vikasietoisen — mutta ei automaattisesti. Vikasietoisuus pitää suunnitella.
Broker kaatuu: kaikki kommunikaatio lakkaa. Laitteet jäävät viimeiseen ohjattuun tilaan. Mosquitto käynnistyy Docker-kontin mukana automaattisesti — tyypillinen katkos on sekunteja.
Node-RED käynnistyy uudelleen: se lukee retain-viesteistä viimeisimmän tilan ja jatkaa. Ensimmäinen minuuttisykli päivittää tilanteen täysin.
HA käynnistyy uudelleen: Node-RED odottaa uusia telemetriaviestejä. Safety Guardian saa vaihevirtatiedot vasta kun HA alkaa julkaista uudelleen — tämä on tiedostettu rajoite.
Verkkoyhteys katkeaa: jos Mosquitto ja Node-RED ovat samalla koneella, ne kommunikoivat paikallisesti riippumatta internetyhteydestä. Nordpool-hintadata ei päivity, mutta viimeisin tunnettu hinta säilyy Node-REDin omassa kontekstissa.
Topicit käytännössä
Koko EnergyHubin MQTT-liikenne on tarkasteltavissa yhdellä komennolla:
bash
mosquitto_sub -h localhost -t "energyhub/#" -v
Tämä on yksi järjestelmän tärkeimmistä debuggaustyökaluista. Kun jokin ei toimi, ensimmäinen tarkistus on katsoa mitä MQTT:ssä liikkuu. Onko telemetria päivittymässä? Lähettääkö Node-RED komentoja? Onko safety_trip jäänyt retain-viestiksi?
Käytännön esimerkki 25.5.2026: Safety Guardian laukaisi safety_trip: true kun L1-vaihe ylitti 24,5 ampeeria. Viesti kulki energyhub/system/safety_trip-topiciin QoS 1:lla ja retain-lipulla. HA vastaanotti sen ja siirtyi emergency-moodiin. Kun tilanne raukesi, false-viesti lähetettiin eksplisiittisesti. Koko tapahtumaketju näkyi reaaliajassa mosquitto_sub-komennolla.
MQTT ei ole ratkaisu kaikkeen
MQTT sopii erinomaisesti asynkroniseen, tapahtumaohjattuun viestintään. Se ei sovi kaikkeen.
Modbus-kommunikaatio kenttälaitteiden kanssa tapahtuu HA:n sisällä — ei MQTT:n kautta. Sungrow-invertteri ja Thermia-lämpöpumppu puhuvat Modbusia, ja HA toimii Modbus-masterina. Tämä on integraatiokerroksen sisäinen asia joka ei näy MQTT-väylässä.
Historiadatan tallennus on InfluxDB:n vastuulla — ei MQTT:n. MQTT on viestintäväylä, ei tietokanta. Observability-topicin viestit tallennetaan InfluxDB:hen, mutta MQTT ei pidä niistä kirjaa pidempään kuin retain-viesti kestää.
Näiden rajojen pitäminen selkeinä on osa arkkitehtuurin hallittavuutta. MQTT tekee yhden asian hyvin: välittää viestejä löyhästi kytkettyjen komponenttien välillä. Se ei yritä tehdä enempää.
Seuraavaksi: Osa 9 — Hintaohjauksen flow Node-REDissä. Miten päätöslogiikka rakentuu käytännössä ja miten Priority Resolver tekee valintansa.
Tekninen toteutus: MQTT-topicrakenne ja Mosquitto-konfiguraatio on kuvattu ohjeessa HA:n valmistelu integraatiokerrokseksi sekä Node-RED flowt — rakenne ja toteutus.