feat: enerOS Site Intelligence MVP v0.1#13
Conversation
|
There was a problem hiding this comment.
Pull request overview
Implements the enerOS Site Intelligence MVP v0.1 end-to-end: a simulator generates site telemetry, a FastAPI backend ingests/persists it and derives alerts/recommendations, and a React/Vite dashboard visualizes the live operational picture (plus Docker Compose for one-command startup).
Changes:
- Expanded simulator into
file/history/livemodes with API posting support and containerization. - Added FastAPI + SQLAlchemy backend with analytics rules, seeded demo assets, and pytest coverage for endpoints/rules.
- Added a React/Vite/TypeScript dashboard (plus Nginx container) and local dev proxying.
Reviewed changes
Copilot reviewed 34 out of 36 changed files in this pull request and generated 14 comments.
Show a summary per file
| File | Description |
|---|---|
| services/simulator/simulate.py | Adds simulator modes, record generation, and API posting logic. |
| services/simulator/requirements.txt | Introduces Python dependencies for the simulator container build. |
| services/simulator/README.md | Documents simulator modes and environment variables. |
| services/simulator/Dockerfile | Containerizes the simulator for Docker Compose. |
| README.md | Updates repo-level docs for the MVP, quick starts, and scenarios. |
| docker-compose.yml | Adds full-stack dev composition (db/api/simulator/dashboard). |
| data/sample-telemetry.json | Updates sample telemetry payloads to match the newer schema/content. |
| apps/dashboard/vite.config.ts | Adds Vite dev server config including /api proxy. |
| apps/dashboard/tsconfig.json | Adds TypeScript compiler configuration for the dashboard. |
| apps/dashboard/src/types.ts | Defines dashboard domain types (assets/telemetry/alerts/recommendations). |
| apps/dashboard/src/main.tsx | Adds dashboard React entrypoint. |
| apps/dashboard/src/index.css | Adds global styling tokens and base styles. |
| apps/dashboard/src/components/TelemetryPanel.tsx | Live telemetry KPI panel UI. |
| apps/dashboard/src/components/RecommendationsPanel.tsx | Recommendations list UI with dismiss action. |
| apps/dashboard/src/components/AssetsPanel.tsx | Asset status list UI based on latest telemetry. |
| apps/dashboard/src/components/AlertsPanel.tsx | Alerts list UI with resolve action. |
| apps/dashboard/src/App.tsx | Main dashboard app: polling, state management, actions. |
| apps/dashboard/src/App.css | Dashboard layout and component styling. |
| apps/dashboard/README.md | Documents dashboard features and dev/build usage. |
| apps/dashboard/package.json | Adds dashboard npm metadata and deps (React/Vite/TS). |
| apps/dashboard/nginx.conf | Nginx config for SPA hosting + /api proxy in Docker. |
| apps/dashboard/index.html | Dashboard HTML entry for Vite build. |
| apps/dashboard/Dockerfile | Multi-stage Docker build for dashboard (build + Nginx). |
| apps/api/tests/test_api.py | Endpoint integration tests for API routes. |
| apps/api/tests/test_analytics.py | Unit tests for analytics alert/recommendation rules. |
| apps/api/tests/conftest.py | Test DB setup (StaticPool) and FastAPI dependency overrides. |
| apps/api/tests/init.py | Marks API tests package. |
| apps/api/requirements.txt | Pins API runtime + test dependencies. |
| apps/api/README.md | Documents API endpoints and how to run/test locally. |
| apps/api/models.py | Adds ORM models and Pydantic schemas. |
| apps/api/main.py | Adds FastAPI app, routes, DB init/seeding, and analytics integration. |
| apps/api/Dockerfile | Containerizes API service for Docker Compose. |
| apps/api/database.py | Adds SQLAlchemy engine/session setup and schema init. |
| apps/api/analytics.py | Implements analytics rules producing alerts/recommendations. |
| apps/api/init.py | Marks API package. |
| .env.example | Adds example env configuration for Docker Compose. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @@ -0,0 +1 @@ | |||
| requests==2.32.3 | |||
| ) | ||
| battery_soc = 60.0 | ||
| while True: | ||
| ts = datetime.now(tz=timezone.utc).replace(second=0, microsecond=0) |
| args = parser.parse_args() | ||
| mode = args.mode or "file" | ||
|
|
| battery_delta = net + generator_kw | ||
| battery_change = max(-10.0, min(10.0, battery_delta)) | ||
| battery_soc = round(max(0.0, min(100.0, battery_soc + battery_change)), 1) | ||
| battery_kw = round(battery_change, 2) | ||
|
|
||
| grid_kw = round(net + generator_kw - battery_change, 2) |
| record_ts = record.get("timestamp", ts) | ||
| if isinstance(record_ts, str): | ||
| record_ts = datetime.fromisoformat(record_ts.replace("Z", "+00:00")) | ||
| hour = record_ts.hour if hasattr(record_ts, "hour") else ts.hour | ||
|
|
| app.add_middleware( | ||
| CORSMiddleware, | ||
| allow_origins=["*"], | ||
| allow_methods=["*"], | ||
| allow_headers=["*"], | ||
| ) |
| def test_get_latest_telemetry(client): | ||
| r = client.get("/api/v1/telemetry/latest") | ||
| assert r.status_code == 200 | ||
| assert "solar_kw" in r.json() |
| from typing import Optional | ||
|
|
||
| from pydantic import BaseModel | ||
| from sqlalchemy import DateTime, Float, Integer, String, Text |
| alert_type: Mapped[str] = mapped_column(String(64), nullable=False) | ||
| severity: Mapped[str] = mapped_column(String(16), nullable=False) # info | warning | critical | ||
| message: Mapped[str] = mapped_column(Text, nullable=False) | ||
| resolved: Mapped[bool] = mapped_column(Integer, default=0) # SQLite bool compat |
| priority: Mapped[str] = mapped_column(String(16), nullable=False) # low | medium | high | ||
| message: Mapped[str] = mapped_column(Text, nullable=False) | ||
| action: Mapped[str] = mapped_column(Text, nullable=False) | ||
| dismissed: Mapped[bool] = mapped_column(Integer, default=0) |




Implements the full enerOS Site Intelligence MVP — a live operational picture of one simulated energy site, from raw telemetry through analytics to an operator dashboard.
Backend (
apps/api/)analytics.py) — deterministic rules evaluated on every ingested record:CRITICAL_BATTERY,LOW_BATTERY,HIGH_GRID_IMPORT,GENERATOR_RUNNING,SOLAR_UNDERPERFORM,HIGH_LOADCHARGE_BATTERY,REDUCE_GRID_IMPORT,SCHEDULE_LOADS,GENERATOR_TESTSimulator (
services/simulator/simulate.py)Three modes via CLI:
Physics model: 50 kW solar curve, 10 kW battery, 15 kW generator, base + peak load profile.
Dashboard (
apps/dashboard/)React 18 / Vite / TypeScript SPA — polls
/api/v1/*every 5 s. Four panels: live telemetry metrics, per-asset status, active alerts (resolvable), recommendations (dismissable). Vite dev proxy forwards/apitolocalhost:8000.Tests (
apps/api/tests/)40 pytest tests — full coverage of every API endpoint and every alert/recommendation rule using an in-memory SQLite
StaticPoolwith dependency override.One-command start
Dashboard:
http://localhost:5173· API docs:http://localhost:8000/docs