[React]傘忘れ防止!Echo Showに雨の有無だけを表示するWebアプリを作る
傘忘れ防止!Echo Showに雨の有無だけを表示するWebアプリを作る
前置き
作ったいきさつとか
天気予報見てますか?
私は見てないです。
少し前では、朝起きたらテレビがあって天気予報を見るのは普通のことでしたが、昨今では家にテレビがないという人も多いのではないでしょうか。私もそのうちの一人です。
テレビがないとなると、今日の天気を知るという行為は、途端に主体性の必要な動作になってくるんですね。スマホで調べたりなんなりする必要がある。
こうなってくると、気象予報テクノロジーの恩恵を享受するハードルはとんでもなく上昇します。ダメ人間サイドの私は、家を出るときに雨が降っていなければ、傘を持ち出すことはなくなってしまいました。帰りに雨が降ったら濡れながら帰るかビニール傘を買うしかないのです。
スマートディスプレイで万事解決...?
テレビは今更買う気はしませんが、スマートディスプレイという選択肢がありますよね。私はEcho Show 5をブラックフライデーで買いました。これにて万事解決!と思いきや違うのです。
Alexaの提示する天気予報は難しいんですね。傘が必要なのかどうかが知りたいだけなのに、気温やら、湿度やら、情報過多な上に、肝心の降水確率は曖昧でよく分からない[1]。実家にいればおかんから「傘持っていきや」という簡潔でクリスプな出力を得られたので、なんとかなっていましたが、独身男性として世に放り出されたら詰むわけです。
本記事では、これを解決します。
本編 傘が必要かどうかだけをEcho Show 5に表示させ続けるWebアプリを作る
前置きが長くなりましたが、表題の通りのアプリを作ります。
Alexaならスキルじゃないの?と思われるかもしれませんが、あれは結構ややこしそうなので止めました。
以降はこんな構成です。
- アプリ概要
- 開発時のポイント1
- 開発時のポイント2
- ...
アプリ概要
動作フロー
- エリア選択
- 天気情報を取得
2a. 晴れなら時計を表示
2b. 雨なら警告を表示
※ 天気情報は5分ごとに更新
アプリ構成
言語,FW
- Vite
- TypeScript
- React
- Chakra UI
htmlに全部べた書きでも済むようなアプリですが、Reactに興味があったので、これを機に触ってみます。
気象データ
気象庁非公式APIから取得します。
後述しますが、CORS対応のものはこれしかありませんでした。
公開基盤
Github Pages使います。これも後述します。
ポイント1 気象庁APIの利用
気象庁APIとは
気象庁が以下のサイトで内部的に使用してるっぽいやつです。
気象庁が公式に提供しているAPIではないです
が、常識の範囲で使っても良さげなお達しは出てるのでお借りします。
使い方
主な流れは以下です。
エリアコードを取得→天気を取得
エリアコードについて
以下からエリアコード全部載せのjsonを取得できます。
https://www.jma.go.jp/bosai/common/const/area.json
jsonの構成については以下がわかりやすかったので引用させていただきます。
気象庁の地域コードは
centers, offices, class10s, class15s, class20s
という階層に分かれています。
階層名 | 対応する階層 | 例 |
---|---|---|
centers | 地方 | 近畿地方 |
offices | 都道府県 | 京都府 |
class10s | 位置 | 南部 |
class15s | 代表都市 | 京都・亀岡 |
class20s | 市町村 | 京都市 |
引用元:
天気の取得
上記で取得したofficesのコードを利用して、以下から天気の情報を取得できます。
https://www.jma.go.jp/bosai/forecast/data/forecast/<offices>.json
こちらで得られるjsonですが、気候や気圧,温度などいろいろな情報が入っていて、全貌は理解できてないです。
とりあえず、以下のように辿っていくと各エリアの天気が配列になって入ってます。ここでいうエリアとは先述のclass10s
に対応します。
weatherReport[0].timeSeries[0].areas
雨かどうかだけ知りたいならこんなコード(多分)
weatherReport[0].timeSeries[0].areas
.find((item) => item.area.code === <class10s>)
?.weathers?.[0]?.includes("雨") || false
とにかく複雑なjsonだったのですが、chatGPTに見せたらすぐ解説してくれて、ts用の型定義も作ってくれました。文明とOpenAIに感謝!
ポイント2 GitHub Pagesへのデプロイ
GitHub Pagesとは
ざっくり言うと、WebページをGitHubがホスティングしてくれる仕組みです。GitHub単体でCIが完結するので導入も簡単。
しかも無料!!
導入手順
設定ファイルの用意 deploy.yml
リポジトリ直下に↓のファイルを用意します
.github/workflows/deploy.yml
中身はこんな感じ
name: Build and Deploy
on: [push]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install and Build
run: |
yarn
yarn build
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./dist
chatGPTにプロジェクトの構成を教えたら作ってくれたものですが、問題なく動いてます。何を指示してるのかも結構わかりやすいですね。
GitLabのPagesはもっと分かりづらくて苦戦した記憶が
GitHub Pages トラブルシュート集
私が詰まったところ集
デプロイエラー Action failed with "The process '/usr/bin/git' failed with exit code 128"
CIの中でブランチ操作をする部分がありますが、そこが権限不足で失敗してるもよう。
リポジトリのSttings->Actions->General
と辿ったところにあるWorkflow permissions
を以下のようにすれば解決しました。
public配下のリソースが読み込めない
viteが作ってくれるpublicディレクトリは、普段↓のように参照できると思います。
<img src="/image.png" />
これを、このままPagesにデプロイすると読み込みに失敗します。↓のように修正する必要がありました。
<img src={`${import.meta.env.BASE_URL}/image.png`} />
正直理屈はあんまりわかってないですが、ビルドするとroot
=public
ではなくなるんですかね?GitHub Pagesに限らない話なのかもしれません。
ポイント3 スリープ防止の工夫
Echo Showの仕様として、ブラウザ(Silk)でサイトを開いていても、5分経つとホーム画面に戻るそうです。
裏で動画をループ再生することで、回避できるようなのでこんな実装をしてます。
<video
className="video"
id="video"
loop
autoPlay
style={{
position: "absolute",
zIndex: -1,
opacity: 0,
width: "100%",
height: "100%",
}}
>
<source
src={`${import.meta.env.BASE_URL}/sample-5s.mp4`}
type="video/mp4"
/>
</video>
こちらのスライドのおかげで知りました。圧倒的感謝。
成果物
リポジトリ
公開先(※裏で動画流してるので音が出ます)
エリア選択
傘がいらない場合
傘が必要な場合
感想
普段はどちらかというとバックエンド寄りの作業が多くて、フロントを触る機会があってもjQueryでDOM操作とかが主です。なので、今回触る技術の全部が新鮮でした。
便利なものが多くて楽しそうな界隈ですが、生業にするにはかなりハードルが高そう...
あとReactを触ってると、手続型?とだいぶ異なっていて、プログラミング学びたての頃のような新鮮な気持ちになれて楽しいですね。難しすぎる
-
私は降水確率の意味をよく理解してないです。知ってるふりをして今まで生きてきました。多分これからもそう。 ↩︎
Discussion