def test_transform_raw_data_packet_to_sample_raw_aux( self, mock_parse_packet_standard_raw_aux): data = sample_packet_standard_raw_aux(0) parser = ParseRaw() parser.transform_raw_data_packet_to_sample(data) mock_parse_packet_standard_raw_aux.assert_called_once()
def test_transform_raw_data_packets_to_sample(self): datas = [sample_packet(0), sample_packet(1), sample_packet(2)] parser = ParseRaw(gains=[24, 24, 24, 24, 24, 24, 24, 24]) samples = parser.transform_raw_data_packets_to_sample(datas) self.assertEqual(len(samples), len(datas)) for i in range(len(samples)): self.assertEqual(samples[i].sample_number, i)
def test_get_ads1299_scale_factors_volts(self): gains = [24, 24, 24, 24, 24, 24, 24, 24] expected_scale_factors = [] for gain in gains: scale_factor = 4.5 / float((pow(2, 23) - 1)) / float(gain) expected_scale_factors.append(scale_factor) parser = ParseRaw() actual_scale_factors = parser.get_ads1299_scale_factors(gains) self.assertEqual( actual_scale_factors, expected_scale_factors, "should be able to get scale factors for gains in volts")
class WiFiShieldServer(asyncore.dispatcher): def __init__(self, host, port, callback=None, gains=None, high_speed=True, daisy=False): asyncore.dispatcher.__init__(self) self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.set_reuse_addr() self.bind((host, port)) self.daisy = daisy self.listen(5) self.callback = None self.handler = None self.parser = ParseRaw(gains=gains) self.high_speed = high_speed def handle_accept(self): pair = self.accept() if pair is not None: sock, addr = pair print('Incoming connection from %s' % repr(addr)) self.handler = WiFiShieldHandler(sock, self.callback, high_speed=self.high_speed, parser=self.parser, daisy=self.daisy) def set_callback(self, callback): self.callback = callback if self.handler is not None: self.handler.callback = callback def set_daisy(self, daisy): self.daisy = daisy if self.handler is not None: self.handler.daisy = daisy def set_gains(self, gains): self.parser.set_ads1299_scale_factors(gains) def set_parser(self, parser): self.parser = parser if self.handler is not None: self.handler.parser = parser
def __init__(self, host, port, callback=None, gains=None, high_speed=True, daisy=False): asyncore.dispatcher.__init__(self) self.create_socket(socket.AF_INET, socket.SOCK_STREAM) self.set_reuse_addr() self.bind((host, port)) self.daisy = daisy self.listen(5) self.callback = None self.handler = None self.parser = ParseRaw(gains=gains) self.high_speed = high_speed
def set_channel_settings(self, channel, enabled=True, gain=24, input_type=0, include_bias=True, use_srb2=True, use_srb1=True): try: if channel > self.num_channels: raise ValueError('Cannot set non-existant channel') if self.board_type == k.BOARD_GANGLION: raise ValueError('Cannot use with Ganglion') ch_array = list("12345678QWERTYUI") #defaults command = list("x1060110X") # Set channel command[1] = ch_array[channel - 1] # Set power down if needed (default channel enabled) if not enabled: command[2] = '1' # Set gain (default 24) if gain == 1: command[3] = '0' if gain == 2: command[3] = '1' if gain == 4: command[3] = '2' if gain == 6: command[3] = '3' if gain == 8: command[3] = '4' if gain == 12: command[3] = '5' #TODO: Implement input type (default normal) # Set bias inclusion (default include) if not include_bias: command[5] = '0' # Set srb2 use (default use) if not use_srb2: command[6] = '0' # Set srb1 use (default don't use) if use_srb1: command[6] = '1' command_send = ''.join(command) self.wifi_write(command_send) #Make sure to update gain in wifi self.gains[channel - 1] = gain self.local_wifi_server.set_gains(gains=self.gains) self.local_wifi_server.set_parser( ParseRaw(gains=self.gains, board_type=self.board_type)) except ValueError as e: print("Something went wrong while setting channel settings: " + str(e))
def test_get_data_array_accel(self): expected_sample_number = 0 data = sample_packet(expected_sample_number) parser = ParseRaw(gains=[24, 24, 24, 24, 24, 24, 24, 24], scaled_output=True) expected_accel_data = [] for i in range(k.RAW_PACKET_ACCEL_NUMBER_AXIS): expected_accel_data.append(k.CYTON_ACCEL_SCALE_FACTOR_GAIN * i) parser.raw_data_to_sample.raw_data_packet = data actual_accel_data = parser.get_data_array_accel( parser.raw_data_to_sample) self.assertListEqual(actual_accel_data, expected_accel_data)
def test_get_channel_data_array(self): expected_gains = [24, 24, 24, 24, 24, 24, 24, 24] expected_sample_number = 0 data = sample_packet(expected_sample_number) parser = ParseRaw(gains=expected_gains, scaled_output=True) scale_factors = parser.get_ads1299_scale_factors(expected_gains) expected_channel_data = [] for i in range(k.NUMBER_OF_CHANNELS_CYTON): expected_channel_data.append(scale_factors[i] * (i + 1)) parser.raw_data_to_sample.raw_data_packet = data actual_channel_data = parser.get_channel_data_array( parser.raw_data_to_sample) self.assertListEqual(actual_channel_data, expected_channel_data)
def test_interpret_24_bit_as_int_32(self): parser = ParseRaw() # 0x000690 === 1680 expected_value = 1680 actual_value = parser.interpret_24_bit_as_int_32( bytearray([0x00, 0x06, 0x90])) self.assertEqual(actual_value, expected_value, 'converts a small positive number') # 0x02C001 === 180225 expected_value = 180225 actual_value = parser.interpret_24_bit_as_int_32( bytearray([0x02, 0xC0, 0x01])) self.assertEqual(actual_value, expected_value, 'converts a large positive number') # 0xFFFFFF === -1 expected_value = -1 actual_value = parser.interpret_24_bit_as_int_32( bytearray([0xFF, 0xFF, 0xFF])) self.assertEqual(actual_value, expected_value, 'converts a small negative number') # 0x81A101 === -8281855 expected_value = -8281855 actual_value = parser.interpret_24_bit_as_int_32( bytearray([0x81, 0xA1, 0x01])) self.assertEqual(actual_value, expected_value, 'converts a large negative number')
def __init__(self, sock, callback=None, high_speed=True, parser=None, daisy=False): asyncore.dispatcher_with_send.__init__(self, sock) self.callback = callback self.daisy = daisy self.high_speed = high_speed self.last_odd_sample = OpenBCISample() self.parser = parser if parser is not None else ParseRaw( gains=[24, 24, 24, 24, 24, 24, 24, 24])
def test_parse_packet_standard_accel(self): data = sample_packet() expected_scale_factor = 4.5 / 24 / (pow(2, 23) - 1) parser = ParseRaw(gains=[24, 24, 24, 24, 24, 24, 24, 24], scaled_output=True) parser.raw_data_to_sample.raw_data_packet = data sample = parser.parse_packet_standard_accel(parser.raw_data_to_sample) self.assertIsNotNone(sample) for i in range(len(sample.channel_data)): self.assertEqual(sample.channel_data[i], expected_scale_factor * (i + 1)) for i in range(len(sample.accel_data)): self.assertEqual(sample.accel_data[i], k.CYTON_ACCEL_SCALE_FACTOR_GAIN * i) self.assertEqual(sample.packet_type, k.RAW_PACKET_TYPE_STANDARD_ACCEL) self.assertEqual(sample.sample_number, 0x45) self.assertEqual(sample.start_byte, 0xA0) self.assertEqual(sample.stop_byte, 0xC0) self.assertTrue(sample.valid)
def test_parse_raw_init(self): expected_board_type = k.BOARD_DAISY expected_gains = [24, 24, 24, 24, 24, 24, 24, 24] expected_log = True expected_micro_volts = True expected_scaled_output = False parser = ParseRaw(board_type=expected_board_type, gains=expected_gains, log=expected_log, micro_volts=expected_micro_volts, scaled_output=expected_scaled_output) self.assertEqual(parser.board_type, expected_board_type) self.assertEqual(parser.scaled_output, expected_scaled_output) self.assertEqual(parser.log, expected_log)
def test_transform_raw_data_packet_to_sample_time_sync_raw( self, mock_parse_packet_time_synced_raw_aux): data = sample_packet_raw_aux_time_sync_set(0) parser = ParseRaw() parser.transform_raw_data_packet_to_sample(data) mock_parse_packet_time_synced_raw_aux.assert_called_once() mock_parse_packet_time_synced_raw_aux.reset_mock() data = sample_packet_raw_aux_time_synced(0) parser.transform_raw_data_packet_to_sample(data) mock_parse_packet_time_synced_raw_aux.assert_called_once()
def test_interpret_16_bit_as_int_32(self): parser = ParseRaw() # 0x0690 === 1680 self.assertEqual( parser.interpret_16_bit_as_int_32(bytearray([0x06, 0x90])), 1680, 'converts a small positive number') # 0x02C0 === 704 self.assertEqual( parser.interpret_16_bit_as_int_32(bytearray([0x02, 0xC0])), 704, 'converts a large positive number') # 0xFFFF === -1 self.assertEqual( parser.interpret_16_bit_as_int_32(bytearray([0xFF, 0xFF])), -1, 'converts a small negative number') # 0x81A1 === -32351 self.assertEqual( parser.interpret_16_bit_as_int_32(bytearray([0x81, 0xA1])), -32351, 'converts a large negative number')
def connect(self): """ Connect to the board and configure it. Note: recreates various objects upon call. """ if self.ip_address is None: raise ValueError('self.ip_address cannot be None') if self.log: print("Init WiFi connection with IP: " + self.ip_address) """ Docs on these HTTP requests and more are found: https://app.swaggerhub.com/apis/pushtheworld/openbci-wifi-server/1.3.0 """ res_board = requests.get("http://%s/board" % self.ip_address) if res_board.status_code == 200: board_info = res_board.json() if not board_info['board_connected']: raise RuntimeError( "No board connected to WiFi Shield. To learn how to connect to a Cyton or Ganglion visit http://docs.openbci.com/Tutorials/03-Wifi_Getting_Started_Guide" ) self.board_type = board_info['board_type'] self.eeg_channels_per_sample = board_info['num_channels'] if self.log: print("Connected to %s with %s channels" % (self.board_type, self.eeg_channels_per_sample)) self.gains = None if self.board_type == k.BOARD_CYTON: self.gains = [24, 24, 24, 24, 24, 24, 24, 24] self.daisy = False elif self.board_type == k.BOARD_DAISY: self.gains = [ 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24 ] self.daisy = True elif self.board_type == k.BOARD_GANGLION: self.gains = [51, 51, 51, 51] self.daisy = False self.local_wifi_server.set_daisy(daisy=self.daisy) self.local_wifi_server.set_parser( ParseRaw(gains=self.gains, board_type=self.board_type)) if self.high_speed: output_style = 'raw' else: output_style = 'json' res_tcp_post = requests.post("http://%s/tcp" % self.ip_address, json={ 'ip': self.local_ip_address, 'port': self.local_wifi_server_port, 'output': output_style, 'delimiter': True, 'latency': self.latency }) if res_tcp_post.status_code == 200: tcp_status = res_tcp_post.json() if tcp_status['connected']: if self.log: print("WiFi Shield to Python TCP Socket Established") else: raise RuntimeWarning( "WiFi Shield is not able to connect to local server. Please open an issue." )
def test_make_daisy_sample_object_wifi(self): parser = ParseRaw(gains=[24, 24, 24, 24, 24, 24, 24, 24]) # Make the lower sample(channels 1 - 8) lower_sample_object = OpenBCISample(sample_number=1) lower_sample_object.channel_data = [1, 2, 3, 4, 5, 6, 7, 8] lower_sample_object.aux_data = [0, 1, 2] lower_sample_object.timestamp = 4 lower_sample_object.accel_data = [0, 0, 0] # Make the upper sample(channels 9 - 16) upper_sample_object = OpenBCISample(sample_number=2) upper_sample_object.channel_data = [9, 10, 11, 12, 13, 14, 15, 16] upper_sample_object.accel_data = [0, 1, 2] upper_sample_object.aux_data = [3, 4, 5] upper_sample_object.timestamp = 8 daisy_sample_object = parser.make_daisy_sample_object_wifi( lower_sample_object, upper_sample_object) # should have valid object true self.assertTrue(daisy_sample_object.valid) # should make a channelData array 16 elements long self.assertEqual(len(daisy_sample_object.channel_data), k.NUMBER_OF_CHANNELS_DAISY) # should make a channelData array with lower array in front of upper array for i in range(16): self.assertEqual(daisy_sample_object.channel_data[i], i + 1) self.assertEqual(daisy_sample_object.id, daisy_sample_object.sample_number) self.assertEqual(daisy_sample_object.sample_number, daisy_sample_object.sample_number) # should put the aux packets in an object self.assertIsNotNone(daisy_sample_object.aux_data['lower']) self.assertIsNotNone(daisy_sample_object.aux_data['upper']) # should put the aux packets in an object in the right order for i in range(3): self.assertEqual(daisy_sample_object.aux_data['lower'][i], i) self.assertEqual(daisy_sample_object.aux_data['upper'][i], i + 3) # should take the lower timestamp self.assertEqual(daisy_sample_object.timestamp, lower_sample_object.timestamp) # should take the lower stopByte self.assertEqual(daisy_sample_object.stop_byte, lower_sample_object.stop_byte) # should place the old timestamps in an object self.assertEqual(daisy_sample_object._timestamps['lower'], lower_sample_object.timestamp) self.assertEqual(daisy_sample_object._timestamps['upper'], upper_sample_object.timestamp) # should store an accelerometer value if present self.assertIsNotNone(daisy_sample_object.accel_data) self.assertListEqual(daisy_sample_object.accel_data, [0, 1, 2]) lower_sample = OpenBCISample(sample_number=1) lower_sample.accel_data = [0, 1, 2] upper_sample = OpenBCISample(sample_number=2) upper_sample.accel_data = [0, 0, 0] # Call the function under test daisy_sample = parser.make_daisy_sample_object_wifi( lower_sample, upper_sample) self.assertIsNotNone(daisy_sample.accel_data) self.assertListEqual(daisy_sample.accel_data, [0, 1, 2])