|
3 | 3 | import busio
|
4 | 4 | from digitalio import DigitalInOut, Direction, Pull
|
5 | 5 | import adafruit_dotstar as dotstar
|
6 |
| -from adafruit_esp32spi import adafruit_esp32spi |
7 |
| -from adafruit_esp32spi import adafruit_esp32spi_wifimanager |
8 |
| -import adafruit_esp32spi.adafruit_esp32spi_socket as socket |
9 |
| -import adafruit_minimqtt.adafruit_minimqtt as MQTT |
10 |
| -from adafruit_io.adafruit_io import IO_MQTT |
11 |
| -from adafruit_io.adafruit_io_errors import AdafruitIO_MQTTError |
| 6 | +from adafruit_esp32spi import adafruit_esp32spi, adafruit_esp32spi_wifimanager |
| 7 | +from adafruit_io.adafruit_io import IO_HTTP, AdafruitIO_RequestError |
12 | 8 | from simpleio import map_range
|
13 | 9 |
|
14 | 10 | import adafruit_pm25
|
|
34 | 30 | status_light = dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, 1, brightness=0.2)
|
35 | 31 | wifi = adafruit_esp32spi_wifimanager.ESPSPI_WiFiManager(esp, secrets, status_light)
|
36 | 32 |
|
37 |
| - |
38 | 33 | # Connect to a PM2.5 sensor over UART
|
39 | 34 | uart = busio.UART(board.TX, board.RX, baudrate=9600)
|
40 | 35 | pm25 = adafruit_pm25.PM25_UART(uart)
|
|
43 | 38 | i2c = busio.I2C(board.SCL, board.SDA)
|
44 | 39 | bme280 = adafruit_bme280.Adafruit_BME280_I2C(i2c)
|
45 | 40 |
|
46 |
| -### MiniMQTT Callback Functions ### |
47 |
| -def connected(client): |
48 |
| - # Connected function will be called when the client is connected to Adafruit IO. |
49 |
| - # This is a good place to subscribe to feed changes. The client parameter |
50 |
| - # passed to this function is the Adafruit IO MQTT client so you can make |
51 |
| - # calls against it easily. |
52 |
| - print("Connected to Adafruit IO!") |
53 |
| - |
54 |
| -# pylint: disable=unused-argument |
55 |
| -def disconnected(client): |
56 |
| - # Disconnected function will be called when the client disconnects. |
57 |
| - print("Disconnected from Adafruit IO!") |
58 |
| - |
59 |
| -def message(client, topic, message): |
60 |
| - pass |
61 |
| - |
62 |
| -def on_new_time(client, topic, message): |
63 |
| - """Obtains new time from Adafruit IO time service |
64 |
| - and parses the current_hour/current_minute |
65 |
| - """ |
66 |
| - global current_hour, current_minute |
67 |
| - current_time = message.split("-")[2].split("T")[1] |
68 |
| - current_time = current_time.split(".")[0] |
69 |
| - current_hour = int(current_time.split(":")[0]) |
70 |
| - current_minute = int(current_time.split(":")[1]) |
71 |
| - |
72 |
| - |
73 |
| - |
74 | 41 | ### Sensor Functions ###
|
75 | 42 | def calculate_aqi(pm_sensor_reading):
|
76 | 43 | """Returns a calculated air quality index (AQI)
|
@@ -151,127 +118,68 @@ def read_bme280(is_celsius=False):
|
151 | 118 | return temperature, humidity
|
152 | 119 |
|
153 | 120 |
|
154 |
| -### CODE ### |
155 |
| - |
156 |
| -# Connect to WiFi |
157 |
| -print("Connecting to WiFi...") |
158 |
| -wifi.connect() |
159 |
| -print("Connected!") |
160 |
| - |
161 |
| -# Initialize MQTT interface with the esp interface |
162 |
| -MQTT.set_socket(socket, esp) |
163 |
| - |
164 |
| -# Initialize a new MQTT Client object |
165 |
| -mqtt_client = MQTT.MQTT( |
166 |
| - broker="io.adafruit.com", username=secrets["aio_user"], password=secrets["aio_key"], |
167 |
| -) |
| 121 | +# Create an instance of the Adafruit IO HTTP client |
| 122 | +io = IO_HTTP(secrets['aio_user'], secrets['aio_key'], wifi) |
168 | 123 |
|
169 |
| -# Initialize an Adafruit IO MQTT Client |
170 |
| -io = IO_MQTT(mqtt_client) |
| 124 | +# Describes feeds used to hold Adafruit IO data |
| 125 | +feed_aqi = io.get_feed("air-quality-sensor.aqi") |
| 126 | +feed_aqi_category = io.get_feed("air-quality-sensor.category") |
| 127 | +feed_humidity = io.get_feed("air-quality-sensor.humidity") |
| 128 | +feed_temperature = io.get_feed("air-quality-sensor.temperature") |
171 | 129 |
|
172 |
| -# Connect the callback methods defined above to Adafruit IO |
173 |
| -io.on_connect = connected |
174 |
| -io.on_disconnect = disconnected |
175 |
| -io.on_message = message |
176 |
| - |
177 |
| -# Connect to Adafruit IO |
178 |
| -print("Connecting to Adafruit IO...") |
179 |
| -io.connect() |
180 |
| - |
181 |
| -# Subscribe to the air quality sensor group |
182 |
| -group_air_quality = "air-quality-sensor" |
183 |
| -io.subscribe(group_key=group_air_quality) |
184 |
| - |
185 |
| -# Feeds within the air quality sensor group |
186 |
| -# Temperature |
187 |
| -feed_temp = group_air_quality + ".temperature" |
188 |
| -# Humidity |
189 |
| -feed_humid = group_air_quality + ".humidity" |
190 |
| -# Air quality index (AQI) |
191 |
| -feed_aqi = group_air_quality + ".aqi" |
192 |
| -# Air quality index category |
193 |
| -feed_aqi_category = group_air_quality + ".category" |
194 | 130 |
|
195 | 131 | # Set up location metadata
|
196 |
| -# TODO: Use secrets.py |
| 132 | +# TODO: Use secrets.py instead! |
197 | 133 | location_metadata = "40.726190, -74.005334, -6"
|
198 | 134 |
|
199 |
| -# Call on_new_time to update the time from Adafruit IO |
200 |
| -io._client.add_topic_callback("time/ISO-8601", on_new_time) |
201 |
| -# Subscribe to the Adafruit IO UTC time service |
202 |
| -io.subscribe_to_time("ISO-8601") |
203 |
| - |
204 |
| -initial_time = time.monotonic() |
205 |
| - |
206 |
| -current_hour = 0 |
207 |
| -current_minute = 0 |
208 |
| -prv_hour = 0 |
209 |
| -prv_minute = 0 |
210 |
| -time_elapsed = 0 |
211 |
| - |
212 |
| -average_aqi = 0 |
| 135 | +elapsed_minutes = 0 |
| 136 | +prv_mins = 0 |
| 137 | +aqi_readings = 0 |
213 | 138 |
|
214 | 139 | while True:
|
215 |
| - try: |
216 |
| - # Keep device connected to io.adafruit.com |
217 |
| - # and process any incoming data. |
218 |
| - io.loop() |
219 |
| - except (ValueError, RuntimeError, AdafruitIO_MQTTError) as e: |
220 |
| - print("Failed to get data, retrying\n", e) |
221 |
| - wifi.reset() |
222 |
| - wifi.connect() |
223 |
| - io.reconnect() |
224 |
| - continue |
225 |
| - |
226 |
| - # Check current time against io.adafruit time service |
227 |
| - if (current_hour - prv_hour >= 1): |
228 |
| - print("new hour!") |
229 |
| - # Reset prv_hour |
230 |
| - prv_hour = current_hour |
231 |
| - io.publish(feed_temp, current_minute) |
232 |
| - time_elapsed = True |
233 |
| - elif (current_minute - prv_minute >= 1): |
234 |
| - print("new 1m increment!") |
235 |
| - print(current_minute) |
236 |
| - # Reset prv_minute |
237 |
| - prv_minute = int(current_minute) |
238 |
| - io.publish(feed_temp, current_minute) |
239 |
| - time_elapsed = True |
240 |
| - elif current_minute % 10 == 0: |
241 |
| - print("new 10m increment!") |
242 |
| - # Reset prv_minute |
243 |
| - prv_minute = int(current_minute) |
244 |
| - io.publish(feed_temp, current_minute) |
245 |
| - time_elapsed = True |
246 |
| - else: |
247 |
| - # no difference in current time |
248 |
| - continue |
| 140 | + print("Obtaining time") |
| 141 | + try: |
| 142 | + cur_time = io.receive_time() |
| 143 | + # print(cur_time) |
| 144 | + except (ValueError, RuntimeError) as e: |
| 145 | + print("Failed to get data, retrying\n", e) |
| 146 | + wifi.reset() |
| 147 | + continue |
249 | 148 |
|
250 |
| - if time_elapsed: |
251 |
| - aqi_reading = sample_aq_sensor() |
252 |
| - aqi, aqi_category = calculate_aqi(aqi_reading) |
253 |
| - # Average AQI readings over amount of readings |
254 |
| - if current_minute > 0: |
255 |
| - average_aqi += aqi |
256 |
| - average_aqi /= current_minute |
| 149 | + if cur_time[4] > prv_mins: |
| 150 | + print("%d min elapsed.."%elapsed_minutes) |
| 151 | + # Sample the AQI every minute |
| 152 | + aqi_readings += sample_aq_sensor() |
| 153 | + prv_mins = cur_time[4] |
| 154 | + elapsed_minutes += 1 |
| 155 | + |
| 156 | + if elapsed_minutes >= 10: |
| 157 | + print("Sampling AQI...") |
| 158 | + # Average AQI over 10 individual readings |
| 159 | + aqi_readings /= 10 |
| 160 | + aqi, aqi_category = calculate_aqi(aqi_readings) |
| 161 | + print("AQI: %d"%aqi) |
| 162 | + print("Category: %s"%aqi_category) |
| 163 | + |
| 164 | + # temp and humidity |
| 165 | + print("Sampling environmental sensor...") |
| 166 | + temperature, humidity = read_bme280() |
| 167 | + print("Temperature: %0.1f F" % temperature) |
| 168 | + print("Humidity: %0.1f %%" % humidity) |
| 169 | + # TODO: Publish all values to Adafruit IO |
257 | 170 |
|
258 |
| - print("AQI: %d"%aqi) |
259 |
| - print("Category: %s"%aqi_category) |
| 171 | + try: |
| 172 | + io.send_data(feed_aqi["key"], str(aqi)) |
| 173 | + io.send_data(feed_aqi_category["key"], aqi_category) |
| 174 | + io.send_data(feed_temperature["key"], str(temperature)) |
| 175 | + io.send_data(feed_humidity["key"], str(humidity)) |
| 176 | + except (ValueError, RuntimeError) as e: |
| 177 | + print("Failed to get data, retrying\n", e) |
| 178 | + wifi.reset() |
| 179 | + continue |
260 | 180 |
|
261 |
| - # temp and humidity |
262 |
| - temperature, humidity = read_bme280() |
263 |
| - print("Temperature: %0.1f F" % temperature) |
264 |
| - print("Humidity: %0.1f %%" % humidity) |
265 | 181 |
|
266 |
| - # Publish to IO |
267 |
| - print("Publishing to Adafruit IO...") |
268 |
| - # TODO: These need to be within a try/except block |
269 |
| - io.publish(feed_aqi, int(aqi), location_metadata) |
270 |
| - io.publish(feed_aqi_category, aqi_category) |
271 |
| - io.publish(feed_humid, humidity) |
272 |
| - io.publish(feed_temp, temperature) |
273 |
| - print("Published!") |
274 |
| - # Reset time_elapsed |
275 |
| - time_elapsed = False |
| 182 | + # Reset timer |
| 183 | + elapsed_minutes = 0 |
| 184 | + time.sleep(30) |
276 | 185 |
|
277 |
| - time.sleep(60) |
0 commit comments