mirror of
https://github.com/merbanan/rtl_433.git
synced 2026-04-23 02:57:07 -04:00
1
.gitignore
vendored
1
.gitignore
vendored
@@ -45,3 +45,4 @@ build/
|
||||
.project
|
||||
|
||||
*.orig
|
||||
*~
|
||||
|
||||
25
README.md
25
README.md
@@ -31,15 +31,22 @@ Running:
|
||||
|
||||
rtl_433 -h
|
||||
|
||||
Usage: [-d device_index (default: 0)]
|
||||
[-g gain (default: 0 for auto)]
|
||||
[-a analyze mode, print a textual description of the signal]
|
||||
[-l change the detection level used to determine pulses (0-32000) default 10000]
|
||||
[-f change the receive frequency, default is 433.92MHz]
|
||||
[-S force sync output (default: async)]
|
||||
[-r read data from file instead of from a receiver]
|
||||
filename (a '-' dumps samples to stdout)
|
||||
|
||||
Usage: [-d device_index (default: 0)]
|
||||
[-g gain (default: 0 for auto)]
|
||||
[-a analyze mode, print a textual description of the signal]
|
||||
[-t signal auto save, use it together with analyze mode (-a -t)
|
||||
[-l change the detection level used to determine pulses (0-3200) default: 10000]
|
||||
[-f [-f...] receive frequency[s], default: 433920000 Hz]
|
||||
[-s samplerate (default: 250000 Hz)]
|
||||
[-S force sync output (default: async)]
|
||||
[-r read data from file instead of from a receiver]
|
||||
[-p ppm_error (default: 0)]
|
||||
[-r test file name (indata)]
|
||||
[-m test file mode (0 rtl_sdr data, 1 rtl_433 data)]
|
||||
[-D print debug info on event
|
||||
[-z override short value
|
||||
[-x override long value
|
||||
filename (a '-' dumps samples to stdout)
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
@@ -35,9 +35,10 @@
|
||||
#define BITBUF_ROWS 50
|
||||
|
||||
/* Supported modulation types */
|
||||
#define OOK_PWM_D 1 /* Pulses are of the same length, the distance varies */
|
||||
#define OOK_PWM_D 1 /* Pulses are of the same length, the distance varies (PPM) */
|
||||
#define OOK_PWM_P 2 /* The length of the pulses varies */
|
||||
#define OOK_MANCHESTER 3 /* Manchester code */
|
||||
#define OOK_PWM_RAW 4 /* Pulse Width Modulation. No startbit removal. Short pulses = 1, Long = 0 */
|
||||
|
||||
typedef struct {
|
||||
unsigned int id;
|
||||
|
||||
@@ -17,5 +17,6 @@ extern r_device mebus433;
|
||||
extern r_device intertechno;
|
||||
extern r_device newkaku;
|
||||
extern r_device alectov1;
|
||||
extern r_device fineoffset_WH2;
|
||||
|
||||
#endif /* INCLUDE_RTL_433_DEVICES_H_ */
|
||||
|
||||
@@ -30,7 +30,8 @@ add_executable(rtl_433
|
||||
devices/mebus.c
|
||||
devices/intertechno.c
|
||||
devices/alecto.c
|
||||
devices/newkaku.c)
|
||||
devices/newkaku.c
|
||||
devices/fineoffset.c)
|
||||
|
||||
target_link_libraries(rtl_433
|
||||
${LIBRTLSDR_LIBRARIES}
|
||||
|
||||
110
src/devices/fineoffset.c
Normal file
110
src/devices/fineoffset.c
Normal file
@@ -0,0 +1,110 @@
|
||||
/* Fine Offset Electronics sensor protocol
|
||||
*
|
||||
* The protocol is for the wireless Temperature/Humidity sensor
|
||||
* Fine Offset Electronics WH2
|
||||
* aka Agimex Rosenborg 66796 (sold in Denmark)
|
||||
* aka ClimeMET CM9088 (Sold in UK)
|
||||
* aka ...
|
||||
*
|
||||
* The sensor sends two identical packages of 48 bits each ~50s. The bits are PWM modulated with On Off Keying
|
||||
*
|
||||
* The data is grouped in 6 bytes / 12 nibbles
|
||||
* [pre] [pre] [type] [id] [id] [temp] [temp] [temp] [humi] [humi] [crc] [crc]
|
||||
*
|
||||
* pre is always 0xFF
|
||||
* type is always 0x4 (may be different for different sensor type?)
|
||||
* id is a random id that is generated when the sensor starts
|
||||
* temp is 12 bit signed magnitude scaled by 10 celcius
|
||||
* humi is 8 bit relative humidity percentage
|
||||
*
|
||||
* Based on reverse engineering with gnu-radio and the nice article here:
|
||||
* http://lucsmall.com/2012/04/29/weather-station-hacking-part-2/
|
||||
*
|
||||
* Copyright (C) 2015 Tommy Vestermark
|
||||
* 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 "rtl_433.h"
|
||||
|
||||
|
||||
// Generic CRC-8
|
||||
// (Should probably be moved to somewhere common)
|
||||
// polynomial byte is from x^7 to x^0 (x^8 is implicitly one)
|
||||
uint8_t crc8(uint8_t const message[], unsigned nBytes, uint8_t polynomial) {
|
||||
uint8_t remainder = 0;
|
||||
unsigned byte, bit;
|
||||
|
||||
for (byte = 0; byte < nBytes; ++byte) {
|
||||
remainder ^= message[byte];
|
||||
for (bit = 0; bit < 8; ++bit) {
|
||||
if (remainder & 0x80) {
|
||||
remainder = (remainder << 1) ^ polynomial;
|
||||
}
|
||||
else {
|
||||
remainder = (remainder << 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return remainder;
|
||||
}
|
||||
|
||||
|
||||
static int fineoffset_WH2_callback(uint8_t bb[BITBUF_ROWS][BITBUF_COLS], int16_t bits_per_row[BITBUF_ROWS]) {
|
||||
uint8_t ID;
|
||||
float temperature;
|
||||
float humidity;
|
||||
|
||||
const uint8_t polynomial = 0x31; // x8 + x5 + x4 + 1 (x8 is implicit)
|
||||
|
||||
// Validate package
|
||||
if (bits_per_row[0] >= 48 && // Dont waste time on a short package
|
||||
bb[0][0] == 0xFF && // Preamble
|
||||
bb[0][5] == crc8(&bb[0][1], 4, polynomial) // CRC (excluding preamble)
|
||||
)
|
||||
{
|
||||
// Nibble 3,4 contains ID
|
||||
ID = ((bb[0][1]&0x0F) << 4) | ((bb[0][2]&0xF0) >> 4);
|
||||
|
||||
// Nible 5,6,7 contains 12 bits of temperature
|
||||
// The temperature is signed magnitude and scaled by 10
|
||||
int16_t temp;
|
||||
temp = bb[0][3];
|
||||
temp |= (int16_t)(bb[0][2] & 0x0F) << 8;
|
||||
if(temp & 0x800) {
|
||||
temp &= 0x7FF; // remove sign bit
|
||||
temp = -temp; // reverse magnitude
|
||||
}
|
||||
temperature = (float)temp / 10;
|
||||
|
||||
// Nibble 8,9 contains humidity
|
||||
humidity = bb[0][4];
|
||||
|
||||
fprintf(stderr, "Fine Offset Electronics, WH2:\n");
|
||||
fprintf(stderr, "ID = 0x%2X\n", ID);
|
||||
fprintf(stderr, "temperature = %.1f C\n", temperature);
|
||||
fprintf(stderr, "humidity = %2.0f %%\n", humidity);
|
||||
// fprintf(stderr, "raw = %02x %02x %02x %02x %02x %02x\n",bb[0][0],bb[0][1],bb[0][2],bb[0][3],bb[0][4],bb[0][5]);
|
||||
|
||||
if (debug_output)
|
||||
debug_callback(bb, bits_per_row);
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
r_device fineoffset_WH2 = {
|
||||
/* .id = */ 12,
|
||||
/* .name = */ "Fine Offset Electronics, WH-2 Sensor",
|
||||
/* .modulation = */ OOK_PWM_RAW,
|
||||
/* .short_limit = */ 200, // Short pulse 136, long pulse 381, fixed gap 259
|
||||
/* .long_limit = */ 700, // Maximum pulse period (long pulse + fixed gap)
|
||||
/* .reset_limit = */ 700, // We just want 1 package
|
||||
/* .json_callback = */ &fineoffset_WH2_callback,
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -15,6 +15,32 @@ unsigned int get_os_humidity(unsigned char *message, unsigned int sensor_id) {
|
||||
return humidity;
|
||||
}
|
||||
|
||||
unsigned int get_os_rollingcode(unsigned char *message, unsigned int sensor_id){
|
||||
int rc = 0;
|
||||
rc = (message[2]&0x0F) + (message[3]&0xF0);
|
||||
return rc;
|
||||
}
|
||||
|
||||
unsigned short int power(const unsigned char* d){
|
||||
unsigned short int val = 0;
|
||||
val += d[4] << 8;
|
||||
val += d[3];
|
||||
//fprintf(stderr, "Power: %x %d", val, val);
|
||||
return val & 0xFFF0 ;
|
||||
}
|
||||
|
||||
unsigned long total(const unsigned char* d){
|
||||
unsigned long val = 0;
|
||||
if ( (d[1]&0x0F) == 0 ){
|
||||
// Sensor returns total only if nibble#4 == 0
|
||||
val = (unsigned long)d[8]<<24;
|
||||
val += (unsigned long)d[7] << 16;
|
||||
val += d[6] << 8;
|
||||
val += d[5];
|
||||
}
|
||||
return val ;
|
||||
}
|
||||
|
||||
static int validate_os_checksum(unsigned char *msg, int checksum_nibble_idx) {
|
||||
// Oregon Scientific v2.1 and v3 checksum is a 1 byte 'sum of nibbles' checksum.
|
||||
// with the 2 nibbles of the checksum byte swapped.
|
||||
@@ -126,9 +152,13 @@ static int oregon_scientific_v2_1_parser(uint8_t bb[BITBUF_ROWS][BITBUF_COLS], i
|
||||
if (channel == 4)
|
||||
channel = 3; // sensor 3 channel number is 0x04
|
||||
float temp_c = get_os_temperature(msg, sensor_id);
|
||||
if (sensor_id == 0x1d20) fprintf(stderr, "Weather Sensor THGR122N Channel %d ", channel);
|
||||
unsigned int rc = get_os_rollingcode(msg, sensor_id);
|
||||
if (sensor_id == 0x1d20) {
|
||||
fprintf(stderr, "Weather Sensor THGR122N RC %x Channel %d ", rc, channel);
|
||||
//fprintf(stderr, "Message: "); for (i=0 ; i<20 ; i++) fprintf(stderr, "%02x ", msg[i]);
|
||||
}
|
||||
else fprintf(stderr, "Weather Sensor THGR968 Outdoor ");
|
||||
fprintf(stderr, "Temp: %3.1f°C %3.1f°F Humidity: %d%%\n", temp_c, ((temp_c*9)/5)+32,get_os_humidity(msg, sensor_id));
|
||||
fprintf(stderr, "Temp: %3.1fC %3.1fF Humidity: %d%%\n", temp_c, ((temp_c*9)/5)+32,get_os_humidity(msg, sensor_id));
|
||||
}
|
||||
return 1;
|
||||
} else if (sensor_id == 0x5d60) {
|
||||
@@ -144,7 +174,7 @@ static int oregon_scientific_v2_1_parser(uint8_t bb[BITBUF_ROWS][BITBUF_COLS], i
|
||||
else if (forecast == 6) forecast_str = "Partly Cloudy";
|
||||
else if (forecast == 0xc) forecast_str = "Sunny";
|
||||
float temp_c = get_os_temperature(msg, 0x5d60);
|
||||
fprintf(stderr,"Weather Sensor BHTR968 Indoor Temp: %3.1f°C %3.1f°F Humidity: %d%%", temp_c, ((temp_c*9)/5)+32, get_os_humidity(msg, 0x5d60));
|
||||
fprintf(stderr,"Weather Sensor BHTR968 Indoor Temp: %3.1fC %3.1fF Humidity: %d%%", temp_c, ((temp_c*9)/5)+32, get_os_humidity(msg, 0x5d60));
|
||||
fprintf(stderr, " (%s) Pressure: %dmbar (%s)\n", comfort_str, ((msg[7] & 0x0f) | (msg[8] & 0xf0))+856, forecast_str);
|
||||
}
|
||||
return 1;
|
||||
@@ -162,7 +192,7 @@ static int oregon_scientific_v2_1_parser(uint8_t bb[BITBUF_ROWS][BITBUF_COLS], i
|
||||
channel = 3; // sensor 3 channel number is 0x04
|
||||
float temp_c = get_os_temperature(msg, sensor_id);
|
||||
if (sensor_id == 0xec40) fprintf(stderr, "Thermo Sensor THR228N Channel %d ", channel);
|
||||
fprintf(stderr, "Temp: %3.1f°C %3.1f°F\n", temp_c, ((temp_c*9)/5)+32);
|
||||
fprintf(stderr, "Temp: %3.1fC %3.1fF\n", temp_c, ((temp_c*9)/5)+32);
|
||||
}
|
||||
return 1;
|
||||
} else if (sensor_id == 0xec40 && num_valid_v2_bits==129) {
|
||||
@@ -174,7 +204,7 @@ static int oregon_scientific_v2_1_parser(uint8_t bb[BITBUF_ROWS][BITBUF_COLS], i
|
||||
unsigned char rolling_code = ((msg[2] << 4)&0xF0) | ((msg[3] >> 4)&0x0F);
|
||||
float temp_c = get_os_temperature(msg, sensor_id);
|
||||
if (sensor_id == 0xec40) fprintf(stderr, "Thermo Sensor THN132N, Channel %d, Battery: %s, Rolling-code 0x%0X, ", channel, battery_low?"Low":"Ok", rolling_code);
|
||||
fprintf(stderr, "Temp: %3.1f°C %3.1f°F\n", temp_c, ((temp_c*9)/5)+32);
|
||||
fprintf(stderr, "Temp: %3.1fC %3.1fF\n", temp_c, ((temp_c*9)/5)+32);
|
||||
}
|
||||
return 1;
|
||||
} else if (num_valid_v2_bits > 16) {
|
||||
@@ -192,62 +222,62 @@ fprintf(stderr, "Message: "); for (i=0 ; i<20 ; i++) fprintf(stderr, "%02x ", ms
|
||||
static int oregon_scientific_v3_parser(uint8_t bb[BITBUF_ROWS][BITBUF_COLS], int16_t bits_per_row[BITBUF_ROWS]) {
|
||||
|
||||
// Check stream for possible Oregon Scientific v3 protocol data (skip part of first and last bytes to get past sync/startup bit errors)
|
||||
if ((((bb[0][0]&0xf) == 0x0f) && (bb[0][1] == 0xff) && ((bb[0][2]&0xc0) == 0xc0)) ||
|
||||
if ((((bb[0][0]&0xf) == 0x0f) && (bb[0][1] == 0xff) && ((bb[0][2]&0xc0) == 0xc0)) ||
|
||||
(((bb[0][0]&0xf) == 0x00) && (bb[0][1] == 0x00) && ((bb[0][2]&0xc0) == 0x00))) {
|
||||
int i,j;
|
||||
unsigned char msg[BITBUF_COLS] = {0};
|
||||
unsigned int sync_test_val = (bb[0][2]<<24) | (bb[0][3]<<16) | (bb[0][4]<<8);
|
||||
int dest_bit = 0;
|
||||
int pattern_index;
|
||||
// Could be extra/dropped bits in stream. Look for sync byte at expected position +/- some bits in either direction
|
||||
for(pattern_index=0; pattern_index<16; pattern_index++) {
|
||||
unsigned int mask = (unsigned int)(0xfff00000>>pattern_index);
|
||||
unsigned int pattern = (unsigned int)(0xffa00000>>pattern_index);
|
||||
unsigned int pattern2 = (unsigned int)(0xff500000>>pattern_index);
|
||||
unsigned int pattern3 = (unsigned int)(0x00500000>>pattern_index);
|
||||
//fprintf(stderr, "OS v3 Sync nibble search - test_val=%08x pattern=%08x mask=%08x\n", sync_test_val, pattern, mask);
|
||||
if (((sync_test_val & mask) == pattern) ||
|
||||
((sync_test_val & mask) == pattern2) ||
|
||||
((sync_test_val & mask) == pattern3)) {
|
||||
// Found sync byte - start working on decoding the stream data.
|
||||
// pattern_index indicates where sync nibble starts, so now we can find the start of the payload
|
||||
int start_byte = 3 + (pattern_index>>3);
|
||||
int start_bit = (pattern_index+4) & 0x07;
|
||||
//fprintf(stderr, "Oregon Scientific v3 Sync test val %08x ok, starting decode at byte index %d bit %d\n", sync_test_val, start_byte, start_bit);
|
||||
j = start_bit;
|
||||
for (i=start_byte;i<BITBUF_COLS;i++) {
|
||||
while (j<8) {
|
||||
unsigned char bit_val = ((bb[0][i] & (0x80 >> j)) >> (7-j));
|
||||
int i,j;
|
||||
unsigned char msg[BITBUF_COLS] = {0};
|
||||
unsigned int sync_test_val = (bb[0][2]<<24) | (bb[0][3]<<16) | (bb[0][4]<<8);
|
||||
int dest_bit = 0;
|
||||
int pattern_index;
|
||||
// Could be extra/dropped bits in stream. Look for sync byte at expected position +/- some bits in either direction
|
||||
for(pattern_index=0; pattern_index<16; pattern_index++) {
|
||||
unsigned int mask = (unsigned int)(0xfff00000>>pattern_index);
|
||||
unsigned int pattern = (unsigned int)(0xffa00000>>pattern_index);
|
||||
unsigned int pattern2 = (unsigned int)(0xff500000>>pattern_index);
|
||||
unsigned int pattern3 = (unsigned int)(0x00500000>>pattern_index);
|
||||
//fprintf(stderr, "OS v3 Sync nibble search - test_val=%08x pattern=%08x mask=%08x\n", sync_test_val, pattern, mask);
|
||||
if (((sync_test_val & mask) == pattern) ||
|
||||
((sync_test_val & mask) == pattern2) ||
|
||||
((sync_test_val & mask) == pattern3)) {
|
||||
// Found sync byte - start working on decoding the stream data.
|
||||
// pattern_index indicates where sync nibble starts, so now we can find the start of the payload
|
||||
int start_byte = 3 + (pattern_index>>3);
|
||||
int start_bit = (pattern_index+4) & 0x07;
|
||||
//fprintf(stderr, "Oregon Scientific v3 Sync test val %08x ok, starting decode at byte index %d bit %d\n", sync_test_val, start_byte, start_bit);
|
||||
j = start_bit;
|
||||
for (i=start_byte;i<BITBUF_COLS;i++) {
|
||||
while (j<8) {
|
||||
unsigned char bit_val = ((bb[0][i] & (0x80 >> j)) >> (7-j));
|
||||
|
||||
// copy every bit from source stream to dest packet
|
||||
msg[dest_bit>>3] |= (((bb[0][i] & (0x80 >> j)) >> (7-j)) << (7-(dest_bit & 0x07)));
|
||||
|
||||
//fprintf(stderr,"i=%d j=%d dest_bit=%02x bb=%02x msg=%02x\n",i, j, dest_bit, bb[0][i], msg[dest_bit>>3]);
|
||||
if ((dest_bit & 0x07) == 0x07) {
|
||||
// after assembling each dest byte, flip bits in each nibble to convert from lsb to msb bit ordering
|
||||
int k = (dest_bit>>3);
|
||||
unsigned char indata = msg[k];
|
||||
// flip the 4 bits in the upper and lower nibbles
|
||||
msg[k] = ((indata & 0x11) << 3) | ((indata & 0x22) << 1) |
|
||||
((indata & 0x44) >> 1) | ((indata & 0x88) >> 3);
|
||||
}
|
||||
dest_bit++;
|
||||
j++;
|
||||
}
|
||||
j=0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// copy every bit from source stream to dest packet
|
||||
msg[dest_bit>>3] |= (((bb[0][i] & (0x80 >> j)) >> (7-j)) << (7-(dest_bit & 0x07)));
|
||||
|
||||
//fprintf(stderr,"i=%d j=%d dest_bit=%02x bb=%02x msg=%02x\n",i, j, dest_bit, bb[0][i], msg[dest_bit>>3]);
|
||||
if ((dest_bit & 0x07) == 0x07) {
|
||||
// after assembling each dest byte, flip bits in each nibble to convert from lsb to msb bit ordering
|
||||
int k = (dest_bit>>3);
|
||||
unsigned char indata = msg[k];
|
||||
// flip the 4 bits in the upper and lower nibbles
|
||||
msg[k] = ((indata & 0x11) << 3) | ((indata & 0x22) << 1) |
|
||||
((indata & 0x44) >> 1) | ((indata & 0x88) >> 3);
|
||||
}
|
||||
dest_bit++;
|
||||
j++;
|
||||
}
|
||||
j=0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((msg[0] == 0xf8) && (msg[1] == 0x24)) {
|
||||
if (validate_os_checksum(msg, 15) == 0) {
|
||||
int channel = ((msg[2] >> 4)&0x0f);
|
||||
float temp_c = get_os_temperature(msg, 0xf824);
|
||||
int humidity = get_os_humidity(msg, 0xf824);
|
||||
fprintf(stderr,"Weather Sensor THGR810 Channel %d Temp: %3.1f°C %3.1f°F Humidity: %d%%\n", channel, temp_c, ((temp_c*9)/5)+32, humidity);
|
||||
fprintf(stderr,"Weather Sensor THGR810 Channel %d Temp: %3.1fC %3.1fF Humidity: %d%%\n", channel, temp_c, ((temp_c*9)/5)+32, humidity);
|
||||
}
|
||||
return 1;
|
||||
return 1; //msg[k] = ((msg[k] & 0x0F) << 4) + ((msg[k] & 0xF0) >> 4);
|
||||
} else if ((msg[0] == 0x19) && (msg[1] == 0x84)) {
|
||||
if (validate_os_checksum(msg, 17) == 0) {
|
||||
float gustWindspeed = (msg[11]+msg[10])/100;
|
||||
@@ -256,11 +286,50 @@ static int oregon_scientific_v3_parser(uint8_t bb[BITBUF_ROWS][BITBUF_COLS], int
|
||||
}
|
||||
return 1;
|
||||
} 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(stderr, "%02x ", msg[i]); fprintf(stderr, "\n");
|
||||
fprintf(stderr, " Raw: "); for (i=0 ; i<BITBUF_COLS ; i++) fprintf(stderr, "%02x ", bb[0][i]); fprintf(stderr,"\n\n");
|
||||
} else if (bb[0][3] != 0) {
|
||||
//fprintf(stderr, "\nPossible Oregon Scientific v3 message, but sync nibble wasn't found\n"); fprintf(stderr, "Raw Data: "); for (i=0 ; i<BITBUF_COLS ; i++) fprintf(stderr, "%02x ", bb[0][i]); fprintf(stderr,"\n\n");
|
||||
fprintf(stderr, "Message received from unrecognized Oregon Scientific v3 sensor.\n");
|
||||
fprintf(stderr, "Message: "); for (i=0 ; i<BITBUF_COLS ; i++) fprintf(stderr, "%02x ", msg[i]); fprintf(stderr, "\n");
|
||||
fprintf(stderr, " Raw: "); for (i=0 ; i<BITBUF_COLS ; i++) fprintf(stderr, "%02x ", bb[0][i]); fprintf(stderr,"\n\n");
|
||||
} else if (bb[0][0] == 0 && bb[0][1] == 0 && bb[0][2] == 0 && bb[0][5] == 0x3c) {
|
||||
//fprintf(stderr, "Raw Data: "); for (i=0 ; i<BITBUF_COLS ; i++) fprintf(stderr, "%02x ", bb[0][i]); fprintf(stderr,"\n\n");
|
||||
|
||||
int start_bit = 0;
|
||||
int start_byte = 3;
|
||||
j = start_bit;
|
||||
for (i=start_byte;i<BITBUF_COLS;i++) {
|
||||
while (j<8) {
|
||||
unsigned char bit_val = ((bb[0][i] & (0x80 >> j)) >> (7-j));
|
||||
|
||||
// copy every bit from source stream to dest packet
|
||||
msg[dest_bit>>3] |= (((bb[0][i] & (0x80 >> j)) >> (7-j)) << (7-(dest_bit & 0x07)));
|
||||
|
||||
//fprintf(stderr,"i=%d j=%d dest_bit=%02x bb=%02x msg=%02x\n",i, j, dest_bit, bb[0][i], msg[dest_bit>>3]);
|
||||
if ((dest_bit & 0x07) == 0x07) {
|
||||
// after assembling each dest byte, flip bits in each nibble to convert from lsb to msb bit ordering
|
||||
int k = (dest_bit>>3);
|
||||
unsigned char indata = msg[k];
|
||||
// flip the 4 bits in the upper and lower nibbles
|
||||
msg[k] = ((indata & 0x11) << 3) | ((indata & 0x22) << 1) |
|
||||
((indata & 0x44) >> 1) | ((indata & 0x88) >> 3);
|
||||
// Flip nibbles
|
||||
msg[k] = (msg[k] & 0xF0) >> 4 | (msg[k] & 0x0F) << 4;
|
||||
}
|
||||
dest_bit++;
|
||||
j++;
|
||||
}
|
||||
j=0;
|
||||
}
|
||||
unsigned short int ipower = power(msg);
|
||||
unsigned long itotal = total(msg);
|
||||
float total_energy = itotal/3600/1000.0;
|
||||
if (itotal)
|
||||
fprintf(stderr,"Energy Sensor CMR180 Id %x%x power: %dW, total: %luW, Total Energy: %.3fkWh\n", msg[0], msg[1], ipower, itotal, total_energy);
|
||||
else
|
||||
fprintf(stderr,"Energy Sensor cmr180 Id %x%x power: %dW\n", msg[0], msg[1], ipower);
|
||||
|
||||
//for (i=0 ; i<15 ; i++) fprintf(stderr, "%02x ", msg[i]);fprintf(stderr,"\n");
|
||||
} else if (bb[0][3] != 0 ) {
|
||||
//fprintf(stderr, "\nPossible Oregon Scientific v3 message, but sync nibble wasn't found\n");
|
||||
//fprintf(stderr, "Raw Data: "); for (i=0 ; i<BITBUF_COLS ; i++) fprintf(stderr, "%02x ", bb[0][i]); fprintf(stderr,"\n\n");
|
||||
}
|
||||
}
|
||||
else { // Based on first couple of bytes, either corrupt message or something other than an Oregon Scientific v3 message
|
||||
|
||||
@@ -796,6 +796,55 @@ static void manchester_decode(struct dm_state *demod, struct protocol_state* p,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Pulse Width Modulation. No startbit removal */
|
||||
static void pwm_raw_decode(struct dm_state *demod, struct protocol_state* p, int16_t *buf, uint32_t len) {
|
||||
unsigned int i;
|
||||
for (i = 0; i < len; i++) {
|
||||
if (p->start_c) p->sample_counter++;
|
||||
|
||||
// Detect Pulse Start (leading edge)
|
||||
if (!p->pulse_start && (buf[i] > demod->level_limit)) {
|
||||
p->pulse_start = 1;
|
||||
p->sample_counter = 0;
|
||||
// Check for first bit in sequence
|
||||
if(!p->start_c) {
|
||||
p->start_c = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Detect Pulse End (trailing edge)
|
||||
if (p->pulse_start && (buf[i] < demod->level_limit)) {
|
||||
p->pulse_start = 0;
|
||||
if (p->sample_counter <= p->short_limit) {
|
||||
demod_add_bit(p, 1);
|
||||
} else {
|
||||
demod_add_bit(p, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Detect Pulse period overrun
|
||||
if (p->sample_counter == p->long_limit) {
|
||||
demod_next_bits_packet(p);
|
||||
}
|
||||
|
||||
// Detect Pulse exceeding reset limit
|
||||
if (p->sample_counter > p->reset_limit) {
|
||||
p->sample_counter = 0;
|
||||
p->start_c = 0;
|
||||
p->pulse_start = 0;
|
||||
|
||||
if (p->callback)
|
||||
events+=p->callback(p->bits_buffer, p->bits_per_row);
|
||||
else
|
||||
demod_print_bits_packet(p);
|
||||
|
||||
demod_reset_bits_packet(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Something that might look like a IIR lowpass filter
|
||||
*
|
||||
* [b,a] = butter(1, 0.01) -> quantizes nicely thus suitable for fixed point
|
||||
@@ -874,6 +923,9 @@ static void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx) {
|
||||
case OOK_MANCHESTER:
|
||||
manchester_decode(demod, demod->r_devs[i], demod->f_buf, len/2);
|
||||
break;
|
||||
case OOK_PWM_RAW:
|
||||
pwm_raw_decode(demod, demod->r_devs[i], demod->f_buf, len / 2);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unknown modulation %d in protocol!\n", demod->r_devs[i]->modulation);
|
||||
}
|
||||
@@ -1013,6 +1065,7 @@ int main(int argc, char **argv) {
|
||||
register_protocol(demod, &alectov1);
|
||||
register_protocol(demod, &intertechno);
|
||||
register_protocol(demod, &mebus433);
|
||||
register_protocol(demod, &fineoffset_WH2);
|
||||
|
||||
if (argc <= optind - 1) {
|
||||
usage();
|
||||
|
||||
Reference in New Issue
Block a user