def test_last_analog_channel_state_can_be_read(self): rc = RemoteController() for i in range(10): analog = [0] * 10 # ith button is pressed analog[i] = 255 rc.tick( RemoteControllerCommand(buttons=[False] * 32, analog=analog)) for j in range(10): self.assertEqual(analog[i], rc.analog_value(i))
def test_requested_channels_are_passed_to_analog_handlers(self): rc = RemoteController() mock24 = Mock() mock3 = Mock() mock_invalid = Mock() rc.on_analog_values([2, 4], mock24) rc.on_analog_values([3], mock3) rc.on_analog_values([3, 11], mock_invalid) rc.tick(RemoteControllerCommand(buttons=[False] * 32, analog=[255, 254, 253, 123, 43, 65, 45, 42])) self.assertEqual(mock24.call_count, 1) self.assertEqual(mock3.call_count, 1) # invalid channels are silently ignored self.assertEqual(mock_invalid.call_count, 0) self.assertEqual(mock24.call_args[0][0], [253, 43]) self.assertEqual(mock3.call_args[0][0], [123])
def __init__(self, interface: RevvyControl, revvy, sound_paths, sw_version, default_config=None): print("RobotManager: __init__()") self.needs_interrupting = True self._configuring = False self._robot = Robot(interface, sound_paths, sw_version) self._interface = interface self._ble = revvy self._default_configuration = default_config or RobotConfig() self._status_update_thread = periodic(self._update, 0.02, "RobotStatusUpdaterThread") self._background_fn_lock = Lock() self._background_fns = [] rc = RemoteController() rcs = RemoteControllerScheduler(rc) rcs.on_controller_detected(self._on_controller_detected) rcs.on_controller_lost(self._on_controller_lost) self._remote_controller = rc self._remote_controller_scheduler = rcs self._remote_controller_thread = create_remote_controller_thread(rcs) self._resources = { 'led_ring': Resource(), 'drivetrain': Resource(), 'sound': Resource(), **{ 'motor_{}'.format(port.id): Resource() for port in self._robot.motors }, **{ 'sensor_{}'.format(port.id): Resource() for port in self._robot.sensors } } revvy['live_message_service'].register_message_handler( self._remote_controller_scheduler.data_ready) revvy.on_connection_changed(self._on_connection_changed) self._scripts = ScriptManager(self) self._config = self._default_configuration self._status_code = RevvyStatusCode.OK self.exited = False
def test_buttons_are_edge_triggered(self): rc = RemoteController() mocks = [] for i in range(32): mock = Mock() rc.on_button_pressed(i, mock) mocks.append(mock) for i in range(32): buttons = [False] * 32 rc.tick(RemoteControllerCommand(buttons=buttons, analog=[0] * 10)) # ith button is pressed buttons[i] = True rc.tick(RemoteControllerCommand(buttons=buttons, analog=[0] * 10)) # button is kept pressed rc.tick(RemoteControllerCommand(buttons=buttons, analog=[0] * 10)) for j in range(32): self.assertEqual(mocks[j].call_count, 1 if i == j else 0) mocks[j].reset_mock()
def test_last_button_pressed_state_can_be_read(self): rc = RemoteController() rc.tick(RemoteControllerCommand(buttons=[False] * 32, analog=[0] * 10)) for i in range(32): buttons = [False] * 32 # ith button is pressed buttons[i] = True rc.tick(RemoteControllerCommand(buttons=buttons, analog=[0] * 10)) for j in range(32): self.assertEqual(buttons[i], rc.is_button_pressed(i))
def __init__(self, robot: Robot, sw_version, revvy_ble): self._log = get_logger('RobotManager') self._log('init') self.needs_interrupting = True self._configuring = False self._robot = robot self._ble = revvy_ble self._sw_version = sw_version self._status_update_thread = periodic(self._update, 0.005, "RobotStatusUpdaterThread") self._background_fns = [] rc = RemoteController() rcs = RemoteControllerScheduler(rc) rcs.on_controller_detected(self._on_controller_detected) rcs.on_controller_lost(self._on_controller_lost) self._remote_controller = rc self._remote_controller_thread = create_remote_controller_thread(rcs) self._resources = { 'led_ring': Resource('RingLed'), 'drivetrain': Resource('DriveTrain'), 'sound': Resource('Sound'), **{ f'motor_{port.id}': Resource(f'Motor {port.id}') for port in self._robot.motors }, **{ f'sensor_{port.id}': Resource(f'Sensor {port.id}') for port in self._robot.sensors } } revvy_ble['live_message_service'].register_message_handler( rcs.data_ready) revvy_ble.on_connection_changed(self._on_connection_changed) self._scripts = ScriptManager(self) self._config = empty_robot_config self._status_code = RevvyStatusCode.OK self.exited = Event() self.start_remote_controller = self._remote_controller_thread.start
def test_reset_removed_button_and_analog_handlers_and_clears_stored_data( self): mock = Mock() rc = RemoteController() rc.tick(RemoteControllerCommand(buttons=[False] * 32, analog=[])) rc.on_analog_values([2, 4], mock) rc.on_analog_values([3], mock) rc.on_button_pressed(5, mock) rc.tick( RemoteControllerCommand( buttons=[True] * 32, analog=[255, 254, 253, 123, 43, 65, 45, 42])) self.assertEqual(3, mock.call_count) self.assertEqual(254, rc.analog_value(1)) self.assertTrue(rc.is_button_pressed(1)) mock.reset_mock() rc.reset() self.assertEqual(0, rc.analog_value(1)) self.assertFalse(rc.is_button_pressed(1)) rc.tick( RemoteControllerCommand( buttons=[True] * 32, analog=[255, 254, 253, 123, 43, 65, 45, 42])) self.assertEqual(0, mock.call_count)
def test_error_raised_for_invalid_button(self): rc = RemoteController() self.assertRaises(IndexError, lambda: rc.on_button_pressed(32, lambda: None))
def test_remote_controller_buttons_need_initial_zero_state(self): mock = Mock() rc = RemoteController() rc.on_button_pressed(5, mock) rc.tick(RemoteControllerCommand(buttons=[True] * 32, analog=[])) self.assertEqual(0, mock.call_count) self.assertFalse(rc.is_button_pressed(1)) rc.tick(RemoteControllerCommand(buttons=[False] * 32, analog=[])) rc.tick(RemoteControllerCommand(buttons=[True] * 32, analog=[])) self.assertEqual(1, mock.call_count) self.assertTrue(rc.is_button_pressed(1)) rc.tick(RemoteControllerCommand(buttons=[False] * 32, analog=[])) mock.reset_mock() rc.reset() rc.tick(RemoteControllerCommand(buttons=[True] * 32, analog=[])) rc.tick(RemoteControllerCommand(buttons=[True] * 32, analog=[])) self.assertEqual(0, mock.call_count) self.assertFalse(rc.is_button_pressed(1))