Skip to content

Commit 9a2e13b

Browse files
committed
Use packages and github repo
Packages to neatly collect different ESPHome pieces together with a single associated feature, such as the display having fonts, display, pages, switches, and intervals in a single file Reference Github repo, so end users only need a single file to create their entry in ESPHome Also added a full_config folder with the fully expanded config in a single file so it is completely stand-alone, if users desire it
1 parent 9959b62 commit 9a2e13b

10 files changed

+3332
-1537
lines changed

airgradient-basic.yaml

Lines changed: 18 additions & 306 deletions
Original file line numberDiff line numberDiff line change
@@ -1,317 +1,29 @@
11
---
2-
# Reference for substitutions: https://github.com/ajfriesen/ESPHome-AirGradient/blob/main/air-gradient-pro-diy.yaml
2+
# AirGradient DIY Basic
3+
# https://www.airgradient.com/open-airgradient/instructions/overview/
4+
35
substitutions:
46
devicename: "ag-basic"
5-
upper_devicename: "AG Basic"
6-
ag_esphome_config_version: 0.1.1
7-
8-
# Instructions: https://esphome.io/guides/getting_started_hassio.html
9-
esphome:
10-
name: "${devicename}"
11-
friendly_name: "${upper_devicename}"
12-
name_add_mac_suffix: true # Set to false if you don't want part of the MAC address in the name
13-
14-
esp8266:
15-
board: d1_mini
16-
17-
# Enable logging
18-
# https://esphome.io/components/logger.html
19-
logger:
20-
logs:
21-
component: ERROR # Hiding warning messages about component taking a long time https://github.com/esphome/issues/issues/4717
7+
friendly_devicename: "AG Basic"
8+
ag_esphome_config_version: 1.0.0
9+
add_mac_suffix: "true" # Must have quotes around value
2210

2311
# Enable Home Assistant API
24-
api:
12+
api: # Add encryption key as desired
2513

26-
ota:
14+
ota: # Add password as desired
2715

2816
wifi:
2917
# Enable fallback hotspot (captive portal) in case wifi connection fails
3018
ap:
3119

32-
# The captive portal is a fallback mechanism for when connecting to the configured WiFi fails.
33-
# https://esphome.io/components/captive_portal.html
34-
captive_portal:
35-
36-
http_request:
37-
# Used to support POST request to send data to AirGradient
38-
# https://esphome.io/components/http_request.html
39-
40-
switch:
41-
- platform: safe_mode
42-
# Create a switch for safe_mode in order to flash the device
43-
# Solution from this thread:
44-
# https://community.home-assistant.io/t/esphome-flashing-over-wifi-does-not-work/357352/1
45-
name: "Flash Mode (Safe Mode)"
46-
icon: "mdi:cellphone-arrow-down"
47-
48-
- platform: template
49-
name: "Display Temperature in °F"
50-
icon: "mdi:thermometer"
51-
id: display_in_f
52-
restore_mode: RESTORE_DEFAULT_ON
53-
optimistic: True
54-
55-
- platform: template
56-
name: "Upload to AirGradient Dashboard"
57-
id: upload_airgradient
58-
restore_mode: RESTORE_DEFAULT_ON
59-
optimistic: True
60-
61-
uart:
62-
# https://esphome.io/components/uart.html#uart
63-
- rx_pin: D4
64-
tx_pin: D3
65-
baud_rate: 9600
66-
id: senseair_s8_uart
67-
68-
- rx_pin: D5
69-
tx_pin: D6
70-
baud_rate: 9600
71-
id: pms5003_uart
72-
73-
i2c:
74-
sda: D2
75-
scl: D1
76-
77-
sensor:
78-
- platform: pmsx003
79-
# Default interval of updating every second, but using an average over the last 30 seconds/readings
80-
# PMS5003 https://esphome.io/components/sensor/pmsx003.html
81-
type: PMSX003
82-
uart_id: pms5003_uart
83-
pm_2_5:
84-
name: "PM 2.5"
85-
id: pm_2_5
86-
filters:
87-
- sliding_window_moving_average:
88-
window_size: 30
89-
send_every: 30
90-
pm_1_0:
91-
name: "PM 1.0"
92-
id: pm_1_0
93-
filters:
94-
- sliding_window_moving_average:
95-
window_size: 30
96-
send_every: 30
97-
pm_10_0:
98-
name: "PM 10.0"
99-
id: pm_10_0
100-
filters:
101-
- sliding_window_moving_average:
102-
window_size: 30
103-
send_every: 30
104-
pm_0_3um:
105-
name: "PM 0.3"
106-
id: pm_0_3um
107-
filters:
108-
- sliding_window_moving_average:
109-
window_size: 30
110-
send_every: 30
111-
112-
- platform: template
113-
# Depends on another sensor providing an ID of pm_2_5 such as a pms5003
114-
name: "PM 2.5 AQI"
115-
id: pm_2_5_aqi
116-
update_interval: 5 min
117-
unit_of_measurement: "AQI"
118-
icon: "mdi:air-filter"
119-
accuracy_decimals: 0
120-
filters:
121-
- skip_initial: 10 # Need valid data from PM 2.5 sensor before able to calculate
122-
lambda: |-
123-
// https://en.wikipedia.org/wiki/Air_quality_index#Computing_the_AQI
124-
// Borrowed from https://github.com/kylemanna/sniffer/blob/master/esphome/sniffer_common.yaml
125-
if (id(pm_2_5).state <= 12.0) {
126-
// good
127-
return((50.0 - 0.0) / (12.0 - 0.0) * (id(pm_2_5).state - 0.0) + 0.0);
128-
} else if (id(pm_2_5).state <= 35.4) {
129-
// moderate
130-
return((100.0 - 51.0) / (35.4 - 12.1) * (id(pm_2_5).state - 12.1) + 51.0);
131-
} else if (id(pm_2_5).state <= 55.4) {
132-
// usg
133-
return((150.0 - 101.0) / (55.4 - 35.5) * (id(pm_2_5).state - 35.5) + 101.0);
134-
} else if (id(pm_2_5).state <= 150.4) {
135-
// unhealthy
136-
return((200.0 - 151.0) / (150.4 - 55.5) * (id(pm_2_5).state - 55.5) + 151.0);
137-
} else if (id(pm_2_5).state <= 250.4) {
138-
// very unhealthy
139-
return((300.0 - 201.0) / (250.4 - 150.5) * (id(pm_2_5).state - 150.5) + 201.0);
140-
} else if (id(pm_2_5).state <= 350.4) {
141-
// hazardous
142-
return((400.0 - 301.0) / (350.4 - 250.5) * (id(pm_2_5).state - 250.5) + 301.0);
143-
} else if (id(pm_2_5).state <= 500.4) {
144-
// hazardous 2
145-
return((500.0 - 401.0) / (500.4 - 350.5) * (id(pm_2_5).state - 350.5) + 401.0);
146-
} else {
147-
return(500);
148-
}
149-
150-
- platform: senseair
151-
# SenseAir S8 https://esphome.io/components/sensor/senseair.html
152-
# https://senseair.com/products/size-counts/s8-lp/
153-
co2:
154-
name: "SenseAir S8 CO2"
155-
id: co2
156-
filters:
157-
- skip_initial: 2
158-
- clamp:
159-
min_value: 400 # 419 as of 2023-06 https://gml.noaa.gov/ccgg/trends/global.html
160-
id: senseair_s8
161-
uart_id: senseair_s8_uart
162-
163-
# - platform: sht4x
164-
# # SHT40 https://esphome.io/components/sensor/sht4x.html
165-
# temperature:
166-
# name: "Temperature"
167-
# id: temp
168-
# humidity:
169-
# name: "Humidity"
170-
# id: humidity
171-
# address: 0x44
172-
173-
- platform: sht3xd
174-
# SHT30 https://esphome.io/components/sensor/sht3xd.html
175-
temperature:
176-
name: "Temperature"
177-
id: temp
178-
humidity:
179-
name: "Humidity"
180-
id: humidity
181-
address: 0x44
182-
183-
- platform: wifi_signal
184-
name: "WiFi Signal"
185-
id: wifi_dbm
186-
update_interval: 60s
187-
188-
- platform: uptime
189-
name: "Uptime"
190-
id: device_uptime
191-
update_interval: 10s
192-
193-
194-
font:
195-
# Font to use on the display
196-
# Open Source font Liberation Sans by Red Hat
197-
# https://www.dafont.com/liberation-sans.font
198-
- file: './fonts/liberation_sans/LiberationSans-Regular.ttf'
199-
id: font1
200-
size: 24
201-
202-
display:
203-
- platform: ssd1306_i2c
204-
# https://esphome.io/components/display/ssd1306.html?highlight=display
205-
model: "SSD1306 64x48"
206-
id: oled_display
207-
reset_pin: D0
208-
address: 0x3C
209-
# rotation: 180 # Enable to 180 to flip screen around
210-
pages:
211-
- id: display_pm2
212-
lambda: |-
213-
it.print(0, 0, id(font1), "PM2");
214-
it.printf(64, 24, id(font1), TextAlign::TOP_RIGHT, "%.0f",id(pm_2_5).state);
215-
- id: display_co2
216-
lambda: |-
217-
it.print(0, 0, id(font1), "CO2");
218-
it.printf(64, 24, id(font1), TextAlign::TOP_RIGHT, "%.0f",id(co2).state);
219-
# - id: display_temp
220-
# lambda: |-
221-
# it.print(0, 0, id(font1), "°C");
222-
# it.printf(64, 24, id(font1), TextAlign::TOP_RIGHT, "%.1f",id(temp).state);
223-
- id: display_tempf
224-
lambda: |-
225-
it.print(0, 0, id(font1), "°F");
226-
it.printf(64, 24, id(font1), TextAlign::TOP_RIGHT, "%.1f",id(temp).state*9/5+32);
227-
- id: display_humidity
228-
lambda: |-
229-
it.print(0, 0, id(font1), "HUM");
230-
it.printf(64, 24, id(font1), TextAlign::TOP_RIGHT, "%.0f%%",id(humidity).state);
231-
- id: boot
232-
lambda: |-
233-
it.printf(0, 0, id(font1), TextAlign::TOP_RIGHT, "%s", get_mac_address().substr(6,11).c_str());
234-
on_page_change:
235-
to: boot
236-
then:
237-
- if:
238-
# Skip the boot page after initial boot
239-
condition:
240-
lambda: 'return id(device_uptime).state > 30;'
241-
then:
242-
- display.page.show_next: oled_display
243-
- component.update: oled_display
244-
245-
246-
button:
247-
# https://github.com/esphome/issues/issues/2444
248-
- platform: template
249-
name: SenseAir S8 Calibration
250-
id: senseair_s8_calibrate_button
251-
on_press:
252-
then:
253-
- senseair.background_calibration: senseair_s8
254-
- delay: 70s
255-
- senseair.background_calibration_result: senseair_s8
256-
257-
- platform: template
258-
name: SenseAir S8 Enable Automatic Calibration
259-
id: senseair_s8_enable_calibrate_button
260-
on_press:
261-
then:
262-
- senseair.abc_enable: senseair_s8
263-
264-
- platform: template
265-
name: SenseAir S8 Disable Automatic Calibration
266-
id: senseair_s8_disable_calibrate_button
267-
on_press:
268-
then:
269-
- senseair.abc_disable: senseair_s8
270-
271-
- platform: template
272-
name: SenseAir S8 Show Calibration Interval
273-
id: senseair_s8_show_calibrate_interval
274-
on_press:
275-
then:
276-
- senseair.abc_get_period: senseair_s8
277-
278-
interval:
279-
- interval: 5s
280-
# Automatically switch to the next page every five seconds
281-
then:
282-
- if:
283-
# Show boot screen for first 10 seconds with serial number and config version
284-
condition:
285-
lambda: 'return id(device_uptime).state < 10;'
286-
then:
287-
- display.page.show: boot
288-
- lambda: id(device_uptime).set_update_interval(1);
289-
else:
290-
# Change page on display
291-
- display.page.show_next: oled_display
292-
- component.update: oled_display
293-
294-
- interval: 2.5min
295-
# Send data to AirGradient API server
296-
then:
297-
if:
298-
condition:
299-
switch.is_on: upload_airgradient
300-
then:
301-
- http_request.post:
302-
# https://api.airgradient.com/public/docs/api/v1/
303-
# AirGradient URL with the MAC address all lower case
304-
url: !lambda |-
305-
return "http://hw.airgradient.com/sensors/airgradient:" + get_mac_address().substr(6,11) + "/measures";
306-
headers:
307-
Content-Type: application/json
308-
# "!lambda return to_string(id(pm_2_5).state);" Converts sensor output from double to string
309-
json:
310-
wifi: !lambda return to_string(id(wifi_dbm).state);
311-
pm01: !lambda return to_string(id(pm_1_0).state);
312-
pm02: !lambda return to_string(id(pm_2_5).state);
313-
pm10: !lambda return to_string(id(pm_10_0).state);
314-
pm003_count: !lambda return to_string(id(pm_0_3um).state);
315-
rco2: !lambda return to_string(id(co2).state);
316-
atmp: !lambda return to_string(id(temp).state);
317-
rhum: !lambda return to_string(id(humidity).state);
20+
packages:
21+
board: github://MallocArray/airgradient_esphome/packages/airgradient_d1_mini_board.yaml
22+
pm_2.5: github://MallocArray/airgradient_esphome/packages/sensor_pms5003.yaml
23+
co2: github://MallocArray/airgradient_esphome/packages/sensor_s8.yaml
24+
temp_humidity: github://MallocArray/airgradient_esphome/packages/sensor_sht30.yaml
25+
display: github://MallocArray/airgradient_esphome/packages/display_ssd1306.yaml
26+
airgradient_api: github://MallocArray/airgradient_esphome/packages/airgradient_api_d1_mini_no_sgp41.yaml
27+
wifi: github://MallocArray/airgradient_esphome/packages/sensor_wifi.yaml
28+
uptime: github://MallocArray/airgradient_esphome/packages/sensor_uptime.yaml
29+
safe_mode: github://MallocArray/airgradient_esphome/packages/switch_safe_mode.yaml

0 commit comments

Comments
 (0)