Commit message: Fix overflow in Acurite-00275rm (closes #2012)
CVE: None
CWE: CWE-703
Vulnerability description: None

Project: rtl_433
File: acurite.c

static int acurite_590tx_decode(r_device *decoder, bitbuffer_t *bitbuffer)
{
    data_t *data;
    uint8_t *b;
    int row;
    int sensor_id;  // the sensor ID - basically a random number that gets reset whenever the battery is removed
    int battery_ok; // the battery status: 1 is good, 0 is low
    int channel;
    int humidity;
    int temp_raw; // temperature as read from the data packet
    float temp_c; // temperature in C

    row = bitbuffer_find_repeated_row(bitbuffer, 3, 25); // expected are min 3 rows
    if (row < 0)
        return DECODE_ABORT_EARLY;

    if (bitbuffer->bits_per_row[row] > 25)
        return DECODE_ABORT_LENGTH;

    b = bitbuffer->bb[row];

    if (b[4] != 0) // last byte should be zero
        return DECODE_FAIL_SANITY;

    // reject all blank messages
    if (b[0] == 0 && b[1] == 0 && b[2] == 0 && b[3] == 0)
        return DECODE_FAIL_SANITY;

    // parity check: odd parity on bits [0 .. 10]
    // i.e. 8 bytes and another 2 bits.
    uint8_t parity = b[0]; // parity as byte
    parity = (parity >> 4) ^ (parity & 0xF); // fold to nibble
    parity = (parity >> 2) ^ (parity & 0x3); // fold to 2 bits
    parity ^= b[1] >> 6; // add remaining bits
    parity = (parity >> 1) ^ (parity & 0x1); // fold to 1 bit

    if (!parity) {
        decoder_log(decoder, 1, __func__, "parity check failed");
        return DECODE_FAIL_MIC;
    }

    // Processing the temperature:
    // Upper 4 bits are stored in nibble 1, lower 8 bits are stored in nibble 2
    // upper 4 bits of nibble 1 are reserved for other usages (e.g. battery status)
    sensor_id = b[0] & 0xFE; //first 6 bits and it changes each time it resets or change the battery
    battery_ok = (b[0] & 0x01); //1=ok, 0=low battery
    //next 2 bits are checksum
    //next two bits are identify ID (maybe channel ?)
    channel = (b[1] >> 4) & 0x03;

    temp_raw = (int16_t)(((b[1] & 0x0F) << 12) | (b[2] << 4));
    temp_raw = temp_raw >> 4;
    temp_c   = (temp_raw - 500) * 0.1f; // NOTE: there seems to be a 50 degree offset?

    if (temp_raw >= 0 && temp_raw <= 100) // NOTE: no other way to differentiate humidity from temperature?
        humidity = temp_raw;
    else
        humidity = -1;

    /* clang-format off */
     data = data_make(
            "model",            "",             DATA_STRING, "Acurite-590TX",
            "id",               "",             DATA_INT,    sensor_id,
            "battery_ok",       "Battery",      DATA_INT,    battery_ok,
            "channel",          "Channel",      DATA_INT,    channel,
            "humidity",         "Humidity",     DATA_COND,   humidity != -1,    DATA_INT,    humidity,
            "temperature_C",    "Temperature",  DATA_COND,   humidity == -1,    DATA_FORMAT, "%.1f C", DATA_DOUBLE, temp_c,
            "mic",              "Integrity",    DATA_STRING, "PARITY",
            NULL);
    /* clang-format on */

    decoder_output_data(decoder, data);
    return 1;
}

Project: rtl_433
File: acurite.c

static int acurite_txr_decode(r_device *decoder, bitbuffer_t *bitbuffer)
{
    int browlen, valid = 0;
    uint8_t *bb;
    float tempf, wind_dir, wind_speed_kph, wind_speed_mph;
    uint8_t humidity, sequence_num, message_type;
    // uint8_t sensor_status;
    uint16_t sensor_id;
    int raincounter, battery_low;
    data_t *data;

    bitbuffer_invert(bitbuffer);

    for (uint16_t brow = 0; brow < bitbuffer->num_rows; ++brow) {
        browlen = (bitbuffer->bits_per_row[brow] + 7)/8;
        bb = bitbuffer->bb[brow];

        decoder_logf(decoder, 2, __func__, "row %u bits %u, bytes %d", brow, bitbuffer->bits_per_row[brow], browlen);

        if ((bitbuffer->bits_per_row[brow] < ACURITE_TXR_BITLEN ||
                bitbuffer->bits_per_row[brow] > ACURITE_5N1_BITLEN + 1)
                && bitbuffer->bits_per_row[brow] != ACURITE_6045_BITLEN
                && bitbuffer->bits_per_row[brow] != ACURITE_ATLAS_BITLEN
                && bitbuffer->bits_per_row[brow] != ACURITE_515_BITLEN) {
            if (bitbuffer->bits_per_row[brow] > 16)
                decoder_log(decoder, 2, __func__, "skipping wrong len");
            continue; // DECODE_ABORT_LENGTH
        }

        // 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--;

        // sum of first n-1 bytes modulo 256 should equal nth byte
        // also disregard a row of all zeros
        int sum = add_bytes(bb, browlen - 1);
        if (sum == 0 || (sum & 0xff) != bb[browlen - 1]) {
            decoder_log_bitrow(decoder, 1, __func__, bb, bitbuffer->bits_per_row[brow], "bad checksum");
            continue; // DECODE_FAIL_MIC
        }

        // acurite sensors with a common format appear to have a message type
        // in the lower 6 bits of the 3rd byte.
        // Format: PBMMMMMM
        // P = Parity
        // B = Battery Normal
        // M = Message type
        message_type = bb[2] & 0x3f;

        // Multiple AcuRite sensors use the same basic message format,
        // with a shared header and integrity scheme. These are differentiated
        // by the message_type.
        if (browlen == ACURITE_TXR_BITLEN / 8) {
            int decoded = 0;

            if (message_type == ACURITE_MSGTYPE_LEAK_DETECTOR) {
                decoded = acurite_leak_detector_decode(decoder, bb);
            } else if (message_type == ACURITE_MSGTYPE_TOWER_SENSOR) {
                decoded = acurite_tower_decode(decoder, bb);
            }

            // The decoder attempts for this size message will return a positive
            // value if they successfully decoded a message.
            if (decoded > 0) {
                valid++;
            }
        }

        // 515 sensor messages are 6 bytes.
        if (browlen == ACURITE_515_BITLEN / 8) {
            char const *channel_str = acurite_getChannelAndType(bb[0], message_type);

            // Sensor ID is the last 14 bits of byte 0 and 1
            // CCII IIII | IIII IIII
            // The sensor ID changes on each power-up of the sensor.
            sensor_id = ((bb[0] & 0x3f) << 8) | bb[1];

            // Sensor type (refrigerator, freezer) is determined by the message_type.
            if (message_type != ACURITE_MSGTYPE_515_REFRIGERATOR
                    && message_type != ACURITE_MSGTYPE_515_FREEZER) {
                decoder_logf(decoder, 2, __func__, "Acurite 515 sensor 0x%04X Ch %s, Unknown message type 0x%02x",
                        sensor_id, channel_str, message_type);
                continue; // DECODE_FAIL_MIC
            }

            // temperature encoding used by 515 sensors
            // 14 bits available after removing both parity bits.
            int temp_raw = ((bb[3] & 0x7F) << 7) | (bb[4] & 0x7F);
            tempf = (temp_raw - 1480) * 0.1f;
            // Battery status is the 7th bit 0x40. 1 = normal, 0 = low
            battery_low = (bb[2] & 0x40) == 0;

            /* clang-format off */
            data = data_make(
                    "model",                "",             DATA_STRING, "Acurite-515",
                    "id",                   "",             DATA_INT,    sensor_id,
                    "channel",              NULL,           DATA_STRING, channel_str,
                    "battery_ok",           "Battery",      DATA_INT,    !battery_low,
                    "temperature_F",        "Temperature",  DATA_FORMAT, "%.1f F", DATA_DOUBLE, tempf,
                    "mic",                  "Integrity",    DATA_STRING, "CHECKSUM",
                    NULL);
            /* clang-format on */

            decoder_output_data(decoder, data);
            valid++;
        }

        // The 5-n-1 weather sensor messages are 8 bytes.
        else if (message_type == ACURITE_MSGTYPE_5N1_WINDSPEED_WINDDIR_RAINFALL ||
                 message_type == ACURITE_MSGTYPE_5N1_WINDSPEED_TEMP_HUMIDITY ||
                 message_type == ACURITE_MSGTYPE_3N1_WINDSPEED_TEMP_HUMIDITY ||
                 message_type == ACURITE_MSGTYPE_RAINFALL) {
            decoder_log_bitrow(decoder, 1, __func__, bb, bitbuffer->bits_per_row[brow], "Acurite 5n1 raw msg");
            char const *channel_str = acurite_getChannel(bb[0]);

            // 5-n-1 sensor ID is the last 12 bits of byte 0 & 1
            // byte 0     | byte 1
            // CC RR IIII | IIII IIII
            sensor_id    = ((bb[0] & 0x0f) << 8) | bb[1];
            // The sensor sends the same data three times, each of these have
            // an indicator of which one of the three it is. This means the
            // checksum and first byte will be different for each one.
            // The bits 5,4 of byte 0 indicate which copy of the 65 bit data string
            //  00 = first copy
            //  01 = second copy
            //  10 = third copy
            //  1100 xxxx  = channel A 1st copy
            //  1101 xxxx  = channel A 2nd copy
            //  1110 xxxx  = channel A 3rd copy
            sequence_num = (bb[0] & 0x30) >> 4;
            battery_low = (bb[2] & 0x40) == 0;

            // Only for 5N1, range: 0 to 159 kph
            // raw number is cup rotations per 4 seconds
            // http://www.wxforum.net/index.php?topic=27244.0 (found from weewx driver)
            int speed_raw = ((bb[3] & 0x1F) << 3)| ((bb[4] & 0x70) >> 4);
            wind_speed_kph = 0;
            if (speed_raw > 0) {
                wind_speed_kph = speed_raw * 0.8278 + 1.0;
            }

            if (message_type == ACURITE_MSGTYPE_5N1_WINDSPEED_WINDDIR_RAINFALL) {
                // Wind speed, wind direction, and rain fall
                wind_dir = acurite_5n1_winddirections[bb[4] & 0x0f] * 22.5f;

                // range: 0 to 99.99 in, 0.01 inch increments, accumulated
                raincounter = ((bb[5] & 0x7f) << 7) | (bb[6] & 0x7F);

                /* clang-format off */
                data = data_make(
                        "model",        "",   DATA_STRING,    "Acurite-5n1",
                        "message_type", NULL,   DATA_INT,       message_type,
                        "id",           NULL, DATA_INT,       sensor_id,
                        "channel",      NULL,   DATA_STRING,    channel_str,
                        "sequence_num",  NULL,   DATA_INT,      sequence_num,
                        "battery_ok",       "Battery",      DATA_INT,    !battery_low,
                        "wind_avg_km_h",   "wind_speed",   DATA_FORMAT,    "%.1f km/h", DATA_DOUBLE,     wind_speed_kph,
                        "wind_dir_deg", NULL,   DATA_FORMAT,    "%.1f", DATA_DOUBLE,    wind_dir,
                        "rain_in",      "Rainfall Accumulation",   DATA_FORMAT, "%.2f in", DATA_DOUBLE, raincounter * 0.01f,
                        "mic",                  "Integrity",    DATA_STRING, "CHECKSUM",
                        NULL);
                /* clang-format on */

                decoder_output_data(decoder, data);
                valid++;
            }
            else if (message_type == ACURITE_MSGTYPE_5N1_WINDSPEED_TEMP_HUMIDITY) {
                // Wind speed, temperature and humidity

                // range -40 to 158 F
                int temp_raw = (bb[4] & 0x0F) << 7 | (bb[5] & 0x7F);
                tempf = (temp_raw - 400) * 0.1f;

                humidity = (bb[6] & 0x7f); // 1-99 %rH

                /* clang-format off */
                data = data_make(
                        "model",        "",   DATA_STRING,    "Acurite-5n1",
                        "message_type", NULL,   DATA_INT,       message_type,
                        "id",           NULL, DATA_INT,  sensor_id,
                        "channel",      NULL,   DATA_STRING,    channel_str,
                        "sequence_num",  NULL,   DATA_INT,      sequence_num,
                        "battery_ok",       "Battery",      DATA_INT,    !battery_low,
                        "wind_avg_km_h",   "wind_speed",   DATA_FORMAT,    "%.1f km/h", DATA_DOUBLE,     wind_speed_kph,
                        "temperature_F",     "temperature",    DATA_FORMAT,    "%.1f F", DATA_DOUBLE,    tempf,
                        "humidity",     NULL,    DATA_FORMAT,    "%u %%",   DATA_INT,   humidity,
                        "mic",                  "Integrity",    DATA_STRING, "CHECKSUM",
                        NULL);
                /* clang-format on */

                decoder_output_data(decoder, data);
                valid++;
            }
            else if (message_type == ACURITE_MSGTYPE_3N1_WINDSPEED_TEMP_HUMIDITY) {
                // Wind speed, temperature and humidity for 3-n-1
                sensor_id = ((bb[0] & 0x3f) << 8) | bb[1]; // 3-n-1 sensor ID is the bottom 14 bits of byte 0 & 1
                humidity = (bb[3] & 0x7f); // 1-99 %rH

                // note the 3n1 seems to have one more high bit than 5n1
                int temp_raw = (bb[4] & 0x1F) << 7 | (bb[5] & 0x7F);
                tempf        = (temp_raw - 1480) * 0.1f; // regression yields (rawtemp-1480)*0.1

                wind_speed_mph = bb[6] & 0x7f; // seems to be plain MPH

                /* clang-format off */
                data = data_make(
                        "model",        "",   DATA_STRING,    "Acurite-3n1",
                        "message_type", NULL,   DATA_INT,       message_type,
                        "id",    NULL,   DATA_FORMAT,    "0x%02X",   DATA_INT,       sensor_id,
                        "channel",      NULL,   DATA_STRING,    channel_str,
                        "sequence_num",  NULL,   DATA_INT,      sequence_num,
                        "battery_ok",       "Battery",      DATA_INT,    !battery_low,
                        "wind_avg_mi_h",   "wind_speed",   DATA_FORMAT,    "%.1f mi/h", DATA_DOUBLE,     wind_speed_mph,
                        "temperature_F",     "temperature",    DATA_FORMAT,    "%.1f F", DATA_DOUBLE,    tempf,
                        "humidity",     NULL,    DATA_FORMAT,    "%u %%",   DATA_INT,   humidity,
                        "mic",                  "Integrity",    DATA_STRING, "CHECKSUM",
                        NULL);
                /* clang-format on */

                decoder_output_data(decoder, data);
                valid++;
            }
            else if (message_type == ACURITE_MSGTYPE_RAINFALL) {
                // Rain Fall Gauge 899
                // The high 2 bits of byte zero are the channel (bits 7,6), 00 = A, 01 = B, 10 = C
                int channel = bb[0] >> 6;
                raincounter = ((bb[5] & 0x7f) << 7) | (bb[6] & 0x7f); // one tip is 0.01 inch, i.e. 0.254mm

                /* clang-format off */
                data = data_make(
                        "model",            "",                         DATA_STRING, "Acurite-Rain899",
                        "id",               "",                         DATA_INT,    sensor_id,
                        "channel",          "",                         DATA_INT,    channel,
                        "battery_ok",       "Battery",                  DATA_INT,    !battery_low,
                        "rain_mm",          "Rainfall Accumulation",    DATA_FORMAT, "%.2f mm", DATA_DOUBLE, raincounter * 0.254,
                        "mic",                  "Integrity",    DATA_STRING, "CHECKSUM",
                        NULL);
                /* clang-format on */

                decoder_output_data(decoder, data);
                valid++;
            }
            else {
                decoder_logf(decoder, 2, __func__, "Acurite 5n1 sensor 0x%04X Ch %s, Status %02X, Unknown message type 0x%02x",
                        sensor_id, channel_str, bb[3], message_type);
            }
        }

        else if (message_type == ACURITE_MSGTYPE_6045M) {
            // TODO: check parity and reject if invalid
            valid += acurite_6045_decode(decoder, bitbuffer, brow);
        }

        else if ((message_type == ACURITE_MSGTYPE_ATLAS_WNDSPD_TEMP_HUM ||
                  message_type == ACURITE_MSGTYPE_ATLAS_WNDSPD_RAIN ||
                  message_type == ACURITE_MSGTYPE_ATLAS_WNDSPD_UV_LUX ||
                  message_type == ACURITE_MSGTYPE_ATLAS_WNDSPD_TEMP_HUM_LTNG ||
                  message_type == ACURITE_MSGTYPE_ATLAS_WNDSPD_RAIN_LTNG ||
                  message_type == ACURITE_MSGTYPE_ATLAS_WNDSPD_UV_LUX_LTNG)) {
            valid += acurite_atlas_decode(decoder, bitbuffer, brow);
        }
    }

    return valid;
}

Project: rtl_433
File: acurite.c

static int acurite_6045_decode(r_device *decoder, bitbuffer_t *bitbuffer, unsigned row)
{
    float tempf;
    uint8_t humidity;
    // uint8_t message_type, l_status;
    char raw_str[31], *rawp;
    uint16_t sensor_id;
    uint8_t strike_count, strike_distance;
    int battery_low, active, rfi_detect;
    int exception = 0;
    data_t *data;

    int browlen = (bitbuffer->bits_per_row[row] + 7) / 8;
    uint8_t *bb = bitbuffer->bb[row];

    char const *channel_str = acurite_getChannel(bb[0]); // same as TXR

    // Tower sensor ID is the last 14 bits of byte 0 and 1
    // CCII IIII | IIII IIII
    sensor_id = ((bb[0] & 0x3f) << 8) | bb[1]; // same as TXR
    battery_low = (bb[2] & 0x40) == 0;
    humidity = (bb[3] & 0x7f); // 1-99 %rH, same as TXR
    active = (bb[4] & 0x40) == 0x40;    // Sensor is actively listening for strikes
    //message_type = bb[2] & 0x3f;

    // 12 bits of temperature after removing parity and status bits.
    // Message native format appears to be in 1/10 of a degree Fahrenheit
    // Device Specification: -40 to 158 F  / -40 to 70 C
    // Available range given 12 bits with +1480 offset: -140.0 F to +261.5 F
    int temp_raw = ((bb[4] & 0x1F) << 7) | (bb[5] & 0x7F);
    tempf = (temp_raw - 1480) * 0.1f;

    // Strike count is 8 bits, LSB in following byte
    strike_count = ((bb[6] & 0x7f) << 1) | ((bb[7] & 0x40) >> 6);
    strike_distance = bb[7] & 0x1f;
    rfi_detect = (bb[7] & 0x20) == 0x20;
    //l_status = (bb[7] & 0x60) >> 5;

    /*
     * 2018-04-21 rct - There are still a number of unknown bits in the
     * message that need to be figured out. Add the raw message hex to
     * to the structured data output to allow future analysis without
     * having to enable debug for long running rtl_433 processes.
     */
    rawp = (char *)raw_str;
    for (int i=0; i < MIN(browlen, 15); i++) {
        sprintf(rawp,"%02x",bb[i]);
        rawp += 2;
    }
    *rawp = '\0';

    // Flag whether this message might need further analysis
    if (((bb[4] & 0x20) != 0) ||  // unknown status bits, always off
        (humidity > 100) ||
        (tempf > 158) ||
        (tempf < -40)) {
        exception++;
    }

    /* clang-format off */
    data = data_make(
            "model",            "",                 DATA_STRING, "Acurite-6045M",
            "id",               NULL,               DATA_INT,    sensor_id,
            "channel",          NULL,               DATA_STRING, channel_str,
            "battery_ok",       "Battery",          DATA_INT,    !battery_low,
            "temperature_F",    "temperature",      DATA_FORMAT, "%.1f F",     DATA_DOUBLE,     tempf,
            "humidity",         "humidity",         DATA_FORMAT, "%u %%", DATA_INT,    humidity,
            "strike_count",     "strike_count",     DATA_INT,    strike_count,
            "storm_dist",       "storm_distance",   DATA_INT,    strike_distance,
            "active",           "active_mode",      DATA_INT,    active,    // @todo convert to bool
            "rfi",              "rfi_detect",       DATA_INT,    rfi_detect,     // @todo convert to bool
            "exception",        "data_exception",   DATA_INT,    exception,    // @todo convert to bool
            "raw_msg",          "raw_message",      DATA_STRING, raw_str,
            NULL);
    /* clang-format on */

    decoder_output_data(decoder, data);
    return 1;
}

Project: rtl_433
File: acurite.c

static char const *acurite_getChannelAndType(uint8_t byte, uint8_t mtype)
{
    static char const *channel_strs[] = {"CR", "ER", "BR", "AR", "CF", "EF", "BF", "AF"}; // 'E' stands for error

    int channel = ((mtype & 0x01) << 2) | ((byte & 0xC0) >> 6);
    return channel_strs[channel];
}

Project: rtl_433
File: acurite.c

static int acurite_th_decode(r_device *decoder, bitbuffer_t *bitbuffer)
{
    uint8_t *bb = NULL;
    int cksum, battery_low, valid = 0;
    float tempc;
    uint8_t humidity, id, status;
    data_t *data;
    int result = 0;

    for (uint16_t brow = 0; brow < bitbuffer->num_rows; ++brow) {
        if (bitbuffer->bits_per_row[brow] != 40) {
            result = DECODE_ABORT_LENGTH;
            continue; // DECODE_ABORT_LENGTH
        }

        bb = bitbuffer->bb[brow];

        cksum = (bb[0] + bb[1] + bb[2] + bb[3]);

        if (cksum == 0 || ((cksum & 0xff) != bb[4])) {
            result = DECODE_FAIL_MIC;
            continue; // DECODE_FAIL_MIC
        }

        // Temperature in Celsius is encoded as a 12 bit integer value
        // multiplied by 10 using the 4th - 6th nybbles (bytes 1 & 2)
        // negative values are recovered by sign extend from int16_t.
        int temp_raw = (int16_t)(((bb[1] & 0x0f) << 12) | (bb[2] << 4));
        tempc        = (temp_raw >> 4) * 0.1f;
        id           = bb[0];
        status       = (bb[1] & 0xf0) >> 4;
        battery_low  = status & 0x8;
        humidity     = bb[3];

        /* clang-format off */
        data = data_make(
                "model",            "",             DATA_STRING, "Acurite-609TXC",
                "id",               "",             DATA_INT,    id,
                "battery_ok",       "Battery",      DATA_INT,    !battery_low,
                "temperature_C",    "Temperature",  DATA_FORMAT, "%.1f C", DATA_DOUBLE, tempc,
                "humidity",         "Humidity",     DATA_FORMAT, "%u %%", DATA_INT,    humidity,
                "status",           "",             DATA_INT,    status,
                "mic",              "Integrity",    DATA_STRING, "CHECKSUM",
                NULL);
        /* clang-format on */

        decoder_output_data(decoder, data);
        valid++;
    }

    if (valid)
        return 1;

    // Only returns the latest result, but better than nothing.
    return result;
}

Project: rtl_433
File: acurite.c

static int acurite_00275rm_decode(r_device *decoder, bitbuffer_t *bitbuffer)
{
    int result = 0;
    bitbuffer_invert(bitbuffer);

    // This sensor repeats a signal three times. Combine as fallback.
    uint8_t *b_rows[3] = {0};
    int n_rows         = 0;
    for (int row = 0; row < bitbuffer->num_rows; ++row) {
        if (n_rows < 3 && bitbuffer->bits_per_row[row] == 88) {
            b_rows[n_rows] = bitbuffer->bb[row];
            n_rows++;
        }
    }

    // Combine signal if exactly three repeats were found
    if (n_rows == 3) {
        bitbuffer_add_row(bitbuffer);
        uint8_t *b = bitbuffer->bb[bitbuffer->num_rows - 1];
        for (int i = 0; i < 11; ++i) {
            // The majority bit count wins
            b[i] = (b_rows[0][i] & b_rows[1][i]) |
                    (b_rows[1][i] & b_rows[2][i]) |
                    (b_rows[2][i] & b_rows[0][i]);
        }
        bitbuffer->bits_per_row[bitbuffer->num_rows - 1] = 88;
    }

    // Output the first valid row
    for (int row = 0; row < bitbuffer->num_rows; ++row) {
        if (bitbuffer->bits_per_row[row] != 88) {
            result = DECODE_ABORT_LENGTH;
            continue; // return DECODE_ABORT_LENGTH;
        }
        uint8_t *b = bitbuffer->bb[row];

        // Check CRC
        if (crc16lsb(b, 11, 0x00b2, 0x00d0) != 0) {
            decoder_log_bitrow(decoder, 1, __func__, b, 11 * 8, "sensor bad CRC");
            result = DECODE_FAIL_MIC;
            continue; // return DECODE_FAIL_MIC;
        }

        //  Decode common fields
        int id          = (b[0] << 16) | (b[1] << 8) | b[3];
        int battery_low = (b[2] & 0x40) == 0;
        int model_flag  = (b[2] & 1);
        float tempc     = ((b[4] << 4) | (b[5] >> 4)) * 0.1 - 100;
        int probe       = b[5] & 3;
        int humidity    = ((b[6] & 0x1f) << 2) | (b[7] >> 6);

        //  Water probe (detects water leak)
        int water = (b[7] & 0x0f) == 15; // valid only if (probe == 1)
        //  Soil probe (detects temperature)
        float ptempc = (((b[7] & 0x0f) << 8) | b[8]) * 0.1 - 100; // valid only if (probe == 2 || probe == 3)
        //  Spot probe (detects temperature and humidity)
        int phumidity = b[9] & 0x7f; // valid only if (probe == 3)

        /* clang-format off */
        data_t *data = data_make(
                "model",            "",             DATA_STRING,    model_flag ? "Acurite-00275rm" : "Acurite-00276rm",
                "subtype",          "Probe",        DATA_INT,       probe,
                "id",               "",             DATA_INT,       id,
                "battery_ok",       "Battery",      DATA_INT,       !battery_low,
                "temperature_C",    "Celsius",      DATA_FORMAT,    "%.1f C",  DATA_DOUBLE, tempc,
                "humidity",         "Humidity",     DATA_FORMAT,    "%u %%", DATA_INT,      humidity,
                "water",            "",             DATA_COND, probe == 1, DATA_INT,        water,
                "temperature_1_C",  "Celsius",      DATA_COND, probe == 2, DATA_FORMAT, "%.1f C",   DATA_DOUBLE, ptempc,
                "temperature_1_C",  "Celsius",      DATA_COND, probe == 3, DATA_FORMAT, "%.1f C",   DATA_DOUBLE, ptempc,
                "humidity_1",       "Humidity",     DATA_COND, probe == 3, DATA_FORMAT, "%u %%",    DATA_INT,    phumidity,
                "mic",              "Integrity",    DATA_STRING,    "CRC",
                NULL);
        /* clang-format on */

        decoder_output_data(decoder, data);

        return 1;
    }
    // Only returns the latest result, but better than nothing.
    return result;
}

Project: rtl_433
File: acurite.c

static int acurite_606_decode(r_device *decoder, bitbuffer_t *bitbuffer)
{
    data_t *data;
    uint8_t *b;
    int row;
    int16_t temp_raw; // temperature as read from the data packet
    float temp_c;     // temperature in C
    int battery_ok;   // the battery status: 1 is good, 0 is low
    int sensor_id;    // the sensor ID - basically a random number that gets reset whenever the battery is removed

    row = bitbuffer_find_repeated_row(bitbuffer, 3, 32); // expected are 6 rows
    if (row < 0)
        return DECODE_ABORT_EARLY;

    if (bitbuffer->bits_per_row[row] > 33)
        return DECODE_ABORT_LENGTH;

    b = bitbuffer->bb[row];

    if (b[4] != 0)
        return DECODE_FAIL_SANITY;

    // reject all blank messages
    if (b[0] == 0 && b[1] == 0 && b[2] == 0 && b[3] == 0)
        return DECODE_FAIL_SANITY;

    // calculate the checksum and only continue if we have a matching checksum
    uint8_t chk = lfsr_digest8(b, 3, 0x98, 0xf1);
    if (chk != b[3])
        return DECODE_FAIL_MIC;

    // Processing the temperature:
    // Upper 4 bits are stored in nibble 1, lower 8 bits are stored in nibble 2
    // upper 4 bits of nibble 1 are reserved for other usages (e.g. battery status)
    sensor_id  = b[0];
    battery_ok = (b[1] & 0x80) >> 7;
    temp_raw   = (int16_t)((b[1] << 12) | (b[2] << 4));
    temp_raw   = temp_raw >> 4;
    temp_c     = temp_raw * 0.1f;

    /* clang-format off */
    data = data_make(
            "model",            "",             DATA_STRING, "Acurite-606TX",
            "id",               "",             DATA_INT, sensor_id,
            "battery_ok",       "Battery",      DATA_INT,    battery_ok,
            "temperature_C",    "Temperature",  DATA_FORMAT, "%.1f C", DATA_DOUBLE, temp_c,
            "mic",              "Integrity",    DATA_STRING, "CHECKSUM",
            NULL);
    /* clang-format on */

    decoder_output_data(decoder, data);
    return 1;
}

Project: rtl_433
File: acurite.c

static int acurite_tower_decode(r_device* decoder, uint8_t* bb)
{
    // checksum in the last byte has been validated in the calling function

    // Verify parity bits
    // Bytes 2, 3, 4, and 5 should all have a parity bit in their MSB
    int parity = parity_bytes(&bb[2], 4);
    if (parity) {
        decoder_log_bitrow(decoder, 1, __func__, bb, 7 * 8, "bad parity");
        return DECODE_FAIL_MIC;
    }

    // Channel is the first two bits of the 0th byte
    // but only 3 of the 4 possible values are valid
    char const* channel_str = acurite_getChannel(bb[0]);
    if (*channel_str == 'E') {
        decoder_logf(decoder, 1, __func__, "bad channel Ch %s", channel_str);
        return DECODE_FAIL_SANITY;
    }

    // Tower sensor ID is the last 14 bits of byte 0 and 1
    // CCII IIII | IIII IIII
    int sensor_id = ((bb[0] & 0x3f) << 8) | bb[1];

    // Battery status is the 7th bit 0x40. 1 = normal, 0 = low
    // pxxx xxxB
    int battery_low = (bb[2] & 0x40) == 0;

    // Humidity is stored in byte 3
    // The value is directly encoded as %rH
    // The possible values here are 0-128, but the manufacturer specifies that valid values
    // are only 1-99 %rH
    // pIII IIII
    int humidity = (bb[3] & 0x7f);
    if (humidity < 0 || humidity > 100) {
        decoder_logf(decoder, 1, __func__, "0x%04X Ch %s : Impossible humidity: %d %%rH",
                sensor_id, channel_str, humidity);
        return DECODE_FAIL_SANITY;
    }

    // temperature encoding used by "tower" sensors 592txr
    // 14 bits available after removing both parity bits.
    // 11 bits needed for specified range -40 C to 70 C (-40 F - 158 F)
    // Possible ranges are -100 C to 1538.4 C, but most of that range
    // is not possible on Earth.
    // pIII IIII pIII IIII
    int temp_raw = ((bb[4] & 0x7F) << 7) | (bb[5] & 0x7F);
    float tempc = temp_raw * 0.1 - 100;
    if (tempc < -40 || tempc > 70) {
        decoder_logf(decoder, 1, __func__, "0x%04X Ch %s : Impossible temperature: %0.2f C",
                sensor_id, channel_str, tempc);
        return DECODE_FAIL_SANITY;
    }

    data_t* data;
    /* clang-format off */
    data = data_make(
            "model",                "",             DATA_STRING, "Acurite-Tower",
            "id",                   "",             DATA_INT,    sensor_id,
            "channel",              NULL,           DATA_STRING, channel_str,
            "battery_ok",           "Battery",      DATA_INT,    !battery_low,
            "temperature_C",        "Temperature",  DATA_FORMAT, "%.1f C", DATA_DOUBLE, tempc,
            "humidity",             "Humidity",     DATA_FORMAT, "%u %%", DATA_INT,    humidity,
            "mic",                  "Integrity",    DATA_STRING, "CHECKSUM",
            NULL);
    /* clang-format on */

    decoder_output_data(decoder, data);

    return 1;
}

Project: rtl_433
File: acurite.c

static char const *acurite_getChannel(uint8_t byte)
{
    static char const *channel_strs[] = {"C", "E", "B", "A"}; // 'E' stands for error

    int channel = (byte & 0xC0) >> 6;
    return channel_strs[channel];
}

Project: rtl_433
File: acurite.c

static int acurite_rain_896_decode(r_device *decoder, bitbuffer_t *bitbuffer)
{
    uint8_t *b = bitbuffer->bb[0];
    int id;
    float total_rain;
    data_t *data;

    // 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
    if (bitbuffer->bits_per_row[0] < 24)
        return DECODE_ABORT_LENGTH;

    if ((b[0] == 0) || (b[1] == 0) || (b[2] == 0) || (b[3] != 0) || (b[4] != 0))
        return DECODE_ABORT_EARLY;

    id = b[0];
    total_rain = ((b[1] & 0xf) << 8) | b[2];
    total_rain *= 0.5; // Sensor reports number of bucket tips.  Each bucket tip is .5mm

    decoder_logf(decoder, 2, __func__, "Total Rain is %2.1fmm", total_rain);
    decoder_log_bitrow(decoder, 2, __func__, b, bitbuffer->bits_per_row[0], "Raw Message ");

    /* clang-format off */
    data = data_make(
            "model",                "",             DATA_STRING, "Acurite-Rain",
            "id",                   "",             DATA_INT,    id,
            "rain_mm",              "Total Rain",   DATA_FORMAT, "%.1f mm", DATA_DOUBLE, total_rain,
            NULL);
    /* clang-format on */

    decoder_output_data(decoder, data);
    return 1;
}

Project: rtl_433
File: acurite.c

static int acurite_986_decode(r_device *decoder, bitbuffer_t *bitbuffer)
{
    int const browlen = 5;
    uint8_t *bb, sensor_num, status, crc, crcc;
    uint8_t br[8];
    int8_t tempf; // Raw Temp is 8 bit signed Fahrenheit
    uint16_t sensor_id, valid_cnt = 0;
    char sensor_type;
    char *channel_str;
    int battery_low;
    data_t *data;

    int result = 0;

    for (uint16_t brow = 0; brow < bitbuffer->num_rows; ++brow) {

        decoder_logf(decoder, 2, __func__, "row %u bits %u, bytes %d", brow, bitbuffer->bits_per_row[brow], browlen);

        if (bitbuffer->bits_per_row[brow] < 39 ||
            bitbuffer->bits_per_row[brow] > 43 ) {
            if (bitbuffer->bits_per_row[brow] > 16)
                decoder_log(decoder, 2, __func__,"skipping wrong len");
            result = DECODE_ABORT_LENGTH;
            continue; // DECODE_ABORT_LENGTH
        }
        bb = bitbuffer->bb[brow];

        // Reduce false positives
        // may eliminate these with a better PPM (precise?) demod.
        if ((bb[0] == 0xff && bb[1] == 0xff && bb[2] == 0xff) ||
                (bb[0] == 0x00 && bb[1] == 0x00 && bb[2] == 0x00)) {
            result = DECODE_ABORT_EARLY;
            continue; // DECODE_ABORT_EARLY
        }

        // Reverse the bits, msg sent LSB first
        for (int i = 0; i < browlen; i++)
            br[i] = reverse8(bb[i]);

        decoder_log_bitrow(decoder, 1, __func__, br, browlen * 8, "reversed");

        tempf = br[0];
        sensor_id = (br[1] << 8) + br[2];
        status = br[3];
        sensor_num = (status & 0x01) + 1;
        status = status >> 1;
        battery_low = ((status & 1) == 1);

        // By default Sensor 1 is the Freezer, 2 Refrigerator
        sensor_type = sensor_num == 2 ? 'F' : 'R';
        channel_str = sensor_num == 2 ? "2F" : "1R";

        crc = br[4];
        crcc = crc8le(br, 4, 0x07, 0);

        if (crcc != crc) {
            decoder_logf_bitrow(decoder, 2, __func__, br, browlen * 8, "bad CRC: %02x -", crc8le(br, 4, 0x07, 0));
            // HACK: rct 2018-04-22
            // the message is often missing the last 1 bit either due to a
            // problem with the device or demodulator
            // Add 1 (0x80 because message is LSB) and retry CRC.
            if (crcc == (crc | 0x80)) {
                decoder_logf(decoder, 2, __func__, "CRC fix %02x - %02x", crc, crcc);
            }
            else {
                continue; // DECODE_FAIL_MIC
            }
        }

        if (tempf & 0x80) {
            tempf = (tempf & 0x7f) * -1;
        }

        decoder_logf(decoder, 1, __func__, "sensor 0x%04x - %d%c: %d F", sensor_id, sensor_num, sensor_type, tempf);

        /* clang-format off */
        data = data_make(
                "model",            "",             DATA_STRING, "Acurite-986",
                "id",               NULL,           DATA_INT,    sensor_id,
                "channel",          NULL,           DATA_STRING, channel_str,
                "battery_ok",       "Battery",      DATA_INT,    !battery_low,
                "temperature_F",    "temperature",  DATA_FORMAT, "%f F", DATA_DOUBLE,    (float)tempf,
                "status",           "status",       DATA_INT,    status,
                "mic",              "Integrity",    DATA_STRING, "CRC",
                NULL);
        /* clang-format on */

        decoder_output_data(decoder, data);

        valid_cnt++;
    }

    if (valid_cnt)
        return 1;

    return result;
}

Project: rtl_433
File: acurite.c

static int acurite_atlas_decode(r_device *decoder, bitbuffer_t *bitbuffer, unsigned row)
{
    uint8_t humidity, sequence_num, message_type;
    char raw_str[31], *rawp;
    uint16_t sensor_id;
    int raincounter, battery_low;
    int exception = 0;
    float tempf, wind_dir, wind_speed_mph;
    data_t *data;

    int browlen = (bitbuffer->bits_per_row[row] + 7) / 8;
    uint8_t *bb = bitbuffer->bb[row];

    // {80} 82 f3 65 00 88 72 22 00 9f 95  {80} 86 f3 65 00 88 72 22 00 9f 99  {80} 8a f3 65 00 88 72 22 00 9f 9d
    // {80} 82 f3 66 00 05 e4 81 00 9f e4  {80} 86 f3 66 00 05 e4 81 00 9f e8  {80} 8a f3 66 00 05 e4 81 00 9f ec
    // {80} 82 f3 e7 00 00 00 96 00 9f 91  {80} 86 f3 e7 00 00 00 96 00 9f 95  {80} 8a f3 e7 00 00 00 96 00 9f 99
    // {80} 82 f3 66 00 05 60 81 00 9f 60  {80} 86 f3 66 00 05 60 81 00 9f 64  {80} 8a f3 66 00 05 60 81 00 9f 68
    // {80} 82 f3 65 00 88 71 24 00 9f 96  {80} 86 f3 65 00 88 71 24 00 9f 9a  {80} 8a f3 65 00 88 71 24 00 9f 9e
    // {80} 82 f3 65 00 88 71 a5 00 9f 17  {80} 86 f3 65 00 88 71 a5 00 9f 1b  {80} 8a f3 65 00 88 71 a5 00 9f 1f

    // decoder_log_bitrow(decoder, 0, __func__, bb, bitbuffer->bits_per_row[brow], "Acurite Atlas raw msg");
    message_type = bb[2] & 0x3f;
    sensor_id = ((bb[0] & 0x03) << 8) | bb[1];
    char const *channel_str = acurite_getChannel(bb[0]);

    // There are still a few unknown/unused bits in the message that
    // message that could possibly hold some data. Add the raw message hex to
    // to the structured data output to allow future analysis without
    // having to enable debug for long running rtl_433 processes.
    rawp = (char *)raw_str;
    for (int i=0; i < MIN(browlen, 15); i++) {
        sprintf(rawp,"%02x",bb[i]);
        rawp += 2;
    }
    *rawp = '\0';

    // The sensor sends the same data three times, each of these have
    // an indicator of which one of the three it is. This means the
    // checksum and first byte will be different for each one.
    // The bits 4,5 of byte 0 indicate which copy
    //  xxxx 00 xx = first copy
    //  xxxx 01 xx = second copy
    //  xxxx 10 xx = third copy
    sequence_num = (bb[0] & 0x0c) >> 2;
    // Battery status is the 7th bit 0x40. 1 = normal, 0 = low
    battery_low = (bb[2] & 0x40) == 0;

    // Wind speed is 8-bits raw MPH
    wind_speed_mph = ((bb[3] & 0x7F) << 1) | ((bb[4] & 0x40) >> 6);

    /* clang-format off */
    data = data_make(
            "model",                "",             DATA_STRING, "Acurite-Atlas",
            "id",                   NULL,           DATA_INT,    sensor_id,
            "channel",              NULL,           DATA_STRING, channel_str,
            "sequence_num",         NULL,           DATA_INT,    sequence_num,
            "battery_ok",           "Battery",      DATA_INT,    !battery_low,
            "message_type",         NULL,           DATA_INT,    message_type,
            "wind_avg_mi_h",        "Wind Speed",   DATA_FORMAT, "%.1f mi/h", DATA_DOUBLE, wind_speed_mph,
            NULL);
    /* clang-format on */

    if (message_type == ACURITE_MSGTYPE_ATLAS_WNDSPD_TEMP_HUM ||
            message_type == ACURITE_MSGTYPE_ATLAS_WNDSPD_TEMP_HUM_LTNG) {
        // Wind speed, temperature and humidity

        // range -40 to 160 F
        // TODO: are there really 13 bits? use 11 for now.
        int temp_raw = (bb[4] & 0x0F) << 7 | (bb[5] & 0x7F);
        tempf = (temp_raw - 400) * 0.1;

        humidity = (bb[6] & 0x7f); // 1-99 %rH

        /* clang-format off */
        data = data_append(data,
                "temperature_F",    "temperature",  DATA_FORMAT,    "%.1f F",       DATA_DOUBLE, tempf,
                "humidity",         NULL,           DATA_FORMAT,    "%u %%",        DATA_INT,    humidity,
                NULL);
        /* clang-format on */
    }

    if (message_type == ACURITE_MSGTYPE_ATLAS_WNDSPD_RAIN ||
            message_type == ACURITE_MSGTYPE_ATLAS_WNDSPD_RAIN_LTNG) {
        // Wind speed, wind direction, and rain fall
        wind_dir = ((bb[4] & 0x1f) << 5) | ((bb[5] & 0x7c) >> 2);

        // range: 0 to 5.11 in, 0.01 inch increments, accumulated
        // JRH: Confirmed 9 bits, counter rolls over after 5.11 inches
        raincounter = ((bb[5] & 0x03) << 7) | (bb[6] & 0x7F);

        /* clang-format off */
        data = data_append(data,
                "wind_dir_deg",     NULL,           DATA_FORMAT,    "%.1f",         DATA_DOUBLE, wind_dir,
                "rain_in",          "Rainfall Accumulation", DATA_FORMAT, "%.2f in", DATA_DOUBLE, raincounter * 0.01f,
                NULL);
        /* clang-format on */
    }

    if (message_type == ACURITE_MSGTYPE_ATLAS_WNDSPD_UV_LUX ||
            message_type == ACURITE_MSGTYPE_ATLAS_WNDSPD_UV_LUX_LTNG) {
        // Wind speed, UV Index, Light Intensity, Lightning?
        int uv  = (bb[4] & 0x0f);
        int lux = ((bb[5] & 0x7f) << 7) | (bb[6] & 0x7F);

        /* clang-format off */
        data = data_append(data,
                "uv",               NULL,           DATA_INT, uv,
                "lux",              NULL,           DATA_INT, lux * 10,
                NULL);
        /* clang-format on */
    }

    if ((message_type == ACURITE_MSGTYPE_ATLAS_WNDSPD_TEMP_HUM_LTNG ||
                message_type == ACURITE_MSGTYPE_ATLAS_WNDSPD_RAIN_LTNG ||
                message_type == ACURITE_MSGTYPE_ATLAS_WNDSPD_UV_LUX_LTNG)) {

        // @todo decode strike_distance to miles or KM.
        int strike_count    = ((bb[7] & 0x7f) << 2) | ((bb[8] & 0x60) >> 5);
        int strike_distance = bb[8] & 0x1f;

        /* clang-format off */
        data = data_append(data,
                "strike_count",         NULL,           DATA_INT, strike_count,
                "strike_distance",      NULL,           DATA_INT, strike_distance,
                NULL);
        /* clang-format on */
    }

    data = data_append(data,
            "exception",        "data_exception",   DATA_INT,    exception,    // @todo convert to bool
            "raw_msg",          "raw_message",      DATA_STRING, raw_str,
            NULL);

    decoder_output_data(decoder, data);

    return 1; // one valid message decoded
}

Project: rtl_433
File: acurite.c

static int acurite_leak_detector_decode(r_device* decoder, uint8_t* bb)
{
    // checksum in the last byte has been validated in the calling function

    // Verify parity bits
    // Bytes 2, 3, 4, and 5 should all have a parity bit in their MSB
    int parity = parity_bytes(&bb[2], 4);
    if (parity) {
        decoder_log_bitrow(decoder, 1, __func__, bb, 7 * 8, "bad parity");
        return DECODE_FAIL_MIC;
    }

    // Channel is the first two bits of the 0th byte
    // but only 3 of the 4 possible values are valid
    char const* channel_str = acurite_getChannel(bb[0]);
    if (*channel_str == 'E') {
        decoder_logf(decoder, 1, __func__, "Acurite TXR sensor : bad channel Ch %s", channel_str);
        return DECODE_FAIL_SANITY;
    }

    // Tower sensor ID is the last 14 bits of byte 0 and 1
    // CCII IIII | IIII IIII
    int sensor_id = ((bb[0] & 0x3f) << 8) | bb[1];

    // Battery status is the 7th bit 0x40. 1 = normal, 0 = low
    int battery_low = (bb[2] & 0x40) == 0;

    // Leak indicator bit is the 5th bit of byte 3. 1 = wet, 0 = dry
    int is_wet = (bb[3] & 0x10) >> 4;

    data_t* data;
    /* clang-format off */
    data = data_make(
            "model",                "",             DATA_STRING, "Acurite-Leak",
            "id",                   "",             DATA_INT,    sensor_id,
            "channel",              NULL,           DATA_STRING, channel_str,
            "battery_ok",           "Battery",      DATA_INT,    !battery_low,
            "leak_detected",        "Leak",         DATA_INT,    is_wet,
            "mic",                  "Integrity",    DATA_STRING, "CHECKSUM",
            NULL);
    /* clang-format on */

    decoder_output_data(decoder, data);

    return 1;
}