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
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
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)
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
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)
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()
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)
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)
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
def processMsg(self, cmdId, msg, args): nodeStatus = args['nodeStatus'] comm = args['comm'] clock = args['clock'] if len(msg) > 0: # Parse command header header = deserialize(msg, cmdId, 'header') if header != None: updateNodeMsgRcvdStatus(nodeStatus, header, clock) # Check for command counter cmdStatus = checkCmdCounter(self, header, msg, comm) if cmdStatus == False: # old command counter return # Parse message contents if cmdId not in [ TDMACmds['TimeOffsetSummary'], TDMACmds['BlockData'], TDMACmds['LinkStatus'], TDMACmds['LinkStatusSummary'] ]: try: msgContents = deserialize(msg, cmdId, 'body') if msgContents == None: return except KeyError: print("Invalid command ID.") return # Process message by command id for case in switch(cmdId): if case(TDMACmds['TimeOffset']): if nodeStatus: nodeStatus[ header['sourceId'] - 1].timeOffset = msgContents['timeOffset'] / 100.0 break if case(TDMACmds['MeshStatus']): if self.nodeParams.commStartTime == []: # accept value if one not already present self.nodeParams.commStartTime = msgContents[ 'commStartTimeSec'] # store comm start time break if case(TDMACmds['TimeOffsetSummary'] ): # Compiled table of time offsets from all nodes # Calculate header size headerSize = calcsize(headers[CmdDict[cmdId].header]['format']) # Unpack message msgSize = calcsize(CmdDict[cmdId].packFormat) timeOffsetFormatSize = calcsize( CmdDict['TimeOffsetSummaryContents'].packFormat) numNodes = unpack(CmdDict[cmdId].packFormat, msg[headerSize:headerSize + msgSize])[0] if (len(msg) != (numNodes * timeOffsetFormatSize) + headerSize + msgSize): print("Serial message length incorrect length:", str(len(msg))) break for i in range(numNodes): # Extract time offset of all nodes msgContents = deserialize( msg[i * timeOffsetFormatSize + headerSize + msgSize:i * timeOffsetFormatSize + (timeOffsetFormatSize + headerSize + msgSize)], 'TimeOffsetSummaryContents', 'body') if msgContents == None: return nodeStatus[i].timeOffset = msgContents['offset'] / 100.0 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] break if case(TDMACmds['LinkStatusSummary'] ): # Complete table of links between nodes msgSize = self.nodeParams.config.maxNumNodes headerSize = calcsize(headers[CmdDict[cmdId].header]['format']) linkTable = unpack( '=' + msgSize * msgSize * CmdDict['LinkStatusSummaryContents'].packFormat, msg[headerSize:]) # Place received data into link status array for i in range(msgSize): for j in range(msgSize): self.nodeParams.linkStatus[i][j] = linkTable[i * msgSize + j] 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)