Dear Particle Team
I love my Electron (SARA-U270) on the Asset Tracker (v 2.0.1) and would like to track things like vehicles or people.
The idea is to publish (Particle.publish) a location update every 5 seconds and forward that event to an own backend via Particle Cloud’s webhook.
To improve the GPS positioning, I attached the external Adafruit antenna and for debugging a single chainable LED to the Grove port.
I use my own SIM card, set the carrier’s APN and use a keepAlive of 30s.
Unfortunately, I see that the electron quite often loses connectivity to the Particle Cloud, i.e. the electron’s LED is blinking cyan (not green).
It’s not breathing but also not that rapidly blinking like I see it just before a cloud connection is established. If I then restart the electron manually (power off/on), the setup works and the electron is connected again to the cloud.
With that in mind, I checked out blessed @rickkas7 Github libraries and tried to aggressively restart the electron if anything is not working as expected.
However, this doesn’t solve the issues and I would like to know whether there is an even quicker and more reliable way to reconnect to the cloud? Or is my code doing something stupid and I could improve it there?
I appreciate any feedback, thank you!
Please find below my used code:
#include <AssetTrackerRK.h>
#include <PublishQueueAsyncRK.h>
#include <electronsample.h>
#include "cellular_hal.h"
#include "Particle.h"
#include "AppWatchdogWrapper.h"
#include "ConnectionCheck.h"
#include "ConnectionEvents.h"
#include "SessionCheck.h"
#include <Grove_ChainableLED.h>
STARTUP(cellular_credentials_set("gprs.swisscom.ch", "", "", NULL));
SYSTEM_THREAD(ENABLED);
SYSTEM_MODE(SEMI_AUTOMATIC);
retained uint8_t publishQueueRetainedBuffer[2048];
PublishQueueAsync publishQueue(publishQueueRetainedBuffer, sizeof(publishQueueRetainedBuffer));
ConnectionEvents connectionEvents("connEventStats");
SessionCheck sessionCheck(300);
ConnectionCheck connectionCheck;
AppWatchdogWrapper watchdog(60000);
int transmittingData = 1;
long lastPublish = 0;
float minSpeed = 1.7; // in knots
int delayMilliSeconds = 5000;
ChainableLED leds(D1, D0, 1);
AssetTracker t = AssetTracker();
FuelGauge fuel;
void setup() {
// t.begin();
t.gpsOn();
t.startThreadedMode();
t.antennaExternal();
Serial.begin(9600);
connectionEvents.setup();
sessionCheck.setup();
connectionCheck.setup();
publishQueue.setup();
Particle.keepAlive(60);
Particle.connect();
leds.init();
if (waitUntil(Particle.connected)) {
Particle.function("tmode", transmitMode);
Particle.function("minSpeed", setMinSpeed);
Particle.function("delaySeconds", setDelayMilliSeconds);
Particle.function("batt", batteryStatus);
Particle.function("gps", gpsPublish);
Particle.function("jsonLocation", publishJsonLocation);
Particle.publish("startup", "electron", PRIVATE);
}
Serial.println("setup completed");
}
void loop() {
sessionCheck.loop();
connectionCheck.loop();
connectionEvents.loop();
colorLed();
if (
transmittingData &&
t.getFixQuality() &&
t.getSatellites() > 4 &&
(lastPublish == 0 || (millis()-lastPublish > delayMilliSeconds && t.getSpeed() > minSpeed))
) {
// if (waitFor(Particle.connected, 2000)) {
lastPublish = millis();
publishJsonLocation("");
// }
}
}
void colorLed() {
if (t.getSatellites() > 4) {
leds.setColorRGB(0, 0, 255, 0);
} else if (t.getSatellites() > 0) {
leds.setColorRGB(0, 0, 0, 255);
} else {
leds.setColorRGB(0, 255, 0, 0);
}
}
long setDelayMilliSeconds(String command) {
delayMilliSeconds = atol(command);
return delayMilliSeconds;
}
int transmitMode(String command) {
transmittingData = atoi(command);
return transmittingData;
}
float setMinSpeed(String command) {
minSpeed = atof(command);
return minSpeed;
}
int gpsPublish(String command) {
if (t.getFixQuality()) {
Particle.publish("G", t.readLatLon(), 60, PRIVATE);
}
return t.getSatellites();
}
int publishJsonLocation(String command) {
publishQueue.publish("location", String::format("{\"lat\":%f, \"lng\":%f, \"speed\":%.3f, \"satellites\":%d, \"timestamp\": \"20%d-%02d-%02dT%02d:%02d:%02d.%03dZ\", \"rssiStrength\":%.2f, \"rssiQuality\":%.2f, \"gpsFix\":%d, \"gpsFixQuality\":%d}",
t.readLatDeg(),
t.readLonDeg(),
t.getSpeed(),
t.getSatellites(),
t.getYear(), t.getMonth(), t.getDay(), t.getHour(), t.getMinute(), t.getSeconds(), t.getMilliseconds(),
Cellular.RSSI().getStrength(),
Cellular.RSSI().getQuality(),
t.gpsFix(),
t.getFixQuality()
), PRIVATE);
return 1;
}
int batteryStatus(String command){
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;}
}