Merge pull request #1 from merbanan/master

Testing a way to update my repo
This commit is contained in:
ovrheat
2016-02-25 03:11:43 +01:00
15 changed files with 352 additions and 72 deletions

View File

@@ -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_ */

View File

@@ -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 */

View File

@@ -48,7 +48,8 @@
DECL(oil_watchman) \
DECL(current_cost) \
DECL(emontx) \
DECL(ht680)
DECL(ht680) \
DECL(s3318p)
typedef struct {
char name[256];

View File

@@ -64,6 +64,7 @@ add_executable(rtl_433
devices/waveman.c
devices/wt450.c
devices/x10_rf.c
devices/s3318p.c
)

View File

@@ -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 \
@@ -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)

View File

@@ -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) {

12
src/data.c Normal file → Executable file
View File

@@ -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;
@@ -316,7 +317,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) {
@@ -390,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)
@@ -420,7 +424,7 @@ static void print_kv_data(data_printer_context_t *printer_ctx, data_t *data, cha
}
}
if (!strcmp(data->key, "time"))
fprintf(file, "");
/* fprintf(file, "") */ ;
else if (!strcmp(data->key, "model"))
fprintf(file, ":\t");
else
@@ -436,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)

View File

@@ -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,

View File

@@ -20,9 +20,26 @@ 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[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: *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",
"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 +55,8 @@ static int ht680_callback(bitbuffer_t *bitbuffer) {
static char *output_fields[] = {
"model",
"adress",
"tristate",
"address",
"data",
"button1",
"button2",

View File

@@ -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_ms";
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
};

23
src/devices/oregon_scientific.c Normal file → Executable file
View File

@@ -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;
}
@@ -413,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
/*
@@ -425,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),
@@ -460,9 +465,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<BITBUF_COLS ; i++) fprintf(stdout, "%02x ", msg[i]); fprintf(stdout, "\n");
fprintf(stderr, " Raw: "); for (i=0 ; i<BITBUF_COLS ; i++) fprintf(stdout, "%02x ", bb[0][i]); fprintf(stdout,"\n\n");
if(debug_output) {
fprintf(stderr, "Message received from unrecognized Oregon Scientific v3 sensor.\n");
fprintf(stderr, "Message: "); for (i=0 ; i<BITBUF_COLS ; i++) fprintf(stdout, "%02x ", msg[i]); fprintf(stdout, "\n");
fprintf(stderr, " Raw: "); for (i=0 ; i<BITBUF_COLS ; i++) fprintf(stdout, "%02x ", bb[0][i]); fprintf(stdout,"\n\n");
}
} else if (bb[0][3] != 0 ) {
//fprintf(stdout, "\nPossible Oregon Scientific v3 message, but sync nibble wasn't found\n");
//fprintf(stdout, "Raw Data: "); for (i=0 ; i<BITBUF_COLS ; i++) fprintf(stdout, "%02x ", bb[0][i]); fprintf(stdout,"\n\n");

146
src/devices/s3318p.c Normal file
View File

@@ -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
};

View File

@@ -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
};

2
src/devices/x10_rf.c Normal file → Executable file
View File

@@ -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] == ((0xff & (~bb[1][3])))) // Check integrity
)
{
fprintf(stdout, "X10 RF:\n");

101
src/rtl_433.c Normal file → Executable file
View File

@@ -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)
@@ -209,6 +212,8 @@ 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 &&
(pos = strrchr(d->format, 'F'))) {
@@ -222,6 +227,8 @@ 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 &&
(pos = strrchr(d->format, 'C'))) {
@@ -231,18 +238,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 +746,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;
@@ -756,7 +799,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;
@@ -862,11 +905,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 +943,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 +1191,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;
}