GPS neustart eingebaut

This commit is contained in:
2026-05-25 16:34:07 +02:00
parent 8c8bfd9e5b
commit 5b1ac5fe62
7 changed files with 3954 additions and 27 deletions
@@ -1,4 +1,5 @@
#!/usr/bin/env python3
import errno
import fcntl
import glob
import http.server
@@ -8,6 +9,7 @@ import shutil
import socketserver
import struct
import subprocess
import termios
import threading
import time
@@ -25,6 +27,14 @@ CAMERA_SETTINGS_FILE = os.path.join(
os.path.dirname(__file__), '..', 'config', 'camera_settings.json'
)
MOTOR_TEST_LOCK = threading.Lock()
GPS_PORT_PATTERNS = [
'/dev/serial/by-id/*',
'/dev/serial/by-path/*',
'/dev/ttyUSB*',
'/dev/ttyACM*',
]
GPS_BAUD_RATE = 4800
GPS_COLD_START_COMMAND = '$PAIR006*3C\r\n'
CAMERA_PROFILES = [
{
'id': '640x480',
@@ -216,6 +226,31 @@ def get_wifi_status():
return 'kein wlan0'
def get_wifi_signal():
stdout, _, returncode = run_command(['nmcli', '-t', '-f', 'GENERAL.STATE,AP.SIGNAL', 'device', 'show', 'wlan0'])
if returncode != 0 or not stdout:
return 'unbekannt'
state = ''
signal = ''
for line in stdout.splitlines():
if line.startswith('GENERAL.STATE:'):
state = line.split(':', 1)[1].strip()
elif line.startswith('AP[1].SIGNAL:'):
signal = line.split(':', 1)[1].strip()
if 'connected' not in state.lower():
return 'nicht verbunden'
if not signal:
return 'unbekannt'
try:
percent = max(0, min(100, int(float(signal))))
except ValueError:
return 'unbekannt'
return f'{percent} %'
def get_systemd_state(service_name):
stdout, _, returncode = run_command(['systemctl', 'is-active', service_name])
if returncode == 0 and stdout:
@@ -245,6 +280,7 @@ def collect_status():
'status': 'Bereit',
'system': {
'wifi': get_wifi_status(),
'wifi_signal': get_wifi_signal(),
'ips': get_ip_addresses(),
'undervoltage': undervoltage['text'],
'undervoltage_state': undervoltage['state'],
@@ -451,6 +487,85 @@ def restart_exomy_container():
subprocess.Popen(['docker', 'restart', EXOMY_CONTAINER])
def restart_gps_node():
subprocess.Popen([
'docker', 'exec', EXOMY_CONTAINER, 'bash', '-lc',
"pkill -f '/root/exomy_ws/src/exomy/src/gps_node.py' || true; "
"sleep 1; "
"source /opt/ros/melodic/setup.bash && source /root/exomy_ws/devel/setup.bash && "
"nohup python /root/exomy_ws/src/exomy/src/gps_node.py > /tmp/gps_node.log 2>&1 &"
])
def resolve_gps_device():
candidates = []
seen = set()
for pattern in GPS_PORT_PATTERNS:
for path in sorted(glob.glob(pattern)):
if path in seen:
continue
seen.add(path)
candidates.append(path)
return candidates[0] if candidates else None
def configure_gps_serial(fd, baud_rate):
baud_map = {
4800: termios.B4800,
9600: termios.B9600,
19200: termios.B19200,
38400: termios.B38400,
57600: termios.B57600,
115200: termios.B115200,
}
baud = baud_map.get(int(baud_rate), termios.B4800)
attrs = termios.tcgetattr(fd)
attrs[0] = 0
attrs[1] = 0
attrs[2] = termios.CS8 | termios.CREAD | termios.CLOCAL
attrs[3] = 0
attrs[4] = baud
attrs[5] = baud
attrs[6][termios.VMIN] = 0
attrs[6][termios.VTIME] = 0
termios.tcsetattr(fd, termios.TCSANOW, attrs)
termios.tcflush(fd, termios.TCIOFLUSH)
def send_gps_serial_command(command_text, baud_rate=GPS_BAUD_RATE):
device_path = resolve_gps_device()
if not device_path:
raise RuntimeError('Kein GPS-Empfänger gefunden')
payload = command_text.encode('ascii')
fd = None
try:
fd = os.open(device_path, os.O_RDWR | os.O_NOCTTY | os.O_NONBLOCK)
configure_gps_serial(fd, baud_rate)
os.write(fd, payload)
termios.tcdrain(fd)
except OSError as exc:
if exc.errno == errno.ENOENT:
raise RuntimeError('GPS-Gerät nicht erreichbar')
raise RuntimeError(f'GPS-Befehl fehlgeschlagen: {exc}')
except termios.error as exc:
raise RuntimeError(f'GPS-Port konnte nicht konfiguriert werden: {exc}')
finally:
if fd is not None:
try:
os.close(fd)
except OSError:
pass
return device_path
def cold_start_gps_receiver():
device_path = send_gps_serial_command(GPS_COLD_START_COMMAND)
time.sleep(1.5)
restart_gps_node()
return device_path
def stop_exomy_container():
stdout, _, returncode = run_command(['docker', 'stop', '-t', '2', EXOMY_CONTAINER])
return returncode == 0, stdout
@@ -1256,6 +1371,14 @@ class Handler(http.server.BaseHTTPRequestHandler):
return
actions = {
'/api/cold-start-gps': {
'handler': cold_start_gps_receiver,
'status': 'GPS-Kaltstart wird ausgelöst'
},
'/api/restart-gps': {
'handler': restart_gps_node,
'status': 'GPS-Node wird neu gestartet'
},
'/api/restart-camera': {
'handler': restart_camera_service,
'status': 'Kameradienst wird neu gestartet'