Add support for Tekelek oil gauge ()

This commit is contained in:
Christian W. Zuckschwerdt 2023-10-29 22:57:23 +01:00
parent e202e85efa
commit 27482e3be6
3 changed files with 21 additions and 14 deletions

View file

@ -319,7 +319,7 @@ See [CONTRIBUTING.md](./docs/CONTRIBUTING.md).
[231] Govee Water Leak Detector H5054
[232] TFA Dostmann 14.1504.V2 Radio-controlled grill and meat thermometer
[233]* CED7000 Shot Timer
[234] Watchman Sonic Advanced / Plus
[234] Watchman Sonic Advanced / Plus, Tekelek
[235] Oil Ultrasonic SMART FSK
[236] Gasmate BA1008 meat thermometer
[237] Flowis flow meters

View file

@ -460,7 +460,7 @@ convert si
protocol 231 # Govee Water Leak Detector H5054
protocol 232 # TFA Dostmann 14.1504.V2 Radio-controlled grill and meat thermometer
# protocol 233 # CED7000 Shot Timer
protocol 234 # Watchman Sonic Advanced / Plus
protocol 234 # Watchman Sonic Advanced / Plus, Tekelek
protocol 235 # Oil Ultrasonic SMART FSK
protocol 236 # Gasmate BA1008 meat thermometer
protocol 237 # Flowis flow meters

View file

@ -15,7 +15,8 @@
Watchman Sonic Advanced/Plus oil tank level monitor.
Tested devices:
- Watchman Sonic Advanced
- Watchman Sonic Advanced, model code 0x0401 (seen on two devices)
- Tekelek, model code 0x0106 (seen on two devices)
The devices uses GFSK with 500 us long and short pulses.
Using -Y minmax should be sufficient to get it to work.
@ -23,35 +24,34 @@ Using -Y minmax should be sufficient to get it to work.
Total length of message including preamble is 192 bits.
The format might be most easily summarised in a BitBench string:
PRE: 40b SYNC: 16h MODEL: 24h ID: 24d 8h TEMP: 8h 16h DEPTH: 8d 32h CRC: 16h
PRE: 40b SYNC: 16h LEN:8d MODEL:16h ID:24d 8h TEMP:8h ?:16h DEPTH:8d VER:32h CRC:16h
Data Layout:
- 40 bits of preamble, i.e. 10101010 etc.
- 0x2dd4 - 'standard' sync word
- 2 byte of 0x2dd4 - 'standard' sync word
- 1 byte - message length, fixed 0x0e (14)
- 2 byte - fixed 0x0401 - presumably a model identifier, common at least to the two devices we have tested this on
- 0x0e0401 - presumably a model identifier, common at least to the two devices we have tested this on
- 2 byte - fixed 0x0401 or 0x0106 - presumably a model identifier, common at least to the devices we have tested
- 3 byte integer serial number - as printed on a label attached to the device itself
- 1 byte status:
- 0xC0 - during the first 20ish minutes after sync with the receiver when the device is transmitting once per second
- 0x80 - the first one or two transmissions after the sync period when the device seems to be calibrating itself
- 0x98 - normal, live value that you'll see on every transmission when the device is up and running
- 1 byte temperature, in intervals of 0.5 degrees, offset by 0x48
- two more varying bytes which could be the raw sensor reading
- 2 byte - varying bytes which could be the raw sensor reading
- 1 byte integer depth (i.e. the distance between the sensor and the oil in the tank)
- 0x01050300 - 4 bytes of constant values which could be a version number? (1.5.3.0)
- 4 byte of 0x01050300 - constant values which could be a version number? (1.5.3.0)
- 2 byte CRC-16 poly 0x8005 init 0
*/
static int oil_watchman_advanced_decode(r_device *decoder, bitbuffer_t *bitbuffer)
{
static uint8_t const PREAMBLE_SYNC_LENGTH_BITS = 40;
static uint8_t const HEADER_LENGTH_BITS = 24;
static uint8_t const BODY_LENGTH_BITS = 128;
static uint8_t const HEADER_LENGTH_BITS = 8;
static uint8_t const BODY_LENGTH_BITS = 144;
// no need to match all the preamble; 24 bits worth should do
// include part of preamble, sync-word, length, message identifier
uint8_t const preamble_pattern[] = {0xaa, 0xaa, 0xaa, 0x2d, 0xd4, 0x0e, 0x04, 0x01};
uint8_t const preamble_pattern[] = {0xaa, 0xaa, 0xaa, 0x2d, 0xd4, 0x0e};
unsigned bitpos = 0;
int events = 0;
@ -67,13 +67,20 @@ static int oil_watchman_advanced_decode(r_device *decoder, bitbuffer_t *bitbuffe
uint8_t *b = msg;
if (crc16(b, (BODY_LENGTH_BITS + HEADER_LENGTH_BITS) / 8, 0x8005, 0) != 0) {
decoder_log(decoder, 2, __func__, "failed CRC check");
return DECODE_FAIL_MIC;
}
int mcode = (b[1] << 8) | b[2];
if (mcode != 0x0401 && mcode != 0x0106) {
decoder_logf(decoder, 1, __func__, "Unknown model code %04x", mcode);
return DECODE_FAIL_SANITY;
}
// as printed on the side of the unit
uint32_t serial = (b[3] << 16) | (b[4] << 8) | b[5];
uint8_t status = b[6];
float temperature = (float)(int8_t)(0.5 * (b[7] - 0x48)); // truncate to whole number
float temperature = (b[7] - 0x48) / 2; // truncate to whole number
uint8_t depth = b[10];
/* clang-format off */
@ -103,7 +110,7 @@ static char const *const output_fields[] = {
};
r_device const oil_watchman_advanced = {
.name = "Watchman Sonic Advanced / Plus",
.name = "Watchman Sonic Advanced / Plus, Tekelek",
.modulation = FSK_PULSE_PCM,
.short_width = 500,
.long_width = 500,