How to send feed data from emoncms to emonGLCD?

Hi there,

I am running an emoncms/emonHub installation on a Raspberry Pi which is receiving data from an emonTX and an emonTH.
Additionally the Pi is posting other data directly into emoncms. Now I would like to display this data on my emonGLCD. Also displaying emonTX data after processing in emoncms would be very interesting.

I've read in an other thread that this is a planned feature for emonHub in the future - for now it can be done by adding a "hack" to emonHub.

@pb66: Paul, could you explain what I have to do to send out an emoncms feed value, let say, every 20 seconds?

Thank you very much

Matthias

pb66's picture

Re: How to send feed data from emoncms to emonGLCD?

In the not so distant future I hope emonHub will have the ability to route data from one source to another directly, but for the moment the easiest route is to "fetch" a value(s) from emoncms.

To "fetch" multiple feed values in a single request

so the idea is to "fetch" the feed values from emoncms and send them out over the RFM network much the same way the "PacketGen hack" works.

Using Emonhub with the emoncms PacketGen module

Won't need to install packetgen​, but will still need to import urllib2, you will also need to import struct.

The main bit that needs changing is the 2 "packet" lines

    packet = urllib2.urlopen("http://localhost/emoncms/packetgen/rfpacket.json?apikey=APIKEY").read()

    packet = packet[1:-1]

The first one will need to be changed to "fetch" the feed values by id number. This will return float values that need to be converted to byte values for transmission. The second line will need some experimenting probably but you can try replacing it with something like, which should unpack each float into 4 byte values

packet = packet.split(' ')
f=[]
for value in packet;
      bytes = struct.unpack('<B'*4, struct.pack('<f', value))
      for byte in bytes;
            f.append(byte)
packet = f

I haven't tested this at all so may need some debugging (who am I kidding? it almost definitely will need debugging) there's certainly enough there to get the gist at least.

The pit fall of using a url request is that if there is no response it can block emonhub from continuing until it times out,

You may want to re think how the data arrives at the emonGLCD, if you have 3 sources time, hack and emonth/tx it will weigh heavily on the glcd sketch, so you may want to amalgamate payloads by getting all data from emoncms.

​If you squeeze it all into one payload you could use the existing timer rather than adding the packetgen one.

Sending a time update to emonGLCD from emonHub 

I'm not really the guy to help you with the glcd sketch but I'm happy to help with the emonhub end of things.

Paul

pb66's picture

Re: How to send feed data from emoncms to emonGLCD?

What are the value ranges of the emoncms values (min, max and decimal precision)? the payload size can be reduced by not using 4 byte floats.

McFly's picture

Re: How to send feed data from emoncms to emonGLCD?

Hey Paul,

thank you very much for your detailed description.
Although Python is really new to me (I am familiar with microcontrollers and C) I got it working finally ;-)

I followed your advice to get all data, which is to be displayed on emonGLCD, from emoncms feeds. So I am using the _send_time() function to send out all necessary data.

Here is how my _send_time() functions looks like now:

        """ Send time and feed data to emonGLCD """
        packet = urllib2.urlopen("http://localhost/emoncms/feed/fetch.json?ids=12,22,27&apikey=my_read_api_key").read()
        self._log.info(self.name + " broadcasting feed values: " + packet)
        packet = packet.translate(None, '"[]')
        
        sendstr = "%02d,%02d,%02d,%02d," % (now.day, now.hour, now.minute, now.second)
        packet = packet.split(',')
        for value in packet:
            bytes = struct.unpack('BBBB', struct.pack('<i', int((float(value) + 0.05) * 10)))
                
            for byte in bytes:
                sendstr = sendstr + "%d," % int(byte)

        sendstr = sendstr + "s"
        self._ser.write(sendstr)

I add 4 bytes for date/time information at the beginning, then send out the feed values multiplied by 10 (and rounded to get one decimal place precision).

On the emonGLCD side I receive the data with this structure:
typedef struct { uint8_t day, hour, minute, seconds;  int32_t data1, data2, data3; } PayloadHub;

Thank you very much for pointing me in the right direction - I really appreciate it!

Best regards,

Matthias

 

pb66's picture

Re: How to send feed data from emoncms to emonGLCD?

Fantastic, thanks for sharing your solution. Constructing the string as you go makes far more sense than appending to a list, I prefer your way. May I ask what the translate line is for ? (I'm not a programmer so forgive me if it's obvious)

Paul

McFly's picture

Re: How to send feed data from emoncms to emonGLCD?

The translate function is for removing some unwanted characters from the string.
From emoncms you get something like this: ["2195","5.424","1"]
To use it with the split function, I remove the brackets and the quote signs to get this: 2195,5.424,1

Matthias
 

pb66's picture

Re: How to send feed data from emoncms to emonGLCD?

Ah, yes of course! I did raise a question about the format of the returned data a while back on git https://github.com/emoncms/emoncms/issues/273 , but that's quite a effective way of "trimming off the fat"

Paul

modenet's picture

Re: How to send feed data from emoncms to emonGLCD?

Hi, I'm using packet gen such described here https://github.com/emoncms/emoncms/blob/low-write/docs/emonhubmod.md#usi... .

I send to emonglcd the outer temperature readed from emoncms, all is ok, but if the temperature is under 0 I receive a strange value, how to decode negative value?

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.