def __init__(self, uri): self._event = Event() with SyncCrazyflie(uri, cf=Crazyflie(rw_cache='./cache')) as scf: helper = LighthouseMemHelper(scf.cf) helper.read_all_geos(self._geo_read_ready) self._event.wait() self._event.clear() helper.read_all_calibs(self._calib_read_ready) self._event.wait()
def __init__(self, uri, geo_dict, calib_dict): self._event = Event() with SyncCrazyflie(uri, cf=Crazyflie(rw_cache='./cache')) as scf: helper = LighthouseMemHelper(scf.cf) helper.write_geos(geo_dict, self._data_written) self._event.wait() self._event.clear() helper.write_calibs(calib_dict, self._data_written) self._event.wait()
def __init__(self, URI): # Tool to process the data from drone's sensors self.processing = Processing(URI) self.id = URI[-2:] cflib.crtp.init_drivers(enable_debug_driver=False) self.scf = SyncCrazyflie(URI, cf=Crazyflie(rw_cache='./cache')) self.cf = self.scf.cf # Connect callbacks from the Crazyflie API self.cf.connected.add_callback(self.connected) self.cf.disconnected.add_callback(self.disconnected) # Connect to the Crazyflie self.cf.open_link(URI)
def setUp(self): self.uri = 'radio://0/60/2M' self.cf_mock = MagicMock(spec=Crazyflie) self.cf_mock.connected = Caller() self.cf_mock.connection_failed = Caller() self.cf_mock.disconnected = Caller() self.cf_mock.open_link = AsyncCallbackCaller( cb=self.cf_mock.connected, args=[self.uri]).trigger self.sut = SyncCrazyflie(self.uri, self.cf_mock)
def connect_reality(self, uris): """ Set amount of drones to actual drones in reality and set up simulated drones to work with real ones. :param uris: URIs of the drones to connect to. """ # Update amount of drones to that of real drones self.update_drone_amount(len(uris)) # For every drone, create SyncCrazyflie object and store it, then connect to the drone via it for num, drone in enumerate(self.drones): drone.crazyflie = SyncCrazyflie(uris[num], cf=Crazyflie(rw_cache='./cache')) drone.crazyflie.open_link()
def setUp(self): self.uri = 'radio://0/60/2M' self.cf_mock = MagicMock(spec=Crazyflie) self.cf_mock.connected = Caller() self.cf_mock.connection_failed = Caller() self.cf_mock.disconnected = Caller() self.cf_mock.open_link = AsyncCallbackCaller( cb=self.cf_mock.connected, args=[self.uri], delay=0.2 ).trigger self.close_link_mock = AsyncCallbackCaller( cb=self.cf_mock.disconnected, args=[self.uri], delay=0.2 ) self.cf_mock.close_link = self.close_link_mock.trigger self.sut = SyncCrazyflie(self.uri, self.cf_mock)
def _hover_test(self): print("sending initial thrust of 0") self._cf.commander.send_setpoint(0,0,0,0); time.sleep(0.5); print("putting in althold") self._cf.param.set_value("flightmode.althold","True") print("Stay in althold for 7s") lg_stab = LogConfig(name='Stabilizer', period_in_ms=10) lg_stab.add_variable('stabilizer.roll','float') lg_stab.add_variable('stabilizer.pitch','float') lg_stab.add_variable('stabilizer.yaw','float') cf = Crazyflie(rw_cache='./cache') with SyncCrazyflie(available[0][0],cf=cf) as scf: with SyncLogger(scf, lg_stab) as logger: endTime = time.time()+10 it=0 self._cf.commander.send_setpoint(0.66,1,0,35000) time.sleep(2) #Bug here #self._cf.param.set_value("flightmode.althold","True") for log_entry in logger: print('HI') timestamp = log_entry[0] data = log_entry[1] logconf_name = log_entry[2] print('[%d][%s]: %s' % (timestamp,logconf_name,data)) #while it<200: #self._cf.commander.send_setpoint(roll, pitch, yawrate, thrust) #self._cf.commander.send_setpoint(0.66,-1,0,32767) self._cf.commander.send_setpoint(0.66,1,0,32767) self._cf.param.set_value("flightmode.althold","True") #self._cf.param.set_value("flightmode.poshold","False") #time.sleep(0.01) #it+=1 if time.time()>endTime: print("Close connection") self._cf.commander.send_setpoint(0,0,0,0) self._cf.close_link() break
def distance_measurement(): for uri in uris: with SyncCrazyflie(uri, cf=Crazyflie(rw_cache='./cache')) as scf: lpos = LogConfig(name='rxCNT', period_in_ms=500) lpos.add_variable('rxCNT.rxcnt10') lpos.add_variable('rxCNT.rxcnt20') lpos.add_variable('rxCNT.rxcnt30') lpos.add_variable('rxCNT.rxcnt40') scf.cf.log.add_config(lpos) lpos.data_received_cb.add_callback(pos_data) lpos.start() time.sleep(2) lpos.stop() df = pd.DataFrame( dt, columns=['uri', 'rxcnt10', 'rxcnt20', 'rxcnt30', 'rxcnt40']) df.to_csv('./rxcnt.csv', index=False) dt.clear() dt_mapper.clear() for uri in uris: with SyncCrazyflie(uri, cf=Crazyflie(rw_cache='./cache')) as scf: lpos = LogConfig(name='rxCNT', period_in_ms=500) lpos.add_variable('rangingCNT.rangingcnt10') lpos.add_variable('rangingCNT.rangingcnt20') lpos.add_variable('rangingCNT.rangingcnt30') lpos.add_variable('rangingCNT.rangingcnt40') scf.cf.log.add_config(lpos) lpos.data_received_cb.add_callback(pos_data2) lpos.start() time.sleep(2) lpos.stop() df = pd.DataFrame(dt, columns=[ 'uri', 'rangingcnt10', 'rangingcnt20', 'rangingcnt30', 'rangingcnt40' ]) df.to_csv('./rangingcnt.csv', index=False) print("done") return
def __init__(self, distance): """ Inicialização dos drivers, parâmetros do controle PID e decolagem do drone. """ self.distance = distance self.pid_foward = PID(distance, 0.01, 0.0001, 0.01, 500, -500, 0.7, -0.7) self.pid_yaw = PID(0, 0.33, 0.0, 0.33, 500, -500, 100, -100) self.pid_angle = PID(0.0, 0.01, 0.0, 0.01, 500, -500, 0.3, -0.3) self.pid_height = PID(0.0, 0.002, 0.0002, 0.002, 500, -500, 0.3, -0.2) cflib.crtp.init_drivers(enable_debug_driver=False) self.factory = CachedCfFactory(rw_cache='./cache') self.URI4 = 'radio://0/40/2M/E7E7E7E7E4' self.cf = Crazyflie(rw_cache='./cache') self.sync = SyncCrazyflie(self.URI4, cf=self.cf) self.sync.open_link() self.mc = MotionCommander(self.sync) self.cont = 0 self.notFoundCount = 0 self.calculator = DistanceCalculator() self.cap = cv2.VideoCapture(1) self.mc.take_off() time.sleep(1)
def main(): # Initialize the low-level drivers (don't list the debug drivers) cflib.crtp.init_drivers(enable_debug_driver=False) with SyncCrazyflie(URI, cf=Crazyflie(rw_cache='./cache')) as scf: damn = curses.initscr() damn.nodelay(1) curses.noecho() # We take off when the commander is created print("\rStart motion commander:") print("\r u/d - up/down") print("\r l/r - left/right") print("\r f/b - forward/back") print("\r c/w - turn left/right 90 degrees") print("\r i/I - circle left/right 360 degrees") print("\r q - quit") with MotionCommander(scf) as mc: time.sleep(TIME_SEC) while True: c = damn.getch() if c == ord('u'): # u - up mc.up(Z_STEP) elif c == ord('d'): # d - down mc.down(Z_STEP) elif c == ord('l'): # l - left mc.left(X_STEP) elif c == ord('r'): # r - right mc.right(X_STEP) elif c == ord('f'): # f - forward mc.forward(X_STEP) elif c == ord('b'): # b - backward mc.back(X_STEP) elif c == ord('w'): # clockwise mc.turn_right(CW_STEP) elif c == ord('c'): # counter clockwise mc.turn_left(CW_STEP) elif c == ord('i'): mc.circle_left(0.3) elif c == ord('I'): mc.circle_right(0.3) elif c == ord('q'): # q - quit break curses.echo() curses.endwin()
def run_flight(): cflib.crtp.init_drivers(enable_debug_driver=False) threads = [] for spec in SPEC: scf = SyncCrazyflie(spec[0], cf=Crazyflie(rw_cache='./cache')) scfs.append(scf) t = Thread(target=run_drone, args=(scf, spec), daemon=True) threads.append(t) t.start() for t in threads: t.join()
def setUp(self): self.uri = uri_helper.uri_from_env( default='radio://0/80/2M/E7E7E7E7E7') self.cf_mock = MagicMock(spec=Crazyflie) self.cf_mock.connected = Caller() self.cf_mock.connection_failed = Caller() self.cf_mock.disconnected = Caller() self.cf_mock.fully_connected = Caller() self.cf_mock.open_link = AsyncCallbackCaller(cb=self.cf_mock.connected, args=[self.uri], delay=0.2).trigger self.close_link_mock = AsyncCallbackCaller( cb=self.cf_mock.disconnected, args=[self.uri], delay=0.2) self.cf_mock.close_link = self.close_link_mock.trigger # Register a callback to be called when connected. Use it to trigger a callback # to trigger the call to the param.all_updated() callback self.cf_mock.connected.add_callback(self._connected_callback) self.sut = SyncCrazyflie(self.uri, cf=self.cf_mock)
def __init__(self, uri, threaded=False): super().__init__(threaded) # TODO: maybe add a parameter so people can change the default velocity # Initialize the low-level drivers (don't list the debug drivers) cflib.crtp.init_drivers(enable_debug_driver=False) # the connection to the crazyflie self._scf = SyncCrazyflie(uri, cf=Crazyflie(rw_cache='./cache')) # temp (or maybe will be permanent) state variable self._is_open = False self._running = False self._send_rate = 5 # want to send messages at 5Hz NOTE: the minimum is 2 Hz self._out_msg_queue = queue.Queue() # a queue for sending data between threads self._write_handle = threading.Thread(target=self.command_loop) self._write_handle.daemon = True # since can only command velocities and not positions, the connection # needs some awareness of the current position to be able to do # the math necessary self._current_position_xyz = [0.0, 0.0, 0.0] # [x, y, z]
def __init__(self, uri): self.got_data = False with SyncCrazyflie(uri, cf=Crazyflie(rw_cache='./cache')) as scf: mems = scf.cf.mem.get_mems(MemoryElement.TYPE_LH) count = len(mems) if count != 1: raise Exception('Unexpected nr of memories found:', count) print('Rquesting data') mems[0].update(self._data_updated) while not self.got_data: time.sleep(1)
def room_border(): with SyncCrazyflie(uri, cf=Crazyflie(rw_cache='./cache')) as scf: start_position_printing(scf) with PositionHlCommander( scf, x=0, y=0, z=0, default_velocity=0.3, default_height=0.2, controller=PositionHlCommander.CONTROLLER_MELLINGER) as pc: height = 1 pc.go_to(-1.3,-1.8,height) pc.go_to(1.3,-1.8,height) pc.go_to(1.3,1.8,height) pc.go_to(-1.3,1.8,height) pc.go_to(-1.3,-1.8,height)
def main(): try: #logfile reset myfile = open('SensorMaster.txt', 'w') myfile.write myfile.close() cflib.crtp.init_drivers(enable_debug_driver=False) scf = SyncCrazyflie(URI) fc = FlightCtrl(scf) m = Myo() Thread(target=fc.gesture_ctrl, args=(fc, gesture)).start() Thread(target=m.gesture_detection, args=(gesture, )).start() prev_t = 0 while True: t = int(time.time()) if scf.vbat is not None: if t % 20 == 0 and t != prev_t: # print every 20 seconds print "Battery voltage: %.2fV" % (scf.vbat, ) prev_t = t if t % 5 == 0 and t != prev_t and scf.vbat > MIN_VBAT and scf.vbat < WARN_VBAT: print "WARN: Battery voltage: %.2fV. Landing soon..." % ( scf.vbat, ) prev_t = t if t % 5 == 0 and scf.vbat < MIN_VBAT: print "Battery voltage %.2f too low; landing..." % ( scf.vbat) fc.mc.land() os.kill(os.getpid(), signal.SIGINT) time.sleep(0.1) except KeyboardInterrupt: print('\nClosing link...') scf.close_link() print('Shutting down...') os.kill(os.getpid(), signal.SIGINT) except Exception, e: print(str(e)) print('\nShutting down...') scf.close_link() sys.exit(0)
def main(): cflib.crtp.init_drivers(enable_debug_driver=False) with SyncCrazyflie(URI) as scf: with MotionCommander(scf) as mq90: mq90.forward(0.5) mq90.turn_right(144) mq90.forward(0.5) mq90.turn_right(144) mq90.forward(0.5) mq90.turn_right(144) mq90.forward(0.5) mq90.turn_right(144) mq90.forward(0.5) mq90.turn_right(144) mq90.land()
def complex_flight(): with SyncCrazyflie(uri, cf=Crazyflie(rw_cache='./cache')) as scf: with PositionHlCommander( scf, x=1.0, y=1.0, z=0.0, default_velocity=0.3, default_height=0.5, controller=PositionHlCommander.CONTROLLER_MELLINGER) as pc: pc.set_default_velocity(0.3) pc.set_default_height(1.0) #pc.go_to(1.0, 1.0) pc.go_to(3.0, 1.0) pc.go_to(2.0, 3.0) pc.go_to(1.0, 1.0)
def initDrone(self, posAddressList): print("Resetting and locating ", self.address) scf = SyncCrazyflie(self.address, cf=Crazyflie(rw_cache='./cache')) scf.open_link() self.reset_estimator(scf) self.start_position_printing(scf) time.sleep(0.2) self.pos posAddressList.append([self.pos, self.address]) print("added", [self.pos, self.address]) scf.close_link()
def __init__(self, uri, bs1, bs2): self.data_written = False with SyncCrazyflie(uri, cf=Crazyflie(rw_cache='./cache')) as scf: mems = scf.cf.mem.get_mems(MemoryElement.TYPE_LH) count = len(mems) if count != 1: raise Exception('Unexpected nr of memories found:', count) mems[0].geometry_data = [bs1, bs2] print('Writing data') mems[0].write_data(self._data_written) while not self.data_written: time.sleep(1)
def call(x, y, z, yawrate): URI = 'radio://0/80/1M' # Only output errors from the logging framework logging.basicConfig(level=logging.ERROR) if __name__ == '__main__': # Initialize the low-level drivers (don't list the debug drivers) cflib.crtp.init_drivers(enable_debug_driver=False) with SyncCrazyflie(URI, cf=Crazyflie(rw_cache='./cache')) as scf: cf = scf.cf with MotionCommander(scf) as mc: time.sleep(0) mc._set_vel_setpoint(x, y, z, yawrate) time.sleep(1) mc.stop()
def __init__(self, uri): self._event = Event() self._cf = Crazyflie(rw_cache='./cache') with SyncCrazyflie(uri, cf=self._cf) as scf: mems = scf.cf.mem.get_mems(MemoryElement.TYPE_DECK_MEMORY) count = len(mems) if count != 1: raise Exception('Unexpected nr of memories found:', count) mem = mems[0] mem.query_decks(self.query_complete_cb) self._event.wait() if len(mem.deck_memories.items()) == 0: print('No memories to read') for id, deck_mem in mem.deck_memories.items(): print('-----') print('Deck id:', id) print('Name:', deck_mem.name) print('is_started:', deck_mem.is_started) print('supports_read:', deck_mem.supports_read) print('supports_write:', deck_mem.supports_write) if deck_mem.supports_fw_upgrade: print('This deck supports FW upgrades') print( f' The required FW is: hash={deck_mem.required_hash}, ' f'length={deck_mem.required_length}, name={deck_mem.name}' ) print(' is_fw_upgrade_required:', deck_mem.is_fw_upgrade_required) if (deck_mem.is_bootloader_active): print(' In bootloader mode, ready to be flashed') else: print(' In FW mode') print('') if deck_mem.supports_read: print('Reading first 10 bytes of memory') self._event.clear() deck_mem.read(0, 10, self.read_complete, self.read_failed) self._event.wait()
def main(): cflib.crtp.init_drivers(enable_debug_driver=False) numVertex = int( input("Quin número de vertex vols que tingui la estrella?")) numRepeticions = int(input("Quants cops vols realitzar l'estrella?")) llargadaArestes = float( input("Longitud de les arestes (Entre 0.4m i 1 m)?")) with SyncCrazyflie(URI) as scf: with MotionCommander(scf) as mq90: grausAresta = 180 - (180 / numVertex) for repeticio in range(numRepeticions): for vertex in range(numVertex): mq90.forward(llargadaArestes) mq90.turn_right(grausAresta) mq90.land()
def run(self): while True: print("run") #load crazyflie driver cflib.crtp.init_drivers(enable_debug_driver=False) #conenct crazyflie with SyncCrazyflie(uri, cf=Crazyflie(rw_cache='./cache')) as scf: print("connected") cf = scf.cf #activate position commander self.activate_high_level_commander(cf) self.reset_estimator(cf) #Rückgabe der Position der Crazyflie self.start_position_printing(scf) #start statemachine self.stateMachine = StateMachine(self.position) #start queueHandler self.queueHandler(cf)
def talker(): pub = rospy.Publisher('chatter', String, queue_size=10) rospy.init_node('talker', anonymous=True) rate = rospy.Rate(10) # 10hz cflib.crtp.init_drivers(enable_debug_driver=False) cf = Crazyflie(rw_cache='./cache') while not rospy.is_shutdown(): with SyncCrazyflie(URI, cf=cf) as scf: with MotionCommander(scf) as motion_commander: with Multiranger(scf) as multiranger: #reset_estimator(scf) start_position_printing(scf) keep_flying = True while keep_flying: print("tadaaaaa-----", x) VELOCITY = 0.5 velocity_x = 0.0 velocity_y = 0.0 if is_close(multiranger.front): velocity_x -= VELOCITY if is_close(multiranger.back): velocity_x += VELOCITY if is_close(multiranger.left): velocity_y -= VELOCITY if is_close(multiranger.right): velocity_y += VELOCITY if is_close(multiranger.up): keep_flying = False hello_str = "hello world %s" % multiranger.front rospy.loginfo(hello_str) #pub.publish(hello_str) motion_commander.start_linear_motion( velocity_x, velocity_y, 0) #print(data['kalman.stateX']) time.sleep(0.1) print('Demo terminated!') rate.sleep()
def __init__(self, uri): self.got_data = False with SyncCrazyflie(uri, cf=Crazyflie(rw_cache='./cache')) as scf: mems = scf.cf.mem.get_mems(MemoryElement.TYPE_LH) count = len(mems) if count != 1: raise Exception('Unexpected nr of memories found:', count) lh_mem = mems[0] print('Requesting data') print('-- Geo 0') self.got_data = False lh_mem.read_geo_data(0, self._geo_data_updated, update_failed_cb=self._update_failed) while not self.got_data: time.sleep(1) print('-- Geo 1') self.got_data = False lh_mem.read_geo_data(1, self._geo_data_updated, update_failed_cb=self._update_failed) while not self.got_data: time.sleep(1) print('-- Calibration 0') self.got_data = False lh_mem.read_calib_data(0, self._calib_data_updated, update_failed_cb=self._update_failed) while not self.got_data: time.sleep(1) print('-- Calibration 1') self.got_data = False lh_mem.read_calib_data(1, self._calib_data_updated, update_failed_cb=self._update_failed) while not self.got_data: time.sleep(1)
def __init__(self, uri, geos, calibs): self.data_written = False self.result_received = False with SyncCrazyflie(uri, cf=Crazyflie(rw_cache='./cache')) as scf: mems = scf.cf.mem.get_mems(MemoryElement.TYPE_LH) count = len(mems) if count != 1: raise Exception('Unexpected nr of memories found:', count) lh_mem = mems[0] for bs, geo in geos.items(): self.data_written = False print('Write geoetry', bs, 'to RAM') lh_mem.write_geo_data(bs, geo, self._data_written, write_failed_cb=self._data_failed) while not self.data_written: time.sleep(0.1) for bs, calib in calibs.items(): self.data_written = False print('Write calibration', bs, 'to RAM') lh_mem.write_calib_data(bs, calib, self._data_written, write_failed_cb=self._data_failed) while not self.data_written: time.sleep(0.1) print('Persist data') scf.cf.loc.receivedLocationPacket.add_callback( self._data_persisted) scf.cf.loc.send_lh_persist_data_packet(list(range(16)), list(range(16))) while not self.result_received: time.sleep(0.1)
def main(): cflib.crtp.init_drivers(enable_debug_driver=False) numVertices = int( input("¿Qué número de vertices quieres que tenga la estrella?")) numRepeticiones = int( input("¿Cuántas veces quieres realizar la estrella?")) distanciaAristas = float( input("¿Longitud de las aristas (Entre 0.4m y 1 m)?")) with SyncCrazyflie(URI) as scf: with MotionCommander(scf) as mq90: gradosArista = 180 - (180 / numVertices) for repeticio in range(numRepeticiones): for vertex in range(numVertices): mq90.forward(distanciaAristas) mq90.turn_right(gradosArista) mq90.land()
def __init__(self, uriDrone, flightList): if len(flightList) != 0: #Setting up connection with SyncCrazyflie(uriDrone, cf=Crazyflie(rw_cache='./cache')) as scf: cf = scf.cf cf.param.set_value('kalman.resetEstimation', '1') time.sleep(0.1) cf.param.set_value('kalman.resetEstimation', '0') time.sleep(2) for flight in flightList: if flight[0] != flightTypes[ 0]: #If the user selected a flight type different than None for repeat in range(int(flight[5])): if flight[0] == flightTypes[1]: cf.commander.send_setpoint( float(flight[1]), float(flight[2]), float(flight[3]), int(flight[4])) #Thrust elif flight[0] == flightTypes[2]: cf.commander.send_velocity_world_setpoint( float(flight[1]), float(flight[2]), float(flight[3]), float(flight[4])) elif flight[0] == flightTypes[3]: cf.commander.send_zdistance_setpoint( float(flight[1]), float(flight[2]), float(flight[3]), float(flight[4])) cf.commander.send_hover_setpoint( float(flight[1]), float(flight[2]), float(flight[3]), float(flight[4])) time.sleep(float(flight[6]) / 1000) #cast it to seconds cf.commander.send_stop_setpoint()
def async_log_ranging(link_uri, log_cfg_name='TSranging', log_var={}, log_save_path="./default.csv", period_in_ms=100, keep_time_in_s=5): cflib.crtp.init_drivers() log_data = pd.DataFrame(columns=log_var.keys()) with SyncCrazyflie(link_uri=link_uri, cf=Crazyflie(rw_cache="./cache")) as scf: log_cfg = LogConfig(name=log_cfg_name, period_in_ms=period_in_ms) scf.cf.log.add_config(log_cfg) for log_var_name, log_var_type in log_var.items(): log_cfg.add_variable(log_cfg.name + '.' + log_var_name, log_var_type) log_cfg.data_received_cb.add_callback(async_log_cb) log_cfg.start() time.sleep(keep_time_in_s)
def fly_square(self, id): """ Example of simple logico to make the drone fly in a square trajectory at fixed speed""" # Sync with drone with SyncCrazyflie(id, cf=self._cf) as scf: # Send position commands with PositionHlCommander(scf) as pc: pc.up(1.0) # print('Moving up') pc.forward(1.0) # print('Moving forward') pc.left(1.0) # print('Moving left') pc.back(1.0) # print('Moving back') pc.right(1.0) # print('Moving right') self._disconnected
class SyncCrazyflieTest(unittest.TestCase): def setUp(self): self.uri = 'radio://0/60/2M' self.cf_mock = MagicMock(spec=Crazyflie) self.cf_mock.connected = Caller() self.cf_mock.connection_failed = Caller() self.cf_mock.disconnected = Caller() self.cf_mock.open_link = AsyncCallbackCaller( cb=self.cf_mock.connected, args=[self.uri]).trigger self.sut = SyncCrazyflie(self.uri, self.cf_mock) def test_different_underlying_cf_instances(self): # Fixture # Test scf1 = SyncCrazyflie('uri 1') scf2 = SyncCrazyflie('uri 2') # Assert actual1 = scf1.cf actual2 = scf2.cf self.assertNotEquals(actual1, actual2) def test_open_link(self): # Fixture # Test self.sut.open_link() # Assert self.assertTrue(self.sut.is_link_open()) def test_failed_open_link_raises_exception(self): # Fixture expected = 'Some error message' self.cf_mock.open_link = AsyncCallbackCaller( cb=self.cf_mock.connection_failed, args=[self.uri, expected]).trigger # Test try: self.sut.open_link() except Exception as e: actual = e.args[0] else: self.fail('Expect exception') # Assert self.assertEqual(expected, actual) def test_open_link_of_already_open_link_raises_exception(self): # Fixture self.sut.open_link() # Test # Assert with self.assertRaises(Exception): self.sut.open_link() def test_close_link(self): # Fixture self.sut.open_link() # Test self.sut.close_link() # Assert self.cf_mock.close_link.assert_called_once_with() self.assertFalse(self.sut.is_link_open()) def test_close_link_that_is_not_open(self): # Fixture # Test self.sut.close_link() # Assert self.assertFalse(self.sut.is_link_open()) def test_closed_if_connection_is_lost(self): # Fixture self.sut.open_link() # Test AsyncCallbackCaller( cb=self.cf_mock.disconnected, args=[self.uri]).call_and_wait() # Assert self.assertFalse(self.sut.is_link_open()) def test_open_close_with_context_mangement(self): # Fixture # Test with SyncCrazyflie(self.uri, self.cf_mock) as sut: self.assertTrue(sut.is_link_open()) # Assert self.cf_mock.close_link.assert_called_once_with()