Files
keinasystem/document/12_マスタードキュメント_気象データ編.md
Akira 6e99164e3f Triliumに記録しました。
ドキュメント整備が全て完了しました。今回のセッションで行った作業のまとめ:

実装した機能

Windmill フロー f/weather/weather_sync(毎朝6時 Asia/Tokyo)の作成・本番稼働
/weather フロントエンドページ(年別集計 / 期間指定の2モード)
Recharts 3.7.0 による月別・日次グラフ(気温折れ線、降水量棒+日照折れ線 2軸)
整備したドキュメント

ドキュメント	内容
CLAUDE.md	weather 画面追加・Windmill フロー・マスタードキュメントリンク
document/12_マスタードキュメント_気象データ編.md	気象機能の完全リファレンス(新規作成)
MEMORY.md	Windmill API パターン・Recharts TypeScript パターン
Trilium マスタードキュメント	フロントエンド2モード・Recharts・document/12_ 参照追加
2026-02-28 14:05:32 +09:00

7.6 KiB
Raw Permalink Blame History

気象データ機能 マスタードキュメント

最終更新: 2026-02-28 状態: 本番稼働中


概要

Open-Meteo archive API から窪川の気象データを日次取得し、PostgreSQL に蓄積する。 農業における積算温度計算・類似年分析・作期の気象振り返りを目的とする。

  • 観測地点: 窪川 (lat=33.213, lon=133.133)
  • データソース: Open-Meteo Archive API(無料)
  • 蓄積期間: 2016-01-01 〜 前日(毎朝自動更新)
  • Django アプリ: backend/apps/weather/

データモデル

WeatherRecord (apps/weather/models.py)

フィールド 説明
date DateField (unique) 日付
temp_mean FloatField nullable 平均気温 (℃)
temp_max FloatField nullable 最高気温 (℃)
temp_min FloatField nullable 最低気温 (℃)
sunshine_h FloatField nullable 日照時間 (h)
precip_mm FloatField nullable 降水量 (mm)
wind_max FloatField nullable 最大風速 (m/s)
pressure_min FloatField nullable 最低気圧 (hPa)

Crop.base_temp (apps/plans/models.py に追加):

  • FloatField, default=0.0
  • GDD有効積算温度計算の基準温度

API エンドポイント (/api/weather/)

POST /api/weather/sync/

  • 認証: X-API-KeyMAIL_API_KEY 設定値、Windmill と共用)
  • 用途: Windmill から日次データを受け取り upsert
  • リクエスト: 単一オブジェクトまたはリスト
  • レスポンス: {"saved": N} or {"saved": N, "errors": [...]}
[
  {
    "date": "2026-02-27",
    "temp_mean": 8.5, "temp_max": 14.2, "temp_min": 3.1,
    "sunshine_h": 6.3, "precip_mm": 0.0,
    "wind_max": 4.2, "pressure_min": 1008.0
  }
]

GET /api/weather/records/

  • 認証: JWT
  • クエリパラメータ:
    • ?year=2025 — 年指定
    • ?start=2025-05-01&end=2025-09-30 — 日付範囲指定
  • レスポンス: WeatherRecord の配列date 昇順)

GET /api/weather/summary/?year=2025

  • 認証: JWT
  • レスポンス:
{
  "year": 2025,
  "monthly": [
    {
      "month": 1,
      "temp_mean_avg": 5.2, "temp_max_avg": 10.1, "temp_min_avg": 0.8,
      "precip_total": 45.0, "sunshine_total": 98.3, "wind_max": 9.5,
      "hot_days": 0, "cold_days": 8, "rainy_days": 12
    },
    ...
  ],
  "annual": {
    "temp_mean_avg": 16.1, "precip_total": 2310.0, "sunshine_total": 1850.5,
    "hot_days": 12, "cold_days": 25
  }
}
  • hot_days: 最高気温 ≥ 35℃ の日数
  • cold_days: 最低気温 < 0℃ の日数
  • rainy_days: 降水量 ≥ 1.0mm の日数

GET /api/weather/gdd/

  • 認証: JWT
  • 用途: 播種日〜現在の有効積算温度Growing Degree Daysを計算
  • クエリパラメータ:
    • ?start_date=2025-05-15 (必須) — 起算日
    • ?base_temp=10 (省略時=0) — 基準温度 ℃
    • ?end_date=2025-09-30 (省略時=昨日)
  • レスポンス:
{
  "start_date": "2025-05-15",
  "end_date": "2025-09-30",
  "base_temp": 10.0,
  "total_gdd": 1342.5,
  "records": [
    {"date": "2025-05-15", "temp_mean": 18.2, "daily_gdd": 8.2, "cumulative_gdd": 8.2},
    ...
  ]
}
  • 日積算温度 = max(0, 平均気温 - 基準温度)

GET /api/weather/similarity/?year=2026

  • 認証: JWT
  • 用途: 今年 1/1〜昨日 の気象パターンと過去年を比較し、類似年 Top3 を返す
  • アルゴリズム: (平均気温, 総降水量, 総日照時間) の正規化ユークリッド距離
  • レスポンス:
{
  "target_year": 2026,
  "comparison_period": "1/1〜2/27",
  "target_features": {"mean_temp": 7.3, "total_precip": 185.0, "total_sunshine": 240.5},
  "similar_years": [
    {
      "year": 2020, "distance": 0.312,
      "features": {...},
      "monthly": [...]
    }
  ]
}

管理コマンド

# 全期間取得(初回のみ)
docker compose exec backend python manage.py fetch_weather --full

# 差分取得(最終レコード翌日〜昨日)
docker compose exec backend python manage.py fetch_weather

# 任意期間
docker compose exec backend python manage.py fetch_weather --start-date 2025-01-01 --end-date 2025-12-31

仕様:

  • 年単位で Open-Meteo API を呼び出しAPI 制限回避のため分割)
  • upsert: 既存データを上書き更新
  • --full: 2016-01-01 から昨日まで(初回投入用)

Windmill フロー

項目
パス f/weather/weather_sync
スケジュール 0 0 6 * * *(毎朝 6:00 Asia/Tokyo
スクリプト windmill/u/admin/weather_sync.flow/a.inline_script.py
状態 本番稼働中windmill.keinafarm.net

使用 Windmill Variables:

変数名 内容
u/admin/KEINASYSTEM_API_KEY API キー(メール機能と共用)
u/admin/KEINASYSTEM_API_URL https://keinafarm.net

フロントエンド画面 (/weather)

年別集計モード(デフォルト)

  • 年セレクタ (2016〜現在)
  • 年間サマリーカード: 平均気温 / 年間降水量 / 年間日照時間 / 猛暑日数・冬日数
  • グラフタブ: 月別気温折れ線(最高・平均・最低)、月別降水量棒 + 日照時間折れ線2軸
  • 月別サマリータブ: 12ヶ月のテーブル
  • 直近14日タブ: 日次データテーブルWindmill 同期確認用)

期間指定モード

  • 開始日・終了日の date input + 「表示」ボタン
  • 期間集計カード: 期間の平均気温 / 総降水量 / 総日照時間 / 猛暑日・冬日
  • グラフタブ: 日次気温折れ線 + 日次降水量棒+日照折れ線
    • X軸ラベル自動間引き30日以内→3日おき、3ヶ月→週1、半年→2週、1年超→月1
    • 60日以内はドット表示あり
  • 一覧タブ: 日次データテーブル(スクロール対応)

使用ライブラリ: Recharts 3.7.xfrontend/package.json に登録済み)


ファイル索引

ファイル 役割
backend/apps/weather/models.py WeatherRecord モデル
backend/apps/weather/views.py 5つのAPIビュー
backend/apps/weather/urls.py URL設定
backend/apps/weather/serializers.py Serializer
backend/apps/weather/admin.py 管理画面登録
backend/apps/weather/migrations/0001_initial.py 初回マイグレーション
backend/apps/weather/management/commands/fetch_weather.py 管理コマンド
backend/apps/plans/migrations/0004_crop_base_temp.py Crop.base_temp 追加
frontend/src/app/weather/page.tsx 気象画面400行
windmill/u/admin/weather_sync.flow/a.inline_script.py Windmill Python スクリプト
windmill/u/admin/weather_sync.flow/flow.yaml Windmill フロー定義

将来計画Phase 2 以降)

  1. GDD 到達日予測: Crop.base_temp を使い、播種日から目標GDDに達する日を予測
  2. 類似年ベースの収穫予測: 類似年の収穫時期を参考に今年の予測を表示
  3. 作付け計画との連携: 作期ごとの気象サマリーを圃場詳細に表示
  4. 気象アラート: 猛暑・長雨・強風などの異常気象を検知して通知

注意事項

  • Open-Meteo archive API は前日までのデータしか取得できない(リアルタイム不可)
  • pressure_minsurface_pressure_min(地表気圧)。海面更正気圧とは異なる
  • Open-Meteo の sunshine_duration は秒単位 → sunshine_h = 秒 ÷ 3600 で変換