Exemplo n.º 1
0
static int oil_watchman_callback(bitbuffer_t *bitbuffer) {
	uint8_t *b;
	uint32_t unit_id;
	uint16_t depth = 0;
	uint16_t binding_countdown = 0;
	uint8_t flags;
	uint8_t maybetemp;
	double temperature;
	char time_str[LOCAL_TIME_BUFLEN];
	data_t *data;
	unsigned bitpos = 0;
	bitbuffer_t databits = {0};
	int events = 0;

	local_time_str(0, time_str);

	// Find a preamble with enough bits after it that it could be a complete packet
	while ((bitpos = bitbuffer_search(bitbuffer, 0, bitpos, &preamble_pattern, 6)) + 136 <=
	       bitbuffer->bits_per_row[0]) {

		// Skip the matched preamble bits to point to the data
		bitpos += 6;

		bitpos = bitbuffer_manchester_decode(bitbuffer, 0, bitpos, &databits, 64);
		if (databits.bits_per_row[0] != 64)
			continue;

		b = databits.bb[0];

		// Check for postamble, depending on last data bit
		if (bitbuffer_search(bitbuffer, 0, bitpos, &postamble_pattern[b[7] & 1], 2) != bitpos)
			continue;

		if (b[7] != crc8le(b, 7, 0x31, 0))
			continue;

		// The unit ID changes when you rebind by holding a magnet to the
		// sensor for long enough; it seems to be time-based.
		unit_id = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];

		// 0x01: Rebinding (magnet held to sensor)
		// 0x08: Leak/theft alarm
		// top three bits seem also to vary with temperature (independently of maybetemp)
		flags = b[4];

		// Not entirely sure what this is but it might be inversely
		// proportional to temperature.
		maybetemp = b[5] >> 2;
		temperature = (double)(145.0 - 5.0 * maybetemp) / 3.0;
		if (flags & 1)
			// When binding, the countdown counts up from 0x51 to 0x5a
			// (as long as you hold the magnet to it for long enough)
			// before the device ID changes. The receiver unit needs
			// to receive this *strongly* in order to change its
			// allegiance.
			binding_countdown = b[6];
		else
			// A depth reading of zero indicates no reading. Even with
			// the sensor flat down on a table, it still reads about 13.
			depth = ((b[5] & 3) << 8) | b[6];

		data = data_make("time", "", DATA_STRING, time_str,
			"model", "", DATA_STRING, "Oil Watchman",
			"id", "", DATA_FORMAT, "%06x", DATA_INT, unit_id,
			"flags", "", DATA_FORMAT, "%02x", DATA_INT, flags,
			"maybetemp", "", DATA_INT, maybetemp,
			"temperature_C", "", DATA_DOUBLE, temperature,
			"binding_countdown", "", DATA_INT, binding_countdown,
			"depth", "", DATA_INT, depth,
			NULL);
		data_acquired_handler(data);
		events++;
	}
	return events;
}
Exemplo n.º 2
0
static int acurite_986_callback(bitbuffer_t *bitbuf) {
    int browlen;
    uint8_t *bb, sensor_num, status, crc, crcc;
    uint8_t br[8];
    int8_t tempf; // Raw Temp is 8 bit signed Fahrenheit
    float tempc;
    uint16_t sensor_id, valid_cnt = 0;
    char sensor_type;

    local_time_str(0, 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;
	}

	// 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)) {
	    continue;
	}

	// There will be 1 extra false zero bit added by the demod.
	// this forces an extra zero byte to be added
	if (browlen > 5 && bb[browlen - 1] == 0)
	    browlen--;

	// 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",br[i]);
	    fprintf(stderr,"\n");
	}

	tempf = br[0];
	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
	    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 & 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);
	}

	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",
	       time_str, sensor_id, sensor_num, sensor_type,
	       tempc, tempf);

	valid_cnt++;

    }

    if (valid_cnt)
	return 1;

    return 0;
}