diff options
author | Eric S. Raymond <esr@thyrsus.com> | 2011-04-25 15:32:08 -0400 |
---|---|---|
committer | Eric S. Raymond <esr@thyrsus.com> | 2011-04-25 15:32:08 -0400 |
commit | 78ed39bd60d8356c49a9669495e5f3af35196bb8 (patch) | |
tree | 5f1269b66ce3af7eee301e83d0f628b12714a9cd | |
parent | bb7b81d07184915551c633dda56384a0d13e5e4f (diff) | |
download | gpsd-78ed39bd60d8356c49a9669495e5f3af35196bb8.tar.gz |
Fix some bugs in JSON parsing and dumping of timestamps.
-rw-r--r-- | ais_json.c | 35 | ||||
-rw-r--r-- | gpsd_json.c | 16 | ||||
-rw-r--r-- | jsongen.py.in | 17 | ||||
-rw-r--r-- | www/AIVDM.txt | 102 |
4 files changed, 103 insertions, 67 deletions
@@ -90,7 +90,8 @@ int json_ais_read(const char *buf, &ais->type4.month, &ais->type4.day, &ais->type4.hour, - &ais->type4.minute, &ais->type4.second); + &ais->type4.minute, + &ais->type4.second); } } else if (strstr(buf, "\"type\":5,") != NULL) { status = json_read_object(buf, json_ais5, endptr); @@ -102,12 +103,33 @@ int json_ais_read(const char *buf, (void)sscanf(eta, "%02u-%02uT%02u:%02uZ", &ais->type5.month, &ais->type5.day, - &ais->type5.hour, &ais->type5.minute); + &ais->type5.hour, + &ais->type5.minute); } } else if (strstr(buf, "\"type\":6,") != NULL) { bool imo = false; if (strstr(buf, "\"fid\":12,") != NULL) { status = json_read_object(buf, json_ais6_fid12, endptr); + if (status == 0) { + ais->type6.dac1fid12.lmonth = AIS_MONTH_NOT_AVAILABLE; + ais->type6.dac1fid12.lday = AIS_DAY_NOT_AVAILABLE; + ais->type6.dac1fid12.lhour = AIS_HOUR_NOT_AVAILABLE; + ais->type6.dac1fid12.lminute = AIS_MINUTE_NOT_AVAILABLE; + (void)sscanf(departure, "%02u-%02uT%02u:%02uZ", + &ais->type6.dac1fid12.lmonth, + &ais->type6.dac1fid12.lday, + &ais->type6.dac1fid12.lhour, + &ais->type6.dac1fid12.lminute); + ais->type6.dac1fid12.nmonth = AIS_MONTH_NOT_AVAILABLE; + ais->type6.dac1fid12.nday = AIS_DAY_NOT_AVAILABLE; + ais->type6.dac1fid12.nhour = AIS_HOUR_NOT_AVAILABLE; + ais->type6.dac1fid12.nminute = AIS_MINUTE_NOT_AVAILABLE; + (void)sscanf(eta, "%02u-%02uT%02u:%02uZ", + &ais->type6.dac1fid12.nmonth, + &ais->type6.dac1fid12.nday, + &ais->type6.dac1fid12.nhour, + &ais->type6.dac1fid12.nminute); + } imo = true; } else if (strstr(buf, "\"fid\":15,") != NULL) { @@ -143,6 +165,15 @@ int json_ais_read(const char *buf, } else if (strstr(buf, "\"fid\":31,") != NULL || strstr(buf, "\"fid\":11,") != NULL) { status = json_read_object(buf, json_ais8_fid31, endptr); + if (status == 0) { + ais->type5.day = AIS_DAY_NOT_AVAILABLE; + ais->type5.hour = AIS_HOUR_NOT_AVAILABLE; + ais->type5.minute = AIS_MINUTE_NOT_AVAILABLE; + (void)sscanf(eta, "%02uT%02u:%02uZ", + &ais->type5.day, + &ais->type5.hour, + &ais->type5.minute); + } imo = true; } if (!imo) { diff --git a/gpsd_json.c b/gpsd_json.c index f5b8053b..e5be1b0a 100644 --- a/gpsd_json.c +++ b/gpsd_json.c @@ -1621,9 +1621,10 @@ void json_aivdm_dump(const struct ais_t *ais, break; case 4: /* Base Station Report */ case 11: /* UTC/Date Response */ + /* some fields have beem merged to an ISO8601 date */ if (scaled) { (void)snprintf(buf + strlen(buf), buflen - strlen(buf), - "\"timestamp\":\"%4u:%02u:%02uT%02u:%02u:%02uZ\"," + "\"timestamp\":\"%4u-%02u-%02uT%02u:%02u:%02uZ\"," "\"accuracy\":%s,\"lon\":%.4f,\"lat\":%.4f," "\"epfd\":\"%s\",\"raim\":%s,\"radio\":%u}\r\n", ais->type4.year, @@ -1656,6 +1657,7 @@ void json_aivdm_dump(const struct ais_t *ais, } break; case 5: /* Ship static and voyage related data */ + /* some fields have beem merged to an ISO8601 partial date */ if (scaled) { /* *INDENT-OFF* */ (void)snprintf(buf + strlen(buf), buflen - strlen(buf), @@ -1720,11 +1722,10 @@ void json_aivdm_dump(const struct ais_t *ais, if (ais->type6.dac == 1) switch (ais->type6.fid) { case 12: /* IMO236 -Dangerous cargo indication */ + /* some fields have beem merged to an ISO8601 partial date */ (void)snprintf(buf + strlen(buf), buflen - strlen(buf), - "\"lastport\":\"%s\",\"lmonth\":%u,\"lday\":%u," - "\"lhour\":%u,\"lminute\":%u," - "\"nextport\":\"%s\",\"nmonth\":%u,\"nday\":%u," - "\"nhour\":%u,\"nminute\":%u," + "\"lastport\":\"%s\",\"departure\":\"%02u-%02uT%02u:%02uZ\"," + "\"nextport\":\"%s\",\"eta\":\"%02u-%02uT%02u:%02uZ\"," "\"dangerous\":\"%s\",\"imdcat\":\"%s\"," "\"unid\":%u,\"amount\":%u,\"unit\":%u", ais->type6.dac1fid12.lastport, @@ -1793,7 +1794,7 @@ void json_aivdm_dump(const struct ais_t *ais, break; case 23: /* IMO289 - Area notice - addressed */ break; - case 25: /* IMO289 = Dangerous cargo indication */ + case 25: /* IMO289 - Dangerous cargo indication */ break; case 28: /* IMO289 - Route info - addressed */ break; @@ -1833,6 +1834,7 @@ void json_aivdm_dump(const struct ais_t *ais, switch (ais->type8.fid) { case 11: /* IMO236 - Meteorological/Hydrological data */ case 31: /* IMO289 - Meteorological/Hydrological data */ + /* some fields have beem merged to an ISO8601 partial date */ /* layout is almost identical to FID=31 from IMO289 */ if (scaled) (void)snprintf(buf + strlen(buf), buflen - strlen(buf), @@ -1849,7 +1851,7 @@ void json_aivdm_dump(const struct ais_t *ais, "\"accuracy\":%s,", JSON_BOOL(ais->type8.dac1fid31.accuracy)); (void)snprintf(buf + strlen(buf), buflen - strlen(buf), - "\"day\":%u,\"hour\":%u,\"minute\":%u," + "\"timestamp\":\"%02uT%02u:%02uZ\"," "\"wapeed\":%u,\"wgust\":%u,\"wdir\":%u," "\"wgustdir\":%u,\"humidity\":%u", ais->type8.dac1fid31.day, diff --git a/jsongen.py.in b/jsongen.py.in index c0260e0c..f779c60e 100644 --- a/jsongen.py.in +++ b/jsongen.py.in @@ -101,21 +101,16 @@ ais_specs = ( "fieldmap":( # fieldname type default ('lastport', 'string', None), - ('lmonth', 'uinteger', 'AIS_MONTH_NOT_AVAILABLE'), - ('lday', 'uinteger', 'AIS_DAY_NOT_AVAILABLE'), - ('lhour', 'uinteger', 'AIS_HOUR_NOT_AVAILABLE'), - ('lminute', 'uinteger', 'AIS_MINUTE_NOT_AVAILABLE'), + ('departure', 'string', None), ('nextport', 'string', None), - ('nmonth', 'uinteger', 'AIS_MONTH_NOT_AVAILABLE'), - ('nday', 'uinteger', 'AIS_DAY_NOT_AVAILABLE'), - ('nhour', 'uinteger', 'AIS_HOUR_NOT_AVAILABLE'), - ('nminute', 'uinteger', 'AIS_MINUTE_NOT_AVAILABLE'), + ('eta', 'string', None), ('dangerous', 'string', None), ('imdcat', 'string', None), ('unid', 'uinteger', '0'), ('amount', 'uinteger', '0'), ('unit', 'uinteger', '0'), ), + "stringbuffered":("departure","eta",), }, { "initname" : "json_ais6_fid15", @@ -212,9 +207,7 @@ ais_specs = ( ('dac1fid31.lon', 'integer', 'DAC1FID31_LON_NOT_AVAILABLE'), ('dac1fid31.lat', 'integer', 'DAC1FID31_LAT_NOT_AVAILABLE'), ('dac1fid31.accuracy', 'boolean', 'false'), - ('dac1fid31.day', 'uinteger', 'AIS_DAY_NOT_AVAILABLE'), - ('dac1fid31.hour', 'uinteger', 'AIS_HOUR_NOT_AVAILABLE'), - ('dac1fid31.minute', 'uinteger', 'AIS_MINUTE_NOT_AVAILABLE'), + ('timestamp', "string", None), ('dac1fid31.wspeed', 'uinteger', 'DAC1FID31_WIND_NOT_AVAILABLE'), ('dac1fid31.wgust ', 'uinteger', 'DAC1FID31_WIND_NOT_AVAILABLE'), ('dac1fid31.wdir', 'uinteger', 'DAC1FID31_DIR_NOT_AVAILABLE'), @@ -245,7 +238,7 @@ ais_specs = ( ('dac1fid31.salinity', 'uinteger', 'DAC1FID31_SALINITY_NOT_AVAILABLE'), ('dac1fid31.ice', 'boolean', 'false'), ), - "stringbuffered":("data",), + "stringbuffered":("timestamp",), }, { "initname" : "json_ais9", diff --git a/www/AIVDM.txt b/www/AIVDM.txt index a28cc3b4..947da01b 100644 --- a/www/AIVDM.txt +++ b/www/AIVDM.txt @@ -650,12 +650,12 @@ The standard uses "EPFD" to designate any Electronic Position Fixing Device. |0-5 | 6 |Message Type |type |u|Constant: 4 |6-7 | 2 |Repeat Indicator |repeat |u|Unknown |8-37 | 30 |MMSI |mmsi |u|9 decimal digits -|38-51 | 14 |Year |year |u|UTC, 1-999, 0 = N/A (default) -|52-55 | 4 |Month |month |u|1-12; 0 = N/A (default) -|56-60 | 5 |Day |day |u|1-31; 0 = N/A (default) -|61-65 | 5 |Hour |hour |u|0-23; 24 = N/A (default) -|66-71 | 6 |Minute |minute |u|0-59; 60 = N/A (default) -|72-77 | 6 |Second |second |u|0-59; 60 = N/A (default) +|38-51 | 14 |Year (UTC) |year |u|UTC, 1-999, 0 = N/A (default) +|52-55 | 4 |Month (UTC) |month |u|1-12; 0 = N/A (default) +|56-60 | 5 |Day (UTC) |day |u|1-31; 0 = N/A (default) +|61-65 | 5 |Hour (UTC) |hour |u|0-23; 24 = N/A (default) +|66-71 | 6 |Minute (UTC) |minute |u|0-59; 60 = N/A (default) +|72-77 | 6 |Second (UTC) |second |u|0-59; 60 = N/A (default) |78-78 | 1 |Fix quality |accuracy |b|As in Common Navigation Block |79-106 | 28 |Longitude |lon |I4|As in Common Navigation Block |107-133 | 27 |Latitude |lat |I4|As in Common Navigation Block @@ -710,10 +710,10 @@ humans rather than gathered automatically from sensors. |258-263 | 6 |Dimension to Port |to_port |u|Meters |264-269 | 6 |Dimension to Starboard |to_starboard |u|Meters |270-273 | 4 |Position Fix Type |epfd |u|As in Type 4 EPSD codes -|274-277 | 4 |ETA month |month |u|1-12, 0=N/A (default) -|278-282 | 5 |ETA day |day |u|1-31, 0=N/A (default) -|283-287 | 5 |ETA hour |hour |u|0-23, 24=N/A (default) -|288-293 | 6 |ETA minute |minute |u|0-59, 60=N/A (default) +|274-277 | 4 |ETA month (UTC) |month |u|1-12, 0=N/A (default) +|278-282 | 5 |ETA day (UTC) |day |u|1-31, 0=N/A (default) +|283-287 | 5 |ETA hour (UTC) |hour |u|0-23, 24=N/A (default) +|288-293 | 6 |ETA minute (UTC) |minute |u|0-59, 60=N/A (default) |294-301 | 8 |Draught |draught |U1|Meters/10 |302-421 |120 |Destination |destination |t|20 6-bit characters |422-422 | 1 |DTE |dte |b|0=Data terminal ready, @@ -903,15 +903,15 @@ This is the <<IMO236>> version, now deprecated; there is a later |72-81 | 10 |DAC |dac |u|DAC = 001 |82-87 | 6 |FID |fid |u|FID = 12 |88-117 | 30 |Last Port Of Call |lastport |t|5 6-bit characters, UN locode -|118-121 | 4 |ETA month |lmonth |u|1-12, 0=N/A (default) -|122-126 | 5 |ETA day |lday |u|1-31, 0=N/A (default) -|127-131 | 5 |ETA hour |lhour |u|0-23, 24=N/A (default) -|132-137 | 6 |ETA minute |lminute |u|0-59, 60=N/A (default) +|118-121 | 4 |ETA month (UTC) |lmonth |u|1-12, 0=N/A (default) +|122-126 | 5 |ETA day (UTC) |lday |u|1-31, 0=N/A (default) +|127-131 | 5 |ETA hour (UTC) |lhour |u|0-23, 24=N/A (default) +|132-137 | 6 |ETA minute (UTC) |lminute |u|0-59, 60=N/A (default) |138-167 | 30 |Next Port Of Call |nextport |t|5 6-bit characters, UN locode -|168-171 | 4 |ETA month |nmonth |u|1-12, 0=N/A (default) -|172-176 | 5 |ETA day |nday |u|1-31, 0=N/A (default) -|177-181 | 5 |ETA hour |nhour |u|0-23, 24=N/A (default) -|182-187 | 6 |ETA minute |nminute |u|0-59, 60=N/A (default) +|168-171 | 4 |ETA month (UTC) |nmonth |u|1-12, 0=N/A (default) +|172-176 | 5 |ETA day (UTC) |nday |u|1-31, 0=N/A (default) +|177-181 | 5 |ETA hour (UTC) |nhour |u|0-23, 24=N/A (default) +|182-187 | 6 |ETA minute (UTC) |nminute |u|0-59, 60=N/A (default) |188-307 |120 |Main Dangerous Good |dangerous |t|20 6-bit characters |308-331 | 24 |IMD Category |imdcat |t|4 6-bit characters |332-344 | 13 |UN Number |unid |u|1-3363 UN Number @@ -1049,10 +1049,10 @@ A message 6 subtype. DAC = 001 FID = 18. Fixed length: 360 bits. |72-81 | 10 |DAC |dac |u|DAC = 001 |82-87 | 6 |FID |fid |u|FID = 18 |88-97 | 10 |Message Linkage ID |linkage |u|Unsigned integer -|98-101 | 4 |Month |month |u|1-12; 0 = N/A (default) -|102-106 | 5 |Day |day |u|1-31; 0 = N/A (default) -|107-111 | 5 |Hour |hour |u|0-23; 24 = N/A (default) -|112-117 | 6 |Minute |minute |u|0-59; 60 = N/A (default) +|98-101 | 4 |Month (UTC) |month |u|1-12; 0 = N/A (default) +|102-106 | 5 |Day (UTC) |day |u|1-31; 0 = N/A (default) +|107-111 | 5 |Hour (UTC) |hour |u|0-23; 24 = N/A (default) +|112-117 | 6 |Minute (UTC) |minute |u|0-59; 60 = N/A (default) |118-237 |120 |Name of Port & Berth |portname |u|20 6-bit characters |238-267 | 30 |Destination |destination|u|5 6-bit characters |268-292 | 25 |Longitude |lon |I3|Unit = minutes * 0.001, @@ -1095,10 +1095,10 @@ bit is on. 255 = >= 25.5m 0 = N/A (default) |115-117 | 3 |Mooring Position |position |u|See below -|118-121 | 4 |Month |month |u|1-12; 0 = N/A (default) -|122-126 | 5 |Day |day |u|1-31; 0 = N/A (default) -|127-131 | 5 |Hour |hour |u|0-23; 24 = N/A (default) -|132-137 | 6 |Minute |minute |u|0-59; 60 = N/A (default) +|118-121 | 4 |Month (UTC) |month |u|1-12; 0 = N/A (default) +|122-126 | 5 |Day (UTC) |day |u|1-31; 0 = N/A (default) +|127-131 | 5 |Hour (UTC) |hour |u|0-23; 24 = N/A (default) +|132-137 | 6 |Minute (UTC) |minute |u|0-59; 60 = N/A (default) |138-138 | 1 |Services Availability|availability|u|0 = services types unknown 1 = services types are known |139-140 | 2 |Agent |agent |u|Service status value @@ -1267,10 +1267,10 @@ A message 6 subtype. DAC = 001 FID = 28. Variable length: 204-1029 bits. 1 = authority, 27 = reserved for future use |101-105 | 5 |Route Type |rtype |u|See table below -|106-109 | 4 |Start month |month |u|1-12, 0=N/A (default) -|110-114 | 5 |Start day |day |u|1-31, 0=N/A (default) -|115-119 | 5 |Start hour |hour |u|0-23, 24=N/A (default) -|120-125 | 6 |Start minute |minute |u|0-59, 60=N/A (default) +|106-109 | 4 |Start month (UTC) |month |u|1-12, 0=N/A (default) +|110-114 | 5 |Start day (UTC) |day |u|1-31, 0=N/A (default) +|115-119 | 5 |Start hour (UTC) |hour |u|0-23, 24=N/A (default) +|120-125 | 6 |Start minute (UTC)|minute |u|0-59, 60=N/A (default) |126-143 | 18 |Duration |duration |u|Minutes from start time, 0 = cancel route, 262,143 = N/A (default), @@ -1490,9 +1490,9 @@ broadcast of this message of 12 minutes. |80-104 | 25 |Longitude |lon |I3|Unit = minutes * 0.001, 181000 = N/A (default), N positive, S negative. -|105-109 | 5 |Day |day |u|1-31, 0=N/A (default) -|110-114 | 5 |Hour |hour |u|0-23, >=24=N/A (default) -|115-120 | 6 |Minute |minute |u|0-59, >=60=N/A (default) +|105-109 | 5 |Day (UTC) |day |u|1-31, 0=N/A (default) +|110-114 | 5 |Hour (UTC) |hour |u|0-23, >=24=N/A (default) +|115-120 | 6 |Minute (UTC) |minute |u|0-59, >=60=N/A (default) |121-127 | 7 |Average Wind Speed |wspeed |u|10-min avg wind speed, knots, 127 = N/A (default). |128-134 | 7 |Gust Speed |wgust |u|10-min max wind speed, knots, @@ -1651,14 +1651,14 @@ Described in <<IMO236>> but deprecated by <<IMO289>>. |296-415 |120 |Location of Closing To |dangerous|t|20 6-bit characcters |416-425 | 10 |Radius extension |radius |u|0-1000, 10001 = N/A (default) |426-427 | 2 |Unit of extension |extunit |u|0=m, 1=km, 2=nm, 3=cables -|428-432 | 5 |From day |fday |u|1-31, 0=N/A (default) -|433-436 | 4 |From month |fmonth |u|1-12, 0=N/A (default) -|437-441 | 5 |From hour |fhour |u|0-23, 24=N/A (default) -|442-447 | 6 |From minute |fminute |u|0-59, 60=N/A (default) -|448-452 | 5 |To day |tday |u|1-31, 0=N/A (default) -|453-456 | 4 |To month |tmonth |u|1-12, 0=N/A (default) -|457-461 | 5 |To hour |thour |u|0-23, 24=N/A (default) -|462-467 | 6 |To minute |tminute |u|0-59, 60=N/A (default) +|428-432 | 5 |From day (UTC) |fday |u|1-31, 0=N/A (default) +|433-436 | 4 |From month (UTC) |fmonth |u|1-12, 0=N/A (default) +|437-441 | 5 |From hour (UTC) |fhour |u|0-23, 24=N/A (default) +|442-447 | 6 |From minute (UTC) |fminute |u|0-59, 60=N/A (default) +|448-452 | 5 |To day (UTC) |tday |u|1-31, 0=N/A (default) +|453-456 | 4 |To month (UTC) |tmonth |u|1-12, 0=N/A (default) +|457-461 | 5 |To hour (UTC) |thour |u|0-23, 24=N/A (default) +|462-467 | 6 |To minute (UTC) |tminute |u|0-59, 60=N/A (default) |468-471 | 4 |Spare | |x|Not used |============================================================================== @@ -3348,10 +3348,20 @@ The general ground rules for JSON-AIS encoding are as follows: 2. When multiple kinds of JSON objects may occur in a data stream, AIS objects have the attribute "class":"AIS". -3. Collections of fields aggregating to a timestamp are dumped in -ISO8601 format. Messages for which this rule is relevant are type 4; -type 5; type 6 with DAC = 1 and FID = 12, 14, 28, 32; type 8 with DAC -1 and FID = 11, 13. +3. Some collections of fields aggregating to a timestamp are dumped in +ISO8601 format. + +.Timestamp fields +[frame="topbot",options="header"] +|=========================================================================== +|Message| ITU/IMO fields | JSON ISO8601 | Format +| 4 | year,month,day,hour,minute,second| timestamp | %4u-%02u-%02uT%02u:%02u:%02uZ +| 5 | month,day,hour,minute | eta | %02u-%02uT%02u:%02uZ +|6(1/12)| lmonth,lday,lhour,lminute | departure | %02u-%02uT%02u:%02uZ +| | nmonth,nday,nhour,nminute | eta | %02u-%02uT%02u:%02uZ +|8(1/11)| day,hour,minute | timestamp | %02uT%02u:%02uZ +|8(1/11)| day,hour,minute | timestamp | %02uT%02u:%02uZ +|=========================================================================== 4. There are two variants of the encoding, one scaled and one unscaled, which differ in the treatment of float and @@ -3389,7 +3399,7 @@ integer indices. In scaled mode, the values are dumped as strings. | | swellheight, watertemp salinity | | 8(1/17)| lon, lat | - | 8(1/18)| lon, lat | - -| 8(1/21)| lon. lat, visibility, airtemp, | - +| 8(1/21)| lon, lat, visibility, airtemp, | - | | watertemp, waveheight, | | | swellheight, speed, pressure, pdelta,| | | rwindspeed, mgustspeed, airtemp, | |