Greetings,
From a review of past forum posts, it seems there is no existing support for accessing Cayenne using the Adafruit FONA or other GSM modules. It seemed like it would be easy enough to implement this through Adafruit’s own FONA-friendly MQTT library, but I am running into a problem.
When I attempt to start the MQTT connection, it appears to send an appropriate connection string, which looks like this:
MQTT , $[my client ID]$[my username]([my password]
But the Cayenne server does not respond, and so the request times out.
If I leave off the client ID, I get a valid connection packet back from the server, but data I send does not show up in the target widget.
The same code – with different credentials, of course – works fine on adafruit.io.
The code is below. I’d appreciate any insight. I’d also love to see what came through at the server end; some transparency there would be really helpful as I go through this process.
#include "Adafruit_FONA.h"
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_FONA.h"
#include <SoftwareSerial.h>
#define FONA_RST 4
#define FONA_RX 5
#define FONA_TX 6
#define FONA_KEY 7
SoftwareSerial fonaSerial = SoftwareSerial(FONA_TX, FONA_RX);
Adafruit_FONA fona = Adafruit_FONA(FONA_RST);
#define CAYENNE_SERVER "mqtt.mydevices.com"
#define CAYENNE_SERVERPORT 1883
#define CAYENNE_USERNAME "57eadfa57-57a11ed-c0a1e5ced" // Fake news, sad!
#define CAYENNE_PASSWORD "f01ded-5a1ad" // Fake news, sad!
#define CAYENNE_CLIENTID "c0ded-5eac0a575" // Fake news, sad!
uint8_t txfailures = 0;
// MQTT connection object.
Adafruit_MQTT_FONA mqtt(&fona, CAYENNE_SERVER, CAYENNE_SERVERPORT, CAYENNE_CLIENTID, CAYENNE_USERNAME, CAYENNE_PASSWORD);
// Publish object. Note MQTT paths for Cayenne follow the form: <username>/things/<client_id>/data/<channel_number>
Adafruit_MQTT_Publish datapoint = Adafruit_MQTT_Publish(&mqtt, "v1/" CAYENNE_USERNAME "/things/" CAYENNE_CLIENTID "/data/1");
void setup() {
Serial.begin(57600);
Serial.println(F("\nFONA Cayenne code demo"));
fonaOn();
}
void loop() {
delay(5000);
MQTT_connect();
delay(5000);
if(! mqtt.ping()) {
Serial.println(F("MQTT Ping failed."));
}
char* publishString = "242";
Serial.print(F("\nSending value: "));
Serial.print(publishString);
Serial.print("...");
if (! datapoint.publish(publishString)) {
Serial.println(F("Failed"));
txfailures++;
} else {
Serial.println(F("Published."));
txfailures = 0;
}
delay(5000);
}
void MQTT_connect() {
int8_t ret;
// Stop if already connected.
if (mqtt.connected()) {
return;
}
Serial.print("Connecting to MQTT... ");
while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
Serial.println(mqtt.connectErrorString(ret));
Serial.println("Retrying MQTT connection in 5 seconds...");
mqtt.disconnect();
delay(5000); // wait 5 seconds
}
Serial.println("MQTT Connected.");
}
boolean fonaOn() {
fonaSerial.begin(4800); // Open a serial interface to FONA
/*if(fona.sendCheckReply(F("AT"), F("OK")) == false) {*/ // If the FONA is off...
Serial.print(F("Powering FONA on..."));
digitalWrite(FONA_KEY, LOW); // ...pulse the Key pin low...
delay(2000);
digitalWrite(FONA_KEY, HIGH); // ...and then return it to high
Serial.println(F(" done."));
//}
Serial.println(F("Initializing FONA..."));
if(fona.begin(fonaSerial) == false) { // Start the FONA on serial interface
Serial.println(F("FONA not found. Check wiring and power."));
return false;
}
else {
Serial.print(F("FONA online. "));
unsigned long gsmTimeout = millis() + 30000;
boolean gsmTimedOut = false;
Serial.print(F("Waiting for GSM network... "));
while(1) {
byte network_status = fona.getNetworkStatus();
if(network_status == 1 || network_status == 5) break;
if(millis() >= gsmTimeout) {
gsmTimedOut = true;
break;
}
delay(250);
}
if(gsmTimedOut == true) {
Serial.println(F("timed out. Check SIM card, antenna, and signal."));
return false;
}
else {
Serial.println(F("done."));
}
// RSSI is a measure of signal strength -- higher is better; less than 10 is worrying
byte rssi = fona.getRSSI();
Serial.print(F("RSSI: "));
Serial.println(rssi);
delay(3000); // Give the network a moment
//fona.setGPRSNetworkSettings(F("cellcard")); // Set APN to your local carrier
if(rssi > 5) {
if(fona.enableGPRS(true) == false) {
// Sometimes enableGPRS() returns false even though it succeeded
if(fona.GPRSstate() != 1) {
for(byte GPRSattempts = 0; GPRSattempts < 5; GPRSattempts++) {
Serial.println(F("Trying again..."));
delay(2000);
fona.enableGPRS(true);
if(fona.GPRSstate() == 1) {
Serial.println(F("GPRS is on."));
break;
}
else {
Serial.print(F("Failed to turn GPRS on... "));
}
}
}
}
}
else {
Serial.println(F("Can't transmit, network signal strength is poor."));
gsmTimedOut = true;
}
return true;
}
}