Raspberry Piで部屋の外からビデオ会議中か分かる装置を作る!

この記事は [ABEJAアドベントカレンダー2020](https://qiita.com/advent-calendar/2020/abeja) の6日目の記事です。

ABEJAでは小売店舗の状況を数値化・データ化を推進し店舗運営を改善するSaaSプロダクトを開発しています。

## イントロ

Raspberry Piを用いて、部屋の中から外に設置したLEDを光らせることで部屋の外にビデオ会議中か分かる装置をつくりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9830/c39f6f45-eecd-6315-0dff-d967fdb1ee9a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9830/86bef342-d3d6-7324-b909-791c241df361.png)

## Why

今年は新型コロナウイルスの流行もあって自宅からのリモートワークを基本とする業務体制にシフトし、ミーティングは基本的にはすべてビデオ会議ツールを用いて実施するようになりました。

私は現在、妻との2人でマンションに住んでいて、1部屋を私の勉強や作業スペースとして利用できるように2LDKを借りているのでリモートワーク自体はスムーズに移行できました。

しかしビデオ会議をしていると**妻が庭に洗濯物を干す際に写り込んでしまったり、家庭内の声やTVの音声が入り込んでしまったりという課題**がでてきました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9830/82ea7e71-b0ff-89ba-76f3-aaf96834fc4b.png)

**特に家庭内の会話に関しては、恥ずかしくて絶対に外に出したくなく**、今回Raspberry Piを用いて部屋の外からビデオ会議中かどうか状態を表示するような装置を作成しました。

## アイデア

信号機のように、色と光で現在の部屋の状況を部屋の外にいる妻に伝えるようにする装置を作ることにしました。

| LED色 | 説明 |
|:-:|:-:|
|青| 仕事をしていない状態 |
|黄|仕事中|
|赤|ビデオ会議中|

## Raspberry PiでLEDを点灯させる

電子工作でのHello Worldに当たるLチカ（LEDをチカチカ点滅させる; LEDチカチカ）があるようにLEDの制御は初心者でも簡単に実施することができます。
Raspberry Piの入門の仕方については、最後の章に簡単にまとめたいと思います。

[Raspberry Pi Zero WH](https://akizukidenshi.com/catalog/g/gM-12958/) とフレットボード、抵抗内蔵LEDを以下のようにつないで作成しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9830/97efae39-bcc3-ffe1-c092-cafbb0c81e70.png)

![IMG_20201205_163716.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9830/b9a939f0-3ea0-d017-8c8c-dd27a61ba5ac.jpeg)

## 部屋の状態をRaspberry Pi に通知する

部屋の状態をRaspberry Pi に通知する方法として [Firebase](https://firebase.google.com/) のFirestoreを利用しました。

Firestoreはデータの永続化とサブスクライブしているクライアントへWebsocket経由でデータ変更を通知する機能を持っており、お手軽な情報の通知手段として利用することができます。

Firestoreとの通信はインターネットに接続する必要があるので、Raspberry Piのwifiをつないでインターネット接続は事前にできるようにしてあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9830/de91fa67-b8b7-7f77-36eb-fb92d1a1536d.png)

```python:main.py
import RPi.GPIO as GPIO
from time import sleep

import firebase_admin
from firebase_admin import credentials, firestore

available_pin = 23
working_pin = 24
meeting_pin = 17
button_pin = 25

GPIO.setmode(GPIO.BCM)
GPIO.setup(available_pin, GPIO.OUT)
GPIO.setup(working_pin, GPIO.OUT)
GPIO.setup(meeting_pin, GPIO.OUT)
GPIO.setup(button_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)

cred = credentials.Certificate("./service-account.json")
firebase_admin.initialize_app(cred)
db = firestore.client()

def on_snapshot(doc_snapshot, changes, read_time):
    for doc in doc_snapshot:
        print('Received document snapshot: {}'.format(doc.id))
        state = doc.to_dict()['tkgState']
        print('tkgState: {}'.format(state))
        GPIO.output(available_pin, GPIO.LOW)
        GPIO.output(working_pin, GPIO.LOW)
        GPIO.output(meeting_pin, GPIO.LOW)

        if state == 'available':
            GPIO.output(available_pin, GPIO.HIGH)
        if state == 'working':
            GPIO.output(working_pin, GPIO.HIGH)
        if state == 'meeting':
            GPIO.output(meeting_pin, GPIO.HIGH)

doc_ref = db.collection('store').document('v1')
doc_watch = doc_ref.on_snapshot(on_snapshot)

try:
    while True:
        sleep(1)
except KeyboardInterrupt:
    pass

GPIO.cleanup()
```

## 部屋の状態をFirestoreに保存する

取り急ぎ疎通確認も兼ねてFirestoreに部屋の状態を保存できるようにNext.jsでフロントエンドのアプリを作成しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9830/9bfa6e8a-84d4-59ba-e58e-d0f628b1f98c.png)

[Next.js](https://nextjs.org/)は特に難しい設定無しで簡単にReactアプリを作ることができるのでちょっとしたものを作る際にも活用しています。

ブラウザでボタンを押すことでFirestoreの状態を変更できるようにしています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9830/39b02608-a456-97aa-5dd8-96fc12df464c.png)

メインのコードは以下となっています

```typescript:index.tsx
import { useState } from 'react';
import Layout from '../components/Layout'

// Firebase part
import * as firebase from "firebase/app";
import "firebase/firestore";

const firebaseConfig = {
  apiKey: "xxx",
  authDomain: "xxx",
  databaseURL: "xxx",
  projectId: "xxx",
  storageBucket: "xxx",
  messagingSenderId: "xxx",
  appID: "xxx",
};

if (!firebase.apps.length) {
  firebase.initializeApp(firebaseConfig);
}

const IndexPage = () => {
  const [tkgState, setTkgState] = useState('');

  const db = firebase.firestore();
  const storeRef = db.collection("store").doc("v1");

  storeRef.get().then((snapshot) => {
    setTkgState(snapshot?.data()?.tkgState)
  });

  const changeState = async (nextState: string) => {
    await storeRef.update({
      tkgState: nextState
    });

    setTkgState(nextState)
  }

  return (
    <Layout title="tkg state">
      <h1>tkg state: {tkgState}</h1>

      <h2>Change State</h2>
      <div>
        <button onClick={() => changeState('available')}>Available</button>
        <button onClick={() => changeState('working')}>Working</button>
        <button onClick={() => changeState('meeting')}>Meeting</button>
      </div>
    </Layout>
  )
}

export default IndexPage
```

これで**ブラウザを経由して、部屋の中から部屋の外のLEDの制御し部屋の状態を表現**ができるようになりました。

![ezgif-7-f96a6159db7d.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9830/153bb161-356f-9afa-5520-ef4454acf5ad.gif)


## Next Action

部屋の中から部屋の外のLEDの制御し部屋の状態を表現する仕組みをつくることができました。
ただ試してみた結果、**意外とステータスの変更が面倒**だということがわかったので、年末年始の宿題として部屋内にRaspberry Piとマイクを設置して会議中の声に反応して状態が変わるように計画中です。

## Raspberry Pi入門について

Raspberry PiはLinuxベースのOSで動作しWeb技術でよく利用するソフトウエアが動作する一方、GPIOを用いてLEDやセンサー等を取り付けてリアル環境に対してインプット・アウトプットすることができます。

[ラズパイ4対応 カラー図解 最新 Raspberry Piで学ぶ電子工作 作る、動かす、しくみがわかる!](https://www.amazon.co.jp/%E3%83%A9%E3%82%BA%E3%83%91%E3%82%A44%E5%AF%BE%E5%BF%9C-Raspberry-Pi%E3%81%A7%E5%AD%A6%E3%81%B6%E9%9B%BB%E5%AD%90%E5%B7%A5%E4%BD%9C-%E4%BD%9C%E3%82%8B%E3%80%81%E5%8B%95%E3%81%8B%E3%81%99%E3%80%81%E3%81%97%E3%81%8F%E3%81%BF%E3%81%8C%E3%82%8F%E3%81%8B%E3%82%8B-%E3%83%96%E3%83%AB%E3%83%BC%E3%83%90%E3%83%83%E3%82%AF%E3%82%B9/dp/4065193397/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=raspberry+pi+%E3%83%96%E3%83%AB%E3%83%BC%E3%83%90%E3%83%83%E3%82%AF%E3%82%B9&qid=1607179673&sr=8-3) が入門を読んで、[秋月電子](https://akizukidenshi.com/catalog/top.aspx)　でパーツを揃えて作ってみると理解が深まリます。

ぜひ年末年始おやすみにいかがでしょうか？