/* * Copyright (c) 2025 LG Electronics Inc. * SPDX-License-Identifier: LicenseRef-LGE-Proprietary */ using Aurora; using Aurora.Api; using Aurora.Api.Devices; using Hermes; using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Sockets; using System.Reactive.Linq; using System.Reactive.Subjects; using System.Text; using System.Threading.Tasks; using System.Windows; namespace AuroraDeviceCommon.Devices { public abstract class SocketClientDevice : Device { // private Config _Config; protected readonly Logger Log; private readonly Subject _Received = new Subject(); private object Lock = new object(); SocketConnConfig _config; public IObservable Received { get; } public Socket Client; public int SocketNotActivatedAlarmCode { get; set; } public SocketClientDevice(string deviceId) { this.Client = null; DeviceId = deviceId; Log = new Logger(DeviceId); Received = _Received.AsObservable(); } public virtual int Send(byte[] data) { if (IsSimul) { return E1.OK; } try { if (!IsActivated) { Application.Current.AuroraEnv().AlarmService.SetAlarm(SocketNotActivatedAlarmCode); return E1.GENERIC; } if (Client != null) { if (Client.Send(data) > 0) { return E1.OK; } else { if (Client.Send(data) > 0) { Log.D("Socket Send Fail. Retry Send OK"); return E1.OK; } } Log.D("Socket Send Fail. Retry Send Fail"); } else { if (Activate() == E1.OK) { if (Client.Send(data) > 0) { Log.D("Socket Client Retry success!!"); return E1.OK; } } else { Log.D("Socket Client is Null. Re-Connect Fail."); } } Log.D("Socket Send Error. Retry / Re-Connect Fail. Socket Deactivated"); //Application.Current.AuroraEnv().AlarmService.SetAlarm((int)ALARM_DEVICE.eDESC.SOCKET_DEVICE_DISCONNECTED); DoDeactivate(); return E1.GENERIC; } catch (Exception e) { Log.FuncE(e.Message); //Application.Current.AuroraEnv().AlarmService.SetAlarm((int)ALARM_DEVICE.eDESC.SOCKET_DEVICE_DISCONNECTED); DoDeactivate(); return E1.GENERIC; } } protected override int DoActivate(IDeviceConfig config) { int err = E1.OK; _config = config.ConnConfig as SocketConnConfig; if (Client == null) { err = Connect(); } return err; } protected override int DoDeactivate() { int err = E1.OK; if (Client != null) { err = DisConnect(); } return err; } protected virtual byte[] ConvertStringToByte(string data) { return Encoding.Default.GetBytes(data); } protected string ConvertByteToString(byte[] data) { return Encoding.Default.GetString(data); } private int Connect() { if (IsSimul) { return E1.OK; } try { var endPoint = new IPEndPoint(IPAddress.Parse(_config.Address.IpAddress), _config.Address.PortNumber); Client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true); Client.Connect(endPoint); if (Client.LocalEndPoint != null) { StartReceive(); } return E1.OK; } catch (Exception e) { DisConnect(); Log.FuncE(e.Message); } return E1.GENERIC; } private void StartReceive() { var buffer = new Byte[1024]; try { lock (Lock) { if (Client != null) { Client.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, ReceiveCallBack, buffer); } } } catch (Exception e) { Log.FuncE(e.Message); } } private void ReceiveCallBack(IAsyncResult result) { lock (Lock) { if (Client == null) { return; } } var length = 0; try { length = Client.EndReceive(result); } catch (Exception e) { Log.FuncE(e.Message); } var buffer = (byte[])result.AsyncState; var data = new byte[length]; Array.Copy(buffer, data, data.Length); _Received.OnNext(data); StartReceive(); } private int DisConnect() { if (IsSimul) { return E1.OK; } try { lock (Lock) { Client.Shutdown(SocketShutdown.Both); Client.Close(); Client = null; return E1.OK; } } catch (Exception e) { Client = null; Log.FuncE(e.Message); } return E1.GENERIC; } } }