/ examples / aws_iot_shadows.py
aws_iot_shadows.py
  1  import time
  2  import json
  3  import board
  4  import busio
  5  from digitalio import DigitalInOut
  6  import neopixel
  7  from adafruit_esp32spi import adafruit_esp32spi
  8  from adafruit_esp32spi import adafruit_esp32spi_wifimanager
  9  import adafruit_esp32spi.adafruit_esp32spi_socket as socket
 10  import adafruit_minimqtt as MQTT
 11  from adafruit_aws_iot import MQTT_CLIENT
 12  
 13  ### WiFi ###
 14  
 15  # Get wifi details and more from a secrets.py file
 16  try:
 17      from secrets import secrets
 18  except ImportError:
 19      print("WiFi secrets are kept in secrets.py, please add them there!")
 20      raise
 21  
 22  # Get device certificate
 23  try:
 24      with open("aws_cert.pem.crt", "rb") as f:
 25          DEVICE_CERT = f.read()
 26  except ImportError:
 27      print("Certificate (aws_cert.pem.crt) not found on CIRCUITPY filesystem.")
 28      raise
 29  
 30  # Get device private key
 31  try:
 32      with open("private.pem.key", "rb") as f:
 33          DEVICE_KEY = f.read()
 34  except ImportError:
 35      print("Certificate (private.pem.key) not found on CIRCUITPY filesystem.")
 36      raise
 37  
 38  # If you are using a board with pre-defined ESP32 Pins:
 39  esp32_cs = DigitalInOut(board.ESP_CS)
 40  esp32_ready = DigitalInOut(board.ESP_BUSY)
 41  esp32_reset = DigitalInOut(board.ESP_RESET)
 42  
 43  # If you have an externally connected ESP32:
 44  # esp32_cs = DigitalInOut(board.D9)
 45  # esp32_ready = DigitalInOut(board.D10)
 46  # esp32_reset = DigitalInOut(board.D5)
 47  
 48  spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
 49  esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
 50  
 51  # Verify nina-fw version >= 1.4.0
 52  assert (
 53      int(bytes(esp.firmware_version).decode("utf-8")[2]) >= 4
 54  ), "Please update nina-fw to >=1.4.0."
 55  
 56  # Use below for Most Boards
 57  status_light = neopixel.NeoPixel(
 58      board.NEOPIXEL, 1, brightness=0.2
 59  )  # Uncomment for Most Boards
 60  # Uncomment below for ItsyBitsy M4
 61  # status_light = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2)
 62  # Uncomment below for an externally defined RGB LED
 63  # import adafruit_rgbled
 64  # from adafruit_esp32spi import PWMOut
 65  # RED_LED = PWMOut.PWMOut(esp, 26)
 66  # GREEN_LED = PWMOut.PWMOut(esp, 27)
 67  # BLUE_LED = PWMOut.PWMOut(esp, 25)
 68  # status_light = adafruit_rgbled.RGBLED(RED_LED, BLUE_LED, GREEN_LED)
 69  wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, secrets, status_light)
 70  
 71  ### Code ###
 72  
 73  # Define callback methods which are called when events occur
 74  # pylint: disable=unused-argument, redefined-outer-name
 75  def connect(client, userdata, flags, rc):
 76      # This function will be called when the client is connected
 77      # successfully to the broker.
 78      print("Connected to MQTT Broker!")
 79      print("Flags: {0}\n RC: {1}".format(flags, rc))
 80  
 81      # Subscribe client to all shadow updates
 82      print("Subscribing to shadow updates...")
 83      aws_iot.shadow_subscribe()
 84  
 85  
 86  def disconnect(client, userdata, rc):
 87      # This method is called when the client disconnects
 88      # from the broker.
 89      print("Disconnected from MQTT Broker!")
 90  
 91  
 92  def subscribe(client, userdata, topic, granted_qos):
 93      # This method is called when the client subscribes to a new topic.
 94      print("Subscribed to {0} with QOS level {1}".format(topic, granted_qos))
 95  
 96      # Update device shadow with example JSON payload
 97      payload = {"state": {"reported": {"moisture": 50, "temp": 30}}}
 98      aws_iot.shadow_update(json.dumps(payload))
 99  
100      # We can also retrieve the shadow from AWS IoT,
101      # aws_iot.shadow_get()
102  
103      # or delete the shadow
104      # aws_iot.shadow_delete()
105  
106  
107  def unsubscribe(client, userdata, topic, pid):
108      # This method is called when the client unsubscribes from a topic.
109      print("Unsubscribed from {0} with PID {1}".format(topic, pid))
110  
111  
112  def publish(client, userdata, topic, pid):
113      # This method is called when the client publishes data to a topic.
114      print("Published to {0} with PID {1}".format(topic, pid))
115  
116  
117  def message(client, topic, msg):
118      # This method is called when the client receives data from a topic.
119      print("Message from {}: {}".format(topic, msg))
120  
121  
122  # Set AWS Device Certificate
123  esp.set_certificate(DEVICE_CERT)
124  
125  # Set AWS RSA Private Key
126  esp.set_private_key(DEVICE_KEY)
127  
128  # Connect to WiFi
129  print("Connecting to WiFi...")
130  wifi.connect()
131  print("Connected!")
132  
133  # Initialize MQTT interface with the esp interface
134  MQTT.set_socket(socket, esp)
135  
136  # Set up a new MiniMQTT Client
137  client = MQTT.MQTT(broker=secrets["broker"], client_id=secrets["client_id"])
138  
139  # Initialize AWS IoT MQTT API Client
140  aws_iot = MQTT_CLIENT(client)
141  
142  # Connect callback handlers to AWS IoT MQTT Client
143  aws_iot.on_connect = connect
144  aws_iot.on_disconnect = disconnect
145  aws_iot.on_subscribe = subscribe
146  aws_iot.on_unsubscribe = unsubscribe
147  aws_iot.on_publish = publish
148  aws_iot.on_message = message
149  
150  print("Attempting to connect to %s" % client.broker)
151  aws_iot.connect()
152  
153  # Pump the message loop forever, all events
154  # are handled in their callback handlers
155  # while True:
156  #   aws_iot.loop()
157  
158  # Start a blocking message loop...
159  # NOTE: NO code below this loop will execute
160  # NOTE: Network reconnection is handled within this loop
161  while True:
162      try:
163          aws_iot.loop()
164      except (ValueError, RuntimeError) as e:
165          print("Failed to get data, retrying\n", e)
166          wifi.reset()
167          aws_iot.reconnect()
168          continue
169      time.sleep(1)