View difference between Paste ID: Erwq1cdh and NsW8fLTL
SHOW: | | - or go back to the newest paste.
1
# The Variables for this device are here AND in the secrets file!
2
substitutions:
3
  device_name_friendly: 'Kamer'
4
  device_name: 'kamer' #DNS NAME!
5
#More changes after here required.
6
7
esphome:
8
  name: ${device_name}
9
  platform: ESP32
10
  board: mhetesp32minikit
11
  on_boot: #For fun let the light transition trough random colours when booting
12
  #  - light.turn_on:
13
  #      id: rgblicht
14
  #      brightness: 100%
15
  #      red: 0%
16
  #      green: 0%
17
  #      blue: 100%
18
  #  - delay: 1s
19
  #  - light.control:
20
  #      id: rgblicht
21
  #      effect: "Random Effect"
22
  #  - delay: 10s
23
  #  - light.control:
24
  #      id: rgblicht
25
  #      effect: "none"
26
    - if: #Turn off the screen after booting if microwave and pir sensor don't see motion. 
27
        condition:
28
          and:
29
            - binary_sensor.is_off: microwave
30
            - binary_sensor.is_off: pir
31
        then:
32
          - lambda: id(scherm).turn_off();
33
34
wifi:
35
  ssid: !secret wifi_ssid_iot
36
  password: !secret wifi_password_iot
37
  #fast_connect: true #probably not necessary
38
  #reboot_timeout: 45min #probably not necessary
39
  # power_save_mode: none #fixed regular disconnects causing sensor data to be 'unavailable'. No longer necessar
40
  # Optional manual IP
41
  manual_ip:
42
    static_ip: 192.168.0.25 #Necessary to be able to read the logs and update the device over wifi rather than using an USB cable
43
    gateway: 92.168.0.1 #probably not necessary
44
    subnet: 255.255.255.0 #probably not necessary
45
  #  dns1: 195.130.130.1 #probably not necessary
46
  #  dns2: 195.130.131.1 #probably not necessary
47
48
49
  # Enable fallback hotspot (captive portal) in case wifi connection fails
50
  #ap:
51
  #  ssid: '${device_name_friendly}Fallback'
52
  #  password: !secret wifi_fallback_password
53
54
#captive_portal:
55
56
# Enable logging
57
#logger:
58
#  level: DEBUG
59
  # level: VERY_VERBOSE I can only get the CO2 sensor manual calibration to work in very verbose mode
60
61
# Enable Home Assistant API
62
api:
63
  password: !secret esphome_local
64
65
ota:
66
  password: !secret esphome_local
67
68
esp32_ble_tracker: #required to activate the bluetooth low energy tracker. Which is needed for the Xiaomi Smart Scale integration and for bluetooth_proxy
69
bluetooth_proxy: #Home Assistant can expand its Bluetooth reach by communicating through the Bluetooth proxy component in ESPHome
70
71
light:
72
  - platform: fastled_clockless
73
    chipset: WS2812
74
    pin: GPIO23
75
    num_leds: 1
76
    rgb_order: GRB
77
    name: '${device_name_friendly} RGB LED'
78
    id: rgblicht
79
    effects:
80
      - random:
81
          name: "Random Effect"
82
          transition_length: 1s
83
          update_interval: 1s
84
85
  # Define pins to be used on the ESP32 for UART which is used by the senseair platform to provide the data
86
uart:
87
  rx_pin: GPIO16
88
  tx_pin: GPIO17
89
  baud_rate: 9600
90
91
# setup ic bus
92
i2c:
93
  sda: 21
94
  scl: 22
95
  scan: True
96
  id: bus_a #Probably not necessary
97
98
sensor:
99
  # - platform: wifi_signal
100
  #   name: '${device_name_friendly} WiFi Signal'
101
  #   update_interval: 60s
102
  - platform: bh1750 #setup illuminance sensor
103
    id: luminosity
104
    name: '${device_name_friendly} illuminance'
105
    address: 0x23
106
    #measurement_duration: 254 #Higher value allows to measure darker scenes and probably also more accurate but reduces Max range. No longer an option as it is now calculated dynamically
107
    filters:
108
      - delta : 0.5 
109
    update_interval: 5s
110
    on_value:
111
      then:
112
        - light.turn_on:
113
            id: rgblicht
114
            brightness: !lambda |-
115
              //sets the brightness of the LED based on luminosity sensor. 0LUX sets brightness to 20% (below that my LED flickers) while 200LUX or higher sets brightness to 100%
116
              static float brightness_intense = 0.0;
117
              static float brightness_max = 1.0;
118
              static float brightness_min = 0.0;
119
              brightness_intense = (x / 250.0) + 0.2;
120
              brightness_intense = clamp(brightness_intense,brightness_min,brightness_max);
121
              return brightness_intense;
122
  - platform: aht10 #setup temperature & humidity sensor. 
123
    temperature:
124
      id: '${device_name}temp'
125
      name: "${device_name_friendly} Temperature"
126
      filters:
127
        - offset: +0.5
128
        - delta : 0.25
129
    humidity:
130
      id: '${device_name}hum'
131
      name: "${device_name_friendly} Humidity"
132
      filters:
133
        - offset: -4.0
134
        - delta : 0.5
135
    update_interval: 5s
136
  - platform: senseair #Setup the sensair sensor
137
    id: '${device_name}CO2'
138
    co2:
139
      name: '${device_name_friendly} CO2'
140
      id: '${device_name}co2state'
141
      on_value:
142
        then:
143
          - light.turn_on:
144
              id: rgblicht
145
              state: on
146
              # brightness: 100% #Already defined this based on luminosity sensor
147
# Objective: 400ppm=Green; 900ppm=Yellow; 1200ppm=Red with transitions in between
148
# -->Between 400ppm and 900ppm Red should gradually increase from 0 to 1: Formula: (X-400)/(900-400) & clamp function will restrict result to be between 0 and 1.
149
# -->Between 900ppm and 1200ppm Green should gradually decrease from 1 to 0: Formula: 1-(X-900)/(1200-900) & clamp function will restrict result to be between 0 and 1.
150
              red: !lambda |-
151
                static float red_intense = 0.0;
152
                static float red_max = 1.0;
153
                static float red_min = 0.0;
154
                ESP_LOGD("main", "Input Number is: %f", x);
155
                red_intense = ((x-400.0) / 500.0);
156
                ESP_LOGD("main", "Red Number is: %f", red_intense);
157
                red_intense = clamp(red_intense,red_min,red_max);
158
                ESP_LOGD("main", "Red Number clamped is: %f", red_intense);
159
                return red_intense;
160
              green: !lambda |-
161
                static float green_intense = 0.0;
162
                static float green_max = 1.0;
163
                static float green_min = 0.0;
164
                ESP_LOGD("main", "Input Number is: %f", x);
165
                green_intense = (1 - (x-900.0) / 300.0);
166
                ESP_LOGD("main", "Green Number is: %f", green_intense);
167
                green_intense = clamp(green_intense,green_min,green_max);
168
                ESP_LOGD("main", "Green Number clamped is: %f", green_intense);
169
                return green_intense;
170
              blue: 0.0
171
      filters:
172
        - delta : 4.0 #only send the result if the parts per million difference with the last sent result is higher than this
173
    update_interval: 4s #delta filter above will prevent too many updates 
174
  - platform: homeassistant #Get value of my outdoor temperature sensor from home assistant
175
    id: outdoor_temperature
176
    entity_id: sensor.temperature_buiten
177
    internal: true
178
      
179
binary_sensor:
180
  - platform: gpio #Microwave technology motion sensor
181
    pin: GPIO36
182
    name: '${device_name_friendly} Microwave'
183
    id: microwave
184
    internal: true #Don't expose this sensor to Home Assistant
185
    device_class: motion
186
    on_state: #turns on the OLED display if microwave motion is detected and turns it off 15 seconds after PIR and Microwave sensors stop detecting motion
187
      then:
188
        - if:
189
            condition:
190
              - binary_sensor.is_on: microwave
191
            then:
192
              - lambda: id(scherm).turn_on();
193
            else: #The microwave sensor is not detecting motion (anymore)
194
              - wait_until: #This will stop waiting after 15 seconds or as soon as motion is detected. 
195
                  condition:
196
                    or:
197
                      - binary_sensor.is_on: microwave
198
                      - binary_sensor.is_on: pir
199
                  timeout: 15s
200
              - if: #If wait_untill finished due to the timeout it means the motion sensors have not detected any motion for 15s and thus the screen can be turned off. As we don't know whether this is the reason wait_untill finished we need to check whether indeed both sensors are off. 
201
                  condition:
202
                    and:
203
                      - binary_sensor.is_off: microwave
204
                      - binary_sensor.is_off: pir
205
                  then:
206
                    - lambda: id(scherm).turn_off();
207
  - platform: gpio #PIR technology motion sensor
208
    pin: GPIO19
209
    id: pir
210
    internal: true #Don't expose this sensor to Home Assistant
211
    name: '${device_name_friendly} PIR'
212
    device_class: motion
213
    on_state: #turns on the OLED display if PIR motion is detected and turns it off 15 seconds after PIR and Microwave sensors stop detecting motion
214
      then:
215
        - if:
216
            condition:
217
              - binary_sensor.is_on: pir
218
            then:
219
              - lambda: id(scherm).turn_on();
220
            else: #The pir sensor is not detecting motion (anymore)
221
              - wait_until: #This will stop waiting after 15 seconds or as soon as motion is detected. 
222
                  condition:
223
                    or:
224
                      - binary_sensor.is_on: microwave
225
                      - binary_sensor.is_on: pir
226
                  timeout: 15s
227
              - if: #If wait_untill finished due to the timeout it means the motion sensors have not detected any motion for 15s and thus the screen can be turned off. As we don't know whether this is the reason wait_untill finished we need to check whether indeed both sensors are off. 
228
                  condition:
229
                    and:
230
                      - binary_sensor.is_off: microwave
231
                      - binary_sensor.is_off: pir
232
                  then:
233
                    - lambda: id(scherm).turn_off();
234
  - platform: template #Create virtual motion sensor that is only triggered if both Microwave and PIR sensor see motion
235
    id: motion
236
    name: '${device_name_friendly} Motion'
237
    device_class: motion
238
    lambda: !lambda |-
239
      if ((id(microwave).state) and (id(pir).state)) {
240
        return true;
241
      } else {
242
        return false;
243
      }
244
245
switch:
246
  - platform: template
247
    name: "Trigger background calibration"
248
    turn_on_action:
249
      - senseair.background_calibration: '${device_name}CO2'
250
  #- platform: template #result will be printed in the logs
251
  #  name: "Get background calibration result"
252
  #  turn_on_action:
253
  #    - senseair.background_calibration_result: '${device_name}CO2'
254
  #- platform: template #result will be printed in the logs
255
  #  name: "Get ABC Period"
256
  #  turn_on_action:
257
  #    - senseair.abc_get_period: '${device_name}CO2'
258
  - platform: template
259
    name: "Disable ABC"
260
    turn_on_action:
261
      - senseair.abc_disable: '${device_name}CO2'
262
  - platform: template
263
    name: "Enable ABC"
264
    turn_on_action:
265
      - senseair.abc_enable: '${device_name}CO2'
266
      
267
268
font: #Define fonts to be used for the display. font file is to be stored in Home Assistant in folder config/esphome
269
  - file: 'BebasNeue-Regular.ttf'
270
    id: font0
271
    size: 14
272
  - file: 'BebasNeue-Regular.ttf'
273
    id: font1
274
    size: 20
275
  - file: 'BebasNeue-Regular.ttf'
276
    id: font2
277
    size: 26
278
279
image: #Define images to be used for the display. Image file is to be stored in Home Assistant in folder config/esphome
280
  - file: "nomotion.png"
281
    id: nomotionimage
282
    resize: 35x35
283
  - file: "motion.png"
284
    id: motionimage
285
    resize: 35x35
286
    
287
graph:
288
  # Define auto-ranged CO2 graph
289
  - id: ${device_name}co2graph
290
    sensor: ${device_name}co2state #sensor to be used
291
    duration: 1h #show range of 1 hour
292
    width: 128
293
    height: 64
294
    border: false
295
    x_grid: 10min #show 1 gridline per 10 minutes
296
    y_grid: 100 #show 1 gridline per 100PPM co2
297
    
298
299
display: #Set up the display
300
  - platform: ssd1306_i2c
301
    model: "SSD1306 128x64"
302
    id: scherm
303
    # reset_pin: D0  #Optionally you can also connect the RESET pin to a pin on the ESP which may improve reliability. My display doesn't have this pin.
304
    # address: 0x3C #defaults to 0x3C which should be the right address. Otherwise check the logs.
305
    update_interval: never #The interval to re-draw the screen. Defaults to 5s. Set to never as I control the updates separately futher below.
306
    pages: #Insteadf of 1 screen that never changes this defines pages that you can transition between
307
      - id: page1 #Page with values of all my sensors
308
        lambda: |-
309
          // Als buitensensor HomeAssistant beschikbaar: Print Temp gemonteerde sensor + buitensensor van HomeAssistant; anders print enkel temp gemonteerde sensor.
310
          if (id(outdoor_temperature).has_state()) {
311
            it.printf(0, 0, id(font1), "°C In:%.1f Out:%.1f", id(${device_name}temp).state, id(outdoor_temperature).state);
312
          } else {
313
            it.printf(0, 0, id(font1), "%.1f°C", id(${device_name}temp).state);
314
          }
315
          // Print Humidity & LUX value (%% prints %)
316
          it.printf(0, 20, id(font1), "%.0f%% %.0fLUX", id(${device_name}hum).state, id(luminosity).state);
317
          // Print CO2 value
318
          it.printf(0, 40, id(font2), "%.0fppmCO2", id(${device_name}co2state).state);
319
          //print motion state using an image
320
          if (id(motion).state) {
321
            it.image(100, 20, id(motionimage));
322
          } else {
323
            it.image(100, 20, id(nomotionimage));
324
          }
325
          //Print on bottom right P0M1 if microwave triggered, P1M0 if PIR trigered, P1M1 if both triggered and P0M0 if none triggered
326
          it.printf(it.get_width(), 50, id(font0), TextAlign::TOP_RIGHT, "%s%s", id(pir).state ? "P1" : "P0", id(microwave).state ? "M1" : "M0");
327
      - id: page2 # Page with CO2 sensor graph. SHows that gridlines are 10 minues and 100PPm each. Also show the CO2 value on top right.
328
        lambda: |-
329
          // Draw the graph at position [x,y]
330
          it.graph(0, 0, id(${device_name}co2graph));
331
          it.print(0, 48, id(font0), "10min");
332
          it.print(0, 0, id(font0), "100ppm");
333
          it.print(60, 0, id(font0), "CO2");
334
          it.printf(it.get_width(), 0, id(font1), TextAlign::TOP_RIGHT, "%.0f", id(${device_name}co2state).state);
335
          
336
337
# cycle through pages on a timer and regularly update the content. In practice this shows page2 for 3 seconds and then page1 for 10 seconds. Not sure why it's not 7 seconds for page1.
338
interval:
339
  - interval: 10s
340
    then:
341
      - display.page.show: page2
342
      - component.update: scherm
343
      - delay: 3s
344
      - display.page.show: page1
345
      - component.update: scherm
346
      - delay: 1s
347
      - component.update: scherm
348
      - delay: 1s
349
      - component.update: scherm
350
      - delay: 1s
351
      - component.update: scherm
352
      - delay: 1s
353
      - component.update: scherm
354
      - delay: 1s
355
      - component.update: scherm