The Eric Wroolie Blog

Overpass Experiences

  • Blog
  • Videos
  • Overpass Apps

Powered by Overpass Apps

Connecting to the Nike+ API with C#

May 5, 2008 by wroolie 14 Comments

A few months ago, I started writing some small personal apps which take information from the Nike+ service. Nike+ is the gadget I attach to my IPod and my running shoes which tracks details about my runs. It tracks things like distance, time, what I’m listening to, etc. When I sync the ipod, this information gets uploaded to the Nike+ website where I can see a couple of flash-heavy graphs of my running progress. Ideally, I would like to use this data myself–so I looked for an API.

I only found one example of an API referrence. This is a WordPress plugin written in PHP (http://www.ear-fung.us/apps/nikeplus/). There is very little documentation on the API out there. What I’ve been able to do involved a lot of trial and error to figure out how to get it working.

API Overview

Basically, the API (like most web-based APIs) includes a list of URLs which return an XML string. The first url will return an authentication cookie which all of the other urls use.

Here are the URLs:

URL Description
https://secure-nikeplus.nike.com/nikeplus/v1/services/widget/generate_pin.jhtml?
login=<Username>&password=<Password>
Authenticates the user. Once this information is passed in, a cookie is put on the client and used for the other calls. I’ll outline how to get around this later.
http://secure-nikeplus.nike.com/nikeplus/v1/services/app/get_user_data.jhtml Gets all of the data about the user (Name, Gender, Country, etc)
https://secure-nikeplus.nike.com/nikeplus/v1/services/app/goal_list.jhtml List of goals for the user.
https://secure-nikeplus.nike.com/nikeplus/v1/services/app/run_list.jhtml A list of all runs with basic summary information. This can get pretty long.
https://secure-nikeplus.nike.com/nikeplus/v1/services/app/get_run.jhtml?id=<RunNumber> A more detailed view of a specific run using the run number from the run list.
https://secure-nikeplus.nike.com/nikeplus/v1/services/widget/get_challenges_for_user.jhtml List of the Challenges the user has.
https://secure-nikeplus.nike.com/nikeplus/v1/services/app/personal_records.jhtml Lists all personal records for the user.

Authenticating

The biggest problem I had when using these urls was how to deal with the cookie information. Since I wanted something that would sit outside the browser (like a sidebar gadget or a web component), I didn’t want to worry about only hosting one session at a time. So I captured the cookie information and fed it back to the server for each additional call.

        public  bool Authenticate()
        {

            //get the login URL (which I include app.config)
            string authURI = String.Format(ConfigurationSettings.AppSettings["CreateSession"].ToString()+"?login={0}&password={1}",
                    _userName, _passWord);

            //Make the call to initiate the connection
            WebRequest objRequest = System.Net.HttpWebRequest.Create(authURI);

            //Read the response
            WebResponse objResponse = objRequest.GetResponse();

            //a cookie will be returned for authentication-- catch it here
            _authenticationCookie = objResponse.Headers["SET-COOKIE"].ToString();

            StreamReader webResponse = new StreamReader(objResponse.GetResponseStream());

            XmlDocument dataDoc = new XmlDocument();
            dataDoc.LoadXml(webResponse.ReadToEnd());

            if (dataDoc.SelectSingleNode("//status").InnerText == "success")
            {
                return true;
            }
            else
            {
                return false;
            }

        }


 

The xml that’s returned is pretty simple, it returns a status node. The important thing it returns is the cookie.

I basically capture the cookie information in the “SET-COOKIE” information which gets passed in with the http header. I store this in a class variable so I can send it in with later calls.

Retrieving Data

Now that I’ve authenticated, all I need to do is pass the cookie details back to the api with each subsequent request.

        private XmlDocument getAdditionalDetails(string uri)
        {
            WebRequest objRequest = System.Net.HttpWebRequest.Create(uri);

            //return the authorization cookie
            objRequest.Headers.Add("Cookie", _authenticationCookie);

            WebResponse objResponse = objRequest.GetResponse();

            StreamReader webResponse = new StreamReader(objResponse.GetResponseStream());

            XmlDocument dataDoc = new XmlDocument();
            dataDoc.LoadXml(webResponse.ReadToEnd());

            return dataDoc;
        }

 

I do this by using the Headers.Add() function. I pass back the same information I retrieved on the initial request. I am no longer dependent on cookies at all. Now, I can read the xml in the application.

Reading the Data

The API does not have any published schemas. However, these are very easy to decipher once you read them. I’ve actually written an entire API wrapper which assigns these xml values to an object model. This is probably overkill, however. An example of the run list xml is below:

<?xml version="1.0" encoding="UTF-8"?>
<plusService>
  <status>success</status>
  <runList>
    <run id="888888">
      <startTime>2006-10-07T10:03:31+01:00</startTime>
      <distance>6.8276</distance>
      <duration>2035266</duration>
      <syncTime>2006-10-07T09:51:46+00:00</syncTime>
      <calories>631</calories>
      <name><![CDATA[]]></name>
      <description><![CDATA[]]></description>
    </run>
    <run id="99999999">
      <startTime>2006-10-10T08:26:10+01:00</startTime>
      <distance>4.51</distance>
      <duration>1331531</duration>
      <syncTime>2006-10-10T07:54:38+00:00</syncTime>
      <calories>417</calories>
      <name><![CDATA[]]></name>
      <description><![CDATA[]]></description>
    </run>
. . .

Summary

I will admit that I should have used all of the time I spent playing with this api to actually be out running. Still it was fun to get it working. I only used the data for small projects. I hope that someone creates some decent gadgets for the Vista or Google Desktop sidebars from this.

If you would like my actual API wrapper code, drop me an email and I can send you what I’ve done. I’ve written the proper object oriented classes along with unit tests, etc. However, once you can get the xml data, you have all you need.

I hope this helps someone out there. Like I said, this is not documented anywhere else, so it could possibly change in the future (so keep your apps flexible).

Filed Under: C# Coding, Software Dev & Productivity

The big problem with Web TV

April 3, 2008 by wroolie 2 Comments

It seems that every network now broadcasts they’re shows on the web for a set period.  In the UK, we have the iPlayer for BBC.  The networks provide this service–not to please audiences–but because piracy has forced them to.  By showing the best TV programmes on the web, they can still generate ad revenue and make it easier to watch than finding a dodgy download.  It’s a great idea, really.

But then you try to use it.  I’ve been to the big US network sites and tried to watch their videos, but always get told that they are not available in my country.  While visiting my hometown newspaper site, Sign-on San Diego, I read a glowing review of Hulu.com and the future of web tv.  But, when I try to view a show, I get this:

image

“Unfortunately this video is not currently available in your country or region.  We apologize for the inconvenience.”

This is where the lawyers got involved, I think.  They’re still trying to get ad revenue to feed this.  “It will be just like TV, but we’ll put it on the web!  People will still see that Ace Hardware commercial three times an hour–but it will be on the web!  There is no Ace Hardware overseas?  Well, we’ll just let people in the US see it.”  They’ve probably not even thought about charging a reasonable subscription price.  This is where it falls down when trying to beat piracy.

Since moving to the UK 10 years ago, I’ve become increasingly annoyed that the industrial age companies still insist on making countries outside the US wait for things.  A hit blockbuster movie might be release in the UK 6 weeks after being released in the states.  By the time it gets here, all reviews have been read and all clips have been seen.  All this so they can fly the stars out and do the red carpet thing in Leicester Square?

Back in 1999, the news here would show a story of some UK guys who flew out to New York to see the premier of the “Phantom Menace” since it came out in the UK 2 months later.  These guys camped out in a queue for weeks.  Imagine their disappointment when they found out how crap it was.  But now, this doesn’t happen.  Now, people find the pirate copies.  They are either offered up by Chinese dealers on the streets of London or downloaded.  The same is true with TV. 

The net savvy are all caught up on Lost and other TV shows.  They are not trying to steal.  These people participate in global forums talking about their favourite shows.  They are tired of trying to avoid spoilers.  They would happily watch some adds or pay a few dollars a month to see something when everyone else sees it. 

Filed Under: Uncategorized

MyGeneration – a timesaver

March 31, 2008 by wroolie Leave a Comment

Code Generators are nothing new. I played around with Codesmith back before they started charging $200 for it and have looked into some of the codegen tools on sourceforge but was generally unimpressed. Most lacked enough documentation to really customise anything.

I even tried some of the high-end tools like Tier Developer which costs $1k and provided everything but the kitchen sink. You can download it for the trial, but it requires a steep learning curve to customise and you actually get a salesman call you up on the phone.

If you’ve never used a code generator, it’s basically an application that spits out code based on collections you pass it. Most of the time, it’s a database structure. You design your database, point your code generator at it, and select which tables you want to use. The template will create some output files for you based on what you select. For example, I selected five tables and used a code generator to create my CRUD stored proc files. I select a directory to output to and the code generators put the files there. I can then run these files against a database or include them in a Visual Studio database project. Since this is a one-shot generation, I can freely modify these files after they’ve been created.

I first looked at MyGeneration a few months ago. Like most of the cool new tools, I thought about all the cool things I could do with it– then I moved on to something else.

Today I started automating some of my Model classes using it. So I got to really use it in anger. Here are the things I really like about it:

    1. It’s free.
    2. There is a huge template library
    3. Tempates can be written in VBScript– so no new languages to learn.

Every time I look through a template library for a code generator, I get some really ambitious code. Everyone wants to generate all of your stored procs, data access layers, business objects, and test cases. I usually just want something simple like business logic layer. With this tool, it’s easy to write your own.

In a few hours, I wrote code to generate all of my interfaces and model objects. Since it was vbs, it was just like writing a classic asp page. I just looped through all the tables and created the beginning of my business objects:

<%

'******************************Class File*************************************
%>
#region headerblock
// Filename : <%=tableName%>.cs
// Change history
// date            version: author : description of change
// <%=Now()%>    <%=vbtab%>0.1    <%=vbtab%><%=input.Item("txtDeveloperName")%>    <%=vbtab%>Object Created

#endregion

using System;
using System.Data;
using System.Collections;

namespace <%= TrimSpaces(namespace) %>
{
    public class <%=tableName %> : I<%=tableName %>
    {

        public <%= tableName %>()
        {

        }

        #region Internals
        <% For Each objColumn in objTable.Columns %>
            private <%=objColumn.LanguageType%> <%=InternalVariableName(objColumn,true)%>;<%Next%>
        #endregion

        #region Properties
        <% For Each objColumn in objTable.Columns 
        %>
            public <%=objColumn.LanguageType%> <%=InternalVariableName(objColumn,false)%> {
                get 
                {
                    return  <%=InternalVariableName(objColumn,true)%>;
                }
                set 
                {
                     <%=InternalVariableName(objColumn,true)%> = value;
                }
            }
        <%Next%>
        #endregion

    }
}
<% 
    call SaveFile(tableName,input.item("txtPath"))

%>

One of the most tedious aspects of creating a model project is generating this code. Sure, I need to modify this further and I will probably normalise the database further–but this gives me a decent start and saves a few hours. I can also use this to generate the very basic unit tests (ie. can I create the object? Do all of the properties match?, etc).

It’s definitely a tool to check out. It’s a lot more fun to create your own template (or modify an existing one) than it is to use what’s given to you.

You can find MyGeneration at : http://www.mygenerationsoftware.com

I was tempted to title this post “Talking ’bout MyGeneration” but I fought back the urge.


Filed Under: C# Coding, Software Dev & Productivity

  • « Previous Page
  • 1
  • …
  • 72
  • 73
  • 74
  • 75
  • 76
  • …
  • 111
  • Next Page »

Recent Posts

  • My Gig and the Imposter Syndrome
  • Getting Picked Last for Teams in PE
  • One Little Growth Opportunity at a Time
  • I’m sorry if I look like I know what I’m doing
  • New Years Reclamations