diff --git a/.idea/runConfigurations/tmtcclient_Software_Serial.xml b/.idea/runConfigurations/tmtcclient_Binary_Upload_Serial.xml similarity index 77% rename from .idea/runConfigurations/tmtcclient_Software_Serial.xml rename to .idea/runConfigurations/tmtcclient_Binary_Upload_Serial.xml index 0dfd7b192a6af6da43bb59f26b4b1c33c7030405..0f71641f824fd4d2ef324b83f038e96cf4a6d467 100644 --- a/.idea/runConfigurations/tmtcclient_Software_Serial.xml +++ b/.idea/runConfigurations/tmtcclient_Binary_Upload_Serial.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 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" /> @@ -13,9 +13,9 @@ <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="PARAMETERS" value="-m 5 -c 1" /> <option name="SHOW_COMMAND_LINE" value="false" /> - <option name="EMULATE_TERMINAL" 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="" /> diff --git a/.idea/runConfigurations/tmtcclient_Clear_SD_Card_.xml b/.idea/runConfigurations/tmtcclient_Clear_SD_Card_.xml new file mode 100644 index 0000000000000000000000000000000000000000..0625478e1096c8e4741c5a679e7f1a5106657c74 --- /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$/obsw_tmtc_client.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..d91be384b7b6603e6fbb013d2d72767e64c340c3 --- /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$/obsw_tmtc_client.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..df307b80bceb31890f70e8a330843cce7d4412be --- /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$/obsw_tmtc_client.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..cc27520bd0fab79801e5e6cb318253da46476c3c --- /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$/obsw_tmtc_client.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..b6645926453ca505e2732cd9a09225e1f7b733cc --- /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$/obsw_tmtc_client.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_Enable_Periodic_Print.xml b/.idea/runConfigurations/tmtcclient_Enable_Periodic_Print.xml new file mode 100644 index 0000000000000000000000000000000000000000..b7394cbce13ae7c4f410959e820edcf2c31248c5 --- /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$/obsw_tmtc_client.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..050cb977f81f9aebbc5e2509619b6e5bf3a54821 --- /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$/obsw_tmtc_client.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..7aa42a29328053467a3364d0c8fd1e5623643b94 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" /> diff --git a/.idea/runConfigurations/tmtcclient_GPS1_Serial.xml b/.idea/runConfigurations/tmtcclient_GPS1_Serial.xml index 1f8098a72d1b52a387c0256e35fa3cebdb4ccfae..2e914ff6b1e6f74ba631fb5d3a019074c29bfe49 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" /> diff --git a/.idea/runConfigurations/tmtcclient_Listener_Serial.xml b/.idea/runConfigurations/tmtcclient_Listener_Serial.xml index c59efdb836593429d3c211d1ed21f814c1a13177..8655adedcf593f6bc9146582d876f95a7b5a29f6 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" /> diff --git a/.idea/runConfigurations/tmtcclient_Lock_file.xml b/.idea/runConfigurations/tmtcclient_Lock_file.xml new file mode 100644 index 0000000000000000000000000000000000000000..dc7e019138759e7d48e4bbaa6bcf32dc3dd89849 --- /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$/obsw_tmtc_client.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..317ef3ef1694004f58e6eca515834aa7bc1f6525 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" /> diff --git a/.idea/runConfigurations/tmtcclient_PowerCycle_OBC_.xml b/.idea/runConfigurations/tmtcclient_PowerCycle_OBC_.xml new file mode 100644 index 0000000000000000000000000000000000000000..b443130565f1120cc74f261a940059def5685f68 --- /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$/obsw_tmtc_client.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..5c359f03920f2de984dfbd0496d6ca80534ebfb2 --- /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$/obsw_tmtc_client.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..3e529385b41396062e99870991fcde125cffd9be --- /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$/obsw_tmtc_client.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..8e3e5851b3f02f90adb088bc83c11d659719c433 --- /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$/obsw_tmtc_client.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_Serial.xml b/.idea/runConfigurations/tmtcclient_Service_17_Serial.xml index 5145e3b7acd8d267540c2cc4214eb61b7c4c8f67..9abd7b47887bd512e9ab8324697489c8d241f991 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" /> diff --git a/.idea/runConfigurations/tmtcclient_Service_2_Serial.xml b/.idea/runConfigurations/tmtcclient_Service_2_Serial.xml index 38316e0359a813bff39ae6574bb14beb0430e97e..1ffb46d6a63706b548933833b4bd1e4575723b3e 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" /> diff --git a/.idea/runConfigurations/tmtcclient_Service_3_Serial_.xml b/.idea/runConfigurations/tmtcclient_Service_3_Serial_.xml index 7b0db83d4daea21024c7ef99394582f529ca1486..92741a34eaf48f82d59302d0c44c0b4d8e918556 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" /> diff --git a/.idea/runConfigurations/tmtcclient_Service_5_Serial.xml b/.idea/runConfigurations/tmtcclient_Service_5_Serial.xml index aadf325a5002b612eaf8c56d8652bb56d02a7288..58a794a73e1b785409f4b477af84e3355a96967c 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" /> diff --git a/.idea/runConfigurations/tmtcclient_Service_8_Serial.xml b/.idea/runConfigurations/tmtcclient_Service_8_Serial.xml index 1c96bce8f9e66fec8a1b6be5948348f2928904c7..7d9695d2c9c2e0c3ea98b767c37b8cf11948c2df 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" /> diff --git a/.idea/runConfigurations/tmtcclient_Service_9_Serial.xml b/.idea/runConfigurations/tmtcclient_Service_9_Serial.xml index f755f02c30089f9d2bc2a6efb46f47f65ac9e3a7..781448c3ff0319a1b8f5c887741b7b837010a29d 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" /> diff --git a/.idea/runConfigurations/tmtcclient_Single_Command_Serial_.xml b/.idea/runConfigurations/tmtcclient_Single_Command_Serial.xml similarity index 87% rename from .idea/runConfigurations/tmtcclient_Single_Command_Serial_.xml rename to .idea/runConfigurations/tmtcclient_Single_Command_Serial.xml index c59814017c5419b0cfa0d262228897e93ae23e4f..aa1a2f4b2ae631f47148b51f094fe3d17986b6e4 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" /> @@ -13,7 +13,7 @@ <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="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_Trigger_Exceptions.xml b/.idea/runConfigurations/tmtcclient_Trigger_Exceptions.xml new file mode 100644 index 0000000000000000000000000000000000000000..d8483e91e0c5ee927bf310001149083e5b92467e --- /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$/obsw_tmtc_client.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_Unlock_File.xml b/.idea/runConfigurations/tmtcclient_Unlock_File.xml new file mode 100644 index 0000000000000000000000000000000000000000..d484de6c0b86bb59356bcc78423c8267138bebed --- /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$/obsw_tmtc_client.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..8613b8d723259f83a52b98fc2a01f8fe8253d24c 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" /> diff --git a/config/obsw_com_config.py b/config/obsw_com_config.py index 66e5da5837784e1577612a39e0f19a1f4a01843a..a425ea64333295e7ff5af1a36c8999fdb6800384 100644 --- a/config/obsw_com_config.py +++ b/config/obsw_com_config.py @@ -40,9 +40,7 @@ def set_communication_interface(tmtc_printer: TmTcPrinter) -> Union[Communicatio 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: - serial_timeout = g.G_SERIAL_TIMEOUT - communication_interface = QEMUComIF( - tmtc_printer=tmtc_printer, serial_timeout=serial_timeout) + communication_interface = QEMUComIF(tmtc_printer=tmtc_printer, serial_timeout=g.G_TM_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 7adbb6d2d0c9375c2fea57b8709141e91be630cc..30dbd15fd492fcdb6d0caac7b3fb3b5ca6c1d5ed 100644 --- a/config/obsw_config.py +++ b/config/obsw_config.py @@ -11,7 +11,6 @@ import struct import pprint import logging from socket import INADDR_ANY - from config.obsw_definitions import ModeList, ComIF """ @@ -21,6 +20,9 @@ Mission/Device specific information. # TODO: Automate / Autofill this file with the MIB parser # Object IDs +CORE_CONTROLLER_ID = bytearray([0x40, 0x00, 0x10, 0x00]) +SW_IMAGE_HANDLER_ID = bytearray([0x4D, 0x00, 0x90, 0x00]) +PUS_SERVICE_17 = bytearray([0x53, 0x00, 0x00, 0x17]) GPS0_DEVICE_ID = bytearray([0x44, 0x10, 0x1F, 0x00]) GPS1_DEVICE_ID = bytearray([0x44, 0x20, 0x20, 0x00]) DUMMY_DEVICE_ID = bytearray([0x44, 0x00, 0xAF, 0xFE]) @@ -62,6 +64,7 @@ LOGGER = logging.getLogger(G_TMTC_LOGGER_NAME) G_SCRIPT_MODE = 1 G_MODE_ID = 0 G_SERVICE = 17 +G_OP_CODE = 0 G_DISPLAY_MODE = "long" # General TMTC Settings @@ -69,6 +72,7 @@ G_APID = 0x73 # Binary Upload Settings G_MAX_BINARY_FRAME_LENGTH = 1500 +G_MAX_APP_DATA_LENGTH = G_MAX_BINARY_FRAME_LENGTH - 100 G_COM_IF = 2 # COM Port for serial communication @@ -111,9 +115,11 @@ 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 + 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 + if args.shortDisplayMode: G_DISPLAY_MODE = "short" else: @@ -149,6 +155,13 @@ def set_globals(args): 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 @@ -157,6 +170,7 @@ 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 global_setup_hook() diff --git a/gui/obsw_backend_test.py b/gui/obsw_backend_test.py new file mode 100644 index 0000000000000000000000000000000000000000..d9e6c488a10a2a9c5050d4dd33f328f01d548abb --- /dev/null +++ b/gui/obsw_backend_test.py @@ -0,0 +1,37 @@ +from multiprocessing.connection import Listener +from multiprocessing import Process +from tmtc_core.utility.obsw_logger import get_logger +import logging + + +LOGGER = get_logger() + + +class TmTcBackend(Process): + def __init__(self): + from obsw_tmtc_client import TmTcHandler + super(TmTcBackend, self).__init__() + self.address = ('localhost', 6000) # family is deduced to be 'AF_INET' + self.tmtc_backend = TmTcHandler() + self.listener = Listener(self.address, authkey=None) + self.conn = 0 + + def run(self): + self.listen() + + def listen(self): + self.conn = self.listener.accept() + LOGGER.info("TmTcBackend: Connection accepted from %s", str(self.listener.last_accepted)) + while True: + msg = self.conn.recv() + # do something with msg + # here, the core client could be called to perform operations based on received message + if msg == 'test': + LOGGER.info("TmTcBackend: Hallo Welt !") + elif msg == 'close': + try: + self.conn.close() + break + except OSError: + logging.exception("Error: ") + self.listener.close() diff --git a/gui/obsw_tmtc_gui.py b/gui/obsw_tmtc_gui.py index ba7985fc3334f6542fb8189b500634622214dfb0..ae29984ce4108a75a6bad1437319a08cf624390b 100644 --- a/gui/obsw_tmtc_gui.py +++ b/gui/obsw_tmtc_gui.py @@ -22,6 +22,7 @@ import threading 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) diff --git a/obsw_tmtc_client.py b/obsw_tmtc_client.py index dbeb01f8a83d69673fcd341a69df26f2d316d954..379a3cd280c22d56aac8e8177ec7bfa92525d4ba 100755 --- a/obsw_tmtc_client.py +++ b/obsw_tmtc_client.py @@ -48,7 +48,7 @@ from tmtc_core.utility.obsw_logger import set_tmtc_logger, get_logger 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 utility.obsw_binary_uploader import perform_file_upload from obsw_user_code import command_preparation_hook import gui.obsw_tmtc_gui @@ -151,11 +151,11 @@ 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.tm_listener.clear_reply_event() self.command_received = True elif self.mode == g.ModeList.SingleCommandMode: @@ -176,7 +176,9 @@ class TmTcHandler: 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") @@ -200,7 +202,7 @@ 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() + perform_file_upload(self.communication_interface, self.tmtc_printer, self.tm_listener) self.command_received = True self.mode = g.ModeList.ListenerMode diff --git a/requirements.txt b/requirements.txt index 4a3f79dd0651dd1e85c8e72f74264a7f5a6cecde..4ac62a18eeebe75e7db2b6cc16666ea926ccad88 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,7 @@ aiohttp==3.6.2 astroid==2.4.2 async-timeout==3.0.1 -attrs==19.3.0 +attrs==20.2.0 chardet==3.0.4 colorama==0.4.3 cpplint==1.5.4 @@ -9,18 +9,18 @@ crcmod>=1.7 docopt==0.6.2 future==0.18.2 idna==2.10 -iso8601==0.1.12 -isort==5.4.2 +iso8601==0.1.13 +isort==5.6.3 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 +pylint>=2.6.0 +PyQt5>=5.15.1 +PyQt5-sip>=12.8.1 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 +typing-extensions==3.7.4.3 +wrapt==1.12.1 +yarl==1.6.0 diff --git a/tc/obsw_image_handler.py b/tc/obsw_image_handler.py new file mode 100644 index 0000000000000000000000000000000000000000..5f96ad68b051046aea733aa89bb2321f9c792f3d --- /dev/null +++ b/tc/obsw_image_handler.py @@ -0,0 +1,37 @@ +from tmtc_core.tc.obsw_pus_tc_base import PusTelecommand, Deque +from tc.obsw_tc_service8 import make_action_id +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_img_handler_packet(service_queue: Deque, op_code: int): + # 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()) 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..52152688dad6933afa6fa76d717a9be147d9f736 100644 --- a/tc/obsw_pus_tc_packer.py +++ b/tc/obsw_pus_tc_packer.py @@ -14,11 +14,13 @@ 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_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 +34,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 +47,28 @@ 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() == "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 !") 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..24ce024e069c49f1b22d4b9c8dfb86ab6bbfa12e 100644 --- a/tc/obsw_tc_service20.py +++ b/tc/obsw_tc_service20.py @@ -14,7 +14,7 @@ from tc.obsw_tc_service200 import pack_mode_data def pack_service20_test_into(tc_queue: Deque, called_externally: bool = False) -> Deque: - #parameter IDs + # parameter IDs parameterID0 = 0 parameterID1 = 1 parameterID2 = 2 @@ -29,33 +29,33 @@ 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 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 tc_queue.appendleft(("print", "Testing Service 20: Load uint32_t")) parameter_id = struct.pack(">I", parameterID0) parameter_data = struct.pack(">I", 42) @@ -63,7 +63,7 @@ def pack_service20_test_into(tc_queue: Deque, called_externally: bool = False) - command = PusTelecommand(service=20, subservice=128, ssc=2001, 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 @@ -101,9 +101,6 @@ def pack_service20_test_into(tc_queue: Deque, called_externally: bool = False) - tc_queue.appendleft(command.pack_command_tuple()) """ - - - """ # set mode on tc_queue.appendleft(("print", "Testing Service 8: Set On Mode")) 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..ccd07d808c1b253838c2d5e3e4b9322b88c0fdbf --- /dev/null +++ b/tc/obsw_tc_service23_sdcard.py @@ -0,0 +1,584 @@ +# -*- coding: utf-8 -*- +""" +Created: 21.01.2020 07:48 + +@author: Jakob Meier +""" +import math +from enum import Enum + +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() + + +class FileTransferHelper: + """ + This helper class fills the provided TC queue with appropriate PUS telecommands + to transfer a large 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=g.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.__transfer_mode = self.TransferMode.NORMAL + self.max_size_of_app_data = max_size_of_app_data + self.__max_file_data_size = 0 + 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.__renamed_name = self.target_filename + "old" + self.object_id = object_id + self.tc_queue = tc_queue + + 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.__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): + 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): + if self.__transfer_mode == self.TransferMode.DELETE_OLD: + command = generate_rm_file_srv23_2_packet(self.target_filename, self.target_repository, + ssc, self.object_id) + self.__number_of_delete_packets = 1 + ssc += 1 + self.tc_queue.appendleft(command.pack_command_tuple()) + elif self.__transfer_mode == self.TransferMode.RENAME_OLD: + # not implemented yet + pass + 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] + else: + # Small file, one packet for file creation sufficient + command = generate_create_file_srv23_1_packet( + self.target_filename, self.target_repository, ssc, self.max_size_of_app_data, + self.__file_data) + ssc += 1 + self.tc_queue.appendleft(command.pack_command_tuple()) + return + + # Create large file. + command = generate_create_file_srv23_1_packet( + self.target_filename, self.target_repository, ssc, self.max_size_of_app_data, + init_data) + ssc += 1 + self.tc_queue.appendleft(command.pack_command_tuple()) + 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=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=ssc) + ssc += 1 + last_command = generate_finish_append_to_file_srv23_131_packet( + filename=self.target_filename, repository_path=self.target_repository, + ssc=ssc, lock_file=self.__lock_file) + self.tc_queue.appendleft(last_command.pack_command_tuple()) + self.__number_of_packets = \ + self.__number_of_append_packets + self.__number_of_create_packets + \ + self.__number_of_delete_packets + 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 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..9166214399eed0fa485d9d471cf1d6ee358da9bb 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,7 @@ 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 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/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/tm/obsw_pus_tm_factory_hook.py b/tm/obsw_pus_tm_factory_hook.py index 94899de4acb68c275049ca88e28cd29c6be22a96..6effae10a4852b37511e9a0d243dc7351e9e5dcf 100644 --- a/tm/obsw_pus_tm_factory_hook.py +++ b/tm/obsw_pus_tm_factory_hook.py @@ -3,6 +3,7 @@ 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 +from tm.obsw_tm_service_23 import Service23TM import struct LOGGER = get_logger() @@ -24,6 +25,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") @@ -141,4 +144,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_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/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..d226d02405b4af3d6c655357e3467b7c63683d8c 100644 --- a/utility/obsw_args_parser.py +++ b/utility/obsw_args_parser.py @@ -18,12 +18,15 @@ 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") @@ -38,7 +41,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..7f27a9e3f6255ef4cac7671785d2af0ee00f9e31 100644 --- a/utility/obsw_binary_uploader.py +++ b/utility/obsw_binary_uploader.py @@ -6,20 +6,67 @@ 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 tmtc_core.comIF.obsw_com_interface import CommunicationInterface +from tc.obsw_tc_service23_sdcard 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 +from tmtc_core.tm.obsw_pus_tm_factory import PusTmQueueT +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]") + +def perform_file_upload(com_if: CommunicationInterface, tmtc_printer: TmTcPrinter, + tm_listener: TmListener): + 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 + # TODO: prompt whether this is a binary upload or a normal file upload. Or use op code + # two different commands to achieve the same. + 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]: ") + + 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") @@ -27,13 +74,143 @@ def perform_binary_upload(): 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 + iobc_prompt = input("iOBC? [y/n]: ") + if iobc_prompt in ['y', 'yes', 1]: + iobc_prompt = True + else: + 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" + + # 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 - # We have to split the binary here first + 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 + 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) + + 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) + interval = 0.6 + last_sent = time.time() + total_time = interval * total_num_packets + idx = 1 + reception_deque: PusTmQueueT = deque() + while tc_queue: + next_send = last_sent + 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 + com_if.send_telecommand(tc_packet, tc_info) + 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) * interval, 2)) + \ + " seconds" + print_progress_bar(idx - 2, total_num_packets, print_end="\n", suffix=remaining_time_string) + # sys.stdout.write("\033[F") # Cursor up one line + reception_deque.extend(tm_listener.retrieve_tm_packet_queue()) + time_to_sleep = next_send - time.time() + last_sent = next_send + time.sleep(time_to_sleep) + + 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(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 + tm_listener.clear_tm_packet_queue() + LOGGER.info("Transitioning back to listener mode..") + +# 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()