nRF5 SDK for Thread and Zigbee v3.0.0
Thread Google Cloud Platform CoAP Example

Table of Contents

This example demonstrates the interaction between the development kit and the Google Cloud Platform. The nRF52840 node uses the built-in OpenThread CoAP protocol (with optional DTLS security).

The application uses the temperature sensor to measure the current temperature and uses the internal counter that can be altered between 15 and 30 (which corresponds to the Celsius degree range). The node sends the temperature with the counter value each time BSP_BUTTON_2 or BSP_BUTTON_3 are pressed and with each TEMP_MEASUREMENT_INTERVAL, by default 5000 ms. Additionally, these buttons decrease and increase the counter value, respectively.

Another functionality is reading and applying the LED configuration from the cloud. This functionality is bound to BSP_BUTTON_0. The example implements an optional CLI interface that you can use to communicate with the nodes through the serial port and configure them manually.

thread_google_iot_coap_architecture.svg
Figure 1: Thread Google IoT CoAP communication architecture.

Description

This example is based on the Thread Border Router and Thread NCP/RCP Example. For proper operation, you must set up Nordic's Thread Border Router to provide Internet connectivity to the Thread network.

After the Thread Border Router is set up, configure the cloud and the node to ensure they communicate. Once configured, each CoAP packet sent to the cloud will contain a JSON Web Token (JWT) that acts as signature and confirms the identity of the device. For this configuration to work, you must embed the following data in the JWT:

With this information embedded, you will obtain the current unix time, which is used for JWT generation. You must also embed the private key used to sign the message, while the complementary public key must be uploded to the cloud to make the authentication possible. See the following subsections for more details.

Setting up the cloud

For a device to be able to connect, it must first be registered with the Cloud IoT Core: you must add the device to a collection (the registry) and define some essential properties. You can configure the cloud side by using the Google Cloud Shell as described later in this document.

The Cloud IoT Core uses public key (or asymmetric) authentication:

To set up the cloud:

  1. Generate an ES256 key pair with the Eliptic Curve algorithm by running the following commands on your development PC:
    openssl ecparam -genkey -name prime256v1 -noout -out ec_private.pem
    openssl ec -in ec_private.pem -pubout -out ec_public.pem
    These commands create the following public/private key pair:
    • ec_private.pem: The private key that must be securely stored on the device. It is used to sign the authentication JWT.
    • ec_public.pem: The public key that must be stored in Cloud IoT Core. It is used to verify the signature of the authentication JWT.
  2. Open the Google Cloud Platform Console webpage.
  3. Click the console logo in the right upper corner of the Google Cloud Platform panel. This activates the Google Cloud Shell, needed to configure the cloud side.
  4. Enter the following commands:
    git clone https://github.com/GoogleCloudPlatform/community.git
    cd community/tutorials/cloud-iot-coap-proxy
    gcloud services enable cloudiot.googleapis.com cloudbuild.googleapis.com compute.googleapis.com containerregistry.googleapis.com
    gcloud pubsub topics create coap-events
    gcloud iot registries create coap-demo --region us-central1 --event-notification-config topic=coap-events
    scripts/cloudbuild.sh
    gcloud compute instances create-with-container coap-proxy-demo \
    --tags=coap --container-image gcr.io/$GOOGLE_CLOUD_PROJECT/coap-proxy \
    --zone us-central1-a \
    --container-env=PSK_IDENTITY=my_identity,PSK_SECRET=some_secret
    gcloud compute firewall-rules create allow-coap --action=ALLOW \
    --rules=udp:5683 --source-ranges=0.0.0.0/0 --target-tags=coap
    gcloud compute firewall-rules create allow-coaps --action=ALLOW \
    --rules=udp:5684 --source-ranges=0.0.0.0/0 --target-tags=coap
  5. Upload the ec_public.pem file generated previously to your home directory by clicking three dots symbol in the Google Cloud Shell.
  6. Create a device by running the following command:
    gcloud iot devices create --registry=coap-demo --region=us-central1 \
    --public-key path=~/ec_public.pem,type=es256-pem demo-device
  7. Create a Firestone database in the native mode using the panel on the left side.
  8. Create the following resource hierachy in the Firestone database:
    • Collection with name collection_id.
    • Document with name document_id.
    • Two integer fields: temp, counter.
      Note
      If you choose different values, these changes must be reflected in the main.py script below.
  9. Create a Google Cloud Function:
    • Trigger Cloud Pub/Sub
    • Topic coap-events
    • Language Python 3.7
    • main.py Script content:
      import base64
      import json
      from google.cloud import firestore
      def hello_pubsub(event, context):
      """Triggered from a message on a Cloud Pub/Sub topic.
      Args:
      event (dict): Event payload.
      context (google.cloud.functions.Context): Metadata for the event.
      """
      pubsub_message = base64.b64decode(event['data']).decode('utf-8')
      print(pubsub_message)
      x_dict = json.loads(pubsub_message)
      db = firestore.Client()
      doc_ref = db.collection(u'collection_id').document(u'document_id')
      doc_ref.set({
      u'temp': x_dict["temp"],
      u'counter': x_dict["counter"]
      })
    • Edit requirements.txt.
      # Function dependencies, for example:
      # package>=version
      google-cloud-firestore>=0.31.0
  10. Obtain the gateway IPv4 address by running the following command:
    gcloud compute instances describe coap-proxy-demo --zone us-central1-a --format="value(networkInterfaces.accessConfigs[0].natIP)"
  11. Embed the obtained gateway IPv4 address in the GCP_COAP_IOT_CORE_SERVER_ADDRESS define in the main.c file.
    • For example, the address 35.195.184.91 translates to the following hexadecimal values: 0x23, 0xc3, 0xb8, 0x5b. This results in the following define value:
      #define GCP_COAP_IOT_CORE_SERVER_ADDRESS "64:ff9b::23c3:b85b"
  12. Obtain the project ID by running the following command:
    echo $GOOGLE_CLOUD_PROJECT
  13. Embed the project ID in the GCP_COAP_IOT_CORE_PROJECT_ID define in the main.c file.
    Note
    The remaining GCP CoAP defines are set to default. If you altered any of the commands above, you might need to adjust more define parameters in the main.c file.
  14. Fill the GCP_COAP_IOT_CORE_DEVICE_KEY define in the thread\\examples\\cloud\\google_iot_coap\\main.c file.
    #define GCP_COAP_IOT_CORE_DEVICE_ID "some_device_id"
    #define GCP_COAP_IOT_CORE_DEVICE_KEY
    "-----BEGIN EC PRIVATE KEY-----\r\n" \
    "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\r\n" \
    "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\r\n" \
    "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX==\r\n" \
    "-----END EC PRIVATE KEY-----\r\n"

Enabling the secure communication with DTLS

To enable the secure communication with Datagram Transport Layer Security (DTLS), you must enable a DTLS session between the Thread device and Google IoT Cloud:

  1. Locate the following lines in the main.c file of the example:
    #define GCP_COAP_SECURE_ENABLED 0
    #define GCP_COAP_SECURE_PSK "some_secret"
    #define GCP_COAP_SECURE_PSK_INDENTITY "my_identity"
  2. Edit the GCP_COAP_SECURE_ENABLED from 0 to 1 and provide the correct values for PSK and PSK Identity below it.

Setup

You can find the source code and the makefile in the following folder: <InstallFolder>\examples\thread\cloud\google_iot_coap.

Client LED assignments

Client button assignments

Testing

To test this example, you need the same hardware as for Thread Border Router.

Testing the temperature sensor

Note
All capital strings in the URLs need to be replaced with the values present in the main.c.

To test the temperature sensor:

  1. Open The Firestone Database and choose your device.
    https://console.cloud.google.com/firestore?project=GCP_COAP_IOT_CORE_PROJECT_ID
  2. Turn on the OpenThread Border Router.
  3. Turn on the Thread device and wait few seconds to make sure that device has joined the Thread network.
  4. Observe the LED status:
    • LED1 blinking: Device is joining the network.
    • LED1 solid: Device joined the network.
  5. Push BUTTON 3 to decrease the simulated counter value.
  6. Observe the data received in the Firestore database. Replace some_device_id with the value defined in the main.c.
    https://console.cloud.google.com/firestore/data/devices/GCP_COAP_IOT_CORE_DEVICE_ID?project=GCP_COAP_IOT_CORE_PROJECT_ID
  7. Push BUTTON 4 to increase the simulated counter value.
  8. Observe the data received in the Firestore database. Replace some_device_id with the value defined in the main.c.
    https://console.cloud.google.com/firestore/data/devices/GCP_COAP_IOT_CORE_DEVICE_ID?project=GCP_COAP_IOT_CORE_PROJECT_ID

Testing reading and applying the LED configuration from the cloud

To test reading and applying the LED configuration from the cloud:

  1. Complete all the steps in Testing the temperature sensor.
  2. Navigate to the Device webpage:
    https://console.cloud.google.com/iot/locations/GCP_COAP_IOT_CORE_REGION/registries/GCP_COAP_IOT_CORE_REGISTRY_ID/devices/GCP_COAP_IOT_CORE_DEVICE_ID?project=GCP_COAP_IOT_CORE_PROJECT_ID
  3. Change the LED configuration in the IoT Core device settings.
    Note
    The device accepts only the following strings:
    • "LED1"
    • "LED2"
    • "LED3"
    • "LED4"
  4. Push BSP_BUTTON_0 to obtain the configuration of the device.
  5. Observe that only the configured LED is turned on.

Troubleshooting

How to verify that Thread Border Router has been booted up correctly and is providing Internet access?

Follow Border Router test connectivity to test connectivity to public Google DNS server (64:ff9b::808:808).

How to verify that two nodes have joined the same network and my device communicates with Google IoT Cloud?

You can use the nRF Sniffer for 802.15.4 project to sniff Thread packets. To decrypt them correctly, set up Wireshark according to steps 4-8 in Configuring Wireshark for Thread.


Documentation feedback | Developer Zone | Subscribe | Updated