示例#1
0
    def test_processMsgs(self):
        """Test processMsgs method of SerialComm."""
        # Create message parser for testing purposes
        msg = SLIPMsg(self.nodeParams.config.parseMsgMax)
        self.serialComm.msgParser.msg = msg

        # Create and send test messages
        nodeStatus = [NodeState(node + 1) for node in range(5)]
        clock = FormationClock()

        cmdId1 = NodeCmds['NoOp']  # No op command
        cmdMsg1 = Command(cmdId1, None, [cmdId1, 1, 200]).serialize()
        cmdId2 = NodeCmds['GCSCmd']  # GCS command
        cmdMsg2 = Command(cmdId2, {
            'destId': 1,
            'mode': 2
        }, [cmdId2, 1, 201]).serialize()
        self.serialComm.sendMsg(cmdMsg1)
        self.serialComm.sendMsg(cmdMsg2)
        time.sleep(0.1)

        # Test processing
        self.serialComm.processMsgs(
            args={
                'logFile': [],
                'nav': [],
                'nodeStatus': nodeStatus,
                'clock': clock,
                'comm': self.serialComm
            })

        assert (cmdId1 in self.serialComm.cmdQueue
                )  # Test that correct message added to cmdQueue
        assert (cmdId2 in self.serialComm.cmdQueue
                )  # Test that correct message added to cmdQueue
示例#2
0
 def test_serialize(self):
     """Test serialization of command."""
     command = Command(self.cmdId, self.cmdData, self.header)
     
     serMsg = command.serialize(0)
     assert(len(serMsg) == (calcsize(headers[CmdDict[self.cmdId].header]['format']) + calcsize(CmdDict[self.cmdId].packFormat))) # serial message the correct length
         
示例#3
0
    def getBlockTxPacket(self):
        # Check for block data
        #if (self.blockTxData == None): # no data to send
        #    return None

        # Create mesh packet from next chunk of block data
        if (self.blockTx.dataLoc >= len(self.blockTx.data)): # no packets remaining
            return None
        elif (len(self.blockTx.data) > self.blockTx.dataLoc + self.nodeParams.config.commConfig['blockTxPacketSize']): 
            newBlockTxDataLoc = self.blockTx.dataLoc + int(self.nodeParams.config.commConfig['blockTxPacketSize'])
            blockDataChunk = self.blockTx.data[self.blockTx.dataLoc:newBlockTxDataLoc]
            self.blockTx.dataLoc = newBlockTxDataLoc
        else: # send remainder of data block
            blockDataChunk = self.blockTx.data[self.blockTx.dataLoc:]
            self.blockTx.dataLoc = len(self.blockTx.data) # reached end of data block
       
        # Generate new packet command
        self.blockTx.packetNum += 1
        blockDataCmd = Command(TDMACmds['BlockData'], {'blockReqId': self.blockTx.reqId, 'packetNum': self.blockTx.packetNum, 'dataLength': len(blockDataChunk), 'data': blockDataChunk}, [TDMACmds['BlockData'], self.nodeParams.config.nodeId])
        blockDataSerialized = self.tdmaCmdParser.encodeMsg(blockDataCmd.serialize(self.nodeParams.clock.getTime()))
 
        blockPacket = self.createMeshPacket(self.blockTx.destId, b'', blockDataSerialized, self.nodeParams.config.nodeId, BLOCK_TX_MSG)
                    
        print("Node " + str(self.nodeParams.config.nodeId) + " - Sending block transmit packet", self.blockTx.packetNum, ". Length-", len(blockPacket))

        return blockPacket
示例#4
0
    def initMesh(self, currentTime=time.time()):
        """Initialize node mesh networks."""
        # Create tdma comm messages
        flooredStartTime = math.floor(self.nodeParams.commStartTime)
        self.tdmaCmds[TDMACmds['MeshStatus']] = Command(
            TDMACmds['MeshStatus'], {
                'commStartTimeSec': int(flooredStartTime),
                'status': self.nodeParams.tdmaStatus
            }, [TDMACmds['MeshStatus'], self.nodeParams.config.nodeId],
            self.nodeParams.config.commConfig['statusTxInterval'])

        self.tdmaCmds[TDMACmds['LinkStatus']] = Command(
            TDMACmds['LinkStatus'], {
                'linkStatus': self.nodeParams.linkStatus,
                'nodeId': self.nodeParams.config.nodeId
            }, [TDMACmds['LinkStatus'], self.nodeParams.config.nodeId],
            self.nodeParams.config.commConfig['linksTxInterval'])

        if self.nodeParams.config.nodeId != 0:  # stop ground node from broadcasting time offset
            self.tdmaCmds[TDMACmds['TimeOffset']] = Command(
                TDMACmds['TimeOffset'], {
                    'nodeStatus':
                    self.nodeParams.nodeStatus[self.nodeParams.config.nodeId -
                                               1]
                }, [TDMACmds['TimeOffset'], self.nodeParams.config.nodeId],
                self.nodeParams.config.commConfig['offsetTxInterval'])

        # Determine where in frame mesh network currently is
        self.syncTDMAFrame(currentTime)

        self.inited = True
        print("Node " + str(self.nodeParams.config.nodeId) +
              " - Initializing comm")
示例#5
0
    def sendBlock(self):
        if self.dataBlock:
            if len(self.dataBlock[self.dataBlockPos:]
                   ) > self.nodeParams.config.commConfig[
                       'maxBlockTransferSize']:  # buffer portion of data block
                blockDataCmd = Command(
                    TDMACmds['BlockData'], {
                        'data':
                        self.dataBlock[self.dataBlockPos:self.dataBlockPos +
                                       self.nodeParams.config.
                                       commConfig['maxBlockTransferSize']]
                    }, [TDMACmds['BlockData'], self.nodeParams.config.nodeId
                        ]).serialize(self.nodeParams.clock.getTime())
                self.dataBlockPos += self.nodeParams.config.commConfig[
                    'maxBlockTransferSize']
            else:  # send entire data block
                blockDataCmd = Command(
                    TDMACmds['BlockData'], {
                        'data': self.dataBlock[self.dataBlockPos:]
                    }, [TDMACmds['BlockData'], self.nodeParams.config.nodeId
                        ]).serialize(self.nodeParams.clock.getTime())
                self.clearDataBlock()  # clear stored data block
                self.blockTxStatus[
                    'blockTxComplete'] = True  # end block transfer

            # Send block data
            self.radio.bufferTxMsg(blockDataCmd)
            self.radio.bufferTxMsg(SLIP_END_TDMA)
            self.radio.sendBuffer(
                self.nodeParams.config.commConfig['maxBlockTransferSize'])

        else:  # end block transfer - no data to send
            self.blockTxStatus['blockTxComplete'] = True
示例#6
0
    def test_processMeshMsgs(self):
        """Test processMeshMsgs method of TDMAComm."""
        commStartTime = int(time.time())
        cmd = Command(TDMACmds['MeshStatus'], {'commStartTimeSec': commStartTime, 'status': TDMAStatus.nominal}, [TDMACmds['MeshStatus'], self.nodeParams.config.nodeId])
        encodedCmd = self.tdmaComm.tdmaCmdParser.encodeMsg(cmd.serialize())

        # Verify pre-test conditions
        assert(self.tdmaComm.commStartTime == None)
        self.tdmaComm.processMeshMsgs(encodedCmd)
        assert(self.tdmaComm.commStartTime == commStartTime)
示例#7
0
    def test_init(self):
        """Test creation of Command instance."""
        # Test creation without header
        command = Command(self.cmdId, self.cmdData)
        assert(command.cmdId == self.cmdId)
        assert(command.cmdData == self.cmdData)

        # Test creation with header
        command = Command(self.cmdId, self.cmdData, self.header)
        assert(isinstance(command.header, dict) == True) # header created as dict
        assert(len(command.header['header']) == len(self.header)) # header has same number of entries as provided header data
示例#8
0
    def test_packHeader(self):
        """Test packHeader method of Command class."""
        command = Command(self.cmdId, self.cmdData, self.header)

        # Test with header
        header = command.packHeader()
        assert (header == packHeader(command.header))

        # Test without header
        command.header = []
        header = command.packHeader()
        assert (len(header) == 0)
示例#9
0
    def test_packBody(self):
        """Test packBody method of Command class."""
        command = Command(self.cmdId, self.cmdData)

        # Test with serialize method
        body = command.packBody()
        assert (len(body) == calcsize(CmdDict[self.cmdId].packFormat))
        assert (body == CmdDict[self.cmdId].serialize(command.cmdData, 0))

        # Test without serialize method
        command.serializeMethod = []
        body = command.packBody()
        assert (len(body) == 0)
示例#10
0
    def test_syncTDMAFrame(self):
        """Test syncTDMAFrame method of TDMAComm."""
        # Setup test conditions
        testTime = 5.0
        self.tdmaComm.rxBufferReadPos = 10
        self.tdmaComm.commStartTime = testTime - 0.5*self.tdmaComm.frameLength
        self.tdmaComm.tdmaCmds[TDMACmds['MeshStatus']] = Command(TDMACmds['MeshStatus'], {'commStartTimeSec': 0.0, 'status': TDMAStatus.blockTx}, [TDMACmds['MeshStatus'], self.nodeParams.config.nodeId])
        self.tdmaComm.tdmaStatus = TDMAStatus.nominal
        assert(self.tdmaComm.nodeParams.nodeStatus[self.tdmaComm.nodeParams.config.nodeId-1].timeOffset == 127) # offset at default value
        
        # Call method under test
        self.tdmaComm.syncTDMAFrame(testTime)

        # Check frame time variables
        assert(self.tdmaComm.frameTime == 0.5*self.tdmaComm.frameLength)
        assert(self.tdmaComm.frameStartTime == testTime - self.tdmaComm.frameTime)

        # Check that TDMA status updated in outgoing MeshStatus message
        assert(self.tdmaComm.tdmaCmds[TDMACmds['MeshStatus']].cmdData['status'] == TDMAStatus.nominal)

        # Check that rx buffer position reset
        assert(self.tdmaComm.rxBufferReadPos == 0)

        # Verify time offset check
        assert(self.tdmaComm.nodeParams.nodeStatus[self.tdmaComm.nodeParams.config.nodeId-1].timeOffset != 127) # offset updated
示例#11
0
    def test_processMsg(self):
        """Test processMsg method of SerialComm."""
        # Create message and test processing
        nodeStatus = [NodeState(node + 1) for node in range(5)]
        clock = FormationClock()

        cmdId = NodeCmds['NoOp']
        cmdMsg = Command(cmdId, None, [cmdId, 1, 200]).serialize()
        assert (self.serialComm.processMsg(cmdMsg,
                                           args={
                                               'logFile': [],
                                               'nav': [],
                                               'nodeStatus': nodeStatus,
                                               'clock': clock,
                                               'comm': self.serialComm
                                           }) == True)

        assert (cmdId in self.serialComm.cmdQueue
                )  # Test that correct message added to cmdQueue

        # Confirm proper return when no message processed successfully
        assert (self.serialComm.processMsg(b'12345',
                                           args={
                                               'logFile': [],
                                               'nav': [],
                                               'nodeStatus': nodeStatus,
                                               'clock': clock,
                                               'comm': self.serialComm
                                           }) == False)
示例#12
0
    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
示例#13
0
 def updateBlockTxStatus(self):
     # Monitor for block transmit end
     if (self.blockTx.complete or self.nodeParams.clock.getTime() >= self.blockTx.endTime): # block transmit ended
         if (self.blockTx.srcId == self.nodeParams.config.nodeId): # sender end block tx
             # Send block transmit end message
             self.tdmaCmds[TDMACmds['BlockTxRequest']] = Command(TDMACmds['BlockTxRequest'], {'blockReqId': self.blockTx.reqId, 'destId': self.blockTx.destId, 'startTime': self.blockTx.startTime, 'length': self.blockTx.length, 'status': 0}, [TDMACmds['BlockTxRequest'], self.nodeParams.config.nodeId, self.nodeParams.get_cmdCounter()])
 
         # End block transmit
         self.endBlockTx()
示例#14
0
    def sendDataBlock(self, dataBlock):
        """Begins block transfer process."""

        # Calculate block tx parameters
        length = int(
            ceil(
                len(dataBlock) /
                self.nodeParams.config.commConfig['maxBlockTransferSize']))
        if length > self.nodeParams.config.commConfig['maxTxBlockSize']:
            # Too much data to transmit
            return False

        startTime = int(self.frameStartTime +
                        self.nodeParams.config.commConfig['frameLength'] *
                        self.nodeParams.config.commConfig['minBlockTxDelay'])

        # Store data block
        self.dataBlock = dataBlock

        # Populate response list
        self.populateBlockResponseList()

        # Send block tx request
        blockReqID = random.randint(1, 255)  # just a random "unique" number
        blockTxCmd = Command(TDMACmds['BlockTxRequest'], {
            'blockReqID': blockReqID,
            'startTime': startTime,
            'length': length
        }, [
            TDMACmds['BlockTxRequest'], self.nodeParams.config.nodeId,
            self.nodeParams.get_cmdCounter()
        ])
        self.bufferTxMsg(blockTxCmd.serialize(self.nodeParams.clock.getTime()))

        # Update blockTxStatus
        self.blockTxStatus['blockReqID'] = blockReqID
        self.blockTxStatus['startTime'] = startTime
        self.blockTxStatus['length'] = length
        self.blockTxStatus['requestTime'] = self.frameStartTime
        self.blockTxStatus['txNode'] = self.nodeParams.config.nodeId
        self.blockTxStatus['status'] = TDMABlockTxStatus.pending

        return True
示例#15
0
    def test_sendTDMACmds(self):
        """Test sendTDMACmds method of TDMAComm."""
        self.tdmaComm.commStartTime = time.time();
        flooredStartTime = math.floor(self.tdmaComm.commStartTime)
        self.tdmaComm.tdmaCmds.update({TDMACmds['MeshStatus']: Command(TDMACmds['MeshStatus'], {'commStartTimeSec': flooredStartTime, 'status': self.tdmaComm.tdmaStatus}, [TDMACmds['MeshStatus'], self.nodeParams.config.nodeId], 0.500)})

        # Check command serialized and returned
        tdmaCmdBytes = self.tdmaComm.sendTDMACmds()
        assert(len(tdmaCmdBytes) > 0)

        # Wait for resend
        time.sleep(0.1)
        assert(len(self.tdmaComm.sendTDMACmds()) == 0) # should not return anything
        time.sleep(0.4)
        assert(len(self.tdmaComm.sendTDMACmds()) > 0) # should return bytes

        # Confirm non-periodic commands are returned and then removed
        self.tdmaComm.tdmaCmds = {TDMACmds['MeshStatus']: Command(TDMACmds['MeshStatus'], {'commStartTimeSec': flooredStartTime, 'status': self.tdmaComm.tdmaStatus}, [TDMACmds['MeshStatus'], self.nodeParams.config.nodeId])}
        assert(len(self.tdmaComm.sendTDMACmds()) > 0)
        assert(len(self.tdmaComm.tdmaCmds) == 0)
示例#16
0
    def initMesh(self, currentTime=time.time()):
        self.tdmaCmds[TDMACmds['LinkStatus']] = Command(
            TDMACmds['LinkStatus'], {
                'linkStatus': self.nodeParams.linkStatus,
                'nodeId': self.nodeParams.config.nodeId
            }, [TDMACmds['LinkStatus'], self.nodeParams.config.nodeId],
            self.nodeParams.config.commConfig['linksTxInterval'])

        if self.nodeParams.config.nodeId != 0:  # stop ground node from broadcasting time offset
            self.tdmaCmds[TDMACmds['TimeOffset']] = Command(
                TDMACmds['TimeOffset'], {
                    'nodeStatus':
                    self.nodeParams.nodeStatus[self.nodeParams.config.nodeId -
                                               1]
                }, [TDMACmds['TimeOffset'], self.nodeParams.config.nodeId],
                self.nodeParams.config.commConfig['offsetTxInterval'])

        self.inited = True
        print("Node " + str(self.nodeParams.config.nodeId) +
              " - Initializing comm")
示例#17
0
    def initMesh(self, currentTime=time.time()):
        """Initialize node mesh networks."""
        # Create tdma comm messages
        flooredStartTime = math.floor(self.commStartTime)
        self.tdmaCmds[TDMACmds['MeshStatus']] = Command(TDMACmds['MeshStatus'], {'commStartTimeSec': int(flooredStartTime), 'status': self.tdmaStatus, 'configHash': self.nodeParams.config.calculateHash()}, [TDMACmds['MeshStatus'], self.nodeParams.config.nodeId], self.nodeParams.config.commConfig['statusTxInterval'])

        self.tdmaCmds[TDMACmds['LinkStatus']] = Command(TDMACmds['LinkStatus'], {'linkStatus': self.nodeParams.linkStatus, 'nodeId': self.nodeParams.config.nodeId}, [TDMACmds['LinkStatus'], self.nodeParams.config.nodeId], self.nodeParams.config.commConfig['linksTxInterval'])
        
        if self.nodeParams.config.nodeId != 0: # stop ground node from broadcasting time offset
            self.tdmaCmds[TDMACmds['TimeOffset']] = Command(TDMACmds['TimeOffset'], {'nodeStatus': self.nodeParams.nodeStatus[self.nodeParams.config.nodeId-1]}, [TDMACmds['TimeOffset'], self.nodeParams.config.nodeId], self.nodeParams.config.commConfig['offsetTxInterval'])
        
        # Current network configuration message
        self.initialConfigTxTime = self.commStartTime + self.nodeParams.config.nodeId * self.nodeParams.config.commConfig['configTxInterval']
        configHash = self.nodeParams.config.calculateHash()
        config_pb = NodeConfig.toProtoBuf(self.nodeParams.config.rawConfig).SerializeToString()
        self.tdmaCmds[TDMACmds['CurrentConfig']] = Command(TDMACmds['CurrentConfig'], {'config': config_pb, 'configLength': len(config_pb), 'configHash': configHash, 'hashLength': self.nodeParams.config.hashSize}, [TDMACmds['CurrentConfig'], self.nodeParams.config.nodeId], self.maxNumSlots * self.nodeParams.config.commConfig['configTxInterval'])

        # Determine where in frame mesh network currently is
        self.syncTDMAFrame(currentTime)

        self.inited = True
        print("Node " + str(self.nodeParams.config.nodeId) + " - Initializing comm")
示例#18
0
    def test_packageMeshPacket(self):
        """Test packageMeshPacket method of TDMAComm."""
        packetHeaderLen = 8

        # Test no send of empty message
        msgBytes = b''
        destId = 5
        assert(len(self.tdmaComm.packageMeshPacket(destId, msgBytes)) == 0)
        
        # Confirm packet structure
        msgBytes = b'1234567890'
        packet = self.tdmaComm.packageMeshPacket(destId, msgBytes)
        assert(len(packet) == packetHeaderLen + len(msgBytes))
        packetHeader = struct.unpack('<BBHHH', packet[0:packetHeaderLen])        
        assert(packetHeader[0] == self.tdmaComm.nodeParams.config.nodeId)
        assert(packetHeader[1] == destId)
        assert(packetHeader[2] == 0) # no admin bytes
        assert(packetHeader[3] == len(msgBytes))
 
        # Test sending of periodic TDMA commands (broadcast message only)
        cmd = Command(TDMACmds['MeshStatus'], {'commStartTimeSec': int(time.time()), 'status': TDMAStatus.nominal}, [TDMACmds['MeshStatus'], self.nodeParams.config.nodeId])
        encodedCmd = self.tdmaComm.tdmaCmdParser.encodeMsg(cmd.serialize())
        self.tdmaComm.tdmaCmds = dict()
        self.tdmaComm.tdmaCmds[TDMACmds['MeshStatus']] = cmd

        destId = 0 # broadcast message
        packet = self.tdmaComm.packageMeshPacket(destId, msgBytes)
        assert(len(packet) == packetHeaderLen + len(encodedCmd) + len(msgBytes))
        assert(packet[packetHeaderLen:packetHeaderLen+len(encodedCmd)] == encodedCmd)
        assert(packet[packetHeaderLen+len(encodedCmd):] == msgBytes)

        # Confirm admin bytes still sent with zero length message bytes
        msgBytes = b''
        self.tdmaComm.tdmaCmds[TDMACmds['MeshStatus']] = cmd
        packet = self.tdmaComm.packageMeshPacket(destId, msgBytes)
        assert(len(packet) == packetHeaderLen + len(encodedCmd))
        assert(packet[packetHeaderLen:packetHeaderLen+len(encodedCmd)] == encodedCmd)
示例#19
0
 def test_checkForInit(self):
     """Test checkForInit method of TDMAComm."""
     # Confirm radio is off
     assert(self.radio.mode == RadioMode.off)
     
     # Test without message
     self.tdmaComm.checkForInit()
     assert(self.radio.mode == RadioMode.receive)
     assert(self.tdmaComm.commStartTime == None)
     
     # Test with MeshStatus message
     startTime = int(time.time())
     self.tdmaComm.tdmaCmds[TDMACmds['MeshStatus']] = Command(TDMACmds['MeshStatus'], {'commStartTimeSec': startTime, 'status': TDMAStatus.nominal}, [TDMACmds['MeshStatus'], self.nodeParams.config.nodeId], 0)
     self.tdmaComm.bufferTxMsg(self.tdmaComm.packageMeshPacket(0, b''))
     #self.tdmaComm.bufferTxMsg(cmd.serialize())
     self.tdmaComm.sendBuffer()
     time.sleep(0.1)
     self.tdmaComm.checkForInit()
     assert(self.tdmaComm.commStartTime == startTime)
示例#20
0
    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)
示例#21
0
    def test_initComm(self):
        """Test initComm method of TDMAComm."""
        testTime = time.time()
        # Confirm starting conditions
        assert(self.radio.mode == RadioMode.off)
        assert(self.tdmaComm.initStartTime == None)

        # Init comm and check radio is now in receive
        self.tdmaComm.initComm(testTime)
        assert(self.tdmaComm.initStartTime == testTime)
        self.tdmaComm.initComm(testTime + 0.01)
        assert(self.radio.mode == RadioMode.receive)
        
        # Send MeshStatus message and confirm that commStartTime is updated
        commStartTime = int(testTime)
        self.tdmaComm.tdmaCmds[TDMACmds['MeshStatus']] = Command(TDMACmds['MeshStatus'], {'commStartTimeSec': commStartTime, 'status': TDMAStatus.nominal}, [TDMACmds['MeshStatus'], self.nodeParams.config.nodeId], 0)
        assert(self.tdmaComm.commStartTime != commStartTime) # check that comm start times do not match
        #print(cmd.serialize())
        #self.tdmaComm.bufferTxMsg(cmd.serialize())
        self.tdmaComm.bufferTxMsg(self.tdmaComm.packageMeshPacket(0, b''))
        self.tdmaComm.sendBuffer()
        time.sleep(0.1)
        self.tdmaComm.initComm(testTime)
        assert(self.tdmaComm.commStartTime == commStartTime) # check that comm start times now match
示例#22
0
    def sendDataBlock(self, destId, blockBytes):
        """This function receives a large data block to be sent over the mesh network for Block Transfer."""
        if (self.blockTxReqPending
                or self.blockTxAccepted):  # block tx already pending
            return False

        # Store data block and request block data transfer
        blockTxStartTime = int(
            self.nodeParams.clock.getTime() +
            self.nodeParams.config.commConfig['pollTimeout'])
        blockTxLength = math.ceil(
            len(blockBytes) /
            self.nodeParams.config.commConfig['blockTxPacketSize']
        )  # length in number of packets

        if (blockTxLength >
                self.nodeParams.config.commConfig['blockTxMaxLength']
            ):  # data block is too large
            return False

        self.blockTxData = blockBytes
        self.comm.tdmaCmds[TDMACmds['BlockTxRequest']] = Command(
            TDMACmds['BlockTxRequest'], {
                'blockReqId': self.getBlockRequestId(),
                'destId': destId,
                'startTime': blockTxStartTime,
                'length': blockTxLength,
                'status': 1
            }, [
                TDMACmds['BlockTxRequest'], self.nodeParams.config.nodeId,
                self.nodeParams.get_cmdCounter()
            ])

        self.blockTxReqPending = True

        return True
def processMsg(self, cmdId, msg, args):
        nodeStatus = args['nodeStatus'] 
        comm = args['comm']
        clock = args['clock']

        cmdStatus = False
 
        if len(msg) > 0:
            # Parse command header
            header = deserialize(msg, cmdId, 'header')
            if (processHeader(self, header, msg, nodeStatus, clock, comm) == False): # stale command
                return False

            # Parse message contents
            if cmdId not in [TDMACmds['BlockData'], TDMACmds['LinkStatus']]:
                try: 
                    msgContents = deserialize(msg, cmdId, 'body')       
                    if msgContents == None:
                        return False
                except Exception as e:
                    print("Exception occurred while deserializing message:", e)
                    return False
            
            # Process message by command id
            for case in switch(cmdId):
                if case(TDMACmds['TimeOffset']):
                    if nodeStatus and len(nodeStatus) >= header['sourceId']:
                        nodeStatus[header['sourceId']-1].timeOffset = msgContents['timeOffset']/100.0
                    cmdStatus = True
                    break
                    
                if case(TDMACmds['MeshStatus']):
                    if not comm.commStartTime: # accept value if one not already present
                        comm.commStartTime = msgContents['commStartTimeSec'] # store comm start time
                    cmdStatus = True

                    break

                if case(TDMACmds['LinkStatus']): # Status of links to other nodes
                    msgSize = self.nodeParams.config.maxNumNodes
                    headerSize = calcsize(headers[CmdDict[cmdId].header]['format'])
                    linkData = unpack('=' + msgSize*CmdDict['LinkStatusContents'].packFormat, msg[headerSize:])
       
                    # Determine sending node array index
                    node =  header['sourceId'] - 1

                    # Place received data into appropriate link status subarray
                    for i in range(msgSize):
                       self.nodeParams.linkStatus[node][i] = linkData[i]
                    cmdStatus = True
                    break

                if case(TDMACmds['BlockTxRequest']): # Request for a block of transmit time
                    blockTxResponse = False
                    if comm.blockTxStatus['status'] == TDMABlockTxStatus.false: # no current block tx active
                        # Check block transmit constraints
                        if validateBlockTxRequest(msgContents, header, self.nodeParams):        
                            # Store pending request parameters
                            comm.blockTxStatus['blockReqID'] = msgContents['blockReqID']
                            comm.blockTxStatus['status'] = TDMABlockTxStatus.pending # set to pending status and wait for start
                            comm.blockTxStatus['startTime'] = msgContents['startTime'] # store time of request
                            comm.blockTxStatus['txNode'] = header['sourceId'] # store requesting node's ID
                            comm.blockTxStatus['length'] = msgContents['length'] # transmit block length

                            blockTxResponse = True # set response to request

                    elif comm.blockTxStatus['status'] == TDMABlockTxStatus.pending:
                        if comm.blockTxStatus['blockReqID'] == msgContents['blockReqId'] and header['sourceId'] == comm.blockTxStatus['txNode']: # repeat positive response
                            blockTxResponse = True  
                            
                    # Send response
                    responseCmd = Command(TDMACmds['BlockTxRequestResponse'], {'blockReqID': msgContents['blockReqID'], 'accept': blockTxResponse}, [TDMACmds['BlockTxRequestResponse'], self.nodeParams.config.nodeId, self.nodeParams.get_cmdCounter()])
                    comm.radio.bufferTxMsg(responseCmd.serialize(self.nodeParams.clock.getTime()))
            
                    break           

                if case(TDMACmds['BlockTxConfirmed']): # Transmit block confirmation
                    if comm.blockTxStatus['status'] == TDMABlockTxStatus.pending: # pending block transmit
                        if comm.blockTxStatus['blockReqID'] == msgContents['blockReqID'] and comm.blockTxStatus['txNode'] == header['sourceId']: # confirmation received correct node with correct block ID
                            comm.blockTxStatus['status'] = TDMABlockTxStatus.confirmed              
                    break        

                if case(TDMACmds['BlockTxRequestResponse']): 
                    if comm.blockTxStatus['status'] == TDMABlockTxStatus.pending and comm.blockTxStatus['txNode'] == self.nodeParams.config.nodeId: # Block Tx previously requested by this node
                        if header['sourceId'] in comm.blockTxStatus['blockResponseList']: # this node in response list
                            comm.blockTxStatus['blockResponseList'][header['sourceId']] = msgContents['accept']
                    break

                if case(TDMACmds['BlockTxStatus']):
                    updateStatus = False
                    if comm.blockTxStatus['status'] == TDMABlockTxStatus.false: # receiving node not aware of block transmit    
                        updateStatus = True
                        
                    elif comm.blockTxStatus['status'] == TDMABlockTxStatus.pending:
                        if msgContents['blockReqID'] == comm.blockTxStatus['blockReqID']: # may have missed confirm message
                            updateStatus = True

                    if updateStatus:
                        # Update block transmit status
                        comm.blockTxStatus['blockReqID'] = msgContents['blockReqID']
                        comm.blockTxStatus['status'] = TDMABlockTxStatus.confirmed # jump to confirmed status
                        comm.blockTxStatus['startTime'] = msgContents['startTime'] # store time of request
                        comm.blockTxStatus['txNode'] = header['sourceId'] # store requesting node's ID
                        comm.blockTxStatus['length'] = msgContents['length'] # transmit block length

                    break

                if case(TDMACmds['BlockData']): # raw block data
                    headerSize = calcsize(headers[CmdDict[cmdId].header]['format'])
                    blockData = msg[headerSize:]
                    print("Block data received:", blockData)
                    
        return cmdStatus                    
示例#24
0
    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)
示例#25
0
    def test_processMsgs(self):
        """Test processMsgs method of TDMAComm."""
        commStartTime = int(time.time())
        cmd = Command(TDMACmds['MeshStatus'], {'commStartTimeSec': commStartTime, 'status': TDMAStatus.nominal}, [TDMACmds['MeshStatus'], self.nodeParams.config.nodeId])
        encodedCmd = self.tdmaComm.tdmaCmdParser.encodeMsg(cmd.serialize())
        self.tdmaComm.tdmaCmds = dict()
        self.tdmaComm.tdmaCmds[TDMACmds['MeshStatus']] = cmd
        payloadBytes = b'1234567890'
        
        # Verify pre-test conditions
        assert(len(self.tdmaComm.cmdRelayBuffer) == 0)
        assert(self.tdmaComm.commStartTime == None)

        # Send test packet
        packet = self.tdmaComm.packageMeshPacket(0, payloadBytes)
        self.tdmaComm.bufferTxMsg(packet)
        self.tdmaComm.sendBuffer()
        time.sleep(0.1)
        
        # Confirm payload bytes buffered for host
        assert(len(self.tdmaComm.hostBuffer) == 0)
        self.tdmaComm.readMsgs()
        self.tdmaComm.processMsgs()
        assert(len(self.tdmaComm.hostBuffer) > 0)
        assert(self.tdmaComm.hostBuffer == payloadBytes)

        # Confirm mesh admin message processed
        assert(self.tdmaComm.commStartTime == commStartTime)

        ## Test proper relaying
        cmdRelayBufferLen = len(self.tdmaComm.cmdRelayBuffer)
        assert(cmdRelayBufferLen > 0) # new broadcast command should be relayed
        self.tdmaComm.bufferTxMsg(packet)
        self.tdmaComm.sendBuffer()
        time.sleep(0.1)
        self.tdmaComm.readMsgs()
        self.tdmaComm.processMsgs()
        assert(len(self.tdmaComm.cmdRelayBuffer) == cmdRelayBufferLen) # stale command should be tossed
        # Send msg with destination that should be relayed
        self.tdmaComm.maxNumSlots = 7
        self.tdmaComm.meshPaths = [[]*7]*7
        self.tdmaComm.nodeParams.linkStatus = [[0, 1, 1, 0, 0, 0, 0],
                                               [1, 0, 0, 1, 0 ,0, 0],
                                               [1, 0, 0, 1, 0, 0, 0],
                                               [0, 1, 1, 0, 1, 1, 0],
                                               [0, 0, 0, 1, 0, 0, 1],
                                               [0, 0, 0, 1, 0, 0, 1],
                                               [0, 0, 0, 0, 1, 1, 0]]
        self.tdmaComm.updateShortestPaths()
        
        self.tdmaComm.cmdRelayBuffer = bytearray()
        destId = 3
        self.tdmaComm.nodeParams.config.nodeId = 2
        packet = self.tdmaComm.packageMeshPacket(destId, payloadBytes)
        self.tdmaComm.bufferTxMsg(packet)
        self.tdmaComm.sendBuffer()
        time.sleep(0.1)
        self.tdmaComm.readMsgs()
        self.tdmaComm.nodeParams.config.nodeId = 1
        self.tdmaComm.processMsgs()
        assert(len(self.tdmaComm.cmdRelayBuffer) > 0)

        # Send msg with destination that should not be relayed
        self.tdmaComm.cmdRelayBuffer = bytearray()
        destId = 4
        self.tdmaComm.nodeParams.config.nodeId = 2
        packet = self.tdmaComm.packageMeshPacket(destId, payloadBytes)
        self.tdmaComm.bufferTxMsg(packet)
        self.tdmaComm.sendBuffer()
        time.sleep(0.1)
        self.tdmaComm.readMsgs()
        self.tdmaComm.nodeParams.config.nodeId = 1
        self.tdmaComm.processMsgs()
        assert(len(self.tdmaComm.cmdRelayBuffer) == 0)
示例#26
0
    def test_sendMsg(self):
        """Test sendMsg method of TDMAComm."""
        # Test send only when conditions met
        self.tdmaComm.enabled = False
        self.tdmaComm.tdmaMode = TDMAMode.receive
        self.tdmaComm.transmitComplete = False
        assert(len(self.tdmaComm.radio.txBuffer) == 0)
        self.tdmaComm.radio.bufferTxMsg(b'12345')
        assert(len(self.tdmaComm.radio.txBuffer) > 0)
        self.tdmaComm.sendMsg()
        assert(len(self.tdmaComm.radio.txBuffer) > 0) # message not sent
        assert(self.tdmaComm.transmitComplete == False)
        self.tdmaComm.enabled = True
        self.tdmaComm.sendMsg()
        assert(len(self.tdmaComm.radio.txBuffer) > 0) # message still not sent
        self.tdmaComm.tdmaMode = TDMAMode.transmit
        self.tdmaComm.sendMsg()
        assert(len(self.tdmaComm.radio.txBuffer) == 0) # message sent
        

        # Test transmission of periodic commands
        #serBytes = self.tdmaComm.radio.getRxBytes() # clear incoming bytes
        #assert(len(self.tdmaComm.cmdBuffer) == 0)
        #assert(len(self.tdmaComm.cmdRelayBuffer) == 0)
        #cmd = Command(TDMACmds['MeshStatus'], {'commStartTimeSec': int(time.time()), 'status': TDMAStatus.nominal}, [TDMACmds['MeshStatus'], self.nodeParams.config.nodeId])
        #self.tdmaComm.tdmaCmds[TDMACmds['MeshStatus']] = cmd
        #self.tdmaComm.sendMsg()
        #time.sleep(0.1)
        #self.tdmaComm.readBytes()
        #serBytes = self.tdmaComm.radio.getRxBytes()
        #assert(len(serBytes) > 0)
        #assert(serBytes[-1:] == HDLC_END_TDMA) # check for end of message indicator

        # Test command relay buffer
        testMsg = b'1234567890'
        self.tdmaComm.radio.clearRxBuffer()
        self.tdmaComm.cmdRelayBuffer = testMsg
        self.tdmaComm.sendMsg()
        time.sleep(0.1)
        self.tdmaComm.readBytes()
        serBytes = self.tdmaComm.radio.getRxBytes()
        assert(testMsg in serBytes)
       
        # Test command buffer
        self.tdmaComm.radio.clearRxBuffer()
        testCmd = {'bytes': b'12345'}
        self.tdmaComm.cmdBuffer['key1'] = testCmd
        self.tdmaComm.sendMsg()
        assert(len(self.tdmaComm.cmdBuffer) == 0) # command buffer flushed out
        time.sleep(0.1)
        self.tdmaComm.readBytes()
        assert(len(self.tdmaComm.radio.getRxBytes()) > 0)

        ## Test meshQueue processing
        # Test no output for empty queue
        self.tdmaComm.sendMsg()
        time.sleep(0.1)
        self.tdmaComm.readBytes()
        assert(len(self.tdmaComm.radio.getRxBytes()) > 0) # nothing sent when meshQueue is empty (and no periodic commands)

        # Test broadcast message output
        cmd = Command(TDMACmds['MeshStatus'], {'commStartTimeSec': int(time.time()), 'status': TDMAStatus.nominal}, [TDMACmds['MeshStatus'], self.nodeParams.config.nodeId])
        self.tdmaComm.tdmaCmds[TDMACmds['MeshStatus']] = cmd
        encodedCmd = self.tdmaComm.tdmaCmdParser.encodeMsg(cmd.serialize())
        self.tdmaComm.sendMsg()
        time.sleep(0.1)
        self.tdmaComm.readBytes()
        assert(len(self.tdmaComm.radio.getRxBytes()) > 0) # message sent when periodic commands pending
        self.tdmaComm.parseMsgs()
        assert(len(self.tdmaComm.msgParser.parsedMsgs) == 1)
        packetHeader = struct.unpack('<BBHHH', self.tdmaComm.msgParser.parsedMsgs[0][0:8])
        assert(packetHeader[1] == 0) # broadcast message
        assert(encodedCmd in self.tdmaComm.msgParser.parsedMsgs[0]) # tdmaCmds included in message

        # Test destination specific output
        self.nodeParams.config.commConfig['recvAllMsgs'] = True # receive all messages, regardless of dest
        msg1 = b'1234567890'
        msg1Dest = 3
        msg2 = b'0987654321'
        msg2Dest = 5
        self.tdmaComm.meshQueueIn[msg1Dest] = msg1
        self.tdmaComm.meshQueueIn[msg2Dest] = msg2 
        self.tdmaComm.sendMsg()
        time.sleep(0.1)
        self.tdmaComm.readBytes()
        assert(len(self.tdmaComm.radio.getRxBytes()) > 0)
        self.tdmaComm.processMsgs()
        assert(len(self.tdmaComm.hostBuffer) > 0)
        assert(msg1 in self.tdmaComm.hostBuffer)
        assert(msg2 in self.tdmaComm.hostBuffer)

        # Test without receiving messages for other nodes
        self.tdmaComm.hostBuffer = bytearray()
        self.nodeParams.config.commConfig['recvAllMsgs'] = False
        msg1Dest = self.nodeParams.config.nodeId
        self.tdmaComm.meshQueueIn[msg1Dest] = msg1
        self.tdmaComm.meshQueueIn[msg2Dest] = msg2 
        self.tdmaComm.sendMsg()
        time.sleep(0.1)
        self.tdmaComm.readBytes()
        assert(len(self.tdmaComm.radio.getRxBytes()) > 0)
        self.tdmaComm.processMsgs()
        assert(len(self.tdmaComm.hostBuffer) > 0)
        assert(self.tdmaComm.hostBuffer == msg1)
示例#27
0
    def monitorBlockTx(self):
        """Monitors current status of block transmit."""
        if self.blockTxStatus['status'] == TDMABlockTxStatus.false:
            return

        elif self.blockTxStatus[
                'status'] == TDMABlockTxStatus.pending:  # monitor pending block request
            if self.blockTxStatus[
                    'txNode'] == self.nodeParams.config.nodeId:  # this node requested block tx
                # Check block request responses
                response = self.checkBlockResponse()
                if response == True:
                    # Confirm block tx
                    blockConfirmCmd = Command(
                        TDMACmds['BlockTxConfirmed'],
                        {'blockReqID': self.blockTxStatus['blockReqID']}, [
                            TDMACmds['BlockTxConfirmed'],
                            self.nodeParams.config.nodeId,
                            self.nodeParams.get_cmdCounter()
                        ])
                    self.radio.bufferTxMsg(
                        blockConfirmCmd.serialize(
                            self.nodeParams.clock.getTime()))
                    self.blockTxStatus['status'] = TDMABlockTxStatus.confirmed
                    return

                elif response == False:
                    # Cancel request
                    self.resetBlockTxStatus()
                    return

                # Check for request timeout
                if (self.frameStartTime - self.blockTxStatus['requestTime']
                    ) > self.nodeParams.config.commConfig[
                        'blockTxRequestTimeout'] * self.nodeParams.config.commConfig[
                            'frameLength']:
                    # Request timed out - reset status
                    self.resetBlockTxStatus()
                    return
            if self.frameStartTime >= self.blockTxStatus[
                    'startTime']:  # no block confirmed received
                # Cancel pending block
                self.resetBlockTxStatus()
                return

        elif self.blockTxStatus['status'] == TDMABlockTxStatus.confirmed:
            # Check for block start
            if self.frameStartTime >= self.blockTxStatus[
                    'startTime']:  # start block
                self.blockTxStatus['status'] = TDMABlockTxStatus.active
                self.nodeParams.tdmaStatus = TDMAStatus.blockTx

            # Send block transmit status message
            if self.blockTxStatus['txNode'] == self.nodeParams.config.nodeId:
                blockStatusCmd = Command(
                    TDMACmds['BlockTxStatus'], {
                        'blockReqID': self.blockTxStatus['blockReqID'],
                        'startTime': self.blockTxStatus['startTime'],
                        'length': self.blockTxStatus['length']
                    }, [
                        TDMACmds['BlockTxStatus'],
                        self.nodeParams.config.nodeId,
                        self.nodeParams.get_cmdCounter()
                    ])
                self.radio.bufferTxMsg(
                    blockStatusCmd.serialize(self.nodeParams.clock.getTime()))

        elif self.blockTxStatus[
                'status'] == TDMABlockTxStatus.active:  # block transmit in progress
            # Check for end of block transmit
            if self.blockTxStatus['blockTxComplete'] or (
                    self.frameStartTime - self.blockTxStatus['startTime']
            ) >= self.blockTxStatus['length'] * self.nodeParams.config.commConfig[
                    'frameLength'] or self.nodeParams.tdmaStatus == TDMAStatus.nominal:
                # Block transmit ended - reset status
                self.resetBlockTxStatus()
示例#28
0
    def checkPolling(self):

        # Update poll status
        for poll in self.networkPolls:
            # Respond to poll
            if (poll.voteSent == False):  # respond to poll
                cmdResponse = None
                if (poll.cmdId == TDMACmds['ConfigUpdate']):
                    if (poll.cmd['valid'] == True):
                        poll.votes[self.nodeParams.config.nodeId -
                                   1] = NetworkVote.Yes
                        cmdResponse = True
                    else:  # invalid config
                        poll.votes[self.nodeParams.config.nodeId -
                                   1] = NetworkVote.No
                        cmdResponse = False
                elif (poll.cmdId == TDMACmds['NetworkRestart']):
                    poll.votes[self.nodeParams.config.nodeId -
                               1] = NetworkVote.Yes
                    cmdResponse = True
                elif (poll.cmdId == TDMACmds['BlockTxRequest']):
                    if (self.blockTxAccepted or
                            self.comm.blockTxInProgress):  # reject new request
                        poll.votes[self.nodeParams.config.nodeId -
                                   1] = NetworkVote.No
                        cmdResponse = False
                    else:  # accept request
                        poll.votes[self.nodeParams.config.nodeId -
                                   1] = NetworkVote.Yes
                        cmdResponse = True
                else:  # rejected unrecognized command ids
                    poll.votes[self.nodeParams.config.nodeId -
                               1] = NetworkVote.No
                    cmdResponse = False

                # Send poll response
                print("Node " + str(self.nodeParams.config.nodeId) +
                      ": Sending command response")
                self.comm.tdmaCmds[NodeCmds['CmdResponse']] = Command(
                    NodeCmds['CmdResponse'], {
                        'cmdId': poll.cmdId,
                        'cmdCounter': poll.cmdCounter,
                        'cmdResponse': cmdResponse
                    },
                    [NodeCmds['CmdResponse'], self.nodeParams.config.nodeId])
                poll.voteSent = True

            # Process any pending command responses
            if (poll.cmdCounter in self.nodeParams.cmdResponse):
                for key in self.nodeParams.cmdResponse[poll.cmdCounter]:
                    if (self.nodeParams.cmdResponse[poll.cmdCounter][key] == 1
                        ):
                        poll.votes[key - 1] = NetworkVote.Yes
                    elif (self.nodeParams.cmdResponse[poll.cmdCounter][key] ==
                          0):
                        poll.votes[key - 1] = NetworkVote.No

                del self.nodeParams.cmdResponse[poll.cmdCounter]

            # Check for poll decision
            yesVotes = 0
            for node in range(0, self.nodeParams.config.maxNumNodes):
                if (node + 1 in poll.exclusions):
                    poll.votes[node] = NetworkVote.Excluded
                elif (self.nodeParams.nodeStatus[node].updating == False
                      ):  # node not updating
                    poll.votes[node] = NetworkVote.Excluded
                    poll.exclusions.append(node +
                                           1)  # add node to exclusion list
                elif (poll.votes[node] == NetworkVote.No):  # node voted no
                    poll.decision = VoteDecision.No
                    print(
                        "Node " + str(self.nodeParams.config.nodeId) +
                        ": Vote failed - ", poll.cmdId, poll.cmdCounter)
                elif (poll.votes[node] == NetworkVote.Yes):  # node voted yes
                    yesVotes += 1

            if (yesVotes == (self.nodeParams.config.maxNumNodes -
                             len(poll.exclusions))
                ):  # all present and not excluded notes have concurred
                poll.decision = VoteDecision.Yes
                print(
                    "Node " + str(self.nodeParams.config.nodeId) +
                    ": Vote succeeded - ", poll.cmdId, poll.cmdCounter)

        # Update poll status
        updatedPolls = []
        for poll in self.networkPolls:
            if (poll.decision == VoteDecision.Undecided):
                # Check expiration on undecided polls
                if (self.nodeParams.clock.getTime() <=
                    (poll.startTime +
                     self.nodeParams.config.commConfig['pollTimeout'])
                    ):  # poll has not yet expired
                    updatedPolls.append(poll)
                else:
                    print("Node " + str(self.nodeParams.config.nodeId) +
                          ": Clearing poll")

            else:  # take action on completed poll
                self.executeNetworkAction(poll)
        self.networkPolls = updatedPolls
示例#29
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)
示例#30
0
# 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()])
testCmds.update({cmdId: cmd})

# NodeCmds['GCSCmd']
cmdId = NodeCmds['GCSCmd']
cmdData = {'destId': 0, 'mode': 1}
cmd = Command(cmdId, cmdData, [cmdId, 0, nodeParams.get_cmdCounter()])
testCmds.update({cmdId: cmd})

# NodeCmds['ConfigRequest']
cmdId = NodeCmds['ConfigRequest']
cmdData = {'configHash': nodeParams.config.calculateHash()}
cmd = Command(cmdId, cmdData, [cmdId, 0, nodeParams.get_cmdCounter()])
testCmds.update({cmdId: cmd})

# NodeCmds['ParamUpdate']