Messaggi Server → Client

Formato dei messaggi

Ogni messaggio è un oggetto JSON con una sola chiave di primo livello. Questa chiave codifica il tipo di evento e può includere una descrizione leggibile separata da un trattino:

"aa-dump all data"   →  tipo evento = primi 2 caratteri = "aa"
"ea"                 →  tipo evento = "ea"
"d"                  →  tipo evento = "d" (carattere unico)

I client devono confrontare i primi 1 o 2 caratteri della chiave, non l’intera stringa, poiché la parte descrittiva può cambiare.

Tutte le chiavi degli eventi inviate dal server sono in minuscolo (es. d, ea, ap, gc).


Indice dei tipi di evento

ChiaveDescrizione
dDump iniziale completo (risposta a DU)
aaDump completo di un modulo (modulo caricato/ricaricato)
apSostituzione completa di una proprietà
eaAggiornamento di tutti i valori degli elementi di una proprietà
eeAggiornamento di un singolo valore di elemento
evAggiornamento di un valore di elemento con i suoi vincoli
elLOV locale dell’elemento modificata
psAggiornamento dello stato e dell’abilitazione di una proprietà
dmModulo eliminato
dpProprietà eliminata
gcRiga di griglia creata
guRiga di griglia aggiornata
gdRiga di griglia eliminata
grReset della griglia (tutte le righe eliminate)
lcLOV creato o fuso
luLOV sostituito
ldLOV eliminato
fsProfilo salvato
flProfilo caricato
fcProfilo modificato (modifiche non salvate)
lVoce di log
ucAggiornamento dei dati del controller
afFile aggiunto
dfFile eliminato
adCartella aggiunta
ddCartella eliminata
qaRisposta a una richiesta di modulo (meccanismo inter-modulo, non destinato al client)
xxPong keepalive

d — Dump iniziale completo

Inviato in risposta a una richiesta DU. Contiene tutto: tutti i moduli, i log, gli elenchi di file e i dati del controller. Il dettaglio delle chiavi di controllerdata e di files è in Controller, GlobalDatastore e file; l’esempio seguente ne mostra solo alcune.

{
  "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": {} }
    }
  }
}
Abbreviazioni del formato wire

m = modules, p = properties, e = elements, l = globallovs, f = profile. Normalizzare queste abbreviazioni ai loro nomi completi durante la memorizzazione interna.


aa — Dump completo di un modulo (modulo caricato/ricaricato)

Inviato quando un modulo viene caricato o ricaricato a runtime. Contiene lo stato completo del modulo. La chiave inizia con "aa".

{
  "aa-dump all data": {
    "Guider": {
      "infos": { "modulelabel": "Guider", "description": "..." },
      "f": { "name": "default", "changed": false },
      "l": {},
      "p": {
        "status": { ... }
      }
    }
  }
}

ap — Sostituzione completa di una proprietà

Sostituisce interamente una o più proprietà. La chiave inizia con "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 — Aggiornamento di tutti i valori degli elementi (livello proprietà)

Il messaggio di aggiornamento più comune. Invia i valori correnti di tutti gli elementi di una proprietà. Contiene solo i valori — senza metadati. La chiave è esattamente "ea".

{
  "ea": {
    "Allsky": {
      "p": {
        "coming": {
          "e": {
            "sunrise": { "hh": 7, "mm": 6, "ss": 51 },
            "sunset":  { "hh": 21, "mm": 15, "ss": 1 }
          }
        }
      }
    }
  }
}

Per i tipi semplici (int, float, bool, string, light), il valore è uno scalare:

{
  "ea": {
    "Focus": {
      "p": {
        "parameters": {
          "e": {
            "iterations": 5,
            "exposure": 3.5,
            "active": true
          }
        }
      }
    }
  }
}

ee — Aggiornamento di un singolo valore di elemento

Aggiorna il valore di un singolo elemento. Stesso formato di ea ma per un solo elemento. La chiave è esattamente "ee".

{
  "ee": {
    "Focus": {
      "p": {
        "parameters": {
          "e": {
            "iterations": 7
          }
        }
      }
    }
  }
}
ee è solo di origine backend

ee viene inviato solo per iniziativa del backend stesso (es. un cambio di valore proveniente da un device, un polling interno) — mai come risposta diretta a una scrittura del client. Qualsiasi risposta a un SV o SA avviato dal client è sempre un ea dell’intera proprietà, indipendentemente dal numero di elementi effettivamente cambiati.


ev — Aggiornamento di un elemento con metadati

Aggiorna il valore di un elemento e i suoi vincoli (min, max, format). La chiave inizia con "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 — LOV locale modificata

Inviato quando la lista di valori locale (listOfValues) di un elemento viene aggiunta, aggiornata o svuotata per iniziativa del server stesso — ad es. i nomi degli slot di una ruota portafiltri (ri)letti dal device. La chiave inizia con "el". Stesso formato di payload di ev (valore corrente, vincoli e listOfValues sono tutti inclusi), ma a differenza di ev questo evento non marca mai come modificato il profilo di una proprietà hasprofile (fc): una LOV locale è decorativa, non un valore di profilo memorizzato.

{
  "el-element's own local lov changed": {
    "Sequencer": {
      "p": {
        "sequence": {
          "e": {
            "filter": {
              "value": 1,
              "listOfValues": { "1": "Luminance", "2": "Red", "3": "Green", "4": "Blue" }
            }
          }
        }
      }
    }
  }
}

ps — Aggiornamento dello stato di una proprietà

Aggiorna solo i campi status e enabled di una proprietà. La chiave inizia con "ps".

{
  "ps-only property state": {
    "Focus": {
      "p": {
        "autofocus": {
          "status": 2,
          "enabled": true
        }
      }
    }
  }
}

Valori di stato: 0 Standby · 1 OK · 2 Occupato · 3 Errore


dm — Modulo eliminato

Inviato quando un modulo viene scaricato. Il client deve eliminare tutti i dati di questo modulo. La chiave inizia con "dm".

{
  "dm-delete/remove module": {
    "Focus": {}
  }
}

dp — Proprietà eliminata

Inviato quando una proprietà viene rimossa da un modulo. La chiave inizia con "dp".

{
  "dp-delete/remove property": {
    "Focus": {
      "p": {
        "oldProperty": ""
      }
    }
  }
}

gc — Riga di griglia creata

Inviato dopo l’aggiunta di una nuova riga in una proprietà di tipo griglia. La chiave inizia con "gc".

{
  "gc-grid new line ": {
    "Sequencer": {
      "p": {
        "sequence": {
          "i": 3,
          "values": {
            "target": "M31",
            "exposure": 120,
            "count": 10
          }
        }
      }
    }
  }
}

i è l’indice della riga appena creata. values è un oggetto indicizzato per nome elemento.


gu — Riga di griglia aggiornata

Inviato quando una riga esistente della griglia viene modificata. La chiave inizia con "gu".

{
  "gu-grid update line": {
    "Sequencer": {
      "p": {
        "sequence": {
          "i": 1,
          "values": {
            "target": "M42",
            "exposure": 60,
            "count": 20
          }
        }
      }
    }
  }
}

gd — Riga di griglia eliminata

Inviato quando una riga della griglia viene rimossa. La chiave inizia con "gd".

{
  "gd-grid delete line": {
    "Sequencer": {
      "p": {
        "sequence": {
          "i": 0
        }
      }
    }
  }
}

i è l’indice (base zero) della riga eliminata. Le righe successive si spostano di una posizione verso l’alto.


gr — Reset della griglia

Elimina l’intera griglia di una proprietà. La chiave inizia con "gr".

{
  "gr-grid reset": {
    "Sequencer": {
      "p": {
        "sequence": {}
      }
    }
  }
}

lc / lu / ld — Eventi LOV

lc — LOV creato/fuso (chiave inizia con "lc"):

LOV di modulo:

{
  "lc-lov create": {
    "Focus": {
      "l": {
        "myLov": {
          "label": "My LOV",
          "type": "string",
          "values": { "a": "Option A", "b": "Option B" }
        }
      }
    }
  }
}

LOV del controller (senza involucro modulo, usa la chiave lovs):

{
  "lc-lov create": {
    "lovs": {
      "sharedLov": {
        "label": "Shared LOV",
        "type": "string",
        "values": { "x": "Value X" }
      }
    }
  }
}

lu — LOV sostituito (stesso formato di lc, sostituzione completa).

ld — LOV eliminato (chiave inizia con "ld"):

{
  "ld-lov delete": {
    "lovs": {
      "sharedLov": {}
    }
  }
}

fs / fl / fc — Eventi di profilo

Inviati quando un profilo viene salvato, caricato o modificato.

{
  "fs-profile saved": {
    "Focus": {
      "f": { "name": "myProfile", "changed": false }
    }
  }
}
Prefisso chiaveEvento
fsProfilo salvato
flProfilo caricato
fcProfilo con modifiche non salvate

l — Voce di log

Inviato per ogni messaggio di log generato dal server. La chiave è esattamente "l".

{
  "l": {
    "d": "2024-01-01T12:00:00.000",
    "c": "Focus",
    "t": "Autofocus completed successfully",
    "l": 1
  }
}
CampoDescrizione
dData/ora ISO 8601 con millisecondi
cContesto/fonte (nome del modulo o "WS")
tTesto del messaggio (tradotto nella lingua del client)
lLivello: 0 Debug · 1 Info · 2 Avviso · 3 Errore · 4 Critico

uc — Aggiornamento dei dati del controller

Inviato quando i dati globali del controller cambiano: profili, configurazioni, driver INDI attivi, elenchi di file (files, folders), carico del sistema (systemwatcher, ogni 10 s per impostazione predefinita). La chiave inizia con "uc". Le chiavi possibili sono descritte in Controller, GlobalDatastore e file.

{
  "uc-update controller data": {
    "profiles": {
      "Focus": ["default", "highres"],
      "Guider": ["default"]
    }
  }
}

Il payload è {"chiave": valore} dove valore può essere una stringa, un array o un oggetto. Ogni messaggio porta una sola chiave e il suo valore sostituisce interamente quello precedente.


af / df / ad / dd — Eventi di file e cartella

Inviato a tutti i client quando il contenuto della cartella di file sorvegliata cambia (vedi File system). A differenza degli altri messaggi, il valore è una stringa nuda: il percorso interessato, non racchiuso in un oggetto o array — il server segnala sempre un solo percorso per messaggio.

{ "af": "/Allsky/image_001.jpeg" }
{ "df": "/Allsky/old_image.jpeg" }
ChiaveSignificato
afFile aggiunto alla cartella selezionata
dfFile eliminato dalla cartella selezionata
adSottocartella aggiunta ovunque nel webroot
ddSottocartella eliminata ovunque nel webroot

af/df riguardano solo la cartella attualmente selezionata tramite FS — non viene segnalato nulla per il contenuto delle altre cartelle. ad/dd sono globali: si attivano per l’intero albero del webroot, indipendentemente da cosa è attualmente selezionato. Vedi File system per il quadro completo.


qa — Risposta a una richiesta di modulo

Comunicazione inter-modulo, non una funzionalità client

Vedi la nota su QY: questo meccanismo esiste principalmente perché un modulo ne interroghi un altro internamente. Documentato qui per completezza, non come funzionalità destinata al client.

Risposta a una richiesta QY. QY/qa è un meccanismo generico di richiesta/risposta specifico per modulo: un client (o un altro modulo, internamente) pone a un modulo una domanda nominata con parametri, e riceve indietro una risposta nominata. Quali nomi di richiesta un modulo comprenda realmente, e la forma della sua risposta, dipende interamente da quel modulo — il protocollo definisce solo l’involucro, non il contenuto.

{
  "qa-query answer": {
    "Sequencer": {
      "q": {
        "query": "profileduration",
        "result": { "seconds": 3600 }
      }
    }
  }
}

result è ciò che il modulo ha restituito per quella richiesta — la sua forma dipende interamente da query. Un modulo senza un caso corrispondente al nome query richiesto restituisce silenziosamente un result vuoto.

Ancora poco da vedere

Oggi solo il modulo Sequencer implementa una vera risposta (profileduration), usata internamente dal modulo Planner piuttosto che da un qualsiasi flusso client documentato. Nessun altro modulo distribuito risponde in modo significativo a nessun nome di richiesta per ora — il meccanismo esiste ed è completamente cablato, ma c’è ancora poco da interrogare in pratica.


xx — Pong keepalive

Inviato dal server in risposta a un heartbeat client (XX). Nessun payload utile; i client possono ignorarlo.

{ "xx": {} }