Pull to refresh

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

Reading time 5 min
Views 17K


Не так давно я стал счастливым обладателем 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.

ОБНОВЛЕНИЕ: Так как данная отправка с помощью HTTP далека от идеала, то лучше использовать порт Arduino SDK под названием Azure IoT Hub library for Arduino

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


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

Articles