Sunday, 28 October 2012

The UDP Interface (Again)

When I previously looked at the LightwaveRF UDP interface I got as far as:
  • Writing an application to poll for energy measurements.
  • Controlling the lights and sockets with an Android application.
The first bullet above was great but for two reasons it was less than ideal.  Firstly it relied on my PC being on all the time.  This is unlikely as it's a rubbish Vista PC and is used by the whole family.  Secondly, viewing results required me to open a CSV file and do some Excel jiggery pokery.

COSM (see previous post) was the answer to the viewing the results.  I just needed a way to have a reliable platform to periodically poll for energy measurements.  Continuing my plan to use an Android handset for my tinkering, I needed to find a way to get it to send UDP messages, detect the result and then post the results to COSM.

on{X} wasn't any use as, while it provides methods for using HTTP it doesn't do raw UDP.  A full Android application was possible but it's so much b*#% ache writing them that I didn't want to do this.  The answer came with a quick Google for "android script".  This led me to SL4A, a Google code project that provides a scripting environment for Android.  Basically you install SL4A and then further install various script interpreters (Python, Ruby, Perl, PHP) to work within it.  I chose to use Python as it sounds quite cool!

I set up my "server" using an old Samsung Galaxy S1 that my wife has grown out of.  It sits on my home WiFi with a fixed IP address (simple router config.) and can access any other system on my home WiFi.  As an easy example of what you can do, these 4 lines of code turns an Android handset in to a webserver.
import SimpleHTTPServer
from os import chdir
chdir('/sdcard/')
SimpleHTTPServer.test()
How easy is that!  Point another browser on your home LAN at http://127.0.0.1:8000 (replace IP address accordingly) and the Android device serves you pages.

So a simple script sends the UDP messages every minute:

import socket
import time

UDP_IP = '1.2.3.4'
UDP_PORT = 9760
INET_ADDR = (UDP_IP,UDP_PORT)

MESSAGE = "123,@?\0"

print "UDP target IP:", UDP_IP 
print "UDP target port:", UDP_PORT 
print "message:", MESSAGE

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

#sock.sendto(MESSAGE, (UDP_IP, UDP_PORT))

while True:
  sock.sendto(MESSAGE, INET_ADDR)
  print "done sending udp"
  time.sleep(60)

(Replace IP address with one relevant to you).

..and then a separate "server" script waits for results:

#Bind a socket 
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
sock.bind((UDP_IP, UDP_PORT))

#Now just loop unit you receive a response
while True:
    #Read data from the buffer
    data, addr = sock.recvfrom(1024) #buffer size is 1024               
    
    #Write to our debug log file
    WriteDebugLog("What we read from the buffer: " + data)

Strips out the individual parts:

    #Split the string and assign to variables  
    SplitMeasurement = MeasurementCSV.split(',')    
    WattsNow = SplitMeasurement[0]            #The power value for now (Watts)
    MaxWatts = SplitMeasurement[1]            #The max power today (Watts)
    CumToday = SplitMeasurement[2]            #Cumulative today (Watt Hours)
    TotalYesterday = SplitMeasurement[3]      #Total yesterday (Watt Hours)

...and sends to COSM:


 #Now do the HTTP magic - Connect to the server
  h = httplib.HTTP('api.cosm.com')
  
  # build url we want to request
  FullURL = 'http://api.cosm.com/v2/feeds/'+ FeedToUse + '/datastreams/' + DataStreamToUse + '/datapoints.csv'

  #Print the URI string we will use
  print "Full URL: " + FullURL
  
  # POST our data.  
  h.putrequest('POST',FullURL)    
 
  # setup the headers
  h.putheader('X-ApiKey',KeyToUse)
  h.putheader('Content-Length',MyStrLen)   

  # we're done with the headers....
  h.endheaders()
  
  #Send the data
  h.send(MyDateTimeString)

Then you get to see the results on COSM:
So here you can see it being quiet around noon when we were out, spikes of usage across the afternoon and then sustained usage in the evening.
Also, based upon a)the cumulative Wh figure and b)knowledge of my electricity tariff (kWh figure and daily standing charge) I can chart the cumulative cost of electricity for each day:

So it cost us roughly 37p to cook our tea tonight!