forked from CPL/Simulator
Добавлен сервер для отправки телеметрии
This commit is contained in:
258
DroneClient/TelemetryServer.cs
Normal file
258
DroneClient/TelemetryServer.cs
Normal file
@ -0,0 +1,258 @@
|
||||
using DroneClient.Models;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using TelemetryIO;
|
||||
using TelemetryIO.Models;
|
||||
|
||||
namespace TelemetryIO
|
||||
{
|
||||
internal class TelemetryServer : TelemetryIO.BaseCommHandler
|
||||
{
|
||||
ConcurrentQueue<byte[]> sendQueue = new ConcurrentQueue<byte[]>();
|
||||
Telemetry telemetry = Telemetry.Instance;
|
||||
MonitorContainer monitoring = MonitorContainer.Instance;
|
||||
private bool isClientConnected = false;
|
||||
|
||||
public event EventHandler OnTeleClientConnected = delegate { };
|
||||
public event EventHandler OnTeleClientDisconnected = delegate { };
|
||||
|
||||
public bool isClientAvailable { get { return isClientConnected; } }
|
||||
|
||||
public TelemetryServer()
|
||||
{
|
||||
|
||||
}
|
||||
public override void Close()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void CloseConnection()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override bool IsOpen()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public async override Task Open()
|
||||
{
|
||||
await StartServerAsync();
|
||||
//Console.ReadLine();
|
||||
}
|
||||
|
||||
public async Task StartServerAsync()
|
||||
{
|
||||
var listener = new TcpListener(IPAddress.Any, Port);
|
||||
listener.Start();
|
||||
Console.WriteLine("Server is running");
|
||||
try
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
//if (isClientConnected) await Task.Delay(25);
|
||||
var client = await listener.AcceptTcpClientAsync();
|
||||
StrikeOnTeleClientConnected();
|
||||
isClientConnected = true;
|
||||
Debug.WriteLine("Client is connected");
|
||||
//this.client = client;
|
||||
var readTask = StartReadingAsync(client);
|
||||
var writeTask = SendMessageAsync(client);
|
||||
await readTask;
|
||||
await writeTask;
|
||||
}
|
||||
}
|
||||
catch (IOException ex) when (IsNetworkError(ex))
|
||||
{
|
||||
// Специальная обработка сетевых ошибок
|
||||
Debug.WriteLine($"Ошибка при запуске сервера: {ex.Message}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine("An error occurred: " + ex.Message);
|
||||
}
|
||||
finally
|
||||
{
|
||||
listener.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SendMessageAsync(TcpClient c)
|
||||
{
|
||||
if (c.GetStream() == null || !c.Connected)
|
||||
{
|
||||
Console.WriteLine("Not connected to server");
|
||||
return;
|
||||
}
|
||||
|
||||
while (c.Connected)
|
||||
{
|
||||
if (sendQueue.TryDequeue(out byte[] buffer))
|
||||
{
|
||||
try
|
||||
{
|
||||
await c.GetStream().WriteAsync(buffer, 0, buffer.Length);
|
||||
Debug.WriteLine($"Sent");
|
||||
}
|
||||
catch (IOException ex) when (IsNetworkError(ex))
|
||||
{
|
||||
// Специальная обработка сетевых ошибок
|
||||
Debug.WriteLine($"Клиент отключился: {ex.Message}");
|
||||
HandleDisconnectedClient(c);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"Error sending message: {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async override Task StartReadingAsync(object C)
|
||||
{
|
||||
TcpClient client;
|
||||
if (C is TcpClient) client = (TcpClient)C;
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
using NetworkStream stream = client.GetStream();
|
||||
|
||||
while (client.Connected)
|
||||
{
|
||||
byte[] buffer = new byte[1024];
|
||||
int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length);
|
||||
//string response = await reader.ReadLineAsync();
|
||||
if (bytesRead > 0)
|
||||
{
|
||||
EnqueueData(buffer, bytesRead);
|
||||
}
|
||||
data_extract();
|
||||
}
|
||||
}
|
||||
catch (IOException ex) when (IsNetworkError(ex))
|
||||
{
|
||||
// Специальная обработка сетевых ошибок
|
||||
Debug.WriteLine($"Клиент отключился: {ex.Message}");
|
||||
HandleDisconnectedClient(client);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"Error sending message: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ProcessCommand(int cmd, int slot, byte[] data, int offset, int len)
|
||||
{
|
||||
Debug.WriteLine(@"server cmd = " + cmd);
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case TELE_CMD_HELLO:
|
||||
byte[] load = telemetry.getSlot(cmd, offset, len);
|
||||
putRequest(prepareTelegram(cmd, 0, load, 0, load.Length));
|
||||
break;
|
||||
|
||||
case TELE_CMD_RD_ONCE:
|
||||
byte[] load1 = telemetry.getSlot(slot, offset, len);
|
||||
putRequest(prepareTelegram(cmd, slot, load1, offset, load1.Length));
|
||||
break;
|
||||
|
||||
case TELE_CMD_WR:
|
||||
setData(data, slot, offset, len);
|
||||
sendVoidAnswer(TELE_CMD_WR);
|
||||
break;
|
||||
|
||||
case TELE_CMD_RD_MON_ON:
|
||||
monitoring.isMonitor = 1;
|
||||
sendVoidAnswer(TELE_CMD_RD_MON_ON);
|
||||
break;
|
||||
|
||||
case TELE_CMD_RD_MON_OFF:
|
||||
monitoring.isMonitor = 0;
|
||||
sendVoidAnswer(TELE_CMD_RD_MON_OFF);
|
||||
break;
|
||||
|
||||
case TELE_CMD_RD_MON_ADD:
|
||||
int id = monitoring.monitorPut(slot, offset, 4);
|
||||
sendIntAnswer(TELE_CMD_RD_MON_ADD, id);
|
||||
monitoring.isMonitor = 1;
|
||||
break;
|
||||
|
||||
case TELE_CMD_RD_MON_REMOVE:
|
||||
id = monitoring.monitorRemove(offset);//in this case offset == id
|
||||
if(monitoring.monitorFillLevel == 0)monitoring.isMonitor = 0;//if monitor_fill_level == 0 there is no item to monitor
|
||||
if (monitoring.isMonitor > 0) sendIntAnswer(TELE_CMD_RD_MON_REMOVE, id);
|
||||
else sendVoidAnswer(TELE_CMD_RD_MON_REMOVEALL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void setData(byte[] load, int slot, int offset, int len)
|
||||
{
|
||||
telemetry.setSlot(slot, load, offset, len);
|
||||
}
|
||||
|
||||
private void sendVoidAnswer(int command)
|
||||
{
|
||||
putRequest(prepareTelegram(command, 0, new byte[0], 0));
|
||||
}
|
||||
|
||||
private void sendIntAnswer(int command, int param)
|
||||
{
|
||||
putRequest(prepareTelegram(command, 0, new byte[0], param));
|
||||
}
|
||||
|
||||
protected override void sendData(byte[] data)
|
||||
{
|
||||
sendQueue.Enqueue(data);
|
||||
}
|
||||
|
||||
public override void setCommParams(iCommParams commParams)
|
||||
{
|
||||
if (commParams.GetType() == typeof(TCPCommParams))
|
||||
{
|
||||
var comm = (TCPCommParams)commParams;
|
||||
IP = comm.IP;
|
||||
Port = comm.Port;
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleDisconnectedClient(TcpClient client)
|
||||
{
|
||||
isClientConnected = false;
|
||||
StrikeOnTeleClientDisconnected();
|
||||
}
|
||||
|
||||
private bool IsNetworkError(Exception ex)
|
||||
{
|
||||
// Проверяем типичные сетевые ошибки при разрыве соединения
|
||||
return ex is IOException
|
||||
|| ex is SocketException
|
||||
|| ex.InnerException is SocketException;
|
||||
}
|
||||
|
||||
public void StrikeOnTeleClientConnected()
|
||||
{
|
||||
OnTeleClientConnected?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
public void StrikeOnTeleClientDisconnected()
|
||||
{
|
||||
OnTeleClientDisconnected?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user