Продолжение работы с облаком Intel IoT Analytics, будет посвящена обратной связи с устройством, отправка команд для управления устройством. Первая часть Intel Edison. Работа с облаком Intel IoT Analytics: регистрация и отправка данных. Реализуем операции включения/выключения светодиода и реле. Для демонстрации, возьмем стенд из предыдущего поста.
Для отправки команд устройству используется специальный тип компонента — Actuation. В предыдущем посте рассматривался тип компонента “sensor”, который позволяет отправлять данные с устройства. Actuation передает данные по протоколу MQTT и WebSocket. Этот тип компонента вызывает команду “command String” и для нее параметры имя/значение.
Регистрация Actuation в облаке Intel IoT Analytics
Рассмотрим Actuation заданный по умолчанию, который подойдет без изменений для светодиода. Откроем раздел Account, раздел Catalog, компонент Powerswitch.v1.0
Окно свойств компонента Powerswitch.v1.0
Тип компонента Actuator. Т.к. светодиод может быть только в двух состояниях, то тип данных Boolean. LED.v1.0 — команда для светодиода. Ключ/значение, название — LED, принимаемое значение 0 или 1.
Реле является однотипным компонентом со светодиодом, поэтому так же создадим Actuator для реле.
Типы компонентов созданы.
Настройка iotkit agent на Intel Edison
Теперь требуется зайти по SSH на Intel Edison. В предыдущем посте была выполнена настройка Wi-Fi, поэтому можно подключиться к устройству по ЛВС.
Поддержка компонента Actuation заявлена только с версии агента 1.5.2 и выше. Рекомендуется обновить агента до последней актуальной версии.
Узнать версию агента:
# iotkit-admin -V
Команда обновления агента:
# npm update iotkit-agent
В последней версии агента появилась возможность работать по WebSocket. Для работы по WebSocket требуется настроить агента командой:
# iotkit-admin protocol rest+ws
Перевести обратно в режим работы по MQTT:
# iotkit-admin protocol mqtt
Выполним регистрацию Actuator для светодиода и реле на Intel Edison.
Регистрация датчиков выполняется командой # iotkit-admin register [имя_датчика] [тип_датчика]. Выполним команды:
# iotkit-admin register led1 powerswitch.v1.0
# iotkit-admin register relay1 relay.v1.0
Подготовка скетча для Arduino
Компоненты зарегистрированы. Теперь подготовим скетч для Arduino, в качество основы возьмём пример IoTKitActuationExample
Рассмотрим код:
Функция void setup(), ничем не отличается от предыдущего примера.
В функцию void loop(), вносится функция для периодической проверки полученных сообщений, где json — указатель на сообщение в формате JSON.
void loop() {
iotkit.receive(callback);
delay(5000);
}
Функция void callback(char* json)
void callback(char* json) {
Serial.println(json);
aJsonObject* parsed = aJson.parse(json);
if (&parsed == NULL) {
// invalid or empty JSON
Serial.println("recieved invalid JSON");
return;
}
Если присутствуют поступившие данных, то далее следуем их разбор.
aJsonObject* component = aJson.getObjectItem(parsed, "component");
aJsonObject* command = aJson.getObjectItem(parsed, "command");
aJsonObject* argv = aJson.getObjectItem(parsed, "argv");
aJsonObject* argvArray = argv->child;
aJsonObject* name = argvArray->child; // name : on
aJsonObject* value = name->next; // value: 1/0
Проверка поступивших команд LED.v1.0, и значения “0” или “1”
if ((component != NULL)) {
if (strcmp(component->valuestring, "power") == 0) {
if ((command != NULL)) {
if (strcmp(command->valuestring, "LED.v1.0") == 0 && strcmp(value->valuestring, "0") == 0) {
Serial.println("Light Off!");
pinMode(13, OUTPUT);
digitalWrite(13, false);
}
if (strcmp(command->valuestring, "LED.v1.0") == 0 && strcmp(value->valuestring, "1") == 0) {
Serial.println("Light on!");
pinMode(13, OUTPUT);
digitalWrite(13, true);
}
}
}
}
Итоговый скетч с датчиками и управлением:
//LCD
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
#define LCD_I2C_ADDR 0x20 // Define I2C Address where the PCF8574T is
#define BACKLIGHT 7
#define LCD_EN 4
#define LCD_RW 5
#define LCD_RS 6
#define LCD_D4 0
#define LCD_D5 1
#define LCD_D6 2
#define LCD_D7 3
LiquidCrystal_I2C lcd(LCD_I2C_ADDR,LCD_EN,LCD_RW,LCD_RS,LCD_D4,LCD_D5,LCD_D6,LCD_D7);
//BMP085 Barometric Pressure & Temp Sensor
#include <Wire.h>
#include <Adafruit_BMP085.h>
Adafruit_BMP085 bmp;
//for Intel Cloud
#include <IoTkit.h> // include IoTkit.h to use the Intel IoT Kit
#include <Ethernet.h> // must be included to use IoTkit
// create an object of the IoTkit class
IoTkit iotkit;
float temperature1;
int pressure1;
int moisturevalue1;
bool led1,relay1;
void setup() {
iotkit.begin();
Serial.begin(9600);
bmp.begin();
//init LCD
lcd.begin (20,4);
lcd.setBacklightPin(BACKLIGHT,NEGATIVE); // init the backlight
lcd.setBacklight(HIGH); // Backlight on
lcd.home (); // go home
lcd.setCursor ( 0, 0 );
lcd.print("Edison. Habrahabr");
//Current state Actiator
//LED от DFRobot работает инверсно
pinMode(8, OUTPUT);
digitalWrite(8, !false);
pinMode(9, OUTPUT);
digitalWrite(9, false);
//Send state Actiator
iotkit.send("led1", 0);
iotkit.send("relay1", 0);
}
void loop() {
lcd.setCursor ( 0, 1 );
lcd.print("Tempera. = ");
lcd.print(bmp.readTemperature());
lcd.print(" *C");
//
lcd.setCursor ( 0, 2 );
lcd.print("Pressure = ");
lcd.print(bmp.readPressure());
lcd.print(" Pa");
//
lcd.setCursor ( 0, 3 );
lcd.print("Moisture Value = ");
lcd.print(analogRead(0));
//read
temperature1=bmp.readTemperature();
pressure1=bmp.readPressure();
moisturevalue1=analogRead(0);
//Console and Send to Intel Cloud
Serial.println("Sensors");
Serial.print("temperature1=");
Serial.println(temperature1);
iotkit.send("temperature1", temperature1);
delay(2000);
Serial.print("pressure1=");
Serial.println(pressure1);
iotkit.send("pressure1", pressure1);
delay(2000);
Serial.print("moisturevalue1=");
Serial.println(moisturevalue1);
moisturevalue1=20;
iotkit.send("moisturevalue1", moisturevalue1);
//Get command for Actiator
iotkit.receive(callback);
//
delay(1000); // wait for a second
}
void callback(char* json) {
Serial.println(json);
aJsonObject* parsed = aJson.parse(json);
if (&parsed == NULL) {
// invalid or empty JSON
Serial.println("recieved invalid JSON");
return;
}
aJsonObject* component = aJson.getObjectItem(parsed, "component");
aJsonObject* command = aJson.getObjectItem(parsed, "command");
aJsonObject* argv = aJson.getObjectItem(parsed, "argv");
aJsonObject* argvArray = argv->child;
aJsonObject* name = argvArray->child; // name : on
aJsonObject* value = name->next; // value: 1/0
//LED
if ((component != NULL)) {
if (strcmp(component->valuestring, "led1") == 0) {
if ((command != NULL)) {
if (strcmp(command->valuestring, "LED.v1.0") == 0 && strcmp(value->valuestring, "0") == 0) {
Serial.println("Light Off!");
digitalWrite(8, !false);
//Send state Actiator
iotkit.send("led1", 0);
}
if (strcmp(command->valuestring, "LED.v1.0") == 0 && strcmp(value->valuestring, "1") == 0) {
Serial.println("Light on!");
digitalWrite(8, !true);
//Send state Actiator
iotkit.send("led1", 0);
}
}
}
}
//RELAY
if ((component != NULL)) {
if (strcmp(component->valuestring, "relay1") == 0) {
if ((command != NULL)) {
if (strcmp(command->valuestring, "RELAY.v1.0") == 0 && strcmp(value->valuestring, "0") == 0) {
Serial.println("Relay Off!");
digitalWrite(9, false);
//Send state Actiator
iotkit.send("relay1", 0);
}
if (strcmp(command->valuestring, "RELAY.v1.0") == 0 && strcmp(value->valuestring, "1") == 0) {
Serial.println("Relay on!");
digitalWrite(9, true);
//Send state Actiator
iotkit.send("relay1", 0);
}
}
}
}
}
Отправка команды для управления
Отправить команды на управления из облака Intel IoT Analytics. Откроем раздел Control. Выберем устройство и компонент.
Добавим действия на включение и выключение светодиода. После заполнения полей нажимаем на кнопку Add action.
Так же делаем и для реле. В результате, в таблице появится четыре записи. Для включения светодиода выбираем последнюю строку и кликаем по ссылке Send.
Через пару секунд светодиод загорится.
Подведем краткий итог
Управление устройством не сложнее чем получение данных от датчиков. От разработчика требуется разобрать поступивший запрос в формате JSON и применить соответствующую логику.
Ссылки