AndroidアプリのBLE実装 2 (Central)
こんにちは、アプリケーションエンジニアの難波です。
BraveridgeではIoTデバイスを製作する時によくNordic社のSoCを使用しています。
そのNordic社はAndroid用のBLEライブラリをOSSとしてリリースしています。
AndroidアプリでBLE機能を実装しようとすると、OSのバージョンや機種依存、ハマりやすいポイント等があったりと結構クセが強いです。
NordicのAndroid用BLEライブラリはその辺りを良い感じに吸収してくれています。
今回は Android-BLE-Library のCentralに関連する機能を実装例と共に紹介します。
Centralを実装する時に BLEデバイスのスキャン と BLEデバイスに接続して制御 という2機能を実装する必要があります。
このライブラリは BLEデバイスへの接続と制御 を担当します。
※Android-BLE-LibraryはCentralだけでなくPeripheralを実装する場合にも利用することができます。
1. BleManager を継承したclassを実装します。
このclassでBLEデバイスへの接続・切断とcharacteristicのread、write、notifyのcallbackを実装します。
まず BleManagerGattCallback を実装します。(SampleBleManagerGattCallbackクラス)
BLE接続が完了すると isRequiredServiceSupported(gatt) がコールされます。
この時点で接続したPeripheralのServiceリストを取得しているので、discoveredServicesHandler でViewModelやActivityなど呼び出し側に伝えます。
次に getGattCallback() を実装します。
このメソッドは親クラスのコンストラクタでコールされるので、SampleBleManagerクラス のコンストラクタよりも先に getGattCallback() が呼ばれます。
そのため gattCallbackプロパティ をnullチェックして、初回コール時のみ SampleBleManagerGattCallbackクラス をインスタンス化しています。
BleManagerクラス では以下の機能が実装されているので、SampleBleManagerクラス で簡単に利用する事ができます。
こういった機能はとてもありがたいです。
サンプルアプリを含めたソースコード全体は github で確認できます。
BraveridgeではIoTデバイスを製作する時によくNordic社のSoCを使用しています。
そのNordic社はAndroid用のBLEライブラリをOSSとしてリリースしています。
AndroidアプリでBLE機能を実装しようとすると、OSのバージョンや機種依存、ハマりやすいポイント等があったりと結構クセが強いです。
NordicのAndroid用BLEライブラリはその辺りを良い感じに吸収してくれています。
今回は Android-BLE-Library のCentralに関連する機能を実装例と共に紹介します。
Centralを実装する時に BLEデバイスのスキャン と BLEデバイスに接続して制御 という2機能を実装する必要があります。
このライブラリは BLEデバイスへの接続と制御 を担当します。
※Android-BLE-LibraryはCentralだけでなくPeripheralを実装する場合にも利用することができます。
1. BleManager を継承したclassを実装します。
このclassでBLEデバイスへの接続・切断とcharacteristicのread、write、notifyのcallbackを実装します。
class SampleBleManager(context: Context) : BleManager(context) { var discoveredServicesHandler: ((List ) -> Unit)? = null private var gattCallback: BleManagerGattCallback? = null
private inner class SampleBleManagerGattCallback: BleManagerGattCallback() {
// Peripheral接続後にコールされる public override fun isRequiredServiceSupported(gatt: BluetoothGatt):Boolean { discoveredServicesHandler?.apply { this(gatt.services) } return true } override fun onDeviceDisconnected() {} } // 親クラスのコンストラクタでコールされる override fun getGattCallback() = gattCallback ?: run { gattCallback = SampleBleManagerGattCallback() gattCallback!! }
}
まず BleManagerGattCallback を実装します。(SampleBleManagerGattCallbackクラス)
BLE接続が完了すると isRequiredServiceSupported(gatt) がコールされます。
この時点で接続したPeripheralのServiceリストを取得しているので、discoveredServicesHandler でViewModelやActivityなど呼び出し側に伝えます。
次に getGattCallback() を実装します。
このメソッドは親クラスのコンストラクタでコールされるので、SampleBleManagerクラス のコンストラクタよりも先に getGattCallback() が呼ばれます。
そのため gattCallbackプロパティ をnullチェックして、初回コール時のみ SampleBleManagerGattCallbackクラス をインスタンス化しています。
val connectionObserver = object: BaseConnectionObserver {}実装した SampleBleManagerクラス をインスタンス化してPeripheralに接続します。
// ↑ BaseConnectionObserver は ConnectionObserver の各メソッドをデフォルト実装したインターフェース
val bleManager: SampleBleManager by lazy { val manager = SampleBleManager(app)
manager.setConnectionObserver(connectionObserver) manager.discoveredServicesHandler = { services ->
services.forEach { Log.d(TAG, it.uuid.toString()) }
} manager }
// Peripheralに接続する val bluetoothDevice: BluetoothDevice // BLEスキャンで取得したBluetoothDeviceインスタンス bleManager.connect(bluetoothDevice).enqueue()
// Peripheralとの接続を切断する
bleManager.disconnect().enqueue()
BleManagerクラス では以下の機能が実装されているので、SampleBleManagerクラス で簡単に利用する事ができます。
- RSSIの取得
- characteristicの操作(read、write、notifyのcallback)
- MTUの変更
- ボンディング(ペアリング)
よくある実装ミスとして、Peripheralへ上記操作を複数同時並行にリクエストしてしまい、Peripheral側がいくつかのリクエストをスルーしてしまう事があります。
BleManagerクラス では内部にリクエストキューを実装しているので、必ずシーケンシャルに実行してくれます。こういった機能はとてもありがたいです。
サンプルアプリを含めたソースコード全体は github で確認できます。
AndroidアプリのBLE実装 3 (Peripheral)
こんにちは、アプリケーションエンジニアの難波です。
BraveridgeではIoTデバイスを製作する時によくNordic社のSoCを使用しています。
そのNordic社はAndroid用のBLEライブラリをOSSとしてリリースしています。
AndroidアプリでBLE機能を実装しようとすると、OSのバージョンや機種依存、ハマりやすいポイント等があったりと結構クセが強いです。
NordicのAndroid用BLEライブラリはその辺りを良い感じに吸収してくれています。
今回は Android-BLE-Library のPeripheralに関連する機能を実装例と共に紹介します。
Centralの場合と比べて少し複雑になります。
まず BleServerManager を継承したclassを実装します。
このclassでPeripheralのProfileを定義します。
上の例ではread用のcharacteristicを含むserviceを定義しています。
Advertiseは Android-BLE-Library の範囲外なので自分で実装する必要があります。
最後に BleServerManager に接続された時に BleManager を関連づけます。
SampleBleServerManager#open() をコールすると SampleBleServerManager#initializeServer() が実行され、Peripheralとしての動作準備を行います。
動作準備が完了すると SampleBleServerManager#onServerReady() がコールされるので、Advertiseを開始してPeripheralとして動作します。
Peripheralを実装するには接続したCentralのBluetoothDeviceインスタンスを管理する必要がありますが、BleServerManager を利用するとその必要もありません。
またCentralとのコミュニケーションを BleManager が行うので、リクエスト・レスポンスのキューを実装する必要がありません。
AndroidのBLE処理をきちんと実装するとコード量が多くなりがちですが、Android-BLE-Libraryを利用すると結構コンパクトに実装できます。
サンプルアプリを含めたソースコード全体は github で確認できます。
BraveridgeではIoTデバイスを製作する時によくNordic社のSoCを使用しています。
そのNordic社はAndroid用のBLEライブラリをOSSとしてリリースしています。
AndroidアプリでBLE機能を実装しようとすると、OSのバージョンや機種依存、ハマりやすいポイント等があったりと結構クセが強いです。
NordicのAndroid用BLEライブラリはその辺りを良い感じに吸収してくれています。
今回は Android-BLE-Library のPeripheralに関連する機能を実装例と共に紹介します。
Centralの場合と比べて少し複雑になります。
まず BleServerManager を継承したclassを実装します。
このclassでPeripheralのProfileを定義します。
class SampleBleServerManager(private val context: Context)initializeServer() の戻り値がBLE接続時にCentralが取得するServiceリストになります。
: BleServerManager(context) {
val characteristicForRead = characteristic(
UUID.randomUUID(),
BluetoothGattCharacteristic.PROPERTY_READ,
BluetoothGattCharacteristic.PERMISSION_READ
).apply {
value = byteArrayOf(0x1)
}
private val serviceUUID = UUID.randomUUID()
override fun initializeServer() = listOf(service(serviceUUID, characteristicForRead))
}
上の例ではread用のcharacteristicを含むserviceを定義しています。
Advertiseは Android-BLE-Library の範囲外なので自分で実装する必要があります。
class SampleBleServerManager(private val context: Context) : BleServerManager(context) {次にCentralとの接続から切断までを制御するために BleManager を継承したclassを実装します。BleManager はCentralの実装時にも登場しましたが、Peripheralを実装するときも使用します。
// 追加
fun startAdvertising() {
val adviserSettings = AdvertiseSettings.Builder() .build()
val advertiseData = AdvertiseData.Builder()
.addServiceUuid(ParcelUuid(serviceUuid))
.build()
val advertiseCallback = object : AdvertiseCallback() {}
// Advertise開始 BluetoothAdapter.getDefaultAdapter().bluetoothLeAdvertiser
?.startAdvertising(adviserSettings, advertiseData, advertiseCallback)
}
}
class SampleConnectedBleManager(context: Context) : BleManager(context) { private var gattCallback: BleManagerGattCallback? = null private inner class GattCallback : BleManagerGattCallback() { override fun isRequiredServiceSupported(gatt: BluetoothGatt) = true override fun onDeviceDisconnected() {} } override fun getGattCallback() = gattCallback ?: run { gattCallback = GattCallback() gattCallback!! } }
最後に BleServerManager に接続された時に BleManager を関連づけます。
class SampleBleServerManager(private val context: Context) : BleServerManager(context) {
private val connectionObserver = object: BaseConnectionObserver {}
private val serverObserver = object: ServerObserver { override fun onServerReady() {
// advertise開始 startAdvertising() }
override fun onDeviceConnectedToServer(device: BluetoothDevice) {
// BleServerManager と BleManager を関連づける
val connectedManager = SampleConnectedBleManager(context) connectedManager. setConnectionObserver(connectionObserver)
connectedManager.useServer(this) connectedManager .connect(device) .enqueue() } override fun onDeviceDisconnectedFromServer(device: BluetoothDevice) {} }
init { setServerObserver(serverObserver) } }
SampleBleServerManager#open() をコールすると SampleBleServerManager#initializeServer() が実行され、Peripheralとしての動作準備を行います。
動作準備が完了すると SampleBleServerManager#onServerReady() がコールされるので、Advertiseを開始してPeripheralとして動作します。
val bleServerManager = SampleBleServerManager(context) bleServerManager.open()
Peripheralを実装するには接続したCentralのBluetoothDeviceインスタンスを管理する必要がありますが、BleServerManager を利用するとその必要もありません。
またCentralとのコミュニケーションを BleManager が行うので、リクエスト・レスポンスのキューを実装する必要がありません。
AndroidのBLE処理をきちんと実装するとコード量が多くなりがちですが、Android-BLE-Libraryを利用すると結構コンパクトに実装できます。
サンプルアプリを含めたソースコード全体は github で確認できます。
AndroidアプリのBLE実装 1 (Scanner)
こんにちは、アプリケーションエンジニアの難波です。
BraveridgeではIoTデバイスを製作する時によくNordic社のSoCを使用しています。
そのNordic社はAndroid用のBLEライブラリをOSSとしてリリースしています。
AndroidアプリでBLE機能を実装しようとすると、OSのバージョンや機種依存、ハマりやすいポイント等があったりと結構クセが強いです。
NordicのAndroid用BLEライブラリはその辺りを良い感じに吸収してくれています。
今回は Android-Scanner-Compat-Library を実装例と共に紹介します。
Centralを実装する時に BLEデバイスのスキャン と BLEデバイスに接続して制御 という2機能を実装する必要があります。
このライブラリは BLEデバイスのスキャン を担当します。
使用方法は簡単というか、単に BluetoothLeScannerクラス を BluetoothLeScannerCompatクラス に置き換えれば使用できます。
一番簡単な使用例:
少しコード量が減るくらいです。
なお、バックグラウンドでも(アプリがkillされても)BLEスキャンを動作させたい場合、READMEにあるように BroadcastReceiver を実装して startScan() と stopScan() をコールする時に PendingIntent を渡せばOKです。とても簡単ですね。
サンプルアプリを含めたソースコード全体は github で確認できます。
BraveridgeではIoTデバイスを製作する時によくNordic社のSoCを使用しています。
そのNordic社はAndroid用のBLEライブラリをOSSとしてリリースしています。
AndroidアプリでBLE機能を実装しようとすると、OSのバージョンや機種依存、ハマりやすいポイント等があったりと結構クセが強いです。
NordicのAndroid用BLEライブラリはその辺りを良い感じに吸収してくれています。
今回は Android-Scanner-Compat-Library を実装例と共に紹介します。
Centralを実装する時に BLEデバイスのスキャン と BLEデバイスに接続して制御 という2機能を実装する必要があります。
このライブラリは BLEデバイスのスキャン を担当します。
使用方法は簡単というか、単に BluetoothLeScannerクラス を BluetoothLeScannerCompatクラス に置き換えれば使用できます。
一番簡単な使用例:
val scanCallBack = object : ScanCallback() { override fun onScanResult(callbackType: Int, result: ScanResult) { Log.d("TAG", result.device.toString()) } override fun onBatchScanResults(results: List<ScanResult>) { results.forEach { Log.d("TAG", it.device.toString()) } } } // スキャン開始 BluetoothLeScannerCompat.getScanner().startScan(scanCallBack) // スキャン停止 BluetoothLeScannerCompat.getScanner().stopScan(scanCallback)この BluetoothLeScannerCompatクラス を使用するだけで以下のメリットがあります。
- 古いバージョンのOS(7以下)でも可能な限り同じ動作をしてくれる
- バックグラウンドでも良い感じに動作してくれる
- Android 8以上
- フォアグランドのみ使用
少しコード量が減るくらいです。
なお、バックグラウンドでも(アプリがkillされても)BLEスキャンを動作させたい場合、READMEにあるように BroadcastReceiver を実装して startScan() と stopScan() をコールする時に PendingIntent を渡せばOKです。とても簡単ですね。
サンプルアプリを含めたソースコード全体は github で確認できます。
糸島工場IoT推進委員会 - 勤怠システム
こんにちは、アプリケーションエンジニアの難波です。
Braveridgeでは2019年4月に糸島工場IoT推進委員会を立ち上げ、スマートファクトリー化を進めています。
第5弾として勤怠システムを構築しました。
糸島工場では約50人のパートの方が働いていますが、勤怠の記録を紙に記載する方式をとっています。そのため、毎月、総務が全員分の勤怠データを手入力して給与計算しています。
そこで、ボタン型ビーコンを活用して業務改善を図りました。
NFCカードを利用した勤怠システムがありますが、NFCだとリーダーにカードをかざす必要があり、50人が一斉に出勤すると行列を作ってしまいます。ですがビーコンだと複数人同時に勤怠を記録することができ、並ぶ必要がありません。
自社製品のボタン式ビーコン pochiruをパートさん全員に配り、出勤時と退勤時にボタンを押してもらって勤怠の記録を付けてもらうようにしました。
以下、システム概要図です。
ボタンが押されたタイミングで勤怠時間をDBに格納するので、総務がデータ入力せずに給与計算時の勤務時間の算出ができるようになりました。
あとは、給与ソフトに勤務時間データをインポートすれば給与計算は完了です。
Web画面では今日の勤怠一覧を確認できます。
誰が出勤しているのか、またお休みなのかをすぐ把握できます。
パートの方から年間の勤務時間を確認したいという希望があったので、マイページを提供することにしました。マイページといえばパスワードによるログインが一般的ですが、利便性があまり良くないので他の方式を考えました。
ほとんどの方がLINEを使用しているようなので、勤務時間を確認できるLINE botを作成することにしました。糸島工場LINE botと友達になると、メニューボタンを押すだけで勤務時間を確認できます。
糸島市実証実験 - 河川の水位検知
こんにちは、アプリケーションエンジニアの難波です。
Braveridgeが携わっている糸島市の実証実験について紹介します。
10/4に糸島市の河川に水位検知センサーを設置しました。
今回センサーを設置した地域は周辺に田畑が多く、稲穂が頭を垂れていました。そろそろ稲刈りの時期です。
この地域では激しく雨が降った時は川から水が氾濫することもあり、周辺の田畑が水害にあうこともあるそうです。そのため、糸島市としては川が氾濫する前に状況を把握する必要があり、今回の水位検知センサーを設置することになりました。
防水された水位検知センサーを川の横の壁に設置します。
糸島市に許可を得て、弊社の手嶋がドリルでボルト用の穴を空けます。
写真中央の白いボックスが水位検知センサーです。
今回はテスト設置なので、雨量が少し多い時に水位検知センサーが反応するように、低めに設置しました。
今回はテスト設置なので、雨量が少し多い時に水位検知センサーが反応するように、低めに設置しました。
水位が上がると、水位検知センサーの端子が通電してIFCsに検知情報を送信します。そして、IFCsから水位警報システムに検知情報が転送され、あらかじめ設定されたメールアドレスやLINEへ通知されます。
糸島市の担当者はリアルタイムに河川が警戒水位になったか知ることができます。
今年度は全部で6箇所設置予定です。
少しでも防災に貢献できればと思います。
糸島工場IoT推進委員会 - 糸島工場の棚卸
こんにちは、アプリケーションエンジニアの難波です。
Braveridgeでは2019年4月に糸島工場IoT推進委員会を立ち上げ、スマートファクトリー化を進めています。
第四弾として棚卸サポートシステムを構築しました。
※今回はIoTではなくITの話です
Braveridgeの糸島工場では、半期に一度のペースで倉庫内の部材の棚卸をしています。
(部材点数は約2000点!)
(部材点数は約2000点!)
これまでの棚卸は次のように行なっていました。
1. パートさんが部材を数える
2. カーボンコピーの用紙に品目名と数を記入する
3. 一枚は部材が入った箱に添付し、もう一枚を社員に渡す
※箱に用紙を添付するのは棚卸済みのマーキングのため
4. 後日、社員が記入された用紙を見ながらデータ入力する
4のデータ入力が問題になっていて、社員総出で休日出勤してデータ入力していたようです。。。
そこで棚卸を効率化するために棚卸サポートシステムを構築しました。
既存の在庫管理システムとは、CSVファイルのインポート・エクスポートで連携します。
パートさんが棚卸をした時に、棚卸アプリ(iOS)で対象品目を検索して棚卸数を入力します。
完了ボタンを押すと、モバイルプリンタから品目名と数が印刷され、同時にサーバにデータ登録します。
モバイルプリンタはスター精密のSM-L200を使用しました。Bluetooth接続のプリンタを使用するのは初めてでしたが、StarPRNT SDKがとても使いやすくすぐに実装できました。
スター精密のプリンタ、オススメです。
始めは棚卸アプリの操作に戸惑っていましたが、すぐに慣れて問題なく操作できていました。
今回のシステム開発では、倉庫で数回、β版アプリを試してもらい、現場に意見を出してもらいながら改善しました。おかげで大きなトラブルもなく棚卸が完了できました。
やはり現場は大事です。
棚卸のIoT化といえばRFIDタグや重量センサーを用いたものがありますが、このような簡易的なサポートシステムでも棚卸コストを軽減することができます。
糸島工場IoT推進委員会 - 生産表示板システム
こんにちは、アプリケーションエンジニアの難波です。
Braveridgeでは2019年4月に糸島工場IoT推進委員会を立ち上げ、スマートファクトリー化を進めています。
Braveridgeでは2019年4月に糸島工場IoT推進委員会を立ち上げ、スマートファクトリー化を進めています。
第三弾として生産表示板システムを構築しました。
弊社工場では毎日生産するものが変わる事もあり、組み立て作業自体を自動化するのは難しいです。
そのため、生産進捗を管理するために生産表示板を使用しています。
そのため、生産進捗を管理するために生産表示板を使用しています。
組み立てが完了するたびにボタンを押してカウントアップします。
これまでは、この生産表示板は生産現場(2F)でしか確認できませんでした。
そこで遠隔地でも生産進捗を可視化するシステムを構築しました。
そこで遠隔地でも生産進捗を可視化するシステムを構築しました。
システム概要図はこうなります。
IFCsは弊社IoTプラットフォームになります。
各生産ラインの進捗は以下の画面で確認できます。
工場長からのリクエストで「進度」で生産進捗を表しています。
工場長からのリクエストで「進度」で生産進捗を表しています。
生産ラインがある2階では大型ディスプレイに表示しています。
各生産ラインの進度をリアルタイムで把握できるので、人員配置の調整がジャストインタイムで行えるようになりました。
糸島工場IoT推進委員会 - 社員呼び出しシステム
こんにちは、アプリケーションエンジニアの難波です。
Braveridgeでは2019年4月に糸島工場IoT推進委員会を立ち上げ、スマートファクトリー化を進めています。
Braveridgeでは2019年4月に糸島工場IoT推進委員会を立ち上げ、スマートファクトリー化を進めています。
第二弾として生産ラインでの社員呼び出しシステムを構築しました。
弊社では入社後2週間は工場研修があり、生産ラインで組み立て工程などを担当します。
私も工場研修を受けたのですが、その時の経験をもとに社員呼び出しシステムを構築しました。
工場の生産ラインで組み立て作業を行っている時に、治具が不調になったり部材が足りなくなるなど問題が発生することがあります。生産ラインで問題が発生すると作業がストップしてしまい、作業時間の損失が発生します。
こういう場合はしかるべき担当者を呼んで対応してもらう必要がありますが、すぐに見つからず探す事もありました。
そこで自社製品のPochiruを使用して社員呼び出しシステムを構築しました。
Pochiruを3個使って、それぞれに治具不良・部品不足・その他/緊急と役割を設定しています。
システム概要図はこうなります。
IFCは弊社IoTプラットフォームになります。
例えば治具不良ボタンを押すと、工場社員が参加しているLINEグループにメッセージが送信されます。
ボタン付きメッセージにしているので、対応する人がすぐ返事できるようにしています。
ボタン付きメッセージにしているので、対応する人がすぐ返事できるようにしています。
集計画面でどの生産ラインでどのボタンがよく押されているのか把握することができ、次の改善に活かせます。
今後の機能拡充予定として、LINEメッセージの「対応する」ボタンが押されたら、ダウンリンクでもうすぐ担当者が来ることを呼び出した方にお知らせできるようにすることを計画しています。