@@ -18,3 +18,8 @@ | |||
-DCRTSCTS=0x00020000 | |||
-DONLCR=0x00000002 | |||
-D__gnuc_va_list=va_list | |||
-D__signed__=signed | |||
-D__pid_t=int | |||
-D__size_t=size_t | |||
-Dpps_handle_t=int | |||
@@ -7,3 +7,4 @@ Jeff Francis <jeff@gritch.org> | |||
Amaury Jacquot <sxpert@esitcom.org> | |||
Chris Kuethe <chris.kuethe@gmail.com> | |||
Ville Nuorvala <vnuorval@tcs.hut.fi> | |||
Fulup Ar Foll <fulup@sinagot.net> |
@@ -2,3 +2,11 @@ For the gpsd project, the information that was traditionally placed in | |||
this file is in the repository as: | |||
www/hacking.html | |||
If you only have www/hacking.html.in, run | |||
scons www | |||
This builds www/hacking.html with some magic cookies usefully substituted. | |||
@@ -85,7 +85,7 @@ various additional features have additional prerequisites: | |||
|pgtk-2/cairo bindings | the main test client, xgps, needs this | |||
|========================================================================== | |||
Some ncurses packages comntain the terminfo library; some break it out | |||
Some ncurses packages contain the terminfo library; some break it out | |||
separately as libtinfo5 or libtinfo. | |||
The Python code in GPSD is actually compatible back to Python 2.4 except that | |||
@@ -157,8 +157,5 @@ first time it's invoked, it will generate a file called | |||
'gpsd_config.inc' in that directory containing configuration | |||
information; edit to taste. | |||
4. Note for people using gpsd as time source for ntpd: In case you're | |||
using dhcp3-client to configure your system, make sure you disable | |||
/etc/dhcp3/dhclient-exit-hooks.d/ntp, as dhclient would restart | |||
ntpd with an automatically created ntp.conf otherwise - and gpsd | |||
would not be able to talk with ntpd anymore. | |||
For special instructions related to using GPSD for time service, see the | |||
GPSD Time Service HOWTO in the distribution or on the web. |
@@ -1,3 +1,16 @@ | |||
GPSD project news | |||
* Fri 22 Oct 2013 Eric S. Raymond <esr@snark.thyrsus.com> - 3.10 | |||
AIS: Adds gps2udp, an AIS data relay, split24 option supports | |||
passing through Type 24 halves; support for Inland AIS; "scaled" no | |||
longer controls dumping of controlled-vocabulary fields; instead, | |||
the're always dumped numerically and as text, with text in an | |||
attribute name generated by appending "_text" to the name of the | |||
base attribute. The packetizer's handling of write boundaries not | |||
coinciding with packet boundaries is improved. Better support for | |||
mode and speed switching in the UBX driver. PPS message now ships | |||
nsec. PPS events are visible in gpsmon. Time-reporting fix to TSIP. | |||
* Wed 1 May 2013 Eric S. Raymond <esr@snark.thyrsus.com> - 3.9 | |||
Note to packagers: this is an urgent release that fixes a possible | |||
DoS or security hole! Armor the AIS driver against an implausible | |||
@@ -8,10 +21,11 @@ | |||
* Mon 25 Feb 2013 Eric S. Raymond <esr@snark.thyrsus.com> - 3.8 | |||
Fix various minor errors in the AIVDM/AIVDO description. Repair the | |||
xmlto support in the build system. Add two more regression tests. Significant | |||
improvements to NMEA2000 support. Upgrade the PHP client to v3 of the | |||
Google Maps API. Support for the Telit SL869 chipset. Added a nautical-style | |||
display to xgpsspeed. Minor improvements to leapsecond.py. | |||
xmlto support in the build system. Add two more regression | |||
tests. Significant improvements to NMEA2000 support. Upgrade the PHP | |||
client to v3 of the Google Maps API. Support for the Telit SL869 | |||
chipset. Added a nautical-style display to xgpsspeed. Minor | |||
improvements to leapsecond.py. | |||
* Mon 02 Jul 2012 Eric S. Raymond <esr@snark.thyrsus.com> - 3.7 | |||
Snap release to get the midnight change in the default leap-second | |||
@@ -45,7 +59,7 @@ | |||
* Sat Oct 29 2011 Eric S. Raymond <esr@snark.thyrsus.com> - 3.3 | |||
Improvements to build and release-procedure documentation. Make | |||
sirf=no build work again. Main reason for this release is to make | |||
chrpath a mandatory build depedency and explain why in the build | |||
chrpath a mandatory build dependency and explain why in the build | |||
documentation. | |||
* Wed Oct 25 2011 Eric S. Raymond <esr@snark.thyrsus.com> - 3.2 | |||
@@ -286,7 +300,7 @@ | |||
* Sun Mar 12 2006 Eric S. Raymond <esr@snark.thyrsus.com> - 2.32-1 | |||
Cleanup of the xgps layout, and minor memory-leak fixes for xgps. Fix | |||
to cope with Antares uBlox by Andreas Stricker. Minor fix to libgps | |||
to cope with Antares u-blox by Andreas Stricker. Minor fix to libgps | |||
cgpxlogger. Merge cgpxlogger and gpxlogger documentation onto | |||
the xgps(1) manual page and rename it gps(1). | |||
@@ -16,6 +16,44 @@ See the GPSD bug tracker on the project website, but don't be | |||
surprised if it's empty or very sparse. Our rate of new defects per | |||
month is quite low. | |||
*** Client bugs | |||
**** In gpsmon's PPS Offset field | |||
resently PPS Offset is displayed in direct mode for NMEA, SiRF, and | |||
UBX devices. Others should probably do likewise, notably the | |||
Motorola Oncore and Garmin drivers. | |||
**** gpsmon driver switching and blocking on error | |||
Hal Murray reports: | |||
If I run .gpsmon /dev/ttyUSB0 | |||
It starts up in NMEA0183 mode as I expect. | |||
"i" switches to SiRF, again, as I expect. | |||
"n" switches the display to NMEA layout, but the header still says SiRF. | |||
Another "n" now says: Device type has no mode switcher. | |||
At this point, "i" doesn't do anything. (no pause either) | |||
The second 'n' is losing information that it shouldn't. | |||
If I start over and feed it an "f", it starts blinking "Unknown command "f" | |||
The logging and display update stops. After I type another character, it | |||
clears the blinking error message and stars logging/updating again. | |||
Display update should not stop while this is going on. | |||
*** Speed, mode and rate-changes in client-mode gpsmon. | |||
Are not implemented. In theory they could be. | |||
*** Speed, mode and rate-changes in client-mode gpsctl. | |||
Baud rate and mode changes work in direct mode but are not | |||
reliable in client mode. | |||
*** Dispatcher/network issues | |||
**** Reading AISHub data via UDP confuses xgps with short writes | |||
@@ -26,17 +64,17 @@ packet aggregation issue as it doesn't happen with test logs. | |||
*** Driver issues | |||
**** gpsctl -b should work on UBX, but does not. | |||
Presently this means there's no way to kick a UBX into returning | |||
binary data. Chris Kuethe is supposed to fix this one. | |||
**** RTCM3 analysis is incomplete | |||
We can presently decode RTCM3 messages of type 1004, 1005, 1006, 1008, 1012, | |||
1013, and 1029. This is not the complete set. We need more test data with | |||
different types in them, and a copy of the RTCM3 standard at latest revision | |||
(all we have is revision 3). | |||
We can presently decode RTCM3 messages of type 1001-1014, 1029, and | |||
1033. This is not the complete set. We need more test data with | |||
different types in them, and a copy of the RTCM3 standard at latest | |||
revision (all we have is revision 3). | |||
The support for unpacking RTCM3 sentences in the client library is | |||
limited to 1001, 1002, 1007, 1008, 1009, 1010, 1014, and 1033. There | |||
are some design issues with the baby JSON parser that are going to | |||
make extending this set difficult. | |||
**** Reporting code for specialized Type 6 and 8 AIS messages is incomplete. | |||
@@ -49,19 +87,6 @@ message 6 and 8 subtypes - specifically, 6/23, 8/21, 8/22, 8/24, and | |||
We'd need machinery to shift a byte array 30 bits left... | |||
**** JSON passthrough for AIS | |||
Roy Barkas wants to be able to pass custom JSON up to GPSD in an | |||
armored AIS sentence, so all his clients will get it. See | |||
http://lists.nongnu.org/archive/html/gpsd-dev/2013-01/msg00022.html | |||
for the full proposal. | |||
** Ports | |||
*** Windows port | |||
Partially complete. David Ludlow <dave@adsllc.com> is working on it. | |||
** To do: | |||
*** Make subframe reports available in the C API. | |||
@@ -83,7 +108,7 @@ shouldn't be difficult. | |||
*** Enable flocktest on the Debian server farm | |||
Debian server farm boxes have a screwy chrooted envorinment setup. | |||
Debian server farm boxes have a screwy chrooted environment setup. | |||
flocktest needs to be modified to deal with it. | |||
*** Finish gpssim | |||
@@ -579,11 +579,13 @@ static void Destroy(Widget w) | |||
/* Exported Procedures */ | |||
// cppcheck-suppress unusedFunction | |||
int TachometerGetValue(Widget w) | |||
{ | |||
return (((TachometerWidget) w)->tachometer.value); | |||
} | |||
// cppcheck-suppress unusedFunction | |||
int TachometerSetValue(Widget w, int i) | |||
{ | |||
int old; | |||
@@ -122,7 +122,7 @@ int json_ais_read(const char *buf, | |||
&ais->type5.minute); | |||
} | |||
} else if (strstr(buf, "\"type\":6,") != NULL) { | |||
bool imo = false; | |||
bool structured = false; | |||
if (strstr(buf, "\"dac\":1,") != NULL) { | |||
if (strstr(buf, "\"fid\":12,") != NULL) { | |||
status = json_read_object(buf, json_ais6_fid12, endptr); | |||
@@ -148,15 +148,15 @@ int json_ais_read(const char *buf, | |||
&ais->type6.dac1fid12.nhour, | |||
&ais->type6.dac1fid12.nminute); | |||
} | |||
imo = true; | |||
structured = true; | |||
} | |||
else if (strstr(buf, "\"fid\":15,") != NULL) { | |||
status = json_read_object(buf, json_ais6_fid15, endptr); | |||
imo = true; | |||
structured = true; | |||
} | |||
else if (strstr(buf, "\"fid\":16,") != NULL) { | |||
status = json_read_object(buf, json_ais6_fid16, endptr); | |||
imo = true; | |||
structured = true; | |||
} | |||
else if (strstr(buf, "\"fid\":18,") != NULL) { | |||
status = json_read_object(buf, json_ais6_fid18, endptr); | |||
@@ -171,7 +171,7 @@ int json_ais_read(const char *buf, | |||
&ais->type6.dac1fid18.hour, | |||
&ais->type6.dac1fid18.minute); | |||
} | |||
imo = true; | |||
structured = true; | |||
} | |||
else if (strstr(buf, "\"fid\":20,") != NULL) { | |||
status = json_read_object(buf, json_ais6_fid20, endptr); | |||
@@ -187,11 +187,11 @@ int json_ais_read(const char *buf, | |||
&ais->type6.dac1fid20.hour, | |||
&ais->type6.dac1fid20.minute); | |||
} | |||
imo = true; | |||
structured = true; | |||
} | |||
else if (strstr(buf, "\"fid\":25,") != NULL) { | |||
status = json_read_object(buf, json_ais6_fid25, endptr); | |||
imo = true; | |||
structured = true; | |||
} | |||
else if (strstr(buf, "\"fid\":28,") != NULL) { | |||
status = json_read_object(buf, json_ais6_fid28, endptr); | |||
@@ -207,24 +207,62 @@ int json_ais_read(const char *buf, | |||
&ais->type6.dac1fid28.hour, | |||
&ais->type6.dac1fid28.minute); | |||
} | |||
imo = true; | |||
structured = true; | |||
} | |||
else if (strstr(buf, "\"fid\":30,") != NULL) { | |||
status = json_read_object(buf, json_ais6_fid30, endptr); | |||
imo = true; | |||
structured = true; | |||
} | |||
else if (strstr(buf, "\"fid\":32,") != NULL || strstr(buf, "\"fid\":14,") != NULL) { | |||
status = json_read_object(buf, json_ais6_fid32, endptr); | |||
imo = true; | |||
structured = true; | |||
} | |||
} | |||
else if (strstr(buf, "\"dac\":235,") != NULL || strstr(buf, "\"dac\":250,") != NULL) { | |||
if (strstr(buf, "\"fid\":10,") != NULL) { | |||
status = json_read_object(buf, json_ais6_fid10, endptr); | |||
imo = true; | |||
structured = true; | |||
} | |||
} | |||
if (!imo) { | |||
else if (strstr(buf, "\"dac\":200,") != NULL) { | |||
if (strstr(buf, "\"fid\":21,") != NULL) { | |||
status = json_read_object(buf, json_ais6_fid21, endptr); | |||
structured = true; | |||
if (status == 0) { | |||
ais->type6.dac200fid21.month = AIS_MONTH_NOT_AVAILABLE; | |||
ais->type6.dac200fid21.day = AIS_DAY_NOT_AVAILABLE; | |||
ais->type6.dac200fid21.hour = AIS_HOUR_NOT_AVAILABLE; | |||
ais->type6.dac200fid21.minute = AIS_MINUTE_NOT_AVAILABLE; | |||
// cppcheck-suppress uninitvar | |||
(void)sscanf(eta, "%02u-%02uT%02u:%02u", | |||
&ais->type6.dac200fid21.month, | |||
&ais->type6.dac200fid21.day, | |||
&ais->type6.dac200fid21.hour, | |||
&ais->type6.dac200fid21.minute); | |||
} | |||
} | |||
else if (strstr(buf, "\"fid\":22,") != NULL) { | |||
status = json_read_object(buf, json_ais6_fid22, endptr); | |||
structured = true; | |||
if (status == 0) { | |||
ais->type6.dac200fid22.month = AIS_MONTH_NOT_AVAILABLE; | |||
ais->type6.dac200fid22.day = AIS_DAY_NOT_AVAILABLE; | |||
ais->type6.dac200fid22.hour = AIS_HOUR_NOT_AVAILABLE; | |||
ais->type6.dac200fid22.minute = AIS_MINUTE_NOT_AVAILABLE; | |||
// cppcheck-suppress uninitvar | |||
(void)sscanf(rta, "%02u-%02uT%02u:%02u", | |||
&ais->type6.dac200fid22.month, | |||
&ais->type6.dac200fid22.day, | |||
&ais->type6.dac200fid22.hour, | |||
&ais->type6.dac200fid22.minute); | |||
} | |||
} | |||
else if (strstr(buf, "\"fid\":55,") != NULL) { | |||
status = json_read_object(buf, json_ais6_fid55, endptr); | |||
structured = true; | |||
} | |||
} | |||
if (!structured) { | |||
status = json_read_object(buf, json_ais6, endptr); | |||
if (status == 0) | |||
lenhex_unpack(data, &ais->type6.bitcount, | |||
@@ -234,7 +272,7 @@ int json_ais_read(const char *buf, | |||
|| strstr(buf, "\"type\":13,") != NULL) { | |||
status = json_read_object(buf, json_ais7, endptr); | |||
} else if (strstr(buf, "\"type\":8,") != NULL) { | |||
bool imo = false; | |||
bool structured = false; | |||
if (strstr(buf, "\"dac\":1,") != NULL) { | |||
if (strstr(buf, "\"fid\":11,") != NULL) { | |||
status = json_read_object(buf, json_ais8_fid11, endptr); | |||
@@ -248,7 +286,7 @@ int json_ais_read(const char *buf, | |||
&ais->type8.dac1fid11.hour, | |||
&ais->type8.dac1fid11.minute); | |||
} | |||
imo = true; | |||
structured = true; | |||
} | |||
else if (strstr(buf, "\"fid\":13,") != NULL) { | |||
status = json_read_object(buf, json_ais8_fid13, endptr); | |||
@@ -274,19 +312,55 @@ int json_ais_read(const char *buf, | |||
&ais->type8.dac1fid13.thour, | |||
&ais->type8.dac1fid13.tminute); | |||
} | |||
imo = true; | |||
structured = true; | |||
} | |||
else if (strstr(buf, "\"fid\":15,") != NULL) { | |||
status = json_read_object(buf, json_ais8_fid15, endptr); | |||
imo = true; | |||
structured = true; | |||
} | |||
else if (strstr(buf, "\"fid\":16,") != NULL) { | |||
status = json_read_object(buf, json_ais8_fid16, endptr); | |||
structured = true; | |||
} | |||
else if (strstr(buf, "\"fid\":17,") != NULL) { | |||
status = json_read_object(buf, json_ais8_fid17, endptr); | |||
imo = true; | |||
structured = true; | |||
} | |||
else if (strstr(buf, "\"fid\":19,") != NULL) { | |||
status = json_read_object(buf, json_ais8_fid19, endptr); | |||
imo = true; | |||
structured = true; | |||
} | |||
else if (strstr(buf, "\"fid\":23,") != NULL) { | |||
status = json_read_object(buf, json_ais8_fid23, endptr); | |||
ais->type8.dac200fid23.start_year = AIS_YEAR_NOT_AVAILABLE; | |||
ais->type8.dac200fid23.start_month = AIS_MONTH_NOT_AVAILABLE; | |||
ais->type8.dac200fid23.start_day = AIS_DAY_NOT_AVAILABLE; | |||
ais->type8.dac200fid23.start_hour = AIS_HOUR_NOT_AVAILABLE; | |||
ais->type8.dac200fid23.start_minute = AIS_MINUTE_NOT_AVAILABLE; | |||
ais->type8.dac200fid23.end_year = AIS_YEAR_NOT_AVAILABLE; | |||
ais->type8.dac200fid23.end_month = AIS_MONTH_NOT_AVAILABLE; | |||
ais->type8.dac200fid23.end_day = AIS_DAY_NOT_AVAILABLE; | |||
ais->type8.dac200fid23.end_hour = AIS_HOUR_NOT_AVAILABLE; | |||
ais->type8.dac200fid23.end_minute = AIS_MINUTE_NOT_AVAILABLE; | |||
// cppcheck-suppress uninitvar | |||
(void)sscanf(start, "%09u-%02u-%02uT%02u:%02u", | |||
&ais->type8.dac200fid23.start_year, | |||
&ais->type8.dac200fid23.start_month, | |||
&ais->type8.dac200fid23.start_day, | |||
&ais->type8.dac200fid23.start_hour, | |||
&ais->type8.dac200fid23.start_minute); | |||
// cppcheck-suppress uninitvar | |||
(void)sscanf(end, "%09u-%02u-%02uT%02u:%02u", | |||
&ais->type8.dac200fid23.end_year, | |||
&ais->type8.dac200fid23.end_month, | |||
&ais->type8.dac200fid23.end_day, | |||
&ais->type8.dac200fid23.end_hour, | |||
&ais->type8.dac200fid23.end_minute); | |||
structured = true; | |||
} | |||
else if (strstr(buf, "\"fid\":24,") != NULL) { | |||
status = json_read_object(buf, json_ais8_fid24, endptr); | |||
structured = true; | |||
} | |||
else if (strstr(buf, "\"fid\":27,") != NULL) { | |||
status = json_read_object(buf, json_ais8_fid27, endptr); | |||
@@ -302,11 +376,11 @@ int json_ais_read(const char *buf, | |||
&ais->type8.dac1fid27.hour, | |||
&ais->type8.dac1fid27.minute); | |||
} | |||
imo = true; | |||
structured = true; | |||
} | |||
else if (strstr(buf, "\"fid\":29,") != NULL) { | |||
status = json_read_object(buf, json_ais8_fid29, endptr); | |||
imo = true; | |||
structured = true; | |||
} | |||
else if (strstr(buf, "\"fid\":31,") != NULL) { | |||
status = json_read_object(buf, json_ais8_fid31, endptr); | |||
@@ -320,10 +394,20 @@ int json_ais_read(const char *buf, | |||
&ais->type8.dac1fid31.hour, | |||
&ais->type8.dac1fid31.minute); | |||
} | |||
imo = true; | |||
structured = true; | |||
} | |||
} | |||
else if (strstr(buf, "\"dac\":200,") != NULL) { | |||
if (strstr(buf, "\"fid\":10,") != NULL) { | |||
status = json_read_object(buf, json_ais8_fid10, endptr); | |||
structured = true; | |||
} | |||
if (strstr(buf, "\"fid\":40,") != NULL) { | |||
status = json_read_object(buf, json_ais8_fid40, endptr); | |||
structured = true; | |||
} | |||
} | |||
if (!imo) { | |||
if (!structured) { | |||
status = json_read_object(buf, json_ais8, endptr); | |||
if (status == 0) | |||
lenhex_unpack(data, &ais->type8.bitcount, | |||
@@ -10,6 +10,7 @@ | |||
AIS_HEADER | |||
{"status", t_uinteger, .addr.uinteger = &ais->type1.status, | |||
.dflt.uinteger = 0}, | |||
{"status_text", t_ignore}, | |||
{"turn", t_integer, .addr.integer = &ais->type1.turn, | |||
.dflt.integer = AIS_TURN_NOT_AVAILABLE}, | |||
{"speed", t_uinteger, .addr.uinteger = &ais->type1.speed, | |||
@@ -48,6 +49,7 @@ | |||
.dflt.integer = AIS_LAT_NOT_AVAILABLE}, | |||
{"epfd", t_uinteger, .addr.uinteger = &ais->type4.epfd, | |||
.dflt.uinteger = 0}, | |||
{"epfd_text", t_ignore}, | |||
{"raim", t_boolean, .addr.boolean = &ais->type4.raim, | |||
.dflt.boolean = false}, | |||
{"radio", t_uinteger, .addr.uinteger = &ais->type4.radio, | |||
@@ -68,6 +70,7 @@ | |||
.len = sizeof(ais->type5.shipname)}, | |||
{"shiptype", t_uinteger, .addr.uinteger = &ais->type5.shiptype, | |||
.dflt.uinteger = 0}, | |||
{"shiptype_text", t_ignore}, | |||
{"to_bow", t_uinteger, .addr.uinteger = &ais->type5.to_bow, | |||
.dflt.uinteger = 0}, | |||
{"to_stern", t_uinteger, .addr.uinteger = &ais->type5.to_stern, | |||
@@ -78,6 +81,7 @@ | |||
.dflt.uinteger = 0}, | |||
{"epfd", t_uinteger, .addr.uinteger = &ais->type5.epfd, | |||
.dflt.uinteger = 0}, | |||
{"epfd_text", t_ignore}, | |||
{"eta", t_string, .addr.string = eta, | |||
.len = sizeof(eta)}, | |||
{"draught", t_uinteger, .addr.uinteger = &ais->type5.draught, | |||
@@ -109,8 +113,10 @@ | |||
.dflt.uinteger = 0}, | |||
{"racon", t_uinteger, .addr.uinteger = &ais->type6.dac235fid10.racon, | |||
.dflt.uinteger = 0}, | |||
{"racon_text", t_ignore}, | |||
{"light", t_uinteger, .addr.uinteger = &ais->type6.dac235fid10.light, | |||
.dflt.uinteger = 0}, | |||
{"light_text", t_ignore}, | |||
{"alarm", t_boolean, .addr.boolean = &ais->type6.dac235fid10.alarm, | |||
.dflt.boolean = false}, | |||
{"stat_ext", t_uinteger, .addr.uinteger = &ais->type6.dac235fid10.stat_ext, | |||
@@ -161,26 +167,6 @@ | |||
{NULL} | |||
}; | |||
const struct json_attr_t json_ais6_fid25_cargos_subtype[] = { | |||
{"code", t_uinteger,STRUCTOBJECT(struct cargo_t, code), | |||
.dflt.uinteger = 0}, | |||
{"subtype", t_uinteger,STRUCTOBJECT(struct cargo_t, subtype), | |||
.dflt.uinteger = 0}, | |||
{NULL} | |||
}; | |||
/*@-type@*//* STRUCTARRAY confuses splint */ | |||
const struct json_attr_t json_ais6_fid25[] = { | |||
AIS_HEADER | |||
AIS_TYPE6 | |||
{"unit", t_uinteger, .addr.uinteger = &ais->type6.dac1fid25.unit, | |||
.dflt.uinteger = 0}, | |||
{"amount", t_uinteger, .addr.uinteger = &ais->type6.dac1fid25.amount, | |||
.dflt.uinteger = 0}, | |||
{"cargos", t_array, STRUCTARRAY(ais->type6.dac1fid25.cargos, json_ais6_fid25_cargos_subtype, &ais->type6.dac1fid25.ncargos)}, | |||
{NULL} | |||
}; | |||
/*@+type@*/ | |||
char arrival[JSON_VAL_MAX+1]; | |||
const struct json_attr_t json_ais6_fid18[] = { | |||
AIS_HEADER | |||
@@ -212,6 +198,7 @@ | |||
.dflt.uinteger = 0}, | |||
{"position", t_uinteger, .addr.uinteger = &ais->type6.dac1fid20.position, | |||
.dflt.uinteger = 0}, | |||
{"position_text", t_ignore}, | |||
{"arrival", t_string, .addr.string = arrival, | |||
.len = sizeof(arrival)}, | |||
{"availability", t_uinteger, .addr.uinteger = &ais->type6.dac1fid20.availability, | |||
@@ -277,6 +264,69 @@ | |||
{NULL} | |||
}; | |||
const struct json_attr_t json_ais6_fid21[] = { | |||
AIS_HEADER | |||
AIS_TYPE6 | |||
{"country", t_string, .addr.string = ais->type6.dac200fid21.country, | |||
.len = sizeof(ais->type6.dac200fid21.country)}, | |||
{"locode", t_string, .addr.string = ais->type6.dac200fid21.locode, | |||
.len = sizeof(ais->type6.dac200fid21.locode)}, | |||
{"section", t_string, .addr.string = ais->type6.dac200fid21.section, | |||
.len = sizeof(ais->type6.dac200fid21.section)}, | |||
{"terminal", t_string, .addr.string = ais->type6.dac200fid21.terminal, | |||
.len = sizeof(ais->type6.dac200fid21.terminal)}, | |||
{"hectometre", t_string, .addr.string = ais->type6.dac200fid21.hectometre, | |||
.len = sizeof(ais->type6.dac200fid21.hectometre)}, | |||
{"eta", t_string, .addr.string = eta, | |||
.len = sizeof(eta)}, | |||
{"tugs", t_uinteger, .addr.uinteger = &ais->type6.dac200fid21.tugs, | |||
.dflt.uinteger = 0}, | |||
{"airdraught", t_uinteger, .addr.uinteger = &ais->type6.dac200fid21.airdraught, | |||
.dflt.uinteger = 0}, | |||
{NULL} | |||
}; | |||
char rta[JSON_VAL_MAX+1]; | |||
const struct json_attr_t json_ais6_fid22[] = { | |||
AIS_HEADER | |||
AIS_TYPE6 | |||
{"country", t_string, .addr.string = ais->type6.dac200fid22.country, | |||
.len = sizeof(ais->type6.dac200fid22.country)}, | |||
{"locode", t_string, .addr.string = ais->type6.dac200fid22.locode, | |||
.len = sizeof(ais->type6.dac200fid22.locode)}, | |||
{"section", t_string, .addr.string = ais->type6.dac200fid22.section, | |||
.len = sizeof(ais->type6.dac200fid22.section)}, | |||
{"terminal", t_string, .addr.string = ais->type6.dac200fid22.terminal, | |||
.len = sizeof(ais->type6.dac200fid22.terminal)}, | |||
{"hectometre", t_string, .addr.string = ais->type6.dac200fid22.hectometre, | |||
.len = sizeof(ais->type6.dac200fid22.hectometre)}, | |||
{"rta", t_string, .addr.string = rta, | |||
.len = sizeof(rta)}, | |||
{"status", t_uinteger, .addr.uinteger = &ais->type6.dac200fid22.status, | |||
.dflt.uinteger = DAC200FID22_STATUS_NOT_AVAILABLE}, | |||
{NULL} | |||
}; | |||
const struct json_attr_t json_ais6_fid25_cargos_subtype[] = { | |||
{"code", t_uinteger,STRUCTOBJECT(struct cargo_t, code), | |||
.dflt.uinteger = 0}, | |||
{"subtype", t_uinteger,STRUCTOBJECT(struct cargo_t, subtype), | |||
.dflt.uinteger = 0}, | |||
{NULL} | |||
}; | |||
/*@-type@*//* STRUCTARRAY confuses splint */ | |||
const struct json_attr_t json_ais6_fid25[] = { | |||
AIS_HEADER | |||
AIS_TYPE6 | |||
{"unit", t_uinteger, .addr.uinteger = &ais->type6.dac1fid25.unit, | |||
.dflt.uinteger = 0}, | |||
{"amount", t_uinteger, .addr.uinteger = &ais->type6.dac1fid25.amount, | |||
.dflt.uinteger = 0}, | |||
{"cargos", t_array, STRUCTARRAY(ais->type6.dac1fid25.cargos, json_ais6_fid25_cargos_subtype, &ais->type6.dac1fid25.ncargos)}, | |||
{NULL} | |||
}; | |||
/*@+type@*/ | |||
char start[JSON_VAL_MAX+1]; | |||
const struct json_attr_t json_ais6_fid28_waypoints_subtype[] = { | |||
{"lon", t_integer, STRUCTOBJECT(struct waypoint_t, lon), | |||
@@ -295,6 +345,7 @@ | |||
.dflt.uinteger = 0}, | |||
{"rtype", t_uinteger, .addr.uinteger = &ais->type6.dac1fid28.rtype, | |||
.dflt.uinteger = 0}, | |||
{"rtype_text", t_ignore}, | |||
{"start", t_string, .addr.string = start, | |||
.len = sizeof(start)}, | |||
{"duration", t_uinteger, .addr.uinteger = &ais->type6.dac1fid28.duration, | |||
@@ -346,6 +397,18 @@ | |||
}; | |||
/*@+type@*/ | |||
const struct json_attr_t json_ais6_fid55[] = { | |||
AIS_HEADER | |||
AIS_TYPE6 | |||
{"crew", t_uinteger, .addr.uinteger = &ais->type6.dac200fid55.crew, | |||
.dflt.uinteger = DAC200FID55_COUNT_NOT_AVAILABLE}, | |||
{"passengers", t_uinteger, .addr.uinteger = &ais->type6.dac200fid55.passengers, | |||
.dflt.uinteger = DAC200FID55_COUNT_NOT_AVAILABLE}, | |||
{"personnel", t_uinteger, .addr.uinteger = &ais->type6.dac200fid55.personnel, | |||
.dflt.uinteger = DAC200FID55_COUNT_NOT_AVAILABLE}, | |||
{NULL} | |||
}; | |||
const struct json_attr_t json_ais7[] = { | |||
AIS_HEADER | |||
{"mmsi1", t_uinteger, .addr.uinteger = &ais->type7.mmsi1, | |||
@@ -367,6 +430,35 @@ | |||
{NULL} | |||
}; | |||
const struct json_attr_t json_ais8_fid10[] = { | |||
AIS_HEADER | |||
AIS_TYPE8 | |||
{"vin", t_string, .addr.string = ais->type8.dac200fid10.vin, | |||
.len = sizeof(ais->type8.dac200fid10.vin)}, | |||
{"length", t_uinteger, .addr.uinteger = &ais->type8.dac200fid10.length, | |||
.dflt.uinteger = 0}, | |||
{"beam", t_uinteger, .addr.uinteger = &ais->type8.dac200fid10.beam, | |||
.dflt.uinteger = 0}, | |||
{"type", t_uinteger, .addr.uinteger = &ais->type8.dac200fid10.type, | |||
.dflt.uinteger = 0}, | |||
{"type_text", t_ignore}, | |||
{"hazard", t_uinteger, .addr.uinteger = &ais->type8.dac200fid10.hazard, | |||
.dflt.uinteger = 0}, | |||
{"hazard_text", t_ignore}, | |||
{"draught", t_uinteger, .addr.uinteger = &ais->type8.dac200fid10.draught, | |||
.dflt.uinteger = 0}, | |||
{"loaded", t_uinteger, .addr.uinteger = &ais->type8.dac200fid10.loaded, | |||
.dflt.uinteger = 0}, | |||
{"loaded_text", t_ignore}, | |||
{"speed_q", t_boolean, .addr.boolean = &ais->type8.dac200fid10.speed_q, | |||
.dflt.boolean = false}, | |||
{"course_q", t_boolean, .addr.boolean = &ais->type8.dac200fid10.course_q, | |||
.dflt.boolean = false}, | |||
{"heading_q", t_boolean, .addr.boolean = &ais->type8.dac200fid10.heading_q, | |||
.dflt.boolean = false}, | |||
{NULL} | |||
}; | |||
const struct json_attr_t json_ais8_fid11[] = { | |||
AIS_HEADER | |||
AIS_TYPE8 | |||
@@ -434,22 +526,26 @@ | |||
.dflt.uinteger = DAC1FID11_WATERTEMP_NOT_AVAILABLE}, | |||
{"preciptype", t_uinteger, .addr.uinteger = &ais->type8.dac1fid11.preciptype, | |||
.dflt.uinteger = DAC1FID11_PRECIPTYPE_NOT_AVAILABLE}, | |||
{"preciptype_text", t_ignore}, | |||
{"salinity", t_uinteger, .addr.uinteger = &ais->type8.dac1fid11.salinity, | |||
.dflt.uinteger = DAC1FID11_SALINITY_NOT_AVAILABLE}, | |||
{"ice", t_uinteger, .addr.uinteger = &ais->type8.dac1fid11.ice, | |||
.dflt.uinteger = DAC1FID11_ICE_NOT_AVAILABLE}, | |||
{"ice_text", t_ignore}, | |||
{NULL} | |||
}; | |||
char closefrom[JSON_VAL_MAX+1]; | |||
char closeto[JSON_VAL_MAX+1]; | |||
const struct json_attr_t json_ais8_fid13[] = { | |||
AIS_HEADER | |||
AIS_TYPE8 | |||
{"reason", t_string, .addr.string = ais->type8.dac1fid13.reason, | |||
.len = sizeof(ais->type8.dac1fid13.reason)}, | |||
{"closefrom", t_string, .addr.string = ais->type8.dac1fid13.closefrom, | |||
.len = sizeof(ais->type8.dac1fid13.closefrom)}, | |||
{"closeto", t_string, .addr.string = ais->type8.dac1fid13.closeto, | |||
.len = sizeof(ais->type8.dac1fid13.closeto)}, | |||
{"closefrom", t_string, .addr.string = closefrom, | |||
.len = sizeof(closefrom)}, | |||
{"closeto", t_string, .addr.string = closeto, | |||
.len = sizeof(closeto)}, | |||
{"radius", t_uinteger, .addr.uinteger = &ais->type8.dac1fid13.radius, | |||
.dflt.uinteger = AIS_DAC1FID13_RADIUS_NOT_AVAILABLE}, | |||
{"extunit", t_uinteger, .addr.uinteger = &ais->type8.dac1fid13.extunit, | |||
@@ -481,6 +577,14 @@ | |||
{NULL} | |||
}; | |||
const struct json_attr_t json_ais8_fid16[] = { | |||
AIS_HEADER | |||
AIS_TYPE8 | |||
{"persons", t_uinteger, .addr.uinteger = &ais->type8.dac1fid16.persons, | |||
.dflt.uinteger = 0}, | |||
{NULL} | |||
}; | |||
const struct json_attr_t json_ais8_fid17_targets_subtype[] = { | |||
{"idtype", t_uinteger,STRUCTOBJECT(struct target_t, idtype), | |||
.dflt.uinteger = DAC1FID17_IDTYPE_OTHER}, | |||
@@ -528,15 +632,67 @@ | |||
.dflt.uinteger = 0}, | |||
{"signal", t_uinteger, .addr.uinteger = &ais->type8.dac1fid19.signal, | |||
.dflt.uinteger = 0}, | |||
{"signal_text", t_ignore}, | |||
{"hour", t_uinteger, .addr.uinteger = &ais->type8.dac1fid19.hour, | |||
.dflt.uinteger = AIS_HOUR_NOT_AVAILABLE}, | |||
{"minute", t_uinteger, .addr.uinteger = &ais->type8.dac1fid19.minute, | |||
.dflt.uinteger = AIS_MINUTE_NOT_AVAILABLE}, | |||
{"nextsignal", t_uinteger, .addr.uinteger = &ais->type8.dac1fid19.nextsignal, | |||
.dflt.uinteger = 0}, | |||
{"nextsignal_type", t_ignore}, | |||
{NULL} | |||
}; | |||
char end[JSON_VAL_MAX+1]; | |||
const struct json_attr_t json_ais8_fid23[] = { | |||
AIS_HEADER | |||
AIS_TYPE8 | |||
{"start", t_string, .addr.string = start, | |||
.len = sizeof(start)}, | |||
{"end", t_string, .addr.string = end, | |||
.len = sizeof(end)}, | |||
{"start_lon", t_integer, .addr.integer = &ais->type8.dac200fid23.start_lon, | |||
.dflt.integer = AIS_LON4_NOT_AVAILABLE}, | |||
{"start_lat", t_integer, .addr.integer = &ais->type8.dac200fid23.start_lat, | |||
.dflt.integer = AIS_LAT4_NOT_AVAILABLE}, | |||
{"end_lon", t_integer, .addr.integer = &ais->type8.dac200fid23.end_lon, | |||
.dflt.integer = AIS_LON4_NOT_AVAILABLE}, | |||
{"end_lat", t_integer, .addr.integer = &ais->type8.dac200fid23.end_lat, | |||
.dflt.integer = AIS_LAT4_NOT_AVAILABLE}, | |||
{"type", t_uinteger, .addr.uinteger = &ais->type8.dac200fid23.type, | |||
.dflt.uinteger = DAC200FID23_TYPE_UNKNOWN}, | |||
{"type_text", t_ignore}, | |||
{"min", t_integer, .addr.integer = &ais->type8.dac200fid23.min, | |||
.dflt.integer = DAC200FID23_MIN_UNKNOWN}, | |||
{"max", t_integer, .addr.integer = &ais->type8.dac200fid23.max, | |||
.dflt.integer = DAC200FID23_MAX_UNKNOWN}, | |||
{"intensity", t_uinteger, .addr.uinteger = &ais->type8.dac200fid23.intensity, | |||
.dflt.uinteger = DAC200FID23_CLASS_UNKNOWN}, | |||
{"intensity_text", t_ignore}, | |||
{"wind", t_uinteger, .addr.uinteger = &ais->type8.dac200fid23.wind, | |||
.dflt.uinteger = DAC200FID23_WIND_UNKNOWN}, | |||
{"wind_text", t_ignore}, | |||
{NULL} | |||
}; | |||
const struct json_attr_t json_ais8_fid24_gauges_subtype[] = { | |||
{"id", t_uinteger,STRUCTOBJECT(struct gauge_t, id), | |||
.dflt.uinteger = DAC200FID24_GAUGE_ID_UNKNOWN}, | |||
{"level", t_integer, STRUCTOBJECT(struct gauge_t, level), | |||
.dflt.integer = DAC200FID24_GAUGE_LEVEL_UNKNOWN}, | |||
{NULL} | |||
}; | |||
/*@-type@*//* STRUCTARRAY confuses splint */ | |||
const struct json_attr_t json_ais8_fid24[] = { | |||
AIS_HEADER | |||
AIS_TYPE8 | |||
{"country", t_string, .addr.string = ais->type8.dac200fid24.country, | |||
.len = sizeof(ais->type8.dac200fid24.country)}, | |||
{"gauges", t_array, STRUCTARRAY(ais->type8.dac200fid24.gauges, json_ais8_fid24_gauges_subtype, &ais->type8.dac200fid24.ngauges)}, | |||
{NULL} | |||
}; | |||
/*@+type@*/ | |||
const struct json_attr_t json_ais8_fid27_waypoints_subtype[] = { | |||
{"lon", t_integer, STRUCTOBJECT(struct waypoint_t, lon), | |||
.dflt.integer = AIS_LON4_NOT_AVAILABLE}, | |||
@@ -554,6 +710,7 @@ | |||
.dflt.uinteger = 0}, | |||
{"rtype", t_uinteger, .addr.uinteger = &ais->type8.dac1fid27.rtype, | |||
.dflt.uinteger = 0}, | |||
{"rtype_text", t_ignore}, | |||
{"start", t_string, .addr.string = start, | |||
.len = sizeof(start)}, | |||
{"duration", t_uinteger, .addr.uinteger = &ais->type8.dac1fid27.duration, | |||
@@ -644,6 +801,7 @@ | |||
.dflt.integer = DAC1FID31_WATERTEMP_NOT_AVAILABLE}, | |||
{"preciptype", t_uinteger, .addr.uinteger = &ais->type8.dac1fid31.preciptype, | |||
.dflt.uinteger = DAC1FID31_PRECIPTYPE_NOT_AVAILABLE}, | |||
{"preciptype_text", t_ignore}, | |||
{"salinity", t_uinteger, .addr.uinteger = &ais->type8.dac1fid31.salinity, | |||
.dflt.uinteger = DAC1FID31_SALINITY_NOT_AVAILABLE}, | |||
{"ice", t_uinteger, .addr.uinteger = &ais->type8.dac1fid31.ice, | |||
@@ -651,6 +809,22 @@ | |||
{NULL} | |||
}; | |||
const struct json_attr_t json_ais8_fid40[] = { | |||
AIS_HEADER | |||
AIS_TYPE8 | |||
{"form", t_uinteger, .addr.uinteger = &ais->type8.dac200fid40.form, | |||
.dflt.uinteger = DAC200FID40_FORM_UNKNOWN}, | |||
{"facing", t_uinteger, .addr.uinteger = &ais->type8.dac200fid40.facing, | |||
.dflt.uinteger = DAC200FID40_FACING_UNKNOWN}, | |||
{"direction", t_uinteger, .addr.uinteger = &ais->type8.dac200fid40.direction, | |||
.dflt.uinteger = DAC200FID40_DIRECTION_UNKNOWN}, | |||
{"direction_text", t_ignore}, | |||
{"status", t_uinteger, .addr.uinteger = &ais->type8.dac200fid40.status, | |||
.dflt.uinteger = DAC200FID40_STATUS_UNKNOWN}, | |||
{"status_text", t_ignore}, | |||
{NULL} | |||
}; | |||
const struct json_attr_t json_ais9[] = { | |||
AIS_HEADER | |||
{"alt", t_uinteger, .addr.uinteger = &ais->type9.alt, | |||
@@ -815,6 +989,7 @@ | |||
.len = sizeof(ais->type19.shipname)}, | |||
{"shiptype", t_uinteger, .addr.uinteger = &ais->type19.shiptype, | |||
.dflt.uinteger = 0}, | |||
{"shiptype_text", t_ignore}, | |||
{"to_bow", t_uinteger, .addr.uinteger = &ais->type19.to_bow, | |||
.dflt.uinteger = 0}, | |||
{"to_stern", t_uinteger, .addr.uinteger = &ais->type19.to_stern, | |||
@@ -825,6 +1000,7 @@ | |||
.dflt.uinteger = 0}, | |||
{"epfd", t_uinteger, .addr.uinteger = &ais->type19.epfd, | |||
.dflt.uinteger = 0}, | |||
{"epfd_text", t_ignore}, | |||
{"raim", t_boolean, .addr.boolean = &ais->type19.raim, | |||
.dflt.boolean = false}, | |||
{"dte", t_uinteger, .addr.uinteger = &ais->type19.dte, | |||
@@ -875,6 +1051,7 @@ | |||
AIS_HEADER | |||
{"aid_type", t_uinteger, .addr.uinteger = &ais->type21.aid_type, | |||
.dflt.uinteger = 0}, | |||
{"aid_type_text", t_ignore}, | |||
{"name", t_string, .addr.string = ais->type21.name, | |||
.len = sizeof(ais->type21.name)}, | |||
{"accuracy", t_boolean, .addr.boolean = &ais->type21.accuracy, | |||
@@ -893,6 +1070,7 @@ | |||
.dflt.uinteger = 0}, | |||
{"epfd", t_uinteger, .addr.uinteger = &ais->type21.epfd, | |||
.dflt.uinteger = 0}, | |||
{"epfd_text", t_ignore}, | |||
{"second", t_uinteger, .addr.uinteger = &ais->type21.second, | |||
.dflt.uinteger = 0}, | |||
{"regional", t_uinteger, .addr.uinteger = &ais->type21.regional, | |||
@@ -951,8 +1129,10 @@ | |||
.dflt.integer = AIS_GNS_LAT_NOT_AVAILABLE}, | |||
{"stationtype", t_uinteger, .addr.uinteger = &ais->type23.stationtype, | |||
.dflt.uinteger = 0}, | |||
{"stationtype_text", t_ignore}, | |||
{"shiptype", t_uinteger, .addr.uinteger = &ais->type23.shiptype, | |||
.dflt.uinteger = 0}, | |||
{"shiptype_text", t_ignore}, | |||
{"txrx", t_uinteger, .addr.uinteger = &ais->type23.txrx, | |||
.dflt.uinteger = 0}, | |||
{"interval", t_uinteger, .addr.uinteger = &ais->type23.interval, | |||
@@ -968,8 +1148,13 @@ | |||
.len = sizeof(ais->type24.shipname)}, | |||
{"shiptype", t_uinteger, .addr.uinteger = &ais->type24.shiptype, | |||
.dflt.uinteger = 0}, | |||
{"shiptype_text", t_ignore}, | |||
{"vendorid", t_string, .addr.string = ais->type24.vendorid, | |||
.len = sizeof(ais->type24.vendorid)}, | |||
{"model", t_uinteger, .addr.uinteger = &ais->type24.model, | |||
.dflt.uinteger = 0}, | |||
{"serial", t_uinteger, .addr.uinteger = &ais->type24.serial, | |||
.dflt.uinteger = 0}, | |||
{"callsign", t_string, .addr.string = ais->type24.callsign, | |||
.len = sizeof(ais->type24.callsign)}, | |||
{"mothership_mmsi",t_uinteger, .addr.uinteger = &ais->type24.mothership_mmsi, | |||
@@ -115,19 +115,28 @@ double getbed64(const char *buf, int off) | |||
return l_d.d; | |||
} | |||
/*@-shiftimplementation@*/ | |||
void putbef32(char *buf, int off, float val) | |||
{ | |||
union int_float i_f; | |||
i_f.f = val; | |||
/* this would be a putbe32 call if not for a signedness issue */ | |||
buf[off] = (char)(((i_f.i) >> 16) >> 8); | |||
/*@-shiftimplementation +ignoresigns@*/ | |||
putbe32(buf, off, i_f.i); | |||
/*@+shiftimplementation -ignoresigns@*/ | |||
} | |||
/*@+shiftimplementation@*/ | |||
#ifdef __UNUSED__ | |||
// cppcheck-suppress unusedFunction | |||
void putbed64(char *buf, int off, double val) | |||
{ | |||
union long_double l_d; | |||
l_d.d = val; | |||
/*@-shiftimplementation +ignoresigns@*/ | |||
putbe32(buf, (off), (l_d.l) >> 32); | |||
putbe32(buf, (off)+4, (l_d.l)); | |||
/*@+shiftimplementation -ignoresigns@*/ | |||
} | |||
u_int16_t swap_u16(u_int16_t i) | |||
/* byte-swap a 16-bit unsigned int */ | |||
{ | |||
@@ -139,7 +148,6 @@ u_int16_t swap_u16(u_int16_t i) | |||
return (c1 << 8) + c2; | |||
} | |||
// cppcheck-suppress unusedFunction | |||
u_int32_t swap_u32(u_int32_t i) | |||
/* byte-swap a 32-bit unsigned int */ | |||
{ | |||
@@ -153,7 +161,6 @@ u_int32_t swap_u32(u_int32_t i) | |||
return ((u_int32_t)c1 << 24) + ((u_int32_t)c2 << 16) + ((u_int32_t)c3 << 8) + c4; | |||
} | |||
// cppcheck-suppress unusedFunction | |||
u_int64_t swap_u64(u_int64_t i) | |||
/* byte-swap a 64-bit unsigned int */ | |||
{ | |||
@@ -48,6 +48,7 @@ extern double getbed64(const char *, int); | |||
#define putbe32(buf,off,l) do {putbe16(buf, (off), (l) >> 16); putbe16(buf, (off)+2, (l));} while (0) | |||
extern void putbef32(char *, int, float); | |||
extern void putbed64(char *, int, double); | |||
/* bitfield extraction */ | |||
extern uint64_t ubits(unsigned char buf[], unsigned int, unsigned int, bool); | |||
@@ -130,7 +130,6 @@ b64_ntop(unsigned char const *src, size_t srclength, char *target, | |||
size_t datalength = 0; | |||
unsigned char input[3]; | |||
unsigned char output[4]; | |||
size_t i; | |||
while (2 < srclength) { | |||
input[0] = *src++; | |||
@@ -157,6 +156,7 @@ b64_ntop(unsigned char const *src, size_t srclength, char *target, | |||
/* Now we worry about padding. */ | |||
if (0 != srclength) { | |||
size_t i; | |||
/* Get what's left. */ | |||
input[0] = input[1] = input[2] = '\0'; | |||
for (i = 0; i < srclength; i++) | |||
@@ -185,6 +185,7 @@ b64_ntop(unsigned char const *src, size_t srclength, char *target, | |||
return (datalength); | |||
} | |||
#ifdef __UNUSED__ | |||
/*@ -matchanyintegral +type @*/ | |||
/* skips all whitespace anywhere. | |||
@@ -311,5 +312,6 @@ int b64_pton(char const *src, unsigned char *target, size_t targsize) | |||
} | |||
/*@ +matchanyintegral -charint @*/ | |||
#endif /* __UNUSED__ */ | |||
#endif /* !defined(HAVE_B64_NTOP) && !defined(HAVE___B64_NTOP) */ |
@@ -1,7 +1,9 @@ | |||
= Building GPSD from source == | |||
This is a guide to building GPSD from a bare source tree. It includes | |||
guidance on how to cross-build the package. | |||
guidance on how to cross-build the package. | |||
Some hints for people building binary packages are in packaging/readme.txt. | |||
(This file is marked up in asciidoc.) | |||
@@ -10,7 +12,7 @@ guidance on how to cross-build the package. | |||
Under Linux, assuming you have all your build prerequisites in place, | |||
this line will do: | |||
scons && scons testregress && sudo scons udev-install | |||
scons && scons check && sudo scons udev-install | |||
If you get any errors, you need to read the detailed instructions that follow. | |||
@@ -18,26 +20,29 @@ If you get any errors, you need to read the detailed instructions that follow. | |||
Necessary components for any build: | |||
|============================================================================== | |||
|============================================================================ | |||
|C compiler | gpsd and client library are written in C | |||
|Python | some code is generated from python scripts | |||
|scons | for executing the build recipe | |||
|chrpath | needed with scons for RPATH setting | |||
|============================================================================== | |||
|============================================================================ | |||
=== C compiler === | |||
C99 conformance is required in the compiler. The C code depends on one | |||
non-C99 feature: anonymous unions. We could eliminate these, but the | |||
cost would be source-level interface breakage if we have to move | |||
structure members in and out of unions. | |||
non-C99 feature (supported by GCC, clang, and pretty much any C | |||
compiler that also speaks C++): anonymous unions. We could eliminate | |||
these, but the cost would be source-level interface breakage if we | |||
have to move structure members in and out of unions. | |||
GPSD is normally built and tested with GCC. The shared-memory | |||
interface relies on one GCCism, but the code is otherwise pretty | |||
compiler-agnostic. It is reported that clang produces a gpsd that | |||
passes all regression tests. If -Wmissing-field-initializers or | |||
its non-gcc equivalent is set you will get a lot of warnings; | |||
this is due to generated code and cannot be fixed. | |||
GPSD is normally built and tested with GCC. If the option | |||
-Wmissing-field-initializers or its non-gcc equivalent is set you will | |||
get a lot of warnings; this is due to generated code and cannot be | |||
fixed. | |||
The shared-memory interface relies on one GCCism, but the code is | |||
otherwise pretty compiler-agnostic. It is reported that clang | |||
produces a gpsd that passes all regression tests. | |||
Older versions of gcc don't recognize Wno-missing-field-initializers; | |||
this has been reported from GCC 3.4.6. We don't recommend building | |||
@@ -60,6 +65,13 @@ extensions. Usually these are called "python" and "python-dev". You | |||
will know you are missing the latter if your compilation fails | |||
because of a missing Python.h. | |||
The xgps test client requires the following Python extensions: | |||
|============================================================================ | |||
|gobject | GNOME object introspection library | |||
|pygtk | Python bindings for GTK | |||
|=========================================================================== | |||
=== Scons === | |||
You will need scons version 2.0.1 or later to build the code. The | |||
@@ -111,6 +123,7 @@ various additional capabilities and extensions: | |||
|C++ compiler | allows building libgpsmm C++ wrapper for client library | |||
|Qt 4.53+ | allows building libQgpsmm C++ wrapper for client library | |||
|libcap | Capabilities library, allows 1PPS support under Linux | |||
|curses | curses screen-painting library, allows building cgps | |||
|============================================================================ | |||
If you have libusb-1.0.0 or later, the GPSD build will autodetect | |||
@@ -129,14 +142,19 @@ For working with DBUS, you'll need the DBUS development | |||
headers and libraries installed. Under Debian/Ubuntu these | |||
are the packages libdbus-1-dev and libdbus-glib-1-dev. | |||
Under Ubuntu, the ncurses package you want is libncurses5-dev. | |||
Depending on how your distribution packages ncurses you may | |||
also require libtinfo5, a separate terminfo library. | |||
Under Ubuntu, the ncurses package you want is libncurses5-dev. Under | |||
Fedora, it's ncurses-devel. Depending on how your distribution | |||
packages ncurses you may also require libtinfo5, a separate terminfo | |||
library. | |||
On some recent versions of Ubuntu (notably 11.10) there is a packaging | |||
defect that may cause your build to blow up in SCons. It's a missing | |||
package info file for the tinfo library. To fix this, install the file | |||
packaging/tinfo.pc in /usr/lib/pkgconfig/tinfo.pc. | |||
packaging/tinfo.pc in /usr/lib/pkgconfig/tinfo.pc. 13.10 fixed this. | |||
We've seen a report that compiling on the Raspberry Pi fails with | |||
a complaint about curses.h not being found. You need to install | |||
Raspbian's curses development library if this happens. | |||
For building from the source tree, or if you change the man page | |||
source, xslt and docbook xsl style files are used to generate nroff | |||
@@ -147,6 +165,7 @@ process: | |||
|libxslt | xsltproc is used to build man pages from xml | |||
|docbook-xsl | style file for xml to man translation | |||
|xmlto | DocBook formatter program | |||
|asciidoc | DocBook front end with lighter markup | |||
|============================================================================ | |||
The build degrades gracefully in the absence of any of these. You should | |||
@@ -167,7 +186,7 @@ will need some subset of the following modules: | |||
|cdc_am | USB Communication Device Class Abstract Control Model interface | |||
|============================================================================ | |||
These are listed in rough order of devices covered as of 2011; the | |||
These are listed in rough order of devices covered as of 2013; the | |||
PL23203 by itself accounts for over 70% of deployed USB mice. We | |||
recommend building with pl2303, ftdi_sio, cypress_m8, and cp210x. | |||
@@ -217,10 +236,10 @@ won't try building the documentation. The actual fix is to install | |||
DocBook on your machine so there will be a local copy of the | |||
stylesheet where xmlto can find it. | |||
After building, please run 'scons testregress' to test the correctness | |||
After building, please run 'scons check' to test the correctness | |||
of the build. It is not necessary to install first, but you do need | |||
to have "." in your $PATH to run regressions uninstalled. Python is | |||
required for regression tests. If any of the tests fail, you probavly | |||
required for regression tests. If any of the tests fail, you probably | |||
have a toolchain issue. The most common such problem is issues with | |||
strict C99 conformance in floating-point libraries. | |||
@@ -239,6 +258,39 @@ included with the distribution. To install it, copy the file | |||
'gpsd.php' to your HTML document directory. Then see the | |||
post-installation instructions in INSTALL for how to configure it. | |||
== The leapseconds cache == | |||
Early in your build, the recipe will try to go over the Internet to | |||
one of several sources of current data on the leap-second offset in | |||
order to ensure that the file leapseconds.cache is up to date. This, | |||
in turn, is used to build a timebase.h include file. | |||
This procedure may fail if you are building inside an intranet that | |||
requires an authenticating web proxy. If that occurs, it will time | |||
out with a warning and a suggestion to use the leapfetch=no build | |||
option. | |||
Building with leapfetch=no may, in unusual circumstances, result in | |||
reported GPS time being off by a second or more. The circumstances | |||
are: | |||
1. It has been less than 20 minutes since power-up; the GPS has | |||
not yet received the current leapsecond offset as part of the | |||
periodic ephemeris download. | |||
2. One or more leap-second offset increments have been issued between | |||
when your GPSD source tree was cloned from the repository (or | |||
leapsecond.cache was later updated) and now. Leap-second | |||
increments, compensating for minute and unpredictable changes in | |||
the Earth's rotation, are occasionally issued by international time | |||
authorities. | |||
Note that the same failure can occur with any GPSD installation. But | |||
by refreshing leapseconds.cache you reduce the error window for | |||
leap-second offset bumps to affect your installation so that it begins | |||
as late as possible, at your build time rather than from when the | |||
source tree was copied. | |||
== Optional features == | |||
By giving command-line options to scons you can configure certain rarely-used | |||
@@ -266,17 +318,29 @@ status of Qt supported platforms as of version 4.6. | |||
== Port and toolchain testing == | |||
'scons testregress' will run a comprehensive regression-test suite. | |||
You should do this, at minimum, every time you build from source | |||
on a new machine type. GPSD does enough bit-twiddling and floating | |||
point that it is very sensitive to toolchain problems; you'll want to | |||
be sure those aren't going to bite you in production. | |||
'scons check' will run a comprehensive regression-test suite. You | |||
should do this, at minimum, every time you build from source on a new | |||
machine type. GPSD does enough bit-twiddling and floating point that | |||
it is very sensitive to toolchain problems; you'll want to be sure | |||
those aren't going to bite you in production. | |||
So the tests will run fast and be easy to do often, we make the test | |||
framework shove data through the pty and socket layers *way* faster | |||
than would ever occur in production. If you get regression-test | |||
failures that aren't repeatable and look like the test framework is | |||
sporadically failing to feed the last line or two of test loads, try | |||
increasing the delay constants in fake.py. If you have to do this, | |||
please report your experience to the GPSD maintainers. | |||
For instructions on how to live-test the software, see the file INSTALL. | |||
== Reverting to a clean state == | |||
The scons equivalent of 'make clean' is 'scons -c'. This will revert | |||
your source tree to a clean state as though you had just cloned or | |||
downloaded it. | |||
your source tree to a clean state nearly as though you had just cloned or | |||
downloaded it; some scons housekeeping stuff is left in place. If you | |||
interrupted a regression test, 'distclean' will remove generated test | |||
programs. | |||
== Cross-building == | |||
@@ -351,6 +415,8 @@ When you are cross-compiling, you'll need chrpath at version 0.14 or | |||
later for cross-architecture support. If it's not yet packaged for | |||
your environment, see http://alioth.debian.org/projects/chrpath/ | |||
You may also find it useful to set manbuild=no. | |||
== Autostarting the daemon == | |||
The preferred way to start gpsd is on-demand by a hotplug script | |||
@@ -363,3 +429,5 @@ If you for some reason need to start gpsd unconditionally at | |||
boot time (in particular, if you need to support RS232 devices) | |||
there's a model init.d script under packaging/deb and a systemd | |||
setup under systemd/. | |||
// end |
@@ -96,6 +96,7 @@ | |||
#ifndef S_SPLINT_S | |||
#include <unistd.h> | |||
#endif /* S_SPLINT_S */ | |||
#include <ctype.h> | |||
#include "gpsd_config.h" | |||
#include "gps.h" | |||
@@ -410,7 +411,7 @@ static void update_compass_panel(struct gps_data_t *gpsdata) | |||
static void update_gps_panel(struct gps_data_t *gpsdata) | |||
/* This gets called once for each new GPS sentence. */ | |||
{ | |||
int i, j, n; | |||
int i, j; | |||
int newstate; | |||
char scr[128], *s; | |||
bool usedflags[MAXCHANNELS]; | |||
@@ -444,7 +445,7 @@ static void update_gps_panel(struct gps_data_t *gpsdata) | |||
SATELLITES_WIDTH - 3, scr); | |||
} | |||
} else { | |||
n = 0; | |||
int n = 0; | |||
for (i = 0; i < MAX_POSSIBLE_SATS; i++) { | |||
if (n < display_sats) { | |||
if ((i < gpsdata->satellites_visible) | |||
@@ -639,9 +640,14 @@ static void update_gps_panel(struct gps_data_t *gpsdata) | |||
} | |||
/* Be quiet if the user requests silence. */ | |||
/*@-modobserver@*/ | |||
if (!silent_flag && raw_flag && (s = (char *)gps_data(gpsdata)) != NULL) { | |||
(void)waddstr(messages, s); | |||
char *p; | |||
for (p = s + strlen(s); --p > s && isspace(*p); *p = '\0') | |||
; | |||
(void)wprintw(messages, "%s\n", s); | |||
} | |||
/*@+modobserver@*/ | |||
/* Reset the status_timer if the state has changed. */ | |||
if (newstate != state) { | |||
@@ -682,7 +688,6 @@ static void usage(char *prog) | |||
int main(int argc, char *argv[]) | |||
{ | |||
int option; | |||
int c; | |||
unsigned int flags = WATCH_ENABLE; | |||
/*@ -observertrans @*/ | |||
@@ -808,6 +813,8 @@ int main(int argc, char *argv[]) | |||
/* heart of the client */ | |||
for (;;) { | |||
int c; | |||
if (!gps_waiting(&gpsdata, 5000000)) { | |||
die(GPS_TIMEOUT); | |||
} else { | |||
@@ -41,3 +41,14 @@ display the satellite view properly. webgps.py can be called with the argument | |||
"c" to run continously, with an integer duration and a unit suffix to run this | |||
long (units allowed are "s", "m", "h" and "d", e.g. "4h"), or without argument | |||
to create a snapshot of the current sat view. | |||
ntpoffset generate an estimate of your GPS's offset from a peerstats | |||
file. For instructions on how to use this script, see the GPSD Time | |||
Service HOWTO in this distrubution. | |||
ppscheck watches a specified serial device for changes in handshake lines | |||
CD, RI, and CTS by running ioctl(...., TIOCMIWAIT, ...) in a loop. When it | |||
sees a state change it emits a timestamped line of output dumping the state | |||
of the handshake signals. It's useful for checking whether a device is | |||
emitting 1PPS. There is troubleshooting advice in the header comment. | |||
@@ -16,7 +16,7 @@ | |||
void spinner(int ); | |||
int main(int argc, char **argv) { | |||
int speed, n, l, ifd, ofd; | |||
int speed, n, ifd, ofd; | |||
struct termios term; | |||
char buf[BUFSIZ]; | |||
@@ -58,7 +58,7 @@ int main(int argc, char **argv) { | |||
tcflush(ifd, TCIOFLUSH); | |||
n = 0; | |||
while (1){ | |||
l = read(ifd, buf, BUFSIZ); | |||
int l = read(ifd, buf, BUFSIZ); | |||
if (l > 0) | |||
assert(write(ofd, buf, l) > 0); | |||
usleep(1000); | |||
@@ -1,5 +1,7 @@ | |||
/* This file is Copyright (c)2010 by the GPSD project | |||
* BSD terms apply: see the file COPYING in the distribution root for details. | |||
* | |||
* Stuff the contents of a specified file into a specified tty. | |||
*/ | |||
#include <sys/types.h> | |||
#include <sys/mman.h> | |||
@@ -28,7 +30,7 @@ int main( int argc, char **argv){ | |||
struct termios term; | |||
char *buf, tn[32]; | |||
int ifd, ofd, sfd; | |||
int dflag = 0, c, sleeptime, len, rate = 0, speed = 0; | |||
int dflag = 0, c, sleeptime, len, speed = 0; | |||
while((c = getopt(argc, argv, "d:r:s:")) != -1) { | |||
switch(c){ | |||
@@ -36,24 +38,6 @@ int main( int argc, char **argv){ | |||
dflag = 1; | |||
strncpy(tn, optarg, sizeof(tn)-1); | |||
break; | |||
case 'r': | |||
rate = atoi(optarg); | |||
switch (rate) { | |||
case 230400: | |||
case 115200: | |||
case 57600: | |||
case 38400: | |||
case 28800: | |||
case 19200: | |||
case 14400: | |||
case 9600: | |||
case 4800: | |||
break; | |||
default: | |||
fprintf(stderr, "invalid data rate: %d\n", rate); | |||
return 1; | |||
} | |||
break; | |||
case 's': | |||
speed = atoi(optarg); | |||
switch (speed) { | |||
@@ -82,16 +66,8 @@ int main( int argc, char **argv){ | |||
if (argc != 1) | |||
usage(); | |||
if (rate > speed){ | |||
printf("data rate cannot be higher than port speed.\n"); | |||
return 1; | |||
} | |||
if (0 == rate && 0 != speed) | |||
rate = speed; | |||
if (0 == rate && 0 == speed) | |||
rate = speed = 4800; | |||
if (0 == speed) | |||
speed = 4800; | |||
printf("opening %s\n", argv[0]); | |||
if ((ifd = open(argv[0], O_RDONLY, 0444)) == -1) | |||
@@ -165,6 +141,6 @@ void spinner(int n){ | |||
} | |||
void usage(void){ | |||
fprintf(stderr, "usage: binreplay [-d <device>] [-r <data_rate>] [-s <port_speed>] <file>\n"); | |||
fprintf(stderr, "usage: binreplay [-d <device>] [-s <port_speed>] <file>\n"); | |||
exit(1); | |||
} |
@@ -166,8 +166,9 @@ char *gpsd_hexdump(char *binbuf, size_t binbuflen) | |||
return hexbuf; | |||
} | |||
int gpsd_hexpack(char *src, char *dst, int len){ | |||
int i, k, l; | |||
int gpsd_hexpack(char *src, char *dst, int len) | |||
{ | |||
int i, l; | |||
l = (int)(strlen(src) / 2); | |||
if ((l < 1) || (l > len)) | |||
@@ -175,7 +176,7 @@ int gpsd_hexpack(char *src, char *dst, int len){ | |||
bzero(dst, len); | |||
for (i = 0; i < l; i++) | |||
if ((k = hex2bin(src+i*2)) != -1) | |||
if (hex2bin(src+i*2) != -1) | |||
dst[i] = (char)(k & 0xff); | |||
else | |||
return -1; | |||
@@ -0,0 +1,10 @@ | |||
#!/bin/sh | |||
# | |||
# Generate an estimate of your GPS's offset from a peerstats file | |||
# For instructions on how to use this script, see the GPSD Time | |||
# Service HOWTO in this distrubution. | |||
# | |||
awk ' | |||
/127\.127\.28\.0/ { sum += $5 * 1000; cnt++; } | |||
END { print sum / cnt; } | |||
' </var/log/ntpstats/peerstats |
@@ -0,0 +1,98 @@ | |||
/* | |||
* Watch a specified serial port for transitions that might be 1PPS. | |||
* | |||
* Each output line is the second and nanosecond parts of a timestamp | |||
* followed by the names of handshake signals then asserted. Off | |||
* transitions may generate lines with no signals aserted. | |||
* | |||
* If you don't see output within a second, use gpsmon or some other | |||
* equivalent tool to check that your device has satellite lock and is | |||
* getting fixes before giving up on the possibility of 1PPS. | |||
* | |||
* Also, check your cable. Cheap DB9 to DB9 cables such as those | |||
* issued with UPSes often carry TXD/RXD/SG only, omitting handshake | |||
* lines such as DCD. Suspect this especially if the cable jacket | |||
* looks too skinny to hold more than three leads! | |||
* | |||
* This code requires only ANSI/POSIX. If it doesn't compile and run | |||
* on your Unix there is something very wrong with your Unix. | |||
* | |||
* This code by ESR, Copyright (C) 2013, under BSD terms. | |||
*/ | |||
#include <stdio.h> | |||
#include <string.h> | |||
#include <sys/types.h> | |||
#include <sys/stat.h> | |||
#ifndef S_SPLINT_S | |||
#include <unistd.h> | |||
#endif /* S_SPLINT_S */ | |||
#include <fcntl.h> /* needed for open() and friends */ | |||
#include <sys/ioctl.h> | |||
#include <errno.h> | |||
#include <time.h> | |||
struct assoc { | |||
int mask; | |||
char *string; | |||
}; | |||
/* | |||
* Possible pins for PPS: DCD, CTS, RTS, RI, DSR. Pinouts: | |||
* | |||
* DB9 DB25 Name Full name | |||
* --- ---- ---- -------------------- | |||
* 3 2 TXD --> Transmit Data | |||
* 2 3 RXD <-- Receive Data | |||
* 7 4 RTS --> Request To Send | |||
* 8 5 CTS <-- Clear To Send | |||
* 6 6 DSR <-- Data Set Ready | |||
* 4 20 DTR --> Data Terminal Ready | |||
* 1 8 DCD <-- Data Carrier Detect | |||
* 9 22 RI <-- Ring Indicator | |||
* 5 7 GND Signal ground | |||
*/ | |||
const static struct assoc hlines[] = { | |||
{TIOCM_CD, "TIOCM_CD"}, | |||
{TIOCM_RI, "TIOCM_RI"}, | |||
{TIOCM_DSR, "TIOCM_DSR"}, | |||
{TIOCM_CTS, "TIOCM_CTS"}, | |||
}; | |||
int main(int argc, char *argv[]) | |||
{ | |||
struct timespec ts; | |||
int fd = open(argv[1], O_RDONLY); | |||
if (fd == -1) { | |||
(void)fprintf(stderr, | |||
"open(%s) failed: %d %.40s\n", | |||
argv[1], errno, strerror(errno)); | |||
return 1; | |||
} | |||
for (;;) { | |||
if (ioctl(fd, TIOCMIWAIT, TIOCM_CD|TIOCM_DSR|TIOCM_CAR|TIOCM_RI|TIOCM_CTS) != 0) { | |||
(void)fprintf(stderr, | |||
"PPS ioctl(TIOCMIWAIT) failed: %d %.40s\n", | |||
errno, strerror(errno)); | |||
break; | |||
} else { | |||
const struct assoc *sp; | |||
int handshakes; | |||
(void)clock_gettime(CLOCK_REALTIME, &ts); | |||
(void)ioctl(fd, TIOCMGET, &handshakes); | |||
(void)fprintf(stdout, "%10ld %10ld", ts.tv_sec, ts.tv_nsec); | |||
for (sp = hlines; | |||
sp < hlines + sizeof(hlines)/sizeof(hlines[0]); | |||
sp++) | |||
if ((handshakes & sp->mask) != 0) { | |||
(void)fputc(' ', stdout); | |||
(void)fputs(sp->string, stdout); | |||
} | |||
(void)fputc('\n', stdout); | |||
} | |||
} | |||
} | |||
/* end */ |
@@ -1,14 +1,47 @@ | |||
#!/usr/bin/env python | |||
# encoding: utf-8 | |||
# webgps.py | |||
# | |||
# This is a Python port of webgps.c from http://www.wireless.org.au/~jhecker/gpsd/ | |||
# by Beat Bolli <me+gps@drbeat.li> | |||
# | |||
"""webgps.py | |||
This is a Python port of webgps.c from http://www.wireless.org.au/~jhecker/gpsd/ | |||
by Beat Bolli <me+gps@drbeat.li> | |||
It creates a skyview of the currently visible GPS satellites and their tracks | |||
over a time period. | |||
Usage: | |||
./webgps.py [duration] | |||
duration may be | |||
- a number of seconds | |||
- a number followed by a time unit ('s' for secinds, 'm' for minutes, | |||
'h' for hours or 'd' for days, e.g. '4h' for a duration of four hours) | |||
- the letter 'c' for continuous operation | |||
If duration is missing, the current skyview is generated and webgps.py exits | |||
immediately. This is the same as giving a duration of 0. | |||
If a duration is given, webgps.py runs for this duration and generates the | |||
tracks of the GPS satellites in view. If the duration is the letter 'c', | |||
the script never exits and continuously updates the skyview. | |||
webgps.py generates two files: a HTML5 file that can be browsed, and a | |||
JavaScript file that contains the drawing commands for the skyview. The HTML5 | |||
file auto-refreshes every five minutes. The generated file names are | |||
"gpsd-<duration>.html" and "gpsd-<duration>.js". | |||
If webgps.py is interrupted with Ctrl-C before the duration is over, it saves | |||
the current tracks into the file "tracks.p". This is a Python "pickle" file. | |||
If this file is present on start of webgps.py, it is loaded. This allows to | |||
restart webgps.py without losing accumulated satellite tracks. | |||
""" | |||
import time, calendar, math, socket, sys, os, select, pickle | |||
from gps import * | |||
try: | |||
from gps import * | |||
except ImportError: | |||
sys.path.append('..') | |||
from gps import * | |||
TRACKMAX = 1024 | |||
STALECOUNT = 10 | |||
@@ -42,6 +75,10 @@ class Track: | |||
return 1 | |||
return 0 | |||
def track(self): | |||
'''Return the track as canvas drawing operations.''' | |||
return 'M(%d,%d); ' % self.posn[0] + ''.join(['L(%d,%d); ' % p for p in self.posn[1:]]) | |||
class SatTracks(gps): | |||
'''gpsd client writing HTML5 and <canvas> output.''' | |||
@@ -192,17 +229,11 @@ function draw_satview() { | |||
ctx.strokeStyle = 'red'; | |||
"""); | |||
def M(p): | |||
return 'M(%d,%d); ' % p | |||
def L(p): | |||
return 'L(%d,%d); ' % p | |||
# Draw the tracks | |||
for t in self.sattrack.values(): | |||
if t.posn: | |||
fh.write(" ctx.globalAlpha = %s; ctx.beginPath(); %s%sctx.stroke();\n" % ( | |||
t.stale == 0 and '0.66' or '1', M(t.posn[0]), | |||
''.join([L(p) for p in t.posn[1:]]) | |||
fh.write(" ctx.globalAlpha = %s; ctx.beginPath(); %sctx.stroke();\n" % ( | |||
t.stale == 0 and '0.66' or '1', t.track() | |||
)) | |||
fh.write(""" | |||
@@ -250,14 +281,14 @@ function draw_satview() { | |||
t = self.sattrack[prn] | |||
except KeyError: | |||
self.sattrack[prn] = t = Track(prn) | |||
self.needsupdate += t.add(x, y) | |||
if t.add(x, y): | |||
self.needsupdate = 1 | |||
def update_tracks(self): | |||
self.make_stale() | |||
for s in self.satellites: | |||
x, y = polartocart(s.elevation, s.azimuth) | |||
if self.insert_sat(s.PRN, x, y): | |||
self.needsupdate = 1 | |||
self.insert_sat(s.PRN, x, y) | |||
self.delete_stale() | |||
def generate_html(self, htmlfile, jsfile): | |||
@@ -273,7 +304,8 @@ function draw_satview() { | |||
def run(self, suffix, period): | |||
jsfile = 'gpsd' + suffix + '.js' | |||
htmlfile = 'gpsd' + suffix + '.html' | |||
end = time.time() + period | |||
if period is not None: | |||
end = time.time() + period | |||
self.needsupdate = 1 | |||
self.stream(WATCH_ENABLE | WATCH_NEWSTYLE) | |||
for report in self: | |||
@@ -284,8 +316,10 @@ function draw_satview() { | |||
self.generate_js(jsfile) | |||
self.needsupdate = 0 | |||
self.generate_html(htmlfile, jsfile) | |||
if period <= 0 and self.fix.mode >= MODE_2D \ | |||
or period > 0 and time.time() > end: | |||
if period is not None and ( | |||
period <= 0 and self.fix.mode >= MODE_2D or | |||
period > 0 and time.time() > end | |||
): | |||
break | |||
def main(): | |||
@@ -294,17 +328,14 @@ def main(): | |||
factors = { | |||
's': 1, 'm': 60, 'h': 60 * 60, 'd': 24 * 60 * 60 | |||
} | |||
arg = argv and argv[0] or '' | |||
arg = argv and argv[0] or '0' | |||
if arg[-1:] in factors.keys(): | |||
period = int(arg[:-1]) * factors[arg[-1]] | |||
elif arg == 'c': | |||
period = None | |||
elif arg: | |||
period = int(arg) | |||
period = None | |||
else: | |||
period = 0 | |||
if arg: | |||
arg = '-' + arg | |||
period = int(arg) | |||
prefix = '-' + arg | |||
sat = SatTracks() | |||
@@ -316,7 +347,7 @@ def main(): | |||
p.close() | |||
try: | |||
sat.run(arg, period) | |||
sat.run(prefix, period) | |||
except KeyboardInterrupt: | |||
# save the tracks | |||
p = open(pfile, 'w') | |||
@@ -3,7 +3,7 @@ | |||
Package: gpsd | |||
Description: monitoring daemon for GPSes, AIS radios, and other navigation aids | |||
Description: A monitoring daemon for GPSes, AIS radios, and other nav sensors. | |||
gpsd is a userland daemon acting as a translator between GPS and | |||
AIS receivers and their clients. gpsd listens on port 2947 for clients | |||
requesting position/time/velocity information. The receivers are | |||
@@ -159,6 +159,7 @@ unsigned crc24q_hash(unsigned char *data, int len) | |||
#define MID(x) (unsigned char)(((x) >> 8) & 0xff) | |||
#define HI(x) (unsigned char)(((x) >> 16) & 0xff) | |||
#ifdef __UNUSED__ | |||
void crc24q_sign(unsigned char *data, int len) | |||
{ | |||
unsigned crc = crc24q_hash(data, len); | |||
@@ -167,6 +168,7 @@ void crc24q_sign(unsigned char *data, int len) | |||
data[len + 1] = MID(crc); | |||
data[len + 2] = LO(crc); | |||
} | |||
#endif /* __UNUSED__ */ | |||
bool crc24q_check(unsigned char *data, int len) | |||
{ | |||
@@ -1237,7 +1237,12 @@ if __name__ == "__main__": | |||
sys.stdout.write(raw) | |||
if not bogon: | |||
if json: | |||
print "{" + ",".join(map(lambda x: '"' + x[0].name + '":' + str(x[1]), parsed)) + "}" | |||
def quotify(x): | |||
if type(x) == type(""): | |||
return '"' + str(x) + '"' | |||
else: | |||
return str(x) | |||
print "{" + ",".join(map(lambda x: '"' + x[0].name + '":' + quotify(x[1]), parsed)) + "}" | |||
elif dsv: | |||
print "|".join(map(lambda x: str(x[1]), parsed)) | |||
elif histogram: | |||
@@ -2,7 +2,7 @@ | |||
# | |||
# striplog -- strip leading lines from logs | |||
# | |||
# striplog -1 strips the first line only. | |||
# striplog -j strips JSON leader sentences. | |||
# striplog with no option strips all leading lines beginning with # | |||
# | |||
# This file is Copyright (c) 2010 by the GPSD project | |||
@@ -10,19 +10,46 @@ | |||
# | |||
import getopt, sys | |||
firstline = False | |||
(options, argumwnts) = getopt.getopt(sys.argv[1:], "1") | |||
secondline = firstline = stripjson = False | |||
stripval = 0 | |||
(options, arguments) = getopt.getopt(sys.argv[1:], "12n:j") | |||
for (switch, val) in options: | |||
if (switch == '-1'): | |||
firstline = True | |||
if (switch == '-2'): | |||
secondline = True | |||
if (switch == '-n'): | |||
stripval = int(val) | |||
if (switch == '-j'): | |||
stripjson = True | |||
if firstline: | |||
sys.stdin.readline() | |||
else: | |||
while True: | |||
line = sys.stdin.readline() | |||
if line[0] != '#': | |||
break | |||
sys.stdout.write(line) | |||
try: | |||
if firstline: | |||
sys.stdin.readline() | |||
elif secondline: | |||
sys.stdin.readline() | |||
sys.stdin.readline() | |||
elif stripval: | |||
for _dummy in range(stripval): | |||
sys.stdin.readline() | |||
elif stripjson: | |||
while True: | |||
line = sys.stdin.readline() | |||
if line.startswith('{"class":"VERSION"') \ | |||
or line.startswith('{"class":"DEVICE"') \ | |||
or line.startswith('{"class":"DEVICES"') \ | |||
or line.startswith('{"class":"WATCH"'): | |||
continue | |||
else: | |||
break | |||
sys.stdout.write(line) | |||
else: | |||
while True: | |||
line = sys.stdin.readline() | |||
if line[0] != '#': | |||
break | |||
sys.stdout.write(line) | |||
sys.stdout.write(sys.stdin.read()) | |||
sys.stdout.write(sys.stdin.read()) | |||
except KeyboardInterrupt: | |||
pass |
@@ -6,10 +6,12 @@ | |||
# correct offsets in the tables themselves. | |||
# | |||
# Requires the AIVDM.txt file on standard input. Takes a single argument, | |||
# the line number of a table start. Things you can generate: | |||
# which must match a string in a //: Type comment. Things you can generate: | |||
# | |||
# * -t: A corrected version of the table. It will redo all the offsets to be | |||
# in conformance with the bit widths. | |||
# in conformance with the bit widths. (The other options rely only on the | |||
# bit widths). If the old and new tables are different, an error message | |||
# describing the corrections will be emitted to standard error. | |||
# | |||
# * -s: A structure definition capturing the message info, with member | |||
# names extracted from the table and types computed from it. | |||
@@ -26,8 +28,9 @@ | |||
# generate the specification structure for a JSON parse that reads JSON | |||
# into an instance of the message structure. | |||
# | |||
# * -a: Generate all of -s, -d, -c, and -r, , not to stdout but to | |||
# files named with the argument as a distinguishing part of the stem. | |||
# * -a: Generate all of -s, -d, -c, and -r, and -t, not to stdout but to | |||
# files named with 'tablegen' as a distinguishing part of the stem. | |||
# The stem name can be overridden with the -o option. | |||
# | |||
# This generates almost all the code required to support a new message type. | |||
# It's not quite "Look, ma, no handhacking!" You'll need to add default | |||
@@ -46,13 +49,21 @@ | |||
# of fields in the table. This may be useful for dealing with groups of | |||
# messages that have a common head section. | |||
# | |||
# This code interprets magic comments in the input | |||
# | |||
# //: Type | |||
# The token following "Type" is the name of the table | |||
# //: xxxx vocabulary | |||
# A subtable describing a controlled vocabulary for field xxxx in the | |||
# preceding table. | |||
# | |||
# TO-DO: generate code for ais.py. | |||
import sys, getopt | |||
def correct_table(wfp): | |||
# Writes the corrected table. | |||
print >>sys.stderr, "Total bits:", base | |||
print >>sys.stderr, "Total bits:", base | |||
for (i, t) in enumerate(table): | |||
if offsets[i].strip(): | |||
print >>wfp, "|" + offsets[i] + t[owidth+1:].rstrip() | |||
@@ -62,7 +73,8 @@ def correct_table(wfp): | |||
def make_driver_code(wfp): | |||
# Writes calls to bit-extraction macros. | |||
# Requires UBITS, SBITS, UCHARS to act as they do in the AIVDM driver. | |||
# Also relies on ais_context->bitlen to be the message bit length. | |||
# Also relies on bitlen to be the message bit length, and i to be | |||
# available as abn index variable. | |||
record = after is None | |||
arrayname = None | |||
base = '\t' | |||
@@ -92,16 +104,16 @@ def make_driver_code(wfp): | |||
print >>wfp, '#define ELEMENT_SIZE %s' % trailing | |||
if explicit: | |||
lengthfield = last | |||
print >>wfp, indent + "for (ind = 0; ind < %s; ind++) {" % lengthfield | |||
print >>wfp, indent + "for (i = 0; i < %s; i++) {" % lengthfield | |||
else: | |||
lengthfield = "n" + arrayname | |||
print >>wfp, indent + "for (ind = 0; ARRAY_BASE + (ELEMENT_SIZE*ind) <= ais_context->bitlen; ind++) {" | |||
print >>wfp, indent + "for (i = 0; ARRAY_BASE + (ELEMENT_SIZE*i) < bitlen; i++) {" | |||