using Edge.Core.Processor;using Edge.Core.IndustryStandardInterface.Pump; using NozzleLockConfiguration; using SinochemCarplateService.Models; using SinochemCloudClient.Models; using SinochemInternetPlusApp.EpsTrxCleanup; using SinochemPosClient.Models; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using System.Xml.Serialization; using Wayne.FDCPOSLibrary; using Wayne.Lib.Log; using WayneChina_IcCardReader_SinoChem.MessageEntity; using WayneChina_IcCardReader_SinoChem.MessageEntity.Incoming; using Global_Pump_Fdc; using System.Threading.Tasks; using Wayne.Lib; namespace SinochemInternetPlusApp { public class Eps : IDisposable { private List fuelingPoints; private Dictionary> fuelingPointNozzlesDict = new Dictionary>(); private Dictionary> openTrxNozzleDict = new Dictionary>(); private EpsTrxCleanupManager epsTrxCleanupManager; protected DebugLogger debugLogger; private int requestId; private object requestSyncObj = new object(); #region devices and services private Sinochem_CarPlateRecognizeCamera_HuLianWangJia.Handler carPlateServer; private IEnumerable cardReaderHandlers; private PumpGroupHandler globalPumpGroup; //private FdcCommunicator fccClient; private CloudManager cloudManager; private PosManager posManger; private object openTrxSyncObj = new object(); private Dictionary fpSqNoDict = new Dictionary(); private IEnumerable processors; private IEnumerable pumpControllers; #endregion static NLog.Logger logger = NLog.LogManager.LoadConfiguration("nlog.config").GetLogger("SinochemEpsApp"); #region constants public int InvalidNozzleId { get { return 9999; } } #endregion ForecourtTrxManager forecourtTrxManager; private Dictionary nozzleMappingGradeName { get; set; } = new Dictionary(); #region Constructor public Eps(IEnumerable fpIds, Dictionary> fpNozzlesDict, IEnumerable processors) { var identifiableEntity = new IdentifiableEntity(0, "EpsMain", "", null); debugLogger = new DebugLogger(identifiableEntity); fuelingPoints = new List(fpIds.Count()); foreach (int fpId in fpIds) { fuelingPoints.Add(new FuelingPoint(fpId, fpNozzlesDict[fpId], this)); } fuelingPointNozzlesDict = fpNozzlesDict; epsTrxCleanupManager = new EpsTrxCleanupManager(this); cloudManager = new CloudManager(); posManger = new PosManager(); NozzleLockAccessor.FillinNozzles(fpNozzlesDict); this.processors = processors; var pumpControllerList = new List(); foreach (dynamic processor in processors) { if (processor is IAppProcessor) continue; var handler = processor.Context.Handler; if (handler is IEnumerable) { pumpControllerList.AddRange(handler); } } pumpControllers = pumpControllerList; debugLogger.Add("Eps has been constructed"); //logger.Info("Eps has been constructed"); logger.Info(string.Format($"{this.processors.Count()} processors were loaded.")); foreach (var proc in this.processors) { logger.Info(proc.GetType().ToString()); } forecourtTrxManager = new ForecourtTrxManager(pumpControllers, GenericSinochemEpsApp.PumpSideMapping, GenericSinochemEpsApp.ForceMappingFusionHoseToHuiTianHoseStr,GenericSinochemEpsApp.PosDatabaseConnString, GenericSinochemEpsApp.RawProductNameToPosProductNameStr); forecourtTrxManager.Init(); nozzleMappingGradeName = forecourtTrxManager.GetNozzleFuelMapping(); } internal TrxNotificationResponse NotifySuccessfulTrxToPos(EpsTransactionModel model, DebugLogger debugLogger) { return posManger.NotifyPosSuccessfulTrx(model, debugLogger); } internal PaymentResponse SendPaymentToCloud(EpsTransactionModel currentEpsTrxModel, DebugLogger debugLogger) { return cloudManager.Payment(currentEpsTrxModel, debugLogger); } internal BalanceInquiryResponse SendBalanceInquiryToCloud(string cardNo, string encryptedPin, string tid, int nozzleId, DebugLogger debugLogger) { return cloudManager.BalanceInquiry(cardNo, encryptedPin, tid, nozzleId, debugLogger); } #endregion public void Run() { fpSqNoDict.Clear(); SetupICCardReaderHandler(); if (fuelingPoints != null) { foreach (var fp in fuelingPoints) { if (!fpSqNoDict.ContainsKey(fp.FuelingPointId)) { fpSqNoDict.Add(fp.FuelingPointId, 0); } fp.Start(); } } epsTrxCleanupManager.Start(); SetupFccClient(); SetupCarplateServer(); } private void SetupFccClient() { foreach (var pumpController in pumpControllers) { pumpController.OnStateChange += (s, a) => { var pump = s as IFdcPumpController; if (a.NewPumpState == LogicalDeviceState.FDC_CALLING) { logger.Info($"Pump {pump.PumpId} at state CALLING"); int sitewiseNozzleId = SiteConfigUtility.Default.GetSiteLevelNozzleIdByLogicalNozzleId(pump.PumpId, a.StateChangedNozzles.FirstOrDefault()?.LogicalId ?? 0); FccClient_NozzleLifted(sitewiseNozzleId, pump); } else if (a.NewPumpState == LogicalDeviceState.FDC_READY) { int sitewiseNozzleId = 0; if (a.StateChangedNozzles != null) { SiteConfigUtility.Default.GetSiteLevelNozzleIdByLogicalNozzleId(pump.PumpId, a.StateChangedNozzles.FirstOrDefault()?.LogicalId ?? 0); } else { logger.Info("StateChangeNozzles null, use sitewiseNozzleId 0"); } logger.Info($"Pump {pump.PumpId} at state: FDC_READY, siteWiseNozzleId: {sitewiseNozzleId}"); FccClient_NozzleReplaced(sitewiseNozzleId, pump.PumpId); } else if (a.NewPumpState == LogicalDeviceState.FDC_AUTHORISED) { int sitewiseNozzleId = SiteConfigUtility.Default.GetSiteLevelNozzleIdByLogicalNozzleId(pump.PumpId, a.StateChangedNozzles.FirstOrDefault()?.LogicalId ?? 0); logger.Info($"Pump {pump.PumpId} at state FDC_AUTHORISED, siteWiseNozzleId: {sitewiseNozzleId}"); FccClient_AuthOk(sitewiseNozzleId, 1999); } else if (a.NewPumpState == LogicalDeviceState.FDC_FUELLING) { logger.Info($"Pump {pump.PumpId} is fueling"); } }; pumpController.OnCurrentFuellingStatusChange += (s, a) => { var pump = s as IFdcPumpController; if (a.Transaction.Finished) { int sitewiseNozzleId = SiteConfigUtility.Default.GetSiteLevelNozzleIdByLogicalNozzleId(pump.PumpId, a.Transaction.Nozzle.LogicalId); logger.Info($"Pump {pump.PumpId} fueling finished, siteWiseNozzleId: {sitewiseNozzleId}, amount: {a.Transaction.Amount}"); FccClient_NozzleReplaced(sitewiseNozzleId, pump.PumpId); FccClient_FuelingDone(sitewiseNozzleId, a.Transaction.SequenceNumberGeneratedOnPhysicalPump, Convert.ToDecimal(a.Transaction.Amount / Math.Pow(10, pump.VolumeDecimalDigits)), Convert.ToDecimal(a.Transaction.Volumn / Math.Pow(10, pump.VolumeDecimalDigits)), 1999); } }; Console.WriteLine($"setup fcc client pump done for {pumpController.PumpId}"); } } private void Pump_OnStateChange(object sender, FdcPumpControllerOnStateChangeEventArg e) { throw new NotImplementedException(); } private void Pump_OnCurrentFuellingStatusChange(object sender, FdcTransactionDoneEventArg e) { throw new NotImplementedException(); } // find car plate handler and listen to the new car plate event private void SetupCarplateServer() { var carPlateProcessors = processors.OfType>>(); carPlateServer = carPlateProcessors.Select(proc => (Sinochem_CarPlateRecognizeCamera_HuLianWangJia.Handler)proc.Context.Handler) .FirstOrDefault(); if (carPlateServer != null) { carPlateServer.NewCarPlateScanned += CarPlateServer_NewCarPlateScanned; carPlateServer.QRCodePaid += CarPlateServer_QRCodePaid; carPlateServer.IndoorPaid += CarPlateServer_IndoorPaid; carPlateServer.OnMessageReceivedViaFdc += (msg) => { logger.Info($"fdc message:\n {msg}"); if (msg.Length > 10 && msg.StartsWith("("DisplayResponse ACK", OverallResult.Success); }; } else { Console.WriteLine("carPlateServer not found!!!"); debugLogger.Add("carPlateServer not found!!!"); } } /// /// /// /// private void CarPlateServer_NewCarPlateScanned(CarPlateTrxRequest request) { int sitewiseNozzleId = InvalidNozzleId; try { sitewiseNozzleId = int.Parse(request.gun); } catch(Exception ex) { logger.Error(ex.ToString()); } if (IsNozzleConfiguredOpen(sitewiseNozzleId)) { var fp = GetFp(sitewiseNozzleId); fp?.SignalNewCarplate(request); } else { debugLogger.Add (string.Format($"Physical nozzle# {sitewiseNozzleId} is closed, so we ignore the car plate event!!!")); } } private void CarPlateServer_QRCodePaid(QRCodePayResultRequest request) { logger.Info("CarPlateServer_QRCodePaid"); ThreadPool.QueueUserWorkItem(o => { if (request != null) { logger.Info($"CarPlateServer_QRCodePaid, ttc:{request.ttc}, nozzleId:{request.nozzleId}, status: {request.status}, openId:{request.openId}"); EpsTransactionModel epsTrxModel = EpsTransactionQuery.GetEpsTrxByTTC(request.ttc, request.nozzleId); if (epsTrxModel != null && epsTrxModel.trx_status != EpsTrxStatus.PaymentOk) { EpsTransaction epsTrx = EpsTransaction.RestroeEpsTrxFrom(epsTrxModel); if (request.status == "1") { EpsTransactionQuery.UpdateEpsTrxByttc(request.ttc, request.nozzleId, request.amount, request.openId, "07_pos", EpsTrxStatus.PaymentOk); //delete xiaofei2 EpsTransactionQuery.DeleteXiaoFei2(epsTrxModel.liushuino, request.nozzleId); MultiFusionsSupport.DeleteXiaofei2FromTargetFusion(request.nozzleId, epsTrxModel.liushuino, debugLogger); //notify POS TrxNotificationResponse response = NotifySuccessfulTrxToPos(EpsTransactionQuery.RefreshEpsTrx(epsTrx.Model.id), debugLogger); if (response != null && response.IsSuccessful()) { epsTrx.UpdateNotifyPosFlagToDb(NotifyPosFlag.NotifyOk); } } else { epsTrx.UpdateTrxStatusToDb(EpsTrxStatus.PaymentFailed); } //broadcast the trx to big screen BroadCastTrxCompleteToBigScreen(request.nozzleId); } } }); } private void CarPlateServer_IndoorPaid(IndoorPayResultRequest request) { logger.Info("CarPlateServer_IndoorPaid"); ThreadPool.QueueUserWorkItem(o => { if (request != null) { logger.Info($"CarPlateServer_IndoorPaid, ttc:{request.liushuino}, nozzleId:{request.nozzleId}"); EpsTransactionModel epsTrxModel = EpsTransactionQuery.GetEpsTrxByLiuShuiNO(request.liushuino, request.nozzleId); if (epsTrxModel != null) { EpsTransactionQuery.UpdateEpsTrxByliushuino(request.liushuino, request.nozzleId, request.amount, EpsTrxStatus.PaymentOk); BroadCastTrxCompleteToBigScreen(request.nozzleId); } } }); } private void BroadCastTrxCompleteToBigScreen(int nozzleId) { //broadcast to big screen var fp = GetFp(nozzleId); var validTrx = EpsTransactionQuery.GetValidCarPlateEpsTrxModels( fp.GetAllNozzlesOnThisSide(), ConfigurationValues.AlreadyDoneEpsTrxCountPerDisplay, fp.DebugLogger); var availableNozzleInfo = fp.GetAvailableNozzleInfo(); if (availableNozzleInfo != null) { foreach (var trx in validTrx) { if (trx.trx_status == EpsTrxStatus.BeforeFueling || trx.trx_status == EpsTrxStatus.Fueling) { trx.AvailableNozzleGrade = availableNozzleInfo; } } } var text = fp.Eps.CreateDisplayTrxCommand(validTrx, out requestId, 0); if (fp.Eps.CarPlateHandler != null) { fp.Eps.CarPlateHandler.BroadcastMessageViaFdc(text); } } /// /// Get the pairs "nozzleId, gradeName" for the available FP on this side /// public Dictionary NozzleMappingGradeName() { return nozzleMappingGradeName; //Mapping grade name & nozzleId } public PumpState GetFPState(int fpId) { foreach (var pump in pumpControllers) { if (pump.PumpId == fpId) { var state = pump.QueryStatusAsync().Result; if (state == LogicalDeviceState.FDC_CALLING) return PumpState.Calling; else if (state == LogicalDeviceState.FDC_AUTHORISED) return PumpState.Authorized; else if (state == LogicalDeviceState.FDC_FUELLING) return PumpState.Fuelling; else if (state == LogicalDeviceState.FDC_READY) return PumpState.Idle; else if (state == LogicalDeviceState.FDC_CLOSED) return PumpState.Closed; } } return PumpState.Unknown; } private void SetupICCardReaderHandler() { var icCardReaderProcessors = processors.OfType>(); cardReaderHandlers = icCardReaderProcessors.Select(proc => (WayneChina_IcCardReader_SinoChem.Handler)proc.Context.Handler); if (cardReaderHandlers != null && cardReaderHandlers.Count() > 0) { Console.WriteLine($"Card reader handlers count: {cardReaderHandlers.Count()} "); foreach (var handler in cardReaderHandlers) { handler.OnCardReaderMessageReceived += Handler_OnCardReaderMessageReceived; } } else { Console.WriteLine("card reader handlers not found!!"); logger.Info("card reader handlers not found!!"); } } private void Handler_OnCardReaderMessageReceived(object sender, WayneChina_IcCardReader_SinoChem.CardReaderMessageEventArgs e) { //debugLogger.AddIfActive($"Receiving Card Reader message {e.CardReaderMessage.GetType().ToString()} for FP id = {e.FuelingPointId}"); var latestSqNo = GetCurrentSqNoForFp(e.FuelingPointId); //debugLogger.AddIfActive($"latestSqNo {latestSqNo}"); if (latestSqNo.HasValue) { var currentSqNo = e.CardReaderMessage.MessageSeqNumber; if (latestSqNo.Value != currentSqNo || currentSqNo == 0) { //Update the current sequence number for the designated fueling point. fpSqNoDict[e.FuelingPointId] = currentSqNo; var targetFP = fuelingPoints.First(_ => _.FuelingPointId == e.FuelingPointId);//GetFp(e.NozzleId); if (e.CardReaderMessage is ACK) { targetFP?.SingalAckReceived((ACK)e.CardReaderMessage); } else if (e.CardReaderMessage is SignDataResponse) { targetFP?.SignalSignedDataArrived((SignDataResponse)e.CardReaderMessage); } else if (e.CardReaderMessage is CardReaderStateEvent) { targetFP?.SingalCardReaderStateEvent((CardReaderStateEvent)e.CardReaderMessage); } else if (e.CardReaderMessage is CardExternalCheckErrorRequest) { targetFP?.SignalCardExternalCheckFailure((CardExternalCheckErrorRequest)e.CardReaderMessage); } else if (e.CardReaderMessage is CardOnlineVerificationRequest) { targetFP?.SignalCardOnlineVerification((CardOnlineVerificationRequest)e.CardReaderMessage); } else if (e.CardReaderMessage is HeartBeat) { targetFP?.SignalCardReaderHeartbeat((HeartBeat)e.CardReaderMessage); } } //If the sequence number of the received message is the same as the latest stored sequence number, //it's probably a re-send from the terminal. else { //2019-06-25, Card reader side updated SqNo as error code in Heartbeat. if (e.CardReaderMessage is HeartBeat) { var targetFP = fuelingPoints.First(_ => _.FuelingPointId == e.FuelingPointId);//GetFp(e.NozzleId); targetFP?.SignalCardReaderHeartbeat((HeartBeat)e.CardReaderMessage); } else { logger.Info($"A repeated message from terminal: {e}"); var targetFP = fuelingPoints.First(_ => _.FuelingPointId == e.FuelingPointId);//GetFp(e.NozzleId); targetFP?.SignalRepeatedMessageRecieved(e.CardReaderMessage); return; } } } } private byte? GetCurrentSqNoForFp(int fpId) { if (fpSqNoDict.ContainsKey(fpId)) { return fpSqNoDict[fpId]; } else { return null; } } #region Cloud interactions internal RefundResponse SendRefundToCloud(EpsTransactionModel trxModel, DebugLogger debugLogger) { return cloudManager.Refund(trxModel, debugLogger); } internal TrxStatusInquiryResponse SendTrxQueryToCloud(EpsTransactionModel trxModel, DebugLogger debugLogger) { return cloudManager.TrxStatusInquiry(trxModel, debugLogger); } #endregion #region FDC client interactions private void FccClient_NozzleReplaced(int sitewiseNozzleId, int pumpId) { if (sitewiseNozzleId != 0) { var fp = GetFp(sitewiseNozzleId); fp?.SignalNozzleReplaced(sitewiseNozzleId, pumpId); } else { var fp = GetFuelingPoint(pumpId); fp?.SignalNozzleReplaced(sitewiseNozzleId, pumpId); } } private void FccClient_AuthFailed(int sitewiseNozzleId) { var fp = GetFp(sitewiseNozzleId); fp?.SignalAuthFailed(); } private void FccClient_AuthOk(int sitewiseNozzleId, long? authId) { var fp = GetFp(sitewiseNozzleId); fp?.SignalAuthOk(authId); } private void FccClient_NozzleLifted(int sitewiseNozzleId, IFdcPumpController callingPump) { logger.Info($"SiteNozzle number: {sitewiseNozzleId}, from Pump {callingPump.PumpId} lifted"); if (IsNozzleConfiguredOpen(sitewiseNozzleId)) { var fp = GetFp(sitewiseNozzleId); fp?.SignalNozzleLifted(callingPump, sitewiseNozzleId); } else { logger.Info(string.Format($"Physical nozzle# {sitewiseNozzleId} is closed, so we ignore the nozzle lift event!!!")); } } private bool IsNozzleConfiguredOpen(int sitewiseNozzleId) { return !NozzleLockAccessor.IsNozzleClosedInTermsOfSale(sitewiseNozzleId); } private void FccClient_FuelingDone(int sitewiseNozzleId, int seqNum, decimal fuelAmount, decimal fuelingQty, long authId) { var fp = GetFp(sitewiseNozzleId); fp?.SignalFuelingDone(sitewiseNozzleId, seqNum, fuelAmount, fuelingQty, authId); } public void AuthorizePumpAsync(IFdcPumpController callingPump, int sitewiseNozzleId, decimal authAmount) { //Have to put pump auth in a different thread due to FC reasons, 2019/06/19 Task.Run(() => { LogicalNozzle logicalNozzle = callingPump.Nozzles.First(); foreach (var nozzle in callingPump.Nozzles) { if (SiteConfigUtility.Default.GetSiteLevelNozzleIdByLogicalNozzleId(callingPump.PumpId, Convert.ToInt32(nozzle.LogicalId)) == sitewiseNozzleId) { logicalNozzle = nozzle; } } callingPump.AuthorizeWithAmountAsync((int)((double)authAmount * Math.Pow(10, callingPump.AmountDecimalDigits)), logicalNozzle.LogicalId); }); } #endregion private void TeardownFccClient() { //if (fccClient != null) //{ // fccClient.NozzleLifted -= FccClient_NozzleLifted; // fccClient.NozzleReplaced -= FccClient_NozzleReplaced; // fccClient.AuthOk -= FccClient_AuthOk; // fccClient.AuthFailed -= FccClient_AuthFailed; // fccClient.FuelingDone -= FccClient_FuelingDone; //} } public void Shutdown() { TeardownCarplateServer(); TeardownCardReaderHandler(); if (fuelingPoints != null) { foreach (var fp in fuelingPoints) { fp.SignalShutdown(); } } } public WayneChina_IcCardReader_SinoChem.Handler GetHandler(int fuelingPointId) { //debugLogger.AddIfActive($"Trying to get card reader handler for fueling point: {fuelingPointId}"); foreach (var handler in cardReaderHandlers) { if (handler.SupportedNozzles.Contains(fuelingPointId)) return handler; } return null; } private void TeardownCarplateServer() { if (carPlateServer != null) { carPlateServer.NewCarPlateScanned -= CarPlateServer_NewCarPlateScanned; carPlateServer.QRCodePaid -= CarPlateServer_QRCodePaid; carPlateServer.IndoorPaid -= CarPlateServer_IndoorPaid; } } private void TeardownCardReaderHandler() { if (cardReaderHandlers != null) { foreach (var handler in cardReaderHandlers) { handler.OnCardReaderMessageReceived -= Handler_OnCardReaderMessageReceived; } } } public Sinochem_CarPlateRecognizeCamera_HuLianWangJia.Handler CarPlateHandler => carPlateServer; public WayneChina_IcCardReader_SinoChem.Handler GetCardReader(int nozzleId) { return cardReaderHandlers.FirstOrDefault(h => h.SupportedNozzles.Contains(nozzleId)); } public FuelingPoint GetFp(int nozzleId) { foreach (var fp in fuelingPoints) { if (fp.AssociatedNozzles != null && fp.AssociatedNozzles.Contains(nozzleId)) return fp; } return null; } public FuelingPoint GetFuelingPoint(int fpId) { return fuelingPoints?.FirstOrDefault(_ => fpId == _.FuelingPointId); } public int GetNextRequestId() { lock (requestSyncObj) { if (requestId == int.MaxValue) { requestId = 0; } return requestId++; } } /// /// /// /// /// /// /// public string CreateDisplayTrxCommand(IEnumerable epsTrxList, out int requestId, int i) { Display display; string cmdText = ""; XmlSerializer serializer = new XmlSerializer(typeof(Display)); MemoryStream ms; StreamReader sr; display = new Display(); display.ScreenType = ScreenType.ShowTrxList; display.RequestId = GetNextRequestId(); display.TimeoutSpecified = true; display.Timeout = 300; requestId = display.RequestId; display.PumpInfo = new DisplayPumpInfo { Id = 1, NozzleId = 1 }; int count = epsTrxList.Count(); display.TrxList = new DisplayTrx[epsTrxList.Count()]; for (int index = 0; index < count; index++) { display.TrxList[index] = ConvertEpsTrxModelToDisplayTrx(epsTrxList.ToArray()[index]); } ms = new MemoryStream(); serializer.Serialize(ms, display); ms.Position = 0; sr = new StreamReader(ms, true); cmdText = sr.ReadToEnd(); ms.Close(); sr.Close(); return cmdText; } public DisplayTrx ConvertEpsTrxModelToDisplayTrx(EpsTransactionModel epsTrxModel) { TrxStatus state = TrxStatus.ReadyForFillingStart; if (epsTrxModel.trx_status == EpsTrxStatus.BeforeFueling) state = TrxStatus.ReadyForFillingStart; else if (epsTrxModel.trx_status == EpsTrxStatus.BeforePayment) state = TrxStatus.PendingForPayment; else if (epsTrxModel.trx_status == EpsTrxStatus.Fueling) state = TrxStatus.FillingOngoing; else if (epsTrxModel.trx_status == EpsTrxStatus.FuelingDone) state = TrxStatus.PendingForPayment; else if (epsTrxModel.trx_status == EpsTrxStatus.PaymentOk) state = TrxStatus.Success; else if (epsTrxModel.trx_status == EpsTrxStatus.PaymentFailed) state = TrxStatus.Failed; else if (epsTrxModel.trx_status == EpsTrxStatus.PaymentNeedConfirm) state = TrxStatus.Failed; else if (epsTrxModel.trx_status == EpsTrxStatus.PaymentOkButNeedRefund) state = TrxStatus.Failed; else if (epsTrxModel.trx_status == EpsTrxStatus.PaymentRefunded) state = TrxStatus.Failed; var displayTrx = new DisplayTrx { Id = epsTrxModel.id.ToString(), State = state, TimeStamp = new DisplayTrxTimeStamp { StartTime = epsTrxModel.created_time, FinishTime = string.IsNullOrEmpty(epsTrxModel.xf_time) ? epsTrxModel.created_time : Utilities.CombineDateAndTime(epsTrxModel.xf_date, epsTrxModel.xf_time) }, MemberInfo = new DisplayTrxMemberInfo { Id = epsTrxModel.cardNo_masked, LicensePlateNo = epsTrxModel.car_number }, FillingInfo = new DisplayTrxFillingInfo { PumpId = 1, NozzleId = epsTrxModel.jihao, ProductNo = 1, UnitPrice = (decimal)epsTrxModel.danjia, ProductType = epsTrxModel.youpin, ProductDiscription = "汽油", Amount = (decimal)epsTrxModel.amount, AmountPaid = (decimal)epsTrxModel.real_pay_amount, Volume = (decimal)epsTrxModel.qty, NozzleSelected = epsTrxModel.nozzleSelected, } }; if (epsTrxModel.AvailableNozzleGrade != null) { displayTrx.NozzleList = new DisplayTrxNozzle[epsTrxModel.AvailableNozzleGrade.Count]; int index = 0; foreach (var pair in epsTrxModel.AvailableNozzleGrade) { displayTrx.NozzleList[index] = new DisplayTrxNozzle { NozzleId = pair.Key, Prompt = pair.Key.ToString() + "号枪" +pair.Value, }; index++; } } return displayTrx; } public string CreateDisplayCommand(ScreenType screenType) { Display display; string cmdText = ""; XmlSerializer serializer = new XmlSerializer(typeof(Display)); MemoryStream ms; StreamReader sr; switch (screenType) { case ScreenType.Idle: display = new Display(); display.ScreenType = screenType; display.CompanyContactInfo = new DisplayCompanyContactInfo { Tel = "010-59569575", Address = "世界500强企业\n中国第四大国家石油公司" }; display.StationInfo = new DisplayStationInfo { StationNo = "000001", StationName = "沈阳望花中街加油加气站" }; display.PumpInfo = new DisplayPumpInfo { Id = 1, NozzleId = 1 }; ms = new MemoryStream(); serializer.Serialize(ms, display); ms.Position = 0; sr = new StreamReader(ms, true); cmdText = sr.ReadToEnd(); break; case ScreenType.Welcome: display = new Display(); display.ScreenType = screenType; display.CompanyContactInfo = new DisplayCompanyContactInfo { Tel = "010-59569575", Address = "世界500强企业\n中国第四大国家石油公司" }; display.MemberInfo = new DisplayMemberInfo { LicensePlateNo = "京A88888", Id = "1234567" }; display.PumpInfo = new DisplayPumpInfo { Id = 1, NozzleId = 1 }; ms = new MemoryStream(); serializer.Serialize(ms, display); ms.Position = 0; sr = new StreamReader(ms, true); cmdText = sr.ReadToEnd(); break; case ScreenType.ShowTrxList: display = new Display(); display.ScreenType = screenType; display.PumpInfo = new DisplayPumpInfo { Id = 1, NozzleId = 1 }; display.TrxList = new DisplayTrx[] { new DisplayTrx { Id = "100", FillingInfo = new DisplayTrxFillingInfo { Amount = 200, NozzleId = 1, ProductType = "95#", UnitPrice = 6.78m, Volume = 35, ProductDiscription = "汽油" }, MemberInfo = new DisplayTrxMemberInfo { LicensePlateNo = "京A88888", Id = "1234567" }, State = TrxStatus.Success, TimeStamp = new DisplayTrxTimeStamp { StartTime = DateTime.Now, FinishTime =DateTime.Now } }, new DisplayTrx { Id = "101", FillingInfo = new DisplayTrxFillingInfo { Amount = 211, NozzleId = 1, ProductType = "95#", UnitPrice = 6.78m, Volume = 35, ProductDiscription = "汽油" }, MemberInfo = new DisplayTrxMemberInfo { LicensePlateNo = "京A88888", Id = "1234567" }, State = TrxStatus.Success, TimeStamp = new DisplayTrxTimeStamp { StartTime = DateTime.Now, FinishTime =DateTime.Now } }, new DisplayTrx { Id = "102", FillingInfo = new DisplayTrxFillingInfo { Amount = 222, NozzleId = 1, ProductType = "95#", UnitPrice = 6.78m, Volume = 35, ProductDiscription = "汽油" }, MemberInfo = new DisplayTrxMemberInfo { LicensePlateNo = "京A88888", Id = "1234567" }, State = TrxStatus.Success, TimeStamp = new DisplayTrxTimeStamp { StartTime = DateTime.Now, FinishTime =DateTime.Now } }, new DisplayTrx { Id = "103", FillingInfo = new DisplayTrxFillingInfo { Amount = 233, NozzleId = 1, ProductType = "95#", UnitPrice = 6.78m, Volume = 35, ProductDiscription = "汽油" }, MemberInfo = new DisplayTrxMemberInfo { LicensePlateNo = "京A88888", Id = "1234567" }, State = TrxStatus.Success, TimeStamp = new DisplayTrxTimeStamp { StartTime = DateTime.Now, FinishTime =DateTime.Now } }, new DisplayTrx { Id = "104", FillingInfo = new DisplayTrxFillingInfo { Amount = 244, NozzleId = 1, ProductType = "95#", UnitPrice = 6.78m, Volume = 35, ProductDiscription = "汽油" }, MemberInfo = new DisplayTrxMemberInfo { LicensePlateNo = "京A88888", Id = "1234567" }, State = TrxStatus.Success, TimeStamp = new DisplayTrxTimeStamp { StartTime = DateTime.Now, FinishTime =DateTime.Now } } }; ms = new MemoryStream(); serializer.Serialize(ms, display); ms.Position = 0; sr = new StreamReader(ms, true); cmdText = sr.ReadToEnd(); break; case ScreenType.TrxResult: display = new Display(); display.ScreenType = screenType; display.PumpInfo = new DisplayPumpInfo { Id = 1, NozzleId = 1 }; display.TrxList = new DisplayTrx[] { new DisplayTrx { Id = "100", FillingInfo = new DisplayTrxFillingInfo { Amount = 200, NozzleId = 1, ProductType = "95#", UnitPrice = 6.78m, Volume = 35, ProductDiscription = "汽油" }, MemberInfo = new DisplayTrxMemberInfo { LicensePlateNo = "京A88888", Id = "1234567" }, State = TrxStatus.Success, TimeStamp = new DisplayTrxTimeStamp { StartTime = DateTime.Now, FinishTime =DateTime.Now } } }; ms = new MemoryStream(); serializer.Serialize(ms, display); ms.Position = 0; sr = new StreamReader(ms, true); cmdText = sr.ReadToEnd(); break; default: throw new Exception("Unsupported screen type"); } return cmdText; } #region IDisposable Support private bool disposedValue = false; // To detect redundant calls protected virtual void Dispose(bool disposing) { if (!disposedValue) { if (disposing) { // TODO: dispose managed state (managed objects). if (fuelingPoints != null) { foreach (var fp in fuelingPoints) { fp.Dispose(); } } if(epsTrxCleanupManager != null) { epsTrxCleanupManager.Dispose(); } if(debugLogger != null) { debugLogger.Dispose(); } } // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below. // TODO: set large fields to null. disposedValue = true; } } // TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources. // ~Eps() { // // Do not change this code. Put cleanup code in Dispose(bool disposing) above. // Dispose(false); // } // This code added to correctly implement the disposable pattern. public void Dispose() { // Do not change this code. Put cleanup code in Dispose(bool disposing) above. Dispose(true); // TODO: uncomment the following line if the finalizer is overridden above. // GC.SuppressFinalize(this); } #endregion } public enum PumpState { /// /// Pump is closed. /// Closed, /// /// Pump is inoperative /// Inoperative, /// /// Pump is Idle /// Idle, /// /// Pump is Calling for authorization /// Calling, /// /// Pump is authorised and ready to begin fuelling. /// Authorized, /// /// Pump is fuelling /// Fuelling, /// /// pump is Suspended /// Suspended, /// /// Unknown state /// Unknown, /// /// Error state /// Error, /// /// Offline state /// Offline, /// /// Starting state /// Starting, /// /// Stopped state /// Stopped, } }