Глава 1. Установка сервера Mosquitto MQTT 3.1.1

В этой главе мы начнём своё путешествие по направлению применения самого предпочтительного IoT протокола обмена сообщениями издатель- подписчик с малым весом в разнообразных IoT решениях, комбинирования с мобильными прикладными программами и веб приложениями. Мы изучим как рабоатет MQTT и его система обмена сообщениями.

Мы разберёмся в мозаике MQTT: клиенты, серверы (ранее именовавшиеся брокерами) и соединения. Мы ознакомимся с процедурами установки сервера Mosquitto MQTT 3.1.1 в Linux, macOS и Windows. Мы изучим особенности запуска сервера Mosquitto в облачном решении (Azure, AWS и прочих поставщиков). Мы разберёмся со следующим:

  • Понимание подходящих сценариев для протокола MQTT

  • Работа с шаблоном издатель- подписчик

  • Работа с фильтрацией сообщений

  • Понимание мозаики MQTT: клиенты, серверы и соединения

  • Установка сервера Mosquitto в Linux

  • Установка сервера Mosquitto в macOS

  • Установка сервера Mosquitto в Windows

  • Вопросы запуска сервера Mosquitto в облачном решении

Понимание подходящих для протокола MQTT сценариев

Представим себе что у нас имеются десятки различных устройств, которые должны обмениваться данными между собой. Эти устройства должны запрашивать данные у прочих устройств, а те устройства, которые получают подобные запросы должны отвечать данными. Те устройства, которые запрашивают необходимые им данные, должны обрабатывать эти получаемые с других устройств данные, на которые отвечают требуемыми данными.

Эти устройства являются платами IoT (Internet of Things), которые обладают десятками зашитыми в них датчиками. У нас имеются следующие платы IoT с различными по мощности процессорами:

  • Raspberry Pi 3 Model B+

  • Qualcomm DragonBoard 410c

  • Udoo Neo

  • BeagleBone Black

  • Phytec phyBoard-i.MX7-Zeta

  • e-con Systems eSOMiMX6-micro

  • MinnowBoard Turbot Quad-Core

Каждая из этих плат способна отправлять и принимать данные. Кроме того, мы хотим чтобы веб приложения имели возможность отправлять и принимать данные. Мы желаем отправлять и принимать данные в близком к реальному масштабе времени через Интернет, и при этом мы можем сталкиваться с некоторыми сетевыми проблемами: наши беспроводные сетевые среды порой ненадёжны и у нас имеются некие среды с высокой латентностью (с большими задержками). Некоторые устройства имеют небольшую мощность, многие из них запитываются от батарей, а их ресурсы очень скудны. Кроме того, мы обязаны заботиться о применении общей пропускной способности сетевой среды, так как некоторые из устройств применяют платные соединения.

[Замечание]Замечание

Платные соединения (metered connections) являются сетевыми соединениями, в которых у нас имеется предельный объём использования данных в месяц. Если мы выходим за этот предел данных, мы получаем регистрацию обмена по высокому тарифу.

Мы можем применять запросы HTTP и выполнять построение модели издатель- подписчик для обмена данными между различными устройствами. Однако, существует некий протокол, который был специально разработан с тем, чтобы обладать меньшим весом чем протоколы HTTP 1.1 и HTTP/2. Протокол MQTT (MQ Telemetry Transport) лучше приспособлен для ситуации в которой большое число устройств должно обмениваться между собой данными в близком к реальному масштабе времени через интернет и когда нам нужно потреблять по возможности как можно меньше сетевой полосы пропускания. Этот протокол работает лучше чем HTTP 1.1 и HTTP/2 когда вовлечены в процесс ненадёжные сетевые среды, а связь прерывается время от времени.

Пртокол MQTT является протоколом machine-to-machine (M2M и связи IoT. MQTT является протоколом с малым весом обмена сообщениями , который при работе основывается на механизме издатель- подписчик поверх TCP/IP (Transmission Control Protocol/Internet Protocol). Приводимая далее схема отображает как наш протокол MQTT находится в вершине общего стека TCP/IP:

 

Рисунок 1-1



[Замечание]Замечание

Наиболее популярными версиями MQTT являются 3.1.1 и 3.1. В этой книге мы будем работать с MQTT 3.1.1. Всякий раз когда мы ссылаемся на MQTT, мы подразумеваем MQTT 3.1.1., самую новую версию данного протокола. Спецификация MQTT 3.1.1 была принята в качестве стандарта консорциумом OASIS. Кроме того, MQTT 3.1.1 стал и неким стандартом ISO (ISO/IEC 20922) в 2016.

MQTT обладает меньшим весом чем протоколы HTTP 1.1 и HTTP/2 и следовательно он является более интересным вариантом когда мы должны отправлять и принимать даннык в близком к реальному масштабе времени с применением модели издатель- потребитель и при этом требует самый низкий из возможных отпечаток. MQTT очень популярен в IoT, M2M, а также во встраиваемых проектах, но он также и получил присутствие в веб приложениях и мобильных прикладных программах, которым требуется гарантированный обмен сообщениями и некое эффективное распространение сообщений. Подводя итог, MQTT подходит для следующих областей приложений, в которых требуется обмен данными:

  • Отслеживание ресурсов и управление ими

  • Интегрированные средства передачи и обработки информации автомобилей

  • Регистрация химикатов

  • Мониторинг среды и трафика

  • Автоматизация сотрудников на полях

  • Контроль пожара и утечек газа

  • Автоматизация дома

  • Бортовая информационно- развлекательная система (IVI, In-Vehicle Infotainment)

  • Медицина

  • Обмен сообщениями

  • Киоски пунктов продаж (POS, Point of Sale)

  • Железные дороги

  • Радиочастотная идентификация (RFID, Radio-Frequency Identification)

  • Диспетчерское управление и сбор данных (SCADA, Supervisory Control and Data Acquisition)

  • Игровые автоматы (Slot machines)

Суммируя, MQTT был разработан чтобы отвечать поддержке следующих типичных вызовов в IoT, M2M, встраиваемых и мобильных приложениях:

  • Обладать малым весом с тем, чтобы быть способным передавать большие объёмы данных без гигантских накладных расходов

  • Распространять минимальные пакеты данных в гигантских объёмах

  • Сопровождать ориентированную на события парадигму активной доставкой асинхронных, двунаправленных сообщений с низкой латентностью

  • Простой эмиссией данных от одного клиента множеству клиентов

  • Создание возможности ожидания событий всякий раз когда они происходят (ориентированная на события архитектура)

  • Поддерживать модели постоянной связи и эпизодической связи

  • Публиковать информацию в ненадёжных сетях и предоставлять надёжные доставки поверх хрупких соединений

  • Очень хорошо работать с запитываемыми от батарей устройствами или с приборами с низким энергопотреблением

  • Предоставлять оперативность чтобы сделать возможной достижения близкой к реальному времени доставки информации

  • Предлагать безопасность и приватность всем имеющимся данным

  • Иметь возможность предоставления необходимой масштабируемости для распространения данных на сотни тысяч клиентов

Работа с шаблоном издатель- подписчик

Прежде чем углубляться в MQTT, мы должны разобраться с шаблоном издатель- подписчик, также именуемым шаблоном pub-sub (publish-subscribe). В этой схеме издатель- подписчик некий публикующий сообщение клиент отвязан от другого клиента или клиентов, которые получают данное сообщение. Сами клиенты даже не знают о существовании таких иных клиентов. Некий клиент может публиковать сообщения определённого типа и лишь те клиенты, которые интересуются этим особым типом сообщения будут получать такие опубликованные сообщения.

Данная модель издателя- подписчика требует некий сервер, также именуемый брокером. Все его клиенты устанавливают какое- то соединение с этим сервером. Некий клиент, который отправляет сообщение через такой сервер именуется издателем (publisher). Сам сервер фильтрует все входящие сообщения и распределяет их по своим клиентам, которые высказали заинтересованность в данном типе сообщений на приём. Клиенты, зарегистрированные в этом сервере, как проявившие заинтересованность в определённом виде получаемых сообщений называются подписчиками (subscribers). Таким образом, и здатели и подписчики устанавливают некое соединение с имеющимся сервером.

Для более наглядного понимания того как работают вещи проще рассмотреть пример схемы. Приводимый ниже рисунок показывает одного издателя и двух подписчиков подключёнными к серверу:

 

Рисунок 1-2



Плата Raspberry Pi 3 Model B+ с датчиком высоты зашита в своём издателе, который устанавливает некое соединение с основным сервером. Плата BeagleBone Black и плата Udoo Neo являются двумя подписчиками, которые устанавливают соединение с тем же сервером.

Плата BeagleBone Black обозначает своему серверу, что она желает подписываться на все относящиеся к sensors/drone01/altitude. Вторая плата Udoo Neo указывает то же самое своему серверу. Следовательно, обе платы подписаны на тему sensors/drone01/altitude.

[Замечание]Замечание

Тема (topic) обозначает некий логический канал, и она также может именоваться каналом или объектом. Имеющийся сервер будет отправлять подписчиками только сообщения с темами на которые те подписаны.

Плата Raspberry Pi 3 Model B+ публикует сообщение с полезной нагрузкой 100 feet (100 футов) и sensors/drone01/altitude в качестве темы. Данная плата, то есть наш издатель, отправляет этот публикуемый запрос в соответствующий сервер.

[Замечание]Замечание

Данные для некоторого запроса именуются как полезная нагрузка (payload). Собщение сожержит темы к которым оно относится и саму полезную нагрузку.

Наш сервер распространяет данное сообщение своим двум клиентам, которые подписаны на обозначенную тему sensors/drone01/altitude: и плате BeagleBone Black, и плате sensors/drone01/altitude.

Издатели и подписчики разъединены в пространстве, так как они не осведомлены друг о друге. Издетели и подписчики не обязаны исполняться в одно и то же время. Определённый издатель может публиковать некое сообщение, а конкретный получатель может получать его позднее. Кроме того, данная операция публикации никоим образом не синхронизируется с соответствующей операцией приёма.

Издатель запрашивает свой сервер о публикации сообщения и те различные клиенты, которые подписаны на соответствующие темы, могут получать это сообщение в различные времена. Сам издатель может отправлять сообщение как некую асинхронную операцию во избежание блокировки до того момента пока его сервер не получит данное сообщение. Однако, у него также имеется возможность отправлять сообщение в свой сервер и в виде синхронной операции с данным сервером и продолжать работу только после того как операция завершится успехом. В большинстве случаев мы желаем получать преимущества асинхронных операций.

Издатель, запрашивающий отправку некоторого сообщения сотням клиентов может осуществлять это вего лишь одной операцией публикации в каком- то сервере. Сам сервер отвечает за отправку опубликованного сообщения всем клиентам, которые подписались на соответствующую тему. Так как издатели и подписчики разъединены, издатель не знает имеются ли какие- бы то ни было подписчики, которые ожидают сообщения, которые он собирается отправлять. Следовательно, порой требуется чтобы подписчик сам стал издателем и опубликовал сообщение, указывающее то, что он получил и обработал сообщение. Конкретные требования зависят от вида решения, которое мы выстраиваем. MQTT предлагает множество функций, которые облегчают нашу жизнь в большом числе ситуаций, которые мы анализировали. На протяжении данной книги мы будем применять эти различные свойства.

Работа с фильтрацией сообщений

Наш сервер должен обеспечить что только лишь те подписчики, которые в нём заинтересованы. имеется возможность выполнять фильтрацию на основе различных критериев в рамках модели издатель- подписчик. Мы сосредоточимся на анализе фильтрации на основе тем (topic-based), также именуемой фильтрацией на основе предмета (subject-based).

Рассмотрим вариант когда каждое сообщение относится к некоторой теме. Когда издатель запрашивает сервер опубликовать некое сообщение, он должен определить и тему и сообщение. Основной сервер получает данное сообщение и доставляет его всем подписчикам, которые подписались на ту тему, к которой относится данное сообщение.

У сервера нет необходимости проверять имеющуюся полезную нагрузку для подлежащего доставке соответствующим подписчикам сообщения; ему всего лишь требуется проверять содержимое темы для каждого появляющегося сообщения и необходимо выполнять фильтрацию перед его публикацией для соответствующих подписчиков.

некий подписчик может быть подписан на более чем одну тему. В данном случае наш сервер обязан удостовериться что этот подписчик получит сообщения, которые относятся ко всем темам на которые он подписан. Будет проще уяснить как это работает посмотрев на приводимую ниже схему.

На следующей схеме показаны два публикующих в будущем издателя, которые пока ещё не публиковали никаких сообщений, сервер, и два подписчика, подключённых к данному серверу:

 

Рисунок 1-3



Плата Raspberry Pi 3 Model B+ с неким датчиком высоты вшитым в неё и плата Raspberry Pi 3 с каким- то датчиком температуры вшитым в неё желают быть двумя издателями. Плата BeagleBone Black и плата Udoo Neo выступают двумя подписчиками, которые установили соединение с имеющимся сервером.

Плата BeagleBone Black указывает своему серверу что она желает подписываться на все сообщения, которые относятся к теме sensors/drone01/altitude. Плата Udoo Neo указывает своему серверу что она желает подписаться на все сообщения, которые относятся к темам: sensors/drone01/altitude и sensors/drone40/temperature. Следовательно, наша плата Udoo Neo подписана на две темы, в то время как плата BeagleBone Black подписана только на одну тему.

Следующая схема показывает что происходит после того как два издателя подключатся и опубликуют сообщения с различными темами через свой сервер:

 

Рисунок 1-4



Плата Raspberry Pi 3 Model B+ публикует сообщение с 120 feet в качестве полезной нагрузки и с sensors/drone01/altitude в качетсве темы. Эта плата, то есть издатель, отправляет данное публикуемое сообщение своему серверу. Этот сервер распространяет данное сообщение лвум своим клиентам, которые подписаны на данную тему sensors/drone01/altitude: платам BeagleBone Black и Udoo Neo.

Плата Raspberry Pi 3 публикует сообщение с 75 F (75 градусов по Фарингейту) в качестве своей полезной нагрузки и sensors/drone40/temperature в качестве своей темы. Её сервер распространяет полученное сообщение всего лишь одному клиенту, который подписан на тему sensors/drone40/temperature: плате Udoo Neo. Таким образом, плата Udoo Neo получает два сообщения от своего сервера, а именно, одно относящееся к теме sensors/drone01/altitude, а второе относищееся к теме sensors/drone40/temperature.

Следующая схема показывает что происходит после публикации издателем сообщения с темой через основной сервер и тему, которая имеет только одного подписчика:

 

Рисунок 1-5



Плата Raspberry Pi 3 публикует сообщение с 76 F в качестве своей полезной нагрузки и sensors/drone40/temperature в качестве его темы. Данная плата, то есть издатель, отправляет запрос на публикацию сообщения в свой сервер. Данный сервер распространяет полученное сообщение единственному клиенту, подписавшемуся на тему sensors/drone40/temperature: плату Udoo Neo.

Знакомство с мозаикой MQTT - клиенты, серверы и соединения

В версиях протокола MQTT, предшествовавшим 3.1.1., сервер MQTT именовался рокером MQTT. Начиная с MQTT 3.1.1, этот брокер MQTT переименован в сервер MQTT, и следовательно мы будем теперь называть его сервером. Однако мы принимаем во внимание что имеющаяся документация дл серверов MQTT, инструментария и библиотек клиентов могут применять старое название брокера вместо сервера. MQTT серверы также именуются брокерами сообщений.

Сервер MQTT применяет ранее объяснённую нами фильтрацию верхнего уровня для отсеивания и распространения сообщений надлежащим подписчикам. Существует множество реализаций сервера MQTT, которые предоставляют дополнительные свойства фильтрации сообщений путём предоставления индивидуальных подключаемых модулей. {Прим. пер.: см. например реализацию RabbitMQ поверх MQTT.} Однако мы сосредоточимся на тех свойствах, которые являются частью требований протокола MQRT.

Как уже объяснялось ранее, издатели и подписчики MQTT полностью отвязаны. Издатели и подписчики являются клиентами MQTT, которые только устанавливают некое соединение с сервером MQTT. Некий клиент MQTT может быть одновременно и издателем и подписчиком, то есть, этот клиент может публиковать сообщения в определённых темах, а также принимать сообщения, относящиеся к тем темам, на которые подписан данный клиент.

Существуют библиотеки клиентов MQTT, доступные для большинства популярных языков и платформ программирования. Одна из наиболее важных вещей, которую мы должны рассмотреть при выборе клиентской библиотеки MQTT состоит в основном перечне тех свойств MQTT, которые она поддерживает и тех, которые требуются в нашем решении. Порой мы можем выбирать среди множества библиотек для некоторых определённых языка и платформы программирования, причём некоторые из них могут реализовывать не весь набор функций. На протяжении данной книги мы будем применять наиболее полные библиотеки для современных версий Python, которые поддерживают широкий диапазон платформ.

Клиентом MQTT способно стать любое устройство, у которого имеется некий стек TCP/IP и возможность использования какой- то библиотеки MQTT, то есть издателем, подписчиком, или одновременно и издателем, и подписчиком. Библиотек MQTT делает возможным устройствам общаться через MQTT поверх TCP/IP и взаимодействовать с особыми видами сервера MQTT. Например, каждый из перечисленных ниже, помимо прочих имеющихся, может стать неким клиентом MQTT:

  • Плата Arduino

  • Плата Raspberry Pi 3 Model B+

  • Плата Udoo Neo

  • iPhone

  • iPad

  • Планшет Android

  • Смартфон Android

  • Ноутбук под управлением Windows

  • Сервер под управлением Linux

  • MacBook под управлением macOS

Имеется монжество серверов MQYY, доступных для большинства популярных платформ, в том числе Linux, Windows и macOS. Многие из них являются серверами, которые могут выступать в качестве серверов MQTT и помимо этого они предоставляют дополнительные функции. Некий MQTT может реализовывать только некое подмножество из всех возможностей MQTT и может могут иметь определённые ограничения. Следовательно, очень важно проверить все возможности, которые будут требоваться в нашем решении прежде чем выбрать некий сервер MQTT. Как это происходит и спрочим программным обеспечением промежуточного уровня, у нас имеются версии с открытым исходным кодом, бесплатные версии, а также платные версии. Таким образом, мы также должны быть уверены что мы выбрали подходящий сервер на основе своего бюджета и наших специфических потребностей.

На протяжении данной книги мы будем работать с сервером MQTT Eclipse Mosquitto. Mosquitto является сервером MQTT с открытым исходным кодом с лицензией EPL/ EDL, который совместим с MQTT версий 3.1.1 и 3.1.. Мы будем применять преимущества всего что мы можем изучить в прочих серверах MQTT, таких как EMQ (Erlang MQTT Broker)) Emqttd, а также HiveMQ помимо почих. Кроме того мы можем применять наши знания работы с серверами MQTT на базе облачных решений, таких как CloudMQTT и мост MQTT PubNub. Мы специально поработаем также и с поставщиками MQTT облачных решений.

Сервер MQTT является центральных хабомимеющейся модели издатель- подписчик, которую мы проанализировали ранее. Сервер MQTT отвечает за необходимые аутентификацию и авторизацию своих клиентов MQTT, которве будут способны становиться издателями и/ или подписчиками после того как они осуществят аутентификацию и авторизацию. Поэтому, первая вещь, которую должен сделать некий клиент MQTT, это установить некое соединение со своим сервером MQTT.

Для установления соединения определённый клиент MQTT должен отправить некий управляющий пакет CONNECT своему серверу MQTT с полезной нагрузкой, которая должна содержать всю необходимую информацию для инициации данного подключения и выполнения необходимых аутентификации и авторизации. Сам сервер MQTT проверит полученный пакет CONNECT, осуществит аутентификацию и авторизацию и отправляет некий отклик этому клиенту с управляющим пакетом CONNACK, который мы подробно проанализируем после того как разберёмся со своим управляющим пакетом CONNECT. Если данный клиент MQTT отправил некий неверный управляющий пакет CONNECT, наш сервер автоматически закроет данное подключение.

Следующая схема показывает взаимодействии между клиентом MQTT и сервером MQTT для установления соединения:

 

Рисунок 1-6



[Замечание]Замечание

После успешного установления соединения между клиентом MQTT и сервером MQTT, этот сервер будет поддерживать данное соединение открытым пока его клиент не потеряет данное подключение или не пошлёт управляющий пакет DISCONNECT в данный сервер чтобы закрыть данное подключение.

Управляющий пакет CONNECT должен включать в свой состав значения для приводимых далее полей в своей полезной нагрузке, а также битлв для специальных флагов байта, который включён в данный управляющий пакет. Мы хотим разобраться со значениями этих полей и флагов, так как мы желаем иметь возможность определять их значения когда мы работаем с инструментами MQTT и библиотеками клиента MQTT в Python:

  • ClientId: Идентификатор клиента, также именуемый как client ID, является строкой, которая идентифицирует каждого клиента MQTT, который подключён к серверу MQTT. Всякий подключаемый к определённому серверу MQTT клиент обязан иметь некий уникальный ClientId, а этот сервер применяет его чтобы определять текущее состояние, которое он поддерживает для данного сеанса MQTT между конкретным клиентом и данным сервером. Если некий клиент определяет пустое значение в качестве данного ClientId, сервер MQTT обязан сгенерировать какой- то уникальный ClientId для указания на этого клиента. Однако, такое поведение зависит от значения, определяемого для поля CleanSession.

  • CleanSession: Значение флага очистки сеанса является Булевым и определяет что происходит после того как данный клиент MQTT отключается от своего сервера MQTT и затем повторно подключается. Если CleanSession установлен в 1 или True, данный клиент предписывает своему серверу MQTT что данный сеанс будет единственным и последним на протяжении времени жизни данного соединения. После того как данный клиент отключается от своего сервера MQTT, вся относящаяся к этому сеансу информация разрушается. Некое новое подключение от того же самого клиента MQTT к данному серверу MQTT не будет применять данные из своего предыдущего сеанса и это будет новый чистый сеанс. Если CleanSession установлен в 0 или False, мы будем работать с удерживаемым сеансом. В данном случае наш сервер MQTT запоминает все свои подписки для определённого клиента MQTT и когда данный клиент MQTT отключается, наш сервер MQTT сохраняет все те сообщения, которые появились с определёнными уровнями качества обслуживания, соответствующими тем подпискам, которые этот клиент имел на момент возникновения отключения. Таким образом, когда тот же самый клиент устанавливает некое новое подключение к данному серверу MQTT, этот клиент MQTT будет иметь те же самые подписки и получит все те сообщения, которые не он смог получить при утрате подключения. Мы будем погружаться глубже в уровни качества обслуживания для сообщений и их взаимосвязь с флагом очистки сеанса позднее а Главе 2, Применение инструментов командной строки и GUI для изучения того как работает MQTT.

    [Замечание]Замечание

    Когда флаг очистки сеанса установлен в 0 или False, данный клиент указывает своему серверу что он нуждается в удержании сеанса. Мы должны только запомнить что очищаемый сеанс противопоставляется удерживаемому сеансу.

  • UserName: Если данный клиент желает определить некое имя пользователя для запроса аутентификации и авторизации от данного сервера MQTT, он должен установить значение флага UserName в 1 или True и определить некое значение для самого поля UserName.

  • Password: Если данный клиент желает определить некое имя пользователя для запроса аутентификации и авторизации от данного сервера MQTT, он должен установить значение флага Password в 1 или True и определить некое значение для самого поля Password

    [Совет]Совет

    Мы уделим целую главу безопасности MQTT и, следовательно, мы просто упоминаем данные поля и флаги, которые содержатся в управляющем пакете CONNECT.

  • ProtocolLevel: Значение уровня протокла указывает саму версию протокола MQTT, которую применяют все запросы данного клиента MQTT к нашему серверу MQTT. Помните, что мы всегда будем работать с MQTT версии 3.1.1.

  • KeepAlive: KeepAlive является интервалом времени, выражаемым в секундах. Ессли значение для KeepAlive не равно 0, данный клиент MQTT фиксирует отправку управляющих пакетов к своему серверу в пределах значения времени, определяемого в KeepAlive. Если данный клиент MQTT не должен отправлять никакие управляющие пакеты, он должен отправить своему серверу MQTT некий управляющий пакет PINGREQ, какой- то запрос пинга, чтобы сообщать своему серверу MQTT что соединение данного клиента жизнеспособно. Его сервер MQTT отвечает на такой управляющий пакет PINGREQ неким откликом PINGRESP для своего клиента MQTT, какой- то отклик пинга, чтобы сообщить своему клиенту MQTT что соединение с данным сервером MQTT является жизнеспособным. В случае отсутствия данных управляющих пакетов это соединение закрывается. Если же значение для KeepAlive равно 0, данный механизм удержания отключён.

  • Will, WillQoS, WillRetain, WillTopic и WillMessage: эти флаги и поля позволяют данному клиенту MQTT получать преимущества от установленной функциональности MQTT последнего желания (last will) и завещания (testament). Если данный клиент MQTT устанавливает значения флага Will в 1 или True, это предписывает то, что он хочет чтобы сервер MQTT сохранил сообщение последнего желания связанное с данным сеансом. Значение флага WillQoS определяет желательное качество обслуживания для данного сообщения последнего желания, а флаг WillRetain указывает должно ли данное сообщение удерживаться после его публикации. Если данный клиент MQTT устанавливает значение флага Will в 1 или True, он должен определить значение темы для данного сообщения Will, а также само сообщение в полях WillTopic и WillMessage. Если данный клиент отключается или утрачивает подключение со своим сервером MQTT, этот сервер MQTT опубликует то сообщение, которое было определено в значении поля WillMessage в тему, которая указана в значении поля WillTopic с выбранным качеством обслуживания. Мы проанализируем данную функциональность позднее.

Сервер MQTT обработает правильный управляющий пакет CONNECT и это будет подтверждено в отклике управляющим пакетом CONNACK. Данный управляющий пакет будет содержать значения для приводимых ниже флагов, содержащихся в его заголовке. Мы хотим уяснить устанавливаемые значения этих флагов потому что мы желаем иметь возможность осуществлять выборку их значений при работе с инструментами MQTT и библиотеками клиента MQTT:

  • SessionPresent: Если данный сервер MQTT получает некий запрос на соединение с установленным в 1 или True флагом CleanSession, значением для флага SessionPresent будет 0 или False, так как никакой сохранённый сеанс не будет повторно применяться. Если же значение флага CleanSession было установлено в соответствующем запросе на соединение в 0 или False, данный сервер MQTT будет работать с удерживаемым сеансом и его значением для флага SessionPresent будет 1 или True если данный сервер имеет некий удерживаемый сеанс для данного клиента из предыдущего подключения и он будет восстановлен. В противном случае значением SessionPresent будет 0 или False. Тот клиент MQTT, который желает работать с удерживаемым сеансом может применять получаемое из этого флага значение для определения того должен ли он запрашивать подписку для желаемых тем, или же данные подписки будут восстановлены из имеющегося удерживаемого сеанса.

  • ReturnCode: Если значения авторизации и аутентификации переданы и данное соединение было успешно установлено, значением для ReturnCode будет 0. В противном случае значение кода возврата будет отличаться от 0 и данное сетевое соединение между клиентом и сервером будет закрыто. Следующая таблица отображает возможные значения для ReturnCode с их значениями:

    Таблица 1-1. Коды возврата
    Значение ReturnCode Описание

    0

    Данное соединение принято

    1

    Данное соединение было отклонено, так как текущий сервер MQTT не поддерживает ту версию протокола MQTT, которая запрашивается клиентом MQTT в обслуживаемом управляющем пакете CONNECT

    2

    Данное соединение было отклонено, так как значение ClientId было отклонено

    3

    Данное соединение было отклонено, так как сетевое соединение было установлено, но указанная служба MQTT не доступна

    4

    Данное соединение было отклонено, так как значения имени пользователя или пароля ошибочны

    5

    Данное соединение было отклонено, так как отказано в авторизации

Установка сервера Mosquitto в Linux

Теперь мы изучим все необходимые этапы для установки сервера Mosquitto в большинстве популярных операционных систем: Linux, macOS и Windows.

[Замечание]Замечание

Чрезвычайно важно работсть с самыми последними доступными версиями Mosquitto чтобы быть уверенным в том, что многие имевшиеся в предыдущих версиях уязвимости безопасности разрешены. К примеру, Mosquitto 1.4.15 разрешил две важные уязвимости безопасности, которые оказывали своё воздействие в версиях с 1.0 по 1.4.14 включительно.

Для начала мы начнём с Linux; в частности, мы будем работать с Ubuntu Linux. Если вы желаете работать с другим дистрибутивом Linux, вы можете разыскать подробности процедуры установки в соответствующем разделе выгруэок Mosquitto: http:/​/​mosquitto.​org/​download.

Для установки сервера Mosquitto в Ubuntu Linux придерживайтесь приводимых ниже шагов; учитывайте что вам понадобятся привелегии root:

  1. Откройте терминальное окно или воспользуйтесь безопасной оболочкой (ssh) для доступа к Ubuntu и запустите следующую команду чтобы добавить необходимый репозиторий Mosquitto:

    
    sudo apt-add-repository ppa:mosquitto-dev/mosquitto-ppa
     	   

    Вы увидите вывод похожий на следующие строки (названия временных файлов могут отличаться):

    
    gpg: keyring `/tmp/tmpi5yrsz7i/secring.gpg' created
    gpg: keyring `/tmp/tmpi5yrsz7i/pubring.gpg' created
    gpg: requesting key 262C4500 from hkp server keyserver.ubuntu.com
    gpg: /tmp/tmpi5yrsz7i/trustdb.gpg: trustdb created
    gpg: key 262C4500: public key "Launchpad mosquitto" imported
    gpg: Total number processed: 1
    gpg: imported: 1 (RSA: 1)
    OK
     	   
  2. Для обновления всех пакетов при помощи только что добавленного репозитория выполните следующую команду:

    
    sudo apt-get update
     	   

    Вы обнаружите вывод похожий на приводимый в следующих строках. Отметим, что эти строки показывают вывод некоторого сервера Ubuntu, исполняемого в качестве виртуальной машины Windows Azure и по этой причине вывод может быть похожим:

    
    Hit:1 http://azure.archive.ubuntu.com/ubuntu xenial InRelease
    Get:2 http://azure.archive.ubuntu.com/ubuntu xenial-updates
    InRelease [102 kB]
    Get:3 http://azure.archive.ubuntu.com/ubuntu xenial-backports
    InRelease [102 kB]
    
    ...
    
    Get:32 http://security.ubuntu.com/ubuntu xenial-security/universe
    Translation-en [121 kB]
    Get:33 http://security.ubuntu.com/ubuntu xenialsecurity/multiverse amd64 Packages [3,208 B]
    Fetched 12.8 MB in 2s (4,809 kB/s)
    Reading package lists... Done
     	   
  3. Теперь для установки необходимого пакета сервера Mosquitto запустите такую команду:

    
    sudo apt-get install mosquitto
     	   

    Вы увидите вывод аналогичный приводимому далее.

  4. Введите Н и нажмите Enter в ответ на вопрос и выполните процесс установки:

    
    Building dependency tree
    Reading state information... Done
    The following additional packages will be installed:
      libev4 libuv1 libwebsockets7
    The following NEW packages will be installed:
      libev4 libuv1 libwebsockets7 mosquitto
    0 upgraded, 4 newly installed, 0 to remove and 29 not upgraded.
    Need to get 280 kB of archives.
    After this operation, 724 kB of additional disk space will be used.
    Do you want to continue? [Y/n] Y
     	   
  5. и Самые последние строки должны содержать некую строку, которая сообщает Setting up mosquitto с последующим номером версии, что отбражено в приводимых ниже строках:

    
    Setting up libuv1:amd64 (1.8.0-1) ...
    Setting up libev4 (1:4.22-1) ...
    Setting up libwebsockets7:amd64 (1.7.1-1) ...
    Setting up mosquitto (1.4.15-0mosquitto1~xenial1) ...
    Processing triggers for libc-bin (2.23-0ubuntu10) ...
    Processing triggers for systemd (229-4ubuntu21.1) ...
    Processing triggers for ureadahead (0.100.0-19) ...
     	   
  6. Теперь для установки пакетов клиента Mosquitto выполните следующую команду, которая позволит нам запускать команды для публикации сообщений в темах и подписываться на фильтры тем:

    
    sudo apt-get install mosquitto-clients
     	   

    Вы обнаружите вывод похожий на приводимый далее.

  7. Введите Н и нажмите Enter в ответ на вопрос и выполните процесс установки:

    
    Reading package lists... Done
    Building dependency tree
    Reading state information... Done
    The following additional packages will be installed:
      libc-ares2 libmosquitto1
    The following NEW packages will be installed:
      libc-ares2 libmosquitto1 mosquitto-clients
    0 upgraded, 3 newly installed, 0 to remove and 29 not upgraded.
    Need to get 144 kB of archives.
    After this operation, 336 kB of additional disk space will be used.
    Do you want to continue? [Y/n] Y
     	   

    Самые последние строки содержат строку сообщающую Setting up mosquitto-clients, за чем следует номер их версии, как это показано в последующих строках:

    
    Setting up libmosquitto1:amd64 (1.4.15-0mosquitto1~xenial1) ...
    Setting up mosquitto-clients (1.4.15-0mosquitto1~xenial1) ...
    Processing triggers for libc-bin (2.23-0ubuntu10) ...
     	   
  8. Наконец, запустите приводимую ниже команду чтобы проверить текущее состояние для службы mosquitto, которую мы только что установили:

    
    sudo service mosquitto status
     	   

Самые первые строки в получаемом выводе должны быть похожи на последующие строки с отображаемым состоянием active (running). Подробности после CGroup указывают ту командную строку, которая запускает данную службу. Параметр -c, за которым следует /etc/mosquitto/mosquitto.conf, определяет что Mosquitto применяет этот файл настроек:


mosquitto.service - LSB: mosquitto MQTT v3.1 message broker
   Loaded: loaded (/etc/init.d/mosquitto; bad; vendor preset: enabled)
   Active: active (running) since Sun 2018-03-18 19:58:15 UTC; 3min 8s ago
     Docs: man:systemd-sysv-generator(8)
   CGroup: /system.slice/mosquitto.service
           └─15126 /usr/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf
 	   

Вы также можете выполнить следующую команду чтобы проверить выполняет ли ваш сервер Mosquitto ожидание по установленному по умолчанию порту, 1883.


netstat -an | grep 1883
 	   

Приводимые ниже строки показывают полученные результаты предыдущей команды, которые указывают что ваш сервер Mosquitto открыл сокеты ожидания IPv4 и IPv6 для порта 1883:


tcp 0 0 0.0.0.0:1883 0.0.0.0:* LISTEN

tcp6 0 0 :::1883 :::* LISTEN
 	   

Установка сервера Mosquitto в macOS

Для установки сервера Mosquitto в macOS, именуемой как OS X вплоть до macOS Sierra, придерживайтесь следующих этапов:

  1. Если у вас нет установленного Homebrew, откройте терминальное окно и запустите команду, указанную на домашней странице Homebrew чтобы установить этот популярный диспетчер пакетов для macOS. Приводимая далее команда выполнит это задание. Тем не менее, полезно посетить домашнюю страницу Homebrew и проверить все подробные инструкции, которые всегда обновляются с новейшими версиями macOS и которые становятся доступными. Если у вас уже установлен Homebrew, перейдите к следующему шагу:

    
    /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
     	   
  2. Откройте окно терминала и выполните следующую команду запроса Homebrew на установку Mosquitto:

    
    brew install mosquitto
     	   

    Заметим, что в некоторых случаях Homebrew может потребовать установки дополнительного программного обеспечения в вашем компьютере прежде чем вы сможете установить Mosquitto. Если понадобится установка дополнительного программного обеспечения, например, иснтрументария командной строки Xcode, Homebrew предоставит вам необходимые указания.

  3. Следующие строки показывают самые последние сообщения, отображаемые в Терминале, которые указывают что Homebrew установил Mosquitto и необходимые инструкции для запуска вашего сервера MQTT:

    
    ==> Installing dependencies for mosquitto: c-ares, openssl,
    libev, libuv, libevent, libwebsockets
    ==> Installing mosquitto dependency: c-ares
    ==> Caveats
    A CA file has been bootstrapped using certificates from the
    SystemRoots
    keychain. To add additional certificates (e.g. the certificates
    added in the System keychain), place .pem files in
    /usr/local/etc/openssl/certs and run
    /usr/local/opt/openssl/bin/c_rehash
    
    This formula is keg-only, which means it was not symlinked into
    /usr/local, because Apple has deprecated use of OpenSSL in favor
    of its own TLS and crypto libraries. If you need to have this
    software first in your PATH run:
    
    echo 'export PATH="/usr/local/opt/openssl/bin:$PATH"' >>
    ~/.bash_profile
    
    For compilers to find this software you may need to set:
    LDFLAGS: -L/usr/local/opt/openssl/lib
    CPPFLAGS: -I/usr/local/opt/openssl/include
    
    ==> Installing mosquitto
    ==> Downloading https://homebrew.bintray.com/bottles/mosquitto-
        1.4.14_2.el_capit
     #######################################################################100.0%
    ==> Pouring mosquitto-1.4.14_2.el_capitan.bottle.tar.gz
    ==> Caveats
    mosquitto has been installed with a default configuration file.
    You can make changes to the configuration by editing:
        /usr/local/etc/mosquitto/mosquitto.conf
    
    To have launchd start mosquitto now and restart at login:
      brew services start mosquitto
    
    Or, if you don't want/need a background service you can just run:
      mosquitto -c /usr/local/etc/mosquitto/mosquitto.conf
     	   
  4. После того как установка Mosquitto завершится, выполните приводимую далее программу в новом терминальном окне чтобы запустить Mosquitto с установленным по умолчанию файлом настроек. Параметр -c с последующим /usr/local/etc/mosquitto/mosquitto.conf указывает что мы хотим применять именно этот файл настроек:

    
    /usr/local/sbin/mosquitto -c /usr/local/etc/mosquitto/mosquitto.conf
     	   

    После выполнения предыдущей команды вы увидите такой вывод:

    
    1521488973: mosquitto version 1.4.14 (build date 2017-10-22 16:34:20+0100) starting
    1521488973: Config loaded from
    /usr/local/etc/mosquitto/mosquitto.conf.
    1521488973: Opening ipv4 listen socket on port 1883.
    1521488973: Opening ipv6 listen socket on port 1883.
     	   

Самая последняя строка указывает что ваш сервер Mosquitto открыл сокеты ожидания IPv4 и IPv6 для порта по умолчанию, 1883. Оставьте это терминальное окно открытым, так нам требуется запущенный на данном локальном компьютере Mosquitto чтобы работать со своими последующими примерами.

Установка сервера Mosquitto в Windows

Для установки сервера Mosquitto в Windows придерживайтесь приводимым здесь шагам. Учтите что вам понадобится Windows Vista или выше (Windows 7, 8, 8.1, 10, или последующие). Эти инструкции также работают для Windows Server 2008, 2012, 2016 и далее:

  1. Выгрузите необходимый исполняемый файл перечисленный под Binary Installation и Windows , которые предоставляют естественное построение на веб странице выгрузок Mosquitto http:/​/mosquitto.​org/​download. Для Mosquitto 1.4.15 необходимое название файла это mosquitto-1.4.15-install-win32.exe. Вам следует кликнуть или подключиться к данному имени файла и вы будете перенаправлены в соответствующий репозиторий Eclipse с большим числом вариантов зеркал, включая установленное по умолчанию, с которых вы можете выгрузить свой исполняемый файл.

  2. Запустите выгруженный ранее исполняемый файл и мастер mosquitto Setup отобразит свой блок приветствия. Кликните Next > для продолжения. Ваш мастер установки отобразит имеющиеся зависимости,которые вы обязаны установить: OpenSSL и pthreads. Данный блок диалога отобразит необходимые ссылки, которые вы можете применить для выгрузки и исполнения установок для этих двух требований, как это показано на следующем снимке экрана:

     

    Рисунок 1-7



  3. Если у вас нет установленного в Windows Win32 OpenSSL v1.0.2j Light, проследуйте на веб страницу Win32 OpenSSL и выгрузите файл Win32 OpenSSL v1.1.0g Light, перечисленные в таблице под Download Win32 OpenSSL. Не выгружайте версию Win64, так как вам требуется именно версия Win32 чтобы сделать возможными для Mosquitto иметь свои зависимости. Если у вас уже имеется установленный Win32 OpenSSL v1.1.0g Light, перейдите сразу к шагу 7. Для Win32 OpenSSL v1.1.0g Light необходимым именем файла является Win32OpenSSL_Light-1_1_0g.exe. Запустите выгруженный исполняемый файл и OpenSSL Light (32-bit) отобразит свой блок приветствия. Для продолжения кликните Next >.

  4. Появившийся мастер установки отобразит лицензионное соглашение. Прочтите его, выберите I Accept the agreement (я принимаю условия) и кликните Next >. Выберите ту папку, в которую вы желаете установить OpenSSL Light (32-bit) если вы не желаете применять предлагаемую по умолчанию. Запомните ту папку, которую вы определили, так как впоследствии вам понадобится скопировать несколько файлов DLL в эту папку. Папкой по умолчанию является C:\OpenSSL-Win32.

  5. Для продолжения кликните Next >, если это требуется, определите другую папку Start Menu и кликните Next >. Выберите The OpenSSL binaries (/bin) directory как желательный вариант для Copy OpenSSL DLLs to. Таким образом, ваша установка скопирует необходимые DLL во вложенную папку bin внутри предварительно определённой папки, по умолчанию C:\OpenSSL-Win32\bin.

  6. Для продолжения кликните Next >. Просмотрите выбранные опции установки и кликните Install для осуществления установки OpenSSL Light (32-bit). Наконец, ознакомьтесь со вкладами в проект Win32 OpenSSL и кликните Finish для того чтобы покинуть установку.

  7. В своём веб браузере перейдите на следующий адрес ftp:/​/​sources.​redhat.​com/pub/​pthreads-​win32/​dll-​latest/​dll/​x86. Для этого каталога FTP ваш браузер отобразит множество файлов. Кликните правой кнопкой по pthreadVC2.dll и сохраните это файл в свою папку Downloads. У вас будет иметься копия данного DLL для установки впоследствии его в папку Mosquitto.

  8. Теперь вернитесь в своё окно mosquitto Setup и кликните Next > для продолжения. По умолчанию Mosquitto установит все файлы и необходимую службу Mosquitto. Оставьте эти назначенные для установки по умолчанию компоненты и для продолжения кликните Next >.

  9. Выберите ту папку, в которую вы желаете установить Mosquitto если вы не хотите применять нзначаемую по умолчанию папку. Запомните определённую вами папку, так как вам понадобится позднее скопировать в эту папку несколько DLL. Папкой по умолчанию является C:\Program Files (x86)\mosquitto. Кликните Install для выполнения установки. Отметим, что mosquitto Setup может отображать ошибки, вызванные пропущенными DLL. Мы исправим эту проблему в наших последующих шагах. После того как данная установка завершится, кликните Finish чтобы закрыть данный мастер mosquitto Setup.

  10. Откройте окно File Explorer и перейдите во вложенную папку bin внутри своей установки OpenSSL Light (32-bit), по умолчанию это C:\OpenSSL-Win32\bin.

  11. Скопируйте следующие четыре DLL: libcrypto-1_1.dll, libeay32.dll, ssleay32.dll и libssl-1_1.dll. Теперь перейдите в папку, в которую вы установили Mosquitto и вставьте туда эти четыре DLL. По умолчанию папкой установки Mosquitto является C:\Program Files (x86)\mosquitto. Вам понадобятся полномочия администратора для вставки этих DLL в назначенной по умолчанию папке.

  12. Откройте окно File Explorer и перейдите в свою папку Downloads. Скопируйте выгруженный вами на одном из предыдущих шагов DLL pthreads, pthreadVC2.dll. Теперь перейдите в папку в которой у вас установлен Mosquitto и вставьте туда этот DLL. Вам понадобятся полномочия администратора для вставки этого DLL в данную папку установки Mosquitto по умолчанию.

  13. Теперь, когда все необходимые зависимости включены в папку установки Mosquitto, необходимо запустить установку снова чтобы настроить необходимую службу Windows. Запустите ранее выгруженную установку Mosquitto снова. Для Mosquitto 1.4.15 название необходимого файла mosquito-1.4.15-install-win32.exe. Убедитесь что вы определили ту же самую папку установки, что и та папка, в которую вы копировали необходимые DLL и что необходимый компонент Service активирован. Кликните Next > множество раз и кликните Install для завершения настроек для своей службы Windows. Когда установка завершится, кликните Finish чтобы закрыть свой мастер mosquitto Setup.

  14. Откройте приложение Services в Windows и отыщите службу с названием Mosquitto Broker. Кликните правой кнопкой по названию этой службы и выберите Start. Её состояние изменится на Running. По умолчанию эта служба настроена на то, чтобы иметь свой Startup Type установленным в Automatic. Если вы не желаете автоматически запускать эту службу Mosquitto Broker, замените Startup Type на Manual. Вам придётся повторять эти шаги, которые вы только что сделали, чтобы запускать данную службу перед тем как приступать к работе с Mosquitto в компьютере Windows. Отметим, что в описании данной службы указано MQTT v3.1 broker, как это отображено на следующем снимке экрана. Это описание устарело, так как данная служба представляет некий сервер MQTT 3.1.1, который также совместим с MQTT 3.1:

     

    Рисунок 1-8



Откройте окно Windows PowerShell или Command Prompt и запустите следующую команду чтобы проверить выполняет ли сервер Mosquitto ожидание по назначенному по умолчанию порту, 1883:


netstat -an | findstr 1883
		

Следующие строки отображают результаты предыдущей команды, которые указывают, что сервер MQTT Mosquitto открыл сокеты ожидания IPv4 и IPv6 для порта 1883:


TCP 0.0.0.0:1883 0.0.0.0:0 LISTENING
TCP [::]:1883 [::]:0 LISTENING
		

Связанные с запуском сервера Mosquitto в облачном решении вопросы

Мы поработали с разными установками по умолчанию для сервера Mosquitto в Linux, macOS и Windows. Наш сервер Mosquitto будет работать с TCP портом 1883. Если вы желете взаимодействовать с этим сервером Mosquitto с различных устройств или компьютеров вам придётся убедиться что ваш межсетевой экран, который исполняется на этом компьютере, имеет надлежащие настройки для данного номера порта.

Когда вы запускаете некий сервер Mosquitto в какой- то виртуальной машине Linux или Windows в соответствующем облачном решении, вам придётся убедиться что имеющаяся сетевая фильтрация данной виртуальной машины, которая управляет как входящим, так и исходящим обменом, имеет надлежащие настройки для разрешения и входящего и исходящего обменов по порту 1883. Вам следует выполнить авторизацию входящего и исходящего обменов по порту 1883.

Проверьте свои знания

Давайте рассмотрим правильно ли вы можете ответить на следующие вопросы:

  1. MQTT запускается поверх:

    1. Протокола MQTT

    2. Протокола TCP/IP

    3. Протокола IoT

  2. Данные для сообщения MQTT именуются как:

    1. Полезная нагрузка

    2. Пакет

    3. Загрузка

  3. Брокер MQTT версии 3.1.1 имеет название:

    1. Агента MQTT

    2. Клиента MQTT

    3. Сервера MQTT

  4. Mosquitto это:

    1. Сервер MQTT на базе облачного решения, который может исполняться только в Windows Azure

    2. Сервер MQTT на базе облачного решения, который может исполняться только в Amazon Web Services

    3. Сервер MQTT с открытым исходным кодом, совместимый с версиями 3.1.1 и 3.1 MQTT

  5. Назначаемый по умолчанию порт TCP, который применяет сервер Mosquitto это:

    1. 22

    2. 1883

    3. 9000

Правильные ответы приводятся в Дополнении A. Решения.

Выводы

В этой главе мы начали своё путешествие в сторону понимания самого протокола MQTT. Мы разобрались с общими сценариями для данного протокола, подробностях модели изатель- подписчик, а также фильтрации сообщений. Мы изучили базовые понятия связанные с MQTT и познакомились с его различными компонентами: клиентами, серверами или брокерами и соединениями.

Мы изучили установку сервера Mosquitto в Linux, macOS и Windows. приэтом мы воспользовались задаваемыми по умолчанию установками, так как это позволяет нам разобраться как всё обустроено под капотом пока мы будем пользоваться Mosquitto. Далее мы обезопасим свой сервер. Таким образом нам будет проще начать применять библиотеки клиентов в Python для публикации сообщений MQYY и чтобы подписываться на фильтры тем MQTT.

Теперь у нас имеется готовая среда для начала работы с пока ещё не безопасным сервером Mosquitto, мы поработаем из командной строки и инструментов GUI чтобы изучить подробнее как работает MQTT. Мы ознакомимся с основами MQTT, специфическим словарём для MQTT, а также его рабочими режимами, что является темами, которые мы намереваемся обсуждать в Главе 2, Применение инструментов командной строки и GUI для изучения того как работает MQTT.