Протокол MQTT и открытый проект клиента MQTT на Delphi
Протокол MQTT применяется для обмена сообщениями в интернете вещей. Интересен прежде всего тем, что поддерживается крупнейшими провайдерами облачных сервисов, такими как IBM, Microsoft, Amazon.
Можно бесплатно получить аккаунт в этих сервисах, настроить там службу приема MQTT сообщений и наблюдать через эти сервисы за жизнью своих устройств, например, в умном доме. Также через эти сервисы устройства могут общаться между собой.
Демонстрация подключения клиента к службе MQTT облака IBM Bluemix прилагается.
MQTT предельно примитивен: с коротким заголовком, без контроля целостности, не накладывает никаких ограничения на структуру, кодирование или схему данных. Единственное требование к данным в каждом пакете — они должны сопровождаться идентификатором информационного канала. Этот идентификатор в спецификации называется Topic Name или проще топик. Данные передаются пакетам поверх протокола TCP. Количество данных в пакете может быть от одного байта до 268 435 455 байт. Весьма гибко! Хотя публичные облачные сервисы вводят здесь более жесткие ограничения, до нескольких килобайт.
Протокол MQTT требует обязательного наличия брокера данных. Это центральная идея технологии. Все устройства посылают данные только брокеру и принимают данные тоже только от него. Брокер — это программа, выполняющая функции TCP сервера с динамической базой данных.
База данных брокера в частности содержит таблицу со всеми полученными пакетами с индексацией по топикам этих пакетов. Получив пакет, брокер рассылает его всем устройствам в сети согласно их подписке. Чтобы устройство что-то получило от брокера оно должно подписаться на топик. Топики возникают динамически по факту подписки или по факту прихода пакета с данным топиком. От подписки на топик можно и отказаться. Таким образом топики представляют собой удобный механизм организации связей разных видов: один ко многим, многие к одному и многие ко многим. Если у пакета нету подписчика, то он отбрасывается. Если подписчик не на связи, то пакет либо сразу стирается в базе брокера, либо ждет подключения подписчика некоторое заданное в конфигурации время. Вариант поведения определяется атрибутом QoS пакета.
• Устройства первыми устанавливают связь с брокером. Т.е. устройства могут находится за трансляторами сетевых адресов (NAT-ами) и не иметь статических IP адресов и это не помешает связи.
• Может быть применён протокол SSL для шифрации трафика. Но можно работать и без SSL даже с сервисами IBM, что облегчает отладку.
• В исключительно тяжёлых случаях MQTT брокеры позволяют подключаться к ним через протокол WebSocket на 80-й порт.
• Также может быть произвольно изменен порт штатного протокола MQTT.
• И клиент/клиенты с графическим пользовательским интерфейсом и брокер могут находится на одном компьютере. Т.е. решение может быть и абсолютно локальным и масштабироваться в глобальное одним кликом.
• Разные брокеры могут соединяться между собой подписываясь на сообщения друг у друга.
• Концепция топиков хорошо ложится на технологию NoSQL баз данных. С той же целью облачные сервисы склоняют пользователей использовать JSON кодирование данных.
Выбор MQTT брокеров довольно большой. Но как ни странно удобных клиентов с оконным пользовательским интерфейсом под Windows практически нет. А клиент такой для освоения протокола MQTT просто необходим поскольку за рамками спецификаций находится много практических нюансов работы брокеров и все их надо как-то изучать и тестировать.
Было решено реализовать MQTT клиента на Delphi.
Google для Delphi может предложить только компонент TMQTTClient. Но это старый и не рабочий компонент. Большинство других клиентов, написанных на языках Java, Erlang, Haskell, Javscript в Delphi интегрировать весьма проблематично.
Нашелся единственный подходящий проект — Mosquitto
Написан на чистом C-и. Компилируется под разные операционные системы. Имеет скрипты генерации проекта для Visual Studio. На выходе под Windows получаем dll файлы с реализацией функциональности клиента и брокера. Применение C-и обнадёживает по части быстродействия. А динамические библиотеки, написанные на C-и легко подключаются к программам на Delphi.
Сам Delphi в лице Embarcadero RAD Studio XE8 весьма мощный инструмент для создания гибких и удобных пользовательских интерфейсов под Windows особенно если он вооружён пакетами DevExpress, TeeChart, RxLib, FireDAC и др.
Нам понадобится среда разработки MS Visual Studio 2015. В ней будет компилироваться проект Mosquitto и все вспомогательные проекты от которых зависит Mosquitto. Альтернативно Mosquitto под Windows можно компилировать с помощью пакета Cigwin, но Visual Studio показался удобней.
Для генерации файлов проекта Visual Studio надо скачать и установить утилиту Cmake. Источник cmake.org
И разумеется нужен RAD Studio XE8. Дополнительно в RAD Studio должен быть установлен пакет компонентов DevExpress VCL версии не ниже 14.2.2. Хотя это не имеет принципиального значения, проект пользовательского интерфейса можно легко переделать и под стандартные компоненты RAD Studio.
Mosquitto зависит от нескольких сторонних проектов, это:
• OpenSSL v 1.0.2e. Источник — http://slproweb.com/download/Win32OpenSSL-1_0_2e.exe
• Pthreads v 2.9.1. Источник — ftp://sourceware.org/pub/pthreads-win32/pthreads-w32–2–9–1-release.zip
• Libwebsockets v 1.4. Источник — https://github.com/warmcat/libwebsockets
Скачиваем эти проекты.
OpenSSL не компилируем, а сразу берем от туда два нужных файла: libeay32.dll и ssleay32.dll из директории bin. Часто бывает, что на компьютере они уже установлены от других проектов. Это надо проверять.
Pthreads тоже не компилируем, а берем уже скомпилированный файл pthreadVC2.dll из директории dll\x86.
Libwebsockets идет без заранее скомпилированных файлов и без проекта под Visual Studio, но имеет конфигурационный файл CMakeLists.txt. В этом случае с помощью утилиты Cmake генерируем файл проекта Visual Studio в отдельную директорию (директория libwebsockets_VS_proj). А затем открыв сгенерированный файл проекта в Visual Studio компилируем. Получаем нужный нам файл websockets.dll.
После всех предыдущих действий можно компилировать проект Mosquitto. Здесь также сначала надо будет сгенерировать файл проекта Visual Studio (директория Mosquitto_VS_proj) из прилагающегося файла конфигурации CMakeLists.txt. Сгенерированный проект не совсем получается рабочим, придется поменять пути к некоторым внешним заголовочным файлам и библиотекам, включить некоторые макросы в проект и несколько модифицировать исходные тексты. В результате получаем файл mosquitto.dll.
Для простоты все файлы и структура директорий с упомянутыми проектами содержаться в архивном файле, прилагаемом к статье.
По ходу вместе с клиентской библиотекой компиляция проекта Mosquitto дает нам и исполняемый файл брокера MQTT — mosquitto.exe.
Таким образом мы получаем сразу и клиента, и брокера MQTT, т.е. практически все что нужно для организации эффективного интернета вещей.
Чтобы интегрировать в Delphi библиотеку mosquitto.dll надо создать модуль объявлений функций библиотеки на Object Pascal. Для этого была выполнена конвертация файла mosquitto.h в файл MOSQUITTO.PAS.
Проект клиента очень простой, состоит всего из 4-х файлов с исходными текстами. Клиент демонстрирует подключение и отключение, формирование завещания (Will), посылку данных пакетом PUBLISH брокеру, прием данных пакетом PUBLISH от брокера, подписку и отказ от подписки.
Программа сохраняет все атрибуты подключения, именуемые термином профиль в таблицу профилей сохраняемую на диске. На диск также сохраняется отдельно логи полученных и отправленных пакетов PUBLISH.
Запускаем файл TMQTTC.exe.
Для того чтобы было с кем обмениваться сообщениями запускаем тестового брокера командой Run_mosquitto.cmd в директории Mosquitto_1_4_5_bin. Для удобства брокер сконфигурирован на подключение без SSL и проверки пароля.
Заполняем поля как на скриншоте.
Пароль и имя пользователя не обязательны. В навигаторе нажимаем кнопку фиксации изменений, чтобы сохранить данные в таблице. После чего нажимаем кнопку Connect.
После соединения становятся доступны команды публикации и подписки. Команды PING клиент Mosquitto генерирует автоматически.
Чтобы клиент что-то получал следует еще раз запустить программу TMQTTC.exe с другим идентификатором клиента и подписаться одним клиентом на получение данных от другого.
Первое что надо сделать это получить акаунт в Bluemix
Получив акаунт, мы заходим в свою панель управления на Bluemix. Здесь сразу надо переключиться на регион US South. Для этого щелкаем в правом верхнем углу по пиктограме акаунта и меняем значение в поле Region. Всего есть три региона, но имеено US South дает возможность испытать большинство сервисов. Далее надо создать Space. Вид экрана должен быть как на криншоте ниже. Здесь создана организация INDEMSYS и Space INDEMSYS SPACE.
Теперь нажимаем на CATALOG в верхнем меню. Спускаемся в самый низ и выбираем Internet of Things Foundation.
Предложенные поля по умолчанию не меняем и жмем Create
Internet of Things Foundation — это сервис включающий брокера MQTT и пользовательский интерфейс к нему.
После создания в появившемся окне нажимаем кнопку с надписью Launch dashboard.
Это панель управления IoT. Теперь надо создать устройства. Нажимаем Add device. В появляющихся диалогах создаем тип устройства (Create device type) Даем ему имя Type1, остальные поля не заполняем для упрощения. Жмем Next → Next → Create → Next. Даем имя устройству Device1. Далее Next → Next → Next → Add. В результате получаем такое окно:
Все, здесь мы получили все реквизиты для подключения нашего первого устройства к MQTT брокеру Bluemix .
Испытаем сможет ли к нему подключиться наш клиент. Вводим реквизиты в окно клиента.
Как видно клиент успешно подключился к Bluemix. Здесь следует обратить внимание на имя хоста. Оно начинается с Organization ID полученного при создании Internet of Things Foundation. Поле User ID тоже составное и кодируется как: d: <Organization ID>: <Device Type>: <Device ID>. Поле User Name содержит фиксированную строку use-token-auth.
Топики сообщений для брокера Bluemix в отличие от брокера Mosquitto не могут содержать произвольные данные. Они кодируются по определенным правилам. Эти правила следует изучить в документации на Internet of Things Foundation. На скриншоте показан один из возможных допустимых топиков.
Репозитарий проекта: https://github.com/Indemsys/Delphi_MQTT_mosquitto