Added AverageWindEncoder.

Refactored AverageWindDecoder - it now implements MessageDecoder.
Refactored AverageWind - it now uses milliseconds and knots, instead of packed MMperSec and tenths of a second. It also exposes its attributes now.
Added (un)packAverageWindPeriod to AC35UnitConverter.
Added AverageWindDecoderTest.
issue #35 #36
#story[1095]
main
fjc40 8 years ago
parent ce63f58429
commit da800e659a

@ -199,8 +199,8 @@ public class BinaryMessageDecoder {
case AVGWIND:
//System.out.println("Average Wind Message!");
AverageWindDecoder awDecoder = new AverageWindDecoder(messageBody);
return awDecoder.getAverageWind();
AverageWindDecoder awDecoder = new AverageWindDecoder();
return awDecoder.decode(messageBody);
case BOATACTION:
BoatActionDecoder baDecoder = new BoatActionDecoder();

@ -1,56 +1,103 @@
package network.MessageDecoders;
import network.Messages.AC35Data;
import network.Messages.AverageWind;
import network.Utils.ByteConverter;
import static network.Utils.AC35UnitConverter.*;
import java.util.Arrays;
/**
* Created by hba56 on 23/04/17.
* Decodes {@link AverageWind} messages.
*/
public class AverageWindDecoder implements MessageDecoder {
/**
* The encoded message.
*/
public class AverageWindDecoder {
byte messageVersionNumber;
byte[] byteTime;
byte[] byteRawPeriod;
byte[] byteRawSpeed;
byte[] bytePeriod2;
byte[] byteSpeed2;
byte[] bytePeriod3;
byte[] byteSpeed3;
byte[] bytePeriod4;
byte[] byteSpeed4;
AverageWind averageWind;
public AverageWindDecoder(byte[] encodedAverageWind) {
messageVersionNumber = encodedAverageWind[0];
byteTime = Arrays.copyOfRange(encodedAverageWind, 1, 7);
byteRawPeriod = Arrays.copyOfRange(encodedAverageWind, 7, 9);
byteRawSpeed = Arrays.copyOfRange(encodedAverageWind, 9, 11);
bytePeriod2 = Arrays.copyOfRange(encodedAverageWind, 11, 13);
byteSpeed2 = Arrays.copyOfRange(encodedAverageWind, 13, 15);
bytePeriod3 = Arrays.copyOfRange(encodedAverageWind, 15, 17);
byteSpeed3 = Arrays.copyOfRange(encodedAverageWind, 17, 19);
bytePeriod4 = Arrays.copyOfRange(encodedAverageWind, 19, 21);
byteSpeed4 = Arrays.copyOfRange(encodedAverageWind, 21, 23);
int msgNum = ByteConverter.bytesToInt(messageVersionNumber);
long lngTime = ByteConverter.bytesToLong(byteTime);
private byte[] encodedMessage;
/**
* The decoded message.
*/
private AverageWind message;
public AverageWindDecoder() {
}
@Override
public AC35Data decode(byte[] encodedMessage) {
this.encodedMessage = encodedMessage;
byte messageVersionNumber = encodedMessage[0];
byte[] byteTime = Arrays.copyOfRange(encodedMessage, 1, 7);
long time = ByteConverter.bytesToLong(byteTime);
byte[] byteRawPeriod = Arrays.copyOfRange(encodedMessage, 7, 9);
int intRawPeriod = ByteConverter.bytesToInt(byteRawPeriod);
long rawPeriod = unpackAverageWindPeriod(intRawPeriod);
byte[] byteRawSpeed = Arrays.copyOfRange(encodedMessage, 9, 11);
int intRawSpeed = ByteConverter.bytesToInt(byteRawSpeed);
double rawSpeedKnots = unpackMMperSecToKnots(intRawSpeed);
byte[] bytePeriod2 = Arrays.copyOfRange(encodedMessage, 11, 13);
int intPeriod2 = ByteConverter.bytesToInt(bytePeriod2);
long period2 = unpackAverageWindPeriod(intPeriod2);
byte[] byteSpeed2 = Arrays.copyOfRange(encodedMessage, 13, 15);
int intSpeed2 = ByteConverter.bytesToInt(byteSpeed2);
double speed2Knots = unpackMMperSecToKnots(intSpeed2);
byte[] bytePeriod3 = Arrays.copyOfRange(encodedMessage, 15, 17);
int intPeriod3 = ByteConverter.bytesToInt(bytePeriod3);
long period3 = unpackAverageWindPeriod(intPeriod3);
byte[] byteSpeed3 = Arrays.copyOfRange(encodedMessage, 17, 19);
int intSpeed3 = ByteConverter.bytesToInt(byteSpeed3);
double speed3Knots = unpackMMperSecToKnots(intSpeed3);
byte[] bytePeriod4 = Arrays.copyOfRange(encodedMessage, 19, 21);
int intPeriod4 = ByteConverter.bytesToInt(bytePeriod4);
long period4 = unpackAverageWindPeriod(intPeriod4);
byte[] byteSpeed4 = Arrays.copyOfRange(encodedMessage, 21, 23);
int intSpeed4 = ByteConverter.bytesToInt(byteSpeed4);
double speed4Knots = unpackMMperSecToKnots(intSpeed4);
this.averageWind = new AverageWind(msgNum, lngTime, intRawPeriod, intRawSpeed, intPeriod2, intSpeed2, intPeriod3, intSpeed3, intPeriod4, intSpeed4);
message = new AverageWind(
messageVersionNumber,
time,
rawPeriod,
rawSpeedKnots,
period2,
speed2Knots,
period3,
speed3Knots,
period4,
speed4Knots );
return message;
}
public AverageWind getAverageWind() {
return averageWind;
/**
* Returns the decoded message.
* @return The decoded message.
*/
public AverageWind getMessage() {
return message;
}
}

@ -51,7 +51,7 @@ public class DecoderFactory {
case COURSEWIND: return new CourseWindsDecoder();
//case AVGWIND: return new AverageWindDecoder()//TODO;
case AVGWIND: return new AverageWindDecoder();
case REQUEST_TO_JOIN: return new RequestToJoinDecoder();

@ -0,0 +1,86 @@
package network.MessageEncoders;
import network.Messages.AC35Data;
import network.Messages.AverageWind;
import java.nio.ByteBuffer;
import static network.Utils.AC35UnitConverter.*;
import static network.Utils.ByteConverter.intToBytes;
import static network.Utils.ByteConverter.longToBytes;
/**
* This encoder can encode a {@link AverageWind} message.
*/
public class AverageWindEncoder implements MessageEncoder {
/**
* Constructor.
*/
public AverageWindEncoder() {
}
@Override
public byte[] encode(AC35Data message) {
//Downcast.
AverageWind averageWind = (AverageWind) message;
byte messageVersionNumber = averageWind.getMessageVersionNumber();
long time = averageWind.getTime();
byte[] byteTime = longToBytes(time,6);
long rawPeriod = averageWind.getRawPeriod();
int rawPeriodInt = packAverageWindPeriod(rawPeriod);
byte[] byteRawPeriod = intToBytes(rawPeriodInt, 2);
double rawSampleSpeed = averageWind.getRawSpeedKnots();
int rawSampleSpeedInt = packKnotsToMMperSec(rawSampleSpeed);
byte[] byteRawSpeed = intToBytes(rawSampleSpeedInt, 2);
long period2 = averageWind.getSampleTwoPeriod();
int period2Int = packAverageWindPeriod(period2);
byte[] bytePeriod2 = intToBytes(period2Int, 2);
double speed2 = averageWind.getSampleTwoSpeedKnots();
int speed2Int = packKnotsToMMperSec(speed2);
byte[] byteSpeed2 = intToBytes(speed2Int, 2);
long period3 = averageWind.getSampleThreePeriod();
int period3Int = packAverageWindPeriod(period3);
byte[] bytePeriod3 = intToBytes(period3Int, 2);
double speed3 = averageWind.getSampleThreeSpeedKnots();
int speed3Int = packKnotsToMMperSec(speed3);
byte[] byteSpeed3 = intToBytes(speed3Int, 2);
long period4 = averageWind.getSampleFourPeriod();
int period4Int = packAverageWindPeriod(period4);
byte[] bytePeriod4 = intToBytes(period4Int, 2);
double speed4 = averageWind.getSampleFourSpeedKnots();
int speed4Int = packKnotsToMMperSec(speed4);
byte[] byteSpeed4 = intToBytes(speed4Int, 2);
ByteBuffer result = ByteBuffer.allocate(23);
result.put(messageVersionNumber);
result.put(byteTime);
result.put(byteRawPeriod);
result.put(byteRawSpeed);
result.put(bytePeriod2);
result.put(byteSpeed2);
result.put(bytePeriod3);
result.put(byteSpeed3);
result.put(bytePeriod4);
result.put(byteSpeed4);
return result.array();
}
}

@ -51,7 +51,7 @@ public class EncoderFactory {
case COURSEWIND: return new CourseWindsEncoder();
//case AVGWIND: return new AverageWindEncoder();//TODO
case AVGWIND: return new AverageWindEncoder();
case REQUEST_TO_JOIN: return new RequestToJoinEncoder();

@ -126,34 +126,6 @@ public class RaceVisionByteEncoder {
public static byte[] averageWind(int time, int rawPeriod, int rawSampleSpeed, int period2, int speed2, int period3, int speed3, int period4, int speed4){
int messageVersionNumber = 0b1;
byte[] byteTime = longToBytes(time,6);
byte[] byteRawPeriod = intToBytes(rawPeriod, 2);
byte[] byteRawSpeed = intToBytes(rawSampleSpeed, 2);
byte[] bytePeriod2 = intToBytes(period2, 2);
byte[] byteSpeed2 = intToBytes(speed2, 2);
byte[] bytePeriod3 = intToBytes(period3, 2);
byte[] byteSpeed3 = intToBytes(speed3, 2);
byte[] bytePeriod4 = intToBytes(period4, 2);
byte[] byteSpeed4 = intToBytes(speed4, 2);
ByteBuffer result = ByteBuffer.allocate(23);
result.put(intToBytes(messageVersionNumber, 1));
result.put(byteTime);
result.put(byteRawPeriod);
result.put(byteRawSpeed);
result.put(bytePeriod2);
result.put(byteSpeed2);
result.put(bytePeriod3);
result.put(byteSpeed3);
result.put(bytePeriod4);
result.put(byteSpeed4);
return result.array();
}
/**
* Encodes a given message.
* @param message Message to encode.

@ -4,33 +4,187 @@ package network.Messages;
import network.Messages.Enums.MessageType;
/**
* Created by fwy13 on 25/04/17.
* Represents an AverageWind message in the streaming API (see section 4.12).
*/
public class AverageWind extends AC35Data {
private int msgNum;
private long lngTime;
private int rawPeriod;
private int rawSpeed;
private int period2;
private int speed2;
private int period3;
private int speed3;
private int period4;
private int speed4;
public AverageWind(int msgNum, long lngTime, int rawPeriod, int rawSpeed, int period2, int speed2, int period3, int speed3, int period4, int speed4){
/**
* The current version number for this message type.
*/
public static final byte currentMessageVersionNumber = 1;
/**
* The version number for this message.
*/
private byte messageVersionNumber;
/**
* Timestamp for when the measurement was taken. Milliseconds since unix epoch.
*/
private long time;
/**
* Raw sample rate period. Milliseconds.
*/
private long rawPeriod;
/**
* Raw wind speed, in knots.
*/
private double rawSpeedKnots;
/**
* Wind speed average period for second sample. Milliseconds.
*/
private long sampleTwoPeriod;
/**
* Wind speed of second sample. Knots.
*/
private double sampleTwoSpeedKnots;
/**
* Wind speed average period for third sample. Milliseconds.
*/
private long sampleThreePeriod;
/**
* Wind speed of third sample. Knots.
*/
private double sampleThreeSpeedKnots;
/**
* Wind speed average period for fourth sample. Milliseconds.
*/
private long sampleFourPeriod;
/**
* Wind speed of fourth sample. Knots.
*/
private double sampleFourSpeedKnots;
/**
* Creates an AverageWind message, with the given parameters.
* @param messageVersionNumber The version number of message.
* @param time The timestamp of the message.
* @param rawPeriod The period of the raw measurement. Milliseconds.
* @param rawSpeedKnots The speed of the raw measurement. Knots.
* @param sampleTwoPeriod The period of the second measurement. Milliseconds.
* @param sampleTwoSpeedKnots The speed of the second measurement. Knots.
* @param sampleThreePeriod The period of the third measurement. Milliseconds.
* @param sampleThreeSpeedKnots The speed of the third measurement. Knots.
* @param sampleFourPeriod The period of the fourth measurement. Milliseconds.
* @param sampleFourSpeedKnots The speed of the fourth measurement. Knots.
*/
public AverageWind(
byte messageVersionNumber,
long time,
long rawPeriod,
double rawSpeedKnots,
long sampleTwoPeriod,
double sampleTwoSpeedKnots,
long sampleThreePeriod,
double sampleThreeSpeedKnots,
long sampleFourPeriod,
double sampleFourSpeedKnots ) {
super(MessageType.AVGWIND);
this.msgNum = msgNum;
this.lngTime = lngTime;
this.messageVersionNumber = messageVersionNumber;
this.time = time;
this.rawPeriod = rawPeriod;
this.rawSpeed = rawSpeed;
this.period2 = period2;
this.speed2 = speed2;
this.period3 = period3;
this.speed3 = speed3;
this.period4 = period4;
this.speed4 = speed4;
this.rawSpeedKnots = rawSpeedKnots;
this.sampleTwoPeriod = sampleTwoPeriod;
this.sampleTwoSpeedKnots = sampleTwoSpeedKnots;
this.sampleThreePeriod = sampleThreePeriod;
this.sampleThreeSpeedKnots = sampleThreeSpeedKnots;
this.sampleFourPeriod = sampleFourPeriod;
this.sampleFourSpeedKnots = sampleFourSpeedKnots;
}
/**
* Returns the version number of this message.
* @return Message version number.
*/
public byte getMessageVersionNumber() {
return messageVersionNumber;
}
/**
* Returns the timestamp of this message.
* @return Timestamp of this message. Milliseconds since unix epoch.
*/
public long getTime() {
return time;
}
/**
* Returns the period of time over which the raw sample was done. Milliseconds.
* @return Raw sample's period.
*/
public long getRawPeriod() {
return rawPeriod;
}
/**
* Returns the wind speed of the raw sample. Knots.
* @return Wind speed of raw sample. Knots
*/
public double getRawSpeedKnots() {
return rawSpeedKnots;
}
/**
* Returns the period of time over which the second sample was done. Milliseconds.
* @return Second sample's period.
*/
public long getSampleTwoPeriod() {
return sampleTwoPeriod;
}
/**
* Returns the wind speed of the second sample. Knots.
* @return Wind speed of second sample. Knots
*/
public double getSampleTwoSpeedKnots() {
return sampleTwoSpeedKnots;
}
/**
* Returns the period of time over which the third sample was done. Milliseconds.
* @return Third sample's period.
*/
public long getSampleThreePeriod() {
return sampleThreePeriod;
}
/**
* Returns the wind speed of the third sample. Knots.
* @return Wind speed of third sample. Knots
*/
public double getSampleThreeSpeedKnots() {
return sampleThreeSpeedKnots;
}
/**
* Returns the period of time over which the fourth sample was done. Milliseconds.
* @return Fourth sample's period.
*/
public long getSampleFourPeriod() {
return sampleFourPeriod;
}
/**
* Returns the wind speed of the fourth sample. Knots.
* @return Wind speed of fourth sample. Knots
*/
public double getSampleFourSpeedKnots() {
return sampleFourSpeedKnots;
}
}

@ -85,4 +85,23 @@ public class AC35UnitConverter {
}
/**
* Packs an average wind period, in milliseconds, into an int, in tenths of a second.
* @param periodMilliseconds Period in milliseconds.
* @return Period in tenths of a second.
*/
public static int packAverageWindPeriod(long periodMilliseconds) {
return (int) (periodMilliseconds / 100);
}
/**
* Unpacks an average wind period, in tenths of a second, into an long, in milliseconds.
* @param periodTenthsOfSecond Period in tenths of a second.
* @return Period in milliseconds
*/
public static long unpackAverageWindPeriod(int periodTenthsOfSecond) {
return (periodTenthsOfSecond * 100);
}
}

@ -0,0 +1,75 @@
package network.MessageDecoders;
import network.MessageEncoders.RaceVisionByteEncoder;
import network.Messages.AverageWind;
import static org.junit.Assert.*;
import org.junit.Test;
import shared.model.Bearing;
import java.util.ArrayList;
/**
* Test for the AverageWind encoder and decoder
*/
public class AverageWindDecoderTest {
/**
* Creates a AverageWind message, encodes it, decodes it, and checks that the result matches the starting message.
* @throws Exception if test fails.
*/
@Test
public void averageWindEncodeDecodeTest() throws Exception {
AverageWind averageWind = new AverageWind(
AverageWind.currentMessageVersionNumber,
System.currentTimeMillis(),
3000,
12.5,
4050,
12.6,
3055,
12.7,
6051,
13.37
);
byte[] encodedMessage = RaceVisionByteEncoder.encode(averageWind);
AverageWindDecoder averageWindDecoder = new AverageWindDecoder();
averageWindDecoder.decode(encodedMessage);
AverageWind averageWindDecoded = averageWindDecoder.getMessage();
compareAverageWindMessages(averageWind, averageWindDecoded);
}
/**
* Compares two AverageWind messages to check that they are equal.
* @param original The original AverageWind message.
* @param decoded The decoded AverageWind message.
*/
public static void compareAverageWindMessages(AverageWind original, AverageWind decoded) {
assertEquals(original.getMessageVersionNumber(), decoded.getMessageVersionNumber());
assertEquals(original.getTime(), decoded.getTime());
assertEquals(original.getRawPeriod(), decoded.getRawPeriod(), 100);
assertEquals(original.getRawSpeedKnots(), decoded.getRawSpeedKnots(), 0.01);
assertEquals(original.getSampleTwoPeriod(), decoded.getSampleTwoPeriod(), 100);
assertEquals(original.getSampleTwoSpeedKnots(), decoded.getSampleTwoSpeedKnots(), 0.01);
assertEquals(original.getSampleThreePeriod(), decoded.getSampleThreePeriod(), 100);
assertEquals(original.getSampleThreeSpeedKnots(), decoded.getSampleThreeSpeedKnots(), 0.01);
assertEquals(original.getSampleFourPeriod(), decoded.getSampleFourPeriod(), 100);
assertEquals(original.getSampleFourSpeedKnots(), decoded.getSampleFourSpeedKnots(), 0.01);
}
}
Loading…
Cancel
Save