User Tools

Site Tools


oak:tutorials:python-get

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

oak:tutorials:python-get [2016/03/24 18:54] (current)
jwhendy created
Line 1: Line 1:
 +===== Oak: using python and Particle.variable() to get data from the Oak =====
 +
 +In this example, we'll show one way you can make the data sent by the Oak useful with ''​python''​. You can install python as described in [[oak:​tutorials:​serialfirmware|the firmware over serial]] tutorial. Make sure for the below that you're using ''​python''​ version 2.x (e.g. 2.7), not ''​python''​ v3.
 +
 +===== Components used =====
 +
 +^Part ^Quantity ^Identification^
 +|Oak with solid headers | 1 | |
 +|Breadboard | 1 | |
 +|Temperature sensor | 1 | |
 +|Battery pack | 1 | |
 +|Jumper wires | 3 | |
 +
 +To verify your ''​python''​ environment,​ open a Command Prompt or terminal and type ''​python''​ and press enter. If ''​python''​ is working properly, you should enter a session:
 +
 +<​code>​Python 2.7.11 (default, Mar  3 2016, 11:​00:​04) ​
 +[GCC 5.3.0] on linux2
 +Type "​help",​ "​copyright",​ "​credits"​ or "​license"​ for more information.
 +>>> ​
 +</​code>​
 +
 +If that happens, you're all set! If not, you should get ''​python''​ in order before proceding. Type ''​quit()''​ and press enter to quit this session.
 +
 +===== Concepts =====
 +
 +=== python ===
 +
 +''​python''​ is a [[https://​www.python.org/​|programming language]]. It offers a wide range of capabilities through "​modules"​ which can be imported. Since it has wide adoption as a good general programming language and is relatively fast, it is used in many fields for academic and industry purposes. The modules make it very easy to do certain tasks without having to write the code yourself.
 +
 +For some examples, it is easy to grab web pages with the module ''​urllib'',​ easy to import and read json data with the ''​json''​ module, and ''​smtplib''​ will make it very simple to send an email with ''​python'',​ as shown below. Since you will often want to use a computer of some sort to act on the data you collect with the Oak, knowing a little about how to program is a a useful skill.
 +
 +===== Circuit =====
 +
 +This tutorial will utilize a TMP36 analog temperature sensor, but a [[http://​digistump.com/​wiki/​oak/​tutorials/​onewiretemp|digital temperature sensor]] or anything that can generate a changing value read by the Oak will work. The circuit is quite simple:
 +
 +[[http://​digistump.com/​wiki/​_media/​oak/​tutorials/​fritz-tmp36-battery.png|{{http://​digistump.com/​wiki/​_media/​oak/​tutorials/​fritz-tmp36-battery.png?​400|}}]]
 +
 +Here's the setup in real life, with the outer TMP36 pins plugged directly into Vcc and ground, and a soldered jumper connecting the middle pin to ''​A0''​. It's connected to power using a surplus store 4 x AA battery pack. You could jumper everything to a breadboard just as well if you don't have access to a soldering iron.
 +
 +[[http://​digistump.com/​wiki/​_media/​oak/​tutorials/​tmp36-hookup.jpg|{{http://​digistump.com/​wiki/​_media/​oak/​tutorials/​tmp36-hookup.jpg?​400}}]]
 +
 +
 +===== Code ======
 +
 +=== Oak: reading the sensor ===
 +
 +To read the temperature,​ we'll convert the analog reading to millivolts and then to degrees Celsius as described in [[https://​learn.adafruit.com/​tmp36-temperature-sensor/​using-a-temp-sensor|this Adafruit tutorial]]. The variable will be accessible through the ''​Particle.variable()''​ function, which we'll read with ''​python''​ and then use to email a notification when it falls below a certain level.
 +
 +Here's the Oak code:
 +
 +<​code>​
 +double tempC = 0;
 +int analog = 0;
 +double mv;
 +
 +void setup()
 +{                ​
 +
 +  // the Particle.variable() function takes two arguments:
 +  // 1) the name of the Particle variable. This is how you interact
 +  //    with the Particle cloud to access the value
 +  // 2) the local variable name to be stored in the cloud variable
 +  Particle.variable("​temp",​ tempC);
 +
 +  // we'll configure the on-board LED to blink
 +  // this is handy for simply making sure the Oak is running your sketch
 +  pinMode(1, OUTPUT);
 +  digitalWrite(1,​ LOW);
 +  pinMode(A0, INPUT);
 +  ​
 +}
 +
 +
 +void loop()
 +{
 +
 +  // with the tmp36, the temperature is found using this formula:
 +  // temp in C = (millivolts out - 500)/10
 +  // we're reading an analog value (0-1023) which is proportional
 +  // to the analog reference voltage, which on the Oak is 3.3v for Vcc.
 +
 +  // get the analog value
 +  analog = analogRead(A0);​
 +
 +  // convert to millivolts
 +  // if your temperature readings are incorrect; adjust the 2700 value below
 +  // this *should* be 3300 for a 3.3V analog device, however plain and simple
 +  // sometimes the sensor needs calibration
 +  mv = analog * 2700.0 / 1024.0;
 +    ​
 +  // convert from mV to degrees C
 +  tempC = (mv - 500.0) / 10.0;
 + 
 +  // flash the LED
 +  digitalWrite(1,​ HIGH);
 +  delay(100);
 +  digitalWrite(1,​ LOW);
 +  delay(500);
 +  ​
 +}
 +</​code>​
 +
 +After uploading this sketch, we can do a test call to the Particle API as described in the [[oak:​tutorials:​particle-variable|Particle.variable() tutorial]].
 +
 +==== Testing the code ====
 +
 +<​code>​
 +$ curl https://​api.particle.io/​v1/​devices/​id_here/​temp?​access_token=token_here
 +{
 +  "​cmd":​ "​VarReturn",​
 +  "​name":​ "​temp",​
 +  "​result":​ 19.609375,
 +  "​coreInfo":​ {
 +    "​last_app":​ "",​
 +    "​last_heard":​ "​2016-03-20T17:​44:​21.275Z",​
 +    "​connected":​ true,
 +    "​last_handshake_at":​ "​2016-03-20T17:​43:​52.080Z",​
 +    "​deviceID":​ "​12345678",​
 +    "​product_id":​ 82
 +  }
 +</​code>​
 +
 +=== Code: reading the Particle data with python ===
 +
 +With that working properly, let's go about reading that data from a computer using ''​python''​. For the utter basics, we need to import ''​urllib''​ and ''​json''​ to get the API response and read it in. We've added some other modules in order to delay a loop (''​time''​),​ get the current time (''​datetime''​),​ and send an email (''​smtplib''​ and ''​MIMEText''​). The core of the functionality is simply in getting and parsing the data; save the following code as ''​temp-get.py'':​
 +
 +<​code>​
 +## import what we need
 +import urllib
 +import json
 +
 +## simplify the url a bit
 +## replace placeholders for device_id and token below!
 +base = "​https://​api.particle.io/​v1/​devices/"​
 +device_id = "​device_id_here"​
 +token = "​token_goes_here"​
 +
 +## change this if you used a different Particle.variable() name
 +var = "/​temp"​
 +option = "?​access_token="​
 +
 +## put together the full url to query
 +url = base + device_id + var + option + token
 +
 +# opens/reads the URL and then parses the json response
 +data = urllib.urlopen(url).read()
 +data_json = json.loads(data)
 +
 +## gets the json value under the "​result"​ key
 +temp = round(float(data_json["​result"​]),​ 2)
 +
 +print temp
 +</​code>​
 +
 +Each time you run the code above, ''​python''​ will print the value stored in ''​results'',​ which corresponds to our call for the ''​temp''​ variable defined by ''​Particle.variable()'':​
 +
 +<​code>​
 +$ python ./​temp-get.py
 +19.84
 +
 +$ python ./​temp-get.py
 +20.14
 +</​code>​
 +
 +=== Code: sending an email with python ===
 +
 +If that works, you can now put ''​python''​ to work, checking the temperature with some frequency and doing something in response. Perhaps you might want to check if something gets down to a certain temperature and then email you about it. For this tutorial, we'll imagine that you have put a beer in the freezer and want an email when it's cold.
 +
 +This is the algorithm we'll use:
 +
 +  * get the temperature
 +  * log the current time and temperature in a log file
 +  * see if it's below a cut off
 +  * if so, send an email and quit
 +  * if not, wait a little bit (no sense reading once a second here) and repeat
 +
 +If we move the code above into a ''​while''​ loop, we can accomplish this flow like so:
 +
 +<​code>​
 +## import what we need
 +## added in time and email requirements
 +import urllib
 +import json
 +import smtplib
 +import datetime
 +from time import sleep
 +from email.mime.text import MIMEText
 +
 +## simplify the url a bit
 +## replace placeholders for device_id and token below!
 +base = "​https://​api.particle.io/​v1/​devices/"​
 +device_id = "​device_id_here"​
 +token = "​token_goes_here"​
 +
 +## change this if you used a different Particle.variable() name
 +var = "/​temp" ​
 +option = "?​access_token="​
 +
 +## put together the full url to query
 +url = base + device_id + var + option + token
 +
 +# initialize a variable so we know when to stop the loop
 +email = 0
 +
 +# as long as email is 0, run the below again and again
 +while email == 0:
 +
 +    # same code as above; get URL data, convert to json and extract temp
 +    data = urllib.urlopen(url).read()
 +    data_json = json.loads(data)
 +
 +    temp = round(float(data_json["​result"​]),​ 2)
 +
 +    # store the current system time for this reading
 +    now = datetime.datetime.now().strftime("​%Y-%m-%d-%H:​%M:​%S"​)
 +
 +    # define some cutoff; if the temperature is below 5C, do this:
 +    if temp < 5 :
 +    ​
 +        # this composes the message
 +        msg = MIMEText("​The beer is cold; it's " + str(temp) + " C!")
 +        addy = "​your_email_address@here.com"​
 +        msg["​Subject"​] = "Get to the freezer!"​
 +        msg["​From"​] = addy
 +        msg["​To"​] = addy
 +
 +        # this will send an email from you, to you, through your smtp server
 +        # google your email provider and "smtp settings"​ to find out yours
 +        print "​emailing..."​
 +        smtpserver = smtplib.SMTP("​smtp.gmail.com",​ 587)
 +        smtpserver.ehlo()
 +        smtpserver.starttls()
 +        smtpserver.ehlo()
 +        smtpserver.login(addy,​ "​your_email_password"​)
 +        smtpserver.sendmail(addy,​ addy, msg.as_string())
 +        smtpserver.close()
 +
 +        # now we set email to 1 so the while loop stops
 +        email = 1
 +
 +    # each time through, add the time and temperature to a file
 +    # you may have to create this file if it doesn'​t exist
 +    log = open("/​path/​to/​tmp36_data-log.csv",​ "​a"​)
 +    log.write(str(temp) + ","​ + now + "​\n"​)
 +    log.close()
 +
 +    # wait 10 seconds and repeat
 +    sleep(10)
 +
 +# when all done (email sent), tell us
 +print "​done"​
 +</​code>​
 +
 +Unfortunately,​ long wires on the TMP36 thwarted my attempts to record an actual beer's temperature in my freezer, so I simply put the bundle out on my porch (Minnesota). The nice part about storing the data to a local log file is you can plot it easily by importing the ''​csv''​ formatted file into Excel, LibreOffice,​ etc.
 +
 +
 +[[http://​digistump.com/​wiki/​_media/​oak/​tutorials/​temp-plot.png|{{http://​digistump.com/​wiki/​_media/​oak/​tutorials/​temp-plot.png?​600}}]]
 +
 +Based on the temperature outside, I adjusted the cutoff to 11C (''​if temp < 11''​ above) after I saw it wasn't going to drop below 10C. Here's what I got!
 +
 +[[http://​digistump.com/​wiki/​_media/​oak/​tutorials/​python-email-notify.png|{{http://​digistump.com/​wiki/​_media/​oak/​tutorials/​python-email-notify.png?​400}}]]
 +
 +===== Conclusion =====
 +
 +This tutorial taught a little about how to collect data from the Oak with python so that some functionality could be enabled. In this instance, we were sending an email; some real life applications might be:
 +
 +  * letting you know it's near freezing so you can cover your plants and protect from frost
 +  * an alert about the temperature at a cabin so you can wirelessly turn on the heat and your pipes don't freeze
 +  * a notification that your beer in the freezer is now cold so you don't forget and have it explode in your ice tray...
 +
 +Perhaps you can imagine other ways you'd like to "​act"​ on some bit of data you could collect with the Oak. Hopefully this helps you in some small way to start on such a project!
  
oak/tutorials/python-get.txt · Last modified: 2016/03/24 18:54 by jwhendy