Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Adds support for a controller to request connection termination #73

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Add message to control Timewarp
Add message to control camera position
Add message to send a log line to KSP from Arduino
Add message to emulate a keypress in KSP (to open the map, quicksave, etc.)
Add message to inform the controler about the current SAS mode
Add message to inform the controller about the current SAS mode
Add message for flight status (including warp speed, status, crew, com)

Add support for console command to start/stop the connection
Expand Down
35 changes: 32 additions & 3 deletions KerbalSimpit/KSPSerialPort.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,19 @@ public class KSPSerialPort
private int BaudRate;
public byte ID;

private List<int> subscribedPackets = new List<int>();

const int IDLE_TIMEOUT = 10; //Timeout to consider the connection as idle, in seconds.
private long lastTimeMsgReceveived;

// Enum for the different states a port can have
public enum ConnectionStatus
{
CLOSED, // The port is closed, SimPit does not use it.
WAITING_HANDSHAKE, // The port is opened, waiting for the controler to start the handshake
WAITING_HANDSHAKE, // The port is opened, waiting for the controller to start the handshake
HANDSHAKE, // The port is opened, the first handshake packet was received, waiting for the SYN/ACK
CONNECTED, // The connection is established and a message was received from the controler in the last IDLE_TIMEOUT seconds
IDLE, // The connection is established and no message was received from the controler in the last IDLE_TIMEOUT seconds. This can indicate a failure on the controler side or a controler that only read data.
CONNECTED, // The connection is established and a message was received from the controller in the last IDLE_TIMEOUT seconds
IDLE, // The connection is established and no message was received from the controller in the last IDLE_TIMEOUT seconds. This can indicate a failure on the controller side or a controller that only read data.
ERROR, // The port could not be openned.
}

Expand Down Expand Up @@ -165,6 +167,33 @@ private void handleError()
}
}


public List<int> getPacketSubscriptionList()
{
return this.subscribedPackets;
}

public void addPacketSubscriptionRecord(int packetID)
{
this.subscribedPackets.Add(packetID);
}

public bool isPacketSubscribedTo(int packetID)
{
return this.subscribedPackets.Contains(packetID);
}

public void removePacketSubscriptionRecord(int packetID)
{
this.subscribedPackets.Remove(packetID);
}

public void removeAllPacketSubscriptionRecords()
{
this.subscribedPackets.Clear();
}


// Construct a KerbalSimpit packet, and enqueue it.
// Note that callers of this method are rarely in the main
// game thread, hence using a threadsafe queue implementation.
Expand Down
42 changes: 39 additions & 3 deletions KerbalSimpit/KerbalSimpit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ private void initPorts()
}

this.onSerialReceivedArray[CommonPackets.Synchronisation].Add(this.handshakeCallback);
this.onSerialReceivedArray[InboundPackets.CloseSerialPort].Add(this.serialCalledClose);
this.onSerialReceivedArray[InboundPackets.RegisterHandler].Add(this.registerCallback);
this.onSerialReceivedArray[InboundPackets.DeregisterHandler].Add(this.deregisterCallback);

Expand Down Expand Up @@ -308,6 +309,30 @@ private void handshakeCallback(byte portID, object data)
}
}

private void serialCalledClose(byte portID, object data)
{
// Spit out log that the port wants to be closed
if (Config.Verbose)
{
Debug.Log(String.Format("KerbalSimpit: Serial port {0} asked to be closed", portID));
}

foreach(int packetID in SerialPorts[portID].getPacketSubscriptionList())
{

// Remove the callback of the serial port from the event caller
toSerialArray[packetID].Remove(SerialPorts[portID].sendPacket);

if (Config.Verbose)
{
Debug.Log(String.Format("KerbalSimpit: Serial port {0} unsubscribed from packet {1}", portID, packetID));
}
}

SerialPorts[portID].removeAllPacketSubscriptionRecords();
ClosePort(portID);
}

private void registerCallback(byte portID, object data)
{
byte[] payload = (byte[]) data;
Expand All @@ -319,9 +344,14 @@ private void registerCallback(byte portID, object data)
{
Debug.Log(String.Format("KerbalSimpit: Serial port {0} subscribing to channel {1}", portID, idx));
}
toSerialArray[idx].Add(SerialPorts[portID].sendPacket);

onSerialChannelSubscribedArray[idx].Fire(idx, null);
if (!SerialPorts[portID].isPacketSubscribedTo(idx))
{
// Adds the sendPacket method as a callback to the event that is called when a value in the toSerialArray is updated
toSerialArray[idx].Add(SerialPorts[portID].sendPacket);
onSerialChannelSubscribedArray[idx].Fire(idx, null);
// Adds a record of the port subscribing to a packet to a list stored in the port instance.
SerialPorts[portID].addPacketSubscriptionRecord(idx);
}
}
}

Expand All @@ -333,6 +363,12 @@ private void deregisterCallback(byte portID, object data)
{
idx = payload[i];
toSerialArray[idx].Remove(SerialPorts[portID].sendPacket);
// Removes the record of a port subscribing to a packet from the port's internal record
SerialPorts[portID].removePacketSubscriptionRecord(idx);
if (Config.Verbose)
{
Debug.Log(String.Format("KerbalSimpit: Serial port {0} ubsubscribed from channel {1}", portID, idx));
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions KerbalSimpit/KerbalSimpitPackets.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ public static class OutboundPackets

public static class InboundPackets
{
public static byte CloseSerialPort = 7;
public static byte RegisterHandler = 8;
public static byte DeregisterHandler = 9;
public static byte CAGEnable = 10;
Expand Down
2 changes: 1 addition & 1 deletion KerbalSimpit/SimpitGUI/Window.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ void WindowGUI(int windowID)
foreach (Serial.KSPSerialPort port in KSPit.SerialPorts)
{
// For all port (except the first one), add a prefix to indicate which port we refer to.
// For the first one, nothing is written so that for the vast majority if users (that only use a single controler), they are not bothered by port ID.
// For the first one, nothing is written so that for the vast majority if users (that only use a single controller), they are not bothered by port ID.
String portName = "";
if (port.ID > 0)
{
Expand Down