ESP8266 and C1101 433 MHz KERUI Receiver

I wanted to include a cheap magnetic window sensor into my MQTT system using ESP8266 connected to WIFI.

I came across this nice sensor which emits 433 MHz signals for OPEN, CLOSE, TAMPER and LOW BATTERY. It costs around 6-7 € per piece which is rather low compared to other sensors.

KERUI D026 on BangGood or directly in China, which makes it even cheaper. 

Neuftech CC1101 Wireless Module on Amazon for 6 €, if you have time you can get it for 3 €. 

Required libraries:

  • https://github.com/sui77/rc-switch
  • https://github.com/LSatan/RCSwitch-CC1101-Driver-Lib

The Code

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <ELECHOUSE_CC1101_RCS_DRV.h>
#include <RCSwitch.h>

const char* ssid     = "_REMOVED_";
const char* password = "_REMOVED_";
const char* mqtt_server = "mqtt";
char clientRSSI[50];
const int PIN_WIFI_LED = D4;
const int PIN_433_LED = D0;

RCSwitch c1101 = RCSwitch();

void callback(char* topic, byte* payload, unsigned int length);

WiFiClient espClient;
PubSubClient client(mqtt_server, 1883, callback, espClient);

void callback(char* topic, byte* payload, unsigned int length) {
}

void reconnectWifi() {
    WiFi.begin(ssid, password); 
    while (WiFi.status() != WL_CONNECTED) {
      delay(500);
    }
    String str = String(WiFi.RSSI());
    str.toCharArray(clientRSSI, str.length()+1);
}

void reconnectMQTT() {
  
  while (!client.connected()) {
   
    if (client.connect("Generic433","sensors/433/health", 0, true, "offline")) {
      client.setCallback(callback);      

      client.publish("sensors/433/rssi", clientRSSI, true);
      client.publish("sensors/433", "started", true);
      client.publish("sensors/433/health", "online", true);

      digitalWrite(PIN_WIFI_LED, HIGH);
    
    } else {
      delay(1000);
    }
  }
}

void setup() {
  Serial.begin(9600);

  pinMode(PIN_WIFI_LED, OUTPUT);  
  digitalWrite(PIN_WIFI_LED, LOW);

  pinMode(PIN_433_LED, OUTPUT);  
  digitalWrite(PIN_433_LED, LOW);  
  
  ELECHOUSE_cc1101.setMHZ(433.92);
  ELECHOUSE_cc1101.Init(PA10);
  
  c1101.enableReceive(D2);

  ELECHOUSE_cc1101.SetRx();
}

unsigned long ledBackoffTimer = 0;


void loop() {

  if(ledBackoffTimer != 0) {
    if(millis() > (ledBackoffTimer + 50)) {
      ledBackoffTimer = 0;
      digitalWrite(PIN_433_LED, LOW);
    }
  }
  
  if (c1101.available()) {

    forward(c1101.getReceivedValue(), c1101.getReceivedBitlength());
    c1101.resetAvailable();

    ledBackoffTimer = millis();
    digitalWrite(PIN_433_LED, HIGH);
  }

  if(WiFi.status() != WL_CONNECTED) {
    digitalWrite(PIN_WIFI_LED, LOW);
    reconnectWifi();
  }
 
  if (!client.connected()) {
    digitalWrite(PIN_WIFI_LED, LOW);
    reconnectMQTT();
  }

  client.loop(); 
}

unsigned long lastReceived = 0;
unsigned long lastDecimal = 0;

void forward(unsigned long decimal, unsigned int length) {

  if(lastDecimal == decimal && millis() < lastReceived + 2000) {
    return;
  }
  else {
    lastDecimal = decimal;
    lastReceived = millis();
    
    const char* bits = bitstring(decimal, length);
  
    char total[250];
    sprintf(total, "{\"decimal\":\"%d\", \"binary\":\"%s\"}", decimal, bits);
  
    client.publish("sensors/433/receive", total);
  }
}

static char * bitstring(unsigned long decimal, unsigned int bitLength) {
  static char bin[64]; 
  unsigned int i=0;

  while (decimal > 0) {
    bin[32+i++] = ((decimal & 1) > 0) ? '1' : '0';
    decimal = decimal >> 1;
  }

  for (unsigned int j = 0; j< bitLength; j++) {
    if (j >= bitLength - i)
      bin[j] = bin[ 31 + i - (j - (bitLength - i)) ];
    else
      bin[j] = '0';
  }

  bin[bitLength] = '\0';  
  return bin;
}

MQTT Output

The above program transparently forwards all received signals from 433 MHz receiver to a MQTT server:

{"decimal":"1242378", "binary":"000100101111010100001010"}

It de-bounces multiple signals from same cycle and publishes only one instance of the event to MQTT. In good conditions I receive up to 18 instances of the same event. Sensors which are far away make it to 4 or 5 events.

Raw Output on Serial

When dumping out on the serial line you get this:

OPEN

Decimal: 10275310 (24Bit) Binary: 100111001100100111101110 Tri-State: not applicable PulseLength: 305 microseconds Protocol: 1
Raw data: 9471,943,357,272,1007,278,972,932,334,930,320,933,352,298,959,296,954,962,321,944,336,306,947,338,922,970,313,299,26,939,310,945,322,960,295,964,312,947,323,332,942,940,309,946,319,962,300,316,959,

CLOSE

Decimal: 10275303 (24Bit) Binary: 100111001100100111100111 Tri-State: not applicable PulseLength: 305 microseconds Protocol: 1
Raw data: 9506,919,384,253,1000,282,975,923,346,935,325,942,341,300,948,311,972,921,337,955,310,319,963,302,949,964,302,324,958,295,960,948,319,934,326,948,312,947,322,332,943,316,946,958,330,945,313,950,296,

TAMPER

Decimal: 10275307 (24Bit) Binary: 100111001100100111101011 Tri-State: not applicable PulseLength: 306 microseconds Protocol: 1
Raw data: 9493,962,314,328,951,311,945,941,329,952,318,939,336,294,958,330,945,939,310,959,302,316,959,322,950,937,324,301,955,318,955,943,325,932,319,954,309,970,303,327,945,939,323,306,968,941,311,946,323,

UNDERVOLTAGE

Decimal: 10275311 (24Bit) Binary: 100111001100100111101111 Tri-State: not applicable PulseLength: 307 microseconds Protocol: 1
Raw data: 9484,969,325,305,944,330,951,944,296,958,323,940,335,293,966,309,970,926,336,943,337,306,948,312,973,945,312,325,938,310,940,955,318,957,309,944,311,954,319,311,970,941,296,965,311,946,323,958,296,

The first 20 bits represent the ID of the sensor, the last 4 bits represent the state:

OPEN        10011100110010011110  1110
CLOSE       10011100110010011110  0111
TAMPER      10011100110010011110  1011
LOW VOLTAGE 10011100110010011110  1111

on battery insertion, OPEN is triggered

LOW VOLTAGE is fired at around 6V.

The wiring and driver was taken from RCSwitch-CC1101-Driver-Lib – thanks to LSatan.

Finally

This is a 12 € solution (6 € ESP8266 and 6 € C1101 receiver) to receive 433 MHz signals from a wide range of C1101 compatible devices and bridge them to WIFI. It allows you to basically connect any of those cheap devices into a system. The antenna is fairly good and sensors are recognized practically anywhere in the house. On free areas up to 300 m.

The actual processing of the events can be done at a MQTT subscriber somewhere offloaded on the backend.

This also shows how weak the security of the most systems actually is. It is a few minutes job to fool most of the cheap alarm systems which do not use code rotation or other concepts. Of course it also acts a a simple 433 MHz sniffer which receives all signals which do not belong to „your system“. LOL.