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
{
///
/// This pump handler only listen the ic card reader, will never send message.
///
public class SilentPumpHandler : IFdcPumpController, IDeviceHandler
{
static NLog.Logger logger = NLog.LogManager.LoadConfiguration("nlog.config").GetLogger("PumpHandler");
protected IContext context;
public event EventHandler OnStateChange;
///
/// fired on fueling process is on going, the fuel amount should keep changing.
///
public event EventHandler 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 nozzles = new List();
public IEnumerable Nozzles => this.nozzles;
///
///
///
///
public SilentPumpHandler(int pumpId)
{
this.pumpId = pumpId;
//this.nozzles.Add(new LogicalNozzle(pumpId, 1, 1, null));
}
public void Init(IContext context)
{
this.context = context;
}
public virtual async Task Process(IContext 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;
///
/// Gets the Identification of the pump for the system. Is the logical number of the pump
///
public int PumpId => this.pumpId;
///
/// 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.
/// 地址面地址
///
public int PumpPhysicalId => 0;
public int AmountDecimalDigits => 2;
public int VolumeDecimalDigits => 2;
public int PriceDecimalDigits => 2;
public int VolumeTotalizerDecimalDigits => 2;
public virtual async Task 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;
}
///
///
///
/// MoneyTotalizer:VolumnTotalizer
public async Task> QueryTotalizerAsync(byte logicalNozzleId)
{
throw new NotImplementedException();
}
public virtual async Task ChangeFuelPriceAsync(int newPriceWithoutDecimalPoint, byte logicalNozzleId)
{
throw new NotImplementedException();
}
///
///
///
/// useless for this type of pump, it always one pump one nozzle
///
public virtual async Task AuthorizeAsync(byte logicalNozzleId)
{
throw new NotImplementedException();
}
///
///
///
///
/// useless for this type of pump, it always one pump one nozzle
///
public virtual async Task AuthorizeWithAmountAsync(int moneyAmountWithoutDecimalPoint, byte logicalNozzleId)
{
throw new NotImplementedException();
}
///
///
///
///
/// useless for this type of pump, it always one pump one nozzle
///
public virtual async Task AuthorizeWithVolumeAsync(int volumnWithoutDecimalPoint, byte logicalNozzleId)
{
throw new NotImplementedException();
}
public virtual async Task FuelingRoundUpByAmountAsync(int amount)
{
throw new NotImplementedException();
}
#region not implemented
public async Task UnAuthorizeAsync(byte logicalNozzleId)
{
throw new NotImplementedException();
}
public async Task SuspendFuellingAsync()
{
throw new NotImplementedException();
}
public async Task ResumeFuellingAsync()
{
throw new NotImplementedException();
}
public async Task FuelingRoundUpByVolumeAsync(int volume)
{ throw new NotImplementedException(); }
#endregion
///
///
protected Dictionary logicalNozzleIdToLastFuelSaleTrxMapping = new Dictionary();
public void OnFdcServerInit(Dictionary 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;
//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 LockNozzleAsync(byte logicalNozzleId)
{
return false;
}
public async Task UnlockNozzleAsync(byte logicalNozzleId)
{
return false;
}
}
}