Tag Archive: 433Mhz


More 433Mhz RF Hacking

I touched on the smoke detectors and door/window sensors I ordered last week: – here are a few more details.

The smoke detectors were £5.75 each – http://www.ebay.co.uk/itm/260990530306#ht_3800wt_1385 (all now sold out, but more available on a separate listing from the same seller – http://stores.ebay.co.uk/greatgougo)
The door/window sensors were £2.50 each – http://www.ebay.co.uk/itm/200759112077?ssPageName=STRK:MEWNX:IT&_trksid=p3984.m1439.l2649#ht_500wt_1170 (shop link if/when the listing ends – http://stores.ebay.co.uk/HI-AYY-STORE)

The RF signals broadcast by both devices are not decoded by the RFXCom receiver/transceiver RFXtrx433. This meant finding a way to receive and decode myself.

I already had a few jeenodes (http://jeelabs.com/products/jeenode) knocking about and a 433Mhz plug (http://jeelabs.com/products/ook-433-plug) – there are many alternatives available. I fired up some sketches from the jeelib library (https://github.com/jcw/jeelib/) but wasn’t getting any output when triggering the door/window sensors or the smoke detectors;

I found a discussion on the jeelabs forum (http://forum.jeelabs.net/node/87) which led me to an application called ProtocolAnalyzer (http://wiki.nethome.nu/doku.php/analyzer/start). ProtocolAnalyzer describes a real simple circuit design which brings the RF signal voltage down to a safe voltage to pump into the microphone/line-in port:

I didn’t even have the right components so I improvised:

I only had a 4K7 variable resistor rather than fixed, and I think those fixed resistors are about 370 ohm so I doubled up. I didn’t have any capacitors, so I’ve omitted for the time being but that might be the reason I’m getting slightly inconsistent results as you will see later.

I fired up ProtocolAnalyzer and immediately started to see data coming in (without activating the sensors)- this suggested my CurrentCost devices and such were probably being heard. Many of the signals were being identified as conforming to the "Pronto" protocol, but the data wasn’t very helpful (nor was the way in which it was being displayed). To read the data you had to drill-down on each record. As I ultimately wanted to compare a large result set in an attempt to find patterns and work out which bits/bytes/words meant what this wasn’t really practical.

So I disabled all of the decoders and enabled just the raw signal capture:

I could now drill down and determine the pulse spec:

Which I could then use in an Arduino sketch to capture data. I used the ookRelay2 sketch and modified the Home Easy (HEZ) decoding function to decode my new devices:

class HezDecoder : public DecodeOOK {
public:
HezDecoder () {}
// see also http://homeeasyhacking.wikia.com/wiki/Home_Easy_Hacking_Wiki
virtual char decode (word width) {
if (400 <= width && width < 1600) {
gotBit(width <= 600);
return 0;
}
if (width >= 3000 && pos >= 5) {
for (byte i = 0; i < 6; ++i)
gotBit(0);
alignTail(64); // keep last 56 bits
return 1;
}
return -1;
}
};

As soon as I activated one of the sensors data started to flood in:

[ookRelay2]
HEZ 51 85 171 42 51 3
HEZ 166 106 85 101 102 32 51 85 171 42 51 3
HEZ 153 169 90 85 153 3
HEZ 51 85 171 42 51 3
HEZ 51 83 171 42 51 3
HEZ 51 85 171 42 51 3
HEZ 166 106 85 101 102 32 51 83 169 42 51 3
HEZ 51 85 171 42 51 3
HEZ 170 86 85 102 6 50 51 85 171 42 51 3
HEZ 51 85 171 42 51 3
HEZ 204 85 171 42 51 3
HEZ 51 83 181 170 50 3
HEZ 51 85 171 42 51 3

I’m not 100% sure of the reason for the receptions (I think some protocols rebroadcast multiple times to enable validation). Nor am I sure of the reason for the discrepancies (you can see most of the packets are HEZ 51 85 171 42 51 3 but a few contain different values).

I took the most common result and recorded it along with the jumper position (presumably indicating the home code):

I followed a methodical approach of moving the jumpers and recording the result- ending up with a pattern something like:

ABCD-EFGHIJ?? IJ GH EF AB CD
NNNN-NNNNNNNN HEZ 51 51 51 51 51 3
NNNL-NNNNNNNN HEZ 51 51 51 51 179 2
NNNH-NNNNNNNN HEZ 51 51 51 51 83 3
NNLN-NNNNNNNN HEZ 51 51 51 51 43 3
NNLL-NNNNNNNN HEZ 51 51 51 51 171 2
NNLH-NNNNNNNN HEZ 51 51 51 51 75 3
NNHN-NNNNNNNN HEZ 51 51 51 51 53 3
NNHL-NNNNNNNN HEZ 44 51 51 51 181 2
NNHH-NNNNNNNN HEZ 51 51 51 51 85 3
NLNN-NNNNNNNN HEZ 51 51 51 179 50 3
NHNN-NNNNNNNN HEZ 51 51 51 83 51 3
LNNN-NNNNNNNN HEZ 51 51 51 43 51 3
HNNN-NNNNNNNN HEZ 51 51 51 53 51 3
NNNN-NNNNNNNN HEZ 51 51 51 51 51 3
NNNN-NNNNNNNL HEZ 51 51 51 51 51 3
NNNN-NNNNNNNH HEZ 51 51 51 51 51 3
NNNN-NNNNNNLN HEZ 50 51 51 51 51 3
NNNN-NNNNNNHN HEZ 51 51 51 51 51 3
NNNN-NNNNNLNN HEZ 43 51 51 51 51 3
NNNN-NNNNNHNN HEZ 53 51 51 51 51 3
NNNN-NNNNHHNN HEZ 85 51 51 51 51 3
NNNN-NNNNLLNN HEZ 171 50 51 51 51 3
NNNN-NNNHNNNN HEZ 51 53 51 51 51 3
NNNN-NNHHNNNN HEZ 51 85 51 51 51 3
NNNN-NHNNNNNN HEZ 51 51 83 51 51 3
NNNN-HNNNNNNN HEZ 51 51 53 51 51 3

So I could see that the jumpers in pairs appeared to directly affect each byte of data being returned. I think built this table to demonstrate how I think they correlate:

DDDD-AAAAAAAA
3210-76543210
A0 = Not Used
A1 = Not Used
HEZ AA32 AA54 AA76 DD32 DD10
NN = 51
NL = 43
NH = 53
LN = 179
LL = 171
LH = 181
HN = 83
HL = 75
HH = 85

Next steps:

  • Configure each of the sensors with unique jumper configurations
  • Determine and position the sensors
  • Add the 433Mhz receiver to the jeenode connected to my raspberry pi (running DomotiGa) and modify the sketch to decode these signals as well as receiving 868Mhz broadcasts from other jeenodes
  • Tweak the DomotiGa code to interpret the received data

I wrote another little shell script / python script to pull the status & current playing track name:

import xml.etree.cElementTree as XML import requests endpoint = '/MediaRenderer/AVTransport/Control' action = '"urn:schemas-upnp-org:service:AVTransport:1#GetTransportInfo"' body = '<u:GetTransportInfo xmlns:u="urn:schemas-upnp-org:service:AVTransport:1"><InstanceID>0</InstanceID><Channel>Master</Channel></u:GetTransportInfo>' headers = { 'Content-Type': 'text/xml', 'SOAPACTION': action } soap = '<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body>' + body + '</s:Body></s:Envelope>' r = requests.post('http://192.168.0.218:1400' + endpoint, data=soap, headers=headers) dom = XML.fromstring(r.content) print dom.findtext('.//CurrentTransportState') action = '"urn:schemas-upnp-org:service:AVTransport:1#GetPositionInfo"' body = '<u:GetPositionInfo xmlns:u="urn:schemas-upnp-org:service:AVTransport:1"><InstanceID>0</InstanceID><Channel>Master</Channel></u:GetPositionInfo>' headers = { 'Content-Type': 'text/xml', 'SOAPACTION': action } soap = '<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body>' + body + '</s:Body></s:Envelope>' r = requests.post('http://192.168.0.218:1400' + endpoint, data=soap, headers=headers) dom = XML.fromstring(r.content) track = {} import re print re.search('<dc:title>(.*)</dc:title>', dom.findtext('.//TrackMetaData'), re.IGNORECASE).group(1)

See:

I also got lighttpd & php5 up and running on my raspberry pi running domotiga so I can access the web interface:

Now I’m trying to get the 433Mhz door/window sensors connected but first I need to work out how to decode the rf packets. I tapped into my jeelabs 433Mhz ook plug and built a circuit similar to that described here: http://wiki.nethome.nu/doku.php/analyzer/hardware

I didn’t have all the right bits handy but it worked regardless!

After doing some captures in Protcol Analyzer I think I have determined the pulse width to be around 1500μs:

But I’m still at a bit of a loss how to then decode (I’m hoping I can somehow separate each "data packet" then compare packets origination from two different sensors) then work out which bit relates to the "house code" etc

Here’s a sample of the hex data:

Door Sensor #1

0000 0067 0000 0019 0017 003b 0040 0012 0040 0012 0040 0012 0017 003b 0040 0012 0017 003b 0016 003b 0017 003b 0040 0012 0040 0012 0040 0013 0016 003b 0040 0012 0017 003b 0040 0012 0016 003c 003f 0013 0016 003b 0040 0013 003f 0013 003f 0013 0016 003c 0016 003b 0016 0279

0000 0067 0000 0019 0016 003b 0040 0012 0040 0011 0040 0012 0017 003a 0040 0011 0018 003a 0016 003b 0018 003a 0040 0011 0040 0013 0040 0011 0018 003a 0040 0012 0016 003c 003f 0013 0016 003b 0040 0012 0016 003c 003f 0012 0040 0013 003f 0013 0016 003c 0016 003b 0016 0279

0000 0067 0000 0019 0018 0039 0041 0010 0040 0011 0040 0011 0018 003a 0040 0010 001a 0038 0019 0038 001a 0037 0042 000f 0040 0012 0040 0012 0017 003a 0040 0011 0017 003b 0040 0012 0017 003a 0040 0012 0017 003a 0040 0011 0040 0012 0040 0012 0017 003b 0016 003b 0017 0277

Door Sensor #2

0000 0067 0000 0019 0016 0038 003b 0010 0016 0039 0016 0038 0016 0038 003a 0011 0016 0039 0016 0038 0016 0038 003a 0011 003a 0011 003a 0011 0016 0038 003a 0011 0016 0039 0039 0011 0016 0039 0039 0012 0015 0039 0039 0012 0039 0012 0039 0012 0015 0039 0015 0039 0016 0265

0000 0067 0000 0019 0016 0038 003a 0011 0016 0038 0016 0038 0016 0039 003a 0010 0016 0039 0016 0038 0016 0038 003a 0011 003a 0011 003a 0011 0016 0038 003a 0011 0016 0038 003a 0011 0016 0039 0039 0012 0015 0039 0039 0012 0039 0012 0039 0011 0016 0039 0015 0039 0015 0266

0000 0067 0000 0019 0016 0038 003a 0011 0016 0038 0016 0038 0016 0039 003a 0011 0015 0039 0016 0038 0016 0039 0039 0011 003a 0011 003a 0011 0016 0039 0039 0011 0016 0039 0039 0012 0015 0039 0039 0012 0015 0039 0039 0012 0039 0012 0039 0012 0015 0039 0015 0039 0016 0265

L

Home Automation Update

Not a lot to say- just a quick update. I’ve ordered a few more bits to add to the home automation project. These have already come:

-RFXCom 433Mhz transceiver
-Byron 433Mhz switch, pir, remote plug/socket & "in ceiling switching module".
-Linksys SPA3102

And I’m still waiting for (or haven’t ordered):

-433Mhz smoke alarms
-433Mhz doorbell
-433Mhz door/window open/close sensors
-Wifi or 433Mhz bathroom scales

Here’s a quick shot of one of the raspberry pis hooked into a little portable LCD, the RFXCOM transceiver, the CurrentCost EnviR and a Jeelabs Jeenode:

The next step I decided to tackle was getting a few real basics pieces of information from my Enigma2 digital satellite receiver into DomitiGa. I decided to use the nifty little shell script module to execute:

#!/bin/bash
rm current
wget -q http://192.168.0.222/ajax/current
cat current | grep "Name:" | sed 's/.*: (.*)<.*/1/'
cat current | grep "Title:" | sed 's/.*: (.*)<.*/1/'
cat current | grep "Recording Status:" | sed 's/.*: (.*)<.*/1/'

Which returns three lines with: The current channel, programme and whether a recording is in progress. I hope to take this a lot further and start capturing stats from my VDSL & ADSL modems, fileserver etc. You can see the satellite details below "Sky: Lounge":

I have been meaning to get my gas meter, hot & cold water monitored for a long time. The gas meter is relatively straight forward as it provides a convenient RJ11 socket with pulses- I just needed a sketch to load onto a jeenode to catch and report these pulses. I decided to try the sketch from the OpenEnergyMonitor project (http://openenergymonitor.org/emon/emontx) found here: https://github.com/openenergymonitor/emonTxFirmware/tree/master/emonTx_Pulse

I made some changes:

-Set freq to 868Mhz
-Set nodeID and networkGroup
-Unset UNO

I think that’s it:

/*
EmonTx Pulse example

An example sketch for the emontx module for
CT only electricity monitoring.

Part of the openenergymonitor.org project
Licence: GNU GPL V3

Authors: Glyn Hudson, Trystan Lea
Builds upon JeeLabs RF12 library and Arduino

*/

#define freq RF12_868MHZ // Frequency of RF12B module can be RF12_433MHZ, RF12_868MHZ or RF12_915MHZ. You should use the one matching the module you have.433MHZ, RF12_868MHZ or RF12_915MHZ. You should use the one matching the module you have.
const int nodeID = 2; // emonTx RFM12B node ID
const int networkGroup = 212; // emonTx RFM12B wireless network group - needs to be same as emonBase and emonGLCD needs to be same as emonBase and emonGLCD

const int UNO = 0; // Set to 0 if your not using the UNO bootloader (i.e using Duemilanove) - All Atmega's shipped from OpenEnergyMonitor come with Arduino Uno bootloader
#include <avr/wdt.h> // the UNO bootloader

#include <JeeLib.h> // Download JeeLib: http://github.com/jcw/jeelib
ISR(WDT_vect) { Sleepy::watchdogEvent(); }

typedef struct { int power, pulse, misc1, misc2; } PayloadTX;
PayloadTX emontx; // neat way of packaging data for RF comms

const int LEDpin = 9;

// Pulse counting settings
long pulseCount = 0; // Number of pulses, used to measure energy.
unsigned long pulseTime,lastTime; // Used to measure power.
double power, elapsedWh; // power and energy
int ppwh = 1; // 1000 pulses/kwh = 1 pulse per wh - Number of pulses per wh - found or set on the meter.

void setup()
{
Serial.begin(57600);
Serial.println("emonTX Pulse example");

rf12_initialize(nodeID, freq, networkGroup); // initialize RF
rf12_sleep(RF12_SLEEP);

pinMode(LEDpin, OUTPUT); // Setup indicator LED
digitalWrite(LEDpin, HIGH);

attachInterrupt(1, onPulse, FALLING); // KWH interrupt attached to IRQ 1 = pin3 - hardwired to emonTx pulse jackplug. For connections see: http://openenergymonitor.org/emon/node/208

if (UNO) wdt_enable(WDTO_8S);
}

void loop()
{
emontx.pulse = pulseCount;
pulseCount = 0;
//Serial.println(pulseCount);
send_rf_data(); // *SEND RF DATA* - see emontx_lib
emontx_sleep(10); // sleep or delay in seconds - see emontx_lib
digitalWrite(LEDpin, HIGH); delay(2); digitalWrite(LEDpin, LOW); // flash LED
}

// The interrupt routine - runs each time a falling edge of a pulse is detected
void onPulse()
{
lastTime = pulseTime; //used to measure time between pulses.
pulseTime = micros();
pulseCount++; //pulseCounter
//Serial.println("Pulse!");
emontx.power = int((3600000000.0 / (pulseTime - lastTime))/ppwh); //Calculate power
}

void send_rf_data()
{
rf12_sleep(RF12_WAKEUP);
// if ready to send + exit loop if it gets stuck as it seems too
int i = 0; while (!rf12_canSend() && i<10) {rf12_recvDone(); i++;}
rf12_sendStart(0, &emontx, sizeof emontx);
// set the sync mode to 2 if the fuses are still the Arduino default
// mode 3 (full powerdown) can only be used with 258 CK startup fuses
rf12_sendWait(2);
rf12_sleep(RF12_SLEEP);
}

void emontx_sleep(int seconds) {
for (int i=0; i<seconds; i++) {
delay(1000);
if (UNO) wdt_reset();
}
}

L

%d bloggers like this: