LoginSignup
1
0

More than 1 year has passed since last update.

[SwiftUI + CoreBluetooth]感染症対策・熱中症対策に iPhone や MacBook Air(M1)で温度・湿度を測定する

Last updated at Posted at 2022-12-23

記事の内容

ソニーが販売している IoT タグ MESH を利用して、温度・湿度を測定する。
スクリーンショット 2022-12-20 0.10.25.png

動機

感染症対策・熱中症対策として、部屋の温度・湿度を測定したい

「感染症対策・熱中症対策には温度と湿度の管理が大切」 ということはわかっていたが、実際の温度・湿度は把握していなかった。

単純に温度計・湿度計を購入して測定すればいいが、自動的に一定間隔で測定データを記録して、そのデータを可視化したり機械学習で活用できるのではないか。

また以前、BLE通信を利用してセンサと接続できる iOS アプリを開発するプロジェクトに参画していた。その際の内容を思い出すためにも、温度・湿度を測定できる iOS アプリの開発に挑戦した。

開発環境

PC
MacBook Air(2020,M1) メモリ:16GB ストレージ:1TB

言語
Swift

フレームワーク
SwiftUI

MESH
温度・湿度ブロック

  • 測定できる温度の範囲: -10℃ 〜 50℃
  • 測定できる湿度の範囲: 0% 〜 100%
  • 充電: Micro-USB

アプリの要件

  • MESH 温度・湿度ブロック 1台と MacBook Air を BLE 通信を利用して接続する
  • MESH 温度・湿度ブロックは接続後、0.5秒ごとに温度・湿度の測定データを PC に送信する
  • iOS アプリで現在の温度と湿度を確認する
  • 今回は MacBook Air をセントラル MESH 温度・湿度ブロックをペリフェラル とする(※セントラル・ペリフェルについては後述)

BLE 通信

BLEとは

  • 近距離無線通信の規格 Bluetooth を省電力化した通信形式
  • PC、スマートフォンなど通信の親機に相当する機器のことを セントラル と呼ぶ
  • MESH や忘れ物防止タグなど通信の子機に相当する機器のことを ペリフェラル と呼ぶ

BLE通信の流れ

※ 説明をわかりやすくするため、簡略化しています

  1. ペリフェラルが通信待ちの状態では、周囲の不特定多数の機器を対象に無線信号を送信(アドバタイズ
  2. セントラルがスキャンを実行することで、アドバタイズを受信
  3. セントラルが1対1で通信したいペリフェラルに対して、接続を要求
  4. ペリフェラルがセントラルからの接続要求を受信し、1対1の通信(GATT通信)に切り替える
  5. ペリフェラルからセントラルへ通信データを送信する ※
  6. セントラルがペリフェラルに対して、切断を要求

※ GATT 通信の特徴
サービスキャラクタリスティック の形で測定データをやり取りする

コード

ポイント

CoreBluetooth を利用する

つまづいたところ

センサと接続が完了した際に、ペリフェラルのデリゲートを設定する

  • peripheral.delegate = self を記載が必要であることを気づかず、時間を浪費した
DeviceManager.swift
  func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        guard let peripheral = devices.first?.peripheral else { return }
        peripheral.delegate = self
        peripheral.discoverServices(services)
        print("centralManager did connect peripheral: \(peripheral.name?.description ?? "unnnamed")")
    }

ペリフェラルにブロック機能の有効化・温度や湿度、測定頻度の設定コマンドを送信する

  • 必要な知識: リトルエンディアン・16進数の足し算(チェックサムの値を算出するために必要)
  • 16進数の足し算: MacBook Air にプリインストールされている 「計算機」 アプリで対応
DeviceManager.swift
    func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
        let byteArray: [UInt8] = [0x00, 0x02, 0x01, 0x03]
        let data = Data(byteArray)
        let batteryLevelArray: [UInt8] = [0x00,0x03,0x00,0x03]
        let batteryLevelData = Data(batteryLevelArray)
        
        let modeSettingArray: [UInt8] = [0x01,0x00,0x01,0xF4,0x01,0xFF,0x9C,0x64,0x00,0x00,0x00,0x11,0x11,0x20,0x38]
        let modeSettingData = Data(modeSettingArray)
        
        guard let characteristics = service.characteristics else { return }
        
        for characteristic in characteristics {
            peripheral.setNotifyValue(true, for: characteristic)
            peripheral.writeValue(data, for: characteristic, type: .withResponse)
            peripheral.writeValue(data, for: characteristic, type: .withoutResponse)
        }
        print("did Discover Characteristics for executed")
        
        for characteristic in characteristics {
            peripheral.setNotifyValue(true, for: characteristic)
            peripheral.writeValue(batteryLevelData, for: characteristic, type: .withResponse)
            peripheral.writeValue(batteryLevelData, for: characteristic, type: .withoutResponse)
        }
        
        for characteristic in characteristics {
            peripheral.setNotifyValue(true, for: characteristic)
            peripheral.writeValue(modeSettingData, for: characteristic, type: .withResponse)
            peripheral.writeValue(modeSettingData, for: characteristic, type: .withoutResponse)
        }
        
    }

実際にアプリを動かす

iPhone SE (2nd Generation) を使って、MESH センサと接続する様子を収録した。

1日中動かすと、室内の湿度が1日で10〜20%前後変動することがわかった。特に、朝は感染症のリスクが高くなる湿度40%以下になる傾向があるため、部屋で洗濯物を干す・湯を沸かす等の対策が取れた。

(部屋のサイズや人数にもよるが、もしかしたら加湿器をわざわざ購入しなくても良いかも ... )

このアプリの使い所

  • 感染症対策
  • 熱中症対策
  • ペットがいる家庭での温度管理
  • 職場の温度・湿度管理

今後したいこと

  • WidgetKit を利用して、アプリを立ち上げなくても温度・湿度を確認する。

App Store での配信開始

2023/01/09 配信開始 🎉

2023/01/10 ver 1.2.0 で測定したデータを保存できるようにした
・ 当初 CoreData を利用する予定だったが、Xcode でのアーカイブ時にエラーが発生
・ 上記エラーを解決するのに時間がかかりそうだったため Realm を採用した

参考資料

MESH 技術ドキュメント
MESH の操作方法・通信仕様がまとめられている。

Qiita
下記記事がとてもわかりやすい。

Speacker Deck (2023/04/04 追記)
この記事の取り組みを スライド にまとめました。

1
0
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
1
0