Verbessere die Mount-Überprüfung und Fehlerbehandlung für USB-Geräte
This commit is contained in:
49
app.py
49
app.py
@@ -568,13 +568,43 @@ def r_wifi_status():
|
|||||||
|
|
||||||
_browse_mounts = {} # usb_port -> mount_point
|
_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):
|
def get_browse_mp(dev):
|
||||||
port = dev.get('usb_port', '')
|
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']
|
return dev['mount']
|
||||||
|
|
||||||
|
# Gecachten Mount prüfen
|
||||||
mp = _browse_mounts.get(port)
|
mp = _browse_mounts.get(port)
|
||||||
if mp and Path(mp).is_dir():
|
if mp:
|
||||||
return mp
|
if _mp_is_alive(mp):
|
||||||
|
return mp
|
||||||
|
_drop_browse_mount(port) # veraltet → aufräumen
|
||||||
|
|
||||||
|
# Frisch mounten
|
||||||
mp = f'/mnt/picopy_br_{port}'
|
mp = f'/mnt/picopy_br_{port}'
|
||||||
os.makedirs(mp, exist_ok=True)
|
os.makedirs(mp, exist_ok=True)
|
||||||
r = subprocess.run(['mount', dev['device'], mp], capture_output=True)
|
r = subprocess.run(['mount', dev['device'], mp], capture_output=True)
|
||||||
@@ -592,11 +622,11 @@ def r_browse():
|
|||||||
devs = usb_devices()
|
devs = usb_devices()
|
||||||
dev = next((d for d in devs if d['usb_port'] == port), None)
|
dev = next((d for d in devs if d['usb_port'] == port), None)
|
||||||
if not dev:
|
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)
|
mp = get_browse_mp(dev)
|
||||||
if not mp:
|
if not mp:
|
||||||
return jsonify(error='Gerät nicht mountbar'), 500
|
return jsonify(error='Gerät nicht lesbar – bitte neu einstecken'), 500
|
||||||
|
|
||||||
try:
|
try:
|
||||||
base = Path(mp).resolve()
|
base = Path(mp).resolve()
|
||||||
@@ -618,12 +648,19 @@ def r_browse():
|
|||||||
'size': s.st_size if item.is_file() else None,
|
'size': s.st_size if item.is_file() else None,
|
||||||
'mtime': datetime.fromtimestamp(s.st_mtime).strftime('%d.%m.%y %H:%M'),
|
'mtime': datetime.fromtimestamp(s.st_mtime).strftime('%d.%m.%y %H:%M'),
|
||||||
})
|
})
|
||||||
except Exception:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
rel = str(target.relative_to(base))
|
rel = str(target.relative_to(base))
|
||||||
return jsonify(path='' if rel == '.' else rel, entries=entries)
|
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:
|
except Exception as e:
|
||||||
return jsonify(error=str(e)), 500
|
return jsonify(error=str(e)), 500
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user