Merge branch 'master' into story_64_sails
# Conflicts: # racevisionGame/src/main/java/mock/app/MockOutput.java # racevisionGame/src/main/java/mock/model/MockRace.java # racevisionGame/src/main/java/mock/model/commandFactory/CommandFactory.java # racevisionGame/src/main/java/network/MessageDecoders/BoatActionDecoder.java # racevisionGame/src/main/java/network/MessageDecoders/BoatLocationDecoder.java # racevisionGame/src/main/java/visualiser/app/VisualiserInput.java # racevisionGame/src/main/java/visualiser/gameController/ControllerServer.java # racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java # racevisionGame/src/main/java/visualiser/model/VisualiserRace.java # racevisionGame/src/main/resources/visualiser/scenes/connect.fxml # racevisionGame/src/main/resources/visualiser/scenes/lobby.fxml # racevisionGame/src/test/java/mock/model/MockRaceTest.java # racevisionGame/src/test/java/network/Utils/AC35UnitConverterTest.java # racevisionGame/src/test/java/network/XMLMessageEncoderTest.java
This commit is contained in:
@@ -1,56 +1,107 @@
|
||||
package network.MessageDecoders;
|
||||
|
||||
|
||||
import network.Exceptions.InvalidMessageException;
|
||||
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 {
|
||||
byte messageVersionNumber;
|
||||
byte[] byteTime;
|
||||
byte[] byteRawPeriod;
|
||||
byte[] byteRawSpeed;
|
||||
byte[] bytePeriod2;
|
||||
byte[] byteSpeed2;
|
||||
byte[] bytePeriod3;
|
||||
byte[] byteSpeed3;
|
||||
byte[] bytePeriod4;
|
||||
byte[] byteSpeed4;
|
||||
public class AverageWindDecoder implements MessageDecoder {
|
||||
|
||||
AverageWind averageWind;
|
||||
/**
|
||||
* The encoded message.
|
||||
*/
|
||||
private byte[] encodedMessage;
|
||||
|
||||
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);
|
||||
/**
|
||||
* The decoded message.
|
||||
*/
|
||||
private AverageWind message;
|
||||
|
||||
int msgNum = ByteConverter.bytesToInt(messageVersionNumber);
|
||||
long lngTime = ByteConverter.bytesToLong(byteTime);
|
||||
int intRawPeriod = ByteConverter.bytesToInt(byteRawPeriod);
|
||||
int intRawSpeed = ByteConverter.bytesToInt(byteRawSpeed);
|
||||
int intPeriod2 = ByteConverter.bytesToInt(bytePeriod2);
|
||||
int intSpeed2 = ByteConverter.bytesToInt(byteSpeed2);
|
||||
int intPeriod3 = ByteConverter.bytesToInt(bytePeriod3);
|
||||
int intSpeed3 = ByteConverter.bytesToInt(byteSpeed3);
|
||||
int intPeriod4 = ByteConverter.bytesToInt(bytePeriod4);
|
||||
int intSpeed4 = ByteConverter.bytesToInt(byteSpeed4);
|
||||
|
||||
this.averageWind = new AverageWind(msgNum, lngTime, intRawPeriod, intRawSpeed, intPeriod2, intSpeed2, intPeriod3, intSpeed3, intPeriod4, intSpeed4);
|
||||
|
||||
public AverageWindDecoder() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public AC35Data decode(byte[] encodedMessage) throws InvalidMessageException {
|
||||
this.encodedMessage = encodedMessage;
|
||||
|
||||
try {
|
||||
|
||||
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);
|
||||
|
||||
|
||||
message = new AverageWind(
|
||||
messageVersionNumber,
|
||||
time,
|
||||
rawPeriod,
|
||||
rawSpeedKnots,
|
||||
period2,
|
||||
speed2Knots,
|
||||
period3,
|
||||
speed3Knots,
|
||||
period4,
|
||||
speed4Knots);
|
||||
|
||||
return message;
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new InvalidMessageException("Could not decode AverageWind message.", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public AverageWind getAverageWind() {
|
||||
return averageWind;
|
||||
/**
|
||||
* Returns the decoded message.
|
||||
* @return The decoded message.
|
||||
*/
|
||||
public AverageWind getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +1,56 @@
|
||||
package network.MessageDecoders;
|
||||
|
||||
import network.Exceptions.InvalidMessageException;
|
||||
import network.Messages.AC35Data;
|
||||
import network.Messages.BoatAction;
|
||||
import network.Messages.Enums.BoatActionEnum;
|
||||
|
||||
public class BoatActionDecoder {
|
||||
byte byteBoatAction;
|
||||
BoatActionEnum boatAction;
|
||||
import java.util.Arrays;
|
||||
|
||||
public BoatActionDecoder(byte[] encodedBoatAction) {
|
||||
byteBoatAction = encodedBoatAction[0];
|
||||
/**
|
||||
* Decodes {@link BoatAction} messages.
|
||||
*/
|
||||
public class BoatActionDecoder implements MessageDecoder {
|
||||
|
||||
boatAction = BoatActionEnum.fromByte(byteBoatAction);
|
||||
/**
|
||||
* The encoded message.
|
||||
*/
|
||||
private byte[] encodedMessage;
|
||||
|
||||
/**
|
||||
* The decoded message.
|
||||
*/
|
||||
private BoatAction message;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a decoder to decode a given message.
|
||||
*/
|
||||
public BoatActionDecoder() {
|
||||
}
|
||||
|
||||
public BoatActionEnum getBoatAction() {
|
||||
return boatAction;
|
||||
@Override
|
||||
public AC35Data decode(byte[] encodedMessage) throws InvalidMessageException {
|
||||
this.encodedMessage = encodedMessage;
|
||||
|
||||
try {
|
||||
BoatActionEnum boatActionEnum = BoatActionEnum.fromByte(encodedMessage[0]);
|
||||
|
||||
message = new BoatAction(boatActionEnum);
|
||||
|
||||
return message;
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new InvalidMessageException("Could not decode BoatAction message.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the decoded message.
|
||||
* @return The decoded message.
|
||||
*/
|
||||
public BoatAction getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,140 +1,168 @@
|
||||
package network.MessageDecoders;
|
||||
|
||||
|
||||
import network.Exceptions.InvalidMessageException;
|
||||
import network.Messages.AC35Data;
|
||||
import network.Messages.BoatLocation;
|
||||
import network.Messages.Enums.BoatLocationDeviceEnum;
|
||||
import shared.model.Azimuth;
|
||||
import shared.model.Bearing;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static network.Utils.AC35UnitConverter.*;
|
||||
import static network.Utils.ByteConverter.*;
|
||||
|
||||
|
||||
/**
|
||||
* Created by hba56 on 21/04/17.
|
||||
* Decodes {@link BoatLocation} messages.
|
||||
*/
|
||||
public class BoatLocationDecoder {
|
||||
private byte messageVersionNumber;
|
||||
private byte[] time;
|
||||
private byte[] sourceID;
|
||||
private byte[] seqNum;
|
||||
private byte deviceType;
|
||||
private byte[] latitude;
|
||||
private byte[] longitude;
|
||||
private byte[] altitude;
|
||||
private byte[] heading;
|
||||
private byte[] pitch;
|
||||
private byte[] roll;
|
||||
private byte[] boatSpeed;
|
||||
private byte[] cog;
|
||||
private byte[] sog;
|
||||
private byte[] apparentWindSpeed;
|
||||
private byte[] apparentWindAngle;
|
||||
private byte[] trueWindSpeed;
|
||||
private byte[] trueWindDirection;
|
||||
private byte[] trueWindAngle;
|
||||
private byte[] currentDrift;
|
||||
private byte[] currentSet;
|
||||
private byte[] rudderAngle;
|
||||
public class BoatLocationDecoder implements MessageDecoder {
|
||||
|
||||
/**
|
||||
* The encoded message.
|
||||
*/
|
||||
private byte[] encodedMessage;
|
||||
|
||||
/**
|
||||
* The decoded message.
|
||||
*/
|
||||
private BoatLocation message;
|
||||
|
||||
public BoatLocationDecoder(byte[] encodedBoatLocation) {
|
||||
byte numMessageVersionNumber = 0;
|
||||
long numTime = 0;
|
||||
int numSourceID = 0;
|
||||
int numSeqNum = 0;
|
||||
byte numDeviceType = 0;
|
||||
int numLatitude = 0;
|
||||
int numLongitude = 0;
|
||||
int numAltitude = 0;
|
||||
int numHeading = 0;
|
||||
short numPitch = 0;
|
||||
short numRoll = 0;
|
||||
int numBoatSpeed = 0;
|
||||
int numCog = 0;
|
||||
int numSog = 0;
|
||||
int numApparentWindSpeed = 0;
|
||||
short numApparentWindAngle = 0;
|
||||
int numTrueWindSpeed = 0;
|
||||
short numTrueWindDirection = 0;
|
||||
short numTrueWindAngle = 0;
|
||||
int numCurrentDrift = 0;
|
||||
int numCurrentSet = 0;
|
||||
short numRudderAngle = 0;
|
||||
|
||||
try {
|
||||
messageVersionNumber = encodedBoatLocation[0];
|
||||
numMessageVersionNumber = messageVersionNumber;
|
||||
time = Arrays.copyOfRange(encodedBoatLocation, 1, 7);
|
||||
numTime = bytesToLong(time);
|
||||
sourceID = Arrays.copyOfRange(encodedBoatLocation, 7, 11);
|
||||
numSourceID = bytesToInt(sourceID);
|
||||
seqNum = Arrays.copyOfRange(encodedBoatLocation, 11, 15);
|
||||
numSeqNum = bytesToInt(seqNum);
|
||||
deviceType = encodedBoatLocation[15];
|
||||
numDeviceType = deviceType;
|
||||
latitude = Arrays.copyOfRange(encodedBoatLocation, 16, 20);
|
||||
numLatitude = bytesToInt(latitude);
|
||||
longitude = Arrays.copyOfRange(encodedBoatLocation, 20, 24);
|
||||
numLongitude = bytesToInt(longitude);
|
||||
altitude = Arrays.copyOfRange(encodedBoatLocation, 24, 28);
|
||||
numAltitude = bytesToInt(altitude);
|
||||
heading = Arrays.copyOfRange(encodedBoatLocation, 28, 30);
|
||||
numHeading = bytesToInt(heading);
|
||||
pitch = Arrays.copyOfRange(encodedBoatLocation, 30, 32);
|
||||
numPitch = bytesToShort(pitch);
|
||||
roll = Arrays.copyOfRange(encodedBoatLocation, 32, 34);
|
||||
numRoll = bytesToShort(roll);
|
||||
boatSpeed = Arrays.copyOfRange(encodedBoatLocation, 34, 36);
|
||||
numBoatSpeed = bytesToInt(boatSpeed);
|
||||
cog = Arrays.copyOfRange(encodedBoatLocation, 36, 38);
|
||||
numCog = bytesToInt(cog);
|
||||
sog = Arrays.copyOfRange(encodedBoatLocation, 38, 40);
|
||||
numSog = bytesToInt(sog);
|
||||
apparentWindSpeed = Arrays.copyOfRange(encodedBoatLocation, 40, 42);
|
||||
numApparentWindSpeed = bytesToInt(apparentWindSpeed);
|
||||
apparentWindAngle = Arrays.copyOfRange(encodedBoatLocation, 42, 44);
|
||||
numApparentWindAngle = bytesToShort(apparentWindAngle);
|
||||
trueWindSpeed = Arrays.copyOfRange(encodedBoatLocation, 44, 46);
|
||||
numTrueWindSpeed = bytesToInt(trueWindSpeed);
|
||||
trueWindDirection = Arrays.copyOfRange(encodedBoatLocation, 46, 48);
|
||||
numTrueWindDirection = bytesToShort(trueWindDirection);
|
||||
trueWindAngle = Arrays.copyOfRange(encodedBoatLocation, 48, 50);
|
||||
numTrueWindAngle = bytesToShort(trueWindAngle);
|
||||
currentDrift = Arrays.copyOfRange(encodedBoatLocation, 50, 52);
|
||||
numCurrentDrift = bytesToInt(currentDrift);
|
||||
currentSet = Arrays.copyOfRange(encodedBoatLocation, 52, 54);
|
||||
numCurrentSet = bytesToShort(currentSet);
|
||||
rudderAngle = Arrays.copyOfRange(encodedBoatLocation, 54, 56);
|
||||
numRudderAngle = bytesToShort(rudderAngle);
|
||||
} catch(ArrayIndexOutOfBoundsException e){
|
||||
|
||||
}
|
||||
|
||||
message = new BoatLocation(numMessageVersionNumber, numTime,
|
||||
numSourceID, numSeqNum, numDeviceType, numLatitude,
|
||||
numLongitude, numAltitude, numHeading, numPitch,
|
||||
numRoll, numBoatSpeed, numCog, numSog, numApparentWindSpeed,
|
||||
numApparentWindAngle, numTrueWindSpeed, numTrueWindDirection,
|
||||
numTrueWindAngle, numCurrentDrift, numCurrentSet, numRudderAngle
|
||||
);/*
|
||||
message = new BoatLocation(messageVersionNumber, bytesToLong(time),
|
||||
bytesToInt(sourceID), bytesToInt(seqNum),
|
||||
deviceType, bytesToInt(latitude),
|
||||
bytesToInt(longitude), bytesToInt(altitude),
|
||||
bytesToInt(heading), bytesToShort(pitch),
|
||||
bytesToShort(roll), bytesToInt(boatSpeed),
|
||||
bytesToInt(cog), bytesToInt(sog),
|
||||
bytesToInt(apparentWindSpeed), bytesToShort(apparentWindAngle),
|
||||
bytesToInt(trueWindSpeed), bytesToShort(trueWindDirection),
|
||||
bytesToShort(trueWindAngle), bytesToInt(currentDrift),
|
||||
bytesToInt(currentSet), bytesToShort(rudderAngle)
|
||||
);*/
|
||||
|
||||
// System.out.println(bytesToInt(sourceID));
|
||||
// System.out.println(bytesToInt(boatSpeed));
|
||||
/**
|
||||
* Constructs a decoder to decode a given message.
|
||||
*/
|
||||
public BoatLocationDecoder() {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public AC35Data decode(byte[] encodedMessage) throws InvalidMessageException {
|
||||
this.encodedMessage = encodedMessage;
|
||||
|
||||
try {
|
||||
|
||||
byte[] messageVersionNumberBytes = Arrays.copyOfRange(encodedMessage, 0, 1);
|
||||
byte messageVersionNumber = messageVersionNumberBytes[0];
|
||||
|
||||
byte[] timeBytes = Arrays.copyOfRange(encodedMessage, 1, 7);
|
||||
long time = bytesToLong(timeBytes);
|
||||
|
||||
byte[] sourceIDBytes = Arrays.copyOfRange(encodedMessage, 7, 11);
|
||||
int sourceID = bytesToInt(sourceIDBytes);
|
||||
|
||||
byte[] seqNumBytes = Arrays.copyOfRange(encodedMessage, 11, 15);
|
||||
int seqNum = bytesToInt(seqNumBytes);
|
||||
|
||||
byte[] deviceTypeBytes = Arrays.copyOfRange(encodedMessage, 15, 16);
|
||||
BoatLocationDeviceEnum deviceType = BoatLocationDeviceEnum.fromByte(deviceTypeBytes[0]);
|
||||
|
||||
byte[] latitudeBytes = Arrays.copyOfRange(encodedMessage, 16, 20);
|
||||
int numLatitude = bytesToInt(latitudeBytes);
|
||||
double latitude = unpackGPS(numLatitude);
|
||||
|
||||
byte[] longitudeBytes = Arrays.copyOfRange(encodedMessage, 20, 24);
|
||||
int numLongitude = bytesToInt(longitudeBytes);
|
||||
double longitude = unpackGPS(numLongitude);
|
||||
|
||||
byte[] altitudeBytes = Arrays.copyOfRange(encodedMessage, 24, 28);
|
||||
int numAltitude = bytesToInt(altitudeBytes);
|
||||
|
||||
byte[] headingBytes = Arrays.copyOfRange(encodedMessage, 28, 30);
|
||||
int numHeading = bytesToInt(headingBytes);
|
||||
Bearing heading = Bearing.fromDegrees(unpackHeading(numHeading));
|
||||
|
||||
byte[] pitchBytes = Arrays.copyOfRange(encodedMessage, 30, 32);
|
||||
short numPitch = bytesToShort(pitchBytes);
|
||||
|
||||
byte[] rollBytes = Arrays.copyOfRange(encodedMessage, 32, 34);
|
||||
short numRoll = bytesToShort(rollBytes);
|
||||
|
||||
byte[] boatSpeedBytes = Arrays.copyOfRange(encodedMessage, 34, 36);
|
||||
int numBoatSpeed = bytesToInt(boatSpeedBytes);
|
||||
double boatSpeedKnots = unpackMMperSecToKnots(numBoatSpeed);
|
||||
|
||||
byte[] cogBytes = Arrays.copyOfRange(encodedMessage, 36, 38);
|
||||
int numCog = bytesToInt(cogBytes);
|
||||
Bearing cog = Bearing.fromDegrees(unpackHeading(numCog));
|
||||
|
||||
byte[] sogBytes = Arrays.copyOfRange(encodedMessage, 38, 40);
|
||||
int numSog = bytesToInt(sogBytes);
|
||||
double sogKnots = unpackMMperSecToKnots(numSog);
|
||||
|
||||
byte[] apparentWindSpeedBytes = Arrays.copyOfRange(encodedMessage, 40, 42);
|
||||
int numApparentWindSpeed = bytesToInt(apparentWindSpeedBytes);
|
||||
double apparentWindSpeedKnots = unpackMMperSecToKnots(numApparentWindSpeed);
|
||||
|
||||
byte[] apparentWindAngleBytes = Arrays.copyOfRange(encodedMessage, 42, 44);
|
||||
short numApparentWindAngle = bytesToShort(apparentWindAngleBytes);
|
||||
Azimuth apparentWindAngle = Azimuth.fromDegrees(unpackTrueWindAngle(numApparentWindAngle));
|
||||
|
||||
byte[] trueWindSpeedBytes = Arrays.copyOfRange(encodedMessage, 44, 46);
|
||||
int numTrueWindSpeed = bytesToInt(trueWindSpeedBytes);
|
||||
double trueWindSpeedKnots = unpackMMperSecToKnots(numTrueWindSpeed);
|
||||
|
||||
byte[] trueWindDirectionBytes = Arrays.copyOfRange(encodedMessage, 46, 48);
|
||||
short numTrueWindDirection = bytesToShort(trueWindDirectionBytes);
|
||||
Bearing trueWindDirection = Bearing.fromDegrees(unpackHeading(numTrueWindDirection));
|
||||
|
||||
byte[] trueWindAngleBytes = Arrays.copyOfRange(encodedMessage, 48, 50);
|
||||
short numTrueWindAngle = bytesToShort(trueWindAngleBytes);
|
||||
Azimuth trueWindAngle = Azimuth.fromDegrees(unpackTrueWindAngle(numTrueWindAngle));
|
||||
|
||||
byte[] currentDriftBytes = Arrays.copyOfRange(encodedMessage, 50, 52);
|
||||
int numCurrentDrift = bytesToInt(currentDriftBytes);
|
||||
double currentDriftKnots = unpackMMperSecToKnots(numCurrentDrift);
|
||||
|
||||
byte[] currentSetBytes = Arrays.copyOfRange(encodedMessage, 52, 54);
|
||||
int numCurrentSet = bytesToShort(currentSetBytes);
|
||||
Bearing currentSet = Bearing.fromDegrees(unpackHeading(numCurrentSet));
|
||||
|
||||
byte[] rudderAngleBytes = Arrays.copyOfRange(encodedMessage, 54, 56);
|
||||
short numRudderAngle = bytesToShort(rudderAngleBytes);
|
||||
Azimuth rudderAngle = Azimuth.fromDegrees(unpackTrueWindAngle(numRudderAngle));
|
||||
|
||||
|
||||
message = new BoatLocation(
|
||||
messageVersionNumber,
|
||||
time,
|
||||
sourceID,
|
||||
seqNum,
|
||||
deviceType,
|
||||
latitude,
|
||||
longitude,
|
||||
numAltitude,
|
||||
heading,
|
||||
numPitch,
|
||||
numRoll,
|
||||
boatSpeedKnots,
|
||||
cog,
|
||||
sogKnots,
|
||||
apparentWindSpeedKnots,
|
||||
apparentWindAngle,
|
||||
trueWindSpeedKnots,
|
||||
trueWindDirection,
|
||||
trueWindAngle,
|
||||
currentDriftKnots,
|
||||
currentSet,
|
||||
rudderAngle);
|
||||
|
||||
return message;
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new InvalidMessageException("Could not decode BoatLocation message.", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the decoded message.
|
||||
* @return The decoded message.
|
||||
*/
|
||||
public BoatLocation getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
package network.MessageDecoders;
|
||||
|
||||
|
||||
import network.Exceptions.InvalidMessageException;
|
||||
import network.Messages.BoatStatus;
|
||||
import network.Messages.Enums.BoatStatusEnum;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static network.Utils.ByteConverter.*;
|
||||
|
||||
|
||||
/**
|
||||
* Decodes {@link BoatStatus} messages.
|
||||
*/
|
||||
public class BoatStatusDecoder {
|
||||
|
||||
/**
|
||||
* The encoded message.
|
||||
*/
|
||||
private byte[] encodedMessage;
|
||||
|
||||
/**
|
||||
* The decoded message.
|
||||
*/
|
||||
private BoatStatus message;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a decoder to decode a given message.
|
||||
*/
|
||||
public BoatStatusDecoder() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decodes the contained message.
|
||||
* @param encodedMessage The message to decode.
|
||||
* @return The decoded message.
|
||||
* @throws InvalidMessageException Thrown if the encoded message is invalid in some way, or cannot be decoded.
|
||||
*/
|
||||
public BoatStatus decode(byte[] encodedMessage) throws InvalidMessageException {
|
||||
this.encodedMessage = encodedMessage;
|
||||
|
||||
try {
|
||||
|
||||
byte[] sourceIDBytes = Arrays.copyOfRange(encodedMessage, 0, 4);
|
||||
int sourceID = bytesToInt(sourceIDBytes);
|
||||
|
||||
byte[] boatStatusBytes = Arrays.copyOfRange(encodedMessage, 4, 5);
|
||||
BoatStatusEnum boatStatus = BoatStatusEnum.fromByte(boatStatusBytes[0]);
|
||||
|
||||
byte[] legNumberBytes = Arrays.copyOfRange(encodedMessage, 5, 6);
|
||||
byte legNumber = legNumberBytes[0];
|
||||
|
||||
byte[] numPenaltiesAwardedBytes = Arrays.copyOfRange(encodedMessage, 6, 7);
|
||||
byte numPenaltiesAwarded = numPenaltiesAwardedBytes[0];
|
||||
|
||||
byte[] numPenaltiesServedBytes = Arrays.copyOfRange(encodedMessage, 7, 8);
|
||||
byte numPenaltiesServed = numPenaltiesServedBytes[0];
|
||||
|
||||
byte[] estTimeAtNextMarkBytes = Arrays.copyOfRange(encodedMessage, 8, 14);
|
||||
long estTimeAtNextMark = bytesToLong(estTimeAtNextMarkBytes);
|
||||
|
||||
byte[] estTimeAtFinishBytes = Arrays.copyOfRange(encodedMessage, 14, 20);
|
||||
long estTimeAtFinish = bytesToLong(estTimeAtFinishBytes);
|
||||
|
||||
message = new BoatStatus(
|
||||
sourceID,
|
||||
boatStatus,
|
||||
legNumber,
|
||||
numPenaltiesAwarded,
|
||||
numPenaltiesServed,
|
||||
estTimeAtNextMark,
|
||||
estTimeAtFinish );
|
||||
|
||||
return message;
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new InvalidMessageException("Could not decode BoatStatus message.", e);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the decoded message.
|
||||
* @return The decoded message.
|
||||
*/
|
||||
public BoatStatus getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
@@ -1,64 +1,102 @@
|
||||
package network.MessageDecoders;
|
||||
|
||||
|
||||
import network.Exceptions.InvalidMessageException;
|
||||
import network.Messages.CourseWind;
|
||||
import shared.model.Bearing;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static network.Utils.ByteConverter.bytesToInt;
|
||||
import static network.Utils.ByteConverter.bytesToLong;
|
||||
import static network.Utils.AC35UnitConverter.*;
|
||||
import static network.Utils.ByteConverter.*;
|
||||
|
||||
|
||||
/**
|
||||
* Created by hba56 on 23/04/17.
|
||||
* Decodes {@link CourseWind} messages.
|
||||
*/
|
||||
public class CourseWindDecoder {
|
||||
byte messageVersionNumber;
|
||||
byte byteWindID;
|
||||
byte loopCount;
|
||||
ArrayList<CourseWind> loopMessages = new ArrayList();
|
||||
|
||||
public CourseWindDecoder(byte[] encodedCourseWind) {
|
||||
final int lengthInBytesOfMessages = 20;
|
||||
/**
|
||||
* The encoded message.
|
||||
*/
|
||||
private byte[] encodedMessage;
|
||||
|
||||
messageVersionNumber = encodedCourseWind[0];
|
||||
byteWindID = encodedCourseWind[1];
|
||||
loopCount = encodedCourseWind[2];
|
||||
byte[] loopMessagesBytes = Arrays.copyOfRange(encodedCourseWind, 3, lengthInBytesOfMessages*loopCount+3);
|
||||
int messageLoopIndex = 0;
|
||||
/**
|
||||
* The decoded message.
|
||||
*/
|
||||
private CourseWind message;
|
||||
|
||||
for (int i=0; i < loopCount; i++) {
|
||||
byte[] messageBytes = Arrays.copyOfRange(loopMessagesBytes, messageLoopIndex, messageLoopIndex+20);
|
||||
ArrayList test = new ArrayList();
|
||||
byte[] windId = Arrays.copyOfRange(messageBytes, 0, 1);
|
||||
byte[] time = Arrays.copyOfRange(messageBytes, 1, 7);
|
||||
byte[] raceID = Arrays.copyOfRange(messageBytes, 7, 11);
|
||||
byte[] windDirection = Arrays.copyOfRange(messageBytes, 11, 13);
|
||||
byte[] windSpeed = Arrays.copyOfRange(messageBytes, 13, 15);
|
||||
byte[] bestUpwindAngle = Arrays.copyOfRange(messageBytes, 15, 17);
|
||||
byte[] bestDownwindAngle = Arrays.copyOfRange(messageBytes, 17, 19);
|
||||
byte[] flags = Arrays.copyOfRange(messageBytes, 19, 20);
|
||||
|
||||
CourseWind message = new CourseWind(windId[0], bytesToLong(time),
|
||||
bytesToInt(raceID), bytesToInt(windDirection),
|
||||
bytesToInt(windSpeed), bytesToInt(bestUpwindAngle),
|
||||
bytesToInt(bestDownwindAngle), flags[0]);
|
||||
|
||||
loopMessages.add(message);
|
||||
messageLoopIndex += 20;
|
||||
/**
|
||||
* Constructs a decoder to decode a given message.
|
||||
*/
|
||||
public CourseWindDecoder() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decodes the contained message.
|
||||
* @param encodedMessage The message to decode.
|
||||
* @return The decoded message.
|
||||
* @throws InvalidMessageException Thrown if the encoded message is invalid in some way, or cannot be decoded.
|
||||
*/
|
||||
public CourseWind decode(byte[] encodedMessage) throws InvalidMessageException {
|
||||
this.encodedMessage = encodedMessage;
|
||||
|
||||
try {
|
||||
|
||||
byte[] windId = Arrays.copyOfRange(encodedMessage, 0, 1);
|
||||
|
||||
byte[] timeBytes = Arrays.copyOfRange(encodedMessage, 1, 7);
|
||||
long time = bytesToLong(timeBytes);
|
||||
|
||||
byte[] raceIDBytes = Arrays.copyOfRange(encodedMessage, 7, 11);
|
||||
int raceIDInt = bytesToInt(raceIDBytes);
|
||||
|
||||
byte[] windDirectionBytes = Arrays.copyOfRange(encodedMessage, 11, 13);
|
||||
int windDirectionInt = bytesToInt(windDirectionBytes);
|
||||
Bearing windDirection = Bearing.fromDegrees(unpackHeading(windDirectionInt));
|
||||
|
||||
byte[] windSpeedBytes = Arrays.copyOfRange(encodedMessage, 13, 15);
|
||||
int windSpeedInt = bytesToInt(windSpeedBytes);
|
||||
double windSpeedKnots = unpackMMperSecToKnots(windSpeedInt);
|
||||
|
||||
byte[] bestUpwindAngleBytes = Arrays.copyOfRange(encodedMessage, 15, 17);
|
||||
int bestUpwindAngleInt = bytesToInt(bestUpwindAngleBytes);
|
||||
Bearing bestUpwindAngle = Bearing.fromDegrees(unpackHeading(bestUpwindAngleInt));
|
||||
|
||||
byte[] bestDownwindAngleBytes = Arrays.copyOfRange(encodedMessage, 17, 19);
|
||||
int bestDownwindAngleInt = bytesToInt(bestDownwindAngleBytes);
|
||||
Bearing bestDownwindAngle = Bearing.fromDegrees(unpackHeading(bestDownwindAngleInt));
|
||||
|
||||
byte[] flags = Arrays.copyOfRange(encodedMessage, 19, 20);
|
||||
|
||||
|
||||
message = new CourseWind(
|
||||
windId[0],
|
||||
time,
|
||||
raceIDInt,
|
||||
windDirection,
|
||||
windSpeedKnots,
|
||||
bestUpwindAngle,
|
||||
bestDownwindAngle,
|
||||
flags[0]);
|
||||
|
||||
return message;
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new InvalidMessageException("Could not decode CourseWind message.", e);
|
||||
}
|
||||
}
|
||||
|
||||
public ArrayList<CourseWind> getLoopMessages() {
|
||||
return loopMessages;
|
||||
|
||||
/**
|
||||
* Returns the decoded message.
|
||||
* @return The decoded message.
|
||||
*/
|
||||
public CourseWind getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public byte getMessageVersionNumber() {
|
||||
return messageVersionNumber;
|
||||
}
|
||||
|
||||
public byte getByteWindID() {
|
||||
return byteWindID;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
package network.MessageDecoders;
|
||||
|
||||
|
||||
import network.Exceptions.InvalidMessageException;
|
||||
import network.Messages.AC35Data;
|
||||
import network.Messages.CourseWind;
|
||||
import network.Messages.CourseWinds;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static network.Utils.ByteConverter.bytesToInt;
|
||||
import static network.Utils.ByteConverter.bytesToLong;
|
||||
|
||||
|
||||
/**
|
||||
* Decodes {@link CourseWinds} messages.
|
||||
*/
|
||||
public class CourseWindsDecoder implements MessageDecoder {
|
||||
|
||||
/**
|
||||
* The encoded message.
|
||||
*/
|
||||
private byte[] encodedMessage;
|
||||
|
||||
/**
|
||||
* The decoded message.
|
||||
*/
|
||||
private CourseWinds message;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a decoder to decode a given message.
|
||||
*/
|
||||
public CourseWindsDecoder() {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public AC35Data decode(byte[] encodedMessage) throws InvalidMessageException {
|
||||
this.encodedMessage = encodedMessage;
|
||||
|
||||
try {
|
||||
|
||||
//The header is three bytes.
|
||||
byte messageVersionNumber = encodedMessage[0];
|
||||
byte byteWindID = encodedMessage[1];
|
||||
byte loopCount = encodedMessage[2];
|
||||
|
||||
|
||||
//A CourseWind object is 20 bytes.
|
||||
final int courseWindByteLength = 20;
|
||||
|
||||
List<CourseWind> loopMessages = new ArrayList();
|
||||
|
||||
//The header is 3 bytes, so we need the remaining bytes.
|
||||
byte[] loopMessagesBytes = Arrays.copyOfRange(encodedMessage, 3, courseWindByteLength * loopCount + 3);
|
||||
|
||||
for (int messageLoopIndex = 0; messageLoopIndex < (loopCount * courseWindByteLength); messageLoopIndex += courseWindByteLength) {
|
||||
|
||||
byte[] messageBytes = Arrays.copyOfRange(loopMessagesBytes, messageLoopIndex, messageLoopIndex + courseWindByteLength);
|
||||
|
||||
CourseWindDecoder courseWindDecoder = new CourseWindDecoder();
|
||||
CourseWind courseWind = courseWindDecoder.decode(messageBytes);
|
||||
|
||||
loopMessages.add(courseWind);
|
||||
}
|
||||
|
||||
|
||||
message = new CourseWinds(
|
||||
messageVersionNumber,
|
||||
byteWindID,
|
||||
loopMessages);
|
||||
|
||||
return message;
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new InvalidMessageException("Could not decode CourseWinds message.", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the decoded message.
|
||||
* @return The decoded message.
|
||||
*/
|
||||
public CourseWinds getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package network.MessageDecoders;
|
||||
|
||||
|
||||
import network.Exceptions.InvalidMessageTypeException;
|
||||
import network.Messages.Enums.MessageType;
|
||||
|
||||
/**
|
||||
* Factory to create the appropriate decoder for a given message.
|
||||
*/
|
||||
public class DecoderFactory {
|
||||
|
||||
|
||||
/**
|
||||
* Private constructor. Currently doesn't need to be constructed.
|
||||
*/
|
||||
private DecoderFactory(){
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates the correct type of decoder for a given message type.
|
||||
* @param type Type of message you want a decoder for.
|
||||
* @return The decoder.
|
||||
* @throws InvalidMessageTypeException If you pass in a {@link MessageType} that isn't recognised.
|
||||
*/
|
||||
public static MessageDecoder create(MessageType type) throws InvalidMessageTypeException {
|
||||
|
||||
|
||||
switch (type) {
|
||||
|
||||
case HEARTBEAT: return new HeartBeatDecoder();
|
||||
|
||||
case RACESTATUS: return new RaceStatusDecoder();
|
||||
|
||||
//case DISPLAYTEXTMESSAGE: return new DisplayTextMessageDecoder();//TODO
|
||||
|
||||
case XMLMESSAGE: return new XMLMessageDecoder();
|
||||
|
||||
case RACESTARTSTATUS: return new RaceStartStatusDecoder();
|
||||
|
||||
//case YACHTEVENTCODE: return new YachtEventCodeDecoder();//TODO
|
||||
|
||||
//case YACHTACTIONCODE: return new YachtActionCodeDecoder();//TODO
|
||||
|
||||
//case CHATTERTEXT: return new ChatterTextDecoder();//TODO
|
||||
|
||||
case BOATLOCATION: return new BoatLocationDecoder();
|
||||
|
||||
case MARKROUNDING: return new MarkRoundingDecoder();
|
||||
|
||||
case COURSEWIND: return new CourseWindsDecoder();
|
||||
|
||||
case AVGWIND: return new AverageWindDecoder();
|
||||
|
||||
case REQUEST_TO_JOIN: return new RequestToJoinDecoder();
|
||||
|
||||
case JOIN_ACCEPTANCE: return new JoinAcceptanceDecoder();
|
||||
|
||||
case BOATACTION: return new BoatActionDecoder();
|
||||
|
||||
|
||||
default: throw new InvalidMessageTypeException("Unrecognised message type: " + type);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package network.MessageDecoders;
|
||||
|
||||
import network.Exceptions.InvalidMessageException;
|
||||
import network.Messages.AC35Data;
|
||||
import network.Messages.Enums.BoatActionEnum;
|
||||
import network.Messages.HeartBeat;
|
||||
|
||||
import static network.Utils.ByteConverter.bytesToLong;
|
||||
|
||||
/**
|
||||
* Decodes {@link network.Messages.HeartBeat} messages.
|
||||
*/
|
||||
public class HeartBeatDecoder implements MessageDecoder {
|
||||
|
||||
/**
|
||||
* The encoded message.
|
||||
*/
|
||||
private byte[] encodedMessage;
|
||||
|
||||
/**
|
||||
* The decoded message.
|
||||
*/
|
||||
private HeartBeat message;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a decoder to decode a given message.
|
||||
*/
|
||||
public HeartBeatDecoder() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AC35Data decode(byte[] encodedMessage) throws InvalidMessageException {
|
||||
this.encodedMessage = encodedMessage;
|
||||
|
||||
try {
|
||||
|
||||
message = new HeartBeat(bytesToLong(encodedMessage));
|
||||
|
||||
return message;
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new InvalidMessageException("Could not decode HeartBeat message.", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the decoded message.
|
||||
* @return The decoded message.
|
||||
*/
|
||||
public HeartBeat getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package network.MessageDecoders;
|
||||
|
||||
|
||||
import network.Exceptions.InvalidMessageException;
|
||||
import network.Messages.AC35Data;
|
||||
import network.Messages.Enums.JoinAcceptanceEnum;
|
||||
import network.Messages.JoinAcceptance;
|
||||
import network.Utils.ByteConverter;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Decoder for {@link JoinAcceptance} messages.
|
||||
*/
|
||||
public class JoinAcceptanceDecoder implements MessageDecoder {
|
||||
|
||||
/**
|
||||
* The encoded message.
|
||||
*/
|
||||
private byte[] encodedMessage;
|
||||
|
||||
/**
|
||||
* The decoded message.
|
||||
*/
|
||||
private JoinAcceptance message;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a decoder to decode a given message.
|
||||
*/
|
||||
public JoinAcceptanceDecoder() {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public AC35Data decode(byte[] encodedMessage) throws InvalidMessageException {
|
||||
this.encodedMessage = encodedMessage;
|
||||
|
||||
try {
|
||||
|
||||
//SourceID is first four bytes.
|
||||
byte[] sourceIdBytes = Arrays.copyOfRange(encodedMessage, 0, 4);
|
||||
|
||||
//Next byte is acceptance type.
|
||||
byte[] acceptanceBytes = Arrays.copyOfRange(encodedMessage, 4, 5);
|
||||
|
||||
|
||||
//SourceID is an int.
|
||||
int sourceID = ByteConverter.bytesToInt(sourceIdBytes);
|
||||
|
||||
//Acceptance enum is a byte.
|
||||
JoinAcceptanceEnum acceptanceType = JoinAcceptanceEnum.fromByte(acceptanceBytes[0]);
|
||||
|
||||
|
||||
message = new JoinAcceptance(acceptanceType, sourceID);
|
||||
|
||||
return message;
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new InvalidMessageException("Could not decode JoinAcceptance message.", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the decoded message.
|
||||
* @return The decoded message.
|
||||
*/
|
||||
public JoinAcceptance getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,52 +1,97 @@
|
||||
package network.MessageDecoders;
|
||||
|
||||
|
||||
import network.Exceptions.InvalidMessageException;
|
||||
import network.Messages.AC35Data;
|
||||
import network.Messages.Enums.MarkRoundingBoatStatusEnum;
|
||||
import network.Messages.Enums.MarkRoundingSideEnum;
|
||||
import network.Messages.Enums.MarkRoundingTypeEnum;
|
||||
import network.Messages.MarkRounding;
|
||||
import network.Utils.ByteConverter;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Created by hba56 on 23/04/17.
|
||||
* Decoder for {@link MarkRounding} messages.
|
||||
*/
|
||||
public class MarkRoundingDecoder {
|
||||
byte messageVersionNumber;
|
||||
byte[] byteTime;
|
||||
byte[] byteAck;
|
||||
byte[] byteRaceID;
|
||||
byte[] byteSourceID;
|
||||
byte byteBoatStatus;
|
||||
byte byteRoundingSide;
|
||||
byte byteMarkType;
|
||||
byte byteMarkID;
|
||||
public class MarkRoundingDecoder implements MessageDecoder {
|
||||
|
||||
MarkRounding markRounding;
|
||||
/**
|
||||
* The encoded message.
|
||||
*/
|
||||
private byte[] encodedMessage;
|
||||
|
||||
public MarkRoundingDecoder(byte[] encodedMarkRounding) {
|
||||
messageVersionNumber = encodedMarkRounding[0];
|
||||
byteTime = Arrays.copyOfRange(encodedMarkRounding, 1, 7);
|
||||
byteAck = Arrays.copyOfRange(encodedMarkRounding, 7, 9);
|
||||
byteRaceID = Arrays.copyOfRange(encodedMarkRounding, 9, 13);
|
||||
byteSourceID = Arrays.copyOfRange(encodedMarkRounding, 13, 17);
|
||||
byteBoatStatus = encodedMarkRounding[17];
|
||||
byteRoundingSide = encodedMarkRounding[18];
|
||||
byteMarkType = encodedMarkRounding[19];
|
||||
byteMarkID = encodedMarkRounding[20];
|
||||
/**
|
||||
* The decoded message.
|
||||
*/
|
||||
private MarkRounding message;
|
||||
|
||||
int intMsgVer = ByteConverter.bytesToInt(messageVersionNumber);
|
||||
long lngTime = ByteConverter.bytesToLong(byteTime);
|
||||
int intAck = ByteConverter.bytesToInt(byteAck);
|
||||
int intRaceID = ByteConverter.bytesToInt(byteRaceID);
|
||||
int intSourceID = ByteConverter.bytesToInt(byteSourceID);
|
||||
int intBoatState = ByteConverter.bytesToInt(byteBoatStatus);
|
||||
int intRoundingSide = ByteConverter.bytesToInt(byteRoundingSide);
|
||||
int intMarkType = ByteConverter.bytesToInt(byteMarkType);
|
||||
int intMarkID = ByteConverter.bytesToInt(byteMarkID);
|
||||
|
||||
markRounding = new MarkRounding(intMsgVer, lngTime, intAck, intRaceID, intSourceID, intBoatState, intRoundingSide, intMarkType, intMarkID);
|
||||
/**
|
||||
* Constructs a decoder to decode a given message.
|
||||
*/
|
||||
public MarkRoundingDecoder() {
|
||||
}
|
||||
|
||||
public MarkRounding getMarkRounding() {
|
||||
return markRounding;
|
||||
@Override
|
||||
public AC35Data decode(byte[] encodedMessage) throws InvalidMessageException {
|
||||
this.encodedMessage = encodedMessage;
|
||||
|
||||
try {
|
||||
|
||||
byte messageVersionNumber = encodedMessage[0];
|
||||
|
||||
byte[] byteTime = Arrays.copyOfRange(encodedMessage, 1, 7);
|
||||
long time = ByteConverter.bytesToLong(byteTime);
|
||||
|
||||
byte[] byteAck = Arrays.copyOfRange(encodedMessage, 7, 9);
|
||||
int ackNumber = ByteConverter.bytesToInt(byteAck);
|
||||
|
||||
byte[] byteRaceID = Arrays.copyOfRange(encodedMessage, 9, 13);
|
||||
int raceID = ByteConverter.bytesToInt(byteRaceID);
|
||||
|
||||
byte[] byteSourceID = Arrays.copyOfRange(encodedMessage, 13, 17);
|
||||
int sourceID = ByteConverter.bytesToInt(byteSourceID);
|
||||
|
||||
byte byteBoatStatus = encodedMessage[17];
|
||||
MarkRoundingBoatStatusEnum boatStatus = MarkRoundingBoatStatusEnum.fromByte(byteBoatStatus);
|
||||
|
||||
byte byteRoundingSide = encodedMessage[18];
|
||||
MarkRoundingSideEnum roundingSide = MarkRoundingSideEnum.fromByte(byteRoundingSide);
|
||||
|
||||
byte byteMarkType = encodedMessage[19];
|
||||
MarkRoundingTypeEnum markType = MarkRoundingTypeEnum.fromByte(byteMarkType);
|
||||
|
||||
byte byteMarkID = encodedMessage[20];
|
||||
|
||||
|
||||
message = new MarkRounding(
|
||||
messageVersionNumber,
|
||||
time,
|
||||
ackNumber,
|
||||
raceID,
|
||||
sourceID,
|
||||
boatStatus,
|
||||
roundingSide,
|
||||
markType,
|
||||
byteMarkID);
|
||||
|
||||
|
||||
return message;
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new InvalidMessageException("Could not decode AverageWind message.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the decoded message.
|
||||
*
|
||||
* @return The decoded message.
|
||||
*/
|
||||
public MarkRounding getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package network.MessageDecoders;
|
||||
|
||||
|
||||
import network.Exceptions.InvalidMessageException;
|
||||
import network.Messages.AC35Data;
|
||||
|
||||
|
||||
/**
|
||||
* This is the interface that all message decoders must implement.
|
||||
* It allows for {@link #decode(byte[])}ing messages.
|
||||
*/
|
||||
public interface MessageDecoder {
|
||||
|
||||
|
||||
/**
|
||||
* Decodes a given message.
|
||||
* @param encodedMessage The message to decode.
|
||||
* @return The decoded message.
|
||||
* @throws InvalidMessageException Thrown if the encoded message is invalid in some way, or cannot be decoded.
|
||||
*/
|
||||
public AC35Data decode(byte[] encodedMessage) throws InvalidMessageException;
|
||||
|
||||
}
|
||||
@@ -1,66 +1,86 @@
|
||||
package network.MessageDecoders;
|
||||
|
||||
|
||||
import network.Exceptions.InvalidMessageException;
|
||||
import network.Messages.AC35Data;
|
||||
import network.Messages.Enums.RaceStartTypeEnum;
|
||||
import network.Messages.RaceStartStatus;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static network.Utils.ByteConverter.*;
|
||||
|
||||
|
||||
/**
|
||||
* Created by hba56 on 21/04/17.
|
||||
* Decodes {@link RaceStartStatus} messages.
|
||||
*/
|
||||
public class RaceStartStatusDecoder {
|
||||
private byte messageVersion;
|
||||
private byte[] timestamp;
|
||||
private byte[] ackNumber;
|
||||
private byte[] raceStartTime;
|
||||
private byte[] raceIdentifier;
|
||||
private byte notificationType;
|
||||
public class RaceStartStatusDecoder implements MessageDecoder {
|
||||
|
||||
private long time;
|
||||
private short ack;
|
||||
private long startTime;
|
||||
private int raceID;
|
||||
private char notification;
|
||||
/**
|
||||
* The encoded message.
|
||||
*/
|
||||
private byte[] encodedMessage;
|
||||
|
||||
/**
|
||||
* The decoded message.
|
||||
*/
|
||||
private RaceStartStatus message;
|
||||
|
||||
|
||||
public RaceStartStatusDecoder(byte[] encodedRaceStartStatus) {
|
||||
messageVersion = encodedRaceStartStatus[0];
|
||||
timestamp = Arrays.copyOfRange(encodedRaceStartStatus, 1, 7);
|
||||
ackNumber = Arrays.copyOfRange(encodedRaceStartStatus, 7, 9);
|
||||
raceStartTime = Arrays.copyOfRange(encodedRaceStartStatus, 9, 15);
|
||||
raceIdentifier = Arrays.copyOfRange(encodedRaceStartStatus, 15, 19);
|
||||
notificationType = encodedRaceStartStatus[19];
|
||||
|
||||
time = bytesToLong(timestamp);
|
||||
ack = bytesToShort(ackNumber);
|
||||
startTime = bytesToLong(raceStartTime);
|
||||
raceID = bytesToInt(raceIdentifier);
|
||||
notification = bytesToChar(notificationType);
|
||||
/**
|
||||
* Constructs a decoder to decode a given message.
|
||||
*/
|
||||
public RaceStartStatusDecoder() {
|
||||
}
|
||||
|
||||
|
||||
public byte getMessageVersion() {
|
||||
return messageVersion;
|
||||
@Override
|
||||
public AC35Data decode(byte[] encodedMessage) throws InvalidMessageException {
|
||||
this.encodedMessage = encodedMessage;
|
||||
|
||||
try {
|
||||
|
||||
byte messageVersion = encodedMessage[0];
|
||||
|
||||
byte[] timestamp = Arrays.copyOfRange(encodedMessage, 1, 7);
|
||||
long time = bytesToLong(timestamp);
|
||||
|
||||
byte[] ackNumber = Arrays.copyOfRange(encodedMessage, 7, 9);
|
||||
short ack = bytesToShort(ackNumber);
|
||||
|
||||
byte[] raceStartTime = Arrays.copyOfRange(encodedMessage, 9, 15);
|
||||
long startTime = bytesToLong(raceStartTime);
|
||||
|
||||
byte[] raceIdentifier = Arrays.copyOfRange(encodedMessage, 15, 19);
|
||||
int raceID = bytesToInt(raceIdentifier);
|
||||
|
||||
byte notificationType = encodedMessage[19];
|
||||
|
||||
|
||||
message = new RaceStartStatus(
|
||||
messageVersion,
|
||||
time,
|
||||
ack,
|
||||
startTime,
|
||||
raceID,
|
||||
RaceStartTypeEnum.fromByte(notificationType)
|
||||
);
|
||||
|
||||
return message;
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new InvalidMessageException("Could not decode RaceStartStatus message.", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public short getAck() {
|
||||
return ack;
|
||||
}
|
||||
|
||||
public long getStartTime() {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
public int getRaceID() {
|
||||
return raceID;
|
||||
}
|
||||
|
||||
public char getNotification() {
|
||||
return notification;
|
||||
/**
|
||||
* Returns the decoded message.
|
||||
* @return The decoded message.
|
||||
*/
|
||||
public RaceStartStatus getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,119 +1,125 @@
|
||||
package network.MessageDecoders;
|
||||
|
||||
|
||||
import network.Exceptions.InvalidMessageException;
|
||||
import network.Messages.AC35Data;
|
||||
import network.Messages.BoatStatus;
|
||||
import network.Messages.Enums.RaceStatusEnum;
|
||||
import network.Messages.Enums.RaceTypeEnum;
|
||||
import network.Messages.RaceStatus;
|
||||
import network.Utils.AC35UnitConverter;
|
||||
import shared.model.Bearing;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static network.Utils.ByteConverter.*;
|
||||
|
||||
|
||||
/**
|
||||
* Created by hba56 on 21/04/17.
|
||||
* Decodes {@link RaceStatus} messages.
|
||||
*/
|
||||
public class RaceStatusDecoder {
|
||||
private byte versionNum;
|
||||
private byte[] timeBytes;
|
||||
private byte[] raceID;
|
||||
private byte raceStatus;
|
||||
private byte[] expectedStart;
|
||||
private byte[] raceWind;
|
||||
private byte[] windSpeed;
|
||||
private byte numBoats;
|
||||
private byte bytesRaceType;
|
||||
private byte[] boatsBytes;
|
||||
public class RaceStatusDecoder implements MessageDecoder {
|
||||
|
||||
private long time;
|
||||
private int race;
|
||||
private byte raceState;
|
||||
private long startTime;
|
||||
private int raceWindDir;
|
||||
private short raceWindSpeed;
|
||||
private int numberOfBoats;
|
||||
private int raceType;
|
||||
private ArrayList<BoatStatus> boats = new ArrayList<>();
|
||||
/**
|
||||
* The encoded message.
|
||||
*/
|
||||
private byte[] encodedMessage;
|
||||
|
||||
/**
|
||||
* The decoded message.
|
||||
*/
|
||||
private RaceStatus message;
|
||||
|
||||
|
||||
public RaceStatusDecoder(byte[] encodedRaceStatus){
|
||||
versionNum = encodedRaceStatus[0];
|
||||
timeBytes = Arrays.copyOfRange(encodedRaceStatus, 1, 7);
|
||||
raceID = Arrays.copyOfRange(encodedRaceStatus, 7, 11);
|
||||
raceStatus = encodedRaceStatus[11];
|
||||
expectedStart = Arrays.copyOfRange(encodedRaceStatus, 12, 18);
|
||||
raceWind = Arrays.copyOfRange(encodedRaceStatus, 18, 20);
|
||||
windSpeed = Arrays.copyOfRange(encodedRaceStatus, 20, 22);
|
||||
numBoats = encodedRaceStatus[22];
|
||||
bytesRaceType = encodedRaceStatus[23];
|
||||
boatsBytes = Arrays.copyOfRange(encodedRaceStatus, 24, 25+20*this.numBoats);
|
||||
|
||||
time = bytesToLong(timeBytes);
|
||||
race = bytesToInt(raceID);
|
||||
raceState = raceStatus;
|
||||
startTime = bytesToLong(expectedStart);
|
||||
raceWindDir = bytesToInt(raceWind);
|
||||
raceWindSpeed = bytesToShort(windSpeed);
|
||||
numberOfBoats = bytesToInt(numBoats);
|
||||
/**
|
||||
* Constructs a decoder to decode a given message.
|
||||
*/
|
||||
public RaceStatusDecoder() {
|
||||
}
|
||||
|
||||
int boatLoopIndex = 0;
|
||||
|
||||
for (int i=0; i < numberOfBoats; i++) {
|
||||
byte[] boatBytes = Arrays.copyOfRange(boatsBytes, boatLoopIndex, boatLoopIndex+20);
|
||||
@Override
|
||||
public AC35Data decode(byte[] encodedMessage) throws InvalidMessageException {
|
||||
this.encodedMessage = encodedMessage;
|
||||
|
||||
byte[] sourceID = Arrays.copyOfRange(boatBytes, 0, 3);
|
||||
byte boatStatus = boatBytes[4];
|
||||
byte legNumber = boatBytes[5];
|
||||
byte numPenaltiesAwarded = boatBytes[6];
|
||||
byte numPenaltiesServed = boatBytes[7];
|
||||
byte[] estTimeAtNextMark = Arrays.copyOfRange(boatBytes, 8, 14);
|
||||
byte[] estTimeAtFinish = Arrays.copyOfRange(boatBytes, 14, 20);
|
||||
try {
|
||||
|
||||
BoatStatus boat = new BoatStatus(bytesToInt(sourceID),boatStatus,
|
||||
legNumber, numPenaltiesAwarded, numPenaltiesServed,
|
||||
bytesToLong(estTimeAtNextMark), bytesToLong(estTimeAtFinish));
|
||||
byte[] versionNumBytes = Arrays.copyOfRange(encodedMessage, 0, 1);
|
||||
byte versionNum = versionNumBytes[0];
|
||||
|
||||
boats.add(boat);
|
||||
boatLoopIndex += 20;
|
||||
byte[] timeBytes = Arrays.copyOfRange(encodedMessage, 1, 7);
|
||||
long time = bytesToLong(timeBytes);
|
||||
|
||||
byte[] raceIDBytes = Arrays.copyOfRange(encodedMessage, 7, 11);
|
||||
int raceID = bytesToInt(raceIDBytes);
|
||||
|
||||
byte[] raceStatusBytes = Arrays.copyOfRange(encodedMessage, 11, 12);
|
||||
RaceStatusEnum raceStatus = RaceStatusEnum.fromByte(raceStatusBytes[0]);
|
||||
|
||||
byte[] expectedStartBytes = Arrays.copyOfRange(encodedMessage, 12, 18);
|
||||
long expectedStart = bytesToLong(expectedStartBytes);
|
||||
|
||||
byte[] windDirectionBytes = Arrays.copyOfRange(encodedMessage, 18, 20);
|
||||
int windDirectionInt = bytesToInt(windDirectionBytes);
|
||||
Bearing windDirection = Bearing.fromDegrees(AC35UnitConverter.unpackHeading(windDirectionInt));
|
||||
|
||||
byte[] windSpeedBytes = Arrays.copyOfRange(encodedMessage, 20, 22);
|
||||
int windSpeedInt = bytesToInt(windSpeedBytes);
|
||||
double windSpeedKnots = AC35UnitConverter.unpackMMperSecToKnots(windSpeedInt);
|
||||
|
||||
byte[] numberOfBoatsBytes = Arrays.copyOfRange(encodedMessage, 22, 23);
|
||||
int numberOfBoats = bytesToInt(numberOfBoatsBytes);
|
||||
|
||||
byte[] raceTypeBytes = Arrays.copyOfRange(encodedMessage, 23, 24);
|
||||
RaceTypeEnum raceType = RaceTypeEnum.fromByte(raceTypeBytes[0]);
|
||||
|
||||
byte[] boatStatusesBytes = Arrays.copyOfRange(encodedMessage, 24, 25 + 20 * numberOfBoats);
|
||||
List<BoatStatus> boatStatuses = new ArrayList<>();
|
||||
|
||||
|
||||
//BoatStatus is 20 bytes.
|
||||
int boatStatusByteLength = 20;
|
||||
|
||||
|
||||
//Decode each BoatStatus.
|
||||
for (int boatLoopIndex = 0; boatLoopIndex < (numberOfBoats * boatStatusByteLength); boatLoopIndex += boatStatusByteLength) {
|
||||
|
||||
byte[] boatStatusBytes = Arrays.copyOfRange(boatStatusesBytes, boatLoopIndex, boatLoopIndex + boatStatusByteLength);
|
||||
|
||||
BoatStatusDecoder boatStatusDecoder = new BoatStatusDecoder();
|
||||
|
||||
boatStatuses.add(boatStatusDecoder.decode(boatStatusBytes));
|
||||
}
|
||||
|
||||
|
||||
message = new RaceStatus(
|
||||
versionNum,
|
||||
time,
|
||||
raceID,
|
||||
raceStatus,
|
||||
expectedStart,
|
||||
windDirection,
|
||||
windSpeedKnots,
|
||||
raceType,
|
||||
boatStatuses);
|
||||
|
||||
return message;
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new InvalidMessageException("Could not decode RaceStatus message.", e);
|
||||
}
|
||||
}
|
||||
|
||||
public byte getVersionNum() {
|
||||
return versionNum;
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public int getRace() {
|
||||
return race;
|
||||
}
|
||||
|
||||
public byte getRaceState() {
|
||||
return raceState;
|
||||
}
|
||||
|
||||
public long getStartTime() {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
public int getRaceWindDir() {
|
||||
return raceWindDir;
|
||||
}
|
||||
|
||||
public short getRaceWindSpeed() {
|
||||
return raceWindSpeed;
|
||||
}
|
||||
|
||||
public int getNumberOfBoats() {
|
||||
return numberOfBoats;
|
||||
}
|
||||
|
||||
public int getRaceType() {
|
||||
return raceType;
|
||||
}
|
||||
|
||||
public ArrayList<BoatStatus> getBoats() {
|
||||
return boats;
|
||||
/**
|
||||
* Returns the decoded message.
|
||||
* @return The decoded message.
|
||||
*/
|
||||
public RaceStatus getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
package network.MessageDecoders;
|
||||
|
||||
|
||||
import network.Exceptions.InvalidMessageException;
|
||||
import network.Messages.AC35Data;
|
||||
import network.Messages.Enums.RequestToJoinEnum;
|
||||
import network.Messages.RequestToJoin;
|
||||
import network.Utils.ByteConverter;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Decoder for {@link network.Messages.RequestToJoin} messages.
|
||||
*/
|
||||
public class RequestToJoinDecoder implements MessageDecoder{
|
||||
|
||||
/**
|
||||
* The encoded message.
|
||||
*/
|
||||
private byte[] encodedRequest;
|
||||
|
||||
/**
|
||||
* The decoded message.
|
||||
*/
|
||||
private RequestToJoin message;
|
||||
|
||||
/**
|
||||
* Constructs a decoder to decode a given message.
|
||||
*/
|
||||
public RequestToJoinDecoder() {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public AC35Data decode(byte[] encodedRequest) throws InvalidMessageException {
|
||||
this.encodedRequest = encodedRequest;
|
||||
|
||||
try {
|
||||
|
||||
//Request type is first four bytes.
|
||||
byte[] requestTypeBytes = Arrays.copyOfRange(encodedRequest, 0, 4);
|
||||
|
||||
//Request type is an integral type.
|
||||
int requestTypeInt = ByteConverter.bytesToInt(requestTypeBytes);
|
||||
RequestToJoinEnum requestType = RequestToJoinEnum.fromInt(requestTypeInt);
|
||||
|
||||
|
||||
message = new RequestToJoin(requestType);
|
||||
|
||||
return message;
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new InvalidMessageException("Could not decode RequestToJoin message.", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the decoded message.
|
||||
* @return The decoded message.
|
||||
*/
|
||||
public RequestToJoin getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
package network.MessageDecoders;
|
||||
|
||||
import network.Exceptions.InvalidMessageException;
|
||||
import network.Messages.AC35Data;
|
||||
import network.Messages.Enums.XMLMessageType;
|
||||
import network.Messages.XMLMessage;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@@ -9,73 +12,74 @@ import static network.Utils.ByteConverter.bytesToShort;
|
||||
|
||||
|
||||
/**
|
||||
* Created by hba56 on 20/04/17.
|
||||
* Decodes {@link network.Messages.XMLMessage} messages.
|
||||
*/
|
||||
public class XMLMessageDecoder {
|
||||
private byte messageVersionNumber;
|
||||
private short ackNumber;
|
||||
private long timeStamp;
|
||||
private byte xmlMsgSubType;
|
||||
private short sequenceNumber;
|
||||
private short xmlMsgLength;
|
||||
private String xmlMessage;
|
||||
public class XMLMessageDecoder implements MessageDecoder {
|
||||
|
||||
private byte[] bytes;
|
||||
/**
|
||||
* The encoded message.
|
||||
*/
|
||||
private byte[] encodedMessage;
|
||||
|
||||
public XMLMessageDecoder(byte[] bytes) {
|
||||
this.bytes = bytes;
|
||||
}
|
||||
|
||||
public void decode(){
|
||||
byte[] ackNumberBytes = Arrays.copyOfRange(bytes, 1, 3);
|
||||
byte[] timeStampBytes = Arrays.copyOfRange(bytes, 3, 9);
|
||||
byte[] sequenceNumberBytes = Arrays.copyOfRange(bytes, 10, 12);
|
||||
byte[] xmlMsgLengthBytes = Arrays.copyOfRange(bytes, 12, 14);
|
||||
byte[] xmlMessagebytes = Arrays.copyOfRange(bytes, 14, bytes.length);
|
||||
|
||||
this.xmlMsgSubType = bytes[9];
|
||||
this.messageVersionNumber = bytes[0];
|
||||
this.ackNumber = bytesToShort(ackNumberBytes);
|
||||
|
||||
this.timeStamp = bytesToLong(timeStampBytes);
|
||||
|
||||
this.sequenceNumber = bytesToShort(sequenceNumberBytes);
|
||||
this.xmlMsgLength = bytesToShort(xmlMsgLengthBytes);
|
||||
this.xmlMessage = new String(xmlMessagebytes).trim();
|
||||
}
|
||||
|
||||
public byte getMessageVersionNumber() {
|
||||
return messageVersionNumber;
|
||||
}
|
||||
|
||||
public short getAckNumber() {
|
||||
return ackNumber;
|
||||
}
|
||||
|
||||
public long getTimeStamp() {
|
||||
return timeStamp;
|
||||
}
|
||||
|
||||
public XMLMessageType getXmlMsgSubType() {
|
||||
return XMLMessageType.fromByte(xmlMsgSubType);
|
||||
}
|
||||
|
||||
public short getSequenceNumber() {
|
||||
return sequenceNumber;
|
||||
}
|
||||
|
||||
public short getXmlMsgLength() {
|
||||
return xmlMsgLength;
|
||||
}
|
||||
/**
|
||||
* The decoded message.
|
||||
*/
|
||||
private XMLMessage message;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the contents of the XML message (e.g., the contents of a race.xml file).
|
||||
* @return The contents of the XML message.
|
||||
* Constructs a decoder to decode a given message.
|
||||
*/
|
||||
public String getXmlMessageContents() {
|
||||
return xmlMessage;
|
||||
public XMLMessageDecoder() {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public AC35Data decode(byte[] encodedMessage) throws InvalidMessageException {
|
||||
this.encodedMessage = encodedMessage;
|
||||
|
||||
try {
|
||||
|
||||
byte[] messageVersionNumberBytes = Arrays.copyOfRange(encodedMessage, 0, 1);
|
||||
byte[] ackNumberBytes = Arrays.copyOfRange(encodedMessage, 1, 3);
|
||||
byte[] timeStampBytes = Arrays.copyOfRange(encodedMessage, 3, 9);
|
||||
byte[] xmlMsgSubTypeBytes = Arrays.copyOfRange(encodedMessage, 9, 10);
|
||||
byte[] sequenceNumberBytes = Arrays.copyOfRange(encodedMessage, 10, 12);
|
||||
byte[] xmlMsgLengthBytes = Arrays.copyOfRange(encodedMessage, 12, 14);
|
||||
byte[] xmlMessagebytes = Arrays.copyOfRange(encodedMessage, 14, encodedMessage.length);
|
||||
|
||||
|
||||
byte messageVersionNumber = messageVersionNumberBytes[0];
|
||||
short ackNumber = bytesToShort(ackNumberBytes);
|
||||
long timeStamp = bytesToLong(timeStampBytes);
|
||||
XMLMessageType xmlMsgSubType = XMLMessageType.fromByte(xmlMsgSubTypeBytes[0]);
|
||||
short sequenceNumber = bytesToShort(sequenceNumberBytes);
|
||||
short xmlMsgLength = bytesToShort(xmlMsgLengthBytes);
|
||||
String xmlMessage = new String(xmlMessagebytes);
|
||||
|
||||
|
||||
message = new XMLMessage(
|
||||
messageVersionNumber,
|
||||
ackNumber,
|
||||
timeStamp,
|
||||
xmlMsgSubType,
|
||||
sequenceNumber,
|
||||
xmlMessage);
|
||||
|
||||
return message;
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new InvalidMessageException("Could not decode XMLMessage message.", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the decoded message.
|
||||
* @return The decoded message.
|
||||
*/
|
||||
public XMLMessage getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user