Raspberry Pi 3(ラズパイ)を使って温度を自動計測し、自動的にサーバ上(Docker python3+bottle+MySQL)にアップして閲覧する!

  • 67
    Like
  • 0
    Comment
More than 1 year has passed since last update.

はじめに

「優しいIT」という理念の基、ITコンサルタントをしている亀井亮介と申します!
主な仕事は要求分析・要件定義の上流工程から、開発のマネジメントまでしていますが、プライベートでウェブシステム開発をしています!
優しいIT活動の一環として「教育用ようにプログラミング可能なPCを安価に提供する」理念の「Raspberry Pi 3(通称ラズパイ)」 で製作したモノ・サービス・プログラムを紹介します!

今回は、ラズパイコンテスト2016に応募したDocker利用のサンプルを紹介します!
温度を1分ごとに自動計測し、Docker上のデータベース(MySQL)に登録し、ブラウザで温度を閲覧できるサンプルです!

Githubにファイルを上げているので、興味のある方は使ってくださいね!

目次

  1. 目的
  2. 準備
  3. 環境構築
  4. 動作確認
  5. 終わりに

1. 目的

1-1. Dockerを利用したウェブサーバ構築の提案

ラズパイ好きの方で
「電子工作は得意だけど、ネットに公開となるとよく分からない…」
という方も多いのではないでしょうか?

ラズパイにウェブサーバを構築することもできるのですが、アプリケーションサーバやら、データベースサーバやらインストールは面倒だし、煩わしいし、試みても動かなかった…
ウェブサーバ構築は、敷居が高いと思われているのでしょうか?

誰でもできるだけ簡単にウェブサーバ構築をできるように、コンテナ技術Dockerを利用して、少ない手間でウェブサーバ構築する事例を紹介します!

1-2. ラズパイにサーバを構築する際の課題

ラズパイのOSはLinux系OS"Raspbian"であるために、ウェブサーバのApacheやデータベースサーバのMySQLをインストールできますが、次のような課題もあります。

  1. 不具合が発生した時に何が原因か分からない。
  2. ウェブサーバやデータベースのインストールや設定が煩雑
  3. ウェブサーバやデータベースサーバの設定のやり直しがやりにくい

ラズパイ上にウェブサーバを構築する際の課題

  1. 不具合が発生した時に何が原因か分からない。
    電子工作をする場合、温度取得などのシステムとウェブサーバなどの仕組みを同じマシンに構築するため問題が発生した時に、問題の切り分けが難しいです。

  2. ウェブサーバやデータベースのインストールや設定が煩雑
    ウェブサーバApacheやデータベースサーバのMySQLなどをインストールすることはできますが、インストールや設定に手間がかかります。経験された方もいると思いますが、きちんとメモなどを取らないと、正しい設定がわからなくなったり、なんとなく動いている状態になります。

  3. ウェブサーバやデータベースサーバの設定のやり直しがやりにくい
    ウェブサーバやデータベースの設定をやり直したい場合、既存の環境に手を入れるために、動かなくなったらどうしようなどの不安が尽きません。

1-3. Dockerで解決!

  1. 不具合が発生した時に何が原因か分からない。
    Dockerはコンテナと呼ばれる技術を使っています。ラズパイ上に「仮想的なOS」を立ち上げます。アプリケーションコンテナ、データベースコンテナと明確に役割を分担し、ラズパイ本体のOSは温度センサ・湿度センサ・照度センサなどのハードウェアとの通信に特化します。
    不具合が発生した時に、原因を探る際に問題の切り分けがやりやすくなります!

  2. ウェブサーバやデータベースのインストールや設定が煩雑
    Dockerを利用すると、煩わしいミドルウェアのインストールから、難しい設定までが施されたイメージファイルを無料で利用できます!
    イメージファイルはオフィシャルのものから、細かくカスタマイズされたものもあり、プラモデルを組み立てるように組み合わせて使うことができます!

  3. ウェブサーバやデータベースサーバの設定のやり直しがやりにくい
    Dockerはインストールや設定を1つのファイルにまとめることが可能です。設定が間違えていたら、そのファイルを元に、別の環境で実験をします。もし、にっちもさっちもいかなくてもそのコンテんを捨ててしまい、うまくできている設定ファイルを再度呼び込みやり直しをすることが可能です。
    Dockerはイメージファイルを使えば、並列化(いつでもどこでも同じ環境を構築)することができるので、移植もスムーズに行えます!

1-4. Dockerをラズパイで利用する場合の課題

Dockerにも課題があります。
一般的なサーバはx86_64アーキテクチャであり、Docker Hubのイメージもほとんどがx86_64アーキテクチャのイメージです。Raspberry Piのarmv7lアーキテクチャのイメージが少なく、Raspberry Pi + Dockerの情報もまだ少ない状況です。

今回は、このような現状を踏まえ、Raspberry上でDockerを利用するための事例を紹介します!

1-5. 今回のサンプル

温度を定点観測し、データベースに記録し、ウェブサーバで閲覧します!

① ラズパイ本体側で、デジタル温度センサで取得します

ラズパイで温度取得

② 取得した温度はプログラムからAPIを通して、データベースに登録されます。

システム構成図

③ ウェブブラウザでは、データベースに登録された温度を表示することができます。

ブラウザ表示

これらは私のGithub上に置いてあり、比較的簡単な手順で、構築することができます。これがDockerの利点の一つです。

環境構築は「3. 環境を構築」で解説します!

2. 準備

DockerとGitがインストールされていない方は下記の記事をご覧ください。
RaspberryPi3(ラズパイ)にDockerとGitをインストール

3. 環境構築

早速、Dockerを利用して、アプリケーションコンテナ、データベースコンテナ、データコンテナを構築します!

詳細は下記記事をご覧ください!
RaspberryPi3(ラズパイ)にDockerでPython+bottle+MySQL環境構築する!【簡単構築編】

動画版もあります!
動いている様子

3-1. 構築手順

gitでクローンしファイルをダウンロード
$ git clone git@github.com:RyosukeKamei/rpi-python-bottle.git

※パスワードを求められたら、rsaキーを作成した時のパスワードを入力

クローンされたフォルダに移動
$ cd rpi-python-bottle
docker-composeでデータコンテナとデータベースコンテナをビルドし起動
$ docker-compose up -d

※私の環境で3分くらいでした。

イメージを確認
$ docker images
コンテナを確認
$ docker ps -a
データベースコンテナにログイン
$ docker exec -it rpi-python-bottle-db bash
サンプルのテーブルとデータを入力
# mysql -u bottle -pbottle measurement < /docker-entrypoint-initdb.d/create_table.sql

※SQLはサンプルのテーブルとデータを入力しています。

データーベースコンテナをログアウト
# (Contrl + p, Control + q)

※ exitを使うとコンテナも止めてしまいますので注意してください。

アプリケーションコンテナをビルド
$ docker build -t hypriot/rpi-python .

※私の環境で1時間くらいかかりました。のんびり待ちましょう

アプリケーションコンテナを起動しログイン
$ docker run --name rpi-python-bottle-app -it hypriot/rpi-python bash
サーバを起動
# /usr/local/bin/python3 /home/bottle/server.py

ブラウザで開くと、下記のように表示されます。
ブラウザで確認

3-2. フォルダ構成

git cloneすると次のようなフォルダ構成になります!

フォルダ構成

3-3. /app/server.py

データベースに登録された温度データと、データ登録用のAPIです。

@route('/list')
温度データをSQLのSELECT文で取得し、一覧表示します。

@route('/input_temperature')
温度データを受け取り、SQLのINSERT文を生成し登録します。
形式例:
http://172.17.0.4:8080/input_temperature?server_id=1&temperature=29&user_id=1

server_id : サーバのID(サンプルでは固定値。今後の拡張性を考慮)
temperature : 温度センサで取得した温度
user_id : ユーザID(サンプルでは固定値。今後の拡張性を考慮)

詳細は#で始まるコメントに記載をしています。

/app/server.py
# bottleのライブラリ
from bottle import route, run, request

# MySQLドライバはmysql.connector
import mysql.connector

# 補足
# 本当はテンプレートを入れるとHTMLが綺麗になります。
# その辺は後日…

# hostのIPアドレスは、$ docker inspect {データベースのコンテナ名}で調べる
# MySQLのユーザやパスワード、データベースはdocker-compose.ymlで設定したもの
# user     : MYSQL_USER
# password : MYSQL_PASSWORD
# database : MYSQL_DATABASE
connector = mysql.connector.connect (
            user     = 'bottle',
            password = 'bottle',
            host     = '172.17.0.3',
            database = 'measurement'
)



@route('/list')
def list():
    # 温度を表示
    cursor = connector.cursor()
    cursor.execute("select `id`, `temperature`, `careted_at` from temperatures")

    disp  = "<table>"
    # ヘッダー
    disp += "<tr><th>ID</th><th>温度</th><th>登録日</th></tr>"

    # 一覧部分
    for row in cursor.fetchall():
        disp += "<tr><td>" + str(row[0]) + "</td><td>" + str(row[1]) + "</td><td>" + str(row[2]) + "</td></tr>"

    disp += "</table>"

    cursor.close

    return "DBから取得 "+disp

@route('/input_temperature')
def input_temperature():
    # 温度を入力
    cursor = connector.cursor()
    cursor.execute("INSERT INTO `temperatures` (`server_id`, `temperature`, `careted_at`, `careted_user`, `updated_at`, `updated_user`) VALUES (" + request.query.server_id + ", " + request.query.temperature + ", NOW(), " + request.query.user_id + ", NOW(), " + request.query.user_id + ")")

    # コミット
    connector.commit();

    cursor.close

    return "OK"


# コネクターをクローズ
connector.close

# サーバ起動
run(host='0.0.0.0', port=8080, debug=True, reloader=True)

3-4. digital_temperature_sensor_for_api.py

1分ごとに、温度センサから、I2C経由で温度を取得し、データ登録APIにアクセスします。

APIの値の例
http://172.17.0.4:8080/input_temperature?server_id=1&temperature=29&user_id=1

digital_temperature_sensor_for_api.py
# 準備
# $ sudo apt-get install libi2c-dev 
# $ sudo sh -c 'echo "options i2c_bcm2708 combined=1" >> /etc/modprobe.d/i2c.conf'

# GPIOを制御するライブラリ
import wiringpi

# タイマーのライブラリ
import time

# I2Cデバイスからの読み取りに必要なライブラリを呼び出す
import os
import struct

# URLアクセス
import urllib.request

# I2Cのインスタンスを作成
wiringpi.wiringPiSetup()
i2c = wiringpi.I2C()

# I2Cの設定
# 通信する機器のI2Cアドレスを指定
temperture_dev = i2c.setup(0x48)

# 温度を16ビットのデータ取得
# その他めレジスタ0x03に設定
i2c.writeReg8(temperture_dev, 0x03, 0x80)

while True:
    # 温度センサーの2バイト分を読み取る
    temperture_data = struct.unpack('2B', os.read(temperture_dev, 2))

    # 値が2バイトずつ分かれるので1つにまとめる
    temperture = ( ( temperture_data[0] << 8 ) + temperture_data[1] )

    # 負の値の場合は数値を変換
    if ( temperture_data[0] >= 0x80 ):
        temperture = temperture - 65536

    # 取得した値を128で割って温度を算出
    temperture = temperture / 128

    # 温度表示
    print ( "温度 " , temperture , "C" )

    response = urllib.request.urlopen('http://172.17.0.4:8080/input_temperature?server_id=1&temperature=' + str(temperture) + '&user_id=1')
    data = response.read()

    print ( "サーバレスポンス : ", data )

    # 1分ごと
    time.sleep(60)

3-5. /docker/mysql/my.cnf

MySQLの日本語対応ファイルです。
実動的に設定するので、深い説明は省略します。

/docker/mysql/my.cnf
[mysqld]
innodb_strict_mode
innodb_file_format = Barracuda
innodb_file_per_table
innodb_large_prefix = 1
character-set-server=utf8mb4
skip-character-set-client-handshake
max_allowed_packet = 32m
skip-networking = 0

[client]
default-character-set=utf8mb4

3-6. docker-compose.yml

データベースコンテナとデータコンテナを一元管理します。

詳細は下記記事をご覧ください!
RaspberryPi3(ラズパイ)にDockerでPython+bottle+MySQL環境構築する!【簡単構築編】

3-7. Dockerfile

アプリケーションコンテナの設定ファイルです。

こちらも詳細は下記記事をご覧ください!
RaspberryPi3(ラズパイ)にDockerでPython+bottle+MySQL環境構築する!【簡単構築編】

3-8. /initdb.d/create_table.sql

テーブル定義と、動作確認用の初期データを登録するSQLです。
構築時に、コマンドを使い実行しています。

/initdb.d/create_table.sql
USE measurement;

CREATE TABLE `temperatures` (
  `id`           int(11) NOT NULL AUTO_INCREMENT,
  `server_id`    int(11) NOT NULL,
  `temperature`  int(11) NOT NULL,
  `careted_at`   datetime NOT NULL,
  `careted_user` int(11) NOT NULL,
  `updated_at`   datetime NOT NULL,
  `updated_user` int(11) NOT NULL,
  KEY `id` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `temperatures` 
  (`id`, `server_id`, `temperature`, `careted_at`, `careted_user`, `updated_at`, `updated_user`) 
  VALUES 
  (1, 1, 29, NOW(), 1, NOW(), 1);

3-9. README.md

Gitで自動生成されるREADMEファイルです。
動作には関係ありません。
(もう少し丁寧に書くと良いのですが…)

3-10. /vim/python.vim

アプリケーションコンテナでvimを利用するときに、Pythonを書くために便利な設定をしています。
こちらもアプリケーションのイメージを作成時に自動的にビルドしています。

3-11. 回路図

デジタル温度センサで温度取得

4. 動作確認

いよいよ動作確認です。

4-1. ラズパイ本体側で、温度をデジタル温度センサで取得

ラズパイで、git cloneで作成されたフォルダに"digital_temperature_sensor_for_api.py"というファイルがあるので起動します。

温度を取得する
$ cd {git cloneしたフォルダ}/rpi-python-bottle
$ sudo python3 digital_temperature_sensor_for_api.py

次のように温度が取得されます(画像には引数がついているのですが、無視されています)。
ラズパイで温度取得

取得した温度はプログラムからAPIを通して、データベースに登録されます。

システム構成図

4-2. ウェブブラウザでは、データベースに登録された温度を表示

ラズパイのブラウザで"http://172.17.0.4:8080/list"にアクセスすると、次のような表示を確認することが可能です!

ブラウザ表示

/vim/python.vim
setl expandtab
setl tabstop=4
setl shiftwidth=4
setl softtabstop=0
autocmd BufWritePre * :%s/\s\+$//ge
setlocal textwidth=80

5. 終わりに

今回は温度センサを利用しましたが、明るさを測る照度センサ、湿度を測る湿度センサを使えば、照度・湿度を測ることが可能です!

遠隔地から、温度・照度・湿度を見たいというニーズがあればこれで対応できますね!
これ以外にも何か役に立ちそうなことがあれば応用したいと考えています!

サイトマップ

Raspberry Pi 3 (ラズパイ)セットアップ

Raspberry Pi 3インストール→無線LAN→日本語入出力→Macから操作

Raspberry Pi 3 にDockerを乗せてPython+MySQL環境を構築!

RaspberryPi3(ラズパイ)にDockerをインストール
RaspberryPi3(ラズパイ)にDockerでPython+bottle+MySQL環境構築する!【簡単構築編】
RaspberryPi3(ラズパイ)にDockerでPython+bottle+MySQL環境構築する!【試行錯誤編】

Raspberry Pi 3でエアコン一体型パソコン「airpi」を作る!

Raspberry Pi 3でエアコン一体型パソコン「airpi」を作る!

ついに…Raspberry Pi 3でpythonを使いラジコンを作る!

ボタン押している間モーターが動く
磁石を近づけている間モータが動く
磁石を近づけるとモータが動き、自動で止まる

Raspberry Pi 3 (ラズパイ)とpythonで遊ぼう ラズパイ奮闘の記録

Raspberry Pi 3でプログラミングをする Node-REDと普通にプログラミング
Raspberry Pi 3でpythonを使いLEDを光らせる(Hello World)
Raspberry Pi 3でスイッチの状態を検出する
Raspberry Pi 3でpythonを使いサーボモータを動かす
Raspberry Pi 3でpythonを使いモータードライバーを使いモータを制御する!
Raspberry Pi 3でpythonを使いスライドスイッチを検出する!
Raspberry Pi 3でpythonを使い磁石スイッチを検出する!
Raspberry Pi 3でpythonを使い温度を検出する!
Raspberry Pi 3でpythonを使いブザーを鳴らす!
Raspberry Pi 3でpythonを使いA/Dコンバーターでアナログ信号を検出する!
Raspberry Pi 3でpythonを使い「明るさ」を検出する!
Raspberry Pi 3でpythonを使い「温度(A/Dコンバーターを利用)」を検出する!
Raspberry Pi 3でpythonを使い「7セグメントLED」に出力する!
Raspberry Pi 3でpythonを使いスイッチ制御でLEDを光らせる!
Raspberry Pi 3でpythonを使い暗くなったらLEDを光らせる!

テスト駆動開発を重点においた規則

コーディング規則「優しいコードを書こう」(FuelPHP)
命名規則「3ヶ月後の自分自身に優しく、チームに優しく、まだ見ぬメンバーに優しく」

Docker+PythonでWebアプリケーション開発

Docker上のCentOSにPython3と、関連ライブラリpip, virtualenvとフレームワークDjango, bottle, Flaskのインストール!これらをまとめたDockerfile付き!

開発しやすい環境構築(Docker+PHP)

Dockerを利用しApacheにPHP環境 + Eclipseを連携
Dockerを利用したFuelPHP開発環境構築
Docker利用したFuelPHP開発環境の初期設定とscaffoldを利用してCRUDスケルトン作成
FuelPHPのデータベースマイグレーション