The stand-alone PS4Mount (ps4mount.elf) and the app's module must not run together (both register, mount and unmount the same games). The lock on port 9032 alone did not hold: rest mode closes the sockets of payloads. Now any of three signs counts: its web panel answers on 8770, the lock on 9032 is held by someone else, or a process is named like it. - start and switching on: not loaded a second time while it runs; the module waits (the page says why) and takes over by itself once the stand-alone one has ended (a waiter looks every 15 s) - running: seen twice in a row (e.g. after rest mode), the module gives way and waits instead of switching itself off for the session - payload starts (page and startup profiles): a PS4Mount ELF, known by its content and not by its name, is refused with 409 ps4mount_running while a PS4Mount runs; the app's own ELF is exempt - GET /api/v1/ps4mount names the reason in "standalone" Design: "Aktuell" is now "Standard" and its cards are opaque again; a stored "aktuell" falls back to "standard". Handbook, API notes and translations in six languages. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
48 KiB
Schnittstelle (API)
README · Handbuch · API · Entwicklung
Die Web-Oberfläche spricht mit der App über eine JSON-Schnittstelle unter
http://<PS5-IP>:8086/api/v1/. Alles, was die Oberfläche kann, geht damit auch
aus Skripten. Für Anfragen mit Origin gelten die Regeln aus
HANDBUCH.md.
Endpunkte
| Methode | Pfad | Zweck |
|---|---|---|
| GET | /api/v1/status |
Momentaufnahme (Temperaturen, Lüfter, Adapter) |
| GET/POST | /api/v1/history |
Temperaturverlauf der letzten 24 Stunden (ein Punkt pro Minute) samt Spitzenwerten; POST setzt ihn zurück |
| GET | /api/v1/cooling-health |
Langzeitauswertung der Kühlleistung je Woche (aus thermal-health.csv); seit 1.54.1 zählen nur Wochen unter den jetzt geltenden Einstellungen (Einstellungs-Stempel): zusätzlich weeks_needed (4), since_ms (seit wann diese Einstellungen gelten) und older_weeks (davon ausgeschlossene Wochen) |
| POST | /api/v1/cooling-health |
„Vergleich neu beginnen“: erhöht den Zähler im Stempel, alle bisherigen Wochen bleiben in der Datei, zählen aber nicht mehr mit |
| GET | /api/v1/channels |
Aufzeichnung aller SoC-Sensorkanäle samt Last und Lüfterdrehzahl |
| GET/PUT | /api/v1/config |
Konfiguration lesen / schreiben |
| GET | /api/v1/config/export |
komplette Konfiguration als JSON herunterladen (inkl. Spielprofile) |
| POST | /api/v1/config/import |
komplette Konfiguration aus JSON übernehmen (inkl. Spielprofile) |
| POST | /api/v1/fan/threshold |
Direktwert setzen ({"threshold_c":55}): in automatic als Zieltemperatur, in observe als feste Schwelle |
| POST | /api/v1/tile/ensure |
Homescreen-Kachel installieren |
| POST | /api/v1/tile/upload |
Kachel-Paket als Rohdaten hochladen (bis 64 MB, abgelegt als /data/PS5-Cooling-Center/tile.pkg) |
| POST | /api/v1/power |
Konsole ausschalten, neu starten, in den Ruhemodus oder abgesicherten Modus versetzen ({"action":"off"|"reboot"|"standby"|"safemode"}); 409 standby_disabled, wenn der Ruhemodus in den Energieeinstellungen aus ist |
| GET | /api/v1/logs |
Ereignisse als JSON |
| GET | /api/v1/logs/tail?count=25 |
letzte Einträge für Live-Anzeige |
| GET | /api/v1/klog?after=<n>&max=<m> |
Kernel-Log live: die Zeilen nach Nummer after (0 = die letzten max), höchstens max (Vorgabe 500, bis 1000), älteste zuerst. Antwort {ok, newest, lost, more, lines:[{n, t, s, m?}]}: n Zeilennummer (ab 1, wird nie neu vergeben), t Uhrzeit der Konsole in ms, wann die App die Zeile zuerst sah, s der Text, m:1 ein Hinweis der App (etwa „Lücke“) statt einer Kernelzeile; more: es warten weitere Zeilen; lost: zwischen after und der ersten gelieferten Zeile fehlen welche (die App hält einige tausend) oder die Nummern begannen neu. Gelesen wird kern.msgbuf (eine Kopie, nicht /dev/klog), höchstens zweimal je Sekunde, egal wie viele fragen |
| GET | /api/v1/klog/files |
der Ordner /data/PS5-Cooling-Center/klog-live-log (siehe Handbuch): {ok, dir, count, bytes, files, record}; files neueste zuerst, höchstens 200, je {name, size, mtime, kind, active} (kind save für klog-….log, rec für aufnahme-….log; active wahr bei der Datei, die gerade aufgenommen wird); record wie bei /api/v1/klog/record. Nur Dateien mit diesen beiden Namensformen werden gezählt |
| GET | /api/v1/klog/file?name=<name> |
eine dieser Dateien als Download (Content-Disposition: attachment); 404 für jeden anderen Namen (nur klog- und aufnahme-, dann Buchstaben, Ziffern, -, _, und .log) |
| POST | /api/v1/klog/save?tz=<min> |
Text als Auszug ablegen: Der Rumpf (text/plain, 1 Byte bis 8 MB) wird als klog-<Datum>_<Uhrzeit>.log gespeichert; tz ist die Zeitzone des Absenders in Minuten östlich von UTC (Vorgabe 0 = UTC; bestimmt den Dateinamen). Antwort {ok, name, bytes}. Ein vorhandener Name wird nie überschrieben (Nummer dahinter) |
| POST | /api/v1/klog/files/clear |
löscht alle Dateien dieser Namensformen im Ordner, außer der Aufnahme, die gerade läuft; Antwort {ok, deleted, bytes, kept}. Unterordner, andere Namen und Verknüpfungen bleiben |
| GET/POST | /api/v1/klog/record |
GET der Stand der Aufnahme: {ok, recording, file, bytes, lines, max_bytes, elapsed_s, reason} (reason nennt, warum die letzte endete: angehalten, Größe erreicht …, Speicher der Konsole knapp, Schreibfehler …). POST {"on":true,"tz":<min>} beginnt eine Aufnahme (die Konsole liest das Kernel-Log einmal pro Sekunde und schreibt es in aufnahme-….log; 409, wenn schon eine läuft oder weniger als 512 MB frei sind), POST {"on":false} beendet sie |
| GET | /api/v1/playtime?max=<n> |
Spielzeit-Sitzungen (siehe Handbuch): die gespeicherten, neueste zuerst, höchstens max (Vorgabe und Grenze 3500), dazu die laufende. Antwort {ok, now, enabled, live, titles, sessions, total, kept}: now Uhr der Konsole in Sekunden seit 1970; enabled ist false, wenn die Spielerkennung aus ist (dann wird nichts mitgeschrieben); live die laufende Sitzung oder null: {id, name, start, play, state, cpu_max, cpu_avg, soc_max, soc_avg, fan_avg, fan_max, flags} mit state front (vorn), back (pausiert) oder gone (verschwunden, die 45 s Frist läuft); titles der Name je Titel-ID der gelieferten Sitzungen; sessions je {id, start, end, play, cpu_max, cpu_avg, soc_max, soc_avg, fan_avg, fan_max, flags}: Zeiten in Sekunden nach der Konsolenuhr (end ist der letzte Augenblick im Vordergrund), play die Sekunden im Vordergrund, Temperaturen in °C, Lüfter in % (-1: keine Messung), flags als Bits (1 Notfallmodus, 2 Temperaturwarnung, 4 Ende geschätzt); total die Zahl der gespeicherten Sitzungen (wirklich gezählt, auch wenn sessions höchstens die neuesten 3500 liefert), kept ihre Obergrenze (3000) |
| POST | /api/v1/playtime/reset |
löscht die gespeicherten Sitzungen (sessions.csv); eine laufende zählt weiter |
| GET | /api/v1/saves |
Spielstände (siehe Handbuch): was die Konsole hat, wohin gesichert werden kann, welche Sicherungen es gibt. Antwort {ok, now, console, game_running, game_id, users, drives, backups, unfinished, job}: users je {uid, name, bytes, titles:[{id, name, installed, platform, bytes, files, mtime}]} (platform PS4 oder PS5; name leer und installed falsch, wenn der Titel nicht installiert ist; mtime die neueste Änderung in Sekunden seit 1970); drives je {mount, label, free_bytes} (der Konsolenspeicher heißt /user, gesichert wird dort unter /data); backups die 40 neuesten (nach dem Zeitstempel im Ordnernamen), neueste zuerst, je {created, path, name, mount, label, kind, bytes, files, this_console, users:[{uid, name}], titles:[{uid, id, name, platform, bytes}]} (kind backup oder undo; this_console falsch bei der Sicherung einer anderen Konsole und bei einer, deren Liste keine Konsole nennt); unfinished die Zahl der unfertigen Sicherungen (mit der Marke .ps5cc-unfertig), die nicht aufgelistet werden; game_running wahr, solange ein Spiel läuft, auch pausiert; job wie bei /api/v1/saves/job |
| GET | /api/v1/saves/job |
der Vorgang mit den Spielständen. Antwort {ok, state, active, can_cancel, kind, phase, percent, files_done, files_total, bytes_total, current, error, note, path, undo, ok_files, bad_files, elapsed_s, finished_ago_s}: state idle, scanning, copying, verifying, applying, done, failed oder cancelled; kind backup, verify oder restore; can_cancel ist beim Zurückspielen ab dem Umbenennen der Dateien falsch (bis dahin sind alle neuen Dateien nur neben die alten geschrieben und der Vorgang lässt sich folgenlos abbrechen); path die Sicherung, die gemacht oder geprüft wird, undo die Sicherung des Stands davor; ok_files/bad_files das Ergebnis von Prüfen und Sichern; finished_ago_s Sekunden seit dem Ende, -1 solange nichts zu Ende ging |
| POST | /api/v1/saves/backup |
Sicherung starten: {"target":"/mnt/usb0","users":["10000001"],"titles":["10000001/PPSA01001"]}. target ist ein mount aus drives; users und titles (<Benutzer>/<Titel-ID>) sind wahlweise, ohne sie wird alles gesichert. Antwort ist der Vorgang. 404 unbekanntes Ziel, Benutzer oder Titel; 400 ein falsch geschriebener Titel; 409 ein Spiel läuft (auch pausiert), ein Vorgang läuft schon oder ein Kopieren, Konvertieren, Verschieben von Spielen oder das Aufteilen eines Pakets |
| POST | /api/v1/saves/verify |
eine Sicherung prüfen: {"path":"<path aus backups>"}; 404, wenn es sie nicht (mehr) gibt; 409 bei laufendem Vorgang |
| POST | /api/v1/saves/delete |
die Spielstände eines Titels für einen Benutzer löschen: {"uid":"1ea2f4d9","id":"PPSA01001","mount":"/mnt/usb0"}; mount ist das Ziel der Sicherung des jetzigen Stands; ohne mount wird mit 409 abgelehnt, außer mit "no_backup":true (dann ohne Sicherung). Antwort wie jeder Auftrag (kind: "delete"); 400 bei falschen Kennungen, 404 bei unbekanntem Benutzer, Titel oder Ziel, 409 ohne Ziel oder wenn ein Spiel oder ein anderer Vorgang läuft (ab 1.51.0) |
| POST | /api/v1/saves/restore |
einen Titel zurückspielen: {"path":…,"user":"10000001","title":"PPSA01001","confirm":true}. Ohne "confirm": true (der Wert true, kein Text) 400 confirm_missing: Niemand soll mit einer verirrten Anfrage Spielstände ersetzen. 400 bei einem Benutzer oder Titel, der keine Kennung ist, und bei /saves/backup, wenn users oder titles keine Liste aus Texten ist (oder mehr als 16 Benutzer, 400 Titel enthält: nichts wird stillschweigend gekürzt); 404, wenn Sicherung, Benutzer oder Titel fehlen; 409, wenn ein Spiel läuft, ein Vorgang läuft, die Sicherung unfertig ist oder von einer anderen Konsole stammt |
| POST | /api/v1/saves/cancel |
laufenden Vorgang abbrechen; ab dem Umbenennen der Dateien beim Zurückspielen nimmt die Konsole das nicht mehr an (can_cancel falsch). Antwort ist der Vorgang |
| GET | /api/v1/packages |
die Pakete der letzten Suche (siehe Handbuch): {ok, scanning, ever, seen, parsed, failed, current, scanned_at, now, drives, packages}; ever falsch, solange noch nie gesucht wurde; seen die Zahl der Dateien, die nach einem Paket aussahen, parsed die der gelesenen Pakete, failed die der Dateien, die keins waren; drives je {mount, label, free_bytes, count}; packages je {id, path, file, drive, title_id, content_id, name, version, kind, plat, size, total, mtime, has_icon, parts?} (id eine Kennung aus 16 Hex-Zeichen, die nur für die Liste der letzten Suche gilt; kind base, update oder dlc; plat 5 für PS5, 4 für PS4, 0 unbekannt; bei einem geteilten Paket file der ursprüngliche Dateiname, size die Teile, die gefunden wurden, total das ganze Paket und parts {total, found, missing:[…], complete}) |
| POST | /api/v1/packages/scan |
startet die Suche im Hintergrund (läuft eine, bleibt es dabei); Antwort wie GET /api/v1/packages, mit scanning wahr |
| GET | /api/v1/packages/icon?id=<id> |
das Bild eines Pakets aus der Liste (PNG, 5 Minuten im Browser zu halten, X-Content-Type-Options: nosniff); 404 bei einer Kennung, die die Suche nicht vergeben hat, bei einem Paket ohne Bild und bei einem Bild, das kein PNG ist. Es kommt nie ein Pfad in der Anfrage vor |
| GET | /api/v1/packages/job |
der Vorgang „Paket aufteilen“: {ok, state, active, can_cancel, phase, name, file, dir, parts, part, bytes_total, bytes_done, percent, error, note, sha256, elapsed_s, finished_ago_s}; state idle, splitting, verifying, done, failed oder cancelled; bytes_total ist doppelt so groß wie das Paket (Schreiben, dann Zurücklesen); sha256 die Prüfsumme des Pakets nach dem Lesen; finished_ago_s Sekunden seit dem Ende, -1 solange nichts zu Ende ging |
| POST | /api/v1/packages/split |
ein Paket aufteilen: {"id":"<id>","target":"/mnt/usb0","part_mb":4095}; target ist ein mount aus drives (der Konsolenspeicher heißt /user, geteilt wird dort nach /data/pkg), part_mb die größte Größe einer Teil-Datei in MB (64 bis 65536, höchstens 256 Teile). Antwort ist der Vorgang. 400 bei fehlender oder unzulässiger Größe; 404 bei unbekanntem Paket oder Ziel; 409, wenn das Paket schon ein Teil ist oder nicht größer als ein Teil, im Ordner pkg des Ziels schon Teile dieses Namens liegen, der Platz nicht reicht, schon ein Vorgang läuft oder ein Kopieren, Konvertieren, Verschieben oder eine Sicherung der Spielstände |
| POST | /api/v1/packages/cancel |
den laufenden Vorgang abbrechen; die Konsole entfernt, was geschrieben wurde. Antwort ist der Vorgang |
| GET | /api/v1/packages/install/plan?id=<id> |
was bei der Installation dieses Pakets geschähe (siehe Handbuch): {ok, can_install, blocked, warning, id, name, file, title_id, content_id, version, kind, plat, size, parts, installed, space}; blocked ist leer, wenn nichts im Weg steht, sonst der Grund in Worten (dann ist can_install falsch); warning ein Hinweis, der nichts verhindert; size die Größe des ganzen Pakets (bei einem geteilten die Summe der Teile), parts die Zahl der Teil-Dateien (0 bei einer einzelnen); installed {state, version} (state 1: steht in der Datenbank der Konsole, 0: nicht, -1: nicht feststellbar); space {known, free, needed} in Bytes (der interne Speicher). 404 packages_unknown bei einer Kennung, die die letzte Suche nicht vergeben hat. Es kommt nie ein Pfad in der Anfrage vor |
| GET | /api/v1/packages/install/job |
der Vorgang „Paket installieren“: {ok, state, seq, active, can_cancel, cancelling, helper_restarts, blind, started, verified, phase, name, file, title_id, content_id, version, kind, plat, bytes_total, bytes_done, bytes_sent, percent, remain_s, promote_percent, system_status, attempt, error, error_code, note, elapsed_s, finished_ago_s}; state idle, preparing, starting, installing, finishing, done, failed oder cancelled; bytes_done das, was die Konsole als gelesen meldet (nie mehr, als die App gesendet hat), bytes_sent alles, was der Server ausgeliefert hat (ein Stück, das die Konsole zweimal liest, zählt zweimal, die Zahl kann bytes_total übersteigen); system_status das Wort der Konsole (running, playable, …); attempt der wievielte Versuch (bis 3); helper_restarts wie viele Hilfsprogramme nach dem ersten gestartet wurden (es war weg oder hing; die Installation der Konsole läuft dabei weiter); blind wahr, solange sich die Konsole nicht nach dem Fortschritt fragen lässt (kein Hilfsprogramm): bytes_done ist dann, was der Server zum ersten Mal ausgeliefert hat, und bei done heißt es: alles ausgeliefert, ob die Installation fertig ist, steht nicht fest (verified ist dann falsch); error_code der Code der Konsole als 0x…, leer bei allem, was von der App kommt; cancelling wahr, wenn das Stoppen verlangt wurde und noch läuft (dann ist can_cancel falsch); started wahr, sobald die Konsole das Paket angenommen hat (ab da kann sie etwas angelegt haben, das bei einem Abbruch liegen bleibt); verified bei done: das Ergebnis wurde in der Liste der Konsole gefunden (falsch: „fertig gemeldet, nicht bestätigt“, die Gründe stehen in note); remain_s ist 0, wenn die Konsole keine Schätzung nennt; elapsed_s und finished_ago_s laufen nach einer Uhr, die nur vorwärts geht; note ein Hinweis (Abbruch, lange Wartezeit, „noch nicht in der Liste“); remain_s die Restzeit, die die Konsole schätzt; promote_percent der Fortschritt, den die Konsole für das Freischalten zum Spielen nennt; finished_ago_s Sekunden seit dem Ende, -1 solange nichts zu Ende ging |
| POST | /api/v1/packages/install |
eine Installation starten: {"id":"<id>"} (die Kennung aus der Liste; sonst nichts). Antwort ist der Vorgang. Die Konsole prüft dabei noch einmal alles, was der Plan zeigt. 404 bei einer unbekannten Kennung; 409 mit dem Grund in Worten (install_refused) bei allem, was im Weg steht: schon installiert, das Spiel läuft, ein anderer Vorgang läuft (Kopieren, Konvertieren, Verschieben, Sichern, Teilen, eine Installation), die Datei hat sich verändert. Gestartet wird nie ohne diesen Aufruf |
| POST | /api/v1/packages/install/cancel |
die laufende Installation abbrechen (das Hilfsprogramm und der Server werden beendet; was die Konsole schon angelegt hat, bleibt unter Umständen liegen). Antwort ist der Vorgang; läuft keiner, bleibt er idle oder bei seinem Ergebnis |
| GET | /api/v1/packages/queue |
die Warteschlange der Installationen: {ok, running, pause_requested, cancelling, halted, halt_kind ("failed", "stopped", "wait"), halt_reason, job_seq, max, counts{total, waiting, running, done, failed, skipped, cancelled}, items[{id, name, title_id, version, kind, plat, size, mtime, has_icon, state, message, verified}]}; job_seq ist die seq des Installationsvorgangs, den die Warteschlange zuletzt gestartet hat (so erkennt die Seite ihn in install/job) |
| POST | /api/v1/packages/queue/add |
Pakete der letzten Suche hineinlegen: {"ids":["<id>", …]} (oder {"id":"<id>"}, höchstens 64); Antwort wie GET plus added, ignored, message. Was schon wartet oder läuft, wird nicht doppelt aufgenommen |
| POST | /api/v1/packages/queue/start |
die Warteschlange starten oder nach einem Halt fortsetzen; 409, wenn sie läuft, nichts wartet oder eine Installation läuft |
| POST | /api/v1/packages/queue/pause |
nach dem laufenden Paket anhalten |
| POST | /api/v1/packages/queue/cancel |
das laufende Paket abbrechen und die Warteschlange anhalten |
| POST | /api/v1/packages/queue/remove |
ein Paket herausnehmen: {"id":"<id>"}; 409 beim laufenden |
| POST | /api/v1/packages/queue/retry |
fehlgeschlagene, abgebrochene und übersprungene wieder wartend machen ({"id":…} oder alle) |
| POST | /api/v1/packages/queue/clear |
{"all":false}: die erledigten entfernen; {"all":true}: alles außer dem laufenden |
| POST | /api/v1/packages/live/init |
eine Übertragung vom PC beginnen: {"name":"x.pkg","size":<Bytes>}; Antwort ist der Zustand mit id (live-N), seg_bytes (1 MiB), slots, send (welche Stücke gewünscht sind). 400 bei ungültigem Namen oder unplausibler Größe, 409 wenn schon eine Übertragung oder ein anderer Vorgang läuft, 503 ohne Speicher (ab 1.52.0) |
| PUT, POST | /api/v1/packages/live/segment?id=<id>&n=<Nr> |
ein Stück (Rohdaten, höchstens 1 MiB, das letzte so lang wie der Rest) in den Ring; Antwort ist der neue Zustand. 400 bei falscher Länge oder Nummer, 404 unbekannt, 410 die Übertragung ist beendet, 503 busy (kein Platz im Ring: kurz warten und noch einmal), 408 wenn das Stück nicht vollständig ankam |
| GET | /api/v1/packages/live/state?id=<id>[&since=<ver>&wait=<ms>] |
Zustand: state (head, parsing, ready, failed, ended), send (wunschgeordnet), ver, bytes_in, resident, nach dem Lesen des Kopfes title_id, content_id, title, version, kind, plat; error bei failed und ended. Mit since und wait (höchstens 5000 ms) antwortet die Abfrage erst, wenn sich ver geändert hat |
| POST | /api/v1/packages/live/cancel |
die Übertragung beenden ({"id":"live-N"}). Installiert wird mit POST /packages/install und {"id":"live-N"}, der Plan kommt von GET /packages/install/plan?id=live-N |
| GET | /api/v1/qr |
die Adresse dieser Weboberfläche als QR-Code: {"ok":true,"url":"http://192.168.1.94:8086/","svg":"<svg …>"}; der Server erzeugt ihn nur für die eigene Adresse und nimmt keinen Text entgegen; 404 no_address, wenn die Konsole keine Netzwerkadresse hat (ab 1.52.0) |
| GET | /api/v1/system |
Modell, Firmware, Laufzeit, RAM, Laufwerke |
| GET | /api/v1/payloads |
laufende Payloads (Prozesse) |
| POST | /api/v1/payloads/kill |
ein laufendes Payload beenden ({"pid":123}) |
| GET | /api/v1/payload-files |
Payload-Dateien: Ordner /data/PS5-Cooling-Center/payloads und .elf-Dateien auf USB-Sticks (Hauptverzeichnis und Ordner payloads); je Datei Größe, Datum, valid und bei Ungültigen der Grund (ab 1.46.0) |
| POST | /api/v1/payload-files/start |
Payload an den ELF-Lader (Port 9021) senden: {"source":"internal"|"usb","mount":"/mnt/usb0","dir":""|"payloads","name":"x.elf"}; Antwort mit Bytes und den ersten Worten des Payloads; 409 ps4mount_running, wenn die Datei PS4Mount ist (erkannt am Inhalt) und schon ein PS4Mount läuft, das der App oder ein eigenständiges |
| POST | /api/v1/payload-files/copy |
von einem USB-Stick in den internen Ordner kopieren (mount, dir, name; vorhandene Dateien werden nie überschrieben) |
| POST | /api/v1/payload-files/delete |
eine Datei aus dem internen Ordner löschen ({"name":"x.elf"}) |
| GET, POST | /api/v1/payload-profiles |
Payload-Profile: GET liefert {"startup":"<id>","profiles":[{"id","name","items":["a.elf","!2000"]}]}; POST ersetzt das ganze Dokument (geprüft: höchstens 24 Profile, 64 Einträge, Einträge sind .elf-Namen ohne Pfad oder Pausen !<ms> mit 1…600000, Kennungen a-z0-9-_; Antwort 400 mit Grund) (ab 1.51.0) |
| POST | /api/v1/payload-profiles/run |
Profil ausführen ({"id":"…"}), 202; 404 unbekannt, 409 läuft schon, 400 leer |
| POST | /api/v1/payload-profiles/stop |
den laufenden Ablauf nach dem aktuellen Schritt anhalten |
| GET | /api/v1/payload-profiles/status |
running, id, name, step, total, startup, results[{item,ok,msg}] |
| GET | /api/v1/controller/diag |
Passive Controller/HID-Diagnose (nur Verfügbarkeit) |
| GET | /api/v1/sensors/risky |
Risky-Telemetrie auf Abruf (Last/Takt/Leistung) |
| GET | /api/v1/drives |
Optionale Laufwerkstelemetrie (/dev/daN, wenn freigeschaltet) |
| GET | /api/v1/logs/export |
Ereignisse als Textdatei |
| GET | /api/v1/library |
Spiele des Startbildschirms aus der App-Datenbank der Konsole: Titel, Titel-/Content-ID, Version, Spielzeit, Format/Speicherort, Backport/AMPR/PlayGo (ab 1.46.0) |
| GET | /api/v1/library/cover?id=PPSA20396 |
Cover eines Spiels aus der Liste (PNG, darf zwischengespeichert werden) |
| GET | /api/v1/library/cache |
der Zwischenspeicher „Covers & Metadaten speichern“ (siehe Handbuch): {ok, enabled, dir, titles, covers, bytes}; dir ist /data/PS5-Cooling-Center/covers_and_more, titles die Zahl der Spiele-Ordner darin, covers die der Bildkopien, bytes ihre Größe. Der Schalter selbst ist das Konfigurationsfeld library_cache |
| POST | /api/v1/library/cache/clear |
leert den Ordner (nur, was die App selbst angelegt hat: Ordner mit einer Titel-ID als Namen, darin meta.json, icon0.png und deren Zwischendateien). Antwort {ok, titles, bytes}; die nächste Liste wird neu gelesen und füllt den Ordner wieder, wenn der Schalter an ist |
| POST | /api/v1/library/launch |
Start ({"id":"PPSA20396"}): Läuft das Spiel schon, wird es nach vorn geholt; läuft keines, startet es direkt wie der Homebrew Launcher. Beides schließt dabei den Browser der Konsole, wenn von dort ausgelöst. Lehnt der Starter ab (etwa ein Abbild, das ShadowMountPlus noch nicht eingehängt hat), kommt eine Meldung mit Taste „Starten“. Derselbe Titel wird innerhalb von 30 s nie ein zweites Mal gestartet oder angeboten (already_starting): Einen laufenden Titel erneut zu starten, bringt die Konsole laut Elf Arsenal zum Absturz. Läuft ein anderes Spiel, wird nichts gestartet: Antwort 409 other_running mit running und target (je id, name). Ob ein Spiel läuft, fragt die App auch den Kernel (auch pausierte Spiele und solche hinter dem Browser). Mit {"id":…,"close":"<Titel-ID des laufenden Spiels>"} beendet die Konsole jenes Spiel im Hintergrund und startet danach das neue (202; Verlauf unter GET /api/v1/library/close); die Seite nutzt das seit dem 03.10.2026 nicht mehr, sie beendet mit /library/close und startet erst auf den nächsten Tipp |
| GET/POST | /api/v1/library/close |
POST {"id":"<laufendes Spiel>"} beendet das laufende Spiel im Hintergrund (SIGKILL auf dessen eboot.bin, wie „Close App“ in Elf Arsenal; nur der Titel, den die Seite nennt; nicht Gespeichertes geht verloren). GET meldet den Auftrag: state (idle, closing, starting, done, failed), closing, then, message. done erst, wenn das System den Bereich des Spiels (/mnt/sandbox/<ID>_…) entfernt hat und eine weitere Sekunde vergangen ist (so wartet auch ShadowMountPlus, bevor es aushängt): Das nächste Spiel startet dann sofort |
| GET | /api/v1/library/copy/plan?id=PPSA20396 |
Kopierplan: Laufwerke und Ziele (A Homebrew, mit Warnung vor ShadowMountPlus-Doppelfund / B Sicherung) |
| GET/POST | /api/v1/library/copy |
Status / Kopieren starten ({"id":…,"target":…,"mode":"homebrew"|"backup"}) |
| POST | /api/v1/library/copy/cancel |
laufendes Kopieren abbrechen |
| GET | /api/v1/library/convert/plan?id=PPSA20396 |
Konvertierungsplan: mögliche Zielformate für diesen Titel, raw_bytes (Größe als exFAT-Abbild) und ffpkg_bytes (Größe des .ffpkg; 0, wenn sie sich nicht berechnen lässt, dann nennt ffpkg_error den Grund, z. B. einen Ordner mit zu vielen Einträgen), je Ziel, ob der Platz reicht und ob FAT32 die Datei nicht aufnimmt (fat32_too_big nach der Größe als exFAT-Abbild, fat32_too_big_ffpkg nach der des .ffpkg) |
| GET/POST | /api/v1/library/convert |
Status / Konvertieren starten ({"id":…,"op":"exfat"|"ffpkg"|"ffpfsc","target":…,"mode":"homebrew"|"backup","ampr_index":true}; ampr_index baut bei einem Dump-Ordner vorher den AMPR-Index) |
| POST | /api/v1/library/convert/cancel |
laufende Konvertierung abbrechen |
| GET | /api/v1/library/ampr?id=PPSA20396 |
AMPR-Index des Spiels: format, has_index, files, mtime, can_build und, wenn nicht, der Grund why |
| POST | /api/v1/library/ampr |
AMPR-Index bauen ({"id":…}): Dump-Ordner direkt, Abbild über ShadowMountPlus (/games/mount mit "mode":"rw", danach /games/unmount); ein alter Index bleibt als ampr_emu.index.bak |
| GET | /api/v1/library/ampr/job |
Stand des Auftrags (idle/running/done/failed, phase, files, collisions, error) |
| POST | /api/v1/ampr-emu/install |
Die in der App mitgelieferten Versionen, die noch nicht im Ordner liegen, dorthin legen (entpackt, Prüfsumme geprüft; eine gleichnamige Datei der Person bleibt); Antwort wie die Liste, dazu installed (wie viele) |
| GET | /api/v1/ampr-emu |
Die Versionen der APR-EMU-Datei im Ordner /data/PS5-Cooling-Center/AMPR_EMU (neueste zuerst): name, label, version, variant, size, sha256, pack (liest LZ4-Pakete), debug, valid (SELF-Kopf und Kennung [AMPR_EMU]), stored (liegt im Ordner), bundled (die App bringt genau diese Datei mit; nicht im Ordner liegende mitgelieferte stehen trotzdem in der Liste); dazu emus (der Emulator-Ordner von ShadowMountPlus) |
| POST | /api/v1/playgo/install |
Wie /api/v1/ampr-emu/install, für die PlayGo-Stubs (Ordner /data/PS5-Cooling-Center/PlayGo) |
| GET | /api/v1/playgo |
Wie /api/v1/ampr-emu, für die PlayGo-Stubs (libScePlayGo.sprx-0.6-log/-nolog; Kennung playgo_stub.dat; pack immer false, debug bei „log“); die Antworten tragen lib (ampr/playgo) |
| GET | /api/v1/library/emu?id=PPSA20396&lib=playgo |
Wie die nächste Zeile; lib ist ampr (Standard) oder playgo (libScePlayGo.sprx, packed immer false); eine andere Angabe gibt 400 |
| GET | /api/v1/library/trace?id=PPSA06328 |
Der Mitschnitt eines Spiels (trace.c): ob er laufen kann (can_start, sonst why), ob fakelib2 mit der Debug-APR-EMU liegt (active), die eingesammelten Sitzungen und das erzeugte Profil |
| POST | /api/v1/library/trace |
{"id":…,"action":"start"|"collect"|"generate"|"stop"}: Mitschnitt starten (legt fakelib2 an), die Sitzung nach /data/PS5-Cooling-Center/traces/<Titel-ID>/<n>/ einsammeln, aus allen Sitzungen das Profil <Titel-ID>-mitschnitt.toml in LZ4_Profile erzeugen, Mitschnitt beenden (entfernt fakelib2); Antwort {ok, message}, bei Ablehnung 4xx trace_refused |
| GET | /api/v1/library/plugins?id=PPSA06328 |
Die Spiel-Plugins (plugins.c): je Bibliothek (libScePlayGo.sprx, DLC-Module) Zustand (missing, current, old, unknown, noexec), Fassung und ob die App sie ändern darf |
| GET | /api/v1/ps4mount |
PS4Mount (src/ps4m_core.c): enabled, running, standalone (nur wenn eingeschaltet und wartend: warum, das eigenständige ps4mount.elf läuft), version, config (batch, batch_size, dlc, paths) und games (je title_id, name, version, has_patch, size, state = ready/running/pending/removed/internal/duplicate, mount, source, dlc, update_issue) |
| POST | /api/v1/ps4mount |
{"action":"enable"|"disable"|"scan"|"add"|"remove"|"config"}; add und remove mit "id":"CUSAxxxxx", config mit batch, batch_size, dlc, paths (eine Zeile je Ordner); Antwort {ok, message}, 409 bei Ablehnung |
| GET | /api/v1/ps4mount/icon?id=CUSAxxxxx |
icon0.png des Spiels (aus der Konsole oder dem Paket) |
| GET | /api/v1/ps4mount/log |
Ende des Protokolls (/data/ps4mount/log.txt) als {log} |
| POST | /api/v1/library/plugins |
{"id":…}: bringt die Plugins des Spiels auf den neuesten Stand (alte Datei als .old, Ausführungsrecht gesetzt); Antwort {ok, message, detail} |
| GET | /api/v1/library/emu?id=PPSA20396 |
Die APR-EMU-Datei eines Spiels: place (game: fakelib im Spiel, backport: <Suchpfad>/backports/<Titel-ID>/fakelib), can_change/why, installed (present, size, sha256, emu, known, label, pack, has_orig), packed, fakelib2, backport, emus (overrides: ShadowMountPlus ersetzt die Datei beim Spielstart) |
| POST | /api/v1/library/emu |
Ändern ({"id":…,"action":"apply"|"restore"|"remove","name":"libSceAmpr.sprx-0.4.2.1-test-pack"}, name nur bei apply; dazu "lib":"playgo" für die PlayGo-Datei, sonst APR-EMU); läuft als Auftrag des AMPR-Index (.../library/ampr/job, dort kind: "emu", lib, op, note; im Verlauf ampr_emu oder playgo) |
| GET | /api/v1/library/lz4?id=PPSA20396 |
LZ4-Pakete des Spiels: can/why (nur Spiele als Ordner), ampr_import (1: eboot.bin oder ein Modul in sce_module nennt libSceAmpr, 0: nicht, -1: eboot.bin nicht lesbar; bei 0 lehnt POST pack/copy mit 409 ab), has_index, free_bytes, packed, bei gepackten pack (files_packed, files_loose, logical_bytes, stored_bytes, volumes, chunks, has_crc, build_id), last_check (when, bytewise, files), profiles (id wie app:name.toml/usb0:name.toml, name, where; Ordner /data/PS5-Cooling-Center/LZ4_Profile und <Laufwerk>/LZ4_Profile) |
| GET | /api/v1/library/lz4/plan?id=…&level=9&profile=app:x.toml |
Was die Auswahl packen würde, ohne zu packen: valid, pack_files, pack_bytes, loose_files, loose_bytes, chunks, block_shift (oder valid: false mit error samt Zeilennummer) |
| POST | /api/v1/library/lz4 |
Starten ({"id":…,"kind":"pack"|"copy"|"verify"|"unpack","level":9,"profile":""}); läuft im Platz der Abbild-Aufträge (Fortschritt /api/v1/library/image/job mit kind lz4pack/lz4copy/lz4verify/lz4unpack und lz4_logical, lz4_stored, lz4_packed, lz4_loose; Abbrechen /api/v1/library/image/cancel); 409, wenn das Spiel läuft, ein anderer Vorgang läuft, es schon gepackt ist (pack/copy), nicht gepackt ist (verify/unpack) oder der Ordner <Name>-lz4 schon besteht |
| GET | /api/v1/library/image?id=PPSA20396 |
Abbild des Spiels: format (exfat/ffpkg/ffpfsc), image_bytes, can_check, can_unpack, repair (state fine/fixable/broken/na, bei fixable declared und actual, bei broken der Grund why), last_check (Ergebnis der letzten Prüfung dieses Abbilds, bis zum Neustart), bei can_check: false der Grund why |
| GET | /api/v1/library/image/plan?id=PPSA20396 |
Entpackplan: files, size_bytes, largest_bytes, damaged und je Laufwerk mount, label, path (<Laufwerk>/homebrew/<Name>), free_bytes, exists, enough_space, fat32_too_big, path_too_long; 409, wenn das Spiel kein Abbild ist |
| POST | /api/v1/library/image |
Vorgang starten ({"kind":"check"|"unpack"|"repair","id":…,"target":"/mnt/usb0"}, target nur beim Entpacken); 409, wenn das Spiel läuft, ein anderer Vorgang der App läuft oder das Abbild nicht zum Vorgang passt |
| GET | /api/v1/library/image/job |
Stand: state (idle/running/done/failed/cancelled), kind, phase, current, work_done/work_total, files_done/files_total, bad_files, bad[] (path, offset), container, clean, dest, fixed_from/fixed_to, bytes_per_s, eta_s |
| POST | /api/v1/library/image/cancel |
laufenden Abbild-Vorgang abbrechen (beim Entpacken wird der unfertige Ordner entfernt) |
| GET | /api/v1/jobs/history |
Verlauf aller Vorgänge der App, neueste zuerst: entries[] mit t, kind, title, detail, result (done/failed/cancelled), error, bytes, ms (höchstens 500, Datei /data/PS5-Cooling-Center/history.jsonl) |
| POST | /api/v1/jobs/history/clear |
Verlauf leeren |
| GET | /api/v1/library/storage/plan?id=PPSA20396&op=move |
Verschiebe-/Entpackplan über ShadowMountPlus (op move oder unpack) |
| GET/POST | /api/v1/library/storage |
Status / Verschieben oder Entpacken starten ({"id":…,"op":"move"|"unpack","target":…,"delete_source":false}), beides über ShadowMountPlus |
| POST | /api/v1/library/storage/cancel |
laufendes Verschieben/Entpacken abbrechen |
| POST | /api/v1/library/delete/plan |
was Löschen täte: Body {kind:"game"|"backup", id: Titel-ID oder Pfad einer Sicherung}; Antwort {ok, kind (installed|smp|backup|other), id, name, path, format, version, size_bytes, saves_kept, items[], can_delete, why?, confirm?}; confirm ist das Kennwort für den Start (einmal, 10 min) |
| GET/POST | /api/v1/library/delete |
GET der Löschauftrag {ok, state (idle|deleting|done|failed), active, kind, id, name, phase, error, note, files, bytes, percent, bytes_total, bytes_done, elapsed_s, finished_ago_s}; percent der Fortschritt 0–100 (100 nur bei done), bytes_total/bytes_done die Bytes des laufenden Schritts (Spieldaten oder Sicherung beim Löschen; bei einem installierten Spiel seine Ordner, die die Konsole leert; 0, wenn nichts zu zählen ist); POST {kind, id, confirm} startet ihn (403 ohne gültiges Kennwort, 409 wenn es gerade nicht geht) |
| GET | /api/v1/files/places |
die Orte des Dateimanagers: {ok, places:[{label, path, free_bytes, writable}]} |
| GET | /api/v1/files/list?path= |
ein Ordner (Pfad percent-kodiert): {ok, path, parent, writable, free_bytes, total, truncated, entries:[{name, type (dir|file|dirlink|link|other), size, mtime, writable}]}; höchstens 3000 Einträge |
| GET | /api/v1/files/download?path= |
eine Datei als Download (nur gewöhnliche Dateien) |
| GET | /api/v1/files/view?path=&max= |
eine Datei zum Ansehen im Browser (Content-Disposition: inline): ein Bild (PNG, JPG, GIF, WebP, BMP, ICO; bis 16 MB, sonst 413) mit seinem Typ oder der Anfang einer Textdatei als text/plain (max Bytes, Standard 256 KB, höchstens 1 MB; Kopf X-Fm-Size = ganze Größe, X-Fm-Truncated = 1, wenn gekürzt). Binärdateien: 415 not_text. Die Antwort trägt Content-Security-Policy: default-src 'none'; sandbox und nosniff |
| GET | /api/v1/files/size?path= |
Größe einer Datei oder eines Ordners samt allem darunter: {ok, path, bytes, files, folders, partial}. Die Konsole zählt höchstens 8 Sekunden; ein zu großer Ordner kommt mit partial: true und dem bisher Gezählten zurück (untere Grenze). Verknüpfungen werden nicht verfolgt, ein anderes Laufwerk darunter nicht betreten |
| POST | /api/v1/files/upload?path=&name= |
Rohdaten als neue Datei im Ordner path (nie überschreiben; 409 wenn der Name vergeben ist, 403 außerhalb der Laufwerke und /data) |
| POST | /api/v1/files/mkdir |
{path, name}: neuer Ordner |
| POST | /api/v1/files/rename |
{path, name}: neuer Name im selben Ordner |
| POST | /api/v1/files/copy, /api/v1/files/move |
{paths[≤100], dest}: startet den Auftrag; 409 mit conflicts[], wenn Namen im Ziel vergeben sind, oder bei zu wenig Platz |
| POST | /api/v1/files/delete/plan |
{paths}: {items, folders, files, bytes, paths, confirm}; confirm ist das Kennwort (einmal, 10 min, genau diese Liste) |
| POST | /api/v1/files/delete |
{paths, confirm}: startet das Löschen (403 ohne gültiges Kennwort) |
| GET | /api/v1/files/job |
der Auftrag: {state (idle|counting|copying|deleting|done|failed|cancelled), active, kind (copy|move|delete), dest, current, error, note, percent, bytes_total, bytes_done, files_total, files_done, items, items_done, skipped, elapsed_s, finished_ago_s} |
| POST | /api/v1/files/job/cancel |
bricht den laufenden Auftrag ab (409 wenn keiner läuft) |
| GET | /api/v1/library/backups |
die Sicherungen der App: {ok, backups:[{path, name, drive, type, size_bytes, modified, unfinished, sums}]} |
| GET/PUT | /api/v1/games |
Spielprofile (Regeln je Spiel) lesen / schreiben |
| GET | /api/v1/games/export |
Spielprofile als JSON exportieren |
| POST | /api/v1/games/import |
Spielprofile aus JSON importieren |
| POST | /api/v1/profile/username |
Anzeigenamen des Benutzers ändern ({"name":"…"}) |
| GET | /api/v1/profile/avatar/current |
aktuelles Profilbild (PNG) |
| POST | /api/v1/profile/avatar/file?name=avatar.png |
eine Datei des Profilbild-Satzes als Rohdaten in den Zwischenbereich laden (avatar64.dds … avatar440.dds, picture64.dds … picture440.dds, avatar.png, picture.png, online.json) |
| POST | /api/v1/profile/avatar/apply |
Zwischenbereich als Profilbild übernehmen; vor der ersten Übernahme wird das bisherige gesichert |
| POST | /api/v1/profile/avatar/restore |
das gesicherte vorherige Profilbild zurückholen |
Kompression und Sprachen
- Komprimierte Auslieferung. Die Dateien der Oberfläche (HTML, CSS, JS, JSON, SVG) liegen in der App bereits gzip-komprimiert
und gehen so an Browser, deren Anfrage
Accept-Encoding: gzipenthält (Antwort mitContent-Encoding: gzipundVary: Accept-Encoding). Alle anderen bekommen den Text unkomprimiert: Die App entpackt ihn dazu beim Senden. Bilder (PNG, JPG) bleiben unverändert. Die JSON-Antworten der Schnittstelle selbst werden nicht komprimiert. - Wörterbücher.
GET /lang/<xx>.json(en,it,es,fr,ru) liefert das Wörterbuch einer Sprache der Oberfläche:{"v":1,"lang":"xx","t":{"deutscher Text":"Übersetzung", …}}. Texte mit Platzhaltern ({0},{1}, …) stehen mit den Platzhaltern darin. Für Deutsch gibt es kein Wörterbuch; die Seite wählt die Sprache selbst (gemerkte Wahl, sonst Sprache des Browsers, sonst Englisch) und lädt nur das eine Wörterbuch.GET /handbuch.<xx>.htmlund/faq.<xx>.htmlsind Handbuch und FAQ in der Sprache (Deutsch ohne Kürzel:/handbuch.html,/faq.html).
Konfiguration
Konfiguration liegt unter /data/PS5-Cooling-Center/config.json.
Bereiche, die GET /api/v1/config meldet (seit 07.10.2026; die Werte setzt die App, nicht der Client): target_min_c /
target_max_c (Zieltemperatur der Automatik, 60–91 °C), threshold_min_c / threshold_max_c (Lüfterschwelle, 45–91 °C: der
feste Wert der Betriebsart „Beobachten“ und das, was die Regelung einstellen darf) und safety_min_c / safety_max_c
(Notfallgrenze, 72–95 °C; sie liegt immer mindestens 4 °C über dem Ziel und wird beim Speichern dorthin angehoben). Werte
außerhalb werden auf den Bereich begrenzt, nicht abgelehnt.
Neue Konfigurationsfelder:
warning_countdown_s(30-900): Dauer bis Eskalationshinweis bei aktiver Warnlage.telemetry_retention_days(7-365): Aufbewahrung fürhistory.csvundthermal-health.csvbeim Laden.lightbar_enabled(0/1): Prospero-Lights-Status aktiv.lightbar_warn_c/lightbar_hot_c: Schwellwerte für GELB/ROT.fan_reapply_sec(1-300): Reapply-Intervall für die Lüfterschwelle (wichtig, weil die Firmware den Wert bei Spielstarts zurücksetzt).library_cache(0/1, ab Werk 0): „Covers & Metadaten speichern“ auf der Seite Spiele; die Liste legt dann Titelbilder und langsam zu ermittelnde Angaben im Ordner/data/PS5-Cooling-Center/covers_and_moreab und nutzt sie. Teil von Export und Import der Einstellungen.
Probe-Maske (probe_mask) Bits:
0x01(PS5TM_PROBE_GAME): Spielerkennung.0x02(PS5TM_PROBE_PAD): Controller-Akku.0x04(PS5TM_PROBE_NETDISP): Netzwerk und Bildschirm.0x08(PS5TM_PROBE_RISKY): optionale Last-/Takt-/Leistungsabfragen.0x10(PS5TM_PROBE_DRIVE): optionale Laufwerkstelemetrie.0x20(PS5TM_PROBE_FPS): Bilder pro Sekunde.
Zeitlich begrenzte Abfragen („Diagnose 2/5/10 Min."): PUT /api/v1/config mit
probe_mask und probe_revert_after_s (10–900) setzt die Maske sofort, merkt
sich die bisherige und stellt sie nach Ablauf selbst wieder her — auch wenn die
Seite längst geschlossen ist. Auf der Platte steht dabei immer die bisherige
Maske, ein Neustart der App beendet die Diagnose also von selbst. Ein
gewöhnliches Setzen von probe_mask bricht sie ab. GET /api/v1/config meldet
solange probe_revert_in_s und probe_revert_mask.
Einstellungen, die abgelehnt werden (400/409), statt sich unbemerkt auf die
Erreichbarkeit der Oberfläche auszuwirken: http_port nur 1024–65535 und nur,
wenn dort kein anderes Programm lauscht (409 port_in_use); bind_address nur
als IPv4-Adresse.
Hinweise zu einzelnen Endpunkten
Hinweis zu den neuen Endpunkten:
/api/v1/sensors/riskyist bewusst on-demand und nicht Teil des 1-s-Livepfads./api/v1/drivesliefert nur dann Daten, wennPS5TM_PROBE_DRIVEaktiv ist; sonst antwortet der Endpunkt mit409./api/v1/driveslistet Volumes als Telemetrieobjekte mit Typ-Hinweisen (internal_ssd,m2_expansion,usb_storage,block_da) und zeigt, ob eine Temperaturquelle direkt oder nur als Proxy verfügbar ist.
Kopieren und Konvertieren (/api/v1/library/copy, /api/v1/library/convert):
Der Status eines Auftrags (GET) enthält seit 03.10.2026 zusätzlich, weil jedes
Ergebnis nach dem Schreiben vom Laufwerk zurückgelesen und geprüft wird:
- Kopie:
checked_bytes— wie viel der kopierten Bytes schon zurückgelesen und mit dem Original verglichen ist. Fortschritt, Tempo (bytes_per_s) und Restzeit (eta_s) zählen beide Durchgänge zusammen; die Arbeit ist doppelt so groß wietotal_bytes.done_bytessagt weiter nur, wie viel kopiert ist. - Konvertierung: Im Zustand
verifying(das Ergebnis wird zurückgelesen)check_total_bytesundcheck_done_bytes, dazu Tempo und Restzeit dieses Durchgangs. Beiffpkgumfasst die Summe zwei Durchgänge: die Dateiinhalte gegen ihre Prüfsummen, dann die ganze Datei für die SHA-256. sums— Pfad der Prüfsummen-Datei<Ziel>.sha256, sobald sie geschrieben ist (Format vonsha256sum; bei einer Ordner-Kopie je Datei eine Zeile mit dem Pfad ab dem Namen des Zielordners). Fehlt sie, steht der Grund innote.note— etwas, das den Auftrag nicht aufgehalten hat, zum Beispiel dass die Prüfsummen-Datei sich nicht schreiben ließ.- Eine abweichende Datei oder ein Fehler beim Zurücklesen beendet den Auftrag mit
state: "failed"und einer Meldung im Felderror; das Ergebnis und die Prüfsummen-Datei sind dann entfernt.
Controller-Akku in GET /api/v1/status (controller-Objekt):
from_log: truebedeutet: Der Wert stammt aus dem Kernel-Protokoll (last-known), nicht aus einem Live-Poll gegenscePad.restored: truebedeutet: Der Wert wurde nach einem App-Neustart auspad-battery.txtwiederhergestellt und in dieser Laufzeit noch nicht durch einen neuen Log-Eintrag aktualisiert.age_sist die Altersangabe zum Messzeitpunkt und bleibt auch nach Neustart konsistent, weil der Zeitstempel mit gespeichert wird.
Die passive Backend-Diagnose aus /api/v1/controller/diag wird auch auf der
Systemseite unter Controller-Diagnose angezeigt.
Spielzeit-Dateien (playtime.c):
sessions.csv: eine Kopfzeile (# start_s,end_s,play_s,cpu_max,cpu_avg,soc_max,soc_avg,fan_avg,fan_max,flags,title,name), danach eine Zeile je beendeter Sitzung, die älteste zuerst; der Name steht zuletzt und darf Kommas enthalten. Neue Zeilen werden angehängt; wächst die Datei über 450 KB, bleiben die letzten 3000. Zeilen, die sich nicht lesen lassen (auch solche mit unsinnigen Zahlen oder Titeln, wie eine an eine andere geklebte Zeile sie ergibt), und eine noch halb geschriebene letzte Zeile werden übergangen. Vor dem Anhängen endet eine Zeile ohne Zeilenumbruch (Rest eines abgebrochenen Schreibens) auf eigener Zeile; ein abgebrochener Schreibvorgang lässt keine halbe Zeile zurück.session-open.csv: eine Zeile mit dem Stand der laufenden Sitzung (v2,…, mit Beginn, letzter Sichtung, letztem Moment im Vordergrund und der Angabe, ob das Spiel vorn war; älterev1,…-Zeilen werden weiter gelesen), alle 30 Sekunden neu geschrieben (erst in eine.tmp-Datei, dann umbenannt) und beim Ende der Sitzung gelöscht — erst, wenn ihre Zeile insessions.csvsteht. Ein Rest nach einem Absturz oder Ausschalten wird beim nächsten Start fortgeführt (gleicher Titel läuft, zuletzt vor höchstens 180 s gesehen) oder als Sitzung mitflags4 abgeschlossen.
Sicherungen der Spielstände (savebackup.c), je ein Ordner PS5-Sicherung/Spielstaende/<JJJJ-MM-TT_HH-MM-SS>
(beim Stand vor dem Zurückspielen mit dem Zusatz _vor-Zurueckspielen_<Titel-ID>) im Hauptverzeichnis des
Laufwerks (/mnt/usbN, /mnt/extN) oder unter /data (Konsolenspeicher), Ordner 0700, Dateien 0600:
manifest.json:{format: 1, kind, created, app, console, users:[{uid, name}], titles:[{uid, id, platform, name, bytes, files:[{p, s, h}]}], system:[{p, s, h}], files, bytes}.kindistbackupoderundo;consoleModell und maskierte Seriennummer der Konsole, die sie gemacht hat;pder Pfad unter dem Ordner,sdie Größe,hdie SHA-256 (hex). Beim Zurückspielen und Prüfen werden die Pfade einzeln gegen eine Liste erlaubter Orte geprüft (kein.., nurhome/<Benutzer>/(savedata|savedata_prospero|…_meta)/<Titel-ID>/…und die Datenbankdateien); ein anderer Eintrag lässt den Vorgang scheitern, ehe etwas geändert wird.pruefsummen.sha256imsha256sum-Format: Im Ordnersha256sum -c pruefsummen.sha256prüft die Sicherung am PC.home/<Benutzer>/savedata/<CUSA…>/,home/<Benutzer>/savedata_meta/user/<CUSA…>/,home/<Benutzer>/savedata_prospero/<PPSA…>/,home/<Benutzer>/savedata_prospero_meta/user/<PPSA…>/: die Ordner der Konsole unter/user/home/<Benutzer>/, Datei für Datei.system/<Benutzer>/db/user/savedata.dbundsystem/<Benutzer>/game_setting.dat(aus/system_data/savedata/<Benutzer>/) gibt es nur bei einer Sicherung, nicht beim Stand vor dem Zurückspielen, und sie werden nie zurückgespielt..ps5cc-unfertig: die Marke, solange die Sicherung geschrieben wird. Eine Sicherung mit ihr wird weder aufgelistet noch geprüft noch zurückgespielt; bricht der Vorgang ab, wird der ganze Ordner entfernt.- Beim Zurückspielen entsteht zuerst für jede Datei
<Name>.ps5cc-neuneben der alten, geprüft gegen die Sicherung; erst wenn alle da sind, werden sie umbenannt. Reste eines abgebrochenen Laufs räumt der nächste Lauf ab. Liste eines Titels mit mehreren Einträgen intitles(derselbe Benutzer und dieselbe Titel-ID) werden zusammengefasst; eine Datei, die doppelt genannt wird, lässt den Vorgang scheitern, ehe etwas geändert wird.
Langzeitdatei thermal-health.csv:
- Das Format wurde um eine sechste Spalte erweitert:
sum_activity(Anzahl foreground-aktiver Samples). - Alte fünfspaltige Dateien bleiben kompatibel und werden weiterhin eingelesen.
- Die Wochenauswertung bevorzugt Wochen mit nennenswerter Aktivität, fällt bei zu wenig Daten aber automatisch auf die klassische Auswertung zurück.