All four cameras went fps=0 and the TV camwall froze after a 2.4 GHz channel change during WiFi tuning — root-caused NOT to the cameras but to telep-router leaving the cams-VLAN bridge br-cams stuck state DOWN, qdisc noop with no inet after a wifi reload. The cameras stayed WiFi-associated but were L3-unreachable (gateway/DHCP 192.168.30.1 gone). Fixed with a forced br-cams down/up cycle on the router, then a camwall restart on telep-mainframe.

Root cause — a wireless-only OpenWrt bridge can drop and NOT auto-recover on wifi reload

br-camsonly bridge member is the cams AP phy1-ap1 (SSID telep-cc, network=cams, isolate=1, hidden=1). A runtime wifi reload (here triggered by uci set wireless.radio1.channel=11; uci commit; wifi reload) bounced that AP, and OpenWrt left br-cams in state DOWN, qdisc noop — the static L3 config (network.cams, proto static, 192.168.30.1/24 on device br-cams) was NOT reapplied. This is a known OpenWrt quirk with wireless-only bridges: the bridge loses carrier when its sole wireless member bounces and does not come back on its own.

For Agents

Symptom looks identical to two OTHER failures but the fix is different — branch on ip addr show br-cams:

Camera map: DÉL/South .119 = 18:69:45:a9:01:25 = telep_cam1+telep_cam2; ÉSZAK/North .139 = c0:3a:55:5c:8b:33 = telep_cam3+telep_cam4. Both Tapo cams on the isolated cams VLAN 192.168.30.0/24, gateway/DHCP = br-cams 192.168.30.1 on telep-router.

Trigger

During WiFi tuning the 2.4 GHz channel (radio1) was moved 1 → 11:

uci set wireless.radio1.channel=11
uci commit
wifi reload

wifi reload bounced every AP on radio1 — including the cams AP phy1-ap1 (telep-cc). That AP is the only member of br-cams, so when it dropped, the bridge went carrier-down and OpenWrt did not reapply the static network.cams L3 config.

Symptom chain

  1. cams gateway/DHCP 192.168.30.1 gone (br-cams had no inet).
  2. Both Tapo cameras stayed WiFi-ASSOCIATED — good signal, present in iwinfo assoclist — but were L3-UNREACHABLE: no ping even from the router, no ARP/neigh entry, and .119 had no DHCP lease.
  3. go2rtc producers = None for all streams; Frigate camera_fps=0 on all 4 cameras.
  4. The frigate-fps-watchdog auto-restarted Frigate (Frigate uptime ~18 min at diagnosis) — but that did NOT help, because the break was network-side, not in Frigate.
  5. The camwall (4× mpv 2×2 grid on HDMI) froze on its last frames.

Misleading detail — do NOT chase the cameras

The ONVIF reboot (~/tapo-ctl/reboot-cams-onvif.py) errored with ConnectTimeout to port 2020 on BOTH cams. This looked like dead cameras, but it was only because they were L3-unreachable — the reboot RPC couldn’t reach them. The cameras were fine. Check ip addr show br-cams on the router FIRST before touching the cameras.

Diagnosis sequence that worked

Run top-down; each step narrows from app → network → the bridge:

# On the mainframe (ssh levander@100.115.209.87):
sudo docker exec frigate curl 127.0.0.1:1984/api/streams   # producers = None for all
sudo docker exec frigate curl 127.0.0.1:5000/api/stats     # camera_fps = 0 on all 4
 
# On the router (ssh root@100.69.112.32):
ping -c1 192.168.30.119; ping -c1 192.168.30.139           # both DOWN, even from the router
grep 192.168.30 /tmp/dhcp.leases                           # .119 lease MISSING
ip neigh | grep 192.168.30                                 # empty — no ARP entries
ip addr show br-cams                                       # state DOWN qdisc noop, NO inet  ← ROOT CAUSE

The last line is the tell: br-cams in state DOWN, qdisc noop with no inet 192.168.30.1/24 = the bridge lost its L3 config after the wifi reload.

Fix that worked

ifup cams alone does NOT fix a carrier-down wireless-only bridge

Neither ifup cams by itself nor /etc/init.d/network reload; wifi up brought br-cams back. The bridge needs a forced link-layer down/up cycle before the L3 config will reapply.

On telep-router (ssh root@100.69.112.32):

ifdown cams
sleep 2
ip link set dev br-cams up
ifup cams
sleep 5
ip addr show br-cams        # now: state UP, inet 192.168.30.1/24

Result: br-cams came UP with inet 192.168.30.1/24, phy1-ap1 master br-cams state UP, and both cameras pingable again.

Then on telep-mainframe (ssh levander@100.115.209.87):

sudo systemctl restart camwall

Frigate camera_fps returned to ~5.0 on all 4 cameras, the mpv tiles re-pulled their streams, and the wall was live again. (mpv holds the last frozen frame after a stream drop and won’t auto-reconnect — the camwall restart is what re-rolls the panes.)

How this differs from the 2026-08-03 wedged-RTSP incident

Both present as fps=0 / a frozen camwall, so the runbook must branch on ip addr show br-cams state:

2026-08-03 — wedged RTSPThis (2026-08-15) — bridge down
LayerCamera-side (RTSP session slots stuck)Router-side (br-cams carrier/L3 down)
Cameras pingable?Yes (L3 fine, RTSP wedged)No (L3 unreachable)
ip addr show br-camsUP, has inetDOWN, qdisc noop, no inet
FixONVIF reboot + systemctl restart camwallifdown/ip link up/ifup cams + systemctl restart camwall

Durable guards (NOT yet applied — user to decide)

Options to stop wifi reload from taking the cams VLAN down again

  1. Hotplug hook (recommended, set-and-forget) — an OpenWrt hotplug handler that auto-runs ifup cams (or the down/up cycle) after wifi events, so the bridge self-recovers.
  2. Persistent dummy member on br-cams — add a permanent (e.g. dummy) interface to the bridge so it’s never a wireless-only bridge and never goes carrier-down when the AP bounces.
  3. Operational rule — never wifi reload radio1 without immediately following with the br-cams down/up cycle (below). The camwall runbook now documents this branch.

Separate bug fixed — OliveTin ONVIF reboot used system python3 (no onvif module)

tapo-ctl scripts MUST run via the venv python, not system python3

The OliveTin action “Kamerák újraindítása (ONVIF)” (and the raw reboot-cams-onvif.py invocation) called system python3, which lacks the onvif module — that module lives only in ~/tapo-ctl/venv. So the action failed with a ModuleNotFoundError independent of the network outage above.

Fix — the OliveTin action in /home/levander/admin-portal/olivetin/config/config.yaml now calls the venv python explicitly:

~/tapo-ctl/venv/bin/python ~/tapo-ctl/reboot-cams-onvif.py

General rule: every ~/tapo-ctl/ script must run via ~/tapo-ctl/venv/bin/python, never system python3.