mirror of https://github.com/merbanan/rtl_433.git
127 lines
4.2 KiB
C
127 lines
4.2 KiB
C
/** @file
|
|
TFA Dostmann 30.3196 T/H outdoor sensor.
|
|
|
|
Copyright (c) 2019 Christian W. Zuckschwerdt <zany@triq.net>
|
|
Documented by Ekkehart Tessmer.
|
|
|
|
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.
|
|
*/
|
|
|
|
/**
|
|
TFA Dostmann 30.3196 T/H outdoor sensor at 868.33M.
|
|
|
|
https://www.tfa-dostmann.de/en/produkt/temperature-humidity-transmitter-11/
|
|
https://clientmedia.trade-server.net/1768_tfadost/media/7/86/3786.pdf
|
|
|
|
The device comes with 'TFA Modus Plus' (indoor) base station.
|
|
Up to three outdoor sensors can be operated (ch 1, 2, or 3).
|
|
|
|
- At the start there is a 6 ms gap (FSK space)
|
|
- Data is Manchester coded with a half-bit width of 245 us
|
|
- The data row is repeated four times with 7 ms gaps (FSK space)
|
|
|
|
- A second layer of manchester coding yields 16 bit preamble and 48 bits data
|
|
- The 64 bits of preamble 0xcccccccccccccccc, after first MC 0xaaaaaaaa, after second MC 0xffff
|
|
- A data row consists of 48 bits (6 Bytes).
|
|
|
|
Data layout:
|
|
|
|
FFFFFFFF ??CCTTTT TTTTTTTT BHHHHHHH AAAAAAAA AAAAAAAA
|
|
|
|
- F: 8 bit Fixed message type 0xA8. d2d2d333 -> 9995 -> 57 (~ A8)
|
|
- C: 2 bit Channel number (1,2,3,X)
|
|
- T: 12 bit Temperature (Celsius) offset 40 scaled 10
|
|
- B: 1 bit Low battery indicator
|
|
- H: 7 bit Humidity
|
|
- A: 16 bit LFSR hash, gen 0x8810, key 0x22d0
|
|
- e.g. TYPE:8h ?2h CH:2d TEMP:12d BATT:1b HUM:7d CHK?16h
|
|
|
|
Example data:
|
|
|
|
a8 21 fa 5b 38 54 : 10101000 00100001 11111010 01011011 00111000 01010100
|
|
a8 22 22 5e 90 48 : 10101000 00100010 00100010 01011110 10010000 01001000
|
|
|
|
*/
|
|
|
|
#include "decoder.h"
|
|
|
|
static int tfa_303196_callback(r_device *decoder, bitbuffer_t *bitbuffer)
|
|
{
|
|
uint8_t const preamble_pattern[] = {0x55, 0x56}; // 12 bit preamble + 4 bit data
|
|
int row;
|
|
data_t *data;
|
|
uint8_t *b;
|
|
bitbuffer_t databits = {0};
|
|
|
|
row = bitbuffer_find_repeated_row(bitbuffer, 2, 48 * 2 + 12); // expected are 4 rows, require 2
|
|
if (row < 0)
|
|
return DECODE_ABORT_EARLY;
|
|
|
|
unsigned start_pos = bitbuffer_search(bitbuffer, row, 0, preamble_pattern, 16);
|
|
start_pos += 12; // skip preamble
|
|
|
|
if (bitbuffer->bits_per_row[row] - start_pos < 48 * 2)
|
|
return DECODE_ABORT_LENGTH; // short buffer or preamble not found
|
|
|
|
bitbuffer_manchester_decode(bitbuffer, row, start_pos, &databits, 48);
|
|
|
|
if (databits.bits_per_row[0] < 48)
|
|
return DECODE_ABORT_LENGTH; // payload malformed MC
|
|
|
|
b = databits.bb[0];
|
|
|
|
if (b[0] != 0xa8)
|
|
return DECODE_FAIL_SANITY;
|
|
|
|
uint16_t digest = (b[4] << 8) | (b[5]);
|
|
int chk = lfsr_digest16(b, 4, 0x8810, 0x22d0) ^ digest;
|
|
|
|
//decoder_logf_bitrow(decoder, 0, __func__, b, 48, "TFA-303196 (%08x %04x %04x)", chk_data, digest, session);
|
|
|
|
int channel = (b[1] >> 4) + 1;
|
|
int temp_raw = ((b[1] & 0x0F) << 8) | b[2];
|
|
float temp_c = (temp_raw - 400) * 0.1f;
|
|
int battery_low = b[3] >> 7;
|
|
int humidity = b[3] & 0x7F;
|
|
|
|
/* clang-format off */
|
|
data = data_make(
|
|
"model", "", DATA_STRING, "TFA-303196",
|
|
"id", "", DATA_INT, chk,
|
|
"channel", "Channel", DATA_INT, channel,
|
|
"battery_ok", "Battery", DATA_INT, !battery_low,
|
|
"temperature_C", "Temperature", DATA_FORMAT, "%.1f C", DATA_DOUBLE, temp_c,
|
|
"humidity", "Humidity", DATA_FORMAT, "%u %%", DATA_INT, humidity,
|
|
"mic", "Integrity", DATA_STRING, "missing",
|
|
NULL);
|
|
/* clang-format on */
|
|
|
|
decoder_output_data(decoder, data);
|
|
return 1;
|
|
}
|
|
|
|
static char const *const output_fields[] = {
|
|
"model",
|
|
"id",
|
|
"channel",
|
|
"battery_ok",
|
|
"temperature_C",
|
|
"humidity",
|
|
"mic",
|
|
NULL,
|
|
};
|
|
|
|
r_device const tfa_303196 = {
|
|
.name = "TFA Dostmann 30.3196 T/H outdoor sensor",
|
|
.modulation = FSK_PULSE_MANCHESTER_ZEROBIT,
|
|
.short_width = 245,
|
|
.long_width = 0, // unused
|
|
.tolerance = 60,
|
|
.reset_limit = 22000,
|
|
.decode_fn = &tfa_303196_callback,
|
|
.fields = output_fields,
|
|
};
|