Missing Publish with 5min interval

I am trying to publish some GPS data but having issues with the interval time. I have reproduce it using the example “GPS_BASIC” code.

I am setting the delayMinutes to 5 and have created a web hook. When I look at the web hook log, it is only triggered every 10mins (almost like every second one is missing).

Has anyone else experienced this? Code and web hook log below

Code:

#include "AssetTracker.h"

// Set whether you want the device to publish data to the internet by default here.
// 1 will Particle.publish AND Serial.print, 0 will just Serial.print
// Extremely useful for saving data while developing close enough to have a cable plugged in.
// You can also change this remotely using the Particle.function "tmode" defined in setup()
int transmittingData = 1;

// Used to keep track of the last time we published data
long lastPublish = 0;

// How many minutes between publishes? 10+ recommended for long-time continuous publishing!
int delayMinutes = 5;

// Creating an AssetTracker named 't' for us to reference
AssetTracker t = AssetTracker();

// A FuelGauge named 'fuel' for checking on the battery state
FuelGauge fuel;

// setup() and loop() are both required. setup() runs once when the device starts
// and is used for registering functions and variables and initializing things
void setup() {
    // Sets up all the necessary AssetTracker bits
    t.begin();
    
    // Enable the GPS module. Defaults to off to save power. 
    // Takes 1.5s or so because of delays.
    t.gpsOn();
    
    // Opens up a Serial port so you can listen over USB
    Serial.begin(9600);
    
    // These three functions are useful for remote diagnostics. Read more below.
    Particle.function("tmode", transmitMode);
    Particle.function("batt", batteryStatus);
    Particle.function("gps", gpsPublish);
}

// loop() runs continuously
void loop() {
    // You'll need to run this every loop to capture the GPS output
    t.updateGPS();

    // if the current time - the last time we published is greater than your set delay...
    if(millis()-lastPublish > delayMinutes*60*1000){
        // Remember when we published
        lastPublish = millis();
        
        //String pubAccel = String::format("%d,%d,%d",t.readX(),t.readY(),t.readZ());
        //Serial.println(pubAccel);
        //Particle.publish("A", pubAccel, 60, PRIVATE);
        
        // Dumps the full NMEA sentence to serial in case you're curious
        Serial.println(t.preNMEA());
        
        // GPS requires a "fix" on the satellites to give good data,
        // so we should only publish data if there's a fix
        if(t.gpsFix()){
            // Only publish if we're in transmittingData mode 1;
            if(transmittingData){
                // Short publish names save data!
                Particle.publish("G", t.readLatLon(), 60, PRIVATE);
            }
            // but always report the data over serial for local development
            Serial.println(t.readLatLon());
        }
    }
}

// Allows you to remotely change whether a device is publishing to the cloud
// or is only reporting data over Serial. Saves data when using only Serial!
// Change the default at the top of the code.
int transmitMode(String command){
    transmittingData = atoi(command);
    return 1;
}

// Actively ask for a GPS reading if you're impatient. Only publishes if there's
// a GPS fix, otherwise returns '0'
int gpsPublish(String command){
    if(t.gpsFix()){ 
        Particle.publish("G", t.readLatLon(), 60, PRIVATE);
        
        // uncomment next line if you want a manual publish to reset delay counter
        // lastPublish = millis();
        return 1;
    }
    else { return 0; }
}

// Lets you remotely check the battery status by calling the function "batt"
// Triggers a publish with the info (so subscribe or watch the dashboard)
// and also returns a '1' if there's >10% battery left and a '0' if below
int batteryStatus(String command){
    // Publish the battery voltage and percentage of battery remaining
    // if you want to be really efficient, just report one of these
    // the String::format("%f.2") part gives us a string to publish,
    // but with only 2 decimal points to save space
    Particle.publish("B", 
          "v:" + String::format("%.2f",fuel.getVCell()) + 
          ",c:" + String::format("%.2f",fuel.getSoC()),
          60, PRIVATE
    );
    // if there's more than 10% of the battery left, then return 1
    if(fuel.getSoC()>10){ return 1;} 
    // if you're running out of battery, return 0
    else { return 0;}
}

Web hook log

If I change the delayMinutes to 2 it works as expected

int delayMinutes = 2;

Web hook logs

What about your 2 Serial.print statements in loop. Are both of those printing at 10 minute intervals also?

After some more playing this evening I tried creating a simple script that just publishes every 5 minutes and could reproduce without any GPS or Accelerometer.

Eventually I figured out it is due to the SIM card I am using. I had swapped the Particle one for a another (Aldi Mobile Australia). As soon as I put the original Particle one back in it worked as expected.

I am unsure what would be causing this on another network. Aldi uses the same network as Particle so it worked without me setting a custom APN. Even when I explicitly set the APN the issue was still present. (note I was flashing the code OTA so the device was definitely connected)

Hopefully this helps someone else using a different SIM.

1 Like

You need to set Particle.keepAlive() in respect to your providers needs and make sure your device will be awake often enough to keep the connection alive.

1 Like

And to add to @ScruffR’s comment, it’s not because the provider is the same as the one used by Particle that the parameters will stay the same. These are negotiated agreements and will vary widely even on the same network!

2 Likes

I will try this using the Aldi Mobile SIM and report back. How come this isn’t required when using the Particle SIM?

Because the Particle SIMs are the default solution and hence the system already has the correct values set by default.

Adding Particle.keepAlive() has solved the problem, thanks for the help.

For reference if anyone is using an Electron in Australia. Aldi Mobile seems to be a very inexpensive network and ideal for the Electron. Pay as you got and credit lasts a full 12 months - https://www.aldimobile.com.au

Once adding Particle.keepAlive() it appears to be working great.

Thanks for reporting back :+1:
Can you also state what value will be the sweet spot between minimal data consuption and maximum reliability?