Exemplo n.º 1
0
    def setup_method(self, method):

        if testSerialPort:
            serialPort = serial.Serial(port=testSerialPort,
                                       baudrate=57600,
                                       timeout=0)
        else:
            serialPort = []

        self.nodeParams = NodeParams(configFile=configFilePath)
        self.nodeParams.commStartTime = time.time()
        self.nodeParams.config.commConfig['transmitSlot'] = 1
        self.radio = Radio(
            serialPort, {
                'uartNumBytesToRead':
                self.nodeParams.config.uartNumBytesToRead,
                'rxBufferSize': 2000
            })
        commProcessor = CommProcessor([TDMACmdProcessor, TestCmdProcessor],
                                      self.nodeParams)
        msgParser = SLIPMsgParser(
            {'parseMsgMax': self.nodeParams.config.parseMsgMax})
        self.tdmaComm = TDMAComm(commProcessor, self.radio, msgParser,
                                 self.nodeParams)
        self.tdmaComm.nodeParams.frameStartTime = time.time()
Exemplo n.º 2
0
    def setup_method(self, method):
        
        # Create NodeConfig instance
        self.nodeConfig = NodeConfig(configFilePath)

        if method.__name__ != "test_init":
            self.nodeParams = NodeParams(config=self.nodeConfig) # Create NodeParams instance
Exemplo n.º 3
0
    def test_init(self):
        """Test NodeParams init function."""

        # Test that init function loads node configuration from file
        print("Testing init with configFile")
        nodeParams = NodeParams(configFile=configFilePath)
        assert (nodeParams.config.__dict__ == self.nodeConfig.__dict__)

        # Test that init function loads node configuration from provided config
        nodeParams = NodeParams(config=self.nodeConfig)
        assert (nodeParams.config.__dict__ == self.nodeConfig.__dict__)
Exemplo n.º 4
0
 def setup_method(self, method):
     self.nodeStatus = [NodeState(i + 1) for i in range(5)]
     self.nodeParams = NodeParams(configFile=configFilePath)
     msgParser = MsgParser(
         {'parseMsgMax': self.nodeParams.config.parseMsgMax}, SLIPMsg(256))
     radio = Radio(
         [], {
             'uartNumBytesToRead':
             self.nodeParams.config.uartNumBytesToRead,
             'rxBufferSize': 2000
         })
     self.comm = TDMAComm([TDMACmdProcessor], radio, msgParser,
                          self.nodeParams)
Exemplo n.º 5
0
class TestNodeParams:
    def setup_method(self, method):

        # Create NodeConfig instance
        self.nodeConfig = NodeConfig(configFilePath)

        if method.__name__ != "test_init":
            self.nodeParams = NodeParams(
                config=self.nodeConfig)  # Create NodeParams instance

    def test_init(self):
        """Test NodeParams init function."""

        # Test that init function loads node configuration from file
        print("Testing init with configFile")
        nodeParams = NodeParams(configFile=configFilePath)
        assert (nodeParams.config.__dict__ == self.nodeConfig.__dict__)

        # Test that init function loads node configuration from provided config
        nodeParams = NodeParams(config=self.nodeConfig)
        assert (nodeParams.config.__dict__ == self.nodeConfig.__dict__)

    def test_getCmdCounter(self):
        """Test NodeParams command counter get function."""

        # Test getting random command counter
        counter = self.nodeParams.get_cmdCounter()
        assert (counter >= 1)  # value within range
        assert (counter <= 65536)  # value within range
Exemplo n.º 6
0
    def setup_method(self, method):
        # Create CommProcessor instance
        nodeParams = NodeParams(configFile=configFilePath)
        self.commProcessor = CommProcessor([PixhawkCmdProcessor], nodeParams)
        self.serialComm = SerialComm([], [], nodeParams.config)

        # Truth data
        self.crcLength = 2
Exemplo n.º 7
0
class TestNodeCmdProcessor:
    def setup_method(self, method):
        self.nodeStatus = [NodeState(i + 1) for i in range(5)]
        self.nodeParams = NodeParams(configFile=configFilePath)
        msgParser = MsgParser(
            {'parseMsgMax': self.nodeParams.config.parseMsgMax}, SLIPMsg(256))
        radio = Radio(
            [], {
                'uartNumBytesToRead':
                self.nodeParams.config.uartNumBytesToRead,
                'rxBufferSize': 2000
            })
        self.comm = SerialComm([NodeCmdProcessor], self.nodeParams, radio,
                               msgParser)

    def test_processMsg(self):
        """Test processMsg method of NodeCmdProcessor."""

        # Test processing of all NodeCmds
        for cmdId in cmdsToTest:
            cmdMsg = testCmds[cmdId].serialize()
            print(cmdId)
            assert (self.comm.processMsg(cmdMsg,
                                         args={
                                             'nodeStatus': self.nodeStatus,
                                             'comm': self.comm,
                                             'clock': self.nodeParams.clock
                                         }) == True)
            if cmdId == NodeCmds['NoOp']:
                pass
            elif cmdId == NodeCmds['ParamUpdate']:
                assert (self.nodeParams.config.parseMsgMax == unpack(
                    '=H', testCmds[cmdId].cmdData['paramValue'])[0])
            elif cmdId == NodeCmds['ConfigUpdate']:
                assert (self.nodeParams.newConfig != None
                        )  # new config staged for updating
                cmdResponse = None
                for entry in self.nodeParams.cmdResponse:
                    if (entry['cmdId'] == NodeCmds['ConfigUpdate']):
                        cmdResponse = entry
                        break
                assert (cmdResponse != None)
                assert (cmdResponse['cmdResponse'] == 1)

    def test_malformedCmd(self):
        # Test command with improper message contents
        badMsg = packHeader(
            createHeader([
                CmdDict[NodeCmds['GCSCmd']].header,
                [NodeCmds['GCSCmd'], 0,
                 self.nodeParams.get_cmdCounter()]
            ]))  # header only
        assert (self.comm.processMsg(badMsg,
                                     args={
                                         'nodeStatus': self.nodeStatus,
                                         'comm': self.comm,
                                         'clock': self.nodeParams.clock
                                     }) == False)
Exemplo n.º 8
0
 def setup_method(self, method):
     from mesh.generic.xbeeRadio import XbeeRadio
     self.nodeParams = NodeParams(configFile=configFilePath)
     self.xbeeRadio = XbeeRadio(
         [], {
             'uartNumBytesToRead':
             self.nodeParams.config.uartNumBytesToRead,
             'rxBufferSize': 2000
         }, "P8_12")
Exemplo n.º 9
0
 def setup_method(self, method):
     self.nodeStatus = [NodeState(i + 1) for i in range(5)]
     self.nodeParams = NodeParams(configFile=configFilePath)
     radio = Radio(
         [], {
             'uartNumBytesToRead':
             self.nodeParams.config.uartNumBytesToRead,
             'rxBufferSize': 2000
         })
     self.comm = SerialComm([GndCmdProcessor], self.nodeParams, radio, [])
Exemplo n.º 10
0
    def setup_method(self, method):

        self.nodeParams = NodeParams(configFile=configFilePath)
        self.nodeParams.config.commConfig['transmitSlot'] = 1
        self.radio = Radio(None, {'uartNumBytesToRead': self.nodeParams.config.uartNumBytesToRead, 'rxBufferSize': 2000})
        msgParser = MsgParser({'parseMsgMax': self.nodeParams.config.parseMsgMax}, HDLCMsg(256))
        self.tdmaComm = TDMAComm([TDMACmdProcessor], self.radio, msgParser, self.nodeParams)
    
        # Test article
        self.meshController = MeshController(self.nodeParams, self.tdmaComm)
Exemplo n.º 11
0
 def setup_method(self, method):
     self.serialPort = serial.Serial(port=testSerialPort,
                                     baudrate=57600,
                                     timeout=0)
     self.nodeParams = NodeParams(configFile=configFilePath)
     self.li1Radio = Li1Radio(
         self.serialPort, {
             'uartNumBytesToRead':
             self.nodeParams.config.uartNumBytesToRead,
             'rxBufferSize': 2000
         })
Exemplo n.º 12
0
 def setup_method(self, method):
     self.nodeParams = NodeParams(configFile=configFilePath)
     self.serialPort = serial.Serial(port=testSerialPort,
                                     baudrate=57600,
                                     timeout=0)
     self.radio = Radio(
         self.serialPort, {
             'uartNumBytesToRead':
             self.nodeParams.config.uartNumBytesToRead,
             'rxBufferSize': 2000
         })
     self.serialComm = SerialComm([NodeCmdProcessor], self.nodeParams,
                                  self.radio, [])
Exemplo n.º 13
0
 def setup_method(self, method):
     self.nodeParams = NodeParams(configFile=configFilePath)
     self.serialPort = serial.Serial(port=testSerialPort,
                                     baudrate=57600,
                                     timeout=0)
     self.radio = Radio(
         self.serialPort, {
             'uartNumBytesToRead':
             self.nodeParams.config.uartNumBytesToRead,
             'rxBufferSize': 2000
         })
     msgParser = SLIPMsgParser(
         {'parseMsgMax': self.nodeParams.config.parseMsgMax})
     self.comm = SerialComm([], self.nodeParams, self.radio, msgParser)
Exemplo n.º 14
0
    def setup_method(self, method):

        if testSerialPort:
            serialPort = serial.Serial(port=testSerialPort, baudrate=57600, timeout=0)
        else:
            serialPort = []

        self.nodeParams = NodeParams(configFile=configFilePath)
        self.nodeParams.config.commConfig['transmitSlot'] = 1
        self.radio = Radio(serialPort, {'uartNumBytesToRead': self.nodeParams.config.uartNumBytesToRead, 'rxBufferSize': 2000})
        msgParser = MsgParser({'parseMsgMax': self.nodeParams.config.parseMsgMax}, HDLCMsg(256))
        self.tdmaComm = TDMAComm([TDMACmdProcessor], self.radio, msgParser, self.nodeParams)
  
        # Flush radio
        self.radio.serial.read(100)
Exemplo n.º 15
0
 def setup_method(self, method):
     self.nodeParams = NodeParams(configFile=configFilePath)
     self.serialPort = serial.Serial(port=testSerialPort,
                                     baudrate=57600,
                                     timeout=0)
     commProcessor = CommProcessor([PixhawkCmdProcessor], self.nodeParams)
     radio = Radio(
         self.serialPort, {
             'uartNumBytesToRead':
             self.nodeParams.config.uartNumBytesToRead,
             'rxBufferSize': 2000
         })
     msgParser = SLIPMsgParser(
         {'parseMsgMax': self.nodeParams.config.parseMsgMax})
     self.nodeComm = NodeComm(commProcessor, radio, msgParser,
                              self.nodeParams)
     pass
Exemplo n.º 16
0
    def setup_method(self, method):
        self.nodeParams = NodeParams(configFile=configFilePath)

        # Setup comms
        self.serialConfig = {
            'uartNumBytesToRead': self.nodeParams.config.uartNumBytesToRead,
            'rxBufferSize': self.nodeParams.config.rxBufferSize
        }
        self.serialPort = serial.Serial(port=testSerialPort,
                                        baudrate=57600,
                                        timeout=0)
        radio = Radio(self.serialPort, self.serialConfig)
        nodeComm = SerialComm([], radio, [])

        #self.FCSerialPort = serial.Serial(port=testSerialPort, baudrate=57600, timeout=0)
        #radio = Radio(self.FCSerialPort, serialConfig)
        FCComm = SerialComm([], radio, [])

        # Create executive
        self.nodeExecutive = NodeExecutive(self.nodeParams, None, [nodeComm],
                                           FCComm, [])
Exemplo n.º 17
0
class TestTDMACmdProcessor:
    def setup_method(self, method):
        self.nodeStatus = [NodeState(i + 1) for i in range(5)]
        self.nodeParams = NodeParams(configFile=configFilePath)
        msgParser = MsgParser(
            {'parseMsgMax': self.nodeParams.config.parseMsgMax}, SLIPMsg(256))
        radio = Radio(
            [], {
                'uartNumBytesToRead':
                self.nodeParams.config.uartNumBytesToRead,
                'rxBufferSize': 2000
            })
        self.comm = TDMAComm([TDMACmdProcessor], radio, msgParser,
                             self.nodeParams)

    def test_validateBlockTxRequest(self):
        """Test validateBlockTxRequest  method of TDMACmdProcessor."""
        # Test request rejected if start time passed
        contents = {
            'startTime': time.time() - 1.0,
            'length': self.nodeParams.config.commConfig['maxTxBlockSize']
        }
        assert (validateBlockTxRequest(contents, [], self.nodeParams) == False)

        # Test request rejected if block too long
        contents = {
            'startTime': time.time() + 1.0,
            'length': self.nodeParams.config.commConfig['maxTxBlockSize'] + 1
        }
        assert (validateBlockTxRequest(contents, [], self.nodeParams) == False)

        # Test for request acceptance
        contents = {
            'startTime': time.time() + 1.0,
            'length': self.nodeParams.config.commConfig['maxTxBlockSize']
        }
        assert (validateBlockTxRequest(contents, [], self.nodeParams) == True)

    def test_processMsg(self):
        """Test processMsg method of TDMACmdProcessor."""

        # Test processing of all TDMACmds
        for cmdId in cmdsToTest:
            self.comm.networkMsgQueue = [
            ]  # clear command queue to check for additions after command processing
            assert (self.comm.processMsg(testCmds[cmdId].serialize(),
                                         args={
                                             'nodeStatus': self.nodeStatus,
                                             'comm': self.comm,
                                             'clock': self.nodeParams.clock
                                         }) == True)
            if cmdId == TDMACmds['TimeOffset']:
                sourceId = testCmds[cmdId].header['header']['sourceId']
                assert (self.nodeStatus[sourceId - 1].timeOffset ==
                        testCmds[cmdId].cmdData['nodeStatus'].timeOffset
                        )  # verify time offset parsed correctly
            elif cmdId == TDMACmds['MeshStatus']:
                assert (self.comm.commStartTime ==
                        testCmds[cmdId].cmdData['commStartTimeSec']
                        )  # comm start time stored
            elif cmdId == TDMACmds['LinkStatus']:
                msgNodeId = testCmds[cmdId].cmdData['nodeId']
                for i in range(0, self.nodeParams.config.maxNumNodes):
                    assert (self.nodeParams.linkStatus[msgNodeId - 1][i] ==
                            testCmds[cmdId].cmdData['linkStatus'][msgNodeId -
                                                                  1][i])
            elif cmdId == TDMACmds['ConfigUpdate']:
                assert (self.nodeParams.newConfig != None
                        )  # new config staged for updating
                assert (len(self.comm.networkMsgQueue) > 0)
            elif cmdId == TDMACmds['NetworkRestart']:
                assert (len(self.comm.networkMsgQueue) > 0)

        # Resend and test that commStartTime is not updated once it has previously been set
        cmdId = TDMACmds['MeshStatus']
        self.comm.commStartTime = testCmds[cmdId].cmdData[
            'commStartTimeSec'] - 1
        assert (self.comm.processMsg(testCmds[cmdId].serialize(),
                                     args={
                                         'nodeStatus': self.nodeStatus,
                                         'comm': self.comm,
                                         'clock': self.nodeParams.clock
                                     }) == True)
        assert (self.comm.commStartTime !=
                testCmds[cmdId].cmdData['commStartTimeSec']
                )  # comm start time should not have been updated

    def test_blockTxCmdsProcessing(self):
        """Test processing of block transmit related commands."""
        return  # skip this test

        self.comm.commStartTime = self.nodeParams.clock.getTime() - 1.0
        blockReqID = random.randint(1, 255)  # just a random "unique" number
        startTime = int(self.nodeParams.clock.getTime() + 10.0)
        length = self.nodeParams.config.commConfig['maxTxBlockSize']
        txNode = 1

        ## TDMACmds['BlockTxRequest']
        cmdMsg = Command(TDMACmds['BlockTxRequest'], {
            'blockReqID': blockReqID,
            'startTime': startTime,
            'length': length
        }, [
            TDMACmds['BlockTxRequest'], txNode,
            self.nodeParams.get_cmdCounter()
        ]).serialize(self.nodeParams.clock.getTime())

        # Process and check results
        assert (self.comm.processMsg(cmdMsg,
                                     args={
                                         'nodeStatus': self.nodeStatus,
                                         'comm': self.comm,
                                         'clock': self.nodeParams.clock
                                     }) == True)
        assert (len(self.comm.radio.txBuffer) == calcsize(
            CmdDict[TDMACmds['BlockTxRequestResponse']].packFormat) +
                calcsize(headers['NodeHeader']['format']))  # response sent
        assert (self.comm.blockTxStatus['blockReqID'] == blockReqID)
        assert (self.comm.blockTxStatus['status'] == TDMABlockTxStatus.pending)
        assert (self.comm.blockTxStatus['txNode'] == txNode)
        assert (self.comm.blockTxStatus['startTime'] == startTime)
        assert (self.comm.blockTxStatus['length'] == length)

        ## TDMACmds['BlockTxConfirmed']
        time.sleep(0.01)
        cmdMsg = Command(TDMACmds['BlockTxConfirmed'], {
            'blockReqID': blockReqID
        }, [
            TDMACmds['BlockTxConfirmed'], txNode,
            self.nodeParams.get_cmdCounter()
        ]).serialize(self.nodeParams.clock.getTime())
        assert (self.comm.processMsg(cmdMsg,
                                     args={
                                         'nodeStatus': self.nodeStatus,
                                         'comm': self.comm,
                                         'clock': self.nodeParams.clock
                                     }) == True)
        assert (
            self.comm.blockTxStatus['status'] == TDMABlockTxStatus.confirmed
        )  # status updated to confirmed

        ## TDMACmds['BlockTxStatus']
        self.comm.resetBlockTxStatus()
        time.sleep(0.01)
        cmdMsg = Command(TDMACmds['BlockTxStatus'], {
            'blockReqID': blockReqID,
            'startTime': startTime,
            'length': length
        }, [
            TDMACmds['BlockTxStatus'], txNode,
            self.nodeParams.get_cmdCounter()
        ]).serialize(self.nodeParams.clock.getTime())
        # Check status updated
        assert (self.comm.processMsg(cmdMsg,
                                     args={
                                         'nodeStatus': self.nodeStatus,
                                         'comm': self.comm,
                                         'clock': self.nodeParams.clock
                                     }) == True)
        assert (len(self.comm.radio.txBuffer) == calcsize(
            CmdDict[TDMACmds['BlockTxRequestResponse']].packFormat) +
                calcsize(headers['NodeHeader']['format']))  # response sent
        assert (self.comm.blockTxStatus['blockReqID'] == blockReqID)
        assert (
            self.comm.blockTxStatus['status'] == TDMABlockTxStatus.confirmed)
        assert (self.comm.blockTxStatus['txNode'] == txNode)
        assert (self.comm.blockTxStatus['startTime'] == startTime)
        assert (self.comm.blockTxStatus['length'] == length)

        # Check status updated to confirmed if only pending
        time.sleep(0.01)
        cmdMsg = Command(TDMACmds['BlockTxStatus'], {
            'blockReqID': blockReqID,
            'startTime': startTime,
            'length': length
        }, [
            TDMACmds['BlockTxStatus'], txNode,
            self.nodeParams.get_cmdCounter()
        ]).serialize(self.nodeParams.clock.getTime())  # update command counter
        self.comm.blockTxStatus['status'] = TDMABlockTxStatus.pending
        assert (self.comm.processMsg(cmdMsg,
                                     args={
                                         'nodeStatus': self.nodeStatus,
                                         'comm': self.comm,
                                         'clock': self.nodeParams.clock
                                     }) == True)
        assert (
            self.comm.blockTxStatus['status'] == TDMABlockTxStatus.confirmed)

        ## TDMACmds['BlockTxRequestResponse']
        time.sleep(0.01)
        self.comm.resetBlockTxStatus()
        self.comm.blockTxStatus[
            'txNode'] = self.nodeParams.config.nodeId  # this node requested block transfer
        self.comm.blockTxStatus['status'] = TDMABlockTxStatus.pending
        cmdMsg = Command(TDMACmds['BlockTxRequestResponse'], {
            'blockReqID': blockReqID,
            "accept": True
        }, [
            TDMACmds['BlockTxRequestResponse'], 1,
            self.nodeParams.get_cmdCounter()
        ]).serialize(self.nodeParams.clock.getTime())
        print(self.nodeParams.config.nodeId)
        self.nodeParams.nodeStatus[
            0].present = True  # mark another node as present
        self.comm.populateBlockResponseList()  # create block response list

        # Test acceptance marked
        assert (self.comm.processMsg(cmdMsg,
                                     args={
                                         'nodeStatus': self.nodeStatus,
                                         'comm': self.comm,
                                         'clock': self.nodeParams.clock
                                     }) == True)
        assert (self.comm.blockTxStatus['blockResponseList'][1] == True)

        # Test rejection marked
        time.sleep(0.01)
        cmdMsg = Command(TDMACmds['BlockTxRequestResponse'], {
            'blockReqID': blockReqID,
            "accept": False
        }, [
            TDMACmds['BlockTxRequestResponse'], 1,
            self.nodeParams.get_cmdCounter()
        ]).serialize(self.nodeParams.clock.getTime())
        assert (self.comm.processMsg(cmdMsg,
                                     args={
                                         'nodeStatus': self.nodeStatus,
                                         'comm': self.comm,
                                         'clock': self.nodeParams.clock
                                     }) == True)
        assert (self.comm.blockTxStatus['blockResponseList'][1] == False)
Exemplo n.º 18
0
    def __init__(self, configFile, meshNum, runFlag):
        super().__init__(name="CommProcess")

        # Node control run flag
        self.nodeControlRunFlag = runFlag

        # Configuration
        self.nodeParams = NodeParams(configFile=configFile)

        # Node/Comm interface
        interfaceConfig = {
            'uartNumBytesToRead': self.nodeParams.config.uartNumBytesToRead,
            'rxBufferSize': self.nodeParams.config.rxBufferSize,
            'ipAddr': self.nodeParams.config.interface['nodeCommIntIP'],
            'readPort': self.nodeParams.config.interface['commRdPort'],
            'writePort': self.nodeParams.config.interface['commWrPort']
        }
        #self.interface = SerialComm([], UDPRadio(interfaceConfig), SLIPMsgParser({'parseMsgMax': self.nodeParams.config.parseMsgMax}))
        self.interface = SerialComm(
            [], self.nodeParams, UDPRadio(interfaceConfig),
            MsgParser({'parseMsgMax': self.nodeParams.config.parseMsgMax},
                      SLIPMsg(256)))  # UDP connection to node control process

        # Interprocess data package (Google protocol buffer interface to node control process)
        self.dataPackage = NodeThreadMsg()
        self.cmdTxLog = {}
        self.lastNodeCmdTime = []

        ## Create comm object
        # Serial connection
        ser = serial.Serial(port=self.nodeParams.config.meshDevices[meshNum],
                            baudrate=self.nodeParams.config.meshBaudrate,
                            timeout=0)

        # Radio
        radioConfig = {
            'uartNumBytesToRead': self.nodeParams.config.uartNumBytesToRead,
            'rxBufferSize': self.nodeParams.config.rxBufferSize
        }
        if (self.nodeParams.config.commConfig['fpga'] == True):
            from mesh.generic.fpgaRadio import FPGARadio
            radio = FPGARadio(ser, radioConfig)
        else:
            if self.nodeParams.config.radios[meshNum] == "Xbee":
                radio = XbeeRadio(ser, radioConfig, "P8_12")
            elif self.nodeParams.config.radios[meshNum] == "Li-1":
                radio = Li1Radio(ser, radioConfig)

        # Message parser
        parserConfig = {'parseMsgMax': self.nodeParams.config.parseMsgMax}
        if self.nodeParams.config.msgParsers[meshNum] == "HDLC":
            msgParser = MsgParser(parserConfig, HDLCMsg(256))
        elif self.nodeParams.config.msgParsers[meshNum] == "standard":
            msgParser = MsgParser(parserConfig)

        # Create comm
        if (self.nodeParams.config.commConfig['fpga'] == True):
            from mesh.generic.tdmaComm_fpga import TDMAComm_FPGA as TDMAComm
        else:
            from mesh.generic.tdmaComm import TDMAComm

        self.comm = TDMAComm([], radio, msgParser, self.nodeParams)

        # Node control run time bounds
        if (self.nodeParams.config.commConfig['fpga'] == False
            ):  # only needed for software-controlled comm
            if self.comm.transmitSlot == 1:  # For first node, run any time after transmit slot
                self.maxNodeControlTime = self.comm.frameLength - self.comm.slotLength
                self.minNodeControlTime = self.comm.slotLength
            else:  # For other nodes, avoid running near transmit slot
                self.minNodeControlTime = (
                    self.comm.transmitSlot - 2
                ) * self.comm.slotLength  # don't run within 1 slot of transmit
                self.maxNodeControlTime = self.comm.transmitSlot * self.comm.slotLength
Exemplo n.º 19
0
import time
import struct
from collections import namedtuple
from mesh.generic.tdmaState import TDMAStatus
from mesh.generic.cmdDict import CmdDict
from mesh.generic.nodeConfig import ParamId
from mesh.generic.cmds import NodeCmds, TDMACmds, GndCmds
from mesh.generic.commandMsg import CommandMsg
from mesh.generic.command import Command
from mesh.generic.nodeHeader import createHeader
from mesh.generic.nodeParams import NodeParams
from mesh.generic.nodeState import NodeState, LinkStatus
from unittests.testConfig import configFilePath

nodeParams = NodeParams(configFile=configFilePath)

# TestCmd type
TestCmd = namedtuple('TestCmd', ['cmdData', 'body', 'header'])

# Node configuration
nodeId = 1
cmdCounter = 11

# Test commands dictionary
testCmds = dict()

### NodeCmds
# NodeCmds['NoOp']
cmdId = NodeCmds['NoOp']
cmdData = {}
cmd = Command(cmdId, cmdData, [cmdId, nodeId, nodeParams.get_cmdCounter()])
Exemplo n.º 20
0
    def __init__(self, configFile, runFlag):
        super().__init__(name="NodeControlProcess", )

        # Run flag
        self.runFlag = runFlag

        # Configuration
        nodeParams = NodeParams(configFile=configFile)

        # Flight computer serial port
        FCSer = serial.Serial(port=nodeParams.config.FCCommDevice,
                              baudrate=nodeParams.config.FCBaudrate,
                              timeout=0)

        # Create radios
        radios = []
        radioConfig = {
            'uartNumBytesToRead': nodeParams.config.uartNumBytesToRead,
            'rxBufferSize': nodeParams.config.rxBufferSize,
            'ipAddr': nodeParams.config.interface['nodeCommIntIP'],
            'readPort': nodeParams.config.interface['commWrPort'],
            'writePort': nodeParams.config.interface['commRdPort']
        }
        for i in range(nodeParams.config.numMeshNetworks):
            radios.append(
                UDPRadio(radioConfig))  # connection to communication processes
        FCRadio = Radio(FCSer, radioConfig)

        # Create message parsers
        msgParsers = []
        parserConfig = {'parseMsgMax': nodeParams.config.parseMsgMax}
        for i in range(nodeParams.config.numMeshNetworks):
            if nodeParams.config.msgParsers[i] == "SLIP":
                msgParsers.append(SLIPMsgParser(parserConfig))
            elif nodeParams.config.msgParsers[i] == "standard":
                msgParsers.append(MsgParser(parserConfig))
        FCMsgParser = SLIPMsgParser(parserConfig)

        # Open logfiles
        currentTime = str(time.time())
        FCLogFilename = 'fc_' + currentTime + '.log'
        self.FCLogFile = open(FCLogFilename, 'w')
        nodeCommLogFilename = 'node_' + currentTime + '.log'
        self.nodeCommLogFile = open(nodeCommLogFilename, 'w')

        # Failsafe LED interval
        failsafeLEDTime = 1.0  # seconds
        failsafeLEDOnTime = -1.0
        failsafeLEDOn = False

        # Initialize node and flight computer communication variables
        nodeComm = [[]] * nodeParams.config.numMeshNetworks
        FCComm = []

        # Instantiate specific node software
        self.nodeController = []
        self.nodeExecutive = []
        for case in switch(nodeParams.config.platform
                           ):  # Platform specific initializations
            if case("SpecificNode"):
                pass
            else:  # generic node
                from mesh.generic.nodeComm import NodeComm
                from mesh.generic.nodeController import NodeController
                from mesh.generic.nodeExecutive import NodeExecutive

                print("Initializing generic node")

                # Initialize communication variables
                for i in range(nodeParams.config.numMeshNetworks):
                    nodeComm[i] = NodeComm([], radios[i], msgParsers[i],
                                           nodeParams)
                FCComm = NodeComm([], FCRadio, FCMsgParser, nodeParams)

                # Node controller
                self.nodeController = NodeController(nodeParams,
                                                     self.nodeCommLogFile)

                # Node executive
                self.nodeExecutive = NodeExecutive(nodeParams,
                                                   self.nodeController,
                                                   nodeComm, FCComm,
                                                   self.FCLogFile)
Exemplo n.º 21
0
class TestNodeParams:
    def setup_method(self, method):

        # Create NodeConfig instance
        self.nodeConfig = NodeConfig(configFilePath)

        if method.__name__ != "test_init":
            self.nodeParams = NodeParams(
                config=self.nodeConfig)  # Create NodeParams instance

    def test_init(self):
        """Test NodeParams init function."""

        # Test that init function loads node configuration from file
        print("Testing init with configFile")
        nodeParams = NodeParams(configFile=configFilePath)
        assert (nodeParams.config.__dict__ == self.nodeConfig.__dict__)

        # Test that init function loads node configuration from provided config
        nodeParams = NodeParams(config=self.nodeConfig)
        assert (nodeParams.config.__dict__ == self.nodeConfig.__dict__)

    def test_getCmdCounter(self):
        """Test NodeParams command counter get function."""

        # Test getting random command counter
        counter = self.nodeParams.get_cmdCounter()
        assert (counter >= 1)  # value within range
        assert (counter <= 65536)  # value within range

        # Test getting time-based command counter (NOTE: time-based counter commented out)
        #self.nodeParams.commStartTime = time.time()
        #time.sleep(0.5)
        #counter = self.nodeParams.get_cmdCounter()
        #assert(counter >= 0.5 * 1000)
        #assert(counter <= 0.6 * 1000)

    def test_checkNodeLinks(self):
        nodeId = self.nodeParams.config.nodeId - 1

        # Test for direct link
        self.nodeParams.nodeStatus[2].present = True
        self.nodeParams.nodeStatus[2].lastMsgRcvdTime = time.time(
        ) - 0.90 * self.nodeParams.config.commConfig['linkTimeout']
        self.nodeParams.checkNodeLinks()
        assert (self.nodeParams.linkStatus[nodeId][2] == LinkStatus.GoodLink)

        # Test for indirect link
        self.nodeParams.nodeStatus[2].present = False
        self.nodeParams.nodeStatus[2].updating = True
        self.nodeParams.checkNodeLinks()
        assert (
            self.nodeParams.linkStatus[nodeId][2] == LinkStatus.IndirectLink)

        # Test for no link
        self.nodeParams.nodeStatus[2].present = False
        self.nodeParams.nodeStatus[2].updating = False
        self.nodeParams.checkNodeLinks()
        assert (self.nodeParams.linkStatus[nodeId][2] == LinkStatus.NoLink)

    def test_updateStatus(self):
        """Test updateStatus method of NodeParams."""

        # Test without confirmed config
        self.nodeParams.updateStatus()
        assert (self.nodeParams.nodeStatus[self.nodeParams.config.nodeId -
                                           1].status == 0)

        # Test with confirmed config
        self.nodeParams.configConfirmed = True
        self.nodeParams.updateStatus()
        assert (self.nodeParams.nodeStatus[self.nodeParams.config.nodeId -
                                           1].status == 64)

    def test_loadConfig(self):
        """Test loadConfig method of NodeParams."""

        # Create new config for update
        newConfig = NodeConfig(configFilePath)
        newConfigHash = newConfig.calculateHash()
        with open(configFilePath, "r") as jsonFile:
            configData = json.load(jsonFile)
        newConfig_pb = NodeConfig.toProtoBuf(configData).SerializeToString()

        # Test update method
        badHash = hashlib.sha1()
        assert (self.nodeParams.loadConfig(newConfig_pb, badHash) == False
                )  # test rejection with bad hash
        assert (self.nodeParams.newConfig == None)
        assert (self.nodeParams.loadConfig(newConfig_pb, newConfigHash) == True
                )  # test acceptance
        assert (self.nodeParams.newConfig != None)

    def test_updateConfig(self):
        """Test updateConfig method of NodeParams."""

        # Load valid new config
        newConfig = NodeConfig(configFilePath)
        newConfigHash = newConfig.calculateHash()
        with open(configFilePath, "r") as jsonFile:
            configData = json.load(jsonFile)
        newConfig_pb = NodeConfig.toProtoBuf(configData).SerializeToString()
        self.nodeParams.loadConfig(newConfig_pb, newConfigHash)

        # Test successful loading
        self.nodeParams.config.FCBaudrate = newConfig.FCBaudrate / 2.0  # change a parameter to verify loading of new config
        assert (self.nodeParams.config.FCBaudrate != newConfig.FCBaudrate)
        assert (self.nodeParams.updateConfig() == True)
        assert (self.nodeParams.config.FCBaudrate == newConfig.FCBaudrate)
        assert (self.nodeParams.newConfig == None)

        # Expect no load when config missing
        assert (self.nodeParams.updateConfig() == False)
Exemplo n.º 22
0
    def setup_method(self, method):

        self.nodeParams = NodeParams(configFile=configFilePath)
        self.radio = UDPRadio({'uartNumBytesToRead': self.nodeParams.config.uartNumBytesToRead, 'rxBufferSize': 2000, 'ipAddr': "127.0.0.1", 'readPort': 5000, 'writePort': 5000})
Exemplo n.º 23
0
 def setup_method(self, method):
     nodeParams = NodeParams(configFile=configFilePath)
     self.nodeController = NodeController(nodeParams)
Exemplo n.º 24
0
import serial
import os, time, sys
from natsort import natsorted
from multiprocessing import Value
from mesh.generic.nodeParams import NodeParams
from commProcess import CommProcess
from nodeControlProcess import NodeControlProcess

# Execute communication and node control as separate processes
if __name__ == '__main__':
    # Node control shared run flag
    runFlag = Value('B', 1)

    # Load network node configuration
    configFile = 'nodeConfig.json'
    nodeParams = NodeParams(configFile=configFile)

    # Create node communication processes (one process per network)
    commProcesses = [None] * nodeParams.config.numMeshNetworks
    for i in range(nodeParams.config.numMeshNetworks):
        commProcesses[i] = CommProcess(configFile, i, runFlag)
        commProcesses[i].daemon = True

    # Create node control process
    nodeControlProcess = NodeControlProcess(configFile, runFlag)
    nodeControlProcess.daemon = True  # run node control as a daemon

    # Start processes
    for process in commProcesses:
        process.start()
Exemplo n.º 25
0
class TestNodeParams:
    

    def setup_method(self, method):
        
        # Create NodeConfig instance
        self.nodeConfig = NodeConfig(configFilePath)

        if method.__name__ != "test_init":
            self.nodeParams = NodeParams(config=self.nodeConfig) # Create NodeParams instance
            
    def test_init(self):
        """Test NodeParams init function."""

        # Test that init function loads node configuration from file
        print("Testing init with configFile")
        nodeParams = NodeParams(configFile=configFilePath)
        assert(nodeParams.config.__dict__ == self.nodeConfig.__dict__)

        # Test that init function loads node configuration from provided config
        nodeParams = NodeParams(config=self.nodeConfig)
        assert(nodeParams.config.__dict__ == self.nodeConfig.__dict__)
    
    def test_getCmdCounter(self):
        """Test NodeParams command counter get function."""

        # Test getting random command counter
        counter = self.nodeParams.get_cmdCounter()
        assert(counter >= 1) # value within range
        assert(counter <= 65536) # value within range
        
        # Test getting time-based command counter (NOTE: time-based counter commented out)
        #self.nodeParams.commStartTime = time.time()
        #time.sleep(0.5)
        #counter = self.nodeParams.get_cmdCounter()
        #assert(counter >= 0.5 * 1000)
        #assert(counter <= 0.6 * 1000)
    
    def test_checkNodeLinks(self):
        nodeId = self.nodeParams.config.nodeId - 1

        # Test for direct link 
        self.nodeParams.nodeStatus[2].present = True
        self.nodeParams.nodeStatus[2].lastMsgRcvdTime = time.time() - 0.90 * self.nodeParams.config.commConfig['linkTimeout']
        self.nodeParams.checkNodeLinks()
        assert(self.nodeParams.linkStatus[nodeId][2] == LinkStatus.GoodLink)

        # Test for indirect link
        self.nodeParams.nodeStatus[2].present = False
        self.nodeParams.nodeStatus[2].updating = True
        self.nodeParams.checkNodeLinks()
        assert(self.nodeParams.linkStatus[nodeId][2] == LinkStatus.IndirectLink)

        # Test for no link
        self.nodeParams.nodeStatus[2].present = False
        self.nodeParams.nodeStatus[2].updating = False
        self.nodeParams.checkNodeLinks()
        assert(self.nodeParams.linkStatus[nodeId][2] == LinkStatus.NoLink)
        
    def test_updateStatus(self):
        """Test updateStatus method of NodeParams."""
        
        # Test without confirmed config
        self.nodeParams.updateStatus()
        assert(self.nodeParams.nodeStatus[self.nodeParams.config.nodeId-1].status == 0)

        # Test with confirmed config
        self.nodeParams.configConfirmed = True
        self.nodeParams.updateStatus()
        assert(self.nodeParams.nodeStatus[self.nodeParams.config.nodeId-1].status == 64)
Exemplo n.º 26
0
 def setup_method(self, method):
     self.nodeParams = NodeParams(configFile=configFilePath)
     self.commProcessor = CommProcessor([], self.nodeParams)
     msgParser = SLIPMsgParser(
         {'parseMsgMax': self.nodeParams.config.parseMsgMax})
     self.comm = TDMAComm([], [], msgParser, self.nodeParams)
Exemplo n.º 27
0
class TestTDMABlockTx:
    def setup_method(self, method):

        if testSerialPort:
            serialPort = serial.Serial(port=testSerialPort,
                                       baudrate=57600,
                                       timeout=0)
        else:
            serialPort = []

        self.nodeParams = NodeParams(configFile=configFilePath)
        self.nodeParams.commStartTime = time.time()
        self.nodeParams.config.commConfig['transmitSlot'] = 1
        self.radio = Radio(
            serialPort, {
                'uartNumBytesToRead':
                self.nodeParams.config.uartNumBytesToRead,
                'rxBufferSize': 2000
            })
        commProcessor = CommProcessor([TDMACmdProcessor, TestCmdProcessor],
                                      self.nodeParams)
        msgParser = SLIPMsgParser(
            {'parseMsgMax': self.nodeParams.config.parseMsgMax})
        self.tdmaComm = TDMAComm(commProcessor, self.radio, msgParser,
                                 self.nodeParams)
        self.tdmaComm.nodeParams.frameStartTime = time.time()

    def test_populateBlockResponseList(self):
        """Test populateBlockResponseList method of TDMAComm."""
        # Set node presence flags
        presentNodes = [1, 2, 3]
        for node in presentNodes:
            self.nodeParams.nodeStatus[node - 1].present = True

        self.tdmaComm.populateBlockResponseList()
        for node in presentNodes:
            assert (node in self.tdmaComm.blockTxStatus['blockResponseList'])

    def test_checkBlockResponse(self):
        """Test checkBlockResponse method of TDMAComm."""
        # Set block response list
        self.tdmaComm.blockTxStatus['blockResponseList'] = {
            1: None,
            2: None,
            3: None
        }

        # False response test
        self.tdmaComm.blockTxStatus['blockResponseList'][2] = False
        assert (self.tdmaComm.checkBlockResponse() == False)

        # Waiting for responses test
        self.tdmaComm.blockTxStatus['blockResponseList'][2] = True
        assert (self.tdmaComm.checkBlockResponse() == None)

        # True responses test
        for node in self.tdmaComm.blockTxStatus['blockResponseList']:
            self.tdmaComm.blockTxStatus['blockResponseList'][node] = True
        assert (self.tdmaComm.checkBlockResponse() == True)

    def test_sendDataBlock(self):
        """Test sendDataBlock method of TDMAComm."""
        # Manually set frame start time
        self.tdmaComm.frameStartTime = time.time()

        dataBlock = b'1234567890' * 50

        self.tdmaComm.sendDataBlock(dataBlock)

        # Check data stored and block tx request sent
        assert (self.tdmaComm.dataBlock == dataBlock)  # data block stored
        header, msgContents = deserialize(
            self.tdmaComm.radio.txBuffer[1:-3], TDMACmds['BlockTxRequest']
        )  # parse only raw message portions of output
        assert (msgContents['blockReqID'] ==
                self.tdmaComm.blockTxStatus['blockReqID'])
        assert (msgContents['startTime'] ==
                self.tdmaComm.blockTxStatus['startTime'])
        assert (msgContents['length'] == self.tdmaComm.blockTxStatus['length'])

    def test_monitorBlockTx(self):
        """Test monitorBlockTx method of TDMAComm."""
        # Manually set frame start time
        self.tdmaComm.frameStartTime = time.time()

        ## Test block pending behavior
        # Check for block request response checks
        self.setupBlockRequest('tx')
        for node in self.tdmaComm.blockTxStatus['blockResponseList']:
            self.tdmaComm.blockTxStatus['blockResponseList'][node] = True
        self.tdmaComm.monitorBlockTx()
        assert (self.tdmaComm.blockTxStatus['status'] ==
                TDMABlockTxStatus.confirmed)

        # Check for request timeout
        self.setupBlockRequest('tx')
        self.tdmaComm.frameStartTime += 0.5 * self.nodeParams.config.commConfig[
            'blockTxRequestTimeout'] * self.nodeParams.config.commConfig[
                'frameLength']
        self.tdmaComm.monitorBlockTx()
        assert (
            self.tdmaComm.blockTxStatus['status'] == TDMABlockTxStatus.pending)
        self.tdmaComm.frameStartTime += 0.5 * self.nodeParams.config.commConfig[
            'blockTxRequestTimeout'] * self.nodeParams.config.commConfig[
                'frameLength'] + 0.1
        self.tdmaComm.monitorBlockTx()
        assert (
            self.tdmaComm.blockTxStatus['status'] == TDMABlockTxStatus.false)

        # Check for cancel when not confirmed
        self.setupBlockRequest('rx')
        self.tdmaComm.frameStartTime = self.tdmaComm.blockTxStatus[
            'requestTime']
        self.tdmaComm.frameStartTime += 0.5 * (
            self.tdmaComm.blockTxStatus['startTime'] -
            self.tdmaComm.blockTxStatus['requestTime'])
        self.tdmaComm.monitorBlockTx()
        assert (
            self.tdmaComm.blockTxStatus['status'] == TDMABlockTxStatus.pending)
        self.tdmaComm.frameStartTime += 0.5 * (
            self.tdmaComm.blockTxStatus['startTime'] -
            self.tdmaComm.blockTxStatus['requestTime'])
        self.tdmaComm.monitorBlockTx()
        assert (
            self.tdmaComm.blockTxStatus['status'] == TDMABlockTxStatus.false)

        ## Test block confirmed behavior
        # Check for change to active block tx status
        self.setupBlockRequest('rx')
        self.tdmaComm.blockTxStatus['status'] = TDMABlockTxStatus.confirmed
        self.tdmaComm.frameStartTime = self.tdmaComm.blockTxStatus[
            'requestTime']
        self.tdmaComm.frameStartTime += 0.5 * (
            self.tdmaComm.blockTxStatus['startTime'] -
            self.tdmaComm.blockTxStatus['requestTime'])
        self.tdmaComm.monitorBlockTx()
        assert (self.tdmaComm.blockTxStatus['status'] ==
                TDMABlockTxStatus.confirmed)
        self.tdmaComm.frameStartTime += 0.5 * (
            self.tdmaComm.blockTxStatus['startTime'] -
            self.tdmaComm.blockTxStatus['requestTime'])
        self.tdmaComm.monitorBlockTx()
        assert (
            self.tdmaComm.blockTxStatus['status'] == TDMABlockTxStatus.active)

        # Check block tx status message sent
        self.tdmaComm.radio.txBuffer = bytearray()
        self.setupBlockRequest()
        self.tdmaComm.blockTxStatus['status'] = TDMABlockTxStatus.confirmed
        self.tdmaComm.frameStartTime = self.tdmaComm.blockTxStatus[
            'requestTime']
        self.tdmaComm.monitorBlockTx()
        print(self.tdmaComm.radio.txBuffer)
        header, msgContents = deserialize(self.tdmaComm.radio.txBuffer,
                                          TDMACmds['BlockTxStatus'])
        assert (msgContents['blockReqID'] ==
                self.tdmaComm.blockTxStatus['blockReqID'])
        assert (msgContents['startTime'] ==
                self.tdmaComm.blockTxStatus['startTime'])
        assert (msgContents['length'] == self.tdmaComm.blockTxStatus['length'])

        ## Test block active behavior
        # Check for block end from time
        self.setupBlockTxActive()
        self.tdmaComm.monitorBlockTx()
        assert (
            self.tdmaComm.blockTxStatus['status'] == TDMABlockTxStatus.active)
        self.tdmaComm.frameStartTime += self.tdmaComm.blockTxStatus[
            'length'] * self.nodeParams.config.commConfig['frameLength']
        self.tdmaComm.monitorBlockTx()
        assert (
            self.tdmaComm.blockTxStatus['status'] == TDMABlockTxStatus.false)

        # Check for block end from complete flag set
        self.setupBlockTxActive()
        self.tdmaComm.monitorBlockTx()
        assert (
            self.tdmaComm.blockTxStatus['status'] == TDMABlockTxStatus.active)
        self.tdmaComm.blockTxStatus['blockTxComplete'] = True
        self.tdmaComm.monitorBlockTx()
        assert (
            self.tdmaComm.blockTxStatus['status'] == TDMABlockTxStatus.false)

        # Check for block end from status set to nominal
        self.setupBlockTxActive()
        self.tdmaComm.monitorBlockTx()
        assert (
            self.tdmaComm.blockTxStatus['status'] == TDMABlockTxStatus.active)
        self.nodeParams.tdmaStatus = TDMAStatus.nominal
        self.tdmaComm.monitorBlockTx()
        assert (
            self.tdmaComm.blockTxStatus['status'] == TDMABlockTxStatus.false)

    def test_sendBlock(self):
        """Test sendBlock method of TDMAComm."""
        dataBlock = b'1234567890' * 50

        # Check for blockTxComplete set if no data block
        assert (self.tdmaComm.blockTxStatus['blockTxComplete'] == False)
        self.tdmaComm.sendBlock()
        assert (self.tdmaComm.blockTxStatus['blockTxComplete'] == True)

        ## Test that block is sent in appropriately sized chunks
        self.tdmaComm.blockTxStatus[
            'blockTxComplete'] = False  # reset block tx complete flag
        self.nodeParams.config.commConfig['maxBlockTransferSize'] = int(
            len(dataBlock) / 2) + 1  # half of block + 1
        self.tdmaComm.dataBlock = dataBlock
        self.tdmaComm.sendBlock()
        time.sleep(0.1)

        # Check that max block transfer sized chunk sent
        assert (self.tdmaComm.dataBlockPos ==
                self.nodeParams.config.commConfig['maxBlockTransferSize'])
        self.tdmaComm.radio.readBytes(True)
        assert (self.tdmaComm.radio.bytesInRxBuffer ==
                self.nodeParams.config.commConfig['maxBlockTransferSize'])
        assert (self.tdmaComm.blockTxStatus['blockTxComplete'] == False)

        # Check that rest of block sent
        self.tdmaComm.radio.clearRxBuffer()
        self.tdmaComm.sendBlock()
        time.sleep(0.1)
        assert (self.tdmaComm.dataBlockPos == 0)
        self.tdmaComm.radio.readBytes(True)
        assert (
            self.tdmaComm.radio.bytesInRxBuffer == int(len(dataBlock) / 2) + 1
        )  # half of block + END byte
        assert (self.tdmaComm.blockTxStatus['blockTxComplete'] == True)

    #def test_dumpBlockData(self):
    #    """Test dumpBlockData method of TDMAComm."""
    #    self.tdmaComm.receivedBlockData = b'1234567890'*10
    #    self.tdmaComm.dumpBlockData('./')
    #    assert(len(self.tdmaComm.receivedBlockData) == 0)

    def test_nominalTDMABlockTx(self):
        """Test TDMA block transfer sequence."""
        # Force init
        self.tdmaComm.meshInited = True

        dataBlock = b'1234567890' * 50
        self.nodeParams.config.commConfig['maxBlockTransferSize'] = int(
            len(dataBlock) / 2) + 1
        self.tdmaComm.frameStartTime = time.time()

        # Set present nodes
        self.nodeParams.nodeStatus[0].present = True
        self.nodeParams.nodeStatus[1].present = True

        # Request sending of data block
        self.initiateBlockTransmit()
        assert (
            self.tdmaComm.blockTxStatus['status'] == TDMABlockTxStatus.pending)

        ## Execute TDMA comm and monitor block transfer process
        # Check for status change to pending
        self.tdmaComm.frameStartTime += self.nodeParams.config.commConfig[
            'frameLength']
        self.tdmaComm.execute(self.tdmaComm.frameStartTime)
        assert (
            self.tdmaComm.blockTxStatus['status'] == TDMABlockTxStatus.pending)

        # "Send" positive request response from one node
        cmdMsg = Command(
            TDMACmds['BlockTxRequestResponse'], {
                'blockReqID': self.tdmaComm.blockTxStatus['blockReqID'],
                "accept": True
            }, [
                TDMACmds['BlockTxRequestResponse'], 1,
                self.nodeParams.get_cmdCounter()
            ]).serialize(self.nodeParams.clock.getTime())
        self.tdmaComm.commProcessor.processMsg(cmdMsg,
                                               args={
                                                   'nodeStatus':
                                                   self.nodeParams.nodeStatus,
                                                   'comm': self.tdmaComm,
                                                   'clock':
                                                   self.nodeParams.clock
                                               })
        print(self.tdmaComm.blockTxStatus['blockResponseList'])
        assert (self.tdmaComm.blockTxStatus['blockResponseList'][1] == True
                )  # response list updated
        self.tdmaComm.frameStartTime += self.nodeParams.config.commConfig[
            'frameLength']
        self.tdmaComm.execute(self.tdmaComm.frameStartTime)
        assert (
            self.tdmaComm.blockTxStatus['status'] == TDMABlockTxStatus.pending)

        # Send remaining positive responses and check for update to confirmed status
        time.sleep(0.1)
        cmdMsg = Command(
            TDMACmds['BlockTxRequestResponse'], {
                'blockReqID': self.tdmaComm.blockTxStatus['blockReqID'],
                "accept": True
            }, [
                TDMACmds['BlockTxRequestResponse'], 2,
                self.nodeParams.get_cmdCounter()
            ]).serialize(self.nodeParams.clock.getTime())
        self.tdmaComm.commProcessor.processMsg(cmdMsg,
                                               args={
                                                   'nodeStatus':
                                                   self.nodeParams.nodeStatus,
                                                   'comm': self.tdmaComm,
                                                   'clock':
                                                   self.nodeParams.clock
                                               })
        self.tdmaComm.frameStartTime += self.nodeParams.config.commConfig[
            'frameLength']
        self.tdmaComm.execute(self.tdmaComm.frameStartTime)
        assert (self.tdmaComm.blockTxStatus['status'] ==
                TDMABlockTxStatus.confirmed)

        # Advance to block start time
        self.tdmaComm.radio.txBuffer = bytearray()  # clear tx buffer
        self.tdmaComm.frameStartTime = self.tdmaComm.blockTxStatus['startTime']
        self.tdmaComm.execute(self.tdmaComm.frameStartTime)
        time.sleep(0.1)
        self.tdmaComm.radio.readBytes(True)
        assert (
            self.tdmaComm.blockTxStatus['status'] == TDMABlockTxStatus.active
        )  # block started
        assert (self.nodeParams.tdmaStatus == TDMAStatus.blockTx
                )  # tdma status updated
        assert (self.tdmaComm.radio.bytesInRxBuffer >=
                self.nodeParams.config.commConfig['maxBlockTransferSize'])
        assert (self.tdmaComm.blockTxStatus['blockTxComplete'] == False)

        # Continue sending and check for block tx complete flag
        self.tdmaComm.frameStartTime += self.nodeParams.config.commConfig[
            'frameLength']
        self.tdmaComm.execute(self.tdmaComm.frameStartTime)
        assert (self.tdmaComm.blockTxStatus['blockTxComplete'] == True)

        # Check for transition back to nominal TDMA
        self.tdmaComm.frameStartTime += self.nodeParams.config.commConfig[
            'frameLength']
        self.tdmaComm.execute(self.tdmaComm.frameStartTime)
        assert (self.nodeParams.tdmaStatus == TDMAStatus.nominal)
        assert (
            self.tdmaComm.blockTxStatus['status'] == TDMABlockTxStatus.false)

    def test_rejectedTDMABlockTx(self):
        """Test rejecting block transmit request."""
        # Force init
        self.tdmaComm.meshInited = True

        # Start block transmit
        self.initiateBlockTransmit()
        assert (
            self.tdmaComm.blockTxStatus['status'] == TDMABlockTxStatus.pending)

        # "Send" negative response from other node
        time.sleep(0.01)
        cmdMsg = Command(
            TDMACmds['BlockTxRequestResponse'], {
                'blockReqID': self.tdmaComm.blockTxStatus['blockReqID'],
                "accept": False
            }, [
                TDMACmds['BlockTxRequestResponse'], 2,
                self.nodeParams.get_cmdCounter()
            ]).serialize(self.nodeParams.clock.getTime())
        self.tdmaComm.commProcessor.processMsg(cmdMsg,
                                               args={
                                                   'nodeStatus':
                                                   self.nodeParams.nodeStatus,
                                                   'comm': self.tdmaComm,
                                                   'clock':
                                                   self.nodeParams.clock
                                               })
        self.tdmaComm.frameStartTime += self.nodeParams.config.commConfig[
            'frameLength']
        self.tdmaComm.execute(self.tdmaComm.frameStartTime)
        assert (
            self.tdmaComm.blockTxStatus['status'] == TDMABlockTxStatus.false
        )  # request cancelled

    def test_blockTxEndTime(self):
        """Test block transmit ended due to block length reached."""
        # Force init
        self.tdmaComm.meshInited = True

        # Start block transmit
        self.initiateBlockTransmit()
        self.tdmaComm.blockTxStatus['status'] = TDMABlockTxStatus.confirmed
        self.tdmaComm.frameStartTime = self.tdmaComm.blockTxStatus['startTime']
        self.tdmaComm.execute(self.tdmaComm.frameStartTime)
        assert (
            self.tdmaComm.blockTxStatus['status'] == TDMABlockTxStatus.active)
        assert (self.nodeParams.tdmaStatus == TDMAStatus.blockTx)

        # Advance to block end and check that block terminated
        self.tdmaComm.frameStartTime += self.nodeParams.config.commConfig[
            'frameLength'] * self.tdmaComm.blockTxStatus['length']
        self.tdmaComm.execute(self.nodeParams.frameStartTime)
        assert (
            self.tdmaComm.blockTxStatus['status'] == TDMABlockTxStatus.false)
        assert (self.nodeParams.tdmaStatus == TDMAStatus.nominal)

    def test_processSendBlockDataCmd(self):
        """Test processing of SendBlockData command from GCS."""
        self.tdmaComm.frameStartTime = 0.0  # set a frame start time since main execution is bypassed

        # Create TestCmds['SendBlockData'] command
        cmdMsg = Command(TestCmds['SendDataBlock'], {
            'destId': self.nodeParams.config.nodeId
        }, [TestCmds['SendDataBlock'], 0,
            self.nodeParams.get_cmdCounter()]).serialize(
                self.nodeParams.clock.getTime())

        # Process command and check result
        self.tdmaComm.commProcessor.processMsg(cmdMsg,
                                               args={
                                                   'nodeStatus':
                                                   self.nodeParams.nodeStatus,
                                                   'comm': self.tdmaComm
                                               })
        assert (
            self.tdmaComm.blockTxStatus['status'] == TDMABlockTxStatus.pending)
        assert (self.tdmaComm.dataBlock == b'1234567890' * 100)

    def test_nodePresenceUpdate(self):
        """Test that node presence does not timeout during block transmits."""
        self.nodeParams.frameStartTime = time.time()
        self.tdmaComm.blockTxStatus['status'] = TDMABlockTxStatus.active
        self.tdmaComm.blockTxStatus[
            'txNode'] = self.nodeParams.config.nodeId + 1
        self.tdmaComm.blockTxStatus['length'] = 10
        self.tdmaComm.blockTxStatus[
            'startTime'] = self.nodeParams.frameStartTime
        self.nodeParams.tdmaStatus = TDMAStatus.blockTx

        # Set present nodes
        self.nodeParams.nodeStatus[1].present = True
        self.nodeParams.nodeStatus[2].present = True

        # Propagate time and check that node update time is updated
        self.tdmaComm.execute(0.0)
        assert (
            self.tdmaComm.blockTxStatus['status'] == TDMABlockTxStatus.active)
        assert ((self.nodeParams.nodeStatus[1].lastStateUpdateTime -
                 time.time()) <= 0.001)

        time.sleep(5.0)
        self.tdmaComm.execute(0.0)
        assert (
            self.tdmaComm.blockTxStatus['status'] == TDMABlockTxStatus.active)
        assert ((self.nodeParams.nodeStatus[1].lastStateUpdateTime -
                 time.time()) <= 0.001)

    def initiateBlockTransmit(self):
        """Initiate block transmit process."""
        dataBlock = b'1234567890' * 50
        self.nodeParams.config.commConfig['maxBlockTransferSize'] = int(
            len(dataBlock) / 2) + 1
        self.tdmaComm.frameStartTime = time.time()

        # Set present nodes
        self.nodeParams.nodeStatus[0].present = True
        self.nodeParams.nodeStatus[1].present = True

        # Request sending of data block
        self.tdmaComm.sendDataBlock(dataBlock)

    def setupBlockTxActive(self):
        self.setupBlockRequest('tx')
        self.tdmaComm.blockTxStatus['status'] = TDMABlockTxStatus.active
        self.nodeParams.tdmaStatus = TDMAStatus.blockTx
        self.tdmaComm.frameStartTime = self.tdmaComm.blockTxStatus['startTime']

    def setupBlockRequest(self, role='tx'):
        self.tdmaComm.resetBlockTxStatus()
        currentTime = time.time()
        self.tdmaComm.blockTxStatus['blockReqID'] = 5
        self.tdmaComm.blockTxStatus['startTime'] = int(
            currentTime +
            self.nodeParams.config.commConfig['minBlockTxDelay'] *
            self.nodeParams.config.commConfig['frameLength'])
        self.tdmaComm.blockTxStatus['length'] = 5

        # Set block response list
        self.tdmaComm.blockTxStatus['blockResponseList'] = {
            1: None,
            2: None,
            3: None
        }

        if role == 'tx':  # This node transmitting
            self.tdmaComm.blockTxStatus[
                'txNode'] = self.nodeParams.config.nodeId
        else:
            self.tdmaComm.blockTxStatus[
                'txNode'] = self.nodeParams.config.nodeId + 1
        self.tdmaComm.blockTxStatus['status'] = TDMABlockTxStatus.pending
        self.tdmaComm.blockTxStatus['requestTime'] = currentTime
Exemplo n.º 28
0
class TestTDMACmdProcessor:
    def setup_method(self, method):
        self.nodeStatus = [NodeState(i + 1) for i in range(5)]
        self.nodeParams = NodeParams(configFile=configFilePath)
        self.commProcessor = CommProcessor([TDMACmdProcessor], self.nodeParams)
        msgParser = SLIPMsgParser(
            {'parseMsgMax': self.nodeParams.config.parseMsgMax})
        radio = Radio(
            [], {
                'uartNumBytesToRead':
                self.nodeParams.config.uartNumBytesToRead,
                'rxBufferSize': 2000
            })
        self.comm = TDMAComm(self.commProcessor, radio, msgParser,
                             self.nodeParams)

    def test_validateBlockTxRequest(self):
        """Test validateBlockTxRequest  method of TDMACmdProcessor."""
        # Test request rejected if start time passed
        contents = {
            'startTime': time.time() - 1.0,
            'length': self.nodeParams.config.commConfig['maxTxBlockSize']
        }
        assert (validateBlockTxRequest(contents, [], self.nodeParams) == False)

        # Test request rejected if block too long
        contents = {
            'startTime': time.time() + 1.0,
            'length': self.nodeParams.config.commConfig['maxTxBlockSize'] + 1
        }
        assert (validateBlockTxRequest(contents, [], self.nodeParams) == False)

        # Test for request acceptance
        contents = {
            'startTime': time.time() + 1.0,
            'length': self.nodeParams.config.commConfig['maxTxBlockSize']
        }
        assert (validateBlockTxRequest(contents, [], self.nodeParams) == True)

    def test_processMsg(self):
        """Test processMsg method of TDMACmdProcessor."""

        # Test processing of all TDMACmds
        for cmdId in cmdsToTest:
            cmdMsg = packHeader(testCmds[cmdId].header) + testCmds[cmdId].body
            self.commProcessor.processMsg(cmdMsg,
                                          args={
                                              'nodeStatus': self.nodeStatus,
                                              'comm': self.comm,
                                              'clock': self.nodeParams.clock
                                          })
            if cmdId == TDMACmds['TimeOffset']:
                sourceId = testCmds[cmdId].header['header']['sourceId']
                assert (
                    self.nodeStatus[sourceId -
                                    1].timeOffset == testCmds[cmdId].body[0] /
                    100.0)
            elif cmdId == TDMACmds['TimeOffsetSummary']:
                for i in range(len(testCmds[cmdId].cmdData['nodeStatus'])):
                    assert (self.nodeStatus[i].timeOffset == testCmds[cmdId].
                            cmdData['nodeStatus'][i].timeOffset)
            elif cmdId == TDMACmds['MeshStatus']:
                assert (self.nodeParams.commStartTime ==
                        testCmds[cmdId].cmdData['commStartTimeSec'])

        # Resend and test that commStartTime is not updated once it has previously been set
        cmdId = TDMACmds['MeshStatus']
        self.nodeParams.commStartTime = testCmds[cmdId].cmdData[
            'commStartTimeSec'] - 1
        cmdMsg = packHeader(testCmds[cmdId].header) + testCmds[cmdId].body
        self.commProcessor.processMsg(cmdMsg,
                                      args={
                                          'nodeStatus': self.nodeStatus,
                                          'comm': self.comm,
                                          'clock': self.nodeParams.clock
                                      })
        assert (self.nodeParams.commStartTime !=
                testCmds[cmdId].cmdData['commStartTimeSec'])

    def test_blockTxCmdsProcessing(self):
        """Test processing of block transmit related commands."""
        self.nodeParams.commStartTime = self.nodeParams.clock.getTime() - 1.0
        blockReqID = random.randint(1, 255)  # just a random "unique" number
        startTime = int(self.nodeParams.clock.getTime() + 10.0)
        length = self.nodeParams.config.commConfig['maxTxBlockSize']
        txNode = 1

        ## TDMACmds['BlockTxRequest']
        cmdMsg = Command(TDMACmds['BlockTxRequest'], {
            'blockReqID': blockReqID,
            'startTime': startTime,
            'length': length
        }, [
            TDMACmds['BlockTxRequest'], txNode,
            self.nodeParams.get_cmdCounter()
        ]).serialize(self.nodeParams.clock.getTime())

        # Process and check results
        self.commProcessor.processMsg(cmdMsg,
                                      args={
                                          'nodeStatus': self.nodeStatus,
                                          'comm': self.comm,
                                          'clock': self.nodeParams.clock
                                      })
        assert (len(self.comm.radio.txBuffer) == calcsize(
            CmdDict[TDMACmds['BlockTxRequestResponse']].packFormat) +
                calcsize(headers['NodeHeader']['format']))  # response sent
        assert (self.comm.blockTxStatus['blockReqID'] == blockReqID)
        assert (self.comm.blockTxStatus['status'] == TDMABlockTxStatus.pending)
        assert (self.comm.blockTxStatus['txNode'] == txNode)
        assert (self.comm.blockTxStatus['startTime'] == startTime)
        assert (self.comm.blockTxStatus['length'] == length)

        ## TDMACmds['BlockTxConfirmed']
        time.sleep(0.01)
        cmdMsg = Command(TDMACmds['BlockTxConfirmed'], {
            'blockReqID': blockReqID
        }, [
            TDMACmds['BlockTxConfirmed'], txNode,
            self.nodeParams.get_cmdCounter()
        ]).serialize(self.nodeParams.clock.getTime())
        self.commProcessor.processMsg(cmdMsg,
                                      args={
                                          'nodeStatus': self.nodeStatus,
                                          'comm': self.comm,
                                          'clock': self.nodeParams.clock
                                      })
        assert (
            self.comm.blockTxStatus['status'] == TDMABlockTxStatus.confirmed
        )  # status updated to confirmed

        ## TDMACmds['BlockTxStatus']
        self.comm.resetBlockTxStatus()
        time.sleep(0.01)
        cmdMsg = Command(TDMACmds['BlockTxStatus'], {
            'blockReqID': blockReqID,
            'startTime': startTime,
            'length': length
        }, [
            TDMACmds['BlockTxStatus'], txNode,
            self.nodeParams.get_cmdCounter()
        ]).serialize(self.nodeParams.clock.getTime())
        # Check status updated
        self.commProcessor.processMsg(cmdMsg,
                                      args={
                                          'nodeStatus': self.nodeStatus,
                                          'comm': self.comm,
                                          'clock': self.nodeParams.clock
                                      })
        assert (len(self.comm.radio.txBuffer) == calcsize(
            CmdDict[TDMACmds['BlockTxRequestResponse']].packFormat) +
                calcsize(headers['NodeHeader']['format']))  # response sent
        assert (self.comm.blockTxStatus['blockReqID'] == blockReqID)
        assert (
            self.comm.blockTxStatus['status'] == TDMABlockTxStatus.confirmed)
        assert (self.comm.blockTxStatus['txNode'] == txNode)
        assert (self.comm.blockTxStatus['startTime'] == startTime)
        assert (self.comm.blockTxStatus['length'] == length)

        # Check status updated to confirmed if only pending
        time.sleep(0.01)
        cmdMsg = Command(TDMACmds['BlockTxStatus'], {
            'blockReqID': blockReqID,
            'startTime': startTime,
            'length': length
        }, [
            TDMACmds['BlockTxStatus'], txNode,
            self.nodeParams.get_cmdCounter()
        ]).serialize(self.nodeParams.clock.getTime())  # update command counter
        self.comm.blockTxStatus['status'] = TDMABlockTxStatus.pending
        self.commProcessor.processMsg(cmdMsg,
                                      args={
                                          'nodeStatus': self.nodeStatus,
                                          'comm': self.comm,
                                          'clock': self.nodeParams.clock
                                      })
        assert (
            self.comm.blockTxStatus['status'] == TDMABlockTxStatus.confirmed)

        ## TDMACmds['BlockTxRequestResponse']
        time.sleep(0.01)
        self.comm.resetBlockTxStatus()
        self.comm.blockTxStatus[
            'txNode'] = self.nodeParams.config.nodeId  # this node requested block transfer
        self.comm.blockTxStatus['status'] = TDMABlockTxStatus.pending
        cmdMsg = Command(TDMACmds['BlockTxRequestResponse'], {
            'blockReqID': blockReqID,
            "accept": True
        }, [
            TDMACmds['BlockTxRequestResponse'], 1,
            self.nodeParams.get_cmdCounter()
        ]).serialize(self.nodeParams.clock.getTime())
        print(self.nodeParams.config.nodeId)
        self.nodeParams.nodeStatus[
            0].present = True  # mark another node as present
        self.comm.populateBlockResponseList()  # create block response list

        # Test acceptance marked
        self.commProcessor.processMsg(cmdMsg,
                                      args={
                                          'nodeStatus': self.nodeStatus,
                                          'comm': self.comm,
                                          'clock': self.nodeParams.clock
                                      })
        assert (self.comm.blockTxStatus['blockResponseList'][1] == True)

        # Test rejection marked
        time.sleep(0.01)
        cmdMsg = Command(TDMACmds['BlockTxRequestResponse'], {
            'blockReqID': blockReqID,
            "accept": False
        }, [
            TDMACmds['BlockTxRequestResponse'], 1,
            self.nodeParams.get_cmdCounter()
        ]).serialize(self.nodeParams.clock.getTime())
        self.commProcessor.processMsg(cmdMsg,
                                      args={
                                          'nodeStatus': self.nodeStatus,
                                          'comm': self.comm,
                                          'clock': self.nodeParams.clock
                                      })
        assert (self.comm.blockTxStatus['blockResponseList'][1] == False)