Hi @ScruffR,
quite many lines of code though.
#pragma SPARK_NO_PREPROCESSOR
#include "Particle.h"
#include "MQTT.h"
#include "device.h"
#include "cellular_hal.h"
SYSTEM_THREAD(ENABLED);
#if ( PLATFORM_ID == PLATFORM_ELECTRON_PRODUCTION )
STARTUP(cellular_credentials_set("bredband.tre.se", "", "", NULL));
//STARTUP(cellular_credentials_set("data.tre.se", "", "", NULL));
#endif
#define MQTT_TOPIC_SENSOR "iot-2/evt/data/fmt/json"
#define MQTT_TOPIC_STATUS "iot-2/evt/status/fmt/json"
#define MQTT_TOPIC_CMD "iot-2/cmd/+/fmt/json"
/*
* System defines
*/
#define EXT_SERIAL Serial1
#define MAXBUFFLENGTH 400
#define MQTT_KEEPALIVE 2 * 1000UL //Seconds
#define MQTT_CONN_TIME 1 * 1000UL //Seconds
#define CELL_CHECK_TIME 2 * 60000UL //Minutes
#define UNIT_STATUS_TIME 3 * 60000UL //Minutes
/*
* EEPROM address
*/
#define DIAGF_ADD 0
/*
* Debug defines
*/
#define _DIAG
//#define _DEBUG_MQTT
//#define _DEBUG_SERIAL
typedef struct ExtCom {
char buf1[MAXBUFFLENGTH];
char buf2[MAXBUFFLENGTH];
char *currBuf;
char *lastBuf;
byte bufIdx;
bool recvdflag;
} ExtCom;
enum DiagInfo {
RSTWD,
RSTRDY,
RSTCONN,
RSTMQTT
} DiagInfo;
#define DIAGRST 16
bool runSerialCmd = false;
long tMqttConn = 0, tMqttLoop = 0, tStatus = 0, tCellCk = 0;
ExtCom extCom;
int cnt = 0;
int diagFlags = 0;
//***** Function declaration *****
void mqttCallback(char* topic, byte* payload, unsigned int length);
void rstTimer();
void rstWd();
void rst( char rstType );
int diagFlagRst( String command );
//***** Class declaration *****
MQTT client(MS_PROXY, MQTT_PORT, mqttCallback);
Timer mqttReConnT( 90 * 1000UL, rstTimer, true );
// reset the system after 5 seconds if the application is unresponsive
ApplicationWatchdog wd( 5 * 60000UL, rstWd );
void rst( char rstType ) {
diagFlags |= 1UL << rstType;
EEPROM.put( DIAGF_ADD, diagFlags );
Particle.publish( "Rst unit", String(rstType) );
Particle.publish( "Diagnos flags", String(diagFlags) );
System.reset();
}
void rstTimer() {
rst( RSTMQTT );
}
void rstWd() {
rst( RSTWD );
}
int diagFlagRst( String command ) {
diagFlags = 0;
EEPROM.put( DIAGF_ADD, diagFlags );
return 0;
}
int reboot( String command ) {
Particle.publish( "reboot" );
System.reset();
return 0;
}
/*
* MQTT functions
*/
void mqttInit() {
// connect to the Mqtt broaker
client.connect( MQTT_CLIENT_ID, AUTHMETHOD, AUTHTOKEN );
// publish/subscribe
if ( client.isConnected() ) {
client.subscribe(MQTT_TOPIC_CMD);
#ifdef _DEBUG_MQTT
Serial.println("MQTT online");
#endif
return;
}
#ifdef _DEBUG_MQTT
Serial.println("MQTT offline");
#endif
}
void mqttCallback(char* topic, byte* payload, unsigned int length) {
char temp[100];
char p[length + 1];
memcpy(p, payload, length);
p[length] = NULL;
String message(p);
String msgTopic(topic);
#ifdef _DEBUG_MQTT
sprintf( temp, "MQTT Recieve: %s : %s", topic, p );
Serial.println( temp );
#endif
}
void serialEvent1() {
char c = 0;
int cnt = 0;
/*
* Data is JSON formated like this:
*
* $ in the begining, indicates new serial string,
* '\n' newline in the end indicate then end of the string.
*
* Example:
* sprintf(serialBuf, "&{\"seq_num\":\"%d\"}", packetnum);
* Serial1.println(serialBuf);
*/
// read data from serial
while ( EXT_SERIAL.available() ) {
c = EXT_SERIAL.read();
if (c == '&') {
extCom.currBuf[extCom.bufIdx] = 0;
extCom.bufIdx = 0;
}
else if (c == '\n') {
// extCom.currBuf[extCom.bufIdx] = c;
if (extCom.currBuf == extCom.buf1) {
extCom.currBuf = extCom.buf2;
extCom.lastBuf = extCom.buf1;
} else {
extCom.currBuf = extCom.buf1;
extCom.lastBuf = extCom.buf2;
}
extCom.recvdflag = true;
break;
}
else if (c == '\r') {
//Don't add this char to buffer
}
else {
extCom.currBuf[extCom.bufIdx++] = c;
}
if (extCom.bufIdx >= MAXBUFFLENGTH) {
extCom.bufIdx = MAXBUFFLENGTH-1;
}
}
}
/*
* System functions
*/
void setup() {
//Used for external unit communication
EXT_SERIAL.begin(19200);
//Used for debug
Serial.begin(19200);
extCom.currBuf = extCom.buf1;
extCom.lastBuf = extCom.buf2;
extCom.bufIdx = 0;
extCom.recvdflag = false;
#ifdef _DIAG
//***** Register cloud function/ variables
Particle.variable( "DiagFlags", diagFlags );
Particle.function( "DiagFlagsClr", diagFlagRst );
Particle.function( "UnitReboot", reboot );
// Particle.keepAlive(10); // send a ping every 10 sec
EEPROM.get( DIAGF_ADD, diagFlags );
// Erased EEPROM has value 0xFF, need to be set to 0x00 first time.
// DIAGRST could also be used to reset the DiagFlags
if ( diagFlags & DIAGRST ) {
diagFlags = 0;
EEPROM.put( DIAGF_ADD, diagFlags );
Particle.publish( "Diagnos erase" );
}
#if ( PLATFORM_ID == PLATFORM_ELECTRON_PRODUCTION )
if ( !waitFor( Cellular.ready, 60000 * 3 ) ) rst( RSTRDY );
#endif
Particle.publish( "Diagnos flags", String(diagFlags) );
#endif
tCellCk = millis();
tMqttLoop = millis();
// Run instant
tStatus = millis() + UNIT_STATUS_TIME;
tMqttConn = millis() + MQTT_CONN_TIME;
}
void loop() {
char payload[300];
int reSend;
char *pEnd, *pStart;
wd.checkin(); // resets the AWDT count
if (extCom.recvdflag) {
extCom.recvdflag = false;
runSerialCmd = true;
#ifdef _DEBUG_SERIAL
Serial.println( extCom.lastBuf );
#endif
}
if (client.isConnected()) {
if (millis() - tMqttLoop >= MQTT_KEEPALIVE) {
client.loop();
#ifdef _DIAG
if ( mqttReConnT.isActive() ) mqttReConnT.stop();
#endif
tMqttLoop = millis();
}
if (runSerialCmd) {
runSerialCmd = false;
reSend = 0;
if ( strstr( extCom.lastBuf, "asc" ) ) {
sprintf(payload, "{\"d\":%s}", extCom.lastBuf);
while( !client.publish( MQTT_TOPIC_SENSOR, payload ) && reSend++ < 4 );
#ifdef _DEBUG_MQTT
Serial.println( payload );
#endif
}
if ( strstr( extCom.lastBuf, "time" ) ) {
sprintf( payload, "&{\"time\":%u}", Time.now() );
EXT_SERIAL.println( payload );
Serial.println( payload );
}
}
#if ( PLATFORM_ID == PLATFORM_ELECTRON_PRODUCTION )
if ( millis() - tStatus >= UNIT_STATUS_TIME ) {
CellularSignal sig = Cellular.RSSI();
sprintf(payload, "{\"d\":{\"rssi\":\"%d\",\"qual\":\"%d\"}}", sig.rssi, sig.qual);
client.publish( MQTT_TOPIC_STATUS, payload );
Particle.publish( "Cell RSSI", payload );
Particle.publish( "Free memory", String(System.freeMemory()) );
tStatus = millis();
}
#endif
#if ( PLATFORM_ID == PLATFORM_PHOTON_PRODUCTION )
if ( millis() - tStatus >= UNIT_STATUS_TIME ) {
sprintf(payload, "{\"d\":{\"rssi\":\"%d\"}}", WiFi.RSSI() );
client.publish( MQTT_TOPIC_STATUS, payload );
Particle.publish( "WiFi RSSI", payload );
Particle.publish( "Free memory", String(System.freeMemory()) );
tStatus = millis();
}
#endif
}
else if ( millis() - tMqttConn >= MQTT_CONN_TIME ) {
mqttInit();
#ifdef _DIAG
if ( !mqttReConnT.isActive() ) mqttReConnT.start();
#endif
tMqttConn = millis();
}
#ifdef _DIAG
#if ( PLATFORM_ID == PLATFORM_ELECTRON_PRODUCTION )
if ( millis() - tCellCk >= CELL_CHECK_TIME ) {
if ( !waitFor( Cellular.ready, 60000 ) ) rst( RSTRDY );
if ( waitFor( Cellular.connecting, 60000 ) ) rst( RSTCONN );
tCellCk = millis();
}
#endif
#endif
}