diff --git a/main.py b/main.py index 13fe739..a0e29ce 100755 --- a/main.py +++ b/main.py @@ -1,8 +1,10 @@ import os +import sys import time import ujson import machine import network +import ssl from umqtt.simple import MQTTClient #Enter your wifi SSID and password below. @@ -15,22 +17,21 @@ aws_endpoint = b'AWS_ENDPOINT.amazonaws.com' #If you followed the blog, these names are already set. +# To validate the IoT endpoint, the Amazon Root CA cert is needed. +# You can get this from https://www.amazontrust.com/repository/AmazonRootCA1.pem +# This can also be downloaded when creating the certs for your device in the IoT Console +# For more details: +# https://docs.aws.amazon.com/iot/latest/developerguide/server-authentication.html#server-authentication-certs thing_name = "BlogThing" client_id = "BlogClient" private_key = "private.pem.key" private_cert = "cert.pem.crt" - -#Read the files used to authenticate to AWS IoT Core -with open(private_key, 'r') as f: - key = f.read() -with open(private_cert, 'r') as f: - cert = f.read() +ca_cert = "AmazonRootCA1.pem" #These are the topics we will subscribe to. We will publish updates to /update. #We will subscribe to the /update/delta topic to look for changes in the device shadow. topic_pub = "$aws/things/" + thing_name + "/shadow/update" topic_sub = "$aws/things/" + thing_name + "/shadow/update/delta" -ssl_params = {"key":key, "cert":cert, "server_side":False} #Define pins for LED and light sensor. In this example we are using a FeatherS2. #The sensor and LED are built into the board, and no external connections are required. @@ -51,12 +52,37 @@ print('Connection successful') print('Network config:', wlan.ifconfig()) -def mqtt_connect(client=client_id, endpoint=aws_endpoint, sslp=ssl_params): - mqtt = MQTTClient(client_id=client, server=endpoint, port=8883, keepalive=1200, ssl=True, ssl_params=sslp) +def connect_to_iot(mqtt_client): print("Connecting to AWS IoT...") - mqtt.connect() + mqtt_client.connect() print("Done") - return mqtt + return mqtt_client + +# used for micropython 1.23 and above +def mqtt_connect_new(client=client_id, endpoint=aws_endpoint, key=private_key, cert=private_cert, ca=ca_cert): + ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT) + + # cert and key must be strings if using a file path. + # If these are bytes (b""), then they are interpreted as the cert data + ctx.load_cert_chain(cert, key) + + # to verify the IoT Endpoint's certificate is valid + ctx.load_verify_locations(cafile=ca) + ctx.verify_mode = ssl.CERT_REQUIRED + + mqtt = MQTTClient(client_id=client, server=endpoint, port=8883, keepalive=1200, ssl=ctx) + return connect_to_iot(mqtt) + +# used for micropython 1.22 and below +def mqtt_connect(client=client_id, endpoint=aws_endpoint): + with open(private_key, 'r') as f: + key = f.read() + with open(private_cert, 'r') as f: + cert = f.read() + + sslp = {"key": key, "cert": cert, "server_side": False} + mqtt = MQTTClient(client_id=client, server=endpoint, port=8883, keepalive=1200, ssl=True, ssl_params=sslp) + return connect_to_iot(mqtt) def mqtt_publish(client, topic=topic_pub, message=''): print("Publishing message...") @@ -74,6 +100,14 @@ def mqtt_subscribe(topic, msg): def led_state(message): led.value(message['state']['led']['onboard']) +# determine micropython version +# change the connection implementation if 1.23+ due to a breaking change with ssl +# see: https://github.com/micropython/micropython-lib/pull/793 +if sys.implementation.version[1] >= 23: + mqtt_connect = mqtt_connect_new +else: + mqtt_connect = mqtt_connect + #We use our helper function to connect to AWS IoT Core. #The callback function mqtt_subscribe is what will be called if we #get a new message on topic_sub.