lafrech/oem_gateway

Using RFM2Pi to send packets from another program

Closed this issue · 7 comments

Hi Jerome,

Would it be possible (for you) to make the gateway bi-directional? I am new with python - but by looking at your code, making the socket call ser.write(string) seems possible to implement, right?

Kind regards,
Troels

[Edit: Title modification - Jérôme]

Hi.

I don't understand what you mean. What would be the use case ?

You can write anything in the COM port. The limit is rather the RFM2Pi board, I believe. (But you can modify it as well).

What I want to do is having the gateway send data to a remote node, based on an event or manually entered. The remote node will then be able to fx blink an led.

The problem with writing in the COM port is - from what I have understood - that the gateway is occupying the serial port while running, meaning you will have to kill the gateway, send the message, and the start the gateway again. This I think could be solved with the socket.

Ok, now I think I get it.

On second thought, the RFM2Pi shouldn't be the limit. You can use it to send a packet to a node:
https://github.com/mharizanov/RFM2Pi/blob/master/firmware/Full_RF12demo_atmega328/Full_RF12demo_atmega328.ino

I wouldn't call that bi-directional, the logic is a bit different. The usual way, the gateway receives data from sources and routes it to a data display (processing and display, actually, with emoncms). It is also more or less capable to communicate with a source, for parametering, for instance, which you could use for what you want to do.

I would create a specific listener, one that would inherit from OemGatewayRFM2PiListener

class OemGatewayRFM2PiListenerCommander(OemGatewayRFM2PiListener):

and I would override the init() and run() function.

    def __init__(self, com_port, port_nb):

        # Initialization
        super(OemGatewayRFM2PiListenerCommander, self).__init__(com_port)

        # Open socket (see OemGatewaySocketListener)


    def run(self):
        """Comment"""

        # Execute run() method from parent
        super(OemGatewayRFM2PiListenerCommander, self).run()

        # Read commands from socket (see OemGatewaySocketListener)

        # Check if data received
        ready_to_read, ready_to_write, in_error = \
            select.select([self._socket], [], [], 0)

        # If data received, add it to RX buffer
        if self._socket in ready_to_read:

            # Accept connection
            conn, addr = self._socket.accept()

            # Read data
            self._rx_buf = self._rx_buf + conn.recv(1024)
            # Or if you know the frame length, conn.recv(length) 
            # and you don't have to check for end of line

            # Close connection
            conn.close()

        # Beware, the frame might be incomplete. Check for end of line.
        # If no complete frame, exit
        if '\r\n' not in self._rx_buf:
            return

        # This is where you decode the instructions. 
        # Otherwise, process first frame in buffer:
        f, self._rx_buf = self._rx_buf.split('\r\n', 1)

        # f is your frame, process it here

This is the idea. It is probably possible to do better with the socket handling.

Needs a bit more thinking, but maybe we can come up with a simplistic and generic protocol to provide RF frames via a socket, so that the code could be integrated in the trunk. The most simple is to let the frames be provided as is, and act as a repeater. In fact, our best choice here is probably a low-level repeater, while the logic that is specific to your project lies on the other side of the socket (and can be implemented in any programming language).

It's not much work. I'll keep that in mind. Tell me how it goes on your side. I'd be happy to integrate such a feature.

I am sorry for the confusion! I will take a look at the code you have provided and see what I can do. I will let you know if I get it working or run into trouble.

I am thinking that creating a (second) socket which can be called from python/php would be great - or even from emoncms as it could then be triggered by the event module. You are probably right that keeping the gateway as a repeater and then doing the processing of frames somewhere else is the most simple way to do it. In this case it will also become easier too to do different stuff; like sending data, changing freq and so on.

Don't be sorry. I was just trying to figure out what you meant. The logic of OEM gateway itself is a bit twisted, I admit. Partly for historical reasons.

I shall look into that as well, when I get the time. It is simple and useful.

Someone here seems interested as well: http://openenergymonitor.org/emon/node/2856

Hi.

I added a new listener: OemGatewayRFM2PiListenerRepeater

See recent commits.

Can you please have a look and tell me if it answers your need ?

As far as I used it, it worked.

(I use it so simulate inputs while testing other features.)

Closing. Please reopen if you think the feature is not satisfying.