diff --git a/comIF/OBSW_ComInterface.py b/comIF/OBSW_ComInterface.py index 99eb20078581fbfc531d33ad46546a6722750db5..50112a2fd95fd944c3729268850c337731c0600c 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 0000000000000000000000000000000000000000..6ad9351df97654a09e29c5bd50b0ccc8aa779029 --- /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 e9735b351f8da7e40e68f626553f2fc7e7b15ce5..cc5a075dd8c72dcbebb2605365cdc07af87faa81 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 c7bf1fd219f90817d60dbf22e4c89d74b0ebbc69..cf9e4f4e5ef1cff84f55a3b3d0855484f5a4fb2e 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 edef475070131c906367e2bb5664bff39f308176..e16cf3055f402f71cc1d47d008ca6ed367af4322 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 53a79e5fc576152089762e1742b35ebd61f75d7f..137ed265dd76b3989e93b3703c5bc35299118f9f 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 08eee74a200f78b0296f82f8aa4d2e31d959246b..94de8744dc523f390ea3b7dc75b9da57714eb4d9 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