😀

[React]傘忘れ防止!Echo Showに雨の有無だけを表示するWebアプリを作る

2024/01/22に公開

傘忘れ防止!Echo Showに雨の有無だけを表示するWebアプリを作る

前置き

作ったいきさつとか

天気予報見てますか?

私は見てないです。
少し前では、朝起きたらテレビがあって天気予報を見るのは普通のことでしたが、昨今では家にテレビがないという人も多いのではないでしょうか。私もそのうちの一人です。
テレビがないとなると、今日の天気を知るという行為は、途端に主体性の必要な動作になってくるんですね。スマホで調べたりなんなりする必要がある。
こうなってくると、気象予報テクノロジーの恩恵を享受するハードルはとんでもなく上昇します。ダメ人間サイドの私は、家を出るときに雨が降っていなければ、傘を持ち出すことはなくなってしまいました。帰りに雨が降ったら濡れながら帰るかビニール傘を買うしかないのです。

スマートディスプレイで万事解決...?

テレビは今更買う気はしませんが、スマートディスプレイという選択肢がありますよね。私はEcho Show 5をブラックフライデーで買いました。これにて万事解決!と思いきや違うのです。
Alexaの提示する天気予報は難しいんですね。傘が必要なのかどうかが知りたいだけなのに、気温やら、湿度やら、情報過多な上に、肝心の降水確率は曖昧でよく分からない[1]。実家にいればおかんから「傘持っていきや」という簡潔でクリスプな出力を得られたので、なんとかなっていましたが、独身男性として世に放り出されたら詰むわけです。
本記事では、これを解決します。

本編 傘が必要かどうかだけをEcho Show 5に表示させ続けるWebアプリを作る

前置きが長くなりましたが、表題の通りのアプリを作ります。
Alexaならスキルじゃないの?と思われるかもしれませんが、あれは結構ややこしそうなので止めました。

以降はこんな構成です。

  • アプリ概要
  • 開発時のポイント1
  • 開発時のポイント2
  • ...

アプリ概要

動作フロー

  1. エリア選択
  2. 天気情報を取得
    2a. 晴れなら時計を表示
    2b. 雨なら警告を表示

※ 天気情報は5分ごとに更新

アプリ構成

言語,FW
  • Vite
  • TypeScript
  • React
  • Chakra UI

htmlに全部べた書きでも済むようなアプリですが、Reactに興味があったので、これを機に触ってみます。

気象データ

気象庁非公式APIから取得します。
後述しますが、CORS対応のものはこれしかありませんでした。

公開基盤

Github Pages使います。これも後述します。

ポイント1 気象庁APIの利用

気象庁APIとは

気象庁が以下のサイトで内部的に使用してるっぽいやつです。

https://www.jma.go.jp/bosai/map.html

気象庁が公式に提供しているAPIではないです
が、常識の範囲で使っても良さげなお達しは出てるのでお借りします。

https://twitter.com/e_toyoda/status/1364504338572410885

使い方

主な流れは以下です。
エリアコードを取得→天気を取得

エリアコードについて

以下からエリアコード全部載せのjsonを取得できます。

https://www.jma.go.jp/bosai/common/const/area.json

jsonの構成については以下がわかりやすかったので引用させていただきます。

気象庁の地域コードはcenters, offices, class10s, class15s, class20sという階層に分かれています。

階層名 対応する階層
centers 地方 近畿地方
offices 都道府県 京都府
class10s 位置 南部
class15s 代表都市 京都・亀岡
class20s 市町村 京都市

引用元:

https://qiita.com/yamato1413/items/2e02d1532f8779395a18

天気の取得

上記で取得した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が完結するので導入も簡単。

しかも無料!!

https://docs.github.com/ja/pages/getting-started-with-github-pages/about-github-pages

導入手順

設定ファイルの用意 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を以下のようにすれば解決しました。
image.png

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>

こちらのスライドのおかげで知りました。圧倒的感謝。

https://speakerdeck.com/arkw/amazon-echo-showxiang-keuebuapurifalsekai-fa?slide=34

成果物

リポジトリ

https://github.com/ymat19/WeatherReport

公開先(※裏で動画流してるので音が出ます)

https://ymat19.github.io/WeatherReport/

エリア選択
IMG20240122183727.jpg

傘がいらない場合
IMG20240122183755.jpg

傘が必要な場合
IMG20240122183738.jpg

感想

普段はどちらかというとバックエンド寄りの作業が多くて、フロントを触る機会があってもjQueryでDOM操作とかが主です。なので、今回触る技術の全部が新鮮でした。
便利なものが多くて楽しそうな界隈ですが、生業にするにはかなりハードルが高そう...
あとReactを触ってると、手続型?とだいぶ異なっていて、プログラミング学びたての頃のような新鮮な気持ちになれて楽しいですね。難しすぎる

脚注
  1. 私は降水確率の意味をよく理解してないです。知ってるふりをして今まで生きてきました。多分これからもそう。 ↩︎

GitHubで編集を提案

Discussion