Raspberry PiでIoT 温度・湿度・気圧データ編の2回目です。前回はRaspberry Piに温度・湿度・気圧データが測定出来るセンサモジュールのBME280を接続して値を取得しました。
以下が、Raspberry PiでIoT(温度・湿度・気圧データ編)の記事一覧です。
Raspberry PiでIoT(温度・湿度・気圧データ編 その1)BME280でデータ取得
Raspberry PiでIoT(温度・湿度・気圧データ編 その2)Webサーバ側構築とデータ送信
Raspberry PiでIoT(温度・湿度・気圧データ編 その3)データ表示とグラフ表示”
Raspberry PiでIoT(温度・湿度・気圧データ編 その4)アラートメール送信
今回は以下のデータ保存の流れで、右側のWebサーバ(データベース)の部分を構築します。そして、構築したサーバにセンサーデータを送信します。送信処理は以下のデータ保存の流れで左側です。ここでの私のサーバ環境は、レンタルサーバ上で、ウェブサーバ:Apache、データベース:MYSQL、開発言語:PHPです。今時であれば他にもいろいろと選択肢があるとは思いますがこれでやってみました。
データ保存の流れ
Raspberry Pi + センサー => インターネット => Webサーバ(データベース)
今回の作業手順は以下です。
1.データベースの構築(Webサーバ上)
2.PHPプログラムの作成(Webサーバ上)
3.Raspberry PiからPython単体テスト送信
4.Raspberry PiからセンサーデータをPythonで送信
5.ブラウザでデータ確認
6.cronでの自動実行
早速順番に書きます。但しですが、詳細の環境構築方法や、詳細のツールの使用法等は必ずしも書きませんので、実際に作業する場合はマニュアルサイト等を探してみて下さい。また、各プログラムは単なるテストプログラムです。動作保証は一切しておりません。
1.データベースの構築(Webサーバ上)
ここではMYSQLを使うので管理ツールは phpMyAdminです。以下のCreate文のテーブルを作成しました。
-- -- データベース: `indpsys_iot` -- テーブルの構造 `sensorvalues` -- CREATE TABLE `sensorvalues` ( `id` int(11) NOT NULL AUTO_INCREMENT, `datetime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, `temp` float NOT NULL, `hum` float NOT NULL, `press` float NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=316 ;
2.PHPプログラムの作成(Webサーバ上)
以下のプログラムを作成しました。
<?php $pdo = new PDO('mysql:host=localhost;dbname=dbname;charset=utf8','tablename','mypassword'); switch ($_SERVER['REQUEST_METHOD']) { case 'GET': $st = $pdo->query("SELECT * FROM sensorvalues"); echo json_encode($st->fetchAll(PDO::FETCH_ASSOC)); break; case 'POST': $in = json_decode(file_get_contents('php://input'), true); if (!isset($in['id'])) { $st = $pdo->prepare("INSERT INTO sensorvalues(datetime,temp,hum,press) VALUES(:datetime,:temp,:hum,:press)"); } $st->execute($in); echo json_encode("normal end"); break; } ?>
このプログラムをインターネット上でもローカル環境でもいいですが、Webサーバ上にアクセス出来るように配置します。処理としては、HTTPのGETとPOSTの処理を実装しています。
GETの場合は全レコードをJSON形式で返しています。POSTの場合は念のためidという項目が設定されていなかったら、追加レコードとしてINSERT文を実行します。
3.Raspberry PiからPython単体テスト送信
ここでの作業、処理は以下の太字の部分です。
データ保存の流れ
Raspberry Pi + センサー => インターネット => Webサーバ(データベース)
上記のPHPプログラムにRaspberry PiのPythonのプログラムからまずは単体テスト的にPOSTします。以下のPythonプログラムを使用します。
import requests import json from datetime import datetime def uploadSensorValues(temp, hum, press): url = 'http://yourdomain/subsub/sensvalues.php' sensorsdata = {'datetime':datetime.now().strftime("%Y/%m/%d %H:%M:%S"),'temp':temp,'hum':hum,'press':press} print json.dumps(sensorsdata) headers = {'content-type': 'application/json'} res = requests.post(url, data=json.dumps(sensorsdata), headers=headers, verify=False) print res.json() pass def main(): uploadSensorValues(21.8, 39.1, 1020) if __name__ == '__main__': main()
以下のように実行します。ここではweb.pyというファイル名で作成しています。
この場合は、main()が呼ばれるので、温度:21.8、湿度:39.1、気圧:1020というテストデータをjsonデータでPOSTしています。作成したjsonデータとレスポンスを画面に表示しています。
正常に終了すると、PHPからのレスポンスの normal end が表示されます。
データベース側を、phpMyAdminで確認します。以下のように確認出来ました。
4.Raspberry PiからセンサーデータをPythonで送信
いよいよ実際のセンサーデータを送信します。
まずは、前回のようにしっかりとbme280センサーモジュールを接続します。
前回のフォルダに上記のweb.pyを追加して、bme280Main.pyをbme280MyMain.pyに名称変更して、以下のファイル構成にします。(※すいません別にメインのファイル名は任意でいいです。好きなファイル名にして下さい。)
bme280MyMain.py
bme280_custom.py
web.py
ここでbme280MyMain.py(メイン)を以下のように編集します。
#coding: utf-8 import bme280_custom import datetime from web import uploadSensorValues #センサー値をカンマ区切りで取得 csv = bme280_custom.readData() list = csv.split(",") #カンマ区切りを別々の変数に格納 press = list[0] temp = list[1] hum = list[2] #それぞれを表示 print temp print hum print press #webへPOST uploadSensorValues(temp,hum,press);
以下のようにメインを実行します。sudo を忘れないで下さい。正常に処理出来れば、センサーの各値、normal endのレスポンスが確認出来ると思います。
5.ブラウザでデータ確認
実際に保存したデータをブラウザでも確認します。ブラウザで以下のようにPHPのURLを指定します。
http://youdomainOrIPAdress/subsub/sensvalues.php
確かに、値が確認出来ますが、JSON形式のテキストで表示されただけです。この表示の続き等は次回に書きます。
6.cronでの自動実行
センサーデータを送信するプログラムをcronを使って自動実行します。以下で自動実行を設定します。
$ sudo crontab -e
編集状態で以下を追記します。これでセンサー送信プログラムが1分おきに実行されます。
0-59/1 * * * * sudo python /home/pi/bme280/bme280MyMain.py
前項の方法でブラウザで結果を確認します。ここではデータが増えているなという程度に分かればいいです。次回にデータの一覧表示、グラフ表示を作成します。
技術要素についての補足と雑感等
今回のWebサーバ側構築とデータ送信では以下のような技術要素が出てきました。
Webプラットフォーム
LAMPと呼ばれている環境を使いました。Linux(OS)、Apache(Webサーバ)、MYSQL(RDBMS)、PHP(プログラミング言語)の組み合わせです。どうやら最近は、MYSQLの後継としてMariaDBが出てきているようです。この環境をとりあずローカル環境で構築するのであれば、XAMPPも選択肢の一つだと思います。
HTTP通信(TCP/IP)
まずは、TCP/IPとはインターネットの通信プロトコル(通信規約)のことです。以下の記事で少し書きましたが、大きな特徴として他の類似の通信プロトコル(osi参照モデルとよく比較されます)と同様に「階層構造」になっていることです。
Arduino Ethernetシールド(旧製品)を使ってみた
TCP/IPの階層構造は以下です。
アプリケーション層 – アプリケーションプロトコル(HTTP、FTP、SMTP等)
トランスポート層 – プログラム間通信、制御(TCP、UDP等)
ネットワーク層 – ネットワーク層(IP4、IP6等)
リンク層 – Ethernet、Wifi等
HTTPはWebブラウザでも利用されていますが、アプリケーションプロトコルの一つです。Raspberry PiからPythonプログラムでこのHTTPのPOSTメソッドを使ってセンサーデータを送信しました。
今回では使用していませんが、IoTでよく利用されるプロトコルにMQTTがあります。MQTTの特徴としてはシンプルで軽量なことです。どこかで取り上げたいと思っています。