Timer creation sporadically fails

Hi there,

I use the following code (snippet) after setting up the connection to a MetaMotionR and after initializing it to then activate some modules and to setup some processors and timers:

mbl_mw_metawearboard_tear_down(m_metawear_board);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
mbl_mw_settings_set_connection_parameters(m_metawear_board, 7.5, 7.5, 0, 6000);

switch_dc_promise = std::promise<bool>();
auto switch_future = switch_dc_promise.get_future();
auto switch_signal = mbl_mw_switch_get_state_data_signal(m_metawear_board);
mbl_mw_dataprocessor_passthrough_create(switch_signal, MBL_MW_PASSTHROUGH_MODE_COUNT, 0, nullptr,
                                    C_MWC::c_switch_dc_recorded);
switch_future.wait();

switch_processor_promise = std::promise<bool>();
auto switch_processor_future = switch_processor_promise.get_future();
if (switch_dc_processor != nullptr) {
    mbl_mw_event_record_commands(switch_dc_processor);
    mbl_mw_led_stop_and_clear(m_metawear_board);
    mbl_mw_event_end_record(switch_dc_processor, nullptr,
                            C_MWC::c_switch_processor_recorded);
    switch_processor_future.get();
}

timer_promise = std::promise<int>();
auto timer_future = timer_promise.get_future();
auto batt_signal = mbl_mw_settings_get_battery_state_data_signal(m_metawear_board);
mbl_mw_datasignal_subscribe(batt_signal, nullptr, C_MWC::c_handle_battery);
mbl_mw_timer_create_indefinite(m_metawear_board, 500, 0, nullptr, C_MWC::c_timer_created);
timer_future.get();
mbl_mw_datasignal_read(batt_signal);

disconnect_promise = std::promise<bool>();
auto disconnect_future = disconnect_promise.get_future();
// Setup disconnect event to stop fusion and set led to red
MblMwEvent *dc_event = mbl_mw_settings_get_disconnect_event(m_metawear_board);
mbl_mw_event_record_commands(dc_event);
mbl_mw_sensor_fusion_stop(m_metawear_board);
mbl_mw_sensor_fusion_clear_enabled_mask(m_metawear_board);
mbl_mw_gyro_bmi160_stop(m_metawear_board);
mbl_mw_gyro_bmi160_disable_rotation_sampling(m_metawear_board);
mbl_mw_acc_stop(m_metawear_board);
mbl_mw_acc_disable_acceleration_sampling(m_metawear_board);
auto timer = mbl_mw_timer_lookup_id(m_metawear_board, m_battery_id);
if (timer != nullptr) {
    mbl_mw_timer_stop(timer);
    mbl_mw_timer_remove(timer);
}
if (switch_dc_processor != nullptr) mbl_mw_dataprocessor_passthrough_set_count(switch_dc_processor, 1);

mbl_mw_event_end_record(dc_event, nullptr, C_MWC::c_disconnect_recorded);
disconnect_future.get();

I use the promises to synchronize the asynchronous callbacks and the callbacks are handled in a friend class with static methods and a static reference to the class setting everything up, so that I have access to the members from there.

The callbacks of the snippet above are the following:

void C_MWC::c_switch_dc_recorded(void *context, MblMwDataProcessor *processor) {
    this_->switch_dc_recorded(processor);
}

void switch_dc_recorded(MblMwDataProcessor *pProcessor) {
    switch_dc_processor = pProcessor;
    switch_dc_promise.set_value(true);
}

void C_MWC::c_switch_processor_recorded(void *context, MblMwEvent *event, int32_t status) {
    this_->switch_processor_recorded(event, status);
}

void switch_processor_recorded(MblMwEvent *pEvent, int32_t status) {
    switch_processor_promise.set_value(status == 0);
}

void C_MWC::c_timer_created(void *cointext, MblMwTimer *timer) {
    this_->timer_created(timer);
}

void timer_created(MblMwTimer *pTimer) {
    if (pTimer != nullptr) {
        m_battery_timer = pTimer;
        m_battery_id = mbl_mw_timer_get_id(m_battery_timer);
        auto battery_signal = mbl_mw_settings_get_battery_state_data_signal(m_metawear_board);
        mbl_mw_event_record_commands((MblMwEvent *) pTimer);
        mbl_mw_datasignal_read(battery_signal);
        mbl_mw_event_end_record((MblMwEvent *) pTimer, nullptr, C_MWC::c_cmds_recorded);
    } else {
        m_logger.debug("Received a nullptr in timer_created");
        cmds_recorded(nullptr, TIMER_CREATION_ERROR_NULLPTR);
    }
}

void C_MWC::c_cmds_recorded(void *context, MblMwEvent *evt, int32_t status) {
    this_->cmds_recorded(evt, status);
}

void cmds_recorded(MblMwEvent *pEvent, int32_t status) {
    switch (status) {
        case MBL_MW_STATUS_OK:
            m_logger.debug("battery timer setup done!");
            mbl_mw_timer_start((MblMwTimer *) pEvent);
            break;
        case MBL_MW_STATUS_ERROR_TIMEOUT:
            m_logger.debug("timed out on recording battery reading command!");
            break;
        case TIMER_CREATION_ERROR_NULLPTR:
            m_logger.debug("was not able to get a valid timer pointer!");
            break;
        default:
            m_logger.debug("was not able to setup battery timer [UNKNOWN]");
            break;
    }

    timer_promise.set_value(status);
}

void C_MWC::c_disconnect_recorded(void *context, MblMwEvent *event, int32_t status) {
    this_->disconnect_recorded(event, status);
}

void disconnect_recorded(MblMwEvent *pEvent, int32_t status) {
    if (status == MBL_MW_STATUS_OK) {
        disconnect_promise.set_value(true);
    } else {
        if (status == MBL_MW_STATUS_ERROR_TIMEOUT) m_logger.debug("[TIMEOUT]");
        disconnect_promise.set_value(false);
    }
}

On the first connection to a sensor this is working, all the events and processors are created successfully. Unfortunately, after some successful connections, I am unable to get a valid timer when executing

mbl_mw_timer_create_indefinite(m_metawear_board, 500, 0, nullptr, C_MWC::c_timer_created);

In the callback I only get a nullptr as the MblMwTimer* parameter.

Currently I can only resolve this by resetting the sensor. Afterwards I get a valid timer on the first connection, and start getting nullptrs after some connections (sometimes, but not always, as soon as the second one).

All the other processors are still created successfully, and I can also use sensor fusion, the switch module, the vibration motor and the LED. Only the timer I create to periodically check the current battery is not working.

Can you see some any mistakes I made when setting this up? Is there anything I can do to mitigate that problem?

Thank you!
Marcus

Comments

  • I forgot to mention that I remove the created timers and processors before disconnecting, e.g. to remove the mentioned battery timer I use:

    if (m_battery_timer != nullptr) {
        m_logger.debug("removing battery timer");
        auto timer = mbl_mw_timer_lookup_id(m_metawear_board, m_battery_id);
        if (timer != nullptr) {
            mbl_mw_timer_stop(timer);
            mbl_mw_timer_remove(timer);
        }
        m_battery_timer = nullptr;
        m_battery_id = 0;
    } else {
        m_logger.debug("no battery timer to remove");
    }
    mbl_mw_datasignal_unsubscribe(mbl_mw_settings_get_battery_state_data_signal(m_metawear_board));
    
  • What is the id of the timers that are created prior to receiving a nullptr (mbl_mw_timer_get_id)?
    Can you confirm that the remove command is being received by the device before the script terminates?

  • HI, sorry for not replying sooner.

    I read out the IDs I receive before getting a nullptr and got the following:

    14.08.2018 12:46:55.349 [debug] MetaWearDevice Setting up modules
    14.08.2018 12:46:55.349 [debug] MetaWearDevice Enabling battery
    14.08.2018 12:46:55.449 [debug] MetaWearDevice Created the battery timer with timer ID: 0
    
    14.08.2018 12:48:02.400 [debug] MetaWearDevice Setting up modules
    14.08.2018 12:48:02.400 [debug] MetaWearDevice Enabling battery
    14.08.2018 12:48:02.500 [debug] MetaWearDevice Created the battery timer with timer ID: 1
    
    14.08.2018 12:48:25.000 [debug] MetaWearDevice Enabling battery
    14.08.2018 12:48:25.101 [debug] MetaWearDevice Created the battery timer with timer ID: 2
    
    14.08.2018 12:49:24.551 [debug] MetaWearDevice Enabling battery
    14.08.2018 12:49:24.701 [debug] MetaWearDevice Created the battery timer with timer ID: 3
    

    As the IDs increased every time and as you asked me to confirm, that the timer is actually removed before the sensor is disconnected, I had a look again at the code, where the timer is removed.

    As I posted before, the code was:

        auto timer = mbl_mw_timer_lookup_id(m_metawear_board, m_battery_id);
        if (timer != nullptr) {
            mbl_mw_timer_stop(timer);
            mbl_mw_timer_remove(timer);
        }
        m_battery_timer = nullptr;
    

    I included some additional logging and received the following outputs:

    14.08.2018 12:52:36.604 [debug] MetaWearDevice Enabling battery
    14.08.2018 12:52:36.704 [debug] MetaWearDevice Created the battery timer with timer ID: 4
    ...
    got request: 'disconnect'
    14.08.2018 12:52:39.591 [debug] MetaWearDevice removing battery timer for battery_id 4
    14.08.2018 12:52:39.591 [debug] MetaWearDevice Looking up the battery id resulted in a nullptr. Can't remove timer!
    
    14.08.2018 12:54:44.455 [debug] MetaWearDevice Created the battery timer with timer ID: 5
    ...
    got request: 'disconnect'
    14.08.2018 12:54:46.889 [debug] MetaWearDevice removing battery timer for battery_id 5
    14.08.2018 12:54:46.889 [debug] MetaWearDevice Looking up the battery id resulted in a nullptr. Can't remove timer!
    

    So the problem seems to be, that I receive a nullptr on mbl_mw_timer_lookup_id and am therefore not removing the timer. As a workaround I will not request it before removing but instead remember it after creation, but what might be the problem here?

  • I think I found the problem.

    I am setting up a disconnect handler on board, that disables the modules I activate, as well as trying to remove any timers and processors.

    Currently the following code is executed:

    disconnect_promise = std::promise<bool>();
    auto disconnect_future = disconnect_promise.get_future();
    MblMwEvent *dc_event = mbl_mw_settings_get_disconnect_event(m_metawear_board);
    mbl_mw_event_record_commands(dc_event);
    // ...
    // Disabling of some modules
    // ...
    auto timer = mbl_mw_timer_lookup_id(m_metawear_board, m_battery_id);
    if (timer != nullptr) {
        mbl_mw_timer_stop(timer);
        mbl_mw_timer_remove(timer);
    }
    if (switch_dc_processor != nullptr) mbl_mw_dataprocessor_passthrough_set_count(switch_dc_processor, 1);
    mbl_mw_event_end_record(dc_event, nullptr, C_MWC::c_disconnect_recorded);
    disconnect_future.get();
    

    If I remove the line with mbl_mw_timer_remove(timer); from this code block, leaving only the mbl_mw_timer_stop(timer); everything then works as expected. I receive a valid timer during the actual disconnect using mbl_mw_timer_lookup_id and on the next connection I receive the same timer ID, which I guess means, that the timer was actually removed.

    I therefore assume, that by calling mbl_mw_timer_remove during the mbl_mw_event_record_commands I somehow invalidate the timer? Am I actually removing it from the board during the recording?

    Unfortunately, the timer is now of course no longer removed on an unexpected disconnect in the disconnect handler. So after a connection loss I get a timer with a higher ID.

    Is there some way to remove timers (and processors I guess) during the registering of a disconnect handler without making them invalid?

  • I am also wondering about the effect of the mbl_mw_metawearboard_tear_down I am doing directly after connecting to the board.

    In the API it is described as

    Removes all data processors and timers from the MetaWear board. 
    

    But it seems not to remove any stale timers. Do I have to use it differently?

  • mbl_mw_metawearboard_tear_down only removes timers it is aware of; it is meant to be called at the end of a script.

    You already have the timer pointer so just use m_battery_timer directly instead of looking it up again by id.

    Given that you're running so much code to stop everything, just reset the board on disconnect.

  • Hi,

    sorry to reopen this stale thread, but I have question more or less regarding the topics already discussed here.

    Currently we chose to follow your suggestion and to just reset the board on disconnect to remove all timers and processors should we loose the connection.

    We do this as we still face the problem that removing timers or dataprocessors during the disconnect event recording results in them being removed instantly, not after a disconnect, which makes this approach unusable.

    But we are currently thinking about implementing a charging indicator for disconnected boards that would require a registered handler for the charge_status_data_signal that survives a disconnect.

    Is it possible to setup something like this?
    In detail we would need the following:

    • setup dataprocessors and timers for data streaming (from a connected board)
    • some way to remove these from the board on disconnect (either planned or unexpected)
    • a way to register a handler for the charge_status datasignal to react on charge status changes (we want to change the LED) that survives disconnecting
  • Program the charge events with the macro module

  • Hi Eric,

    I setup a process to program charge events (as well as writing calibration data for sensor fusion) using the macro module as you advised.

    This is working, in that I receive a valid macro ID and it seems these macros also survive a disconnect, as I receive a higher macro ID when I try to store a new one after disconnecting.
    (so the first macro recording results in macro ID 0, after a disconnect the next recording results in macro ID 1, and so on)

    But it seems the recordings do not survive a board debug reset.
    If I not only disconnect but reset between flashing a macro, I always get macro ID 0.

    So I assume the macro module is in fact not a solution to the problem I outlined before?

  • edited February 19

    Post the macro setup code that you believe is failing.

  • edited February 22

    Hi,

    I have the following code in an Android App that tries to write previously stored calibration data and a (simple, not yet really functional) reaction to a power status change as a macro

    public void writeCalibrationData() {
        final Macro macro = metawear.getModule(Macro.class);
        final SensorFusionBosch sensorFusion = metawear.getModule(SensorFusionBosch.class);
        final Settings settings = metawear.getModule(Settings.class);
        final Led led = metawear.getModule(Led.class);
        macro.startRecord(true);
        sensorFusion.writeCalibrationData(calibrationData);
        settings.powerStatus().addRouteAsync(new RouteBuilder() {
            @Override
            public void configure(RouteComponent source) {
                source.react(new RouteComponent.Action() {
                    @Override
                    public void execute(DataToken token) {
                        led.stop(true);
                        led.editPattern(Led.Color.GREEN, Led.PatternPreset.PULSE);
                        led.play();
                    }
                });
    
            }
        }).continueWith( innrtask -> {
            macro.endRecordAsync().continueWith(new Continuation<Byte, Void>() {
                @Override
                public Void then(Task<Byte> task) throws Exception {
                    Log.i("MainActivity", "Macro ID = " + task.getResult());
                    return null;
                }
            });
            return null;
            }
        );
    }
    

    As I mentioned before, the first time I execute this I get a log with

    Macro ID = 0
    

    If I execute the same method again without calling macro.eraseAll() in between I get

    Macro ID = 1
    

    This is the behaviour I expected.

    My problem is that when I write a macro (ID = 0) and then debug reset the sensor, this macro is presumably also deleted, as I get Macro ID = 0 again the next time I try to write one.
    Currently we are calling debug reset in the onboard disconnect handler, as we are otherwise unable to reliably clean up all stored timers and dataprocessors (as I described in my previous posts).

    • where in the macro code does the reset occur?
    • Have you tested of the power status macro works with and without the reset?
  • The reset is not issued inside the macro.

    Our current setup is the following:

    • the android code I posted above is from a small setup app we use to configure and setup our sensors (names, firmware updates, etc.), this is where we would like to setup the macro
    • the reset is issued from the disconnect handler we setup from a c++ library we use to actually interact with our sensors (data streaming, etc.), the code for that is

      m_logger.debug("Setting up disconnect event");
      disconnect_promise = std::promise<bool>();
      auto disconnect_future = disconnect_promise.get_future();
      MblMwEvent *dc_event = mbl_mw_settings_get_disconnect_event(m_metawear_board);
      mbl_mw_event_record_commands(dc_event);
      mbl_mw_debug_reset(m_metawear_board);
      mbl_mw_event_end_record(dc_event, nullptr, [](void *context, MblMwEvent *event, int32_t status) {
          if (status == MBL_MW_STATUS_OK) {
              C_MWC::this_->m_logger.debug("disconnect commands recorded!");
              C_MWC::this_->disconnect_promise.set_value(true);
          } else {
              if (status == MBL_MW_STATUS_ERROR_TIMEOUT) C_MWC::this_->m_logger.debug("[TIMEOUT]");
              C_MWC::this_->m_logger.debug("error recording disconnect commands: " + std::to_string(status));
              C_MWC::this_->disconnect_promise.set_value(false);
          }
      });
      

    We shortly tried the macro with the code I posted above, but we did not see any LED reaction. But we stopped trying when we realized that the macros seem to be deleted.

  • edited March 13

    Sorry to bump this, but do you have any more feedback regarding the topic?

    Especially regarding:

    • is it possible to create macros that survive a reset?
    • if not, is it possible to reliably delete all timers and processors on board in case of an unexpected disconnect without using reset?
  • @mgeorgi said:
    Sorry to bump this, but do you have any more feedback regarding the topic?

    Especially regarding:

    • is it possible to create macros that survive a reset?

    Yes. If it wasn't, MetaBase wouldn't work.

    You can confirm this by having a macro turn on the LED at boot, then reset the board. The LED will turn on once reset.

  • I just tried this.

    I wrote a macro that turns on the LED on boot (much like the example from the android docs) and it worked after putting the device to sleep (I used metabase, so I assume it uses enablePowersave) and rebooting with the button.

    But if I issue a debug reset (also using metabase, I assume using resetAsync) afterwards and put it to sleep after reconnecting, the LED will not turn on when pressing the button (and I also get macro ID = 0 again).

  • edited March 14

    MetaBase clears everything with that reeset button; what you are describing is the expected behavior.

    I am talking about simple reset, no macro or log clears.

  • Thank you for clearing up the confusion, I assumed that the reset in MetaBase would only issue a simple reset.

    When not using MetaBase reset but only a "simple" reset, this actually works and the macro survives.

    One follow-up question though:
    Is it possible to manipulate routes or dataprocessors set up in a macro from an application that did not create that macro?

    I ask because the macro we set up changes the LED based on whether a power source is attached and whether the battery is currently being charged or not.
    But of course this behaviour now also persists when actually using the sensor, which is something we would like to avoid.

    I was hoping to maybe use a dataprocessor with a modifyable signal like a comparator to change that processor once connected and thereby effectively "disabling" the route. But when I connect the sensor and issue a mbl_mw_dataprocessor_lookup_id with ID 0 (assuming that would be one of the dataprocessor IDs created in the macro) without having created any dataprocessors in that (C++) application I only get a SIGABRT beause of 'std::out_of_range' from _Map_base::at at dataprocessor.cpp:592

    Is there any other way to modify the internal routes set up in the macro?

    And also: shouldn't the lookup_id return a nullptr when no object can be found (like mentioned in the docs)?

  • @mgeorgi said:
    One follow-up question though:
    Is it possible to manipulate routes or dataprocessors set up in a macro from an application that did not create that macro?

    The only cross device usage we support is downloading logged data. You could do it if the applications are using the same SDK but not in the general case.

    I was hoping to maybe use a dataprocessor with a modifyable signal like a comparator to change that processor once connected and thereby effectively "disabling" the route. But when I connect the sensor and issue a mbl_mw_dataprocessor_lookup_id with ID 0 (assuming that would be one of the dataprocessor IDs created in the macro) without having created any dataprocessors in that (C++) application I only get a SIGABRT beause of 'std::out_of_range' from _Map_base::at at dataprocessor.cpp:592

    Is there any other way to modify the internal routes set up in the macro?

    No

    And also: shouldn't the lookup_id return a nullptr when no object can be found (like mentioned in the docs)?

    Yes it should. You can catch the exception as a temporary workaround.

  • Alright, thanks

    @Eric said:
    The only cross device usage we support is downloading logged data. You could do it if the applications are using the same SDK but not in the general case.

    Can you tell me more about that? Would it be possible to change something in the processors if I set up the macro using the C++ SDK? Or is the same SDK the requirement for downloading log data?

  • @mgeorgi said:
    Alright, thanks

    @Eric said:
    The only cross device usage we support is downloading logged data. You could do it if the applications are using the same SDK but not in the general case.

    Can you tell me more about that? Would it be possible to change something in the processors if I set up the macro using the C++ SDK? Or is the same SDK the requirement for downloading log data?

    You can manipulate the board however you want if you are using the same SDK.

    Downloading logged data is the only universal thing you can do regardless of SDK.

  • @Eric said:
    You can manipulate the board however you want if you are using the same SDK.

    I did replicate the macro setup using the C++ SDK to try and change the dataprocessors I created.

    The code for setting up the macro is the following (sorry for the long lines, it was easiest to just chain the callbacks):

    struct board_and_promise {
    
        board_and_promise(MblMwMetaWearBoard* board, MblMwDataSignal * power, MblMwDataSignal * charge, std::shared_ptr<std::promise<bool>> &prom) {
            this->board = board;
            this->power = power;
            this->charge = charge;
            this->promise = prom;
        }
    
        MblMwMetaWearBoard * board;
        MblMwDataSignal * power;
        MblMwDataSignal * charge;
        std::shared_ptr<std::promise<bool>> promise;
    };
    
    auto power_signal = mbl_mw_settings_get_power_status_data_signal(m_metawear_board);
    auto charge_signal = mbl_mw_settings_get_charge_status_data_signal(m_metawear_board);
    mbl_mw_macro_record(m_metawear_board, 1);
    if (power_signal != nullptr && charge_signal != nullptr) {
        auto dt_prom = std::make_shared<std::promise<bool>>();
        auto dt_ftr = dt_prom->get_future();
        board_and_promise bap(m_metawear_board, power_signal, charge_signal, dt_prom);
        mbl_mw_dataprocessor_comparator_create(power_signal, MBL_MW_COMPARATOR_OP_GT, 0,
                (void *) &bap, [](void* context, MblMwDataProcessor* processor) {
            printf("comparison processor for power created\n");
            mbl_mw_event_record_commands((MblMwEvent*)processor);
            mbl_mw_led_stop(((board_and_promise *) context)->board);
            MblMwLedPattern pattern_pulse{};
            mbl_mw_led_load_preset_pattern(&pattern_pulse, MBL_MW_LED_PRESET_PULSE);
            mbl_mw_led_write_pattern(((board_and_promise *) context)->board, &pattern_pulse, MBL_MW_LED_COLOR_GREEN);
            mbl_mw_led_autoplay(((board_and_promise *) context)->board);
            mbl_mw_event_end_record((MblMwEvent*)processor, context, [](void* context, MblMwEvent*, int32_t) {
                printf("comparator for power active created\n");
    
                mbl_mw_dataprocessor_comparator_create(((board_and_promise *) context)->power, MBL_MW_COMPARATOR_OP_EQ, 0,
                        context, [](void* context, MblMwDataProcessor* processor) {
                    printf("comparison processor for power created\n");
                    mbl_mw_event_record_commands((MblMwEvent*)processor);
                    mbl_mw_led_stop(((board_and_promise *) context)->board);
                    mbl_mw_event_end_record((MblMwEvent*)processor, context, [](void* context, MblMwEvent*, int32_t) {
                        printf("comparator for power inactive created\n");
    
                        mbl_mw_dataprocessor_comparator_create(((board_and_promise *) context)->charge, MBL_MW_COMPARATOR_OP_GT, 0,
                                context, [](void* context, MblMwDataProcessor* processor) {
                            printf("comparison processor for charge created\n");
                            mbl_mw_event_record_commands((MblMwEvent*)processor);
                            MblMwLedPattern pattern_pulse{};
                            mbl_mw_led_load_preset_pattern(&pattern_pulse, MBL_MW_LED_PRESET_PULSE);
                            mbl_mw_led_write_pattern(((board_and_promise *) context)->board, &pattern_pulse, MBL_MW_LED_COLOR_GREEN);
                            mbl_mw_event_end_record((MblMwEvent*)processor, context, [](void* context, MblMwEvent*, int32_t) {
                                printf("comparator for charge active created\n");
    
                                mbl_mw_dataprocessor_comparator_create(((board_and_promise *) context)->charge, MBL_MW_COMPARATOR_OP_EQ, 0,
                                        context, [](void* context, MblMwDataProcessor* processor) {
                                    printf("comparison processor for charge created\n");
                                    mbl_mw_event_record_commands((MblMwEvent*)processor);
                                    MblMwLedPattern pattern_solid{};
                                    mbl_mw_led_load_preset_pattern(&pattern_solid, MBL_MW_LED_PRESET_SOLID);
                                    mbl_mw_led_write_pattern(((board_and_promise *) context)->board, &pattern_solid, MBL_MW_LED_COLOR_GREEN);
                                    mbl_mw_event_end_record((MblMwEvent*)processor, context, [](void* context, MblMwEvent*, int32_t) {
                                        ((board_and_promise *) context)->promise->set_value(true);
                                    });
                                });
                            });
                        });
                    });
                });
            });
        });
        dt_ftr.get();
    }
    
    mbl_mw_macro_end_record(m_metawear_board, (void *) clb_promise.get(), [](void* context, MblMwMetaWearBoard* board, int32_t id){
        std::cout << "Macro ID = " << id << std::endl;
        ((std::promise<bool> *) context)->set_value(true);
    });
    clb_future.get();
    std::cout << "Onboot Macros setup" << std::endl;
    std::this_thread::sleep_for(std::chrono::milliseconds(200));
    std::cout << "Slept" << std::endl;
    mbl_mw_debug_reset_after_gc(m_metawear_board);
    

    This is working in so far, as that the LED is reacting to plugging in a power source as intended.

    I still have the problem, that I can't "deactivate" these routes once I connect the sensor again afterwards and I tried to do what I initially planned to do and change the comparator dataprocessors.

    But a mbl_mw_dataprocessor_lookup_id with ID 0 on a fresh connection still results in a nullptr / out_of_range.
    Is it not possible to actually check for exisiting dataprocessors? Do I have to "remember" them after setting them up and just assume they are there?

  • edited March 22

    Yes, you have to remember them between runs. That is what serialization is for.

    https://mbientlab.com/cppdocs/0/advanced_features.html#serialization

  • Understood.

    But is there any way to find out after connecting a sensor whether any macros were already setup on that specific device?

    I am asking because we want to ensure backwards compatibility of our software to sensors we did not yet setup with the charging macros.

  • @mgeorgi said:
    Understood.

    But is there any way to find out after connecting a sensor whether any macros were already setup on that specific device?

    No, there is not.

    I am asking because we want to ensure backwards compatibility of our software to sensors we did not yet setup with the charging macros.

    You can have the boards with the new setup retain some special state that your app can use distinguish between the two. The debug module has a 4 byte temp variable that you can use to write whatever value you want to it.

    mbl_mw_debug_get_key_register_data_signal
    mbl_mw_debug_set_key_register

  • Thanks, I'll have a look into that!

Sign In or Register to comment.