175 lines
5.6 KiB
C#
175 lines
5.6 KiB
C#
using System;
|
||
using System.Collections.Concurrent;
|
||
using System.Text;
|
||
using System.Threading.Tasks;
|
||
|
||
namespace Plane.Communication
|
||
{
|
||
/// <summary>
|
||
/// (通过DTU服务端的Udp透传管道)与飞机进行通信的连接器。
|
||
/// </summary>
|
||
public partial class UdpThroughDtuServiceConnection : ExceptionThrownEventSource, IConnection
|
||
{
|
||
#region Fields
|
||
private byte[] _currentByteArray;
|
||
private int _currentIndex;
|
||
#if LOG_PACKETS
|
||
private System.Text.StringBuilder _log = new System.Text.StringBuilder();
|
||
#endif
|
||
private ConcurrentQueue<byte[]> _inputQueue = new ConcurrentQueue<byte[]>();
|
||
/// <summary>
|
||
/// 表示向DTU服务端飞控透传通道握手的协议头
|
||
/// </summary>
|
||
protected string FLAG_DTU_HANDSHAKE_HEAD = "*#$";
|
||
/// <summary>
|
||
/// 表示向DTU服务端的Udp飞控透传管道建立申请的结果状态
|
||
/// </summary>
|
||
protected enum DTUHandShakeResult
|
||
{
|
||
Unknown = 0,
|
||
Successful = 1,
|
||
NotExisted,
|
||
Occupied,
|
||
}
|
||
#endregion
|
||
|
||
#region Properties
|
||
/// <summary>
|
||
/// 希望连接到哪台飞机
|
||
/// </summary>
|
||
public string CopterIDToBind { get; set; }
|
||
|
||
public bool IsOpen { get; private set; }
|
||
|
||
/// <summary>
|
||
/// 获取即将或正在与服务端连接的服务端IP
|
||
/// </summary>
|
||
public string DtuServiceIP { get; set; }
|
||
|
||
/// <summary>
|
||
/// 获取即将或正在与服务端连接的服务端端口
|
||
/// </summary>
|
||
public int DtuServicePort { get; set; }
|
||
#endregion
|
||
|
||
public virtual async Task<int> ReadAsync(byte[] buffer, int offset, int size)
|
||
{
|
||
if (!IsOpen)
|
||
{
|
||
return 0;
|
||
}
|
||
try
|
||
{
|
||
var indexLessThan = offset + size;
|
||
for (int i = offset; i < indexLessThan; i++, _currentIndex++)
|
||
{
|
||
while (_currentByteArray == null || _currentIndex >= _currentByteArray.Length)
|
||
{
|
||
while (_inputQueue.Count <= 0)
|
||
{
|
||
if (!IsOpen)
|
||
{
|
||
return 0;
|
||
}
|
||
await Task.Delay(5).ConfigureAwait(false);
|
||
}
|
||
while (!_inputQueue.TryDequeue(out _currentByteArray))
|
||
{
|
||
if (!IsOpen)
|
||
{
|
||
return 0;
|
||
}
|
||
await Task.Delay(5).ConfigureAwait(false);
|
||
}
|
||
_currentIndex = 0;
|
||
}
|
||
buffer[i] = _currentByteArray[_currentIndex];
|
||
}
|
||
return size;
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
RaiseExceptionThrown(ex);
|
||
return 0;
|
||
}
|
||
}
|
||
public int BytesToRead()
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
public virtual async Task WriteAsync(byte[] buffer, int offset, int count)
|
||
{
|
||
if (IsOpen)
|
||
{
|
||
try
|
||
{
|
||
if (offset == 0)
|
||
{
|
||
await SendAsync(buffer, count);
|
||
}
|
||
else
|
||
{
|
||
var data = new byte[count];
|
||
for (int i = 0, j = offset; i < count; i++, j++)
|
||
{
|
||
data[i] = buffer[j];
|
||
}
|
||
await SendAsync(data, count);
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
Close();
|
||
RaiseExceptionThrown(ex);
|
||
}
|
||
}
|
||
}
|
||
|
||
internal void EnqueueDatagram(byte[] datagram)
|
||
{
|
||
if (datagram != null && IsOpen)
|
||
{
|
||
#if LOG_PACKETS
|
||
_log.AppendLine("------------");
|
||
for (int i = 0; i < datagram.Length; i++)
|
||
{
|
||
_log.Append(datagram[i]).Append(" ");
|
||
}
|
||
_log.AppendLine();
|
||
#endif
|
||
_inputQueue.Enqueue(datagram);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 构建用于发向DTU服务端的握手包
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
protected virtual byte[] ConstructHandShakeDatagramToDTUService()
|
||
{
|
||
var str = string.Format("{0}{1}", FLAG_DTU_HANDSHAKE_HEAD, CopterIDToBind??string.Empty);
|
||
return Encoding.ASCII.GetBytes(str);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 分析由DTU服务端返回的我握手包
|
||
/// </summary>
|
||
/// <param name="buffer"></param>
|
||
/// <returns></returns>
|
||
protected virtual DTUHandShakeResult AnalyzeHandShakeDatagramFromDTUService(byte[] buffer)
|
||
{
|
||
var strResult = Encoding.ASCII.GetString(buffer);//返回的格式为“*#$xxxx|0”
|
||
if (strResult.StartsWith(FLAG_DTU_HANDSHAKE_HEAD))
|
||
{
|
||
var strList = strResult.Substring(FLAG_DTU_HANDSHAKE_HEAD.Length).Split('|');
|
||
var copterID = strList[0];
|
||
int iValue;
|
||
int.TryParse(strList[1], out iValue);
|
||
return (DTUHandShakeResult)iValue;
|
||
}
|
||
return DTUHandShakeResult.Unknown;
|
||
}
|
||
}
|
||
}
|