Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

- **Fixed** the optional **Hampel outlier filter** (`HAMPEL_WINDOW`) freezing your grid reading permanently. After any lasting change in the house — solar arriving, an oven switching on — the filter treated every later reading as an outlier and kept reporting the value from before the change, for as long as AstraMeter ran, leaving the batteries steering against a stale number. It now holds a real change back only until enough readings agree (about half the window), while still rejecting genuine spikes. Also fixed wildly wrong per-phase values when the total briefly passed near zero. Affects both the Python service and the ESPHome component ([#587](https://github.com/tomquist/astrameter/pull/587)).

- **Added** a **live status dashboard**: one page showing grid power, your batteries, power-source health and — when AstraMeter is steering them — each battery's target and the balancer's internal state, plus the ability to change your configuration and steer individual batteries without editing files. On by default and able to change things: in the Home Assistant add-on it opens from the sidebar, and running AstraMeter yourself it is at `http://<host>:52500/`. That address has no login of its own, so set `DASHBOARD_ALLOW_WRITE = False` for a read-only page, or `DASHBOARD_ENABLED = False` to serve nothing. See [docs/dashboard.md](docs/dashboard.md) ([#577](https://github.com/tomquist/astrameter/pull/577), [#604](https://github.com/tomquist/astrameter/pull/604), [#615](https://github.com/tomquist/astrameter/pull/615), [#617](https://github.com/tomquist/astrameter/pull/617)).
- **Added** a **live status dashboard**: one page showing grid power, your batteries, power-source health and — when AstraMeter is steering them — each battery's target and the balancer's internal state, plus the ability to change your configuration and steer individual batteries without editing files. On by default and able to change things: in the Home Assistant add-on it opens from the sidebar, and running AstraMeter yourself it is at `http://<host>:52500/`. That address has no login of its own, so set `DASHBOARD_ALLOW_WRITE = False` for a read-only page, `WEB_CONFIG_ENABLED = False` to keep only the configuration out of it, or `DASHBOARD_ENABLED = False` to serve nothing but the health check. Open it by IP address, `localhost`, a `.local` or a `.home.arpa` name; any other name — a reverse proxy, or a router-assigned one such as `astrameter.fritz.box` — is refused until you add it to `DASHBOARD_ALLOWED_HOSTS`. See [docs/dashboard.md](docs/dashboard.md) ([#577](https://github.com/tomquist/astrameter/pull/577), [#604](https://github.com/tomquist/astrameter/pull/604), [#615](https://github.com/tomquist/astrameter/pull/615), [#617](https://github.com/tomquist/astrameter/pull/617), [#618](https://github.com/tomquist/astrameter/pull/618)).

- **Added** the same **live status dashboard to the ESPHome component**, served by the ESP32 itself at `http://<device>/` with no configuration at all, showing grid power, every battery and the balancer's state. If you already use ESPHome's `web_server:`, the page moves to `http://<device>/astrameter/` and ESPHome's own page gains a link to it. Add `controls: true` under `dashboard:` to steer batteries from the page, or `dashboard: false` to leave it out of the firmware; see [docs/dashboard.md](docs/dashboard.md#esphome-on-an-esp32) ([#605](https://github.com/tomquist/astrameter/pull/605), [#606](https://github.com/tomquist/astrameter/pull/606), [#607](https://github.com/tomquist/astrameter/pull/607)).
- **Added** the **ESPHome native API** as a power source (`[ESPHOMENATIVE]`): AstraMeter reads power data from an esphome device via the native API. This should be more performant than the polling mechanism of the ESPHOME component. See [docs/powermeters.md](docs/powermeters.md#esphomenative) ([#566](https://github.com/tomquist/astrameter/pull/566))
Expand Down
14 changes: 10 additions & 4 deletions config.ini.example
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ DEVICE_TYPE = shellypro3em
# DEVICE_IDS = shellypro3em-c59b15461a21
# Skip initial powermeter test on startup
SKIP_POWERMETER_TEST = False
# Enable the web-based configuration editor at http://<host>:<port>/config (opt-in, default False)
# The web-based configuration editor at http://<host>:<port>/config. Left
# unset it follows DASHBOARD_ENABLED below, whose Configuration tab is that
# editor. Set it to True to serve the editor with no dashboard, or to False
# to refuse it even with one — False also takes the dashboard's Configuration
# tab away, and is the way to keep an unauthenticated port from editing this
# file at all.
# WEB_CONFIG_ENABLED = False
# The live status dashboard at http://<host>:<port>/ (default True).
# Shows grid power, every battery's target and reported power, power-source
Expand All @@ -25,9 +30,10 @@ SKIP_POWERMETER_TEST = False
# way in and the dashboard is already served there.
# DASHBOARD_DIRECT_ACCESS = False
# Extra host names the web port answers under, comma-separated. IP addresses,
# localhost and .local names always work, so most setups need nothing here.
# Add a name only if you reach the dashboard through one that resolves via a
# nameserver — a reverse proxy or a private DNS entry. Names are refused by
# localhost, .local and .home.arpa names always work, so most setups need
# nothing here. Add a name if you reach the dashboard through one that
# resolves via a nameserver — a reverse proxy, a private DNS entry, or a
# router-assigned name such as astrameter.fritz.box. Names are refused by
# default because a name is the one part of the address another website can
# aim at this port from your browser (DNS rebinding), and this port has no
# login to fall back on.
Expand Down
42 changes: 35 additions & 7 deletions docs/dashboard.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ Two add-on options control it:
|---|---|---|
| `dashboard_allow_write` | `true` | Lets the dashboard change configuration and control batteries. Turn it off for a read-only dashboard. |
| `dashboard_direct_access` | `false` | Also serves the page on `http://<host>:52500` **with no authentication**. See [Security](#security). |
| `dashboard_allowed_hosts` | empty | Extra host names that port answers under, comma-separated. IP addresses, `localhost` and `.local` names always work — needed only behind a reverse proxy or a private DNS entry. See [Security](#only-addresses-that-cannot-be-pointed-here). |
| `dashboard_allowed_hosts` | empty | Extra host names that port answers under, comma-separated. IP addresses, `localhost`, `.local` and `.home.arpa` names always work — needed for a reverse proxy, a private DNS entry, or a router-assigned name such as `astrameter.fritz.box`. See [Security](#only-addresses-that-cannot-be-pointed-here). |

This holds for a `custom_config` file too: `DASHBOARD_ENABLED` and
`ENABLE_WEB_SERVER` in that file are ignored, because the sidebar panel and the
Expand All @@ -106,7 +106,7 @@ The port follows `WEB_SERVER_PORT`. Nothing else is needed: outside the add-on
there is no Home Assistant in front of the page, so this address is the
dashboard, unauthenticated — see [Security](#security).

Two keys in `[GENERAL]` narrow it:
Keys in `[GENERAL]` narrow it:

```ini
[GENERAL]
Expand All @@ -115,12 +115,28 @@ DASHBOARD_ALLOW_WRITE = False
# Stop serving the dashboard — only the health check is left, plus the
# standalone config editor if WEB_CONFIG_ENABLED is on (default True).
DASHBOARD_ENABLED = False
# Drop the Configuration tab and the /config editor behind it, keeping the
# rest of the page. Left unset it follows DASHBOARD_ENABLED above; set it to
# True to keep /config served even with the dashboard off.
WEB_CONFIG_ENABLED = False
Comment thread
coderabbitai[bot] marked this conversation as resolved.
# Extra host names this port answers under, comma-separated. IP addresses,
# localhost and .local names always work, so this is only needed if you
# reach the dashboard through a reverse proxy or a private DNS entry.
# localhost, .local and .home.arpa names always work, so this is only needed
# if you reach the dashboard through a reverse proxy, a private DNS entry, or
# a router-assigned name such as astrameter.fritz.box.
DASHBOARD_ALLOWED_HOSTS = astrameter.example.lan
```

`WEB_CONFIG_ENABLED` decides whether there is a configuration surface at all,
not whether the page may write. It has three states: left out it follows the
dashboard, `True` serves the editor even with `DASHBOARD_ENABLED = False`, and
`False` refuses it even with the dashboard on. If you set it in an earlier
release, it still means what it said — the dashboard does not override it.

That makes it the narrower of the two switches: `DASHBOARD_ALLOW_WRITE = False`
makes the whole page read-only, batteries included, while `WEB_CONFIG_ENABLED =
False` leaves the battery controls working and takes only the configuration
away.

### ESPHome on an ESP32

On by default — there is nothing to add. Flash a `ct002:` configuration and
Expand Down Expand Up @@ -159,7 +175,7 @@ those who run that sub-block — but:
|---|---|---|
| `controls` | `false` | Lets the page change batteries: manual target, auto/manual, active, distribution weight, efficiency window, min DC output, and the device's active control / force rotation. |
| `path` | `/`, or `/astrameter` when `web_server:` is configured | Where the page is mounted. |
| `allowed_hosts` | empty | Extra host names the device answers under. Its IP address, `localhost` and its `.local` mDNS name always work — needed only behind a reverse proxy. See [Security](#only-addresses-that-cannot-be-pointed-here). |
| `allowed_hosts` | empty | Extra host names the device answers under. Its IP address, `localhost`, its `.local` mDNS name and any `.home.arpa` name always work — needed behind a reverse proxy or for a router-assigned name. See [Security](#only-addresses-that-cannot-be-pointed-here). |
| `web_server_link` | `true` | Adds a link to the dashboard at the top of ESPHome's own page. Only does anything when `web_server:` is configured. |
| `id` | generated | The usual ESPHome component id. |

Expand Down Expand Up @@ -371,7 +387,14 @@ under addresses that could not have got there that way:
- **`localhost`** and any **`.local`** name — `.local` is mDNS, resolved on
your link rather than by a nameserver someone outside can answer for. This
covers every ESPHome device, which mDNS names automatically.
- **Names you list yourself**, for a reverse proxy or a private DNS entry:
- Any **`.home.arpa`** name — the suffix reserved for home networks
([RFC 8375](https://www.rfc-editor.org/rfc/rfc8375)). The DNS root delegates
it to nobody, so there is no outside nameserver to poison.
- **Names you list yourself**, for a reverse proxy, a private DNS entry, or a
name your router hands out — `astrameter.fritz.box` and `nas.lan` are
refused until you list them, because `.box` is a real top-level domain and
`.lan` an ordinary label, so unlike the three above a nameserver *can* be
asked about them:
`DASHBOARD_ALLOWED_HOSTS` (comma-separated) in `config.ini`,
`dashboard_allowed_hosts` in the add-on, `allowed_hosts:` under the ESPHome
`dashboard:` block.
Expand Down Expand Up @@ -406,7 +429,12 @@ address is refused, check that AstraMeter is running, that you are on the port
than an IP address, and that name is not one AstraMeter answers under — see
[Security](#only-addresses-that-cannot-be-pointed-here). Use the IP address, or
add the name to `DASHBOARD_ALLOWED_HOSTS` (`dashboard_allowed_hosts` in the
add-on, `allowed_hosts:` on ESPHome).
add-on, `allowed_hosts:` on ESPHome). A name your router hands out, such as
`astrameter.fritz.box`, needs listing like any other.

**The Configuration tab is gone.** `WEB_CONFIG_ENABLED = False` is set — it
takes the tab and the `/config` editor with it, leaving the rest of the page.
Remove the line to have it follow the dashboard again.

**"Lost contact with AstraMeter."** The page could not reach the service for
two polls. It keeps retrying, dims the values and switches every relative time
Expand Down
13 changes: 9 additions & 4 deletions esphome/components/ct002/controls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,10 +208,15 @@ bool is_allowed_host(const std::string &host, const std::vector<std::string> &al
if (normalise_host(entry) == name) return true;
}
if (is_ipv4_literal(name) || is_ipv6_literal(name)) return true;
// `localhost` resolves to the loopback address and nowhere else, and
// `.local` is mDNS (RFC 6762) — resolved by multicast on the link, not
// through a nameserver an outsider can answer for.
return name == "localhost" || ends_with(name, ".localhost") || ends_with(name, ".local");
// `localhost` resolves to the loopback address and nowhere else, `.local`
// is mDNS (RFC 6762) — resolved by multicast on the link, not through a
// nameserver an outsider can answer for — and `.home.arpa` is reserved for
// home networks (RFC 8375), which the DNS root will not delegate, so there
// is no outside nameserver to ask about a name under it either. A merely
// common router suffix (`.box`, `.lan`) is not reserved and stays an
// `allowed_hosts` decision. Mirrors ALWAYS_ALLOWED_HOST* in web_server.py.
return name == "localhost" || ends_with(name, ".localhost") || ends_with(name, ".local") ||
ends_with(name, ".home.arpa");
}

bool is_consumer_field(const std::string &field) {
Expand Down
Loading