Cleanup LaCrosse LTV-WSDTH01 BreezePro

This commit is contained in:
Christian W. Zuckschwerdt 2020-09-05 18:52:01 +02:00
parent 15c6d6e0a2
commit 9c1945885e
9 changed files with 68 additions and 59 deletions

View file

@ -239,6 +239,7 @@ See [CONTRIBUTING.md](./docs/CONTRIBUTING.md).
[163] Acurite 590TX Temperature with optional Humidity
[164] Security+ 2.0 (Keyfob)
[165] TFA Dostmann 30.3221.02 T/H Outdoor Sensor
[166] LaCrosse Technology View LTV-WSDTH01 Breeze Pro Wind Sensor
* Disabled by default, use -R n or -G

View file

@ -347,6 +347,7 @@ stop_after_successful_events false
protocol 163 # Acurite 590TX Temperature with optional Humidity
protocol 164 # Security+ 2.0 (Keyfob)
protocol 165 # TFA Dostmann 30.3221.02 T/H Outdoor Sensor
protocol 166 # LaCrosse Technology View LTV-WSDTH01 Breeze Pro Wind Sensor
## Flex devices (command line option "-X")

View file

@ -173,6 +173,7 @@
DECL(acurite_590tx) \
DECL(secplus_v2) \
DECL(tfa_30_3221) \
DECL(lacrosse_breezepro) \
/* Add new decoders here. */
#define DECL(name) extern r_device name;

View file

@ -616,6 +616,9 @@ Security+ 2.0 (Keyfob)
.TP
[ \fB165\fI\fP ]
TFA Dostmann 30.3221.02 T/H Outdoor Sensor
.TP
[ \fB166\fI\fP ]
LaCrosse Technology View LTV\-WSDTH01 Breeze Pro Wind Sensor
* Disabled by default, use \-R n or \-G
.SS "Input device selection"

View file

@ -100,6 +100,7 @@ add_library(r_433 STATIC
devices/kerui.c
devices/klimalogg.c
devices/lacrosse.c
devices/lacrosse_breezepro.c
devices/lacrosse_tx141x.c
devices/lacrosse_tx35.c
devices/lacrosse_ws7000.c

View file

@ -99,6 +99,7 @@ rtl_433_SOURCES = abuf.c \
devices/kerui.c \
devices/klimalogg.c \
devices/lacrosse.c \
devices/lacrosse_breezepro.c \
devices/lacrosse_tx141x.c \
devices/lacrosse_tx35.c \
devices/lacrosse_ws7000.c \

View file

@ -1,5 +1,5 @@
/** @file
LaCrosse Breeze Pro LTV-WSDTH01 sensor.
LaCrosse Technology View LTV-WSDTH01 Breeze Pro Wind Sensor.
Copyright (C) 2020 Mike Bruski (AJ9X) <michael.bruski@gmail.com>
@ -9,7 +9,7 @@
(at your option) any later version.
*/
/**
LaCrosse Breeze Pro LTV-WSDTH01 sensor.
LaCrosse Technology View LTV-WSDTH01 Breeze Pro Wind Sensor.
LaCrosse Color Forecast Station (model 79400) utilizes the remote temp/
humidity/wind speed/wind direction sensor LTV-WSDTH01.
@ -18,6 +18,13 @@ Product pages:
https://www.lacrossetechnology.com/products/79400
https://www.lacrossetechnology.com/products/ltv-wsdth01
Specifications:
- Wind Speed Range: 0 to 178 kmh
- Degrees of Direction: 360 deg with 16 Cardinal Directions
- Outdoor Temperature Range: -29 C to 60 C
- Outdoor Humidity Range: 10 to 99 %RH
- Update Interval: Every 31 Seconds
Internal inspection of the remote sensor reveals that the device
utilizes a HopeRF CMT2119A ISM transmitter chip which is capable of
transmitting up to 32 bytes of data on any ISM frequency using OOK
@ -37,76 +44,75 @@ CMT2219A.
(http://www.cmostek.com/download/CMT2219A.pdf)
(http://www.cmostek.com/download/AN138%20CMT2219A%20Configuration%20Guideline.pdf)
Protocol Specification:
Data bits are NRZ encoded with logical 1 and 0 bits 106.842us in length.
SYN:32h ID:24h ?:4 SEQ:3b ?:1b TEMP:12d HUM:12d WSPD:12d WDIR:12d CHK:8h END:32h
SYN:32h ID:24h ?:4b SEQ:3d ?:1b TEMP:12d HUM:12d WSPD:12d WDIR:12d CHK:8h END:32h
Packet length is 264 bits according to inspectrum broken down as follows:
preamble: 7 bytes (when aligned with sync word these are 0xaa)
sync word: 4 bytes (0xd2aa2dd4)
device ID: 3 bytes (matches bar code underside of unit covering pgm port)
x1: 4 bit (unknown, bit 0?00 might be 'battery low')
sequence: 3 bits (0-7, one up per packet, then repeats)
x2: 1 bit (unknown)
celsius: 12 bits (base 400, scale 10, range: -29°C to 60°C)
humidity: 12 bits (10 to 99% relative humidity)
wind speed: 12 bits (0.0 to 178.0 kMh)
wind direction: 12 bits (0 to 359°)
checksum: 8 bits (CRC-8 poly 0x31 init 0x00 over 10 bytes after sync)
end: 32 bytes (0xd2d2d200)
- warm-up: 7 bytes (0x55, aligned with sync word these are 0xaa)
- preamble/sync 4 bytes 0xd2aa2dd4 (see as 0x695516ea05)
- device id: 3 bytes (matches bar code underside of unit covering pgm port)
- x1: 4 bit (unknown, bit 0?00 might be 'battery low')
- sequence: 3 bits (0-7, one up per packet, then repeats)
- x2: 1 bit (unknown)
- celsius: 12 bits (offset 400, scale 10, range: -29 C to 60 C)
- humidity: 12 bits (10 to 99% relative humidity)
- wind speed: 12 bits (0.0 to 178.0 kMh)
- wind direction: 12 bits (0 to 359 deg)
- checksum: 8 bits (CRC-8 poly 0x31 init 0x00 over 10 bytes after sync)
- trailer: 32 bytes (0xd2d2d200)
The sensor generates a packet every 'n' seconds but only transmits if one or
more of the following conditions are satified:
temp changes +/- 0.8 degrees C
humidity changes +/- 1%
wind speed changes +/- 0.5 kM/h
- temp changes +/- 0.8 degrees C
- humidity changes +/- 1%
- wind speed changes +/- 0.5 kM/h
Thus, if there is a gap in sequencing, it is due to bad packet[s] (too short,
failed CRC) or packet[s] that didn't satisfy at least one of these three
conditions. 'n' above varies with temperature. At 0C and above, 'n' is 31.
Between -17C and 0C, 'n' is 60. Below -17C, 'n' is 360.
Between -17C and 0C, 'n' is 60. Below -17C, 'n' is 360.
*/
#include "decoder.h"
static const uint8_t sync_word[] = { 0xd2, 0xaa, 0x2d, 0xd4 };
static int lacrosse_breezepro_decode(r_device *decoder, bitbuffer_t *bitbuffer)
{
uint8_t const preamble_pattern[] = { 0xd2, 0xaa, 0x2d, 0xd4 };
data_t *data;
uint8_t p[32], l, *c, x1, x2, seq, offset, chk;
uint8_t b[11];
uint32_t id;
uint16_t raw_temp, humidity, raw_speed, direction;
int flags, seq, offset, chk;
int raw_temp, humidity, raw_speed, direction;
float temp_c, speed_kmh;
if (bitbuffer->bits_per_row[0] < 264) {
if (decoder->verbose) {
fprintf(stderr, "%s: Wrong packet length: %d\n", __func__, bitbuffer->bits_per_row[0]);
}
}
return DECODE_ABORT_LENGTH;
}
offset = bitbuffer_search(bitbuffer, 0, 0,
sync_word, sizeof(sync_word) * 8);
preamble_pattern, sizeof(preamble_pattern) * 8);
if (offset == bitbuffer->bits_per_row[0]) {
if (offset >= bitbuffer->bits_per_row[0]) {
if (decoder->verbose) {
fprintf(stderr, "%s: Sync word not found\n", __func__);
}
return DECODE_FAIL_SANITY;
}
return DECODE_ABORT_EARLY;
}
offset += sizeof(preamble_pattern) * 8;
bitbuffer_extract_bytes(bitbuffer, 0, offset, b, 11 * 8);
c = bitbuffer->bb[offset];
chk = crc8(c, 10, 0x31, 0x00);
chk = crc8(b, 11, 0x31, 0x00);
if (chk) {
if (decoder->verbose) {
fprintf(stderr, "%s: CRC failed!\n", __func__);
@ -118,35 +124,29 @@ static int lacrosse_breezepro_decode(r_device *decoder, bitbuffer_t *bitbuffer)
bitbuffer_print(bitbuffer);
}
l = bitbuffer->bits_per_row[0] - offset;
offset += sizeof(sync_word) * 8;
bitbuffer_extract_bytes(bitbuffer, 0, offset, p, l);
id = (b[0] << 16) | (b[1] << 8) | b[2];
flags = (b[3] & 0xf1); // masks off seq bits
seq = (b[3] & 0x0e) >> 1;
raw_temp = b[4] << 4 | ((b[5] & 0xf0) >> 4);
humidity = ((b[5] & 0x0f) << 8) | b[6];
raw_speed = b[7] << 4 | ((b[8] & 0xf0) >> 4);
direction = ((b[8] & 0x0f) << 8) | b[9];
id = (p[0] << 16) | (p[1] << 8) | p[2];
x1 = (p[3] & 0xf0) >> 4;
seq = (p[3] & 0x0e) >> 1;
x2 = p[3] & 0x01;
raw_temp = p[4] << 4 | ((p[5] & 0xf0) >> 4);
humidity = ((p[5] & 0x0f) << 8) | p[6];
raw_speed = p[7] << 4 | ((p[8] & 0xf0) >> 4);
direction = ((p[8] & 0x0f) << 8) | p[9];
/* base and/or scale adjustments */
temp_c = (float)raw_temp * 0.1 - 40.0;
speed_kmh = (float)raw_speed * 0.1;
// base and/or scale adjustments
temp_c = (raw_temp - 400) * 0.1f;
speed_kmh = raw_speed * 0.1f;
/* clang-format off */
data = data_make(
"model", "", DATA_STRING, "LaCrosse-LTV-WSDTH01",
"model", "", DATA_STRING, "LaCrosse-BreezePro",
"id", "Sensor ID", DATA_FORMAT, "%06x", DATA_INT, id,
"x1", "unknown", DATA_INT, x1,
"seq", "Sequence", DATA_FORMAT, "%01x", DATA_INT, seq,
"x2", "unknown", DATA_INT, x2,
"flags", "unknown", DATA_INT, flags,
"temperature_C", "Temperature", DATA_FORMAT, "%.1f C", DATA_DOUBLE, temp_c,
"humidity", "Humidity", DATA_FORMAT, "%u %%", DATA_INT, humidity,
"wind_avg_km_h", "Wind speed", DATA_FORMAT, "%.1f km/h", DATA_DOUBLE, speed_kmh,
"wind_dir_deg", "Wind direction", DATA_INT, direction,
"mic", "Integrity", DATA_STRING, "CRC8",
"mic", "Integrity", DATA_STRING, "CRC",
NULL);
/* clang-format on */
@ -157,26 +157,23 @@ static int lacrosse_breezepro_decode(r_device *decoder, bitbuffer_t *bitbuffer)
static char *output_fields[] = {
"model",
"id",
"x1",
"seq",
"x2",
"seq",
"flags",
"temperature_C",
"humidity",
"wind_avg_km_h",
"wind_dir_deg",
"test",
"mic",
NULL,
};
// flex decoder m=FSK_PCM, s=107, l=107, r=5900
r_device lacrosse_breezepro = {
.name = "LaCrosse LTV-WSDTH01 sensor",
.name = "LaCrosse Technology View LTV-WSDTH01 Breeze Pro Wind Sensor",
.modulation = FSK_PULSE_PCM,
.short_width = 107,
.long_width = 107,
.reset_limit = 5900,
.decode_fn = &lacrosse_breezepro_decode,
.disabled = 0,
.fields = output_fields,
};

View file

@ -223,6 +223,7 @@ COPY ..\..\libusb\MS64\dll\libusb*.dll $(TargetDir)</Command>
<ClCompile Include="..\src\devices\kerui.c" />
<ClCompile Include="..\src\devices\klimalogg.c" />
<ClCompile Include="..\src\devices\lacrosse.c" />
<ClCompile Include="..\src\devices\lacrosse_breezepro.c" />
<ClCompile Include="..\src\devices\lacrosse_tx141x.c" />
<ClCompile Include="..\src\devices\lacrosse_tx35.c" />
<ClCompile Include="..\src\devices\lacrosse_ws7000.c" />

View file

@ -406,6 +406,9 @@
<ClCompile Include="..\src\devices\lacrosse.c">
<Filter>Source Files\devices</Filter>
</ClCompile>
<ClCompile Include="..\src\devices\lacrosse_breezepro.c">
<Filter>Source Files\devices</Filter>
</ClCompile>
<ClCompile Include="..\src\devices\lacrosse_tx141x.c">
<Filter>Source Files\devices</Filter>
</ClCompile>