Connect Raspberry Pi to Google Cloud IoT (GCP IoT) using NodeJS

This project covers, step by step, how to connect Raspberry Pi to Google Cloud IoT and how to send data from Raspberry Pi to GCP IoT via MQTT. As an example, Raspberry Pi uses the BME280 sensor to acquire temperature and humidity. Next, it sends these sensor readings to Google Cloud IoT. The Google Cloud Raspberry client is written in NodeJS.

Project steps

Below the project steps that we have to complete to connect Raspberry Pi to Google Cloud IoT using NodeJS:

  • Configuring a GCP IoT
    • Enable PubSub
    • Create and configure a Registry
    • Configuring a Google Cloud IoT device
  • Connecting Raspberry Pi to BME280
  • Sending data from Raspberry Pi to Google Cloud IoT through MQTT

During this Raspberry tutorial, we will use Google Cloud Console (CLI) instead of configuring the GCP using Web Interface.

If you prefer to use the Web interface to configure the GCP you can read my previous tutorial: how to send data to Google using ESP32.

Prerequisites

To complete this project you need:

  1. A Google account. You can create it for free
  2. Google Cloud IoT account. It is free with some limitations but you can test it without spending money
  3. Raspberry Pi
  4. NodeJS installed on your Raspberry Pi
  5. BME280 to read temperature and humidity

Configuring Google Cloud IoT

To send data to Google Cloud IoT from Raspberry Pi, it is necessary to configure the GCP IoT. This step is the same and it doesn’t depend on the language you’re using to build the Raspberry Pi client. In this example, we are using NodeJS but you can choose another language too.

Creating a Google Cloud Project

To create a Google Cloud Project so that the Raspberry NodeJS client can connect to it, use the terminal writing this code:

export PROJECT_ID="raspberry-gcp" gcloud projects create $PROJECT_ID gcloud config set project $PROJECT_ID

Next, once the project is created, it is time to enable Google Cloud API:

gcloud services enable pubsub.googleapis.com new console "https://console.cloud.google.com/iot/api?project=$PROJECT_ID"

Alternatively, you can open the browser log in into the Google console and then write this URL:

https://console.cloud.google.com/iot/api?project=raspberry-gcp

Configuring the MQTT Topic in GCP

In this project the NodeJS client sends data to Google cloud using MQTT. Therefore, it is necessary to create the topic where Raspberry Pi will publish data. Use the following commands:

export pub_topic="rasp-pub" export subscription=”rasp-sub” gcloud pubsub topics create $pub_topic gcloud pubsub subscriptions create $subscription --topic $pub_topic

The commands above create a MQTT topic named rasp-pub and then a subscription to the same MQTT topic.

Configuring a Google Registry

After creating the topic, we have to create the Google cloud registry. Using the CLI write to the following lines:

export registry_name=”swa_registry” export region="europe-west1" gcloud iot registries create $registry_name \ --region=$region \ --event-notification-config=topic=$pub_topic \ --enable-mqtt-config --enable-http-config

Notice that the registry is swa_registry, while the region is europe-west1. You can change the registry name as you prefer, while the region depends on the country where you live. We will use these information when we will connect the Raspberry Pi to Google Cloud IoT to send data through MQTT.

Checking the Google Cloud Project

Before going on and developing the NodeJS Google cloud client, it is useful to check that all the work made until now is correct.

Let us connect to the Google Cloud console and select the project you have created. You should see the following information:

If everything is ok we can go on adding a device to Google Cloud.

Creating the client certificate to connect to Google IoT

Add a new device using the Google Console as shown in the picture below:

Configuring the device in Google Cloud IoT

To create the certificate to use in the previous configuration, you have to use this command:

openssl req -x509 -newkey rsa:2048 -keyout rasp_private.pem -nodes -out rasp_cert.pem -subj "/CN=unused"

Using the previous command, we have created two different certificates:

  • public certificate named rasp_cert.pem that we wil use in the Google Console
  • private certificate named rasp_private.pem that we will use to connect Raspberry Pi to Google Cloud IoT

How to connect Raspberry Pi to Google Cloud IoT

To connect Raspberry Pi to Google Cloud IoT we wil develop a NodeJs application that runs on Raspberry. Using NodeJS app, Raspberry connects to BME280 to acquire temperature and humidity.

Schematic: Raspberry Pi – BME280

The schematic below shows how to connect Raspberry Pi to BME280 so that we can read sensor data to send to GCP:

NodeJS Project setup

Before developing the code, it is necessary to create a new directory that will hold the NodeJS source code:

mkdir rasp-gcp

Then initialize the project:

npm init -y

Installing NodeJS libaries

Moreover, it is necessary to install the library that we will use in our NodeJS code:

npm install jsonwebtoken --save npm install bme280 --save npm install mqtt --save

Implementing the NodeJS code

The NodeJS code is shown below:

var fs = require('fs'); var jwt = require('jsonwebtoken'); var mqtt = require('mqtt'); var bme280 = require('bme280'); // Define project info var projectId = "raspberry-gcp"; var region = "europe-west1"; var registryId = "swa_registry"; var deviceId = "rasp-device"; // MQTT Broker var mqttHost = "mqtt.googleapis.com"; var mqttPort = 8883; var alg = "RS256"; // MQTT topic var mqttTopic = "/devices/rasp-device/events"; // Key var privateKeyFile = "/home/pi/rasp-gcp/certs/rasp_private.pem"; // Let us make clientId var clientId = "projects/" + projectId + "/locations/" + region + "/registries/" + registryId + "/devices/" + deviceId; console.log("Client Id ["+clientId+"]"); const mqttArgs = { host: mqttHost, port: mqttPort, clientId: clientId, username: 'unused', password: createJwt(projectId, privateKeyFile, alg), protocol: 'mqtts', secureProtocol: "TLSv1_2_method" } // Connecting var client = mqtt.connect(mqttArgs); client.on('connect', function(success) { if (!success) { console.log("client not connected..."); } else { console.log("connected"); sendData(); } }); client.on('error', function(err) { console.log('error', err); }); client.on('close', function() { console.log("Connection closed"); } ); client.on('message', function(topic, message, packet) { console.log(topic, 'message received: ', Buffer.from(message, 'base64').toString('ascii')); }); function createJwt(projectId, privateKeyFile, algorithm) { var token = { 'iat': parseInt(Date.now() / 1000), 'exp': parseInt(Date.now() / 1000) + 3600, 'aud': projectId }; var privateKey = fs.readFileSync(privateKeyFile); return jwt.sign(token, privateKey, {algorithm: algorithm}); } function sendData() { bme280.open( { i2cAddress: 0x76 }).then(async sensor => { var data = await sensor.read(); console.log(data); var payload = JSON.stringify(data); console.log("Publishing data to MQTT Topic..."); client.publish(mqttTopic, payload, {qos: 1}); await sensor.close(); }).catch(console.log); setTimeout(sendData, 60000); }

In the beginning, you have to replace the values with your values. The code is quite simple. Notice that the MQTT password it the JWT token.

Testing the connection between Raspberry Pi and Google Cloud IoT

Runs the NodeJS code on your Raspberry and wait while the BME280 reads temperature and humidity. Connect o GCP consone and check the results:

Raspberry Pi connects to Google Cloud IoT

Wrapping up

In summary, we have covered how to connect Raspberry Pi to the Google Cloud IoT platform using NodeJS. We have described how to use MQTT to integrate Raspberry with the Google Cloud IoT platform and how to send sensor readings.