using System; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace AIParkingApplication { public delegate void C3DeviceEvent(int doorId, string cardNumber); public class C3DeviceController : IDoorControlAccess { private string ipAddress; private int port; private IntPtr oneTimeConnectedParamHandler; private string connectionString; private bool isReconnected; private int reconnectCounter; public event C3DeviceEvent OnNewCardReceived; public C3DeviceController(string ipAddress, int port = C3Constant.DEFAULT_C3_PORT) { this.ipAddress = ipAddress; this.port = port; connectionString = $"protocol=TCP,ipaddress={this.ipAddress},port={this.port},timeout=2000,passwd="; oneTimeConnectedParamHandler = IntPtr.Zero; isReconnected = true; reconnectCounter = 0; } ~C3DeviceController() { Disconnect(); } [DllImport(C3Constant.PLCOMMPRO_DLL, EntryPoint = C3Constant.ENTRY_POINT_CONNECT)] public static extern IntPtr Connect(string Parameters); [DllImport(C3Constant.PLCOMMPRO_DLL, EntryPoint = C3Constant.ENTRY_POINT_PULL_LAST_ERROR)] public static extern int PullLastError(); [DllImport(C3Constant.PLCOMMPRO_DLL, EntryPoint = C3Constant.ENTRY_POINT_DISCONNECT)] public static extern void Disconnect(IntPtr h); [DllImport(C3Constant.PLCOMMPRO_DLL, EntryPoint = C3Constant.ENTRY_POINT_CONTROL_DEVICE)] public static extern int ControlDevice(IntPtr h, int operationid, int param1, int param2, int param3, int param4, string options); [DllImport(C3Constant.PLCOMMPRO_DLL, EntryPoint = C3Constant.ENTRY_POINT_GET_RT_LOG)] public static extern int GetRTLog(IntPtr h, ref byte buffer, int buffersize); public ActionResult Connect() { if (Util.IsPingable(ipAddress, out long replyTime)) { oneTimeConnectedParamHandler = Connect(connectionString); if (oneTimeConnectedParamHandler != IntPtr.Zero) { var result = new ActionResult { HasError = false, Message = string.Format(C3Constant.CONNECTED_SUCCESSFULLY, DateTime.Now.GetTimeFormatted(), ipAddress) }; return result; } else { var result = new ActionResult { HasError = true, Message = string.Format(C3Constant.FAILED_TO_CONNECT, DateTime.Now.GetTimeFormatted(), ipAddress, PullLastError()) }; return result; } } else { var result = new ActionResult { HasError = true, Message = string.Format(C3Constant.FAILED_TO_PING, DateTime.Now.GetTimeFormatted(), ipAddress) }; return result; } } public ActionResult OpenDoor(int doorId) { if (oneTimeConnectedParamHandler != IntPtr.Zero) { int controlDeviceResult = ControlDevice(oneTimeConnectedParamHandler, 1, doorId, 1, 1, 0, ""); if (controlDeviceResult >= 0) { var result = new ActionResult { HasError = false, Message = string.Format(C3Constant.OPENNED_DOOR_SUCCESSFULLY, DateTime.Now.GetTimeFormatted(), ipAddress) }; return result; } else { var result = new ActionResult { HasError = true, Message = string.Format(C3Constant.FAILED_TO_OPEN_DOOR, DateTime.Now.GetTimeFormatted(), ipAddress) }; return result; } } else { var result = new ActionResult { HasError = true, Message = string.Format(C3Constant.NOT_CONNECTTED, DateTime.Now.GetTimeFormatted(), ipAddress) }; return result; } } public async Task GetLogToReceiveNewCard() { while (true) { await Task.Delay(1000); ActionResult getRTLogResult = GetRTLog(out int doorId, out string cardNumber); if (doorId != C3Constant.DEFAULT_DOOR_ID && cardNumber != C3Constant.DEFAULT_CARD_NUMBER) { OnNewCardReceived?.Invoke(doorId, cardNumber); } } } private ActionResult GetRTLog(out int doorId, out string cardNumber) { doorId = C3Constant.DEFAULT_DOOR_ID; cardNumber = C3Constant.DEFAULT_CARD_NUMBER; if (!Util.IsPingable(ipAddress, out long replyTime)) { isReconnected = false; var result = new ActionResult { HasError = true, Message = string.Format(C3Constant.FAILED_TO_PING, DateTime.Now.GetTimeFormatted(), ipAddress) }; return result; } try { int buffersize = 256; byte[] buffer = new byte[buffersize]; int resultRTLog = GetRTLog(oneTimeConnectedParamHandler, ref buffer[0], buffersize); if (resultRTLog >= 0) { string bufferString = Encoding.Default.GetString(buffer); string[] data = bufferString.Split(','); reconnectCounter = 0; cardNumber = data[2]; int.TryParse(data[3], out doorId); var result = new ActionResult { HasError = false }; return result; } else { reconnectCounter += 1; if (!isReconnected && reconnectCounter >= C3Constant.MAX_TIME_GET_LOG_BEFORE_RECONNECT) { ActionResult reconnectResult = Connect(); if (!reconnectResult.HasError) { isReconnected = true; reconnectCounter = 0; reconnectResult.Message = string.Format(C3Constant.RECONNECTED_SUCCESSFULLY, DateTime.Now.GetTimeFormatted(), ipAddress); } return reconnectResult; } var result = new ActionResult { HasError = true, Message = string.Format(C3Constant.FAILED_TO_READ_LOG, DateTime.Now.GetTimeFormatted(), ipAddress) }; return result; } } catch (Exception ex) { doorId = C3Constant.DEFAULT_DOOR_ID; cardNumber = C3Constant.DEFAULT_CARD_NUMBER; var result = new ActionResult { HasError = true, Message = string.Format(C3Constant.WRONG_FORMAT_DATA, DateTime.Now.GetTimeFormatted(), ipAddress, ex.Message) }; return result; } } public ActionResult Disconnect() { Disconnect(oneTimeConnectedParamHandler); oneTimeConnectedParamHandler = IntPtr.Zero; var result = new ActionResult { HasError = false, Message = string.Format(C3Constant.DISCONNECTED_SUCCESSFULLY, DateTime.Now.GetTimeFormatted(), ipAddress) }; return result; } } public static class C3Constant { #region DLL Entry Point public const string PLCOMMPRO_DLL = "plcommpro.dll"; public const string ENTRY_POINT_CONNECT = "Connect"; public const string ENTRY_POINT_PULL_LAST_ERROR = "PullLastError"; public const string ENTRY_POINT_DISCONNECT = "Disconnect"; public const string ENTRY_POINT_CONTROL_DEVICE = "ControlDevice"; public const string ENTRY_POINT_GET_RT_LOG = "GetRTLog"; #endregion public const int DEFAULT_C3_PORT = 4370; public const string CONNECTED_SUCCESSFULLY = "{0}\t{1}\tKết nối thành công hệ thống đóng mở cửa"; public const string FAILED_TO_CONNECT = "{0}\t{1}\tKhông thể kết nối tới thiết bị C3\tError Code: {2}"; public const string NOT_CONNECTTED = "{0}\t{1}\tChưa kết nối tới thiết bị C3"; public const string FAILED_TO_PING = "{0}\t{1}\tKhông thể PING tới thiết bị C3"; public const string DISCONNECTED_SUCCESSFULLY = "{0}\t{1}\tĐã ngắt kết nối thành công tới thiết bị C3"; public const string OPENNED_DOOR_SUCCESSFULLY = "{0}\t{1}\tMở cửa thành công!"; public const string FAILED_TO_OPEN_DOOR = "{0}\t{1}\tKhông thể mở cửa!"; public const string WRONG_FORMAT_DATA = "{0}\t{1}\tĐịnh dạng dữ liệu đọc từ thiết bị sai!\tErrorMessage:{2}"; public const string FAILED_TO_READ_LOG = "{0}\t{1}\tKhông đọc được dữ liệu RTLog từ thiết bị C3"; public const string RECONNECTED_SUCCESSFULLY = "{0}\t{1}\tĐã kết nối lại tới thiết bị C3"; public const string DEFAULT_CARD_NUMBER = "0"; public const int DEFAULT_DOOR_ID = 0; public const string DATETIME_FORMAT = "HH:mm:ss dd/MM/yyyy"; public const int MAX_TIME_GET_LOG_BEFORE_RECONNECT = 5; } }