# スマホから猫と遊ぶ技術
## これを作りたい
HPにボタンを設置し、オフィスのラズパイに信号を送り、サーボを制御するというものです。
https://www.youtube.com/watch?v=UA4ztZSOPIw

## 手法の検討
### 通信手段の検討
HPから社内LANにつながるラズパイにアクセスするには、何かしらの通信をする必要があります。
WEBサイトの通信というと、HTTP/HTTPS通信、websocket通信などが挙げられます。
* HTTP/HTTPS通信
webサーバとブラウザ間でよく使われている通信です。HTTPSの方は、暗号化されてよりセキュアな通信ができます。
* WebSocket通信
HTTP通信を簡略化した通信です。HTTPよりも低コストでの通信が可能です。
以上2つの通信方法を検討しましたが、HPを作成したWiXというツールではWebSocketもHTTPも非対応であったあため、**HTTPS通信を採用**しました。
WiXではWebSocketの使用を想定されておらず、HTTPはセキュリティ上の都合でNG、とのことでした。
### 通信経路の検討
以下のようなシステムにて構築します。
||
|:-:|
ユーサがLefixeaのHPにアクセスし、「点灯」ボタンを押すとHTTPS通信で信号がインターネット経由でLefixea社内に到達します。信号を受けたモデムはラズパイに受け渡し、ラズパイが信号を検出するとライトを点灯させるしくみです。
</br>
</br>
## ラズパイwebサーバの構築
クライアントであるユーザのPCに表示されたホームページからの信号に応答するためには、何かしらのWEBサーバを設置する必要があります。例えばGoogleのサービスもWEBサーバとのやりとりによって成立しています。今回も例外ではなく、HPからの点灯ボタンに応答する処理を行うWEBサーバが必要です。
サーバの設置場所としては
1. ラズパイがあるLAN内に設置する方法
2. ラズパイ自体をWEBサーバとしてしまう方法
の2種類を検討しました。今回はただ単にラズパイのGPIOを操作するだけのため負荷は軽いだろうと考え、ラズパイ自体をWEBサーバとしてしまう方法を採りました。
### ラズパイにwebサーバ設置
WEBサーバ構築には、apache2を用います。オープンソースの有名なWEBサーバーソフトです。
||
|:-:|
```
$ sudo apt-get update
$ sudo apt-get upgrade -y
$ sudo apt-get install apache2
```
apacheのインストールが完了したら、WEBサーバ構築完了!
同じLAN内にあるPCなどから、ブラウザで
192.168.x.x(ラズパイのIP)
を入力してapacheサーバにアクセスしてみましょう。IPは、
`$ ifconfig`
の「inet」の192.168.~~の項目です。私は192.168.1.25に固定しています。
apacheの導入が成功していれば、「It works!」と表示されます。

続いて、サーバーサイドでよく使われる言語であるPHPをインストールします。
`$ sudo apt-get install php7.1`
続いて、apacheでphpを使えるように設定します。
`sudo nano /etc/apache2/mods-available/mime.conf`
で開いて、以下3行を追記します。
> AddType application/x-httpd-php .php
> AddType application/x-httpd-php-source .phps
> :
> :
> AddHandler cgi-script .cgi .php
`$ sudo nano /var/www/html/index.php`
に以下のphpプログラムを記入します。
```
<?php
phpinfo();
?>
```
apache2を再起動します。
`systemctl reload apache2`
ブラウザから
http://192.168.1.25/index.php
にアクセスし、

こんな表示が出たら成功です。
</br>
</br>
## プログラムの配置
次に、実際に動作するプログラム類を作成、配置していきます。
### HP側のHTMLファイル
HPに配置するボタンを作成します。
ボタンを押すと、「neko」というデータがPOSTでactionの宛先(ラズパイWEBサーバ)に送信されます。
```html
<html>
<body>
<form method="POST" action="https://lefipi.hopto.org/sample.php">
<input type="hidden" name="text1" value=neko>
<input type="submit" name="btn1" value="ねこじゃらしボタン">
</form>
</body>
</html>
```

こんな感じの表示になります。
### サーバ側のPHPファイル
ねこじゃらしボタンから送信されたデータを受け取り、ねこじゃらしを動かすためのpythonコマンドを実行します。
データを受け取ってpythonを実行したあとは、ボタンを再度表示させるためにHTML形式でprintしています。これで、何度でもボタンを押せるようになります。
/var/www/html/sample.php
```php
<?php
$input_data = (int)$_POST['text1'];
if ($input_data == neko){
$command='sudo /usr/bin/python /home/pi/Documents/servo.py';
exec($command,$output,$state);//コマンド実行
print('<form method="POST" action="https://lefipi.hopto.org/sample.php">');
print('<input type="hidden" name="text1" value=neko>');
print('<input type="submit" name="btn1" value="ねこじゃらしボタン">');
print('</form>');
}
else{
}
a?>
```
### サーバ側のpythonファイル
pythonファイルを作成します。自動ねこじゃらしはこのpythonファイルを用いて動作させます。
サーボを1回振るだけの単純なプログラムです。
/home/pi/Documents/servo.py
```python
import RPi.GPIO as GPIO
import time
def servo_move():
PIN = 21
GPIO.setmode(GPIO.BCM)
GPIO.setup(PIN, GPIO.OUT)
servo = GPIO.PWM(PIN, 50) # GPIO.PWM(PIN, [周波数(Hz)])
val = [2.5,3.6875,4.875,6.0625,7.25,8.4375,9.625,10.8125,12]
# サーボ動かすプログラム
servo.start(0.0)
servo.ChangeDutyCycle(val[0])
time.sleep(0.5)
servo.ChangeDutyCycle(val[3])
time.sleep(0.5)
servo.ChangeDutyCycle(val[0])
time.sleep(0.5)
servo.stop(0.0)
if __name__ == "__main__":
servo_move()
```
</br>
## ネットワーク環境の整備
通信のためのネットワーク設定を行っていきます。
### DDNSサービスを利用してグローバルIPが変化してもOKな状態にする
まずは、DDNSサービスを用いてグローバルIPが変化してもドメインと紐いてくれるように設定します。
#### 説明
少し説明します。
IPアドレスには「グローバルIP」と「プライベートIP」の2種類があります。
グローバルIPはインターネット上でのIPで、プライベートIPはLAN内でのIPです。
回線契約時に「固定IP」サービスに加入していない場合(普通は加入しない)、グローバルIPが度々変化します。グローバルIPはインターネット上からサーバの場所を特定するために必要な情報ですので、グローバルIPが変化するとサーバの場所を特定できなくなります。つまり、ラズパイWEBサーバーにアクセスできなくなります。
IP固定サービスに加入してIPを固定してもいいのですが、月額500~1000円程度かかります。
そこで、DDNSサービスを利用することでグローバルIPが変化してもDDNSに登録したドメインに紐付けてくれるのです。
DDNSサービスは色々ありますが、今回はNO-IPというサービスを利用しました。無料ですが、月1回NO-IPにサインインしないとIP紐付機能を停止されます。無料なので仕方ないです。
#### 利用手順
NO-IPのサイトにて、アカウント作成(Sign Up)を行います。
その後メールが届きますので、アカウントを有効化してください。
https://www.noip.com/

ラズパイにnoipディレクトリを作成
`mkdir /home/pi/noip`
noipディレクトリに移動
`cd /home/pi/noip`
noipクライアントをダウンロード
`wget http://www.no-ip.com/client/linux/noip-duc-linux.tar.gz`
ダウンロードしたクライアントを解凍
`tar vzxf noip-duc-linux.tar.gz`
クライアントソフトの中に移動
`cd noip-2.1.9-1`
インストール
`sudo make`
設定
`sudo make install`
#### 自動起動の設定
```
$ sudo cp debian.noip2.sh /etc/init.d/noip2
$ sudo chmod +x /etc/init.d/noip2
$ sudo vi /etc/rc.lcal
以下の1行を追加します
/etc/init.d/noip2 start
```
#### 設定
```
$ sudo /etc/init.d/noip2 stop
$ sudo /usr/local/bin/noip2 -C # 再度設定
$ sudo /etc/init.d/noip2 start # 起動
```
#### 確認
`$ sudo /usr/local/bin/noip2 -S`
</br>
### HTTP→HTTPS化する
今のままでもWEBサーバとしての機能は発揮できるのですが、WiXと通信するにはもうひと手間加える必要があります。
WiXではhttp通信を用いるのはセキュリティの観点から推奨されていないため、HTTPS通信でWiXとラズパイの通信を行います。
HTTPS通信は暗号化された通信で、第三者はこの通信内容を見ることができません。一方HTTP通信は暗号化されておらず、簡単に通信内容を傍受できます。
現在HTTPサーバであるapacheサーバに、SSL証明書を発行してHTTPS化を行います。
HTTPS化は、
1. 自己署名証明書によるもの(オレオレ証明書)
2. 第三者認証局の証明書によるもの
があります。
1のオレオレ証明書は、SSL証明書を認証局から取得せずに、自分で証明書を発行する方法です。
2の第三者認証局を使ったほうがWEBサーバの信頼性が上がるのは言うまでもないですが、通常は料金がかかります。
ただし、認証局からの証明書発行にもグレードがあり、無料のものも存在します。
今回は、無料で利用できる認証局からのSSl証明書を用いてHTTPS化を行います。
#### Let’s EncryptでSSl取得
参考:https://www.miki-ie.com/network/raspberry-pi-certificate-ssl-lets-encrypt/
下記コマンドでパッケージをインストールし、
sudo apt-get install certbot
sudo apt-get install python-certbot-apache
下記コマンドでSSL証明書の取得を行います。
sudo certbot --apache
> Saving debug log to /var/log/letsencrypt/letsencrypt.log
> Plugins selected: Authenticator apache, Installer apache
>
> Which names would you like to activate HTTPS for?
> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
> 1: www.domain.com
> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
> Select the appropriate numbers separated by commas and/or spaces, or leave input
> blank to select all options shown (Enter 'c' to cancel): 1
> Obtaining a new certificate
> Deploying Certificate to VirtualHost /etc/apache2/sites-enabled/aaa.domain2-ssl.conf
> Created an SSL vhost at /etc/apache2/sites-available/domain2-le-ssl.conf
> Deploying Certificate to VirtualHost /etc/apache2/sites-available/domain2-le-ssl.conf
> Enabling available site: /etc/apache2/sites-available/domain2-le-ssl.conf
>
> Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
> 1: No redirect - Make no further changes to the webserver configuration.
> 2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
> new sites, or if you're confident your site works on HTTPS. You can undo this
> change by editing your web server's configuration.
> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
> Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2
> Redirecting vhost in /etc/apache2/sites-enabled/aaa.domain2.conf to ssl vhost in /etc/apache2/sites-enabled/aaa.domain2-ssl.conf
> Redirecting vhost in /etc/apache2/sites-enabled/domain2.conf to ssl vhost in /etc/apache2/sites-available/domain2-le-ssl.conf
>
> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
> Congratulations! You have successfully enabled https://aaa.domain.com and
> https://www.domain.com
>
> You should test your configuration at:
> https://www.ssllabs.com/ssltest/analyze.html?d=aaa.domain.com
> https://www.ssllabs.com/ssltest/analyze.html?d=www.domain.com
> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
>
> IMPORTANT NOTES:
> - Congratulations! Your certificate and chain have been saved at:
> /etc/letsencrypt/live/aaa.domain.com/fullchain.pem
> Your key file has been saved at:
> /etc/letsencrypt/live/aaa.domain.com/privkey.pem
> Your cert will expire on 2019-12-03. To obtain a new or tweaked
> version of this certificate in the future, simply run certbot again
> with the "certonly" option. To non-interactively renew *all* of
> your certificates, run "certbot renew"
> - If you like Certbot, please consider supporting our work by:
>
> Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
> Donating to EFF: https://eff.org/donate-le
エラーがでなければこれで完了です。
</br>
### ポート開放
ポート開放をして、LAN外からHPにアクセスできるようにします。
ルータによって設定方法が異なりますが、今回はNTTのモデム兼ルータのRX-600KIでのポート開放を行います。
192.168.1.1にアクセスし、ログインして管理画面を参照します。
「静的マスカレード設定」にて、編集ボタンを押します。
||
|:-:|
||
|:-:|
プロトコル:TCP
対象ポート:443
IPアドレス:(ラズパイのIP)
ポート:443
入力し、「設定」を押します。まだ終わりではありません。
||
|:-:|
この画面で先程入力した行のチェックを入れ、設定ボタンを押します。
これで設定完了です。
</br>
</br>
## 動作確認
HPにボタンを追加して、いざ動作テストです。
||
|:-:|
HTMLでボタンを埋め込み、

ボタンを押すと...ねこじゃらしが動きました!
↓で試せますので、皆さんもボタンを押してみてください。
https://www.lefixea.com/iot
</br>
## うまくできない時は
以下を確認してください。
**2重ルータになっていないこと**
確認方法:windowsPCのコマンドプロンプトで「tracert 8.8.8.8」と入力。先頭2行がプライベートIPであれば2重ルータになっている。
**ファイヤウォールでブロックされていないこと**
確認方法:ラズパイで「sudo ufw status」と打って443がALLOWになっているか確認。パッケージが見つからなければラズパイにファイヤウォールは入っていない。
**ポート開放ができていること**
確認方法:ポート開放確認サイトにてドメイン名orグローバルIPと、確認するポート番号(443)を入力。し、開放できれいるか確認。https://www.cman.jp/network/support/port.html
## おわりに
ラズパイでWEBサーバを構築して外出先からねこじゃらしを振ることができました。
このしくみを応用すれば、もっと面白そうなことができそうですね。
以上、スマホから猫と遊ぶ技術の解説を終了します。