Skip to content

Add GCP IoT Core WiFi, GSM, and NB examples #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 19, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ Related tutorials on Arduino Project Hub:
** https://create.arduino.cc/projecthub/132016/securely-connecting-an-arduino-mkr-wifi-1010-to-aws-iot-core-a9f365[Securely connecting an Arduino MKR WiFi 1010 to AWS IoT Core]
* Azure
** https://create.arduino.cc/projecthub/Arduino_Genuino/securely-connecting-an-arduino-nb-1500-to-azure-iot-hub-af6470[Securely Connecting an Arduino NB 1500 to Azure IoT Hub]
* Google Cloud
** https://create.arduino.cc/projecthub/Arduino_Genuino/securely-connecting-an-arduino-mkr-gsm-1400-to-gcp-iot-core-b8b628[Securely Connecting an Arduino MKR GSM 1400 to GCP IoT Core]
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
/*
GCP (Google Cloud Platform) IoT Core GSM

This sketch securely connects to GCP IoT Core using MQTT over GSM/3G.
It uses a private key stored in the ATECC508A and a JSON Web Token (JWT) with
a JSON Web Signature (JWS).

It publishes a message every 5 seconds to "/devices/{deviceId}/state" topic
and subscribes to messages on the "/devices/{deviceId}/config" and
"/devices/{deviceId}/commands/#" topics.

The circuit:
- MKR GSM 1400 board
- Antenna
- SIM card with a data plan
- LiPo battery

This example code is in the public domain.
*/

#include <ArduinoECCX08.h>
#include <utility/ECCX08JWS.h>
#include <ArduinoMqttClient.h>
#include <Arduino_JSON.h>
#include <MKRGSM.h>

#include "arduino_secrets.h"

/////// Enter your sensitive data in arduino_secrets.h
const char pinnumber[] = SECRET_PINNUMBER;
const char gprs_apn[] = SECRET_GPRS_APN;
const char gprs_login[] = SECRET_GPRS_LOGIN;
const char gprs_password[] = SECRET_GPRS_PASSWORD;

const char projectId[] = SECRET_PROJECT_ID;
const char cloudRegion[] = SECRET_CLOUD_REGION;
const char registryId[] = SECRET_REGISTRY_ID;
const String deviceId = SECRET_DEVICE_ID;

const char broker[] = "mqtt.googleapis.com";

GSM gsmAccess;
GPRS gprs;

GSMSSLClient gsmSslClient;
MqttClient mqttClient(gsmSslClient);

unsigned long lastMillis = 0;

void setup() {
Serial.begin(9600);
while (!Serial);

if (!ECCX08.begin()) {
Serial.println("No ECCX08 present!");
while (1);
}

// Calculate and set the client id used for MQTT
String clientId = calculateClientId();

mqttClient.setId(clientId);

// Set the message callback, this function is
// called when the MQTTClient receives a message
mqttClient.onMessage(onMessageReceived);
}

void loop() {
if (gsmAccess.status() != GSM_READY || gprs.status() != GPRS_READY) {
connectGSM();
}

if (!mqttClient.connected()) {
// MQTT client is disconnected, connect
connectMQTT();
}

// poll for new MQTT messages and send keep alives
mqttClient.poll();

// publish a message roughly every 5 seconds.
if (millis() - lastMillis > 5000) {
lastMillis = millis();

publishMessage();
}
}

unsigned long getTime() {
// get the current time from the cellular module
return gsmAccess.getTime();
}

void connectGSM() {
Serial.println("Attempting to connect to the cellular network");

while ((gsmAccess.begin(pinnumber) != GSM_READY) ||
(gprs.attachGPRS(gprs_apn, gprs_login, gprs_password) != GPRS_READY)) {
// failed, retry
Serial.print(".");
delay(1000);
}

Serial.println("You're connected to the cellular network");
Serial.println();
}

void connectMQTT() {
Serial.print("Attempting to connect to MQTT broker: ");
Serial.print(broker);
Serial.println(" ");

while (!mqttClient.connected()) {
// Calculate the JWT and assign it as the password
String jwt = calculateJWT();

mqttClient.setUsernamePassword("", jwt);

if (!mqttClient.connect(broker, 8883)) {
// failed, retry
Serial.print(".");
delay(5000);
}
}
Serial.println();

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

// subscribe to topics
mqttClient.subscribe("/devices/" + deviceId + "/config", 1);
mqttClient.subscribe("/devices/" + deviceId + "/commands/#");
}

String calculateClientId() {
String clientId;

// Format:
//
// projects/{project-id}/locations/{cloud-region}/registries/{registry-id}/devices/{device-id}
//

clientId += "projects/";
clientId += projectId;
clientId += "/locations/";
clientId += cloudRegion;
clientId += "/registries/";
clientId += registryId;
clientId += "/devices/";
clientId += deviceId;

return clientId;
}

String calculateJWT() {
unsigned long now = getTime();

// calculate the JWT, based on:
// https://cloud.google.com/iot/docs/how-tos/credentials/jwts
JSONVar jwtHeader;
JSONVar jwtClaim;

jwtHeader["alg"] = "ES256";
jwtHeader["typ"] = "JWT";

jwtClaim["aud"] = projectId;
jwtClaim["iat"] = now;
jwtClaim["exp"] = now + (24L * 60L * 60L); // expires in 24 hours

return ECCX08JWS.sign(0, JSON.stringify(jwtHeader), JSON.stringify(jwtClaim));
}

void publishMessage() {
Serial.println("Publishing message");

// send message, the Print interface can be used to set the message contents
mqttClient.beginMessage("/devices/" + deviceId + "/state");
mqttClient.print("hello ");
mqttClient.print(millis());
mqttClient.endMessage();
}

void onMessageReceived(int messageSize) {
// we received a message, print out the topic and contents
Serial.print("Received a message with topic '");
Serial.print(mqttClient.messageTopic());
Serial.print("', length ");
Serial.print(messageSize);
Serial.println(" bytes:");

// use the Stream interface to print the contents
while (mqttClient.available()) {
Serial.print((char)mqttClient.read());
}
Serial.println();

Serial.println();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// GSM settings
#define SECRET_PINNUMBER ""
#define SECRET_GPRS_APN "GPRS_APN" // replace with your GPRS APN
#define SECRET_GPRS_LOGIN "login" // replace with your GPRS login
#define SECRET_GPRS_PASSWORD "password" // replace with your GPRS password

// Fill in your Google Cloud Platform - IoT Core info
#define SECRET_PROJECT_ID ""
#define SECRET_CLOUD_REGION ""
#define SECRET_REGISTRY_ID ""
#define SECRET_DEVICE_ID ""
Loading