Hi,
Jussi and I have been taking a look at the Geoclue API recently and
looking at ways to improve it. Apologies that this email is so long.
The current D-Bus interfaces are quite large and repetitive, so we have
removed the common elements and made the interfaces more fine grained.
The advantage in this is that the backends only need to implement the
interfaces that they support. It makes no sense for the hostip backend
to have methods dealing with direction of travel or satellites. This
also allows clients to check what methods a backend supports - asking
for a DBusProxy on an interface which doesn't exist will return NULL
[1]. The master process will hopefully use this to be able to switch
backends easily.
The interfaces we have come up with at the moment are:
* org.freedesktop.Geoclue
* org.freedesktop.Geoclue.Position
* org.freedesktop.Geoclue.Velocity
* org.freedesktop.Geoclue.Address
* org.freedesktop.Geoclue.Geocode
* org.freedesktop.Geoclue.ReverseGeocode
* org.freedesktop.Geoclue.Accuracy
* org.freedesktop.Geoclue.Satellites
I'll go through each of these interfaces and explain where our thinking
about them is coming from.
* org.freedesktop.Geoclue - This contains all the common metadata about
the backend
<interface name="org.freedesktop.Geoclue">
<property name="ServiceName" type="s" access="read"/>
<method name="GetVersion">
<arg name="major" type="i" direction="out" />
<arg name="minor" type="i" direction="out" />
<arg name="micro" type="i" direction="out" />
</method>
<method name="GetStatus" />
<signal name="StatusChanged" />
<method name="Shutdown" />
</interface>
We're not sure yet how best to do GetStatus and StatusChanged. The
thinking behind it is that the master process would be able to use that
to check if a backend can currently be used, IE a GPS backend's status
would indicate that it cannot be used if the GPS device isn't connected,
or a backend that requires network access would indicate that it cannot
be used if the network has disappeared.
The main problem with this is that it would require backends to have a
lot of complex logic and maybe have a lot more dependencies
(network-manager for knowledge about networks, but then we have the
problem of what to do when network-manager isn't used.) This may just be
more trouble than its worth, but we think we'll know more about the
requirements when we come to do the master process which is why we left
them in for the time being.
* org.freedesktop.Geoclue.Position - A latitude/longitude position
interface
<interface name="org.freedesktop.Geoclue.Position">
<method name="GetPosition">
<arg type="i" name="fields" direction="out" />
<arg type="i" name="timestamp" direction="out" />
<arg type="d" name="latitude" direction="out" />
<arg type="d" name="longitude" direction="out" />
<arg type="d" name="altitude" direction="out" />
</method>
<signal name="PositionChanged">
<arg type="i" name="fields" />
<arg type="i" name="timestamp" />
<arg type="d" name="latitude" />
<arg type="d" name="longitude" />
<arg type="d" name="altitude" />
</signal>
</interface>
This interface simply contains the latitude/longitude position as some
backends can provide this but not a civic location (like GPS), and some
vice versa. It should be fairly self explanatory :) The fields arg is a
bitmask that indicates what other arguments contain valid data, for
example if only latitude and longitude are known then the fields would
indicate that, and the client would know not to do anything with the
altitude arguement. This is needed because there isn't really any valid
"not set" value for any of the arguments.
* org.freedesktop.Geoclue.Velocity - Current course information
<interface name="org.freedesktop.Geoclue.Velocity">
<method name="GetVelocity">
<arg type="i" name="fields" direction="out" />
<arg type="i" name="timestamp" direction="out" />
<arg type="d" name="speed" direction="out" />
<arg type="d" name="direction" direction="out" />
<arg type="d" name="climb" direction="out" />
</method>
<signal name="VelocityChanged">
<arg type="i" name="fields" />
<arg type="i" name="timestamp" />
<arg type="d" name="speed" />
<arg type="d" name="direction" />
<arg type="d" name="climb" />
</signal>
</interface>
Again, similar to the Position interface it has been split out from the
original geoclue.position interface as it is specific to certain
backends.
* org.freedesktop.Geoclue.Address - A Civic location interface
<interface name="org.freedesktop.Geoclue.Address">
<method name="GetAddress">
<arg type="i" name="fields" direction="out" />
<arg type="i" name="timestamp" direction="out" />
<arg type="s" name="country_code" direction="out" />
<arg type="s" name="country" direction="out" />
<arg type="s" name="region" direction="out" />
<arg type="s" name="locality" direction="out" />
<arg type="s" name="area" direction="out" />
<arg type="s" name="postalcode" direction="out" />
<arg type="s" name="street" direction="out" />
<arg type="s" name="description" direction="out" />
<arg type="s" name="text" direction="out" />
<arg type="s" name="uri" direction="out" />
</method>
<signal name="AddressChanged">
<arg type="i" name="fields" />
<arg type="i" name="timestamp" />
<arg type="s" name="country_code" direction="out" />
<arg type="s" name="country" direction="out" />
<arg type="s" name="region" direction="out" />
<arg type="s" name="locality" direction="out" />
<arg type="s" name="area" direction="out" />
<arg type="s" name="postalcode" direction="out" />
<arg type="s" name="street" direction="out" />
<arg type="s" name="description" direction="out" />
<arg type="s" name="text" direction="out" />
<arg type="s" name="uri" direction="out" />
</signal>
</interface>
This interface contains the human understandable location address. It
was originally the civic location methods, but Address seemed more
understandable. We also removed the incredibly fine grained building
name, floor and room number, as we didn't think many services would be
that accurate.
* org.freedesktop.Geoclue.Geocode - Geocoding interface
* org.freedesktop.Geoclue.ReverseGeocode
<interface name="org.freedesktop.Geoclue.Geocode">
<method name="AddressToPosition">
<arg type="s" name="countrycode" direction="in" />
<arg type="s" name="country" direction="in" />
<arg type="s" name="region" direction="in" />
<arg type="s" name="locality" direction="in" />
<arg type="s" name="area" direction="in" />
<arg type="s" name="postalcode" direction="in" />
<arg type="s" name="street" direction="in" />
<arg type="s" name="description" direction="in" />
<arg type="s" name="text" direction="in" />
<arg type="s" name="uri" direction="in" />
<arg name="fields" type="i" direction="out" />
<arg name="latitude" type="d" direction="out" />
<arg name="longitude" type="d" direction="out" />
<arg name="altitude" type="d" direction="out" />
</method>
</interface>
<interface name="org.freedesktop.Geoclue.ReverseGeocode">
<method name="PositionToAddress">
<arg name="latitude" type="d" direction="in" />
<arg name="longitude" type="d" direction="in" />
<arg type="s" name="countrycode" direction="out" />
<arg type="s" name="country" direction="out" />
<arg type="s" name="region" direction="out" />
<arg type="s" name="locality" direction="out" />
<arg type="s" name="area" direction="out" />
<arg type="s" name="postalcode" direction="out" />
<arg type="s" name="street" direction="out" />
<arg type="s" name="description" direction="out" />
<arg type="s" name="text" direction="out" />
<arg type="s" name="uri" direction="out" />
</method>
Geocode and reverse geocoding have been seperated out into two
interfaces so that backends can support one and not the other.
* org.freedesktop.Geoclue.Accuracy - An interface for reporting accuracy
<interface name="org.freedesktop.Geoclue.Accuracy">
<method name="GetAccuracy">
<arg type="i" name="level" direction="out" />
<arg type="d" name="horizontal" direction="out" />
<arg type="d" name="vertical" direction="out" />
</method>
<signal name="AccuracyChanged" />
<arg type="i" name="level" />
<arg type="d" name="horizontal" />
<arg type="d" name="vertical" />
</signal>
</interface>
In the original position interface there were methods and signals which
returned the latitudinal and longitudinal accuracy, but we changed this
to better match the accuracy that a GPS reports. The level argument will
need some explaining, Jussi and I discussed it the most of everything we
did, so it might be controversial.
The level is an enum giving a fuzzy version of the accuracy. I envision
it having levels like this:
GEOCLUE_ACCURACY_LEVEL_STREET
GEOCLUE_ACCURACY_LEVEL_DISTRICT
GEOCLUE_ACCURACY_LEVEL_CITY
GEOCLUE_ACCURACY_LEVEL_LOCALITY
GEOCLUE_ACCURACY_LEVEL_COUNTY
GEOCLUE_ACCURACY_LEVEL_STATE
GEOCLUE_ACCURACY_LEVEL_COUNTRY
These enums represent a backend's inability to give a sensible result in
metres, and so rely on the user knowing the context behind being
informed that a location is city level accurate. The example is given on
the geoclue website that Boston is more than simply a point at the
corner of Tremont and Beacon Street.
There is also an enum GEOCLUE_ACCURACY_LEVEL_DETAILED which is used when
we know the accuracy in metres (as given by a GPS or some other way).
In my head, these levels also come into play in the map interfaces, but
I've not convinced Jussi of this yet :)
* org.freedesktop.Geoclue.Satellites - Interface for backends to provide
extra satellite details.
<interface name="org.freedesktop.Geoclue.Satellites">
<method name="GetSatellites">
<arg type="i" name="timestamp" direction="out" />
<arg type="i" name="number_in_use" direction="out" />
<arg type="i" name="number_in_view" direction="out" />
<arg type="ai" name="id" direction="out" />
<arg type="ab" name="in_use" direction="out" />
<arg type="ad" name="elevation" direction="out" />
<arg type="ad" name="azimuth" direction="out" />
<arg type="ad" name="snr" direction="out" />
</method>
</interface>
The advantage of the multiple interface idea is that backends can be
made up of a mix of different ones, and we can have specialised
interfaces like a Satellites interface, which only a GPS backend could
provide. We aren't 100% convinced about the usefulness of being this
specific yet, but we can see some usecases for it.
Observant readers (if they've managed to get this far, apologies again
for the length) will have noticed that there is no status in any of the
other interfaces. This is because we feel that D-Bus errors should
suffice, giving both an error code, and a text description of any errors
or problems that may have occurred.
For example the GPS backend could emit an error like
GEOCLUE_ERROR_NOT_AVAILABLE with the error message "GPS device not
connected", and a web based backend could emit the same error code, but
with the message "Could not reach http://hostip.com" and the client
would be able to handle them the same way.
Finally we have not covered all the interfaces yet. Notably missing so
far is the mapping interface and to a lesser extent the master and find
interfaces. We felt that the best plan for the map interface may be to
look at one free map provider (like openstreetmap) and write a good
interface for it, but we haven't come up with anything concrete yet.
The find interface we're not sure what Keith's plans were for it, there
are no backends written for it, so we'll need to discuss that with him.
Hopefully this isn't too much of a shake up? Please feel free to comment
on anything, and Jussi will correct anything I've forgotten to mention
or got wrong :)
iain
[1] - This is similar to the way Telepathy handles the multitude of
capabilities from different instant messenger services.