Metadata-Version: 2.4
Name: franklinwh-system-view
Version: 0.2.0
Summary: A friendly picture of a FranklinWH site (grid, aGate, batteries, solar, home, circuits) shared by the FranklinWH bridges: payload schema, layout and the overlay page
Author: david2069
License: MIT
Project-URL: Source, https://github.com/david2069/franklinwh-system-view
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: test
Requires-Dist: pytest>=8.0; extra == "test"
Dynamic: license-file

# franklinwh-system-view

A friendly picture of a FranklinWH site, shared by the FranklinWH bridges: grid, aGate,
batteries, solar, home, smart circuits and generator, with live flows. It opens as a
full-page overlay over a bridge's own dashboard, and can be the page a browser starts on.

- **Simple by default.** Pictures and plain words: battery charge, mode, what the inverter
  is doing, grid up or down, solar, home use, circuits. Hover for a sentence, click for details.
- **Fits any screen.** Desktop and tablet get a landscape layout, phones a portrait one.
  Zoom with − / Fit / +, pinch, or Ctrl+wheel; drag to pan when zoomed.
- **Colours mean state.** Green normal, grey offline or disabled, amber warning, red critical.
- **Only what's there is drawn.** A site with no solar shows no solar.

## How a bridge uses it

```python
from fastapi.staticfiles import StaticFiles
import franklinwh_system_view as sv

app.mount("/system-view", StaticFiles(directory=sv.static_dir()), name="system-view")

@app.get("/api/system")
def api_system():
    return sv.build(my_payload())      # validates, then adds both layouts per gateway
```

```html
<link rel="stylesheet" href="system-view/system-view.css">
<script src="system-view/system-view.js"></script>
<script>FWHSystemView.mount({endpoint: "api/system"});</script>
<button onclick="FWHSystemView.open()">System view</button>
```

**Customise diagram.** Where no reading tells the bridge how a site is built, the user
tells it. The bridge stores the answers (one JSON object) and lets the package do the rest:

```python
raw = my_payload()
p = sv.customise.apply(raw, saved)                     # names, legs, models, solar, appliances
p["customise"] = {"endpoint": "api/system/customise", "fields": sv.customise.fields(raw, saved)}
return sv.build(p)

@app.put("/api/system/customise")
def save(values: dict):
    store(sv.customise.clean(values, my_payload()))   # ValueError → 400
```

**Weather.** Put the current Open-Meteo reading in `site.weather` (`code`, `condition`,
`temp_c`); the page draws it next to the site's name.

The payload is described in `schema.py`; `fixtures/` holds examples. Signs: grid
`power_w` > 0 imports, battery `power_w` > 0 discharges. Leave out what you can't read.

## Try it

```bash
python -m franklinwh_system_view.demo us_tou_two_apowers_solar
```

Design: franklinwh-direct-connect-bridge #428.
