31
33

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

BLEとAWS IoTでクラウドと連携するボタンをつくる

Last updated at Posted at 2015-12-08

今日中に間に合うか!?

この記事は出張中の京都で講演を聴きながら書かれています。
BLE Advent Calenderの今日の当番なので、頑張って書きます。゚(゚´Д`゚)゚。

→すいません、投稿遅れましたm(_ _)m

IoTボタンのブループリント

button

これ!がつくりたいんですが、Wi-Fi使っていると思うので、それだと直接クラウドにつながっちゃってBLE使わない!ってことで、せっかくなのでBLEを使って作成します。

ちなみにざっくりイカのような構成でつくってみました。これは実はTechCrunch Tokyo 2015 CTO Nightで使われたプレゼンボタンです。

blueprint

ボタンを押すと、BLEでスマフォに通信が行って、MQTTでAWS経由で自分の手元のPCまでPub/Subでメッセージが来て、最後にWebSocketでつながっているプレゼンツールが次のページに行ったら成功です!

まずボタン(ハード)をつくる

ボタンの構成はこれです。

  • ポップンみたいなボタンパーツ(既成品)
  • 見栄えを良くするための筐体(Fusion 360で設計→3Dプリンタで製造)

ボタンを買って、

https://www.sengoku.co.jp/mod/sgk_cart/detail.php?code=EEHD-4LG4
button

3DCADで設計して、

cad

3Dプリンターで出力します!

3d

これで一旦ハードウェアの完成です!

基板作成

EagleやQuadceptを使って作成。回路図・アートワークはまた今度。

要素的には

BLEのチップ
⇅ (ファームウェアで制御)
GPIO(Input|Interrupt)
⇅ (電気的なHIGH/LOWを受け取る)
ボタン

ができる構成。

ファーム

ソースを紹介したいけど、NDA(´・ω・`)
今後Nordicのチップを使うことでオープンにしていきたいと思っています。

仮想言語で書くとこんな感じ

void interrupt() {
    notification(characteristic_hander, 1);
}

割り込みピンで入力があったときに呼ばれるコールバックの中に、キャラクタリスティックの通知を送信する関数を呼ぶだけです。

BLE

  • BLEのネットワーク構造はスター型
    • IoTボタン側をペリフェラルとする
    • スマートフォンがセントラル
  • Notification
    • セントラルは基本的には任意のタイミングでペリフェラルにインベントを起こせる/Write
    • ペリフェラルからもセントラルが通知を購読していると、ペリフェラルからのpushがリアルタイム受け取れる(セントラルがペリフェラルをポーリング/readしなくていい)
  • GATTの設計
    • Notificationができるキャラクタリスティックが一つだけ

iOS

CoreBluetoothを使ってゴニョゴニョします。Swiftを使ったCoreBluetoothの使い方については @shu223 のブログに詳しいのでそちらを見て下さい!

Core Bluetooth with Swift (ObjCのおまけ付き) - Qiita

スキャン
import CoreBluetooth
...
    self.centralManager.scanForPeripheralsWithServices(services, options: nil)
...
func centralManager(central: CBCentralManager,
     didDiscoverPeripheral peripheral: CBPeripheral,
     advertisementData: [String : AnyObject],
     RSSI: NSNumber){
     self.peripheral = peripheral
}
接続
...
    self.centralManager.connectPeripheral(self.peripheral, options: nil)
...
func centralManager(central: CBCentralManager,
     didConnectPeripheral peripheral: CBPeripheral) {
}
サービスとキャラクタリスティックの探索
    let services : [CBUUID]? = [self.serviceUUID]
    self.peripheral.delegate = self
    self.peripheral.discoverServices(services)
...
func peripheral(peripheral: CBPeripheral,
     didDiscoverCharacteristicsForService service: CBService,
     error: NSError?){
    let characteristics = service.characteristics!
    self.characteristic = characteristics[0]
}
Notificationを受け取りたいキャラクタリスティックの登録
self.peripheral.setNotifyValue(true, forCharacteristic: self.characteristic)
Notificationが届いたときに受け取る
func peripheral(peripheral: CBPeripheral,
     didUpdateValueForCharacteristic characteristic: CBCharacteristic,
     error: NSError?) {
    print("Update! characteristic UUID: \(characteristic.UUID), value: \(characteristic.value)")
}

ほい、だいぶ端折りましたが、これでペリフェラルのキャラクタリスティックからのNotificationを受け取れるようになりました!

iOS→AWS IoT

iOSがBLE経由で受け取った通知をそのままAWS IoTを使ってPublishします。

プロトコルはMQTTです。

iOSでMQTTにPublishする
import Moscapsule

moscapsule_init()

let mqttConfig = MQTTConfig(clientId: "iot_button", 
           host: "AAAAAAAAAAAAAA.iot.ap-northeast-1.amazonaws.com", port: 8883, keepAlive: 60)
let certFile = NSBundle.mainBundle().pathForResource("1111111111-certificate.pem", ofType: "crt")
let keyFile = NSBundle.mainBundle().pathForResource("2222222222-private.pem", ofType: "key")
let caFile = NSBundle.mainBundle().pathForResource("ca", ofType: "pem")

mqttConfig.mqttServerCert = MQTTServerCert(cafile: caFile, capath: nil)
mqttConfig.mqttClientCert = MQTTClientCert(certfile: certFile!, keyfile: keyFile!, keyfile_passwd: nil)

self.mqttClient = MQTT.newConnection(mqttConfig)
self.mqttClient!.publish(data, topic: "topic/hoge", qos: 1, retain: false)

AWS IoT→Mac

Nodeで書きました!

MQTTを購読してメッセージを受け取る
// aws iotでMQTTの購読
var awsIot = require('aws-iot-device-sdk');
var device = awsIot.device({
    keyPath:  '1111111111-private.pem.key',
    certPath: '2222222222-certificate.pem.crt',
    caPath:   'ca.pem',
    clientId: 'iot_button_sub',
    region: 'ap-northeast-1'
});
// 接続できたら購読する
device.on('connect', function() {
    device.subscribe('topic/hoge');
});
// メッセージを受け取る
device.on('message', function(topic, payload) {
    ...
});

Mac→スライドツール

スライドツールはJS製のものなので、色々ハックできて便利です。

サーバー側
// websocketでブラウザと接続
var io = require('socket.io').listen(8080)
var socket;
io.sockets.on('connection', function(_socket) {
    socket = _socket;
});

// MQTTのメッセージが届いたらsocketでメッセージを送る
socket.emit('click', 'next page');
クライアント(ブラウザ)側
var socket = io.connect("http://localhost:8080");
socket.on('connect', function() {
});
socket.on('click', function(data) {  
    talkie.next.push();
});

これだけ!簡単ですね!

デモ

gif

まとめ

今回はBLEを使ったIoTボタンを作成してみました!Wi-Fiでもやってみたいですが、電池消費を気にすると接続しっぱなしってのは辛いと思うので、リアルタイム性って意味だとBLEで実装してスマフォやIoT Hubでやり取りする方がこういう用途には向くと思いました。

BLEは触っているけどサーバー側までは…って人の参考になれば幸いです☆

31
33
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
31
33

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?