From 653e6ab31f02d10f0e2190ec14ea302633d0982d Mon Sep 17 00:00:00 2001 From: igorok107 Date: Sun, 7 Feb 2016 21:34:59 +0300 Subject: [PATCH 01/20] Added tristate coding. --- src/devices/ht680.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/devices/ht680.c b/src/devices/ht680.c index 47e55dfe..b8efb305 100644 --- a/src/devices/ht680.c +++ b/src/devices/ht680.c @@ -20,9 +20,24 @@ static int ht680_callback(bitbuffer_t *bitbuffer) { (b[3] & 0x82) == 0x82 && //Buttons(4,3) always mask 10000010 (b[4] & 0x0A) == 0x0A){ //Buttons(2,1) always mask 00001010 b[0] = b[0] & 0x0F; //Clear sync + + // Tristate coding + char tristate[20] = ""; + for(uint8_t byte = 0; byte < 5; byte++){ + for(int8_t bit = 7; bit > 0; bit -= 2){ + switch ((b[byte] >> (bit-1)) & 0x03){ + case 0x00: strcat(tristate,"0"); break; + case 0x01: strcat(tristate,"?"); break; //Invalid code 01 + case 0x02: strcat(tristate,"Z"); break; //Floating state Z is 10 + case 0x03: strcat(tristate,"1"); break; + default: strcat(tristate,"!"); break; //Unknown error + } + } + } data = data_make("model", "", DATA_STRING, "HT680 Remote control", - "addres", "Addres code", DATA_FORMAT, "%06X", DATA_INT, (b[0]<<16)+(b[1]<<8)+b[2], + "tristate","Tristate code",DATA_STRING, tristate, + "address", "Address", DATA_FORMAT, "0x%06X", DATA_INT, (b[0]<<16)+(b[1]<<8)+b[2], "button1", "Button 1", DATA_STRING, (((b[4]>>4) & 0x03) == 3) ? "PRESSED" : "", "button2", "Button 2", DATA_STRING, (((b[4]>>6) & 0x03) == 3) ? "PRESSED" : "", "button3", "Button 3", DATA_STRING, ((((b[3]&0x7D)>>2) & 0x03) == 3) ? "PRESSED" : "", @@ -38,7 +53,8 @@ static int ht680_callback(bitbuffer_t *bitbuffer) { static char *output_fields[] = { "model", - "adress", + "tristate", + "address", "data", "button1", "button2", From d7a73d545e839d5fc0aef5b92d56d81f7d025c43 Mon Sep 17 00:00:00 2001 From: igorok107 Date: Sun, 7 Feb 2016 21:37:29 +0300 Subject: [PATCH 02/20] Correction data types in bitbuffer_find_repeated_row() --- include/bitbuffer.h | 2 +- src/bitbuffer.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/bitbuffer.h b/include/bitbuffer.h index 9bacd172..827eae9d 100644 --- a/include/bitbuffer.h +++ b/include/bitbuffer.h @@ -66,6 +66,6 @@ unsigned bitbuffer_manchester_decode(bitbuffer_t *inbuf, unsigned row, unsigned /// Find a repeated row that has a minimum count of bits. /// Return the row index or -1. -int bitbuffer_find_repeated_row(bitbuffer_t *bits, int min_repeats, int min_bits); +int bitbuffer_find_repeated_row(bitbuffer_t *bits, unsigned min_repeats, unsigned min_bits); #endif /* INCLUDE_BITBUFFER_H_ */ diff --git a/src/bitbuffer.c b/src/bitbuffer.c index fc7e7d31..4140c698 100644 --- a/src/bitbuffer.c +++ b/src/bitbuffer.c @@ -184,7 +184,7 @@ static unsigned count_repeats(bitbuffer_t *bits, unsigned row) { return cnt; } -int bitbuffer_find_repeated_row(bitbuffer_t *bits, int min_repeats, int min_bits) { +int bitbuffer_find_repeated_row(bitbuffer_t *bits, unsigned min_repeats, unsigned min_bits) { for (int i = 0; i < bits->num_rows; ++i) { if (bits->bits_per_row[i] >= min_bits && count_repeats(bits, i) >= min_repeats) { From 39c096d95d0d6be44336df6bc92c04415e5f434c Mon Sep 17 00:00:00 2001 From: "Christian W. Zuckschwerdt" Date: Tue, 26 Jan 2016 12:45:42 +0100 Subject: [PATCH 03/20] new feature: allow multiple outputs (WIP) --- src/data.c | 5 ++- src/rtl_433.c | 95 +++++++++++++++++++++++++++++++++++---------------- 2 files changed, 70 insertions(+), 30 deletions(-) diff --git a/src/data.c b/src/data.c index 7fad5852..3910bbcb 100644 --- a/src/data.c +++ b/src/data.c @@ -316,7 +316,10 @@ void data_print(data_t* data, FILE *file, data_printer_t *printer, void *aux) .aux = aux }; ctx.printer->print_data(&ctx, data, NULL, file); - fputc('\n', file); + if (file) { + fputc('\n', file); + fflush(file); + } } static void print_value(data_printer_context_t *printer_ctx, FILE *file, data_type_t type, void *value, char *format) { diff --git a/src/rtl_433.c b/src/rtl_433.c index 0771fda1..22c1030d 100644 --- a/src/rtl_433.c +++ b/src/rtl_433.c @@ -193,13 +193,16 @@ static unsigned int signal_end = 0; static unsigned int signal_pulse_data[4000][3] = { {0}}; static unsigned int signal_pulse_counter = 0; -typedef enum { - OUTPUT_KV, - OUTPUT_JSON, - OUTPUT_CSV -} output_format_t; -static output_format_t output_format; -void *csv_aux_data; + +typedef struct output_handler { + /*data_printer_t*/ void *printer; + void (*aux_free)(void *aux); + FILE *file; + void *aux; + struct output_handler *next; +} output_handler_t; +static output_handler_t *output_handler = NULL; +static output_handler_t **next_output_handler = &output_handler; /* handles incoming structured data by dumping it */ void data_acquired_handler(data_t *data) @@ -231,18 +234,9 @@ void data_acquired_handler(data_t *data) } } - switch (output_format) { - case OUTPUT_KV: { - data_print(data, stdout, &data_kv_printer, NULL); - } break; - case OUTPUT_JSON: { - data_print(data, stdout, &data_json_printer, NULL); - } break; - case OUTPUT_CSV: { - data_print(data, stdout, &data_csv_printer, csv_aux_data); - } break; + for (output_handler_t *output = output_handler; output; output = output->next) { + data_print(data, output->file, output->printer, output->aux); } - fflush(stdout); data_free(data); } @@ -748,6 +742,51 @@ void *determine_csv_fields(r_device* devices, int num_devices) return csv_aux; } +void add_json_output() +{ + output_handler_t *output = calloc(1, sizeof(output_handler_t)); + if (!output) { + fprintf(stderr, "rtl_433: failed to allocate memory for output handler\n"); + exit(1); + } + output->printer = &data_json_printer; + output->file = stdout; + *next_output_handler = output; + next_output_handler = &output->next; +} + +void add_csv_output(void *aux_data) +{ + if (!aux_data) { + fprintf(stderr, "rtl_433: failed to allocate memory for CSV auxiliary data\n"); + exit(1); + } + output_handler_t *output = calloc(1, sizeof(output_handler_t)); + if (!output) { + fprintf(stderr, "rtl_433: failed to allocate memory for output handler\n"); + exit(1); + } + output->printer = &data_csv_printer; + output->aux_free = &data_csv_free; + output->file = stdout; + output->aux = aux_data; + *next_output_handler = output; + next_output_handler = &output->next; +} + +void add_kv_output() +{ + output_handler_t *output = calloc(1, sizeof(output_handler_t)); + if (!output) { + fprintf(stderr, "rtl_433: failed to allocate memory for output handler\n"); + exit(1); + } + output->printer = &data_kv_printer; + output->file = stdout; + *next_output_handler = output; + next_output_handler = &output->next; +} + int main(int argc, char **argv) { #ifndef _WIN32 struct sigaction sigact; @@ -862,11 +901,11 @@ int main(int argc, char **argv) { break; case 'F': if (strcmp(optarg, "json") == 0) { - output_format = OUTPUT_JSON; + add_json_output(); } else if (strcmp(optarg, "csv") == 0) { - output_format = OUTPUT_CSV; + add_csv_output(determine_csv_fields(devices, num_r_devices)); } else if (strcmp(optarg, "kv") == 0) { - output_format = OUTPUT_KV; + add_kv_output(); } else { fprintf(stderr, "Invalid output format %s\n", optarg); usage(devices); @@ -900,12 +939,8 @@ int main(int argc, char **argv) { out_filename = argv[optind]; } - if (output_format == OUTPUT_CSV) { - csv_aux_data = determine_csv_fields(devices, num_r_devices); - if (!csv_aux_data) { - fprintf(stderr, "rtl_433: failed to allocate memory for CSV auxiliary data\n"); - exit(1); - } + if (!output_handler) { + add_kv_output(); } for (i = 0; i < num_r_devices; i++) { @@ -1152,8 +1187,10 @@ int main(int argc, char **argv) { rtlsdr_close(dev); out: - if (csv_aux_data) { - data_csv_free(csv_aux_data); + for (output_handler_t *output = output_handler; output; output = output->next) { + if (output->aux_free) { + output->aux_free(output->aux); + } } return r >= 0 ? r : -r; } From 8dc1f98e6429761a03343db5f06d9dc03e83a94b Mon Sep 17 00:00:00 2001 From: David Sheldon Date: Mon, 8 Feb 2016 08:25:08 +0000 Subject: [PATCH 04/20] Decode device id from current_cost, and support more devices --- src/devices/current_cost.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/devices/current_cost.c b/src/devices/current_cost.c index 7c748e8f..c3e06377 100644 --- a/src/devices/current_cost.c +++ b/src/devices/current_cost.c @@ -30,15 +30,19 @@ static int current_cost_callback(bitbuffer_t *bitbuffer) { bitbuffer_t packet_bits = {0}; start_pos = bitbuffer_manchester_decode(bitbuffer, 0, start_pos, &packet_bits, 0); + uint8_t *packet = packet_bits.bb[0]; // Read data - if(packet_bits.bits_per_row[0] >= 56 && packet[0] == 0x0d){ + if(packet_bits.bits_per_row[0] >= 56 && ((packet[0] & 0xf0) == 0) ){ + uint16_t device_id = (packet[0] & 0x0f) << 8 | packet[1]; + uint16_t watt0 = (packet[2] & 0x7F) << 8 | packet[3] ; uint16_t watt1 = (packet[4] & 0x7F) << 8 | packet[5] ; uint16_t watt2 = (packet[6] & 0x7F) << 8 | packet[7] ; data = data_make("time", "", DATA_STRING, time_str, "model", "", DATA_STRING, "CurrentCost TX", //TODO: it may have different CC Model ? any ref ? //"rc", "Rolling Code", DATA_INT, rc, //TODO: add rolling code b[1] ? test needed + "dev_id", "Device Id", DATA_FORMAT, "%d", DATA_INT, device_id, "power0", "Power 0", DATA_FORMAT, "%d W", DATA_INT, watt0, "power1", "Power 1", DATA_FORMAT, "%d W", DATA_INT, watt1, "power2", "Power 2", DATA_FORMAT, "%d W", DATA_INT, watt2, From 85733efeeeb1ff068bfd633fb46837eda57678ef Mon Sep 17 00:00:00 2001 From: Martin Hauke Date: Mon, 8 Feb 2016 23:27:51 +0100 Subject: [PATCH 05/20] Add support for Conrad S3318P --- include/rtl_433.h | 2 +- include/rtl_433_devices.h | 3 +- src/CMakeLists.txt | 1 + src/Makefile.am | 3 +- src/devices/s3318p.c | 149 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 155 insertions(+), 3 deletions(-) create mode 100644 src/devices/s3318p.c diff --git a/include/rtl_433.h b/include/rtl_433.h index 9ba3adce..2c4afeaa 100755 --- a/include/rtl_433.h +++ b/include/rtl_433.h @@ -35,7 +35,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 45 +#define MAX_PROTOCOLS 46 #define SIGNAL_GRABBER_BUFFER (12 * DEFAULT_BUF_LENGTH) /* Supported modulation types */ diff --git a/include/rtl_433_devices.h b/include/rtl_433_devices.h index 3ec93dd7..3d8f36be 100755 --- a/include/rtl_433_devices.h +++ b/include/rtl_433_devices.h @@ -48,7 +48,8 @@ DECL(oil_watchman) \ DECL(current_cost) \ DECL(emontx) \ - DECL(ht680) + DECL(ht680) \ + DECL(s3318p) typedef struct { char name[256]; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4df093e7..b9f998e8 100755 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -64,6 +64,7 @@ add_executable(rtl_433 devices/waveman.c devices/wt450.c devices/x10_rf.c + devices/s3318p.c ) diff --git a/src/Makefile.am b/src/Makefile.am index ed1acdcf..19bbcc89 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -49,7 +49,8 @@ rtl_433_SOURCES = baseband.c \ devices/valeo.c \ devices/waveman.c \ devices/wt450.c \ - devices/x10_rf.c + devices/x10_rf.c \ + devices/s3318p.c rtl_433_LDADD = $(LIBRTLSDR) $(LIBM) diff --git a/src/devices/s3318p.c b/src/devices/s3318p.c new file mode 100644 index 00000000..16a1792d --- /dev/null +++ b/src/devices/s3318p.c @@ -0,0 +1,149 @@ +#include "rtl_433.h" +#include "data.h" +#include "util.h" + +/* Conrad Electronics S3318P outdoor sensor + * + * Transmit Interval: every ~50s + * Message Format: 40 bits (10 nibbles) + * + * + * Nibble: 1 2 3 4 5 6 7 8 9 10 + * Type: PP IIIIIIII ??CCTTTT TTTTTTTT HHHHHHHH XB?????? PP + * BIT/8 00 01234567 01234567 01234567 01234567 01234567 00 + * BIT/A 00 01234567 89012345 57890123 45678901 23456789 00 + * 0 1 2 3 + * I = sensor ID (changes on battery change) + * C = channel number + * T = temperature + * H = humidity + * X = tx-button pressed + * B = low battery + * P = Pre-/Postamble + * ? = unknown meaning + * + * + * [01] {42} 04 15 66 e2 a1 00 : 00000100 00010101 01100110 11100010 10100001 00 ---> Temp/Hum/Ch:23.2/46/1 + * + * Temperature: + * Sensor sends data in °F, lowest supported value is 90°F + * 12 bit uingned and scaled by 10 (Nibbles: 6,5,4) + * in this case "011001100101" = 1637/10 - 90 = 73.7 °F (23.17 °C) + * + * Humidity: + * 8 bit unsigned (Nibbles 8,7) + * in this case "00101110" = 46 + * + * Channel number: (Bits 10,11) + 1 + * in this case "00" --> "00" +1 = Channel1 + * + * Battery status: (Bit 33) (0 normal, 1 voltage is below ~2.7 V) + * TX-Button: (Bit 32) (0 indicates regular transmission, 1 indicates requested by pushbutton) + * + * Rolling Code / Device ID: (Nibble 1) + * changes on every battery change + * + * Unknown1: (Bits 8,9) changes not so often + * Unknown2: (Bits 36-39) changes with every packet, probably checksum + * Unknown3: (Bits 34,35) changes not so often, mayby also part of the checksum + * + */ + + +static int s3318p_callback(bitbuffer_t *bitbuffer) { + bitrow_t *bb = bitbuffer->bb; + data_t *data; + char time_str[LOCAL_TIME_BUFLEN]; + + /* Get time now */ + local_time_str(0, time_str); + + /* Reject codes of wrong length */ + if ( 42 != bitbuffer->bits_per_row[1]) + return 0; + + /* shift all the bits left 2 to align the fields */ + int i; + for (i = 0; i < BITBUF_COLS-1; i++) { + uint8_t bits1 = bb[1][i] << 2; + uint8_t bits2 = (bb[1][i+1] & 0xC0) >> 6; + bits1 |= bits2; + bb[1][i] = bits1; + } + + uint8_t humidity; + uint8_t button; + uint8_t battery_low; + uint8_t channel; + uint8_t sensor_id; + uint16_t temperature_with_offset; + float temperature_f; + float temperature_c; + + /* IIIIIIII ??CCTTTT TTTTTTTT HHHHHHHH XB?????? PP */ + humidity = (uint8_t)(((bb[1][3] & 0x0F) << 4) | ((bb[1][3] & 0xF0) >> 4)); + button = (uint8_t)(bb[1][4] >> 7); + battery_low = (uint8_t)((bb[1][4] & 0x40) >> 6); + channel = (uint8_t)(((bb[1][1] & 0x30) >> 4) + 1); + sensor_id = (uint8_t)(bb[1][0]); + + temperature_with_offset = (uint16_t)(((bb[1][2] & 0x0F) << 8) | (bb[1][2] & 0xF0) | (bb[1][1] & 0x0F)); + temperature_f = (float)((temperature_with_offset - 900) / 10.0); + temperature_c = fahrenheit2celsius(temperature_f); + + if (debug_output) { + bitbuffer_print(bitbuffer); + fprintf(stderr, "Sensor ID = %2x\n", sensor_id); + fprintf(stdout, "Bitstream HEX = %02x %02x %02x %02x %02x %02x\n",bb[1][0],bb[1][1],bb[1][2],bb[1][3],bb[1][4],bb[1][5]); + fprintf(stdout, "Humidity HEX = %02x\n", bb[1][3]); + fprintf(stdout, "Humidity DEC = %u\n", humidity); + fprintf(stdout, "Button = %d\n", button); + fprintf(stdout, "Battery Low = %d\n", battery_low); + fprintf(stdout, "Channel HEX = %02x\n", bb[1][1]); + fprintf(stdout, "Channel = %u\n", channel); + fprintf(stdout, "temp_with_offset HEX = %02x\n", temperature_with_offset); + fprintf(stdout, "temp_with_offset = %d\n", temperature_with_offset); + fprintf(stdout, "TemperatureF = %.1f\n", temperature_f); + fprintf(stdout, "TemperatureC = %.1f\n", temperature_c); + } + + data = data_make("time", "", DATA_STRING, time_str, + "model", "", DATA_STRING, "S3318P Temperature & Humidity Sensor", + "id", "House Code", DATA_INT, sensor_id, + "channel", "Channel", DATA_INT, channel, + "battery", "Battery", DATA_STRING, battery_low ? "LOW" : "OK", + "button", "Button", DATA_INT, button, + "temperature_C", "Temperature", DATA_FORMAT, "%.02f C", DATA_DOUBLE, temperature_c, + "humidity", "Humidity", DATA_FORMAT, "%u %%", DATA_INT, humidity, + NULL); + + data_acquired_handler(data); + + return 0; +} + +static char *output_fields[] = { + "time", + "model", + "id", + "channel", + "battery", + "button", + "temperature_C", + "humidity", + NULL +}; + + +r_device s3318p = { + .name = "S3318P Temperature & Humidity Sensor", + .modulation = OOK_PULSE_PPM_RAW, + .short_limit = 2800, + .long_limit = 4400, + .reset_limit = 8000, + .json_callback = &s3318p_callback, + .disabled = 0, + .demod_arg = 0, + .fields = output_fields +}; + From 7383ffd5cfe73a26cee731c0e8e88e6cb14e2fd0 Mon Sep 17 00:00:00 2001 From: Martin Hauke Date: Tue, 9 Feb 2016 00:31:28 +0100 Subject: [PATCH 06/20] s3318p: use native temperature format --- src/CMakeLists.txt | 2 +- src/devices/s3318p.c | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b9f998e8..b094802e 100755 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -64,7 +64,7 @@ add_executable(rtl_433 devices/waveman.c devices/wt450.c devices/x10_rf.c - devices/s3318p.c + devices/s3318p.c ) diff --git a/src/devices/s3318p.c b/src/devices/s3318p.c index 16a1792d..80712645 100644 --- a/src/devices/s3318p.c +++ b/src/devices/s3318p.c @@ -78,7 +78,6 @@ static int s3318p_callback(bitbuffer_t *bitbuffer) { uint8_t sensor_id; uint16_t temperature_with_offset; float temperature_f; - float temperature_c; /* IIIIIIII ??CCTTTT TTTTTTTT HHHHHHHH XB?????? PP */ humidity = (uint8_t)(((bb[1][3] & 0x0F) << 4) | ((bb[1][3] & 0xF0) >> 4)); @@ -89,7 +88,6 @@ static int s3318p_callback(bitbuffer_t *bitbuffer) { temperature_with_offset = (uint16_t)(((bb[1][2] & 0x0F) << 8) | (bb[1][2] & 0xF0) | (bb[1][1] & 0x0F)); temperature_f = (float)((temperature_with_offset - 900) / 10.0); - temperature_c = fahrenheit2celsius(temperature_f); if (debug_output) { bitbuffer_print(bitbuffer); @@ -104,7 +102,6 @@ static int s3318p_callback(bitbuffer_t *bitbuffer) { fprintf(stdout, "temp_with_offset HEX = %02x\n", temperature_with_offset); fprintf(stdout, "temp_with_offset = %d\n", temperature_with_offset); fprintf(stdout, "TemperatureF = %.1f\n", temperature_f); - fprintf(stdout, "TemperatureC = %.1f\n", temperature_c); } data = data_make("time", "", DATA_STRING, time_str, @@ -113,7 +110,7 @@ static int s3318p_callback(bitbuffer_t *bitbuffer) { "channel", "Channel", DATA_INT, channel, "battery", "Battery", DATA_STRING, battery_low ? "LOW" : "OK", "button", "Button", DATA_INT, button, - "temperature_C", "Temperature", DATA_FORMAT, "%.02f C", DATA_DOUBLE, temperature_c, + "temperature_F", "Temperature", DATA_FORMAT, "%.02f F", DATA_DOUBLE, temperature_f, "humidity", "Humidity", DATA_FORMAT, "%u %%", DATA_INT, humidity, NULL); From d2fe3a07cfd55111f54e274748d28b4d59ea301d Mon Sep 17 00:00:00 2001 From: Martin Hauke Date: Mon, 8 Feb 2016 23:27:51 +0100 Subject: [PATCH 07/20] Add support for Conrad S3318P --- include/rtl_433.h | 2 +- include/rtl_433_devices.h | 3 +- src/CMakeLists.txt | 1 + src/Makefile.am | 3 +- src/devices/s3318p.c | 146 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 152 insertions(+), 3 deletions(-) create mode 100644 src/devices/s3318p.c diff --git a/include/rtl_433.h b/include/rtl_433.h index 9ba3adce..2c4afeaa 100755 --- a/include/rtl_433.h +++ b/include/rtl_433.h @@ -35,7 +35,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 45 +#define MAX_PROTOCOLS 46 #define SIGNAL_GRABBER_BUFFER (12 * DEFAULT_BUF_LENGTH) /* Supported modulation types */ diff --git a/include/rtl_433_devices.h b/include/rtl_433_devices.h index 3ec93dd7..3d8f36be 100755 --- a/include/rtl_433_devices.h +++ b/include/rtl_433_devices.h @@ -48,7 +48,8 @@ DECL(oil_watchman) \ DECL(current_cost) \ DECL(emontx) \ - DECL(ht680) + DECL(ht680) \ + DECL(s3318p) typedef struct { char name[256]; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4df093e7..b094802e 100755 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -64,6 +64,7 @@ add_executable(rtl_433 devices/waveman.c devices/wt450.c devices/x10_rf.c + devices/s3318p.c ) diff --git a/src/Makefile.am b/src/Makefile.am index ed1acdcf..19bbcc89 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -49,7 +49,8 @@ rtl_433_SOURCES = baseband.c \ devices/valeo.c \ devices/waveman.c \ devices/wt450.c \ - devices/x10_rf.c + devices/x10_rf.c \ + devices/s3318p.c rtl_433_LDADD = $(LIBRTLSDR) $(LIBM) diff --git a/src/devices/s3318p.c b/src/devices/s3318p.c new file mode 100644 index 00000000..80712645 --- /dev/null +++ b/src/devices/s3318p.c @@ -0,0 +1,146 @@ +#include "rtl_433.h" +#include "data.h" +#include "util.h" + +/* Conrad Electronics S3318P outdoor sensor + * + * Transmit Interval: every ~50s + * Message Format: 40 bits (10 nibbles) + * + * + * Nibble: 1 2 3 4 5 6 7 8 9 10 + * Type: PP IIIIIIII ??CCTTTT TTTTTTTT HHHHHHHH XB?????? PP + * BIT/8 00 01234567 01234567 01234567 01234567 01234567 00 + * BIT/A 00 01234567 89012345 57890123 45678901 23456789 00 + * 0 1 2 3 + * I = sensor ID (changes on battery change) + * C = channel number + * T = temperature + * H = humidity + * X = tx-button pressed + * B = low battery + * P = Pre-/Postamble + * ? = unknown meaning + * + * + * [01] {42} 04 15 66 e2 a1 00 : 00000100 00010101 01100110 11100010 10100001 00 ---> Temp/Hum/Ch:23.2/46/1 + * + * Temperature: + * Sensor sends data in °F, lowest supported value is 90°F + * 12 bit uingned and scaled by 10 (Nibbles: 6,5,4) + * in this case "011001100101" = 1637/10 - 90 = 73.7 °F (23.17 °C) + * + * Humidity: + * 8 bit unsigned (Nibbles 8,7) + * in this case "00101110" = 46 + * + * Channel number: (Bits 10,11) + 1 + * in this case "00" --> "00" +1 = Channel1 + * + * Battery status: (Bit 33) (0 normal, 1 voltage is below ~2.7 V) + * TX-Button: (Bit 32) (0 indicates regular transmission, 1 indicates requested by pushbutton) + * + * Rolling Code / Device ID: (Nibble 1) + * changes on every battery change + * + * Unknown1: (Bits 8,9) changes not so often + * Unknown2: (Bits 36-39) changes with every packet, probably checksum + * Unknown3: (Bits 34,35) changes not so often, mayby also part of the checksum + * + */ + + +static int s3318p_callback(bitbuffer_t *bitbuffer) { + bitrow_t *bb = bitbuffer->bb; + data_t *data; + char time_str[LOCAL_TIME_BUFLEN]; + + /* Get time now */ + local_time_str(0, time_str); + + /* Reject codes of wrong length */ + if ( 42 != bitbuffer->bits_per_row[1]) + return 0; + + /* shift all the bits left 2 to align the fields */ + int i; + for (i = 0; i < BITBUF_COLS-1; i++) { + uint8_t bits1 = bb[1][i] << 2; + uint8_t bits2 = (bb[1][i+1] & 0xC0) >> 6; + bits1 |= bits2; + bb[1][i] = bits1; + } + + uint8_t humidity; + uint8_t button; + uint8_t battery_low; + uint8_t channel; + uint8_t sensor_id; + uint16_t temperature_with_offset; + float temperature_f; + + /* IIIIIIII ??CCTTTT TTTTTTTT HHHHHHHH XB?????? PP */ + humidity = (uint8_t)(((bb[1][3] & 0x0F) << 4) | ((bb[1][3] & 0xF0) >> 4)); + button = (uint8_t)(bb[1][4] >> 7); + battery_low = (uint8_t)((bb[1][4] & 0x40) >> 6); + channel = (uint8_t)(((bb[1][1] & 0x30) >> 4) + 1); + sensor_id = (uint8_t)(bb[1][0]); + + temperature_with_offset = (uint16_t)(((bb[1][2] & 0x0F) << 8) | (bb[1][2] & 0xF0) | (bb[1][1] & 0x0F)); + temperature_f = (float)((temperature_with_offset - 900) / 10.0); + + if (debug_output) { + bitbuffer_print(bitbuffer); + fprintf(stderr, "Sensor ID = %2x\n", sensor_id); + fprintf(stdout, "Bitstream HEX = %02x %02x %02x %02x %02x %02x\n",bb[1][0],bb[1][1],bb[1][2],bb[1][3],bb[1][4],bb[1][5]); + fprintf(stdout, "Humidity HEX = %02x\n", bb[1][3]); + fprintf(stdout, "Humidity DEC = %u\n", humidity); + fprintf(stdout, "Button = %d\n", button); + fprintf(stdout, "Battery Low = %d\n", battery_low); + fprintf(stdout, "Channel HEX = %02x\n", bb[1][1]); + fprintf(stdout, "Channel = %u\n", channel); + fprintf(stdout, "temp_with_offset HEX = %02x\n", temperature_with_offset); + fprintf(stdout, "temp_with_offset = %d\n", temperature_with_offset); + fprintf(stdout, "TemperatureF = %.1f\n", temperature_f); + } + + data = data_make("time", "", DATA_STRING, time_str, + "model", "", DATA_STRING, "S3318P Temperature & Humidity Sensor", + "id", "House Code", DATA_INT, sensor_id, + "channel", "Channel", DATA_INT, channel, + "battery", "Battery", DATA_STRING, battery_low ? "LOW" : "OK", + "button", "Button", DATA_INT, button, + "temperature_F", "Temperature", DATA_FORMAT, "%.02f F", DATA_DOUBLE, temperature_f, + "humidity", "Humidity", DATA_FORMAT, "%u %%", DATA_INT, humidity, + NULL); + + data_acquired_handler(data); + + return 0; +} + +static char *output_fields[] = { + "time", + "model", + "id", + "channel", + "battery", + "button", + "temperature_C", + "humidity", + NULL +}; + + +r_device s3318p = { + .name = "S3318P Temperature & Humidity Sensor", + .modulation = OOK_PULSE_PPM_RAW, + .short_limit = 2800, + .long_limit = 4400, + .reset_limit = 8000, + .json_callback = &s3318p_callback, + .disabled = 0, + .demod_arg = 0, + .fields = output_fields +}; + From bf605749ef4a6442fcf4ea3b3d9b1840d35439ed Mon Sep 17 00:00:00 2001 From: YGator Date: Mon, 8 Feb 2016 20:07:48 -0500 Subject: [PATCH 08/20] Fix --- src/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index ed1acdcf..f6ca4e55 100755 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -26,7 +26,7 @@ rtl_433_SOURCES = baseband.c \ devices/emontx.c \ devices/esperanza_ews.c \ devices/fineoffset.c \ - devices/fineoffset_wh1080 \ + devices/fineoffset_wh1080.c \ devices/generic_remote.c \ devices/generic_temperature_sensor.c \ devices/gt_wt_02.c \ From e006899bc1480a5d8ea0dfbb907346d16523ca43 Mon Sep 17 00:00:00 2001 From: "Christian W. Zuckschwerdt" Date: Tue, 9 Feb 2016 20:19:40 +0100 Subject: [PATCH 09/20] also switch the labels on output conversion --- src/rtl_433.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/rtl_433.c b/src/rtl_433.c index 22c1030d..ed8a6a29 100644 --- a/src/rtl_433.c +++ b/src/rtl_433.c @@ -212,6 +212,7 @@ void data_acquired_handler(data_t *data) if ((d->type == DATA_DOUBLE) && !strcmp(d->key, "temperature_F")) { *(double*)d->value = fahrenheit2celsius(*(double*)d->value); + d->key = strdup("temperature_C"); char *pos; if (d->format && (pos = strrchr(d->format, 'F'))) { @@ -225,6 +226,7 @@ void data_acquired_handler(data_t *data) if ((d->type == DATA_DOUBLE) && !strcmp(d->key, "temperature_C")) { *(double*)d->value = celsius2fahrenheit(*(double*)d->value); + d->key = strdup("temperature_F"); char *pos; if (d->format && (pos = strrchr(d->format, 'C'))) { From dfa321808bfbf4f66bb0eed87123993e296a4adc Mon Sep 17 00:00:00 2001 From: YGator Date: Thu, 11 Feb 2016 21:02:46 -0500 Subject: [PATCH 10/20] Spurious output for debug mode --- src/devices/oregon_scientific.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) mode change 100644 => 100755 src/devices/oregon_scientific.c diff --git a/src/devices/oregon_scientific.c b/src/devices/oregon_scientific.c old mode 100644 new mode 100755 index acf50e80..d7bda681 --- a/src/devices/oregon_scientific.c +++ b/src/devices/oregon_scientific.c @@ -119,8 +119,10 @@ static int validate_os_checksum(unsigned char *msg, int checksum_nibble_idx) { if (sum_of_nibbles == checksum) { return 0; } else { - fprintf(stderr, "Checksum error in Oregon Scientific message. Expected: %02x Calculated: %02x\n", checksum, sum_of_nibbles); - fprintf(stderr, "Message: "); int i; for (i=0 ;i<((checksum_nibble_idx+4)>>1) ; i++) fprintf(stdout, "%02x ", msg[i]); fprintf(stdout, "\n\n"); + if(debug_output) { + fprintf(stderr, "Checksum error in Oregon Scientific message. Expected: %02x Calculated: %02x\n", checksum, sum_of_nibbles); + fprintf(stderr, "Message: "); int i; for (i=0 ;i<((checksum_nibble_idx+4)>>1) ; i++) fprintf(stdout, "%02x ", msg[i]); fprintf(stdout, "\n\n"); + } return 1; } } @@ -131,8 +133,10 @@ static int validate_os_v2_message(unsigned char * msg, int bits_expected, int va if (bits_expected == valid_v2_bits_received) { return (validate_os_checksum(msg, nibbles_in_checksum)); } else { - fprintf(stderr, "Bit validation error on Oregon Scientific message. Expected %d bits, received error after bit %d \n", bits_expected, valid_v2_bits_received); - fprintf(stderr, "Message: "); int i; for (i=0 ;i<(bits_expected+7)/8 ; i++) fprintf(stdout, "%02x ", msg[i]); fprintf(stdout, "\n\n"); + if(debug_output) { + fprintf(stderr, "Bit validation error on Oregon Scientific message. Expected %d bits, received error after bit %d \n", bits_expected, valid_v2_bits_received); + fprintf(stderr, "Message: "); int i; for (i=0 ;i<(bits_expected+7)/8 ; i++) fprintf(stdout, "%02x ", msg[i]); fprintf(stdout, "\n\n"); + } } return 1; } @@ -460,9 +464,11 @@ static int oregon_scientific_v3_parser(bitbuffer_t *bitbuffer) { fprintf(stdout,"Energy Sensor CM180 Id %x%x power: %dW\n", msg[0], msg[1], ipower); } else if ((msg[0] != 0) && (msg[1]!= 0)) { // sync nibble was found and some data is present... - fprintf(stderr, "Message received from unrecognized Oregon Scientific v3 sensor.\n"); - fprintf(stderr, "Message: "); for (i=0 ; i Date: Thu, 11 Feb 2016 22:22:50 -0500 Subject: [PATCH 11/20] Remove some compiler warnings --- src/data.c | 2 +- src/devices/x10_rf.c | 2 +- src/rtl_433.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) mode change 100644 => 100755 src/data.c mode change 100644 => 100755 src/devices/x10_rf.c mode change 100644 => 100755 src/rtl_433.c diff --git a/src/data.c b/src/data.c old mode 100644 new mode 100755 index 3910bbcb..2cd90760 --- a/src/data.c +++ b/src/data.c @@ -423,7 +423,7 @@ static void print_kv_data(data_printer_context_t *printer_ctx, data_t *data, cha } } if (!strcmp(data->key, "time")) - fprintf(file, ""); + ; else if (!strcmp(data->key, "model")) fprintf(file, ":\t"); else diff --git a/src/devices/x10_rf.c b/src/devices/x10_rf.c old mode 100644 new mode 100755 index 810d6cf7..1872106f --- a/src/devices/x10_rf.c +++ b/src/devices/x10_rf.c @@ -17,7 +17,7 @@ static int X10_RF_callback(bitbuffer_t *bitbuffer) { // Validate package if ((bitbuffer->bits_per_row[1] == 32) // Dont waste time on a short package // && (bb[1][0] == (uint8_t)(~bb[1][1])) // Check integrity - apparently some chips may use both bytes.. - && (bb[1][2] == (uint8_t)(~bb[1][3])) // Check integrity + && (bb[1][2] == (255 - bb[1][3])) // Check integrity ) { fprintf(stdout, "X10 RF:\n"); diff --git a/src/rtl_433.c b/src/rtl_433.c old mode 100644 new mode 100755 index ed8a6a29..92f2a7b5 --- a/src/rtl_433.c +++ b/src/rtl_433.c @@ -797,7 +797,7 @@ int main(int argc, char **argv) { char *in_filename = NULL; FILE *in_file; int n_read; - int r, opt; + int r = 0, opt; int i, gain = 0; int sync_mode = 0; int ppm_error = 0; From 40ae3819913880e7935b4cacebf8b3f72ad13a50 Mon Sep 17 00:00:00 2001 From: rknobbe Date: Fri, 12 Feb 2016 13:48:36 -0800 Subject: [PATCH 12/20] fix wind direction nibble extract for WGR800 --- src/devices/oregon_scientific.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/devices/oregon_scientific.c b/src/devices/oregon_scientific.c index d7bda681..5b74a575 100755 --- a/src/devices/oregon_scientific.c +++ b/src/devices/oregon_scientific.c @@ -417,6 +417,7 @@ static int oregon_scientific_v3_parser(bitbuffer_t *bitbuffer) { return 1; } else if ((msg[0] == 0x19) && (msg[1] == 0x84)) { if (validate_os_checksum(msg, 17) == 0) { + // 8 Direction, Not BCD – binary value from 0..15. Direction in degrees is value * 22.5 degrees. // 13..11 Current Speed, meters per second, LSD is 0.1 m/s // 16..14 Average speed, meters per second, LSD is 0.1 m/s /* @@ -429,7 +430,7 @@ static int oregon_scientific_v3_parser(bitbuffer_t *bitbuffer) { float gustWindspeed = (msg[5]&0x0f) /10.0F + ((msg[6]>>4)&0x0f) *1.0F + (msg[6]&0x0f) * 10.0F; float avgWindspeed = ((msg[7]>>4)&0x0f) / 10.0F + (msg[7]&0x0f) *1.0F + ((msg[8]>>4)&0x0f) * 10.0F; int battery = get_os_battery(msg, ID_WGR800); - float quadrant = (0x0f&(msg[5]>>4))*22.5; + float quadrant = (0x0f&(msg[4]>>4))*22.5F; data = data_make("time", "", DATA_STRING, time_str, "model", "", DATA_STRING, "Weather Sensor WGR800 Wind Gauge", "id", "House Code", DATA_INT, get_os_rollingcode(msg, ID_WGR800), From 9c2e7b0826e99eccd3e62f6493b1b730e19c9ad3 Mon Sep 17 00:00:00 2001 From: YGator Date: Sat, 13 Feb 2016 14:00:42 -0500 Subject: [PATCH 13/20] Remove some compiler warnings --- src/data.c | 2 +- src/devices/x10_rf.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/data.c b/src/data.c index 2cd90760..25a7728c 100755 --- a/src/data.c +++ b/src/data.c @@ -423,7 +423,7 @@ static void print_kv_data(data_printer_context_t *printer_ctx, data_t *data, cha } } if (!strcmp(data->key, "time")) - ; + /* fprintf(file, "") */ ; else if (!strcmp(data->key, "model")) fprintf(file, ":\t"); else diff --git a/src/devices/x10_rf.c b/src/devices/x10_rf.c index 1872106f..4d48b168 100755 --- a/src/devices/x10_rf.c +++ b/src/devices/x10_rf.c @@ -17,6 +17,7 @@ static int X10_RF_callback(bitbuffer_t *bitbuffer) { // Validate package if ((bitbuffer->bits_per_row[1] == 32) // Dont waste time on a short package // && (bb[1][0] == (uint8_t)(~bb[1][1])) // Check integrity - apparently some chips may use both bytes.. + // (255 - bb[1][3]) is equivalent to ~bb[1][3] but does not cause compiler warning && (bb[1][2] == (255 - bb[1][3])) // Check integrity ) { From 9f13efc983747551fbe76f72967fd06f300495a0 Mon Sep 17 00:00:00 2001 From: YGator Date: Sat, 13 Feb 2016 20:36:37 -0500 Subject: [PATCH 14/20] Remove some compiler warnings --- src/devices/x10_rf.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/devices/x10_rf.c b/src/devices/x10_rf.c index 4d48b168..b01ffeca 100755 --- a/src/devices/x10_rf.c +++ b/src/devices/x10_rf.c @@ -17,8 +17,7 @@ static int X10_RF_callback(bitbuffer_t *bitbuffer) { // Validate package if ((bitbuffer->bits_per_row[1] == 32) // Dont waste time on a short package // && (bb[1][0] == (uint8_t)(~bb[1][1])) // Check integrity - apparently some chips may use both bytes.. - // (255 - bb[1][3]) is equivalent to ~bb[1][3] but does not cause compiler warning - && (bb[1][2] == (255 - bb[1][3])) // Check integrity + && (bb[1][2] == ((0xff & (~bb[1][3])))) // Check integrity ) { fprintf(stdout, "X10 RF:\n"); From fc9166435efd01339837cde7adce53e25f990664 Mon Sep 17 00:00:00 2001 From: "Christian W. Zuckschwerdt" Date: Thu, 18 Feb 2016 07:54:56 +0100 Subject: [PATCH 15/20] fix off-by-one and make the null explicit --- src/devices/ht680.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/devices/ht680.c b/src/devices/ht680.c index b8efb305..500484cc 100644 --- a/src/devices/ht680.c +++ b/src/devices/ht680.c @@ -22,18 +22,20 @@ static int ht680_callback(bitbuffer_t *bitbuffer) { b[0] = b[0] & 0x0F; //Clear sync // Tristate coding - char tristate[20] = ""; + char tristate[21]; + char *p = tristate; for(uint8_t byte = 0; byte < 5; byte++){ for(int8_t bit = 7; bit > 0; bit -= 2){ switch ((b[byte] >> (bit-1)) & 0x03){ - case 0x00: strcat(tristate,"0"); break; - case 0x01: strcat(tristate,"?"); break; //Invalid code 01 - case 0x02: strcat(tristate,"Z"); break; //Floating state Z is 10 - case 0x03: strcat(tristate,"1"); break; - default: strcat(tristate,"!"); break; //Unknown error + case 0x00: *p++ = '0'; break; + case 0x01: *p++ = '?'; break; //Invalid code 01 + case 0x02: *p++ = 'Z'; break; //Floating state Z is 10 + case 0x03: *p++ = '1'; break; + default: *p++ = '!'; break; //Unknown error } } } + *p = '\0'; data = data_make("model", "", DATA_STRING, "HT680 Remote control", "tristate","Tristate code",DATA_STRING, tristate, From 57475bb19ae3bd3c8ba48d6ac6dbd1744314c005 Mon Sep 17 00:00:00 2001 From: Jussi Vestman Date: Sun, 21 Feb 2016 15:44:52 +0200 Subject: [PATCH 16/20] LaCrosse WS-2310 json output --- src/devices/lacrossews.c | 70 +++++++++++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 16 deletions(-) diff --git a/src/devices/lacrossews.c b/src/devices/lacrossews.c index d3815e58..b9c6048e 100755 --- a/src/devices/lacrossews.c +++ b/src/devices/lacrossews.c @@ -19,6 +19,7 @@ #include "rtl_433.h" #include "util.h" +#include "data.h" #define LACROSSE_WS_BITLEN 52 @@ -84,7 +85,8 @@ static int lacrossews_callback(bitbuffer_t *bitbuffer) { uint8_t ws_id, msg_type, sensor_id, msg_data, msg_unknown, msg_checksum; int msg_value_bcd, msg_value_bcd2, msg_value_bin; float temp_c, temp_f, wind_dir, wind_spd, rain_mm, rain_in; - char time_str[LOCAL_TIME_BUFLEN]; + char time_str[LOCAL_TIME_BUFLEN], *wind_key, *wind_label; + data_t *data; for (m = 0; m < BITBUF_ROWS; m++) { // break out the message nybbles into separate bytes @@ -102,7 +104,7 @@ static int lacrossews_callback(bitbuffer_t *bitbuffer) { local_time_str(0, time_str); - if (debug_output) + if (debug_output) fprintf(stderr, "%1X%1X%1X%1X%1X%1X%1X%1X%1X%1X%1X%1X%1X ", msg_nybbles[0], msg_nybbles[1], msg_nybbles[2], msg_nybbles[3], msg_nybbles[4], msg_nybbles[5], msg_nybbles[6], msg_nybbles[7], @@ -113,27 +115,41 @@ static int lacrossews_callback(bitbuffer_t *bitbuffer) { // Temperature case 0: temp_c = (msg_value_bcd - 300.0) / 10.0; - temp_f = temp_c * 1.8 + 32; - printf("%s LaCrosse WS %02X-%02X: Temperature %3.1f C / %3.1f F\n", - time_str, ws_id, sensor_id, temp_c, temp_f); + data = data_make("time", "", DATA_STRING, time_str, + "model", "", DATA_STRING, "LaCrosse WS", + "ws_id", "", DATA_INT, ws_id, + "id", "", DATA_INT, sensor_id, + "temperature_C", "Temperature", DATA_FORMAT, "%.1f C", DATA_DOUBLE, temp_c, + NULL); + data_acquired_handler(data); events++; + break; // Humidity case 1: if(msg_nybbles[7] == 0xA && msg_nybbles[8] == 0xA) - printf("%s LaCrosse WS %02X-%02X: Humidity Error\n", + fprintf(stderr, "%s LaCrosse WS %02X-%02X: Humidity Error\n", time_str, ws_id, sensor_id); - else - printf("%s LaCrosse WS %02X-%02X: Humidity %2d %%\n", - time_str, ws_id, sensor_id, msg_value_bcd2); + else { + data = data_make("time", "", DATA_STRING, time_str, + "model", "", DATA_STRING, "LaCrosse WS", + "ws_id", "", DATA_INT, ws_id, + "id", "", DATA_INT, sensor_id, + "humidity", "Humidity", DATA_INT, msg_value_bcd2, + NULL); + data_acquired_handler(data); events++; + } break; // Rain case 2: rain_mm = 0.5180 * msg_value_bin; - rain_in = 0.0204 * msg_value_bin; - printf("%s LaCrosse WS %02X-%02X: Rain %3.2f mm / %3.2f in\n", - time_str, ws_id, sensor_id, rain_mm, rain_in); + data = data_make("time", "", DATA_STRING, time_str, + "model", "", DATA_STRING, "LaCrosse WS", + "ws_id", "", DATA_INT, ws_id, + "id", "", DATA_INT, sensor_id, + "rainfall_mm", "Rainfall", DATA_FORMAT, "%3.2f mm", DATA_DOUBLE, rain_mm, NULL); + data_acquired_handler(data); events++; break; // Wind @@ -143,11 +159,18 @@ static int lacrossews_callback(bitbuffer_t *bitbuffer) { wind_dir = msg_nybbles[9] * 22.5; wind_spd = (msg_nybbles[7] * 16 + msg_nybbles[8])/ 10.0; if(msg_nybbles[7] == 0xF && msg_nybbles[8] == 0xE) - printf("%s LaCrosse WS %02X-%02X: %s Not Connected\n", + fprintf(stderr, "%s LaCrosse WS %02X-%02X: %s Not Connected\n", time_str, ws_id, sensor_id, msg_type == 3 ? "Wind":"Gust"); else { - printf("%s LaCrosse WS %02X-%02X: %s Dir %3.1f Speed %3.1f m/s / %3.1f mph\n", - time_str, ws_id, sensor_id, msg_type == 3 ? "Wind":"Gust", wind_dir, wind_spd, wind_spd * 2.236936292054); + wind_key = msg_type == 3 ? "wind_speed_ms":"gust_speed"; + wind_label = msg_type == 3 ? "Wind speed":"Gust speed"; + data = data_make("time", "", DATA_STRING, time_str, + "model", "", DATA_STRING, "LaCrosse WS", + "ws_id", "", DATA_INT, ws_id, + "id", "", DATA_INT, sensor_id, + wind_key, wind_label, DATA_FORMAT, "%3.1f m/s", DATA_DOUBLE, wind_spd, + "wind_direction", "Direction", DATA_DOUBLE, wind_dir, NULL); + data_acquired_handler(data); events++; } break; @@ -163,13 +186,28 @@ static int lacrossews_callback(bitbuffer_t *bitbuffer) { return events; } +static char *output_fields[] = { + "time", + "model", + "ws_id", + "id", + "temperature_C", + "humidity", + "rainfall_mm", + "wind_speed_ms", + "gust_speed_ms", + "wind_direction", + NULL +}; + r_device lacrossews = { .name = "LaCrosse WS-2310 Weather Station", .modulation = OOK_PULSE_PWM_RAW, .short_limit = 952, .long_limit = 3000, .reset_limit = 8000, - .json_callback = &lacrossews_callback, + .json_callback = &lacrossews_callback, .disabled = 0, .demod_arg = 0, + .fields = output_fields }; From aca936a1f4edbb092190a73f22d844e982a72192 Mon Sep 17 00:00:00 2001 From: Jussi Vestman Date: Sun, 21 Feb 2016 21:24:40 +0200 Subject: [PATCH 17/20] Fixed WS-2310 json gust_speed to gust_speed_ms --- src/devices/lacrossews.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/devices/lacrossews.c b/src/devices/lacrossews.c index b9c6048e..a4b2bf44 100755 --- a/src/devices/lacrossews.c +++ b/src/devices/lacrossews.c @@ -162,7 +162,7 @@ static int lacrossews_callback(bitbuffer_t *bitbuffer) { fprintf(stderr, "%s LaCrosse WS %02X-%02X: %s Not Connected\n", time_str, ws_id, sensor_id, msg_type == 3 ? "Wind":"Gust"); else { - wind_key = msg_type == 3 ? "wind_speed_ms":"gust_speed"; + wind_key = msg_type == 3 ? "wind_speed_ms":"gust_speed_ms"; wind_label = msg_type == 3 ? "Wind speed":"Gust speed"; data = data_make("time", "", DATA_STRING, time_str, "model", "", DATA_STRING, "LaCrosse WS", From 4f3d1071451befb31dd6cb6c5150500db61ffb34 Mon Sep 17 00:00:00 2001 From: YGator Date: Mon, 22 Feb 2016 18:49:28 -0500 Subject: [PATCH 18/20] Fix some memory leaks --- src/data.c | 1 + src/rtl_433.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/data.c b/src/data.c index 25a7728c..32a33713 100755 --- a/src/data.c +++ b/src/data.c @@ -302,6 +302,7 @@ void data_free(data_t *data) { data_t *prev_data = data; if (dmt[data->type].value_release) dmt[data->type].value_release(data->value); + free(data->format); free(data->pretty_key); free(data->key); data = data->next; diff --git a/src/rtl_433.c b/src/rtl_433.c index 92f2a7b5..3ec2f1ab 100755 --- a/src/rtl_433.c +++ b/src/rtl_433.c @@ -212,6 +212,7 @@ void data_acquired_handler(data_t *data) if ((d->type == DATA_DOUBLE) && !strcmp(d->key, "temperature_F")) { *(double*)d->value = fahrenheit2celsius(*(double*)d->value); + free(d->key); d->key = strdup("temperature_C"); char *pos; if (d->format && @@ -226,6 +227,7 @@ void data_acquired_handler(data_t *data) if ((d->type == DATA_DOUBLE) && !strcmp(d->key, "temperature_C")) { *(double*)d->value = celsius2fahrenheit(*(double*)d->value); + free(d->key); d->key = strdup("temperature_F"); char *pos; if (d->format && From 906eb80bf9e297fbf97a6da3f9dcad67f4e72c03 Mon Sep 17 00:00:00 2001 From: Jussi Vestman Date: Wed, 24 Feb 2016 20:44:58 +0200 Subject: [PATCH 19/20] TFA Twin Plus 30.3049 json support --- src/devices/tfa_twin_plus_30.3049.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/devices/tfa_twin_plus_30.3049.c b/src/devices/tfa_twin_plus_30.3049.c index 5a28bc1c..29990eca 100644 --- a/src/devices/tfa_twin_plus_30.3049.c +++ b/src/devices/tfa_twin_plus_30.3049.c @@ -1,5 +1,6 @@ #include "rtl_433.h" #include "util.h" +#include "data.h" /* * TFA-Twin-Plus-30.3049 @@ -55,6 +56,7 @@ inline static uint8_t reverse_byte(uint8_t byte) static int tfa_twin_plus_303049_process_row(int row, const bitbuffer_t *bitbuffer) { + data_t *data; const uint8_t *b = bitbuffer->bb[row]; const uint16_t length = bitbuffer->bits_per_row[row]; @@ -91,10 +93,15 @@ static int tfa_twin_plus_303049_process_row(int row, const bitbuffer_t *bitbuffe char time_str[LOCAL_TIME_BUFLEN]; local_time_str(0, time_str); - /* @todo make temperature unit configurable, not printing both */ - fprintf(stdout, "%s TFA-Twin-Plus-30.3049 Sensor %02x: battery %s, channel %d, temperature %3.1f C / %3.1f F, humidity %2d%%\n" - , time_str, sensor_id, battery_low ? "low" : "OK", channel, tempC, celsius2fahrenheit(tempC), humidity - ); + data = data_make("time", "", DATA_STRING, time_str, + "model", "", DATA_STRING, "TFA-Twin-Plus-30.3049", + "id", "", DATA_INT, sensor_id, + "channel", "", DATA_INT, channel, + "battery", "Battery", DATA_STRING, battery_low ? "LOW" : "OK", + "temperature_C", "Temperature", DATA_FORMAT, "%.1f C", DATA_DOUBLE, tempC, + "humidity", "Humidity", DATA_FORMAT, "%u %%", DATA_INT, humidity, + NULL); + data_acquired_handler(data); } return 1; @@ -359,6 +366,17 @@ Passed 74/74 positive tests #endif +static char *output_fields[] = { + "time", + "model", + "id", + "channel", + "battery", + "temperature_C", + "humidity", + NULL +}; + r_device tfa_twin_plus_303049 = { .name = "TFA-Twin-Plus-30.3049 and Ea2 BL999", .modulation = OOK_PULSE_PPM_RAW, @@ -368,4 +386,5 @@ r_device tfa_twin_plus_303049 = { .json_callback = &tfa_twin_plus_303049_callback, .disabled = 0, .demod_arg = 0, + .fields = output_fields }; From 15e4269811e9132a3065fcaf8004f46cbe6862fa Mon Sep 17 00:00:00 2001 From: YGator Date: Wed, 24 Feb 2016 14:17:15 -0500 Subject: [PATCH 20/20] Output less decimal places to get rid of bogus digits --- src/data.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/data.c b/src/data.c index 32a33713..c0fa4479 100755 --- a/src/data.c +++ b/src/data.c @@ -394,7 +394,7 @@ static void print_json_string(data_printer_context_t *printer_ctx, const char *s static void print_json_double(data_printer_context_t *printer_ctx, double data, char *format, FILE *file) { - fprintf(file, "%f", data); + fprintf(file, "%.3f", data); } static void print_json_int(data_printer_context_t *printer_ctx, int data, char *format, FILE *file) @@ -440,7 +440,7 @@ static void print_kv_data(data_printer_context_t *printer_ctx, data_t *data, cha static void print_kv_double(data_printer_context_t *printer_ctx, double data, char *format, FILE *file) { - fprintf(file, format ? format : "%f", data); + fprintf(file, format ? format : "%.3f", data); } static void print_kv_int(data_printer_context_t *printer_ctx, int data, char *format, FILE *file)