2026-08-13 14:10:39 +08:00
|
|
|
# hass.windy.lan — Home Assistant (HAOS)
|
|
|
|
|
|
|
|
|
|
## Role and access
|
|
|
|
|
|
|
|
|
|
| Item | Value |
|
|
|
|
|
|---|---|
|
|
|
|
|
| Role | Home Assistant automation hub |
|
|
|
|
|
| IPv4 | `192.168.55.11` (LAN55) |
|
|
|
|
|
| DNS | `hass.windy.lan` (AdGuard rewrite on `dns.windy.lan`; legacy `hass.local` alias) |
|
|
|
|
|
| SSH | `ssh hassio@hass.windy.lan` |
|
|
|
|
|
| **Host** | **PVE VM 180 (`haos`)** — not a separate physical host (verified 2026-08-09) |
|
|
|
|
|
| Platform | Home Assistant OS; kernel `6.1.115-haos` (aarch64) |
|
|
|
|
|
| Web UI | `http://hass.windy.lan:8123` (LAN); WAN port-forward `hass` on gw → `:8123` |
|
|
|
|
|
|
|
|
|
|
Use `hassio` for routine SSH inspection. Key-only login was verified on
|
2026-08-13 17:54:33 +08:00
|
|
|
2026-08-13 from the WSL client (`BatchMode=yes`).
|
|
|
|
|
|
|
|
|
|
The `ha` supervisor CLI (`/usr/bin/ha`) authenticates with `SUPERVISOR_TOKEN`.
|
|
|
|
|
Interactive login works because `~hassio/.zprofile` runs `exec sudo -i`, which
|
|
|
|
|
loads a root environment carrying the supervisor API token. Non-interactive
|
|
|
|
|
`ssh hassio 'command'` does not source `.zprofile` and fails with
|
|
|
|
|
`unauthorized: missing or invalid API token`. Run `ha` non-interactively via:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
ssh -o BatchMode=yes hassio@hass.windy.lan 'sudo -n -i ha core info'
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Verified 2026-08-13 that `sudo -n -i ha core info` works from the WSL client.
|
|
|
|
|
Never copy the supervisor token into this repository.
|
2026-08-13 14:10:39 +08:00
|
|
|
|
|
|
|
|
The current SSH ED25519 host-key fingerprint is
|
|
|
|
|
`SHA256:DMcMOgDzFsFTon1fndXowEP7jlyOK3/AX3PVK8BATvk` (verified 2026-08-13).
|
|
|
|
|
Verify a changed key out of band before accepting it.
|
|
|
|
|
|
|
|
|
|
Do not store Home Assistant long-lived tokens, integration credentials, or
|
|
|
|
|
recovery codes in this repository.
|
|
|
|
|
|
|
|
|
|
## Network
|
|
|
|
|
|
|
|
|
|
| Interface | Address / role |
|
|
|
|
|
|---|---|
|
|
|
|
|
| `end1` | `192.168.55.11/24`; primary LAN55 address |
|
|
|
|
|
| `wg0` | `10.13.13.2/32`; WireGuard (add-on / integration tunnel) |
|
|
|
|
|
| `hassio` / `docker0` | internal HAOS Docker bridges (`172.30.32.0/23`, `172.30.232.0/23`) |
|
|
|
|
|
|
|
|
|
|
LAN55 clients reach the HTTP API on `dns.windy.lan:80` for the AdGuard Home
|
|
|
|
|
integration; see [hosts/dns.windy.lan.md](dns.windy.lan.md).
|
|
|
|
|
|
2026-08-13 17:20:49 +08:00
|
|
|
## API access
|
|
|
|
|
|
|
|
|
|
Home Assistant exposes a REST API at `http://hass.windy.lan:8123/api/` (same
|
|
|
|
|
as `http://192.168.55.11:8123/api/`). Authenticate with a **long-lived access
|
|
|
|
|
token** created under **Profile → Security → Long-lived access tokens**.
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
HA_URL="http://hass.windy.lan:8123"
|
|
|
|
|
HA_TOKEN="<long-lived-access-token>"
|
|
|
|
|
|
|
|
|
|
# Health check — expect {"message":"API running."} and HTTP:200
|
|
|
|
|
curl -sS -w "\nHTTP:%{http_code}\n" \
|
|
|
|
|
-H "Authorization: Bearer $HA_TOKEN" "$HA_URL/api/"
|
|
|
|
|
|
|
|
|
|
# Read one entity state
|
|
|
|
|
curl -sS -H "Authorization: Bearer $HA_TOKEN" \
|
|
|
|
|
"$HA_URL/api/states/sensor.csg_30d_max"
|
|
|
|
|
|
|
|
|
|
# List entities / recent errors
|
|
|
|
|
curl -sS -H "Authorization: Bearer $HA_TOKEN" "$HA_URL/api/states"
|
|
|
|
|
curl -sS -H "Authorization: Bearer $HA_TOKEN" "$HA_URL/api/error_log"
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
- `401` → token invalid or expired; create a new one.
|
|
|
|
|
- `404` on `/api/states/<id>` → entity does not exist.
|
|
|
|
|
- The token is a secret: never commit it here; keep it in the shell
|
|
|
|
|
environment or a secrets file outside the repo.
|
|
|
|
|
|
|
|
|
|
### HTTP proxy gotcha (verified 2026-08-13)
|
|
|
|
|
|
|
|
|
|
The WSL client had `http_proxy` set to Mihomo (`192.168.66.99:7890`). LAN
|
|
|
|
|
hostnames sent **through that proxy** returned empty `502`, even though DNS
|
|
|
|
|
resolved and the HA UI was up. Direct `192.168.55.11:8123` worked, and
|
|
|
|
|
`hass.windy.lan:8123` worked only after clearing the HTTP proxy.
|
|
|
|
|
|
|
|
|
|
Before debugging a "502" on a LAN URL, check `env | grep -i proxy` and bypass
|
|
|
|
|
the proxy:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
unset http_proxy HTTP_PROXY all_proxy ALL_PROXY
|
|
|
|
|
curl -sS -w "\nHTTP:%{http_code}\n" \
|
|
|
|
|
-H "Authorization: Bearer $HA_TOKEN" "$HA_URL/api/"
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
For a persistent fix, add `.windy.lan` (leading dot) and the LAN ranges to
|
|
|
|
|
`NO_PROXY`, or add `*.windy.lan` to the proxy's own bypass/skip-proxy list.
|
|
|
|
|
See `~/.config/zsh/env/local/environment.env` for the client-side setting.
|
|
|
|
|
|
2026-08-13 14:10:39 +08:00
|
|
|
## Safe verification
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
ssh -o BatchMode=yes hassio@hass.windy.lan 'hostname; ip -4 addr show end1'
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
From a LAN client, confirm DNS and UI reachability:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
getent hosts hass.windy.lan
|
|
|
|
|
# expect 192.168.55.11
|
|
|
|
|
```
|
|
|
|
|
|
2026-08-13 19:48:18 +08:00
|
|
|
## Local patches (custom components)
|
|
|
|
|
|
|
|
|
|
**`tianqi` weather recorder patch (verified 2026-08-13, W1N-75):**
|
|
|
|
|
`/config/custom_components/tianqi/weather.py` has a local patch adding
|
|
|
|
|
`_unrecorded_attributes = frozenset({"hourly_temperature", "hourly_skycon",
|
|
|
|
|
"hourly_cloudrate", "hourly_precipitation"})` to the `WeatherEntity` class.
|
|
|
|
|
Without it, weather.guangzhou's state attributes (~19 KB, dominated by the 4
|
|
|
|
|
hourly_* arrays of up to 48 entries) exceed the recorder 16384-byte limit, so
|
|
|
|
|
the recorder drops **all** attributes for the entity and logs
|
|
|
|
|
`Recorder.db_schema: State attributes for weather.guangzhou exceed maximum
|
|
|
|
|
size of 16384 bytes`. The patch excludes only the 4 arrays from recording
|
|
|
|
|
(live state unchanged; other attributes still stored; ~6.3 KB payload). Backup
|
|
|
|
|
at `weather.py.bak-w1n75`. **Re-apply after any `tianqi` component update.**
|
|
|
|
|
The `_unrecorded_attributes` mechanism exists in Core 2026.8.1
|
|
|
|
|
(`Entity.__init_subclass__` → `state_info["unrecorded_attributes"]`, consumed
|
|
|
|
|
by recorder `shared_attrs_bytes_from_event`).
|
|
|
|
|
|
|
|
|
|
## Known issues
|
|
|
|
|
|
|
|
|
|
**Bluetooth hci0 instability — RTL8821CS (verified 2026-08-13, W1N-74):**
|
|
|
|
|
The local Bluetooth controller hci0 is an **RTL8821CS** combo chip on the
|
|
|
|
|
x88 Pro board. Kernel logs show recurring `hci0: hardware error 0x00`,
|
|
|
|
|
`Opcode 0x200c tx timeout` (HCI_LE_Set_Scan_Parameters), `Unable to disable
|
|
|
|
|
scanning: -110`, `Peer device has reset` — the chip hardware-stalls during
|
|
|
|
|
active scanning. HA's `bluetooth_auto_recovery` power-cycle then times out
|
|
|
|
|
after 5 s and retries every ~2 min:
|
|
|
|
|
`bluetooth_auto_recovery.recover: Could not reset the power state of the
|
|
|
|
|
Bluetooth adapter hci0 ... due to timeout after 5 seconds`. The HAOS image
|
|
|
|
|
already ships custom systemd units to cope (`x88-bt-hci-recovery.service` and
|
|
|
|
|
a "Patch HA Bluetooth scanner mode for x88 RTL8821CS" service, visible in host
|
|
|
|
|
journal). **No user impact:** there are **no BLE entities** in HA
|
|
|
|
|
(xiaomi_ble / bthome / led_ble / bluetooth / esphome domains are all empty;
|
|
|
|
|
platforms merely load from stray advertisements). Real IoT devices are Zigbee
|
|
|
|
|
(via Zigbee2MQTT) or WiFi/MQTT/cloud. An ESPHome Bluetooth-proxy ESP32
|
|
|
|
|
(`/config/esphome/bluetooth.yaml`, bluetooth_proxy: active, WiFi `ubnt-haas`)
|
|
|
|
|
is configured but currently offline (ESPHome add-on stopped, port 6053
|
|
|
|
|
unreachable) and produced no entities. Follow-up (optional): disable the
|
|
|
|
|
local adapter and rely on the ESPHome proxy, or stop the bluetooth
|
|
|
|
|
integration entirely.
|
|
|
|
|
|
|
|
|
|
**eMMC disk lifetime 10% (verified 2026-08-13, W1N-76):** `ha host info`
|
|
|
|
|
reports `disk_life_time: 10` — the boot eMMC (`/dev/mmcblk2`, CJTD4R
|
|
|
|
|
`0xacacc064`, 64 GB) has ~10% life left. `disk_free: 40.2/56.4 GB`. Full
|
|
|
|
|
backup `pre-maintenance-20260813` (slug `411a4ba5`, 144.26 MB) taken
|
|
|
|
|
2026-08-13 covers current config; monitor `disk_life_time` on each health
|
|
|
|
|
snapshot and plan a disk replacement / data-disk migration before the eMMC
|
|
|
|
|
fails.
|
|
|
|
|
|
2026-08-13 14:10:39 +08:00
|
|
|
## Related docs
|
|
|
|
|
|
2026-08-13 17:54:33 +08:00
|
|
|
- [runbooks/home-assistant-maintenance.md](../runbooks/home-assistant-maintenance.md) — `ha` CLI maintenance runbook + [script](../runbooks/scripts/ha-maintenance.sh)
|
2026-08-13 14:10:39 +08:00
|
|
|
- [docs/lan-overview.md](../docs/lan-overview.md) — LAN map and gw port-forward
|
|
|
|
|
- [hosts/dns.windy.lan.md](dns.windy.lan.md) — `hass.windy.lan` / `hass.local` rewrites
|