MessageRouterCommunicator.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. using Edge.Core.Processor;using Edge.Core.IndustryStandardInterface.Pump;
  2. using MessageRouter;
  3. using Microsoft.Extensions.Logging;
  4. using Edge.Core.Parser;
  5. using System;
  6. using System.Collections.Specialized;
  7. using System.Linq;
  8. using System.Threading;
  9. namespace GlobalCommunicator
  10. {
  11. public class MessageRouterCommunicator<T> : IDisposable
  12. {
  13. public static ILogger fccLogger { get; set; }
  14. private const string DEFAULT_FUSION_USER_NAME = "SSF"; // default fusion user id
  15. private const string DEFAULT_FUSION_PASSWORD = "MINIMEINFINITERINGTONES"; // default fusion password
  16. /// <summary>
  17. /// 0 for not started, 1 for started already.
  18. /// </summary>
  19. private int isStarted = 0;
  20. private IMessageParser<object, T> parser;
  21. public event EventHandler<FccDataReceivedEventArgs> OnDataReceived;
  22. private readonly MessageRouterClient msgRouterClient;
  23. /// <summary>
  24. /// Will automatically call the Start() for MessageRouterClient.
  25. /// </summary>
  26. /// <param name="msgRouterClient">unstarted MessageRouterClient</param>
  27. public MessageRouterCommunicator(IMessageParser<object, T> parser, MessageRouterClient msgRouterClient)
  28. {
  29. this.parser = parser;
  30. this.msgRouterClient = msgRouterClient;
  31. this.msgRouterClient.OnConnect += (conn, reconnect) =>
  32. {
  33. fccLogger.LogDebug("Connected with MessageRouterServer");
  34. string clientId = DEFAULT_FUSION_USER_NAME;
  35. string password = DEFAULT_FUSION_PASSWORD;
  36. string userName = clientId;
  37. userName = MsgRouterMessageUtility.AppendSpaceOnRight(userName, 20);
  38. password = MsgRouterMessageUtility.AppendSpaceOnRight(password, 25);
  39. char[] cryptedPwd = MsgRouterMessageUtility.Crypt(password.ToCharArray(), 25, userName.ToCharArray(), 20);
  40. password = MsgRouterMessageUtility.BinToHexString(cryptedPwd, 25);
  41. if (!msgRouterClient.SendMessage(MsgRouterMessageUtility.Login(clientId.ToUpper(), password)))
  42. fccLogger.LogDebug("Login failed to send to msgRouter server");
  43. SendSubscriptions();
  44. };
  45. this.msgRouterClient.OnDisconnect += (client, exp) => fccLogger.LogDebug("!!!msgRouterClient disconnected with MessageRouterServer");
  46. this.msgRouterClient.OnMessageRouterMessageReceived += this.OnMessageRouterMessageReceived;
  47. }
  48. private void OnMessageRouterMessageReceived(MessageRouterClient client, string msgType, string evtType, StringDictionary parameters)
  49. {
  50. fccLogger.LogDebug("Message received from MessageRouterServer");
  51. fccLogger.LogDebug(" message type: " + msgType);
  52. fccLogger.LogDebug(" event type: " + evtType);
  53. fccLogger.LogDebug(" params(name->value): " + (parameters.Count == 0 ? "" : parameters.Keys.Cast<string>().Select(k => k + "->" + parameters[k]).Aggregate((acc, n) => acc + ", " + n)));
  54. if (msgType == "ECHO")
  55. {
  56. parameters["PumpID"] = "-1";
  57. parameters["EventType"] = "EchoEvent";
  58. this.OnDataReceived?.Invoke(this, new FccDataReceivedEventArgs(parameters));
  59. }
  60. else if (msgType == "POST")
  61. ProcessMessage(msgType, evtType, parameters);
  62. }
  63. private void ProcessMessage(string msgType, string evtType, StringDictionary parameters)
  64. {
  65. string evt = "";
  66. string pumpId = "";
  67. if (evtType.IndexOf("_ID_") > 0)
  68. {
  69. evt = evtType.Substring(0, evtType.Length - 7);
  70. pumpId = evtType.Substring(evtType.Length - 3, 3);
  71. }
  72. else
  73. {
  74. evt = evtType;
  75. }
  76. switch (evt)
  77. {
  78. #region
  79. case "RES_GENERIC_ERROR":
  80. break;
  81. case "RES_FCRT_PUMPS_CONFIG":
  82. break;
  83. case "EVT_PUMP_STATUS_CHANGE":
  84. ProcessPumpStatusChange(parameters, Convert.ToInt32(pumpId));
  85. break;
  86. case "EVT_PUMP_DELIVERY_PROGRESS":
  87. ProcessPumpDeliveryProgressChange(parameters, Convert.ToInt32(pumpId));
  88. break;
  89. case "RES_SECU_LOGIN":
  90. break;
  91. case "RES_SECU_ACCESS_DENIED":
  92. break;
  93. case "RES_PRICES_REFRESH_PRICE_CHANGE_TBL":
  94. //LoadNewPrices();
  95. break;
  96. case "RES_PRICES_SET_NEW_PRICE_CHANGE":
  97. //RefreshPriceChangeTable();
  98. break;
  99. case "EVT_NEW_PRICE_CHANGE_APPLIED":
  100. //SendFuelPriceChange();
  101. break;
  102. case "REQ_RECEIVE_PRESET_FROM_FORECOURT":
  103. //ProcessPresetFromFPOS(parameters, Convert.ToInt32(pumpId));
  104. break;
  105. case "REQ_RECEIVE_OUTDOOR_TRANSACTION_DENIED":
  106. //ProcessOutdoorTrxDeniedFromFPOS(parameters, Convert.ToInt32(pumpId));
  107. break;
  108. case "REQ_RECEIVE_OUTDOOR_TRANSACTION_APPROVED":
  109. //ProcessOutdoorTrxApprovedFromFPOS(parameters, Convert.ToInt32(pumpId));
  110. break;
  111. case "REQ_RECEIVE_OUTDOOR_AIRLOCK":
  112. //ProcessOutdoorTrxAirlock(parameters, Convert.ToInt32(pumpId));
  113. break;
  114. default:
  115. break;
  116. #endregion
  117. }
  118. }
  119. private void ProcessPumpDeliveryProgressChange(StringDictionary parameters, int pumpId)
  120. {
  121. if (string.IsNullOrEmpty(parameters["GR"]) || string.IsNullOrEmpty(parameters["AM"]) ||
  122. string.IsNullOrEmpty(parameters["PU"]) || string.IsNullOrEmpty(parameters["VO"]))
  123. {
  124. fccLogger.LogDebug("Ignore ProcessPumpDeliveryProgressChange event for pump: " + pumpId);
  125. return;
  126. }
  127. try
  128. {
  129. //parameters["PumpID"] = pumpId.ToString();
  130. //parameters["EventType"] = "FuellingStatusChange";
  131. //parameters["Finished"] = "false";
  132. //fccLogger.LogDebug("ProcessPumpDeliveryProgressChange event for pump: " + pumpId);
  133. //foreach (string key in parameters.Keys)
  134. //{
  135. // fccLogger.LogDebug(string.Format("Key: {0}, Value: {1}", key, parameters[key]));
  136. //}
  137. //this.OnDataReceived?.Invoke(this, new FccDataReceivedEventArgs(parameters));
  138. //var gradeFriendlyName = Translator.GetFriendlyGradeName(SiteConfigUtility.Default.GetGradeNameByGradeId(int.Parse(gradeId)));
  139. //using (var posSqlConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["PosDatabaseConnStr"].ConnectionString))
  140. //{
  141. // try
  142. // {
  143. // var updatePumpOnFuelingCommand =
  144. // new SqlCommand(string.Format("Update jy_info set [status] = '{1}', youpin = N'{2}', qty= {3}, amount= {4} where jihao = '{0}'",
  145. // SiteConfigUtility.Default.GetSiteLevelNozzleIdByLogicalNozzleId(p, logicalHoseId),
  146. // 'B',
  147. // gradeFriendlyName,
  148. // currentQty,
  149. // currentAmount),
  150. // posSqlConnection);
  151. // fccLogger.LogDebug("updatePumpOnFuelingCommand: " + updatePumpOnFuelingCommand.CommandText, DebugLogLevel.Maximized);
  152. // posSqlConnection.Open();
  153. // updatePumpOnFuelingCommand.ExecuteNonQuery();
  154. // }
  155. // catch (Exception ex)
  156. // {
  157. // fccLogger.LogDebug("executing updatePumpOnFuelingCommand failed, exception detail: " + ex,
  158. // DebugLogLevel.Normal);
  159. // }
  160. //}
  161. }
  162. catch (Exception ex)
  163. {
  164. fccLogger.LogDebug("Exception in handling ProcessPumpDeliveryProgressChange:" + ex);
  165. }
  166. }
  167. private void ProcessPumpStatusChange(StringDictionary parameters, int pumpId)
  168. {
  169. try
  170. {
  171. parameters["PumpID"] = pumpId.ToString();
  172. parameters["EventType"] = "PumpStatusChange";
  173. fccLogger.LogDebug("ProcessPumpStatusChange event for pump: " + pumpId);
  174. foreach (string key in parameters.Keys)
  175. {
  176. fccLogger.LogDebug(string.Format("Key: {0}, Value: {1}", key, parameters[key]));
  177. }
  178. this.OnDataReceived?.Invoke(this, new FccDataReceivedEventArgs(parameters));
  179. }
  180. catch (Exception ex)
  181. {
  182. fccLogger.LogError(" Exception in ProcessPumpStatusChange: " + parameters.ToString() + ", detail: \r\n" + ex.ToString());
  183. }
  184. //if (pumpStatusStr == "AUTHORIZED")
  185. //{
  186. // /* indicate a nozzle was lifted, and pending for start fueling */
  187. //}
  188. //else if (pumpStatusStr == "STARTING")
  189. //{
  190. // /* 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 */
  191. // var gradeId = parameters["GR"];
  192. // var hoseId = int.Parse(parameters["ho"]);
  193. // var gradeFriendlyName = Translator.GetFriendlyGradeName(SiteConfigUtility.Default.GetGradeNameByGradeId(int.Parse(gradeId)));
  194. // using (var posSqlConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["PosDatabaseConnStr"].ConnectionString))
  195. // {
  196. // try
  197. // {
  198. // var setPumpOnStartingCommand =
  199. // new SqlCommand(string.Format(
  200. // "Update jy_info set [status] = '{1}', youpin = N'{2}', qty= 0, amount= 0 where jihao = '{0}'"
  201. // , SiteConfigUtility.Default.GetSiteLevelNozzleIdByLogicalNozzleId(p, hoseId), 'B', gradeFriendlyName), posSqlConnection);
  202. // fccLogger.LogDebug("setPumpOnStartingCommand: " + setPumpOnStartingCommand.CommandText, DebugLogLevel.Maximized);
  203. // posSqlConnection.Open();
  204. // setPumpOnStartingCommand.ExecuteNonQuery();
  205. // }
  206. // catch (Exception ex)
  207. // {
  208. // fccLogger.LogDebug("executing setPumpOnStartingCommand failed, exception detail: " + ex,
  209. // DebugLogLevel.Normal);
  210. // }
  211. // }
  212. //}
  213. //else if (pumpStatusStr == "FUELLING")
  214. //{
  215. // /* indicate for fueling is ongoing */
  216. //}
  217. //else if (pumpStatusStr == "IDLE")
  218. //{
  219. // /* indicate for nozzle if replaced back */
  220. // var sizeLevelNozzleIdsOnPump = SiteConfigUtility.Default.GetSiteLevelNozzleIdsByPumpId(p);
  221. // if (!sizeLevelNozzleIdsOnPump.Any())
  222. // {
  223. // fccLogger.LogDebug("Could not found any site level nozzle ids for pump: " + p);
  224. // return;
  225. // }
  226. // using (var posSqlConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["PosDatabaseConnStr"].ConnectionString))
  227. // {
  228. // try
  229. // {
  230. // /* idle would not carry nozzle id, so here reset all nozzles on target pump.*/
  231. // var setPumpOnIdleCommand
  232. // = new SqlCommand(sizeLevelNozzleIdsOnPump.Select(siteLevelNozzleId =>
  233. // {
  234. // var totalizer = SiteConfigUtility.Default.GetTotalizer(siteLevelNozzleId);
  235. // return
  236. // string.Format(
  237. // "Update jy_info set [status] = '{1}', qty=0, amount=0, fzqty={2}, fzamount={3}" +
  238. // " where jihao = '{0}'", siteLevelNozzleId, 'F',
  239. // totalizer.Item1, totalizer.Item2);
  240. // })
  241. // .Aggregate((acc, n) => acc + " " + n), posSqlConnection);
  242. // fccLogger.LogDebug("setPumpOnIdleCommand: " + setPumpOnIdleCommand.CommandText);
  243. // posSqlConnection.Open();
  244. // setPumpOnIdleCommand.ExecuteNonQuery();
  245. // }
  246. // catch (Exception ex)
  247. // {
  248. // fccLogger.LogDebug("executing setPumpOnIdleCommand failed, exception detail: " + ex);
  249. // }
  250. // }
  251. //}
  252. }
  253. public bool Start()
  254. {
  255. if (0 == Interlocked.CompareExchange(ref this.isStarted, 1, 0))
  256. {
  257. this.msgRouterClient.Start();
  258. return true;
  259. }
  260. else
  261. {
  262. throw new InvalidOperationException("Already started.");
  263. }
  264. }
  265. public bool IsStarted
  266. {
  267. get { return this.isStarted == 1; }
  268. }
  269. private void SendSubscriptions()
  270. {
  271. Thread.Sleep(100);
  272. // pump events
  273. this.msgRouterClient.SendMessage(MsgRouterMessageUtility.SubscribePumpStatusChange());
  274. Thread.Sleep(100);
  275. // pump delivery
  276. this.msgRouterClient.SendMessage(MsgRouterMessageUtility.SubscribePumpDeliveryProgress());
  277. Thread.Sleep(100);
  278. // fuel price change events
  279. this.msgRouterClient.SendMessage(MsgRouterMessageUtility.SubscribeNewPriceChangeApplied());
  280. Thread.Sleep(100);
  281. this.msgRouterClient.SendMessage(MsgRouterMessageUtility.SubscribeRefreshPriceChangeTbl());
  282. Thread.Sleep(100);
  283. this.msgRouterClient.SendMessage(MsgRouterMessageUtility.SubscribeSetNewPriceChange());
  284. Thread.Sleep(100);
  285. this.msgRouterClient.SendMessage(MsgRouterMessageUtility.SubscribeReceivePresetFromForecourt());
  286. Thread.Sleep(100);
  287. this.msgRouterClient.SendMessage(MsgRouterMessageUtility.SubscribeReceiveOutdoorTrxDeniedFromForecourt());
  288. Thread.Sleep(100);
  289. this.msgRouterClient.SendMessage(MsgRouterMessageUtility.SubscribeReceiveOutdoorTrxApprovedFromForecourt());
  290. Thread.Sleep(100);
  291. this.msgRouterClient.SendMessage(MsgRouterMessageUtility.SubscribeReceiveOutdoorTrxAirlockFromForecourt());
  292. }
  293. public void Dispose()
  294. {
  295. this.msgRouterClient.Dispose();
  296. }
  297. }
  298. }