Редизайн на основе текущей ветки мейнстрима + новые устройства.
[rtl-433.git] / src / devices / xc0348.c
1 /*
2  * Digitech XC0348 weather station
3  * Reports 1 row, 88 pulses
4  * Format: ff ID ?X XX YY ZZ ?? ?? ?? UU CC
5  * - ID: device id
6  * - ?X XX: temperature, likely in 0.1C steps (.1 e7 == 8.7C, .1 ef == 9.5C)
7  * - YY: percent in a single byte (for example 54 == 84%)
8  * - ZZ: wind speed (00 == 0, 01 == 1.1km/s, ...)
9  * - UU: wind direction: 00 is N, 02 is NE, 04 is E, etc. up to 0F is seems
10  * - CC: checksum
11  *
12  * still unknown - rain, pressure
13  */
14
15 #include "data.h"
16 #include "rtl_433.h"
17 #include "util.h"
18
19 #define CRC_POLY 0x31
20 #define CRC_INIT 0xff
21
22 static const char* wind_directions[] = {
23     "N", "NNE", "NE",
24     "ENE", "E", "ESE",
25     "SE", "SSE", "S", "SSW", "SW",
26     "WSW", "W", "WNW",
27     "NW", "NNW",
28 };
29
30 static float get_temperature(const uint8_t* br) {
31     const int temp_raw = (br[2] << 8) + br[3];
32     return ((temp_raw & 0x0fff) - 0x190) / 10.0;
33 }
34
35 static int get_humidity(const uint8_t* br) {
36     return br[4];
37 }
38
39 static const char* get_wind_direction(const uint8_t* br) {
40     return wind_directions[br[9] & 0x0f];
41 }
42
43 static float get_wind_speed(const uint8_t* br) {
44     return br[5] * 1.1f;
45 }
46
47 static int digitech_ws_callback(bitbuffer_t *bitbuffer) {
48     data_t *data;
49     char time_str[LOCAL_TIME_BUFLEN];
50     local_time_str(0, time_str);
51
52     if (bitbuffer->num_rows != 1) {
53         return 0;
54     }
55     if (bitbuffer->bits_per_row[0] != 88) {
56         return 0;
57     }
58
59         const uint8_t *br = bitbuffer->bb[0];
60
61     if (br[0] != 0xff) {
62         // preamble missing
63         return 0;
64     }
65
66     if (br[10] != crc8(br, 10, CRC_POLY, CRC_INIT)) {
67         // crc mismatch
68         return 0;
69     }
70
71     const float temperature = get_temperature(br);
72     const int humidity = get_humidity(br);
73     const char* direction = get_wind_direction(br);
74     const float speed = get_wind_speed(br);
75     const char device_id = br[1];
76
77     data = data_make("time",          "",               DATA_STRING, time_str,
78                      "model",         "",               DATA_STRING, "Digitech XC0348 weather station",
79                      "id",            "",               DATA_INT,    device_id,
80                      "temperature_C", "Temperature",    DATA_DOUBLE, temperature,
81                      "humidity",      "Humidity",       DATA_INT,    humidity,
82                      "direction",     "Wind direction", DATA_STRING, direction,
83                      "speed",         "Wind speed",     DATA_DOUBLE, speed,
84                      NULL);
85     data_acquired_handler(data);
86     return 1;
87 }
88
89 static char *output_fields[] = {
90         "time",
91         "model",
92         "id",
93         "temperature_C",
94         "humidity",
95         "direction",
96         "speed",
97         NULL
98 };
99
100 r_device digitech_ws = {
101     .name           = "Digitech XC0348 Weather Station",
102     .modulation     = OOK_PULSE_PWM_RAW,
103     .short_limit    = 976,
104     .long_limit     = 2400,
105     .reset_limit    = 10520,
106     .json_callback  = &digitech_ws_callback,
107     .disabled       = 0,
108     .demod_arg      = 0,
109     .fields         = output_fields,
110 };