123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946 |
- using Edge.Core.Processor;
- using Edge.Core.IndustryStandardInterface.Pump;
- using Dfs.WayneChina.HengshanPayTerminal;
- using Dfs.WayneChina.HengshanPayTerminal.MessageEntity;
- using Dfs.WayneChina.HengshanPayTerminal.MessageEntity.Incoming;
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Linq;
- using Dfs.WayneChina.HengshanPayTerminal.Support;
- using Applications.FDC;
- using Edge.Core.Database;
- using FdcServerHost;
- using Dfs.WayneChina.CardTrxManager.TrxSubmitter;
- using Dfs.WayneChina.CardTrxManager;
- using System.Threading.Tasks;
- using Dfs.WayneChina.IPosPlus.ServiceClient;
- using Dfs.WayneChina.SpsDataCourier;
- using NLog.LayoutRenderers.Wrappers;
- using Edge.Core.Configuration;
- using Edge.Core.Processor.Dispatcher.Attributes;
- namespace Dfs.WayneChina.IPosPlus
- {
- /// <summary>
- /// Serves as an application controller containing the terminal handlers and terminal managers,
- /// as well as the database access manager.
- /// </summary>
- [MetaPartsDescriptor(
- "lang-zh-cn:iPosPlus应用lang-en-us:iPOS Plus App",
- "lang-zh-cn:用于管理加油机IC卡终端控制" +
- "lang-en-us:Used for managing all IC card terminals on dispensers across the site",
- new[] { "lang-zh-cn:加油机lang-en-us:Pump", "lang-zh-cn:IfsfFdcServerlang-en-us:IfsfFdcServer" })]
- public class IPosPlusApp : IAppProcessor
- {
- #region Fields
- private SpsDbManager.SpsManager spsManager;
- private List<HengshanPayTermHandler> paymentTerminalHandlers = new List<HengshanPayTermHandler>();
- private List<TerminalManager> terminalManagers = new List<TerminalManager>();
- private NLog.Logger logger = NLog.LogManager.LoadConfiguration("NLog.config").GetLogger("IPosPlusApp");
- private PosInitialData initalData;
- private object syncObj = new object();
- private FdcServerHostApp fdcServerApp;
- private string fuelProductMapping;
- private IEnumerable<NozzleExtraInfo> nozzleProductConfig = Configurator.Default.NozzleExtraInfoConfiguration.Mapping;
- private Dictionary<int, int> fuelMappingDict = new Dictionary<int, int>();
- private List<FillingInfo> customerFillings = new List<FillingInfo>();
- private List<TrxSubmitter> submitters = new List<TrxSubmitter>();
- private CloudCredential cloudCredential;
- private bool onlineDiscount = false;
- private int discountTimeout = 3;
- private string promotionCategories = string.Empty;
- private Dictionary<int, string> fuelNameDict = new Dictionary<int, string>();
- private Dictionary<string, uint> fuelCodePriceDict = new Dictionary<string, uint>();
- public int CardAppType { get; }
- private int interval;
- private Dictionary<int, bool> pumpPriceDict = new Dictionary<int, bool>();
- private object dictSync = new object();
- private SpsDataCourierApp spsDataCourierApp;
- private StoreForwardManager sfManager;
- private int stationNo = 0;
- private string stationName = "";
- private int mode = 1;
- private int reservedBalance = 20;
- #endregion
- #region MySQL connection string
- private string _mysqlConn =
- "server=localhost;port=3306;user=root;password=HS1205;database=sps_db;TreatTinyAsBoolean=false;Convert Zero Datetime=True";
- #endregion
- #region Constructor
- [ParamsJsonSchemas("appCtorParamsJsonSchema")]
- public IPosPlusApp(PosAppContructorParameterV1 config)
- {
- PosId = config.PosId;
- _mysqlConn = FormatConnectionString(config.ConnectionString);
- spsManager = new SpsDbManager.SpsManager(_mysqlConn);
- //Current Business Unit Id.
- var fakeBuId = Configurator.Default
- .MetaConfiguration
- .Parameter?
- .FirstOrDefault(p => p.Name.Equals("serialNumber", StringComparison.OrdinalIgnoreCase))?.Value;
- cloudCredential = new CloudCredential
- {
- UserName = config.Username,
- Password = config.Password,
- AuthServiceBaseUrl = config.AuthServiceBaseUrl,
- TransactionServiceBaseUrl = config.TransactionServiceBaseUrl,
- DiscountServiceBaseUrl = config.DiscountServiceBaseUrl,
- DeviceSN = config.DeviceSN,
- CurrentBuId = fakeBuId
- };
- onlineDiscount = config.OnlineDiscount;
- discountTimeout = config.DiscountTimeout;
- if (this.onlineDiscount)
- {
- DiscountServiceClient = new DiscountServiceClient(this, cloudCredential, promotionCategories, discountTimeout);
- }
- promotionCategories = config.PromoCategories;
- fuelProductMapping = string.Join(";", config.FuelMappingArr.Select(m => $"{m.Barcode}:{m.FuelNo}"));
- CardAppType = config.CardAppType;
- interval = config.Interval;
- mode = config.PumpMode;
- stationNo = config.StationNo;
- stationName = config.StationName;
- reservedBalance = config.ReservedBalance;
- SetFuelProductMapping();
- pumpPriceDict.Clear();
- sfManager = new StoreForwardManager(cloudCredential);
- }
- public IPosPlusApp(int posId, string username, string password, string authServiceBaseUrl, string transactionServiceBaseUrl,
- string discountServiceBaseUrl, bool onlineDiscount, int discountTimeout, string deviceSN, string promoCategories, List<FuelMappingV1> fuelMappingArr,/*string fuelMapping,*/
- int cardAppType, int reservedBalance, int interval, SpsDbConnectionSetting connectionString)
- {
- PosId = posId;
- _mysqlConn = FormatConnectionString(connectionString);//connectionString;
- spsManager = new SpsDbManager.SpsManager(_mysqlConn);
- //Current Business Unit Id.
- var fakeBuId = Configurator.Default
- .MetaConfiguration
- .Parameter?
- .FirstOrDefault(p => p.Name.Equals("serialNumber", StringComparison.OrdinalIgnoreCase))?.Value;
- cloudCredential = new CloudCredential
- {
- UserName = username,
- Password = password,
- AuthServiceBaseUrl = authServiceBaseUrl,
- TransactionServiceBaseUrl = transactionServiceBaseUrl,
- DiscountServiceBaseUrl = discountServiceBaseUrl,
- DeviceSN = deviceSN,
- CurrentBuId = fakeBuId
- };
- this.onlineDiscount = onlineDiscount;//Convert.ToBoolean(onlineDiscount);
- this.discountTimeout = discountTimeout;
- promotionCategories = promoCategories;
- if (this.onlineDiscount)
- {
- DiscountServiceClient = new DiscountServiceClient(this, cloudCredential, promotionCategories, discountTimeout);
- }
- fuelProductMapping = string.Join(";", fuelMappingArr.Select(m => $"{m.Barcode}:{m.FuelNo}")); //fuelMapping;
- CardAppType = cardAppType;
- this.interval = interval;
- this.reservedBalance = reservedBalance;
- SetFuelProductMapping();
- pumpPriceDict.Clear();
- sfManager = new StoreForwardManager(cloudCredential);
- }
- private string FormatConnectionString(SpsDbConnectionSetting spsDbConnectionSetting)
- {
- return $"server={spsDbConnectionSetting.Server};port={spsDbConnectionSetting.Port};uid={spsDbConnectionSetting.Username};password={spsDbConnectionSetting.Password};database=sps_db;TreatTinyAsBoolean=false;Convert Zero Datetime=true;";
- }
- #endregion
- #region IApplication interface implementation
- public string MetaConfigName { get; set; }
- public void Init(IEnumerable<IProcessor> processors)
- {
- foreach (dynamic p in processors)
- {
- if (p is IAppProcessor)
- {
- FdcServerHostApp fdcServer = p as FdcServerHostApp;
- if (fdcServer != null)
- fdcServerApp = p;
- SpsDataCourierApp dataCourier = p as SpsDataCourierApp;
- if (dataCourier != null)
- spsDataCourierApp = dataCourier;
- continue;
- }
- var handler = p.Context.Handler;
- if (handler is HengshanPayTermHandler)
- {
- paymentTerminalHandlers.Add(handler);
- }
- }
- SetupTerminalManagers();
- SetupTransactionSubmitters();
- GetInitialData();
- GetStationInfo();
- if (fdcServerApp != null)
- {
- fdcServerApp.OnCurrentFuellingStatusChange += FdcServerApp_OnCurrentFuellingStatusChange;
- }
- }
- private bool UpsertSpsConfig()
- {
- if (fdcServerApp == null)
- {
- logger.Error($"Could not get FdcServer instance");
- return false;
- }
- var allNozzleExtraInfo = fdcServerApp.GetNozzleExtraInfos();
- var productNames = allNozzleExtraInfo.Select(n => n.ProductName).Distinct().ToList();
- //filter out the product names
- foreach (var item in productNames)
- {
- var tank = allNozzleExtraInfo.FirstOrDefault(n => n.ProductName == item)?.TankNumber;
- logger.Info($"Distinct product name: {item}, related tank: {tank}");
- }
- //filter out the tanks
- var tanks = allNozzleExtraInfo.Select(n => n.TankNumber).Distinct();
- foreach (var item in tanks)
- {
- logger.Info($"Distinct tank number: {item}");
- }
- var siteProducts = allNozzleExtraInfo.Select(n => new { Barcode = n.ProductBarcode, Name = n.ProductName }).ToList();
- var fuelBarcodes = allNozzleExtraInfo.Select(n => n.ProductBarcode).Distinct().ToList();
- if (fuelBarcodes.Count > tanks.Count())
- {
- logger.Error($"More fuel product types, less tanks, abort!");
- return false;
- }
- foreach (var product in siteProducts)
- {
- logger.Info($"Update product: {product.Barcode}, {product.Name}");
-
- var fuelCode = fuelMappingDict[product.Barcode]; // Code for fuel product, e.g. 1021, 2001
- string fuelClassNo = "1000";
- if (fuelCode >= 1000 && fuelCode < 2000)
- fuelClassNo = "1000";
- else if (fuelCode >= 2000)
- fuelClassNo = "2000";
- spsManager.AddOrUpdateFuelProduct(Convert.ToString(fuelCode), fuelClassNo, product.Name, 999);
- }
- //Tank product
- var tankProducts = new Dictionary<int, string>();
- foreach (var tank in tanks)
- {
- //product barcode for the tank
- var productBarcode = allNozzleExtraInfo.First(n => n.TankNumber == tank.Value).ProductBarcode;
- if (!tankProducts.ContainsKey(tank.Value))
- {
- string fuelNo = Convert.ToString(fuelMappingDict[productBarcode]);
- logger.Info($"Add to tankProducts Dict, tank.value: {tank.Value}, fuelno: {fuelNo}");
- tankProducts.Add(tank.Value, fuelNo); // tank_no, fuel_no
- }
- }
- foreach (var item in tankProducts)
- {
- spsManager.AddOrUpdateTankConfig(item.Key, item.Value);
- logger.Info($"add or update tank config: {item.Key}, {item.Value}");
- }
- foreach (var tankProduct in tankProducts)
- {
- logger.Info($"tank id: {tankProduct.Key}, tank product code: {tankProduct.Value}");
- }
- // filter out the pumps
- var pumps = allNozzleExtraInfo.Select(n => n.PumpId).Distinct();
- foreach (var pump in pumps)
- {
- logger.Info($"Distinct pump id: {pump}");
- foreach (var ptHandler in paymentTerminalHandlers)
- {
- if (ptHandler.AssociatedPumpIds.Contains(pump))
- {
- int serialPort = 4;
- string portName = ptHandler.CommIdentity;
- logger.Info($"Communicator identity: {portName}");
- if (!string.IsNullOrEmpty(portName))
- {
- string name = "";
- for (int i = 0; i < portName.Length; i++)
- {
- if (Char.IsDigit(portName[i]))
- name += portName[i];
- }
- if (name.Length > 0)
- {
- int.TryParse(name, out serialPort);
- if (serialPort == 0)
- serialPort = 4;
- }
- if (portName.Contains('.'))
- {
- string[] sections = portName.Split(':');
- name = sections.LastOrDefault();
- int.TryParse(name, out serialPort);
- int originalPort = serialPort;
- serialPort = originalPort % 100;
- logger.Info($"Parsed with dot, original: {originalPort} serialPort: {serialPort}");
- if (serialPort == 0)
- serialPort = 4;
- }
- }
- else
- {
- serialPort = ptHandler.AssociatedPumpIds.Max();
- }
- var subAddress = ptHandler.GetSubAddressForPump(pump);
- logger.Info($"Sub Address: {subAddress}, COM: {serialPort} for Pump: {pump}");
- spsManager.AddOrUpdatePump(mode, Convert.ToByte(pump), serialPort, Convert.ToByte(subAddress), 999999);
- logger.Info($"Updating pump: {pump}, sub address: {subAddress}");
- }
- }
- }
- foreach (var nozzleExtraInfo in allNozzleExtraInfo)
- {
- logger.Info($"PumpId: {nozzleExtraInfo.PumpId}, NozzleLogicalId: {nozzleExtraInfo.NozzleLogicalId}, " +
- $"SiteLevelNozzleId: {nozzleExtraInfo.SiteLevelNozzleId}, ProductBarcode: {nozzleExtraInfo.ProductBarcode}, " +
- $"ProductName: {nozzleExtraInfo.ProductName}, TankNumber: {nozzleExtraInfo.TankNumber}");
- byte nozzleId = Convert.ToByte(nozzleExtraInfo.SiteLevelNozzleId);
- byte pumpId = Convert.ToByte(nozzleExtraInfo.PumpId);
- byte tankId = Convert.ToByte(nozzleExtraInfo.TankNumber);
- string fuelNo = tankProducts[nozzleExtraInfo.TankNumber.Value];
-
- spsManager.AddOrUpdateNozzle(nozzleId, pumpId, tankId, fuelNo);
- logger.Info($"Updating NozzleId: {nozzleId}, PumpId: {pumpId}, TankId: {tankId}, FuelNo: {fuelNo}");
- }
- spsManager.UpdateGeneralInfoVersion();
- spsManager.UpdateFuelPriceVersion();
- logger.Info($"Updating station no: {stationNo}, station name: {stationName}");
- spsManager.UpdateStationInfo(stationNo, stationName);
- return true;
- }
- private void FdcServerApp_OnCurrentFuellingStatusChange(object sender, FdcServerTransactionDoneEventArg e)
- {
- if (e.Transaction.Finished)
- {
- InfoLog($"There is a finished filling, ReleaseToken: {e.ReleaseToken}, PumpId: {e.Transaction.Nozzle.PumpId}," +
- $" LogicalNozzleId: {e.Transaction.Nozzle.LogicalId}, SequenceNo: {e.Transaction.SequenceNumberGeneratedOnPhysicalPump}");
- Task.Run(async () => await HandleCustomerCardFillings(e));
- }
- }
- //初步定位在这触发
- private async Task HandleCustomerCardFillings(FdcServerTransactionDoneEventArg e)
- {
- int nozzleNoForCurrentTrx = e.Transaction.Nozzle.PumpId;
- byte currentPumpId = Convert.ToByte(e.Transaction.Nozzle.PumpId);
- var pth = paymentTerminalHandlers.First(h => h.AssociatedPumpIds.Contains(currentPumpId));
- if (pth != null)
- {
- var nozzleNos = pth.PumpSiteNozzleNoDict[currentPumpId];
- foreach (var item in nozzleNos)
- {
- if (pth.NozzleLogicIdDict[item] == e.Transaction.Nozzle.LogicalId)
- {
- nozzleNoForCurrentTrx = item;
- }
- }
- }
- //调整当前加油记录List 加上日期的筛选 -45天前的记录
- var filling = customerFillings.OrderByDescending(p => p.StartTime).FirstOrDefault(f => f.SequenceNo == e.Transaction.SequenceNumberGeneratedOnPhysicalPump &&
- f.PumpId == e.Transaction.Nozzle.PumpId && f.NozzleId == nozzleNoForCurrentTrx && f.StartTime > DateTime.Now.AddDays(-45));
- if (filling != null)
- {
- InfoLog("Locking transaction");
- var lockedTrx = await fdcServerApp.LockFuelSaleTrxAndNotifyAllFdcClientsAsync(100, e.Transaction.Nozzle.PumpId, filling.SequenceNo, e.ReleaseToken.Value);
- if (lockedTrx == null)
- {
- InfoLog("Amazing, failed to lock transaction in FdcServer, try again in 100 ms");
- await Task.Delay(100);
- lockedTrx = await fdcServerApp.LockFuelSaleTrxAndNotifyAllFdcClientsAsync(100, e.Transaction.Nozzle.PumpId, filling.SequenceNo, e.ReleaseToken.Value);
- if (lockedTrx == null)
- {
- InfoLog("Locking transaction failed in second try");
- await Task.Delay(100);
- lockedTrx = await fdcServerApp
- .LockFuelSaleTrxAndNotifyAllFdcClientsAsync(100, e.Transaction.Nozzle.PumpId, filling.SequenceNo, e.ReleaseToken.Value);
- }
- }
- InfoLog("Ready to submit the customer card transaction!");
- var submitter = GetSubmitter(filling.PumpId);
- if (submitter != null)
- {
- InfoLog("Grabbed instance of submitter");
- var cardAccountInfo = spsManager.GetCardAccountInfo(filling.CardNo);
- var result = await submitter.SubmitTrxAsync(new ClientTrxInfo
- {
- PumpId = filling.PumpId,
- NozzleId = 1,
- SiteNozzleNo = filling.NozzleId,//filling.PumpId,
- Barcode = GetBarcode(filling.FuelProductCode),
- Volume = Convert.ToDecimal(filling.Volume) / 100,
- Amount = Convert.ToDecimal(filling.FillingAmount) / 100,
- PayAmount = Convert.ToDecimal(filling.PayAmount) / 100,
- UnitPrice = Convert.ToDecimal(filling.UnitPrice) / 100,
- CardNo = filling.CardNo,
- CurrentCardBalance = Convert.ToDecimal(filling.CardBalance) / 100,
- FdcSqNo = e.ReleaseToken.Value,
- SeqNo = filling.SequenceNo,
- FuelingStartTime = filling.StartTime,
- FuelingFinishedTime = filling.EndTime,
- VolumeTotalizer = Convert.ToDecimal(filling.VolumeTotal) / 100,
- CardHolder = cardAccountInfo?.Holder,
- AccountName = cardAccountInfo?.BelongTo
- });
- InfoLog($"Submit successfully? {result}");
- if (result)
- {
- InfoLog("Clearing transaction");
- await fdcServerApp.ClearFuelSaleTrxAndNotifyAllFdcClientsAsync(e.Transaction.Nozzle.PumpId,
- filling.SequenceNo.ToString(), e.ReleaseToken.Value, "100");
- //After uploading, remove it.
- customerFillings.Remove(filling);
- }
- }
- }
- }
- public void AddCustomerCardFilling(FillingInfo fillingInfo)
- {
- customerFillings.Add(fillingInfo);
- }
- private void GetInitialData()
- {
- var result = spsManager.GetInitialData(PosId);
- if (result != null)
- {
- initalData = new PosInitialData
- {
- BillNo = result.Bill_No,
- ShiftNo = result.Shift_No,
- ShiftState = result.Shift_State
- };
- }
- }
- private void GetStationInfo()
- {
- var stationData = spsManager.GetStationInfo();
- if (stationData != null)
- {
- StationInfo = new StationInfo { StationNo = stationData.Sno };
- }
- }
- private void UpdateStationInfo(int stationNo, string name)
- {
- spsManager.UpdateStationInfo(stationNo, name);
- }
- public int GetNextBillNo()
- {
- lock (syncObj)
- {
- return ++initalData.BillNo;
- }
- }
- public Task<bool> Start()
- {
- //Hook up the terminal message event handler
- foreach (var handler in paymentTerminalHandlers)
- {
- handler.OnTerminalMessageReceived += Handler_OnTerminalMessageReceived;
- handler.OnFuelPriceChangeRequested += Handler_OnFuelPriceChangeRequested;
- }
- InitFuelName();
- InitFuelPrices();
- if (spsDataCourierApp != null)
- logger.Info("SpsDataCourier instance exists!");
- spsManager.Start();
- sfManager.Start();
- sfManager.OnStoreForwardCompleted += SfManagerStoreForwardCompleted;
- // Inserting configuration data into sps_db.
- var result = UpsertSpsConfig();
- if (result == false)
- return Task.FromResult(false);
- return Task.FromResult(true);
- }
- private async void SfManagerStoreForwardCompleted(object sender, StoreForwardCompletedEventArgs e)
- {
- logger.Info($"SF completed, clear transaction, pump id: {e.PumpdId}, sq no: {e.SeqNo}, rt: {e.ReleaseToken}");
- await fdcServerApp.ClearFuelSaleTrxAndNotifyAllFdcClientsAsync(e.PumpdId, e.SeqNo.ToString(), e.ReleaseToken, "100");
- }
- private void Handler_OnFuelPriceChangeRequested(object sender, FuelPriceChangeRequestEventArgs e)
- {
- logger.Info($"PosApp: {e.PumpId}, {e.NozzleId}, {e.Price}");
- var result = spsManager.GetFuelPriceConfig();
- var fdcServerNozzleProductConfig = fdcServerApp.GetNozzleExtraInfos();
- var nozzle = fdcServerNozzleProductConfig.First(c => c.PumpId == e.PumpId && c.NozzleLogicalId == e.NozzleId);
- logger.Info($"PosApp: Nozzle, barcode: {nozzle.ProductBarcode}");
- var fuelNo = GetFuelNo(nozzle.ProductBarcode);
- logger.Info($"PosApp: Got Fuel No: {fuelNo}");
- spsManager.UpdateFuelPrice(Convert.ToString(fuelNo), e.Price);
- lock (dictSync)
- {
- pumpPriceDict[e.PumpId] = true;
- if (pumpPriceDict.Count(p => p.Value == false) > 1)
- {
- return;
- }
- else if (pumpPriceDict.Count(p => p.Value == false) == 1)
- {
- logger.Info("PosApp: FuelPrice dict, only one pump left, update price version");
- spsManager.UpdateFuelPriceVersion();
- }
- else
- {
- // After all pumps' requests handled, reset the dictionary
- foreach (var item in pumpPriceDict.Keys.ToList())
- {
- pumpPriceDict[item] = false;
- }
- }
- }
- InitFuelPrices();
- }
- public Task<bool> Stop()
- {
- //Unhook the terminal message event handler
- foreach (var handler in paymentTerminalHandlers)
- {
- handler.OnTerminalMessageReceived -= Handler_OnTerminalMessageReceived;
- handler.OnFuelPriceChangeRequested -= Handler_OnFuelPriceChangeRequested;
- }
- if (fdcServerApp != null)
- {
- fdcServerApp.OnCurrentFuellingStatusChange -= FdcServerApp_OnCurrentFuellingStatusChange;
- }
- return Task.FromResult(true);
- }
- public void LockUnlockPump(int pumpId, LockUnlockOperation operation)
- {
- var terminalManager = GetTerminalManager(pumpId);
- terminalManager.LockUnlockPump(operation);
- }
- private async void Handler_OnTerminalMessageReceived(object sender, TerminalMessageEventArgs e)
- {
- await HandleTerminalMessage(e);
- }
- private async Task HandleTerminalMessage(TerminalMessageEventArgs e)
- {
- var message = e.Message;
- DebugLog($"Incoming terminal message, HandlerGroup:[{e.Identifier}], Source {message.SourceAddress}, " +
- $"Destination {message.DestinationAddress}, FrameSeqNoByte {message.FrameSqNoByte}");
- var terminalManager = GetTerminalManager(e.Identifier, message.DestinationAddress);
- if (terminalManager == null)
- {
- logger.Error($"Could not find TerminalManager for message of identifier: {e.Identifier}, dest addr: {message.DestinationAddress}");
- return;
- }
- DebugLog($"Terminal Manager {terminalManager.PumpId} handle the message");
- if (message is RegisterRequest)
- {
- terminalManager.HandleRegiser((RegisterRequest)message);
- DebugLog($"RegisterRequest handled, Source {message.SourceAddress}, Destination {message.DestinationAddress}");
- }
- else if (message is CheckCmdRequest)
- {
- DebugLog($"CheckCmdRequest, Source {message.SourceAddress}, Destination {message.DestinationAddress}");
- terminalManager.HandleCheckCmdRequest((CheckCmdRequest)message);
- DebugLog("Sent checkcmdResponse");
- }
- else if (message is ValidateCardRequest)
- {
- terminalManager.HandleCardValidation((ValidateCardRequest)message);
- DebugLog($"ValidateCardRequest, Source {message.SourceAddress}, Destination {message.DestinationAddress}");
- }
- else if (message is AuthRequest)
- {
- terminalManager.HandlAuthorization((AuthRequest)message);
- DebugLog($"AuthRequest handled, Source {message.SourceAddress}, Destination {message.DestinationAddress}");
- }
- else if (message is FuelingDataRequest)
- {
- terminalManager.HandleFuelingData((FuelingDataRequest)message);
- DebugLog($"FuelingDataRequest handled, Source {message.SourceAddress}, Destination {message.DestinationAddress}");
- }
- else if (message is PaymentRequest)
- {
- terminalManager.HandlePaymentRequest((PaymentRequest)message);
- DebugLog($"PaymentRequest handled, Source {message.SourceAddress}, Destination {message.DestinationAddress}");
- }
- else if (message is TransactionDataRequest)
- {
- await terminalManager.HandleTransactionData((TransactionDataRequest)message);
- DebugLog($"TransactionDataRequest handled, Source {message.SourceAddress}, Destination {message.DestinationAddress}");
- }
- else if (message is LockOrUnlockPumpAck)
- {
- terminalManager.HandleLockUnlockPumpResult((LockOrUnlockPumpAck)message);
- DebugLog($"LockOrUnlock ack, Source: {message.SourceAddress}, Destination: {message.DestinationAddress}, " +
- $"Operation: {((LockOrUnlockPumpAck)message).OperationType}, Result state: {((LockOrUnlockPumpAck)message).DispenserState}");
- }
- else if (message is DataDownloadRequest)
- {
- terminalManager.HandleDataDownloadRequest((DataDownloadRequest)message);
- }
- else if (message is DataContentRequest)
- {
- terminalManager.HandleDataContentRequest((DataContentRequest)message);
- }
- else if (message is ChangeAuthModeAck)
- {
- terminalManager.HandleModeChangeResult((ChangeAuthModeAck)message);
- }
- else if (message is CancelAuthRequest)
- {
- terminalManager.HandleCancelAuth((CancelAuthRequest)message);
- }
- else if (message is QueryGrayRecordRequest)
- {
- terminalManager.HandleQueryGrayRecord((QueryGrayRecordRequest)message);
- }
- else if (message is null)
- {
- terminalManager.HandleFakeNullMessage();
- }
- }
- private void SetupTerminalManagers()
- {
- foreach (var ptHandler in paymentTerminalHandlers)
- {
- foreach (var pumpId in ptHandler.AssociatedPumpIds)
- {
- var mgr = new TerminalManager(this, pumpId, ptHandler.GetSubAddressForPump(pumpId), spsManager, ptHandler, interval, this.CardAppType);
- terminalManagers.Add(mgr);
- InfoLog($"Setting up TerminalManager, Pump Id: {mgr.PumpId}, Sub address: {mgr.SubAddress}");
- }
- }
- }
- private void InitPumpPriceDict()
- {
- foreach (var ptHandler in paymentTerminalHandlers)
- {
- foreach (var p in ptHandler.AssociatedPumpIds)
- {
- if (!pumpPriceDict.ContainsKey(p))
- {
- pumpPriceDict.Add(p, false);
- }
- }
- }
- }
- private void SetupTransactionSubmitters()
- {
- foreach (var ptHandler in paymentTerminalHandlers)
- {
- foreach (var p in ptHandler.AssociatedPumpIds)
- {
- if (submitters.Any(s => s.Id == p))
- continue;
- var s = new TrxSubmitter(p, cloudCredential);
- submitters.Add(s);
- InfoLog($"Setting up Transaction submitter, Pump Id: {p}");
- }
- }
- }
- private TrxSubmitter GetSubmitter(int pumpId)
- {
- return submitters.FirstOrDefault(s => s.Id == pumpId);
- }
- private void SetFuelProductMapping()
- {
- if (!string.IsNullOrEmpty(fuelProductMapping))
- {
- var sequence = fuelProductMapping.Split(';')
- .Select(s => s.Split(':'))
- .Select(a => new { Barcode = int.Parse(a[0]), FuelNo = int.Parse(a[1]) });
- foreach (var pair in sequence)
- {
- if (!fuelMappingDict.ContainsKey(pair.Barcode))
- {
- fuelMappingDict.Add(pair.Barcode, pair.FuelNo);
- }
- }
- }
- }
- private int GetFuelNo(int barcode)
- {
- if (fuelMappingDict.ContainsKey(barcode))
- return fuelMappingDict[barcode];
- return -1;
- }
- public int GetBarcode(int fuelNo)
- {
- return fuelMappingDict.FirstOrDefault(x => x.Value == fuelNo).Key;
- }
- private void InitFuelName()
- {
- fuelNameDict.Clear();
- var fuelNames = spsManager.GetFuelNames();
- foreach (var item in fuelNameDict)
- {
- int barcode = GetBarcode(Convert.ToInt32(item.Key));
- if (!fuelNameDict.ContainsKey(barcode))
- {
- fuelNameDict.Add(barcode, item.Value);
- }
- }
- }
- private void InitFuelPrices()
- {
- fuelCodePriceDict.Clear();
- var fuelPrices = spsManager.GetCurrentFuelPrices();
- foreach (var item in fuelPrices)
- {
- if (!fuelCodePriceDict.ContainsKey(item.Key))
- {
- fuelCodePriceDict.Add(item.Key, item.Value);
- }
- }
- }
- public string GetFuelName(int barcode)
- {
- string fuelName = string.Empty;
- fuelNameDict.TryGetValue(barcode, out fuelName);
- return fuelName;
- }
- private TerminalManager GetTerminalManager(int pumpId)
- {
- return terminalManagers.FirstOrDefault(t => t.PumpId == pumpId);
- }
- private TerminalManager GetTerminalManager(string identifier, int pumpId)
- {
- return terminalManagers.FirstOrDefault(t => t.Identifier == identifier && t.SubAddress == pumpId);
- }
- private void InfoLog(string info)
- {
- logger.Info(info);
- }
- private void DebugLog(string debugMsg)
- {
- logger.Debug(debugMsg);
- }
- #endregion
- #region Properties
- public FdcServerHostApp FdcServer
- {
- get { return fdcServerApp; }
- }
- public SpsDataCourierApp SpsDataCourier => spsDataCourierApp;
- public int PosId { get; private set; }
- public long CurrentShiftNo
- {
- get { return initalData.ShiftNo; }
- }
- public DiscountServiceClient DiscountServiceClient { get; }
- public Dictionary<string, uint> CurrentFuelPrices => fuelCodePriceDict;
- public StationInfo StationInfo { get; private set; }
- public int ReservedBalance => reservedBalance;
- #endregion
- }
- #region Config parameters
- public class PosAppContructorParameterV1
- {
- public int PosId { get; set; }
- public string Username { get; set; }
- public string Password { get; set; }
-
- public string AuthServiceBaseUrl { get; set; }
-
- public string TransactionServiceBaseUrl { get; set; }
-
- public string DiscountServiceBaseUrl { get; set; }
-
- public bool OnlineDiscount { get; set; }
- public int DiscountTimeout { get; set; }
-
- public string DeviceSN { get; set; }
-
- public string PromoCategories { get; set; }
-
- public List<FuelMappingV1> FuelMappingArr { get; set; }
-
- public int CardAppType { get; set; }
- public int ReservedBalance { get; set; }
- public int PumpMode { get; set; }
-
- public int Interval { get; set; }
-
- public SpsDbConnectionSetting ConnectionString { get; set; }
- public int StationNo { get; set; }
- public string StationName { get; set; }
- }
- public class FuelMappingV1
- {
- public int Barcode { get; set; }
- public string FuelNo { get; set; }
- }
- public class SpsDbConnectionSetting
- {
- public string Server { get; set; }
- public int Port { get; set; }
- public string Username { get; set; }
- public string Password { get; set; }
- }
- #endregion
- }
|