Skip to content

Commit 46b10d6

Browse files
committed
v0.4.24: ZimaOS support — writable path probing + Docker bridge IP fix
1 parent bed6055 commit 46b10d6

3 files changed

Lines changed: 34 additions & 11 deletions

File tree

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,15 @@
22

33
All notable changes to SMART Sniffer are documented here.
44

5+
## v0.4.24 — 2026-03-20
6+
7+
### Fixed
8+
- Zeroconf discovery now correctly selects real LAN IPs (10.x, 192.168.x) over Docker bridge IPs (172.17.x) on container-based systems like ZimaOS/CasaOS
9+
10+
### Added
11+
- Installer now probes for writable paths on immutable-rootfs platforms (ZimaOS, CasaOS); falls back to `/DATA/smartha-agent/` or `/opt/smartha-agent/`
12+
- New doc: `docs/platform-install-paths.md` — explains platform-specific install locations and how to add new ones
13+
514
## v0.4.23 — 2026-03-19
615

716
### Fixed

custom_components/smart_sniffer/config_flow.py

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,13 @@ async def async_step_user(
9090
def _pick_best_ip(discovery_info: ZeroconfServiceInfo) -> str:
9191
"""Choose the best IP from discovery info.
9292
93-
Prefers RFC 1918 private addresses (192.168.x, 10.x, 172.16-31.x)
94-
over VPN/tunnel IPs (Tailscale 100.x, WireGuard, etc.). Falls back
95-
to whatever is available.
93+
Prioritizes real LAN addresses over virtual/tunnel IPs:
94+
1. 192.168.x.x, 10.x.x.x (almost always physical LAN)
95+
2. 172.16-31.x.x (RFC 1918, but often Docker/container bridges)
96+
3. 100.64-127.x.x (CGNAT — Tailscale, WireGuard, etc.)
97+
4. Anything else
98+
99+
Falls back to whatever is available.
96100
"""
97101
# discovery_info may expose ip_address (single) and ip_addresses (list).
98102
candidates: list[str] = []
@@ -104,16 +108,26 @@ def _pick_best_ip(discovery_info: ZeroconfServiceInfo) -> str:
104108
if not candidates:
105109
return str(discovery_info.ip_address)
106110

107-
# Prefer private (RFC 1918) addresses over anything else.
108-
for ip_str in candidates:
111+
def _score(ip_str: str) -> int:
112+
"""Lower score = more preferred."""
109113
try:
110114
addr = ipaddress.ip_address(ip_str)
111-
if addr.is_private and not ip_str.startswith("100."):
112-
return ip_str
113115
except ValueError:
114-
continue
115-
116-
# No private IP found — return the first candidate.
116+
return 99
117+
if not addr.is_private:
118+
return 90
119+
# 192.168.x.x and 10.x.x.x — almost always a real LAN interface.
120+
if ip_str.startswith("192.168.") or ip_str.startswith("10."):
121+
return 10
122+
# 172.16-31.x.x — RFC 1918 but frequently Docker/container bridges.
123+
if ip_str.startswith("172."):
124+
return 50
125+
# 100.64-127.x.x — CGNAT range (Tailscale, WireGuard, etc.)
126+
if ip_str.startswith("100."):
127+
return 70
128+
return 80
129+
130+
candidates.sort(key=_score)
117131
return candidates[0]
118132

119133
async def async_step_zeroconf(

custom_components/smart_sniffer/manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@
99
"iot_class": "local_polling",
1010
"issue_tracker": "https://github.com/DAB-LABS/smart-sniffer/issues",
1111
"requirements": [],
12-
"version": "0.4.23",
12+
"version": "0.4.24",
1313
"zeroconf": [{"type": "_smartha._tcp.local."}]
1414
}

0 commit comments

Comments
 (0)