[AIS] Fix IMO236 met/hydro message handling From: Christian Gagneraud This patch fix the message decoding and the JSON writing of the IMO236 Met/Hydro message. It adds a regression test as well. I hope to come soon with fixes for the IMO289 version. Signed-off-by: Christian Gagneraud --- driver_ais.c | 34 +++++++++++++---- gps.h | 25 +++++++++--- gpsd_json.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- www/AIVDM.txt | 2 - 4 files changed, 156 insertions(+), 21 deletions(-) diff --git a/driver_ais.c b/driver_ais.c index f1fb5be..cd464f8 100644 --- a/driver_ais.c +++ b/driver_ais.c @@ -4,10 +4,12 @@ * See the file AIVDM.txt on the GPSD website for documentation and references. * AIVDM de-armoring is handled elsewhere; this is the binary-packet driver. * - * Code for message types 1-15, 18-21, and 24 has been tested against - * live data with known-good decodings. Code for message types 16-17, - * 22-23, and 25-27 has not. The IMO special messages in types 6 and 8 - * are also untested. + * Code for message types 1-15, 18-21, and 24 has been tested against live + * data with known-good decodings. Code for message types 16-17, 22-23, and + * 25-27 has not. + * For the special IMO messages (types 6 and 8), only the following have been + * tested against know-good decodings: + * - IMO236 met/hydro message: Type=8, DAC=1, FI=11 * * This file is Copyright (c) 2010 by the GPSD project * BSD terms apply: see the file COPYING in the distribution root for details. @@ -25,8 +27,8 @@ #define DAC1FID31_AIRTEMP_OFFSET 600 #define DAC1FID31_DEWPOINT_OFFSET 200 -#define DAC1FID31_PRESSURE_OFFSET 800 -#define DAC1FID11_LEVEL_OFFSET 10 +#define DAC1FID31_PRESSURE_OFFSET -800 +#define DAC1FID11_LEVEL_OFFSET 100 #define DAC1FID31_LEVEL_OFFSET 100 #define DAC1FID31_WATERTEMP_OFFSET 100 @@ -375,7 +377,23 @@ bool ais_binary_decode(struct ais_t *ais, if (ais->type8.dac == 1) switch (ais->type8.fid) { case 11: /* IMO236 - Meteorological/Hydrological data */ - /* layout is almost identical to FID=31 from IMO289 */ + /* Layout is almost identical to FID=31 from IMO289. + * Differences between IMO236 (FID=11) and 289 (FID=31) are: + * Only in IMO289: + * - Position accuracy bit + * - Greater visibility bit + * Long/Lat: + * - IMO236: latitude comes first, followed by longitute + * - IMO289: longitude comes first, followed by latitude + * Signed vs unsigned: + * - IMO236: signedness is achived by using offset on unsigned values + * - IMO289: uses 2's complement for signed value (except water level) + * Data not available: + * - IMO236: all the bits are sets. + * - IMO289: special values are used + * Units/Precision: + * - Water level: 0.1m on 9bits for IMO236, 0.01m on 12 bits for IMO289 + */ ais->type8.dac1fid31.lat = SBITS(56, 24); ais->type8.dac1fid31.lon = SBITS(80, 25); ais->type8.dac1fid31.accuracy = false; @@ -386,7 +404,7 @@ bool ais_binary_decode(struct ais_t *ais, 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 = SBITS(153, 11) + ais->type8.dac1fid31.airtemp = UBITS(153, 11) - DAC1FID31_AIRTEMP_OFFSET; ais->type8.dac1fid31.humidity = UBITS(164, 7); ais->type8.dac1fid31.dewpoint = UBITS(171, 10) diff --git a/gps.h b/gps.h index b96e143..fd719af 100644 --- a/gps.h +++ b/gps.h @@ -1191,37 +1191,46 @@ struct ais_t #define DAC1FID31_WIND_NOT_AVAILABLE 127 unsigned int wdir; /* wind direction */ unsigned int wgustdir; /* wind gust direction */ +#define DAC1FID11_DIR_NOT_AVAILABLE 511 #define DAC1FID31_DIR_NOT_AVAILABLE 360 int airtemp; /* temperature, units 0.1C */ +#define DAC1FID11_AIRTEMP_NOT_AVAILABLE 1447 #define DAC1FID31_AIRTEMP_NOT_AVAILABLE -1084 unsigned int humidity; /* relative humidity, % */ +#define DAC1FID11_HUMIDITY_NOT_AVAILABLE 127 #define DAC1FID31_HUMIDITY_NOT_AVAILABLE 101 int dewpoint; /* dew point, units 0.1C */ +#define DAC1FID11_DEWPOINT_NOT_AVAILABLE 823 #define DAC1FID31_DEWPOINT_NOT_AVAILABLE 501 unsigned int pressure; /* air pressure, hpa */ +#define DAC1FID11_PRESSURE_NOT_AVAILABLE 1311 #define DAC1FID31_PRESSURE_NOT_AVAILABLE 511 #define DAC1FID31_PRESSURE_HIGH 402 unsigned int pressuretend; /* tendency */ #define DAC1FID31_PRESSURETREND_NOT_AVAILABLE 3 bool visgreater; /* visibility greater than */ unsigned int visibility; /* units 0.1 nautical miles */ +#define DAC1FID11_VISIBILITY_NOT_AVAILABLE 255 #define DAC1FID31_VISIBILITY_NOT_AVAILABLE 127 int waterlevel; /* decimeters or cm */ -#define DAC1FID11_WATERLEVEL_NOT_AVAILABLE 4001 +#define DAC1FID11_WATERLEVEL_NOT_AVAILABLE 411 #define DAC1FID31_WATERLEVEL_NOT_AVAILABLE 40001 unsigned int leveltrend; /* water level trend code */ #define DAC1FID31_LEVELTREND_NOT_AVAILABLE 3 - unsigned int cspeed; /* current speed in deciknots */ + unsigned int cspeed; /* surface current speed in deciknots */ #define DAC1FID31_CSPEED_NOT_AVAILABLE 255 - unsigned int cdir; /* current dir., degrees */ + 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, 0.1m */ + unsigned int cdepth2; /* measurement depth, m */ +#define DAC1FID11_CDEPTH_NOT_AVAILABLE 31 #define DAC1FID31_CDEPTH_NOT_AVAILABLE 301 unsigned int cspeed3; /* current speed in deciknots */ unsigned int cdir3; /* current dir., degrees */ - unsigned int cdepth3; /* measurement depth, 0.1m */ + unsigned int cdepth3; /* measurement depth, m */ unsigned int waveheight; /* in decimeters */ +#define DAC1FID11_HEIGHT_NOT_AVAILABLE 255 #define DAC1FID31_HEIGHT_NOT_AVAILABLE 31 unsigned int waveperiod; /* in seconds */ #define DAC1FID31_PERIOD_NOT_AVAILABLE 63 @@ -1232,9 +1241,11 @@ struct ais_t unsigned int seastate; /* Beaufort scale, 0-12 */ #define DAC1FID31_SEASTATE_NOT_AVAILABLE 15 int watertemp; /* units 0.1deg Celsius */ -#define DAC1FID31_PRECIPTYPE_NOT_AVAILABLE 7 +#define DAC1FID11_WATERTEMP_NOT_AVAILABLE 923 unsigned int preciptype; /* 0-7, enumerated */ - unsigned int salinity; /* units of 0.1% */ +#define DAC1FID31_PRECIPTYPE_NOT_AVAILABLE 7 + unsigned int salinity; /* units of 0.1ppt */ +#define DAC1FID11_SALINITY_NOT_AVAILABLE 511 #define DAC1FID31_SALINITY_NOT_AVAILABLE 510 bool ice; /* is there sea ice? */ } dac1fid31;