Skip to content

Commit b9b8650

Browse files
authored
Add Support of Bresser 8-in-1 Weather Sensor (#221)
* Initial support of Bresser 8-in-1 weather sensor * Added Globe Thermometer Temperature * Disabled m5stack_core2 due to compiler error
1 parent f181d10 commit b9b8650

File tree

13 files changed

+117
-18
lines changed

13 files changed

+117
-18
lines changed

.github/workflows/CI.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
- esp32:esp32:heltec_wifi_lora_32_V3
2828
- esp32:esp32:adafruit_feather_esp32s2
2929
- esp32:esp32:featheresp32
30-
- esp32:esp32:m5stack_core2
30+
#- esp32:esp32:m5stack_core2
3131
#- esp32:esp32:esp32s3_powerfeather
3232
- esp8266:esp8266:generic:dbg=Disabled
3333
- esp8266:esp8266:generic:dbg=Serial

examples/BresserWeatherSensorBasic/BresserWeatherSensorBasic.ino

+10
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
// 20240209 Added Leakage, Air Quality (HCHO/VOC) and CO2 Sensors
5252
// 20240213 Added PM1.0 to Air Quality (Particulate Matter) Sensor decoder
5353
// 20240716 Fixed output of invalid battery state with 6-in-1 decoder
54+
// 20250127 Added Globe Thermometer Temperature (8-in-1 Weather Sensor)
5455
//
5556
// ToDo:
5657
// -
@@ -217,6 +218,15 @@ void loop()
217218
else {
218219
Serial.printf("Light: [--.-klx] ");
219220
}
221+
if (ws.sensor[i].s_type == SENSOR_TYPE_WEATHER2) {
222+
if (ws.sensor[i].w.tglobe_ok) {
223+
Serial.printf("T_globe: [%3.1fC] ",
224+
ws.sensor[i].w.tglobe_c);
225+
}
226+
else {
227+
Serial.printf("T_globe: [--.-C] ");
228+
}
229+
}
220230
#endif
221231
Serial.printf("\n");
222232

examples/BresserWeatherSensorCallback/BresserWeatherSensorCallback.ino

+10
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
// 20220815 Changed to modified WeatherSensor class; added support of multiple sensors
4545
// 20221227 Replaced DEBUG_PRINT/DEBUG_PRINTLN by Arduino logging functions
4646
// 20240507 Added configuration of maximum number of sensors at run time
47+
// 20250127 Added Globe Thermometer Temperature (8-in-1 Weather Sensor)
4748
//
4849
// ToDo:
4950
// -
@@ -188,6 +189,15 @@ void loop()
188189
{
189190
Serial.printf("Light: [--.-Klux] ");
190191
}
192+
if (ws.sensor[i].s_type == SENSOR_TYPE_WEATHER2) {
193+
if (ws.sensor[i].w.tglobe_ok) {
194+
Serial.printf("T_globe: [%3.1fC] ",
195+
ws.sensor[i].w.tglobe_c);
196+
}
197+
else {
198+
Serial.printf("T_globe: [--.-C] ");
199+
}
200+
}
191201
#endif
192202
Serial.printf("\n");
193203

examples/BresserWeatherSensorMQTT/BresserWeatherSensorMQTT.ino

+8
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@
120120
// 20240507 Added configuration of maximum number of sensors at run time
121121
// 20240603 Modified for arduino-esp32 v3.0.0
122122
// 20241113 Added getting/setting of sensor include/exclude lists via MQTT
123+
// 20250127 Added Globe Thermometer Temperature (8-in-1 Weather Sensor)
123124
//
124125
// ToDo:
125126
//
@@ -675,6 +676,7 @@ void publishWeatherdata(bool complete)
675676
}
676677
else if ((weatherSensor.sensor[i].s_type == SENSOR_TYPE_WEATHER0) ||
677678
(weatherSensor.sensor[i].s_type == SENSOR_TYPE_WEATHER1) ||
679+
(weatherSensor.sensor[i].s_type == SENSOR_TYPE_WEATHER2) ||
678680
(weatherSensor.sensor[i].s_type == SENSOR_TYPE_THERMO_HYGRO) ||
679681
(weatherSensor.sensor[i].s_type == SENSOR_TYPE_POOL_THERMO))
680682
{
@@ -717,6 +719,12 @@ void publishWeatherdata(bool complete)
717719
{
718720
mqtt_payload += String(",\"light_klx\":") + JSON_FLOAT(String(weatherSensor.sensor[i].w.light_klx, 1));
719721
}
722+
if (weatherSensor.sensor[i].s_type == SENSOR_TYPE_WEATHER2) {
723+
if (weatherSensor.sensor[i].w.tglobe_ok || complete)
724+
{
725+
mqtt_payload += String(",\"t_globe_c\":") + JSON_FLOAT(String(weatherSensor.sensor[i].w.tglobe_c, 1));
726+
}
727+
}
720728
if (weatherSensor.sensor[i].w.rain_ok || complete)
721729
{
722730
mqtt_payload += String(",\"rain\":") + JSON_FLOAT(String(weatherSensor.sensor[i].w.rain_mm, 1));

examples/BresserWeatherSensorMQTTCustom/BresserWeatherSensorMQTTCustom.ino

+7
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@
120120
// 20240507 Added configuration of maximum number of sensors at run time
121121
// 20240603 Modified for arduino-esp32 v3.0.0
122122
// 20241113 Added getting/setting of sensor include/exclude lists via MQTT
123+
// 20250127 Added Globe Thermometer Temperature (8-in-1 Weather Sensor)
123124
//
124125
// ToDo:
125126
//
@@ -717,6 +718,12 @@ void publishWeatherdata(bool complete)
717718
{
718719
mqtt_payload += String(",\"light_klx\":") + JSON_FLOAT(String(weatherSensor.sensor[i].w.light_klx, 1));
719720
}
721+
if (weatherSensor.sensor[i].s_type == SENSOR_TYPE_WEATHER2) {
722+
if (weatherSensor.sensor[i].w.tglobe_ok || complete)
723+
{
724+
mqtt_payload += String(",\"t_globe_c\":") + JSON_FLOAT(String(weatherSensor.sensor[i].w.tglobe_c, 1));
725+
}
726+
}
720727
if (weatherSensor.sensor[i].w.rain_ok || complete)
721728
{
722729
mqtt_payload += String(",\"rain\":") + JSON_FLOAT(String(weatherSensor.sensor[i].w.rain_mm, 1));

examples/BresserWeatherSensorMQTTCustom/src/WeatherSensor.h

+10-5
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@
8484
// 20240714 Added decoder to struct Sensor
8585
// 20240716 Added option to skip initialization of filters in begin()
8686
// 20241113 Added getting/setting of sensor include/exclude list from JSON strings
87+
// 20250127 Added SENSOR_TYPE_WEATHER2 (8-in-1 Weather Sensor)
8788
//
8889
// ToDo:
8990
// -
@@ -100,7 +101,7 @@
100101
#include <RadioLib.h>
101102

102103

103-
// Sensor Types
104+
// Sensor Types / Decoders / Part Numbers
104105
// 0 - Weather Station 5-in-1; PN 7002510..12/7902510..12
105106
// 1 - Weather Station 6-in-1; PN 7002585
106107
// - Professional Wind Gauge 6-in-1; PN 7002531
@@ -114,6 +115,7 @@
114115
// 9 - Lightning Sensor PN 7009976
115116
// 10 - CO2 Sensor 7-in-1; PN 7009977
116117
// 11 - HCHO/VCO Sensor 7-in-1; PN 7009978
118+
// 13 - Weather Station (8-in-1) 7-in-1; PN 7003150
117119
#define SENSOR_TYPE_WEATHER0 0 // Weather Station
118120
#define SENSOR_TYPE_WEATHER1 1 // Weather Station
119121
#define SENSOR_TYPE_THERMO_HYGRO 2 // Thermo-/Hygro-Sensor
@@ -125,6 +127,7 @@
125127
#define SENSOR_TYPE_LIGHTNING 9 // Lightning Sensor
126128
#define SENSOR_TYPE_CO2 10 // CO2 Sensor
127129
#define SENSOR_TYPE_HCHO_VOC 11 // Air Quality Sensor (HCHO and VOC)
130+
#define SENSOR_TYPE_WEATHER2 13 // Weather Station (8-in-1)
128131

129132

130133
// Sensor specific rain gauge overflow threshold (mm)
@@ -159,7 +162,7 @@ typedef enum DecodeStatus {
159162
* \brief Mapping of sensor IDs to names
160163
*/
161164
typedef struct SensorMap {
162-
uint32_t id; //!< ID if sensor (as transmitted in radio message)
165+
uint32_t id; //!< ID of sensor (as transmitted in radio message)
163166
std::string name; //!< Name of sensor (e.g. for MQTT topic)
164167
} SensorMap;
165168

@@ -196,7 +199,7 @@ class WeatherSensor {
196199
void sleep(void);
197200

198201
/*!
199-
\brief Wait for reception of data or occurrance of timeout.
202+
\brief Wait for reception of data or occurrence of timeout.
200203
With BRESSER_6_IN_1, data is distributed across two different messages. Reception of entire
201204
data is tried if 'complete' is set.
202205
@@ -209,7 +212,7 @@ class WeatherSensor {
209212
\param func Callback function for each loop iteration. (default: NULL)
210213
211214
\returns false: Timeout occurred.
212-
true: Reception (according to parammeter 'complete') successful.
215+
true: Reception (according to parameter 'complete') successful.
213216
*/
214217
bool getData(uint32_t timeout, uint8_t flags = 0, uint8_t type = 0, void (*func)() = NULL);
215218

@@ -232,12 +235,14 @@ class WeatherSensor {
232235

233236
struct Weather {
234237
bool temp_ok = false; //!< temperature o.k. (only 6-in-1)
238+
bool tglobe_ok = false; //!< globe temperature o.k. (only 8-in-1)
235239
bool humidity_ok = false; //!< humidity o.k.
236240
bool light_ok = false; //!< light o.k. (only 7-in-1)
237241
bool uv_ok = false; //!< uv radiation o.k. (only 6-in-1)
238242
bool wind_ok = false; //!< wind speed/direction o.k. (only 6-in-1)
239243
bool rain_ok = false; //!< rain gauge level o.k.
240244
float temp_c = 0.0; //!< temperature in degC
245+
float tglobe_c = 0.0; //!< globe temperature in degC (only 8-in-1)
241246
float light_klx = 0.0; //!< Light KLux (only 7-in-1)
242247
float light_lux = 0.0; //!< Light lux (only 7-in-1)
243248
float uv = 0.0; //!< uv radiation (only 6-in-1 & 7-in-1)
@@ -291,7 +296,7 @@ class WeatherSensor {
291296

292297
struct AirVOC {
293298
uint16_t hcho_ppb; //!< formaldehyde concentration in ppb
294-
uint8_t voc_level; //!< volatile organic oompounds; 1 - bad air quality .. 5 - very good air quality
299+
uint8_t voc_level; //!< volatile organic compounds; 1 - bad air quality .. 5 - very good air quality
295300
bool hcho_init; //!< measurement value invalid due to initialization
296301
bool voc_init; //!< measurement value invalid due to initialization
297302
};

examples/BresserWeatherSensorMQTTCustom/src/WeatherSensorDecoders.cpp

+16-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
///////////////////////////////////////////////////////////////////////////////////////////////////
2-
// WeatherSensorDecoder.cpp
2+
// WeatherSensorDecoders.cpp
33
//
44
// Sensor data decoding functions
55
//
@@ -198,7 +198,7 @@ DecodeStatus WeatherSensor::decodeMessage(const uint8_t *msg, uint8_t msgSize)
198198
}
199199

200200
//
201-
// From from rtl_433 project - https://github.com/merbanan/rtl_433/blob/master/src/devices/bresser_5in1.c (20220212)
201+
// From rtl_433 project - https://github.com/merbanan/rtl_433/blob/master/src/devices/bresser_5in1.c (20220212)
202202
//
203203
// Example input data:
204204
// EA EC 7F EB 5F EE EF FA FE 76 BB FA FF 15 13 80 14 A0 11 10 05 01 89 44 05 00
@@ -244,7 +244,7 @@ DecodeStatus WeatherSensor::decodeBresser5In1Payload(const uint8_t *msg, uint8_t
244244
}
245245
}
246246

247-
// Verify checksum (number number bits set in bytes 14-25)
247+
// Verify checksum (number bits set in bytes 14-25)
248248
uint8_t bitsSet = 0;
249249
uint8_t expectedBitsSet = msg[13];
250250

@@ -604,7 +604,7 @@ DecodeStatus WeatherSensor::decodeBresser6In1Payload(const uint8_t *msg, uint8_t
604604
#endif
605605

606606
//
607-
// From from rtl_433 project - https://github.com/merbanan/rtl_433/blob/master/src/devices/bresser_7in1.c (20230215)
607+
// From rtl_433 project - https://github.com/merbanan/rtl_433/blob/master/src/devices/bresser_7in1.c (20230215)
608608
//
609609
/**
610610
Decoder for Bresser Weather Center 7-in-1, outdoor sensor.
@@ -752,8 +752,9 @@ DecodeStatus WeatherSensor::decodeBresser7In1Payload(const uint8_t *msg, uint8_t
752752
sensor[slot].complete = true;
753753
sensor[slot].rssi = rssi;
754754

755-
if (s_type == SENSOR_TYPE_WEATHER1)
755+
if ((s_type == SENSOR_TYPE_WEATHER1) || (s_type == SENSOR_TYPE_WEATHER2))
756756
{
757+
sensor[slot].w.tglobe_ok = false;
757758
int wdir = (msgw[4] >> 4) * 100 + (msgw[4] & 0x0f) * 10 + (msgw[5] >> 4);
758759
int wgst_raw = (msgw[7] >> 4) * 100 + (msgw[7] & 0x0f) * 10 + (msgw[8] >> 4);
759760
int wavg_raw = (msgw[8] & 0x0f) * 100 + (msgw[9] >> 4) * 10 + (msgw[9] & 0x0f);
@@ -795,6 +796,15 @@ DecodeStatus WeatherSensor::decodeBresser7In1Payload(const uint8_t *msg, uint8_t
795796
sensor[slot].w.light_klx = light_klx;
796797
sensor[slot].w.light_lux = light_lux;
797798
sensor[slot].w.uv = uv_index;
799+
800+
if (s_type == SENSOR_TYPE_WEATHER2)
801+
{
802+
// 8-in-1 sensor
803+
if ((msgw[23] >> 4) < 10) {
804+
sensor[slot].w.tglobe_ok = true;
805+
sensor[slot].w.tglobe_c = (msgw[22] >> 4) * 10 + (msgw[22] & 0x0f) + (msgw[23] >> 4) * 0.1f;
806+
}
807+
}
798808
}
799809
else if (s_type == SENSOR_TYPE_AIR_PM)
800810
{
@@ -1026,4 +1036,4 @@ DecodeStatus WeatherSensor::decodeBresserLeakagePayload(const uint8_t *msg, uint
10261036

10271037
return DECODE_OK;
10281038
}
1029-
#endif
1039+
#endif

examples/BresserWeatherSensorMQTTWifiMgr/BresserWeatherSensorMQTTWifiMgr.ino

+7
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@
105105
// 20240507 Added configuration of maximum number of sensors at run time
106106
// 20240603 Modified for arduino-esp32 v3.0.0
107107
// 20241113 Added getting/setting of sensor include/exclude lists via MQTT
108+
// 20250127 Added Globe Thermometer Temperature (8-in-1 Weather Sensor)
108109
//
109110
// ToDo:
110111
//
@@ -901,6 +902,12 @@ void publishWeatherdata(bool complete)
901902
{
902903
mqtt_payload += String(",\"light_klx\":") + JSON_FLOAT(String(weatherSensor.sensor[i].w.light_klx, 1));
903904
}
905+
if (weatherSensor.sensor[i].s_type == SENSOR_TYPE_WEATHER2) {
906+
if (weatherSensor.sensor[i].w.tglobe_ok || complete)
907+
{
908+
mqtt_payload += String(",\"t_globe_c\":") + JSON_FLOAT(String(weatherSensor.sensor[i].w.tglobe_c, 1));
909+
}
910+
}
904911
if (weatherSensor.sensor[i].w.rain_ok || complete)
905912
{
906913
mqtt_payload += String(",\"rain\":") + JSON_FLOAT(String(weatherSensor.sensor[i].w.rain_mm, 1));

examples/BresserWeatherSensorOptions/BresserWeatherSensorOptions.ino

+12
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
// 20231027 Refactored sensor structure
3939
// 20240504 Added board initialization
4040
// 20240507 Added configuration of maximum number of sensors at run time
41+
// 20250127 Added Globe Thermometer Temperature (8-in-1 Weather Sensor)
4142
//
4243
// ToDo:
4344
// -
@@ -164,6 +165,17 @@ void print_data(void)
164165
{
165166
Serial.printf("Light: [--.-Klux] ");
166167
}
168+
if (ws.sensor[i].s_type == SENSOR_TYPE_WEATHER2) {
169+
if (ws.sensor[i].w.tglobe_ok)
170+
{
171+
Serial.printf("T_globe: [%3.1fC] ",
172+
ws.sensor[i].w.tglobe_c);
173+
}
174+
else
175+
{
176+
Serial.printf("T_globe: [--.-C] ");
177+
}
178+
}
167179
#endif
168180
Serial.printf("\n");
169181
} // for (size_t i=0; i<ws.sensor.size(); i++)

examples/BresserWeatherSensorTest/BresserWeatherSensorTest.ino

+16-2
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
// 20231027 Refactored sensor structure
4545
// 20240209 Added Air Quality (HCHO/VOC), Air Quality (PM2.5/PM10), CO2 Sensor and Pool Thermometer
4646
// 20240504 Added board initialization
47+
// 20250127 Added 8-in-1 Weather Sensor sample data
4748
//
4849
// ToDo:
4950
// -
@@ -98,7 +99,11 @@ const uint8_t testData[][MSG_BUF_SIZE-1] = {
9899

99100
// #10: Air Quality (HCHO/VOC) Sensor
100101
{0x0c, 0x1c, 0xc4, 0xa5, 0xaa, 0xaf, 0xb1, 0xaa, 0xa8, 0xaa, 0xa8, 0xaa, 0xa8, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
101-
0xaa, 0xaa, 0xe9, 0xff, 0xaa, 0xaa, 0x00}
102+
0xaa, 0xaa, 0xe9, 0xff, 0xaa, 0xaa, 0x00},
103+
104+
// #11: 8-in-1 Weather Sensor
105+
{0x6E, 0xA7, 0xC8, 0xEB, 0x88, 0x2A, 0xD8, 0xAD, 0xAA, 0xFD, 0xAA, 0xA8, 0x98, 0xAA, 0xBF, 0xFC, 0x3E, 0xAA, 0x82,
106+
0x22, 0xAA, 0xAA, 0xBE, 0x3A, 0xAA, 0x00}
102107
};
103108

104109
WeatherSensor ws;
@@ -127,7 +132,7 @@ void loop()
127132
// Timeout occurs after a small multiple of expected time-on-air.
128133
DecodeStatus decode_status = ws.decodeMessage(&testData[idx][0], MSG_BUF_SIZE-1);
129134

130-
idx = (idx == 10) ? 0 : idx+1;
135+
idx = (idx == 12) ? 0 : idx+1;
131136
Serial.printf("testData[%d]\n", idx);
132137

133138
if (decode_status == DECODE_OK) {
@@ -242,6 +247,15 @@ void loop()
242247
else {
243248
Serial.printf("Light: [--.-Klux] ");
244249
}
250+
if (ws.sensor[i].s_type == SENSOR_TYPE_WEATHER2) {
251+
if (ws.sensor[i].w.tglobe_ok) {
252+
Serial.printf("T_globe: [%3.1fC] ",
253+
ws.sensor[i].w.tglobe_c);
254+
}
255+
else {
256+
Serial.printf("T_globe: [--.-C] ");
257+
}
258+
}
245259
#endif
246260
Serial.printf("\n");
247261
}

src/WeatherSensor.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@
104104
// 20240714 Added option to skip initialization of include/exclude lists
105105
// 20241205 Added radio LR1121
106106
// 20241227 Added LilyGo T3 S3 LR1121 RF switch and TCXO configuration
107+
// 20250127 Added SENSOR_TYPE_WEATHER2 (8-in-1 Weather Sensor) to 7-in-1 decoder
107108
//
108109
// ToDo:
109110
// -

0 commit comments

Comments
 (0)