forked from ajfriesen/ESPHome-AirGradient
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathair-gradient-open-air.yaml
319 lines (287 loc) · 10 KB
/
air-gradient-open-air.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
# Airgradient Open Air Outdoor v1.1 presoldered
#
# @llamagecko, @Hendrik and @spectrumjade from AirGradient forum
# did most of the work for this integration, see the following thread:
# https://forum.airgradient.com/t/outdoor-monitor-esphome-configuration/823
#
substitutions:
id: "1"
devicename: "airgradient-open-air"
# WARNING: upper_devicename is component of SSID which is limited to 32 characters
upper_devicename: "AirGradient Open Air"
esphome:
name: "${devicename}-${id}"
friendly_name: "${upper_devicename} ${id}"
# Automatically add the mac address to the name
# so you can use a single firmware for all devices
# name_add_mac_suffix: true
platform: esp32
board: esp32-c3-devkitm-1
# Enable logging
logger:
baud_rate: 0
# Enable Home Assistant API (API password is deprecated in favor of encryption key)
# https://esphome.io/components/api.html
api:
encryption:
key: !secret home_assistant_encryption_key
ota:
password: !secret ota_password
wifi:
networks:
- ssid: !secret wifi_ssid
password: !secret wifi_password
reboot_timeout: 15min
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "${upper_devicename} Hotspot"
password: !secret fallback_ssid_password
# Used to support POST request to send data to AirGradient
# https://esphome.io/components/http_request.html
http_request:
# Creates a simple web server on the node that can be accessed through any browser
# https://esphome.io/components/web_server.html
web_server:
port: 80
include_internal: true
# The captive portal is a fallback mechanism for when connecting to the configured WiFi fails.
# https://esphome.io/components/captive_portal.html
captive_portal:
# Create a switch for safe_mode in order to flash the device
# Solution from this thread:
# https://community.home-assistant.io/t/esphome-flashing-over-wifi-does-not-work/357352/1
switch:
- platform: safe_mode
name: "Flash Mode (Safe Mode)"
icon: "mdi:cellphone-arrow-down"
button:
- platform: restart
name: "Restart"
disabled_by_default: true
id: button_restart
output:
- platform: gpio
id: watchdog
pin: GPIO2
# Reset hardware watchdog every 5 minutes
interval:
- interval: 5min
then:
- output.turn_on: watchdog
- delay: 20ms
- output.turn_off: watchdog
- interval: 5min
# Send data to AirGradient API server
# for more details have a look at sendToServer() function:
# https://www.airgradient.com/open-airgradient/blog/airgradient-diy-pro-instructions/
then:
- http_request.post:
# AirGradient URL with full MAC address in Hex format all lower case
url: !lambda |-
return "http://hw.airgradient.com/sensors/airgradient:" + get_mac_address() + "/measures";
headers:
Content-Type: application/json
# "!lambda return to_string(id(pm2).state);" Converts sensor output from double to string
body: !lambda |-
String jsonString;
StaticJsonDocument<1024> doc;
doc["wifi"] = id(airgradient_wifi_signal).state;
doc["pm01"] = to_string(id(pm_1_0).state);
doc["pm02"] = to_string(id(pm_2_5).state);
doc["pm10"] = to_string(id(pm_10_0).state);
doc["pm003_count"] = to_string(id(pm_0_3um).state);
doc["atmp"] = to_string(id(temperature).state);
doc["rhum"] = to_string(id(humidity).state);
doc["boot"] = "1";
JsonObject channels = doc.createNestedObject("channels");
JsonObject channels_1 = channels.createNestedObject("1");
channels_1["pm01"] = to_string(id(pm1_1_0).state);
channels_1["pm02"] = to_string(id(pm1_2_5).state);
channels_1["pm10"] = to_string(id(pm1_10_0).state);
channels_1["pm003_count"] = to_string(id(pm1_0_3um).state);
channels_1["atmp"] = to_string(id(pm1_temperature).state);
channels_1["rhum"] = to_string(id(pm1_humidity).state);
JsonObject channels_2 = channels.createNestedObject("2");
channels_2["pm01"] = to_string(id(pm2_1_0).state);
channels_2["pm02"] = to_string(id(pm2_2_5).state);
channels_2["pm10"] = to_string(id(pm2_10_0).state);
channels_2["pm003_count"] = to_string(id(pm2_0_3um).state);
channels_2["atmp"] = to_string(id(pm2_temperature).state);
channels_2["rhum"] = to_string(id(pm2_humidity).state);
// Serialize the JSON document into the string
serializeJson(doc, jsonString);
// Convert String to std::string
std::string stdJsonString(jsonString.c_str());
return stdJsonString;
light:
- platform: status_led
name: "Status LED"
pin: GPIO10
binary_sensor:
- platform: gpio
name: "Button"
pin:
number: GPIO9
inverted: true
mode:
input: true
pullup: true
on_click:
min_length: 5s
then:
- button.press: button_restart
i2c:
sda: GPIO7 # Pin 21
scl: GPIO6 # Pin 20
scan: false
uart:
- id: uart_pm1
baud_rate: 9600
rx_pin: GPIO20 # Pin 30 / RXD0
tx_pin: GPIO21 # Pin 31 / TXD0
- id: uart_pm2
baud_rate: 9600
rx_pin: GPIO0 # Pin 12
tx_pin: GPIO1 # Pin 13
sensor:
- platform: pmsx003
type: PMS5003T
uart_id: uart_pm1
update_interval: 3min # Sensor will go into sleep mode for extended operation lifetime
pm_1_0:
id: pm1_1_0
name: "${upper_devicename} Particulate Matter <1.0µm Concentration (1)"
pm_2_5:
id: pm1_2_5
name: "${upper_devicename} Particulate Matter <2.5µm Concentration (1)"
pm_10_0:
id: pm1_10_0
name: "${upper_devicename} Particulate Matter <10.0µm Concentration (1)"
pm_0_3um:
id: pm1_0_3um
name: "${upper_devicename} Particulate Matter >0.3µm Count (1)"
pm_0_5um:
id: pm1_0_5um
name: "${upper_devicename} Particulate Matter >0.5µm Count (1)"
pm_1_0um:
id: pm1_1_0um
name: "${upper_devicename} Particulate Matter >1.0µm Count (1)"
pm_2_5um:
id: pm1_2_5um
name: "${upper_devicename} Particulate Matter >2.5µm Count (1)"
temperature:
id: pm1_temperature
name: "${upper_devicename} Temperature (1)"
humidity:
id: pm1_humidity
accuracy_decimals: 1
name: "${upper_devicename} Relative Humidity (1)"
- platform: pmsx003
type: PMS5003T
uart_id: uart_pm2
update_interval: 3min # Sensor will go into sleep mode for extended operation lifetime
pm_1_0:
id: pm2_1_0
name: "${upper_devicename} Particulate Matter <1.0µm Concentration (2)"
pm_2_5:
id: pm2_2_5
name: "${upper_devicename} Particulate Matter <2.5µm Concentration (2)"
pm_10_0:
id: pm2_10_0
name: "${upper_devicename} Particulate Matter <10.0µm Concentration (2)"
pm_0_3um:
id: pm2_0_3um
name: "${upper_devicename} Particulate Matter >0.3µm Count (2)"
pm_0_5um:
id: pm2_0_5um
name: "${upper_devicename} Particulate Matter >0.5µm Count (2)"
pm_1_0um:
id: pm2_1_0um
name: "${upper_devicename} Particulate Matter >1.0µm Count (2)"
pm_2_5um:
id: pm2_2_5um
name: "${upper_devicename} Particulate Matter >2.5µm Count (2)"
temperature:
id: pm2_temperature
name: "${upper_devicename} Temperature (2)"
humidity:
id: pm2_humidity
accuracy_decimals: 1
name: "${upper_devicename} Relative Humidity (2)"
# Calculate the average sensor values
- platform: template
id: temperature
name: "${upper_devicename} Temperature"
icon: mdi:home-thermometer-outline
device_class: temperature
accuracy_decimals: 1
unit_of_measurement: "°C"
lambda: return (id(pm1_temperature).state + id(pm2_temperature).state) / 2;
- platform: template
id: humidity
name: "${upper_devicename} Relative Humidity"
icon: mdi:water-percent
device_class: humidity
accuracy_decimals: 1
unit_of_measurement: "%"
lambda: return (id(pm1_humidity).state + id(pm2_humidity).state) / 2;
- platform: template
id: pm_1_0
name: "${upper_devicename} Particulate Matter <1.0µm Concentration"
icon: mdi:chemical-weapon
device_class: pm1
accuracy_decimals: 0
unit_of_measurement: µg/m³
lambda: return (id(pm1_1_0).state + id(pm2_1_0).state) / 2;
- platform: template
id: pm_2_5
name: "${upper_devicename} Particulate Matter <2.5µm Concentration"
icon: mdi:chemical-weapon
device_class: pm25
accuracy_decimals: 0
unit_of_measurement: µg/m³
lambda: return (id(pm1_2_5).state + id(pm2_2_5).state) / 2;
- platform: template
id: pm_10_0
name: "${upper_devicename} Particulate Matter <10.0µm Concentration"
icon: mdi:chemical-weapon
device_class: pm10
accuracy_decimals: 0
unit_of_measurement: µg/m³
lambda: return (id(pm1_10_0).state + id(pm2_10_0).state) / 2;
- platform: template
id: pm_0_3um
name: "${upper_devicename} Particulate Matter >0.3µm Count"
icon: mdi:counter
accuracy_decimals: 0
unit_of_measurement: /dL
lambda: return (id(pm1_0_3um).state + id(pm2_0_3um).state) / 2;
- platform: template
id: pm_0_5um
name: "${upper_devicename} Particulate Matter >0.5µm Count"
icon: mdi:counter
accuracy_decimals: 0
unit_of_measurement: /dL
lambda: return (id(pm1_0_5um).state + id(pm2_0_5um).state) / 2;
- platform: template
id: pm_1_0um
name: "${upper_devicename} Particulate Matter >1.0µm Count"
icon: mdi:counter
accuracy_decimals: 0
unit_of_measurement: /dL
lambda: return (id(pm1_1_0um).state + id(pm2_1_0um).state) / 2;
- platform: template
id: pm_2_5um
name: "${upper_devicename} Particulate Matter >2.5µm Count"
icon: mdi:counter
accuracy_decimals: 0
unit_of_measurement: /dL
lambda: return (id(pm1_2_5um).state + id(pm2_2_5um).state) / 2;
- platform: wifi_signal
name: "Wifi Strength"
id: airgradient_wifi_signal
update_interval: 60s
- platform: uptime
name: "Uptime Sensor"
id: uptime_sensor
update_interval: 60s