Возможности современных технологий ярче всего проявляются при их совместном использовании. Например, что можно сделать, если объединить Intel Edison, Microsoft Azure и Windows Phone? На самом деле, много всего. Здесь мы рассмотрим один из вариантов – дистанционное включение и выключение светодиода, присоединённого к одному из цифровых выходов Edison с коммутационной платой Arduino.
Мобильный сервис Azure связывает Edison и «пульт управления», в роли которого выступает приложение, работающее на платформе Windows Phone. Edison читает значение атрибута из таблицы мобильного сервиса и выполняет некие действия в соответствии с полученными данными. Приложение для смартфона меняет значение в таблице, что позволяет ему воздействовать на плату.
Предварительные требования
Мы предполагаем, что читатель обладает базовыми навыками разработки приложений для платформы Windows Phone и способен связать такое приложение с мобильной службой Azure. Если вы не знаете, как создавать серверную часть приложения, взгляните на этот материал.
Для реализации проекта понадобится следующее аппаратное и программное обеспечение:
- Плата Intel Edison с коммутационной платой Arduino
- Светодиод
- Visual Studio
- Arduino IDE
- Мобильный сервис Azure
Сначала создадим мобильный сервис Azure. Тому, как это делается, посвящено множество публикаций. Например, можете воспользоваться этим руководством и создать мобильный сервис, который содержит одну таблицу. Эту таблицу назовите «controltable». В ней должно быть два столбца. Один – с именем «status», второй – «name». Значение «status» будет либо 1, либо 0. В «name» будет «Edison/Arduino».
Мобильный сервис Azure
Обратите внимание на то, что атрибут «device» в SQL-таблице Azure значения не имеет. Его, если хотите, вполне можете удалить.
Теперь займёмся разработкой приложения для Windows Phone, которое будет добавлять или модифицировать значение атрибута.
Приложение для Windows Phone
Здесь мы не вдаёмся в подробности разработки для Windows Phone. Если вам нужны дополнительные сведения об этом, взгляните на материалы, размещённые на этом ресурсе.
В нашем приложении будет всего две кнопки: «on» и «off». Вот, как всё это выглядит.
Экран приложения для Windows Phone
На кнопку-ссылку «Log out» можете внимания не обращать.
Итак, как же работает приложение? При нажатии на кнопки «on» и «off» меняется атрибут «status» в таблице Azure, он устанавливается либо в 1, либо в 0.
Однако, тут мы сталкиваемся с проблемой. Дело в том, что для того, чтобы записать в какое-нибудь поле 1 или 0, нужно сначала это поле создать. Поэтому приложение выполняет двойную функцию. При первом подключении к облаку оно создаёт таблицу и заполняет её некими значениями по умолчанию, а в следующий раз лишь обновляет данные.
Когда приложение будет готово, его нужно будет протестировать, проверить, действительно ли нажатия на кнопки обновляют поле «status». Когда всё заработает так, как задумано, можно идти дальше.
Разработка для Edison
Займёмся разработкой для Edison. Прежде чем приступить, нужно настроить плату. После подключения Edison к компьютеру, выясните номер COM-порта, который соответствует плате. Затем запустите IDE Arduino и, из списка поддерживаемых устройств, выберите Edison. Если нужную плату в списке найти не удаётся, нужно загрузить необходимые файлы с помощью инструмента Boards Manager.
Загрузка файлов для Edison в IDE Arduino
После того, как вы откроете IDE Arduino, к вашим услугам будет пара функций – это void setup()
и void loop()
. Edison оснащён встроенным Wi-Fi-адаптером. Мы будем использовать его для подключения устройства к интернету. Поэтому первым делом импортируем в проект библиотеку для поддержки Wi-Fi. Для этого нужно выполнить команду Sketch->include library->Wi-Fi. Теперь добавим в проект нижеприведённый код, который позволит подключить устройство к Wi-Fi-сети.
#include <SPI.h>
#include <WiFi.h>
WiFiClient client;
char ssid[] = "networkssid"; // SSID (имя) сети
char pass[] = "password"; // пароль для подключения к сети (для сети с поддержкой WPA), или ключ (для сети с поддержкой WEP)
int keyIndex = 0; // индекс ключа сети (нужен только для WEP)
int status = WL_IDLE_STATUS;
void setup()
{
pinMode(13,OUTPUT);
digitalWrite(13,HIGH);
Serial.begin(115200);
while (!Serial) {
; // ожидаем подключение по последовательному порту. Нужно только для Leonardo
}
// Проверка наличия платы расширения:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// не будем продолжать:
while(true);
}
String fv = WiFi.firmwareVersion();
if( fv != "1.1.0" )
Serial.println("Please upgrade the firmware");
// пытаемся подключиться к Wi-Fi-сети:
while (status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
// Подключение к сети WPA/WPA2. Измените эту строчку, если используете открытую сеть или сеть с поддержкой WEP:
status = WiFi.begin(ssid, pass);
}
}
Этот фрагмент кода позволяет подключить Edison к интернету по Wi-Fi. Кроме того, мы установили PIN 13 в режим вывода и перевели в отключенное состояние. Мы будем использовать последовательный порт для мониторинга процесса в IDE Arduino.
Теперь займёмся методом void loop()
. Получение данных из Azure выполняется с помощью метода GET.
void loop()
{
send_request();
wait_response();
read_response();
end_request();
delay(100);
}
Эти функции будут загружать данные из таблицы облачного сервиса. Но, прежде чем рассмотреть код функций, нам нужно добавить в проект несколько глобальных констант, которые будут хранить данные, необходимые для подключения Edison к Azure.
const char* server= "YourAzureService.azure-mobile.net";
const char* table_name= "TableName";
const char* ams_key="YourApplicationKey";
char buffer[64];
Ключ приложения (ams_key
) можно найти в разделе управления ключами в вашей учётной записи Azure. Теперь рассмотрим код методов, используемых в void loop()
.
void send_request()
{
Serial.println("nconnecting...");
if (client.connect(server, 80))
{
sprintf(buffer, "GET /tables/%s HTTP/1.1", table_name);
client.println(buffer);
// Заголовок хоста
sprintf(buffer, "Host: %s", server);
client.println(buffer);
// Ключ приложения Azure Mobile Services
sprintf(buffer, "X-ZUMO-APPLICATION: %s", ams_key);
client.println(buffer);
// Тип содержимого – JSON
client.println("Content-Type: application/json");
// Размер содержимого
client.print("Content-Length: ");
client.println(strlen(buffer));
// Окончание заголовка
client.println();
// Тело запроса
client.println(buffer);
}
else
{
Serial.println("connection failed");
}
}
Мы выполнили HTTP-запрос и вызвали GET, где сначала указали имя таблицы, имя сервера и код ключа. Это нужно для успешного получения данных из облака. Затем мы указали, в каком формате хотим получить данные, в нашем случае – это JSON. Теперь займёмся кодом функции wait_response()
.
void wait_response()
{
while (!client.available())
{
if (!client.connected())
{
return;
}
}
}
После того, как данные получены, их надо прочитать. Так как мы имеем дело с форматом JSON, нужно разобрать полученную строку для того, чтобы извлечь из неё то, что нам нужно. Вот как такая строка может выглядеть:
{"id":"2492D996-C471-48F0-B3C9-F33E3B37477F","status":"0","name":"arduino"}
Для разбора JSON существует весьма эффективная библиотека, ArduinoJson. Она выполняет основную часть работ. Но полученная строка с JSON-данными заключена в прямоугольные скобки «[]». Прежде чем передавать строку библиотеке, эти скобки нужно удалить. Итак, сначала включим библиотеку в наш код и добавим следующие глобальные переменные:
#include <ArduinoJson.h>
#define RESPONSE_JSON_DATA_LINENNO 10
int charIndex=0;
StaticJsonBuffer<200> jsonbuffer;
Теперь, в методе read_response()
, напишем следующее:
void read_response()
{
boolean bodyStarted;
int jsonStringLength;
int jsonBufferCntr=0;
int numline=RESPONSE_JSON_DATA_LINENNO;
//Во всём ответе нам интересна лишь десятая строка
while (client.available())
{
//Serial.println("Reading:");
char c = client.read();
if (c == 'n')
{
numline -=1;
}
else
{
if (numline == 0 && (c!='[')&& (c!=']') )
{
buffer[jsonBufferCntr++] = c;
buffer[jsonBufferCntr] = '';
}
}
}
Serial.println("Received:");
Serial.println(buffer);
Serial.println("");
parse();
}
Вышеприведённый код выполняет чтение ответа. Метод parse
ответственен за разбор строки. Вот код этого метода. Здесь мы изменяем состояние вывода PIN 13 на плате в соответствии с полученными данными.
void parse()
{
StaticJsonBuffer<150> jsonbuffer;
JsonObject& root = jsonbuffer.parseObject(buffer);
if(!root.success())
{
Serial.println("PARSING FAILED!!!");
return;
}
int f= root["status"];
Serial.println("Decoded: ");
Serial.println(f);
if(f==0)
digitalWrite(13,LOW);
else
digitalWrite(13,HIGH);
}
В этом коде переменная f
хранит значение атрибута status. Мы это значение проверяем и, в зависимости от того, 0 или 1 окажется в переменной, переводим выход на плате в состояние HIGH или LOW. Нам осталось рассмотреть код лишь одного метода, end_request()
. Вот он.
void end_request()
{
client.stop();
}
Вполне вероятно то, что после компиляции этой программы вы столкнётесь с неожиданными ошибками. С ними надо разобраться. Причина ошибок описана здесь. Дело в том, что в файле WString.h отсутствует некоторый необходимый код. Здесь можно оценить различия правильного и неправильного файлов. Рабочий файл нужно поместить по такому пути:
C:UsersUsernameAppDataRoamingArduino15packagesIntelhardwarei6861.6.2+1.0coresarduinoWString.h
После этого ошибки исчезнут, можно будет добиться правильной компиляции кода и прошить его на Edison. Теперь подключите к плате светодиод, присоединив более длинную ножку (сюда так же можно добавить резистор на 233 Ом) к PIN 13, а короткую – к GND. Теперь система, состоящая из платы Intel Edison, облачной службы Microsoft Azure и Windows Phone, готова к испытанию.
Напомним: мы собираемся управлять светодиодом, подключённым к Edison, с помощью устройства на Windows Phone, пользуясь для этого облачным сервисом Azure, который является связующим звеном проекта. Взгляните на окно с отладочной информацией, которая поступает от Edison. Первая стадия работы – попытка подключения к Wi-Fi-сети.
Edison подключается к Wi-Fi сети
Следующий шаг – подключение к мобильному сервису Azure. После подключения Edison загружает данные в формате JSON, затем осуществляется их разбор с использованием соответствующей библиотеки, из данных извлекается интересующий нас показатель. Светодиод, подключённый к PIN 13, включается или выключается в соответствии со значением этого показателя.
Intel Edison подключился к облаку и получил данные
Итоги
Из этого материала вы узнали о том, как организовать управление платой Intel Edison с использованием мобильных сервисов Microsoft Azure. В нашем случае мобильный сервис – это связующее звено. Он позволяет взаимодействовать приложению, запущенному на Windows Phone, и плате Intel Edison. Делается это благодаря тому, что приложение, работающее на смартфоне, записывает данные в таблицу, а Edison эти данные считывает и соответствующим образом реагирует на них.
В нашем проекте всё устроено очень просто: светодиод загорается или гаснет в ответ на нажатие экранной кнопки. Но несложно заметить, что по такой же модели можно реализовать и гораздо более сложные схемы взаимодействия подключённых к интернету интеллектуальных «вещей» и модулей для управления ими.
Автор: Intel