diff options
-rw-r--r-- | ais_json.c | 18 | ||||
-rw-r--r-- | driver_ais.c | 89 | ||||
-rw-r--r-- | gps.h | 69 | ||||
-rw-r--r-- | gpsd_json.c | 289 | ||||
-rw-r--r-- | gpsdecode.c | 61 | ||||
-rw-r--r-- | jsongen.py.in | 43 |
6 files changed, 438 insertions, 131 deletions
@@ -228,7 +228,21 @@ int json_ais_read(const char *buf, } else if (strstr(buf, "\"type\":8,") != NULL) { bool imo = false; if (strstr(buf, "\"dac\":1,") != NULL) { - if (strstr(buf, "\"fid\":13,") != NULL) { + if (strstr(buf, "\"fid\":11,") != NULL) { + status = json_read_object(buf, json_ais8_fid11, endptr); + if (status == 0) { + ais->type8.dac1fid11.day = AIS_DAY_NOT_AVAILABLE; + ais->type8.dac1fid11.hour = AIS_HOUR_NOT_AVAILABLE; + ais->type8.dac1fid11.minute = AIS_MINUTE_NOT_AVAILABLE; + // cppcheck-suppress uninitvar + (void)sscanf(timestamp, "%02uT%02u:%02uZ", + &ais->type8.dac1fid11.day, + &ais->type8.dac1fid11.hour, + &ais->type8.dac1fid11.minute); + } + imo = true; + } + else if (strstr(buf, "\"fid\":13,") != NULL) { status = json_read_object(buf, json_ais8_fid13, endptr); if (status == 0) { ais->type8.dac1fid13.fmonth = AIS_MONTH_NOT_AVAILABLE; @@ -286,7 +300,7 @@ int json_ais_read(const char *buf, status = json_read_object(buf, json_ais8_fid29, endptr); imo = true; } - else if (strstr(buf, "\"fid\":31,") != NULL || strstr(buf, "\"fid\":11,") != NULL) { + else if (strstr(buf, "\"fid\":31,") != NULL) { status = json_read_object(buf, json_ais8_fid31, endptr); if (status == 0) { ais->type8.dac1fid31.day = AIS_DAY_NOT_AVAILABLE; diff --git a/driver_ais.c b/driver_ais.c index 463b060e..9ee5783e 100644 --- a/driver_ais.c +++ b/driver_ais.c @@ -25,10 +25,15 @@ * Parse the data from the device */ +#define DAC1FID11_AIRTEMP_OFFSET 600 +#define DAC1FID11_DEWPOINT_OFFSET 200 +#define DAC1FID11_PRESSURE_OFFSET -800 +#define DAC1FID11_LEVEL_OFFSET 100 +#define DAC1FID11_WATERTEMP_OFFSET 100 + #define DAC1FID31_AIRTEMP_OFFSET 600 #define DAC1FID31_DEWPOINT_OFFSET 200 #define DAC1FID31_PRESSURE_OFFSET -800 -#define DAC1FID11_LEVEL_OFFSET 100 #define DAC1FID31_LEVEL_OFFSET 100 #define DAC1FID31_WATERTEMP_OFFSET 100 @@ -378,49 +383,47 @@ bool ais_binary_decode(struct ais_t *ais, switch (ais->type8.fid) { case 11: /* IMO236 - Meteorological/Hydrological data */ /* layout is almost identical to FID=31 from IMO289 */ - ais->type8.dac1fid31.lat = SBITS(56, 24); - ais->type8.dac1fid31.lon = SBITS(80, 25); - ais->type8.dac1fid31.accuracy = false; - ais->type8.dac1fid31.day = UBITS(105, 5); - ais->type8.dac1fid31.hour = UBITS(110, 5); - ais->type8.dac1fid31.minute = UBITS(115, 6); - ais->type8.dac1fid31.wspeed = UBITS(121, 7); - ais->type8.dac1fid31.wgust = UBITS(128, 7); - ais->type8.dac1fid31.wdir = UBITS(135, 9); - ais->type8.dac1fid31.wgustdir = UBITS(144, 9); - ais->type8.dac1fid31.airtemp = UBITS(153, 11) - - DAC1FID31_AIRTEMP_OFFSET; - ais->type8.dac1fid31.humidity = UBITS(164, 7); - ais->type8.dac1fid31.dewpoint = UBITS(171, 10) - - DAC1FID31_DEWPOINT_OFFSET; - ais->type8.dac1fid31.pressure = UBITS(181, 9) - - DAC1FID31_PRESSURE_OFFSET; - ais->type8.dac1fid31.pressuretend = UBITS(190, 2); - ais->type8.dac1fid31.visgreater = false; - ais->type8.dac1fid31.visibility = UBITS(192, 8); - ais->type8.dac1fid31.waterlevel = UBITS(200, 9) + ais->type8.dac1fid11.lat = SBITS(56, 24); + ais->type8.dac1fid11.lon = SBITS(80, 25); + ais->type8.dac1fid11.day = UBITS(105, 5); + ais->type8.dac1fid11.hour = UBITS(110, 5); + ais->type8.dac1fid11.minute = UBITS(115, 6); + ais->type8.dac1fid11.wspeed = UBITS(121, 7); + ais->type8.dac1fid11.wgust = UBITS(128, 7); + ais->type8.dac1fid11.wdir = UBITS(135, 9); + ais->type8.dac1fid11.wgustdir = UBITS(144, 9); + ais->type8.dac1fid11.airtemp = UBITS(153, 11) + - DAC1FID11_AIRTEMP_OFFSET; + ais->type8.dac1fid11.humidity = UBITS(164, 7); + ais->type8.dac1fid11.dewpoint = UBITS(171, 10) + - DAC1FID11_DEWPOINT_OFFSET; + ais->type8.dac1fid11.pressure = UBITS(181, 9) + - DAC1FID11_PRESSURE_OFFSET; + ais->type8.dac1fid11.pressuretend = UBITS(190, 2); + ais->type8.dac1fid11.visibility = UBITS(192, 8); + ais->type8.dac1fid11.waterlevel = UBITS(200, 9) - DAC1FID11_LEVEL_OFFSET; - ais->type8.dac1fid31.leveltrend = UBITS(209, 2); - ais->type8.dac1fid31.cspeed = UBITS(211, 8); - ais->type8.dac1fid31.cdir = UBITS(219, 9); - ais->type8.dac1fid31.cspeed2 = UBITS(228, 8); - ais->type8.dac1fid31.cdir2 = UBITS(236, 9); - ais->type8.dac1fid31.cdepth2 = UBITS(245, 5); - ais->type8.dac1fid31.cspeed3 = UBITS(250, 8); - ais->type8.dac1fid31.cdir3 = UBITS(258, 9); - ais->type8.dac1fid31.cdepth3 = UBITS(267, 5); - ais->type8.dac1fid31.waveheight = UBITS(272, 8); - ais->type8.dac1fid31.waveperiod = UBITS(280, 6); - ais->type8.dac1fid31.wavedir = UBITS(286, 9); - ais->type8.dac1fid31.swellheight = UBITS(295, 8); - ais->type8.dac1fid31.swellperiod = UBITS(303, 6); - ais->type8.dac1fid31.swelldir = UBITS(309, 9); - ais->type8.dac1fid31.seastate = UBITS(318, 4); - ais->type8.dac1fid31.watertemp = UBITS(322, 10) - - DAC1FID31_WATERTEMP_OFFSET; - ais->type8.dac1fid31.preciptype = UBITS(332, 3); - ais->type8.dac1fid31.salinity = UBITS(335, 9); - ais->type8.dac1fid31.ice = UBITS(344, 2); + ais->type8.dac1fid11.leveltrend = UBITS(209, 2); + ais->type8.dac1fid11.cspeed = UBITS(211, 8); + ais->type8.dac1fid11.cdir = UBITS(219, 9); + ais->type8.dac1fid11.cspeed2 = UBITS(228, 8); + ais->type8.dac1fid11.cdir2 = UBITS(236, 9); + ais->type8.dac1fid11.cdepth2 = UBITS(245, 5); + ais->type8.dac1fid11.cspeed3 = UBITS(250, 8); + ais->type8.dac1fid11.cdir3 = UBITS(258, 9); + ais->type8.dac1fid11.cdepth3 = UBITS(267, 5); + ais->type8.dac1fid11.waveheight = UBITS(272, 8); + ais->type8.dac1fid11.waveperiod = UBITS(280, 6); + ais->type8.dac1fid11.wavedir = UBITS(286, 9); + ais->type8.dac1fid11.swellheight = UBITS(295, 8); + ais->type8.dac1fid11.swellperiod = UBITS(303, 6); + ais->type8.dac1fid11.swelldir = UBITS(309, 9); + ais->type8.dac1fid11.seastate = UBITS(318, 4); + ais->type8.dac1fid11.watertemp = UBITS(322, 10) + - DAC1FID11_WATERTEMP_OFFSET; + ais->type8.dac1fid11.preciptype = UBITS(332, 3); + ais->type8.dac1fid11.salinity = UBITS(335, 9); + ais->type8.dac1fid11.ice = UBITS(344, 2); imo = true; break; case 13: /* IMO236 - Fairway closed */ @@ -1107,6 +1107,72 @@ struct ais_t size_t bitcount; /* bit count of the data */ union { char bitdata[(AIS_TYPE8_BINARY_MAX + 7) / 8]; + /* IMO236 - Meteorological-Hydrological data + * Trial message, not to be used after January 2013 + * Replaced by IMO289 (DAC 1, FID 31) + */ + struct { +#define DAC1FID11_LATLON_SCALE 1000 + int lon; /* longitude in minutes * .001 */ +#define DAC1FID11_LON_NOT_AVAILABLE 0x1FFFFFF + int lat; /* longitude in minutes * .001 */ +#define DAC1FID11_LAT_NOT_AVAILABLE 0xFFFFFF + unsigned int day; /* UTC day */ + unsigned int hour; /* UTC hour */ + unsigned int minute; /* UTC minute */ + unsigned int wspeed; /* average wind speed */ + unsigned int wgust; /* wind gust */ +#define DAC1FID11_WSPEED_NOT_AVAILABLE 127 + unsigned int wdir; /* wind direction */ + unsigned int wgustdir; /* wind gust direction */ +#define DAC1FID11_WDIR_NOT_AVAILABLE 511 + int airtemp; /* temperature, units 0.1C */ +#define DAC1FID11_AIRTEMP_NOT_AVAILABLE 1447 + unsigned int humidity; /* relative humidity, % */ +#define DAC1FID11_HUMIDITY_NOT_AVAILABLE 127 + int dewpoint; /* dew point, units 0.1C */ +#define DAC1FID11_DEWPOINT_NOT_AVAILABLE 823 + unsigned int pressure; /* air pressure, hpa */ +#define DAC1FID11_PRESSURE_NOT_AVAILABLE 1311 + unsigned int pressuretend; /* tendency */ +#define DAC1FID11_PRESSURETREND_NOT_AVAILABLE 3 + unsigned int visibility; /* units 0.1 nautical miles */ +#define DAC1FID11_VISIBILITY_NOT_AVAILABLE 255 + int waterlevel; /* decimeters */ +#define DAC1FID11_WATERLEVEL_NOT_AVAILABLE 411 + unsigned int leveltrend; /* water level trend code */ +#define DAC1FID11_LEVELTREND_NOT_AVAILABLE 3 + unsigned int cspeed; /* surface current speed in deciknots */ +#define DAC1FID11_CSPEED_NOT_AVAILABLE 255 + unsigned int cdir; /* surface current dir., degrees */ +#define DAC1FID11_CDIR_NOT_AVAILABLE 511 + unsigned int cspeed2; /* current speed in deciknots */ + unsigned int cdir2; /* current dir., degrees */ + unsigned int cdepth2; /* measurement depth, m */ +#define DAC1FID11_CDEPTH_NOT_AVAILABLE 31 + unsigned int cspeed3; /* current speed in deciknots */ + unsigned int cdir3; /* current dir., degrees */ + unsigned int cdepth3; /* measurement depth, m */ + unsigned int waveheight; /* in decimeters */ +#define DAC1FID11_WAVEHEIGHT_NOT_AVAILABLE 255 + unsigned int waveperiod; /* in seconds */ +#define DAC1FID11_WAVEPERIOD_NOT_AVAILABLE 63 + unsigned int wavedir; /* direction in degrees */ +#define DAC1FID11_WAVEDIR_NOT_AVAILABLE 511 + unsigned int swellheight; /* in decimeters */ + unsigned int swellperiod; /* in seconds */ + unsigned int swelldir; /* direction in degrees */ + unsigned int seastate; /* Beaufort scale, 0-12 */ +#define DAC1FID11_SEASTATE_NOT_AVAILABLE 15 + int watertemp; /* units 0.1deg Celsius */ +#define DAC1FID11_WATERTEMP_NOT_AVAILABLE 923 + unsigned int preciptype; /* 0-7, enumerated */ +#define DAC1FID11_PRECIPTYPE_NOT_AVAILABLE 7 + unsigned int salinity; /* units of 0.1ppt */ +#define DAC1FID11_SALINITY_NOT_AVAILABLE 511 + unsigned int ice; /* is there sea ice? */ +#define DAC1FID11_ICE_NOT_AVAILABLE 3 + } dac1fid11; /* IMO236 - Fairway Closed */ struct { char reason[20+1]; /* Reason For Closing */ @@ -1174,7 +1240,7 @@ struct ais_t #define AIS_DAC1FID29_TEXT_MAX 162 /* 920 bits of six-bit, plus NUL */ char text[AIS_DAC1FID29_TEXT_MAX]; } dac1fid29; - /* IMO236 & IMO289 - Meteorological-Hydrological data */ + /* IMO289 - Meteorological-Hydrological data */ struct { bool accuracy; /* position accuracy, <10m if true */ #define DAC1FID31_LATLON_SCALE 1000 @@ -1207,7 +1273,6 @@ struct ais_t unsigned int visibility; /* units 0.1 nautical miles */ #define DAC1FID31_VISIBILITY_NOT_AVAILABLE 127 int waterlevel; /* decimeters or cm */ -#define DAC1FID11_WATERLEVEL_NOT_AVAILABLE 4001 #define DAC1FID31_WATERLEVEL_NOT_AVAILABLE 40001 unsigned int leveltrend; /* water level trend code */ #define DAC1FID31_LEVELTREND_NOT_AVAILABLE 3 diff --git a/gpsd_json.c b/gpsd_json.c index 460c72aa..c954c9de 100644 --- a/gpsd_json.c +++ b/gpsd_json.c @@ -2058,74 +2058,63 @@ 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 */ + /* some fields have been 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), "\"lat\":%.3f,\"lon\":%.3f,", - ais->type8.dac1fid31.lat / AIS_LATLON3_SCALE, - ais->type8.dac1fid31.lon / AIS_LATLON3_SCALE); + ais->type8.dac1fid11.lat / AIS_LATLON3_SCALE, + ais->type8.dac1fid11.lon / AIS_LATLON3_SCALE); else (void)snprintf(buf + strlen(buf), buflen - strlen(buf), "\"lat\":%d,\"lon\":%d,", - ais->type8.dac1fid31.lat, - ais->type8.dac1fid31.lon); - if (ais->type8.fid == 31) - (void)snprintf(buf + strlen(buf), buflen - strlen(buf), - "\"accuracy\":%s,", - JSON_BOOL(ais->type8.dac1fid31.accuracy)); + ais->type8.dac1fid11.lat, + ais->type8.dac1fid11.lon); (void)snprintf(buf + strlen(buf), buflen - strlen(buf), "\"timestamp\":\"%02uT%02u:%02uZ\"," "\"wspeed\":%u,\"wgust\":%u,\"wdir\":%u," "\"wgustdir\":%u,\"humidity\":%u,", - ais->type8.dac1fid31.day, - ais->type8.dac1fid31.hour, - ais->type8.dac1fid31.minute, - ais->type8.dac1fid31.wspeed, - ais->type8.dac1fid31.wgust, - ais->type8.dac1fid31.wdir, - ais->type8.dac1fid31.wgustdir, - ais->type8.dac1fid31.humidity); + ais->type8.dac1fid11.day, + ais->type8.dac1fid11.hour, + ais->type8.dac1fid11.minute, + ais->type8.dac1fid11.wspeed, + ais->type8.dac1fid11.wgust, + ais->type8.dac1fid11.wdir, + ais->type8.dac1fid11.wgustdir, + ais->type8.dac1fid11.humidity); if (scaled) (void)snprintf(buf + strlen(buf), buflen - strlen(buf), - "\"airtemp\":%1f,\"dewpoint\":%1f," + "\"airtemp\":%.1f,\"dewpoint\":%.1f," "\"pressure\":%u,\"pressuretend\":\"%s\",", - ais->type8.dac1fid31.airtemp * 0.1, - ais->type8.dac1fid31.dewpoint * 0.1, - ais->type8.dac1fid31.pressure, - trends[ais->type8.dac1fid31.pressuretend]); + ais->type8.dac1fid11.airtemp * 0.1, + ais->type8.dac1fid11.dewpoint * 0.1, + ais->type8.dac1fid11.pressure, + trends[ais->type8.dac1fid11.pressuretend]); else (void)snprintf(buf + strlen(buf), buflen - strlen(buf), "\"airtemp\":%d,\"dewpoint\":%d," - "\"pressure\":%u,\"pressuretend\":%u," - "\"visgreater\":%s,", - ais->type8.dac1fid31.airtemp, - ais->type8.dac1fid31.dewpoint, - ais->type8.dac1fid31.pressure, - ais->type8.dac1fid31.pressuretend, - JSON_BOOL(ais->type8.dac1fid31.visgreater)); + "\"pressure\":%u,\"pressuretend\":%u,", + ais->type8.dac1fid11.airtemp, + ais->type8.dac1fid11.dewpoint, + ais->type8.dac1fid11.pressure, + ais->type8.dac1fid11.pressuretend); if (scaled) (void)snprintf(buf + strlen(buf), buflen - strlen(buf), "\"visibility\":%.1f,", - ais->type8.dac1fid31.visibility * 0.1); + ais->type8.dac1fid11.visibility * 0.1); else (void)snprintf(buf + strlen(buf), buflen - strlen(buf), "\"visibility\":%u,", - ais->type8.dac1fid31.visibility); + ais->type8.dac1fid11.visibility); if (!scaled) (void)snprintf(buf + strlen(buf), buflen - strlen(buf), "\"waterlevel\":%d,", - ais->type8.dac1fid31.waterlevel); - else if (ais->type8.fid == 31) - (void)snprintf(buf + strlen(buf), buflen - strlen(buf), - "\"waterlevel\":%.1f,", - ais->type8.dac1fid31.waterlevel * 0.01); + ais->type8.dac1fid11.waterlevel); else (void)snprintf(buf + strlen(buf), buflen - strlen(buf), "\"waterlevel\":%.1f,", - ais->type8.dac1fid31.waterlevel * 0.1); + ais->type8.dac1fid11.waterlevel * 0.1); if (scaled) { const char *preciptypes[] = { @@ -2138,6 +2127,11 @@ void json_aivdm_dump(const struct ais_t *ais, "reserved", "N/A", }; + const char *ice[] = { + "no", + "yes", + "N/A", + }; (void)snprintf(buf + strlen(buf), buflen - strlen(buf), "\"leveltrend\":\"%s\"," "\"cspeed\":%.1f,\"cdir\":%u," @@ -2147,26 +2141,26 @@ void json_aivdm_dump(const struct ais_t *ais, "\"swellheight\":%.1f,\"swellperiod\":%u,\"swelldir\":%u," "\"seastate\":%u,\"watertemp\":%.1f," "\"preciptype\":%s,\"salinity\":%.1f,\"ice\":%s", - trends[ais->type8.dac1fid31.leveltrend], - ais->type8.dac1fid31.cspeed * 0.1, - ais->type8.dac1fid31.cdir, - ais->type8.dac1fid31.cspeed2 * 0.1, - ais->type8.dac1fid31.cdir2, - ais->type8.dac1fid31.cdepth2, - ais->type8.dac1fid31.cspeed3 * 0.1, - ais->type8.dac1fid31.cdir3, - ais->type8.dac1fid31.cdepth3, - ais->type8.dac1fid31.waveheight * 0.1, - ais->type8.dac1fid31.waveperiod, - ais->type8.dac1fid31.wavedir, - ais->type8.dac1fid31.swellheight * 0.1, - ais->type8.dac1fid31.swellperiod, - ais->type8.dac1fid31.swelldir, - ais->type8.dac1fid31.seastate, - ais->type8.dac1fid31.watertemp * 0.1, - preciptypes[ais->type8.dac1fid31.preciptype], - ais->type8.dac1fid31.salinity * 0.1, - JSON_BOOL(ais->type8.dac1fid31.ice)); + trends[ais->type8.dac1fid11.leveltrend], + ais->type8.dac1fid11.cspeed * 0.1, + ais->type8.dac1fid11.cdir, + ais->type8.dac1fid11.cspeed2 * 0.1, + ais->type8.dac1fid11.cdir2, + ais->type8.dac1fid11.cdepth2, + ais->type8.dac1fid11.cspeed3 * 0.1, + ais->type8.dac1fid11.cdir3, + ais->type8.dac1fid11.cdepth3, + ais->type8.dac1fid11.waveheight * 0.1, + ais->type8.dac1fid11.waveperiod, + ais->type8.dac1fid11.wavedir, + ais->type8.dac1fid11.swellheight * 0.1, + ais->type8.dac1fid11.swellperiod, + ais->type8.dac1fid11.swelldir, + ais->type8.dac1fid11.seastate, + ais->type8.dac1fid11.watertemp * 0.1, + preciptypes[ais->type8.dac1fid11.preciptype], + ais->type8.dac1fid11.salinity * 0.1, + ice[ais->type8.dac1fid11.ice]); } else (void)snprintf(buf + strlen(buf), buflen - strlen(buf), "\"leveltrend\":%u," @@ -2176,27 +2170,27 @@ void json_aivdm_dump(const struct ais_t *ais, "\"waveheight\":%u,\"waveperiod\":%u,\"wavedir\":%u," "\"swellheight\":%u,\"swellperiod\":%u,\"swelldir\":%u," "\"seastate\":%u,\"watertemp\":%d," - "\"preciptype\":%u,\"salinity\":%u,\"ice\":%s", - ais->type8.dac1fid31.leveltrend, - ais->type8.dac1fid31.cspeed, - ais->type8.dac1fid31.cdir, - ais->type8.dac1fid31.cspeed2, - ais->type8.dac1fid31.cdir2, - ais->type8.dac1fid31.cdepth2, - ais->type8.dac1fid31.cspeed3, - ais->type8.dac1fid31.cdir3, - ais->type8.dac1fid31.cdepth3, - ais->type8.dac1fid31.waveheight, - ais->type8.dac1fid31.waveperiod, - ais->type8.dac1fid31.wavedir, - ais->type8.dac1fid31.swellheight, - ais->type8.dac1fid31.swellperiod, - ais->type8.dac1fid31.swelldir, - ais->type8.dac1fid31.seastate, - ais->type8.dac1fid31.watertemp, - ais->type8.dac1fid31.preciptype, - ais->type8.dac1fid31.salinity, - JSON_BOOL(ais->type8.dac1fid31.ice)); + "\"preciptype\":%u,\"salinity\":%u,\"ice\":%u", + ais->type8.dac1fid11.leveltrend, + ais->type8.dac1fid11.cspeed, + ais->type8.dac1fid11.cdir, + ais->type8.dac1fid11.cspeed2, + ais->type8.dac1fid11.cdir2, + ais->type8.dac1fid11.cdepth2, + ais->type8.dac1fid11.cspeed3, + ais->type8.dac1fid11.cdir3, + ais->type8.dac1fid11.cdepth3, + ais->type8.dac1fid11.waveheight, + ais->type8.dac1fid11.waveperiod, + ais->type8.dac1fid11.wavedir, + ais->type8.dac1fid11.swellheight, + ais->type8.dac1fid11.swellperiod, + ais->type8.dac1fid11.swelldir, + ais->type8.dac1fid11.seastate, + ais->type8.dac1fid11.watertemp, + ais->type8.dac1fid11.preciptype, + ais->type8.dac1fid11.salinity, + ais->type8.dac1fid11.ice); (void)strlcat(buf, "}\r\n", buflen - strlen(buf)); imo = true; break; @@ -2359,6 +2353,143 @@ void json_aivdm_dump(const struct ais_t *ais, json_stringify(buf1, sizeof(buf1), ais->type8.dac1fid29.text)); break; + case 31: /* IMO289 - Meteorological/Hydrological data */ + /* some fields have been merged to an ISO8601 partial date */ + /* layout is almost identical to FID=11 from IMO236 */ + if (scaled) + (void)snprintf(buf + strlen(buf), buflen - strlen(buf), + "\"lat\":%.3f,\"lon\":%.3f,", + ais->type8.dac1fid31.lat / AIS_LATLON3_SCALE, + ais->type8.dac1fid31.lon / AIS_LATLON3_SCALE); + else + (void)snprintf(buf + strlen(buf), buflen - strlen(buf), + "\"lat\":%d,\"lon\":%d,", + ais->type8.dac1fid31.lat, + ais->type8.dac1fid31.lon); + (void)snprintf(buf + strlen(buf), buflen - strlen(buf), + "\"accuracy\":%s,", + JSON_BOOL(ais->type8.dac1fid31.accuracy)); + (void)snprintf(buf + strlen(buf), buflen - strlen(buf), + "\"timestamp\":\"%02uT%02u:%02uZ\"," + "\"wspeed\":%u,\"wgust\":%u,\"wdir\":%u," + "\"wgustdir\":%u,\"humidity\":%u,", + ais->type8.dac1fid31.day, + ais->type8.dac1fid31.hour, + ais->type8.dac1fid31.minute, + ais->type8.dac1fid31.wspeed, + ais->type8.dac1fid31.wgust, + ais->type8.dac1fid31.wdir, + ais->type8.dac1fid31.wgustdir, + ais->type8.dac1fid31.humidity); + if (scaled) + (void)snprintf(buf + strlen(buf), buflen - strlen(buf), + "\"airtemp\":%1f,\"dewpoint\":%1f," + "\"pressure\":%u,\"pressuretend\":\"%s\",", + ais->type8.dac1fid31.airtemp * 0.1, + ais->type8.dac1fid31.dewpoint * 0.1, + ais->type8.dac1fid31.pressure, + trends[ais->type8.dac1fid31.pressuretend]); + else + (void)snprintf(buf + strlen(buf), buflen - strlen(buf), + "\"airtemp\":%d,\"dewpoint\":%d," + "\"pressure\":%u,\"pressuretend\":%u," + "\"visgreater\":%s,", + ais->type8.dac1fid31.airtemp, + ais->type8.dac1fid31.dewpoint, + ais->type8.dac1fid31.pressure, + ais->type8.dac1fid31.pressuretend, + JSON_BOOL(ais->type8.dac1fid31.visgreater)); + + if (scaled) + (void)snprintf(buf + strlen(buf), buflen - strlen(buf), + "\"visibility\":%.1f,", + ais->type8.dac1fid31.visibility * 0.1); + else + (void)snprintf(buf + strlen(buf), buflen - strlen(buf), + "\"visibility\":%u,", + ais->type8.dac1fid31.visibility); + if (!scaled) + (void)snprintf(buf + strlen(buf), buflen - strlen(buf), + "\"waterlevel\":%d,", + ais->type8.dac1fid31.waterlevel); + else + (void)snprintf(buf + strlen(buf), buflen - strlen(buf), + "\"waterlevel\":%.1f,", + ais->type8.dac1fid31.waterlevel * 0.01); + + if (scaled) { + const char *preciptypes[] = { + "rain", + "thunderstorm", + "freezing rain", + "mixed/ice", + "snow", + "reserved", + "reserved", + "N/A", + }; + (void)snprintf(buf + strlen(buf), buflen - strlen(buf), + "\"leveltrend\":\"%s\"," + "\"cspeed\":%.1f,\"cdir\":%u," + "\"cspeed2\":%.1f,\"cdir2\":%u,\"cdepth2\":%u," + "\"cspeed3\":%.1f,\"cdir3\":%u,\"cdepth3\":%u," + "\"waveheight\":%.1f,\"waveperiod\":%u,\"wavedir\":%u," + "\"swellheight\":%.1f,\"swellperiod\":%u,\"swelldir\":%u," + "\"seastate\":%u,\"watertemp\":%.1f," + "\"preciptype\":%s,\"salinity\":%.1f,\"ice\":%s", + trends[ais->type8.dac1fid31.leveltrend], + ais->type8.dac1fid31.cspeed * 0.1, + ais->type8.dac1fid31.cdir, + ais->type8.dac1fid31.cspeed2 * 0.1, + ais->type8.dac1fid31.cdir2, + ais->type8.dac1fid31.cdepth2, + ais->type8.dac1fid31.cspeed3 * 0.1, + ais->type8.dac1fid31.cdir3, + ais->type8.dac1fid31.cdepth3, + ais->type8.dac1fid31.waveheight * 0.1, + ais->type8.dac1fid31.waveperiod, + ais->type8.dac1fid31.wavedir, + ais->type8.dac1fid31.swellheight * 0.1, + ais->type8.dac1fid31.swellperiod, + ais->type8.dac1fid31.swelldir, + ais->type8.dac1fid31.seastate, + ais->type8.dac1fid31.watertemp * 0.1, + preciptypes[ais->type8.dac1fid31.preciptype], + ais->type8.dac1fid31.salinity * 0.1, + JSON_BOOL(ais->type8.dac1fid31.ice)); + } else + (void)snprintf(buf + strlen(buf), buflen - strlen(buf), + "\"leveltrend\":%u," + "\"cspeed\":%u,\"cdir\":%u," + "\"cspeed2\":%u,\"cdir2\":%u,\"cdepth2\":%u," + "\"cspeed3\":%u,\"cdir3\":%u,\"cdepth3\":%u," + "\"waveheight\":%u,\"waveperiod\":%u,\"wavedir\":%u," + "\"swellheight\":%u,\"swellperiod\":%u,\"swelldir\":%u," + "\"seastate\":%u,\"watertemp\":%d," + "\"preciptype\":%u,\"salinity\":%u,\"ice\":%s", + ais->type8.dac1fid31.leveltrend, + ais->type8.dac1fid31.cspeed, + ais->type8.dac1fid31.cdir, + ais->type8.dac1fid31.cspeed2, + ais->type8.dac1fid31.cdir2, + ais->type8.dac1fid31.cdepth2, + ais->type8.dac1fid31.cspeed3, + ais->type8.dac1fid31.cdir3, + ais->type8.dac1fid31.cdepth3, + ais->type8.dac1fid31.waveheight, + ais->type8.dac1fid31.waveperiod, + ais->type8.dac1fid31.wavedir, + ais->type8.dac1fid31.swellheight, + ais->type8.dac1fid31.swellperiod, + ais->type8.dac1fid31.swelldir, + ais->type8.dac1fid31.seastate, + ais->type8.dac1fid31.watertemp, + ais->type8.dac1fid31.preciptype, + ais->type8.dac1fid31.salinity, + JSON_BOOL(ais->type8.dac1fid31.ice)); + (void)strlcat(buf, "}\r\n", buflen - strlen(buf)); + imo = true; + break; } } if (!imo) diff --git a/gpsdecode.c b/gpsdecode.c index 4588649f..412c9ed4 100644 --- a/gpsdecode.c +++ b/gpsdecode.c @@ -123,12 +123,63 @@ static void aivdm_csv_dump(struct ais_t *ais, char *buf, size_t buflen) break; case 8: /* Binary Broadcast Message */ (void)snprintf(buf + strlen(buf), buflen - strlen(buf), - "%u|%u|%zd:%s", + "%u|%u", ais->type8.dac, - ais->type8.fid, - ais->type8.bitcount, - gpsd_hexdump(ais->type8.bitdata, - (ais->type8.bitcount + 7) / 8)); + ais->type8.fid); + int imo = 0; + switch(ais->type8.dac) { + case 1: /* International */ + switch(ais->type8.fid) { + case 11: /* IMO236 - Met/Hydro message */ + (void)snprintf(buf + strlen(buf), buflen - strlen(buf), + "|%d|%d|%02uT%02u:%02uZ|%u|%u|%u|%u|%d|%u|%d|%u|%u|%u|%d|%u|%u|%u|%u|%u|%u|%u|%u|%u|%u|%u|%u|%u|%u|%u|%u|%d|%u|%u|%u", + ais->type8.dac1fid11.lon, + ais->type8.dac1fid11.lat, + ais->type8.dac1fid11.day, + ais->type8.dac1fid11.hour, + ais->type8.dac1fid11.minute, + ais->type8.dac1fid11.wspeed, + ais->type8.dac1fid11.wgust, + ais->type8.dac1fid11.wdir, + ais->type8.dac1fid11.wgustdir, + ais->type8.dac1fid11.airtemp, + ais->type8.dac1fid11.humidity, + ais->type8.dac1fid11.dewpoint, + ais->type8.dac1fid11.pressure, + ais->type8.dac1fid11.pressuretend, + ais->type8.dac1fid11.visibility, + ais->type8.dac1fid11.waterlevel, + ais->type8.dac1fid11.leveltrend, + ais->type8.dac1fid11.cspeed, + ais->type8.dac1fid11.cdir, + ais->type8.dac1fid11.cspeed2, + ais->type8.dac1fid11.cdir2, + ais->type8.dac1fid11.cdepth2, + ais->type8.dac1fid11.cspeed3, + ais->type8.dac1fid11.cdir3, + ais->type8.dac1fid11.cdepth3, + ais->type8.dac1fid11.waveheight, + ais->type8.dac1fid11.waveperiod, + ais->type8.dac1fid11.wavedir, + ais->type8.dac1fid11.swellheight, + ais->type8.dac1fid11.swellperiod, + ais->type8.dac1fid11.swelldir, + ais->type8.dac1fid11.seastate, + ais->type8.dac1fid11.watertemp, + ais->type8.dac1fid11.preciptype, + ais->type8.dac1fid11.salinity, + ais->type8.dac1fid11.ice); + imo = 1; + break; + } + break; + } + if (imo == 0) + (void)snprintf(buf + strlen(buf), buflen - strlen(buf), + "|%zd:%s", + ais->type8.bitcount, + gpsd_hexdump(ais->type8.bitdata, + (ais->type8.bitcount + 7) / 8)); break; case 9: (void)snprintf(buf + strlen(buf), buflen - strlen(buf), diff --git a/jsongen.py.in b/jsongen.py.in index ef2e639b..86e21696 100644 --- a/jsongen.py.in +++ b/jsongen.py.in @@ -277,6 +277,49 @@ ais_specs = ( "stringbuffered":("data",), }, { + "initname" : "json_ais8_fid11", + "headers": ("AIS_HEADER","AIS_TYPE8",), + "structname": "ais->type8.dac1fid11", + "fieldmap":( + # fieldname type default + ('lat', 'integer', 'DAC1FID11_LAT_NOT_AVAILABLE'), + ('lon', 'integer', 'DAC1FID11_LON_NOT_AVAILABLE'), + ('timestamp', 'string', None), + ('wspeed', 'uinteger', 'DAC1FID11_WSPEED_NOT_AVAILABLE'), + ('wgust', 'uinteger', 'DAC1FID11_WSPEED_NOT_AVAILABLE'), + ('wdir', 'uinteger', 'DAC1FID11_WDIR_NOT_AVAILABLE'), + ('wgustdir', 'uinteger', 'DAC1FID11_WDIR_NOT_AVAILABLE'), + ('airtemp', 'integer', 'DAC1FID11_AIRTEMP_NOT_AVAILABLE'), + ('humidity', 'uinteger', 'DAC1FID11_HUMIDITY_NOT_AVAILABLE'), + ('dewpoint', 'integer', 'DAC1FID11_DEWPOINT_NOT_AVAILABLE'), + ('pressure', 'uinteger', 'DAC1FID11_PRESSURE_NOT_AVAILABLE'), + ('pressuretend', 'uinteger', 'DAC1FID11_PRESSURETREND_NOT_AVAILABLE'), + ('visibility', 'uinteger', 'DAC1FID11_VISIBILITY_NOT_AVAILABLE'), + ('waterlevel', 'integer', 'DAC1FID11_WATERLEVEL_NOT_AVAILABLE'), + ('leveltrend', 'uinteger', 'DAC1FID11_LEVELTREND_NOT_AVAILABLE'), + ('cspeed', 'uinteger', 'DAC1FID11_CSPEED_NOT_AVAILABLE'), + ('cdir', 'uinteger', 'DAC1FID11_CDIR_NOT_AVAILABLE'), + ('cspeed2', 'uinteger', 'DAC1FID11_CSPEED_NOT_AVAILABLE'), + ('cdir2', 'uinteger', 'DAC1FID11_CDIR_NOT_AVAILABLE'), + ('cdepth2', 'uinteger', 'DAC1FID11_CDEPTH_NOT_AVAILABLE'), + ('cspeed3', 'uinteger', 'DAC1FID11_CSPEED_NOT_AVAILABLE'), + ('cdir3', 'uinteger', 'DAC1FID11_CDIR_NOT_AVAILABLE'), + ('cdepth3', 'uinteger', 'DAC1FID11_CDEPTH_NOT_AVAILABLE'), + ('waveheight', 'uinteger', 'DAC1FID11_WAVEHEIGHT_NOT_AVAILABLE'), + ('waveperiod', 'uinteger', 'DAC1FID11_WAVEPERIOD_NOT_AVAILABLE'), + ('wavedir', 'uinteger', 'DAC1FID11_WAVEDIR_NOT_AVAILABLE'), + ('swellheight', 'uinteger', 'DAC1FID11_WAVEHEIGHT_NOT_AVAILABLE'), + ('swellperiod', 'uinteger', 'DAC1FID11_WAVEPERIOD_NOT_AVAILABLE'), + ('swelldir', 'uinteger', 'DAC1FID11_WAVEDIR_NOT_AVAILABLE'), + ('seastate', 'uinteger', 'DAC1FID11_SEASTATE_NOT_AVAILABLE'), + ('watertemp', 'integer', 'DAC1FID11_WATERTEMP_NOT_AVAILABLE'), + ('preciptype', 'uinteger', 'DAC1FID11_PRECIPTYPE_NOT_AVAILABLE'), + ('salinity', 'uinteger', 'DAC1FID11_SALINITY_NOT_AVAILABLE'), + ('ice', 'uinteger', 'DAC1FID11_ICE_NOT_AVAILABLE'), + ), + "stringbuffered":("timestamp",), + }, + { "initname" : "json_ais8_fid13", "headers": ("AIS_HEADER","AIS_TYPE8",), "structname": "ais->type8.dac1fid13", |