Connecting the ESP32 Feather HUZZAH32 kit for Google IoT Core with Windows 10

As a non-computer guy, I actually found connecting an IoT device to the Google Cloud Platform (GCP) easier than expected, given that Google IoT Core is (as of this posting) in beta.  That being said, before this posting, I couldn't find one complete set of instructions from top to bottom that connects ESP32 to GCP.  And despite my best efforts following the Mongoose OS Cloud Integration Google IoT Core instructions, the mos tool kept returning this
Server Error: gcloud device create exit status 1
when trying to register the device on Google Cloud IoT Core - but Ill show you what fixed it.  The error prevented me from sending messages back and forth between GCP and the device.  Anyway, since I had some difficulty, I thought I would share my experience in the event that I could help someone else just like me!

My initial conditions:
-  WiFi access
-  Windows 10 (64bit) computer
-  GCP account
-  ESP32 kit I purchased through the Mongoose OS website



Step 1
If you have set up your GCP account already above and have received your ESP32 kit, take the ESP32 microprocessor (HUZZAH32) and carefully insert the pins into the breadboard (rectangular thing) with the USB connect facing outward.  

Step 2
Connect the other side of the USB to your computer.  

Step 3 
Download the mos.exe file mos tool download to your computer.


Step 4
Double-click on the executable which will automatically open a new browser and show you a prompt to connect your device.  You should get a screen that looks like this:


Hopefully, your computer auto-detects the device.  Unfortunately, my computer did not as you can see in the drop down menu above.  Luckily, the Mongoose website has some slick links to ensure you have USB-to-Serial drivers installed.  You can do this by looking at the links Mongoose OS provides within the Troubleshooting Section.


For me, I had to install the the Silabs drivers.  In short, this is what I had to do:
- Download the Windows 10 Universal software.
- I ran the “CP210xVCPInstaller_x64”
- I installed it manually.  Make sure ESP32 is plugged in, run Device Manager on your computer, locate the device you want to install, right click on the device and choose "Update Driver Software ...", follow the instructions.  I restarted my computer.

From here, I reopened the executable to launch mos again.  This time, I was able to select the device address, platform, app and WiFi config...  


Success!  Now, I have linked the device to the mos tool which allows me to access the device files and run commands via the mos terminal.  

Step 5 
The next step is to register the device with GCP IoT Core.  You can do this via the Google Cloud SDK Shell (if you installed it on your computer), Google Cloud Shell within the GCP console, or via the GCP console.  I will show you via the GCP Console in conjunction with the Google Cloud Shell.  This seems to be easiest for me since I can quickly run commands and see the changes visually on the console.

Now, Im not sure when using the Google Cloud Shell if the beta tools are always installed, but I ran the command anyway via the Cloud Shell and followed the prompts:
gcloud components install beta
Step 6 
Next, I created a project and named it "esp32-iot-demo" using the panel on the left hand side of the console:


Once you name your project, be sure to Enable Billing via the three vertical dots to the right of your project name in the console and be sure to to also Enable the Cloud IoT Core API via the API & Services on the menu on the left.  All GCP projects must be tied to a billing account.  Then, be sure that you set this newly created project as your current project.  For this, just use the drop down menu in blue at the top of the GCP home screen.

Step 7
Now this section is easiest when using the Google Cloud Shell command line.  

Run this command to add permission for IoT Core.  Copy and paste this command, except add your own project name in place of YOUR_PROJECT_NAME below:
gcloud projects add-iam-policy-binding YOUR_PROJECT_NAME --member=serviceAccount:cloud-iot@system.gserviceaccount.com --role=roles/pubsub.publisher

Run this command to create a PubSub topic for all of your device data.  Copy and paste this command.  The command below creates a topic called "telemetry-topic":

gcloud beta pubsub topics create telemetry-topic

Run this command to create a PubSub subscription for all of your device data.  Copy and paste this command.  The command below creates a subscription called "telemetry-subscription" to the above topic:

gcloud beta pubsub subscriptions create --topic telemetry-topic telemetry-subscription
Run this command to create a device registry called "esp32-registry" in "us-central1" zone under "telemetry-topic":
gcloud beta iot registries create esp32-registry --region us-central1 --event-pubsub-topic=telemetry-topic
If you navigate to IoT Core on the console and you can verify what you just created:


Step 8
Next, add your device!  This is were I had a bit of trouble.  Since I wasn't aware of how keys worked, I bypassed this section.  As a result, this is where the mos tool and GCP seemed to be unable to communicate by returning the following via the mos terminal:

Server Error: gcloud device create exit status 1

As I understand it, GCP Iot Core supports two protocols to connect and communicate which are HTTP and MQTT.  HTTP does not maintain connection with IoT Core, while MQTT does and seems to be a standard when it comes to connecting embedded devices and machine-to-machine devices.  So, in a nutshell, what happens here is that there are public keys and private keys.  (You want to safeguard private keys)  Public keys are stored with IoT Core, while private keys are stored on the device itself.  The MQTT bridge verifies the private key against the public key and then accepts the connection.

Click Add Device.  Go ahead and name your device, then select ES256 Public Key Format. 


Now, you have to obtain the public and private keys.  So open the Google Cloud Shell and copy and paste the following to create the key pair.  
openssl ecparam -genkey -name prime256v1 -noout -out ec_private.pem
openssl ec -in ec_private.pem -pubout -out ec_public.pem
View these keys by opening the Launch Code Editor button the on the top right of the Google Cloud Shell window.  This will open up a new browser tab.  Once the new browser opens, you should be able to see:

ec_private.pem 
ec_public.pem 

Click on ec_public.pem and copy all of the contents and paste it into the Public Key Value block of the device creation section including the 'Begin' and 'End' portion.  Then click Add to add the device to your registry.

Step 9
Now that IoT Core has the public key, you will have to perform a similar method for the private key.  Click on ec_private.pem and copy the contents.

Go back to the mos tool, click Device Files on the left pane, click ca.pem and scroll to the bottom.  Return a few spaces and paste the private key contents including the 'Begin' and 'End' portion.  Also, I used the header format of one of the other certificates in the file which seems to set boundaries on the key validity.  I have modified and grayed out an example of mine below:


Step 10
Finally, we can now connect the ESP32 device to GCP IoT Core via the mos terminal!  If you are following along in my example above, again, these are my variables.  Feel free to swap these out in the code below as needed.

PROJECT=esp32-iot-demo
REGION=us-central1
REGISTRY=esp32-registry
DEVICE_ID=my-device

Of note, you can use port 8883 instead of port 443.  I found that port 8883 is blocked by my firewall so I used port 443.

Copy and paste the following into the mos terminal:
mos config-set mqtt.enable=true mqtt.server=mqtt.googleapis.com:443 mqtt.ssl_ca_cert=ca.pem sntp.enable=true gcp.enable=true gcp.project=esp32-iot-demo gcp.region=us-central1 gcp.registry=esp32-registry gcp.device=my-device device.id=my-device gcp.key=ca.pem debug.stderr_topic=/devices/my-device/events/log debug.stdout_topic=/devices/my-device/events/log  

Step 11
Now, test it.  Run the following command from the mos terminal:
mos ui
From what I understand, the ESP32 is now sending telemetry to GCP Iot Core.  What you want to see is:

Published: 1 /devices/my-device/state -> {"free_ram":140096,"total_ram":229560} 

You can verify this on the GCP IoT Core within your device.  Go to Device and click on Configuration & State History.  Here, you can see the messages published.  Specifically the same "free_ram":140096,"total_ram":229560 shown above:

Step 12
Next, you can send messages the other direction from IoT Core to ESP32.  In the same GCP window above, click Update Config, then type a message and send it to the device. 

Go back to your mos terminal and see the message arrive in the device log.

Done!  You have now connected your ESP32 to Google IoT Core!  I hope this was helpful!

Main sources of information that helped me and for further reading, please see the following links:

Comments