Raspberry PiのデータをGCPに送ってみた(無料)


Raspberry PiのデータをGCPに送ってみた(無料)

Raspberry PiのデータをMySQLに格納し、Web上で確認できる仕組みを作りたかった。
VPSにサーバーを立てて、データのやり取りをしたい人向け。

※本記事は、Rasberry Pi上で気温データを取得し、送信することを目的としています。

開発環境

  • Windows10 Pro
  • Powershell
  • Windows Subsystem for Linux(Ubuntu)

GCPについて

Google Cloud Platformの略称で、Googleが提供しているクラウドコンピューティングサービスである。

https://cloud.google.com/?hl=ja

GCPの始め方はこちらを参考に

https://cloud.google.com/gcp/getting-started/?hl=ja

Windows Subsystem for Linux(WSL)について

  • Ubuntu(バージョン明記なし)をMicrosoft Storeからインストール
    • どうやら自動的に最新版になるらしい
  • ホームディレクトリは/home/[作成ユーザー名]/になっている
    • Powershellは/mnt/c/Users/[ユーザー名]/
  • /mnt/c/Users/[ユーザー名]/にcdコマンドで移動して作業開始

Webサーバを立てる

  • GCPプロジェクトの作成
  • 好きなOSのVMを立てる(筆者は、Ubuntu 18.04 LTS)

※無償枠で作成する場合はこちらを参考に作成してください。

https://cloud.google.com/free/docs/gcp-free-tier?hl=ja

  • SSH認証を行う(Windowsからアクセスする用)

※補足:公開鍵をscpで送りたい場合

scp ~/.ssh/[公開鍵] [ユーザー名]@[転送先サーバのIP]:~/.ssh/
  • apache2のインストール
sudo apt-get update
sudo apt-get install apache2 -y
curl http://[外部IP]

※外部IPはGoogle Cloud Platform -> Computer Engine -> VMインスタンス

  • ファイアーフォールの設定 (ufwのインストールと設定)
#有効化
sudo ufw enable
#使っているTCP/UDPポートを調べる
sudo ufw status
#nmapでも可能
sudo nmap -sTU localhost
#ポートの解放(ルールの登録)
sudo ufw allow [許可したいポート番号]
#ルールの削除
sudo ufw status numbered
sudo ufw delete [number]
#無効化
sudo ufw disable

DBの構築(MySQL)

sudo apt install mysql-server mysql-client
#サービスの起動確認
sudo service mysql status
#MySQLの初期設定
sudo mysql_secure_installation
#コンソールからMySQLサーバへ接続
sudo mysql -u root -p
  • MySQLのユーザー情報の確認等
#状態表示
mysql> status
#データベース一覧表示
mysql> show database;
#ユーザー一覧表示
mysql> select user, host from mysql.user;
#特定ユーザの権限確認(ex) ユーザー:root, ホスト名:localhost)
mysql> show grants for 'root'@'localhost';
#終了
mysql> exit

https://www.yokoweb.net/2018/05/13/ubuntu-18_04-server-mysql/

  • 実際に構築をする
    • 今回は、取得時間と気温データの2つのフィールドを作成する
sudo mysql
#データベースの作成
mysql> create database [db_name]
mysql> show databases;
#データベースの移動
mysql> use [db_name]
#テーブルの作成(シングルコートいらない)
mysql> create table [tbl_name] ( id int(11) NOT NULL AUTO_INCREMENT, 
    -> ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    -> temp float NOT NULL,
    -> PRIMARY KEY(id)) ENGINE=MyISAM
#確認
mysql> show tables from [db_name];
mysql> show columns from [tbl_name];
+-------+-----------+------+-----+-------------------+-----------------------------+
| Field | Type      | Null | Key | Default           | Extra                       |
+-------+-----------+------+-----+-------------------+-----------------------------+
| id    | int(11)   | NO   | PRI | NULL              | auto_increment              |
| ts    | timestamp | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| temp  | float     | NO   |     | NULL              |                             |
+-------+-----------+------+-----+-------------------+-----------------------------+
3 rows in set

※トランザクション処理は行わないので、MyISAM。上記コードは温度データのみ格納用。

http://zetcode.com/databases/mysqltutorial/storageengines/

プログラムの作成

PHPの環境設定

  • PHPをインストール
#最新版でなければこれでOK(最新はver7.3、aptの場合ver7.2)
sudo apt install php
  • ドキュメントルート(apacheがブラウザに送信するHTML)は/var/www/html/
  • パーミッションを変更
  • PHPの動作確認はphpinfoで可能
<?php phpinfo(); ?>

PHPからDB(MySQL)へのアクセス確認

  • PHP Data Objects(PDO) ※今回はPDOを使用
    • PHPからデータベースのアクセスを抽象的にやってくれる
  • mysqli
    • MySQL改良版拡張モジュール

<?php
try{
// PDOクラスのオブジェクトを作成
$pdo = new PDO('mysql:host=localhost;dbname=[db_name];charset=utf8', '[ユーザー名]', '[パスワード]', array(PDO::ATTR_EMULATE_PREPARES => false));
}catch(PDOException $e){
exit('データベース接続失敗。'.$e->getMessage());
}
// DB処理
switch ($_SERVER['REQUEST_METHOD']) {
    case 'GET':
        $st = $pdo->query("select * from [テーブル名]");
        echo json_encode($st->fetchAll(PDO::FETCH_ASSOC));
        break;

    case 'POST':
        $data = json_decode(file_get_contents('php://input'), true);
        $st = $pdo->prepare("insert into [テーブル名](ts, temp) values (:datetime,:temp)");
        $st->execute($data);
        header('Content-Type: application/json');
        echo json_encode("end");
        break;
}
?>

Raspberry PiからPHPへのデータ送信処理(Python)

# coding: utf-8
import requests
import json
from datetime import datetime

def main():

    url = 'http://[外部IP]/[プログラム名].php'
    #気温取得の処理
    ...
    temp = #値

    data = {'datetime':datetime.now().strftime("%Y/%m/%d %H:%M:%S"),'temp':temp}
    #JSON形式にdataをエンコード
    print(json.dumps(data))
    #JSON形式でPOSTリクエストを送信する(json形式のレスポンスが欲しいため、Content-type指定)
    response = requests.post(url, json.dumps(data), headers={'Content-type': 'application/json'})    #正しく返された場合にresponseに値が入る
    print(response.json())
    pass

if __name__ == '__main__':
    main()

センサーデータをうまく利活用し、クラウドとの連携をしていきたい…