ESPHOME custom mqtt?

Abstract :

ESPHOME sends an MQTT message per sensor, binary sensor, textsensor …). If many sensors are in use, then a large number of messages are sent to the MQTT Brocker via the network.

sample

Improvement: Bundling of the MQTT messages per sensor that are connected to a board.

Example: ESP32 with DHT, BH1750FVI, AS3935, SDS011.

ESPHOME MQTT: 24 MQTT messages ESPHOME Custom MQTT: 1 Message!

I am currently using platform: uptime to only send one MQTT message.

  1. How can I prevent values that are not available (NaN) from being sent as a payload.
  2. How can I group the values of the sensors in the payload?

I haven’t found a way to do this through the root object.
Is there a solution for this ?

# Uptime Sensor
  # see: https://esphome.io/components/sensor/uptime.html?highlight=uptime
  - platform: uptime
    id: upti
    name: "${friendly_name} Uptime"
    update_interval: ${publish_interval}
    state_topic: tele/${device_name}/uptime
    on_value:
      - wait_until:
          mqtt.connected:
      - mqtt.publish_json:
          topic: tele/$device_id/infodata
          payload: |-
              root["dht_temperature"] = id(temp).state;
              root["dht_humidity"] = id(rh).state;
              root["dht_humidity_abs"] = id(rha).state;
              root["dht_dewpoint"] = isnan(id(taupunkt).state) ? id(temp).state : id(taupunkt).state;
              root["dht_heatindex"] = isnan(id(heatindex).state) ? id(temp).state : id(heatindex).state;
              root["bh1750_light"] = id(lightsensor).state;
              root["sds011_pm10"] = isnan(id(pm10).state) ? -1 : id(pm10).state;
              root["sds011_pm25"] = isnan(id(pm25).state) ? -1 : id(pm25).state;
              root["ightning_energy"] = isnan(id(asbe).state) ? -1 : id(asbe).state;
              root["lightning_distance"] = isnan(id(asdis).state) ? 10000 : id(asdis).state;
              root["lightning_warning"] = id(sturm).state;
              root["sun_elevation"] = isnan(id(sune).state) ? -1 : id(sune).state;
              root["sun_azimuth"] =  isnan(id(suna).state) ? -1 : id(suna).state;
              root["sun_sunrise"] = id(sunup).state;
              root["sun_sunset"] = id(sundown).state;
              root["wifisignal"] = id(wifisignal).state;
              root["wifiip"] = id(wifiip).state;
              root["wifissid"] = id(wifissid).state;
              root["wifibssid"] = id(wifibssid).state;
              root["uptime"] = id(upti).state;
              root["timestamp"] = id(systime).state;
              root["version"] = id(appver).state;
              root["appversion"] = "${appversion}";
              root["attribution"] ="${attribution}";
      - logger.log: "MQTT Data published"

Result:

{
    "dht_temperature": 24.4,
    "dht_humidity": 65.6,
    "dht_humidity_abs": 14.49275,
    "dht_dewpoint": 17.41075,
    "dht_heatindex": 24.4,
    "bh1750_light": 68.33333,
    "sds011_pm10": 6.7,
    "sds011_pm25": 3.7,
    "ightning_energy": -1,
    "lightning_distance": 10000,
    "lightning_warning": false,
    "sun_elevation": 32.72499,
    "sun_azimuth": 245.7026,
    "sun_sunrise": "06:33:18",
    "sun_sunset": "20:08:40",
    "wifisignal": -56,
    "wifiip": "10.1.1.71",
    "wifissid": "McNessi",
    "wifibssid": "88:1B:A6:34:3E:82",
    "uptime": 5334.562,
    "timestamp": "2020-08-28 16:44:49",
    "version": "1.15.0b4 Aug 27 2020, 14:49:39",
    "appversion": "1.0.0",
    "attribution": "Data provided by ESPHome"
}

This would be the result I want:

{
    "dht": {
        "temperature": 24.5,
        "humidity": 55.2,
        "humidity_abs": 12.39751,
        "dewpoint": 14.91253,
        "heatindex": 24.5
    },
    "bh1750": {
        "light": 69.16666
    },
    "sds011": {
        "pm10": 5.4,
        "pm25": 3.1
    },
    "as3935": {
        "lightning": -1,
        "distance": 10000,
        "warning": false
    },
    "sun": {
        "elevation": 48.97265,
        "azimuth": 208.4818,
        "sunrise": "06:33:18",
        "sunset": "20:08:40"
    },
    "wifi": {
        "signal": -55,
        "ip": "10.1.1.71",
        "ssid": "McNessi",
        "bssid": "88:1F:A1:34:3E:82"
    },
    "system": {
        "uptime": 56.503,
        "timestamp": "2020-08-28 14:35:11",
        "version": "1.15.0b4 Aug 27 2020, 14:49:39",
        "appversion": "1.0.0",
        "attribution": "Data provided by ESPHome"
    }
}

How can I solve this ?

You can post the code for the BH1750FVI, I have some but can’t get it to work.

## ############################################
## UMWELT SENSOR  esp32dev board
## Autor: Peter Siebler
## Version: 1.0.0
## ############################################
substitutions:
  device_id: "esp32uws"
  device_name: umweltsensor
  device_name_upper: "Umwelt Sensor"
  update_time: 10s
  publish_interval: 60s
  device_name_short: umweltsensor
  platform: ESP32
  board: esp32dev
  attribution: "Data provided by esp32 umweltsensor"
  appversion: "1.0.0"
  device_description: Testcase ESP32, AS3935, DHT22, SDS011

# see: https://esphome.io/devices/esp32.html     
esphome:
  name: $device_name_short
  comment: ${device_description}
  platform: ${platform}
  board: ${board}

# Logger Component
# see: https://esphome.io/components/logger.html?highlight=logger#logger-component
logger:
  level: DEBUG
  
# MQTT Client Component
# see: https://esphome.io/components/mqtt.html?highlight=mqtt
# inlude mqtt broker and wifi settings w/o api
<<: !include common/mqttonly.yaml


# publish all data for all sensors
# How to handle the NaN values ??
interval:
  - interval: ${publish_interval}
    then:
        - wait_until:
            mqtt.connected:
        - mqtt.publish_json:
            topic: "tele/${device_name_short}/data"
            payload:
              root["dht_temperature"] = id(temp).state;
              root["dht_humidity"] = id(rh).state;
              root["dht_humidity_abs"] = id(rha).state;
              root["dht_dewpoint"] = id(taupunkt).state;
              root["dht_heatindex"] = id(heatindex).state;
              root["bh1750_light"] = id(lightsensor).state;
              root["sds011_pm10"] = id(pm10).state;
              root["sds011_pm25"] = id(pm25).state;
              root["ightning_energy"] = id(asbe).state;
              root["lightning_distance"] = id(asdis).state; 
              root["lightning_warning"] = id(sturm).state;
              root["sun_elevation"] = id(sune).state;
              root["sun_azimuth"] = id(suna).state;
              root["sun_sunrise"] = id(sunup).state;
              root["sun_sunset"] = id(sundown).state;
              root["wifisignal"] = id(wifisignal).state;
              root["wifiip"] = id(wifiip).state;
              root["wifissid"] = id(wifissid).state;
              root["wifibssid"] = id(wifibssid).state;
              root["uptime"] = id(upti).state;
              root["timestamp"] = id(systime).state;
              root["version"] = id(appver).state;
              root["appversion"] = "${appversion}";
              root["attribution"] ="${attribution}";
              
        - logger.log: "MQTT Data published"


# Sun component
# see: https://esphome.io/components/sun.html
sun:
  id: sun_sun
  latitude: !secret home_latitude
  longitude: !secret home_longitude

# ESP32 Bluetooth Low Energy Device
# configuration entry for finding MAC addresses
# see: https://esphome.io/components/esp32_ble_tracker.html
esp32_ble_tracker:

# I²C Bus
# see: https://esphome.io/components/i2c.html?highlight=i2c#i2c-bus
# bus_a: connection AS3935 Franklin Lightning Sensor
# bus_b: connection BH1750 ambient light sensor
i2c:
  - id: bus_a # as3935
    scl: 22
    sda: 21
    scan: True
    frequency: 400
  - id: bus_b  # bh1750
    scl: 26
    sda: 25
    scan: True  

# AMS AS3935 Franklin Lightning Sensor
# see: https://esphome.io/components/sensor/as3935.html?highlight=as3935
as3935_i2c:
  irq_pin: 5
  indoor: False
  watchdog_threshold: 5
  spike_rejection: 3

# UART Bus
# see: https://esphome.io/components/uart.html?highlight=uart
# Connection SDS011 Particulate Matter Sensor
uart:
  rx_pin: 16
  tx_pin: 17
  baud_rate: 9600

# Integration Sensor
# see: https://esphome.io/components/sensor/integration.html?highlight=sensor
# disable MQTT for each sensor: do not use a name ??
sensor:

  # SDS011 Particulate Matter Sensor
  # see: https://esphome.io/components/sensor/sds011.html?highlight=sds011   
  - platform: sds011
    rx_only: false
    pm_2_5:
      #name: "${device_name_upper} Staub <2.5µm"
      id: pm25
      unit_of_measurement: "µm"
    pm_10_0:
      #name: "${device_name_upper} Staub <10.0µm" 
      id: pm10
      unit_of_measurement: "µm"
    update_interval: 1min


  # AS3935 Franklin Lightning Sensor SEN0290 Brand: DFRobot Sensor
  # see: https://esphome.io/components/sensor/as3935.html?highlight=as3935
  - platform: as3935
    # i2c_id: bus_a   ! DO NOT WORK
    lightning_energy:
      id: asbe
      #name: "${device_name_upper} Blitz Energie"
    distance:
      id: asdis
      #name: "${device_name_upper} Sturm Entfernung"
      filters:
      unit_of_measurement: "km"

  
  # BH1750 ambient light sensor    
  # see: https://esphome.io/components/sensor/bh1750.html
  - platform: bh1750
    i2c_id: bus_b
    update_interval: 10s
    #name: "${device_name_upper} Licht"
    id: lightsensor


  # DHT22 Temperature+Humidity Sensor
  # see: https://esphome.io/components/sensor/dht.html
  - platform: dht
    pin: 27 # GPIO 27
    model: DHT22
    temperature:
      #name:  "${device_name_upper} Temperatur"  
      id: temp
      unit_of_measurement: "°C"
      accuracy_decimals: 2
    humidity:
      #name:  "${device_name_upper} Feuchtigkeit"
      id: rh
      unit_of_measurement: "%"
      accuracy_decimals: 2
    update_interval: 10s

  # Template Sensor DHT Humidity abs.
  - platform: template
    #name:  "${device_name_upper} Feuchtigkeit abs."  
    id: rha
    unit_of_measurement: "g/m^3"
    lambda:
      const float mw = 18.01534; 
      const float r = 8.31447215;
      return (6.112 * powf(2.718281828, (17.67 * id(temp).state) / (id(temp).state + 243.5)) * id(rh).state * mw) / ((273.15 + id(temp).state) * r); 
    accuracy_decimals: 2
    update_interval: 10s

  # Template Sensor DHT Dew. Point
  - platform: template
    #name: "${device_name_upper} Taupunkt"  
    id: taupunkt
    unit_of_measurement: "°C"
    lambda:
      const float a = 17.27;
      const float b = 237.7;
      return ( (b * ( (id(temp).state * a) / ( b + id(temp).state) + logf (id(rh).state/100) ) )/( a - ( (id(temp).state * a) / ( b + id(temp).state) + logf (id(rh).state/100) ) ) ); 
    accuracy_decimals: 2
    update_interval: 10s

  # Template Sensor DHT Heatindex
  - platform: template
    #name:  "${device_name_upper} Heatindex"
    id: heatindex
    lambda:
        const float t = id(temp).state;
        const float h = id(temp).state;
        const float c1 = -42.379;
        const float c2 = 2.04901523;
        const float c3 = 10.14333127;
        const float c4 = -0.22475541;
        const float c5 = -6.83783e-3;
        const float c6 = -5.481717e-2;
        const float c7 = 1.22874e-3;
        const float c8 = 8.5282e-4;
        const float c9 = -1.99e-6;
        static float hi = 0.5 * (t + 61.0 + ((t - 68.0) * 1.2) + (h * 0.094));
        if (hi >= 80.00) {
          hi = c1+c2*t+c3*h+c4*t*h+sqrt(c5*t)+c6*sqrt(h)+c7*sqrt(t)*h+c8*t*sqrt(h)+c9*sqrt(t)*sqrt(h);
        }
        return hi;
    accuracy_decimals: 2
    unit_of_measurement: "°C"
    update_interval: 10s

  
  # sun component 
  # see: https://esphome.io/components/sun.html?highlight=sun
  - platform: sun
    #name: "Sonne Elevation"
    id: sune
    type: elevation
    update_interval: 30s
    
  - platform: sun
    # name: Sonne Azimuth
    id: suna
    type: azimuth
    update_interval: 30s

      
  # WiFi Signal Sensor
  # see: https://esphome.io/components/sensor/wifi_signal.html?highlight=wifi_signal
  - platform: wifi_signal
    #name: ${device_id} WiFi Signal
    id: wifisignal
    unit_of_measurement: "dB"
    update_interval: 60s  


  # Uptime Sensor
  # see: https://esphome.io/components/sensor/uptime.html?highlight=uptime
  - platform: uptime
    id: upti
    #name: "${device_name_upper} Uptime"  
    
# Binary Sensor Component
# AS3935 Franklin Lightning Sensor SEN0290 Brand: DFRobot Sensor
# see https://esphome.io/components/sensor/as3935.html?highlight=as3935
binary_sensor:
  - platform: as3935
    #name: "${device_name_upper} Sturm Warnung"
    id: sturm
    state_topic: tele/${device_name_short}/blitzwarnung

# Text Sensor Component
# see: https://esphome.io/components/text_sensor/index.html?highlight=text_sensor
text_sensor:

  # sun component 
  # see: https://esphome.io/components/sun.html?highlight=sun
  - platform: sun
    #name: "Nächster Sonnenaufgang"
    id: sunup
    type: sunrise
    
  - platform: sun
    #name: "Nächster Sonnenuntergang"
    id: sundown
    type: sunset
    
  # Version Text Sensor
  # see: https://esphome.io/components/text_sensor/version.html?highlight=platform%20version
  - platform: version
    #name: ${device_name_upper} Version
    id: appver
  
  # WiFi Info Text Sensor
  # see: https://esphome.io/components/text_sensor/wifi_info.html?highlight=platform%20wifi_info
  - platform: wifi_info
    ip_address:
      #name: ${device_name_upper} IP
      id: wifiip
      icon: mdi:ip-network
    ssid:
      #name: ${device_name_upper} SSID
      id: wifissid
    bssid:
      id: wifibssid
      #name: ${device_name_upper} BSSID 
      
  # Template Text Sensor Timestamp
  # see: https://esphome.io/components/text_sensor/template.html?highlight=platform%20template
  - platform: template
    id: systime
    lambda:
      char str[20];
      time_t currTime = id(sntp_time).now().timestamp;
      strftime(str, sizeof(str), "%Y-%m-%d %H:%M:%S", localtime(&currTime));
      return (std::string) str;      

I see that my code is correct for the bh1750.
But it does not work.
[bh1750.sensor: 030]: Communication with BH1750 failed!
I have copied your identic code, but it doesn’t work either.
What board are you using? I am using a D1 mini.

I see you also use an as3935. Another sensor that does not work well for me. Never detected lightning. Does the as3935 work for you?

@Roglogg

D1 mini has only one I²C bus, i use ESP32 for more than one I²C bus.

# I²C Bus
# see: https://esphome.io/components/i2c.html?highlight=i2c#i2c-bus
# bus_a: connection AS3935 Franklin Lightning Sensor
# bus_b: connection BH1750 ambient light sensor
i2c:
  - id: bus_a # as3935
    scl: 22
    sda: 21
    scan: True
    frequency: 400
  - id: bus_b  # bh1750
    scl: 26
    sda: 25
    scan: True  

Simple test for D1 mini:

More Info here, but in german.
https://www.kriwanek.de/index.php/de/homeautomation/esp8266-geräte/wemos-geräte/555-bh1750-helligkeitssensor

Does the as3935 work for you?

Negativ, no solution found, never detected lightning.
see: AS3935_i2C - Read failed! · Issue #1411 · esphome/issues · GitHub

1 Like

I have tried with ESP32 and it doesn’t work either. I think the BH1750 sensor is bad.

The as3935 sensor I have not seen anyone that works for it.

Thanks for the info.