async def test_singleConnection(self): """ Test that we can get a packet with a single vehicle with single connection """ # Start the connection maxtrix self.connmtrx = ConnectionManager( self.loop, self.dialect, self.version, 0, 0) # Dict of vehicles self.allvehicles = VehicleManager(self.loop) # Module manager self.allModules = moduleManager( self.loop, self.dialect, self.version, False) # and link them all together await self.doEventLinkages() # add a link await self.allvehicles.add_vehicle("VehA", 255, 0, 4, 0, self.dialect, self.version, 'tcpserver:127.0.0.1:15000') # Start a remote connection (TCP) self.remoteClient = TCPConnection(rxcallback=self.newpacketcallback, dialect=self.dialect, mavversion=self.version, srcsystem=0, srccomp=0, server=False, name=self.cname) await asyncio.sleep(0.3) await self.loop.create_connection(lambda: self.remoteClient, self.ip, self.port) # wait for 0.02 sec await asyncio.sleep(0.02) # send a heartbeat packet pkt = self.mod.MAVLink_heartbeat_message( 5, 4, 0, 0, 0, int(self.version)) self.remoteClient.send_data(pkt.pack(self.mav, force_mavlink1=False)) await asyncio.sleep(0.02) self.remoteClient.close() # assert the vehicle recieved the packet assert len(self.allvehicles.get_vehicle("VehA").latestPacketDict) == 1 assert self.allvehicles.get_vehicle("VehA").latestPacketDict[0] == pkt
async def test_link_serial(self): """Test passing data over a serial connections""" # server = SerialConnection server = SerialConnection(rxcallback=self.newpacketcallback, dialect=self.dialect, mavversion=self.version, srcsystem=0, srccomp=0, name=self.sname) client = TCPConnection(rxcallback=self.newpacketcallback, dialect=self.dialect, mavversion=self.version, srcsystem=0, srccomp=0, server=True, name=self.cname) await asyncio.sleep(0.10) await serial_asyncio.create_serial_connection(self.loop, lambda: server, self.sPort, self.baud) await self.loop.create_server(lambda: client, self.ip, self.port) # wait for 1.00 sec await asyncio.sleep(1.0) # send a mavlink packet each way: pkt = self.mod.MAVLink_heartbeat_message( 5, 4, 0, 0, 0, int(self.version)) client.send_data(pkt.pack(self.mav, force_mavlink1=False)) server.send_data(pkt.pack(self.mav, force_mavlink1=False)) # wait for 0.30 sec await asyncio.sleep(0.30) client.close() server.close() # Assert the packets were sent assert self.cnum == 1 assert self.snum == 1
async def test_link_tcp_client(self): """Test passing data when there's only a client present""" client = TCPConnection(rxcallback=self.newpacketcallback, dialect=self.dialect, mavversion=self.version, srcsystem=0, srccomp=0, server=False, name=self.cname) try: await self.loop.create_connection(lambda: client, self.ip, self.port) except ConnectionRefusedError: pass # This is the exception we want # send a mavlink packet: pkt = self.mod.MAVLink_heartbeat_message(5, 4, 0, 0, 0, int(self.version)) client.send_data(pkt.pack(self.mav, force_mavlink1=False)) # wait for 0.10 sec await asyncio.sleep(0.10) client.close() # Assert the packets were not sent assert self.cnum == 0
class IntegratedTest(asynctest.TestCase): """ Class to test the integrated link-vehicle-module connections """ def setUp(self): """Set up some data that is reused in many tests""" self.dialect = 'ardupilotmega' self.version = 2.0 self.port = 15000 self.ip = "127.0.0.1" self.cname = 'tcpclient:127.0.0.1:15000' self.mod = getpymavlinkpackage(self.dialect, self.version) self.mav = self.mod.MAVLink( self, srcSystem=4, srcComponent=0, use_native=False) self.connmtrx = None self.allvehicles = None self.allModules = None self.cnum = 0 def newpacketcallback(self, pkt, strconnection): """Callback when a link has a new packet""" if pkt.get_type != 'BAD_DATA': if strconnection == self.cname: self.cnum += 1 async def tearDown(self): """Called at the end of each test""" if self.allvehicles: for veh in self.allvehicles.get_vehiclelist(): await self.allvehicles.remove_vehicle(veh) if self.connmtrx: await self.connmtrx.stoploop() # for task in asyncio.Task.all_tasks(): # task.cancel() async def doEventLinkages(self): """Create the event linkages. Assumes that connmtrx, allvehicles, allModules have been initialised """ # event links from connmaxtrix -> vehicle manager self.connmtrx.onPacketAttach(self.allvehicles.onPacketRecieved) # event links from vehicle manager -> connmatrix self.allvehicles.onPacketBufTxAttach(self.connmtrx.outgoingPacket) await self.allvehicles.onLinkAddAttach(self.connmtrx.addVehicleLink) await self.allvehicles.onLinkRemoveAttach(self.connmtrx.removeLink) # event links from module manager -> vehicle manager self.allModules.onPktTxAttach(self.allvehicles.send_message) self.allModules.onVehListAttach(self.allvehicles.get_vehiclelist) self.allModules.onVehGetAttach(self.allvehicles.get_vehicle) # event links vehicle manager -> module manager self.allvehicles.onAddVehicleAttach(self.allModules.addVehicle) self.allvehicles.onRemoveVehicleAttach(self.allModules.removeVehicle) self.allvehicles.onPacketRxAttach(self.allModules.incomingPacket) async def test_startup(self): """ Test that we can cleanly startup and shutdown """ # Start the connection maxtrix self.connmtrx = ConnectionManager( self.loop, self.dialect, self.version, 0, 0) # Dict of vehicles self.allvehicles = VehicleManager(self.loop) # Module manager self.allModules = moduleManager( self.loop, self.dialect, self.version, False) # and link them all together await self.doEventLinkages() async def test_singleConnection(self): """ Test that we can get a packet with a single vehicle with single connection """ # Start the connection maxtrix self.connmtrx = ConnectionManager( self.loop, self.dialect, self.version, 0, 0) # Dict of vehicles self.allvehicles = VehicleManager(self.loop) # Module manager self.allModules = moduleManager( self.loop, self.dialect, self.version, False) # and link them all together await self.doEventLinkages() # add a link await self.allvehicles.add_vehicle("VehA", 255, 0, 4, 0, self.dialect, self.version, 'tcpserver:127.0.0.1:15000') # Start a remote connection (TCP) self.remoteClient = TCPConnection(rxcallback=self.newpacketcallback, dialect=self.dialect, mavversion=self.version, srcsystem=0, srccomp=0, server=False, name=self.cname) await asyncio.sleep(0.3) await self.loop.create_connection(lambda: self.remoteClient, self.ip, self.port) # wait for 0.02 sec await asyncio.sleep(0.02) # send a heartbeat packet pkt = self.mod.MAVLink_heartbeat_message( 5, 4, 0, 0, 0, int(self.version)) self.remoteClient.send_data(pkt.pack(self.mav, force_mavlink1=False)) await asyncio.sleep(0.02) self.remoteClient.close() # assert the vehicle recieved the packet assert len(self.allvehicles.get_vehicle("VehA").latestPacketDict) == 1 assert self.allvehicles.get_vehicle("VehA").latestPacketDict[0] == pkt
async def initLink(self, strconnection: str): """Try initialising a connection. returns True if connection was successful, False otherwise""" constr = strconnection.split(":") newlink = None try: if constr[0] == "udpserver": newlink = UDPConnection(rxcallback=self.incomingPacket, clcallback=self.closelinkcallback, dialect=self.dialect, mavversion=self.mavversion, server=True, srcsystem=self.sourceSystem, srccomp=self.sourceComponent, name=strconnection) trans = self.loop.create_datagram_endpoint( lambda: newlink, local_addr=(constr[1], constr[2])) await asyncio.wait_for(trans, timeout=0.2) elif constr[0] == "udpclient": newlink = UDPConnection(rxcallback=self.incomingPacket, clcallback=self.closelinkcallback, dialect=self.dialect, mavversion=self.mavversion, server=False, srcsystem=self.sourceSystem, srccomp=self.sourceComponent, name=strconnection) trans = self.loop.create_datagram_endpoint( lambda: newlink, remote_addr=(constr[1], constr[2])) await asyncio.wait_for(trans, timeout=0.2) elif constr[0] == "serial": newlink = SerialConnection(rxcallback=self.incomingPacket, clcallback=self.closelinkcallback, dialect=self.dialect, mavversion=self.mavversion, srcsystem=self.sourceSystem, srccomp=self.sourceComponent, name=strconnection) trans = serial_asyncio.create_serial_connection(self.loop, lambda: newlink, constr[1], int(constr[2])) await asyncio.wait_for(trans, timeout=0.2) elif constr[0] == "tcpclient": newlink = TCPConnection(rxcallback=self.incomingPacket, clcallback=self.closelinkcallback, dialect=self.dialect, mavversion=self.mavversion, server=False, srcsystem=self.sourceSystem, srccomp=self.sourceComponent, name=strconnection) trans = self.loop.create_connection( lambda: newlink, constr[1], int(constr[2])) await asyncio.wait_for(trans, timeout=0.2) elif constr[0] == "tcpserver": newlink = TCPConnection(rxcallback=self.incomingPacket, clcallback=self.closelinkcallback, dialect=self.dialect, mavversion=self.mavversion, server=True, srcsystem=self.sourceSystem, srccomp=self.sourceComponent, name=strconnection) await self.loop.create_server(lambda: newlink, constr[1], int(constr[2])) else: logging.debug("Bad link type: %s", constr) return False # ok, we've got a link self.linkdict[strconnection] = newlink logging.debug("Added link - %s", strconnection) return True except(OSError, asyncio.TimeoutError): logging.debug("Can't connect - %s", strconnection) self.linkdict[strconnection] = None return False
async def test_outgoingdistribution(self): """Test outgoing packets (from gcs) are distributed correctly""" # -VehA: LinkA,LinkB, VehB: LinkB, VehC: LinkC await self.VehA.setHearbeatRate(0) await self.VehB.setHearbeatRate(0) await self.VehC.setHearbeatRate(0) matrix = ConnectionManager( self.loop, self.dialect, self.version, 0, 0, 0.05) matrix.onPacketAttach(self.newpacketcallbackVeh) self.VehA.onPacketTxAttach(matrix.outgoingPacket) self.VehB.onPacketTxAttach(matrix.outgoingPacket) self.VehC.onPacketTxAttach(matrix.outgoingPacket) await matrix.addVehicleLink(self.VehA.name, self.VehA.target_system, self.linkA) await matrix.addVehicleLink(self.VehA.name, self.VehA.target_system, self.linkB) await matrix.addVehicleLink(self.VehB.name, self.VehB.target_system, self.linkB) await matrix.addVehicleLink(self.VehC.name, self.VehC.target_system, self.linkC) # now wait for a bit await asyncio.sleep(0.15) # now connect the other sides tcpserver = TCPConnection(rxcallback=self.newpacketcallbackLnk, dialect=self.dialect, mavversion=self.version, srcsystem=0, srccomp=0, server=True, name='tcpserver:127.0.0.1:15001') tcpclient = TCPConnection(rxcallback=self.newpacketcallbackLnk, dialect=self.dialect, mavversion=self.version, srcsystem=0, srccomp=0, server=False, name='tcpclient:127.0.0.1:15020') udpserver = UDPConnection(rxcallback=self.newpacketcallbackLnk, dialect=self.dialect, mavversion=self.version, srcsystem=0, srccomp=0, server=True, name='udpserver:127.0.0.1:15002') await self.loop.create_server(lambda: tcpserver, self.ip, 15001) await self.loop.create_connection(lambda: tcpclient, self.ip, 15020) await self.loop.create_datagram_endpoint(lambda: udpserver, local_addr=(self.ip, 15002)) # send packets on each link and wait await asyncio.sleep(0.15) # send packet from the GCS of VehA, VehB and VehC pktbytesA = self.VehA.sendPacket(self.mod.MAVLINK_MSG_ID_HEARTBEAT, type=self.mod.MAV_TYPE_GCS, autopilot=self.mod.MAV_AUTOPILOT_INVALID, base_mode=0, custom_mode=0, system_status=0, mavlink_version=int(self.VehA.mavversion)) await asyncio.sleep(0.10) pktbytesB = self.VehB.sendPacket(self.mod.MAVLINK_MSG_ID_HEARTBEAT, type=self.mod.MAV_TYPE_GCS, autopilot=self.mod.MAV_AUTOPILOT_INVALID, base_mode=0, custom_mode=0, system_status=0, mavlink_version=int(self.VehB.mavversion)) await asyncio.sleep(0.10) pktbytesC = self.VehC.sendPacket(self.mod.MAVLINK_MSG_ID_HEARTBEAT, type=self.mod.MAV_TYPE_GCS, autopilot=self.mod.MAV_AUTOPILOT_INVALID, base_mode=0, custom_mode=0, system_status=0, mavlink_version=int(self.VehC.mavversion)) # wait for packets to send await asyncio.sleep(0.15) # and close everything await matrix.stoploop() tcpserver.close() tcpclient.close() udpserver.close() # assert the links are all still there assert len(matrix.getAllVeh()) == 3 assert len(matrix.linkdict) == 3 # assert packets were recived on the endpoints assert self.rxdata['tcpserver:127.0.0.1:15001'][0].get_msgbuf( ) == pktbytesA assert self.rxdata['tcpclient:127.0.0.1:15020'][0].get_msgbuf( ) == pktbytesC assert self.rxdata['tcpclient:127.0.0.1:15020'][1].get_msgbuf( ) == pktbytesB assert self.rxdata['udpserver:127.0.0.1:15002'][0].get_msgbuf( ) == pktbytesC
async def test_incomingdistribution(self): """Test incoming packets (from vehicle) are distributed correctly""" # -VehA: LinkA,LinkB, VehB: LinkB, VehC: LinkC matrix = ConnectionManager( self.loop, self.dialect, self.version, 0, 0, 0.05) matrix.onPacketAttach(self.newpacketcallbackVeh) await matrix.addVehicleLink(self.VehA.name, self.VehA.target_system, self.linkA) await matrix.addVehicleLink(self.VehA.name, self.VehA.target_system, self.linkB) await matrix.addVehicleLink(self.VehB.name, self.VehB.target_system, self.linkB) await matrix.addVehicleLink(self.VehC.name, self.VehC.target_system, self.linkD) # now wait for a bit await asyncio.sleep(0.10) # now connect the other sides tcpserver = TCPConnection(rxcallback=self.newpacketcallbackLnk, dialect=self.dialect, mavversion=self.version, srcsystem=0, srccomp=0, server=True, name='tcpserver:127.0.0.1:15001') tcpclient = TCPConnection(rxcallback=self.newpacketcallbackLnk, dialect=self.dialect, mavversion=self.version, srcsystem=0, srccomp=0, server=False, name='tcpclient:127.0.0.1:15020') udpclient = UDPConnection(rxcallback=self.newpacketcallbackLnk, dialect=self.dialect, mavversion=self.version, srcsystem=0, srccomp=0, server=False, name='udpclient:127.0.0.1:15021') await self.loop.create_server(lambda: tcpserver, self.ip, 15001) await self.loop.create_connection(lambda: tcpclient, self.ip, 15020) await self.loop.create_datagram_endpoint(lambda: udpclient, remote_addr=(self.ip, 15021)) # send packets on each link and wait await asyncio.sleep(0.10) pkt = self.mod.MAVLink_heartbeat_message( 5, 4, 0, 0, 0, int(self.version)) pktbytes = pkt.pack(self.mavUAS, force_mavlink1=False) pktbytesone = pkt.pack(self.mavoneUAS, force_mavlink1=False) # send packet to VehA on LinkA tcpserver.send_data(pktbytes) await asyncio.sleep(0.10) # send new (updated) packet to VehA on LinkB pktupdate = self.mod.MAVLink_heartbeat_message( 5, 3, 0, 0, 0, int(self.version)) pktbytesupdate = pktupdate.pack(self.mavUAS, force_mavlink1=False) tcpclient.send_data(pktbytesupdate) # need a small sleep here otherwise the linkB gets confused await asyncio.sleep(0.10) # send packet to VehB on linkB tcpclient.send_data(pktbytesone) await asyncio.sleep(0.10) # send packet to VehC on LinkC udpclient.send_data(pktbytes) # wait for packets to send await asyncio.sleep(0.10) # and close everything await matrix.stoploop() tcpserver.close() tcpclient.close() udpclient.close() # assert the links are all still there assert len(matrix.getAllVeh()) == 3 assert len(matrix.linkdict) == 3 # assert packets were recived assert self.vehpkts[self.VehA.name][0].get_msgbuf() == pktbytes assert self.vehpkts[self.VehA.name][1].get_msgbuf() == pktbytesupdate assert self.vehpkts[self.VehB.name][0].get_msgbuf() == pktbytesone assert self.vehpkts[self.VehC.name][0].get_msgbuf() == pktbytes
async def test_linkretry_tcp(self): """For each of the TCP link types, test that they keep re-trying to connect, by only adding in the other side of the link 0.5 sec after startup""" matrix = ConnectionManager( self.loop, self.dialect, self.version, 0, 0, 0.05) matrix.onPacketAttach(self.newpacketcallbackVeh) await matrix.addVehicleLink(self.VehA.name, self.VehA.target_system, self.linkA) await matrix.addVehicleLink(self.VehB.name, self.VehB.target_system, self.linkB) # now wait for a bit await asyncio.sleep(0.10) # now connect the other sides tcpserver = TCPConnection(rxcallback=self.newpacketcallbackLnk, dialect=self.dialect, mavversion=self.version, srcsystem=0, srccomp=0, server=True, name='tcpserver:127.0.0.1:15001') tcpclient = TCPConnection(rxcallback=self.newpacketcallbackLnk, dialect=self.dialect, mavversion=self.version, srcsystem=0, srccomp=0, server=False, name='tcpclient:127.0.0.1:15020') await self.loop.create_server(lambda: tcpserver, self.ip, 15001) await self.loop.create_connection(lambda: tcpclient, self.ip, 15020) # send packets on each link and wait await asyncio.sleep(0.20) pkt = self.mod.MAVLink_heartbeat_message( 5, 4, 0, 0, 0, int(self.version)) pktbytes = pkt.pack(self.mavUAS, force_mavlink1=False) pktbytesone = pkt.pack(self.mavoneUAS, force_mavlink1=False) tcpserver.send_data(pktbytes) tcpclient.send_data(pktbytesone) await asyncio.sleep(0.20) await matrix.stoploop() tcpserver.close() tcpclient.close() # assert the links are all still there assert len(matrix.getAllVeh()) == 2 assert len(matrix.linkdict) == 2 # assert packets were recived on both links (vehicles) in the matrix assert self.vehpkts[self.VehA.name][0].get_msgbuf() == pktbytes assert self.vehpkts[self.VehB.name][0].get_msgbuf() == pktbytesone
async def test_link_baddata(self): """Test passing corrupted data between two tcplink connections""" client = TCPConnection(rxcallback=self.newpacketcallback, dialect=self.dialect, mavversion=self.version, srcsystem=0, srccomp=0, server=False, name=self.cname) server = TCPConnection(rxcallback=self.newpacketcallback, dialect=self.dialect, mavversion=self.version, srcsystem=0, srccomp=0, server=True, name=self.sname) await self.loop.create_server(lambda: server, self.ip, self.port) await self.loop.create_connection(lambda: client, self.ip, self.port) # wait for 0.10 sec await asyncio.sleep(0.10) # send a mavlink packet each way: pkt = self.mod.MAVLink_heartbeat_message(5, 4, 0, 0, 0, int(self.version)) packeddata = pkt.pack(self.mav, force_mavlink1=False) corruptdata = b'q837ot4c' client.send_data(packeddata + corruptdata) server.send_data(corruptdata + packeddata) # wait for 0.10 sec await asyncio.sleep(0.10) client.close() server.close() # Assert only the correct packets were sent assert self.cnum == 1 assert self.snum == 1