using System; using System.Collections.Generic; using System.IO.Ports; using System.Linq; using System.Text; using System.Threading; using System.Threading.Channels; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Xml.Serialization; using System.Windows.Threading; using System.Diagnostics; using System.Collections.ObjectModel; using SafeBagDE70.Model; using HandyControl.Tools; using System.Drawing.Printing; using System.Drawing; using static HandyControl.Tools.Interop.InteropValues; using SafeBagDE70.API; using Newtonsoft.Json; using System.IO; using System.Reflection; using DE70_CMDv2; using System.Configuration; using Serilog; using System.ComponentModel; using SafeBagDE70.StateMachine; using static System.Windows.Forms.VisualStyles.VisualStyleElement.Window; using System.Runtime.Intrinsics.Arm; using SafeBagDE70.Services; namespace SafeBagDE70 { //Summary public partial class DepositSMUC : UserControl { SerialPort serialPortDE70 = new SerialPort(); SerialPort serialPortSensor= new SerialPort(); List sessions = new List(); public ObservableCollection lvCountItems = new ObservableCollection(); private DispatcherTimer timer; private DispatcherTimer sensorTimer; int countTimer = 0; CCmdRsp cCmdRsp = null; bool bInitialized = false; private string? _currentState; private string? _prevState; public DepositSMUC() { InitializeComponent(); _currentState = App.StateMachineConfig.States.FirstOrDefault(); UpdateStateMessage(); } public string GetCurrentState() { return _currentState; } public string GetPrevioustState() { return _prevState; } private void UserControl_Loaded(object sender, RoutedEventArgs e) { InitTransaction(); } public void InitTransaction() { try { lblName.Content= "Vietinbank " + Environment.MachineName; if (AppData.IsAuthenticated) { lblUser.Content = $"Xin chào khách hàng: {AppData.CurrentCustomerAccount.Name} (Gian hàng {AppData.CurrentCustomerAccount.CustomerId})"; } cCmdRsp = new CCmdRsp(serialPortDE70); AppData.cCmdRsp = cCmdRsp; // LoginUsingQRCode(); InitSerialPorts(); //Subscrible to the DataReveied event\ bInitialized = InitSession(); InitTimers(); AppData.IsInTransaction = true; } catch (Exception ex) { ShowError("LỖI CỔNG KẾT NỐI, VUI LÒNG KIỂM TRA LẠI CỔNG KẾT NỐI"); } } private void InitSerialPorts() { InitSerialPortDE70(); InitSerialPortSensor(); } private void InitSerialPortSensor() { if (serialPortSensor.IsOpen) serialPortSensor.Close(); serialPortSensor.PortName = AppData.SensorPort; serialPortSensor.BaudRate = 9600; serialPortSensor.Parity = Parity.None; serialPortSensor.DataBits = 8; serialPortSensor.StopBits = StopBits.One; serialPortSensor.ReadTimeout = 1000; serialPortSensor.WriteTimeout = 1000; if (!serialPortSensor.IsOpen) serialPortSensor.Open(); } private void InitSerialPortDE70() { if (serialPortDE70.IsOpen) serialPortDE70.Close(); serialPortDE70.ReadBufferSize = 4096; serialPortDE70.WriteBufferSize = 4096; serialPortDE70.PortName = AppData.CDMPort; serialPortDE70.BaudRate = 9600; serialPortDE70.Parity = Parity.Even; serialPortDE70.DataBits = 8; serialPortDE70.StopBits = StopBits.One; serialPortDE70.ReadTimeout = 10000; serialPortDE70.WriteTimeout = 10000; if (!serialPortDE70.IsOpen) serialPortDE70.Open(); } private void InitTimers() { timer = new DispatcherTimer(); timer.Interval = new TimeSpan(0, 0, 10); //10 seconds timer.Tick += Timer_Tick; timer.Start(); sensorTimer = new DispatcherTimer(); sensorTimer.Interval = new TimeSpan(0, 0, 1); //1 seconds sensorTimer.Tick += SensorTimer_Tick; sensorTimer.Start(); } public void EndTransaction() { try { AppData.IsInTransaction = false; if (timer != null) { timer.Tick -= Timer_Tick; timer.Stop(); } if (sensorTimer != null) { sensorTimer.Tick -= SensorTimer_Tick; sensorTimer.Stop(); } } catch (Exception ex) { } } public void InitSessionCount() { if (lvCount.Items.Count == 11) { foreach(var item in lvCountItems) { item.Quantity = "0"; } } else { lvCountItems = new ObservableCollection() { new LvCountItem{Name = "500",Quantity = "0"}, new LvCountItem{Name = "1000",Quantity = "0"}, new LvCountItem{Name = "2000",Quantity = "0"}, new LvCountItem{Name = "5000",Quantity = "0"}, new LvCountItem{Name = "10000",Quantity = "0"}, new LvCountItem{Name = "20000",Quantity = "0"}, new LvCountItem{Name = "50000",Quantity = "0"}, new LvCountItem{Name = "100000",Quantity = "0"}, new LvCountItem{Name = "200000",Quantity = "0"}, new LvCountItem{Name = "500000",Quantity = "0"}, new LvCountItem{Name = "Tổng",Quantity = "0",Value="0"}, }; } lvCount.ItemsSource = lvCountItems; //lvCountItems[0].Quantity = "10"; } public long maxQuantitySheet = 10000; public int quantityStored = 0; public int totalAllDenominations = 0; public int posDenomi; public bool printerFlag = false; public static string? recvDataString; // public int[] TempQuantity = new int[10] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // public int[] TempNote = new int[5] { 0, 0, 0, 0, 0 }; // public int[] Notes = new int[5] { 0, 0, 0, 0, 0 }; public int countSensorTimer = 0; //PrinterManager printerManager = new PrinterManager(); private void SensorTimer_Tick(object? sender, EventArgs e) { try { timer.IsEnabled = false; //countSensorTimer++; //if(countSensorTimer%5==0) //{ // Log.Information("SensorTimer_Tick " + PrinterManager.IsPaperOut()); // PrinterManager.UpdateStatus(); // if (PrinterManager.IsNearPaperOut()) // { // ((MainWindow)Application.Current.MainWindow).ShowInformationScreen("ĐỀ NGHỊ BỔ SUNG GIẤY ĐỂ TIẾP TỤC", true); // } // else if (PrinterManager.IsPaperOut()) // { // ((MainWindow)Application.Current.MainWindow).ShowErrorScreen("HẾT GIẤY TRONG MÁY IN"); // } //} GetSensorValue(); if (_currentState=="End"||_currentState=="AutoEnd"||_currentState=="Logout") { if(countSensorTimer>=15) TransitionToState("Start"); countSensorTimer++; } else { countSensorTimer = 0; } if (AppData.IsInTransaction) { if (AppData.WDTCount == 30) { TransitionToState("Timeout"); //((MainWindow)Application.Current.MainWindow).ShowTimeoutScreen(); } else if (AppData.WDTCount == 60) { TransitionToState("AutoEnd"); //Nhận tiền và Kết thúc //DoStoreStart(); //EndSession(); //((MainWindow)Application.Current.MainWindow).ShowWelcomeScreen(); //AppData.IsInTransaction = false; //AppData.WDTCount = 0; } AppData.WDTCount++; } else { AppData.WDTCount = 0; } timer.IsEnabled = true; } catch (Exception ex) { Log.Fatal(ex, "Sensor_Timer"); } } Stopwatch watch = new Stopwatch(); private void GetSensorValue() { try { int state = 0; if (serialPortSensor.IsOpen == true) { //serialPortSensor.DiscardInBuffer(); //serialPortSensor.DiscardOutBuffer(); serialPortSensor.Write(new byte[] { (byte)'S', 13, 10 }, 0, 3); var buffer = new byte[16]; int n = serialPortSensor.Read(buffer, 0, buffer.Length); for (int i = 1; i < n - 1; i++) { if ((buffer[i] == 13) && (buffer[i + 1] == 10)) { state = buffer[i - 1] - 48; if (bInitialized) { if (state != 0) gridMain.IsEnabled = false; else gridMain.IsEnabled = true; } switch (state) { case 0: lblStatus.Content = "NGĂN KÉT: ĐÓNG, NGĂN TÚI: ĐÓNG"; break; case 1: lblStatus.Content = "NGĂN KÉT: ĐÓNG, NGĂN TÚI: MỞ"; break; case 2: lblStatus.Content = "NGĂN KÉT: MỞ, NGĂN TÚI: ĐÓNG"; break; case 3: lblStatus.Content = "NGĂN KÉT: MỞ, NGĂN TÚI: MỞ"; break; } if (state > 0) { TransitionToState("Maintainance"); } else { if(_currentState== "Maintainance") TransitionToState("Start"); //if (((MainWindow)Application.Current.MainWindow).IsMaintainanceScreen()) // ((MainWindow)Application.Current.MainWindow).BackScreen(); } break; } } // the code that you want to measure comes here watch.Stop(); var elapsedMs = watch.ElapsedMilliseconds; Debug.WriteLine(elapsedMs); watch.Start(); } } catch (Exception ex) { Log.Fatal(ex,"GetSensorValue"); if(serialPortSensor.IsOpen) serialPortSensor.Close(); serialPortSensor.Open(); serialPortSensor.DiscardInBuffer(); serialPortSensor.DiscardOutBuffer(); } } private void Timer_Tick(object? sender, EventArgs e) { timer.IsEnabled = false; APIModels.SendHealthCheck(); timer.IsEnabled = true; } public int UpdateTotalQuantity() { int total = 0; foreach (var item in lvCountItems) { if (item.Name != "Tổng") { int quantity = 0; if (int.TryParse(item.Quantity, out quantity)) { total += quantity; } } } return total; } public int AutoSerialGet() { try { int ret; ushort seri_num = 0; ushort get_num = 0; bool endflg = false; var countSession = new CountSession(); countSession.IsStored = false; sessions.Add(countSession); while (true) { AppData.WDTCount = 0; ret = cCmdRsp.SendSerialSense(); if (ret == Constants.E_OK) { ret = cCmdRsp.GetSerialNum(out seri_num); if (ret == Constants.E_OK) { // Serial number acquisition if (cCmdRsp.ChkCntEnd()) { endflg = true; //Debug.WriteLine("END FLAG: "+cCmdRsp.recv_dat.dat[1]); } //Debug.WriteLine("START"); //Debug.WriteLine($"Num Serial: {seri_num}"); //Log.Information($"Num Serial: {seri_num}"); while (get_num < seri_num) { AppData.WDTCount = 0; get_num++; Log.Information($"Serial Idx: {get_num}/{seri_num}"); ret = cCmdRsp.SendGetSerial(get_num); Log.Information($"Serial Status: {cCmdRsp.recv_dat.dat[18]}"); switch (cCmdRsp.recv_dat.dat[18]) { case 0x00: countSession.TempNotes[0]++;break; case 0x02: //TempNote[1] ++; Log.Information($"Serial Value: {cCmdRsp.recv_dat.dat[17]}"); switch (cCmdRsp.recv_dat.dat[17]) { //case 0x00: TempQuantity[0]++; break; //case 0x01: TempQuantity[1]++; break; //case 0x02: TempQuantity[2]++; break; //case 0x03: TempQuantity[3]++; break; //case 0x04: TempQuantity[4]++; break; //case 0x05: TempQuantity[5]++; break; //case 0x06: TempQuantity[6]++; break; //case 0x07: TempQuantity[7]++; break; //case 0x08: TempQuantity[8]++; break; //case 0x09: TempQuantity[9]++; break; case 0x00: countSession.QuantityDenomi[0]++; break; case 0x01: countSession.QuantityDenomi[1]++; break; case 0x02: countSession.QuantityDenomi[2]++; break; case 0x03: countSession.QuantityDenomi[3]++; break; case 0x04: countSession.QuantityDenomi[4]++; break; case 0x05: countSession.QuantityDenomi[5]++; break; case 0x06: countSession.QuantityDenomi[6]++; break; case 0x07: countSession.QuantityDenomi[7]++; break; case 0x08: countSession.QuantityDenomi[8]++; break; case 0x09: countSession.QuantityDenomi[9]++; break; } break; //case 0x03: TempNote[2] ++; Notes[2] += TempNote[2]; break; //case 0x0b: TempNote[3] ++; Notes[3] += TempNote[3]; break; //case 0x0c: TempNote[4] ++; Notes[4] += TempNote[4]; break; case 0x03: countSession.TempNotes[2]++; break; case 0x0b: countSession.TempNotes[3]++; break; case 0x0c: countSession.TempNotes[4]++; break; } UpdateListViewCountItems(); } //Debug.WriteLine("Ellapsed Time: " + timeSpan.TotalSeconds); if (endflg) { break; } } else { break; } } else { break; } } if (countSession.QuantityDenomi.Sum() == 0 && countSession.TempNotes.Sum() == 0) { sessions.Remove(countSession); } }catch(Exception ex) { Log.Fatal(ex, "AutoSerialGet"); } //Log.Information(JsonConvert.SerializeObject(sessions)); return 0; } private string GetShortInforFromCountItems() { return JsonConvert.SerializeObject(lvCountItems); } private bool CountStart() { bool bSuccess = true; printerFlag = false; string currentMethod = MethodBase.GetCurrentMethod().Name; try { serialPortDE70.DiscardInBuffer(); serialPortDE70.DiscardOutBuffer(); cCmdRsp.SendXXCmd((byte)Command.CMD_DE_CNTSTART); //var recvData = DE70_CMD.SendxxCmd((byte)CMD_BYTE.CMD_DE_CNTSTART, serialPort); //Thread.Sleep(20000); if (cCmdRsp.recv_dat != null && cCmdRsp.recv_dat.dat[2] != 43) { } do { serialPortDE70.DiscardInBuffer(); serialPortDE70.DiscardOutBuffer(); cCmdRsp.SendXXCmd((byte)Command.CMD_SENSE); } while (cCmdRsp.recv_dat != null && cCmdRsp.recv_dat.dat[1] == 0x09); //SR2 = 0x09 : Counting Status //SR3 = 0x43 : Stacker full Log.Information("Before AutoCount: " + GetShortInforFromCountItems()); Thread thread = new Thread(new ThreadStart(() => { AutoSerialGet(); })); thread.Start(); //InitSessionCount(); //UpdateListViewCountItems(); //if (sessions == null || sessions.Count == 0) //{ // double tempSum = 0; // for (int i = 0; i < 10; i++) // { // lvCountItems[i].Quantity = TempQuantity[9 - i].ToString(); // tempSum += lvCountItems[i].getValue(); // } // lvCountItems[10].Quantity = UpdateTotalQuantity().ToString(); // lvCountItems[10].Value = tempSum.ToString(); //} //else //{ // InitSessionCount(); // double sum = 0; // for (int i = 0; i < 10; i++) // { // int a = 0; // for (int j = 0; j < sessions.Count; j++) // { // a += sessions[j].QuantityDenomi[9 - i]; // } // a += TempQuantity[9 - i]; // lvCountItems[i].Quantity = a.ToString(); // sum += lvCountItems[i].getValue(); // } // //Update amount of money // lvCountItems[10].Quantity = UpdateTotalQuantity().ToString(); // lvCountItems[10].Value = sum.ToString(); //} Log.Information("After AutoCount: " + GetShortInforFromCountItems()); } catch (Exception ex) { bSuccess = false; Log.Fatal(ex,currentMethod); } return bSuccess; } private void UpdateListViewCountItems() { Dispatcher.Invoke(DispatcherPriority.Normal, () => { double sum = 0; if (sessions != null && sessions.Count > 0) { for (int i = 0; i < 10; i++) { int quantity = 0; for (int j = 0; j < sessions.Count; j++) { quantity += sessions[j].QuantityDenomi[9 - i]; } //a += TempQuantity[9 - i]; lvCountItems[i].Quantity = quantity.ToString(); sum += lvCountItems[i].getValue(); } //Update amount of money lvCountItems[10].Quantity = UpdateTotalQuantity().ToString(); lvCountItems[10].Value = sum.ToString(); } else { for (int i = 0; i < 11; i++) { lvCountItems[i].Quantity = "0"; lvCountItems[i].Value = "0"; } } }); } private bool DoCheck() { bool bSuccess = true; string currentMethod = MethodBase.GetCurrentMethod().Name; try { Log.Information("Before Check: "+GetShortInforFromCountItems()); serialPortDE70.DiscardInBuffer(); serialPortDE70.DiscardOutBuffer(); cCmdRsp.SendXXCmd((byte)Command.CMD_DE_CANCEL); Log.Information(JsonConvert.SerializeObject(sessions)); sessions.RemoveAll(item=>!item.IsStored); Log.Information(JsonConvert.SerializeObject(sessions)); UpdateListViewCountItems(); //double sumStored; //TempNote[1] = 0; //if (sessions != null) //{ // sumStored = 0; // for (int i = 0; i < 10; i++) // { // int a = 0; // for (int j = 0; j < sessions.Count; j++) // { // a += sessions[j].QuantityDenomi[9 - i]; // //quantityStored += lvCountItems[i].getQuantity(); // } // lvCountItems[i].Quantity = a.ToString(); // sumStored += lvCountItems[i].getValue(); // } // lvCountItems[10].Quantity = UpdateTotalQuantity().ToString(); // lvCountItems[10].Value = sumStored.ToString(); //} //else //{ // InitSessionCount(); //} Log.Information("After Check: "+GetShortInforFromCountItems()); } catch (Exception ex) { bSuccess = false; Log.Fatal(ex, currentMethod); } return bSuccess; } private bool WaitUntilEnscrowEmpty(int nSecondTimeout) { CDMSTATE state = null; int nTimes = 0; bool bSuccess = false; while(true) { state = GetCDMState(); if (state.IsNotesInEscrow == 0) { bSuccess = true; break; } nTimes++; Thread.Sleep(1000); if ((nSecondTimeout > 0) && nTimes >= nSecondTimeout) break; } return bSuccess; } private bool DoStoreStart() { bool bSuccess = true; printerFlag = true; string currentMethod = MethodBase.GetCurrentMethod().Name; try { serialPortDE70.DiscardInBuffer(); serialPortDE70.DiscardOutBuffer(); //sessions.Add(new CountSession()); // sessions[sessions.Count - 1].QuantityDenomi = (int[])TempQuantity.Clone(); foreach(var item in sessions) { item.IsStored = true; } quantityStored = UpdateTotalQuantity(); Log.Information("Stored "+GetShortInforFromCountItems()); //Debug.WriteLine(quantityStored); cCmdRsp.SendXXCmd((byte)Command.CMD_DE_STORESTART); bSuccess=WaitUntilEnscrowEmpty(10); } catch (Exception ex) { bSuccess = false; Log.Fatal(ex, currentMethod); } return bSuccess; } private bool DoStart() { bool bSuccess = true; InitSession(); string currentMethod = MethodBase.GetCurrentMethod().Name; AppData.IsInTransaction = true; try { serialPortDE70.DiscardInBuffer(); serialPortDE70.DiscardOutBuffer(); 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]); cCmdRsp.SendLock(); } } catch (Exception ex) { bSuccess = false; Log.Fatal(ex, currentMethod); } return bSuccess; } private bool DoEnd() { bool bSuccess = false; var state = GetCDMState(); Log.Information("CDM State: " + JsonConvert.SerializeObject(state)); if (state.IsNotesInEscrow > 0) { ((MainWindow)Application.Current.MainWindow).ShowInformationScreen("ĐỀ NGHỊ BỎ TIỀN TRONG NGĂN PHỤ HOẶC ẤN LƯU TRỮ ĐỂ TIẾP TỤC", true); } else if (state.IsNotesInRejectPocket > 0 || state.IsRejectPocketFull > 0) { ((MainWindow)Application.Current.MainWindow).ShowInformationScreen("ĐỀ NGHỊ BỎ TIỀN KHÔNG HỢP LỆ ĐỂ TIẾP TỤC", true); } else { bSuccess = true; AppData.WDTCount = 0; EndSession(); } return bSuccess; } private bool DoLogout() { bool bSuccess = false; var state = GetCDMState(); Log.Information("CDM State: " + JsonConvert.SerializeObject(state)); InitSessionCount(); if (state.IsNotesInEscrow > 0) { ((MainWindow)Application.Current.MainWindow).ShowInformationScreen("ĐỀ NGHỊ BỎ TIỀN TRONG NGĂN PHỤ HOẶC ẤN LƯU TRỮ ĐỂ TIẾP TỤC", true); } else if (state.IsNotesInRejectPocket > 0 || state.IsRejectPocketFull > 0) { ((MainWindow)Application.Current.MainWindow).ShowInformationScreen("ĐỀ NGHỊ BỎ TIỀN KHÔNG HỢP LỆ ĐỂ TIẾP TỤC", true); } else //if (double.Parse(lvCountItems[10].Value)== 0) { bSuccess = true; AppData.IsInTransaction = false; AppData.WDTCount = 0; EndSession(); ((MainWindow)Application.Current.MainWindow).ShowWelcomeScreen(); } return bSuccess; } private void EndSession() { string currentMethod = MethodBase.GetCurrentMethod().Name; var totalQuantity = lvCountItems[10].Quantity; var totalValue = lvCountItems[10].Value; try { Log.Information(currentMethod); serialPortDE70.DiscardInBuffer(); serialPortDE70.DiscardOutBuffer(); if (double.Parse(totalValue) > 0) { var data2Send = new CountingData2Send { TransactionCode = AppData.CurrentCustomerAccount.TransactionCode, Sessions = sessions, MachineId = Environment.MachineName, UserId = AppData.CurrentCustomerAccount.CustomerId, MachineTime = DateTime.Now.ToString("yyyyMMddHHmmss"), //RejectNotes = Notes[0], GenuineNotes = quantityStored, //UnfitNotes = Notes[2], //CounterfeitNotes = Notes[3], // SuspendNotes = Notes[4] }; SyncData(data2Send); //Reset all and ready to next session if (printerFlag == true) { if (double.Parse(totalValue) > 0) PrintReceipt(); printerFlag = false; } InitSession(); String strNotify = $"BẠN VỪA THỰC HIỆN TIỀN VÀO MÁY CDM:\r\n" + $"SỐ LƯỢNG TỜ: {totalQuantity}\r\n" + $"SỐ TIỀN: {totalValue} VND\r\n"; ((MainWindow)Application.Current.MainWindow).ShowInformationScreen(strNotify, false, false); AppData.WDTCount = 45; } //SendData2Server } catch (Exception ex) { Log.Fatal(ex, currentMethod); } } private async Task SyncData(CountingData2Send data2Send) { Log.Information("Saving data to DB: " + JsonConvert.SerializeObject(data2Send)); var history = Save2DB(data2Send); Log.Information("Sending data to server: "+JsonConvert.SerializeObject(data2Send)); bool bSuccess = await APIModels.SendCountingData(data2Send); if (bSuccess) { history.IsSent = true; Update2DB(history); Log.Information("Sending data to server successfully"); } else { Log.Information("Sending data to server failed"); } } public History Save2DB(CountingData2Send data2Send) { var data = JsonConvert.SerializeObject(data2Send); var history = new History { Data = data, DepositTime = DateTime.Now, IsSent = false, UserCode = AppData.CurrentCustomerAccount.CustomerId }; try { using (var db = new CDMDbContext()) { db.Histories.Add(history); db.SaveChanges(); } } catch (Exception ex) { Log.Fatal(ex,"Save2DB Exception"); } return history; } public History Update2DB(History history) { try { using (var db = new CDMDbContext()) { db.Histories.Update(history); db.SaveChanges(); } } catch (Exception ex) { Log.Fatal(ex,"Update2DB Exception"); } return history; } private void ShowError(string strError) { //gridMain.IsEnabled = false; //btnCollect2.Visibility=Visibility.Collapsed; //panelError.Visibility = Visibility.Visible; //lblError.Text = strError; //((MainWindow)Application.Current.MainWindow).ShowWelcomeScreen(); ((MainWindow)Application.Current.MainWindow).ShowErrorScreen(strError); } public class CDMSTATE { public int IsCassetteFull = 0; public int IsNotesInEscrow = 0; public int IsRejectPocketFull = 0; public int IsNotesInRejectPocket = 0; } private CDMSTATE GetCDMState() { 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; var cdmState = new CDMSTATE(); cdmState.IsCassetteFull = data[17] & 0x08; cdmState.IsNotesInEscrow = data[4] & 0x01; cdmState.IsRejectPocketFull = data[3] & 0x40; cdmState.IsNotesInRejectPocket = data[3] & 0x10; return cdmState; } private bool InitSession() { try { //Check status var cdmState = GetCDMState(); if (cdmState.IsCassetteFull != 0) { ((MainWindow)Application.Current.MainWindow).ShowCollectionScreen(); return false; } else if (cdmState.IsNotesInEscrow != 0) { ((MainWindow)Application.Current.MainWindow).ShowInformationScreen("ĐỀ NGHỊ BỎ TIỀN TRONG NGĂN PHỤ ĐỂ TIẾP TỤC"); } else { InitSessionCount(); sessions.Clear(); quantityStored = 0; maxQuantitySheet = 0; cCmdRsp.SendXXCmd((byte)Command.CMD_DE_UNLOCK); return true; } } catch(Exception ex) { Log.Fatal(ex,"InitSession"); } return false; } private void PrintReceipt() { Log.Information("PrintReceipt"); var shopName = AppData.CurrentCustomerAccount.Name; var shopCode = AppData.CurrentCustomerAccount.CustomerId; var tradingCode = AppData.CurrentCustomerAccount.TransactionCode;// "TRA04052024CDM"; var storeAccountNumber = 686868686688; var currentTime = DateTime.Now; var printDocument = new PrintDocument(); System.Drawing.Image LogoAeonMall = System.Drawing.Image.FromFile("Logo\\logoAeonmall.png"); System.Drawing.Image LogoVietin = System.Drawing.Image.FromFile("Logo\\logoVietin.png"); printDocument.PrinterSettings.PrinterName = "CUSTOM K80"; printDocument.PrintPage += (sender, e) => { int fontSize = 8; int lineSpace = 20; float marginLeft = 25; float marginTop = 5; float width = 275; float height = 280; float LogoAeonWidth = 90; // Chiều rộng của LogoAeon float LogoAeonHeight = 30; // Chiều cao của LogoAeon float LogoAeonX = marginLeft + 25; // Đặt LogoAeon ở giữa theo chiều ngang float LogoAeonY = marginTop + 10; // Khoảng cách từ mép trên của viền đến LogoAeon float LogoVietinWidth = 90; // Chiều rộng của LogoVietin float LogoVietinHeight = 30; // Chiều cao của LogoVietin float LogoVietinX = marginLeft + 165; // Đặt LogoVietin ở giữa theo chiều ngang float LogoVietinY = marginTop + 10; // Khoảng cách từ mép trên của viền đến LogoVietin e.Graphics.DrawImage(LogoVietin, LogoVietinX, LogoVietinY, LogoVietinWidth, LogoVietinHeight); e.Graphics.DrawImage(LogoAeonMall, LogoAeonX, LogoAeonY, LogoAeonWidth, LogoAeonHeight); e.Graphics.DrawImage(LogoVietin, LogoVietinX, LogoVietinY, LogoVietinWidth, LogoVietinHeight); e.Graphics.DrawImage(LogoAeonMall, LogoAeonX, LogoAeonY, LogoAeonWidth, LogoAeonHeight); e.Graphics.DrawRectangle(new System.Drawing.Pen(System.Drawing.Color.Black, 1), marginLeft, marginTop, width, height); e.Graphics.DrawString("Biên nhận nộp tiền", new Font("Arial", 12, System.Drawing.FontStyle.Bold), System.Drawing.Brushes.Black, new PointF(80, 50)); e.Graphics.DrawString("Mã máy CDM: "+Environment.MachineName, new Font("Arial", fontSize), System.Drawing.Brushes.Black, new PointF(50, lineSpace * 1 + 65)); e.Graphics.DrawString("Thời gian giao dịch: " + currentTime.ToString("dd/MM/yyyy HH:mm:ss"), new Font("Arial", fontSize), System.Drawing.Brushes.Black, new PointF(50, lineSpace * 2 + 65)); e.Graphics.DrawString("Mã giao dịch: " + tradingCode, new Font("Arial", fontSize), System.Drawing.Brushes.Black, new PointF(50, lineSpace * 3 + 65)); e.Graphics.DrawString("Mã Gian hàng: " + shopCode, new Font("Arial", fontSize), System.Drawing.Brushes.Black, new PointF(50, lineSpace * 4 + 65)); e.Graphics.DrawString("Tên Gian hàng: " + shopName, new Font("Arial", fontSize), System.Drawing.Brushes.Black, new PointF(50, lineSpace * 5 + 65)); e.Graphics.DrawString("Số tài khoản gian hàng: " + storeAccountNumber, new Font("Arial", fontSize), System.Drawing.Brushes.Black, new PointF(50, lineSpace * 6 + 65)); e.Graphics.DrawString("Nội dung giao dịch: Nop doanh so tien mat_", new Font("Arial", fontSize), System.Drawing.Brushes.Black, new PointF(50, lineSpace * 7 + 65)); e.Graphics.DrawString(shopCode, new Font("Arial", fontSize), System.Drawing.Brushes.Black, new PointF(50, lineSpace * 8 + 65)); e.Graphics.DrawString("Số tiền nộp: " + lvCountItems[10].Value, new Font("Arial", fontSize), System.Drawing.Brushes.Black, new PointF(50, lineSpace * 9 + 65)); e.Graphics.DrawString("*****Xin cám ơn*****", new Font("Arial", 7), System.Drawing.Brushes.Black, new PointF(120, lineSpace * 10 + 65)); // To send raw ESC/POS commands, you'd typically use e.Graphics.DrawString() with the command string, // or for more complex scenarios, directly manipulate the byte stream sent to the printer. }; printDocument.Print(); } private void UserControl_Unloaded(object sender, RoutedEventArgs e) { EndTransaction(); } private void DisableButtons() { btnStart.IsEnabled = false; btnCountStart.IsEnabled = false; btnCheck.IsEnabled = false; btnStoreStart.IsEnabled = false; btnEnd.IsEnabled = false; btnLogout.IsEnabled=false; } private void UpdateStateMessage() { // StateMessage.Text = $"Current State: {_processStateMachine.CurrentState}"; // Enable or disable buttons based on the current state and available transitions btnStart.IsEnabled = CanTransitionTo("Init", out _); btnCountStart.IsEnabled = CanTransitionTo("Count", out _); btnCheck.IsEnabled = CanTransitionTo("Check", out _); btnStoreStart.IsEnabled =CanTransitionTo("Store", out _); } private Button _previousClickedButton = null; private void btnCommon_Click(object sender, RoutedEventArgs e) { var btn = sender as Button; if (_previousClickedButton != null) { _previousClickedButton.BorderBrush = System.Windows.Media.Brushes.Transparent; _previousClickedButton.BorderThickness = new Thickness(1); } // Set the border of the currently clicked button btn.BorderBrush = System.Windows.Media.Brushes.DarkRed; btn.BorderThickness = new Thickness(3); // Update the previously clicked button reference _previousClickedButton = btn; SoundManager.StartButtonPressSound(); // Console.Beep(800, 200); AppData.WDTCount = 0; if (btn==btnStart) { TransitionToState("Init"); //Log.Information("Deposit starting"); //Log.Information("User: " + AppData.CurrentCustomerAccount.CustomerId); //Log.Information("1. Start starting"); //DoStart(); //Log.Information("1. Start completed"); //AppData.WDTCount = 0; } else if(btn==btnCountStart) { TransitionToState("Count"); //Log.Information("2. Count starting"); //CountStart(); //Log.Information("2. Count completed"); //AppData.WDTCount = 0; } else if(btn==btnCheck) { TransitionToState("Check"); //Log.Information($"3. Check starting"); //DoCheck(); //Log.Information($"3. Check completed"); //AppData.WDTCount = 0; } else if (btn == btnStoreStart) { TransitionToState("Store"); //Log.Information("4. Store starting"); //DoStoreStart(); //Log.Information("4. Store completed"); //AppData.WDTCount = 0; } else if (btn == btnEnd) { TransitionToState("End"); //Log.Information("5. End starting"); //DoEnd(); //Log.Information("5. End Completed"); } else if (btn == btnLogout) { TransitionToState("Logout"); //Log.Information("6. Exit starting"); //DoLogout(); //Log.Information("6. Exit Completed"); } } public string CurrentState => _currentState; public bool CanTransitionTo(string newState, out Transition transition) { transition = App.StateMachineConfig.Transitions .FirstOrDefault(t => t.From.Contains(_currentState) && t.To.Contains(newState)); return transition != null; } public void TransitionToState(string newState) { Log.Information("State changing to: " + newState); if (CanTransitionTo(newState, out Transition transition)) { if (ExecuteActions(transition)) { // Transition to the new state if the required condition is met _prevState = _currentState; _currentState = newState; Log.Information("State changed to: " + newState); } else { Log.Error($"Failed to meet action requirements. Staying in {_currentState}."); } } else { Log.Error($"Cannot transition from {_currentState} to {newState}"); } UpdateStateMessage(); } private bool ExecuteActions(Transition transition) { bool allRequiredActionsSucceeded = true; bool atLeastOneActionSucceeded = false; foreach (var action in transition.Actions) { bool success = ExecuteAction(action.Name); if (success) { atLeastOneActionSucceeded = true; } if (action.IsRequired && !success) { allRequiredActionsSucceeded = false; } } // Determine if the transition should happen based on the condition if (transition.RequireAtLeastOneActionSuccess) { return atLeastOneActionSucceeded; } else { return allRequiredActionsSucceeded; } } private bool ExecuteAction(string actionName) { // Simulate action execution based on the action name //Console.WriteLine($"Executing action: {App.StateMachineConfig.Actions[actionName]}"); Log.Information("Action: "+actionName); bool bSuccess = true; switch (actionName) { case "DoInit": bSuccess=DoStart(); break; case "DoCount": bSuccess = CountStart(); break; case "DoCheck": bSuccess = DoCheck(); break; case "DoStore": bSuccess = DoStoreStart(); break; case "DoLogout": bSuccess = DoLogout(); break; case "ShowTimeoutScreen": ((MainWindow)Application.Current.MainWindow).ShowTimeoutScreen(); break; case "ShowWelcomeScreen": ((MainWindow)Application.Current.MainWindow).ShowWelcomeScreen(); break; case "ShowMaintainanceScreen": ((MainWindow)Application.Current.MainWindow).ShowMaintainanceScreen(); break; case "BackScreen": ((MainWindow)Application.Current.MainWindow).BackScreen(); break; case "DoEnd": bSuccess = DoEnd(); break; } // For the sake of this example, all actions succeed return bSuccess; } } }