Added support for FineOffset/ECOWITT WH51 ()

* Added support for FineOffset/ECOWITT WH51
This commit is contained in:
0x4d0x44 2020-01-08 00:30:02 +01:00 committed by Benjamin Larsson
parent 3de2c414ac
commit 084e8f3033
2 changed files with 125 additions and 0 deletions

View file

@ -149,6 +149,7 @@
DECL(norgo) \
DECL(tpms_elantra2012) \
DECL(auriol_hg02832) \
DECL(fineoffset_WH51) \
/* Add new decoders here. */

View file

@ -3,6 +3,7 @@
Copyright (C) 2017 Tommy Vestermark
Enhanced (C) 2019 Christian W. Zuckschwerdt <zany@triq.net>
Added WH51 Soil Moisture Sensor (C) 2019 Marco Di Leo
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
@ -508,6 +509,108 @@ static int fineoffset_WH25_callback(r_device *decoder, bitbuffer_t *bitbuffer)
return 1;
}
/*
Fine Offset WH51, ECOWITT WH51, MISOL/1 Soil Moisture Sensor
Test decoding with: rtl_433 -f 433920000 -X "n=soil_sensor,m=FSK_PCM,s=58,l=58,t=5,r=5000,g=4000,preamble=aa2dd4"
Data format:
00 01 02 03 04 05 06 07 08 09 10 11 12 13
aa aa aa 2d d4 51 00 6b 58 6e 7f 24 f8 d2 ff ff ff 3c 28 8
FF II II II TB YY MM ZA AA XX XX XX CC SS
Sync: aa aa aa ...
Preamble: 2d d4
FF: Family code 0x51 (ECOWITT/FineOffset WH51)
IIIIII: ID (3 bytes)
T: Transmission period boost: highest 3 bits set to 111 on moisture change and decremented each transmission;
if T = 0 period is 70 sec, if T > 0 period is 10 sec
B: Battery voltage: lowest 5 bits are battery voltage * 10 (e.g. 0x0c = 12 = 1.2V). Transmitter works down to 0.7V (0x07)
YY: ? Fixed: 0x7f
MM: Moisture percentage 0%-100% (0x00-0x64) MM = (AD - 70) / (450 - 70)
Z: ? Fixed: leftmost 7 bit 1111 100
AAA: 9 bit AD value MSB byte[07] & 0x01, LSB byte[08]
XXXXXX: ? Fixed: 0xff 0xff 0xff
CC: CRC of the preceding 12 bytes (Polynomial 0x31, Initial value 0x00, Input not reflected, Result not reflected)
SS: Sum of the preceding 13 bytes % 256
See http://www.ecowitt.com/upfile/201904/WH51%20Manual.pdf for relationship between AD and moisture %
Short explanation:
Soil Moisture Percentage = (Moisture AD 0%AD) / (100%AD 0%AD) * 100
0%AD = 70
100%AD = 450 (manual states 500, but sensor internal computation are closer to 450)
If sensor-calculated moisture percentage are inaccurate at low/high values, use the AD value and the above formaula
changing 0%AD and 100%AD to cover the full scale from dry to damp
*/
static int fineoffset_WH51_callback(r_device *decoder, bitbuffer_t *bitbuffer)
{
data_t *data;
uint8_t const preamble[] = {0xAA, 0x2D, 0xD4};
uint8_t b[14];
unsigned bit_offset;
// Validate package
if (bitbuffer->bits_per_row[0] < 136) { // Minimum length 14 bytes data + 3 bytes preamble
return DECODE_ABORT_LENGTH;
}
// Find a data package and extract data payload
bit_offset = bitbuffer_search(bitbuffer, 0, 0, preamble, sizeof(preamble) * 8) + sizeof(preamble) * 8;
if (bit_offset + sizeof(b) * 8 > bitbuffer->bits_per_row[0]) { // Did not find a big enough package
if (decoder->verbose)
bitbuffer_printf(bitbuffer, "Fineoffset_WH51: short package. Header index: %u\n", bit_offset);
return DECODE_ABORT_LENGTH;
}
bitbuffer_extract_bytes(bitbuffer, 0, bit_offset, b, sizeof(b) * 8);
// Verify family code
if (b[0] != 0x51) {
if (decoder->verbose)
fprintf(stderr, "Fineoffset_WH51: Msg family unknown: %2x\n", b[0]);
return DECODE_ABORT_EARLY;
}
// Verify checksum
if ((add_bytes(b, 13) & 0xff) != b[13]) {
if (decoder->verbose)
bitrow_printf(b, sizeof (b) * 8, "Fineoffset_WH51: Checksum error: ");
return DECODE_FAIL_MIC;
}
// Verify crc
if (crc8(b, 12, 0x31, 0) != b[12]) {
if (decoder->verbose)
bitrow_printf(b, sizeof (b) * 8, "Fineoffset_WH51: Bitsum error: ");
return DECODE_FAIL_MIC;
}
// Decode data
char id[7];
sprintf( id, "%2.2x%2.2x%2.2x", b[1], b[2], b[3]);
int boost = (b[4] & 0xe0) >> 5;
float battery = (b[4] & 0x1f) * 0.1;
int ad = (((int)b[7] & 0x01) << 8) | (int)b[8];
uint8_t moisture = b[6];
/* clang-format off */
data = data_make(
"model", "", DATA_STRING, "Fineoffset-WH51",
"id", "ID", DATA_STRING, id,
"boost", "Transmission boost", DATA_FORMAT, "%u", DATA_INT, boost,
"battery", "Battery", DATA_FORMAT, "%.01f V", DATA_DOUBLE, battery,
"moisture", "Moisture", DATA_FORMAT, "%u %%", DATA_INT, moisture,
"ad", "AD", DATA_FORMAT, "%u", DATA_INT, ad,
NULL);
/* clang-format on */
decoder_output_data(decoder, data);
return 1;
}
/**
Alecto WS-1200 V1.0 decoder by Christian Zuckschwerdt, documentation by Andreas Untergasser, help by curlyel.
@ -846,6 +949,16 @@ static char *output_fields_WH25[] = {
NULL,
};
static char *output_fields_WH51[] = {
"model",
"id",
"boost",
"battery",
"moisture",
"ad",
NULL,
};
static char *output_fields_WH0530[] = {
"model",
"id",
@ -882,6 +995,17 @@ r_device fineoffset_WH25 = {
.fields = output_fields_WH25,
};
r_device fineoffset_WH51 = {
.name = "Fine Offset Electronics/ECOWITT WH51 Soil Moisture Sensor",
.modulation = FSK_PULSE_PCM,
.short_width = 58, // Bit width = 58µs (measured across 580 samples / 40 bits / 250 kHz )
.long_width = 58, // NRZ encoding (bit width = pulse width)
.reset_limit = 5000,
.decode_fn = &fineoffset_WH51_callback,
.disabled = 0,
.fields = output_fields_WH51,
};
r_device fineoffset_WH0530 = {
.name = "Fine Offset Electronics, WH0530 Temperature/Rain Sensor",
.modulation = OOK_PULSE_PWM,