d0ugal / python-rfxcom

A Python 3.3+ library for working with your RFXTrx and automating your home.
BSD 3-Clause "New" or "Revised" License
8 stars 9 forks source link

Improve the handling of the RFXtrx mode. #16

Open d0ugal opened 10 years ago

d0ugal commented 10 years ago

Background: The mode of the RFXtrx is used to enable and disable different protocols and/or manufacturers. Therefore, we need to make sure the protocols we are using are enabled. The status packet returns the enabled modes, the default action is to log the currently enabled modes.

At the moment we have a static mode which is set during the statup. This enables the devices that are currently implemented by python-rfxcom and disables all of the others.

We need to handle the following cases:

This issue replaces #7 and #13 which described different parts of the issue, but I think they probably need to be handled together.

kalfa commented 10 years ago

Not sure what you mean with the first point (user may want to enable ...).

From what I understand, and I might be terribly wrong, the MODE packet should be send once. Or can you send multiple packets, e.g each enabling or disabling a single protocol (like a mask)?

Ideally users/actors in this case are the asyncio protocols in use. Those are known (ideally) before the transport setup starts. I don't think there is a use case for a protocol to be hot plugged to a running transport.

In other words, the transport should know what asyncio protocols (and thereof rfxcom protocols) are in use and create the MODE accordingly.

Am I getting it right?

It's a bit tricky, as for what I can see in the asyncio world there usually is a transport instance for each protocol instance and vice versa. The transport needs to know the protocol instance since it needs to notify events to it (connection_made, data_received, etc). A protocol might need to know its transport (which is passed to it when connection_made is called) since it might want to write back and not just getting notified.

This would probably mean (just thinking out loud) a bit of refactoring of the transport into:

This might be done also (but I don't know what is better between the two) by a single transport which accepts multiple protocols. It seems right in this case, as rfxcom transceiver does actually that: a single transport which talks multiple protocols.

In python-rfxcom specific case, there is currently a mix up, hardwiring the protocol (via protocol.HANDLERS) into the base transport. This works fine - although a bit unhortodox from a OOP POV - as long as you want all the HANDLERS always 'registered'. IIRC in the transceiver doc it's suggested to set only the protocols you actually use, to increase the transceiver range and performance (and consume, which might be improtant if attached to low powered device like RPi).

This means that in a scenario for which both you and I use this module, but we have a different set of devices, it would be sub optimal.

Currently the MODE might be set by adding something like protocols.getMODE() which will iterate all protocols and get their enablement string to be added to MODE. But this is just another way to further hardwiring the two. What I'd like is the transport to query all the protocols in use in the current serial connection and make the MODE up.

In other terms, it might be useful to refactor transport and protocol decoupling them as much as we can, before thinking of a way to set the MODE.

d0ugal commented 10 years ago

The mode should be set once, in theory. You can set it and save it so its persistent after the device is restarted, otherwise it resets each time you turn it on and off. For simplicity we set it each time we startup. However, users of python-rfxcom may want to use devices that we don't support, so they should be able to manipulate what is and isn't enabled. I don't think you can do a mask update, you need to enable/disable all protocols in one operation.

So, for example, the user may have some home easy devices, currently they wouldn't be visible as we have not enabled them. The rfxtrx would ignore those packets and we then wouldn't receive them. The only way to work with them would be to send another mode packet after ours has been sent.

Does that clarify the first point?

d0ugal commented 10 years ago

I think your approach makes sense, so I as a python-rfxcom users passes in the different protocols we want to use, rather than it assuming all of them. It then figures out the correct mode from these and sets it.

kalfa commented 10 years ago

yes, I see home representing what you call 'users'. Home will allow somehow a configuration. The way it will do it does not matter, as long as it will be able to feed the loop with Transport+DeviceProtocol.

It makes sense for me to have the MODE set once at setup time. And it's also simpler. Also because I suppose that RESET+MODE means losing any packet arriving while this is happening. Unless the firmware does a really good job :smile: