Add support for WS2032 weather station ()

This commit is contained in:
Christian W. Zuckschwerdt 2020-01-11 19:15:11 +01:00 committed by GitHub
parent cbe18f7b44
commit 2736df3762
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 137 additions and 0 deletions

View file

@ -220,6 +220,7 @@ Read the Test Data section at the bottom.
[142] Fine Offset Electronics/ECOWITT WH51 Soil Moisture Sensor
[143] Holman Industries iWeather WS5029 weather station (older PWM)
[144] TBH weather sensor
[145] WS2032 weather station
* Disabled by default, use -R n or -G

View file

@ -331,6 +331,7 @@ stop_after_successful_events false
protocol 142 # Fine Offset Electronics/ECOWITT WH51 Soil Moisture Sensor
protocol 143 # Holman Industries iWeather WS5029 weather station (older PWM)
protocol 144 # TBH weather sensor
protocol 145 # WS2032 weather station
## Flex devices (command line option "-X")

View file

@ -152,6 +152,7 @@
DECL(fineoffset_WH51) \
DECL(holman_ws5029pwm) \
DECL(archos_tbh) \
DECL(ws2032) \
/* Add new decoders here. */

View file

@ -559,6 +559,9 @@ Holman Industries iWeather WS5029 weather station (older PWM)
.TP
[ \fB144\fI\fP ]
TBH weather sensor
.TP
[ \fB145\fI\fP ]
WS2032 weather station
* Disabled by default, use \-R n or \-G
.SS "Input device selection"

View file

@ -144,6 +144,7 @@ add_executable(rtl_433
devices/vaillant_vrt340f.c
devices/waveman.c
devices/wg_pb12v1.c
devices/ws2032.c
devices/wssensor.c
devices/wt0124.c
devices/wt450.c

View file

@ -145,6 +145,7 @@ rtl_433_SOURCES = abuf.c \
devices/vaillant_vrt340f.c \
devices/waveman.c \
devices/wg_pb12v1.c \
devices/ws2032.c \
devices/wssensor.c \
devices/wt0124.c \
devices/wt450.c \

125
src/devices/ws2032.c Normal file
View file

@ -0,0 +1,125 @@
/** @file
WS2032 weather station.
Copyright (C) 2019 Christian W. Zuckschwerdt <zany@triq.net>
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.
*/
/**
WS2032 weather station.
- Outdoor temperature range: -40F to 140F (-40C to 60C)
- Temperature accuracy: +- 1.0 C
- Humidity range: 20% to 90%
- Humidity accuracy: +-5%
- Wind direction: E,S,W,N,SE,NE,SW,NW
- Wind direction accuracy: +- 10 deg
- Wind speed: 0 to 50m/s, Accuracy: 0.1 m/s
Data format:
1x PRE:8h ID:16h ?8h DIR:4h TEMP:12d HUM:8d AVG?8d GUST?8d 24h SUM8h CHK8h TRAIL:3b
OOK with PWM. Long = 1000 us, short = 532 us, gap = 484 us.
The overlong and very short pulses are sync, see the Pulseview.
Temp, not 2's complement but a dedicated sign-bit, i.e. 1 bit sign, 11 bit temp.
*/
#include "decoder.h"
static int fineoffset_ws2032_decode(r_device *decoder, bitbuffer_t *bitbuffer)
{
uint8_t const preamble[] = {0x0a}; // 8 bits, 0xf5 inverted
data_t *data;
uint8_t b[14];
// find a proper row
int row = bitbuffer_find_repeated_row(bitbuffer, 2, 14 * 8); // expected: 3 rows of 113 bits
if (row < 0) {
return DECODE_ABORT_EARLY;
}
unsigned offset = bitbuffer_search(bitbuffer, row, 0, preamble, 8);
if (offset + 14 * 8 > bitbuffer->bits_per_row[row]) {
return DECODE_ABORT_LENGTH;
}
// invert and align the row
bitbuffer_invert(bitbuffer);
bitbuffer_extract_bytes(bitbuffer, row, offset, b, 14 * 8);
// verify the checksums
int sum = add_bytes(b, 12);
if (sum == 0) {
return DECODE_FAIL_SANITY; // discard all zeros
}
if ((sum & 0xff) != b[12]) {
return DECODE_FAIL_MIC; // sum mismatch
}
if (crc8(b, 14, 0x31, 0x00)) {
return DECODE_FAIL_MIC; // crc mismatch
}
// get weather sensor data
// 1x PRE:8h ID:16h ?8h DIR:4h TEMP:12d HUM:8d AVG?8d GUST?8d 24h SUM8h CHK8h TRAIL:3b
int device_id = (b[1] << 8) | (b[2]);
int flags = (b[3]);
//int battery_low = b[3] & 0x80;
float dir = (b[4] >> 4) * 22.5f;
int temp_sign = (b[4] & 0x08) ? -1 : 1;
int temp_raw = ((b[4] & 0x07) << 8) | b[5];
float temperature = temp_sign * temp_raw * 0.1;
int humidity = b[6];
float speed = (b[7] * 0.43f) * 3.6f; // m/s -> km/h
float gust = (b[8] * 0.43f) * 3.6f; // m/s -> km/h
int rain_raw = (b[9] << 16) | (b[10] << 8) | b[11]; // maybe?
/* clang-format off */
data = data_make(
"model", "", DATA_STRING, "WS2032",
"id", "StationID", DATA_FORMAT, "%04X", DATA_INT, device_id,
//"battery_ok", "Battery", DATA_INT, !battery_low,
"temperature_C", "Temperature", DATA_FORMAT, "%.01f C", DATA_DOUBLE, temperature,
"humidity", "Humidity", DATA_FORMAT, "%u %%", DATA_INT, humidity,
"direction_deg", "Wind direction", DATA_FORMAT, "%.01f", DATA_DOUBLE, dir,
"wind_avg_km_h", "Wind avg speed", DATA_FORMAT, "%.01f", DATA_DOUBLE, speed,
"wind_max_km_h", "Wind gust", DATA_FORMAT, "%.01f", DATA_DOUBLE, gust,
"maybe_flags", "Flags?", DATA_FORMAT, "%02x", DATA_INT, flags,
"maybe_rain", "Rain?", DATA_FORMAT, "%06x", DATA_INT, rain_raw,
"mic", "Integrity", DATA_STRING, "CRC",
NULL);
/* clang-format on */
decoder_output_data(decoder, data);
return 1;
}
static char *output_fields[] = {
"model",
"id",
"battery",
"temperature_C",
"humidity",
"direction_deg",
"wind_avg_km_h",
"wind_max_km_h",
NULL,
};
r_device ws2032 = {
.name = "WS2032 weather station",
.modulation = OOK_PULSE_PWM,
.short_width = 500,
.long_width = 1000,
.gap_limit = 750,
.reset_limit = 4000,
.decode_fn = &fineoffset_ws2032_decode,
.disabled = 0,
.fields = output_fields,
};

View file

@ -260,6 +260,7 @@
<ClCompile Include="..\src\devices\vaillant_vrt340f.c" />
<ClCompile Include="..\src\devices\waveman.c" />
<ClCompile Include="..\src\devices\wg_pb12v1.c" />
<ClCompile Include="..\src\devices\ws2032.c" />
<ClCompile Include="..\src\devices\wssensor.c" />
<ClCompile Include="..\src\devices\wt0124.c" />
<ClCompile Include="..\src\devices\wt450.c" />

View file

@ -541,6 +541,9 @@
<ClCompile Include="..\src\devices\wg_pb12v1.c">
<Filter>Source Files\devices</Filter>
</ClCompile>
<ClCompile Include="..\src\devices\ws2032.c">
<Filter>Source Files\devices</Filter>
</ClCompile>
<ClCompile Include="..\src\devices\wssensor.c">
<Filter>Source Files\devices</Filter>
</ClCompile>