Top View


Author Yuhei Okazaki

LINE BeaconとM5Stackでリモートワーク中の在席状況を自動通知する

2020/05/13

背景

リモートワークにおけるコミュニケーション手段にDiscordを利用

私達のチームは、リモートワークにおける会話でのコミュニケーション手段として「Discord」を利用しています。

Discordはボイスチャンネルを複数作れるので、他のメンバーの作業を阻害せずにクローズドに会話できます。

Discordのボイスチャンネル

実際、会社のオフィスにいるときと遜色なく、コミュニケーションが取れて良いと感じています。

問題点: 話しかける相手が離席中の場合がある

相手が離席中だと、話しかけて数秒間応答が無い状態となり、「ああ、おそらくXXさんは離席中だな」と判断します。

数秒ではありますが、これは非効率です。

相手が離席中の場合

Discordに限らず、チャットツールには自分自身のステータスを設定することができます。

各自離席・着席するときにこのステータスを漏れなく更新しておけば、ステータスを見て相手が離席中かどうか判断できます。

カスタムステータス

しかし、人間は忘れる生き物なので、ステータスの更新を忘れることはざらにあります。

解決案: 席を立ったらDiscordに通知する

ステータスの更新忘れを防ぐため、席を立ったらDiscordに通知するIoTシステムを作ることにしました。

IoTシステムのイメージ

席を立ったかどうかはLINE Beaconを使ってみることにしました。

過去に、iBeaconを使った記事も書きましたが、LINE Beaconを使うとデバイス側を簡素化できるので良いです。

LINE Beacon端末は持っていないので、手元にあったM5Stack(とM5StickC)で代用することにしました。

M5StackとM5StickC

システム開発

構成

IoTシステム構成図

LINE Beaconでは、LINE Beacon端末がBLEパケットをアドバタイズします。

手元のスマホがそれを受信すると、指定したWebhookURLにビーコンイベントをPOSTしてくれます。

AWS上にPOST先のエンドポイントを作っておき、LambdaでDiscordへ通知します。

本当はカスタムステータスの更新までできると良かったのですが、今回はWebhookURLでチャットへの通知のみ行っています。

LINE Beacon端末の実装

M5Stackに書き込むプログラムはこちらの記事をほぼそのまま使わせていただきました。

ただし、POWER_LEVELは最小値のESP_PWR_LVL_N12を指定しています。

最小値まで下げないと、家中どこにいてもアドバタイズを拾える状態となってしまい、席を立っただけでは通知がされないためです。

BLEアドバタイズの送信範囲

エンドポイントの実装

SAMを使ってAWS上にAPI Gateway + Lambdaの環境を構築しました。

以下はLambdaハンドラのソースコードです。使い慣れているRubyで実装しました。

require 'json'

WEBHOOK = '{ DiscordのWebhookURL }'

def lambda_handler(event:, context:)
  parsed_events = JSON.parse(event['body'])
  return if parsed_events.nil? || parsed_events['events'].nil?
  
  parsed_events['events'].each do |json|
    return res unless json.dig('source', 'type') == 'user'
    return res unless json.dig('source', 'userId') == '{ 自分のuserId }'
    return res unless json.dig('beacon', 'type') == 'enter'
    
    content = case json.dig('beacon', 'hwid')
              when '{ 部屋の中に設置するLINE Beacon端末のHWID }'
                'okazaki is comming back.'
              when '{ 部屋の外に設置するLINE Beacon端末のHWID}'
                'okazaki is going away.'
              else
              end
    
    uri = URI.parse(WEBHOOK)
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true
    http.post(
      uri.path,
      { content: content }.to_json,
      'Content-Type': 'application/json'
    )
  end

  { statusCode: 200, body: { success: true }.to_json }
end

動作確認で発生した問題

その1: 席を立ったタイミングで通知が来ない

当初は部屋の中に設置した1台のLINE Beacon端末で部屋の出入りを検知できる想定でした。

1台のLINE Beacon端末による検知

しかし、ビーコンイベント の仕様にも書かれているのですが、beacon.typeleave廃止予定となっています。

BLEアドバタイズを受信できなくなった場合に何かしら通知があるだろうと淡い期待をしていたのですが、席を立ってからしばらくして通知が来るようです。

これでは当初の目的を達成できないので、LINE Beacon端末を1台追加することにしました。

LINE Beacon端末を追加

これにより、部屋の外のBeaconを検知したタイミングで「離席」を、部屋の中のBeaconを検知したタイミングで「着席」を通知します。

その2: ちょっとした離席だと、席を戻ったタイミングで通知が来ない

これもLINE Beaconの仕様と思われますが、わずかでもアドバタイズを受信していたり、一瞬アドバタイズが途切れる程度ではleaveしたとみなされないようです。

このため、部屋から少ししか離れていなかったり、すぐに部屋に戻ってきたりすると「離席」しか通知されないケースがあります。

離席しか通知されないケース

対策として、いい塩梅で通知されるようLINE Beacon端末の設置場所を調整しました。

それでも100%防げる訳ではないので、この問題は運用でカバーします。

LINE Beacon端末の設置場所を調整

感想

問題はあったものの、LINE Beacon自体はとても便利でした。

今後、Beaconを使ったシステムを作る場合、第一候補にして良い気がしています。

  • LINEが入ったスマートフォンは大抵の人が所持しているので、LINE Beacon端末さえ準備すれば誰でも利用できます
  • BLEアドバタイズの受信や通知をLINEが担ってくれるので、アプリケーションの実装に注力できます

まとめ

LINE BeaconとM5Stackを使って、在席状況を通知するIoTシステムを作りました。

LINE Beacon端末の設置場所を調整

コロナウイルスの感染者数も徐々に減少してきているようです。外出自粛は不便ですが、このようなちょっとした工夫で問題を解決しつつ、完全収束に向けて頑張りましょう。

Yuhei Okazaki

Yuhei Okazaki

Twitter X

2018年の年明けに組込み畑からやってきた、2児の父 兼 Webエンジニアです。 mockmockの開発・運用を担当しており、組込みエンジニア時代の経験を活かしてデバイスをプログラミングしたり、簡易的なIoTシステムを作ったりしています。主な開発言語はRuby、時々Go。