2
2
import board
3
3
import busio
4
4
from digitalio import DigitalInOut , Direction , Pull
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
+
5
12
from simpleio import map_range
13
+
6
14
import adafruit_pm25
7
15
import adafruit_bme280
8
16
17
+ ### WiFi ###
18
+
19
+ # Get wifi details and more from a secrets.py file
20
+ try :
21
+ from secrets import secrets
22
+ except ImportError :
23
+ print ("WiFi secrets are kept in secrets.py, please add them there!" )
24
+ raise
25
+
26
+ # If you have an externally connected ESP32:
27
+ esp32_cs = DigitalInOut (board .D13 )
28
+ esp32_reset = DigitalInOut (board .D12 )
29
+ esp32_ready = DigitalInOut (board .D11 )
30
+
31
+ spi = busio .SPI (board .SCK , board .MOSI , board .MISO )
32
+ esp = adafruit_esp32spi .ESP_SPIcontrol (spi , esp32_cs , esp32_ready , esp32_reset )
33
+ status_light = dotstar .DotStar (board .APA102_SCK , board .APA102_MOSI , 1 , brightness = 0.2 )
34
+ wifi = adafruit_esp32spi_wifimanager .ESPSPI_WiFiManager (esp , secrets , status_light )
35
+
9
36
10
37
# Connect to a PM2.5 sensor over UART
11
38
uart = busio .UART (board .TX , board .RX , baudrate = 9600 )
15
42
i2c = busio .I2C (board .SCL , board .SDA )
16
43
bme280 = adafruit_bme280 .Adafruit_BME280_I2C (i2c )
17
44
45
+ ### MiniMQTT Callback Functions ###
46
+ def connected (client ):
47
+ # Connected function will be called when the client is connected to Adafruit IO.
48
+ # This is a good place to subscribe to feed changes. The client parameter
49
+ # passed to this function is the Adafruit IO MQTT client so you can make
50
+ # calls against it easily.
51
+ print ("Connected to Adafruit IO!" )
52
+
53
+ # Subscribe to Group
54
+ io .subscribe (group_key = group_name )
55
+
56
+ # pylint: disable=unused-argument
57
+ def disconnected (client ):
58
+ # Disconnected function will be called when the client disconnects.
59
+ print ("Disconnected from Adafruit IO!" )
60
+
61
+ ### Sensor Functions ###
18
62
def calculate_aqi (pm_sensor_reading ):
19
63
"""Returns a calculated air quality index (AQI)
20
64
and category as a tuple.
@@ -28,30 +72,30 @@ def calculate_aqi(pm_sensor_reading):
28
72
if 0.0 <= pm_sensor_reading <= 12.0 :
29
73
# AQI calculation using EPA breakpoints (Ilow-IHigh)
30
74
aqi = map_range (int (pm_sensor_reading ), 0 , 12 , 0 , 50 )
31
- aqi_condition = "Good"
75
+ aqi_category = "Good"
32
76
elif 12.1 <= pm_sensor_reading <= 35.4 :
33
77
aqi = map_range (int (pm_sensor_reading ), 12 , 35 , 51 , 100 )
34
- aqi_condition = "Moderate"
78
+ aqi_category = "Moderate"
35
79
elif 35.5 <= pm_sensor_reading <= 55.4 :
36
80
aqi = map_range (int (pm_sensor_reading ), 36 , 55 , 101 , 150 )
37
- aqi_condition = "Unhealthy for Sensitive Groups"
81
+ aqi_category = "Unhealthy for Sensitive Groups"
38
82
elif 55.5 <= pm_sensor_reading <= 150.4 :
39
83
aqi = map_range (int (pm_sensor_reading ), 56 , 150 , 151 , 200 )
40
- aqi_condition = "Unhealthy"
84
+ aqi_category = "Unhealthy"
41
85
elif 150.5 <= pm_sensor_reading <= 250.4 :
42
86
aqi = map_range (int (pm_sensor_reading ), 151 , 250 , 201 , 300 )
43
- aqi_condition = "Very Unhealthy"
87
+ aqi_category = "Very Unhealthy"
44
88
elif 250.5 <= pm_sensor_reading <= 350.4 :
45
89
aqi = map_range (int (pm_sensor_reading ), 251 , 350 , 301 , 400 )
46
- aqi_condition = "Hazardous"
90
+ aqi_category = "Hazardous"
47
91
elif 350.5 <= pm_sensor_reading <= 500.4 :
48
92
aqi = map_range (int (pm_sensor_reading ), 351 , 500 , 401 , 500 )
49
- aqi_condition = "Hazardous"
93
+ aqi_category = "Hazardous"
50
94
else :
51
95
print ("Invalid PM2.5 concentration" )
52
96
aqi = - 1
53
- aqi_condition = None
54
- return aqi , aqi_condition
97
+ aqi_category = None
98
+ return aqi , aqi_category
55
99
56
100
def sample_aq_sensor ():
57
101
"""Samples PM2.5 sensor
@@ -93,16 +137,65 @@ def read_bme280(is_celsius=False):
93
137
temperature = temperature * 1.8 + 32
94
138
return temperature , humidity
95
139
140
+ ### CODE ###
141
+
142
+ # Connect to WiFi
143
+ print ("Connecting to WiFi..." )
144
+ wifi .connect ()
145
+ print ("Connected!" )
146
+
147
+ # Initialize MQTT interface with the esp interface
148
+ MQTT .set_socket (socket , esp )
149
+
150
+ # Initialize a new MQTT Client object
151
+ mqtt_client = MQTT .MQTT (
152
+ broker = "io.adafruit.com" , username = secrets ["aio_user" ], password = secrets ["aio_key" ],
153
+ )
154
+
155
+
156
+ # Initialize an Adafruit IO MQTT Client
157
+ io = IO_MQTT (mqtt_client )
158
+
159
+ # Connect the callback methods defined above to Adafruit IO
160
+ io .on_connect = connected
161
+ io .on_disconnect = disconnected
162
+
163
+ # Connect to Adafruit IO
164
+ print ("Connecting to Adafruit IO..." )
165
+ io .connect ()
166
+
167
+ # Subscribe to the air quality sensor group
168
+ group_air_quality = "air-quality-sensor"
169
+ io .subscribe (group_key = group_air_quality )
170
+
171
+ # Feeds within the air quality sensor group
172
+ # Temperature
173
+ feed_temp = group_air_quality + ".temperature"
174
+ # Humidity
175
+ feed_humid = group_air_quality + ".humidity"
176
+ # Air quality index (AQI)
177
+ feed_aqi = group_air_quality + ".aqi"
178
+ # Air quality index category
179
+ feed_aqi_category = group_air_quality + ".category"
96
180
97
181
98
182
while True :
99
- # TODO: Sample every 10min.
100
- # Air Quality
183
+ try :
184
+ # Keep device connected to io.adafruit.com
185
+ # and process any incoming data.
186
+ io .loop ()
187
+ # TODO: read every 10min
188
+ # air quality
101
189
aqi_reading = sample_aq_sensor ()
102
- aqi_index , aqi_condition = calculate_aqi (aqi_reading )
103
- print ("AQI: %d" % aqi_index )
104
- print ("Condition : %s" % aqi_condition )
190
+ aqi , aqi_category = calculate_aqi (aqi_reading )
191
+ print ("AQI: %d" % aqi )
192
+ print ("category : %s" % aqi_category )
105
193
# temp and humidity
106
194
temperature , humidity = read_bme280 ()
107
195
print ("Temperature: %0.1f F" % temperature )
108
196
print ("Humidity: %0.1f %%" % humidity )
197
+ except (ValueError , RuntimeError ) as e :
198
+ print ("Failed to get data, retrying\n " , e )
199
+ wifi .reset ()
200
+ io .reconnect ()
201
+ continue
0 commit comments