rccn-gen 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rccn_gen-1.0.0/.gitignore +21 -0
- rccn_gen-1.0.0/.gitlab-ci.yml +16 -0
- rccn_gen-1.0.0/PKG-INFO +123 -0
- rccn_gen-1.0.0/README.md +109 -0
- rccn_gen-1.0.0/pyproject.toml +27 -0
- rccn_gen-1.0.0/src/rccn_gen/LICENSE +674 -0
- rccn_gen-1.0.0/src/rccn_gen/__init__.py +13 -0
- rccn_gen-1.0.0/src/rccn_gen/application.py +0 -0
- rccn_gen-1.0.0/src/rccn_gen/service.py +0 -0
- rccn_gen-1.0.0/src/rccn_gen/systems.py +481 -0
- rccn_gen-1.0.0/src/rccn_gen/telemetry.py +83 -0
- rccn_gen-1.0.0/src/rccn_gen/text_modules/cargo_toml/cargo.txt +14 -0
- rccn_gen-1.0.0/src/rccn_gen/text_modules/command/command.txt +11 -0
- rccn_gen-1.0.0/src/rccn_gen/text_modules/command/command_module_enum.txt +2 -0
- rccn_gen-1.0.0/src/rccn_gen/text_modules/command/command_module_struct.txt +1 -0
- rccn_gen-1.0.0/src/rccn_gen/text_modules/main/main.txt +24 -0
- rccn_gen-1.0.0/src/rccn_gen/text_modules/main/service_module_import_service.txt +1 -0
- rccn_gen-1.0.0/src/rccn_gen/text_modules/main/service_module_mod_service.txt +1 -0
- rccn_gen-1.0.0/src/rccn_gen/text_modules/main/service_module_register_service.txt +2 -0
- rccn_gen-1.0.0/src/rccn_gen/text_modules/mod/mod.txt +3 -0
- rccn_gen-1.0.0/src/rccn_gen/text_modules/service/command_module_match_cmd.txt +3 -0
- rccn_gen-1.0.0/src/rccn_gen/text_modules/service/service.txt +34 -0
- rccn_gen-1.0.0/src/rccn_gen/text_modules/telemetry/telemetry.txt +6 -0
- rccn_gen-1.0.0/src/rccn_gen/utils.py +159 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
*.rs
|
2
|
+
*.DS_Store
|
3
|
+
*.ipynb
|
4
|
+
*.pyc
|
5
|
+
venv/
|
6
|
+
examples/
|
7
|
+
tests/
|
8
|
+
*.diff
|
9
|
+
*.rs
|
10
|
+
*.orig
|
11
|
+
*.rej
|
12
|
+
*.lock
|
13
|
+
__pycache__/
|
14
|
+
*target/
|
15
|
+
*.xml
|
16
|
+
*.whl
|
17
|
+
*.egg-info/
|
18
|
+
/dist
|
19
|
+
rccn_usr_com_app/Cargo.toml
|
20
|
+
.rccn_diffs/
|
21
|
+
.rccn_snapshots/
|
@@ -0,0 +1,16 @@
|
|
1
|
+
stages:
|
2
|
+
- deploy
|
3
|
+
deploy:
|
4
|
+
stage: deploy
|
5
|
+
script:
|
6
|
+
- python3 -m venv .venv
|
7
|
+
- source .venv/bin/activate
|
8
|
+
- pip install build twine
|
9
|
+
- python -m build
|
10
|
+
- python3 -m twine upload --verbose --repository pypi dist/* -u __token__ -p $RCCN_3_PYPI
|
11
|
+
only:
|
12
|
+
- main
|
13
|
+
before_script:
|
14
|
+
- apt-get update
|
15
|
+
- apt-get install -y python3 python3-pip
|
16
|
+
- apt install -y python3.11-venv
|
rccn_gen-1.0.0/PKG-INFO
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: rccn_gen
|
3
|
+
Version: 1.0.0
|
4
|
+
Summary: A python based generator for RACCOON OS source files in Rust from yamcs-pymdb config files.
|
5
|
+
Project-URL: Homepage, https://gitlab.com/rccn/pymdb_code_generation
|
6
|
+
Project-URL: Issues, https://gitlab.com/rccn/pymdb_code_generation/issues
|
7
|
+
Author-email: Fabian Krech <f.krech@tu-berlin.de>
|
8
|
+
License-Expression: GPL-3.0
|
9
|
+
Classifier: Operating System :: OS Independent
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
11
|
+
Requires-Python: >=3.8
|
12
|
+
Requires-Dist: yamcs-pymdb>=0.1.0
|
13
|
+
Description-Content-Type: text/markdown
|
14
|
+
|
15
|
+
# RCCN Code Generator
|
16
|
+
This generator is used to generate Rust files to deploy on the RACCOON OS satellite based on the pymdb config files used to generate the ground station XTCE files.
|
17
|
+
## Setup
|
18
|
+
- Pull the repo
|
19
|
+
- Set up a virtual python environment with python 13 kernel and activate:
|
20
|
+
```zsh
|
21
|
+
python -m venv .venv
|
22
|
+
source .venv/bin/activate
|
23
|
+
```
|
24
|
+
- Install pymdb with `pip install yamcs-pymdb`
|
25
|
+
|
26
|
+
## Using the Generator
|
27
|
+
The generator is based on pymdb and uses the same structure. Where pymdb gives the user freedom in defining systems, subsystems and their respective relations, the definitions for rust code generation is more restricted. For the rust generation, the user is binded to the following classes:
|
28
|
+
- Application,
|
29
|
+
- Service, and
|
30
|
+
- RCCNCommand.
|
31
|
+
|
32
|
+
All classes inherit from pymdb's Subsystem class and extend their functionality. This means that an existing pymdb definition can be used to generate rust code by renaming the respective instances. No functionality for pymdb's XTCE generation will be lost.
|
33
|
+
|
34
|
+
A root system may be defined for the satellite.
|
35
|
+
```python
|
36
|
+
root_system = System("Satellite")
|
37
|
+
```
|
38
|
+
|
39
|
+
### Application
|
40
|
+
An application can be defined with the following statement.
|
41
|
+
```python
|
42
|
+
app = Application(system=root_system, name="ExampleApp", apid=42)
|
43
|
+
```
|
44
|
+
It has the obligatory arguments **system**, **name** and **apid**. After all Applications, Services and RCCNCommands are defined, the rust code generator can be called on the application with `app.generate_rccn_code()`.
|
45
|
+
|
46
|
+
### Service
|
47
|
+
|
48
|
+
A service may be defined with the following command.
|
49
|
+
```python
|
50
|
+
service = Service(name="ExampleService", system=app, service_id = 131)
|
51
|
+
```
|
52
|
+
It has the obligatory arguments **name** and **system**. The system corresponds to the application where the service is associated to. Note that each service has one associated app. A service cannot be associated to more than one apps. You may think of the Application-Service-Command structure as a mathematical tree, where merging branches are not allowed. However, you can create multiple instances of the same service and associate them to different applications, or create multiple identical command instances and associate them to different services.
|
53
|
+
|
54
|
+
### RCCNCommand
|
55
|
+
An RCCNCommand can be defined with the following statement.
|
56
|
+
```python
|
57
|
+
RCCNCommand(
|
58
|
+
system=service,
|
59
|
+
assignments={"subtype": 2},
|
60
|
+
name="StopProcess",
|
61
|
+
arguments=[StringArgument("name", encoding=StringEncoding())],
|
62
|
+
)
|
63
|
+
```
|
64
|
+
Obligatory arguments are **system**, **base**, **name** and **arguments**. The latter can be an empty list. The definition must contain a subtype definition in the assignment property, like shown in the example.
|
65
|
+
|
66
|
+
## Output
|
67
|
+
From the python configuration, the `main.rs`, `service.rs`, `command.rs`, `mod.rs`, `Cargo.toml` and `telemetry.rs` files are generated and are structured accordingly:
|
68
|
+
- rccn_usr_example_app/
|
69
|
+
- Cargo.toml
|
70
|
+
- src/
|
71
|
+
- main.rs
|
72
|
+
- example_service/
|
73
|
+
- command.rs
|
74
|
+
- service.rs
|
75
|
+
- mod.rs
|
76
|
+
- telemetry.rs
|
77
|
+
|
78
|
+
The `Cargo.toml` and `mod.rs` files are generated only if the files don't exist already, as their content doesn't depend on the pymdb config. No user changes will be overwritten. The command and service files are created for each service in the application.
|
79
|
+
|
80
|
+
## How It Works
|
81
|
+
The code is generated from templates in the `text_modules` folder. Base templates define the structure for all generated files, respectively. In the templates, two types of keywords can be found and are indicated by `<<KEYWORD>>` encapsulation.
|
82
|
+
|
83
|
+
Keywords beginning with `VAR_` point to a value in the python config created by the user, as shown above. Examples for this are the application identifier (APID) with `<<VAR_APID>>` or the service name with `<<VAR_SERVICE_NAME_UCASE>>`.
|
84
|
+
|
85
|
+
Keywords beginning with `SERVICE_MODULE` or `COMMAND_MODULE` point to other template files in the same folder. The prefix `SERVICE` or `COMMAND` indicates, that this module should be inserted once for every service in the application or once for every command in the service. In this way, the structure of the generated code can be segmented, organized and restructured without any need to change the code generator itself.
|
86
|
+
|
87
|
+
The keyword `<<SERVICE_MODULE_REGISTER_SERVICE>>` for example can be found in the main template and inserts the contents from the `service_module_register_service.txt` file for every service:
|
88
|
+
|
89
|
+
```rust
|
90
|
+
let service<<VAR_SERVICE_ID>> = <<VAR_SERVICE_NAME_UCASE>>::new();
|
91
|
+
app.register_service(service<<VAR_SERVICE_ID>>);
|
92
|
+
```
|
93
|
+
|
94
|
+
The variable keywords are replaced with the corresponding values in the python configuration.
|
95
|
+
|
96
|
+
## Editing Generated Files
|
97
|
+
The code generator allows for the user to make changes to the generated .rs files directly and to keep those changes if the files are regenerated. For this purpose, snapshots of the .rs files are taken, .diff files are created and user changes are rebased to regenerated .rs files. If this behaviour is not desired, it can be turned off with the commands showed below.
|
98
|
+
|
99
|
+
```python
|
100
|
+
app.generate_rccn_code(rebase_changes=False) # Turn off rebaseing of user changes to newly generated .rs files
|
101
|
+
app.generate_rccn_code(snapshots=False, rebase_changes=False) # Turn of rebaseing and snapshot creation
|
102
|
+
```
|
103
|
+
|
104
|
+
Please note that switching off rebasing and snapshot creation means that **existing files will be overwritten** and all changes made prior will be lost.
|
105
|
+
|
106
|
+
### Sequence in File Generation
|
107
|
+
With the snapshot and rebase functionality enabled, the following steps are run through during the generation of every file. For this example it is assumed that the file that is about to be generated already exists in the export directory from a previous generation and user changes where made to the generated file since then.
|
108
|
+
|
109
|
+
1. If a snapshot exists in `.rccn_snapshots/generated/`, a diff file containing the changes from the snapshot to the file as it exists in the export directory is created.
|
110
|
+
2. The current file in the export directory is copied to `.rccn_snapshots/user/`. A subfolder indicates the time of creation.
|
111
|
+
3. The new .rs file is generated based on the pymdb config and exported to the export directory, overwriting the existing file.
|
112
|
+
4. The new .rs file is copied to `.rccn_snapshots/generated/` for future use.
|
113
|
+
5. The new .rs file is patched using the diff file from step 1.
|
114
|
+
|
115
|
+
The sequence from above is changed accordingly if no previous snapshot exists. In the `/generated/` folder, there is only one snapshot per application at one time. And this snapshot always represents the .rs file as it is generated. No user changes to the .rs files are tracked in this snapshot. It is only used to determine the user changes to the .rs file in the export directory since the generation.
|
116
|
+
|
117
|
+
Snapshots of the .rs files in the export directory are stored in `/user/`. These can be used to undo code regeneration if conflicts arise during the patching. Please note that by default, only the last 10 user snapshots are stored. You can change this property with the following command.
|
118
|
+
|
119
|
+
```python
|
120
|
+
app.keep_snapshots = 15 # What ever value you want
|
121
|
+
```
|
122
|
+
|
123
|
+
With the sequence from above, it becomes apperant that changes to the .rs file in the export directory always trump changes to the pymdb config. If for example, a main.rs file is generated for an application with and APID of 42, and this apid is changed in the main.rs file to 45, this change will persist after regenerating from the python config. Even if changes to the pymdb config where made after the changes to the main.rs file.
|
rccn_gen-1.0.0/README.md
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
# RCCN Code Generator
|
2
|
+
This generator is used to generate Rust files to deploy on the RACCOON OS satellite based on the pymdb config files used to generate the ground station XTCE files.
|
3
|
+
## Setup
|
4
|
+
- Pull the repo
|
5
|
+
- Set up a virtual python environment with python 13 kernel and activate:
|
6
|
+
```zsh
|
7
|
+
python -m venv .venv
|
8
|
+
source .venv/bin/activate
|
9
|
+
```
|
10
|
+
- Install pymdb with `pip install yamcs-pymdb`
|
11
|
+
|
12
|
+
## Using the Generator
|
13
|
+
The generator is based on pymdb and uses the same structure. Where pymdb gives the user freedom in defining systems, subsystems and their respective relations, the definitions for rust code generation is more restricted. For the rust generation, the user is binded to the following classes:
|
14
|
+
- Application,
|
15
|
+
- Service, and
|
16
|
+
- RCCNCommand.
|
17
|
+
|
18
|
+
All classes inherit from pymdb's Subsystem class and extend their functionality. This means that an existing pymdb definition can be used to generate rust code by renaming the respective instances. No functionality for pymdb's XTCE generation will be lost.
|
19
|
+
|
20
|
+
A root system may be defined for the satellite.
|
21
|
+
```python
|
22
|
+
root_system = System("Satellite")
|
23
|
+
```
|
24
|
+
|
25
|
+
### Application
|
26
|
+
An application can be defined with the following statement.
|
27
|
+
```python
|
28
|
+
app = Application(system=root_system, name="ExampleApp", apid=42)
|
29
|
+
```
|
30
|
+
It has the obligatory arguments **system**, **name** and **apid**. After all Applications, Services and RCCNCommands are defined, the rust code generator can be called on the application with `app.generate_rccn_code()`.
|
31
|
+
|
32
|
+
### Service
|
33
|
+
|
34
|
+
A service may be defined with the following command.
|
35
|
+
```python
|
36
|
+
service = Service(name="ExampleService", system=app, service_id = 131)
|
37
|
+
```
|
38
|
+
It has the obligatory arguments **name** and **system**. The system corresponds to the application where the service is associated to. Note that each service has one associated app. A service cannot be associated to more than one apps. You may think of the Application-Service-Command structure as a mathematical tree, where merging branches are not allowed. However, you can create multiple instances of the same service and associate them to different applications, or create multiple identical command instances and associate them to different services.
|
39
|
+
|
40
|
+
### RCCNCommand
|
41
|
+
An RCCNCommand can be defined with the following statement.
|
42
|
+
```python
|
43
|
+
RCCNCommand(
|
44
|
+
system=service,
|
45
|
+
assignments={"subtype": 2},
|
46
|
+
name="StopProcess",
|
47
|
+
arguments=[StringArgument("name", encoding=StringEncoding())],
|
48
|
+
)
|
49
|
+
```
|
50
|
+
Obligatory arguments are **system**, **base**, **name** and **arguments**. The latter can be an empty list. The definition must contain a subtype definition in the assignment property, like shown in the example.
|
51
|
+
|
52
|
+
## Output
|
53
|
+
From the python configuration, the `main.rs`, `service.rs`, `command.rs`, `mod.rs`, `Cargo.toml` and `telemetry.rs` files are generated and are structured accordingly:
|
54
|
+
- rccn_usr_example_app/
|
55
|
+
- Cargo.toml
|
56
|
+
- src/
|
57
|
+
- main.rs
|
58
|
+
- example_service/
|
59
|
+
- command.rs
|
60
|
+
- service.rs
|
61
|
+
- mod.rs
|
62
|
+
- telemetry.rs
|
63
|
+
|
64
|
+
The `Cargo.toml` and `mod.rs` files are generated only if the files don't exist already, as their content doesn't depend on the pymdb config. No user changes will be overwritten. The command and service files are created for each service in the application.
|
65
|
+
|
66
|
+
## How It Works
|
67
|
+
The code is generated from templates in the `text_modules` folder. Base templates define the structure for all generated files, respectively. In the templates, two types of keywords can be found and are indicated by `<<KEYWORD>>` encapsulation.
|
68
|
+
|
69
|
+
Keywords beginning with `VAR_` point to a value in the python config created by the user, as shown above. Examples for this are the application identifier (APID) with `<<VAR_APID>>` or the service name with `<<VAR_SERVICE_NAME_UCASE>>`.
|
70
|
+
|
71
|
+
Keywords beginning with `SERVICE_MODULE` or `COMMAND_MODULE` point to other template files in the same folder. The prefix `SERVICE` or `COMMAND` indicates, that this module should be inserted once for every service in the application or once for every command in the service. In this way, the structure of the generated code can be segmented, organized and restructured without any need to change the code generator itself.
|
72
|
+
|
73
|
+
The keyword `<<SERVICE_MODULE_REGISTER_SERVICE>>` for example can be found in the main template and inserts the contents from the `service_module_register_service.txt` file for every service:
|
74
|
+
|
75
|
+
```rust
|
76
|
+
let service<<VAR_SERVICE_ID>> = <<VAR_SERVICE_NAME_UCASE>>::new();
|
77
|
+
app.register_service(service<<VAR_SERVICE_ID>>);
|
78
|
+
```
|
79
|
+
|
80
|
+
The variable keywords are replaced with the corresponding values in the python configuration.
|
81
|
+
|
82
|
+
## Editing Generated Files
|
83
|
+
The code generator allows for the user to make changes to the generated .rs files directly and to keep those changes if the files are regenerated. For this purpose, snapshots of the .rs files are taken, .diff files are created and user changes are rebased to regenerated .rs files. If this behaviour is not desired, it can be turned off with the commands showed below.
|
84
|
+
|
85
|
+
```python
|
86
|
+
app.generate_rccn_code(rebase_changes=False) # Turn off rebaseing of user changes to newly generated .rs files
|
87
|
+
app.generate_rccn_code(snapshots=False, rebase_changes=False) # Turn of rebaseing and snapshot creation
|
88
|
+
```
|
89
|
+
|
90
|
+
Please note that switching off rebasing and snapshot creation means that **existing files will be overwritten** and all changes made prior will be lost.
|
91
|
+
|
92
|
+
### Sequence in File Generation
|
93
|
+
With the snapshot and rebase functionality enabled, the following steps are run through during the generation of every file. For this example it is assumed that the file that is about to be generated already exists in the export directory from a previous generation and user changes where made to the generated file since then.
|
94
|
+
|
95
|
+
1. If a snapshot exists in `.rccn_snapshots/generated/`, a diff file containing the changes from the snapshot to the file as it exists in the export directory is created.
|
96
|
+
2. The current file in the export directory is copied to `.rccn_snapshots/user/`. A subfolder indicates the time of creation.
|
97
|
+
3. The new .rs file is generated based on the pymdb config and exported to the export directory, overwriting the existing file.
|
98
|
+
4. The new .rs file is copied to `.rccn_snapshots/generated/` for future use.
|
99
|
+
5. The new .rs file is patched using the diff file from step 1.
|
100
|
+
|
101
|
+
The sequence from above is changed accordingly if no previous snapshot exists. In the `/generated/` folder, there is only one snapshot per application at one time. And this snapshot always represents the .rs file as it is generated. No user changes to the .rs files are tracked in this snapshot. It is only used to determine the user changes to the .rs file in the export directory since the generation.
|
102
|
+
|
103
|
+
Snapshots of the .rs files in the export directory are stored in `/user/`. These can be used to undo code regeneration if conflicts arise during the patching. Please note that by default, only the last 10 user snapshots are stored. You can change this property with the following command.
|
104
|
+
|
105
|
+
```python
|
106
|
+
app.keep_snapshots = 15 # What ever value you want
|
107
|
+
```
|
108
|
+
|
109
|
+
With the sequence from above, it becomes apperant that changes to the .rs file in the export directory always trump changes to the pymdb config. If for example, a main.rs file is generated for an application with and APID of 42, and this apid is changed in the main.rs file to 45, this change will persist after regenerating from the python config. Even if changes to the pymdb config where made after the changes to the main.rs file.
|
@@ -0,0 +1,27 @@
|
|
1
|
+
[build-system]
|
2
|
+
requires = ["hatchling"]
|
3
|
+
build-backend = "hatchling.build"
|
4
|
+
|
5
|
+
[project]
|
6
|
+
name = "rccn_gen"
|
7
|
+
version = "1.0.0"
|
8
|
+
authors = [
|
9
|
+
{ name="Fabian Krech", email="f.krech@tu-berlin.de" },
|
10
|
+
]
|
11
|
+
description = "A python based generator for RACCOON OS source files in Rust from yamcs-pymdb config files."
|
12
|
+
readme = "README.md"
|
13
|
+
requires-python = ">=3.8"
|
14
|
+
dependencies = [
|
15
|
+
"yamcs-pymdb>=0.1.0",
|
16
|
+
]
|
17
|
+
classifiers = [
|
18
|
+
"Programming Language :: Python :: 3",
|
19
|
+
"Operating System :: OS Independent",
|
20
|
+
]
|
21
|
+
license = "GPL-3.0"
|
22
|
+
license-files = ["LICEN[CS]E*"]
|
23
|
+
|
24
|
+
[project.urls]
|
25
|
+
Homepage = "https://gitlab.com/rccn/pymdb_code_generation"
|
26
|
+
Issues = "https://gitlab.com/rccn/pymdb_code_generation/issues"
|
27
|
+
|