Giter Site home page Giter Site logo

tbsalling / aismessages Goto Github PK

View Code? Open in Web Editor NEW
151.0 22.0 65.0 821 KB

AISmessages is a Java-based light-weight, zero-dependency, and ultra-efficient message decoder for maritime navigation and safety messages compliant with ITU 1371 (NMEA armoured AIS messages). A live demo of AISmessages is available on http://ais.tbsalling.dk.

Home Page: https://github.com/tbsalling/aismessages/wiki

License: Other

Java 100.00%

aismessages's People

Contributors

besuikerd avatar chenzhang22 avatar dependabot[bot] avatar dieforfree avatar ftence avatar gildegoma avatar hbs avatar imilad avatar m0r13n avatar pedrolopes10 avatar pthariensflame avatar tbsalling avatar yipeng avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

aismessages's Issues

BinaryBroadcastMessage aren't correctly decoded

!AIVDM,1,1,,B,84QjLb1Kf9pf<SwKAO4t2km7Hk:d=m2hq;rPtVJosMCFfTkrNkcf,0*39

http://www.maritec.co.za/tools/aisvdmvdodecoding/ decode:

Field Value
DAC 366
FI 56

http://www.aggsoft.com/ais-decoder.htm decode:

Field Value
Application ID 23480

Wich is 0x5BB8

0x5BB8 >> 0x08 = 0x16E = 366 (DAC)
0x5BB8 && 0x3F = 0x038 =  56 (FI)

http://ais.tbsalling.dk decode:

Field Value
DAC 1467
FI 8

… which is different from previous results.

DAC 1467 is not documented on the web.
DAC 366 FI 56 are referenced in this talk: https://en.wikipedia.org/wiki/Talk:Automatic_identification_system#Military_vessels

For the US "blue force" transmissions, they are done with type 8 messages, DAC 366, and FIDs 56 (256 bytes) and 57 (512 bytes). These are sent not only by military vessels, but also Homeland Security (USCG) and law enforcement vessels.

Also, getBinaryData() return only the first 4 bits of the data.

Validate NMEA checksum

The NMEA checksum can be used to check for transmission errors. It would be nice to include a validation of the checksum against the message body in the NMEAMessage.isValid() method.

Call to AISMessage#dataFields is slow

The reason is that dataFields uses introspection to determine the various fields and in the process calls the method isComplex which calls Class.getPackage which is slowing the overall execution.

Calls to getPackage should be replaced by something less resource hungry.

NPE

在 AISMessage.java 方法 decodePayloadToBitString
会调用 NMEAMessage.java 内的 方法getFillBits可能出现空指针异常

`
protected static String decodePayloadToBitString(NMEAMessage... nmeaMessages) {
StringBuilder sixBitEncodedPayload = new StringBuilder();
int fillBits = -1;
for (int i = 0; i < nmeaMessages.length; i++) {
NMEAMessage m = nmeaMessages[i];
sixBitEncodedPayload.append(m.getEncodedPayload());
if (i == nmeaMessages.length - 1) {
fillBits = m.getFillBits();//may be throw NPE
}
}

    // The AIS message payload stored as a string of 0's and 1's
    return toBitString(sixBitEncodedPayload.toString(), fillBits);
}

`

UnsupportedMessageType : $AIALR

I'm receiving the error UnsupportedMessageType: $AIALR when trying this code:

NMEAMessageHandler aisMessageReceiver = new NMEAMessageHandler("TEST", new MessageConsumer() );
NMEAMessage message = NMEAMessage.fromString( "$AIALR,185615.00,025,A,V,AIS: external EPFS lost*23");
aisMessageReceiver.accept( message );

The trace:

$AIALR,185615.00,025,A,V,AIS: external EPFS lost*23
dk.tbsalling.aismessages.nmea.exceptions.UnsupportedMessageType: $AIALR
	at dk.tbsalling.aismessages.nmea.messages.NMEAMessage.validate(NMEAMessage.java:134)
	at dk.tbsalling.aismessages.nmea.messages.NMEAMessage.<init>(NMEAMessage.java:124)
	at dk.tbsalling.aismessages.nmea.messages.NMEAMessage.fromString(NMEAMessage.java:47)

AidToNavigationReport issue with Name of "Aid-to- Navigation Extension" parameter

I was getting index out of bounds exceptions in the method fromEncodedMessage when trying to create the nameExtension,

According to http://www.navcen.uscg.gov/pdf/AIS/ITU-R_M1371-3_AIS_Msg_21.pdf this parameter can vary in size. I adjusted it to use the getNumberOfBits() to determine the size.

String nameExtension = DecoderImpl.convertToString(encodedMessage.getBits(272, encodedMessage.getNumberOfBits())); //361

Not sure if there are other message types that have parameters like this. If so I would have copied that code.

Incorrect SpeedOverGround?

Hi,
I've been using your online decoder today, and have just had an unexpected result:
!AIVDM,1,1,,B,C69DqeP0Ar8;JH3R6<4O7wWPl@:62L>jcaQgh0000000?104222P,0*32
is reporting Speed as 3.5, but I think (based on trying a couple of other decoders) that it should be 7.1?
I've already been through several Type 1/2/3 messages without a problem - this was the first Type 19 I've tried so far.

fails to compile on Ubuntu 14.04 and Windows 7

synopsis:

Project fails to build with maven 3 on both Ubuntu 14.04 and Win7. Attempted fix listed here to no effect: http://stackoverflow.com/questions/15886209/maven-is-not-working-in-java-8-when-javadoc-tags-are-incomplete. Attempted build via trimed down pom, also to no effect.

version info:

Apache Maven 3.0.5
Maven home: /usr/share/maven
Java version: 1.8.0_20, vendor: Oracle Corporation
Java home: /usr/lib/jvm/java-8-oracle/jre
Default locale: en_US, platform encoding: UTF-8
OS name: "linux", version: "3.11.0-19-generic", arch: "amd64", family: "unix"

(behaviour is the same regardless of linux or Win7)

maven dump:

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building aismessages 2.0.0-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ aismessages ---
[INFO] Deleting /home/dholiday/MDA-Stuff/aismessages/aismessages/target
[INFO]
[INFO] --- maven-enforcer-plugin:1.0:enforce (enforce-maven) @ aismessages ---
[INFO]
[INFO] --- maven-resources-plugin:2.3:resources (default-resources) @ aismessages ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ aismessages ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 54 source files to /home/dholiday/MDA-Stuff/aismessages/aismessages/target/classes
An exception has occurred in the compiler (1.8.0_20). Please file a bug at the Java Developer Connection (http://java.sun.com/webapps/bugreport) after checking the Bug Parade for duplicates. Include your program and the following diagnostic in your report. Thank you.
java.lang.NullPointerException
at com.sun.tools.javac.code.Types.isConvertible(Types.java:290)
at com.sun.tools.javac.comp.Check.assertConvertible(Check.java:922)
at com.sun.tools.javac.comp.Check.checkMethod(Check.java:876)
at com.sun.tools.javac.comp.Attr.checkMethod(Attr.java:3838)
at com.sun.tools.javac.comp.Attr.checkIdInternal(Attr.java:3615)
at com.sun.tools.javac.comp.Attr.checkMethodIdInternal(Attr.java:3522)
at com.sun.tools.javac.comp.Attr.checkMethodId(Attr.java:3501)
at com.sun.tools.javac.comp.Attr.checkId(Attr.java:3488)
at com.sun.tools.javac.comp.Attr.visitIdent(Attr.java:3237)
at com.sun.tools.javac.tree.JCTree$JCIdent.accept(JCTree.java:2011)
at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:607)
at com.sun.tools.javac.comp.Attr.visitApply(Attr.java:1843)
at com.sun.tools.javac.tree.JCTree$JCMethodInvocation.accept(JCTree.java:1465)
at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:607)
at com.sun.tools.javac.comp.Attr.visitReturn(Attr.java:1704)
at com.sun.tools.javac.tree.JCTree$JCReturn.accept(JCTree.java:1384)
at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:607)
at com.sun.tools.javac.comp.Attr.attribStat(Attr.java:676)
at com.sun.tools.javac.comp.Attr.attribStats(Attr.java:692)
at com.sun.tools.javac.comp.Attr.visitBlock(Attr.java:1142)
at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:909)
at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:607)
at com.sun.tools.javac.comp.Attr.attribStat(Attr.java:676)
at com.sun.tools.javac.comp.Attr.visitMethodDef(Attr.java:1035)
at com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:778)
at com.sun.tools.javac.comp.Attr.attribTree(Attr.java:607)
at com.sun.tools.javac.comp.Attr.attribStat(Attr.java:676)
at com.sun.tools.javac.comp.Attr.attribClassBody(Attr.java:4342)
at com.sun.tools.javac.comp.Attr.attribClass(Attr.java:4252)
at com.sun.tools.javac.comp.Attr.attribClass(Attr.java:4181)
at com.sun.tools.javac.comp.Attr.attrib(Attr.java:4156)
at com.sun.tools.javac.main.JavaCompiler.attribute(JavaCompiler.java:1248)
at com.sun.tools.javac.main.JavaCompiler.compile2(JavaCompiler.java:901)
at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:860)
at com.sun.tools.javac.main.Main.compile(Main.java:523)
at com.sun.tools.javac.api.JavacTaskImpl.doCall(JavacTaskImpl.java:129)
at com.sun.tools.javac.api.JavacTaskImpl.call(JavacTaskImpl.java:138)
at org.codehaus.plexus.compiler.javac.JavaxToolsCompiler.compileInProcess(JavaxToolsCompiler.java:126)
at org.codehaus.plexus.compiler.javac.JavacCompiler.performCompile(JavacCompiler.java:169)
at org.apache.maven.plugin.compiler.AbstractCompilerMojo.execute(AbstractCompilerMojo.java:785)
at org.apache.maven.plugin.compiler.CompilerMojo.execute(CompilerMojo.java:129)
at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:209)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)
at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)
at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183)
at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161)
at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:320)
at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:156)
at org.apache.maven.cli.MavenCli.execute(MavenCli.java:537)
at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:196)
at org.apache.maven.cli.MavenCli.main(MavenCli.java:141)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:289)
at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:229)
at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:415)
at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:356)
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR] An unknown compilation problem occurred
[INFO] 1 error
[INFO] -------------------------------------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.204s
[INFO] Finished at: Fri Oct 10 15:17:55 PDT 2014
[INFO] Final Memory: 16M/266M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project aismessages: Compilation failure
[ERROR] An unknown compilation problem occurred
[ERROR] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoFailureException

Validate minimum message length when decoding a message

Whenever fields of a message are decoded, the getBits call can fail whenever the AIS message that was decoded did not meet the expected minimum length of a message with a StringIndexOutOfBoundsException. At use site there is also no way to check what the message length is, since this field is private.

It would be nice to either have access to the message length or have proper validation. I can see there already is a checkAISMessage with an empty body

Receiving invalid AIS Message while it can be decoded using another decoder.

Actually I am trying to migrate from AisDecoder (ArunDale) to your library. I never got and error using AisDecoder, it can decode all the Satellite AIS stream I have with 0 rejected / error from millions data received.

Using your library, I always got these kind of error:

Oct 10, 2022 2:50:10 PM dk.tbsalling.aismessages.nmea.NMEAMessageInputStreamReader run
WARNING: Received invalid AIS message: "\s:rORBCOMM999,c:1665388207*26\!AIVDM,1,1,,,H8Ih`40l58hTr0AD622222222200,2*4E"
Oct 10, 2022 2:50:13 PM dk.tbsalling.aismessages.nmea.NMEAMessageInputStreamReader run
WARNING: Received invalid AIS message: "\g:2-2-1089*5D\!AIVDM,2,2,7,,mWVP0@@;ONOeD,0*08"
Oct 10, 2022 2:50:16 PM dk.tbsalling.aismessages.nmea.NMEAMessageInputStreamReader run
WARNING: Received invalid AIS message: "\s:rORBCOMM999,c:1665388213*23\!AIVDM,1,1,,,H7tD750e=210U<<E>22222222200,2*6F"
Oct 10, 2022 2:50:16 PM dk.tbsalling.aismessages.nmea.NMEAMessageInputStreamReader run
WARNING: Received invalid AIS message: "\g:2-2-1142*5B\!AIVDM,2,2,0,,689P000<<@OeD,0*2E"
Oct 10, 2022 2:50:18 PM dk.tbsalling.aismessages.nmea.NMEAMessageInputStreamReader run
WARNING: Received invalid AIS message: "\s:rORBCOMM999,c:1665388218*28\!AIVDM,1,1,,,H7tKep@H>0u8<PTB222222222200,2*01"
Oct 10, 2022 2:50:18 PM dk.tbsalling.aismessages.nmea.NMEAMessageInputStreamReader run
WARNING: Received invalid AIS message: "\s:rORBCOMM999,c:1665388216*26\!AIVDM,1,1,,,H7tKep@H>0u8<PTB222222222200,2*01"
Oct 10, 2022 2:50:20 PM dk.tbsalling.aismessages.nmea.NMEAMessageInputStreamReader run
WARNING: Received invalid AIS message: "\s:rORBCOMM999,c:1665388217*27\!AIVDM,1,1,,,H8HugK0QB08D59=>222222222200,2*64"

And often after some errors, no data will be processed anymore. Is there any way to analyze those error? Because it is almost impossible to look for causes using only those WARNING.

I tried to decode it using another tools i.e. maritec and aggsoft

Invalid Message error, but mesage seems valid

I'm receiving this error for some message:

Message does not comply with regexp "^!.*\*[0-9A-Fa-f]{2}$": <MESSAGE>

This is some examples (not same pack):

!AIVDM,1,1,,A,3:U70chP@7LrG1SjrgmKF8uh00vP,0*56
!AIVDM,1,1,,B,33n4qd5000LrA8ejqcN9DjqF0Dg:,0*72
!AIVDM,1,1,,A,1:U8Qv07@2trCMWjs8IMK73b06@@,0*43

Invalid message

Having trouble with this vessel-generated message:
!AIVDM,1,1,,B,H3m9T21HTe<H`u8B22222222220,0*0F

Code:

    String msg = "!AIVDM,1,1,,B,H3m9T21HTe<H`u8B22222222220,0*0F";
    NMEAMessage nmeaMessage = NMEAMessage.fromString(msg);
    AISMessage aisMessage = AISMessage.create(nmeaMessage);

I get this exception from AISMessage.create():
dk.tbsalling.aismessages.nmea.exceptions.InvalidMessage: Message of type ClassBCSStaticDataReport should be exactly 158, 160 or 168 bits long; not 162. Assumed sourceMmsi: 257057800.

MMSI, IMO should be a String

If we look how AIS data will be used, I don't think it is good idea to declare MMSI and IMO as an Integer. Will be better if it declared as String.

Often, AIS data has been compromised and there is possibility to have MMSI and IMO that not fulfill the standard.

It is highly possible we catch an AIS data starting with 0, but it is not a coastal station nor group of a ships, e.g 012345678.
I just worried if it declared as Integer, it will be shrunk to "12345678" because of leading zero in Integer is meaningless. And we will get wrong MID is we use that shrunk MMSI.

Request for adding UDP receiver

Thanks for your excellent job.
I just request to add udp receiver into your work.
...

package dk.tbsalling.aismessages.nmea;

import java.io.IOException;
import java.io.InputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.function.Consumer;
import java.util.logging.Logger;

import dk.tbsalling.aismessages.nmea.messages.NMEAMessage;

public class NMEAMessageUDPSocket {

private static final Logger log = Logger.getLogger(NMEAMessageSocketClient.class.getName());

@SuppressWarnings("unused")
private NMEAMessageUDPSocket() {
    this.nmeaMessageConsumer = null;
    this.host = null;
    this.port = null;
}

public NMEAMessageUDPSocket(String host, Integer port, Consumer<? super NMEAMessage> nmeaMessageConsumer) throws UnknownHostException {
    this.host = host;
    this.port = port;
    this.nmeaMessageConsumer = nmeaMessageConsumer;
}

public void requestStop() {
    if (streamReader != null)
        streamReader.requestStop();
}

public void run() throws IOException {
    log.info("NMEAMessageUDPSockerServer running.");
    UDPInputStream udpStream = new UDPInputStream(host, port);
    log.info("Connected to AIS server on " + host);
    streamReader = new NMEAMessageInputStreamReader(udpStream, nmeaMessageConsumer);
    streamReader.run();
    // TODO: Close socket
    log.info("NMEAMessageUDPSockerServer stopping.");
}

private NMEAMessageInputStreamReader streamReader;
private final String host;
private final Integer port;
private final Consumer<? super NMEAMessage> nmeaMessageConsumer;


/*
Copyright 2007 Creare Inc.

Licensed under the Apache License, Version 2.0 (the "License"); 
you may not use this file except in compliance with the License. 
You may obtain a copy of the License at 

http://www.apache.org/licenses/LICENSE-2.0 

Unless required by applicable law or agreed to in writing, software 
distributed under the License is distributed on an "AS IS" BASIS, 
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
See the License for the specific language governing permissions and 
limitations under the License.
*/

/*
  *****************************************************************
  ***                ***
  ***  Name :  UDPInputStream                                 ***
  ***  By   :  U. Bergstrom   (Creare Inc., Hanover, NH)  ***
  ***  For  :  E-Scan            ***
  ***  Date :  October, 2001          ***
  ***                ***
  ***  Copyright 2001 Creare Inc.        ***
  ***  All Rights Reserved          ***
  ***                ***
  ***  Description :            ***
  ***       This class extends InputStream, providing its API   ***
  ***   for calls to a UDPSocket.                               ***
  ***                ***
  *****************************************************************
*/  
public class UDPInputStream extends InputStream {

    private static final int PACKET_BUFFER_SIZE = 5000;

    DatagramSocket dsock = null;
    DatagramPacket dpack = null;

    byte[] ddata = new byte[PACKET_BUFFER_SIZE];
    int packSize = 0;
    int packIdx = 0;

    int value;

    /********************** constructors ********************/
    /*
    *****************************************************************
    ***                ***
    ***  Name :  UDPInputStream                                 ***
    ***  By   :  U. Bergstrom   (Creare Inc., Hanover, NH)  ***
    ***  For  :  E-Scan            ***
    ***  Date :  October, 2001          ***
    ***                ***
    ***  Copyright 2001 Creare Inc.        ***
    ***  All Rights Reserved          ***
    ***                ***
    ***  Description :            ***
    ***       Default constructor.                                ***
    ***                ***
    *****************************************************************
    */
    public UDPInputStream() {}

    /*
    *****************************************************************
    ***                ***
    ***  Name :  UDPInputStream                                 ***
    ***  By   :  U. Bergstrom   (Creare Inc., Hanover, NH)  ***
    ***  For  :  E-Scan            ***
    ***  Date :  October, 2001          ***
    ***                ***
    ***  Copyright 2001 Creare Inc.        ***
    ***  All Rights Reserved          ***
    ***                ***
    ***  Description :            ***
    ***       Constructor.  Requires the address and port of the  ***
    ***   UDP socket to read from.                                ***
    ***                ***
    *****************************************************************
    */
    public UDPInputStream(String address, int port) 
    throws UnknownHostException, SocketException {

    open(address, port);
    }

    /************ opening and closing the stream ************/
    /*
    *****************************************************************
    ***                ***
    ***  Name :  open                                             ***
    ***  By   :  U. Bergstrom   (Creare Inc., Hanover, NH)  ***
    ***  For  :  E-Scan            ***
    ***  Date :  October, 2001          ***
    ***                ***
    ***  Copyright 2001 Creare Inc.        ***
    ***  All Rights Reserved          ***
    ***                ***
    ***  Description :            ***
    ***       The user may use this method to set the address and ***
    ***   port of the UDP socket to read from.                    ***
    ***                ***
    *****************************************************************
    */
    public void open(String address, int port)
    throws UnknownHostException, SocketException {
        dsock = new DatagramSocket(port, InetAddress.getByName(address));
    }

    /*
    *****************************************************************
    ***                ***
    ***  Name :  close                                       ***
    ***  By   :  U. Bergstrom   (Creare Inc., Hanover, NH)  ***
    ***  For  :  E-Scan            ***
    ***  Date :  October, 2001          ***
    ***                ***
    ***  Copyright 2001 Creare Inc.        ***
    ***  All Rights Reserved          ***
    ***                ***
    ***  Description :            ***
    ***       Close the UDP socket and UDPInputStream.            ***
    ***                ***
    *****************************************************************
    */
    public void close() throws IOException {
        dsock.close();
        dsock = null;
        ddata = null;
        packSize = 0;
        packIdx = 0;
    }

    /****** reading, skipping and checking available data ******/
    /*
    *****************************************************************
    ***                ***
    ***  Name :  available                                 ***
    ***  By   :  U. Bergstrom   (Creare Inc., Hanover, NH)  ***
    ***  For  :  E-Scan            ***
    ***  Date :  October, 2001          ***
    ***                ***
    ***  Copyright 2001 Creare Inc.        ***
    ***  All Rights Reserved          ***
    ***                ***
    ***  Description :            ***
    ***       Determines how many more values may be read before  ***
    ***   next blocking read.                                     ***
    ***                ***
    *****************************************************************
    */
    public int available() throws IOException {
        return packSize - packIdx;
    }

    /*
    *****************************************************************
    ***                ***
    ***  Name :  read()                                     ***
    ***  By   :  U. Bergstrom   (Creare Inc., Hanover, NH)  ***
    ***  For  :  E-Scan            ***
    ***  Date :  October, 2001          ***
    ***                ***
    ***  Copyright 2001 Creare Inc.        ***
    ***  All Rights Reserved          ***
    ***                ***
    ***  Description :            ***
    ***       Reads the next value available.  Returns the value  ***
    ***   as an integer from 0 to 255.                            ***
    ***                ***
    *****************************************************************
    */
    public int read() throws IOException {
        if (packIdx == packSize) {
         receive();
        }

        value = ddata[packIdx] & 0xff;
        packIdx++;
        return value;
        }

    /*
    *****************************************************************
    ***                ***
    ***  Name :  read(byte[])                                 ***
    ***  By   :  U. Bergstrom   (Creare Inc., Hanover, NH)  ***
    ***  For  :  E-Scan            ***
    ***  Date :  October, 2001          ***
    ***                ***
    ***  Copyright 2001 Creare Inc.        ***
    ***  All Rights Reserved          ***
    ***                ***
    ***  Description :            ***
    ***       Reads the next buff.length values into the input    ***
    ***   byte array, buff.                                       ***
    ***                ***
    *****************************************************************
    */
    public int read(byte[] buff) throws IOException {
        return read(buff, 0, buff.length);
    }

    /*
    *****************************************************************
    ***                ***
    ***  Name :  read(byte[], int, int)                         ***
    ***  By   :  U. Bergstrom   (Creare Inc., Hanover, NH)  ***
    ***  For  :  E-Scan            ***
    ***  Date :  October, 2001          ***
    ***                ***
    ***  Copyright 2001 Creare Inc.        ***
    ***  All Rights Reserved          ***
    ***                ***
    ***  Description :            ***
    ***       Reads the next len values into the input byte array,***
    ***   buff, starting at offset off.                           ***
    ***                ***
    *****************************************************************
    */
    public int read(byte[] buff, int off, int len) throws IOException {
        if (packIdx == packSize) {
         receive();
        }

        int lenRemaining = len;

        while(available() < lenRemaining) {
         System.arraycopy(ddata,
              packIdx,
              buff,
              off + (len - lenRemaining),
              available());
         lenRemaining -= available();
         receive();
        }

        System.arraycopy(ddata,
          packIdx,
          buff,
          off + (len - lenRemaining),
          lenRemaining);
        packIdx += lenRemaining;
        return len;
    }

    /*
    *****************************************************************
    ***                ***
    ***  Name :  skip                                       ***
    ***  By   :  U. Bergstrom   (Creare Inc., Hanover, NH)  ***
    ***  For  :  E-Scan            ***
    ***  Date :  October, 2001          ***
    ***                ***
    ***  Copyright 2001 Creare Inc.        ***
    ***  All Rights Reserved          ***
    ***                ***
    ***  Description :            ***
    ***       Skips over the next len values.                     ***
    ***                ***
    *****************************************************************
    */
    public long skip(long len) throws IOException {
        if (packIdx == packSize) {
         receive();
        }

        long lenRemaining = len;

        while(available() < lenRemaining) {
         lenRemaining -= available();
         receive();
        }

        packIdx += (int) lenRemaining;
        return len;
    }

    /****************** receiving more data ******************/
    /*
    *****************************************************************
    ***                ***
    ***  Name :  receive                                    ***
    ***  By   :  U. Bergstrom   (Creare Inc., Hanover, NH)  ***
    ***  For  :  E-Scan            ***
    ***  Date :  October, 2001          ***
    ***                ***
    ***  Copyright 2001 Creare Inc.        ***
    ***  All Rights Reserved          ***
    ***                ***
    ***  Description :            ***
    ***       A blocking read to receive more data from the UDP   ***
    ***   socket.                                                 ***
    ***                ***
    *****************************************************************
    */
    private void receive() throws IOException {
        dpack = new DatagramPacket(ddata, PACKET_BUFFER_SIZE);
        dsock.receive(dpack);
        packIdx = 0;
        packSize = dpack.getLength();
    }

    /********* marking and reseting are unsupported ********/
    public void mark(int readlimit) {}

    public void reset() throws IOException {
        throw new IOException("Marks are not supported by UDPInputStream.");
    }

    public boolean markSupported() {
        return false;
    }

}   

}

Lots of Error Processing Fragmented Message

I received a lot of error when handling fragmented message e.g.:

Oct 13, 2022 8:58:30 AM dk.tbsalling.aismessages.nmea.NMEAMessageInputStreamReader run
WARNING: Received invalid AIS message: "\g:2-2-6291*51\!AIVDM,2,2,3,,88888888HsgOPl58Tp60lt8ThF0000000,2*3C"
Oct 13, 2022 8:58:38 AM dk.tbsalling.aismessages.nmea.NMEAMessageInputStreamReader run
WARNING: Received invalid AIS message: "\g:2-2-6333*58\!AIVDM,2,2,5,,0s1,0*20"
Oct 13, 2022 9:00:01 AM dk.tbsalling.aismessages.nmea.NMEAMessageInputStreamReader run
WARNING: Received invalid AIS message: "\g:2-2-6902*50\!AIVDM,2,2,4,,Q@000018HsFfgP017JvRt0g@u:MOwp0PSm,2*4A"
Oct 13, 2022 9:00:12 AM dk.tbsalling.aismessages.nmea.NMEAMessageInputStreamReader run
WARNING: Received invalid AIS message: "\g:2-2-6967*53\!AIVDM,2,2,9,,00000008Ht6P?P3`7JO5J0cld;F?vJ0PS2,2*5B"
Oct 13, 2022 9:00:14 AM dk.tbsalling.aismessages.nmea.NMEAMessageInputStreamReader run
WARNING: Received invalid AIS message: "\g:2-2-6994*5F\!AIVDM,2,2,6,,ng60gHnm2D;p2d<O,0*6A"

I guess the API cannot find the first fragment. Any suggestion where I have to start analysing the code?

Course Over Ground valued 511

Is it possible that this library produce Course Over Ground with value 511?

I found that values in my application, checked all logic and found nothing incorect in my code.

As far as I know, value 511 is only valid in Heading Sensor (true heading) data, which mean "no heading sensor". It is not applied to course over ground. CMIIW

NMEAMessage will not handle messages that use comment blocks

If trying to decode a message that begins with a comment block /.../!AIVDM,1,1,,B,15MvlfPOh2G?nwbEdVDsnSTR00S?,0*41 the regex will fail.

I am not sure how to decode the comment block so as a workaround I was just skipping it.

private NMEAMessage(String rawMessage) {
// !AIVDM,1,1,,B,15MvlfPOh2G?nwbEdVDsnSTR00S?,0*41

    // Will not handle comment block \...\
    rawMessage = rawMessage.substring(rawMessage.indexOf('!'));

    final String nmeaMessageRegExp = "^!.*\\*[0-9A-Fa-f]{2}$";

AISMessage does not properly implement equality in the presence of metadata

AISMessage does not properly implement equality (and hashcode etc) because Metadata does not implement equality

Example:

String source = "test";
Instant time = Instant.now();
String nmea = NMEAMessage.fromString("!AIVDM,1,1,,A,13aEOK?P00PD2wVMdLDRhgvL289?,0*26");

Metadata meta1 = new Metadata(source, time);
Metadata meta2 = new Metadata(source, time);

AISMessage ais1 = AISMessage.create(meta1, nmea);
AISMessage ais2 = AISMessage.create(meta2, nmea);

// Is false, expected true
meta1.equals(meta2);
ais1.equals(ais2);

Open question: is the same AIS message (NMEA strings) equal if the metadata is different?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.