Webサービス開発

ラズパイの見守りモニタにMixhostのLaravelからアクセスする

 

student taro
見習いタロー

ラズパイの見守りモニタを進化させたいんだけど…

koala
プロコアラ

Laravelからラズパイ MJPG Streamerにアクセスできるようにしてみよう。

この記事を書いた人
koala
プロコアラ@エンジニアブロガー
10年間エンジニアをしており、副業でWebサイトやWebサービスを作っています。
一時期資格取得にハマりTOEIC860点オーバー、応用情報処理は取得。休日はラズパイをいじるコアラ好きです。

 

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で動かすベース部分はできました。

ここからデータをグラフ化したり色々やっていきたいと思います。

ではでは!

ABOUT ME
律野桜哉
RPAコンサルタントのプロコアラです。長年のエンジニア経験を活かしてして外資系コンサルファームでRPAコンサルしてます。 転職ノウハウ、プログラミング、英語の勉強方法など分かりやすいように解説していきます。