Home Assistant setup¶
Solar AI Optimizer is an external application that connects to Home Assistant over REST and WebSocket. For fail-safe and software updates from HA itself, install the HACS custom integration (Home Assistant 2026.7+).
Install from oraad/solar-ai-integration — not this repository (this repo is the Solar app / HA Apps add-on only).
A legacy YAML fail-safe package still exists for older setups; prefer the integration and disable the package when both would run.
Choose your deployment path:
| Path | When to use |
|---|---|
| Supervisor app | HAOS or Supervised — recommended for most HA users |
| Docker + hass_ingress | Standalone container on the same network as HA |
| Standalone Docker | Direct :8000 access; optional local admin login |
| HA custom integration | Fail-safe + Updates in HA (pairs with any of the above) |
After connecting, complete entity mapping. For fail-safe, use the custom integration (or optionally the legacy package).
Long-lived access token¶
Required for Docker and Proxmox when Solar must write inverter entities (the HA app uses the Supervisor token when fields are left empty). Prefer IndieAuth in Solar Settings when available.
The HACS integration talks to Solar with a pairing code (not this LLAT).
Scripts may still use env API_TOKEN.
- In Home Assistant, open your Profile (bottom-left avatar).
- Scroll to Security → Long-Lived Access Tokens.
- Click Create Token, name it (e.g.
solar-ai-optimizer), and copy the token immediately — it is shown only once. - In the optimizer dashboard → Settings → Home Assistant connection:
- URL:
http://homeassistant.local:8123or your HA IP (e.g.http://192.168.1.10:8123) - Token: paste the long-lived token
- Verify SSL: enable if HA uses HTTPS with a valid certificate
For the HA app, leave URL/token empty to use http://supervisor/core and SUPERVISOR_TOKEN.
Rotate tokens periodically and revoke unused tokens from the same Security page.
Supervisor app¶
- Settings → Apps → App store → ⋮ → Custom repositories → add:
https://github.com/oraad/solar-ai-optimizer - Install Solar AI Optimizer and start it.
- Open the ingress panel from the HA sidebar.
- In Settings, configure latitude/longitude, PV arrays, and inverter entities.
The app pulls ghcr.io/oraad/solar-ai-optimizer from GHCR (version tag from the app manifest); no build on the HA host.
Settings, telemetry, and learned models persist on the Supervisor /data volume. run.sh forces DATA_DIR=/data on app startup (overriding the image default /app/data) so UI config survives restarts and upgrades.
App options (Supervisor UI) map to environment variables via run.sh:
| App option | Environment variable |
|---|---|
prerelease_updates |
ADDON_PRERELEASE_UPDATES |
shadow_mode |
SHADOW_MODE |
log_level |
LOG_LEVEL |
ha_base_url / ha_token |
HA_BASE_URL / HA_TOKEN |
solcast_api_key |
SOLCAST_API_KEY |
api_token |
API_TOKEN |
Ingress is trusted automatically when running as a Supervisor app (SUPERVISOR_TOKEN); set TRUST_INGRESS_HEADERS=true for external Docker/Proxmox deployments. This enables proxied user identity and X-Frame-Options: SAMEORIGIN for the sidebar panel.
See Roles and access for admin vs viewer behavior.
App updates¶
- The HA app store manifest promotes stable releases only. Pre-release builds publish to GHCR but do not change the store version until a stable GA release.
- Update via Settings → Apps → Solar AI Optimizer → Update when Supervisor shows an update.
- The in-app Software updates section is hidden on HA App installs (updates are managed by Supervisor).
- Optional Pre-release updates (app configuration): when enabled and the app is restarted, the optimizer checks for newer beta/RC builds and logs when one is available. Update manually via Settings → Apps when Supervisor offers a matching version. Users already on a beta build stay on it until a stable GA release or manual reinstall.
Docker with hass_ingress¶
Use when the optimizer runs as a separate container but HA users should open it from the HA sidebar.
1. Optimizer container¶
Example docker-compose.yml service on the same Docker network as Home Assistant:
services:
solar-ai-optimizer:
image: ghcr.io/oraad/solar-ai-optimizer:latest
container_name: solar-ai-optimizer
restart: unless-stopped
environment:
SHADOW_MODE: "true"
TRUST_INGRESS_HEADERS: "true"
DATA_DIR: /app/data
DATABASE_URL: sqlite+aiosqlite:////app/data/solar.db
# Optional direct admin access to :8000 (keep port unpublished if ingress-only):
# LOCAL_ADMIN_USERNAME: admin
# LOCAL_ADMIN_PASSWORD_HASH: ...
# SESSION_SECRET: ...
volumes:
- solar-data:/app/data
networks:
- homeassistant
# Do not publish 8000 publicly when using ingress-only access.
networks:
homeassistant:
external: true # or shared with your HA stack
volumes:
solar-data:
Configure HA URL/token in Settings after first start, or set HA_BASE_URL / HA_TOKEN in environment.
2. Home Assistant ingress block¶
Add to configuration.yaml:
ingress:
solar_ai:
title: Solar AI
icon: mdi:solar-power-variant
require_admin: false
work_mode: ingress
url: http://solar-ai-optimizer:8000
headers:
X-Remote-User-Id: $user_id
X-Remote-User-Name: $username
X-Remote-User-Display-Name: $user_name
Reload ingress: Developer tools → YAML → INGRESS.
Requires TRUST_INGRESS_HEADERS=true on the optimizer so HA can embed the panel in the sidebar (X-Frame-Options: SAMEORIGIN).
Full auth patterns: Roles and access.
Standalone Docker¶
docker compose up -d --build
Open http://localhost:8000 directly. Optionally enable local admin login via
LOCAL_ADMIN_PASSWORD_HASH and SESSION_SECRET (see Configuration).
Set HA URL and token in Settings — no ingress wrapper required.
Home Assistant packages¶
Packages let you split YAML configuration into files under config/packages/.
Enable packages in configuration.yaml¶
If not already present:
homeassistant:
packages: !include_dir_named packages
Restart Home Assistant or reload core configuration after adding this block.
Fail-safe heartbeat package¶
Copy the example package into your HA config:
config/packages/solar-optimizer-failsafe.yaml
Source file in the repository:
examples/home-assistant/packages/solar-optimizer-failsafe.yaml
The package creates:
| Entity | Purpose |
|---|---|
input_datetime.solar_optimizer_heartbeat |
Heartbeat timestamp (site-local wall clock, pulsed by optimizer) |
input_number.solar_optimizer_heartbeat_stale_s |
Stale threshold (seconds) for healthy sensor |
input_number.solar_optimizer_max_grid_charge_a |
Max grid charge current for fail-safe automation |
binary_sensor.solar_optimizer_healthy |
Template sensor (as_datetime \| as_local age check) |
Before reloading, edit placeholders:
switch.YOUR_GRID_CHARGE_ENTITY— same as Settings → Inverter → Grid charge enablenumber.YOUR_MAX_GRID_CHARGE_CURRENT— same as Settings → Inverter → Max grid charge currentinput_number.solar_optimizer_max_grid_charge_ainitial — match Settings → Grid charge → Max grid charge current (A)
Reload helpers, templates, and automations. Then configure the optimizer side: Home Assistant fail-safe.
Inverter entity discovery¶
The optimizer uses a vendor-agnostic entity map in Settings → Inverter entity map. Logical capabilities (battery SOC, PV power, grid charge enable, etc.) map to your HA entity IDs. When HA is connected, fields offer autocomplete from live entities.
Use Developer tools → States to find entity IDs. The tables below are starting points — naming varies by integration version and device model.
Read sensors¶
| Capability | Deye / Sunsynk (MSA) | Victron (Venus / HA) | Growatt |
|---|---|---|---|
pv_power |
sensor.*_pv*_power or sensor.*_solar_power |
sensor.*_pv_power |
sensor.*_pv_power |
load_power |
sensor.*_load_power |
sensor.*_ac_consumption |
sensor.*_load_power |
battery_soc |
sensor.*_battery_soc |
sensor.*_soc |
sensor.*_battery_soc |
battery_power |
sensor.*_battery_power |
sensor.*_battery_power |
sensor.*_battery_power |
grid_power |
sensor.*_grid_power |
sensor.*_grid_power |
sensor.*_grid_power |
grid_present |
binary_sensor.*_grid_connected |
binary_sensor.*_ac_input |
binary_sensor.*_grid_status |
battery_temp |
sensor.*_battery_temperature |
sensor.*_battery_temperature |
sensor.*_battery_temp |
Write controls¶
| Capability | Deye / Sunsynk (MSA) | Victron | Growatt |
|---|---|---|---|
grid_charge_enable |
switch.*_grid_charge |
integration-specific | switch.*_grid_charge |
max_grid_charge_current |
number.*_grid_charge_current |
number.*_max_charge_current |
number.*_max_grid_charge |
Load shedding¶
Each tier accepts multiple switch entities (pool pump + heater, AC power switch, etc.).
Use switch.* or input_boolean.* entities for power control.
Companion entities (climate, select, fan, etc.) on the same Home Assistant device are discovered automatically and snapshotted when shedding; they are restored when the tier comes back. Devices that were off before shedding are never turned on by restore.
Per-tier options:
| Field | Purpose |
|---|---|
restore_enabled |
Restore on SOC when soc >= restore_above_soc |
restore_on_grid |
Restore when grid is present (if global flag is on) |
state_entities |
Optional override map of power entity → companion entity IDs |
Omit a key in state_entities to autodiscover companions; set [] for switch-only.
Configure in the dashboard Load shedding tab. Grid-charge write entities are not required for shedding-only deployments (use the shed-only preset on that tab). You still need inverter read sensors for battery SOC and grid presence.
See Dashboard user guide → Load-shedding tiers.
Outdoor temperature (optional)¶
Settings → Forecast → Temperature → Outdoor sensor entity — any sensor.* reporting
°C for temperature-aware load forecasting.
Verification checklist¶
- Dashboard top bar shows HA connected (not offline).
- Overview status cards show live SOC, PV, and load values.
- Forecast tab shows a 48-hour chart (requires latitude/longitude in Settings).
- Settings entity fields autocomplete when typing (requires valid token).
- Fail-safe:
input_datetime.solar_optimizer_heartbeatupdates in HA Developer tools (if package imported).
Troubleshooting¶
| Symptom | What to check |
|---|---|
| HA offline | URL reachable from container; token valid; SSL setting matches HA |
| Empty status cards | Read entities mapped correctly; entities not unavailable in HA |
| No forecast | Latitude/longitude set; not 0,0 |
| Writes fail | Write entities mapped; shadow mode off; HA reachable |
| Ingress 401/403 | TRUST_INGRESS_HEADERS=true; ingress URL matches container hostname |
Related guides¶
- Installation — Docker, HA app, Proxmox
- Home Assistant fail-safe — heartbeat tuning
- Roles and access — admin vs viewer
- Configuration — env vars and persistence