From ca8c60e6ec797583c1c7ab99bd540cedfc8284dc Mon Sep 17 00:00:00 2001 From: rct Date: Sat, 14 Nov 2015 14:16:54 -0500 Subject: [PATCH 1/5] Acurite 986 Refrig/Freezer Temp initial support --- include/rtl_433.h | 2 +- include/rtl_433_devices.h | 3 +- src/devices/acurite.c | 135 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 138 insertions(+), 2 deletions(-) diff --git a/include/rtl_433.h b/include/rtl_433.h index 793f8726..81a647bf 100755 --- a/include/rtl_433.h +++ b/include/rtl_433.h @@ -30,7 +30,7 @@ #define DEFAULT_LEVEL_LIMIT 8000 // Theoretical high level at I/Q saturation is 128x128 = 16384 (above is ripple) #define MINIMAL_BUF_LENGTH 512 #define MAXIMAL_BUF_LENGTH (256 * 16384) -#define MAX_PROTOCOLS 39 +#define MAX_PROTOCOLS 40 #define SIGNAL_GRABBER_BUFFER (12 * DEFAULT_BUF_LENGTH) /* Supported modulation types */ diff --git a/include/rtl_433_devices.h b/include/rtl_433_devices.h index 87ca973c..caf9bcba 100755 --- a/include/rtl_433_devices.h +++ b/include/rtl_433_devices.h @@ -42,7 +42,8 @@ DECL(efergy_e2_classic) \ DECL(kw9015b) \ DECL(generic_temperature_sensor) \ - DECL(acurite_txr) + DECL(acurite_txr) \ + DECL(acurite_986) typedef struct { char name[256]; diff --git a/src/devices/acurite.c b/src/devices/acurite.c index 918dddc5..6345c361 100644 --- a/src/devices/acurite.c +++ b/src/devices/acurite.c @@ -9,6 +9,7 @@ * - 896 Rain gauge, Model: 00896 * - 592TXR / 06002RM Tower sensor (temperature and humidity) * - "Th" temperature and humidity sensor (Model(s) ??) + * - Acurite 986 Refrigerator / Freezer Thermometer */ @@ -484,6 +485,117 @@ static int acurite_txr_callback(bitbuffer_t *bitbuf) { } +/* + * Acurite 00896 Refrigerator / Freezer Thermometer + * + * Includes two sensors and a display, labeled 1 and 2, + * by default 1 - Refridgerator, 2 - Freezer + * + * PPM, 5 bytes, sent twice, no gap between repeaters + * start/sync pulses two short, with short gaps, followed by + * 4 long pulse/gaps. + * + * @todo, the 2 short sync pulses get confused as data. + * + * Data Format - 5 bytes, sent LSB first, reversed + * + * TT II II SS CC + * + * T - Temperature in Fahrenehit, 2's complement, integer + * I - 16 bit sensor ID. + * S - status/sensor type, 0x01 = Sensor 2 + * C = Check/CRC? + * + * @todo + * - needs new PPM demod that can separate out the short + * start/sync pulses which confuse things and cause + * one data bit to be lost in the check value. + * - Figure out check/CRC + * - low battery detection + * - verify 2's complement + * + */ + +static int acurite_986_callback(bitbuffer_t *bitbuf) { + int browlen; + uint8_t *bb, sensor_num, status, check, tempf; + float tempc; + time_t time_now; + uint16_t sensor_id; + char sensor_type; + + time(&time_now); + local_time_str(time_now, time_str); + + if (debug_output > 1) { + fprintf(stderr,"acurite_986\n"); + bitbuffer_print(bitbuf); + } + + for (uint16_t brow = 0; brow < bitbuf->num_rows; ++brow) { + browlen = (bitbuf->bits_per_row[brow] + 7)/8; + bb = bitbuf->bb[brow]; + + if (debug_output > 1) + fprintf(stderr,"acurite_986: row %d bits %d, bytes %d \n", brow, bitbuf->bits_per_row[brow], browlen); + + if (bitbuf->bits_per_row[brow] < 39 || + bitbuf->bits_per_row[brow] > 43 ) { + if (debug_output > 1 && bitbuf->bits_per_row[brow] > 16) + fprintf(stderr,"acurite_986: skipping wrong len\n"); + continue; + } + + // XXX FIXME DELETE - temporary false positive work around + if ((bb[0] == 0xff && bb[1] == 0xff && bb[2] == 0xff) || + (bb[0] == 0x00 && bb[1] == 0x00 && bb[2] == 0x00)) { + continue; + } + + + // There will be 1 extra false zero bit added by the demod. + // this forces an extra zero byte to be added + if (bb[browlen - 1] == 0) + browlen--; + + if (debug_output > 1) { + fprintf(stderr,"Acurite 986 Raw bytes: "); + for (uint8_t i = 0; i < browlen; i++) + fprintf(stderr," %02x",bb[i]); + fprintf(stderr,"\n"); + } + + if (debug_output > 0) { + fprintf(stderr,"Acurite 986 reversed: "); + for (uint8_t i = 0; i < browlen; i++) + fprintf(stderr," %02x",reverse8(bb[i])); + fprintf(stderr,"\n"); + } + + tempf = reverse8(bb[0]); + tempc = fahrenheit2celsius(tempf); + sensor_id = (reverse8(bb[1]) << 8) + reverse8(bb[2]); + status = reverse8(bb[3]); + sensor_num = (status & 0x01) + 1; + status = status >> 1; + sensor_type = sensor_num == 2 ? 'F' : 'R'; + check = reverse8(bb[4]); + + if (status != 0) { + fprintf(stderr, "%s Acurite 986 sensor 0x%04x - %d%c: Unexpected status %02x\n", + time_str, sensor_id, sensor_num, sensor_type, status); + } + + printf("%s Acurite 986 sensor 0x%04x - %d%c: %3.1f C %d F\n", + time_str, sensor_id, sensor_num, sensor_type, + tempc, tempf); + + + } + + return 0; +} + r_device acurite5n1 = { .name = "Acurite 5n1 Weather Station", .modulation = OOK_PWM_P, @@ -555,3 +667,26 @@ r_device acurite_txr = { // .disabled = 0, // .demod_arg = (unsigned long)&pwm_precise_param_acurite_txr, //}; + + +/* + * Acurite 00986 Refrigerator / Freezer Thermometer + * + * Temperature only, Pulse Position + * + * 4 x 400 sample (150 uS) start/sync pulses + * 40 (42) 50 (20 uS) (sample data pulses) + * short gap approx 130 samples + * long gap approx 220 samples + * + */ +r_device acurite_986 = { + .name = "Acurite 986 Refrigerator / Freezer Thermometer", + .modulation = OOK_PULSE_PPM_RAW, + .short_limit = 180, // Threshold between short and long gap + .long_limit = 320, + .reset_limit = 1000, + .json_callback = &acurite_986_callback, + .disabled = 0, + .demod_arg = 2, +}; From c7899241b89cf7658711d2161c0a3d04d886bf79 Mon Sep 17 00:00:00 2001 From: rct Date: Mon, 16 Nov 2015 14:58:56 -0500 Subject: [PATCH 2/5] Acurite 986, add CRC check, fix negative values --- src/devices/acurite.c | 65 +++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 24 deletions(-) diff --git a/src/devices/acurite.c b/src/devices/acurite.c index 6345c361..ee47b884 100644 --- a/src/devices/acurite.c +++ b/src/devices/acurite.c @@ -110,6 +110,7 @@ const float acurite_5n1_winddirections[] = static int acurite_raincounter = 0; +// FIXME< this is a checksum, not a CRC static int acurite_crc(uint8_t row[BITBUF_COLS], int cols) { // sum of first n-1 bytes modulo 256 should equal nth byte int i; @@ -486,7 +487,7 @@ static int acurite_txr_callback(bitbuffer_t *bitbuf) { /* - * Acurite 00896 Refrigerator / Freezer Thermometer + * Acurite 00986 Refrigerator / Freezer Thermometer * * Includes two sensors and a display, labeled 1 and 2, * by default 1 - Refridgerator, 2 - Freezer @@ -494,34 +495,35 @@ static int acurite_txr_callback(bitbuffer_t *bitbuf) { * PPM, 5 bytes, sent twice, no gap between repeaters * start/sync pulses two short, with short gaps, followed by * 4 long pulse/gaps. - * + * * @todo, the 2 short sync pulses get confused as data. - * + * * Data Format - 5 bytes, sent LSB first, reversed * * TT II II SS CC * - * T - Temperature in Fahrenehit, 2's complement, integer + * T - Temperature in Fahrenehit, integer, MSB = sign. + * Encoding is "Sign and magnitude" * I - 16 bit sensor ID. * S - status/sensor type, 0x01 = Sensor 2 - * C = Check/CRC? + * C = CRC (CRC-8 poly 0x07, little-endian) * * @todo - * - needs new PPM demod that can separate out the short + * - needs new PPM demod that can separate out the short * start/sync pulses which confuse things and cause * one data bit to be lost in the check value. - * - Figure out check/CRC * - low battery detection - * - verify 2's complement * */ static int acurite_986_callback(bitbuffer_t *bitbuf) { int browlen; - uint8_t *bb, sensor_num, status, check, tempf; + uint8_t *bb, sensor_num, status, crc, crcc; + uint8_t br[8]; + int8_t tempf; // Raw Temp is 8 bit signed Fahrenheit float tempc; time_t time_now; - uint16_t sensor_id; + uint16_t sensor_id, valid_cnt = 0; char sensor_type; time(&time_now); @@ -546,53 +548,68 @@ static int acurite_986_callback(bitbuffer_t *bitbuf) { continue; } - // XXX FIXME DELETE - temporary false positive work around + // XXX FIXME DELETE - temporary false positive avoidance if ((bb[0] == 0xff && bb[1] == 0xff && bb[2] == 0xff) || (bb[0] == 0x00 && bb[1] == 0x00 && bb[2] == 0x00)) { continue; } - // There will be 1 extra false zero bit added by the demod. // this forces an extra zero byte to be added - if (bb[browlen - 1] == 0) + if (browlen > 5 && bb[browlen - 1] == 0) browlen--; - if (debug_output > 1) { - fprintf(stderr,"Acurite 986 Raw bytes: "); - for (uint8_t i = 0; i < browlen; i++) - fprintf(stderr," %02x",bb[i]); - fprintf(stderr,"\n"); - } + // Reverse the bits + for (uint8_t i = 0; i < browlen; i++) + br[i] = reverse8(bb[i]); if (debug_output > 0) { fprintf(stderr,"Acurite 986 reversed: "); for (uint8_t i = 0; i < browlen; i++) - fprintf(stderr," %02x",reverse8(bb[i])); + fprintf(stderr," %02x",br[i]); fprintf(stderr,"\n"); } - tempf = reverse8(bb[0]); + tempf = br[0]; tempc = fahrenheit2celsius(tempf); - sensor_id = (reverse8(bb[1]) << 8) + reverse8(bb[2]); - status = reverse8(bb[3]); + sensor_id = (br[1] << 8) + br[2]; + status = br[3]; sensor_num = (status & 0x01) + 1; status = status >> 1; sensor_type = sensor_num == 2 ? 'F' : 'R'; - check = reverse8(bb[4]); + crc = br[4]; + + if ((crcc = crc8le(br, 5, 0x07, 0)) != 0) { + // XXX make debug + fprintf(stderr,"%s Acurite 986 sensor bad CRC: %02x -", + time_str, crc8le(br, 4, 0x07, 0)); + for (uint8_t i = 0; i < browlen; i++) + fprintf(stderr," %02x", br[i]); + fprintf(stderr,"\n"); + continue; + } if (status != 0) { fprintf(stderr, "%s Acurite 986 sensor 0x%04x - %d%c: Unexpected status %02x\n", time_str, sensor_id, sensor_num, sensor_type, status); } + if (tempf & 0x80) { + tempf = (tempf & 0x7f) * -1; + } + + printf("%s Acurite 986 sensor 0x%04x - %d%c: %3.1f C %d F\n", time_str, sensor_id, sensor_num, sensor_type, tempc, tempf); + valid_cnt++; } + if (valid_cnt) + return 1; + return 0; } From a4456ed361fee0ad41a353507d09f179af4dde02 Mon Sep 17 00:00:00 2001 From: rct Date: Fri, 20 Nov 2015 21:08:34 -0500 Subject: [PATCH 3/5] Acurite 986 low battery detection --- src/devices/acurite.c | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/src/devices/acurite.c b/src/devices/acurite.c index ee47b884..d702dd0c 100644 --- a/src/devices/acurite.c +++ b/src/devices/acurite.c @@ -504,8 +504,11 @@ static int acurite_txr_callback(bitbuffer_t *bitbuf) { * * T - Temperature in Fahrenehit, integer, MSB = sign. * Encoding is "Sign and magnitude" - * I - 16 bit sensor ID. - * S - status/sensor type, 0x01 = Sensor 2 + * I - 16 bit sensor ID + * changes at each power up + * S - status/sensor type + * 0x01 = Sensor 2 + * 0x02 = low battery * C = CRC (CRC-8 poly 0x07, little-endian) * * @todo @@ -548,9 +551,10 @@ static int acurite_986_callback(bitbuffer_t *bitbuf) { continue; } - // XXX FIXME DELETE - temporary false positive avoidance + // Reduce false positives + // may eliminate these with a beter PPM (precise?) demod. if ((bb[0] == 0xff && bb[1] == 0xff && bb[2] == 0xff) || - (bb[0] == 0x00 && bb[1] == 0x00 && bb[2] == 0x00)) { + (bb[0] == 0x00 && bb[1] == 0x00 && bb[2] == 0x00)) { continue; } @@ -571,25 +575,33 @@ static int acurite_986_callback(bitbuffer_t *bitbuf) { } tempf = br[0]; - tempc = fahrenheit2celsius(tempf); sensor_id = (br[1] << 8) + br[2]; status = br[3]; sensor_num = (status & 0x01) + 1; status = status >> 1; + // By default Sensor 1 is the Freezer, 2 Refrigerator sensor_type = sensor_num == 2 ? 'F' : 'R'; crc = br[4]; if ((crcc = crc8le(br, 5, 0x07, 0)) != 0) { // XXX make debug - fprintf(stderr,"%s Acurite 986 sensor bad CRC: %02x -", - time_str, crc8le(br, 4, 0x07, 0)); - for (uint8_t i = 0; i < browlen; i++) - fprintf(stderr," %02x", br[i]); - fprintf(stderr,"\n"); + if (debug_output) { + fprintf(stderr,"%s Acurite 986 sensor bad CRC: %02x -", + time_str, crc8le(br, 4, 0x07, 0)); + for (uint8_t i = 0; i < browlen; i++) + fprintf(stderr," %02x", br[i]); + fprintf(stderr,"\n"); + } continue; } - if (status != 0) { + if ((status & 1) == 1) { + fprintf(stderr, "%s Acurite 986 sensor 0x%04x - %d%c: low battery, status %02x\n", + time_str, sensor_id, sensor_num, sensor_type, status); + } + + // catch any status bits that haven't been decoded yet + if ((status & 0xFE) != 0) { fprintf(stderr, "%s Acurite 986 sensor 0x%04x - %d%c: Unexpected status %02x\n", time_str, sensor_id, sensor_num, sensor_type, status); } @@ -597,6 +609,7 @@ static int acurite_986_callback(bitbuffer_t *bitbuf) { if (tempf & 0x80) { tempf = (tempf & 0x7f) * -1; } + tempc = fahrenheit2celsius(tempf); printf("%s Acurite 986 sensor 0x%04x - %d%c: %3.1f C %d F\n", From 18bba7095911655c6c414c63ce1af55cb606e284 Mon Sep 17 00:00:00 2001 From: AlexandreCo Date: Sun, 22 Nov 2015 09:11:22 +0000 Subject: [PATCH 4/5] Inovalley kw9015b : fix negative temperature --- src/devices/inovalley-kw9015b.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/devices/inovalley-kw9015b.c b/src/devices/inovalley-kw9015b.c index f242ff71..0b880d53 100644 --- a/src/devices/inovalley-kw9015b.c +++ b/src/devices/inovalley-kw9015b.c @@ -30,7 +30,7 @@ static int kw9015b_callback(bitbuffer_t *bitbuffer) { //D : checksum device=reverse8(bb[i][0]); - fTemp=(float)(reverse8(bb[i][2])*256+reverse8(bb[i][1]))/160; + fTemp=(float)((signed short)(reverse8(bb[i][2])*256+reverse8(bb[i][1]))) /160; iRain = reverse8(bb[i][3]); chksum=((reverse8(bb[i][0])>>4)+(reverse8(bb[i][0])&0x0F)+ (reverse8(bb[i][1])>>4)+(reverse8(bb[i][1])&0x0F)+ From 159c45a120da1a82b1df624680c188604ea13878 Mon Sep 17 00:00:00 2001 From: AlexandreCo Date: Sun, 22 Nov 2015 09:39:05 +0000 Subject: [PATCH 5/5] Generic temperature sensor 1 : fix negative temperature --- src/devices/generic_temperature_sensor.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/devices/generic_temperature_sensor.c b/src/devices/generic_temperature_sensor.c index f61b16b9..cf56c92b 100644 --- a/src/devices/generic_temperature_sensor.c +++ b/src/devices/generic_temperature_sensor.c @@ -22,14 +22,16 @@ static int generic_temperature_sensor_callback(bitbuffer_t *bitbuffer) { } } - //AAAAAAAA BBBBCCCC CCCCCCCC + //AAAAAAAA BBCCCCCC CCCCCCCC //AAAAAAAA : ID //BBBB : battery ? - //CCCCCCCCCCCC : Temp * 40 + //CCCCCCCCCCCC : Temp device=(bb[1][0]); battery=(bb[1][1]&0xF0)>>4; - fTemp=(float)((bb[1][1]&0x0f)*256+bb[1][2])/40.0; + + + fTemp=(float)((signed short)(((bb[1][1]&0x3f)*256+bb[1][2])<<2))/160.0; fprintf(stdout, "\nSensor = Temperature event\n"); fprintf(stdout, "Device = %d\n", device); fprintf(stdout, "Battery? = %02X\n", battery);