You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 23 Next »

Overview


Specifications


Product:


Transmitter:

SpecificationValue
Model00606TXA1
FCC IDRNE606TXA1

Receiver:

SpecificationValue
Model00606TXA1
FCC IDRNE606TXA1


RTL_433 Reverse Engineering 

Using rtl_433: 


> rtl_433

Output: 

rtl_433 version 19.08-18-g8eecdbb branch master at 201909241811 inputs file rtl_tcp RTL-SDR
Use -h for usage help and see https://triq.org/ for documentation.
Trying conf file at "rtl_433.conf"...
Trying conf file at "/Users/john.mehan/.config/rtl_433/rtl_433.conf"...
Trying conf file at "/usr/local/etc/rtl_433/rtl_433.conf"...
Trying conf file at "/etc/rtl_433/rtl_433.conf"...

Consider using "-M newmodel" to transition to new model keys. This will become the default someday.
A table of changes and discussion is at https://github.com/merbanan/rtl_433/pull/986.

Registered 108 out of 138 device decoding protocols [ 1-4 8 11-12 15-17 19-21 23 25-26 29-36 38-60 63 67-71 73-100 102-103 108-116 119 121 124-128 131-138 ]
Found Rafael Micro R820T tuner
Exact sample rate is: 250000.000414 Hz
[R82XX] PLL not locked!
Sample rate set to 250000 S/s.
Tuner gain set to Auto.
Tuned to 433.920MHz.
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
time : 2019-10-03 11:08:26
model : Acurite 606TX Sensor id : 120
Battery : OK Temperature: 25.9 C Integrity : CHECKSUM


> rtl 

Detected OOK package	2019-10-03 11:49:46
Analyzing pulses...
Total count:  237,  width: 744.45 ms		(186112 S)
Pulse width distribution:
 [ 0] count:  237,  width:  508 us [496;516]	( 127 S)
Gap width distribution:
 [ 0] count:  154,  width: 1932 us [1924;1944]	( 483 S)
 [ 1] count:   70,  width: 3884 us [3876;3896]	( 971 S)
 [ 2] count:    5,  width:  468 us [460;476]	( 117 S)
 [ 3] count:    6,  width: 8520 us [8516;8532]	(2130 S)
 [ 4] count:    1,  width:  708 us [708;708]	( 177 S)
Pulse period distribution:
 [ 0] count:  154,  width: 2440 us [2432;2456]	( 610 S)
 [ 1] count:   70,  width: 4392 us [4380;4408]	(1098 S)
 [ 2] count:    5,  width:  972 us [972;980]	( 243 S)
 [ 3] count:    6,  width: 9032 us [9028;9040]	(2258 S)
 [ 4] count:    1,  width: 1220 us [1220;1220]	( 305 S)
Level estimates [high, low]:  15939,   1378
RSSI: -0.1 dB SNR: 10.6 dB Noise: -10.7 dB
Frequency offsets [F1, F2]:   18554,      0	(+70.8 kHz, +0.0 kHz)
Guessing modulation: Pulse Position Modulation with fixed pulse width
Attempting demodulation... short_width: 468, long_width: 708, reset_limit: 8536, sync_width: 0
Use a flex decoder with -X 'n=name,m=OOK_PPM,s=468,l=708,g=712,r=8536'
pulse_demod_ppm(): Analyzer Device 
bitbuffer:: Number of rows: 25 
[00] { 0}           : 
[01] { 0}           : 
[02] { 0}           : 
[03] { 0}           : 
[04] { 0}           : 
[05] { 0}           : 
[06] { 0}           : 
[07] { 0}           : 
[08] { 0}           : 
[09] { 0}           : 
[10] { 0}           : 
[11] { 0}           : 
[12] { 0}           : 
[13] { 0}           : 
[14] { 0}           : 
[15] { 0}           : 
[16] { 0}           : 
[17] { 0}           : 
[18] { 0}           : 
[19] { 0}           : 
[20] { 0}           : 
[21] { 0}           : 
[22] { 0}           : 
[23] { 0}           : 
[24] { 0}           : 
... Maximum number of rows reached. Message is likely truncated.

So, this is showing us that it detected OOK modulation but when it tries to convert to bits, it fails... 

What is an OOK package?

On Off Keying is a form of Amplitude Shift Keying (ASK) limited to two values. If you use ASK with only two values, you are essentially using OOK.



Finding the Bits

Install Let's install Universal Radio Hacker.

pip3 install urh


Running URH

> urh


From the initial window, select File → Record Signal

Click Start button and once you noticed your signal, click Stop and Save. Close the window 

The Interpretation Screen should appear.

  • zoom in on the first burst.
  • Set the signal view to Demodulated.

Looking at the entire signal, we see that it sends the identical information 7 times. 


This particular signal starts every bit by turning ON the RF signal and then turning if off for either 2 or 4 milliseconds. Staying off for 2 ms signifies a value of 0 while staying off for 4 ms signifies a value of 1.


What we deduced from looking at the signal:

PulseDelay
On Pulse0.5 ms
0 value2 ms off between On Pulse
1 value

4 ms off between On Pulse

Stop Pulse0.5 ms

9 ms delay between repeats

repeat the whole thing a total of 7 times.


If we look at just one of the pulses, we see that it contains 32 bits or 4 bytes:

We received the following data:

1110 0110 1000 0001 0011 0110 0001 0011  (E6 81 36 13 hex)



The Protocol

The protocol for this device is publish at the following URL: 

http://www.osengr.org/WxShield/Downloads/Weather-Sensor-RF-Protocols.pdf

Details

The protocol for the AcuRite 00606TX is:

 


All in nibbles (4 bits). 

Rolling Code(2), Status(1), Temperature (signed binary), Hash Code


Data being sent:

NiblePurposeOur ValueDescription
1-2Rolling CodeE6

The rolling code randomly generated when the transmitter powers up.

After the receiver receives it's first rolling code, it will not accept messages with a different code unless rebooted.

3Status8

A status of 8 signifies that the batter is ok.

The status nibble's MSB is a "battery okay" flag which is normally one. It goes to zero when the battery drops below about 2.6 volts or so.

4-6Temperature136

The temperature with 1 decimal place. 

A temperature of 31.0C = 31.0*10 = 310 dec = 136 hex

7-8Hash13Hash computed using 


Checksum/Hash

This sensor does not use a simple checksum or even a more advanced CRC. Instead data integrity is verified by a hash code, generated by multiplying the message bits with the byte sequence generated by a linear feedback shift register (LFSR). This algorithm has been referred to as "an LFSR-based Toeplitz hash" in some of the literature.


Algorithm

1. Generate LSFR sequence equal to the length of the message.

In our case, our message is 32 bits long, so we will need 32 values plus an addition 5 since we are going to start at the fifth byte in the sequence.


  • Start with an 8-bit register initialized to the value 0x7C (0111 1100)
  • Generate a number of values equal to the message size in bits by repeating the following operations once for each bit.

• Rotate the register right one bit.

• If the bit shifted out of the LSB and into the MSB during the rotation was a one, then exclusive-or the value 0x18 into the register (i.e. flip the state of bits 3 and 4). Do this after the rotate operation.

• The register value after these two operations is the sequence value to be stored. Perform these steps once for each bit in the message. If the message contains 32 bits for example (as with the F007TH message) then you will need to generate a sequence of 40 bytes. Because this sequence does not depend on the data message contents and can be pre-computed once and stored to save time.


Start ValueShift Right

XOR with 0x18 if MSB =1

(flip bits 3 and 4)

XorValue
10111 1100 (0x7C)→ 0011 1110 NO -0011 1110 (0x3e)
20011 1110 (0x3e)→ 0001 1111NO-0001 1111 (0x1f)
30001 1111 (0x1f)→ 1000 1111YESxor 0x181001 0111 (0x97)
41001 0111 (0x97)→ 1100 1011YESxor 0x181101 0011 (0xd3)
51101 0011 (0xd3)→ 1110 1001YESxor 0x181111 0001 (0xf1)
...




321000 0110 (0x86)→ 0100 0011NO-0100 0011 (0x43)
...




370011 0001 (0x31)→ 1001 1000YESxor 0x181000 000 (0x80)


Values


2. Combines the LSFR sequence with message bits to form the final hash value

To compute the message hash value, sequence through the 24 message bits in the order they were received. Since everything here is big-endian, that means proceeding from MSB to LSB. Start by initializing the hash register to the value 0x00. As the message bits are read, for every bit in the message that is a one, exclusive-or the corresponding value (+5) from the LSFR sequence into the hash register.

For example, if the 10th bit is a one, then take the 15th value from the LFSR sequence and exclusive-or it into the hash register. If the message were all zeros, then nothing would be added to the hash register and the result would be the initial value of 0x00.

From MSB to LSB for message 1110 0110 1000 0001 0011 0110  (E6 81 36 hex)

Register ValueIndexValueValue=1?Calculation

New Register Value

(xor with LSFR Sequence starting at the 5th (0xF1)

0023 -MSB1Yes00 xor f1f1
f1221Yesf1 xor e011
11211Yes11 xor 7061
...




1300No-13


Checksum/Hash Source Code

#define MESSAGE_SIZE 32
#define OFFSET 4

uint8_t LSFR_sequence[MESSAGE_SIZE] = {0};

void calculateLSFR() {
	int i;
	uint8_t reg = 0x7C;
	uint8_t temp_reg = 0;

	for (i = 0; i < MESSAGE_SIZE; i++) {
		temp_reg = reg & 0x01;
		reg >>= 1;
		reg |= (temp_reg << 7);

		if (temp_reg) {
			reg ^= 0x18;
		}

		LSFR_sequence[i] = reg;
		//printf("%02x\n", LSFR_sequence[i]);
	}
}

uint8_t combineLSFR(uint8_t len, uint8_t *data) {
	uint8_t hash_reg = 0; // not 0x64
	int byte_idx, bit_idx;
	uint8_t byte, bit;
	//printf("***COMBINE\n");

	for (byte_idx = 0; byte_idx < len; byte_idx++) {
		for (bit_idx = 7; bit_idx >= 0; bit_idx--) {
			bit = (data[byte_idx] & (1 << bit_idx)) >> bit_idx;
			if (bit) {
				hash_reg ^= LSFR_sequence[byte_idx * 8 + (7 - bit_idx) + OFFSET];
				//printf("[%d]: %02x\n", byte_idx * 8 + (7 - bit_idx), hash_reg);
			}
			bit = 0;
		}
	}

	return hash_reg;
}

uint8_t Checksum(int length, uint8_t *buff) {
	calculateLSFR();
	return combineLSFR(length, buff);
}


Sending Temperatures to the Receiver

In an effort to send our own temperatures to the receiver, we put together a program running on an ESP8266 (Wemos mini) connected with RF transmitter.

Transmitter Code

const int TX_PIN = 4;   // ESP8266 pin D2

typedef struct  {
    boolean power;
    int duration;   // micro seconds
} signal;

const signal SHORT_ON { true, 500 };
const signal SHORT_OFF { false, 2000 };
const signal LONG_ON { true, 850 }; // not used
const signal LONG_OFF { false, 4000 };
const signal STOP_OFF { false, 500 };
const int REST = 9000; // 9 ms gap


// Here's a temperature of 24.5 forever...
//
signal sig_1 [] {
    SHORT_ON,             // start bit
    SHORT_OFF, SHORT_ON,  // a zero (0) bit
    LONG_OFF, SHORT_ON,   // a one (1) bit
    LONG_OFF, SHORT_ON,   // a one (1) bit
    LONG_OFF, SHORT_ON,   // a one (1) bit
    
    LONG_OFF, SHORT_ON,   // a one (1) bit
    SHORT_OFF, SHORT_ON,  // a zero (0) bit
    SHORT_OFF, SHORT_ON,  // a zero (0) bit
    SHORT_OFF, SHORT_ON,  // a zero (0) bit
    
    LONG_OFF, SHORT_ON,   // a one (1) bit
    SHORT_OFF, SHORT_ON,  // a zero (0) bit
    SHORT_OFF, SHORT_ON,  // a zero (0) bit
    SHORT_OFF, SHORT_ON,  // a zero (0) bit

    SHORT_OFF, SHORT_ON,  // a zero (0) bit
    SHORT_OFF, SHORT_ON,  // a zero (0) bit
    SHORT_OFF, SHORT_ON,  // a zero (0) bit
    SHORT_OFF, SHORT_ON,  // a zero (0) bit
//    LONG_OFF, SHORT_ON,   // a one (1) bit

    LONG_OFF, SHORT_ON,   // a one (1) bit
    LONG_OFF, SHORT_ON,   // a one (1) bit
    LONG_OFF, SHORT_ON,   // a one (1) bit
    LONG_OFF, SHORT_ON,   // a one (1) bit

    SHORT_OFF, SHORT_ON,  // a zero (0) bit
    LONG_OFF, SHORT_ON,   // a one (1) bit
    SHORT_OFF, SHORT_ON,  // a zero (0) bit
    LONG_OFF, SHORT_ON,   // a one (1) bit

    SHORT_OFF, SHORT_ON,  // a zero (0) bit
    SHORT_OFF, SHORT_ON,  // a zero (0) bit
    SHORT_OFF, SHORT_ON,  // a zero (0) bit
    SHORT_OFF, SHORT_ON,  // a zero (0) bit

    LONG_OFF, SHORT_ON,   // a one (1) bit
    LONG_OFF, SHORT_ON,   // a one (1) bit
    LONG_OFF, SHORT_ON,   // a one (1) bit
    SHORT_OFF, SHORT_ON,  // a zero (0) bit

    STOP_OFF, SHORT_ON    // stop bit
};


void doTransmission(signal array[67]) {

    Serial.println("Doing transmission...");
    for (int burst = 1; burst <= 7; burst++) {

        for (int idx = 0; idx < 66; ++idx ) {   // payload
            digitalWrite(TX_PIN, array[idx].power);
            delayMicroseconds( array[idx].duration );
        }
        delayMicroseconds(REST);                // rest between bursts
    }
}

void setup ( void ) {
    pinMode(TX_PIN, OUTPUT);
    Serial.begin ( 115200 );
}


void loop ( void ) {

  Serial.println("Sending...");
  doTransmission(sig_1);
  delay(10000);

}



References



  • No labels