1 /* Bresser sensor protocol
3 * The protocol is for the wireless Temperature/Humidity sensor
4 * Bresser Thermo-/Hygro-Sensor 3CH
6 * The sensor sends 15 identical packages of 40 bits each ~60s.
7 * The bits are PWM modulated with On Off Keying.
9 * A short pulse of 250 us followed by a 500 us gap is a 0 bit,
10 * a long pulse of 500 us followed by a 250 us gap is a 1 bit,
11 * there is a sync preamble of pulse, gap, 750 us each, repeated 4 times.
12 * Actual received and demodulated timings might be 2% shorter.
14 * The data is grouped in 5 bytes / 10 nibbles
15 * [id] [id] [flags] [temp] [temp] [temp] [humi] [humi] [chk] [chk]
17 * id is an 8 bit random id that is generated when the sensor starts
18 * flags are 4 bits battery low indicator, test button press and channel
19 * temp is 12 bit unsigned fahrenheit offset by 90 and scaled by 10
20 * humi is 8 bit relative humidity percentage
22 * Copyright (C) 2015 Christian W. Zuckschwerdt <zany@triq.net>
25 #include "pulse_demod.h"
29 static int bresser_3ch_callback(bitbuffer_t *bitbuffer) {
30 bitrow_t *bb = bitbuffer->bb;
32 char time_str[LOCAL_TIME_BUFLEN];
34 int id, status, battery_low, test, channel, temp_raw, humidity;
38 4 double wide sync pulses each go to an own row, the rows length will be
39 1 1 1 1 41 1 1 1 1 41 1 1 1 1 41 1 1 1 1 41 1 1 1 1 491
41 int r = bitbuffer_find_repeated_row(bitbuffer, 3, 40);
42 if (r < 0 || bitbuffer->bits_per_row[r] > 41) {
53 if (((b[0] + b[1] + b[2] + b[3] - b[4]) & 0xFF) != 0) {
55 fprintf(stderr, "Bresser 3CH checksum error\n");
62 battery_low = (b[1] & 0x80) >> 7;
63 test = (b[1] & 0x40) >> 6;
64 channel = (b[1] & 0x30) >> 4;
66 temp_raw = ((b[1] & 0x0F) << 8) + b[2];
67 // 12 bits allows for values -90.0 F - 319.6 F (-67 C - 159 C)
68 temp_f = (temp_raw - 900) / 10.0;
72 if ((channel == 0) || (humidity > 100) || (temp_f < -20.0) || (temp_f > 160.0)) {
74 fprintf(stderr, "Bresser 3CH data error\n");
79 local_time_str(0, time_str);
80 data = data_make("time", "", DATA_STRING, time_str,
81 "model", "", DATA_STRING, "Bresser 3CH sensor",
82 "id", "", DATA_INT, id,
83 "channel", "Channel", DATA_INT, channel,
84 "battery", "Battery", DATA_STRING, battery_low ? "LOW": "OK",
85 "temperature_F", "Temperature", DATA_FORMAT, "%.2f F", DATA_DOUBLE, temp_f,
86 "humidity", "Humidity", DATA_FORMAT, "%u %%", DATA_INT, humidity,
88 data_acquired_handler(data);
93 static char *output_fields[] = {
104 r_device bresser_3ch = {
105 .name = "Bresser Thermo-/Hygro-Sensor 3CH",
106 .modulation = OOK_PULSE_PWM_RAW,
107 .short_limit = 375, // short pulse is ~250 us, long pulse is ~500 us
108 .long_limit = 625, // long gap (with short pulse) is ~500 us, sync gap is ~750 us
109 .reset_limit = 1250, // maximum gap is 1000 us (long gap + longer sync gap on last repeat)
110 .json_callback = &bresser_3ch_callback,
113 .fields = output_fields,