I've been looking at how easily common 433MHz home automation devices can be hooked up to centralize gathering data and control. One thing that is handy to know about these days with soaring energy costs is electricity consumption. The common Owl Energy Monitor (wireless) is an inexpensive way of doing this and a with bit of poking around it seems others are also having a look at this device.
While the other attempts at figuring this out are fairly crude (eg. trying to buffer and align on the end of the data rather than using the in-built sync sequence), I would like to have a comprehensive understanding, and this is how far I've got so far.
Intelligence gathering
It's easy to take some flying guesses and working out something that seems to work only for some assumption to fail and it all to become a complete mess, so always best checking what high quality information (note - I avoid saying "facts" since I don't fully trust published information) is available.
-
What appears to be simple current transformers are used as sensors (CMA113). These state 71A Max on them... which any engineer should immediately pick up on: that would be the rounded RMS current with a peak current of 100A. Crude measurement circuits are likely to peak detect rather than use RMS, so it would be likely that we are actually measuring peak current up to 100A which is a nice round number.
-
Specs seem to suggest the maximum current 71A... as above
-
There are 3 connections to allow 3-phase measurement
-
The display unit alerts when the battery is low.... so there must be data transmitted about the battery condition
-
This is a multi-voltage unit and can be configured for different voltages, plus there is no means of measuring voltage so it's fair to assume that current measurements are made and converted into power (watts) by the display (P=VI)
-
Recording power readouts on the display, measurements are clearly quantized. By dividing the power by the configured voltage we get ~70mA steps... or probably ~100mA Peak
-
Based on the above we would need a range of about 0-1000 to reach the maximum range which translates into a 10-bit (0-1023) measurement
-
It's not clear if the 3 phases are summed into the same measurement (ie. 3x range would be required) or sent as separate measurements at this point
-
There are 3 "channels" which are presumably just IDs rather than RF channels since cheap RF circuits would not have the discrimination to fit real RF channels into the narrow band available
Baseband Signal
I bought cheap 433MHz modules on eBay and hooked them up to a sound card as a quick & dirty recording mechanism. The signal looks like this:

That's clearly recognizable: Manchester coding (aka Biphase and various other names)
This is nice as it makes data sync easy and takes well to AC coupled circuits where there is no fixed datum point (ground).
A look at the beginning of a transmission (packet) shows a familiar pattern:

This uses common good practices for a reliable transmission. Sections marked are:
-
Junk at start of transmission as receiver settles
-
Preamble - this gets the receiver settled and synced to the incoming symbol rate. Typically this will be done by transmitting 0x00 or 0xff
-
Sync pattern - this is a deliberate change in the data from the preamble to sync where the start of complete bits (and bytes) are. Typically this will be done by transmitting 0x55, 0xaa or similar
-
Data - this is where the actual information to be transferred is
This is a very well designed protocol and shows that skilled engineers were behind this. That's a lot more than I can say for some of the other 433MHz devices kicking around.
A bit of coding later and I had a basic Manchester decoder which can turn this into individual bits, and in turn find the sync and slice it up into bytes.
Data Structure (initial guess)
After decoding and messing with sync patterns to fit the data exactly, we find there are 13 bytes of data. A few tests with varying power levels isolated the bits containing measurement data.
Conclusions at this point:
-
The Sync (LSB first so read right to left) is 0xaf meaning that we have a nybble of preamble and a nybble of alternating bits to sync
-
13 bytes transmitted after sync
-
It's clear that data is transmitted LSB first
-
Bytes 4 and 5 (upper bits always zero) contain the measurement data, confirmed by matching it directly with displayed power readings
-
Bytes 6 and 7 vary all over the place... no idea what they are about
-
Bytes 8 and 9 seem fairly stable... no idea what they are about
-
Bytes 10 and 11 seem to always be zero no matter what
-
Bytes 12 and 13 vary all over the place... I suspect a checksum of some sort
Test: Zero current
This reduced the amount of bit variance and after a number of runs it appears:
-
Bytes 4 and 5 are zero as expected
-
Bytes 6 and 7 are also stable so seem affected by the measurement but no consistent pattern... starting to suspect it's an ADC with a floating input picking up noise / coupling to other signals
-
Bytes 12 and 13 really behave like a checksum - they are consistent when the rest of the bits are the same and a few bits flip when other data bits flip. That also suggests this is a fairly basic checksum as the changes in the checksum are minimal for small data changes. Robust (cryptographic) checksums would likely have all or almost all bits change with a small change in data.
-
No bits behave like counters/timers or anything like that
Test: Different sensor sockets
Data always comes back in the same place and no bits change based connection so it's fair to assume that all the sensors are summed and added together. This means that we will actually need 12-bits to represent full scale. We also know that the unit is agnostic over which socket is used and does not transmit data about how many phases are used.
Test: Different Channels
This shows that the first two bits after the sync are used for channel, however the next two bits seem to have always stayed zero for all further tests. I suspect the first nybble is actually available for addressing though only the first two bits used.
Test: Different battery voltages
This has been a bit inconclusive with 3 bits (1 in Byte 1 and 2 in Byte 2) going high with the lowest voltage test (3V). May also be suffering from floating inputs. No other bits than the end two bytes which are now very much looking like a checksum.
Test: Different temperatures
After scratching my head about what the other data could be I tried varying the temperature in case it measures this as well. This again was inconclusive with a few bits changing erratically in Bytes 2 and 3 but nothing correlating with temperature, plus of course the suspected checksum bytes. Again, this might indicate some floating inputs and varying temperatures shifted thresholds enough (or just varied static levels) enough to flip bits.
Best guess at this point (updated!)
Based on what I have to date, we seem to have a data structure like this:
0 |
Sync: 0xaf |
1 |
Lowest nybble appears to be "channel", upper nybble is a minute countdown in 6 second periods |
2 |
Random(?) ID generated at startup, but only upper nybble. Bit 0x01 may be a low-battery flag, bit 0x04 is a "recently powered up" flag (for first 30 min). |
3 |
Random(?) ID generated at startup |
4 |
Lower 8-bits of Current |
5 |
Upper 2-bits of Current, but may actually be 4-bits with all phases being summed. Upper bits seem to be consistently zero, so possibly could treat these bytes as a 16-bit word. |
6 |
Accumulated Current Counter0 |
7 |
Accumulated Current Counter1 |
8 |
Accumulated Current Counter2 |
9 |
Accumulated Current Counter3 |
10 |
Accumulated Current Counter4 |
11 |
Accumulated Current Counter5 |
12 |
Likely Checksum of some sort, probably parity/XOR based as parity of this byte matches parity from the second (upper) nybble of Byte 1 Through Byte 11
|
13 |
Checksum of nybbles from the second (upper) nybble of Byte 1 Through Byte 11 |
This is very nicely designed again - we clearly have thought that has gone into what data representations are useful as well as additional information like recent power on flag and battery low flags which could be used to make the user experience better. Data integrity is well considered giving two bytes of checks which although one isn't fully understood yet, together likely make a very robust system.
Update 1
After looking at the output of the real-time decode that I've got running for this now, I've made the following observations:
-
Bytes 6-11 are a 48-bit counter accumulating the current measurement each second, and bytes 10-11 are always zero because it hasn't counted that far yet. This is very useful as allows an average since a previous sample to be taken.
-
Updates are sent at least every 60 seconds, but more frequently (down to 6 seconds, in 6 second steps) when energy usage is fluctuating
-
The high nybble of Byte is a period count-down. Every 6 second period it ticks down from 9 reaching 0 each minute. It's unclear what purpose this serves. It's worth noting that the 60 second intervals always start on a 0 value to another 0 value - this may be a simple means of ensuring 1 (predictable) sample every 60 seconds, or at least syncing timing with the receiver.
-
I had originally suspected that Bytes 12-13 were a checksum, but have had no success reverse-engineering the algorithm. What I have however found is that Byte 13 hovers around a value of 100 (a serious checksum would be near random) which is suspiciously like double UK mains frequency. Graphing the distribution and it's very closely centred on 100 - in fact I get a mean of 99.89... I'm beginning to think this is a crude indication of the mains frequency and 0.5Hz (2x) resolution is as good as practical in 8 bits giving space for 60Hz countries. It does however drift around quite a lot so not certain at this point. Byte 12 still does have a fairly even distribution across all values so possibilities still open. See Update 3
Update 2
-
Bytes 2-3 appear to change every time the power is applied and likely act as a randomized(?) unique ID... or at least the upper 24bits are - see below.
-
The lowest nybble of Byte 2 appears to be a set of flags, and it would appear that bit 0x01 is the low battery flag. Bit 0x04 appears to be on immediately after power-up so possibly a "recently powered on" flag or similar and goes low again 30 minutes after power up. Other bits are not known at this point.
Update 3
It's gradually making more sense...
-
Byte 13 definitely stacks up as being a sum of nybbles from the upper of Byte 1 (ie. after the channel) through to Byte 11. This results in the rather tight coincidental distribution around 100 but it all makes more sense now.
-
Byte 12 is not included in the checksum which suggests that it may also be a checksum of some sort. What does seem consistent is that the parity of this byte matches the parity of the data set used for Byte 13 which suggests this is some kind of XOR based validation. This byte along with two bits (flags) is the only thing between me and a full decode, but at this stage it's completely possible to use this for basic parity checking.