Bugfixes
[rtl-433.git] / src / devices / new_template.c
1 /* Template decoder
2  *
3  * Copyright © 2016 Benjamin Larsson
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  */
10
11 /* Use this as a starting point for a new decoder. */
12
13 #include "rtl_433.h"
14 #include "pulse_demod.h"
15 #include "util.h"
16
17
18 /*
19  * Hypothetical template device
20  *
21  * Message is 68 bits long
22  * Messages start with 0xAA
23  *
24  */
25 #define MYDEVICE_BITLEN         68
26 #define MYDEVICE_STARTBYTE      0xAA
27 #define MYDEVICE_MSG_TYPE       0x10
28 #define MYDEVICE_CRC_POLY       0x80
29 #define MYDEVICE_CRC_INIT       0x00
30
31
32 static int template_callback(bitbuffer_t *bitbuffer) {
33     char time_str[LOCAL_TIME_BUFLEN];
34     uint8_t *bb;
35     uint16_t brow, row_nbytes;
36     uint16_t sensor_id = 0;
37     uint8_t msg_type, r_crc, c_crc;
38     int16_t value;
39     data_t *data;
40     int valid = 0;
41
42
43     /*
44      * Early debugging aid to see demodulated bits in buffer and
45      * to determine if your limit settings are matched and firing
46      * this callback.
47      *
48      * 1. Enable with -D -D (debug level of 2)
49      * 2. Delete this block when your decoder is working
50      */
51     //    if (debug_output > 1) {
52     //        fprintf(stderr,"new_tmplate callback:\n");
53     //        bitbuffer_print(bitbuffer);
54     //    }
55
56     local_time_str(0, time_str);
57
58     /*
59      * bit buffer will contain multiple rows, many of them empty.
60      * Typically a complete message will be contained in a single
61      * row if long and reset limits are set correctly.
62      * May contain multiple message repeats.
63      * Message might not appear in row 0, if protocol uses
64      * start/preamble periods of different lengths.
65      */
66
67     for (brow = 0; brow < bitbuffer->num_rows; ++brow) {
68         bb = bitbuffer->bb[brow];
69
70         /*
71          * Validate message and reject invalid messages as
72          * early as possible before attempting to parse data..
73          *
74          * Check "message envelope"
75          * - valid message length
76          * - valid preamble/device type/fixed bits if any
77          * - Data integrity checks (CRC/Checksum/Parity)
78          */
79
80         if (bitbuffer->bits_per_row[brow] != 68)
81             continue;
82
83         /*
84          * number of bytes in row.
85          *
86          * Number of decoded bits may not be a multiple of 8.
87          * bitbuffer row will have enough bytes to contain
88          * all bytes, so round up.
89          */
90         row_nbytes = (bitbuffer->bits_per_row[brow] + 7)/8;
91
92
93         /*
94          * Reject rows that don't start with the correct start byte
95          * Example message should start with 0xAA
96          */
97         if (bb[0] != MYDEVICE_STARTBYTE)
98             continue;
99
100         /*
101          * Check message integrity (CRC/Checksum/parity)
102          *
103          * Example device uses CRC-8
104          */
105         r_crc = bb[row_nbytes - 1];
106         c_crc = crc8(bb, row_nbytes - 1, MYDEVICE_CRC_POLY, MYDEVICE_CRC_INIT);
107         if (r_crc != c_crc) {
108             // example debugging output
109             if (debug_output >= 1)
110                 fprintf(stderr, "%s new_tamplate bad CRC: calculated %02x, received %02x\n",
111                         time_str, c_crc, r_crc);
112
113             // reject row
114             continue;
115         }
116
117         /*
118          * Now that message "envelope" has been validated,
119          * start parsing data.
120          */
121
122         msg_type = bb[1];
123         sensor_id = bb[2] << 8 | bb[3];
124         value = bb[4] << 8 | bb[5];
125
126         if (msg_type != MYDEVICE_MSG_TYPE) {
127             /*
128              * received an unexpected message type
129              * could be a bad message or a new message not
130              * previously seen.  Optionally log debug putput.
131              */
132             continue;
133         }
134
135         data = data_make("time", "", DATA_STRING, time_str,
136                          "model", "", DATA_STRING, "New Template",
137                          "id", "", DATA_INT, sensor_id,
138                          "data","", DATA_INT, value,
139                          NULL);
140
141         data_acquired_handler(data);
142
143         valid++;
144     }
145
146     // Return 1 if message successfully decoded
147     if (valid)
148         return 1;
149
150     return 0;
151 }
152
153 /*
154  * List of fields to output when using CSV
155  *
156  * Used to determine what fields will be output in what
157  * order for this devince when using -F csv.
158  *
159  */
160 static char *csv_output_fields[] = {
161         "time",
162         "model",
163         "id",
164         "data",
165         NULL
166 };
167
168 /*
169  * r_device - registers device/callback. see rtl_433_devices.h
170  *
171  * Timings:
172  *
173  * short, long, nad reset - specify pulse/period timings
174  *     based on number of samples at 250 Khz samples/second.
175  *     These timings will determine if the received pulses
176  *     match, so your callback will fire after demodulation.
177  *
178  * for readabiliy, specify timings based on 1 Mhz samples
179  *     but a divide by 4 in the definition.
180  *
181  *
182  * Demodular:
183  *
184  * The function used to turn the received signal into bits.
185  * See:
186  * - pulse_demod.h for descriptions
187  * - rtL_433.h for the list of defined names
188  *
189  * This device is disabled by default. Enable it with -R 61 on the commandline
190  */
191
192 r_device template = {
193         .name           = "Template decoder",
194         .modulation     = OOK_PULSE_PPM_RAW,
195         .short_limit    = ((56+33)/2)*4,
196         .long_limit     = (56+33)*4,
197         .reset_limit    = (56+33)*2*4,
198         .json_callback  = &template_callback,
199         .disabled       = 1,
200         .demod_arg      = 0,
201         .fields         = csv_output_fields,
202 };