static int thermopro_tp12_sensor_callback(bitbuffer_t *bitbuffer) { int iTemp1, iTemp2, good = -1; float fTemp1, fTemp2; uint8_t *bytes; unsigned int device, value; char time_str[LOCAL_TIME_BUFLEN]; data_t *data; // The device transmits 16 rows, let's check for 3 matching. // (Really 17 rows, but the last one doesn't match because it's missing a trailing 1.) good = bitbuffer_find_repeated_row(bitbuffer, 5, 40); if (good < 0) { return 0; } bytes = bitbuffer->bb[good]; if (!bytes[0] && !bytes[1] && !bytes[2] && !bytes[3]) { return 0; // reduce false positives } // Note: the device ID changes randomly each time you replace the battery, so we can't early out based on it. // This is probably to allow multiple devices to be used at once. When you replace the receiver batteries // or long-press its power button, it pairs with the first device ID it hears. device = bytes[0]; if(debug_output) { // There is a mysterious checksum in bytes[4]. It may be the same as the checksum used by the TP-11, // which consisted of a lookup table containing, for each bit in the message, a byte to be xor-ed into // the checksum if the message bit was 1. It should be possible to solve for that table using Gaussian // elimination, so dump some data so we can try this. // This format is easily usable by bruteforce-crc, after piping through | grep raw_data | cut -d':' -f2 // bruteforce-crc didn't find anything, though - this may not be a CRC algorithm specifically. fprintf(stderr,"thermopro_tp12_raw_data:"); for(int bit_index = 0; bit_index < 40; ++bit_index){ fputc(bitrow_get_bit(bytes, bit_index) + '0', stderr); } fputc('\n', stderr); } iTemp1 = ((bytes[2] & 0xf0) << 4) | bytes[1]; iTemp2 = ((bytes[2] & 0x0f) << 8) | bytes[3]; fTemp1 = (iTemp1 - 200) / 10.; fTemp2 = (iTemp2 - 200) / 10.; local_time_str(0, time_str); data = data_make("time", "", DATA_STRING, time_str, "model", "", DATA_STRING, MODEL, "id", "Id", DATA_FORMAT, "\t %d", DATA_INT, device, "temperature_1_C", "Temperature 1 (Food)", DATA_FORMAT, "%.01f C", DATA_DOUBLE, fTemp1, "temperature_2_C", "Temperature 2 (Barbecue)", DATA_FORMAT, "%.01f C", DATA_DOUBLE, fTemp2, NULL); data_acquired_handler(data); return 1; }
static int lightwave_rf_callback(bitbuffer_t *bitbuffer) { bitrow_t *bb = bitbuffer->bb; // Validate package // Transmitted pulses are always 72 // Pulse 72 (delimiting "1" is not demodulated, as gap becomes End-Of-Message - thus expected length is 71 if ((bitbuffer->bits_per_row[0] == 71) && (bitbuffer->num_rows == 1)) // There should be only one message (and we use the rest...) { // Polarity is inverted bitbuffer_invert(bitbuffer); // Expand all "0" to "10" (bit stuffing) // row_in = 0, row_out = 1 bitbuffer_add_row(bitbuffer); for (unsigned n=0; n < bitbuffer->bits_per_row[0]; ++n) { if (bitrow_get_bit(bb[0], n)) { bitbuffer_add_bit(bitbuffer, 1); } else { bitbuffer_add_bit(bitbuffer, 1); bitbuffer_add_bit(bitbuffer, 0); } } // Check length is correct // Due to encoding there will be two "0"s per byte, thus message grows to 91 bits if (bitbuffer->bits_per_row[1] != 91) return 0; // Check initial delimiter bit is "1" unsigned bit_idx = 0; uint8_t delimiter_bit = bitrow_get_bit(bb[1], bit_idx++); if (delimiter_bit == 0) return 0; // Decode error // Strip delimiter bits // row_in = 1, row_out = 2 bitbuffer_add_row(bitbuffer); for(unsigned n=0; n<10; ++n) { // We have 10 bytes delimiter_bit = bitrow_get_bit(bb[1], bit_idx++); if (delimiter_bit == 0) return 0; // Decode error for(unsigned m=0; m<8; ++m) { bitbuffer_add_bit(bitbuffer, bitrow_get_bit(bb[1], bit_idx++)); } } // Final delimiter bit will be missing - so do not check... // Decode bytes to nibbles // row_in = 2, row_out = 3 bitbuffer_add_row(bitbuffer); for(unsigned n=0; n<10; ++n) { // We have 10 bytes/nibbles int nibble = lightwave_rf_nibble_from_byte(bb[2][n]); if (nibble < 0) { if (debug_output) { fprintf(stderr, "LightwaveRF. Nibble decode error %X, idx: %u\n", bb[2][n], n); bitbuffer_print(bitbuffer); } return 0; // Decode error } for (unsigned m=0; m<4; ++m) { // Add nibble one bit at a time... bitbuffer_add_bit(bitbuffer, (nibble & (8 >> m)) >> (3-m)); } } // Print out generic decode // Decoded nibbles are in row 3 fprintf(stdout, "LightwaveRF:\n"); fprintf(stdout, "ID = 0x%X%X%X\n", bb[3][2], bb[3][3], bb[3][4]); fprintf(stdout, "Subunit = %u\n", (bb[3][1] & 0xF0) >> 4); fprintf(stdout, "Command = %u\n", bb[3][1] & 0x0F); fprintf(stdout, "Parameter = %u\n", bb[3][0]); if (debug_output) { bitbuffer_print(bitbuffer); fprintf(stderr, " Row 0 = Input, Row 1 = Zero bit stuffing, Row 2 = Stripped delimiters, Row 3 = Decoded nibbles\n"); } return 1; }