Fusic Tech Blog

Fusion of Society, IT and Culture

IoT でオンライン会議スペースを監視し Slack に表示する
2022/04/27

IoT でオンライン会議スペースを監視し Slack に表示する

はじめまして 2022 年 2 月に中途入社した松山です。
中途研修として開発した IoT システムを紹介します。
中途研修のお題は、「オンライン会議用の個室利用を効率化せよ!」というものです。

コワーキングスペースなどにもありますが、Fusic にはオンライン会議スペース (個室) が 6 部屋あります。
この 6 部屋のうち 3 部屋は Outlook で予約して利用し、残り 3 部屋は予約不要で利用できます。

↓こんな感じ

オンライン会議スペース

予約不要の部屋は気軽に使えて便利なのですが、予約不要なだけに「行ってみたけど使われてた」ということが起こります。

そのため、まず空いているか確認するためだけに見に行って、

  • 空いていた場合: パソコンを持って再度移動
  • 空いてない場合: Outlook で予約を確認する

となると、「予約不要なのに、結局手間がかかかるじゃん!」
と言われても仕方がない。。。

この問題を解決するのが、今回の IoT システムです!

設置した IoT デバイス

さっそくですが、個室に設置した IoT デバイスを紹介します。

IoT デバイス の中身

"いる"/"いない" の判断には超音波センサーを使いました。

デバイスの材料は以下です。

材料 値段 備考
Grove IoT スターターキット 17,578 円 Wio LTE超音波センサー を使用

こちらは、なんと ! Grove IoT スターターキット にあるものだけで作成できます!
「試しに買ったけど余っているんだよなー」という方は是非、作ってみてください〜。

設置したら以下のようになります。

設置した IoT デバイス

  • ケース: 3D プリンタで 花園 が作ってくれました

    • 洗練されたシックなデザイン
  • 設置: 壁がフェルトだったので、マジックテープで付けています

    • 壁を傷つけずに​設置可能
  • 給電: 個室にある USB を利用しています

設置に必要な部材は以下です。

部材 値段 備考
アクリルケース 2,580 円 市販のものだとこのくらいのお値段
USB ケーブル 612 円 2 本分のお値段
マジックテープ 655 円 10 cm くらいしか使っていない

なぜ超音波センサーにしたのか ?

人を感知するものとしては、人感センサー (赤外線) が有名かと思います。
が、動きがないと "いない" と判断されるという落とし穴があります
(トイレで、照明が消えて手を振ったことがある人もいるかと思います)。
人がいる間は反応し続ける、超音波センサーを選びました。

なぜ LTE にしたのか ?

そこに Grove IoT スターターキット があったから、、、

Wi-Fi で社内ネットワークに接続するというのは、一見簡単で、お手軽に思います。
が、そこは社内ネットワーク、重要な情報にアクセスできてしまうパスワードを、IoT デバイスが持つことに。。
実は、LTE の方が社内ネットワークに影響を与えず、セキュアで手軽に試せるのです!

ユーザーインターフェース

他の IT の会社でもそうでしょうが Fusic では Slack が日常的なコミュニケーションツールとして使われています。
Slack には スラッシュコマンド という、特定のアクションを簡単に呼べる仕組みがあります。
Slack を日常的に使っているのであれば、 Web ページを開くよりも身近なインターフェースであるため、今回はスラッシュコマンドを選びました。

今回作成したスラッシュコマンドを実行すると、以下のようなメッセージが返ってきます。

Slack のメッセージ

数字が部屋番号で、🟥 が空いていない、🟩 が空いている、ということを示します。
文字で書かれるより直観的に分かる!

システム構成

システム構成を以下に示します。

システム構成図

利用したサービスは以下です。

サービス名 初期費用 サービス使用量 備考
SORACOM Air 1,287 円 330 円/月 plan-D (データ通信のみ/D-300MB)
SORACOM Funnel 0 円 0 円/月 月間 50,000 リクエストまで毎月無料
AWS IoT Core AWS IoT Core の料金 メッセージング、ルールエンジンを利用
Amazon DynamoDB Amazon DynamoDB 料金 プロビジョニング済みキャパシティーモードを利用
Amazon API Gateway Amazon API Gateway の料金 REST API を作成
AWS Lambda AWS Lambda 料金 今回は Ruby で実装

収集フローの実装

以下の作業を実施することで、個室の利用状況を IoT デバイスで取得し DynamoDB に保存できます。

Wio LTE の実装

超音波センサーを用いて、"いる"/"いない" を判定し、状態を SORACOM Funnel に送信する、プログラムを Wio LTE に実装します。

Wio LTE、超音波センサーのセットアップについては、 SORACOM IoT レシピ:IoTでジェスチャーシステム が詳しいので、こちらをご参照ください。

今回のソースは こちら

ソースだけだと分からないと思いますので、フローチャートを書きました。

Wio LTE のフローチャート

↓動かすとこんな感じ

Wio LTE 動画

LTE の色の意味は以下のようになってます。

  • 緑 = 'leave' (近くに何もない)
  • 赤 = 'enter' (近くに何かある)
  • 青 = 'leave' (動きがない)

SORACOM Funnel で AWS IoT Core に送る設定

Wio LTE からのデータを AWS IoT Core まで送るためには、SORACOM FunnelAWS IAMAWS IoT Core の設定が必要です。

AWS IoT アダプターを使用する に詳しく書かれています。
AWS IoT アダプターを使用するステップ 4 までを実施すれば、ここで実現したい、 AWS IoT Core への送信が実現できます。

DynamoDB テーブルの作成

Wio LTE からのデータを貯めるのに、Amazon DynamoDB を利用します。

今回は、

  • パーティションキー: imsi (文字列)
  • ソートキー: timestamp (数値)

でテーブルを作成します。

DynamoDB テーブルの作成

DynamoDB へデータを送る AWS IoT ルールの作成

AWS IoT Core から、作成した Amazon DynamoDB のテーブルへ送るための設定を実施します。

AWS IoT アダプターを使用する は、Amazon SNS でメール通知する手順ですので、これを Amazon DynamoDB へデータを送るルールにしたいです。

AWS IoT アダプターを使用するステップ 6 において、
アクションの追加で、DynamoDB テーブル (DynamoDBv2) の複数列にメッセージを分割する を選択し、
アクションの設定において、作成したテーブル名を指定、ロールの作成 を実施して、アクションを追加します。

DynamoDBv2 テーブル名の選択

これで、データが保存されているはずです。
IoT デバイスを起動し、DynamoDB にデータが保存されているか、確認してみてください。

表示フローの実装

以下の作業を実施することで、Slack のスラッシュコマンドから DynamoDB の保存された個室の利用状況を表示できます。

Lambda の実装

AWS Lambda にて Amazon DynamoDB から個室の状態を取得し、Slack へのメッセージを返すプログラムを作成します。

Lambda で実行する Ruby のソースコードを以下に示します。
処理の大まかな流れは、

  • Slack slash コマンドのパラメータから token を取得し、検証する。
  • DynamoDB から IMSI ごとの最新データを取得する。
  • 部屋が空いてたら 🟩 空いてなかったら 🟥 のメッサージを返す。

です。

require 'uri'
require 'aws-sdk'

TABLE_NAME = 'usage_of_compartment'.freeze
IMSI_LIST = [ 'xxxxxxxxxxxxxxx', 'yyyyyyyyyyyyyyy', 'zzzzzzzzzzzzzzz' ].freeze
STATUS_EMOJI = { 'leave' => '🟩', 'enter' => '🟥' }.freeze

def lambda_handler(event:, context:)
    params = Hash[URI::decode_www_form(event['body-json'])]
    return { text: 'Unauthorized' } unless params['token'] == ENV['SLACK_APP_TOKEN']
    
    message = ''
    IMSI_LIST.each_with_index do |imsi, index|
        response = latest_room_status(imsi)
        message += "#{index + 1} #{STATUS_EMOJI[response]} "
    end
    
    { text: message }
end

def latest_room_status(imsi)
    query = {
        table_name: TABLE_NAME,
        limit: 1,
        scan_index_forward: false,
        key_condition_expression: 'imsi = :imsi',
        expression_attribute_values: { ':imsi' => imsi }
    }
    
    client = Aws::DynamoDB::Client.new
    response = client.query(query)
    return 'leave' if response[:count] == 0
    
    response.dig(:items, 0, 'payloads', 'status')
end

Lambda から DynamoDB への接続設定

このままでは、AWS Lambda から Amazon DynamoDB へのアクセス権限がないため、権限を付与します。

  1. アクセス権限実行ロールロール名 のところにあるリンクをクリックし、Lambda のアクセス権限ロールを開きます。

ラムダアクセス権限

  1. AmazonDynamoDBReadOnlyAccess を選択し、ポリシーをアタッチ をクリックします。

DynamoDBReadOnly

Slack スラッシュコマンド向け API Gateway の作成

Slack スラッシュコマンドからは、HTTP の POST リクエストがくるため、リクエストを受ける REST API を Amazon API Gateway で作成します。

HTTP POST リクエストが来たら、作成した Lamdba を呼び出すよう、設定します。

  1. REST API を作成し、POST のメソッドに作成した Lambda を指定します。

API Gateway の POST メソッド

  1. POST統合リクエスト から Slack スラッシュコマンドを受けるための マッピングテンプレートを設定します。

    • テンプレートが定義されてない場合 (推奨) を選択し
    • マッピングテンプレートの追加 から application/x-www-form-urlencoded を選択
    • テンプレートの生成 から メソッドリクエストのパススルー を選択し、保存

API Gateway の Content-Type

  1. アクション ボタンから API のデプロイ を実行し、URL の呼び出し にある URL を確認します。

API Gateway の URL

Slack アプリおよびスラッシュコマンドの作成

個室の利用状況を表示する、独自の Slack アプリおよび、スラッシュコマンドを作成します。

slack apiCreate New App よりアプリを作成します。
作成したアプリの Basic Information で、 Add features and functionality の中から、 Slash Commands をクリックし、スラッシュコマンドを作成します。

Request URL には API Gateway の URL を入力してください。 Create New Command

Slack からこのアプリ使うために Install your app より、アプリをインストールしてください。
これで、ようやく、スラッシュコマンドは実行できます。
が、今の時点で実行しても、Unauthorized が返ってくるだけです。。。

Slack アプリの Verification Token を Lambda に設定

Lambda の実装SLACK_APP_TOKEN の環境変数設定が必要なことを覚えていますでしょうか ?
そうです、外部から実行されないために Lambda において Token の検証を行なっているのです。

Token は、Basic InformationApp Credential にある Verification Token です。

App Credentials

これを Lambda の環境変数 SLACK_APP_TOKEN に設定します。

Environment variable

これで、Slack から作成したスラッシュコマンドを実行すると、 ユーザーインターフェース で示すような表示がえられるはずです !

まとめ

Kazuhiro Matsuyama

Kazuhiro Matsuyama

IoT エンジニア (お勉強中)