Should I use service or/and alarm manager to download log entries from the board?

Hi,


What is the best way to periodically and reliably download logs from the board?
Should I use two apps one to program the sensor and another app (service/alarm manager) to download logs?
Right now I stream data and immediately upload to the cloud but when phone gets disconnected from the board I am loosing entries.

I was trying to split the app into two but I don't know how to get the MessageHandler to run on the service app.

Thank you very much,
Michael

Comments

  • You don't need two apps for this; the same app can handle both uses.  Schedule a task to connect, download, then disconnect using the Handler class after you're done setting up the board.
  • Thank you Eric. I will try this. Seems like it should work even when the app is not active. 
  • For some reason the board doesn't re-connect. Works only the first time around. Should I also reset BLE? Thanks!


       android.os.Handler handler = new android.os.Handler();
    private final Runnable sendData = new Runnable(){
    public void run(){
    try {
    //prepare and send the data here..
    i++;
    Log.i("tutorial", "Doownload#:" + String.format("%d",i));

    if(!mwBoard.isConnected()){
    mwBoard.connect();
    Log.i("tutorial", "Disconnected, try to connect");
    }
    if(mwBoard.isConnected()){
    //download from board/upload to cloud
    Log.i("tutorial", "connected ");
    try {

    accModule = mwBoard.getModule(Bmi160Accelerometer.class);
    accModule.stop();
    accModule.disableAxisSampling();
    loggingModule = mwBoard.getModule(Logging.class);
    loggingModule.stopLogging();
    Log.i("tutorial","stop logging");

    } catch (UnsupportedModuleException e) {
    Log.e("tutorial", e.toString());
    }

    loggingModule.downloadLog(0.f, new Logging.DownloadHandler() {
    @Override
    public void onProgressUpdate(int nEntriesLeft, int totalEntries) {
    if (nEntriesLeft == 0) {
    Log.i("tutorial", "Log download complete");
    }
    }});
    accModule.enableAxisSampling();
    accModule.start();
    loggingModule.startLogging(true);
    Log.i("tutorial", "start logging and disconnect");
    mwBoard.disconnect();
    }

    //------------------------------------------------------------------
    handler.postDelayed(this, INTERVAL);
    }
    catch (Exception e) {
    e.printStackTrace();
    }
    }
    };


  • Connect is an asynchronous operation.  You need to rely on the ConnectionStateHandler class to react to connection attempts.


  • Thank you Eric. It works but it is very inconsistent.  The app is crashing while trying to reconnect and i am losing stored logs. Should I do soft reset, stop and start logging?  Here is my code:
  • Thank you Eric. It works but it is very inconsistent.  The app is crashing while trying to reconnect and i am losing stored logs.
     Should I do soft reset, stop and start logging?  Here is my code:
  • public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    handler.postDelayed(sendData, 900000);//15*60*1000=900000 debug 1min =60000

    }

    //---------------------------------------------------------------------------
    private final MetaWearBoard.ConnectionStateHandler stateHandler = new MetaWearBoard.ConnectionStateHandler() {
    @Override
    public void connected() {
    handler.postDelayed(sendData, 900000);//15*60*1000=900000 debug 1min =60000
    }
    };

    private void connectDevice() {
    // mwBoard = metaWearBinder.getMetaWearBoard(device);
    mwBoard.setConnectionStateHandler(stateHandler);
    mwBoard.connect();

    }

    android.os.Handler handler = new android.os.Handler();
    private final Runnable sendData = new Runnable() {
    public void run() {
    // ????
    connectDevice();
    //prepare and send data here..
    loggingModule.downloadLog(0.f, new Logging.DownloadHandler() {
    @Override
    public void onProgressUpdate(int nEntriesLeft, int totalEntries) {
    if (nEntriesLeft == 0) {

    mwBoard.disconnect();
    }
    }
    });
    handler.postDelayed(sendData, 900000);//15*60*1000=900000 debug 1min =60000
    }
    };
  • You are only connecting to the board once while downloading the log multiple times with a disconnect call after the download is complete.
  • Sorry, can you elaborate a bit more? You mean I don't need to run connectDevice(); every time when I download the log? I need the  board to reconnect and download when the board is in close proximity from the phone and on WiFi.I can't find any examples on your site or GitHub.
  • Apologies, I misinterpreted your code.

    The only thing your Runnable should do is attempt to connect.  Use the ConnectionStateHandler to start a download if the attempt is successful.  If the connection fails, schedule another connection attempt.
  • It is still not working for me. Even when Runnable reports that the board is connected  the ConnectionStateHandler  connected() event is not firing.  
     android.os.Handler handler = new android.os.Handler();
    private final Runnable sendData = new Runnable() {
    public void run() {
    // is connected
    mwBoard.setConnectionStateHandler(stateHandler);
    mwBoard.connect();
                handler.postDelayed(sendData, INTERVAL);//15*60*1000=900000 debug 1min =60000
    }
    };
    private final MetaWearBoard.ConnectionStateHandler stateHandler = new MetaWearBoard.ConnectionStateHandler() {
    @Override
    public void connected() {
    // doesn't run
    downloadLog();
    }
  • If you already have a connection, you don't need to call connect and can immediately start a log download.
  • As you have advised I disconnect after I finish log download. I do that in my downloadLog() method.
    I am using your starter sample. Also what's the most frustrating is that the log gets wiped out if I restart the app. How do I preserve it and  download first?  

     As a side note, why can't you just give us a two simple classes - one to program the board and another to retrieve the log? All I am trying to do is to get RMS off the board every 10 minutes. Why is it so hard? 

  • Write the data to a file or database for persistent storage.

    I've identified a firmware bug that crashes the firmware when connecting to the board during logging which is most likely the root cause of the "only works the first time" issue you mentioned.   I've passed it on to the firmware developer to look into.

    The starter templates, as is, are not a "one size fits all" solution for every app.  They simply serve as a quick  way to get started with creating a simple MetaWear app and will not cover all uses.  Users are encouraged to modify the code as needed to suit their individual use cases.
  • Thank you Eric. So back to my original question if my code above is in fact correct.
    When MetaWearBoard.ConnectionStateHandler() is connected  I  download log off the board and then disconnect  in "connected()"  method and only connect again on every run from Runnable expecting "connected()" event to fire to start download and disconnect againI don't understand then why this isn't working for me on every iteration. It works perfectly when I connect manually and push download button from activity fragment.  
    And yes, I do save data to local db when WiFi is not available, otherwise I immediately upload to IBM Bluemix.
    My main goal is to periodically push data to the cloud.   
    Thanks again for all your help.
     

  • Hi,

    @mikesv could you share a sample of the Android service you did ?

    I'm also looking for a background service that connect to the device, retrive logs, and do something like
    - push notification
    - upload to the cloud

    I made a 3d print connected cap and need to retrieve when the cap is open/closed throught gyroscope to say "you don't drink enought"

    All samples describe how to download data log from an app but not how to do it all day long from a service.

    Thanks !
  • Hi,

    I am actually using Eric's link from above . It is not a service but scheduled task. It works great for my project. I have a dedicated Android phone that uploads data from sensor's log when it is in close proximity.
    I use MQTT and Node-Red to store data into DashDB on IBM Bluemix. Then I run specific analytics and send results back as an email message using Node-Red every few hours.
    Here is my post with links to code samples:

    https://developer.ibm.com/answers/questions/270908/mqtt-client-cant-connect-to-my-iot-application-on.html#answer-270942

    Your idea is great but it will be one expensive cap. :)  I am replacing batteries every week and they are not cheap.  Maybe you should consider making a cap for wine bottles and say "you drink TOO much" :) 
    Sorry, couldn't resist the joke.
    Good luck with your project! It's a lot of fun and MbientLab guys are awesome.
    Michael



This discussion has been closed.