feat 🔌 TP17: statische Shelly-IP + in-pool-Reservierung + voller HA-MAC-Scan
- Entscheidung: alle Shellys bekommen statische IP (10.40.30.<octet>, gw/dns .30.1) + in-pool DHCP-Reservierung als Backup. set_sta auf static=true (Default) umgestellt (Ziel-IP aus Oktett), _sta_cfg-Helper. - pool-v30 auf .100-.250 erweitert (Reservierungen jetzt in-pool, User-Konvention). - s24 (14:33:5c:d8:2d:7c) ins inventory/bf.csv + .30.204-Reservierung. - Voller HA-Device-Scan (alle MAC-Geräte, nicht nur configuration_url): fand Apple TV 4K + Philips TV (aus, VLAN40) — vor cudy-Teardown VLAN verifizieren; Apple TV = vmtl. Thread-Border-Router (TP17.1). Tasmota bestätigt tot (MAC nicht im Netz). - .41.246/.247 = cudy1/cudy2 (Teardown-Ziele) dokumentiert. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -121,37 +121,58 @@ def get_device(ip: str) -> dict:
|
||||
return out
|
||||
|
||||
|
||||
V30_NET = "10.40.30"
|
||||
V30_MASK = "255.255.255.0"
|
||||
V30_GW = "10.40.30.1"
|
||||
|
||||
|
||||
def _sta_cfg(ssid: str, static: bool, target_ip: str) -> dict:
|
||||
"""Build the WiFi STA config. Project decision (2026-07-11): all Shellys get a
|
||||
STATIC IP on-device (keeping the last octet) plus a matching in-pool DHCP
|
||||
reservation as backup — not DHCP-only."""
|
||||
sta = {"ssid": ssid, "pass": IOT_PSK, "enable": True}
|
||||
if static:
|
||||
sta.update({"ipv4mode": "static", "ip": target_ip, "netmask": V30_MASK,
|
||||
"gw": V30_GW, "nameserver": V30_GW})
|
||||
else:
|
||||
sta["ipv4mode"] = "dhcp"
|
||||
return sta
|
||||
|
||||
|
||||
@mcp.tool()
|
||||
def set_sta(ip: str, confirm: bool = False, ssid: str | None = None) -> dict:
|
||||
def set_sta(ip: str, confirm: bool = False, ssid: str | None = None,
|
||||
static: bool = True) -> dict:
|
||||
"""MIGRATION ACTION — point a Shelly's Wi-Fi STA at the IOT SSID, then reboot.
|
||||
|
||||
Reconfigures a LIVE device: it drops off VLAN1 and rejoins on VLAN30 via DHCP.
|
||||
Reconfigures a LIVE device: it drops off VLAN1 and rejoins on VLAN30. Per the
|
||||
project decision it sets a STATIC IP (10.40.30.<same-last-octet>, gw/dns .30.1);
|
||||
a matching in-pool DHCP reservation exists as backup. Pass static=False to use DHCP.
|
||||
A wrong PSK leaves it in AP-mode (physical reset needed). Therefore:
|
||||
- confirm MUST be true to actually write,
|
||||
- SHELLY_IOT_PSK must be set in the environment.
|
||||
With confirm=false this is a dry-run (returns the exact config that would be sent).
|
||||
"""
|
||||
target_ssid = ssid or IOT_SSID
|
||||
target_ip = f"{V30_NET}.{ip.rsplit('.', 1)[-1]}"
|
||||
ident = discover.probe(ip)
|
||||
plan = {"ip": ip, "target_ssid": target_ssid,
|
||||
plan = {"ip": ip, "target_ssid": target_ssid, "target_ip": target_ip,
|
||||
"mode": "static" if static else "dhcp",
|
||||
"device": ident, "psk_configured": bool(IOT_PSK)}
|
||||
if not ident:
|
||||
return {**plan, "ok": False, "error": "device not reachable"}
|
||||
if not IOT_PSK:
|
||||
return {**plan, "ok": False, "error": "SHELLY_IOT_PSK not set in environment"}
|
||||
sta = _sta_cfg(target_ssid, static, target_ip)
|
||||
if not confirm:
|
||||
redacted = {**sta, "pass": "***"}
|
||||
return {**plan, "ok": False, "dry_run": True,
|
||||
"would_send": {"method": "WiFi.SetConfig",
|
||||
"params": {"config": {"sta": {"ssid": target_ssid,
|
||||
"pass": "***", "enable": True,
|
||||
"ipv4mode": "dhcp"}}}}}
|
||||
"params": {"config": {"sta": redacted}}}}
|
||||
try:
|
||||
cfg = {"config": {"sta": {"ssid": target_ssid, "pass": IOT_PSK,
|
||||
"enable": True, "ipv4mode": "dhcp"}}}
|
||||
res = _rpc(ip, "WiFi.SetConfig", cfg)
|
||||
res = _rpc(ip, "WiFi.SetConfig", {"config": {"sta": sta}})
|
||||
reboot = _rpc(ip, "Shelly.Reboot")
|
||||
return {**plan, "ok": True, "set_result": res, "reboot": reboot,
|
||||
"note": "device rebooting; expect it on VLAN30 (10.40.30.x) shortly"}
|
||||
"note": f"device rebooting; expect it at {target_ip} shortly"}
|
||||
except Exception as e:
|
||||
return {**plan, "ok": False, "error": f"{type(e).__name__}: {e}"}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user