ビーコンのMajor値を場所、Minor値を温度の値としてアドバタイズして、
それを受信する温度管理アプリを作るまでのメモ。
参考
Bluetooth仕様 Bluetooth Specifications
開発環境セットアップ方法 【改訂版】BLE112 / 113 の開発環境を Mac に構築する
参考にさせて頂くiBeacon送信ソース slackhappy/ble112/beacon
BGScript関連 BLEデバイス製作とIPHONEからのコントロールの基本
調査
Bluetoothの設定はBGScriptで開発できる。以下4ファイルを作成してout.hexを生成する。
- gatt.xml
- hardware.xml
- beacon.bgs
- project.xml
project.xml
<project>
<gatt in="gatt.xml" />
<hardware in="hardware.xml" />
<script in="beacon.bgs" />
<image out="out.hex" />
</project>
ビーコン送信のgattとbgsが何やっているか調べてみた。
gatt.xml
<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
<!—- 標準サービスUUID 0x1800 = 汎用アクセスプロファイルGAP -—>
<service uuid="1800">
<description>Generic Access Profile</description>
<!—- 標準キャラクタリスティックタイプUUID 0x2A00 = デバイス名称 -—>
<characteristic uuid="2a00">
<properties read="true" const="true" />
<value>iBeacon Demo</value>
</characteristic>
<!—- 標準キャラクタリスティックタイプUUID 0x2a01 = 外観 -—>
<characteristic uuid="2a01">
<properties read="true" const="true" />
<value type="hex">4142</value>
</characteristic>
</service>
<!—- 標準サービスUUID 0x180A = デバイス情報(すべてオプション。無くてもよい?) -—>
<service uuid="180A">
<description>Device Information</description>
<!—- 標準キャラクタリスティックタイプUUID 0x2a29 = メーカー名 -—>
<characteristic uuid="2a29">
<properties read="true" const="true" />
<value>Bluegiga</value>
</characteristic>
<!—- 標準キャラクタリスティックタイプUUID 0x2a28 = ソフトウェアリビジョン -—>
<characteristic uuid="2a28">
<properties read="true" const="true" />
<value>1.0</value>
</characteristic>
<!—- 標準キャラクタリスティックタイプUUID 0x2a26 = ファームウェアリビジョン -—>
<characteristic uuid="2a26">
<properties read="true" const="true" />
<value>25</value>
</characteristic>
<!—- 標準キャラクタリスティックタイプUUID 0x2a24 = モデル番号 -—>
<characteristic uuid="2a24">
<properties read="true" const="true" />
<value>BLE112</value>
</characteristic>
</service>
<!—- ユーザー独自定義タイプのUUIDは128ビット -—>
<!—- 7548d6e0-3476-11e3-aa6e-0800200c9a66は何でもよい? -—>
<service uuid="7548d6e0-3476-11e3-aa6e-0800200c9a66" advertise="true">
<description>iBeacon Service</description>
<!—- id属性を付けるとbgsファイルから参照できる(idはキャラクタリスティックのみ付けられる) -—>
<characteristic uuid="7548d6e1-3476-11e3-aa6e-0800200c9a66" id="xgatt_beacon_uuid">
<description>UUID</description>
<properties read="true" write="true" />
<!—- UUID値 -—>
<value length="16" type="hex">E2C56DB5DFFB48D2B060D0F5A71096E0</value>
</characteristic>
<characteristic uuid="7548d6e2-3476-11e3-aa6e-0800200c9a66" id="xgatt_beacon_major">
<description>Major</description>
<properties read="true" write="true" />
<!—- Major値 -—>
<value length="2" type="hex">0001</value>
</characteristic>
<characteristic uuid="7548d6e3-3476-11e3-aa6e-0800200c9a66" id="xgatt_beacon_minor">
<!—- Minor値 -—>
<description>Minor</description>
<properties read="true" write="true" />
<value length="2" type="hex">0002</value>
</characteristic>
<characteristic uuid="7548d6e4-3476-11e3-aa6e-0800200c9a66" id="xgatt_beacon_tx">
<!—- 送信電波出力 -—>
<description>Tx Power</description>
<properties read="true" write="true" />
<value length="1" type="hex">BC</value>
</characteristic>
<characteristic uuid="7548d6e5-3476-11e3-aa6e-0800200c9a66" id="xgatt_beacon_adv">
<!—- ペイロードデータ。bgs内で作成するのでvalueは空 -—>
<description>Advertising Payload</description>
<properties read="true"/>
<value length="30" type="hex"></value>
</characteristic>
</service>
</configuration>
beacon.bgs
# 変数は32bit-integer。必ず定義が必要
dim load_result
dim load_len
dim uuid_value(16)
dim major_value(2)
dim minor_value(2)
dim tx_value(1)
dim ps_beacon_uuid
dim ps_beacon_major
dim ps_beacon_minor
dim ps_beacon_tx
dim adv_data(30) # custom adv data
# Boot event listener
event system_boot(major, minor, patch, build, ll_version, protocol_version, hw)
# ‘$’を付けると16進数
ps_beacon_uuid = $8000
# PS Storeから読み込み。GATT event listernerの方が先に呼ばれる(のだろう)
# PS Storeにはユーザーデータを保存することができて、8000から807Fのキーが利用可能。それぞれ32Bytes保存可能。
call flash_ps_load(ps_beacon_uuid)(load_result, load_len, uuid_value(0:16))
# xgatt_beacon_uuidの値をuuid_valueに出力
call attributes_write(xgatt_beacon_uuid, 0, load_len, uuid_value(0:16))
ps_beacon_major = $8001
call flash_ps_load(ps_beacon_major)(load_result, load_len, major_value(0:2))
call attributes_write(xgatt_beacon_major, 0, load_len, major_value(0:2))
ps_beacon_minor = $8002
call flash_ps_load(ps_beacon_minor)(load_result, load_len, minor_value(0:2))
call attributes_write(xgatt_beacon_minor, 0, load_len, minor_value(0:2))
ps_beacon_tx = $8003
call flash_ps_load(ps_beacon_tx)(load_result, load_len, tx_value(0:1))
call attributes_write(xgatt_beacon_tx, 0, load_len, tx_value(0:1))
# iBeacon用のパケットを生成
adv_data( 0:1) = $02 # ad field length = 2 bytes
adv_data( 1:1) = gap_ad_type_flags # ad field type = 0x01 (Flags)
adv_data( 2:1) = $06 # 3.C.18.1: 00000110b generaldisc, no BR/EDR
adv_data( 3:1) = $1a # ad field length = 26 bytes
adv_data( 4:1) = $ff # 3.C.18.11 manufacturer-specific data
adv_data( 5:1) = $4c # Apple, Inc.
adv_data( 6:1) = $00 # Apple, Inc.
adv_data( 7:1) = $02 # iBeacon header, part 1
adv_data( 8:1) = $15 # iBeacon header, part 2 (maybe length?)
adv_data(9:16) = uuid_value(0:16)
adv_data(25:2) = major_value(0:2)
adv_data(27:2) = minor_value(0:2)
adv_data(29:1) = tx_value(0:1) # 2's complement of calibrated Tx Power
# set advertising payload so it can be seen in the GATT
call attributes_write(xgatt_beacon_adv, 0, 30, adv_data(0:30))
# set the iBeacon data
call gap_set_adv_data(0, 30, adv_data(0:30))
call gap_set_mode(gap_user_data, gap_undirected_connectable)
end
# GATT event listener
event attributes_value(connection, reason, handle, offset, value_len, value)
if handle = xgatt_beacon_uuid then
call flash_ps_save(ps_beacon_uuid, 16, value(0:16))
adv_data(9:16) = value(0:16)
end if
if handle = xgatt_beacon_major then
call flash_ps_save(ps_beacon_major, 2, value(0:2))
adv_data(25:2) = value(0:2)
end if
if handle = xgatt_beacon_minor then
call flash_ps_save(ps_beacon_minor, 2, value(0:2))
adv_data(27:2) = value(0:2)
end if
if handle = xgatt_beacon_tx then
call flash_ps_save(ps_beacon_tx, 1, value(0:1))
adv_data(29:1) = value(0:1) # 2's complement of calibrated Tx Power
end if
# update the advertising payload
call attributes_write(xgatt_beacon_adv, 0, 30, adv_data(0:30))
call gap_set_adv_data(0, 30, adv_data(0:30))
end
event connection_disconnected(handle, result)
call gap_set_mode(gap_user_data, gap_undirected_connectable)
end
わかったこと
adv_data(27:2) = minor_value(0:2)
の部分に温度を入れれば良さそう。
次は温度を取得するサンプルを調べてみる。