@@ -21,6 +21,7 @@ Devices decoded:
2121 (Note: Some newer sensors share the 592TXR coding for compatibility.
2222- Acurite 609TXC "TH" temperature and humidity sensor (609A1TX)
2323- Acurite 986 Refrigerator / Freezer Thermometer
24+ - Acurite/Chaney 985 Refrigerator / Freezer Thermometer
2425- Acurite 515 Refrigerator / Freezer Thermometer
2526- Acurite 606TX / Technoline TX960 temperature sensor, optional with channels and [TX]Button
2627- Acurite 6045M Lightning Detector
@@ -1592,6 +1593,166 @@ static int acurite_986_decode(r_device *decoder, bitbuffer_t *bitbuffer)
15921593 return result ;
15931594}
15941595
1596+ /**
1597+ Acurite/Chaney 00985 Refrigerator / Freezer Thermometer.
1598+
1599+ Includes two sensors and a display, labeled 1 and 2,
1600+ by default 1 - Refrigerator, 2 - Freezer.
1601+
1602+ This is very similar to the Acurite 00986. The 985 is likely the version
1603+ they sold before they rebranded as Acurite. Chaney Instrument Co. is a
1604+ subsidiary of the Primex Family of Companies and Acurite is a brand.
1605+
1606+ FCC ID: RNE00985TX
1607+
1608+ Temperature range: -40F to 104F (-40C to 40C)
1609+ Accuracy +- 2F
1610+ Base frequency is 433MHz
1611+
1612+ Data Format - 7 bytes, sent LSB first, bit-reversed per byte:
1613+
1614+ XX XX TT II II SS CC
1615+
1616+ - X - Unknown (likely sync pulse / preamble)
1617+ - T - Temperature in Fahrenheit, integer, MSB = sign (sign and magnitude)
1618+ More than maximum is 0x7f
1619+ Less than minimum is 0xff
1620+ - I - 16 bit sensor ID, changes at each power up
1621+ - S - status/sensor type
1622+ bit 0: 0 for channel 1 (Refrigerator), 1 for channel 2 (Freezer)
1623+ bit 1: low battery indicator for channel 1
1624+ bit 2: low battery indicator for channel 2
1625+ low battery: 0=normal, 1=low (under 2.5V)
1626+ All other bits are undefined
1627+ - C - CRC (CRC-8 poly 0x07, little-endian)
1628+
1629+ The devices transmit three groups which are transmitted within 1 second.
1630+
1631+ The transmitting interval is initially 64 seconds upon power on.
1632+ After 20 minutes, the interval of sensor1 is 7.5 minutes, and
1633+ the interval of sensor2 is 6 minutes.
1634+
1635+ */
1636+ static int acurite_985_decode (r_device * decoder , bitbuffer_t * bitbuffer )
1637+ {
1638+ uint8_t * bb , sensor_num , status , crc , crcc ;
1639+ uint8_t br [7 ];
1640+ int bits ;
1641+ int8_t tempf ;
1642+ uint16_t sensor_id , valid_cnt = 0 ;
1643+ char sensor_type ;
1644+ char const * channel_str ;
1645+ int battery_low ;
1646+ int result = 0 ;
1647+
1648+ for (uint16_t brow = 0 ; brow < bitbuffer -> num_rows ; ++ brow ) {
1649+ bb = bitbuffer -> bb [brow ];
1650+ bits = bitbuffer -> bits_per_row [brow ];
1651+
1652+ decoder_logf (decoder , 2 , __func__ , "row %u bits %u" , brow , bits );
1653+
1654+ if (bits < 55 || bits > 59 ) {
1655+ if (bits > 16 )
1656+ decoder_log (decoder , 2 , __func__ , "skipping wrong len" );
1657+ result = DECODE_ABORT_LENGTH ;
1658+ continue ;
1659+ }
1660+
1661+ // Reduce false positives. All zero bytes will pass the CRC check.
1662+ if (bb [2 ] == 0x00 && bb [3 ] == 0x00 && bb [4 ] == 0x00 &&
1663+ bb [5 ] == 0x00 && bb [6 ] == 0x00 ) {
1664+ decoder_log (decoder , 2 , __func__ , "skipping all zeros" );
1665+ result = DECODE_ABORT_EARLY ;
1666+ continue ;
1667+ }
1668+
1669+ // Reverse the bits, msg sent LSB first
1670+ for (int i = 0 ; i < 7 ; i ++ )
1671+ br [i ] = reverse8 (bb [i ]);
1672+
1673+ decoder_log_bitrow (decoder , 1 , __func__ , br , 56 , "reversed" );
1674+
1675+ // First 2 bytes appear to be sync/preamble
1676+ tempf = br [2 ];
1677+ sensor_id = (br [3 ] << 8 ) | br [4 ];
1678+ status = br [5 ];
1679+ sensor_num = (status & 0x01 ) + 1 ;
1680+
1681+ // The two sensors use a different bit to denote low battery
1682+ if (sensor_num == 2 )
1683+ battery_low = (status & 0x04 ) ? 1 : 0 ;
1684+ else
1685+ battery_low = (status & 0x02 ) ? 1 : 0 ;
1686+
1687+ // By default Sensor 1 is Refrigerator, 2 is Freezer
1688+ sensor_type = sensor_num == 2 ? 'F' : 'R' ;
1689+ channel_str = sensor_num == 2 ? "2F" : "1R" ;
1690+
1691+ crc = br [6 ];
1692+ crcc = crc8le (br + 2 , 4 , 0x07 , 0 );
1693+
1694+ decoder_logf (decoder , 1 , __func__ , "rawtemp=0x%02x id=%u sensor_num=%d batt=%s" ,
1695+ tempf , sensor_id , sensor_num , battery_low ? "low" : "ok" );
1696+ decoder_logf (decoder , 2 , __func__ , "crc=0x%02x crcc=0x%02x" , crc , crcc );
1697+
1698+ if (crcc != crc ) {
1699+ decoder_logf_bitrow (decoder , 2 , __func__ , br , 56 , "bad CRC: %02x -" , crcc );
1700+ // HACK: the message is often missing the last 1 bit either due to a
1701+ // problem with the device or demodulator
1702+ // Add 1 (0x80 because message is LSB) and retry CRC.
1703+ if (crcc == (crc | 0x80 )) {
1704+ decoder_logf (decoder , 2 , __func__ , "CRC fix %02x - %02x" , crc , crcc );
1705+ }
1706+ else {
1707+ result = DECODE_FAIL_MIC ;
1708+ continue ;
1709+ }
1710+ }
1711+
1712+ // Convert from sign-and-magnitude
1713+ if (tempf & 0x80 ) {
1714+ tempf = (tempf & 0x7f ) * -1 ;
1715+ }
1716+
1717+ // Validate temperature
1718+ if (tempf >= -40 && tempf <= 104 ) {
1719+ decoder_logf (decoder , 1 , __func__ , "valid temperature: %d" , tempf );
1720+ }
1721+ else if (tempf == -127 || tempf == 127 ) {
1722+ decoder_logf (decoder , 1 , __func__ , "temperature %s operational range" ,
1723+ tempf == 127 ? "above" : "below" );
1724+ }
1725+ else {
1726+ decoder_logf (decoder , 1 , __func__ , "skipping bad temperature: %d" , tempf );
1727+ result = DECODE_FAIL_SANITY ;
1728+ continue ;
1729+ }
1730+
1731+ decoder_logf (decoder , 1 , __func__ , "sensor 0x%04x - %d%c: %d F" , sensor_id , sensor_num , sensor_type , tempf );
1732+
1733+ /* clang-format off */
1734+ data_t * data = data_make (
1735+ "model" , "" , DATA_STRING , "Acurite-985" ,
1736+ "id" , "" , DATA_INT , sensor_id ,
1737+ "channel" , "" , DATA_STRING , channel_str ,
1738+ "battery_ok" , "Battery" , DATA_INT , !battery_low ,
1739+ "temperature_F" , "temperature" , DATA_FORMAT , "%f F" , DATA_DOUBLE , (float )tempf ,
1740+ "status" , "Status" , DATA_INT , status ,
1741+ "mic" , "Integrity" , DATA_STRING , "CRC" ,
1742+ NULL );
1743+ /* clang-format on */
1744+
1745+ decoder_output_data (decoder , data );
1746+
1747+ valid_cnt ++ ;
1748+ }
1749+
1750+ if (valid_cnt )
1751+ return 1 ;
1752+
1753+ return result ;
1754+ }
1755+
15951756/**
15961757Acurite 606TX / Technoline TX960 Temperature sensor decoder.
15971758
@@ -1954,6 +2115,34 @@ r_device const acurite_986 = {
19542115 .fields = acurite_986_output_fields ,
19552116};
19562117
2118+ /*
2119+ * Acurite/Chaney 00985 Refrigerator / Freezer Thermometer
2120+ *
2121+ * Temperature only
2122+ */
2123+ static char const * const acurite_985_output_fields [] = {
2124+ "model" ,
2125+ "id" ,
2126+ "channel" ,
2127+ "battery_ok" ,
2128+ "temperature_F" ,
2129+ "status" ,
2130+ "mic" ,
2131+ NULL ,
2132+ };
2133+
2134+ r_device const acurite_985 = {
2135+ .name = "Acurite/Chaney 985 Refrigerator / Freezer Thermometer" ,
2136+ .modulation = OOK_PULSE_PPM ,
2137+ .short_width = 556 ,
2138+ .long_width = 1104 ,
2139+ .gap_limit = 4000 ,
2140+ .reset_limit = 7636 ,
2141+ .sync_width = 2996 ,
2142+ .decode_fn = & acurite_985_decode ,
2143+ .fields = acurite_985_output_fields ,
2144+ };
2145+
19572146/*
19582147 * Acurite 00606TX Tower Sensor
19592148 *
0 commit comments