commit
7d35312644
@ -0,0 +1,10 @@
|
|||||||
|
package seng302.DataInput;
|
||||||
|
|
||||||
|
import SharedModel.Regatta;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by zwu18 on 25/04/17.
|
||||||
|
*/
|
||||||
|
public interface RegattaDataSource {
|
||||||
|
Regatta getRegatta();
|
||||||
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package seng302;
|
package seng302.DataInput;
|
||||||
|
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
import org.w3c.dom.Element;
|
import org.w3c.dom.Element;
|
||||||
@ -1,10 +0,0 @@
|
|||||||
package seng302.Mock;
|
|
||||||
|
|
||||||
import seng302.Model.Regatta;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by zwu18 on 25/04/17.
|
|
||||||
*/
|
|
||||||
public interface RegattaDataSource{
|
|
||||||
Regatta getRegatta();
|
|
||||||
}
|
|
||||||
@ -1,107 +0,0 @@
|
|||||||
package seng302.Networking;
|
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.ByteOrder;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by hba56 on 21/04/17.
|
|
||||||
*/
|
|
||||||
public class BinaryMessageDecoder {
|
|
||||||
private byte[] fullMessage;
|
|
||||||
private byte[] header;
|
|
||||||
private byte[] message;
|
|
||||||
private byte[] crc;
|
|
||||||
|
|
||||||
private byte headerSync1;
|
|
||||||
private byte headerSync2;
|
|
||||||
private byte headerMessageType;
|
|
||||||
private byte[] headerTimeStamp;
|
|
||||||
private byte[] headerSourceID;
|
|
||||||
private byte[] headerMessageLength;
|
|
||||||
|
|
||||||
|
|
||||||
public BinaryMessageDecoder(byte[] fullMessage) {
|
|
||||||
this.fullMessage = fullMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void decode() throws IndexOutOfBoundsException{
|
|
||||||
//get the header
|
|
||||||
this.header = 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 message
|
|
||||||
this.message = Arrays.copyOfRange(this.fullMessage, 15, this.fullMessage.length - 4);
|
|
||||||
|
|
||||||
//get crc
|
|
||||||
this.crc = Arrays.copyOfRange(this.fullMessage, this.fullMessage.length - 4, fullMessage.length);
|
|
||||||
|
|
||||||
//run through the checks
|
|
||||||
if (this.message.length != bytesToShort(this.headerMessageLength)){
|
|
||||||
System.err.println("message length in header does not equal the message length");
|
|
||||||
System.err.println("message length in header: " + bytesToInt(this.headerMessageLength));
|
|
||||||
System.err.println("message length: " + this.message.length);
|
|
||||||
}else if(this.headerSync1 != 0x47){
|
|
||||||
System.err.println("Sync byte 1 is wrong");
|
|
||||||
}else if(this.headerSync2 !=(byte) 0x83){
|
|
||||||
System.err.println("Sync byte 2 is wrong");
|
|
||||||
}else if(false){
|
|
||||||
//todo check crc
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private short bytesToShort(byte[] bytesShort){
|
|
||||||
ByteBuffer wrapped = ByteBuffer.wrap(bytesShort);
|
|
||||||
short num = wrapped.getShort();
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int bytesToInt(byte[] bytesInt){
|
|
||||||
ByteBuffer wrapped = ByteBuffer.wrap(bytesInt);
|
|
||||||
int num = wrapped.getInt();
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
|
|
||||||
private long bytesToLong(byte[] bytesLong){
|
|
||||||
ByteBuffer byteBuffer = ByteBuffer.allocate(8);
|
|
||||||
byteBuffer.order(ByteOrder.BIG_ENDIAN);
|
|
||||||
byteBuffer.put((byte)0);
|
|
||||||
byteBuffer.put((byte)0);
|
|
||||||
byteBuffer.put(bytesLong[0]);
|
|
||||||
byteBuffer.put(bytesLong[1]);
|
|
||||||
byteBuffer.put(bytesLong[2]);
|
|
||||||
byteBuffer.put(bytesLong[3]);
|
|
||||||
byteBuffer.put(bytesLong[4]);
|
|
||||||
byteBuffer.put(bytesLong[5]);
|
|
||||||
long longVal = byteBuffer.getLong(0);
|
|
||||||
return longVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getTimeStamp() {
|
|
||||||
return bytesToLong(this.headerTimeStamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSourceID() {
|
|
||||||
return bytesToInt(this.headerSourceID);
|
|
||||||
}
|
|
||||||
|
|
||||||
public short getMessageLength() {
|
|
||||||
return bytesToShort(this.headerMessageLength);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getMessageType(){
|
|
||||||
return (int) this.headerMessageType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getMessage() {
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
package seng302.Networking.MessageDecoders;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
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, 18);
|
|
||||||
byteBoatStatus = encodedMarkRounding[18];
|
|
||||||
byteRoundingSide = encodedMarkRounding[19];
|
|
||||||
byteMarkType = encodedMarkRounding[20];
|
|
||||||
byteMarkID = encodedMarkRounding[21];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,347 +0,0 @@
|
|||||||
package seng302.Networking.MessageEncoders;
|
|
||||||
|
|
||||||
import seng302.Model.BoatInRace;
|
|
||||||
import seng302.Networking.Utils.BoatLocationMessage;
|
|
||||||
import seng302.Networking.Utils.CourseWind;
|
|
||||||
import seng302.Networking.Utils.RaceMessage;
|
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by fwy13 on 19/04/17.
|
|
||||||
*/
|
|
||||||
public class RaceVisionByteEncoder {
|
|
||||||
|
|
||||||
public byte[] heartBeat(int seq){
|
|
||||||
ByteBuffer heartBeat = ByteBuffer.allocate(4);
|
|
||||||
heartBeat.putInt(seq);
|
|
||||||
byte [] result = heartBeat.array();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] raceStatus(long time, int race, int raceState, long startTime, short raceWindDir, short raceWindSpeed, int raceType, ArrayList<BoatInRace> boats){
|
|
||||||
ByteBuffer raceStatusMessage = ByteBuffer.allocate(24 + 20*boats.size());
|
|
||||||
//Version Number 1 bytes
|
|
||||||
byte versionNum = 0b10; //this changes with the pdf. (2)
|
|
||||||
byte[] timeBytes = convert(time, 6);//time (6 bytes)
|
|
||||||
byte[] raceID = ByteBuffer.allocate(4).putInt(race).array();//race identifier incase multiple races are going at once.
|
|
||||||
byte[] raceStatus = convert(raceState, 1);//race status 0 - 10
|
|
||||||
byte[] expectedStart = convert(startTime, 6);//number of milliseconds from Jan 1, 1970 for when the data is valid
|
|
||||||
byte[] raceWind = ByteBuffer.allocate(2).putShort(raceWindDir).array();//North = 0x0000 East = 0x4000 South = 0x8000
|
|
||||||
byte[] windSpeed = ByteBuffer.allocate(2).putShort(raceWindSpeed).array();//mm/sec
|
|
||||||
byte[] numBoats = convert(boats.size(), 1);
|
|
||||||
byte[] bytesRaceType = convert(raceType, 1);//1 match race, 2 fleet race
|
|
||||||
|
|
||||||
raceStatusMessage.put(versionNum);
|
|
||||||
raceStatusMessage.put(timeBytes);
|
|
||||||
raceStatusMessage.put(raceID);
|
|
||||||
raceStatusMessage.put(raceStatus);
|
|
||||||
raceStatusMessage.put(expectedStart);
|
|
||||||
raceStatusMessage.put(raceWind);
|
|
||||||
raceStatusMessage.put(windSpeed);
|
|
||||||
raceStatusMessage.put(numBoats);
|
|
||||||
raceStatusMessage.put(bytesRaceType);
|
|
||||||
|
|
||||||
for (int i = 0; i < boats.size(); i++){
|
|
||||||
int sourceID = 0; //TODO use boats source id.
|
|
||||||
byte[] legNum = convert(boats.get(i).getCurrentLeg().getLegNumber(), 1);
|
|
||||||
byte[] numPenalties = convert(0, 1); //TODO use boats in race penalties class
|
|
||||||
byte[] numPenaltiesServed = convert(0, 1);//TODO use boats in race penalites served.
|
|
||||||
byte[] estNextMarkTime = convert((long)0, 6);//TODO use boats estimated time to next mark.
|
|
||||||
byte[] estFinishTime = convert((long) 0, 6);//TODO use boats estimated time to the finish.
|
|
||||||
|
|
||||||
raceStatusMessage.putInt(sourceID);
|
|
||||||
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 = convert(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(convert(message[i].getLineNumber(), 1));
|
|
||||||
mess.put(convert(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(convert(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 = convert(time, 6);
|
|
||||||
byte[] ackNumber = convert(ack, 2);
|
|
||||||
byte[] raceStartTime = convert(startTime, 6);
|
|
||||||
int raceIdentifier = raceID;
|
|
||||||
byte[] notificationType = convert(notification, 1);
|
|
||||||
|
|
||||||
ByteBuffer result = ByteBuffer.allocate(20);
|
|
||||||
result.put(convert(messageVersion, 1));
|
|
||||||
result.put(timestamp);
|
|
||||||
result.put(ackNumber);
|
|
||||||
result.put(raceStartTime);
|
|
||||||
result.putInt(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 = convert(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 = convert(eventID, 1);
|
|
||||||
|
|
||||||
ByteBuffer result = ByteBuffer.allocate(22);
|
|
||||||
result.put(convert(messageVersion, 1));
|
|
||||||
result.put(encodeTime);
|
|
||||||
result.putShort(ackNum);
|
|
||||||
result.putInt(raceUID);
|
|
||||||
result.putInt(destSource);
|
|
||||||
result.putInt(incident);
|
|
||||||
result.put(event);
|
|
||||||
return result.array();
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] chatterText(int messageType, String message){
|
|
||||||
int messageVersion = 0b1;
|
|
||||||
byte[] type = convert(messageType, 1);
|
|
||||||
byte[] length = convert(message.length(), 1);
|
|
||||||
byte[] text = convert(message, length[0]);
|
|
||||||
|
|
||||||
ByteBuffer result = ByteBuffer.allocate(3 + text.length);
|
|
||||||
result.put(convert(messageVersion, 1));
|
|
||||||
result.put(type);
|
|
||||||
result.put(length);
|
|
||||||
result.put(text);
|
|
||||||
|
|
||||||
return result.array();
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] boatLocation(BoatLocationMessage boatLocationMessage){
|
|
||||||
int messageVersionNumber = 0b1;
|
|
||||||
byte[] time = convert(boatLocationMessage.getTime(), 6);
|
|
||||||
byte[] sourceID = convert(boatLocationMessage.getSourceID(), 4);
|
|
||||||
byte[] seqNum = convert(boatLocationMessage.getSequenceNumber(), 4);
|
|
||||||
byte deviceType = boatLocationMessage.getDeviceType();
|
|
||||||
byte[] latitude = convert(boatLocationMessage.getLatitude(), 4);
|
|
||||||
byte[] longitude = convert(boatLocationMessage.getLongitude(), 4);
|
|
||||||
byte[] altitude = convert(boatLocationMessage.getAltitude(), 4);
|
|
||||||
byte[] heading = convert(boatLocationMessage.getHeading(), 2);
|
|
||||||
byte[] pitch = convert(boatLocationMessage.getPitch(), 2);
|
|
||||||
byte[] roll = convert(boatLocationMessage.getRoll(), 2);
|
|
||||||
byte[] boatSpeed = convert(boatLocationMessage.getBoatSpeed(), 2);
|
|
||||||
byte[] cog = convert(boatLocationMessage.getBoatCOG(), 2);
|
|
||||||
byte[] sog = convert(boatLocationMessage.getBoatSOG(), 2);
|
|
||||||
byte[] apparentWindSpeed = convert(boatLocationMessage.getApparentWindSpeed(), 2);
|
|
||||||
byte[] apparentWindAngle = convert(boatLocationMessage.getApparentWindAngle(), 2);
|
|
||||||
byte[] trueWindSpeed = convert(boatLocationMessage.getTrueWindSpeed(), 2);
|
|
||||||
byte[] trueWindDirection = convert(boatLocationMessage.getTrueWindDirection(), 2);
|
|
||||||
byte[] trueWindAngle = convert(boatLocationMessage.getTrueWindAngle(), 2);
|
|
||||||
byte[] currentDrift = convert(boatLocationMessage.getCurrentDrift(), 2);
|
|
||||||
byte[] currentSet = convert(boatLocationMessage.getCurrentSet(), 2);
|
|
||||||
byte[] rudderAngle = convert(boatLocationMessage.getRudderAngle(), 2);
|
|
||||||
|
|
||||||
ByteBuffer result = ByteBuffer.allocate(56);
|
|
||||||
result.put(convert(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 = convert(time, 6);
|
|
||||||
byte[] byteAck = convert(ackNumber, 2);
|
|
||||||
byte[] byteRaceID = convert(raceID, 4);
|
|
||||||
byte[] byteSourceID = convert(sourceID, 4);
|
|
||||||
byte[] byteBoatStatus = convert(boatStatus, 1);
|
|
||||||
byte[] byteRoundingSide = convert(roundingSide, 1);
|
|
||||||
byte[] byteMarkType = convert(markType, 1);
|
|
||||||
byte[] byteMarkID = convert(markID, 1);
|
|
||||||
|
|
||||||
ByteBuffer result = ByteBuffer.allocate(21);
|
|
||||||
result.put(convert(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 = convert(courseWinds.size(), 1);
|
|
||||||
ByteBuffer result = ByteBuffer.allocate(3 + 20 * courseWinds.size());
|
|
||||||
result.put(convert(messageVersionNumber, 1));
|
|
||||||
result.put(byteWindID);
|
|
||||||
result.put(loopcount);
|
|
||||||
for (CourseWind wind: courseWinds){
|
|
||||||
result.put(convert(wind.getID(), 1));
|
|
||||||
result.put(convert(wind.getTime(), 6));
|
|
||||||
result.put(convert(wind.getRaceID(), 4));
|
|
||||||
result.put(convert(wind.getWindDirection(), 2));
|
|
||||||
result.put(convert(wind.getWindSpeed(), 2));
|
|
||||||
result.put(convert(wind.getBestUpwindAngle(), 2));
|
|
||||||
result.put(convert(wind.getBestDownwindAngle(), 2));
|
|
||||||
result.put(convert(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 = convert(time,6);
|
|
||||||
byte[] byteRawPeriod = convert(rawPeriod, 2);
|
|
||||||
byte[] byteRawSpeed = convert(rawSampleSpeed, 2);
|
|
||||||
byte[] bytePeriod2 = convert(period2, 2);
|
|
||||||
byte[] byteSpeed2 = convert(speed2, 2);
|
|
||||||
byte[] bytePeriod3 = convert(period3, 2);
|
|
||||||
byte[] byteSpeed3 = convert(speed3, 2);
|
|
||||||
byte[] bytePeriod4 = convert(period4, 2);
|
|
||||||
byte[] byteSpeed4 = convert(speed4, 2);
|
|
||||||
|
|
||||||
ByteBuffer result = ByteBuffer.allocate(23);
|
|
||||||
result.put(convert(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();
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] convert(String s, int size){
|
|
||||||
byte[] m = s.getBytes(Charset.forName("UTF-8"));
|
|
||||||
int length = m.length;
|
|
||||||
byte[] result;
|
|
||||||
if (length > 255){
|
|
||||||
length = 255;
|
|
||||||
} else if (size < 1){
|
|
||||||
result = new byte[0];
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
result = Arrays.copyOfRange(m, 0, length + 1);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] convert(int n, int size){
|
|
||||||
byte[] result;
|
|
||||||
if (size > 4){
|
|
||||||
result = new byte[4];
|
|
||||||
return result;
|
|
||||||
} else if (size < 1){
|
|
||||||
result = new byte[0];
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
ByteBuffer byteBuffer = ByteBuffer.allocate(4);
|
|
||||||
byteBuffer.putInt(n);
|
|
||||||
byte[] bytes = byteBuffer.array();
|
|
||||||
result = Arrays.copyOfRange(bytes, 4 - size, 4);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] convert(long n, int size){
|
|
||||||
byte[] result;
|
|
||||||
if (size > 8){
|
|
||||||
result = new byte[8];
|
|
||||||
return result;
|
|
||||||
} else if (size < 1){
|
|
||||||
result = new byte[0];
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
ByteBuffer byteBuffer = ByteBuffer.allocate(8);
|
|
||||||
byteBuffer.putLong(n);
|
|
||||||
byte[] bytes = byteBuffer.array();
|
|
||||||
result = Arrays.copyOfRange(bytes, 8 - size, 8);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public byte[] convert(short n, int size){
|
|
||||||
byte[] result;
|
|
||||||
if (size > 2){
|
|
||||||
result = new byte[2];
|
|
||||||
return result;
|
|
||||||
} else if (size < 1){
|
|
||||||
result = new byte[0];
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
ByteBuffer byteBuffer = ByteBuffer.allocate(2);
|
|
||||||
byteBuffer.putShort(n);
|
|
||||||
byte[] bytes = byteBuffer.array();
|
|
||||||
result = Arrays.copyOfRange(bytes, 2 - size, 2);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,77 +0,0 @@
|
|||||||
package seng302.Networking.MessageEncoders;
|
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.ByteOrder;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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(byte messageVersionNumber, short ackNumber, long timeStamp, byte xmlMsgSubType, short sequenceNumber, short xmlMsgLenght, String xmlMessage) {
|
|
||||||
this.messageVersionNumber = messageVersionNumber;
|
|
||||||
this.ackNumber = ackNumber;
|
|
||||||
this.timeStamp = timeStamp;
|
|
||||||
this.xmlMsgSubType = xmlMsgSubType;
|
|
||||||
this.sequenceNumber = sequenceNumber;
|
|
||||||
this.xmlMsgLength = xmlMsgLenght;
|
|
||||||
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 = new byte[2];
|
|
||||||
ackNumberBytes[0] = (byte) (ackNumber & 0xff);
|
|
||||||
ackNumberBytes[1] = (byte) ((ackNumber >> 8) & 0xff);
|
|
||||||
|
|
||||||
//sequenceNumber converted to bytes
|
|
||||||
byte[] sequenceNumberBytes = new byte[2];
|
|
||||||
sequenceNumberBytes[0] = (byte) (sequenceNumber & 0xff);
|
|
||||||
sequenceNumberBytes[1] = (byte) ((sequenceNumber >> 8) & 0xff);
|
|
||||||
|
|
||||||
//xmlMsgLength converted to bytes
|
|
||||||
byte[] xmlMsgLengthBytes = new byte[2];
|
|
||||||
xmlMsgLengthBytes[0] = (byte) (xmlMsgLength & 0xff);
|
|
||||||
xmlMsgLengthBytes[1] = (byte) ((xmlMsgLength >> 8) & 0xff);
|
|
||||||
|
|
||||||
|
|
||||||
tempOutputByteBuffer.put(messageVersionNumber);
|
|
||||||
tempOutputByteBuffer.put(ackNumberBytes);
|
|
||||||
tempOutputByteBuffer.put(longToSixBytes(timeStamp));
|
|
||||||
tempOutputByteBuffer.put(xmlMsgSubType);
|
|
||||||
tempOutputByteBuffer.put(sequenceNumberBytes);
|
|
||||||
tempOutputByteBuffer.put(xmlMsgLengthBytes);
|
|
||||||
tempOutputByteBuffer.put(messageBytes);
|
|
||||||
|
|
||||||
return tempOutputByteBuffer.array();
|
|
||||||
}
|
|
||||||
|
|
||||||
private byte[] longToSixBytes(long x) {
|
|
||||||
ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
|
|
||||||
buffer.putLong(x);
|
|
||||||
|
|
||||||
// System.out.println("====encode====");
|
|
||||||
// for (byte i:buffer.array()
|
|
||||||
// ) {
|
|
||||||
// System.out.println(i);
|
|
||||||
// }
|
|
||||||
// System.out.println("====encode====");
|
|
||||||
|
|
||||||
return Arrays.copyOfRange(buffer.array(), 2, 8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,357 +0,0 @@
|
|||||||
package seng302.Networking.Utils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by f123 on 21-Apr-17.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the information in a boat location message (AC streaming spec: 4.9).
|
|
||||||
*/
|
|
||||||
public class BoatLocationMessage
|
|
||||||
{
|
|
||||||
///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 int 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;
|
|
||||||
|
|
||||||
private short 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.
|
|
||||||
*/
|
|
||||||
public BoatLocationMessage()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ctor, with all parameters.
|
|
||||||
* @param messageVersionNumber
|
|
||||||
* @param time
|
|
||||||
* @param sourceID
|
|
||||||
* @param sequenceNumber
|
|
||||||
* @param deviceType
|
|
||||||
* @param latitude
|
|
||||||
* @param longitude
|
|
||||||
* @param altitude
|
|
||||||
* @param heading
|
|
||||||
* @param pitch
|
|
||||||
* @param roll
|
|
||||||
* @param boatSpeed
|
|
||||||
* @param boatCOG
|
|
||||||
* @param boatSOG
|
|
||||||
* @param apparentWindSpeed
|
|
||||||
* @param apparentWindAngle
|
|
||||||
* @param trueWindSpeed
|
|
||||||
* @param trueWindDirection
|
|
||||||
* @param trueWindAngle
|
|
||||||
* @param currentDrift
|
|
||||||
* @param currentSet
|
|
||||||
* @param rudderAngle
|
|
||||||
*/
|
|
||||||
public BoatLocationMessage(byte messageVersionNumber, long time, int sourceID, int 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, short trueWindDirection, short trueWindAngle, int currentDrift, int currentSet, short rudderAngle)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//Getters and setters for message properties.
|
|
||||||
|
|
||||||
|
|
||||||
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 int getSequenceNumber()
|
|
||||||
{
|
|
||||||
return sequenceNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSequenceNumber(int 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 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 short getTrueWindDirection() {
|
|
||||||
return trueWindDirection;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTrueWindDirection(short 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,18 +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);
|
|
||||||
|
|
||||||
private byte value;
|
|
||||||
|
|
||||||
private MessageType(int value) { this.value = (byte)value; }
|
|
||||||
|
|
||||||
public byte getValue() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,87 @@
|
|||||||
|
package seng302.Data;
|
||||||
|
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
import seng302.DataInput.RaceDataSource;
|
||||||
|
import seng302.DataInput.RaceXMLReader;
|
||||||
|
|
||||||
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static junit.framework.TestCase.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by esa46 on 25/04/17.
|
||||||
|
*/
|
||||||
|
public class BoatDataTest {
|
||||||
|
|
||||||
|
|
||||||
|
private static final String ROOT_TAG = "BoatConfig";
|
||||||
|
private static final String[] REQUIRED_TAGS = new String[]{
|
||||||
|
"Boats", "GPSposition"
|
||||||
|
};
|
||||||
|
private static final String[] REQUIRED_ATTRIBUTES = new String[]{
|
||||||
|
"SourceID", "ShapeID", "HullNum", "StoweName",
|
||||||
|
"ShortName", "BoatName"
|
||||||
|
};
|
||||||
|
|
||||||
|
String result;
|
||||||
|
RaceDataSource raceDataSource;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void initReader() {
|
||||||
|
try {
|
||||||
|
raceDataSource = new RaceXMLReader("raceXML/bermuda_AC35.xml");
|
||||||
|
BoatData boatData = new BoatData(raceDataSource.getBoats());
|
||||||
|
result = boatData.createXML();
|
||||||
|
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (SAXException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (ParserConfigurationException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void xmlHasAllNecessaryTags() {
|
||||||
|
|
||||||
|
assertTrue(result.contains("<" + ROOT_TAG + ">"));
|
||||||
|
for (String tag : REQUIRED_TAGS) {
|
||||||
|
assertTrue(result.contains("<" + tag + ">") || result.contains("<" + tag + " "));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void xmlHasAllNecessaryAttributes() {
|
||||||
|
|
||||||
|
for (String attribute : REQUIRED_ATTRIBUTES) {
|
||||||
|
assertTrue(result.contains(attribute + "="));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void allTagsAreTerminated() {
|
||||||
|
|
||||||
|
for (String tag : REQUIRED_TAGS) {
|
||||||
|
int lastIndex = 0;
|
||||||
|
String openTag = "<" + tag + ">";
|
||||||
|
String closeTag = "</" + tag + ">";
|
||||||
|
while (lastIndex < result.length() && lastIndex > 0) {
|
||||||
|
lastIndex = result.indexOf(openTag, lastIndex);
|
||||||
|
if (lastIndex > 0) {
|
||||||
|
|
||||||
|
lastIndex = result.indexOf(closeTag, lastIndex);
|
||||||
|
assertTrue(lastIndex > 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,74 @@
|
|||||||
|
package seng302.Data;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.xml.sax.SAXException;
|
||||||
|
import seng302.DataInput.RaceDataSource;
|
||||||
|
import seng302.DataInput.RaceXMLReader;
|
||||||
|
import seng302.DataInput.RegattaDataSource;
|
||||||
|
import seng302.DataInput.RegattaXMLReader;
|
||||||
|
|
||||||
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static junit.framework.TestCase.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by esa46 on 25/04/17.
|
||||||
|
*/
|
||||||
|
public class RegattaDataTest {
|
||||||
|
|
||||||
|
private static final String ROOT_TAG = "RegattaConfig";
|
||||||
|
private static final String[] REQUIRED_TAGS = new String[]{
|
||||||
|
"RegattaID", "RegattaName", "CourseName", "CentralLatitude", "CentralLongitude",
|
||||||
|
"CentralAltitude", "UtcOffset", "MagneticVariation"
|
||||||
|
};
|
||||||
|
String result;
|
||||||
|
RegattaDataSource regattaDataSource;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void initReader() {
|
||||||
|
try {
|
||||||
|
regattaDataSource = new RegattaXMLReader("mockXML/regattaTest.xml");
|
||||||
|
RegattaData regattaData = new RegattaData(regattaDataSource);
|
||||||
|
result = regattaData.createXML();
|
||||||
|
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (SAXException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (ParserConfigurationException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void xmlHasAllNecessaryFields() {
|
||||||
|
|
||||||
|
assertTrue(result.contains("<" + ROOT_TAG + ">"));
|
||||||
|
for (String tag : REQUIRED_TAGS) {
|
||||||
|
System.out.println(tag);
|
||||||
|
assertTrue(result.contains("<" + tag + ">") || result.contains("<" + tag + " "));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void allTagsAreTerminated() {
|
||||||
|
|
||||||
|
for (String tag : REQUIRED_TAGS) {
|
||||||
|
int lastIndex = 0;
|
||||||
|
String openTag = "<" + tag + ">";
|
||||||
|
String closeTag = "</" + tag + ">";
|
||||||
|
while (lastIndex < result.length() && lastIndex > 0) {
|
||||||
|
lastIndex = result.indexOf(openTag, lastIndex);
|
||||||
|
if (lastIndex > 0) {
|
||||||
|
|
||||||
|
lastIndex = result.indexOf(closeTag, lastIndex);
|
||||||
|
assertTrue(lastIndex > 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,50 +0,0 @@
|
|||||||
package seng302.Networking.MessageDecoders;
|
|
||||||
|
|
||||||
import javafx.scene.paint.Color;
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Test;
|
|
||||||
import seng302.Model.BoatInRace;
|
|
||||||
import seng302.Model.Leg;
|
|
||||||
import seng302.Networking.MessageDecoders.RaceStatusDecoder;
|
|
||||||
import seng302.Networking.MessageEncoders.RaceVisionByteEncoder;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by hba56 on 23/04/17.
|
|
||||||
*/
|
|
||||||
public class RaceStatusDecoderTest {
|
|
||||||
@Test
|
|
||||||
public void getByteArrayTest(){
|
|
||||||
long time = System.currentTimeMillis();
|
|
||||||
BoatInRace boat1 = new BoatInRace("Test", 1, Color.ALICEBLUE, "tt", 1);
|
|
||||||
Leg testLeg = new Leg("test leg", 1);
|
|
||||||
boat1.setCurrentLeg(testLeg);
|
|
||||||
BoatInRace boat2 = new BoatInRace("Test2", 1, Color.ALICEBLUE, "tt", 1);
|
|
||||||
boat2.setCurrentLeg(testLeg);
|
|
||||||
ArrayList boats = new ArrayList();
|
|
||||||
boats.add(boat1);
|
|
||||||
boats.add(boat2);
|
|
||||||
long time2 = System.currentTimeMillis();
|
|
||||||
|
|
||||||
RaceVisionByteEncoder raceVisionByteEncoder = new RaceVisionByteEncoder();
|
|
||||||
|
|
||||||
byte[] encodedRaceStatus = raceVisionByteEncoder.raceStatus(time, 1, 2, time2,
|
|
||||||
(short)2, (short)3,4, boats);
|
|
||||||
|
|
||||||
RaceStatusDecoder decoderTest = new RaceStatusDecoder(encodedRaceStatus);
|
|
||||||
|
|
||||||
Assert.assertEquals(0b10, decoderTest.getVersionNum());
|
|
||||||
Assert.assertEquals(time, decoderTest.getTime());
|
|
||||||
Assert.assertEquals(1, decoderTest.getRace());
|
|
||||||
Assert.assertEquals(2, decoderTest.getRaceState());
|
|
||||||
Assert.assertEquals(time2, decoderTest.getStartTime());
|
|
||||||
Assert.assertEquals((short)2, decoderTest.getRaceWindDir());
|
|
||||||
Assert.assertEquals((short)3, decoderTest.getRaceWindSpeed());
|
|
||||||
|
|
||||||
Assert.assertEquals(0, decoderTest.getBoats().get(0).getBoatStatus());
|
|
||||||
Assert.assertEquals(0, decoderTest.getBoats().get(0).getLegNumber());
|
|
||||||
Assert.assertEquals(0, decoderTest.getBoats().get(0).getNumPenaltiesAwarded());
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,146 @@
|
|||||||
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>seng302</groupId>
|
||||||
|
<artifactId>team-7</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<name>network</name>
|
||||||
|
<artifactId>network</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>seng302</groupId>
|
||||||
|
<artifactId>sharedModel</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>4.12</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-all -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mockito</groupId>
|
||||||
|
<artifactId>mockito-all</artifactId>
|
||||||
|
<version>1.9.5</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.testng</groupId>
|
||||||
|
<artifactId>testng</artifactId>
|
||||||
|
<version>6.11</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>maven2-repository.dev.java.net</id>
|
||||||
|
<name>Java.net repository</name>
|
||||||
|
<url>http://download.java.net/maven/2</url>
|
||||||
|
</repository>
|
||||||
|
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.5.1</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
<version>2.4.3</version>
|
||||||
|
<configuration>
|
||||||
|
<transformers>
|
||||||
|
<transformer
|
||||||
|
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||||
|
<manifestEntries>
|
||||||
|
<Main-Class>seng302.App</Main-Class>
|
||||||
|
<X-Compile-Source-JDK>${maven.compiler.source}</X-Compile-Source-JDK>
|
||||||
|
<X-Compile-Target-JDK>${maven.compiler.target}</X-Compile-Target-JDK>
|
||||||
|
</manifestEntries>
|
||||||
|
</transformer>
|
||||||
|
</transformers>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>shade</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
<reporting>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jxr-plugin</artifactId>
|
||||||
|
<version>2.5</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-pmd-plugin</artifactId>
|
||||||
|
<version>3.6</version>
|
||||||
|
<configuration>
|
||||||
|
<linkXRef>true</linkXRef>
|
||||||
|
<targetJdk>${maven.compiler.target}</targetJdk>
|
||||||
|
<rulesets>
|
||||||
|
<ruleset>/rulesets/java/basic.xml</ruleset>
|
||||||
|
<ruleset>/rulesets/java/imports.xml</ruleset>
|
||||||
|
<ruleset>/rulesets/java/codesize.xml</ruleset>
|
||||||
|
<ruleset>/rulesets/java/design.xml</ruleset>
|
||||||
|
<ruleset>/rulesets/java/empty.xml</ruleset>
|
||||||
|
<ruleset>/rulesets/java/junit.xml</ruleset>
|
||||||
|
<ruleset>/rulesets/java/unusedcode.xml</ruleset>
|
||||||
|
</rulesets>
|
||||||
|
<includeXmlInSite>true</includeXmlInSite>
|
||||||
|
<sourceEncoding>utf-8</sourceEncoding>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
|
<version>2.10.3</version>
|
||||||
|
<configuration>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-report-plugin</artifactId>
|
||||||
|
<version>2.19.1</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-project-info-reports-plugin</artifactId>
|
||||||
|
<version>2.8.1</version>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</reporting>
|
||||||
|
</project>
|
||||||
@ -0,0 +1,165 @@
|
|||||||
|
package seng302.Networking;
|
||||||
|
|
||||||
|
import seng302.Networking.MessageDecoders.*;
|
||||||
|
import seng302.Networking.Utils.*;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
private byte headerSync1;
|
||||||
|
private byte headerSync2;
|
||||||
|
private byte headerMessageType;
|
||||||
|
private byte[] headerTimeStamp;
|
||||||
|
private byte[] headerSourceID;
|
||||||
|
private byte[] headerMessageLength;
|
||||||
|
|
||||||
|
|
||||||
|
public BinaryMessageDecoder(byte[] fullMessage) {
|
||||||
|
this.fullMessage = fullMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AC35Data decode() throws IndexOutOfBoundsException{
|
||||||
|
//get the header
|
||||||
|
this.header = 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);
|
||||||
|
|
||||||
|
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 crc
|
||||||
|
this.crc = Arrays.copyOfRange(this.fullMessage, this.fullMessage.length - 4, fullMessage.length);
|
||||||
|
|
||||||
|
|
||||||
|
CRC32 crc = new CRC32();
|
||||||
|
crc.reset();
|
||||||
|
crc.update(this.fullMessage);
|
||||||
|
|
||||||
|
//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() != 0){
|
||||||
|
//todo check crc
|
||||||
|
System.err.println("CRC is not 0 and is instead:" + crc.getValue());
|
||||||
|
return;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
MessageType mType = MessageType.valueOf(this.headerMessageType);
|
||||||
|
AC35Data data = null;
|
||||||
|
|
||||||
|
switch(mType){
|
||||||
|
case HEARTBEAT:
|
||||||
|
// System.out.println("HeartBeat Message!");
|
||||||
|
data = new Heartbeat();
|
||||||
|
break;
|
||||||
|
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;
|
||||||
|
case DISPLAYTEXTMESSAGE:
|
||||||
|
// System.out.println("Display Text Message");
|
||||||
|
//no decoder for this.
|
||||||
|
break;
|
||||||
|
case XMLMESSAGE:
|
||||||
|
// System.out.println("XML Message!");
|
||||||
|
XMLMessageDecoder xmdecoder = new XMLMessageDecoder(this.message);
|
||||||
|
xmdecoder.decode();
|
||||||
|
data = new XMLMessage(xmdecoder.getAckNumber(), xmdecoder.getTimeStamp(), xmdecoder.getXmlMsgSubType(), xmdecoder.getSequenceNumber(), xmdecoder.getXmlMsgLength(), xmdecoder.getXmlMessageInputSource());
|
||||||
|
break;
|
||||||
|
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;
|
||||||
|
case YACHTEVENTCODE:
|
||||||
|
// System.out.println("Yacht Action Code!");
|
||||||
|
//no decoder
|
||||||
|
break;
|
||||||
|
case YACHTACTIONCODE:
|
||||||
|
// System.out.println("Yacht Action Code!");
|
||||||
|
//no decoder
|
||||||
|
break;
|
||||||
|
case CHATTERTEXT:
|
||||||
|
// System.out.println("Chatter Text Message!");
|
||||||
|
//no decoder
|
||||||
|
break;
|
||||||
|
case BOATLOCATION:
|
||||||
|
// System.out.println("Boat Location Message!");
|
||||||
|
BoatLocationDecoder blDecoder = new BoatLocationDecoder(this.message);
|
||||||
|
data = blDecoder.getMessage();
|
||||||
|
break;
|
||||||
|
case MARKROUNDING:
|
||||||
|
// System.out.println("Mark Rounding Message!");
|
||||||
|
MarkRoundingDecoder mrDecoder = new MarkRoundingDecoder(this.message);
|
||||||
|
data = mrDecoder.getMarkRounding();
|
||||||
|
break;
|
||||||
|
case COURSEWIND:
|
||||||
|
// System.out.println("Couse Wind Message!");
|
||||||
|
CourseWindDecoder cwDecoder = new CourseWindDecoder(this.message);
|
||||||
|
data =new CourseWinds(cwDecoder.getMessageVersionNumber(), cwDecoder.getByteWindID(), cwDecoder.getLoopMessages());
|
||||||
|
break;
|
||||||
|
case AVGWIND:
|
||||||
|
// System.out.println("Average Wind Message!");
|
||||||
|
AverageWindDecoder awDecoder = new AverageWindDecoder(this.message);
|
||||||
|
data = awDecoder.getAverageWind();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// System.out.println("Broken Message!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public long getTimeStamp() {
|
||||||
|
return ByteConverter.bytesToLong(this.headerTimeStamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSourceID() {
|
||||||
|
return ByteConverter.bytesToInt(this.headerSourceID, ByteOrder.BIG_ENDIAN);
|
||||||
|
}
|
||||||
|
|
||||||
|
public short getMessageLength() {
|
||||||
|
return ByteConverter.bytesToShort(this.headerMessageLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMessageType(){
|
||||||
|
return (int) this.headerMessageType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@ -0,0 +1,51 @@
|
|||||||
|
package seng302.Networking.MessageDecoders;
|
||||||
|
|
||||||
|
import seng302.Networking.Utils.ByteConverter;
|
||||||
|
import seng302.Networking.Utils.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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,299 @@
|
|||||||
|
package seng302.Networking.MessageEncoders;
|
||||||
|
|
||||||
|
|
||||||
|
import seng302.Networking.Utils.*;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
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){
|
||||||
|
|
||||||
|
ArrayList<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(BoatLocationMessage boatLocationMessage){
|
||||||
|
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);
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,62 @@
|
|||||||
|
package seng302.Networking.MessageEncoders;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,134 @@
|
|||||||
|
package seng302.Networking;
|
||||||
|
import seng302.Networking.MessageEncoders.RaceVisionByteEncoder;
|
||||||
|
import seng302.Networking.MessageEncoders.XMLMessageEncoder;
|
||||||
|
import seng302.Networking.Utils.BoatLocationMessage;
|
||||||
|
import seng302.Networking.Utils.MessageType;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TCP client to recive information from AC35 data source
|
||||||
|
*/
|
||||||
|
public class MockOutput
|
||||||
|
{
|
||||||
|
private long lastHeartbeatTime;
|
||||||
|
|
||||||
|
private RaceVisionByteEncoder messageEncoder = new RaceVisionByteEncoder();
|
||||||
|
|
||||||
|
//socket port 4942 as 4940 is ac35 live port and 4941 is ac35 test port
|
||||||
|
private Socket mockSocket;
|
||||||
|
private DataOutputStream outToVisualiser;
|
||||||
|
|
||||||
|
//a buffer that contains items that are waiting to be sent
|
||||||
|
private ArrayList<byte[]> messagesToSendBuffer = new ArrayList<>();
|
||||||
|
|
||||||
|
private short messageNumber = 1;
|
||||||
|
|
||||||
|
private short xmlSequenceNumber = 1;
|
||||||
|
private int heartbeatSequenceNum = 1;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
MockOutput() throws IOException{
|
||||||
|
/*******************************Test********************************/
|
||||||
|
StringBuilder xmlString;
|
||||||
|
|
||||||
|
BufferedReader br = new BufferedReader(new InputStreamReader(
|
||||||
|
this.getClass().getResourceAsStream(("/raceXML/Regatta.xml"))));
|
||||||
|
|
||||||
|
String line;
|
||||||
|
xmlString = new StringBuilder();
|
||||||
|
while((line=br.readLine())!= null){
|
||||||
|
xmlString.append(line.trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
parseXMLString(xmlString.toString(), 5);
|
||||||
|
|
||||||
|
/*******************************Test********************************/
|
||||||
|
|
||||||
|
/**************sockets*******************/
|
||||||
|
//start Time
|
||||||
|
lastHeartbeatTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
|
||||||
|
mockSocket = new Socket("localhost", 4942);
|
||||||
|
outToVisualiser = new DataOutputStream(mockSocket.getOutputStream());
|
||||||
|
|
||||||
|
|
||||||
|
//loop that sends
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
//sends a heartbeat every 5 seconds
|
||||||
|
if (timeSinceHeartbeat() >= 5.00){
|
||||||
|
outToVisualiser.write(heartbeat());
|
||||||
|
lastHeartbeatTime = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
//checks the buffer to see if there is anything to send
|
||||||
|
if (messagesToSendBuffer.size() > 0) {
|
||||||
|
for (byte[] binaryMessage : messagesToSendBuffer) {
|
||||||
|
//sends the message to the visualiser
|
||||||
|
outToVisualiser.write(binaryMessage);
|
||||||
|
}
|
||||||
|
//cleans out buffer
|
||||||
|
messagesToSendBuffer.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**************sockets*******************/
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* calculates the time since last heartbeat
|
||||||
|
* @return time since last heartbeat
|
||||||
|
*/
|
||||||
|
private double timeSinceHeartbeat() {
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
return (now - lastHeartbeatTime) / 1000.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//returns the heartbeat message
|
||||||
|
private byte[] heartbeat(){
|
||||||
|
byte[] heartbeatMessage = messageEncoder.heartBeat(heartbeatSequenceNum);
|
||||||
|
heartbeatSequenceNum++;
|
||||||
|
BinaryMesageEncoder binaryMesageEncoder = new BinaryMesageEncoder(MessageType.HEARTBEAT, System.currentTimeMillis(), messageNumber, (short)heartbeatMessage.length, heartbeatMessage);
|
||||||
|
messageNumber++;
|
||||||
|
return binaryMesageEncoder.getFullMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to give the mockOutput an xml string to be made into a message and sent
|
||||||
|
* @param xmlString the xml string to send
|
||||||
|
* @param messageType the kind of xml string, values given in AC35 spec (5 regatta, 6 race, 7 boat)
|
||||||
|
*/
|
||||||
|
public void parseXMLString(String xmlString, int messageType){
|
||||||
|
XMLMessageEncoder encoder = new XMLMessageEncoder(messageNumber, System.currentTimeMillis(), messageType, xmlSequenceNumber,(short) xmlString.length(), xmlString);
|
||||||
|
//iterates the sequence numbers
|
||||||
|
xmlSequenceNumber++;
|
||||||
|
byte[] encodedXML = encoder.encode();
|
||||||
|
|
||||||
|
BinaryMesageEncoder binaryMesageEncoder = new BinaryMesageEncoder(MessageType.XMLMESSAGE, System.currentTimeMillis(), messageNumber, (short)encodedXML.length, encodedXML);
|
||||||
|
//iterates the message number
|
||||||
|
messageNumber++;
|
||||||
|
|
||||||
|
addMessageToBufferToSend(binaryMesageEncoder.getFullMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to give the mocOutput information about boat location to be made into a message and sent
|
||||||
|
*/
|
||||||
|
public void parseBoatLocation(){
|
||||||
|
/// TODO: 26/04/17
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addMessageToBufferToSend(byte[] messagesToSendBuffer) {
|
||||||
|
this.messagesToSendBuffer.add(messagesToSendBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String argv[]) throws Exception
|
||||||
|
{
|
||||||
|
MockOutput client = new MockOutput();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,67 @@
|
|||||||
|
package seng302.Networking.PacketDump;
|
||||||
|
|
||||||
|
import seng302.Networking.BinaryMesageEncoder;
|
||||||
|
import seng302.Networking.BinaryMessageDecoder;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
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<>();
|
||||||
|
|
||||||
|
System.out.println(dump.length);
|
||||||
|
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());
|
||||||
|
decoder.decode();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args){
|
||||||
|
try {
|
||||||
|
AC35DumpReader ac35DumpReader = new AC35DumpReader("dataDumps/ac35.bin");
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,15 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
package seng302.Networking.Utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,253 @@
|
|||||||
|
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
|
||||||
|
//////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public static int bytesToInt(byte bite){
|
||||||
|
byte[] bytes = {bite};
|
||||||
|
return bytesToInt(bytes, ByteOrder.LITTLE_ENDIAN);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int bytesToInt(byte[] bytes){
|
||||||
|
return bytesToInt(bytes, ByteOrder.LITTLE_ENDIAN);
|
||||||
|
}
|
||||||
|
|
||||||
|
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++) {
|
||||||
|
bites[i] = bytes[i];
|
||||||
|
if (i > maxSize){//break if over hte limit
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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++) {
|
||||||
|
bites[i] = bytes[i - maxSize + bytes.length];
|
||||||
|
if (i > maxSize){//break if over the limit
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,21 @@
|
|||||||
|
package seng302.Networking.Utils;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
package seng302.Networking.Utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by fwy13 on 25/04/17.
|
||||||
|
*/
|
||||||
|
public class Heartbeat extends AC35Data{
|
||||||
|
|
||||||
|
public Heartbeat(){
|
||||||
|
super(MessageType.HEARTBEAT);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,52 @@
|
|||||||
|
package seng302.Networking.Utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,49 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package seng302.Networking.Utils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,72 @@
|
|||||||
|
package seng302.Networking.Utils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 ArrayList<BoatStatus> boatStatuses;
|
||||||
|
|
||||||
|
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;
|
||||||
|
this.raceStatus = raceStatus;
|
||||||
|
this.expectedStartTime = expectedStartTime;
|
||||||
|
this.windDirection = windDirection;
|
||||||
|
this.windSpeed = windSpeed;
|
||||||
|
this.raceType = raceType;
|
||||||
|
this.boatStatuses = boatStatuses;//note this is a copy so any alterations to the parent will affect this.
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///Getters.
|
||||||
|
|
||||||
|
public long getCurrentTime()
|
||||||
|
{
|
||||||
|
return currentTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRaceID()
|
||||||
|
{
|
||||||
|
return raceID;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 ArrayList<BoatStatus> getBoatStatuses()
|
||||||
|
{
|
||||||
|
return boatStatuses;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
package seng302.Networking.Utils;
|
||||||
|
|
||||||
|
import org.xml.sax.InputSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 InputSource xmlMessage;
|
||||||
|
|
||||||
|
public static int XMLTypeRegatta = 5;
|
||||||
|
public static int XMLTypeRace = 6;
|
||||||
|
public static int XMLTypeBoat = 7;
|
||||||
|
|
||||||
|
public XMLMessage(int ackNumber, long timeStamp, int xmlMsgSubType, int sequenceNumber, int xmlMsgLength, InputSource xmlMessage){
|
||||||
|
super(MessageType.XMLMESSAGE);
|
||||||
|
this.ackNumber = ackNumber;
|
||||||
|
this.timeStamp = timeStamp;
|
||||||
|
this.xmlMsgSubType = xmlMsgSubType;
|
||||||
|
this.sequenceNumber = sequenceNumber;
|
||||||
|
this.xmlMsgLength = xmlMsgLength;
|
||||||
|
this.xmlMessage = xmlMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,157 @@
|
|||||||
|
package seng302.Networking;
|
||||||
|
import seng302.Networking.BinaryMessageDecoder;
|
||||||
|
import seng302.Networking.MessageDecoders.*;
|
||||||
|
import seng302.Networking.Utils.*;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.*;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import static seng302.Networking.Utils.ByteConverter.bytesToInt;
|
||||||
|
import static seng302.Networking.Utils.ByteConverter.bytesToShort;
|
||||||
|
import static seng302.Networking.Utils.MessageType.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TCP server to act as the mock AC35 streaming interface
|
||||||
|
*/
|
||||||
|
public class VisualiserInput
|
||||||
|
{
|
||||||
|
//time since last heartbeat
|
||||||
|
private long lastHeartbeatTime;
|
||||||
|
|
||||||
|
//socket port 4942 as 4940 is ac35 live port and 4941 is ac35 test port
|
||||||
|
private ServerSocket visualiserSocket;
|
||||||
|
private Socket connectionSocket;
|
||||||
|
|
||||||
|
long heartbeatSeqNum;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
VisualiserInput() throws IOException{
|
||||||
|
|
||||||
|
//sockets to connect to
|
||||||
|
// ServerSocket visualiserSocket = new ServerSocket(4942);
|
||||||
|
// Socket connectionSocket = visualiserSocket.accept();
|
||||||
|
|
||||||
|
//this is the test data that streams form the AC35 website
|
||||||
|
Socket connectionSocket = new Socket("livedata.americascup.com",4941);
|
||||||
|
|
||||||
|
|
||||||
|
//start Time
|
||||||
|
lastHeartbeatTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
|
||||||
|
//receiver loop that gets the input
|
||||||
|
boolean receiverLoop = true;
|
||||||
|
while(receiverLoop) {
|
||||||
|
//gets the input from the socket
|
||||||
|
InputStream inFromClient = connectionSocket.getInputStream();
|
||||||
|
|
||||||
|
//converts the input into a byte array that can be read by the decoder
|
||||||
|
byte[] binaryMessage = getBytes(inFromClient);
|
||||||
|
|
||||||
|
//decode the binary message into readable date
|
||||||
|
BinaryMessageDecoder testDecoder = new BinaryMessageDecoder(binaryMessage);
|
||||||
|
testDecoder.decode();
|
||||||
|
|
||||||
|
//checks which message is being received and does what is needed for that message
|
||||||
|
MessageType mType = MessageType.valueOf((byte) testDecoder.getMessageType());
|
||||||
|
switch (mType) {
|
||||||
|
case HEARTBEAT:
|
||||||
|
lastHeartbeatTime = System.currentTimeMillis();
|
||||||
|
//note: if the program runs for over 340 years, this will crash.
|
||||||
|
heartbeatSeqNum = ByteConverter.bytesToLong(testDecoder.getMessage());
|
||||||
|
System.out.println("HeartBeat Message! " + heartbeatSeqNum);
|
||||||
|
break;
|
||||||
|
case RACESTATUS:
|
||||||
|
// System.out.println("Race Status Message");
|
||||||
|
break;
|
||||||
|
case DISPLAYTEXTMESSAGE:
|
||||||
|
// System.out.println("Display Text Message");
|
||||||
|
//no decoder for this.
|
||||||
|
break;
|
||||||
|
case XMLMESSAGE:
|
||||||
|
// System.out.println("XML Message!");
|
||||||
|
XMLMessageDecoder xmlMessageDecoder = new XMLMessageDecoder(testDecoder.getMessage());
|
||||||
|
xmlMessageDecoder.decode();
|
||||||
|
System.out.println(xmlMessageDecoder.getXmlMessageInputSource());
|
||||||
|
break;
|
||||||
|
case RACESTARTSTATUS:
|
||||||
|
// System.out.println("Race Start Status Message");
|
||||||
|
break;
|
||||||
|
case YACHTEVENTCODE:
|
||||||
|
// System.out.println("Yacht Action Code!");
|
||||||
|
//no decoder
|
||||||
|
break;
|
||||||
|
case YACHTACTIONCODE:
|
||||||
|
// System.out.println("Yacht Action Code!");
|
||||||
|
//no decoder
|
||||||
|
break;
|
||||||
|
case CHATTERTEXT:
|
||||||
|
// System.out.println("Chatter Text Message!");
|
||||||
|
//no decoder
|
||||||
|
break;
|
||||||
|
case BOATLOCATION:
|
||||||
|
// System.out.println("Boat Location Message!");
|
||||||
|
break;
|
||||||
|
case MARKROUNDING:
|
||||||
|
// System.out.println("Mark Rounding Message!");
|
||||||
|
break;
|
||||||
|
case COURSEWIND:
|
||||||
|
// System.out.println("Course Wind Message!");
|
||||||
|
break;
|
||||||
|
case AVGWIND:
|
||||||
|
// System.out.println("Average Wind Message!");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// System.out.println("Broken Message!");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//if no heartbeat has been received in more than 6 seconds
|
||||||
|
//the connection will need to be restarted
|
||||||
|
if (timeSinceHeartbeat() > 6){
|
||||||
|
System.out.println("Connection has stopped, trying to reconnect");
|
||||||
|
receiverLoop = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* calculates the time since last heartbeat
|
||||||
|
* @return time since last heartbeat
|
||||||
|
*/
|
||||||
|
private double timeSinceHeartbeat() {
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
return (now - lastHeartbeatTime) / 1000.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes an inputStream and reads the first 15 bytes (the header) and gets the message length
|
||||||
|
* for the whole message then reads that and returns the byte array
|
||||||
|
* @param inStream inputStream from socket
|
||||||
|
* @return encoded binary messsage bytes
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private static byte[] getBytes(InputStream inStream) throws IOException {
|
||||||
|
byte[] headerBytes = new byte[15];
|
||||||
|
int i = inStream.read(headerBytes);
|
||||||
|
byte[] messageLenBytes = Arrays.copyOfRange(headerBytes, 13, 15);
|
||||||
|
short messageLen = bytesToShort(messageLenBytes);
|
||||||
|
byte[] messageBytesWithCRC = new byte[messageLen+4];
|
||||||
|
int j = inStream.read(messageBytesWithCRC);
|
||||||
|
ByteBuffer binaryMessageBytes = ByteBuffer.allocate(headerBytes.length+messageBytesWithCRC.length);
|
||||||
|
binaryMessageBytes.put(headerBytes);
|
||||||
|
binaryMessageBytes.put(messageBytesWithCRC);
|
||||||
|
return binaryMessageBytes.array();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String argv[]) throws Exception
|
||||||
|
{
|
||||||
|
VisualiserInput reciever = new VisualiserInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Binary file not shown.
@ -0,0 +1,119 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<BoatConfig>
|
||||||
|
<Modified>2017-04-19T15:49:40+1200</Modified>
|
||||||
|
<Version>1</Version>
|
||||||
|
<Settings>
|
||||||
|
<RaceBoatType Type="AC45" />
|
||||||
|
<BoatDimension BoatLength="14.019" HullLength="13.449" />
|
||||||
|
<ZoneSize MarkZoneSize="40.347" CourseZoneSize="40.347" />
|
||||||
|
<ZoneLimits Limit1="200" Limit2="100" Limit3="40.347" Limit4="0" Limit5="-100" />
|
||||||
|
</Settings>
|
||||||
|
<BoatShapes>
|
||||||
|
<BoatShape ShapeID="0">
|
||||||
|
<Vertices>
|
||||||
|
<Vtx Seq="1" Y="0" X="-2.659" />
|
||||||
|
<Vtx Seq="2" Y="18.359" X="-2.659" />
|
||||||
|
<Vtx Seq="3" Y="18.359" X="2.659" />
|
||||||
|
<Vtx Seq="4" Y="0" X="2.659" />
|
||||||
|
</Vertices>
|
||||||
|
</BoatShape>
|
||||||
|
<BoatShape ShapeID="1">
|
||||||
|
<Vertices>
|
||||||
|
<Vtx Seq="1" Y="0" X="-1.278" />
|
||||||
|
<Vtx Seq="2" Y="8.876" X="-1.278" />
|
||||||
|
<Vtx Seq="3" Y="8.876" X="1.278" />
|
||||||
|
<Vtx Seq="4" Y="0" X="1.278" />
|
||||||
|
</Vertices>
|
||||||
|
</BoatShape>
|
||||||
|
<BoatShape ShapeID="2">
|
||||||
|
<Vertices>
|
||||||
|
<Vtx Seq="1" Y="0" X="-1.1" />
|
||||||
|
<Vtx Seq="2" Y="8.3" X="-1.1" />
|
||||||
|
<Vtx Seq="3" Y="8.3" X="1.1" />
|
||||||
|
<Vtx Seq="4" Y="0" X="1.1" />
|
||||||
|
</Vertices>
|
||||||
|
</BoatShape>
|
||||||
|
<BoatShape ShapeID="3">
|
||||||
|
<Vertices>
|
||||||
|
<Vtx Seq="1" Y="0" X="-0.75" />
|
||||||
|
<Vtx Seq="2" Y="3" X="-0.75" />
|
||||||
|
<Vtx Seq="3" Y="3" X="0.75" />
|
||||||
|
<Vtx Seq="4" Y="0" X="0.75" />
|
||||||
|
</Vertices>
|
||||||
|
</BoatShape>
|
||||||
|
<BoatShape ShapeID="4">
|
||||||
|
<Vertices>
|
||||||
|
<Vtx Seq="1" Y="0" X="-3.46" />
|
||||||
|
<Vtx Seq="2" Y="13.449" X="-3.46" />
|
||||||
|
<Vtx Seq="3" Y="14.019" X="0" />
|
||||||
|
<Vtx Seq="4" Y="13.449" X="3.46" />
|
||||||
|
<Vtx Seq="5" Y="0" X="3.46" />
|
||||||
|
</Vertices>
|
||||||
|
<Catamaran>
|
||||||
|
<Vtx Seq="1" Y="1.769" X="-2.752" />
|
||||||
|
<Vtx Seq="2" Y="0" X="-2.813" />
|
||||||
|
<Vtx Seq="3" Y="0" X="-3.34" />
|
||||||
|
<Vtx Seq="4" Y="5.351" X="-3.46" />
|
||||||
|
<Vtx Seq="5" Y="10.544" X="-3.387" />
|
||||||
|
<Vtx Seq="6" Y="13.449" X="-3.075" />
|
||||||
|
<Vtx Seq="7" Y="10.851" X="-2.793" />
|
||||||
|
<Vtx Seq="8" Y="6.669" X="-2.699" />
|
||||||
|
<Vtx Seq="9" Y="6.669" X="2.699" />
|
||||||
|
<Vtx Seq="10" Y="10.851" X="2.793" />
|
||||||
|
<Vtx Seq="11" Y="13.449" X="3.075" />
|
||||||
|
<Vtx Seq="12" Y="10.544" X="3.387" />
|
||||||
|
<Vtx Seq="13" Y="5.351" X="3.46" />
|
||||||
|
<Vtx Seq="14" Y="0" X="3.34" />
|
||||||
|
<Vtx Seq="15" Y="0" X="2.813" />
|
||||||
|
<Vtx Seq="16" Y="1.769" X="2.752" />
|
||||||
|
</Catamaran>
|
||||||
|
<Bowsprit>
|
||||||
|
<Vtx Seq="1" Y="6.669" X="-0.2" />
|
||||||
|
<Vtx Seq="2" Y="11.377" X="-0.2" />
|
||||||
|
<Vtx Seq="3" Y="14.019" X="0" />
|
||||||
|
<Vtx Seq="4" Y="11.377" X="0.2" />
|
||||||
|
<Vtx Seq="5" Y="6.669" X="0.2" />
|
||||||
|
</Bowsprit>
|
||||||
|
<Trampoline>
|
||||||
|
<Vtx Seq="1" Y="2" X="-2.699" />
|
||||||
|
<Vtx Seq="2" Y="6.438" X="-2.699" />
|
||||||
|
<Vtx Seq="3" Y="6.438" X="2.699" />
|
||||||
|
<Vtx Seq="4" Y="2" X="2.699" />
|
||||||
|
</Trampoline>
|
||||||
|
</BoatShape>
|
||||||
|
<BoatShape ShapeID="5" />
|
||||||
|
</BoatShapes>
|
||||||
|
<Boats>>
|
||||||
|
<Boat Type="Yacht" SourceID="101" ShapeID="4" HullNum="AC4501" ShortName="USA"
|
||||||
|
BoatName="ORACLE TEAM USA" Country="USA">
|
||||||
|
<GPSposition Z="1.738" Y="0.625" X="0.001" />
|
||||||
|
<MastTop Z="21.496" Y="4.233" X="0.000" />
|
||||||
|
</Boat>
|
||||||
|
<Boat Type="Yacht" SourceID="102" ShapeID="4" HullNum="AC4502" ShortName="GBR"
|
||||||
|
BoatName="Land Rover BAR" Country="United Kingdom">
|
||||||
|
<GPSposition Z="1.738" Y="0.625" X="0.001" />
|
||||||
|
<MastTop Z="21.496" Y="4.233" X="0.000" />
|
||||||
|
</Boat>
|
||||||
|
<Boat Type="Yacht" SourceID="103" ShapeID="4" HullNum="AC4503" ShortName="JPN"
|
||||||
|
BoatName="SoftBank Team Japan" Country="Japan">
|
||||||
|
<GPSposition Z="1.738" Y="0.625" X="0.001" />
|
||||||
|
<MastTop Z="21.496" Y="4.233" X="0.000" />
|
||||||
|
</Boat>
|
||||||
|
<Boat Type="Yacht" SourceID="104" ShapeID="4" HullNum="AC4504" ShortName="FRA"
|
||||||
|
BoatName="Groupama Team France" Country="France">
|
||||||
|
<GPSposition Z="1.738" Y="0.625" X="0.001" />
|
||||||
|
<MastTop Z="21.496" Y="4.233" X="0.000" />
|
||||||
|
</Boat>
|
||||||
|
<Boat Type="Yacht" SourceID="105" ShapeID="4" HullNum="AC4505" ShortName="SWE"
|
||||||
|
BoatName="Artemis Racing" Country="Sweden">
|
||||||
|
<GPSposition Z="1.738" Y="0.625" X="0.001" />
|
||||||
|
<MastTop Z="21.496" Y="4.233" X="0.000" />
|
||||||
|
</Boat>
|
||||||
|
<Boat Type="Yacht" SourceID="106" ShapeID="4" HullNum="AC4506" ShortName="NZL"
|
||||||
|
BoatName="Emirates Team New Zealand" Country="New Zealand">
|
||||||
|
<GPSposition Z="1.738" Y="0.625" X="0.001" />
|
||||||
|
<MastTop Z="21.496" Y="4.233" X="0.000" />
|
||||||
|
</Boat>
|
||||||
|
</Boats>
|
||||||
|
</BoatConfig>
|
||||||
@ -0,0 +1,58 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Race>
|
||||||
|
<RaceID>17041901</RaceID>
|
||||||
|
<RaceType>Fleet</RaceType>
|
||||||
|
<CreationTimeDate>2017-04-19T15:30:00+1200</CreationTimeDate >
|
||||||
|
<RaceStartTime Time="2019-06-01T13:30:00-0400" Postpone="false" />
|
||||||
|
<Participants>
|
||||||
|
<Yacht SourceID="001" Entry="Port" />
|
||||||
|
<Yacht SourceID="002" Entry="Port" />
|
||||||
|
<Yacht SourceID="003" Entry="Port" />
|
||||||
|
<Yacht SourceID="004" Entry="Port" />
|
||||||
|
<Yacht SourceID="005" Entry="Port" />
|
||||||
|
<Yacht SourceID="006" Entry="Port" />
|
||||||
|
</Participants>
|
||||||
|
<Course>
|
||||||
|
<CompoundMark CompoundMarkID="1" Name="StartLine">
|
||||||
|
<Mark SeqID="1" Name="PRO" TargetLat="32.296577" TargetLng="-64.854304" SourceID="101" />
|
||||||
|
<Mark SeqID="2" Name="PIN" TargetLat="32.293771" TargetLng="-64.855242" SourceID="102" />
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="2" Name="M1">
|
||||||
|
<Mark Name="M1" TargetLat="32.293039" TargetLng="-64.843983" SourceID="103" />
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="3" Name="WindwardGate">
|
||||||
|
<Mark SeqID="1" Name="G1" TargetLat="32.284680" TargetLng="-64.850045" SourceID="104" />
|
||||||
|
<Mark SeqID="2" Name="G2" TargetLat="32.280164" TargetLng="-64.847591" SourceID="105" />
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="4" Name="LeewardGate">
|
||||||
|
<Mark SeqID="1" Name="G1" TargetLat="32.309693" TargetLng="-64.835249" SourceID="106" />
|
||||||
|
<Mark SeqID="2" Name="G2" TargetLat="32.308046" TargetLng="-64.831785" SourceID="107" />
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="5" Name="FinishLine">
|
||||||
|
<Mark SeqID="1" Name="PRO" TargetLat="32.317379" TargetLng="-64.839291" SourceID="108" />
|
||||||
|
<Mark SeqID="2" Name="PIN" TargetLat="32.317257" TargetLng="-64.836260" SourceID="109" />
|
||||||
|
</CompoundMark>
|
||||||
|
</Course>
|
||||||
|
<CompoundMarkSequence>
|
||||||
|
<Corner SeqID="1" CompoundMarkID="1" Rounding="SP" ZoneSize="3" />
|
||||||
|
<Corner SeqID="2" CompoundMarkID="2" Rounding="Port" ZoneSize="3" />
|
||||||
|
<Corner SeqID="3" CompoundMarkID="3" Rounding="Port" ZoneSize="3" />
|
||||||
|
<Corner SeqID="4" CompoundMarkID="4" Rounding="Port" ZoneSize="3" />
|
||||||
|
<Corner SeqID="3" CompoundMarkID="3" Rounding="Port" ZoneSize="3" />
|
||||||
|
<Corner SeqID="5" CompoundMarkID="5" Rounding="SP" ZoneSize="3"/>
|
||||||
|
</CompoundMarkSequence>
|
||||||
|
<CourseLimit>
|
||||||
|
<Limit SeqID="1" Lat="32.313922" Lon="-64.837168"/>
|
||||||
|
<Limit SeqID="2" Lat="32.317379" Lon="-64.839291"/>
|
||||||
|
<Limit SeqID="3" Lat="32.317911" Lon="-64.836996"/>
|
||||||
|
<Limit SeqID="4" Lat="32.317257" Lon="-64.836260"/>
|
||||||
|
<Limit SeqID="5" Lat="32.304273" Lon="-64.822834"/>
|
||||||
|
|
||||||
|
<Limit SeqID="6" Lat="32.279097" Lon="-64.841545"/>
|
||||||
|
<Limit SeqID="7" Lat="32.279604" Lon="-64.849871"/>
|
||||||
|
<Limit SeqID="8" Lat="32.289545" Lon="-64.854162"/>
|
||||||
|
<Limit SeqID="9" Lat="32.290198" Lon="-64.858711"/>
|
||||||
|
<Limit SeqID="10" Lat="32.297164" Lon="-64.856394"/>
|
||||||
|
<Limit SeqID="11" Lat="32.296148" Lon="-64.849184"/>
|
||||||
|
</CourseLimit>
|
||||||
|
</Race>
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<RegattaConfig>
|
||||||
|
<RegattaID>1</RegattaID>
|
||||||
|
<RegattaName>Seng302 Mock Test</RegattaName>
|
||||||
|
<CourseName>Bermuda AC35</CourseName>
|
||||||
|
<CentralLatitude>-32.296577</CentralLatitude>
|
||||||
|
<CentralLongitude>64.854304</CentralLongitude>
|
||||||
|
<CentralAltitude>0.00</CentralAltitude>
|
||||||
|
<UtcOffset>-4</UtcOffset>
|
||||||
|
<MagneticVariation>-14.78</MagneticVariation>
|
||||||
|
</RegattaConfig>
|
||||||
@ -0,0 +1,165 @@
|
|||||||
|
package seng302.Networking;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import seng302.Networking.Utils.ByteConverter;
|
||||||
|
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by fwy13 on 25/04/17.
|
||||||
|
*/
|
||||||
|
public class ByteConverterTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLargerIntToByte(){
|
||||||
|
int int1 = 1532158456; //100 in bytes
|
||||||
|
byte[] bytes1 = {(byte)0xF8, (byte)0xE1, 0x52, 0x5B};//this is in little endian
|
||||||
|
assertTrue(testArrayContents(ByteConverter.intToBytes(int1), bytes1));
|
||||||
|
byte[] bytes2 = {0x5B, 0x52, (byte)0xE1, (byte)0xF8};// this is big endian
|
||||||
|
assertTrue(testArrayContents(ByteConverter.intToBytes(int1, ByteConverter.IntegerSize, ByteOrder.BIG_ENDIAN), bytes2));
|
||||||
|
//test chopping
|
||||||
|
byte[] chopped1 = ByteConverter.intToBytes(int1, 3, ByteOrder.LITTLE_ENDIAN);
|
||||||
|
byte[] bytes3 = {(byte)0xF8, (byte)0xE1, 0x52};
|
||||||
|
assertTrue(testArrayContents(chopped1, bytes3));
|
||||||
|
byte[] chopped2 = ByteConverter.intToBytes(int1, 2, ByteOrder.LITTLE_ENDIAN);
|
||||||
|
byte[] bytes4 = {(byte)0xF8, (byte)0xE1};
|
||||||
|
assertTrue(testArrayContents(chopped2, bytes4));
|
||||||
|
byte[] chopped3 = ByteConverter.intToBytes(int1, 1, ByteOrder.LITTLE_ENDIAN);
|
||||||
|
byte[] bytes5 = {(byte)0xF8};
|
||||||
|
assertTrue(testArrayContents(chopped3, bytes5));
|
||||||
|
|
||||||
|
byte[] chopped4 = ByteConverter.intToBytes(int1, 3, ByteOrder.BIG_ENDIAN);
|
||||||
|
byte[] bytes6 = {0x52, (byte)0xE1, (byte)0xF8};
|
||||||
|
assertTrue(testArrayContents(chopped4, bytes6));
|
||||||
|
byte[] chopped5 = ByteConverter.intToBytes(int1, 2, ByteOrder.BIG_ENDIAN);
|
||||||
|
byte[] bytes7 = {(byte)0xE1, (byte)0xF8};
|
||||||
|
assertTrue(testArrayContents(chopped5, bytes7));
|
||||||
|
byte[] chopped6 = ByteConverter.intToBytes(int1, 1, ByteOrder.BIG_ENDIAN);
|
||||||
|
byte[] bytes8 = {(byte)0xF8};
|
||||||
|
assertTrue(testArrayContents(chopped6, bytes8));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testByteToInt(){
|
||||||
|
int int1 = 100; //100 in bytes
|
||||||
|
byte[] bytes1 = {100, 0, 0, 0};//this is in little endian
|
||||||
|
assertTrue(ByteConverter.bytesToInt(bytes1) == int1);
|
||||||
|
assertTrue(ByteConverter.bytesToInt(bytes1, ByteOrder.LITTLE_ENDIAN) == int1);
|
||||||
|
byte[] bytes2 = {0, 0, 0, 100};// this is big endian
|
||||||
|
assertTrue(ByteConverter.bytesToInt(bytes2, ByteOrder.BIG_ENDIAN) == int1);
|
||||||
|
//check single bytes to integers
|
||||||
|
assertTrue(ByteConverter.bytesToInt((byte)100) == int1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testByteToLong(){
|
||||||
|
long lng1 = 15; //100 in bytes
|
||||||
|
byte[] bytes1 = {15, 0, 0, 0, 0, 0, 0, 0};//this is in little endian
|
||||||
|
assertTrue(ByteConverter.bytesToLong(bytes1) == lng1);
|
||||||
|
assertTrue(ByteConverter.bytesToLong(bytes1, ByteOrder.LITTLE_ENDIAN) == lng1);
|
||||||
|
byte[] bytes2 = {0, 0, 0, 0, 0, 0, 0, 15};// this is big endian
|
||||||
|
assertTrue(ByteConverter.bytesToLong(bytes2, ByteOrder.BIG_ENDIAN) == lng1);
|
||||||
|
//check single bytes to integers
|
||||||
|
assertTrue(ByteConverter.bytesToLong((byte)15) == lng1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testByteToShort(){
|
||||||
|
short short1 = 20; //100 in bytes
|
||||||
|
byte[] bytes1 = {20, 0};//this is in little endian
|
||||||
|
assertTrue(ByteConverter.bytesToShort(bytes1) == short1);
|
||||||
|
assertTrue(ByteConverter.bytesToShort(bytes1, ByteOrder.LITTLE_ENDIAN) == short1);
|
||||||
|
byte[] bytes2 = {0, 20};// this is big endian
|
||||||
|
assertTrue(ByteConverter.bytesToShort(bytes2, ByteOrder.BIG_ENDIAN) == short1);
|
||||||
|
//check single bytes to integers
|
||||||
|
assertTrue(ByteConverter.bytesToShort((byte)20) == short1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testByteToChar(){
|
||||||
|
char char1 = 20; //100 in bytes
|
||||||
|
byte[] bytes1 = {20, 0};//this is in little endian
|
||||||
|
assertTrue(ByteConverter.bytesToChar(bytes1) == char1);
|
||||||
|
assertTrue(ByteConverter.bytesToChar(bytes1, ByteOrder.LITTLE_ENDIAN) == char1);
|
||||||
|
byte[] bytes2 = {0, 20};// this is big endian
|
||||||
|
assertTrue(ByteConverter.bytesToChar(bytes2, ByteOrder.BIG_ENDIAN) == char1);
|
||||||
|
//check single bytes to integers
|
||||||
|
assertTrue(ByteConverter.bytesToChar((byte)20) == char1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIntToByte(){
|
||||||
|
int int1 = 100; //100 in bytes
|
||||||
|
byte[] bytes1 = {100, 0, 0, 0};//this is in little endian
|
||||||
|
assertTrue(testArrayContents(ByteConverter.intToBytes(int1), bytes1));
|
||||||
|
byte[] bytes2 = {0, 0, 0, 100};// this is big endian
|
||||||
|
assertTrue(testArrayContents(ByteConverter.intToBytes(int1, ByteConverter.IntegerSize, ByteOrder.BIG_ENDIAN), bytes2));
|
||||||
|
//test chopping
|
||||||
|
byte[] chopped1 = ByteConverter.intToBytes(int1, 3, ByteOrder.LITTLE_ENDIAN);
|
||||||
|
byte[] bytes3 = {100, 0, 0};
|
||||||
|
assertTrue(testArrayContents(chopped1, bytes3));
|
||||||
|
byte[] chopped2 = ByteConverter.intToBytes(int1, 2, ByteOrder.LITTLE_ENDIAN);
|
||||||
|
byte[] bytes4 = {100, 0};
|
||||||
|
assertTrue(testArrayContents(chopped2, bytes4));
|
||||||
|
byte[] chopped3 = ByteConverter.intToBytes(int1, 1, ByteOrder.LITTLE_ENDIAN);
|
||||||
|
byte[] bytes5 = {100};
|
||||||
|
assertTrue(testArrayContents(chopped3, bytes5));
|
||||||
|
|
||||||
|
byte[] chopped4 = ByteConverter.intToBytes(int1, 3, ByteOrder.BIG_ENDIAN);
|
||||||
|
byte[] bytes6 = {0, 0, 100};
|
||||||
|
assertTrue(testArrayContents(chopped4, bytes6));
|
||||||
|
byte[] chopped5 = ByteConverter.intToBytes(int1, 2, ByteOrder.BIG_ENDIAN);
|
||||||
|
byte[] bytes7 = {0, 100};
|
||||||
|
assertTrue(testArrayContents(chopped5, bytes7));
|
||||||
|
byte[] chopped6 = ByteConverter.intToBytes(int1, 1, ByteOrder.BIG_ENDIAN);
|
||||||
|
byte[] bytes8 = {100};
|
||||||
|
assertTrue(testArrayContents(chopped6, bytes8));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testLongToBytes(){
|
||||||
|
long lng1 = 15; //100 in bytes
|
||||||
|
byte[] bytes1 = {15, 0, 0, 0, 0, 0, 0, 0};//this is in little endian
|
||||||
|
assertTrue(testArrayContents(ByteConverter.longToBytes(lng1), bytes1));
|
||||||
|
byte[] bytes2 = {0, 0, 0, 0, 0, 0, 0, 15};// this is big endian
|
||||||
|
assertTrue(testArrayContents(ByteConverter.longToBytes(lng1, ByteConverter.LongSize, ByteOrder.BIG_ENDIAN), bytes2));
|
||||||
|
//test chopping
|
||||||
|
byte[] chopped1 = ByteConverter.longToBytes(lng1, 3, ByteOrder.LITTLE_ENDIAN);
|
||||||
|
byte[] bytes3 = {15, 0, 0};
|
||||||
|
assertTrue(testArrayContents(chopped1, bytes3));
|
||||||
|
byte[] chopped2 = ByteConverter.longToBytes(lng1, 2, ByteOrder.LITTLE_ENDIAN);
|
||||||
|
byte[] bytes4 = {15, 0};
|
||||||
|
assertTrue(testArrayContents(chopped2, bytes4));
|
||||||
|
byte[] chopped3 = ByteConverter.longToBytes(lng1, 1, ByteOrder.LITTLE_ENDIAN);
|
||||||
|
byte[] bytes5 = {15};
|
||||||
|
assertTrue(testArrayContents(chopped3, bytes5));
|
||||||
|
|
||||||
|
byte[] chopped4 = ByteConverter.longToBytes(lng1, 3, ByteOrder.BIG_ENDIAN);
|
||||||
|
byte[] bytes6 = {0, 0, 15};
|
||||||
|
assertTrue(testArrayContents(chopped4, bytes6));
|
||||||
|
byte[] chopped5 = ByteConverter.longToBytes(lng1, 2, ByteOrder.BIG_ENDIAN);
|
||||||
|
byte[] bytes7 = {0, 15};
|
||||||
|
assertTrue(testArrayContents(chopped5, bytes7));
|
||||||
|
byte[] chopped6 = ByteConverter.longToBytes(lng1, 1, ByteOrder.BIG_ENDIAN);
|
||||||
|
byte[] bytes8 = {15};
|
||||||
|
assertTrue(testArrayContents(chopped6, bytes8));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean testArrayContents(byte[] bytes1, byte[] bytes2){
|
||||||
|
if (bytes1.length != bytes2.length){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < bytes1.length; i++){
|
||||||
|
if (bytes1[i] != bytes2[i]){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,75 @@
|
|||||||
|
package seng302.Networking.MessageDecoders;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
import seng302.Networking.MessageEncoders.RaceVisionByteEncoder;
|
||||||
|
import seng302.Networking.Utils.BoatStatus;
|
||||||
|
import seng302.Networking.Utils.RaceStatus;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by hba56 on 23/04/17.
|
||||||
|
*/
|
||||||
|
public class RaceStatusDecoderTest {
|
||||||
|
@Test
|
||||||
|
public void getByteArrayTest(){
|
||||||
|
long time = System.currentTimeMillis();
|
||||||
|
|
||||||
|
//Create data to serialize.
|
||||||
|
int boat1SourceID = 5;
|
||||||
|
int boat2SourceID = 8;
|
||||||
|
byte boat1Status = 2;
|
||||||
|
byte boat2Status = 2;
|
||||||
|
byte boat1LegNumber = 5;
|
||||||
|
byte boat2LegNumber = 3;
|
||||||
|
byte boat1PenaltiesAwarded = 4;
|
||||||
|
byte boat2PenaltiesAwarded = 0;
|
||||||
|
byte boat1PenaltiesServed = 2;
|
||||||
|
byte boat2PenaltiesServed = 0;
|
||||||
|
long boat1TimeAtNextMark = time + (1000 * 3);
|
||||||
|
long boat2TimeAtNextMark = time + (1000 * 2);
|
||||||
|
long boat1TimeAtFinish = boat1TimeAtNextMark + (1000 * 15);
|
||||||
|
long boat2TimeAtFinish = boat2TimeAtNextMark + (1000 * 7);
|
||||||
|
|
||||||
|
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;
|
||||||
|
long raceStartTime = time - (1000 * 31);
|
||||||
|
int windDirection = 2341;
|
||||||
|
int windSpeed = 10201;
|
||||||
|
int raceType = 1;
|
||||||
|
ArrayList<BoatStatus> boatStatuses = new ArrayList<>(2);
|
||||||
|
boatStatuses.add(boatStatus1);
|
||||||
|
boatStatuses.add(boatStatus2);
|
||||||
|
|
||||||
|
RaceStatus raceStatusObject = new RaceStatus(time, raceID, raceStatus, raceStartTime, windDirection, windSpeed, raceType, boatStatuses);
|
||||||
|
|
||||||
|
|
||||||
|
byte[] encodedRaceStatus = RaceVisionByteEncoder.raceStatus(raceStatusObject);
|
||||||
|
|
||||||
|
RaceStatusDecoder decoderTest = new RaceStatusDecoder(encodedRaceStatus);
|
||||||
|
|
||||||
|
Assert.assertEquals(0b10, decoderTest.getVersionNum());
|
||||||
|
Assert.assertEquals(time, decoderTest.getTime());
|
||||||
|
Assert.assertEquals(raceID, decoderTest.getRace());
|
||||||
|
Assert.assertEquals(raceStatus, decoderTest.getRaceState());
|
||||||
|
Assert.assertEquals(raceStartTime, decoderTest.getStartTime());
|
||||||
|
Assert.assertEquals(windDirection, decoderTest.getRaceWindDir());
|
||||||
|
Assert.assertEquals(windSpeed, decoderTest.getRaceWindSpeed());
|
||||||
|
|
||||||
|
|
||||||
|
BoatStatus boat1 = decoderTest.getBoats().get(0);
|
||||||
|
|
||||||
|
Assert.assertEquals(boat1SourceID, boat1.getSourceID());
|
||||||
|
Assert.assertEquals(boat1Status, boat1.getBoatStatus());
|
||||||
|
Assert.assertEquals(boat1LegNumber, boat1.getLegNumber());
|
||||||
|
Assert.assertEquals(boat1PenaltiesAwarded, boat1.getNumPenaltiesAwarded());
|
||||||
|
Assert.assertEquals(boat1PenaltiesServed, boat1.getNumPenaltiesServed());
|
||||||
|
Assert.assertEquals(boat1TimeAtNextMark, boat1.getEstTimeAtNextMark());
|
||||||
|
Assert.assertEquals(boat1TimeAtFinish, boat1.getEstTimeAtFinish());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<RegattaConfig>
|
||||||
|
<RegattaID>1</RegattaID>
|
||||||
|
<RegattaName>Seng302 Mock Test</RegattaName>
|
||||||
|
<CourseName>Bermuda AC35</CourseName>
|
||||||
|
<CentralLatitude>-32.296577</CentralLatitude>
|
||||||
|
<CentralLongitude>64.854304</CentralLongitude>
|
||||||
|
<CentralAltitude>0.00</CentralAltitude>
|
||||||
|
<UtcOffset>-4</UtcOffset>
|
||||||
|
<MagneticVariation>-14.78</MagneticVariation>
|
||||||
|
</RegattaConfig>
|
||||||
@ -0,0 +1,155 @@
|
|||||||
|
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>seng302</groupId>
|
||||||
|
<artifactId>team-7</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<name>sharedModel</name>
|
||||||
|
<artifactId>sharedModel</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>4.12</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-all -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mockito</groupId>
|
||||||
|
<artifactId>mockito-all</artifactId>
|
||||||
|
<version>1.9.5</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.testng</groupId>
|
||||||
|
<artifactId>testng</artifactId>
|
||||||
|
<version>6.11</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.geotools</groupId>
|
||||||
|
<artifactId>gt-referencing</artifactId>
|
||||||
|
<version>9.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<id>maven2-repository.dev.java.net</id>
|
||||||
|
<name>Java.net repository</name>
|
||||||
|
<url>http://download.java.net/maven/2</url>
|
||||||
|
</repository>
|
||||||
|
|
||||||
|
|
||||||
|
<repository>
|
||||||
|
<id>osgeo</id>
|
||||||
|
<name>Open Source Geospatial Foundation Repository</name>
|
||||||
|
<url>http://download.osgeo.org/webdav/geotools/</url>
|
||||||
|
</repository>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</repositories>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.5.1</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
<version>2.4.3</version>
|
||||||
|
<configuration>
|
||||||
|
<transformers>
|
||||||
|
<transformer
|
||||||
|
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||||
|
<manifestEntries>
|
||||||
|
<Main-Class>seng302.App</Main-Class>
|
||||||
|
<X-Compile-Source-JDK>${maven.compiler.source}</X-Compile-Source-JDK>
|
||||||
|
<X-Compile-Target-JDK>${maven.compiler.target}</X-Compile-Target-JDK>
|
||||||
|
</manifestEntries>
|
||||||
|
</transformer>
|
||||||
|
</transformers>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>shade</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
<reporting>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-jxr-plugin</artifactId>
|
||||||
|
<version>2.5</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-pmd-plugin</artifactId>
|
||||||
|
<version>3.6</version>
|
||||||
|
<configuration>
|
||||||
|
<linkXRef>true</linkXRef>
|
||||||
|
<targetJdk>${maven.compiler.target}</targetJdk>
|
||||||
|
<rulesets>
|
||||||
|
<ruleset>/rulesets/java/basic.xml</ruleset>
|
||||||
|
<ruleset>/rulesets/java/imports.xml</ruleset>
|
||||||
|
<ruleset>/rulesets/java/codesize.xml</ruleset>
|
||||||
|
<ruleset>/rulesets/java/design.xml</ruleset>
|
||||||
|
<ruleset>/rulesets/java/empty.xml</ruleset>
|
||||||
|
<ruleset>/rulesets/java/junit.xml</ruleset>
|
||||||
|
<ruleset>/rulesets/java/unusedcode.xml</ruleset>
|
||||||
|
</rulesets>
|
||||||
|
<includeXmlInSite>true</includeXmlInSite>
|
||||||
|
<sourceEncoding>utf-8</sourceEncoding>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
|
<version>2.10.3</version>
|
||||||
|
<configuration>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-report-plugin</artifactId>
|
||||||
|
<version>2.19.1</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-project-info-reports-plugin</artifactId>
|
||||||
|
<version>2.8.1</version>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</reporting>
|
||||||
|
</project>
|
||||||
@ -1,7 +1,4 @@
|
|||||||
package seng302;
|
package SharedModel;
|
||||||
|
|
||||||
import javafx.scene.paint.Color;
|
|
||||||
import seng302.Model.BoatInRace;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constants that are used throughout the program
|
* Constants that are used throughout the program
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package seng302;
|
package SharedModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GPS Coordinate for the world map.
|
* GPS Coordinate for the world map.
|
||||||
@ -1,7 +1,6 @@
|
|||||||
package seng302.Model;
|
package SharedModel;
|
||||||
|
|
||||||
import org.geotools.referencing.GeodeticCalculator;
|
import org.geotools.referencing.GeodeticCalculator;
|
||||||
import seng302.GPSCoordinate;
|
|
||||||
|
|
||||||
import java.awt.geom.Point2D;
|
import java.awt.geom.Point2D;
|
||||||
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package seng302.Model;
|
package SharedModel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by jjg64 on 19/04/17.
|
* Created by jjg64 on 19/04/17.
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
package seng302;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by f123 on 27-Apr-17.
|
||||||
|
*/
|
||||||
|
public class App {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue