Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Bresser water leakage sensor, PN: 7009975 #2590

Merged
merged 17 commits into from
Oct 22, 2023
Merged
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,7 @@ See [CONTRIBUTING.md](./docs/CONTRIBUTING.md).
[244] Fine Offset Electronics WS90 weather station
[245]* ThermoPro TX-2C Thermometer and Humidity sensor
[246] TFA 30.3151 Weather Station
[247] Bresser water leakage

* Disabled by default, use -R n or a conf file to enable

Expand Down
1 change: 1 addition & 0 deletions conf/rtl_433.example.conf
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,7 @@ stop_after_successful_events false
protocol 244 # Fine Offset Electronics WS90 weather station
# protocol 245 # ThermoPro TX-2C Thermometer and Humidity sensor
protocol 246 # TFA 30.3151 Weather Station
protocol 247 # Bresser water leakage

## Flex devices (command line option "-X")

Expand Down
1 change: 1 addition & 0 deletions include/rtl_433_devices.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@
DECL(fineoffset_ws90) \
DECL(thermopro_tx2c) \
DECL(tfa_303151) \
DECL(bresser_leakage) \

/* Add new decoders here. */

Expand Down
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ add_library(r_433 STATIC
devices/bresser_5in1.c
devices/bresser_6in1.c
devices/bresser_7in1.c
devices/bresser_leakage.c
devices/bt_rain.c
devices/burnhardbbq.c
devices/calibeur.c
Expand Down
165 changes: 165 additions & 0 deletions src/devices/bresser_leakage.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
/** @file
Bresser Water Leakage Sensor.

Copyright (C) 2023 Matthias Prinke <[email protected]>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
*/

#define SENSOR_TYPE_LEAKAGE 5

/**
Decoder for Bresser Water Leakage outdoor sensor, PN 7009975

see https://github.com/merbanan/rtl_433/issues/2576

Based on bresser_6in1.c

Preamble: aa aa 2d d4

Data layout:
CCCCCCCC CCCCCCCC IIIIIIII IIIIIIII IIIIIIII IIIIIIII SSSSQHHH ANBBFFFF

- C: 16-bit, crc16/xmodem, polynomial: 0x1021, init: 0x0000, range: byte 2...6
- I: 24-bit little-endian id; changes on power-up/reset
- S: 4 bit sensor type
- Q: 1 bit startup; changes from 0 to 1 approx. one hour after power-on/reset
- H: 3 bit channel; set via switch on the device, latched at power-on/reset
- A: 1 bit alarm
- N: 1 bit no_alarm; inverse of alarm
- B: 2 bit battery state; 0b11 if battery is o.k.
- F: 4 bit flags (always 0b0000)


Examples:
---------
[Bresser Water Leakage Sensor, PN 7009975]

[00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25]

C7 70 35 97 04 08 57 70 00 00 00 00 00 00 00 00 03 FF FF FF FF FF FF FF FF FF [CH7]
DF 7D 36 49 27 09 56 70 00 00 00 00 00 00 00 00 03 FF FF FF FF FF FF FF FF FF [CH6]
9E 30 79 84 33 06 55 70 00 00 00 00 00 00 00 00 03 FF FD DF FF BF FF DF FF FF [CH5]
E2 C8 68 27 91 24 54 70 00 00 00 00 00 00 00 00 03 FF FF FF FF FF FF FF FF FF [CH4]
B3 DA 55 57 17 40 53 70 00 00 00 00 00 00 00 00 03 FF FF FF FF FF FF FF FF FB [CH3]
37 FA 84 73 03 02 52 70 00 00 00 00 00 00 00 00 03 FF FF FF DF FF FF FF FF FF [CH2]
27 F3 80 02 52 88 51 70 00 00 00 00 00 00 00 00 03 FF FF FF FF FF DF FF FF FF [CH1]
A6 FB 80 02 52 88 59 70 00 00 00 00 00 00 00 00 03 FD F7 FF FF BF FF FF FF FF [CH1+NSTARTUP]
A6 FB 80 02 52 88 59 B0 00 00 00 00 00 00 00 00 03 FF FF FF FD FF F7 FF FF FF [CH1+NSTARTUP+ALARM]
A6 FB 80 02 52 88 59 70 00 00 00 00 00 00 00 00 03 FF FF BF F7 F7 FD 7F FF FF [CH1+NSTARTUP]
[Reset]
C0 10 36 79 37 09 51 70 00 00 00 00 00 00 00 00 01 1E FD FD FF FF FF DF FF FF [CH1]
C0 10 36 79 37 09 51 B0 00 00 00 00 00 00 00 00 03 FE FD FF AF FF FF FF FF FD [CH1+ALARM]
[Reset]
71 9C 54 81 72 09 51 40 00 00 00 00 00 00 00 00 0F FF FF FF FF FF FF DF FF FE [CH1+BATT_LO]
71 9C 54 81 72 09 51 40 00 00 00 00 00 00 00 00 0F FE FF FF FF FF FB FF FF FF
71 9C 54 81 72 09 51 40 00 00 00 00 00 00 00 00 07 FD F7 FF DF FF FF DF FF FF
71 9C 54 81 72 09 51 80 00 00 00 00 00 00 00 00 1F FF FF F7 FF FF FF FF FF FF [CH1+BATT_LO+ALARM]
F0 94 54 81 72 09 59 40 00 00 00 00 00 00 00 00 0F FF DF FF FF FF FF BF FD F7 [CH1+BATT_LO+NSTARTUP]
F0 94 54 81 72 09 59 80 00 00 00 00 00 00 00 00 03 FF B7 FF ED FF FF FF DF FF [CH1+BATT_LO+NSTARTUP+ALARM]

*/

#include "decoder.h"

static int bresser_leakage_decode(r_device *decoder, bitbuffer_t *bitbuffer)
{
uint8_t const preamble_pattern[] = {0xaa, 0xaa, 0x2d, 0xd4};
data_t *data;
uint8_t msg[18];
uint32_t sensor_id;
uint8_t s_type;
uint8_t chan;
uint8_t startup;
uint8_t battery_ok;
int alarm;
int no_alarm;
int decode_ok;

if (bitbuffer->num_rows != 1
|| bitbuffer->bits_per_row[0] < 160
|| bitbuffer->bits_per_row[0] > 440) {
decoder_logf(decoder, 2, __func__, "bit_per_row %u out of range", bitbuffer->bits_per_row[0]);
return DECODE_ABORT_EARLY; // Unrecognized data
}

unsigned start_pos = bitbuffer_search(bitbuffer, 0, 0,
preamble_pattern, sizeof (preamble_pattern) * 8);

if (start_pos >= bitbuffer->bits_per_row[0]) {
return DECODE_ABORT_LENGTH;
}
start_pos += sizeof (preamble_pattern) * 8;

unsigned len = bitbuffer->bits_per_row[0] - start_pos;
if (len < sizeof(msg) * 8) {
decoder_logf(decoder, 2, __func__, "%u too short", len);
return DECODE_ABORT_LENGTH; // message too short
}

bitbuffer_extract_bytes(bitbuffer, 0, start_pos, msg, sizeof(msg) * 8);

decoder_log_bitrow(decoder, 2, __func__, msg, sizeof(msg) * 8, "");

// CRC check
uint16_t crc_calculated = crc16(&msg[2], 5, 0x1021, 0x0000);
uint16_t crc_received = msg[0] << 8 | msg[1];
decoder_logf(decoder, 2, __func__, "CRC 0x%04X = 0x%04X", crc_calculated, crc_received);
if (crc_received != crc_calculated) {
decoder_logf(decoder, 1, __func__, "CRC check failed (0x%04X != 0x%04X)", crc_calculated, crc_received);
return DECODE_FAIL_MIC;
}

sensor_id = ((uint32_t)msg[2] << 24) | (msg[3] << 16) | (msg[4] << 8) | (msg[5]);
s_type = msg[6] >> 4;
chan = (msg[6] & 0x7);
battery_ok = ((msg[7] & 0x30) != 0x00) ? 1 : 0;
startup = (msg[6] >> 3) & 1;
alarm = ((msg[7] & 0x80) == 0x80) ? 1 : 0;
no_alarm = ((msg[7] & 0x40) == 0x40) ? 1 : 0;

matthias-bs marked this conversation as resolved.
Show resolved Hide resolved
// Sanity checks
decode_ok = (s_type == SENSOR_TYPE_LEAKAGE) &&
(alarm != no_alarm) &&
(chan != 0);

if (!decode_ok)
return 0;

/* clang-format off */
data = data_make(
"model", "", DATA_STRING, "Bresser-Leakage",
"id", "", DATA_FORMAT, "%08x", DATA_INT, sensor_id,
"channel", "", DATA_INT, chan,
"battery_ok", "Battery", DATA_INT, battery_ok,
"alarm", "Alarm", DATA_INT, alarm,
"startup", "Startup", DATA_COND, startup, DATA_INT, startup,
NULL);
/* clang-format on */

decoder_output_data(decoder, data);
return 1;
}

static char const *const output_fields[] = {
"model",
"id",
"channel",
"battery_ok",
"startup",
"alarm",
NULL,
};

r_device const bresser_leakage = {
.name = "Bresser water leakage",
.modulation = FSK_PULSE_PCM,
.short_width = 124,
.long_width = 124,
.reset_limit = 25000,
.decode_fn = &bresser_leakage_decode,
.fields = output_fields,
};
Loading