Buddycloud runs all messages through an XMPP cloud. This design works well and avoids the pitfalls of http based polling models.
To allow http based protocols to connect into our cloud we run an http-bind proxy that will receive http based messages, inject them to the xmpp cloud and return the answer. Our HTTP-bind proxy conforms to the specs of the Bidirectional-streams Over Synchronous HTTP" XEP.
Connection url: http://api.buddycloud.com/http-bind
Client to server:
<iq from='username@buddycloud.com/buddycloud' id='log1' to='butler.buddycloud.com' type='set'>
<location xmlns='http://buddycloud.com/protocol/location'
time='1199393605640' /* Required. Time at which the following information was obtained, in milliseconds since unix epoch */
latitude='47.897689' /* Optional. Latitude at which the following information was obtained, in degrees range -90 to 90 */
longitude='11.6045698' /* Optional. Longitude at which the following information was obtained, in degrees range -180 to 180 */
accuracy='150' /* Optional. Accuracy of latitude and longitude in meters. */
format='full'> /* Optional. Desired output format. Either 'simple' or 'full' Default = 'simple' */
<beacons> /* Optional. To get any meaningful output, at least one beacon or latitude / longitude should be present */
<beacon
id='262:03:30329:30429' /* Required. Unique identifier of beacon. For cells: mcc:mnc:lac:cid, for others the mac address */
type='cell' /* Required. Type of radio beacon. One of ('cell', 'wifi', 'wimax' or 'bluetooth')
signalstrength='-85'> /* Optional. Signal strength in dBM
<beacon
id='00:A0:C5:79:CF:84'
type='wlan'
signalstrength='-72'
encoding='open'/> /* Optional. Encryption type. One of ('open', 'wep', 'ieee802_1', 'wpa', 'wpa_psk', 'wpa2' or 'unknown' (default))*/
<beacon
id='00:AD:98:F4:CC:88'
type='wlan'/>
<beacon
id='00:A3:92:54:3C:55'
type='bluetooth'/>
</beacons>
</location>
</iq>
Server to client (simple format):
<iq from='butler.buddycloud.com' id='log1' to='user@buddycloud.com/buddycloud' type='result'>
<location
xmlns='http://buddycloud.com/protocol/location'
state='restless' /* Motion state, enum(moving, restless, stationary) */
placeid='456' /* Identifier of place, if known */
label='Near Lisboa Bar'> /* Suggested location display label, drawn from */
/* state, place, area, city and country */
</iq>
Server to client (full format):
<iq from='butler.buddycloud.com' id='log1' to='user@buddycloud.com/buddycloud' type='result'>
<location
xmlns='http://buddycloud.com/protocol/location'
state='restless' /* Motion state, enum(moving, restless, stationary) */
latitude='47.897689' /* Latitude in degrees range -90.0 to 90.0 */
longitude='11.6045698' /* Longitude in degrees range -180.0 to 180.0 */
accuracy='150' /* Estimated position accuracy in meters */
country='Germany' /* Country, if known */
city='Munich' /* City, if known */
area='Haidhausen' /* Area within city, if known */
postalcode='81667' /* Postal code, if known */
place='Lisboa Bar' /* Name of place, if known */
placeid='456' /* Identifier of place, if known */
label='Near Lisboa Bar'> /* Suggested location display label, drawn from */
/* state, accuracy place, area, city and country */
</iq>
If latitude and longitude were provided, these are echoed in the location result, if not they will be derived from place, area, city or country. In the latter case the accuracy will be depending on the state, and level of fix (in the order of hundreds of kilometers if only country is known, and down to 50m if place is known and state is stationary)
Client to server:
<iq from='user@buddycloud.com' to='butler.buddycloud.com' type='set' xml:lang='en' id='add'>
<command xmlns='http://jabber.org/protocol/commands' node='location'>
<x xmlns='jabber:x:data' type='form'>
<field type='hidden' var='FORM_TYPE'>
<value>buddycloud:place:add</value>
</field>
<field type='boolean' var='public'>
<value>true</value>
</field>
<field type='text-single' var='name'>
<value>Starbucks Coffee</value>
</field>
<field type='text-single' var='description'>
<value>If you've seen one you've seen 'em all</value>
</field>
<field type='text-single' var='street'>
<value>Unter den Linden 45</value>
</field>
<field type='text-single' var='district'>
<value>12345 Berlin</value>
</field>
<field type='text-single' var='country'>
<value>Germany</value>
</field>
<field type='text-single' var='latitude'>
<value>58.447266</value>
</field>
<field type='text-single' var='longitude'>
<value>28.168051</value>
</field>
<field type='text-single' var='wikiurl'>
<value>http://de.wikipedia.org/wiki/Starbucks</value>
</field>
<field type='text-single' var='siteurl'>
<value>http://starbucks.com</de/berlin/unter_den_linden.html</value>
</field>
</x>
</command>
</iq>
NOTE: "name" is required and all other optional
Server to client (on success):
<iq from='butler.buddycloud.com' to='user@buddycloud.com' type='result' xml:lang='en' id='add' />
Client to server:
<iq from='user@buddycloud.com' to='butler.buddycloud.com' type='set' xml:lang='en' id='delete123'>
<command xmlns='http://jabber.org/protocol/commands' node='place'>
<x xmlns='jabber:x:data' type='form'>
<field type='hidden' var='FORM_TYPE'>
<value>buddycloud:place:delete</value>
</field>
<field type='text-single' var='id'>
<value>123</value>
</field>
</x>
</command>
</iq>
NOTE: "name" is required and all other optional
Server to client (on success):
<iq from='butler.buddycloud.com' to='user@buddycloud.com' type='result' xml:lang='en' id='delete123' />
Client to server:
<iq from='user@buddycloud.com' to='butler.buddycloud.com' type='get' xml:lang='en' id='edit1'>
<command xmlns='http://jabber.org/protocol/commands' node='place'>
<x xmlns='jabber:x:data' type='form'>
<field type='hidden' var='FORM_TYPE'>
<value>buddycloud:place:edit</value>
</field>
<field type='text-single' var='id'>
<value>672</value>
</field>
<field type='boolean' var='public'>
<value>true</value>
</field>
<field type='text-single' var='name'>
<value>Starbucks Coffee</value>
</field>
<field type='text-single' var='description'>
<value>If you've seen one you've seen 'em all</value>
</field>
<field type='text-single' var='street'>
<value>Unter den Linden 45</value>
</field>
<field type='text-single' var='district'>
<value>12345 Berlin</value>
</field>
<field type='text-single' var='country'>
<value>Germany</value>
</field>
<field type='text-single' var='latitude'>
<value>58.447266</value>
</field>
<field type='text-single' var='longitude'>
<value>28.168051</value>
</field>
<field type='text-single' var='wikiurl'>
<value>http://de.wikipedia.org/wiki/Starbucks</value>
</field>
<field type='text-single' var='siteurl'>
<value>http://starbucks.com</de/berlin/unter_den_linden.html</value>
</field>
</x>
</command>
</iq>
NOTE: "id" is required, all other fields are optional.
Server to client (on success)
<iq to='user@buddycloud.com/resource' from='butler.buddycloud.com' type='result' xml:lang='en' id='edit1' />
Client to server:
<iq from='user@buddycloud.com' to='butler.buddycloud.com' type='set' xml:lang='en' id='set_current_loc_1'>
<command xmlns='http://jabber.org/protocol/commands' node='location'>
<x xmlns='jabber:x:data' type='form'>
<field type='hidden' var='FORM_TYPE'>
<value>buddycloud:location:set_current</value>
</field>
<field type='text-single' var='label'>
<value>The loo</value>
</field>
</x>
</command>
</iq>
Server to client (on success)
<iq from='butler.buddycloud.com' to='user@buddycloud.com' type='result' xml:lang='en' id='set_current_loc_1' >
</iq>
Client to server:
<iq from='user@buddycloud.com' to='butler.buddycloud.com' type='set' xml:lang='en' id='set_current_loc_1'>
<command xmlns='http://jabber.org/protocol/commands' node='location'>
<x xmlns='jabber:x:data' type='form'>
<field type='hidden' var='FORM_TYPE'>
<value>buddycloud:location:set_current</value>
</field>
<field type='text-single' var='place_id'>
<value>123</value>
</field>
<field type='boolean' var='store'>
<value>true</value>
</field>
</x>
</command>
</iq>
Server to client (on success):
<iq from='butler.buddycloud.com' to='user@buddycloud.com' type='result' xml:lang='en' id='set_current_loc_1' >
</iq>
Client to server:
<iq from='user@buddycloud.com' to='butler.buddycloud.com' type='set' xml:lang='en' id='set_current_loc_1'>
<command xmlns='http://jabber.org/protocol/commands' node='location'>
<x xmlns='jabber:x:data' type='form'>
<field type='hidden' var='FORM_TYPE'>
<value>buddycloud:location:set_current</value>
</field>
<field type='boolean' var='public'>
<value>true</value>
</field>
<field type='text-single' var='name'>
<value>Starbucks Coffee</value>
</field>
<field type='text-single' var='description'>
<value>If you've seen one you've seen 'em all</value>
</field>
<field type='text-single' var='street'>
<value>Unter den Linden 45</value>
</field>
<field type='text-single' var='district'>
<value>12345 Berlin</value>
</field>
<field type='text-single' var='country'>
<value>Country</value>
</field>
<field type='text-single' var='latitude'>
<value>58.447266</value>
</field>
<field type='text-single' var='longitude'>
<value>28.168051</value>
</field>
<field type='text-single' var='wikiurl'>
<value>http://de.wikipedia.org/wiki/Starbucks</value>
</field>
<field type='text-single' var='siteurl'>
<value>http://starbucks.com</de/berlin/unter_den_linden.html</value>
</field>
<field type='boolean' var='store'>
<value>true</value>
</field>
</x>
</command>
</iq>
NOTE: "name" is required and all other optional, will behave as one-shot if "store" is not present or set to false
Server to client (on success):
<iq from='butler.buddycloud.com' to='user@buddycloud.com' type='result' xml:lang='en' id='set_current_loc_1' >
<command xmlns='http://jabber.org/protocol/commands' node='location'>
<x xmlns='jabber:x:data' type='form'>
<field type='text-single' var='place_id'>
<value>234</value>
</field>
</x>
</command>
</iq>
Client to server:
<iq from='user@buddycloud.com' to='butler.buddycloud.com' type='set' xml:lang='en' id='set_next_loc_1'>
<command xmlns='http://jabber.org/protocol/commands' node='location'>
<x xmlns='jabber:x:data' type='form'>
<field type='hidden' var='FORM_TYPE'>
<value>buddycloud:location:set_next</value>
</field>
<field type='text-single' var='label'>
<value>The Pub</value>
</field>
<field type='text-single' var='place_id'>
<value>967</value>
</field>
</x>
</command>
</iq>
Server to client (on success)
<iq from='butler.buddycloud.com' to='user@buddycloud.com' type='result' xml:lang='en' id='set_next_loc_1' >
</iq>
Searches for places with similar names near the user's current location
Client to server:
<iq from='user@buddycloud.com' to='butler.buddycloud.com' type='get' xml:lang='en' id='place_search_1'>
<command xmlns='http://jabber.org/protocol/commands' node='place'>
<x xmlns='jabber:x:data' type='form'>
<field type='hidden' var='FORM_TYPE'>
<value>buddycloud:place:search</value>
</field>
<field type='text-single' var='name'>
<value>Starbucks Coffee</value>
</field>
</x>
</command>
</iq>
Note that the server will use the submitting user's current location, nearby locations or most recently seen cell to determine the country and district to which the search will be limited.
Server to client:
<iq from="butler.buddycloud.com" type="result" to="user@buddycloud.com/resource" id="place_search_1">
<command xmlns="http://jabber.org/protocol/commands" node="place">
<x xmlns="jabber:x:data" type="form">
<reported>
<field type="text-single" var="name" />
<field type="text-single" var="street" />
<field type="text-single" var="district" />
<field type="text-single" var="country" />
<field type="text-single" var="latitude" />
<field type="text-single" var="longitude" />
</reported>
<item>
<field var="name">
<value>Starbucks Coffee House</value>
</field>
<field var="street">
<value>Residenzstr. 7</value>
</field>
<field var="district">
<value>80333 Munchen</value>
</field>
<field var="country">
<value>Germany</value>
</field>
<field var="latitude">
<value>11.577312</value>
</field>
<field var="longitude">
<value>48.13908</value>
</field>
</item>
<item>
<field var="name">
<value>Starbucks Coffee House</value>
</field>
<field var="street">
<value>Sendlinger Str. 27</value>
</field>
<field var="district">
<value>80331 Munchen</value>
</field>
<field var="country">
<value>Germany</value>
</field>
<field var="latitude">
<value>11.569875</value>
</field>
<field var="longitude">
<value>48.135101</value>
</field>
</item>
</x>
</command>
</iq>
Client to server:
<iq from='user@buddycloud.com' to='butler.buddycloud.com' type='get' xml:lang='en' id='get_1'>
<command xmlns='http://jabber.org/protocol/commands' node='place'>
<x xmlns='jabber:x:data' type='form'>
<field type='hidden' var='FORM_TYPE'>
<value>buddycloud:place:get</value>
</field>
<field type='text-single' var='id'>
<value>123</value>
</field>
</x>
</command>
</iq>
Server to client (on success):
<iq from="butler.buddycloud.com" type="result" to="user@buddycloud.com/resource" id="get_1">
<command xmlns="http://jabber.org/protocol/commands" node="place">
<x xmlns="jabber:x:data" type="form">
<field type='text-single' var='id'>
<value>672</value>
</field>
<field type='boolean' var='visibility'>
<value>public</value>
</field>
<field type='text-single' var='name'>
<value>Starbucks Coffee</value>
</field>
<field type='text-single' var='description'>
<value>If you've seen one you've seen 'em all</value>
</field>
<field type='text-single' var='street'>
<value>Unter den Linden 45</value>
</field>
<field type='text-single' var='district'>
<value>12345 Berlin</value>
</field>
<field type='text-single' var='country'>
<value>Germany</value>
</field>
<field type='text-single' var='latitude'>
<value>58.447266</value>
</field>
<field type='text-single' var='longitude'>
<value>28.168051</value>
</field>
<field type='text-single' var='wikiurl'>
<value>http://de.wikipedia.org/wiki/Starbucks</value>
</field>
<field type='text-single' var='siteurl'>
<value>http://starbucks.com/de/berlin/unter_den_linden.html</value>
</field>
</x>
</command>
</iq>
Client to server:
<iq from='user@buddycloud.com' to='butler.buddycloud.com' type='get' xml:lang='en' id='history_1'>
<command xmlns='http://jabber.org/protocol/commands' node='place'>
<x xmlns='jabber:x:data' type='form'>
<field type='hidden' var='FORM_TYPE'>
<value>buddycloud:place:history</value>
</field>
<field type='text-single' var='max'>
<value>5</value>
</field>
</x>
</command>
</iq>
NOTE: Field max is optional.
Server to client:
<iq from="butler.buddycloud.com" type="result" to="user@buddycloud.com/resource" id="history_1">
<command xmlns="http://jabber.org/protocol/commands" node="place">
<x xmlns="jabber:x:data" type="form">
<reported>
<field type="text-single" var="id" />
<field type="text-single" var="name" />
<field type="text-single" var="visibility" />
<field type="text-single" var="population" />
</reported>
<item>
<field var="id">
<value>123</value>
</field>
<field var="name">
<value>Starbucks Coffee House</value>
</field>
<field var="visibility">
<value>public</value>
</field>
<field var="population">
<value>2</value>
</field>
</item>
<item>
<field var="id">
<value>10</value>
</field>
<field var="name">
<value>Downing Street</value>
</field>
<field var="visibility">
<value>private</value>
</field>
<field var="population">
<value>1</value>
</field>
</item>
<item>
<field var="id">
<value>667</value>
</field>
<field var="name">
<value>The neighbour of the Beast</value>
</field>
<field var="visibility">
<value>public</value>
</field>
<field var="population">
<value>0</value>
</field>
</item>
</x>
</command>
</iq>
NOTE: Form structure is identical to buddycloud:location:subscriptions and buddycloud:location:near
Client to server:
<iq from='user@buddycloud.com' to='butler.buddycloud.com' type='get' xml:lang='en' id='sub1'>
<command xmlns='http://jabber.org/protocol/commands' node='place'>
<x xmlns='jabber:x:data' type='form'>
<field type='hidden' var='FORM_TYPE'>
<value>buddycloud:place:subscribe</value>
</field>
<field type='text-single' var='id'>
<value>123</value>
</field>
</x>
</command>
</iq>
Server to client:
<iq from="butler.buddycloud.com" type="result" to="user@buddycloud.com/resource" id="sub1" />
Client to server:
<iq from='user@buddycloud.com' to='butler.buddycloud.com' type='get' xml:lang='en' id='sub1'>
<command xmlns='http://jabber.org/protocol/commands' node='place'>
<x xmlns='jabber:x:data' type='form'>
<field type='hidden' var='FORM_TYPE'>
<value>buddycloud:place:unsubscribe</value>
</field>
<field type='text-single' var='id'>
<value>123</value>
</field>
</x>
</command>
</iq>
Server to client:
<iq from="butler.buddycloud.com" type="result" to="user@buddycloud.com/resource" id="sub1" />
Client to server:
<iq from='user@buddycloud.com' to='butler.buddycloud.com' type='get' xml:lang='en' id='sub1'>
<command xmlns='http://jabber.org/protocol/commands' node='place'>
<x xmlns='jabber:x:data' type='form'>
<field type='hidden' var='FORM_TYPE'>
<value>buddycloud:place:subscriptions</value>
</field>
</x>
</command>
</iq>
Server to client:
<iq from="butler.buddycloud.com" type="result" to="user@buddycloud.com/resource" id="sub1">
<command xmlns="http://jabber.org/protocol/commands" node="place">
<x xmlns="jabber:x:data" type="form">
<reported>
<field type="text-single" var="id" />
<field type="text-single" var="name" />
<field type="text-single" var="visibility" />
<field type="text-single" var="population" />
</reported>
<item>
<field var="id">
<value>123</value>
</field>
<field var="name">
<value>Starbucks Coffee House</value>
</field>
<field var="visibility">
<value>public</value>
</field>
<field var="population">
<value>2</value>
</field>
</item>
<item>
<field var="id">
<value>10</value>
</field>
<field var="name">
<value>Downing Street</value>
</field>
<field var="visibility">
<value>private</value>
</field>
<field var="population">
<value>1</value>
</field>
</item>
<item>
<field var="id">
<value>667</value>
</field>
<field var="name">
<value>The neighbour of the Beast</value>
</field>
<field var="visibility">
<value>public</value>
</field>
<field var="population">
<value>0</value>
</field>
</item>
</x>
</command>
</iq>
NOTE: Form structure is identical to buddycloud:place:history and buddycloud:location:places_near
Returns places near the user's current location
Client to server:
<iq from='user@buddycloud.com' to='butler.buddycloud.com' type='get' xml:lang='en' id='near1'>
<command xmlns='http://jabber.org/protocol/commands' node='location'>
<x xmlns='jabber:x:data' type='form'>
<field type='hidden' var='FORM_TYPE'>
<value>buddycloud:location:places_near</value>
</field>
</x>
</command>
</iq>
Server to client:
<iq from="butler.buddycloud.com" type="result" to="user@buddycloud.com/resource" id="near1">
<command xmlns="http://jabber.org/protocol/commands" node="location">
<x xmlns="jabber:x:data" type="form">
<reported>
<field type="text-single" var="id" />
<field type="text-single" var="name" />
<field type="text-single" var="visibility" />
<field type="text-single" var="population" />
</reported>
<item>
<field var="id">
<value>123</value>
</field>
<field var="name">
<value>Starbucks Coffee House</value>
</field>
<field var="visibility">
<value>public</value>
</field>
<field var="population">
<value>2</value>
</field>
</item>
<item>
<field var="id">
<value>10</value>
</field>
<field var="name">
<value>Downing Street</value>
</field>
<field var="visibility">
<value>private</value>
</field>
<field var="population">
<value>1</value>
</field>
</item>
<item>
<field var="id">
<value>667</value>
</field>
<field var="name">
<value>The neighbour of the Beast</value>
</field>
<field var="visibility">
<value>public</value>
</field>
<field var="population">
<value>0</value>
</field>
</item>
</x>
</command>
</iq>
NOTE: Form structure is identical to buddycloud:place:history and buddycloud:place:subscriptions
Returns people near the user's current location
Client to server:
<iq from='user@buddycloud.com' to='butler.buddycloud.com' type='get' xml:lang='en' id='near1'>
<command xmlns='http://jabber.org/protocol/commands' node='location'>
<x xmlns='jabber:x:data' type='form'>
<field type='hidden' var='FORM_TYPE'>
<value>buddycloud:location:people_near</value>
</field>
</x>
</command>
</iq>
NOTE: The field locationid is optional. If not set, the people near the submitting user's current location will be returned.
Server to client:
<iq from="butler.buddycloud.com" type="result" to="user@buddycloud.com/resource" id="near1">
<command xmlns="http://jabber.org/protocol/commands" node="location">
<x xmlns="jabber:x:data" type="form">
<reported>
<field type="text-single" var="jid" />
<field type="text-single" var="locationname" />
</reported>
<item>
<field var="jid">
<value>bob@gmail.com</value>
</field>
<field var="licationid">
<value>345</value>
</field>
<field var="locationname">
<value>Starbucks's Coffee</value>
</field>
</item>
<item>
<field var="jid">
<value>simon@buddycloud.com</value>
</field>
<field var="name">
<value>Simon Tennant</value>
</field>
<field var="licationid">
<value>345</value>
</field>
<field var="locationname">
<value>Starbucks's Coffee</value>
</field>
</item>
<item>
<field var="jid">
<value>bond@jamesbond.com</value>
</field>
<field var="licationid">
<value>235</value>
</field>
<field var="locationname">
<value>MI6 HQ</value>
</field>
</item>
</x>
</command>
</iq>
Note: Pushed to location subscribers when a user enters or leaves a location
Server to Client:
<iq from='butler.maginator.com' id='pub4' to='user@buddycloud.com' type='set'>
<place xmlns='http://buddycloud.com/protocol/location'>
<id>17</id>
<population>5</population>
</place>
</iq>