diff --git a/.gitignore b/.gitignore index 6a2160e6a4af03358cfeebef7471e2753e105836..e79337e8feef5d626089a78b32af08acea338276 100644 --- a/.gitignore +++ b/.gitignore @@ -11,16 +11,15 @@ _dependencies .idea .idea/* +__pycache__ .project .cproject -__pycache__ - *.lnk *.tmp *.open *.ini generators/*.csv -/AT91/ +tmtc_log.txt \ No newline at end of file diff --git a/OBSW_Config.py b/OBSW_Config.py index 7dfe133b9cbf5e65e1cd12f5e6e090cd42d405cf..e555f56be57245bafd1527260f85e2db5f4ad9e8 100644 --- a/OBSW_Config.py +++ b/OBSW_Config.py @@ -26,8 +26,13 @@ recAddress = 0 sendAddress = 0 sockSend = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sockReceive = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - +sockSend.setblocking(0) # Print Settings printToFile = False printRawTmData = False + +def keyboardInterruptHandler(): + print("Disconnect registered") + disconnect = bytearray([0, 0, 0, 0, 0]) + sockSend.sendto(disconnect, sendAddress) diff --git a/OBSW_UdpClient.py b/OBSW_UdpClient.py index 80e05e9909d8b802fc99ef19346d7ed9520d4f4a..63fa2a2284bf8300efe2ece0172d804d43eb5a11 100644 --- a/OBSW_UdpClient.py +++ b/OBSW_UdpClient.py @@ -54,8 +54,10 @@ import sys import atexit +import signal import queue import socket +import time import unittest import argparse @@ -80,33 +82,36 @@ modeList = { def main(): args = parseInputArguments() setGlobals(args) + if g.modeId == "GUIMode": + print("GUI not implemented yet") + exit() + setUpSocket() + atexit.register(g.keyboardInterruptHandler) print("Attempting to connect") connectToBoard() - if g.modeId == "GUIMode": - pass - elif g.modeId == "ListenerMode": + if g.modeId == "ListenerMode": Receiver = CommandSenderReceiver(g.displayMode, g.tmTimeout, g.tcSendTimeoutFactor, g.printToFile) Receiver.performListenerMode() elif g.modeId == "SingleCommandMode": pusPacketTuple = commandPreparation() SenderAndReceiver = SingleCommandSenderReceiver(g.displayMode, pusPacketTuple, g.tmTimeout, - g.tcSendTimeoutFactor, g.printToFile) + g.tcSendTimeoutFactor, True, g.printToFile) SenderAndReceiver.sendSingleTcAndReceiveTm() elif g.modeId == "ServiceTestMode": serviceQueue = queue.Queue() SenderAndReceiver = SequentialCommandSenderReceiver(g.displayMode, g.tmTimeout, serviceTestSelect(g.service, serviceQueue), - g.tcSendTimeoutFactor, g.printToFile) + g.tcSendTimeoutFactor, True, g.printToFile) SenderAndReceiver.sendQueueTcAndReceiveTmSequentially() elif g.modeId == "SoftwareTestMode": allTcQueue = createTotalTcQueue() SenderAndReceiver = SequentialCommandSenderReceiver(g.displayMode, g.tmTimeout, - allTcQueue, g.tcSendTimeoutFactor, g.printToFile) + allTcQueue, g.tcSendTimeoutFactor, True, g.printToFile) SenderAndReceiver.sendQueueTcAndReceiveTmSequentially() elif g.modeId == "OBSWUnitTest": @@ -192,13 +197,18 @@ def setUpSocket(): g.sockReceive.setblocking(False) -def keyboardInterruptHandler(): - print("The End !") - disconnect = bytearray([0, 0, 0, 0, 0]) - g.sockSend.sendto(disconnect, g.sendAddress) +class GracefulKiller: + kill_now = False + + def __init__(self): + signal.signal(signal.SIGINT, self.exit_gracefully) + signal.signal(signal.SIGTERM, self.exit_gracefully) + + def exit_gracefully(self): + self.kill_now = True + print("I was killed") if __name__ == "__main__": - atexit.register(keyboardInterruptHandler) main() diff --git a/sendreceive/OBSW_CommandSenderReceiver.py b/sendreceive/OBSW_CommandSenderReceiver.py index 7c8259b3abde80d4bbacb47cb314489a0b297130..b127803f6e121ee241d6db2e4873f8849b0a796d 100644 --- a/sendreceive/OBSW_CommandSenderReceiver.py +++ b/sendreceive/OBSW_CommandSenderReceiver.py @@ -15,6 +15,7 @@ This is still experimental. import OBSW_Config as g import select import time +import atexit from utility.OBSW_TmTcPrinter import TmtcPrinter from tm.OBSW_TmPacket import PUSTelemetryFactory @@ -22,10 +23,11 @@ from tm.OBSW_TmPacket import PUSTelemetryFactory # Generic TMTC SendReceive class which is implemented # by specific implementations (e.g. SingleCommandSenderReceiver) class CommandSenderReceiver: - def __init__(self, displayMode, tmTimeout, tcSendTimeoutFactor, doPrintToFile): + def __init__(self, displayMode, tmTimeout, tcSendTimeoutFactor, printTc, doPrintToFile): self.displayMode = displayMode - # TODO: Make this variable modifiable ! - self.timeoutInSeconds = tmTimeout + self.tmTimeout = tmTimeout + self.printTc = printTc + self.replyReceived = False self.tmReady = False self.pusPacketInfo = [] @@ -36,10 +38,11 @@ class CommandSenderReceiver: self.timeoutCounter = 0 self.tcSendTimeoutFactor = tcSendTimeoutFactor self.doPrintToFile = doPrintToFile + self.queueEntryIsTelecommand = True # checks for replies. if no reply is received, send telecommand again def checkForFirstReply(self): - self.tmReady = select.select([g.sockReceive], [], [], self.timeoutInSeconds * self.tcSendTimeoutFactor) + self.tmReady = select.select([g.sockReceive], [], [], self.tmTimeout * self.tcSendTimeoutFactor) if self.tmReady[0]: self.checkForOneTelemetrySequence() self.replyReceived = True @@ -54,10 +57,23 @@ class CommandSenderReceiver: while self.tmReady[0]: packet = self.receiveTelemetry() self.tmtcPrinter.printTelemetry(packet) - self.tmReady = select.select([g.sockReceive], [], [], self.timeoutInSeconds / 1.5) + self.tmReady = select.select([g.sockReceive], [], [], self.tmTimeout / 1.5) + + def checkQueueEntry(self, tcQueueEntry): + (self.pusPacketInfo, self.pusPacket) = tcQueueEntry + self.queueEntryIsTelecommand = False + if self.pusPacketInfo == "wait": + waitTime = self.pusPacket + time.sleep(waitTime) + elif self.pusPacketInfo == "print": + printString = self.pusPacket + self.tmtcPrinter.printString(printString) + else: + self.queueEntryIsTelecommand = True def sendTelecommand(self): - self.tmtcPrinter.displaySentCommand(self.pusPacketInfo, self.pusPacket, self.displayMode) + if self.printTc: + self.tmtcPrinter.displaySentCommand(self.pusPacketInfo, self.pusPacket, self.displayMode) g.sockSend.sendto(self.pusPacket, g.sendAddress) def performListenerMode(self): @@ -75,7 +91,7 @@ class CommandSenderReceiver: exit() if self.start_time != 0: self.elapsed_time = time.time() - self.start_time - if self.elapsed_time > self.timeoutInSeconds * self.tcSendTimeoutFactor: + if self.elapsed_time > self.tmTimeout * self.tcSendTimeoutFactor: print("Timeout ! Sending Telecommand again") self.sendTelecommand() self.timeoutCounter = self.timeoutCounter + 1 diff --git a/sendreceive/OBSW_MultipleCommandsSenderReceiver.py b/sendreceive/OBSW_MultipleCommandsSenderReceiver.py index 55c62d0f03d1240802d73f3e4d7fb6cbc724f973..1b0ca479638db99644630120a426844f6b639901 100644 --- a/sendreceive/OBSW_MultipleCommandsSenderReceiver.py +++ b/sendreceive/OBSW_MultipleCommandsSenderReceiver.py @@ -19,7 +19,7 @@ import select class MultipleCommandSenderReceiver(SequentialCommandSenderReceiver): def __init__(self, displayMode, tcQueue, tmTimeout, waitIntervals, waitTime, printTm, printTc, tcTimeoutFactor, doPrintToFile): - super().__init__(displayMode, tmTimeout, tcQueue, tcTimeoutFactor, doPrintToFile) + super().__init__(displayMode, tmTimeout, tcQueue, tcTimeoutFactor, printTc, doPrintToFile) self.waitIntervals = waitIntervals self.waitTime = waitTime self.printTm = printTm @@ -32,18 +32,18 @@ class MultipleCommandSenderReceiver(SequentialCommandSenderReceiver): def sendTcQueueAndReturnTcInfo(self): receiverThread = threading.Thread(target=self.checkForMultipleReplies) receiverThread.start() - self.sendAllQueue() + time.sleep(1) try: - self.handleTcSending() + self.sendAllQueue() + self.handleTcResending() except (KeyboardInterrupt, SystemExit): super().handleInterrupt(receiverThread) return self.tcInfoQueue, self.tmInfoQueue - def handleTcSending(self): + def handleTcResending(self): while not self.allRepliesReceived: if self.tcQueue.empty(): if self.start_time == 0: - print("TC queue empty") self.start_time = time.time() self.checkForTimeout() if self.doPrintToFile: @@ -56,11 +56,10 @@ class MultipleCommandSenderReceiver(SequentialCommandSenderReceiver): waitCounter = self.handleWaiting(waitCounter) def sendAndPrintTc(self): - (self.pusPacketInfo, self.pusPacket) = self.tcQueue.get() - if self.printTc: - self.tmtcPrinter.displaySentCommand(self.pusPacketInfo, self.pusPacket, self.displayMode) - self.tcInfoQueue.put(self.pusPacketInfo) - g.sockSend.sendto(self.pusPacket, g.sendAddress) + self.checkQueueEntry(self.tcQueue.get()) + if self.queueEntryIsTelecommand: + self.tcInfoQueue.put(self.pusPacketInfo) + self.sendTelecommand() def handleWaiting(self, waitCounter): time.sleep(0.5) @@ -73,26 +72,14 @@ class MultipleCommandSenderReceiver(SequentialCommandSenderReceiver): super().checkForMultipleReplies() def handleReplyListening(self): - super().handleReplyListening() - - def handleTelemetrySequence(self): - if self.run_event.is_set(): - self.checkForOneTelemetrySequence() - if self.tcQueue.empty(): - print("Setting flag all reply received in handleTelemetrySequence") - self.allRepliesReceived = True - - def handleFirstReplyListening(self): - super().handleFirstReplyListening() - - # check for one sequence of replies for a telecommand (e.g. TM[1,1] , TM[1,7] ...) - def checkForOneTelemetrySequence(self): - while self.tmReady[0]: + self.tmReady = select.select([g.sockReceive], [], [], 2.0) + if self.tmReady[0]: self.receiveTelemetryAndStoreInformation() - self.tmReady = select.select([g.sockReceive], [], [], self.timeoutInSeconds / 1.5) - print("I checked the sequence") + time.sleep(0.5) if self.tcQueue.empty(): - print("After checking, the TC queue is empty") + print("TC queue empty. Listening for a few more seconds ... ") + start_time = time.time() + self.handleLastRepliesListening(start_time) self.allRepliesReceived = True def receiveTelemetryAndStoreInformation(self): @@ -102,3 +89,15 @@ class MultipleCommandSenderReceiver(SequentialCommandSenderReceiver): tmInfo = packet.packTmInformation() self.tmInfoQueue.put(tmInfo) + def handleLastRepliesListening(self, start_time): + elapsed_time_seconds = 0 + while elapsed_time_seconds < self.tmTimeout: + elapsed_time_seconds = time.time() - start_time + self.tmReady = select.select([g.sockReceive], [], [], 2.0) + if self.tmReady[0]: + self.receiveTelemetryAndStoreInformation() + + + + + diff --git a/sendreceive/OBSW_SequentialSenderReceiver.py b/sendreceive/OBSW_SequentialSenderReceiver.py index 0ec83305fbc44d57616c98e29e723afcdb479413..10eef52789d1c73150f24f54218ffbc7460841ab 100644 --- a/sendreceive/OBSW_SequentialSenderReceiver.py +++ b/sendreceive/OBSW_SequentialSenderReceiver.py @@ -17,8 +17,8 @@ import select # Specific implementation of CommandSenderReceiver to send multiple telecommands in sequence class SequentialCommandSenderReceiver(CommandSenderReceiver): - def __init__(self, displayMode, tmTimeout, tcQueue, tcTimeoutFactor, doPrintToFile): - super().__init__(displayMode, tmTimeout, tcTimeoutFactor, doPrintToFile) + def __init__(self, displayMode, tmTimeout, tcQueue, tcTimeoutFactor, printTc, doPrintToFile): + super().__init__(displayMode, tmTimeout, tcTimeoutFactor, printTc, doPrintToFile) self.tcQueue = tcQueue self.firstReplyReceived = False self.allRepliesReceived = False @@ -66,20 +66,21 @@ class SequentialCommandSenderReceiver(CommandSenderReceiver): self.checkForTimeout() def sendAndReceiveFirstPacket(self): - (self.pusPacketInfo, self.pusPacket) = self.tcQueue.get() - self.sendTelecommand() + self.checkQueueEntry(self.tcQueue.get()) + if self.queueEntryIsTelecommand: + self.sendTelecommand() + else: + self.sendAndReceiveFirstPacket() def sendNextTelecommand(self): - (self.pusPacketInfo, self.pusPacket) = self.tcQueue.get() - if self.pusPacketInfo == "wait": - waitTime = self.pusPacket - time.sleep(waitTime) - else: - self.tmtcPrinter.displaySentCommand(self.pusPacketInfo, self.pusPacket, self.displayMode) + self.checkQueueEntry(self.tcQueue.get()) + if self.queueEntryIsTelecommand: + self.sendTelecommand() self.replyReceived = False - g.sockSend.sendto(self.pusPacket, g.sendAddress) + else: + self.sendNextTelecommand() - # this function runs is a separate thread andchecks for replies. If the first reply has not been received, + # this function runs is a separate thread and checks for replies. If the first reply has not been received, # it attempts to send the telecommand again. # if the tc queue is empty and the last telemetry sequence has been received, # a flag is set to transition into listener mode @@ -87,10 +88,10 @@ class SequentialCommandSenderReceiver(CommandSenderReceiver): while not self.allRepliesReceived and self.run_event.is_set(): # listen for duration timeoutInSeconds for replies self.handleReplyListening() - self.tmReady = select.select([g.sockReceive], [], [], 5.0) def handleReplyListening(self): if self.firstReplyReceived: + self.tmReady = select.select([g.sockReceive], [], [], 2.0) if self.tmReady[0]: self.handleTelemetrySequence() else: diff --git a/tc/OBSW_TcPacker.py b/tc/OBSW_TcPacker.py index 8c49f4f54f13e9d8834312816c6ae55aee69b2e7..a6a8bda55d6bb698199817718d45ac915dc00714 100644 --- a/tc/OBSW_TcPacker.py +++ b/tc/OBSW_TcPacker.py @@ -133,12 +133,15 @@ def packService8TestInto(tcQueue): def packService17TestInto(tcQueue): # ping test + tcQueue.put(("print", "Testing Service 17: Ping Test")) command = PUSTelecommand(service=17, subservice=1, SSC=1700) tcQueue.put(command.packCommandTuple()) # enable event + tcQueue.put(("print", "Testing Service 17: Enable Event")) command = PUSTelecommand(service=5, subservice=5, SSC=52) tcQueue.put(command.packCommandTuple()) # test event + tcQueue.put(("print", "Testing Service 17: Trigger event")) command = PUSTelecommand(service=17, subservice=128, SSC=1701) tcQueue.put(command.packCommandTuple()) return tcQueue diff --git a/test/OBSW_UnitTest.py b/test/OBSW_UnitTest.py index 52633cbe65efffad8cc704004af18f2cbdb7f84e..de96f5fa5575d0f2b4e350cf28fc2086b6b64bf7 100644 --- a/test/OBSW_UnitTest.py +++ b/test/OBSW_UnitTest.py @@ -34,7 +34,7 @@ class TestService(unittest.TestCase): def setUpClass(cls): cls.displayMode = "long" # default timeout for receiving TM, set in subclass manually - cls.tmTimeout = 15 + cls.tmTimeout = 3 # wait intervals between tc send bursts. # Example: [2,4] sends to send 2 tc from queue and wait, then sends another 2 and wait again cls.waitIntervals = [] @@ -43,7 +43,7 @@ class TestService(unittest.TestCase): # default wait time between tc send bursts cls.waitTime = 5.0 cls.testQueue = queue.Queue() - cls.tcTimeoutFactor = 2.0 + cls.tcTimeoutFactor = 3.0 connectToBoard() def performTestingAndGenerateAssertionDict(self): @@ -203,6 +203,7 @@ class TestService17(TestService): print("Testing Service 17") cls.waitIntervals = [2] cls.waitTime = 2 + cls.tmTimeout = 2 packService17TestInto(cls.testQueue) def test_Service17(self): diff --git a/utility/OBSW_TmTcPrinter.py b/utility/OBSW_TmTcPrinter.py index 8e41f0013cda5b975de8ea4581dcb81f814587e1..b61113d02ceb275f9b63bddc1c267d1ae3a7895a 100644 --- a/utility/OBSW_TmTcPrinter.py +++ b/utility/OBSW_TmTcPrinter.py @@ -105,6 +105,12 @@ class TmtcPrinter: strToPrint += ']' return strToPrint + def printString(self, string): + self.printBuffer = string + print(self.printBuffer) + if self.doPrintToFile: + self.addPrintBufferToFileBuffer() + def addPrintBufferToFileBuffer(self): if self.doPrintToFile: self.fileBuffer = self.fileBuffer + self.printBuffer + "\n"