From feca9acf9b55998e0237756af08bdc5275cad173 Mon Sep 17 00:00:00 2001 From: Robin Mueller <robin.mueller.m@gmail.com> Date: Mon, 9 Mar 2020 14:19:43 +0100 Subject: [PATCH] TMTC refactoring continued --- comIF/OBSW_ComInterface.py | 18 ++++-- comIF/OBSW_DummyComIF.py | 24 ++++++++ comIF/OBSW_Ethernet_ComIF.py | 9 ++- comIF/OBSW_Serial_ComIF.py | 13 +++-- sendreceive/OBSW_SequentialSenderReceiver.py | 12 ++-- .../OBSW_SingleCommandSenderReceiver.py | 1 + sendreceive/OBSW_TmListener.py | 55 ++++++++++++++----- 7 files changed, 97 insertions(+), 35 deletions(-) create mode 100644 comIF/OBSW_DummyComIF.py diff --git a/comIF/OBSW_ComInterface.py b/comIF/OBSW_ComInterface.py index 99eb200..50112a2 100644 --- a/comIF/OBSW_ComInterface.py +++ b/comIF/OBSW_ComInterface.py @@ -19,12 +19,23 @@ class CommunicationInterface: # Send Telecommand @abstractmethod - def sendTelecommand(self, tcPacket, tcPacketInfo=""): + def sendTelecommand(self, tcPacket, tcPacketInfo="") -> None: + """ + Send telecommands + :param tcPacket: TC packet to send + :param tcPacketInfo: TC packet information + :return: None for now + """ pass # Receive telemetry and process it @abstractmethod def receiveTelemetry(self, parameters=0): + """ + Returns a list of packets. Most of the time, this will simply call the pollInterface function + :param parameters: + :return: + """ packetList = [] return packetList @@ -43,11 +54,6 @@ class CommunicationInterface: def dataAvailable(self, parameters): pass - # Listen for packets - # @abstractmethod - # def performListenerMode(self): - # pass - # Receive Telemetry and store it into a queue def receiveTelemetryAndStoreIntoQueue(self, tmQueue): pass diff --git a/comIF/OBSW_DummyComIF.py b/comIF/OBSW_DummyComIF.py new file mode 100644 index 0000000..6ad9351 --- /dev/null +++ b/comIF/OBSW_DummyComIF.py @@ -0,0 +1,24 @@ +""" +@file OBSW_DummyComIF.py +@date 09.03.2020 +@brief Dummy Communication Interface + +@author R. Mueller +""" +from typing import Tuple + +from comIF.OBSW_ComInterface import CommunicationInterface + + +class Dummy_ComIF(CommunicationInterface): + def dataAvailable(self, parameters): + pass + + def pollInterface(self, parameters) -> Tuple[bool, list]: + pass + + def receiveTelemetry(self, parameters=0): + pass + + def sendTelecommand(self, tcPacket, tcPacketInfo="") -> None: + pass diff --git a/comIF/OBSW_Ethernet_ComIF.py b/comIF/OBSW_Ethernet_ComIF.py index e9735b3..cc5a075 100644 --- a/comIF/OBSW_Ethernet_ComIF.py +++ b/comIF/OBSW_Ethernet_ComIF.py @@ -1,10 +1,9 @@ -# -*- coding: utf-8 -*- """ -Program: OBSW_UnitTest.py -Date: 01.11.2019 -Description: Ethernet Communication Interface +@file OBSW_Ethernet_ComIF.py +@date 01.11.2019 +@brief Ethernet Communication Interface -@author: R. Mueller +@author R. Mueller """ import select diff --git a/comIF/OBSW_Serial_ComIF.py b/comIF/OBSW_Serial_ComIF.py index c7bf1fd..cf9e4f4 100644 --- a/comIF/OBSW_Serial_ComIF.py +++ b/comIF/OBSW_Serial_ComIF.py @@ -1,10 +1,15 @@ -import time -from typing import Tuple +""" +@file OBSW_Serial_ComIF.py +@date 01.11.2019 +@brief Serial Communication Interface -from comIF.OBSW_ComInterface import CommunicationInterface +@author R. Mueller +""" +import time import serial import logging - +from typing import Tuple +from comIF.OBSW_ComInterface import CommunicationInterface from tm.OBSW_TmPacket import PUSTelemetryFactory diff --git a/sendreceive/OBSW_SequentialSenderReceiver.py b/sendreceive/OBSW_SequentialSenderReceiver.py index edef475..e16cf30 100644 --- a/sendreceive/OBSW_SequentialSenderReceiver.py +++ b/sendreceive/OBSW_SequentialSenderReceiver.py @@ -43,8 +43,8 @@ class SequentialCommandSenderReceiver(CommandSenderReceiver): self.start_time = 0 self.elapsed_time = 0 self.abortFlag = False - self.run_event = threading.Event() - self.run_event.set() + self.seqSenderActive = threading.Event() + self.seqSenderActive.set() def sendQueueTcAndReceiveTmSequentially(self): self.tmListener.modeId = g.modeList[3] @@ -113,7 +113,7 @@ class SequentialCommandSenderReceiver(CommandSenderReceiver): # if the tc queue is empty and the last telemetry sequence has been received, # a flag is set to transition into listener mode def checkForMultipleReplies(self): - while not self.allRepliesReceived and self.run_event.is_set(): + while not self.allRepliesReceived and self.seqSenderActive.is_set(): # listen for duration timeoutInSeconds for replies self.handleReplyListening() @@ -126,17 +126,19 @@ class SequentialCommandSenderReceiver(CommandSenderReceiver): self.handleFirstReplyListening() def handleTelemetrySequence(self): - if self.run_event.is_set(): + if self.seqSenderActive.is_set(): success = self.tmListener.checkForOneTelemetrySequence() if success: # set this flag so the other thread can send the next telecommand self.replyReceived = True + self.tmListener.replyEvent.clear() if self.tcQueue.empty(): print("Receiver: All replies received") + self.tmListener.modeOpFinished.set() self.allRepliesReceived = True def handleFirstReplyListening(self): - while not self.firstReplyReceived and self.run_event.is_set(): + while not self.firstReplyReceived and self.seqSenderActive.is_set(): # this function sends the telecommand again if no reply is received self.checkForFirstReply() if self.replyReceived: diff --git a/sendreceive/OBSW_SingleCommandSenderReceiver.py b/sendreceive/OBSW_SingleCommandSenderReceiver.py index 53a79e5..137ed26 100644 --- a/sendreceive/OBSW_SingleCommandSenderReceiver.py +++ b/sendreceive/OBSW_SingleCommandSenderReceiver.py @@ -46,5 +46,6 @@ class SingleCommandSenderReceiver(CommandSenderReceiver): # wait until reply is received super().checkForFirstReply() if self.replyReceived: + self.tmListener.modeOpFinished.set() print("Listening for packages ...") diff --git a/sendreceive/OBSW_TmListener.py b/sendreceive/OBSW_TmListener.py index 08eee74..94de874 100644 --- a/sendreceive/OBSW_TmListener.py +++ b/sendreceive/OBSW_TmListener.py @@ -19,30 +19,49 @@ TmListenerT = TypeVar('TmListenerT', bound='TmListener') class TmListener: + """ + Performs all TM listening operations. + This listener can be used by setting the modeChangeEvent Event with the set() function + and changing the mode to do special mode operations. The mode operation ends as soon + the modeOpFinished Event is set() ! + """ def __init__(self, comInterface: ComIF_T, tmTimeout: int, tcTimeoutFactor: int): self.tmTimeout = tmTimeout self.tcTimeoutFactor = tcTimeoutFactor self.comInterface = comInterface # this will be the default mode (listener mode) self.modeId = g.modeList[1] - self.active = True - self.listenerThread = threading.Thread(target=self.performOperation) + self.listenerActive = threading.Event() # TM Listener operations can be suspended by setting this flag + self.listenerActive.set() + # I don't think a listener is useful without the main program, so we might just declare it daemonic. + self.listenerThread = threading.Thread(target=self.performOperation, daemon=True) + # This Event is set by sender objects to perform mode operations self.modeChangeEvent = threading.Event() + # This Event is set by sender objects if all necessary operations are done to transition back to listener mode + self.modeOpFinished = threading.Event() # maybe we will just make the thread daemonic... - self.terminationEvent = threading.Event() + # self.terminationEvent = threading.Event() + # This Event is set and cleared by the listener to inform the sender objects if a reply has been received self.replyEvent = threading.Event() def start(self): self.listenerThread.start() def performOperation(self): - while self.active: - self.defaultOperation() + while True: + if self.listenerActive.is_set(): + self.defaultOperation() + else: + time.sleep(1) def defaultOperation(self): - while not self.terminationEvent.is_set(): - self.comInterface.pollInterface() - if self.modeChangeEvent.is_set(): + self.comInterface.pollInterface() + if self.modeChangeEvent.is_set(): + # TODO: We should put this in a timeout.. Each mode operation up until now only takes + # a maximum specified time. Otherwise, this is a permanent loop + self.modeChangeEvent.clear() + self.modeId = g.modeList[1] # After Mode Operation, mode will be listener mode. + while not self.modeOpFinished.is_set(): self.performModeOperation() def performModeOperation(self): @@ -51,20 +70,26 @@ class TmListener: the TmListener is instructed to perform certain operations. :return: """ + # Listener Mode if self.modeId == g.modeList[1]: - self.modeChangeEvent.clear() + pass + # Single Command Mode elif self.modeId == g.modeList[2]: + # Listen for one reply sequence. if self.checkForOneTelemetrySequence(): print("All replies received!") - print("Listening for packets...") - else: - print("TM Listener: Something went wrong.") - self.modeId = g.modeList[1] - self.modeChangeEvent.clear() + self.replyEvent.set() + # Sequential Command Mode elif self.modeId == g.modeList[3]: - pass + if self.checkForOneTelemetrySequence(): + print("Reply sequence received!") + self.replyEvent.set() def checkForOneTelemetrySequence(self): + """ + Receive all telemetry for a specified time period. + :return: + """ tmReady = self.comInterface.dataAvailable(self.tmTimeout * self.tcTimeoutFactor) if tmReady is False: return False -- GitLab