From cc16e554503b2b293515363ae7fb516a54427f80 Mon Sep 17 00:00:00 2001 From: Sandeep Mistry Date: Tue, 12 Mar 2019 17:13:40 -0400 Subject: [PATCH 1/2] Add GCP IoT Core WiFi, GSM, and NB examples --- .../GCP_IoT_Core_GSM/GCP_IoT_Core_GSM.ino | 199 ++++++++++++++++++ .../GCP_IoT_Core_GSM/arduino_secrets.h | 11 + .../GCP_IoT_Core_NB/GCP_IoT_Core_NB.ino | 196 +++++++++++++++++ .../GCP_IoT_Core_NB/arduino_secrets.h | 8 + .../GCP_IoT_Core_WiFi/GCP_IoT_Core_WiFi.ino | 193 +++++++++++++++++ .../GCP_IoT_Core_WiFi/arduino_secrets.h | 9 + 6 files changed, 616 insertions(+) create mode 100644 examples/Google Cloud Platform IoT Core/GCP_IoT_Core_GSM/GCP_IoT_Core_GSM.ino create mode 100644 examples/Google Cloud Platform IoT Core/GCP_IoT_Core_GSM/arduino_secrets.h create mode 100644 examples/Google Cloud Platform IoT Core/GCP_IoT_Core_NB/GCP_IoT_Core_NB.ino create mode 100644 examples/Google Cloud Platform IoT Core/GCP_IoT_Core_NB/arduino_secrets.h create mode 100644 examples/Google Cloud Platform IoT Core/GCP_IoT_Core_WiFi/GCP_IoT_Core_WiFi.ino create mode 100644 examples/Google Cloud Platform IoT Core/GCP_IoT_Core_WiFi/arduino_secrets.h diff --git a/examples/Google Cloud Platform IoT Core/GCP_IoT_Core_GSM/GCP_IoT_Core_GSM.ino b/examples/Google Cloud Platform IoT Core/GCP_IoT_Core_GSM/GCP_IoT_Core_GSM.ino new file mode 100644 index 0000000..f9b5fda --- /dev/null +++ b/examples/Google Cloud Platform IoT Core/GCP_IoT_Core_GSM/GCP_IoT_Core_GSM.ino @@ -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 +#include +#include +#include +#include + +#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(); +} diff --git a/examples/Google Cloud Platform IoT Core/GCP_IoT_Core_GSM/arduino_secrets.h b/examples/Google Cloud Platform IoT Core/GCP_IoT_Core_GSM/arduino_secrets.h new file mode 100644 index 0000000..4ec82da --- /dev/null +++ b/examples/Google Cloud Platform IoT Core/GCP_IoT_Core_GSM/arduino_secrets.h @@ -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 "" diff --git a/examples/Google Cloud Platform IoT Core/GCP_IoT_Core_NB/GCP_IoT_Core_NB.ino b/examples/Google Cloud Platform IoT Core/GCP_IoT_Core_NB/GCP_IoT_Core_NB.ino new file mode 100644 index 0000000..f6c6406 --- /dev/null +++ b/examples/Google Cloud Platform IoT Core/GCP_IoT_Core_NB/GCP_IoT_Core_NB.ino @@ -0,0 +1,196 @@ +/* + GCP (Google Cloud Platform) IoT Core NB + + This sketch securely connects to GCP IoT Core using MQTT over NB IoT/LTE Cat M1. + 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 NB 1500 board + - Antenna + - SIM card with a data plan + - LiPo battery + + This example code is in the public domain. +*/ + +#include +#include +#include +#include +#include + +#include "arduino_secrets.h" + +/////// Enter your sensitive data in arduino_secrets.h +const char pinnumber[] = SECRET_PINNUMBER; + +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"; + +NB nbAccess; +GPRS gprs; + +NBSSLClient nbSslClient; +MqttClient mqttClient(nbSslClient); + +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 (nbAccess.status() != NB_READY || gprs.status() != GPRS_READY) { + connectNB(); + } + + 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 nbAccess.getTime(); +} + +void connectNB() { + Serial.println("Attempting to connect to the cellular network"); + + while ((nbAccess.begin(pinnumber) != NB_READY) || + (gprs.attachGPRS() != 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(); +} diff --git a/examples/Google Cloud Platform IoT Core/GCP_IoT_Core_NB/arduino_secrets.h b/examples/Google Cloud Platform IoT Core/GCP_IoT_Core_NB/arduino_secrets.h new file mode 100644 index 0000000..d00469c --- /dev/null +++ b/examples/Google Cloud Platform IoT Core/GCP_IoT_Core_NB/arduino_secrets.h @@ -0,0 +1,8 @@ +// NB settings +#define SECRET_PINNUMBER "" + +// 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 "" diff --git a/examples/Google Cloud Platform IoT Core/GCP_IoT_Core_WiFi/GCP_IoT_Core_WiFi.ino b/examples/Google Cloud Platform IoT Core/GCP_IoT_Core_WiFi/GCP_IoT_Core_WiFi.ino new file mode 100644 index 0000000..212ac2e --- /dev/null +++ b/examples/Google Cloud Platform IoT Core/GCP_IoT_Core_WiFi/GCP_IoT_Core_WiFi.ino @@ -0,0 +1,193 @@ +/* + GCP (Google Cloud Platform) IoT Core WiFi + + This sketch securely connects to GCP IoT Core using MQTT over WiFi. + 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: + - Arduino MKR WiFi 1010 or MKR1000 + + This example code is in the public domain. +*/ + +#include +#include +#include +#include +#include // change to #include for MKR1000 + +#include "arduino_secrets.h" + +/////// Enter your sensitive data in arduino_secrets.h +const char ssid[] = SECRET_SSID; +const char pass[] = SECRET_PASS; + +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"; + +WiFiSSLClient wifiSslClient; +MqttClient mqttClient(wifiSslClient); + +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 (WiFi.status() != WL_CONNECTED) { + connectWiFi(); + } + + 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 WiFi module + return WiFi.getTime(); +} + +void connectWiFi() { + Serial.print("Attempting to connect to SSID: "); + Serial.print(ssid); + Serial.print(" "); + + while (WiFi.begin(ssid, pass) != WL_CONNECTED) { + // failed, retry + Serial.print("."); + delay(5000); + } + Serial.println(); + + Serial.println("You're connected to the 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(); +} diff --git a/examples/Google Cloud Platform IoT Core/GCP_IoT_Core_WiFi/arduino_secrets.h b/examples/Google Cloud Platform IoT Core/GCP_IoT_Core_WiFi/arduino_secrets.h new file mode 100644 index 0000000..da51668 --- /dev/null +++ b/examples/Google Cloud Platform IoT Core/GCP_IoT_Core_WiFi/arduino_secrets.h @@ -0,0 +1,9 @@ +// Fill in your WiFi networks SSID and password +#define SECRET_SSID "" +#define SECRET_PASS "" + +// 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 "" From da971332047f7ba40846a2731fae018a7a3f5615 Mon Sep 17 00:00:00 2001 From: Sandeep Mistry Date: Tue, 19 Mar 2019 10:31:53 -0400 Subject: [PATCH 2/2] Add project hub link for GSM --- README.adoc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.adoc b/README.adoc index 8775718..26a5c0e 100644 --- a/README.adoc +++ b/README.adoc @@ -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]