using Dfs.WayneChina.GilbarcoDispenserPayTerminal; using Dfs.WayneChina.GilbarcoDispenserPayTerminal.MessageEntities; using Dfs.WayneChina.GilbarcoDispenserPayTerminal.MessageEntities.Incoming; using Dfs.WayneChina.GilbarcoDispenserPayTerminal.MessageEntities.Outgoing; using Edge.Core.IndustryStandardInterface.Pump; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; using System.Timers; using Wayne.FDCPOSLibrary; namespace Dfs.WayneChina.GilbarcoPos { public class TerminalManager { private class SeqNoGenerator { private List seqNoList; private int i = 0; public SeqNoGenerator() { seqNoList = new List(); for (byte i = 0x5F; i >= 0x40; i--) { seqNoList.Add(i); } } public byte GetNextSeqNo() { i++; return seqNoList[i % 32]; } } public byte PumpId { get; } private GilbarcoPosApp PosApp { get; } private GilbarcoPayTerminalHandler terminal; private Timer timer; private int _interval; private byte seqNo; private SeqNoGenerator Sqg { get; } private Queue fillings = new Queue(10); private NLog.Logger logger = NLog.LogManager.LoadConfiguration("NLog.config").GetLogger("IPosPlusApp"); public TerminalManager(GilbarcoPosApp posApp, GilbarcoPayTerminalHandler terminalHandler, int interval) { PosApp = posApp; terminal = terminalHandler; _interval = interval; PumpId = terminalHandler.PumpId; Sqg = new SeqNoGenerator(); } public void Start() { timer = new Timer(); timer.Interval = _interval; timer.Elapsed += Timer_Elapsed; timer.Start(); } private void Timer_Elapsed(object sender, ElapsedEventArgs e) { SendCheckCommand(); } private byte GetNextSeqNo() { return (byte)(seqNo++ % 0x7F); } private void SendCheckCommand() { logger.Debug($"Checking pump {PumpId}"); CheckCommand checkCommand = new CheckCommand(); checkCommand.DestinationAddress = terminal.TerminalAddress; checkCommand.SourceAddress = terminal.Address; checkCommand.FrameSqNoByte = Sqg.GetNextSeqNo(); checkCommand.Time = long.Parse(DateTime.Now.ToString("yyyyMMddHHmmss")); checkCommand.BaseBlacklistVersion = PosApp.CurrentVersionInfo.BaseBlacklistVersion; checkCommand.AddBlacklistVersion = PosApp.CurrentVersionInfo.AddBlacklistVersion; checkCommand.DeleteBlacklistVersion = PosApp.CurrentVersionInfo.DeleteBlacklistVersion; checkCommand.WhitelistVersion = PosApp.CurrentVersionInfo.WhitelistVersion; checkCommand.PriceVersion = PosApp.CurrentVersionInfo.PriceVersion; checkCommand.StationGeneralInfoVersion = PosApp.CurrentVersionInfo.StationGeneralInfoVersion; checkCommand.PrivateDataDownloadFlag = PosApp.CurrentVersionInfo.PrivateDataDownloadFlag; checkCommand.SoftwareDownloadFlag = PosApp.CurrentVersionInfo.SoftwareDownloadFlag; terminal.Write(checkCommand); } public void HandleInfoCommand(InfoCommand command) { logger.Debug("Handling INFO command"); if (command.Count > 0) { if (command.CardInsertedStates != null) { } else if (command.NozzleOperatingStates != null) { var nozzleOperationState = command.NozzleOperatingStates[0]; if (nozzleOperationState.State == NozzleOperatingState.PumpStateChangeCode.NozzleLiftOrFueling) { if (nozzleOperationState.PRC == 0) { //Assume this is nozzle lift => FDC_CALLING terminal.UpdatePumpState(LogicalDeviceState.FDC_CALLING); } else if (nozzleOperationState.PRC > 0 && nozzleOperationState.VOL == 0) { //Assume this is FDC_AUTHORIZED terminal.UpdatePumpState(LogicalDeviceState.FDC_AUTHORISED); } else if (nozzleOperationState.VOL > 0) { //Assume this is FDC_FUELLING terminal.UpdatePumpState(LogicalDeviceState.FDC_FUELLING); terminal.UpdateFuelingStatus(new FdcTransaction { Finished = false, Nozzle = new LogicalNozzle(PumpId, 1, 1, null), Amount = nozzleOperationState.AMN, Price = nozzleOperationState.PRC, Volumn = nozzleOperationState.VOL }); } } } } else { //Terminal is running fine for now. } } public void HandleTransactionData(TransactionData transactionData) { logger.Info("Handling TransactionData"); //First trigger pump state change, idle again => FDC_READY terminal.UpdatePumpState(Wayne.FDCPOSLibrary.LogicalDeviceState.FDC_READY); // Handle possible duplicate var filling = fillings.FirstOrDefault(f => f.Nozzle.PumpId == transactionData.NozzleNo && f.SequenceNumberGeneratedOnPhysicalPump == transactionData.PosTtc); if (filling == null) { //Fuelling is done now, trigger as well the fueling status change var trans = new FdcTransaction { Finished = true, Nozzle = new LogicalNozzle(PumpId, 1, 1, null), Amount = transactionData.Amount, Price = transactionData.Price, Volumn = transactionData.Volume, VolumeTotalizer = Convert.ToInt32(transactionData.VolumeTotalizer), SequenceNumberGeneratedOnPhysicalPump = transactionData.PosTtc }; terminal.UpdateFuelingStatus(trans); if (fillings.Count >= 10) { fillings.Dequeue(); } fillings.Enqueue(trans); } var ack = CreateTransactionDataAck(0); terminal.Write(ack); } private TransactionDataAck CreateTransactionDataAck(byte result) { TransactionDataAck ack = new TransactionDataAck(); ack.DestinationAddress = terminal.TerminalAddress; ack.SourceAddress = terminal.Address; ack.FrameSqNoByte = Sqg.GetNextSeqNo(); ack.Result = result; return ack; } } }