diff --git a/.gitignore b/.gitignore index 754bc9f09a550be8eda2fe17f67ad5ce9f128085..ff456d6912b537e7a9fb03f28635b2d78c449818 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,3 @@ -obsw_user_code.py - _build/* _dependencies/* _bin/* diff --git a/.idea/runConfigurations/tmtcclient_Binary_Upload_Serial.xml b/.idea/runConfigurations/tmtcclient_Binary_Upload_Serial.xml new file mode 100644 index 0000000000000000000000000000000000000000..1ea009cce7889d056cdffd4c6141e644cdb073df --- /dev/null +++ b/.idea/runConfigurations/tmtcclient_Binary_Upload_Serial.xml @@ -0,0 +1,24 @@ +<component name="ProjectRunConfigurationManager"> + <configuration default="false" name="tmtcclient Binary Upload Serial" type="PythonConfigurationType" factoryName="Python" folderName="Serial SD-Card and Image"> + <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$/tmtc_client_cli.py" /> + <option name="PARAMETERS" value="-m 5 -c 1" /> + <option name="SHOW_COMMAND_LINE" value="false" /> + <option name="EMULATE_TERMINAL" value="true" /> + <option name="MODULE_MODE" value="false" /> + <option name="REDIRECT_INPUT" value="false" /> + <option name="INPUT_FILE" value="" /> + <method v="2" /> + </configuration> +</component> \ No newline at end of file diff --git a/.idea/runConfigurations/tmtcclient_Software_Serial.xml b/.idea/runConfigurations/tmtcclient_CLI.xml similarity index 75% rename from .idea/runConfigurations/tmtcclient_Software_Serial.xml rename to .idea/runConfigurations/tmtcclient_CLI.xml index 0dfd7b192a6af6da43bb59f26b4b1c33c7030405..3fff92f9f52936c715fe17aca61e15aac6db9efc 100644 --- a/.idea/runConfigurations/tmtcclient_Software_Serial.xml +++ b/.idea/runConfigurations/tmtcclient_CLI.xml @@ -1,5 +1,5 @@ <component name="ProjectRunConfigurationManager"> - <configuration default="false" name="tmtcclient Software Serial" type="PythonConfigurationType" factoryName="Python" folderName="Serial Communication"> + <configuration default="false" name="tmtcclient CLI" type="PythonConfigurationType" factoryName="Python"> <module name="tmtc" /> <option name="INTERPRETER_OPTIONS" value="" /> <option name="PARENT_ENVS" value="true" /> @@ -12,8 +12,8 @@ <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$/obsw_tmtc_client.py" /> - <option name="PARAMETERS" value="-m 4 -c 1 --hk -t 2.5" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/tmtc_client_cli.py" /> + <option name="PARAMETERS" value="" /> <option name="SHOW_COMMAND_LINE" value="false" /> <option name="EMULATE_TERMINAL" value="false" /> <option name="MODULE_MODE" value="false" /> diff --git a/.idea/runConfigurations/tmtcclient_Clear_SD_Card_.xml b/.idea/runConfigurations/tmtcclient_Clear_SD_Card_.xml new file mode 100644 index 0000000000000000000000000000000000000000..44da0a930bf8625b82da82554d98660f440a5520 --- /dev/null +++ b/.idea/runConfigurations/tmtcclient_Clear_SD_Card_.xml @@ -0,0 +1,24 @@ +<component name="ProjectRunConfigurationManager"> + <configuration default="false" name="tmtcclient Clear SD-Card " type="PythonConfigurationType" factoryName="Python" folderName="Serial SD-Card and Image"> + <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$/tmtc_client_cli.py" /> + <option name="PARAMETERS" value="-m 3 -s SD -o A20 -c 1 -t 2.5" /> + <option name="SHOW_COMMAND_LINE" value="false" /> + <option name="EMULATE_TERMINAL" value="true" /> + <option name="MODULE_MODE" value="false" /> + <option name="REDIRECT_INPUT" value="false" /> + <option name="INPUT_FILE" value="" /> + <method v="2" /> + </configuration> +</component> \ No newline at end of file diff --git a/.idea/runConfigurations/tmtcclient_Copy_Bootloader.xml b/.idea/runConfigurations/tmtcclient_Copy_Bootloader.xml new file mode 100644 index 0000000000000000000000000000000000000000..736bcabfd2d44298567bb23488fc72e175261a20 --- /dev/null +++ b/.idea/runConfigurations/tmtcclient_Copy_Bootloader.xml @@ -0,0 +1,24 @@ +<component name="ProjectRunConfigurationManager"> + <configuration default="false" name="tmtcclient Copy Bootloader" type="PythonConfigurationType" factoryName="Python" folderName="Serial SD-Card and Image"> + <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$/tmtc_client_cli.py" /> + <option name="PARAMETERS" value="-m 3 -s Img -o A11S -c 1 -t 4" /> + <option name="SHOW_COMMAND_LINE" value="false" /> + <option name="EMULATE_TERMINAL" value="true" /> + <option name="MODULE_MODE" value="false" /> + <option name="REDIRECT_INPUT" value="false" /> + <option name="INPUT_FILE" value="" /> + <method v="2" /> + </configuration> +</component> \ No newline at end of file diff --git a/.idea/runConfigurations/tmtcclient_Copy_OBSW_Update.xml b/.idea/runConfigurations/tmtcclient_Copy_OBSW_Update.xml new file mode 100644 index 0000000000000000000000000000000000000000..5da1e90b560d3818ec94438c15516f7203be48b3 --- /dev/null +++ b/.idea/runConfigurations/tmtcclient_Copy_OBSW_Update.xml @@ -0,0 +1,24 @@ +<component name="ProjectRunConfigurationManager"> + <configuration default="false" name="tmtcclient Copy OBSW Update" type="PythonConfigurationType" factoryName="Python" folderName="Serial SD-Card and Image"> + <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$/tmtc_client_cli.py" /> + <option name="PARAMETERS" value="-m 3 -s Img -o A4U -c 1 -t 4" /> + <option name="SHOW_COMMAND_LINE" value="false" /> + <option name="EMULATE_TERMINAL" value="true" /> + <option name="MODULE_MODE" value="false" /> + <option name="REDIRECT_INPUT" value="false" /> + <option name="INPUT_FILE" value="" /> + <method v="2" /> + </configuration> +</component> \ No newline at end of file diff --git a/.idea/runConfigurations/tmtcclient_Create_File_Struct_AT91.xml b/.idea/runConfigurations/tmtcclient_Create_File_Struct_AT91.xml new file mode 100644 index 0000000000000000000000000000000000000000..c6f1d6803daa7b6e151b38e5659b81fa811dd892 --- /dev/null +++ b/.idea/runConfigurations/tmtcclient_Create_File_Struct_AT91.xml @@ -0,0 +1,24 @@ +<component name="ProjectRunConfigurationManager"> + <configuration default="false" name="tmtcclient Create File Struct AT91" type="PythonConfigurationType" factoryName="Python" folderName="Serial SD-Card and Image"> + <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$/tmtc_client_cli.py" /> + <option name="PARAMETERS" value="-m 3 -s SD -o C0A -c 1 -t 2.5" /> + <option name="SHOW_COMMAND_LINE" value="false" /> + <option name="EMULATE_TERMINAL" value="true" /> + <option name="MODULE_MODE" value="false" /> + <option name="REDIRECT_INPUT" value="false" /> + <option name="INPUT_FILE" value="" /> + <method v="2" /> + </configuration> +</component> \ No newline at end of file diff --git a/.idea/runConfigurations/tmtcclient_Disable_Periodic_Print_.xml b/.idea/runConfigurations/tmtcclient_Disable_Periodic_Print_.xml new file mode 100644 index 0000000000000000000000000000000000000000..0e02490417cea00fc0c0d247dcf7eccd85b77b38 --- /dev/null +++ b/.idea/runConfigurations/tmtcclient_Disable_Periodic_Print_.xml @@ -0,0 +1,24 @@ +<component name="ProjectRunConfigurationManager"> + <configuration default="false" name="tmtcclient Disable Periodic Print " type="PythonConfigurationType" factoryName="Python" folderName="Serial Utility"> + <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$/tmtc_client_cli.py" /> + <option name="PARAMETERS" value="-m 3 -s 17 -o 130 -c 1 -t 2.2" /> + <option name="SHOW_COMMAND_LINE" value="false" /> + <option name="EMULATE_TERMINAL" value="true" /> + <option name="MODULE_MODE" value="false" /> + <option name="REDIRECT_INPUT" value="false" /> + <option name="INPUT_FILE" value="" /> + <method v="2" /> + </configuration> +</component> \ No newline at end of file diff --git a/.idea/runConfigurations/tmtcclient_Dummy_UDP.xml b/.idea/runConfigurations/tmtcclient_Dummy_UDP.xml index f591aac987e2c7e3c3038ad565a68c9404b06266..8d3a1fc9ee91099739631f163b2f072d09c32ab8 100644 --- a/.idea/runConfigurations/tmtcclient_Dummy_UDP.xml +++ b/.idea/runConfigurations/tmtcclient_Dummy_UDP.xml @@ -12,7 +12,7 @@ <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$/obsw_tmtc_client.py" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/core/tmtc_client_core.py" /> <option name="PARAMETERS" value="-m 3 -c 3 -s Dummy -t 3" /> <option name="SHOW_COMMAND_LINE" value="false" /> <option name="EMULATE_TERMINAL" value="true" /> diff --git a/.idea/runConfigurations/tmtcclient_Enable_Periodic_Print.xml b/.idea/runConfigurations/tmtcclient_Enable_Periodic_Print.xml new file mode 100644 index 0000000000000000000000000000000000000000..73417998676784fcda6e5155a672f1e0211fce7c --- /dev/null +++ b/.idea/runConfigurations/tmtcclient_Enable_Periodic_Print.xml @@ -0,0 +1,24 @@ +<component name="ProjectRunConfigurationManager"> + <configuration default="false" name="tmtcclient Enable Periodic Print" type="PythonConfigurationType" factoryName="Python" folderName="Serial Utility"> + <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$/tmtc_client_cli.py" /> + <option name="PARAMETERS" value="-m 3 -s 17 -o 129 -c 1 -t 2.2" /> + <option name="SHOW_COMMAND_LINE" value="false" /> + <option name="EMULATE_TERMINAL" value="true" /> + <option name="MODULE_MODE" value="false" /> + <option name="REDIRECT_INPUT" value="false" /> + <option name="INPUT_FILE" value="" /> + <method v="2" /> + </configuration> +</component> \ No newline at end of file diff --git a/.idea/runConfigurations/tmtcclient_Format_SD_Card_.xml b/.idea/runConfigurations/tmtcclient_Format_SD_Card_.xml new file mode 100644 index 0000000000000000000000000000000000000000..455cfed9156e5b7daca84fa9b650634aa46df8c5 --- /dev/null +++ b/.idea/runConfigurations/tmtcclient_Format_SD_Card_.xml @@ -0,0 +1,24 @@ +<component name="ProjectRunConfigurationManager"> + <configuration default="false" name="tmtcclient Format SD-Card " type="PythonConfigurationType" factoryName="Python" folderName="Serial SD-Card and Image"> + <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$/tmtc_client_cli.py" /> + <option name="PARAMETERS" value="-m 3 -s SD -o A21 -c 1 -t 2.5" /> + <option name="SHOW_COMMAND_LINE" value="false" /> + <option name="EMULATE_TERMINAL" value="true" /> + <option name="MODULE_MODE" value="false" /> + <option name="REDIRECT_INPUT" value="false" /> + <option name="INPUT_FILE" value="" /> + <method v="2" /> + </configuration> +</component> \ No newline at end of file diff --git a/.idea/runConfigurations/tmtcclient_GPS0_Serial.xml b/.idea/runConfigurations/tmtcclient_GPS0_Serial.xml index 0f8cd5fea5235267554c57f05839890d0fdd1617..c7a506c644d571a404d22dca29e26e433951d5bf 100644 --- a/.idea/runConfigurations/tmtcclient_GPS0_Serial.xml +++ b/.idea/runConfigurations/tmtcclient_GPS0_Serial.xml @@ -1,5 +1,5 @@ <component name="ProjectRunConfigurationManager"> - <configuration default="false" name="tmtcclient GPS0 Serial" type="PythonConfigurationType" factoryName="Python" folderName="Serial Communication"> + <configuration default="false" name="tmtcclient GPS0 Serial" type="PythonConfigurationType" factoryName="Python" folderName="Serial Service Test"> <module name="tmtc" /> <option name="INTERPRETER_OPTIONS" value="" /> <option name="PARENT_ENVS" value="true" /> @@ -12,7 +12,7 @@ <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$/obsw_tmtc_client.py" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/tmtc_client_cli.py" /> <option name="PARAMETERS" value="-m 3 -s GPS0 -c 1 --hk -t 3" /> <option name="SHOW_COMMAND_LINE" value="false" /> <option name="EMULATE_TERMINAL" value="true" /> diff --git a/.idea/runConfigurations/tmtcclient_GPS1_Serial.xml b/.idea/runConfigurations/tmtcclient_GPS1_Serial.xml index 1f8098a72d1b52a387c0256e35fa3cebdb4ccfae..a6623ad0098f1d2678150becbabca84296cf88a1 100644 --- a/.idea/runConfigurations/tmtcclient_GPS1_Serial.xml +++ b/.idea/runConfigurations/tmtcclient_GPS1_Serial.xml @@ -1,5 +1,5 @@ <component name="ProjectRunConfigurationManager"> - <configuration default="false" name="tmtcclient GPS1 Serial" type="PythonConfigurationType" factoryName="Python" folderName="Serial Communication"> + <configuration default="false" name="tmtcclient GPS1 Serial" type="PythonConfigurationType" factoryName="Python" folderName="Serial Service Test"> <module name="tmtc" /> <option name="INTERPRETER_OPTIONS" value="" /> <option name="PARENT_ENVS" value="true" /> @@ -12,7 +12,7 @@ <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$/obsw_tmtc_client.py" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/tmtc_client_cli.py" /> <option name="PARAMETERS" value="-m 3 -s GPS1 -c 1 -t 3" /> <option name="SHOW_COMMAND_LINE" value="false" /> <option name="EMULATE_TERMINAL" value="true" /> diff --git a/.idea/runConfigurations/tmtcclient_GUI.xml b/.idea/runConfigurations/tmtcclient_GUI.xml index 6ae7919b09fd2b1514488e8ab73c7b964ebf0c64..7dd7c34ab2e002427304aad205be2c0b137a0e44 100644 --- a/.idea/runConfigurations/tmtcclient_GUI.xml +++ b/.idea/runConfigurations/tmtcclient_GUI.xml @@ -12,8 +12,8 @@ <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$/obsw_tmtc_client.py" /> - <option name="PARAMETERS" value="-m 0" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/tmtc_client_gui.py" /> + <option name="PARAMETERS" value="" /> <option name="SHOW_COMMAND_LINE" value="false" /> <option name="EMULATE_TERMINAL" value="false" /> <option name="MODULE_MODE" value="false" /> diff --git a/.idea/runConfigurations/tmtcclient_Hamming_from_FRAM.xml b/.idea/runConfigurations/tmtcclient_Hamming_from_FRAM.xml new file mode 100644 index 0000000000000000000000000000000000000000..34f82294477bd8f4553ea425b1297a44699fc91e --- /dev/null +++ b/.idea/runConfigurations/tmtcclient_Hamming_from_FRAM.xml @@ -0,0 +1,24 @@ +<component name="ProjectRunConfigurationManager"> + <configuration default="false" name="tmtcclient Hamming from FRAM" type="PythonConfigurationType" factoryName="Python" folderName="Serial SD-Card and Image"> + <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$/tmtc_client_cli.py" /> + <option name="PARAMETERS" value="-m 3 -c 1 -s Img -o P1 -t 3" /> + <option name="SHOW_COMMAND_LINE" value="false" /> + <option name="EMULATE_TERMINAL" value="true" /> + <option name="MODULE_MODE" value="false" /> + <option name="REDIRECT_INPUT" value="false" /> + <option name="INPUT_FILE" value="" /> + <method v="2" /> + </configuration> +</component> \ No newline at end of file diff --git a/.idea/runConfigurations/tmtcclient_Hamming_from_SD.xml b/.idea/runConfigurations/tmtcclient_Hamming_from_SD.xml new file mode 100644 index 0000000000000000000000000000000000000000..886cb5a0638f95667d240ce2ae51d2c3efc0fd51 --- /dev/null +++ b/.idea/runConfigurations/tmtcclient_Hamming_from_SD.xml @@ -0,0 +1,24 @@ +<component name="ProjectRunConfigurationManager"> + <configuration default="false" name="tmtcclient Hamming from SD" type="PythonConfigurationType" factoryName="Python" folderName="Serial SD-Card and Image"> + <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$/tmtc_client_cli.py" /> + <option name="PARAMETERS" value="-m 3 -c 1 -s Img -o P0 -t 3" /> + <option name="SHOW_COMMAND_LINE" value="false" /> + <option name="EMULATE_TERMINAL" value="true" /> + <option name="MODULE_MODE" value="false" /> + <option name="REDIRECT_INPUT" value="false" /> + <option name="INPUT_FILE" value="" /> + <method v="2" /> + </configuration> +</component> \ No newline at end of file diff --git a/.idea/runConfigurations/tmtcclient_Help.xml b/.idea/runConfigurations/tmtcclient_Help.xml index 6aece9026d223bfd963b60d15dc2fe90cc60130e..1ce63fbd7352d94774f10a0e4d7bd2cb4385e5c1 100644 --- a/.idea/runConfigurations/tmtcclient_Help.xml +++ b/.idea/runConfigurations/tmtcclient_Help.xml @@ -12,7 +12,7 @@ <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$/obsw_tmtc_client.py" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/tmtc_client_cli.py" /> <option name="PARAMETERS" value="-h" /> <option name="SHOW_COMMAND_LINE" value="false" /> <option name="EMULATE_TERMINAL" value="false" /> diff --git a/.idea/runConfigurations/tmtcclient_Listener_Serial.xml b/.idea/runConfigurations/tmtcclient_Listener_Serial.xml index c59efdb836593429d3c211d1ed21f814c1a13177..caf110fdf15843a00e038d4ae9df69dab0104517 100644 --- a/.idea/runConfigurations/tmtcclient_Listener_Serial.xml +++ b/.idea/runConfigurations/tmtcclient_Listener_Serial.xml @@ -1,5 +1,5 @@ <component name="ProjectRunConfigurationManager"> - <configuration default="false" name="tmtcclient Listener Serial" type="PythonConfigurationType" factoryName="Python" folderName="Serial Communication"> + <configuration default="false" name="tmtcclient Listener Serial" type="PythonConfigurationType" factoryName="Python" folderName="Serial Service Test"> <module name="tmtc" /> <option name="INTERPRETER_OPTIONS" value="" /> <option name="PARENT_ENVS" value="true" /> @@ -12,7 +12,7 @@ <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$/obsw_tmtc_client.py" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/tmtc_client_cli.py" /> <option name="PARAMETERS" value="-m 1 --hk -c 1" /> <option name="SHOW_COMMAND_LINE" value="false" /> <option name="EMULATE_TERMINAL" value="false" /> diff --git a/.idea/runConfigurations/tmtcclient_Lock_file.xml b/.idea/runConfigurations/tmtcclient_Lock_file.xml new file mode 100644 index 0000000000000000000000000000000000000000..d071692fbc812f1034f3a4b4553c7da72f1785a8 --- /dev/null +++ b/.idea/runConfigurations/tmtcclient_Lock_file.xml @@ -0,0 +1,24 @@ +<component name="ProjectRunConfigurationManager"> + <configuration default="false" name="tmtcclient Lock file" type="PythonConfigurationType" factoryName="Python" folderName="Serial FileManagement"> + <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$/tmtc_client_cli.py" /> + <option name="PARAMETERS" value="-m 3 -s SD -o 5 -c 1 -t 2.5" /> + <option name="SHOW_COMMAND_LINE" value="false" /> + <option name="EMULATE_TERMINAL" value="true" /> + <option name="MODULE_MODE" value="false" /> + <option name="REDIRECT_INPUT" value="false" /> + <option name="INPUT_FILE" value="" /> + <method v="2" /> + </configuration> +</component> \ No newline at end of file diff --git a/.idea/runConfigurations/tmtcclient_Module_Test_Serial.xml b/.idea/runConfigurations/tmtcclient_Module_Test_Serial.xml index 61aa71dc850e5caf9c5bc54cb29b45ff3b63c73e..5a7ccb64b8f6d2578ee686fb0d9eba74db8113b4 100644 --- a/.idea/runConfigurations/tmtcclient_Module_Test_Serial.xml +++ b/.idea/runConfigurations/tmtcclient_Module_Test_Serial.xml @@ -1,5 +1,5 @@ <component name="ProjectRunConfigurationManager"> - <configuration default="false" name="tmtcclient Module Test Serial" type="PythonConfigurationType" factoryName="Python" folderName="Serial Communication"> + <configuration default="false" name="tmtcclient Module Test Serial" type="PythonConfigurationType" factoryName="Python" folderName="Serial Service Test"> <module name="tmtc" /> <option name="INTERPRETER_OPTIONS" value="" /> <option name="PARENT_ENVS" value="true" /> @@ -12,7 +12,7 @@ <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$/obsw_tmtc_client.py" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/tmtc_client_cli.py" /> <option name="PARAMETERS" value="-m 6 -c 1 --hk" /> <option name="SHOW_COMMAND_LINE" value="false" /> <option name="EMULATE_TERMINAL" value="true" /> diff --git a/.idea/runConfigurations/tmtcclient_PowerCycle_OBC_.xml b/.idea/runConfigurations/tmtcclient_PowerCycle_OBC_.xml new file mode 100644 index 0000000000000000000000000000000000000000..b3b97842056ab569cc84d1da2d200123a03562d5 --- /dev/null +++ b/.idea/runConfigurations/tmtcclient_PowerCycle_OBC_.xml @@ -0,0 +1,24 @@ +<component name="ProjectRunConfigurationManager"> + <configuration default="false" name="tmtcclient PowerCycle OBC " type="PythonConfigurationType" factoryName="Python" folderName="Serial Core"> + <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$/tmtc_client_cli.py" /> + <option name="PARAMETERS" value="-m 3 -s Core -o A11 -c 1 -t 2.5" /> + <option name="SHOW_COMMAND_LINE" value="false" /> + <option name="EMULATE_TERMINAL" value="true" /> + <option name="MODULE_MODE" value="false" /> + <option name="REDIRECT_INPUT" value="false" /> + <option name="INPUT_FILE" value="" /> + <method v="2" /> + </configuration> +</component> \ No newline at end of file diff --git a/.idea/runConfigurations/tmtcclient_Print_SD_Card.xml b/.idea/runConfigurations/tmtcclient_Print_SD_Card.xml new file mode 100644 index 0000000000000000000000000000000000000000..b88172c9db66aadba52a7de897399ddeabfdb037 --- /dev/null +++ b/.idea/runConfigurations/tmtcclient_Print_SD_Card.xml @@ -0,0 +1,24 @@ +<component name="ProjectRunConfigurationManager"> + <configuration default="false" name="tmtcclient Print SD-Card" type="PythonConfigurationType" factoryName="Python" folderName="Serial SD-Card and Image"> + <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$/tmtc_client_cli.py" /> + <option name="PARAMETERS" value="-m 3 -s SD -o A2 -c 1 -t 2.5" /> + <option name="SHOW_COMMAND_LINE" value="false" /> + <option name="EMULATE_TERMINAL" value="true" /> + <option name="MODULE_MODE" value="false" /> + <option name="REDIRECT_INPUT" value="false" /> + <option name="INPUT_FILE" value="" /> + <method v="2" /> + </configuration> +</component> \ No newline at end of file diff --git a/.idea/runConfigurations/tmtcclient_Reset_OBC.xml b/.idea/runConfigurations/tmtcclient_Reset_OBC.xml new file mode 100644 index 0000000000000000000000000000000000000000..8faaee31ebf7848379248c44bf3d5551a332a9fe --- /dev/null +++ b/.idea/runConfigurations/tmtcclient_Reset_OBC.xml @@ -0,0 +1,24 @@ +<component name="ProjectRunConfigurationManager"> + <configuration default="false" name="tmtcclient Reset OBC" type="PythonConfigurationType" factoryName="Python" folderName="Serial Core"> + <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$/tmtc_client_cli.py" /> + <option name="PARAMETERS" value="-m 3 -s Core -o A10 -c 1 -t 2.5" /> + <option name="SHOW_COMMAND_LINE" value="false" /> + <option name="EMULATE_TERMINAL" value="true" /> + <option name="MODULE_MODE" value="false" /> + <option name="REDIRECT_INPUT" value="false" /> + <option name="INPUT_FILE" value="" /> + <method v="2" /> + </configuration> +</component> \ No newline at end of file diff --git a/.idea/runConfigurations/tmtcclient_Run_Time_Stats_OBC_.xml b/.idea/runConfigurations/tmtcclient_Run_Time_Stats_OBC_.xml new file mode 100644 index 0000000000000000000000000000000000000000..f35cbb6d2bc1329f5e9142483fbd4b054414ac25 --- /dev/null +++ b/.idea/runConfigurations/tmtcclient_Run_Time_Stats_OBC_.xml @@ -0,0 +1,24 @@ +<component name="ProjectRunConfigurationManager"> + <configuration default="false" name="tmtcclient Run Time Stats OBC " type="PythonConfigurationType" factoryName="Python" folderName="Serial Core"> + <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$/tmtc_client_cli.py" /> + <option name="PARAMETERS" value="-m 3 -s Core -o A0 -c 1 -t 2.5" /> + <option name="SHOW_COMMAND_LINE" value="false" /> + <option name="EMULATE_TERMINAL" value="true" /> + <option name="MODULE_MODE" value="false" /> + <option name="REDIRECT_INPUT" value="false" /> + <option name="INPUT_FILE" value="" /> + <method v="2" /> + </configuration> +</component> \ No newline at end of file diff --git a/.idea/runConfigurations/tmtcclient_Service_17_QEMU.xml b/.idea/runConfigurations/tmtcclient_Service_17_QEMU.xml index 394ad5de13110eb11529d1301784fb505a53da2f..7ea51c07201800ebcb05346185ebe4cb5c6902e0 100644 --- a/.idea/runConfigurations/tmtcclient_Service_17_QEMU.xml +++ b/.idea/runConfigurations/tmtcclient_Service_17_QEMU.xml @@ -12,7 +12,7 @@ <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$/obsw_tmtc_client.py" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/tmtc_client_cli.py" /> <option name="PARAMETERS" value="-m 3 -s 17 -c 2 -t 2" /> <option name="SHOW_COMMAND_LINE" value="false" /> <option name="EMULATE_TERMINAL" value="false" /> diff --git a/.idea/runConfigurations/tmtcclient_Service_17_Serial.xml b/.idea/runConfigurations/tmtcclient_Service_17_Serial.xml index 5145e3b7acd8d267540c2cc4214eb61b7c4c8f67..850e14b920d3f00f752d6faa00a4d4e7d8c39f14 100644 --- a/.idea/runConfigurations/tmtcclient_Service_17_Serial.xml +++ b/.idea/runConfigurations/tmtcclient_Service_17_Serial.xml @@ -1,5 +1,5 @@ <component name="ProjectRunConfigurationManager"> - <configuration default="false" name="tmtcclient Service 17 Serial" type="PythonConfigurationType" factoryName="Python" folderName="Serial Communication"> + <configuration default="false" name="tmtcclient Service 17 Serial" type="PythonConfigurationType" factoryName="Python" folderName="Serial Service Test"> <module name="tmtc" /> <option name="INTERPRETER_OPTIONS" value="" /> <option name="PARENT_ENVS" value="true" /> @@ -12,7 +12,7 @@ <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$/obsw_tmtc_client.py" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/tmtc_client_cli.py" /> <option name="PARAMETERS" value="-m 3 -s 17 -c 1 -t 2.2" /> <option name="SHOW_COMMAND_LINE" value="false" /> <option name="EMULATE_TERMINAL" value="true" /> diff --git a/.idea/runConfigurations/tmtcclient_Service_17_UDP.xml b/.idea/runConfigurations/tmtcclient_Service_17_UDP.xml index f8ab43f96a2a4f9497d0d2bd5d76fcd602e00c9b..20619467d64c2c7257e21a1fa282cde93912dcef 100644 --- a/.idea/runConfigurations/tmtcclient_Service_17_UDP.xml +++ b/.idea/runConfigurations/tmtcclient_Service_17_UDP.xml @@ -12,7 +12,7 @@ <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$/obsw_tmtc_client.py" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/core/tmtc_client_core.py" /> <option name="PARAMETERS" value="-m 3 -c 3 -s 17 -t 3" /> <option name="SHOW_COMMAND_LINE" value="false" /> <option name="EMULATE_TERMINAL" value="true" /> diff --git a/.idea/runConfigurations/tmtcclient_Service_200_UDP.xml b/.idea/runConfigurations/tmtcclient_Service_200_UDP.xml index cf246a41cd1d20f0cbe32274fb3b4f554e659b60..069fe98fb5550a3d7dc2de6556aea4bdbd5fb63e 100644 --- a/.idea/runConfigurations/tmtcclient_Service_200_UDP.xml +++ b/.idea/runConfigurations/tmtcclient_Service_200_UDP.xml @@ -12,7 +12,7 @@ <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$/obsw_tmtc_client.py" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/core/tmtc_client_core.py" /> <option name="PARAMETERS" value="-m 3 -c 3 -s 200 -t 3" /> <option name="SHOW_COMMAND_LINE" value="false" /> <option name="EMULATE_TERMINAL" value="true" /> diff --git a/.idea/runConfigurations/tmtcclient_Service_20_QEMU___.xml b/.idea/runConfigurations/tmtcclient_Service_20_QEMU___.xml index 506baaca1246070f05f4e7b72e07c2ad33ec0e9d..779ce5bf884a48d549e55de87b71580aab791da7 100644 --- a/.idea/runConfigurations/tmtcclient_Service_20_QEMU___.xml +++ b/.idea/runConfigurations/tmtcclient_Service_20_QEMU___.xml @@ -12,7 +12,7 @@ <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$/obsw_tmtc_client.py" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/core/tmtc_client_core.py" /> <option name="PARAMETERS" value="-m 3 -s 20 -c 2 -t 3" /> <option name="SHOW_COMMAND_LINE" value="false" /> <option name="EMULATE_TERMINAL" value="true" /> diff --git a/.idea/runConfigurations/tmtcclient_Service_2_QEMU.xml b/.idea/runConfigurations/tmtcclient_Service_2_QEMU.xml index 59d368399ee161ca806e6177a62aebb1c761bd33..dd374950dc37b895e686f27afa139b632f87c112 100644 --- a/.idea/runConfigurations/tmtcclient_Service_2_QEMU.xml +++ b/.idea/runConfigurations/tmtcclient_Service_2_QEMU.xml @@ -12,7 +12,7 @@ <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$/obsw_tmtc_client.py" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/tmtc_client_cli.py" /> <option name="PARAMETERS" value="-m 3 -s 2 -c 2 -t 2.5" /> <option name="SHOW_COMMAND_LINE" value="false" /> <option name="EMULATE_TERMINAL" value="true" /> diff --git a/.idea/runConfigurations/tmtcclient_Service_2_Serial.xml b/.idea/runConfigurations/tmtcclient_Service_2_Serial.xml index 38316e0359a813bff39ae6574bb14beb0430e97e..4d0d694a22fba38ee47e1221d9c93c58b3cd2a75 100644 --- a/.idea/runConfigurations/tmtcclient_Service_2_Serial.xml +++ b/.idea/runConfigurations/tmtcclient_Service_2_Serial.xml @@ -1,5 +1,5 @@ <component name="ProjectRunConfigurationManager"> - <configuration default="false" name="tmtcclient Service 2 Serial" type="PythonConfigurationType" factoryName="Python" folderName="Serial Communication"> + <configuration default="false" name="tmtcclient Service 2 Serial" type="PythonConfigurationType" factoryName="Python" folderName="Serial Service Test"> <module name="tmtc" /> <option name="INTERPRETER_OPTIONS" value="" /> <option name="PARENT_ENVS" value="true" /> @@ -12,7 +12,7 @@ <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$/obsw_tmtc_client.py" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/tmtc_client_cli.py" /> <option name="PARAMETERS" value="-m 3 -s 2 -c 1 -t 3.5" /> <option name="SHOW_COMMAND_LINE" value="false" /> <option name="EMULATE_TERMINAL" value="false" /> diff --git a/.idea/runConfigurations/tmtcclient_Service_2_UDP.xml b/.idea/runConfigurations/tmtcclient_Service_2_UDP.xml index d592060fa408a267fbe76d06d59580403fc484d3..4375154dbd140756c61b29ed461c2d444b80b07c 100644 --- a/.idea/runConfigurations/tmtcclient_Service_2_UDP.xml +++ b/.idea/runConfigurations/tmtcclient_Service_2_UDP.xml @@ -12,7 +12,7 @@ <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$/obsw_tmtc_client.py" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/core/tmtc_client_core.py" /> <option name="PARAMETERS" value="-m 3 -c 3 -s 2 -t 3" /> <option name="SHOW_COMMAND_LINE" value="false" /> <option name="EMULATE_TERMINAL" value="false" /> diff --git a/.idea/runConfigurations/tmtcclient_Service_3_QEMU_.xml b/.idea/runConfigurations/tmtcclient_Service_3_QEMU_.xml index 2ec6365acecc8cc4291b929e08f7bd85a6dca548..621b333828a97c3da5073d28191f71d6ff92e3f1 100644 --- a/.idea/runConfigurations/tmtcclient_Service_3_QEMU_.xml +++ b/.idea/runConfigurations/tmtcclient_Service_3_QEMU_.xml @@ -12,7 +12,7 @@ <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$/obsw_tmtc_client.py" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/tmtc_client_cli.py" /> <option name="PARAMETERS" value="-m 3 -s 3 -c 2 -t 2 --hk" /> <option name="SHOW_COMMAND_LINE" value="false" /> <option name="EMULATE_TERMINAL" value="true" /> diff --git a/.idea/runConfigurations/tmtcclient_Service_3_Serial_.xml b/.idea/runConfigurations/tmtcclient_Service_3_Serial_.xml index 7b0db83d4daea21024c7ef99394582f529ca1486..15d51da4d1d1c373b763e2928324f7070bd1a14f 100644 --- a/.idea/runConfigurations/tmtcclient_Service_3_Serial_.xml +++ b/.idea/runConfigurations/tmtcclient_Service_3_Serial_.xml @@ -1,5 +1,5 @@ <component name="ProjectRunConfigurationManager"> - <configuration default="false" name="tmtcclient Service 3 Serial " type="PythonConfigurationType" factoryName="Python" folderName="Serial Communication"> + <configuration default="false" name="tmtcclient Service 3 Serial " type="PythonConfigurationType" factoryName="Python" folderName="Serial Service Test"> <module name="tmtc" /> <option name="INTERPRETER_OPTIONS" value="" /> <option name="PARENT_ENVS" value="true" /> @@ -12,7 +12,7 @@ <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$/obsw_tmtc_client.py" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/tmtc_client_cli.py" /> <option name="PARAMETERS" value="-m 3 -s 3 -c 1 -t 3 --hk" /> <option name="SHOW_COMMAND_LINE" value="false" /> <option name="EMULATE_TERMINAL" value="false" /> diff --git a/.idea/runConfigurations/tmtcclient_Service_5_QEMU_.xml b/.idea/runConfigurations/tmtcclient_Service_5_QEMU_.xml index 7669c7a025df306fa0658ef487b7c2e997ba833f..9d97d32114c666ee252cd8e255c451a9f10a902f 100644 --- a/.idea/runConfigurations/tmtcclient_Service_5_QEMU_.xml +++ b/.idea/runConfigurations/tmtcclient_Service_5_QEMU_.xml @@ -12,7 +12,7 @@ <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$/obsw_tmtc_client.py" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/tmtc_client_cli.py" /> <option name="PARAMETERS" value="-m 3 -s 5 -c 2 -t 2" /> <option name="SHOW_COMMAND_LINE" value="false" /> <option name="EMULATE_TERMINAL" value="true" /> diff --git a/.idea/runConfigurations/tmtcclient_Service_5_Serial.xml b/.idea/runConfigurations/tmtcclient_Service_5_Serial.xml index aadf325a5002b612eaf8c56d8652bb56d02a7288..f4def1c17b51f567888b60277830b9e0bd391011 100644 --- a/.idea/runConfigurations/tmtcclient_Service_5_Serial.xml +++ b/.idea/runConfigurations/tmtcclient_Service_5_Serial.xml @@ -1,5 +1,5 @@ <component name="ProjectRunConfigurationManager"> - <configuration default="false" name="tmtcclient Service 5 Serial" type="PythonConfigurationType" factoryName="Python" folderName="Serial Communication"> + <configuration default="false" name="tmtcclient Service 5 Serial" type="PythonConfigurationType" factoryName="Python" folderName="Serial Service Test"> <module name="tmtc" /> <option name="INTERPRETER_OPTIONS" value="" /> <option name="PARENT_ENVS" value="true" /> @@ -12,7 +12,7 @@ <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$/obsw_tmtc_client.py" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/tmtc_client_cli.py" /> <option name="PARAMETERS" value="-m 3 -s 5 -c 1 -t 2.0" /> <option name="SHOW_COMMAND_LINE" value="false" /> <option name="EMULATE_TERMINAL" value="true" /> diff --git a/.idea/runConfigurations/tmtcclient_Service_8_QEMU__.xml b/.idea/runConfigurations/tmtcclient_Service_8_QEMU__.xml index 90becd426bf2091b79d593abc446d5e6a3eaacb0..c6acd1116ef80ac6a796d560fc2a6c16256a48c9 100644 --- a/.idea/runConfigurations/tmtcclient_Service_8_QEMU__.xml +++ b/.idea/runConfigurations/tmtcclient_Service_8_QEMU__.xml @@ -12,7 +12,7 @@ <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$/obsw_tmtc_client.py" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/tmtc_client_cli.py" /> <option name="PARAMETERS" value="-m 3 -s 8 -c 2 -t 2.5" /> <option name="SHOW_COMMAND_LINE" value="false" /> <option name="EMULATE_TERMINAL" value="true" /> diff --git a/.idea/runConfigurations/tmtcclient_Service_8_Serial.xml b/.idea/runConfigurations/tmtcclient_Service_8_Serial.xml index 1c96bce8f9e66fec8a1b6be5948348f2928904c7..55402cb29bfedf316785073627623a1b5c9fb358 100644 --- a/.idea/runConfigurations/tmtcclient_Service_8_Serial.xml +++ b/.idea/runConfigurations/tmtcclient_Service_8_Serial.xml @@ -1,5 +1,5 @@ <component name="ProjectRunConfigurationManager"> - <configuration default="false" name="tmtcclient Service 8 Serial" type="PythonConfigurationType" factoryName="Python" folderName="Serial Communication"> + <configuration default="false" name="tmtcclient Service 8 Serial" type="PythonConfigurationType" factoryName="Python" folderName="Serial Service Test"> <module name="tmtc" /> <option name="INTERPRETER_OPTIONS" value="" /> <option name="PARENT_ENVS" value="true" /> @@ -12,7 +12,7 @@ <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$/obsw_tmtc_client.py" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/tmtc_client_cli.py" /> <option name="PARAMETERS" value="-m 3 -s 8 -c 1 -t 3" /> <option name="SHOW_COMMAND_LINE" value="false" /> <option name="EMULATE_TERMINAL" value="true" /> diff --git a/.idea/runConfigurations/tmtcclient_Service_8_UDP.xml b/.idea/runConfigurations/tmtcclient_Service_8_UDP.xml index f7797b9f92b1467733968774111393c5b01dd13f..1da3af4e1ce31f7baa623f63dd69ae0308c97d0b 100644 --- a/.idea/runConfigurations/tmtcclient_Service_8_UDP.xml +++ b/.idea/runConfigurations/tmtcclient_Service_8_UDP.xml @@ -12,7 +12,7 @@ <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$/obsw_tmtc_client.py" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/core/tmtc_client_core.py" /> <option name="PARAMETERS" value="-m 3 -c 3 -s 8" /> <option name="SHOW_COMMAND_LINE" value="false" /> <option name="EMULATE_TERMINAL" value="true" /> diff --git a/.idea/runConfigurations/tmtcclient_Service_9_Serial.xml b/.idea/runConfigurations/tmtcclient_Service_9_Serial.xml index f755f02c30089f9d2bc2a6efb46f47f65ac9e3a7..952b164ef6a663285f3772b919e878c028a44abd 100644 --- a/.idea/runConfigurations/tmtcclient_Service_9_Serial.xml +++ b/.idea/runConfigurations/tmtcclient_Service_9_Serial.xml @@ -1,5 +1,5 @@ <component name="ProjectRunConfigurationManager"> - <configuration default="false" name="tmtcclient Service 9 Serial" type="PythonConfigurationType" factoryName="Python" folderName="Serial Communication"> + <configuration default="false" name="tmtcclient Service 9 Serial" type="PythonConfigurationType" factoryName="Python" folderName="Serial Service Test"> <module name="tmtc" /> <option name="INTERPRETER_OPTIONS" value="" /> <option name="PARENT_ENVS" value="true" /> @@ -12,7 +12,7 @@ <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$/obsw_tmtc_client.py" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/tmtc_client_cli.py" /> <option name="PARAMETERS" value="-m 3 -s 9 -c 1 -t 3" /> <option name="SHOW_COMMAND_LINE" value="false" /> <option name="EMULATE_TERMINAL" value="true" /> diff --git a/.idea/runConfigurations/tmtcclient_Service_Dummy_QEMU.xml b/.idea/runConfigurations/tmtcclient_Service_Dummy_QEMU.xml index 78e091163340f8bd1a7597a8dbd58f3c338d3c53..f7d6feedef966405ee32a1e4e2154025a7cdee6d 100644 --- a/.idea/runConfigurations/tmtcclient_Service_Dummy_QEMU.xml +++ b/.idea/runConfigurations/tmtcclient_Service_Dummy_QEMU.xml @@ -12,7 +12,7 @@ <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$/obsw_tmtc_client.py" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/tmtc_client_cli.py" /> <option name="PARAMETERS" value="-m 3 -s Dummy -c 2 -t 2" /> <option name="SHOW_COMMAND_LINE" value="false" /> <option name="EMULATE_TERMINAL" value="true" /> diff --git a/.idea/runConfigurations/tmtcclient_Service_GPS0_QEMU__.xml b/.idea/runConfigurations/tmtcclient_Service_GPS0_QEMU__.xml index e859a0a53f4994efb589bf38808f27852b89581f..a1e01a69e621608c5dab37f395f2376f0d5cce2a 100644 --- a/.idea/runConfigurations/tmtcclient_Service_GPS0_QEMU__.xml +++ b/.idea/runConfigurations/tmtcclient_Service_GPS0_QEMU__.xml @@ -12,7 +12,7 @@ <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$/obsw_tmtc_client.py" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/tmtc_client_cli.py" /> <option name="PARAMETERS" value="-m 3 -s GPS0 -c 2 -t 2.5 --hk" /> <option name="SHOW_COMMAND_LINE" value="false" /> <option name="EMULATE_TERMINAL" value="true" /> diff --git a/.idea/runConfigurations/tmtcclient_Service_GPS1_QEMU___.xml b/.idea/runConfigurations/tmtcclient_Service_GPS1_QEMU___.xml index 8a100cfd5b5483a1c943a682f32482cbe0d3822b..74f6c148547b1779ec9c462ca16e58c0f4160f4b 100644 --- a/.idea/runConfigurations/tmtcclient_Service_GPS1_QEMU___.xml +++ b/.idea/runConfigurations/tmtcclient_Service_GPS1_QEMU___.xml @@ -12,7 +12,7 @@ <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$/obsw_tmtc_client.py" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/tmtc_client_cli.py" /> <option name="PARAMETERS" value="-m 3 -s GPS1 -c 2 -t 2.5 --hk" /> <option name="SHOW_COMMAND_LINE" value="false" /> <option name="EMULATE_TERMINAL" value="true" /> diff --git a/.idea/runConfigurations/tmtcclient_Single_Command.xml b/.idea/runConfigurations/tmtcclient_Single_Command.xml index 46d240300da9f6c7eec267237729c2fd9c72737d..9a116c2a5c403abf9e9712ea5b205f437bd7c2a9 100644 --- a/.idea/runConfigurations/tmtcclient_Single_Command.xml +++ b/.idea/runConfigurations/tmtcclient_Single_Command.xml @@ -12,7 +12,7 @@ <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$/obsw_tmtc_client.py" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/core/tmtc_client_core.py" /> <option name="PARAMETERS" value="-m 2 -c 3 --boardIP=127.0.0.1" /> <option name="SHOW_COMMAND_LINE" value="false" /> <option name="EMULATE_TERMINAL" value="false" /> diff --git a/.idea/runConfigurations/tmtcclient_Single_Command_Serial_.xml b/.idea/runConfigurations/tmtcclient_Single_Command_Serial.xml similarity index 80% rename from .idea/runConfigurations/tmtcclient_Single_Command_Serial_.xml rename to .idea/runConfigurations/tmtcclient_Single_Command_Serial.xml index c59814017c5419b0cfa0d262228897e93ae23e4f..abef5a62f8645002647d6ac3a6cfdc487d12d13f 100644 --- a/.idea/runConfigurations/tmtcclient_Single_Command_Serial_.xml +++ b/.idea/runConfigurations/tmtcclient_Single_Command_Serial.xml @@ -1,5 +1,5 @@ <component name="ProjectRunConfigurationManager"> - <configuration default="false" name="tmtcclient Single Command Serial " type="PythonConfigurationType" factoryName="Python" folderName="Serial Communication"> + <configuration default="false" name="tmtcclient Single Command Serial" type="PythonConfigurationType" factoryName="Python" folderName="Serial Service Test"> <module name="tmtc" /> <option name="INTERPRETER_OPTIONS" value="" /> <option name="PARENT_ENVS" value="true" /> @@ -12,8 +12,8 @@ <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$/obsw_tmtc_client.py" /> - <option name="PARAMETERS" value="-m 2 -c 1 -t 5" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/tmtc_client_cli.py" /> + <option name="PARAMETERS" value="-m 2 -c 1 -t 3" /> <option name="SHOW_COMMAND_LINE" value="false" /> <option name="EMULATE_TERMINAL" value="false" /> <option name="MODULE_MODE" value="false" /> diff --git a/.idea/runConfigurations/tmtcclient_Software_QEMU_.xml b/.idea/runConfigurations/tmtcclient_Software_QEMU_.xml index 49a2418a343c21a57464df1f2c30035460fb530d..12abc3e6fc029245c7ccecde450954847d2ee574 100644 --- a/.idea/runConfigurations/tmtcclient_Software_QEMU_.xml +++ b/.idea/runConfigurations/tmtcclient_Software_QEMU_.xml @@ -12,7 +12,7 @@ <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$/obsw_tmtc_client.py" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/core/tmtc_client_core.py" /> <option name="PARAMETERS" value="-m 4 -c 2 -t 3" /> <option name="SHOW_COMMAND_LINE" value="false" /> <option name="EMULATE_TERMINAL" value="true" /> diff --git a/.idea/runConfigurations/tmtcclient_Trigger_Exceptions.xml b/.idea/runConfigurations/tmtcclient_Trigger_Exceptions.xml new file mode 100644 index 0000000000000000000000000000000000000000..6bea4aeed0a664d610f0c8fb3ad9fbd87a9fe3f6 --- /dev/null +++ b/.idea/runConfigurations/tmtcclient_Trigger_Exceptions.xml @@ -0,0 +1,24 @@ +<component name="ProjectRunConfigurationManager"> + <configuration default="false" name="tmtcclient Trigger Exceptions" type="PythonConfigurationType" factoryName="Python" folderName="Serial Utility"> + <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$/tmtc_client_cli.py" /> + <option name="PARAMETERS" value="-m 3 -s 17 -o 150 -c 1 -t 2.2" /> + <option name="SHOW_COMMAND_LINE" value="false" /> + <option name="EMULATE_TERMINAL" value="true" /> + <option name="MODULE_MODE" value="false" /> + <option name="REDIRECT_INPUT" value="false" /> + <option name="INPUT_FILE" value="" /> + <method v="2" /> + </configuration> +</component> \ No newline at end of file diff --git a/.idea/runConfigurations/tmtcclient_Unittest_QEMU.xml b/.idea/runConfigurations/tmtcclient_Unittest_QEMU.xml index 07cedcf92c05201048b69b1cadd88c498dff07ac..edae8f21dd310739cd449f1929d40989aed0997c 100644 --- a/.idea/runConfigurations/tmtcclient_Unittest_QEMU.xml +++ b/.idea/runConfigurations/tmtcclient_Unittest_QEMU.xml @@ -12,7 +12,7 @@ <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$/obsw_tmtc_client.py" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/core/tmtc_client_core.py" /> <option name="PARAMETERS" value="-m 5 -c 2 -t 5" /> <option name="SHOW_COMMAND_LINE" value="false" /> <option name="EMULATE_TERMINAL" value="true" /> diff --git a/.idea/runConfigurations/tmtcclient_Unlock_File.xml b/.idea/runConfigurations/tmtcclient_Unlock_File.xml new file mode 100644 index 0000000000000000000000000000000000000000..ce9839baac94e9bcd4d9ae5dee6dfa9060779881 --- /dev/null +++ b/.idea/runConfigurations/tmtcclient_Unlock_File.xml @@ -0,0 +1,24 @@ +<component name="ProjectRunConfigurationManager"> + <configuration default="false" name="tmtcclient Unlock File" type="PythonConfigurationType" factoryName="Python" folderName="Serial FileManagement"> + <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$/tmtc_client_cli.py" /> + <option name="PARAMETERS" value="-m 3 -s SD -o 6 -c 1 -t 2.5" /> + <option name="SHOW_COMMAND_LINE" value="false" /> + <option name="EMULATE_TERMINAL" value="true" /> + <option name="MODULE_MODE" value="false" /> + <option name="REDIRECT_INPUT" value="false" /> + <option name="INPUT_FILE" value="" /> + <method v="2" /> + </configuration> +</component> \ No newline at end of file diff --git a/.idea/runConfigurations/tmtcclient__Service_200_Serial.xml b/.idea/runConfigurations/tmtcclient__Service_200_Serial.xml index ec2175bfadade9795139b22a62d815dd0ffa752e..e6a5fc66113e81d283604b4062241a7a392f1156 100644 --- a/.idea/runConfigurations/tmtcclient__Service_200_Serial.xml +++ b/.idea/runConfigurations/tmtcclient__Service_200_Serial.xml @@ -1,5 +1,5 @@ <component name="ProjectRunConfigurationManager"> - <configuration default="false" name="tmtcclient Service 200 Serial" type="PythonConfigurationType" factoryName="Python" folderName="Serial Communication"> + <configuration default="false" name="tmtcclient Service 200 Serial" type="PythonConfigurationType" factoryName="Python" folderName="Serial Service Test"> <module name="tmtc" /> <option name="INTERPRETER_OPTIONS" value="" /> <option name="PARENT_ENVS" value="true" /> @@ -12,7 +12,7 @@ <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$/obsw_tmtc_client.py" /> + <option name="SCRIPT_NAME" value="$PROJECT_DIR$/tmtc_client_cli.py" /> <option name="PARAMETERS" value="-m 3 -s 200 -c 1 --hk -t 3" /> <option name="SHOW_COMMAND_LINE" value="false" /> <option name="EMULATE_TERMINAL" value="false" /> diff --git a/README.md b/README.md index 518c9cc833847de56233ab94d5dd857f6089c5a6..0c0ec34d7c3969a442abbceaff67a769d5fc6e3a 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,6 @@ git clone https://git.ksat-stuttgart.de/source/tmtc.git Initiate the core components by initiating and updating the submodules ```sh git submodule init -git submodule sync git submoduke update ``` @@ -27,7 +26,7 @@ pip install -r requirements.txt Now the script can be tested by running ```sh -python3 obsw_tmtc_client.py -h +python obsw_tmtc_client.py -h ``` It is recommended to use and setup PyCharm to also use the preconfigured @@ -137,4 +136,4 @@ a new PyCharm project in a new window. To add new configurations, go to Edit Configurations... at the top right corner in the drop-down menu. -Specify the new run configurations and set a tick at Share through VCS. \ No newline at end of file +Specify the new run configurations and set a tick at Share through VCS. diff --git a/gui/obsw_backend_test.py b/archive/obsw_backend_test.py similarity index 85% rename from gui/obsw_backend_test.py rename to archive/obsw_backend_test.py index c21caeec5ea9d5dacbc119a6c49e66b27237083a..62a3c3e5904060ea253302aae872ec213707ea51 100644 --- a/gui/obsw_backend_test.py +++ b/archive/obsw_backend_test.py @@ -6,9 +6,10 @@ import logging LOGGER = get_logger() + class TmTcBackend(Process): def __init__(self): - from obsw_tmtc_client import TmTcHandler + from core.tmtc_client_core import TmTcHandler super(TmTcBackend, self).__init__() self.address = ('localhost', 6000) # family is deduced to be 'AF_INET' self.tmtc_backend = TmTcHandler() @@ -20,7 +21,7 @@ class TmTcBackend(Process): def listen(self): self.conn = self.listener.accept() - LOGGER.info("TmTcBackend: Connection accepted from %s",str(self.listener.last_accepted)) + LOGGER.info("TmTcBackend: Connection accepted from %s", str(self.listener.last_accepted)) while True: msg = self.conn.recv() # do something with msg diff --git a/archive/obsw_pus_tm_base.py b/archive/obsw_pus_tm_base.py deleted file mode 100644 index 287c9cdf06a80daf381a63a58d6e20007e14f18b..0000000000000000000000000000000000000000 --- a/archive/obsw_pus_tm_base.py +++ /dev/null @@ -1,59 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Created on Wed Apr 4 11:44:48 2018 -Generic PUS packet class to deserialize raw PUS telemetry. -@author: S. Gaisser -""" - -import crcmod -import datetime - - -class ObswPusPacket: - def __init__(self, byte_array: bytearray): - self.__packet_raw = byte_array - self.PUSHeader = PUSPacketHeader(byte_array) - byte_array = byte_array[6:] - self.dataFieldHeader = OBSWPUSPacketDataFieldHeader(byte_array) - byte_array = byte_array[12:] - self.data = byte_array[:len(byte_array) - 2] - self.crc = byte_array[len(byte_array) - 2] << 8 | byte_array[len(byte_array) - 1] - - def get_raw_packet(self) -> bytearray: - return self.__packet_raw - - def append_pus_packet_header(self, array): - self.dataFieldHeader.printDataFieldHeader(array) - self.PUSHeader.printPusPacketHeader(array) - - def append_pus_packet_header_column_headers(self, array): - self.dataFieldHeader.printDataFieldHeaderColumnHeader(array) - self.PUSHeader.printPusPacketHeaderColumnHeaders(array) - - def getPacketSize(self): - # PusHeader Size + data size - size = PUSPacketHeader.headerSize + self.PUSHeader.length + 1 - return size - - def getService(self): - return self.dataFieldHeader.type - - def getSubservice(self): - return self.dataFieldHeader.subtype - - def getSSC(self): - return self.PUSHeader.sourceSequenceCount - - def printData(self): - print(self.returnDataString()) - - def returnDataString(self): - strToPrint = "[" - for byte in self.data: - strToPrint += str(hex(byte)) + " , " - strToPrint = strToPrint.rstrip(' , ') - strToPrint += ']' - return strToPrint - - - diff --git a/config/obsw_com_config.py b/config/obsw_com_config.py index 3de6c2863cc55bd60f83dc150043fe31ff972d53..0d45593ee4d216993bc43b1dc0daf1f79d857681 100644 --- a/config/obsw_com_config.py +++ b/config/obsw_com_config.py @@ -25,12 +25,12 @@ def set_communication_interface(tmtc_printer: TmTcPrinter) -> Union[Communicatio :return: CommunicationInterface object """ try: - if g.G_COM_IF == g.ComIF.Ethernet: + if g.G_COM_IF == g.ComInterfaces.Ethernet: communication_interface = EthernetComIF( tmtc_printer=tmtc_printer, tm_timeout=g.G_TM_TIMEOUT, tc_timeout_factor=g.G_TC_SEND_TIMEOUT_FACTOR, send_address=g.G_ETHERNET_SEND_ADDRESS, receive_address=g.G_ETHERNET_RECV_ADDRESS) - elif g.G_COM_IF == g.ComIF.Serial: + elif g.G_COM_IF == g.ComInterfaces.Serial: serial_baudrate = g.G_SERIAL_BAUDRATE serial_timeout = g.G_SERIAL_TIMEOUT communication_interface = SerialComIF( @@ -39,10 +39,14 @@ def set_communication_interface(tmtc_printer: TmTcPrinter) -> Union[Communicatio ser_com_type=SerialCommunicationType.DLE_ENCODING) communication_interface.set_dle_settings( g.G_SERIAL_DLE_MAX_QUEUE_LEN, g.G_SERIAL_DLE_MAX_FRAME_SIZE, serial_timeout) - elif g.G_COM_IF == g.ComIF.QEMU: + elif g.G_COM_IF == g.ComInterfaces.QEMU: + serial_timeout = g.G_SERIAL_TIMEOUT communication_interface = QEMUComIF( - tmtc_printer=tmtc_printer, tm_timeout=g.G_TM_TIMEOUT, - tc_timeout_factor=g.G_TC_SEND_TIMEOUT_FACTOR) + tmtc_printer=tmtc_printer, + serial_timeout=serial_timeout, + ser_com_type=SerialCommunicationType.DLE_ENCODING) + communication_interface.set_dle_settings( + g.G_SERIAL_DLE_MAX_QUEUE_LEN, g.G_SERIAL_DLE_MAX_FRAME_SIZE, serial_timeout) else: communication_interface = DummyComIF(tmtc_printer=tmtc_printer) if not communication_interface.valid: diff --git a/config/obsw_config.py b/config/obsw_config.py index e703586eed6d5560c1e3c9de539e14a23b59c4e4..60b761db14e45ba9a9f40b0534969dfa172b98fe 100644 --- a/config/obsw_config.py +++ b/config/obsw_config.py @@ -10,8 +10,7 @@ import struct import pprint import logging -from socket import INADDR_ANY -from config.obsw_definitions import ModeList, ComIF +from config.obsw_definitions import ModeList, ComInterfaces """ Mission/Device specific information. @@ -28,6 +27,15 @@ Other global variables # TMTC Client G_TMTC_LOGGER_NAME = "TMTC Logger" G_ERROR_LOG_FILE_NAME = "tmtc_error.log" +G_PP = pprint.PrettyPrinter() +LOGGER = logging.getLogger(G_TMTC_LOGGER_NAME) +# General Settings +G_SCRIPT_MODE = 1 +G_MODE_ID: ModeList = ModeList.ListenerMode +G_SERVICE = 17 +G_OP_CODE = 0 +G_LISTENER_AFTER_OP = False +G_DISPLAY_MODE = "long" # General TMTC Settings G_APID = 0x65 # Global APID for EIVE @@ -44,6 +52,13 @@ G_TM_TIMEOUT = 6 G_TC_SEND_TIMEOUT_FACTOR = 2.0 # Serial communication +# Binary Upload Settings +G_MAX_BINARY_FRAME_LENGTH = 1500 +G_MAX_APP_DATA_LENGTH = G_MAX_BINARY_FRAME_LENGTH - 100 + +G_COM_IF: ComInterfaces = ComInterfaces.QEMU +# COM Port for serial communication +G_COM_PORT = 'COM0' G_SERIAL_TIMEOUT = 0.01 G_SERIAL_BAUDRATE = 230400 G_SERIAL_FRAME_SIZE = 256 @@ -79,14 +94,13 @@ G_TM_LISTENER = None G_COM_INTERFACE = None G_TMTC_PRINTER = None - # noinspection PyUnusedLocal def set_globals(args): - global G_ETHERNET_RECV_ADDRESS, G_ETHERNET_SEND_ADDRESS, G_SCRIPT_MODE, G_MODE_ID, G_SERVICE, G_DISPLAY_MODE,\ - G_COM_IF, G_COM_PORT, G_SERIAL_TIMEOUT, G_TM_TIMEOUT, G_TC_SEND_TIMEOUT_FACTOR, \ - G_PRINT_TO_FILE, G_PRINT_HK_DATA, G_PRINT_RAW_TM, G_PRINT_TM - if args.mode == 0: - LOGGER.info("GUI mode not implemented yet !") + global G_ETHERNET_RECV_ADDRESS, G_ETHERNET_SEND_ADDRESS, G_SCRIPT_MODE, G_MODE_ID, G_SERVICE, \ + G_DISPLAY_MODE, G_COM_IF, G_COM_PORT, G_SERIAL_TIMEOUT, G_TM_TIMEOUT, \ + G_TC_SEND_TIMEOUT_FACTOR, G_PRINT_TO_FILE, G_PRINT_HK_DATA, G_PRINT_RAW_TM, G_PRINT_TM, \ + G_OP_CODE, G_RESEND_TC, G_LISTENER_AFTER_OP + if args.shortDisplayMode: G_DISPLAY_MODE = "short" else: @@ -108,20 +122,28 @@ def set_globals(args): G_MODE_ID = ModeList.UnitTest else: G_MODE_ID = ModeList[1] - if args.com_if == ComIF.Ethernet.value: - G_COM_IF = ComIF.Ethernet - elif args.com_if == ComIF.Serial.value: - G_COM_IF = ComIF.Serial - elif args.com_if == ComIF.QEMU.value: - G_COM_IF = ComIF.QEMU + + if args.com_if == ComInterfaces.Ethernet.value: + G_COM_IF = ComInterfaces.Ethernet + elif args.com_if == ComInterfaces.Serial.value: + G_COM_IF = ComInterfaces.Serial + elif args.com_if == ComInterfaces.QEMU.value: + G_COM_IF = ComInterfaces.QEMU else: - G_COM_IF = ComIF.Dummy + G_COM_IF = ComInterfaces.Dummy G_SERVICE = str(args.service) if G_SERVICE.isdigit(): G_SERVICE = int(args.service) else: G_SERVICE = args.service + + G_OP_CODE = str(args.op_code) + if G_OP_CODE.isdigit(): + G_OP_CODE = int(G_OP_CODE) + else: + G_OP_CODE = str(G_OP_CODE) + G_MODE_ID = G_MODE_ID G_PRINT_HK_DATA = args.print_hk G_PRINT_TM = args.print_tm @@ -130,6 +152,8 @@ def set_globals(args): G_COM_PORT = args.com_port G_TM_TIMEOUT = args.tm_timeout G_RESEND_TC = args.resend_tc - from obsw_user_code import global_setup_hook + G_LISTENER_AFTER_OP = args.listener + + from config.obsw_user_code import global_setup_hook global_setup_hook() diff --git a/config/obsw_definitions.py b/config/obsw_definitions.py index 738119abdf4f43de91c60393b82652efb511962b..3aff14867aa39318c7bfa8907fbcf511c7ea4ea8 100644 --- a/config/obsw_definitions.py +++ b/config/obsw_definitions.py @@ -17,7 +17,7 @@ class ModeList(enum.Enum): PromptMode = 32 -class ComIF(enum.Enum): +class ComInterfaces(enum.Enum): Dummy = 0 Serial = 1 QEMU = 2 diff --git a/obsw_user_code.py b/config/obsw_user_code.py similarity index 100% rename from obsw_user_code.py rename to config/obsw_user_code.py diff --git a/gui/__init__.py b/core/__init__.py similarity index 100% rename from gui/__init__.py rename to core/__init__.py diff --git a/obsw_tmtc_client.py b/core/tmtc_backend.py old mode 100755 new mode 100644 similarity index 61% rename from obsw_tmtc_client.py rename to core/tmtc_backend.py index d97dc3586a4c4345c9312a4803f0d644d7077a85..392a009f2fe156e6b7d05904005139e828668441 --- a/obsw_tmtc_client.py +++ b/core/tmtc_backend.py @@ -1,121 +1,78 @@ -#!/usr/bin/python3 -# -*- coding: utf-8 -*- -""" -@brief This client was developed by KSat for the SOURCE project to test the on-board software. -@details -This client features multiple sender/receiver modes and has been designed -to be extensible and easy to use. This clien is based on the PUS standard for the format -of telecommands and telemetry. It can also send TMTC via different interfaces like the -serial interface (USB port) or ethernet interface. - -@license -Copyright 2020 KSat e.V. Stuttgart - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -@manual -Run this file with the -h flag to display options. -""" import atexit import time import logging import sys +from multiprocessing import Process from collections import deque from typing import Tuple, Union from config import obsw_config as g -from config.obsw_config import set_globals -from config.obsw_com_config import set_communication_interface +from config.obsw_definitions import ModeList +from config.obsw_user_code import command_preparation_hook +from tmtc_core.utility.obsw_logger import get_logger from tmtc_core.tc.obsw_pus_tc_base import PusTcInfo from tmtc_core.sendreceive.obsw_single_command_sender_receiver import SingleCommandSenderReceiver from tmtc_core.sendreceive.obsw_sequential_sender_receiver import SequentialCommandSenderReceiver from tmtc_core.sendreceive.obsw_tm_listener import TmListener +from tmtc_core.comIF.obsw_com_interface import CommunicationInterface from tmtc_core.utility.obsw_tmtc_printer import TmTcPrinter from tmtc_core.utility.obsw_exit_handler import keyboard_interrupt_handler -from tmtc_core.utility.obsw_logger import set_tmtc_logger, get_logger +from tc.obsw_pus_tc_packer import ServiceQueuePacker, create_total_tc_queue from test.obsw_pus_service_test import run_selected_pus_tests -from tc.obsw_pus_tc_packer import create_total_tc_queue, ServiceQueuePacker -from utility.obsw_args_parser import parse_input_arguments -from utility.obsw_binary_uploader import perform_binary_upload - -from gui.obsw_tmtc_gui import TmTcGUI -from gui.obsw_backend_test import TmTcBackend -from obsw_user_code import command_preparation_hook +from config.obsw_com_config import set_communication_interface +from utility.obsw_binary_uploader import BinaryFileUploader LOGGER = get_logger() -def main(): +class TmTcHandler: """ - Main method, reads input arguments, sets global variables and start TMTC handler. + This is the primary class which handles TMTC reception. This can be seen as the backend + in case a GUI or front-end is implemented. """ - set_tmtc_logger() - LOGGER.info("Starting TMTC Client") - - LOGGER.info("Parsing input arguments") - args = parse_input_arguments() - - LOGGER.info("Setting global variables") - set_globals(args) - - LOGGER.info("Starting TMTC Handler") - - if g.G_MODE_ID == g.ModeList.GUIMode: - do_gui_test() - - else: - tmtc_handler = TmTcHandler() - tmtc_handler.perform_operation() + def __init__(self, init_mode: ModeList = ModeList.ListenerMode): + self.mode = init_mode + self.com_if = g.G_COM_IF + # This flag could be used later to command the TMTC Client with a front-end + self.one_shot_operation = True - # At some later point, the program will run permanently and be able to take commands. - # For now we put a permanent loop here so the program - # doesn't exit automatically (TM Listener is daemonic) - while True: - pass + self.tmtc_printer: Union[None, TmTcPrinter] = None + self.communication_interface: Union[None, CommunicationInterface] = None + self.tm_listener: Union[None, TmListener] = None + self.single_command_package: Tuple[bytearray, Union[None, PusTcInfo]] = bytearray(), None -def do_gui_test(): - # Experimental - backend = TmTcBackend() - backend.start() - gui = TmTcGUI() - gui.start() - backend.join() - gui.join() - LOGGER.info("Both processes have closed") - sys.exit() + def set_one_shot_or_loop_handling(self, enable: bool): + """ + Specify whether the perform_operation() call will only handle one action depending + on the mode or keep listening for replies after handling an operation. + """ + self.one_shot_operation = enable + def set_mode(self, mode: ModeList): + """ + Set the mode which will determine what perform_operation does. + """ + self.mode = mode -def command_preparation() -> Tuple[bytearray, Union[None, PusTcInfo]]: - """ - Prepare command for single command testing - :return: - """ - return command_preparation_hook() + @staticmethod + def prepare_tmtc_handler_start(init_mode: ModeList = g.ModeList.ListenerMode): + tmtc_handler = TmTcHandler(init_mode) + tmtc_task = Process(target=TmTcHandler.start_handler, args=(tmtc_handler, )) + return tmtc_task + @staticmethod + def start_handler(executed_handler): + executed_handler.initialize() + executed_handler.perform_operation() -class TmTcHandler: - """ - This is the primary class which handles TMTC reception. This can be seen as the backend - in case a GUI or front-end is implemented. - """ - def __init__(self): - self.mode = g.G_MODE_ID - self.com_if = g.G_COM_IF - # This flag could be used later to command the TMTC Client with a front-end - self.command_received = True + def initialize(self): + """ + Perform initialization steps which might be necessary after class construction. + This has to be called at some point before using the class! + """ self.tmtc_printer = TmTcPrinter(g.G_DISPLAY_MODE, g.G_PRINT_TO_FILE, True) self.communication_interface = set_communication_interface(self.tmtc_printer) self.tm_listener = TmListener( @@ -133,25 +90,16 @@ class TmTcHandler: """ Periodic operation """ - while True: - try: - if self.command_received: - self.command_received = False - self.handle_action() - if self.mode == g.ModeList.Idle: - LOGGER.info("TMTC Client in idle mode") - time.sleep(5) - if self.mode == g.ModeList.ListenerMode: - time.sleep(1) - except KeyboardInterrupt: - LOGGER.info("Closing TMTC client.") - sys.exit() - except IOError as e: - LOGGER.exception(e) - LOGGER.info("Closing TMTC client.") - sys.exit() - - def handle_action(self): + try: + self.__core_operation(self.one_shot_operation) + except KeyboardInterrupt: + LOGGER.info("Keyboard Interrupt.") + sys.exit() + except IOError as e: + LOGGER.error("IO Error occured!") + sys.exit() + + def __handle_action(self): """ Command handling. """ @@ -159,27 +107,31 @@ class TmTcHandler: self.prompt_mode() if self.mode == g.ModeList.ListenerMode: - if self.tm_listener.event_reply_received.is_set(): + if self.tm_listener.reply_event(): LOGGER.info("TmTcHandler: Packets received.") self.tmtc_printer.print_telemetry_queue(self.tm_listener.retrieve_tm_packet_queue()) self.tm_listener.clear_tm_packet_queue() - self.tm_listener.event_reply_received.clear() - self.command_received = True + self.tm_listener.clear_reply_event() elif self.mode == g.ModeList.SingleCommandMode: - pus_packet_tuple = command_preparation() + if self.single_command_package is None: + pus_packet_tuple = command_preparation() + else: + LOGGER.info("send package from gui") + pus_packet_tuple = self.single_command_package sender_and_receiver = SingleCommandSenderReceiver( com_interface=self.communication_interface, tmtc_printer=self.tmtc_printer, tm_listener=self.tm_listener) LOGGER.info("Performing single command operation") sender_and_receiver.send_single_tc_and_receive_tm(pus_packet_tuple=pus_packet_tuple) - self.command_received = True self.mode = g.ModeList.PromptMode elif self.mode == g.ModeList.ServiceTestMode: service_queue = deque() service_queue_packer = ServiceQueuePacker() - service_queue_packer.pack_service_queue(g.G_SERVICE, service_queue) + op_code = g.G_OP_CODE + service_queue_packer.pack_service_queue( + service=g.G_SERVICE, service_queue=service_queue, op_code=op_code) if not self.communication_interface.valid: return LOGGER.info("Performing service command operation") @@ -187,7 +139,6 @@ class TmTcHandler: com_interface=self.communication_interface, tmtc_printer=self.tmtc_printer, tm_listener=self.tm_listener, tc_queue=service_queue) sender_and_receiver.send_queue_tc_and_receive_tm_sequentially() - self.command_received = True self.mode = g.ModeList.ListenerMode elif self.mode == g.ModeList.SoftwareTestMode: @@ -203,8 +154,9 @@ class TmTcHandler: elif self.mode == g.ModeList.BinaryUploadMode: # Upload binary, prompt user for input, in the end prompt for new mode and enter that # mode - perform_binary_upload() - self.command_received = True + file_uploader = BinaryFileUploader(self.communication_interface, self.tmtc_printer, + self.tm_listener) + file_uploader.perform_file_upload() self.mode = g.ModeList.ListenerMode elif self.mode == g.ModeList.UnitTest: @@ -219,6 +171,19 @@ class TmTcHandler: logging.error("Unknown Mode, Configuration error !") sys.exit() + + def __core_operation(self, one_shot): + if not one_shot: + while True: + self.__handle_action() + if self.mode == g.ModeList.Idle: + LOGGER.info("TMTC Client in idle mode") + time.sleep(5) + elif self.mode == g.ModeList.ListenerMode: + time.sleep(1) + else: + self.__handle_action() + def prompt_mode(self): next_mode = input("Please enter next mode (enter h for list of modes): ") if next_mode == 'h': @@ -235,6 +200,22 @@ class TmTcHandler: else: self.mode = g.ModeList.ListenerMode + # These two will not be used for now. + @staticmethod + def prepare_tmtc_handler_start_in_process(init_mode: ModeList): + tmtc_handler_task = Process(target=TmTcHandler.start_tmtc_handler, args=(init_mode, )) + return tmtc_handler_task + + @staticmethod + def start_tmtc_handler(handler_args: any): + tmtc_handler = TmTcHandler(handler_args) + tmtc_handler.initialize() + tmtc_handler.perform_operation() + -if __name__ == "__main__": - main() +def command_preparation() -> Tuple[bytearray, Union[None, PusTcInfo]]: + """ + Prepare command for single command testing + :return: + """ + return command_preparation_hook() diff --git a/core/tmtc_client_core.py b/core/tmtc_client_core.py new file mode 100755 index 0000000000000000000000000000000000000000..08b93b1296755014784b019de34c275ae927ead7 --- /dev/null +++ b/core/tmtc_client_core.py @@ -0,0 +1,75 @@ +#!/usr/bin/python3 +""" +@brief This client was developed by KSat for the SOURCE project to test the on-board software. +@details +This client features multiple sender/receiver modes and has been designed +to be extensible and easy to use. This clien is based on the PUS standard for the format +of telecommands and telemetry. It can also send TMTC via different interfaces like the +serial interface (USB port) or ethernet interface. + +@license +Copyright 2020 KSat e.V. Stuttgart + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +@manual +Run this file with the -h flag to display options. +""" +from multiprocessing import Process +from tmtc_core.utility.obsw_logger import set_tmtc_logger, get_logger + +from config.obsw_config import set_globals +import config.obsw_config as g +from core.tmtc_backend import TmTcHandler +from core.tmtc_frontend import TmTcFrontend +from utility.obsw_args_parser import parse_input_arguments + +LOGGER = get_logger() + +def run_tmtc_client(use_gui: bool): + """ + Main method, reads input arguments, sets global variables and start TMTC handler. + """ + set_tmtc_logger() + LOGGER.info("Starting TMTC Client") + + if not use_gui: + LOGGER.info("Parsing input arguments") + args = parse_input_arguments() + + LOGGER.info("Setting global variables") + set_globals(args) + + LOGGER.info("Starting TMTC Handler") + + tmtc_frontend_task = Process + + # Currently does not work, problems with QEMU / Asyncio + if not use_gui: + tmtc_handler = TmTcHandler(g.G_MODE_ID) + tmtc_handler.set_one_shot_or_loop_handling(g.G_LISTENER_AFTER_OP) + tmtc_handler.initialize() + tmtc_handler.perform_operation() + else: + tmtc_gui = TmTcFrontend() + tmtc_gui.start_ui() + # tmtc_handler_task = TmTcHandler.prepare_tmtc_handler_start() + # tmtc_frontend = TmTcFrontend() + # tmtc_frontend_task = tmtc_frontend.prepare_start(tmtc_frontend) + # tmtc_frontend_task.start() + # tmtc_handler_task.start() + # tmtc_handler_task.join() + # tmtc_frontend_task.join() + + + diff --git a/core/tmtc_frontend.py b/core/tmtc_frontend.py new file mode 100644 index 0000000000000000000000000000000000000000..9a5908a2cc24732126de974caf32f2df8df9480c --- /dev/null +++ b/core/tmtc_frontend.py @@ -0,0 +1,356 @@ +#!/usr/bin/python3.7 +""" +@file tmtc_frontend.py +@date 01.11.2019 +@brief This is part of the TMTC client developed by the SOURCE project by KSat +@description GUI Testing for TMTC client +@manual +@author R. Mueller, P. Scheurenbrand +""" +from multiprocessing import Process + +from PyQt5.QtWidgets import * +from core.tmtc_backend import TmTcHandler +from tmtc_core.tc.obsw_pus_tc_base import PusTelecommand +from tmtc_core.utility.obsw_logger import get_logger +from config import obsw_config +from config.obsw_definitions import ComInterfaces +import threading + +LOGGER = get_logger() + +""" +TODO: Make it look nicer. Add SOURCE or KSat logo. +""" + +class TmTcFrontend: + + # TODO: this list should probably be inside an enum in the obsw_config.py + serviceList = [ 2, 3, 5, 8, 9, 17, 20, 200, "Dummy", "GPS0", "GPS1" ] # , "Error"] + + service_test_button: QPushButton + single_command_button: QPushButton + command_table: QTableWidget + + single_command_service: int = 17 + single_command_sub_service: int = 1 + single_command_ssc: int = 20 + single_command_data: bytearray = bytearray([]) + + is_busy: bool + + def __init__(self): + self.tmtc_handler = TmTcHandler() + # TODO: Perform initialization on button press with specified ComIF + # Also, when changing ComIF, ensure that old ComIF is closed (e.g. with printout) + # Lock all other elements while ComIF is invalid. + self.tmtc_handler.initialize() + obsw_config.G_SERVICE = 17 + obsw_config.G_COM_IF = obsw_config.ComInterfaces.QEMU + + def prepare_start(self, args: any) -> Process: + return Process(target=self.start_ui) + + def service_index_changed(self, index: int): + obsw_config.G_SERVICE = self.serviceList[index] + LOGGER.info("service_test_mode_selection updated: " + str(self.serviceList[index])) + + def single_command_set_service(self, value): + self.single_command_service = value + + def single_command_set_sub_service(self, value): + self.single_command_sub_service = value + + def single_command_set_ssc(self, value): + self.single_command_ssc = value + + def start_service_test_clicked(self): + LOGGER.info("start service test button pressed") + LOGGER.info("start testing service: " + str(obsw_config.G_SERVICE)) + self.tmtc_handler.mode = obsw_config.ModeList.ServiceTestMode + # start the action in a new process + p = threading.Thread(target=self.handle_tm_tc_action) + p.start() + + def send_single_command_clicked(self, table): + LOGGER.info("send single command pressed") + + # parse the values from the table + #service = int(self.commandTable.item(0, 0).text()) + #subservice = int(self.commandTable.item(0, 1).text()) + #ssc = int(self.commandTable.item(0, 2).text()) + + LOGGER.info("service: " + str(self.single_command_service) + + ", subservice: " + str(self.single_command_sub_service) + + ", ssc: " + str(self.single_command_ssc)) + + # TODO: data needs to be parsed in a different way + # data = int(self.commandTable.item(0, 3).text()) + # crc = int(self.commandTable.item(0, 4).text()) + + # create a command out of the parsed table + command = PusTelecommand( + service=self.single_command_service, subservice=self.single_command_sub_service, + ssc=self.single_command_ssc) + self.tmtc_handler.single_command_package = command.pack_command_tuple() + + self.tmtc_handler.mode = obsw_config.ModeList.SingleCommandMode + # start the action in a new process + p = threading.Thread(target=self.handle_tm_tc_action) + p.start() + + def handle_tm_tc_action(self): + LOGGER.info("start tmtc_handler.handle_action") + self.is_busy = True + self.set_send_buttons(False) + self.tmtc_handler.perform_operation() + self.is_busy = False + self.set_send_buttons(True) + LOGGER.info("finished tmtc_handler.handle_action") + + def set_send_buttons(self, state: bool): + self.service_test_button.setEnabled(state) + self.single_command_button.setEnabled(state) + + def start_ui(self): + app = QApplication([]) + + win = QWidget() + grid = QGridLayout() + + row = 0 + grid.addWidget(QLabel("Configuration:"), row, 0, 1, 2) + row += 1 + + checkbox_console = QCheckBox("print output to console") + checkbox_console.setChecked(obsw_config.G_PRINT_TM) + checkbox_console.stateChanged.connect(checkbox_console_print) + + checkbox_log = QCheckBox("print output to log file") + checkbox_log.setChecked(obsw_config.G_PRINT_TO_FILE) + checkbox_log.stateChanged.connect(checkbox_log_print) + + checkbox_raw_tm = QCheckBox("print all raw TM data directly") + checkbox_raw_tm.setChecked(obsw_config.G_PRINT_RAW_TM) + checkbox_raw_tm.stateChanged.connect(checkbox_print_raw_data) + + checkbox_hk = QCheckBox("print hk data") + checkbox_hk.setChecked(obsw_config.G_PRINT_HK_DATA) + checkbox_hk.stateChanged.connect(checkbox_print_hk_data) + + checkbox_short = QCheckBox("short display mode") + checkbox_short.setChecked(obsw_config.G_DISPLAY_MODE == "short") + checkbox_short.stateChanged.connect(checkbox_short_display_mode) + + grid.addWidget(checkbox_log, row, 0, 1, 1) + grid.addWidget(checkbox_console, row, 1, 1, 1) + row += 1 + grid.addWidget(checkbox_raw_tm, row, 0, 1, 1) + grid.addWidget(checkbox_hk, row, 1, 1, 1) + row += 1 + grid.addWidget(checkbox_short, row, 0, 1, 1) + row += 1 + + grid.addWidget(QLabel("TM Timeout:"), row, 0, 1, 1) + grid.addWidget(QLabel("TM Timeout Factor:"), row, 1, 1, 1) + row += 1 + + spin_timeout = QDoubleSpinBox() + spin_timeout.setValue(4) + # TODO: set sensible min/max values + spin_timeout.setSingleStep(0.1) + spin_timeout.setMinimum(0.25) + spin_timeout.setMaximum(60)# + # https://youtrack.jetbrains.com/issue/PY-22908 + # Ignore those warnings for now. + spin_timeout.valueChanged.connect(number_timeout) + grid.addWidget(spin_timeout, row, 0, 1, 1) + + spin_timeout_factor = QDoubleSpinBox() + spin_timeout_factor.setValue(obsw_config.G_TC_SEND_TIMEOUT_FACTOR) + # TODO: set sensible min/max values + spin_timeout_factor.setSingleStep(0.1) + spin_timeout_factor.setMinimum(0.25) + spin_timeout_factor.setMaximum(10) + spin_timeout_factor.valueChanged.connect(number_timeout_factor) + grid.addWidget(spin_timeout_factor, row, 1, 1, 1) + row += 1 + + grid.addWidget(QLabel("Client IP:"), row, 0, 1, 1) + grid.addWidget(QLabel("Board IP:"), row, 1, 1, 1) + row += 1 + + spin_client_ip = QLineEdit() + # TODO: set sensible min/max values + spin_client_ip.setInputMask("000.000.000.000;_") + spin_client_ip.textChanged.connect(ip_change_client) + grid.addWidget(spin_client_ip, row, 0, 1, 1) + + spin_board_ip = QLineEdit() + # TODO: set sensible min/max values + spin_board_ip.setInputMask("000.000.000.000;_") + spin_board_ip.textChanged.connect(ip_change_board) + #spin_board_ip.setText(obsw_config.G_SEND_ADDRESS[0]) + grid.addWidget(spin_board_ip, row, 1, 1, 1) + + + row += 1 + # com if configuration + grid.addWidget(QLabel("Communication Interface:"), row, 0, 1, 1) + com_if_comboBox = QComboBox() + # add all possible ComIFs to the comboBox + for comIf in obsw_config.ComInterfaces: + com_if_comboBox.addItem(comIf.name) + com_if_comboBox.setCurrentIndex(obsw_config.G_COM_IF.value) + com_if_comboBox.currentIndexChanged.connect(com_if_index_changed) + grid.addWidget(com_if_comboBox, row, 1, 1, 1) + row += 1 + + # service test mode gui + grid.addWidget(QLabel("Service Test Mode:"), row, 0, 1, 2) + row += 1 + + comboBox = QComboBox() + for service in self.serviceList: + comboBox.addItem("Service - " + str(service)) + comboBox.setCurrentIndex(self.serviceList.index(obsw_config.G_SERVICE)) + comboBox.currentIndexChanged.connect(self.service_index_changed) + grid.addWidget(comboBox, row, 0, 1, 1) + + self.service_test_button = QPushButton() + self.service_test_button.setText("Start Service Test") + self.service_test_button.clicked.connect(self.start_service_test_clicked) + grid.addWidget(self.service_test_button, row, 1, 1, 1) + row += 1 + + # single command operation + grid.addWidget(QLabel("Single Command Operation:"), row, 0, 1, 1) + row += 1 + + single_command_grid = QGridLayout() + single_command_grid.setSpacing(5) + + single_command_grid.addWidget(QLabel("Service:"), row, 0, 1, 1) + single_command_grid.addWidget(QLabel("SubService:"), row, 1, 1, 1) + single_command_grid.addWidget(QLabel("SSC:"), row, 2, 1, 1) + + row += 1 + + spin_service = QSpinBox() + spin_service.setValue(self.single_command_service) + # TODO: set sensible min/max values + spin_service.setMinimum(0) + spin_service.setMaximum(99999) + spin_service.valueChanged.connect(self.single_command_set_service) + single_command_grid.addWidget(spin_service, row, 0, 1, 1) + + spin_sub_service = QSpinBox() + spin_sub_service.setValue(self.single_command_sub_service) + # TODO: set sensible min/max values + spin_sub_service.setMinimum(0) + spin_sub_service.setMaximum(99999) + spin_sub_service.valueChanged.connect(self.single_command_set_sub_service) + single_command_grid.addWidget(spin_sub_service, row, 1, 1, 1) + + spin_ssc = QSpinBox() + spin_ssc.setValue(self.single_command_ssc) + # TODO: set sensible min/max values + spin_ssc.setMinimum(0) + spin_ssc.setMaximum(99999) + spin_ssc.valueChanged.connect(self.single_command_set_ssc) + single_command_grid.addWidget(spin_ssc, row, 2, 1, 1) + + row += 1 + + single_command_grid.addWidget(QLabel("Data:"), row, 0, 1, 3) + + row += 1 + + # TODO: how should this be converted to the byte array? + single_command_data_box = QTextEdit() + single_command_grid.addWidget(single_command_data_box, row, 0, 1, 3) + + grid.addItem(single_command_grid, row, 0, 1, 2) + + row += 1 + + #self.commandTable = SingleCommandTable() + #grid.addWidget(self.commandTable, row, 0, 1, 2) + row += 1 + self.single_command_button = QPushButton() + self.single_command_button.setText("Send single command") + self.single_command_button.clicked.connect(self.send_single_command_clicked) + grid.addWidget(self.single_command_button, row, 0, 1, 2) + row += 1 + + win.setLayout(grid) + win.resize(900, 800) + win.show() + + # resize table columns to fill the window width + #for i in range(0, 5): + # self.commandTable.setColumnWidth(i, int(self.commandTable.width() / 5) - 3) + + app.exec_() + +class SingleCommandTable(QTableWidget): + def __init__(self): + super().__init__() + self.setRowCount(1) + self.setColumnCount(5) + self.setHorizontalHeaderItem(0, QTableWidgetItem("Service")) + self.setHorizontalHeaderItem(1, QTableWidgetItem("Subservice")) + self.setHorizontalHeaderItem(2, QTableWidgetItem("SSC")) + self.setHorizontalHeaderItem(3, QTableWidgetItem("Data")) + self.setHorizontalHeaderItem(4, QTableWidgetItem("CRC")) + self.setItem(0, 0, QTableWidgetItem("17")) + self.setItem(0, 1, QTableWidgetItem("1")) + self.setItem(0, 2, QTableWidgetItem("20")) + +def com_if_index_changed(index: int): + obsw_config.G_COM_IF = ComInterfaces(index) + LOGGER.info("com if updated: " + str(obsw_config.G_COM_IF)) + +def checkbox_console_print(state: int): + LOGGER.info(["enabled", "disabled"][state == 0] + " console print") + obsw_config.G_PRINT_TM = state == 0 + + +def checkbox_log_print(state: int): + LOGGER.info(["enabled", "disabled"][state == 0] + " print to log") + obsw_config.G_PRINT_TO_FILE = state == 0 + + +def checkbox_print_raw_data(state: int): + LOGGER.info(["enabled", "disabled"][state == 0] + " printing of raw data") + obsw_config.G_PRINT_RAW_TM = state == 0 + + +def checkbox_print_hk_data(state: int): + LOGGER.info(["enabled", "disabled"][state == 0] + " printing of hk data") + obsw_config.G_PRINT_HK_DATA = state == 0 + + +def checkbox_short_display_mode(state: int): + LOGGER.info(["enabled", "disabled"][state == 0] + " short display mode") + obsw_config.G_DISPLAY_MODE = ["short", "long"][state == 0] + + +def number_timeout(value: float): + LOGGER.info("tm timeout changed to: " + str(value)) + obsw_config.G_TM_TIMEOUT = value + + +def number_timeout_factor(value: float): + LOGGER.info("tm timeout factor changed to: " + str(value)) + obsw_config.G_TC_SEND_TIMEOUT_FACTOR = value + + +def ip_change_client(value): + LOGGER.info("client ip changed: " + value) + obsw_config.G_REC_ADDRESS = (value, 2008) + + +def ip_change_board(value): + LOGGER.info("board ip changed: " + value) + obsw_config.G_SEND_ADDRESS = (value, 7) \ No newline at end of file diff --git a/gui/obsw_tmtc_gui.py b/gui/obsw_tmtc_gui.py deleted file mode 100644 index 8c322d5e8e7f54f2ba7a23b5dd9b6209624db546..0000000000000000000000000000000000000000 --- a/gui/obsw_tmtc_gui.py +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/python3.7 -# -*- coding: utf-8 -*- -""" -@file - obsw_tmtc_gui.py -@date - 01.11.2019 -@brief - This is part of the TMTC client developed by the SOURCE project by KSat -@description - GUI Testing for TMTC client -@manual -@author: - R. Mueller -""" -import tkinter as tk -from multiprocessing.connection import Client -from multiprocessing import Process -from tmtc_core.utility.obsw_logger import get_logger -import time - -LOGGER = get_logger() - -# A first simple version has drop down menus to chose all necessary options -# which are normally handled by the args parser. -# when pressing save, all chosen values get passed to the globals file (OBSW_Config) -# To start the program, another button with start needs to be set up. -# A third button to perform a keyboard interrupt should be implemented -# include a really nice source badge and make it large ! -# plan this on paper first... -# Step 1: Huge Mission Badge in Tkinter window because that is cool. -# Step 2: Simple buttons to run servce tests around the badge. -class TmTcGUI(Process): - def __init__(self): - super(TmTcGUI, self).__init__() - self.root = None - self.address = ('localhost', 6000) - self.conn = Client(self.address, authkey=None) - self.counter = 0 - - def run(self): - self.open() - - def open(self): - self.root = tk.Tk() - self.root.title("Hallo Welt") - while True: - LOGGER.info("TmTcGUI: Sending test message") - self.conn.send("test") - self.root.update() - time.sleep(0.1) - self.counter = self.counter + 1 - if self.counter == 50: - self.conn.send("close") - self.conn.close() - break - # self.window.mainloop() - - def close(self): - pass - # self.window.quit() diff --git a/requirements.txt b/requirements.txt index 4a3f79dd0651dd1e85c8e72f74264a7f5a6cecde..78c3bdb95643e7298470cc47c523f99b3c2a4989 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,26 +1,4 @@ -aiohttp==3.6.2 -astroid==2.4.2 -async-timeout==3.0.1 -attrs==19.3.0 -chardet==3.0.4 -colorama==0.4.3 -cpplint==1.5.4 crcmod>=1.7 -docopt==0.6.2 -future==0.18.2 -idna==2.10 -iso8601==0.1.12 -isort==5.4.2 -lazy-object-proxy==1.5.1 -mccabe==0.6.1 -multidict==4.7.6 -pylint>=2.5.3 -PyQt5>=5.15.0 -PyQt5-sip>=12.8.0 +PyQt5>=5.15.1 +PyQt5-stubs>=5.14.2.2 pyserial>=3.4 -PyYAML==5.3.1 -six==1.15.0 -toml==0.10.1 -typing-extensions==3.7.4.2 -wrapt==1.11.2 -yarl==1.5.1 diff --git a/tc/obsw_image_handler.py b/tc/obsw_image_handler.py new file mode 100644 index 0000000000000000000000000000000000000000..6f3216861781687d30e6180c43cdb21eed8379a7 --- /dev/null +++ b/tc/obsw_image_handler.py @@ -0,0 +1,54 @@ +from typing import Union + +from tmtc_core.tc.obsw_pus_tc_base import PusTelecommand, Deque +from tc.obsw_tc_service8 import make_action_id +from tc.obsw_tc_service20 import pack_boolean_parameter_setting +from tmtc_core.utility.obsw_logger import get_logger +from config.obsw_config import SW_IMAGE_HANDLER_ID + +LOGGER = get_logger() + + +def generate_copy_bl_sdc_to_flash_packet(ssc: int, from_fram: bool = False, + object_id: bytearray = SW_IMAGE_HANDLER_ID): + app_data = bytearray(object_id) + app_data += make_action_id(11) + app_data.append(from_fram) + return PusTelecommand(service=8, subservice=128, ssc=ssc, app_data=app_data) + + +# Slot values: 0 -> Slot 0, 1 -> Slot 1, 2 -> Update Slot +def generate_copy_obsw_sdc_to_flash_packet(ssc: int, slot: int, + object_id: bytearray = SW_IMAGE_HANDLER_ID): + app_data = bytearray(object_id) + app_data += make_action_id(4) + app_data.append(slot) + return PusTelecommand(service=8, subservice=128, ssc=ssc, app_data=app_data) + + +def generate_param_packet_hamming_from_sdcard(enable: bool, ssc: int, + object_id: bytearray = SW_IMAGE_HANDLER_ID): + return pack_boolean_parameter_setting(object_id=object_id, domain_id=0, unique_id=0, + parameter=enable, ssc=ssc) + + +def generate_img_handler_packet(service_queue: Deque, op_code: Union[int, str]): + # Action ID 4 (Copy SDC to Flash, Software Update Image) + if op_code == "A4U": + service_queue.appendleft(("print", "Generating command to copy SDC OBSW to flash.")) + command = generate_copy_obsw_sdc_to_flash_packet(ssc=0, slot=2) + service_queue.appendleft(command.pack_command_tuple()) + # Action ID 11 (Copy bootloader from SDC to flash + elif op_code == "A11S": + service_queue.appendleft(("print", "Generating command to copy SDC bootloader to flash.")) + command = generate_copy_bl_sdc_to_flash_packet(0) + service_queue.appendleft(command.pack_command_tuple()) + elif op_code == "P0": + service_queue.appendleft(("print", "Configuring hamming code to be taken from SD card")) + command = generate_param_packet_hamming_from_sdcard(enable=True, ssc=0) + service_queue.appendleft(command.pack_command_tuple()) + elif op_code == "P1": + service_queue.appendleft(("print", "Configuring hamming code to be taken from FRAM")) + command = generate_param_packet_hamming_from_sdcard(enable=False, ssc=0) + service_queue.appendleft(command.pack_command_tuple()) + diff --git a/tc/obsw_pus_tc_frame_packer.py b/tc/obsw_pus_tc_frame_packer.py index 71d045feb2fdf3a4565384d88afd0678ee3fa7e7..12447d34e9288af1fcff012337ac936c21d9e0ff 100644 --- a/tc/obsw_pus_tc_frame_packer.py +++ b/tc/obsw_pus_tc_frame_packer.py @@ -49,4 +49,4 @@ def pack_tc_info(tc_list: List[PusTelecommand]) -> List[PusTcInfo]: tc_info_list = list() for tc in tc_list: tc_info_list.append(tc.pack_information()) - return tc_info_list \ No newline at end of file + return tc_info_list diff --git a/tc/obsw_pus_tc_packer.py b/tc/obsw_pus_tc_packer.py index 23920defffab2162592f8143a8a002861c3f0126..c4d281ed5f67cd7d483a8e84c7430df55ea3bb4f 100644 --- a/tc/obsw_pus_tc_packer.py +++ b/tc/obsw_pus_tc_packer.py @@ -14,11 +14,14 @@ from tc.obsw_tc_service2 import pack_service2_test_into from tc.obsw_tc_service3 import pack_service3_test_into from tc.obsw_tc_service8 import pack_service8_test_into from tc.obsw_tc_service9 import pack_service9_test_into -from tc.obsw_tc_service23 import pack_service23_test_into +from tc.obsw_tc_service23_sdcard import pack_service23_commands_into from tc.obsw_tc_service20 import pack_service20_test_into +from tc.obsw_tc_utility import pack_utility_command from tc.obsw_tc_service200 import pack_mode_data, pack_service200_test_into from tc.obsw_tc_service5_17 import pack_service5_test_into, pack_service17_test_into +from tc.obsw_image_handler import generate_img_handler_packet from tc.obsw_tc_gps import pack_gps_test_into +from tc.obsw_tc_core import pack_core_command from tmtc_core.utility.obsw_logger import get_logger import config.obsw_config as g @@ -32,7 +35,8 @@ class ServiceQueuePacker: def __init__(self): pass - def pack_service_queue(self, service: Union[int, str], service_queue: TcQueueT): + @staticmethod + def pack_service_queue(service: Union[int, str], op_code: int, service_queue: TcQueueT): if service == 2: return pack_service2_test_into(service_queue) if service == 3: @@ -44,24 +48,30 @@ class ServiceQueuePacker: if service == 9: return pack_service9_test_into(service_queue) if service == 17: - return pack_service17_test_into(service_queue) + return pack_service17_test_into(service_queue, op_code) if service == 20: return pack_service20_test_into(service_queue) - if service == 23: - return pack_service23_test_into(service_queue) + if service == 23 or service.lower() == "sd": + return pack_service23_commands_into(service_queue, op_code) if service == 200: return pack_service200_test_into(service_queue) - if service == "Dummy": + if service.lower() == "dummy": return pack_dummy_device_test_into(service_queue) - if service == "GPS0": + if service.lower() == "img": + return generate_img_handler_packet(service_queue, op_code) + if service.lower() == "core": + return pack_core_command(service_queue, op_code) + if service.lower() == "led": + return pack_utility_command(service_queue, op_code) + if service.lower() == "gps0": # Object ID: GPS Device object_id = g.GPS0_DEVICE_ID return pack_gps_test_into(object_id, service_queue) - if service == "GPS1": + if service.lower() == "gps1": # Object ID: GPS Device object_id = g.GPS1_DEVICE_ID return pack_gps_test_into(object_id, service_queue) - if service == "Error": + if service.lower() == "Error": return pack_error_testing_into(service_queue) LOGGER.warning("Invalid Service !") @@ -77,6 +87,7 @@ def create_total_tc_queue() -> TcQueueT: tc_queue = pack_service8_test_into(tc_queue) tc_queue = pack_service9_test_into(tc_queue) tc_queue = pack_service17_test_into(tc_queue) + tc_queue = pack_service20_test_into(tc_queue) tc_queue = pack_service200_test_into(tc_queue) tc_queue = pack_dummy_device_test_into(tc_queue) object_id = g.GPS0_DEVICE_ID diff --git a/tc/obsw_tc_core.py b/tc/obsw_tc_core.py new file mode 100644 index 0000000000000000000000000000000000000000..be4a2fa3910f779bcdd995113cf4b6fff0a6287c --- /dev/null +++ b/tc/obsw_tc_core.py @@ -0,0 +1,38 @@ +from typing import Deque + +from config.obsw_config import CORE_CONTROLLER_ID +from tc.obsw_tc_service8 import make_action_id +from tmtc_core.tc.obsw_pus_tc_base import PusTelecommand + + +def pack_core_command(tc_queue: Deque, op_code, ssc: int = 0): + if op_code.lower() == "a0": + tc_queue.appendleft(("print", "Generating OBC run time stats")) + command = generate_run_time_stats_generation_command(ssc=ssc) + tc_queue.appendleft(command.pack_command_tuple()) + if op_code.lower() == "a10": + tc_queue.appendleft(("print", "Resetting OBC.")) + command = generate_reset_obc_command(ssc=ssc) + tc_queue.appendleft(command.pack_command_tuple()) + if op_code.lower() == "a11": + tc_queue.appendleft(("print", "Power cycling OBC.")) + command = generate_power_cycle_obc_command(ssc=ssc) + tc_queue.appendleft(command.pack_command_tuple()) + + +def generate_reset_obc_command(ssc: int, object_id: bytearray = CORE_CONTROLLER_ID): + app_data = bytearray(object_id) + app_data += make_action_id(10) + return PusTelecommand(service=8, subservice=128, ssc=ssc, app_data=app_data) + + +def generate_power_cycle_obc_command(ssc: int, object_id: bytearray = CORE_CONTROLLER_ID): + app_data = bytearray(object_id) + app_data += make_action_id(11) + return PusTelecommand(service=8, subservice=128, ssc=ssc, app_data=app_data) + + +def generate_run_time_stats_generation_command(ssc: int, object_id: bytearray = CORE_CONTROLLER_ID): + app_data = bytearray(object_id) + app_data += make_action_id(0) + return PusTelecommand(service=8, subservice=128, ssc=ssc, app_data=app_data) diff --git a/tc/obsw_tc_gps.py b/tc/obsw_tc_gps.py index 9d9e1eb29cd230694aab8ed3129e640c7eaf2f4f..1a047bf304543f8268967c814f068419fd3bfc96 100644 --- a/tc/obsw_tc_gps.py +++ b/tc/obsw_tc_gps.py @@ -11,6 +11,7 @@ from tc.obsw_tc_service2 import pack_mode_data import config.obsw_config as g + def pack_gps_test_into(object_id: bytearray, tc_queue: TcQueueT) -> TcQueueT: if object_id == g.GPS0_DEVICE_ID: gps_string = "GPS0" diff --git a/tc/obsw_tc_service20.py b/tc/obsw_tc_service20.py index 1b316d68e38b0f2750857c2e78392f9968dc1d7e..b0dedf027528d041fa0b87c3adb7aa26ed746abd 100644 --- a/tc/obsw_tc_service20.py +++ b/tc/obsw_tc_service20.py @@ -9,15 +9,52 @@ import struct from typing import Deque import config.obsw_config as g -from tmtc_core.tc.obsw_pus_tc_base import PusTelecommand +from tmtc_core.tc.obsw_pus_tc_base import PusTelecommand, TcQueueT +from tmtc_core.utility.obsw_logger import get_logger from tc.obsw_tc_service200 import pack_mode_data +LOGGER = get_logger() + + +def pack_boolean_parameter_setting(object_id: bytearray, domain_id: int, + unique_id: int, parameter: bool, ssc: int): + """ + Generic function to pack a telecommand to tweak a boolean parameter + @param object_id: + @param domain_id: + @param unique_id: + @param parameter: + @param ssc: + @return: + """ + parameter_id = bytearray(4) + parameter_id[0] = domain_id + if unique_id > 255: + LOGGER.warning("Invalid unique ID, should be smaller than 255!") + return + parameter_id[1] = unique_id + parameter_id[2] = 0 + parameter_id[3] = 0 + data_to_pack = bytearray(object_id) + data_to_pack.extend(parameter_id) + # PTC and PFC for uint8_t according to CCSDS + ptc = 3 + pfc = 4 + rows = 1 + columns = 1 + data_to_pack.append(ptc) + data_to_pack.append(pfc) + data_to_pack.append(rows) + data_to_pack.append(columns) + data_to_pack.append(parameter) + return PusTelecommand(service=20, subservice=128, ssc=ssc, app_data=data_to_pack) + def pack_service20_test_into(tc_queue: Deque, called_externally: bool = False) -> Deque: - #parameter IDs + # parameter IDs parameterID0 = 0 - parameterID1 = 1 - parameterID2 = 2 + parameterID1 = 256 + parameterID2 = 512 if called_externally is False: tc_queue.appendleft(("print", "Testing Service 20")) @@ -29,121 +66,68 @@ def pack_service20_test_into(tc_queue: Deque, called_externally: bool = False) - command = PusTelecommand(service=200, subservice=1, ssc=2000, app_data=mode_data) tc_queue.appendleft(command.pack_command_tuple()) - #test invalid subservice - #use subservice 130 for invalid subservice check, as this is in use for dump reply - #(and therefore will never be a valid subservice) - #tc_queue.appendleft(("print", "Testing Service 20: Invalid subservice")) - #mode_data = pack_mode_data(object_id, 2, 0) - #command = PusTelecommand(service=20, subservice=130, ssc=810, app_data=mode_data) - #tc_queue.appendleft(command.pack_command_tuple()) - - #test invalid objectid //TODO: do we have an objectid known to be empty (even in future)? - #tc_queue.appendleft(("print", "Testing Service 20: Invalid object ID")) - #mode_data = pack_mode_data(object_id, 2, 0) - #command = PusTelecommand(service=20, subservice=128, ssc=810, app_data=mode_data) - #tc_queue.appendleft(command.pack_command_tuple()) - - #test invalid parameterID for load - #tc_queue.appendleft(("print", "Testing Service 20: Invalid parameter ID for load")) - #mode_data = pack_mode_data(object_id, 2, 0) - #command = PusTelecommand(service=20, subservice=128, ssc=810, app_data=mode_data) - #tc_queue.appendleft(command.pack_command_tuple()) - - #test invalid parameterID for dump - #tc_queue.appendleft(("print", "Testing Service 20: Invalid parameter ID for dump")) - #mode_data = pack_mode_data(object_id, 2, 0) - #command = PusTelecommand(service=20, subservice=129, ssc=810, app_data=mode_data) - #tc_queue.appendleft(command.pack_command_tuple()) - - #test checking Load for uint32_t + # test checking Load for uint32_t tc_queue.appendleft(("print", "Testing Service 20: Load uint32_t")) parameter_id = struct.pack(">I", parameterID0) + type_and_matrix_data = pack_type_and_matrix_data(3, 14, 1, 1) parameter_data = struct.pack(">I", 42) - payload = object_id + parameter_id + parameter_data - command = PusTelecommand(service=20, subservice=128, ssc=2001, app_data=payload) + payload = object_id + parameter_id+ type_and_matrix_data + parameter_data + command = PusTelecommand(service=20, subservice=128, ssc=2010, app_data=payload) tc_queue.appendleft(command.pack_command_tuple()) - #test checking Dump for uint32_t + # test checking Dump for uint32_t tc_queue.appendleft(("print", "Testing Service 20: Dump uint32_t")) parameter_id = struct.pack(">I", parameterID0) payload = object_id + parameter_id - command = PusTelecommand(service=20, subservice=129, ssc=2001, app_data=payload) + command = PusTelecommand(service=20, subservice=129, ssc=2020, app_data=payload) tc_queue.appendleft(command.pack_command_tuple()) - if called_externally is False: - tc_queue.appendleft(("export", "log/tmtc_log_service20.txt")) - return tc_queue - - -""" - #test checking Load for int32_t + # test checking Load for int32_t tc_queue.appendleft(("print", "Testing Service 20: Load int32_t")) - mode_data = pack_mode_data(object_id, 2, 0) - command = PusTelecommand(service=20, subservice=128, ssc=2003, app_data=mode_data) + parameter_id = struct.pack(">I", parameterID1) + type_and_matrix_data = pack_type_and_matrix_data(4, 14, 1, 1) + parameter_data = struct.pack(">i", -42) + payload = object_id + parameter_id+ type_and_matrix_data + parameter_data + command = PusTelecommand(service=20, subservice=128, ssc=2030, app_data=payload) tc_queue.appendleft(command.pack_command_tuple()) - #test checking Dump for int32_t + # test checking Dump for int32_t tc_queue.appendleft(("print", "Testing Service 20: Dump int32_t")) - mode_data = pack_mode_data(object_id, 2, 0) - command = PusTelecommand(service=20, subservice=129, ssc=2004, app_data=mode_data) + parameter_id = struct.pack(">I", parameterID1) + payload = object_id + parameter_id + command = PusTelecommand(service=20, subservice=129, ssc=2040, app_data=payload) tc_queue.appendleft(command.pack_command_tuple()) - #test checking Load for float + # test checking Load for float tc_queue.appendleft(("print", "Testing Service 20: Load float")) - mode_data = pack_mode_data(object_id, 2, 0) - command = PusTelecommand(service=20, subservice=128, ssc=2005, app_data=mode_data) + parameter_id = struct.pack(">I", parameterID2) + type_and_matrix_data = pack_type_and_matrix_data(5, 1, 1, 1) + parameter_data = struct.pack(">f", 4.2) + payload = object_id + parameter_id+ type_and_matrix_data + parameter_data + command = PusTelecommand(service=20, subservice=128, ssc=2050, app_data=payload) tc_queue.appendleft(command.pack_command_tuple()) - #test checking Dump for float + # test checking Dump for float tc_queue.appendleft(("print", "Testing Service 20: Dump float")) - mode_data = pack_mode_data(object_id, 2, 0) - command = PusTelecommand(service=20, subservice=129, ssc=2006, app_data=mode_data) - tc_queue.appendleft(command.pack_command_tuple()) -""" - - - - -""" - # set mode on - tc_queue.appendleft(("print", "Testing Service 8: Set On Mode")) - mode_data = pack_mode_data(object_id, 1, 0) - command = PusTelecommand(service=200, subservice=1, ssc=800, app_data=mode_data) + parameter_id = struct.pack(">I", parameterID2) + payload = object_id + parameter_id + command = PusTelecommand(service=20, subservice=129, ssc=2060, app_data=payload) tc_queue.appendleft(command.pack_command_tuple()) - # set mode normal - tc_queue.appendleft(("print", "Testing Service 8: Set Normal Mode")) - mode_data = pack_mode_data(object_id, 2, 0) - command = PusTelecommand(service=200, subservice=1, ssc=810, app_data=mode_data) - tc_queue.appendleft(command.pack_command_tuple()) + if called_externally is False: + tc_queue.appendleft(("export", "log/tmtc_log_service20.txt")) + return tc_queue - # Direct command which triggers completion reply - tc_queue.appendleft(("print", "Testing Service 8: Trigger Completion Reply")) - action_id = g.DUMMY_COMMAND_1 - direct_command = object_id + action_id - command = PusTelecommand(service=8, subservice=128, ssc=820, app_data=direct_command) - tc_queue.appendleft(command.pack_command_tuple()) - # Direct command which triggers _tm_data reply - tc_queue.appendleft(("print", "Testing Service 8: Trigger Data Reply")) - action_id = g.DUMMY_COMMAND_2 - command_param1 = g.DUMMY_COMMAND_2_PARAM_1 - command_param2 = g.DUMMY_COMMAND_2_PARAM_2 - direct_command = object_id + action_id + command_param1 + command_param2 - command = PusTelecommand(service=8, subservice=128, ssc=830, app_data=direct_command) - tc_queue.appendleft(command.pack_command_tuple()) +def pack_type_and_matrix_data(ptc, pfc, column, row): + data = bytearray(4) + data[0] = ptc + data[1] = pfc + data[2] = column + data[3] = row + return data - # Direct command which triggers an additional step reply and one completion reply - tc_queue.appendleft(("print", "Testing Service 8: Trigger Step and Completion Reply")) - action_id = g.DUMMY_COMMAND_3 - direct_command = object_id + action_id - command = PusTelecommand(service=8, subservice=128, ssc=840, app_data=direct_command) - tc_queue.appendleft(command.pack_command_tuple()) - # set mode off - tc_queue.appendleft(("print", "Testing Service 8: Set Off Mode")) - mode_data = pack_mode_data(object_id, 0, 0) - command = PusTelecommand(service=200, subservice=1, ssc=800, app_data=mode_data) - tc_queue.appendleft(command.pack_command_tuple()) - tc_queue.appendleft(("wait", 2)) -""" +def pack_service23_commands_into(tc_queue: TcQueueT, op_code: int): + if op_code == 0: + pack_service20_test_into(tc_queue=tc_queue) diff --git a/tc/obsw_tc_service23.py b/tc/obsw_tc_service23.py deleted file mode 100644 index d0e09076441a3838e1db0e7958a7f3d2ec70863a..0000000000000000000000000000000000000000 --- a/tc/obsw_tc_service23.py +++ /dev/null @@ -1,255 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Created: 21.01.2020 07:48 - -@author: Jakob Meier -""" -import math -import config.obsw_config as g -from typing import Deque - -from tc.obsw_pus_tc_packer import PusTelecommand - - -class Service23WriteToFile: - """ This class generates the telecommand packet for the custom PUS service [23, 128] - @param objectID(bytearray): The objectID of the filesystem handler (e.g. SD_CARD_HANDLER_ID, PLOCHandler) - @param repository_path(str): The directory of the file - @param filename(str): The name of the file (e.g. boot.bin) - @param file_data(bytearray): The data to write to the file - """ - def __init__(self, repository_path: str, filename: str, size_of_data_blocks: int, - object_id: bytearray = bytearray([]), file_data: bytearray = bytearray([])): - """ - - @param repository_path: - @param filename: - @param object_id: - @param file_data: - """ - self.file_data = [] - self.number_of_packets = 0 - self.file_data = file_data - self.data_to_pack = object_id - repository_path_length_h = len(bytearray(repository_path, 'utf-8')) >> 8 - repository_path_length_l = 0x00FF & len(bytearray(repository_path, 'utf-8')) - self.data_to_pack.append(repository_path_length_h) - self.data_to_pack.append(repository_path_length_l) - if repository_path != "": - self.data_to_pack += bytearray(repository_path, 'utf-8') - self.data_to_pack.append(len(bytearray(filename, 'utf-8'))) - self.data_to_pack += bytearray(filename, 'utf-8') - self.pus_packets = self.split_large_file(size_of_data_blocks) - - def split_large_file(self, size_of_data_blocks): - """ This function splits a large file in multiple packets - This is necessary because the packet size is limited - - :param size_of_data_blocks: The file is splitted in data blocks of this size - :return: List containing the PUS packets generated for each data block - """ - self.number_of_packets = math.floor(len(self.file_data) / size_of_data_blocks) - packetNumber = 0 - - commands = [] - for i in range(self.number_of_packets): - # append packet number - self.data_to_pack.append(size_of_data_blocks) - self.data_to_pack.append(packetNumber >> 8) - self.data_to_pack.append(0xFF & packetNumber) - self.data_to_pack += self.file_data[i * size_of_data_blocks:(i + 1) * size_of_data_blocks] - commands.append(PusTelecommand(service=23, subservice=128, ssc=21, app_data=self.data_to_pack)) - # Last data block, packet number and data block size is removed to create new command with next data block, - # packet number and data block size - self.data_to_pack = self.data_to_pack[:len(self.data_to_pack) - size_of_data_blocks - 2 - 1] - packetNumber = packetNumber + 1 - # Calculate remaining data bytes - remaining_data_size = len(self.file_data) - self.number_of_packets * size_of_data_blocks - self.data_to_pack.append(remaining_data_size) - self.data_to_pack.append(packetNumber >> 8) - self.data_to_pack.append(0xFF & packetNumber) - self.data_to_pack += self.file_data[self.number_of_packets * size_of_data_blocks:len(self.file_data)] - commands.append(PusTelecommand(service=23, subservice=128, ssc=21, app_data=self.data_to_pack)) - return commands - - def get_number_of_packets(self): - return self.number_of_packets - -# def sendSoftwareUpdate(comInterface, tmtcPrinter, tmListener, tmTimeout, tcTimeoutFactor, doPrintToFile): -# """ This function sends all packets to upload a new version of the software image -# The new image is assumed to be stored in the tmtc directory -# """ -# image = open("sourceobsw-at91sam9g20_ek-sdram.bin", "rb").read() -# update = Service23WriteToFile("", "boot.bin", objectID=[0x4D, 0x00, 0x73, 0xAD], file_data=image) -# updateQueue = deque() -# updateQueue.appendleft(("print", "Service 23 Software Update")) -# i = 1 -# for packet in update.pus_packets: -# updateQueue.appendleft( -# ("print", "Packet " + str(i) + "/" + str(len(update.pus_packets)) + " of software update sent")) -# updateQueue.appendleft(packet.packCommandTuple()) -# i = i + 1 -# updateQueue.appendleft(("print", "Transmission of software update complete")) -# SenderAndReceiver = SequentialCommandSenderReceiver(comInterface, tmtcPrinter, tmListener, tmTimeout, updateQueue, -# tcTimeoutFactor, doPrintToFile) -# SenderAndReceiver.sendQueueTcAndReceiveTmSequentially() - - -def generate_service23_subservice2_packet(filename: str, repositoryPath: str = "", - object_id=bytearray([])): - """ This function generates the application data field of a service 23/subservice 2 to - delete a file on a file-system-capable on-board memory. - : param filename: The name of the file to delete - repository_path: The path where the directory shall be created - objectID: The object ID of the memory handler which manages the file system - :return The TC[23,2] PUS packet - """ - data_to_pack = object_id - data_to_pack += bytearray(repositoryPath, 'utf-8') - # Add string terminator to repository_path - data_to_pack.append(0) - data_to_pack += bytearray(filename, 'utf-8') - # Add string terminator to filename - data_to_pack.append(0) - return PusTelecommand(service=23, subservice=2, ssc=21, app_data=data_to_pack) - - -def generate_service23_subservice9_packet(directory_name: str, repository_path: str = "", - object_id=bytearray([])): - """ This function generates the application data field of a service 23/subservice 9 packet. - This service can be used to create directories on file systems. - : param repository_path: The path where the directory shall be created - directoryName: The name of the directory to create - objectID: The object ID of the memory handler which manages the file system - :return - """ - data_to_pack = object_id - data_to_pack += bytearray(repository_path, 'utf-8') - # Add string terminator to repository path - data_to_pack.append(0) - data_to_pack += bytearray(directory_name, 'utf-8') - # Add string terminator to directory name - data_to_pack.append(0) - return PusTelecommand(service=23, subservice=9, ssc=21, app_data=data_to_pack) - - -def generateService23Subservice10Packet(directory_name: str, repository_path: str = "", - object_id=bytearray([])): - """ This function generates the application data field for a PUS packet with service - 23 and subservie 10. - This service deletes the directory dirname. - @param directory_name: Name of the directory to delete - @param repository_path: Path to directory dirname - @param object_id: object ID of the memory handler (e.g. SD Card Handler) - @return The application data field of the (23,10) PUS packet - """ - data_to_pack = object_id - data_to_pack += bytearray(repository_path, 'utf-8') - # Add string terminator of repository path - data_to_pack.append(0) - data_to_pack += bytearray(directory_name, 'utf-8') - # Add string terminator of directory name - data_to_pack.append(0) - return PusTelecommand(service=23, subservice=10, ssc=21, app_data=data_to_pack) - - -def generate_service23_subservice128_packet(repository_path: str, filename: str, - object_id: bytearray = bytearray([]), - file_data: bytearray = bytearray([])): - """ This function generates the application data field for a PUS packet with service - 23 and subservie 128. Subservice 128 is a custom service to write data in a file. - Additionally file is created if not already existing. - @param repository_path: The path of the target file - @param filename: Name of file from which the content shall be read - @param object_id: object ID of the memory handler (e.g. SD Card Handler) - @param file_data: The data to write in the file - @return: The application data field of the (23,128) PUS packet - """ - data_to_pack = object_id - data_to_pack += bytearray(repository_path, 'utf-8') - # Add string terminator of repository path - data_to_pack.append(0) - data_to_pack += bytearray(filename, 'utf-8') - # Add string terminator of filename - data_to_pack.append(0) - return split_large_file(data_to_pack, 236, file_data) - - -def split_large_file(data_to_pack: bytearray, size_of_data_blocks, data: bytearray): - """ - This function splits a large file in multiple packets. - This is necessary because the packet size is limited. - @param data_to_pack: bytearray of data. data will be split and appended to this bytearray - @param size_of_data_blocks: The file is splitted in data blocks of this size - @param data: The data to pack in multiple packets - @return List containing the PUS packets generated for each data block - """ - numberOfPackets = math.floor(len(data) / size_of_data_blocks) - - packetNumber = 0 - - commands = [] - for i in range(numberOfPackets): - data_to_pack.append(packetNumber >> 8) - data_to_pack.append(0xFF & packetNumber) - data_to_pack += data[i * size_of_data_blocks:(i + 1) * size_of_data_blocks] - commands.append(PusTelecommand(service=23, subservice=128, ssc=21, app_data=data_to_pack)) - # Last data block, packet number and data block size is removed to create new command with - # next data block, packet number - data_to_pack = data_to_pack[:len(data_to_pack) - size_of_data_blocks - 2] - packetNumber = packetNumber + 1 - data_to_pack.append(packetNumber >> 8) - data_to_pack.append(0xFF & packetNumber) - data_to_pack += data[numberOfPackets * size_of_data_blocks:len(data)] - commands.append(PusTelecommand(service=23, subservice=128, ssc=21, app_data=data_to_pack)) - return commands - - -def generate_service23_subservice129_packet(repository_path: str, filename: str, - object_id: bytearray = bytearray([])): - """ - This function generates the application data field for a PUS packet with service - 23 and subservie 129. Subservice 129 is a custom service to request the data of a file. - @param repository_path: The path of the target file - @param filename: Name of file from which the content shall be read - @param object_id: object ID of the memory handler (e.g. SD Card Handler) - @return: The application data field of the (23,129) PUS packet - """ - data_to_pack = object_id - data_to_pack += bytearray(repository_path, 'utf-8') - # Add string terminator of repository paht - data_to_pack.append(0) - data_to_pack += bytearray(filename, 'utf-8') - # Add string terminator of filename - data_to_pack.append(0) - return PusTelecommand(service=23, subservice=129, ssc=21, app_data=data_to_pack) - - -def pack_service23_test_into(tc_queue: Deque) -> Deque: - sd_handler_id = g.SD_CARD_HANDLER_ID - tc_queue.appendleft(("print", "Testing Service 23")) - tc_queue.append(("print", "Create directory 'test'")) - command = generate_service23_subservice9_packet(directory_name="test", object_id=sd_handler_id) - tc_queue.appendleft(command.pack_command_tuple()) - # tc_queue.append(("print", "Create subdirectory 'subdir' in 'test'")) - # command = generate_service23_subservice9_packet(repository_path="test", directory_name="subdir", - # object_id=sd_handler_id) - # tc_queue.appendleft(command.pack_command_tuple()) - # tc_queue.appendleft(("print", "Create and write in test.bin")) - # command = generate_service23_subservice128_packet( - # "test/subdir", "test.bin", sd_handler_id, file_data=bytearray([0x01, 0x00, 0x01, 0x00])) - # tc_queue.appendleft(command[0].pack_command_tuple()) - # tc_queue.appendleft(("print", "Read data of test.bin")) - # command = generate_service23_subservice129_packet("test/subdir", "test.bin", sd_handler_id) - # tc_queue.appendleft(command.pack_command_tuple()) - # tc_queue.appendleft(("print", "Delete 'test.bin'")) - # command = generate_service23_subservice2_packet("test.bin", "test/subdir", object_id=sd_handler_id) - # tc_queue.appendleft(command.pack_command_tuple()) - # tc_queue.appendleft(("print", "Delete 'subdir' directory")) - # command = generateService23Subservice10Packet("subdir", "test", object_id=sd_handler_id) - # tc_queue.appendleft(command.pack_command_tuple()) - # tc_queue.appendleft(("print", "Delete 'test' directory")) - # command = generateService23Subservice10Packet(directory_name="test", object_id=sd_handler_id) - # tc_queue.appendleft(command.pack_command_tuple()) - tc_queue.appendleft(("print", "\r")) - return tc_queue diff --git a/tc/obsw_tc_service23_sdcard.py b/tc/obsw_tc_service23_sdcard.py new file mode 100644 index 0000000000000000000000000000000000000000..b89ae1bfb3f10dc9cd95af6f9d92ed503f2e20a0 --- /dev/null +++ b/tc/obsw_tc_service23_sdcard.py @@ -0,0 +1,381 @@ +# -*- coding: utf-8 -*- +""" +Created: 21.01.2020 07:48 + +@author: Jakob Meier +""" +import config.obsw_config as g +from typing import Deque, Union + +from tc.obsw_pus_tc_packer import PusTelecommand, TcQueueT +from tc.obsw_tc_service8 import make_action_id +from tmtc_core.utility.obsw_logger import get_logger + +LOGGER = get_logger() + + +def generate_print_sd_card_packet( + ssc: int, object_id: bytearray = g.SD_CARD_HANDLER_ID) -> PusTelecommand: + app_data = bytearray(object_id) + app_data += make_action_id(2) + return PusTelecommand(service=8, subservice=128, ssc=ssc, app_data=app_data) + + +def generate_clear_sd_card_packet( + ssc: int, object_id: bytearray = g.SD_CARD_HANDLER_ID) -> PusTelecommand: + app_data = bytearray(object_id) + app_data += make_action_id(20) + return PusTelecommand(service=8, subservice=128, ssc=ssc, app_data=app_data) + + +def generate_format_sd_card_packet( + ssc: int, object_id: bytearray = g.SD_CARD_HANDLER_ID) -> PusTelecommand: + app_data = bytearray(object_id) + app_data += make_action_id(21) + return PusTelecommand(service=8, subservice=128, ssc=ssc, app_data=app_data) + + +def generate_generic_folder_structure( + tc_queue: Deque, init_ssc: int, object_id: bytearray = g.SD_CARD_HANDLER_ID, + iobc: bool = False): + tc_queue.appendleft(("print", "Creating TC folder")) + command = generate_mkdir_srv23_9_packet("TC", ssc=init_ssc, object_id=object_id) + tc_queue.appendleft(command.pack_command_tuple()) + init_ssc += 1 + command = generate_mkdir_srv23_9_packet( + repository_path="TC", directory_name="LARGE", ssc=init_ssc, object_id=object_id) + tc_queue.appendleft(command.pack_command_tuple()) + init_ssc += 1 + command = generate_mkdir_srv23_9_packet( + repository_path="TC", directory_name="SMALL", ssc=init_ssc, object_id=object_id) + tc_queue.appendleft(command.pack_command_tuple()) + init_ssc += 1 + + tc_queue.appendleft(("print", "Creating TM folder")) + command = generate_mkdir_srv23_9_packet("TM", ssc=init_ssc, object_id=object_id) + tc_queue.appendleft(command.pack_command_tuple()) + init_ssc += 1 + command = generate_mkdir_srv23_9_packet( + repository_path="TM", directory_name="HK", ssc=init_ssc, object_id=object_id) + tc_queue.appendleft(command.pack_command_tuple()) + init_ssc += 1 + command = generate_mkdir_srv23_9_packet( + repository_path="TM", directory_name="SC", ssc=init_ssc, object_id=object_id) + tc_queue.appendleft(command.pack_command_tuple()) + command = generate_mkdir_srv23_9_packet( + repository_path="TM/SC", directory_name="LARGE", ssc=init_ssc, object_id=object_id) + tc_queue.appendleft(command.pack_command_tuple()) + init_ssc += 1 + command = generate_mkdir_srv23_9_packet( + repository_path="TM/SC", directory_name="SMALL", ssc=init_ssc, object_id=object_id) + tc_queue.appendleft(command.pack_command_tuple()) + init_ssc += 1 + + tc_queue.appendleft(("print", "Creating BIN folder")) + command = generate_mkdir_srv23_9_packet("BIN", ssc=init_ssc, object_id=object_id) + tc_queue.appendleft(command.pack_command_tuple()) + init_ssc += 1 + if iobc: + command = generate_mkdir_srv23_9_packet( + repository_path="BIN", directory_name="IOBC", ssc=init_ssc, object_id=object_id) + tc_queue.appendleft(command.pack_command_tuple()) + init_ssc += 1 + command = generate_mkdir_srv23_9_packet( + repository_path="BIN/IOBC", directory_name="BL", ssc=init_ssc, object_id=object_id) + tc_queue.appendleft(command.pack_command_tuple()) + init_ssc += 1 + command = generate_mkdir_srv23_9_packet( + repository_path="BIN/IOBC", directory_name="OBSW", ssc=init_ssc, object_id=object_id) + tc_queue.appendleft(command.pack_command_tuple()) + init_ssc += 1 + else: + command = generate_mkdir_srv23_9_packet( + repository_path="BIN", directory_name="AT91", ssc=init_ssc, object_id=object_id) + tc_queue.appendleft(command.pack_command_tuple()) + init_ssc += 1 + command = generate_mkdir_srv23_9_packet( + repository_path="BIN/AT91", directory_name="BL", ssc=init_ssc, object_id=object_id) + tc_queue.appendleft(command.pack_command_tuple()) + init_ssc += 1 + command = generate_mkdir_srv23_9_packet( + repository_path="BIN/AT91", directory_name="OBSW", ssc=init_ssc, object_id=object_id) + tc_queue.appendleft(command.pack_command_tuple()) + init_ssc += 1 + + tc_queue.appendleft(("print", "Creating MISC folder")) + command = generate_mkdir_srv23_9_packet("MISC", ssc=init_ssc, object_id=object_id) + tc_queue.appendleft(command.pack_command_tuple()) + + +def generate_create_file_srv23_1_packet( + filename: str, repository_path: str, ssc: int, max_size_of_app_data: int, + initial_data: bytearray = bytearray([]), + object_id: bytearray = g.SD_CARD_HANDLER_ID) -> Union[PusTelecommand, None]: + if len(initial_data) > calculate_allowed_file_data_size( + max_size_of_app_data, filename, repository_path): + LOGGER.error("generate_create_file_srv23_1_packet: Initial data too large!") + return None + data_to_pack = pack_generic_file_command_header(object_id=object_id, first_path=repository_path, + second_path=filename) + data_to_pack += initial_data + return PusTelecommand(service=23, subservice=1, ssc=ssc, app_data=data_to_pack) + + +def generate_rm_file_srv23_2_packet(filename: str, repository_path: str, + ssc: int, object_id=g.SD_CARD_HANDLER_ID) -> PusTelecommand: + """ + This function generates a packet which is used to delete a file on a + file-system-capable on-board memory. + @param filename: The name of the file to delete + @param repository_path: The path where the directory shall be created + @param ssc: source sequence count + @param object_id: The object ID of the memory handler which manages the file system + @return The telecommand. + """ + data_to_pack = pack_generic_file_command_header(object_id=object_id, first_path=repository_path, + second_path=filename) + return PusTelecommand(service=23, subservice=2, ssc=ssc, app_data=data_to_pack) + + +def generate_report_file_attr_srv23_3_packet( + filename: str, repository_path: str, ssc: int, + object_id=g.SD_CARD_HANDLER_ID) -> PusTelecommand: + """ + @param filename: The name of the file to delete + @param repository_path: The path where the directory shall be created + @param ssc: source sequence count + @param object_id: The object ID of the memory handler which manages the file system + @return The telecommand. + """ + data_to_pack = pack_generic_file_command_header(object_id=object_id, first_path=repository_path, + second_path=filename) + return PusTelecommand(service=23, subservice=3, ssc=ssc, app_data=data_to_pack) + + +def generate_mkdir_srv23_9_packet(directory_name: str, ssc: int, repository_path: str = "/", + object_id: bytearray = g.SD_CARD_HANDLER_ID) -> PusTelecommand: + """ + This function generates a packet which is used to create directories on file systems. + @param directory_name: The path where the directory shall be created + @param repository_path: The name of the directory to create + @param ssc: source sequence count + @param object_id: The object ID of the memory handler which manages the file system + @return The telecommand. + """ + data_to_pack = pack_generic_file_command_header(object_id=object_id, first_path=repository_path, + second_path=directory_name) + return PusTelecommand(service=23, subservice=9, ssc=ssc, app_data=data_to_pack) + + +def generate_rmdir_srv23_10_packet(directory_name: str, repository_path: str, ssc: int, + object_id: bytearray = g.SD_CARD_HANDLER_ID) -> PusTelecommand: + """ + This function generates a packet which deletes the a directory at the specified repository path. + @param directory_name: Name of the directory to delete + @param repository_path: Path to directory dirname + @param ssc: source sequence count + @param object_id: object ID of the memory handler (e.g. SD Card Handler) + @return The telecommand. + """ + data_to_pack = pack_generic_file_command_header(object_id=object_id, first_path=repository_path, + second_path=directory_name) + return PusTelecommand(service=23, subservice=10, ssc=ssc, app_data=data_to_pack) + + +def generate_append_to_file_srv23_130_packet( + filename: str, repository_path: str, packet_sequence_number: int, + ssc: int, file_data: bytearray = bytearray([]), + object_id: bytearray = g.SD_CARD_HANDLER_ID) -> PusTelecommand: + data_to_pack = pack_generic_file_command_header(object_id=object_id, first_path=repository_path, + second_path=filename) + data_to_pack += file_data + data_to_pack.append(packet_sequence_number >> 8) + data_to_pack.append(packet_sequence_number & 0xff) + return PusTelecommand(service=23, subservice=130, ssc=ssc, app_data=data_to_pack) + + +def generate_finish_append_to_file_srv23_131_packet( + filename: str, repository_path: str, ssc: int, lock_file: bool = False, + object_id: bytearray = g.SD_CARD_HANDLER_ID): + data_to_pack = pack_generic_file_command_header(object_id=object_id, first_path=repository_path, + second_path=filename) + data_to_pack.append(lock_file) + return PusTelecommand(service=23, subservice=131, ssc=ssc, app_data=data_to_pack) + + +def generate_read_file_srv23_140_packet( + repository_path: str, filename: str, ssc: int, + object_id: bytearray = g.SD_CARD_HANDLER_ID) -> PusTelecommand: + """ + This function generates the application data field for a PUS packet with service + 23 and subservie 140. Subservice 140 is a custom service to request the data of a file. + @param repository_path: The path of the target file + @param filename: Name of file from which the content shall be read + @param ssc: source sequence count + @param object_id: object ID of the memory handler (e.g. SD Card Handler) + @return: The application data field of the (23,129) PUS packet + """ + data_to_pack = pack_generic_file_command_header(object_id=object_id, first_path=repository_path, + second_path=filename) + return PusTelecommand(service=23, subservice=140, ssc=ssc, app_data=data_to_pack) + + +def generate_lock_file_srv23_5_6_packet(ssc: int, lock: bool, repository_path: str, + filename: str, object_id: bytearray = g.SD_CARD_HANDLER_ID): + data_to_pack = pack_generic_file_command_header(object_id=object_id, first_path=repository_path, + second_path=filename) + if lock: + return PusTelecommand(service=23, subservice=5, ssc=ssc, app_data=data_to_pack) + else: + return PusTelecommand(service=23, subservice=6, ssc=ssc, app_data=data_to_pack) + + +def pack_service23_commands_into(tc_queue: TcQueueT, op_code: int) -> Deque: + # sd_handler_id = g.SD_CARD_HANDLER_ID + if op_code == 0: + generate_generic_service_23_test(tc_queue) + elif op_code == "3" or op_code == 3: + LOGGER.info("Press h in the following input requests") + LOGGER.info("to send a command to display the folder structure instead") + (repo_path, filename) = prompt_for_repo_filename() + if repo_path == "" and filename == "h": + tc_queue.appendleft(generate_print_sd_card_packet(ssc=0).pack_command_tuple()) + elif repo_path == "" and filename == "c": + return tc_queue + else: + tc_queue.append(("print", "Requesting file attributes")) + command = generate_report_file_attr_srv23_3_packet( + ssc=0, filename=filename, repository_path=repo_path) + tc_queue.appendleft(command.pack_command_tuple()) + elif op_code == "5" or op_code == 5: + LOGGER.info("Press h in the following input requests") + LOGGER.info("to send a command to display the folder structure instead") + (repo_path, filename) = prompt_for_repo_filename() + if repo_path == "" and filename == "h": + tc_queue.append(("print", "Printing active file system")) + tc_queue.appendleft(generate_print_sd_card_packet(ssc=0).pack_command_tuple()) + elif repo_path == "" and filename == "c": + return tc_queue + else: + tc_queue.append(("print", "Locking file")) + command = generate_lock_file_srv23_5_6_packet(ssc=0, repository_path=repo_path, + filename=filename, lock=True) + tc_queue.appendleft(command.pack_command_tuple()) + elif op_code == "6" or op_code == 6: + LOGGER.info("Press h in the following input requests to send a command to display the" + "folder structure instead") + (repo_path, filename) = prompt_for_repo_filename() + if repo_path == "" and filename == "h": + tc_queue.append(("print", "Printing active file system")) + tc_queue.appendleft(generate_print_sd_card_packet(ssc=0).pack_command_tuple()) + elif repo_path == "" and filename == "c": + return tc_queue + else: + tc_queue.append(("print", "Unlocking file")) + command = generate_lock_file_srv23_5_6_packet(ssc=0, repository_path=repo_path, + filename=filename, lock=False) + tc_queue.appendleft(command.pack_command_tuple()) + elif op_code == "A2": + tc_queue.append(("print", "Printing active file system")) + command = generate_print_sd_card_packet(ssc=2300) + tc_queue.appendleft(command.pack_command_tuple()) + elif op_code == "A20": + tc_queue.append(("print", "Clearing active file system")) + command = generate_clear_sd_card_packet(ssc=2300) + tc_queue.appendleft(command.pack_command_tuple()) + elif op_code == "A21": + tc_queue.append(("print", "Formatting active file system")) + command = generate_format_sd_card_packet(ssc=2300) + tc_queue.appendleft(command.pack_command_tuple()) + elif op_code == "C0A": + tc_queue.append(("print", "Generating generic folder structure on AT91")) + generate_generic_folder_structure(tc_queue, init_ssc=0, iobc=False) + elif op_code == "C0I": + tc_queue.append(("print", "Generating generic folder structure on iOBC")) + generate_generic_folder_structure(tc_queue, init_ssc=0, iobc=True) + + return tc_queue + + +def generate_generic_service_23_test(tc_queue: TcQueueT): + tc_queue.appendleft(("print", "Testing Service 23")) + + tc_queue.append(("print", "Create directory 'test'")) + command = generate_mkdir_srv23_9_packet(directory_name="test", repository_path="/", ssc=2300) + tc_queue.appendleft(command.pack_command_tuple()) + tc_queue.append(("print", "Create subdirectory 'subdir' in 'test'")) + command = generate_mkdir_srv23_9_packet(repository_path="test", ssc=2301, + directory_name="subdir") + tc_queue.appendleft(command.pack_command_tuple()) + + tc_queue.appendleft(("print", "Create test.bin")) + command = generate_create_file_srv23_1_packet( + filename="test.bin", repository_path="test/subdir", ssc=2302, + initial_data=bytearray([0x01, 0x00, 0x01, 0x00]), + max_size_of_app_data=1024) + tc_queue.appendleft(command.pack_command_tuple()) + + tc_queue.appendleft(("print", "Printing file structure.")) + command = generate_print_sd_card_packet(ssc=2300) + tc_queue.appendleft(command.pack_command_tuple()) + + tc_queue.appendleft(("print", "Clearing SD card")) + command = generate_clear_sd_card_packet(ssc=2301) + tc_queue.appendleft(command.pack_command_tuple()) + + tc_queue.appendleft(("print", "Printing file structure")) + command = generate_print_sd_card_packet(ssc=2302) + tc_queue.appendleft(command.pack_command_tuple()) + + # tc_queue.appendleft(("print", "Read data of test.bin")) + # command = generate_read_file_srv23_129_packet("test/subdir", "test.bin", ssc=2303) + # tc_queue.appendleft(command.pack_command_tuple()) + tc_queue.appendleft(("print", "Delete 'test.bin'")) + command = generate_rm_file_srv23_2_packet( + filename="test.bin", repository_path="test/subdir", ssc=2304) + tc_queue.appendleft(command.pack_command_tuple()) + tc_queue.appendleft(("print", "Delete 'subdir' directory")) + command = generate_rmdir_srv23_10_packet(directory_name="subdir", repository_path="test", + ssc=2305) + tc_queue.appendleft(command.pack_command_tuple()) + tc_queue.appendleft(("print", "Delete 'test' directory")) + command = generate_rmdir_srv23_10_packet(directory_name="test", repository_path="/", + ssc=2306) + tc_queue.appendleft(command.pack_command_tuple()) + + +def calculate_allowed_file_data_size(max_app_data_size: int, filename: str, repository: str): + # Subtract two because of '\0' terminators + return max_app_data_size - len(filename) - len(repository) - 2 + + +def prompt_for_repo_filename(): + input_confirmation = False + repo_path = "" + filename = "" + while not input_confirmation: + repo_path = input("Please type in repository path [c to cancel]: ") + if repo_path == "h": + return "", "h" + filename = input("Please type in filename path [c to cancel]: ") + print("Selection for repostiory path: " + str(repo_path)) + print("Selection for filename: " + str(filename)) + if repo_path == "c" or filename == "c": + return "", "c" + if repo_path == "h" or filename == "h": + return "", "h" + input_confirmation = input("Confirm selection [y/n]: ") + if input_confirmation in ['y', "yes", 1]: + input_confirmation = True + return repo_path, filename + + +def pack_generic_file_command_header(object_id: bytearray, first_path: str, second_path: str): + data_to_pack = bytearray(object_id) + data_to_pack += first_path.encode('utf-8') + # Add string terminator of repository paht + data_to_pack.append(0) + data_to_pack += second_path.encode('utf-8') + # Add string terminator of filename + data_to_pack.append(0) + return data_to_pack diff --git a/tc/obsw_tc_service5_17.py b/tc/obsw_tc_service5_17.py index 9045f08e163c5778014c80d116ac8721ed4f7699..23dbd25701c81f31e544a658d3a617df6f281a03 100644 --- a/tc/obsw_tc_service5_17.py +++ b/tc/obsw_tc_service5_17.py @@ -36,23 +36,45 @@ def pack_service5_test_into(tc_queue: TcQueueT) -> TcQueueT: return tc_queue -def pack_service17_test_into(tc_queue: TcQueueT) -> TcQueueT: - tc_queue.appendleft(("print", "Testing Service 17")) - # ping test - tc_queue.appendleft(("print", "Testing Service 17: Ping Test")) - command = PusTelecommand(service=17, subservice=1, ssc=1700) - tc_queue.appendleft(command.pack_command_tuple()) - # enable event - tc_queue.appendleft(("print", "Testing Service 17: Enable Event")) - command = PusTelecommand(service=5, subservice=5, ssc=52) - tc_queue.appendleft(command.pack_command_tuple()) - # test event - tc_queue.appendleft(("print", "Testing Service 17: Trigger event")) - command = PusTelecommand(service=17, subservice=128, ssc=1701) +def pack_service17_test_into(tc_queue: TcQueueT, op_code: int = 0) -> TcQueueT: + if op_code == 0: + tc_queue.appendleft(("print", "Testing Service 17")) + # ping test + tc_queue.appendleft(("print", "Testing Service 17: Ping Test")) + command = PusTelecommand(service=17, subservice=1, ssc=1700) + tc_queue.appendleft(command.pack_command_tuple()) + # enable event + tc_queue.appendleft(("print", "Testing Service 17: Enable Event")) + command = PusTelecommand(service=5, subservice=5, ssc=52) + tc_queue.appendleft(command.pack_command_tuple()) + # test event + tc_queue.appendleft(("print", "Testing Service 17: Trigger event")) + command = PusTelecommand(service=17, subservice=128, ssc=1701) + tc_queue.appendleft(command.pack_command_tuple()) + # invalid subservice + tc_queue.appendleft(("print", "Testing Service 17: Invalid subservice")) + command = PusTelecommand(service=17, subservice=243, ssc=1702) + tc_queue.appendleft(command.pack_command_tuple()) + tc_queue.appendleft(("export", "log/tmtc_log_service17.txt")) + elif op_code == 129: + pack_enable_periodic_print_packet(tc_queue, True, 0) + elif op_code == 130: + pack_enable_periodic_print_packet(tc_queue, False, 0) + elif op_code == 150: + pack_trigger_exception_packet(tc_queue, 0) + return tc_queue + + +def pack_enable_periodic_print_packet(tc_queue: TcQueueT, enable: bool, ssc: int): + tc_queue.appendleft(("print", "Enabling periodic printout")) + if enable: + command = PusTelecommand(service=17, subservice=129, ssc=ssc) + else: + command = PusTelecommand(service=17, subservice=130, ssc=ssc) tc_queue.appendleft(command.pack_command_tuple()) - # invalid subservice - tc_queue.appendleft(("print", "Testing Service 17: Invalid subservice")) - command = PusTelecommand(service=17, subservice=243, ssc=1702) + + +def pack_trigger_exception_packet(tc_queue: TcQueueT, ssc: int): + tc_queue.appendleft(("print", "Triggering software exception")) + command = PusTelecommand(service=17, subservice=150, ssc=ssc) tc_queue.appendleft(command.pack_command_tuple()) - tc_queue.appendleft(("export", "log/tmtc_log_service17.txt")) - return tc_queue diff --git a/tc/obsw_tc_service8.py b/tc/obsw_tc_service8.py index 130bc4996265e30a73c82913165456293dc80e2e..6449fcf45f5599368fc0b30061cc7d68ef0ce8ea 100644 --- a/tc/obsw_tc_service8.py +++ b/tc/obsw_tc_service8.py @@ -5,6 +5,7 @@ @author R. Mueller @date 01.11.2019 """ +import struct from typing import Deque import config.obsw_config as g @@ -62,3 +63,14 @@ def pack_service8_test_into(tc_queue: Deque, called_externally: bool = False) -> if called_externally is False: tc_queue.appendleft(("export", "log/tmtc_log_service8.txt")) return tc_queue + + +def generate_action_command(object_id: bytearray, action_id: int, data: bytearray = bytearray([]), + ssc: int = 0): + data_to_pack = bytearray(object_id) + data_to_pack += make_action_id(action_id) + data + return PusTelecommand(service=8, subservice=128, ssc=ssc, app_data=data_to_pack) + + +def make_action_id(action_id: int) -> bytearray: + return bytearray(struct.pack('!I', action_id)) diff --git a/tc/obsw_tc_service9.py b/tc/obsw_tc_service9.py index 507b57ffbba4723c9661970c4194ed97034a8aee..7970b0e5215faba74de4de94156f4a6236f16e29 100644 --- a/tc/obsw_tc_service9.py +++ b/tc/obsw_tc_service9.py @@ -36,4 +36,4 @@ def pack_service9_test_into(tc_queue: TcQueueT) -> TcQueueT: tc_queue.appendleft(command.pack_command_tuple()) # TODO: Add other time formats here tc_queue.appendleft(("export", "log/tmtc_log_service9.txt")) - return tc_queue \ No newline at end of file + return tc_queue diff --git a/tc/obsw_tc_utility.py b/tc/obsw_tc_utility.py new file mode 100644 index 0000000000000000000000000000000000000000..9f21283dc0bdfdc34194b3e135432540233b7d13 --- /dev/null +++ b/tc/obsw_tc_utility.py @@ -0,0 +1,13 @@ +from typing import Union + +from tmtc_core.tc.obsw_pus_tc_base import TcQueueT +from tc.obsw_tc_service8 import generate_action_command +from config.obsw_config import LED_TASK_ID + + +def pack_utility_command(service_queue: TcQueueT, op_code: Union[str, int]): + if op_code == "A0": + service_queue.appendleft(generate_action_command(LED_TASK_ID, 0x00).pack_command_tuple()) + elif op_code == "A1": + service_queue.appendleft(generate_action_command(LED_TASK_ID, 0x01).pack_command_tuple()) + diff --git a/test/obsw_module_test.py b/test/obsw_module_test.py index 07b97cec3523a0a73e1c6d78fc63e88a33f2a511..fbdd1b609b3beed2f19d34c24108f6909c7bf47c 100644 --- a/test/obsw_module_test.py +++ b/test/obsw_module_test.py @@ -240,10 +240,12 @@ class TestService(unittest.TestCase): if current_tm_info[TmDictionaryKeys.SERVICE] == 1: self.scan_for_respective_tc(current_tm_info) # Here, the desired event Id or RID can be specified + elif current_tm_info[TmDictionaryKeys.SERVICE] == 5: # TODO: hardcoded values.. should be in config file - if (current_tm_info[TmDictionaryKeys.EVENT_ID] == 8300 and - current_tm_info[TmDictionaryKeys.REPORTER_ID] == 0x51001700): + if current_tm_info[TmDictionaryKeys.EVENT_ID] == 9700 and \ + current_tm_info[TmDictionaryKeys.REPORTER_ID] == \ + (struct.unpack('>I', g.PUS_SERVICE_17)[0]): self.event_counter = self.event_counter + 1 elif current_tm_info[TmDictionaryKeys.SERVICE] == 17: self.misc_counter = self.misc_counter + 1 diff --git a/test/obsw_pus_service_test.py b/test/obsw_pus_service_test.py index 1d8410c8075715b454453f8f7824a217c41f8077..16137a669cb53a9f0cfc0076a1c349c2ab771bcf 100644 --- a/test/obsw_pus_service_test.py +++ b/test/obsw_pus_service_test.py @@ -11,7 +11,7 @@ from typing import Deque from test.obsw_module_test import TestService, PusTmInfoQueueT, TmDictionaryKeys, AssertionDictKeys from tmtc_core.tc.obsw_pus_tc_base import PusTcInfoQueueT from tc.obsw_pus_tc_packer import pack_service17_test_into, pack_service5_test_into, \ - pack_service2_test_into, pack_service8_test_into, pack_service200_test_into + pack_service2_test_into, pack_service8_test_into, pack_service200_test_into, pack_service20_test_into import config.obsw_config as g from tmtc_core.utility.obsw_logger import get_logger diff --git a/tm/obsw_pus_tm_factory_hook.py b/tm/obsw_pus_tm_factory_hook.py index 94899de4acb68c275049ca88e28cd29c6be22a96..94359cf02de06f448c37c09b620af0f6d13944a1 100644 --- a/tm/obsw_pus_tm_factory_hook.py +++ b/tm/obsw_pus_tm_factory_hook.py @@ -1,9 +1,13 @@ +import struct + from tmtc_core.tm.obsw_pus_tm_base import PusTelemetry from tmtc_core.utility.obsw_logger import get_logger + from tm.obsw_tm_service_1 import Service1TM from tm.obsw_tm_service_3 import Service3TM from tm.obsw_tm_service_5 import Service5TM -import struct +from tm.obsw_tm_service_20 import Service20TM +from tm.obsw_tm_service_23 import Service23TM LOGGER = get_logger() @@ -24,6 +28,8 @@ def tm_factory_hook(raw_tm_packet: bytearray) -> PusTelemetry: return Service17TM(raw_tm_packet) if service_type == 20: return Service20TM(raw_tm_packet) + if service_type == 23: + return Service23TM(raw_tm_packet) if service_type == 200: return Service200TM(raw_tm_packet) LOGGER.info("The service " + str(service_type) + " is not implemented in Telemetry Factory") @@ -86,23 +92,6 @@ class Service17TM(PusTelemetry): return -class Service20TM(PusTelemetry): - def __init__(self, byte_array): - super().__init__(byte_array) - self.parameter_id = struct.unpack('>I', self._tm_data[0:4])[0] - self.specify_packet_info("Functional Commanding Reply") - - def append_telemetry_content(self, array): - super().append_telemetry_content(array) - array.append(self.parameter_id) - return - - def append_telemetry_column_headers(self, array): - super().append_telemetry_column_headers(array) - array.append("param0_dump_repl") - return - - class Service200TM(PusTelemetry): def __init__(self, byte_array): super().__init__(byte_array) @@ -141,4 +130,4 @@ class Service200TM(PusTelemetry): elif self.isModeReply: array.append("Mode") array.append("Submode") - return \ No newline at end of file + return diff --git a/tm/obsw_tm_service_20.py b/tm/obsw_tm_service_20.py new file mode 100644 index 0000000000000000000000000000000000000000..48d4d630d126251cbd80976cf87fffcc78401c8f --- /dev/null +++ b/tm/obsw_tm_service_20.py @@ -0,0 +1,62 @@ +import struct + +from tmtc_core.tm.obsw_pus_tm_base import PusTelemetry, TmDictionaryKeys, PusTmInfoT + + +class Service20TM(PusTelemetry): + def __init__(self, byte_array): + super().__init__(byte_array) + datasize = len(self._tm_data) + self.objectId = struct.unpack('>I', self._tm_data[0:4])[0] + self.parameter_id = struct.unpack('>I', self._tm_data[4:8])[0] + if self.get_subservice() == 130: + self.type = struct.unpack('>H', self._tm_data[8:10])[0] + self.type_ptc = self._tm_data[8] + self.type_pfc = self._tm_data[9] + self.column = self._tm_data[10] + self.row = self._tm_data[11] + if self.type_ptc == 3 and self.type_pfc == 14: + self.param = struct.unpack('>I', self._tm_data[12:datasize])[0] + if self.type_ptc == 4 and self.type_pfc == 14: + self.param = struct.unpack('>i', self._tm_data[12:datasize])[0] + if self.type_ptc == 5 and self.type_pfc == 1: + self.param = struct.unpack('>f', self._tm_data[12:datasize])[0] + else: + logger.info("Error when receiving Pus Service 20 TM: subservice is != 130, but 130 is \ + only known subservice") + self.specify_packet_info("Functional Commanding Reply") + + def append_telemetry_content(self, array): + super().append_telemetry_content(array) + array.append(hex(self.objectId)) + array.append(self.parameter_id) + if self.get_subservice() == 130: + array.append("PTC: " + str(self.type_ptc) + " | PFC: " + str(self.type_pfc)) + array.append(str(self.column)) + array.append(str(self.row)) + if self.type_ptc == 5 and self.type_pfc == 1: + array.append(str(float(self.param))) + else: + array.append(str(hex(self.param))) + return + + def append_telemetry_column_headers(self, array): + super().append_telemetry_column_headers(array) + array.append("objectID") + array.append("parameterID") + if self.get_subservice() == 130: + array.append("type") + array.append("column") + array.append("row") + array.append("parameter") + return + + def pack_tm_information(self) -> PusTmInfoT: + tm_information = super().pack_tm_information() + add_information = { + TmDictionaryKeys.REPORTER_ID: self.objectId, + TmDictionaryKeys.EVENT_ID: self.parameter_id, + TmDictionaryKeys.EVENT_PARAM_1: self.param + } + tm_information.update(add_information) + return tm_information diff --git a/tm/obsw_tm_service_23.py b/tm/obsw_tm_service_23.py new file mode 100644 index 0000000000000000000000000000000000000000..b4668c332ff5c583f286129cbed23a6e5a5dafd3 --- /dev/null +++ b/tm/obsw_tm_service_23.py @@ -0,0 +1,79 @@ +import struct + +from tmtc_core.tm.obsw_pus_tm_base import PusTelemetry +from tmtc_core.utility.obsw_logger import get_logger + +LOGGER = get_logger() + + +class Service23TM(PusTelemetry): + MAX_REPOSITORY_LENGTH = 64 + MAX_FILENAME_LENGTH = 12 + + def __init__(self, byte_array): + super().__init__(byte_array) + if len(self.get_tm_data()) < 4: + LOGGER.error("Service23TM: Invalid packet format!") + return + self.object_id = struct.unpack('!I', self._tm_data[0:4])[0] + self.repo_path = "" + self.filename = "" + self.file_size = 0 + self.lock_status = False + self.data_start_idx = 0 + if self.get_subservice() == 4: + self.unpack_repo_and_filename() + self.unpack_file_attributes() + elif self.get_subservice() == 132: + self.unpack_repo_and_filename() + pass + + def unpack_repo_and_filename(self): + repo_path_found = False + path_idx_start = 0 + max_len_to_scan = len(self.get_tm_data()) - 4 + for idx in range(4, max_len_to_scan): + if not repo_path_found and self._tm_data[idx] == 0: + repo_bytes = self._tm_data[4:idx] + self.repo_path = repo_bytes.decode('utf-8') + path_idx_start = idx + 1 + idx += 1 + repo_path_found = True + if repo_path_found: + if self._tm_data[idx] == 0: + filename_bytes = self._tm_data[path_idx_start:idx] + self.filename = filename_bytes.decode('utf-8') + self.data_start_idx = idx + 1 + break + + def unpack_file_attributes(self): + # Size of file length (4) + lock status (1), adapt if more field are added! + print(len(self.get_tm_data()) - self.data_start_idx) + if len(self.get_tm_data()) - self.data_start_idx != 5: + LOGGER.error("Service23TM: Invalid lenght of file attributes data") + return + self.file_size = struct.unpack('!I', self.get_tm_data()[ + self.data_start_idx: self.data_start_idx + 4])[0] + self.lock_status = self.get_tm_data()[self.data_start_idx + 4] + + def append_telemetry_content(self, content_list: list): + super().append_telemetry_content(content_list) + content_list.append(hex(self.object_id)) + content_list.append(self.repo_path) + content_list.append(self.filename) + if self.get_subservice() == 4: + content_list.append(self.file_size) + if self.lock_status == 0: + content_list.append("No") + else: + content_list.append("Yes") + + def append_telemetry_column_headers(self, header_list: list): + super().append_telemetry_column_headers(header_list) + header_list.append("Object ID") + header_list.append("Repo Path") + header_list.append("File Name") + if self.get_subservice() == 4: + header_list.append("File Size") + header_list.append("Locked") + diff --git a/tm/obsw_tm_service_3.py b/tm/obsw_tm_service_3.py index 96be1223fc42fdfb94298ffabd993dfdc1434ede..ddb4376333700671b40b2f244a48a4a14f8b691a 100644 --- a/tm/obsw_tm_service_3.py +++ b/tm/obsw_tm_service_3.py @@ -122,8 +122,8 @@ class Service3TM(PusTelemetry): # TODO: size check. sth not right with gps 0 test self.number_of_parameters = 9 self.hk_header = ["Fix Mode", "SV in Fix", "GNSS Week", "Time of Week", "Latitude", - "Longitude", "Mean Sea Altitude", "Position X", "Position Y", "Position Z", - "Velocity X", "Velocity Y", "Velocity Z"] + "Longitude", "Mean Sea Altitude", "Position X", "Position Y", + "Position Z", "Velocity X", "Velocity Y", "Velocity Z"] fix_mode = self._tm_data[4] sv_in_fix = self._tm_data[5] gnss_week = struct.unpack('>H', self._tm_data[6:8])[0] diff --git a/tmtc_client_cli.py b/tmtc_client_cli.py new file mode 100644 index 0000000000000000000000000000000000000000..48c02fbe3b710e6d782bdb345d16760375c0aab8 --- /dev/null +++ b/tmtc_client_cli.py @@ -0,0 +1,34 @@ +#!/usr/bin/python3 +""" +@brief This client was developed by KSat for the SOURCE project to test the on-board software. +@details +This client features multiple sender/receiver modes and has been designed +to be extensible and easy to use. This clien is based on the PUS standard for the format +of telecommands and telemetry. It can also send TMTC via different interfaces like the +serial interface (USB port) or ethernet interface. + +@license +Copyright 2020 KSat e.V. Stuttgart + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +@manual +Run this file with the -h flag to display options. +""" +from core.tmtc_client_core import run_tmtc_client + +def main(): + run_tmtc_client(False) + +if __name__ == "__main__": + main() diff --git a/tmtc_client_gui.py b/tmtc_client_gui.py new file mode 100644 index 0000000000000000000000000000000000000000..60722026def47208fcd2bef2eb3e07607f2ea440 --- /dev/null +++ b/tmtc_client_gui.py @@ -0,0 +1,33 @@ +#!/usr/bin/python3 +""" +@brief This client was developed by KSat for the SOURCE project to test the on-board software. +@details +This client features multiple sender/receiver modes and has been designed +to be extensible and easy to use. This clien is based on the PUS standard for the format +of telecommands and telemetry. It can also send TMTC via different interfaces like the +serial interface (USB port) or ethernet interface. + +@license +Copyright 2020 KSat e.V. Stuttgart + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +@manual +""" +from core.tmtc_client_core import run_tmtc_client + +def main(): + run_tmtc_client(True) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/tmtc_core b/tmtc_core index 4d37769e7c8254bf7e20a016cf076ae48db31e57..1e06be166b0bf47a2a921fd45eed49ea9f5782c3 160000 --- a/tmtc_core +++ b/tmtc_core @@ -1 +1 @@ -Subproject commit 4d37769e7c8254bf7e20a016cf076ae48db31e57 +Subproject commit 1e06be166b0bf47a2a921fd45eed49ea9f5782c3 diff --git a/utility/binary_writer.py b/utility/binary_writer.py new file mode 100644 index 0000000000000000000000000000000000000000..c07ab66cdf39ec3d3a3e6aa5c6bdf129d0124079 --- /dev/null +++ b/utility/binary_writer.py @@ -0,0 +1,54 @@ +import os +import struct +from glob import glob + + +def main(): + """ + Was written to assign sixth arm vector to binary size for bootloader. + @return: + """ + + # Parse for binaries + file_path = file_selector("../../_bin", '*.bin') + file_size = os.path.getsize(file_path) + print("File size: " + str(file_size)) + size_uint32 = struct.pack("<I", file_size) + print("File size as uint32: " + ' '.join(map('{:02X}'.format, size_uint32))) + with open(file_path, "rb+") as file: + # Read the first seven ARM vectors. The sixth one will be replaced. + arm_vectors = file.read(4 * 7) + print("ARM vectors: ") + # print(''.join('{:02x}'.format(x) for x in arm_vectors)) + for x in range(0, 28, 4): + print(' '.join(map('{:02X}'.format, arm_vectors[x:x + 4]))) + file.seek(5*4) + file.write(size_uint32) + file.seek(0) + arm_vectors = file.read(4 * 7) + print("New ARM vector: ") + for x in range(0, 28, 4): + print(' '.join(map('{:02X}'.format, arm_vectors[x:x + 4]))) + pass + + +def file_selector(path: str, pattern: str) -> str: + result = [y for x in os.walk(path) for y in glob(os.path.join(x[0], pattern))] + print("Files found in _bin folder: ") + for idx, path in enumerate(result): + print("Selection " + str(idx) + ": " + str(path)) + selection = input("Please enter desired selection [c to cancel]: ") + while True: + if selection == 'c': + return "" + if not selection.isdigit(): + selection = input("Invalid input, try again [c to cancel]: ") + if selection.isdigit(): + if int(selection) < len(result): + return result[int(selection)] + else: + selection = input("Invalid input, try again [c to cancel]: ") + + +if __name__ == "__main__": + main() diff --git a/utility/obsw_args_parser.py b/utility/obsw_args_parser.py index bef39878d7c7eb07d7c2766e11bb4d11da000167..47f2018ae2a2a64961d5f7e4e6b5eadc207e2ce3 100644 --- a/utility/obsw_args_parser.py +++ b/utility/obsw_args_parser.py @@ -18,16 +18,23 @@ def parse_input_arguments(): arg_parser = argparse.ArgumentParser(description="TMTC Client Command Line Interface") arg_parser.add_argument( - '-m', '--mode', type=int, help='Target Mode. Default is 1(Listener Mode), ' - '0: GUI Mode, 1:Listener Mode, 2: Single Command Mode, 3: Service Test Mode, ' - '4: Software Test Mode, 5: Unit Test Mode ', default=0) + '-m', '--mode', type=int, help='Target Mode. Default is 1 (Listener Mode), ' + '0: GUI Mode, 1: Listener Mode, 2: Single Command Mode, 3: Service Test Mode, ' + '4: Software Test Mode, 5: Binary Upload Mode, 6: Unit Test Mode ', default=0) arg_parser.add_argument( '-c', '--com_if', type=int, help='Communication Interface. 0: Dummy Interface, 1: Serial, ' '2: QEMU, 3: UDP', default=2) + arg_parser.add_argument( + '-o', '--op_code', help='Operation code, which is passed to the TC ' + 'packer functions', default=0) arg_parser.add_argument('--clientIP', help='Client(Computer) IP. Default:\'\'', default='') arg_parser.add_argument( '--boardIP', help='Board IP. Default: Localhost 127.0.0.1', default="127.0.0.1") arg_parser.add_argument('-s', '--service', help='Service to test. Default: 17', default=17) + arg_parser.add_argument( + '-l','--listener', help='Determine whether the listener mode will be active after ' + 'performing the operation', + action='store_false') arg_parser.add_argument( '-t', '--tm_timeout', type=float, help='TM Timeout when listening to verification sequence.' ' Default: 5 seconds', default=5.0) @@ -38,7 +45,7 @@ def parse_input_arguments(): '--np', dest='print_tm', help='Supply --np to suppress print output to console.', action='store_false') arg_parser.add_argument( - '-o', '--tc_timeout_factor', type=float, help='TC Timeout Factor. Multiplied with ' + '--tc_timeout_factor', type=float, help='TC Timeout Factor. Multiplied with ' 'TM Timeout, TC sent again after this time period. Default: 3.5', default=3.5) arg_parser.add_argument( '-r', '--rawDataPrint', help='Supply -r to print all raw TM data directly', diff --git a/utility/obsw_binary_uploader.py b/utility/obsw_binary_uploader.py index 5c9cc8bef3b166d2bb1979a55634df00c6aa990b..60c3de66a08d7a357d2ae58b547c3c0d61c3d09b 100644 --- a/utility/obsw_binary_uploader.py +++ b/utility/obsw_binary_uploader.py @@ -6,34 +6,241 @@ This module will be used to upload binaries to the OBC via a communication port, a supplied binary. The binary will be sent via the specified communication interface. It will be possible to encode the data (for example using DLE encoding) """ +import os +import time import tkinter as tk from tkinter import filedialog +from collections import deque +from glob import glob +from typing import Deque +from tmtc_core.comIF.obsw_com_interface import CommunicationInterface +from utility.obsw_file_transfer_helper import FileTransferHelper import config.obsw_config as g +from tmtc_core.utility.obsw_tmtc_printer import TmTcPrinter, DisplayMode +from tmtc_core.utility.obsw_logger import get_logger +from tmtc_core.sendreceive.obsw_tm_listener import TmListener +LOGGER = get_logger() -def perform_binary_upload(): - print("Please select file to upload") - root = tk.Tk() - root.withdraw() - root.wm_attributes('-topmost', 1) - file_path = filedialog.askopenfilename(parent=root) - print("File select: " + str(file_path)) - calc_hamming_code = input("Calculate and send hamming code? [y/n]") - if calc_hamming_code in ['y', 'yes', 1]: - calc_hamming_code = True - print("Hamming code will be calculated and sent in tail packet") - else: - calc_hamming_code = False - print("Hamming code will not be calculated") - # Right now, the size of PUS packets is limited to 1024 bytes. Therefore, we split up the - # binary in 1000 byte packets - frame_length = g.G_MAX_BINARY_FRAME_LENGTH +class BinaryFileUploader: + def __init__(self, com_if: CommunicationInterface, tmtc_printer: TmTcPrinter, + tm_listener: TmListener): + """ + Initializes the binary file uploader with the required components. + @param com_if: + @param tmtc_printer: + @param tm_listener: + """ + self.com_if = com_if + self.tmtc_printer = tmtc_printer + self.tm_listener = tm_listener + self.iobc = False + self.send_interval = 1.0 - if calc_hamming_code: - # now we calculate the hamming code - pass + def perform_file_upload(self): + gui_cl_prompt = input("GUI(0) or command line version (1)? [0/1]: ") + if gui_cl_prompt == 0: + gui_cl_prompt = True + else: + gui_cl_prompt = False + print("Please select file to upload: ") + file_path = "" + if gui_cl_prompt: + root = tk.Tk() + root.withdraw() + root.wm_attributes('-topmost', 1) + file_path = filedialog.askopenfilename(parent=root) + print("File select: " + str(file_path)) + if file_path == (): + LOGGER.warning("Invalid file path, exiting binary upload mode.") + return + else: + result = [y for x in os.walk("../_bin") for y in glob(os.path.join(x[0], '*.bin'))] + print("Files found in _bin folder: ") + for idx, path in enumerate(result): + print("Selection " + str(idx) + ": " + str(path)) + select_valid = False + selection = input("Please enter desired selection [c to cancel]: ") + while not select_valid: + if selection == 'c': + print("Exiting binary upload mode..") + return + if not selection.isdigit(): + selection = input("Invalid input, try again [c to cancel]: ") + if selection.isdigit(): + if int(selection) < len(result): + file_path = result[int(selection)] + select_valid = True + else: + selection = input("Invalid input, try again [c to cancel]: ") - # We have to split the binary here first + print_string = file_path.rsplit(os.path.sep, 1)[-1] + " was selected." + LOGGER.info(print_string) + calc_hamming_code = input("Calculate and send hamming code? [y/n]: ") + if calc_hamming_code in ['y', 'yes', 1]: + calc_hamming_code = True + print("Hamming code will be calculated and sent in tail packet") + else: + calc_hamming_code = False + print("Hamming code will not be calculated") + iobc_prompt = input("iOBC? [y/n]: ") + if iobc_prompt in ['y', 'yes', 1]: + self.iobc = True + self.send_interval = 0.8 + iobc_prompt = True + else: + self.iobc = False + self.send_interval = 0.6 + iobc_prompt = False + + bootloader_prompt = input("Bootloader (0) or Software Image (1)? [0/1]: ") + if str(bootloader_prompt) == "0": + bootloader_prompt = True + else: + bootloader_prompt = False + + prompt_lock = input("Lock file with last packet? [y/n]: ") + if prompt_lock in ['n', "no", 0]: + prompt_lock = False + else: + prompt_lock = True + + if bootloader_prompt: + file_name = "bl.bin" + else: + file_name = "obsw_up.bin" + + if iobc_prompt: + if bootloader_prompt: + repository_name = "BIN/IOBC/BL" + else: + repository_name = "BIN/IOBC/OBSW" + else: + if bootloader_prompt: + repository_name = "BIN/AT91/BL" + else: + repository_name = "BIN/AT91/OBSW" + + if calc_hamming_code: + pass + + # Right now, the size of PUS packets is limited to 1500 bytes which also limits the app + # data length. + frame_length = g.G_MAX_APP_DATA_LENGTH + + if calc_hamming_code: + # now we calculate the hamming code + pass + + tc_queue = deque() + + # Delete existing binary file first, otherwise data might be appended to otherwise + # valid file which already exists. + file_transfer_helper = FileTransferHelper( + tc_queue=tc_queue, max_size_of_app_data=frame_length, target_repository=repository_name, + target_filename=file_name) + + init_ssc = 0 + self.tmtc_printer.set_display_mode(DisplayMode.SHORT) + + # Configure file transfer helper + file_transfer_helper.set_data_from_file(file_path) + file_transfer_helper.set_to_delete_old_file() + if prompt_lock: + file_transfer_helper.set_to_lock_file(prompt_lock) + else: + file_transfer_helper.set_to_lock_file(prompt_lock) + + # Generate the packets. + file_transfer_helper.generate_packets(init_ssc) + + self.tm_listener.set_listener_mode(TmListener.ListenerModes.MANUAL) + print_string = "BinaryUploader: Detected file size: " + str( + file_transfer_helper.file_size()) + LOGGER.info(print_string) + total_num_packets = file_transfer_helper.get_number_of_packets_generated() + print_string = "BinaryUploader: " + str(total_num_packets) + \ + " packets generated." + if prompt_lock: + print_string += " File will be locked." + else: + print_string += " File will not be locked." + LOGGER.info(print_string) + + reception_deque = deque() + self.__perform_send_algorithm(tc_queue, total_num_packets, reception_deque) + + print_string = "BinaryUploader: All binary packets were sent!" + LOGGER.info(print_string) + print_string = str(reception_deque.__len__()) + " replies received." + + LOGGER.info(print_string) + time.sleep(15) + reception_deque.extend(self.tm_listener.retrieve_tm_packet_queue()) + for tm_list in reception_deque: + for tm_packet in tm_list: + if tm_packet.get_service() == 23 and tm_packet.get_subservice() == 132: + # tmtc_printer.print_telemetry(tm_packet) + pass + self.tm_listener.clear_tm_packet_queue() + LOGGER.info("Transitioning back to listener mode..") + + def __perform_send_algorithm(self, tc_queue: Deque, number_of_packets: int, reception_deque: + Deque): + last_check = time.time() + last_sent = time.time() + total_time = self.send_interval * number_of_packets + idx = 1 + while tc_queue: + next_send = last_sent + self.send_interval + (tc_packet, tc_info) = tc_queue.pop() + if not isinstance(tc_packet, str): + # print_string = "Sending packet " + str(idx) + ".." + # LOGGER.info(print_string) + idx += 1 + self.com_if.send_telecommand(tc_packet, tc_info) + self.tmtc_printer.print_telecommand(tc_packet, tc_info) + elif tc_packet == "print": + LOGGER.info(tc_info) + remaining_time_string = "Remaining time: " + \ + str(round(total_time - (idx - 2) * self.send_interval, 2)) + \ + " seconds" + print_progress_bar(idx - 2, number_of_packets, print_end="\n", + suffix=remaining_time_string) + # sys.stdout.write("\033[F") # Cursor up one line + packets_received = self.tm_listener.retrieve_tm_packet_queue() + reception_deque.extend(packets_received) + # Every 5 seconds, check whether any reply has been received. If not, cancel operation. + if time.time() - last_check > 5.0 and len(packets_received) == 0: + LOGGER.warning("No replies are being received, cancelling upload operation..") + time_to_sleep = next_send - time.time() + last_sent = next_send + time.sleep(time_to_sleep) + + +# https://stackoverflow.com/questions/3173320/text-progress-bar-in-the-console +# Thank you Greensticks :-) +def print_progress_bar(iteration, total, prefix='', suffix='', decimals=1, length=100, + fill='â–ˆ', print_end="\r"): + """ + Call in a loop to create terminal progress bar + @params: + iteration - Required : current iteration (Int) + total - Required : total iterations (Int) + prefix - Optional : prefix string (Str) + suffix - Optional : suffix string (Str) + decimals - Optional : positive number of decimals in percent complete (Int) + length - Optional : character length of bar (Int) + fill - Optional : bar fill character (Str) + print_end - Optional : end character (e.g. "\r", "\r\n") (Str) + """ + percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total))) + filled_length = int(length * iteration // total) + bar = fill * filled_length + '-' * (length - filled_length) + print(f'\r{prefix} |{bar}| {percent}% {suffix}', end=print_end) + # Print New Line on Complete + if iteration == total: + print() diff --git a/utility/obsw_file_transfer_helper.py b/utility/obsw_file_transfer_helper.py new file mode 100644 index 0000000000000000000000000000000000000000..c6efb90e7e15cf98b494e9c895f9137b88107c6f --- /dev/null +++ b/utility/obsw_file_transfer_helper.py @@ -0,0 +1,241 @@ +from enum import Enum +import math + +from config.obsw_config import SD_CARD_HANDLER_ID +from tmtc_core.tc.obsw_pus_tc_base import TcQueueT, PusTelecommand +from tc.obsw_tc_service23_sdcard import \ + calculate_allowed_file_data_size, generate_rm_file_srv23_2_packet, \ + generate_create_file_srv23_1_packet, generate_finish_append_to_file_srv23_131_packet, \ + generate_lock_file_srv23_5_6_packet + + +class FileTransferHelper: + """ + This helper class fills the provided TC queue with appropriate PUS telecommands + to transfer a file. + There are three modes which determine which telecommands will be generated: + 1. NORMAL: Generate telecommand to create a new file and append data packets if + the file data is too large. This will be the default mode. + 2. DELETE_OLD: Generate telecommand to delete old file and then perform same steps as the + normal mode + 3. RENAME_OLD: Rename old file and then perform same steps as in normal mode. + + Please note that the setter functions set_data have to be used to assign data, otherwise + an empty file will be created. The mode is set with setter commands as well. + """ + class TransferMode(Enum): + # Normal mode + NORMAL = 1 + # Generate a command to delete the old file first + DELETE_OLD = 2 + # Generate a command to rename the old file first. + RENAME_OLD = 3 + + def __init__(self, tc_queue: TcQueueT, max_size_of_app_data: int, + target_repository: str, target_filename: str, + object_id=SD_CARD_HANDLER_ID): + """ + @param tc_queue: TC queue which will be filled + @param max_size_of_app_data: Maximum allowed app data size. Number of generated packets + will depend on this value + @param target_repository: Repository path on target. + @param target_filename: Filename on target + @param object_id: + """ + self.object_id = object_id + self.max_size_of_app_data = max_size_of_app_data + self.allowed_file_data_size = calculate_allowed_file_data_size( + max_size_of_app_data, target_filename, target_repository) + + self.target_filename = target_filename + self.target_repository = target_repository + + self.tc_queue = tc_queue + + self.__transfer_mode = self.TransferMode.NORMAL + self.__max_file_data_size = 0 + self.__renamed_name = self.target_filename + "old" + + self.__large_file = False + self.__number_of_packets = 0 + self.__number_of_append_packets = 0 + self.__number_of_create_packets = 1 + self.__number_of_delete_packets = 0 + self.__number_of_finish_packets = 1 + + self.__current_ssc = 0 + self.__lock_file = True + self.__local_filename = "" + self.__file_data = bytearray() + # This will generate a telecommand to delete the old file, if it exists + self.delete_old_file = False + # This will generater a telecommand to rename the old file, if it exists + self.rename_old_file = False + + def set_data_from_file(self, local_filename: str): + with open(local_filename, 'rb') as file: + self.__file_data = file.read() + + def set_data_raw(self, tc_data: bytearray): + self.__file_data = tc_data + + def set_to_delete_old_file(self): + self.__transfer_mode = self.TransferMode.DELETE_OLD + + def set_to_rename_old_file(self, renamed_name: str): + self.__transfer_mode = self.TransferMode.RENAME_OLD + self.__renamed_name = renamed_name + + def set_to_lock_file(self, lock_file: bool): + """ + Command will be sent to lock file after succesfull transfer + @param lock_file: + @return: + """ + self.__lock_file = lock_file + + def get_number_of_packets_generated(self): + return self.__number_of_packets + + def set_max_file_data_size(self, max_file_data_size: int): + """ + If this value is specified and the source file is large (larger than the maximum allowed + app data!), the file data size will be set to this value. + @param max_file_data_size: + @return: + """ + self.__max_file_data_size = max_file_data_size + + def file_size(self): + return len(self.__file_data) + + def generate_packets(self, ssc: int): + """ + Main function to generate all packets and fill them into the provided deque. + @param ssc: + @return: + """ + self.__current_ssc = ssc + self.__handle_delete_packet_generation() + if self.__transfer_mode == self.TransferMode.RENAME_OLD: + # not implemented yet + pass + self.__handle_create_file_packet_generation() + self.__handle_finish_and_lock_packet_generation() + self.__number_of_packets = \ + self.__number_of_create_packets + self.__number_of_append_packets + \ + self.__number_of_delete_packets + self.__number_of_finish_packets + + def __handle_delete_packet_generation(self): + if self.__transfer_mode == self.TransferMode.DELETE_OLD: + command = generate_rm_file_srv23_2_packet( + filename=self.target_filename, repository_path=self.target_repository, + ssc=self.__current_ssc, object_id=self.object_id) + self.__number_of_delete_packets = 1 + self.__current_ssc += 1 + self.tc_queue.appendleft(command.pack_command_tuple()) + + def __handle_create_file_packet_generation(self): + if len(self.__file_data) > self.allowed_file_data_size: + # Large file, create file with init_data + if self.__max_file_data_size > 0: + init_data = self.__file_data[0:self.__max_file_data_size] + else: + init_data = self.__file_data[0:self.allowed_file_data_size] + self.__large_file = True + else: + init_data = self.__file_data + + # Create file. + command = generate_create_file_srv23_1_packet( + self.target_filename, self.target_repository, ssc=self.__current_ssc, + max_size_of_app_data=self.max_size_of_app_data, initial_data=init_data) + self.__current_ssc += 1 + self.tc_queue.appendleft(command.pack_command_tuple()) + if not self.__large_file: + return + rest_of_data = self.__file_data[self.allowed_file_data_size:] + # Generate the rest of the packets to write to large file + if self.__max_file_data_size > 0: + self.__generate_append_to_file_packets_automatically( + data=rest_of_data, target_repository=self.target_repository, + target_filename=self.target_filename, size_of_data_blocks=self.__max_file_data_size, + init_ssc=self.__current_ssc) + else: + self.__generate_append_to_file_packets_automatically( + data=rest_of_data, target_repository=self.target_repository, + target_filename=self.target_filename, size_of_data_blocks=self.max_size_of_app_data, + init_ssc=self.__current_ssc) + self.__current_ssc += 1 + + def __generate_append_to_file_packets_automatically( + self, data: bytearray, target_repository: str, target_filename: str, + size_of_data_blocks: int, init_ssc: int): + """ + This function generates PUS packets which is used to write data in a file. + A new file will be created if not already existing. If the file already exists, this might + lead to + + If the file data is larger than the maximum allowed size of application data, this function + will split the data into multiple packets and increment the initial SSC number by one for + each packet. + @param data: Data which will be split up. + @param init_ssc: First SSC, which will be incremented for each packet. + """ + header = bytearray(self.object_id) + header += target_repository.encode('utf-8') + # Add string terminator of repository path + header.append(0) + header += target_filename.encode('utf-8') + # Add string terminator of filename + header.append(0) + self.__split_large_file(header, size_of_data_blocks, data, init_ssc) + + def __split_large_file(self, header: bytearray, size_of_data_blocks: int, + data: bytearray, init_ssc: int): + """ + This function splits a large file in multiple packets and packs the generated packets + into the member deque. This is necessary because the packet size is limited. + @param header: Repository and file name which will always stay the same + @param size_of_data_blocks: The file data blocks will have this size + @param data: The data to pack in multiple packets + @param init_ssc: The ssc of the first command, will be incremented by one for each packet. + """ + number_of_packets = math.floor(len(data) / size_of_data_blocks) + packet_sequence_number = 0 + + for i in range(number_of_packets): + header.append(packet_sequence_number >> 8) + header.append(0xFF & packet_sequence_number) + header += data[i * size_of_data_blocks:(i + 1) * size_of_data_blocks] + + commands = PusTelecommand(service=23, subservice=130, ssc=init_ssc + i, + app_data=header) + self.tc_queue.appendleft(commands.pack_command_tuple()) + + # Remove everything except the header + header = header[:len(header) - size_of_data_blocks - 2] + packet_sequence_number = packet_sequence_number + 1 + # Last packet will be subservice 131 to finish the append operation + header.append(packet_sequence_number >> 8) + header.append(0xFF & packet_sequence_number) + self.__number_of_append_packets += number_of_packets + header += data[number_of_packets * size_of_data_blocks:len(data)] + commands = PusTelecommand(service=23, subservice=130, ssc=init_ssc + packet_sequence_number, + app_data=header) + self.tc_queue.appendleft(commands.pack_command_tuple()) + + def __handle_finish_and_lock_packet_generation(self): + if self.__large_file: + last_command = generate_finish_append_to_file_srv23_131_packet( + filename=self.target_filename, repository_path=self.target_repository, + ssc=self.__current_ssc, lock_file=self.__lock_file) + else: + if self.__lock_file: + last_command = generate_lock_file_srv23_5_6_packet( + filename=self.target_filename, repository_path=self.target_repository, + object_id=self.object_id, lock=True, ssc=self.__current_ssc) + else: + self.__number_of_finish_packets = 0 + return + self.tc_queue.appendleft(last_command.pack_command_tuple()) \ No newline at end of file