2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

CoreBluetoothでBLEセンサーの情報を取得する

Last updated at Posted at 2021-09-04

iOSのCore Bluetooth APIを使ってBLE温湿度センサーから情報を読み取るメモです。BLEセンサーはSANWA SUPPLYのMM-BLEBC7を使用しました。

Core Bluetoothとは

Core BluetoothはAppleの公式フレームワークで、iOSにランタイムが内臓されているので外付けのライブラリーは不要です。importするだけで使うことができます。

swift
import CoreBluetooth

Core Bluetoothの使用方法

Core Bluetooth APIはBEL機器をペリフェラルとして定義していて、ペリフェラルの中に複数のサービス、サービスの中に複数のキャラクタリスティックとう具合に階層化されています。そのため、BLE機器からデータを取得するためには、それぞれの階層を順番に辿って、目的のデータを見つける必要があります。

手順例

  1. ペリフェラルの検出
  2. ペリフェラルへ接続
  3. サービスのディスカバー
  4. キャラクタリスティックの取得
  5. データ取得

なのですが、MM-BLEBC7ではすべてのサービス、すべてのキャラクタリスティックを探しても、温度や湿度のデータが見つかりませんでした。はたと、ペリフェラルの検出時のアドバイス情報をダンプしたところ、Dictionaryの「kCBAdvDataServiceData」の中に入っていました。今回の場合、温湿度データの取得は上の手順の1だけで良いことになります。

["kCBAdvDataServiceData": {FFE1 = {length = 13, bytes = 0xa1010e183d4d191xxxxxxxxxxxx};}]

先頭の0xa101は固定で、その後に電池残量、温度、湿度を示します。
xxxxxxxxxxxxのところはMACアドレスが入っています。(リトルエンディアン)

サンプルコード

swift
import UIKit
import CoreBluetooth

class ViewController: UIViewController {
    var centralManager: CBCentralManager!
    var peripheral: CBPeripheral!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // セントラルマネージャの生成
        self.centralManager = CBCentralManager(delegate: self, queue: nil, options: nil)
    }
}

extension ViewController: CBCentralManagerDelegate {
    // Bluetoothの状態
    func centralManagerDidUpdateState(_ central: CBCentralManager) {
        switch central.state {
        case CBManagerState.poweredOn:
            print("poweredOn")

            // スキャン開始
            self.centralManager.scanForPeripherals(withServices: nil, options: nil)
        
        case CBManagerState.poweredOff:
            print("poweredOff")
        
        default:
            break
        }
    }

    // ペリフェラルの検出
    func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String: Any], rssi RSSI: NSNumber) {
        if (peripheral.name == nil || peripheral.name == "nRF5x") {
            print("advertisementData:", advertisementData)
            if let dic = advertisementData["kCBAdvDataServiceData"] as? Dictionary<CBUUID, Data> {
                if let data = dic[CBUUID(string:"FFE1")] {
                    print("data:", data.map({ String(format:"%02x ", $0) }).joined())
                    
                    if (data.count == 13) {
                        let frameType = data[0] // 0xA1固定
                        let productMode = data[1] // 0x01固定
                        let batteryLevel = data[2] // 電池残量(100%)
                        let temperature = Float(data[3]) + Float(data[4]) / 256 // 温度:固定小数点(1バイト目:整数部、2バイト目:少数部)
                        let humidity = Float(data[5]) + Float(data[6]) / 256 // 湿度:固定小数点(1バイト目:整数部、2バイト目:少数部)
                        let macAddress = data[7...12].reversed()// MACアドレス(リトルエンディアン)

                        print("frameType:", String(format: "%02x", frameType))
                        print("productMode:", String(format: "%02x", productMode))
                        print("batteryLevel:", batteryLevel)
                        print("temperature:", temperature)
                        print("humidity:", humidity)
                        print("macAddress:", macAddress.map({ String(format:"%02x ", $0) }).joined())
                        
                        //スキャン停止
                        self.centralManager.stopScan()
                    }
                }
            }
        }
    }
}

参考

[翻訳] 初めてのCore Bluetooth

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?