From c3ed30019cab1b8826d8b8a52f04c0b5a2091b36 Mon Sep 17 00:00:00 2001 From: fjc40 Date: Sat, 5 Aug 2017 22:11:54 +1200 Subject: [PATCH] Added BoatLocationEncoder. Updated BoatLocationDecoder test to use new encoder. Updated MockOutput to use new encoder. It logs a warning if encoding fails. #story[1095] --- .../src/main/java/mock/app/MockOutput.java | 24 ++++-- .../MessageEncoders/BoatLocationEncoder.java | 83 +++++++++++++++++++ .../MessageEncoders/EncoderFactory.java | 2 + .../RaceVisionByteEncoder.java | 50 ----------- .../BoatLocationDecoderTest.java | 45 ++++++++-- 5 files changed, 140 insertions(+), 64 deletions(-) create mode 100644 racevisionGame/src/main/java/network/MessageEncoders/BoatLocationEncoder.java diff --git a/racevisionGame/src/main/java/mock/app/MockOutput.java b/racevisionGame/src/main/java/mock/app/MockOutput.java index aff0947e..b773a06a 100644 --- a/racevisionGame/src/main/java/mock/app/MockOutput.java +++ b/racevisionGame/src/main/java/mock/app/MockOutput.java @@ -3,6 +3,7 @@ package mock.app; import network.BinaryMessageEncoder; +import network.Exceptions.InvalidMessageException; import network.MessageEncoders.RaceVisionByteEncoder; import network.Messages.*; import network.Messages.Enums.MessageType; @@ -13,6 +14,8 @@ import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; +import java.util.logging.Level; +import java.util.logging.Logger; /** * TCP server to send race information to connected clients. @@ -158,12 +161,13 @@ public class MockOutput implements Runnable * Encodes/serialises a BoatLocation message, and returns it. * @param boatLocation The BoatLocation message to serialise. * @return The BoatLocation message in a serialised form. + * @throws InvalidMessageException If the message cannot be encoded. */ - private synchronized byte[] parseBoatLocation(BoatLocation boatLocation){ + private synchronized byte[] parseBoatLocation(BoatLocation boatLocation) throws InvalidMessageException { //Encodes the message. - byte[] encodedBoatLoc = RaceVisionByteEncoder.boatLocation(boatLocation); + byte[] encodedBoatLoc = RaceVisionByteEncoder.encode(boatLocation); //Encodes the full message with header. BinaryMessageEncoder binaryMessageEncoder = new BinaryMessageEncoder( @@ -277,11 +281,19 @@ public class MockOutput implements Runnable BoatLocation boatLocation = this.latestMessages.getBoatLocation(sourceID); if (boatLocation != null) { - //Encode. - byte[] boatLocationBlob = this.parseBoatLocation(boatLocation); - //Write it. - this.outToVisualiser.write(boatLocationBlob); + try { + //Encode. + byte[] boatLocationBlob = this.parseBoatLocation(boatLocation); + + //Write it. + this.outToVisualiser.write(boatLocationBlob); + + } catch (InvalidMessageException e) { + Logger.getGlobal().log(Level.WARNING, "Could not encode BoatLocation: " + boatLocation, e); + } + + } } diff --git a/racevisionGame/src/main/java/network/MessageEncoders/BoatLocationEncoder.java b/racevisionGame/src/main/java/network/MessageEncoders/BoatLocationEncoder.java new file mode 100644 index 00000000..9ff3e197 --- /dev/null +++ b/racevisionGame/src/main/java/network/MessageEncoders/BoatLocationEncoder.java @@ -0,0 +1,83 @@ +package network.MessageEncoders; + + +import network.Messages.AC35Data; +import network.Messages.BoatLocation; + +import java.nio.ByteBuffer; + +import static network.Utils.ByteConverter.intToBytes; +import static network.Utils.ByteConverter.longToBytes; + +/** + * This encoder can encode a {@link BoatLocation} message. + */ +public class BoatLocationEncoder implements MessageEncoder { + + + /** + * Constructor. + */ + public BoatLocationEncoder() { + } + + + @Override + public byte[] encode(AC35Data message) { + + //Downcast. + BoatLocation boatLocation = (BoatLocation) message; + + + int messageVersionNumber = 0b1; + byte[] messageVersionBytes = intToBytes(messageVersionNumber, 1); + byte[] time = longToBytes(boatLocation.getTime(), 6); + byte[] sourceID = intToBytes(boatLocation.getSourceID(), 4); + byte[] seqNum = longToBytes(boatLocation.getSequenceNumber(), 4); + byte[] deviceType = intToBytes(boatLocation.getDeviceType(), 1); + byte[] latitude = intToBytes(boatLocation.getLatitude(), 4); + byte[] longitude = intToBytes(boatLocation.getLongitude(), 4); + byte[] altitude = intToBytes(boatLocation.getAltitude(), 4); + byte[] heading = intToBytes(boatLocation.getHeading(), 2); + byte[] pitch = intToBytes(boatLocation.getPitch(), 2); + byte[] roll = intToBytes(boatLocation.getRoll(), 2); + byte[] boatSpeed = intToBytes(boatLocation.getBoatSpeed(), 2); + byte[] cog = intToBytes(boatLocation.getBoatCOG(), 2); + byte[] sog = intToBytes(boatLocation.getBoatSOG(), 2); + byte[] apparentWindSpeed = intToBytes(boatLocation.getApparentWindSpeed(), 2); + byte[] apparentWindAngle = intToBytes(boatLocation.getApparentWindAngle(), 2); + byte[] trueWindSpeed = intToBytes(boatLocation.getTrueWindSpeed(), 2); + byte[] trueWindDirection = intToBytes(boatLocation.getTrueWindDirection(), 2); + byte[] trueWindAngle = intToBytes(boatLocation.getTrueWindAngle(), 2); + byte[] currentDrift = intToBytes(boatLocation.getCurrentDrift(), 2); + byte[] currentSet = intToBytes(boatLocation.getCurrentSet(), 2); + byte[] rudderAngle = intToBytes(boatLocation.getRudderAngle(), 2); + + ByteBuffer result = ByteBuffer.allocate(56); + result.put(messageVersionBytes); + result.put(time); + result.put(sourceID); + result.put(seqNum); + result.put(deviceType); + result.put(latitude); + result.put(longitude); + result.put(altitude); + result.put(heading); + result.put(pitch); + result.put(roll); + result.put(boatSpeed); + result.put(cog); + result.put(sog); + result.put(apparentWindSpeed); + result.put(apparentWindAngle); + result.put(trueWindSpeed); + result.put(trueWindDirection); + result.put(trueWindAngle); + result.put(currentDrift); + result.put(currentSet); + result.put(rudderAngle); + + return result.array(); + + } +} diff --git a/racevisionGame/src/main/java/network/MessageEncoders/EncoderFactory.java b/racevisionGame/src/main/java/network/MessageEncoders/EncoderFactory.java index ebb7814a..e23541db 100644 --- a/racevisionGame/src/main/java/network/MessageEncoders/EncoderFactory.java +++ b/racevisionGame/src/main/java/network/MessageEncoders/EncoderFactory.java @@ -29,6 +29,8 @@ public class EncoderFactory { switch (type) { + case BOATLOCATION: return new BoatLocationEncoder(); + case REQUEST_TO_JOIN: return new RequestToJoinEncoder(); case JOIN_ACCEPTANCE: return new JoinAcceptanceEncoder(); diff --git a/racevisionGame/src/main/java/network/MessageEncoders/RaceVisionByteEncoder.java b/racevisionGame/src/main/java/network/MessageEncoders/RaceVisionByteEncoder.java index e3269fba..1bd0d1f9 100644 --- a/racevisionGame/src/main/java/network/MessageEncoders/RaceVisionByteEncoder.java +++ b/racevisionGame/src/main/java/network/MessageEncoders/RaceVisionByteEncoder.java @@ -220,56 +220,6 @@ public class RaceVisionByteEncoder { } - public static byte[] boatLocation(BoatLocation boatLocation){ - int messageVersionNumber = 0b1; - byte[] time = longToBytes(boatLocation.getTime(), 6); - byte[] sourceID = intToBytes(boatLocation.getSourceID(), 4); - byte[] seqNum = longToBytes(boatLocation.getSequenceNumber(), 4); - byte[] deviceType = intToBytes(boatLocation.getDeviceType(), 1); - byte[] latitude = intToBytes(boatLocation.getLatitude(), 4); - byte[] longitude = intToBytes(boatLocation.getLongitude(), 4); - byte[] altitude = intToBytes(boatLocation.getAltitude(), 4); - byte[] heading = intToBytes(boatLocation.getHeading(), 2); - byte[] pitch = intToBytes(boatLocation.getPitch(), 2); - byte[] roll = intToBytes(boatLocation.getRoll(), 2); - byte[] boatSpeed = intToBytes(boatLocation.getBoatSpeed(), 2); - byte[] cog = intToBytes(boatLocation.getBoatCOG(), 2); - byte[] sog = intToBytes(boatLocation.getBoatSOG(), 2); - byte[] apparentWindSpeed = intToBytes(boatLocation.getApparentWindSpeed(), 2); - byte[] apparentWindAngle = intToBytes(boatLocation.getApparentWindAngle(), 2); - byte[] trueWindSpeed = intToBytes(boatLocation.getTrueWindSpeed(), 2); - byte[] trueWindDirection = intToBytes(boatLocation.getTrueWindDirection(), 2); - byte[] trueWindAngle = intToBytes(boatLocation.getTrueWindAngle(), 2); - byte[] currentDrift = intToBytes(boatLocation.getCurrentDrift(), 2); - byte[] currentSet = intToBytes(boatLocation.getCurrentSet(), 2); - byte[] rudderAngle = intToBytes(boatLocation.getRudderAngle(), 2); - - ByteBuffer result = ByteBuffer.allocate(56); - result.put(intToBytes(messageVersionNumber, 1)); - result.put(time); - result.put(sourceID); - result.put(seqNum); - result.put(deviceType); - result.put(latitude); - result.put(longitude); - result.put(altitude); - result.put(heading); - result.put(pitch); - result.put(roll); - result.put(boatSpeed); - result.put(cog); - result.put(sog); - result.put(apparentWindSpeed); - result.put(apparentWindAngle); - result.put(trueWindSpeed); - result.put(trueWindDirection); - result.put(trueWindAngle); - result.put(currentDrift); - result.put(currentSet); - result.put(rudderAngle); - return result.array(); - } - public static byte[] markRounding(int time, int ackNumber, int raceID, int sourceID, int boatStatus, int roundingSide, int markType, int markID){ int messageVersionNumber = 0b1; byte[] byteTime = longToBytes(time, 6); diff --git a/racevisionGame/src/test/java/network/MessageDecoders/BoatLocationDecoderTest.java b/racevisionGame/src/test/java/network/MessageDecoders/BoatLocationDecoderTest.java index 2f269257..18893609 100644 --- a/racevisionGame/src/test/java/network/MessageDecoders/BoatLocationDecoderTest.java +++ b/racevisionGame/src/test/java/network/MessageDecoders/BoatLocationDecoderTest.java @@ -7,23 +7,52 @@ import org.junit.Test; /** - * Created by hba56 on 23/04/17. + * Test for the BoatLocation encoder and decoder */ public class BoatLocationDecoderTest { + + + /** + * Creates a BoatLocation message, encodes it, decodes it, and checks that the result matches the starting message. + */ @Test - public void getByteArrayTest(){ + public void getByteArrayTest() throws Exception { + + //Create message. long time = System.currentTimeMillis(); - BoatLocation testMessage = new BoatLocation((byte) 1, time, 2, - 3, (byte) 1, 180, -180, 4, 5, - (short) 6, (short) 7, 8, 9, 10, 11, - (short) 12, 13, 14 , (short) 15, - 16, 17, (short) 18); - byte [] testEncodedMessage = RaceVisionByteEncoder.boatLocation(testMessage); + BoatLocation testMessage = new BoatLocation( + (byte) 1, + time, + 2, + 3, + (byte) 1, + 180, + -180, + 4, + 5, + (short) 6, + (short) 7, + 8, + 9, + 10, + 11, + (short) 12, + 13, + 14, + (short) 15, + 16, + 17, + (short) 18 ); + + //Encode. + byte [] testEncodedMessage = RaceVisionByteEncoder.encode(testMessage); + //Decode. BoatLocationDecoder testDecoder = new BoatLocationDecoder(testEncodedMessage); BoatLocation decodedTest = testDecoder.getMessage(); + //Check if valid. Assert.assertEquals(testMessage.getMessageVersionNumber(), decodedTest.getMessageVersionNumber()); Assert.assertEquals(testMessage.getTime(), decodedTest.getTime()); Assert.assertEquals(testMessage.getSequenceNumber(), decodedTest.getSequenceNumber());