You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

210 lines
9.0 KiB
C#

2 years ago
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace BirdyFlash.Lib {
public class CommPortTCP : CommPort {
public struct TCPRXPacket {
public byte[] data;
}
public struct TCPTXPacket {
public byte[] packet;
public TaskCompletionSource<TCPRXPacket> task;
}
public BinaryWriter tx;
public BinaryReader rx;
public TcpClient client;
private Thread receiveThread;
public Uri connectionURI;
public string Identifier;
private Queue<TCPTXPacket> txQueue;
public CommPortTCP(Uri uri) {
txQueue = new Queue<TCPTXPacket>();
Console.WriteLine("New CommPortTCP {0}", uri.ToString());
this.connectionURI = uri;
this.Initiate();
}
public async void Initiate() {
Console.WriteLine("Initiate");
try {
this.client = new TcpClient();
await client.ConnectAsync(connectionURI.Host, connectionURI.Port);
Console.WriteLine("Connected");
if (client.Connected == false) {
DeviceFinder.instance.DisablePort(this.connectionURI.ToString());
return;
}
this.tx = new BinaryWriter(client.GetStream());
this.rx = new BinaryReader(client.GetStream());
this.receiveThread = new Thread(this.StartRX);
this.receiveThread.Start();
SendTX(0x30, new byte[] { 0x13, 0x37, 0x13, 0x37, 0x13, 0x37 });
//Console.WriteLine("this.Identifier={0}", this.Identifier);
} catch (Exception ex) {;
Console.WriteLine("Fail");
Console.WriteLine(ex.Message);
DeviceFinder.instance.DisablePort(this.connectionURI.ToString());
return;
}
}
public TaskCompletionSource<TCPRXPacket> SendTX(byte type, byte[] data) {
var task = new TaskCompletionSource<TCPRXPacket>();
List<byte> packet = new List<byte> { type, (byte)(data.Length >> 8 & 0xFF), (byte)(data.Length & 0xFF) };
packet.AddRange(data);
var txrxjob = new TCPTXPacket
{
packet = packet.ToArray(),
task = task
};
txQueue.Enqueue(txrxjob);
packet.Clear();
return task;
}
public void StartRX() {
try {
Console.WriteLine("StartRX");
while (client.Connected) {
Console.WriteLine("Wait TX");
while (txQueue.Count < 1)
Task.Delay(100);
var txRXJob = txQueue.Dequeue();
try {
if (txRXJob.packet == null) throw new Exception("something fucked up hard");
Console.WriteLine("TX {0} {1} bytes", txQueue.Count, txRXJob.packet.Length);
this.tx.Write(txRXJob.packet);
this.tx.Flush();
Console.WriteLine("Wait RX");
var packetType = this.rx.ReadByte();
Console.WriteLine("Got Packet {0:X2}", packetType);
var packetLength = this.rx.ReadByte() << 8 | this.rx.ReadByte();
Console.WriteLine("Length= {0}", packetLength);
var packetPayload = this.rx.ReadBytes(packetLength);
Console.WriteLine("RX= {0}", BitConverter.ToString(packetPayload));
if (txRXJob.task != null)
txRXJob.task.TrySetResult(new TCPRXPacket {
data = packetPayload
});
} catch (Exception ex) {
Console.WriteLine(ex.ToString());
//txRXJob.task.TrySetException(ex);
}
/*
switch (packetType) {
case 0x31:
Identifier = Encoding.ASCII.GetString(packetPayload);
Console.WriteLine("Port FriendlyName = {0}", Identifier);
SendTX(0x31, new byte[] { 0x13, 0x37, 0x13, 0x37, 0x13, 0x37 });
break;
case 0x30:
Console.WriteLine("Got Test {0}", BitConverter.ToString(packetPayload));
break;
case 0x33:
tempPacket = new RXPacket();
tempPacket.dataLength = (byte)(packetLength & 0xFF);
tempPacket.data = packetPayload;
tempPacket.valid = true;
if (txRXJob.task != null)
txRXJob.task.Task.TrySetResult(tempPacket);
break;
}*/
}
} catch (Exception ex) {
Console.WriteLine(ex.Message);
}
}
public override TaskCompletionSource<RXPacket> SendCommand(byte[] cmd) {
if (this.client == null || this.client.Connected == false) {
this.Initiate();
}
var rxPacketTask = new TaskCompletionSource<RXPacket>();
var tcpTask = SendTX(0x32, cmd);
tcpTask.Task.ContinueWith((tcpRxPacket) => {
if (tcpRxPacket.IsFaulted) {
rxPacketTask.SetException(tcpRxPacket.Exception);
return;
}
RXPacket rxPacket = new RXPacket
{
dataLength = (byte)(tcpRxPacket.Result.data.Length & 0xFF),
data = tcpRxPacket.Result.data,
valid = true,
crc=0,
rcrc = 0,
};
Console.WriteLine("Task continued, after rxpacket");
rxPacketTask.TrySetResult(rxPacket);
});
Console.WriteLine("TX {0}", BitConverter.ToString(cmd));
return rxPacketTask;
}
public async override void ForceGotoProg() {
/*
* //int bdBefore = this.port.BaudRate;
this.ResetReOpen(9600);
for (int i = 0; i < 2; i++) {
this.SendRawSimplex(Encoding.ASCII.GetBytes("GOTOPROG"));
this.SendRawSimplex(Encoding.ASCII.GetBytes("GOTOPROG"));
this.SendRawSimplex(Encoding.ASCII.GetBytes("GOTOPROG"));
//await Task.Delay(320);
}
this.ResetReOpen(19600);
for (int i = 0; i < 3; i++) {
this.SendRawSimplex(Encoding.ASCII.GetBytes("GOTOPROG"));
this.SendRawSimplex(Encoding.ASCII.GetBytes("GOTOPROG"));
this.SendRawSimplex(Encoding.ASCII.GetBytes("GOTOPROG"));
//await Task.Delay(320);
}
this.ResetReOpen();*/
}
public override async Task<bool> SwitchHighspeed() {
Console.WriteLine("AskHighspeed {0}", this.ToString());
return await this.SwitchSpeed(true);
}
public override async Task<bool> SwitchLowspeed() {
Console.WriteLine("AskLowspeed {0}", this.ToString());
return await this.SwitchSpeed(false);
}
public async Task<bool> SwitchSpeed(bool highspeed) {
Console.WriteLine("AskLowspeed {0}", this.ToString());
var tcpTask = SendTX(0x34, new byte[] { (byte)(highspeed ? 0x01 : 0x00) });
var success = await tcpTask.Task.ContinueWith((tcpRxPacket) => {
if (tcpRxPacket.IsFaulted) {
return false;
}
Console.WriteLine("Task continued, after rxpacket");
return tcpRxPacket.Result.data[0] == 0x01;
});
if (success) {
Console.WriteLine("ChangeSpeed success");
}
return success;
}
private Action<Task<TCPRXPacket>> HandleCommandResponse(TaskCompletionSource<RXPacket> task) {
throw new NotImplementedException();
}
public override string ToString() {
return this.connectionURI.ToString();
}
public override void Dispose() {
Console.WriteLine("Disposing TCP");
if (this.client != null) this.client.Close();
if (this.client != null) this.client.Dispose();
if (this.rx != null) this.rx.Dispose();
if (this.tx != null) this.tx.Dispose();
}
}
}