feat(devices): WiZ Connected LAN target type

Adds support for WiZ Connected (Philips' budget-tier) smart bulbs that
accept JSON commands as UDP datagrams on port 38899 with broadcast LAN
discovery on 255.255.255.255:38899.

Backend:
- WiZClient is a single-pixel UDP adapter: averages the incoming strip
  to one RGB triple and pushes it via setPilot with r/g/b params.
  Brightness folds into the RGB scaling so we burn one packet per frame
  instead of two.
- UDP fire-and-forget tolerates high update rates with no ack overhead,
  so the default rate gate is 50 ms (~20 Hz) -- 10x faster than Yeelight.
- supports_fast_send=True with a synchronous send_pixels_fast hot path.
- Broadcast discovery sends the standard registration envelope; bulb
  replies are parsed for IP+MAC and surfaced as DiscoveredDevice
  entries. Broadcast failures (no network, firewall) yield [] rather
  than raising.
- Health check sends getPilot and waits 1.5s for any reply on a
  one-shot UDP socket.
- WiZConfig joins the typed config union; Device storage gains a
  wiz_min_interval_ms field; full to_dict/from_dict/to_config wiring.
- 36 unit tests cover URL parsing, MAC extraction, strip averaging,
  rate limiting, fast-send hot path, provider validate/discover/health,
  and Device.to_config round-trip.

Frontend:
- 'wiz' in DEVICE_TYPE_KEYS (next to 'yeelight'), lightbulb icon
  (deliberate smart-bulb family grouping with Hue + Yeelight).
- isWizDevice predicate + per-type field show/hide in create and
  settings modals.
- Rate-limit number input (default 50 ms) in both modals with hint
  text noting the UDP fire-and-forget characteristic.
- Locale strings in en/ru/zh.

WiZ bulbs are reachable from the existing "Scan network" button -- no
new discovery UI affordance was needed.
This commit is contained in:
2026-05-16 02:12:01 +03:00
parent 4b65005823
commit ede627b4ac
19 changed files with 962 additions and 8 deletions
+10 -3
View File
@@ -695,9 +695,16 @@ Xiaomi/Yeelight bulbs, port 55443 TCP JSON. Direct protocol (no
Philips' UDP-local budget tier. Port 38899 JSON UDP.
- [ ] Reuse the discovery scaffolding from Yeelight (UDP broadcast pattern)
- [ ] `WiZConfig` + `WiZLEDClient` + `WiZDeviceProvider`
- [ ] Frontend additions + locales
- [x] `WiZConfig` + `WiZClient` + `WiZDeviceProvider`
- [x] UDP broadcast discovery on 255.255.255.255:38899 with the standard
`registration` envelope; replies parsed for IP+MAC.
- [x] Sync `send_pixels_fast` for the hot loop (UDP is fire-and-forget,
no async needed). 50 ms default min interval → ~20 Hz cap.
- [x] Health check sends `getPilot` and waits for any reply.
- [x] Storage + API schemas + route handler wiring
- [x] 36 unit tests
- [ ] Frontend: WiZ in device-type picker + edit form
- [ ] Locale strings (en/ru/zh)
### Phase 2 — Unified discovery + pairing UX layer