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