概要
3000円の Bluetooth 対応体重計を Raspberry Pi を使って Google Fit に対応させてみた その1 の続き。
前回までのおさらい
- 3000円で買ってきた Bluetooth(BLE)対応体重計を Google Fit に対応させたい
- Node.js の BLE モジュール noble をつかって接続を試みる
- どうやら「000FatScale01」という名前を名乗っているデバイスが該当の体重計らしい
- Device Information サービスをみつけたので特性の一覧を出力してみた
今回の内容
- Device Information サービスの特性(characteristic)を探査してその値を読む
- 「00FatScale01」の独自サービス(0xFFF0)の特性を探査
- 探査した特性を購読(subscribe)して体重の値を受信する
Device Information サービスの特性の値を読む
パーミッションについて
前回 noble を使って取得した Device Information サービスの特性(Characteristic)は、このような構造になっていた。
Characteristic {
_serviceUuid: '180a',
uuid: '2a29',
name: 'Manufacturer Name String',
type: 'org.bluetooth.characteristic.manufacturer_name_string',
properties: [ 'read' ],
descriptors: null }
uuid
、name
,type
はわかるが、properties
とはなにものだろうか。
調べてみたところ、 properties
は特性に対して許可されている操作のリストになっているとのこと。
properties 属性の主な値
Property | 内容 |
---|---|
read | 読み込み可能 |
write | 書き込み可能 |
notify | 送信側からの値変更通知(notify)を、購読(subscribe)できる |
ここでは read
のみが許可されているので読み込みが可能ということになる。
各々の値を読んでみた
各特性が読み込み可能だということがわかったので、さっそく値を読んでみたい。
read-device-information-characteristics.js
const noble = require('noble')
const FAT_SCALE = '000FatScale01'
// Bluetooth のステータスを監視
noble.on('stateChange', (state) => {
console.log(`\nstateChange: ${state}\n`)
if (state === 'poweredOn') {
// Bluetooth がオンの場合は周辺機器のスキャンを開始
noble.startScanning()
} else {
// Bluetooth がオフの場合は周辺機器のスキャンを停止
noble.stopScanning()
}
})
// 周辺機器が見つかったら、接続後サービスを探査
noble.on('discover', (peripheral) => {
const localName = peripheral.advertisement.localName
if (localName === FAT_SCALE) {
console.log(`discover peripheral: ${FAT_SCALE}\n`)
// スキャンを停止
noble.stopScanning()
// 接続後 Device Information サービス(0x180a)を探査
peripheral.once('connect', () => {
peripheral.discoverServices(['180a'])
})
// 探査されたサービスを出力
peripheral.once('servicesDiscover', onServiceDiscover)
// 見つかった 000FatScale01 に接続
peripheral.connect()
}
})
// 探査されたサービスの特性を探査
function onServiceDiscover (services) {
services
.forEach((service) => {
console.log('Discover Service: Device Information\n')
service.once('characteristicsDiscover', onCharacteristicsDiscover)
service.discoverCharacteristics()
})
}
// 探査された特性の値を出力
function onCharacteristicsDiscover (characteristics) {
console.log('Discover Characteristics:\n')
characteristics
.forEach(characteristic => {
characteristic.read((err, data) => {
if (err) throw err
// type に _string を含む場合は文字列として値を取得
// その他の場合は16進数として取得
let value = (characteristic.type.indexOf('_string') !== -1)
? data.toString() : data.toString('hex')
console.log(`(${characteristic.uuid}) ${characteristic.name} : ${value}`)
})
})
}
その結果がこちら(※シリアルナンバーの一部は念のため伏せ字にした)。
$ node read-device-information-characteristics.js
stateChange: poweredOn
discover peripheral: 000FatScale01
Discover Service: Device Information
Discover Characteristics:
(2a29) Manufacturer Name String : FSRK
(2a24) Model Number String : BT 4.0
(2a25) Serial Number String : Xqm2017****
(2a26) Firmware Revision String : sdkv37-no32k
(2a27) Hardware Revision String : FSRK-34-32-S
(2a28) Software Revision String : V003-noupdate
(2a23) System ID : 0000000000000000
(2a2a) IEEE 11073-20601 Regulatory Certification Data List : fe006578706572696d656e74616c
(2a50) PnP ID : 010e0012340167
Bluetoothデバイスから初めて読み込んだなにかしらの具体的なデータなので、なんか感動した。
「000FatScale01」 の独自サービス(0xfff0)の調査
無事、Device Information サービスの特性の値を読むことができたので、続いて本丸である「000FatScale01」の独自サービスだと思われる 0xfff0 を見ていくことにしたい。
0xfff0 の特性を探査
まずはどんな特性があるか見てみた。
discover-0xfff0-characteristics.js
const noble = require('noble')
const FAT_SCALE = '000FatScale01'
// Bluetooth のステータスを監視
noble.on('stateChange', (state) => {
console.log(`\nstateChange: ${state}\n`)
if (state === 'poweredOn') {
// Bluetooth がオンの場合は周辺機器のスキャンを開始
noble.startScanning()
} else {
// Bluetooth がオフの場合は周辺機器のスキャンを停止
noble.stopScanning()
}
})
// 周辺機器が見つかったら、接続後サービスを探査
noble.on('discover', (peripheral) => {
const localName = peripheral.advertisement.localName
if (localName === FAT_SCALE) {
console.log(`discover peripheral: ${FAT_SCALE}\n`)
// スキャンを停止
noble.stopScanning()
// 接続後サービス(0xfff0)を探査
peripheral.once('connect', () => {
peripheral.discoverServices(['fff0'])
})
// 探査されたサービスを出力
peripheral.once('servicesDiscover', onServiceDiscover)
// 見つかった 000FatScale01 に接続
peripheral.connect()
}
})
// 探査されたサービスの特性を探査
function onServiceDiscover (services) {
services
.forEach((service) => {
console.log('Discover Service: Device Information\n')
service.once('characteristicsDiscover', onCharacteristicsDiscover)
service.discoverCharacteristics()
})
}
// 探査された特性の内容を出力
function onCharacteristicsDiscover (characteristics) {
console.log('Discover Characteristics:\n')
characteristics
.forEach(characteristic => {
// 不要なデータを削除
delete characteristic._noble
delete characteristic._peripheralId
delete characteristic._serviceUuid
console.dir(characteristic)
console.log()
})
}
その結果がこちら。
$ node discover-0xfff0-characteristics.js
stateChange: poweredOn
discover peripheral: 000FatScale01
Discover Service: Device Information
Discover Characteristics:
Characteristic {
uuid: 'fff2',
name: null,
type: null,
properties: [ 'read', 'write' ],
descriptors: null }
Characteristic {
uuid: 'fff6',
name: null,
type: null,
properties: [ 'read', 'write', 'notify' ],
descriptors: null }
Characteristic {
uuid: 'fff1',
name: null,
type: null,
properties: [ 'read', 'write', 'notify' ],
descriptors: null }
fff1
,fff2
,fff6
という3つの特性が探査できた。
fff1
は 読み込み・書き込みが可能、fff2
と fff6
は、読み込み・書き込み・通知の購読が可能のようだ。
とりあえず特性を読む
とりあえず、3つとも読み込みが可能ということなので、値を読んでみた。
read-0xfff0-characteristics.js
// (中略)
// 探査された特性の値を出力
function onCharacteristicsDiscover (characteristics) {
console.log('Discover Characteristics:\n')
characteristics
.forEach(characteristic => {
characteristic.read((err, data) => {
if (err) throw err
console.log(`(${characteristic.uuid}): ${data.toString('hex')}`)
})
})
}
$ node read-0xfff0-characteristics.js
stateChange: poweredOn
discover peripheral: 000FatScale01
Discover Service: Device Information
Discover Characteristics:
(fff2): 0000000000000000000000000000000000000000
(fff6): 0000000000000000000000000000000000000000
(fff1): 0000000000000000000000000000000000000000
ものの見事にスッカラカンだった。
特性を購読(subscribe)してみる
値をいきなり読み込むのはあきらめて、購読可能な fff2
と fff6
を購読してみることにする。
subscribe-0xfff0-characteristics.js
// (中略)
// 探査された購読可能な特性を購読して
// 通知が来たらつど出力
function onCharacteristicsDiscover (characteristics) {
console.log('Discover Characteristics:\n')
characteristics
.forEach(characteristic => {
// notify が許可されている場合
if (characteristic.properties.includes('notify')) {
// 通知を受信したら値を出力
characteristic.on('data', (data) => {
console.log(`(${characteristic.uuid}):`)
console.dir(data)
})
// 通知を購読
characteristic.subscribe((err) => {
if (err) throw err
console.log(`(${characteristic.uuid}): start subscribe`)
})
}
})
}
結果がこちら。
$ node subscribe-0xfff0-characteristics.js
stateChange: poweredOn
discover peripheral: 000FatScale01
disconnect: 000FatScale01
Discover Service: Device Information
Discover Characteristics:
(fff6): start subscribe
(fff1): start subscribe
(fff1):
Buffer [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
(fff1):
Buffer [ 0, 2, 216, 0, 172, 0, 0, 0, 0, 0, 0, 0, 0, 116, 170, 2, 216, 0, 172, 0 ]
(fff1):
Buffer [ 0, 0, 0, 0, 0, 0, 0, 116, 170, 2, 216, 0, 172, 0, 0, 0, 0, 0, 0, 0 ]
(fff1):
Buffer [ 0, 116, 170, 2, 216, 0, 172, 0, 0, 0, 0, 0, 0, 0, 0, 116, 170, 2, 216, 0 ]
(fff1):
Buffer [ 172, 0, 0, 0, 0, 0, 0, 0, 0, 116, 170, 2, 216, 0, 172, 0, 0, 0, 0, 0 ]
(fff1):
Buffer [ 0, 0, 0, 116, 170, 2, 216, 0, 172, 0, 0, 0, 0, 0, 0, 0, 0, 116, 170 ]
(fff1):
Buffer [ 2, 216, 0, 172, 0, 0, 0, 0, 0, 0, 0, 0, 116, 170 ]
(fff1):
Buffer [ 2, 216, 0, 172, 0, 0, 0, 0, 0, 0, 0, 0, 116, 170 ]
(fff1):
Buffer [ 2, 216, 0, 172, 0, 0, 0, 0, 0, 0, 0, 0, 116, 170 ]
(fff1):
Buffer [ 2, 216, 0, 172, 0, 0, 0, 0, 0, 0, 0, 0, 116, 170 ]
(fff1):
Buffer [ 2, 216, 0, 172, 0, 0, 0, 0, 0, 0, 0, 0, 116, 170 ]
(fff1):
Buffer [ 2, 216, 0, 172, 0, 0, 0, 0, 0, 0, 0, 0, 116, 170 ]
(fff1):
Buffer [ 2, 216, 0, 172, 0, 0, 0, 0, 0, 0, 0, 0, 116, 170 ]
(fff1):
Buffer [ 2, 216, 0, 172, 0, 0, 0, 0, 0, 0, 0, 0, 116, 170 ]
(fff1):
Buffer [ 2, 216, 0, 172, 0, 0, 0, 0, 0, 0, 0, 0, 116, 170 ]
(fff1):
Buffer [ 2, 216, 0, 172, 0, 0, 0, 0, 0, 0, 0, 0, 116, 170 ]
(fff1):
Buffer [ 2, 216, 0, 172, 0, 0, 0, 0, 0, 0, 0, 0, 116, 170 ]
(fff1):
Buffer [ 2, 216, 0, 172, 0, 0, 0, 0, 0, 0, 0, 0, 116, 170 ]
(fff1):
Buffer [ 2, 216, 0, 173, 0, 0, 0, 0, 0, 0, 0, 0, 117, 170 ]
(fff1):
Buffer [ 2, 216, 0, 172, 0, 0, 0, 0, 0, 0, 0, 0, 116, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 0, 0, 170 ]
おぉ、なんかズラズラとデータがでてきた!
ちなみに何回かやってみた結果、このような傾向があることがわかった。
# 体重計の液晶に表示されている数値が 17.2kg の場合(※計測は座りながら行っていた)
.
.
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
(fff1):
Buffer [ 2, 221, 0, 172, 0, 168, 230, 233, 1, 123, 20, 128, 56, 170 ]
.
.
# 体重計の数値が 10.8kg の場合
.
.
Buffer [ 2, 221, 0, 108, 0, 162, 230, 228, 1, 130, 21, 128, 7, 170 ]
(fff1):
Buffer [ 2, 221, 0, 108, 0, 162, 230, 228, 1, 130, 21, 128, 7, 170 ]
(fff1):
Buffer [ 2, 221, 0, 108, 0, 162, 230, 228, 1, 130, 21, 128, 7, 170 ]
.
.
# 体重計の数値が 18.1kg の場合
.
.
Buffer [ 2, 221, 0, 181, 0, 156, 230, 229, 1, 125, 24, 128, 19, 170 ]
(fff1):
Buffer [ 2, 221, 0, 181, 0, 156, 230, 229, 1, 125, 24, 128, 19, 170 ]
(fff1):
Buffer [ 2, 221, 0, 181, 0, 156, 230, 229, 1, 125, 24, 128, 19, 170 ]
(fff1):
Buffer [ 2, 221, 0, 181, 0, 156, 230, 229, 1, 125, 24, 128, 19, 170 ]
.
.
おわかりだろうか。
受信したデータの先頭から数えて3byte目(先頭は0byte目と数える)の値を10で割った数値がどうやら体重の値である可能性が高そうだ。
ちなみに1byteだと最大で255までの数値しか扱えない(この場合25.5kgまでしか扱えない)ので、おそらく2byte目と3byte目の合計16bitで体重の値を表しているのではないかと思われる。
その仮説を検討する為に、今まで横着して座って計測していたのをちゃんと立って計測してみることにした。1
# 体重計の数値が 93.6kg の場合の受信データ
.
.
(fff1):
Buffer [ 2, 221, 3, 168, 0, 213, 214, 222, 1, 168, 25, 128, 155, 170 ]
(fff1):
Buffer [ 2, 221, 3, 168, 0, 213, 214, 222, 1, 168, 25, 128, 155, 170 ]
(fff1):
Buffer [ 2, 221, 3, 168, 0, 213, 214, 222, 1, 168, 25, 128, 155, 170 ]
.
.
2byte目の数値が 3
、3byte目の数値が 168
である。これを16進数でつなげて表すと 0x03a8
となり、10進数だと 936
になる。これを10で割ると 93.6
だ。
どうやら、仮説は運良くあたっていたようである。
取得した体重データを REST API で Google Fit へ記録する
どうにかこうにか無事に Bluetooth 対応体重計「00FatScale01」と BLE で通信して体重のデータを取得することに成功した。
その1に続き長くなってしまったので、取得した体重を Goole Fit へ自動的に登録するのは次の記事にて。
関連記事
- 3000円の Bluetooth 対応体重計を Raspberry Pi を使って Google Fit に対応させてみた その1
- 3000円の Bluetooth 対応体重計を Raspberry Pi を使って Google Fit に対応させてみた その2
参考
-
なぜ体重管理が必要なのか立位でのデータをみてお分かりいただけたと思う ↩