Merge pull request from foldynl/WT450

Wt450 device
This commit is contained in:
Benjamin Larsson 2015-10-05 22:04:41 +02:00
commit 6bcd3b1439
7 changed files with 197 additions and 2 deletions

View file

@ -115,5 +115,6 @@ int pulse_demod_pwm_ternary(const pulse_data_t *pulses, struct protocol_state *d
/// @return number of events processed
int pulse_demod_manchester_zerobit(const pulse_data_t *pulses, struct protocol_state *device);
int pulse_demod_clock_bits(const pulse_data_t *pulses, struct protocol_state *device);
#endif /* INCLUDE_PULSE_DEMOD_H_ */

View file

@ -30,7 +30,7 @@
#define DEFAULT_LEVEL_LIMIT 8000 // Theoretical high level at I/Q saturation is 128x128 = 16384 (above is ripple)
#define MINIMAL_BUF_LENGTH 512
#define MAXIMAL_BUF_LENGTH (256 * 16384)
#define MAX_PROTOCOLS 32
#define MAX_PROTOCOLS 33
#define SIGNAL_GRABBER_BUFFER (12 * DEFAULT_BUF_LENGTH)
/* Supported modulation types */
@ -42,6 +42,7 @@
#define OOK_PULSE_PWM_PRECISE 6 // Pulse Width Modulation with precise timing parameters
#define OOK_PULSE_PWM_RAW 7 // Pulse Width Modulation. Short pulses = 1, Long = 0
#define OOK_PULSE_PWM_TERNARY 8 // Pulse Width Modulation with three widths: Sync, 0, 1. Sync determined by argument
#define OOK_PULSE_CLOCK_BITS 9 // Level shift within the clock cycle.
#define FSK_DEMOD_MIN_VAL 16 // Dummy. FSK demodulation must start at this value
#define FSK_PULSE_PCM 16 // FSK, Pulse Code Modulation

View file

@ -35,7 +35,8 @@
DECL(chuango) \
DECL(generic_remote) \
DECL(tfa_twin_plus_303049) \
DECL(digitech_ws)
DECL(digitech_ws) \
DECL(wt450)
typedef struct {

View file

@ -52,6 +52,7 @@ add_executable(rtl_433
devices/generic_remote.c
devices/tfa_twin_plus_30.3049.c
devices/xc0348.c
devices/wt450.c
)
target_link_libraries(rtl_433

144
src/devices/wt450.c Normal file
View file

@ -0,0 +1,144 @@
/* wt450 wireless weather sensors protocol
*
* Tested devices:
* WT260H
* WT405H
*
* Copyright (C) 2015 Tommy Vestermark
* Copyright (C) 2015 Ladislav Foldyna
* 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.
*/
/*
source from:
http://ala-paavola.fi/jaakko/doku.php?id=wt450h
The signal is FM encoded with clock cycle around 2000 µs
No level shift within the clock cycle translates to a logic 0
One level shift within the clock cycle translates to a logic 1
Each clock cycle begins with a level shift
My timing constants defined below are those observed by my program
+---+ +---+ +-------+ + high
| | | | | | |
| | | | | | |
+ +---+ +---+ +-------+ low
^ ^ ^ ^ ^ clock cycle
| 1 | 1 | 0 | 0 | translates as
Each transmission is 36 bits long (i.e. 72 ms)
Data is transmitted in pure binary values, NOT BCD-coded.
*/
/*
* Outdoor sensor transmits data temperature, humidity.
* Transmissions also include channel code and house code. The sensor transmits
* every 60 seconds 3 packets.
*
* 1100 0001 | 0011 0011 | 1000 0011 | 1011 0011 | 0001
* xxxx ssss | ccxx bhhh | hhhh tttt | tttt tttt | tttp
*
* x - constant
* s - House code
* c - Channel
* b - battery indicator (0=>OK, 1=>LOW)
* h - Humidity
* t - Temperature
* p - parity (xor of all bits should give 0)
*/
#include "rtl_433.h"
#include "util.h"
#include "pulse_demod.h"
static int wt450_callback(bitbuffer_t *bitbuffer) {
bitrow_t *bb = bitbuffer->bb;
uint8_t *b = bb[0];
uint8_t humidity = 0;
uint8_t temp_whole = 0;
uint8_t temp_fraction = 0;
uint8_t house_code = 0;
uint8_t channel = 0;
uint8_t battery_low = 0;
float temp = 0;
uint8_t bit;
uint8_t parity = 0;
time_t time_now;
char time_str[LOCAL_TIME_BUFLEN];
time(&time_now);
local_time_str(time_now, time_str);
//bitbuffer_print(bitbuffer);
if ( bitbuffer->bits_per_row[0] != 36 )
{
fprintf(stderr, "wt450_callback: wrong size of bit per row %d\n",
bitbuffer->bits_per_row[0] );
return 0;
}
if ( b[0]>>4 != 0xC )
{
fprintf(stderr, "wt450_callback: wrong preamble\n");
bitbuffer_print(bitbuffer);
return 0;
}
for ( bit = 0; bit < bitbuffer->bits_per_row[0]; bit++ )
{
parity ^= b[bit/8] & (0x80 >> (bit % 8));
}
if ( !parity )
{
fprintf(stderr, "wt450_callback: wrong parity\n");
bitbuffer_print(bitbuffer);
return 0;
}
house_code = b[0] & 0xF;
channel = (b[1] >> 6) + 1;
battery_low = b[1] & 0x8;
humidity = ((b[1] & 0x7) << 4) + (b[2] >> 4);
temp_whole = (b[2] << 4) + (b[3] >> 4);
temp_fraction = ((b[3] & 0xF) << 3) + (b[4] >> 5);
temp = (temp_whole - 50) + (temp_fraction/100.0);
/*
fprintf(stdout, "Temperature[%d]\n", temp_whole-50);
fprintf(stdout, "temp fraction[%u]\n", temp_fraction);
*/
fprintf(stdout, "%s WT450 sensor: House Code %u, "
"Channel %u, Battery %s, "
"Temperature %.02f C, Humidity %u %%\n",
time_str, house_code,
channel, (battery_low) ? "LOW" : "OK",
temp, humidity);
return 1;
}
PWM_Precise_Parameters clock_bits_parameters_generic = {
.pulse_tolerance = 20,
.pulse_sync_width = 0, // No sync bit used
};
r_device wt450 = {
.name = "WT450",
.modulation = OOK_PULSE_CLOCK_BITS,
.short_limit = 245,
.long_limit = 488,
.reset_limit = 4500,
.json_callback = &wt450_callback,
.disabled = 0,
.demod_arg = (unsigned long)&clock_bits_parameters_generic,
};

View file

@ -276,3 +276,45 @@ int pulse_demod_manchester_zerobit(const pulse_data_t *pulses, struct protocol_s
}
return events;
}
int pulse_demod_clock_bits(const pulse_data_t *pulses, struct protocol_state *device) {
unsigned int symbol[PD_MAX_PULSES * 2];
unsigned int n;
PWM_Precise_Parameters *p = (PWM_Precise_Parameters *)device->demod_arg;
bitbuffer_t bits = {0};
int events = 0;
for(n = 0; n < pulses->num_pulses; n++) {
symbol[n*2] = pulses->pulse[n];
symbol[(n*2)+1] = pulses->gap[n];
}
for(n = 0; n < pulses->num_pulses * 2; ++n) {
if ( abs(symbol[n] - device->short_limit) < p->pulse_tolerance) {
// Short - 1
bitbuffer_add_bit(&bits, 1);
if ( abs(symbol[++n] - device->short_limit) > p->pulse_tolerance) {
/* fprintf(stderr, "Detected error during pulse_demod_clock_bits(): %s\n",
device->name);
*/ return events;
}
} else if ( abs(symbol[n] - device->long_limit) < p->pulse_tolerance) {
// Long - 0
bitbuffer_add_bit(&bits, 0);
} else if (symbol[n] >= (unsigned int)device->reset_limit - p->pulse_tolerance ) {
//END message ?
if (device->callback) {
events += device->callback(&bits);
}
if(!device->callback || (debug_output && events > 0)) {
fprintf(stderr, "pulse_demod_clock_bits(): %s \n", device->name);
bitbuffer_print(&bits);
}
bitbuffer_clear(&bits);
}
}
return events;
}

View file

@ -672,6 +672,7 @@ static void rtlsdr_callback(unsigned char *iq_buf, uint32_t len, void *ctx) {
case OOK_PULSE_PWM_RAW:
case OOK_PULSE_PWM_TERNARY:
case OOK_PULSE_MANCHESTER_ZEROBIT:
case OOK_PULSE_CLOCK_BITS:
case FSK_PULSE_PCM:
break;
default:
@ -708,6 +709,9 @@ static void rtlsdr_callback(unsigned char *iq_buf, uint32_t len, void *ctx) {
case OOK_PULSE_MANCHESTER_ZEROBIT:
pulse_demod_manchester_zerobit(&demod->pulse_data, demod->r_devs[i]);
break;
case OOK_PULSE_CLOCK_BITS:
pulse_demod_clock_bits(&demod->pulse_data, demod->r_devs[i]);
break;
// FSK decoders
case FSK_PULSE_PCM:
break;
@ -730,6 +734,7 @@ static void rtlsdr_callback(unsigned char *iq_buf, uint32_t len, void *ctx) {
case OOK_PULSE_PWM_RAW:
case OOK_PULSE_PWM_TERNARY:
case OOK_PULSE_MANCHESTER_ZEROBIT:
case OOK_PULSE_CLOCK_BITS:
break;
case FSK_PULSE_PCM:
pulse_demod_pcm(&demod->fsk_pulse_data, demod->r_devs[i]);