mirror of
https://github.com/merbanan/rtl_433.git
synced 2026-04-22 18:46:58 -04:00
adding Oil Ultrasonic Standard protocol
This commit is contained in:
committed by
Benjamin Larsson
parent
58f2973bcb
commit
d2fd99aba1
@@ -93,6 +93,7 @@ add_executable(rtl_433
|
||||
devices/lacrosse_tx35.c
|
||||
devices/vaillant_vrt340f.c
|
||||
devices/ibis_beacon.c
|
||||
devices/oil_standard.c
|
||||
|
||||
)
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@ rtl_433_SOURCES = baseband.c \
|
||||
devices/rftech.c \
|
||||
devices/vaillant_vrt340f.c \
|
||||
devices/wg_pb12v1.c \
|
||||
devices/ibis_beacon.c
|
||||
devices/ibis_beacon.c \
|
||||
devices/oil_standard.c
|
||||
|
||||
rtl_433_LDADD = $(LIBRTLSDR) $(LIBM)
|
||||
|
||||
136
src/devices/oil_standard.c
Normal file
136
src/devices/oil_standard.c
Normal file
@@ -0,0 +1,136 @@
|
||||
/* Oil tank monitor using manchester encoded FSK protocol
|
||||
*
|
||||
* Tested devices:
|
||||
* APOLLO ULTRASONIC STANDARD (maybe also VISUAL but not SMART)
|
||||
* Should apply to similar Watchman and Beckett devices too.
|
||||
*
|
||||
* Copyright (C) 2017 Christian W. Zuckschwerdt <zany@triq.net>
|
||||
* based on code Copyright (C) 2015 David Woodhouse
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
#include "rtl_433.h"
|
||||
#include "util.h"
|
||||
|
||||
// The sensor sends a single packet once every hour or twice a second
|
||||
// for 11 minutes when in pairing/test mode (pairing needs 35 sec).
|
||||
// depth reading is in cm, lowest reading is ~3, highest is ~305, 0 is invalid
|
||||
//
|
||||
// IIII IIII IIII IIII 0FFF L0OP DDDD DDDD
|
||||
//
|
||||
// example packets are:
|
||||
// 010101 01010101 01010111 01101001 10011010 10101001 10100101 10011010 01101010 10011001 10011010 0000
|
||||
// 010101 01010101 01011000 10011010 01010110 01101010 10101010 10100101 01101010 10100110 10101001 1111
|
||||
|
||||
// Start of frame full preamble is depending on first data bit either
|
||||
// 01 0101 0101 0101 0101 0111 01
|
||||
// 01 0101 0101 0101 0101 1000 10
|
||||
static const unsigned char preamble_pattern0[2] = { 0x55, 0x5D };
|
||||
static const unsigned char preamble_pattern1[2] = { 0x55, 0x62 };
|
||||
|
||||
// End of frame is the last half-bit repeated additional 4 times
|
||||
|
||||
static int oil_standard_decode(bitbuffer_t *bitbuffer, unsigned row, unsigned bitpos) {
|
||||
char time_str[LOCAL_TIME_BUFLEN];
|
||||
data_t *data;
|
||||
uint8_t *b;
|
||||
uint16_t unit_id;
|
||||
uint16_t depth = 0;
|
||||
uint16_t binding_countdown = 0;
|
||||
uint8_t flags;
|
||||
uint8_t alarm;
|
||||
bitbuffer_t databits = {0};
|
||||
|
||||
local_time_str(0, time_str);
|
||||
|
||||
bitpos = bitbuffer_manchester_decode(bitbuffer, row, bitpos, &databits, 33);
|
||||
|
||||
if (databits.bits_per_row[0] != 32)
|
||||
return 0;
|
||||
|
||||
b = databits.bb[0];
|
||||
|
||||
// The unit ID changes when you rebind by holding a magnet to the
|
||||
// sensor for long enough.
|
||||
unit_id = (b[0] << 8) | b[1];
|
||||
|
||||
// 0x01: Rebinding (magnet held to sensor)
|
||||
// 0x02: High-bit for depth
|
||||
// 0x04: (always zero?)
|
||||
// 0x08: Leak/theft alarm
|
||||
// 0x10: (unkown toggle)
|
||||
// 0x40: (unkown toggle)
|
||||
// 0x10: (unkown toggle)
|
||||
// 0x80: (always zero?)
|
||||
flags = b[2] & ~0x0A;
|
||||
alarm = (b[2] & 0x08) >> 3;
|
||||
|
||||
if (flags & 1)
|
||||
// When binding, the countdown counts up from 0x40 to 0x4a
|
||||
// (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[3];
|
||||
else
|
||||
// A depth reading of zero indicates no reading.
|
||||
depth = ((b[2] & 0x02) << 7) | b[3];
|
||||
|
||||
data = data_make(
|
||||
"time", "", DATA_STRING, time_str,
|
||||
"model", "", DATA_STRING, "Oil Ultrasonic STANDARD",
|
||||
"id", "", DATA_FORMAT, "%04x", DATA_INT, unit_id,
|
||||
"flags", "", DATA_FORMAT, "%02x", DATA_INT, flags,
|
||||
"alarm", "", DATA_INT, alarm,
|
||||
"binding_countdown", "", DATA_INT, binding_countdown,
|
||||
"depth_cm", "", DATA_INT, depth,
|
||||
NULL);
|
||||
data_acquired_handler(data);
|
||||
|
||||
return 1;
|
||||
};
|
||||
|
||||
static int oil_standard_callback(bitbuffer_t *bitbuffer) {
|
||||
unsigned bitpos = 0;
|
||||
int events = 0;
|
||||
|
||||
// Find a preamble with enough bits after it that it could be a complete packet
|
||||
while ((bitpos = bitbuffer_search(bitbuffer, 0, bitpos, (uint8_t *)&preamble_pattern0, 16)) + 78 <=
|
||||
bitbuffer->bits_per_row[0]) {
|
||||
events += oil_standard_decode(bitbuffer, 0, bitpos + 14);
|
||||
bitpos += 2;
|
||||
}
|
||||
|
||||
bitpos = 0;
|
||||
while ((bitpos = bitbuffer_search(bitbuffer, 0, bitpos, (uint8_t *)&preamble_pattern1, 16)) + 78 <=
|
||||
bitbuffer->bits_per_row[0]) {
|
||||
events += oil_standard_decode(bitbuffer, 0, bitpos + 14);
|
||||
bitpos += 2;
|
||||
}
|
||||
return events;
|
||||
}
|
||||
|
||||
static char *output_fields[] = {
|
||||
"time",
|
||||
"model",
|
||||
"id",
|
||||
"flags",
|
||||
"alarm",
|
||||
"binding_countdown",
|
||||
"depth_cm",
|
||||
NULL
|
||||
};
|
||||
|
||||
r_device oil_standard = {
|
||||
.name = "Oil Ultrasonic STANDARD",
|
||||
.modulation = FSK_PULSE_PCM,
|
||||
.short_limit = 500,
|
||||
.long_limit = 500,
|
||||
.reset_limit = 2000,
|
||||
.json_callback = &oil_standard_callback,
|
||||
.disabled = 0,
|
||||
.fields = output_fields,
|
||||
};
|
||||
Reference in New Issue
Block a user