-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathgpsd.cpp
More file actions
179 lines (149 loc) · 5.29 KB
/
gpsd.cpp
File metadata and controls
179 lines (149 loc) · 5.29 KB
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/* Get lat/long from gpsd daemon running on any host port 2947.
*
* general info: https://gpsd.gitlab.io/gpsd/
* raw interface: https://gpsd.gitlab.io/gpsd/client-howto.html
*
* Simple server test, run this command:
* while true; do echo '"mode":2 "lat":34.567 "lon":-123.456 "time":"2020-01-02T03:04:05.000Z"' | nc -l 192.168.7.11 2947; done
*/
#include "HamClock.h"
#define GPSD_PORT 2947 // tcp port
#define MAX_READ 2048 // give up if no info after this much
static time_t gpsd_time; // set by lookforTime if successful
/* look for time and sufficient mode in the given string from gpsd.
* if found, save in gpsd_time and return true, else return false.
*/
static bool lookforTime (const char *buf, size_t n_buf)
{
// quick check for fields
if (n_buf < 43)
return(false);
const char *modestr = strstr (buf, "\"mode\":");
if (!modestr || n_buf-(modestr-buf) < 10)
return(false);
const char *timestr = strstr (buf, "\"time\":");
if (!timestr || n_buf-(timestr-buf) < 33)
return(false);
// start pessimistic
bool ok = false;
// crack fields
int mode = atoi (modestr+7);
if (mode >= 2) {
// get time now so we can correct after we process and display
uint32_t t0 = millis();
// crack time form: "time":"2012-04-05T15:00:01.501Z"
int yr, mo, dy, hr, mn, sc;
if (sscanf (timestr+8, "%d-%d-%dT%d:%d:%d", &yr, &mo, &dy, &hr, &mn, &sc) != 6)
return (false);
Serial.println (F("GPSD: time ok"));
// reformat
tmElements_t tm;
tm.Year = yr - 1970;
tm.Month = mo;
tm.Day = dy;
tm.Hour = hr;
tm.Minute = mn;
tm.Second = sc;
gpsd_time = makeTime (tm);
// correct for time spent here
gpsd_time += (millis() - t0 + 500)/1000;
// good
ok = true;
}
// success?
return (ok);
}
/* look for lat and lon and sufficient mode in the given string from gpsd.
* if found, save in de_ll and NV and return true, else return false and tell user if mode < 2
*/
static bool lookforLatLong (const char *buf, size_t n_buf)
{
// quick check for fields
if (n_buf < 34)
return (false);
const char *modestr = strstr (buf, "\"mode\":");
if (!modestr || n_buf-(modestr-buf) < 10)
return (false);
const char *latstr = strstr (buf, "\"lat\":");
if (!latstr || n_buf-(latstr-buf) < 12)
return (false);
const char *lonstr = strstr (buf, "\"lon\":");
if (!lonstr || n_buf-(lonstr-buf) < 12)
return (false);
// start pessimistic
bool ok = false;
// crack fields
int mode = atoi(modestr+7);
if (mode >= 2) {
// store
de_ll.lat_d = atof(latstr+6);
de_ll.lng_d = atof(lonstr+6);
normalizeLL (de_ll);
setMaidenhead (NV_DE_GRID, de_ll);
NVWriteFloat (NV_DE_LAT, de_ll.lat_d);
NVWriteFloat (NV_DE_LNG, de_ll.lng_d);
// good
Serial.println (F("GPSD: L/L ok"));
ok = true;
}
// success?
return (ok);
}
/* connect to gpsd and return whether lookf() found what it wants.
*/
static bool getGPSDSomething(bool (*lookf)(const char *buf, size_t n_buf))
{
// get host name, done if not enabled
char host[NV_GPSDHOST_LEN];
if (!getGPSDHost (host))
return (false);
// prep state
WiFiClient gpsd_client;
bool look_ok = false;
bool connect_ok = false;
bool got_something = false;
// connect to and read from gpsd server,
Serial.printf ("GPSD: %s\n", host);
resetWatchdog();
if (wifiOk() && gpsd_client.connect (host, GPSD_PORT)) {
// initial progress
connect_ok = true;
// enable reporting
gpsd_client.print (F("?WATCH={\"enable\":true,\"json\":true}"));
// build buf, give to lookf, done when it's happy or no more
char buf[MAX_READ];
size_t n_buf = 0;
while (!look_ok && n_buf < MAX_READ-1 && getChar (gpsd_client, &buf[n_buf])) {
got_something = true;
buf[++n_buf] = '\0';
look_ok = (*lookf)(buf, n_buf);
}
}
// finished with connection
gpsd_client.stop();
// report problems
if (!look_ok) {
if (got_something)
Serial.println (F("GPSD: unexpected response"));
else if (connect_ok)
Serial.println (F("GPSD: connected but no response"));
else
Serial.println (F("GPSD: no connection"));
}
// success?
return (look_ok);
}
/* return time from GPSD if available, else return 0
*/
time_t getGPSDUTC()
{
if (getGPSDSomething (lookforTime))
return (gpsd_time);
return (0);
}
/* get lat/long from GPSD and set de_ll if using gpsd.
*/
void getGPSDDELatLong()
{
(void) getGPSDSomething (lookforLatLong);
}