LoginSignup
10
7

More than 3 years have passed since last update.

ラズパイ初心者がRaspberrypiZeroWHを使ってLINEで動くスマートロックを作ってみた(サーバー構築編1)

Posted at

概要

賃貸のスマートホーム化をしたい!!!

と思い、「まずは家に入るところから」とスマートロックの購入を検討したところ、安くても10000円以上・・・
僕はこう感じた

あんな鍵回すだけの機械になんで10000円も払わなあかんねん!!!!
こんなんなら自分で作ったるわ!!!

元からラズパイを触りたかったということもあって、勢いでRaspberrypiZeroWHを購入。
せっかくラズパイを使うなら、なにかサーバーを立てて操作したいと思った。
過去にLINEbotを作ったという経験もあり、LINEbotで操作できるスマートロックを作ることとした。

今回の記事はLINEで動くスマートロック制作のためのサーバー構築編1。
ラズパイのセットアップからラズパイ本体にWebサーバーを構築、https通信でHelloWorldするところまで書いていく。

ただのメモなので再現性はないかも。参考程度に。

筆者のスキル

  • 研究でnumpyやpandasを使ったデータ解析をしていた
  • サーバー関係はEC2を使ってApacheでWebサーバーを構築できるレベル(ほぼ初心者)
  • Herokuを使ってLINEbotを作ったことがある
  • ラズパイ経験はなし
  • 電気回路系は何もわからない

今回使うスキル

  • Linuxの基本操作
  • Flask
  • uwsgi
  • nginx
  • Docker、Docker-compose
  • line-bot-sdk

必要なもの

  • RaspberrypiZeroWH
  • ラズパイの電源ケーブル
  • サーボモーター(SG92R)
  • ジャンパワイヤー3本

開発環境

  • Windows10

OSのインストール・SSH通信

宅配ボックスにRaspberrypiが、届き、ワクワクしながら箱を開ける。
最初からSDカードにOSが入ってるとのことなので、早速起動して、いざセットアップ・・・!!

・・・ん・・・?

あ!!!!!!有線のキーボードがない!!!!!!!!!!!!!!なにも操作できないじゃんか!!!!!!!!!

どうしよう、さっそく調べる。
どうやらSDカードであらかじめWifiのセッティングファイルをぶち込んでラズパイを起動することで、何も操作せずともラズパイにSSH通信を許可することが出来るらしい。

というわけで、OSのインストール方法とSSH通信の方法を書いていく。

OSのインストール

RaspberryPiImagerを使うと便利。
こちらを参照

SSH通信でしか操作しないならGUIもいらないので、
RaspberryPiOS(other) → RaspberryPiOSLiteでOK
GUIが入ってない分かなり軽量。

SSH

こちらを参照

要約すると、OSの入っているSDカード直下に以下のファイルを作ればOK

ssh
(何も書かない)
wpa_supplicant.conf
country=JP
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
    ssid="WifiのSSID"
    psk="WifiのPW"
}

sshに「(何も書かない)」って書いちゃだめだよ!!

ファイルを生成し終えたら、RaspberrypiにSDカードをいれて早速起動!

5分くらい待ってから、自分のPCのコマンドプロンプトから以下のコマンドを実行
初期パスワードはraspberrypi

コマンドプロンプト
$ ssh pi@raspberrypi
pi@raspberrypi's password:(入力しても何も表示されないが、ちゃんと入力されてる)

色々表示されて、以下のような待ち受けになったら成功

コマンドプロンプト
pi@raspberrypi:~ $

Docker、Docker-composeをインストール

今まで使ったことなかったが、勉強のためにDockerを用いてサーバー構築することにした。
実際、使う必要もなかった気がするが・・・
ただ、また同じ環境を作りたくなった際、環境構築が楽になるかもしれない。

Dockerインストール

コマンドプロンプト
pi@raspberrypi:~ $ curl -sSL https://get.docker.com | sh

// グループの追加
pi@raspberrypi:~ $ sudo usermod -aG docker pi

// OS再起動(グループ追加を反映)
pi@raspberrypi:~ $ sudo shutdown -r now

// dockerサービスの有効化
pi@raspberrypi:~ $ sudo systemctl enable docker

// バージョン確認
pi@raspberrypi:~ $ docker --version
Docker version 20.10.5, build 55c4c88

Docker-composeインストール

githubにソースコードが落ちてるらしいので、そっちでインストールしたほうがいいと思うが、
pipでもインストールが可能らしく、個人的に使い慣れてるのでこちらを用いた。
ラズパイにvenv環境が最初から入っていたか覚えていないので、入っていなかったら各自インストールするように!

コマンドプロンプト
//venv環境の作成
pi@raspberrypi:~ $ python -m venv venv

//venv環境の中に入る
pi@raspberrypi:~ $ source venv/bin/activate

//pipのアップデート
(venv)pi@raspberrypi:~ $ pip install --upgrade pip

// docker-composeのインストール
(venv)pi@raspberrypi:~ $ pip install docker-compose

nginx+flaskでHTTP通信でHelloWorld!

docker-composeを用いてnginxサーバーとflaskサーバーをuwsgiを用いて繋げる

こちらを参照。

基本この記事のディレクトリ構成をパクればうまくいくはず。
あ、ただ、docker-composeは環境変数が設定されてないのでコマンド実行時は~/venv/bin/docker-composeと絶対パスor相対パスを指定しなければならないので注意。めんどくさい人は環境変数を設定してくれ!

ルーターのポートを開放してhttpリクエストを送信!

この記事の通りのディレクトリ構成にした後、自身のルーターのポート番号80番を開けて早速アクセス!
ルーターのポートの開け方は多分自身のルーターの説明書に書いてあるので、各自確認。

グローバルIPを確認したらブラウザに入力
http://グローバルIP

因みにグローバルIPアドレスはこのサイトで見れる。
https://www.cman.jp/network/support/go_access.cgi

2021-04-23.png

成功!

ドメイン、DDNS取得

こちらの記事を参照

お名前.comでドメインを取得し、グローバルIPと関連付ける。
.workドメインであれば年間1円で取得できるから実質タダ。

グローバルIPは時々刻々で変化してていくので、DDNSサービスを用いる必要がある。
DDNSサービスを用いれば変化するグローバルIPとドメインを関連付けることが出来る。
DDNSサービスにはmydnsを用いた。

お名前.comでドメイン取得し、mydnsで動的IPとドメインを関連付けたら早速アクセス
http://www.自分の登録したドメイン

先ほどと同様HelloWorld!が表示されたら成功!

https通信

主な流れは以下の通り

  1. SSL証明書発行前の準備(main.pyを少し改造)
  2. Let's encryptで証明書発行
  3. nginxの設定ファイルを編集してポート443番解放、.pemを関連付ける
  4. ymlファイルの.pemの位置をマウントしdocker-compose実行
  5. ルーターのポート443を開放し、ブラウザでhttpsアクセス

SSL証明書発行前の準備

main.pyに以下の項目を追加。
これを追加しなきゃ正しく証明書を発行できない。

main.py
from flask import Flask, render_template, request, abort

app = Flask(__name__)

@app.route("/")
def hello_world():
    return "hello world!"

############ ここを追加!! ###############################################
@app.route("/.well-known/acme-challenge/<filename>")
def well_known(filename):
    return render_template('.well-known/acme-challenge/'+ filename)
########################################################################

if __name__ == "__main__":
    app.run()

main.pyのファイルが入っているところにtemplate/.well-known/acme-challengeを作る

コマンドプロンプト
(venv)pi@raspberrypi:mkdir -p ~/app/template/.well-known/acme-challenge
(venv)pi@raspberrypi:touch ~/app/template/.well-known/acme-challenge/test.html

Let's encryptで証明書発行

コマンドプロンプト
(venv)pi@raspberrypi:sudo yum install certbot-apache
(venv)pi@raspberrypi:sudo certbot certonly

対話形式で指示に従って入力していく
How would you like to authenticate with the ACME CA?の質問に対してはwebrootの方を選択
あとはメアドとかドメインとか適当に。

/etc/letsencrypt/live/ドメイン名/ にpemファイル等が作成されてたら成功!

これをnginxディレクトリにコピー

コマンドプロンプト
(venv)pi@raspberrypi:mkdir ~/nginx/ssl
(venv)pi@raspberrypi:sudo cp /etc/letsencrypt/live/ドメイン名/fullchain.pem ~/nginx/ssl
(venv)pi@raspberrypi:sudo cp /etc/letsencrypt/live/ドメイン名/privkey.pem ~/nginx/ssl

nginxの設定ファイルを編集してポート443番解放、.pemを関連付ける

nginxの設定ファイルに以下の項目を追加

~/nginx/nginx.conf
user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    upstream uwsgi {
        server uwsgi:3031;
    }

    server {
        listen 80;
        charset utf-8;

        location / {
            include uwsgi_params;
            uwsgi_pass uwsgi;
        }
    }

    ##############ここを追加######################################
    server {
    listen 443 ssl;
    charset utf-8;
        location / {
            include uwsgi_params;
            uwsgi_pass uwsgi;
        }

    ssl_certificate       /etc/nginx/ssl/fullchain.pem;
    ssl_certificate_key   /etc/nginx/ssl/privkey.pem;
    }
    #############################################################
}

ymlファイルの.pemの位置をマウントしdocker-compose実行

ymlファイルに以下の項目を追加

~/docker-compose.yml
version: "3"
services:

  uwsgi:
    # ビルドするDockerfileのでディレクトリ相対パス
    build: ./app
    # 指定したパスをコンテナにマウントする。"ホストのパス:コンテナのパス"となる
    volumes:
      - ./app:/var/www/
    # 解放するポートを指定。"ホスト:コンテナ"のマッピング となる
    ports:
      - "3031:3031"
    # コンテナ内の環境変数を指定する
    environment:
      TZ: "Asia/Tokyo"

  nginx:
    build: ./nginx
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf
      # nginxのログをホストOSの /tmp/nginx_log に出力する
      - /tmp/nginx_log:/var/log/nginx
      ############ここを追加####################
      - ./nginx/ssl:/etc/nginx/ssl/
      #########################################
    links:
      - uwsgi
    ports:
      - "80:80"
      ################ここを追加################
      - "443:443"
      #########################################
    environment:
      TZ: "Asia/Tokyo"

ymlファイルの設定が完了したら、docker-composeを実行

コマンドプロンプト
//docker-composeを実行
(venv)pi@raspberrypi:~/venv/bin/docker-compose build && ~/venv/bin/docker-compose up -d
// 正しく実行されているか確認
(venv)pi@raspberrypi:~/venv/bin/docker-compose ps

ルーターのポート443を開放し、ブラウザでhttpsアクセス

自身のルーターの443ポートを開放。ルーターの説明書を参考に。
ブラウザでhttpsアクセスを試す
https://www.ドメイン名

HelloWorldが出力されたら成功!!!

疲れたので、今回はここまで!
次回はLINEとWebhookしてLINEbot作るよ!

10
7
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
10
7