Add support for Ecowitt temperature sensor

This commit is contained in:
Mark Hansen 2019-05-25 14:05:34 +10:00 committed by Benjamin Larsson
parent 2dc9eb216e
commit f199d35d8e
8 changed files with 133 additions and 3 deletions

View file

@ -312,6 +312,7 @@ stop_after_successful_events false
protocol 124 # LaCrosse/ELV/Conrad WS7000/WS2500 weather sensors
protocol 125 # TS-FT002 Wireless Ultrasonic Tank Liquid Level Meter With Temperature Sensor
protocol 126 # Companion WTR001 Temperature Sensor
protocol 127 # Ecowitt Wireless Outdoor Thermometer WH53/WH0280/WH0281A
## Flex devices (command line option "-X")

View file

@ -21,13 +21,16 @@ enum modulation_types {
FSK_PULSE_MANCHESTER_ZEROBIT = 18, ///< FSK, Manchester encoding.
};
/** Decoders should return n>=0 for n packets successfully decoded,
/** Decoders should return n>0 for n packets successfully decoded,
an ABORT code if the bitbuffer is no applicable,
or a FAIL code if the message is malformed. */
enum decode_return_codes {
DECODE_SUCCESS = 1,
DECODE_FAIL_OTHER = 0, ///< legacy, do not use
/** Bitbuffer row count or row length is wrong for this sensor. */
DECODE_ABORT_LENGTH = -1,
DECODE_ABORT_EARLY = -2,
/** Message Integrity Check failed: e.g. checksum/CRC doesn't validate. */
DECODE_FAIL_MIC = -3,
DECODE_FAIL_SANITY = -4,
};

View file

@ -134,6 +134,7 @@
DECL(lacrosse_ws7000) \
DECL(ts_ft002) \
DECL(companion_wtr001) \
DECL(ecowitt) \
/* Add new decoders here. */
#define DECL(name) extern r_device name;

View file

@ -45,6 +45,7 @@ add_executable(rtl_433
devices/digitech_xc0324.c
devices/dish_remote_6_3.c
devices/dsc.c
devices/ecowitt.c
devices/efergy_e2_classic.c
devices/efergy_optical.c
devices/elro_db286a.c

View file

@ -46,6 +46,7 @@ rtl_433_SOURCES = abuf.c \
devices/digitech_xc0324.c \
devices/dish_remote_6_3.c \
devices/dsc.c \
devices/ecowitt.c \
devices/efergy_e2_classic.c \
devices/efergy_optical.c \
devices/elro_db286a.c \

119
src/devices/ecowitt.c Normal file
View file

@ -0,0 +1,119 @@
/*
* 55-bit one-row data packet format (inclusive ranges, 0-indexed):
* | 0-6 | 7-bit header, ignored for checksum, always 1111111
* | 7-14 | Always 01010011
* | 15-22 | Sensor ID, randomly reinitialized on boot
* | 23-24 | Always 00
* | 25-26 | 2-bit sensor channel, selectable on back of sensor {00=1, 01=2, 10=3}
* | 27-28 | Always 00
* | 29-38 | 10-bit temperature in tenths of degrees C, starting from -40C. e.g. 0=-40C
* | 39-46 | Trailer, always 1111 1111
* | 47-54 | CRC-8 checksum poly 0x31 init 0x00 skipping first 7 bits
*
* Copyright 2019 Google LLC.
*
* 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.
*/
#include "decoder.h"
static int ecowitt_decode(r_device *decoder, bitbuffer_t *bitbuffer) {
// All Ecowitt packets have one row.
if (bitbuffer->num_rows != 1) {
return DECODE_ABORT_LENGTH;
}
// All Ecowitt packets have 55 bits.
if (bitbuffer->bits_per_row[0] != 55) {
return DECODE_ABORT_LENGTH;
}
uint8_t *row = bitbuffer->bb[0];
// All Ecowitt packets have the first 7 bits set.
uint8_t first7bits = row[0] >> 1;
if (first7bits != 0x7F) {
return DECODE_ABORT_EARLY;
}
// Byte-align the rest of the message by skipping the first 7 bits.
uint8_t b[6];
bitbuffer_extract_bytes(bitbuffer, /* row= */ 0, /* pos= */ 7, b, sizeof(b) * 8); // Skip first 7 bits
// All Ecowitt packets continue with a fixed header
if (b[0] != 0x53) {
return DECODE_ABORT_EARLY;
}
// Randomly generated at boot time sensor ID.
int sensorID = b[1];
int channel = b[2] >> 4; // First nybble.
channel++; // Convert 0-indexed wire protocol to 1-indexed channels on the device UI
if (channel < 1 || channel > 3) {
return DECODE_FAIL_SANITY; // The switch only has 1-3.
}
// All Ecowitt packets have bits 27 and 28 set to 0
// Perhaps these are just an extra two high bits for temperature?
// The manual though says it only operates to 60C, which about matches 10 bits (1023/10-40C)=62.3C
// Above 60 is pretty hot - let's just check these are always zero.
if ((b[2] & (4 | 8)) != 0) {
return DECODE_ABORT_EARLY;
}
// Temperature is next 10 bits
float tempC = -40.0; // Bias
tempC += (float) b[3] / 10.0;
tempC += (float) ((b[2] & 0x3) << 8) / 10.0;
// All Ecowitt observed packets have bits 39-48 set.
if (b[4] != 0xFF) {
return DECODE_ABORT_EARLY;
}
// Compute checksum skipping first 7 bits
uint8_t wireCRC = b[5];
int computedCRC = crc8(
b,
/* nBytes= */ sizeof(b)-1, // Exclude the CRC byte itself
/* polynomial= */ 0x31,
/* init= */ 0);
if (wireCRC != computedCRC) {
return DECODE_FAIL_MIC;
}
data_t *data = data_make(
"model", "", DATA_STRING, "Ecowitt-WH53",
"id", "Id", DATA_INT, sensorID,
"channel", "Channel", DATA_INT, channel,
"temperature_C", "Temperature", DATA_FORMAT, "%.01f C", DATA_DOUBLE, tempC,
"mic", "Integrity", DATA_STRING, "CRC",
NULL);
decoder_output_data(decoder, data);
return DECODE_SUCCESS;
}
static char *output_fields[] = {
"model",
"id",
"channel",
"temperature_C",
"mic",
NULL
};
r_device ecowitt = {
.name = "Ecowitt Temperature Sensor",
.modulation = OOK_PULSE_PWM, // copied from output, OOK_PWM = OOK_PULSE_PWM
.short_width = 504, // copied from output
.long_width = 1480, // copied from output
.gap_limit = 4800, // guessing, copied from generic_temperature_sensor
.reset_limit = 968, // copied from output
.sync_width = 0, // copied from output
.decode_fn = &ecowitt_decode,
.disabled = 0,
.fields = output_fields,
};

View file

@ -158,6 +158,7 @@
<ClCompile Include="..\src\devices\digitech_xc0324.c" />
<ClCompile Include="..\src\devices\dish_remote_6_3.c" />
<ClCompile Include="..\src\devices\dsc.c" />
<ClCompile Include="..\src\devices\ecowitt.c" />
<ClCompile Include="..\src\devices\efergy_e2_classic.c" />
<ClCompile Include="..\src\devices\efergy_optical.c" />
<ClCompile Include="..\src\devices\elro_db286a.c" />
@ -249,4 +250,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View file

@ -235,6 +235,9 @@
<ClCompile Include="..\src\devices\dsc.c">
<Filter>Source Files\devices</Filter>
</ClCompile>
<ClCompile Include="..\src\devices\ecowitt.c">
<Filter>Source Files\devices</Filter>
</ClCompile>
<ClCompile Include="..\src\devices\efergy_e2_classic.c">
<Filter>Source Files\devices</Filter>
</ClCompile>
@ -494,4 +497,4 @@
<Filter>Source Files\devices</Filter>
</ClCompile>
</ItemGroup>
</Project>
</Project>