MQTT to protokół zupełnie inny niż HTTP. Przyda nam się gdy chcemy zbudować wiele aplikacji wysyłających sobie nawzajem komunikaty. Podobnie jak zdarzenia (eventy) w językach i frameworkach, MQTT pozwala na wysyłanie zdarzeń i nasłuchiwanie na nie między odległymi aplikacjami.
Musimy na chwilę zapomnieć o HTTP. Zapomnijmy o zapytaniach i odpowiedziach serwera. MQTT działa w zupełnie innej architekturze.
Protokół MQTT służy do komunikacji wiele-do-wielu. Jeśli mamy wiele elementów systemu, które muszą wysyłać informacje o zdarzeniach i komunikować się między sobą – MQTT jest dobrym kandydatem.
Facebook messanger działa przez MQTT. Korzystamy z niego na wielu urządzeniach. Gdy prowadzimy rozmowę na komputerze, możemy płynnie przeskoczyć na komórkę i cała historia rozmowy jest dla nas dostępna.
Broker, klient i tematy – to łatwe
Działanie MQTT jest bardzo łatwe. Podczas wyjaśniania pojęć będziemy od razu korzystać z protokołu.
Broker w MQTT pełni rolę serwera albo centralnego huba lub switcha przesyłającego komunikaty. Najpopularniejszy broker to Mosquitto i jest bajecznie prosty w instalacji. Po zainstalowaniu uruchamiamy program, który czeka na klienty:
$ ./mosquitto mosquitto version 1.3.5 (build date 2014-10-27 15:13:47+0000) starting Using default config. Opening ipv4 listen socket on port 1883. Opening ipv6 listen socket on port 1883.
Z brokerem łączą się klienty aby nasłuchiwać lub wysyłać wiadomości. Każda wiadomość musi mieć odpowiedni temat (topic) oraz treść. Nasłuchiwanie zawsze dotyczy konkretnych tematów. Spróbujmy w nowej konsoli uruchomić klienta, który słucha (z pakietu mosquito):
$ mosquitto_sub -h 127.0.0.1 -t "adam/temat1"
Składnia jest prosta do zrozumienia. Poadliśmy adres serwera oraz temat. Póki co nic się nie dzieje. Program w konsoli czeka na wiadomości. Za to nasz wcześniej uruchomiony serwer powiedział:
New connection from 127.0.0.1 on port 1883. New client connected from 127.0.0.1 as mosqpub/22823-adam. (c1, k60).
Serwer mówi, że ma nowego klienta. Czas na wysłanie wiadomości. W kolejnej konsoli piszemy:
$ mosquitto_pub -h 127.0.0.1 -t "adam/temat1" -m "Zyrafy wchodzą do szafy"
Program od razu się zakończy. Natomiast w konsoli, gdzie mieliśmy uruchomiony mosquito_sub zobaczymy naszą wiadomość. W konsoli serwera zauważymy, że pojawił się kolejny klient.
Tematy wiadomości
Temat wiadomości w MQTT to nie tylko prosty tekst. Tematy możemy dzielić na kolejne poziomy zagnieżdżenia tak, jak katalogi na dysku. Możemy więc mieć temat:
serwer1/core/cpu/temperature
W ten sposób jakiś proces może rozgłaszać temperaturę procesora na serwerze. Słuchając na innym temacie nie otrzymamy wiadomości o temperaturze. Możemy za to nasłuchiwać na wielu tematach oraz używać dopasowań. Przykładowo:
+/core/cpu/temperature
Znak plus dopasowuje się do dowolnej nazwy na jednym poziomie. W ten sposób nasłuchujemy informacji o temperaturze ze wszystkich serwerów. Możemy też słuchać wszystkiego, co pasuje do początku wzorca:
serwer1/core/#
Hasz w nazwie oznacza, że dostaniemy wszystkie komunikaty o temacie z początkiem pasującym do podanego.
MQTT w PHP
Protokół jest dostępny w praktycznie każdej platformie i każdym języku programowania. W naszym ulubionym PHP również. Na sieci znajdziemy sporo bibliotek do obsługi MQTT.
Wybrałem bibliotekę dostępną na GitHubie, która ma łatwy w użyciu interfejs. Po dołączeniu jej do kodu możemy połączyć się z serwerem jako klient MQTT i wysłać wiadomość:
$mqtt = new phpMQTT("127.0.0.1", 1883, "phpMQTT Pub Example"); if ($mqtt->connect()) { $mqtt->publish("adam/temat1","Hello World!",0); $mqtt->close(); }
Jeśli nasz broker mosquitto nadal działa i nadal nasłuchujemy programem mosquitto_sub, w jego konsoli zobaczymy naszą wiadomość „Hello World!”.
Równie łatwe jest odbieranie wiadomości. Wystarczy zapisać się na subskrypcję tematu. Najpierw stwórzmy funkcję odbierającą wiadomości:
function Message($topic,$msg) { printf("Topic: %s; Message: %s\n",$topic,$msg); }
A następnie podłączmy ją do MQTT i zapiszmy się na temat:
$mqtt = new phpMQTT("127.0.0.1", 1883, "phpMQTT Sub Example"); $mqtt->connect(); $topics['adam/#'] = ["qos"=>0, "function"=>"Message"]; $mqtt->subscribe($topics,0); while($mqtt->proc()){} $mqtt->close();
Widzimy, że możemy zdefiniować wiele tematów i osobne funkcje dla każdego z nich. Jeśli uruchomimy nasz skrypt w konsoli, będzie czekał na wiadomości i wypisywał wszystko, co otrzyma.
To wszystko, czego potrzebujemy żeby rozmawiać z brokerem MQTT. Jak zwykle, jest to łatwe i przyjemne.
MQTT i JavaScript
Trochę trudniej jest korzystać z MQTT z poziomu JavaScriptu. Musimy skompilować mosquitto z obsługą WebSocket. Gdy już to zrobimy, mamy do dyspozycji np. bibliotekę Paho, która pozwała w łatwy sposób korzystać z protokołu. Znów stworzymy sobie funkcję odbierającą komunikaty:
function onMessage(message) { console.log("Message:"+message.payloadString); }
Następnie tworzymy połączenie:
client = new Paho.MQTT.Client("127.0.0.1", port, "Nazwa Klienta"); client.onMessageArrived = onMessage;
A gdy połączenie zostanie nawiązane, nasłuchujemy:
client.connect({onSuccess:onConnect}); function onConnect() { console.log("onConnect"); client.subscribe("adam/#"); }
Możemy też wysyłać wiadomości:
message = new Paho.MQTT.Message("Hello"); message.destinationName = "adam/example"; client.send(message);
Na koniec
Protokół MQTT może nam się przydać gdy mamy wiele elementów systemu. Te elementy muszą komunikować się ze sobą w elastyczny sposób. Np. lokalna sieć urządzeń na pokładzie samochodu, autobusu, pociągu, statku lub urządzenia w ramach inteligentnego domu. Możemy bez problemu przesyłać wiadomości w JSON lub XML.
Warto poczytać oficjalną dokumentację MQTT oraz zajrzeć na stronę Mosquitto.