diff options
-rw-r--r-- | driver_aivdm.c | 52 | ||||
-rw-r--r-- | gps.h | 6 | ||||
-rw-r--r-- | gpsd_json.c | 66 | ||||
-rw-r--r-- | gpsdecode.c | 28 | ||||
-rw-r--r-- | json.h | 2 | ||||
-rwxr-xr-x | jsongen.py | 111 | ||||
-rw-r--r-- | www/AIVDM.txt | 4 |
7 files changed, 176 insertions, 93 deletions
diff --git a/driver_aivdm.c b/driver_aivdm.c index 7a5b1089..825b6300 100644 --- a/driver_aivdm.c +++ b/driver_aivdm.c @@ -148,30 +148,30 @@ bool aivdm_decode(char *buf, size_t buflen, struct aivdm_context_t *ais_context) case 1: /* Position Report */ case 2: case 3: - ais->type123.status = UBITS(38, 4); - ais->type123.turn = SBITS(42, 8); - ais->type123.speed = UBITS(50, 10); - ais->type123.accuracy = (bool)UBITS(60, 1); - ais->type123.lon = SBITS(61, 28); - ais->type123.lat = SBITS(89, 27); - ais->type123.course = UBITS(116, 12); - ais->type123.heading = UBITS(128, 9); - ais->type123.second = UBITS(137, 6); - ais->type123.maneuver = UBITS(143, 2); - //ais->type123.spare = UBITS(145, 3); - ais->type123.raim = UBITS(148, 1)!=0; - ais->type123.radio = UBITS(149, 20); + ais->type1.status = UBITS(38, 4); + ais->type1.turn = SBITS(42, 8); + ais->type1.speed = UBITS(50, 10); + ais->type1.accuracy = (bool)UBITS(60, 1); + ais->type1.lon = SBITS(61, 28); + ais->type1.lat = SBITS(89, 27); + ais->type1.course = UBITS(116, 12); + ais->type1.heading = UBITS(128, 9); + ais->type1.second = UBITS(137, 6); + ais->type1.maneuver = UBITS(143, 2); + //ais->type1.spare = UBITS(145, 3); + ais->type1.raim = UBITS(148, 1)!=0; + ais->type1.radio = UBITS(149, 20); gpsd_report(LOG_INF, "Nav=%d TURN=%d SPEED=%d Q=%d Lon=%d Lat=%d COURSE=%d TH=%d Sec=%d\n", - ais->type123.status, - ais->type123.turn, - ais->type123.speed, - (uint)ais->type123.accuracy, - ais->type123.lon, - ais->type123.lat, - ais->type123.course, - ais->type123.heading, - ais->type123.second); + ais->type1.status, + ais->type1.turn, + ais->type1.speed, + (uint)ais->type1.accuracy, + ais->type1.lon, + ais->type1.lat, + ais->type1.course, + ais->type1.heading, + ais->type1.second); break; case 4: /* Base Station Report */ case 11: /* UTC/Date Response */ @@ -232,7 +232,7 @@ bool aivdm_decode(char *buf, size_t buflen, struct aivdm_context_t *ais_context) ais->type6.dest_mmsi = UBITS(40, 30); ais->type6.retransmit = (bool)UBITS(70, 1); //ais->type6.spare = UBITS(71, 1); - ais->type6.application_id = UBITS(72, 16); + ais->type6.app_id = UBITS(72, 16); ais->type6.bitcount = ais_context->bitlen - 88; (void)memcpy(ais->type6.bitdata, (char *)ais_context->bits+11, @@ -240,7 +240,7 @@ bool aivdm_decode(char *buf, size_t buflen, struct aivdm_context_t *ais_context) gpsd_report(LOG_INF, "seqno=%d, dest=%u, id=%u, cnt=%u\n", ais->type6.seqno, ais->type6.dest_mmsi, - ais->type6.application_id, + ais->type6.app_id, ais->type6.bitcount); break; case 7: /* Binary acknowledge */ @@ -253,13 +253,13 @@ bool aivdm_decode(char *buf, size_t buflen, struct aivdm_context_t *ais_context) break; case 8: /* Binary Broadcast Message */ //ais->type8.spare = UBITS(38, 2); - ais->type8.application_id = UBITS(40, 16); + ais->type8.app_id = UBITS(40, 16); ais->type8.bitcount = ais_context->bitlen - 56; (void)memcpy(ais->type8.bitdata, (char *)ais_context->bits+7, (ais->type8.bitcount + 7) / 8); gpsd_report(LOG_INF, "id=%u, cnt=%u\n", - ais->type8.application_id, + ais->type8.app_id, ais->type8.bitcount); break; case 9: /* Standard SAR Aircraft Position Report */ @@ -508,7 +508,7 @@ struct ais_t //uint spare; spare bits */ bool raim; /* RAIM flag */ uint radio; /* radio status bits */ - } type123; + } type1; /* Type 4 - Base Station Report & Type 11 - UTC and Date Response */ struct { uint year; /* UTC year */ @@ -558,7 +558,7 @@ struct ais_t uint dest_mmsi; /* destination MMSI */ bool retransmit; /* retransmit flag */ //uint spare; spare bit(s) */ - uint application_id; /* Application ID */ + uint app_id; /* Application ID */ #define AIS_TYPE6_BINARY_MAX 920 /* 920 bits */ uint bitcount; /* bit count of the data */ char bitdata[(AIS_TYPE6_BINARY_MAX + 7) / 8]; @@ -570,7 +570,7 @@ struct ais_t /* Type 8 - Broadcast Binary Message */ struct { //uint spare; spare bit(s) */ - uint application_id; /* Application ID */ + uint app_id; /* Application ID */ #define AIS_TYPE8_BINARY_MAX 952 /* 952 bits */ uint bitcount; /* bit count of the data */ char bitdata[(AIS_TYPE8_BINARY_MAX + 7) / 8]; diff --git a/gpsd_json.c b/gpsd_json.c index 7eea3670..24462a03 100644 --- a/gpsd_json.c +++ b/gpsd_json.c @@ -632,64 +632,64 @@ void aivdm_json_dump(struct ais_t *ais, bool scaled, char *buf, size_t buflen) * Express turn as nan if not available, * "fastleft"/"fastright" for fast turns. */ - if (ais->type123.turn == -128) + if (ais->type1.turn == -128) (void) strlcpy(turnlegend, "nan", sizeof(turnlegend)); - else if (ais->type123.turn == -127) + else if (ais->type1.turn == -127) (void) strlcpy(turnlegend, "fastleft", sizeof(turnlegend)); - else if (ais->type123.turn == 127) + else if (ais->type1.turn == 127) (void) strlcpy(turnlegend, "fastright", sizeof(turnlegend)); else (void)snprintf(turnlegend, sizeof(turnlegend), "%.0f", - ais->type123.turn * ais->type123.turn / 4.733); + ais->type1.turn * ais->type1.turn / 4.733); /* * Express speed as nan if not available, * "fast" for fast movers. */ - if (ais->type123.speed == AIS_SPEED_NOT_AVAILABLE) + if (ais->type1.speed == AIS_SPEED_NOT_AVAILABLE) (void) strlcpy(speedlegend, "nan", sizeof(speedlegend)); - else if (ais->type123.speed == AIS_SPEED_FAST_MOVER) + else if (ais->type1.speed == AIS_SPEED_FAST_MOVER) (void) strlcpy(speedlegend, "fast", sizeof(speedlegend)); else (void)snprintf(speedlegend, sizeof(speedlegend), - "%.1f", ais->type123.speed / 10.0); + "%.1f", ais->type1.speed / 10.0); (void)snprintf(buf+strlen(buf), buflen-strlen(buf), "\"status\":\"%s\",\"turn\":%s,\"speed\":%s," "\"accuracy\":%s,\"lon\":%.4f,\"lat\":%.4f," "\"course\":%u,\"heading\":%d,\"second\":%u," "\"maneuver\":%d,\"raim\":%s,\"radio\":%d}\r\n", - nav_legends[ais->type123.status], + nav_legends[ais->type1.status], turnlegend, speedlegend, - JSON_BOOL(ais->type123.accuracy), - ais->type123.lon / AIS_LATLON_SCALE, - ais->type123.lat / AIS_LATLON_SCALE, - ais->type123.course, - ais->type123.heading, - ais->type123.second, - ais->type123.maneuver, - JSON_BOOL(ais->type123.raim), - ais->type123.radio); + JSON_BOOL(ais->type1.accuracy), + ais->type1.lon / AIS_LATLON_SCALE, + ais->type1.lat / AIS_LATLON_SCALE, + ais->type1.course, + ais->type1.heading, + ais->type1.second, + ais->type1.maneuver, + JSON_BOOL(ais->type1.raim), + ais->type1.radio); } else { (void)snprintf(buf+strlen(buf), buflen-strlen(buf), "\"status\":%u,\"turn\":%d,\"speed\":%u," "\"accuracy\":%s,\"lon\":%d,\"lat\":%d," "\"course\":%u,\"heading\":%d,\"second\":%u," "\"maneuver\":%d,\"raim\":%s,\"radio\":%d}\r\n", - ais->type123.status, - ais->type123.turn, - ais->type123.speed, - JSON_BOOL(ais->type123.accuracy), - ais->type123.lon, - ais->type123.lat, - ais->type123.course, - ais->type123.heading, - ais->type123.second, - ais->type123.maneuver, - JSON_BOOL(ais->type123.raim), - ais->type123.radio); + ais->type1.status, + ais->type1.turn, + ais->type1.speed, + JSON_BOOL(ais->type1.accuracy), + ais->type1.lon, + ais->type1.lat, + ais->type1.course, + ais->type1.heading, + ais->type1.second, + ais->type1.maneuver, + JSON_BOOL(ais->type1.raim), + ais->type1.radio); } break; case 4: /* Base Station Report */ @@ -788,12 +788,12 @@ void aivdm_json_dump(struct ais_t *ais, bool scaled, char *buf, size_t buflen) case 6: /* Binary Message */ (void)snprintf(buf+strlen(buf), buflen-strlen(buf), "\"seqno\":%u,\"dest_mmsi\":%u," - "\"retransmit\":%u,\"application_id\":%u," + "\"retransmit\":%u,\"app_id\":%u," "\"data\":\"%u:%s\"}\r\n", ais->type6.seqno, ais->type6.dest_mmsi, ais->type6.retransmit, - ais->type6.application_id, + ais->type6.app_id, ais->type6.bitcount, gpsd_hexdump(ais->type6.bitdata, (ais->type6.bitcount+7)/8)); @@ -808,8 +808,8 @@ void aivdm_json_dump(struct ais_t *ais, bool scaled, char *buf, size_t buflen) break; case 8: /* Binary Broadcast Message */ (void)snprintf(buf+strlen(buf), buflen-strlen(buf), - "\"appid\":%u,\"data\":\"%u:%s\"}\r\n", - ais->type8.application_id, + "\"app_id\":%u,\"data\":\"%u:%s\"}\r\n", + ais->type8.app_id, ais->type8.bitcount, gpsd_hexdump(ais->type8.bitdata, (ais->type8.bitcount+7)/8)); diff --git a/gpsdecode.c b/gpsdecode.c index bdebafd4..2f4054dd 100644 --- a/gpsdecode.c +++ b/gpsdecode.c @@ -49,18 +49,18 @@ static void aivdm_csv_dump(struct ais_t *ais, char *buf, size_t buflen) case 3: (void)snprintf(buf+strlen(buf), buflen-strlen(buf), "%u,%d,%u,%u,%d,%d,%u,%d,%u,0x%x,%d,0x%x", - ais->type123.status, - ais->type123.turn, - ais->type123.speed, - (uint)ais->type123.accuracy, - ais->type123.lon, - ais->type123.lat, - ais->type123.course, - ais->type123.heading, - ais->type123.second, - ais->type123.maneuver, - ais->type123.raim, - ais->type123.radio); + ais->type1.status, + ais->type1.turn, + ais->type1.speed, + (uint)ais->type1.accuracy, + ais->type1.lon, + ais->type1.lat, + ais->type1.course, + ais->type1.heading, + ais->type1.second, + ais->type1.maneuver, + ais->type1.raim, + ais->type1.radio); break; case 4: /* Base Station Report */ case 11: /* UTC/Date Response */ @@ -106,7 +106,7 @@ static void aivdm_csv_dump(struct ais_t *ais, char *buf, size_t buflen) ais->type6.seqno, ais->type6.dest_mmsi, ais->type6.retransmit, - ais->type6.application_id, + ais->type6.app_id, ais->type6.bitcount, gpsd_hexdump(ais->type6.bitdata, (ais->type6.bitcount+7)/8)); @@ -122,7 +122,7 @@ static void aivdm_csv_dump(struct ais_t *ais, char *buf, size_t buflen) case 8: /* Binary Broadcast Message */ (void)snprintf(buf+strlen(buf), buflen-strlen(buf), "%u,%u:%s", - ais->type8.application_id, + ais->type8.app_id, ais->type8.bitcount, gpsd_hexdump(ais->type8.bitdata, (ais->type8.bitcount+7)/8)); @@ -58,7 +58,7 @@ struct json_attr_t { }; #define JSON_ATTR_MAX 31 /* max chars in JSON attribute name */ -#define JSON_VAL_MAX 63 /* max chars in JSON value part */ +#define JSON_VAL_MAX 120 /* max chars in JSON value part */ int json_read_object(const char *, const struct json_attr_t *, const char **); int json_read_array(const char *, const struct json_array_t *, const char **); @@ -57,7 +57,7 @@ ais_specs = ( "header": "\tAIS_HEADER,", "structname": "ais->type5", "fieldmap":( - # fieldname type default + # fieldname type default ('imo', 'uinteger', '0'), ('ais_version', 'uinteger', '0'), ('callsign', 'string', None), @@ -75,28 +75,112 @@ ais_specs = ( ), "stringbuffered":("eta",), }, + { + "initname" : "json_ais6", + "header": "\tAIS_HEADER,", + "structname": "ais->type6", + "fieldmap":( + # fieldname type default + ('seqno', 'uinteger', '0'), + ('dest_mmsi', 'uinteger', '0'), + ('retransmit', 'uinteger', '0'), + ('app_id', 'uinteger', '0'), + ('data', 'string', None), + ), + "stringbuffered":("data",), + }, + { + "initname" : "json_ais7", + "header": "\tAIS_HEADER,", + "structname": "ais->type7", + "fieldmap":( + # fieldname type default + ('mmsi1', 'uinteger', '0'), + ('mmsi2', 'uinteger', '0'), + ('mmsi3', 'uinteger', '0'), + ('mmsi4', 'uinteger', '0'), + ), + }, + { + "initname" : "json_ais8", + "header": "\tAIS_HEADER,", + "structname": "ais->type8", + "fieldmap":( + # fieldname type default + ('app_id', 'uinteger', '0'), + ('data', 'string', None), + ), + "stringbuffered":("data",), + }, + { + "initname" : "json_ais9", + "header": "\tAIS_HEADER,", + "structname": "ais->type9", + "fieldmap":( + # fieldname type default + ('alt', 'uinteger', 'AIS_ALT_NOT_AVAILABLE'), + ('speed', 'uinteger', 'AIS_SPEED_NOT_AVAILABLE'), + ('accuracy', 'boolean', 'false'), + ('lon', 'real', 'AIS_LON_NOT_AVAILABLE'), + ('lat', 'real', 'AIS_LAT_NOT_AVAILABLE'), + ('course', 'real', 'AIS_COURSE_NOT_AVAILABLE'), + ('second', 'uinteger', 'AIS_SEC_NOT_AVAILABLE'), + ('regional', 'integer', '0'), + ('dte', 'uinteger', '1'), + ('raim', 'boolean', 'false'), + ('radio', 'integer', '0'), + ), + }, + { + "initname" : "json_ais10", + "header": "\tAIS_HEADER,", + "structname": "ais->type10", + "fieldmap":( + # fieldname type default + ('dest_mmsi', 'uinteger', '0'), + ), + }, + { + "initname" : "json_ais12", + "header": "\tAIS_HEADER,", + "structname": "ais->type12", + "fieldmap":( + # fieldname type default + ('seq', 'uinteger', '0'), + ('dst', 'uinteger', '0'), + ('rexmit', 'uinteger', '0'), + ('text', 'string', None), + ), + }, + { + "initname" : "json_ais13", + "header": "\tAIS_HEADER,", + "structname": "ais->type13", + "fieldmap":( + # fieldname type default + ('mmsi1', 'uinteger', '0'), + ('mmsi2', 'uinteger', '0'), + ('mmsi3', 'uinteger', '0'), + ('mmsi4', 'uinteger', '0'), + ), + }, ) -# Map shared field names to data types -overrides = { - "raim":"boolean", - "accuracy":"boolean", - } - # Give this global the string spec you need to convert with -g -# We do it this mildly odd way only becaue passing Python multiline +# We do it this mildly odd way only because passing Python multiline # string literals on the command line is inconvenient. stringspec = \ - "\"seqno\":%u,\"dest_mmsi\":%u,"\ - "\"retransmit\":%u,\"application_id\":%u,"\ - "\"data\":\"%u:%s\"}\r\n" + "\"mmsi1\":%u,\"mmsi2\":%u,\"mmsi3\":%u,\"mmsi4\":%u}\r\n" # You should not need to modify anything below this liine. def generate(spec): + outboard = [] for (attr, itype, default) in spec["fieldmap"]: if attr in spec.get("stringbuffered", []): - print " char %s[JSON_VAL_MAX+1];" % attr + if attr not in outboard: + print " char %s[JSON_VAL_MAX+1];" % attr + outboard.append(attr) print " const struct json_attr_t %s[] = {" % spec["initname"] if "header" in spec: print spec["header"] @@ -130,6 +214,7 @@ def string_to_specifier(strspec): "d": "integer", "u": "uinteger", "f": "real", + "s": "boolean", # Only booleans print as unquoted strings "\"": "string", } dftmap = { @@ -153,8 +238,6 @@ def string_to_specifier(strspec): attr = attr[1:] if attr[-1] == '"': attr = attr[:-1] - if attr in overrides: - itype = overrides[attr] dflt = dftmap[itype] if dflt is not None: dflt = `dflt` diff --git a/www/AIVDM.txt b/www/AIVDM.txt index 62e6fb59..4cbcf16c 100644 --- a/www/AIVDM.txt +++ b/www/AIVDM.txt @@ -711,7 +711,7 @@ Field Len Description Member Units 70 1 Retransmit flag retransmit 0 = no retransmission (default) 1 = retransmitted 71 1 Spare Not used -72-87 16 Application ID application_id Unsigned integer +72-87 16 Application ID app_id Unsigned integer 88 920 Data data Binary data Field may be shorter than 920 bits. ------------------------------------------------------------------------------- @@ -753,7 +753,7 @@ Field Len Description Member Units 6-7 2 Repeat Indicator repeat As in Common Navigation Block 8-37 30 Source MMSI mmsi Unsigned integer: 9 digits 38-39 2 Spare Not used -40-55 16 Application ID application_id Unsigned integer +40-55 16 Application ID app_id Unsigned integer 56 952 Data data Binary data Field may be shorter than 952 bits. ------------------------------------------------------------------------------- |