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!






Saturday, 20 October 2012

A COSM(ic) Experience

The answer to my "what should I do with my on{X} measurements" came again from the internet of things Twitter feed.  The answer was COSM, an online system designed to allow all and sundry measurements to be uploaded, stored, graphed and shared.  COSM publish an API that can be used to add, remove and edit measurements.

Some simple on{X} code like this:


device.ajax(
      {
      url: 'http://api.cosm.com/v2/feeds/' + MyFeedID + '/datastreams/' + MyDataStream + '/datapoints.csv',
      type: 'POST',
      headers: {
        'X-ApiKey': MyAPIKey
        //'Content-Length': '30',
        //'Content-Type': 'text/csv',
        //'Accept': 'text/csv'
      },
      data: StringToSend
      //data: '2012-09-30T22:00:00.676045+01:00,66'
    }


...allows battery measurements to be uploaded.  Here MyFeedID, MyDataStream and MyAPIKey are variables that hold various things associated with my COSM account.  It's very easy to get an account, set up a feed (in my case my Android handset), a datastream (in this case battery) and a API key.  You then just post data to the API in the format shown on the penultimate line above.  It took a bit of tinkering to get right, (hence all the //comments I've not removed yet), but in the end was not too hard.

Doing this allows you to produce graphs like this:

Here we can see battery measurements that I take and upload every 15 mins.  So what does this tell me? 
  • When I charge my battery the battery % goes up (what a surprise!).
  • When I don't charge the battery the % goes down (wow!).
  • AC charging is quicker than USB charging.
  • With the handset idle it uses less battery than when active (e.g.on a call).
  • There's an interesting charging profile to be seen on the right of the chart.  As the battery charges it starts fast, then slows down (sort of exponentially) then the last ~20% jumps up somewhere between 2 15 minute intervals.  

Now to take more measurements and see if they are useful!

Saturday, 13 October 2012

First Step on the Internet of Things

Right, I've taken the summer off while the nights have been longer,Olympics in London, holiday etc.  However a chance encounter with a particular twitter feed inspired me to tinker some more.

Overall this stems from the stuff I did to take power measurements at home and graph them.  The question was, how can I do this more of this kind of thing in a simpler way.  It also stems from an observation that in a smartphone we have an amazing platform to do stuff with; a screen, keyboard input, WiFi and cellular connectivity,GPS, microphone and speaker, light sensor,accelerometer, application development environment.

It was the latter that always proved a blocker.  I've been able to develop an app for my Android device but always found it to be a pain.  Maybe it was my PC but the IDE and SDK was very flakey and the fact that you split GUI, code and constants across multiple files was a barrier for entry for me as a novice tinkerer.  Whenever I had spare time to do stuff I spent most of it setting up the environment and wrestling with it.  What I needed was a simpler solution....

The answer came through a Twitter feed that I subscribe to.  It's "Internet of Things" (@TheIoT) and the owner shares various interesting stories on M2M, the internet of things and the maker movement. One day they shared information on something called on{X}, an Android application + website that has been developed by Microsoft.

The idea of on{X} is that it provides a simple environment to a)detect a change in state on your handset and b)do something about it.  Best explained by a few examples "recipes" that they provide:

  • Automatically reply "I'm in a meeting, will call you back." when one of my contacts calls during a meeting
  • Text "Good morning" to my friend every Wednesday at 8:00 AM
  • Turn WiFi on when I arrive at work
So detect a time/location/change in state on your handset and do "something".

With on{X} installed on your Android handset you can write Javascript code on the partner website and automatically send it to your handset where at once it starts working.  The Javascript is very simple and insulates you from the underlying Android APIs. This means it's very quick to setup, write code, publish it to your handset, test, modify and so on.  The downside is little or no support for UI but this is not what I'm interested in.

The code segment below shows how you can the handset to detect that the screen has been unlocked,  pop a notification to the notification bar and turn WiFi on.



I've tinkered with loads of stuff but most recently I have scripts running all the time on my handset that:

  • Wake up every 15 minutes and log the battery charge level.
  • Wake up every 15 minutes and log the sound level measured by the handset microphone.
  • Wake up every 15 minutes and log my location.
  • Log when I enter and exit various "regions" (defined by lat + long and a radius value).  I also turn on WiFi when I come home (to save using cellular data). 
I now just need to work out what to do with these measurements....