using Edge.Core.Processor;using Edge.Core.IndustryStandardInterface.Pump; using HengShan_Pump_TQC_IFSF.MessageEntity; using HengShan_Pump_TQC_IFSF.MessageEntity.Incoming; using HengShan_Pump_TQC_IFSF.MessageEntity.Outgoing; using Edge.Core.Parser.BinaryParser.Util; using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Xml; using Wayne.FDCPOSLibrary; using Timer = System.Timers.Timer; namespace HengShan_Pump_TQC_IFSF { public class SilentPumpHandler : PumpHandler { /// /// /// /// /// range from 0x21 to 0x24 /// used to locate the remote tqc pump, must a value different from FC /// used to locate the remote tqc pump /// public SilentPumpHandler(PumpGroupHandler parent, int pumpId, byte ifsfFuelPointId, byte recipientSubnet, byte recipientNode, string nozzlesXmlConfiguration, Func msgTokenGenerator) : base(parent, pumpId, ifsfFuelPointId, recipientSubnet, recipientNode, nozzlesXmlConfiguration, msgTokenGenerator) { //sample of nozzlesXmlConfiguration // // // // // // } public override Task Process(IContext context) { this.context = context; if (context.Incoming.Message is IfsfMessage ifsfMsg && ifsfMsg.MessageType == MessageType.IFSF_MESSAGE_TYPE_UNSOLICITED_ACK) { //logger.Debug("PumpHandlerSilent with ifsfFpId 0x" + base.ifsfFuelPointId.ToHexLogString() + " will ack the Ack requried event!"); context.Outgoing.Write( new AcknowledgeMessage( ifsfMsg.OriginatorSubnet, ifsfMsg.OriginatorNode, PumpGroupHandler.originatorSubnet, PumpGroupHandler.originatorNode, ifsfMsg.MessageToken, ifsfMsg.DatabaseId, MessageAcknowledgeStatus.ACK_PositiveAcknowledgeDataReceived )); } switch (context.Incoming.Message) { case LogicalNozzleDb_Nozzle_PhyId_Event_ACK usedAsExternalNozzleIdConfigurationEvent: // physical nozzle id is actually site level nozzle id. break; case FuellingPointDb_FpStatus_Event fpStatusEvent: { // when trx event piped in, there's no nozzle info linked it within the event(ifsf bad design?), so here always track // and keep the state of the last calling or fuelling nozzle. if (fpStatusEvent.FuelPointState == FuellingPointStatus.CALLING || fpStatusEvent.FuelPointState == FuellingPointStatus.FUELLING) { var operatingNozzlePhysicalId = (byte)(fpStatusEvent.RemovedNozzleIndexes.First() + 0x10); if (this.nozzles.Any(n => n.PhysicalId == operatingNozzlePhysicalId)) base.currentCallingNozzleLogicalId = base.nozzles.First(n => n.PhysicalId == operatingNozzlePhysicalId).LogicalId; else base.currentCallingNozzleLogicalId = (fpStatusEvent.RemovedNozzleIndexes.Any() ? fpStatusEvent.RemovedNozzleIndexes.First() : (byte)1); } logger.Debug("Pump " + this.pumpId + " fpStatusEvent reported: " + fpStatusEvent.FuelPointState); this.HandleFpStatusChange(fpStatusEvent.FuelPointState, this.nozzles.FirstOrDefault(n => n.LogicalId == this.currentCallingNozzleLogicalId)); break; } case FuellingTrxDb_TransactionBufferStatus_Event_ACK trxBufferStatusEvent: { if (trxBufferStatusEvent.Volume != 0 || trxBufferStatusEvent.Amount != 0) { logger.Debug("Pump " + this.pumpId + ", received a Payable trx from TQC with vol(without decimal points): " + trxBufferStatusEvent.Volume + ", amount(without decimal points): " + trxBufferStatusEvent.Amount + ", Price(without decimal points): " + trxBufferStatusEvent.Price); var operatingNozzle = this.nozzles.First(f => f.LogicalId == base.currentCallingNozzleLogicalId); base.FireOnCurrentFuellingStatusChangeEvent(new FdcTransaction() { Nozzle = operatingNozzle, Amount = trxBufferStatusEvent.Amount, Volumn = trxBufferStatusEvent.Volume, Price = int.Parse(trxBufferStatusEvent.Price), SequenceNumberGeneratedOnPhysicalPump = trxBufferStatusEvent.TransactionSeqNumber, Finished = true, }); } break; } case FuellingPointDb_FpRunningTransaction_Event_ACK fpRunningTrxEvent: { var operatingNozzle = this.nozzles.First(f => f.LogicalId == base.currentCallingNozzleLogicalId); base.FireOnCurrentFuellingStatusChangeEvent(new FdcTransaction() { Nozzle = operatingNozzle, Amount = fpRunningTrxEvent.CurrentAmount, Volumn = fpRunningTrxEvent.CurrentVolume, Price = int.Parse(fpRunningTrxEvent.CurrentPrice), Finished = false, }); break; } default: base.Process(context); break; } return Task.CompletedTask; } public override void HandleFpStatusChange(FuellingPointStatus newStatus, LogicalNozzle stateChangedNozzle) { switch (newStatus) { case FuellingPointStatus.Idle: { if (this.lastLogicalDeviceState != LogicalDeviceState.FDC_READY) { this.lastLogicalDeviceState = LogicalDeviceState.FDC_READY; this.FireOnStateChangeEvent(LogicalDeviceState.FDC_READY, stateChangedNozzle); } break; } case FuellingPointStatus.CALLING: { if (this.lastLogicalDeviceState != LogicalDeviceState.FDC_CALLING) { this.lastLogicalDeviceState = LogicalDeviceState.FDC_CALLING; this.FireOnStateChangeEvent(LogicalDeviceState.FDC_CALLING, stateChangedNozzle); } break; } case FuellingPointStatus.AUTHORISED: { if (this.lastLogicalDeviceState != LogicalDeviceState.FDC_AUTHORISED) { this.lastLogicalDeviceState = LogicalDeviceState.FDC_AUTHORISED; this.FireOnStateChangeEvent(LogicalDeviceState.FDC_AUTHORISED, stateChangedNozzle); } break; } case FuellingPointStatus.STARTED: { if (this.lastLogicalDeviceState != LogicalDeviceState.FDC_STARTED) { this.lastLogicalDeviceState = LogicalDeviceState.FDC_STARTED; this.FireOnStateChangeEvent(LogicalDeviceState.FDC_STARTED, stateChangedNozzle); } break; } case FuellingPointStatus.FUELLING: { if (this.lastLogicalDeviceState != LogicalDeviceState.FDC_FUELLING) { this.lastLogicalDeviceState = LogicalDeviceState.FDC_FUELLING; this.FireOnStateChangeEvent(LogicalDeviceState.FDC_FUELLING, stateChangedNozzle); } break; } case FuellingPointStatus.Inoperative: { if (this.lastLogicalDeviceState != LogicalDeviceState.FDC_OFFLINE) { this.lastLogicalDeviceState = LogicalDeviceState.FDC_OFFLINE; this.FireOnStateChangeEvent(LogicalDeviceState.FDC_OFFLINE, stateChangedNozzle); } break; } case FuellingPointStatus.Closed: { if (this.lastLogicalDeviceState != LogicalDeviceState.FDC_CLOSED) { this.lastLogicalDeviceState = LogicalDeviceState.FDC_CLOSED; this.FireOnStateChangeEvent(LogicalDeviceState.FDC_CLOSED, stateChangedNozzle); } break; } } } public override async Task QueryStatusAsync() { return await Task.FromResult(base.lastLogicalDeviceState); } public override async Task AuthorizeAsync(byte logicalNozzleId) { return false; } public override async Task AuthorizeWithAmountAsync(int moneyAmountWithoutDecimalPoint, byte logicalNozzleId) { return false; } public override async Task AuthorizeWithVolumeAsync(int volumnWithoutDecimalPoint, byte logicalNozzleId) { return false; } public override async Task ChangeFuelPriceAsync(int newPriceWithoutDecimalPoint, byte logicalNozzleId) { return false; } public override async Task FuelingRoundUpByAmountAsync(int amount) { return false; } public override async Task FuelingRoundUpByVolumeAsync(int volume) { return false; } public override async Task> QueryTotalizerAsync(byte logicalNozzleId) { return new System.Tuple(-1, -1); } } }