Plane.Sdk3/PlaneGcsSdk_Shared/Communication/UdpThroughDtuServiceConnection.cs

175 lines
5.6 KiB
C#
Raw Normal View History

2017-02-27 02:02:19 +08:00
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;
}
2017-02-27 02:02:19 +08:00
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;
}
}
}