Renamed each test folder to test_old as tests haven't been updated to use new code! Removed unused stuff from mock/visualiser pom.xml.main
parent
2a82298571
commit
2c5380f5d8
@ -1,277 +0,0 @@
|
||||
package seng302.Networking;
|
||||
|
||||
import seng302.Networking.Exceptions.InvalidMessageException;
|
||||
import seng302.Networking.MessageDecoders.*;
|
||||
import seng302.Networking.Messages.*;
|
||||
import seng302.Networking.Utils.*;
|
||||
import seng302.Networking.Messages.Enums.MessageType;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.zip.CRC32;
|
||||
|
||||
/**
|
||||
* This class can be used to decode/convert a byte array into a messageBody object, descended from AC35Data.
|
||||
*/
|
||||
public class BinaryMessageDecoder {
|
||||
|
||||
///Length of the header.
|
||||
private static final int headerLength = 15;
|
||||
///Length of the CRC.
|
||||
private static final int CRCLength = 4;//TODO these should probably be static defined somewhere else to be shared.
|
||||
|
||||
///The value the first sync byte should have.
|
||||
private static final byte syncByte1 = (byte) 0x47;
|
||||
//The value the second sync byte should have.
|
||||
private static final byte syncByte2 = (byte) 0x83;
|
||||
|
||||
///The full message.
|
||||
private byte[] fullMessage;
|
||||
///The messageHeader.
|
||||
private byte[] messageHeader;
|
||||
///The messageBody.
|
||||
private byte[] messageBody;
|
||||
|
||||
///The sync bytes from the header..
|
||||
private byte headerSync1;
|
||||
private byte headerSync2;
|
||||
|
||||
///The message type from the header.
|
||||
private byte headerMessageType;
|
||||
|
||||
///The timestamp from the header.
|
||||
private long headerTimeStamp;
|
||||
|
||||
///The source ID from the header.
|
||||
private int headerSourceID;
|
||||
|
||||
///The message body length from the header.
|
||||
private int messageBodyLength;
|
||||
|
||||
///CRC value read from message header.
|
||||
private long messageCRCValue;
|
||||
///Calculated CRC value from message.
|
||||
private long calculatedCRCValue;
|
||||
|
||||
|
||||
/**
|
||||
* Ctor.
|
||||
* @param fullMessage Entire encoded binary message.
|
||||
*/
|
||||
public BinaryMessageDecoder(byte[] fullMessage) {
|
||||
this.fullMessage = fullMessage;
|
||||
|
||||
//Get the messageHeader.
|
||||
this.messageHeader = Arrays.copyOfRange(this.fullMessage, 0, 15);
|
||||
|
||||
//Get the sync bytes.
|
||||
this.headerSync1 = this.messageHeader[0];
|
||||
this.headerSync2 = this.messageHeader[1];
|
||||
|
||||
//Get the message type.
|
||||
this.headerMessageType = this.messageHeader[2];
|
||||
|
||||
//Get the header timestamp.
|
||||
this.headerTimeStamp = ByteConverter.bytesToLong(Arrays.copyOfRange(this.messageHeader, 3, 9));
|
||||
|
||||
//Get the source ID for the message.
|
||||
this.headerSourceID = ByteConverter.bytesToInt(Arrays.copyOfRange(this.messageHeader, 9, 13));
|
||||
|
||||
//Get the length of the message body.
|
||||
this.messageBodyLength = ByteConverter.bytesToInt(Arrays.copyOfRange(this.messageHeader, 13, 15));
|
||||
|
||||
|
||||
//Get the messageBody.
|
||||
this.messageBody = Arrays.copyOfRange(this.fullMessage, this.headerLength, this.headerLength + this.messageBodyLength);
|
||||
|
||||
//Get the CRC value.
|
||||
this.messageCRCValue = ByteConverter.bytesToLong(Arrays.copyOfRange(this.fullMessage, this.fullMessage.length - CRCLength, this.fullMessage.length));
|
||||
|
||||
//Combine the header and body into a single array.
|
||||
ByteBuffer headerBodyByteBuffer = ByteBuffer.allocate(messageHeader.length + messageBody.length);
|
||||
headerBodyByteBuffer.put(messageHeader);
|
||||
headerBodyByteBuffer.put(messageBody);
|
||||
|
||||
//Calculate the CRC value from the header+body array.
|
||||
CRC32 crc = new CRC32();
|
||||
crc.reset();
|
||||
crc.update(headerBodyByteBuffer.array());
|
||||
this.calculatedCRCValue = crc.getValue();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decodes the byte array (binary message) this object was initialized with, and returns the corresponding message object.
|
||||
* @return Message object corresponding to the binary message.
|
||||
* @throws InvalidMessageException If the message cannot be decoded.
|
||||
*/
|
||||
public AC35Data decode() throws InvalidMessageException {
|
||||
|
||||
//Run through the checks to ensure that the message is valid.
|
||||
if (messageBody.length != messageBodyLength) {//keep like this - hba65
|
||||
//Check the message body length.
|
||||
throw new InvalidMessageException("MessageBody length in header does not equal the messageBody length. MessageBody length in header is: " + messageBodyLength + ", should be: " + messageBody.length);
|
||||
|
||||
}else if (headerSync1 != syncByte1) {
|
||||
//Check the first sync byte.
|
||||
throw new InvalidMessageException("Sync byte 1 is wrong. Sync byte is: " + headerSync1 + ", should be: " + syncByte1);
|
||||
|
||||
}else if (headerSync2 != syncByte2) {
|
||||
//Check the second sync byte.
|
||||
throw new InvalidMessageException("Sync byte 2 is wrong. Sync byte is: " + headerSync2 + ", should be: " + syncByte2);
|
||||
|
||||
}else if (calculatedCRCValue != messageCRCValue) {
|
||||
//Check the CRC value.
|
||||
throw new InvalidMessageException("CRC value is wrong. The calculated value is: " + calculatedCRCValue + ", should be: " + messageCRCValue);
|
||||
|
||||
}
|
||||
|
||||
//Now we create the message object based on what is actually in the message body.
|
||||
MessageType mType = MessageType.fromByte(headerMessageType);
|
||||
|
||||
switch(mType) {
|
||||
case HEARTBEAT:
|
||||
//System.out.println("Decoding HeartBeat Message!");
|
||||
//TODO maybe use HeartbeatDecoder.decode(message).
|
||||
//TODO also, decoders for each message type should encapsulate the constructing of the object. E.g., return HeartbeatDecoder.decode(message);.
|
||||
return new Heartbeat(ByteConverter.bytesToLong(messageBody));
|
||||
|
||||
case RACESTATUS:
|
||||
//System.out.println("Race Status Message");
|
||||
RaceStatusDecoder rsdecoder = new RaceStatusDecoder(messageBody);
|
||||
return new RaceStatus(rsdecoder.getTime(), rsdecoder.getRace(), rsdecoder.getRaceState(), rsdecoder.getStartTime(), rsdecoder.getRaceWindDir(), rsdecoder.getRaceWindSpeed(), rsdecoder.getRaceType(), rsdecoder.getBoats());
|
||||
|
||||
case DISPLAYTEXTMESSAGE:
|
||||
//System.out.println("Display Text Message");
|
||||
//No decoder for this.
|
||||
//throw new InvalidMessageException("Cannot decode DISPLAYTEXTMESSAGE - no decoder.");
|
||||
|
||||
case XMLMESSAGE:
|
||||
//System.out.println("XML Message!");
|
||||
XMLMessageDecoder xmdecoder = new XMLMessageDecoder(messageBody);
|
||||
xmdecoder.decode();
|
||||
return new XMLMessage(xmdecoder.getAckNumber(), xmdecoder.getTimeStamp(), xmdecoder.getXmlMsgSubType(), xmdecoder.getSequenceNumber(), xmdecoder.getXmlMsgLength(), xmdecoder.getXmlMessageInputStream());
|
||||
|
||||
case RACESTARTSTATUS:
|
||||
//System.out.println("Race Start Status Message");
|
||||
RaceStartStatusDecoder rssDecoder = new RaceStartStatusDecoder(messageBody);
|
||||
return new RaceStartStatus(rssDecoder.getTime(), rssDecoder.getAck(), rssDecoder.getStartTime(), rssDecoder.getRaceID(), rssDecoder. getNotification());
|
||||
|
||||
case YACHTEVENTCODE:
|
||||
//System.out.println("Yacht Action Code!");
|
||||
//No decoder for this.
|
||||
//throw new InvalidMessageException("Cannot decode YACHTEVENTCODE - no decoder.");
|
||||
|
||||
case YACHTACTIONCODE:
|
||||
//System.out.println("Yacht Action Code!");
|
||||
//No decoder for this.
|
||||
//throw new InvalidMessageException("Cannot decode YACHTACTIONCODE - no decoder.");
|
||||
|
||||
case CHATTERTEXT:
|
||||
//System.out.println("Chatter Text Message!");
|
||||
//No decoder for this.
|
||||
//throw new InvalidMessageException("Cannot decode CHATTERTEXT - no decoder.");
|
||||
|
||||
case BOATLOCATION:
|
||||
//System.out.println("Boat Location Message!");
|
||||
BoatLocationDecoder blDecoder = new BoatLocationDecoder(messageBody);
|
||||
return blDecoder.getMessage();
|
||||
|
||||
case MARKROUNDING:
|
||||
//System.out.println("Mark Rounding Message!");
|
||||
MarkRoundingDecoder mrDecoder = new MarkRoundingDecoder(messageBody);
|
||||
return mrDecoder.getMarkRounding();
|
||||
|
||||
case COURSEWIND:
|
||||
//System.out.println("Course Wind Message!");
|
||||
CourseWindDecoder cwDecoder = new CourseWindDecoder(messageBody);
|
||||
return new CourseWinds(cwDecoder.getMessageVersionNumber(), cwDecoder.getByteWindID(), cwDecoder.getLoopMessages());
|
||||
|
||||
case AVGWIND:
|
||||
//System.out.println("Average Wind Message!");
|
||||
AverageWindDecoder awDecoder = new AverageWindDecoder(messageBody);
|
||||
return awDecoder.getAverageWind();
|
||||
|
||||
default:
|
||||
//System.out.println("Broken Message!");
|
||||
//throw new InvalidMessageException("Broken message! Did not recognise message type: " + headerMessageType + ".");
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the first sync byte value.
|
||||
* @return The first sync byte value.
|
||||
*/
|
||||
public byte getHeaderSync1() {
|
||||
return headerSync1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the second sync byte value.
|
||||
* @return The second sync byte value.
|
||||
*/
|
||||
public byte getHeaderSync2() {
|
||||
return headerSync2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the message type.
|
||||
* @return The message type.
|
||||
*/
|
||||
public byte getHeaderMessageType() {
|
||||
return headerMessageType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the header timestamp.
|
||||
* @return The header timestamp.
|
||||
*/
|
||||
public long getHeaderTimeStamp() {
|
||||
return headerTimeStamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the header source ID.
|
||||
* @return The header source ID.
|
||||
*/
|
||||
public int getHeaderSourceID() {
|
||||
return headerSourceID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the message body length, according to the header.
|
||||
* @return The message body length.
|
||||
*/
|
||||
public int getMessageBodyLength() {
|
||||
return messageBodyLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the message CRC value, according to the header.
|
||||
* @return The message CRC value.
|
||||
*/
|
||||
public long getMessageCRCValue() {
|
||||
return messageCRCValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the calculated CRC value from the message header + body contents.
|
||||
* @return The calculated CRC value.
|
||||
*/
|
||||
public long getCalculatedCRCValue() {
|
||||
return calculatedCRCValue;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the message body.
|
||||
* @return The message body.
|
||||
*/
|
||||
public byte[] getMessageBody() {
|
||||
return messageBody;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,105 +0,0 @@
|
||||
package seng302.Networking;
|
||||
|
||||
|
||||
import seng302.Networking.Messages.Enums.MessageType;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.zip.CRC32;
|
||||
|
||||
import static seng302.Networking.Utils.ByteConverter.intToBytes;
|
||||
import static seng302.Networking.Utils.ByteConverter.longToBytes;
|
||||
import static seng302.Networking.Utils.ByteConverter.shortToBytes;
|
||||
|
||||
/**
|
||||
* This class can be used to encode/convert a byte array message body, plus header data into a byte array containing the entire message, ready to send.
|
||||
*/
|
||||
public class BinaryMessageEncoder {
|
||||
|
||||
///Length of the header.
|
||||
private static final int headerLength = 15;
|
||||
///Length of the CRC.
|
||||
private static final int CRCLength = 4;//TODO these should probably be static defined somewhere else to be shared.
|
||||
|
||||
///The full message.
|
||||
private byte[] fullMessage;
|
||||
///The message header.
|
||||
private byte[] messageHeader;
|
||||
///The message body.
|
||||
private byte[] messageBody;
|
||||
|
||||
///First sync byte value.
|
||||
private byte headerSync1 = (byte)0x47;
|
||||
///Second sync byte value.
|
||||
private byte headerSync2 = (byte)0x83;
|
||||
|
||||
///The message type to place in header.
|
||||
private byte headerMessageType;
|
||||
///The timestamp to place in header.
|
||||
private long headerTimeStamp;
|
||||
///The source ID to place in header.
|
||||
private int headerSourceID;
|
||||
///The message length to place in header.
|
||||
private short bodyMessageLength;
|
||||
|
||||
///The calculated CRC value.
|
||||
private long calculatedCRCValue;
|
||||
|
||||
/**
|
||||
* Ctor. Constructs a encoder and encodes the full message. Retrieve it with encoder.getFullMessage().
|
||||
* @param headerMessageType The message type to send.
|
||||
* @param headerTimeStamp Timestamp of the message.
|
||||
* @param headerSourceID Source ID of the message.
|
||||
* @param bodyMessageLength The length of the body of the message.
|
||||
* @param messageBody The body of the message (that is, the payload).
|
||||
*/
|
||||
public BinaryMessageEncoder(MessageType headerMessageType, long headerTimeStamp, int headerSourceID, short bodyMessageLength, byte[] messageBody) {
|
||||
//Set the header parameters.
|
||||
this.headerMessageType = headerMessageType.getValue();
|
||||
this.headerTimeStamp = headerTimeStamp;
|
||||
this.headerSourceID = headerSourceID;
|
||||
this.bodyMessageLength = bodyMessageLength;
|
||||
|
||||
//Place the header parameters into a buffer.
|
||||
ByteBuffer tempHeaderByteBuffer = ByteBuffer.allocate(this.headerLength);
|
||||
tempHeaderByteBuffer.put(this.headerSync1);
|
||||
tempHeaderByteBuffer.put(this.headerSync2);
|
||||
tempHeaderByteBuffer.put(this.headerMessageType);
|
||||
tempHeaderByteBuffer.put(longToBytes(this.headerTimeStamp, 6));
|
||||
tempHeaderByteBuffer.put(intToBytes(this.headerSourceID));
|
||||
tempHeaderByteBuffer.put(shortToBytes(this.bodyMessageLength));
|
||||
|
||||
this.messageHeader = tempHeaderByteBuffer.array();
|
||||
|
||||
//Set the message body.
|
||||
this.messageBody = messageBody;
|
||||
|
||||
|
||||
//Place header and body into a buffer.
|
||||
ByteBuffer tempHeaderBodyByteBuffer = ByteBuffer.allocate(this.messageHeader.length + this.bodyMessageLength);
|
||||
tempHeaderBodyByteBuffer.put(this.messageHeader);
|
||||
tempHeaderBodyByteBuffer.put(this.messageBody);
|
||||
|
||||
//Calculate the CRC from header + body.
|
||||
CRC32 crc = new CRC32();
|
||||
crc.reset();
|
||||
crc.update(tempHeaderBodyByteBuffer.array());
|
||||
this.calculatedCRCValue = crc.getValue();
|
||||
|
||||
//Place header, body, and CRC value in buffer.
|
||||
ByteBuffer tempFullMessageByteBuffer = ByteBuffer.allocate(this.messageHeader.length + this.messageBody.length + this.CRCLength);
|
||||
tempFullMessageByteBuffer.put(this.messageHeader);
|
||||
tempFullMessageByteBuffer.put(this.messageBody);
|
||||
tempFullMessageByteBuffer.put(intToBytes((int) this.calculatedCRCValue));
|
||||
|
||||
//Set the full message.
|
||||
this.fullMessage = tempFullMessageByteBuffer.array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the full encoded message. This includes the header, body, and CRC.
|
||||
* @return Full encoded message.
|
||||
*/
|
||||
public byte[] getFullMessage() {
|
||||
return fullMessage;
|
||||
}
|
||||
}
|
||||
@ -1,25 +0,0 @@
|
||||
package seng302.Networking.Exceptions;
|
||||
|
||||
/**
|
||||
* Exception which is thrown when a message is read, but it is invalid in some way (CRC is wrong, sync bytes, etc...).
|
||||
*/
|
||||
public class InvalidMessageException extends Exception
|
||||
{
|
||||
|
||||
/**
|
||||
* Ctor.
|
||||
* @param message String message.
|
||||
*/
|
||||
public InvalidMessageException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ctor.
|
||||
* @param message String message.
|
||||
* @param cause Cause of the exception.
|
||||
*/
|
||||
public InvalidMessageException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
@ -1,55 +0,0 @@
|
||||
package seng302.Networking.MessageDecoders;
|
||||
|
||||
import seng302.Networking.Messages.AverageWind;
|
||||
import seng302.Networking.Utils.ByteConverter;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Created by hba56 on 23/04/17.
|
||||
*/
|
||||
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);
|
||||
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 AverageWind getAverageWind() {
|
||||
return averageWind;
|
||||
}
|
||||
}
|
||||
@ -1,139 +0,0 @@
|
||||
package seng302.Networking.MessageDecoders;
|
||||
|
||||
import seng302.Networking.Messages.BoatLocation;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static seng302.Networking.Utils.ByteConverter.*;
|
||||
|
||||
/**
|
||||
* Created by hba56 on 21/04/17.
|
||||
*/
|
||||
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;
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
public BoatLocation getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
@ -1,61 +0,0 @@
|
||||
package seng302.Networking.MessageDecoders;
|
||||
|
||||
import seng302.Networking.Messages.CourseWind;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static seng302.Networking.Utils.ByteConverter.*;
|
||||
|
||||
/**
|
||||
* Created by hba56 on 23/04/17.
|
||||
*/
|
||||
public class CourseWindDecoder {
|
||||
byte messageVersionNumber;
|
||||
byte byteWindID;
|
||||
byte loopCount;
|
||||
ArrayList<CourseWind> loopMessages = new ArrayList();
|
||||
|
||||
public CourseWindDecoder(byte[] encodedCourseWind) {
|
||||
final int lengthInBytesOfMessages = 20;
|
||||
|
||||
messageVersionNumber = encodedCourseWind[0];
|
||||
byteWindID = encodedCourseWind[1];
|
||||
loopCount = encodedCourseWind[2];
|
||||
byte[] loopMessagesBytes = Arrays.copyOfRange(encodedCourseWind, 3, lengthInBytesOfMessages*loopCount+3);
|
||||
int messageLoopIndex = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
public ArrayList<CourseWind> getLoopMessages() {
|
||||
return loopMessages;
|
||||
}
|
||||
|
||||
public byte getMessageVersionNumber() {
|
||||
return messageVersionNumber;
|
||||
}
|
||||
|
||||
public byte getByteWindID() {
|
||||
return byteWindID;
|
||||
}
|
||||
}
|
||||
@ -1,51 +0,0 @@
|
||||
package seng302.Networking.MessageDecoders;
|
||||
|
||||
import seng302.Networking.Utils.ByteConverter;
|
||||
import seng302.Networking.Messages.MarkRounding;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Created by hba56 on 23/04/17.
|
||||
*/
|
||||
public class MarkRoundingDecoder {
|
||||
byte messageVersionNumber;
|
||||
byte[] byteTime;
|
||||
byte[] byteAck;
|
||||
byte[] byteRaceID;
|
||||
byte[] byteSourceID;
|
||||
byte byteBoatStatus;
|
||||
byte byteRoundingSide;
|
||||
byte byteMarkType;
|
||||
byte byteMarkID;
|
||||
|
||||
MarkRounding markRounding;
|
||||
|
||||
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];
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public MarkRounding getMarkRounding() {
|
||||
return markRounding;
|
||||
}
|
||||
}
|
||||
@ -1,66 +0,0 @@
|
||||
package seng302.Networking.MessageDecoders;
|
||||
|
||||
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static seng302.Networking.Utils.ByteConverter.*;
|
||||
|
||||
/**
|
||||
* Created by hba56 on 21/04/17.
|
||||
*/
|
||||
public class RaceStartStatusDecoder {
|
||||
private byte messageVersion;
|
||||
private byte[] timestamp;
|
||||
private byte[] ackNumber;
|
||||
private byte[] raceStartTime;
|
||||
private byte[] raceIdentifier;
|
||||
private byte notificationType;
|
||||
|
||||
private long time;
|
||||
private short ack;
|
||||
private long startTime;
|
||||
private int raceID;
|
||||
private char notification;
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
public byte getMessageVersion() {
|
||||
return messageVersion;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -1,117 +0,0 @@
|
||||
package seng302.Networking.MessageDecoders;
|
||||
|
||||
import seng302.Networking.Messages.BoatStatus;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static seng302.Networking.Utils.ByteConverter.*;
|
||||
|
||||
/**
|
||||
* Created by hba56 on 21/04/17.
|
||||
*/
|
||||
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;
|
||||
|
||||
private long time;
|
||||
private int race;
|
||||
private int raceState;
|
||||
private long startTime;
|
||||
private int raceWindDir;
|
||||
private short raceWindSpeed;
|
||||
private int numberOfBoats;
|
||||
private int raceType;
|
||||
private ArrayList<BoatStatus> boats = new ArrayList<>();
|
||||
|
||||
|
||||
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 = bytesToInt(raceStatus);
|
||||
startTime = bytesToLong(expectedStart);
|
||||
raceWindDir = bytesToInt(raceWind);
|
||||
raceWindSpeed = bytesToShort(windSpeed);
|
||||
numberOfBoats = bytesToInt(numBoats);
|
||||
|
||||
int boatLoopIndex = 0;
|
||||
|
||||
for (int i=0; i < numberOfBoats; i++) {
|
||||
byte[] boatBytes = Arrays.copyOfRange(boatsBytes, boatLoopIndex, boatLoopIndex+20);
|
||||
|
||||
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);
|
||||
|
||||
BoatStatus boat = new BoatStatus(bytesToInt(sourceID),boatStatus,
|
||||
legNumber, numPenaltiesAwarded, numPenaltiesServed,
|
||||
bytesToLong(estTimeAtNextMark), bytesToLong(estTimeAtFinish));
|
||||
|
||||
boats.add(boat);
|
||||
boatLoopIndex += 20;
|
||||
}
|
||||
}
|
||||
|
||||
public byte getVersionNum() {
|
||||
return versionNum;
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public int getRace() {
|
||||
return race;
|
||||
}
|
||||
|
||||
public int 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;
|
||||
}
|
||||
}
|
||||
@ -1,81 +0,0 @@
|
||||
package seng302.Networking.MessageDecoders;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static seng302.Networking.Utils.ByteConverter.bytesToLong;
|
||||
import static seng302.Networking.Utils.ByteConverter.bytesToShort;
|
||||
|
||||
/**
|
||||
* Created by hba56 on 20/04/17.
|
||||
*/
|
||||
public class XMLMessageDecoder {
|
||||
private byte messageVersionNumber;
|
||||
private short ackNumber;
|
||||
private long timeStamp;
|
||||
private byte xmlMsgSubType;
|
||||
private short sequenceNumber;
|
||||
private short xmlMsgLength;
|
||||
private String xmlMessage;
|
||||
|
||||
private byte[] bytes;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public byte getMessageVersionNumber() {
|
||||
return messageVersionNumber;
|
||||
}
|
||||
|
||||
public short getAckNumber() {
|
||||
return ackNumber;
|
||||
}
|
||||
|
||||
public long getTimeStamp() {
|
||||
return timeStamp;
|
||||
}
|
||||
|
||||
public byte getXmlMsgSubType() {
|
||||
return xmlMsgSubType;
|
||||
}
|
||||
|
||||
public short getSequenceNumber() {
|
||||
return sequenceNumber;
|
||||
}
|
||||
|
||||
public short getXmlMsgLength() {
|
||||
return xmlMsgLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* this will be used latter for the vis
|
||||
* @return xml string as inputsource
|
||||
*/
|
||||
public InputStream getXmlMessageInputStream() {
|
||||
InputStream is = new ByteArrayInputStream(xmlMessage.trim().getBytes(StandardCharsets.UTF_8));
|
||||
// InputSource is = new InputSource(new StringReader(xmlMessage.trim()));
|
||||
return is;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,298 +0,0 @@
|
||||
package seng302.Networking.MessageEncoders;
|
||||
|
||||
|
||||
import seng302.Networking.Messages.*;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static seng302.Networking.Utils.ByteConverter.*;
|
||||
|
||||
/**
|
||||
* Created by fwy13 on 19/04/17.
|
||||
*/
|
||||
public class RaceVisionByteEncoder {
|
||||
|
||||
/**
|
||||
* Serializes a heartbeat message.
|
||||
* @param seq Heartbeat value.
|
||||
* @return Serialized message.
|
||||
*/
|
||||
public static byte[] heartBeat(long seq){
|
||||
ByteBuffer heartBeat = ByteBuffer.allocate(4);
|
||||
heartBeat.put(longToBytes(seq, 4));
|
||||
byte [] result = heartBeat.array();
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes a RaceStatus message.
|
||||
* @param raceStatus Message to serialize.
|
||||
* @return Serialized (byte array) message, ready to be written to a socket.
|
||||
*/
|
||||
public static byte[] raceStatus(RaceStatus raceStatus){
|
||||
|
||||
List<BoatStatus> boatStatuses = raceStatus.getBoatStatuses();
|
||||
|
||||
ByteBuffer raceStatusMessage = ByteBuffer.allocate(24 + 20* boatStatuses.size());
|
||||
//Version Number 1 bytes
|
||||
byte versionNum = 0b10; //this changes with the pdf. (2)
|
||||
byte[] timeBytes = longToBytes(raceStatus.getCurrentTime(), 6);//time (6 bytes)
|
||||
byte[] raceID = ByteBuffer.allocate(4).put(intToBytes(raceStatus.getRaceID())).array();//race identifier incase multiple races are going at once.
|
||||
byte[] raceStatusByte = intToBytes(raceStatus.getRaceStatus(), 1);//race status 0 - 10
|
||||
byte[] expectedStart = longToBytes(raceStatus.getExpectedStartTime(), 6);//number of milliseconds from Jan 1, 1970 for when the data is valid
|
||||
byte[] raceWind = ByteBuffer.allocate(2).put(intToBytes(raceStatus.getWindDirection(), 2)).array();//North = 0x0000 East = 0x4000 South = 0x8000.
|
||||
byte[] windSpeed = ByteBuffer.allocate(2).put(intToBytes(raceStatus.getWindSpeed(), 2)).array();//mm/sec
|
||||
byte[] numBoats = intToBytes(boatStatuses.size(), 1);
|
||||
byte[] bytesRaceType = intToBytes(raceStatus.getRaceType(), 1);//1 match race, 2 fleet race
|
||||
|
||||
raceStatusMessage.put(versionNum);
|
||||
raceStatusMessage.put(timeBytes);
|
||||
raceStatusMessage.put(raceID);
|
||||
raceStatusMessage.put(raceStatusByte);
|
||||
raceStatusMessage.put(expectedStart);
|
||||
raceStatusMessage.put(raceWind);
|
||||
raceStatusMessage.put(windSpeed);
|
||||
raceStatusMessage.put(numBoats);
|
||||
raceStatusMessage.put(bytesRaceType);
|
||||
|
||||
for (int i = 0; i < boatStatuses.size(); i++){
|
||||
byte[] sourceID = intToBytes(boatStatuses.get(i).getSourceID());
|
||||
byte[] boatStatus = intToBytes(boatStatuses.get(i).getBoatStatus(), 1);
|
||||
byte[] legNum = intToBytes(boatStatuses.get(i).getLegNumber(), 1);
|
||||
byte[] numPenalties = intToBytes(boatStatuses.get(i).getNumPenaltiesAwarded(), 1);
|
||||
byte[] numPenaltiesServed = intToBytes(boatStatuses.get(i).getNumPenaltiesServed(), 1);
|
||||
byte[] estNextMarkTime = longToBytes(boatStatuses.get(i).getEstTimeAtNextMark(), 6);
|
||||
byte[] estFinishTime = longToBytes( boatStatuses.get(i).getEstTimeAtFinish(), 6);
|
||||
|
||||
raceStatusMessage.put(sourceID);
|
||||
raceStatusMessage.put(boatStatus);
|
||||
raceStatusMessage.put(legNum);
|
||||
raceStatusMessage.put(numPenalties);
|
||||
raceStatusMessage.put(numPenaltiesServed);
|
||||
raceStatusMessage.put(estNextMarkTime);
|
||||
raceStatusMessage.put(estFinishTime);
|
||||
}
|
||||
|
||||
return raceStatusMessage.array();
|
||||
}
|
||||
|
||||
public byte[] displayTextMessage(RaceMessage[] message){
|
||||
//ByteBuffer result = ByteBuffer.allocate(4 + numLines * 32);
|
||||
int messageVersionNumber = 0b1;//version number
|
||||
short ackNum = 0;//no clue what this does just a placeholder for 2 bytes.
|
||||
byte[] messLines = intToBytes(message.length, 1);
|
||||
|
||||
// result.putInt(messageVersionNumber);
|
||||
// result.putShort(ackNum);
|
||||
// result.put(messLines);
|
||||
|
||||
ArrayList<byte[]> messages = new ArrayList<byte[]>();
|
||||
int size = 4;
|
||||
|
||||
for (int i = 0; i < message.length; i ++){
|
||||
int messageLen = message[i].getMessageText().getBytes().length;
|
||||
byte[] messageAsBytes = message[i].getMessageText().getBytes();
|
||||
if (messageLen < 30){
|
||||
messageLen = 30;
|
||||
}
|
||||
ByteBuffer mess = ByteBuffer.allocate(2 + messageLen);
|
||||
mess.put(intToBytes(message[i].getLineNumber(), 1));
|
||||
mess.put(intToBytes(messageLen, 1));
|
||||
for (int j = 0; j < messageLen; j ++){
|
||||
mess.put(messageAsBytes[j]);
|
||||
}
|
||||
messages.add(mess.array());
|
||||
size += 2 + messageLen;
|
||||
}
|
||||
|
||||
ByteBuffer result = ByteBuffer.allocate(size);
|
||||
result.put(intToBytes(messageVersionNumber, 1));
|
||||
result.putShort(ackNum);
|
||||
result.put(messLines);
|
||||
|
||||
for(byte[] mess: messages){
|
||||
result.put(mess);
|
||||
}
|
||||
|
||||
return result.array();
|
||||
}
|
||||
|
||||
public byte[] raceStartStatus(long time, short ack, long startTime, int raceID, char notification){
|
||||
int messageVersion = 0b1;
|
||||
byte[] timestamp = longToBytes(time, 6);
|
||||
byte[] ackNumber = intToBytes(ack, 2);
|
||||
byte[] raceStartTime = longToBytes(startTime, 6);
|
||||
int raceIdentifier = raceID;
|
||||
byte[] notificationType = intToBytes(notification, 1);
|
||||
|
||||
ByteBuffer result = ByteBuffer.allocate(20);
|
||||
result.put(intToBytes(messageVersion, 1));
|
||||
result.put(timestamp);
|
||||
result.put(ackNumber);
|
||||
result.put(raceStartTime);
|
||||
result.put(intToBytes(raceIdentifier));
|
||||
result.put(notificationType);
|
||||
|
||||
return result.array();
|
||||
}
|
||||
|
||||
public byte[] yachtEventCode(long time, short acknowledgeNumber, int raceID, int destSourceID, int incidentID,
|
||||
int eventID){
|
||||
int messageVersion = 0b10;
|
||||
byte[] encodeTime = longToBytes(time, 6);
|
||||
short ackNum = acknowledgeNumber;
|
||||
int raceUID = raceID;//TODO chekc if this is an into for a 4 char string.
|
||||
int destSource = destSourceID;
|
||||
int incident = incidentID;
|
||||
byte[] event = intToBytes(eventID, 1);
|
||||
|
||||
ByteBuffer result = ByteBuffer.allocate(22);
|
||||
result.put(intToBytes(messageVersion, 1));
|
||||
result.put(encodeTime);
|
||||
result.putShort(ackNum);
|
||||
result.put(intToBytes(raceUID));
|
||||
result.put(intToBytes(destSource));
|
||||
result.put(intToBytes(incident));
|
||||
result.put(event);
|
||||
return result.array();
|
||||
}
|
||||
|
||||
public byte[] chatterText(int messageType, String message){
|
||||
int messageVersion = 0b1;
|
||||
byte[] type = intToBytes(messageType, 1);
|
||||
byte[] text = message.getBytes();
|
||||
byte[] length = intToBytes(text.length, 1);
|
||||
|
||||
ByteBuffer result = ByteBuffer.allocate(3 + text.length);
|
||||
result.put(intToBytes(messageVersion, 1));
|
||||
result.put(type);
|
||||
result.put(length);
|
||||
result.put(text);
|
||||
|
||||
return result.array();
|
||||
}
|
||||
|
||||
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 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);
|
||||
byte[] byteAck = intToBytes(ackNumber, 2);
|
||||
byte[] byteRaceID = intToBytes(raceID, 4);
|
||||
byte[] byteSourceID = intToBytes(sourceID, 4);
|
||||
byte[] byteBoatStatus = intToBytes(boatStatus, 1);
|
||||
byte[] byteRoundingSide = intToBytes(roundingSide, 1);
|
||||
byte[] byteMarkType = intToBytes(markType, 1);
|
||||
byte[] byteMarkID = intToBytes(markID, 1);
|
||||
|
||||
ByteBuffer result = ByteBuffer.allocate(21);
|
||||
result.put(intToBytes(messageVersionNumber, 1));
|
||||
result.put(byteTime);
|
||||
result.put(byteAck);
|
||||
result.put(byteRaceID);
|
||||
result.put(byteSourceID);
|
||||
result.put(byteBoatStatus);
|
||||
result.put(byteRoundingSide);
|
||||
result.put(byteMarkType);
|
||||
result.put(byteMarkID);
|
||||
return result.array();
|
||||
}
|
||||
|
||||
public byte[] courseWind(byte windID, ArrayList<CourseWind> courseWinds){
|
||||
int messageVersionNumber = 0b1;
|
||||
byte byteWindID = windID;
|
||||
byte[] loopcount = intToBytes(courseWinds.size(), 1);
|
||||
ByteBuffer result = ByteBuffer.allocate(3 + 20 * courseWinds.size());
|
||||
result.put(intToBytes(messageVersionNumber, 1));
|
||||
result.put(byteWindID);
|
||||
result.put(loopcount);
|
||||
for (CourseWind wind: courseWinds){
|
||||
result.put(intToBytes(wind.getID(), 1));
|
||||
result.put(longToBytes(wind.getTime(), 6));
|
||||
result.put(intToBytes(wind.getRaceID(), 4));
|
||||
result.put(intToBytes(wind.getWindDirection(), 2));
|
||||
result.put(intToBytes(wind.getWindSpeed(), 2));
|
||||
result.put(intToBytes(wind.getBestUpwindAngle(), 2));
|
||||
result.put(intToBytes(wind.getBestDownwindAngle(), 2));
|
||||
result.put(intToBytes(wind.getFlags(), 1));
|
||||
}
|
||||
return result.array();
|
||||
}
|
||||
|
||||
public 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();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,60 +0,0 @@
|
||||
package seng302.Networking.MessageEncoders;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static seng302.Networking.Utils.ByteConverter.intToBytes;
|
||||
import static seng302.Networking.Utils.ByteConverter.longToBytes;
|
||||
import static seng302.Networking.Utils.ByteConverter.shortToBytes;
|
||||
|
||||
/**
|
||||
* Encodes a XML file into a message of AC35 format
|
||||
*/
|
||||
public class XMLMessageEncoder {
|
||||
private byte[] messageVersionNumber;
|
||||
private short ackNumber;
|
||||
private long timeStamp;
|
||||
private byte[] xmlMsgSubType;
|
||||
private short sequenceNumber;
|
||||
private short xmlMsgLength;
|
||||
private String xmlMessage;
|
||||
|
||||
public XMLMessageEncoder(short ackNumber, long timeStamp, int xmlMsgSubType, short sequenceNumber, short xmlMsgLength, String xmlMessage) {
|
||||
this.messageVersionNumber = intToBytes(1, 1);
|
||||
this.ackNumber = ackNumber;
|
||||
this.timeStamp = timeStamp;
|
||||
this.xmlMsgSubType = intToBytes(xmlMsgSubType, 1);
|
||||
this.sequenceNumber = sequenceNumber;
|
||||
this.xmlMsgLength = xmlMsgLength;
|
||||
this.xmlMessage = xmlMessage;
|
||||
}
|
||||
|
||||
public byte[] encode() {
|
||||
byte[] messageBytes = xmlMessage.getBytes();
|
||||
if (messageBytes.length > this.xmlMsgLength) {
|
||||
//System.err.println("Xml message is to big");
|
||||
return null;
|
||||
}
|
||||
ByteBuffer tempOutputByteBuffer = ByteBuffer.allocate(14 + messageBytes.length);
|
||||
|
||||
//ackNumber converted to bytes
|
||||
byte[] ackNumberBytes = shortToBytes(ackNumber, 2);
|
||||
|
||||
//sequenceNumber converted to bytes
|
||||
byte[] sequenceNumberBytes = shortToBytes(sequenceNumber, 2);
|
||||
|
||||
//xmlMsgLength converted to bytes
|
||||
byte[] xmlMsgLengthBytes = shortToBytes(xmlMsgLength, 2);
|
||||
|
||||
|
||||
tempOutputByteBuffer.put(messageVersionNumber);
|
||||
tempOutputByteBuffer.put(ackNumberBytes);
|
||||
tempOutputByteBuffer.put(longToBytes(timeStamp, 6));
|
||||
tempOutputByteBuffer.put(xmlMsgSubType);
|
||||
tempOutputByteBuffer.put(sequenceNumberBytes);
|
||||
tempOutputByteBuffer.put(xmlMsgLengthBytes);
|
||||
tempOutputByteBuffer.put(messageBytes);
|
||||
|
||||
return tempOutputByteBuffer.array();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
package seng302.Networking.Messages;
|
||||
|
||||
|
||||
import seng302.Networking.Messages.Enums.MessageType;
|
||||
|
||||
/**
|
||||
* The base class for all message types.
|
||||
*/
|
||||
public abstract class AC35Data {
|
||||
|
||||
///Message type from the header.
|
||||
private MessageType type;
|
||||
|
||||
|
||||
/**
|
||||
* Ctor.
|
||||
* @param type The concrete type of this message.
|
||||
*/
|
||||
public AC35Data (MessageType type){
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The concrete type of message this is.
|
||||
* @return The type of message this is.
|
||||
*/
|
||||
public MessageType getType() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
package seng302.Networking.Messages;
|
||||
|
||||
import seng302.Networking.Messages.Enums.MessageType;
|
||||
|
||||
/**
|
||||
* Created by fwy13 on 25/04/17.
|
||||
*/
|
||||
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){
|
||||
super(MessageType.AVGWIND);
|
||||
this.msgNum = msgNum;
|
||||
this.lngTime = lngTime;
|
||||
this.rawPeriod = rawPeriod;
|
||||
this.rawSpeed = rawSpeed;
|
||||
this.period2 = period2;
|
||||
this.speed2 = speed2;
|
||||
this.period3 = period3;
|
||||
this.speed3 = speed3;
|
||||
this.period4 = period4;
|
||||
this.speed4 = speed4;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,557 +0,0 @@
|
||||
package seng302.Networking.Messages;
|
||||
|
||||
import seng302.Networking.Messages.Enums.MessageType;
|
||||
import seng302.Networking.Utils.AC35UnitConverter;
|
||||
|
||||
import static seng302.Networking.Utils.AC35UnitConverter.convertGPS;
|
||||
import static seng302.Networking.Utils.AC35UnitConverter.convertGPSToInt;
|
||||
|
||||
/**
|
||||
* Represents the information in a boat location message (AC streaming spec: 4.9).
|
||||
*/
|
||||
public class BoatLocation extends AC35Data {
|
||||
|
||||
//Knots x this = meters per second.
|
||||
public static final double KnotsToMetersPerSecondConversionFactor =
|
||||
0.514444;
|
||||
public static final byte Unknown = 0;
|
||||
public static final byte RacingYacht = 1;
|
||||
public static final byte CommitteeBoat = 2;
|
||||
public static final byte Mark = 3;
|
||||
public static final byte Pin = 4;
|
||||
public static final byte ChaseBoat = 5;
|
||||
public static final byte MedicalBoat = 6;
|
||||
public static final byte MarshallBoat = 7;
|
||||
public static final byte UmpireBoat = 8;
|
||||
public static final byte UmpireSoftwareApplication = 9;
|
||||
public static final byte PrincipalRaceOfficerApplication = 10;
|
||||
public static final byte WeatherStation = 11;
|
||||
public static final byte Helicopter = 12;
|
||||
public static final byte DataProcessingApplication = 13;
|
||||
///Version number of the message - is always 1.
|
||||
private byte messageVersionNumber = 1;
|
||||
///Time of the event - milliseconds since jan 1 1970. Proper type is 6 byte int.
|
||||
private long time;
|
||||
///Source ID of the boat.
|
||||
private int sourceID;
|
||||
///Sequence number of the message.
|
||||
private long sequenceNumber;
|
||||
///Device type of the message (physical source of the message).
|
||||
private byte deviceType;
|
||||
///Latitude of the boat.
|
||||
private int latitude;
|
||||
|
||||
///Longitude of the boat.
|
||||
private int longitude;
|
||||
|
||||
///Altitude of the boat.
|
||||
private int altitude;
|
||||
|
||||
///Heading of the boat. Clockwise, 0 = north. Proper type is unsigned 2 byte int.
|
||||
private int heading;
|
||||
|
||||
///Pitch of the boat.
|
||||
private short pitch;
|
||||
|
||||
///Roll of the boat.
|
||||
private short roll;
|
||||
|
||||
///Speed of the boat. Proper type is unsigned 2 byte int. millimeters per second.
|
||||
private int boatSpeed;
|
||||
|
||||
///Course over ground (COG) of the boat. Proper type is unsigned 2 byte int.
|
||||
private int boatCOG;
|
||||
|
||||
///Speed over ground (SOG) of the boat. Proper type is unsigned 2 byte int. millimeters per second.
|
||||
private int boatSOG;
|
||||
|
||||
///Apparent wind speed at time of event. Proper type is unsigned 2 byte int. millimeters per second.
|
||||
private int apparentWindSpeed;
|
||||
|
||||
///Apparent wind angle at time of the event. Wind over starboard = positive.
|
||||
private short apparentWindAngle;
|
||||
|
||||
///True wind speed. Proper type is unsigned 2 byte int. millimeters per second.
|
||||
private int trueWindSpeed;
|
||||
|
||||
///True wind direction. Proper type is unsigned 2 byte int. 0x0000 = North, etc..
|
||||
private int trueWindDirection;
|
||||
|
||||
///True wind angle. Clockwise compass direction, 0 = north.
|
||||
private short trueWindAngle;
|
||||
|
||||
///Current drift. Proper type is unsigned 2 byte int. millimeters per second.
|
||||
private int currentDrift;
|
||||
|
||||
///Current set. Proper type is unsigned 2 byte int. Clockwise compass direction, 0 = north.
|
||||
private int currentSet;
|
||||
|
||||
///Rudder angle. Positive is rudder set to turn yacht to port.
|
||||
private short rudderAngle;
|
||||
|
||||
|
||||
/**
|
||||
* Ctor. Default.
|
||||
*/
|
||||
public BoatLocation() {
|
||||
super(MessageType.BOATLOCATION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ctor, with all parameters.
|
||||
*
|
||||
* @param messageVersionNumber message number
|
||||
* @param time time of message
|
||||
* @param sourceID id of boat
|
||||
* @param sequenceNumber number of boat message
|
||||
* @param deviceType type of boat
|
||||
* @param latitude lat of boat
|
||||
* @param longitude lon of boat
|
||||
* @param altitude altitude of boat
|
||||
* @param heading heading of boat
|
||||
* @param pitch pitch of boat
|
||||
* @param roll roll of boat
|
||||
* @param boatSpeed boats speed
|
||||
* @param boatCOG boat cog
|
||||
* @param boatSOG boat sog
|
||||
* @param apparentWindSpeed wind speed
|
||||
* @param apparentWindAngle wind angle
|
||||
* @param trueWindSpeed true wind speed
|
||||
* @param trueWindDirection true wind direction
|
||||
* @param trueWindAngle true wind angle
|
||||
* @param currentDrift current drift
|
||||
* @param currentSet current set
|
||||
* @param rudderAngle rudder angle
|
||||
*/
|
||||
public BoatLocation(byte messageVersionNumber, long time, int sourceID, long sequenceNumber, byte deviceType, int latitude, int longitude, int altitude, int heading, short pitch, short roll, int boatSpeed, int boatCOG, int boatSOG, int apparentWindSpeed, short apparentWindAngle, int trueWindSpeed, int trueWindDirection, short trueWindAngle, int currentDrift, int currentSet, short rudderAngle) {
|
||||
super(MessageType.BOATLOCATION);
|
||||
|
||||
this.messageVersionNumber = messageVersionNumber;
|
||||
this.time = time;
|
||||
this.sourceID = sourceID;
|
||||
this.sequenceNumber = sequenceNumber;
|
||||
this.deviceType = deviceType;
|
||||
this.latitude = latitude;
|
||||
this.longitude = longitude;
|
||||
this.altitude = altitude;
|
||||
this.heading = heading;
|
||||
this.pitch = pitch;
|
||||
this.roll = roll;
|
||||
this.boatSpeed = boatSpeed;
|
||||
this.boatCOG = boatCOG;
|
||||
this.boatSOG = boatSOG;
|
||||
this.apparentWindSpeed = apparentWindSpeed;
|
||||
this.apparentWindAngle = apparentWindAngle;
|
||||
this.trueWindSpeed = trueWindSpeed;
|
||||
this.trueWindDirection = trueWindDirection;
|
||||
this.trueWindAngle = trueWindAngle;
|
||||
this.currentDrift = currentDrift;
|
||||
this.currentSet = currentSet;
|
||||
this.rudderAngle = rudderAngle;
|
||||
}
|
||||
|
||||
public BoatLocation(int sourceID, double lat, double lon, long sequenceNumber, double heading, double boatSpeed, long time) {
|
||||
super(MessageType.BOATLOCATION);
|
||||
|
||||
this.messageVersionNumber = (byte) 1;
|
||||
this.time = time;
|
||||
this.sourceID = sourceID;
|
||||
this.sequenceNumber = sequenceNumber;
|
||||
this.deviceType = 1;
|
||||
this.latitude = convertGPSToInt(lat);
|
||||
this.longitude = convertGPSToInt(lon);
|
||||
this.altitude = 0;
|
||||
this.heading = convertHeadingDoubleToInt(heading);
|
||||
this.pitch = 0;
|
||||
this.roll = 0;
|
||||
this.boatSpeed = convertBoatSpeedDoubleToInt(boatSpeed);
|
||||
this.boatCOG = 0;
|
||||
this.boatSOG = convertBoatSpeedDoubleToInt(boatSpeed);
|
||||
this.apparentWindSpeed = 0;
|
||||
this.apparentWindAngle = 0;
|
||||
this.trueWindSpeed = 0;
|
||||
this.trueWindDirection = 0;
|
||||
this.trueWindAngle = 0;
|
||||
this.currentDrift = 0;
|
||||
this.currentSet = 0;
|
||||
this.rudderAngle = 0;
|
||||
}
|
||||
|
||||
|
||||
//Getters and setters for message properties.
|
||||
|
||||
/**
|
||||
* Converts a double representing a latitude or longitude coordinate to an int, as required by the streaming spec format.
|
||||
*
|
||||
* @param coordinate Latitude or longitude to convert. Double.
|
||||
* @return int representation of coordinate.
|
||||
*/
|
||||
public static int convertCoordinateDoubleToInt(double coordinate) {
|
||||
int coordinateInt = (int) ((coordinate / 180.0) * 2147483648.0);
|
||||
|
||||
return coordinateInt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an int representing a latitude or longitude coordinate to a double, as required by the streaming spec format.
|
||||
*
|
||||
* @param coordinate Latitude or longitude to convert. int.
|
||||
* @return double representation of coordinate.
|
||||
*/
|
||||
public static double convertCoordinateIntToDouble(int coordinate) {
|
||||
double coordinateDouble = (double) ((coordinate * 180.0) / 2147483648.0);
|
||||
|
||||
return coordinateDouble;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an int representing a heading to a double, as required by the streaming spec format.
|
||||
*
|
||||
* @param heading Heading to convert. int.
|
||||
* @return double representation of heading.
|
||||
*/
|
||||
public static double convertHeadingIntToDouble(int heading) {
|
||||
|
||||
double headingDouble = (double) ((heading * 360.0) / 65536.0);
|
||||
|
||||
return headingDouble;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a double representing a heading to an int, as required by the streaming spec format.
|
||||
*
|
||||
* @param heading Heading to convert. double.
|
||||
* @return int representation of heading.
|
||||
*/
|
||||
public static int convertHeadingDoubleToInt(double heading) {
|
||||
|
||||
int headingInt = (int) ((heading * 65536.0) / 360.0);
|
||||
|
||||
return headingInt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a short representing the wind's true angle to a double, as required by the streaming spec format.
|
||||
*
|
||||
* @param angle Angle to convert. short.
|
||||
* @return double representation of heading.
|
||||
*/
|
||||
public static double convertTrueWindAngleShortToDouble(short angle) {
|
||||
|
||||
double angleDouble = (double) ((angle * 180.0) / 32768.0);
|
||||
|
||||
return angleDouble;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a double representing the wind's true angle to a short, as required by the streaming spec format.
|
||||
*
|
||||
* @param angle Angle to convert. double.
|
||||
* @return short representation of heading.
|
||||
*/
|
||||
public static short convertTrueWindAngleDoubleToShort(double angle) {
|
||||
|
||||
short angleShort = (short) ((angle / 180.0) * 32768.0);
|
||||
|
||||
return angleShort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a double representing the speed of a boat in knots to an int in millimeters per second, as required by the streaming spec format.
|
||||
*
|
||||
* @param speed Speed in knots, stored as a double.
|
||||
* @return Speed in millimeters per second, stored as an int (using only the two least significant bytes).
|
||||
*/
|
||||
public static int convertBoatSpeedDoubleToInt(double speed) {
|
||||
//Calculate meters per second.
|
||||
double metersPerSecond = speed * KnotsToMetersPerSecondConversionFactor;
|
||||
|
||||
//Calculate millimeters per second.
|
||||
double millimetersPerSecond = metersPerSecond * 1000.0;
|
||||
|
||||
//Convert to an int.
|
||||
int millimetersPerSecondInt = (int) Math.round(millimetersPerSecond);
|
||||
|
||||
return millimetersPerSecondInt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an int representing the speed of a boat in millimeters per second to a double in knots, as required by the streaming spec format.
|
||||
*
|
||||
* @param speed Speed in millimeters per second, stored as an int.
|
||||
* @return Speed in knots, stored as a double.
|
||||
*/
|
||||
public static double convertBoatSpeedIntToDouble(int speed) {
|
||||
//Calculate meters per second.
|
||||
double metersPerSecond = speed / 1000.0;
|
||||
|
||||
//Calculate knots.
|
||||
double knots = metersPerSecond / KnotsToMetersPerSecondConversionFactor;
|
||||
|
||||
return knots;
|
||||
}
|
||||
|
||||
public byte getMessageVersionNumber() {
|
||||
return messageVersionNumber;
|
||||
}
|
||||
|
||||
public void setMessageVersionNumber(byte messageVersionNumber) {
|
||||
this.messageVersionNumber = messageVersionNumber;
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public void setTime(long time) {
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public int getSourceID() {
|
||||
return sourceID;
|
||||
}
|
||||
|
||||
public void setSourceID(int sourceID) {
|
||||
this.sourceID = sourceID;
|
||||
}
|
||||
|
||||
public long getSequenceNumber() {
|
||||
return sequenceNumber;
|
||||
}
|
||||
|
||||
public void setSequenceNumber(long sequenceNumber) {
|
||||
this.sequenceNumber = sequenceNumber;
|
||||
}
|
||||
|
||||
public byte getDeviceType() {
|
||||
return deviceType;
|
||||
}
|
||||
|
||||
public void setDeviceType(byte deviceType) {
|
||||
this.deviceType = deviceType;
|
||||
}
|
||||
|
||||
public int getLatitude() {
|
||||
return latitude;
|
||||
}
|
||||
|
||||
public void setLatitude(int latitude) {
|
||||
this.latitude = latitude;
|
||||
}
|
||||
|
||||
public int getLongitude() {
|
||||
return longitude;
|
||||
}
|
||||
|
||||
public double getLatitudeDouble(){
|
||||
return convertGPS(this.latitude);
|
||||
}
|
||||
|
||||
public double getLongitudeDouble(){
|
||||
return convertGPS(this.longitude);
|
||||
}
|
||||
|
||||
public void setLongitude(int longitude) {
|
||||
this.longitude = longitude;
|
||||
}
|
||||
|
||||
public int getAltitude() {
|
||||
return altitude;
|
||||
}
|
||||
|
||||
public void setAltitude(int altitude) {
|
||||
this.altitude = altitude;
|
||||
}
|
||||
|
||||
public int getHeading() {
|
||||
return heading;
|
||||
}
|
||||
|
||||
public void setHeading(int heading) {
|
||||
this.heading = heading;
|
||||
}
|
||||
|
||||
public short getPitch() {
|
||||
return pitch;
|
||||
}
|
||||
|
||||
public void setPitch(short pitch) {
|
||||
this.pitch = pitch;
|
||||
}
|
||||
|
||||
public short getRoll() {
|
||||
return roll;
|
||||
}
|
||||
|
||||
public void setRoll(short roll) {
|
||||
this.roll = roll;
|
||||
}
|
||||
|
||||
public int getBoatSpeed() {
|
||||
return boatSpeed;
|
||||
}
|
||||
|
||||
public void setBoatSpeed(int boatSpeed) {
|
||||
this.boatSpeed = boatSpeed;
|
||||
}
|
||||
|
||||
public int getBoatCOG() {
|
||||
return boatCOG;
|
||||
}
|
||||
|
||||
public void setBoatCOG(int boatCOG) {
|
||||
this.boatCOG = boatCOG;
|
||||
}
|
||||
|
||||
public int getBoatSOG() {
|
||||
return boatSOG;
|
||||
}
|
||||
|
||||
public void setBoatSOG(int boatSOG) {
|
||||
this.boatSOG = boatSOG;
|
||||
}
|
||||
|
||||
public int getApparentWindSpeed() {
|
||||
return apparentWindSpeed;
|
||||
}
|
||||
|
||||
public void setApparentWindSpeed(int apparentWindSpeed) {
|
||||
this.apparentWindSpeed = apparentWindSpeed;
|
||||
}
|
||||
|
||||
public short getApparentWindAngle() {
|
||||
return apparentWindAngle;
|
||||
}
|
||||
|
||||
public void setApparentWindAngle(short apparentWindAngle) {
|
||||
this.apparentWindAngle = apparentWindAngle;
|
||||
}
|
||||
|
||||
public int getTrueWindSpeed() {
|
||||
return trueWindSpeed;
|
||||
}
|
||||
|
||||
public void setTrueWindSpeed(int trueWindSpeed) {
|
||||
this.trueWindSpeed = trueWindSpeed;
|
||||
}
|
||||
|
||||
public int getTrueWindDirection()
|
||||
{
|
||||
return trueWindDirection;
|
||||
}
|
||||
|
||||
public void setTrueWindDirection(int trueWindDirection)
|
||||
{
|
||||
this.trueWindDirection = trueWindDirection;
|
||||
}
|
||||
|
||||
public short getTrueWindAngle() {
|
||||
return trueWindAngle;
|
||||
}
|
||||
|
||||
public void setTrueWindAngle(short trueWindAngle) {
|
||||
this.trueWindAngle = trueWindAngle;
|
||||
}
|
||||
|
||||
public int getCurrentDrift() {
|
||||
return currentDrift;
|
||||
}
|
||||
|
||||
public void setCurrentDrift(int currentDrift) {
|
||||
this.currentDrift = currentDrift;
|
||||
}
|
||||
|
||||
public int getCurrentSet() {
|
||||
return currentSet;
|
||||
}
|
||||
|
||||
public void setCurrentSet(int currentSet) {
|
||||
this.currentSet = currentSet;
|
||||
}
|
||||
|
||||
public short getRudderAngle() {
|
||||
return rudderAngle;
|
||||
}
|
||||
|
||||
public void setRudderAngle(short rudderAngle) {
|
||||
this.rudderAngle = rudderAngle;
|
||||
}
|
||||
|
||||
public double getHeadingDegrees(){
|
||||
return AC35UnitConverter.convertHeading(getHeading());
|
||||
}
|
||||
|
||||
public double getTrueWindAngleDegrees(){
|
||||
return AC35UnitConverter.convertTrueWindAngle(getTrueWindAngle());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
||||
builder.append("Message version number: ");
|
||||
builder.append(this.getMessageVersionNumber());
|
||||
|
||||
builder.append("\nTime: ");
|
||||
builder.append(this.getTime());
|
||||
|
||||
builder.append("\nSource ID: ");
|
||||
builder.append(this.getSourceID());
|
||||
|
||||
builder.append("\nSequence number: ");
|
||||
builder.append(this.getSequenceNumber());
|
||||
|
||||
builder.append("\nDevice type: ");
|
||||
builder.append(this.getDeviceType());
|
||||
|
||||
builder.append("\nLatitude: ");
|
||||
builder.append(this.getLatitude());
|
||||
|
||||
builder.append("\nLongitude: ");
|
||||
builder.append(this.getLongitude());
|
||||
|
||||
builder.append("\nAltitude: ");
|
||||
builder.append(this.getAltitude());
|
||||
|
||||
builder.append("\nHeading: ");
|
||||
builder.append(this.getHeading());
|
||||
|
||||
builder.append("\nPitch: ");
|
||||
builder.append(this.getPitch());
|
||||
|
||||
builder.append("\nRoll: ");
|
||||
builder.append(this.getRoll());
|
||||
|
||||
builder.append("\nBoat speed (mm/sec): ");
|
||||
builder.append(this.getBoatSpeed());
|
||||
|
||||
builder.append("\nBoat COG: ");
|
||||
builder.append(this.getBoatCOG());
|
||||
|
||||
builder.append("\nBoat SOG: ");
|
||||
builder.append(this.getBoatSOG());
|
||||
|
||||
builder.append("\nApparent wind speed: ");
|
||||
builder.append(this.getApparentWindSpeed());
|
||||
|
||||
builder.append("\nApparent wind angle: ");
|
||||
builder.append(this.getApparentWindAngle());
|
||||
|
||||
builder.append("\nTrue wind speed: ");
|
||||
builder.append(this.getTrueWindSpeed());
|
||||
|
||||
builder.append("\nTrue wind angle: ");
|
||||
builder.append(this.getTrueWindAngle());
|
||||
|
||||
builder.append("\nCurrent drift: ");
|
||||
builder.append(this.getCurrentDrift());
|
||||
|
||||
builder.append("\nCurrent set: ");
|
||||
builder.append(this.getCurrentSet());
|
||||
|
||||
builder.append("\nRudder angle: ");
|
||||
builder.append(this.getRudderAngle());
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
@ -1,68 +0,0 @@
|
||||
package seng302.Networking.Messages;
|
||||
|
||||
import seng302.Networking.Utils.ByteConverter;
|
||||
import seng302.Networking.Messages.Enums.BoatStatusEnum;
|
||||
|
||||
/**
|
||||
* Created by hba56 on 23/04/17.
|
||||
*/
|
||||
public class BoatStatus {
|
||||
|
||||
private int sourceID;
|
||||
private byte boatStatus;
|
||||
private byte legNumber;
|
||||
private byte numPenaltiesAwarded;
|
||||
private byte numPenaltiesServed;
|
||||
private long estTimeAtNextMark;
|
||||
private long estTimeAtFinish;
|
||||
|
||||
public BoatStatus(int sourceID, byte boatStatus, byte legNumber, byte numPenaltiesAwarded, byte numPenaltiesServed, long estTimeAtNextMark, long estTimeAtFinish) {
|
||||
this.sourceID = sourceID;
|
||||
this.boatStatus = boatStatus;
|
||||
this.legNumber = legNumber;
|
||||
this.numPenaltiesAwarded = numPenaltiesAwarded;
|
||||
this.numPenaltiesServed = numPenaltiesServed;
|
||||
this.estTimeAtNextMark = estTimeAtNextMark;
|
||||
this.estTimeAtFinish = estTimeAtFinish;
|
||||
}
|
||||
|
||||
|
||||
public BoatStatus(int sourceID, BoatStatusEnum boatStatusEnum, int legNum, long estTimeAtNextMark) {
|
||||
this.sourceID = sourceID;
|
||||
this.boatStatus = boatStatusEnum.getValue();
|
||||
this.legNumber = ByteConverter.intToBytes(legNum)[0];
|
||||
this.numPenaltiesAwarded = 0;
|
||||
this.numPenaltiesServed = 0;
|
||||
this.estTimeAtFinish = 0;
|
||||
this.estTimeAtNextMark = estTimeAtNextMark;
|
||||
}
|
||||
|
||||
|
||||
public int getSourceID() {
|
||||
return sourceID;
|
||||
}
|
||||
|
||||
public byte getBoatStatus() {
|
||||
return boatStatus;
|
||||
}
|
||||
|
||||
public byte getLegNumber() {
|
||||
return legNumber;
|
||||
}
|
||||
|
||||
public byte getNumPenaltiesAwarded() {
|
||||
return numPenaltiesAwarded;
|
||||
}
|
||||
|
||||
public byte getNumPenaltiesServed() {
|
||||
return numPenaltiesServed;
|
||||
}
|
||||
|
||||
public long getEstTimeAtNextMark() {
|
||||
return estTimeAtNextMark;
|
||||
}
|
||||
|
||||
public long getEstTimeAtFinish() {
|
||||
return estTimeAtFinish;
|
||||
}
|
||||
}
|
||||
@ -1,57 +0,0 @@
|
||||
package seng302.Networking.Messages;
|
||||
|
||||
import seng302.Networking.Messages.Enums.MessageType;
|
||||
|
||||
/**
|
||||
* Created by fwy13 on 21/04/17.
|
||||
*/
|
||||
public class CourseWind extends AC35Data {
|
||||
|
||||
private int ID, raceID, windDirection, windSpeed, bestUpwindAngle, bestDownwindAngle, flags;
|
||||
private long time;
|
||||
|
||||
public CourseWind(int ID, long time, int raceID, int windDirection, int windSpeed, int bestUpwindAngle, int bestDownwindAngle,
|
||||
int flags){
|
||||
super(MessageType.COURSEWIND);
|
||||
this.ID = ID;
|
||||
this.time = time;
|
||||
this.raceID = raceID;
|
||||
this.windDirection = windDirection;
|
||||
this.windSpeed = windSpeed;
|
||||
this.bestUpwindAngle = bestUpwindAngle;
|
||||
this.bestDownwindAngle = bestDownwindAngle;
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
public int getID() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
public int getRaceID() {
|
||||
return raceID;
|
||||
}
|
||||
|
||||
public int getWindDirection() {
|
||||
return windDirection;
|
||||
}
|
||||
|
||||
public int getWindSpeed() {
|
||||
return windSpeed;
|
||||
}
|
||||
|
||||
public int getBestUpwindAngle() {
|
||||
return bestUpwindAngle;
|
||||
}
|
||||
|
||||
public int getBestDownwindAngle() {
|
||||
return bestDownwindAngle;
|
||||
}
|
||||
|
||||
public int getFlags() {
|
||||
return flags;
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
return time;
|
||||
}
|
||||
}
|
||||
@ -1,23 +0,0 @@
|
||||
package seng302.Networking.Messages;
|
||||
|
||||
import seng302.Networking.Messages.Enums.MessageType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Created by fwy13 on 25/04/17.
|
||||
*/
|
||||
public class CourseWinds extends AC35Data {
|
||||
|
||||
private int msgVerNum;
|
||||
private int selectedWindID;
|
||||
private ArrayList<CourseWind> courseWinds;
|
||||
|
||||
public CourseWinds(int msgVerNum, int selectedWindID, ArrayList<CourseWind> courseWinds){
|
||||
super(MessageType.COURSEWIND);
|
||||
this.msgVerNum = msgVerNum;
|
||||
this.selectedWindID = selectedWindID;
|
||||
this.courseWinds = courseWinds;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,75 +0,0 @@
|
||||
package seng302.Networking.Messages.Enums;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Enumeration that encapsulates the various statuses a boat can have.
|
||||
*/
|
||||
public enum BoatStatusEnum {
|
||||
UNDEFINED(0),
|
||||
PRESTART(1),
|
||||
RACING(2),
|
||||
FINISHED(3),
|
||||
DNS(4),
|
||||
DNF(5),
|
||||
DSQ(6),
|
||||
OCS(7),
|
||||
NOT_A_STATUS(-1);
|
||||
|
||||
///Primitive value of the enum.
|
||||
private byte value;
|
||||
|
||||
|
||||
/**
|
||||
* Ctor. Creates a BoatStatusEnum from a given primitive integer value, cast to a byte.
|
||||
* @param value Integer, which is cast to byte, to construct from.
|
||||
*/
|
||||
private BoatStatusEnum(int value) {
|
||||
this.value = (byte)value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the primitive value of the enum.
|
||||
* @return Primitive value of the enum.
|
||||
*/
|
||||
public byte getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
///Stores a mapping between Byte values and BoatStatusEnum values.
|
||||
private static final Map<Byte, BoatStatusEnum> byteToStatusMap = new HashMap<>();
|
||||
|
||||
|
||||
/*
|
||||
Static initialization block. Initializes the byteToStatusMap.
|
||||
*/
|
||||
static {
|
||||
for (BoatStatusEnum type : BoatStatusEnum.values()) {
|
||||
byteToStatusMap.put(type.value, type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the enumeration value which corresponds to a given byte value.
|
||||
* @param boatStatusByte Byte value to convert to a BoatStatusEnum value.
|
||||
* @return The BoatStatusEnum value which corresponds to the given byte value.
|
||||
*/
|
||||
public static BoatStatusEnum fromByte(byte boatStatusByte) {
|
||||
//Gets the corresponding MessageType from the map.
|
||||
BoatStatusEnum type = byteToStatusMap.get(boatStatusByte);
|
||||
|
||||
if (type == null) {
|
||||
//If the byte value wasn't found, return the NOT_A_STATUS BoatStatusEnum.
|
||||
return BoatStatusEnum.NOT_A_STATUS;
|
||||
}
|
||||
else {
|
||||
//Otherwise, return the BoatStatusEnum.
|
||||
return type;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,79 +0,0 @@
|
||||
package seng302.Networking.Messages.Enums;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Enumeration that encapsulates the various types of messages that can be sent.
|
||||
*/
|
||||
public enum MessageType {
|
||||
HEARTBEAT(1),
|
||||
RACESTATUS(12),
|
||||
DISPLAYTEXTMESSAGE(20),
|
||||
XMLMESSAGE(26),
|
||||
RACESTARTSTATUS(27),
|
||||
YACHTEVENTCODE(29),
|
||||
YACHTACTIONCODE(31),
|
||||
CHATTERTEXT(36),
|
||||
BOATLOCATION(37),
|
||||
MARKROUNDING(38),
|
||||
COURSEWIND(44),
|
||||
AVGWIND(47),
|
||||
NOTAMESSAGE(0);
|
||||
|
||||
///Primitive value of the enum.
|
||||
private byte value;
|
||||
|
||||
/**
|
||||
* Ctor. Creates a MessageType enum from a given primitive integer value, cast to a byte.
|
||||
* @param value Integer, which is cast to byte, to construct from.
|
||||
*/
|
||||
private MessageType(int value) {
|
||||
this.value = (byte)value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the primitive value of the enum.
|
||||
* @return Primitive value of the enum.
|
||||
*/
|
||||
public byte getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
///Stores a mapping between Byte values and MessageType values.
|
||||
private static final Map<Byte, MessageType> byteToTypeMap = new HashMap<>();
|
||||
|
||||
|
||||
/*
|
||||
Static initialization block. Initializes the byteToTypeMap.
|
||||
*/
|
||||
static {
|
||||
for (MessageType type : MessageType.values()) {
|
||||
byteToTypeMap.put(type.value, type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the enumeration value which corresponds to a given byte value.
|
||||
* @param messageTypeByte Byte value to convert to a MessageType value.
|
||||
* @return The MessageType value which corresponds to the given byte value.
|
||||
*/
|
||||
public static MessageType fromByte(byte messageTypeByte) {
|
||||
//Gets the corresponding MessageType from the map.
|
||||
MessageType type = byteToTypeMap.get(messageTypeByte);
|
||||
|
||||
if (type == null) {
|
||||
//If the byte value wasn't found, return the NOTAMESSAGE MessageType.
|
||||
return MessageType.NOTAMESSAGE;
|
||||
}
|
||||
else {
|
||||
//Otherwise, return the MessageType.
|
||||
return type;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -1,108 +0,0 @@
|
||||
package seng302.Networking.Messages.Enums;
|
||||
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Enumeration that encapsulates the various statuses a race can have. See AC35 streaming spec, 4.2.
|
||||
*/
|
||||
public enum RaceStatusEnum {
|
||||
|
||||
NOT_ACTIVE(0),
|
||||
|
||||
/**
|
||||
* Between 3:00 and 1:00 minutes before start.
|
||||
*/
|
||||
WARNING(1),
|
||||
|
||||
/**
|
||||
* Less than 1:00 minutes before start.
|
||||
*/
|
||||
PREPARATORY(2),
|
||||
STARTED(3),
|
||||
|
||||
/**
|
||||
* Obsolete.
|
||||
*/
|
||||
FINISHED(4),
|
||||
|
||||
/**
|
||||
* Obsolete.
|
||||
*/
|
||||
RETIRED(5),
|
||||
ABANDONED(6),
|
||||
POSTPONED(7),
|
||||
TERMINATED(8),
|
||||
RACE_START_TIME_NOT_SET(9),
|
||||
|
||||
/**
|
||||
* More than 3:00 minutes until start.
|
||||
*/
|
||||
PRESTART(10),
|
||||
|
||||
/**
|
||||
* Used to indicate that a given byte value is invalid.
|
||||
*/
|
||||
NOT_A_STATUS(-1);
|
||||
|
||||
|
||||
/**
|
||||
* Primitive value of the enum.
|
||||
*/
|
||||
private byte value;
|
||||
|
||||
|
||||
/**
|
||||
* Ctor. Creates a RaceStatusEnum from a given primitive integer value, cast to a byte.
|
||||
* @param value Integer, which is cast to byte, to construct from.
|
||||
*/
|
||||
private RaceStatusEnum(int value) {
|
||||
this.value = (byte) value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the primitive value of the enum.
|
||||
* @return Primitive value of the enum.
|
||||
*/
|
||||
public byte getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Stores a mapping between Byte values and RaceStatusEnum values.
|
||||
*/
|
||||
private static final Map<Byte, RaceStatusEnum> byteToStatusMap = new HashMap<>();
|
||||
|
||||
|
||||
/*
|
||||
Static initialization block. Initializes the byteToStatusMap.
|
||||
*/
|
||||
static {
|
||||
for (RaceStatusEnum type : RaceStatusEnum.values()) {
|
||||
RaceStatusEnum.byteToStatusMap.put(type.value, type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the enumeration value which corresponds to a given byte value.
|
||||
* @param raceStatusByte Byte value to convert to a RaceStatusEnum value.
|
||||
* @return The RaceStatusEnum value which corresponds to the given byte value.
|
||||
*/
|
||||
public static RaceStatusEnum fromByte(byte raceStatusByte) {
|
||||
//Gets the corresponding MessageType from the map.
|
||||
RaceStatusEnum type = RaceStatusEnum.byteToStatusMap.get(raceStatusByte);
|
||||
|
||||
if (type == null) {
|
||||
//If the byte value wasn't found, return the NOT_A_STATUS RaceStatusEnum.
|
||||
return RaceStatusEnum.NOT_A_STATUS;
|
||||
} else {
|
||||
//Otherwise, return the RaceStatusEnum.
|
||||
return type;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,87 +0,0 @@
|
||||
package seng302.Networking.Messages.Enums;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Enumeration that encapsulates the various types of races. See AC35 streaming spec, 4.2.
|
||||
*/
|
||||
public enum RaceTypeEnum {
|
||||
|
||||
|
||||
/**
|
||||
* A race between two boats.
|
||||
*/
|
||||
MATCH_RACE(1),
|
||||
|
||||
/**
|
||||
* A race between a fleet of boats.
|
||||
*/
|
||||
FLEET_RACE(2),
|
||||
|
||||
/**
|
||||
* Used to indicate that a given byte value is invalid.
|
||||
*/
|
||||
NOT_A_STATUS(-1);
|
||||
|
||||
|
||||
/**
|
||||
* Primitive value of the enum.
|
||||
*/
|
||||
private byte value;
|
||||
|
||||
|
||||
/**
|
||||
* Ctor. Creates a RaceTypeEnum from a given primitive integer value, cast to a byte.
|
||||
* @param value Integer, which is cast to byte, to construct from.
|
||||
*/
|
||||
private RaceTypeEnum(int value) {
|
||||
this.value = (byte) value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the primitive value of the enum.
|
||||
* @return Primitive value of the enum.
|
||||
*/
|
||||
public byte getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Stores a mapping between Byte values and RaceStatusEnum values.
|
||||
*/
|
||||
private static final Map<Byte, RaceTypeEnum> byteToStatusMap = new HashMap<>();
|
||||
|
||||
|
||||
/*
|
||||
Static initialization block. Initializes the byteToStatusMap.
|
||||
*/
|
||||
static {
|
||||
for (RaceTypeEnum type : RaceTypeEnum.values()) {
|
||||
RaceTypeEnum.byteToStatusMap.put(type.value, type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the enumeration value which corresponds to a given byte value.
|
||||
* @param raceTypeEnum Byte value to convert to a RaceTypeEnum value.
|
||||
* @return The RaceTypeEnum value which corresponds to the given byte value.
|
||||
*/
|
||||
public static RaceTypeEnum fromByte(byte raceTypeEnum) {
|
||||
//Gets the corresponding MessageType from the map.
|
||||
RaceTypeEnum type = RaceTypeEnum.byteToStatusMap.get(raceTypeEnum);
|
||||
|
||||
if (type == null) {
|
||||
//If the byte value wasn't found, return the NOT_A_STATUS RaceTypeEnum.
|
||||
return RaceTypeEnum.NOT_A_STATUS;
|
||||
} else {
|
||||
//Otherwise, return the RaceTypeEnum.
|
||||
return type;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -1,29 +0,0 @@
|
||||
package seng302.Networking.Messages;
|
||||
|
||||
import seng302.Networking.Messages.Enums.MessageType;
|
||||
|
||||
/**
|
||||
* Represents a Heartbeat message.
|
||||
*/
|
||||
public class Heartbeat extends AC35Data {
|
||||
|
||||
///Sequence number of the heartbeat.
|
||||
private long sequenceNumber;
|
||||
|
||||
/**
|
||||
* Ctor.
|
||||
* @param sequenceNumber Sequence number of the heartbeat.
|
||||
*/
|
||||
public Heartbeat(long sequenceNumber) {
|
||||
super(MessageType.HEARTBEAT);
|
||||
this.sequenceNumber = sequenceNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sequence number of this heartbeat message.
|
||||
* @return Sequence number of this heartbeat message.
|
||||
*/
|
||||
public long getSequenceNumber() {
|
||||
return sequenceNumber;
|
||||
}
|
||||
}
|
||||
@ -1,69 +0,0 @@
|
||||
package seng302.Networking.Messages;
|
||||
|
||||
import seng302.Networking.Messages.Enums.MessageType;
|
||||
|
||||
/**
|
||||
* Created by fwy13 on 25/04/17.
|
||||
*/
|
||||
public class MarkRounding extends AC35Data {
|
||||
|
||||
private int msgVerNum;
|
||||
private long time;
|
||||
private int ackNum;
|
||||
private int raceID;
|
||||
private int sourceID;
|
||||
private int boatStatus;
|
||||
private int roundingSide;
|
||||
private int markType;
|
||||
private int markID;
|
||||
|
||||
public static int BoatStatusUnknown = 0;
|
||||
public static int BoatStatusRacing = 1;
|
||||
public static int BoatStatusDSQ = 2;
|
||||
public static int BoatStatusWithdrawn = 3;
|
||||
|
||||
public static int RoundingSideUnknown = 0;
|
||||
public static int RoundingSidePort = 1;
|
||||
public static int RoundingSideStarboard = 2;
|
||||
|
||||
public static int MarkTypeUnknown = 0;
|
||||
public static int MarkTypeRoundingMark = 1;
|
||||
public static int MarkTypeGate = 2;
|
||||
|
||||
public static int MarkIDEntryLimitLine = 100;
|
||||
public static int MarkIDEntryLine = 101;
|
||||
public static int MarkIDRaceStartStartline = 102;
|
||||
public static int MarkIDRaceFinishline = 103;
|
||||
public static int MarkIDSpeedTestStart = 104;
|
||||
public static int MarkIDSpeedTestFinish = 105;
|
||||
public static int MarkIDClearStart = 106;
|
||||
|
||||
public MarkRounding(int msgVerNum, long time, int ackNum, int raceID, int sourceID, int boatStatus, int roundingSide, int markType, int markID){
|
||||
super(MessageType.MARKROUNDING);
|
||||
this.msgVerNum = msgVerNum;
|
||||
this.time = time;
|
||||
this.ackNum = ackNum;
|
||||
this.raceID = raceID;
|
||||
this.sourceID = sourceID;
|
||||
this.boatStatus = boatStatus;
|
||||
this.roundingSide = roundingSide;
|
||||
this.markType = markType;
|
||||
this.markID = markID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the boat (source) ID for this message.
|
||||
* @return Boat ID for this message.
|
||||
*/
|
||||
public int getSourceID() {
|
||||
return sourceID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the timestamp for this message.
|
||||
* @return Timestamp for this message.
|
||||
*/
|
||||
public long getTime() {
|
||||
return time;
|
||||
}
|
||||
}
|
||||
@ -1,26 +0,0 @@
|
||||
package seng302.Networking.Messages;
|
||||
|
||||
import seng302.Networking.Messages.Enums.MessageType;
|
||||
|
||||
/**
|
||||
* Created by fwy13 on 19/04/17.
|
||||
*/
|
||||
public class RaceMessage extends AC35Data {
|
||||
|
||||
private int lineNumber;
|
||||
private String messageText;
|
||||
|
||||
public RaceMessage(int lineNumber, String messageText){
|
||||
super(MessageType.DISPLAYTEXTMESSAGE);
|
||||
this.lineNumber = lineNumber;
|
||||
this.messageText = messageText;
|
||||
}
|
||||
|
||||
public int getLineNumber() {
|
||||
return lineNumber;
|
||||
}
|
||||
|
||||
public String getMessageText() {
|
||||
return messageText;
|
||||
}
|
||||
}
|
||||
@ -1,25 +0,0 @@
|
||||
package seng302.Networking.Messages;
|
||||
|
||||
import seng302.Networking.Messages.Enums.MessageType;
|
||||
|
||||
/**
|
||||
* Created by fwy13 on 25/04/17.
|
||||
*/
|
||||
public class RaceStartStatus extends AC35Data {
|
||||
|
||||
private long timestamp;
|
||||
private int ackNum;
|
||||
private long raceStartTime;
|
||||
private int raceID;
|
||||
private int notificationType;
|
||||
|
||||
public RaceStartStatus(long timestamp, int ackNum, long raceStartTime, int raceID, int notificationType){
|
||||
super(MessageType.RACESTARTSTATUS);
|
||||
this.timestamp = timestamp;
|
||||
this.ackNum = ackNum;
|
||||
this.raceStartTime = raceStartTime;
|
||||
this.raceID = raceID;
|
||||
this.notificationType = notificationType;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,129 +0,0 @@
|
||||
package seng302.Networking.Messages;
|
||||
|
||||
import seng302.Networking.Messages.Enums.MessageType;
|
||||
import seng302.Networking.Utils.AC35UnitConverter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by fwy13 on 25/04/17.
|
||||
*/
|
||||
public class RaceStatus extends AC35Data {
|
||||
|
||||
private long currentTime;
|
||||
private int raceID;
|
||||
private int raceStatus;
|
||||
private long expectedStartTime;
|
||||
private int windDirection;
|
||||
private int windSpeed;
|
||||
private int raceType;
|
||||
private List<BoatStatus> boatStatuses;
|
||||
|
||||
public RaceStatus(long currentTime, int raceID, int raceStatus, long expectedStartTime, int windDirection, int windSpeed, int raceType, List<BoatStatus> boatStatuses){
|
||||
super(MessageType.RACESTATUS);
|
||||
this.currentTime = currentTime;
|
||||
this.raceID = raceID;
|
||||
this.raceStatus = raceStatus;
|
||||
this.expectedStartTime = expectedStartTime;
|
||||
this.windDirection = windDirection;
|
||||
this.windSpeed = windSpeed;
|
||||
this.raceType = raceType;
|
||||
this.boatStatuses = boatStatuses;//note this is not a copy so any alterations to the parent will affect this.
|
||||
}
|
||||
|
||||
|
||||
|
||||
///Getters.
|
||||
|
||||
public long getCurrentTime()
|
||||
{
|
||||
return currentTime;
|
||||
}
|
||||
|
||||
public int getRaceID()
|
||||
{
|
||||
return raceID;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return race status number
|
||||
*/
|
||||
public int getRaceStatus()
|
||||
{
|
||||
return raceStatus;
|
||||
}
|
||||
|
||||
public long getExpectedStartTime()
|
||||
{
|
||||
return expectedStartTime;
|
||||
}
|
||||
|
||||
public int getWindDirection()
|
||||
{
|
||||
return windDirection;
|
||||
}
|
||||
|
||||
public int getWindSpeed()
|
||||
{
|
||||
return windSpeed;
|
||||
}
|
||||
|
||||
public int getRaceType()
|
||||
{
|
||||
return raceType;
|
||||
}
|
||||
|
||||
public List<BoatStatus> getBoatStatuses()
|
||||
{
|
||||
return boatStatuses;
|
||||
}
|
||||
|
||||
public boolean isNotActive() {
|
||||
return raceStatus == 0;
|
||||
}
|
||||
|
||||
public boolean isWarning() {
|
||||
return raceStatus == 1;
|
||||
}
|
||||
|
||||
public boolean isPreparatory() {
|
||||
return raceStatus == 2;
|
||||
}
|
||||
|
||||
public boolean isStarted() {
|
||||
return raceStatus == 3;
|
||||
}
|
||||
|
||||
public boolean isFinished() {
|
||||
return raceStatus == 4;
|
||||
}
|
||||
|
||||
public boolean isRetired() {
|
||||
return raceStatus == 5;
|
||||
}
|
||||
|
||||
public boolean isAbandoned() {
|
||||
return raceStatus == 6;
|
||||
}
|
||||
|
||||
public boolean isPostponed() {
|
||||
return raceStatus == 7;
|
||||
}
|
||||
|
||||
public boolean isTerminated() {
|
||||
return raceStatus == 8;
|
||||
}
|
||||
|
||||
public boolean isStartTimeSet() {
|
||||
return raceStatus != 9;
|
||||
}
|
||||
|
||||
public boolean isPrestart() {
|
||||
return raceStatus == 10;
|
||||
}
|
||||
|
||||
public double getScaledWindDirection() {
|
||||
return (double) AC35UnitConverter.convertHeading(windDirection);
|
||||
}
|
||||
}
|
||||
@ -1,57 +0,0 @@
|
||||
package seng302.Networking.Messages;
|
||||
|
||||
import seng302.Networking.Messages.Enums.MessageType;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Created by fwy13 on 25/04/17.
|
||||
*/
|
||||
public class XMLMessage extends AC35Data {
|
||||
|
||||
private int ackNumber;
|
||||
private long timeStamp;
|
||||
private int xmlMsgSubType;
|
||||
private int sequenceNumber;
|
||||
private int xmlMsgLength;
|
||||
private InputStream xmlMessage;
|
||||
|
||||
public static int XMLTypeRegatta = 5;
|
||||
public static int XMLTypeRace = 6;
|
||||
public static int XMLTypeBoat = 7;
|
||||
|
||||
/**
|
||||
* Constructor for an XML Message
|
||||
* @param ackNumber Number for acknowledgement inherited for the AC35Data Packet
|
||||
* @param timeStamp Time received
|
||||
* @param xmlMsgSubType Type of XML message
|
||||
* @param sequenceNumber Order that it has arrived in
|
||||
* @param xmlMsgLength Length of the xml message
|
||||
* @param xmlMessage XML message
|
||||
*/
|
||||
public XMLMessage(int ackNumber, long timeStamp, int xmlMsgSubType, int sequenceNumber, int xmlMsgLength, InputStream xmlMessage){
|
||||
super(MessageType.XMLMESSAGE);
|
||||
this.ackNumber = ackNumber;
|
||||
this.timeStamp = timeStamp;
|
||||
this.xmlMsgSubType = xmlMsgSubType;
|
||||
this.sequenceNumber = sequenceNumber;
|
||||
this.xmlMsgLength = xmlMsgLength;
|
||||
this.xmlMessage = xmlMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the XML Message
|
||||
* @return the XML message as an input stream
|
||||
*/
|
||||
public InputStream getXmlMessage() {
|
||||
return xmlMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of message
|
||||
* @return Gets the type of message the XML message is
|
||||
*/
|
||||
public int getXmlMsgSubType() {
|
||||
return xmlMsgSubType;
|
||||
}
|
||||
}
|
||||
@ -1,71 +0,0 @@
|
||||
package seng302.Networking.PacketDump;
|
||||
|
||||
import seng302.Networking.BinaryMessageDecoder;
|
||||
import seng302.Networking.Exceptions.InvalidMessageException;
|
||||
import seng302.Networking.Messages.AC35Data;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Created by fwy13 on 25/04/17.
|
||||
*/
|
||||
public class AC35DumpReader {
|
||||
|
||||
private byte[] dump;
|
||||
private ArrayList<AC35Packet> packets;
|
||||
|
||||
public AC35DumpReader(String url) throws IOException, URISyntaxException {
|
||||
|
||||
URL uri = getClass().getClassLoader().getResource(url);
|
||||
Path path = Paths.get(uri.toURI());
|
||||
dump = Files.readAllBytes(path);
|
||||
|
||||
packets = new ArrayList<>();
|
||||
|
||||
readAllPackets();
|
||||
}
|
||||
|
||||
private void readAllPackets(){
|
||||
int pointer = 0;
|
||||
while(pointer < dump.length){
|
||||
byte[] messLen = new byte[2];
|
||||
messLen[1] = dump[pointer + 13];
|
||||
messLen[0] = dump[pointer + 14];
|
||||
int messageLength = ByteBuffer.wrap(messLen).getShort();
|
||||
//System.out.println(messageLength);
|
||||
|
||||
packets.add(new AC35Packet(Arrays.copyOfRange(dump, pointer, pointer + messageLength + 19)));
|
||||
|
||||
pointer += 19 + messageLength;
|
||||
}
|
||||
for (AC35Packet pack: packets){
|
||||
BinaryMessageDecoder decoder = new BinaryMessageDecoder(pack.getData());
|
||||
|
||||
try {
|
||||
AC35Data data = decoder.decode();
|
||||
}
|
||||
catch (InvalidMessageException e) {
|
||||
System.out.println(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void main(String[] args){
|
||||
try {
|
||||
AC35DumpReader ac35DumpReader = new AC35DumpReader("dataDumps/ac35.bin");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (URISyntaxException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
package seng302.Networking.PacketDump;
|
||||
|
||||
/**
|
||||
* Created by fwy13 on 25/04/17.
|
||||
*/
|
||||
public class AC35Packet {
|
||||
|
||||
byte[] data;
|
||||
|
||||
public AC35Packet(byte[] data){
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public byte[] getData() {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
@ -1,43 +0,0 @@
|
||||
package seng302.Networking.Utils;
|
||||
|
||||
/**
|
||||
* Created by fwy13 on 28/04/17.
|
||||
*/
|
||||
public class AC35UnitConverter {
|
||||
|
||||
public static double convertGPS(int value){
|
||||
//converts latitude or longitue to angle
|
||||
return (double) value * 180.0 / 2147483648.0;//2^31 = 2147483648
|
||||
}
|
||||
|
||||
public static int convertGPSToInt(double value){
|
||||
//converts latitude or longitue to angle
|
||||
return (int) (value * 2147483648.0/180.0);//2^31 = 2147483648
|
||||
}
|
||||
|
||||
public static double convertHeading(long value){
|
||||
return (double) value * 360.0/65536.0;//2^15
|
||||
}
|
||||
|
||||
public static double convertHeading(int value){
|
||||
return (double) value * 360.0/65536.0;//2^15
|
||||
}
|
||||
|
||||
|
||||
public static double convertHeading(double value){
|
||||
return value * 360.0/65536.0;//2^15
|
||||
}
|
||||
|
||||
public static int encodeHeading(int value){
|
||||
return (int) (value / 360.0 * 65536.0);//2^15
|
||||
}
|
||||
|
||||
public static int encodeHeading(double value){
|
||||
return (int) (value / 360.0 * 65536.0);//2^15
|
||||
}
|
||||
|
||||
public static double convertTrueWindAngle(long value){
|
||||
return (double) value * 180.0/32768.0;//-2^15 to 2^15
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,266 +0,0 @@
|
||||
package seng302.Networking.Utils;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Created by fwy13 on 25/04/17.
|
||||
*/
|
||||
public class ByteConverter {
|
||||
|
||||
public static int IntegerSize = 4;
|
||||
public static int LongSize = 8;
|
||||
public static int CharSize = 2;
|
||||
public static int ShortSize = 2;
|
||||
|
||||
|
||||
//default for AC35 is Little Endian therefore all overloads will be done with Little_Endian unless told else wise
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
//Bytes[] to number conversions
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
//Integer
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @param bite bite to convert
|
||||
* @return int
|
||||
*/
|
||||
public static int bytesToInt(byte bite){
|
||||
byte[] bytes = {bite};
|
||||
return bytesToInt(bytes, ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bytes bytes to convert
|
||||
* @return int
|
||||
*/
|
||||
public static int bytesToInt(byte[] bytes){
|
||||
return bytesToInt(bytes, ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bytes bytes to convert
|
||||
* @param byteOrder order of the bytes
|
||||
* @return int
|
||||
*/
|
||||
public static int bytesToInt(byte[] bytes, ByteOrder byteOrder){
|
||||
byte[] bites = convertBytesToNum(bytes,byteOrder, IntegerSize);
|
||||
return ByteBuffer.wrap(bites).order(byteOrder).getInt();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
//Long
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
public static long bytesToLong(byte bite){
|
||||
byte[] bytes = {bite};
|
||||
return bytesToLong(bytes, ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
|
||||
public static long bytesToLong(byte[] bytes){
|
||||
return bytesToLong(bytes, ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
|
||||
public static long bytesToLong(byte[] bytes, ByteOrder byteOrder){
|
||||
byte[] bites = convertBytesToNum(bytes,byteOrder, LongSize);
|
||||
return ByteBuffer.wrap(bites).order(byteOrder).getLong();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
//Short
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
public static short bytesToShort(byte bite){
|
||||
byte[] bytes = {bite};
|
||||
return bytesToShort(bytes, ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
|
||||
public static short bytesToShort(byte[] bytes){
|
||||
return bytesToShort(bytes, ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
|
||||
public static short bytesToShort(byte[] bytes, ByteOrder byteOrder){
|
||||
byte[] bites = convertBytesToNum(bytes,byteOrder, ShortSize);
|
||||
return ByteBuffer.wrap(bites).order(byteOrder).getShort();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
//Char
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
public static char bytesToChar(byte bite){
|
||||
byte[] bytes = {bite};
|
||||
return bytesToChar(bytes, ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
|
||||
public static char bytesToChar(byte[] bytes){
|
||||
return bytesToChar(bytes, ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
|
||||
public static char bytesToChar(byte[] bytes, ByteOrder byteOrder){
|
||||
byte[] bites = convertBytesToNum(bytes,byteOrder, CharSize);
|
||||
return ByteBuffer.wrap(bites).order(byteOrder).getChar();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
//Conversion Function
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
private static byte[] convertBytesToNum(byte[] bytes, ByteOrder byteOrder, int maxSize){
|
||||
byte[] bites = new byte[maxSize];
|
||||
if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
if (i > maxSize){//break if over hte limit
|
||||
break;
|
||||
}
|
||||
bites[i] = bytes[i];
|
||||
}
|
||||
for (int i = bytes.length; i < maxSize; i++) {
|
||||
bites[i] = 0b0;
|
||||
}
|
||||
}else{//if big endian
|
||||
for (int i = 0; i < maxSize - bytes.length; i++) {
|
||||
bites[i] = 0b0;
|
||||
}
|
||||
for (int i = maxSize - bytes.length; i < maxSize; i++) {
|
||||
if (i > maxSize){//break if over the limit
|
||||
break;
|
||||
}
|
||||
bites[i] = bytes[i - maxSize + bytes.length];
|
||||
}
|
||||
}
|
||||
return bites;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
//Number to Byte[] conversions
|
||||
//////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
//Integer
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
public static byte[] intToBytes(int i){
|
||||
return intToBytes(i, 4, ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
|
||||
public static byte[] intToBytes(int i ,int size){
|
||||
return intToBytes(i, size, ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an Integer to a Byte Array
|
||||
* @param i the integer to be converted
|
||||
* @param size Size that the byte array should be
|
||||
* @param byteOrder the order that the bytes should be ie Big Endian
|
||||
* @return bytes array
|
||||
*/
|
||||
public static byte[] intToBytes(int i ,int size, ByteOrder byteOrder){
|
||||
ByteBuffer buffer = ByteBuffer.allocate(IntegerSize);
|
||||
buffer.order(byteOrder);
|
||||
buffer.putInt(i);
|
||||
byte[] copy = buffer.array();
|
||||
return convertNumtoBytes(copy, size, byteOrder, IntegerSize);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
//Long
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
public static byte[] longToBytes(long i){
|
||||
return longToBytes(i, LongSize, ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
|
||||
public static byte[] longToBytes(long i ,int size){
|
||||
return longToBytes(i, size, ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an Long to a Byte Array
|
||||
* @param i the Long to be converted
|
||||
* @param size Size that the byte array should be
|
||||
* @param byteOrder the order that the bytes should be ie Big Endian
|
||||
* @return byte array
|
||||
*/
|
||||
public static byte[] longToBytes(long i ,int size, ByteOrder byteOrder){
|
||||
ByteBuffer buffer = ByteBuffer.allocate(LongSize);
|
||||
buffer.order(byteOrder);
|
||||
buffer.putLong(i);
|
||||
byte[] copy = buffer.array();
|
||||
return convertNumtoBytes(copy, size, byteOrder, LongSize);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
//Short
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
public static byte[] shortToBytes(short i){
|
||||
return shortToBytes(i, ShortSize, ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
|
||||
public static byte[] shortToBytes(short i ,int size){
|
||||
return shortToBytes(i, size, ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an Short to a Byte Array
|
||||
* @param i the Short to be converted
|
||||
* @param size Size that the byte array should be
|
||||
* @param byteOrder the order that the bytes should be ie Big Endian
|
||||
* @return byte array
|
||||
*/
|
||||
public static byte[] shortToBytes(short i ,int size, ByteOrder byteOrder){
|
||||
ByteBuffer buffer = ByteBuffer.allocate(ShortSize);
|
||||
buffer.order(byteOrder);
|
||||
buffer.putShort(i);
|
||||
byte[] copy = buffer.array();
|
||||
return convertNumtoBytes(copy, size, byteOrder, ShortSize);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
//Char
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
public static byte[] charToBytes(char i){
|
||||
return charToBytes(i, CharSize, ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
|
||||
public static byte[] charToBytes(char i ,int size){
|
||||
return charToBytes(i, size, ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts an Char to a Byte Array
|
||||
* @param i the Char to be converted
|
||||
* @param size Size that the byte array should be
|
||||
* @param byteOrder the order that the bytes should be ie Big Endian
|
||||
* @return byte array
|
||||
*/
|
||||
public static byte[] charToBytes(char i ,int size, ByteOrder byteOrder){
|
||||
ByteBuffer buffer = ByteBuffer.allocate(CharSize);
|
||||
buffer.order(byteOrder);
|
||||
buffer.putChar(i);
|
||||
byte[] copy = buffer.array();
|
||||
return convertNumtoBytes(copy, size, byteOrder, CharSize);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
//Conversion Function
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
private static byte[] convertNumtoBytes(byte[] copy ,int size, ByteOrder byteOrder, int fullsize){
|
||||
byte[] bytes = new byte[size];
|
||||
if (byteOrder == ByteOrder.LITTLE_ENDIAN){
|
||||
bytes = Arrays.copyOfRange(copy, 0, size);
|
||||
}else{// if it is Big Endian
|
||||
bytes = Arrays.copyOfRange(copy, fullsize - size, fullsize);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Loading…
Reference in new issue