1 /** @file
2 Inovalley kw9015b rain and Temperature weather station.
3
4 Copyright (C) 2015 Alexandre Coffignal
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 */
11 /**
12 Inovalley kw9015b rain and Temperature weather station.
13
14 Also TFA-Dostmann rain-sensor 30.3161 (see #1531) with a 0.45mm rain per tip.
15
16 Data layout:
17
18 IIII??RR BRRPtttt TTTTTTTT rrrrrrrr CCCC
19
20 - I : 4-bit ID
21 - ? : 2-bit unknown always 00
22 - T : 12-bit Temp in C, signed, scaled by 10
23 - R : 12-bit Rain
24 - B : 1-bit battery (0 means battery ok, 1 means low battery)
25 - P : 1-bit power up (when batteries are inserted is 1, then always 0)
26 - C : 4-bit Checksum (nibble sum)
27 */
28
29 #include "decoder.h"
30
kw9015b_callback(r_device * decoder,bitbuffer_t * bitbuffer)31 static int kw9015b_callback(r_device *decoder, bitbuffer_t *bitbuffer)
32 {
33 data_t *data;
34 int row;
35 uint8_t *b;
36 int temp_raw, rain, device;
37 unsigned char chksum;
38 float temp_c;
39
40 row = bitbuffer_find_repeated_row(bitbuffer, 3, 36);
41 if (row < 0)
42 return DECODE_ABORT_EARLY;
43
44 if (bitbuffer->bits_per_row[row] > 36)
45 return DECODE_ABORT_LENGTH;
46
47 b = bitbuffer->bb[row];
48
49 device = (reverse8(b[0]) & 0x0f);
50 temp_raw = (int16_t)((reverse8(b[2]) << 8) | (reverse8(b[1]) & 0xf0)); // sign-extend
51 temp_c = (temp_raw >> 4) * 0.1f;
52 rain = ((reverse8(b[0]) & 0xc0) << 4) | ((reverse8(b[1]) & 0x06) << 7) | reverse8(b[3]);
53 chksum = ((reverse8(b[0]) >> 4) + (reverse8(b[0]) & 0x0f) +
54 (reverse8(b[1]) >> 4) + (reverse8(b[1]) & 0x0f) +
55 (reverse8(b[2]) >> 4) + (reverse8(b[2]) & 0x0f) +
56 (reverse8(b[3]) >> 4) + (reverse8(b[3]) & 0x0f));
57 int battery_low = b[1] >> 7;
58
59 if ((chksum & 0x0f) != (reverse8(b[4]) & 0x0f))
60 return DECODE_FAIL_MIC;
61
62 /* clang-format off */
63 data = data_make(
64 "model", "", DATA_STRING, "Inovalley-kw9015b",
65 "id", "", DATA_INT, device,
66 "battery_ok", "Battery", DATA_INT, !battery_low,
67 "temperature_C", "Temperature", DATA_FORMAT, "%.1f C", DATA_DOUBLE, temp_c,
68 "rain", "Rain Count", DATA_INT, rain, // TODO: remove this
69 "rain_mm", "Rain Total", DATA_DOUBLE, rain * 0.45f,
70 NULL);
71 /* clang-format on */
72
73 decoder_output_data(decoder, data);
74 return 1;
75 }
76
77 static char *kw9015b_csv_output_fields[] = {
78 "model",
79 "id",
80 "battery_ok",
81 "temperature_C",
82 "rain", // TODO: remove this
83 "rain_mm",
84 NULL,
85 };
86
87 r_device kw9015b = {
88 .name = "Inovalley kw9015b, TFA Dostmann 30.3161 (Rain and temperature sensor)",
89 .modulation = OOK_PULSE_PPM,
90 .short_width = 2000,
91 .long_width = 4000,
92 .gap_limit = 4800,
93 .reset_limit = 10000,
94 .decode_fn = &kw9015b_callback,
95 .disabled = 1,
96 .fields = kw9015b_csv_output_fields,
97 };
98