ラズパイを使ってWebUIからSwitchBotを操作する

# 1. やったこと

[SwitchBot](https://www.switchbot.jp/bot?lang=ja)を買いました。
スマホアプリから物理スイッチを押してくれる、Home IoTには欠かせないパーツです！
[Hub](https://www.switchbot.jp/hub-mini?lang=ja)を買ってもいいけど、ラズパイがあるのだからせっかくならラズパイから操作したい。
そして、WebUIを出して家の中からスマホで操作できるようにしたい。
というわけで、やってみました。

# 2. 必要なもの

* [SwitchBot](https://www.switchbot.jp/bot?lang=ja) Amazonで購入。キャンペーン期間中でちょっと安くなっていました(3,180円)
* Raspberry Pi。我が家のは3B
* Python3 (もし入っていなかったらインストールしておいてください。[参考](https://okashimoze.jp/blog/raspberry-pi/385.html))

# 3. 手順

## 3-1. ラズパイのコマンドラインからSwitchBotを操作する

公式のライブラリがあるので、それを使うだけです。
自分は以下のページを参考にさせていただきました。

[Raspberry Pi + SwitchBotで風呂を沸かす](https://raspi.taneyats.com/entry/switch-bot-for-furo)

軽く手順を書いておきます

### 3-1-1. Pythonの確認

※この通りのバージョンでなくても大丈夫

```shell
$ python --version
Python 2.7.16

$ python3 --version
Python 3.7.3
```

### 3-1-2. OpenWonderLabs/python-hostのクローン

```shell
$ mkdir switchbot
$ cd switchbot
$ git clone https://github.com/OpenWonderLabs/python-host.git
```

### 3-1-3. 各種ツールのインストール

gattlibのインストールで躓くことがあるようです。
[風呂を沸かす](https://raspi.taneyats.com/entry/switch-bot-for-furo)のページに解決方法も書いてあります。
自分は大丈夫、友人は引っかかった。

```shell
$ sudo apt-get install python3-pip libboost-python-dev libboost-thread-dev
$ sudo apt-get install libbluetooth-dev # READMEにはないがこれも必要
$ sudo pip3 install pybluez
$ sudo pip3 install gattlib
```

### 3-1-4. SwitchBotを探す

python-host付属のツール ```switchbot_py3.py``` で探します
```XX:XX:XX:XX:XX:XX```の部分にあなたのSwitchBotのBLE MACが入ります。メモしておきましょう。

```shell
$ sudo python3 switchbot_py3.py --scan
Scanning for bluetooth low-energy devices
Discovering Switchbot services
 * Found Switchbot service on device XX:XX:XX:XX:XX:XX handle 22
Found 1 devices: ['XX:XX:XX:XX:XX:XX']
Enter the number of the device you want to control:
        0       XX:XX:XX:XX:XX:XX
0
Connected!
Command execution successful
```

### 3-1-5. SwitchBotでボタンを押す

```XX:XX:XX:XX:XX:XX```の部分にメモったBLE MACを入れましょう。

```shell
$ sudo python3 switchbot_py3.py --device XX:XX:XX:XX:XX:XX Press
Connected!
Command execution successful
```

お、動いた！

## 3-2. WebUIを作る

node.js + express でさくっと作ります。
まずは Hello World を出してみましょう。

### 3-2-1. node.js/npmのインストール

すでにインストールしてあればこの作業は不要です

```shell
sudo apt-get update
sudo apt-get install -y nodejs npm
sudo npm cache clean
sudo npm install n -g
sudo -E n stable
sudo ln -sf /usr/local/bin/node /usr/bin/node
sudo apt-get purge -y nodejs npm
sudo apt -y autoremove
sudo npm install require
```

### 3-2-2. フロントエンドを作る

コマンド一発

```shell
pi@raspberrypi:~/switchbot/frontend $ npm init -y
Wrote to /home/pi/switchbot/frontend/package.json:

{
  "name": "frontend",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

pi@raspberrypi:~/switchbot/frontend $ ls
package.json
```

### 3-2-3. npmモジュールのインストール

expressをインストールします

```shell
$ npm install express --save
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN frontend@1.0.0 No description
npm WARN frontend@1.0.0 No repository field.

+ express@4.17.1
added 50 packages from 37 contributors and audited 50 packages in 48.932s
found 0 vulnerabilities
```

### 3-2-4. app.jsとindex.htmlでHello World (静的ルーティング)

ここのページを参考にしました。
[Node.jsとExpressでローカルサーバーを構築する(2) ―Expressでルーティング―](https://qiita.com/koedamon/items/fb85c3eb32e7838f9d7c)

```shell
$ mkdir public
$ cd public
$ vi index.html
```

※index.htmlの内容です

```html
<!DOCTYPE html>
<html>
<head>
        <title>test</title>
</head>
<body>
        <h1>Hello World!</h1>
</body>
</html>
```

```shell
$ cd ..
$ vi app.js
```

※app.jsの内容です

```javascript
/**
 * /app.js
 */

const express = require('express')
const app = express();
const path = require('path')

const port = 8889;

app.listen(port, () => {
        console.log('Running at ' + port + '...');
});

app.use(express.static(path.join(__dirname, 'public')));

app.use((req, res) => {
        res.sendStatus(404);
});
```

### 3-2-5. サーバー起動 (Hello World)

```
$ node app.js
```

ブラウザから localhost:8889 にアクセス
スマホを家のLANにWi-Fi接続して、スマホのブラウザから接続できればOK!

恒久的に起動するときは ```nohup``` を利用します。

```shell
$ nohup node app.js &
```

止めたいときは ```ps``` でプロセスを探して ```kill``` で止めます

```shell
$ ps aux | grep node
pi        1105  0.0  3.9 150324 35644 ?        Sl   12:43   0:01 node app.js
$ kill 1105
```

## 3-3. SwitchBotとつなぐ

これはもう```app.js```と```index.html```を見てもらったほうが早いかと
execで 3-1-5 のコマンドを実行しているだけです。

```javascript
/**
 * /app.js
 */

const express = require('express');
const app = express();
const path = require('path');
const exec = require('child_process').exec;

const port = 8889;

app.listen(port, () => {
        console.log('Running at ' + port + '...');
});

// static page (top page)
app.use('/', express.static(path.join(__dirname, 'public')));

// press (これを追加)
app.get('/press', (req, res) => {
    exec('sudo python3 /home/pi/switchbot/python-host/switchbot_py3.py --device XX:XX:XX:XX:XX:XX Press', (err, stdout, stderr) => {
        if (err) { res.write(err); }
        res.end(stdout);
    });
});

// not found
app.use((req, res) => {
        res.sendStatus(404);
});

```

```html
<!DOCTYPE html>
<html>
<head>
        <title>Switchbot</title>
</head>
<body>
        <h1>Switchbot</h1>
        <a href='press'>スイッチを押す</a><br>
</body>
</html>
```

ラズパイからSwitchBotを動かせました！
これで何でもできるぞ～
Home IoTの第一歩です。

EOF