Skip to content

Commit

Permalink
Adding MQTTS support
Browse files Browse the repository at this point in the history
Now supports SSL connection to Live Objects (activated by default). For this, the sketch loads the DigiCert Root CA certificate in the radio module.
Also more comments in the code ;)
  • Loading branch information
mdelain authored Apr 3, 2020
1 parent 2e7bb92 commit b3ce932
Show file tree
Hide file tree
Showing 3 changed files with 216 additions and 55 deletions.
152 changes: 107 additions & 45 deletions Arduino_MKR1500NB.ino
Original file line number Diff line number Diff line change
@@ -1,60 +1,107 @@
#define DEFAULT_TX_FREQUENCY 60 // message rate by default
// (can be updated over the air from Live Objects platform)
/******************************************************************************
DEFAULT VALUES
******************************************************************************/

// Set MQTT security:
// comment the line to disable security (MQTT),
// uncomment to activate TLS security (MQTTS).
#define MQTT_TLS

// Set the default message transmission rate (in seconds).
// This parameter can be updated later over the air from Live Objects.
#define DEFAULT_MESSAGE_RATE 60

#define SW_REVISION "1.5.0"

/******************************************************************************
INCLUDES
******************************************************************************/

#include "arduino_secrets.h"
#if defined MQTT_TLS
#include "LiveObjectsCert.h"
#endif
#include <MKRNB.h>
#include <ArduinoMqttClient.h>
#include <ArduinoJson.h>
#include <MKRNB.h>

#define sw_revision "1.0.1"
/******************************************************************************
TYPEDEFS
******************************************************************************/

NB nbAccess;
//GPRS gprs;
NBClient nbClient;
MqttClient mqttClient(nbClient);
enum NetworkConnectionAction {
CONNECT,
DISCONNECT
};

const char mqtt_user[] = "json+device";
const char mqtt_pass[] = SECRET_LIVEOBJECTS_API_KEY;
/******************************************************************************
CONSTANTS
******************************************************************************/

// Live Objects information
const char mqtt_id[] = "MKRNB1500";
const char mqtt_broker[] = "liveobjects.orange-business.com";
const char mqtt_pubdata[] = "dev/data";
const char mqtt_pubcfg[] = "dev/cfg";
const char mqtt_subcfg[] = "dev/cfg/upd";
const char mqtt_user[] = "json+device"; // MQTT username for 'device' role
#if defined MQTT_TLS
const uint16_t mqtt_port = 8883; // TLS MQTT port
#else
const uint16_t mqtt_port = 1883; // plain MQTT port
#endif
const char mqtt_pubdata[] = "dev/data"; // topic for publishing data
const char mqtt_pubcfg[] = "dev/cfg"; // subscribed topic for configuration updates
const char mqtt_subcfg[] = "dev/cfg/upd"; // topic for publishing confuguration

// Buffers holding the serialized default payloads for data and configuration
const char* JSONdata = "{\"model\":\"github_sample_MKR\",\"value\":{\"uptime\":0}}";
const char* JSONcfg = "{\"cfg\":{\"message rate (s)\":{\"t\":\"u32\",\"v\":0}}}";

const char pin[] = SECRET_PINNUMBER;
const char apn[] = SECRET_APN;
const char apn_user[] = SECRET_APN_USER;
const char apn_pass[] = SECRET_APN_PASS;
/******************************************************************************
VARIABLES
******************************************************************************/

const char* JSONdata = "{\"model\":\"github_sample_MKR\",\"value\":{\"uptime\":0}}";
const char* JSONcfg= "{\"cfg\":{\"transmit frequency (s)\":{\"t\":\"u32\",\"v\":0}}}";
uint32_t messageRate = DEFAULT_MESSAGE_RATE * 1000; // stores the current data message rate
uint32_t lastMessageTime = DEFAULT_MESSAGE_RATE * 1000; // stores the time when last data message was sent
uint32_t uptimeInSec; // stores the device uptime in seconds (sent in the data message)
bool DigiCert_rootCA_loaded = false; // controls if the root CA certificate has already been stored in the SARA module

uint32_t transmissionFrequency = DEFAULT_TX_FREQUENCY * 1000;
uint32_t lastTransmission = DEFAULT_TX_FREQUENCY * 1000;
void connectionManager(NetworkConnectionAction _action);

uint32_t uptimeInSec = 0;
/******************************************************************************
OBJECTS CREATION
******************************************************************************/

NB nbAccess;
#if defined MQTT_TLS
NBSSLClient nbClient; // for TLS MQTT connection to Live Objects
#else
NBClient nbClient; // for plain MQTT connection to Live Objects
#endif
MqttClient mqttClient(nbClient);
StaticJsonDocument<350> payload;

void connectionManager(bool _way);

void setup() {
Serial.begin(9600);
while (!Serial);
Serial.print("\n\n***\nUsing Arduino LTE-M with Live Objects\nversion ");
Serial.println(sw_revision);
Serial.println("***\n");
while (!Serial); // uncomment this line if you want to run the sketch without monitoring the Serial line.
Serial.print("\n***\nLive Objects on Arduino MKR 1500NB\nrevision ");
Serial.println(SW_REVISION);
Serial.println("***");

if (sizeof(SECRET_LIVEOBJECTS_API_KEY) != 33) {
Serial.print("Please check your Live Objects API key (arduino_secrets.h file).\nStopping here.");
while (1) ;
}

mqttClient.setId(mqtt_id);
mqttClient.setUsernamePassword(mqtt_user, mqtt_pass);
mqttClient.setUsernamePassword(mqtt_user, SECRET_LIVEOBJECTS_API_KEY);
mqttClient.onMessage(onMessageReceived);

connectionManager(1);
connectionManager(CONNECT);
updateConfig();
}

void loop() {
if (millis() - lastTransmission > transmissionFrequency) {
if (millis() - lastMessageTime > messageRate) {
// get data from sensors
Serial.println("Sampling data");
sampleData();
Expand All @@ -63,7 +110,7 @@ void loop() {
Serial.println("Sending data to Live Objects");
//if (nbAccess.status() != NB_READY || gprs.status() != GPRS_READY || !mqttClient.connected())
if (nbAccess.status() != NB_READY || !mqttClient.connected())
connectionManager(1);
connectionManager(CONNECT);

sendData();
}
Expand All @@ -72,23 +119,38 @@ void loop() {
mqttClient.poll();
}

void connectionManager(bool _way = 1) {
switch (_way) {
case 1:
void connectionManager(NetworkConnectionAction _action = CONNECT) {
switch (_action) {
case CONNECT:
Serial.print("Connecting to cellular network");
//while ((nbAccess.begin() != NB_READY) || (gprs.attachGPRS() != GPRS_READY))
while (nbAccess.begin(pin, apn, apn_user, apn_pass) != NB_READY)
while (nbAccess.begin(SECRET_PINNUMBER, SECRET_APN, SECRET_APN_USER, SECRET_APN_PASS) != NB_READY)
Serial.print(".");

Serial.println("\nYou're connected to the network");


#if defined MQTT_TLS // only performed when using TLS, in order to load the needed root CA into the SARA module
if (!DigiCert_rootCA_loaded) {
Serial.println("Loading DigiCert Root CA certificate");
MODEM.sendf("AT+USECMNG=0,0,\"%s\",%d", LO_ROOT_CERT.name, LO_ROOT_CERT.size);
if (MODEM.waitForPrompt() != 1) {
Serial.print("Problem loading certificate!\nStopping here.");
while (1) ;
}
else {
MODEM.write(LO_ROOT_CERT.data, LO_ROOT_CERT.size);
int ready;
while (!MODEM.ready()) ;
DigiCert_rootCA_loaded = true;
Serial.println("Certificate loaded");
}
}
#endif

Serial.print("Connecting to MQTT broker '");
Serial.print(mqtt_broker);
Serial.print("'");

while (!mqttClient.connect(mqtt_broker))
while (!mqttClient.connect(mqtt_broker, mqtt_port))
Serial.print(".");

Serial.println("\nYou're connected to the MQTT broker");
Serial.println();

Expand All @@ -97,7 +159,7 @@ void connectionManager(bool _way = 1) {

break;

case 0:
case DISCONNECT:
Serial.println("\nClosing MQTT connection...");
mqttClient.stop();
Serial.println("Disconnecting from cellular network...");
Expand Down Expand Up @@ -144,14 +206,14 @@ void onMessageReceived(int messageSize) {
void updateConfig() {
if (payload.containsKey(F("cid"))) {
if (payload[F("cfg")].containsKey(F("transmit frequency (s)"))) {
transmissionFrequency = payload[F("cfg")][F("transmit frequency (s)")][F("v")].as<int>() * 1000;
payload[F("cfg")][F("transmit frequency (s)")][F("v")] = transmissionFrequency / 1000;
messageRate = payload[F("cfg")][F("transmit frequency (s)")][F("v")].as<int>() * 1000;
payload[F("cfg")][F("transmit frequency (s)")][F("v")] = messageRate / 1000;
}
}
else {
payload.clear();
deserializeJson(payload, JSONcfg);
payload[F("cfg")][F("transmit frequency (s)")][F("v")] = transmissionFrequency / 1000;
payload[F("cfg")][F("transmit frequency (s)")][F("v")] = messageRate / 1000;
}

char _buffer[300];
Expand All @@ -172,5 +234,5 @@ void sendData() {
char _buffer[300];
serializeJson(payload, _buffer);
publishMessage(mqtt_pubdata, _buffer);
lastTransmission = millis();
lastMessageTime = millis();
}
99 changes: 99 additions & 0 deletions LiveObjectsCert.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
#ifndef _LIVEOBJECTS_CERT_H_INCLUDED
#define _LIVEOBJECTS_CERT_H_INCLUDED

#include <stddef.h>
#include <stdint.h>

struct LORootCert {
const char* name;
const uint8_t* data;
const int size;
};

static const LORootCert LO_ROOT_CERT = {
"DigiCert_Global_Root_CA",
(const uint8_t[]){
0x30, 0x82, 0x03, 0xaf, 0x30, 0x82, 0x02, 0x97, 0xa0, 0x03, 0x02, 0x01,
0x02, 0x02, 0x10, 0x08, 0x3b, 0xe0, 0x56, 0x90, 0x42, 0x46, 0xb1, 0xa1,
0x75, 0x6a, 0xc9, 0x59, 0x91, 0xc7, 0x4a, 0x30, 0x0d, 0x06, 0x09, 0x2a,
0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05, 0x05, 0x00, 0x30, 0x61,
0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55,
0x53, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0c,
0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, 0x6e, 0x63,
0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x10, 0x77,
0x77, 0x77, 0x2e, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, 0x74, 0x2e,
0x63, 0x6f, 0x6d, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, 0x03,
0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x47,
0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43,
0x41, 0x30, 0x1e, 0x17, 0x0d, 0x30, 0x36, 0x31, 0x31, 0x31, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x31, 0x31, 0x31,
0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x61, 0x31,
0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53,
0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0c, 0x44,
0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x49, 0x6e, 0x63, 0x31,
0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x10, 0x77, 0x77,
0x77, 0x2e, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x63,
0x6f, 0x6d, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x47, 0x6c,
0x6f, 0x62, 0x61, 0x6c, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x41,
0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00,
0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xe2, 0x3b, 0xe1,
0x11, 0x72, 0xde, 0xa8, 0xa4, 0xd3, 0xa3, 0x57, 0xaa, 0x50, 0xa2, 0x8f,
0x0b, 0x77, 0x90, 0xc9, 0xa2, 0xa5, 0xee, 0x12, 0xce, 0x96, 0x5b, 0x01,
0x09, 0x20, 0xcc, 0x01, 0x93, 0xa7, 0x4e, 0x30, 0xb7, 0x53, 0xf7, 0x43,
0xc4, 0x69, 0x00, 0x57, 0x9d, 0xe2, 0x8d, 0x22, 0xdd, 0x87, 0x06, 0x40,
0x00, 0x81, 0x09, 0xce, 0xce, 0x1b, 0x83, 0xbf, 0xdf, 0xcd, 0x3b, 0x71,
0x46, 0xe2, 0xd6, 0x66, 0xc7, 0x05, 0xb3, 0x76, 0x27, 0x16, 0x8f, 0x7b,
0x9e, 0x1e, 0x95, 0x7d, 0xee, 0xb7, 0x48, 0xa3, 0x08, 0xda, 0xd6, 0xaf,
0x7a, 0x0c, 0x39, 0x06, 0x65, 0x7f, 0x4a, 0x5d, 0x1f, 0xbc, 0x17, 0xf8,
0xab, 0xbe, 0xee, 0x28, 0xd7, 0x74, 0x7f, 0x7a, 0x78, 0x99, 0x59, 0x85,
0x68, 0x6e, 0x5c, 0x23, 0x32, 0x4b, 0xbf, 0x4e, 0xc0, 0xe8, 0x5a, 0x6d,
0xe3, 0x70, 0xbf, 0x77, 0x10, 0xbf, 0xfc, 0x01, 0xf6, 0x85, 0xd9, 0xa8,
0x44, 0x10, 0x58, 0x32, 0xa9, 0x75, 0x18, 0xd5, 0xd1, 0xa2, 0xbe, 0x47,
0xe2, 0x27, 0x6a, 0xf4, 0x9a, 0x33, 0xf8, 0x49, 0x08, 0x60, 0x8b, 0xd4,
0x5f, 0xb4, 0x3a, 0x84, 0xbf, 0xa1, 0xaa, 0x4a, 0x4c, 0x7d, 0x3e, 0xcf,
0x4f, 0x5f, 0x6c, 0x76, 0x5e, 0xa0, 0x4b, 0x37, 0x91, 0x9e, 0xdc, 0x22,
0xe6, 0x6d, 0xce, 0x14, 0x1a, 0x8e, 0x6a, 0xcb, 0xfe, 0xcd, 0xb3, 0x14,
0x64, 0x17, 0xc7, 0x5b, 0x29, 0x9e, 0x32, 0xbf, 0xf2, 0xee, 0xfa, 0xd3,
0x0b, 0x42, 0xd4, 0xab, 0xb7, 0x41, 0x32, 0xda, 0x0c, 0xd4, 0xef, 0xf8,
0x81, 0xd5, 0xbb, 0x8d, 0x58, 0x3f, 0xb5, 0x1b, 0xe8, 0x49, 0x28, 0xa2,
0x70, 0xda, 0x31, 0x04, 0xdd, 0xf7, 0xb2, 0x16, 0xf2, 0x4c, 0x0a, 0x4e,
0x07, 0xa8, 0xed, 0x4a, 0x3d, 0x5e, 0xb5, 0x7f, 0xa3, 0x90, 0xc3, 0xaf,
0x27, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x63, 0x30, 0x61, 0x30, 0x0e,
0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02,
0x01, 0x86, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55,
0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x03, 0xde, 0x50, 0x35, 0x56, 0xd1,
0x4c, 0xbb, 0x66, 0xf0, 0xa3, 0xe2, 0x1b, 0x1b, 0xc3, 0x97, 0xb2, 0x3d,
0xd1, 0x55, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30,
0x16, 0x80, 0x14, 0x03, 0xde, 0x50, 0x35, 0x56, 0xd1, 0x4c, 0xbb, 0x66,
0xf0, 0xa3, 0xe2, 0x1b, 0x1b, 0xc3, 0x97, 0xb2, 0x3d, 0xd1, 0x55, 0x30,
0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05,
0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xcb, 0x9c, 0x37, 0xaa, 0x48,
0x13, 0x12, 0x0a, 0xfa, 0xdd, 0x44, 0x9c, 0x4f, 0x52, 0xb0, 0xf4, 0xdf,
0xae, 0x04, 0xf5, 0x79, 0x79, 0x08, 0xa3, 0x24, 0x18, 0xfc, 0x4b, 0x2b,
0x84, 0xc0, 0x2d, 0xb9, 0xd5, 0xc7, 0xfe, 0xf4, 0xc1, 0x1f, 0x58, 0xcb,
0xb8, 0x6d, 0x9c, 0x7a, 0x74, 0xe7, 0x98, 0x29, 0xab, 0x11, 0xb5, 0xe3,
0x70, 0xa0, 0xa1, 0xcd, 0x4c, 0x88, 0x99, 0x93, 0x8c, 0x91, 0x70, 0xe2,
0xab, 0x0f, 0x1c, 0xbe, 0x93, 0xa9, 0xff, 0x63, 0xd5, 0xe4, 0x07, 0x60,
0xd3, 0xa3, 0xbf, 0x9d, 0x5b, 0x09, 0xf1, 0xd5, 0x8e, 0xe3, 0x53, 0xf4,
0x8e, 0x63, 0xfa, 0x3f, 0xa7, 0xdb, 0xb4, 0x66, 0xdf, 0x62, 0x66, 0xd6,
0xd1, 0x6e, 0x41, 0x8d, 0xf2, 0x2d, 0xb5, 0xea, 0x77, 0x4a, 0x9f, 0x9d,
0x58, 0xe2, 0x2b, 0x59, 0xc0, 0x40, 0x23, 0xed, 0x2d, 0x28, 0x82, 0x45,
0x3e, 0x79, 0x54, 0x92, 0x26, 0x98, 0xe0, 0x80, 0x48, 0xa8, 0x37, 0xef,
0xf0, 0xd6, 0x79, 0x60, 0x16, 0xde, 0xac, 0xe8, 0x0e, 0xcd, 0x6e, 0xac,
0x44, 0x17, 0x38, 0x2f, 0x49, 0xda, 0xe1, 0x45, 0x3e, 0x2a, 0xb9, 0x36,
0x53, 0xcf, 0x3a, 0x50, 0x06, 0xf7, 0x2e, 0xe8, 0xc4, 0x57, 0x49, 0x6c,
0x61, 0x21, 0x18, 0xd5, 0x04, 0xad, 0x78, 0x3c, 0x2c, 0x3a, 0x80, 0x6b,
0xa7, 0xeb, 0xaf, 0x15, 0x14, 0xe9, 0xd8, 0x89, 0xc1, 0xb9, 0x38, 0x6c,
0xe2, 0x91, 0x6c, 0x8a, 0xff, 0x64, 0xb9, 0x77, 0x25, 0x57, 0x30, 0xc0,
0x1b, 0x24, 0xa3, 0xe1, 0xdc, 0xe9, 0xdf, 0x47, 0x7c, 0xb5, 0xb4, 0x24,
0x08, 0x05, 0x30, 0xec, 0x2d, 0xbd, 0x0b, 0xbf, 0x45, 0xbf, 0x50, 0xb9,
0xa9, 0xf3, 0xeb, 0x98, 0x01, 0x12, 0xad, 0xc8, 0x88, 0xc6, 0x98, 0x34,
0x5f, 0x8d, 0x0a, 0x3c, 0xc6, 0xe9, 0xd5, 0x95, 0x95, 0x6d, 0xde
},
947
};

#endif
20 changes: 10 additions & 10 deletions arduino_secrets.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
//// cellular connection cerdentials
#define SECRET_PINNUMBER "" // unless PIN is deactivated, specify your SIM card PIN number
#define SECRET_APN "" // specify the APN name (if needed)
#define SECRET_APN_USER "" // specify the username for your APN (if needed)
#define SECRET_APN_PASS "" // specify the password for your APN (if needed)
// Cellular connection cerdentials
const char SECRET_PINNUMBER[] = ""; // unless PIN is deactivated, specify your SIM card PIN number
const char SECRET_APN[] = ""; // specify the APN name (if needed)
const char SECRET_APN_USER[] = ""; // specify the username for your APN (if needed)
const char SECRET_APN_PASS[] = ""; // specify the password for your APN (if needed)


//// your Live Objects credential
#define SECRET_LIVEOBJECTS_API_KEY "..." // paste here the Live Objects API key for your device;
// your key must use the "MQTT device" profile
// You API key must have the predefined 'MQTT Device' right (alternatively: 'Device Access' read + write rights).
// If your API key has more important rights, you *need* to use a TLS connection (MQTTS).
// Live Objects credential: paste below your API key (see Configuration > API keys on the portal).
// You API key must have at least the predefined 'MQTT Device' rights profile
// (alternatively: 'Device Access' read + write rights if need to customise the rights).
// Please note that you *must* use a TLS connection (MQTTS) if you grant more rights to the API key.
const char SECRET_LIVEOBJECTS_API_KEY[] = "...";

0 comments on commit b3ce932

Please sign in to comment.