Faster Download

edited May 2022 in Python

from mbientlab.metawear import MetaWear, libmetawear, parse_value, create_voidp, create_voidp_int
from mbientlab.metawear.cbindings import *
from ctypes import c_void_p, cast, POINTER
from time import sleep
from threading import Event
import six
import platform
import sys
from sys import argv
import csv
from datetime import datetime;
import time 
if sys.version_info[0] == 2:
    range = xrange
def retry_connection(d):
       print("----------------------------------Trying CONNECTION---------------------------------------------------")
       sleep(3.0)
       try:
          d.connect()
       except:
          return retry_connection(d)
class State:

    def __init__(self, device):
        self.device = device
        self.samples = 0
        self.e = None
        self.signal = None
        self.logger = None
        self.analog_signal=None
        self.analog_logger=None
        self.signal_acc = None
        self.logger_acc = None
        self.signal_gyro = None
        self.logger_gyr = None
        self.processor = None
    def setup(self):
        try:

            self.e = Event()
            print("Clear entries")
            libmetawear.mbl_mw_logging_clear_entries(self.device.board)
            print("Configuring device")

            self.signal = libmetawear.mbl_mw_multi_chnl_temp_get_temperature_data_signal(self.device.board, MetaWearRProChannel.ON_BOARD_THERMISTOR)
            self.logger = create_voidp(lambda fn: libmetawear.mbl_mw_datasignal_log(self.signal, None, fn), resource = "logger", event = self.e)

            self.analog_signal = libmetawear.mbl_mw_gpio_get_analog_input_data_signal(self.device.board, 1, GpioAnalogReadMode.ABS_REF)
            self.analog_logger = create_voidp(lambda fn: libmetawear.mbl_mw_datasignal_log(self.analog_signal, None, fn), resource = "analog_logger", event = self.e)


            print("Configuring acc odr")
            libmetawear.mbl_mw_acc_set_odr(self.device.board, 100)
            libmetawear.mbl_mw_acc_set_range(self.device.board, 2.0)
            libmetawear.mbl_mw_acc_write_acceleration_config(self.device.board)
            print("Configuring acc odr")
            libmetawear.mbl_mw_gyro_bmi270_set_range(self.device.board, GyroBoschRange._125dps);
            libmetawear.mbl_mw_gyro_bmi270_set_odr(self.device.board, GyroBoschOdr._100Hz);
            libmetawear.mbl_mw_gyro_bmi270_write_config(self.device.board);
            print("Configuring gyr odr")

            self.signal_acc = libmetawear.mbl_mw_acc_get_acceleration_data_signal(self.device.board)
            self.logger_acc = create_voidp(lambda fn: libmetawear.mbl_mw_datasignal_log(self.signal_acc, None, fn), resource = "acc_logger")
            self.signal_gyro = libmetawear.mbl_mw_gyro_bmi270_get_rotation_data_signal(self.device.board)
            self.logger_gyr = create_voidp(lambda fn: libmetawear.mbl_mw_datasignal_log(self.signal_gyro, None, fn), resource = "gyr_logger")
            self.timer = create_voidp(lambda fn: libmetawear.mbl_mw_timer_create_indefinite(self.device.board, 20, 0, None, fn), resource = "timer", event = self.e) #20 intende i ms tra un            campione e l'altro, 20=50Hz, 30 è 30Hz
            libmetawear.mbl_mw_event_record_commands(self.timer)
            libmetawear.mbl_mw_datasignal_read(self.analog_signal)
            libmetawear.mbl_mw_datasignal_read(self.signal)
            create_voidp_int(lambda fn: libmetawear.mbl_mw_event_end_record(self.timer, None, fn), event = self.e)
            libmetawear.mbl_mw_logging_start(self.device.board, 0)
        except RuntimeError as err:
            print(err)

    def start(self):
        try:
            print("Start " + self.device.address)
            libmetawear.mbl_mw_acc_enable_acceleration_sampling(self.device.board)
            libmetawear.mbl_mw_acc_start(self.device.board)
            libmetawear.mbl_mw_gyro_bmi270_enable_rotation_sampling(self.device.board)
            libmetawear.mbl_mw_gyro_bmi270_start(self.device.board)
            libmetawear.mbl_mw_timer_start(self.timer)
        except RuntimeError as err:
            print(err)

    def stop(self):
        try:
            libmetawear.mbl_mw_timer_remove(self.timer)
            print("Stop " + self.device.address)
            libmetawear.mbl_mw_acc_disable_acceleration_sampling(self.device.board)
            libmetawear.mbl_mw_gyro_bmi270_disable_rotation_sampling(self.device.board)
            libmetawear.mbl_mw_logging_stop(self.device.board)
            libmetawear.mbl_mw_gyro_bmi270_stop(self.device.board)

            libmetawear.mbl_mw_event_remove_all(self.device.board)
            libmetawear.mbl_mw_logging_flush_page(self.device.board)
        except RuntimeError as err:
            print(err)
    def download(self):
        def progress_update_handler(context, entries_left, total_entries):
            if (entries_left == 0):
                self.e.set()
</pre>

<p>

Comments

  • edited May 2022
    
          def temp(p):
                with open('./Data/temp_'+self.device.address+'.csv', 'a+', newline='') as file:
                    writer = csv.writer(file, delimiter=';')
                    writer.writerow([datetime.timestamp(datetime.now()), parse_value(p)])
    
            fn_wrapper = FnVoid_VoidP_UInt_UInt(progress_update_handler)
            download_handler = LogDownloadHandler(context = None, \
                received_progress_update = fn_wrapper, \
                received_unknown_entry = cast(None, FnVoid_VoidP_UByte_Long_UByteP_UByte), \
                received_unhandled_entry = cast(None, FnVoid_VoidP_DataP))
            callback = FnVoid_VoidP_DataP(lambda ctx, p:temp(p))
            libmetawear.mbl_mw_logger_subscribe(self.logger, None, callback)
            libmetawear.mbl_mw_logging_download(self.device.board, 0, byref(download_handler))
    
            def analog(p):
                with open('./Data/analog_'+self.device.address+'.csv', 'a+', newline='') as file:
                    writer = csv.writer(file, delimiter=';')
                    writer.writerow([datetime.timestamp(datetime.now()), parse_value(p)*1.85])
            fn_wrapper = FnVoid_VoidP_UInt_UInt(progress_update_handler)
            download_handler = LogDownloadHandler(context = None, \
                received_progress_update = fn_wrapper, \
                received_unknown_entry = cast(None, FnVoid_VoidP_UByte_Long_UByteP_UByte), \
                received_unhandled_entry = cast(None, FnVoid_VoidP_DataP))
            analog_callback = FnVoid_VoidP_DataP(lambda ctx, p:analog(p))
            libmetawear.mbl_mw_logger_subscribe(self.analog_logger, None, analog_callback)
            libmetawear.mbl_mw_logging_download(self.device.board, 0, byref(download_handler))
                  
            def acc(p):
                with open('./Data/dataacc_'+self.device.address+'.csv', 'a+', newline='') as file:
                  writer = csv.writer(file, delimiter=';')
                  writer.writerow([datetime.timestamp(datetime.now()), parse_value(p).x,parse_value(p).y,parse_value(p).z])
    
            fn_wrapper = FnVoid_VoidP_UInt_UInt(progress_update_handler)
            download_handler = LogDownloadHandler(context = None, \
                received_progress_update = fn_wrapper, \
                received_unknown_entry = cast(None, FnVoid_VoidP_UByte_Long_UByteP_UByte), \
                received_unhandled_entry = cast(None, FnVoid_VoidP_DataP))
            acc_callback = FnVoid_VoidP_DataP(lambda ctx, p: acc(p))
            libmetawear.mbl_mw_logger_subscribe(self.logger_acc, None, acc_callback)
            libmetawear.mbl_mw_logging_download(self.device.board, 0, byref(download_handler))
            
            def gyr(p):
                with open('./Data/datagyr_'+self.device.address+'.csv', 'a+', newline='') as file:
                  writer = csv.writer(file, delimiter=';')
                  writer.writerow([datetime.timestamp(datetime.now()), parse_value(p).x,parse_value(p).y,parse_value(p).z])
    
            fn_wrapper = FnVoid_VoidP_UInt_UInt(progress_update_handler)
            download_handler = LogDownloadHandler(context = None, \
                received_progress_update = fn_wrapper, \
                received_unknown_entry = cast(None, FnVoid_VoidP_UByte_Long_UByteP_UByte), \
                received_unhandled_entry = cast(None, FnVoid_VoidP_DataP))
            gyrcallback = FnVoid_VoidP_DataP(lambda ctx, p: gyr(p))
            libmetawear.mbl_mw_logger_subscribe(self.logger_gyr, None, gyrcallback)
            libmetawear.mbl_mw_logging_download(self.device.board, 0, byref(download_handler))
            self.e.wait()
    
        def reset(self):
            e = Event()
            self.device.on_disconnect = lambda status: e.set()
            libmetawear.mbl_mw_debug_reset(self.device.board)
            e.wait()
            print(self.device.address + " resetted")
    
    devices = None
    array = sys.argv
    del array[0]
    print(array)
    states = []
    for a in array:
        device = MetaWear(a)
        device.connect()
        print("Connecting to " + device.address)
        print("CONNECTION STATE  " + str(device.is_connected))
        states.append(State(device))
    
    for s in states:
        print("Configuring %s" % (s.device.address))
        s.setup()
    
    for s in states:
        s.start()
    
    print("Logging data")
    stop = -1
    while stop == -1:
      msg = "Press s to stop data recording: "
      selection = raw_input(msg) if platform.python_version_tuple()[0] == '2' else input(msg)
      if selection == "s":
        stop = 0
    
    for s in states:
        if s.device.is_connected:
            print("connected to " + device.address)
            s.stop()
        else:
            while(not s.device.is_connected):
                retry_connection(s.device)
            s.stop()
    
    print("Downloading data")
    print("This step may take a few minutes")
    for s in states:
        s.download()
    
    print("Resetting sensors")
    for s in states:
        s.reset()
    </pre>
    
    <p>
    
  • this is my code, I would like to ask you if I am doing something wrong and if it is possible to speed up the download in some way.

    Thanks for any answers.

  • @giovanni_dq

    Some ways to improve download speed.

    Keep the device close while downloading to reduce potential interference/packet loss.
    Disable any sensor traffic, such as streaming that may be consuming bandwidth.
    Download over USB if using MMS.
    Limit simultaneous bluetooth connections which may reduce allocated link bandwidth.

    For faster BLE, add the command libmetawear.mbl_mw_settings_set_connection_parameters(d.board, 7.5, 7.5, 0, 6000) shortly after connecting to a device or before initiating the download. This will attempt to negotiate the fastest link parameters. Depending on platform, you may need to dial back the second 7.5 parameter slightly towards 10-15, as requesting too low a latency may fail. https://mbientlab.com/documents/metawear/cpp/latest/settings_8h.html#a1cf3cae052fe7981c26124340a41d66d

  • @Matt

    mbl_mw_settings_set_connection_parameters(device.board, 7.5, 7.5, 0, 6000)

    For 1.7.3 there is no improvement in downloading time which is the same as 1.7.3 higher ie taking 1.5 x times.

    mbl_mw_settings_set_connection_parameters(device.board, 10, 7.5, 0, 6000). - No getting data as logger not found the acceleration data
    guard let logger = self.loggers.removeValue(forKey: "acceleration") else {
    same happened with 12.5.
    mbl_mw_settings_set_connection_parameters(device.board, 12.5, 7.5, 0, 6000)

    is there any specific IOS-based connection parameters ?

  • @Srinivasa Note that the second parameter is max interval, and should always be requested >= min interval. This may explain why you are getting no data with that setting.

    Here is Apples recommendation for the connection parameter settings. It sounds like you should start with min interval at 15ms, and adjust slightly from there to see if there is any change in performance. It is most likely that requests for 7.5/10/12.5 ms are just getting ignored by the client.

    https://developer.apple.com/library/archive/qa/qa1931/_index.html

    I would try (15, 15, 0, 6000), (15, 30, 0, 6000) and (17.5, 32.5, 0, 6000) following those guidelines.

Sign In or Register to comment.