What does an “<oauth/>” stanza look like?
<oauth xmlns='urn:xmpp:oauth:0'>
<oauth_consumer_key>0685bd9184jfhq22</oauth_consumer_key>
<oauth_token>ad180jjd733klru7</oauth_token>
<oauth_signature_method>HMAC-SHA1</oauth_signature_method>
<oauth_signature>9PQkM4YKgaM067wqrDGshXOwDW0=</oauth_signature>
<oauth_timestamp>1218137833</oauth_timestamp>
<oauth_nonce>4572616e48616d6d65724c61686176</oauth_nonce>
<oauth_version>1.0</oauth_version>
</oauth>
In context?
Oh, right.
<iq type='set'
from='francisco@denmark.lit/barracks'
to='fireeagle.com'
id='sub1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<subscribe
node='/api/0.1/user/ad180jjd733klru7'
jid='francisco@denmark.lit'/>
<oauth xmlns='urn:xmpp:oauth:0'>
<oauth_consumer_key>0685bd9184jfhq22</oauth_consumer_key>
<oauth_token>ad180jjd733klru7</oauth_token>
<oauth_signature_method>HMAC-SHA1</oauth_signature_method>
<oauth_signature>9PQkM4YKgaM067wqrDGshXOwDW0=</oauth_signature>
<oauth_timestamp>1218137833</oauth_timestamp>
<oauth_nonce>4572616e48616d6d65724c61686176</oauth_nonce>
<oauth_version>1.0</oauth_version>
</oauth>
</pubsub>
</iq>
Note that the value of <oauth_token/> matches part of the node.
And the response?
<iq type='result'
from='fireeagle.com'
to='francisco@denmark.lit/barracks'
id='sub1'>
<pubsub xmlns='http://jabber.org/protocol/pubsub'>
<subscription
node='/api/0.1/user/ad180jjd733klru7'
jid='francisco@denmark.lit'
subscription='subscribed'/>
</pubsub>
</iq>
What’s with the Shakespeare references?
XMPP tradition.
What does a location update look like?
It’s the same payload you would get if you were explicitly polling /api/0.1/user.xml:
<message from='fireeagle.com' to='francisco@denmark.lit'>
<event xmlns='http://jabber.org/protocol/pubsub#event'>
<items node='ad180jjd733klru7'>
<item>
<rsp xmlns:georss="http://www.georss.org/georss" stat="ok">
<user token="ad180jjd733klru7"
readable="true"
writeable="true"
located-at="2009-01-31T12:51:00-05:00">
<location-hierarchy timezone="America/Los_Angeles"
string="23424977|2347563|12587707|2487956|12797158">
<location best-guess="true">
<id>41</id>
<georss:point>37.7812461853 -122.3957595825</georss:point>
<label></label>
<level>0</level>
<level-name>exact</level-name>
<located-at>2009-01-31T12:51:00-05:00</located-at>
<name>500 3rd St, San Francisco, CA</name>
<normal-name>94107</normal-name>
<place-id exact-match="false">8Xq01wWYA5u_OEMhyQ/place-id>
<woeid exact-match="false">12797158</woeid>
<query>q=500%203rd%20st,%20san%20francisco,%20ca</query>
</location>
<location best-guess="false">
<id>40</id>
<georss:box>37.7494697571 -122.40650177 37.7862281799
-122.3790893555</georss:box>
<label></label>
<level>1</level>
<level-name>postal</level-name>
<located-at>2009-01-31T12:51:00-05:00</located-at>
<name>San Francisco, CA 94107</name>
<normal-name>94107</normal-name>
<place-id exact-match="true">8Xq01wWYA5u_OEMhyQ/place-id>
<woeid exact-match="true">12797158</woeid>
</location>
<location best-guess="false">
<id>39</id>
<georss:box>37.7037811279 -122.5154571533 37.8545417786
-122.32472229</georss:box>
<label></label>
<level>3</level>
<level-name>city</level-name>
<located-at>2009-01-31T12:51:00-05:00</located-at>
<name>San Francisco, CA</name>
<normal-name>San Francisco</normal-name>
<place-id exact-match="true">kH8dLOubBZRvX_YZ</place-id>
<woeid exact-match="true">2487956</woeid>
</location>
<location best-guess="false">
<id>38</id>
<georss:box>37.6930503845 -123.1080169678 37.832359314
-122.3567581177</georss:box>
<label></label>
<level>4</level>
<level-name>region</level-name>
<located-at>2009-01-31T12:51:00-05:00</located-at>
<name>San Francisco County, California</name>
<normal-name>San Francisco</normal-name>
<place-id exact-match="true">hCca8XSYA5nn0X1Sfw</place-id>
<woeid exact-match="true">12587707</woeid>
</location>
<location best-guess="false">
<id>37</id>
<georss:box>32.5342788696 -124.4150238037 42.0093803406
-114.1308135986</georss:box>
<label></label>
<level>5</level>
<level-name>state</level-name>
<located-at>2009-01-31T12:51:00-05:00</located-at>
<name>California</name>
<normal-name>California</normal-name>
<place-id exact-match="true">SVrAMtCbAphCLAtP</place-id>
<woeid exact-match="true">2347563</woeid>
</location>
<location best-guess="false">
<id>36</id>
<georss:box>18.9108390808 -167.2764129639 72.8960571289
-66.6879425049</georss:box>
<label></label>
<level>6</level>
<level-name>country</level-name>
<located-at>2009-01-31T12:51:00-05:00</located-at>
<name>United States</name>
<normal-name>United States</normal-name>
<place-id exact-match="true">4KO02SibApitvSBieQ</place-id>
<woeid exact-match="true">23424977</woeid>
</location>
</location-hierarchy>
</user>
</rsp>
</item>
</items>
</event>
</message>
What kinds of actions does Fire Eagle support?
Right now, you can <subscribe/>, <unsubscribe/>, and list your <subscriptions/>.
Should ‘iq’ be upper or lower-case in my signature base string?
Lower-case, since XMPP elements are always referred to that way. HTTP methods are always referred to in all-caps, which is why they’re upper-cased there.
What’s my URI?
Your URI should be <from>&<to>. E.g., francisco@denmark.lit&fireeagle.com. It’s not really a URI, but we like to think of it as one.
That’s a bare JID. Why should I be using a bare JID?
Excellent observation. Because it doesn’t work if you don’t. We need to fix that.
Should I escape my signature?
No.
What’s a token-missing error mean?
Um. It usually means that you didn’t include an <oauth_token/> element in your request. However, it may also mean that your signature wasn’t calculated correctly (which should be signature-invalid). Assume that’s the case (unless you did actually omit the <oauth_token/>). Sorry for the confusion.
Can I use a Google Talk account with this?
No. Nor should you use a jabber.org account for production data (because the data passes unencrypted through an untrusted party’s servers before being sent to your client). In the future, we may enforce this.
What happens when a user re-authorizes my app (i.e. to change their settings or authorize an additional instance)?
As long as the user hasn’t revoked access to their data by your application, your subscription will persist.
Can I unsubscribe with a new access token after a user re-authorizes my app?
That shouldn’t be a problem.
How can I see what nodes I’m subscribed to?
Make a <subscriptions/> request and sign it with your general purpose access token (instead of a user’s access token). This is an operation that you’re doing on behalf of the application.
Where’s my general purpose access token?
If your application was registered as a “web” application, you can find it on your “manage applications” page in the developer section of the site. If your application is a “mobile”, “desktop”, or “plugin” application, you won’t have one. Sorry.
If I don’t have a general purpose access token, can I check individual subscriptions?
Not yet. In the future, you’ll be able to make <subscriptions/> requests signed with users’ access tokens to determine whether your JID is subscribed to an individual user’s PubSub node.
I’ve subscribed, but I don’t see any updates.
Make sure that fireeagle.com is in your roster; if it isn’t, Fire Eagle won’t know when you’re online (your XMPP server won’t automatically send presence when you come online) and won’t send you any updates.
(You can check the contents of your roster with switchboard roster list. If fireeagle.com isn’t present, add it with switchboard roster add fireeagle.com.)
If you’re making multiple connections with the same JID, Fire Eagle isn’t smart enough (yet) to track presence for multiple resources. If it sees one resource go offline, it assumes all are offline and will stop sending data. You’ll need to send a <presence/> message to Fire Eagle (easiest by going offline then online) for it to begin sending data again.
To see incoming PubSub requests on the command line, use switchboard pubsub listen.
What’s switchboard? How can I get one?
Switchboard is a combination command-line client / XMPP client/component library for Ruby.
Its primary use is as a curl-equivalent for XMPP servers, so you don’t need to be working on Ruby to find it useful.
To install it, you’ll need to be running a relatively recent version of RubyGems (i.e. it may work, but if it doesn’t install, try upgrading RubyGems first). It also depends on a number of not-yet-officially-released libraries (this is the bleeding edge, remember), so you’ll need to install it like so:
$ sudo gem install mojodna-switchboard -s http://gems.github.com/
$ sudo gem install mojodna-oauth -s http://gems.github.com/
(OAuth is an optional switchboard dependency, but you’ll need it to sign requests.)
What’s fire-hydrant? I want one of those too.
Fire Hydrant is a jack that makes it even easier to consume Fire Eagle updates using switchboard. Have a look in examples/ to see it in action.
The same caveats about installing switchboard apply.
$ sudo gem install mojodna-fire-hydrant -s http://gems.github.com/
The coolest (IMO) example is examples/fire_eagle_visualizer.rb: on a Mac, it will use appscript (sudo gem install rb-appscript) to drive Google Earth and display updates from your users in real-time.
All this talk about Ruby. I want to use Java.
Great! Smack supports PubSub, so you can consume the feed without too much trouble. For the time being, you may want to use switchboard to manage subscriptions.
jfireeagle is probably your best bet for converting the XML response into suitable objects.
I’ve heard rumors of a Java library that wraps all of this and handles subscriptions to boot. I’ll keep you updated.
Actually, I changed my mind. I want to use C#.
Sure.
oauth-sharp includes RequestProxies and helpers for signing <subscription/> requests. It’s intended to work with jabber-net.
How ‘bout ActionScript?
Try fireeagle-as3. It doesn’t handle subscriptions (yet), but will wrap Fire Eagle data in native objects.
Hmmm.... Python?
Pyrostream should suffice for your needs. Check out the sample.py to get started.
I want to use something else instead.
Good luck. Let us know how it goes!