In a very cool development, Nathaniel Elijah of RTL-SDR Projects had posted about the decoding of the Efergy E2 Classic FSK data transmissions using RTL-SDR and a Raspberry Pi. I just so happened to stumble upon his page, and knowing just how difficult it can be to reverse engineer transmissions made over the air by proprietary devices, immediately felt a sense of awe.
For those who don’t know, Efergy is a company which has produced many wireless energy monitors which operate in the 433Mhz band. Their most basic systems consist of a wireless energy monitor base station with an LCD that displays the current usage to 2 decimal places (kW), and tallies the aggregated daily usage for the past week, and aggregated monthly usage for the past 12 or so months. The data comes from an inductive clamp sensor which is installed in your distribution box, which plugs into a 433Mhz data transmission device which can be configured to send data every 6s, 12s or 24s.
In order to get more detailed data, they have more advanced models and a hub controller which receives the transmission and “visualizes” it by using their cloud services. This adds more expense to the system, and means that someone else is ultimately dealing with your data. I think in this day and age, it’s high time we considered whether the benefits of the cloud (whose services could disappear or change at any time) outweigh the cost (or sometimes savings) of doing it all in-house.
There’s been quite a bit of interest in the efergy monitors, in terms of physically modifying the receivers for data, and some other attempts at decoding the raw data from the sensors, but I wasn’t made aware of it until I stumbled upon Nathaniel’s site.
Nathaniel specifically referred to the Efergy E2 model, however, I’m currently using an Efergy Elite 1.0R. I suspected that most of their “Elite” models and some others shared the same protocol, so I held high hopes that it would work.
Interestingly enough, I downloaded his source code and tried to build it on my Samsung ARM Chromebook running Chrubuntu with rtl-sdr already installed. Aside from a small hiccup which complained of “undefined reference to function `pow'”, which was resolved by changing the compilation command, it compiled and it ran just fine.
For reference, the compilation command that worked looks like:
gcc -o EfergyRPI_001 EfergyRPI_001.c -lm
Apparently the ordering of the -lm option makes a difference to the linker, so keep that in mind.
To run the program, use:
rtl_fm -f 433550000 -s 200000 -r 96000 -g 19.7 2>/dev/null | ./EfergyRPI_001
This asks for rtl_fm (included in the rtl-sdr package from Osmocom) to demodulate, centred at frequency 433.55Mhz with a bandwidth of 200khz, resampled to 96kHz with a tuner gain set to 19.7dB sent through stdout (to be piped into EfergyRPI_001), whereas the diagnostic information from rtl_fm is sent to /dev/null (silenced).
It builds and runs just fine on Chrubuntu, but it should work equally well on everything that rtl-sdr builds on as it’s just straight C code. I must praise the author for making it so elegantly simple and small.
There’s a few troubleshooting tips – firstly, if you only see the header banner, but no decode and get “thrown” back to the shell, rtl_fm probably ran into trouble.
To find out, just delete everything after the gain value (19.7 in the example) and see what happened. You should get something indicative of an error. If it can’t find your tuner, you may need to run everything as superuser (i.e. su or sudo) or add the current user to a privileged group to access USB devices.
You may find that it doesn’t seem to work at all for some tuners and antennas. For example, my R820T tuner stick will sit there with no packets showing. You should play with the gain figure (19.7 above), and try values between 0-50dB, although values above 35 seem to amplify noise rather than signal.
You may also find that the two processes take a lot of CPU time and eventually slow down the decoding, missing packets and having the cursor blink in the terminal hang. I found this happens with my R820T stick, and it may just be a sign that it’s not too happy with the USB bus, or something went wrong with rtl_fm and it’s not providing samples fast enough/dropping samples due to lack of CPU, or that the signal is just really noisy. I’ve had the best experience with E4000 sticks, decoding for hours with no loss of packets at all. I have no FC0012/0013 based sticks, however, Nathaniel was using an FC0013 based stick. Your mileage will vary.
The output itself is in CSV format to the terminal, although date/time will be affected by your locale settings (thanks Chrubuntu). With this data, you can reprocess it, archive it and analyze it to your hearts content. Great!
If the decoding stops all of a sudden and dumps you back to the prompt, it’s likely rtl_fm died and this can happen if your dongle accidentally gets disconnected from the USB port due to vibration or instabilities.
I’ve personally verified the figures that come out of this, and I can definitely say it’s correct and provides a higher level of precision than the LCD screen itself does. That’s a nice added bonus! But do remember to set your voltage correctly in the .c source file before compiling, if your efergy LCD monitor is set to 240v, and the .c file is set to 230v, you will get slightly different numbers!
Maybe this will cause Efergy branded energy monitors to fly off the shelves … now that a $17 SDR dongle can decode them …
My Tiny Insignificant Contribution
In no way do I intend to overshadow Nathaniel’s developments, in fact, none of this could have happened without him. However, I still felt that for data-logging convenience, I could (with my fairly basic and rusty C skills) add data logging to the core program itself, so it dumps to console and to file.
But better than that, I have it accept an argument for the dumping file name, with compile time options for line ending (Unix or DOS) type and flush interval (number of samples). This can be important if you want to log as much data as possible, knowing the power could go out at any time, but if you don’t want to hammer your disk. SSDs can wear out quickly if you keep flushing small writes as they cause metadata updates which cause additional wear.
I also recommend using the -O3 compiler option for gcc, although its real life impact is probably very small. Maybe for Raspberry Pi users, avoiding the GUI altogether and an overclock might help make it work a little better as well.
I’ve uploaded the code here: EfergyRPI_log.
If you invoke it as …
rtl_fm -f 433550000 -s 200000 -r 96000 -g 19.7 2>/dev/null | ./EfergyRPI_log
… it doesn’t log. It behaves just like the previous code, although maybe slightly less efficient.
But if you invoke it as …
rtl_fm -f 433550000 -s 200000 -r 96000 -g 19.7 2>/dev/null | ./EfergyRPI_log log.csv
… it will log into log.csv, appending to any existing data at the interval specified at compile time. You can wrap this up in an infinite looping script which will call the program again in case it dies because the USB got jiggled. There’s no risk of losing data as the file is always opened in append mode rather than write mode. If the file fails to open, the program (should) exit with a message (as per the coding).
It’s mainly a code of convenience for myself, although if others find it useful, they can use it. As a result, of course, there are no warranties and in fact maybe I’ve even made the code worse. But again, you should probably refer to Nathaniel’s site for further updates and information, and maybe leave him a comment of thanks if it worked for you.
To sum it up – the RTL-SDR shows its versatility yet again, thanks to the genius of the community. In this case, I thank Nathaniel Elijah (whose code I’m using right now) – and I hope to see more interesting developments and details of the work required coming in the future.