From 5ae4bb3148f0a57fe2d9d70894d2e1d823c467de Mon Sep 17 00:00:00 2001 From: Tobias Leuschner Date: Sat, 9 May 2026 01:28:44 +0200 Subject: [PATCH] =?UTF-8?q?Verbessere=20die=20Mount-=C3=9Cberpr=C3=BCfung?= =?UTF-8?q?=20und=20Fehlerbehandlung=20f=C3=BCr=20USB-Ger=C3=A4te?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.py | 49 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/app.py b/app.py index 2427572..9bc3094 100644 --- a/app.py +++ b/app.py @@ -568,13 +568,43 @@ def r_wifi_status(): _browse_mounts = {} # usb_port -> mount_point + +def _mp_is_alive(mp): + """Prüft ob ein Mount-Punkt wirklich aktiv und lesbar ist.""" + try: + with open('/proc/mounts') as f: + mounted = any(mp in line.split() for line in f) + if not mounted: + return False + os.listdir(mp) # I/O-Test: schlägt fehl wenn Gerät entfernt wurde + return True + except Exception: + return False + + +def _drop_browse_mount(port): + """Veralteten Mount bereinigen.""" + mp = _browse_mounts.pop(port, None) + if mp: + subprocess.run(['umount', '-l', mp], capture_output=True) + log.info(f'Browse-Mount bereinigt: {mp}') + + def get_browse_mp(dev): port = dev.get('usb_port', '') - if dev.get('mount'): + + # Auto-mount vom System bevorzugen + if dev.get('mount') and _mp_is_alive(dev['mount']): return dev['mount'] + + # Gecachten Mount prüfen mp = _browse_mounts.get(port) - if mp and Path(mp).is_dir(): - return mp + if mp: + if _mp_is_alive(mp): + return mp + _drop_browse_mount(port) # veraltet → aufräumen + + # Frisch mounten mp = f'/mnt/picopy_br_{port}' os.makedirs(mp, exist_ok=True) r = subprocess.run(['mount', dev['device'], mp], capture_output=True) @@ -592,11 +622,11 @@ def r_browse(): devs = usb_devices() dev = next((d for d in devs if d['usb_port'] == port), None) if not dev: - return jsonify(error='Gerät nicht verbunden'), 404 + return jsonify(error='Gerät nicht verbunden – bitte neu einstecken'), 404 mp = get_browse_mp(dev) if not mp: - return jsonify(error='Gerät nicht mountbar'), 500 + return jsonify(error='Gerät nicht lesbar – bitte neu einstecken'), 500 try: base = Path(mp).resolve() @@ -618,12 +648,19 @@ def r_browse(): 'size': s.st_size if item.is_file() else None, 'mtime': datetime.fromtimestamp(s.st_mtime).strftime('%d.%m.%y %H:%M'), }) - except Exception: + except OSError: pass rel = str(target.relative_to(base)) return jsonify(path='' if rel == '.' else rel, entries=entries) + except OSError as e: + import errno as _errno + if e.errno == _errno.EIO: + # I/O-Fehler = Gerät abgezogen, Mount bereinigen + _drop_browse_mount(port) + return jsonify(error='Gerät nicht mehr erreichbar – bitte neu einstecken'), 503 + return jsonify(error=str(e)), 500 except Exception as e: return jsonify(error=str(e)), 500