1

I have an issue when trying to upload sensor data to ThingSpeak using the GSMSSLClient with the Arduino MKR GSM 1400 over MQTT. Each time I attempt to establish an MQTT connection, the state is always -2. Below is the relevant sections of my code to do this:

 const char broker[] = "mqtt3.thingspeak.com";
 const int port = 8883; 
 GSMSSLClient sslClient;
 GPRS gprs;
 GSM gsmAccess;
 PubSubClient mqttClient(sslClient);

This was what I started with before initializing the MQTT connection. It failed and I thought of implementing the handling of certificates to attempt the connection again. I thus followed the steps in https://www.mathworks.com/matlabcentral/answers/1889632-how-to-download-root-certificate-for-use-with-industrial-communication-toolbox-mqtt-functions to download the root certificate, specifically the DigiCert Global Root G2 PEM certificate. I set it up this way:

 const char* caCert = \
 "-----BEGIN CERTIFICATE-----\n" \
 "XXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
 "XXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
 "XXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
 "-----END CERTIFICATE-----\n";
 sslClient.setTrustedRoot(caCert);

This failed as well. From the SSLCertificateManagement_Example in the MKRGSM library, I saw the certificate was in DER format, so I then used followed the steps here to convert the .pem to .der. I then used the sed command on Linux to format it in the structure 0xab, Below is the command:

 sed 's/../0x&, /g'

I then implemented this in the code in the arduino_secrets.h file:

 const uint8_t CA_CERT[] = {
 0x12, 0x34, 0x56, 0x78, 
 0x9a, 0xbc, 0xcd, 0xe1, 
 };

Then in the .ino file:

 sslClient.setTrustedRoot((const char*)CA_CERT));

It still failed. I then attempted to use the openssl command to get the certificates. I used two variations:

 openssl s_client -showcerts -connect mqtt3.thingspeak.com:443
 openssl s_client -showcerts -connect api.thingspeak.com:443

which output certificates which were similar to each other, but not similar to what I had downloaded from the link I had shared initially with the steps. I attempted to use these certificates as well, both in .pem and .der format but the connection still failed with state -2.

PS: Using port 1883 and GSMClient works and the data is uploaded to ThingSpeak successfully.

Here is a relatively verbose version of my code:

 #include <Adafruit_Sensor.h>
 #include <DHT.h> 
 #include <MKRGSM.h>
 #include "arduino_secrets.h"
 #include <PubSubClient.h> 
 #define DHTPIN 6
 #define DHTTYPE DHT11
 DHT dht(DHTPIN, DHTTYPE);
 // GSM credentials
 // PIN Number
 const char PINNUMBER[] = SECRET_PIN;
 // APN data
 const char GPRS_APN[] = SECRET_GPRS_APN;
 const char GPRS_LOGIN[] = SECRET_GPRS_LOGIN;
 const char GPRS_PASSWORD[] = SECRET_GPRS_PASS;
 // MQTT credentials
 const char* mqttServer = "mqtt3.thingspeak.com";
 const int mqttPort = 8883; 
 const char* mqttClientID = SECRET_MQTT_CLIENT_ID;
 const char* mqttUser = SECRET_MQTT_USERNAME;
 const char* mqttPass = SECRET_MQTT_PASSWORD;
 String topicString = "channels/" + String(SECRET_CH_ID) + "/publish";
 char topic[50];
 // GSM classes
 GSMClient client;
 GPRS gprs;
 GSM gsmAccess;
 PubSubClient mqttClient(client);
 const char* caCert = \
 "-----BEGIN CERTIFICATE-----\n" \
 "XXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
 "XXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
 "XXXXXXXXXXXXXXXXXXXXXXXXXXX\n" \
 "-----END CERTIFICATE-----\n";
 void setup() {
 Serial.begin(115200);
 Serial.println("Initializing DHT11...");
 dht.begin();
 Serial.println("Starting Arudino web client.");
 boolean connected = false;
 delay(10000);
 while (!connected) {
 if ((gsmAccess.begin(PINNUMBER) == GSM_READY) && (gprs.attachGPRS(GPRS_APN, GPRS_LOGIN, GPRS_PASSWORD) == GPRS_READY)) {
 connected = true;
 } else {
 Serial.println("Not connected to cellular network. Retrying...");
 delay(1000);
 }
 }
 Serial.println("Connected to cellular network");
 sslClient.setTrustedRoot(caCert);
 mqttClient.setServer(mqttServer, mqttPort);
 mqttClient.setKeepAlive(60);
 // MQTT connection
 if (mqttConnect()) {
 Serial.println("Connected to MQTT broker");
 } else {
 Serial.println("Failed to connect to MQTT broker");
 }
 }
 bool mqttConnect() {
 Serial.println("Connecting to MQTT...");
 if (mqttClient.connect(mqttClientID, mqttUser, mqttPass)) {
 Serial.println("MQTT connected");
 return true;
 } else {
 Serial.print("MQTT connection failed. State: ");
 Serial.println(mqttClient.state());
 return false;
 }
 }
 void loop() {
 if (!mqttClient.connected()) {
 Serial.println("MQTT disconnected. Reconnecting...");
 mqttConnect();
 }
 mqttClient.loop();
 float humidity = dht.readHumidity();
 float temperature = dht.readTemperature();
 if (isnan(humidity) || isnan(temperature)) {
 Serial.println("Failed to read from DHT sensor!");
 } else {
 Serial.print("Humidity: "); Serial.print(humidity); Serial.println("%");
 Serial.print("Temperature: "); Serial.print(temperature); Serial.println("°C");
 }
 String payload = "field1=" + String(temperature) + "&field2=" + String(humidity);
 // Publish to MQTT topic
 if (mqttClient.publish(topic, payload.c_str())) {
 Serial.print("Publishing to: ");
 Serial.println(topic);
 Serial.print("Payload: ");
 Serial.println(payload);
 Serial.println("Data published to ThingSpeak MQTT.");
 } else {
 Serial.println("MQTT publish failed.");
 }
 delay(15000);
 }
asked Feb 25 at 13:35
4
  • please present the minimal complete code that exhibits the issue Commented Feb 25 at 20:15
  • Added. Each time I attempt to connect, I get the "Connected to cellular network", but then the MQTT is always "MQTT connection failed. State -2". Commented Feb 25 at 22:52
  • What about the \n in the certificate text. Do you translate it to 0x0a? Or do you convert each character \` and n` into a separate hex value? Sorry I not the time to read the whole question, so it might be answered already. Just to present you my idea. ;-) Commented Mar 15 at 10:50
  • No, the \n are not really part of the certificate. They are kind of used for formatting, to introduce a newline so as to have the long certificate content span multiple lines to improve readability, as far as I understand at least. Commented Mar 16 at 17:44

0

Know someone who can answer? Share a link to this question via email, Twitter, or Facebook.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.