Google Homeが盗まれたら自分で悲鳴を上げてもらいます


遅ればせながらGoogle Home Miniを買ったので，遊んでいます．

会社でも調査用途で１台買ってあり，周りの人に遊んでもらえるように置いているのですが「盗難対策どうしよう・・・」と悩んでいました．そこで，ちょうど↓の記事でGoogle Homeにしゃべってもらうというのがあったので，そちらを参考に，盗まれそうになったらGoogle Home自身に悲鳴を上げてもらうようにしてみました！

[帰宅したらGoogleHomeから好きな音声で「おかえり」って言ってもらいます](https://qiita.com/taaaaaaak22/items/abfb9f2a672689c20505)

## 環境

* macOS 10.12
* Node.js 6.11

## 結果

このような感じになりました．

[![2.jpg](https://qiita-image-store.s3.amazonaws.com/0/35592/bd153f99-31ce-018d-c69f-858f583b508d.jpeg "2.jpg") YouTube](https://youtu.be/z5oggZ9YdHI)

* 長めに叫ばせようと思って`"助けてーー！！盗まれるーーーーーーー！！"`というテキストを読み上げさせたら，語尾が情けない感じに😒


## 構成

ラズパイはまだ使ったことがなかったので，以下のような構成にしました．

![google-home-shout.png](https://qiita-image-store.s3.amazonaws.com/0/35592/f1d77e0b-cfc7-2284-a3ae-57254453e5f8.png "google-home-shout.png")

* Google Home Miniがそこにあることを圧力センサで検知してTWELITE(ZigBee)で飛ばしてmac上のNode.jsプロセスで処理し，[google-home-notifier](https://www.npmjs.com/package/google-home-notifier)でしゃべらせています．
* Google Home Miniの重さだけでは圧力センサが十分反応しなかったので，MacBookのACアダプタ（と500円玉）を間にかませています．何か別のセンサにすればよかったかも・・・

    ![google-home-shout-device.jpg](https://qiita-image-store.s3.amazonaws.com/0/35592/176bff89-a901-b8aa-10a8-86dcd81392bd.jpeg "google-home-shout-device.jpg")

* 親機（mac）側はこのような感じでUSBシリアル変換アダプタ（AE-UM232R）を経由しています

    ![google-home-shout-gateway.jpg](https://qiita-image-store.s3.amazonaws.com/0/35592/5d9eddea-fa35-d5a1-7c89-cc2776218aba.jpeg "google-home-shout-gateway.jpg")


## コード

```javascript:index.js
const googlehome = require('google-home-notifier');
const SerialPort = require('serialport');

// setup seiarl port
const port = new SerialPort(process.env.TWELITE_PORT, {
  baudRate: 115200,
})

// setup google home
googlehome.device(process.env.GOOGLE_HOME_NAME, 'ja')
googlehome.ip(process.env.GOOGLE_HOME_IP)
 

port.on('open', () => {
  console.log('port opened')
})

port.on('error', err => {
  console.log('Error: ', err.message);
})

let buffer = ""
port.on('data', data => {
  for (const k of data.keys()) {
    const s = data.toString('utf8', k, k + 1)
    if (s == '\r' || s == '\n') {
      if (buffer !== "") {
        handleTweliteLine(buffer)
        buffer = ""
      }
    } else {
      buffer = buffer + s
    }
  }
})

let lastState // 0: Google Home is on the sensor, 1: not
function handleTweliteLine(line) {
  if (line.length != 49 || line.indexOf(':') != 0) {
    console.error(`invalid line: ${line}`)
    return
  }
  const state = line.charAt(34) == '1' ? 1 : 0
  if (lastState != state) {
    console.log('state changed', state)
  }
  if (lastState == 0 && state == 1) {
    console.log('盗まれた！')
    googlehome.notify('助けてーー！！盗まれるーーーーーーー！！', (res) => {
      console.log(res)
    })
  }
  lastState = state
}
```

* `port.on('data', data => {})` でTWELITEからのシリアルデータを処理しています
    * 圧力センサはTWELITEのDI1に入力しているので，[こちら](https://mono-wireless.com/jp/products/TWE-APPS/App_Twelite/step3-81.html)を参考に35バイト目が0か1かで圧力センサの状態を判断しています
* 改行コードを検知したら，TWELITEの電文として`handleTweliteLine()`で状態の確認とGoogle Homeへの読み上げ要求を出しています

実行して（YouTubeの動画のように）Google Homeを圧力センサに載せる・除けるをすると，次のような出力になります．

```shell
$ export GOOGLE_HOME_NAME="<Google Homeの名前>"
$ export GOOGLE_HOME_IP="<Google HomeのIP>"
$ export TWELITE_PORT="/dev/<TWELITEのTTYデバイス名>"
$ node index.js
port opened
state changed 1
state changed 0
state changed 1
盗まれた！
Device notified
```

Fritzingで作成した回路図も含め，以下にコード等を置いています．

[ottijp/google-home-shout](https://github.com/ottijp/google-home-shout)

## やってみて

盗難されるときは電源抜かれるんだから意味ないよね・・・😝