Skip to main content

Lightweight FastAPI service for DER device registration, telemetry ingestion, and basic control workflows.

Project description

GridOS (under construction)

License: MIT Python 3.11+ CI FastAPI

GridOS is a lightweight FastAPI service for DER device registration, telemetry ingestion, telemetry lookup, and basic control workflows.

The repository still contains broader experimental areas such as digital twin simulation, forecasting, and optimisation. Those modules remain available for contributors. The supported first-run experience is intentionally smaller so that a new user can clone the repository, start the API, send telemetry, and confirm a working result without being forced into a large deployment.

What The Current Release Supports

Area Supported launch scope
API service FastAPI app with /, /health, /docs, device routes, telemetry routes, and control routes
Telemetry Single and batch ingestion, latest-value lookup, and bounded history queries
Control Command acceptance with honest adapter status reporting
Live device connectivity Modbus TCP and MQTT adapters with built-in device/broker simulators; connect, poll live telemetry, and dispatch control over REST
Register maps Named Modbus register maps including SunSpec-style inverter and battery presets, plus inline custom maps
Browser demo A no-terminal /demo page that drives the full device lifecycle for prospects
Economic dispatch & ROI Value-stacked battery dispatch (arbitrage + demand-charge + degradation) and a baseline-vs-optimised ROI backtest, via /api/v1/economics/*
Authentication Optional API-key gate on mutating endpoints (GRIDOS_REQUIRE_AUTH), off by default
Default storage In-memory mode for local development and demos
Persistent storage SQLite file backend with no external service or extra dependencies
Optional persistence InfluxDB and TimescaleDB when configured explicitly
Packaging Editable install, reduced dependency groups, Docker image, and CI workflows

What Is Still Experimental

Area Current position
Protocol adapters Present in the repository but not part of the launch-critical path
Digital twin simulation Experimental helper modules, not required for first use
Forecasting Optional module, not mounted in the default app
Optimisation Optional module, not mounted in the default app
Large multi-service deployment Deferred until the core local path stays stable

Why The Scope Is Smaller

This smaller scope is intentional. It is better for GridOS to be simple, reliable, and truthful than broad and internally inconsistent. The current work focuses on a dependable end-to-end path that works from a fresh clone. Experimental modules are still available for contributors, but the public launch story now matches what the repository can support immediately.

Architecture At A Glance

flowchart LR
    A[Client or Script] --> B[FastAPI Service]
    B --> C[Device Routes]
    B --> D[Telemetry Routes]
    B --> E[Control Routes]
    D --> F[In-Memory Storage by Default]
    F --> G[History and Latest Queries]
    D -. optional .-> H[InfluxDB]
    D -. optional .-> I[TimescaleDB]
    J[Experimental Modules] -. not in default app .-> B

Repository Layout

Path Role
src/gridos/main.py Active FastAPI entry point for the reduced launch path
src/gridos/api/ API routes, dependency wiring, and WebSocket manager
src/gridos/models/ Small Pydantic model surface for the supported workflow
src/gridos/storage/ Storage interface plus optional persistent backends
src/gridos/digital_twin/ Experimental simulation and ML helpers kept outside the default runtime path
docs/ Documentation aligned to the current supported scope
requirements/ Reduced dependency groups for base, dev, ml, and production
tests/ Regression tests for the lightweight supported path

Quick Start

Run from source

git clone https://github.com/iceccarelli/GridOS.git
cd GridOS
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
cp .env.example .env
uvicorn gridos.main:app --host 0.0.0.0 --port 8000 --reload

Then open:

http://localhost:8000/docs

Run with Docker Compose

cp .env.example .env
docker compose up --build

Then open:

http://localhost:8000/docs

Live Device Connectivity (Modbus)

GridOS can talk to real DER hardware over Modbus TCP, and ships a built-in device simulator so the full loop is demonstrable without hardware:

pip install -e ".[adapters]"

# Terminal 1 — emulate a battery on Modbus TCP:
gridos simulate --port 5020

# Terminal 2 — run the API, then drive the device over REST:
gridos serve

Register a device with an adapter_config, then connect, poll live telemetry, and dispatch control:

BASE=http://127.0.0.1:8000/api/v1
curl -s -X POST $BASE/devices/register -H 'Content-Type: application/json' -d '{
  "device": {"device_id":"batt-1","name":"Battery","der_type":"battery","rated_power_kw":100},
  "adapter_config": {"protocol":"modbus_tcp","host":"127.0.0.1","port":5020}
}'
curl -s -X POST $BASE/devices/batt-1/connect      # attach + connect the adapter
curl -s -X POST $BASE/devices/batt-1/poll         # read LIVE telemetry, persist + broadcast it
curl -s -X POST $BASE/control/batt-1 -H 'Content-Type: application/json' \
     -d '{"device_id":"batt-1","mode":"power_setpoint","setpoint_kw":40}'

A complete scripted walkthrough (including a restart to prove device persistence) lives at scripts/demo_modbus.sh.

Register maps (SunSpec)

The Modbus adapter resolves a register map from adapter_config["register_map"], which may be a named preset or an inline custom map. Presets include gridos_default, sunspec_inverter, and sunspec_battery:

{"protocol": "modbus_tcp", "host": "127.0.0.1", "port": 5020, "register_map": "sunspec_inverter"}

The sunspec_* presets approximate the SunSpec information models for common inverter/battery measurement points using fixed scale factors; full SunSpec scale-factor decoding is a future enhancement, and inline maps cover exact hardware. The simulator can emulate any map: gridos simulate seeds registers from the chosen layout.

Live Device Connectivity (MQTT)

For EV chargers and IoT gateways that push telemetry, GridOS ships an MQTT adapter and a self-contained broker simulator:

# Terminal 1 — broker simulator that also publishes battery telemetry:
gridos simulate --protocol mqtt --port 1883

# Register an MQTT device and drive it the same way as Modbus:
curl -s -X POST $BASE/devices/register -H 'Content-Type: application/json' -d '{
  "device": {"device_id":"ev-1","name":"EV Charger","der_type":"ev_charger","rated_power_kw":11},
  "adapter_config": {"protocol":"mqtt","host":"127.0.0.1","port":1883,
                     "telemetry_topic":"gridos/mqtt-sim/telemetry"}
}'
curl -s -X POST $BASE/devices/ev-1/connect
curl -s -X POST $BASE/devices/ev-1/poll

For production, point the adapter at any MQTT broker (e.g. Mosquitto).

Browser Demo

Run gridos serve and open http://127.0.0.1:8000/demo — a no-terminal page that registers a device, connects its adapter, polls live telemetry (with an auto-poll mode), and dispatches a setpoint, all from the browser. Start gridos simulate alongside it and a prospect can watch the full loop without touching a command line.

Economic Dispatch & ROI

GridOS can answer the question a battery owner actually cares about: how much money does this asset make? The economics engine solves a value-stacked MILP (PuLP/CBC) that minimises the total electricity bill across three streams — energy arbitrage, monthly demand-charge reduction, and throughput-based degradation cost — then backtests the optimised schedule against a no-battery baseline.

pip install -e ".[economics]"   # pulls the PuLP solver

# Representative-day demo (prints savings + payback):
PYTHONPATH=src python scripts/roi_demo.py

# Or over REST:
BASE=http://127.0.0.1:8000/api/v1
curl -s -X POST $BASE/economics/roi -H 'Content-Type: application/json' -d '{
  "load_kw": [50, 50, 120, 120, 60, 60, 50, 50],
  "solar_kw": [0, 0, 30, 40, 20, 10, 0, 0],
  "battery": {"capacity_kwh": 215, "max_discharge_kw": 100, "capex": 95000}
}'

The economics routes are mounted by default. Without the [economics] extra they return a clear 503 with remediation rather than crashing the app.

ROI figures are representative-day backtests under perfect foresight of load and solar — illustrative, not guarantees. A receding-horizon (MPC) controller and per-site interval data are the honest next steps before quoting a figure.

Authentication

By default GridOS runs open, which suits local development and demos. To require credentials on mutating endpoints, set two environment variables:

GRIDOS_REQUIRE_AUTH=true
GRIDOS_API_KEYS=gos_your_first_key,gos_your_second_key

When enabled, POST /api/v1/devices/register, DELETE /api/v1/devices/{id}, POST /api/v1/telemetry/, POST /api/v1/telemetry/batch, and POST /api/v1/control/{id} require a matching X-API-Key header. Read endpoints remain open. Check the current posture at GET /api/v1/auth/status.

Default Runtime Behavior

The default .env.example enables in-memory storage. That means the first run does not require any external database.

Mode Intended use
GRIDOS_USE_INMEMORY_STORAGE=true Local development, demos, and validation
GRIDOS_USE_INMEMORY_STORAGE=false + GRIDOS_STORAGE_BACKEND=sqlite Persistent local file storage, no external service
GRIDOS_USE_INMEMORY_STORAGE=false + InfluxDB config Explicit persistent backend setup
GRIDOS_USE_INMEMORY_STORAGE=false + TimescaleDB config Explicit persistent backend setup

Installation Targets

Install target Command
Core development path pip install -e ".[dev]"
Add persistent storage drivers pip install -e ".[storage]"
Add adapter extras pip install -e ".[adapters]"
Add ML extras pip install -e ".[ml]"

Testing

Protect the supported scope first.

pytest tests/test_api.py tests/test_models.py tests/test_storage.py -v --tb=short

Documentation Guide

The most important docs for the current release are:

Document Purpose
docs/quickstart.md Get a working local instance running
docs/deployment.md Understand the supported deployment story
docs/api_reference.md Confirm the active and optional API surface
docs/models.md Understand the real model layer
docs/adapters.md See the adapter framework boundaries
docs/architecture.md See the reduced launch architecture

Contributing

Contributions are welcome, especially when they improve startup reliability, telemetry handling, testing, packaging, and documentation consistency. The priority is to strengthen the lightweight path before expanding the public scope again.

License

GridOS is released under the MIT License.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gridos-0.3.0.tar.gz (98.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

gridos-0.3.0-py3-none-any.whl (117.8 kB view details)

Uploaded Python 3

File details

Details for the file gridos-0.3.0.tar.gz.

File metadata

  • Download URL: gridos-0.3.0.tar.gz
  • Upload date:
  • Size: 98.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.1

File hashes

Hashes for gridos-0.3.0.tar.gz
Algorithm Hash digest
SHA256 2debf6fb9b69bc81da8ed97cc3ce51c72af17fceb477b0d8203d184a7b43b519
MD5 8070bcb8af40a64507af9646f4bc41e5
BLAKE2b-256 0a92bcae1d4a87493fe00ab95b261643d21943e661245e45fcc18a659db23f0c

See more details on using hashes here.

File details

Details for the file gridos-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: gridos-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 117.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.1

File hashes

Hashes for gridos-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 985b0d176b01edca327fc323c93fc915b0dfe0f6991dc488e609b90ebbd6ddc8
MD5 51c4c7847cb579c1445cc7f355c40d6d
BLAKE2b-256 bd072666deb23f800af7b716c59d7b1a97f59f2ef4e69e0d8a2959a767dce4ad

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page