M5Stack社のM5PaperはWi-Fiで画像取得して表示するまで完結して対応できる点が素晴らしいです!
しかも定期取得の合間にはシャットダウンして、電源消費がほぼゼロで長持ち
・・・という事はLinuxホスト側でウェブサイトを画像キャプチャしてhttpで提供すれば・・・
- デザインの自由度が上がる(ウェブデザインが得意な人向け)日めくりとか自由自在
- ウェブサイトを飾れる(スマホPC触れない人も見れる)
のでは?と思いやってみました!
とりあえずヘッドレスchromeでWebキャプチャした画像をImageMagickでゴリっと変換し、 #M5Paper ( @M5Stack )が定時起動でWi-Fiで画像を取りに行って表示して電源Offまで出来た!
— RAWSEQ(ロウゼク) (@RAWSEQ) February 10, 2021
あとはWebデザインの世界ですね^^
ImageMagickのオプションには少々苦戦したが、大体この書き方で行けそう(文字数) https://t.co/QrT89yBCKp pic.twitter.com/fLf8AEu3GT
ホスト(Linux)側でする事
google-chrome
と ImageMagick
と httpd
は各パッケージマネージャ(yum,apt等)でインストール(省略します)
Chromeヘッドレスモード(コマンドラインモード)でウェブサイトをキャプチャ
google-chrome --headless --screenshot https://example.com/ --window-size=960,540
screenshot.png
というファイルができるので、ImageMagickでM5Paperで読み込めるようにコンバート
convert -rotate 90 \
-quality 88 \
-density 120 \
-units PixelsPerInch \
-sampling-factor 4:2:0 \
-colorspace sRGB \
-strip \
-define colorspace:auto-grayscale=false \
-type truecolor \
screenshot.png screenshot.jpg
試行錯誤したので要らないオプションがついていますが、これで大丈夫なはず。
- rotate 画像回転(90度)
- quality クォリティ(89%以下)
- density units DPI指定(120dpi)
- sampling-factor サブサンプリング(4:2:0)
- colorspace カラースペース(sRGB)
- strip その他拡張情報は邪魔なのでトル)
- define type 自動で付与されるグレースケールは互換性ないのでOFF
- 形式変換(png=>jpg)
(※ ImageMagickのバージョンによってはカラースペースのオプションが逆転(RGB<=>sRGB)するバグがあるので注意)
出力したjpg画像をhttpdのドキュメントパスに配置すれば完成。(httpdサービス起動からファイヤーウォールとかポート開放してM5Paperから見えるようにしてください)
上記のコマンドを cron
等に登録して、定時実行しておくと良いでしょう。
M5Paper側でする事
M5Paper側に書き込むプログラムでWi-Fiで画像取得して表示するサンプルがこちらに。
SSIDとパスワード・画像のURLは所定の物を指定してください。
定期的に取得するなら M5.shutdown([終了後、再起動する秒数])
コマンドを最後に書くだけです。
描画前に終了してしまうので、shutdown前に2秒ぐらいのディレイ delay(2000);
を入れておきましょう。
(追記) 1か月運用して分かった事
- shutdown で次回起動予定(〇秒後)をセットするのですが、MAXで3時間(10800)ぐらいまでの様です。
- 3時間おきの1日8回更新で1か月運用した結果、充電無しで電池残量は13%減。単純計算で4,5カ月いける?
#M5paper 日めくり運用開始から1ヶ月が経ちました!!
— RAWSEQ(ロウゼク) (@RAWSEQ) March 15, 2021
電池残量は開始時67%が今日で54%。
なんと13%しか減っていません!
開始から1ヶ月間全く充電して無いんですよ。
単純計算で5ヶ月半ぐらいは持つことに?!
これは長期耐用出来ていると言ってもいいでしょう。#M5stack pic.twitter.com/fHySr7Q7d8
WEBページ側のデザイン
この後のソースはプロトタイプなので、見栄えの良いものではないですが...
参考にしたいと要望頂きましたので、ざっくり上げさせていただきます。
購入した有料ライセンスフォント(画像化済)も含まれますので、ソースコピー等の参考程度にしていただき、画像のコピー・二次転用はご遠慮ください。
単純に position: absolute;
を使って、絶対座標指定でやってます。
「書き方が汚い!」とかは十重承知でございます・・・
APIロジック
天気やTwitterトレンド情報等のAPI接続は
PHPで取得して、中間ファイルを生成しています。
取得タイミングは即時ではなく、CRONで定時に実行するよう設定。ロリポップ等のレンタルサーバーでも簡単に使えます。
天気予報
Dark Sky さんを利用しています。リクエスト頻度の閾値を超えなければ無料というフリーミアムなAPIです。(まあ、基本はどこでもそんな感じですね・・)
https://api.rakuten.net/darkskyapis/api/dark-sky
Rakten Rapid APIさんが言語に合わせたコードを出力してくれるのでほぼやる事ないです。
書いたものを吐き出しているだけですね・・
<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://dark-sky.p.rapidapi.com/【緯度】,【経度】?lang=en&units=auto",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"x-rapidapi-host: dark-sky.p.rapidapi.com",
"x-rapidapi-key: 【APIキー】"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
$fp = fopen('【出力jsonファイルのパス】', 'w');
fwrite($fp, $response);
fclose($fp);
利用したAPIは 「Forcast」で、緯度経度を指定したら、その地点の1時間おき1日間、1日おき1週間の天気予報情報を取得できます。
こちらの例は、1日朝7時に1回実行し
- 0時間後(7時)
- 5時間後(12時)
- 11時間後(18時)
の気温(temperature)、降水確率(precipProbability)を取得して表示します。
降水確率はレシオなのでパーセントに変換(* 100)します。
気温は自動で摂氏になってたはず。(忘れました。設定あったらごめんなさい・・)
天気マークは currentlyのiconを取得しています。
clear-day / clear-night / partly-cloudy-day / partly-cloudy-night / cloudy / rain / sleet / snow / wind / fog
の文字列で来るので、それに合わせてパターン画像を用意して表示しています。
Rakuten Rapid APIが便利すぎて TwitterのAPIもあるのですが、トレンドは取れない様で
仕方なく本件をAPIを利用しています。
(後で気づいたのですが、各SNS総なめのトレンドを取得できるAPIならあるのかも・・)
・・・
(コホン・)気を取り直して
Twitter APIの接続にはこちらのお世話になりました!
https://syncer.jp/Web/API/Twitter/REST_API/
APIトークン類の取得方法等、手取り足取り教えて頂きました。
何を使うにも基本のPHPはこちらです。(このPHPをインクルードして使います。)
<?php
/**
* twitter
*
* @param string $endpoint (スラッシュ以降のパス)
* @param array $params_a (パラメータ(配列)
* @return string (応答json)
*/
function twitter($endpoint, $params_a) {
/**********************
設定
**********************/
$api_key = "【API Key】";
$api_secret = "【API Secret】";
$access_token = "【アクセストークン】";
$access_token_secret = "【アクセストークンシークレット】";
//エンドポイント
$request_method = "GET"; //メソッド
$request_url = "https://api.twitter.com/1.1/".$endpoint.".json"; //URL
/**********************
署名作成
**********************/
//OAuth1.0認証用のパラメータを連想配列で用意
$params_b = array(
"oauth_consumer_key" => $api_key,
"oauth_token" => $access_token,
"oauth_nonce" => microtime(),
"oauth_signature_method" => "HMAC-SHA1",
"oauth_timestamp" => time(),
"oauth_version" => "1.0"
);
//キーを作成する
$signature_key = rawurlencode($api_secret)."&".rawurlencode($access_token_secret);
//オプション・パラメータ[$params_a]と認証用パラメータ[$params_b]を署名作成のため、合体させた[$params_c]を用意
$params_c = array_merge($params_a,$params_b);
//[$params_c]をアルファベット順に並び替える
ksort($params_c);
//配列[$params_c]を[キー=値&キー=値...]の文字列に変換
$signature_params = str_replace(array("+","%7E"),array("%20","~"),http_build_query($params_c,"","&"));
//リクエストメソッド、リクエストURL、パラメータを、URLエンコードしてから[&]で繋ぎ、データを作成する
$signature_data = rawurlencode($request_method)."&".rawurlencode($request_url)."&".rawurlencode($signature_params);
//キー[$signature_key]とデータ[$signature_data]をHMAC-SHA1方式のハッシュ値に変換し、base64エンコードして、署名を作成する
$signature = base64_encode(hash_hmac("sha1",$signature_data,$signature_key,TRUE));
/**********************
GETリクエスト
**********************/
//[$params_c]に、作成した署名を加える
$params_c["oauth_signature"] = $signature;
//[$params_c]を[キー=値,キー=値,...]の文字列に変換する(ヘッダー用)
$header_params = http_build_query($params_c,"",",");
//[$params_a]を、リクエストURLの末尾に付けるクエリーに変換して付ける(GETの場合)
//[例] ?screen_name=arayutw
if($params_a && $request_method=="GET"){
$request_url .= "?".http_build_query($params_a,"","&");
}
//TwitterにGETリクエストを送る [$json]にTwitterから返ってきたJSONが格納される
$json = file_get_contents(
$request_url, //[第1引数:リクエストURL($request_url)]
false, //[第2引数:リクエストURLは相対パスか?(違うのでfalse)]
stream_context_create( //[第3引数:stream_context_create()でメソッドとヘッダーを指定]
array(
"http" => array(
"method" => $request_method, //リクエストメソッド
"header" => array( //カスタムヘッダー
"Authorization: OAuth ".$header_params,
),
)
)
)
);
return $json;
}
そして、それを呼び出してトレンドを取得してファイル出力するだけのPHP
<?php
include_once 'twitter.php';
$out = twitter('trends/place', array('id'=>'1110809'));
$fp = fopen('【出力jsonファイルのパス】', 'w');
fwrite($fp, $out);
fclose($fp);
ざっくり紹介しましたが、そんな感じですね。