栽培管理アプリを作ってます⑩:気象庁APIで天気情報を自動取得する機能を実装した話

目次

はじめに

前回は農薬使用回数カウントとリセット履歴機能を実装しました。
今回は作業登録時に天気情報を自動取得する機能を実装したので、その話をしたいと思います。

栽培管理アプリで作業記録を残す際、「その日の天気」も一緒に記録しておくと便利で、後から振り返る際の重要な情報になるかと思っています。

今回実装した機能は以下の通り:

  • 作業登録時に気象庁APIから天気を自動取得
  • 作業履歴で天気と気温を表示
  • 過去の天気を手動で編集・追加
  • 気象庁ホームページの出典明記

実装した機能

1. 作業登録時の天気自動取得

作業を登録すると、その日の天気情報を気象庁APIから自動で取得してデータベースに保存する。

自動取得できる範囲:

  • 当日作業登録→その日の天気を取得
  • 作業しない日は天気を取得しない
  • 過去の日付は手動入力が必要

同じ日に複数回作業登録した場合:

  • 1回目:気象庁APIから取得してデータベースに保存
  • 2回目以降:データベースから取得(APIは呼ばない)

これにより、無駄なAPI呼び出しを防いでいる。

2. 作業履歴での天気表示

作業履歴ページで、各日付の天気と気温を表示する。

表示内容:

  • 天気:「雨後くもり」「晴れ時々くもり」など、気象庁のテキストデータをそのまま表示
  • 最高気温:自動取得
  • 最低気温:手動入力(後述の理由で自動取得不可)

表示例:2026/1/5 (月) 雨 昼前からくもり 後晴れ [天気編集]

3. 天気の手動編集機能

過去の作業や、自動取得できなかった日付の天気を手動で編集・追加できる。

編集方法:

  • プルダウンメニューから選択(晴れ、くもり、雨など)
  • 「その他」を選択するとテキストボックスで自由入力
  • 最高気温・最低気温も入力可能

4. 気象庁ホームページの出典明記

気象庁の利用規約に従い、ページ下部に出典を明記している。

※ 気象データ: 気象庁ホームページ

気象庁APIについて

無料で使える気象データ

気象庁はWeb表示用のJSONデータを公開しており、これを利用すれば無料で天気情報を取得できる。

エンドポイント:
https://www.jma.go.jp/bosai/forecast/data/forecast/{地域コード}.json

福岡県の例:
https://www.jma.go.jp/bosai/forecast/data/forecast/400000.json

ブラウザでこのURLを開くと、実際のデータを確認できる。

取得できるデータ

  • 本日の天気予報
  • 気温
  • 降水確率
  • 風向・風速

利用規約

気象庁のデータは以下の条件で利用可能:

  • 商用利用OK(無料)
  • 出典明記が必要(「気象庁ホームページ」と記載)
  • APIキー不要

実装時の課題

課題1:当日の最低気温が取得できない

問題:
気象庁APIでは、当日の最低気温は取得できない。

理由:
最低気温は通常、深夜から明け方に記録される。日中に予報を取得する時点では、すでに最低気温の時間帯が過ぎているため、予報データに含まれていない。

APIのデータ構造:

timeDefines: [
  "2026-01-05T09:00:00+09:00",  // [0] 今日 9時
  "2026-01-05T00:00:00+09:00",  // [1] 今日 0時
  "2026-01-06T00:00:00+09:00",  // [2] 明日 0時
  "2026-01-06T09:00:00+09:00"   // [3] 明日 9時
]

temps: [ '12', '12', '5', '12' ]
       [0]   [1]   [2]  [3]

最初の誤解:

  • temps[0] = 12°C → 今日9時の気温?(最高気温
  • temps[1] = 12°C → 今日0時の気温?(最高気温
  • temps[2] = 5°C → 明日0時の気温?(最低気温
  • temps[3] = 12°C → 明日9時の気温?(最高気温

実はtemps[0]temps[1]は両方とも最高気温を指している。今日の最低気温はAPIレスポンスに含まれていない。

ある日の気象庁の天気予報。確かに最高気温しか表示がない。

解決策:

未入力の場合は「?°C」と表示

temps[0]から最高気温のみ取得

最低気温は手動入力欄を用意(最低気温の取得はとりあえず後回しとした)

課題2:過去日付の天気は取得できない

問題:
翌日に前日の作業を登録する場合、気象庁APIでは「今日・明日・明後日」のデータしか取得できないため、前日の天気は取得不可。

対応策:

  • 過去日付では自動取得をスキップ
  • 手動編集で天気を入力

課題3:同じ日に何度も作業登録するとAPI呼び出しが増える

問題:
同じ日に複数の作業(防除、施肥、灌水など)を登録する場合、毎回APIを呼び出すと無駄が多い。

対応策:
データベースにキャッシュ機能を実装。一度取得した天気情報は永久保存し、同じ日の2回目以降はデータベースから取得する。

動作例:

  • 1/5 10時:防除を登録 → APIから取得 → DBに保存
  • 1/5 11時:施肥を登録 → DBから取得(API呼ばない)
  • 1/5 12時:灌水を登録 → DBから取得(API呼ばない)

実際の動作

今日の作業を登録した場合

  1. 作業登録画面で日付・作業内容を入力
  2. 登録ボタンを押す
  3. バックグラウンドで気象庁APIから天気を取得
  4. データベースに天気情報を保存
  5. 作業履歴で天気が表示される

過去の作業を登録した場合

  1. 作業登録画面で過去の日付を選択
  2. 登録ボタンを押す
  3. 天気の自動取得はスキップ(過去日付のため)
  4. 作業履歴で天気は空欄
  5. 「天気編集」ボタンから手動で入力

作業を削除した場合

  • 作業記録は削除される
  • 天気情報はデータベースに残る
  • 同じ日に再度作業を登録すると、天気も表示される

まとめ

今回、気象庁APIを使って天気情報の自動取得機能を実装しました。

実装した結果:

  • 作業登録時に天気を手入力する手間が省けた
  • 過去の作業を振り返る際、天気情報も確認できるようになった
  • 同じ日に複数作業を登録してもAPI呼び出しは1回だけで済む

今後の改善点:

  • 最低気温の自動入力(別のAPIや手法を検討)
  • 他の地域への対応(現在は福岡県のみ)
  • 過去の実測値データの取得方法

実装のポイント(コード例)

1. 気象庁APIから天気を取得

// 気象庁API(福岡県)
const areaCode = "400000";
const url = `https://www.jma.go.jp/bosai/forecast/data/forecast/${areaCode}.json`;

// APIを呼び出し
const response = await fetch(url, { cache: 'no-store' });
const data = await response.json();

// 天気テキストを取得
const timeSeries = data[0].timeSeries[0];
const weather = timeSeries.areas[0].weathers[0]; // 今日の天気

// 気温を取得
const tempSeries = data[0].timeSeries[2];
const temps = tempSeries.areas[0].temps;
const tempMax = parseFloat(temps[0]); // 最高気温のみ

2. データベースに保存

// Supabaseに保存
await supabase.from('cult_weather_records').insert({
  owner_id: user.id,
  date: '2026-01-05',
  weather: weather,           // 例:「雨後くもり」
  temperature_max: tempMax,   // 例:12
  temperature_min: null       // 手入力用にnull
});

3. 作業履歴で表示

// データベースから天気を取得
const { data: weatherRecords } = await supabase
  .from('cult_weather_records')
  .select('date, weather, temperature_max, temperature_min')
  .eq('owner_id', user.id);

// 日付ごとにマッピング
const weatherByDate = weatherRecords.reduce((acc, w) => {
  acc[w.date] = w;
  return acc;
}, {});

// 表示
{weatherByDate[date] && (
  <span>
    {weatherByDate[date].weather}
    {weatherByDate[date].temperature_max}°C / 
    {weatherByDate[date].temperature_min ?? '?'}°C
  </span>
)}

このように、気象庁APIからデータを取得してデータベースに保存し、作業履歴で日付ごとに表示していています。

目次