-
Notifications
You must be signed in to change notification settings - Fork 2
/
location.go
112 lines (103 loc) · 2.79 KB
/
location.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package termux
import (
"bytes"
"context"
"encoding/json"
"github.com/eternal-flame-AD/go-termux/internal/chanbuf"
)
// LocationProvider enumerates the location sources provided by the device
type LocationProvider string
const (
// GPS acquire location with GPS
GPS LocationProvider = "gps"
// Network acquire location using current network
Network LocationProvider = "network"
// Passive acquire location using passive methods
Passive LocationProvider = "passive"
)
// LocationRecord represents a location record provided by the device
type LocationRecord struct {
Latitude float64 `json:"latitude"`
Longitude float64 `json:"longitude"`
Altitude float64 `json:"altitude"`
Accuracy float64 `json:"accuracy"`
Bearing float64 `json:"bearing"`
Speed float64 `json:"speed"`
ElapsedMS int `json:"elapsedMs"`
Provider string `json:"provider"`
}
func location(ctx context.Context, t string, provider LocationProvider) (*LocationRecord, error) {
buf := bytes.NewBuffer([]byte{})
if err := execContext(ctx, nil, buf, "Location", map[string]interface{}{
"provider": string(provider),
"request": t,
}, ""); err != nil {
return nil, err
}
res := buf.Bytes()
if err := checkErr(res); err != nil {
return nil, err
}
r := new(LocationRecord)
if err := json.Unmarshal(res, r); err != nil {
return nil, err
}
return r, nil
}
// LastLocation acquires the last known location of the device
func LastLocation(ctx context.Context, provider LocationProvider) (*LocationRecord, error) {
return location(ctx, "last", provider)
}
// Location acquires the current location of the device
func Location(ctx context.Context, provider LocationProvider) (*LocationRecord, error) {
return location(ctx, "once", provider)
}
// UpdatedLocation acquires the real-time location of the device from a channel
func UpdatedLocation(ctx context.Context, provider LocationProvider) (<-chan struct {
Location *LocationRecord
Error error
}, error) {
response := make(chan []byte)
ret := make(chan struct {
Location *LocationRecord
Error error
})
if err := execContext(ctx, nil, chanbuf.BufToChan{
C: response,
}, "Location", map[string]interface{}{
"provider": string(provider),
"request": "updates",
}, ""); err != nil {
return nil, err
}
go func() {
for {
select {
case <-ctx.Done():
close(ret)
return
case data := <-response:
if err := checkErr(data); err != nil {
ret <- struct {
Location *LocationRecord
Error error
}{nil, err}
continue
}
l := new(LocationRecord)
if err := json.Unmarshal(data, l); err != nil {
ret <- struct {
Location *LocationRecord
Error error
}{nil, err}
continue
}
ret <- struct {
Location *LocationRecord
Error error
}{l, nil}
}
}
}()
return ret, nil
}