В рамках второго этапа олимпиады необходимо разработать устройство для интернета вещей, совместимое с архитектурой Alterozoom IoT. Для этого устройство должно взаимодействовать с элементами архитектуры посредством определенного протокола (ссылка). Данный протокол обеспечивает взаимодействие с устройством путем обмена которкими текстовыми сообщениями определенного формата. В данном документе описан полный процесс от разработки устройства до подключения его к облаку через приложение для ПК IotSchool. Так же кроме приложения возможно использование локального сервера (можно почитать здесь, информация может понадобится на следующиъ этапах).
Для облегчения процесса разработки устройства на микроконтроллерах семейства Arduino и других, поддерживающих тот же API и среду разработки Arduino IDE (например, ESP8266, в частности, NodeMCU), предоставляются библиотеки ARpc и ARpcESP8266WiFiDevice. Первая может быть использована для разработки любого устройства, вторая - узкоспециализированная для разработки устройств на базе микроконтроллеров семейства ESP8266, работающих по Wi-Fi в сетях TCP/IP.
Для установки библиотеки необходимо произвести следующие шаги:
Для выполнения задания второго этапа необходимо разработать устройство, взаимодействующее с приложением для ПК через USB порт. Для этого проще всего воспользоваться примером из библиотеки ARpc. Открываем пример в Arduino IDE (Файл -> Примеры -> ARpc -> SimpleTemperatureSensor) и сохраняем его под другим названием. Ниже мы подробно разберем этот пример.
Подключаем заголовочный файл библиотеки.
Задаем имя устройства, под которым оно будет отображаться в интерфейсах. Генерируем уникальный идентификатор в формате UUID (например, можно воспользоваться сервисом https://www.uuidgenerator.net/version4, при открытии страницы вверху будет готовый UUID). xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx заменяем на полученный UUID, фигурные скобки должны остаться.
Задаем переменную для пина, с которого будут считываться данные. В нашем примере это аналоговый пин A0, к которому подключен абстрактный температурный датчик с аналоговым выходом, диапазону напряжений на входе A0 от 0 до 5В соответствует диапазон температур от 0 до 50 градусов цельсия.
Для получения данных с устройства необходимо подготовить описание датчиков. Для нашего устройства оно выглядит вот так:
Определяем класс для передачи сообщений к ПК через последовательный порт:
Объект этого класса используется, когда библиотеке нужно передать какие-либо данные от устройства. В данном случае это данные, которые мы увидим в мониторе порта. Обратите внимание, что не используется println, так как эта функция добавляет лишний перевод строки, который будет мешать нормальной обработке сообщений.
Далее мы объявляем объект класса ARpc и передаем ему ссылки на созданные выше переменные и объекты:
300 - размер внутреннего буфера этого объекта, используемого для обработки сообщений. Чем больше этот размер, тем более длинные сообщения можно передавать устройству. Размер буфера нужно подбирать, исходя из доступного объема памяти. На микроконтроллерах с большим объемом памяти можно использовать больший размер буфера.
Производим инициальзацию пина и последовательного порта в функции setup() и установку описания датчиков:
И наконец, в функции loop() необходимо проверять последовательный порт на наличие новых данных, передавать их объекту parser и сгенерировать новый отсчет дачика, если с предыдущего раза прошло 10 секунд.
Для проверки можно открыть монитор порта, в котором регулярно должны появляться сообщения с заголовком meas. Если подключить к Arduino потенциометр (крайние ножки к gnd и vcc, среднюю к A0), можно имитировать изменение температуры.
Для того, чтобы в приложении иметь возможность работать с IoT частью, необходима специальная лицензия. Получить лицензию как участнику олимпиады можно, отправив запрос организаторам и указав в запросе свой email. Лицензию нужно вручную положить в папку C:/Users/<usernname>/.IotSchoolApp/module_licenses/
Папка появляется после первого запуска приложения.
Отключаем Arduino от ПК и запускаем приложение IoTSchool, открываем в верхнем меню раздел "IoT devices" (выделенная иконка на скриншоте ниже).
В левом верхнем углу открывшегося поля содержится список всех системных устройств. Так как в системе могут быть и другие устройства (модемы, телефоны и т.д.), приложение автоматически не подключает устройства. В левом нижнем углу список подключенных и идентифицированных устройств, справа - список хранилищ данных для датчиков с устройств. Внизу выводятся информационные сообщения.
Подключаем к компьютеру наше устройство, в списке системных устройств нажимаем кнопку Update. В списке появится еще одно новое устройство, выбираем его и нажимаем Identify. В случае успешной идентификации устройство появится в списке идентифицированных устройств. Если у устройства есть датчики, рядом с названием появится стрелка, при нажатии на которую развернется список датчиков устройства.
Выделяем датчик "temp" устройства и нажимаем кнопку "Add storage for sensor". Появится диалоговое окно настройки параметров хранилища.
Выбираем "Last N Values" и ниже вводим число сохраняемых значений "100 values". Справа выбираем пункт "Add global time on client".
Нажимаем Ok, в правом списке должно появиться хранилище для выбранного датчика. Открываем хранилище двойным кликом и наблюдаем изменяющийся график с данными.
Подключение к удаленному серверу платформы производится с помощью кнопки Bind storage. После нажатия на нее появляется диалоговое окно, в котором нужно выбрать тип облачного сервиса и задать параметры подключения.
Например, для подключения к серверу платформы IotSchools нужно выбрать тип сервиса alterozoom и выбрать радиокнопку "use current application account". После нажатия на Ok данные начнут поступать на удаленный сервер. Для того, чтобы в этом убедиться, можно воспользоваться web интерфейсом.
Веб-интерфейс для неавторизованного пользователя позволяет искать и просматривать публичные документы. Поиск может осуществляться в обычном и расширенном режимах. В расширенном режиме можно выбирать тип документа, а также использовать его географическую привязку.
Для авторизованного пользователя становится возможной работа с приватными документами - их создание и редактирование с помощью веб-редактора.
Для создания и редактирования контента через веб-интерфейс необходимо зайти на страницу "Мои документы", используя соответствующую ссылку в верхнем меню сервиса.
Интерфейс страницы "Мои документы" разделен по горизонтали на навигационную часть и часть веб-редактора.
Навигационная (левая) часть позволяет пользователю создавать категории и базы знаний для структурирования контента, а также документы различных типов - собственно контент.
Категории, базы знаний и документы при создании должны быть описаны метаинформацией (которая задается переходом в панели их свойств нажатием на соответствующие кнопки).
Веб-редактор (правая часть страницы "Мои документы") позволяет размещать в документе изображения, веб-ссылки, списки, таблицы, iframe-ы, HTML-вставки, Диалоги, а также интерфейсы IoT-устройств.
Также веб-редактор с помощью заголовков различных видов позволяет задавать структуру документа (для выбора типа заголовка необходимо зайти в раздел Формат в меню редактора). В режиме просмотра документа заголовки формируют его интерактивное оглавление, располагающееся справа от контента.
Раздел Команды (Commands) позволяет распечатать документ.
Открыть документ в отдельной вкладке в режиме просмотра можно с помощью специальной кнопки, находящейся над меню редактора. Рядом с этой кнопкой расположены другие кнопки, позволяющие сохранять документ, изменять его текущие свойства, а также удалять его.
1. Просмотр списка и изменение параметров устройств
После подключения одного или нескольких устройств к серверу iot.alterozoom.com в интерфейсе редактора документов (в меню вверху экрана) появится ссылка "Мои устройства".
При нажатии на эту ссылку будет показан список всех подключенных устройств и всех компонентов каждого устройства.
Для каждого устройства и каждого компонента устройства можно изменять следующие параметры: название, описание, доступ. Параметр "доступ" может принимать два значения: "публичный" (данные доступны всем) и "приватный" (данные доступны только владельцу текущего аккаунта).
2. Добавление данных, измеренных компонентом устройства (сенсором), в документ.
2.1. Нужно выбрать документ.
2.2. В панели HTML-редактора нужно нажать кнопку "IoT component".
2.3. В открывшемся меню из выпадающих списков нужно выбрать устройство "Device" и компонент устройства "Component". Нажать кнопку "Ok".
2.4. В содержимом документа должа появится область серого цвета, обозначающая место расположение графика с данными.
2.5. Нужно сохранить текущий документ и нажать кнопку "Просмотр".
2.6. В открывшейся вкладке браузера должен быть показан документ, содержащий график с данными выбранного компонента.
Пример документа: https://iot.alterozoom.com/ru/documents/6108.html
Каждое устройство может содержать несколько датчиков разных типов. У каждого датчика в пределах устройства должно быть уникальное название. При разработке устройства описание списка датчиков задается в xml или json формате. В описанном выше примере есть один единственный датчик с названием temp и типом f32_sv.
Значение датчика может передаваться с устройства в бинарном и текстовом виде, для этого используются соответствующие функции writeMeasurementB и writeMeasurement. При передаче значения в бинарном виде очень важно, чтобы используемая переменная языка С++ имела соответствующий тип.
Тип датчика представляет собой несколько ключей, разделенных символом "_". Ключи описывают: тип передаваемых значений, размерность датчика, количество значений, которые могут быть в одном сообщении, наличие или отсутствие метки времени.
Ключи, описывающие тип чисел в измерениях:
Ключ |
Описание |
---|---|
f32 |
Вещественное число одинарной точности согласно стандарту IEEE 754. В языке C/C++ — тип float. |
f64 |
Вещественное число двойной точности согласно стандарту IEEE 754. В языке C/C++ — тип double. |
s8 |
Целое число со знаком размером 8 бит (1 байт). Значения от -128 до 128 |
u8 |
Целое число без знака размером 1 байт. Значения от 0 до 255 |
s16 |
Целое число со знаком размером 2 байта. Значения от -32768 до 32767 |
u16 |
Целое число без знака размером 2 байта. Значения от 0 до 65535 |
s32 |
Целое число со знаком размером 4 байта. Значения от -2147483648 до 2147483647 |
u32 |
Целое число без знака размером 4 байта. Значения от 0 до 4294967295 |
s64 |
Целое число со знаком размером 8 байт. Значения от -9223372036854775808 до 9223372 036854775807 |
u64 |
Целое число без знака размером 8 байт. Значения от 0 до 18446744073709551615 |
txt |
Вместо чисел передается текст в кодировке UTF-8. не передается в бинарном виде. |
Ключ, описывающий размерность отсчета:
Ключ |
Описание |
---|---|
dXX |
XX — размерность отсчета, целое число >=1. Например, d2, d3, d45. Если ключ не указан, размерность по-умолчанию — 1. |
Ключи, описывающие количество значений в одном измерении:
Ключ |
Описание |
---|---|
sv |
Сокращение от "single value". Измерение представляет собой один многомерный отсчет с размерностью, указанной в описании датчика. |
pv |
Сокращение от "packet value". Измерение представляет собой набор многомерных отсчетов с размерностью, указанной в описании датчика. Количество отсчетов в наборе 1 и более, может варьироваться в каждом измерении. |
Ключи, описывающие временную метку измерения:
Ключ |
Описание |
---|---|
lt |
Временная метка локального времени устройства. Может быть в любых единицах измерения (секунды, милли-, микро- или наносекунды, тики и т. д.). |
gt |
Временная метка глобального времени — количество миллисекунд, прошедшее с 01.01.1970г. |
nt |
Временная метка отсутствует. Вариант по-умолчанию, если ни один из ключей не указан. |
Каждое устройство может при необходимости обрабатывать задаваемые разработчиком команды. Каждая команда может иметь 0 или более параметров. Для того, чтобы при использовании устройства можно было управлять им без дополнительных усилий, при разработке можно задать описание некоторого интерфейса управления. В этом интерфейсе команды сгруппированы в группы, которые в свою очередь так же могут быть вложены друг в друга. В группе указывается, как будут размещены ее элементы - по вертикали или по горизонтали. При описании параметра команды задается тип элемента, с помощью которого пользователь будет задавать значение параметра, например обычное полее ввода, или чекбокс, или группа радиокнопок и т.д.
При разработке устройства описание интерфейса управления представляется в виде строки языка С в xml или json формате.
Описание тегов и их атрибутов:
Тег | Описание | Где встречается | Атрибуты |
controls | Корневой тег xml документа | ||
group | Группа | Должен быть первым и единственным дочерним тегом для тега controls, так же может быть дочерним тегом другого тега group | title - название группы layout - размещение элементов по горизонтали и вертикали, может принимать значение h или v; если не задан, v - по-умолчанию. |
control | Команды | Является дочерним тегом для тега group | title - название команды (отображается в UI) command - команда, которая будет передана устройству (может вообще не совпадать с title) layout - размещение элементов-параметров команды, работает как собветствующий атрибут группы force_button - если равен 1, будет принудительно отображаться кнопка отправки команды button_text - текст для кнопки отправки команды |
param | Параметр команды | Является дочерним тегом для тега control, если у команды есть параметры | title - название команды (отображается в UI) type - тип элемента(ов) ui, используемого для задания параметра layout - размещение элементов ui, если для параметра будет сгенерирован не один элемент, например список радиокнопок |
attributes | Свойства элемента ui для параметра команды | Является дочерним тегом для тега param, не обязателен | Зависят от тип параметра |
Примечание: если у команды один параметр, по-умолчанию кнопка отправки команды отображаться не будет, команда будет отправляться при изменении состояния элемента ui, соответствующего параметру. Если это не удобно, для тега control можно задать атрибут force_button.
Типы параметров и возможные свойства
Тип параметра |
Возможные свойства |
Элемент UI |
checkbox |
onValue — значение, передаваемое, когда чекбокс включен (по умолчанию "1") offValue — значение, передаваемое, когда чекбокс выключен (по умолчанию "0") |
Чекбокс, checkable кпопка |
text_edit |
placeholder — текст, отображаемый, если поле пустое |
Поле ввода (с кнопкой отправки справа, если параметр у контрола один) |
select |
values — список значений, разделенных символом "|" (если отсутствует, всегда отправляется "0") titles — список отображаемых названий для значений, разделенных символом "|" |
Выпадающий список |
slider |
min — минимальное значение (по умолчанию 0) max — минимальное значение (по умолчанию 1023) step — величина шаг (по умолчанию 1) layout — вид слайдера ("h" — горизонтальный, "v" - вертикальный) |
Слайдер |
dial |
min — минимальное значение (по умолчанию 0) max — минимальное значение (по умолчанию 1023) step — величина шаг (по умолчанию 1) |
"Крутилка" |
radio |
values - список значений, разделенных символом "|" (если отсутствует или пустой, элемент не отображается, передается значение "0") titles — список отображаемых названий для значений, разделенных символом "|" |
Группа радиокнопок, из которых может быть нажата только одна |
hidden |
value — отправляемое значение ("0", если отсутствует) |
Не отображается в интерфейсе |
Пример описания интерфейса управления для некого упрощенного "кондиционера", выполняющего две команды - включить/выключить и установить температуру в пределах от 18 до 25 градусов:
В виде строковой переменной языка С:
Для обработки команд в скетч устройства нужно добавить несколько кусков кода. Во-первых, нужно создать класс для обработки команд, являющийся наследником ARpcIDevEventsCallback, и его объект
Далее в функции setup() нужно установить описание интерфейса и созданный обработчик
Для управления устройством из приложения нужно подключить устройство к приложению, выбрать его в списке идентифицированных устройств и нажать кнопку "Control device"