はじめに
前回から大分時間が空いてしまいましたが、社内新卒LTで発表したラズパイとLaravelを使ったセンサーデータの可視化の続きを書きます。
前回のラズパイで部屋の見える化してみる、その1ではセンサーからデータの取得とcsvへの保存を行いました。
今回はLravelでAPI作ってデータベースにデータを保存までを書きます。
LaravelやMVCモデルについて詳しく解説というより、やったことを整理して残しておくためのメモ書きのつもりです。
手順
前回の記事を参照すると
- センサーからデータの取得&処理
- 液晶に表示
- csvに保存
- クラウドにデータを投げる
- DBに保存
- webページ上で表示
となっているので今回は4~5を実装していきます。
環境構築
研修でLaravelというものを初めて触ったのでLaravelでバックエンドを作っていきます。
基本的にVSCode の Remote - SSH機能を使ってConoha VPS上でLaravelの開発環境を用意する の説明どおりでLaravelの環境をセットアップし、マイグレーションまでできると思います。
作成したインスタンスのIPアドレスに接続するとLaravelのwelcomeページが表示されます。
データベースの設定
マイグレーション
温湿度センサーのデータを格納するためのDBを用意します。直接DBを叩くのではなくLaravelのmigration機能を使ってテーブルを作成します。
まず、次のコマンドでマイグレーションファイルを作成します。
php artisan make:migration create_sensors_table --create=sensors
database/migrations/
にマイグレーションファイルが生成されるのでpublic function up()
の中に以下のように追加します。
Schema::create('sensors', function (Blueprint $table) {
$table->increments('id');
$table->float('temperature');
$table->float('pressure');
$table->float('humidity');
$table->integer('sensor_id');
$table->timestamps();
});
php artisan migrate
コマンドでマイグレーションが実行されます。
MySQLにログインして確認してみます。
MariaDB [(none)]> use laravel;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
MariaDB [laravel]> show tables;
+-------------------+
| Tables_in_laravel |
+-------------------+
| failed_jobs |
| migrations |
| sensors |
| users |
+-------------------+
4 rows in set (0.00 sec)
MariaDB [laravel]> desc sensors;
+-------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| temperature | double(8,2) | NO | | NULL | |
| pressure | double(8,2) | NO | | NULL | |
| humidity | double(8,2) | NO | | NULL | |
| sensor_id | int(11) | NO | | NULL | |
| created_at | timestamp | YES | | NULL | |
| updated_at | timestamp | YES | | NULL | |
+-------------+------------------+------+-----+---------+----------------+
7 rows in set (0.00 sec)
Sensorsテーブルとカラムが追加されていることが確認できます。
モデルの作成
テーブルが作成されたのでLaravelからDBへアクセスできるようModelクラスを作成します。
以下のコマンドでモデルを作成します。
php artisan make:Sensor
appディレクトリにSensor.php
が作られるので、ファイルの中身をSensorsテーブルに合わせて次のように編集します。
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Sensor extends Model
{
protected $fillable = [
'temperature',
'pressure',
'humidity',
'sensor_id',
];
}
これでDBと連携してデータを保存できるようになりました。
LaravelではModelクラスを呼び出すことでDBへデータを挿入したり取り出したりすることができます。
初めて触ったときはこの辺の動きがよく分からず、とりあえずコピペして動かしたら動いた状態でした。
データを受け取るためのAPIを作る
今回はラズパイで収集したセンサーデータを受け取ってDBへ格納するだけなので、POSTで値を受け取る実装にします。
コントローラの作成
実際にデータを受け取ってモデルを操作するコントローラを作成します。
php artisan make:controller SensorController
app/Http/Controllers/SensorController.php
が作成されます。
このファイルにリクエストの処理を書きます。
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Sensor;
class SensorController extends Controller
{
public function store(Request $request)
{
$sensor = Sensor::create([
'temperature' => $request->input('temperature') ,
'pressure' => $request->input('pressure'),
'humidity' => $request->input('humidity'),
'sensor_id' => $request->input('sensor_id'),
]);
return response()->json($sensor, 201);
}
}
先程作ったModelクラスをuse App\Sensor;
で呼び出しています。
Sensor::create
でDBへ指定した値を保存しています。
理解してしまえばシンプルで扱いやすいなと思いました。
ルーティングを設定
APIのルーティングを設定します。
LaravelではAPIのルーティングはroutes/api.php
に書きます。
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
Route::middleware('api')->group(function () {
Route::post('sensors', 'SensorController@store');
});
ルーティングではリクエストのメソッド、URI、呼び出すコントローラーを指定します。
ここではメソッドがpost、URIはsensors、コントローラーはSensorController@storeを指定しています。
実際にAPIを叩くときはIPアドレス/api/sensors
にPOSTすることでapp/Http/Controllers/SensorController.php
のstoreメソッドが実行されます。
php artisan route:list
コマンドでルーティングを確認することができます。
php artisan route:list
+--------+----------+-------------+------+---------------------------------------------+------------+
| Domain | Method | URI | Name | Action | Middleware |
+--------+----------+-------------+------+---------------------------------------------+------------+
| | GET|HEAD | / | | Closure | web |
| | POST | api/sensors | | App\Http\Controllers\SensorController@store | api |
+--------+----------+-------------+------+---------------------------------------------+------------+
POSTしてみる
ここまででAPIはできたのでラズパイからPOSTできるか確認してみます。
確認のために簡単なプログラムを書きました。
import time
import random
import json
import urllib.request
url = `http://YourIPAddress/api/sensors`
def post_data(temp, press, hum):
data = {
'temperature' : temp,
'pressure' : press,
'humidity' : hum,
'sensor_id' : 6,
}
headers = {
'Content-Type': 'application/json',
}
req = urllib.request.Request(url, json.dumps(data).encode(), headers)
try: urllib.request.urlopen(req)
except urllib.error.URLError as e:
print(e.reason)
while True:
temp = random.uniform(10, 30)
press = random.uniform(980, 1010)
hum = random.uniform(50, 80)
post_data(temp, press, hum)
print("temp={0}, press={1}, hum={2}".format(temp, press, hum))
time.sleep(1)
POSTリクエストはurllibを使って投げるようにします。
ここではPythonのrandom関数を使ってセンサーの値を擬似的に生成して1秒間隔で送信するようにしました。
MySQLにログインして実際にPOSTできたことを確認します。
ここまで実装できると、前回の記事のセンサーデータの取得と組み合わせたらいい感じに表示できそうな気がしてきますね!
終わりに
今回はCONOHA上にインスタンスを立ててLaravelでAPIを作成からデータをPOSTしてDBへ保存するところまでを実装しました。
本当はデータの表示まで書きたかったのですが思ったより長くなったので次回に書こうと思います。
フロントエンド?知らない子ですね。。。