8.9K Views
September 12, 22
スライド概要
iOSDC 2022 day1 LTの発表資料です
https://fortee.jp/iosdc-japan-2022/proposal/f554bc51-9c63-4487-a556-0085269511c4
SwiftとLEGOとBluetooth LEが好きなプログラマ
Bluetoothでレゴを リモートプログラミングしよう 大庭 慎一郎 @ooba / @bricklife
自己紹介 大庭 慎一郎(おおば しんいちろう) ID: @ooba / @bricklife SwiftとLEGOが好きなプログラマ メルカリiOS版 立ち上げメンバー
今日話すこと Bluetoothに対応しているレゴのセットがいっぱいあるよ Bluetooth通信でモーターやセンサーを制御できるよ そのための通信プロトコルがいくつかあるよ Bluetooth LE向けの「LEGO Wireless Protocol」を紹介するよ
レゴでBluetooth? レゴでモーター? レゴでセンサー?
Bluetooth対応パーツ ポートあり WeDo 2.0 2006 2013 2016 2017 2018 SPIKEプライム 2019 SPIKEベーシック 2021 2020 2019
ポート LPF2
LPF2規格のパーツ
カラーセンサーが赤を検知した モーターを50%のスピードで回せ
Bluetooth対応パーツ ポートなし 2020 2018 2021 2018 2022
レゴ公式のプログラミング環境 Powered UP SPIKE MINDSTORMS
LEGO Wireless Protocol
LEGO Wireless Protocol https://lego.github.io/lego-ble-wireless-protocol-docs/ レゴ社がGitHubで公開しているBluetooth LEの通信仕様 最近のBluetooth LE対応パーツはすべてこのプロトコルを採用
LEGO Wireless Protocol対応 ポートあり 2017 2018 SPIKEベーシック 2021 2019
LEGO Wireless Protocol対応 ポートなし 2020 2018 2021 2018 2022
Bluetooth LEの2つの役割 ペリフェラル ペリフェラル セントラル ペリフェラル ペリフェラル
Bluetooth LEの2つの役割
LEGO Wireless Protocolの設計 サービス UUID: 00001623-1212-EFDE-1623-785FEABCD123 Write キャラクタリスティック UUID: 00001624-1212-EFDE-1623-785FEABCD123 Notify
セントラル側のプログラミング手順 1. ペリフェラルをスキャンする 2. ペリフェラルに接続する 3. サービスを取得する 4. キャラクタリスティックを取得する 5. キャラクタリスティックに対して操作をする
iOS / macOSのBluetooth LEプログラミング Core Bluetoothフレームワークを使う ほぼすべてがデリゲートベースの非同期処理 説明しづらいので今日はAsyncBluetoothを使う
AsyncBluetooth https://github.com/manolofdez/AsyncBluetooth Core BluetoothをSwift Concurrencyに対応させるライブラリ セントラル側の一連の流れを直列に書ける
セントラル側のプログラミング手順 1. ペリフェラルをスキャンする 2. ペリフェラルに接続する 3. サービスを取得する 4. キャラクタリスティックを取得する 5. キャラクタリスティックに対して操作をする
モーターを回すまでの最小コード
let serviceUuid = CBUUID(string: "00001623-1212-EFDE-1623-785FEABCD123")
let characteristicUuid = CBUUID(string: "00001624-1212-EFDE-1623-785FEABCD123")
let centralManager = CentralManager()
try await centralManager.waitUntilReady()
1
let scanDataStream = try await centralManager.scanForPeripherals(withServices: [serviceUuid])
2
for await scanData in scanDataStream {
let peripheral = scanData.peripheral
try await centralManager.connect(peripheral, options: nil)
3
try await peripheral.discoverServices([serviceUuid])
guard let service = peripheral.discoveredServices?.first else { continue }
4
try await peripheral.discoverCharacteristics([characteristicUuid], for: service)
guard let characteristic = service.discoveredCharacteristics?.first else { continue }
5
try await peripheral.writeValue(Data([0x08,
[0x08, 0x00, 0x81, 0x00, 0x11, 0x51, 0x00, 0x32]),
0x32]
for: characteristic, type: .withResponse)
}
モーターのパワーを設定するメッセージ https://lego.github.io/lego-ble-wireless-protocol-docs/index.html#output-sub-command-startpower-power ヘッダーパート メッセージパート [0x08, 0x00, 0x81, 0x00, 0x11, 0x51, 0x00, 0x32] メッセージ長: 8 ポート: A (0x00) メッセージタイプ: Port Output Command (0x81) パワー: 50%
メッセージタイプ一覧 https://lego.github.io/lego-ble-wireless-protocol-docs/index.html#message-types Name Value Notes Name Value Notes Hub Properties 0x01 Set or retrieve standard Hub Property information Port Information Request 0x21 Request Port information Hub Actions 0x02 Perform actions on connected hub Port Mode Information Request 0x22 Request Port Mode information Hub Alerts 0x03 Subscribe or retrieve Hub alerts Port Input Format Setup (Single) 0x41 Setup input format for single mode Port Input Format Setup (CombinedMode) 0x42 Setup input format for multiple modes (CombinedMode) Port Information 0x43 N/A Port Mode Information 0x44 N/A Port Value (Single) 0x45 Value update related to single Port Mode Port Value (CombinedMode) 0x46 Value update related to multiple Port Modes in combination (CombinedMode) Port Input Format (Single) 0x47 N/A Port Input Format (CombinedMode) 0x48 N/A Virtual Port Setup 0x61 Used to control synchronization between synchronizable ports. Port Output Command 0x81 Used to execute Port Output commands Port Output Command Feedback 0x82 Provides feedback on completed Port Output commands Hub Attached I/O Generic Error Messages H/W NetWork Commands F/W Update - Go Into Boot Mode F/W Update Lock memory F/W Update Lock Status Request F/W Lock Status 0x04 0x05 0x08 0x10 0x11 0x12 0x13 Transmitted upon Hub detection of attached I/O Generic Error Messages from the Hub Commands used for H/W Networks Set the Hub in a special Boot Loader mode Locks the memory Request the Memory Locking State Answer to the F/W Lock Status Request
実装の参考になるプロジェクト https://github.com/nathankellenicki/node-poweredup - 対応が早くて充実 (Node.js) https://github.com/bricklife/BoostRemote/ - LEGO Wireless Protocol公開前に作り始めたリモコンアプリ (Swift / iOS) https://github.com/LLK/scratch-vm/tree/develop/src/extensions - Scratchの公式拡張機能としてMINDSTORMS EV3、WeDo 2.0、BOOSTに対応している (Node.js) https://github.com/bricklife/scratch-lego-bluetooth-extensions - 上記以外のBluetooth対応レゴをScratchで制御するための拡張機能セット (Node.js)
ありがとうございました