Event

5. 人感センサーを使う – こちらから攻める

5. 人感センサーを使う – こちらから攻める

この記事はiOSDC2022で発表したセッション、Swiftで我が家を より便利に、安全に!の発表の第4部の内容をまとめたものになります。
この記事は、「4. カードリーダーと連携する – SuicaのIDを読み取る」 の記事の続編です。もしまだ読んでいない方は読んでいただけると!
この記事では、人感センサーの使い方と、SwiftからBashコードの実行方法やSwitchBotのAPIの使い方を紹介します。

4. カードリーダーと連携する - SuicaのIDを読み取るこの記事は、「Swiftで我が家をより便利に、安全に」の発表の4部「4. カードリーダーと連携する - SuicaのIDを読み取る 」の内容をまとめた記事になります!...

人感センサーをトリガーに処理を実行する

今回はラズパイと連携した人感センサーが作動して、家主が在宅中でない(①緯度経度や高度情報が家と一致しない、②重量センサーに物が無い、③Suicaで認証されていない)場合のみ実行する、↓を実行することを目指します

  • スピーカーで警告音を流す
  • SwitchBotでデバイスを動かす
  • Push通知を送る(発表では省略)
  • カメラで侵入者を撮影し、Twitterに画像を投稿(今後実装予定)

今回使用した人感センサーは、↓のものです!

実装イメージは以下の通りです!

人感センサーの連携の実装

まずは回路を作りましょう!
今回は電源2本、通信用1本(オレンジ/GPIO25)の3本を使用しています
また人を検知した時に、LEDが点灯するようにしています!

次にコードを確認しましょう!
最初はいつも通り、GPIOインスタンスのセットアップです!
回路の箇所で説明した通り、人感センサー用とLED用のGPIOをセットアップしてます。

let humanSensorGpio = gpios[.P25]!
let humanSensorLedGpio = gpios[.P16]!

humanSensorGpio.direction = .IN
humanSensorLedGpio.direction = .OUT
humanSensorLedGpio.value = 0

次にGPIOの値を監視しましょう
SwiftyGPIOには、GPIOのvalueの変化を監視するメソッドがあり、今回はそのメソッドを使用します
onChangeメソッドを使うことで、valueが1<->0に変化した時に、クロージャが呼ばれるので、その中でLEDの点灯/消灯を設定し、その変化を通知する処理を実装します

humanSensorGpio.onChange { gpio in // ①Called when value changes
    if gpio.value == 1 {
        // Human detected
        self.humanSensorLedGpio.value = 1 // ②turn on the LED
        // (Omit: notify change)
    } else {
        self.humanSensorLedGpio.value = 0 //③turn off the LED
        // (Omit: notify change)
    }
}

最後に上記の処理を使ったメソッドを実装しました。
didDetectedのBoolの値をクロージャーで受け取ります
そしてdidDetectedがtrueの時に、処理が実行できるようにしています。

// ①methods for monitoring
GpioManager.shared.observeHumanMoved { didDetected in
    if didDetected {
        print("Human detected!")
        // (Omit: Execute processing when a person is detected)
    } else {
        print("Human Not detected!")
    }
}

準備ができたら、試しに動かしてみましょう!

ちゃんと人感センサーがちゃんと動いて、人の動作を検知できていることが確認できました!🎉

警告音を再生する実装の詳細

次に侵入者に対して警告音を再生する機能の実装です!

今回はサンプル用のmp3を再生するのに、mpg123のコマンドを使用します
Swiftから上記のサンプル音声を再生するShellスクリプトを実行するようなイメージです!
実行すると、ラズパイのイヤホンジャックに接続したスピーカーから警告音声が流れるようにします!

まずはSwiftからShellスクリプトを実行する共通処理を実装します(参考)

@discardableResult
func shell(_ args: String...) throws ->  Int32 {
    let task = Process()
    task.executableURL = URL(fileURLWithPath: "/usr/bin/env")
    task.arguments = args
    try task.run()
    task.waitUntilExit()
    return task.terminationStatus
}

Macの場合、Package.swiftにmp3をリソースとして指定する必要があるので、追加します

resources: [
    // Copy resource file to bundle
    // Mac: Build artifacts are generated in the DerivedData directory
    // Linux: You can directly refer to the audio files in the cloned directory
    .process("warning_voice.mp3"),
]

上記に少しコメントで記載がありますが、MacとLinuxだとコマンドのパスやビルドされた成果物のmp3のパスが異なるので、それぞれ分けて設定します。
Macの場合、実行時のmp3のパスは、DerivedDataのパスになり、Linuxの場合はリポジトリをcloneしたパスになります

let command: String
let path: String
#if os(Linux)
    command = "/usr/bin/mpg123"
    path = "\(Path.current)/Sources/SwiftHomePi" // If linux, returns repository path
#else
    command = "/opt/homebrew/bin/mpg123"
    // If Mac,  returns DerivedData path
    path = "\(Path.current)/SwiftHomePi_SwiftHomePi.bundle/Contents/Resources"
#endif

最後に上記で実装したShell実行用の共通メソッドに、用意したコマンドとmp3のパスを設定します
コマンドとパラメーターはそれぞれ別々のStringとして設定する必要があります

let voiceFilePath = "\(path)/warning_voice.mp3"
do {
    // ①Separate commands and parameters
    try shell(command, voiceFilePath)
} catch {
    print(error)
}

SwitchBotのデバイスを動かす実装詳細

次にSwitchBotのデバイスを動かす実装です!

今回は我が家にある電源タップテープライトを操作します!
電源プラグは、ネットワーク経由で電源のON/OFFを操作できて、テープライトは、ネットワーク経由でライトのON/OFF、色の種類を操作できます!

Ref: https://www.switchbot.jp/collections/all

SwitchBotのAPIの使い方については、別のブログにまとめました!
詳細はこちらを確認いただけると!!

SwitchBotのAPIを使って、SwitchBotデバイスを操作するSwitchBotのAPIを使って、SwitchBotデバイスを操作する方法をまとめてみました!...

今回は電源タップには、IKEAで買ったスタンド照明を繋いで、玄関ラックに置きます。
人感センサーで検知した時に、スタンドの60W(すごい明るい)電球をつけることで、侵入者の視界を奪います!
60Wのライトは、かなり眩しくて、突然点灯したら、確実に視界が持っていかれます!笑

ちなみにこのシステムを勝手に「太陽拳システム」と呼んでいます!笑

出典: DRAGON BALL(鳥山明)

テープライトは、赤白に点滅させて、侵入者を警告します!

デモ

上記で実装した物をまとめて動かしてみましょう!
今回はデモなので、机の上にラズパイと人感センサーを設置して、手をかざした時に、
①電源タップ経由でスタンドのライト点灯、②テープライト点灯、③警告音再生
の順に処理を実行していきます!

なお↓の動画はSwitchBotの屋内カメラを玄関に無理やりくくりつけて、撮影しています!笑
普段監視用に玄関に置いているカメラが役に立ちました笑

無事想定通りに動かすことができました!!🎉🎉🎉

Push通知を送信する処理

今回は簡単に実装するため、FirebaseのFCMのLegacyAPIを使用します。

SwiftHomePiに以下の実装を追加して、Firebase経由でPush通知を送信できるようにします。
デモなので、Push通知の送付先のFCM Tokenは手動で設定するようにしています。

本実装、及びアプリ側の実装は、Firebaseのドキュメントを確認いただけると!(コード)

let serverKey = SwiftHomeCredentials.fcmServerKey
// This is demo app, so fmc token must be set manually.
let fmcToken = "xxxxxxxx"

let headers: Alamofire.HTTPHeaders = [
    .accept("*/*"),
    .contentType("application/json"),
    .acceptCharset("utf8"),
    .authorization("key=\(serverKey)")
]
let parameter = [
    "registration_ids": [
        fmcToken
    ],
    "notification": [
        "title": "侵入者通知⚠️",
        "body": "家への侵入者を検知しました!カメラを確認してください!",
        "badge": "0",
    ]
] as [String : Any]
let urlString = "https://fcm.googleapis.com/fcm/send"
AF.request(urlString,
           method: .post,
           parameters: parameter,
           encoding: JSONEncoding.default,
           headers: headers
)
.responseString(completionHandler: { response in
    print(response)
})

うまくいくと、↓のように、通知が飛びます!

まとめ

これで5部の紹介は終わりです
4部までに実装したことも使いつつ、デモも交えて紹介することができました!
太陽拳とかふざけつつも、実際に導入できそうな実装ができたのは良かったと思いました!

次はこの発表のまとめを書いた記事です

まとめ - SwiftHomeの実装を終えてこの記事は、「Swiftで我が家をより便利に、安全に」の発表の「まとめ - SwiftHomeの実装を終えて」の内容をまとめた記事になります!...

参考

+1

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA