MQTT

Protokollet MQTT för IoT 14/02/2016

Tänkte gå lite djupare in på tekniska detaljer kring protokollet MQTT och dess användning i min power control applikation. Det är ett protkoll som fått mycket uppmärksamhet inom IoT (Internet of Things).

Kort om min applikation: Skriven i python och kör i Google App Engine (GAE). Godtycklig användare scannar en QR kod med telefonen och hamnar på en webbsida genererad av applikationen. Via URL:en vet applikationen vilket uttag som QR koden hör till. Användaren gör inställningar och klickar sedan på 'On' för att slå på uttaget.

Nu kommer det intressanta. När som helst, 24/7-365 måste applikationen kunna få fram ett meddelande till den lokala kontrollern som styr uttaget. Den är troligvis bakom brandväggar. Med modern uppbyggnad av webben går det på tvärs mot den normala riktningen för att öppna upp förbindelser. Enkla lösningen med 'poll' är väldigt dyr bandbreddsmässigt, speciellt om mobila bredband används så det är inte ett alternativ för mig. Här kommer MQTT till min räddning.

Det består av en central 'broker' som agerar server och ett antal klienter som ansluter. Modellen är väldigt lik modellen för chatprogram och protokoll som XMPP, ICQ eller Jabber. Klienten kopplar upp (MQTT bärs ofta direkt på TCP) och ansvarar för att hålla koppling levande. Sedan utför klienter 'subscribe' på ett antal valfria 'topics'. Andra klienter postar 'publish' på topics och brokern har till uppgift att skicka meddelanden till intresserade mottagare. Topics organiseras i ett träd och man kan välja att utföra subscribe med wildcards på ett helt delträd av topics. De liknar väldigt mycket hur absoluta sökvägar för filer är uppbyggda i filsystem.

I mitt fall innebär det dels en publik MQTT broker och dels klienter för de lokala noderna som har hand on uttagen. Sedan en klient för molnapplikationen. Med lite ordning och reda i hur topics sätts upp, kan all kommunikation lösas mellan lokala nätet och molnapplikationen via MQTT. Vi har en dubbelriktad förbindelse som ständigt är öppen utan att lasta nätet i onödan. Har nu testat detta och det fungerar alldeles utmärkt. Uppsatt system med lokal Raspberry Pi, uppkopplad med 3G modem. 12 timmar senare och kommandot att slå på uttaget gick fram direkt. Det fungerar som tänkt. Jag använder mosquitto broker och de CLI-kommandon som förljer med. Paho-MQTT klient för pythongränsnitt vilket har fungerat riktigt bra.

Tyvärr stödjer inte GAE MQTT direkt, men en enkel python webserver agerar brygga och forwarderar http anrop till MQTT brokern.

Lokal MQTT broker

Funderade vidare. Den lokala 'gateway' jag använder är en Raspberry Pi med en Razberry Z-wave controller. Det är ett av flera protokoll jag vill använda. Framtida alternativ är modbus/RS485 lösningar, tcp/ip inom lokala nätverket eller GPIO pinnar. I framtiden kan det finnas behov av lokal logik så att lokala gatewayen slår av brytare efter viss tid/förbrukning trots att internetförbindelse är borta. Den traditionella metoden här är att klumpa samman allt detta i en monolitisk C/C++/Python applikation och lösa det där. Men såg att detta kan snabbt bli rörigt.

Valde denna gång att ta MQTT spåret ett steg till. Utöver den globala brokern startar jag en lokal broker på min Raspberry Pi, enbart för intern kommunikation mellan program. Hela systemet är i stora drag eventbaserat och vår lokala broker bildar helt enkelt den eventbuss som fördelar events.

Finns flera fördelar:

  • Extremt enkelt att få ut loggning / debugga eventflöden. Starta en konsoll och utför subscribe på alla topics och både loggning + debug blir enkelt utan att röra normala koden.
  • Lätt att dela upp programmet i mindre komponenter. Har inte haft något behov av trådning än, utan UNIX filosofin fungerar med många småprogram som ökar isoleringen och underlättar vidare utveckling.
  • Bra utbyggbarhet. Med de hierarkiska topics så kan man lätt bygga ut systemet.

Så har hittills skelett för följande lokala program:

  • En server som lyssnar på globala och lokala MQTT brokers och passar intressanta meddelanden mellan dessa. I dagsläget behövs bara inkommande data men blir nog dubbelriktad när sensordata ska skickas upp.
  • En server som lyssnar på lokal broker och utför kommandon mot brytare via Telldus utrustning. Använder där 'tdtool' för att utföra kommandon.
  • En server för Razberry Z-wave kontroller. Lyssnar på lokal MQTT broker och styr brytare via Z-wave genom http anrop in i det REST baserade API som Razberry erbjuder.

Så, fungerar det? Ja. Är det överarbetat? En hel del kan tycka det. Men jag är övertygad om att det är en lösning som går att växa i. Speciellt enkelheten att logga och injektera meddelanden för test kommer att löna sig i längden. Som vanligt är det 'proof of concept' hitills så det är en bit kvar till att bli robust.

Generellt har MQTT varit en trevlig bekantskap. Speciellt med CLI-programmen 'mosqitto-pub' och 'mosquitto-sub' samt textbaserade protokoll har det varit riktigt lätt att komma framåt. Prestanda? Helt ok. Kanske 1s fördröjning från klick på webbsidan i mobilen till lampan slockar eller tänds. Helt ok för min del.