Skip to content
This repository was archived by the owner on Jul 20, 2025. It is now read-only.

Commit 2c5a9b4

Browse files
committed
api v0.6.0 commit
1 parent 387c0eb commit 2c5a9b4

File tree

6 files changed

+154
-118
lines changed

6 files changed

+154
-118
lines changed

examples/data_fuser.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
from ctypes import c_void_p, cast, POINTER
2+
from mbientlab.metawear import MetaWear, libmetawear, parse_value, cbindings
3+
from time import sleep
4+
from threading import Event
5+
from sys import argv
6+
7+
states = []
8+
9+
class State:
10+
def __init__(self, device):
11+
self.device = device
12+
self.callback = cbindings.FnVoid_VoidP_DataP(self.data_handler)
13+
self.processor = None
14+
15+
def data_handler(self, ctx, data):
16+
values = parse_value(data, n_elem = 2)
17+
print("acc: (%.4f,%.4f,%.4f), gyro; (%.4f,%.4f,%.4f)" % (values[0].x, values[0].y, values[0].z, values[1].x, values[1].y, values[1].z))
18+
19+
def setup(self):
20+
libmetawear.mbl_mw_settings_set_connection_parameters(self.device.board, 7.5, 7.5, 0, 6000)
21+
sleep(1.5)
22+
23+
e = Event()
24+
25+
def processor_created(context, pointer):
26+
self.processor = pointer
27+
e.set()
28+
fn_wrapper = cbindings.FnVoid_VoidP_VoidP(processor_created)
29+
30+
acc = libmetawear.mbl_mw_acc_get_acceleration_data_signal(self.device.board)
31+
gyro = libmetawear.mbl_mw_gyro_bmi160_get_rotation_data_signal(self.device.board)
32+
33+
signals = (c_void_p * 1)()
34+
signals[0] = gyro
35+
libmetawear.mbl_mw_dataprocessor_fuser_create(acc, signals, 1, None, fn_wrapper)
36+
e.wait()
37+
38+
libmetawear.mbl_mw_datasignal_subscribe(self.processor, None, self.callback)
39+
40+
def start(self):
41+
libmetawear.mbl_mw_gyro_bmi160_enable_rotation_sampling(self.device.board)
42+
libmetawear.mbl_mw_acc_enable_acceleration_sampling(self.device.board)
43+
44+
libmetawear.mbl_mw_gyro_bmi160_start(self.device.board)
45+
libmetawear.mbl_mw_acc_start(self.device.board)
46+
47+
for i in range(len(argv) - 1):
48+
d = MetaWear(argv[i + 1])
49+
d.connect()
50+
print("Connected to " + d.address)
51+
states.append(State(d))
52+
53+
for s in states:
54+
print("configuring %s" % (s.device.address))
55+
s.setup()
56+
57+
for s in states:
58+
s.start()
59+
60+
sleep(10.0)
61+
62+
print("resetting devices")
63+
events = []
64+
for s in states:
65+
e = Event()
66+
events.append(e)
67+
68+
s.device.on_disconnect = lambda s: e.set()
69+
libmetawear.mbl_mw_debug_reset(s.device.board)
70+
71+
for e in events:
72+
e.wait()

mbientlab/metawear/__init__.py

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,29 @@
3030
DataTypeId.LOGGING_TIME: lambda p: cast(p.contents.value, POINTER(LoggingTime)).contents,
3131
DataTypeId.BTLE_ADDRESS: lambda p: cast(p.contents.value, POINTER(BtleAddress)).contents,
3232
DataTypeId.BOSCH_ANY_MOTION: lambda p: cast(p.contents.value, POINTER(BoschAnyMotion)).contents,
33-
DataTypeId.CALIBRATION_STATE: lambda p: cast(p.contents.value, POINTER(CalibrationState)).contents
33+
DataTypeId.CALIBRATION_STATE: lambda p: cast(p.contents.value, POINTER(CalibrationState)).contents,
34+
DataTypeId.BOSCH_TAP: lambda p: cast(p.contents.value, POINTER(BoschTap)).contents
3435
}
35-
def parse_value(p_data):
36+
def parse_value(pointer, **kwargs):
3637
"""
3738
Helper function to extract the value from a Data object. If you are storing the values to be used at a later time,
3839
call copy.deepcopy preserve the value. You do not need to do this if the underlying type is a native type or a byte array
3940
@params:
40-
p_data - Required : Pointer to a Data object
41+
pointer - Required : Pointer to a Data object
42+
n_elem - Optional : Nummber of elements in the value array if the type_id attribute is DataTypeId.DATA_ARRAY
4143
"""
42-
if (p_data.contents.type_id in _value_parsers):
43-
return _value_parsers[p_data.contents.type_id](p_data)
44-
elif (p_data.contents.type_id == DataTypeId.SENSOR_ORIENTATION):
45-
return _value_parsers[DataTypeId.INT32](p_data)
46-
elif (p_data.contents.type_id == DataTypeId.BYTE_ARRAY):
47-
array_ptr= cast(p_data.contents.value, POINTER(c_ubyte * p_data.contents.length))
48-
return [array_ptr.contents[i] for i in range(0, p_data.contents.length)]
44+
if (pointer.contents.type_id in _value_parsers):
45+
return _value_parsers[pointer.contents.type_id](pointer)
46+
elif (pointer.contents.type_id == DataTypeId.SENSOR_ORIENTATION):
47+
return _value_parsers[DataTypeId.INT32](pointer)
48+
elif (pointer.contents.type_id == DataTypeId.BYTE_ARRAY):
49+
array_ptr= cast(pointer.contents.value, POINTER(c_ubyte * pointer.contents.length))
50+
return [array_ptr.contents[i] for i in range(0, pointer.contents.length)]
51+
elif (pointer.contents.type_id == DataTypeId.DATA_ARRAY):
52+
if 'n_elem' in kwargs:
53+
values = cast(pointer.contents.value, POINTER(POINTER(Data) * kwargs['n_elem']))
54+
return [parse_value(values.contents[i]) for i in range(0, kwargs['n_elem'])]
55+
else:
56+
raise RuntimeError("Missing optional parameter 'n_elem' for parsing DataTypeId.DATA_ARRAY value")
4957
else:
50-
raise RuntimeError('Unrecognized data type id: ' + str(p_data.contents.type_id))
58+
raise RuntimeError('Unrecognized data type id: ' + str(pointer.contents.type_id))

mbientlab/metawear/metawear.py

Lines changed: 60 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -93,14 +93,6 @@ def __init__(self, address, **kwargs):
9393

9494
if 'deserialize' not in kwargs or kwargs['deserialize']:
9595
self.deserialize()
96-
dev_info = libmetawear.mbl_mw_metawearboard_get_device_information(self.board)
97-
self.info = {
98-
'hardware': dev_info.contents.hardware_revision.decode('utf8'),
99-
'manufacturer': dev_info.contents.manufacturer.decode('utf8'),
100-
'serial': dev_info.contents.serial_number.decode('utf8'),
101-
'firmware': dev_info.contents.firmware_revision.decode('utf8'),
102-
'model': dev_info.contents.model_number.decode('utf8')
103-
}
10496

10597
try:
10698
os.makedirs(self.cache)
@@ -125,65 +117,82 @@ def disconnect(self):
125117
"""
126118
self.warble.disconnect()
127119

128-
def connect(self, **kwargs):
120+
def connect_async(self, handler, **kwargs):
129121
"""
130122
Connects to the MetaWear board and initializes the SDK. You must first connect to the board before using
131123
any of the SDK functions
132124
@params:
125+
handler - Required : `(BaseException) -> void` function to handle the result of the task
133126
serialize - Optional : Serialize and cached C++ SDK state after initializaion, defaults to true
134127
"""
135-
e = Event()
136-
result = None
128+
137129
def completed(err):
138130
if (err != None):
139-
result = err
140-
e.set()
131+
handler(err)
132+
else:
133+
if not self.in_metaboot_mode:
134+
def init_handler(context, device, status):
135+
if status != Const.STATUS_OK:
136+
self.disconnect()
137+
handler(RuntimeError("Error initializing the API (%d)" % (status)))
138+
else:
139+
if 'serialize' not in kwargs or kwargs['serialize']:
140+
self.serialize()
141+
handler(None)
142+
143+
self._init_handler = FnVoid_VoidP_VoidP_Int(init_handler)
144+
libmetawear.mbl_mw_metawearboard_initialize(self.board, None, self._init_handler)
145+
else:
146+
def read_task():
147+
uuids = self._read_dev_info_state['uuids']
148+
if(len(uuids)):
149+
next = uuids.popleft()
150+
self._read_dev_info_state['next'] = next
151+
if (MetaWear._DEV_INFO[next] not in self.info):
152+
gatt_char = self.warble.find_characteristic(next)
153+
if (gatt_char == None):
154+
handler(RuntimeError("Missing gatt char '%s'" % (next)))
155+
else:
156+
gatt_char.read_value_async(self._read_dev_info_state['completed'])
157+
else:
158+
read_task()
159+
else:
160+
handler(None)
141161

142-
self.warble.connect_async(completed)
143-
e.wait()
162+
def completed(value, error):
163+
if (error == None):
164+
self.info[MetaWear._DEV_INFO[self._read_dev_info_state['next']]] = bytearray(value).decode('utf8')
165+
read_task()
166+
else:
167+
handler(error)
144168

145-
if (result != None):
146-
raise result
169+
self._read_dev_info_state = {
170+
'uuids': deque(MetaWear._DEV_INFO.keys()),
171+
'completed': completed,
172+
'read_task': read_task
173+
}
147174

148-
if not self.in_metaboot_mode:
149-
init_event = Event()
150-
def init_handler(context, device, status):
151-
self._init_status = status
152-
init_event.set()
175+
read_task()
153176

154-
init_handler_fn = FnVoid_VoidP_VoidP_Int(init_handler)
155-
libmetawear.mbl_mw_metawearboard_initialize(self.board, None, init_handler_fn)
156-
init_event.wait()
177+
if 'firmware' in self.info: del self.info['firmware']
178+
self.warble.connect_async(completed)
157179

158-
if self._init_status != Const.STATUS_OK:
159-
self.disconnect()
160-
raise RuntimeError("Error initializing the API (%d)" % (self._init_status))
180+
def connect(self, **kwargs):
181+
"""
182+
Synchronous variant of `connect_async`
183+
"""
184+
e = Event()
185+
result = []
161186

162-
if 'serialize' not in kwargs or kwargs['serialize']:
163-
self.serialize()
164-
else:
165-
uuids = deque(MetaWear._DEV_INFO.keys())
166-
while(len(uuids)):
167-
next = uuids.popleft()
168-
if (MetaWear._DEV_INFO[next] not in self.info):
169-
gatt_char = self.warble.find_characteristic(next)
170-
if (gatt_char == None):
171-
raise RuntimeError("Missing gatt char '%s'" % (next))
172-
173-
e.clear()
174-
results = []
175-
def completed(value, error):
176-
results.append(value)
177-
results.append(error)
178-
e.set()
187+
def completed(error):
188+
result.append(error)
189+
e.set()
179190

180-
gatt_char.read_value_async(completed)
181-
e.wait()
191+
self.connect_async(completed)
192+
e.wait()
182193

183-
if results[1] == None:
184-
self.info[MetaWear._DEV_INFO[next]] = bytearray(results[0]).decode('utf8')
185-
else:
186-
raise results[1]
194+
if (result[0] != None):
195+
raise result[0]
187196

188197
def _read_gatt_char(self, context, caller, ptr_gattchar, handler):
189198
uuid = _gattchar_to_string(ptr_gattchar.contents)

setup.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ def run(self):
6666
setup(
6767
name='metawear',
6868
packages=['mbientlab', 'mbientlab.metawear'],
69-
version='0.5.0',
69+
version='0.6.0',
7070
description='Python bindings for the MetaWear C++ SDK by MbientLab',
7171
long_description=open(os.path.join(os.path.dirname(__file__), "README.rst")).read(),
7272
package_data={'mbientlab.metawear': so_pkg_data},
@@ -92,4 +92,4 @@ def run(self):
9292
'Programming Language :: Python :: 2.7',
9393
'Programming Language :: Python :: 3',
9494
]
95-
)
95+
)

test.py

Lines changed: 0 additions & 53 deletions
This file was deleted.

0 commit comments

Comments
 (0)