Skip to content

Commit 960f3f8

Browse files
committedApr 27, 2020
changed camelcase and subscribe func
1 parent 0cb0ea8 commit 960f3f8

10 files changed

+779
-63
lines changed
 

‎.github/workflows/go.yml

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
name: Go
2+
3+
on:
4+
push:
5+
branches: [ master ]
6+
pull_request:
7+
branches: [ master ]
8+
9+
jobs:
10+
11+
build:
12+
name: Build
13+
runs-on: ubuntu-latest
14+
steps:
15+
16+
- name: Set up Go 1.13
17+
uses: actions/setup-go@v1
18+
with:
19+
go-version: 1.13
20+
id: go
21+
22+
- name: Check out code into the Go module directory
23+
uses: actions/checkout@v2
24+
25+
- name: Build
26+
run: go build -v examples/getlocation.go

‎GeoclueAgent.go

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package geoclue2
2+
3+
import "encoding/json"
4+
5+
// todo: not implemented
6+
7+
// Paths of methods and properties
8+
const (
9+
GeoclueAgentInterface = GeoclueInterface + ".Agent"
10+
11+
GeoclueAgentObjectPath = GeoclueObjectPath + "/Agent"
12+
13+
/* Methods */
14+
GeoclueAgentAuthorizeApp = GeoclueAgentInterface + ".AuthorizeApp"
15+
16+
/* Property */
17+
GeoclueAgentPropertyMaxAccuracyLevel = GeoclueAgentInterface + ".MaxAccuracyLevel" // readable u
18+
)
19+
20+
// This is the interface all application-authorizing agents must implement. There must be a separate agent object for every logged-in user on path "/org/freedesktop/GeoClue2/Agent".
21+
type GeoclueAgent interface {
22+
/* METHODS */
23+
24+
// This is the method that will be called by geoclue to get applications authorized to be given location information.
25+
//IN string desktop_id: The desktop file id (the basename of the desktop file) of the application requesting location information.
26+
//IN u req_accuracy_level: The level of location accuracy requested by client, as GClueAccuracyLevel.
27+
//OUT b authorized: Return value indicating if application should be given location information or not.
28+
//OUT u allowed_accuracy_level: The level of location accuracy allowed for client, as GClueAccuracyLevel.
29+
AuthorizeApp(string, GClueAccuracyLevel) (bool, GClueAccuracyLevel, error)
30+
31+
/* PROPERTIES */
32+
// The global maximum level of accuracy allowed for all clients. Since agents are per-user, this can be different for each user. See GClueAccuracyLevel for possible values.
33+
GetMaxAccuracyLevel() (GClueAccuracyLevel, error)
34+
35+
MarshalJSON() ([]byte, error)
36+
}
37+
38+
// NewGeoclueAgent returns new NewGeoclueAgent Interface
39+
func NewGeoclueAgent() (GeoclueAgent, error) {
40+
var gca geoclueAgent
41+
return &gca, gca.init(GeoclueInterface, GeoclueAgentObjectPath)
42+
}
43+
44+
type geoclueAgent struct {
45+
dbusBase
46+
}
47+
48+
func (gca geoclueAgent) AuthorizeApp(desktopId string, reqLevel GClueAccuracyLevel) (authorized bool, allowedLevel GClueAccuracyLevel, err error) {
49+
var tmpUint uint32
50+
err = gca.callWithReturn2(&authorized, &tmpUint, GeoclueAgentAuthorizeApp, &desktopId, &reqLevel)
51+
if err != nil {
52+
return false, GClueAccuracyLevelNone, err
53+
}
54+
allowedLevel = GClueAccuracyLevel(tmpUint)
55+
return
56+
}
57+
58+
func (gca geoclueAgent) GetMaxAccuracyLevel() (GClueAccuracyLevel, error) {
59+
res, err := gca.getUint32Property(GeoclueAgentPropertyMaxAccuracyLevel)
60+
if err != nil {
61+
return GClueAccuracyLevelNone, err
62+
}
63+
return GClueAccuracyLevel(res), nil
64+
}
65+
66+
func (gca geoclueAgent) MarshalJSON() ([]byte, error) {
67+
maxAccuracyLevel, err := gca.GetMaxAccuracyLevel()
68+
if err != nil {
69+
return nil, err
70+
}
71+
return json.Marshal(map[string]interface{}{
72+
"MaxAccuracyLevel": maxAccuracyLevel,
73+
})
74+
}

‎GeoclueClient.go

+275
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,275 @@
1+
package geoclue2
2+
3+
import (
4+
"encoding/json"
5+
"errors"
6+
"fmt"
7+
"github.com/godbus/dbus/v5"
8+
"time"
9+
)
10+
11+
// Paths of methods and properties
12+
const (
13+
GeoclueClientInterface = GeoclueInterface + ".Client"
14+
GeoclueClientObjectPath = GeoclueObjectPath + "/Client"
15+
16+
/* Methods */
17+
GeoclueClientStart = GeoclueClientInterface + ".Start"
18+
GeoclueClientStop = GeoclueClientInterface + ".Stop"
19+
20+
/* Property */
21+
GeoclueClientPropertyLocation = GeoclueClientInterface + ".Location" // readable o
22+
GeoclueClientPropertyDistanceThreshold = GeoclueClientInterface + ".DistanceThreshold" // readwrite u
23+
GeoclueClientPropertyTimeThreshold = GeoclueClientInterface + ".TimeThreshold" // readwrite u
24+
GeoclueClientPropertyDesktopId = GeoclueClientInterface + ".DesktopId" // readwrite s
25+
GeoclueClientPropertyRequestedAccuracyLevel = GeoclueClientInterface + ".RequestedAccuracyLevel" // readwrite u
26+
GeoclueClientPropertyActive = GeoclueClientInterface + ".Active" // readable b
27+
28+
/* SIGNAL */
29+
GeoclueClientSignalLocationUpdated = "LocationUpdated"
30+
)
31+
32+
// This is the interface you use to retrieve location information and receive location update signals from GeoClue service.
33+
// You get the client object to use this interface on from org.freedesktop.GeoClue2.Manager.GetClient() method.
34+
type GeoclueClient interface {
35+
/* METHODS */
36+
37+
// Start receiving events about the current location. Applications should hook-up to
38+
// LocationUpdated" signal before calling this method.
39+
Start() error
40+
41+
// Stop receiving events about the current location.
42+
Stop() error
43+
44+
/* PROPERTIES */
45+
46+
// Current location as path to a org.freedesktop.Geoclue2.Location object. Please note that this property will
47+
// be set to "/" (D-Bus equivalent of null) initially, until Geoclue finds user's location.
48+
// You want to delay reading this property until your callback to "LocationUpdated" signal is
49+
// called for the first time after starting the client.
50+
GetLocation() (GeoclueLocation, error)
51+
52+
// Contains the current distance threshold in meters. This value is used by the service when it gets new location info.
53+
// If the distance moved is below the threshold, it won't emit the LocationUpdated signal. The default value is 0.
54+
// When TimeThreshold is zero, it always emits the signal.
55+
GetDistanceThreshold() (uint32, error)
56+
SetDistanceThreshold(uint32) error
57+
58+
// Contains the current time threshold in seconds. This value is used by the service when it gets new location info.
59+
// If the time since the last update is below the threshold, it won't emit the LocationUpdated signal.
60+
// The default value is 0. When TimeThreshold is zero, it always emits the signal.
61+
GetTimeThreshold() (uint32, error)
62+
SetTimeThreshold(uint32) error
63+
64+
// The desktop file id (the basename of the desktop file).
65+
// This property must be set by applications for authorization to work.
66+
// e.g. firefox
67+
GetDesktopId() (string, error)
68+
SetDesktopId(string) error
69+
70+
// The level of accuracy requested by client, as GClueAccuracyLevel.
71+
// Please keep in mind that the actual accuracy of location information is dependent on available hardware on
72+
// your machine, external resources and/or how much accuracy user agrees to be confortable with.
73+
GetRequestedAccuracyLevel() (GClueAccuracyLevel, error)
74+
SetRequestedAccuracyLevel(level GClueAccuracyLevel) error
75+
76+
// If client is active, i-e started successfully using Start() and receiving location updates.
77+
// Please keep in mind that geoclue can at any time stop and start the client on user (agent) request.
78+
// Applications that are interested in in these changes, should watch for changes in this property.
79+
IsActive() (bool, error)
80+
81+
MarshalJSON() ([]byte, error)
82+
83+
/* SIGNALS */
84+
// todo
85+
// LocationUpdated signal: The signal is emitted every time the location changes. The client should set the
86+
// DistanceThreshold property to control how often this signal is emitted.
87+
// o old: old location as path to a #org.freedesktop.Geoclue2.Location object
88+
// o new: new location as path to a #org.freedesktop.Geoclue2.Location object
89+
SubscribeLocationUpdated() <-chan *dbus.Signal
90+
// Parse the signal and return the old and new Location
91+
ParseLocationUpdated(v *dbus.Signal) (oldLocation GeoclueLocation, newLocation GeoclueLocation, err error)
92+
93+
Unsubscribe()
94+
}
95+
96+
// NewGeoclueClient returns new GeoclueClient Interface
97+
func NewGeoclueClient(objectPath dbus.ObjectPath) (GeoclueClient, error) {
98+
var gcc geoclueClient
99+
return &gcc, gcc.init(GeoclueInterface, objectPath)
100+
}
101+
102+
type geoclueClient struct {
103+
dbusBase
104+
sigChan chan *dbus.Signal
105+
}
106+
107+
func (gcc geoclueClient) Start() error {
108+
err := gcc.call(GeoclueClientStart)
109+
if err != nil {
110+
return err
111+
}
112+
return err
113+
}
114+
115+
func (gcc geoclueClient) Stop() error {
116+
err := gcc.call(GeoclueClientStop)
117+
if err != nil {
118+
return err
119+
}
120+
return err
121+
}
122+
123+
func (gcc geoclueClient) GetLocation() (GeoclueLocation, error) {
124+
var objPath dbus.ObjectPath
125+
126+
cActive, err := gcc.IsActive()
127+
if !cActive {
128+
return nil, errors.New("client must be started before gathering the location")
129+
}
130+
131+
timeout := time.After(5 * time.Second)
132+
// Please note that this property will be set to "/" (D-Bus equivalent of null) initially,
133+
// until Geoclue finds user's location. You want to delay reading this property until
134+
// your callback to "LocationUpdated" signal is called for the first time after starting the client.
135+
c := gcc.SubscribeLocationUpdated()
136+
select {
137+
case <-timeout:
138+
return nil, errors.New("timed out gathering location object")
139+
case <-c:
140+
objPath, err = gcc.getObjectProperty(GeoclueClientPropertyLocation)
141+
if err != nil {
142+
return nil, err
143+
}
144+
if len(fmt.Sprint(objPath)) > 1 {
145+
break
146+
}
147+
}
148+
gcc.Unsubscribe()
149+
150+
return NewGeoclueLocation(objPath)
151+
}
152+
153+
func (gcc geoclueClient) GetDistanceThreshold() (uint32, error) {
154+
v, err := gcc.getUint32Property(GeoclueClientPropertyDistanceThreshold)
155+
return v, err
156+
}
157+
158+
func (gcc geoclueClient) SetDistanceThreshold(value uint32) error {
159+
return gcc.setProperty(GeoclueClientPropertyDistanceThreshold, value)
160+
161+
}
162+
163+
func (gcc geoclueClient) GetTimeThreshold() (uint32, error) {
164+
v, err := gcc.getUint32Property(GeoclueClientPropertyTimeThreshold)
165+
return v, err
166+
}
167+
168+
func (gcc geoclueClient) SetTimeThreshold(value uint32) error {
169+
return gcc.setProperty(GeoclueClientPropertyTimeThreshold, value)
170+
}
171+
172+
func (gcc geoclueClient) GetDesktopId() (string, error) {
173+
v, err := gcc.getStringProperty(GeoclueClientPropertyDesktopId)
174+
return v, err
175+
}
176+
177+
func (gcc geoclueClient) SetDesktopId(value string) error {
178+
return gcc.setProperty(GeoclueClientPropertyDesktopId, value)
179+
}
180+
181+
func (gcc geoclueClient) GetRequestedAccuracyLevel() (GClueAccuracyLevel, error) {
182+
v, err := gcc.getUint32Property(GeoclueClientPropertyRequestedAccuracyLevel)
183+
return GClueAccuracyLevel(v), err
184+
}
185+
186+
func (gcc geoclueClient) SetRequestedAccuracyLevel(level GClueAccuracyLevel) error {
187+
return gcc.setProperty(GeoclueClientPropertyRequestedAccuracyLevel, level)
188+
}
189+
190+
func (gcc geoclueClient) IsActive() (bool, error) {
191+
v, err := gcc.getBoolProperty(GeoclueClientPropertyActive)
192+
return v, err
193+
}
194+
195+
func (gcc geoclueClient) SubscribeLocationUpdated() <-chan *dbus.Signal {
196+
if gcc.sigChan != nil {
197+
return gcc.sigChan
198+
}
199+
rule := fmt.Sprintf("type='signal', member='%s',path_namespace='%s'", GeoclueClientSignalLocationUpdated, GeoclueClientObjectPath)
200+
gcc.conn.BusObject().Call(dbusMethodAddMatch, 0, rule)
201+
gcc.sigChan = make(chan *dbus.Signal, 10)
202+
gcc.conn.Signal(gcc.sigChan)
203+
return gcc.sigChan
204+
}
205+
func (gcc geoclueClient) ParseLocationUpdated(v *dbus.Signal) (oldLocation GeoclueLocation, newLocation GeoclueLocation, err error) {
206+
if len(v.Body) != 2 {
207+
err = errors.New("error by parsing activation changed signal")
208+
return
209+
}
210+
oPath, ok := v.Body[0].(dbus.ObjectPath)
211+
if !ok {
212+
err = errors.New("error by parsing old object path")
213+
return
214+
}
215+
oldLocation, err = NewGeoclueLocation(oPath)
216+
if err != nil {
217+
return
218+
}
219+
nPath, ok := v.Body[1].(dbus.ObjectPath)
220+
if !ok {
221+
err = errors.New("error by parsing new object path")
222+
return
223+
}
224+
newLocation, err = NewGeoclueLocation(nPath)
225+
if err != nil {
226+
return
227+
}
228+
return
229+
}
230+
231+
func (gcc geoclueClient) Unsubscribe() {
232+
gcc.conn.RemoveSignal(gcc.sigChan)
233+
gcc.sigChan = nil
234+
}
235+
236+
func (gcc geoclueClient) MarshalJSON() ([]byte, error) {
237+
location, err := gcc.GetLocation()
238+
if err != nil {
239+
return nil, err
240+
}
241+
mLocation, err := location.MarshalJSON()
242+
if err != nil {
243+
return nil, err
244+
}
245+
distanceThreshold, err := gcc.GetDistanceThreshold()
246+
if err != nil {
247+
return nil, err
248+
}
249+
250+
timeThreshold, err := gcc.GetTimeThreshold()
251+
if err != nil {
252+
return nil, err
253+
}
254+
desktopId, err := gcc.GetDesktopId()
255+
if err != nil {
256+
return nil, err
257+
}
258+
requestedAccuracyLevel, err := gcc.GetRequestedAccuracyLevel()
259+
if err != nil {
260+
return nil, err
261+
}
262+
isActive, err := gcc.IsActive()
263+
if err != nil {
264+
return nil, err
265+
}
266+
267+
return json.Marshal(map[string]interface{}{
268+
"Location": mLocation,
269+
"DistanceThreshold ": distanceThreshold,
270+
"TimeThreshold": timeThreshold,
271+
"DesktopId": desktopId,
272+
"RequestedAccuracyLevel": requestedAccuracyLevel,
273+
"Active": isActive,
274+
})
275+
}

‎GeoclueLocation.go

+151
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
package geoclue2
2+
3+
import (
4+
"encoding/json"
5+
"github.com/godbus/dbus/v5"
6+
"time"
7+
)
8+
9+
// Paths of methods and properties
10+
const (
11+
GeoclueLocationInterface = GeoclueInterface + ".Location"
12+
13+
/* Methods */
14+
15+
/* Property */
16+
17+
GeoclueLocationPropertyLatitude = GeoclueLocationInterface + ".Latitude" // readable d
18+
19+
GeoclueLocationPropertyLongitude = GeoclueLocationInterface + ".Longitude" // readable d
20+
21+
GeoclueLocationPropertyAccuracy = GeoclueLocationInterface + ".Accuracy" // readable d
22+
23+
GeoclueLocationPropertyAltitude = GeoclueLocationInterface + ".Altitude" // readable d
24+
25+
GeoclueLocationPropertySpeed = GeoclueLocationInterface + ".Speed" // readable d
26+
27+
GeoclueLocationPropertyHeading = GeoclueLocationInterface + ".Heading" // readable d
28+
29+
GeoclueLocationPropertyDescription = GeoclueLocationInterface + ".Description" // readable s
30+
31+
GeoclueLocationPropertyTimestamp = GeoclueLocationInterface + ".Timestamp" // readable (tt)
32+
33+
)
34+
35+
type GeoclueLocation interface {
36+
/* METHODS */
37+
// The latitude of the location, in degrees.
38+
GetLatitude() (float64, error)
39+
// The longitude of the location, in degrees.
40+
GetLongitude() (float64, error)
41+
// The accuracy of the location fix, in meters.
42+
GetAccuracy() (float64, error)
43+
// The altitude of the location fix, in meters. When unknown, its set to minimum double value, -1.7976931348623157e+308.
44+
GetAltitude() (float64, error)
45+
// The speed in meters per second. When unknown, it's set to -1.0.
46+
GetSpeed() (float64, error)
47+
// The heading direction in degrees with respect to North direction, in clockwise order. That means North becomes 0 degree, East: 90 degrees, South: 180 degrees, West: 270 degrees and so on. When unknown, it's set to -1.0.
48+
GetHeading() (float64, error)
49+
//A human-readable description of the location, if available. WARNING: Applications should not rely on this property since not all sources provide a description. If you really need a description (or more details) about current location, use a reverse-geocoding API, e.g geocode-glib.
50+
GetDescription() (string, error)
51+
//The timestamp when the location was determined, in seconds and microseconds since the Epoch. This is the time of measurement if the backend provided that information, otherwise the time when Geoclue received the new location.
52+
// Note that Geoclue can't guarantee that the timestamp will always monotonically increase, as a backend may not respect that. Also note that a timestamp can be very old, e.g. because of a cached location.
53+
GetTimestamp() (time.Time, error)
54+
MarshalJSON() ([]byte, error)
55+
}
56+
57+
// NewGeoclueLocation returns new NewGeoclueLocation Interface
58+
func NewGeoclueLocation(objectPath dbus.ObjectPath) (GeoclueLocation, error) {
59+
var gcl geoclueLocation
60+
return &gcl, gcl.init(GeoclueInterface, objectPath)
61+
}
62+
63+
type geoclueLocation struct {
64+
dbusBase
65+
sigChan chan *dbus.Signal
66+
}
67+
68+
func (gcl geoclueLocation) GetLatitude() (float64, error) {
69+
v, err := gcl.getFloat64Property(GeoclueLocationPropertyLatitude)
70+
return v, err
71+
}
72+
73+
func (gcl geoclueLocation) GetLongitude() (float64, error) {
74+
v, err := gcl.getFloat64Property(GeoclueLocationPropertyLongitude)
75+
return v, err
76+
}
77+
78+
func (gcl geoclueLocation) GetAccuracy() (float64, error) {
79+
v, err := gcl.getFloat64Property(GeoclueLocationPropertyAccuracy)
80+
return v, err
81+
}
82+
83+
func (gcl geoclueLocation) GetAltitude() (float64, error) {
84+
v, err := gcl.getFloat64Property(GeoclueLocationPropertyAltitude)
85+
return v, err
86+
}
87+
88+
func (gcl geoclueLocation) GetSpeed() (float64, error) {
89+
v, err := gcl.getFloat64Property(GeoclueLocationPropertySpeed)
90+
return v, err
91+
}
92+
93+
func (gcl geoclueLocation) GetHeading() (float64, error) {
94+
v, err := gcl.getFloat64Property(GeoclueLocationPropertyHeading)
95+
return v, err
96+
}
97+
98+
func (gcl geoclueLocation) GetDescription() (string, error) {
99+
v, err := gcl.getStringProperty(GeoclueLocationPropertyDescription)
100+
return v, err
101+
}
102+
103+
func (gcl geoclueLocation) GetTimestamp() (time.Time, error) {
104+
v, err := gcl.getTimestampProperty(GeoclueLocationPropertyTimestamp)
105+
106+
return v, err
107+
}
108+
109+
func (gcl geoclueLocation) MarshalJSON() ([]byte, error) {
110+
latitude, err := gcl.GetLatitude()
111+
if err != nil {
112+
return nil, err
113+
}
114+
longitude, err := gcl.GetLongitude()
115+
if err != nil {
116+
return nil, err
117+
}
118+
accuracy, err := gcl.GetAccuracy()
119+
if err != nil {
120+
return nil, err
121+
}
122+
altitude, err := gcl.GetAltitude()
123+
if err != nil {
124+
return nil, err
125+
}
126+
127+
heading, err := gcl.GetHeading()
128+
if err != nil {
129+
return nil, err
130+
}
131+
132+
description, err := gcl.GetDescription()
133+
if err != nil {
134+
return nil, err
135+
}
136+
137+
timestamp, err := gcl.GetTimestamp()
138+
if err != nil {
139+
return nil, err
140+
}
141+
142+
return json.Marshal(map[string]interface{}{
143+
"Latitude": latitude,
144+
"Longitude": longitude,
145+
"Accuracy": accuracy,
146+
"Altitude": altitude,
147+
"Heading": heading,
148+
"Description": description,
149+
"Timestamp": timestamp,
150+
})
151+
}

‎GeoclueManager.go

+132
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
package geoclue2
2+
3+
import (
4+
"encoding/json"
5+
"github.com/godbus/dbus/v5"
6+
"log"
7+
)
8+
9+
// Paths of methods and properties
10+
const (
11+
GeoclueInterface = "org.freedesktop.GeoClue2"
12+
GeoclueManagerInterface = GeoclueInterface + ".Manager"
13+
GeoclueObjectPath = "/org/freedesktop/GeoClue2"
14+
GeoclueManagerObjectPath = GeoclueObjectPath + "/Manager"
15+
16+
/* Methods */
17+
GeoclueManagerGetClient = GeoclueManagerInterface + ".GetClient"
18+
GeoclueManagerCreateClient = GeoclueManagerInterface + ".CreateClient"
19+
GeoclueManagerDeleteClient = GeoclueManagerInterface + ".DeleteClient"
20+
GeoclueManagerAddAgent = GeoclueManagerInterface + ".AddAgent"
21+
22+
/* Property */
23+
GeoclueManagerPropertyInUse = GeoclueManagerInterface + ".InUse" // readable b
24+
GeoclueManagerPropertyAvailableAccuracyLevel = GeoclueManagerInterface + ".AvailableAccuracyLevel" //readable u // readable ao
25+
)
26+
27+
// This is the interface you use to talk to main GeoClue2 manager object at path "/org/freedesktop/GeoClue2/Manager".
28+
// The only thing you do with this interface is to call GetClient() or CreateClient() on it to get your application specific client object(s).
29+
type GeoclueManager interface {
30+
/* METHODS */
31+
32+
// Retrieves a client object which can only be used by the calling application only.
33+
// On the first call from a specific D-Bus peer, this method will create the client object but subsequent
34+
// calls will return the path of the existing client.
35+
GetClient() (GeoclueClient, error)
36+
37+
// Creates and retrieves a client object which can only be used by the calling application only.
38+
// Unlike GetClient(), this method always creates a new client.
39+
CreateClient() (GeoclueClient, error)
40+
41+
// Use this method to explicitly destroy a client, created using GetClient() or CreateClient().
42+
// Long-running applications, should either use this to delete associated client(s) when not needed,
43+
// or disconnect from the D-Bus connection used for communicating with Geoclue (which is implicit
44+
// on client process termination).
45+
DeleteClient(GeoclueClient) error
46+
47+
// An API for user authorization agents to register themselves. Each agent is responsible for the user
48+
// it is running as. Application developers can and should simply ignore this API.
49+
// IN s id: The Desktop ID (excluding .desktop) of the agent
50+
AddAgent(id string) error
51+
52+
/* PROPERTIES */
53+
54+
// Whether service is currently is use by any application.
55+
InUse() (bool, error)
56+
// The level of available accuracy, as GClueAccuracyLevel.
57+
GetAvailableAccuracyLevel() (GClueAccuracyLevel, error)
58+
59+
MarshalJSON() ([]byte, error)
60+
}
61+
62+
// NewGeoclueManager returns new GeoclueManager Interface
63+
func NewGeoclueManager() (GeoclueManager, error) {
64+
var gcm geoclueManager
65+
66+
return &gcm, gcm.init(GeoclueInterface, GeoclueManagerObjectPath)
67+
}
68+
69+
type geoclueManager struct {
70+
dbusBase
71+
}
72+
73+
func (gcm geoclueManager) GetAvailableAccuracyLevel() (GClueAccuracyLevel, error) {
74+
v, err := gcm.getUint32Property(GeoclueManagerPropertyAvailableAccuracyLevel)
75+
return GClueAccuracyLevel(v), err
76+
}
77+
78+
func (gcm geoclueManager) InUse() (bool, error) {
79+
v, err := gcm.getBoolProperty(GeoclueManagerPropertyInUse)
80+
return v, err
81+
82+
}
83+
84+
func (gcm geoclueManager) GetClient() (GeoclueClient, error) {
85+
var clientPath dbus.ObjectPath
86+
err := gcm.callWithReturn(&clientPath, GeoclueManagerGetClient)
87+
if err != nil {
88+
log.Fatal(err.Error())
89+
}
90+
gcc, err := NewGeoclueClient(clientPath)
91+
92+
return gcc, err
93+
}
94+
95+
func (gcm geoclueManager) CreateClient() (GeoclueClient, error) {
96+
var clientPath dbus.ObjectPath
97+
err := gcm.callWithReturn(&clientPath, GeoclueManagerCreateClient)
98+
if err != nil {
99+
log.Fatal(err.Error())
100+
}
101+
gcc, err := NewGeoclueClient(clientPath)
102+
103+
return gcc, err
104+
}
105+
106+
func (gcm geoclueManager) DeleteClient(gcc GeoclueClient) error {
107+
err := gcm.call(GeoclueManagerDeleteClient, &gcc)
108+
if err != nil {
109+
return err
110+
}
111+
return err
112+
}
113+
114+
func (gcm geoclueManager) AddAgent(id string) error {
115+
return gcm.call(GeoclueManagerAddAgent, id)
116+
}
117+
118+
func (gcm geoclueManager) MarshalJSON() ([]byte, error) {
119+
inUse, err := gcm.InUse()
120+
if err != nil {
121+
return nil, err
122+
}
123+
availableAccuracyLevel, err := gcm.GetAvailableAccuracyLevel()
124+
if err != nil {
125+
return nil, err
126+
}
127+
128+
return json.Marshal(map[string]interface{}{
129+
"InUse": inUse,
130+
"AvailableAccuracyLevel ": availableAccuracyLevel,
131+
})
132+
}

‎README.md

+11-6
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
1-
Go-GeoClue2
1+
Go-Geoclue2
22
================
33

4-
Go D-Bus bindings for GeoClue2
4+
[![GoDoc](https://godoc.org/github.com/maltegrosse/go-geoclue2?status.svg)](https://pkg.go.dev/github.com/maltegrosse/go-geoclue2)
5+
[![License](http://img.shields.io/:license-mit-blue.svg?style=flat-square)](http://badges.mit-license.org)
6+
![Go](https://github.com/maltegrosse/go-geoclue2/workflows/Go/badge.svg)
7+
[![Go Report Card](https://goreportcard.com/badge/github.com/maltegrosse/go-geoclue2)](https://goreportcard.com/report/github.com/maltegrosse/go-geoclue2)
8+
Go D-Bus bindings for Geoclue2
9+
10+
Tested with [Geoclue 2 - Version 2.5.6](https://gitlab.freedesktop.org/geoclue/geoclue/-/releases/2.5.6) and Go 1.13
511

6-
Tested with [GeoClue 2 - Version 2.5.6](https://gitlab.freedesktop.org/geoclue/geoclue/-/releases/2.5.6) and Go 1.13
12+
Additional information: [Geoclue2 D-Bus Specs](https://www.freedesktop.org/software/geoclue/docs/ref-dbus.html)
713

8-
Additional information: [GeoClue2 D-Bus Specs](https://www.freedesktop.org/software/geoclue/docs/ref-dbus.html)
914

10-
## Todo
11-
- Agent not implement
1215

1316
## Usage
1417

1518
You can find some examples in the [examples](examples) directory.
1619

20+
## Notes
21+
Agent interface not implement/tested. A Go-ModemManager Dbus Wrapper can be found [here](https://github.com/maltegrosse/go-modemmanager).
1722
## License
1823

1924
[![License](http://img.shields.io/:license-mit-blue.svg?style=flat-square)](http://badges.mit-license.org)

‎enums.go

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package geoclue2
2+
3+
// Used to specify level of accuracy requested by, or allowed for a client.
4+
type GClueAccuracyLevel uint32
5+
6+
//go:generate stringer -type=GClueAccuracyLevel -trimprefix=GClueAccuracyLevel
7+
const (
8+
GClueAccuracyLevelNone GClueAccuracyLevel = 0 // Accuracy level unknown or unset.
9+
GClueAccuracyLevelCountry GClueAccuracyLevel = 1 //Country-level accuracy.
10+
GClueAccuracyLevelCity GClueAccuracyLevel = 4 //City-level accuracy.
11+
GClueAccuracyLevelNeighborhood GClueAccuracyLevel = 5 //neighborhood-level accuracy.
12+
GClueAccuracyLevelStreet GClueAccuracyLevel = 6 //Street-level accuracy.
13+
GClueAccuracyLevelExact GClueAccuracyLevel = 8 //Exact accuracy. Typically requires GPS receiver.
14+
15+
)

‎examples/getlocation.go

+49-8
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,57 @@ package main
33
import (
44
"fmt"
55
"github.com/maltegrosse/go-geoclue2"
6+
67
"log"
78
"os"
89
)
910

1011
func main() {
11-
// create new Instance of GeoClue Manager
12-
gcm, err := go_geoclue2.NewGeoClueManager()
12+
// create new Instance of Geoclue Manager
13+
gcm, err := geoclue2.NewGeoclueManager()
14+
if err != nil {
15+
log.Fatal(err.Error())
16+
17+
}
18+
// req availableAccuracyLevel
19+
aAccuracyLevel, err := gcm.GetAvailableAccuracyLevel()
1320
if err != nil {
1421
log.Fatal(err.Error())
1522

1623
}
17-
// create new Instance of GeoClue Client
24+
fmt.Println("Available Accuracy Level: ", aAccuracyLevel)
25+
// create new Instance of Geoclue Client
1826
client, err := gcm.GetClient()
1927
if err != nil {
2028
log.Fatal(err.Error())
2129
}
30+
2231
// desktop id is required to start the client
2332
// (double check your geoclue.conf file)
2433
err = client.SetDesktopId("firefox")
2534
if err != nil {
2635
log.Fatal(err.Error())
2736
}
37+
38+
// Set RequestedAccuracyLevel
39+
err = client.SetRequestedAccuracyLevel(geoclue2.GClueAccuracyLevelExact)
40+
if err != nil {
41+
log.Fatal(err.Error())
42+
}
43+
44+
// Get RequestedAccuracyLevel
45+
level, err := client.GetRequestedAccuracyLevel()
46+
if err != nil {
47+
log.Fatal(err.Error())
48+
}
49+
fmt.Println("Requested Accuracy Level: ", level)
50+
2851
// client must be started before requesting the location
2952
err = client.Start()
3053
if err != nil {
3154
log.Fatal(err.Error())
3255
}
33-
// create new Instance of GeoClue Location
56+
// create new Instance of Geoclue Location
3457
location, err := client.GetLocation()
3558
if err != nil {
3659
log.Fatal(err.Error())
@@ -56,13 +79,31 @@ func main() {
5679
}
5780
fmt.Println(accuracy)
5881

59-
60-
/*
6182
// listen location updates
62-
c := client.Subscribe()
83+
c := client.SubscribeLocationUpdated()
6384
for v := range c {
6485
fmt.Println(v)
86+
oldl, newl, err := client.ParseLocationUpdated(v)
87+
if err != nil {
88+
log.Fatal(err.Error())
89+
}
90+
fmt.Println("old")
91+
oldjson, err := oldl.MarshalJSON()
92+
if err != nil {
93+
log.Fatal(err.Error())
94+
}
95+
fmt.Println(string(oldjson))
96+
fmt.Println("---")
97+
fmt.Println("new")
98+
newjson, err := newl.MarshalJSON()
99+
if err != nil {
100+
log.Fatal(err.Error())
101+
}
102+
fmt.Println(string(newjson))
103+
104+
fmt.Println("---")
105+
65106
}
66-
*/
107+
67108
os.Exit(0)
68109
}

‎gclueaccuracylevel_string.go

+15-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎utils.go

+31-46
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,34 @@
1-
package go_geoclue2
1+
package geoclue2
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"github.com/godbus/dbus/v5"
7+
"time"
8+
)
29

310
/*
411
Copied and extended from https://github.com/Wifx/gonetworkmanager/blob/master/utils.go
512
on April the 1st 2020
6-
713
The MIT License (MIT)
8-
9-
Copyright (c) 2019 Wifx Sàrl
10-
14+
Copyright (c) 2019 Wifx Sàrl & Copyright (c) 2016 Bellerophon Mobile
1115
Permission is hereby granted, free of charge, to any person obtaining a copy
1216
of this software and associated documentation files (the "Software"), to deal
1317
in the Software without restriction, including without limitation the rights
1418
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1519
copies of the Software, and to permit persons to whom the Software is
1620
furnished to do so, subject to the following conditions:
17-
1821
The above copyright notice and this permission notice shall be included in all
1922
copies or substantial portions of the Software.
20-
2123
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2224
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2325
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2426
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2527
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2628
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2729
SOFTWARE.
28-
29-
------------------------------------------------------------------------------
30-
31-
The MIT License (MIT)
32-
33-
Copyright (c) 2016 Bellerophon Mobile
34-
35-
Permission is hereby granted, free of charge, to any person obtaining a copy
36-
of this software and associated documentation files (the "Software"), to deal
37-
in the Software without restriction, including without limitation the rights
38-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
39-
copies of the Software, and to permit persons to whom the Software is
40-
furnished to do so, subject to the following conditions:
41-
42-
The above copyright notice and this permission notice shall be included in all
43-
copies or substantial portions of the Software.
44-
45-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
46-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
47-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
48-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
49-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
50-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
51-
SOFTWARE.
52-
5330
*/
5431

55-
import (
56-
"encoding/binary"
57-
"fmt"
58-
"net"
59-
"time"
60-
61-
"github.com/godbus/dbus/v5"
62-
)
63-
6432
const (
6533
dbusMethodAddMatch = "org.freedesktop.DBus.AddMatch"
6634
)
@@ -97,7 +65,7 @@ func (d *dbusBase) callWithReturn2(ret1 interface{}, ret2 interface{}, method st
9765

9866
func (d *dbusBase) subscribe(iface, member string) {
9967
rule := fmt.Sprintf("type='signal',interface='%s',path='%s',member='%s'",
100-
iface, d.obj.Path(), GeoClueInterface)
68+
iface, d.obj.Path(), GeoclueInterface)
10169
d.conn.BusObject().Call(dbusMethodAddMatch, 0, rule)
10270
}
10371

@@ -373,8 +341,25 @@ func makeErrVariantType(iface string) error {
373341
return fmt.Errorf("unexpected variant type for '%s'", iface)
374342
}
375343

376-
func ip4ToString(ip uint32) string {
377-
bs := []byte{0, 0, 0, 0}
378-
binary.LittleEndian.PutUint32(bs, ip)
379-
return net.IP(bs).String()
344+
func (d *dbusBase) parsePropertiesChanged(v *dbus.Signal) (interfaceName string, changedProperties map[string]dbus.Variant, invalidatedProperties []string, err error) {
345+
if len(v.Body) != 3 {
346+
err = errors.New("error by parsing property changed signal")
347+
return
348+
}
349+
interfaceName, ok := v.Body[0].(string)
350+
if !ok {
351+
err = errors.New("error by parsing interface name")
352+
return
353+
}
354+
changedProperties, ok = v.Body[1].(map[string]dbus.Variant)
355+
if !ok {
356+
err = errors.New("error by parsing changed properties map name")
357+
return
358+
}
359+
invalidatedProperties, ok = v.Body[2].([]string)
360+
if !ok {
361+
err = errors.New("error by parsing invalidated properties")
362+
return
363+
}
364+
return
380365
}

0 commit comments

Comments
 (0)
Please sign in to comment.