code.py
  1  # SPDX-FileCopyrightText: 2019 Dave Astels for Adafruit Industries
  2  #
  3  # SPDX-License-Identifier: MIT
  4  
  5  """
  6  IoT environmental sensor node.
  7  
  8  Adafruit invests time and resources providing this open source code.
  9  Please support Adafruit and open source hardware by purchasing
 10  products from Adafruit!
 11  
 12  Written by Dave Astels for Adafruit Industries
 13  Copyright (c) 2019 Adafruit Industries
 14  Licensed under the MIT license.
 15  
 16  All text above must be included in any redistribution.
 17  """
 18  
 19  import time
 20  import board
 21  import busio
 22  import air_quality
 23  import gps
 24  import adafruit_bme280
 25  import aio
 26  import adafruit_logging as logging
 27  
 28  logger = logging.getLogger('main')
 29  if not logger.hasHandlers():
 30      logger.addHandler(logging.StreamHandler())
 31  logger.setLevel(logging.INFO)
 32  
 33  gps_uart = busio.UART(board.TX, board.RX, baudrate=9600, timeout=3.000)
 34  gps_interface = gps.Gps(gps_uart)
 35  gps_interface.begin()
 36  
 37  logger.debug('GPS started')
 38  
 39  aio_interface = aio.AIO()
 40  
 41  if aio_interface.onboard_esp:
 42      air_uart = busio.UART(board.D5, board.D7, baudrate=9600)
 43  else:
 44      air_uart = busio.UART(board.A2, board.A3, baudrate=9600)
 45  air = air_quality.AirQualitySensor(air_uart)
 46  
 47  logger.debug('Air quality sensor started')
 48  
 49  i2c = busio.I2C(board.SCL, board.SDA)
 50  bme280 = adafruit_bme280.Adafruit_BME280_I2C(i2c)
 51  
 52  reading_interval = 300.0
 53  reading_time = time.monotonic()
 54  
 55  time_update_interval = 3600.0
 56  time_update_time = time.monotonic()
 57  
 58  logger.info('Getting data from GPS')
 59  
 60  while True:
 61      if gps_interface.get_fix():
 62          break
 63      logger.error('Failed getting fix... retrying')
 64  
 65  gps_interface.read()
 66  
 67  logger.info('Starting reading loop')
 68  
 69  payload = {'value' : 0,
 70             'lat' : gps_interface.latitude,
 71             'lon' : gps_interface.longitude,
 72             'created_at' : ''}
 73  
 74  while True:
 75      now = time.monotonic()
 76  
 77      if now >= time_update_time:
 78          time_update_time = now + time_update_interval
 79          logger.info('refreshing time')
 80          try:
 81              aio_interface.refresh_local_time()
 82          except RuntimeError as e:
 83              logger.debug('Time refresh failed with: %s', str(e))
 84  
 85      if now >= reading_time:
 86          reading_time = now + reading_interval
 87          logger.info('Taking a reading')
 88  
 89          st = time.localtime()
 90          timestamp = '{0}/{1:02}/{2:02} {3:2}:{4:02}:{5:02}'.format(st.tm_year,
 91                                                                     st.tm_mon,
 92                                                                     st.tm_mday,
 93                                                                     st.tm_hour,
 94                                                                     st.tm_min,
 95                                                                     st.tm_sec)
 96          payload['created_at'] = timestamp
 97  
 98          if air.read():
 99              logger.info('Air Quality pm10 standard: %d', air.pm10_standard)
100              payload['value'] = air.pm10_standard
101              if not aio_interface.post('environmental-sensor.pm10-std', payload):
102                  logger.critical('post of pm10 standard failed')
103                  continue
104  
105              logger.info('Air Quality pm25 standard: %d', air.pm25_standard)
106              payload['value'] = air.pm25_standard
107              if not aio_interface.post('environmental-sensor.pm25-std', payload):
108                  logger.critical('post of pm25 standard failed')
109                  continue
110  
111              logger.info('Air Quality pm100 standard: %d', air.pm100_standard)
112              payload['value'] = air.pm100_standard
113              if not aio_interface.post('environmental-sensor.pm100-std', payload):
114                  logger.critical('post of pm100 standard failed')
115                  continue
116  
117              logger.info('Air Quality pm10 env: %d', air.pm10_env)
118              payload['value'] = air.pm10_env
119              if not aio_interface.post('environmental-sensor.pm10-env', payload):
120                  logger.critical('post of pm10 env failed')
121                  continue
122  
123              logger.info('Air Quality pm25 env: %d', air.pm25_env)
124              payload['value'] = air.pm25_env
125              if not aio_interface.post('environmental-sensor.pm25-env', payload):
126                  logger.critical('post of pm10 env failed')
127                  continue
128  
129              logger.info('Air Quality pm100 env: %d', air.pm100_env)
130              payload['value'] = air.pm100_env
131              if not aio_interface.post('environmental-sensor.pm100-env', payload):
132                  logger.critical('post of pm100 env failed')
133                  continue
134  
135              logger.info('Air Quality particles 03um: %d', air.particles_03um)
136              payload['value'] = air.particles_03um
137              if not aio_interface.post('environmental-sensor.03um', payload):
138                  logger.critical('post of particles 03um failed')
139                  continue
140  
141              logger.info('Air Quality particles 05um: %d', air.particles_05um)
142              payload['value'] = air.particles_05um
143              if not aio_interface.post('environmental-sensor.05um', payload):
144                  logger.critical('post of particles 05um failed')
145                  continue
146  
147              logger.info('Air Quality particles 10um: %d', air.particles_10um)
148              payload['value'] = air.particles_10um
149              if not aio_interface.post('environmental-sensor.10um', payload):
150                  logger.critical('post of particles 10um failed')
151                  continue
152  
153              logger.info('Air Quality particles 25um: %d', air.particles_25um)
154              payload['value'] = air.particles_25um
155              if not aio_interface.post('environmental-sensor.25um', payload):
156                  logger.critical('post of particles 25um failed')
157                  continue
158  
159              logger.info('Air Quality particles 50um: %d', air.particles_50um)
160              payload['value'] = air.particles_50um
161              if not aio_interface.post('environmental-sensor.50um', payload):
162                  logger.critical('post of particles 50um failed')
163                  continue
164  
165              logger.info('Air Quality particles 100um: %d', air.particles_100um)
166              payload['value'] = air.particles_100um
167              if not aio_interface.post('environmental-sensor.100um', payload):
168                  logger.critical('post of particles 100um failed')
169                  continue
170  
171          logger.info('Temperature: %f', bme280.temperature)
172          payload['value'] = bme280.temperature
173          if not aio_interface.post('environmental-sensor.temperature', payload):
174              logger.critical('post of temperature failed')
175              continue
176  
177          logger.info('Humidity: %f', bme280.humidity)
178          payload['value'] = bme280.humidity
179          if not aio_interface.post('environmental-sensor.humidity', payload):
180              logger.critical('post of humidity failed')
181              continue
182  
183          logger.info('Pressure: %f', bme280.pressure)
184          payload['value'] = bme280.pressure
185          if not aio_interface.post('environmental-sensor.pressure', payload):
186              logger.critical('post of pressure failed')
187              continue
188  
189          logger.info('Waiting for next reading')