The MetaWear board can log sensor data and store it in the internal memory of the device using loggers to be retrieved at a later time.

Loggers record data from a data signal and are represented by the MblMwDataLogger struct.

Create an MblMwDataLogger object by calling mbl_mw_datasignal_log with the data signal you want to log.

If successful, the callback function will be executed with a MblMwDataLogger pointer and if creating the logger failed, a null pointer will be returned.

signal = libmetawear.mbl_mw_acc_get_acceleration_data_signal(d.board)
logger = create_voidp(lambda fn: libmetawear.mbl_mw_datasignal_log(signal, None, fn), resource = "acc_logger")
def logger_ready(self, context, pointer):
    self.logger = pointer

logger_created_fn= FnVoid_VoidP_VoidP(logger_ready)

libmetawear.mbl_mw_datasignal_log(signal, None, logger_created_fn)

MblMwDataLogger objects only interact with the specific data signal, they do not control the logging features. Logging control functions are detailed in the Logging section.


MblMwDataLogger objects are identified by a numerical id.

This id can be used to keep track of loggers when there is considerable time between the start of a log and the download of a log. It is also useful to get the state of the device (i.e is my device still downloading?).

You can retrieve the id by calling mbl_mw_logger_get_id.

The id is used to retrieve existing loggers from the API with the mbl_mw_logger_lookup_id function.

sensor_data_handler= FnVoid_VoidP_DataP(sensorDataHandler)

logger = libmetawear.mbl_mw_logger_lookup_id(board, 0)
libmetawear.mbl_mw_logger_subscribe(logger, None, sensor_data_handler)

Handling Data

Like a data signal, you can subscribe to an MblMwDataLogger to process the downloaded data.

Call mbl_mw_logger_subscribe to attach a callback function to the MblMwDataLogger which handles all received data.

There is a helper function from the SDK CPP called sensorDataHandler() which you can use (found in common.py).

def sensorDataHandler(self, context, data): // See full definition in common.py
    if (data.contents.type_id == DataTypeId.UINT32):
        data_ptr= cast(data.contents.value, POINTER(c_uint))
        self.data_uint32= c_uint()
        self.data_uint32.value= data_ptr.contents.value
        self.data = self.data_uint32
    elif (data.contents.type_id == DataTypeId.INT32 or data.contents.type_id == DataTypeId.SENSOR_ORIENTATION):
        data_ptr= cast(data.contents.value, POINTER(c_int))
        self.data_int32= c_int()
        self.data_int32.value= data_ptr.contents.value
        self.data = self.data_int32
    elif (data.contents.type_id == DataTypeId.FLOAT):
        data_ptr= cast(data.contents.value, POINTER(c_float))
        self.data_float= c_float()
        self.data_float.value= data_ptr.contents.value
        self.data = self.data_float
    elif (data.contents.type_id == DataTypeId.CARTESIAN_FLOAT):
        data_ptr= cast(data.contents.value, POINTER(CartesianFloat))
        self.data_cartesian_float= copy.deepcopy(data_ptr.contents)
        self.data = self.data_cartesian_float
    elif (data.contents.type_id == DataTypeId.QUATERNION):
        data_ptr= cast(data.contents.value, POINTER(Quaternion))
        self.data= copy.deepcopy(data_ptr.contents)
        raise RuntimeError('Unrecognized data type id: ' + str(data.contents.type_id))

There is also a helper function called parse_value which will handle the data types for you as part of the MetaWear class:

callback = FnVoid_VoidP_DataP(lambda ctx, p: print("{epoch: %d, value: %s}" % (p.contents.epoch, parse_value(p))))
libmetawear.mbl_mw_logger_subscribe(logger, None, callback)
def parse_value(pointer, **kwargs):
Helper function to extract the value from a Data object.  If you are storing the values to be used at a later time,
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
    pointer     - Required  : Pointer to a Data object
    n_elem      - Optional  : Nummber of elements in the value array if the type_id attribute is DataTypeId.DATA_ARRAY
if (pointer.contents.type_id in _value_parsers):
    return _value_parsers[pointer.contents.type_id](pointer)
elif (pointer.contents.type_id == DataTypeId.SENSOR_ORIENTATION):
    return _value_parsers[DataTypeId.INT32](pointer)
elif (pointer.contents.type_id == DataTypeId.BYTE_ARRAY):
    array_ptr= cast(pointer.contents.value, POINTER(c_ubyte * pointer.contents.length))
    return [array_ptr.contents[i] for i in range(0, pointer.contents.length)]
elif (pointer.contents.type_id == DataTypeId.DATA_ARRAY):
    if 'n_elem' in kwargs:
        values = cast(pointer.contents.value, POINTER(POINTER(Data) * kwargs['n_elem']))
        return [parse_value(values.contents[i]) for i in range(0, kwargs['n_elem'])]
        raise RuntimeError("Missing optional parameter 'n_elem' for parsing DataTypeId.DATA_ARRAY value")
    raise RuntimeError('Unrecognized data type id: ' + str(pointer.contents.type_id))


When you no longer want to log the values from a data signal, call mbl_mw_logger_remove to remove the logger.