File size: 9,480 Bytes
13fc29d | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 | # CLAUDE.md
## Project Overview
**SolarWine** β Photosynthesis prediction and tracker control system for an agrivoltaic vineyard (*Vitis vinifera*) in Sde Boker, Israel.
Two-stage pipeline:
1. **Stage 1 (Mechanistic)**: Farquhar et al. (1980) model driven by on-site sensors (PAR, leaf temp, COβ, VPD) β net photosynthesis rate *A* (Β΅mol COβ/mΒ²/s)
2. **Stage 2 (ML)**: IMS weather station data β predict *A* without on-site sensors, enabling day-ahead forecasting
## Repository Layout
```
backend/ FastAPI REST API (routes, auth, workers)
config/ settings.py (paths, IMS channels, panel geometry)
context/ Project docs, todo, code review notes
frontend/ React + TypeScript + Vite SPA
scripts/ CLI tools (data download, pipeline, training)
src/ Core Python modules
advisor/ Day-ahead advisory engine
chatbot/ LLM integration (Google Gemini)
data/ IMS client, ThingsBoard client, DataHub
forecasting/ ML predictors, time-series, Chronos wrapper
models/ Farquhar model, phenology
shading/ Solar geometry, tracker optimizer
tracker/ Tracker optimization module
ui/ Streamlit UI utilities
app.py Legacy Streamlit dashboard
```
## Tech Stack
**Backend**: Python 3.12, FastAPI, uvicorn, pydantic, PyJWT, slowapi, sentry-sdk
**ML/Science**: pandas, numpy, scikit-learn, xgboost, pvlib, scipy, torch, chronos-forecasting (HuggingFace)
**LLM**: google-genai (Gemini)
**Frontend**: React 18, TypeScript 5, Vite 5, Tailwind CSS, shadcn/ui, Recharts, TanStack React Query, React Router 6
**Data sources**: IMS API (station 43, Sde Boker), ThingsBoard (MQTT/REST), on-site sensors
**Deploy**: HuggingFace Spaces (backend, port 7860), Cloudflare Pages (frontend), Streamlit Community Cloud (legacy)
## Environment Setup
```bash
# Python (from repo root)
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
pip install -r backend/requirements.txt
# Frontend
cd frontend && npm install
```
Required `.env` variables:
```
IMS_API_TOKEN=<token>
JWT_SECRET=<secret>
ADMIN_PASSWORD=<password>
# Optional
SENTRY_DSN=<dsn>
ALLOWED_ORIGINS=http://localhost:5173,https://solarwine.pages.dev
```
## Common Commands
### Backend
```bash
# Dev server (auto-reload)
uvicorn backend.api.main:app --reload --port 7860
# Production
uvicorn backend.api.main:app --host 0.0.0.0 --port 7860
```
### Frontend
```bash
cd frontend
npm run dev # Vite dev server β http://localhost:5173
npm run build # Production build β dist/
npm run lint # ESLint
npm run test # Vitest
npm run test:watch # Watch mode
```
### Legacy Streamlit
```bash
streamlit run app.py
```
### Data & Pipelines
```bash
# Download IMS weather data
python -m scripts.download_ims_data --from 2024-01-01 --to 2025-12-31
# Full Stage 1 β Stage 2 pipeline
python -m scripts.run_pipeline
# Fine-tune Chronos (long-context forecasting)
python scripts/run_chronos_long_training.py --device cpu --context-days 28 --num-steps 4000
# Generate trimmed sample CSV for cloud deploy
python -m scripts.create_sample_data
# Control system simulation / validation
python -m scripts.run_control_simulation
python -m scripts.verify_control_system
# Budget audit (compliance report)
python -m src.budget_audit --report # weekly rollup
python -m src.budget_audit --daily 2026-03-29 # single day
# Load test (requires: pip install locust)
locust -f scripts/load_test.py --host https://solarwine-api.hf.space \
--users 10 --spawn-rate 2 --run-time 5m --headless
```
## Architecture Notes
### Backend (FastAPI)
- **`DataHub`** (`src/data/data_providers.py`) β singleton facade over all providers; injected via `backend/api/deps.py`
- **Routes** (`backend/api/routes/`): `health`, `weather`, `sensors`, `energy`, `photosynthesis`, `control`, `chatbot`, `biology`, `login`, `events` (~27 endpoints)
- **Auth**: JWT issued at `/api/auth/login`; guest read-only mode when `JWT_SECRET` unset
- **Middleware**: CORS, rate-limiting (60 req/min via slowapi), request logging, global exception handler β JSON errors
- **Workers** (`backend/workers/`): async background tasks for daily planner and control ticks
- **Services** (`backend/services/`): `DataFlowMonitor` (per-source health), `EmailAlerter` (SMTP alerts on red status)
- **Background loops**: IMS refresh (2h), sensor poll (2min), data flow alert check (5min) β all push SSE events
### Core Python Modules
| Module | Purpose |
|---|---|
| `src/models/farquhar_model.py` | Leaf photosynthesis (FvCB mechanistic, Semillon sigmoid 28β32Β°C transition, vectorized `compute_all()`) |
| `src/data/ims_client.py` | IMS REST API client |
| `src/data/data_providers.py` | DataHub facade (6 services: Weather, VineSensor, PS, Energy, Advisory, Biology) |
| `src/data/thingsboard_client.py` | ThingsBoard REST client (22 devices, 4 trackers, plant asset) |
| `src/forecasting/predictor.py` | Multi-model ML regressor (LR/DT/RF/GBR/XGB) |
| `src/forecasting/ts_predictor.py` | Multi-horizon lag-based time-series |
| `src/forecasting/chronos_forecaster.py` | HuggingFace Chronos wrapper |
| `src/shading/tracker_optimizer.py` | Tilt-angle simulation & stress scheduling |
| `src/shading/solar_geometry.py` | Sun position, shadow projection, canopy PAR |
| `src/shading/tradeoff_engine.py` | InterventionGate (pipeline pattern) + minimum-dose offset search |
| `src/control_loop.py` | Real-time 15-min control orchestration (DI via `__init__()`) |
| `src/budget_audit.py` | Slot-level budget audit log (parquet) + weekly compliance report |
| `src/energy_budget.py` | Hierarchical YearβMonthβWeekβDayβSlot budget planner |
| `src/command_arbiter.py` | 5-level priority stack + hysteresis filter |
| `src/tracker_dispatcher.py` | Send tilt commands to TB trackers, verify execution |
| `src/advisor/day_ahead_advisor.py` | Gemini-powered daily planning engine |
| `src/day_ahead_planner.py` | DP trajectory optimizer for daily slot plans |
| `src/chatbot/vineyard_chatbot.py` | Gemini chatbot with tool dispatch + guardrails |
| `src/chatbot/guardrails.py` | Query classifier (EN+HE), response validator, confidence estimation, range validation, cross-source consistency |
| `backend/services/data_flow_monitor.py` | Per-source data freshness monitor (green/yellow/red) |
| `backend/services/email_alerter.py` | SMTP email alerts with per-source cooldown |
### Frontend
- **Pages**: Home, Agro, Trackers, Power, Monitoring (alarms + system health), Advisor, Control, Photosynthesis, Shading, Docs, Research
- **Custom hooks** (`src/hooks/`): `useWeather`, `useEnergy`, `useSensors`, `useChatbot`, `useControl`, `useAuth`, `useDataFlowStatus`, `useEventStream`
- **API client**: `src/lib/` β typed wrappers around backend endpoints
- **Auth**: JWT stored in `localStorage`; TanStack React Query for server state
### Data Flow
```
IMS API βββ [Redis/CSV cache] βββ Backend βββ API Routes βββ React Frontend
ThingsBoard sensors βββββββββββββ DataHub βββ API Routes
Farquhar + ML models ββββββββββββ PhotosynthesisService βββ /photosynthesis/*
TrackerOptimizer + EnergyBudget β ControlSystem βββ /control/*
DataFlowMonitor βββββββββββββββββ /health/data-sources βββ DataFlowStatus component
β EmailAlerter βββ SMTP alerts
Backend events ββββββββββββββββββ SSE /events/stream βββ auto-invalidate React Query
```
## Key Files to Know
- `config/settings.py` β central config (site coordinates, IMS channel IDs, panel geometry, budget params)
- `backend/api/main.py` β FastAPI app entry point (middleware, router registration)
- `backend/api/routes/` β all API endpoint implementations (~27 endpoints)
- `backend/workers/control_tick.py` β 15-min control loop cron entry point
- `backend/workers/daily_planner.py` β daily plan generation cron entry point
- `src/models/farquhar_model.py` β core mechanistic model
- `src/control_loop.py` β main control loop (sensors β plan β gate β arbiter β dispatch)
- `src/energy_budget.py` β hierarchical energy budget planner
- `src/chatbot/guardrails.py` β anti-hallucination guardrails (query classifier, range validation, cross-source checks)
- `backend/services/data_flow_monitor.py` β data source health monitoring
- `backend/services/email_alerter.py` β SMTP email alerts for data outages
- `backend/api/routes/events.py` β SSE event stream for live frontend updates
- `frontend/src/lib/api.ts` β API client with JWT auth
- `frontend/src/hooks/` β TanStack Query hooks for all API endpoints
- `scripts/load_test.py` β Locust load test (16 weighted endpoints)
- `context/3_todo.md` β current work items and backlog
- `ims_api_documentation.md` β IMS API reference (Hebrew + English)
## Deployment
| Platform | Target | Notes |
|---|---|---|
| HuggingFace Spaces | Backend | Docker, port 7860, see `backend/HF_README.md` |
| Cloudflare Pages | Frontend | `VITE_API_URL` env var points to HF backend |
| Streamlit Cloud | Legacy app | `IMS_API_TOKEN` secret, falls back to `sensors_wide_sample.csv` |
Large files (`Data/Seymour/sensors_wide.csv` ~982 MB, `outputs/`) are gitignored. Cloud deployments use `Data/Seymour/sensors_wide_sample.csv`.
|