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 sendQueue = new ConcurrentQueue(); 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); } } }