A problem about serialization and deserialization of board

Hi,

I got a problem while deserializing metawear board.


This is my downloadData function:

private void downloadData(ProgressBar progress) throws FileNotFoundException {
        String datetime = DateFormat.getDateTimeInstance().format(new Date());
        accelerometerWriter = new DataWriter(board.getMacAddress() + "_" + datetime + "_accelerometer" + ".csv");
        gyroscopeWriter = new DataWriter(board.getMacAddress() + "_" + datetime + "_gyroscope" + ".csv");
        stepWriter = new DataWriter(board.getMacAddress() + "_" + datetime + "_step" + ".csv");
        stopAllSensors(false, false);
        logging.downloadAsync(100, (nEntriesLeft, totalEntries) -> {
            Log.i("MainActivity", "Progress Update = " + (totalEntries - nEntriesLeft) + "/" + totalEntries);
            mainActivity.runOnUiThread(() -> {
                progress.setMax((int) totalEntries);
                progress.setProgress((int) totalEntries - (int) nEntriesLeft);
            });
        }).continueWithTask((Continuation<Void, Task<Void>>) task -> {
            Log.i("MainActivity", "Download completed");
            progress.setProgress(0);
            board.tearDown();
            disconnectBoard(true);
            accelerometerWriter.closeStream();
            gyroscopeWriter.closeStream();
            stepWriter.closeStream();
            return null;
        });
    }

I serialize board right after all sensors are started and right before starting logging, and deserialize the board after "stopAllSensors()" is called.



This is my stopAllSensors() function:

private void stopAllSensors(boolean teardown, boolean disconnect) {
        Log.i(TAG, "Stop all sensors");
        accelerometerBmi160.acceleration().stop();
        accelerometerBmi160.stepDetector().stop();
        accelerometerBmi160.stop();

        gyroBmi160.angularVelocity().stop();
        gyroBmi160.stop();
        logging.stop();
        led.stop(true);
        if (teardown)
            board.tearDown();
        if (disconnect)
            disconnectBoard(true);

        deserializeBoard(); // Load current board state for data collection or clear all the serializeFiles
    }

My subscribers are like below:

 private static Subscriber ACCELEROMETER_HANDLER = (Data data, Object... env) -> {
        String value = data.timestamp().getTimeInMillis() + "," +
                data.formattedTimestamp() + "," +
                "0" + "," +
                data.value(Acceleration.class).x() + "," +
                data.value(Acceleration.class).y() + "," +
                data.value(Acceleration.class).z() + "\n";
        getInstance().accelerometerWriter.write(value);
    };

    private static Subscriber GYROSCOPE_HANDLER = (Data data, Object... env) -> {
        String value = data.timestamp().getTimeInMillis() + "," +
                data.formattedTimestamp() + "," +
                "0" + "," +
                data.value(AngularVelocity.class).x() + "," +
                data.value(AngularVelocity.class).y() + "," +
                data.value(AngularVelocity.class).z() + "\n";
        getInstance().gyroscopeWriter.write(value);
    };

    private static Subscriber STEP_COUNTING_HANDLER = (Data data, Object... env) -> {
        String value = data.timestamp().getTimeInMillis() + "\n";
        getInstance().stepWriter.write(value);
    };

Since I'm using my own data writer object to write data to my mobile phone, I'm not passing any object into subcriber, so I guess I don't have to "setEvironment" before downloading data, right?

It works well if I don't call "deserializeBoard()".


Btw, these are my serialize and deserialize functions:

    /**
     * Serializes the current board into a file locally (identified using the mac address of the device)
     * to be restored when getting data from the device
     */
    public void serializeBoard() {
        File fileDir = new File(Environment.getExternalStorageDirectory().getAbsolutePath(), "mobilityData");
        if (!fileDir.exists()) {
            if (!fileDir.mkdirs())// create root directory
                Log.i(TAG, "serializeBoard: Failed to create data folder...");
        }
        try {
            File serializeFile = new File(Environment.getExternalStorageDirectory().getAbsolutePath()
                    + File.separator
                    + "mobilityData"
                    + File.separator
                    + board.getMacAddress());
            if (!serializeFile.createNewFile())
                Log.i(TAG, "serializeBoard: Failed to create serializeFile...");
            OutputStream writer = new FileOutputStream(serializeFile, false);
            board.serialize(writer);
            writer.close();
            Log.i(TAG, "Serialized: " + board.getMacAddress());
        } catch (IOException e) {
            Log.i(TAG, "Write failed for: " + board.getMacAddress() + " " + e.toString());
            e.printStackTrace();
        }
    }

    /**
     * Deserializes a board that is already stored on the device
     */
    public void deserializeBoard() {
        try {
            File serializeFile =
                    new File(Environment.getExternalStorageDirectory().getAbsolutePath()
                            + File.separator
                            + "mobilityData"
                            + File.separator
                            + board.getMacAddress());
            if (serializeFile.exists()) {
                InputStream reader = new FileInputStream(serializeFile);
                board.deserialize(reader);
                reader.close();
                if (!serializeFile.delete())
                    Log.i(TAG, "deserializeBoard: Failed to delete serializedFile...");
                Log.i(TAG, "Deserialized: " + board.getMacAddress());
            }
            else {
                mainActivity.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(mainActivity, "Cannot find serializedBoardFile for: " + board.getMacAddress(), Toast.LENGTH_LONG).show();
                    }
                });
            }
        } catch (IOException | ClassNotFoundException e) {
            Log.i(TAG, "Failed to read: " + board.getMacAddress() + " " + e.toString());
        }
    }

When I start collecting data, it doesn't show the progress as logs, seems like "receivedUpdate(long nEntriesLeft, long totalEntries)" is never called. And after a few seconds, this log will show up:

W/metawear: Log download finished but no Task object to complete

After that, I checked the storage of my phone, I found the data file (.csv) is right there, it means the data collection was successful. But it never disconnect with the board and my writer streams were not closed. So I think "continueWithTask()" function was not called.

Anyways, I just have two questions:
1. Why it doesn't update the downloading progress?
2. Why the continueWithTask() is not called?

I appreciate any help!




Thanks,
Tianyuan

Comments

  • edited November 2019

    Deserialize the boaed state first, then acquire references to the modules.

    Your logging module, at the download part, is referring to the older object.

  • Hi Eric,

    Thank you so much for your help, I had been stuck here for a few days, it works right now after following your instruction.

Sign In or Register to comment.