using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Globalization; using System.IO; using System.Linq; using System.Threading; using Wayne.FDCPOSLibrary; using Wayne.ForecourtControl.Fusion.ReadDeviceStatus; using Wayne.Lib; using Wayne.Lib.Log; namespace Wayne.ForecourtControl.Fusion { public class FUSIONForecourtControl : IForecourtControl, IConnectable, IIdentifiableEntity, IDisposable { // Fields private string clientName; private string connectionString; private DeviceConnectionState connectionState = DeviceConnectionState.Disconnected; private List fuelPriceList = new List(); private int id; private FUSIONManager _manager; public FUSIONManager manager { get { return _manager; } } private List pricePoleList = new List(); private List pumpList = new List(); private List tankGroupList = new List(); private List fuelProducts = new List(); private int siteMode; private bool siteOpened; public ServiceRequestChangeFuelMode srChangeMode = null; public bool fuelPriceReserved; public ReadDeviceStatusController DeviceStatusController { get; private set; } // Events public event EventHandler OnAlarm; public event EventHandler OnConnectionStateChange; public event EventHandler OnConfigurationChange; public event EventHandler OnFuelPriceChange; public event EventHandler OnSiteModeChange; private readonly DebugLogger debugLogger; #region Methods public FUSIONForecourtControl(int deviceId, ForecourtEntityTypes managedEntityTypes, int[] managedPumpIds, IPumpAuthorizationIdGenerator authorizationIdGenerator) : this(deviceId, managedEntityTypes, managedPumpIds, null, authorizationIdGenerator) { } public FUSIONForecourtControl(int deviceId, ForecourtEntityTypes managedEntityTypes, int[] managedPumpIds, IForecourtConfiguration config, IPumpAuthorizationIdGenerator authorizationIdGenerator) { this.id = deviceId; debugLogger = new DebugLogger(this, true); ForecourtConfiguration = config; DebugLog("Creating FUSIONManager"); DeviceStatusController = new ReadDeviceStatusController(this, this); DeviceStatusController.Initialize(); this._manager = new FUSIONManager(this, managedEntityTypes, managedPumpIds, authorizationIdGenerator, DeviceStatusController); fuelPriceReserved = false; siteOpened = true; DebugLog("Creating ReadDeviceStatusController"); } private void DebugLog(string s) { if (debugLogger.IsActive()) debugLogger.Add(s); } public void ActivateFuelPricesAsync(EventHandler requestCompleted, object userToken) { DebugLog("ActivateFuelPricesAsync init"); int iFuelGrade; decimal price; ServiceRequestChangeFuelPrice sr = new ServiceRequestChangeFuelPrice(); foreach (FUSIONFuelPrice fuelprice in WritableFuelPriceList) { try { Monitor.Enter(fuelprice.locker); iFuelGrade = fuelprice.WritableFuelGrade; DebugLog(string.Format("fuelGrade={0}, ((FUSIONFuelPrice)fuelprice).Changed={1}", fuelprice.WritableFuelGrade, fuelprice.Changed)); if (fuelprice.Changed) { for (int pg = PriceGroup.MinValue; pg <= PriceGroup.MaxValue; pg++) { FUSIONFuelPriceAddPricePerPriceGroup pgd = (FUSIONFuelPriceAddPricePerPriceGroup)(fuelprice.PriceGroupDelta); DebugLog(string.Format("pg = {0}, pgd.getChanged(mode)={1}", pg, pgd.getChanged(pg))); if (pgd.getChanged(pg)) { price = fuelprice.BasePrice + fuelprice.GeneralPriceDelta + fuelprice.PriceGroupDelta[pg]; // Get Fuel Modes that use this price group var fuelModes = manager.forecourtControl.ForecourtConfiguration.GetFuelModes(pg); foreach (var mode in fuelModes) { this._manager.ifsfManager.ChangeFuelPriceAdd(sr, fuelprice.WritableFuelGrade, price, mode); } } } } } catch (Exception ex) { DebugLog("ActivateFuelPricesAsync Exception! " + ex); } finally { Monitor.Exit(fuelprice.locker); } } this._manager.ifsfManager.ChangeFuelPriceSend(sr, null, null, null); foreach (IFuelPrice fuelprice in FuelPrices) { ((FUSIONFuelPrice)fuelprice).WritableReserved = false; } srChangeMode = null; fuelPriceReserved = false; if (requestCompleted != null) requestCompleted(this, new AsyncCompletedEventArgs(true, userToken)); DebugLog("ActivateFuelPricesAsync end"); } public void SetFuelPriceAsync(IList newFuelPrices, EventHandler requestCompleted, object userToken) { DebugLog("SetFuelPriceAsync init"); var sr = new ServiceRequestChangeFuelPrice(); foreach (var newFuelPrice in newFuelPrices.OfType()) { try { var fuelMode = manager.forecourtControl.ForecourtConfiguration.GetDefaultFuelMode(newFuelPrice.PriceGroup); DebugLog(string.Format("fuelGrade={0}, fuelprice={1}, mode={2}", newFuelPrice.Fuelgrade, newFuelPrice.Price, fuelMode)); this._manager.ifsfManager.ChangeFuelPriceAdd(sr, newFuelPrice.Fuelgrade, newFuelPrice.Price, fuelMode); } catch (Exception ex) { DebugLog("SetFuelPriceAsync Exception! " + ex); } } this._manager.ifsfManager.ChangeFuelPriceSend(sr, requestCompleted, userToken, null); DebugLog("SetFuelPriceAsync end"); } public void CloseReconciliationPeriodAsync(EventHandler requestCompleted, object userToken) { DebugLog("CloseReconciliationPeriodAsync init"); this._manager.ifsfManager.CloseReconciliationPeriodAsyncSend(requestCompleted, userToken, null); DebugLog("CloseReconciliationPeriodAsync end"); } public void Connect(string connectionString) { this.connectionString = connectionString; Thread runConnectThread = new Thread(ConnectThreadProc); runConnectThread.Start(); } private void ConnectThreadProc() { this.manager.Connect(connectionString); } public void Disconnect() { this.WritableConnectionState = DeviceConnectionState.Disconnecting; this.manager.Disconnect(); } public void Dispose() { this.Dispose(true); GC.SuppressFinalize(this); } private void Dispose(bool disposing) { if (disposing) { DeviceStatusController.Dispose(); FUSIONFactory.Remove(this); this.manager.Dispose(); debugLogger.Dispose(); } } ~FUSIONForecourtControl() { this.Dispose(false); } internal void FireAlarmEvent(AlarmEventArgs args) { if (this.OnAlarm != null) { this.OnAlarm(this, args); } } internal void FireConfigurationChangeEvent(ConfigurationChangeEventArgs args) { if (this.OnConfigurationChange != null) { this.OnConfigurationChange(this, args); } } public void ReserveFuelPricesAsync(EventHandler requestCompleted, object userToken) { fuelPriceReserved = true; srChangeMode = new ServiceRequestChangeFuelMode(); if (FDCGlobal.ProtocolVersion <= FDCVersion.V0007) srChangeMode.RequestType = "ChangeFuelMode"; else srChangeMode.RequestType = "ChangeFPFuelMode"; foreach (IFuelPrice fuelprice in FuelPrices) { ((FUSIONFuelPrice)fuelprice).WritableReserved = true; } if (requestCompleted != null) requestCompleted(this, new AsyncCompletedEventArgs(true, userToken)); } public void SetSiteModeAsync(int siteMode, EventHandler requestCompleted, object userToken) { WritableSiteMode = siteMode; if (requestCompleted != null) requestCompleted(this, new AsyncCompletedEventArgs(true, userToken)); string sValue = IniFile.IniReadValue(ConfigurationParams.inifile, "Test", "Operation"); if (sValue != "") { Test(); } } public void SetSiteOpenedAsync(bool opened, EventHandler requestCompleted, object userToken) { if (opened) { this.manager.ifsfManager.StartForecourt(requestCompleted, userToken, this); } else this.manager.ifsfManager.StopForecourt(requestCompleted, userToken, this); } public void Test() { int par1 = -1, par2 = -1; int id = -1; int trid = -1; int nozzleId = -1; string sValue = IniFile.IniReadValue(ConfigurationParams.inifile, "Test", "Operation"); string[] sElems; StreamReader sr = new StreamReader(ConfigurationParams.getSINPPath("ini\\") + sValue); while (sr.Peek() != -1) { sValue = sr.ReadLine(); sElems = sValue.Split(','); try { if (sElems.GetLength(0) > 1) { try { par1 = Convert.ToInt32(sElems[1]); } catch (Exception ex) { } } if (sElems.GetLength(0) > 2) { try { par2 = Convert.ToInt32(sElems[2]); } catch (Exception ex) { } } sValue = sElems[0]; id = par1; trid = par2; } catch (Exception ex) { } if (sValue == "StartFuelPointTest") { manager.ifsfManager.StartFuelPointTest(id, null, null, null); } else if (sValue == "EndFuelPointTest") { this.manager.ifsfManager.EndFuelPointTest(id, null, null, null); } else if (sValue == "CloseFuelPoint") { this.manager.ifsfManager.CloseFuelPoint(id, null, null, null); } else if (sValue == "OpenFuelPoint") { this.manager.ifsfManager.OpenFuelPoint(id, null, null, null); } else if (sValue == "AuthoriseFuelPoint") { AuthorizeParameters authParams = new AuthorizeParameters(); authParams.PresetType = PresetType.Amount; authParams.PresetValue = 50; this.manager.ifsfManager.AuthoriseFuelPoint(id, trid, FuellingType.Unknown, 0, authParams, null, null, null); } else if (sValue == "SuspendFuelling") { FUSIONPump pump = this.manager.GetPumpById(id); if (pump != null) pump.SuspendAsync(new EventHandler(Test_SuspendResult), null); //this.manager.ifsfManager.SuspendFuelling(id, null, null); } else if (sValue == "ResumeFuelling") { FUSIONPump pump = this.manager.GetPumpById(id); if (pump != null) pump.ResumeAsync(new EventHandler(Test_ResumeResult), null); //this.manager.ifsfManager.ResumeFuelling(id, null, null); } else if (sValue == "TerminateFuelling") { this.manager.ifsfManager.TerminateFuelling(id, null, null, null); } else if (sValue == "LogOff") { this.manager.ifsfManager.LogOff(); } else if (sValue == "LogOn") { this.manager.ifsfManager.LogOn("", ""); } else if (sValue == "GetFuelMode") { this.manager.ifsfManager.GetFuelMode(id, null, null, null); } else if (sValue == "GetModeTable") { this.manager.ifsfManager.GetModeTable(null, null, null); } else if (sValue == "ClearFuelSaleTrx") { this.manager.ifsfManager.ClearFuelSaleTrx(id, trid, 0, "", null, null, null); } else if (sValue == "LockFuelSaleTrx") { this.manager.ifsfManager.LockFuelSaleTrx(id, trid, 0, null, null, null); } else if (sValue == "UnlockFuelSaleTrx") { this.manager.ifsfManager.UnlockFuelSaleTrx(id, trid, 0, null, null, null); } else if (sValue == "getCountrySetting") { this.manager.ifsfManager.GetCountrySettings(null, null, null); } else if (sValue == "GetCurrentFuellingStatus") { this.manager.ifsfManager.GetCurrentFuellingStatus(id, null, null, null); } else if (sValue == "LockNozzle") { this.manager.ifsfManager.LockNozzle(id, nozzleId, null, null, null); } else if (sValue == "UnlockNozzle") { this.manager.ifsfManager.UnlockNozzle(id, nozzleId, null, null, null); } else if (sValue == "GetDeviceState") { this.manager.ifsfManager.GetDeviceState(Wayne.FDCPOSLibrary.DeviceType.DT_FuelDispenser, id, null, null, null); } else if (sValue == "GetFuelPointTotals") { nozzleId = par2; this.manager.ifsfManager.GetFuelPointTotals(id, nozzleId, null, null, null); } else if (sValue == "CloseFuelPoint") { this.manager.ifsfManager.CloseFuelPoint(id, null, null, null); } else if (sValue == "OpenFuelPoint") { this.manager.ifsfManager.OpenFuelPoint(id, null, null, null); } else if (sValue == "ReserveFuelPoint") { FUSIONPump pump = this.manager.GetPumpById(id); if (pump != null) pump.ReserveAsync(FuellingType.Unknown, 0, new EventHandler(Test_ReserveResult), null); //this.manager.ifsfManager.ReserveFuelPoint(id, null, null); } else if (sValue == "FreeFuelPoint") { FUSIONPump pump = this.manager.GetPumpById(id); if (pump != null) pump.UnreserveAsync(new EventHandler(Test_UnreserveResult), null); //this.manager.ifsfManager.FreeFuelPoint(id, null, null); } else if (sValue == "GetFuelSaleTrxDetails") { this.manager.ifsfManager.GetFuelSaleTrxDetails(id, trid, 0, null, null, null); } else if (sValue == "GetAvailableFuelSaleTrxs") { this.manager.ifsfManager.GetAvailableFuelSaleTrxs(id, null, null, null); } else if (sValue == "ChangeFuelMode") { int priceGroup = par2; this.manager.ifsfManager.ChangeFuelMode(id, priceGroup, 0, null, null, null); } else if (sValue == "SendConfig") { this.manager.ifsfManager.SendConfig(sElems[1], null, null, null); } else { } } sr.Close(); } private void Test_SuspendResult(Object src, Wayne.Lib.AsyncCompletedEventArgs completed) { try { IPump pump = (IPump)completed.UserToken; if (pump != null) { DebugLog(string.Format("pump={0}, result={1}", ((FUSIONPump)(pump)).realId, completed.Success)); } } catch (Exception ex) { DebugLog(string.Format("EXCEPTION! {0}", ex)); } } private void Test_ResumeResult(Object src, Wayne.Lib.AsyncCompletedEventArgs completed) { try { IPump pump = (IPump)completed.UserToken; if (pump != null) { DebugLog(string.Format("pump={0}, result={1}", ((FUSIONPump)(pump)).realId, completed.Success)); } } catch (Exception ex) { DebugLog(string.Format("EXCEPTION! {0}", ex)); } } private void Test_ReserveResult(Object src, Wayne.Lib.AsyncCompletedEventArgs completed) { try { IPump pump = (IPump)completed.UserToken; if (pump != null) { DebugLog(string.Format("pump={0}, result={1}", ((FUSIONPump)(pump)).realId, completed.Success)); } } catch (Exception ex) { DebugLog(string.Format("EXCEPTION! {0}", ex)); } } private void Test_UnreserveResult(Object src, Wayne.Lib.AsyncCompletedEventArgs completed) { try { IPump pump = (IPump)completed.UserToken; if (pump != null) { DebugLog(string.Format("pump={0}, result={1}", ((FUSIONPump)(pump)).realId, completed.Success)); } } catch (Exception ex) { DebugLog(string.Format("EXCEPTION! {0}", ex)); } } public override string ToString() { return ("Forecourt Control ClientId=" + this.ClientId.ToString(CultureInfo.InvariantCulture)); } public void UnreserveFuelPricesAsync(EventHandler requestCompleted, object userToken) { //if (this.manager.forecourtControl.fuelPriceReserved) // this.manager.ifsfManager.ChangeFuelModeSend(this.manager.forecourtControl.srChangeMode, requestCompleted, // userToken, this); foreach (IFuelPrice fuelprice in FuelPrices) { ((FUSIONFuelPrice)fuelprice).WritableReserved = false; } if (requestCompleted != null && !this.manager.forecourtControl.fuelPriceReserved) requestCompleted(this, new AsyncCompletedEventArgs(true, userToken)); srChangeMode = null; fuelPriceReserved = false; } #endregion /// /// Get Fuel prices. /// /// Delegate that will be called on completion. /// A user supplied object that will be returned in the requestCompleted callback public void GetFuelPricesAsync( EventHandler>> requestCompleted, object userToken) { DebugLog("GetFuelPricesAsync init"); this.manager.ifsfManager.GetFuelPrices(requestCompleted, userToken, this); } /// /// Get Pump Totals. /// /// Delegate that will be called on completion. /// A user supplied object that will be returned in the requestCompleted callback public void GetPumpTotalsAsync(FuelTotalReading totalReading, EventHandler> requestCompleted, object userToken) { DebugLog("GetPumpTotalsAsync init"); this._manager.ifsfManager.GetPumpTotals(totalReading.DeviceClass, requestCompleted, userToken, this); } /// /// Get Tank reconciliation /// /// /// Delegate that will be called on completion. /// A user supplied object that will be returned in the requestCompleted callback public void GetTankReconciliationAsync(int deviceId, EventHandler> requestCompleted, object userToken) { DebugLog("GetTankReconciliationAsync init"); this.manager.ifsfManager.GetTankReconciliation(deviceId, requestCompleted, userToken, this); } /// /// Get Tank delivery /// /// /// Delegate that will be called on completion. /// A user supplied object that will be returned in the requestCompleted callback public void GetTankDeliveryAsync(int deviceId, EventHandler> requestCompleted, object userToken) { DebugLog("GetTankDeliveryAsync init"); this.manager.ifsfManager.GetTankDelivery(deviceId, requestCompleted, userToken, this); } #region Properties public int ClientId { get { return int.Parse(this.manager.ifsfManager.clientSocket.applicationSender); } } public string ClientName { get { return this.clientName; } } public DeviceConnectionState ConnectionState { get { return this.connectionState; } } public string EntitySubType { get { return ""; } } public string EntityType { get { return "FUSIONForecourtControl"; } } /// /// This is used by the logger and should never be set by inheriting classes /// public string FullEntityName { get; set; } public ReadOnlyCollection FuelPrices { get { return new ReadOnlyCollection(new List(this.fuelPriceList)); } } public ReadOnlyCollection FuelPriceReadings { get { return this.manager.FuelPriceReadings.AsReadOnly(); } } public int Id { get { return this.id; } set { id = value; } } public IIdentifiableEntity ParentEntity { get { return null; } } public ReadOnlyCollection PricePoles { get { return this.pricePoleList.AsReadOnly(); } } public ReadOnlyCollection Pumps { get { return this.pumpList.AsReadOnly(); } } public ReadOnlyCollection FuelProducts { get { return this.WritableFuelProducts.AsReadOnly(); } } public int SiteMode { get { return this.siteMode; } } public bool SiteOpened { get { return this.siteOpened; } } public ReadOnlyCollection TankGroups { get { return this.tankGroupList.AsReadOnly(); } } internal DeviceConnectionState WritableConnectionState { get { return this.connectionState; } set { DebugLog(string.Format("old connectionState={0}, new connectionState={1}", this.connectionState, value)); if (this.connectionState != value) { this.connectionState = value; if (this.OnConnectionStateChange != null) { this.OnConnectionStateChange(this, new ConnectionChangedEventArgs(value)); } } } } internal List WritableFuelPriceList { get { return this.fuelPriceList; } } internal List WritablePricePoleList { get { return this.pricePoleList; } } internal List WritablePumpList { get { return this.pumpList; } } internal List WritableFuelProducts { get { return fuelProducts; } } internal int WritableSiteMode { get { return this.siteMode; } set { if (this.siteMode != value) { this.siteMode = value; if (this.OnSiteModeChange != null) { this.OnSiteModeChange(this, new SiteModeChangeEventArgs(this.siteMode, this.siteOpened)); } } } } internal List WritableTankGroupList { get { return this.tankGroupList; } } public IFuelPrice getFuelPriceByProductId(int productId) { foreach (FUSIONFuelPrice fuelprice in WritableFuelPriceList) { if (productId == fuelprice.WritableFuelGrade) return fuelprice; } return null; } public IForecourtConfiguration ForecourtConfiguration { get; internal set; } #endregion #region IForecourtControl Members public void ReservePumpClusterAsync(int terminalDeviceId, EventHandler requestCompleted, object userToken) { throw new NotImplementedException(); } public void UnreservePumpClusterAsync(int terminalDeviceId, EventHandler requestCompleted, object userToken) { throw new NotImplementedException(); } public void SendDeviceAlarmAsync(int terminalDeviceId, string deviceClassType, IEnumerable alarmIds, IEnumerable messages, EventHandler requestCompleted, object userToken) { manager.ifsfManager.SetDeviceAlarm(deviceClassType, terminalDeviceId, alarmIds, messages, requestCompleted, userToken, this); } #endregion public void ReadStatusBeforeSetConnectionState(DeviceConnectionState deviceConnectionState) { if (deviceConnectionState == DeviceConnectionState.Connected) { DeviceStatusController.Start(); } else { WritableConnectionState = deviceConnectionState; } } } }