123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438 |
- using Edge.Core.Processor;using Edge.Core.IndustryStandardInterface.Pump;
- using LSForecourtSimulatorImpl;
- using MessageRouter;
- using Microsoft.Extensions.Logging;
- using Edge.Core.Parser;
- using System;
- using System.Collections.Generic;
- using System.Collections.Specialized;
- using System.Threading;
- using Wayne.ForecourtControl;
- using Wayne.ForecourtControl.Fusion;
- using Wayne.Lib;
- using Wayne.Lib.IO;
- namespace GlobalCommunicator
- {
- public class FdcCommunicator<T> : IDisposable
- {
- public static ILogger fccLogger { get; set; }
- public event EventHandler<FccDataReceivedEventArgs> OnDataReceived;
- private const string DEFAULT_FDC_SERVER_CONNECT_STRING = "Host=127.0.0.1,Port=4710,ClientId=101,ClientName=PetroChinaProxy,PortB=4710,PortC=4710";
- private readonly string concreteFdcServerConnString = string.Empty;
- private readonly IForecourtControl forecourtControl;
- /// <summary>
- /// 0 for not started, 1 for started already.
- /// </summary>
- private int isStarted = 0;
- private int authorizationId = 0;
- private IMessageParser<object, T> parser;
- private event EventHandler<AsyncCompletedEventArgs<PumpAccumulatorReading>> OnPumpAccumulatorReceived;
- private readonly MessageRouterClient msgRouterClient;
- /// <summary>
- /// The Fdc communicator works as a FDC client which connected to FC.
- /// </summary>
- /// <param name="msgRouterClient">somehow, still need to communicate the Message Router</param>
- public FdcCommunicator(IMessageParser<object, T> parser, MessageRouterClient msgRouterClient, string fdcServerIpAddress, string clientId)
- {
- this.parser = parser;
- this.OnPumpAccumulatorReceived += FdcCommunicator_OnPumpAccumulatorReceived;
- this.concreteFdcServerConnString = DEFAULT_FDC_SERVER_CONNECT_STRING.Replace("127.0.0.1", fdcServerIpAddress)
- .Replace("ClientId=101", "ClientId=" + clientId);
- var fileSupport = FileSupport.fileSupport;
- var config = new FuelModeAndPriceModeConfig(fileSupport.Paths.Parse("FuelModeConfig.xml"), fileSupport);
- this.forecourtControl = FUSIONFactory.CreateForecourtControl(0, config, new InputParameterAuthorizationIdGenerator());
- this.forecourtControl.OnConnectionStateChange += forecourtControl_OnConnectionStateChange;
- this.msgRouterClient = msgRouterClient;
- this.msgRouterClient.Start();
- }
- void forecourtControl_OnConnectionStateChange(object sender, ConnectionChangedEventArgs e)
- {
- fccLogger.LogDebug("forecourtControl_OnConnectionStateChange(), new state: " + e.ConnectionState);
- if (e.ConnectionState == DeviceConnectionState.Disconnected)
- {
- foreach (var pump in this.forecourtControl.Pumps)
- {
- pump.OnFuellingStateChange -= FdcCommunicator_OnFuellingStateChange;
- pump.OnNozzleStateChange -= FdcCommunicator_OnNozzleStateChange;
- pump.OnEventOccured -= FdcCommunicator_OnEventOccured;
- }
- }
- else if (e.ConnectionState == DeviceConnectionState.Connected)
- {
- // sometimes could not receive any notification from FDC server even attached the event handler,
- // suspect some underlying bug in communication layer, so here try sleep a while to avoid(probably) this.
- //
- Thread.Sleep(500);
- foreach (var pump in this.forecourtControl.Pumps)
- {
- pump.OnFuellingStateChange += FdcCommunicator_OnFuellingStateChange;
- pump.OnNozzleStateChange += FdcCommunicator_OnNozzleStateChange;
- pump.OnEventOccured += FdcCommunicator_OnEventOccured;
- }
- const int maxRetryTimes = 10;
- int retriedTimes = 0;
- while (!this.msgRouterClient.SendMessage(MsgRouterMessageUtility.RefreshPumpStatus()))
- {
- if (++retriedTimes > maxRetryTimes) break;
- fccLogger.LogDebug("failed to send RefreshPumpStatus() to MsgRouterServer, will keep retrying until max times reached...");
- Thread.Sleep(2000);
- }
- this.forecourtControl.SetSiteOpenedAsync(true, (_, __) => { }, null);
- }
- }
- void FdcCommunicator_OnEventOccured(object sender, PumpEventOccuredEventArgs e)
- {
- fccLogger.LogDebug("FdcCommunicator_OnEventOccured(), args: " + e);
- }
- void FdcCommunicator_OnNozzleStateChange(object sender, NozzleStateChangeEventArgs e)
- {
- var callingPump = sender as IPump;
- fccLogger.LogDebug("FdcCommunicator_OnNozzleStateChange(), args: pumpId: " + callingPump.Id + " nozzleId: " + e.Nozzle.Id + ", newState: " + e.NozzleState);
- //if (e.NozzleState == NozzleState.In)
- //{
- // /* indicate for nozzle if replaced back */
- // var sizeLevelNozzleIdsOnPump = SiteConfigUtility.Default.GetSiteLevelNozzleIdsByPumpId(callingPump.Id);
- // if (!sizeLevelNozzleIdsOnPump.Any())
- // {
- // fccLogger.LogDebug("Could not found any site level nozzle ids for pump: " + callingPump.Id);
- // return;
- // }
- // using (var posSqlConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["PosDatabaseConnStr"].ConnectionString))
- // {
- // try
- // {
- // /* idle would not carry nozzle id, so here reset all nozzles on target pump.*/
- // var setPumpOnIdleCommand
- // = new SqlCommand(sizeLevelNozzleIdsOnPump.Select(siteLevelNozzleId =>
- // {
- // var totalizer = SiteConfigUtility.Default.GetTotalizer(siteLevelNozzleId);
- // return
- // string.Format(
- // "Update jy_info set [status] = '{1}', qty=0, amount=0, fzqty={2}, fzamount={3}" +
- // " where jihao = '{0}'", siteLevelNozzleId, 'F',
- // totalizer.Item1, totalizer.Item2);
- // })
- // .Aggregate((acc, n) => acc + " " + n), posSqlConnection);
- // fccLogger.LogDebug("setPumpOnIdleCommand(via Fdc): " + setPumpOnIdleCommand.CommandText);
- // posSqlConnection.Open();
- // setPumpOnIdleCommand.ExecuteNonQuery();
- // }
- // catch (Exception ex)
- // {
- // fccLogger.LogDebug("executing setPumpOnIdleCommand(via Fdc) failed, exception detail: " + ex,
- // DebugLogLevel.Normal);
- // }
- // }
- //}
- //else if (this.autoAuthorizePumpWhenCalling && e.NozzleState == NozzleState.Out)
- //{
- // var authParameter = new AuthorizeParameters()
- // {
- // PriceGroup = PriceGroup.FullService,
- // LockToReleaseClient = false,
- // PresetType = PresetType.Amount,
- // PresetValue = 0,
- // Prepay = false,
- // PayType = "PC",
- // AuthorizationId = authorizationId++ % int.MaxValue
- // };
- // for (int i = 0; i < callingPump.Nozzles.Count; i++)
- // {
- // int idFuelGrade = callingPump.Nozzles[i].FuelGrade;
- // authParameter.AllowedFuelGrade[idFuelGrade] = true;
- // }
- // fccLogger.LogDebug("Authorizing for pumpId: " + callingPump.Id);
- // callingPump.AuthorizeAsync((byte)(callingPump.Id - 1), authParameter, (_, arg) =>
- // {
- // var pumpId = (int)(arg.UserToken);
- // if (arg.Success)
- // {
- // fccLogger.LogDebug("AuthorizeAsync finished successfully for pumpId: " + pumpId);
- // }
- // else
- // {
- // fccLogger.LogDebug("AuthorizeAsync failed for pumpId: " + pumpId);
- // }
- // }, callingPump.Id);
- //}
- }
- void FdcCommunicator_OnFuellingStateChange(object sender, FuellingStateChangeEventArgs e)
- {
- try
- {
- fccLogger.LogDebug("FdcCommunicator_OnFuellingStateChange(), args: " + e);
- fccLogger.LogDebug("\r\n PumpID = " + e.Fuelling.Pump.Id +
- "\r\n Nozzle = " + e.Fuelling.Nozzle.Id +
- "\r\n Quantity = " + e.Fuelling.Quantity +
- "\r\n Amount = $" + e.Fuelling.Amount +
- "\r\n FuelGrade = " + e.Fuelling.FuelGrade +
- "\r\n Price = $" + e.Fuelling.Price +
- "\r\n CompletionDateTime = $" + e.Fuelling.CompletionDateTime +
- "\r\n ReservingDeviceId = " + e.Fuelling.ReservingDeviceId +
- "\r\n ReservedBy = " + e.Fuelling.ReservedBy +
- "\r\n FuelPeriodID = " + e.Fuelling.FuelPeriodId +
- "\r\n FuellingSeqNumber = " + e.Fuelling.FuellingSequenceNumber +
- "\r\n State = " + e.State);
- var parameters = new StringDictionary();
- parameters["PumpID"] = e.Fuelling.Pump.Id.ToString();
- parameters["EventType"] = "FuellingStatusChange";
- parameters["Finished"] = "true";
- parameters["State"] = e.State.ToString();
- parameters["FuelingSequenceNo"] = e.Fuelling.FuellingSequenceNumber.ToString();
- parameters["ho"] = e.Fuelling.Nozzle.Id.ToString();
- parameters["GR"] = e.Fuelling.FuelGrade.ToString();
- parameters["VO"] = e.Fuelling.Quantity.ToString();
- parameters["AM"] = e.Fuelling.Amount.ToString();
- parameters["PU"] = e.Fuelling.Price.ToString();
- this.OnDataReceived?.Invoke(this, new FccDataReceivedEventArgs(parameters));
- }
- catch (Exception ex)
- {
- fccLogger.LogDebug("Exception in handling FdcCommunicator_OnFuellingStateChange:" + ex);
- }
- if (e.State == FuellingState.PayableTransaction)
- {
- /* in SinoChem project, the pump was set to FullService mode, so the PayableTransaction case here is impossible to happen, but just leave the code here*/
- this.forecourtControl.Pumps[e.Fuelling.Pump.Id - 1].Fuellings.ForEach(f =>
- {
- var fsn = f.FuellingSequenceNumber;
- fccLogger.LogDebug("Sending SetAsPaidAsync for pumpId: " + f.Pump.Id + ", FuellingSequenceNumber: " + fsn);
- f.SetAsPaidAsync((_, arg) =>
- {
- var pumpId = (int)(arg.UserToken);
- if (arg.Success)
- {
- fccLogger.LogDebug("SetAsPaidAsync finished successfully for pumpId: " + pumpId + ", FuellingSequenceNumber: " + fsn);
- }
- else
- {
- fccLogger.LogDebug("SetAsPaidAsync failed for pumpId: " + pumpId + ", FuellingSequenceNumber: " + fsn);
- }
- }, f.Pump.Id);
- });
- }
- //else if (e.State == FuellingState.Paid)
- //{
- // var posSqlConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["PosDatabaseConnStr"].ConnectionString);
- // using (posSqlConnection)
- // {
- // try
- // {
- // // see a case in site that 0.1 price sale reported in here, checked with FC side which should
- // // just a 0 amount trx, not sure why here changed the price to 0.1(fdc client bug?), no time to fix, just add
- // // a check to skip.
- // if (e.Fuelling.Price <= 1 || e.Fuelling.Amount < 1)
- // {
- // fccLogger.LogDebug("insert xiaofei2 will be skipped due to unexpected price or amount fuel sale-> "
- // + "qty: " + e.Fuelling.Quantity
- // + "Price: " + e.Fuelling.Price
- // + "Amount: " + e.Fuelling.Amount
- // + "seqNo.: " + e.Fuelling.FuellingSequenceNumber,
- // DebugLogLevel.Maximized);
- // return;
- // }
- // var totalizer = SiteConfigUtility.Default.GetTotalizer(e.Fuelling.Pump.Id, e.Fuelling.Nozzle.Id);
- // var updateFuelingTrxDoneCommand =
- // new SqlCommand(
- // string.Format(
- // "insert xiaofei2 (jihao, youpin, qty, danjia, amount, xf_date, xf_time, liushuino, fzqty, fzamount)" +
- // " values({0}, N'{1}', {2}, {3}, {4}, '{5}', '{6}', {7}, {8}, {9})",
- // SiteConfigUtility.Default.GetSiteLevelNozzleIdByLogicalNozzleId(e.Fuelling.Pump.Id, e.Fuelling.Nozzle.Id),
- // Translator.GetFriendlyGradeName(SiteConfigUtility.Default.GetGradeNameByGradeId(e.Fuelling.FuelGrade)),
- // e.Fuelling.Quantity,
- // e.Fuelling.Price,
- // e.Fuelling.Amount,
- // DateTime.Now.Date.ToString("yyyy-MM-dd"),
- // DateTime.Now.ToString("HH:mm:ss"),
- // e.Fuelling.FuellingSequenceNumber,
- // totalizer.Item1,
- // totalizer.Item2),
- // posSqlConnection);
- // fccLogger.LogDebug("updateFuelingTrxDoneCommand: " + updateFuelingTrxDoneCommand.CommandText,
- // DebugLogLevel.Maximized);
- // posSqlConnection.Open();
- // updateFuelingTrxDoneCommand.ExecuteNonQuery();
- // }
- // catch (Exception ex)
- // {
- // fccLogger.LogDebug("executing updateFuelingTrxDoneCommand failed, exception detail: " + ex,
- // DebugLogLevel.Normal);
- // }
- // }
- //}
- }
- public void AuthorizePumpAsync(Dictionary<string, object> parameterDic)
- {
- IPump callingPump = null;
- int pumpId = int.Parse(parameterDic["PumpId"].ToString());
- int sitewiseNozzleId = int.Parse(parameterDic["SitewiseNozzleId"].ToString());
- decimal authAmount = 0;
- decimal volume = 0;
- AuthorizeParameters authParameter = null;
- foreach (var pump in this.forecourtControl.Pumps)
- {
- if (pump.Id == pumpId)
- {
- callingPump = pump;
- break;
- }
- }
- if (parameterDic.ContainsKey("AuthAmount"))
- {
- authAmount = decimal.Parse(parameterDic["AuthAmount"].ToString());
- authParameter = new AuthorizeParameters()
- {
- PriceGroup = PriceGroup.FullService,
- LockToReleaseClient = false,
- PresetType = PresetType.Amount,
- PresetValue = authAmount,
- Prepay = false,
- PayType = "PC",
- AuthorizationId = authorizationId++ % int.MaxValue
- };
- }
- else if (parameterDic.ContainsKey("Volume"))
- {
- volume = decimal.Parse(parameterDic["Volume"].ToString());
- authParameter = new AuthorizeParameters()
- {
- PriceGroup = PriceGroup.FullService,
- LockToReleaseClient = false,
- PresetType = PresetType.Quantity,
- PresetValue = volume,
- Prepay = false,
- PayType = "PC",
- AuthorizationId = authorizationId++ % int.MaxValue
- };
- }
- else
- {
- authParameter = new AuthorizeParameters()
- {
- PriceGroup = PriceGroup.FullService,
- LockToReleaseClient = false,
- PresetType = PresetType.Unknown,
- Prepay = false,
- PayType = "PC",
- AuthorizationId = authorizationId++ % int.MaxValue
- };
- }
- for (int i = 0; i < callingPump.Nozzles.Count; i++)
- {
- int idFuelGrade = callingPump.Nozzles[i].FuelGrade;
- authParameter.AllowedFuelGrade[idFuelGrade] = true;
- }
- fccLogger.LogDebug("Authorizing for pumpId: " + callingPump.Id + ", authAmount:" + authAmount);
- callingPump.AuthorizeAsync((byte)(callingPump.Id - 1), authParameter, (_, arg) =>
- {
- if (arg.Success)
- {
- fccLogger.LogDebug("AuthorizeAsync finished successfully for pumpId: " + pumpId);
- }
- else
- {
- fccLogger.LogDebug("AuthorizeAsync failed for pumpId: " + pumpId);
- }
- var parameters = new StringDictionary();
- parameters["EventType"] = "AuthorizePump";
- parameters["PumpID"] = arg.UserToken.ToString();
- parameters["Result"] = arg.Result.ToString();
- parameters["Success"] = arg.Success.ToString();
- this.OnDataReceived?.Invoke(this, new FccDataReceivedEventArgs(parameters));
- }, callingPump.Id);
- }
- public void QueryTotalizer(Dictionary<string, object> parameterDic)
- {
- var newFuelPrices = new List<IFuelPriceReading>();
- string pumpId = parameterDic["PumpId"].ToString();
- string nozzleId = parameterDic["LogicalNozzleId"].ToString();
- (forecourtControl as FUSIONForecourtControl).GetPumpTotalsAsync(new FuelTotalReading(pumpId, nozzleId, "FP"), OnPumpAccumulatorReceived, null);
- }
- void FdcCommunicator_OnPumpAccumulatorReceived(object sender, AsyncCompletedEventArgs<PumpAccumulatorReading> e)
- {
- try
- {
- var parameters = new StringDictionary();
- parameters["PumpID"] = e.Result.Pump.Id.ToString();
- parameters["EventType"] = "TotalizerReceived";
- parameters["NozzleID"] = e.Result.Nozzle.Id.ToString();
- parameters["AmountTotalizer"] = e.Result.Amount.ToString();
- parameters["VolumeTotalizer"] = e.Result.Quantity.ToString();
- fccLogger.LogDebug("FdcCommunicator_OnPumpAccumulatorReceived event for pump: " + parameters["PumpID"]);
- foreach (string key in parameters.Keys)
- {
- fccLogger.LogDebug(string.Format("Key: {0}, Value: {1}", key, parameters[key]));
- }
- this.OnDataReceived?.Invoke(this, new FccDataReceivedEventArgs(parameters));
- }
- catch (Exception ex)
- {
- fccLogger.LogDebug("Exception in handling FdcCommunicator_OnPumpAccumulatorReceived:" + ex);
- }
- }
- public void SetFuelPrice(Dictionary<string, object> parameterDic)
- {
- var newFuelPrices = new List<IFuelPriceReading>();
- int fuelGrade = int.Parse(parameterDic["FuelGrade"].ToString());
- decimal newPrice = decimal.Parse(parameterDic["NewFuelPrice"].ToString());
- var fuelPriceReading = new FuelPriceReading(fuelGrade, 1, newPrice, string.Empty);
- newFuelPrices.Add(fuelPriceReading);
- // IList<IFuelPriceReading> newFuelPrices, EventHandler< AsyncCompletedEventArgs > requestCompleted, object userToken
- forecourtControl.SetFuelPriceAsync(newFuelPrices, null, null);
- }
- public void Dispose()
- {
- this.forecourtControl.Dispose();
- }
- public bool Start()
- {
- if (0 == Interlocked.CompareExchange(ref this.isStarted, 1, 0))
- {
- fccLogger.LogDebug("Connecting to FDC server with connStr: " + this.concreteFdcServerConnString);
- this.forecourtControl.Connect(this.concreteFdcServerConnString);
- return true;
- }
- else
- {
- throw new InvalidOperationException("Already started.");
- }
- }
- public bool IsStarted
- {
- get { return this.isStarted == 1; }
- }
- }
- }
|