Posting 1-wire/RasPi data to Xively without third-party libraries – the simple way

Recently I connected to Xively (you know, the site accepting your environmental data, keeping it and letting you manage it for free – roughly speaking) with Raspberry. I just wanted to send some temperature data with the very famous  1-wire solution. Other help here.

There is a plenty of info about what software to use. I lately fell in love with python, so the language had to be that. If you look for help, you will find that Xively itself and Tinkerforge gives you some handy… pieces of python, and the same with the library owfs  but:

  • Xively gives a library with a full API, very useful but too large for my needs
  • Tinkerforge’s library is based – obviously and rightly – on the hardware they sell. Too large again.
  • OWFS shares – IMHO – the same problems as the Xively one: too large
  • all of them need to be downloaded, installed, etc.
  • really do we need a library? At the end of the day we just must send a PUT call to the HTTP(S) server

So I ended up with a personal version based on the – anyway well done – Tinkerforge version. Mine is “pure python”, using just and only the normal python installation. Probably you still will want to work to refine the code, but that could be considered a good starting point. Here it is:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import socket
import sys
import time
import math
import logging as log
import httplib
import json
import threading

log.basicConfig(level=log.INFO)

MIN_TEMP = -100

def read_temperature():
    # the following code will be different in your case
    tfile = open("/sys/bus/w1/devices/28-0000046ca58d/w1_slave") 
    text = tfile.read()
    tfile.close()

    lines = text.split("\n")

    if lines[0].find("YES") > 0:
        temp = float(lines[1].split(" ")[9][2:])
        temp /= 1000
        return temp
    return MIN_TEMP - 1

class Xively:
    HOST = 'api.xively.com'
    AGENT = "my-agent"
    FEED = 'FEED-ID'
    API_KEY = 'unreadeable-code-given-by-xively'

    def __init__(self):
        self.items = {}
        self.headers = {
            "Content-Type"  : "application/x-www-form-urlencoded",
            "X-ApiKey"      : Xively.API_KEY,
            "User-Agent"    : Xively.AGENT,
        }
        self.params = "/v2/feeds/" + str(Xively.FEED)

        self.upload_thread = threading.Thread(target=self.upload)
        self.upload_thread.daemon = True
        self.upload_thread.start()

    def put(self, identifier, value):
        try:
            _, min_value, max_value = self.items[identifier]
            if value < min_value:                 
                min_value = value             
            if value > max_value:
                max_value = value
            self.items[identifier] = (value, min_value, max_value)
        except:
            self.items[identifier] = (value, value, value)

    def upload(self):
        while True:
            time.sleep(10 * 60) # Upload data every ... min
            if len(self.items) == 0:
                continue

            stream_items = []
            for identifier, value in self.items.items():
                stream_items.append({'id': identifier,
                                     'current_value': value[0],
                                     'min_value': value[1],
                                     'max_value': value[2]})

            data = {'version': '1.0.0',
                    'datastreams': stream_items}
            self.items = {}
            body = json.dumps(data)

            try:
                http = httplib.HTTPSConnection(Xively.HOST)
                http.request('PUT', self.params, body, self.headers)
                response = http.getresponse()
                http.close()

                if response.status != 200:
                    log.error('Could not upload to xively -> ' +
                              str(response.status) + ': ' + response.reason)
            except Exception as e:
                log.error('HTTP error: ' + str(e))

#========================
if __name__ == "__main__":

    log.info('Start')

    xively = Xively()
    i = 0
    while True:
        i += 1
        print('reading ' + str(i))
        temp = read_temperature()
        xively.put('temperature', temp)

        time.sleep(60)

    log.info('End')
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s