In this project we take a Raspberry Pi 2 and use it to send some pH data to the Microsoft Cloud. The Raspberry Pi 2 seems like it might be overkill for this purpose but there are a few other nice things that we can do with this computer. We can write a few estimation algorithms to "clean up" the noisy output of the sensor. This work will mostly be done in Python while the work on the microsoft Azure side will be mostly in NodeJS for now. We use Microsoft's DocumentDB framework to store the data and retrieve it. We are also making the hardware side open source so feel free to also use "portal-0"

Embedded Code Overview

The purpose of this file is to initialize the communication with the Atlas Scientific probe and then write it to a file. It just repeats this process endlessly. You should probably run it in the background. You could also take out the 'print' statements but I leave them in there so you can 'see' it working on the embedded side.

import serial # required for communication with boards
import time, datetime
from time import strftime # used for timestamps

#USB parameters
usbport = '/dev/ttyACM0'
ser = serial.Serial(usbport, 9600, timeout = 0) # sets the serial port to the specified port, with a 9600 baud rate
# Timeout = 0 tells the serial port to not wait for input if there is non 

# declare and initialize the data buffers
line = "" 
user_input = ""

#clear serial buffer

#turn on LEDS

#enable streaming

def check_ph_level(line):
    # compares the ph reading to a value and displays if its higher or lower
        ph = float(line) # converts the string into a floating point number
        if(ph >= 7.5):
            print("High"+ "\n")
        if(ph < 7.5):
            print("Low"+ "\n")
    except ValueError:
        # if the string is not a valid floating point number, dont do anything
filename = "data.txt" ## "/hummingbirdembedded1/models/data.txt" ## "
#main loop
while True:
    # sensor receive
    data = # get serial data
    if(data == "\r"): # if its terminated by a newline
        print("> " + strftime("%Y-%m-%d %H:%M:%S") + 
        " Received from sensor: " + line + "\n") #print the timestamp and received data to the main screen
        check_ph_level(line) # calls function to check ph levels
        with open(filename,"r+") as f:
            f.write("P " + line)
        line = "" # clears the input
        line  = line + data # if the line isn't complete, add the new characters to it

Here is how you post the data. Like I said we are giving out the key for anyone to post to our service. You can also see the hash algorithm. This took awhile to figure out so I hope someone can benefit from it.

import re, requests, json ,datetime, time
import urllib
import hashlib
import hmac
import base64

class sensor(object):
    def __init__(self, sType=None, value=None, unit=None, status=None):
        self.sType = sType
        self.value = value
        self.unit = unit
        self.status = status
class Device(object):
    def __init__(self, power=None, sensor=sensor, ID=None, name=None, version=None, deviceStatus=None):
        self.deviceStaus = deviceStatus
        self.power = power
        self.sensor = sensor
        self.ID = ID = name
        self.version=  version

def uploadData():
    sD = ""
    key = 'YOMfbmtih/oEERPw3u3ha2wazXR0N2uSFsN61+cKjpM='
    url = ''
    keyName = 'DevicePolicy'
    now = datetime.datetime.utcnow()
    then = datetime.datetime(1970, 1, 1, 0, 00, 00, 000000)
    expiry = str(int((now-datetime.datetime(1970,1,1)).total_seconds())) ##  '1440710529' ## 
    ##print str(expiry)
    resourceUri = urllib.quote_plus(url).lower()
    message = bytes(resourceUri).encode('utf-8') + '\n' + expiry
    ##print message
    secret = bytes(key).encode('utf-8')
    ##print secret
    signature = urllib.quote_plus(base64.b64encode(,message,hashlib.sha256).digest()))
    ##print signature
    signature = re.sub("(%[0-9A-F][0-9A-F])", lambda m:, signature);
    ##print signature
    token = "SharedAccessSignature sr={0}&sig={1}&se={2}&skn={3}".format(unicode(resourceUri,'utf-8'), unicode(signature,'utf-8'), unicode(expiry,'utf-8'),  unicode(keyName,'utf-8'))
    ##print token
    filename = "data.txt" ## "/hummingbirdembedded1/models/data.txt" ## "
    with open(filename,"r+") as f:
        d = str(f.readlines()) ## Get the datafile
    for s in d:
        sD = sD + s ## dump the line into a string    
    if "P" in sD:
        indL = d.index("P") ## get the index of the measurment in the array

        sensorList = []

        deviceStatus = []
        deviceStatus.append(Device("100", sensorList, "00PH-0000-0000-0000","000PH", ""))
        payload = json.dumps({
                    'DeviceId' : deviceStatus[0].ID,
                    'Name': deviceStatus[0].name,
                    'DeviceStatus': 'Remove this field',
                    'PowerStatus': deviceStatus[0].power,
                    'SoftwareVersion': deviceStatus[0].version,
                    'Time' : str(now),
                    'Sensors':  {sensorList[0].sType : sensorList[0].value}
        print payload
        headers = {'Authorization':'%s' % token}
        r =, data=payload, headers=headers)
        print r.status_code
        print "file poorly formed. wait another cycle"

while True:

The last step is to visit portal-0 and see the pH information you're uploading.