はじめに
前回ラズパイで L チカができました!!
今回は BLE を使って iOS 端末からチカチカさせてみます!!
ほぼ下記参考にしました(コードはほぼコピペです)。
Bluetoothを使って自作iPhoneアプリとRaspberry piでLEDチカらせる
セントラル、ペリフェラル、サービス、アドバタイズとかは気にせず実装!!(実装してから後で知ればいいきっと。。。)
ラズパイ側の実装
ラズパイは下記のように実装します。
-
SSH 接続する。
-
下記コマンドを実行していきラズパイを BLE 接続できるようにする。
1234567891011121314151617181920212223242526# node.jsインストール$ sudo apt-get install -y nodejs# npmインストール$ sudo apt-get install -y npm# blenoに必要なやつインストール$ sudo apt-get install bluetooth bluez libbluetooth-dev libudev-dev# ble_ledディレクトリ作成$ mkdir ble_led# ble_ledディレクトリに移動$ cd ble_led# npm初期化$ npm init -y# blenoとonoffインストール$ npm install -D @abandonware/bleno onoff# ble.jsファイル作成$ touch ble.js# ble.jsファイル編集$ vim ble.jsbleno をインストールすると bluetooth-hci-socket のインストールでエラーになったので @abandonware/bleno をインストールしました。
-
i と入力し入力モードにする。
-
下記ソースをコピペする。
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556var Gpio = require('onoff').Gpiovar led = new Gpio(17, 'out');var bleno = require('@abandonware/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 SwitchCharacteristic()]});function exit() {led.unexport();process.exit();}process.on('SIGINT', exit); //ctr + c などの信号 -
esc を押して入力モードを終了する。
-
:wq と入力し Enter で保存して終了する。
package.json の中身は下記のようになっていました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
{ "name": "ble_led", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "@abandonware/bleno": "^0.5.1-3", "onoff": "^6.0.1" } } |
iOS 側の実装
iOS は下記のように実装します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
import UIKit import CoreBluetooth final class ViewController: UIViewController { private var centralManager: CBCentralManager! private var peripheral: CBPeripheral? private var lightCharacteristic: CBCharacteristic? override func viewDidLoad() { super.viewDidLoad() centralManager = CBCentralManager(delegate: self, queue: nil) } @IBAction private func scanForPeripherals(_ sender: Any) { centralManager.scanForPeripherals(withServices: nil, options: nil) } @IBAction private func connectPeripheral(_ sender: Any) { if let peripheral = peripheral { centralManager.connect(peripheral, options: nil) } } @IBAction private func switchLED(_ sender: UISwitch) { guard let peripheral = peripheral, let lightCharacteristic = lightCharacteristic else { sender.isOn.toggle() return } var value: CUnsignedInt = sender.isOn ? 1 : 0 print("write characteristic and \(sender.isOn)") let data = Data(bytes: &value, count: 1) peripheral.writeValue(data, for: lightCharacteristic, type: .withResponse) } } extension ViewController: CBCentralManagerDelegate { func centralManagerDidUpdateState(_ central: CBCentralManager) { switch central.state { case .unknown: print("state: unknown") case .resetting: print("state: resetting") case .unsupported: print("state: unsupported") case .unauthorized: print("state: unauthorized") case .poweredOff: print("state: poweredOff") case .poweredOn: print("state: poweredOn") @unknown default: assertionFailure("想定外") } } func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) { guard let peripheralName = peripheral.name else { return } print("peripheral: \(peripheralName)") // 1回目は"led service"で見つかったけど2回目から"raspberrypi"になった。。。 if peripheralName == "led service" || peripheralName == "raspberrypi" { centralManager.stopScan() self.peripheral = peripheral } } func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) { print("connected") peripheral.delegate = self peripheral.discoverServices(nil) } func centralManager(_ central: CBCentralManager, didFailToConnect peripheral: CBPeripheral, error: Error?) { print("fail connect") } } extension ViewController: CBPeripheralDelegate { func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) { guard let services = peripheral.services else { if let error = error { print("error: \(error)") } return } print("Found \(services.count) services: \(services)") for service in services { print(service.uuid.uuidString) if service.uuid.uuidString == "FF10" { print("discovering characteristics") peripheral.discoverCharacteristics(nil, for: service) } } } func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) { guard let characteristics = service.characteristics else { if let error = error { print("error in dicovercharc: \(error)") } return } print("Found \(characteristics) characteristics! : \(characteristics)") for characteristic in characteristics { if characteristic.uuid.uuidString == "FF11" { self.lightCharacteristic = characteristic } } } } |
レイアウトはこんな感じです。
配線
配線は前回のやつとほぼ同じです。
違うのは1箇所だけです。ラズパイの GPIO2 に挿していたジャンバ線1のメスを GPIO17 に挿し替えます。
起動
iOS アプリから LED をチカチカさせます!
-
SSH 接続する。
-
下記コマンドを実行しアドバタイズを開始する。
12$ cd ble_led$ sudo node ble.js -
start advertise と表示されるのを待ち iOS アプリを起動する。
-
iOS アプリで Scan ボタンを押下する。
-
iOS アプリで Connect ボタンを押下する。
-
iOS アプリでスイッチを操作して LED がチカチカする。
接続できていればスイッチ操作時にターミナルに下記のように表示されます。
1 2 |
write request: 01 write request: 00 |
おわりに
これで iPhone からラズパイを操作できるようになりました!!次は何しようかな。
コメント