using DE70_CMDv2; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using SafeBagDE70.API; using SafeBagDE70.Model; using Serilog; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.ServiceProcess; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Forms.VisualStyles; using System.Windows.Threading; namespace SafeBagDE70 { public static class AppData { public static string CDMPort = "COM4"; public static string SensorPort = "COM3"; public static Version? CurrentVersion = null; public static ObservableCollection? customerAccounts = null; public static CustomerAccount? CurrentCustomerAccount{get;set;} public static CCmdRsp? cCmdRsp=null; public static bool IsAuthenticated = false; public static bool IsInTransaction = false; public static int WDTCount = 0; public static ObservableCollection logCollection = new ObservableCollection(); public static ListView logListView = null; public static int MaxLogCount = 500; public static int MaxNotes = 300; public static string BaseURL = ""; public static int TenantId = 0; public static bool IsInternetOk = false; static Task? resendTaskHistories = null; static Task? resendTaskEvents = null; static Task? commandTask = null; private static DeviceStatus? _DeviceStatus = null; public static DeviceStatusFile? DeviceStatusFile = null; public static DeviceStatus? DeviceStatus { set { _DeviceStatus = value; } get { if (_DeviceStatus == null) { InitDeviceStatus(); } else { _DeviceStatus.DeviceTime = DateTime.Now; } return _DeviceStatus; } } public static bool bInitUser = false; static AppData() { CDMSTATE = new CDMSTATE(); ADMINDEVICESTATUS = new ADMINDEVICESTATUS(); customerAccounts = new ObservableCollection(); GetDeviceStatusFromFile(); //InitDeviceStatus(); } public static void Init() { try { bInitUser = InitUsers(); } catch (Exception ex) { Log.Fatal(ex, "AppInit: "+ex.Message); if(DeviceStatus != null) { DeviceStatus.Description = "Exception in AppInit: "+ex.Message; APIModels.SendEvent(DeviceStatus); } } } public static void RestartApp(bool bAutoRestart=false) { Application.Current.Dispatcher.Invoke(() => { if (AppData.IsInTransaction) { if (!bAutoRestart) { MessageBox.Show("LƯU Ý, THAO TÁC NÀY SẼ LÀM MẤT TẤT CẢ DỮ LIỆU ĐANG THAO TÁC. " + "HÃY HOÀN TẤT GIAO DỊCH ĐỂ TIẾP TỤC", "CẢNH BÁO", MessageBoxButton.OK); } } else { string exePath = Process.GetCurrentProcess().MainModule.FileName; Process.Start(exePath); System.Windows.Application.Current.Shutdown(); } }); } public static void InitDeviceStatus() { DeviceStatus = new DeviceStatus { Device = Environment.MachineName, TenantId = AppData.TenantId, Status = 0, CDMStatus = 0, PrinterStatus = 0, SensorStatus = 0, Notes = "", OtherError = 0, }; } public static bool InitUsers() { int retryCount = 0; int maxRetries = 20; // Max retries before giving up int delay = 5000; // Delay between retries (5 seconds) while (retryCount < maxRetries) { try { customerAccounts.Clear(); using (var context = new CDMDbContext()) { var customers = context.Customers; foreach (var customer in customers) { var ca = new CustomerAccount { Name = customer.TenantName, CustomerId = customer.AccountNumber, QRCode = customer.AccountNumber, PINCode = customer.PinCode }; customerAccounts.Add(ca); } } CurrentCustomerAccount = customerAccounts[0]; Log.Information("InitUsers thành công"); bInitUser = true; break; } catch (Exception ex) { Log.Information($"Retry InitUser: {retryCount}/{maxRetries}"); retryCount++; if (retryCount >= maxRetries) { Log.Fatal(ex, "InitUsers: " + ex.Message); if (DeviceStatus != null) { DeviceStatus.Description = "Exception in InitUsers: " + ex.Message; APIModels.SendEvent(DeviceStatus); } break; } // Wait for the next retry Thread.Sleep(delay); } } return bInitUser; } public static CDMSTATE CDMSTATE; public static ADMINDEVICESTATUS ADMINDEVICESTATUS; private static DateTime CutOffTime = new DateTime(1, 1, 1, 11, 0, 0); // 11:00 a.m as cut-off time public static string GetNumberPartFromMerchantCode(string merchantCode) { if (merchantCode == null) return ""; var match = Regex.Match(merchantCode, @"\d+$"); string merchantCode_part = match.Value; return merchantCode_part; } public static void CreateNewTransactionCode() { DateTime transactionDateTime = DateTime.Now; string merchantCode_part = GetNumberPartFromMerchantCode(CurrentCustomerAccount.CustomerId); // Adjust transaction date if it's past cut-off time (12:00 noon) DateTime prevadjustedDate = CurrentCustomerAccount.TransactionTime.Hour >= CutOffTime.Hour ? transactionDateTime.Date : transactionDateTime.Date.AddDays(-1); DateTime adjustedDate = transactionDateTime.Hour >= CutOffTime.Hour ? transactionDateTime.Date : transactionDateTime.Date.AddDays(-1); if ((adjustedDate - prevadjustedDate).Days > 0) { CurrentCustomerAccount.TransactionCount =1; } else { CurrentCustomerAccount.TransactionCount++; } var transactionCount = CurrentCustomerAccount.TransactionCount; string datePart = transactionDateTime.ToString("yyyyMMdd"); string timePart = transactionDateTime.ToString("HHmmss"); string transactionCountPart = transactionCount.ToString("D2"); // Ensure 2 digits // Combine all parts to form the transaction ID string transactionId = $"{datePart}{timePart}{merchantCode_part}{transactionCountPart}"; CurrentCustomerAccount.TransactionCode = transactionId; CurrentCustomerAccount.TransactionTime = transactionDateTime; } public static string GetTransactionCode() { if (CurrentCustomerAccount != null) return CurrentCustomerAccount.TransactionCode; else return ""; } public static CDMSTATE? GetCDMState() { try { if (cCmdRsp != null) { cCmdRsp.SendDeSense(); string strSend = cCmdRsp.GetSendDat(false); string strRecv = cCmdRsp.GetRecvDat(); Log.Information($"[SEND] {strSend}"); Log.Information($"[RECV] {strRecv}"); var data = cCmdRsp.recv_dat.dat; if (AppData.CDMSTATE != null) { AppData.CDMSTATE.IsCassetteFull = data[17] & 0x08; AppData.CDMSTATE.IsNotesInEscrow = data[4] & 0x01; AppData.CDMSTATE.IsRejectPocketFull = data[3] & 0x40; AppData.CDMSTATE.IsNotesInRejectPocket = data[3] & 0x10; AppData.CDMSTATE.IsNotesInHopper = data[3] & 0x01; AppData.CDMSTATE.IsStackerFull = (data[2] == 0x43?1:0); if (data[0] == 0x40 && (data[1] == 0x07 || data[1]==0x09)) AppData.CDMSTATE.IsError = 0; else AppData.CDMSTATE.IsError = 1; AppData.CDMSTATE.RequestTime = DateTime.Now; AppData.CDMSTATE.UpdateCDMStatus(cCmdRsp.recv_dat); } } return AppData.CDMSTATE; } catch (Exception ex) { Log.Fatal(ex, "GetCDMState"); return null; } } public static byte[] GetCassetteData() { //for(int i = 0; i < 2; i++)//Retry if failed //{ // cCmdRsp.SendXXCmd((byte)Command.CMD_DE_READ_CASSETTE); // if (cCmdRsp.recv_dat.dat[0] != 0x40) // { // Thread.Sleep(1000); // } // else // break; //} cCmdRsp.SendXXCmd((byte)Command.CMD_DE_READ_CASSETTE); var data = cCmdRsp.recv_dat.dat; StringBuilder str = new StringBuilder(); var recv_dat = cCmdRsp.recv_dat; AppData.DeviceStatus.Notes = GetNotesString(recv_dat.dat); str.Append("DATA:"); for (int i = 0; i < recv_dat.leng - 1; i++) { var dat = string.Format("{0:X2} ", recv_dat.dat[i]); str.Append(dat); } Log.Information("[CASSETTE]" + str.ToString()); return (byte[])data.Clone(); } public static string GetNotesString(byte[] cassetData) { int notes = 0; int offset = 14; string str = ""; for (int i = 0; i < 10; i++) { notes = cassetData[2 * i + offset] * 256 + cassetData[2 * i + 1 + offset]; str += notes + ","; } return str.Trim(','); } public static void ResendData() { ResendDepositHistories(); ResendEvents(); } private static void ResendDepositHistories() { if (!AppData.IsInTransaction && AppData.IsInternetOk) { if (resendTaskHistories == null || resendTaskHistories.IsCompleted) { resendTaskHistories = Task.Run(async () => { try { using (var context = new CDMDbContext()) { var startTime = DateTime.Now.Date.AddDays(-2).Date; var unsentHist = context.Histories .Where(x => x.DepositTime >= startTime) .Where(x => ((x.IsSent == null || x.IsSent == false))) .ToList(); foreach (var item in unsentHist) { var data2Send = JsonConvert.DeserializeObject(item.Data); var bResult = await APIModels.SendCountingData(data2Send); if (bResult) { item.IsSent = true; context.Histories.Update(item); context.SaveChanges(); Log.Information("ResendHistories: " + item.Data + " successfully"); } else { Log.Error("ResendHistories: " + item.Data + " failed"); } } } } catch (Exception ex) { Log.Fatal(ex, "ResendHistories failed"); } }); } else { Log.Information("Previous ResendHistories are running"); } } else { Log.Information($"ResendHistories could not start IsInTransaction: {AppData.IsInTransaction} IsInternetOk: {AppData.IsInternetOk}"); } } private static void ResendEvents() { if (!AppData.IsInTransaction && AppData.IsInternetOk) { if (resendTaskEvents == null || resendTaskEvents.IsCompleted) { resendTaskEvents = Task.Run(async () => { try { using (var context = new CDMDbContext()) { var startTime = DateTime.Now.Date.AddDays(-2).Date; var unsentHist = context.DeviceEvents .Where(x => x.DeviceTime >= startTime) .Where(x => ((x.IsSent == null || x.IsSent == false))) .ToList(); foreach (var item in unsentHist) { var data2Send = JsonConvert.DeserializeObject(item.Data); var bResult = await APIModels.TaskSendEvent(data2Send); if (bResult) { item.IsSent = true; context.DeviceEvents.Update(item); context.SaveChanges(); Log.Information("ResendEvents: " + item.Data + " successfully"); } else { Log.Error("ResendEvents: " + item.Data + " failed"); } } } } catch (Exception ex) { Log.Fatal(ex, "ResendEvents failed"); } }); } else { Log.Information("Previous ResendEvents are running"); } } else { Log.Information($"ResendEvents could not start IsInTransaction: {AppData.IsInTransaction} IsInternetOk: {AppData.IsInternetOk}"); } } public static void GetandExecuteCommands() { if (IsInternetOk && (commandTask == null || commandTask.IsCompleted)) { commandTask = Task.Run(async () => { try { var commands= await APIModels.GetCommands(); if(commands != null && commands.Count()>0) { foreach (var command in commands) { bool bResult = false; switch(command.CommandCode) { case 0: break; case 1: Log.Information("Remote Reset CDM Error"); //Restart CDM bResult=ResetCDMError(); break; case 2: Log.Information("Remote Reset CDM Counter"); bResult = ResetCDMCounter(); if (!bResult) { bResult = ResetCDMCounter(); } break; case 3: if(IsInternetOk && !IsInTransaction) { Log.Information("Request update Customers"); int nCount = await UpdateCustomers(); Log.Information($"Updated {nCount} users"); InitUsers(); if (nCount > 0) bResult = true; } break; case 4: if (!IsInTransaction) { await APIModels.UpdateDeviceCommand(command.Id,1); RestartApp(true); } break; } // await APIModels.UpdateDeviceCommand(command.Id, bResult?1:2); } } } catch (Exception ex) { Log.Fatal(ex, "GetandExecuteCommands failed"); } }); } else { var str = ""; if (commandTask != null && !commandTask.IsCompleted) str += "Previous command state are running; "; if (!IsInternetOk) str += "No Internet Connection"; Log.Error("GetandExecuteCommands error: "+str); } } static string deviceStatusFileName = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),"device_status.txt"); public static void GetDeviceStatusFromFile() { try { lock(deviceStatusFileName) { if (File.Exists(deviceStatusFileName)) { var fileContent = File.ReadAllText(deviceStatusFileName); DeviceStatusFile = JsonConvert.DeserializeObject(fileContent); } else { DeviceStatusFile = new DeviceStatusFile(); UpdateDeviceStatusToFile(); } } Log.Information("GetPrinterStatusFromFile success"); } catch(Exception ex) { Log.Fatal(ex, "GetPrinterStatusFromFile"); } } public static void UpdatePrinterStatus(bool IsPrinterPaperOut) { try { if (DeviceStatusFile!=null) { DeviceStatusFile.IsPrinterNearPaperOut = IsPrinterPaperOut; if (!IsPrinterPaperOut) { DeviceStatusFile.PrintingCountFromNPO = 0; } } }catch(Exception ex) { Log.Fatal(ex, "UpdatePrinterStatus"); } } public static void UpdatePrintingCountToStatusFile() { try { Log.Information("UpdateTransactionCountToStatusFile"); if (DeviceStatusFile!=null) { if (DeviceStatusFile.IsPrinterNearPaperOut) { DeviceStatusFile.PrintingCountFromNPO++; } else { DeviceStatusFile.PrintingCountFromNPO = 0; } UpdateDeviceStatusToFile(); Log.Information("UpdateTransactionCountToStatusFile success"); } } catch (Exception ex) { Log.Fatal(ex, "UpdateTransactionCountToStatusFile"); } } public static void UpdateDeviceStatusToFile() { try { lock (deviceStatusFileName) { var fileContent = JsonConvert.SerializeObject(DeviceStatusFile); File.WriteAllText(deviceStatusFileName, fileContent); } Log.Information("UpdatePrinterStatusFromFile success"); } catch (Exception ex) { Log.Fatal(ex, "UpdatePrinterStatusFromFile"); } } public static bool IsStopPrinting() { try { if (DeviceStatusFile != null) return DeviceStatusFile.IsStopPrinting(); else return false; } catch(Exception ex) { return false; } } public static async Task UpdateCustomers() { try { var amCustomers = await APIModels.GetAeonMallCustomers(AppData.TenantId); using (var context = new CDMDbContext()) { var customers = context.Customers; context.Customers.RemoveRange(customers); context.SaveChanges(); foreach (var amCustomer in amCustomers) { var customer = new Customer { AccountNumber = amCustomer.TenantCode, AccountHolder = amCustomer.TenantName, TenantName = amCustomer.TenantShortName, TenantCode = amCustomer.TenantCode, PinCode = amCustomer.TenantCode, UpdatedTime = DateTime.Now, }; customers.Add(customer); } context.SaveChanges(); } return amCustomers.Count(); } catch(Exception ex) { } return 0; } public static bool ResetCDMCounter() { bool bResetOk = false; if (AppData.cCmdRsp != null) { Log.Information("[ADMIN] reset counter"); CCmdRsp cCmdRsp = AppData.cCmdRsp; cCmdRsp.SendDeSense(); Thread.Sleep(1000); cCmdRsp.SendXXCmd((byte)Command.CMD_DE_UNLOCK); Thread.Sleep(1000); cCmdRsp.SendDeSense(); Thread.Sleep(1000); //Event fix var recvData = cCmdRsp.recv_dat; if (recvData.dat[14] == recvData.dat[16]) { cCmdRsp.SendLock(); } else { cCmdRsp.SendEventFix(recvData.dat[16]); cCmdRsp.SendLock(); } var currentMode = cCmdRsp.GetLockParam().mode; cCmdRsp.GetLockParam().mode = Mode.MODE_COLLECTION; cCmdRsp.SendLock(); Thread.Sleep(10000); cCmdRsp.SendDeSense(); Thread.Sleep(1000); recvData = cCmdRsp.recv_dat; if (recvData.dat[14] != recvData.dat[16]) { AppData.GetCassetteData(); bResetOk = true; } } return bResetOk; } public static bool ResetCDMError() { var cCmdRsp = AppData.cCmdRsp; bool bSuccess = false; if(cCmdRsp!=null && cCmdRsp.recv_dat!=null) { //if(cCmdRsp.recv_dat.dat[1] == 0x1C && cCmdRsp.recv_dat.dat[2] == 0x4A) if (cCmdRsp.recv_dat.dat[1] == 0x1C) { cCmdRsp.SendXXCmd((byte)Command.CMD_DE_SENSE); var recvData = cCmdRsp.recv_dat; if (recvData.dat[14] == recvData.dat[16]) { cCmdRsp.SendLock(); } else { cCmdRsp.SendEventFix(recvData.dat[16]); } Thread.Sleep(1000); cCmdRsp.SendXXCmd((byte)Command.CMD_DE_RESET); Thread.Sleep(2000); cCmdRsp.SendXXCmd((byte)Command.CMD_DE_SENSE); if (cCmdRsp.recv_dat.dat[1] == 0x04 && cCmdRsp.recv_dat.dat[2] == 0x41) { bSuccess = true; } } } return bSuccess; } private static void LogCmdData() { try { string strSend = cCmdRsp.GetSendDat(false); string strRecv = cCmdRsp.GetRecvDat(); Log.Information($"[SEND] {strSend}"); Log.Information($"[RECV] {strRecv}"); } catch (Exception e) { Log.Fatal(e, "LogCmdData"); } } public static bool ResetAbnormalStorage605() { var cCmdRsp = AppData.cCmdRsp; bool bSuccess = false; if (cCmdRsp != null) { Log.Information("START ABNORMAL STORAGE RESET PROC"); cCmdRsp.SendXXCmd((byte)Command.CMD_DE_SENSE); LogCmdData(); if (cCmdRsp.recv_dat != null && ((cCmdRsp.recv_dat.dat[18] & 0xF0) == 0xE0)) { //0. Check notes in escrow or not? //1. Event Fix var recvData = cCmdRsp.recv_dat; if (recvData.dat[14] == recvData.dat[16]) { cCmdRsp.SendLock(); } else { cCmdRsp.SendEventFix(recvData.dat[16]); } //2. UnLock // cCmdRsp.SendXXCmd((byte)Command.CMD_DE_SENSE); cCmdRsp.SendXXCmd((byte)Command.CMD_DE_UNLOCK); LogCmdData(); Thread.Sleep(1000); //3. Lock with MODE IMPORTANT ERROR var currentMode = cCmdRsp.GetLockParam().mode; cCmdRsp.GetLockParam().mode = Mode.MODE_SECERROR; cCmdRsp.SendLock(); LogCmdData(); Thread.Sleep(1000); cCmdRsp.SendXXCmd((byte)Command.CMD_DE_SENSE); LogCmdData(); recvData = cCmdRsp.recv_dat; var SR2 = recvData.dat[1]; var S2 = recvData.dat[18]; if (SR2 == 0x1C && (S2==0xE2 || S2==0xE4)) { cCmdRsp.SendXXCmd((byte)Command.CMD_DE_RESET); LogCmdData(); Thread.Sleep(1000); for (int i=0;i<10;i++) { cCmdRsp.SendXXCmd((byte)Command.CMD_DE_SENSE); LogCmdData(); Thread.Sleep(1000); S2 = recvData.dat[18]; SR2 = recvData.dat[1]; if (SR2 == 0x07) break; } Thread.Sleep(2000); cCmdRsp.SendXXCmd((byte)Command.CMD_DE_CNTSTART); LogCmdData(); Thread.Sleep(2000); cCmdRsp.SendXXCmd((byte)Command.CMD_DE_STORESTART); Thread.Sleep(2000); LogCmdData(); if ((cCmdRsp.recv_dat.dat[1] == 0x07 || cCmdRsp.recv_dat.dat[1]==0x09) && cCmdRsp.recv_dat.dat[2] == 0x41) { //Wait until SR2=0x04 for(int i = 0; i < 10; i++) { cCmdRsp.SendXXCmd((byte)Command.CMD_DE_SENSE); LogCmdData(); Thread.Sleep(1000); SR2 = recvData.dat[1]; if (SR2 == 0x04) { bSuccess = true; } } } } else { } Log.Information("END ABNORMAL STORAGE RESET PROC"); } } return bSuccess; } } public class CustomerAccount { public string? Name { get; set; } public string? CustomerId { get; set; } public string? QRCode { get; set; } public string? PINCode { get; set; } public int TransactionCount { get; set; } = 1; public DateTime TransactionTime { get; set; } public string TransactionCode { get; set; } } public class CountSession { public CountSession() { for (int i = 0; i < QuantityDenomi.Count(); i++) { QuantityDenomi[i] = 0; } for (int i = 0; i < SumDenomi.Count(); i++) { SumDenomi[i] = 0; } for (int i = 0; i < TempNotes.Count(); i++) { TempNotes[i] = 0; } } public int[] QuantityDenomi { get; set; } = new int[10]; public int[] SumDenomi { get; set; } = new int[10]; public bool IsStored = false; public int[] TempNotes { get; set; } = new int[5]; } public class CountingData2Send { public string? TransactionCode { get; set; } public List? Sessions { get; set; } public string? UserId { get; set; } public string? MachineId { get; set; } public string? MachineTime { get; set; } public int RejectNotes { get; set; } public int GenuineNotes { get; set; } public int UnfitNotes { get; set; } public int CounterfeitNotes { get; set; } public int SuspendNotes { get; set; } public int CountingState { get; set; }//0-Normal End, 1-Timeout End } public class NotesInSession : INotifyPropertyChanged { private int _GenuineNotes; public int GenuineNotes { get { return _GenuineNotes; } set { if (_GenuineNotes != value) { _GenuineNotes = value; OnPropertyChanged(nameof(GenuineNotes)); } } } private int _RejectNotes; public int RejectNotes { get { return _RejectNotes; } set { if (_RejectNotes != value) { _RejectNotes = value; OnPropertyChanged(nameof(RejectNotes)); } } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } public enum COUNTINGSTATE { NORMAL=0, AUTOEND=1, FULLIFSTORE=2 } public class ADMINDEVICESTATUS : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } private string? _PrinterStatus; public string? PrinterStatus { get { return _PrinterStatus; } set { if (_PrinterStatus != value) { _PrinterStatus = value; OnPropertyChanged(nameof(PrinterStatus)); } } } private string? _SensorStatus; public string? SensorStatus { get { return _SensorStatus; } set { if (_SensorStatus != value) { _SensorStatus = value; OnPropertyChanged(nameof(SensorStatus)); } } } private string? _DeviceStatus; public string? DeviceStatus { get { return _DeviceStatus; } set { if (_DeviceStatus != value) { _DeviceStatus = value; OnPropertyChanged(nameof(DeviceStatus)); } } } } public class CDMSTATE : INotifyPropertyChanged { public int IsCassetteFull = 0; public int IsNotesInEscrow = 0; public int IsRejectPocketFull = 0; public int IsNotesInRejectPocket = 0; public int IsNotesInHopper = 0; public int IsStackerFull = 0; public int IsError = 0; public RecvData? RecvDat = null; public byte GetSR1() { if (RecvDat != null) return RecvDat.dat[0]; return 0; } public byte GetSR2() { if (RecvDat != null) return RecvDat.dat[1]; return 0; } public byte GetSR3() { if (RecvDat != null) return RecvDat.dat[2]; return 0; } public string GetSRStatus() { if (RecvDat != null) return "SR1/2/3: " + AppData.cCmdRsp.GetSR1Summary(RecvDat.dat[0]) + ", " + AppData.cCmdRsp.GetSR2Summary(RecvDat.dat[1]) + ", " + AppData.cCmdRsp.GetSR3Summary(RecvDat.dat[2]); else return ""; } public string GetDtatus() { string strStatus = ""; if (RecvDat != null) { if(RecvDat.leng>8) { var dat=RecvDat.dat; strStatus += "D1: "+AppData.cCmdRsp.GetD1Summary(dat[3]); strStatus += "\r\nD2: "+AppData.cCmdRsp.GetD2Summary(dat[4]); strStatus += "\r\nD3: " + AppData.cCmdRsp.GetD3Summary(dat[5]); strStatus += "\r\nD4: " + AppData.cCmdRsp.GetD4Summary(dat[6]); strStatus += "\r\nD5: " + AppData.cCmdRsp.GetD5Summary(dat[7]); strStatus += "\r\nD6: " + AppData.cCmdRsp.GetD6Summary(dat[8]); } } return strStatus; } public string GetSStatus() { string strStatus = ""; if (RecvDat != null) { if (RecvDat.leng > 18) { var dat = RecvDat.dat; strStatus += "S1: "+ AppData.cCmdRsp.GetS1Summary(dat[17]); strStatus += "\r\nS2: " + AppData.cCmdRsp.GetS2Summary(dat[18]); } } return strStatus; } public string GetFullStatus() { string strStatus = ""; strStatus = GetSRStatus(); strStatus += "\r\n"+GetDtatus(); strStatus += "\r\n"+GetSStatus(); return strStatus; } public void UpdateCDMStatus(RecvData recv_data) { RecvDat=recv_data; if (AppData.cCmdRsp != null) { CDMStatus = RequestTime.ToString("yyyy/MM/dd HH:mm:ss ") + GetSRStatus(); } } private string? _CDMStatus; public string? CDMStatus { get { return _CDMStatus; } set { if (_CDMStatus != value) { _CDMStatus = value; OnPropertyChanged(nameof(CDMStatus)); } } } public DateTime RequestTime = DateTime.Now; public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } public class DeviceStatus { public int TenantId { get; set; } public string Device { get; set; } public int Status { get; set; } public DateTime DeviceTime { get; set; } public int CDMStatus { get; set; } public int PrinterStatus { get; set; } public int SensorStatus { get; set; } public int OtherError { get; set; } public string? Notes { get; set; } public string? TransactionCode { get; set; } public string Description { get; set; } } public class DeviceStatusFile { public bool IsPrinterNearPaperOut = false; public int PrintingCountFromNPO = 0;//Transaction Count From Near Paper Out public bool IsStopPrinting() { if (IsPrinterNearPaperOut && PrintingCountFromNPO >= 50) { return true; } return false; } } public enum DeviceStatusCode { NORMAL=0, ERROR=1 } public enum PrinterStatusCode { NORMAL = 0, NEARPAPEROUT = 1, PAPEROUT=2, ERROR=3 } public enum SensorStatusCode { NORMAL = 0, ERROR = 4 } public enum CDMStatusCode { NORMAL = 0, DISCONNECT_SERIALPORT=1, ERROR = 3, } }