iPhoneからBLE技術を使ってラズパイをLチカさせたいと思った時に、なかなか資料が見つからなくてつまりまくったのでまとめておきます。
Goal
やること
- そもそもラズパイのLチカまで(MacからSSH接続をし、キーボード、ディスプレイ無しでやる)
- Swiftを使ったiPhone(セントラル)の実装
- node.jsとblenoモジュールを使ったラズパイの実装
- 作成したnode.jsファイルを起動時に自動実行
事前準備&知識
raspberry piについて
まず、このへんをみて買ったり回路を組んだりしました。
http://qiita.com/IsaoTakahashi/items/f59cb21f1202fade3d4f
http://deviceplus.jp/hobby/raspberrypi_entry_009/
実際に買ったのは
- raspberry pi3 (wifiやbluetoothが標準で扱える)
- ブレッドボード
- メスxオスのジャンプワイヤ
- LED
- 抵抗
- micro SDカード(microですよ!)
- micro SDカードをpcとつなげるための変換機
- LANケーブル及びMACにLANケーブル刺すための変換器
- raspberry piとmacをつなぐケーブル(androidのもの)
セットアップは以下などを参考にしました。
http://karaage.hatenadiary.jp/entry/2015/07/15/080000
また実際のssh接続については、OSインストール後にLANケーブルでMACとraspberry piをつなぎ、macのターミナルで
ssh pi@raspberrypi.local
をし、デフォルトのパスワード、「raspberry」を入力すれば接続できました
配線は以下を参考にしました
http://deviceplus.jp/hobby/raspberrypi_entry_009/
またラズパイを操作してLチカさせることについては
http://deviceplus.jp/hobby/raspberrypi_entry_009/
のコマンド実行の下りが参考になります。
またwi-fiの設定については
http://qiita.com/morizotter/items/48ad0b17207b0dd66cac
http://yamaryu0508.hatenablog.com/entry/2014/08/15/001312
このへんを参考にしましたが、要するに
/etc/wpa_supplicant/wpa_supplicant.conf
にvimかなんかで
network={
ssid="SSID"
psk="パスワード"
}
を突っ込めばokです。
僕だけかもしれませんが、networkを複数書くとつながらないので注意です。また複数のwi-fiを設定しておきたいときは別途面倒くさい設定がいるみたいです。
この段階でやることの1番目が終わってますね。
BLEとは?
Bluetooth Low Energyの略です。
基本知識は
http://qiita.com/appwatcher/items/5c4585f61fc0a0d6269b
http://qiita.com/miyatay/items/4d4ce4ccd7905ddc0144
この辺が参考になりました。
ひとまずBLEを使うために必要な知識としては
- BLEの接続元(主体)をセントラル、接続先(客体)をペリフェラルという。ペリフェラルが受け身の方
- ペリフェラル側にセントラルから実行してほしい機能を実装するが、その機能はキャラクタリスティックから成るサービスという単位で実装する。
- セントラルはペリフェラルがアドバタイズ(広告的な意味で発信的な...)をしてくれることで端末を発見する
- セントラルはペリフェラルを発見したら、そのサービスを見つけ、さらにサービスのキャラクタリスティックを見つけ、そこに書き込みや読み込みをする。
- 今回はSwiftでセントラル側の実装を、node.jsでペリフェラル側の実装を行えばいい。
2. Swiftを使ったiPhone(セントラル)の実装
CoreBluetoothを使います。
というか基本的に
http://qiita.com/shu223/items/78614325ce25bf7f4379
これ見ればなんとかなります。
とりあえず、Centralとして振る舞わせるんですが、
- Peripheralを検索する
- Peripheralに接続する。
- サービスを見つける
- キャラクタリスティックをみつける。
- キャラクタリスティックに書き込み処理をする。(後述しますが、今回は0, 1でoff on です)
↑をデリゲートを使いながらうまくやればOKです
リファクタリングも何も行っていない汚コードですが一応参考はこちら
=> https://github.com/kentarohorie/RasPiTest
3. node.jsとblenoモジュールを使ったラズパイの実装
node.js 及び bleno というモジュールを使います。
blenoはPeripheralとしての振る舞いを実装するためのモジュールです。
またLEDを扱うための onoffモジュールもインストールしましょう。
ラズパイに上記インストールしてください。
インストールの際はwi-fiがしっかりつながっていることを pingコマンドなどで確認しておきましょう。
またnodeコマンドやsudo nodeコマンドが使えない場合はwhereis コマンドやln -s コマンド等を使って、コマンドの置き場(/usr/binに貼ったらいけたはず)にシンボリックを貼りましょう。
Peripheralとしての処理は
- characteristic作成
- characteristicに書き込み、読み込みがあったときにどのような処理をするか実装
- service作成&characteristicの追加
- advertize実行(僕BLEいけますよーって発信する)
みたいな感じです。
基本的に
https://github.com/sandeepmistry/bleno (bleno公式)
http://don.github.io/slides/2015-09-27-rpi-ble/#/ (ほぼ同じことをしているスライドの説明)
https://github.com/don/mfny2015-rpi-ble/blob/master/peripheral/led.js (そのスライドの全コード)
この辺を参考に、ほぼコピーで実装しました。
var Gpio = require('onoff').Gpio
var led = new Gpio(17, 'out');
var bleno = require('bleno');
var util = require('util');
var Characteristic = bleno.Characteristic;
var PrimaryService = bleno.PrimaryService;
bleno.on('stateChange', function(state) {
if(state=='poweredOn') {
console.log('bluetooth power on')
bleno.startAdvertising('led service', ['FF10']);
}
});
bleno.on('advertisingStart', function(err) {
if(!err) {
console.log('start advertise')
bleno.setServices([lightService]);
}
});
var SwitchCharacteristic = function() {
SwitchCharacteristic.super_.call(this, {
uuid: 'ff11',
properties: ['read', 'write']
});
};
util.inherits(SwitchCharacteristic, Characteristic);
SwitchCharacteristic.prototype.onReadRequest = function(offset, callback) {
console.log('read request');
var data = new Buffer(1);
data[0] = led.readSync();
callback(this.RESULT_SUCCESS, data);
};
SwitchCharacteristic.prototype.onWriteRequest = function(data, offset, withoutResponse, callback) {
console.log('write request: ' + data.toString('hex'));
led.writeSync(data[0]);
callback(this.RESULT_SUCCESS);
};
var lightService = new PrimaryService({
uuid: 'ff10',
characteristics: [
new SwitchCharc()
]
});
function exit() {
led.unexport();
process.exit();
}
process.on('SIGINT', exit); //ctr + c などの信号
これを
sudo node ~.js
で実行するとアドバタイズが開始されます。
sudo コマンドは必須です。
4. 作成したnode.jsファイルを起動時に自動実行
forever をインストールして、
/etc/rc.local
に
forever start /home/pi/my_codes/bleno_test.js
を記述したらいけました。
起動後10秒~20秒くらいはかかります。
ちなみにhomeを「〜」で記述するとうまくいかないみたいです。(http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q12151965192)
たぶん以上です。
電子工作したことない、そもそもBLEってなんなの、ていうかJSあんま書けない
ってところからスタートしたので基礎知識から勉強したりコストかかりました。。。
だいぶざっくり雑に書きましたが僕のように余計に時間がかからずタイトルのようなことを実現できることを祈ります。