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 task; } public BinaryWriter tx; public BinaryReader rx; public TcpClient client; private Thread receiveThread; public Uri connectionURI; public string Identifier; private Queue txQueue; public CommPortTCP(Uri uri) { txQueue = new Queue(); 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 SendTX(byte type, byte[] data) { var task = new TaskCompletionSource(); List packet = new List { 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 SendCommand(byte[] cmd) { if (this.client == null || this.client.Connected == false) { this.Initiate(); } var rxPacketTask = new TaskCompletionSource(); 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 SwitchHighspeed() { Console.WriteLine("AskHighspeed {0}", this.ToString()); return await this.SwitchSpeed(true); } public override async Task SwitchLowspeed() { Console.WriteLine("AskLowspeed {0}", this.ToString()); return await this.SwitchSpeed(false); } public async Task 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> HandleCommandResponse(TaskCompletionSource 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(); } } }