Java tutorial
/* 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(); } } }