Particle.syncTime() not providing expected results

Hi all,

I have a Particle Electron running with a setup() that contains

Particle.syncTime();
Time.setFormat(TIME_FORMAT_ISO8601_FULL)

In the loop I then run a number of Particle.Publish() commands, which send a string of sensory data, including the timestamp.

The timestamp is generated like this: String tStamp = Time.format(Time.now());

Occasionally, the timestamp generated seems to be Epoch, instead of the current time - am I missing something obvious here?

An example of an incorrect timestamp:

{"timestamp":"1969-12-01 01:00:31"}

Nearly always it returns the current ISO8601 date time, however this happens very sporadically and is not something I’ve found to be repeatable.

Thanks.

You are not clear what else you are doing with the Electron. The timestamp going to 1969 suggests the RTC is resetting since the unix epoch time is 1970 start?

Are you testing using Time.isValid() anywhere before calling Time.now() or in fact using time functions? This is a very good thing to do because if you are offline - which is likely with the Electron then presumably you do not want the application to block trying to connect.

Particle.syncTime() is asynchronous. It won’t complete until some time in the future. You can call Particle.syncTimeDone() or Time.isValid() to find out it it’s done.

I think this is likely the problem then, as I wasn’t aware that Particle.syncTime() was an async function. From your experience, is this likely to take seconds or minutes to complete? I’d be tempted to insert a while(!Particle.syncTimeDone()) function in setup() so that the prog halts until the time is valid.

Secondly, is using Particle.syncTime() once in setup() recommended or would you call this before the main loop of Particle.Publish() commands?

Thanks all. @armor your comments are also inline with this, so thanks.

Rick is expert so I would defer to his greater knowledge. For what it is worth I have the following function called from loop(). I always test for Time.isValid() before using Time.now().

    if (Particle.connected() && param.opMode == D_CONNECTED)                    //Only time sync when in connected operation mode and Cloud connected
    {
        time_t lastSyncTimestamp;
        unsigned long lastSync = Particle.timeSyncedLast(lastSyncTimestamp);
        if (millis() - lastSync >= ONE_DAY_MILLIS)                              //More than one day since last time sync
        {
            unsigned long cur = millis();
            Particle.syncTime();                                                //Request time synchronization from Particle Device Cloud
            waitUntil(Particle.syncTimeDone);                                   //Wait until Photon receives time from Particle Device Cloud (or connection to Particle Device Cloud is lost)
            if (Particle.timeSyncedLast() >= cur)                               //Check if synchronized successfully
            {
                initBacklog(); //this is daily event log clean up
            }
        }
    }
2 Likes

Particle.syncTime is more or less immediate - as long as the cloud connection is already up.

I believe it could block for a while waiting for the cloud connection to be established. It probably makes sense to do what Armor did and wait for Particle.connected() then try to do the syncTime.

1 Like

Hmm… this worked ok on a Photon, but Particle.syncTimeDone isn’t working on an Electron: class CloudClass has no member named 'syncTimeDone'

Is your Electron running system firmware 0.6.1 or later? That’s the version it was added in. It’s not conditionally included by platform:

Ah that would explain it. The Particle Electron is running 0.4.8 (it’s around 2 years old I believe). Remotely deployed on a site so I can’t remotely update the firmware :thinking:

You can remotely upgrade the system firmware, it just uses about 270K of your data allowance to do that. However, since your Electron has 0.4.8 it has to upgrade to 0.5.3 first, then to the eventual version, so it’s twice that to remotely upgrade an Electron.

The upgrade can be done automatically by flashing user firmware that requires a newer Device OS version.

It can also be done manually by flashing the system parts. However, make sure if you’re upgrading from 0.4.8 to anything 0.6.0 or later (including 1.0.0), you do the intermediate upgrade to 0.5.3 (or 0.5.4 or 0.5.5). The reason is that 0.6.0 and later have 3 system parts vs. 2 system parts in older versions. Those 0.5.x versions are the only ones that can successfully navigate the switch from 2 to 3 parts.

1 Like

Hi all, apologies to reopen this thread. I thought I’d solved the issue but it’s come back again.

I used @armor’s code as inspiration and wrote a function that I call as the first line in setup(), which looks like this:

void syncTimeFromCloud() {
  if (Particle.connected()) {                   //Only time sync when in connected operation mode and Cloud connected
        Particle.syncTime();                                                //Request time synchronization from Particle Device Cloud
        waitUntil(Particle.syncTimeDone);                                   //Wait until Photon receives time from Particle Device Cloud (or connection to Particle Device Cloud is lost)
    }

But this didn’t work, as I recently got another incorrect time. I could remote update the firmware as @rickkas7 suggested but this is really my last resort, as it’s a remote device and would be hard to access if it doesn’t work.

Perhaps I do need to implement some Time.isValid() logic before I use Time.now().

Sorry to hear that time sync isn’t working. Could you help us in replying to this by confirming a couple of things? Device? Device OS?

Do you have SYSTEM_THREAD(ENABLED);?
How are you operating the cloud connection - default / AUTOMATIC I assume?

When the device first connects to the cloud (at the startup if AUTOMATIC) the time will be sync’d. Remember that between the power on and the cloud connection and sync there will be a variable amount of time where the time is not set/valid. Thus, you always need to check Time.isValid() before using Time.now() for this reason.

The syncTimeFromCloud function is meant to be called once every 24 hours after initial startup to ensure the time stays sync’d. It is not required to be called in setup().

Hi @armor

It’s on 0.4.8 (Electron). I don’t have SYSTEM_THREAD(ENABLED); - should this be in place or is it enabled by default?

It’s on the default cloud connection. Looks like I need to use Time.isValid() and implement syncTimeFromCloud() every 24 hours too.

I am sure there is an argument for use without SYSTEM_THREAD(ENABLED) - I do everything with this set.

I think you are due an upgrade to 1.0.1?