Tym wpisem rozpoczynamy serię na temat bardzo popularnego w IoT i M2M protokołu o nazwie MQTT. Jeśli interesujesz się koncepcją Internetu Rzeczy to pewnie już ta nazwa obiła Ci się kiedyś o uszy. Jeśli nie, to na pewno warto się z tym terminem zapoznać i teraz masz ku temu idealną okazję 🙂 Na początku przedstawię trochę teorii, a następnie wykorzystamy protokół w praktyce.
Wprowadzenie
MQTT jest otwartym protokołem komunikacyjnym, który wyróżnia lekkość i prostota, dzięki czemu można go z powodzeniem wykorzystywać na niewielkich mikrokontrolerach, przy ograniczonych zasobach sprzętowych, a także gdy mamy do czynienia z niską przepustowością łącza, co idealnie wpasowuje się w koncepcję IoT. Nie dziwi więc też fakt, że znajduje zastosowanie przy łączeniu urządzeń z chmurami (np. Amazon Web Services czy Microsoft Azure). Wspierany jest przez wiele platform, takich jak Arduino, ESP8266 czy Raspberry Pi – istnieje wiele bibliotek i gotowych rozwiązań, dzięki czemu można łatwo, szybko i przyjemnie zacząć z niego korzystać.
MQTT, podobnie jak wszechobecny HTTP, znajduje się na samej górze stosu TCP/IP – w warstwie aplikacyjnej, jednak specyfika ich działania jest zupełnie inna. Jak widzisz, pojawiły się tutaj takie pojęcia jak HTTP i stos TCP/IP. Znajomość zagadnień sieciowych nie jest tutaj niezbędna – po przeczytaniu tej serii i bez tego będziesz w stanie korzystać z tego protokołu, ale podstawy zdecydowanie warto poznać. Szczególnie jeśli będziesz chciał wszystko zrozumieć i wykorzystywać go w trochę bardziej zaawansowanych przypadkach. Przydatny powinien być kurs na kanale youtube Pasja informatyki. Jeżeli zagadnienia sieciowe są Ci zupełnie obce to warto się z nimi zapoznać.
Jak to działa?
Protokół MQTT działa w oparciu o model publikacja/subskrypcja (ang. publish/subscribe), który umożliwia asynchroniczną komunikację pomiędzy klientami publikującymi (ang. publisher) i subskrybującymi (ang. subsciber).
Klientem MQTT nazywamy dowolne urządzenie podłączone do sieci (np. mikrokontroler, komputer) które ma zaimplementowany stos TCP/IP i protokół MQTT (potrafi komunikować się za jego pomocą). Istnieją gotowe biblioteki klientów MQTT w różnych językach, ale o tym dokładnie opowiem w kolejnej części. Warto jeszcze w tym miejscu wspomnieć, że jeden klient MQTT może jednocześnie pełnić funkcję subscribera i publishera.
Klienci, publisher i subscriber, nie komunikują się ze sobą bezpośrednio. Co więcej, jeden klient może przekazać wiadomość innemu klientowi bez znajomości jego adresu IP i wiedzy o jego istnieniu 🙂 Jak to jest możliwe? Otóż, pomiędzy klientami w modelu publish/subscribe zawsze występuje element pośredniczący – message broker. Odbiera on wiadomości od klientów publikujących, a następnie rozsyła je do odpowiednich klientów subskrybujących.
Tutaj pojawia się kolejne pytanie, skąd broker wie do których subskrybujących klientów przesłać daną wiadomość? Na nasze szczęście to też nie jest skomplikowane 🙂 Publisher, wysyłając wiadomość, dodaje do niej dodatkową informację – tekst nazywany tematem (ang. topic), a broker rozsyła wiadomość do tych klientów, którzy subskrybują ten temat. Bardzo dobrze przedstawia to poniższa grafika:
Dzięki takiemu mechanizmowi jeden klient może przekazać informację do wielu klientów i to bardzo małym kosztem: wystarczy, że wyśle wiadomość do brokera, a on już odwala za niego całą brudną robotę. I bardzo dobrze. Właśnie dzięki temu klienta możemy zaimplementować na małych mikrokontrolerach.
Oczywiście w takim wypadku broker potrzebuje już dużo większych zasobów. Może przecież być do niego podłączonych wielu klientów, musi filtrować i rozsyłać wiele wiadomości, zajmować się uwierzytelnianiem i autoryzacją klientów, a także przechowywaniem wiadomości. W związku z tym instaluje się go na wydajniejszych platformach. Na szczęście, podobnie jak w przypadku klienta, istnieją gotowe rozwiązania do wykorzystania – zarówno płatne jak i darmowe.
MQTT w praktyce
Wiemy już z grubsza jak protokół działa w teorii, czas przejść do praktyki. Zajmiemy się teraz instalacją brokera i klientów, żeby w praktyce sprawdzić ich działanie. Zaczniemy od instalacji brokera. Istnieją jego różne implementacje, bardzo popularny jest np. open-sourcowy broker Eclipse Mosquitto i właśnie go tutaj wykorzystamy. Na stronie producenta znajdziesz potrzebne pliki dla różnych systemów operacyjnych oraz instrukcję instalacji. Jeśli korzystasz z Linuxa na PC albo Raspberry Pi to sprawa jest banalnie prosta – wystarczy w konsoli wpisać:
1 |
apt-get install mosquitto |
Po instalacji brokera trzeba jeszcze zainstalować programy klientów:
1 |
apt-get install mosquitto-clients |
Aby uruchomić broker wystarczy w konstoli wpisać mosquitto. Jak widać broker domyślnie słucha na porcie 1883:
Teraz przejdziemy do uruchomienia klientów. Zacznijmy od subskrybenta – program nazywa się mosquitto_sub. Uruchamiamy go w nowej konsoli lub z innego urządzenia:
Znaczenie poszczególnych flag:
- -t : nazwa subskrybowanego tematu
- -h : adres IP brokera. W tym przypadku broker i klient uruchomione są na tej samej maszynie – podajemy adres localhosta (w takim wypadku, nie ma konieczności ustawiania tej flagi, ponieważ jest to wartość domyślna)
- -p : numer portu (w tym przypadku także można było pominąć tą flagę, ponieważ 1883 jest wartością domyślną)
Opis wszystkich dostępnych flag można sprawdzić poprzez wpisanie w konsoli:
1 |
mosquitto_sub --help |
Po uruchomieniu, program czeka na wiadomości i jeśli jakąś otrzyma to wyświetli nam ją w konsoli. Natomiast broker pokazuje, że nastąpiło połączenie:
Czas przesłać jakąś wiadomość. Do tego celu służy program mosquitto_pub, który możemy uruchomić poprzez wpisanie w nowej konsoli:
1 |
mosquitto_pub –h 127.0.0.1 –t "test" –m "HelloWorld!" |
Jak widać doszła nowa flaga:
- -m : treść przesyłanej wiadomości.
Ja w tym przypadku zdecydowałem się wysłać coś z innego komputera, działającego pod windowsem. Wygląda to identycznie: klienta także uruchamiamy z poziomu konsoli. Jedyne o czym należy pamiętać to przejście do katalogu, gdzie został zainstalowany mosquitto oraz podanie adresu IP hosta, na którym postawiony jest broker, a nie localhosta.
I w ten oto sposób do naszego subskrybującego klienta doszła wiadomość:
Jak widać sprawa wygląda bardzo prosto. Polecam jeszcze pokombinować z różnymi hostami, portami, nazwami tematów i zobaczyć co się dzieje 🙂
Tematy wiadomości
Dotychczas używaliśmy najprostszych nazw tematów. Warto trochę dokładniej omówić to zagadnienie. Po pierwsze wielkość liter ma znaczenie i nazwy tematów „Test” oraz „test” będą traktowane jako dwa różne. Kolejną, bardzo istotną rzeczą jest to, że istnieje możliwość tworzenia tematów wielopoziomowych i warto z tej możliwości korzystać 🙂 W takiej sytuacji każdy poziom oddzielamy znakiem „/”, np.:
1 2 3 |
warehouse/01/temperature warehouse/01/humidity warehouse/02/temperature |
Dzięki wprowadzonej wielopoziomowości klient ma możliwość subskrypcji grupy tematów i służą do tego znaki specjalne. Klient może subskrybować temat „warehouse/01/temperature” i otrzymywać temperaturę z magazynu pierwszego, ale może też poprosić brokera o temperatury ze wszystkich magazynów. W takiej sytuacji wykorzystywany jest znak „+”:
1 |
warehouse/+/temperature |
Co istotne, znak „+” obejmuje tylko jeden poziom. To znaczy, że subskrybent otrzyma wiadomości z tematami:
1 2 |
warehouse/01/temperature warehouse/02/temperature |
ale z tematami:
1 2 |
office/01/temperature warehouse/01/humidity |
już nie.
Istnieje także możliwość subskrypcji tematów z wielu poziomów, ale w takim wypadku należy wykorzystać znak „#”. Dla przykładu, klient subskrybujący temat „warehouse/01/#” będzie otrzymywał wiadomości o tematach:
1 2 3 |
warehouse/01/temperature warehouse/01/humidity warehouse/01/temperature/... |
A w przypadku subskrypcji „warehouse/#” będzie otrzymywał wartości wszystkich parametrów ze wszystkich magazynów. Inaczej mówiąc, dostanie wszystkie wiadomości o tematach rozpoczynających się od „warehouse/„.
QoS – Quality of Service
Przy transmisji danych w sieciach komputerowych dosyć często spotykanym pojęciem jest tzw. QoS – Quality of Service. Jest ono także wykorzystywane w przypadku protokołu MQTT, który zapewnia trzy poziomy QoS w odniesieniu do gwarancji dostarczania wiadomości pomiędzy serwerem i klientami.
- QoS0 (at most once): wiadomość może zostać dostarczona co najwyżej raz lub nie zostać dostarczona w ogóle. Przy tak ustawionej wartości QoS wiadomości nie są przechowywane przez nadawcę (broker lub publisher) i nie są wykorzystywane potwierdzenia odbioru oraz realizowane ewentualne retransmisje.
- QoS1 (at least once): wiadomość zostanie dostarczona co najmniej raz, ale może także dojść do zduplikowania wiadomości. Przy tak ustawionej wartości QoS wykorzystywane są potwierdzenia odbioru i nadawca przechowuje wiadomości na wypadek konieczności retransmisji.
- QoS2 (exactly once): wybór tej wartości QoS zapewnia najwyższą jakość i gwarantuje dostarczenie wiadomości dokładnie raz. Wymaga jednak najbardziej złożonego systemu potwierdzeń przez co transmisja trwa najdłużej.
Warto jeszcze tutaj zwrócić uwagę na jedną rzecz: publisher przesyłając wiadomość do brokera ustawia jej określoną wartość QoS. Subscriber odbierający wiadomość od brokera także może to robić z dowolną wartością QoS. W związku z tym, poziom QoS jednej wiadomości przekazywanej na drodze publisher – broker i broker – subscriber może mieć różne wartości. Dlatego wiadomość wysłana przez publishera z QoS1 lub QoS2 mimo wszystko może nie dojść do subscribera, jeśli ten będzie subskrybwał dany temat z QoS0.
Podsumowanie
No i podstawową teorię oraz najważniejsze informacje dotyczące protokołu MQTT mamy za sobą 😉 Jak wspominałem na początku, MQTT jest świetnym protokołem dla aplikacji IoT, więc jeśli interesuje Cię ta tematyka to zdecydowanie warto poznać go trochę dokładniej – do przepracowania jest jeszcze kilka zagadnień 🙂
Na razie do obsługi klientów wykorzystaliśmy gotowe programy z poziomu konsoli. W następnym wpisie zajmiemy się tematem implementacji klienta, aby móc napisać własny program umożliwiający wysyłanie lub subskrybowanie wiadomości. Do zobaczenia w kolejnej części 🙂