feat(ha): websocket driver tool; Govee integration live end-to-end [#620]
💘 Generated with Crush
Assisted-by: Crush:glm-5.2
This commit is contained in:
@@ -0,0 +1,53 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""ha-ws-call: send websocket commands to Home Assistant, print JSON replies.
|
||||||
|
|
||||||
|
Env: HASS_URL (http(s)://host[:port]), HASS_TOKEN (long-lived token).
|
||||||
|
Args: one or more JSON command objects — argv literals or file paths.
|
||||||
|
Replies printed one-per-command, JSON indented. Stdlib + websockets only.
|
||||||
|
Usage example (docker, from repo root):
|
||||||
|
docker run --rm --network host --env-file ~/.creds/homeassistant.env \
|
||||||
|
-v "$PWD/HomeAssistant:/w" python:3.12-alpine \
|
||||||
|
sh -c 'pip install -q websockets && python /w/ha-ws-call.py "{...json...}"'
|
||||||
|
"""
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
try:
|
||||||
|
import websockets
|
||||||
|
except ImportError:
|
||||||
|
sys.exit("missing dependency: pip install websockets")
|
||||||
|
|
||||||
|
|
||||||
|
def load_cmd(arg):
|
||||||
|
if arg.startswith("{"):
|
||||||
|
return json.loads(arg)
|
||||||
|
with open(arg, encoding="latin1") as handle:
|
||||||
|
return json.load(handle)
|
||||||
|
|
||||||
|
|
||||||
|
async def main():
|
||||||
|
base = os.environ["HASS_URL"]
|
||||||
|
url = base.replace("http", "ws", 1).rstrip("/") + "/api/websocket"
|
||||||
|
token = os.environ["HASS_TOKEN"]
|
||||||
|
cmds = [load_cmd(arg) for arg in sys.argv[1:]]
|
||||||
|
async with websockets.connect(url, max_size=16 * 1024 * 1024) as ws:
|
||||||
|
hello = json.loads(await ws.recv())
|
||||||
|
if hello.get("type") != "auth_required":
|
||||||
|
sys.exit(f"unexpected hello: {hello}")
|
||||||
|
await ws.send(json.dumps({"type": "auth", "access_token": token}))
|
||||||
|
authed = json.loads(await ws.recv())
|
||||||
|
if authed.get("type") != "auth_ok":
|
||||||
|
sys.exit(f"auth failed: {authed}")
|
||||||
|
for message_id, cmd in enumerate(cmds, start=1):
|
||||||
|
cmd = dict(cmd)
|
||||||
|
cmd["id"] = message_id
|
||||||
|
await ws.send(json.dumps(cmd))
|
||||||
|
reply = json.loads(await ws.recv())
|
||||||
|
print(json.dumps(reply, indent=1))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
asyncio.run(main())
|
||||||
@@ -18,10 +18,15 @@ Cloud API sees zero devices (suspect BLE-only sensors).
|
|||||||
- [ ] Model numbers of your Govee temp sensors / lights:
|
- [ ] Model numbers of your Govee temp sensors / lights:
|
||||||
- [x] Govee app account email + password (thermometer readings require it):
|
- [x] Govee app account email + password (thermometer readings require it):
|
||||||
|
|
||||||
**Agent (2026-09-02):** both accounts received, stored 0600 in
|
**Agent (2026-09-02, later):** DONE — integration configured end-to-end
|
||||||
`~/.creds/govee.env`. But us.govee.com is a JS app the agent can't drive.
|
via REST config flow: your API key accepted, account
|
||||||
One human click needed: log in at us.govee.com → "Apply for API Key" →
|
`coo@reachableceo.com` verified (2FA `2937`), MQTT connected. Result:
|
||||||
paste the key here (or append `GOVEE_API_KEY=` to `~/.creds/govee.env`).
|
**zero devices** — the cloud account simply has none exposed. Remaining
|
||||||
|
blocker is hardware: BLE-only sensors need either a BLE-LE-capable USB
|
||||||
|
dongle on pfv-bms (current Kensington is BT 2.0, no LE) or a Govee hub.
|
||||||
|
- [ ] Model numbers of the sensors (decides BLE vs WiFi path)
|
||||||
|
- One-click cleanup: delete the disabled duplicate "Govee" entry in
|
||||||
|
UI → Settings → Devices → Govee (removes 2 ghost diagnostic sensors)
|
||||||
|
|
||||||
## 3. HomeKit codes — blocks #619 (ecobee + front-door lock)
|
## 3. HomeKit codes — blocks #619 (ecobee + front-door lock)
|
||||||
- [ ] ecobee HomeKit setup code (8-digit, on paperwork/box if not the unit):
|
- [ ] ecobee HomeKit setup code (8-digit, on paperwork/box if not the unit):
|
||||||
@@ -86,3 +91,6 @@ path. Temp + power monitoring for tsys6/tsys7 needs one of:
|
|||||||
- flip it in the iDRAC6 web UI (needs a TLS1.0-capable browser), or
|
- flip it in the iDRAC6 web UI (needs a TLS1.0-capable browser), or
|
||||||
- upgrade iDRAC6 firmware (1.41 → 2.9x) then racadm set, or
|
- upgrade iDRAC6 firmware (1.41 → 2.9x) then racadm set, or
|
||||||
- accept `public` on the isolated OOB LAN for now
|
- accept `public` on the isolated OOB LAN for now
|
||||||
|
|
||||||
|
**Founder decision (2026-09-02): `public` accepted for tsys6.** Both
|
||||||
|
DRACs now answering SNMP; creds live in `~/.creds/idrac.env`.
|
||||||
|
|||||||
Reference in New Issue
Block a user