Go Down

Topic: Smoke Detector ALECTO SA-30 HACKED (Read 3741 times) previous topic - next topic

digi128pci

Hi everyone,

I recently bought some smoke detectors that communicate wirelessly 433 MHz.

I was wondering if i could receive the data like my KAKU devices.

The idea is to send an HTTP post to a SMS gateway when there is smoke detected to warn me.

Anyway i could not find any posts for this smoke detector so i decided to HACK it.

Components:
* arduino uno
* 433 Mhz receiver
* 433 Mhz aircoold antenna
* Scope
* Some luck

To make maters difficult there is allot of noise in the 433MHz band caused by my neighbors ...

Scope image attached

I noticed a reoccurring pattern:

A long pulse and short pulses

Basically a sync pulse and data and END pulse

I wrote a program for arduino to read the codes and timing, then decode it:

Code: [Select]


void setup()
{
 pinMode(pin, OUTPUT);
 Serial.begin(115200);
 attachInterrupt(0, pinChanged, CHANGE);
}

void loop()
{
digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
 delay(1000);               // wait for a second
 digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
 delay(1000);               // wait for a second
}



void pinChanged() {
 static unsigned int period;
 static short state=-1;
 static unsigned short receivedBit; //Contains "bit" currently receiving
 static long receivedCode; //Contains received code
 static unsigned long lastChange=0; //Time of previous edge
 static unsigned int syncDuration=4000; //minimal time between two edges before decoding starts first pulse is +- 4000 us from SA-30
 static unsigned int min1Period, max1Period, min2Period, max2Period;

 long currentTime=micros();
 int duration=currentTime-lastChange; //Duration = Time between edges
 lastChange=currentTime;

 if (state==-1) { //Waiting for sync-bit
   // error-margin
   if ((duration > syncDuration-50) && (duration < syncDuration+50)) {
     
     Serial.print(duration);
     Serial.println("us. state 1");
     
     state = -2;

     
     return;  
     
   
 }
   else {
     return;
   }
 
 
}
 else if (state == -2) {

   if ((duration > (3750-100)) && (duration < (3750+100))) {
     Serial.print(duration);
     Serial.println("us. state 2");
     state = -3;
     
     return;
     
   }else{
     state = -1;
   }
 
}
 else if (state == -3) {
   
   if ((duration > (3800-100)) && (duration < (3800+100))) {
     Serial.print(duration);
     Serial.println("us. state 3");
     state = -4;
     
     return;
     
   }else{
     state = -1;
   }  
 
 
 
 
}
 else if (state == -4) {
     //Serial.print(duration);
     //Serial.println("us. state 0");
     
   //808-824us = High short= "1"
   //2044-2064us = Low long = "00"
   //1860-1848us = High long = "11"
   //1000-1028us = Low short = "0"
   //864-888 us = end
   // 33 pulsen + 3 start = 36 pulsen
   
   if ((duration > (600)) && (duration < (842))) {
     // High short
     Serial.println(duration);
     return;
     
     
    }else if((duration > (980)) && (duration < (1100))){
      // low short  
      Serial.println(duration);
     return;
     
    }else if((duration > (2000)) && (duration < (2100))){
      // low Long  
      Serial.println(duration);
     return;
     
    }else if((duration > (1800)) && (duration < (1900))){
      // High Long  
      Serial.println(duration);
     return;
     
    }else if((duration > (850)) && (duration < (890))){
      // High Long  
      Serial.println(duration);
      Serial.println("END");
      state = -1;
     return;

   }else{
     Serial.print("error: ");
     Serial.println(duration);
     state = -1;
   }
   
 }


}




This gave me an output:

Code: [Select]

4004us. state 1
3744us. state 2
3828us. state 3
812
2060
808
2060
808
2060
812
2060
1844
1024
1844
1028
1840
1028
800
2068
804
2064
1844
1024
808
2064
1836
1032
1836
1028
808
2064
804
2064
1844
1028
860
END


Again i found a pattern:

Syncpulse:

4004us. state 1
3744us. state 2
3828us. state 3

Data: ...

End: 860

In the data i decided to group:

808-824us = High short
2044-2064us = Low long
1860-1848us = High long
1000-1028us = Low short


High Short + Low Long = "1"
High Long + low short = "0"


digi128pci

Now decoding and printing the code received:

Code: [Select]

void setup()
{


 pinMode(pin, OUTPUT);
 Serial.begin(115200);
 attachInterrupt(0, pinChanged, CHANGE);
 
}

void loop()
{
digitalWrite(13, HIGH);   // turn the LED on (HIGH is the voltage level)
 delay(1000);               // wait for a second
 digitalWrite(13, LOW);    // turn the LED off by making the voltage LOW
 delay(1000);               // wait for a second
 
 
}



void pinChanged() {

 static short state=-1;
 static unsigned long lastChange=0; //Time of previous edge
 static unsigned int syncDuration=4000; //minimal time between two edges before decoding starts first pulse is +- 4000 us from SA-30
 static unsigned int receivedBit;                                // Contains "bit" currently receiving
 static byte decode;  //store sequence for decoding
 static unsigned int receivedCode;              // Contains received code
 static unsigned int previousCode;              // Contains previous received code
 static byte confirmed;  // wait for 3 times same code
 

 long currentTime=micros();
 int duration=currentTime-lastChange; //Duration = Time between edges
 lastChange=currentTime;

 if (state==-1) { //Waiting for sync-bit
   // error-margin
   if ((duration > syncDuration-50) && (duration < syncDuration+50)) {
     
     //Serial.print(duration);
     //Serial.println("us. state 1");
     
     state = -2;
     
     return;    
   
 }
   else {
     return;
   }
 
 
}
 else if (state == -2) {

   if ((duration > (3750-50)) && (duration < (3750+50))) {
     //Serial.print(duration);
     //Serial.println("us. state 2");
     state = -3;
     
     return;
     
   }else{
     state = -1;
   }
 
}
 else if (state == -3) {
   
   if ((duration > (3800-50)) && (duration < (3800+50))) {
     //Serial.print(duration);
     //Serial.println("us. state 3");
     state = -4;
     
     //reset vars after sync
     decode = 0;
     receivedBit = 0;
     
     
     return;
     
   }else{
     state = -1;
   }  
 
 
 
 
}
 else if (state == -4) {
     //Serial.print(duration);
     //Serial.println("us. state 0");
   
   //decode
   //808-824us = High short = "1"
   //2044-2064us = Low long = "2"
   //1860-1848us = High long = "3"
   //1000-1028us = Low short = "4"
   //864-888 us = end = "5"
   
   // possible situations
   // High Short + Low Long = "1"
   // High Long + low short = "0"
   
   // 33 pulsen + 3 start = 36 pulsen
   
   
   
   if ((duration > (700)) && (duration < (842))) {
     // High short
     decode = 1;
     //Serial.println(duration);
     return;
     
     
    }else if((duration > (980)) && (duration < (1100))){
      // low short
      if(decode == 3){
       
        // move bit
        receivedBit <<= 1;
       
         // zero
         bitClear(receivedBit,0); // Clear LSB of receivedBit
         //Serial.print("0");
       }
       decode = 0;
      //Serial.println(duration);
     return;
     
    }else if((duration > (2000)) && (duration < (2150))){
      // low Long
      if(decode == 1){
       
        // move bit
        receivedBit <<= 1;
       
       // One
        bitSet(receivedBit,0); // Set LSB of receivedBit
       //Serial.print("1");
       }
       decode = 0;
      //Serial.println(duration);
     return;
     
    }else if((duration > (1750)) && (duration < (1900))){
      // High Long
      decode = 3;
      //Serial.println(duration);
     return;
     
    }else if((duration > (850)) && (duration < (890))){
      // End  
     
      //strCode += 0;
     
      //copy final code
      //Code += strCode;
     

      //Serial.println(duration);
     
      //Serial.println(" end");
      //Serial.println(receivedBit, BIN);
     
      //save old code
      previousCode = receivedCode;
      // get new code
      receivedCode = receivedBit;
     
      // old code same as new code?
      if (receivedCode == previousCode){
        confirmed++;
      }  
     
      if (confirmed >= 1) {
        Serial.println(receivedCode, BIN);
        confirmed = 0;
      }
       
      //Serial.println(Code);
      state = -1;
     return;

   }else{
     Serial.print("error: ");
     Serial.println(duration);
     state = -1;
   }
   
 }


}


This code was tested successfully with my 3 devices.
I tried grouping the smoke detectors again so they got new wireless sequence, again it worked and decoded the signal.

This is the status of the project atm.

I wanted to share my results with other people so this device can be used in other projects.

TODO:
* interface to web
* sending code to test smoke alarms (cron maybe monthly test)

hjgode

Hello digi128pci

this post is very interesting. Did you get any furter? Can you post your findings?

Is there a way to see which sensor has issued an alarm?

Is there any byte encoded showing the battery status?

I have a set of similar smoke detetctors by Pollin (I assume that the cheaper ones are all the same inside, this is true for some very cheap and high priced standard smoke detectors).

I would like to decode the signal and at least know which senor has initiated the alarm and, if possible, get a battery level or at least a warning.

Josef

ahull

A lot of these gadgets are based on the SC2262 chip (it is also used in garage door systems, burglar alarms, remote control power sockets.. you name it... ).

http://www.ebay.co.uk/itm/433Mhz-4-7M-ohm-Wireless-Smoke-Detector-Sensor-for-Burglar-Alarm-System-/290637311252?pt=UK_Burglar_Alarms&hash=item43ab556d14

.. for example...

.. if your particular device doesn't use that, it may use one of the similar Holtek devices 

There is quite a lot of information already in this forum about these two chips. Search for SC2262 or Holtek

Go Up