summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ais_json.c18
-rw-r--r--driver_ais.c89
-rw-r--r--gps.h69
-rw-r--r--gpsd_json.c289
-rw-r--r--gpsdecode.c61
-rw-r--r--jsongen.py.in43
6 files changed, 438 insertions, 131 deletions
diff --git a/ais_json.c b/ais_json.c
index 6f285a2b..1b041b4c 100644
--- a/ais_json.c
+++ b/ais_json.c
@@ -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 */
diff --git a/gps.h b/gps.h
index 44febe85..d200641d 100644
--- a/gps.h
+++ b/gps.h
@@ -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",