Skip to content

Commit

Permalink
Add support for Bresser water leakage sensor PN: 7009975 (#2590)
Browse files Browse the repository at this point in the history
  • Loading branch information
matthias-bs authored Oct 22, 2023
1 parent a76f169 commit e72e7d5
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 0 deletions.
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 @@ convert si
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 <m.prinke@arcor.de>
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;

// 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,
};

0 comments on commit e72e7d5

Please sign in to comment.