Intel Edison. Работа с облаком Intel IoT Analytics: управление устройством

Intel IoT Analytics управление устройством

Продолжение работы с облаком 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
Intel IoT Analytics управление устройством
Окно свойств компонента Powerswitch.v1.0
Intel IoT Analytics управление устройством
Тип компонента Actuator. Т.к. светодиод может быть только в двух состояниях, то тип данных Boolean. LED.v1.0 — команда для светодиода. Ключ/значение, название — LED, принимаемое значение 0 или 1.
Реле является однотипным компонентом со светодиодом, поэтому так же создадим Actuator для реле.
Intel IoT Analytics управление устройством
Типы компонентов созданы.

Настройка 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
Intel IoT Analytics управление устройством

Подготовка скетча для 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. Выберем устройство и компонент.
Intel IoT Analytics управление устройством

Добавим действия на включение и выключение светодиода. После заполнения полей нажимаем на кнопку Add action.
Intel IoT Analytics управление устройством

Так же делаем и для реле. В результате, в таблице появится четыре записи. Для включения светодиода выбираем последнюю строку и кликаем по ссылке Send.
Intel IoT Analytics управление устройством

Через пару секунд светодиод загорится.
Intel IoT Analytics управление устройством

Подведем краткий итог
Управление устройством не сложнее чем получение данных от датчиков. От разработчика требуется разобрать поступивший запрос в формате JSON и применить соответствующую логику.

Ссылки

  1. Скетч листинга кода IoTkit
  2. github.com — enableiotcom
  3. Edison Getting Started Guide — Windows
  4. Flashing Intel Edison (wired) — Windows
  5. Cloud Intel IoT Analytics
  6. Intel Internet of Things (IoT) Developer Kit IoT Cloud-Based Analytics User Guide November 2014

© Geektimes