whaleygeek / pyenergenie

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

Push radio handler code into C #34

Closed whaleygeek closed 8 years ago

whaleygeek commented 8 years ago

This is ongoing work related to #4 and #32 but opened as a placeholder for all activity related to "pushing the radio code into C'.

In the original design of this library, I wrote as much as possible in Python due to the speed of prototyping and development. Python is also a great language for writing a spec for later C code.

However, testing with the legacy OOK devices has shown that the inter-burst delays between repeated messages, reduce the probability of switching on some devices.

Work is going on at the moment (in the drv folder) to push the whole of the transmit and receive functionality (the physical layer) into a separate linkable C driver, with a python ctypes wrapper. The interface to this is the 'radio' abstraction.

When testing is completed, radio.py and spi.py will be deprecated, and the existing radio2.py switched into place instead.

Present status is that the OOK transmitter is working well, but I want to do more work in the transmit routine to extend the amount of payload repeats beyond the 255 limit as set by the payloadlen counter in the HRF radio.

Once that is working, I will get the FSK transmit and receive working in the C library before then re-testing everything and integrating it with the main Python code.

whaleygeek commented 8 years ago

OOK transmit with up to 8 repeats now supported, tested with radio2_test.py, and integrated into legacy.py

whaleygeek commented 8 years ago

OOK transmit with up to 75 repeats (2 seconds) tested on feature branch long-tx

Will close when this merges back to master.

hotear commented 8 years ago

Any news on the merge and when it may be possible to use both green and purple sockets from the same code?

whaleygeek commented 8 years ago

Hi @hotear I'm planning to merge and re-test everything tomorrow (Friday 13th!!). While it has my focus I'll have a look through the legacy/switch/monitor framework and perhaps propose how a combined script might pan out.

It would be helpful, if you have any ideas about how you plan to use the two together, to post them here, as that will influence my thinking.

I'm thinking of a device-agnostic interface, so you can just have python variables for any connected device (green button or purple), with a simple device registry. Then instigate methods on them. This will knit up to the radio interface under the bonnet for you, and switch between OOK and FSK mode automatically - mostly leaving the radio idling in FSK receive mode to increase the chances of hearing a report. Later I will add a message scheduler that learns the reporting schedule, and defers FSK or OOK transmits to 'free timeslots' to improve the performance of the overall system.

So something a bit like this maybe:

(when configuring the system) print("Press the learn button on the TV device") energenie.start_learn(house_code=0xABCDE, index=2) raw_input("Press enter when done") energenie.stop_learn()

energenie.create_device("tv", energenie.device.ENER002, index=2, house_code=0xABCDE) energenie.create_device("aquarium", energenie.device.MIHO005, address=0x1234)

(when running the system)

tv = energenie.get("tv") aquarium = energenie.get("aquarium")

tv.off() aquarium.on() time.sleep(10) if aquarium.power > 20: print("Has the pump motor stalled??")

def just_turned_off(device): print("Your user just turned off %s" % device) print("I'm turning it back on!") device.on()

aquarium.when_turned_off(just_turned_off)

whaleygeek commented 8 years ago

Tested, long-tx branch merged, closing. Moving suggestsions for new API to a new issue.

whaleygeek commented 8 years ago

Just a note, @hotear that the unified_radio branch is now implemented and tested, and this allows both FSK (MiHome purple) and OOK (green button) devices to be used in the same build - both the FSK and OOK now work from a single unified low level radio driver.

I've yet to do work on the device classes and the registry to make this work like you probably want it to, but there is nothing stoping you trying something like this now using the unified_radio branch.

build FSK messages for MiHome purple

PURPLE_ID = 0x68B # captured from a real device using Monitor.py m = OpenThings.alterMessage(Messages.SWITCH, header_sensorid=PURPLE_ID, recs_0_value=1) purple_on = OpenThings.encode(m)

m = OpenThings.alterMessage(Messages.SWITCH, header_sensorid=PURPLE_ID, recs_0_value=0) purple_off = OpenThings.encode(m)

build OOK messages for green button

GREEN_ON = encoder.build_switch_msg(True, device_address=1) GREEN_OFF = encoder.build_switch_msg(False, device_address=1)

while True: radio.transmitter(ook=True) radio.transmit(GREEN_ON) radio.transmitter(fsk=True) radio.transmit(purple_on) time.sleep(2)

radio.transmitter(ook=True)
radio.transmit(GREEN_OFF)
radio.transmitter(fsk=True)
radio.transmit(purple_off)
time.sleep(2)
whaleygeek commented 8 years ago

Sorry, markdown problem with github. I'll create a combined.py in the unified_radio branch that you can try @hotear

whaleygeek commented 8 years ago

Ok @hotear try combined.py

You should use legacy.py first to 'learn' your device to the default house address. Then use monitor.py to find out what the sensorId is of your purple MiHome. Then code that sensorid into the combined.py

Then sudo python combined.py.

I tried this just now with a purple and a green, and it works.

It should be enough to get you going until I write the rest of the device class code.

whaleygeek commented 8 years ago

combined.py added as an example of this.

hotear commented 8 years ago

Thanks, I will hopefully give it a try this evening.

whaleygeek commented 8 years ago

Ok thanks @hotear , let me know how it goes. combined.py is only an example. I will be working on a 'nicer' application interface over the coming weeks that will hide all the radio setup details, but it might get you going in the short term at least. #18 is where all that work will surface in the future, so feel free to add any suggestions you have into that issue, based on your experiments.

hotear commented 8 years ago

It's all working lovely. Green plugs turning off and on and purple plugs still listening and switching. As part of my program I did get this message appearing on the terminal as I ran but it didn't seem to cause any issues. warning: method is untested:<function receive_len at 0x76a1b270>

whaleygeek commented 8 years ago

Great, glad it works! The warning is only because I haven't tested the receive_len function yet, it's a reminder to me. But it's not used in any of the existing examples, so that is fine.

Thanks for testing it and reporting back.

I'll be looking into the device classes soon, perhaps sometime later this week, which will make it more 'fun' to write apps with, as you will just get a variable in the python for each device and be able to say tv.on() or tv.get_power() for example. This particular issue number is closed now - please do feed back anything you think of regarding the more friendly api on issue #18 Thanks!