LoginSignup
13
3

More than 3 years have passed since last update.

Gobotを使ってトイレ混雑問題と真剣に向き合ってみた

Last updated at Posted at 2019-12-18

この記事はGo3 Advent Calendar 2019の19日目です。

はじめに

人類はこれまで幾度となく文明を進化させてきましたが、今だに解決仕切れていない問題があります。
そう、それは「トイレ混雑問題」。人間として生きていくためには避けて通れない問題です。

最近ではこの問題を危惧した様々な企業さん達が、こぞって記事を出しています。

「トイレの混雑」を改善したリクルートの超アナログな方法

職場のトイレの個室でソシャゲに没頭する困った大人たち

『駅の空いてるトイレが分かる』アプリケーションを開発。「これを待っていた!」とSNSで話題に

弊社もオフィスによっては個室の数が少なく、空いているかいないかのチェックに苦労している人もいるそうです。

その為、この問題をIoTで簡単に解決できないかと考え、「ラズパイ×Gobot」でトイレの混雑検知の仕組みを試作してみました!!!

構成

この辺りの記事を参考に構成を組んでいます。

超音波距離センサ(HC-SR04)を使う

【Raspberry Pi】自作人感センサーの使い方と活用法

iOS の画像 (3).jpg

iOS の画像 (2).jpg

ソースコード

人感センサで人を感知した後に、人の背後に置いた超音波センサで人が席を離れたどうかを判定します。
超音波センサの判定距離はデモ用に作っているので、適当に設定しています。
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))
}

結果

スクリーンショット 2019-12-18 14.57.53.png

...なんか鬱陶しいメンヘラチックですね。

さいごに

これ実は弊社の開発合宿で作った成果物でした!下記はその時の内容が書かれているテックブログです。
【チェックリスト付き】開発合宿 運営マニュアル 〜計画から実施までの流れ〜

かなり短い時間で開発を行ったのですが、Gobotでの実装がかなり楽ですぐ作ることができました。シビアな実行環境でなければ、組み込みの軽いプロトタイプを作る際におすすめです!

本記事で紹介したソースコードはとても汚い試作要素が強いので、実行環境によってステータスとかいじって使ってみてください!

トイレにはハードルが高い...という方は普通にGobotの一例として参考にしていただければと思います。

13
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
3