Skip to content

Instantly share code, notes, and snippets.

@CurlyWurly-1
Created May 13, 2017 13:22
Show Gist options
  • Save CurlyWurly-1/0e7b74b01537f6af4a4d2a80896fd558 to your computer and use it in GitHub Desktop.
Save CurlyWurly-1/0e7b74b01537f6af4a4d2a80896fd558 to your computer and use it in GitHub Desktop.
A pair of Arduino UNO sketches to decrypt and spoof 433 MHz "static code" communication
/*
sketch : sniffer_433_RX (sister of "sniffer_433_TX")
Author : Peter Matthews (CurlyWurly) May 2017
Desc : When a static 433 transmission is received, a "int codez[]=.." line is output to the serial bus.
Copy this line and paste it into the the sister sketch "sniffer_433_TX"
INFORMATION
N.B. Connect pin 2 (rxpin) to the RX module output
N.B. Copy the output "int codez[] = ...." from serial bus and copy into the sister sketch "Sniffer_433_TX"
N.B. This sniffer sketch just outputs a set value of 35 in code[0]. This means that you may have to
experiment using a different "repeat" value (usually a value of 15 - 45) when used in the "TX" sketch
N.B. The code structure is contained from code[0] to code[n] and is defined as:
code[0] - No. of times to repeat the code
code[1] - No. of pulses (Hi/low combination) - This means it is half the total number of Hi and Low states
code[2] - Wait unit time (Hi and Low states are constructed with multiples of this)
code[3] - First HIGH state multiplier - multiply with code[2]
code[4] - First LOW state multiplier - multiply with code[2]
....
code[n] - last LOW state multiplier
The first pulse is made up of code[3] and code[4]
and the second pulse is made up of code[5] and code[6]
*/
#define rxPin 2 //Input from receiver
#define maxState 300 //Maximum States (Halve for pulses, will detect "pulse trains" up to 75 pulses long)
bool pinstate; // State of input pin - Hi(1) or Low(0)
int stateCount; // State change counter
int i; // Array counter
int low1; // Index of Low period 1
int low2; // Index of Low period 2
int low3; // Index of Low period 3
int low4; // Index of Low period 4
unsigned long T_array[maxState]; // Array of HiLo pulse lengths (starts with Hi)
unsigned long same_cntr; // "Still Same State" Counter (arbitrary
unsigned long minlengthHI; // Minimum Hi pulse length in us
unsigned long maxlengthHI; // Maximum Hi pulse length in us
unsigned long minlengthLOW; // Minimum Lo pulse length in us
unsigned long maxlengthLOW; // Maximum Lo pulse length in us
unsigned long pulseLen; // pulse length in us
unsigned long startTime; // Start Time of pulse in us
unsigned long endTime; // End Time of pulse in us
unsigned long unitlen; // lowest pulse length in us (assumed L.C.Denominator)
//*********************************************************************************************
void setup() {
//*********************************************************************************************
pinMode(rxPin, INPUT); // initialize input pin used for input signal
Serial.begin(57600); // Set up Serial baud rate
pinstate = 0; // prepare stored version of pin state to start as "low"
startTime = micros(); // Store first "Start time"
same_cntr = 0; // initialise
stateCount = 0; // initialise
minlengthHI = 9999; // initialise
maxlengthHI = 0; // initialise
minlengthLOW = 9999; // initialise
maxlengthLOW = 0; // initialise
}
//*********************************************************************************************
void loop() {
//*********************************************************************************************
// If no state change, then increment same_cntr
if (pinstate == digitalRead(rxPin)) {
same_cntr++;
}
else
{
endTime = micros(); //Record the end time of the read period.
pinstate = !pinstate;
// If there has been a input state change, then use "same_cntr"
// to arbitrarily check if pulse length is acceptable
if (same_cntr < 10 || same_cntr > 10000 ) {
// if you are here, then pulse length is either too short or too long, so reset variables
startTime = endTime;
same_cntr = 0;
stateCount = 0;
minlengthHI = 9999;
maxlengthHI = 0;
minlengthLOW = 9999;
maxlengthLOW = 0;
}
else
{
// if you are here, then there has been a state change and pulse length is OK
pulseLen = endTime - startTime; // Calculate Pulse length in us
startTime = endTime; // Remember start time for next state change
same_cntr = 0; // Initialise "Same State" counter
T_array[stateCount] = pulseLen; // Store Pulse Length
// Remember the max/min time extremes for each state
if (pinstate == false) {
if (pulseLen > maxlengthHI) { maxlengthHI = pulseLen; };
if (pulseLen < minlengthHI) { minlengthHI = pulseLen; }
} else {
if (pulseLen > maxlengthLOW) { maxlengthLOW = pulseLen; };
if (pulseLen < minlengthLOW) { minlengthLOW = pulseLen; };
}
// Keep storing data up to "maxState" times
if (stateCount < maxState) {
stateCount++;
} else {
//********************************************************************************
// If you are here, then we have reached the "MaxState" number of time lengths,
// so now we interpret the array data to determine where the repeating
// patterns are, so that we can output the "code" to serial before trying again
//********************************************************************************
stateCount = 0;
// First, we detect the first 4 longest LOW states
low1 = 0;
low2 = 0;
low3 = 0;
low4 = 0;
for(i=0; i<maxState; i=i+1){
if ( T_array[i] > ( maxlengthLOW * .80 ) )
{
if ( low1 == 0 ) {
low1 = i;
} else {
if ( low2 == 0 ) {
low2 = i;
} else {
if ( low3 == 0 ) {
low3 = i;
} else {
if ( low4 == 0 ) {
low4 = i;
}
};
};
};
};
};
// Now we check if the 3 latest pulse trains between the LOW states
// have the same number of state changes.
// If they agree, then output the data
// N.B. the first pulse train could be unreliable so it is ignored.
if ( ( ( low2 - low1 ) == ( low4 - low3 ) )
&& ( ( low3 - low2 ) == ( low4 - low3 ) )
&& ( low1 > 0 )
&& ( low2 > 0 )
&& ( low3 > 0 )
&& ( low4 > 0 ) ) {
// Re-examine pulse widths for our selected pulse train
// N.B. We start from 3rd pulse train because it is hoped it is the most reliable
minlengthHI = 9999;
maxlengthHI = 0;
minlengthLOW = 9999;
maxlengthLOW = 0;
for(i=low3+1; i<low4+1; i=i+1){
if ( ( ( i - low3 ) % 2) == 0 ) {
if (T_array[i] > maxlengthLOW) { maxlengthLOW = T_array[i]; };
if (T_array[i] < minlengthLOW) { minlengthLOW = T_array[i]; };
} else {
if (T_array[i] > maxlengthHI) { maxlengthHI = T_array[i]; };
if (T_array[i] < minlengthHI) { minlengthHI = T_array[i]; }
};
// if ( ( ( j - low3 ) >= 0 ) && ( j <= ( low4 - 2 ) ) ) {
// Serial.print(T_array[j]);
// Serial.print(", ");
// };
};
// Calculate unit length of pulses
unitlen = 0;
if ( minlengthLOW < ( minlengthHI / 2 )) {
unitlen = minlengthLOW ;
} else {
unitlen = ( ( minlengthHI + minlengthLOW ) / 2 );
};
// Output deciphered data for TX sketch
Serial.print("int codez[] = {35,");
Serial.print( ( low4 - low3 ) / 2 );
Serial.print(",");
Serial.print(unitlen);
for(i=low3+1; i<low4+1; i=i+1){
Serial.print(",");
// Serial.print( (T_array[i] / unitlen) );
Serial.print( ( (T_array[i] * 10) + (5 * unitlen) ) / (10 * unitlen) );
};
Serial.println("};");
};
// Output deciphered data as HnLn
// Serial.print("Pulses = ");
// Serial.print( ( low4 - low3 ) / 2 );
// Serial.print(", Unit length = ");
// Serial.print(unitlen);
// Serial.print(", Code = ");
// for(i=low3+1; i<low4+1; i=i+1){
// if ( ( ( i - low3 ) % 2) == 0 ) {
// Serial.print("L");
// Serial.print( ( (T_array[i] * 10) + (5 * unitlen) ) / (10 * unitlen) );
// Serial.print(", ");
// } else {
// Serial.print("H");
// Serial.print( ( (T_array[i] * 10) + (5 * unitlen) ) / (10 * unitlen) );
// };
// };
// Serial.println(" ");
// };
// Reset "extreme" variables
minlengthHI = 99999;
maxlengthHI = 0;
minlengthLOW = 99999;
maxlengthLOW = 0;
};
//*******************************************
// The above is part of the decipering code *
//*******************************************
};
};
}
/*
sketch : sniffer_433_TX (sister of "sniffer_433_RX")
Author : Peter Matthews (CurlyWurly) May 2017
Desc : Copy the "int codez[]=.." line manufactured by the sister sketch "sniffer_433_RX"
and paste it into this sketch so that this sketch can spoof the original transmitter.
INFORMATION
N.B. Connect pin 3 (txpin) to the TX module input
N.B. Copy the output "int codez[] = ...." from the "Sniffer_433_RX" sketch and paste where marked below
N.B. The sniffer sketch just outputs a set value of 35 in code[0]. This means that you may have to
experiment using a different "repeat" value (usually a value of 15 - 45 is OK)
N.B. The code structure is contained from code[0] to code[n] and is defined as:
code[0] - No. of times to repeat the code
code[1] - No. of pulses (Hi/low combination) - This means it is half the total number of Hi and Low states
code[2] - Wait unit time (Hi and Low states are constructed with multiples of this)
code[3] - First HIGH state multiplier - multiply with code[2]
code[4] - First LOW state multiplier - multiply with code[2]
....
code[n] - last LOW state multiplier
The first pulse is made up of code[3] and code[4]
and the second pulse is made up of code[5] and code[6]
*/
#define ldPin 13 //Onboard LED = digital pin 13
#define txPin 3 //Output to RF TX module
//*********************** Copy the output from the "Sniffer_433_RX" sketch here **************************
// int codez[] =
//**************************** and reference it in "loop()" as tx(codez); ********************************
// Maplin mains switch 1,1 ON
int code1[] = {10,25,434,1,3,1,3,1,3,3,1,1,3,3,1,1,3,3,1,1,3,1,3,1,3,3,1,1,3,3,1,1,3,3,1,1,3,3,1,1,3,3,1,1,3,3,1,1,3,3,1,1,31};
// Maplin mains switch 1,1 OFF
int code2[] = {10,25,432,1,3,1,3,1,3,3,1,1,3,3,1,1,3,3,1,1,3,1,3,1,3,3,1,1,3,3,1,1,3,3,1,1,3,3,1,1,3,3,1,1,3,3,1,1,3,1,3,1,31};
// 1byOne driveway alarm
int code3[] = {41,18,362,1,3,1,3,1,1,3,1,3,1,3,3,1,1,3,1,3,3,1,1,3,3,1,3,1,1,3,1,3,1,3,1,3,1,3,18};
// Friedland PIR alarm
int code4[] = {15,21,754,1,1,1,1,1,1,1,4,1,5,1,4,1,4,1,5,1,6,1,4,1,7,1,4,1,7,1,3,1,5,1,5,1,5,1,5,1,4,1,5,1,27};
void tx(int code);
//************************************************************
void setup() {
//************************************************************
pinMode(ldPin, OUTPUT);
pinMode(txPin, OUTPUT);
Serial.begin(57600); // Set up Serial baud rate
}
//************************************************************
void loop() {
//************************************************************
tx(code1);
delay(2000);
tx(code2);
delay(2000);
tx(code3);
delay(2000);
tx(code4);
delay(2000);
}
//************************************************************
void tx(int code[]){
//************************************************************
digitalWrite(ldPin, HIGH); // LED pin on
for(int j=0; j<code[0]; j=j+1 ){
for(int i=3; i<((code[1]*2)+3); i=i+1 ){
if ( ( ( i ) % 2) == 0 ) {
digitalWrite(txPin, LOW);
} else {
digitalWrite(txPin, HIGH);
};
for(int k=0; k<code[i]; k=k+1){
delayMicroseconds(code[2]);
};
};
};
digitalWrite(ldPin, LOW); // LED pin off
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment