tutorial
IoT и Galileo Gen2: часть вторая

В первой части мы рассмотрели как настроить среду разработки и подготовить плату Galileo для экспериментов. В этой статье будет рассмотрен пример состоящий из двух приложений, одно на Galileo и будет опрашивать температуру с датчика BMP085, а другое запущено на смартфоне будет отображать эту температуру на графике. За основу были взяты стандартные примеры но немного доработаны.
Приложение для Galileo
За основу был взят пример Local Temperature, в нем использовался датчик температуры Grove, но такого не оказалось в наличии и схема была собрана с датчиком BMP085.

В примере библиотека mraa была заменена модулем jsupm_bmpx8x. Для подключения других датчиков можно посмотреть примеры. Датчик BMP085 умеет измерять давление, температуру, высоту над уровнем моря, но в примере будем использовать только температуру.
В результате программа выглядит следующим образом:
//Load Barometer module
var bmpx8x = require('jsupm_bmpx8x');
// load this on i2c
var myBarometerObj = new bmpx8x.BMPX8X(0, bmpx8x.ADDR);
var pressure, temperature, altitude, sealevel;
/*
Function: startSensorWatch(socket)
Parameters: socket - client communication channel
Description: Read Temperature Sensor and send temperature in degrees every 60 seconds
*/
function startSensorWatch(socket) {
'use strict';
setInterval(function () {
//var pressure = myBarometerObj.getPressure();
var temperature = myBarometerObj.getTemperature();
//var altitude = myBarometerObj.getAltitude();
//var sealevel = myBarometerObj.getSealevelPressure();
console.log("Temperature: " + temperature);
socket.emit("message", temperature);
}, 60000);
}
//Create Socket.io server
var http = require('http');
var app = http.createServer(function (req, res) {
'use strict';
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('<h1>Hello world from Intel IoT platform!</h1>');
}).listen(1337);
var io = require('socket.io')(app);
//Attach a 'connection' event handler to the server
io.on('connection', function (socket) {
'use strict';
console.log('a user connected');
//Emits an event along with a message
socket.emit('connected', 'Welcome');
//Start watching Sensors connected to Galileo board
startSensorWatch(socket);
//Attach a 'disconnect' event handler to the socket
socket.on('disconnect', function () {
console.log('user disconnected');
});
});
Полный пример можно взять на github.
Компилируем и загружаем приложение на Galileo.
У нас получилось приложение, которое считывает значение температуры с сенсора и передает его раз в минуту.
Приложение компаньон
Приложение компаньон для смартфона будет подключаться к Galileo и раз в минуту запрашивать значение температуры и рисовать график с помощью D3.js библиотеки. За основу было взято приложение, но немного модифицировано.
После адаптирования графика к сенсору BMP085 приложение стало выглядеть следующим образом:

Минимум усилий и мы получили кроссплатформенное приложение. Добавив к Galileo различной периферии и разместив это все в приложении компаньоне, можно построить свой умный дом с управлением через интернет.
В следующей статье про Galileo расскажу как установить на плату mini PCI Express Wi-Fi адаптер Intel® Centrino® Wireless-N 135, подписывайтесь, будет интересно.
IoT и Galileo Gen2: часть первая

Сегодня поговорим о IoT, что в переводе Интернет вещей. В последнее время этот термин очень тесно вошел в нашу жизнь. В этом цикле статей попробуем разобраться в этой проблеме.
В качестве подопытного будет выступать плата Galileo Gen2 от Intel с microSD на 8Gb и Mac.
В первой части рассмотрим установку необходимого программного обеспечения.
Подготовки Galileo
Обновление прошивки
Первое, что необходимо сделать — это обновить прошивку. Загружаем утилиту для обновления Firmware (для каждой ОС свой updater).
В утилите необходимо выбрать порт, к которому подключена плата и нажать Update Firmware:

Процесс обновления может занять до 5 минут, в процессе обновления не отключайте питание или провод usb, а также не нажимайте кнопки на плате. После успешного обновления вы должны увидеть соответствующее сообщение.
Подготовка microSD карты
Все действия описаны для Mac OSX.
Для работы с IoT нам потребуется записать на карту памяти Yocto образ.
Карта памяти должна быть от 4 до 32 Гб, также потребуется картридер.
Загружаем последний Yocto образ: http://iotdk.intel.com/images/iot-devkit-latest-mmcblkp0.direct.bz2.
Распаковываем архив:
bunzip2 iot-devkit-latest-mmcblkp0.direct.bz2
Форматируем microSD с помощью дисковой утилиты в MS DOS (FAT).
Запускаем утилиту для монтирования дисков и смотрим список дисков в системе:
diskutil list
В появившейся таблице находим строчку с картой памяти и в столбце IDENTIFIER запоминаем имя, например у меня это disk2.
Отмонтируем карту памяти:
diskutil unmountDisk disk2
С помощью утилиты dd запишем образ на карту памяти командой:
sudo dd bs=8m if=iot-devkit-version-mmcblkp0.direct of=/dev/disk2
Процес может занять довольно продолжительное время, при этом на экране ничего не отображается. По окончании процесса будет написано, что данные были записаны. У меня этот процесс занял около 15 минут.
Проверяем в менеджере файлов, что образ записался и извлекаем карту памяти:
diskutil eject disk2
Настройка Linux на Galileo
Вставляем карту памяти, подключаем LAN-кабель и питание. Приблизительно через минуту можно попробовать подключиться по ssh (в настройках роутера нужно посмотреть, какой IP адрес получила плата):
ssh root@192.168.1.2
Установим пароль для пользователя root:
passwd
Установим синхронизацию времени по NTP:
rdate www.nist.gov
Проверим текущее время командой:
timedatectl status
При необходимости установим свой временной пояс:
timedatectl set-timezone Europe/Moscow
Обновим библиотеки libmraa и upm:
echo "src maa-upm http://iotdk.intel.com/repos/1.1/intelgalactic" > /etc/opkg/intel-iotdk.conf
opkg update
opkg upgrade
Galileo готово для последующих экспериментов, можно проверить работоспособность на моргании светодиода. Для этого нам потребуется текстовый редактор nano. Загрузка и установка:
mkdir nano-src
cd nano-src
curl http://www.nano-editor.org/dist/v2.2/nano-2.2.6.tar.gz >nano-2.2.6.tar.gz
tar zxvf nano-2.2.6.tar.gz
cd nano-2.2.6
./configure
make
make install
libmraa и светодиод
Попробуем с помощью C++ поморгать светодиодом. Создадим новый файл:
nano blink.cpp
И добавим следующее содержимое:
#include "mraa.h"
int main() {
mraa_gpio_context gpio;
gpio = mraa_gpio_init(13);
mraa_gpio_dir(gpio, MRAA_GPIO_OUT);
bool ledState=true;
while(true){
mraa_gpio_write(gpio, ledState?1:0);
ledState=!ledState;
sleep(1);
}
}
Скомпилируем:
g++ blink.cpp -lmraa -o blink
Запустим получившееся приложение:
./blink
После этого встроенный светодиод на плате начнет моргать.
Перейдем к следующему шагу.
Установка Intel XDK IoT Edition
Загружаем XDK для своей ОС на странице.
И устанавливаем согласно инструкции.
Среда разработки выглядит следующим образом:

Чтобы подключиться к плате, нужно в списке IoT Device выбрать свою плату, после чего появиться диалоговое окно с предложением ввести имя пользователя и пароль. Пользователь по умолчанию root, а пароль, тот что установили выше. Нажимаем Connect и ждем подключения, состояние его можно увидеть в нижнем окне.
Обновление xdk-daemon
Завершающим шагом будет обновление xdk демона.
На панели инструментов нажимаем кнопку с изображением шестеренки и выбираем Upgrade xdk-daemon on IoT device:

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

Для начала создадим новый проект:
$ pebble new-project Geolocation-Pebble
В созданном проекте, в папке src, добавим новый каталог js, а в нем новый файл pebble-js-app.js
В файле напишем 2 функции, одна будет вызываться при успешном получении координат, другая при ошибке:
function locationSuccess(pos) {
var coordinates = pos.coords;
Pebble.sendAppMessage({
"KEY_LATITUDE" : coordinates.latitude.toString(),
"KEY_LONGITUDE" : coordinates.longitude.toString()
});
console.log("lat: " + coordinates.latitude);
console.log("lon: " + coordinates.longitude);
}
function locationError(err) {
console.warn('location error (' + err.code + '): ' + err.message);
}
var locationOptions = {
enableHightAccuracy : true,
timeout : 60000,
maximumAge : 10000
};
Когда мы получили координаты, мы их собираем в объект и отправляем в часы функцией Pebble.sendAppMessage.
Также добавим опции, такие как enableHightAccuracy — повышенная точность определения местоположения, timeout — максимальное время на получение координат и maximumAge — максимальный допустимый возраст координат. Подробнее о спецификации можно почитать на сайте W3C.
После этого добавить слушатель, который будет получать команду из часов и запускать процесс определения координат:
Pebble.addEventListener("appmessage",
function(e) {
window.navigator.geolocation.getCurrentPosition(locationSuccess, locationError, locationOptions);
}
);
Далее перейдем к файлу appinfo.json и добавим туда 2 ключа, в одном будет передаваться широта, в другом долгота и добавим разрешение на использование геолокационного сервиса:
"capabilities": [ "location" ],
"appKeys": {
"KEY_LATITUDE" : 0,
"KEY_LONGITUDE" : 1
},
Перейдем к написанию самого приложения для часов, оно будет состоять из 2х текстовых полей и одного события. При нажатии на кнопку «выбор» будет происходить обновление координат.
В функции windows_load опишем текстовые поля:
static void window_load(Window *window) {
Layer *window_layer = window_get_root_layer(window);
latitude_layer = text_layer_create(GRect(0, 45, 144, 68));
text_layer_set_text_color(latitude_layer, GColorWhite);
text_layer_set_background_color(latitude_layer, GColorClear);
text_layer_set_font(latitude_layer, fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD));
text_layer_set_text_alignment(latitude_layer, GTextAlignmentCenter);
layer_add_child(window_layer, text_layer_get_layer(latitude_layer));
text_layer_set_text(latitude_layer, "Press SELECT for update");
longitude_layer = text_layer_create(GRect(0, 90, 144, 68));
text_layer_set_text_color(longitude_layer, GColorWhite);
text_layer_set_background_color(longitude_layer, GColorClear);
text_layer_set_font(longitude_layer, fonts_get_system_font(FONT_KEY_GOTHIC_18_BOLD));
text_layer_set_text_alignment(longitude_layer, GTextAlignmentCenter);
layer_add_child(window_layer, text_layer_get_layer(longitude_layer));
text_layer_set_text(longitude_layer, "N/A");
}
Создадим функции для отслеживания нажатий на кнопку «выбор» и передачи команды в JavaScript Framework для обновления координат:
static void select_click_handler(ClickRecognizerRef recognizer, void *context) {
Tuplet initial_values[] = {
TupletCString(KEY_LATITUDE, "N/A"),
TupletCString(KEY_LONGITUDE, "N/A"),
};
app_sync_init(&sync, sync_buffer, sizeof(sync_buffer), initial_values, ARRAY_LENGTH(initial_values),
sync_tuple_changed_callback, sync_error_callback, NULL);
send_cmd();
}
static void click_config_provider(void *context) {
window_single_click_subscribe(BUTTON_ID_SELECT, select_click_handler);
}
Опишем функцию передачи данных в JavaScript Framework, хотя мы и будем передавать пустой объект, это все для того чтобы запустить Pebble.addEventListener:
static void send_cmd(void) {
Tuplet value = TupletInteger(2, 1);
DictionaryIterator *iter;
app_message_outbox_begin(&iter);
if (iter == NULL) {
return;
}
dict_write_tuplet(iter, &value);
dict_write_end(iter);
app_message_outbox_send();
}
В следующей функции мы принимаем объект состоящий из 2х ключей и обновляем наши соответствующие текстовые поля:
static void sync_tuple_changed_callback(const uint32_t key, const Tuple* new_tuple, const Tuple* old_tuple, void* context) {
switch (key) {
case KEY_LATITUDE:
text_layer_set_text(latitude_layer, new_tuple->value->cstring);
break;
case KEY_LONGITUDE:
text_layer_set_text(longitude_layer, new_tuple->value->cstring);
break;
}
}
Незабываем добавить пару строчек в функцию init:
app_message_open(app_message_inbox_size_maximum(), app_message_outbox_size_maximum());
window_set_click_config_provider(window, click_config_provider);
При желании или необходимости можно добавить таймер и через определенный интервал обновлять координаты, а потом, например, рисовать пройденный трек, но мне для своего приложения этого не требовалось, поэтому об этом расскажу может в следующий раз.
Полную версию исходников можно посмотреть на GitHub.
Учебник по Pebble SDK
Привожу ссылки на замечательный цикл статей по разработке для Pebble от Chris Lewis.
В 10 статьях будет описано почти все возможности Pebble SDK, кроме тех которые появились в версии 2.5 и выше.