Connecting MicroPython devices to Google Cloud IoT Core

Carl Krauss
Google Cloud - Community
6 min readJun 12, 2019

Intro

A few weeks ago, I started building another IoT project. (More to come on that later) When laying out all of the components and determining how I’m going to set it up, I took a second to think about the software side of things. I saw two main paths forward. On one hand, I could go the Arduino C/C++ route which is a pretty well documented and in more cases a good route to go. But on the other hand, I had heard about MicroPython but had never gotten around to giving it a shot. I also could not find any good information about using MicroPython with Google Cloud IoT Core.

So the goal of this blog is to share a step-by-step walk through of how to get a MicroPython-compatible micro-controller, in this case a ESP32, configured to connect and send events over MQTT to Google Cloud IoT Core.

Select a device

Like I mentioned before, we’ll be starting out with an ESP32 development board. These can be found fairly cheaply on eBay, Banggood, Aliexpress, etc. However, I picked up a lolin32 on Amazon. In any case, most (if not all) ESP32 development boards should work.

Because your device likely doesn’t have MicroPython already installed, we’ll need to go ahead and flash it. Don’t worry, this is a pretty straightforward process. In my case I’m using the current latest stable (esp32–20190529-v1.11.bin) but if you’re up for it, it might be worth checking out the latest and greatest. You can find the binary files on the MicroPython site: http://micropython.org/download#esp32

After you’ve selected and downloaded the MicroPython binary file, we’ll want to make sure you have the esptool which allows you to easily communicate with the ROM bootloader of the device. The code for this is located here, but you can easily install it using pip. Additionally, we’ll also want to have a tool that can communicate and control the MicroPython board over serial. This tool is called ampy and we’ll install that now as well.

pip install esptool adafruit-ampy

Now that you have the esptool installed, you’ll want to plug the board into your computer and find out which serial port it is on. Since I’m using a Mac, I’ll do something like:

ls /dev/ | grep -i "tty" | grep -i "usb"

In my case the serial port ended up being /dev/tty.SLAB_USBtoUART, however yours may be different depending on your operating system. We can store this in an environment variable to make it a little easier.

export SERIALPORT="/dev/tty.SLAB_USBtoUART"

You can now confirm that everything is working by running a check on the device:

esptool.py —-port $SERIALPORT flash_id

This should print out some details about the ESP32 chip.

At this point we’re ready to erase the flash that’s currently on the board and go ahead and flash it with MicroPython. Here are the two commands to do that. [Note: This assumes that your MicroPython file is in your home directory Downloads folder and your serial port may be different from the one listed below]

esptool.py —-chip esp32 —-port $SERIALPORT erase_flashesptool.py —-chip esp32 —-port $SERIALPORT —-baud 460800 write_flash -z 0x1000 ~/Downloads/esp32–20190529-v1.11.bin

After that finishes…Success! You now have MicroPython installed on your ESP32 board. You can view the files that are currently on the device by using ampy. There should only be one file named boot.py which is loaded unsurprisingly every time the device boots.

ampy —-port $SERIALPORT -—baud 115200 ls

Now it’s time to generate an RSA public/private key pair. You can do this by running the following two commands.

openssl genrsa -out rsa_private.pem 2048openssl rsa -in rsa_private.pem -pubout -out rsa_public.pem

This will output 2 files rsa_private.pem and rsa_public.pem. You’re going to need these in the next step, but make sure to keep them private.

Configure Google Cloud IoT Core

We now need to setup setup Google Cloud IoT Core so that we have all of the values that we need when configuring the device. Login to https://console.cloud.google.com. If you don’t already have an account, you can try it for free.

On the left hand side you’ll want to navigate to “IoT Core”. If this is your first time, you’ll need to enable the API.

Next you’ll need to create a registry and fill out the following information:

Registry ID — This is a registry that will contain 1 or more devices that you would like to connect.

Region — Select the region that’s best for you. In my case I’ll use us-central1 since it’s the closest to me.

Select the Pub/Sub topics for telemetry and state. (You can create a new one for each of these)

Once the registry is created, we can now create a device in the registry for our esp32 board. Go to “Devices” then “Create a new device”. In this section we’ll configure the device. Give it a unique device ID, for this setup I just used something like esp32-dev-1, but you can use whatever ID you would like. We’ll leave the defaults as they are.

Device Communication — Allow
Authentication — Enter Manually
Public key format — RS256.

In the Public key value we’ll paste in the contents of the file rsa_public.pem that was created in a previous step. At this point we can click create and we’re all set on the Google Cloud side.

Device Setup

Cool. So now we’re ready to get some code onto this device. For this we’re going to use some sample code from here: https://github.com/GoogleCloudPlatform/iot-core-micropython

git clone https://github.com/GoogleCloudPlatform/iot-core-micropythoncd iot-core-micropython/

In this repo there will be a file named config.py.example. This is a template config that you will need to update with your information. When you get to the jwt_config section, we’re going to have to do a little work around to get this working. I wasn’t able to get the pyasn1 library to run on the ESP32 in MicroPython due to memory constraints. (However, this might change in the future) This is used to encode and decode ASN.1 data types in to PEM or DER formats, which are the formats used by RSA. To work around this we’ll have to use our local machine to decode the private key and store the components of the key in a tuple. We’ll then use this with the RSA library. To read the values you can run:

pip install rsapython utils/decode_rsa.py

And it should output 5 (very large) integers within parentheses. You’ll need to copy and paste this value into the jwt_config section for the private_key value. After you’ve updated the information you’ll need to rename the file to config.py.

Next, we will use ampy to copy the files to the device. We’ll do this by issuing the following 3 commands.

ampy —-port $SERIALPORT —-baud 115200 put libampy —-port $SERIALPORT —-baud 115200 put config.pyampy —-port $SERIALPORT —-baud 115200 put main.py

You can verify that the files are on the board by using an ampy ls command.

ampy —-port /dev/tty.SLAB_USBtoUART —-baud 115200 ls/boot.py
/config.py
/lib
/main.py

At this point you can reset your board and view the output by using screen.

screen -L /dev/tty.SLAB_USBtoUART 115200 -L

If all goes well you should see output that looks something like this:

Publishing message {“temp”: 113, “device_id”: “esp32-oled-1”}
Publishing message {“temp”: 114, “device_id”: “esp32-oled-1”}
Publishing message {“temp”: 114, “device_id”: “esp32-oled-1”}

Wrapping Up

Congratulations! You now have your device sending data to IoT Core. You can view the message by opening up a cloud shell and running the command:

gcloud pubsub subscriptions pull —-limit=10 —-auto-ack projects/[your-project-id]/subscriptions/[your-subscription-id]

--

--

Carl Krauss
Google Cloud - Community

Product Manager at Google. All thoughts / views are my own.