30
AWS IoT で ででで IoT ででででで 土土 土土

AWS IoTで家庭内IoTをやってみた【JAWS DAYS 2016】

Embed Size (px)

Citation preview

Page 1: AWS IoTで家庭内IoTをやってみた【JAWS DAYS 2016】

AWS IoTで家庭内 IoTやってみた土持 昌志

Page 2: AWS IoTで家庭内IoTをやってみた【JAWS DAYS 2016】

自己紹介• 土持昌志• @pampitter

• 株式会社鈴木商店• JAWS-UG大阪• 好きな AWSサービス: Lambda、

S3

Page 3: AWS IoTで家庭内IoTをやってみた【JAWS DAYS 2016】

AWS IoTをやってみたきっかけ

Page 4: AWS IoTで家庭内IoTをやってみた【JAWS DAYS 2016】

AWS IoTをやってみたきっかけ• 2015年 10月に子供が生まれました• 2015年 10月の re:Inventで AWS IoT発表• 風邪・インフルエンザ対策に湿度データを収集してみよう

Page 5: AWS IoTで家庭内IoTをやってみた【JAWS DAYS 2016】

AWS IoTの概要

Page 6: AWS IoTで家庭内IoTをやってみた【JAWS DAYS 2016】

Device Gateway

DeviceGateway(Broker)

Publisher Subscriber

Publisher

Publisher Subscriber

Subscriber

MQTTHTTP

WebSocket

MQTTHTTP

WebSocket

Page 7: AWS IoTで家庭内IoTをやってみた【JAWS DAYS 2016】

Rule Engine

Action

SELECT humidityFROM '#'WHERE humidity <= 40

Rule Query

DeviceGateway

{"temp": 20.0}{"humidity": 40.0}{"temp": 22.0}

{"humidity": 70.0}{"temp": 21.0}

{"humidity": 20.0}

{"humidity": 40.0}{"humidity": 20.0}

Page 8: AWS IoTで家庭内IoTをやってみた【JAWS DAYS 2016】

Demo 1

湿度センサー

MQTT

Rule EngineTopic

Page 9: AWS IoTで家庭内IoTをやってみた【JAWS DAYS 2016】

センサーデータを収集# -*- coding: utf-8 -*-from __future__ import divisionfrom __future__ import absolute_importfrom __future__ import print_functionfrom __future__ import unicode_literals

from sense_hat import SenseHatimport datetimeimport json

sense = SenseHat()hum = sense.get_humidity()

now = datetime.datetime.now()

hum_json = {    'timestamp': now.strftime("%Y-%m-%d %H:%M:%S"),    'humidity': hum}

print(json.dumps(hum_json))

Page 10: AWS IoTで家庭内IoTをやってみた【JAWS DAYS 2016】

var execSync = require('child_process').execSync;

module.exports = {    sensor: function() {        var data = "" + execSync('python ' + __dirname + '/sensor.py');        return JSON.parse(data);    }}

Nodeから Pythonへのブリッジ

Page 11: AWS IoTで家庭内IoTをやってみた【JAWS DAYS 2016】

var awsIot = require('aws-iot-device-sdk');var bridge = require('./bridge.js');

var device = awsIot.device({    keyPath: './certs/private.pem.key',    certPath: './certs/certificate.pem.crt',    caPath: './certs/root-CA.crt',    clientId: 'pi2_01',    region: 'ap-northeast-1'});

device    .on('connect', function() {        console.log('connect');        setInterval(function() {            var humidity = bridge.sensor();            console.log(humidity)            device.publish('pi2_01', JSON.stringify(humidity));        }, 1000);    });

AWS IoTにパブリッシュ

Page 12: AWS IoTで家庭内IoTをやってみた【JAWS DAYS 2016】

Demo 1

Page 13: AWS IoTで家庭内IoTをやってみた【JAWS DAYS 2016】

Device Shadow

Device Device Shadow

App

Page 14: AWS IoTで家庭内IoTをやってみた【JAWS DAYS 2016】

• desired:管理アプリなどから指定されたあるべき状態• reported:デバイスが報告した現在の状態• delta:desiredと reportedの差分

Device Shadow{  "desired": {    "color": "white"  },  "reported": {    "color": "white"  }}

{  "desired": {    "color": "red"  },  "reported": {    "color": "red"  }}

{  "desired": {    "color": "red"  },  "reported": {    "color": "white"  },  "delta": {    "color": "red"  }}

Page 15: AWS IoTで家庭内IoTをやってみた【JAWS DAYS 2016】

Demo 2

LED

Device Shadow Console

Page 16: AWS IoTで家庭内IoTをやってみた【JAWS DAYS 2016】

LEDを点灯# -*- coding: utf-8 -*-from __future__ import divisionfrom __future__ import absolute_importfrom __future__ import print_functionfrom __future__ import unicode_literals

from sense_hat import SenseHatimport sys

sense = SenseHat()argv = sys.argv

colors = {    "red": (255, 0, 0),    "yellow": (255, 215, 0),    "green": (50, 205, 50),    "blue": (0, 0, 255),    "light_blue": (91, 192, 222),    "white": (255, 255, 255),    "black": (0, 0, 0)}

if colors.has_key(argv[1]):    color = colors[argv[1]]else:    color = colors['black']

pixels = []for pix in range(0, 64) :    pixels.append(color)

sense.set_pixels(pixels)

Page 17: AWS IoTで家庭内IoTをやってみた【JAWS DAYS 2016】

var execSync = require('child_process').execSync;

module.exports = {    sensor: function() {        var data = "" + execSync('python ' + __dirname + '/sensor.py');        return JSON.parse(data);    },    led: function(color) {        execSync('python ' + __dirname + '/led.py ' + color);        return;    }}

Nodeから Pythonへのブリッジ

Page 18: AWS IoTで家庭内IoTをやってみた【JAWS DAYS 2016】

var awsIot = require('aws-iot-device-sdk');var bridge = require('./bridge.js');

var thingShadows = awsIot.thingShadow({    keyPath: './certs/private.pem.key',    certPath: './certs/certificate.pem.crt',    caPath: './certs/root-CA.crt',    clientId: 'pi2_01',    region: 'ap-northeast-1'});

var clientTokenGet;var clientTokenUpdate;

thingShadows.on('connect', function() {    thingShadows.register('pi2_01');    setTimeout(function() {        clientTokenGet = thingShadows.get('pi2_01');    }, 2000);});

Device Shadowから LEDを操作thingShadows.on('status', function(thingName, stat, clientToken, stateObject) {    console.log('received ' + stat + ' on ' + thingName + ': ' + JSON.stringify(stateObject));    if('delta' in stateObject.state && 'color' in stateObject.state.delta){        var delta_state = stateObject.state.delta.color;        bridge.led(delta_state);        console.log('received delta ' + ' on ' + thingName + ': ' + JSON.stringify(stateObject));        clientTokenUpdate = thingShadows.update('pi2_01', { "state": { "reported": { "color": delta_state } } });    }});

thingShadows.on('delta', function(thingName, stateObject) {    var state = stateObject.state.color;    bridge.led(state);    console.log('received delta ' + ' on ' + thingName + ': ' + JSON.stringify(stateObject));    clientTokenUpdate = thingShadows.update('pi2_01', { "state": { "reported": { "color": state } } });});

thingShadows.on('timeout', function(thingName, clientToken) {    console.log('received timeout ' + ' on ' + operation + ': ' + clientToken);});

Page 19: AWS IoTで家庭内IoTをやってみた【JAWS DAYS 2016】

Demo 2

Page 20: AWS IoTで家庭内IoTをやってみた【JAWS DAYS 2016】

Demo 3

湿度センサーRule EngineTopic

LED Device Shadow

Page 21: AWS IoTで家庭内IoTをやってみた【JAWS DAYS 2016】

var awsIot = require('aws-iot-device-sdk');var bridge = require('./bridge.js');

var thingShadows = awsIot.thingShadow({    keyPath: './certs/private.pem.key',    certPath: './certs/certificate.pem.crt',    caPath: './certs/root-CA.crt',    clientId: 'pi2_01',    region: 'ap-northeast-1'});

var clientTokenGet;var clientTokenUpdate;

thingShadows.on('connect', function() {    thingShadows.register( 'pi2_01' );    setTimeout( function() {       clientTokenGet = thingShadows.get('pi2_01');    }, 2000 );    setInterval(function() {        var humidity = bridge.sensor();        console.log(humidity)        thingShadows.publish('pi2_01', JSON.stringify(humidity));    }, 1000);});

センサーデータを収集/Device Shadowから LEDを操作

thingShadows.on('status', function(thingName, stat, clientToken, stateObject) {    console.log('received ' + stat + ' on ' + thingName + ': ' + JSON.stringify(stateObject));    if('delta' in stateObject.state && 'color' in stateObject.state.delta){        var delta_state = stateObject.state.delta.color;        bridge.led(delta_state);        console.log('received delta ' + ' on ' + thingName + ': ' + JSON.stringify(stateObject));        clientTokenUpdate = thingShadows.update('pi2_01', { "state": { "reported": { "color": delta_state } } });    }});

thingShadows.on('delta', function(thingName, stateObject) {    var state = stateObject.state.color;    bridge.led(state);    console.log('received delta ' + ' on ' + thingName + ': ' + JSON.stringify(stateObject));    clientTokenUpdate = thingShadows.update('pi2_01', { "state": { "reported": { "color": state } } });});

thingShadows.on('timeout', function(thingName, clientToken) {    console.log('received timeout ' + ' on ' + operation + ': ' + clientToken);});

Page 22: AWS IoTで家庭内IoTをやってみた【JAWS DAYS 2016】

センサーデータを収集/Device Shadowから LEDを操作

// データの送受信のみの場合は device.publishdevice.publish('pi2_01', JSON.stringify(humidity));

// DeviceShadow使用時は thingShadows.publishthingShadows.publish('pi2_01', JSON.stringify(humidity));

Page 23: AWS IoTで家庭内IoTをやってみた【JAWS DAYS 2016】

# -*- coding: utf-8 -*-from __future__ import print_functionfrom __future__ import unicode_literalsfrom __future__ import absolute_importfrom __future__ import division

import jsonimport boto3

print('Loading function')

iot = boto3.client('iot-data')

def lambda_handler(event, context):    print("Received event: " + json.dumps(event))    humidity = event['humidity']        if humidity < 40:        color = 'blue'    elif humidity >= 40 and humidity <= 70:        color = 'green'    else :        color = 'red'

DeviceShadowを操作するLambda Function

    try:        shadow_stream = response = iot.get_thing_shadow(            thingName='pi2_01'        )                shadow_string = shadow_stream['payload'].read().decode('utf-8')        shadow = json.loads(shadow_string)        desired_color = shadow['state']['desired']['color']                if color != desired_color:            payload = {                "state": {                    "desired": {                        "color": color,                    }                }            }            iot.update_thing_shadow(                thingName='pi2_01',                payload=json.dumps(payload)            )            print('Update DeviceShadow delta: {}'.format(color))        else:            print('DeviceShadow has been updated')        return    except Exception as e:        print(e)        print('Error')        raise e

Page 24: AWS IoTで家庭内IoTをやってみた【JAWS DAYS 2016】

Demo 3

Page 25: AWS IoTで家庭内IoTをやってみた【JAWS DAYS 2016】

気をつけたいところ

• DynamoDBにデータが入らない!?• AWS SDKに IoT関連のものが 2つある

Page 26: AWS IoTで家庭内IoTをやってみた【JAWS DAYS 2016】

DynamoDBにデータが入らない!?

Page 27: AWS IoTで家庭内IoTをやってみた【JAWS DAYS 2016】

DynamoDBにデータが入らない!?

Page 28: AWS IoTで家庭内IoTをやってみた【JAWS DAYS 2016】

• Python

• Node.js

• Java

AWS SDKに IoT関連のものが 2つある

Page 29: AWS IoTで家庭内IoTをやってみた【JAWS DAYS 2016】

まとめ• AWS IoTで簡単にセンサーデータをアップできるようになった。• Device Shadowでリモートからのデバイス制御がやりやすくなった。• この冬は風邪を引かなかった!

Page 30: AWS IoTで家庭内IoTをやってみた【JAWS DAYS 2016】

まとめ

• 家庭の課題解決から IoTを始めよう!