この記事はGo3 Advent Calendar 2019の19日目です。
はじめに
人類はこれまで幾度となく文明を進化させてきましたが、今だに解決仕切れていない問題があります。
そう、それは「トイレ混雑問題」。人間として生きていくためには避けて通れない問題です。
最近ではこの問題を危惧した様々な企業さん達が、こぞって記事を出しています。
『駅の空いてるトイレが分かる』アプリケーションを開発。「これを待っていた!」とSNSで話題に
弊社もオフィスによっては個室の数が少なく、空いているかいないかのチェックに苦労している人もいるそうです。
その為、この問題をIoTで簡単に解決できないかと考え、「ラズパイ×Gobot」でトイレの混雑検知の仕組みを試作してみました!!!
構成
この辺りの記事を参考に構成を組んでいます。
【Raspberry Pi】自作人感センサーの使い方と活用法
ソースコード
人感センサで人を感知した後に、人の背後に置いた超音波センサで人が席を離れたどうかを判定します。
超音波センサの判定距離はデモ用に作っているので、適当に設定しています。
slackへの通知はincoming-webhookを使い、このために作った専用のチャンネルに送信しています。
import (
"gobot.io/x/gobot/drivers/gpio"
"gobot.io/x/gobot/platforms/raspi"
"time"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"gobot.io/x/gobot"
)
const (
SensorValueDetect = 1
SensorValueUndetect = 0
)
func main() {
err := motion()
if err != nil {
println(err)
}
}
func motion() error {
r := raspi.NewAdaptor()
f := false
trigPin := gpio.NewDirectPinDriver(r, "11")
echoPin := gpio.NewDirectPinDriver(r, "13")
work := func() {
gobot.Every(3*time.Second, func() {
// 7番ピンから直接センサーの値を読み取る
v, _ := r.DigitalRead("7")
if v == SensorValueDetect {
if f == false {
slack.SlackPostIn("誰かが来た様です。")
f = true
}
println("Starting probing ")
err := trigPin.DigitalWrite(byte(0))
if err != nil {
println(err)
return
}
time.Sleep(2 * time.Microsecond)
err = trigPin.DigitalWrite(byte(1))
if err != nil {
println(err)
return
}
start := time.Now()
end := time.Now()
for {
val, err := echoPin.DigitalRead()
start = time.Now()
if err != nil {
println(err)
break
}
if val == 0 {
continue
}
break
}
for {
val, err := echoPin.DigitalRead()
end = time.Now()
if err != nil {
break
}
if val == 1 {
continue
}
break
}
duration := end.Sub(start)
distance := duration.Seconds() * 34300
distance = distance / 2
println(distance)
if distance > 1000 {
println(distance)
slackPostOut("部屋が空きました。")
f = false
}
}
})
}
robot := gobot.NewRobot("blinkBot",
[]gobot.Connection{r},
[]gobot.Device{trigPin, echoPin},
work,
)
robot.Start()
return nil
}
var IncomingURL string = "incoming-webhookで取得したURL"
// jsonの情報
type Slack struct {
Text string `json:"text"`
Username string `json:"username"`
IconEmoji string `json:"icon_emoji"`
IconURL string `json:"icon_url"`
Channel string `json:"channel"`
}
func slackPostIn(text string) {
arg := text
params := Slack{
Text: fmt.Sprintf("%s", arg),
Username: "Close Push",
IconEmoji: ":cold_sweat:",
IconURL: "",
Channel: "",
}
jsonparams, _ := json.Marshal(params)
resp, _ := http.PostForm(
IncomingURL,
url.Values{"payload": {string(jsonparams)}},
)
body, _ := ioutil.ReadAll(resp.Body)
defer resp.Body.Close()
println(string(body))
}
func SlackPostOut(text string) {
arg := text
params := Slack{
Text: fmt.Sprintf("%s", arg),
Username: "Open Push",
IconEmoji: ":relaxed:",
IconURL: "",
Channel: "",
}
jsonparams, _ := json.Marshal(params)
resp, _ := http.PostForm(
IncomingURL,
url.Values{"payload": {string(jsonparams)}},
)
body, _ := ioutil.ReadAll(resp.Body)
defer resp.Body.Close()
println(string(body))
}
結果
...なんか鬱陶しいメンヘラチックですね。
さいごに
これ実は弊社の開発合宿で作った成果物でした!下記はその時の内容が書かれているテックブログです。
【チェックリスト付き】開発合宿 運営マニュアル 〜計画から実施までの流れ〜
かなり短い時間で開発を行ったのですが、Gobotでの実装がかなり楽ですぐ作ることができました。シビアな実行環境でなければ、組み込みの軽いプロトタイプを作る際におすすめです!
本記事で紹介したソースコードはとても汚い試作要素が強いので、実行環境によってステータスとかいじって使ってみてください!
トイレにはハードルが高い...という方は普通にGobotの一例として参考にしていただければと思います。