whaleygeek / pyenergenie

A python interface to the Energenie line of products
MIT License
81 stars 51 forks source link

How did you "Captured address of David's RF hand controller"? #81

Closed nickcw123 closed 5 years ago

nickcw123 commented 7 years ago

In the code there is the following line:

HOUSE_ADDRESS = 0xA0170 # Captured address of David's RF hand controller

How did you capture the RF hand controller address?

I am under the impression devices MIHO002 and MIHO008 can only be paired to 2 controllers.

I have mine paired to 1 hand controller and a Mi Home gateway. I dont want to loose the pairing to these.

How do I find out the house address of the RF hand controller? How do I find out the house address of the Mi home gateway? Can I use the web API to get this information. How does the Mi home gateway handle the 4 device limit per house address.

If I know one of the above I can use the ENER314-RT to send the address of the hand controller or the mi home gateway so I dont need to pair ENER314-RT with my devices. Am I understanding this correctly?

whaleygeek commented 7 years ago

To develop and debug the low level radio driver, I bought one of these devices:

https://greatscottgadgets.com/hackrf/

I used GnuRadio from a bootable memory stick that I created from here:

http://gnuradio.org/redmine/projects/gnuradio/wiki/GNURadioLiveDVD

I then wrote a simple gnuradio flow that tuned to the Energenie radio channel, OOK demodulated the payload and displayed it on a virtual scope window in triggered mode, which captured a complete transmission sequence in a form that I could see on the screen.. I then manually decoded the bit pattern to work out what the house code was when I pressed the button on the RF hand controller.

I programmed that code into the python, and then proved that the python transmitted a timing accurate version of the same code when run, and correctly actuated the switches that had previously 'learnt' from the RF hand controller - thus proving that the timing of the transmission generated from the python code was the same as the timing of the code generated from the RF hand controller (as the receiver end has a reasonably wide set of tolerances and will learn almost anything that looks roughly like it starts with the right preamble). This was mainly to track down and fix an issue where the transmitter radio was incorrectly configured and was sending out patterns at the wrong baud rate, but the receiver switches were still learning that (wrong and much longer) pattern.

To do this yourself would be quite an expensive purchase for one outcome. You might be able to get a cheap £10 SDR dongle and do a similar thing with gnuradio, if you are interested in doing that, let me know and I can upload the .grc file from gnuradio that I used to do this with, as I still have it on that booting memory stick.

I have it on the issues list to write an OOK receiver in this python/C stack of code, to allow people to learn the codes of their RF hand controllers themselves at low cost, and that would then allow you to use both an RF hand controller, the MiHome gateway and the python code with devices that only remember two codes - but I haven't had the time to commit to this.

Yes, the OOK receive devices like the MIHO002 will only store two patterns. If you put them back into learning mode and learn a new pattern, it deletes the oldest learned pattern and replaces it with the new pattern, so you can only store two at any one time. MIHO002 is branded as a newer looking device, but has the older 'green button' legacy device hardware inside it, as that is receive only.

The other MIHO Mihome devices that are two-way use a different radio scheme, and they have factory programmed unique ID's inside each of them, and the learning is done at the raspberry pi end. You can have any number of devices in a system using that newer scheme.

whaleygeek commented 7 years ago

Also note that the full web API that is used by the MiHome gateway is documented here:

https://mihome4u.co.uk/docs/api-documentation

You might be able to use that to get hold of the house code assigned to your account perhaps, and then manually load that into the python code, as a way of getting the code.

From what I recall, the web api is RESTful, so you could write some python to drive it, or a node.js script. You might even be able to exercise it manually using a REST tester, such as the POSTMAN google chrome plugin perhaps, and query your account record for the allocated house code, if that is stored in the configuration (which I'm not sure either way whether it is or is not) - a look at the api docs might surface some further understanding about that I guess.

gpbenton commented 7 years ago

How do I find out the house address of the RF hand controller?

I don't know if it helps, but I just this week built a decoder using these instructions that successfully decoded my remote. You get a decimal code for each button.

I haven't tried using the codes it produces to send from the Pi, but it should be straight forward. It is a relatively inexpensive way of decoding, especially if you have a spare NodeMCU lying around.

nickcw123 commented 7 years ago

Thank you for this information.

I have set up the API and it does return an id for the gateway and for each paired device. I have not had success using these ids with the pi mote. I am not sure how they map to the ids needed for OOK.

I am going to try your SDR approach. I have found on ebay a digital TV dongel that has a chipset (RTL2832U R820T) which I think is supported by GnuRadio. It was a bout £7. When it arrives I will let you know how I get on.

I dont suppose you still have the required GnuRadio commands? I will try and work them out if not.

Thanks again.

whaleygeek commented 7 years ago

Sure, I'll boot up my gnuradio memory stick later today and capture the .grc file and add it to this project.

It's relatively simple, and mostly based on Michael Ossmann's OOK lesson here:

http://greatscottgadgets.com/sdr/8/

https://twitter.com/michaelossmann

But I will upload it later today for you, to save you the trouble.

You have to fiddle with the virtual scope settings a bit to get it into trigger mode and get the x and y scales correct so that you can capture the whole packet on the screen, but I managed to do this quite quickly once I worked out the settings on the virtual scope component in GRC.

nickcw123 commented 7 years ago

Thanks. Those tutorials look very interesting.

whaleygeek commented 7 years ago

Ok, so attached is a zip of my OOK decoder written in GNURadioCompanion

OOK_djw.grc.zip

whaleygeek commented 7 years ago

I downloaded this image:

http://gnuradio.org/redmine/projects/gnuradio/wiki/GNURadioLiveDVD

It's a livecd image, so I burnt it onto CD and booted from it.

I did also find a way to get this onto a USB memory stick, which was more convenient. That mostly consisted of using the startup disk creator to format a USB memory stick, I put two partitions on there and then used the mkfs and dd commands to copy the iso image on there. I forget the exact steps, but if you search for 'turn an iso image into a booting USB memory stick on linux' you'll probably find enough steps to do it yourself.

Let me know how you get on with this.

If you need any help turning the bit pattern into an address, look in this file, where the comments explain the encoding: https://github.com/whaleygeek/pyenergenie/blob/master/src/energenie/TwoBit.py#L33

DEFAULT_ADDR = 0x6C6C6

#                   5     6     7     8     9     10    11    12    13    14
#                   1(01) 1(10) 1(11) 0(00) 0(01) 0(10) 0(11) 1(00) 1(01) 1(10)
DEFAULT_ADDR_ENC = [0x8e, 0xe8, 0xee, 0x88, 0x8e, 0xe8, 0xee, 0x88, 0x8e, 0xe8]

# D0=high, D1=high, D2-high, D3=high (S1 on) sent as:(D0D1D2D3)
# 128 64 32 16  8  4  2  1        128 64 32 16  8  4  2  1
#   1  B  B  0  1  A  A  0          1  B  B  0  1  A  A  0
#   1  1  1  0  1  1  1  0          1  1  1  0  1  1  1  0

SW1_ON_ENC  = [0xEE, 0xEE] # 1111 sent as 1111

# D0=high, D1=high, D2=high, D3=low (S1 off)
# 128 64 32 16  8  4  2  1        128 64 32 16  8  4  2  1
#   1  B  B  0  1  A  A  0          1  B  B  0  1  A  A  0
#   1  1  1  0  1  1  1  0          1  1  1  0  1  0  0  0

SW1_OFF_ENC = [0xEE, 0xE8] # 1110 sent as 0111
jeremypoulter commented 7 years ago

There is a nice utility for using RTL-SDR for decoding 433MHz (and other), have a look at https://github.com/merbanan/rtl_433

I just ran with the -a option and pulled the house code from the output. rtl_433 -a

nickcw123 commented 7 years ago

OK so the TV dongal arrived. I made a GNU radio DVD. I booted it up my laptop. I loaded your grc file. And pressed a button my remote control and I heard a beeping sound and saw the signal in the wave form. I was expecting to have to configure the TV dongel in some way but it all just worked out of the box, very impressive.

I watched the lesson by Michael Ossmann very interesting this GNU Radio companion looks really good. I am going to play around with it a lot more.

My next step is to record the sound the laptop makes and put it in audacity and then try and decode the signal. Is that what you did?

I am a little confused about how to decode the signal though. I am looking at your python file and I can see how the default address translates into the binary values in brackets but I dont understand where the values outside the brackets come from. I am then not sure how that translates to the hex values.

Also... SW1_ON_ENC = [0xEE, 0xEE] # 1111 sent as 1111

1111 = F, how does this become 0xEE, 0xEE.

I am sure I am missing something simple?

Thanks for your help this is all very interesting.

nickcw123 commented 7 years ago

Thanks Jeremy

I tried your method and have got the following....

1 on

*** signal_start = 246446421, signal_end = 246484907 signal_len = 38486, pulses = 75 Iteration 1. t: 108 min: 57 (36) max: 159 (39) delta 5 Iteration 2. t: 108 min: 57 (36) max: 159 (39) delta 0 Pulse coding: Short pulse length 57 - Long pulse length 159

Short distance: 48, long distance: 151, packet distance: 1661

p_limit: 108 bitbuffer:: Number of rows: 3 [00] {25} 8b 4e 8f 00 : 10001011 01001110 10001111 0 [01] {25} 8b 4e 8f 00 : 10001011 01001110 10001111 0 [02] {25} 8b 4e 8f 00 : 10001011 01001110 10001111 0

1 off

*** signal_start = 248678985, signal_end = 248730899 signal_len = 51914, pulses = 125 Iteration 1. t: 108 min: 57 (65) max: 159 (60) delta 5 Iteration 2. t: 108 min: 57 (65) max: 159 (60) delta 0 Pulse coding: Short pulse length 57 - Long pulse length 159

Short distance: 48, long distance: 150, packet distance: 1661

p_limit: 108 bitbuffer:: Number of rows: 5 [00] {25} 8b 4e 8e 00 : 10001011 01001110 10001110 0 [01] {25} 8b 4e 8e 00 : 10001011 01001110 10001110 0 [02] {25} 8b 4e 8e 00 : 10001011 01001110 10001110 0 [03] {25} 8b 4e 8e 00 : 10001011 01001110 10001110 0 [04] {25} 8b 4e 8e 00 : 10001011 01001110 10001110 0

2 on*** signal_start = 250576799, signal_end = 250642144 signal_len = 65345, pulses = 175 Iteration 1. t: 108 min: 57 (91) max: 159 (84) delta 5 Iteration 2. t: 108 min: 57 (91) max: 159 (84) delta 0 Pulse coding: Short pulse length 57 - Long pulse length 159

Short distance: 48, long distance: 151, packet distance: 1661

p_limit: 108 bitbuffer:: Number of rows: 7 [00] {25} 8b 4e 87 00 : 10001011 01001110 10000111 0 [01] {25} 8b 4e 87 00 : 10001011 01001110 10000111 0 [02] {25} 8b 4e 87 00 : 10001011 01001110 10000111 0 [03] {25} 8b 4e 87 00 : 10001011 01001110 10000111 0 [04] {25} 8b 4e 87 00 : 10001011 01001110 10000111 0 [05] {25} 8b 4e 87 00 : 10001011 01001110 10000111 0 [06] {25} 8b 4e 87 00 : 10001011 01001110 10000111 0

2 off

*** signal_start = 253007923, signal_end = 253066554 signal_len = 58631, pulses = 150 Iteration 1. t: 108 min: 57 (84) max: 159 (66) delta 10 Iteration 2. t: 108 min: 57 (84) max: 159 (66) delta 0 Pulse coding: Short pulse length 57 - Long pulse length 159

Short distance: 48, long distance: 150, packet distance: 1662

p_limit: 108 bitbuffer:: Number of rows: 6 [00] {25} 8b 4e 86 00 : 10001011 01001110 10000110 0 [01] {25} 8b 4e 86 00 : 10001011 01001110 10000110 0 [02] {25} 8b 4e 86 00 : 10001011 01001110 10000110 0 [03] {25} 8b 4e 86 00 : 10001011 01001110 10000110 0 [04] {25} 8b 4e 86 00 : 10001011 01001110 10000110 0 [05] {25} 8b 4e 86 00 : 10001011 01001110 10000110 0

3 on

*** signal_start = 255731963, signal_end = 255797306 signal_len = 65343, pulses = 175 Iteration 1. t: 108 min: 57 (91) max: 159 (84) delta 5 Iteration 2. t: 108 min: 57 (91) max: 159 (84) delta 0 Pulse coding: Short pulse length 57 - Long pulse length 159

Short distance: 48, long distance: 150, packet distance: 1662

p_limit: 108 bitbuffer:: Number of rows: 7 [00] {25} 8b 4e 8b 00 : 10001011 01001110 10001011 0 [01] {25} 8b 4e 8b 00 : 10001011 01001110 10001011 0 [02] {25} 8b 4e 8b 00 : 10001011 01001110 10001011 0 [03] {25} 8b 4e 8b 00 : 10001011 01001110 10001011 0 [04] {25} 8b 4e 8b 00 : 10001011 01001110 10001011 0 [05] {25} 8b 4e 8b 00 : 10001011 01001110 10001011 0 [06] {25} 8b 4e 8b 00 : 10001011 01001110 10001011 0

3 off

*** signal_start = 257879112, signal_end = 257937743 signal_len = 58631, pulses = 150 Iteration 1. t: 108 min: 57 (84) max: 159 (66) delta 5 Iteration 2. t: 108 min: 57 (84) max: 159 (66) delta 0 Pulse coding: Short pulse length 57 - Long pulse length 159

Short distance: 48, long distance: 151, packet distance: 1662

p_limit: 108 bitbuffer:: Number of rows: 6 [00] {25} 8b 4e 8a 00 : 10001011 01001110 10001010 0 [01] {25} 8b 4e 8a 00 : 10001011 01001110 10001010 0 [02] {25} 8b 4e 8a 00 : 10001011 01001110 10001010 0 [03] {25} 8b 4e 8a 00 : 10001011 01001110 10001010 0 [04] {25} 8b 4e 8a 00 : 10001011 01001110 10001010 0 [05] {25} 8b 4e 8a 00 : 10001011 01001110 10001010 0

4 on

*** signal_start = 260138203, signal_end = 260196831 signal_len = 58628, pulses = 150 Iteration 1. t: 108 min: 57 (84) max: 159 (66) delta 5 Iteration 2. t: 108 min: 57 (84) max: 159 (66) delta 0 Pulse coding: Short pulse length 57 - Long pulse length 159

Short distance: 48, long distance: 150, packet distance: 1661

p_limit: 108 bitbuffer:: Number of rows: 6 [00] {25} 8b 4e 83 00 : 10001011 01001110 10000011 0 [01] {25} 8b 4e 83 00 : 10001011 01001110 10000011 0 [02] {25} 8b 4e 83 00 : 10001011 01001110 10000011 0 [03] {25} 8b 4e 83 00 : 10001011 01001110 10000011 0 [04] {25} 8b 4e 83 00 : 10001011 01001110 10000011 0 [05] {25} 8b 4e 83 00 : 10001011 01001110 10000011 0

4 off

*** signal_start = 262459143, signal_end = 262524487 signal_len = 65344, pulses = 175 Iteration 1. t: 108 min: 57 (105) max: 159 (70) delta 8 Iteration 2. t: 108 min: 57 (105) max: 159 (70) delta 0 Pulse coding: Short pulse length 57 - Long pulse length 159

Short distance: 48, long distance: 150, packet distance: 1661

p_limit: 108 bitbuffer:: Number of rows: 7 [00] {25} 8b 4e 82 00 : 10001011 01001110 10000010 0 [01] {25} 8b 4e 82 00 : 10001011 01001110 10000010 0 [02] {25} 8b 4e 82 00 : 10001011 01001110 10000010 0 [03] {25} 8b 4e 82 00 : 10001011 01001110 10000010 0 [04] {25} 8b 4e 82 00 : 10001011 01001110 10000010 0 [05] {25} 8b 4e 82 00 : 10001011 01001110 10000010 0 [06] {25} 8b 4e 82 00 : 10001011 01001110 10000010 0

all on

*** signal_start = 264798439, signal_end = 264951078 signal_len = 152639, pulses = 500 Iteration 1. t: 108 min: 57 (260) max: 159 (240) delta 8 Iteration 2. t: 108 min: 57 (260) max: 159 (240) delta 0 Pulse coding: Short pulse length 57 - Long pulse length 159

Short distance: 48, long distance: 150, packet distance: 1661

p_limit: 108 bitbuffer:: Number of rows: 20 [00] {25} 8b 4e 8d 00 : 10001011 01001110 10001101 0 [01] {25} 8b 4e 8d 00 : 10001011 01001110 10001101 0 [02] {25} 8b 4e 8d 00 : 10001011 01001110 10001101 0 [03] {25} 8b 4e 8d 00 : 10001011 01001110 10001101 0 [04] {25} 8b 4e 8d 00 : 10001011 01001110 10001101 0 [05] {25} 8b 4e 8d 00 : 10001011 01001110 10001101 0 [06] {25} 8b 4e 8d 00 : 10001011 01001110 10001101 0 [07] {25} 8b 4e 8d 00 : 10001011 01001110 10001101 0 [08] {25} 8b 4e 8d 00 : 10001011 01001110 10001101 0 [09] {25} 8b 4e 8d 00 : 10001011 01001110 10001101 0 [10] {25} 8b 4e 8d 00 : 10001011 01001110 10001101 0 [11] {25} 8b 4e 8d 00 : 10001011 01001110 10001101 0 [12] {25} 8b 4e 8d 00 : 10001011 01001110 10001101 0 [13] {25} 8b 4e 8d 00 : 10001011 01001110 10001101 0 [14] {25} 8b 4e 8d 00 : 10001011 01001110 10001101 0 [15] {25} 8b 4e 8d 00 : 10001011 01001110 10001101 0 [16] {25} 8b 4e 8d 00 : 10001011 01001110 10001101 0 [17] {25} 8b 4e 8d 00 : 10001011 01001110 10001101 0 [18] {25} 8b 4e 8d 00 : 10001011 01001110 10001101 0 [19] {25} 8b 4e 8d 00 : 10001011 01001110 10001101 0

all off

*** signal_start = 267708628, signal_end = 267773973 signal_len = 65345, pulses = 175 Iteration 1. t: 108 min: 57 (98) max: 159 (77) delta 5 Iteration 2. t: 108 min: 57 (98) max: 159 (77) delta 0 Pulse coding: Short pulse length 57 - Long pulse length 159

Short distance: 48, long distance: 150, packet distance: 1661

p_limit: 108 bitbuffer:: Number of rows: 7 [00] {25} 8b 4e 8c 00 : 10001011 01001110 10001100 0 [01] {25} 8b 4e 8c 00 : 10001011 01001110 10001100 0 [02] {25} 8b 4e 8c 00 : 10001011 01001110 10001100 0 [03] {25} 8b 4e 8c 00 : 10001011 01001110 10001100 0 [04] {25} 8b 4e 8c 00 : 10001011 01001110 10001100 0 [05] {25} 8b 4e 8c 00 : 10001011 01001110 10001100 0 [06] {25} 8b 4e 8c 00 : 10001011 01001110 10001100 0

nickcw123 commented 7 years ago

So I guess that makes the hoome address: 8b 4e 8

So I have written this python.....

import energenie

APP_DELAY = 1 socket6 = energenie.Devices.OOKSwitch((0x8b4e8,1)) socket6.turn_off()

When I run it I get... :~/auto/pyenergenie-master/src$ sudo python nic_test.py

Segmentation fault (core dumped)

dmesg

[602102.462226] brcmfmac: brcmf_sdio_kso_control: max tries: rd_val=0xff err=-110 [602102.462248] brcmfmac: brcmf_sdio_bus_sleep: error while changing bus sleep state -110 [602102.462296] brcmfmac: brcmf_do_escan: error (-52) [602102.462310] brcmfmac: brcmf_cfg80211_scan: scan error (-52)

Any idea what is going on? Is my address correct? Is my python correct?

All very interesting.

nickcw123 commented 7 years ago

OK I have sorted it.

The address is correct.

The issue is with the python. I missed the init part of the script

import time import energenie

APP_DELAY = 1

energenie.init()

socket6 = energenie.Devices.OOKSwitch((0x8b4e8, 1))

socket6.turn_on()

davet2001 commented 7 years ago

Hi, I face the same problem, how to get the house address from my ENER002-C handset without any extra radio equipment.

On the back of the remote there is a 4 digit number. Maybe this maps to the 20bit unique code somehow.

If you have such a handset and have found the house address, please post back with the label code and the house address. Maybe if you have access to several remotes you could do this for several devices. Maybe then that will give us enough information to reverse engineer it. Or perhaps if we are unlucky it's just a batch/date code and nothing to do with the house address.

If you have more information about this, please reply. I'll start:

label=1814, house_code=?????

jeremypoulter commented 7 years ago

For what it is worth mine is label=5213, house_code=0x24780.

davet2001 commented 7 years ago

Hmm. I've seen 1814 written on everything I bought (outside of main box, and on each programmable socket, which as we know don't have a unique code). Perhaps this is just a week number, e.g. [1814]=[week 18, year 2014].

whaleygeek commented 7 years ago

I think you are right, that is probably a batch code.

I'll check my hand controller at the weekend to see if it has any other markings on it or inside it.

I think it's a bit of work to turn the radio into an OOK receiver so you can suck the code out of the hand controller. But I might have a cursory look at it soon just to at least assess how much work is required.

It's mainly about getting the HRF69 module set up with the correct parameters, as the bit-receive path is already commissioned for the FSK mode. So it might not be quite as involved as perhaps I'm imagining. We might be able to use the sync detector of the HRF69 module to sense the start pattern.

The thing I'm most worried about is that the hand controller is battery operated probably with a low accuracy oscillator, and the OOK encoding spec has a very wide acceptance range on the timing - those sockets basically learn almost anything to be honest! The HRF69 radio requires a baud rate parameter to be set which essentially sets in stone the clock rate that the bits are clocked in at, so to get an accurate sample with such a wide tolerance on the timings, we might have to oversample at, say, 16 times the bit rate, and then parse the bitstream out in software.

Not sure yet, as I say, I think a bit of technical due diligence is required first to scope the scale of the task.

gpbenton commented 7 years ago

I don't know if it helps, but I receive the codes from my remote using the circuit from this blog article. I use it to keep my HomeAssistant set up in sync with the switches.

davet2001 commented 7 years ago

I've figured out my hand controller remote code without any additional equipment.

It turns out to be a bit of a lateral thinking puzzle.

The possible codes are 0x00000 to 0xFFFFF, which is 1048576 options, the raspberry pi can do ~5 per second. I made a script that turns off all sockets at each address incrementing from 0x00000 to 0xFFFFF, logging each address tried to a file. Max duration is about 3 days. Then I turned one of my sockets on manually, plugged the raspberry pi into it and started the script.

A couple of weird things happened:

No complaints from the neighbours but I probably turned off most energenie devices within the vicinity (sorry everyone!). Anyway the raspberry pi stopped itself after 2 days. I plugged it back into a normal socket, turned the remote socket on and started the script again changing the start point to a few before the last item logged, and adding a 2 second delay between each try. Then quite reliably all my sockets turn off at code 0xFD160.

So there you have it, I know my hand controller code.

Enjoy!

Dave

learn_house_code.py.txt

redlegoman commented 6 years ago

Dave, Whatever you used to upload the learn_house_code.py.txt file has truncated some lines like this: print("Socket must already be programmed with your house remote (any button$ Are you able to upload a copy of the python script somewhere else? Perhaps paste it into the comment box using the code formatting?

davet2001 commented 6 years ago

Sorry about the messed up formatting. Try this:

# Learn a energenie house code without any special equipment.
# Dave T 6/7/2017
# This script runs on a raspberry pi and instructs a connected
# ENER314-RT VER01 module to turn off all house codes in sequence.
# Then look at the log to see which code turned the Rpi off.
# Run this script in the pyenergenie src directory with
#
# nohup sudo python -u learn_house_code.py
import time
import datetime
import energenie
import sys

SEARCH_START = 0x00000
SEARCH_END   = 0xFFFFF

def learn_socket_loop():
    """Try house codes in sequence"""

    print("Socket must already be programmed with your house remote (any button)")
    print("and raspberry pi must be plugged into the socket.")
    print("This script will try to turn off each house code in turn from")
    print("0x00000 to 0xFFFFF.")
    print("The last entry logged to learn_house_code.log is your house code")
    print("or perhaps one or two earlier depending on your power supply")
    print("capacitor.")
    #raw_input("Press enter to begin, or ctrl-C to quit")

    starttime = datetime.datetime.now()

    f = open("learn_house_code.log","w")

    for housecode in range(SEARCH_START, SEARCH_END):
        thetime = datetime.datetime.now()
        elapsedtime = thetime - starttime
        if elapsedtime.days == 0 and elapsedtime.seconds <= 0:
            elapsedtimestr = "???"
            remainingtimestr = "???"
        else:
            elapsedtimestr = "%dd %dh:%dm" % (elapsedtime.days, elapsedtime.seconds//3600, (elapsedtime.seconds//60)%60)
            remainingtime = elapsedtime / (housecode - SEARCH_START) * (SEARCH_END - housecode)
            remainingtimestr = "%dd %dh:%dm" % (remainingtime.days, remainingtime.seconds//3600, (remainingtime.seconds//60)%60)
        s = "%05X: OFF" % housecode
        print "%s elapsed:[%s] rem:[%s]\r" % (s, elapsedtimestr, remainingtimestr),
        f.write(s + "\n")
        f.flush()
        socket = energenie.Devices.ENER002((housecode, 0))
        socket.turn_off()
        time.sleep(2)

    f.close()

if __name__ == "__main__":
    print("Starting house code learner")

    energenie.init()

    try:
        learn_socket_loop()
    finally:
        energenie.finished()
megatron-uk commented 5 years ago

Just a quick note to say that the tip to use rtl_433 worked great. I bought a cheap (£7) rtl2832 dvb-t dongle, downloaded the latest rtl_433 and rtl-sdr library (https://osmocom.org/projects/rtl-sdr/wiki/Rtl-sdr#Building-the-software), compiled and ran the tool.

It picked up the codes from my first (of 6) remote handset straight away.

Just another 5 handsets to map now....

davet2001 commented 4 years ago

Just in case it helps people, once you've captured the house code (I did it using universal radio hacker), it is possible to use rpi-rf to directly control the energenie "green button" sockets, even without an ener314-RT.

housecode=0xfd160; channel=3; newstate=1; rpi-rf_send -g 19 $(($housecode*16+16#$(echo $((channel)) | tr '12345678' 'e6a2c480')+$newstate))

Further explanation here: https://github.com/davet2001/miscellaneous/blob/master/energenie_rpi-rf_433.sh