Python	で BLE
(Bluetooth	Low	Energy)
2016年9月15日
西本卓也 @24motz
広島版 IoT 縛りの勉強会 Vol.3
http://ja.nishimotz.com/iotlt_hiroshima
https://github.com/nishimotz/BluefruitLE_samples
1
CR2032 ボタン電池
• 230mAh,	3V	で 6ヶ月 =	BLE	のユースケース
• http://rbs.ta36.com/?p=20398
2
Generic	Access	Profile
• Peripheral	=	デバイス(ITAG)
• Central	=	デバイスと接続するアプリ(Python)
• Broadcaster	=	ビーコン
• Observer	=	ビーコン受信アプリ
3
Key	Finder	+	リモコン機能
• ITAGを紛失するとスマートフォンが警告
• スマートフォンを紛失するとITAGが警告
• ITAGのボタンを押すと
• 位置情報を記録
• ダブルクリックでボイスレコーダー実行
• アプリ iTracing →	更新されていない
• 互換アプリはある(Androidのみ確認)
• いつの間にか静かに接続が切れていたり
• 夜中に突然警告が鳴ったり
4
ITAGの中身
5
状態遷移モデル
6
スタンバイ
アドバタイズ
スレーブ
LED点滅
電源オフ
3秒押し
5秒押し
ボタン押しを送信
警告を受信
警告(LED点滅とブザー)
切断
ボタン押し
ボタン押し
接続
警告停止
Centralの状態遷移モデル
7
スタンバイ
デバイスの一覧を取得
スキャン
イニシエイト
マスター
特定のデバイスに接続要求
スレーブの機能を利用(このまま数ヶ月でも)
LightBlue for	Mac
• BLEデバイスのリストが見える
• スタンバイ →	スキャン →	スタンバイ状態
• 機器を選ぶと Service,	Characteristic	が見える
• イニシエイト →	マスター状態
• GATT	=	Generic Attribute Profile
• 16進数(GUID/UUID)で指定
• ベース部分は共通
• BATTERY SERVICE =	180f
• 0000180f-0000-1000-8000-00805f9b34fb
8
ITAGで確認できること
• 180f	=	BATTERY	SERVICE
• 2a19	=	BATTERY	LEVEL
• 0x64	=	100
• 1802	=	IMMEDIATE	ALERT	SERVICE
• 2a06	=	ALERT	LEVEL
• 0x02	を書き込むと警告
• 0x00	で停止
• ffe0	=	未定義Service
• ffe1	=	未定義Characteristics
• subscribe	するとボタン押しで 0x01	が notify	される
9
BluefruitLE Python	Library
• Adafruit が公開
• MacとLinux(Raspberry	Pi)に対応
• Linux	PyBluez
• Core Bluetooth	PyObjC
• Adafruit のデバイスで使う例しかない
• やってみたら ITAG	を叩ける
10
メインループ
import	Adafruit_BluefruitLE,	uuid
BATTERY_SERVICE	=	uuid.UUID('0000180f-…)
BATTERY_LEVEL	=	uuid.UUID('00002a19-…')
def main():
#デバイスのスキャン、接続、値の読み書き
provider	=	Adafruit_BluefruitLE.get_provider()
provider.initialize()
provider.run_mainloop_with(main)
11
デバイスのスキャン
adapter	=	provider.get_default_adapter()				
adapter.power_on()
adapter.start_scan()
device	=	provider.find_device()
adapter.stop_scan()
print(device.name)
12
接続して値の読み取り
device.connect()
device.discover([BATTERY_SERVICE],	[BATTERY_LEVEL])
service	=	device.find_service(BATTERY_SERVICE)
c	=	service.find_characteristic(BATTERY_LEVEL)
v	=	c.read_value()
print(ord(v[0]))
device.disconnect()
13
書き込み:write_value()
通知待ち:start_notify()
まとめ
• IMMEDIATE_ALERT は hello	world
• Bluefruit LE	Python	は Central	専用
• データ収集
• Peripheral	の調査やデバッグ
• RasPi を Central	として運用
• MacでPythonが独自ビルド版の場合は
• pip	install	pyobjc
• リファレンスがないのでソースを読んで理解
• スマートフォンアプリ開発
14

Mac から Python で BLE ペリフェラルを操作する