using System; using System.Collections.ObjectModel; using System.Collections.Generic; using System.Globalization; using System.Threading; using Wayne.Lib; using Wayne.FDCPOSLibrary; namespace Wayne.ForecourtControl.Fusion { public class FUSIONPump : IPumpEx, IDisposable { // Fields private bool blocked; private bool capFuelGradeSelected; private bool capNozzleDetection; private bool capSetLight; private bool capSuspendFuelling; private bool connected; private IFuelling currentFuelling; private string entitySubType; private bool fuelGradeSelected; private List fuellingList; private FUSIONManager manager; private int nfsPumpSymbol; private List nozzles; private bool open; private IIdentifiableEntity parerentDevice; private PriceGroup priceGroup; private int pumpId; private int reservedBy; private Timer runningFuellingDataTimer; private bool _runningFuellingUpdates; private PumpState state; private TankLevelSwitchStatus tankLevelSwitchStatus; // Events public event EventHandler OnEventOccured; public event EventHandler OnFuellingDataChange; public event EventHandler OnFuellingStateChange; public event EventHandler OnNozzleStateChange; public event EventHandler OnStateChange; public event EventHandler OnTankLevelSwitchStatusChange; public event EventHandler OnFuelModeChange; // Methods public FUSIONPump(FUSIONManager manager) { this.manager = manager; this.fuellingList = new List(); this.nozzles = new List(); this.currentFuelling = new FUSIONFuelling(manager, this); } public void AuthorizeAsync(IAuthorizeParameters authorizeParams, EventHandler> requestCompleted, object userToken) { //this.CheckDisposed(); //if (authorizeParams == null) //{ // throw new ArgumentException("Must supply a valid IAuthorizeParams object"); //} //FUSIONAsyncOperation operation = this.manager.AsyncManager.RegisterOperation>(this, requestCompleted, userToken); //this.SendAuthorizationRequest(0xcd, operation.Id, authorizeParams); while (this.manager.forecourtControl.fuelPriceReserved) { Thread.Sleep(200); Trace.WriteLine(String.Format("FUSIONPump.AuthorizeAsync: pumpId={0} - fuel price running, wait ...", this.realId)); } int transactionId = 0; // is generated on the server side // ++FUSIONFuelling.transactionId; FUSIONFuelling currentFuelling = null; currentFuelling = (FUSIONFuelling)(CurrentFuelling); currentFuelling.WritableFuellingSequenceNumber = 0; currentFuelling.WritableAuthorizationId = 0; currentFuelling.WritablePresetType = authorizeParams.PresetType; currentFuelling.WritablePresetValue = authorizeParams.PresetValue; //FG, OCT-13-10, Add PayType to show outdoor payment type on FM currentFuelling.PayType = authorizeParams.PayType; Trace.WriteLine(String.Format("FUSIONPump.AuthorizeAsync: pumpId={0}, presetAmount=[{1}, reservingDeviceId={2}, fuellingType={3}", this.realId, currentFuelling.PresetValue, currentFuelling.ReservingDeviceId, currentFuelling.Type)); this.manager.ifsfManager.AuthoriseFuelPoint(this.realId, transactionId, currentFuelling.Type, currentFuelling.ReservingDeviceId, authorizeParams, requestCompleted, userToken, this); } public void AuthorizeUpdateAsync(IAuthorizeParameters authorizeParams, EventHandler requestCompleted, object userToken) { //this.CheckDisposed(); //if (authorizeParams == null) //{ // throw new ArgumentException("Must supply a valid IAuthorizeParams object"); //} //FUSIONAsyncOperation operation = this.manager.AsyncManager.RegisterOperation(this, requestCompleted, userToken); //this.SendAuthorizationRequest(0xd5, operation.Id, authorizeParams); } private void CheckDisposed() { if (this.manager == null) { throw new ObjectDisposedException("", "The pump object is not available anymore."); } } public void Dispose() { //if (this.runningFuellingDataTimer != null) //{ // this.runningFuellingDataTimer.Dispose(); //} this.manager = null; foreach (FUSIONNozzle nozzle in this.nozzles) { nozzle.Dispose(); } foreach (FUSIONFuelling fuelling in this.fuellingList) { fuelling.Dispose(); } ((FUSIONFuelling)this.currentFuelling).Dispose(); } internal void FireFuellingDataChange(IFuelling fuelling, decimal amount, decimal quantity) { if (this.OnFuellingDataChange != null) { this.OnFuellingDataChange.BeginInvoke(this, new FuellingDataChangeEventArgs(fuelling, amount, quantity), null, null); } } internal void FireFuellingStateChange(IFuelling fuelling, FuellingState state) { if (this.OnFuellingStateChange != null) { this.OnFuellingStateChange.BeginInvoke(this, new FuellingStateChangeEventArgs(fuelling, state), null, null); } } internal void FireNozzleStateChange(INozzle nozzle, NozzleState nozzleState) { if (this.OnNozzleStateChange != null) { this.OnNozzleStateChange.BeginInvoke(this, new NozzleStateChangeEventArgs(nozzle, nozzleState), null, null); } } internal void FirePumpEventOccured(PumpEventType pumpEventType) { if (this.OnEventOccured != null) { this.OnEventOccured.BeginInvoke(this, new PumpEventOccuredEventArgs(pumpEventType), null, null); } } internal void FireFuelModeChange(int mode) { if (this.OnFuelModeChange != null) { this.OnFuelModeChange.BeginInvoke(this, new FuelModeChangeEventArgs(this, mode), null, null); } } private void PerformStopPump(EventHandler requestCompleted, object userToken) { //FUSIONAsyncOperation operation = this.manager.AsyncManager.RegisterOperation(this, requestCompleted, userToken); //Function function = new Function(0xc9, ParserDomain.FillingServer, new Parameter[] { new PrimitiveParameter(0x17, PrimitiveType.Byte, this.pumpId) }); //this.manager.Send(function); //AsyncCompletedEventArgs resultEventArgs = new AsyncCompletedEventArgs(true, operation.UserToken); //operation.Complete(resultEventArgs); this.manager.ifsfManager.TerminateFuelling(this.realId, requestCompleted, userToken, this); } public void ReserveAsync(FuellingType fuellingType, byte DeviceId, EventHandler reservedCompleted, object userToken) { //this.CheckDisposed(); //FUSIONAsyncOperation operation = this.manager.AsyncManager.RegisterOperation(this, reservedCompleted, userToken); //Function function = new Function(0xcc, ParserDomain.FillingServer, new Parameter[] { new PrimitiveParameter(0x66, PrimitiveType.UInt16, operation.Id), new PrimitiveParameter(0x17, PrimitiveType.Byte, this.pumpId), new PrimitiveParameter(5, PrimitiveType.Byte, DeviceId), new PrimitiveParameter(7, PrimitiveType.Int16, NfsConvert.DecodeFillingType(fuellingType)) }); //this.manager.Send(function); FUSIONFuelling currentFuelling = null; currentFuelling = (FUSIONFuelling)(CurrentFuelling); Trace.WriteLine(String.Format("FUSIONPump.ReserveAsync: pumpId={0}, reservingDeviceId={1}, fuellingType={2}", this.realId, currentFuelling.ReservingDeviceId, currentFuelling.Type)); if (currentFuelling.Type == fuellingType && currentFuelling.ReservingDeviceId == DeviceId && reservedCompleted != null) { Trace.WriteLine(String.Format("FUSIONPump.ReserveAsync: pumpId={0}, reservingDeviceId={1}, fuellingType={2} ALREADY RESERVED by the same DeviceId!", this.realId, currentFuelling.ReservingDeviceId, currentFuelling.Type)); reservedCompleted.BeginInvoke(this, new AsyncCompletedEventArgs(true, userToken), null, null); } else { currentFuelling.WritableType = fuellingType; currentFuelling.WritableReservingDeviceId = DeviceId; this.manager.ifsfManager.ReserveFuelPoint(this.realId, reservedCompleted, userToken, this); } //if (reservedCompleted != null) // reservedCompleted.Invoke(this, new AsyncCompletedEventArgs(true, userToken)); } public void ResumeAsync(EventHandler resumeCompleted, object userToken) { //this.CheckDisposed(); //FUSIONAsyncOperation operation = this.manager.AsyncManager.RegisterOperation(this, resumeCompleted, userToken); //this.manager.Send(new Function(0xcb, ParserDomain.FillingServer, new Parameter[] { new PrimitiveParameter(0x66, PrimitiveType.UInt16, operation), new PrimitiveParameter(0x17, PrimitiveType.Byte, this.Id) })); this.manager.ifsfManager.ResumeFuelling(this.realId, resumeCompleted, userToken, this); //if (resumeCompleted != null) // resumeCompleted.Invoke(this, new AsyncCompletedEventArgs(true, userToken)); } private void RunningFuellingTimerProc(object state) { if (this.RunningFuellingUpdates && (this.manager != null)) { this.manager.RequestFillingData(this.pumpId, true); } } private void SendAuthorizationRequest(ushort fid, int sequenceNumber, IAuthorizeParameters authorizeParams) { //this.CheckDisposed(); //Function function = new Function(fid, ParserDomain.FillingServer, new Parameter[] { new PrimitiveParameter(0x66, PrimitiveType.UInt16, sequenceNumber), new PrimitiveParameter(0x17, PrimitiveType.Byte, this.pumpId), new PrimitiveParameter(0x16, PrimitiveType.Byte, NfsConvert.DecodePresetType(authorizeParams.PresetType)), new PrimitiveParameter(0x10, PrimitiveType.Decimal, authorizeParams.PresetValue), new PrimitiveParameter(0x27, PrimitiveType.Byte, NfsConvert.DecodePriceGroup(authorizeParams.PriceGroup)), new PrimitiveParameter(0x25, PrimitiveType.Byte, 0), new PrimitiveParameter(120, PrimitiveType.Byte, Convert.ToInt32(authorizeParams.LockToReleaseClient)) }); //ArrayParameter parameter = new ArrayParameter(14); //for (int i = 0; i < authorizeParams.AllowedFuelGrade.Count; i++) //{ // if (!authorizeParams.AllowedFuelGrade[i]) // { // parameter.Add(new PrimitiveParameter(0x1c, PrimitiveType.Byte, i)); // } //} //function.Add(parameter); //this.manager.Send(function); } public void SetBlockedAsync(bool blocked, EventHandler requestCompleted, object userToken) { //if (blocked) // this.manager.ifsfManager.LockNozzle(this.Id, -1, requestCompleted, userToken); //else // this.manager.ifsfManager.UnlockNozzle(this.Id, -1, requestCompleted, userToken); if (blocked) this.manager.ifsfManager.CloseDevice(this.realId, requestCompleted, userToken, this); else this.manager.ifsfManager.OpenDevice(this.realId, requestCompleted, userToken, this); //if (requestCompleted != null) // requestCompleted.Invoke(this, new AsyncCompletedEventArgs(true, userToken)); } public void SetPriceGroupAsync(PriceGroup priceGroup, EventHandler requestCompleted, object userToken) { //this.CheckDisposed(); //FUSIONAsyncOperation operation = this.manager.AsyncManager.RegisterOperation(this, requestCompleted, userToken); //Function function = new Function(0xd6, ParserDomain.FillingServer, new Parameter[] { new PrimitiveParameter(0x66, PrimitiveType.UInt16, operation.Id), new PrimitiveParameter(0x17, PrimitiveType.Byte, this.pumpId), new PrimitiveParameter(0x27, PrimitiveType.Byte, NfsConvert.DecodePriceGroup(priceGroup)) }); //this.manager.Send(function); if (this.manager.forecourtControl.fuelPriceReserved) this.manager.ifsfManager.ChangeFuelModeAdd(this.manager.forecourtControl.srChangeMode, this.realId, (int)priceGroup, requestCompleted, userToken, this); //this.manager.ifsfManager.ChangeFuelMode(this.Id, (int)priceGroup, requestCompleted, userToken); else this.manager.ifsfManager.ChangeFuelMode(this.realId, (int)priceGroup, requestCompleted, userToken, this); } public void SignalEventAsync(PumpEventType eventType, EventHandler signalEventCompleted, object userToken) { //this.CheckDisposed(); //FUSIONAsyncOperation operation = this.manager.AsyncManager.RegisterOperation(this, signalEventCompleted, userToken); //Function function = new Function(0xd8, ParserDomain.FillingServer, new Parameter[] { new PrimitiveParameter(0x66, PrimitiveType.UInt16, operation.Id), new PrimitiveParameter(0x17, PrimitiveType.Byte, this.Id), new PrimitiveParameter(0x7a, PrimitiveType.UInt16, eventType) }); //this.manager.Send(function); } public void StopAsync(EventHandler requestCompleted, object userToken) { this.CheckDisposed(); this.PerformStopPump(requestCompleted, userToken); } public void SuspendAsync(EventHandler suspendCompleted, object userToken) { this.CheckDisposed(); // FUSIONAsyncOperation operation = this.manager.AsyncManager.RegisterOperation(this, suspendCompleted, userToken); // this.manager.Send(new Function(0xca, ParserDomain.FillingServer, new Parameter[] { new PrimitiveParameter(0x66, PrimitiveType.UInt16, operation), new PrimitiveParameter(0x17, PrimitiveType.Byte, this.Id) })); this.manager.ifsfManager.SuspendFuelling(this.realId, suspendCompleted, userToken, this); } public override string ToString() { return this.ToString("", CultureInfo.InvariantCulture); } public string ToString(IFormatProvider provider) { return this.ToString("", provider); } public string ToString(string format) { return this.ToString(format, CultureInfo.InvariantCulture); } public string ToString(string format, IFormatProvider provider) { return ("Pump DeviceId=" + this.pumpId.ToString(format, provider)); } public void UnauthorizeAsync(EventHandler requestCompleted, object userToken) { this.CheckDisposed(); this.PerformStopPump(requestCompleted, userToken); } public void UnreserveAsync(EventHandler requestCompleted, object userToken) { //this.CheckDisposed(); //FUSIONAsyncOperation operation = this.manager.AsyncManager.RegisterOperation(this, requestCompleted, userToken); //Function function = new Function(210, ParserDomain.FillingServer, new Parameter[] { new PrimitiveParameter(0x66, PrimitiveType.UInt16, operation.Id), new PrimitiveParameter(0x17, PrimitiveType.Byte, this.pumpId) }); //this.manager.Send(function); FUSIONFuelling currentFuelling = null; currentFuelling = (FUSIONFuelling)(CurrentFuelling); currentFuelling.WritableReservingDeviceId = 0; Trace.WriteLine(String.Format("FUSIONPump.UnreserveAsync: pumpId={0}, reservingDeviceId={1}, fuellingType={2}", this.realId, currentFuelling.ReservingDeviceId, currentFuelling.Type)); this.manager.ifsfManager.FreeFuelPoint(this.realId, requestCompleted, userToken, this); //if (requestCompleted != null) // requestCompleted.Invoke(this, new AsyncCompletedEventArgs(true, userToken)); } public PumpState convertPumpState(LogicalDeviceState fdcState) { if (fdcState == LogicalDeviceState.FDC_REQUESTED) return PumpState.Authorized; else if (fdcState == LogicalDeviceState.FDC_AUTHORISED) return PumpState.Authorized; else if (fdcState == LogicalDeviceState.FDC_CALLING) return PumpState.Calling; //else if (fdcState == LogicalDeviceState.FDC_INACTIVATED) return PumpState.Closed; else if (fdcState == LogicalDeviceState.FDC_DISABLED) return PumpState.Closed; else if (fdcState == LogicalDeviceState.FDC_CLOSED) return PumpState.Closed; else if (fdcState == LogicalDeviceState.FDC_FUELLING) return PumpState.Fuelling; else if (fdcState == LogicalDeviceState.FDC_STARTED) return PumpState.Fuelling; else if (fdcState == LogicalDeviceState.FDC_READY) return PumpState.Idle; else if (fdcState == LogicalDeviceState.FDC_OUTOFORDER) return PumpState.Inoperative; else if (fdcState == LogicalDeviceState.FDC_OFFLINE) return PumpState.Inoperative; else if (fdcState == LogicalDeviceState.FDC_SUSPENDED) return PumpState.Suspended; else if (fdcState == LogicalDeviceState.FDC_SUSPENDED_STARTED) return PumpState.Suspended; else if (fdcState == LogicalDeviceState.FDC_SUSPENDED_FUELLING) return PumpState.Suspended; else if (fdcState == LogicalDeviceState.FDC_INVALIDSTATE) return PumpState.Unknown; else if (fdcState == LogicalDeviceState.FDC_UNDEFINED) return PumpState.Unknown; else if (fdcState == LogicalDeviceState.FDC_CONFIGURE) return PumpState.Closed; #if !_USE_OLD_FCONTROL_ else if (fdcState == LogicalDeviceState.FDC_ERRORSTATE) return PumpState.Error; #else else if (fdcState == LogicalDeviceState.FDC_ERRORSTATE) return PumpState.Inoperative; #endif //else if (fdcState == LogicalDeviceState.FDC_LOCKED) return PumpState.Closed; else return PumpState.Unknown; } public IFuelling getFuellingByTransactionId(int transactionId, int releaseToken) { // first look for transactionId or for the authorizationId foreach (IFuelling fuelling in fuellingList) { if (transactionId > 0 && fuelling.FuellingSequenceNumber == transactionId || transactionId == 0 && fuelling.AuthorizationId == releaseToken) return fuelling; } return null; } #region Properties public bool Blocked { get { return this.blocked; } } public bool CapFuelGradeSelected { get { return this.capFuelGradeSelected; } } public bool CapNozzleDetection { get { return this.capNozzleDetection; } } public bool CapSetLight { get { return this.capSetLight; } } public bool CapSuspendFuelling { get { return this.capSuspendFuelling; } } public bool Connected { get { return this.connected; } } public IFuelling CurrentFuelling { get { return this.currentFuelling; } } public string EntitySubType { get { return ""; } } public string EntityType { get { return "Pump"; } } /// /// This is used by the logger and should never be set by implementing classes /// public string FullEntityName { get; set; } public FUSIONManager Manager { get { return this.manager; } } public bool FuelGradeSelected { get { return this.fuelGradeSelected; } } public ReadOnlyCollection Fuellings { get { return this.fuellingList.AsReadOnly(); } } public int Id { get { if (manager.IdPumpShift > 0) return this.pumpId + manager.IdPumpShift; else return this.pumpId + manager.IdShift; } } public int realId { get { return this.pumpId; } } internal int NfsPumpSymbol { get { return this.nfsPumpSymbol; } set { this.nfsPumpSymbol = value; } } public ReadOnlyCollection Nozzles { get { return this.nozzles.AsReadOnly(); } } public bool Open { get { return this.open; } } public IIdentifiableEntity ParentEntity { get { return this.parerentDevice; } } public PriceGroup PriceGroup { get { return priceGroup; } } public int ReservedBy { get { return this.reservedBy; } } public bool RunningFuellingUpdates { get { //return (this.runningFuellingDataTimer != null); return _runningFuellingUpdates; } set { this.CheckDisposed(); if (this.runningFuellingDataTimer != null) { Trace.WriteLine("RunningFuellingTimer disposed on Pump: " + this.pumpId); this.runningFuellingDataTimer.Dispose(); this.runningFuellingDataTimer = null; } if (value) { // TODO read timeout from ini file Trace.WriteLine("RunningFuellingTimer create on Pump: " + this.pumpId); this.runningFuellingDataTimer = new Timer(new TimerCallback(this.RunningFuellingTimerProc), null, manager.forecourtControl.ConfigParam.ReadRunningFuelling, manager.forecourtControl.ConfigParam.ReadRunningFuelling); } //if (value && !_runningFuellingUpdates) //{ // // send GetCurrentFuellingUpdates command // this.manager.ifsfManager.GetCurrentFuellingStatus(this.Id); //} //else if (!value && _runningFuellingUpdates) //{ //} _runningFuellingUpdates = value; } } public PumpState State { get { return this.state; } } public void NozzleStateChange(INozzle nozzle, NozzleState nozzleState) { if (this.OnNozzleStateChange != null) { Trace.WriteLine("OnNozzleStateChange.Invoke"); this.OnNozzleStateChange.BeginInvoke(this, new NozzleStateChangeEventArgs(nozzle, nozzleState), null, null); } } public TankLevelSwitchStatus TankLevelSwitchStatus { get { return this.tankLevelSwitchStatus; } } internal bool WritableBlocked { get { return this.blocked; } set { this.blocked = value; } } internal bool WritableCapFuelGradeSelected { get { return this.capFuelGradeSelected; } set { this.capFuelGradeSelected = value; } } internal bool WritableCapNozzleDetection { get { return this.capNozzleDetection; } set { this.capNozzleDetection = value; } } internal bool WritableCapSetLight { get { return this.capSetLight; } set { this.capSetLight = value; } } internal bool WritableCapSuspendFuelling { get { return this.capSuspendFuelling; } set { this.capSuspendFuelling = value; } } internal bool WritableConnected { get { return this.connected; } set { this.connected = value; } } internal IFuelling WritableCurrentFuelling { get { return this.currentFuelling; } } internal string WritableDeviceName { get { return this.entitySubType; } set { this.entitySubType = value; } } internal bool WritableFuelGradeSelected { get { return this.fuelGradeSelected; } set { this.fuelGradeSelected = value; } } internal List WritableFuellingList { get { return this.fuellingList; } } internal List WritableNozzleList { get { return this.nozzles; } } internal bool WritableOpen { get { return this.open; } set { this.open = value; } } internal IIdentifiableEntity WritableParentDevice { get { return this.parerentDevice; } set { this.parerentDevice = value; } } internal PriceGroup WritablePriceGroup { get { return this.priceGroup; } set { this.priceGroup = value; } } internal int WritablePumpId { get { return this.pumpId; } set { this.pumpId = value; } } internal int WritableReservedBy { get { return this.reservedBy; } set { this.reservedBy = value; } } internal PumpState WritableState { get { return this.state; } set { if (this.state != value) { this.state = value; Trace.WriteLine("state is different"); if (this.OnStateChange != null) { Trace.WriteLine("OnStateChange.Invoke"); this.OnStateChange.BeginInvoke(this, new PumpStateChangeEventArgs(this, this.state), null, null); } } } } internal TankLevelSwitchStatus WritableTankLevelSwitchStatus { get { return this.tankLevelSwitchStatus; } set { if (this.tankLevelSwitchStatus != value) { this.tankLevelSwitchStatus = value; if (this.OnTankLevelSwitchStatusChange != null) { this.OnTankLevelSwitchStatusChange.BeginInvoke(this, new TankLevelSwitchStatusChangeEventArgs(this, this.tankLevelSwitchStatus), null, null); } } } } #endregion // properties } }