dk.dma.ais.decode.DecodeTest.java Source code

Java tutorial

Introduction

Here is the source code for dk.dma.ais.decode.DecodeTest.java

Source

/* Copyright (c) 2011 Danish Maritime Authority.
 *
 * 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.
 */
package dk.dma.ais.decode;

import dk.dma.ais.binary.SixbitException;
import dk.dma.ais.message.AisMessage;
import dk.dma.ais.message.AisMessage6;
import dk.dma.ais.message.AisPositionMessage;
import dk.dma.ais.message.binary.RouteSuggestionReply;
import dk.dma.ais.packet.AisPacket;
import dk.dma.ais.packet.AisPacketReader;
import dk.dma.ais.packet.AisPacketTags;
import dk.dma.ais.proprietary.IProprietaryTag;
import dk.dma.ais.proprietary.ProprietaryFactory;
import dk.dma.ais.sentence.Abk;
import dk.dma.ais.sentence.Abm;
import dk.dma.ais.sentence.SentenceException;
import dk.dma.ais.sentence.SentenceLine;
import dk.dma.ais.sentence.Vdm;
import dk.dma.enav.model.Country;
import dk.dma.enav.model.geometry.Position;
import org.apache.commons.lang3.StringUtils;
import org.junit.Assert;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.Locale;
import java.util.function.Consumer;

public class DecodeTest {

    private static final Logger LOG = LoggerFactory.getLogger(DecodeTest.class);

    /**
     * Test the AisStreamReader class
     * 
     * Notice that inputStream could be any InputStream. TCP, file, pipe etc. For fail tolerant TCP reading use AisTcpReader
     * 
     * @throws IOException
     * @throws InterruptedException
     * 
     */
    @Test
    public void aisStreamReaderTest() throws IOException, InterruptedException {
        // Make handler instances
        BaseReportHandler baseHandler = new BaseReportHandler();
        PositionHandler posHandler = new PositionHandler();

        try (AisPacketReader r = AisPacketReader.createFromSystemResource("stream_example.txt", true)) {
            r.forEachRemainingMessage(baseHandler, posHandler);
        }

        // There should be 70 base stations in file
        Assert.assertEquals("Expected 70 base stations", 70, baseHandler.getBaseStations().size());

        Assert.assertEquals("Expected 54 base station origins", 54, baseHandler.getBaseStationOrigins().size());

    }

    /**
     * Decode all messages in a file Tries to handle proprietary messages
     * 
     * Demonstrates and tests the process of decoding lines into Vdm messages, and the decoding into AIS messages
     * 
     * @throws IOException
     */
    @Test
    public void readLoopTest() throws IOException {
        // Make a list of proprietary handlers

        // Open file
        URL url = ClassLoader.getSystemResource("stream_example.txt");
        Assert.assertNotNull(url);
        try (BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()))) {
            Assert.assertNotNull(in);
            String line;

            // Prepare message classes
            AisMessage message;
            Vdm vdm = new Vdm();
            LinkedList<IProprietaryTag> tags = new LinkedList<>();

            while ((line = in.readLine()) != null) {

                // Ignore everything else than sentences
                if (!line.startsWith("$") && !line.startsWith("!")) {
                    continue;
                }

                // Check if proprietary line
                if (ProprietaryFactory.isProprietaryTag(line)) {
                    // Try to parse with one the registered factories in
                    // META-INF/services/dk.dma.ais.proprietary.ProprietaryFactory
                    IProprietaryTag tag = ProprietaryFactory.parseTag(new SentenceLine(line));
                    if (tag != null) {
                        tags.add(tag);
                    }
                    continue;
                }

                // Handle VDM/VDO line
                try {
                    int result = vdm.parse(new SentenceLine(line));
                    // LOG.info("result = " + result);
                    if (result == 0) {
                        message = AisMessage.getInstance(vdm);
                        Assert.assertNotNull(message);
                        if (tags.size() > 0) {
                            message.setTags(tags);
                        }

                        // Message ready for handling

                    } else if (result == 1) {
                        // Wait for more data
                        continue;
                    } else {
                        LOG.error("Failed to parse line: " + line + " result = " + result);
                        Assert.assertTrue(false);
                    }

                } catch (Exception e) {
                    LOG.info("VDM failed: " + e.getMessage() + " line: " + line + " tag: "
                            + (tags.size() > 0 ? tags.peekLast() : "null"));
                    Assert.assertTrue(false);
                }

                // Create new VDM
                vdm = new Vdm();
                tags.clear();
            }
        }
    }

    @Test
    public void simpleDecodeTest() throws IOException {
        try (AisPacketReader r = AisPacketReader.createFromSystemResource("small_example.txt", true)) {
            r.forEachRemaining(new Consumer<AisPacket>() {
                public void accept(AisPacket t) {
                }
            });
        }
    }

    @Test
    public void decodeWithCommentBlocks() throws IOException {
        try (AisPacketReader r = AisPacketReader.createFromSystemResource("small_cb_example.txt", false)) {
            r.forEachRemainingMessage(new Consumer<AisMessage>() {
                public void accept(AisMessage t) {
                    System.out.println(t.getVdm().getCommentBlock());
                }
            });
        }
    }

    @Test
    public void decodeAbmTest() throws SentenceException, SixbitException {
        String sentence = "!AIABM,1,1,0,219997000,0,12,<>j?1GhlLplPD5CDP6B?=P6BF,0*5F";
        Abm abm = new Abm();
        int result = abm.parse(new SentenceLine(sentence));
        Assert.assertEquals("ABM parse failed", 0, result);
        Assert.assertEquals("Message ID wrong", 12, abm.getMsgId());
    }

    @Test
    public void decodeRouteReplyAbm() throws SentenceException, SixbitException {
        String sentence = "!AIABM,1,1,1,990219000,0,6,0200<b1,0*16";
        Abm abm = new Abm();
        int result = abm.parse(new SentenceLine(sentence));
        Assert.assertEquals("ABM parse failed", 0, result);
        AisMessage6 msg6 = (AisMessage6) abm.getAisMessage(377085000, 0, 0);
        RouteSuggestionReply routeSuggestionReply = (RouteSuggestionReply) msg6.getApplicationMessage();
        Assert.assertEquals("ABM parse failed", 1, routeSuggestionReply.getResponse());
    }

    @Test
    public void decodeAbkTest() throws Exception {
        String line = "$AIABK,219012679,B,12,1,0*1D";
        Abk abk = new Abk();
        abk.parse(new SentenceLine(line));
        Assert.assertEquals(abk.getDestination(), 219012679);
        Assert.assertEquals(abk.getChannel().charValue(), 'B');
        Assert.assertEquals(abk.getMsgId(), 12);
        Assert.assertEquals(abk.getSequence(), 1);
        Assert.assertEquals(abk.getResult().getRes(), 0);

        line = "$AIABK,,,8,3,3*54";
        abk = new Abk();
        abk.parse(new SentenceLine(line));
        Assert.assertEquals(abk.getChannel().charValue(), '\0');
        Assert.assertEquals(abk.getMsgId(), 8);
        Assert.assertEquals(abk.getSequence(), 3);
        Assert.assertEquals(abk.getResult().getRes(), 3);
    }

    // @Test
    public void makeTrackTest() throws IOException {
        // Open input stream
        // URL url = ClassLoader.getSystemResource("small_cb_example.txt");
        // Assert.assertNotNull(url);
        // InputStream inputStream = url.openStream();
        // Assert.assertNotNull(inputStream);
        String filename = "/Users/oleborup/pride_of_hull_311062900.txt";
        // String filename = "/Users/oleborup/pride_of_rotterdam_244980000.txt";
        final ArrayList<AisPositionMessage> posMessages = new ArrayList<>();

        try (FileInputStream inputStream = new FileInputStream(filename);
                AisPacketReader r = new AisPacketReader(inputStream);) {

            // Make AIS reader instance
            r.forEachRemaining(new Consumer<AisPacket>() {
                @Override
                public void accept(AisPacket packet) {
                    Date t = packet.getTimestamp();
                    if (t == null) {
                        return;
                    }
                    // Filter on country
                    AisPacketTags tags = packet.getTags();
                    if (tags == null) {
                        return;
                    }
                    Country country = tags.getSourceCountry();
                    if (country == null) {
                        return;
                    }
                    if (!country.getTwoLetter().equals("NL") && !country.getTwoLetter().equals("GB")) {
                        return;
                    }
                    AisMessage message = packet.tryGetAisMessage();
                    if (message == null || !(message instanceof AisPositionMessage)) {
                        return;
                    }
                    posMessages.add((AisPositionMessage) message);
                }
            });
        }
        System.out.println("Position messages: " + posMessages.size());

        ArrayList<String> positions = new ArrayList<>();
        Integer mmsi = null;
        Position lastPos = null;
        Position refPos = Position.create(52.58, 2.3);
        for (AisPositionMessage posMessage : posMessages) {
            Position pos = posMessage.getPos().getGeoLocation();
            if (pos == null) {
                continue;
            }
            if (refPos.rhumbLineDistanceTo(pos) > 500000) {
                continue;
            }
            if (mmsi == null) {
                mmsi = posMessage.getUserId();
            }
            if (lastPos != null) {
                // Downsample on distance
                if (lastPos.rhumbLineDistanceTo(pos) < 1000) {
                    continue;
                }
            }
            String strPos = String.format(Locale.US, "%f,%f,0", pos.getLongitude(), pos.getLatitude());
            positions.add(strPos);
            lastPos = pos;
        }

        System.out.println("Positions in KML: " + positions.size());
        StringBuilder buf = new StringBuilder();
        buf.append("<kml><Document><name>Tracks</name><open>1</open><Folder><name>" + mmsi + "</name>");
        buf.append("<Placemark><name>" + mmsi + "</name><LineString><coordinates>\n");
        buf.append(StringUtils.join(positions, " "));
        buf.append("\n</coordinates></LineString></Placemark></Folder></Document></kml>");
        try (PrintWriter out = new PrintWriter(filename + ".kml")) {
            out.print(buf);
        }
    }

    @Test
    public void testCharset() throws IOException {
        byte[] b = new byte[] { -1, '!', '\n' };
        try (AisPacketReader apr = new AisPacketReader(new ByteArrayInputStream(b))) {
            apr.readPacket();
        }
    }

}