BresserWeatherSensorReceiver is an Arduino library for receiving and decoding 868 MHz wireless data from Bresser weather sensors using ESP32, ESP8266, or RP2040 microcontrollers with RF transceivers (CC1101, SX1276/RFM95W, SX1262, or LR1121).
- Receive and decode RF messages from multiple Bresser sensor types (5-in-1, 6-in-1, 7-in-1, 8-in-1 weather stations, lightning sensors, water leakage sensors, etc.)
- Support multiple simultaneous sensors with ID filtering and slot management
- Provide post-processing for rain gauge statistics and lightning detection
- Integrate with MQTT, WiFi, OLED displays, SD cards, and Home Assistant
| Class | File | Purpose |
|---|---|---|
WeatherSensor |
WeatherSensor.h/.cpp |
Main receiver class - RF reception, message decoding, multi-sensor management |
RainGauge |
RainGauge.h/.cpp |
Rain statistics - hourly/daily/weekly/monthly accumulation, overflow handling |
Lightning |
Lightning.h/.cpp |
Lightning strike counting, hourly history, post-processing |
InitBoard |
InitBoard.h/.cpp |
Board-specific initialization for 15+ ESP32/ESP8266 variants |
- Union-Based Memory Efficiency: Sensor data stored in unions to minimize memory footprint
- Conditional Compilation: Features selectable via
WeatherSensorCfg.hmacros - Circular History Buffers: 60-minute history for rain/lightning with wraparound
- Preferences Storage: Flash-based persistence for sensor configs, rain/lightning history
- Slot-Based Multi-Sensor: Dynamic
std::vector<Sensor>for managing multiple sensors - Decoder Chain: Try decoders in order (7-in-1 → 6-in-1 → 5-in-1 → Lightning → Leakage) until success
- Classes:
CamelCase(e.g.,WeatherSensor,RainGauge) - Functions/Methods:
camelCase(e.g.,getMessage(),getData()) - Variables:
snake_case(e.g.,sensor_id,wind_speed_ms) - Constants/Macros:
UPPER_SNAKE_CASE(e.g.,NUM_SENSORS,BRESSER_5_IN_1) - Private Members: No specific prefix convention
src/
├── WeatherSensor.h/.cpp # Core receiver & decoder orchestration
├── WeatherSensorCfg.h # User configuration (pins, sensors, decoders)
├── WeatherSensorConfig.cpp # Runtime configuration via JSON
├── WeatherSensorDecoders.cpp # Protocol decoders (5/6/7-in-1, Lightning, Leakage)
├── WeatherUtils.h/.cpp # Utility functions (dew point, wind chill, etc.)
├── RainGauge.h/.cpp # Rain statistics module
├── Lightning.h/.cpp # Lightning post-processing module
└── InitBoard.h/.cpp # Board initialization
examples/
├── BresserWeatherSensorBasic/ # Simple receive & print
├── BresserWeatherSensorMQTT/ # MQTT integration
├── BresserWeatherSensorMQTTCustom/ # Advanced MQTT with local copy of library
└── [12 other examples]
test/
└── src/ # CppUTest unit tests
Every source file must include:
- File header comment block with:
- File name and purpose
- Project URL:
https://github.com/matthias-bs/BresserWeatherSensorReceiver - Credits/references to original work
- MIT License text
- Detailed history log with dates and changes
- Author: Matthias Prinke
- Include guards (not
#pragma once) - Arduino.h include for Arduino types
- Doxygen-style comments for public API
- Use
///for Doxygen comments on functions/classes - Use
//for inline explanations - Add
@brief,@param,@returntags for public methods - Reference rtl_433 project sources when applicable
- Document protocol details and sensor quirks extensively
- Indentation: 4 spaces (no tabs)
- Braces: Opening brace on same line for functions/classes
- Line Length: No strict limit, but keep readable (~100-120 chars preferred)
- Comments: Extensive inline documentation explaining RF protocols, sensor behavior, edge cases
- Debug Output: Use
log_d(),log_i(),log_w(),log_e()macros (ESP32/ESP8266) - Conditional Features: Wrap optional features in
#ifdef FEATURE_NAME
- Return
DecodeStatusenum from decoders (e.g.,DECODE_OK,DECODE_DIG_ERR,DECODE_CHK_ERR) - Use validation flags in structs (e.g.,
temp_ok,humidity_ok,wind_ok) - Check sensor startup flag to prevent false rain/lightning counts after battery replacement
- Validate CRC/checksums using
lfsr_digest16()orcrc16()
Use macros in WeatherSensorCfg.h to enable/disable features:
#define BRESSER_5_IN_1 // Enable 5-in-1 decoder
#define BRESSER_6_IN_1 // Enable 6-in-1 decoder
#define BRESSER_7_IN_1 // Enable 7-in-1 decoder
#define BRESSER_LIGHTNING // Enable lightning decoder
#define LIGHTNING_USE_PREFS // Store lightning history in flash#include <Preferences.h>
Preferences preferences;
preferences.begin("namespace", false); // false = read/write
uint32_t value = preferences.getUInt("key", default_value);
preferences.putUInt("key", value);
preferences.end();RainGauge rainGauge;
rainGauge.reset(); // Reset all statistics
rainGauge.update(timestamp, rain_mm, startup_flag);
float hourly = rainGauge.pastHour();
float daily = rainGauge.currentDay();Lightning lightning;
lightning.reset();
lightning.update(timestamp, strike_count, distance_km, startup_flag);
uint8_t strikes_past_hour = lightning.pastHour();// Add sensor configuration
std::vector<uint32_t> sensor_ids = {0x39582376};
weatherSensor.setSensorsCfg(sensor_ids);
// Get data with timeout
int decode_status = weatherSensor.getData(RX_TIMEOUT, DATA_COMPLETE);
if (decode_status == DECODE_OK) {
for (size_t i = 0; i < weatherSensor.sensor.size(); i++) {
if (weatherSensor.sensor[i].valid) {
uint32_t id = weatherSensor.sensor[i].sensor_id;
// Process sensor data...
}
}
}Decoders should:
- Check message length:
if (msg_size != EXPECTED_SIZE) return DECODE_INVALID; - Validate CRC/checksum:
if (calculated_crc != expected_crc) return DECODE_CHK_ERR; - Extract sensor ID and type
- Decode fields with proper scaling/units
- Set validity flags for each field
- Return
DecodeStatus
- ESP32 (primary target) - full feature support
- ESP8266 - limited RAM, use carefully with multiple sensors
- RP2040 - limited testing, basic features supported
Predefined board configs in WeatherSensorCfg.h:
LORAWAN_NODE- Custom board based on DFRobot FireBeetle ESP32DFROBOT_COVER_LORA- DFRobot FireBeetle ESP32 with FireBeetle Cover LoRa RadioTTGO_LORA32- TTGO ESP32 with integrated SX1276ADAFRUIT_FEATHER_ESP32S2- Adafruit Feather with RFM95WARDUINO_DFROBOT_FIREBEETLE_ESP32- DFRobot FireBeetle ESP32ESP32_LORA_V2- Heltec ESP32 LoRa V2M5CORE2_MODULE_LORA868- M5Stack Core2 with LoRa module
Define pins in WeatherSensorCfg.h:
#define PIN_RECEIVER_CS 27 // SPI chip select
#define PIN_RECEIVER_IRQ 21 // CC1101: GDO0 / SX127x: DIO0
#define PIN_RECEIVER_GPIO 33 // CC1101: GDO2 / SX127x: DIO1
#define PIN_RECEIVER_RST 32 // Reset pin (SX127x) or RADIOLIB_NC (CC1101)- CppUTest for unit tests (desktop)
- arduino-ci for Arduino library validation
#include "CppUTest/TestHarness.h"
TEST_GROUP(TestGroupName) {
void setup() { /* Initialize */ }
void teardown() { /* Cleanup */ }
};
TEST(TestGroupName, TestName) {
// Arrange
// Act
// Assert
DOUBLES_EQUAL(expected, actual, tolerance);
}# Run CppUTest
cd test
make
# Run Arduino CI
# Automated via GitHub Actions- RadioLib (7.5.0) - RF transceiver abstraction layer
- ArduinoJson (7.4.2) - JSON parsing for configuration
- Preferences (2.2.2) - Flash storage API (ESP32/ESP8266)
- MQTT (2.5.2) - MQTT client for IoT integrations
- WiFiManager (2.0.17) - WiFi credential management
- ESP_DoubleResetDetector (1.3.2) - Factory reset via double-reset
- ESPAsyncWebServer (3.9.4) - Web interface for configuration
- Adafruit_SSD1306 (2.5.16) - OLED display support
- RTClib (2.1.4) - Real-time clock support
- Add sensor type constant in
WeatherSensor.h(e.g.,#define SENSOR_TYPE_NEW 0xNN) - Add decoder function in
WeatherSensorDecoders.cpp:DecodeStatus decodeBresserNewPayload(const uint8_t *msg, uint8_t msgSize) { // Validate length and CRC // Extract sensor ID and type // Decode fields with proper units // Set validity flags return DECODE_OK; }
- Add decoder to chain in
WeatherSensor::decodeMessage() - Add conditional compilation guard:
#ifdef BRESSER_NEW - Document protocol details in comments
- Add board definition to
WeatherSensorCfg.h:#elif defined(MY_BOARD) #define PIN_RECEIVER_CS XX #define PIN_RECEIVER_IRQ XX #define PIN_RECEIVER_GPIO XX #define PIN_RECEIVER_RST XX
- Document pin connections
- Test RF reception and decoding
- Add transceiver type macro:
#define USE_NEW_RADIO - Add RadioLib module initialization in
WeatherSensor::begin() - Configure modulation parameters (FSK, frequency, bandwidth, etc.)
- Test message reception with known sensors
- ESP8266 has limited RAM (~40KB usable) - minimize heap allocations
- Use
std::vector.reserve()if max sensor count is known - Prefer stack allocation for temporary buffers
- Use unions for mutually exclusive sensor data types
- Set appropriate RX timeout based on sensor transmit intervals (typically 30-60 seconds)
- Handle incomplete 6-in-1 messages (alternating temp/humidity and rain/wind)
- Clear slots before each RX cycle to prevent stale data
- Check
startupflag to prevent false rain/lightning accumulation
- Support both include and exclude lists
- Use
rxFlags.DATA_COMPLETEcautiously - some sensors never provide complete data
- Use
CORE_DEBUG_LEVEL(ESP32) orWeatherSensorCfg.hdefines (ESP8266) - Add debug output with
log_d(),log_i(),log_v()macros - Use
DEBUG_OUTPUT.mdfor debug level documentation
- Follow semantic versioning (MAJOR.MINOR.PATCH)
- Update
library.propertiesversion field - Update
package.jsonversion field - Document changes in file history blocks
- Update
CHANGELOG.md(if present)
Examples demonstrate progressive complexity:
- Basic - Simple message reception and printing
- Waiting/Callback - Advanced reception strategies
- Options - Configuration customization
- OLED - Display integration
- MQTT - IoT platform integration
- MQTTCustom - Advanced MQTT with local library copy (for development)
- Domoticz/M5Core2/CanvasGauges/SDCard - Specific use cases
- Publish sensor data as JSON to topic:
<base_topic>/data - Support MQTT auto-discovery (Home Assistant format)
- Include sensor ID, type, and all available measurements
- Handle TLS/SSL for secure connections
- Use MQTT auto-discovery protocol
- Publish discovery configs to:
homeassistant/<component>/<object_id>/config - Set appropriate device classes (temperature, humidity, etc.)
- Include unique IDs based on sensor ID
- Never commit WiFi credentials or MQTT passwords
- Use
secrets.h(gitignored) for sensitive data - Define
SECRETSmacro when using separate secrets file - Support secure WiFi (WPA2) and secure MQTT (TLS/SSL)
- Bresser5in1-CC1101 by Sean Siford - Initial CC1101 implementation
- RadioLib by Jan Gromeš - RF transceiver library
- rtl_433 by Benjamin Larsson - Protocol specifications and decoders
- Repository: https://github.com/matthias-bs/BresserWeatherSensorReceiver
- Wiki: https://github.com/matthias-bs/BresserWeatherSensorReceiver/wiki
- Issues: https://github.com/matthias-bs/BresserWeatherSensorReceiver/issues
- Discussions: Use GitHub Issues for questions and feature requests
This project is licensed under the MIT License. All contributions must maintain the MIT license header in source files.