Stellar ControlMission control · by Stellar Systems v0.1.0

Operations

Continuous Streams

Payload streams carried and archived without decoding, and the measures of their quality.

A continuous stream is payload data that flows without interruption — imaging, video, instrument data — which the MCS carries and archives but never decodes. The gateway publishes the stream in segments, JetStream archives them, and downstream chains subscribed to the stream process the content. The MCS measures the quality of each stream (rate, bytes, lost segments) as ordinary measures, so that procedures and alarms can use them.

Declaring a stream#

Streams are declared in the catalogue by the standard stream component: one identifier and a nominal rate per stream. Its instances are the streams (enum stream.stream_id). A stream is started and stopped by ordinary telecommands of this component, addressed to the stream:

YAML
components:
  stream:
    streams:
      camera: {rate: 256 kbit/s}
    telecommands:
      start_stream:
        verify: [echo]
      stop_stream:
        verify: [echo]
    alarms:
      stream_gap:
        severity: warning
        when: delta(gaps, 30 s) > 0
text
step "Start the camera"
  uses sat: platform-v3
  send start_stream to sat.stream[camera]
  expect sat.stream[camera].rate > 0 within 30 s

The stream component declares neither instances nor measures: both are generated. See Files and Streams.

Carrying the segments#

The gateway publishes each segment raw on stellar.stream.<target>.<stream_id>, with two headers:

HeaderMeaning
Stellar-Ground-TimeGround reception time (RFC 3339)
Stellar-Stream-SeqSegment number, from 1, consecutive as long as nothing is lost

In the SDKs, a gateway calls publish_segment(target, stream, seq, segment, ground_time), in Rust (Downlink::publish_segment) as in Python. Its NATS credentials allow it to publish the streams of its targets only. See Writing a Gateway.

The archive#

The JetStream stream STREAMS archives every segment. Its retention is set in the global configuration:

YAML
archive:
  streams:
    max_age: 30d
    max_bytes: 2TB

The first limit reached applies; the oldest segments go first. The reconciler applies the retention when it starts. JetStream reserves max_bytes on the disk of the server: when it cannot, the archive is bounded by max_age only, and the reconciler logs a warning.

Quality of a stream#

The transfer manager measures each stream on the segments it receives, and publishes three measures of the stream component every second, per stream:

MeasureMeaning
stream[camera].rateThroughput in bit/s over the last 5 seconds
stream[camera].bytesBytes received
stream[camera].gapsSegments lost, counted from the jumps of Stellar-Stream-Seq

A sequence number that goes back is a restart of the numbering, not a gap. When a stream stops, a rate of 0 is published once.

These measures are published as raw values on stellar.tm.decoded.<target>, like those of a driver: the compute stage, the current value table, the procedures and the alarms treat them as any measure. They are measures of the platform, not of the drivers: they do not count in the coverage a driver must declare.

The catalogue can declare derived measures and alarms on them, as stream_gap above, which raises a warning as soon as a segment was lost in the last 30 seconds.

Shell
stellar watch sat1-fm 'stream[camera].rate' 'stream[camera].gaps'

Simulated streams#

The simulator produces the segments of a stream on board at its nominal rate, once a telecommand marked stream: start is sent to it, until one marked stream: stop. Outside a pass, the segments are lost. Its stream_gap verb ({stream, segments}) drops the next segments of a stream, to exercise the gaps measure and its alarms:

Shell
nats request stellar.ctl.rpc.gateway.sim-gw-1.stream_gap '{"stream": "camera", "segments": 5}'

See also#

Stellar Control · v0.1.0

↑↓ to moveEnter to open