Memory Leak ? in my code for asset Tracker

I have been working on this project for quite some time , I have multiple versions to track vehicles. this one was more geared up toward keeping up with an hour meter on a piece of equipment and keeping up location if the equipment is being transported ( I figure it wont move faster than 15MPH on its own). after loading the firmware the device seems to work as expected for a few days then the mph will get stuck at 5.31 mph. after getting stuck at the 5.31 it doesnt send the Hour Meter information, but it will still (sometimes) allow you to “ping” the unit via the gpsPublish() function. the health meter through the console seems to still be communicating with the unit as well, but the unit wont allow itself to be flashed without an reset sometimes as well. which leads me to wonder if my program is what is hanging up the hardware. the only thing I omitted from the running program is my device name device name = { } , just omit the curlys and enter the name. I do plan to change the function to keep the publish out of the function , I just haven’t don’t that yet. I know the publish strings are not common Json, I just figure the less information I send about the data allows the space to send more actual data and let the Webhook and the .php take care of the sending and parsing. thank you for all your help !!


#include <AssetTracker.h>
#include <PublishManager.h>
SYSTEM_THREAD(ENABLED);


PublishManager<10,10,120> publishManager;
//change per user and device
const char* devicepre = "{insertNameHere}";
int unitId = 4;
int hourMeter = 15; // in minutes 
//change name for each custom
//String savedData[20]; // to make an array when data cant be sent out 
//int SD = 0; // SD for  Saved Data
//int transmittingData = 1;
int lastPubSpeed = 3;
//unsigned long pubOffset = 0;
//unsigned long offsetMark = 0;
//int increaseTime = 0;
unsigned long millisNow = 0;
int beepPin = A0;
int ignitionPin = A1;
//int pulseLock = D1;
//int pulseUnlock = D0;

//bool panicNow = FALSE;
bool meterNow = FALSE;
unsigned long meterStart = 0;
unsigned long meterFinish = 0;
float meterTimeMin = 0;
float meterMinSave = 0;

int led = D7;
// Used to keep track of the last time we published data
unsigned long lastPublish = 0;
unsigned long motion = 0;
float speedKnots = 0;
float speedMph = 0;
float lat = 0;
float lon = 0;
// How many minutes minimum between publishes? 10+ recommended!
int delayMinutes = 2;
int longDelay = 4*60;
// Threshold to trigger a publish
// 9000 is VERY sensitive, 12000 will still detect small bumps
// Creating an AssetTracker named 't' for us to reference
AssetTracker t = AssetTracker();

// A FuelGauge named 'fuel' for checking on the battery state
FuelGauge fuel;
int accelThreshold = 9900; // 9000 verry secenitive
bool secureVeh = FALSE;
bool secureNot = FALSE;
//bool detCRASH = FALSE;
//bool CRASHnot = FALSE;
//int CRASHthresh = 35500;

int devMonth;
int devYear;
int devDay;
int devHour;
int devMin;
int devSec;


void setup() {
    // Enable the GPS module. Defaults to off to save power.
   // Takes 1.5s or so because of delays.
   t.gpsOn();
   delay(500);
   Time.zone(-4);
    // 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("aThresh",accelThresholder);
   Particle.function("vSecure", secure);
   Particle.function("gps", gpsPublish);
 //  Particle.function("panicOff", offPanic);

// Changed from OUTPUT to INPUT , having issues with the HIGH setting causing the 
// door locks to hang in whatever posistion thry were in and disabling the buttons to lock and unlock
// hopefully this works , a INPUT setting should make the pin "float" 
 //pinMode(pulseLock,OUTPUT);
 //pinMode(pulseUnlock,OUTPUT);
 //digitalWrite(pulseLock,LOW);
// digitalWrite(pulseUnlock,LOW);

 
   
     // Sets up all the necessary AssetTracker bits
   t.begin();
   
   pinMode(beepPin,OUTPUT);
   pinMode(ignitionPin,INPUT_PULLDOWN);  // add pull down resistor and resistor voltage divider input will be positive
   pinMode(led,OUTPUT);
   digitalWrite(beepPin,LOW);
   
}
void loop() {
    // You'll need to run this every loop to capture the GPS output
  
   t.updateGPS();
   delay(100);
   publishManager.process();
   delay(100);
   
   if(Time.isDST() == TRUE && Time.getDSTOffset() == 0) {   Time.beginDST()  ;  }
   if(Time.isDST() == FALSE && Time.getDSTOffset() == 1) {   Time.endDST()  ;   }
  // Serial.println("Time.now");
   // Check if there's been a big acceleration
if(t.readXYZmagnitude() > accelThreshold)  {
    delayMinutes = 2 ;
    motion = millis();
    }
/*if(panicNow == FALSE && digitalRead(panicPin) == LOW) {
   panicNow = TRUE; } */

millisNow = millis();
if(millisNow - motion >= 1.5*60*1000)  {
   // after 1.5 minutes publish will run gps data every 4 hrs
   delayMinutes = longDelay;
   //pubOffset = 0;
   secureNot = FALSE; 
  // CRASHnot = FALSE;
    // digitalWrite(led,LOW);
   }
 speedKnots = t.getSpeed(); 
 speedMph = speedKnots*1.151;
 if(speedMph < 2.2) {  speedMph = 0; }
     
// check for idle time start
if(meterNow == FALSE && digitalRead(ignitionPin) == HIGH) { 
   meterNow = TRUE;
   meterStart = millis();
   }
// check for idle time stop
if(meterNow == TRUE && digitalRead(ignitionPin) == LOW) { 
   millisNow = millis();
   meterFinish = millisNow - meterStart;
   meterTimeMin = (meterFinish / (60*1000));
   meterNow = FALSE;
  // meterFinish = 0;
           }
   millisNow = millis();
if(meterNow == TRUE && ((millisNow - meterStart) > (hourMeter * 60*1000)) && digitalRead(ignitionPin)== HIGH) { 
   millisNow = millis();
   meterFinish = millisNow - meterStart;
   meterTimeMin = (meterFinish / (60*1000));
   meterStart = millis();
  // meterFinish = 0;
                  }
   

millisNow = millis();
 if(millisNow - lastPublish >= delayMinutes*60*1000) {
     if((lastPubSpeed != 0) || (speedMph >= 15) || (delayMinutes == longDelay)) {
       
       if(t.gpsFix()) {
           
                 lat = (t.readLatDeg());
                 lon = (t.readLonDeg());
                 speedKnots = t.getSpeed(); 
                 speedMph = speedKnots*1.151;
                 if(speedMph < 2.5) { 
                 speedMph = 0; }
                 
                 devHour = Time.hour();
                 devMin = Time.minute();
                 devSec = Time.second();
                 devYear = Time.year();
                 devMonth = Time.month();
                 devDay = Time.day();
               
               char data[256];
               snprintf(data, sizeof(data), "{%f,%f,%.2f,%.2f,%s,%i,%i,%i,%i,%i,%i,%i}", lat, lon, speedMph, fuel.getVCell(), devicepre , unitId, devHour, devMin, devSec, devYear, devMonth, devDay);
               //snprintf(data, sizeof(data), "{\"LAT\":%f,\"LON\":%f,\"MPH\":%.2f,\"BATT\":%.2f,\"DEVICEPRE\":%s,\"DEVICENUMBER\":%i}", lat, lon, speedMph, fuel.getVCell(), devicepre , unitId);
               publishManager.publish("CELL", data);
               lastPublish = millis();
               lastPubSpeed = speedMph;
              
                       } }  }
               

  millisNow = millis();                              
  if(secureVeh == TRUE && (t.readXYZmagnitude() > accelThreshold) && (millisNow - lastPublish >= 1*60*1000)) {
      if(t.gpsFix()) {
          if(secureNot == FALSE) {
               
                
                 lat = (t.readLatDeg());
                 lon = (t.readLonDeg());
                 speedKnots = t.getSpeed(); 
                 speedMph = speedKnots*1.151;
                 if(speedMph < 2) { 
                 speedMph = 0; }
                 
                 devHour = Time.hour();
                 devMin = Time.minute();
                 devSec = Time.second();
                 devYear = Time.year();
                 devMonth = Time.month();
                 devDay = Time.day();
            
               char data[256];
               snprintf(data, sizeof(data), "{%f,%f,%.2f,%.2f,%s,%i,%i,%i,%i,%i,%i,%i}", lat, lon, speedMph, fuel.getVCell(), devicepre , unitId, devHour, devMin, devSec, devYear, devMonth, devDay);
               //snprintf(data, sizeof(data), "{\"LAT\":%f,\"LON\":%f,\"MPH\":%.2f,\"BATT\":%.2f,\"DEVICEPRE\":%s,\"DEVICENUMBER\":%i}", lat, lon, speedMph, fuel.getVCell(), devicepre , unitId);
               publishManager.publish("ALARM2", data);
               lastPublish = millis();
               lastPubSpeed = speedMph;
              // pubOffset = 0;
              // increaseTime = 0;
               secureNot = TRUE;
              // CRASHnot = FALSE;
                       }   }  }    
  millisNow = millis();  
  speedKnots = t.getSpeed();
  speedMph = speedKnots*1.151;
  if(speedMph < 2.5) { speedMph = 0; }
  
    if(secureVeh == TRUE && (speedMph >= 5) && (millisNow - lastPublish >= 1*60*1000)) {
     
       if(t.gpsFix()) {
           
              
                 lat = (t.readLatDeg());
                 lon = (t.readLonDeg());
                 speedKnots = t.getSpeed(); 
                 speedMph = speedKnots*1.151;
                 if(speedMph < 2.5) { 
                 speedMph = 0; }
                 
                 devHour = Time.hour();
                 devMin = Time.minute();
                 devSec = Time.second();
                 devYear = Time.year();
                 devMonth = Time.month();
                 devDay = Time.day();
                 
               char data[256];
               snprintf(data, sizeof(data), "{%f,%f,%.2f,%.2f,%s,%i,%i,%i,%i,%i,%i,%i}", lat, lon, speedMph, fuel.getVCell(), devicepre , unitId, devHour, devMin, devSec, devYear, devMonth, devDay);
              // snprintf(data, sizeof(data), "{\"LAT\":%f,\"LON\":%f,\"MPH\":%.2f,\"BATT\":%.2f,\"DEVICEPRE\":%s,\"DEVICENUMBER\":%i}", lat, lon, speedMph, fuel.getVCell(), devicepre , unitId);
               publishManager.publish("ALARM2", data);
               lastPublish = millis();
               lastPubSpeed = speedMph;
              // pubOffset = 0;
              // increaseTime = 0;
               secureNot = TRUE;
              // CRASHnot = FALSE;
                        }   }                           
                       
                       

// system reset after 7 days of operation, if not currently sensing motion and reporting every 2 min
// needed because data became ?static? ?unreliable? after logging for 13 days, unit may have been running for 14+ days
millisNow = millis();
if((millisNow > 14*24*60*60*1000) && delayMinutes == longDelay && secureVeh == FALSE) {
           System.reset(); }
if((millisNow > 32*24*60*60*1000) && speedMph == 0 && lastPubSpeed == 0 && secureVeh == FALSE) {
           System.reset(); }
// panic button check 
/*if(panicNow == TRUE && digitalRead(panicPin) == LOW)  { 
   panicNow == FALSE; }*/
   
if(meterTimeMin != 0) {
   meterMinSave = meterMinSave + meterTimeMin;
       meterTimeMin = 0;
           
       if(t.gpsFix()) { 
            lat = (t.readLatDeg());
                 lon = (t.readLonDeg());
                 speedKnots = t.getSpeed(); 
                 speedMph = speedKnots*1.151;
                 if(speedMph < 2) { 
                 speedMph = 0; }
                 devHour = Time.hour();
                 devMin = Time.minute();
                 devSec = Time.second();
                 devYear = Time.year();
                 devMonth = Time.month();
                 devDay = Time.day();
            
               char data[256];
               snprintf(data, sizeof(data), "{%f,%f,%.2f,%.2f,%s,%i,%i,%i,%i,%i,%i,%i}", lat, lon, meterMinSave, fuel.getVCell(), devicepre , unitId, devHour, devMin, devSec, devYear, devMonth, devDay);
              // snprintf(data, sizeof(data), "{\"LAT\":%f,\"LON\":%f,\"IDLE\":%.2f,\"DEVICEPRE\":%s,\"DEVICENUMBER\":%i}", lat, lon, meterTimeMin, devicepre , unitId);
               publishManager.publish("METER", data);
               //lastPubSpeed = speedMph;
               lastPublish = millis();
              // pubOffset = 0;
              // increaseTime = 0;
               meterMinSave = 0;  
              // CRASHnot = FALSE;
                                 }  }
                                
   

// end
}           

 
int secure(String command) {
   if(command == "Lock") {
   accelThreshold = 9900;
   secureVeh = TRUE;
   digitalWrite(beepPin,HIGH);
   // code here to Lock doors
  // pinMode(pulseLock,OUTPUT);
  // digitalWrite(pulseLock,HIGH);
   delay(400);
   digitalWrite(beepPin,LOW); 
  // pinMode(pulseLock,INPUT);
   
   return 1;
   }
   else if(command == "Unlock") {
       accelThreshold = 9900;
       secureVeh = FALSE;
      // digitalWrite(led,LOW);
       // code here to unlock door
      // pinMode(pulseUnlock,OUTPUT);
     digitalWrite(beepPin,HIGH);
       delay(400);
       digitalWrite(beepPin,LOW); 
      // pinMode(pulseUnlock,INPUT);
       delay(250);
       //pinMode(pulseUnlock,OUTPUT);
       digitalWrite(beepPin,HIGH);
       delay(400); 
       digitalWrite(beepPin,LOW);
  
      // pinMode(pulseUnlock,INPUT);
       
       
   return 0;
   }
   }


int gpsPublish(String command) {
   if (t.gpsFix()) {
       lat = (t.readLatDeg());
       lon = (t.readLonDeg());
       speedKnots = t.getSpeed(); 
       speedMph = speedKnots*1.151;
       if(speedMph < 2) { 
       speedMph = 0; }
    
     char data[256];
      snprintf(data, sizeof(data), " %f, %f, %.2f, %.2f, {insertNameHere} : %i " , lat, lon, speedMph, fuel.getVCell(), unitId);
     Particle.publish("GPS", data, PRIVATE);

       return 1;
   } else {
     return 0;
   }
}


Didn’t study the code to much, but are you sure your char data will always be <256 ?
print the data strlen after your snprintf’s to see how close you are to the wall.

yes , the data doesn’t change by much. its around 63 chars each time.

System firmware version is what? I’ve watched 0.7.0 (can’t speak to 0.8.X however) consume and fragment memory space over time. Reverting to 0.6.3 and all is well. Also cleaned up the soft AP issues we were bumping into.

You may want to check on the device health / diagnostics after you have them running for a bit.

I’m using 0.8.0-rc.4 to try out the health checks. I’ve been using the same firmware for some different versions for testing and they seem to work well. I have the same reset after so many days programmed to them as well. the devices all seem to throw an error for weak signal even if they are in a good signal area. I have noticed the GPS signal tends to start drifting before it becomes unusable. I can still run the function to locate , but the function to secure the equipment will not produce the audible tone from the piezo hooked up to the device. this is on a bobcat which limits the “clear view of the sky”. could there be an issue with the GPS loosing a locked signal or too weak of a signal and that causing issues with the program running?? I thought about adding an external antenna, but trying to keep the unit as hidden as possible.