[SOLVED]APIs for Noobs

Posted on
Fri Jan 17, 2014 4:41 pm
Bollar offline
Posts: 528
Joined: Aug 11, 2013

[SOLVED]APIs for Noobs

I know the answers are in this forum, but I'm just too noob to even know where to search. If you've been following the Evapotranspiration thread, you will see that I have the notion that I can approximate the solar radiation number by my solar array's performance. I report my data to PVOutput.org and they have an API. http://pvoutput.org/help.html#api-spec

From that, I figured out that if I enter http://pvoutput.org/service/r2/getstatus.jsp?key=myKey&sid=24036 into a browser, 20140117,15:40,33743,5487,25441,1455,0.323,11.6,NaN is returned, which is great!

Really, all I need to do is parse this string into Indigo variables. I assume this is easy enough to do with Python, but I could use some direction on where to look. I won't be offended if you send me a link to RTM, or a prior discussion here -- my noobness prevented me from using the right search terms.

If you want to see our array on PVOutput: http://pvoutput.org/intraday.jsp?id=26327&sid=24036

Insteon / Z-Wave / Bryant Evolution Connex /Tesla / Roomba / Elk M1 / SiteSage / Enphase Enlighten / NOAA Alerts

Posted on
Fri Jan 17, 2014 9:39 pm
berkinet offline
User avatar
Posts: 3298
Joined: Nov 18, 2008
Location: Berkeley, CA, USA & Mougins, France

Re: APIs for Noobs

I think Python is clearly the scripting language of choice for Indigo. However, for a fairly straightforward task like you have described, AppleScript, with a shell call to use curl, may be a better choice for someone just getting started. In particular, opening a URL and reading back the data is somewhat more complex.

Code: Select all
-- set theResult to do shell script ("/usr/bin/curl http://pvoutput.org/service/r2/getstatus.jsp?key=myKey\\&sid=24036")

set theResult to "20140117,15:40,33743,5487,25441,1455,0.323,11.6,NaN"

set {myTID, AppleScript's text item delimiters} to {AppleScript's text item delimiters, {","}}
set inVars to text items of theResult -- Gives list {"2", "69", "12"}
set AppleScript's text item delimiters to myTID -- It's considered good practice to return the TID's to their original state

tell application "IndigoServer"
   set the value of variable "foo" to text item 1 of inVars
   set the value of variable "bar" to text item 2 of inVars
end tell


Note, since I don't have your API key I just commented out the curl call and added a line to set theResult to the example text you posted. Of course, you need to create the variables in Indigo and fix the assignments to set the variables you created from the correct positional item.

Anyway, give this a try and post back if you have any questions.

EDIT: This script should be created in the AppleScript editor, saved, and run as an external script in an Indigo schedule.

EDIT: Escaped the "&" in the curl args
Last edited by berkinet on Sat Jan 18, 2014 12:08 am, edited 3 times in total.

Posted on
Fri Jan 17, 2014 9:46 pm
Bollar offline
Posts: 528
Joined: Aug 11, 2013

Re: APIs for Noobs

Neat. I will try it later tonight!

Insteon / Z-Wave / Bryant Evolution Connex /Tesla / Roomba / Elk M1 / SiteSage / Enphase Enlighten / NOAA Alerts

Posted on
Sat Jan 18, 2014 12:19 am
Bollar offline
Posts: 528
Joined: Aug 11, 2013

Re: APIs for Noobs

Just for those who follow behind, berkinet found the ampersand before the sid needed to be escaped:
Code: Select all
-- set theResult to do shell script ("/usr/bin/curl http://pvoutput.org/service/r2/getstatus.jsp?key=myKey\\&sid=24036")

set theResult to "20140117,15:40,33743,5487,25441,1455,0.323,11.6,NaN"

set {myTID, AppleScript's text item delimiters} to {AppleScript's text item delimiters, {","}}
set inVars to text items of theResult -- Gives list {"2", "69", "12"}
set AppleScript's text item delimiters to myTID -- It's considered good practice to return the TID's to their original state

tell application "IndigoServer"
   set the value of variable "foo" to text item 1 of inVars
   set the value of variable "bar" to text item 2 of inVars
end tell

Insteon / Z-Wave / Bryant Evolution Connex /Tesla / Roomba / Elk M1 / SiteSage / Enphase Enlighten / NOAA Alerts

Posted on
Sat Jan 18, 2014 10:24 am
Bollar offline
Posts: 528
Joined: Aug 11, 2013

Re: APIs for Noobs

So, this is good. I've been able to incorporate the code into Grognard's Evapotranspiration script, and I'm sure I'll be able to calculate a good solar radiation value from the PVOutput data.

But now that I see how this works, I want to try something more complex!

My Enphase solar system has an API that returns data in two different formats:

Code: Select all
https://api.enphaseenergy.com/api/systems/264170/power_today?callback=test_method&key=mykey

test_method({"first_interval_end_date":"2014-01-18T00:05:00-06:00","interval_length":300,"production":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,¬
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,18,44,82,117,151,192,230,259,283,309,332,354,375,393,¬
411,426,442,459,477,494,511,532,556,581,612,654,742,860,977,1195]})


or without the callback wrapper:

Code: Select all
https://api.enphaseenergy.com/api/systems/264170/power_today?key=mykey

{"first_interval_end_date":"2014-01-18T00:05:00-06:00","interval_length":300,"production":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,¬
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,18,44,82,117,151,192,230,259,283,309,332,354,375,393,411,¬
426,442,459,477,494,511,532,556,581,612,654,742,860,977,1195,1356]}


Are these JSON responses easy enough to parse?

https://api.enphaseenergy.com/doc/api/index.html

Insteon / Z-Wave / Bryant Evolution Connex /Tesla / Roomba / Elk M1 / SiteSage / Enphase Enlighten / NOAA Alerts

Posted on
Sat Jan 18, 2014 11:42 am
berkinet offline
User avatar
Posts: 3298
Joined: Nov 18, 2008
Location: Berkeley, CA, USA & Mougins, France

Re: APIs for Noobs

I am sure others will have an opinion on your JSON question. Here's mine.

As long as all you data is represented in one element, which it looks like it is,
you can probably get away with treating it like comma-delimited data, without
the callback wrapper and using the same basic script you use for the solar-radiation
data.

You might need to set the item delimiters to "{}:,[]" as and play a bit with
locating the offset for specific items, but, it should work.

Posted on
Sat Jan 18, 2014 12:01 pm
jay (support) offline
Site Admin
User avatar
Posts: 18256
Joined: Mar 19, 2008
Location: Austin, Texas

Re: APIs for Noobs

Parsing JSON in Python is really simple. From within a plugin or Python script run by Indigo:

Code: Select all
import simplejson
response = simplejson.loads(theReplyFromHttpGet)
indigo.variable.updateValue(12345678, response["first_interval_end_date"]) # inserts date from json into var id 12345678
indigo.variable.updateValue(87654321, response["interval_length"]) # inserts date from json into var id 87654321
productionList = response["production"]
# productionList now contains that list of numbers - do whatever you need to process the list
firstElement = productionList[0]  # gets the first element into the python variable firstElement
for element in productionList:  # loops over the entire list starting with the first
    # do whatever you need
    indigo.server.log("Element: %i" % element)


So, to summarize: loads() will return a python object that represents the entire JSON structure - which are lists, dictionaries, etc. You then use that object as you would any other Python object. In your case, the top-level is a dictionary so what's returned is a Python dict.

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Sat Jan 18, 2014 1:10 pm
Bollar offline
Posts: 528
Joined: Aug 11, 2013

Re: APIs for Noobs

jay (support) wrote:
Parsing JSON in Python is really simple. From within a plugin or Python script run by Indigo:


There is obviously a missing first paragraph from your answer. It doesn't look very noobish to me. :mrgreen:

But seriously, thanks for the help & the code -- you've given me something to work with and that's super helpful.

Insteon / Z-Wave / Bryant Evolution Connex /Tesla / Roomba / Elk M1 / SiteSage / Enphase Enlighten / NOAA Alerts

Posted on
Sat Jan 18, 2014 3:50 pm
jay (support) offline
Site Admin
User avatar
Posts: 18256
Joined: Mar 19, 2008
Location: Austin, Texas

Re: APIs for Noobs

Actually, the one line that parses the JSON into Python objects is what's easy. The rest is just straight Python or IOM - if you don't know Python then you'll have to learn it. If you don't know how to use the IOM then that's what the technical documents section of the documentation is for. Just like you'd need to learn AppleScript and Indigo's specific implementation of it if you were to use that.

Bottom line: to write Indigo scripts you must learn the scripting language and the Indigo specifics - same for any product for which a scripting language is provided. Nothing comes for free...

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Sat Jan 18, 2014 9:05 pm
Bollar offline
Posts: 528
Joined: Aug 11, 2013

Re: APIs for Noobs

With some help at Weather Underground, I was able to write this script to pull forecasted precipitation for the next four days:
Code: Select all
import urllib2
import simplejson
f = urllib2.urlopen('http://api.wunderground.com/api/myKey/forecast/q/TX/Southlake.json')
json_string = f.read()
parsed_json = simplejson.loads(json_string)
qpf0 = parsed_json['forecast']['simpleforecast']['forecastday'][0]['qpf_allday']['mm']
qpf1 = parsed_json['forecast']['simpleforecast']['forecastday'][1]['qpf_allday']['mm']
qpf2 = parsed_json['forecast']['simpleforecast']['forecastday'][2]['qpf_allday']['mm']
qpf3 = parsed_json['forecast']['simpleforecast']['forecastday'][3]['qpf_allday']['mm']


indigo.variable.updateValue(61377101, value=str(qpf0))
indigo.variable.updateValue(789565637, value=str(qpf1))
indigo.variable.updateValue(997159976, value=str(qpf2))
indigo.variable.updateValue(1755035595, value=str(qpf3))
f.close()

Insteon / Z-Wave / Bryant Evolution Connex /Tesla / Roomba / Elk M1 / SiteSage / Enphase Enlighten / NOAA Alerts

Posted on
Sat Jan 18, 2014 11:27 pm
Bollar offline
Posts: 528
Joined: Aug 11, 2013

Re: APIs for Noobs

Since I'm at it, here are two for Enphase. I found that this all went a lot easier once I got it working in a browser and then pasted the output into a JSON viewer (like: http://jsonmate.com) so I could understand the database hierarchy.

Code: Select all
import urllib2
import simplejson
f = urllib2.urlopen('https://api.enphaseenergy.com/api/systems/264170/summary?key=myKey')
json_string = f.read()
parsed_json = simplejson.loads(json_string)

enphaseCurrentPower = parsed_json['current_power']
enphaseEnergyLifetime = parsed_json['energy_lifetime']
enphaseEnergyMonth = parsed_json['energy_month']
enphaseEnergyToday = parsed_json['energy_today']
enphaseEnergyWeek = parsed_json['energy_week']
enphaseModules = parsed_json['modules']


indigo.variable.updateValue(634541491, value=str(enphaseCurrentPower))
indigo.variable.updateValue(1092021701, value=str(enphaseEnergyLifetime))
indigo.variable.updateValue(205768048, value=str(enphaseEnergyMonth))
indigo.variable.updateValue(1160765877, value=str(enphaseEnergyToday))
indigo.variable.updateValue(1286163160, value=str(enphaseEnergyWeek))
indigo.variable.updateValue(604442588, value=str(enphaseModules))

f.close()
Code: Select all
import urllib2
import simplejson
f = urllib2.urlopen('https://api.enphaseenergy.com/api/systems/264170/alerts?key=myKey')
json_string = f.read()
parsed_json = simplejson.loads(json_string)
enphaseAlerts = parsed_json['alerts']

indigo.variable.updateValue(836372145, value=str(enphaseAlerts))
f.close()

Insteon / Z-Wave / Bryant Evolution Connex /Tesla / Roomba / Elk M1 / SiteSage / Enphase Enlighten / NOAA Alerts

Posted on
Sat Jan 18, 2014 11:34 pm
berkinet offline
User avatar
Posts: 3298
Joined: Nov 18, 2008
Location: Berkeley, CA, USA & Mougins, France

Re: APIs for Noobs

Good going... Now you can go back and recode the first example in Python :wink:

Posted on
Sat Jan 18, 2014 11:37 pm
Bollar offline
Posts: 528
Joined: Aug 11, 2013

Re: APIs for Noobs

berkinet wrote:
Good going... Now you can go back and recode the first example in Python :wink:

Ha!

It's not returned in JSON, so I'll have to ask for another pointer. :D

Insteon / Z-Wave / Bryant Evolution Connex /Tesla / Roomba / Elk M1 / SiteSage / Enphase Enlighten / NOAA Alerts

Posted on
Sun Jan 19, 2014 12:23 am
berkinet offline
User avatar
Posts: 3298
Joined: Nov 18, 2008
Location: Berkeley, CA, USA & Mougins, France

Re: APIs for Noobs

Check out "split"

Posted on
Sun Jan 19, 2014 9:47 am
Bollar offline
Posts: 528
Joined: Aug 11, 2013

Re: APIs for Noobs

berkinet wrote:
Check out "split"

That was a good start. I also had to find a different way to poll the data, so here's your original Applescript in Python:
Code: Select all
import urllib2
response = urllib2.urlopen('http://pvoutput.org/service/r2/getstatus.jsp?key=myKey&sid=24036')
f = response.read()
pv = f.split(",")

indigo.variable.updateValue(1920763080, value=str(pv[0])) # Date
indigo.variable.updateValue(1705190321, value=str(pv[1])) # Time
indigo.variable.updateValue(690513764, value=str(pv[2])) # Energy Generation
indigo.variable.updateValue(133349311, value=str(pv[3])) # Power Generation
indigo.variable.updateValue(1101260058, value=str(pv[4])) # Energy Consumption
indigo.variable.updateValue(1991582166, value=str(pv[5])) # Power Consumption
indigo.variable.updateValue(835833028, value=str(pv[6])) # Efficiency
indigo.variable.updateValue(74384762, value=str(pv[7])) # Temperature
indigo.variable.updateValue(114588059, value=str(pv[8])) # Voltage


response.close()


Maybe my next task will be posting data to a site.

Insteon / Z-Wave / Bryant Evolution Connex /Tesla / Roomba / Elk M1 / SiteSage / Enphase Enlighten / NOAA Alerts

Who is online

Users browsing this forum: No registered users and 6 guests