Development¶
Environment¶
| Tool | Version |
|---|---|
| Platform | WSL2 / Linux |
| Dev container | .devcontainer.json |
| HA Supervisor | 2026.03.0.dev (local) |
| Python | 3.12 (Alpine in container) |
The workspace is mounted into the HA Supervisor at
/data/addons/local/miniEMS/miniems/.
VSCode Tasks¶
All tasks are defined in .vscode/tasks.json.
| Task | Action |
|---|---|
| Start Home Assistant | Starts the supervisor if not running |
| Rebuild and Start Addon | Full rebuild: stops → removes container/image → builds → patches supervisor cache → starts → follows logs |
| Start Addon | Quick restart without rebuild |
Rebuild and Start — what it does¶
ha apps stop local_miniems
docker rm -f addon_local_miniems
docker rmi -f <image-id>
ha apps rebuild --force local_miniems
# Patch supervisor cache (dev bug workaround)
docker exec hassio_supervisor python3 -c "
import json; d=json.load(open('/data/addons.json'));
s=d['system']['local_miniems'];
s['schema']['long_lived_token']='str?';
s['options']['long_lived_token']='';
s['homeassistant_api']=True;
json.dump(d,open('/data/addons.json','w'))
"
ha apps start local_miniems
docker logs --follow addon_local_miniems
Why the cache patch? The dev version of the Supervisor (2026.03.0.dev) does not propagate
homeassistant_api: truefromconfig.yamlinto its in-memory state on reload. The patch writes directly to/data/addons.jsoninside the supervisor container. A full HA restart permanently fixes this.
File Structure¶
miniems/
├── config.yaml # Add-on manifest
├── Dockerfile # Build instructions
├── requirements.txt # Python dependencies
├── translations/ # UI translation source files
│ ├── de.yaml
│ └── en.yaml
└── rootfs/
└── usr/
└── bin/
├── main.py # Entry point
├── const.py # Shared constants & EMSMode enum
├── config_loader.py # Config + migration runner
├── migration.py # Schema migrations (v0→v5)
├── ha_ws_client.py # HA state reader (REST poll)
├── ha_sensor_publisher.py # HA state writer (REST POST)
├── ems_controller.py # Mode decision logic
├── cost_optimizer.py # Cost/savings accumulator
├── consumption_model.py # Load & PV yield prediction
├── weather_client.py # weather.get_forecasts client
├── inverter_controller.py # Inverter work-mode & power control
├── store.py # SQLite daily energy history
├── web_server.py # FastAPI dashboard + i18n
├── translations/ # UI strings (copied from source)
│ ├── de.yaml
│ └── en.yaml
├── templates/
│ ├── dashboard.html # Dashboard (Jinja2 + JS)
│ └── settings.html # Settings page
└── static/
├── style.css
└── icon.svg
Adding a New Config Field¶
- Add the field (with default) to the
Configdataclass inconfig_loader.py - Add it to
options:andschema:inconfig.yaml - If renaming or transforming an existing field, add a migration step in
migration.py, incrementCONFIG_SCHEMA_VERSIONinconst.py, and add the new migration function to the_MIGRATIONSchain
The current schema version is v5. The migration chain is:
v0→v1→v2→v3→v4→v5
Adding a New HA Sensor¶
Add a tuple to the _SENSORS list in ha_sensor_publisher.py:
(
"sensor.miniems_my_new_sensor", # entity_id
"my_status_key", # key in status_store dict
{
"friendly_name": "miniEMS My New Sensor",
"unit_of_measurement": "W",
"device_class": "power",
"state_class": "measurement",
"icon": "mdi:lightning-bolt",
},
),
The value must be present in the dict returned by EMSController.update().
Debugging¶
# Follow live logs
docker logs -f addon_local_miniems
# Inspect container environment
docker exec addon_local_miniems env | grep -E "SUPERVISOR|HASSIO"
# Test API access manually
docker exec addon_local_miniems wget -qO- \
--header "Authorization: Bearer $SUPERVISOR_TOKEN" \
http://hassio/homeassistant/api/ 2>&1
# Check persisted config
docker exec addon_local_miniems cat /data/config.json
Test weather forecast manually¶
# From inside the container – replace TOKEN and ENTITY as needed
TOKEN=$(docker exec addon_local_miniems sh -c 'echo $SUPERVISOR_TOKEN')
docker exec addon_local_miniems wget -qO- \
--header "Authorization: Bearer $TOKEN" \
--header "Content-Type: application/json" \
--post-data '{"entity_id":"weather.openweathermap","type":"daily"}' \
"http://hassio/homeassistant/api/services/weather/get_forecasts?return_response=true"
A successful response contains service_response → weather.openweathermap → forecast.
Known Supervisor Dev Issue¶
The Supervisor version 2026.03.0.dev does not update the in-memory addon
config from config.yaml on ha supervisor reload. Workaround:
- The Rebuild task patches
/data/addons.jsondirectly after each rebuild. - A full HA restart (
supervisor_runor reboot) loads the patched file cleanly.