Nachrichten Server → Client
Nachrichtenformat
Jede Nachricht ist ein JSON-Objekt mit genau einem Schlüssel der obersten Ebene. Dieser Schlüssel kodiert den Ereignistyp und kann eine lesbare, durch einen Bindestrich getrennte Beschreibung enthalten:
"aa-dump all data" → Ereignistyp = erste 2 Zeichen = "aa"
"ea" → Ereignistyp = "ea"
"d" → Ereignistyp = "d" (einzelnes Zeichen)Clients müssen die ersten 1 oder 2 Zeichen des Schlüssels abgleichen, nicht die vollständige Zeichenkette, da sich der Beschreibungsteil ändern kann.
Alle vom Server gesendeten Ereignisschlüssel sind klein geschrieben (z. B. d, ea, ap, gc).
Übersicht der Ereignistypen
| Schlüssel | Beschreibung |
|---|---|
d | Vollständiger initialer Dump (Antwort auf DU) |
aa | Vollständiger Dump eines Moduls (Modul geladen/neu geladen) |
ap | Vollständiger Ersatz einer Property |
ea | Update aller Elementwerte einer Property |
ee | Update eines einzelnen Elementwerts |
ev | Update eines Elementwerts mit seinen Einschränkungen |
el | Lokale LOV eines Elements geändert |
ps | Update von Status und Enabled-Zustand einer Property |
dm | Modul gelöscht |
dp | Property gelöscht |
gc | Grid-Zeile erstellt |
gu | Grid-Zeile aktualisiert |
gd | Grid-Zeile gelöscht |
gr | Grid-Reset (alle Zeilen gelöscht) |
lc | LOV erstellt oder zusammengeführt |
lu | LOV ersetzt |
ld | LOV gelöscht |
fs | Profil gespeichert |
fl | Profil geladen |
fc | Profil geändert (nicht gespeicherte Änderungen) |
l | Log-Eintrag |
uc | Update der Controller-Daten |
af | Datei hinzugefügt |
df | Datei gelöscht |
ad | Verzeichnis hinzugefügt |
dd | Verzeichnis gelöscht |
qa | Antwort auf eine Modul-Anfrage (Inter-Modul-Mechanismus, nicht für Clients gedacht) |
xx | Keepalive-Pong |
d — Vollständiger initialer Dump
Wird als Antwort auf eine DU-Anfrage gesendet. Enthält alles: alle Module, Logs, Dateilisten und Controller-Daten. Die Details der Schlüssel von controllerdata und files stehen in Controller, GlobalDatastore und Dateien; das Beispiel unten zeigt nur einige davon.
{
"d": {
"grant-client": "1",
"grant-server": "0",
"serverlng": "en",
"m": {
"Focus": {
"infos": { "modulelabel": "Focus", "description": "..." },
"f": { "name": "default", "changed": false },
"l": {
"myLov": { "label": "My LOV", "type": "string", "values": { "a": "Option A" } }
},
"p": {
"parameters": {
"label": "Parameters",
"order": "10",
"level1": "Focus",
"level2": "Config",
"status": 0,
"permission": 2,
"enabled": true,
"showElts": true,
"hasGrid": false,
"hasGraph": false,
"rule": 0,
"badge": false,
"preicon1": "", "preicon2": "", "posticon1": "", "posticon2": "",
"hasprofile": true,
"freevalue": "",
"e": {
"iterations": {
"type": "int",
"label": "Iterations",
"order": "10",
"hint": "",
"autoupdate": false,
"badge": false,
"directedit": false,
"value": 5,
"min": 1,
"max": 20,
"step": 1,
"format": "",
"slider": 0
}
}
}
}
}
},
"files": {
"folders": ["", "/Allsky", "/Allsky/archives"],
"files": ["/image.jpeg"],
"selectedfolder": "/home/user/ostmedia"
},
"logs": [
{ "d": "2024-01-01T12:00:00.000", "c": "Focus", "t": "Module loaded", "l": 1 }
],
"controllerdata": {
"profiles": {
"Focus": ["default", "test"]
},
"currentconf": "default"
},
"lovs": {
"sharedLov": { "label": "Shared LOV", "type": "string", "values": {} }
}
}
}m = modules, p = properties, e = elements, l = globallovs, f = profile.
Diese Abkürzungen bei der internen Speicherung auf ihre vollständigen Namen normalisieren.
aa — Vollständiger Dump eines Moduls (Modul geladen/neu geladen)
Wird gesendet, wenn ein Modul zur Laufzeit geladen oder neu geladen wird. Enthält den vollständigen Zustand des Moduls. Der Schlüssel beginnt mit "aa".
{
"aa-dump all data": {
"Guider": {
"infos": { "modulelabel": "Guider", "description": "..." },
"f": { "name": "default", "changed": false },
"l": {},
"p": {
"status": { ... }
}
}
}
}ap — Vollständiger Ersatz einer Property
Ersetzt eine oder mehrere Properties vollständig. Der Schlüssel beginnt mit "ap".
{
"ap-dump all property data": {
"Focus": {
"p": {
"parameters": {
"label": "Parameters",
"status": 0,
"permission": 2,
"enabled": true,
"showElts": true,
"hasGrid": false,
"hasGraph": false,
"rule": 0,
"e": {
"iterations": {
"type": "int",
"value": 7,
"min": 1, "max": 20, "step": 1,
"label": "Iterations", "order": "10", "hint": "",
"autoupdate": false, "badge": false, "directedit": false,
"format": "", "slider": 0
}
}
}
}
}
}
}ea — Update aller Elementwerte (Property-Ebene)
Die häufigste Update-Nachricht. Sendet die aktuellen Werte aller Elemente einer Property. Enthält ausschließlich Werte — keine Metadaten. Der Schlüssel ist genau "ea".
{
"ea": {
"Allsky": {
"p": {
"coming": {
"e": {
"sunrise": { "hh": 7, "mm": 6, "ss": 51 },
"sunset": { "hh": 21, "mm": 15, "ss": 1 }
}
}
}
}
}
}Bei einfachen Typen (int, float, bool, string, light) ist der Wert ein Skalar:
{
"ea": {
"Focus": {
"p": {
"parameters": {
"e": {
"iterations": 5,
"exposure": 3.5,
"active": true
}
}
}
}
}
}ee — Update eines einzelnen Elementwerts
Aktualisiert den Wert eines einzelnen Elements. Gleiches Format wie ea, aber für ein einzelnes Element. Der Schlüssel ist genau "ee".
{
"ee": {
"Focus": {
"p": {
"parameters": {
"e": {
"iterations": 7
}
}
}
}
}
}ee kommt nur vom Backend ausee wird ausschließlich auf Initiative des Backends selbst gesendet (z. B. eine geräteseitige Wertänderung, internes Polling) — nie als direkte Antwort auf einen Client-Schreibvorgang. Jede Antwort auf ein clientseitig ausgelöstes SV oder SA ist immer ein ea der gesamten Property, unabhängig davon, wie viele Elemente sich tatsächlich geändert haben.
ev — Update eines Elements mit Metadaten
Aktualisiert den Wert eines Elements sowie seine Einschränkungen (min, max, format). Der Schlüssel beginnt mit "ev".
{
"ev-set one element value/min/max/format ": {
"Focus": {
"p": {
"parameters": {
"e": {
"temperature": {
"value": 12.5,
"min": -40.0,
"max": 80.0,
"format": "%.1f"
}
}
}
}
}
}
}el — Lokale LOV geändert
Wird gesendet, wenn die eigene lokale Liste von Werten (listOfValues) eines Elements auf Initiative des Servers hinzugefügt, aktualisiert oder gelöscht wird — z. B. wenn die Filterrad-Slotnamen (neu) vom Gerät gelesen werden. Der Schlüssel beginnt mit "el". Gleiches Payload-Format wie ev (aktueller Wert, Einschränkungen und listOfValues sind alle enthalten), aber im Gegensatz zu ev markiert dies niemals das Profil einer hasprofile-Property als geändert (fc): eine lokale LOV ist dekorativ, kein gespeicherter Profilwert.
{
"el-element's own local lov changed": {
"Sequencer": {
"p": {
"sequence": {
"e": {
"filter": {
"value": 1,
"listOfValues": { "1": "Luminance", "2": "Red", "3": "Green", "4": "Blue" }
}
}
}
}
}
}
}ps — Update des Status einer Property
Aktualisiert ausschließlich die Felder status und enabled einer Property. Der Schlüssel beginnt mit "ps".
{
"ps-only property state": {
"Focus": {
"p": {
"autofocus": {
"status": 2,
"enabled": true
}
}
}
}
}Statuswerte: 0 Ruhe · 1 OK · 2 Beschäftigt · 3 Fehler
dm — Modul gelöscht
Wird gesendet, wenn ein Modul entladen wird. Der Client muss alle Daten dieses Moduls entfernen. Der Schlüssel beginnt mit "dm".
{
"dm-delete/remove module": {
"Focus": {}
}
}dp — Property gelöscht
Wird gesendet, wenn eine Property aus einem Modul entfernt wird. Der Schlüssel beginnt mit "dp".
{
"dp-delete/remove property": {
"Focus": {
"p": {
"oldProperty": ""
}
}
}
}gc — Grid-Zeile erstellt
Wird gesendet, nachdem eine neue Zeile in einer Grid-Property hinzugefügt wurde. Der Schlüssel beginnt mit "gc".
{
"gc-grid new line ": {
"Sequencer": {
"p": {
"sequence": {
"i": 3,
"values": {
"target": "M31",
"exposure": 120,
"count": 10
}
}
}
}
}
}i ist der Index der neu erstellten Zeile. values ist ein Objekt, indexiert nach Elementname.
gu — Grid-Zeile aktualisiert
Wird gesendet, wenn eine bestehende Grid-Zeile geändert wird. Der Schlüssel beginnt mit "gu".
{
"gu-grid update line": {
"Sequencer": {
"p": {
"sequence": {
"i": 1,
"values": {
"target": "M42",
"exposure": 60,
"count": 20
}
}
}
}
}
}gd — Grid-Zeile gelöscht
Wird gesendet, wenn eine Grid-Zeile entfernt wird. Der Schlüssel beginnt mit "gd".
{
"gd-grid delete line": {
"Sequencer": {
"p": {
"sequence": {
"i": 0
}
}
}
}
}i ist der (nullbasierte) Index der gelöschten Zeile. Nachfolgende Zeilen rücken um eine Position vor.
gr — Grid-Reset
Löscht die gesamte Grid einer Property. Der Schlüssel beginnt mit "gr".
{
"gr-grid reset": {
"Sequencer": {
"p": {
"sequence": {}
}
}
}
}lc / lu / ld — LOV-Ereignisse
lc — LOV erstellt/zusammengeführt (Schlüssel beginnt mit "lc"):
Modul-LOV:
{
"lc-lov create": {
"Focus": {
"l": {
"myLov": {
"label": "My LOV",
"type": "string",
"values": { "a": "Option A", "b": "Option B" }
}
}
}
}
}Controller-LOV (ohne Modul-Struktur, verwendet den Schlüssel lovs):
{
"lc-lov create": {
"lovs": {
"sharedLov": {
"label": "Shared LOV",
"type": "string",
"values": { "x": "Value X" }
}
}
}
}lu — LOV ersetzt (gleiches Format wie lc, vollständiger Ersatz).
ld — LOV gelöscht (Schlüssel beginnt mit "ld"):
{
"ld-lov delete": {
"lovs": {
"sharedLov": {}
}
}
}fs / fl / fc — Profil-Ereignisse
Werden gesendet, wenn ein Profil gespeichert, geladen oder geändert wird.
{
"fs-profile saved": {
"Focus": {
"f": { "name": "myProfile", "changed": false }
}
}
}| Schlüsselpräfix | Ereignis |
|---|---|
fs | Profil gespeichert |
fl | Profil geladen |
fc | Profil mit nicht gespeicherten Änderungen |
l — Log-Eintrag
Wird für jede vom Server erzeugte Log-Nachricht gesendet. Der Schlüssel ist genau "l".
{
"l": {
"d": "2024-01-01T12:00:00.000",
"c": "Focus",
"t": "Autofocus completed successfully",
"l": 1
}
}| Feld | Beschreibung |
|---|---|
d | ISO-8601-Datum/Uhrzeit mit Millisekunden |
c | Kontext/Quelle (Modulname oder "WS") |
t | Nachrichtentext (übersetzt in die Sprache des Clients) |
l | Stufe: 0 Debug · 1 Info · 2 Warnung · 3 Fehler · 4 Kritisch |
uc — Update der Controller-Daten
Wird gesendet, wenn sich globale Controller-Daten ändern: Profile, Konfigurationen, aktive INDI-Treiber, Dateilisten (files, folders), Systemlast (systemwatcher, standardmäßig alle 10 s). Der Schlüssel beginnt mit "uc". Die möglichen Schlüssel sind in Controller, GlobalDatastore und Dateien beschrieben.
{
"uc-update controller data": {
"profiles": {
"Focus": ["default", "highres"],
"Guider": ["default"]
}
}
}Der Payload ist {"Schlüssel": Wert}, wobei Wert eine Zeichenkette, ein Array oder ein Objekt sein kann. Jede Nachricht trägt einen einzigen Schlüssel, und ihr Wert ersetzt den alten vollständig.
af / df / ad / dd — Datei- und Ordnerereignisse
Wird an alle Clients gesendet, wenn sich der Inhalt des überwachten Dateiordners ändert (siehe Dateisystem). Anders als bei anderen Nachrichten ist der Wert eine reine Zeichenkette: der betroffene Pfad, nicht in ein Objekt oder Array verpackt — der Server meldet immer nur einen Pfad pro Nachricht.
{ "af": "/Allsky/image_001.jpeg" }
{ "df": "/Allsky/old_image.jpeg" }| Schlüssel | Bedeutung |
|---|---|
af | Datei zum ausgewählten Ordner hinzugefügt |
df | Datei aus dem ausgewählten Ordner entfernt |
ad | Unterordner irgendwo im Webroot hinzugefügt |
dd | Unterordner irgendwo im Webroot entfernt |
af/df betreffen nur den aktuell über FS ausgewählten Ordner — für den Inhalt anderer Ordner wird nichts gemeldet. ad/dd sind global: sie lösen für den gesamten Webroot-Baum aus, unabhängig von der aktuellen Auswahl. Siehe Dateisystem für das Gesamtbild.
qa — Antwort auf eine Modul-Anfrage
Siehe den Hinweis zu QY: dieser Mechanismus existiert in erster Linie dafür, dass ein Modul ein anderes intern abfragt. Hier der Vollständigkeit halber dokumentiert, nicht als Client-Funktion.
Antwort auf eine QY-Anfrage. QY/qa ist ein generischer, pro Modul definierter Anfrage-/Antwort-Mechanismus: ein Client (oder intern ein anderes Modul) stellt einem Modul eine benannte Frage mit Parametern und erhält eine benannte Antwort zurück. Welche Anfragenamen ein Modul tatsächlich versteht und wie seine Antwort aussieht, entscheidet allein das Modul — das Protokoll definiert nur die Hülle, nicht den Inhalt.
{
"qa-query answer": {
"Sequencer": {
"q": {
"query": "profileduration",
"result": { "seconds": 3600 }
}
}
}
}result ist das, was das Modul für diese Anfrage zurückgegeben hat — seine Form hängt vollständig von query ab. Ein Modul ohne passenden Fall für den angefragten query-Namen liefert stillschweigend ein leeres result.
Heute implementiert nur das Modul Sequencer eine echte Antwort (profileduration), intern genutzt vom Planner-Modul statt von einem dokumentierten Client-Workflow. Kein anderes ausgeliefertes Modul antwortet bislang sinnvoll auf irgendeinen Anfragenamen — der Mechanismus existiert und ist vollständig verdrahtet, aber es gibt derzeit praktisch wenig abzufragen.
xx — Keepalive-Pong
Wird vom Server als Antwort auf einen Client-Heartbeat (XX) gesendet. Kein nützlicher Payload; Clients können ihn ignorieren.
{ "xx": {} }