Read the statement by Michael Teeuw here.
Problems with WLAN connectivity - solved
-
Dear mirror fans,
for your information and reference some findings with my mirror.
I’m running a MagicMirror on a PI5 with an NVME HAT as boot device.
My first approach was to de-assemble an original Pi power supply (because of its form factor) and to build this internally into the mirror-frame.
As reported earlier in a different thread this power supply died due to overheating.My next approach was to use a new PI-power supply - this time externally.
Caused by the circumstances of my installation (power plug far below mirror position and Pi mounted on the top of the mirror) I have used a USB-C to USB-C cable (150cm, 5A) to extend the standard-cable.As it turns out now this wasn’t a good idea, ether:
It worked pretty long (several weeks) good and without any problem.
But since some days I got more and more really stubborn WLAN losses which were often unrecoverable - only plugging out power supply to reforce a restart helped (I’m working headless as majority of you).In the meantime I was able to implement a tiny service which automatically detects the connectivity loss and restarts the WLAN, so a sufficient symptomatic treatment is in place - this discovers connectivity every five minutes, which is OK to me.
While I was just tinkering I’ve thought it could be a nice idea to identify the root cause and so I added some logging features in the mentioned service.
Now the interesting (unexpected) finding: Obvious root cause was an undervoltage!
I’ve searched around (because initially I failed to remember my “cable-extension”) but couldn’t find any reason for this (nothing attached else than the NVME and my mirror doesn’t have anything heavily using the harddisk)…
Then the additional cable came in my mind and - voilà - this was the root cause - despite its thickness and 5A specification.
For now I have added some 230V cabeling to the top of the mirror, installed there (outside the mirror frame) a third (de-assembled) PI power supply and connected the standard-long cable of this power supply to the Pi.
Since then no undervoltage detected (prior to this every few minutes).So my learning: Pi is bitchy with cable extensions and tiny undervoltages can lead to heavy WLAN problems.
May one or the other can benefit from these findings.
Warm regards,
Ralf -
@rkorell awesome post, great info!
-
@sdetweil :-)
Thanks.In addition: If somebody is interested in the scripts and system-services definitions for own purposes - give me a ping and I will share this for sure…
Regards,
Ralf -
@rkorell Thanks for your Insights! Interesting!
One question: How you got the idea that the issue is caused by power/energy circumstances?
Are there any specific logs with those information?And yes - it would be great to get an idea of your scripts :)
-
Dear @schlomm ,
I initially had no clue at all regarding root cause :-)
And the finding “undervoltage” was never expected but came out off my logfiles.After a LOT of tinkering and playing with syptomatic “solutions” system kept to be unstable so I decided to dig in and do some logging to identify root cause.
For this I wrote a shellscript and installed a system service which collects this data every five minutes.
shellscript:
sudo nano /usr/local/bin/wlan-diagnose.sh
content:
#!/bin/bash LOGFILE="/var/log/wlan-diagnose.log" DATE=$(date '+%a %d %b %H:%M:%S %Z %Y') WLAN_IF="wlan0" echo "===== $DATE =====" >> $LOGFILE # IP-Adresse echo "--- IP-Adresse ---" >> $LOGFILE ip addr show $WLAN_IF >> $LOGFILE 2>&1 # Link-Status echo "--- Link Status ---" >> $LOGFILE iw dev $WLAN_IF link >> $LOGFILE 2>&1 # Default Route echo "--- Routing ---" >> $LOGFILE ip route >> $LOGFILE 2>&1 # Wpa_supplicant Status echo "--- wpa_supplicant ---" >> $LOGFILE systemctl status wpa_supplicant --no-pager >> $LOGFILE 2>&1 # Letzte wpa_supplicant Logs echo "--- wpa_supplicant journal (letzte 20 Zeilen) ---" >> $LOGFILE journalctl -u wpa_supplicant -n 20 --no-pager >> $LOGFILE 2>&1 # Kernel/Treiber Logs echo "--- dmesg wlan0 ---" >> $LOGFILE dmesg | tail -n 20 >> $LOGFILE 2>&1 # Ping-Test PING_TARGET="8.8.8.8" ping -I $WLAN_IF -c3 -W3 $PING_TARGET >> $LOGFILE 2>&1 echo "" >> $LOGFILE
set as executable:
sudo chmod +x /usr/local/bin/wlan-diagnose.sh
systemd-timer for this diagnosis script:
sudo nano /etc/systemd/system/wlan-diagnose.timer
content:
[Unit] Description=WLAN Diagnose alle 5 Minuten [Timer] OnBootSec=1min OnUnitActiveSec=5min Persistent=true [Install] WantedBy=timers.target
service file:
sudo nano /etc/systemd/system/wlan-diagnose.service
content:
[Unit] Description=WLAN Diagnose Service [Service] Type=oneshot ExecStart=/usr/local/bin/wlan-diagnose.sh
activate the service:
sudo systemctl daemon-reload sudo systemctl enable --now wlan-diagnose.timer
Created logfile: /var/log/wlan-diagnose.log
possible command for filtering for errors:
grep -i "fail\|error\|disconnect" /var/log/wlan-diagnose.log
in my personal case directly after starting the service the undervoltage warnings appeared in the logfile:
Sep 24 19:23:02 MagicMirrorPi5 wpa_supplicant[702]: wlan0: CTRL-EVENT-CONNECTED - Connection to f8:bc:0e:51:50:48 completed [id=0 id_str=] Sep 24 19:23:02 MagicMirrorPi5 wpa_supplicant[702]: bgscan simple: Failed to enable signal strength monitoring --- dmesg wlan0 --- [ 385.672898] hwmon hwmon4: Voltage normalised [ 399.780700] hwmon hwmon4: Undervoltage detected! [ 401.796721] hwmon hwmon4: Voltage normalised [ 403.812728] hwmon hwmon4: Undervoltage detected! [ 405.831888] hwmon hwmon4: Voltage normalised [ 425.988994] hwmon hwmon4: Undervoltage detected! [ 428.008109] hwmon hwmon4: Voltage normalised [ 434.052979] hwmon hwmon4: Undervoltage detected! [ 438.087587] hwmon hwmon4: Voltage normalised [ 442.117090] hwmon hwmon4: Undervoltage detected! [ 444.133104] hwmon hwmon4: Voltage normalised [ 452.198182] hwmon hwmon4: Undervoltage detected! [ 454.213171] hwmon hwmon4: Voltage normalised [ 470.341318] hwmon hwmon4: Undervoltage detected! [ 478.405369] hwmon hwmon4: Voltage normalised [ 488.485467] hwmon hwmon4: Undervoltage detected! [ 490.505469] hwmon hwmon4: Voltage normalised [ 514.693689] hwmon hwmon4: Undervoltage detected! [ 516.709733] hwmon hwmon4: Voltage normalised [ 520.744884] hwmon hwmon4: Undervoltage detected! PING 8.8.8.8 (8.8.8.8) from 172.23.56.157 wlan0: 56(84) bytes of data. 64 bytes from 8.8.8.8: icmp_seq=1 ttl=116 time=13.2 ms 64 bytes from 8.8.8.8: icmp_seq=2 ttl=116 time=33.6 ms 64 bytes from 8.8.8.8: icmp_seq=3 ttl=116 time=27.5 ms --- 8.8.8.8 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2003ms rtt min/avg/max/mdev = 13.220/24.756/33.576/8.529 ms
So I had identified my root cause with first strike.
In the meantime (today) I had severe additional problems (also “identified” by this mentioned log) - but this was a kernel/device driver problem which I cannot solve today.
But this leads to a modified recovery script because the version from yesterday only tried to restart the WPA_Supplicant which was not sufficient for my problem today.[EDIT - Sep, 8th, 2025: deleted old recovery script because usage of ping without qualified path produced an error by the script itself. For this reason the script is not as useful as I thought. Sorry for confusion! ]
Hope this helps you.
Do not hesitate to ask for further information …Warmest regards,
Ralf -
addition:
the recovery script is: /usr/local/bin/wlan-recovery.shset executable:
sudo chmod +x /usr/local/bin/wlan-recovery.sh
Systemd-Service
sudo nano /etc/systemd/system/wlan-recovery.service
content:
[Unit] Description=WLAN Recovery Script After=network.target [Service] Type=oneshot ExecStart=/usr/local/bin/wlan-recovery.sh
timer:
sudo nano /etc/systemd/system/wlan-recovery.timer
content:
[Unit] Description=Run WLAN Recovery every 5 minutes [Timer] OnBootSec=1min OnUnitActiveSec=5min Persistent=true [Install] WantedBy=timers.target
activate this service:
sudo systemctl daemon-reload sudo systemctl enable --now wlan-recovery.timer
logfile: /var/log/wlan-recovery.log
-
@rkorell Thanks for all these detailed Information! I’ll setup your scripts on my MagicMirror Instances - I have 6 different ones to manage and at least one has some weird problems - maybe also relating to power issues.
Thanks und Vielen Dank :)
-
@schlomm Sehr gern und VIEL ERFOLG!
- melde Dich, wenn Du noch was benötigst.
Ralf
- melde Dich, wenn Du noch was benötigst.
-
Dear @schlomm , team,
as I learned today sometimes system limitations are hard and leads to unwanted results.
I even got more serioous trouble with my pi and his WIFI so I had to dig in deeper.
The aproach until now - because of “growing” up - is a “recovery” and a “diagnose” part.
This leads to - surprise, surprise :-) - inconsistent data and so dignosis is merely impossible.
For this reason I converged both approches into one script and implemented a 4-stages error-handling and consecutive escalation (until reboot).At this stage i had to recognize: almost EVERY test results immediatly in an error at stage 1 (ping) and was resolved at stage 2 (L2/L3 - ICMP problem – checking status of wlan interface).
To identify root cause for this I - again - dig down deeply (ChatGPT was NOT that helpful!) and found: At systemd level (on my system!?) ping is not in PATH !!!
So a fully qualified call solved this problem - and most of my “problems” are solved !If you are using “ping”, too and stuck in problems in scripts - keep this in mind: “usr/bin/ping” might be really helpful for you.
If you are interested in, here my current recovery-script - including some useful logging information:
/usr/local/bin/wlan-recovery.sh #!/bin/bash # ============================================================================ # WLAN Recovery Script (Monolithische Version) # Autor: Dr. Ralf Korell, MD # Datum: 2025-10-07 # # Dieses Script wird per systemd-Timer regelmäßig aufgerufen. # Es prüft die WLAN-Verbindung in mehreren Stufen und führt nur dann # Recovery-Aktionen aus, wenn wirklich eine Unterbrechung vorliegt. # # Features: # - Mehrstufige Diagnose (Ping, iw, IP, Route) # - Schutz vor Fehlalarmen und Selbstabschüssen # - SSH/VNC-Safe-Mode (keine Unterbrechung aktiver Sessions) # - Logrotation + Statistikdatei # ============================================================================ # === Konfiguration ========================================================== LOGFILE="/var/log/wlan-recovery.log" STATSFILE="/var/log/wlan-recovery.stats" MAX_LOG_SIZE=50000 # ~50 KB, dann Logrotation PING_TARGET="172.23.56.1" MAX_CONSECUTIVE_FAILS=2 # bevor Recovery startet COOLDOWN_FILE="/tmp/wlan-recovery.cooldown" COOLDOWN_MINUTES=5 # interne Speicherorte (nicht verändern) STATEFILE="/tmp/wlan-recovery.state" DATE_NOW=$(date "+%Y-%m-%d %H:%M:%S") # === Hilfsfunktionen ======================================================== log() { echo "$DATE_NOW: $1" | tee -a "$LOGFILE" } rotate_log() { if [ -f "$LOGFILE" ] && [ $(wc -c <"$LOGFILE") -gt $MAX_LOG_SIZE ]; then mv "$LOGFILE" "$LOGFILE.old" echo "$DATE_NOW: Log rotated." > "$LOGFILE" fi } increment_stat() { local key="$1" local value value=$(grep "^$key=" "$STATSFILE" 2>/dev/null | cut -d= -f2) value=$((value + 1)) grep -v "^$key=" "$STATSFILE" 2>/dev/null > "${STATSFILE}.tmp" echo "$key=$value" >> "${STATSFILE}.tmp" mv "${STATSFILE}.tmp" "$STATSFILE" } cooldown_active() { if [ -f "$COOLDOWN_FILE" ]; then local last=$(date -r "$COOLDOWN_FILE" +%s) local now=$(date +%s) local diff=$(( (now - last) / 60 )) [ $diff -lt $COOLDOWN_MINUTES ] else return 1 fi } start_cooldown() { touch "$COOLDOWN_FILE" } ssh_or_vnc_active() { ss -tn state established | grep -Eq '(:22|:5900)' } # === Diagnosefunktionen ===================================================== is_connected_l2() { iw dev wlan0 link 2>/dev/null | grep -q "Connected to" } has_ip_l3() { ip -4 addr show wlan0 2>/dev/null | grep -q "inet " } has_route() { ip route get "$PING_TARGET" 2>/dev/null | grep -q "dev wlan0" } ping_ok() { /usr/bin/ping -I wlan0 -c 3 -W 2 "$PING_TARGET" >/dev/null 2>&1 } # === Hauptlogik ============================================================= rotate_log # Init Statsfile falls nicht vorhanden [ -f "$STATSFILE" ] || echo -e "success=0\nrecoveries=0\nfailures=0" > "$STATSFILE" # Lese bisherigen Fehlerzähler fails=0 [ -f "$STATEFILE" ] && fails=$(cat "$STATEFILE") # Diagnose if ping_ok; then log "Ping erfolgreich. WLAN funktioniert." echo 0 > "$STATEFILE" increment_stat "success" exit 0 fi # Wenn Ping fehlschlägt → weitere Prüfungen log "Ping fehlgeschlagen → erweiterte Diagnose..." if is_connected_l2 && has_ip_l3 && has_route; then log "L2/L3 ok → ICMP-Problem (kein Recovery)." increment_stat "failures" echo 0 > "$STATEFILE" exit 0 fi # Hier gilt: echte Verbindung gestört fails=$((fails + 1)) echo "$fails" > "$STATEFILE" if [ $fails -lt $MAX_CONSECUTIVE_FAILS ]; then log "Erster Fehler ($fails/$MAX_CONSECUTIVE_FAILS) → Beobachten..." increment_stat "failures" exit 0 fi # Wenn Cooldown läuft → überspringen if cooldown_active; then log "Cooldown aktiv → Recovery übersprungen." exit 0 fi # === Recovery-Stufen ======================================================== if ssh_or_vnc_active; then log "SSH/VNC aktiv → keine Recovery ausgeführt, nur geloggt." increment_stat "failures" exit 0 fi log "Verbindung tatsächlich gestört → Recovery-Prozess gestartet." increment_stat "recoveries" # Stufe 1: sanfte Reassoziation log "→ Stufe 1: wpa_supplicant Reassoziation..." wpa_cli -i wlan0 reassociate >/dev/null 2>&1 sleep 5 if ping_ok; then log "Reassoziation erfolgreich." echo 0 > "$STATEFILE" start_cooldown exit 0 fi # Stufe 2: Interface Toggle log "→ Stufe 2: Interface Toggle..." ip link set wlan0 down sleep 2 ip link set wlan0 up sleep 8 if ping_ok; then log "Interface Toggle erfolgreich." echo 0 > "$STATEFILE" start_cooldown exit 0 fi # Stufe 3: Treiber-Reload log "→ Stufe 3: Treiber-Reload..." modprobe -r brcmfmac && modprobe brcmfmac sleep 10 if ping_ok; then log "Treiber-Reload erfolgreich." echo 0 > "$STATEFILE" start_cooldown exit 0 fi # Wenn alles fehlschlägt log "Alle Recovery-Stufen fehlgeschlagen → Fehler bleibt bestehen." increment_stat "failures" start_cooldown exit 1
[EDIT: in script above: changed ping count from -c 1 to -c 3 in:
/usr/bin/ping -I wlan0 -c 1 -W 2 “$PING_TARGET” >/dev/null 2>&1
]
Warmest regards,
Ralf -
In addition: It’s possible that the old recovery script was part of my problems - due to the above mentioned ping problem.
For this reason I’ve edited my earlier post and deleted the content of the script.
I’ve added an “edit note” instead.
Sorry for confusion and any inconvenience!Regards,
Ralf