Skip to content
Snippets Groups Projects
Commit ceb5463e authored by Robin.Mueller's avatar Robin.Mueller
Browse files

restructuring client to run a service

parent d291330e
Branches
Tags
No related merge requests found
......@@ -93,15 +93,17 @@ def main():
else:
communicationInterface = setCommunicationInterface(tmtcPrinter)
atexit.register(keyboardInterruptHandler, comInterface=communicationInterface)
tmListener = TmListener(communicationInterface)
tmListener = TmListener(
comInterface=communicationInterface, tmTimeout=g.tmTimeout, tcTimeoutFactor=g.tcSendTimeoutFactor)
tmListener.start()
if g.modeId == "ListenerMode":
pass
print("Listening for packages...")
elif g.modeId == "SingleCommandMode":
pusPacketTuple = commandPreparation()
SenderAndReceiver = SingleCommandSenderReceiver(
comInterface=communicationInterface, tmtcPrinter=tmtcPrinter, pusPacketTuple=pusPacketTuple,
tmTimeout=g.tmTimeout, tcTimeoutFactor=g.tcSendTimeoutFactor, doPrintToFile=g.printToFile)
comInterface=communicationInterface, tmtcPrinter=tmtcPrinter, tmListener=tmListener,
pusPacketTuple=pusPacketTuple, tmTimeout=g.tmTimeout, tcTimeoutFactor=g.tcSendTimeoutFactor,
doPrintToFile=g.printToFile)
SenderAndReceiver.sendSingleTcAndReceiveTm()
elif g.modeId == "ServiceTestMode":
......
......@@ -8,7 +8,7 @@ Description: Generic Communication Interface. Defines the syntax of the communic
@author: R. Mueller
"""
from abc import abstractmethod
from typing import TypeVar
from typing import TypeVar, Tuple
ComIF_T = TypeVar('ComIF_T', bound='CommunicationInterface')
......@@ -28,9 +28,14 @@ class CommunicationInterface:
packetList = []
return packetList
# Poll the interface for data
@abstractmethod
def pollInterface(self, parameters):
def pollInterface(self, parameters) -> Tuple[bool, list]:
"""
Poll the interface and return a list of received packets
:param parameters:
:return: Tuple: boolean which specifies wheather a packet was received, and the packet list containing
Tm packets
"""
pass
# Check whether data is available
......@@ -39,9 +44,9 @@ class CommunicationInterface:
pass
# Listen for packets
@abstractmethod
def performListenerMode(self):
pass
# @abstractmethod
# def performListenerMode(self):
# pass
# Receive Telemetry and store it into a queue
def receiveTelemetryAndStoreIntoQueue(self, tmQueue):
......
......@@ -40,13 +40,14 @@ class EthernetComIF(CommunicationInterface):
elif ready[0]:
return ready
# TODO: This still needs to be fixed, this function should return a list of telemetry packets
def pollInterface(self, pollTimeout):
ready = self.dataAvailable(pollTimeout)
if ready is False:
return False
return False, []
elif ready:
self.receiveTelemetry()
return True
packetList = self.receiveTelemetry()
return True, packetList
def receiveTelemetry(self, parameters=0):
data = self.recvSocket.recvfrom(1024)[0]
......
import time
from typing import Tuple
from comIF.OBSW_ComInterface import CommunicationInterface
import serial
......@@ -26,10 +27,10 @@ class SerialComIF(CommunicationInterface):
self.serial.write(tcPacket)
def receiveTelemetry(self, parameters=0):
packetList = self.pollInterface()
(packetReceived, packetList) = self.pollInterface()
return packetList
def pollInterface(self, parameter=0):
def pollInterface(self, parameter=0) -> Tuple[bool, list]:
if self.dataAvailable():
pusDataList, numberOfPackets = self.pollPusPackets()
packetList = []
......@@ -37,7 +38,9 @@ class SerialComIF(CommunicationInterface):
packet = PUSTelemetryFactory(pusDataList[counter])
self.tmtcPrinter.printTelemetry(packet)
packetList.append(packet)
return packetList
return True, packetList
else:
return False, []
def dataAvailable(self, timeout=0):
if self.serial.in_waiting > 0:
......
......@@ -15,6 +15,7 @@ import time
from config import OBSW_Config as g
from comIF.OBSW_ComInterface import CommunicationInterface, ComIF_T
from utility.OBSW_TmTcPrinter import TmTcPrinterT, TmTcPrinter
from sendreceive.OBSW_TmListener import TmListenerT, TmListener
# Generic TMTC SendReceive class which is implemented
......@@ -23,7 +24,7 @@ class CommandSenderReceiver:
"""
This is the generic CommandSenderReceiver object. All TMTC objects inherit this object
"""
def __init__(self, comInterface: ComIF_T, tmtcPrinter: TmTcPrinterT, tmTimeout: int,
def __init__(self, comInterface: ComIF_T, tmtcPrinter: TmTcPrinterT, tmListener: TmListenerT, tmTimeout: int,
tcSendTimeoutFactor: int, doPrintToFile: bool):
"""
:param comInterface: CommunicationInterface object. Instantiate the desired one and pass it here
......@@ -44,6 +45,11 @@ class CommandSenderReceiver:
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.pusPacketInfo = []
......@@ -62,17 +68,19 @@ class CommandSenderReceiver:
# ignore periodic packets for timeout when checking a sequence
self.isPacketToIgnore = False
# checks for replies. if no reply is received, send telecommand again
def checkForFirstReply(self):
success = self.checkForOneTelemetrySequence()
if success:
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:
print("Command Sender Receiver: Sending command again")
self.comInterface.sendTelecommand(self.pusPacket, self.pusPacketInfo)
self.checkForTimeout()
# Check for special queue entries.
def checkQueueEntry(self, tcQueueEntry):
......@@ -96,6 +104,11 @@ class CommandSenderReceiver:
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()
......@@ -110,24 +123,24 @@ class CommandSenderReceiver:
# check for sequence of replies for a telecommand (e.g. TM[1,1] , TM[1,7] ...) for tmTimeout value
# returns True on success
def checkForOneTelemetrySequence(self):
tmReady = self.comInterface.dataAvailable(self.tmTimeout * self.tcSendTimeoutFactor)
if tmReady is False:
return False
else:
self.comInterface.receiveTelemetry()
start_time = time.time()
elapsed_time = 0
while elapsed_time < self.tmTimeout:
tmReady = self.comInterface.dataAvailable(1.0)
if tmReady:
self.comInterface.receiveTelemetry()
elapsed_time = time.time() - start_time
# the timeout value can be set by special TC queue entries if packet handling takes longer,
# but it is reset here to the global value
if self.tmTimeout is not g.tmTimeout:
self.tmTimeout = g.tmTimeout
return True
# def checkForOneTelemetrySequence(self):
# tmReady = self.comInterface.dataAvailable(self.tmTimeout * self.tcSendTimeoutFactor)
# if tmReady is False:
# return False
# else:
# self.comInterface.receiveTelemetry()
# start_time = time.time()
# elapsed_time = 0
# while elapsed_time < self.tmTimeout:
# tmReady = self.comInterface.dataAvailable(1.0)
# if tmReady:
# self.comInterface.receiveTelemetry()
# elapsed_time = time.time() - start_time
# # the timeout value can be set by special TC queue entries if packet handling takes longer,
# # but it is reset here to the global value
# if self.tmTimeout is not g.tmTimeout:
# self.tmTimeout = g.tmTimeout
# return True
......
......@@ -8,15 +8,35 @@
@brief
Used to send multiple TCs in sequence and listen for replies after each sent tc
"""
from sendreceive.OBSW_CommandSenderReceiver import CommandSenderReceiver
import threading
import time
import config.OBSW_Config as g
from sendreceive.OBSW_CommandSenderReceiver import CommandSenderReceiver
from sendreceive.OBSW_TmListener import TmListenerT
from comIF.OBSW_ComInterface import ComIF_T
from utility.OBSW_TmTcPrinter import TmTcPrinterT
# Specific implementation of CommandSenderReceiver to send multiple telecommands in sequence
class SequentialCommandSenderReceiver(CommandSenderReceiver):
def __init__(self, comInterface, tmtcPrinter, tmTimeout, tcQueue, tcTimeoutFactor, doPrintToFile):
super().__init__(comInterface, tmtcPrinter, tmTimeout, tcTimeoutFactor, doPrintToFile)
"""
Specific implementation of CommandSenderReceiver to send multiple telecommands in sequence
"""
def __init__(self, comInterface: ComIF_T, tmtcPrinter: TmTcPrinterT, tmListener: TmListenerT, tmTimeout: int,
tcQueue, tcTimeoutFactor: int, doPrintToFile: bool):
"""
:param comInterface:
:param tmtcPrinter:
:param tmListener:
:param tmTimeout:
:param tcQueue:
:param tcTimeoutFactor:
:param doPrintToFile:
"""
super().__init__(
comInterface=comInterface, tmtcPrinter=tmtcPrinter, tmListener=tmListener, tmTimeout=tmTimeout,
tcSendTimeoutFactor=tcTimeoutFactor, doPrintToFile=doPrintToFile)
self.tcQueue = tcQueue
self.firstReplyReceived = False
self.allRepliesReceived = False
......@@ -27,15 +47,19 @@ class SequentialCommandSenderReceiver(CommandSenderReceiver):
self.run_event.set()
def sendQueueTcAndReceiveTmSequentially(self):
receiverThread = threading.Thread(target=self.checkForMultipleReplies)
receiverThread.start()
time.sleep(0.5)
self.tmListener.modeId = g.modeList[3]
self.tmListener.modeChangeEvent.set()
# receiverThread = threading.Thread(target=self.checkForMultipleReplies)
# receiverThread.start()
# time.sleep(0.5)
self.sendAndReceiveFirstPacket()
# this flag is set in the separate thread !
try:
self.handleTcSending()
except (KeyboardInterrupt, SystemExit):
self.handleInterrupt(receiverThread)
print("Keyboard Interrupt or System Exit detected")
exit()
# self.handleInterrupt(receiverThread)
def handleTcSending(self):
while not self.allRepliesReceived:
......@@ -48,12 +72,12 @@ class SequentialCommandSenderReceiver(CommandSenderReceiver):
if self.doPrintToFile:
print("Exporting output to log file.")
self.tmtcPrinter.printToFile()
self.comInterface.performListenerMode()
# self.comInterface.performListenerMode()
def handleInterrupt(self, receiverThread):
print("Keyboard Interrupt detected")
self.run_event.clear()
receiverThread.join()
# def handleInterrupt(self, receiverThread):
# print("Keyboard Interrupt detected")
# self.run_event.clear()
# receiverThread.join()
def performNextTcSend(self):
# this flag is set in the separate receiver thread too
......@@ -103,7 +127,7 @@ class SequentialCommandSenderReceiver(CommandSenderReceiver):
def handleTelemetrySequence(self):
if self.run_event.is_set():
success = self.checkForOneTelemetrySequence()
success = self.tmListener.checkForOneTelemetrySequence()
if success:
# set this flag so the other thread can send the next telecommand
self.replyReceived = True
......
......@@ -9,41 +9,42 @@
"""
from sendreceive.OBSW_CommandSenderReceiver import CommandSenderReceiver
from comIF.OBSW_ComInterface import ComIF_T
import threading
import time
from utility.OBSW_TmTcPrinter import TmTcPrinterT
from sendreceive.OBSW_TmListener 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, pusPacketTuple, tmTimeout, tcTimeoutFactor, doPrintToFile):
def __init__(self, comInterface: ComIF_T, tmtcPrinter: TmTcPrinterT, tmListener: TmListenerT,
pusPacketTuple: tuple, tmTimeout: int, tcTimeoutFactor: int, 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, tmtcPrinter, tmTimeout, tcTimeoutFactor, doPrintToFile)
super().__init__(comInterface=comInterface, tmListener=tmListener, tmtcPrinter=tmtcPrinter, tmTimeout=tmTimeout,
tcSendTimeoutFactor=tcTimeoutFactor, doPrintToFile=doPrintToFile)
self.pusPacketTuple = pusPacketTuple
try:
(self.pusPacketInfo, self.pusPacket) = self.pusPacketTuple
except TypeError:
print("Invalid queue entry detected")
logging.exception("Error: ")
exit()
def sendSingleTcAndReceiveTm(self):
print("Starting listener thread")
threading.Thread(target=self.receiveReply).start()
self.tmListener.modeId = g.modeList[2]
self.tmListener.modeChangeEvent.set()
self.comInterface.sendTelecommand(self.pusPacket, self.pusPacketInfo)
while not self.replyReceived:
# wait until reply is received
time.sleep(3)
super().checkForFirstReply()
if self.replyReceived:
print("Listening for packages ...")
self.comInterface.performListenerMode()
# runs in separate thread. sends TC again if no TM is received after timeout
def receiveReply(self):
while not self.replyReceived:
super().checkForFirstReply()
......@@ -10,35 +10,62 @@
"""
import time
import threading
from typing import TypeVar
from comIF.OBSW_ComInterface import ComIF_T
import config.OBSW_Config as g
TmListenerT = TypeVar('TmListenerT', bound='TmListener')
class TmListener:
def __init__(self, comInterface: ComIF_T):
self.tmTimeout = g.tmTimeout
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.mode = 0
self.modeId = g.modeList[1]
self.active = True
self.listenerThread = threading.Thread(target=self.performOperation())
self.listenerThread = threading.Thread(target=self.performOperation)
self.modeChangeEvent = threading.Event()
# maybe we will just make the thread daemonic...
self.terminationEvent = threading.Event()
self.replyEvent = threading.Event()
def start(self):
self.listenerThread.start()
def performOperation(self):
while self.active:
if self.mode == 0:
self.defaultOperation()
self.defaultOperation()
def defaultOperation(self):
while not self.modeChangeEvent.is_set():
while not self.terminationEvent.is_set():
self.comInterface.pollInterface()
if self.modeChangeEvent.is_set():
self.performModeOperation()
def performModeOperation(self):
"""
By setting the modeChangeEvent with set() and specifying the mode variable,
the TmListener is instructed to perform certain operations.
:return:
"""
if self.modeId == g.modeList[1]:
self.modeChangeEvent.clear()
elif self.modeId == g.modeList[2]:
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()
elif self.modeId == g.modeList[3]:
pass
def checkForOneTelemetrySequence(self):
tmReady = self.comInterface.dataAvailable(g.tmTimeout * g.tcSendTimeoutFactor)
tmReady = self.comInterface.dataAvailable(self.tmTimeout * self.tcTimeoutFactor)
if tmReady is False:
return False
else:
......@@ -55,15 +82,3 @@ class TmListener:
if self.tmTimeout is not g.tmTimeout:
self.tmTimeout = g.tmTimeout
return True
# checks for replies. if no reply is received, send telecommand again
def checkForFirstReply(self):
success = self.checkForOneTelemetrySequence()
if success:
self.replyReceived = True
else:
if len(self.pusPacket) == 0:
print("Command Sender Receiver: No command has been sent yet")
else:
print("Command Sender Receiver: Sending command again")
self.comInterface.sendTelecommand(self.pusPacket, self.pusPacketInfo)
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment