|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|