diff options
author | Eric S. Raymond <esr@thyrsus.com> | 2011-05-29 11:18:07 -0400 |
---|---|---|
committer | Eric S. Raymond <esr@thyrsus.com> | 2011-05-29 11:18:07 -0400 |
commit | 2e070b48734a9e3795bd8f6eaa0afc99959eefd8 (patch) | |
tree | 7701f84cefb7f98b16ef359b4a0cd2c90fda2e08 | |
parent | dfd374545d5822d46380bf07463e0dd8040a9e42 (diff) | |
download | gpsd-2e070b48734a9e3795bd8f6eaa0afc99959eefd8.tar.gz |
In AIS, support for Route Info (addressed). All regression tests pass.
-rw-r--r-- | ais_json.c | 4 | ||||
-rw-r--r-- | driver_aivdm.c | 18 | ||||
-rw-r--r-- | gps.h | 18 | ||||
-rw-r--r-- | gpsd_json.c | 72 | ||||
-rw-r--r-- | jsongen.py.in | 21 |
5 files changed, 129 insertions, 4 deletions
@@ -179,6 +179,10 @@ int json_ais_read(const char *buf, status = json_read_object(buf, json_ais6_fid25, endptr); imo = true; } + else if (strstr(buf, "\"fid\":28,") != NULL) { + status = json_read_object(buf, json_ais6_fid28, endptr); + imo = true; + } else if (strstr(buf, "\"fid\":30,") != NULL) { status = json_read_object(buf, json_ais6_fid30, endptr); imo = true; diff --git a/driver_aivdm.c b/driver_aivdm.c index 30592663..a5bcdc2c 100644 --- a/driver_aivdm.c +++ b/driver_aivdm.c @@ -454,6 +454,24 @@ bool aivdm_decode(const char *buf, size_t buflen, ais->type6.dac1fid25.ncargos = i; break; case 28: /* IMO289 - Route info - addressed */ + ais->type6.dac1fid28.linkage = UBITS(88, 10); + ais->type6.dac1fid28.sender = UBITS(98, 3); + /* 5 bits of type e */ + ais->type6.dac1fid28.month = UBITS(106, 4); + ais->type6.dac1fid28.day = UBITS(110, 5); + ais->type6.dac1fid28.hour = UBITS(115, 5); + ais->type6.dac1fid28.minute = UBITS(120, 6); + ais->type6.dac1fid28.duration = UBITS(126, 18); + ais->type6.dac1fid28.waycount = UBITS(144, 5); +#define ARRAY_BASE 149 +#define ELEMENT_SIZE 55 + for (i = 0; i < ais->type6.dac1fid28.waycount; i++) { + int a = ARRAY_BASE + (ELEMENT_SIZE*i); + ais->type6.dac1fid28.waypoints[i].lon = SBITS(a+0, 28); + ais->type6.dac1fid28.waypoints[i].lat = SBITS(a+28,27); + } +#undef ARRAY_BASE +#undef ELEMENT_SIZE break; case 30: /* IMO289 - Text description - addressed */ ais->type6.dac1fid30.linkage = UBITS(88, 10); @@ -1027,13 +1027,29 @@ struct ais_t unsigned int subtype; /* Cargo subtype */ } cargos[28]; } dac1fid25; + /* IMO289 - Route info (addressed) */ + struct { + unsigned int linkage; /* Message Linkage ID */ + unsigned int sender; /* Sender Class */ + unsigned int rtype; /* Route Type */ + unsigned int month; /* Start month (UTC) */ + unsigned int day; /* Start day (UTC) */ + unsigned int hour; /* Start hour (UTC) */ + unsigned int minute; /* Start minute (UTC) */ + unsigned int duration; /* Duration */ + int waycount; /* */ + struct waypoint_t { + signed int lon; /* Longitude */ + signed int lat; /* Latitude */ + } waypoints[16]; + } dac1fid28; /* IMO289 - Text message (addressed) */ struct { unsigned int linkage; #define AIS_DAC1FID30_TEXT_MAX 154 /* 920 bits of six-bit, plus NUL */ char text[AIS_DAC1FID30_TEXT_MAX]; } dac1fid30; - /* IMO289 - Tidal Window */ + /* IMO289 & IMO236 - Tidal Window */ struct { unsigned int type; /* Message Type */ unsigned int repeat; /* Repeat Indicator */ diff --git a/gpsd_json.c b/gpsd_json.c index 6a960f51..340d3e86 100644 --- a/gpsd_json.c +++ b/gpsd_json.c @@ -1482,7 +1482,7 @@ void json_aivdm_dump(const struct ais_t *ais, #define SHIPTYPE_DISPLAY(n) (((n) < (unsigned int)NITEMS(ship_type_legends)) ? ship_type_legends[n] : "INVALID SHIP TYPE") - static char *station_type_legends[16] = { + static const char *station_type_legends[16] = { "All types of mobiles", "Reserved for future use", "All types of Class B mobile stations", @@ -1503,7 +1503,7 @@ void json_aivdm_dump(const struct ais_t *ais, #define STATIONTYPE_DISPLAY(n) (((n) < (unsigned int)NITEMS(ship_type_legends)) ? station_type_legends[n] : "INVALID STATION TYPE") - static char *navaid_type_legends[] = { + static const char *navaid_type_legends[] = { "Unspecified", "Reference point", "RACON", @@ -1540,7 +1540,7 @@ void json_aivdm_dump(const struct ais_t *ais, #define NAVAIDTYPE_DISPLAY(n) (((n) < (unsigned int)NITEMS(navaid_type_legends[0])) ? navaid_type_legends[n] : "INVALID NAVAID TYPE") - static char *signal_legends[] = { + static const char *signal_legends[] = { "N/A", "Serious emergency – stop or divert according to instructions.", "Vessels shall not proceed.", @@ -1560,6 +1560,40 @@ void json_aivdm_dump(const struct ais_t *ais, #define SIGNAL_DISPLAY(n) (((n) < (unsigned int)NITEMS(signal_legends[0])) ? signal_legends[n] : "INVALID SIGNAL TYPE") + static const char *route_type[32] = { + "Undefined (default)", + "Mandatory", + "Recommended", + "Alternative", + "Recommended route through ice", + "Ship route plan", + "Reserved for future use.", + "Reserved for future use.", + "Reserved for future use.", + "Reserved for future use.", + "Reserved for future use.", + "Reserved for future use.", + "Reserved for future use.", + "Reserved for future use.", + "Reserved for future use.", + "Reserved for future use.", + "Reserved for future use.", + "Reserved for future use.", + "Reserved for future use.", + "Reserved for future use.", + "Reserved for future use.", + "Reserved for future use.", + "Reserved for future use.", + "Reserved for future use.", + "Reserved for future use.", + "Reserved for future use.", + "Reserved for future use.", + "Reserved for future use.", + "Reserved for future use.", + "Reserved for future use.", + "Reserved for future use.", + "Cancel route identified by message linkage", + }; (void)snprintf(buf, buflen, "{\"class\":\"AIS\","); if (device != NULL && device[0] != '\0') @@ -1884,6 +1918,38 @@ void json_aivdm_dump(const struct ais_t *ais, (void)strlcat(buf, "]}\r\n,", buflen - strlen(buf)); break; case 28: /* IMO289 - Route info - addressed */ + (void)snprintf(buf + strlen(buf), buflen - strlen(buf), + "\"linkage\":%u,\"sender\":%u", + ais->type6.dac1fid28.linkage, + ais->type6.dac1fid28.sender); + if (scaled) + (void)snprintf(buf + strlen(buf), buflen - strlen(buf), + "\"rtype\":\"%s\"", + route_type[ais->type6.dac1fid28.rtype]); + else + (void)snprintf(buf + strlen(buf), buflen - strlen(buf), + "\"rtype\":%u", + ais->type6.dac1fid28.rtype); + (void)snprintf(buf + strlen(buf), buflen - strlen(buf), + "\"month\":%u,\"day\":%u,\"hour\":%u,\"minute\":%u,\"duration\":%u,\"waycount\":%u", + ais->type6.dac1fid28.month, + ais->type6.dac1fid28.day, + ais->type6.dac1fid28.hour, + ais->type6.dac1fid28.minute, + ais->type6.dac1fid28.duration, + ais->type6.dac1fid28.waycount); + for (i = 0; i < ais->type6.dac1fid28.waycount; i++) { + if (scaled) + (void)snprintf(buf + strlen(buf), buflen - strlen(buf), + "\"lon\":%.4f,\"lat\":%.4f", + ais->type6.dac1fid28.waypoints[i].lon / AIS_LATLON4_SCALE, + ais->type6.dac1fid28.waypoints[i].lat / AIS_LATLON4_SCALE); + else + (void)snprintf(buf + strlen(buf), buflen - strlen(buf), + "\"lon\":%d,\"lat\":%d", + ais->type6.dac1fid28.waypoints[i].lon, + ais->type6.dac1fid28.waypoints[i].lat); + } break; case 30: /* IMO289 - Text description - addressed */ (void)snprintf(buf + strlen(buf), buflen - strlen(buf), diff --git a/jsongen.py.in b/jsongen.py.in index 37ce1ad2..f131238c 100644 --- a/jsongen.py.in +++ b/jsongen.py.in @@ -205,6 +205,27 @@ ais_specs = ( 'stringbuffered' : ('arrival', 'berth_name',), }, { + "initname" : "json_ais6_fid28", + "headers": ("AIS_HEADER","AIS_TYPE6",), + "structname": "ais->type6.dac1fid28", + "fieldmap":( + # fieldname type default + ('linkage', 'uinteger', '0'), + ('sender', 'uinteger', '0'), + ('rtype', 'uinteger', '0'), + ('month', 'uinteger', 'AIS_MONTH_NOT_AVAILABLE'), + ('day', 'uinteger', 'AIS_DAY_NOT_AVAILABLE'), + ('hour', 'uinteger', 'AIS_HOUR_NOT_AVAILABLE'), + ('minute', 'uinteger', 'AIS_MINUTE_NOT_AVAILABLE'), + ('duration', 'uinteger', '0'), + ('waypoints', 'array', ( + ('waypoint_t', 'waycount', ( + ('lon', 'integer', 'AIS_LON4_NOT_AVAILABLE'), + ('lat', 'integer', 'AIS_LAT4_NOT_AVAILABLE'), + )))), + ), + }, + { "initname" : "json_ais6_fid30", "headers": ("AIS_HEADER","AIS_TYPE6",), "structname": "ais->type6.dac1fid30", |