forked from CPL/Simulator
259 lines
8.4 KiB
C#
259 lines
8.4 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|