1 /* wt450 wireless weather sensors protocol
7 * Copyright (C) 2015 Tommy Vestermark
8 * Copyright (C) 2015 Ladislav Foldyna
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
17 http://ala-paavola.fi/jaakko/doku.php?id=wt450h
20 The signal is FM encoded with clock cycle around 2000 µs
21 No level shift within the clock cycle translates to a logic 0
22 One level shift within the clock cycle translates to a logic 1
23 Each clock cycle begins with a level shift
24 My timing constants defined below are those observed by my program
26 +---+ +---+ +-------+ + high
29 + +---+ +---+ +-------+ low
31 | 1 | 1 | 0 | 0 | translates as
33 Each transmission is 36 bits long (i.e. 72 ms)
35 Data is transmitted in pure binary values, NOT BCD-coded.
40 * Outdoor sensor transmits data temperature, humidity.
41 * Transmissions also include channel code and house code. The sensor transmits
42 * every 60 seconds 3 packets.
44 * 1100 0001 | 0011 0011 | 1000 0011 | 1011 0011 | 0001
45 * xxxx ssss | ccxx bhhh | hhhh tttt | tttt tttt | tttp
50 * b - battery indicator (0=>OK, 1=>LOW)
53 * p - parity (xor of all bits should give 0)
58 #include "pulse_demod.h"
61 static int wt450_callback(bitbuffer_t *bitbuffer) {
63 bitrow_t *bb = bitbuffer->bb;
67 uint8_t temp_whole = 0;
68 uint8_t temp_fraction = 0;
69 uint8_t house_code = 0;
71 uint8_t battery_low = 0;
76 char time_str[LOCAL_TIME_BUFLEN];
78 local_time_str(0, time_str);
80 //bitbuffer_print(bitbuffer);
82 if ( bitbuffer->bits_per_row[0] != 36 )
85 fprintf(stderr, "%s wt450_callback: wrong size of bit per row %d\n",
86 time_str, bitbuffer->bits_per_row[0] );
95 fprintf(stderr, "%s wt450_callback: wrong preamble\n", time_str);
96 bitbuffer_print(bitbuffer);
101 for ( bit = 0; bit < bitbuffer->bits_per_row[0]; bit++ )
103 parity ^= (b[bit/8] & (0x80 >> (bit % 8))) ? 1 : 0;
110 fprintf(stderr, "%s wt450_callback: wrong parity\n", time_str);
111 bitbuffer_print(bitbuffer);
116 house_code = b[0] & 0xF;
117 channel = (b[1] >> 6) + 1;
118 battery_low = b[1] & 0x8;
119 humidity = ((b[1] & 0x7) << 4) + (b[2] >> 4);
120 temp_whole = (b[2] << 4) + (b[3] >> 4);
121 temp_fraction = ((b[3] & 0xF) << 3) + (b[4] >> 5);
122 temp = (temp_whole - 50) + (temp_fraction/100.0);
124 data = data_make("time", "", DATA_STRING, time_str,
125 "model", "", DATA_STRING, "WT450 sensor",
126 "id", "House Code", DATA_INT, house_code,
127 "channel", "Channel", DATA_INT, channel,
128 "battery", "Battery", DATA_STRING, battery_low ? "LOW" : "OK",
129 "temperature_C", "Temperature",DATA_FORMAT, "%.02f C", DATA_DOUBLE, temp,
130 "humidity", "Humidity", DATA_FORMAT, "%u %%", DATA_INT, humidity,
132 data_acquired_handler(data);
137 PWM_Precise_Parameters clock_bits_parameters_generic = {
138 .pulse_tolerance = 20,
139 .pulse_sync_width = 0, // No sync bit used
142 static char *output_fields[] = {
155 .modulation = OOK_PULSE_CLOCK_BITS,
158 .reset_limit = 18000,
159 .json_callback = &wt450_callback,
161 .demod_arg = (uintptr_t)&clock_bits_parameters_generic,
162 .fields = output_fields