Clock synchronization


I have an app that connects to metawear device,
starts sensors and logger, disconnects, and moves on to another device
to do the same. It later connects to them one by one again to download
I sometimes find that the base timestamp on the log
captures is incorrect (for example dated a week earlier than the capture
actually started), but it actually has the data from the last capture: so correct data, incorrect timestamp.

From another discussion I understand that it is the android API which sets the base timestamp.

you have any idea how I might be ending up with an outdated timestamp?
When exactly does the android API store the timestamp? How does the
timestamps get synchronized if there are old logs in the flash that were
not retrieved (but will be retrieved next time I do a download)?

And how does this work with the new anonymous routes (I have not yet tested this feature). If logs can be retrieved from a different Android device, then surely the base timestamp is stored in the metawear board.

Metawear android SDK: 3.2.2
Firmware version 1.3.3/1.3.6

Thank you,


  • This thread should address your questions:

    Anonymous routes are somewhat limited in that the board cannot lose power if the data is being retrieved by another device.
  • Thank you Eric. I had already read that thread, it is from where I understood that the timestamp is stored in the API and not in the sensor device.

    However, I would like to understand which is the event/API call that triggers this timestamp storage. Because for some reason this is not always happening in my case, and it is using a week old timestamp.

    And also how this works when there are old logs in the board.

    In my case, the board does not lose power.
  • Please see my post from that thread (2nd post):

    I should rephrase "power off" to "resetting".

    In your tests, are all timestamps incorrect and offset by the same amount, or are only some incorrect and others are correct?

    How long ago is "old logs"?  Any data within 2 months, assuming the board has not been reset, should have the correct timestamps.
  • The question is, when you say "the API will query the current elapsed time reference point from the device", what is the reference point, when and how is it taken in the API.

    When I say old logs I mean day old logs. The device was neither powered off, nor resetted.

    The timestamps are all incorrect by the same amount, as if the base epoch used is incorrect.

    It looks like my issue is solved. It is somehow related to serialization, but I don't know exactly how. In any case, if possible, could you explain about the reference point of the timestamp for future reference?

    Thank you,
  • edited February 2018
    Eric said:

    Please provide some data that illustrates this timestamp issue you are seeing.

    There is no real time clock on the device.  It does know how much time has elapsed and relies on the the host device to recalculate timestamps.  When connection is established, the API will query the current elapsed time reference point from the device.
    These questions are addressed in my previously linked post, quoted above. Please read my post in its entirety.

    I'm not going to explain in further detail how timestamp works. You can look through the API implementation if you want specifics but they do not affect your usage of the API (which is the point of having an API).
  • Hello! I ran into the same issue but was unable to reproduce it.

    I have three MetaMotion C devices and all are logging data. Two of the sensors produced data with correct timestamps. The third device produced data with a timestamps that were offset by -57,123 seconds (which is the time I finished testing the night before).

    The sequence was:

    1. connectAsync successfully to all devices
    2. add routes and start loggers/streams for accelerometer and gyro on all devices
    3. disconnectAsync successfully to all devices
    4. wait ~30 seconds
    5. connectAsync successfully to all devices
    6. stop loggers/streams on all devices
    7. for each device, add routes, download data
    8. disconnectAsync successfully

    I did this entire sequence three times and on the third run, the logger for the first device had incorrect timestamps.

    Decided to see what's actually going on here:

    From the code in LoggingImpl class, it looks like we have three data types and four variables:

    a "resetUid" is presumably an identifier generated on the sensor board which marks a new logging session (so we get a new value after calling logging.clearEntries() and disconnecting)
    a "tick" is a presumably generated by the board whose value is auto-incremented in a fixed period (LoggingImpl.TICK_TIME_STEP milliseconds)
    a "TimeReference" is a tuple that binds a resetUid to a tick value and the system's time

    rollbackTimestamps - a map from resetUid to tick (looks like this is used both to preserve offsets when a disconnect occurs during download and to ensure we don't re-process the same data on a re-download)
    logReferenceTicks - a map from resetUid to a valid TimeReference object
    latestReference - the last TimeReference seen
    lastTimestamp - a map from resetUid to the last tick sent from the board for this resetUid

    On connectAsync (line 734), we call logger.queryTime:

    • LoggingImpl sends a "TIME" read request to the board
    • the board returns with a tick and a resetUid
    • if we don't have any rollbackTimestamps registered, then create a TimeReference marking that resetUid and tick to the current system time
    • update logReferenceTicks if the resetUid is valid (not -1)

    Later, when we receive an event (READOUT_NOTIFY):

    • The event includes a resetUid and a tick
    • First, obtain a TimeReference for the resetUid (using the latestReference if none is registered)
    • Next, we calculate the offset, the last tick seen, and the reference's starting tick value
    • We then update both the calendar and the tick in the TimeReference object
    • Then clone the calendar and return it

    1. Could it be that the board produced a resetUid value which was seen by the app the day before?
    2. Mutability of TimeReference object
    - Why not just store the calendar time and starting tick once and calculate all your offsets based on those?
    - Is it possible you have a race condition in here? Is that responseHandler callback on line 279 ever invoked concurrently?
    3. Usage of legacy Calendar class
    - I assume there's a reason for this, e.g. backwards compatibility but there's which provides backwards compatible immutable DateTime objects
    - that Calendar.clone call forces an object allocation per event, is this really necessary as opposed to just tracking raw timestamps instead? I'll assume benchmarks show this isn't causing memory/perf issues ...

  • edited March 2018
    1) Possible but resetUid does not change unless the board reboots   

    2) It doesn't matter if time references change; everything is relative offsets from a fixed point in time.  However, the reference points probably should not change while the board is actively logging.  

    No, there is no race condition.

    3) Does that library offer any features that is required by the current API implementation?  

    A copy is made so users don't modify the original reference  

  • Ok! Will update thread if I reproduce again :)

    I wouldn't say it's "required", but Calendar class has been deprecated in favor of the newer Date, DateTime, etc classes in java.time package since JDK 8 release back in 2014. See this link and this one.

    I'm not opposing a copy, but in general it's more expensive to copy an object than a long.

    Thanks for the response!

This discussion has been closed.