Отправляем данные с Arduino в Azure IoT Hub

от автора

Не так давно я стал счастливым обладателем Genuino MKR1000. Ресурс Hackster.io совместно с Microsoft проводил конкурс на лучшую идею. Пусть я не успел воплотить свою идею в жизнь и принять участие во второй части конкурса, но я могу поделится с вами информацией, которая поможет вам осуществить свои задумки. Под катом о том, как отправить данные с Arduino в облако и как их считать, если у вас есть WiFi шилд или MKR1000.

Настройка Azure

Заходим на portal.azure.com, нажимаем «+», выбираем «Интернет вещей» — «IoT Hub» и придумываем название нашему хабу. Я решил назвать хаб просто и скромно – alexey. Ценовую категорию я выбрал бесплатную S1 (на одно устройство).

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

Настройка Arduino

Установим необходимую библиотеку WiFi101:

Нам необходима версия выше чем 0.8, так что если у вас уже установлена старая библиотека, то обновите ее.

Azure IoT Hub использует SSL для безопасности подключения. Но так как у Arduino недостаточно памяти для того чтобы хранить в ней сертификат SSL, то нам необходимо записать его в чип WiFi. Для этого нужно обновить Firmware версию WiFi101. Скачиваем по ссылке файл Wifi101_FirmwareUpdater_windows.zip

В Arduino IDE открываем скетч Файл – Примеры – WiFi101 – FirmwareUpdater. Подключаем MRK1000 и загружаем скетч. Теперь плата Arduino готова к получению прошивки с сертификатом.
Распаковываем zip архив Wifi101_FirmwareUpdater_windows, который мы недавно скачали и запускаем winc1500-uploader-gui.exe. Вводим адрес узла нашего хаба.

Кликаем и выделяем COM порт, после чего нажимаем «Upload certificate»

Остается дождаться загрузки сертификата

Microsoft Azure IoT Hub использует Shared Access Signatures.
Это сигнатуры доступа, которые могут быть использованы для работы с очередью сообщений IoT Hub-а без пароля. Нам необходимо создать SAS token. Для того чтобы не делать это в коде Arduino можно использовать утилиту Device Explorer
Скачиваем по ссылке файл SetupDeviceExplorer.msi
Устанавливаем и запускаем. Заходим на портал Azure в IoT Hub и нажимаем на ключик в правом верхнем углу:

Выбираем из списка iothubowner и копируем «Строка подключения – первичный ключ»

Эту строку вводим в окно закладки Configuration приложения Device Explorer и нажимаем кнопку Update

Переходим на закладку Management. Здесь мы можем добавить новое устройство. Кнопка Create, придумываем ID нашему девайсу (я назвал свое устройство myDevice) и нажимаем Create.

В списке появится наше устройство. Выделяем строку с ним и нажимаем SAS Token…
Вводим промежуток дней и нажимаем Generate. Из получившегося токена нам нужна только часть начинающаяся с «SharedAccessSignature sr=» (копируйте аккуратно, так как текст SharedAccessSignature встречается в строке 2 раза)

Англоязычный мануал о том как пользоваться Device Explorer находится здесь:
How to use Device Explorer for IoT Hub devices

Код Arduino

Рассмотрим код Arduino. Заголовок у нас такой:

#include <SPI.h>
#include <WiFi101.h>

char hostname[] = "alexey.azure-devices.net"; // имя узла Azure IoT Hub
char authSAS[] = "SharedAccessSignature sr=alexey.azure-devices.net%2fdevices%2fmyDevice&sig=D7OxGEm98bqAQDYk33d0DzPB92EuGMkjkzKBCsBBksc%3d&se=1493799405"; // SAS token, который был сгенерирован Device Explorer
String deviceName = "myDevice"; // ID нашего девайса
char ssid[] = "myhomenet"; // имя вашей точки доступа wi-fi
char pass[] = "password123"; // пароль от точки доступа
String uri = "/devices/myDevice/messages/events?api-version=2016-02-03";
int status = WL_IDLE_STATUS; // статус доступности интернета
WiFiSSLClient client;

Строка uri будет различна для отправки и для получения данных.
Если бы мы получали данные, то строка была бы
/devices/myDevice/messages/devicebound?api-version=2016-02-03
Кроме отправки и получения существует возможность завершить/отклонить или сбросить сообщение.
В setup мы только делаем стандартное подключение к сети Wi-Fi

void setup() {
Serial.begin(9600);
Serial.println("Setup begin");
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("У Arduino отсутствует WiFi шилд");
while (true); // не продолжаем выполнение кода дальше
}
// пытаемся подключится к сети Wifi:
while ( status != WL_CONNECTED) {
Serial.print("Попытка подключения к точке доступа ");
Serial.println(ssid);
status = WiFi.begin(ssid, pass);
delay(10000); // ждем 10 секунд чтобы подключение завершилось
}
Serial.println("Connected to Wi-Fi");
}

Нам нужен метод, который будет отправлять строку текста запросом POST по протоколу HTTP на наш узел. Я не заморачиваюсь и отправляю строку текста, хотя обычно в примерах генерируют и отправляют json.

void httpPost(String content)
{
client.stop(); // закрываем подключение, если вдруг оно открыто
if (client.connectSSL(hostname, 443)) {
client.print("POST ");
client.print(uri);
client.println(" HTTP/1.1");
client.print("Host: ");
client.println(hostname);
client.print("Authorization: ");
client.println(authSAS);
client.println("Connection: close");
client.print("Content-Type: ");
client.println("text/plain");
client.print("Content-Length: ");
client.println(content.length());
client.println();
client.println(content);
delay(200);
} else {
Serial.println("HTTP POST отправка неудачна");
}
}

Теперь для того чтобы отправить строку текста достаточно вызвать метод

httpPost("Some message from Arduino");

Но мы еще и считаем ответ, чтобы убедится в том, что данные благополучно получены

httpPost("Some message from Arduino");
String response = "";
char c;
while (client.available()) {
c = client.read();
response.concat(c);
}
if (!response.equals(""))
{
if (response.startsWith("HTTP/1.1 204")) {
Serial.println("Строка была отправлена в Azure");
} else {
Serial.println("Ошибка");
Serial.println(response);
}
}

Весь код вы можете скачать с github

Консольное приложение, считывающее данные с очереди сообщений IoT Hub

Создаем консольное приложение.
Открываем NuGet Package Manager, ищем WindowsAzure.ServiceBus и устанавливаем.
Добавляем пару namespace:

using Microsoft.ServiceBus.Messaging; using System.Threading; 

И объявлений:

static string connectionString = "HostName=alexey.azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=xrzUfBj8gaq2i310MhRCcSEs08t3lk7zbCNI4Tltqp4="; static string iotHubD2cEndpoint = "messages/events"; static EventHubClient eventHubClient; 

Здесь вы можете заметить, что значением connectionString я ввел значение, полученное с портала Azure – это «Строка подключения – первичный ключ». Добавляем следующий метод:

private static async Task ReceiveMessagesFromDeviceAsync(string partition, CancellationToken ct) {     var eventHubReceiver = eventHubClient.GetDefaultConsumerGroup().CreateReceiver(partition, DateTime.UtcNow);     while (true)     {         if (ct.IsCancellationRequested) break;         EventData eventData = await eventHubReceiver.ReceiveAsync();         if (eventData == null) continue;          string data = Encoding.UTF8.GetString(eventData.GetBytes());         Console.WriteLine("Message received. Partition: {0} Data: '{1}'", partition, data);     } } 

и, наконец, в Main добавляем код:

Console.WriteLine("Получение сообщений. Ctrl-C для выхода.\n"); eventHubClient = EventHubClient.CreateFromConnectionString(connectionString, iotHubD2cEndpoint);  var d2cPartitions = eventHubClient.GetRuntimeInformation().PartitionIds;  CancellationTokenSource cts = new CancellationTokenSource();  System.Console.CancelKeyPress += (s, e) => {   e.Cancel = true;   cts.Cancel();   Console.WriteLine("Выходим..."); };  var tasks = new List<Task>(); foreach (string partition in d2cPartitions) {    tasks.Add(ReceiveMessagesFromDeviceAsync(partition, cts.Token)); }   Task.WaitAll(tasks.ToArray()); 

Если вы запустите это консольное приложение, то сможете считать сообщения, отправляемые включеной платой Arduino.

Полезные ссылки:

Приступая к работе с центром Azure IoT с использованием .NET
MKR1000 Azure IoT Hub Interface Using HTTP
MKR1000 Temp and Humidity Sensor

ссылка на оригинал статьи https://habrahabr.ru/post/282912/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *