code.py
  1  # SPDX-FileCopyrightText: 2019 Brent Rubell for Adafruit Industries
  2  # SPDX-FileCopyrightText: 2020 Jim Bennett for Adafruit Industries
  3  #
  4  # SPDX-License-Identifier: MIT
  5  
  6  """
  7  PyPortal Azure IoT Plant Monitor
  8  ====================================================
  9  Log plant vitals to Microsoft Azure IoT Central with
 10  your PyPortal
 11  
 12  Authors: Brent Rubell for Adafruit Industries, 2019
 13         : Jim Bennett for Microsoft, 2020
 14  """
 15  import time
 16  import json
 17  import board
 18  import busio
 19  from digitalio import DigitalInOut
 20  from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager
 21  import adafruit_esp32spi.adafruit_esp32spi_socket as socket
 22  import neopixel
 23  import rtc
 24  from adafruit_azureiot import IoTCentralDevice
 25  from adafruit_seesaw.seesaw import Seesaw
 26  
 27  # gfx helper
 28  import azure_gfx_helper
 29  
 30  # init. graphics helper
 31  gfx = azure_gfx_helper.Azure_GFX(is_celsius=True)
 32  
 33  # Get wifi details and more from a secrets.py file
 34  try:
 35      from secrets import secrets
 36  except ImportError:
 37      print("WiFi secrets are kept in secrets.py, please add them there!")
 38      raise
 39  
 40  # PyPortal ESP32 Setup
 41  esp32_cs = DigitalInOut(board.ESP_CS)
 42  esp32_ready = DigitalInOut(board.ESP_BUSY)
 43  esp32_reset = DigitalInOut(board.ESP_RESET)
 44  spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
 45  esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)
 46  
 47  # Set up the WiFi manager with a status light to show the WiFi connection status
 48  status_light = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.2)
 49  wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, secrets, status_light)
 50  print("WiFi connecting...")
 51  wifi.connect()
 52  print("WiFi connected!")
 53  
 54  # Time setup, needed to authenticate with Azure IoT Central
 55  # get_time will raise ValueError if the time isn't available yet so loop until
 56  # it works.
 57  now_utc = None
 58  while now_utc is None:
 59      try:
 60          now_utc = time.localtime(esp.get_time()[0])
 61      except ValueError:
 62          pass
 63  rtc.RTC().datetime = now_utc
 64  
 65  # Soil Sensor Setup
 66  i2c_bus = busio.I2C(board.SCL, board.SDA)
 67  ss = Seesaw(i2c_bus, addr=0x36)
 68  
 69  # Create an instance of the Azure IoT Central device
 70  device = IoTCentralDevice(
 71      socket, esp, secrets["id_scope"], secrets["device_id"], secrets["key"]
 72  )
 73  
 74  # Connect to Azure IoT Central
 75  device.connect()
 76  
 77  # Hide the splash screen and show the telemetry values
 78  gfx.show_text()
 79  
 80  while True:
 81      try:
 82          # read moisture level
 83          moisture_level = ss.moisture_read()
 84          # read temperature
 85          temperature = ss.get_temp()
 86          # display soil sensor values on pyportal
 87          gfx.display_moisture(moisture_level)
 88          gfx.display_temp(temperature)
 89  
 90          print("Sending data to Azure")
 91          gfx.display_azure_status("Sending data...")
 92  
 93          # send the temperature and moisture level to Azure
 94          message = {"Temperature": temperature, "MoistureLevel": moisture_level}
 95          device.send_telemetry(json.dumps(message))
 96          device.loop()
 97  
 98          gfx.display_azure_status("Data sent!")
 99          print("Data sent!")
100      except (ValueError, RuntimeError, ConnectionError, OSError) as e:
101          print("Failed to get data, retrying\n", e)
102          wifi.reset()
103          wifi.connect()
104          device.reconnect()
105          continue
106  
107      # Sleep for 10 minutes before getting the next value
108      time.sleep(600)