Bugfixes
[rtl-433.git] / src / devices / wg_pb12v1.c
1 /* WG-PB12V1 Temperature Sensor
2  * ---
3  * Device method to decode a generic wireless temperature probe. Probe marked
4  * with WG-PB12V1-2016/11.
5  * 
6  * Format of Packets
7  * ---
8  * The packet format appears to be similar those the Lacrosse format.
9  * (http://fredboboss.free.fr/articles/tx29.php)
10  * 
11  * AAAAAAAA ????TTTT TTTTTTTT ???IIIII HHHHHHHH CCCCCCCC
12  * 
13  * A = Preamble - 11111111
14  * ? = Unknown - possibly battery charge
15  * T = Temperature - see below
16  * I = ID of probe is set randomly each time the device is powered off-on, 
17  *     Note, base station has and unused "123" symbol, but ID values can be 
18  *     higher than this.
19  * H = Humidity - not used, is always 11111111
20  * C = Checksum - CRC8, polynomial 0x31, initial value 0x0, final value 0x0
21  * 
22  * Temperature
23  * ---
24  * Temperature value is "milli-celcius", ie 1000 mC = 1C, offset by -40 C.
25  * 
26  * 0010 01011101 = 605 mC => 60.5 C
27  * Remove offset => 60.5 C - 40 C = 20.5 C
28  * 
29  * Unknown
30  * ---
31  * Possbible uses could be weak battey, or new battery.
32  * 
33  * At the moment it this device cannot distinguish between a Fine Offset 
34  * device, see fineoffset.c.
35  * 
36  * Copyright (C) 2015 Tommy Vestermark
37  * Modifications Copyright (C) 2017 Ciarán Mooney
38  * 
39  * This program is free software; you can redistribute it and/or modify
40  * it under the terms of the GNU General Public License as published by
41  * the Free Software Foundation; either version 2 of the License, or
42  * (at your option) any later version.
43  */
44
45 #include "rtl_433.h"
46 #include "data.h"
47 #include "util.h"
48
49 static int wg_pb12v1_callback(bitbuffer_t *bitbuffer) {
50     /* This function detects if the packet (bitbuffer) is from a WG-PB12V1
51      * sensor, and decodes it if it passes the checks.
52      */
53      
54     bitrow_t *bb = bitbuffer->bb;
55     data_t *data;
56
57     char time_str[LOCAL_TIME_BUFLEN];
58
59     uint8_t id;
60     int16_t temp;
61     float temperature;
62     uint8_t humidity;
63     char io[49];
64
65     const uint8_t polynomial = 0x31;    // x8 + x5 + x4 + 1 (x8 is implicit)
66     
67     // Validate package
68     if (bitbuffer->bits_per_row[0] >= 48 &&              // Don't waste time on a short packages
69         bb[0][0] == 0xFF &&                              // Preamble
70         bb[0][5] == crc8(&bb[0][1], 4, polynomial, 0) && // CRC (excluding preamble)
71         bb[0][4] == 0xFF                                 // Humitidy set to 11111111
72         ){
73     
74         /* Get time now */
75         local_time_str(0, time_str);
76         
77          // Nibble 7,8 contains id
78         id = ((bb[0][3]&0x1F));
79
80         // Nibble 5,6,7 contains 12 bits of temperature
81         // The temperature is "milli-celcius", ie 1000 mC = 1C, offset by -40 C.
82         temp = ((bb[0][1] & 0x0F) << 8) | bb[0][2];
83         temperature = ((float)temp / 10)-40;
84
85         // Populate string array with raw packet bits.
86         for (uint16_t bit = 0; bit < bitbuffer->bits_per_row[0]; ++bit){
87             if (bb[0][bit/8] & (0x80 >> (bit % 8))){
88                 io[bit] = 49; // 1
89                } 
90             else {
91                 io[bit] = 48; // 0
92                 }
93             }
94         io[48] = 0; // terminate string array.
95         
96         if (debug_output > 1) {
97            fprintf(stderr, "ID          = 0x%2X\n",  id);
98            fprintf(stderr, "temperature = %.1f C\n", temperature);
99         }
100
101         data = data_make("time",          "",            DATA_STRING, time_str,
102                          "model",         "",            DATA_STRING, "WG-PB12V1",
103                          "id",            "ID",          DATA_INT, id,
104                          "temperature_C", "Temperature", DATA_FORMAT, "%.01f C", DATA_DOUBLE, temperature,
105                          "io",            "io",          DATA_STRING, io,
106                           NULL);
107         data_acquired_handler(data);
108         return 1;
109     }
110     return 0;
111 }
112
113 static char *output_fields[] = {
114     /* Defines the output files for this device function.
115      */
116     "time",
117     "model",
118     "id",
119     "temperature_C",
120     "io",
121     NULL
122 };
123
124 r_device wg_pb12v1 = {
125     /* Defines object information for use in other parts of RTL_433.
126      */
127      .name           = "WG-PB12V1",
128     .modulation     = OOK_PULSE_PWM_RAW,
129     .short_limit    = 650,      // Short pulse 564µs, long pulse 1476µs, fixed gap 960µs
130     .long_limit     = 1550,     // Maximum pulse period (long pulse + fixed gap)
131     .reset_limit    = 2500,     // We just want 1 package
132     .json_callback  = &wg_pb12v1_callback,
133     .disabled       = 0,
134     .demod_arg      = 0,
135     .fields         = output_fields
136 };