Cleanup LaCrosse LTV-WSDTH01 BreezePro
This commit is contained in:
parent
15c6d6e0a2
commit
9c1945885e
9 changed files with 68 additions and 59 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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" />
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Add table
Reference in a new issue