Compare commits
85 Commits
Author | SHA1 | Date | |
---|---|---|---|
d82cecbe6e | |||
14820d63ac
|
|||
3d27711abb
|
|||
1d5db0951e
|
|||
d67987745d | |||
bde03fc9c0
|
|||
be1ac09515 | |||
d1fde6f1e5 | |||
caa843fb1a | |||
11f7ed8436 | |||
88b0c33632 | |||
dd74f6c3ca | |||
783bdd297a
|
|||
bf399c3d91 | |||
06a058fc4d
|
|||
b464182df7
|
|||
a30bccc995
|
|||
980242404a
|
|||
a8545211e8
|
|||
fe439b4d3c | |||
f63f4b9193
|
|||
8d28b321d4
|
|||
8b45dd8bff
|
|||
b20abc5bfb | |||
af1474f10c
|
|||
66db12796b
|
|||
2d08fc0bfa
|
|||
9edc819a97
|
|||
d23cc6834a | |||
33cff5e2d2
|
|||
acbcbbe98f
|
|||
c3b0470aa6
|
|||
1860b754ce
|
|||
68138c6e79
|
|||
e56f8732be | |||
af5e81158c
|
|||
baa1d20556 | |||
1faecb09de
|
|||
1ad621e630
|
|||
5fc3d8de99
|
|||
224328cc85
|
|||
d285b1caec | |||
1f49f0c70d
|
|||
649deac81b
|
|||
7fa1196633
|
|||
1b0a7aeabd
|
|||
412d67494d
|
|||
25377ccfa2
|
|||
6657bf072c
|
|||
7f79ef6c12
|
|||
d72b7d9d66
|
|||
c687b1411c
|
|||
c2bed714dc
|
|||
f9f8f9481f
|
|||
8d6ca602f2
|
|||
c0bd5f572c
|
|||
25c7decb1e
|
|||
cc7b1d3331
|
|||
948f3a1a41
|
|||
8743f59b56
|
|||
2cc4a18c1e | |||
b1fbad39e3 | |||
de57b9da5b | |||
55624f0447 | |||
9841076699
|
|||
f1876681fd | |||
14b558b7f7
|
|||
54a7c3566f
|
|||
011be9837e
|
|||
88161ed125
|
|||
f02230804d | |||
8ddcc37c74 | |||
b50c75c13c | |||
36799ef51d
|
|||
772ef5b323
|
|||
2f8bed4581
|
|||
72def77d40
|
|||
bc1a1774a6 | |||
4b08f5dd5b
|
|||
b0562ea9c7
|
|||
f76cd94535
|
|||
8a1e5b7b99
|
|||
0e208629b0
|
|||
957d756d1e | |||
0a05873f4e |
18
.flake8
18
.flake8
@ -1,18 +0,0 @@
|
||||
[flake8]
|
||||
max-line-length = 100
|
||||
ignore = D203, W503
|
||||
per-file-ignores =
|
||||
*/__init__.py: F401
|
||||
exclude =
|
||||
.git,
|
||||
__pycache__,
|
||||
docs/conf.py,
|
||||
deps
|
||||
old,
|
||||
build,
|
||||
dist,
|
||||
venv
|
||||
max-complexity = 10
|
||||
extend-ignore =
|
||||
# See https://github.com/PyCQA/pycodestyle/issues/373
|
||||
E203,
|
24
.run/CFDP Downlink Test Large.run.xml
Normal file
24
.run/CFDP Downlink Test Large.run.xml
Normal file
@ -0,0 +1,24 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="CFDP Downlink Test Large" type="PythonConfigurationType" factoryName="Python" folderName="CFDP">
|
||||
<module name="tmtc" />
|
||||
<option name="INTERPRETER_OPTIONS" value="" />
|
||||
<option name="PARENT_ENVS" value="true" />
|
||||
<envs>
|
||||
<env name="PYTHONUNBUFFERED" value="1" />
|
||||
</envs>
|
||||
<option name="SDK_HOME" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
<option name="IS_MODULE_SDK" value="true" />
|
||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
|
||||
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/tmtcc.py" />
|
||||
<option name="PARAMETERS" value="cfdp -p /tmp/obsw_update.bin /tmp/obsw_update_copy.bin -d 0.1" />
|
||||
<option name="SHOW_COMMAND_LINE" value="false" />
|
||||
<option name="EMULATE_TERMINAL" value="false" />
|
||||
<option name="MODULE_MODE" value="false" />
|
||||
<option name="REDIRECT_INPUT" value="false" />
|
||||
<option name="INPUT_FILE" value="" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
24
.run/CFDP Downlink Test Larger.run.xml
Normal file
24
.run/CFDP Downlink Test Larger.run.xml
Normal file
@ -0,0 +1,24 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="CFDP Downlink Test Larger" type="PythonConfigurationType" factoryName="Python" folderName="CFDP">
|
||||
<module name="tmtc" />
|
||||
<option name="INTERPRETER_OPTIONS" value="" />
|
||||
<option name="PARENT_ENVS" value="true" />
|
||||
<envs>
|
||||
<env name="PYTHONUNBUFFERED" value="1" />
|
||||
</envs>
|
||||
<option name="SDK_HOME" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
<option name="IS_MODULE_SDK" value="true" />
|
||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
|
||||
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/tmtcc.py" />
|
||||
<option name="PARAMETERS" value="cfdp -p /tmp/fake_5kb.bin /tmp/fake_5kb_copy.bin -d 0.1" />
|
||||
<option name="SHOW_COMMAND_LINE" value="false" />
|
||||
<option name="EMULATE_TERMINAL" value="false" />
|
||||
<option name="MODULE_MODE" value="false" />
|
||||
<option name="REDIRECT_INPUT" value="false" />
|
||||
<option name="INPUT_FILE" value="" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
24
.run/CFDP Downlink Test.run.xml
Normal file
24
.run/CFDP Downlink Test.run.xml
Normal file
@ -0,0 +1,24 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="CFDP Downlink Test" type="PythonConfigurationType" factoryName="Python" folderName="CFDP">
|
||||
<module name="tmtc" />
|
||||
<option name="INTERPRETER_OPTIONS" value="" />
|
||||
<option name="PARENT_ENVS" value="true" />
|
||||
<envs>
|
||||
<env name="PYTHONUNBUFFERED" value="1" />
|
||||
</envs>
|
||||
<option name="SDK_HOME" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
<option name="IS_MODULE_SDK" value="true" />
|
||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
|
||||
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/tmtcc.py" />
|
||||
<option name="PARAMETERS" value="cfdp -p /tmp/hello.txt /tmp/hello2.txt -d 0.1" />
|
||||
<option name="SHOW_COMMAND_LINE" value="false" />
|
||||
<option name="EMULATE_TERMINAL" value="false" />
|
||||
<option name="MODULE_MODE" value="false" />
|
||||
<option name="REDIRECT_INPUT" value="false" />
|
||||
<option name="INPUT_FILE" value="" />
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
52
CHANGELOG.md
52
CHANGELOG.md
@ -10,6 +10,58 @@ list yields a list of all related PRs for each release.
|
||||
|
||||
# [unreleased]
|
||||
|
||||
# [v5.7.0] 2023-10-10
|
||||
|
||||
- `tmtccmd` v6.0.0
|
||||
- `spacepackets` v18.0.0
|
||||
|
||||
## Added
|
||||
|
||||
- Power controller commands.
|
||||
|
||||
# [v5.6.0] 2023-09-14
|
||||
|
||||
- `tmtccmd` v6.0.0
|
||||
- `spacepackets` v18.0.0
|
||||
|
||||
## Added
|
||||
|
||||
- CFDP file downlink support.
|
||||
|
||||
# [v5.5.1] 2023-09-12
|
||||
|
||||
## Fixed
|
||||
|
||||
- Some API usage fixes related to `tmtccmd` update.
|
||||
|
||||
# [v5.5.0] 2023-09-12
|
||||
|
||||
- Version is not specfied dynamically anymore and can be updated in `pyproject.toml`
|
||||
- New events and returnvalues
|
||||
- Bump `tmtccmd` to v6.0.0rc0
|
||||
|
||||
# [v5.4.3] 2023-08-15
|
||||
|
||||
## Added
|
||||
|
||||
- PLOC SUPV HK parsing.
|
||||
|
||||
# [v5.4.2] 2023-08-15
|
||||
|
||||
## Added
|
||||
|
||||
- New NONE entry for PL PCDU submode enum.
|
||||
|
||||
# [v5.4.1] 2023-08-15
|
||||
|
||||
## Added
|
||||
|
||||
- New event TLE_TOO_OLD
|
||||
|
||||
## Changed
|
||||
|
||||
- PL Subsystem mode ID is int enum now.
|
||||
|
||||
# [v5.4.0] 2023-08-15
|
||||
|
||||
## Added
|
||||
|
43
README.md
43
README.md
@ -4,7 +4,7 @@ This application can be used to test the EIVE On-Board Software. Furthermore, it
|
||||
also be used to retrieve all sorts of telemetry data like housekeeping data.
|
||||
|
||||
It is recommended to use this application with a virtual environment.
|
||||
The [virtual environemnt](#venv) chapter describes how to set one up. The [requirements](#reqs)
|
||||
The [virtual environment](#venv) chapter describes how to set one up. The [requirements](#reqs)
|
||||
describes how to install all required packages.
|
||||
|
||||
The configuration file can currently be found at `tmtc_conf.json`. It caches settings
|
||||
@ -61,42 +61,57 @@ Run GUI mode
|
||||
# <a id="reqs"></a> Install requirements
|
||||
|
||||
There are two ways to install the requirements. One is to install the primary dependency
|
||||
`tmtccmd` interactively. This is the recommended way
|
||||
`tmtccmd` interactively.
|
||||
|
||||
Assuming you are running in a virtual environment:
|
||||
## Installing via PyPI
|
||||
|
||||
1. Install `tmtccmd` for virtual environment. `-e` for interactive installation.
|
||||
It is recommended to install `eive-tmtc` itself interactively, which also installs
|
||||
all required dependencies.
|
||||
|
||||
```sh
|
||||
cd deps/tmtccmd
|
||||
pip install -e .[gui]
|
||||
```
|
||||
```sh
|
||||
pip install -e .
|
||||
```
|
||||
|
||||
Alternatively you can also install the packages from PyPI completely, but the risk of
|
||||
incompatibilities will be high there
|
||||
If you only want to install all dependencies:
|
||||
|
||||
```sh
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
## Install interactively
|
||||
|
||||
Clone the dependency first inside the `deps` folder
|
||||
|
||||
```sh
|
||||
cd deps
|
||||
./install_tmtccmd.sh
|
||||
```
|
||||
|
||||
Then you can install `tmtccmd` interactively
|
||||
|
||||
```sh
|
||||
cd tmtccmd
|
||||
pip install -e .
|
||||
```
|
||||
|
||||
# Run Linter
|
||||
|
||||
Can be used to quickly check validity of script. Install `flake8` first
|
||||
|
||||
```sh
|
||||
python3 -m pip install flake8
|
||||
python3 -m pip install ruff
|
||||
```
|
||||
|
||||
or on Windows
|
||||
|
||||
```sh
|
||||
py -m pip install flake8
|
||||
py -m pip install ruff
|
||||
```
|
||||
|
||||
and then run the `lint.py` script
|
||||
and then run it
|
||||
|
||||
```sh
|
||||
./lint.py
|
||||
ruff .
|
||||
```
|
||||
|
||||
# Run Auto-Formatter
|
||||
|
@ -1,13 +1,6 @@
|
||||
__version__ = "5.4.0"
|
||||
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
SW_NAME = "eive-tmtc"
|
||||
VERSION_MAJOR = 5
|
||||
VERSION_MINOR = 4
|
||||
VERSION_REVISION = 0
|
||||
|
||||
EIVE_TMTC_ROOT = Path(__file__).parent
|
||||
PACKAGE_ROOT = EIVE_TMTC_ROOT.parent
|
||||
|
||||
|
0
eive_tmtc/cfdp/__init__.py
Normal file
0
eive_tmtc/cfdp/__init__.py
Normal file
20
eive_tmtc/cfdp/fault_handler.py
Normal file
20
eive_tmtc/cfdp/fault_handler.py
Normal file
@ -0,0 +1,20 @@
|
||||
import logging
|
||||
|
||||
from spacepackets.cfdp import ConditionCode
|
||||
from tmtccmd.cfdp.mib import DefaultFaultHandlerBase
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class EiveCfdpFaultHandler(DefaultFaultHandlerBase):
|
||||
def notice_of_suspension_cb(self, cond: ConditionCode):
|
||||
_LOGGER.info(f"Received notice of suspension: {cond!r}")
|
||||
|
||||
def notice_of_cancellation_cb(self, cond: ConditionCode):
|
||||
_LOGGER.info(f"Received notice of cancellation: {cond!r}")
|
||||
|
||||
def abandoned_cb(self, cond: ConditionCode):
|
||||
_LOGGER.info(f"Abandoned transaction: {cond!r}")
|
||||
|
||||
def ignore_cb(self, cond: ConditionCode):
|
||||
_LOGGER.info(f"Ignored transaction: {cond!r}")
|
27
eive_tmtc/cfdp/tm.py
Normal file
27
eive_tmtc/cfdp/tm.py
Normal file
@ -0,0 +1,27 @@
|
||||
import logging
|
||||
|
||||
from eive_tmtc.config.definitions import CFDP_APID
|
||||
from spacepackets.ccsds import SPACE_PACKET_HEADER_SIZE
|
||||
from spacepackets.cfdp import PduFactory, PduType, DirectiveType
|
||||
from tmtccmd.cfdp.handler import CfdpInCcsdsHandler
|
||||
from tmtccmd.tm import SpecificApidHandlerBase
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class CfdpInCcsdsWrapper(SpecificApidHandlerBase):
|
||||
def __init__(self, cfdp_in_ccsds_handler: CfdpInCcsdsHandler):
|
||||
super().__init__(CFDP_APID, None)
|
||||
self.handler = cfdp_in_ccsds_handler
|
||||
|
||||
def handle_tm(self, packet: bytes, _user_args: any):
|
||||
# Ignore the space packet header. Its only purpose is to use the same protocol and
|
||||
# have a seaprate APID for space packets. If this function is called, the APID is correct.
|
||||
pdu = packet[SPACE_PACKET_HEADER_SIZE:]
|
||||
pdu_base = PduFactory.from_raw(pdu)
|
||||
if pdu_base.pdu_type == PduType.FILE_DATA:
|
||||
_LOGGER.info("Received File Data PDU")
|
||||
else:
|
||||
directive_type = DirectiveType(pdu_base.directive_type)
|
||||
_LOGGER.info(f"Received File Directive PDU with type {directive_type!r}")
|
||||
self.handler.insert_pdu_packet(pdu_base)
|
58
eive_tmtc/cfdp/user.py
Normal file
58
eive_tmtc/cfdp/user.py
Normal file
@ -0,0 +1,58 @@
|
||||
import logging
|
||||
|
||||
from spacepackets.cfdp import ConditionCode
|
||||
from tmtccmd.cfdp import CfdpUserBase, TransactionId
|
||||
from tmtccmd.cfdp.user import (
|
||||
TransactionFinishedParams,
|
||||
MetadataRecvParams,
|
||||
FileSegmentRecvdParams,
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class EiveCfdpUser(CfdpUserBase):
|
||||
def transaction_indication(self, transaction_id: TransactionId):
|
||||
_LOGGER.info(f"CFDP User: Start of File {transaction_id}")
|
||||
|
||||
def eof_sent_indication(self, transaction_id: TransactionId):
|
||||
_LOGGER.info(f"CFDP User: EOF sent for {transaction_id}")
|
||||
|
||||
def transaction_finished_indication(self, params: TransactionFinishedParams):
|
||||
_LOGGER.info(f"CFDP User: {params.transaction_id} finished")
|
||||
_LOGGER.info(f"Delivery Code: {params.delivery_code!r}")
|
||||
_LOGGER.info(f"Condition code: {params.condition_code!r}")
|
||||
_LOGGER.info(f"File delivery status: {params.delivery_code!r}")
|
||||
|
||||
def metadata_recv_indication(self, params: MetadataRecvParams):
|
||||
pass
|
||||
|
||||
def file_segment_recv_indication(self, params: FileSegmentRecvdParams):
|
||||
_LOGGER.info(
|
||||
f"CFDP User: Received File Data PDU for {params.transaction_id} | Offset:"
|
||||
f" {params.offset} | Segment Length: {params.length}"
|
||||
)
|
||||
|
||||
def report_indication(self, transaction_id: TransactionId, status_report: any):
|
||||
pass
|
||||
|
||||
def suspended_indication(
|
||||
self, transaction_id: TransactionId, cond_code: ConditionCode
|
||||
):
|
||||
pass
|
||||
|
||||
def resumed_indication(self, transaction_id: TransactionId, progress: int):
|
||||
pass
|
||||
|
||||
def fault_indication(
|
||||
self, transaction_id: TransactionId, cond_code: ConditionCode, progress: int
|
||||
):
|
||||
pass
|
||||
|
||||
def abandoned_indication(
|
||||
self, transaction_id: TransactionId, cond_code: ConditionCode, progress: int
|
||||
):
|
||||
pass
|
||||
|
||||
def eof_recv_indication(self, transaction_id: TransactionId):
|
||||
_LOGGER.info(f"CFDP User: EOF received for {transaction_id}")
|
@ -76,3 +76,5 @@ class CustomServiceList(str, enum.Enum):
|
||||
SCEX = "scex"
|
||||
TM_STORE = "tm_store"
|
||||
SYSTEM = "system"
|
||||
PWR_CTRL = "pwr_ctrl"
|
||||
EPS_SS = "eps_subsystem"
|
||||
|
@ -94,10 +94,16 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
11205;0x2bc5;MEKF_AUTOMATIC_RESET;INFO;MEKF performed an automatic reset after detection of nonfinite values.;mission/acs/defs.h
|
||||
11206;0x2bc6;MEKF_INVALID_MODE_VIOLATION;HIGH;MEKF was not able to compute a solution during any pointing ACS mode for a prolonged time.;mission/acs/defs.h
|
||||
11207;0x2bc7;SAFE_MODE_CONTROLLER_FAILURE;HIGH;The ACS safe mode controller was not able to compute a solution and has failed. P1: Missing information about magnetic field, P2: Missing information about rotational rate;mission/acs/defs.h
|
||||
11208;0x2bc8;TLE_TOO_OLD;INFO;The TLE for the SGP4 Propagator has become too old.;mission/acs/defs.h
|
||||
11300;0x2c24;SWITCH_CMD_SENT;INFO;Indicates that a FSFW object requested setting a switch P1: 1 if on was requested, 0 for off | P2: Switch Index;mission/power/defs.h
|
||||
11301;0x2c25;SWITCH_HAS_CHANGED;INFO;Indicated that a switch state has changed P1: New switch state, 1 for on, 0 for off | P2: Switch Index;mission/power/defs.h
|
||||
11302;0x2c26;SWITCHING_Q7S_DENIED;MEDIUM;No description;mission/power/defs.h
|
||||
11303;0x2c27;FDIR_REACTION_IGNORED;MEDIUM;No description;mission/power/defs.h
|
||||
11304;0x2c28;DATASET_READ_FAILED;INFO;The dataset read for the inputs of the Power Controller has failed.;mission/power/defs.h
|
||||
11305;0x2c29;VOLTAGE_OUT_OF_BOUNDS;HIGH;No description;mission/power/defs.h
|
||||
11306;0x2c2a;TIMEDELTA_OUT_OF_BOUNDS;LOW;Time difference for Coulomb Counter was too large. P1: time in s * 10;mission/power/defs.h
|
||||
11307;0x2c2b;POWER_LEVEL_LOW;HIGH;The State of Charge is below the limit for payload use. Setting Payload to faulty.;mission/power/defs.h
|
||||
11308;0x2c2c;POWER_LEVEL_CRITICAL;HIGH;The State of Charge is below the limit for higher modes. Setting Reaction Wheels to faulty.;mission/power/defs.h
|
||||
11400;0x2c88;GPIO_PULL_HIGH_FAILED;LOW;No description;mission/tcs/HeaterHandler.h
|
||||
11401;0x2c89;GPIO_PULL_LOW_FAILED;LOW;No description;mission/tcs/HeaterHandler.h
|
||||
11402;0x2c8a;HEATER_WENT_ON;INFO;No description;mission/tcs/HeaterHandler.h
|
||||
@ -121,6 +127,8 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
11604;0x2d54;MPSOC_HANDLER_CRC_FAILURE;LOW;PLOC reply has invalid crc;linux/payload/PlocMpsocHandler.h
|
||||
11605;0x2d55;MPSOC_HANDLER_SEQUENCE_COUNT_MISMATCH;LOW;Packet sequence count in received space packet does not match expected count P1: Expected sequence count P2: Received sequence count;linux/payload/PlocMpsocHandler.h
|
||||
11606;0x2d56;MPSOC_SHUTDOWN_FAILED;HIGH;Supervisor fails to shutdown MPSoC. Requires to power off the PLOC and thus also to shutdown the supervisor.;linux/payload/PlocMpsocHandler.h
|
||||
11607;0x2d57;SUPV_NOT_ON;LOW;SUPV not on for boot or shutdown process. P1: 0 for OFF transition, 1 for ON transition.;linux/payload/PlocMpsocHandler.h
|
||||
11608;0x2d58;SUPV_REPLY_TIMEOUT;LOW;No description;linux/payload/PlocMpsocHandler.h
|
||||
11701;0x2db5;SELF_TEST_I2C_FAILURE;LOW;Get self test result returns I2C failure P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h
|
||||
11702;0x2db6;SELF_TEST_SPI_FAILURE;LOW;Get self test result returns SPI failure. This concerns the MTM connectivity. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h
|
||||
11703;0x2db7;SELF_TEST_ADC_FAILURE;LOW;Get self test result returns failure in measurement of current and temperature. P1: Indicates on which axis the failure occurred. 0 -> INIT, 1 -> +X, 2 -> -X, 3 -> +Y, 4 -> -Y, 5 -> +Z, 6 -> -Z, 7 -> FINA;mission/acs/ImtqHandler.h
|
||||
@ -302,3 +310,5 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
14312;0x37e8;DUMP_MISC_CANCELLED;LOW;P1: Number of dumped packets. P2: Total dumped bytes.;mission/persistentTmStoreDefs.h
|
||||
14313;0x37e9;DUMP_HK_CANCELLED;LOW;P1: Number of dumped packets. P2: Total dumped bytes.;mission/persistentTmStoreDefs.h
|
||||
14314;0x37ea;DUMP_CFDP_CANCELLED;LOW;P1: Number of dumped packets. P2: Total dumped bytes.;mission/persistentTmStoreDefs.h
|
||||
14500;0x38a4;TEMPERATURE_ALL_ONES_START;MEDIUM;Detected invalid values, starting invalid message counting;mission/acs/SusHandler.h
|
||||
14501;0x38a5;TEMPERATURE_ALL_ONES_RECOVERY;INFO;Detected valid values again, resetting invalid message counter. P1: Invalid message counter.;mission/acs/SusHandler.h
|
||||
|
|
@ -136,6 +136,7 @@ ACS_SUBSYSTEM_ID = bytes([0x73, 0x01, 0x00, 0x01])
|
||||
PL_SUBSYSTEM_ID = bytes([0x73, 0x01, 0x00, 0x02])
|
||||
TCS_SUBSYSTEM_ID = bytes([0x73, 0x01, 0x00, 0x03])
|
||||
COM_SUBSYSTEM_ID = bytes([0x73, 0x01, 0x00, 0x04])
|
||||
EPS_SUBSYSTEM_ID = bytes([0x73, 0x01, 0x00, 0x05])
|
||||
|
||||
# Legacy names, kept for backwards compatibility
|
||||
ACS_BOARD_ASS_ID = bytes([0x73, 0x00, 0x00, 0x01])
|
||||
@ -157,6 +158,7 @@ STR_ASSEMBLY = bytes([0x73, 0x00, 0x00, 0x09])
|
||||
TCS_CONTROLLER = bytes([0x43, 0x40, 0x00, 0x01])
|
||||
ACS_CONTROLLER = bytes([0x43, 0x00, 0x00, 0x02])
|
||||
CORE_CONTROLLER_ID = bytes([0x43, 0x00, 0x00, 0x03])
|
||||
PWR_CONTROLLER = bytes([0x43, 0x00, 0x00, 0x04])
|
||||
|
||||
MISC_TM_STORE = bytes([0x73, 0x02, 0x00, 0x01])
|
||||
OK_TM_STORE = bytes([0x73, 0x02, 0x00, 0x02])
|
||||
|
@ -1,6 +1,7 @@
|
||||
0x00005060;P60DOCK_TEST_TASK
|
||||
0x43000002;ACS_CONTROLLER
|
||||
0x43000003;CORE_CONTROLLER
|
||||
0x43000004;POWER_CONTROLLER
|
||||
0x43000006;GLOBAL_JSON_CFG
|
||||
0x43400001;THERMAL_CONTROLLER
|
||||
0x44120006;MGM_0_LIS3_HANDLER
|
||||
@ -161,6 +162,7 @@
|
||||
0x73010002;PL_SUBSYSTEM
|
||||
0x73010003;TCS_SUBSYSTEM
|
||||
0x73010004;COM_SUBSYSTEM
|
||||
0x73010005;EPS_SUBSYSTEM
|
||||
0x73020001;MISC_TM_STORE
|
||||
0x73020002;OK_TM_STORE
|
||||
0x73020003;NOT_OK_TM_STORE
|
||||
|
|
@ -210,6 +210,7 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path
|
||||
0x27a8;DHI_NoReplyExpected;No description;168;DEVICE_HANDLER_IF;fsfw/src/fsfw/devicehandlers/DeviceHandlerIF.h
|
||||
0x27a9;DHI_NonOpTemperature;No description;169;DEVICE_HANDLER_IF;fsfw/src/fsfw/devicehandlers/DeviceHandlerIF.h
|
||||
0x27aa;DHI_CommandNotImplemented;No description;170;DEVICE_HANDLER_IF;fsfw/src/fsfw/devicehandlers/DeviceHandlerIF.h
|
||||
0x27ab;DHI_NonOpStateOfCharge;No description;171;DEVICE_HANDLER_IF;fsfw/src/fsfw/devicehandlers/DeviceHandlerIF.h
|
||||
0x27b0;DHI_ChecksumError;No description;176;DEVICE_HANDLER_IF;fsfw/src/fsfw/devicehandlers/DeviceHandlerIF.h
|
||||
0x27b1;DHI_LengthMissmatch;No description;177;DEVICE_HANDLER_IF;fsfw/src/fsfw/devicehandlers/DeviceHandlerIF.h
|
||||
0x27b2;DHI_InvalidData;No description;178;DEVICE_HANDLER_IF;fsfw/src/fsfw/devicehandlers/DeviceHandlerIF.h
|
||||
|
|
@ -60,3 +60,4 @@
|
||||
142;COM_SUBSYSTEM
|
||||
143;PERSISTENT_TM_STORE
|
||||
144;SYRLINKS_COM
|
||||
145;SUS_HANDLER
|
||||
|
|
163
eive_tmtc/pus_tc/tc_handler.py
Normal file
163
eive_tmtc/pus_tc/tc_handler.py
Normal file
@ -0,0 +1,163 @@
|
||||
import logging
|
||||
from typing import cast
|
||||
|
||||
from eive_tmtc.config.definitions import (
|
||||
CFDP_REMOTE_ENTITY_ID,
|
||||
PUS_APID,
|
||||
CFDP_LOCAL_ENTITY_ID,
|
||||
)
|
||||
from eive_tmtc.pus_tc.procedure_packer import handle_default_procedure
|
||||
from tmtccmd import TcHandlerBase, ProcedureWrapper
|
||||
from tmtccmd.cfdp.defs import CfdpRequestType
|
||||
from tmtccmd.cfdp.handler import CfdpInCcsdsHandler
|
||||
from tmtccmd.logging import get_current_time_string
|
||||
from tmtccmd.logging.pus import RawTmtcTimedLogWrapper
|
||||
from tmtccmd.tc import (
|
||||
DefaultPusQueueHelper,
|
||||
QueueWrapper,
|
||||
FeedWrapper,
|
||||
TcProcedureType,
|
||||
SendCbParams,
|
||||
TcQueueEntryType,
|
||||
)
|
||||
from tmtccmd.config.cfdp import generic_cfdp_params_to_put_request
|
||||
from spacepackets.ecss import PusVerificator
|
||||
from tmtccmd.util import FileSeqCountProvider
|
||||
from spacepackets.cfdp import PduHolder, DirectiveType
|
||||
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class TcHandler(TcHandlerBase):
|
||||
def __init__(
|
||||
self,
|
||||
seq_count_provider: FileSeqCountProvider,
|
||||
cfdp_in_ccsds_handler: CfdpInCcsdsHandler,
|
||||
pus_verificator: PusVerificator,
|
||||
high_level_file_logger: logging.Logger,
|
||||
raw_pus_logger: RawTmtcTimedLogWrapper,
|
||||
gui: bool,
|
||||
):
|
||||
super().__init__()
|
||||
self.cfdp_handler_started = False
|
||||
self.seq_count_provider = seq_count_provider
|
||||
self.pus_verificator = pus_verificator
|
||||
self.high_level_file_logger = high_level_file_logger
|
||||
self.pus_raw_logger = raw_pus_logger
|
||||
self.gui = gui
|
||||
self.proxy_op = True
|
||||
self.queue_helper = DefaultPusQueueHelper(
|
||||
queue_wrapper=QueueWrapper.empty(),
|
||||
default_pus_apid=PUS_APID,
|
||||
seq_cnt_provider=seq_count_provider,
|
||||
pus_verificator=pus_verificator,
|
||||
tc_sched_timestamp_len=4,
|
||||
)
|
||||
self.cfdp_in_ccsds_handler = cfdp_in_ccsds_handler
|
||||
|
||||
def cfdp_done(self) -> bool:
|
||||
if self.cfdp_handler_started:
|
||||
if (
|
||||
not self.cfdp_in_ccsds_handler.put_request_pending()
|
||||
and not self.proxy_op
|
||||
):
|
||||
self.cfdp_handler_started = False
|
||||
return True
|
||||
return False
|
||||
|
||||
def feed_cb(self, info: ProcedureWrapper, wrapper: FeedWrapper):
|
||||
self.queue_helper.queue_wrapper = wrapper.queue_wrapper
|
||||
if info.proc_type == TcProcedureType.DEFAULT:
|
||||
handle_default_procedure(self, info.to_def_procedure(), self.queue_helper)
|
||||
elif info.proc_type == TcProcedureType.CFDP:
|
||||
self.handle_cfdp_procedure(info)
|
||||
|
||||
def send_cb(self, send_params: SendCbParams):
|
||||
entry_helper = send_params.entry
|
||||
if entry_helper.is_tc:
|
||||
if entry_helper.entry_type == TcQueueEntryType.PUS_TC:
|
||||
pus_tc_wrapper = entry_helper.to_pus_tc_entry()
|
||||
# pus_tc_wrapper.pus_tc.apid = PUS_APID
|
||||
raw_tc = pus_tc_wrapper.pus_tc.pack()
|
||||
self.pus_raw_logger.log_tc(pus_tc_wrapper.pus_tc)
|
||||
tc_info_string = f"Sent {pus_tc_wrapper.pus_tc}"
|
||||
_LOGGER.info(tc_info_string)
|
||||
self.high_level_file_logger.info(
|
||||
f"{get_current_time_string(True)}: {tc_info_string}"
|
||||
)
|
||||
# with open("tc.bin", "wb") as of:
|
||||
# of.write(raw_tc)
|
||||
send_params.com_if.send(raw_tc)
|
||||
elif entry_helper.entry_type == TcQueueEntryType.CCSDS_TC:
|
||||
cfdp_packet_in_ccsds = entry_helper.to_space_packet_entry()
|
||||
send_params.com_if.send(cfdp_packet_in_ccsds.space_packet.pack())
|
||||
# TODO: Log raw CFDP packets similarly to how PUS packets are logged.
|
||||
# - Log full raw format including space packet wrapper
|
||||
# - Log context information: Transaction ID, and PDU type and directive
|
||||
# Could re-use file logger. Should probably do that
|
||||
# print(f"sending packet: [{cfdp_packet_in_ccsds.space_packet.pack()}]")
|
||||
# with open(f"cfdp_packet_{self.cfdp_counter}", "wb") as of:
|
||||
# of.write(cfdp_packet_in_ccsds.space_packet.pack())
|
||||
# self.cfdp_counter += 1
|
||||
elif entry_helper.entry_type == TcQueueEntryType.LOG:
|
||||
log_entry = entry_helper.to_log_entry()
|
||||
_LOGGER.info(log_entry.log_str)
|
||||
self.high_level_file_logger.info(log_entry.log_str)
|
||||
|
||||
def handle_cfdp_procedure(self, info: ProcedureWrapper):
|
||||
cfdp_procedure = info.to_cfdp_procedure()
|
||||
if cfdp_procedure.cfdp_request_type == CfdpRequestType.PUT:
|
||||
if (
|
||||
not self.cfdp_in_ccsds_handler.put_request_pending()
|
||||
and not self.cfdp_handler_started
|
||||
):
|
||||
put_req_cfg_wrapper = cfdp_procedure.request_wrapper.to_put_request()
|
||||
if put_req_cfg_wrapper.cfg.proxy_op:
|
||||
self.proxy_op = True
|
||||
put_req = generic_cfdp_params_to_put_request(
|
||||
params=put_req_cfg_wrapper.cfg,
|
||||
local_id=CFDP_LOCAL_ENTITY_ID,
|
||||
remote_id=CFDP_REMOTE_ENTITY_ID,
|
||||
dest_id_proxy_put_req=CFDP_LOCAL_ENTITY_ID,
|
||||
)
|
||||
_LOGGER.info(
|
||||
f"CFDP: Starting file put request with parameters:\n{put_req}"
|
||||
)
|
||||
self.cfdp_in_ccsds_handler.cfdp_handler.put_request(put_req)
|
||||
self.cfdp_handler_started = True
|
||||
|
||||
for source_pair, dest_pair in self.cfdp_in_ccsds_handler:
|
||||
pdu, sp = source_pair
|
||||
pdu = cast(PduHolder, pdu)
|
||||
if pdu.is_file_directive:
|
||||
if pdu.pdu_directive_type == DirectiveType.METADATA_PDU:
|
||||
metadata = pdu.to_metadata_pdu()
|
||||
self.queue_helper.add_log_cmd(
|
||||
"CFDP Source: Sending Metadata PDU for file with size "
|
||||
f"{metadata.file_size}"
|
||||
)
|
||||
elif pdu.pdu_directive_type == DirectiveType.EOF_PDU:
|
||||
self.queue_helper.add_log_cmd(
|
||||
"CFDP Source: Sending EOF PDU"
|
||||
)
|
||||
else:
|
||||
fd_pdu = pdu.to_file_data_pdu()
|
||||
self.queue_helper.add_log_cmd(
|
||||
"CFDP Source: Sending File Data PDU for segment at offset "
|
||||
f"{fd_pdu.offset} with length {len(fd_pdu.file_data)}"
|
||||
)
|
||||
self.queue_helper.add_ccsds_tc(sp)
|
||||
self.cfdp_in_ccsds_handler.confirm_source_packet_sent()
|
||||
self.cfdp_in_ccsds_handler.source_handler.state_machine()
|
||||
|
||||
def queue_finished_cb(self, info: ProcedureWrapper):
|
||||
if info is not None:
|
||||
if info.proc_type == TcQueueEntryType.PUS_TC:
|
||||
def_proc = info.to_def_procedure()
|
||||
_LOGGER.info(
|
||||
f"Finished queue for service {def_proc.service} and op code"
|
||||
f" {def_proc.op_code}"
|
||||
)
|
||||
elif info.proc_type == TcProcedureType.CFDP:
|
||||
_LOGGER.info("Finished CFDP queue")
|
@ -37,12 +37,13 @@ def handle_event_packet( # noqa C901: Complexity okay here
|
||||
else:
|
||||
obj_name = obj_id_obj.name
|
||||
generic_event_string = (
|
||||
f"Object {obj_name} generated Event {info.name} (ID: {event_def.event_id:#04x}) "
|
||||
f"at {tm.time_provider.as_date_time()}"
|
||||
f"Object {obj_name} generated Event {info.name} (ID: {event_def.event_id:#04x})"
|
||||
f" at {tm.time_provider.as_date_time()}"
|
||||
)
|
||||
_LOGGER.info(generic_event_string)
|
||||
pw.file_logger.info(
|
||||
f"{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}: {generic_event_string}"
|
||||
f"{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}:"
|
||||
f" {generic_event_string}"
|
||||
)
|
||||
specific_handler = False
|
||||
if info.name == "MODE_TRANSITION_FAILED":
|
||||
@ -54,8 +55,8 @@ def handle_event_packet( # noqa C901: Complexity okay here
|
||||
if info.name == "SUPV_UPDATE_PROGRESS" or info.name == "WRITE_MEMORY_FAILED":
|
||||
additional_event_info = f"Additional info: {info.info}"
|
||||
context = (
|
||||
f"Progress Percent: {event_def.param1 >> 24 & 0xff} | "
|
||||
f"Sequence Count: {event_def.param1 & 0xffff} | Bytes Written: {event_def.param2}"
|
||||
f"Progress Percent: {event_def.param1 >> 24 & 0xff} | Sequence Count:"
|
||||
f" {event_def.param1 & 0xffff} | Bytes Written: {event_def.param2}"
|
||||
)
|
||||
pw.dlog(additional_event_info)
|
||||
pw.dlog(context)
|
||||
|
@ -188,5 +188,5 @@ def handle_regular_hk_print( # noqa C901: Complexity okay here
|
||||
else:
|
||||
_LOGGER.info(
|
||||
f"Service 3 TM: Parsing for object {object_id} and set ID {set_id} "
|
||||
f"has not been implemented."
|
||||
"has not been implemented."
|
||||
)
|
||||
|
@ -87,7 +87,8 @@ def pus_factory_hook( # noqa C901 : Complexity okay here
|
||||
# TODO: Could improve display further by actually displaying a matrix as a
|
||||
# matrix using row and column information
|
||||
pw.dlog(
|
||||
f"Received vector or matrix data: {param.param_raw.hex(sep=',')}"
|
||||
"Received vector or matrix data:"
|
||||
f" {param.param_raw.hex(sep=',')}"
|
||||
)
|
||||
except ValueError as e:
|
||||
pw.dlog(f"received {e} when trying to parse parameters")
|
||||
|
@ -48,7 +48,7 @@ def generic_retval_printout(
|
||||
if retval_info is None:
|
||||
raw_err = retval
|
||||
return [
|
||||
f"No returnvalue information found for error code with "
|
||||
"No returnvalue information found for error code with "
|
||||
f"subsystem ID {(raw_err >> 8) & 0xff} and unique ID {raw_err & 0xff}"
|
||||
]
|
||||
else:
|
||||
@ -58,9 +58,9 @@ def generic_retval_printout(
|
||||
)
|
||||
string_list = [retval_string]
|
||||
if p1:
|
||||
error_param_1_str = f"Error Parameter 1: hex {p1:#010x} " f"dec {p1} "
|
||||
error_param_1_str = f"Error Parameter 1: hex {p1:#010x} dec {p1} "
|
||||
string_list.append(error_param_1_str)
|
||||
if p2:
|
||||
error_param_2_str = f"Error Parameter 2: hex {p2:#010x} " f"dec {p2}"
|
||||
error_param_2_str = f"Error Parameter 2: hex {p2:#010x} dec {p2}"
|
||||
string_list.append(error_param_2_str)
|
||||
return string_list
|
||||
|
@ -571,8 +571,8 @@ def pack_acs_ctrl_command(p: ServiceProviderParams): # noqa C901
|
||||
def set_acs_ctrl_param_scalar(q: DefaultPusQueueHelper):
|
||||
pt = int(
|
||||
input(
|
||||
'Specify parameter type to set {0: "uint8", 1: "uint16", 2: "int32", 3: "float", '
|
||||
'4: "double"}: '
|
||||
'Specify parameter type to set {0: "uint8", 1: "uint16", 2: "int32", 3:'
|
||||
' "float", 4: "double"}: '
|
||||
)
|
||||
)
|
||||
sid = int(input("Specify parameter struct ID to set: "))
|
||||
@ -808,8 +808,8 @@ def handle_acs_ctrl_sus_raw_data(pw: PrintWrapper, hk_data: bytes):
|
||||
def handle_acs_ctrl_sus_processed_data(pw: PrintWrapper, hk_data: bytes):
|
||||
if len(hk_data) < 3 * 4 * 12 + 3 * 8 * 3:
|
||||
pw.dlog(
|
||||
f"SUS Processed dataset with size {len(hk_data)} does not have expected size"
|
||||
f" of {3 * 4 * 12 + 3 * 8 * 3} bytes"
|
||||
f"SUS Processed dataset with size {len(hk_data)} does not have expected"
|
||||
f" size of {3 * 4 * 12 + 3 * 8 * 3} bytes"
|
||||
)
|
||||
return
|
||||
current_idx = 0
|
||||
@ -846,7 +846,8 @@ def handle_raw_mgm_data(pw: PrintWrapper, hk_data: bytes):
|
||||
|
||||
if len(hk_data) < 61:
|
||||
pw.dlog(
|
||||
f"ACS CTRL HK: MGM HK data with length {len(hk_data)} shorter than expected 61 bytes"
|
||||
f"ACS CTRL HK: MGM HK data with length {len(hk_data)} shorter than expected"
|
||||
" 61 bytes"
|
||||
)
|
||||
pw.dlog(f"Raw Data: {hk_data.hex(sep=',')}")
|
||||
return
|
||||
@ -1018,7 +1019,7 @@ def handle_gps_data_processed(pw: PrintWrapper, hk_data: bytes):
|
||||
inc_len_source = struct.calcsize(fmt_source)
|
||||
inc_len_scalar = struct.calcsize(fmt_scalar)
|
||||
inc_len_vec = struct.calcsize(fmt_vec)
|
||||
if len(hk_data) < 2 * inc_len_scalar + 2 * inc_len_vec + inc_len_source:
|
||||
if len(hk_data) < 3 * inc_len_scalar + 2 * inc_len_vec + inc_len_source:
|
||||
pw.dlog("Received HK set too small")
|
||||
return
|
||||
current_idx = 0
|
||||
@ -1276,8 +1277,8 @@ def perform_mgm_calibration( # noqa C901: Complexity okay
|
||||
reply = CALIBR_SOCKET.recv(1024)
|
||||
if len(reply) != 2:
|
||||
pw.dlog(
|
||||
f"MGM calibration: Reply received command magnetometer_field has invalid "
|
||||
f"length {len(reply)}"
|
||||
"MGM calibration: Reply received command magnetometer_field has"
|
||||
f" invalid length {len(reply)}"
|
||||
)
|
||||
return
|
||||
else:
|
||||
|
@ -12,8 +12,8 @@ from tmtccmd.tc import DefaultPusQueueHelper
|
||||
from tmtccmd.tc.pus_3_fsfw_hk import (
|
||||
make_sid,
|
||||
create_request_one_hk_command,
|
||||
create_enable_periodic_hk_command_with_interval,
|
||||
create_disable_periodic_hk_command,
|
||||
create_enable_periodic_hk_command_with_interval_with_diag,
|
||||
create_disable_periodic_hk_command_with_diag,
|
||||
)
|
||||
from tmtccmd.fsfw.tmtc_printer import FsfwTmTcPrinter
|
||||
|
||||
@ -74,7 +74,7 @@ def add_gps_cmds(defs: TmtcDefinitionWrapper):
|
||||
|
||||
def pack_gps_command( # noqa: C901
|
||||
object_id: bytes, q: DefaultPusQueueHelper, op_code: str
|
||||
): # noqa: C901
|
||||
): # noqa: C901:
|
||||
if op_code in OpCode.RESET_GNSS:
|
||||
# TODO: This needs to be re-implemented
|
||||
_LOGGER.warning("Reset pin handling needs to be re-implemented")
|
||||
@ -83,7 +83,7 @@ def pack_gps_command( # noqa: C901
|
||||
if interval <= 0:
|
||||
raise ValueError("invalid interval")
|
||||
q.add_log_cmd(f"GPS: {Info.ENABLE_CORE_HK}")
|
||||
cmds = create_enable_periodic_hk_command_with_interval(
|
||||
cmds = create_enable_periodic_hk_command_with_interval_with_diag(
|
||||
diag=False,
|
||||
sid=make_sid(object_id=object_id, set_id=SetId.CORE_HK),
|
||||
interval_seconds=interval,
|
||||
@ -93,7 +93,7 @@ def pack_gps_command( # noqa: C901
|
||||
if op_code in OpCode.DISABLE_CORE_HK:
|
||||
q.add_log_cmd(f"gps: {Info.DISABLE_CORE_HK}")
|
||||
q.add_pus_tc(
|
||||
create_disable_periodic_hk_command(
|
||||
create_disable_periodic_hk_command_with_diag(
|
||||
diag=False, sid=make_sid(object_id=object_id, set_id=SetId.CORE_HK)
|
||||
)
|
||||
)
|
||||
@ -109,7 +109,7 @@ def pack_gps_command( # noqa: C901
|
||||
if interval <= 0:
|
||||
raise ValueError("invalid interval")
|
||||
q.add_log_cmd(f"GPS: {Info.ENABLE_SKYVIEW_HK}")
|
||||
cmds = create_enable_periodic_hk_command_with_interval(
|
||||
cmds = create_enable_periodic_hk_command_with_interval_with_diag(
|
||||
diag=False,
|
||||
sid=make_sid(object_id=object_id, set_id=SetId.SKYVIEW_HK),
|
||||
interval_seconds=interval,
|
||||
@ -119,7 +119,7 @@ def pack_gps_command( # noqa: C901
|
||||
if op_code in OpCode.DISABLE_SKYVIEW_HK:
|
||||
q.add_log_cmd(f"gps: {Info.DISABLE_SKYVIEW_HK}")
|
||||
q.add_pus_tc(
|
||||
create_disable_periodic_hk_command(
|
||||
create_disable_periodic_hk_command_with_diag(
|
||||
diag=False, sid=make_sid(object_id=object_id, set_id=SetId.SKYVIEW_HK)
|
||||
)
|
||||
)
|
||||
@ -217,7 +217,7 @@ def handle_skyview_data(pw: PrintWrapper, hk_data: bytes):
|
||||
inc_len_uint8 = struct.calcsize(fmt_str_uint8)
|
||||
unix = struct.unpack(
|
||||
fmt_str_unix, hk_data[current_idx : current_idx + inc_len_unix]
|
||||
)
|
||||
)[0]
|
||||
current_idx += inc_len_unix
|
||||
prn_id = struct.unpack(
|
||||
fmt_str_int16, hk_data[current_idx : current_idx + inc_len_int16]
|
||||
@ -242,7 +242,7 @@ def handle_skyview_data(pw: PrintWrapper, hk_data: bytes):
|
||||
pw.dlog(f"Skyview Time: {unix} unix-sec")
|
||||
pw.dlog(
|
||||
"{:<8} {:<8} {:<8} {:<8} {:<8}".format(
|
||||
"PRN_ID", "AZ [°]", "EL [°]", "S2N [dBW]", "USED"
|
||||
"PRN_ID", "AZ [°]", "EL [°]", "S2N [dBHz]", "USED"
|
||||
)
|
||||
)
|
||||
for idx in range(GpsInfo.MAX_SATELLITES):
|
||||
|
@ -24,8 +24,8 @@ from tmtccmd.tc.pus_3_fsfw_hk import (
|
||||
generate_one_diag_command,
|
||||
generate_one_hk_command,
|
||||
create_request_one_diag_command,
|
||||
create_disable_periodic_hk_command,
|
||||
create_enable_periodic_hk_command_with_interval,
|
||||
create_enable_periodic_hk_command_with_interval_with_diag,
|
||||
create_disable_periodic_hk_command_with_diag,
|
||||
)
|
||||
from tmtccmd.tc.pus_200_fsfw_mode import pack_mode_data, Mode
|
||||
from tmtccmd.util import ObjectIdU32
|
||||
@ -227,12 +227,13 @@ def pack_imtq_test_into( # noqa C901
|
||||
duration = int(
|
||||
input(
|
||||
f"Specify torque duration [range [0, {pow(2, 16) - 1}, "
|
||||
f"0 for continuous generation until update]: "
|
||||
"0 for continuous generation until update]: "
|
||||
)
|
||||
)
|
||||
dur_str = "infinite" if duration == 0 else str(duration)
|
||||
q.add_log_cmd(
|
||||
f"IMTQ: Commanding dipole X={x_dipole}, Y={y_dipole}, Z={y_dipole}, duration={dur_str}"
|
||||
f"IMTQ: Commanding dipole X={x_dipole}, Y={y_dipole}, Z={y_dipole},"
|
||||
f" duration={dur_str}"
|
||||
)
|
||||
q.add_pus_tc(
|
||||
pack_dipole_command(
|
||||
@ -248,7 +249,7 @@ def pack_imtq_test_into( # noqa C901
|
||||
if op_code == OpCode.ENABLE_ENG_HK_NO_TORQUE:
|
||||
q.add_log_cmd("IMTQ: Enable ENG HK")
|
||||
interval = float(input("Please enter collection interval in seconds: "))
|
||||
cmds = create_enable_periodic_hk_command_with_interval(
|
||||
cmds = create_enable_periodic_hk_command_with_interval_with_diag(
|
||||
diag=True,
|
||||
sid=make_sid(object_id.as_bytes, ImtqSetId.ENG_HK_NO_TORQUE),
|
||||
interval_seconds=interval,
|
||||
@ -258,7 +259,7 @@ def pack_imtq_test_into( # noqa C901
|
||||
if op_code == OpCode.DISABLE_ENG_HK_NO_TORQUE:
|
||||
q.add_log_cmd("IMTQ: Disable ENG HK (No Torque)")
|
||||
q.add_pus_tc(
|
||||
create_disable_periodic_hk_command(
|
||||
create_disable_periodic_hk_command_with_diag(
|
||||
True, make_sid(object_id.as_bytes, ImtqSetId.ENG_HK_NO_TORQUE)
|
||||
)
|
||||
)
|
||||
@ -275,7 +276,7 @@ def pack_imtq_test_into( # noqa C901
|
||||
if op_code == OpCode.ENABLE_ENG_HK_WITH_TORQUE:
|
||||
q.add_log_cmd("IMTQ: Enable ENG HK with torque")
|
||||
interval = float(input("Please enter collection interval in seconds: "))
|
||||
cmds = create_enable_periodic_hk_command_with_interval(
|
||||
cmds = create_enable_periodic_hk_command_with_interval_with_diag(
|
||||
diag=True,
|
||||
sid=make_sid(object_id.as_bytes, ImtqSetId.ENG_HK_SET_WITH_TORQUE),
|
||||
interval_seconds=interval,
|
||||
@ -285,7 +286,7 @@ def pack_imtq_test_into( # noqa C901
|
||||
if op_code == OpCode.DISABLE_ENG_HK_WITH_TORQUE:
|
||||
q.add_log_cmd("IMTQ: Disable ENG HK with Torque")
|
||||
q.add_pus_tc(
|
||||
create_disable_periodic_hk_command(
|
||||
create_disable_periodic_hk_command_with_diag(
|
||||
True, make_sid(object_id.as_bytes, ImtqSetId.ENG_HK_SET_WITH_TORQUE)
|
||||
)
|
||||
)
|
||||
@ -320,14 +321,14 @@ def pack_imtq_test_into( # noqa C901
|
||||
if op_code == OpCode.DISABLE_MGM_RAW_NO_TORQUE:
|
||||
q.add_log_cmd("IMTQ: Disable MGM RAW HK (No Torque)")
|
||||
q.add_pus_tc(
|
||||
create_disable_periodic_hk_command(
|
||||
create_disable_periodic_hk_command_with_diag(
|
||||
True, make_sid(object_id.as_bytes, ImtqSetId.RAW_MTM_NO_TORQUE)
|
||||
)
|
||||
)
|
||||
if op_code == OpCode.ENABLE_MGM_RAW_NO_TORQUE:
|
||||
q.add_log_cmd("IMTQ: Enable MGM RAW HK (No Torque)")
|
||||
interval = float(input("Please enter collection interval in seconds: "))
|
||||
cmds = create_enable_periodic_hk_command_with_interval(
|
||||
cmds = create_enable_periodic_hk_command_with_interval_with_diag(
|
||||
diag=True,
|
||||
sid=make_sid(object_id.as_bytes, ImtqSetId.RAW_MTM_NO_TORQUE),
|
||||
interval_seconds=interval,
|
||||
@ -346,7 +347,7 @@ def pack_imtq_test_into( # noqa C901
|
||||
if op_code == OpCode.ENABLE_MGM_RAW_WITH_TORQUE:
|
||||
q.add_log_cmd("IMTQ: Enable MGM RAW HK (No Torque)")
|
||||
interval = float(input("Please enter collection interval in seconds: "))
|
||||
cmds = create_enable_periodic_hk_command_with_interval(
|
||||
cmds = create_enable_periodic_hk_command_with_interval_with_diag(
|
||||
diag=True,
|
||||
sid=make_sid(object_id.as_bytes, ImtqSetId.RAW_MTM_WITH_TORQUE),
|
||||
interval_seconds=interval,
|
||||
@ -356,7 +357,7 @@ def pack_imtq_test_into( # noqa C901
|
||||
if op_code == OpCode.DISABLE_MGM_RAW_WITH_TORQUE:
|
||||
q.add_log_cmd("IMTQ: Disable MGM RAW HK (No Torque)")
|
||||
q.add_pus_tc(
|
||||
create_disable_periodic_hk_command(
|
||||
create_disable_periodic_hk_command_with_diag(
|
||||
True, make_sid(object_id.as_bytes, ImtqSetId.RAW_MTM_WITH_TORQUE)
|
||||
)
|
||||
)
|
||||
@ -388,7 +389,8 @@ def pack_dipole_command(
|
||||
duration = int(round(duration))
|
||||
if duration < 0 or duration > pow(2, 16) - 1:
|
||||
raise ValueError(
|
||||
f"Duration in ms of {duration} smaller than 0 or larger than allowed {pow(2, 16) - 1}"
|
||||
f"Duration in ms of {duration} smaller than 0 or larger than allowed"
|
||||
f" {pow(2, 16) - 1}"
|
||||
)
|
||||
command += struct.pack("!h", x_dipole)
|
||||
command += struct.pack("!h", y_dipole)
|
||||
@ -400,7 +402,8 @@ def pack_dipole_command(
|
||||
|
||||
def raise_dipole_error(dipole_str: str, value: int):
|
||||
raise ValueError(
|
||||
f"{dipole_str} {value} negative or larger than maximum allowed 2000 * 10^-4*Am^2"
|
||||
f"{dipole_str} {value} negative or larger than maximum allowed 2000 *"
|
||||
" 10^-4*Am^2"
|
||||
)
|
||||
|
||||
|
||||
|
@ -261,14 +261,12 @@ def pack_set_speed_command(
|
||||
if speed > 0:
|
||||
if speed < 1000 or speed > 65000:
|
||||
raise ValueError(
|
||||
"Invalid RW speed specified. "
|
||||
"Allowed range is [1000, 65000] 0.1 * RPM"
|
||||
"Invalid RW speed specified. Allowed range is [1000, 65000] 0.1 * RPM"
|
||||
)
|
||||
elif speed < 0:
|
||||
if speed < -65000 or speed > -1000:
|
||||
raise ValueError(
|
||||
"Invalid RW speed specified. "
|
||||
"Allowed range is [-65000, -1000] 0.1 * RPM"
|
||||
"Invalid RW speed specified. Allowed range is [-65000, -1000] 0.1 * RPM"
|
||||
)
|
||||
else:
|
||||
# Speed is 0
|
||||
@ -304,15 +302,16 @@ def handle_rw_hk_data(
|
||||
speed_rpm = speed / 10.0
|
||||
ref_speed_rpm = ref_speed / 10.0
|
||||
pw.dlog(
|
||||
f"Temperature {temp} C | Speed {speed_rpm} rpm | Reference Speed {ref_speed_rpm} rpm"
|
||||
f"Temperature {temp} C | Speed {speed_rpm} rpm | Reference Speed"
|
||||
f" {ref_speed_rpm} rpm"
|
||||
)
|
||||
pw.dlog(
|
||||
f"State {state}. 0: Error, 1: Idle, 2: Coasting, 3: Running, speed stable, "
|
||||
f"4: Running, speed changing"
|
||||
"4: Running, speed changing"
|
||||
)
|
||||
pw.dlog(
|
||||
f"Current Limit Control mode {clc_mode}. 0: Low Current Mode (0.3 A), "
|
||||
f"1: High Current Mode (0.6 A)"
|
||||
"1: High Current Mode (0.6 A)"
|
||||
)
|
||||
pw.dlog(FsfwTmTcPrinter.get_validity_buffer(hk_data[current_idx:], 5))
|
||||
if set_id == RwSetId.LAST_RESET:
|
||||
@ -361,22 +360,24 @@ def handle_rw_hk_data(
|
||||
) = struct.unpack(fmt_str, hk_data[current_idx : current_idx + inc_len])
|
||||
|
||||
pw.dlog(
|
||||
f"MCU Temperature {mcu_temp} | Pressure Sensore Temperature {pressure_sens_temp} C"
|
||||
f"MCU Temperature {mcu_temp} | Pressure Sensore Temperature"
|
||||
f" {pressure_sens_temp} C"
|
||||
)
|
||||
pw.dlog(f"Last Reset Status {last_reset_status}")
|
||||
pw.dlog(
|
||||
f"Current Limit Control mode {clc_mode}. 0: Low Current Mode (0.3 A), "
|
||||
f"1: High Current Mode (0.6 A)"
|
||||
"1: High Current Mode (0.6 A)"
|
||||
)
|
||||
pw.dlog(f"Speed {current_speed} rpm | Reference Speed {ref_speed} rpm")
|
||||
pw.dlog(
|
||||
f"State {state}. 0: Error, 1: Idle, 2: Coasting, 3: Running, speed stable, "
|
||||
f"4: Running, speed changing"
|
||||
"4: Running, speed changing"
|
||||
)
|
||||
pw.dlog("Number Of Invalid Packets:")
|
||||
pw.dlog("CRC | Length | CMD")
|
||||
pw.dlog(
|
||||
f"{num_invalid_crc_packets} | {num_invalid_len_packets} | {num_invalid_cmd_packets}"
|
||||
f"{num_invalid_crc_packets} | {num_invalid_len_packets} |"
|
||||
f" {num_invalid_cmd_packets}"
|
||||
)
|
||||
pw.dlog(
|
||||
f"Num Of CMD Executed Requests {num_of_cmd_executed_requests} | "
|
||||
@ -388,15 +389,16 @@ def handle_rw_hk_data(
|
||||
"RegOverrunErrs | TotalErrs"
|
||||
)
|
||||
pw.dlog(
|
||||
f"{uart_num_of_bytes_written} | {uart_num_of_bytes_read} | {uart_num_parity_errors} | "
|
||||
f"{uart_num_noise_errors} | {uart_num_frame_errors} | {uart_num_reg_overrun_errors} | "
|
||||
f"{uart_total_num_errors}"
|
||||
f"{uart_num_of_bytes_written} | {uart_num_of_bytes_read} |"
|
||||
f" {uart_num_parity_errors} | {uart_num_noise_errors} |"
|
||||
f" {uart_num_frame_errors} | {uart_num_reg_overrun_errors} |"
|
||||
f" {uart_total_num_errors}"
|
||||
)
|
||||
pw.dlog("SPI COM Info:")
|
||||
pw.dlog("NumBytesWritten | NumBytesRead | RegOverrunErrs | TotalErrs")
|
||||
pw.dlog(
|
||||
f"{spi_num_bytes_written} | {spi_num_bytes_read} | {spi_num_reg_overrun_errors} | "
|
||||
f"{spi_total_num_errors}"
|
||||
f"{spi_num_bytes_written} | {spi_num_bytes_read} |"
|
||||
f" {spi_num_reg_overrun_errors} | {spi_total_num_errors}"
|
||||
)
|
||||
if current_idx > 0:
|
||||
pw.dlog(
|
||||
|
@ -83,7 +83,7 @@ def pack_pdec_handler_test(
|
||||
0,
|
||||
ParameterId.POSITIVE_WINDOW,
|
||||
pw,
|
||||
).pack()
|
||||
)
|
||||
)
|
||||
)
|
||||
if op_code == OpCode.NEGATIVE_WINDOW:
|
||||
@ -96,7 +96,7 @@ def pack_pdec_handler_test(
|
||||
0,
|
||||
ParameterId.NEGATIVE_WINDOW,
|
||||
nw,
|
||||
).pack()
|
||||
)
|
||||
)
|
||||
)
|
||||
if op_code == OpCode.RESET_NO_INIT:
|
||||
|
@ -3,6 +3,7 @@ import enum
|
||||
from eive_tmtc.config.definitions import CustomServiceList
|
||||
from eive_tmtc.config.object_ids import COM_SUBSYSTEM_ID
|
||||
from eive_tmtc.tmtc.com.syrlinks_handler import Datarate
|
||||
from tmtccmd.pus.s20_fsfw_param_defs import create_scalar_u8_parameter
|
||||
|
||||
from .defs import Mode as ComMode
|
||||
|
||||
@ -21,7 +22,6 @@ from tmtccmd.tc.pus_200_fsfw_mode import (
|
||||
)
|
||||
from tmtccmd.tc.pus_20_fsfw_param import (
|
||||
create_load_param_cmd,
|
||||
pack_scalar_u8_parameter_app_data,
|
||||
)
|
||||
|
||||
from tmtccmd.pus.s20_fsfw_param import create_scalar_u32_parameter
|
||||
@ -87,7 +87,7 @@ def build_com_subsystem_cmd(p: ServiceProviderParams): # noqa C901
|
||||
q.add_log_cmd(f"{prefix}: {Info.UPDATE_DEFAULT_DATARATE_LOW}")
|
||||
q.add_pus_tc(
|
||||
create_load_param_cmd(
|
||||
pack_scalar_u8_parameter_app_data(
|
||||
create_scalar_u8_parameter(
|
||||
COM_SUBSYSTEM_ID,
|
||||
0,
|
||||
ParameterId.DATARATE,
|
||||
@ -99,7 +99,7 @@ def build_com_subsystem_cmd(p: ServiceProviderParams): # noqa C901
|
||||
q.add_log_cmd(f"{prefix}: {Info.UPDATE_DEFAULT_DATARATE_HIGH}")
|
||||
q.add_pus_tc(
|
||||
create_load_param_cmd(
|
||||
pack_scalar_u8_parameter_app_data(
|
||||
create_scalar_u8_parameter(
|
||||
COM_SUBSYSTEM_ID,
|
||||
0,
|
||||
ParameterId.DATARATE,
|
||||
@ -122,7 +122,7 @@ def build_com_subsystem_cmd(p: ServiceProviderParams): # noqa C901
|
||||
0,
|
||||
ParameterId.TRANSMITTER_TIMEOUT,
|
||||
timeout,
|
||||
).pack()
|
||||
)
|
||||
)
|
||||
)
|
||||
elif o == OpCode.READ_MODE:
|
||||
|
@ -21,9 +21,9 @@ from tmtccmd.tc import DefaultPusQueueHelper
|
||||
from tmtccmd.tc.pus_3_fsfw_hk import (
|
||||
make_sid,
|
||||
create_request_one_diag_command,
|
||||
create_enable_periodic_hk_command_with_interval,
|
||||
create_disable_periodic_hk_command,
|
||||
create_request_one_hk_command,
|
||||
create_enable_periodic_hk_command_with_interval_with_diag,
|
||||
create_disable_periodic_hk_command_with_diag,
|
||||
)
|
||||
from spacepackets.ecss.tc import PusTelecommand
|
||||
from tmtccmd.tc.pus_200_fsfw_mode import Mode, create_mode_command
|
||||
@ -182,24 +182,28 @@ def pack_syrlinks_command( # noqa C901: Complexity okay here.
|
||||
q.add_log_cmd(f"{prefix}: {Info.ENABLE_HK_RX_REGS}")
|
||||
sid = make_sid(obyt, SetId.RX_REGISTERS_DATASET)
|
||||
interval = float(input("HK interval in floating point seconds"))
|
||||
cmds = create_enable_periodic_hk_command_with_interval(True, sid, interval)
|
||||
cmds = create_enable_periodic_hk_command_with_interval_with_diag(
|
||||
True, sid, interval
|
||||
)
|
||||
for cmd in cmds:
|
||||
q.add_pus_tc(cmd)
|
||||
if op_code in OpCode.DISABLE_HK_RX_REGS:
|
||||
q.add_log_cmd(f"{prefix}: {Info.DISABLE_HK_RX_REGS}")
|
||||
sid = make_sid(obyt, SetId.RX_REGISTERS_DATASET)
|
||||
q.add_pus_tc(create_disable_periodic_hk_command(True, sid))
|
||||
q.add_pus_tc(create_disable_periodic_hk_command_with_diag(True, sid))
|
||||
if op_code in OpCode.ENABLE_HK_TX_REGS:
|
||||
q.add_log_cmd(f"{prefix}: {Info.ENABLE_HK_TX_REGS}")
|
||||
sid = make_sid(obyt, SetId.TX_REGISTERS_DATASET)
|
||||
interval = float(input("HK interval in floating point seconds"))
|
||||
cmds = create_enable_periodic_hk_command_with_interval(True, sid, interval)
|
||||
cmds = create_enable_periodic_hk_command_with_interval_with_diag(
|
||||
True, sid, interval
|
||||
)
|
||||
for cmd in cmds:
|
||||
q.add_pus_tc(cmd)
|
||||
if op_code in OpCode.DISABLE_HK_TX_REGS:
|
||||
q.add_log_cmd(f"{prefix}: {Info.DISABLE_HK_TX_REGS}")
|
||||
sid = make_sid(obyt, SetId.TX_REGISTERS_DATASET)
|
||||
q.add_pus_tc(create_disable_periodic_hk_command(True, sid))
|
||||
q.add_pus_tc(create_disable_periodic_hk_command_with_diag(True, sid))
|
||||
if op_code in OpCode.HK_TX_REGS:
|
||||
q.add_log_cmd(f"{prefix}: {Info.HK_TX_REGS}")
|
||||
sid = make_sid(obyt, SetId.TX_REGISTERS_DATASET)
|
||||
|
@ -570,12 +570,12 @@ def handle_ploc_mpsoc_hk_data(pw: PrintWrapper, hk_data: bytes, set_id: int):
|
||||
pw.dlog(f"CAM SoC Temperature: {cam_soc_temp}")
|
||||
pw.dlog(f"System Monitor Temperature: {sysmon_temp}")
|
||||
pw.dlog(
|
||||
f"SYSMON VCC INT {sysmon_vcc_int:.3f} | SYSMON VCC AUX {sysmon_vcc_aux:.3f} | "
|
||||
f"SYSMON VCC BRAM {sysmon_vcc_bram:.3f}"
|
||||
f"SYSMON VCC INT {sysmon_vcc_int:.3f} | SYSMON VCC AUX"
|
||||
f" {sysmon_vcc_aux:.3f} | SYSMON VCC BRAM {sysmon_vcc_bram:.3f}"
|
||||
)
|
||||
pw.dlog(
|
||||
f"SYSMON VCC PAUX {sysmon_vcc_paux:.3f} | SYSMON VCC PINT {sysmon_vcc_pint:.3f} | "
|
||||
f"SYSMON VCC PDRO {sysmon_vcc_pdro:.3f}"
|
||||
f"SYSMON VCC PAUX {sysmon_vcc_paux:.3f} | SYSMON VCC PINT"
|
||||
f" {sysmon_vcc_pint:.3f} | SYSMON VCC PDRO {sysmon_vcc_pdro:.3f}"
|
||||
)
|
||||
|
||||
fmt_str = "!fffffffffffff"
|
||||
@ -602,8 +602,9 @@ def handle_ploc_mpsoc_hk_data(pw: PrintWrapper, hk_data: bytes, set_id: int):
|
||||
f"SYSMON MBA 1V8 {sysmon_mb_1v8:.3f}"
|
||||
)
|
||||
pw.dlog(
|
||||
f"SYSMON VCC 12V {sysmon_vcc_12v:.3f} | SYSMON VCC 5V {sysmon_vcc_5v:.3f} | "
|
||||
f"SYSMON VCC 3V3 {sysmon_vcc_3v3:.3f} | SYSMON VCC 3V3VA {sysmon_vcc_3v3va}"
|
||||
f"SYSMON VCC 12V {sysmon_vcc_12v:.3f} | SYSMON VCC 5V {sysmon_vcc_5v:.3f} |"
|
||||
f" SYSMON VCC 3V3 {sysmon_vcc_3v3:.3f} | SYSMON VCC 3V3VA"
|
||||
f" {sysmon_vcc_3v3va}"
|
||||
)
|
||||
pw.dlog(
|
||||
f"SYSMON VCC 2V5DDR {sysmon_vcc_2v5ddr:.3f} | "
|
||||
|
@ -471,8 +471,8 @@ def pack_ploc_supv_commands(p: ServiceProviderParams): # noqa C901
|
||||
custom_data.extend(struct.pack("!B", memory_id))
|
||||
custom_data.extend(struct.pack("!I", start_address))
|
||||
q.add_log_cmd(
|
||||
f"{prefix}: {Info.MEM_CHECK} for file {update_file} at memory ID {memory_id} at start "
|
||||
f"address {start_address}"
|
||||
f"{prefix}: {Info.MEM_CHECK} for file {update_file} at memory ID"
|
||||
f" {memory_id} at start address {start_address}"
|
||||
)
|
||||
command = create_action_cmd(
|
||||
object_id.as_bytes, SupvActionId.MEM_CHECK, custom_data
|
||||
@ -722,10 +722,42 @@ def get_event_buffer_path() -> str:
|
||||
return file
|
||||
|
||||
|
||||
class SocState(enum.IntEnum):
|
||||
OFF = 0
|
||||
BOOTING = 1
|
||||
OPERATIONAL = 2
|
||||
SHUTDOWN = 3
|
||||
|
||||
|
||||
def handle_supv_hk_data(set_id: int, hk_data: bytes, pw: PrintWrapper):
|
||||
current_idx = 0
|
||||
if set_id == SetIds.HK_REPORT:
|
||||
pass
|
||||
fmt_str = "!IIIQIIIIIBBBB"
|
||||
inc_len = struct.calcsize(fmt_str)
|
||||
(
|
||||
temp_ps,
|
||||
temp_pl,
|
||||
temp_sup,
|
||||
uptime,
|
||||
cpu_load,
|
||||
avail_heap,
|
||||
num_tcs,
|
||||
num_tms,
|
||||
soc_state,
|
||||
nvm_0_1_state,
|
||||
nvm_3_state,
|
||||
mission_io_state,
|
||||
fmc_state,
|
||||
) = struct.unpack(fmt_str, hk_data[:inc_len])
|
||||
pw.dlog(f"Temp PS {temp_ps} C | Temp PL {temp_pl} C | Temp SUP {temp_sup} C")
|
||||
pw.dlog(f"Uptime {uptime} | CPU Load {cpu_load} | Avail Heap {avail_heap}")
|
||||
pw.dlog(f"Number TCs {num_tcs} | Number TMs {num_tms}")
|
||||
pw.dlog(f"SOC state {SocState(soc_state)}")
|
||||
pw.dlog(f"NVM 01 State {nvm_0_1_state}")
|
||||
pw.dlog(f"NVM 3 State {nvm_3_state}")
|
||||
pw.dlog(f"Mission IO state {mission_io_state}")
|
||||
pw.dlog(f"FMC state {fmc_state}")
|
||||
pw.dlog(FsfwTmTcPrinter.get_validity_buffer(hk_data[inc_len:], 13))
|
||||
elif set_id == SetIds.BOOT_STATUS_REPORT:
|
||||
fmt_str = "!BBIIBBBBBB"
|
||||
inc_len = struct.calcsize(fmt_str)
|
||||
@ -743,7 +775,8 @@ def handle_supv_hk_data(set_id: int, hk_data: bytes, pw: PrintWrapper):
|
||||
) = struct.unpack(fmt_str, hk_data[0 : 0 + inc_len])
|
||||
current_idx += inc_len
|
||||
pw.dlog(
|
||||
f"SoC state (0:off, 1:booting, 2:update, 3:operating, 4:shutdown, 5:reset): {soc_state}"
|
||||
"SoC state (0:off, 1:booting, 2:update, 3:operating, 4:shutdown, 5:reset):"
|
||||
f" {soc_state}"
|
||||
)
|
||||
pw.dlog(f"Power Cycles {power_cycles}")
|
||||
pw.dlog(f"Boot after {boot_after_ms} ms | Boot timeout {boot_timeout_ms} ms")
|
||||
|
@ -131,8 +131,7 @@ def pack_scex_cmds(p: ServiceProviderParams): # noqa C901
|
||||
cell_select = int(cell_select)
|
||||
if cell_select < 1 or cell_select > 10:
|
||||
print(
|
||||
f"Invalid cell number {cell_select}, "
|
||||
f"Please enter a valid number: "
|
||||
f"Invalid cell number {cell_select}, Please enter a valid number: "
|
||||
)
|
||||
continue
|
||||
cn = cell_select - 1
|
||||
|
@ -12,7 +12,7 @@ from tmtccmd.tc.decorator import ServiceProviderParams
|
||||
from tmtccmd.tc.pus_200_fsfw_mode import Subservice as ModeSubservice
|
||||
|
||||
|
||||
class ModeId:
|
||||
class ModeId(enum.IntEnum):
|
||||
OFF = 0
|
||||
SUPV_ONLY = 10
|
||||
MPSOC_STREAM = 11
|
||||
|
@ -0,0 +1 @@
|
||||
from .subsystem import add_eps_subsystem_cmds
|
||||
|
@ -200,7 +200,8 @@ def pack_common_gomspace_cmds( # noqa C901: Complexity is okay here.
|
||||
if op_code in GomspaceOpCode.SAVE_TABLE_DEFAULT:
|
||||
source_table = int(
|
||||
input(
|
||||
"Source table [0: Board Config, 1: Module Config, 2: Calibration Parameter]: "
|
||||
"Source table [0: Board Config, 1: Module Config, 2: Calibration"
|
||||
" Parameter]: "
|
||||
)
|
||||
)
|
||||
if source_table not in [0, 1, 2]:
|
||||
@ -215,8 +216,8 @@ def pack_common_gomspace_cmds( # noqa C901: Complexity is okay here.
|
||||
if op_code in GomspaceOpCode.LOAD_TABLE:
|
||||
target_table = int(
|
||||
input(
|
||||
"Target table ID [0: Board Config, 1: Module Config, 2: Calibration Parameter, "
|
||||
"4: HK TM]: "
|
||||
"Target table ID [0: Board Config, 1: Module Config, 2: Calibration"
|
||||
" Parameter, 4: HK TM]: "
|
||||
)
|
||||
)
|
||||
if target_table not in [0, 1, 2, 4]:
|
||||
@ -224,8 +225,8 @@ def pack_common_gomspace_cmds( # noqa C901: Complexity is okay here.
|
||||
if target_table != 4:
|
||||
source_table = int(
|
||||
input(
|
||||
"Source table (file or default) [0: Board Config, 1: Module Config, "
|
||||
"2: Calibration Parameter, value + 4 for default table]: "
|
||||
"Source table (file or default) [0: Board Config, 1: Module Config,"
|
||||
" 2: Calibration Parameter, value + 4 for default table]: "
|
||||
)
|
||||
)
|
||||
if source_table not in [0, 1, 2, 4, 5, 6]:
|
||||
|
@ -86,6 +86,7 @@ class NormalSubmodesMask(enum.IntEnum):
|
||||
|
||||
|
||||
class SubmodeForNormalMode(enum.IntEnum):
|
||||
NONE = 0
|
||||
SSR_ON = 1 << NormalSubmodesMask.SOLID_STATE_RELAYS_ADC_ON
|
||||
DRO_ON = 1 << NormalSubmodesMask.DRO_ON | (
|
||||
1 << NormalSubmodesMask.SOLID_STATE_RELAYS_ADC_ON
|
||||
@ -283,7 +284,7 @@ def hpa_on_procedure(q: DefaultPusQueueHelper):
|
||||
if delay_dro_to_x8 is None:
|
||||
delay_dro_to_x8 = 900
|
||||
q.add_log_cmd(
|
||||
f"Starting procedure to switch on PL PCDU HPA with DRO to X8 "
|
||||
"Starting procedure to switch on PL PCDU HPA with DRO to X8 "
|
||||
f"delay of {delay_dro_to_x8} seconds"
|
||||
)
|
||||
pl_pcdu_on = PusTelecommand(
|
||||
|
302
eive_tmtc/tmtc/power/pwr_ctrl.py
Normal file
302
eive_tmtc/tmtc/power/pwr_ctrl.py
Normal file
@ -0,0 +1,302 @@
|
||||
import datetime
|
||||
import enum
|
||||
import logging
|
||||
import struct
|
||||
|
||||
from eive_tmtc.config.definitions import CustomServiceList
|
||||
from eive_tmtc.config.object_ids import PWR_CONTROLLER
|
||||
from eive_tmtc.pus_tm.defs import PrintWrapper
|
||||
from tmtccmd.config.tmtc import (
|
||||
tmtc_definitions_provider,
|
||||
TmtcDefinitionWrapper,
|
||||
OpCodeEntry,
|
||||
)
|
||||
from tmtccmd.tc import service_provider
|
||||
from tmtccmd.tc.queue import DefaultPusQueueHelper
|
||||
from tmtccmd.tc.pus_200_fsfw_mode import Mode, pack_mode_command
|
||||
from tmtccmd.tc.decorator import ServiceProviderParams
|
||||
from tmtccmd.tc.pus_3_fsfw_hk import (
|
||||
generate_one_hk_command,
|
||||
make_sid,
|
||||
enable_periodic_hk_command_with_interval,
|
||||
disable_periodic_hk_command,
|
||||
)
|
||||
from tmtccmd.fsfw.tmtc_printer import FsfwTmTcPrinter
|
||||
|
||||
from tmtccmd.tc.pus_20_fsfw_param import create_load_param_cmd
|
||||
|
||||
from tmtccmd.pus.s20_fsfw_param_defs import (
|
||||
create_scalar_float_parameter,
|
||||
create_scalar_double_parameter,
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SetId(enum.IntEnum):
|
||||
CORE_HK_SET = 0
|
||||
ENABLE_PL_SET = 1
|
||||
|
||||
|
||||
# class ActionId(enum.IntEnum):
|
||||
|
||||
|
||||
class ParamId(enum.IntEnum):
|
||||
BATTERY_INTERNAL_RESISTANCE = 0
|
||||
BATTERY_MAXIMUM_CAPACITY = 1
|
||||
COULOMB_COUNTER_VOLTAGE_UPPER_THRESHOLD = 2
|
||||
MAX_ALLOWED_TIME_DIFF = 3
|
||||
PAYLOAD_OP_LIMIT_ON = 4
|
||||
PAYLOAD_OP_LIMIT_LOW = 5
|
||||
HIGHER_MODES_LIMIT = 6
|
||||
|
||||
|
||||
class OpCodes:
|
||||
OFF = ["mode_off"]
|
||||
ON = ["mode_on"]
|
||||
NML = ["mode_normal"]
|
||||
SET_PARAMETER = ["set_parameter"]
|
||||
REQUEST_CORE_HK = ["core_hk"]
|
||||
ENABLE_CORE_HK = ["core_enable_hk"]
|
||||
DISABLE_CORE_HK = ["core_disable_hk"]
|
||||
REQUEST_ENABLE_PL_HK = ["enable_pl_hk"]
|
||||
ENABLE_ENABLE_PL_HK = ["enable_pl_enable_hk"]
|
||||
DISABLE_ENABLE_PL_HK = ["enable_pl_disable_hk"]
|
||||
|
||||
|
||||
class Info:
|
||||
OFF = "PWR Ctrl Mode to OFF"
|
||||
ON = "PWR Ctrl Mode to ON"
|
||||
NML = "PWR Ctrl Mode to NORMAL"
|
||||
SET_PARAMETER = "Set Parameter"
|
||||
REQUEST_CORE_HK = "Request Core HK once"
|
||||
ENABLE_CORE_HK = "Enable Core HK Data Generation"
|
||||
DISABLE_CORE_HK = "Disable Core HK Data Generation"
|
||||
REQUEST_ENABLE_PL_HK = "Request Enable PL HK once"
|
||||
ENABLE_ENABLE_PL_HK = "Enable Enable PL HK Data Generation"
|
||||
DISABLE_ENABLE_PL_HK = "Disable Enable PL HK Data Generation"
|
||||
|
||||
|
||||
@tmtc_definitions_provider
|
||||
def acs_cmd_defs(defs: TmtcDefinitionWrapper):
|
||||
oce = OpCodeEntry()
|
||||
oce.add(keys=OpCodes.OFF, info=Info.OFF)
|
||||
oce.add(keys=OpCodes.ON, info=Info.ON)
|
||||
oce.add(keys=OpCodes.NML, info=Info.NML)
|
||||
oce.add(keys=OpCodes.SET_PARAMETER, info=Info.SET_PARAMETER)
|
||||
oce.add(keys=OpCodes.REQUEST_CORE_HK, info=Info.REQUEST_CORE_HK)
|
||||
oce.add(keys=OpCodes.ENABLE_CORE_HK, info=Info.ENABLE_CORE_HK)
|
||||
oce.add(keys=OpCodes.DISABLE_CORE_HK, info=Info.DISABLE_CORE_HK)
|
||||
oce.add(keys=OpCodes.REQUEST_ENABLE_PL_HK, info=Info.REQUEST_ENABLE_PL_HK)
|
||||
oce.add(keys=OpCodes.ENABLE_ENABLE_PL_HK, info=Info.ENABLE_ENABLE_PL_HK)
|
||||
oce.add(keys=OpCodes.DISABLE_ENABLE_PL_HK, info=Info.DISABLE_ENABLE_PL_HK)
|
||||
defs.add_service(
|
||||
name=CustomServiceList.PWR_CTRL.value, info="PWR Controller", op_code_entry=oce
|
||||
)
|
||||
|
||||
|
||||
@service_provider(CustomServiceList.PWR_CTRL.value)
|
||||
def pack_acs_ctrl_command(p: ServiceProviderParams):
|
||||
op_code = p.op_code
|
||||
q = p.queue_helper
|
||||
if op_code in OpCodes.OFF:
|
||||
q.add_log_cmd(f"{Info.OFF}")
|
||||
q.add_pus_tc(pack_mode_command(PWR_CONTROLLER, Mode.OFF, 0))
|
||||
elif op_code in OpCodes.ON:
|
||||
q.add_log_cmd(f"{Info.ON}")
|
||||
q.add_pus_tc(pack_mode_command(PWR_CONTROLLER, Mode.ON, 0))
|
||||
elif op_code in OpCodes.NML:
|
||||
q.add_log_cmd(f"{Info.NML}")
|
||||
q.add_pus_tc(pack_mode_command(PWR_CONTROLLER, Mode.NORMAL, 0))
|
||||
elif op_code in OpCodes.SET_PARAMETER:
|
||||
q.add_log_cmd(f"{Info.SET_PARAMETER}")
|
||||
set_pwr_ctrl_param(q)
|
||||
elif op_code in OpCodes.REQUEST_CORE_HK:
|
||||
q.add_log_cmd(Info.REQUEST_CORE_HK)
|
||||
q.add_pus_tc(
|
||||
generate_one_hk_command(make_sid(PWR_CONTROLLER, SetId.CORE_HK_SET))
|
||||
)
|
||||
elif op_code in OpCodes.ENABLE_CORE_HK:
|
||||
interval = float(input("Please specify interval in floating point seconds: "))
|
||||
q.add_log_cmd(Info.ENABLE_CORE_HK)
|
||||
cmd_tuple = enable_periodic_hk_command_with_interval(
|
||||
False, make_sid(PWR_CONTROLLER, SetId.CORE_HK_SET), interval
|
||||
)
|
||||
q.add_pus_tc(cmd_tuple[0])
|
||||
q.add_pus_tc(cmd_tuple[1])
|
||||
elif op_code in OpCodes.DISABLE_CORE_HK:
|
||||
q.add_log_cmd(Info.DISABLE_CORE_HK)
|
||||
q.add_pus_tc(
|
||||
disable_periodic_hk_command(
|
||||
False, make_sid(PWR_CONTROLLER, SetId.CORE_HK_SET)
|
||||
)
|
||||
)
|
||||
elif op_code in OpCodes.REQUEST_ENABLE_PL_HK:
|
||||
q.add_log_cmd(Info.REQUEST_ENABLE_PL_HK)
|
||||
q.add_pus_tc(
|
||||
generate_one_hk_command(make_sid(PWR_CONTROLLER, SetId.ENABLE_PL_SET))
|
||||
)
|
||||
elif op_code in OpCodes.ENABLE_ENABLE_PL_HK:
|
||||
interval = float(input("Please specify interval in floating point seconds: "))
|
||||
q.add_log_cmd(Info.ENABLE_ENABLE_PL_HK)
|
||||
cmd_tuple = enable_periodic_hk_command_with_interval(
|
||||
False, make_sid(PWR_CONTROLLER, SetId.ENABLE_PL_SET), interval
|
||||
)
|
||||
q.add_pus_tc(cmd_tuple[0])
|
||||
q.add_pus_tc(cmd_tuple[1])
|
||||
elif op_code in OpCodes.DISABLE_ENABLE_PL_HK:
|
||||
q.add_log_cmd(Info.DISABLE_ENABLE_PL_HK)
|
||||
q.add_pus_tc(
|
||||
disable_periodic_hk_command(
|
||||
False, make_sid(PWR_CONTROLLER, SetId.ENABLE_PL_SET)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def set_pwr_ctrl_param(q: DefaultPusQueueHelper):
|
||||
for val in ParamId:
|
||||
print("{:<2}: {:<20}".format(val, val.name))
|
||||
param = int(input("Specify parameter to set \n" ""))
|
||||
match param:
|
||||
case ParamId.BATTERY_INTERNAL_RESISTANCE:
|
||||
value = float(input("Specify parameter value to set [Ohm]: "))
|
||||
q.add_pus_tc(
|
||||
create_load_param_cmd(
|
||||
create_scalar_float_parameter(
|
||||
object_id=PWR_CONTROLLER,
|
||||
domain_id=0,
|
||||
unique_id=ParamId.BATTERY_INTERNAL_RESISTANCE,
|
||||
parameter=value,
|
||||
)
|
||||
)
|
||||
)
|
||||
case ParamId.BATTERY_MAXIMUM_CAPACITY:
|
||||
value = float(input("Specify parameter value to set [Ah]: "))
|
||||
q.add_pus_tc(
|
||||
create_load_param_cmd(
|
||||
create_scalar_float_parameter(
|
||||
object_id=PWR_CONTROLLER,
|
||||
domain_id=0,
|
||||
unique_id=ParamId.BATTERY_MAXIMUM_CAPACITY,
|
||||
parameter=value,
|
||||
)
|
||||
)
|
||||
)
|
||||
case ParamId.COULOMB_COUNTER_VOLTAGE_UPPER_THRESHOLD:
|
||||
value = float(input("Specify parameter value to set [V]: "))
|
||||
q.add_pus_tc(
|
||||
create_load_param_cmd(
|
||||
create_scalar_float_parameter(
|
||||
object_id=PWR_CONTROLLER,
|
||||
domain_id=0,
|
||||
unique_id=ParamId.COULOMB_COUNTER_VOLTAGE_UPPER_THRESHOLD,
|
||||
parameter=value,
|
||||
)
|
||||
)
|
||||
)
|
||||
case ParamId.MAX_ALLOWED_TIME_DIFF:
|
||||
value = float(input("Specify parameter value to set [s]: "))
|
||||
q.add_pus_tc(
|
||||
create_load_param_cmd(
|
||||
create_scalar_double_parameter(
|
||||
object_id=PWR_CONTROLLER,
|
||||
domain_id=0,
|
||||
unique_id=ParamId.MAX_ALLOWED_TIME_DIFF,
|
||||
parameter=value,
|
||||
)
|
||||
)
|
||||
)
|
||||
case ParamId.PAYLOAD_OP_LIMIT_ON:
|
||||
value = float(input("Specify parameter value to set [1]: "))
|
||||
q.add_pus_tc(
|
||||
create_load_param_cmd(
|
||||
create_scalar_float_parameter(
|
||||
object_id=PWR_CONTROLLER,
|
||||
domain_id=0,
|
||||
unique_id=ParamId.PAYLOAD_OP_LIMIT_ON,
|
||||
parameter=value,
|
||||
)
|
||||
)
|
||||
)
|
||||
case ParamId.PAYLOAD_OP_LIMIT_LOW:
|
||||
value = float(input("Specify parameter value to set [1]: "))
|
||||
q.add_pus_tc(
|
||||
create_load_param_cmd(
|
||||
create_scalar_float_parameter(
|
||||
object_id=PWR_CONTROLLER,
|
||||
domain_id=0,
|
||||
unique_id=ParamId.PAYLOAD_OP_LIMIT_LOW,
|
||||
parameter=value,
|
||||
)
|
||||
)
|
||||
)
|
||||
case ParamId.HIGHER_MODES_LIMIT:
|
||||
value = float(input("Specify parameter value to set [1]: "))
|
||||
q.add_pus_tc(
|
||||
create_load_param_cmd(
|
||||
create_scalar_float_parameter(
|
||||
object_id=PWR_CONTROLLER,
|
||||
domain_id=0,
|
||||
unique_id=ParamId.HIGHER_MODES_LIMIT,
|
||||
parameter=value,
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def handle_pwr_ctrl_hk_data(
|
||||
pw: PrintWrapper,
|
||||
set_id: int,
|
||||
hk_data: bytes,
|
||||
packet_time: datetime.datetime,
|
||||
):
|
||||
pw.ilog(_LOGGER, f"Received PWR CTRL HK with packet time {packet_time}")
|
||||
match set_id:
|
||||
case SetId.CORE_HK_SET:
|
||||
handle_core_hk_data(pw, hk_data)
|
||||
case SetId.ENABLE_PL_SET:
|
||||
handle_enable_pl_data(pw, hk_data)
|
||||
|
||||
|
||||
def handle_core_hk_data(pw: PrintWrapper, hk_data: bytes):
|
||||
pw.dlog("Received Core HK Set")
|
||||
fmt_int16 = "!h"
|
||||
fmt_float = "!f"
|
||||
inc_len_int16 = struct.calcsize(fmt_int16)
|
||||
inc_len_float = struct.calcsize(fmt_float)
|
||||
if len(hk_data) < inc_len_int16 + 2 * inc_len_float:
|
||||
pw.dlog("Received HK set too small")
|
||||
return
|
||||
current_idx = 0
|
||||
total_battery_current = struct.unpack(
|
||||
fmt_int16, hk_data[current_idx : current_idx + inc_len_int16]
|
||||
)[0]
|
||||
current_idx += inc_len_int16
|
||||
open_circuit_voltage_charge = struct.unpack(
|
||||
fmt_float, hk_data[current_idx : current_idx + inc_len_float]
|
||||
)[0]
|
||||
current_idx += inc_len_float
|
||||
coulomb_counter_charge = struct.unpack(
|
||||
fmt_float, hk_data[current_idx : current_idx + inc_len_float]
|
||||
)[0]
|
||||
current_idx += inc_len_float
|
||||
pw.dlog(f"Total Battery Current: {total_battery_current} [mA]")
|
||||
pw.dlog(f"Open Circuit Voltage Charge: {open_circuit_voltage_charge*100:8.3f} [%]")
|
||||
pw.dlog(f"Coulomb Counter Charge: {coulomb_counter_charge*100:8.3f} [%]")
|
||||
FsfwTmTcPrinter.get_validity_buffer(hk_data[current_idx:], num_vars=3)
|
||||
|
||||
|
||||
def handle_enable_pl_data(pw: PrintWrapper, hk_data: bytes):
|
||||
pw.dlog("Received Enable PL HK Set")
|
||||
fmt_uint16 = "!B"
|
||||
inc_len_uint16 = struct.calcsize(fmt_uint16)
|
||||
if len(hk_data) < inc_len_uint16:
|
||||
pw.dlog("Received HK set too small")
|
||||
return
|
||||
current_idx = 0
|
||||
pl_use_allowed = struct.unpack(
|
||||
fmt_uint16, hk_data[current_idx : current_idx + inc_len_uint16]
|
||||
)[0]
|
||||
current_idx += inc_len_uint16
|
||||
pw.dlog(f"PL Use Allowed: {pl_use_allowed}")
|
||||
FsfwTmTcPrinter.get_validity_buffer(hk_data[current_idx:], num_vars=1)
|
68
eive_tmtc/tmtc/power/subsystem.py
Normal file
68
eive_tmtc/tmtc/power/subsystem.py
Normal file
@ -0,0 +1,68 @@
|
||||
import enum
|
||||
from typing import Tuple, Dict
|
||||
|
||||
from spacepackets.ecss import PusTelecommand
|
||||
from eive_tmtc.tmtc.common import pack_mode_cmd_with_info
|
||||
from eive_tmtc.config.object_ids import EPS_SUBSYSTEM_ID
|
||||
from eive_tmtc.config.definitions import CustomServiceList
|
||||
from tmtccmd.config.tmtc import (
|
||||
tmtc_definitions_provider,
|
||||
TmtcDefinitionWrapper,
|
||||
OpCodeEntry,
|
||||
)
|
||||
from tmtccmd.tc.pus_200_fsfw_mode import Subservice as ModeSubservices, Mode
|
||||
from tmtccmd.tc import service_provider
|
||||
from tmtccmd.tc.decorator import ServiceProviderParams
|
||||
|
||||
|
||||
class OpCode(str, enum.Enum):
|
||||
OFF = "off"
|
||||
NML = "normal"
|
||||
REPORT_ALL_MODES = "all_modes"
|
||||
|
||||
|
||||
class Info(str, enum.Enum):
|
||||
OFF = "Off Mode Command"
|
||||
NML = "Normal Mode Command"
|
||||
REPORT_ALL_MODES = "Report All Modes Recursively"
|
||||
|
||||
|
||||
HANDLER_LIST: Dict[str, Tuple[int, int, str]] = {
|
||||
OpCode.OFF: (Mode.OFF, 0, Info.OFF),
|
||||
OpCode.NML: (Mode.NORMAL, 0, Info.NML),
|
||||
}
|
||||
|
||||
|
||||
@service_provider(CustomServiceList.EPS_SS.value)
|
||||
def build_eps_subsystem_cmd(p: ServiceProviderParams):
|
||||
op_code = p.op_code
|
||||
q = p.queue_helper
|
||||
info_prefix = "EPS Subsystem"
|
||||
if op_code in OpCode.REPORT_ALL_MODES:
|
||||
q.add_log_cmd(f"{info_prefix}: {Info.REPORT_ALL_MODES}")
|
||||
q.add_pus_tc(
|
||||
PusTelecommand(
|
||||
service=200,
|
||||
subservice=ModeSubservices.TC_MODE_ANNOUNCE_RECURSIVE,
|
||||
app_data=EPS_SUBSYSTEM_ID,
|
||||
)
|
||||
)
|
||||
mode_info_tup = HANDLER_LIST.get(op_code)
|
||||
if mode_info_tup is None:
|
||||
return
|
||||
pack_mode_cmd_with_info(
|
||||
object_id=EPS_SUBSYSTEM_ID,
|
||||
info=f"{info_prefix}: {mode_info_tup[2]}",
|
||||
mode=mode_info_tup[0],
|
||||
submode=mode_info_tup[1],
|
||||
q=q,
|
||||
)
|
||||
|
||||
|
||||
@tmtc_definitions_provider
|
||||
def add_eps_subsystem_cmds(defs: TmtcDefinitionWrapper):
|
||||
oce = OpCodeEntry()
|
||||
for op_code, (_, _, info) in HANDLER_LIST.items():
|
||||
oce.add(op_code, info)
|
||||
oce.add(OpCode.REPORT_ALL_MODES, Info.REPORT_ALL_MODES)
|
||||
defs.add_service(CustomServiceList.EPS_SS, "EPS Subsystem", oce)
|
@ -75,8 +75,8 @@ class WdtInfo:
|
||||
self.pw.dlog(wdt_info)
|
||||
for idx in range(len(self.wdt_reboots_list)):
|
||||
self.pw.dlog(
|
||||
f"{WDT_LIST[idx].ljust(5)} | "
|
||||
f"{self.wdt_reboots_list[idx]:010} | {self.time_pings_left_list[idx]:010}",
|
||||
f"{WDT_LIST[idx].ljust(5)} | {self.wdt_reboots_list[idx]:010} |"
|
||||
f" {self.time_pings_left_list[idx]:010}",
|
||||
)
|
||||
|
||||
def parse(self, wdt_data: bytes, current_idx: int) -> int:
|
||||
@ -327,8 +327,9 @@ def handle_p60_hk_data(pw: PrintWrapper, set_id: int, hk_data: bytes):
|
||||
)
|
||||
pw.dlog(misc_info)
|
||||
batt_info = (
|
||||
f"Batt Temp 0 {batt_temp_0 / 10.0} | Batt Temp 1 {batt_temp_1 / 10.0} | "
|
||||
f"Charge Current {batt_charge_current} | Discharge Current {batt_discharge_current}"
|
||||
f"Batt Temp 0 {batt_temp_0 / 10.0} | Batt Temp 1 {batt_temp_1 / 10.0} |"
|
||||
f" Charge Current {batt_charge_current} | Discharge Current"
|
||||
f" {batt_discharge_current}"
|
||||
)
|
||||
pw.dlog(batt_info)
|
||||
pw.dlog(
|
||||
@ -419,12 +420,12 @@ def handle_acu_hk_data(pw: PrintWrapper, set_id: int, hk_data: bytes):
|
||||
)
|
||||
pw.dlog(f"Boot Cause {boot_cause} | Reset Cause {reset_cause}")
|
||||
pw.dlog(
|
||||
f"Ground WDT: Reboot Count {wdt_cnt_gnd} | Time Left {wdt_gnd_time_left} sec"
|
||||
f"Ground WDT: Reboot Count {wdt_cnt_gnd} | Time Left"
|
||||
f" {wdt_gnd_time_left} sec"
|
||||
)
|
||||
|
||||
pw.dlog(
|
||||
"ACU Dev Types: 0:FRAM|1:ADC|2:ADC|3:DAC|4:DAC|"
|
||||
"5:DAC|6:TempSens|7:Reserved"
|
||||
"ACU Dev Types: 0:FRAM|1:ADC|2:ADC|3:DAC|4:DAC|5:DAC|6:TempSens|7:Reserved"
|
||||
)
|
||||
dev_parser.print(pw=pw)
|
||||
FsfwTmTcPrinter.get_validity_buffer(
|
||||
@ -474,7 +475,8 @@ def pdu_config_table_handler(
|
||||
pw.dlog("[tcs, syrlinks, str, mgt, sus-n, scex, ploc, acs-a, unused]")
|
||||
elif obj_id.as_bytes == PDU_2_HANDLER_ID:
|
||||
pw.dlog(
|
||||
"[obc, pl-pcdu-bat-nom, rw, heaters, sus-r, sa-depl, pl-pcdu-bat-red, acs-b, pl-cam]"
|
||||
"[obc, pl-pcdu-bat-nom, rw, heaters, sus-r, sa-depl, pl-pcdu-bat-red,"
|
||||
" acs-b, pl-cam]"
|
||||
)
|
||||
out_on_cnt = unpack_array_in_data(custom_data, 0x52, 2, 9, "H")
|
||||
out_off_cnt = unpack_array_in_data(custom_data, 0x64, 2, 9, "H")
|
||||
|
@ -12,8 +12,8 @@ from tmtccmd.tc.pus_3_fsfw_hk import (
|
||||
make_sid,
|
||||
generate_one_hk_command,
|
||||
create_request_one_diag_command,
|
||||
create_enable_periodic_hk_command_with_interval,
|
||||
create_request_one_hk_command,
|
||||
create_enable_periodic_hk_command_with_interval_with_diag,
|
||||
)
|
||||
|
||||
|
||||
@ -68,7 +68,7 @@ def pack_tcs_ctrl_commands(q: DefaultPusQueueHelper, op_code: str):
|
||||
)
|
||||
if op_code == OpCode.ENABLE_TEMP_SET:
|
||||
interval_seconds = float(input("Please specify interval in seconds: "))
|
||||
cmds = create_enable_periodic_hk_command_with_interval(
|
||||
cmds = create_enable_periodic_hk_command_with_interval_with_diag(
|
||||
False, make_sid(TCS_CONTROLLER, CtrlSetId.PRIMARY_SENSORS), interval_seconds
|
||||
)
|
||||
for cmd in cmds:
|
||||
|
@ -148,8 +148,8 @@ def time_prompt_offset_from_now() -> datetime.datetime:
|
||||
seconds_offset = math.floor(
|
||||
float(
|
||||
input(
|
||||
"Please enter the time as a offset from now in seconds. Negative offset is "
|
||||
"allowed: "
|
||||
"Please enter the time as a offset from now in seconds. Negative offset"
|
||||
" is allowed: "
|
||||
)
|
||||
)
|
||||
)
|
||||
|
42
lint.py
42
lint.py
@ -1,42 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
def main():
|
||||
exclude_dirs_flag = ""
|
||||
if not os.path.exists("setup.cfg"):
|
||||
exclude_dirs_flag = (
|
||||
"--exclude .git,__pycache__,docs/conf.py,old,build,dist,venv"
|
||||
)
|
||||
additional_flags_both_steps = "--count --statistics"
|
||||
additional_flags_first_step = "--select=E9,F63,F7,F82 --show-source"
|
||||
python_exe = ""
|
||||
if os.name == "nt":
|
||||
python_exe = "py -m"
|
||||
flake8_first_step_cmd = (
|
||||
f"{python_exe} flake8 . {additional_flags_both_steps} "
|
||||
f"{additional_flags_first_step} {exclude_dirs_flag}"
|
||||
)
|
||||
status = os.system(flake8_first_step_cmd)
|
||||
if os.name == "nt":
|
||||
if status != 0:
|
||||
print(f"Flake8 linter errors with status {status}")
|
||||
else:
|
||||
if os.WEXITSTATUS(status) != 0:
|
||||
print(f"Flake8 linter errors with status {status}")
|
||||
sys.exit(0)
|
||||
additional_flags_second_step = (
|
||||
'--exit-zero --max-complexity=10 --per-file-ignores="__init__.py:F401"'
|
||||
)
|
||||
if not os.path.exists("setup.cfg"):
|
||||
additional_flags_second_step += " --max-line-length=100"
|
||||
flake8_second_step_cmd = (
|
||||
f"{python_exe} flake8 . {additional_flags_both_steps} {additional_flags_second_step}"
|
||||
f" {exclude_dirs_flag}"
|
||||
)
|
||||
os.system(flake8_second_step_cmd)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
|
||||
name = "eive-tmtc"
|
||||
description = "TMTC Commander EIVE"
|
||||
readme = "README.md"
|
||||
dynamic = ["version"]
|
||||
version = "5.7.0"
|
||||
requires-python = ">=3.10"
|
||||
license = {text = "Apache-2.0"}
|
||||
authors = [
|
||||
@ -29,9 +29,9 @@ classifiers = [
|
||||
"Topic :: Scientific/Engineering"
|
||||
]
|
||||
dependencies = [
|
||||
"tmtccmd ~= 5.0",
|
||||
"tmtccmd ~= 6.0",
|
||||
"python-dateutil ~= 2.8",
|
||||
# "tmtccmd @ git+https://github.com/robamu-org/tmtccmd@1b110d321ef85#egg=tmtccmd"
|
||||
# "tmtccmd @ git+https://github.com/robamu-org/tmtccmd@main"
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
@ -40,9 +40,11 @@ dependencies = [
|
||||
[tool.setuptools]
|
||||
include-package-data = true
|
||||
|
||||
[tool.setuptools.dynamic]
|
||||
version = {attr = "eive_tmtc.__version__"}
|
||||
|
||||
# Auto-Discovery is problematic for some reason, so use custom-discovery
|
||||
[tool.setuptools.packages]
|
||||
find = {}
|
||||
|
||||
[tool.ruff]
|
||||
ignore = ["E501"]
|
||||
[tool.ruff.extend-per-file-ignores]
|
||||
"__init__.py" = ["F401"]
|
||||
|
@ -3,11 +3,11 @@ Checklist for new releases
|
||||
|
||||
# Pre-Release
|
||||
|
||||
1. Bump version inside the `eive_tmtc/__init__.py` file.
|
||||
1. Bump version inside the `pyproject.toml` file.
|
||||
2. Update `CHANGELOG.md`: Convert `unreleased` section into version section
|
||||
with date and new `unreleased`section.
|
||||
3. Run auto-formatter with `black .`
|
||||
4. Run linter with `flake8 .`
|
||||
4. Run linter with `ruff .`
|
||||
|
||||
# Post-Release
|
||||
|
||||
|
12
setup.py
12
setup.py
@ -1,12 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
We do the package handling in the static setup.cfg but include an empty setup.py
|
||||
to allow editable installs https://packaging.python.org/tutorials/packaging-projects/
|
||||
and provide extensibility
|
||||
"""
|
||||
try:
|
||||
from setuptools import setup
|
||||
except ImportError:
|
||||
from distutils.core import setup
|
||||
|
||||
setup()
|
288
tmtcc.py
288
tmtcc.py
@ -2,59 +2,28 @@
|
||||
import logging
|
||||
import sys
|
||||
import time
|
||||
import traceback
|
||||
from pathlib import Path
|
||||
from typing import cast
|
||||
|
||||
from spacepackets.ccsds import SPACE_PACKET_HEADER_SIZE
|
||||
import tmtccmd
|
||||
from eive_tmtc.cfdp.fault_handler import EiveCfdpFaultHandler
|
||||
from eive_tmtc.cfdp.tm import CfdpInCcsdsWrapper
|
||||
from eive_tmtc.cfdp.user import EiveCfdpUser
|
||||
from spacepackets.ecss import PusVerificator
|
||||
from spacepackets.version import get_version as get_sp_version
|
||||
from spacepackets.cfdp import (
|
||||
ConditionCode,
|
||||
ChecksumType,
|
||||
TransmissionMode,
|
||||
PduHolder,
|
||||
DirectiveType,
|
||||
PduFactory,
|
||||
PduType,
|
||||
)
|
||||
|
||||
from eive_tmtc.pus_tc.tc_handler import TcHandler
|
||||
from tmtccmd.logging import add_colorlog_console_logger
|
||||
from tmtccmd.cfdp import CfdpUserBase, TransactionId
|
||||
from tmtccmd.cfdp.defs import CfdpRequestType
|
||||
from tmtccmd.cfdp.handler import CfdpInCcsdsHandler
|
||||
from tmtccmd.cfdp.mib import (
|
||||
DefaultFaultHandlerBase,
|
||||
LocalEntityCfg,
|
||||
IndicationCfg,
|
||||
RemoteEntityCfg,
|
||||
)
|
||||
from tmtccmd.cfdp.user import (
|
||||
TransactionFinishedParams,
|
||||
MetadataRecvParams,
|
||||
FileSegmentRecvdParams,
|
||||
)
|
||||
from tmtccmd.tc.handler import SendCbParams
|
||||
|
||||
try:
|
||||
import spacepackets
|
||||
except ImportError as error:
|
||||
print(error)
|
||||
print("Python spacepackets module could not be imported")
|
||||
print(
|
||||
'Install with "cd spacepackets && python3 -m pip intall -e ." for interative installation'
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
import tmtccmd
|
||||
except ImportError:
|
||||
run_tmtc_commander = None
|
||||
initialize_tmtc_commander = None
|
||||
tb = traceback.format_exc()
|
||||
print(tb)
|
||||
print("Python tmtccmd submodule could not be imported")
|
||||
sys.exit(1)
|
||||
|
||||
from spacepackets.ecss import PusVerificator
|
||||
from tmtccmd import TcHandlerBase, BackendBase
|
||||
from tmtccmd import BackendBase
|
||||
from tmtccmd.util import FileSeqCountProvider, PusFileSeqCountProvider
|
||||
from tmtccmd.fsfw.tmtc_printer import FsfwTmTcPrinter
|
||||
|
||||
@ -66,15 +35,6 @@ from tmtccmd.logging.pus import (
|
||||
from tmtccmd.pus import VerificationWrapper
|
||||
from tmtccmd.tm import SpecificApidHandlerBase, GenericApidHandlerBase, CcsdsTmHandler
|
||||
from tmtccmd.core import BackendRequest
|
||||
from tmtccmd.logging import get_current_time_string
|
||||
from tmtccmd.tc import (
|
||||
ProcedureWrapper,
|
||||
FeedWrapper,
|
||||
TcProcedureType,
|
||||
TcQueueEntryType,
|
||||
DefaultPusQueueHelper,
|
||||
QueueWrapper,
|
||||
)
|
||||
from tmtccmd.config import (
|
||||
default_json_path,
|
||||
SetupWrapper,
|
||||
@ -86,7 +46,7 @@ from tmtccmd.config.args import (
|
||||
ProcedureParamsWrapper,
|
||||
)
|
||||
from eive_tmtc import APP_LOGGER
|
||||
from eive_tmtc import __version__
|
||||
from importlib.metadata import version
|
||||
from eive_tmtc.config.definitions import (
|
||||
PUS_APID,
|
||||
CFDP_APID,
|
||||
@ -95,7 +55,6 @@ from eive_tmtc.config.definitions import (
|
||||
)
|
||||
from eive_tmtc.config.hook import EiveHookObject
|
||||
from eive_tmtc.pus_tm.pus_demux import pus_factory_hook
|
||||
from eive_tmtc.pus_tc.procedure_packer import handle_default_procedure
|
||||
|
||||
_LOGGER = APP_LOGGER
|
||||
_LOG_LEVEL = logging.INFO
|
||||
@ -105,61 +64,6 @@ ROTATING_TIMED_LOGGER_INTERVAL_WHEN = TimedLogWhen.PER_MINUTE
|
||||
ROTATING_TIMED_LOGGER_INTERVAL = 30
|
||||
|
||||
|
||||
class EiveCfdpFaultHandler(DefaultFaultHandlerBase):
|
||||
def notice_of_suspension_cb(self, cond: ConditionCode):
|
||||
pass
|
||||
|
||||
def notice_of_cancellation_cb(self, cond: ConditionCode):
|
||||
pass
|
||||
|
||||
def abandoned_cb(self, cond: ConditionCode):
|
||||
pass
|
||||
|
||||
def ignore_cb(self, cond: ConditionCode):
|
||||
pass
|
||||
|
||||
|
||||
class EiveCfdpUser(CfdpUserBase):
|
||||
def transaction_indication(self, transaction_id: TransactionId):
|
||||
_LOGGER.info(f"CFDP User: Start of File {transaction_id}")
|
||||
|
||||
def eof_sent_indication(self, transaction_id: TransactionId):
|
||||
_LOGGER.info(f"CFDP User: EOF sent for {transaction_id}")
|
||||
|
||||
def transaction_finished_indication(self, params: TransactionFinishedParams):
|
||||
_LOGGER.info(f"CFDP User: {params.transaction_id} finished")
|
||||
|
||||
def metadata_recv_indication(self, params: MetadataRecvParams):
|
||||
pass
|
||||
|
||||
def file_segment_recv_indication(self, params: FileSegmentRecvdParams):
|
||||
pass
|
||||
|
||||
def report_indication(self, transaction_id: TransactionId, status_report: any):
|
||||
pass
|
||||
|
||||
def suspended_indication(
|
||||
self, transaction_id: TransactionId, cond_code: ConditionCode
|
||||
):
|
||||
pass
|
||||
|
||||
def resumed_indication(self, transaction_id: TransactionId, progress: int):
|
||||
pass
|
||||
|
||||
def fault_indication(
|
||||
self, transaction_id: TransactionId, cond_code: ConditionCode, progress: int
|
||||
):
|
||||
pass
|
||||
|
||||
def abandoned_indication(
|
||||
self, transaction_id: TransactionId, cond_code: ConditionCode, progress: int
|
||||
):
|
||||
pass
|
||||
|
||||
def eof_recv_indication(self, transaction_id: TransactionId):
|
||||
pass
|
||||
|
||||
|
||||
class PusHandler(SpecificApidHandlerBase):
|
||||
def __init__(
|
||||
self,
|
||||
@ -194,151 +98,6 @@ class CustomCcsdsTmHandler(CcsdsTmHandler):
|
||||
_LOGGER.debug(f"Received packet {packet.hex(sep=',')} with APID {apid}")
|
||||
|
||||
|
||||
class CfdpInCcsdsWrapper(SpecificApidHandlerBase):
|
||||
def __init__(self, cfdp_in_ccsds_handler: CfdpInCcsdsHandler):
|
||||
super().__init__(CFDP_APID, None)
|
||||
self.handler = cfdp_in_ccsds_handler
|
||||
|
||||
def handle_tm(self, packet: bytes, _user_args: any):
|
||||
# Ignore the space packet header. Its only purpose is to use the same protocol and
|
||||
# have a seaprate APID for space packets. If this function is called, the APID is correct.
|
||||
pdu = packet[SPACE_PACKET_HEADER_SIZE:]
|
||||
pdu_base = PduFactory.from_raw(pdu)
|
||||
if pdu_base.pdu_type == PduType.FILE_DATA:
|
||||
_LOGGER.info("Received File Data PDU TM")
|
||||
else:
|
||||
if pdu_base.directive_type == DirectiveType.FINISHED_PDU:
|
||||
_LOGGER.info("Received Finished PDU TM")
|
||||
else:
|
||||
_LOGGER.info(
|
||||
f"Received File Directive PDU with type {pdu_base.directive_type!r} TM"
|
||||
)
|
||||
self.handler.pass_pdu_packet(pdu_base)
|
||||
|
||||
|
||||
class TcHandler(TcHandlerBase):
|
||||
def __init__(
|
||||
self,
|
||||
seq_count_provider: FileSeqCountProvider,
|
||||
cfdp_in_ccsds_wrapper: CfdpInCcsdsWrapper,
|
||||
pus_verificator: PusVerificator,
|
||||
high_level_file_logger: logging.Logger,
|
||||
raw_pus_logger: RawTmtcTimedLogWrapper,
|
||||
gui: bool,
|
||||
):
|
||||
super().__init__()
|
||||
self.cfdp_handler_started = False
|
||||
self.cfdp_dest_id = CFDP_REMOTE_ENTITY_ID
|
||||
self.seq_count_provider = seq_count_provider
|
||||
self.pus_verificator = pus_verificator
|
||||
self.high_level_file_logger = high_level_file_logger
|
||||
self.pus_raw_logger = raw_pus_logger
|
||||
self.gui = gui
|
||||
self.queue_helper = DefaultPusQueueHelper(
|
||||
queue_wrapper=QueueWrapper.empty(),
|
||||
default_pus_apid=PUS_APID,
|
||||
seq_cnt_provider=seq_count_provider,
|
||||
pus_verificator=pus_verificator,
|
||||
tc_sched_timestamp_len=4,
|
||||
)
|
||||
self.cfdp_in_ccsds_wrapper = cfdp_in_ccsds_wrapper
|
||||
|
||||
def cfdp_done(self) -> bool:
|
||||
if self.cfdp_handler_started:
|
||||
if not self.cfdp_in_ccsds_wrapper.handler.put_request_pending():
|
||||
self.cfdp_handler_started = False
|
||||
return True
|
||||
return False
|
||||
|
||||
def feed_cb(self, info: ProcedureWrapper, wrapper: FeedWrapper):
|
||||
self.queue_helper.queue_wrapper = wrapper.queue_wrapper
|
||||
if info.proc_type == TcProcedureType.DEFAULT:
|
||||
handle_default_procedure(self, info.to_def_procedure(), self.queue_helper)
|
||||
elif info.proc_type == TcProcedureType.CFDP:
|
||||
self.handle_cfdp_procedure(info)
|
||||
|
||||
def send_cb(self, send_params: SendCbParams):
|
||||
entry_helper = send_params.entry
|
||||
if entry_helper.is_tc:
|
||||
if entry_helper.entry_type == TcQueueEntryType.PUS_TC:
|
||||
pus_tc_wrapper = entry_helper.to_pus_tc_entry()
|
||||
# pus_tc_wrapper.pus_tc.apid = PUS_APID
|
||||
raw_tc = pus_tc_wrapper.pus_tc.pack()
|
||||
self.pus_raw_logger.log_tc(pus_tc_wrapper.pus_tc)
|
||||
tc_info_string = f"Sent {pus_tc_wrapper.pus_tc}"
|
||||
_LOGGER.info(tc_info_string)
|
||||
self.high_level_file_logger.info(
|
||||
f"{get_current_time_string(True)}: {tc_info_string}"
|
||||
)
|
||||
# with open("tc.bin", "wb") as of:
|
||||
# of.write(raw_tc)
|
||||
send_params.com_if.send(raw_tc)
|
||||
elif entry_helper.entry_type == TcQueueEntryType.CCSDS_TC:
|
||||
cfdp_packet_in_ccsds = entry_helper.to_space_packet_entry()
|
||||
send_params.com_if.send(cfdp_packet_in_ccsds.space_packet.pack())
|
||||
# TODO: Log raw CFDP packets similarly to how PUS packets are logged.
|
||||
# - Log full raw format including space packet wrapper
|
||||
# - Log context information: Transaction ID, and PDU type and directive
|
||||
# Could re-use file logger. Should probably do that
|
||||
# print(f"sending packet: [{cfdp_packet_in_ccsds.space_packet.pack()}]")
|
||||
# with open(f"cfdp_packet_{self.cfdp_counter}", "wb") as of:
|
||||
# of.write(cfdp_packet_in_ccsds.space_packet.pack())
|
||||
# self.cfdp_counter += 1
|
||||
elif entry_helper.entry_type == TcQueueEntryType.LOG:
|
||||
log_entry = entry_helper.to_log_entry()
|
||||
_LOGGER.info(log_entry.log_str)
|
||||
self.high_level_file_logger.info(log_entry.log_str)
|
||||
|
||||
def handle_cfdp_procedure(self, info: ProcedureWrapper):
|
||||
cfdp_procedure = info.to_cfdp_procedure()
|
||||
if cfdp_procedure.cfdp_request_type == CfdpRequestType.PUT:
|
||||
if (
|
||||
not self.cfdp_in_ccsds_wrapper.handler.put_request_pending()
|
||||
and not self.cfdp_handler_started
|
||||
):
|
||||
put_req = cfdp_procedure.request_wrapper.to_put_request()
|
||||
put_req.cfg.destination_id = self.cfdp_dest_id
|
||||
_LOGGER.info(
|
||||
f"CFDP: Starting file put request with parameters:\n{put_req}"
|
||||
)
|
||||
self.cfdp_in_ccsds_wrapper.handler.cfdp_handler.put_request(put_req)
|
||||
self.cfdp_handler_started = True
|
||||
|
||||
for source_pair, dest_pair in self.cfdp_in_ccsds_wrapper.handler:
|
||||
pdu, sp = source_pair
|
||||
pdu = cast(PduHolder, pdu)
|
||||
if pdu.is_file_directive:
|
||||
if pdu.pdu_directive_type == DirectiveType.METADATA_PDU:
|
||||
metadata = pdu.to_metadata_pdu()
|
||||
self.queue_helper.add_log_cmd(
|
||||
f"CFDP Source: Sending Metadata PDU for file with size "
|
||||
f"{metadata.file_size}"
|
||||
)
|
||||
elif pdu.pdu_directive_type == DirectiveType.EOF_PDU:
|
||||
self.queue_helper.add_log_cmd(
|
||||
"CFDP Source: Sending EOF PDU"
|
||||
)
|
||||
else:
|
||||
fd_pdu = pdu.to_file_data_pdu()
|
||||
self.queue_helper.add_log_cmd(
|
||||
f"CFDP Source: Sending File Data PDU for segment at offset "
|
||||
f"{fd_pdu.offset} with length {len(fd_pdu.file_data)}"
|
||||
)
|
||||
self.queue_helper.add_ccsds_tc(sp)
|
||||
self.cfdp_in_ccsds_wrapper.handler.confirm_source_packet_sent()
|
||||
self.cfdp_in_ccsds_wrapper.handler.source_handler.state_machine()
|
||||
|
||||
def queue_finished_cb(self, info: ProcedureWrapper):
|
||||
if info is not None:
|
||||
if info.proc_type == TcQueueEntryType.PUS_TC:
|
||||
def_proc = info.to_def_procedure()
|
||||
_LOGGER.info(
|
||||
f"Finished queue for service {def_proc.service} and op code {def_proc.op_code}"
|
||||
)
|
||||
elif info.proc_type == TcProcedureType.CFDP:
|
||||
_LOGGER.info("Finished CFDP queue")
|
||||
|
||||
|
||||
def setup_params() -> (SetupWrapper, int):
|
||||
hook_obj = EiveHookObject(default_json_path())
|
||||
params = SetupParams()
|
||||
@ -361,7 +120,10 @@ def setup_params() -> (SetupWrapper, int):
|
||||
post_arg_parsing_wrapper.set_params_with_prompts(proc_param_wrapper)
|
||||
else:
|
||||
post_arg_parsing_wrapper.set_params_without_prompts(proc_param_wrapper)
|
||||
hk_level = int(post_arg_parsing_wrapper.args_raw.hk)
|
||||
if hasattr(post_arg_parsing_wrapper.args_raw, "hk"):
|
||||
hk_level = int(post_arg_parsing_wrapper.args_raw.hk)
|
||||
else:
|
||||
hk_level = 0
|
||||
params.apid = PUS_APID
|
||||
if params.com_if is None:
|
||||
raise ValueError("could not determine a COM interface.")
|
||||
@ -378,6 +140,15 @@ def setup_cfdp_handler() -> CfdpInCcsdsWrapper:
|
||||
indication_cfg=IndicationCfg(),
|
||||
default_fault_handlers=fh_base,
|
||||
)
|
||||
self_as_remote = RemoteEntityCfg(
|
||||
closure_requested=False,
|
||||
entity_id=CFDP_LOCAL_ENTITY_ID,
|
||||
max_file_segment_len=990,
|
||||
check_limit=None,
|
||||
crc_on_transmission=False,
|
||||
crc_type=ChecksumType.CRC_32,
|
||||
default_transmission_mode=TransmissionMode.UNACKNOWLEDGED,
|
||||
)
|
||||
remote_cfg = RemoteEntityCfg(
|
||||
closure_requested=False,
|
||||
entity_id=CFDP_REMOTE_ENTITY_ID,
|
||||
@ -396,7 +167,7 @@ def setup_cfdp_handler() -> CfdpInCcsdsWrapper:
|
||||
cfdp_user = EiveCfdpUser()
|
||||
cfdp_in_ccsds_handler = CfdpInCcsdsHandler(
|
||||
cfg=cfdp_cfg,
|
||||
remote_cfgs=[remote_cfg],
|
||||
remote_cfgs=[remote_cfg, self_as_remote],
|
||||
ccsds_apid=CFDP_APID,
|
||||
ccsds_seq_cnt_provider=cfdp_ccsds_seq_count_provider,
|
||||
cfdp_seq_cnt_provider=cfdp_seq_count_provider,
|
||||
@ -427,7 +198,7 @@ def setup_tmtc_handlers(
|
||||
high_level_file_logger=printer.file_logger,
|
||||
raw_pus_logger=raw_logger,
|
||||
gui=gui,
|
||||
cfdp_in_ccsds_wrapper=cfdp_in_ccsds_wrapper,
|
||||
cfdp_in_ccsds_handler=cfdp_in_ccsds_wrapper.handler,
|
||||
)
|
||||
return ccsds_handler, tc_handler
|
||||
|
||||
@ -449,8 +220,8 @@ def setup_backend(
|
||||
|
||||
|
||||
def main(): # noqa C901: Complexity okay here.
|
||||
print(f"-- eive tmtc v{__version__} --")
|
||||
print(f"-- spacepackets v{spacepackets.__version__} --")
|
||||
print(f"-- eive tmtc v{version('eive-tmtc')} --")
|
||||
print(f"-- spacepackets v{get_sp_version()} --")
|
||||
add_colorlog_console_logger(_LOGGER)
|
||||
# TODO: -V CLI argument to enable this?
|
||||
_LOGGER.setLevel(_LOG_LEVEL)
|
||||
@ -478,13 +249,16 @@ def main(): # noqa C901: Complexity okay here.
|
||||
try:
|
||||
while True:
|
||||
state = tmtc_backend.periodic_op(None)
|
||||
tc_handler.cfdp_in_ccsds_wrapper.handler.fsm()
|
||||
tc_handler.cfdp_in_ccsds_handler.state_machine()
|
||||
if state.request == BackendRequest.TERMINATION_NO_ERROR:
|
||||
sys.exit(0)
|
||||
elif state.request == BackendRequest.DELAY_IDLE:
|
||||
_LOGGER.info("TMTC Client in IDLE mode")
|
||||
time.sleep(3.0)
|
||||
elif state.request == BackendRequest.DELAY_LISTENER:
|
||||
if tc_handler.proxy_op:
|
||||
time.sleep(0.1)
|
||||
continue
|
||||
if tc_handler.cfdp_done():
|
||||
_LOGGER.info("CFDP transaction done, closing client")
|
||||
sys.exit(0)
|
||||
|
Reference in New Issue
Block a user