Did some large tidy ups, refactoring, and documenting.

Network:
Moved the Network message classes from the Utils package to the Messages package.
Renamed BoatLocationMessage to BoatLocation and BoatStatusMessage to BoatStatus to be consistent with other message classes.
Renamed the BoatStatus enumeration to BoatStatusEnum as it conflicted with BoatStatus (the message).
Moved the BoatStatusEnum and MessageType enumerations from the Utils package to the Messages/Enums package.
Changed the BoatStatusEnum and MessageType enumerations to use map look ups in the enum.fromByte(b) method - this means that there's less copy and pasted values, and the fromByte function doesn't need to be modified if new enumerations are added.
Added a sequenceNumber member to the Heartbeat class.
Added an InvalidMessageException in the package Networking/Exceptions. This is thrown when a message is read, but it is invalid in some way.
Refactored/tidied up the Networking/BinaryMessageEncoder and Decoder classes. The decoder throws InvalidMessageExceptions instead of returning null.

Visualiser:
VisualiserInput now wraps a DataInputStream around the socket. This provides the stream.readFully(buffer) function, which is a blocking read, removing the need for busy wait loops. Replaced the getBytes() function with getNextMessage() and getNextMessageBytes(). These read the next message from the socket, and return it as a message object and a byte array, respectively.
Changed the current heartbeat timeout to 10 seconds. Added some work-in-progress code to attempt to reconnect when connection is lost. It currently doesn't work. I think Fan-Wu was doing a proper implementation, however.
VisualiserInput also has a queue of received events. Currently not really used, but could be useful in the future. Events get added as they are read.
Changed VisualiserInputs main loop to use instanceOf instead of switch+case. Feedback wanted - are there any downsides to using this instanceOf method?

#story[778,782]
This commit is contained in:
fjc40
2017-05-08 03:29:33 +12:00
parent 466e22437b
commit b247244665
38 changed files with 1067 additions and 600 deletions
@@ -1,167 +1,281 @@
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.nio.ByteOrder;
import java.util.Arrays;
import java.util.zip.CRC32;
/**
* Created by hba56 on 21/04/17.
*/
public class BinaryMessageDecoder {
private byte[] fullMessage;
private byte[] header;
private byte[] message;
private byte[] crc;
/**
* 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;
private byte[] headerTimeStamp;
private byte[] headerSourceID;
private byte[] headerMessageLength;
///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;
}
public AC35Data decode() throws IndexOutOfBoundsException{
//get the header
this.header = Arrays.copyOfRange(this.fullMessage, 0, 15);
//Get the messageHeader.
this.messageHeader = Arrays.copyOfRange(this.fullMessage, 0, 15);
this.headerSync1 = this.header[0];
this.headerSync2 = this.header[1];
this.headerMessageType = this.header[2];
this.headerTimeStamp = Arrays.copyOfRange(this.header, 3, 9);
this.headerSourceID = Arrays.copyOfRange(this.header, 9, 13);
this.headerMessageLength = Arrays.copyOfRange(this.header, 13, 15);
//Get the sync bytes.
this.headerSync1 = this.messageHeader[0];
this.headerSync2 = this.messageHeader[1];
if (15 > this.fullMessage.length - 4){
//System.err.println("Message is too short.");
return null;
}
//get message
this.message = Arrays.copyOfRange(this.fullMessage, 15, this.fullMessage.length - 4);
//Get the message type.
this.headerMessageType = this.messageHeader[2];
//get crc
this.crc = Arrays.copyOfRange(this.fullMessage, this.fullMessage.length - 4, fullMessage.length);
ByteBuffer bytes = ByteBuffer.allocate(this.header.length + this.message.length);
bytes.put(this.header);
bytes.put(this.message);
//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(bytes.array(), 0, bytes.array().length);
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);
//run through the checks
if (this.message.length != ByteConverter.bytesToShort(this.headerMessageLength)){//keep like this - hba65
System.err.println("message length in header does not equal the message length");
System.err.println("message length in header: " + ByteConverter.bytesToInt(this.headerMessageLength));
System.err.println("message length: " + this.message.length);
return null;
}else if(this.headerSync1 != 0x47){
System.err.println("Sync byte 1 is wrong: " + this.headerSync1);
return null;
}else if(this.headerSync2 !=(byte) 0x83){
System.err.println("Sync byte 2 is wrong: " + this.headerSync2);
return null;
}else if(crc.getValue() != ByteConverter.bytesToLong(this.crc)){
//todo check crc
System.err.println("CRC is not "+ByteConverter.bytesToLong(this.crc)+" and is instead:" + crc.getValue());
return null;
}
MessageType mType = MessageType.valueOf(this.headerMessageType);
AC35Data data = null;
//Now we create the message object based on what is actually in the message body.
MessageType mType = MessageType.fromByte(headerMessageType);
switch(mType){
switch(mType) {
case HEARTBEAT:
// System.out.println("HeartBeat Message!");
data = new Heartbeat();
break;
//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(this.message);
data = new RaceStatus(rsdecoder.getTime(), rsdecoder.getRace(), rsdecoder.getRaceState(), rsdecoder.getStartTime(), rsdecoder.getRaceWindDir(), rsdecoder.getRaceWindSpeed(), rsdecoder.getRaceType(), rsdecoder.getBoats());
break;
//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.
break;
//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(this.message);
//System.out.println("XML Message!");
XMLMessageDecoder xmdecoder = new XMLMessageDecoder(messageBody);
xmdecoder.decode();
data = new XMLMessage(xmdecoder.getAckNumber(), xmdecoder.getTimeStamp(), xmdecoder.getXmlMsgSubType(), xmdecoder.getSequenceNumber(), xmdecoder.getXmlMsgLength(), xmdecoder.getXmlMessageInputStream());
break;
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(this.message);
data = new RaceStartStatus(rssDecoder.getTime(), rssDecoder.getAck(), rssDecoder.getStartTime(), rssDecoder.getRaceID(), rssDecoder. getNotification());
break;
//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
break;
//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
break;
//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
break;
//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(this.message);
data = blDecoder.getMessage();
break;
//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(this.message);
data = mrDecoder.getMarkRounding();
break;
//System.out.println("Mark Rounding Message!");
MarkRoundingDecoder mrDecoder = new MarkRoundingDecoder(messageBody);
return mrDecoder.getMarkRounding();
case COURSEWIND:
// System.out.println("Couse Wind Message!");
CourseWindDecoder cwDecoder = new CourseWindDecoder(this.message);
data =new CourseWinds(cwDecoder.getMessageVersionNumber(), cwDecoder.getByteWindID(), cwDecoder.getLoopMessages());
break;
//System.out.println("Couse 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(this.message);
data = awDecoder.getAverageWind();
break;
//System.out.println("Average Wind Message!");
AverageWindDecoder awDecoder = new AverageWindDecoder(messageBody);
return awDecoder.getAverageWind();
default:
// System.out.println("Broken Message!");
break;
//System.out.println("Broken Message!");
throw new InvalidMessageException("Broken message! Did not recognise message type: " + headerMessageType + ".");
}
return data;
}
public long getTimeStamp() {
return ByteConverter.bytesToLong(this.headerTimeStamp);
/**
* Returns the first sync byte value.
* @return The first sync byte value.
*/
public byte getHeaderSync1() {
return headerSync1;
}
public int getSourceID() {
return ByteConverter.bytesToInt(this.headerSourceID, ByteOrder.BIG_ENDIAN);
/**
* Returns the second sync byte value.
* @return The second sync byte value.
*/
public byte getHeaderSync2() {
return headerSync2;
}
public short getMessageLength() {
return ByteConverter.bytesToShort(this.headerMessageLength);
/**
* Returns the message type.
* @return The message type.
*/
public byte getHeaderMessageType() {
return headerMessageType;
}
public int getMessageType(){
return (int) this.headerMessageType;
/**
* Returns the header timestamp.
* @return The header timestamp.
*/
public long getHeaderTimeStamp() {
return headerTimeStamp;
}
public byte[] getMessage() {
return message;
/**
* 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,10 +1,9 @@
package seng302.Networking;
import seng302.Networking.Utils.MessageType;
import seng302.Networking.Messages.Enums.MessageType;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.zip.CRC32;
import static seng302.Networking.Utils.ByteConverter.intToBytes;
@@ -14,56 +13,96 @@ import static seng302.Networking.Utils.ByteConverter.shortToBytes;
/**
* Created by hba56 on 21/04/17.
*/
/**
* 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;
private byte[] header;
private byte[] message;
//private byte[] crc;
///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;
private byte headerMessageType;
private long headerTimeStamp;
private int headerSourceID;
private short headerMessageLength;
public BinaryMessageEncoder(MessageType headerMessageType, long headerTimeStamp, int headerSourceID, short headerMessageLength, byte[] message){
//set the header
///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.headerMessageLength = headerMessageLength;
this.bodyMessageLength = bodyMessageLength;
ByteBuffer tempHeaderByteBuffer = ByteBuffer.allocate(15);
//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.putInt(this.headerSourceID);
tempHeaderByteBuffer.put(shortToBytes(this.headerMessageLength));
tempHeaderByteBuffer.put(intToBytes(this.headerSourceID));
tempHeaderByteBuffer.put(shortToBytes(this.bodyMessageLength));
this.messageHeader = tempHeaderByteBuffer.array();
//Set the message body.
this.messageBody = messageBody;
this.header = tempHeaderByteBuffer.array();
//set the message
this.message = message;
//set full message
ByteBuffer tempMessageByteBuffer = ByteBuffer.allocate(19+this.headerMessageLength);
tempMessageByteBuffer.put(this.header);
tempMessageByteBuffer.put(this.message);
//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();
byte[] messageAndHeader = new byte[this.header.length + this.message.length];
System.arraycopy(this.header, 0, messageAndHeader, 0, this.header.length);
System.arraycopy(this.message, 0, messageAndHeader, this.header.length, this.message.length);
crc.update(messageAndHeader);
crc.update(tempHeaderBodyByteBuffer.array());
this.calculatedCRCValue = crc.getValue();
tempMessageByteBuffer.put(intToBytes((int) crc.getValue()));
this.fullMessage = tempMessageByteBuffer.array();
//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;
}
@@ -0,0 +1,29 @@
package seng302.Networking.Exceptions;
/**
* Created by f123 on 07-May-17.
*/
/**
* 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,6 +1,6 @@
package seng302.Networking.MessageDecoders;
import seng302.Networking.Utils.AverageWind;
import seng302.Networking.Messages.AverageWind;
import seng302.Networking.Utils.ByteConverter;
import java.util.Arrays;
@@ -1,9 +1,7 @@
package seng302.Networking.MessageDecoders;
import seng302.Networking.Utils.BoatLocationMessage;
import seng302.Networking.Messages.BoatLocation;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Arrays;
import static seng302.Networking.Utils.ByteConverter.*;
@@ -35,7 +33,7 @@ public class BoatLocationDecoder {
private byte[] currentSet;
private byte[] rudderAngle;
private BoatLocationMessage message;
private BoatLocation message;
public BoatLocationDecoder(byte[] encodedBoatLocation) {
messageVersionNumber = encodedBoatLocation[0];
@@ -64,7 +62,7 @@ public class BoatLocationDecoder {
// System.out.println(bytesToInt(sourceID));
// System.out.println(bytesToInt(boatSpeed));
message = new BoatLocationMessage(messageVersionNumber, bytesToLong(time),
message = new BoatLocation(messageVersionNumber, bytesToLong(time),
bytesToInt(sourceID), bytesToInt(seqNum),
deviceType, bytesToInt(latitude),
bytesToInt(longitude), bytesToInt(altitude),
@@ -79,7 +77,7 @@ public class BoatLocationDecoder {
}
public BoatLocationMessage getMessage() {
public BoatLocation getMessage() {
return message;
}
}
@@ -1,9 +1,7 @@
package seng302.Networking.MessageDecoders;
import seng302.Networking.Utils.CourseWind;
import seng302.Networking.Messages.CourseWind;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.Arrays;
@@ -1,7 +1,7 @@
package seng302.Networking.MessageDecoders;
import seng302.Networking.Utils.ByteConverter;
import seng302.Networking.Utils.MarkRounding;
import seng302.Networking.Messages.MarkRounding;
import java.util.Arrays;
@@ -1,6 +1,6 @@
package seng302.Networking.MessageDecoders;
import seng302.Networking.Utils.BoatStatusMessage;
import seng302.Networking.Messages.BoatStatus;
import java.util.ArrayList;
import java.util.Arrays;
@@ -30,7 +30,7 @@ public class RaceStatusDecoder {
private short raceWindSpeed;
private int numberOfBoats;
private int raceType;
private ArrayList<BoatStatusMessage> boats = new ArrayList<>();
private ArrayList<BoatStatus> boats = new ArrayList<>();
public RaceStatusDecoder(byte[] encodedRaceStatus){
@@ -66,7 +66,7 @@ public class RaceStatusDecoder {
byte[] estTimeAtNextMark = Arrays.copyOfRange(boatBytes, 8, 14);
byte[] estTimeAtFinish = Arrays.copyOfRange(boatBytes, 14, 20);
BoatStatusMessage boat = new BoatStatusMessage(bytesToInt(sourceID),boatStatus,
BoatStatus boat = new BoatStatus(bytesToInt(sourceID),boatStatus,
legNumber, numPenaltiesAwarded, numPenaltiesServed,
bytesToLong(estTimeAtNextMark), bytesToLong(estTimeAtFinish));
@@ -111,7 +111,7 @@ public class RaceStatusDecoder {
return raceType;
}
public ArrayList<BoatStatusMessage> getBoats() {
public ArrayList<BoatStatus> getBoats() {
return boats;
}
}
@@ -1,7 +1,7 @@
package seng302.Networking.MessageEncoders;
import seng302.Networking.Utils.*;
import seng302.Networking.Messages.*;
import java.nio.ByteBuffer;
import java.util.ArrayList;
@@ -32,9 +32,9 @@ public class RaceVisionByteEncoder {
*/
public static byte[] raceStatus(RaceStatus raceStatus){
ArrayList<BoatStatusMessage> boatStatusMessages = raceStatus.getBoatStatusMessages();
ArrayList<BoatStatus> boatStatuses = raceStatus.getBoatStatuses();
ByteBuffer raceStatusMessage = ByteBuffer.allocate(24 + 20* boatStatusMessages.size());
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)
@@ -43,7 +43,7 @@ public class RaceVisionByteEncoder {
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(boatStatusMessages.size(), 1);
byte[] numBoats = intToBytes(boatStatuses.size(), 1);
byte[] bytesRaceType = intToBytes(raceStatus.getRaceType(), 1);//1 match race, 2 fleet race
raceStatusMessage.put(versionNum);
@@ -56,14 +56,14 @@ public class RaceVisionByteEncoder {
raceStatusMessage.put(numBoats);
raceStatusMessage.put(bytesRaceType);
for (int i = 0; i < boatStatusMessages.size(); i++){
byte[] sourceID = intToBytes(boatStatusMessages.get(i).getSourceID());
byte[] boatStatus = intToBytes(boatStatusMessages.get(i).getBoatStatus(), 1);
byte[] legNum = intToBytes(boatStatusMessages.get(i).getLegNumber(), 1);
byte[] numPenalties = intToBytes(boatStatusMessages.get(i).getNumPenaltiesAwarded(), 1);
byte[] numPenaltiesServed = intToBytes(boatStatusMessages.get(i).getNumPenaltiesServed(), 1);
byte[] estNextMarkTime = longToBytes(boatStatusMessages.get(i).getEstTimeAtNextMark(), 6);
byte[] estFinishTime = longToBytes( boatStatusMessages.get(i).getEstTimeAtFinish(), 6);
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);
@@ -173,29 +173,29 @@ public class RaceVisionByteEncoder {
return result.array();
}
public static byte[] boatLocation(BoatLocationMessage boatLocationMessage){
public static byte[] boatLocation(BoatLocation boatLocation){
int messageVersionNumber = 0b1;
byte[] time = longToBytes(boatLocationMessage.getTime(), 6);
byte[] sourceID = intToBytes(boatLocationMessage.getSourceID(), 4);
byte[] seqNum = longToBytes(boatLocationMessage.getSequenceNumber(), 4);
byte[] deviceType = intToBytes(boatLocationMessage.getDeviceType(), 1);
byte[] latitude = intToBytes(boatLocationMessage.getLatitude(), 4);
byte[] longitude = intToBytes(boatLocationMessage.getLongitude(), 4);
byte[] altitude = intToBytes(boatLocationMessage.getAltitude(), 4);
byte[] heading = intToBytes(boatLocationMessage.getHeading(), 2);
byte[] pitch = intToBytes(boatLocationMessage.getPitch(), 2);
byte[] roll = intToBytes(boatLocationMessage.getRoll(), 2);
byte[] boatSpeed = intToBytes(boatLocationMessage.getBoatSpeed(), 2);
byte[] cog = intToBytes(boatLocationMessage.getBoatCOG(), 2);
byte[] sog = intToBytes(boatLocationMessage.getBoatSOG(), 2);
byte[] apparentWindSpeed = intToBytes(boatLocationMessage.getApparentWindSpeed(), 2);
byte[] apparentWindAngle = intToBytes(boatLocationMessage.getApparentWindAngle(), 2);
byte[] trueWindSpeed = intToBytes(boatLocationMessage.getTrueWindSpeed(), 2);
byte[] trueWindDirection = intToBytes(boatLocationMessage.getTrueWindDirection(), 2);
byte[] trueWindAngle = intToBytes(boatLocationMessage.getTrueWindAngle(), 2);
byte[] currentDrift = intToBytes(boatLocationMessage.getCurrentDrift(), 2);
byte[] currentSet = intToBytes(boatLocationMessage.getCurrentSet(), 2);
byte[] rudderAngle = intToBytes(boatLocationMessage.getRudderAngle(), 2);
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));
@@ -0,0 +1,35 @@
package seng302.Networking.Messages;
/**
* Created by fwy13 on 25/04/17.
*/
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,9 +1,11 @@
package seng302.Networking.Utils;
package seng302.Networking.Messages;
import seng302.Networking.Messages.Enums.MessageType;
/**
* Created by fwy13 on 25/04/17.
*/
public class AverageWind extends AC35Data{
public class AverageWind extends AC35Data {
private int msgNum;
private long lngTime;
@@ -1,10 +1,12 @@
package seng302.Networking.Utils;
package seng302.Networking.Messages;
/**
* Created by f123 on 21-Apr-17.
*/
import SharedModel.Constants;
import seng302.Networking.Utils.AC35UnitConverter;
import seng302.Networking.Messages.Enums.MessageType;
import static seng302.Networking.Utils.AC35UnitConverter.convertGPS;
import static seng302.Networking.Utils.AC35UnitConverter.convertGPSToInt;
@@ -12,8 +14,8 @@ import static seng302.Networking.Utils.AC35UnitConverter.convertGPSToInt;
/**
* Represents the information in a boat location message (AC streaming spec: 4.9).
*/
public class BoatLocationMessage extends AC35Data
{
public class BoatLocation extends AC35Data {
public static final byte Unknown = 0;
public static final byte RacingYacht = 1;
public static final byte CommitteeBoat = 2;
@@ -93,7 +95,7 @@ public class BoatLocationMessage extends AC35Data
/**
* Ctor. Default.
*/
public BoatLocationMessage() {
public BoatLocation() {
super(MessageType.BOATLOCATION);
}
@@ -123,7 +125,7 @@ public class BoatLocationMessage extends AC35Data
* @param currentSet current set
* @param rudderAngle rudder angle
*/
public BoatLocationMessage(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) {
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;
@@ -150,7 +152,7 @@ public class BoatLocationMessage extends AC35Data
this.rudderAngle = rudderAngle;
}
public BoatLocationMessage(int sourceID, double lat, double lon, long sequenceNumber, double heading, double boatSpeed) {
public BoatLocation(int sourceID, double lat, double lon, long sequenceNumber, double heading, double boatSpeed) {
super(MessageType.BOATLOCATION);
this.messageVersionNumber = (byte) 1;
@@ -1,11 +1,13 @@
package seng302.Networking.Utils;
package seng302.Networking.Messages;
import seng302.Networking.Utils.Enums.BoatStatus;
import seng302.Networking.Utils.ByteConverter;
import seng302.Networking.Messages.Enums.BoatStatusEnum;
/**
* Created by hba56 on 23/04/17.
*/
public class BoatStatusMessage {
public class BoatStatus {
private int sourceID;
private byte boatStatus;
private byte legNumber;
@@ -14,7 +16,7 @@ public class BoatStatusMessage {
private long estTimeAtNextMark;
private long estTimeAtFinish;
public BoatStatusMessage(int sourceID, byte boatStatus, byte legNumber, byte numPenaltiesAwarded, byte numPenaltiesServed, long estTimeAtNextMark, 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;
@@ -25,9 +27,9 @@ public class BoatStatusMessage {
}
public BoatStatusMessage(int sourceID, BoatStatus boatStatus, int legNum) {
public BoatStatus(int sourceID, BoatStatusEnum boatStatusEnum, int legNum) {
this.sourceID = sourceID;
this.boatStatus = boatStatus.getValue();
this.boatStatus = boatStatusEnum.getValue();
this.legNumber = ByteConverter.intToBytes(legNum)[0];
numPenaltiesAwarded = 0;
numPenaltiesServed = 0;
@@ -1,9 +1,11 @@
package seng302.Networking.Utils;
package seng302.Networking.Messages;
import seng302.Networking.Messages.Enums.MessageType;
/**
* Created by fwy13 on 21/04/17.
*/
public class CourseWind extends AC35Data{
public class CourseWind extends AC35Data {
private int ID, raceID, windDirection, windSpeed, bestUpwindAngle, bestDownwindAngle, flags;
private long time;
@@ -1,11 +1,13 @@
package seng302.Networking.Utils;
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{
public class CourseWinds extends AC35Data {
private int msgVerNum;
private int selectedWindID;
@@ -0,0 +1,79 @@
package seng302.Networking.Messages.Enums;
import java.util.HashMap;
import java.util.Map;
/**
* Created by esa46 on 28/04/17.
*/
/**
* 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;
}
}
}
@@ -0,0 +1,83 @@
package seng302.Networking.Messages.Enums;
/**
* Created by hba56 on 21/04/17.
*/
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;
}
}
}
@@ -0,0 +1,33 @@
package seng302.Networking.Messages;
import seng302.Networking.Messages.Enums.MessageType;
/**
* Created by fwy13 on 25/04/17.
*/
/**
* 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,9 +1,11 @@
package seng302.Networking.Utils;
package seng302.Networking.Messages;
import seng302.Networking.Messages.Enums.MessageType;
/**
* Created by fwy13 on 25/04/17.
*/
public class MarkRounding extends AC35Data{
public class MarkRounding extends AC35Data {
private int msgVerNum;
private long time;
@@ -49,7 +51,19 @@ public class MarkRounding extends AC35Data{
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,4 +1,6 @@
package seng302.Networking.Utils;
package seng302.Networking.Messages;
import seng302.Networking.Messages.Enums.MessageType;
/**
* Created by fwy13 on 19/04/17.
@@ -1,11 +1,12 @@
package seng302.Networking.Utils;
package seng302.Networking.Messages;
import java.util.ArrayList;
import seng302.Networking.Messages.Enums.MessageType;
/**
* Created by fwy13 on 25/04/17.
*/
public class RaceStartStatus extends AC35Data{
public class RaceStartStatus extends AC35Data {
private long timestamp;
private int ackNum;
private long raceStartTime;
@@ -1,11 +1,14 @@
package seng302.Networking.Utils;
package seng302.Networking.Messages;
import seng302.Networking.Messages.Enums.MessageType;
import java.util.ArrayList;
/**
* Created by fwy13 on 25/04/17.
*/
public class RaceStatus extends AC35Data{
public class RaceStatus extends AC35Data {
private long currentTime;
private int raceID;
private int raceStatus;
@@ -13,9 +16,9 @@ public class RaceStatus extends AC35Data{
private int windDirection;
private int windSpeed;
private int raceType;
private ArrayList<BoatStatusMessage> boatStatusMessages;
private ArrayList<BoatStatus> boatStatuses;
public RaceStatus(long currentTime, int raceID, int raceStatus, long expectedStartTime, int windDirection, int windSpeed, int raceType, ArrayList<BoatStatusMessage> boatStatusMessages){
public RaceStatus(long currentTime, int raceID, int raceStatus, long expectedStartTime, int windDirection, int windSpeed, int raceType, ArrayList<BoatStatus> boatStatuses){
super(MessageType.RACESTATUS);
this.currentTime = currentTime;
this.raceID = raceID;
@@ -24,7 +27,7 @@ public class RaceStatus extends AC35Data{
this.windDirection = windDirection;
this.windSpeed = windSpeed;
this.raceType = raceType;
this.boatStatusMessages = boatStatusMessages;//note this is a copy so any alterations to the parent will affect this.
this.boatStatuses = boatStatuses;//note this is a copy so any alterations to the parent will affect this.
}
@@ -70,9 +73,9 @@ public class RaceStatus extends AC35Data{
return raceType;
}
public ArrayList<BoatStatusMessage> getBoatStatusMessages()
public ArrayList<BoatStatus> getBoatStatuses()
{
return boatStatusMessages;
return boatStatuses;
}
public boolean isNotActive() {
@@ -1,13 +1,13 @@
package seng302.Networking.Utils;
package seng302.Networking.Messages;
import org.xml.sax.InputSource;
import seng302.Networking.Messages.Enums.MessageType;
import java.io.InputStream;
/**
* Created by fwy13 on 25/04/17.
*/
public class XMLMessage extends AC35Data{
public class XMLMessage extends AC35Data {
private int ackNumber;
private long timeStamp;
@@ -1,6 +1,8 @@
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;
@@ -48,7 +50,13 @@ public class AC35DumpReader {
}
for (AC35Packet pack: packets){
BinaryMessageDecoder decoder = new BinaryMessageDecoder(pack.getData());
decoder.decode();
try {
AC35Data data = decoder.decode();
}
catch (InvalidMessageException e) {
System.out.println(e.getMessage());
}
}
}
@@ -1,18 +0,0 @@
package seng302.Networking.Utils;
/**
* Created by fwy13 on 25/04/17.
*/
public abstract class AC35Data {
protected MessageType type;
public AC35Data (MessageType type){
this.type = type;
}
public MessageType getType() {
return type;
}
}
@@ -1,41 +0,0 @@
package seng302.Networking.Utils.Enums;
/**
* Created by esa46 on 28/04/17.
*/
public enum BoatStatus {
UNDEFINED(0), PRESTART(1), RACING(2), FINISHED(3), DNS(4), DNF(5), DSQ(6), OCS(7), NOT_A_STATUS(-1);
private byte value;
private BoatStatus(int value) { this.value = (byte)value; }
public byte getValue() {
return value;
}
public static BoatStatus valueOf(byte bite){
switch(bite){
case 0:
return UNDEFINED;
case 1:
return PRESTART;
case 2:
return RACING;
case 3:
return FINISHED;
case 4:
return DNS;
case 5:
return DNF;
case 6:
return DSQ;
case 7:
return OCS;
default:
return NOT_A_STATUS;
}
}
}
@@ -1,12 +0,0 @@
package seng302.Networking.Utils;
/**
* Created by fwy13 on 25/04/17.
*/
public class Heartbeat extends AC35Data{
public Heartbeat(){
super(MessageType.HEARTBEAT);
}
}
@@ -1,49 +0,0 @@
package seng302.Networking.Utils;
/**
* Created by hba56 on 21/04/17.
*/
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);
private byte value;
private MessageType(int value) { this.value = (byte)value; }
public byte getValue() {
return value;
}
public static MessageType valueOf(byte bite){
switch(bite){
case 1:
return HEARTBEAT;
case 12:
return RACESTATUS;
case 20:
return DISPLAYTEXTMESSAGE;
case 26:
return XMLMESSAGE;
case 27:
return RACESTARTSTATUS;
case 29:
return YACHTEVENTCODE;
case 31:
return YACHTACTIONCODE;
case 36:
return CHATTERTEXT;
case 37:
return BOATLOCATION;
case 38:
return MARKROUNDING;
case 44:
return COURSEWIND;
case 47:
return AVGWIND;
default:
return NOTAMESSAGE;
}
}
}
@@ -2,9 +2,12 @@ package seng302.Networking;
import org.junit.Assert;
import org.junit.Test;
import seng302.Networking.Exceptions.InvalidMessageException;
import seng302.Networking.MessageDecoders.XMLMessageDecoder;
import seng302.Networking.MessageEncoders.XMLMessageEncoder;
import seng302.Networking.Utils.MessageType;
import seng302.Networking.Messages.AC35Data;
import seng302.Networking.Messages.Enums.MessageType;
import seng302.Networking.Messages.XMLMessage;
import java.io.*;
@@ -30,19 +33,32 @@ public class BinaryMessageDecoderTest {
BinaryMessageEncoder testMessage = new BinaryMessageEncoder(MessageType.XMLMESSAGE, time, 1, (short)encodedMessage.length, encodedMessage);
BinaryMessageDecoder testDecoder = new BinaryMessageDecoder(testMessage.getFullMessage());
testDecoder.decode();
BinaryMessageDecoder decoder = new BinaryMessageDecoder(testMessage.getFullMessage());
AC35Data message = null;
try {
message = decoder.decode();
}
catch (InvalidMessageException e) {
Assert.assertFalse(e.getMessage(), true);
}
if (!(message instanceof XMLMessage)){
Assert.assertFalse(true);
}
XMLMessage xmlMessage = (XMLMessage) message;
//message length
Assert.assertEquals((short) encodedMessage.length,testDecoder.getMessageLength());
Assert.assertEquals((short) encodedMessage.length, decoder.getMessageBodyLength());
//time stamp
Assert.assertEquals(time,testDecoder.getTimeStamp());
Assert.assertEquals(time, decoder.getHeaderTimeStamp());
//source ID
Assert.assertEquals((short) 1, testDecoder.getSourceID());
Assert.assertEquals((short) 1, decoder.getHeaderSourceID());
//message type
Assert.assertEquals(26, testDecoder.getMessageType());
Assert.assertEquals(26, decoder.getHeaderMessageType());
XMLMessageDecoder decoderXML = new XMLMessageDecoder(testDecoder.getMessage());
XMLMessageDecoder decoderXML = new XMLMessageDecoder(decoder.getMessageBody());
decoderXML.decode();
//tests from seng302.Networking.MessageDecoders.XMLMessageDecoderTest to make sure the file is still good
@@ -62,7 +78,7 @@ public class BinaryMessageDecoderTest {
// Assert.assertEquals(xmlString.toString(), contents);
}catch (IOException e){
e.printStackTrace();
Assert.assertFalse(e.getMessage(), true);
}
}
}
@@ -2,7 +2,7 @@ package seng302.Networking.MessageDecoders;
import org.junit.Assert;
import org.junit.Test;
import seng302.Networking.Utils.BoatLocationMessage;
import seng302.Networking.Messages.BoatLocation;
import seng302.Networking.MessageEncoders.RaceVisionByteEncoder;
@@ -13,7 +13,7 @@ public class BoatLocationDecoderTest {
@Test
public void getByteArrayTest(){
long time = System.currentTimeMillis();
BoatLocationMessage testMessage = new BoatLocationMessage((byte) 1, time, 2,
BoatLocation testMessage = new BoatLocation((byte) 1, time, 2,
3, (byte) 1, 180, -180, 4, 5,
(short) 6, (short) 7, 8, 9, 10, 11,
(short) 12, 13, 14 , (short) 15,
@@ -22,7 +22,7 @@ public class BoatLocationDecoderTest {
byte [] testEncodedMessage = raceVisionByteEncoder.boatLocation(testMessage);
BoatLocationDecoder testDecoder = new BoatLocationDecoder(testEncodedMessage);
BoatLocationMessage decodedTest = testDecoder.getMessage();
BoatLocation decodedTest = testDecoder.getMessage();
Assert.assertEquals(testMessage.getMessageVersionNumber(), decodedTest.getMessageVersionNumber());
Assert.assertEquals(testMessage.getTime(), decodedTest.getTime());
@@ -2,7 +2,7 @@ package seng302.Networking.MessageDecoders;
import org.junit.Assert;
import org.junit.Test;
import seng302.Networking.Utils.CourseWind;
import seng302.Networking.Messages.CourseWind;
import seng302.Networking.MessageEncoders.RaceVisionByteEncoder;
import java.util.ArrayList;
@@ -3,8 +3,8 @@ package seng302.Networking.MessageDecoders;
import org.junit.Assert;
import org.junit.Test;
import seng302.Networking.MessageEncoders.RaceVisionByteEncoder;
import seng302.Networking.Utils.BoatStatusMessage;
import seng302.Networking.Utils.RaceStatus;
import seng302.Networking.Messages.BoatStatus;
import seng302.Networking.Messages.RaceStatus;
import java.util.ArrayList;
@@ -32,8 +32,8 @@ public class RaceStatusDecoderTest {
long boat1TimeAtFinish = boat1TimeAtNextMark + (1000 * 15);
long boat2TimeAtFinish = boat2TimeAtNextMark + (1000 * 7);
BoatStatusMessage boatStatusMessage1 = new BoatStatusMessage(boat1SourceID, boat1Status, boat1LegNumber, boat1PenaltiesAwarded, boat1PenaltiesServed, boat1TimeAtNextMark, boat1TimeAtFinish);
BoatStatusMessage boatStatusMessage2 = new BoatStatusMessage(boat2SourceID, boat2Status, boat2LegNumber, boat2PenaltiesAwarded, boat2PenaltiesServed, boat2TimeAtNextMark, boat2TimeAtFinish);
BoatStatus boatStatus1 = new BoatStatus(boat1SourceID, boat1Status, boat1LegNumber, boat1PenaltiesAwarded, boat1PenaltiesServed, boat1TimeAtNextMark, boat1TimeAtFinish);
BoatStatus boatStatus2 = new BoatStatus(boat2SourceID, boat2Status, boat2LegNumber, boat2PenaltiesAwarded, boat2PenaltiesServed, boat2TimeAtNextMark, boat2TimeAtFinish);
int raceID = 585;
int raceStatus = 3;
@@ -41,11 +41,11 @@ public class RaceStatusDecoderTest {
int windDirection = 2341;
int windSpeed = 10201;
int raceType = 1;
ArrayList<BoatStatusMessage> boatStatusMessages = new ArrayList<>(2);
boatStatusMessages.add(boatStatusMessage1);
boatStatusMessages.add(boatStatusMessage2);
ArrayList<BoatStatus> boatStatuses = new ArrayList<>(2);
boatStatuses.add(boatStatus1);
boatStatuses.add(boatStatus2);
RaceStatus raceStatusObject = new RaceStatus(time, raceID, raceStatus, raceStartTime, windDirection, windSpeed, raceType, boatStatusMessages);
RaceStatus raceStatusObject = new RaceStatus(time, raceID, raceStatus, raceStartTime, windDirection, windSpeed, raceType, boatStatuses);
byte[] encodedRaceStatus = RaceVisionByteEncoder.raceStatus(raceStatusObject);
@@ -61,7 +61,7 @@ public class RaceStatusDecoderTest {
Assert.assertEquals(windSpeed, decoderTest.getRaceWindSpeed());
BoatStatusMessage boat1 = decoderTest.getBoats().get(0);
BoatStatus boat1 = decoderTest.getBoats().get(0);
Assert.assertEquals(boat1SourceID, boat1.getSourceID());
Assert.assertEquals(boat1Status, boat1.getBoatStatus());