{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://git.octoturge.com/Continuum/continuum-schemas/raw/branch/main/schemas/continuum/v1/app/telemetry_message.schema.json", "title": "AppTelemetryMessage", "description": "What continuum-backend pushes down /ws/telemetry to an operator console. Discriminated on 'type'. NOTE the casing: camelCase, unlike continuum/v1/edge/ and every other schema here, because this is the backend's own HTTP vocabulary rather than a format shared with the Rust gateway - the browser already consumes camelCase from GET /printers and should not have to hold two models of a printer. A previous frontend invented its own shape against nothing (printerId, nozzleTempC, progressPct, a closed state enum) and no backend ever sent it; this file exists so both ends have something to mirror.", "oneOf": [ { "type": "object", "title": "PrinterTelemetryPush", "description": "One printer's current state, sent whenever its gateway reports a change. The payload is deliberately the same shape GET /printers/:id returns, so a client can apply it to the row it already has rather than reconciling two vocabularies. Only printers in an organisation the authenticated user belongs to are ever sent.", "properties": { "type": { "const": "printer.telemetry" }, "printer": { "$ref": "#/$defs/PrinterState" } }, "required": ["type", "printer"], "additionalProperties": false }, { "type": "object", "title": "Ready", "description": "Sent once, immediately after the socket authenticates, naming how many printers the user can see. Worth its own message rather than leaving the client to infer readiness from silence: an operator with no printers claimed and an operator whose gateway is offline both see nothing arrive, and those need different things said to them.", "properties": { "type": { "const": "ready" }, "visiblePrinters": { "type": "integer", "minimum": 0 } }, "required": ["type", "visiblePrinters"], "additionalProperties": false } ], "$defs": { "PrinterState": { "type": "object", "description": "A printer as the console displays it. Every telemetry field is nullable because a printer that has never reported has no temperature, and 'no data yet' is not 0 degrees.", "properties": { "id": { "type": "string", "format": "uuid" }, "farmId": { "type": "string", "format": "uuid" }, "name": { "type": "string" }, "vendor": { "type": "string" }, "status": { "type": ["string", "null"], "description": "The backend's own narrowed status, which the UI filters and groups on." }, "vendorState": { "type": ["string", "null"], "description": "The printer's own word for what it is doing - a Bambu's 'RUNNING', 'PREPARE', 'FINISH'. Kept alongside 'status' rather than replaced by it, because the narrowed enum necessarily loses detail an operator sometimes needs. Not an enum here on purpose: an unrecognised state must reach the screen as itself rather than being dropped." }, "vendorErrorCode": { "type": ["integer", "null"] }, "nozzleTempC": { "type": ["number", "null"] }, "nozzleTargetTempC": { "type": ["number", "null"] }, "bedTempC": { "type": ["number", "null"] }, "bedTargetTempC": { "type": ["number", "null"] }, "progressPercent": { "type": ["integer", "null"] }, "currentLayer": { "type": ["integer", "null"] }, "totalLayers": { "type": ["integer", "null"] }, "remainingMinutes": { "type": ["integer", "null"] }, "currentJobName": { "type": ["string", "null"] }, "activeAlerts": { "type": ["integer", "null"], "description": "How many Health-Management-System entries the printer currently has active. A count, not messages: decoding them needs Bambu's HMS tables, which Continuum does not have." }, "cameraStream": { "type": ["string", "null"], "description": "The go2rtc stream name, when this printer has a camera that can actually be restreamed. Null is the common case - only Bambu's X1/H2 class publishes an RTSP URL. Present means it is worth calling GET /printers/:id/stream; null means render no player." }, "cameraSnapshot": { "type": "boolean", "description": "True when the camera can only be read as refreshing JPEG frames (Bambu P1/A1); GET /printers/:id/stream then answers kind 'snapshot'." }, "lastSeenAt": { "type": ["string", "null"], "format": "date-time", "description": "When a gateway last reported this printer. Null means never. This is how a client tells 'idle' from 'nobody has heard from it in an hour', which the status alone cannot say." } }, "required": ["id", "farmId", "name", "vendor"] } } }