push data to emoncms with python

Hi everyone

I have pieced together a python script, from various sources, for loading DS18B20 sensors and reading temperatures directly from pin 4 on a Raspberry Pi. So long so good, but i am having problems forwarding the data to emoncms.
The url seems to be setup correctly and i have used the same way for URL-requests as here: https://github.com/emoncms/raspberrypi/blob/master/rfm2pigateway.py

None the less nothing is being updated in the database one the raspberry.

Output:

pi@raspberrypi ~ $ python sensorRead.py
http://localhost/emoncms/input/post?json={28-000003f1cbe0:2256,28-0000040cd9ec:2256,28-000003f1d3c3:2262}
http://localhost/emoncms/input/post?json={28-000003f1cbe0:2262,28-0000040cd9ec:2256,28-000003f1d3c3:2262}

 

The script:

import os
import glob
import time
import urllib2, httplib

os.system('sudo modprobe w1-gpio')
os.system('sudo modprobe w1-therm')
base_dir = '/sys/bus/w1/devices'

f = open(base_dir + '/w1_bus_master1/w1_master_slave_count', 'r');
sensorCount = f.readlines()
sensorCount = [int(l[0]) for l in sensorCount]
f.close()
f = open(base_dir + '/w1_bus_master1/w1_master_slaves', 'r');
devices = f.readlines()
f.close()

 

def read_temp_raw(sensor):
    device_file = base_dir + '/' + devices[sensor][:-1] + '/w1_slave'
    f = open(device_file, 'r')
    lines = f.readlines()
    f.close()
    return lines
def read_temp(sensor):
    lines = read_temp_raw(sensor)
    while lines[0].strip()[-3:] != 'YES':
        time.sleep(0.2)
        lines = read_temp_raw(sensor)
    equals_pos = lines[1].find('t=')
    if equals_pos != -1:
        temp_string = lines[1][equals_pos+2:]
        return temp_string[0:4]

while True:
url = "http://localhost/emoncms/input/post?json={"

for x in range(0, sensorCount[0]):
  url = url + devices[x][:-1] + ":" + read_temp(x) + ","

url = url[:-1]+"}"
print(url)
urllib2.urlopen(url)
time.sleep(10)

 

 

Does anybody have a clue on what is going wrong?

 

Kind regards, 

Emil Bunk

 

 

Jérôme's picture

Re: push data to emoncms with python

Hi.

Glad to have another pythonist here.

You can test your URLs aside the python script with wget or a browser such as links.

I'm wondering if this is not an apikey issue. Try this:

- http://localhost/emoncms/input/post?json={28-000003f1cbe0:2256,28-0000040cd9ec:2256,28-000003f1d3c3:2262}

+http://localhost/emoncms/input/post?json={28-000003f1cbe0:2256,28-0000040cd9ec:2256,28-000003f1d3c3:2262}&apikey=your_read_write_apikey

 

Jérôme's picture

Re: push data to emoncms with python

I'd like to say you can import rfm2pigateway.py, then instantiate class ServerDataBuffer.

Instantiation :

my buffer = ServerDataBuffer(
                    gateway = self,
                    protocol = 'http://',
                    domain = 'localhost',
                    path = '/emoncms',
                    apikey = s_new['apikey'],
                    period = 0,
                    active = True)
 
then use add_data() and send_data() functions.
 
Except I was not clever enough when I did the design and the ServerDataBuffer needs a Gateway instance for the logging. I'll fix this because now that I realize it, I really think it sucks. I knew it was twisted design when I did it but I didn't think enough, and now I think I know what to do.

 

Jérôme's picture

Re: push data to emoncms with python

Fix commited and pull request sent:

https://github.com/emoncms/raspberrypi/pull/26

With this commit, you can try to import rfm2pigateway and use the ServerDataBuffer class in your script.

emilb's picture

Re: push data to emoncms with python

Pythonist, don't know if i would call myself that. This is my first pythonscript, it just seemed like the easy way to access the sensors (red. somebody else wrote the most of the script)

I tried out the URL and it works fine if i run it with a browser. I thought about the api-key too, but it seemed like a overkill to access the database, just to retrieve the api-key. But i will try it out and see if i have more luck :)

Thanks for the quick response

Jérôme's picture

Re: push data to emoncms with python

You're welcome.

You don't have to access the database to get the key.

You can hardcode it, obviously...

Or you can use the new API from emonCMS v5, just like I did in the python script. See function get_settings().

Accessing the DB would mean hardcoding DB login parameters in the script. Not much better than hardcoding the apikey itself. I'm using the csv module because sometimes separating stuff with special characters could be a little tricky.

Regarding the format to send data, I suppose you saw the API help link in the Input menu.

The ServerDataBuffer class I wrote uses the "bulk mode" which means you can't add names to the inputs. It may be a good idea to use the json format where names can be added but it might not be that simple, since I'm not sure this method allows to send samples with different times.

emilb's picture

Re: push data to emoncms with python

Make sense and that would be an obvious reason to avoid using the API-key, so no hardcoding was needed. Don't we agree that the rfm2pigateway, uses the same way to request/visit the URL as i have tried? with the only difference being; not including the api-key.

I have also tried this methode: https://github.com/openenergymonitor/EmoncmsPythonLink/blob/master/pylink.py
again no luck.

About the input names, i wanted to add the sensor address as names because they are unique, which will make locating the sensors way easier, if one is reading something out of range. I plan on marking every sensor with its address. (The system i am working on is to be used in vaccine cold room facilities and therefore it should be possible to add and remove sensors as needed)

There is no need to send samples with different time stamps, so that should not be a problem.
I will try out your method later today.

Jérôme's picture

Re: push data to emoncms with python

I'm not sure I understand your first paragraph.

I believe adding the hardcoded apikey works for you, right ?

You can take inspiration in rfm2pigateway for the part where you get the settings (including the apikey) through the API if you don't want it hardcoded.

I now realize it is a bit weird that you need the apikey to post locally, but you can get it for free with a local post through the API. In short, why not authorize a local post without the apikey in the first place ? Historical reasons, I guess.

rfm2pigateway does not use the same syntax as yours to send data samples. See here: http://openenergymonitor.org/emon/node/2249. I think you understood that

You'd rather stick to your way as it makes sense to have names for the inputs and you don't do sample buffering. This means you can't use the ServerDataBuffer class as I wanted to suggest you. No big deal, recreating the URL string isn't so difficult. I just like reusable code and I'd like to address this.

 

emilb's picture

Re: push data to emoncms with python

I'm sorry if i have not made myself clear. Im still quite new to; python, emoncms and all that follows :)

To make things clear:
I have not tried with a hardcoded api yet. But it does work without the api-key through a browser, so if i request:
http://localhost/emoncms/input/post?json={28-000003f1cbe0:2256,28-0000040cd9ec:2256,28-000003f1d3c3:2262}
in the browser on the raspberry, it does make 3 inputs, with the 3 addresses as names and the matching readings, which is what i need.

But the urllib2.open(URL) however does nothing.
urllib2.urlopen(http://localhost/emoncms/input/post?json={28-000003f1cbe0:2256,28-0000040cd9ec:2256,28-000003f1d3c3:2262})

And i two want reusable code, that was why i wanted to avoid the api-key altogether.

Jérôme's picture

Re: push data to emoncms with python

I believe you need to add the apikey to post from a browser, unless you're logged in the emoncms interface with the same browser.

Are you saying you can post from your browser without the apikey and without being logged in ? Is this a browser on the Pi ?

 

emilb's picture

Re: push data to emoncms with python

Of course!  didn't think about the login at all, i was logged in when i tried the link. Okay, this should be fixed by adding the API-key, but as we talk about before it would be nice that the script worked without hardcoding an API-key. So is it possible to pull the api?

Thanks again for all your help! :)

Jérôme's picture

Re: push data to emoncms with python

Yes, it is possible. It is what I do in the python script.

You can take inspiration in rfm2pigateway for the part where you get the settings (including the apikey) through the API if you don't want it hardcoded. See function get_settings().

I hope the comments make it clear enough. I'm not a much experienced pythonist myself, I don't use those cryptical one-line-does-it-all instructions, my code is rather step-by-step styled.

emilb's picture

Re: push data to emoncms with python

i think i got the part that i need, however it seems like the get_settings() fails.

This is what i use to get the api:

def get_api():
result = urllib2.urlopen("http://localhost/emoncms/raspberrypi/get.json")
result = result.readline()

result = result[1:-1].split(',')
settings = {}
for s in result:
     s = csv.reader([s], delimiter=':').next()
     settings[s[0]] = s[1].replace("\\","")
return settings['apikey']

with following error:
settings[s[0]] = s[1].replace("\\","")
IndexError: list index out of range

I will admit that i haven't looked into how it works entirely, but in my understanding this should be sufficient for pulling the api.

 

emilb's picture

Re: push data to emoncms with python

I'm still having problems with pulling the api and it will also crash if you remove a sensor. But side from that, everything is working!

Thanks alot for your help Jerome

Jérôme's picture

Re: push data to emoncms with python

You're welcome.

Try this an see what happens:

def get_api():
result = urllib2.urlopen("http://localhost/emoncms/raspberrypi/get.json")
print result
result = result.readline()
print result
result = result[1:-1].split(',')
print result
settings = {}
for s in result:
     print s
     s = csv.reader([s], delimiter=':').next()
     print s
     settings[s[0]] = s[1].replace("\\","")
return settings['apikey']

You get the point.

If this doesn't help. Use the python interpreter, do the imports, and then

result = urllib2.urlopen("http://localhost/emoncms/raspberrypi/get.json")
result.readline()

To see what is returned. There should be only one line, with the settings.

 

 

 

 

emilb's picture

Re: push data to emoncms with python

Hi Jerome, 

It returns nothing, the result is empty. ? Im alittle confused, the path emoncms/raspberrypi/ does not exist, shouldn't it be under /var/www/emoncms/raspberrypi?

Jérôme's picture

Re: push data to emoncms with python

When logged on my rasp, if I issue

$ wget http://localhost/emoncms/raspberrypi/get.json

I get a file with the following content:

{"userid":"1","apikey":"my_apikey","sgroup":"210",... and all my settings}

I can launch a python interpreter and execute the following commands:

python
Python 2.7.3 (default, Jan 13 2013, 11:20:46)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import urllib2
>>> result = urllib2.urlopen("http://localhost/emoncms/raspberrypi/get.json")
>>> result.readline()

and I get the same result.

Don't you ?

 

emilb's picture

Re: push data to emoncms with python

I am still getting nothing :/

 

pi@raspberrypi ~ $ wget http://localhost/emoncms/raspberrypi/get.json
--2013-04-18 22:32:46--  http://localhost/emoncms/raspberrypi/get.json
Resolving localhost (localhost)... 127.0.0.1, ::1
Connecting to localhost (localhost)|127.0.0.1|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 0 [text/html]
Saving to: `get.json'

    [ <=>                                                                         ] 0           --.-K/s   in 0s     

2013-04-18 22:32:46 (0.00 B/s) - `get.json' saved [0/0]

Jérôme's picture

Re: push data to emoncms with python

I didn't answer your question. No, you don't need it to be under /var/www/emoncms/raspberrypi. It's a rewrite rule. emoncms/whater goes into emoncms/Modules/whatever. Roughly speaking.

You did install the raspberrypi module, right ?

I don't see why you would have http://localhost/emoncms/input/post working, but not http://localhost/emoncms/raspberrypi/get.json

Perhaps could you have a look in the apache log ?

/var/log/apache2/error.log

emilb's picture

Re: push data to emoncms with python

Something was definitely wrong with the RPi module. None of the init scripts were there. I didn't do the installation of emoncms myself. I believe my supervisor has been messing around with things. I have made a new SD card from scratch and things seems to work now.

Thanks a lot,

Jerome :)

I will post the script for mounting multiple DS18B20 sensors on the Pi, when I have fixed a few bugs.

Comment viewing options

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