diff --git a/config/OBSW_Config.py b/config/OBSW_Config.py index 1597c0cc738dad3e18108b37e2b4fe7b00af9c3b..622fba063852befa4fa75448bf46b58c1b7e8b91 100644 --- a/config/OBSW_Config.py +++ b/config/OBSW_Config.py @@ -70,7 +70,7 @@ recAddress = 0 sendAddress = (0, 0) # Print Settings -printToFile = False +G_PRINT_TO_FILE = False G_PRINT_HK_DATA = False printRawTmData = False @@ -84,8 +84,9 @@ tmtcPrinter = None # noinspection PyUnusedLocal def setGlobals(args): - global recAddress, sendAddress, scriptMode, modeId, service, displayMode, comIF, comPort, serial_timeout - global tmTimeout, tcSendTimeoutFactor, printToFile, G_PRINT_HK_DATA, printRawTmData + global recAddress, sendAddress, scriptMode, modeId, service, displayMode, comIF, comPort + global serial_timeout, tmTimeout, tcSendTimeoutFactor, G_PRINT_TO_FILE + global G_PRINT_HK_DATA, printRawTmData if args.mode == 0: print("GUI mode not implemented yet !") if args.shortDisplayMode: @@ -139,4 +140,4 @@ def setGlobals(args): printRawTmData = args.rawDataPrint displayMode = displayMode service = service - printToFile = args.printFile + G_PRINT_TO_FILE = args.printFile diff --git a/obsw_tmtc_client.py b/obsw_tmtc_client.py index 6e947273375d0094183be3cbe5d13044b3db8296..b87a27fa7bae48c8e780924c3ffa4abed8a8fff4 100644 --- a/obsw_tmtc_client.py +++ b/obsw_tmtc_client.py @@ -64,7 +64,7 @@ from config import OBSW_Config as g from config.OBSW_Config import setGlobals from tc.OBSW_TcPacker import PUSTelecommand, createTotalTcQueue, serviceTestSelect -from sendreceive.OBSW_SingleCommandSenderReceiver import SingleCommandSenderReceiver +from sendreceive.obsw_single_command_sender_receiver import SingleCommandSenderReceiver from sendreceive.OBSW_SequentialSenderReceiver import SequentialCommandSenderReceiver from sendreceive.obsw_tm_listener import TmListener @@ -87,7 +87,7 @@ def main(): """ args = parseInputArguments() setGlobals(args) - tmtc_printer = TmTcPrinter(g.displayMode, g.printToFile, True) + tmtc_printer = TmTcPrinter(g.displayMode, g.G_PRINT_TO_FILE, True) if g.modeId == g.ModeList.GUIMode: backend = TmTcBackend() backend.start() @@ -111,24 +111,22 @@ def main(): sender_and_receiver = SingleCommandSenderReceiver( comInterface=communication_interface, tmtcPrinter=tmtc_printer, tmListener=tm_listener, pusPacketTuple=pus_packet_tuple, tmTimeout=g.tmTimeout, - tcTimeoutFactor=g.tcSendTimeoutFactor, doPrintToFile=g.printToFile) - sender_and_receiver.sendSingleTcAndReceiveTm() + tcTimeoutFactor=g.tcSendTimeoutFactor, doPrintToFile=g.G_PRINT_TO_FILE) + sender_and_receiver.send_single_tc_and_receive_tm() elif g.modeId == g.ModeList.ServiceTestMode: service_queue = deque() sender_and_receiver = SequentialCommandSenderReceiver( comInterface=communication_interface, tmtcPrinter=tmtc_printer, tmTimeout=g.tmTimeout, tcQueue=serviceTestSelect(g.service, service_queue), - tcTimeoutFactor=g.tcSendTimeoutFactor, doPrintToFile=g.printToFile, - tmListener=tm_listener) + tcTimeoutFactor=g.tcSendTimeoutFactor, tmListener=tm_listener) sender_and_receiver.sendQueueTcAndReceiveTmSequentially() elif g.modeId == g.ModeList.SoftwareTestMode: all_tc_queue = createTotalTcQueue() sender_and_receiver = SequentialCommandSenderReceiver( comInterface=communication_interface, tmtcPrinter=tmtc_printer, tmTimeout=g.tmTimeout, - tcQueue=all_tc_queue, tcTimeoutFactor=g.tcSendTimeoutFactor, - doPrintToFile=g.printToFile, tmListener=tm_listener) + tcQueue=all_tc_queue, tcTimeoutFactor=g.tcSendTimeoutFactor, tmListener=tm_listener) sender_and_receiver.sendQueueTcAndReceiveTmSequentially() elif g.modeId == g.ModeList.UnitTest: diff --git a/sendreceive/OBSW_CommandSenderReceiver.py b/sendreceive/OBSW_CommandSenderReceiver.py deleted file mode 100644 index aaacb4e3c4b27932be65b9474d33fc267e9edee1..0000000000000000000000000000000000000000 --- a/sendreceive/OBSW_CommandSenderReceiver.py +++ /dev/null @@ -1,126 +0,0 @@ -""" -Program: OBSW_UnitTest.py -Date: 01.11.2019 -Description: All functions related to TmTc Sending and Receiving, used by UDP client - -Manual: -Set up the UDP client as specified in the header comment and use the unit testing mode - -A separate thread is used to listen for replies and send a new telecommand -if the first reply has not been received. - -@author: R. Mueller -""" -import time -from comIF.OBSW_ComInterface import CommunicationInterface, ComIF_T -from utility.obsw_tmtc_printer import TmTcPrinterT, TmTcPrinter -from sendreceive.obsw_tm_listener import TmListenerT, TmListener - - -class CommandSenderReceiver: - """ - This is the generic CommandSenderReceiver object. All TMTC objects inherit this object, - for example specific implementations (e.g. SingleCommandSenderReceiver) - """ - def __init__(self, comInterface: ComIF_T, tmtcPrinter: TmTcPrinterT, tmListener: TmListenerT, tmTimeout: float, - tcSendTimeoutFactor: float, doPrintToFile: bool): - """ - :param comInterface: CommunicationInterface object. Instantiate the desired one and pass it here - :param tmtcPrinter: TmTcPrinter object. Instantiate it and pass it here. - :param tmTimeout: TM Timeout. After each sent telecommand, listen for TMs for this time period - :param tcSendTimeoutFactor: If TM is not received, resend TC after tmTimeout * tcSendTimeoutFactor - :param doPrintToFile: Specify whether output is also printed to a file - """ - self.tmTimeout = tmTimeout - self.pusPacketInfo = [] - self.pusPacket = [] - self.tcSendTimeoutFactor = tcSendTimeoutFactor - self.doPrintToFile = doPrintToFile - self.faultyInput = False - - if isinstance(comInterface, CommunicationInterface): - self._comInterface = comInterface - else: - raise TypeError("Invalid communication interface type!") - - if isinstance(tmtcPrinter, TmTcPrinter): - self._tmtcPrinter = tmtcPrinter - else: - raise TypeError("Invalid TMTC Printer type!") - - if isinstance(tmListener, TmListener): - self._tmListener = tmListener - else: - raise TypeError("Invalid TM Listener type!") - self._replyReceived = False - self._tmReady = False - self._queueEntryIsTelecommand = True - - self._start_time = 0 - self._elapsed_time = 0 - self._timeoutCounter = 0 - - # needed to store last actual tc packet from queue - self._lastTc = bytearray() - self._lastTcInfo = dict() - # ignore periodic packets for timeout when checking a sequence - self._isPacketToIgnore = False - - def _checkForFirstReply(self) -> None: - """ - Checks for replies. If no reply is received, send telecommand again in checkForTimeout() - :return: None - """ - if self._tmListener.replyEvent.is_set(): - self._replyReceived = True - self._tmListener.replyEvent.clear() - else: - if len(self.pusPacket) == 0: - print("Command Sender Receiver: No command has been sent yet") - else: - self._checkForTimeout() - - # Check for special queue entries. - def _checkQueueEntry(self, tcQueueEntry): - (self.pusPacketInfo, self.pusPacket) = tcQueueEntry - self._queueEntryIsTelecommand = False - if self.pusPacketInfo == "wait": - waitTime = self.pusPacket - self.tmTimeout = self.tmTimeout + waitTime - time.sleep(waitTime) - elif self.pusPacketInfo == "print": - printString = self.pusPacket - self._tmtcPrinter.print_string(printString) - elif self.pusPacketInfo == "export": - exportName = self.pusPacket - if self.doPrintToFile: - self._tmtcPrinter.print_to_file(exportName, True) - elif self.pusPacketInfo == "timeout": - self.tmTimeout = self.pusPacket - else: - self._queueEntryIsTelecommand = True - self._lastTc, self._lastTcInfo = (self.pusPacket, self.pusPacketInfo) - - def _checkForTimeout(self): - """ - Checks whether a timeout after sending a telecommand has occured and sends telecommand again. - If resending reached certain counter, exit the program. - :return: - """ - if self._timeoutCounter == 5: - print("Command Sender Receiver: No response from command !") - exit() - if self._start_time != 0: - self._elapsed_time = time.time() - self._start_time - if self._elapsed_time > self.tmTimeout * self.tcSendTimeoutFactor: - print("Command Sender Receiver: Timeout, sending TC again !") - self._comInterface.sendTelecommand(self._lastTc, self._lastTcInfo) - self._timeoutCounter = self._timeoutCounter + 1 - self._start_time = time.time() - time.sleep(0.5) - - - - - - diff --git a/sendreceive/OBSW_MultipleCommandsSenderReceiver.py b/sendreceive/OBSW_MultipleCommandsSenderReceiver.py index 9db8d22b57361b09e644fbf101d08d212528865d..9447a275b301a83a3c9f354b59594ed2722884e9 100644 --- a/sendreceive/OBSW_MultipleCommandsSenderReceiver.py +++ b/sendreceive/OBSW_MultipleCommandsSenderReceiver.py @@ -41,8 +41,7 @@ class MultipleCommandSenderReceiver(SequentialCommandSenderReceiver): :param doPrintToFile: """ super().__init__(comInterface=comInterface, tmtcPrinter=tmtcPrinter, tmListener=tmListener, - tmTimeout=tmTimeout, tcQueue=tcQueue, tcTimeoutFactor=tcTimeoutFactor, - doPrintToFile=doPrintToFile) + tmTimeout=tmTimeout, tcQueue=tcQueue, tcTimeoutFactor=tcTimeoutFactor) self.waitIntervals = waitIntervals self.waitTime = waitTime self.printTm = printTm @@ -54,15 +53,15 @@ class MultipleCommandSenderReceiver(SequentialCommandSenderReceiver): def sendTcQueueAndReturnInfo(self): try: - self._tmListener.modeId = g.ModeList.UnitTest - self._tmListener.modeChangeEvent.set() + self._tm_listener.modeId = g.ModeList.UnitTest + self._tm_listener.modeChangeEvent.set() # TC info queue is set in this function self.sendAllQueue() - self.handleLastRepliesListening(self.tmTimeout/2.0) + self.handleLastRepliesListening(self.tm_timeout / 2.0) self.tmInfoQueue = self.retrieveListenerTmInfoQueue() - self._tmListener.modeOpFinished.set() - if self.doPrintToFile: - self._tmtcPrinter.print_to_file() + self._tm_listener.modeOpFinished.set() + if g.G_PRINT_TO_FILE: + self._tmtc_printer.print_to_file() except (KeyboardInterrupt, SystemExit): print("Keyboard Interrupt or System Exit detected") exit() @@ -72,19 +71,18 @@ class MultipleCommandSenderReceiver(SequentialCommandSenderReceiver): def handleTcResending(self): while not self.__allRepliesReceived: if self._tcQueue.empty(): - if self.start_time == 0: - self.start_time = time.time() - self._checkForTimeout() + if self._start_time == 0: + self._start_time = time.time() + self._check_for_timeout() def sendAllQueue(self): while not self._tcQueue.__len__() == 0: self.sendAndPrintTc() def sendAndPrintTc(self): - self._checkQueueEntry(self._tcQueue.pop()) - if self._queueEntryIsTelecommand: + if self.check_queue_entry(self._tcQueue.pop()): self.tcInfoQueue.append(self.pusPacketInfo) - self._comInterface.sendTelecommand(self.pusPacket, self.pusPacketInfo) + self._com_interface.sendTelecommand(self.pusPacket, self.pusPacketInfo) self.handleWaiting() def handleWaiting(self): @@ -96,14 +94,14 @@ class MultipleCommandSenderReceiver(SequentialCommandSenderReceiver): time.sleep(self.waitTime) def retrieveListenerTmInfoQueue(self): - if self._tmListener.replyEvent.is_set(): - return self._tmListener.tmInfoQueue + if self._tm_listener.replyEvent.is_set(): + return self._tm_listener.tmInfoQueue else: print("Multiple Command SenderReceiver: Configuration error," " reply event not set in TM listener") def clearListenerTmInfoQueue(self): - self._tmListener.tmInfoQueue.clear() + self._tm_listener.tmInfoQueue.clear() @staticmethod def handleLastRepliesListening(waitTime: float): diff --git a/sendreceive/OBSW_SequentialSenderReceiver.py b/sendreceive/OBSW_SequentialSenderReceiver.py index 7a940abd954ed14aa995ac1a7edcfd1b4fdb619a..4c2ae27e0beb75717fe1ae0f9a57f875ec686ab8 100644 --- a/sendreceive/OBSW_SequentialSenderReceiver.py +++ b/sendreceive/OBSW_SequentialSenderReceiver.py @@ -8,22 +8,22 @@ @brief Used to send multiple TCs in sequence and listen for replies after each sent tc """ -from typing import Deque import time import config.OBSW_Config as g -from sendreceive.OBSW_CommandSenderReceiver import CommandSenderReceiver +from sendreceive.obsw_command_sender_receiver import CommandSenderReceiver from sendreceive.obsw_tm_listener import TmListenerT from comIF.OBSW_ComInterface import ComIF_T from utility.obsw_tmtc_printer import TmTcPrinterT +from tc.OBSW_TcPacket import tcQueueT class SequentialCommandSenderReceiver(CommandSenderReceiver): """ Specific implementation of CommandSenderReceiver to send multiple telecommands in sequence """ - def __init__(self, comInterface: ComIF_T, tmtcPrinter: TmTcPrinterT, tmListener: TmListenerT, tmTimeout: float, - tcQueue: Deque, tcTimeoutFactor: float, doPrintToFile: bool): + def __init__(self, comInterface: ComIF_T, tmtcPrinter: TmTcPrinterT, tmListener: TmListenerT, + tmTimeout: float, tcQueue: tcQueueT, tcTimeoutFactor: float): """ :param comInterface: CommunicationInterface object, passed on to CommandSenderReceiver :param tmListener: TmListener object which runs in the background and receives all Telemetry @@ -33,16 +33,16 @@ class SequentialCommandSenderReceiver(CommandSenderReceiver): :param doPrintToFile: Specify whether output is also printed to a file """ super().__init__( - comInterface=comInterface, tmtcPrinter=tmtcPrinter, tmListener=tmListener, tmTimeout=tmTimeout, - tcSendTimeoutFactor=tcTimeoutFactor, doPrintToFile=doPrintToFile) + comInterface=comInterface, tmtcPrinter=tmtcPrinter, tmListener=tmListener, + tmTimeout=tmTimeout, tcSendTimeoutFactor=tcTimeoutFactor) self._tcQueue = tcQueue self.__firstReplyReceived = False self.__allRepliesReceived = False self.__modeOpFinished = False def sendQueueTcAndReceiveTmSequentially(self): - self._tmListener.modeId = g.ModeList.ServiceTestMode - self._tmListener.modeChangeEvent.set() + self._tm_listener.modeId = g.ModeList.ServiceTestMode + self._tm_listener.modeChangeEvent.set() self.__sendAndReceiveFirstPacket() # this flag is set in the separate thread ! try: @@ -58,39 +58,41 @@ class SequentialCommandSenderReceiver(CommandSenderReceiver): self.__performNextTcSend() if self._tcQueue.__len__() == 0: self._start_time = time.time() - self._checkForTimeout() + self._check_for_timeout() if not self.__modeOpFinished: - self._tmListener.modeOpFinished.set() + self._tm_listener.modeOpFinished.set() self.__modeOpFinished = True print("Sequential SenderReceiver: All replies received!") - if self.doPrintToFile: + if g.G_PRINT_TO_FILE: print("Sequential SenderReceiver: Exporting output to log file.") - self._tmtcPrinter.print_to_file() + self._tmtc_printer.print_to_file() def __performNextTcSend(self): - if self._tmListener.replyEvent.is_set(): - self._replyReceived = True - self._tmListener.replyEvent.clear() + if self._tm_listener.replyEvent.is_set(): + self._reply_received = True + self._tm_listener.replyEvent.clear() # this flag is set in the separate receiver thread too - if self._replyReceived: + if self._reply_received: self.__sendNextTelecommand() - self._replyReceived = False + self._reply_received = False # just calculate elapsed time if start time has already been set (= command has been sent) else: - self._checkForTimeout() + self._check_for_timeout() def __sendAndReceiveFirstPacket(self): - self._checkQueueEntry(self._tcQueue.pop()) - if self._queueEntryIsTelecommand: - self._comInterface.sendTelecommand(self.pusPacket, self.pusPacketInfo) + tc_queue_tuple = self._tcQueue.pop() + if self.check_queue_entry(tc_queue_tuple): + pus_packet, pus_packet_info = tc_queue_tuple + self._com_interface.sendTelecommand(pus_packet, pus_packet_info) else: self.__sendAndReceiveFirstPacket() def __sendNextTelecommand(self): - self._checkQueueEntry(self._tcQueue.pop()) - if self._queueEntryIsTelecommand: + tc_queue_tuple = self._tcQueue.pop() + if self.check_queue_entry(tc_queue_tuple): self._start_time = time.time() - self._comInterface.sendTelecommand(self.pusPacket, self.pusPacketInfo) + pus_packet, pus_packet_info = tc_queue_tuple + self._com_interface.sendTelecommand(pus_packet, pus_packet_info) elif self._tcQueue.__len__() == 0: # Special case: Last queue entry is not a Telecommand self.__allRepliesReceived = True diff --git a/sendreceive/OBSW_SingleCommandSenderReceiver.py b/sendreceive/OBSW_SingleCommandSenderReceiver.py deleted file mode 100644 index 26f794ac3827920caf3878cee2471c8ccc200c46..0000000000000000000000000000000000000000 --- a/sendreceive/OBSW_SingleCommandSenderReceiver.py +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/python3.8 -""" -@file - OBSW_Config.py -@date - 01.11.2019 -@brief - Used to send single tcs and listen for replies after that -""" -from sendreceive.OBSW_CommandSenderReceiver import CommandSenderReceiver -from comIF.OBSW_ComInterface import ComIF_T -from utility.obsw_tmtc_printer import TmTcPrinterT -from sendreceive.obsw_tm_listener import TmListenerT -import config.OBSW_Config as g -import logging - - -# Specific implementation of CommandSenderReceiver to send a single telecommand -class SingleCommandSenderReceiver(CommandSenderReceiver): - """ This object can be used by instantiating it and calling sendSingleTcAndReceiveTm() """ - def __init__(self, comInterface: ComIF_T, tmtcPrinter: TmTcPrinterT, tmListener: TmListenerT, - pusPacketTuple: tuple, tmTimeout: float, tcTimeoutFactor: float, doPrintToFile: bool): - """ - :param comInterface: CommunicationInterface object, passed on to CommandSenderReceiver - :param tmListener: TmListener object which runs in the background and receives all TM - :param tmtcPrinter: TmTcPrinter object, passed on to CommandSenderReceiver - :param tmTimeout: TM Timeout. After each sent telecommand, listen for TMs for this time period - :param tcTimeoutFactor: If TM is not received, resend TC after tmTimeout * tcSendTimeoutFactor - :param doPrintToFile: Specify whether output is also printed to a file - """ - super().__init__(comInterface=comInterface, tmListener=tmListener, tmtcPrinter=tmtcPrinter, tmTimeout=tmTimeout, - tcSendTimeoutFactor=tcTimeoutFactor, doPrintToFile=doPrintToFile) - try: - (self.pusPacketInfo, self.pusPacket) = pusPacketTuple - except TypeError: - print("Invalid queue entry detected") - logging.exception("Error") - self.faultyInput = True - - def sendSingleTcAndReceiveTm(self): - if not self.faultyInput: - self._tmListener.modeId = g.ModeList.SingleCommandMode - self._tmListener.modeChangeEvent.set() - self._comInterface.sendTelecommand(self.pusPacket, self.pusPacketInfo) - while not self._replyReceived: - # wait until reply is received - super()._checkForFirstReply() - if self._replyReceived: - print("Single Command SenderReceiver: Reply received") - self._tmListener.modeOpFinished.set() - print("Listening for packages ...") - diff --git a/sendreceive/obsw_command_sender_receiver.py b/sendreceive/obsw_command_sender_receiver.py new file mode 100644 index 0000000000000000000000000000000000000000..453caaf629f3ab887c8e1293554493e837086bda --- /dev/null +++ b/sendreceive/obsw_command_sender_receiver.py @@ -0,0 +1,124 @@ +""" +Program: OBSW_UnitTest.py +Date: 01.11.2019 +Description: All functions related to TmTc Sending and Receiving, used by UDP client + +Manual: +Set up the UDP client as specified in the header comment and use the unit testing mode + +A separate thread is used to listen for replies and send a new telecommand +if the first reply has not been received. + +@author: R. Mueller +""" +import sys +import time +from comIF.OBSW_ComInterface import CommunicationInterface, ComIF_T +from utility.obsw_tmtc_printer import TmTcPrinterT, TmTcPrinter +from sendreceive.obsw_tm_listener import TmListenerT, TmListener +from tc.OBSW_TcPacket import tcQueueEntryT + + +# pylint: disable=too-few-public-methods +# pylint: disable=too-many-arguments +# pylint: disable=too-many-instance-attributes +# TODO: Maybe replace timeout, tc send timeout and print boolean by just using global values +# in config file +class CommandSenderReceiver: + """ + This is the generic CommandSenderReceiver object. All TMTC objects inherit this object, + for example specific implementations (e.g. SingleCommandSenderReceiver) + """ + def __init__(self, comInterface: ComIF_T, tmtcPrinter: TmTcPrinterT, tmListener: TmListenerT, + tmTimeout: float, tcSendTimeoutFactor: float): + """ + :param comInterface: CommunicationInterface object. Instantiate the desired one + and pass it here + :param tmtcPrinter: TmTcPrinter object. Instantiate it and pass it here. + :param tmTimeout: TM Timeout. After each sent telecommand, + listen for TMs for this time period + :param tcSendTimeoutFactor: If TM is not received, + resend TC after tmTimeout * tcSendTimeoutFactor + """ + self.tm_timeout = tmTimeout + self.tc_send_timeout_factor = tcSendTimeoutFactor + + if isinstance(comInterface, CommunicationInterface): + self._com_interface = comInterface + else: + raise TypeError("Invalid communication interface type!") + + if isinstance(tmtcPrinter, TmTcPrinter): + self._tmtc_printer = tmtcPrinter + else: + raise TypeError("Invalid TMTC Printer type!") + + if isinstance(tmListener, TmListener): + self._tm_listener = tmListener + else: + raise TypeError("Invalid TM Listener type!") + self._reply_received = False + + self._start_time = 0 + self._elapsed_time = 0 + self._timeout_counter = 0 + + # needed to store last actual tc packet from queue + self._last_tc = bytearray() + self._last_tc_info = dict() + + def _check_for_first_reply(self) -> None: + """ + Checks for replies. If no reply is received, send telecommand again in checkForTimeout() + :return: None + """ + if self._tm_listener.replyEvent.is_set(): + self._reply_received = True + self._tm_listener.replyEvent.clear() + else: + self._check_for_timeout() + + def check_queue_entry(self, tc_queue_entry: tcQueueEntryT) -> bool: + """ + Checks whether the entry in the tc queue is a telecommand. + The last telecommand and respective information are stored in _last_tc + and _last_tc_info + :param tc_queue_entry: + :return: True if queue entry is telecommand, False if it is not + """ + queue_entry_first, queue_entry_second = tc_queue_entry + queue_entry_is_telecommand = False + if queue_entry_first == "wait": + wait_time = queue_entry_second + self.tm_timeout = self.tm_timeout + wait_time + time.sleep(wait_time) + elif queue_entry_first == "print": + print_string = queue_entry_second + self._tmtc_printer.print_string(print_string) + elif queue_entry_first == "export": + export_name = queue_entry_second + self._tmtc_printer.print_to_file(export_name, True) + elif queue_entry_first == "timeout": + self.tm_timeout = queue_entry_second + else: + self._last_tc, self._last_tc_info = (queue_entry_first, queue_entry_second) + return True + return queue_entry_is_telecommand + + def _check_for_timeout(self): + """ + Checks whether a timeout after sending a telecommand has occured and sends telecommand + again. If resending reached certain counter, exit the program. + :return: + """ + if self._timeout_counter == 5: + print("Command Sender Receiver: No response from command !") + sys.exit() + if self._start_time != 0: + self._elapsed_time = time.time() - self._start_time + if self._elapsed_time > self.tm_timeout * self.tc_send_timeout_factor: + print("Command Sender Receiver: Timeout, sending TC again !") + self._com_interface.sendTelecommand(self._last_tc, self._last_tc_info) + self._timeout_counter = self._timeout_counter + 1 + self._start_time = time.time() + time.sleep(0.5) diff --git a/sendreceive/obsw_single_command_sender_receiver.py b/sendreceive/obsw_single_command_sender_receiver.py new file mode 100644 index 0000000000000000000000000000000000000000..27be3c18ce50c958fa70e856d60ddff168043a11 --- /dev/null +++ b/sendreceive/obsw_single_command_sender_receiver.py @@ -0,0 +1,62 @@ +#!/usr/bin/python3.8 +""" +@file + OBSW_Config.py +@date + 01.11.2019 +@brief + Used to send single tcs and listen for replies after that +""" +import logging + +from sendreceive.obsw_command_sender_receiver import CommandSenderReceiver +from sendreceive.obsw_tm_listener import TmListenerT +from comIF.OBSW_ComInterface import ComIF_T +from utility.obsw_tmtc_printer import TmTcPrinterT +import config.OBSW_Config as g + + +class SingleCommandSenderReceiver(CommandSenderReceiver): + """ + Specific implementation of CommandSenderReceiver to send a single telecommand + This object can be used by instantiating it and calling sendSingleTcAndReceiveTm() + """ + def __init__(self, comInterface: ComIF_T, tmtcPrinter: TmTcPrinterT, tmListener: TmListenerT, + pusPacketTuple: tuple, tmTimeout: float, tcTimeoutFactor: float, + doPrintToFile: bool): + """ + :param comInterface: CommunicationInterface object, passed on to CommandSenderReceiver + :param tmListener: TmListener object which runs in the background and receives all TM + :param tmtcPrinter: TmTcPrinter object, passed on to CommandSenderReceiver + :param tmTimeout: TM Timeout. After each sent telecommand, + listen for TMs for this time period + :param tcTimeoutFactor: If TM is not received, + resend TC after tmTimeout * tcSendTimeoutFactor + :param doPrintToFile: Specify whether output is also printed to a file + """ + super().__init__(comInterface=comInterface, tmListener=tmListener, tmtcPrinter=tmtcPrinter, + tmTimeout=tmTimeout, tcSendTimeoutFactor=tcTimeoutFactor, + doPrintToFile=doPrintToFile) + try: + self.pus_packet, self.pus_packet_info = pusPacketTuple + except TypeError: + print("Invalid queue entry detected") + logging.exception("Error") + self.faulty_input = True + + def send_single_tc_and_receive_tm(self): + """ + Send a single telecommand passed to the class and wait for replies + :return: + """ + if not self.faulty_input: + self._tm_listener.modeId = g.ModeList.SingleCommandMode + self._tm_listener.modeChangeEvent.set() + self._com_interface.sendTelecommand(self.pus_packet, self.pus_packet_info) + while not self._reply_received: + # wait until reply is received + super()._check_for_first_reply() + if self._reply_received: + print("Single Command SenderReceiver: Reply received") + self._tm_listener.modeOpFinished.set() + print("Listening for packages ...") diff --git a/tc/OBSW_TcPacket.py b/tc/OBSW_TcPacket.py index fd6e75aa49917e8f38f578c5367368d62ec6abbb..fad67cbfa47a95144ae3cdb3a4e89406262934c4 100644 --- a/tc/OBSW_TcPacket.py +++ b/tc/OBSW_TcPacket.py @@ -11,10 +11,11 @@ from typing import TypeVar, Dict, Union, Tuple, Deque PusTcT = TypeVar('PusTcT', bound='PUSTelecommand') pusTcInfoT = Union[Dict[str, any], None] -pusTcTupleT = Tuple[pusTcInfoT, bytearray] +pusTcTupleT = Tuple[bytearray, pusTcInfoT] tcAuxiliaryTupleT = Tuple[str, any] # Union: Type can be either of those 2 -tcQueueT = Deque[Union[tcAuxiliaryTupleT, pusTcTupleT]] +tcQueueEntryT = Union[tcAuxiliaryTupleT, pusTcTupleT] +tcQueueT = Deque[tcQueueEntryT] pusTcInfoQueueT = Deque[pusTcInfoT] @@ -78,7 +79,7 @@ class PUSTelecommand: return tcInformation def packCommandTuple(self) -> pusTcTupleT: - commandTuple = (self.packInformation(), self.pack()) + commandTuple = (self.pack(), self.packInformation()) return commandTuple def print(self): diff --git a/test/OBSW_UnitTest.py b/test/OBSW_UnitTest.py index b3951a98e34f6159823f906e305ddb9ccb22caa8..800559c78b3014f1d87c3fc6b5391521a524012a 100644 --- a/test/OBSW_UnitTest.py +++ b/test/OBSW_UnitTest.py @@ -69,7 +69,7 @@ class TestService(unittest.TestCase): # default timeout for receiving TM, set in subclass manually cls.tmTimeout = g.tmTimeout cls.tcTimeoutFactor = g.tcSendTimeoutFactor - cls.printFile = g.printToFile + cls.printFile = g.G_PRINT_TO_FILE cls.tmtcPrinter = g.tmtcPrinter cls.tmListener = g.tmListener cls.communicationInterface = g.comInterface diff --git a/utility/OBSW_ArgParser.py b/utility/OBSW_ArgParser.py index 4c7f519a6f2a5c29072f3ca6605c31fbedacaf23..dba2a699879b81e13621ae95986668b62127181b 100644 --- a/utility/OBSW_ArgParser.py +++ b/utility/OBSW_ArgParser.py @@ -71,7 +71,8 @@ def handleUnspecifiedArgs(args): print("5: Unit Test, runs unit test specified in OBSW_UnitTest.py") args.mode = input("Please enter Mode: ") if args.mode == 1 and args.service is None: - args.service = input("No Service specified for Service Mode. Please enter PUS service number: ") + args.service = input("No Service specified for Service Mode. " + "Please enter PUS service number: ") def handleEmptyArgs(args): @@ -80,7 +81,7 @@ def handleEmptyArgs(args): printHk = printHk.lower() except TypeError: pass - if printHk == 'y' or printHk == 'yes' or printHk == 1: + if printHk in ('y', 'yes', 1): args.hk = True else: args.hk = False diff --git a/utility/obsw_tmtc_printer.py b/utility/obsw_tmtc_printer.py index 6ccf78cdaa5172e0e9660b2d05ccfac715deebf5..d3822bc0258bc5d66db381709f13a6641d47be7f 100644 --- a/utility/obsw_tmtc_printer.py +++ b/utility/obsw_tmtc_printer.py @@ -47,8 +47,8 @@ class TmTcPrinter: self.__handle_short_print(packet) else: self.__handle_long_print(packet) - self.handle_wiretapping_packet(packet) - self.handle_data_reply_packet(packet) + self.__handle_wiretapping_packet(packet) + self.__handle_data_reply_packet(packet) if packet.getService() == 3 and \ (packet.getSubservice() == 25 or packet.getSubservice() == 26): self.__handle_hk_print(packet) @@ -100,8 +100,8 @@ class TmTcPrinter: if g.G_PRINT_HK_DATA: self.print_buffer = "HK Data from SID " self.print_buffer = self.print_buffer + str(hex(tm_packet.sid)) + " :" - self.print_hk(tm_packet) - self.print_validity_buffer(tm_packet) + self.__print_hk(tm_packet) + self.__print_validity_buffer(tm_packet) def __handle_hk_definition_print(self, tm_packet: PusTmT): """ @@ -111,9 +111,9 @@ class TmTcPrinter: if g.G_PRINT_HK_DATA: self.print_buffer = "HK Definition from SID " self.print_buffer = self.print_buffer + str(hex(tm_packet.sid)) + " :" - self.print_hk(tm_packet) + self.__print_hk(tm_packet) - def print_hk(self, tm_packet: PusTm3T): + def __print_hk(self, tm_packet: PusTm3T): """ :param tm_packet: :return: @@ -127,7 +127,7 @@ class TmTcPrinter: print(self.print_buffer) self.add_print_buffer_to_file_buffer() - def print_validity_buffer(self, tm_packet: PusTm3T): + def __print_validity_buffer(self, tm_packet: PusTm3T): """ :param tm_packet: :return: @@ -135,9 +135,9 @@ class TmTcPrinter: self.print_buffer = "Valid: " print(self.print_buffer) self.add_print_buffer_to_file_buffer() - self.handle_validity_buffer_print(tm_packet.validity_buffer, tm_packet.numberOfParameters) + self.__handle_validity_buffer_print(tm_packet.validity_buffer, tm_packet.numberOfParameters) - def handle_validity_buffer_print(self, validity_buffer: bytearray, number_of_parameters): + def __handle_validity_buffer_print(self, validity_buffer: bytearray, number_of_parameters): """ :param validity_buffer: :param number_of_parameters: @@ -157,7 +157,7 @@ class TmTcPrinter: print(self.print_buffer) self.add_print_buffer_to_file_buffer() - def handle_wiretapping_packet(self, packet): + def __handle_wiretapping_packet(self, packet): """ :param packet: :return: @@ -170,15 +170,15 @@ class TmTcPrinter: print(self.print_buffer) self.add_print_buffer_to_file_buffer() - def handle_data_reply_packet(self, packet): + def __handle_data_reply_packet(self, tm_packet): """ - - :param packet: + Handles the PUS Service 8 data reply packets. + :param tm_packet: :return: """ - if packet.getService() == 8 and packet.getSubservice() == 130: + if tm_packet.getService() == 8 and tm_packet.getSubservice() == 130: self.print_buffer = "Service 8 Direct Command Reply TM[8,130] with data: " \ - + self.return_data_string(packet.data) + + self.return_data_string(tm_packet.data) print(self.print_buffer) def print_data(self, byte_array: bytearray): @@ -192,6 +192,7 @@ class TmTcPrinter: @staticmethod def return_data_string(byte_array: bytearray) -> str: """ + Converts a bytearray to string format for printing :param byte_array: :return: """ @@ -204,6 +205,7 @@ class TmTcPrinter: def print_string(self, string: str): """ + Print a string and adds it to the file buffer. :param string: :return: """ @@ -221,7 +223,6 @@ class TmTcPrinter: def print_to_file(self, log_name: str = "log/tmtc_log.txt", clear_file_buffer: bool = False): """ - :param log_name: :param clear_file_buffer: :return: @@ -264,11 +265,11 @@ class TmTcPrinter: print("TMTC Printer: No packet info supplied to print") return if self.display_mode == "short": - self.handle_short_tc_print(tc_packet_info) + self.__handle_short_tc_print(tc_packet_info) else: - self.handle_long_tc_print(tc_packet_info) + self.__handle_long_tc_print(tc_packet_info) - def handle_short_tc_print(self, tc_packet_info: pusTcInfoT): + def __handle_short_tc_print(self, tc_packet_info: pusTcInfoT): """ Brief TC print :param tc_packet_info: @@ -280,7 +281,7 @@ class TmTcPrinter: print(self.print_buffer) self.add_print_buffer_to_file_buffer() - def handle_long_tc_print(self, tc_packet_info: pusTcInfoT): + def __handle_long_tc_print(self, tc_packet_info: pusTcInfoT): """ Long TC print :param tc_packet_info: