Редизайн на основе текущей ветки мейнстрима + новые устройства.
[rtl-433.git] / src / devices / honeywell.c
1 /*
2 * *** Honeywell (Ademco) Door/Window Sensors (345.0Mhz) ***
3 *
4 * Tested with the Honeywell 5811 Wireless Door/Window transmitters
5 *
6 * 64 bit packets, repeated multiple times per open/close event
7 *
8 * Protocol whitepaper: "DEFCON 22: Home Insecurity" by Logan Lamb
9 *
10 * 0xfffe Preamble and sync bit
11 * 0x8 Unknown
12 * 0xYYYYY Device serial number
13 * 0xYY Event Information (Open/Close, Heartbeat, etc)
14 * 0xYYYY CRC
15 *
16 */
17
18 #include "rtl_433.h"
19 #include "pulse_demod.h"
20 #include "util.h"
21
22 static int honeywell_callback(bitbuffer_t *bitbuffer) {
23   char time_str[LOCAL_TIME_BUFLEN];
24   const uint8_t *bb;
25   char device_id[6];
26   char hex[2];
27   char binary [65];
28   int heartbeat = 0;
29   uint16_t crc_calculated = 0;
30   uint16_t crc = 0;
31
32   local_time_str(0, time_str);
33
34   if(bitbuffer->num_rows != 1 || bitbuffer->bits_per_row[0] != 64)
35     return 0; // Unrecognized data
36
37   for(uint16_t i=0; i < 8; i++)
38     bitbuffer->bb[0][i] = ~bitbuffer->bb[0][i];
39
40   bb = bitbuffer->bb[0];
41
42   crc_calculated = crc16_ccitt(bb, 6, 0x8005, 0xfffe);
43   crc = (((uint16_t) bb[6]) << 8) + ((uint16_t) bb[7]);
44   if(crc != crc_calculated)
45     return 0; // Not a valid packet
46
47   sprintf(hex, "%02x", bb[2]);
48   device_id[0] = hex[1];
49   sprintf(hex, "%02x", bb[3]);
50   device_id[1] = hex[0];
51   device_id[2] = hex[1];
52   sprintf(hex, "%02x", bb[4]);
53   device_id[3] = hex[0];
54   device_id[4] = hex[1];
55   device_id[5] = '\0';
56
57   // Raw Binary
58   for (uint16_t bit = 0; bit < 64; ++bit) {
59       if (bb[bit/8] & (0x80 >> (bit % 8))) {
60               binary[bit] = '1';
61       } else {
62               binary[bit] = '0';
63       }
64   }
65   binary[64] = '\0';
66
67   data_t *data = data_make(
68                    "time",     "", DATA_STRING, time_str,
69                    "id",       "", DATA_STRING, device_id,
70                    "state",    "", DATA_STRING, ( (bb[5] & 0x80) == 0x00)? "closed":"open",
71                    "heartbeat" , "", DATA_STRING, ( (bb[5] & 0x04) == 0x04)? "yes" : "no",
72                    "crc", "", DATA_STRING, "ok",
73                    "time_unix","", DATA_INT, time(NULL),
74                    "binary",   "", DATA_STRING, binary,
75                           NULL);
76
77   data_acquired_handler(data);
78   return 1;
79 }
80
81 static char *output_fields[] = {
82         "time",
83         "id",
84         "state",
85         "heartbeat",
86         "crc",
87         "time_unix",
88         "binary",
89         NULL
90 };
91
92 r_device honeywell = {
93         .name                   = "Honeywell Door/Window Sensor",
94         .modulation             = OOK_PULSE_MANCHESTER_ZEROBIT,
95         .short_limit    =   39 * 4,
96         .long_limit             = 0,
97         .reset_limit    = 73 * 4,
98         .json_callback  = &honeywell_callback,
99         .disabled               = 0,
100         .demod_arg              = 0,
101         .fields                 = output_fields,
102 };