M5Paperでウェブサイトを表示する（Chromeキャプチャ & ImageMagickで変換）あと、日めくり作成

完成例（こういったのが作れます）
![EuFhrGpUcAA9PKx.jfif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65983/7d8de8aa-a038-60c5-68b3-0ea2f0e90104.jpeg)


M5Stack社のM5PaperはWi-Fiで画像取得して表示するまで完結して対応できる点が素晴らしいです！
しかも定期取得の合間にはシャットダウンして、電源消費がほぼゼロで長持ち

・・・という事はLinuxホスト側でウェブサイトを画像キャプチャしてhttpで提供すれば・・・

- デザインの自由度が上がる（ウェブデザインが得意な人向け）日めくりとか自由自在
- ウェブサイトを飾れる（スマホPC触れない人も見れる）

のでは？と思いやってみました！

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">とりあえずヘッドレスchromeでWebキャプチャした画像をImageMagickでゴリっと変換し、 <a href="https://twitter.com/hashtag/M5Paper?src=hash&amp;ref_src=twsrc%5Etfw">#M5Paper</a> ( <a href="https://twitter.com/M5Stack?ref_src=twsrc%5Etfw">@M5Stack</a> )が定時起動でWi-Fiで画像を取りに行って表示して電源Offまで出来た！<br>あとはWebデザインの世界ですね＾＾<br>ImageMagickのオプションには少々苦戦したが、大体この書き方で行けそう(文字数) <a href="https://t.co/QrT89yBCKp">https://t.co/QrT89yBCKp</a> <a href="https://t.co/fLf8AEu3GT">pic.twitter.com/fLf8AEu3GT</a></p>&mdash; RAWSEQ(ロウゼク) (@RAWSEQ) <a href="https://twitter.com/RAWSEQ/status/1359301208461090819?ref_src=twsrc%5Etfw">February 10, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## ホスト(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は所定の物を指定してください。

https://github.com/m5stack/M5EPD/blob/main/examples/Basics/DISPLAY_URL_JPG/DISPLAY_URL_JPG.ino

定期的に取得するなら `M5.shutdown([終了後、再起動する秒数])` コマンドを最後に書くだけです。
描画前に終了してしまうので、shutdown前に2秒ぐらいのディレイ `delay(2000);` を入れておきましょう。

## (追記) 1か月運用して分かった事

- shutdown で次回起動予定（〇秒後）をセットするのですが、MAXで３時間(10800)ぐらいまでの様です。
- 3時間おきの1日8回更新で1か月運用した結果、充電無しで電池残量は13%減。単純計算で4,5カ月いける？

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr"><a href="https://twitter.com/hashtag/M5paper?src=hash&amp;ref_src=twsrc%5Etfw">#M5paper</a> 日めくり運用開始から1ヶ月が経ちました！！<br>電池残量は開始時67%が今日で54%。<br>なんと13%しか減っていません！<br>開始から1ヶ月間全く充電して無いんですよ。<br>単純計算で5ヶ月半ぐらいは持つことに?!<br>これは長期耐用出来ていると言ってもいいでしょう。<a href="https://twitter.com/hashtag/M5stack?src=hash&amp;ref_src=twsrc%5Etfw">#M5stack</a> <a href="https://t.co/fHySr7Q7d8">pic.twitter.com/fHySr7Q7d8</a></p>&mdash; RAWSEQ(ロウゼク) (@RAWSEQ) <a href="https://twitter.com/RAWSEQ/status/1371256984620593152?ref_src=twsrc%5Etfw">March 15, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## WEBページ側のデザイン

<b>この後のソースはプロトタイプなので、見栄えの良いものではないですが...
参考にしたいと要望頂きましたので、ざっくり上げさせていただきます。
購入した有料ライセンスフォント（画像化済）も含まれますので、ソースコピー等の参考程度にしていただき、画像のコピー・二次転用はご遠慮ください。</b>

https://ltside.com/dash/

単純に `position: absolute;` を使って、絶対座標指定でやってます。
「書き方が汚い！」とかは十重承知でございます・・・

## APIロジック

天気やTwitterトレンド情報等のAPI接続は
PHPで取得して、中間ファイルを生成しています。
取得タイミングは即時ではなく、CRONで定時に実行するよう設定。ロリポップ等のレンタルサーバーでも簡単に使えます。

### 天気予報

Dark Sky さんを利用しています。リクエスト頻度の閾値を超えなければ無料というフリーミアムなAPIです。（まあ、基本はどこでもそんな感じですね・・）
https://api.rakuten.net/darkskyapis/api/dark-sky

Rakten Rapid APIさんが言語に合わせたコードを出力してくれるのでほぼやる事ないです。
書いたものを吐き出しているだけですね・・

```php
<?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」で、緯度経度を指定したら、その地点の１時間おき１日間、１日おき１週間の天気予報情報を取得できます。
こちらの例は、１日朝７時に１回実行し

- 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
の文字列で来るので、それに合わせてパターン画像を用意して表示しています。

### Twitter

Rakuten Rapid APIが便利すぎて TwitterのAPIもあるのですが、トレンドは取れない様で
仕方なく本件をAPIを利用しています。
（後で気づいたのですが、各SNS総なめのトレンドを取得できるAPIならあるのかも・・）
・・・
（コホン・）気を取り直して
Twitter APIの接続にはこちらのお世話になりました！　
https://syncer.jp/Web/API/Twitter/REST_API/
APIトークン類の取得方法等、手取り足取り教えて頂きました。

何を使うにも基本のPHPはこちらです。（このPHPをインクルードして使います。）

```php:twitter.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:trends.php
<?php
include_once 'twitter.php';
$out = twitter('trends/place', array('id'=>'1110809'));
$fp = fopen('【出力jsonファイルのパス】', 'w');
fwrite($fp, $out);
fclose($fp);
```

ざっくり紹介しましたが、そんな感じですね。