前書き

在宅勤務中心の生活になってからかなり長い。 在宅勤務中の悩みの 1 つとして、家族から見て声をかけて良い状態かどうか分かりづらいことが挙げられる。 特に、会議中か否かは分かりづらい。 こちらとしても会議中に家族参戦は意地でも避けたい。 そこで、会議中であることをお知らせするためのデバイスを作成した。

今回は備忘録要素強め。

設計方針

一番簡単なのは、自分の Outlook カレンダーと連動した通知システムを作ること。 しかしながら、会社の PC にむやみやたらとソフトを入れることはできない。 そのため、別 PC から客観的に状態を観測してお知らせする仕組みを考える。 私は普段から Bluetooth イヤフォンを使って会議をしている。 Bluetooth は 2.4GHz 帯の電波を飛ばすので、これを観測すれば間接的に通話中か否か確認できると考えた。

とりあえず部屋前で会議中かどうか分かれば良いので、部屋前で LED を点灯させて会議中であることを PR する。仕組みからして処理負荷はあまり高くない。安価で Bluetooth モジュールを搭載している Raspberry Pi Zero を用いて実装をおこなう。

完成品挙動

Bluetooth イヤフォンの電源に連動して、LED を点灯させることが出来た。 電源 OFF 時は特にラグが大きいが、おそらく蓋を閉じてからもしばらく電波を飛ばしているのが原因だと思われる。 長めに点灯してる分にはセーフなのでヨシッ!

demo

主な材料

  • Raspberry Pi Zero と周辺機器一式 x 1
  • 赤色 LED x 1
  • 抵抗 320Ω x 1

作成したスクリプト

#!/bin/bash

[ "$#" -eq 1 ] || { echo "MAC Address is required. no arguments are provided." >&2; exit 1; }

readonly MAC=${1}
readonly GPIO=${2:-25}
readonly DURATION_S=${3:-30}
readonly WAIT_S=${4:-3}
readonly DEBUG=false

function check_btdevice(){
	mac=$1
	# scan on and wait.
	echo -e 'menu scan\nclear\nback\nscan on' >&${COPROC[1]}
	sleep $WAIT_S
	echo -e 'scan off' >&${COPROC[1]}

	echo -e 'info '$mac>&${COPROC[1]}


	# judge the outputs.
	is_exist=1
	reg_t="*NEW*Device[[:space:]]$mac*"
	reg_f="Device[[:space:]]$mac[[:space:]]not[[:space:]]available*"
	while read -r -u "${COPROC[0]}" line; do
	  if [[ $line == $reg_t ]]; then
		  is_exist=0
		  break
	  fi

	  if [[ $line == $reg_f  ]]; then
		  is_exist=1
		  break
	  fi

	  if $DEBUG; then
		  echo $line
	  fi
	done
	return $is_exist
}

init_gpio() {
	gpio -g mode $GPIO out
	trap "gpio -g write $GPIO 0;echo -e 'exit' >&${COPROC[1]}; exit 0" 0
	gpio -g write $GPIO 0
	return 0
}

gpio_on(){
	gpio -g write $GPIO 1
	return 0
}

gpio_off(){
	gpio -g write $GPIO 0
	return 0
}


coproc bluetoothctl
init_gpio
status=-1
while true; do
 	if check_btdevice $MAC; then
		if [ "$status" != 0 ]; then
			status=0
			echo "Found: $MAC"
			gpio_on
		fi
	else
		if [ "$status" != 1 ]; then
			status=1
			echo "Not Found: $MAC"
			gpio_off
		fi
	fi
	sleep $DURATION_S
done

使い方

事前に自分のイヤフォンの MAC アドレスを調べておく。 bluetoothctl の scan on で調べれば OK。

GPIO のデフォルトポートは 25 番に設定した。LED を 25 に繋いだら、調べた MAC アドレス(XX:XX:XX:XX:XX:XX)を放り込んで実行。

sudo bash bt-check.sh <MACADDR>

仕様ザックリ

書いてしまえば非常にシンプル。

  • 30 秒ごとに以下を繰り返す。
    • bluetoothctl コマンドで bluetooth のスキャンをおこなう。(scan on)
    • 指定した MAC アドレスの bluetooth デバイスが見つかれば LED を点灯する。
    • 指定した MAC アドレスの bluetooth デバイスが見つからなければ LED を消灯する。

ハマりポイント

一度検知したデバイスが二度と表示されない

初回はうまく動いたが、2 回目以降の scan on ではイヤフォンの bluetooth のビーコンが検知されなくなった。 どうやらキャッシュをしているらしく、クリアしてやる必要がある。

$ bluetoothctl
[bluetooth]# scan on
[bluetooth]# menu scan
[bluetooth]# clear

StackOverflow

0 が true で 1 が false

知ってる人は知ってるんだろうけど。。。Python だと true が 1 なので、bash も 1 が true だと思い込んでて時間を浪費した。確かに bash だと、コマンド実行成功の戻り値は 0 なので、true=0, false=1 は妥当性があるなと後から考えて反省。思い込み良くない。

学び

trap

trap を使うと Ctrl+C で終了したときに実行するコマンドを指定できる。今回はプログラム終了時に必ず LED を消灯するために書いた。

感想

  • これで会議中、妻が乗り込んでくるイベントを避けられると思う。そうなっても困ったことにはならないと思うけど。。。念のためね。
  • bash スクリプト書きづらかった。。。bash の関数の書き方って positional argument が基本なのかな。軽く調べたけど keyword argument の設定は大変そうなので諦めた。まだまだ勉強が必要。
  • LED の抵抗値を間違えてないかいつも心配になる。学生実験の時、同級生が吹き飛ばした LED が目の前をかすめていったのがトラウマ。とりあえず今回は吹き飛ばなかったので OK。
  • LED をもっとおしゃれにしたい。非常口とかの、光る LED 看板みたいな感じで。
  • Prometheus とかでログ記録して可視化しても面白いかも。
  • 会社でも「会議中?」って人から聞かれることが多いので、もう一台作って自席の高い位置に置いとくといいかもしれない。