Skip to content

ADD: Aux data to fix wifi #116

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
# v1.1.0

### New Features

* Now supporting digital and analog reading on cyton wifi

# v1.0.2

### Bug Fixes
Expand Down
5 changes: 5 additions & 0 deletions openbci/utils/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,8 @@ class Constants:
SAMPLE_RATE_6400 = 6400
SAMPLE_RATE_800 = 800
SAMPLE_RATE_8000 = 8000

"""Different Aux Modes"""
AUX_MODE_ANALOG = 'analog'
AUX_MODE_DEFAULT = 'default'
AUX_MODE_DIGITAL = 'digital'
60 changes: 59 additions & 1 deletion openbci/utils/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,63 @@ def parse_packet_standard_accel(self, raw_data_to_sample):
return sample_object

def parse_packet_standard_raw_aux(self, raw_data_to_sample):
pass
"""

:param raw_data_to_sample: RawDataToSample
:return:
"""
# Check to make sure data is not null.
if raw_data_to_sample is None:
raise RuntimeError(k.ERROR_UNDEFINED_OR_NULL_INPUT)
if raw_data_to_sample.raw_data_packet is None:
raise RuntimeError(k.ERROR_UNDEFINED_OR_NULL_INPUT)

# Check to make sure the buffer is the right size.
if len(raw_data_to_sample.raw_data_packet) != k.RAW_PACKET_SIZE:
raise RuntimeError(k.ERROR_INVALID_BYTE_LENGTH)

# Verify the correct stop byte.
if raw_data_to_sample.raw_data_packet[0] != k.RAW_BYTE_START:
raise RuntimeError(k.ERROR_INVALID_BYTE_START)

sample_object = OpenBCISample()

sample_object.aux_data = raw_data_to_sample.raw_data_packet[k.RAW_PACKET_POSITION_START_AUX:k.RAW_PACKET_POSITION_STOP_AUX+1]

if(len(sample_object.aux_data) != 0):
# extract value sample_object.aux_data
sample_object.analog_data = {
'A5': sample_object.aux_data[0] << 8 | sample_object.aux_data[1],
'A6': sample_object.aux_data[2] << 8 | sample_object.aux_data[3]
}
sample_object.digital_data = {
'D11': ((sample_object.aux_data[0] & 0xFF00) >> 8),
'D12': sample_object.aux_data[0] & 0xFF,
'D17': sample_object.aux_data[1] & 0xFF
}

sample_object.packet_type = k.RAW_PACKET_TYPE_STANDARD_RAW_AUX

sample_object.channel_data = self.get_channel_data_array(raw_data_to_sample)

sample_object.sample_number = raw_data_to_sample.raw_data_packet[
k.RAW_PACKET_POSITION_SAMPLE_NUMBER
]
sample_object.start_byte = raw_data_to_sample.raw_data_packet[
k.RAW_PACKET_POSITION_START_BYTE
]
sample_object.stop_byte = raw_data_to_sample.raw_data_packet[
k.RAW_PACKET_POSITION_STOP_BYTE
]

sample_object.valid = True

now_ms = int(round(time.time() * 1000))

sample_object.timestamp = now_ms
sample_object.boardTime = 0

return sample_object

def parse_packet_time_synced_accel(self, raw_data_to_sample):
pass
Expand Down Expand Up @@ -370,3 +426,5 @@ def __init__(self,
self._timestamps = {}
self.valid = valid
self.accel_data = accel_data if accel_data is not None else []
self.analog_data = {}
self.digital_data = {}
26 changes: 25 additions & 1 deletion openbci/wifi.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class OpenBCIWiFi(object):

def __init__(self, ip_address=None, shield_name=None, sample_rate=None, log=True, timeout=3,
max_packets_to_skip=20, latency=10000, high_speed=True, ssdp_attempts=5,
num_channels=8, local_ip_address=None):
num_channels=8, local_ip_address=None, aux_mode=Constants.AUX_MODE_DEFAULT):
# these one are used
self.daisy = False
self.gains = None
Expand All @@ -81,6 +81,7 @@ def __init__(self, ip_address=None, shield_name=None, sample_rate=None, log=True
self.ssdp_attempts = ssdp_attempts
self.streaming = False
self.timeout = timeout
self.aux_mode = aux_mode

# might be handy to know API
self.board_type = "none"
Expand Down Expand Up @@ -208,6 +209,10 @@ def connect(self):
raise RuntimeWarning("WiFi Shield is not able to connect to local server."
"Please open an issue.")

if self.board_type != Constants.BOARD_GANGLION:
self.aux_mode_set(self.aux_mode)


def init_streaming(self):
""" Tell the board to record like crazy. """
res_stream_start = requests.get(
Expand Down Expand Up @@ -288,6 +293,25 @@ def wifi_write(self, output):
raise RuntimeError("Error code: %d %s" % (
res_command_post.status_code, res_command_post.text))

def aux_mode_set(self, aux_mode):
"""
Used to configure the cyton to enter digital or analog read mode.
NOTE: Does not work on Ganglion
:param aux_mode: str
Can be either 'default', 'digital', or 'analog'
:return: None
"""
if self.board_type == Constants.BOARD_GANGLION:
raise RuntimeError("Aux mode not implemented on ganglion")
elif aux_mode == Constants.AUX_MODE_DEFAULT:
self.wifi_write('/0')
elif aux_mode == Constants.AUX_MODE_ANALOG:
self.wifi_write('/2')
elif aux_mode == Constants.AUX_MODE_DIGITAL:
self.wifi_write('/3')
else:
raise RuntimeError("Invalid aux mode choice")

def getSampleRate(self):
return self.sample_rate

Expand Down
22 changes: 22 additions & 0 deletions tests/test_parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,28 @@ def test_parse_packet_standard_accel(self):
self.assertEqual(sample.stop_byte, 0xC0)
self.assertTrue(sample.valid)

def test_parse_packet_standard_raw_aux(self):
sample_number = 0x45
data = sample_packet_standard_raw_aux(sample_number)

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_raw_aux(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))
self.assertEqual(sample.aux_data, bytearray([0, 1, 2, 3, 4, 5]), "Ensure 6 bytes were extracted")
self.assertEqual(sample.packet_type, Constants.RAW_PACKET_TYPE_STANDARD_RAW_AUX)
self.assertEqual(sample.sample_number, 0x45)
self.assertEqual(sample.start_byte, 0xA0)
self.assertEqual(sample.stop_byte, 0xC1)
self.assertTrue(sample.valid)

@mock.patch.object(ParseRaw, 'parse_packet_standard_accel')
def test_transform_raw_data_packet_to_sample_accel(self, mock_parse_packet_standard_accel):
data = sample_packet(0)
Expand Down
5 changes: 4 additions & 1 deletion tests/test_wifi.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ def test_wifi_init(self, mock_on_shield_found):
expected_latency = 5000
expected_high_speed = False
expected_ssdp_attempts = 2
expected_aux_mode = 'analog'

wifi = OpenBCIWiFi(ip_address=expected_ip_address,
shield_name=expected_shield_name,
Expand All @@ -26,7 +27,8 @@ def test_wifi_init(self, mock_on_shield_found):
max_packets_to_skip=expected_max_packets_to_skip,
latency=expected_latency,
high_speed=expected_high_speed,
ssdp_attempts=expected_ssdp_attempts)
ssdp_attempts=expected_ssdp_attempts,
aux_mode=expected_aux_mode)

self.assertEqual(wifi.ip_address, expected_ip_address)
self.assertEqual(wifi.shield_name, expected_shield_name)
Expand All @@ -37,6 +39,7 @@ def test_wifi_init(self, mock_on_shield_found):
self.assertEqual(wifi.latency, expected_latency)
self.assertEqual(wifi.high_speed, expected_high_speed)
self.assertEqual(wifi.ssdp_attempts, expected_ssdp_attempts)
self.assertEqual(wifi.aux_mode, expected_aux_mode)

mock_on_shield_found.assert_called_with(expected_ip_address)

Expand Down