| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596 |
- 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 HengShan_Pump_NonIC.MessageEntity;
- 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 HengShan_Pump_NonIC
- {
- public class PumpHandler : IFdcPumpController, IDeviceHandler<byte[], NonICMessageTemplateBase>
- {
- //static ILog fdcLogger = log4net.LogManager.GetLogger("FdcServer");
- //static ILog logger = log4net.LogManager.GetLogger("PumpHandler");
- static NLog.Logger logger = NLog.LogManager.LoadConfiguration("nlog.config").GetLogger("PumpHandler");
- protected IContext<byte[], NonICMessageTemplateBase> 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;
- /// <summary>
- /// Indicator for OnFdcServiceInit function called, the Process() will be called eariler that this function,
- /// </summary>
- protected bool isOnFdcServerInitCalled = false;
- private Guid uniqueId = Guid.NewGuid();
- private int pumpId = -1;
- protected List<LogicalNozzle> nozzles = new List<LogicalNozzle>();
- /// <summary>
- /// this type of pump state change is detected by FC actively polling, then state is always delay reported, so there's a corner case that in a fueling process,
- /// the attendants put back and pull out nozzle very quickly and it happened exactly in the middle of a polling, meanwhile,
- /// an auth request was done to auth the pump again(most likely the autoAuthCallingPump set with True),
- /// then the pump state returned from physical pump will still be read as a fueling state, but actually the
- /// 2nd fueling process is started, so detect the pump state is not enough, need detect if the fueling seq number reset to null(if place back nozzle detected) or not.
- /// </summary>
- protected GetNozzleStatusResponse previousUnfinishedFuelingNozzleStatus;
- public IEnumerable<LogicalNozzle> Nozzles => this.nozzles;
- protected void FireOnStateChangeEvent(LogicalDeviceState state)
- {
- var safe = this.OnStateChange;
- safe?.Invoke(this, new FdcPumpControllerOnStateChangeEventArg(state, this.nozzles.First()));
- }
- protected void FireOnCurrentFuellingStatusChangeEvent(FdcTransaction trx)
- {
- var safe = this.OnCurrentFuellingStatusChange;
- safe?.Invoke(this, new FdcTransactionDoneEventArg(trx));
- }
- /// <summary>
- /// 恒山非IC油机
- /// </summary>
- /// <param name="pumpId"></param>
- /// <param name="nozzlesXmlConfiguration"></param>
- public PumpHandler(int pumpId, string nozzlesXmlConfiguration)
- {
- this.pumpId = pumpId;
- // real nozzle Id put hardcode 1 here since HengShan_pump_nonIC only have 1 nozzle per pump.
- // price is not dectected yet, put Null.
- this.nozzles.Add(new LogicalNozzle(pumpId, 1, 1, null));
- }
- //protected bool isSafeForSend = false;
- public void Init(IContext<byte[], NonICMessageTemplateBase> context)
- {
- this.context = context;
- //this.polling = new Timer(this.pollingInterval);
- //this.polling.Elapsed += (_, __) =>
- //{
- // lock (this.syncObject)
- // {
- // this.isSafeForSend = false;
- // context.Outgoing.Write(new GetNozzleStatusRequest());
- // }
- //};
- //this.polling.Start();
- var timeWindowWithActivePollingOutgoing =
- this.context.Outgoing as TimeWindowWithActivePollingOutgoing<byte[], NonICMessageTemplateBase>;
- timeWindowWithActivePollingOutgoing.PollingMsgProducer = () => new GetNozzleStatusRequest();
- }
- public virtual async Task Process(IContext<byte[], NonICMessageTemplateBase> context)
- {
- if (!isOnFdcServerInitCalled) return;
- this.context = context;
- if (context.Incoming.Message is GetNozzleStatusResponse getNozzleStatusResponse)
- {
- //this.isSafeForSend = true;
- this.lastLogicalDeviceStateReceivedTime = DateTime.Now;
- // put the price by reading the real price.
- this.nozzles.First().RealPriceOnPhysicalPump = getNozzleStatusResponse.单价;
- var latestStatus = getNozzleStatusResponse.GetPumpStatus();
- if (latestStatus.Any(f => f == GetNozzleStatusResponse.PumpStatus.油枪打开)
- && latestStatus.Any(f => f == GetNozzleStatusResponse.PumpStatus.加油结束)
- && latestStatus.Any(f => f == GetNozzleStatusResponse.PumpStatus.不允许加油)
- && latestStatus.Any(f => f == GetNozzleStatusResponse.PumpStatus.电机关)
- && !latestStatus.Any(f => f == GetNozzleStatusResponse.PumpStatus.加油过程))
- {
- /* 非加油状态下的提枪 */
- if (this.lastLogicalDeviceState == LogicalDeviceState.FDC_AUTHORISED)
- {
- logger.Info("Pump: " + this.pumpId + ", " + "收到新状态: 提枪");
- //说明是未提枪时就已经auth成功了,所以还是保持发送 FDC_AUTHORISED 的状态给FdcClient。
- logger.Debug("Pump: " + this.pumpId + ", " + " 未提枪时就已经auth成功了, do nothing");
- }
- else
- {
- if (this.previousUnfinishedFuelingNozzleStatus != null)
- {
- this.previousUnfinishedFuelingNozzleStatus = null;
- // no data loss since getNozzleStatusResponse will still carry last trx data until an auth.
- logger.Info("Pump: " + this.pumpId + ", " + "Detected a fast put back and pull out nozzle case(action time < polling time cause nozzle place back not detected)," +
- "\r\n will fire the trx done event for earlier trx(no data loss)->\r\n "
- + "seqNo: " + getNozzleStatusResponse.流水号
- + ", amount: " + getNozzleStatusResponse.加油金额
- + ", volume: " + getNozzleStatusResponse.加油量
- + ", price: " + getNozzleStatusResponse.单价);
- logger.Info("Pump: " + this.pumpId + ", " + " State switched to FDC_READY(simulate)");
- this.lastLogicalDeviceState = LogicalDeviceState.FDC_READY;
- this.FireOnStateChangeEvent(LogicalDeviceState.FDC_READY);
- var previousFuelingAmount = getNozzleStatusResponse.加油金额;
- var previousFuelingVol = getNozzleStatusResponse.加油量;
- var previousPrice = getNozzleStatusResponse.单价;
- var previousSeqNo = getNozzleStatusResponse.流水号;
- if (this.logicalNozzleIdToLastFuelSaleTrxMapping.ContainsKey(1))
- this.logicalNozzleIdToLastFuelSaleTrxMapping[1] = new FuelSaleTransaction() { TransactionSeqNumberFromPhysicalPump = getNozzleStatusResponse.流水号.ToString() };
- else
- this.logicalNozzleIdToLastFuelSaleTrxMapping.Add(1, new FuelSaleTransaction() { TransactionSeqNumberFromPhysicalPump = getNozzleStatusResponse.流水号.ToString() });
- //ThreadPool.QueueUserWorkItem(o =>
- //{
- var totalizer = await this.QueryTotalizerAsync(1);
- this.FireOnCurrentFuellingStatusChangeEvent(new FdcTransaction()
- {
- // 恒山油机只有一把枪
- Nozzle = this.nozzles.First(),
- Amount = previousFuelingAmount,
- Volumn = previousFuelingVol,
- Price = previousPrice,
- SequenceNumberGeneratedOnPhysicalPump = previousSeqNo,
- AmountTotalizer = totalizer.Item1,
- VolumeTotalizer = totalizer.Item2,
- Finished = true,
- });
- //});
- }
- if (this.lastLogicalDeviceState != LogicalDeviceState.FDC_CALLING)
- {
- logger.Info("Pump: " + this.pumpId + ", " + "收到新状态: 提枪");
- logger.Debug("Pump: " + this.pumpId + ", " + " State switched to FDC_CALLING");
- //直接提枪了
- this.lastLogicalDeviceState = LogicalDeviceState.FDC_CALLING;
- var safe = this.OnStateChange;
- safe?.Invoke(this, new FdcPumpControllerOnStateChangeEventArg(LogicalDeviceState.FDC_CALLING, this.nozzles.First()));
- }
- }
- }
- else if (latestStatus.Any(f => f == GetNozzleStatusResponse.PumpStatus.允许加油)
- && latestStatus.Any(f => f == GetNozzleStatusResponse.PumpStatus.油枪打开)
- && (latestStatus.Any(f => f == GetNozzleStatusResponse.PumpStatus.加油过程)
- || latestStatus.Any(f => f == GetNozzleStatusResponse.PumpStatus.电机打开)))
- {
- /* 正处于加油状态下 */
- this.previousUnfinishedFuelingNozzleStatus = getNozzleStatusResponse;
- if (this.lastLogicalDeviceState != LogicalDeviceState.FDC_FUELLING)
- {
- //status code: B1
- logger.Info("Pump: " + this.pumpId + ", " + "收到新状态: 加油状态中");
- logger.Debug("Pump: " + this.pumpId + ", " + " State switched to FDC_FUELLING");
- this.lastLogicalDeviceState = LogicalDeviceState.FDC_FUELLING;
- var safe0 = this.OnStateChange;
- safe0?.Invoke(this, new FdcPumpControllerOnStateChangeEventArg(LogicalDeviceState.FDC_FUELLING, this.nozzles.First()));
- }
- logger.Debug("Pump: " + this.pumpId + ", " + " fueling in progress with amt: " + getNozzleStatusResponse.加油量
- + ", vol: " + getNozzleStatusResponse.加油量 + ", seq: " + getNozzleStatusResponse.流水号);
- //fire fuelling progress.
- var safe1 = this.OnCurrentFuellingStatusChange;
- safe1?.Invoke(this, new FdcTransactionDoneEventArg(new FdcTransaction()
- {
- // 恒山油机只有一把枪
- Nozzle = this.nozzles.First(),
- Amount = getNozzleStatusResponse.加油金额,
- Volumn = getNozzleStatusResponse.加油量,
- Price = getNozzleStatusResponse.单价,
- SequenceNumberGeneratedOnPhysicalPump = getNozzleStatusResponse.流水号,
- Finished = false,
- }));
- }
- else if (latestStatus.Any(f => f == GetNozzleStatusResponse.PumpStatus.加油结束))
- {
- /* 油机首次上电也会进入此处,并不断发送上一次的加油记录,这种情况下的交易记录并无法判断其之前是否已经发送至系统(并存入数据库),
- 所以继续往系统里送入,由系统判断重复情况。 而其它正常加油过程中的交易记录仅在油机状态变化时才送入系统。*/
- // status code: 40
- //logger.Debug("Pump: " + this.pumpId + ", " + "收到状态: 加油结束");
- this.previousUnfinishedFuelingNozzleStatus = null;
- if (this.lastLogicalDeviceState != LogicalDeviceState.FDC_READY)
- {
- logger.Debug("Pump: " + this.pumpId + ", " + "收到新状态: 加油结束, will send StopRequest(Unauth) anyway");
- this.context.Outgoing.WriteAsync(new StopRequest(),
- (request, testResponse) => testResponse is StopResponse,
- (request, response) =>
- {
- if (response == null) logger.Info("Pump: " + this.pumpId + ", " + "StopRequest(Unauth) timed out");
- else
- {
- var stopResponse = (StopResponse)response;
- if (stopResponse.EnumResult == NonICMessageTemplateBase.Result.失败)
- logger.Info("Pump: " + this.pumpId + ", " + "StopRequest(Unauth) respond a Failure");
- }
- }, 2000);
- logger.Debug("Pump: " + this.pumpId + ", " + " State switched to FDC_READY");
- lastLogicalDeviceState = LogicalDeviceState.FDC_READY;
- var safe0 = this.OnStateChange;
- safe0?.Invoke(this, new FdcPumpControllerOnStateChangeEventArg(LogicalDeviceState.FDC_READY, null));
- // zero trx, do nothing.
- if (getNozzleStatusResponse.加油量 == 0 || getNozzleStatusResponse.加油金额 == 0)
- return;
- // repeat received last fuel sale message, do nothing.
- if (this.logicalNozzleIdToLastFuelSaleTrxMapping.ContainsKey(1)
- && this.logicalNozzleIdToLastFuelSaleTrxMapping[1].TransactionSeqNumberFromPhysicalPump
- == getNozzleStatusResponse.流水号.ToString())
- return;
- // lastSale exists and 流水号 diff
- if (this.logicalNozzleIdToLastFuelSaleTrxMapping.ContainsKey(1)
- && this.logicalNozzleIdToLastFuelSaleTrxMapping[1].TransactionSeqNumberFromPhysicalPump
- != getNozzleStatusResponse.流水号.ToString())
- {
- logger.Info("Pump: " + this.pumpId
- + ", Detect a fuel trx with 流水号: " + getNozzleStatusResponse.流水号 + " which is diff from previous fuel trx(previous 流水号:" +
- this.logicalNozzleIdToLastFuelSaleTrxMapping[1].TransactionSeqNumberFromPhysicalPump + "), will generate a new fuel sale trx with vol: " + getNozzleStatusResponse.加油量);
- this.logicalNozzleIdToLastFuelSaleTrxMapping[1] = new FuelSaleTransaction() { TransactionSeqNumberFromPhysicalPump = getNozzleStatusResponse.流水号.ToString() };
- }
- // lastSale not exists
- if (!this.logicalNozzleIdToLastFuelSaleTrxMapping.ContainsKey(1))
- {
- logger.Info("Pump: " + this.pumpId + ", very first initial trx detected on this pump, will generate a new fuel sale trx(seq: " + getNozzleStatusResponse.流水号 + ", vol: " + getNozzleStatusResponse.加油量 + ", amt: " + getNozzleStatusResponse.加油金额 + ")");
- this.logicalNozzleIdToLastFuelSaleTrxMapping.Add(1, new FuelSaleTransaction() { TransactionSeqNumberFromPhysicalPump = getNozzleStatusResponse.流水号.ToString() });
- }
- var amount = getNozzleStatusResponse.加油金额;
- var fuelingVol = getNozzleStatusResponse.加油量;
- var price = getNozzleStatusResponse.单价;
- var seqNo = getNozzleStatusResponse.流水号;
- //ThreadPool.QueueUserWorkItem(o =>
- //{
- var totalizer = await this.QueryTotalizerAsync(1);
- logger.Info("Pump: " + this.pumpId + ", fire trx done with amt: " + amount + ", vol: " + fuelingVol
- + ", price: " + price + ", seqNo.: " + seqNo);
- var safe1 = this.OnCurrentFuellingStatusChange;
- safe1?.Invoke(this, new FdcTransactionDoneEventArg(new FdcTransaction()
- {
- // 恒山油机 一个加油点只有一把枪
- Nozzle = this.nozzles.First(),
- Amount = amount,
- Volumn = fuelingVol,
- Price = price,
- SequenceNumberGeneratedOnPhysicalPump = seqNo,
- AmountTotalizer = totalizer.Item1,
- VolumeTotalizer = totalizer.Item2,
- Finished = true,
- }));
- //});
- }
- }
- else
- {
- if (this.lastLogicalDeviceState != LogicalDeviceState.FDC_ERRORSTATE)
- {
- this.lastLogicalDeviceState = LogicalDeviceState.FDC_ERRORSTATE;
- logger.Debug("Pump: " + this.pumpId + ", " + "收到未知状态: " + getNozzleStatusResponse.ToLogString() + ", \r\n switch to FDC_ERRORSTATE");
- }
- }
- }
- }
- 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)
- {
- logger.Info("Pump: " + this.pumpId + ", " + " Start QueryTotalizer for logicalNozzle: " + logicalNozzleId);
- if (this.lastLogicalDeviceState == LogicalDeviceState.FDC_CLOSED
- || this.lastLogicalDeviceState == LogicalDeviceState.FDC_OFFLINE)
- {
- logger.Info("Pump: " + this.pumpId + ", " + " Pump is in state FDC_CLOSED or FDC_OFFLINE, will return -1, -1");
- return new System.Tuple<int, int>(-1, -1);
- }
- var result = new System.Tuple<int, int>(-1, -1);
- var response = await this.context.Outgoing.WriteAsync(new GetAccumulateRequest(),
- (request, testResponse) => testResponse is GetAccumulateResponse, 2000);
- if (response == null) logger.Info("Pump: " + this.pumpId + ", " + "QueryTotalizer timed out");
- else
- {
- var accumResponse = (GetAccumulateResponse)response;
- result = new Tuple<int, int>(accumResponse.金额累计, accumResponse.升累计);
- }
- return result;
- }
- public virtual async Task<bool> ChangeFuelPriceAsync(int newPriceWithoutDecimalPoint, byte logicalNozzleId)
- {
- logger.Info("Pump: " + this.pumpId + ", " + " Start ChangeFuelPrice for logicalNozzle: " + logicalNozzleId + " with new price(without decimalPoints): " + newPriceWithoutDecimalPoint);
- if (this.lastLogicalDeviceState == LogicalDeviceState.FDC_CLOSED
- || this.lastLogicalDeviceState == LogicalDeviceState.FDC_OFFLINE)
- {
- logger.Info("Pump: " + this.pumpId + ", " + " Pump is in state FDC_CLOSED or FDC_OFFLINE, ChangeFuelPrice will return false");
- return false;
- }
- var succeed = false;
- var response = await this.context.Outgoing.WriteAsync(new SetFuelPriceRequest() { FuelPrice = newPriceWithoutDecimalPoint },
- (request, testResponse) => testResponse is SetFuelPriceResponse, 2500);
- if (response == null)
- logger.Info("Pump: " + this.pumpId + ", " + "ChangeFuelPrice timed out");
- else
- {
- var priceChangeResponse = (SetFuelPriceResponse)response;
- if (priceChangeResponse.EnumResult != NonICMessageTemplateBase.Result.成功)
- {
- logger.Info("Pump: " + this.pumpId + ", " + "ChangeFuelPriceResponse is NOT NonICMessageTemplateBase.Result.成功");
- succeed = false;
- }
- else
- {
- logger.Info("Pump: " + this.pumpId + ", " + "ChangeFuelPriceResponse succeed");
- succeed = true;
- }
- }
- return succeed;
- }
- /// <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)
- {
- logger.Info("Pump: " + this.pumpId + ", " + "Start Authorize for logicalNozzle: " + logicalNozzleId);
- var succeed = false;
- var response = await this.context.Outgoing.WriteAsync(new StartRequest(),
- (request, testResponse) => testResponse is StartResponse, 2500);
- if (response == null) { logger.Info("Pump: " + this.pumpId + ", " + "Authorize timed out"); }
- else
- {
- var startResponse = (StartResponse)response;
- if (startResponse.EnumResult != NonICMessageTemplateBase.Result.成功)
- {
- logger.Info("Pump: " + this.pumpId + ", " + "StartResponse is NOT NonICMessageTemplateBase.Result.成功");
- succeed = false;
- }
- else
- {
- logger.Info("Pump: " + this.pumpId + ", " + "Authorize (StartResponse) succeed");
- succeed = true;
- }
- }
- return succeed;
- }
- /// <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)
- {
- logger.Info("Pump: " + this.pumpId + ", " + "Start AuthorizeWithAmount for logicalNozzle: " + logicalNozzleId + " with money(without decimalPoint): " + moneyAmountWithoutDecimalPoint);
- var succeed = false;
- var response = await this.context.Outgoing.WriteAsync(new AuthPumpWithAmountRequest() { Amount = moneyAmountWithoutDecimalPoint },
- (request, testResponse) => testResponse is AuthPumpWithAmountResponse, 4000);
- if (response == null) logger.Info("Pump: " + this.pumpId + ", " + "AuthorizeWithAmount timed out");
- var presetResponse = (AuthPumpWithAmountResponse)response;
- if (presetResponse.EnumResult != NonICMessageTemplateBase.Result.成功)
- {
- logger.Info("Pump: " + this.pumpId + ", " + "AuthPumpWithAmountResponse is NOT NonICMessageTemplateBase.Result.成功");
- succeed = false;
- }
- else
- {
- if (this.lastLogicalDeviceState != LogicalDeviceState.FDC_AUTHORISED)
- {
- lastLogicalDeviceState = LogicalDeviceState.FDC_AUTHORISED;
- var safe = this.OnStateChange;
- safe?.Invoke(this, new FdcPumpControllerOnStateChangeEventArg(LogicalDeviceState.FDC_AUTHORISED, this.nozzles.First()));
- }
- Thread.Sleep(500);
- succeed = await this.AuthorizeAsync(logicalNozzleId);
- }
- return succeed;
- }
- /// <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)
- {
- logger.Info("Pump: " + this.pumpId + ", " + "Start AuthorizeWithVolumn for logicalNozzle: " + logicalNozzleId + " with vol(without decimalPoint): " + volumnWithoutDecimalPoint);
- var succeed = false;
- var response = await this.context.Outgoing.WriteAsync(new AuthPumpWithGallonRequest() { Gallon = volumnWithoutDecimalPoint },
- (request, testResponse) => testResponse is AuthPumpWithGallonResponse, 4000);
- if (response == null) logger.Info("Pump: " + this.pumpId + ", " + "AuthPumpWithGallonRequest timed out");
- var presetResponse = (AuthPumpWithGallonResponse)response;
- if (presetResponse.EnumResult != NonICMessageTemplateBase.Result.成功)
- {
- logger.Info("Pump: " + this.pumpId + ", " + "AuthorizeWithVolumnResponse is NOT NonICMessageTemplateBase.Result.成功");
- succeed = false;
- }
- else
- {
- if (this.lastLogicalDeviceState != LogicalDeviceState.FDC_AUTHORISED)
- {
- lastLogicalDeviceState = LogicalDeviceState.FDC_AUTHORISED;
- var safe = this.OnStateChange;
- safe?.Invoke(this, new FdcPumpControllerOnStateChangeEventArg(LogicalDeviceState.FDC_AUTHORISED, this.nozzles.First()));
- }
- Thread.Sleep(500);
- succeed = await this.AuthorizeAsync(logicalNozzleId);
- }
- return succeed;
- }
- public virtual async Task<bool> FuelingRoundUpByAmountAsync(int amount)
- {
- logger.Info("Pump: " + this.pumpId + ", " + " Start FuelingRoundUpByAmount, amount: " + amount + " will be ignored due to hardware limit");
- var succeed = false;
- var response = await this.context.Outgoing.WriteAsync(new RoundUpByAmountRequest(),
- (request, testResponse) => testResponse is RoundUpByAmountResponse, 2500);
- if (response == null)
- {
- succeed = false;
- logger.Info("Pump: " + this.pumpId + ", " + "FuelingRoundUpByAmount timed out");
- }
- else
- {
- var roundUpResponse = (RoundUpByAmountResponse)response;
- if (roundUpResponse.EnumResult != NonICMessageTemplateBase.Result.成功)
- {
- logger.Info("Pump: " + this.pumpId + ", " + "roundUpResponse is NOT NonICMessageTemplateBase.Result.成功");
- succeed = false;
- }
- else
- succeed = true;
- }
- return succeed;
- }
- #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);
- }
- }
- this.isOnFdcServerInitCalled = true;
- }
- public async Task<bool> LockNozzleAsync(byte logicalNozzleId)
- {
- return false;
- }
- public async Task<bool> UnlockNozzleAsync(byte logicalNozzleId)
- {
- return false;
- }
- }
- }
|