Anleitungen erstellt und Bildrate einstellbar

This commit is contained in:
2026-05-25 17:09:31 +02:00
parent 3207b58772
commit 023017d1fb
10 changed files with 663 additions and 36 deletions
@@ -63,6 +63,8 @@ CAMERA_PROFILES = [
]
CAMERA_PROFILE_MAP = {profile['id']: profile for profile in CAMERA_PROFILES}
DEFAULT_CAMERA_PROFILE_ID = '1296x972'
CAMERA_FPS_OPTIONS = [1, 2, 3, 4, 5, 7, 10, 20]
DEFAULT_CAMERA_FPS = 10
class ReusableThreadingTCPServer(socketserver.ThreadingTCPServer):
@@ -292,6 +294,7 @@ def collect_status():
},
'services': {
'camera': get_systemd_state('exomy-camera-stream.service'),
'camera_settings_version': read_camera_settings_version(),
'admin_api': get_systemd_state('exomy-admin-api.service'),
'exomy': get_container_state(EXOMY_CONTAINER),
}
@@ -363,6 +366,16 @@ def normalize_camera_profile(profile_id):
return dict(profile)
def normalize_camera_fps(value):
try:
fps = int(value)
except (TypeError, ValueError):
raise ValueError('Unbekannte Bildrate')
if fps not in CAMERA_FPS_OPTIONS:
raise ValueError('Unbekannte Bildrate')
return fps
def read_camera_settings():
default_profile = get_default_camera_profile()
try:
@@ -371,37 +384,58 @@ def read_camera_settings():
except (FileNotFoundError, json.JSONDecodeError, OSError, ValueError, TypeError):
return default_profile
selected_profile_id = str(payload.get('profile', '')).strip()
if selected_profile_id in CAMERA_PROFILE_MAP:
return dict(CAMERA_PROFILE_MAP[selected_profile_id])
try:
width = int(payload.get('width', default_profile['width']))
height = int(payload.get('height', default_profile['height']))
fps = int(payload.get('fps', default_profile['fps']))
fps = normalize_camera_fps(payload.get('fps', DEFAULT_CAMERA_FPS))
except (TypeError, ValueError):
return default_profile
fps = DEFAULT_CAMERA_FPS
for profile in CAMERA_PROFILES:
if profile['width'] == width and profile['height'] == height and profile['fps'] == fps:
return dict(profile)
return default_profile
selected_profile_id = str(payload.get('profile', '')).strip()
if selected_profile_id in CAMERA_PROFILE_MAP:
profile = dict(CAMERA_PROFILE_MAP[selected_profile_id])
else:
profile = None
for item in CAMERA_PROFILES:
if item['width'] == width and item['height'] == height:
profile = dict(item)
break
if profile is None:
profile = default_profile
profile['fps'] = fps
return profile
def write_camera_settings(profile):
def write_camera_settings(profile, fps):
profile = dict(profile)
fps = normalize_camera_fps(fps)
os.makedirs(os.path.dirname(CAMERA_SETTINGS_FILE), exist_ok=True)
payload = {
'profile': profile['id'],
'width': profile['width'],
'height': profile['height'],
'fps': profile['fps'],
'fps': fps,
'updated_at': int(time.time()),
}
with open(CAMERA_SETTINGS_FILE, 'w', encoding='utf-8') as handle:
json.dump(payload, handle, indent=2, sort_keys=True)
handle.write('\n')
def read_camera_settings_version():
try:
with open(CAMERA_SETTINGS_FILE, 'r', encoding='utf-8') as handle:
payload = json.load(handle)
except (FileNotFoundError, json.JSONDecodeError, OSError, ValueError, TypeError):
return 0
try:
return int(payload.get('updated_at', 0))
except (TypeError, ValueError):
return 0
def get_camera_config():
profile = read_camera_settings()
return {
@@ -411,14 +445,23 @@ def get_camera_config():
'width': profile['width'],
'height': profile['height'],
'fps': profile['fps'],
'fps_options': list(CAMERA_FPS_OPTIONS),
'profiles': [dict(item) for item in CAMERA_PROFILES],
}
}
def set_camera_profile(profile_id):
profile = normalize_camera_profile(profile_id)
write_camera_settings(profile)
def set_camera_config(profile_id=None, fps=None):
current = read_camera_settings()
if profile_id is None:
profile = normalize_camera_profile(current['id'])
else:
profile = normalize_camera_profile(profile_id)
if fps is None:
fps = current.get('fps', DEFAULT_CAMERA_FPS)
fps = normalize_camera_fps(fps)
profile['fps'] = fps
write_camera_settings(profile, fps)
restart_camera_service()
return profile
@@ -1164,14 +1207,15 @@ class Handler(http.server.BaseHTTPRequestHandler):
self.write_json(400, {'status': 'Ungültige Anfrage'})
return
try:
profile = set_camera_profile(payload.get('profile'))
profile = set_camera_config(payload.get('profile'), payload.get('fps'))
self.write_json(200, {
'status': 'Kameraauflösung gespeichert, Kameradienst startet neu',
'status': 'Kameraprofil gespeichert, Kameradienst startet neu',
'camera': {
'selected_profile': profile['id'],
'width': profile['width'],
'height': profile['height'],
'fps': profile['fps'],
'fps_options': list(CAMERA_FPS_OPTIONS),
'profiles': [dict(item) for item in CAMERA_PROFILES],
}
})