ラズパイの見守りモニタを進化させたいんだけど…
Laravelからラズパイ MJPG Streamerにアクセスできるようにしてみよう。
プロコアラ@エンジニアブロガー
10年間エンジニアをしており、副業でWebサイトやWebサービスを作っています。
一時期資格取得にハマりTOEIC860点オーバー、応用情報処理は取得。休日はラズパイをいじるコアラ好きです。
Follow @top_pro_koala
Laravelからラズパイ上のMJPG Streamerにアクセスする方法を解説します。
Laravelから呼び出すことによって、同じ画面にボタンを作ったり取得したデータをグラフ化したりという拡張性が出てきます。
今回は、簡単に生まれてから何日経ったのかを表示したいと思います。
使用するもの
ラズパイ
Webカメラ
ルーター
ELECOMのルーターだとSkyLinkDNSという無料のDynamicDNSサービスが使えます。
今回はELECOM製のルーターを使用します。
ELECOM製のルーターを持っていないなら、ELECOMの直販サイトもオススメ。
定期的にアウトレットセールやってるので、下記サイトをチェックしてみてください!
Mixhostの設定
Mixhostで行う設定を記載します。
データベースの作成
MySQLデータベースを選択します。
データベースを作成します
名前は好きな名前にしてください
ユーザーの作成
ユーザーをデータベースに追加
サブドメインの作成
サブドメインを選択します。
サブドメインを作成します。
好きなドメインを作成してください。
Laravelプロジェクトの作成
Mixhostへファイルを格納するには、sshでmixhostにアクセスします。
一旦babycameraディレクトリを削除してLaravelプロジェクトを作成します。
cd public_html rm babycamera -rf composer create-project --prefer-dist laravel/laravel babycamera
.envファイルを修正します。
先ほど作成したデータベースを設定します。
DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=xeewwbpx_babycamera DB_USERNAME=xeewwbpx_babycamera DB_PASSWORD=YOUR_PASSWORD
ログイン認証を行うようにします。
ログインしていない場合はビデオが見えないようにしてセキュリティを強化します。
php artisan make:auth
ユーザーデータベースを作成します。
php artisan migrate
usersテーブルのシーダーを作成します。
今回のアプリでは登録画面は作らず、1つのIDとパスワードで管理します。
php artisan make:seeder UserSeeder
ファイルを修正します。
UserSeeder.phpを修正します。
<?php use Illuminate\Database\Seeder; class UserSeeder extends Seeder { /** * Run the database seeds. * * @return void */ public function run() { // $now = Carbon::now(); DB::table('users')->truncate(); DB::table('users')->insert([ [ 'name' => 'Taro', 'email' => 'dummy@gmail.com', 'password' => bcrypt('20190604'), ], ]); } }
DatabaseSeeder.phpからUserSeederを呼び出します。
class DatabaseSeeder extends Seeder { /** * Seed the application's database. * * @return void */ public function run() { $this->call(UserSeeder::class); } }
作成したシーダーを実行します。
php artisan db:seed
コントローラーの作成
コントローラー部分を作成します。
php artisan make:controller MainController
ルーターを修正
ルーターを修正します。
authのgroupで囲むことにより、ログイン中のユーザーしか表示されなくなります。
Route::group(['middleware' => 'auth'], function() { Route::get('/home', 'HomeController@index')->name('home'); Route::get('/', 'MainController@index'); }); Auth::routes();
日付を表示する
コントローラーの修正
誕生日は固定でコーディングしてます。
Carbonを使用することで簡単に日付を計算できます。
日付計算した変数をcompactでviewsに渡しています。
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Carbon\Carbon; class MainController extends Controller { public function index () { $birthday = new Carbon('2019-06-04'); $today = Carbon::today(); $elapsed_days = $today->diffInDays($birthday); $today = $today->format('Y年m月d日'); return view('welcome', compact('today', 'elapsed_days')); } }
日本時間にするため、config/app.phpを修正します。
'timezone' => 'Asia/Tokyo',
ログインをemailではなくユーザー名に変更する
LoginController.phpを修正。下記関数を追加。
public function username() { return 'name'; }
ログイン画面を修正します。
login.blade.phpを修正します。
emailの箇所をnameにします。英語を日本語にしています。
@extends('layouts.app') @section('content') <div class="container"> <div class="row justify-content-center"> <div class="col-md-8"> <div class="card"> <div class="card-header">ログイン</div> <div class="card-body"> <form method="POST" action="{{ route('login') }}"> {{ csrf_field() }} <div class="form-group row"> <label for="name" class="col-md-4 col-form-label text-md-right">ユーザー名</label> <div class="col-md-6"> <input id="name" type="name" class="form-control @error('name') is-invalid @enderror" name="name" value="{{ old('name') }}" required autocomplete="name" autofocus> </div> </div> <div class="form-group row"> <label for="password" class="col-md-4 col-form-label text-md-right">パスワード</label> <div class="col-md-6"> <input id="password" type="password" class="form-control @error('password') is-invalid @enderror" name="password" required autocomplete="current-password"> </div> </div> <div class="form-group row"> <div class="col-md-6 offset-md-4"> <div class="form-check"> <input class="form-check-input" type="checkbox" name="remember" id="remember" {{ old('remember') ? 'checked' : '' }}> <label class="form-check-label" for="remember"> ログイン情報を保存する </label> </div> </div> </div> <div class="form-group row mb-0"> <div class="col-md-8 offset-md-4"> <button type="submit" class="btn btn-primary"> ログイン </button> <!-- @if (Route::has('password.request')) <a class="btn btn-link" href="{{ route('password.request') }}"> {{ __('Forgot Your Password?') }} </a> @endif --> </div> </div> </form> </div> </div> </div> </div> </div> @endsection
viewの表示を修正
共通部分のレイアウトであるlayoutsにあるapp.blade.phpを修正します。
<!DOCTYPE html> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <!-- CSRF Token --> <meta name="csrf-token" content="{{ csrf_token() }}"> <title>{{ config('app.name', 'BABY CAMERA') }}</title> <!-- Scripts --> <script src="{{ asset('js/app.js') }}" defer></script> <!-- Fonts --> <link rel="dns-prefetch" href="//fonts.gstatic.com"> <link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet"> <!-- Styles --> <link href="{{ asset('css/app.css') }}" rel="stylesheet"> <link href="https://fonts.googleapis.com/css?family=Nunito:200,600" rel="stylesheet"> </head> <body> <div id="app"> <nav class="navbar navbar-expand-md navbar-light bg-white shadow-sm"> <div class="container"> <a class="navbar-brand" href="{{ url('/') }}"> BABY CAMERA </a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="{{ __('Toggle navigation') }}"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <ul class="navbar-nav mr-auto"> </ul> <ul class="navbar-nav ml-auto"> @guest <li class="nav-item"> <a class="nav-link" href="{{ route('login') }}">ログイン</a> </li> <!-- @if (Route::has('register')) <li class="nav-item"> <a class="nav-link" href="{{ route('register') }}">{{ __('Register') }}</a> </li> @endif --> @else <li class="nav-item dropdown"> <a id="navbarDropdown" class="nav-link dropdown-toggle" href="#" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" v-pre> {{ Auth::user()->name }} <span class="caret"></span> </a> <div class="dropdown-menu dropdown-menu-right" aria-labelledby="navbarDropdown"> <a class="dropdown-item" href="{{ route('logout') }}" onclick="event.preventDefault(); document.getElementById('logout-form').submit();"> ログアウト </a> <form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;"> @csrf </form> </div> </li> @endguest </ul> </div> </div> </nav> <main class="py-4"> @yield('content') </main> </div> </body> </html>
最後に、welcome.blade.phpを修正します。
@extends('layouts.app') @section('content') <div class="container"> <div class="row justify-content-center"> <div class="title m-b-md"> BABY CAMERA </div> <div class="subtitle m-b-md"> 今日は{{$today}}。生まれてから{{$elapsed_days}}日だよ。 </div> <img src="http://your-domain.clear-net.jp:8080/?action=stream" alt="baby camera"> </div> </div> @endsection
LaravelでMJPG Streamerの動画を引っ張ってくることができました。Laravelで作った日付計算もうまく表示できています。
まとめ
やらないといけないことは多々ありますが、Laravelで動かすベース部分はできました。
ここからデータをグラフ化したり色々やっていきたいと思います。
ではでは!