123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290 |
- using System;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.Configuration;
- using System.IO.Ports;
- using System.Linq;
- using System.Text;
- using System.Threading;
- using Timer = System.Timers.Timer;
- using System.Collections;
- using Edge.Core.Processor;using Edge.Core.IndustryStandardInterface.Pump;
- using Wayne.FDCPOSLibrary;
- using System.Xml;
- using Edge.Core.Database.Models;
- using System.Threading.Tasks;
- namespace FuRen_Sinopec_IcCardReader
- {
- /// <summary>
- /// This pump handler only listen the ic card reader, will never send message.
- /// </summary>
- public class SilentPumpHandler : IFdcPumpController, IDeviceHandler<byte[], KaJiLianDongV11MessageTemplateBase>
- {
- static NLog.Logger logger = NLog.LogManager.LoadConfiguration("nlog.config").GetLogger("PumpHandler");
- protected IContext<byte[], KaJiLianDongV11MessageTemplateBase> context;
- public event EventHandler<FdcPumpControllerOnStateChangeEventArg> OnStateChange;
- /// <summary>
- /// fired on fueling process is on going, the fuel amount should keep changing.
- /// </summary>
- public event EventHandler<FdcTransactionDoneEventArg> OnCurrentFuellingStatusChange;
- protected LogicalDeviceState lastLogicalDeviceState = LogicalDeviceState.FDC_CLOSED;
- private DateTime lastLogicalDeviceStateReceivedTime;
- // by seconds
- private const int lastLogicalDeviceStateExpiredTime = 6;
- private Guid uniqueId = Guid.NewGuid();
- private int pumpId = -1;
- protected List<LogicalNozzle> nozzles = new List<LogicalNozzle>();
- public IEnumerable<LogicalNozzle> Nozzles => this.nozzles;
- /// <summary>
- /// </summary>
- /// <param name="pumpId"></param>
- /// <param name="nozzlesXmlConfiguration"></param>
- public SilentPumpHandler(int pumpId)
- {
- this.pumpId = pumpId;
- //this.nozzles.Add(new LogicalNozzle(pumpId, 1, 1, null));
- }
- public void Init(IContext<byte[], KaJiLianDongV11MessageTemplateBase> context)
- {
- this.context = context;
- }
- public virtual async Task Process(IContext<byte[], KaJiLianDongV11MessageTemplateBase> context)
- {
- this.context = context;
- this.lastLogicalDeviceStateReceivedTime = DateTime.Now;
- //PumpStateChangeCommand -- it's also the PC polling message response from pump.
- //PumpNotifyTransactionDoneCommand
- if (this.lastLogicalDeviceState == LogicalDeviceState.FDC_OFFLINE)
- {
- logger.Info("Pump: " + this.pumpId + ", " + "Recevied an IcCard Msg in FDC_OFFLINE state, " +
- "indicates the underlying connection is established, switch to FDC_READY");
- this.lastLogicalDeviceState = LogicalDeviceState.FDC_READY;
- var safe = this.OnStateChange;
- safe?.Invoke(this, new FdcPumpControllerOnStateChangeEventArg(LogicalDeviceState.FDC_READY));
- }
- if (context.Incoming.Message is PumpStateChangeCommand PumpStateChangeCommand)
- {
- if (PumpStateChangeCommand.StateNozzleOperatingSubMessages == null
- && PumpStateChangeCommand.StateNozzleOperatingSubMessages == null)
- {
- if (this.lastLogicalDeviceState != LogicalDeviceState.FDC_READY)
- {
- this.lastLogicalDeviceState = LogicalDeviceState.FDC_READY;
- var safe2 = this.OnStateChange;
- safe2?.Invoke(this, new FdcPumpControllerOnStateChangeEventArg(
- LogicalDeviceState.FDC_READY,
- this.nozzles.FirstOrDefault()));
- }
- }
- if (PumpStateChangeCommand.StateNozzleOperatingSubMessages != null
- && PumpStateChangeCommand.StateNozzleOperatingSubMessages.Any(n =>
- n.St状态字 == PumpStateChangeNozzleOperatingSubState.PumpStateChangeCode.抬枪或加油中))
- {
- if (!this.nozzles.Any())
- this.nozzles.Add(new LogicalNozzle(this.pumpId, 0,
- PumpStateChangeCommand.StateNozzleOperatingSubMessages.First().MZN枪号,
- PumpStateChangeCommand.StateNozzleOperatingSubMessages.First().PRC价格));
- if (this.lastLogicalDeviceState != LogicalDeviceState.FDC_FUELLING)
- {
- this.lastLogicalDeviceState = LogicalDeviceState.FDC_FUELLING;
- var safe = this.OnCurrentFuellingStatusChange;
- safe?.Invoke(this, new FdcTransactionDoneEventArg(new FdcTransaction()
- {
- Nozzle = this.nozzles.First(),
- Amount = PumpStateChangeCommand.StateNozzleOperatingSubMessages.First().AMN数额,
- Volumn = PumpStateChangeCommand.StateNozzleOperatingSubMessages.First().VOL升数,
- Price = PumpStateChangeCommand.StateNozzleOperatingSubMessages.First().PRC价格,
- Finished = false,
- }));
- }
- }
- }
- else if (context.Incoming.Message is PumpNotifyTransactionDoneCommand PumpNotifyTransactionDoneCommand)
- {
- if (!this.nozzles.Any())
- this.nozzles.Add(new LogicalNozzle(this.pumpId, 0,
- PumpNotifyTransactionDoneCommand.NZN_枪号,
- PumpNotifyTransactionDoneCommand.PRC_成交价格));
- var safe1 = this.OnCurrentFuellingStatusChange;
- safe1?.Invoke(this, new FdcTransactionDoneEventArg(new FdcTransaction()
- {
- // 恒山油机 一个加油点只有一把枪
- Nozzle = this.nozzles.First(),
- Amount = PumpNotifyTransactionDoneCommand.AMN数额,
- Volumn = PumpNotifyTransactionDoneCommand.VOL_升数,
- Price = PumpNotifyTransactionDoneCommand.PRC_成交价格,
- SequenceNumberGeneratedOnPhysicalPump = PumpNotifyTransactionDoneCommand.POS_TTC,
- //AmountTotalizer = ,
- VolumeTotalizer = PumpNotifyTransactionDoneCommand.V_TOT_升累计,
- Finished = true,
- }));
- }
- else
- {
- if (logger.IsDebugEnabled)
- logger.Debug("Incoming an unknown message, will do nothing and ignore.");
- }
- }
- public string Name => this.GetType().FullName;
- public Guid Id => this.uniqueId;
- /// <summary>
- /// Gets the Identification of the pump for the system. Is the logical number of the pump
- /// </summary>
- public int PumpId => this.pumpId;
- /// <summary>
- /// this pump have no way to share same comport since this HengShan protocol content does not contains
- /// any id info, so always static 0 here.
- /// 地址面地址
- /// </summary>
- public int PumpPhysicalId => 0;
- public int AmountDecimalDigits => 2;
- public int VolumeDecimalDigits => 2;
- public int PriceDecimalDigits => 2;
- public int VolumeTotalizerDecimalDigits => 2;
- public virtual async Task<LogicalDeviceState> QueryStatusAsync()
- {
- // if last state is expired, we return a OFFLINE here to FdcClient.
- if (DateTime.Now.Subtract(this.lastLogicalDeviceStateReceivedTime).TotalSeconds > lastLogicalDeviceStateExpiredTime)
- {
- if (this.lastLogicalDeviceState != LogicalDeviceState.FDC_OFFLINE)
- {
- this.lastLogicalDeviceState = LogicalDeviceState.FDC_OFFLINE;
- logger.Info("Pump: " + this.pumpId + ", " + " State switched to FDC_OFFLINE due to cached state expired");
- var safe0 = this.OnStateChange;
- safe0?.Invoke(this, new FdcPumpControllerOnStateChangeEventArg(LogicalDeviceState.FDC_OFFLINE, null));
- }
- return LogicalDeviceState.FDC_OFFLINE;
- }
- return this.lastLogicalDeviceState;
- }
- /// <summary>
- ///
- /// </summary>
- /// <returns>MoneyTotalizer:VolumnTotalizer</returns>
- public async Task<Tuple<int, int>> QueryTotalizerAsync(byte logicalNozzleId)
- {
- throw new NotImplementedException();
- }
- public virtual async Task<bool> ChangeFuelPriceAsync(int newPriceWithoutDecimalPoint, byte logicalNozzleId)
- {
- throw new NotImplementedException();
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="logicalNozzleId">useless for this type of pump, it always one pump one nozzle</param>
- /// <returns></returns>
- public virtual async Task<bool> AuthorizeAsync(byte logicalNozzleId)
- {
- throw new NotImplementedException();
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="moneyAmount"></param>
- /// <param name="logicalNozzleId">useless for this type of pump, it always one pump one nozzle</param>
- /// <returns></returns>
- public virtual async Task<bool> AuthorizeWithAmountAsync(int moneyAmountWithoutDecimalPoint, byte logicalNozzleId)
- {
- throw new NotImplementedException();
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="volumn"></param>
- /// <param name="logicalNozzleId">useless for this type of pump, it always one pump one nozzle</param>
- /// <returns></returns>
- public virtual async Task<bool> AuthorizeWithVolumeAsync(int volumnWithoutDecimalPoint, byte logicalNozzleId)
- {
- throw new NotImplementedException();
- }
- public virtual async Task<bool> FuelingRoundUpByAmountAsync(int amount)
- {
- throw new NotImplementedException();
- }
- #region not implemented
- public async Task<bool> UnAuthorizeAsync(byte logicalNozzleId)
- {
- throw new NotImplementedException();
- }
- public async Task<bool> SuspendFuellingAsync()
- {
- throw new NotImplementedException();
- }
- public async Task<bool> ResumeFuellingAsync()
- {
- throw new NotImplementedException();
- }
- public async Task<bool> FuelingRoundUpByVolumeAsync(int volume)
- { throw new NotImplementedException(); }
- #endregion
- /// <summary>
- /// </summary>
- protected Dictionary<byte, FuelSaleTransaction> logicalNozzleIdToLastFuelSaleTrxMapping = new Dictionary<byte, FuelSaleTransaction>();
- public void OnFdcServerInit(Dictionary<string, object> parameters)
- {
- if (parameters.ContainsKey("LastPriceChange"))
- {
- }
- /* Load Last sale(from db) for void the case of FC accidently disconnect from Pump in fueling,
- and may cause a fueling trx gone from FC control */
- if (parameters.ContainsKey("LastFuelSaleTrx"))
- {
- // nozzle logical id:lastSale
- //var lastFuelSaleTrxes = parameters["LastFuelSaleTrx"] as Dictionary<byte, FuelSaleTransaction>;
- //foreach (var lastFuelSaleTrx in lastFuelSaleTrxes)
- //{
- // logger.Info("Pump: " + this.pumpId + ", OnFdcServerInit, load last fuel sale " +
- // "on logical nozzle: " + lastFuelSaleTrx.Key + " with value: " + lastFuelSaleTrx.Value);
- // this.logicalNozzleIdToLastFuelSaleTrxMapping.Remove(lastFuelSaleTrx.Key);
- // this.logicalNozzleIdToLastFuelSaleTrxMapping.Add(lastFuelSaleTrx.Key, lastFuelSaleTrx.Value);
- //}
- }
- }
- public async Task<bool> LockNozzleAsync(byte logicalNozzleId)
- {
- return false;
- }
- public async Task<bool> UnlockNozzleAsync(byte logicalNozzleId)
- {
- return false;
- }
- }
- }
|