Skip to content

Commit de5c8f3

Browse files
Merge branch 'yamcs:master' into pixxel/master
2 parents 74fedfb + 96d3e2d commit de5c8f3

428 files changed

Lines changed: 14509 additions & 6088 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/dependabot.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: "maven"
4+
directory: "/"
5+
schedule:
6+
interval: "weekly"
7+
# Don't notify for regular version updates, only security ones
8+
open-pull-requests-limit: 0
9+
10+
- package-ecosystem: "npm"
11+
directory: "/"
12+
schedule:
13+
interval: "weekly"
14+
# Don't generate version update PRs for webapp (too noisy)
15+
exclude-paths:
16+
- "yamcs-web/src/main/webapp/**"
167 KB
Loading
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<mxfile host="Electron" modified="2025-09-10T14:07:45.144Z" agent="5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/20.3.0 Chrome/104.0.5112.114 Electron/20.1.3 Safari/537.36" etag="ZAMGO0btfpaQRaqPCaTz" version="20.3.0" type="device"><diagram id="bG7BKePdNWSyEMryDBXW" name="Page-1">5Vddb9owFP01PK4iMYT2sUC3Vmu1SVTq9jSZ+JJ4dXIjx4Fkv37XxCGEjK6VKrF2T/iee/11jn2IB2yWlJ80z+I7FKAG/lCUAzYf+L438gP6sUhVIxcTvwYiLYUraoGF/AUOHDq0kALyTqFBVEZmXTDENIXQdDCuNW66ZStU3VkzHkEPWIRc9dEHKUxco+f+pMWvQUZxM7MXXNSZhDfFbid5zAVu9iB2NWAzjWjqVlLOQFnyGl7qfh+PZHcL05Ca53S4m13fYDZ+WHuPX7LH9Y/P9zfLD26UNVeF2/C9TEDJFNyiTdUwobFIBdjBvAGbbmJpYJHx0GY3pD1hsUmUS6+kUjNUqLd92Wq18sOQ8NxofIS9jAiWwTigjFsIaAPl0R16O97owAEmYHRFJa6DzxzV7qyxoYs3rXJeI0e8p1rgMO4OS7QbuuWTGo7SF9Dr9+i9DI1cS2NXvQC9luFbJHo07hLtTU5N9KhHtABj/YCufGEKTSwHihYxXWpqRbbFayUkucuhAiDIA1yI2sQYYcrVVYtOW42GFLU1t4iZU+YnGFM5Q+OFwa5u9Zx2oqc1oHVhoUN4Yu/M2SLXEZi/3fW+phoUJya663h1gcY9gaCEsDDHhan+E1n8U8rCnjSoMAZRKNDvwKJO/18w6VGdKZ7+a75E9Orqm+u/Db7b4GzchPNyPzmvXPSKFyd4C352ftzPhjJJQEj+jr3tuRKd1NuCnkQ91rEw9lt3tns8WGoFz+Mdz9aEJD0HbvkS1FfM6WJiSrklGoPJXsGlkpFNGKvGlLsoJGrJPzs60EMgs/MnZWTfTGd8k7OzIt+WHXjl3J+zOSOcKoWksZpciim8jlF6h99y532jZH/wydHLfZLC9rmzze09GtnVbw==</diagram></mxfile>
16.6 KB
Loading
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
Command Activities
2+
==================
3+
4+
Yamcs is capable of executing a single command as a background activity.
5+
6+
.. note::
7+
Yamcs does not enforce all commands to be activities, rather it has an API to send commands directly. The capability to wrap a command in an activity is primarily intended for use with planned activities.
8+
9+
10+
Activity Options
11+
----------------
12+
13+
command (string)
14+
**Required.** Fully-qualified command name.
15+
16+
args (map)
17+
Command arguments mapped from name to value.
18+
19+
processor (string)
20+
Choose the processor that will handle the command instruction.
21+
22+
This defaults to the first defined processor with commanding capabilities, which by convention is usually called ``realtime``.
23+
24+
extra (map)
25+
Additional command options mapped from name to value (implementation-specific).
26+
27+
stream (string)
28+
Specify the low-level Yamcs stream where the command is emitted.
29+
30+
If undefined, Yamcs will automatically select the target stream (first matching ``tc`` stream under the ``streamConfig`` configuration block. See :doc:`../data-management/streams`.
31+
32+
33+
Execution
34+
---------
35+
36+
The activity finishes successfully when the command could be encoded and submitted to a link. It does not currently track any acknowledgments or command completion.
37+
38+
39+
Yamcs UI
40+
--------
41+
42+
The Yamcs UI does not support **immediate** execution of command activities, because you can send commands directly without the notion of an activity.
43+
44+
To execute a command **at a later time**, go to :menuselection:`Commanding --> Send a command`. Enter the command form, then choose the option :guilabel:`Send later...`. You will be asked to enter the desired execution time. This will create an activity *item* in the :doc:`../timeline/index`.
45+
46+
47+
Python Yamcs Client
48+
-------------------
49+
50+
Run a command activity one minute from now:
51+
52+
.. code-block:: python
53+
54+
from datetime import datetime, timedelta, timezone
55+
56+
from yamcs.client import CommandActivity, YamcsClient, TimelineActivity
57+
58+
client = YamcsClient("http://localhost:8090")
59+
timeline = client.get_timeline_client("simulator")
60+
61+
now = datetime.now(tz=timezone.utc)
62+
63+
item = TimelineActivity(
64+
name="Switch on battery 1 voltage",
65+
start=now + timedelta(minutes=1),
66+
duration=timedelta(seconds=1), # Planned duration
67+
activity=CommandActivity(
68+
command="/YSS/SIMULATOR/SWITCH_VOLTAGE_ON",
69+
args={"voltage_num": 1},
70+
),
71+
)
72+
73+
timeline.save_item(item)
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
Activities
2+
==========
3+
4+
Yamcs can run background activities whose execution state are tracked in the UI.
5+
6+
.. image:: _images/activities-page.png
7+
:alt: Activities Page
8+
:align: center
9+
10+
Yamcs includes a core set of activity types that cover command execution, stack execution and script execution. Yamcs plugins may add additional types.
11+
12+
.. note::
13+
Prior to Yamcs 5.13.0, activities were only available by enabling the :doc:`Timeline Service <../services/instance/timeline-service>`. Since then, activities were upgraded to a core Yamcs functionality, and so no longer require presence of the Timeline Service.
14+
15+
16+
.. rubric:: Status
17+
18+
An activity can assume one of these statuses:
19+
20+
* **RUNNING:** The activity is ongoing
21+
* **CANCELLED:** The activity was cancelled
22+
* **SUCCESSFUL:** The activity completed successfully
23+
* **FAILED:** An error occurred while running the activity
24+
25+
26+
.. rubric:: Relation to Timeline
27+
28+
When combining with the :doc:`../timeline/index`, you can plan activities for future execution:
29+
30+
.. image:: _images/planned-activities.png
31+
:alt: Planned Activities
32+
:align: center
33+
34+
Planned activities are submitted via the UI or API to the Timeline (saved as activity *items*). An activity scheduler monitors all activity items in the Timeline, and submits them to the activity service when due, for immediate execution.
35+
36+
.. toctree::
37+
:maxdepth: 1
38+
:caption: Table of Contents
39+
40+
commands
41+
stacks
42+
scripts
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
Script Activities
2+
=================
3+
4+
Yamcs can run arbitrary scripts or programs as a background activity.
5+
6+
Scripts are predefined and stored under :file:`etc/scripts`.
7+
8+
Script files may be directly executable, or be associated to another program based on its file extension.
9+
10+
11+
Configuration
12+
-------------
13+
14+
Script activity options are configured in the instance configuration file :file:`etc/yamcs.{instance}.yaml`.
15+
16+
.. code-block:: yaml
17+
:caption: :file:`etc/yamcs.{instance}.yaml`
18+
19+
activities:
20+
scriptExecution:
21+
searchPath: etc/scripts
22+
impersonateCaller: false
23+
fileAssociations:
24+
py: python3 -u
25+
26+
27+
Configuration Options
28+
---------------------
29+
30+
searchPath (string or string[])
31+
Directory where to locate scripts or executables.
32+
33+
Default: :file:`etc/scripts`
34+
35+
fileAssociations (map)
36+
Extend or override the default file associations. Each entry maps a file extension (case-insensitive) to a program that should be used to execute this file.
37+
38+
The default file associations are:
39+
40+
.. code-block:: yaml
41+
42+
fileAssociations:
43+
java: java
44+
js: node
45+
mjs: node
46+
pl: perl
47+
py: python -u
48+
rb: ruby
49+
50+
Any file that does not have an association, is executed directly.
51+
52+
.. note::
53+
Some Linux distributions no longer have a ``python`` command. In this case you can adapt the file association to ``python3 -u``. Alternatively, on Debian-based distributions you may want to install the ``python-is-python3`` package:
54+
55+
.. code-block:: shell
56+
57+
sudo apt install python-is-python3
58+
59+
This package creates a symlink so that ``python`` invokes ``python3``.
60+
61+
.. note::
62+
The ``-u`` flag added to the ``python`` command forces Python to run in **unbuffered mode**. This affects how Python handles output streams, allowing Yamcs to capture output in realtime instead of needing to wait until the buffer is full.
63+
64+
impersonateCaller (boolean)
65+
Scripts receive a transient API key via an environment variable. By default this API key uses the built-in ``System`` user, which provides unrestricted access.
66+
67+
When this property is enabled, the script receives instead an API key of the user that started the activity.
68+
69+
Default: ``false``
70+
71+
72+
Activity Options
73+
----------------
74+
75+
script (string)
76+
**Required.** Script path relative to the :file:`etc/scripts` directory.
77+
78+
args (string, or list of strings)
79+
Command line arguments.
80+
81+
processor (string)
82+
If provided this information is passed to the called script as a ``YAMCS_PROCESSOR`` environment variable.
83+
84+
85+
Execution
86+
---------
87+
88+
The script's ``stdout`` and ``stderr`` output streams are captured in the Yamcs activity log. The activity tracks the lifecycle of the subprocess. The exit code of this process determines whether the activity is considered successful or not. A non-zero exit code indicates failure.
89+
90+
91+
Environment Variables
92+
---------------------
93+
94+
Scripts are executed with the following environment variables:
95+
96+
``YAMCS``
97+
Always set to ``1``.
98+
99+
``YAMCS_INSTANCE``
100+
Set to the applicable Yamcs instance.
101+
102+
``YAMCS_PROCESSOR``
103+
Set to the applicable Yamcs processor.
104+
105+
``YAMCS_URL``
106+
URL that the script can use to reach Yamcs.
107+
108+
For example: ``http://localhost:8090``
109+
110+
If Yamcs requires authentication, another environment variable is set:
111+
112+
``YAMCS_API_KEY``
113+
A randomly generated API key that the script may use to authenticate against Yamcs. Keys are invalidated when the script terminates.
114+
115+
Clients can use an API key by setting the ``x-api-key`` HTTP header on each request. Yamcs will know how to link this back to the appropriate user, which (depending on configuration) could be the script caller, or a generic ``System`` user.
116+
117+
118+
Python Scripts
119+
--------------
120+
121+
Python scripts may use the `Python Yamcs Client <https://docs.yamcs.org/python-yamcs-client/>`_ to access the Yamcs API. This includes a static utility function ``YamcsClient.from_environment()`` that reads aforementioned environment variables, and authenticates when needed.
122+
123+
.. code-block:: python
124+
125+
from yamcs.client import YamcsClient
126+
import sys
127+
128+
# Create a client instance
129+
client = YamcsClient.from_environment()
130+
131+
# Print all command-line arguments
132+
print(sys.argv)
133+
134+
# ...
135+
136+
The Python Yamcs Client is something that would need to be installed separate from Yamcs.
137+
138+
139+
Shell Scripts
140+
-------------
141+
142+
Below is an example of a shell script that generates a Yamcs event. Remember to make the file executable.
143+
144+
.. code-block:: shell
145+
146+
#!/bin/sh
147+
148+
echo "Creating event"
149+
150+
MSG="$(whoami) says hi"
151+
JSON_STRING=$(printf '{"message": "%s"}' "$MSG")
152+
153+
curl -XPOST $YAMCS_URL/api/archive/$YAMCS_INSTANCE/events \
154+
--silent -d "$JSON_STRING" --fail-with-body
155+
156+
For authenticated servers, you can specify an additional HTTP header on the curl command:
157+
158+
.. code-block:: shell
159+
160+
-H "x-api-key: $YAMCS_API_KEY"
161+
162+
163+
Yamcs UI
164+
--------
165+
166+
In the Yamcs UI, choose :menuselection:`Procedures --> Run a script`. A list of the available scripts is displayed, and you can choose to run one **immediately**, providing any script arguments.
167+
168+
To execute a script **at a later time**, choose the option :guilabel:`Run later...`. You will be asked to enter the desired execution time. This will create an activity *item* in the :doc:`../timeline/index`.
169+
170+
171+
Python Yamcs Client
172+
-------------------
173+
174+
Run a script activity immediately (does not use Yamcs Timeline):
175+
176+
.. code-block:: python
177+
178+
from yamcs.client import YamcsClient
179+
180+
client = YamcsClient("localhost:8090")
181+
processor = client.get_processor("simulator", "realtime")
182+
183+
# Simulate LOS for 5 seconds
184+
# (the run_script call does not block)
185+
processor.run_script("simulate_los.py", "--duration 5")
186+
187+
188+
Run a script activity one minute from now:
189+
190+
.. code-block:: python
191+
192+
from datetime import datetime, timedelta, timezone
193+
194+
from yamcs.client import ScriptActivity, YamcsClient, TimelineActivity
195+
196+
client = YamcsClient("http://localhost:8090")
197+
timeline = client.get_timeline_client("simulator")
198+
199+
now = datetime.now(tz=timezone.utc)
200+
201+
item = TimelineActivity(
202+
name="Simulate LOS",
203+
start=now + timedelta(minutes=1),
204+
duration=timedelta(seconds=5), # Planned duration
205+
activity=ScriptActivity(
206+
script="simulate_los.py",
207+
args="--duration 5",
208+
processor="realtime",
209+
),
210+
)
211+
timeline.save_item(item)

0 commit comments

Comments
 (0)