createAnonymousRoutesAsync() confuses DataProcessor

As far as I can tell, I stumbled over a firmware-bug. Or at least I am very confused about that behavior and hope that somebody can help me out :)

I am using a MetaMotion R with version 1.4.5. It seems to me that using createAnonymousRoutesAsync(), scrambles with the board state.
When I have the following code, everything works fine:

public void bug1(MetaWearBoard board) {
    board.getModule(Settings.class).battery().addRouteAsync(source -> source.limit(Passthrough.COUNT, (short) 0).name("battery_log").log(null))
    .continueWith(task -> {
        try {
            board.getModule(DataProcessor.class).edit("battery_log", DataProcessor.PassthroughEditor.class).set((short) 1);
            board.getModule(Settings.class).battery().read();
        }
        catch (Exception e) {
            Log.d("board", "Crash!");
            e.printStackTrace();
        }
        Log.d("board", "Success!");
        return null;
    });
}

But adding a createAnonymousRoutesAsync() in between, leads to a ClassCastException:

public void bug2(MetaWearBoard board) {
    board.getModule(Settings.class).battery().addRouteAsync(source -> source.limit(Passthrough.COUNT, (short) 0).name("battery_log").log(null))
    .continueWithTask((Task<Route> task) ->  board.createAnonymousRoutesAsync())
    .continueWith(task -> {
        try {
            board.getModule(DataProcessor.class).edit("battery_log", DataProcessor.PassthroughEditor.class).set((short) 1);
            board.getModule(Settings.class).battery().read();
        }
        catch (Exception e) {
            Log.d("board", "Crash!");
            e.printStackTrace();
        }
        Log.d("board", "Success!");
        return null;
    });
}

It doesnt seem to make a difference if the results from createAnonymousRoutesAsync() are subscribed to or downloadAsync() is called. As soon as createAnonymousRoutesAsync() is used, "battery_log" in the DataProcessor does not seem to exist anymore. Everything works fine if I call createAnonymousRoutesAsync(), disconnect and reconnect from the board.

Am I doing something wrong here?

Thanks for your help!

Comments

  • Why are you creating an anonymous route with the object that created the original logging route?

  • edited October 2019

    @Eric said:
    Why are you creating an anonymous route with the object that created the original logging route?

    I am not. I just simplified the code as much as possible and created a showcase to shed light on behavior I dont really understand :)

    In our app all these steps (creating the DataProcessor, loading the battery state and downloading the data) are used at different points in time.
    The main reason why I am using an anonymous route is because I need to make sure that all data are downloaded even when the board was programmed by another phone.

    This crash is problematic for us because this "error" is also serialized when using board.serialize(). This means that when we download data from the board and then serialize its current state, our app will crash every time the battery state is checked, even after disconnecting the board for a while. Even worse, a second call to createAnonymousRoutesAsync() will crash as well, meaning that no more data can be downloaded without fully resetting the board.

    Is there a reason for that crash and is there a way to avoid it?

  • Anonymous routes are solely for downloading data. If you have the object state available, serialized or original object, you don't need anonymous routes.

  • edited October 2019

    I know, but as far as I understand, anonymous routes are the only way to download data that was not programmed by the current phone (which is something our app needs to be prepared for). And it also gives me the option to check which data will be downloaded (by checking the identifier-strings), before I initiate the actual download by calling downloadAsync().

    The code I posted is just a very simplified test. I don't use this code in our app. I just created it to showcase the cause of the problem.

    As far as I understand, createAnonymousRoutesAsync() only checks for existing downloadable routes and does not change the state of the board.
    So, calling createAnonymousRoutesAsync() should not be able to influence if board.getModule(DataProcessor.class).edit("battery_log", DataProcessor.PassthroughEditor.class) crashes or not. But it does.
    That is why I think it must be a problem with the firmware. Or am I overlooking something?

    It should be impossible that the catch block in the following code will ever be reached, right? But it does so on several different boards. Why?

    public void bug(MetaWearBoard board) {
        board.getModule(Settings.class).battery().addRouteAsync(source -> source.limit(Passthrough.COUNT, (short) 0).name("battery_log").log(null))
            .continueWithTask((Task<Route> task) -> {
                if(task.isFaulted())
                    throw task.getError();
                return board.createAnonymousRoutesAsync(); //replace me with "return null;" and no crash will happen!
            })
            .continueWith(task -> {
                if(task.isFaulted()) {
                    Log.d("board", "There were preceding errors. Abort!");
                    return null;
                }
                try {
                    board.getModule(DataProcessor.class).edit("battery_log", DataProcessor.PassthroughEditor.class).set((short) 1);
                    board.getModule(Settings.class).battery().read();
                }
                catch (ClassCastException e) {
                    Log.d("board", "This crash should be impossible!");
                    e.printStackTrace();
                    return null;
                }
                Log.d("board", "Yay! No crash happened.");
                return null;
            });
    }
    

    (Again I dont intend to use this code, I just want to figure out why it is even able to crash)

    Thank you for your help!

  • Is there any news on this?
    As far as I understand, there is nothing I can do on my end to resolve this issue

  • I really need your input here. There has been some other issues as well which may be connected to this problem.
    Do you need any other information from me?

    Please respond

  • Sorry to bumb again, but we need a solution for this problem.

    Does it happen because I am using createAnonymousRoutesAsync()?
    Will there be a fix for this issue? Or is there any other solution?

  • edited November 2019

    There is no "fix"; as already stated, don't mix the two features.

    If you have the serialized state
    Deserialize and use the api as is. Don't use anonymous routes.

    If you don't have serialized state
    Use anonymous routes to get logged data, but you won't be able to use other on-board features like data processing and macros.

  • edited November 2019

    Ah ok Thanks!

    So, just for my understanding, what does createAnonymousRoutesAsync() actually do differently internally?
    I would guess it overwrites some parts of the saved state of the board? And that is why I cant use the data processor anymore after I have called createAnonymousRoutesAsync() unless I load a previously serialized state of the board?
    Is that assumption correct?
    Why does downloading the data (over anonymous routes) from data processors still work?
    How are macros related to this? :)

    Thanks for your input. That helps a lot!
    You may want to add these limitations to your docs, because as far as I can find, they are stated nowhere in https://mbientlab.com/androiddocs/latest/advanced_features.html#anonymous-routes
    And to me it read like they are an advanced technique for downloading where at least the download types can be checked before downloading - but as far as I understand your responses, it is the other way around :)

Sign In or Register to comment.