はらぺこらいおん

日々、思ったことを。

Laravelの開発Tips

bladeで変数の一覧ダンプしたい時

{{ dd(get_defined_vars()['__data']) }}

URLが自動改行されない時

URLが自動改行してくれない問題

word-break: break-all;

empty/issetなどのtrue/false条件がわからない時

PHP: PHP 型の比較表 - Manual

bladeで改行したい時

LaravelのBladeで改行したいとき

{!! nl2br(e($content)) !!}

seedで改行コードが入らない場合

「'」ではなく「"」で囲む。

'content' => "aaa\nbbb"

migrateでエラーが発生

Laravel 5.5 - 1071 specified key was too long max key length is 767 bytes - HDTuto.com

[Illuminate\Database\QueryException]

SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes (SQL: alter table `users` add unique ` users_email_unique`(`email`))

app/Providers/AppServiceProvider.phpに以下を追加。

    public function boot()

    {

        Schema::defaultStringLength(191);

    }

seedが実行できない

ReflectionException  : Class XXXTableSeeder does not exist

以下を実行する必要がある。

$ composer dump-autoload

特定のキーを使ったArrayListを取得する

php - Eloquent column list by key with array as values? - Stack Overflow

$users = User::all()->keyBy('name')->toArray();

ログインした際にログインしたページにリダイレクトする

【Laravel】ログインした後、固定ページに飛ばさずにログインボタンを押した画面に戻りたい。

app/Http/Controllers/Auth/LoginController.phpに以下を追加。

    public function showLoginForm()
    {
        session(['url.intended' => $_SERVER['HTTP_REFERER']]);
        return view('auth.login');
    }

メール送信できない

Stream Socket Enable Crypto Error Laravel

    'stream' => [
        'ssl' => [
            'verify_peer' => false,
            'verify_peer_name' => false,
            'allow_self_signed' => true,
        ],
    ],

実行したSQLクエリーを取得したい時

DB::enableQueryLog();
# SQL here
dd(DB::getQueryLog());

Laravelインストール時にバージョンを指定したい時

$ composer create-project --prefer-dist laravel/laravel projectname "5.5.*"

リクエストヘッダーの取得を行いたい時

$header = $request->header('HeaderName');

Solidityの開発Tips

コンパイラー(solc)のインストール

https://book.ethereum-jp.net/first_use/contract.html

brew update
brew upgrade
brew tap ethereum/ethereum
brew install solidity
brew linkapps solidity
solc --version

MistをPrivate Netに接続する

mac OS how connect private chain · Issue #1403 · ethereum/mist · GitHub

gethのオプションに以下を追加する。Walletのデフォルトの動きとして以下のディレクトリーにソケットを探しに行くため。

--ipcpath ~/Library/Ethereum/geth.ipc
geth --datadir ./data --mine --nodiscover --maxpeers 0 --networkid 15 --rpc --rpcport 8545 --rpcaddr "0.0.0.0" --rpcapi="db,eth,net,web3,personal,web3" --rpccorsdomain "*" --ipcpath ~/Library/Ethereum/geth.ipc

Parityにconsole接続

How to open the JavaScript console on Parity? - Ethereum Stack Exchange

gethを利用する。

Linux

geth attach ~/.local/share/io.parity.ethereum/jsonrpc.ipc

Mac

geth attach ~/Library/Application Support/io.parity.ethereum/jsonrpc.ipc

Listenしているポートを確認

How to check if port is in use on Linux or Unix - nixCraft

Linux

sudo lsof -i -P -n | grep LISTEN

ArduinoでCO2濃度を計測する(MH-Z19)

ArduinoでCO2濃度を計測するためにいろいろやってみました。

使用パーツ

AE-ATMEGA328-MINI(Arduino Pro Mini互換)

f:id:pictzzz:20170729122213j:plain

akizukidenshi.com

秋月で780円だったので、使ってみることにしました。

USBシリアル変換

f:id:pictzzz:20170729122327j:plain

akizukidenshi.com

ロジックレベルを5Vと3.3Vで切り替えられて、便利なのでよく使ってます。

ブレッドボード

f:id:pictzzz:20170729122427j:plain

akizukidenshi.com

個人的にこれくらいのサイズが使いやすいです。サイズが足りなければ連結できます。

LCD

f:id:pictzzz:20170729122356j:plain

akizukidenshi.com

計測結果を表示するために用意しました。Arduino用のサンプルコードがあり、3.3Vと5Vで接続できます。

MH-Z19(CO2センサー)

f:id:pictzzz:20170729122259j:plain

今回のメイン、CO2センサーです。いろいろなサイトで探してみたのですが、高額だったり、大量ロットで注文しなければならなかったり、なかなか買えませんでした。

下記AliExpressという中国のサイトで見つけて安かったので、今回は試しに買ってみました。2週間ほどで無事に届きました。

AliExpress.com Product - 1PCS module MH-Z19 infrared co2 sensor for co2 monitor Free shipping new stock best quality

CO2センサーからArduinoへデータ取得

CO2センサーからの情報の取得はシリアルとPWMが選択できます。今回はPWMで取得してみようと思います。

まずは、macArduinoを接続します。ツールから以下を選択します。

  • Board: “Arduino Pro or Pro Mini”
  • Processor: “ATmega328 (5V, 16MHz)”
  • Port: “/dev/cu.usbserial-A1032FAZ”

Arduinoとセンサーの接続はシンプルで以下の3本です。

センサーが正常に動作しているかを確認するため、シリアルにログを出力するコードを実行してみます。

#define PWM_PIN 3

int prev_val = LOW;
long high_level_start = 0L;
long high_level_end = 0L;
long low_level_start = 0L;
long low_level_end = 0L;

void setup() {
  Serial.begin(9600);
  pinMode(PWM_PIN, INPUT);
}

void loop() {
  long cycle_start_time = millis();
  int pin_in = digitalRead(PWM_PIN);

  if (pin_in == HIGH) {
    if (prev_val == LOW) {
      long time_high = high_level_end - high_level_start;
      long time_low = low_level_end - low_level_start;
      long ppm = 5000 * (time_high - 0.002) / (time_high + time_low - 0.004);
      Serial.println("PPM = " + String(ppm));
      
      high_level_start = cycle_start_time;
      prev_val = HIGH;
    } else {
      high_level_end = cycle_start_time;
    }
  } else {
    if (prev_val == HIGH) {
      low_level_start = cycle_start_time;
      prev_val = LOW;
    } else {
      low_level_end = cycle_start_time;
    }
  }
}

出力は以下のようになります。室内は少しCO2濃度が高めのようです。

PPM = 905
PPM = 906
PPM = 901
PPM = 941
PPM = 940
PPM = 936
PPM = 941
PPM = 941
PPM = 920
PPM = 916
PPM = 921

仕様書を読むと2000をかけると書かれているのですが、5000にしないと値があわないようでした。

http://clima-sensor.ru/files/MH-Z19_Manual_V2.pdf

ArduinoからLCD(ディスプレイ)へ結果の出力

センサーからの結果をLCDに出力するようにしてみます。

接続は以下の4本です。

I2Cのプルアップ抵抗は初めからArduino側で実装されていましたので、そのまま接続します。

プログラムは以下のようになります。(※ 見直し中)

#include <Wire.h>

#define LCD_ADRS 0x3E
#define PWM_PIN 3

int prev_val = LOW;
long high_level_start = 0L;
long high_level_end = 0L;
long low_level_start = 0L;
long low_level_end = 0L;
int ppm = 0;

boolean is_output_ready = false;

char moji[] = "CO2 = ";

void writeData(byte t_data) {
  Wire.beginTransmission(LCD_ADRS);
  Wire.write(0x40);
  Wire.write(t_data);
  Wire.endTransmission();
  delay(1);
}

void writeCommand(byte t_command) {
  Wire.beginTransmission(LCD_ADRS);
  Wire.write(0x00);
  Wire.write(t_command);
  Wire.endTransmission();
  delay(10);
}

void init_LCD() {
  delay(100);
  writeCommand(0x38);
  delay(20);
  writeCommand(0x39);
  delay(20);
  writeCommand(0x14);
  delay(20);
  writeCommand(0x73);
  delay(20);
  writeCommand(0x52);
  delay(20);
  writeCommand(0x6C);
  delay(20);
  writeCommand(0x38);
  delay(20);
  writeCommand(0x01);
  delay(20);
  writeCommand(0x0C);
  delay(20);
}

void setup() {
  Serial.begin(9600);
  pinMode(PWM_PIN, INPUT);
  Wire.begin();
  init_LCD();
}

void loop() {
  long cycle_start_time = millis();
  int pin_in = digitalRead(PWM_PIN);

  if (pin_in == HIGH) {
    if (prev_val == LOW) {
      long time_high = high_level_end - high_level_start;
      long time_low = low_level_end - low_level_start;
      ppm = 5000 * (time_high - 0.002) / (time_high + time_low - 0.004);
      is_output_ready = true;
      
      high_level_start = cycle_start_time;
      prev_val = HIGH;
    } else {
      high_level_end = cycle_start_time;
    }
  } else {
    if (prev_val == HIGH) {
      low_level_start = cycle_start_time;
      prev_val = LOW;
    } else {
      low_level_end = cycle_start_time;
    }
  }

  if (is_output_ready) {
    writeCommand(0x00 + 0x01);
    for (int i = 0; i < 6; i++) {
      writeData(moji[i]);
    }
    String ppm_text = String(ppm);
    char ppm_print[4];
    ppm_text.toCharArray(ppm_print, 4);
    for (int i = 0 ; i < 4 ; i++) {
      writeData(ppm_text[i]);
    }
    is_output_ready = false;
  }
}

LCDへの文字の出力処理を実装し、Arduinoにアップロードします。

うまくいけば、以下のようにCO2の濃度が出力されます。

f:id:pictzzz:20170729173639j:plain

CentOS7.4にLaravel5.5をインストール

CentOS7.3にLaravel5.4をインストールした際の、記録を残しておきます。
前回の記事でセットアップした、CentOS7.3にLaravel5.4をインストールします。 CentOS7.4、Laravel5.5LTSにアップデートした内容を記載します。(2018/04/07)

pictzzz.hatenablog.com

セットアップ方法

基本的には公式ドキュメントに従って作業していきます。

laravel.com

PHPのバージョンは、PHP >= 5.6.4となっていますが、せっかくなのでPHP7をインストールしてみたいと思います。
データベースにはMariaDBを使いたいと思います。

PHP >= 7.0.0が必須となりました。

PHPインストール

remi 追加

$ sudo rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm

PHP7 インストール

$ sudo yum install --enablerepo=remi,remi-php72 php php-devel php-mbstring php-pdo php-xml php-zip

MariaDBインストール&自動起動を設定

$ sudo yum install mariadb mariadb-server
$ sudo yum install --enablerepo=remi,remi-php72 php-mysql

$ sudo systemctl enable mariadb.service
$ sudo systemctl start mariadb.service

$ mysql_secure_installation

MariaDBユーザーの作成

> create user 'user_name'@'localhost' identified by 'password';
> grant all privileges on *.* to 'user_name'@'localhost';
> flush privileges;

Composerインストール

$ curl -sS https://getcomposer.org/installer | php
$ sudo mv composer.phar /usr/local/bin/composer

プロジェクト作成

$ composer create-project --prefer-dist laravel/laravel _project_name_ "5.5.*"

Firewall設定

$ sudo firewall-cmd --add-service=http --zone=public --permanent
$ sudo firewall-cmd --reload

開発用サーバー起動

$ cd _project_name_
$ php artisan serve --host=0.0.0.0 --port=80

Nginxインストール

$ sudo yum install nginx

PHP-FPMインストール

$ sudo yum install --enablerepo=remi-php72 php-fpm

PHP-FPM設定

$ sudo vi /etc/php-fpm.d/www.conf
user = apache
↓
user = nginx

group = apache
↓
group = nginx

listen = 127.0.0.1:9000
↓
listen = /var/run/php-fpm/php-fpm.sock

;listen.owner = nobody
;listen.group = nobody
;listen.mode = 0660
↓
listen.owner = nginx
listen.group = nginx
listen.mode = 0660

PHP-FPM起動&自動起動を設定

$ sudo systemctl start php-fpm
$ sudo systemctl enable php-fpm.service

Nginx設定

$ sudo vi /etc/nginx/conf.d/laravel.conf
server {
   root   /var/www/_project_name_/public;

   location / {     
        index  index.php;
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass   unix:/var/run/php-fpm/php-fpm.sock;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
}

Nginx起動&自動起動を設定

$ sudo systemctl start nginx
$ sudo systemctl enable nginx.service

ConoHaでインスタンスの初期セットアップ(CentOS7.4 64bit)

ConoHaでインスタンスの初期セットアップ(CentOS7.4 64bit)を行ったので、その記録を残しておきます。 CentOS7.3->7.4でSSHの設定が少し異なっていたので内容をアップデートします。(2018/04/07)

ConoHaコントロールパネル ログイン

ConoHaコントロールパネルへのログインは公式ページより行います。

www.conoha.jp

ログインボタンからID、パスワード、2段階認証コードを入力してログインします。

インスタンス作成

ログインすると以下のような画面が表示されます。

f:id:pictzzz:20170304142344p:plain

コントロールパネルの左側のメニューからサーバーを選択します。 サーバー画面で「+サーバー」をクリックします。

f:id:pictzzz:20170304142826p:plain

接続許可ポート IPv4 / IPv6では、不要なポートはチェックを外します。 今回はリモートメンテナンス用SSHとWebサーバー用Webのみを開けています。

SSHキーは後からでも作成できます。

一般ユーザー作成

サーバー画面から、作成したサーバーを選択します。 画面上部のコンソールボタンをクリックします。

f:id:pictzzz:20170304143641p:plain

以下のようなコンソールが開きます。

f:id:pictzzz:20170304143852p:plain

このコンソールにコマンドを入力することでサーバーを操作することができます。

まずは、ユーザーを作成し、パスワードを設定します。 「username」は作成したいユーザー名になります。 パスワードは入力しても表示されません。

# adduser _username_
# passwd _username_
新しいパスワード:
新しいパスワード(再入力):

次に管理者権限でコマンドを実行できるようにします。 デフォルトでsudoの設定がwheelグループに許可されていました。 許可されるグループやユーザーを指定する場合、visudoコマンドを実行します。

# usermod -G wheel _username_

sudoコマンドが実行できるかを確認します。 viが起動すればOKです。ESCキー + :q + エンターキーで終了します。

# su - _username_
$ sudo vi a.txt
[sudo] password for _username_: 

公開鍵認証設定

リモートでサーバーへ接続するPCでキーペアを作成します。
今回はmacOSで行います。Linuxでは同じコマンドが使えるかと思います。
Windowsではputtyとかをインストールすればキーペアを生成できます。
filenameにはキーファイル名を入力します。(任意の名称)
コマンドを実行後、filenamefilename.pubが生成されているかと思います。

$ ssh-keygen -t rsa -f _filename_
$ 

filename.pubを接続するサーバーへ転送します。 今回はコンソールで入力します。

$ cat _filename_.pub
key-xxxxxxxxx

catコマンドでkeyの中身が表示されるので、コピーしておきます。

Webのコンソールを開きます。rootになっている場合、作成したユーザーに切り替えます。 今ログインしているユーザーはidコマンドで調べることができます。

# su - _username_

ホームディレクトリー下に.sshディレクトリーを作成します。ディレクトリーのパーミッションを700に変更します。 作成した.sshディレクトリー下にauthorized_keysを作成します。authorized_keysには、先ほどコピーしたキーを貼り付けます。
authorized_keysはパーミッションを600に変更します。

$ mkdir .ssh
$ chmod 700 .ssh
$ vi .ssh/authorized_keys
$ chmod 600 .ssh/authorized_keys

sshd設定

sshdの設定を変更して、rootでログインできないようにしておきます。

$ sudo vi /etc/ssh/sshd_config
#Port 22
↓
Port 22

#PubkeyAuthentication yes
↓
PubkeyAuthentication yes

#Banner none
↓
Banner none

PermitRootLogin yes
↓
PermitRootLogin no

変更したらsshdを再起動します。

$ sudo systemctl restart sshd

PCから接続

今回はmacOSからの接続の場合、ターミナルを開いて、sshコマンドを実行します。 ip_addressにはサーバーのIPアドレスを指定します。ConoHaのコントロールパネルに表示されています。 key_pathには今回生成したキーペアの.pubが付いていない方を指定します。

初回接続時には警告が出ますが、yesで進めます。

$ ssh _username_@_ip_address_ -i _key_path_

以上で、セットアップは完了です。

AWSのEBS(ストレージ)を追加する方法

スポットインスタンス機械学習を行っていると、 学習を行っている間はインスタンスを起動しておき、学習を完了した際には、 インスタンスを終了するということを行います。

そうすると学習データや学習したモデルを毎回学習を行うたびにアップロードする必要があります。 AWSではインバウンドトラフィックAWSへの通信)にコストはかかりませんが、 大量の画像データをアップロードするには時間がかかってしまい、 時間とインスタンス料金がもったいないので、 先にデータを保存しておくEBSを別に作っておきます。

そしてインスタンスを起動したら、そのEBSを接続することで、 データを再アップロードせずに済むようにしておきます。

EBS作成

EBSでディスクを作成するのは簡単です。

メニューのボリュームをクリックします。 EBSの画面に表示される、ボリュームの作成をクリックします。

f:id:pictzzz:20170209230628p:plain

わかりやすい名前をつけて、必要なディスクサイズを入力します。

f:id:pictzzz:20170209230727p:plain

接続したいディスクを選択し、アクション>ボリュームのアタッチをクリックします。

f:id:pictzzz:20170209230810p:plain

ボリュームのアタッチを行うウィンドウが表示されます。 アタッチするインスタンスインスタンスにアタッチした際のデバイスを入力します。 フォームをクリックすると、選択肢が表示されるので、そこから選ぶことができます。 入力後、アタッチをクリックするとインスタンスにボリュームが接続されます。

f:id:pictzzz:20170209230853p:plain

マウント

インスタンスに接続します。 マウントするためにはrootになる必要があります。

$ sudo su -

まずは、デバイス名を調べます。デバイス名を調べるのにはlsblkコマンドを使います。

# lsblk
NAME    MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
xvda    202:0    0  20G  0 disk 
└─xvda1 202:1    0  20G  0 part /
xvdf    202:80   0  30G  0 disk 

マウントされてないのはxvdfとわかったので、/dev/xvdfをマウントします。 マウントポイントは任意ですが、今回はルートディレクトリー直下にdataディレクトリーを作って、マウントしたいと思います。

# mkdir /data
# mount /dev/xvdf /data

これで/dataに作成したEBSボリュームが接続され、使用できるようになります。

初めてのマウントの場合(フォーマット)

初めてのマウントの場合、マウントの前にフォーマットを行います。

# mkfs -t ext4 /dev/xvdf

これでext4でフォーマットされます。

AWS CUDA8.0セットアップ済みAMI作成

pictzzz.hatenablog.com

前回の記事ではAWSのP2インスタンスをスポットで利用する方法をまとめました。 これで安くEC2を使うことができるようになりましたが、毎回毎回OSからCUDA、プログラミング環境をセットアップするのは大変手間です。

そこでAMIという仕組みを使い、この問題を解決したいと思います。

AMIとは

AMIとは、スナップショットとインスタンスの管理情報が入っており、 これを使ってOS、CUDA、プログラミング環境のセットアップ済みのインスタンスを直接起動できるようになります。

docs.aws.amazon.com

AMI作成

AMIの作成は簡単です。AMIを作成したいインスタンスを選択し、「アクション」>「イメージ」>「イメージの作成」の順にクリックします。

f:id:pictzzz:20170208223141p:plain

イメージの作成をクリックするとダイアログが表示されるので、名称をつけて保存します。

f:id:pictzzz:20170209222343p:plain

ここでの注意点は以下のものがあります。

  • 再起動しないにチェックを入れないと、インスタンスが再起動されてしまいます。
  • 再起動をしないでも通常は正常にAMIを作ることができます。
  • スポットインスタンスを使っている場合でも、再起動は可能です。
  • AWSではデータの整合性のため、再起動してAMIを作成することを推奨しています。

AMIからスポットインスタンス作成

作成したAMIからスポットインスタンスを作成して見たいと思います。

通常のスポットインスタンスのリクエストページへ移動します。 (EC2 -> スポットインスタンス -> スポットインスタンスのリクエスト)

画面の中ほどにAMIを選択する部分があるのでクリックします。

f:id:pictzzz:20170208224728p:plain

カスタムAMIを使うという選択肢が表示されるので選択します。

f:id:pictzzz:20170208224820p:plain

すると作成したAMIが表示されるので、使用するAMIを選びます。

f:id:pictzzz:20170209221002p:plain

これの状態で通常通りスポットインスタンスのリクエストを行うと、AMIが使用されてインスタンスが作成されます。

f:id:pictzzz:20170208225419p:plain

このようにして作成したインスタンスは、AMI作成時のインスタンスの状態が復元されます。
ただし、グローバルIP(EIP)は付け直す必要があります。

以上で、AMIを使ったスポットインスタンスの作成方法の説明は終了となります。