FXC-5A

FXC-5Aという端末でMaBeeeに接続できない、という問い合わせがありました。Androidは全部の機種をサポートするわけではなく、お問い合わせいただいてもすべて対応できるわけではないのですが、できればなんとかしたい感じで、幸いこの端末は入手することができたので検証してみました。

画面は崩れなどなく、アニメーションも問題無さそうです。しかしスキャンしてもMaBeeeがリストに表示されませんでした。クルクルし続けます。ということでスキャンまわりから追いかけることにしました。

startLeScan

MaBeee AndroidアプリではBLEのスキャンは、startLeScanという関数で開始しています。
startLeScan(LeScanCallback)
startLeScan(UUID[], LeScanCallback)

ソースを追うと、UUID[]の引数がない上の関数は、UUID[]をnullとして下の関数を呼び出しています。ようするにスキャンにヒットしたデバイスのサービスUUIDが、引数のサービスUUID[]にマッチする場合、コールバックを呼ぶ。上の関数か下の関数でUUID[]がnullの場合はヒットしたデバイスすべてについてコールバックを呼ぶ、という仕様ですね。

お、サービス?サービスUUID?って何よ

このあたりBLEの説明になってくわしくはBLE・サービスあたりでググるべきかもしれません。すごく簡単に説明すると、MaBeeeなどのデバイスが持つ機能、例えば電池残量を取得するとか、そういう機能をいくつかまとめたものがサービスです。その名前的なものがサービスUUIDって感じです。電源を入れたデバイスは、アドバタイズパケットという電波信号っていうの?パケット?を送信して、Androidはスキャンでそいつを捕まえます。そのアドバタイズパケットには、サービスUUIDを含めることができます。ということで、MaBeeeのアプリでは、スキャンしてヒットしたデバイスのアドバタイズパケットから、MaBeeeのサービスUUIDを持っているものをリストにして表示している、という感じです。んー説明下手ですね。

onLeScan

スキャンした結果が返ってくるコールバック関数がonLeScanです。
onLeScan(BluetoothDevice, int, byte[])

BluetoothDeviceがなんかデバイスのオブジェクト、intが受信感度?電波強度?のRSSI、byte[]がscanRecordでアドバタイズパケットの中身、サービスUUIDとかが入っているデータになっています。で、BluetoothDeviceの名前とアドレスと、scanRecordをログ出力するような関数をonLeScanに入れました。まあこの場合その関数はどうでもいいと思うんですが、出力だけっていうのもあれなので。


private void printOnLeScanArgs(BluetoothDevice device, int rssi, byte[] scanRecord) {
    String message = device.getAddress() + "\n" + device.getName() + "\n";
    String str = "";
    for (int i = 0; i < scanRecord.length; i++) {
        if (0 < i && 0 == i % 8) {
            message += " " + str + "\n";
            str = "";
        }
        byte c = scanRecord[i];
        message += String.format("%02x ", c);
        if (0x20 <= c && c <= 0x7e) {
            str += String.format("%c", c);
        } else {
          str += " ";
        }
    }
    Log.d("onLeScan", message);
}

ログ取得

startLeScanをUUID[]なしで呼び出すようにしてログをとりました。onLeScanでフィルタして時間とかはちょっと削除してます。動作を確認しているNexus 5と比較することにしました。

FXC-5A

D/onLeScan: E3:70:EA:FC:53:7D
            MaBeee000003
            0d 09 4d 61 42 65 65 65    MaBeee
            30 30 30 30 30 00 00 00  00000
            00 00 00 00 00 00 00 00
            00 00 00 00 00 00 00 00
            00 00 00 00 00 00 00 00
            00 00 00 00 00 00 00 00
            00 00 00 00 00 00 00 00
            00 00 00 00 00 00

D/onLeScan: D0:10:A7:71:E4:DF
            MaBeee000002
            02 01 00 00 00 00 00 00
            00 00 00 00 00 00 00 00
            00 00 00 00 00 00 00 00
            00 00 00 00 00 00 00 00
            00 00 00 00 00 00 00 00
            00 00 00 00 00 00 00 00
            00 00 00 00 00 00 00 00
            00 00 00 00 00 00
Nexus 5

D/onLeScan: E3:70:EA:FC:53:7D
            MaBeee000003
            02 01 06 11 07 d9 74 2c        t,
            ee 53 b4 61 8b c6 46 13   S a  F
            d8 00 ff f5 b9 0d 09 4d         M
            61 42 65 65 65 30 30 30  aBeee000
            30 30 33 00 00 00 00 00  003
            00 00 00 00 00 00 00 00
            00 00 00 00 00 00 00 00
            00 00 00 00 00 00

D/onLeScan: D0:10:A7:71:E4:DF
            MaBeee000002
            02 01 06 11 07 d9 74 2c        t,
            ee 53 b4 61 8b c6 46 13   S a  F
            d8 00 ff f5 b9 0d 09 4d         M
            61 42 65 65 65 30 30 30  aBeee000
            30 30 32 00 00 00 00 00  002
            00 00 00 00 00 00 00 00
            00 00 00 00 00 00 00 00
            00 00 00 00 00 00

結果

まあ見ただけでダメっぽい感じに見えますね、、、

アドバタイズパケットのフォーマットについては、これまたググッてという感じですが、ええと1バイトがそれに続く内容の長さで、内容の先頭1バイトがタグで以降が本当の内容です。わからないですね。最後のログを分解します。


02                             長さ
   01                          タグ
      06                       内容

11                             長さ
   07                          タグ
      d9 74 2c                 内容
      ee 53 b4 61 8b c6 46 13
      d8 00 ff f5 b9

0d                             長さ
   09                          タグ
      4d                       内容
      61 42 65 65 65 30 30 30
      30 30 32

要するに長さが最初にあって、次にタグ、次に内容って感じです。タグは07がサービスUUID、09が名前です。

FXC-5Aは、名前が表示できているのでアドバタイズパケットはちゃんと取得できてるはずなのですが、scanRecordにその値が入ってきてないです。途中まで入ってきているような感じにも見えます。Nexus 5はどちらもちゃんと入っているようです。同じサービスUUIDがありますね。

結論として、この方法で他の端末が問題なくスキャンできていることを考えると、FXC-5AはMaBeeeの使用が現状では難しいという判断になりました。これからPlayストアの対象端末から外す作業をします。画面とかはとても良い感じに見えるのでなんかもったいないっていう感じがします。

なお、scanRecordをどこかで壊している?スレッドかなにか設定する?とか、アドバタイズのなにかを変更する?とか僕の知らない部分で修正できる可能性はあります。なにか考えられること、回避策、あるいは間違いなどありましたら教えてもらえると嬉しいです。

Pocket