hmibook

Розроблення людино-машинних інтерфейсів та систем збирання даних з використанням програмних засобів SCADA/HMI

Головна > 4.Підсистема введення/виведення

4.5. Протокол MQTT

4.5.1. Загальні принципи функціонування MQTT

У підрозділі 9.4 показано структури промислового Інтернету речей, де засоби взаємодіють між собою через мережу Інтернет безпосередньо, або через комунікаційні шлюзи. При такому обміні може й не бути явно виділеного сервера, куди треба передавати дані, адже IoT передбачає зв’язок “речей” між собою, а не з централізованим “концентратором” даних. Тому поряд з використанням HTTP API та WebSocket, в IoT є спеціальні протоколи Інтернету речей, такі як AMQP, MQTT, STOMP та інші, які не передбачають зв’язку типу клієнт-сервер. У цих протоколах одні засоби розміщують повідомлення в буфері або стеці, інші – зчитують їх. MQTT є одним з таких.

MQTT може використовуватися як протокол обміну територіально-розподілених засобів IoT з центральним диспетчерським пунктом SCADA, які його підтримують. У даному випадку SCADA-сервер не обов’язково повинен знаходитися на ПК, який має виділену IP-адресу, а також може бути за NAT та не потребує відкритих вхідних TCP/UDP портів, що робить це рішення простішим і безпечнішим (див. підрозділ 9.5).

MQTT свого часу був внутрішнім і пропрієтарним протоколом для IBM протягом багатьох років. У 2010 р. він був випущений у версії 3.1 в якості безкоштовного продукту, у 2013 р. – стандартизований і прийнятий в консорціум OASIS, у 2014 р. – OASIS опублікував його публічно як версію MQTT 3.1.1. MQTT також є стандартом ISO (ISO / IECPRF 20922).

Протокол MQTT ґрунтується на стеці TCP/IP. У ньому використовується модель публікації-підписування (publish-subscribe, або pub/sub). Клієнт, що передає повідомлення, називається видавцем (publisher); клієнт, який отримує повідомлення – абонентом (subscriber). У центрі знаходиться MQTT-брокер (MQTT broker), який несе відповідальність за обмін повідомленнями між клієнтами і фільтрацію даних (рис. 4.70). Таким способом йде відокремлення клієнта, що відправляє повідомлення, від іншого клієнта, який отримує повідомлення. На відміну від традиційної моделі клієнт-сервер, клієнти, що публікують і підписуються на повідомлення, не обізнані про будь-які фізичні ідентифікатори інтерфейсів пристроїв або застосунків (на зразок IP-адреси, або TCP/UDP порту). Вони знають тільки про розміщення в мережі брокера, через який відбувається обмін. У MQTT може бути багато видавців і багато абонентів.

Абонент, підписуючись під отримування повідомлень від видавців, використовує різноманітні фільтри, які забезпечують:

Рис. 4.70. Принцип обміну MQTT повідомленнями через брокер

Абонент може підписатися на кілька тем. Одна з особливостей моделі видавець/абонент полягає в тому, що перед початком передачі клієнти повинні знати тему гілки і формат даних, але не взаємне розміщення один одного. Це дуже корисно при розгортанні IoT, оскільки IP-адреса клієнтів може бути динамічною або/та приватною.

MQTT є часово-незалежним протоколом. Це значить, що повідомлення, опубліковане одним клієнтом-видавцем, може бути прочитане абонентом в будь-який час. Абонент може перебувати в місці з низьким енергоспоживанням або обмеженою пропускною здатністю і відповісти на повідомлення через кілька хвилин або годин.

Брокери можуть бути розгорнуті на будь-якому загальнодоступному усім клієнтам ресурсі і мати виділену і відому їм адресу. При реалізації IoT з використанням хмарних платформ, функцію брокера бере на себе відповідний сервіс. Керовані хмарою брокери MQTT зазвичай можуть поглинати мільйони повідомлень на годину і підтримувати десятки тисяч видавців.

MQTT не залежить від формату даних. Корисне навантаження (payload) може містити будь-який тип даних, тому і видавці, і абоненти повинні розуміти і погоджувати формат даних. У корисному навантаженні можна передавати текстові повідомлення, дані зображення, звукові дані, зашифровані дані, двійкові дані, об’єкти JSON або практично будь-яку іншу структуру. Тим не менше, текстові і двійкові дані JSON є найбільш поширеними типами даних корисного навантаження.

Максимально допустимий розмір пакета в MQTT становить 256 Мб, що дає можливість отримати надзвичайно велике корисне навантаження. Зверніть увагу, що це також залежить від обмеження клієнтів, хмарних сервісів (якщо використовуються) і брокера. Наприклад, хмарний сервіс IBM Watson дає змогу оброблювати дані розміром до 128 Кб, а Google підтримує 256 Кб. З іншого боку, опубліковане повідомлення може включати корисне навантаження нульової довжини, тобто поле корисного навантаження не обов’язкове. Доцільно звірити відповідність розмірів корисного навантаження з хмарним провайдером або конкретною реалізацією брокера.

В Інтернеті є безкоштовні MQTT брокери, використовуючи які можна обмінюватися між пристроями IoT, не маючи власного сервера або виділеного хмарного сервісу для MQTT. Серед найбільш відомих MQTT брокерів є:

4.5.2. Деталі архітектури MQTT

MQTT може зберігати повідомлення в брокері необмежено довго. Цей режим роботи керується відповідним прапорцем. Збережене на брокері повідомлення відправляється будь-якому клієнту, який підписується на цю тематичну гілку MQTT. При підписуванні повідомлення негайно відправляється новому абоненту, що дозволяє йому отримати статус або сигнал з теми без очікування. Може виникнути ситуація, що абонент може очікувати годину або навіть дні, перш ніж видавець опублікує нові дані.

MQTT означує додатковий об’єкт під назвою Остання воля і заповіт (LWT). LWT – це повідомлення, яке вказує клієнт брокеру на етапі підключення. LWT містить назву теми “Останньої волі” (Last-Will Topic), QoS (Last-Will QoS) і фактичне повідомлення (Last-Will Message; див. рис. 4.71). Якщо клієнт неправильно відключається від брокерського з’єднання (наприклад, тайм-аут keep-alive, помилка введення-виведення або клієнт закриває сеанс без відключення), тоді брокер зобов’язаний транслювати повідомлення LWT усім іншим підписаним на цю тему клієнтам.

Рис. 4.71. Вікно тестового MQTT-клієнта

Незважаючи на те, що MQTT заснований на TCP, з’єднання можуть обриватися, особливо в разі бездротових датчиків. Пристрій може втратити живлення, зв’язок або може відбутися поломка, і сеанс перейде в напіввідкритий стан (тобто, з одного боку, вважається, що з’єднання є, а з іншого – його немає). У цьому випадку TCP-сервер брокера буде вважати, що з’єднання, як і раніше, є надійним і очікуватиме дані. Щоб вийти з цього напіввідкритого стану, MQTT використовує систему keep-alive (утримування). Використовуючи цю систему, як брокер MQTT, так і клієнт мають гарантію того, що з’єднання залишається працездатним, навіть якщо протягом деякого часу не було передачі. Значення часу утримування задає клієнт при підключенні (див. рис. 4.71). Після отримання чергового будь-якого пакета, таймери keep-alive скидаються на клієнті і сервері і починають відлік. Якщо протягом часу keep-alive клієнти не мають даних для відправлення, вони повинні відправити пакет PINGREQ брокеру, який, у свою чергу, підтверджує повідомлення за допомогою PINGRESP. Якщо протягом півтори часу keep-alive пакет не буде отримано, брокер закриє з’єднання і відправить LWT-пакет усім клієнтам. Максимальний час keep-alive – 18 годин 12 хвилин 15 секунд.

MQTT дає також можливість підтримувати постійні сеанси (persistent session). Постійний сеанс зберігає на стороні брокера таке:

Для цього клієнт при підключенні вказує свій client_id (див. рис. 4.71). Клієнт може запитувати постійний сеанс, проте брокер може відхилити запит і примусово перезапустити новий сеанс. При з’єднанні з брокером клієнт використовує прапорець cleanSession (див. рис. 4.71), щоб показати відсутність необхідності постійного сеансу. Клієнт за допомогою повідомлення-відповіді CONNACK може визначити, чи зберігся попередній сеанс.

Постійні сеанси повинні використовуватися для клієнтів, які мають отримувати всі повідомлення, навіть якщо немає зв’язку. Вони не повинні використовуватися в ситуаціях, коли клієнт тільки публікує (записує) дані в теми.

Більше інформації про MQTT можна прочитати в [21].

4.5.3. Рівні якості обслуговування MQTT

У MQTT є три рівні якості обслуговування передачі повідомлень (рис. 4.72):

Рис. 4.72. Рівні обслуговування MQTT

QoS в MQTT визначається і контролюється відправником, і в кожного відправника може бути своя політика. Типові випадки використання:

4.5.4. Установлення з’єднання та обмін повідомленнями в MQTT

MQTT ґрунтується на з’єднаннях клієнтів із сервером-брокером. Кожен клієнт ідентифікує себе з використанням унікального імені, за яким брокер може регулювати правила підключення. Для безпечності з’єднання може також використовуватися ідентифікація користувача та пароль. Також можна використовувати шифровану передачу над TLS/SSL (див. підрозділ 9.5).

З’єднання з використанням MQTT починається з того, що клієнт відправляє повідомлення CONNECT брокеру. Тільки клієнт може ініціювати сеанс, і жоден клієнт не може безпосередньо зв’язатися з іншим клієнтом. У відповідь на повідомлення CONNECT брокер завжди буде відсилати CONNACK і код статусу. Після встановлення з’єднання воно починає працювати.

Рис. 4.73. Послідовність установлення обміну по MQTT для передачі

У табл. 4.9 наведено дані для з’єднання в процедурі CONNECT MQTT.

Таблиця 4.9.

Значення полів при з’єднанні клієнта з брокером.

Поле Обов’язкове поле Опис
clientID Так Ідентифікує клієнта не сервері. Кожний клієнт має унікальний ідентифікатор, від 1 до 23 байт UTF-8
cleanSession Ні 0: сервер повинен відновити сеанс із клієнтом; клієнт і сервер повинні зберегти стан сеансу після відключення; 1: клієнт і сервер повинні відмінити попередній сеанс і почати новий
username Ні Ім’я, що використовується сервером для автентифікації
password Ні Пароль
lastWillTopic Ні Тема (topic) гілки для публікації повідомлення “останньої волі”
lastWillQos Ні Рівень QoS (0…2) повідомлення “останньої волі”
lastWillMessage Ні Корисне навантаження (payload) повідомлення “останньої волі”
lastWillRetain Ні Чи зберігається повідомлення “останньої волі” після публікації
keepAlive Ні Інтервал часу в секундах keep-alive (утримування)

При відповіді CONNACK сервер (брокер) буде повертати код відповіді, які наведені в табл. 4.10.

Таблиця 4.10.

Коди відповідей клієнта.

Код відповіді Опис
0 Успішне з’єднання
1 У з’єднанні відмовлено : неприйнятна версія протоколу MQTT
2 У з’єднанні відмовлено : ідентифікатор клієнта – це правильний UTF-8, однак не дозволений сервером
3 У з’єднанні відмовлено : сервер недосяжний
4 У з’єднанні відмовлено : неправильне ім’я користувача чи пароль
5 У з’єднанні відмовлено : клієнт не авторизований для з’єднання

Клієнт MQTT може публікувати повідомлення, як тільки він підключається до брокера. MQTT використовує фільтрування повідомлень на брокері на основі тем. Кожне повідомлення має містити тему, яку брокер може використовувати для пересилання повідомлення зацікавленим клієнтам. Як правило, кожне повідомлення має корисну інформацію, яка містить дані для передачі у форматі байтів MQTT.

Клієнт, що публікує дані (видавець) вирішує, які дані він хоче відправити: двійкові, текстові, XML або JSON. Повідомлення публікації (PUBLISH) у MQTT має кілька атрибутів, які вказані в табл. 4.11.

Таблиця 4.11.

Атрибути повідомлення PUBLISH

Поле Обов’язкове поле Опис
packetID Так Унікально ідентифікує пакет у змінному заголовку. Для QoS-0 завжди 0
topicName Так Тема гілки для публікації (наприклад, Drive/Speed)
qos Так Рівень QoS (0…2)
retainFlag Так Прапорець, який показує, чи буде дане повідомлення зберігатися як останнє хороше; якщо новий клієнт підпишеться під дану гілку, то він автоматично отримає це повідомлення
payload Ні Корисне навантаження
dupFlag Так Прапорець, який показує, що повідомлення є дублікатом і відправлено повторно

Коли клієнт надсилає повідомлення до MQTT брокера для публікації, брокер читає повідомлення, підтверджує його (відповідно до рівня QoS) і обробляє. Оброблення брокером включає в себе визначення того, які клієнти підписалися на тему та надсилання їм повідомлення.

Клієнт, який спочатку публікує повідомлення, турбується тільки про доставку повідомлення PUBLISH брокерові. Як тільки брокер отримує повідомлення PUBLISH, він зобов’язаний доставити його всім абонентам. Видавець не отримує жодних відгуків щодо того, хто цікавиться опублікованим повідомленням чи скільки клієнтів отримали повідомлення від брокера.

Щоб отримувати повідомлення на потрібні теми, клієнт надсилає до брокерові MQTT повідомлення SUBSCRIBE (рис. 4.74). Це повідомлення містить унікальний ідентифікатор пакета та список підписувань на теми (перелік topicID). Кожна підписка складається з теми та рівня QoS. Тема в повідомленні підписки може містити підстановки, які дають змогу підписатися на теми за вказаним шаблоном, а не на одну конкретну тему. Якщо для одного клієнта існує паралельне підключення, то брокер доставляє повідомлення, яке має найвищий рівень QoS для цієї теми.

Таблиця 4.12.

Атрибути повідомлення SUBSCRIBE

Поле Обов’язкове поле Опис
packetID Так Унікальний ідентифікатор пакета
topic_1 Так Перша гілка, на яку підписується клієнт
qos_1 Так Рівень QoS (0…2) для першої гілки
topic_2 Ні Друга гілка, на яку підписується клієнт
qos_2 Ні Рівень QoS (0…2) для другої гілки

Рис. 4.74. Підписування на повідомлення по MQTT

Для підписування на декілька тем в одному повідомленні можуть використовуватися знаки підстановки. Детальніше про це – в наступному параграфі. Щоб підтвердити кожне підписування, брокер надсилає Клієнту повідомлення про підтвердження SUBAK. Це повідомлення містить ідентифікатор пакета оригінального повідомлення SUBSCRIBE (щоб чітко ідентифікувати повідомлення) та список кодів повернення:

0 – Успішно, Maximum QoS 0;

1 – Успішно, Maximum QoS 1;

2 – Успішно, Maximum QoS 2;

128 – Відмова.

Для відписки від теми використовується пакет Unsubscribe.

4.5.5. Теми повідомлень та використання шаблонів MQTT

У MQTT слово “тема” (“topic”) відноситься до рядка UTF-8, який брокер використовує для фільтрування повідомлень для кожного зв’язаного клієнта. Тема складається з одного або декількох рівнів. Кожен рівень теми розділений косою рискою (“/” – роздільник рівня теми):

Клієнтові не потрібно створювати потрібну тему, перш ніж її публікувати або підписатися на неї. Брокер приймає кожну дійсну тему без попередньої ініціалізації. Кожна тема повинна містити щонайменше 1 символ, рядок теми може мати пробіли. Теми є чутливими до регістру.

Коли клієнт підписується на тему, він може підписатися на конкретну тему опублікованого повідомлення або використовувати шаблони для підписування на кілька тем одночасно. Шаблони (Wildcards) можуть використовуватися лише для підписування на теми, а не для публікації повідомлення. Існує два різних типи шаблонів: single-level (однорівневий) та multi-level (багаторівневий).

Як випливає з назви, однорівневий шаблон замінює один рівень теми. Символ “+” є однорівневим символом у темі:

Будь-яка тема відповідає вказаній в однорівневому шаблоні, якщо вона містить довільний рядок замість символу підстановки (“+”) у шаблоні. Наприклад, підписування на

myhome/groundfloor/+/temperature

може дати такі результати (зелена галочка – відповідність фільтру):

Багаторівневий шаблон охоплює багато рівнів тем і позначається символом “#”. Для того щоб брокер визначив, які теми збігаються, багаторівневий підзаголовок слід розміщувати як останній символ у темі, перед яким передує коса риска:

Якщо клієнт підписується на тему з багаторівневим шаблоном, він отримує всі повідомлення тем, які починаються з шаблону перед символом підстановки, незалежно від того, яка довга назва цієї теми. Якщо ви вказали лише багаторівневий шаблон як тему (#), ви отримуєте всі повідомлення, які надсилаються брокерові MQTT.

Як правило, клієнти можуть публікувати теми MQTT з будь-якими назвами, за винятком тих, що починаються із символу “$”. Такі теми зарезервовані для внутрішньої статистики брокера MQTT, тому клієнти не можуть публікувати повідомлення з такими назвами тем. Наразі немає офіційної стандартизації на використання тем з “$”. Зазвичай використовується теми з “$SYS”, але реалізація брокерів змінюється. Для прикладу нижче за тему вибрано повний шлях до деяких системних тем, доступних для брокера mosquito:

Більше інформації про MQTT можна прочитати в [21].

<– 4.4. Протокол Simatic S7

–> Розділ 5. Людино-машинний інтерфейс