Angelos Orfanakos

Bresser weather station in Home Assistant

This is a guide on how to display data from a Bresser 5-in-1 (or similar) weather station in Home Assistant.

Assumptions

You already have Home Assistant up and running in a system (e.g. Raspberry Pi) with enough power to drive external USB devices.

Necessary hardware

  • A USB dongle that can capture FM radio, as this is how the weather station transmits data. I can recommend the RTL-SDR BLOG V3 which is considered best-in-class.
  • An antenna with an SMA male connector (threads inside, with pin) to connect to the dongle. I wasn’t able to capture any data without the antenna.

Test FM dongle

Screw the antenna to the dongle and plug it in your workstation (regular computer)

Install rtl_433. In Debian:

sudo apt install rtl-433

Verify you can receive data by running the following command for a few minutes:

sudo rtl_433 -f 868.3M -R 172

If protocol 172 does not seem to work, issue rtl_433 -R help for a list of supported protocols.

The output should look something like this:

   time      : <time>
   model     : Bresser-6in1 id        : <id>
   channel   : 0            Battery   : 1             Temperature: 14.5 C
   Humidity  : 61           Sensor type: 1            Wind Gust : 0.0 m/s
   Wind Speed: 0.0 m/s      Direction : 90            UV        : 0.0
   Flags     : 0            Integrity : CRC

Note that if you later place the dongle someplace else, it may not be able to receive data, even with the antenna on (e.g. due to signal interference and/or walls) I realized this, the hard way, after placing it in a closet and trying to debug, for hours, why it’s not receiving anything. So this test should ideally happen (using a laptop) near the physical space the dongle will later be placed at.

Install add-ons

Install the following add-ons in Home Assistant:

  • File editor to edit configuration files (official add-on)
  • Mosquitto broker to store weather station data (official add-on)
  • rtl_433 to receive weather station data with the dongle and forward it to MQTT (community add-on)

Create user

Create a user in Home Assistant, the login details (username, password) of which will be used by rtl_433 in the next step to connect to Mosquitto broker via MQTT.

Configure rtl_433

Edit /homeassistant/rtl_433/rtl_433.conf with the File editor add-on and replace its contents with:

report_meta stats
report_meta time:iso:usec:tz
report_meta protocol

gain 0

convert si

frequency 868.3M

pulse_detect autolevel

verbose 5

output mqtt://core-mosquitto:1883,user=<username>,pass=<password>,retain=1,devices=rtl_433/bresser51output kv

protocol 172 # Bresser Weather Center 6-in-1, 7-in-1 indoor, soil, new 5-in-1, 3-in-1 wind gauge, Froggit WH6000, Ventus C8488A

Make sure you replace <username> and <password> with the details of the user you created in the previous step.

Verify rtl_433 works

Go to the add-on page of Mosquitto broker and rtl_433 and start them (in this order) Make sure the “Start on boot” and “Watchdog” options are enabled.

Switch to the Log tab of rtl_433. You should see an output similar to:

Starting rtl_433 with rtl_433.conf located in /config/rtl_433
rtl_433 version 24.10-3-g4fa37568 branch master at 202411051225 inputs file rtl_tcp RTL-SDR
New defaults active, use "-Y classic -s 250k" if you need the old defaults
MQTT: Publishing MQTT data to core-mosquitto port 1883
MQTT: Publishing device info to MQTT topic "rtl_433/bresser51".
Protocols: Registered 2 out of 266 device decoding protocols [ 172 172 ]
Input: The internals of input handling changed, read about and report problems on PR #1978
SDR: Found 1 device(s)
SDR: trying device 0: Realtek, RTL2838UHIDIR, SN: 00000001
Detached kernel driver
Found Rafael Micro R820T tuner
SDR: Using device 0: Realtek, RTL2838UHIDIR, SN: 00000001, "Generic RTL2832U OEM"
Exact sample rate is: 250000.000414 Hz
[R82XX] PLL not locked!
SDR: Sample rate set to 250000 S/s.
Input: Bit detection level set to 0.0 (Auto).
SDR: Tuner gain set to Auto.
Input: Reading samples in async mode...
SDR: Tuned to 868.300MHz.
MQTT: MQTT Connected...
MQTT: MQTT Connection established.
Baseband: low pass filter for 250000 Hz at cutoff 50000 Hz, 20.0 us

Things to note:

  • Lines 4, 5: Configured to forward any data it receives to MQTT broker
  • Lines 20, 21: Connection to MQTT broker established
  • Line 6: Configured protocol 172 enabled
  • Lines 8, 9, 11, 12: USB dongle detected
  • Line 19: Listening to configured frequency 868.3 MHz

You should also see an output similar to the previous one during the test:

   time      : <time>
   model     : Bresser-6in1 id        : <id>
   channel   : 0            Battery   : 1             Temperature: 14.5 C
   Humidity  : 61           Sensor type: 1            Wind Gust : 0.0 m/s
   Wind Speed: 0.0 m/s      Direction : 90            UV        : 0.0
   Flags     : 0            Integrity : CRC

Which means the dongle is receiving data from the weather station.

Configure sensors in Home Assistant

Edit /homeassistant/configuration.yml with the File editor add-on and append:

mqtt:
  sensor:
    - name: Bresser51 Temperature
      state_topic: rtl_433/bresser51/temperature_C
      unique_id: bresser51_temperature_C
      value_template: '{{ value | float }}'
      unit_of_measurement: '°C'
      device_class: temperature

    - name: Bresser51 Humidity
      state_topic: rtl_433/bresser51/humidity
      unique_id: bresser51_humidity
      value_template: '{{ value | int }}'
      unit_of_measurement: %
      device_class: humidity

    - name: Bresser51 Wind Gust
      state_topic: rtl_433/bresser51/wind_max_m_s
      unique_id: bresser51_wind_max_m_s
      value_template: '{{ value | float }}'
      unit_of_measurement: m/s
      icon: mdi:weather-windy

    - name: Bresser51 Wind Speed
      state_topic: rtl_433/bresser51/wind_avg_m_s
      unique_id: bresser51_wind_avg_m_s
      value_template: '{{ value | float }}'
      unit_of_measurement: m/s
      icon: mdi:weather-windy

    - name: Bresser51 Wind Direction
      state_topic: rtl_433/bresser51/wind_dir_deg
      unique_id: bresser51_wind_dir_deg
      value_template: '{{ value | int }}'
      unit_of_measurement: '°'
      icon: mdi:compass-rose

    - name: Bresser51 Rain
      state_topic: rtl_433/bresser51/rain_mm
      unique_id: bresser51_rain_mm
      value_template: '{{ value | float }}'
      unit_of_measurement: mm
      icon: mdi:weather-rainy

    - name: Bresser51 Time
      state_topic: rtl_433/bresser51/time
      unique_id: bresser51_time
      icon: mdi:clock-outline

    - name: Bresser51 UV
      state_topic: rtl_433/bresser51/uv
      unique_id: bresser51_uv
      value_template: '{{ value | int }}'
      icon: mdi:white-balance-sunny

    - name: Bresser51 Light
      state_topic: rtl_433/bresser51/light_lux
      unique_id: bresser51_light_lux
      value_template: '{{ value | int }}'
      unit_of_measurement: lux
      icon: mdi:lightbulb-outline

  binary_sensor:
    - name: Bresser51 Battery
      state_topic: rtl_433/bresser51/battery_ok
      unique_id: bresser51_battery_ok
      payload_on: 0
      payload_off: 1
      device_class: battery

sql:
  - name: Bresser51 Rain 5 Minutes Cumulative
    query: >-
      SELECT state
      FROM states
      INNER JOIN states_meta ON states.metadata_id = states_meta.metadata_id
      WHERE states_meta.entity_id = 'sensor.bresser51_rain'
      AND last_updated_ts <= strftime('%s', 'now', '-5 minutes')
      ORDER BY last_updated_ts DESC
      LIMIT 1
    column: state
    unit_of_measurement: mm
    icon: mdi:weather-rainy

  - name: Bresser51 Rain 1 Hour Cumulative
    query: >-
      SELECT state
      FROM states
      INNER JOIN states_meta ON states.metadata_id = states_meta.metadata_id
      WHERE states_meta.entity_id = 'sensor.bresser51_rain'
      AND last_updated_ts <= strftime('%s', 'now', '-1 hour')
      ORDER BY last_updated_ts DESC
      LIMIT 1
    column: state
    unit_of_measurement: mm
    icon: mdi:weather-rainy

  - name: Bresser51 Rain 24 Hours Cumulative
    query: >-
      SELECT state
      FROM states
      INNER JOIN states_meta ON states.metadata_id = states_meta.metadata_id
      WHERE states_meta.entity_id = 'sensor.bresser51_rain'
      AND last_updated_ts <= strftime('%s', 'now', '-24 hours')
      ORDER BY last_updated_ts DESC
      LIMIT 1
    column: state
    unit_of_measurement: mm
    icon: mdi:weather-rainy

  - name: Bresser51 Rain 7 Days Cumulative
    query: >-
      SELECT state
      FROM states
      INNER JOIN states_meta ON states.metadata_id = states_meta.metadata_id
      WHERE states_meta.entity_id = 'sensor.bresser51_rain'
      AND last_updated_ts <= strftime('%s', 'now', '-7 days')
      ORDER BY last_updated_ts DESC
      LIMIT 1
    column: state
    unit_of_measurement: mm
    icon: mdi:weather-rainy

  - name: Bresser51 Rain 30 Days Cumulative
    query: >-
      SELECT state
      FROM states
      INNER JOIN states_meta ON states.metadata_id = states_meta.metadata_id
      WHERE states_meta.entity_id = 'sensor.bresser51_rain'
      AND last_updated_ts <= strftime('%s', 'now', '-30 days')
      ORDER BY last_updated_ts DESC
      LIMIT 1
    column: state
    unit_of_measurement: mm
    icon: mdi:weather-rainy

template:
  sensor:
    - name: Bresser51 Wind Speed Beaufort
      unique_id: bresser51_wind_speed_bft
      unit_of_measurement: Bft
      icon: mdi:windsock
      state: |
        {{(((states('sensor.bresser51_wind_speed') | float) / 0.836) ** (2/3)) | round(0, 'ceil')}}

    - name: Bresser51 Wind Gust Beaufort
      unique_id: bresser51_wind_gust_bft
      unit_of_measurement: Bft
      icon: mdi:windsock
      state: |
        {{(((states('sensor.bresser51_wind_gust') | float) / 0.836) ** (2/3)) | round(0, 'ceil')}}

    - name: Bresser51 Wind Direction Sector
      unique_id: bresser51_wind_direction_sector
      icon: mdi:compass-rose
      state: |
        {{((states('sensor.bresser51_wind_direction') | int) / 22) | int % 16}}

    - name: Bresser51 Wind Direction Name
      unique_id: bresser51_wind_direction_name
      icon: mdi:compass-rose
      state: |
        {{"N NNE NE ENE E ESE SE SSE S SSW SW WSW W WNW NW NNW N".split()[states('sensor.bresser51_wind_direction_sector') | int]}}

    - name: Bresser51 Rain 5 Minutes
      unique_id: bresser51_rain_5_minutes
      icon: mdi:weather-rainy
      state: |
        {{((states('sensor.bresser51_rain') | float) - (states('sensor.bresser51_rain_5_minutes_cumulative') | float)) | round(1)}}

    - name: Bresser51 Rain 1 Hour
      unique_id: bresser51_rain_1_hour
      icon: mdi:weather-rainy
      state: |
        {{((states('sensor.bresser51_rain') | float) - (states('sensor.bresser51_rain_1_hour_cumulative') | float)) | round(1)}}

    - name: Bresser51 Rain 24 Hours
      unique_id: bresser51_rain_24_hours
      icon: mdi:weather-rainy
      state: |
        {{((states('sensor.bresser51_rain') | float) - (states('sensor.bresser51_rain_24_hours_cumulative') | float)) | round(1)}}

    - name: Bresser51 Rain 7 Days
      unique_id: bresser51_rain_7_days
      icon: mdi:weather-rainy
      state: |
        {{((states('sensor.bresser51_rain') | float) - (states('sensor.bresser51_rain_7_days_cumulative') | float)) | round(1)}}

    - name: Bresser51 Rain 30 Days
      unique_id: bresser51_rain_30_days
      icon: mdi:weather-rainy
      state: |
        {{((states('sensor.bresser51_rain') | float) - (states('sensor.bresser51_rain_30_days_cumulative') | float)) | round(1)}}

Adjusted for the Northern hemisphere and latest Home Assistant versions (Core 2024.11.0, Supervisor 2024.11.2, Operating System 13.2, Frontend 20241106.0), based on the great article by Johan Vromans

This will eventually end up creating the following, self-explanatory, sensors:

  • sensor.bresser51_temperature (°C)
  • sensor.bresser51_humidity (%)
  • sensor.bresser51_wind_gust (m/s)
  • sensor.bresser51_wind_gust_beaufort (bft)
  • sensor.bresser51_wind_speed (m/s)
  • sensor.bresser51_wind_speed_beaufort (bft)
  • sensor.bresser51_wind_direction (°)
  • sensor.bresser51_wind_direction_name (N, S, W, E, etc)
  • sensor.bresser51_rain (mm)
  • sensor.bresser51_rain_5_minutes (mm)
  • sensor.bresser51_rain_1_hour (mm)
  • sensor.bresser51_rain_24_hours (mm)
  • sensor.bresser51_rain_7_days (mm)
  • sensor.bresser51_rain_30_days (mm)
  • sensor.bresser51_time
  • sensor.bresser51_uv
  • sensor.bresser51_light (lux)
  • binary_sensor.bresser51_battery ("on" if the battery is low)

Note that the amount of rainfall sent by the weather station (sensor.bresser51_rain) is cumulative. All other rainfall sensors are differential (i.e. amount of rain in the last 5 minutes, hour, day, etc)

Create sensors

Restart Home Assistant to reload the configuration.

Install the MQTT integration which will create the sensors.

Display in dashboard

Here’s the vertical-stack card YAML I use in my dashboard to display weather data:

type: vertical-stack
title: Weather station
cards:
  - graph: line
    type: sensor
    entity: sensor.bresser51_temperature
    detail: 2
    unit: ⁰C
    hours_to_show: 48
    name: Temperature
  - type: gauge
    name: Humidity
    unit: %
    entity: sensor.bresser51_humidity
    max: 100
    min: 0
    needle: true
  - type: glance
    entities:
      - entity: sensor.bresser51_wind_direction_name
        name: Direction
      - entity: sensor.bresser51_wind_beaufort
        name: Speed
      - entity: sensor.bresser51_wind_gust_beaufort
        name: Gust
  - type: glance
    entities:
      - entity: sensor.bresser51_rain_5_minutes
        name: 5 Minutes
      - entity: sensor.bresser51_rain_1_hour
        name: Hour
      - entity: sensor.bresser51_rain_24_hours
        name: 24 Hours
      - entity: sensor.bresser51_rain_7_days
        name: 7 Days
      - entity: sensor.bresser51_rain_30_days
        name: 30 Days

Have fun!

Troubleshooting

In case something does not work: