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

Commit 1dcf84b

Browse files
committed
Commit for v0.3.0
1 parent 4eb6407 commit 1dcf84b

File tree

4 files changed

+73
-25
lines changed

4 files changed

+73
-25
lines changed

examples/scan_connect.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
device.connect()
2828

2929
print("Connected")
30+
print("Device information: " + str(device.info))
3031
sleep(5.0)
3132

3233
device.disconnect()

mbientlab/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import pkgutil
2+
__path__ = pkgutil.extend_path(__path__, __name__)

mbientlab/metawear/__init__.py

Lines changed: 69 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,18 @@
44
from threading import Event
55
from .cbindings import *
66

7+
import copy
78
import errno
89
import json
910
import os
10-
import platform
1111
import requests
12+
import sys
1213
import time
1314
import uuid
1415

16+
if sys.version_info[0] == 2:
17+
range = xrange
18+
1519
so_path = os.path.join(os.path.dirname(__file__), 'libmetawear.so')
1620
libmetawear= CDLL(so_path)
1721
init_libmetawear(libmetawear)
@@ -67,6 +71,8 @@ def parse_value(p_data):
6771
return cast(p_data.contents.value, POINTER(Quaternion)).contents
6872
elif (p_data.contents.type_id == DataTypeId.CORRECTED_CARTESIAN_FLOAT):
6973
return cast(p_data.contents.value, POINTER(CorrectedCartesianFloat)).contents
74+
elif (p_data.contents.type_id == DataTypeId.OVERFLOW_STATE):
75+
return cast(p_data.contents.value, POINTER(OverflowState)).contents
7076
else:
7177
raise RuntimeError('Unrecognized data type id: ' + str(p_data.contents.type_id))
7278

@@ -87,6 +93,10 @@ def on_notification(self, handle, data):
8793
class MetaWear(object):
8894
_METABOOT_SERVICE = uuid.UUID("00001530-1212-efde-1523-785feabcd123")
8995

96+
@staticmethod
97+
def _convert(value):
98+
return value if sys.version_info[0] == 2 else value.encode('utf8')
99+
90100
def __init__(self, address, **kwargs):
91101
"""
92102
Creates a MetaWear object
@@ -96,8 +106,7 @@ def __init__(self, address, **kwargs):
96106
device - Optional : hci device to use, defaults to 'hci0'
97107
deserialize - Optional : Deserialize the cached C++ SDK state if available, defaults to true
98108
"""
99-
self.hw = None
100-
self.model = None
109+
self.info = {}
101110

102111
self.address = address
103112
self.cache = kwargs['cache_path'] if ('cache_path' in kwargs) else ".metawear"
@@ -153,10 +162,22 @@ def connect(self, **kwargs):
153162
for c in self.gatt.discover_characteristics():
154163
self.characteristics[c['uuid']] = c['value_handle']
155164

165+
if ('hardware' not in self.info):
166+
self.info['hardware'] = self.gatt.read_by_uuid("00002a27-0000-1000-8000-00805f9b34fb")[0]
167+
168+
if ('manufacturer' not in self.info):
169+
self.info['manufacturer'] = self.gatt.read_by_uuid("00002a29-0000-1000-8000-00805f9b34fb")[0]
170+
171+
if ('serial' not in self.info):
172+
self.info['serial'] = self.gatt.read_by_uuid("00002a25-0000-1000-8000-00805f9b34fb")[0]
173+
174+
if ('model' not in self.info):
175+
self.info['model'] = self.gatt.read_by_uuid("00002a24-0000-1000-8000-00805f9b34fb")[0]
176+
156177
if not self.in_metaboot_mode:
157178
init_event = Event()
158179
def init_handler(device, status):
159-
self.init_status = status;
180+
self.init_status = status
160181
init_event.set()
161182

162183
init_handler_fn = FnVoid_VoidP_Int(init_handler)
@@ -169,10 +190,19 @@ def init_handler(device, status):
169190

170191
if 'serialize' not in kwargs or kwargs['serialize']:
171192
self.serialize()
193+
else:
194+
self.info['firmware'] = self.gatt.read_by_uuid("00002a26-0000-1000-8000-00805f9b34fb")[0]
172195

173196
def _read_gatt_char(self, caller, ptr_gattchar, handler):
174-
value = self.gatt.read_by_uuid(_gattchar_to_string(ptr_gattchar.contents))[0]
175-
value = value if platform.python_version_tuple()[0] == '2' else value.encode('utf8')
197+
uuid = _gattchar_to_string(ptr_gattchar.contents)
198+
raw = self.gatt.read_by_uuid(uuid)[0]
199+
200+
if (('model' not in self.info) and uuid == "00002a24-0000-1000-8000-00805f9b34fb"):
201+
self.info['model'] = raw
202+
elif (uuid == "00002a26-0000-1000-8000-00805f9b34fb"):
203+
self.info['firmware'] = raw
204+
205+
value = MetaWear._convert(raw)
176206
buffer = create_string_buffer(value, len(value))
177207
handler(caller, cast(buffer, POINTER(c_ubyte)), len(buffer.raw))
178208

@@ -206,55 +236,70 @@ def _download_firmware(self, version=None):
206236
with open(info1, "rb") as f:
207237
info1_content = json.load(f)
208238

209-
if (self.hw == None):
210-
self.hw = self.gatt.read_by_uuid("00002a27-0000-1000-8000-00805f9b34fb")[0]
211-
212-
if (self.model == None):
213-
self.model = self.gatt.read_by_uuid("00002a24-0000-1000-8000-00805f9b34fb")[0]
214-
215239
if version is None:
216240
versions = []
217-
for k in info1_content[self.hw][self.model]["vanilla"].keys():
241+
for k in info1_content[self.info['hardware']][self.info['model']]["vanilla"].keys():
218242
versions.append(LooseVersion(k))
219243
versions.sort()
220244
target = str(versions[-1])
221245
else:
222-
if version not in info1_content[self.hw][self.model]["vanilla"]:
246+
if version not in info1_content[self.info['hardware']][self.info['model']]["vanilla"]:
223247
raise ValueError("Firmware '%s' not available for this board" % (version))
224248
target = version
225249

226-
filename = info1_content[self.hw][self.model]["vanilla"][target]["filename"]
227-
local_path = os.path.join(firmware_root, self.hw, self.model, "vanilla", target, filename)
250+
filename = info1_content[self.info['hardware']][self.info['model']]["vanilla"][target]["filename"]
251+
local_path = os.path.join(firmware_root, self.info['hardware'], self.info['model'], "vanilla", target, filename)
228252

229253
if not os.path.isfile(local_path):
230-
url = "https://releases.mbientlab.com/metawear/{}/{}/{}/{}/{}".format(self.hw, self.model, "vanilla", target, filename)
254+
url = "https://releases.mbientlab.com/metawear/{}/{}/{}/{}/{}".format(
255+
self.info['hardware'], self.info['model'], "vanilla", target, filename
256+
)
231257
_download_file(url, local_path)
232258
return local_path
233259

234260
def serialize(self):
235261
"""
236262
Serialize and cache the SDK state
237263
"""
238-
path = os.path.join(self.cache, '%s.bin' % (self.address.replace(':','')))
264+
mac_str = self.address.replace(':','')
265+
path = os.path.join(self.cache, '%s.json' % (mac_str))
239266

240-
size = c_uint(0)
241-
state = cast(libmetawear.mbl_mw_metawearboard_serialize(self.board, byref(size)), POINTER(c_ubyte * size.value))
242-
with open(path, "wb") as f:
243-
f.write(state.contents)
267+
state = { "info": copy.deepcopy(self.info) }
244268

245-
libmetawear.mbl_mw_memory_free(state)
269+
size = c_uint(0)
270+
cpp_state = cast(libmetawear.mbl_mw_metawearboard_serialize(self.board, byref(size)), POINTER(c_ubyte * size.value))
271+
state["cpp_state"] = [cpp_state.contents[i] for i in range(0, size.value)]
272+
libmetawear.mbl_mw_memory_free(cpp_state)
246273

274+
with open(path, "w") as f:
275+
f.write(json.dumps(state, indent=2))
276+
247277
def deserialize(self):
248278
"""
249279
Deserialize the cached SDK state
250280
"""
251-
path = os.path.join(self.cache, '%s.bin' % (self.address.replace(':','')))
281+
mac_str = self.address.replace(':','')
282+
283+
# See if old serialized state exists, if it does, read that then remove it
284+
path = os.path.join(self.cache, '%s.bin' % (mac_str))
252285
if os.path.isfile(path):
253286
with(open(path, "rb")) as f:
254287
content = f.read()
255288
raw = (c_ubyte * len(content)).from_buffer_copy(content)
256289
libmetawear.mbl_mw_metawearboard_deserialize(self.board, raw, len(content))
290+
291+
os.remove(path)
292+
return True
293+
294+
path = os.path.join(self.cache, '%s.json' % (mac_str))
295+
if os.path.isfile(path):
296+
with(open(path, "r")) as f:
297+
content = json.loads(f.read())
298+
self.info = content["info"]
299+
raw = (c_ubyte * len(content)).from_buffer_copy(bytearray(content["cpp_state"]))
300+
libmetawear.mbl_mw_metawearboard_deserialize(self.board, raw, len(content))
257301
return True
302+
258303
return False
259304

260305
def update_firmware_async(self, handler, **kwargs):

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def run(self):
3232
setup(
3333
name='metawear',
3434
packages=['mbientlab', 'mbientlab.metawear'],
35-
version='0.2.0',
35+
version='0.3.0',
3636
description='Python bindings for the MetaWear C++ SDK by MbientLab',
3737
long_description=open(os.path.join(os.path.dirname(__file__), "README.rst")).read(),
3838
package_data={'mbientlab.metawear': ['libmetawear.so*']},

0 commit comments

Comments
 (0)