This page is the reference of every line of a .proc file: the declarations, the statements of
a step and the actions of a procedure. Square brackets mark optional parts, … a repetition.
Durations are literals with a time unit (500 ms, 10 s, 3 min, 1 h); conditions are
boolean expressions (see Expressions, Types and Units).
Summary#
| Line | Where | Grammar |
|---|---|---|
step | top level, procedure | step ["<name>"] [retry …] |
procedure | top level | procedure "<name>" |
description | step, procedure | description "<text>" |
uses | step, procedure | uses <role>: <platform> |
input | step, procedure | input <name>: <type> |
allowed in | procedure | allowed in <environment>[, …] |
send | step | send <telecommand> to <target> [with <arg> = <value>[, …]] [via <link>] |
expect | step | expect <condition> within <duration> |
check | step | check <condition> |
log | step | log <value> or log "<text with {values}>" |
ask | step | ask operator "<question>" [as <type> into <name>] |
wait | step | wait <duration> |
wait until | step | wait until <condition> within <duration> |
download | step | download <role>.files[<file id input>] |
upload | step | upload <file input> to <role>.files[<file id input>] |
configure | step | configure <role> for <mode> |
do | procedure | do "<step>" [with <param>[ = <value>][, …]] [retry …] |
run | procedure | run "<procedure>" [with <param>[ = <value>][, …]] [retry …] |
if failed | procedure | if failed, then an indented block of actions |
retry is retry [<N> times] [every <duration>] [for <duration>], with a count, a total
duration or both; see Retries.
Declarations#
step and procedure#
step "TCU answers" retry 3 times every 2 s
uses sat: platform-v3
input tcu: tcu_id
send ping to sat.tcu[tcu] via direct
expect sat.tcu[tcu].responding is true within 5 sA step or a procedure needs an indented body. A library step has a name; an inline step in a
procedure may have one or not (an unnamed inline step appears as #<n> in the run log, its rank
among the inline steps of the procedure). Procedures cannot be nested: a procedure calls another
with run.
uses and input#
uses psu: lab-psu
input bus_voltage: f32 V
input tcu: tcu_id
input lttm: file_id of lttm
input patch: fileSee Roles and inputs and Input types.
allowed in#
allowed in AIT, IVVThe environments of the topology where the procedure may run; each must exist
(procedure::unknown-environment). Without allowed in, the procedure may run in every
environment. A run in another environment is refused at launch (run::not-allowed). A dry run
ignores it.
Statements of a step#
The statements of a step run in order; the first that fails stops the step. The executor checks between statements whether an operator asked to suspend or abort the run.
send#
send <telecommand> to <target> [with <arg> = <value>, …] [via <link>]send ping to sat.tcu[tcu] via direct
send set_voltage to psu with voltage = bus_voltage
send set_mode to sat.tcu[TCU1] with mode = SAFE_MODE
send delete_file to sat.files[lttm]- The target is always given: a role (single-component platform) or a component with its
instance. The telecommand must belong to that component (
procedure::unknown-telecommand). - Arguments are always named. Each value is checked against the type, unit and range of the
argument (
procedure::type-mismatch,procedure::out-of-rangefor a literal out of itsrange); an argument without default must be given (procedure::missing-argument), an unknown or repeated one is refused. Values from inputs are checked when the run request is resolved. Enum values are written bare (mode = SAFE_MODE). via <link>sends through a link of the target other than its default one. The link name is checked against the target when the run request is resolved (run::unknown-link), and the link must carry the component (run::link-component).
At run time, the executor logs telecommand_sent with the identifier of the telecommand before
it leaves, then follows its acknowledgement chain: requires,
ACK 1 (driver), ACK 2 (gateway), ACK 3 (verify). The statement succeeds when the telecommand
ends VERIFIED or COMPLETE, and fails on any other final state. The end of the chain is
logged as telecommand_finished, with every acknowledgement.
A send of a hazardous telecommand needs a confirmation first; see
Safety Rules.
expect#
expect <condition> within <duration>expect sat.tcu[tcu].responding is true within 5 s
expect sat.files[lttm].transfer is PROCESSED within 8 minWaits until the condition holds on samples received after the last SENT of the step, or after
the start of the step when it has sent nothing. A value that was already true before the
telecommand never satisfies an expect. Samples received while the send was still waiting for
its verification count: the executor reads them back from the PARAMS stream from SENT on. A
measure produced once, such as the reply to ping, therefore satisfies the expect that follows.
within is mandatory (procedure::missing-timeout). The statement fails when the window ends
first. The samples judged are logged as evidence in a checked event.
check#
check <condition>check sat.tcu[tcu].mode is mode
check sat.files[lttm].transfer is PROCESSEDEvaluates the condition once, on the current values. Each measure read must be fresh: its
last sample must be younger than the max_age of the measure in the catalogue, measured from
its ground reception time. A missing or stale value fails the check. The samples used are
logged as evidence.
The current values are never older than what the run already judged: after an expect or a
wait until, a check or a log reads, for each component they judged, values at least as
recent as the newest sample they saw (waiting up to 2 s for the current value table to catch
up). A check right after expect psu.voltage is 28 V +/- 0.5 V within 5 s thus sees that
sample, not the one before.
log#
log <value>
log "<text with {value} …>"log sat.tcu[tcu].anode_voltage
log param sat.tcu[tcu].anode_voltage in Nominal
log "TCU1 at {sat.tcu[TCU1].anode_voltage} in {sat.tcu[TCU1].mode}"
log "Bus {psu.voltage}, threshold {{5 V}}"Writes values in the log of the run, where they appear in the report, the web console,
stellar watch and the API client, without judging them: the value of a measure, a derived
measure, a parameter (param …), an input or any expression of them (psu.voltage * 2,
sat.tcu[tcu].anode_voltage > 5 V).
log <value>writes the expression as in the procedure, then its value:sat.tcu[tcu].anode_voltage = 248.7 V.log "<text>"writes the text, each{expression}replaced by its value:TCU1 at 248.7 V in STANDBY.{{and}}write a brace.- Numbers keep six significant digits at most and their unit; booleans are
trueorfalse, enum values as declared. - The expressions are checked when the procedure is compiled, like those of
check: an unknown measure or a unit mismatch is an error; temporal functions are refused. A malformed text isprocedure::log-template(a{not closed, a}alone, an empty{}). - The values are read when the statement runs, on the current values.
lognever fails: a value that cannot be computed (no sample yet) is writtenunknown, one computed from a sample older than themax_ageof its measure is followed by(stale). - It sends nothing, lasts zero and leaves the step eligible for automatic retries.
The event of the run is logged, with the text written and the samples read (value, on-board
and ground times), shown in the report like the evidence of a check.
ask#
ask operator "<question>"
ask operator "<question>" as <type> into <name>ask operator "Fire the blank on the TCU?"
ask operator "Voltage read on the bench multimeter?" as f32 V into measured
check psu.voltage is measured +/- 0.5 V- Confirmation. Without
as … into, the operator answers yes or no;nofails the step. - Typed answer. With
as <type> into <name>, the operator answers a value of that type (unit and enum included); the answer is then a name of the step, usable in the statements that follow.asandintogo together. - Only
operatoris asked: who actually confirms is set by the environment, not by the text (hazardous_confirmation, see Hazardous Confirmations). - Without human orchestration in the environment, a confirmation is acknowledged automatically and logged as such; a typed answer then fails the step, since no operator is expected.
The run waits for the answer; stellar status shows the question, and stellar answer answers
it. See Questions, Decisions and Control.
wait#
wait <duration>
wait until <condition> within <duration>wait 5 s
wait until psu.output_enabled is true within 10 swait 5 s waits for a duration. wait until waits until a condition holds, starting from the
current values: unlike expect, it does not require a sample received after a telecommand. Its
timeout is mandatory and fails the step when it expires.
download#
download <role>.files[<file id input>]download sat.files[lttm]
expect sat.files[lttm].transfer is PROCESSED within 8 minCreates the download of the current generation of the file, as last listed, with the run as
requester (run <id>), and goes on at once: the transfer continues on its own, pass after pass.
Wait for it with expect on the transfer measure of the file. The platform must declare a
transfer protocol (procedure::transfer-unavailable). See
File Transfers.
upload#
upload <file input> to <role>.files[<file id input>]upload patch to sat.files[slot]
expect sat.files[slot].transfer is VERIFIED within 30 minCreates the upload of a content given at launch, an input of type file (the SHA-256 of a content
stored with stellar put), and goes on at once. The platform must declare a write telecommand
or CFDP. An upload never activates what it writes: activation is a telecommand of its own.
configure#
configure <role> for <mode>step "Configure survival"
configure sat for SurvivalApplies a mode to the target of the role: it sets every parameter of
the platform that has a set to its value in the mode, reads back those that have a readback,
and records the mode as the current mode of the target. The compiler expands it from the
catalogue of the platform of the role:
- for each telecommand that sets parameters, in the order of the catalogue, and for each
instance of its component in the order of the enum of its instances, a
sendwhose parameter arguments areparam <role>.<component>[<instance>].<parameter> in <mode>(its other arguments keep their default); - after each
send, for each of its parameters with areadback, anexpect <readback> is <value> [+/- <tolerance>] within <window>, the window being the longestwithinof the verifications of the setter, 10 s without one; - at the end, the current mode of the target becomes
<mode>, and the run logsmode_changed.
The first failure stops the step, like any statement, and the mode is not recorded. Each send
is logged as usual (telecommand_sent, telecommand_finished) and each readback as a checked
event.
- The mode must be declared in the topology (
procedure::unknown-mode), and the platform must have at least one parameter with aset(procedure::nothing-to-configure). - The sends follow the rules of
send: ahazardoussetter needs itsask operatorbefore theconfigurein the same step, one per hazardous send; a setter withchanges_state: true(the default) makes the step ineligible for retries. See Safety Rules. - At the resolution of the run, the target must have a value of each parameter in the mode
(
run::parameter-undefined).
Actions of a procedure#
do and run#
do "<step>" [with <param>[ = <value>], …] [retry …]
run "<procedure>" [with <param>[ = <value>], …] [retry …]do "TCU answers" with sat, tcu
do "TCU in mode" with sat, tcu, mode = expected_mode
do "TCU answers" with sat, tcu retry every 5 s for 3 min
run "Check TCU" with sat, tcu, expected_mode = STANDBYdo calls a step of the library, run a procedure of the library
(procedure::unknown-step, procedure::unknown-procedure; the help says when the name is the
other kind).
Every role and every input of the callee receives:
- the explicit value written after
=: for a role, a role of the caller; for an input, an expression of the caller (input, answer, literal, enum value); - otherwise, the role or input of the same name of the caller. Listing the name alone
(
with sat, tcu) documents it; leaving it out has the same effect.
A parameter left without value is an error (procedure::missing-argument); an unknown one too
(procedure::unknown-parameter). A role passed must be of the same platform
(procedure::role-mismatch). A file_id input takes a file_id input of the same file type,
a file input another file input.
A call succeeds when the step, or every action of the sub-procedure, succeeds. A retry on the
call overrides the policy of the step; on a run, it replays the whole sub-procedure. See
Retries.
Inline steps#
procedure "Safe TCU"
uses sat: platform-v3
input tcu: tcu_id
step "Command safe mode"
send safe_mode to sat.tcu[tcu]
expect sat.tcu[tcu].mode is SAFE_MODE within 10 sAn inline step is written where it runs, for a one-off action. It inherits the roles and inputs
of its procedure and declares none; it may have a description and a retry on its step line.
if failed#
run "Check TCU" with sat, tcu, expected_mode = STANDBY
if failed
run "Safe TCU" with sat, tcuThe actions of a procedure run in order. When one fails:
- the following actions are skipped, up to the next
if failedblock; - that block runs, its actions in order;
- the procedure stops there and is failed, even if the block succeeds:
if failedhandles the failure, it does not cancel it.
Without a failure, if failed blocks are skipped. An if failed block contains actions only:
do, run and inline steps; no declaration (procedure::misplaced). A failure with no if failed
block after it fails the procedure at once. An abort
by an operator ends the run without running any if failed block.
A sub-procedure that fails makes its run fail in the caller, whose own if failed block then
applies.
Execution order at a glance#
flowchart TD
A[Action] -->|succeeds| B[Next action]
A -->|fails| C{"if failed block<br/>further on?"}
C -->|yes| D[Run the block] --> E[Procedure failed]
C -->|no| E
B -->|no more actions| F[Procedure succeeded]