using Edge.Core.Processor;using Edge.Core.IndustryStandardInterface.Pump; using MessageRouter; using Microsoft.Extensions.Logging; using Edge.Core.Parser; using System; using System.Collections.Specialized; using System.Linq; using System.Threading; namespace GlobalCommunicator { public class MessageRouterCommunicator<T> : IDisposable { public static ILogger fccLogger { get; set; } private const string DEFAULT_FUSION_USER_NAME = "SSF"; // default fusion user id private const string DEFAULT_FUSION_PASSWORD = "MINIMEINFINITERINGTONES"; // default fusion password /// <summary> /// 0 for not started, 1 for started already. /// </summary> private int isStarted = 0; private IMessageParser<object, T> parser; public event EventHandler<FccDataReceivedEventArgs> OnDataReceived; private readonly MessageRouterClient msgRouterClient; /// <summary> /// Will automatically call the Start() for MessageRouterClient. /// </summary> /// <param name="msgRouterClient">unstarted MessageRouterClient</param> public MessageRouterCommunicator(IMessageParser<object, T> parser, MessageRouterClient msgRouterClient) { this.parser = parser; this.msgRouterClient = msgRouterClient; this.msgRouterClient.OnConnect += (conn, reconnect) => { fccLogger.LogDebug("Connected with MessageRouterServer"); string clientId = DEFAULT_FUSION_USER_NAME; string password = DEFAULT_FUSION_PASSWORD; string userName = clientId; userName = MsgRouterMessageUtility.AppendSpaceOnRight(userName, 20); password = MsgRouterMessageUtility.AppendSpaceOnRight(password, 25); char[] cryptedPwd = MsgRouterMessageUtility.Crypt(password.ToCharArray(), 25, userName.ToCharArray(), 20); password = MsgRouterMessageUtility.BinToHexString(cryptedPwd, 25); if (!msgRouterClient.SendMessage(MsgRouterMessageUtility.Login(clientId.ToUpper(), password))) fccLogger.LogDebug("Login failed to send to msgRouter server"); SendSubscriptions(); }; this.msgRouterClient.OnDisconnect += (client, exp) => fccLogger.LogDebug("!!!msgRouterClient disconnected with MessageRouterServer"); this.msgRouterClient.OnMessageRouterMessageReceived += this.OnMessageRouterMessageReceived; } private void OnMessageRouterMessageReceived(MessageRouterClient client, string msgType, string evtType, StringDictionary parameters) { fccLogger.LogDebug("Message received from MessageRouterServer"); fccLogger.LogDebug(" message type: " + msgType); fccLogger.LogDebug(" event type: " + evtType); fccLogger.LogDebug(" params(name->value): " + (parameters.Count == 0 ? "" : parameters.Keys.Cast<string>().Select(k => k + "->" + parameters[k]).Aggregate((acc, n) => acc + ", " + n))); if (msgType == "ECHO") { parameters["PumpID"] = "-1"; parameters["EventType"] = "EchoEvent"; this.OnDataReceived?.Invoke(this, new FccDataReceivedEventArgs(parameters)); } else if (msgType == "POST") ProcessMessage(msgType, evtType, parameters); } private void ProcessMessage(string msgType, string evtType, StringDictionary parameters) { string evt = ""; string pumpId = ""; if (evtType.IndexOf("_ID_") > 0) { evt = evtType.Substring(0, evtType.Length - 7); pumpId = evtType.Substring(evtType.Length - 3, 3); } else { evt = evtType; } switch (evt) { #region case "RES_GENERIC_ERROR": break; case "RES_FCRT_PUMPS_CONFIG": break; case "EVT_PUMP_STATUS_CHANGE": ProcessPumpStatusChange(parameters, Convert.ToInt32(pumpId)); break; case "EVT_PUMP_DELIVERY_PROGRESS": ProcessPumpDeliveryProgressChange(parameters, Convert.ToInt32(pumpId)); break; case "RES_SECU_LOGIN": break; case "RES_SECU_ACCESS_DENIED": break; case "RES_PRICES_REFRESH_PRICE_CHANGE_TBL": //LoadNewPrices(); break; case "RES_PRICES_SET_NEW_PRICE_CHANGE": //RefreshPriceChangeTable(); break; case "EVT_NEW_PRICE_CHANGE_APPLIED": //SendFuelPriceChange(); break; case "REQ_RECEIVE_PRESET_FROM_FORECOURT": //ProcessPresetFromFPOS(parameters, Convert.ToInt32(pumpId)); break; case "REQ_RECEIVE_OUTDOOR_TRANSACTION_DENIED": //ProcessOutdoorTrxDeniedFromFPOS(parameters, Convert.ToInt32(pumpId)); break; case "REQ_RECEIVE_OUTDOOR_TRANSACTION_APPROVED": //ProcessOutdoorTrxApprovedFromFPOS(parameters, Convert.ToInt32(pumpId)); break; case "REQ_RECEIVE_OUTDOOR_AIRLOCK": //ProcessOutdoorTrxAirlock(parameters, Convert.ToInt32(pumpId)); break; default: break; #endregion } } private void ProcessPumpDeliveryProgressChange(StringDictionary parameters, int pumpId) { if (string.IsNullOrEmpty(parameters["GR"]) || string.IsNullOrEmpty(parameters["AM"]) || string.IsNullOrEmpty(parameters["PU"]) || string.IsNullOrEmpty(parameters["VO"])) { fccLogger.LogDebug("Ignore ProcessPumpDeliveryProgressChange event for pump: " + pumpId); return; } try { //parameters["PumpID"] = pumpId.ToString(); //parameters["EventType"] = "FuellingStatusChange"; //parameters["Finished"] = "false"; //fccLogger.LogDebug("ProcessPumpDeliveryProgressChange event for pump: " + 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)); //var gradeFriendlyName = Translator.GetFriendlyGradeName(SiteConfigUtility.Default.GetGradeNameByGradeId(int.Parse(gradeId))); //using (var posSqlConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["PosDatabaseConnStr"].ConnectionString)) //{ // try // { // var updatePumpOnFuelingCommand = // new SqlCommand(string.Format("Update jy_info set [status] = '{1}', youpin = N'{2}', qty= {3}, amount= {4} where jihao = '{0}'", // SiteConfigUtility.Default.GetSiteLevelNozzleIdByLogicalNozzleId(p, logicalHoseId), // 'B', // gradeFriendlyName, // currentQty, // currentAmount), // posSqlConnection); // fccLogger.LogDebug("updatePumpOnFuelingCommand: " + updatePumpOnFuelingCommand.CommandText, DebugLogLevel.Maximized); // posSqlConnection.Open(); // updatePumpOnFuelingCommand.ExecuteNonQuery(); // } // catch (Exception ex) // { // fccLogger.LogDebug("executing updatePumpOnFuelingCommand failed, exception detail: " + ex, // DebugLogLevel.Normal); // } //} } catch (Exception ex) { fccLogger.LogDebug("Exception in handling ProcessPumpDeliveryProgressChange:" + ex); } } private void ProcessPumpStatusChange(StringDictionary parameters, int pumpId) { try { parameters["PumpID"] = pumpId.ToString(); parameters["EventType"] = "PumpStatusChange"; fccLogger.LogDebug("ProcessPumpStatusChange event for pump: " + 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.LogError(" Exception in ProcessPumpStatusChange: " + parameters.ToString() + ", detail: \r\n" + ex.ToString()); } //if (pumpStatusStr == "AUTHORIZED") //{ // /* indicate a nozzle was lifted, and pending for start fueling */ //} //else if (pumpStatusStr == "STARTING") //{ // /* I understood this state as an intermidea, very short period once the trigger was clicked on nozzle, can be treated as indicator for fueling is ongoing */ // var gradeId = parameters["GR"]; // var hoseId = int.Parse(parameters["ho"]); // var gradeFriendlyName = Translator.GetFriendlyGradeName(SiteConfigUtility.Default.GetGradeNameByGradeId(int.Parse(gradeId))); // using (var posSqlConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["PosDatabaseConnStr"].ConnectionString)) // { // try // { // var setPumpOnStartingCommand = // new SqlCommand(string.Format( // "Update jy_info set [status] = '{1}', youpin = N'{2}', qty= 0, amount= 0 where jihao = '{0}'" // , SiteConfigUtility.Default.GetSiteLevelNozzleIdByLogicalNozzleId(p, hoseId), 'B', gradeFriendlyName), posSqlConnection); // fccLogger.LogDebug("setPumpOnStartingCommand: " + setPumpOnStartingCommand.CommandText, DebugLogLevel.Maximized); // posSqlConnection.Open(); // setPumpOnStartingCommand.ExecuteNonQuery(); // } // catch (Exception ex) // { // fccLogger.LogDebug("executing setPumpOnStartingCommand failed, exception detail: " + ex, // DebugLogLevel.Normal); // } // } //} //else if (pumpStatusStr == "FUELLING") //{ // /* indicate for fueling is ongoing */ //} //else if (pumpStatusStr == "IDLE") //{ // /* indicate for nozzle if replaced back */ // var sizeLevelNozzleIdsOnPump = SiteConfigUtility.Default.GetSiteLevelNozzleIdsByPumpId(p); // if (!sizeLevelNozzleIdsOnPump.Any()) // { // fccLogger.LogDebug("Could not found any site level nozzle ids for pump: " + p); // 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: " + setPumpOnIdleCommand.CommandText); // posSqlConnection.Open(); // setPumpOnIdleCommand.ExecuteNonQuery(); // } // catch (Exception ex) // { // fccLogger.LogDebug("executing setPumpOnIdleCommand failed, exception detail: " + ex); // } // } //} } public bool Start() { if (0 == Interlocked.CompareExchange(ref this.isStarted, 1, 0)) { this.msgRouterClient.Start(); return true; } else { throw new InvalidOperationException("Already started."); } } public bool IsStarted { get { return this.isStarted == 1; } } private void SendSubscriptions() { Thread.Sleep(100); // pump events this.msgRouterClient.SendMessage(MsgRouterMessageUtility.SubscribePumpStatusChange()); Thread.Sleep(100); // pump delivery this.msgRouterClient.SendMessage(MsgRouterMessageUtility.SubscribePumpDeliveryProgress()); Thread.Sleep(100); // fuel price change events this.msgRouterClient.SendMessage(MsgRouterMessageUtility.SubscribeNewPriceChangeApplied()); Thread.Sleep(100); this.msgRouterClient.SendMessage(MsgRouterMessageUtility.SubscribeRefreshPriceChangeTbl()); Thread.Sleep(100); this.msgRouterClient.SendMessage(MsgRouterMessageUtility.SubscribeSetNewPriceChange()); Thread.Sleep(100); this.msgRouterClient.SendMessage(MsgRouterMessageUtility.SubscribeReceivePresetFromForecourt()); Thread.Sleep(100); this.msgRouterClient.SendMessage(MsgRouterMessageUtility.SubscribeReceiveOutdoorTrxDeniedFromForecourt()); Thread.Sleep(100); this.msgRouterClient.SendMessage(MsgRouterMessageUtility.SubscribeReceiveOutdoorTrxApprovedFromForecourt()); Thread.Sleep(100); this.msgRouterClient.SendMessage(MsgRouterMessageUtility.SubscribeReceiveOutdoorTrxAirlockFromForecourt()); } public void Dispose() { this.msgRouterClient.Dispose(); } } }