Bugfixes
[rtl-433.git] / src / devices / acurite.c
1 /*
2  * Acurite weather stations and temperature / humidity sensors
3  *
4  * Copyright (c) 2015, Jens Jenson, Helge Weissig, David Ray Thompson, Robert Terzi
5  *
6  * Devices decoded:
7  * - 5-n-1 weather sensor, Model; VN1TXC, 06004RM
8  * - 5-n-1 pro weather sensor, Model: 06014RM
9  * - 896 Rain gauge, Model: 00896
10  * - 592TXR / 06002RM Tower sensor (temperature and humidity)
11  * - 609TXC "TH" temperature and humidity sensor (609A1TX)
12  * - Acurite 986 Refrigerator / Freezer Thermometer
13  * - Acurite 606TX temperature sesor
14  * - Acurite 6045M Lightning Detector (Work in Progress)
15  */
16
17
18 #include "rtl_433.h"
19 #include "util.h"
20 #include "pulse_demod.h"
21 #include "data.h"
22
23 // ** Acurite 5n1 functions **
24
25 #define ACURITE_TXR_BITLEN              56
26 #define ACURITE_5N1_BITLEN              64
27 #define ACURITE_6045_BITLEN             72
28
29 // ** Acurite known message types
30 #define ACURITE_MSGTYPE_WINDSPEED_WINDDIR_RAINFALL  0x31
31 #define ACURITE_MSGTYPE_WINDSPEED_TEMP_HUMIDITY     0x38
32
33 static char time_str[LOCAL_TIME_BUFLEN];
34
35
36 // Acurite 5n1 Wind direction values.
37 // There are seem to be conflicting decodings.
38 // It is possible there there are different versions
39 // of the 5n1 station that report differently.
40 //
41 // The original implementation used by the 5n1 device type
42 // here seems to have a straight linear/cicular mapping.
43 //
44 // The newer 5n1 mapping seems to just jump around with no clear
45 // meaning, but does map to the values sent by Acurite's
46 // only Acu-Link Internet Bridge and physical console 1512.
47 // This is may be a modified/non-standard Gray Code.
48
49 // Mapping 5n1 raw RF wind direction values to aculink's values
50 //    RF, AcuLink
51 //     0,  6,   NW,  315.0
52 //     1,  8,  WSW,  247.5
53 //     2,  2,  WNW,  292.5
54 //     3,  0,    W,  270.0
55 //     4,  4,  NNW,  337.5
56 //     5,  A,   SW,  225.0
57 //     6,  5,    N,    0.0
58 //     7,  E,  SSW,  202.5
59 //     8,  1,  ENE,   67.5
60 //     9,  F,   SE,  135.0
61 //     A,  9,    E,   90.0
62 //     B,  B,  ESE,  112.5
63 //     C,  3,   NE,   45.0
64 //     D,  D,  SSE,  157.0
65 //     E,  7,  NNE,   22.5
66 //     F,  C,    S,  180.0
67
68 // From draythomp/Desert-home-rtl_433
69 // matches acu-link internet bridge values
70 // The mapping isn't circular, it jumps around.
71 char * acurite_5n1_winddirection_str[] =
72     {"NW",  // 0  315
73      "WSW", // 1  247.5
74      "WNW", // 2  292.5
75      "W",   // 3  270
76      "NNW", // 4  337.5
77      "SW",  // 5  225
78      "N",   // 6  0
79      "SSW", // 7  202.5
80      "ENE", // 8  67.5
81      "SE",  // 9  135
82      "E",   // 10 90
83      "ESE", // 11 112.5
84      "NE",  // 12 45
85      "SSE", // 13 157.5
86      "NNE", // 14 22.5
87      "S"};  // 15 180
88
89
90 const float acurite_5n1_winddirections[] =
91     { 315.0, // 0 - NW
92       247.5, // 1 - WSW
93       292.5, // 2 - WNW
94       270.0, // 3 - W
95       337.5, // 4 - NNW
96       225.0, // 5 - SW
97       0.0,   // 6 - N
98       202.5, // 7 - SSW
99       67.5,  // 8 - ENE
100       135.0, // 9 - SE
101       90.0,  // a - E
102       112.5, // b - ESE
103       45.0,  // c - NE
104       157.5, // d - SSE
105       22.5,  // e - NNE
106       180.0, // f - S
107     };
108
109
110 // 5n1 keep state for how much rain has been seen so far
111 static int acurite_5n1raincounter = 0;  // for 5n1 decoder
112 static int acurite_5n1t_raincounter = 0;  // for combined 5n1/TXR decoder
113
114
115 static int acurite_checksum(uint8_t row[BITBUF_COLS], int cols) {
116     // sum of first n-1 bytes modulo 256 should equal nth byte
117     // also disregard a row of all zeros
118     int i;
119     int sum = 0;
120     for ( i=0; i < cols; i++)
121         sum += row[i];
122     if (sum != 0 && (sum % 256 == row[cols]))
123         return 1;
124     else
125         return 0;
126 }
127
128 // Temperature encoding for 5-n-1 sensor and possibly others
129 static float acurite_getTemp (uint8_t highbyte, uint8_t lowbyte) {
130     // range -40 to 158 F
131     int highbits = (highbyte & 0x0F) << 7 ;
132     int lowbits = lowbyte & 0x7F;
133     int rawtemp = highbits | lowbits;
134     float temp_F = (rawtemp - 400) / 10.0;
135     return temp_F;
136 }
137
138 static float acurite_getWindSpeed_kph (uint8_t highbyte, uint8_t lowbyte) {
139     // range: 0 to 159 kph
140     // raw number is cup rotations per 4 seconds
141     // http://www.wxforum.net/index.php?topic=27244.0 (found from weewx driver)
142         int highbits = ( highbyte & 0x1F) << 3;
143     int lowbits = ( lowbyte & 0x70 ) >> 4;
144     int rawspeed = highbits | lowbits;
145     float speed_kph = 0;
146     if (rawspeed > 0) {
147         speed_kph = rawspeed * 0.8278 + 1.0;
148     }
149     return speed_kph;
150 }
151
152 static int acurite_getHumidity (uint8_t byte) {
153     // range: 1 to 99 %RH
154     int humidity = byte & 0x7F;
155     return humidity;
156 }
157
158 static int acurite_getRainfallCounter (uint8_t hibyte, uint8_t lobyte) {
159     // range: 0 to 99.99 in, 0.01 in incr., rolling counter?
160         int raincounter = ((hibyte & 0x7f) << 7) | (lobyte & 0x7F);
161     return raincounter;
162 }
163
164 // The high 2 bits of byte zero are the channel (bits 7,6)
165 //  00 = C
166 //  10 = B
167 //  11 = A
168 static char chLetter[4] = {'C','E','B','A'}; // 'E' stands for error
169
170 static char acurite_getChannel(uint8_t byte){
171     int channel = (byte & 0xC0) >> 6;
172     return chLetter[channel];
173 }
174
175 // 5-n-1 sensor ID is the last 12 bits of byte 0 & 1
176 // byte 0     | byte 1
177 // CC RR IIII | IIII IIII
178 //
179 static uint16_t acurite_5n1_getSensorId(uint8_t hibyte, uint8_t lobyte){
180     return ((hibyte & 0x0f) << 8) | lobyte;
181 }
182
183
184 // The sensor sends the same data three times, each of these have
185 // an indicator of which one of the three it is. This means the
186 // checksum and first byte will be different for each one.
187 // The bits 5,4 of byte 0 indicate which copy of the 65 bit data string
188 //  00 = first copy
189 //  01 = second copy
190 //  10 = third copy
191 //  1100 xxxx  = channel A 1st copy
192 //  1101 xxxx  = channel A 2nd copy
193 //  1110 xxxx  = channel A 3rd copy
194 static int acurite_5n1_getMessageCaught(uint8_t byte){
195     return (byte & 0x30) >> 4;
196 }
197
198
199 // So far, all that's known about the battery is that the
200 // third byte, high nibble has two values.xo 0xb0=low and 0x70=OK
201 // so this routine just returns the nibble shifted to make a byte
202 // for more work as time goes by
203 //
204 // Battery status appears to be the 7th bit 0x40. 1 = normal, 0 = low
205 // The 8th bit appears to be parity.
206 // @todo - determine if the 5th & 6th bits (0x30) are status bits or
207 //         part of the message type. So far these appear to always be 1
208 static int acurite_5n1_getBatteryLevel(uint8_t byte){
209     return (byte & 0x40) >> 6;
210 }
211
212
213 static int acurite_rain_gauge_callback(bitbuffer_t *bitbuffer) {
214         bitrow_t *bb = bitbuffer->bb;
215    // This needs more validation to positively identify correct sensor type, but it basically works if message is really from acurite raingauge and it doesn't have any errors
216     if ((bb[0][0] != 0) && (bb[0][1] != 0) && (bb[0][2]!=0) && (bb[0][3] == 0) && (bb[0][4] == 0)) {
217             float total_rain = ((bb[0][1]&0xf)<<8)+ bb[0][2];
218                 total_rain /= 2; // Sensor reports number of bucket tips.  Each bucket tip is .5mm
219         fprintf(stdout, "AcuRite Rain Gauge Total Rain is %2.1fmm\n", total_rain);
220                 fprintf(stdout, "Raw Message: %02x %02x %02x %02x %02x\n",bb[0][0],bb[0][1],bb[0][2],bb[0][3],bb[0][4]);
221         return 1;
222     }
223     return 0;
224 }
225
226
227 // Acurite 609TXC
228 // Temperature in Celsius is encoded as a 12 bit integer value
229 // multiplied by 10 using the 4th - 6th nybbles (bytes 1 & 2)
230 // negative values are handled by treating it temporarily
231 // as a 16 bit value to put the sign bit in a usable place.
232 //
233 static float acurite_th_temperature(uint8_t *s){
234     uint16_t shifted = (((s[1] & 0x0f) << 8) | s[2]) << 4; // Logical left shift
235     return (((int16_t)shifted) >> 4) / 10.0; // Arithmetic right shift
236 }
237
238 // Acurite 609 Temperature and Humidity Sensor
239 // 5 byte messages
240 // II ST TT HH CC
241 // II - ID byte, changes at each power up
242 // S - Status bitmask, normally 0x2,
243 //     0xa - battery low (bit 0x80)
244 // TTT - Temp in Celsius * 10, 12 bit with complement.
245 // HH - Humidity
246 // CC - Checksum
247 //
248 // @todo - see if the 3rd nybble is battery/status
249 //
250 static int acurite_th_callback(bitbuffer_t *bitbuf) {
251     uint8_t *bb = NULL;
252     int cksum, battery_low, valid = 0;
253     float tempc;
254     uint8_t humidity, id, status;
255     data_t *data;
256
257     local_time_str(0, time_str);
258
259     for (uint16_t brow = 0; brow < bitbuf->num_rows; ++brow) {
260         if (bitbuf->bits_per_row[brow] != 40) {
261             continue;
262         }
263
264         bb = bitbuf->bb[brow];
265
266         cksum = (bb[0] + bb[1] + bb[2] + bb[3]);
267
268         if (cksum == 0 || ((cksum & 0xff) != bb[4])) {
269             continue;
270         }
271
272         tempc = acurite_th_temperature(bb);
273         id = bb[0];
274         status = (bb[1] & 0xf0) >> 4;
275         battery_low = status & 0x8;
276         humidity = bb[3];
277
278         data = data_make(
279                      "time",            "",             DATA_STRING,    time_str,
280                      "model",           "",             DATA_STRING,    "Acurite 609TXC Sensor",
281                      "id",              "",             DATA_INT,       id,
282                      "battery",         "",             DATA_STRING,    battery_low ? "LOW" : "OK",
283                      "status",          "",             DATA_INT,       status,
284                      "temperature_C",   "Temperature",  DATA_FORMAT,    "%.1f C", DATA_DOUBLE, tempc,
285                      "humidity",        "Humidity",     DATA_INT,       humidity,
286                      NULL);
287
288         data_acquired_handler(data);
289         valid++;
290     }
291
292     if (valid)
293         return 1;
294
295     return 0;
296 }
297
298 // Tower sensor ID is the last 14 bits of byte 0 & 1
299 // byte 0    | byte 1
300 // CCII IIII | IIII IIII
301 //
302 static uint16_t acurite_txr_getSensorId(uint8_t hibyte, uint8_t lobyte){
303     return ((hibyte & 0x3f) << 8) | lobyte;
304 }
305
306
307 // temperature encoding used by "tower" sensors 592txr
308 // 14 bits available after removing both parity bits.
309 // 11 bits needed for specified range -40 C to 70 C (-40 F - 158 F)
310 // range -100 C to 1538.4 C
311 static float acurite_txr_getTemp (uint8_t highbyte, uint8_t lowbyte) {
312     int rawtemp = ((highbyte & 0x7F) << 7) | (lowbyte & 0x7F);
313     float temp = rawtemp / 10.0 - 100;
314     return temp;
315 }
316
317
318 /*
319  * Acurite 06045 Lightning sensor Temperature encoding
320  * 12 bits of temperature after removing parity and status bits.
321  * Message native format appears to be in 1/10 of a degree Fahrenheit
322  * Device Specification: -40 to 158 F  / -40 to 70 C
323  * Available range given encoding with 12 bits -150.0 F to +259.6 F
324  */
325 static float acurite_6045_getTemp (uint8_t highbyte, uint8_t lowbyte) {
326     int rawtemp = ((highbyte & 0x1F) << 7) | (lowbyte & 0x7F);
327     float temp = (rawtemp - 1500) / 10.0;
328     return temp;
329 }
330
331 /*
332  * Acurite 06045m Lightning Sensor decoding.
333  *
334  * Specs:
335  * - lightning strike count
336  * - extimated distance to front of storm, up to 25 miles / 40 km
337  * - Temperature -40 to 158 F / -40 to 70 C
338  * - Humidity 1 - 99% RH
339  *
340  * Status Information sent per 06047M/01021 display
341  * - (RF) interference (preventing lightning detection)
342  * - low battery
343  *
344  *
345  * Message format
346  * --------------
347  * Somewhat similar to 592TXR and 5-n-1 weather stations
348  * Same pulse characteristics. checksum, and parity checking on data bytes.
349  *
350  * 0   1   2   3   4   5   6   7   8
351  * CI? II  II  HH  ST  TT  LL  DD? KK
352  *
353  * C = Channel
354  * I = ID
355  * H = Humidity
356  * S = Status/Message type/Temperature MSB.
357  * T = Temperature
358  * D = Lightning distanace and status bits?
359  * L = Lightning strike count.
360  * K = Checksum
361  *
362  * Byte 0 - channel number A/B/C
363  * - Channel in 2 most significant bits - A: 0xC, B: 0x8, C: 00
364  * - TBD: lower 6 bits, ID or unused?
365  *
366  * Bytes 1 & 2 - ID, all 8 bits, no parity.
367  *
368  * Byte 3 - Humidity (7 bits + parity bit)
369  *
370  * Byte 4 - Status (2 bits) and Temperature MSB (5 bits)
371  * - Bitmask PSSTTTTT  (P = Parity, S = Status, T = Temperature)
372  * - 0x40 - Transmitting every 8 seconds (lightning possibly detected)
373  *          normal, off, transmits every 24 seconds
374  * - 0x20 - TBD: normally off, On is possibly low battery?
375  * - 0x1F - Temperature MSB (5 bits)
376  *
377  * Byte 5 - Temperature LSB (7 bits, 8th is parity)
378  *
379  * Byte 6 - Lightning Strike count (7 bits, 8th is parity)
380  * - Stored in EEPROM or something non-volatile)
381  * - Wraps at 127
382  *
383  * Byte 7 - Lightning Distance (5 bits) and status bits (2 bits)  (?)
384  * - Bits PSSDDDDD  (P = Parity, S = Status, D = Distance
385  * - 5 lower bits is distance in unit? (miles? km?) to edge of storm (theory)
386  * - Bit 0x20: (RF) interference / strong RFI detected (to be verified)
387  * - Bit 0x40: TBD, possible activity?
388  * - distance = 0x1f: possible invalid value indication (value at power up)
389  * - Note: Distance sometimes goes to 0 right after strike counter increment
390  *         status bits might indicate validifity of distance.
391  *
392  * Byte 8 - checksum. 8 bits, no parity.
393  *
394  * @todo - Get lightning/distance to front of storm to match display
395  * @todo - Low battery, figure out encoding
396  * @todo - figure out remaining status bits and how to report
397  * @todo - convert to data make once decoding is stable
398  */
399 static int acurite_6045_decode (bitrow_t bb, int browlen) {
400     int valid = 0;
401     float tempf;
402     uint8_t humidity, message_type, l_status;
403     char channel, *wind_dirstr = "";
404     char channel_str[2];
405     uint16_t sensor_id;
406     uint8_t strike_count, strike_distance;
407
408     channel = acurite_getChannel(bb[0]);  // same as TXR
409     sensor_id = (bb[1] << 8) | bb[2];     // TBD 16 bits or 20?
410     humidity = acurite_getHumidity(bb[3]);  // same as TXR
411     message_type = (bb[4] & 0x60) >> 5;  // status bits: 0x2 8 second xmit, 0x1 - TBD batttery?
412     tempf = acurite_6045_getTemp(bb[4], bb[5]);
413     strike_count = bb[6] & 0x7f;
414     strike_distance = bb[7] & 0x1f;
415     l_status = (bb[7] & 0x60) >> 5;
416
417     printf("%s Acurite lightning 0x%04X Ch %c Msg Type 0x%02x: %.1f F %d %% RH Strikes %d Distance %d L_status 0x%02x -",
418            time_str, sensor_id, channel, message_type, tempf, humidity, strike_count, strike_distance, l_status);
419
420     // FIXME Temporarily dump raw message data until the
421     // decoding improves.  Includes parity indicator(*).
422     for (int i=0; i < browlen; i++) {
423         char pc;
424         pc = byteParity(bb[i]) == 0 ? ' ' : '*';
425         fprintf(stdout, " %02x%c", bb[i], pc);
426     }
427     printf("\n");
428
429     valid++;
430     return(valid);
431 }
432
433
434 /*
435  * This callback handles several Acurite devices that use a very
436  * similar RF encoding and data format:
437  *:
438  * - 592TXR temperature and humidity sensor
439  * - 5-n-1 weather station
440  * - 6045M Lightning Detectur with Temperature and Humidity
441  */
442 static int acurite_txr_callback(bitbuffer_t *bitbuf) {
443     int browlen, valid = 0;
444     uint8_t *bb;
445     float tempc, tempf, wind_dird, rainfall = 0.0, wind_speed, wind_speedmph;
446     uint8_t humidity, sensor_status, sequence_num, message_type;
447     char channel, *wind_dirstr = "";
448     char channel_str[2];
449     uint16_t sensor_id;
450     int raincounter, temp, battery_low;
451     uint8_t strike_count, strike_distance;
452     data_t *data;
453
454
455     local_time_str(0, time_str);
456
457     if (debug_output > 1) {
458         fprintf(stderr,"acurite_txr\n");
459         bitbuffer_print(bitbuf);
460     }
461
462     for (uint16_t brow = 0; brow < bitbuf->num_rows; ++brow) {
463         browlen = (bitbuf->bits_per_row[brow] + 7)/8;
464         bb = bitbuf->bb[brow];
465
466         if (debug_output > 1)
467             fprintf(stderr,"acurite_txr: row %d bits %d, bytes %d \n", brow, bitbuf->bits_per_row[brow], browlen);
468
469         if ((bitbuf->bits_per_row[brow] < ACURITE_TXR_BITLEN ||
470              bitbuf->bits_per_row[brow] > ACURITE_5N1_BITLEN + 1) &&
471             bitbuf->bits_per_row[brow] != ACURITE_6045_BITLEN) {
472             if (debug_output > 1 && bitbuf->bits_per_row[brow] > 16)
473                 fprintf(stderr,"acurite_txr: skipping wrong len\n");
474             continue;
475         }
476
477         // There will be 1 extra false zero bit added by the demod.
478         // this forces an extra zero byte to be added
479         if (bb[browlen - 1] == 0)
480             browlen--;
481
482         if (!acurite_checksum(bb,browlen - 1)) {
483             if (debug_output) {
484                 fprintf(stderr, "%s Acurite bad checksum:", time_str);
485                 for (uint8_t i = 0; i < browlen; i++)
486                     fprintf(stderr," 0x%02x",bb[i]);
487                 fprintf(stderr,"\n");
488             }
489             continue;
490         }
491
492         if (debug_output) {
493             fprintf(stderr, "acurite_txr Parity: ");
494             for (uint8_t i = 0; i < browlen; i++) {
495                 fprintf(stderr,"%d",byteParity(bb[i]));
496             }
497             fprintf(stderr,"\n");
498         }
499
500
501         // tower sensor messages are 7 bytes.
502         // @todo - see if there is a type in the message that
503         // can be used instead of length to determine type
504         if (browlen == ACURITE_TXR_BITLEN / 8) {
505             channel = acurite_getChannel(bb[0]);
506             sensor_id = acurite_txr_getSensorId(bb[0],bb[1]);
507             sensor_status = bb[2]; // @todo, uses parity? & 0x07f
508             humidity = acurite_getHumidity(bb[3]);
509             tempc = acurite_txr_getTemp(bb[4], bb[5]);
510             sprintf(channel_str, "%c", channel);
511             battery_low = sensor_status >>7;
512
513             data = data_make(
514                     "time",                     "",             DATA_STRING,    time_str,
515                     "model",                    "",             DATA_STRING,    "Acurite tower sensor",
516                     "id",                       "",             DATA_INT,       sensor_id,
517                     "channel",                  "",             DATA_STRING,    &channel_str,
518                     "temperature_C",    "Temperature",  DATA_FORMAT,    "%.1f C", DATA_DOUBLE, tempc,
519                     "humidity",         "Humidity",     DATA_INT,       humidity,
520                     "battery",          "Battery",      DATA_INT,       battery_low,
521                     "status",           "",             DATA_INT,       sensor_status,
522                     NULL);
523
524             data_acquired_handler(data);
525             valid++;
526         }
527
528         // The 5-n-1 weather sensor messages are 8 bytes.
529         if (browlen == ACURITE_5N1_BITLEN / 8) {
530         if (debug_output) {
531             fprintf(stderr, "Acurite 5n1 raw msg: %02X %02X %02X %02X %02X %02X %02X %02X\n",
532                 bb[0], bb[1], bb[2], bb[3], bb[4], bb[5], bb[6], bb[7]);
533         }
534             channel = acurite_getChannel(bb[0]);
535         sprintf(channel_str, "%c", channel);        
536             sensor_id = acurite_5n1_getSensorId(bb[0],bb[1]);
537             sequence_num = acurite_5n1_getMessageCaught(bb[0]);
538             message_type = bb[2] & 0x3f;
539         battery_low = (bb[2] & 0x40) >> 6;
540
541             if (message_type == ACURITE_MSGTYPE_WINDSPEED_WINDDIR_RAINFALL) {
542             // Wind speed, wind direction, and rain fall
543             wind_speed = acurite_getWindSpeed_kph(bb[3], bb[4]);
544             wind_speedmph = kmph2mph(wind_speed);
545             wind_dird = acurite_5n1_winddirections[bb[4] & 0x0f];
546             wind_dirstr = acurite_5n1_winddirection_str[bb[4] & 0x0f];
547             raincounter = acurite_getRainfallCounter(bb[5], bb[6]);
548             if (acurite_5n1t_raincounter > 0) {
549                 // track rainfall difference after first run
550                 // FIXME when converting to structured output, just output
551                 // the reading, let consumer track state/wrap around, etc. 
552                 rainfall = ( raincounter - acurite_5n1t_raincounter ) * 0.01;
553                 if (raincounter < acurite_5n1t_raincounter) {
554                     fprintf(stderr, "%s Acurite 5n1 sensor 0x%04X Ch %c, rain counter reset or wrapped around (old %d, new %d)\n",
555                         time_str, sensor_id, channel, acurite_5n1t_raincounter, raincounter);
556                     acurite_5n1t_raincounter = raincounter;
557                 }
558             } else {
559                 // capture starting counter
560                 acurite_5n1t_raincounter = raincounter;
561                 fprintf(stderr, "%s Acurite 5n1 sensor 0x%04X Ch %c, Total rain fall since last reset: %0.2f\n",
562                 time_str, sensor_id, channel, raincounter * 0.01);
563             }
564                 
565             data = data_make(
566                 "time",         "",   DATA_STRING,    time_str,
567                 "model",        "",   DATA_STRING,    "Acurite 5n1 sensor",
568                 "sensor_id",    NULL,   DATA_FORMAT,    "0x%02X",   DATA_INT,       sensor_id,   
569                 "channel",      NULL,   DATA_STRING,    &channel_str,
570                 "sequence_num",  NULL,   DATA_INT,      sequence_num,
571                 "battery",      NULL,   DATA_STRING,    battery_low ? "OK" : "LOW",
572                 "message_type", NULL,   DATA_INT,       message_type,
573                 "wind_speed",   NULL,   DATA_FORMAT,    "%.1f mph", DATA_DOUBLE,     wind_speedmph,
574                 "wind_dir_deg", NULL,   DATA_FORMAT,    "%.1f", DATA_DOUBLE,    wind_dird,
575                 "wind_dir",     NULL,   DATA_STRING,    wind_dirstr,
576                 "rainfall_accumulation",     NULL,   DATA_FORMAT,    "%.2f in", DATA_DOUBLE,    rainfall,
577                 "raincounter_raw",  NULL,   DATA_INT,   raincounter,
578                 NULL);
579
580             data_acquired_handler(data);
581
582             } else if (message_type == ACURITE_MSGTYPE_WINDSPEED_TEMP_HUMIDITY) {
583             // Wind speed, temperature and humidity
584             wind_speed = acurite_getWindSpeed_kph(bb[3], bb[4]);
585             wind_speedmph = kmph2mph(wind_speed);
586             tempf = acurite_getTemp(bb[4], bb[5]);
587             tempc = fahrenheit2celsius(tempf);
588             humidity = acurite_getHumidity(bb[6]);
589
590             data = data_make(
591                 "time",         "",   DATA_STRING,    time_str,
592                 "model",        "",   DATA_STRING,    "Acurite 5n1 sensor",
593                 "sensor_id",    NULL,   DATA_FORMAT,    "0x%02X",   DATA_INT,       sensor_id,   
594                 "channel",      NULL,   DATA_STRING,    &channel_str,
595                 "sequence_num",  NULL,   DATA_INT,      sequence_num,
596                 "battery",      NULL,   DATA_STRING,    battery_low ? "OK" : "LOW",
597                 "message_type", NULL,   DATA_INT,       message_type,
598                 "wind_speed",   NULL,   DATA_FORMAT,    "%.1f mph", DATA_DOUBLE,     wind_speedmph,
599                 "temperature_F",        "temperature",  DATA_FORMAT,    "%.1f F", DATA_DOUBLE,    tempf,
600                 "humidity",     NULL,   DATA_FORMAT,    "%d",   DATA_INT,   humidity,
601                 NULL);
602             data_acquired_handler(data);
603             
604             } else {
605             fprintf(stderr, "%s Acurite 5n1 sensor 0x%04X Ch %c, Status %02X, Unknown message type 0x%02x\n",
606                 time_str, sensor_id, channel, bb[3], message_type);
607             }
608         }
609
610         if (browlen == ACURITE_6045_BITLEN / 8) {
611             // @todo check parity and reject if invalid
612             valid += acurite_6045_decode(bb, browlen);
613         }
614
615     }
616
617     if (valid)
618         return 1;
619
620     return 0;
621 }
622
623
624 /*
625  * Acurite 00986 Refrigerator / Freezer Thermometer
626  *
627  * Includes two sensors and a display, labeled 1 and 2,
628  * by default 1 - Refridgerator, 2 - Freezer
629  *
630  * PPM, 5 bytes, sent twice, no gap between repeaters
631  * start/sync pulses two short, with short gaps, followed by
632  * 4 long pulse/gaps.
633  *
634  * @todo, the 2 short sync pulses get confused as data.
635  *
636  * Data Format - 5 bytes, sent LSB first, reversed
637  *
638  * TT II II SS CC
639  *
640  * T - Temperature in Fahrenehit, integer, MSB = sign.
641  *     Encoding is "Sign and magnitude"
642  * I - 16 bit sensor ID
643  *     changes at each power up
644  * S - status/sensor type
645  *     0x01 = Sensor 2
646  *     0x02 = low battery
647  * C = CRC (CRC-8 poly 0x07, little-endian)
648  *
649  * @todo
650  * - needs new PPM demod that can separate out the short
651  *   start/sync pulses which confuse things and cause
652  *   one data bit to be lost in the check value.
653  * - low battery detection
654  *
655  */
656
657 static int acurite_986_callback(bitbuffer_t *bitbuf) {
658     int browlen;
659     uint8_t *bb, sensor_num, status, crc, crcc;
660     uint8_t br[8];
661     int8_t tempf; // Raw Temp is 8 bit signed Fahrenheit
662     float tempc;
663     uint16_t sensor_id, valid_cnt = 0;
664     char sensor_type;
665
666     local_time_str(0, time_str);
667
668     if (debug_output > 1) {
669         fprintf(stderr,"acurite_986\n");
670         bitbuffer_print(bitbuf);
671     }
672
673     for (uint16_t brow = 0; brow < bitbuf->num_rows; ++brow) {
674         browlen = (bitbuf->bits_per_row[brow] + 7)/8;
675         bb = bitbuf->bb[brow];
676
677         if (debug_output > 1)
678             fprintf(stderr,"acurite_986: row %d bits %d, bytes %d \n", brow, bitbuf->bits_per_row[brow], browlen);
679
680         if (bitbuf->bits_per_row[brow] < 39 ||
681             bitbuf->bits_per_row[brow] > 43 ) {
682             if (debug_output > 1 && bitbuf->bits_per_row[brow] > 16)
683                 fprintf(stderr,"acurite_986: skipping wrong len\n");
684             continue;
685         }
686
687         // Reduce false positives
688         // may eliminate these with a beter PPM (precise?) demod.
689         if ((bb[0] == 0xff && bb[1] == 0xff && bb[2] == 0xff) ||
690            (bb[0] == 0x00 && bb[1] == 0x00 && bb[2] == 0x00)) {
691             continue;
692         }
693
694         // There will be 1 extra false zero bit added by the demod.
695         // this forces an extra zero byte to be added
696         if (browlen > 5 && bb[browlen - 1] == 0)
697             browlen--;
698
699         // Reverse the bits
700         for (uint8_t i = 0; i < browlen; i++)
701             br[i] = reverse8(bb[i]);
702
703         if (debug_output > 0) {
704             fprintf(stderr,"Acurite 986 reversed: ");
705             for (uint8_t i = 0; i < browlen; i++)
706                 fprintf(stderr," %02x",br[i]);
707             fprintf(stderr,"\n");
708         }
709
710         tempf = br[0];
711         sensor_id = (br[1] << 8) + br[2];
712         status = br[3];
713         sensor_num = (status & 0x01) + 1;
714         status = status >> 1;
715         // By default Sensor 1 is the Freezer, 2 Refrigerator
716         sensor_type = sensor_num == 2 ? 'F' : 'R';
717         crc = br[4];
718
719         if ((crcc = crc8le(br, 5, 0x07, 0)) != 0) {
720             // XXX make debug
721             if (debug_output) {
722                 fprintf(stderr,"%s Acurite 986 sensor bad CRC: %02x -",
723                         time_str, crc8le(br, 4, 0x07, 0));
724                 for (uint8_t i = 0; i < browlen; i++)
725                     fprintf(stderr," %02x", br[i]);
726                 fprintf(stderr,"\n");
727             }
728             continue;
729         }
730
731         if ((status & 1) == 1) {
732             fprintf(stderr, "%s Acurite 986 sensor 0x%04x - %d%c: low battery, status %02x\n",
733                     time_str, sensor_id, sensor_num, sensor_type, status);
734         }
735
736         // catch any status bits that haven't been decoded yet
737         if ((status & 0xFE) != 0) {
738             fprintf(stderr, "%s Acurite 986 sensor 0x%04x - %d%c: Unexpected status %02x\n",
739                     time_str, sensor_id, sensor_num, sensor_type, status);
740         }
741
742         if (tempf & 0x80) {
743             tempf = (tempf & 0x7f) * -1;
744         }
745         tempc = fahrenheit2celsius(tempf);
746
747
748         printf("%s Acurite 986 sensor 0x%04x - %d%c: %3.1f C %d F\n",
749                time_str, sensor_id, sensor_num, sensor_type,
750                tempc, tempf);
751
752         valid_cnt++;
753
754     }
755
756     if (valid_cnt)
757         return 1;
758
759     return 0;
760 }
761
762 // Checksum code from
763 // https://eclecticmusingsofachaoticmind.wordpress.com/2015/01/21/home-automation-temperature-sensors/
764 // with modifications listed in
765 // http://www.osengr.org/WxShield/Downloads/Weather-Sensor-RF-Protocols.pdf
766 //
767 // This is the same algorithm as used in ambient_weather.c
768 //
769 uint8_t Checksum(int length, uint8_t *buff) {
770   uint8_t mask = 0xd3;
771   uint8_t checksum = 0x00;
772   uint8_t data;
773   int byteCnt;
774
775   for (byteCnt = 0; byteCnt < length; byteCnt++) {
776     int bitCnt;
777     data = buff[byteCnt];
778
779     for (bitCnt = 7; bitCnt >= 0; bitCnt--) {
780       uint8_t bit;
781
782       // Rotate mask right
783       bit = mask & 1;
784       mask = (mask >> 1) | (mask << 7);
785       if (bit) {
786         mask ^= 0x18;
787       }
788
789       // XOR mask into checksum if data bit is 1
790       if (data & 0x80) {
791         checksum ^= mask;
792       }
793       data <<= 1;
794     }
795   }
796   return checksum;
797 }
798
799
800 static int acurite_606_callback(bitbuffer_t *bitbuf) {
801     data_t *data;
802     bitrow_t *bb = bitbuf->bb;
803     float temperature;  // temperature in C
804     int16_t temp;       // temperature as read from the data packet
805     int battery;        // the battery status: 1 is good, 0 is low
806     int8_t sensor_id;   // the sensor ID - basically a random number that gets reset whenever the battery is removed
807
808
809     local_time_str(0, time_str);
810
811     if (debug_output > 1) {
812         fprintf(stderr,"acurite_606\n");
813         bitbuffer_print(bitbuf);
814     }
815
816     // throw out all blank messages
817     if (bb[1][0] == 0 && bb[1][1] == 0 && bb[1][2] == 0 && bb[1][3] == 0)
818       return 0;
819
820     // do some basic checking to make sure we have a valid data record
821     if ((bb[0][0] == 0) && (bb[1][4] == 0)) {                                   //This test may need some more scrutiny...
822         // calculate the checksum and only continue if we have a maching checksum
823         uint8_t chk = Checksum(3, &bb[1][0]);
824
825         if (chk == bb[1][3]) {
826             // Processing the temperature: 
827             // Upper 4 bits are stored in nibble 1, lower 8 bits are stored in nibble 2
828             // upper 4 bits of nibble 1 are reserved for other usages (e.g. battery status)
829             temp = (int16_t)((uint16_t)(bb[1][1] << 12) | (bb[1][2] << 4));
830             temp = temp >> 4;
831
832             temperature = temp / 10.0;
833             sensor_id = bb[1][0];
834             battery = (bb[1][1] & 0x80) >> 7;
835
836             data = data_make("time",          "",            DATA_STRING, time_str,
837                              "model",         "",            DATA_STRING, "Acurite 606TX Sensor",
838                              "id",            "",            DATA_INT, sensor_id,
839                              "battery",       "Battery",     DATA_STRING, battery ? "OK" : "LOW",
840                              "temperature_C", "Temperature", DATA_FORMAT, "%.1f C", DATA_DOUBLE, temperature,
841                              NULL);
842             data_acquired_handler(data);
843             return 1;
844         }
845     }
846
847     return 0;
848 }
849
850
851 static int acurite_00275rm_callback(bitbuffer_t *bitbuf) {
852     int crc, battery_low, id, model, valid = 0;
853     uint8_t *bb;
854     data_t *data;
855     char *model1 = "00275rm", *model2 = "00276rm";
856     float tempc, ptempc;
857     uint8_t probe, humidity, phumidity, water;
858     uint8_t signal[3][11];  //  Hold three copies of the signal
859     int     nsignal = 0;
860
861     local_time_str(0, time_str);
862
863     if (debug_output > 1) {
864         fprintf(stderr,"acurite_00275rm\n");
865         bitbuffer_print(bitbuf);
866     }
867
868     //  This sensor repeats signal three times.  Store each copy.
869     for (uint16_t brow = 0; brow < bitbuf->num_rows; ++brow) {
870         if (bitbuf->bits_per_row[brow] != 88) continue;
871         if (nsignal>=3) continue;
872         memcpy(signal[nsignal], bitbuf->bb[brow], 11);
873         if (debug_output) {
874             fprintf(stderr,"acurite_00275rm: ");
875             for (int i=0; i<11; i++) fprintf(stderr," %02x",signal[nsignal][i]);
876             fprintf(stderr,"\n");
877         }
878         nsignal++;
879     }
880
881     //  All three signals were found
882     if (nsignal==3) {
883         //  Combine signal copies so that majority bit count wins
884         for (int i=0; i<11; i++) {
885             signal[0][i] = 
886                 (signal[0][i] & signal[1][i]) |
887                 (signal[1][i] & signal[2][i]) |
888                 (signal[2][i] & signal[0][i]);
889         }
890         // CRC check fails?
891         if ((crc=crc16(&(signal[0][0]), 11/*len*/, 0xb2/*poly*/, 0xd0/*seed*/)) != 0) {
892             if (debug_output) {
893                 fprintf(stderr,"%s Acurite 00275rm sensor bad CRC: %02x -",
894                     time_str, crc);
895                 for (uint8_t i = 0; i < 11; i++)
896                     fprintf(stderr," %02x", signal[0][i]);
897                 fprintf(stderr,"\n");
898             }
899         // CRC is OK
900         } else {
901             //  Decode the combined signal
902             id = (signal[0][0]<<16) | (signal[0][1]<<8) | signal[0][3];
903             battery_low = (signal[0][2] & 0x40)==0;
904             model       = (signal[0][2] & 1);
905             tempc       = 0.1 * ( (signal[0][4]<<4) | (signal[0][5]>>4) ) - 100;
906             probe       = signal[0][5] & 3;
907             humidity    = ((signal[0][6] & 0x1f) << 2) | (signal[0][7] >> 6);
908             //  No probe
909             if (probe==0) {
910                 data = data_make(
911                     "time",            "",             DATA_STRING,    time_str,
912                     "model",           "",             DATA_STRING,    model ? model1 : model2,
913                     "probe",           "",             DATA_INT,       probe,
914                     "id",              "",             DATA_INT,       id,
915                     "battery",         "",             DATA_STRING,    battery_low ? "LOW" : "OK",
916                     "temperature_C",   "Celcius",      DATA_FORMAT,    "%.1f C",  DATA_DOUBLE, tempc,
917                     "humidity",        "Humidity",     DATA_INT,       humidity,
918                     "crc",             "",             DATA_STRING,    "ok",
919
920                     NULL);
921             //  Water probe (detects water leak)
922             } else if (probe==1) {
923                 water = (signal[0][7] & 0x0f) == 15;
924                 data = data_make(
925                     "time",            "",             DATA_STRING,    time_str,
926                     "model",           "",             DATA_STRING,    model ? model1 : model2,
927                     "probe",           "",             DATA_INT,       probe,
928                     "id",              "",             DATA_INT,       id,
929                     "battery",         "",             DATA_STRING,    battery_low ? "LOW" : "OK",
930                     "temperature_C",   "Celcius",      DATA_FORMAT,    "%.1f C",  DATA_DOUBLE, tempc,
931                     "humidity",        "Humidity",     DATA_INT,       humidity,
932                     "water",           "",             DATA_INT,       water,
933                     "crc",             "",             DATA_STRING,    "ok",
934                     NULL);
935             //  Soil probe (detects temperature)
936             } else if (probe==2) {
937                 ptempc    = 0.1 * ( ((0x0f&signal[0][7])<<8) | signal[0][8] ) - 100; 
938                 data = data_make(
939                     "time",            "",             DATA_STRING,    time_str,
940                     "model",           "",             DATA_STRING,    model ? model1 : model2,
941                     "probe",           "",             DATA_INT,       probe,
942                     "id",              "",             DATA_INT,       id,
943                     "battery",         "",             DATA_STRING,    battery_low ? "LOW" : "OK",
944                     "temperature_C",   "Celcius",      DATA_FORMAT,    "%.1f C",  DATA_DOUBLE, tempc,
945                     "humidity",        "Humidity",     DATA_INT,       humidity,
946                     "ptemperature_C",  "Celcius",      DATA_FORMAT,    "%.1f C",  DATA_DOUBLE, ptempc,
947                     "crc",             "",             DATA_STRING,    "ok",
948                     NULL);
949             //  Spot probe (detects temperature and humidity)
950             } else if (probe==3) {
951                 ptempc    = 0.1 * ( ((0x0f&signal[0][7])<<8) | signal[0][8] ) - 100; 
952                 phumidity = signal[0][9] & 0x7f;
953                 data = data_make(
954                     "time",            "",             DATA_STRING,    time_str,
955                     "model",           "",             DATA_STRING,    model ? model1 : model2,
956                     "probe",           "",             DATA_INT,       probe,
957                     "id",              "",             DATA_INT,       id,
958                     "battery",         "",             DATA_STRING,    battery_low ? "LOW" : "OK",
959                     "temperature_C",   "Celcius",      DATA_FORMAT,    "%.1f C",  DATA_DOUBLE, tempc,
960                     "humidity",        "Humidity",     DATA_INT,       humidity,
961                     "ptemperature_C",  "Celcius",      DATA_FORMAT,    "%.1f C",  DATA_DOUBLE, ptempc,
962                     "phumidity",       "Humidity",     DATA_INT,       phumidity,
963                     "crc",             "",             DATA_STRING,    "ok",
964                     NULL);
965             }
966             data_acquired_handler(data);
967             valid=1;
968         }
969     }
970     if (valid) return 1;
971     return 0;
972 }
973
974
975 r_device acurite_rain_gauge = {
976     .name           = "Acurite 896 Rain Gauge",
977     .modulation     = OOK_PULSE_PPM_RAW,
978     .short_limit    = 1744,
979     .long_limit     = 3500,
980     .reset_limit    = 5000,
981     .json_callback  = &acurite_rain_gauge_callback,
982 // Disabled by default due to false positives on oregon scientific v1 protocol see issue #353
983     .disabled       = 1,
984     .demod_arg      = 0,
985 };
986
987
988 r_device acurite_th = {
989     .name           = "Acurite 609TXC Temperature and Humidity Sensor",
990     .modulation     = OOK_PULSE_PPM_RAW,
991     .short_limit    = 1200,
992     .long_limit     = 3000,
993     .reset_limit    = 10000,
994     .json_callback  = &acurite_th_callback,
995     .disabled       = 0,
996     .demod_arg      = 0,
997 };
998
999 /*
1000  * For Acurite 592 TXR Temp/Mumidity, but
1001  * Should match Acurite 592TX, 5-n-1, etc.
1002  *
1003  *
1004  * @todo, convert to use precise demodulator, after adding a flag
1005  *        to set "polarity" to flip short bits = 0 vs. 1.
1006  */
1007
1008 r_device acurite_txr = {
1009     .name           = "Acurite 592TXR Temp/Humidity, 5n1 Weather Station, 6045 Lightning",
1010     .modulation     = OOK_PULSE_PWM_TERNARY,
1011     .short_limit    = 320,
1012     .long_limit     = 520,
1013     .reset_limit    = 4000,
1014     .json_callback  = &acurite_txr_callback,
1015     .disabled       = 1,
1016     .demod_arg      = 2,
1017 };
1018
1019 // @todo, find a set of values that will work reasonably
1020 // with a range of signal levels
1021 //
1022 // PWM_Precise_Parameters pwm_precise_param_acurite_txr = {
1023 //      .pulse_tolerance        = 50,
1024 //      .pulse_sync_width       = 170,
1025 // };
1026
1027 //r_device acurite_txr = {
1028 //    .name           = "Acurite 592TXR Temp/Humidity sensor",
1029 //    .modulation     = OOK_PULSE_PWM_PRECISE,
1030 //    .short_limit    = 440,
1031 //    .long_limit     = 260,
1032 //    .reset_limit    = 4000,
1033 //    .json_callback  = &acurite_txr_callback,
1034 //    .disabled       = 0,
1035 //    .demod_arg      = (unsigned long)&pwm_precise_param_acurite_txr,
1036 //};
1037
1038
1039 /*
1040  * Acurite 00986 Refrigerator / Freezer Thermometer
1041  *
1042  * Temperature only, Pulse Position
1043  *
1044  * 4 x 400 sample (150 uS) start/sync pulses
1045  * 40 (42) 50 (20 uS)  (sample data pulses)
1046  * short gap approx 130 samples
1047  * long gap approx 220 samples
1048  *
1049  */
1050 r_device acurite_986 = {
1051     .name           = "Acurite 986 Refrigerator / Freezer Thermometer",
1052     .modulation     = OOK_PULSE_PPM_RAW,
1053     .short_limit    = 720,   // Threshold between short and long gap
1054     .long_limit     = 1280,
1055     .reset_limit    = 4000,
1056     .json_callback  = &acurite_986_callback,
1057     .disabled       = 1,
1058     .demod_arg      = 2,
1059 };
1060
1061 /*
1062  * Acurite 00606TX Tower Sensor
1063  *
1064  * Temperature only
1065  *
1066  */
1067 r_device acurite_606 = {
1068     .name           = "Acurite 606TX Temperature Sensor",
1069     .modulation     = OOK_PULSE_PPM_RAW,
1070     .short_limit    = 3500,
1071     .long_limit     = 7000,
1072     .reset_limit    = 10000,
1073     .json_callback  = &acurite_606_callback,
1074     .disabled       = 0,
1075     .demod_arg      = 0,
1076 };
1077
1078 r_device acurite_00275rm = {
1079     .name           = "Acurite 00275rm,00276rm Temp/Humidity with optional probe",
1080     .modulation     = OOK_PULSE_PWM_TERNARY,
1081     .short_limit    = 320,  // = 4* 80,  80  is reported by -G option
1082     .long_limit     = 520,  // = 4*130, 130  "
1083   //  .reset_limit    = 608,  // = 4*152, 152  "
1084     .reset_limit    = 708,  // = 4*152, 152  "
1085     .json_callback  = &acurite_00275rm_callback,
1086     .disabled       = 0,
1087     .demod_arg      = 2,
1088 };