|
| 1 | +<div align="center"> |
1 | 2 |
|
| 3 | +<img src="https://raw.githubusercontent.com/PSCourtney/solar-array-card/main/logo.png" alt="Solar Array Card logo" width="120" /> |
| 4 | + |
| 5 | +<img width="476" height="399" alt="image" src="https://github.com/user-attachments/assets/852c420d-7ab9-4295-ba61-0b3e91476787" /> |
| 6 | + |
| 7 | +# Solar Array Card |
| 8 | + |
| 9 | +A Home Assistant custom Lovelace card that visualizes solar arrays and per-panel power output. Each array becomes a row of panels, and each panel's fill intensity reflects its current power relative to the array's nominal wattage. |
| 10 | + |
| 11 | +[![GitHub Release][release-shield]][release-url] |
| 12 | +[![Downloads][downloads-shield]][release-url] |
| 13 | +[![HACS Custom][hacs-shield]][hacs-url] |
| 14 | +[![License][license-shield]](LICENSE) |
| 15 | + |
| 16 | +[](https://my.home-assistant.io/redirect/hacs_repository/?owner=PSCourtney&repository=solar-array-card&category=Dashboard) |
| 17 | + |
| 18 | +</div> |
| 19 | + |
| 20 | +[release-shield]: https://img.shields.io/github/v/release/PSCourtney/solar-array-card?style=flat-square |
| 21 | +[release-url]: https://github.com/PSCourtney/solar-array-card/releases |
| 22 | +[downloads-shield]: https://img.shields.io/github/downloads/PSCourtney/solar-array-card/total?style=flat-square |
| 23 | +[hacs-shield]: https://img.shields.io/badge/HACS-Custom-41BDF5?style=flat-square |
| 24 | +[hacs-url]: https://github.com/hacs/integration |
| 25 | +[license-shield]: https://img.shields.io/github/license/PSCourtney/solar-array-card?style=flat-square |
| 26 | + |
| 27 | +## Features |
| 28 | + |
| 29 | +- **Per-panel SVG layout** — each array becomes a row of panel tiles, each showing its own watts read-out and a fill bar relative to nominal capacity. |
| 30 | +- **Top TOTAL row** — grand total across all arrays, auto-formatted as W or kW. |
| 31 | +- **Visual GUI editor** — full `ha-form` editor with collapsible array/panel sections, color picker per array, and a demo-mode toggle for previewing layouts with fake values. |
| 32 | +- **Aggregated mode** — set a single sensor on an array and every panel mirrors that one reading (icon state only). For inverters that only expose a per-string total. |
| 33 | +- **Live accent colour** — any panel producing >0 W lights up the array's chosen accent (amber by default). Array totals, the top TOTAL, the compass needle all switch in sync. |
| 34 | +- **OFFLINE state** — totals reading 0 W or with an unavailable entity collapse to an "OFFLINE" label; panels switch to a slashed-panel icon in dim grey. |
| 35 | +- **Compass facing badge** — per-array N/NE/E/.../NW indicator with a half-accent / half-grey needle that rotates to the configured direction. Per-panel facing override available. |
| 36 | + |
| 37 | +## Installation |
| 38 | + |
| 39 | +### HACS |
| 40 | + |
| 41 | +1. Open HACS in Home Assistant. |
| 42 | +2. Click the three-dot menu → **Custom repositories**. |
| 43 | +3. Add `PSCourtney/solar-array-card` with category **Dashboard**. |
| 44 | +4. Install **Solar Array Card** and refresh your browser. |
| 45 | + |
| 46 | +Or use the one-click button in the badge above. |
| 47 | + |
| 48 | +### Manual |
| 49 | + |
| 50 | +1. Download `solar-array-card.js` from the [latest release](https://github.com/PSCourtney/solar-array-card/releases). |
| 51 | +2. Copy it to `<config>/www/community/solar-array-card/solar-array-card.js`. |
| 52 | +3. In **Settings → Dashboards → Resources**, add: |
| 53 | + - URL: `/local/community/solar-array-card/solar-array-card.js` |
| 54 | + - Type: **JavaScript Module** |
| 55 | +4. Refresh your browser. |
| 56 | + |
| 57 | +## Usage |
| 58 | + |
| 59 | +The card has a built-in visual editor — add it to your dashboard and the GUI form will guide you through arrays and panels. The YAML below is what the editor produces under the hood. |
| 60 | + |
| 61 | +```yaml |
| 62 | +type: custom:solar-array-card |
| 63 | +title: Solar Roof # optional header |
| 64 | +show_total: true # default; set false to hide the TOTAL row |
| 65 | +arrays: |
| 66 | + - name: South |
| 67 | + nominal_w: 450 |
| 68 | + facing: S |
| 69 | + color: "#fbbf24" # amber (default — omit to use the global default) |
| 70 | + panels: |
| 71 | + - name: S1 |
| 72 | + entity: sensor.panel_s1_power |
| 73 | + - name: S2 |
| 74 | + entity: sensor.panel_s2_power |
| 75 | + - name: S3 |
| 76 | + entity: sensor.panel_s3_power |
| 77 | + facing: SE # per-panel facing override |
| 78 | + - name: S4 |
| 79 | + entity: sensor.panel_s4_power |
| 80 | + |
| 81 | + - name: Fence |
| 82 | + nominal_w: 450 |
| 83 | + facing: W |
| 84 | + color: "#10b981" # emerald |
| 85 | + panels: |
| 86 | + - name: F1 |
| 87 | + entity: sensor.panel_f1_power |
| 88 | + - name: F2 |
| 89 | + entity: sensor.panel_f2_power |
| 90 | + |
| 91 | + # Aggregated array — single sensor drives every panel's icon state. |
| 92 | + # Use this when your inverter only exposes a per-string total. |
| 93 | + - name: Garage |
| 94 | + entity: sensor.garage_string_power |
| 95 | + facing: SW |
| 96 | + panels: |
| 97 | + - name: G1 |
| 98 | + - name: G2 |
| 99 | + - name: G3 |
| 100 | +``` |
| 101 | +
|
| 102 | +## Configuration |
| 103 | +
|
| 104 | +### Card |
| 105 | +
|
| 106 | +| Key | Type | Required | Default | Description | |
| 107 | +| ------------ | ------- | -------- | ------- | ------------------------------------------------------------------------------------------------------------ | |
| 108 | +| `type` | string | yes | — | `custom:solar-array-card` | |
| 109 | +| `title` | string | no | — | Card header text (currently informational; the SVG renders TOTAL/array names directly). | |
| 110 | +| `show_total` | boolean | no | `true` | Show or hide the top **TOTAL** row. | |
| 111 | +| `demo_mode` | boolean | no | `false` | Render seeded fake values for previewing the layout. Toggle from the editor; switch off before going live. | |
| 112 | +| `arrays` | list | yes | — | One or more arrays (see below). | |
| 113 | + |
| 114 | +### Array |
| 115 | + |
| 116 | +| Key | Type | Required | Default | Description | |
| 117 | +| ----------- | ------ | -------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | |
| 118 | +| `name` | string | no | — | Display name shown on the array's row. | |
| 119 | +| `entity` | string | no | — | If set, **aggregated mode**: this single sensor drives every panel's on/offline state. Per-panel watts are hidden. | |
| 120 | +| `nominal_w` | number | no | `450` | Per-panel nominal wattage. Used for the progress-bar fill ratio. Override per panel below. | |
| 121 | +| `facing` | string | no | — | One of `N`, `NE`, `E`, `SE`, `S`, `SW`, `W`, `NW`. Renders a compass badge on the array row. | |
| 122 | +| `color` | string | no | `#fbbf24` | Any CSS colour (`#10b981`, `dodgerblue`, `hsl(160 80% 45%)`). Drives the active accent for this array's panels, totals, divider, and compass needle. | |
| 123 | +| `panels` | list | yes | — | Panel definitions. | |
| 124 | + |
| 125 | +### Panel |
| 126 | + |
| 127 | +| Key | Type | Required | Default | Description | |
| 128 | +| ----------- | ------ | ------------------------------- | ------------------ | -------------------------------------------------------------------------------------------------------------------------- | |
| 129 | +| `name` | string | no | — | Panel label rendered under the icon. | |
| 130 | +| `entity` | string | yes (no, if array is aggregated) | — | Sensor reporting this panel's power in watts. | |
| 131 | +| `nominal_w` | number | no | array's `nominal_w` | Override the array default for this specific panel. Drives the fill ratio. | |
| 132 | +| `facing` | string | no | — | One of `N`, `NE`, `E`, `SE`, `S`, `SW`, `W`, `NW`. Shown next to the panel name (e.g. `S1 · SE`) when the panel is active. | |
| 133 | + |
| 134 | +## Visual states |
| 135 | + |
| 136 | +Each panel reads at a glance: |
| 137 | + |
| 138 | +| State | When | Visual | |
| 139 | +| -------- | ----------------------------------------------------- | --------------------------------------------------------------------- | |
| 140 | +| Active | Panel reports >0 W (or array is producing in aggregated mode) | Bolt-overlay icon in array accent colour, watts read-out lit, fill bar in accent. | |
| 141 | +| Offline | Panel reads 0 W, or its entity is `unavailable`/`unknown` | Slashed-panel icon in dim grey, watts hidden. | |
| 142 | + |
| 143 | +Array and top totals follow the same logic: they switch to accent the moment any panel reports >0 W, and show **OFFLINE** when their total is 0 W. |
| 144 | + |
| 145 | +## Demo mode |
| 146 | + |
| 147 | +Set `demo_mode: true` (or tick the box in the editor) to render the card with seeded fake panel values. Useful for previewing layouts, taking screenshots, and seeing how each visual state looks without real sensors. The toggle lives in the editor's card-level form; switch it off before saving the dashboard. |
| 148 | + |
| 149 | +## Development |
| 150 | + |
| 151 | +```bash |
| 152 | +npm install |
| 153 | +npm run watch # rebuilds dist/solar-array-card.js on change |
| 154 | +``` |
| 155 | + |
| 156 | +Copy `dist/solar-array-card.js` into `<config>/www/` (or set up a Lovelace resource pointing at a dev server) to test in HA. |
| 157 | + |
| 158 | +## License |
| 159 | + |
| 160 | +[MIT](LICENSE) |
0 commit comments