SatYAML Format
SatYAML files describe satellites to gr-satellites. Each file says how the satellite is named, which transmitters it has, how each one is modulated and framed, and what to do with the decoded data. The gr_satellites tool and the Satellite decoder block read these files to assemble a decoder automatically. This page is the complete reference for the format, including the fields the code reads that the upstream documentation does not mention, and how files are validated.
A First Example
AU03.yml, a satellite with one AFSK transmitter and a telemetry parser:
name: AU03
alternative_names:
- QB50 AU03
- i-INSPIRE II
norad: 42731
data:
&tlm Telemetry:
telemetry: au03
transmitters:
4k8 AFSK downlink:
frequency: 436.330e+6
modulation: AFSK
baudrate: 4800
af_carrier: 3600
deviation: -1200
framing: U482C
data:
- *tlm
Read it as: "AU03 (also called QB50 AU03 or i-INSPIRE II, NORAD 42731) has one data type, Telemetry, parsed with the au03 telemetry definition. It has one transmitter, 4k8 AFSK downlink: 4800 baud AFSK on a 3600 Hz audio carrier with ±1200 Hz tones, using the GOMspace U482C framing. Its frames go to Telemetry."
Structure
name, alternative_names, norad, telemetry_servers ← identity
data: { <data name>: <data sink spec> } ← what to do with frames
transports: { <transport name>: <transport spec> } (optional)
transmitters: { <transmitter name>: <transmitter spec> }
YAML Anchors
The &name / *name syntax is standard YAML. &tlm Telemetry: attaches the anchor tlm to the key Telemetry, and - *tlm later inserts that same string. So these two are equivalent:
data:
- *tlm
data:
- Telemetry
Anchors simply avoid typing the name twice. Whatever you use, the transmitter's data (and transports) list must contain keys that exist in the data (and transports) section.
Top-Level Fields
| Field | Required | Type | Meaning |
|---|---|---|---|
name |
Yes | string | Main name, used to select the satellite and in --list_satellites. |
alternative_names |
No | list of strings (or empty) | Other names that select the satellite. An empty value is allowed. |
norad |
Yes | integer | NORAD catalog number. Used to select the satellite, for sat.cfg, and sent to telemetry servers. |
telemetry_servers |
No | list of strings | Extra telemetry servers (SatNOGS is always used). |
data |
Yes | mapping | Data sinks. See below. |
transports |
No | mapping | Higher-layer protocols. See below. |
transmitters |
Yes | mapping | Transmitters. See below. |
Valid telemetry_servers entries:
| Entry | Server |
|---|---|
FUNcube |
FUNcube Warehouse |
PWSat |
PW-Sat2 ground station |
BME |
BME telemetry server (only NORAD 44830, 44832, 47964) |
BMEWS |
BME WebSocket server |
HIT <port> |
Harbin Institute of Technology proxy on 127.0.0.1:<port> |
SIDS <url> |
Any SIDS server at <url> |
The value after HIT or SIDS is separated by a single space. See Telemetry Submission.
The data Section
Each entry has a name (any string; it appears only in the SatYAML file) and a specification of the data sink to create:
| Specification | Data sink | Example |
|---|---|---|
telemetry: <definition> |
Telemetry parser using satellites.telemetry.<definition> |
telemetry: funcube |
files: <receiver> |
File receiver using satellites.filereceiver.<receiver> |
files: smogp |
image: <receiver> |
Image receiver (file receiver plus feh display) |
image: by70_1 |
decoder: <datasink> |
A custom data sink class from satellites.components.datasinks |
decoder: codec2_udp_sink |
unknown (a bare value, not a mapping) |
Hex dump of each frame | &tlm Telemetry: unknown |
Example with several data entries:
data:
&tlm Telemetry:
telemetry: by70_1
&image Image:
image: by70_1
&codec2 Codec2:
decoder: codec2_udp_sink
Notes from the code:
- The key for file reception is
files(plural). The upstream documentation calls itfile, but afile:entry is not recognized and silently becomes a hex dump sink. - The checks are done in the order
decoder,telemetry,files,image; anything else becomes a hex dump. - A
decoderclass is first constructed withoptions=...; if it does not accept that argument it is constructed with no arguments. - With
--hexdump,telemetryandunknownentries are not created at all. - Telemetry definitions and receivers are looked up by attribute name in the
satellites.telemetryandsatellites.filereceiverpackages, so they must be imported in those packages'__init__.py(see Writing a Telemetry Parser).
Transmitters
A transmitter is one combination of frequency, modulation and coding. Each one gets its own demodulator and deframer, and all of them run in parallel on the same input.
transmitters:
1k2 FSK downlink:
frequency: 437.300e+6
modulation: FSK
baudrate: 1200
framing: AX100 ASM+Golay
data:
- *tlm
- *image
Common fields
| Field | Required | Type | Meaning |
|---|---|---|---|
| (key) | Yes | string | Transmitter name. Printed by the telemetry parser (-> Packet from <name>) and stored as the transmitter key in each frame's metadata. |
frequency |
Yes | number (Hz) | Downlink frequency. Informational: shown by --list_satellites, not used for decoding. |
modulation |
Yes | string | Demodulator to use. See Modulations. |
baudrate |
Yes | number | Symbol rate in baud (before Manchester coding). |
framing |
Yes | string | Deframer to use. See Framings. |
data |
One of data/transports |
list | Data entries that receive this transmitter's frames directly. |
transports |
One of data/transports |
list | Transports that receive this transmitter's frames. |
additional_data |
No | mapping | Extra deframer output ports mapped to data entries (see below). |
Note: Write frequencies the way the bundled files do, with a decimal point and a signed exponent (
437.300e+6) or as a plain integer (437300000). PyYAML follows YAML 1.1, where437.3e6(no sign in the exponent) and437e6are read as strings. A string frequency makes--list_satellitesfail and is rejected by the checker.
Demodulator fields
| Field | Used by | Meaning |
|---|---|---|
af_carrier |
AFSK (required) | Audio frequency in Hz at the centre of the two tones. |
deviation |
AFSK (required), FSK (optional) | Tone offset from the centre in Hz. Negative means the low tone is symbol 1. Overrides --deviation. |
fm_deviation |
AFSK (optional) | FM deviation in Hz, used to size the IQ input filter. Overrides --fm-deviation (default 3000). |
Deframer fields
These fields are passed to the deframer as keyword arguments. Only use them with framings that accept them; otherwise building the decoder fails with a Python TypeError about an unexpected keyword argument.
| Field | Accepted by | Values | Default |
|---|---|---|---|
frame size |
CCSDS framings, GEOSCAN, the RA framings |
Bytes after FEC decoding. For RA framings only 126, 128 or 256 are valid. | CCSDS 223, GEOSCAN 66, RA required |
precoding |
CCSDS framings | differential |
none |
RS basis |
CCSDS Reed-Solomon, CCSDS Concatenated (required); CCSDS Uncoded |
conventional, dual |
dual (constructor) |
RS interleaving |
CCSDS framings | integer | 1 |
scrambler |
CCSDS framings, AX100 ASM+Golay |
CCSDS, none |
CCSDS |
convolutional |
CCSDS Concatenated |
CCSDS, NASA-DSN, CCSDS uninverted, NASA-DSN uninverted |
CCSDS |
callsign |
Mobitex family | callsign string | none |
For example, BY70-1:
9k6 BPSK downlink:
frequency: 436.200e+6
modulation: BPSK
baudrate: 9600
framing: CCSDS Concatenated
precoding: differential
RS basis: conventional
frame size: 114
transports:
- *kiss
Differential precoding resolves the 180° phase ambiguity of BPSK. The CCSDS standard specifies the dual basis for Reed-Solomon, but many satellites use the conventional basis.
additional_data
Some deframers have more than one output port. additional_data maps an extra port name to a data entry. LilacSat-1 sends Codec2 voice on the deframer's codec2 port:
additional_data:
codec2: *codec2
Frames from additional ports are tagged with the transmitter name like regular frames, but go only to the named data entry, not to KISS output, ZMQ or submission.
Transports
Transports sit between the deframer and the data sinks, for protocols that carry packets inside frames. KS-1Q, for example, sends a KISS stream with a 3-byte header in each frame:
name: KS-1Q
norad: 41847
data:
&tlm Telemetry:
telemetry: csp
transports:
&kiss KISS:
protocol: KISS KS-1Q
data:
- *tlm
transmitters:
20k FSK downlink:
frequency: 436.500e+6
modulation: FSK
baudrate: 20000
framing: CCSDS Concatenated
RS basis: dual
frame size: 223
transports:
- *kiss
| Field | Required | Meaning |
|---|---|---|
| (key) | Yes | Transport name (documentation only). |
protocol |
Yes | One of the transport protocols. |
data |
Yes | Data entries that receive the transport's output packets. |
virtual_channels |
For TM KISS and TM short KISS |
List of integer CCSDS virtual channel IDs to extract. |
Note: The upstream KS-1Q example shows
framing: CCSDS Concatenated dual, which is not a valid framing. The bundled file usesframing: CCSDS ConcatenatedwithRS basis: dual, as above.
Validation
gr_satellites does not validate a SatYAML file before using it. Mistakes show up as Python exceptions while the decoder is built, for example a KeyError with the name of an unknown modulation or framing. A thorough checker exists in satellites.satyaml.yamlfiles.check_yaml() and is run on every bundled file by the qa_satyaml unit test. You can run it on your own file:
python3 -c "from satellites.satyaml import yamlfiles; yamlfiles.check_yaml('my_sat.yml')"
It raises satellites.satyaml.satyaml.YAMLError (whose text is in its message attribute) for problems such as:
| Check | Message |
|---|---|
| Unknown top-level key | Unknown word <key> in <file> |
Missing name, norad, data or transmitters |
Missing name field in <file> (and similar) |
norad not an integer |
NORAD field does not contain a number in <file> |
| Unknown telemetry server | Unknown telemetry server <server> |
Transport without valid protocol |
Missing protocol field in transport <key> / Unknown protocol field in transport <key> |
TM KISS without virtual_channels list of ints |
virtual_channels field missing in transport <key> |
Missing frequency, modulation, baudrate, framing |
Missing frequency field in <transmitter> in <file> (and similar) |
Non-numeric frequency, baudrate, af_carrier, deviation, fm_deviation |
Frequency field does not contain a float in ... (and similar) |
| Unknown modulation or framing | Unknown modulation in <transmitter> in <file> / Unknown framing in ... |
AFSK without af_carrier or deviation |
Missing af_carrier field for AFSK in ... |
CCSDS RS/Concatenated without RS basis, or bad precoding, RS basis, RS interleaving, scrambler, convolutional |
No RS basis field in ..., Invalid precoding value ..., ... |
Transmitter with neither data nor transports |
No data or transport field in <transmitter> in <file> |
| Data entry not defined | Data entry <name> used in <transmitter> is not defined in data field in <file> |
additional_data entry not defined |
Additional data entry <name> used in ... |
Limitations of the checker, visible in the code:
- References in a transmitter's
transportslist are not checked against thetransportssection. The check tests for a key namedtransport(singular), which never exists. A typo there only fails at runtime with aKeyError. - It does not check that deframer fields are accepted by the chosen framing, nor
frame sizevalues. - The
CCSDS Uncodedframing is not subject to the CCSDS field checks.