FdcCommunicator.cs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. using SinoChemFC2PosProxy.Communicator;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Configuration;
  5. using System.Data.SqlClient;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading;
  9. using Wayne.Lib;
  10. using Wayne.Lib.Log;
  11. namespace SinoChemFC2PosProxy
  12. {
  13. //public delegate void NozzleLiftedHandler(int sitewiseNozzleId, IPump callingPump);
  14. //public delegate void NozzleReplacedHandler(int sitewiseNozzleId);
  15. //public delegate void FuelingDoneHandler(int sitewiseNozzleId, int seqNum, decimal fuelAmount, decimal quantity, long authId);
  16. //public delegate void AuthOkHandler(int sitewiseNozzleId, long? authId);
  17. //public delegate void AuthFailedHandler(int sitewiseNozzleId);
  18. public class FdcCommunicator //: IDisposable//, ICommunicator
  19. {
  20. //public event NozzleLiftedHandler NozzleLifted;
  21. //public event NozzleReplacedHandler NozzleReplaced;
  22. //public event FuelingDoneHandler FuelingDone;
  23. //public event AuthOkHandler AuthOk;
  24. //public event AuthFailedHandler AuthFailed;
  25. /// <summary>
  26. /// 0 for not started, 1 for started already.
  27. /// </summary>
  28. private int isStarted = 0;
  29. private const string DEFAULT_FDC_SERVER_CONNECT_STRING = "Host=127.0.0.1,Port=4710,ClientId=101,ClientName=PetroChinaProxy,PortB=4710,PortC=4710";
  30. private readonly string concreteFdcServerConnString = string.Empty;
  31. //private readonly DebugLogger debugLogger =
  32. // new DebugLogger(new IdentifiableEntity(0, "FC2PosProxyMain", "", null));
  33. static NLog.Logger debugLogger = NLog.LogManager.LoadConfiguration("nlog.config").GetLogger("PumpHandler");
  34. //private readonly Wayne.ForecourtControl.IForecourtControl forecourtControl;
  35. //private readonly MessageRouterClient msgRouterClient;
  36. private bool autoAuthorizePumpWhenCalling = false;
  37. /// <summary>
  38. /// The Fdc communicator works as a FDC client which connected to FC.
  39. /// </summary>
  40. /// <param name="msgRouterClient">somehow, still need to communicate the Message Router</param>
  41. public FdcCommunicator()
  42. {
  43. //if (!String.IsNullOrEmpty(
  44. // ConfigurationManager.AppSettings["AutoAuthorizePumpWhenCalling"]))
  45. //{
  46. // this.autoAuthorizePumpWhenCalling =
  47. // (ConfigurationManager.AppSettings["AutoAuthorizePumpWhenCalling"].ToLower() ==
  48. // "true"
  49. // ? true
  50. // : false);
  51. //}
  52. //var fdcServerIpAddress = ConfigurationManager.AppSettings["FdcServerIpAddress"];
  53. //this.concreteFdcServerConnString = DEFAULT_FDC_SERVER_CONNECT_STRING.Replace("127.0.0.1", fdcServerIpAddress)
  54. // .Replace("ClientId=101", "ClientId=" + ConfigurationManager.AppSettings["ClientId"]);
  55. //this.forecourtControl = Wayne.ForecourtControl.Fusion.FUSIONFactory.CreateForecourtControl(0);
  56. //this.forecourtControl.OnConnectionStateChange += forecourtControl_OnConnectionStateChange;
  57. //this.msgRouterClient = msgRouterClient;
  58. //this.msgRouterClient.Start();
  59. }
  60. //void forecourtControl_OnConnectionStateChange(object sender, ConnectionChangedEventArgs e)
  61. //{
  62. // debugLogger.Add("forecourtControl_OnConnectionStateChange(), new state: " + e.ConnectionState, DebugLogLevel.Normal);
  63. // if (e.ConnectionState == Wayne.Lib.DeviceConnectionState.Disconnected)
  64. // {
  65. // foreach (var pump in this.forecourtControl.Pumps)
  66. // {
  67. // pump.OnFuellingStateChange -= FdcCommunicator_OnFuellingStateChange;
  68. // pump.OnNozzleStateChange -= FdcCommunicator_OnNozzleStateChange;
  69. // pump.OnEventOccured -= FdcCommunicator_OnEventOccured;
  70. // }
  71. // }
  72. // else if (e.ConnectionState == Wayne.Lib.DeviceConnectionState.Connected)
  73. // {
  74. // // sometimes could not receive any notification from FDC server even attached the event handler,
  75. // // suspect some underlying bug in communication layer, so here try sleep a while to avoid(probably) this.
  76. // //
  77. // Thread.Sleep(500);
  78. // foreach (var pump in this.forecourtControl.Pumps)
  79. // {
  80. // pump.OnFuellingStateChange += FdcCommunicator_OnFuellingStateChange;
  81. // pump.OnNozzleStateChange += FdcCommunicator_OnNozzleStateChange;
  82. // pump.OnEventOccured += FdcCommunicator_OnEventOccured;
  83. // }
  84. // const int maxRetryTimes = 10;
  85. // int retriedTimes = 0;
  86. // while (!this.msgRouterClient.SendMessage(MsgRouterMessageUtility.RefreshPumpStatus()))
  87. // {
  88. // if (++retriedTimes > maxRetryTimes) break;
  89. // debugLogger.Add("failed to send RefreshPumpStatus() to MsgRouterServer, will keep retrying until max times reached...", DebugLogLevel.Normal);
  90. // Thread.Sleep(2000);
  91. // }
  92. // this.forecourtControl.SetSiteOpenedAsync(true, (_, __) => { }, null);
  93. // }
  94. //}
  95. //void FdcCommunicator_OnEventOccured(object sender, Wayne.ForecourtControl.PumpEventOccuredEventArgs e)
  96. //{
  97. // debugLogger.Add("FdcCommunicator_OnEventOccured(), args: " + e, DebugLogLevel.Maximized);
  98. //}
  99. //void FdcCommunicator_OnNozzleStateChange(object sender, Wayne.ForecourtControl.NozzleStateChangeEventArgs e)
  100. //{
  101. // //var callingPump = sender as IPump;
  102. // //debugLogger.Debug("FdcCommunicator_OnNozzleStateChange(), args: pumpId: " + callingPump.Id + " nozzleId: " + e.Nozzle.Id + ", newState: " + e.NozzleState);
  103. // //int sitewiseNozzleId = SiteConfigUtility.Default.GetSiteLevelNozzleIdByLogicalNozzleId(callingPump.Id, e.Nozzle.Id);
  104. // //if (e.NozzleState == NozzleState.In)
  105. // //{
  106. // // /* indicate for nozzle if replaced back */
  107. // // var sizeLevelNozzleIdsOnPump = SiteConfigUtility.Default.GetSiteLevelNozzleIdsByPumpId(callingPump.Id);
  108. // // if (!sizeLevelNozzleIdsOnPump.Any())
  109. // // {
  110. // // debugLogger.Debug("Could not found any site level nozzle ids for pump: " + callingPump.Id);
  111. // // return;
  112. // // }
  113. // // using (var posSqlConnection = new SqlConnection(ConfigurationManager.ConnectionStrings["PosDatabaseConnStr"].ConnectionString))
  114. // // {
  115. // // try
  116. // // {
  117. // // /* idle would not carry nozzle id, so here reset all nozzles on target pump.*/
  118. // // var setPumpOnIdleCommand
  119. // // = new SqlCommand(sizeLevelNozzleIdsOnPump.Select(siteLevelNozzleId =>
  120. // // {
  121. // // var totalizer = SiteConfigUtility.Default.GetTotalizer(siteLevelNozzleId);
  122. // // return
  123. // // string.Format(
  124. // // "Update jy_info set [status] = '{1}', qty=0, amount=0, fzqty='{2}', fzamount={3}" +
  125. // // " where jihao = {0}", siteLevelNozzleId, 'F',
  126. // // totalizer.Item1, totalizer.Item2);
  127. // // })
  128. // // .Aggregate((acc, n) => acc + " " + n), posSqlConnection);
  129. // // debugLogger.Add("setPumpOnIdleCommand(via Fdc): " + setPumpOnIdleCommand.CommandText, DebugLogLevel.Maximized);
  130. // // posSqlConnection.Open();
  131. // // setPumpOnIdleCommand.ExecuteNonQuery();
  132. // // }
  133. // // catch (Exception ex)
  134. // // {
  135. // // debugLogger.Add("executing setPumpOnIdleCommand(via Fdc) failed, exception detail: " + ex,
  136. // // DebugLogLevel.Normal);
  137. // // }
  138. // // }
  139. // // NozzleReplaced?.Invoke(sitewiseNozzleId);
  140. // //}
  141. // //else if (e.NozzleState == NozzleState.Out)
  142. // //{
  143. // // debugLogger.Add("fire nozzle out event");
  144. // // NozzleLifted?.Invoke(sitewiseNozzleId, callingPump);
  145. // //}
  146. //}
  147. //public void AuthorizePumpAsync(IPump callingPump, int sitewiseNozzleId, decimal authAmount)
  148. //{
  149. // if (this.autoAuthorizePumpWhenCalling)
  150. // {
  151. // var authParameter = new AuthorizeParameters()
  152. // {
  153. // PriceGroup = PriceGroup.FullService,
  154. // LockToReleaseClient = false,
  155. // PresetType = PresetType.Amount,
  156. // PresetValue = authAmount,
  157. // Prepay = false,
  158. // PayType = "PC",
  159. // };
  160. // for (int i = 0; i < callingPump.Nozzles.Count; i++)
  161. // {
  162. // int idFuelGrade = callingPump.Nozzles[i].FuelGrade;
  163. // authParameter.AllowedFuelGrade[idFuelGrade] = true;
  164. // }
  165. // debugLogger.Add(
  166. // "Authorizing for pumpId: " + callingPump.Id + ", authAmount:" + authAmount,
  167. // DebugLogLevel.Normal);
  168. // callingPump.AuthorizeAsync(authParameter, (_, arg) =>
  169. // {
  170. // var pumpId = (int)(arg.UserToken);
  171. // if (arg.Success)
  172. // {
  173. // debugLogger.Add(
  174. // "AuthorizeAsync finished successfully for pumpId: " + pumpId,
  175. // DebugLogLevel.Detailed);
  176. // AuthOk?.Invoke(sitewiseNozzleId, arg.Result);
  177. // }
  178. // else
  179. // {
  180. // debugLogger.Add(
  181. // "AuthorizeAsync failed for pumpId: " + pumpId,
  182. // DebugLogLevel.Normal);
  183. // AuthFailed?.Invoke(sitewiseNozzleId);
  184. // }
  185. // }, callingPump.Id);
  186. // }
  187. // else
  188. // {
  189. // debugLogger.Add(
  190. // "No need to auth before fueling for pumpId: " + callingPump.Id,
  191. // DebugLogLevel.Normal);
  192. // AuthOk?.Invoke(sitewiseNozzleId, null);
  193. // }
  194. //}
  195. //void FdcCommunicator_OnFuellingStateChange(object sender, Wayne.ForecourtControl.FuellingStateChangeEventArgs e)
  196. //{
  197. // debugLogger.Add("FdcCommunicator_OnFuellingStateChange(), args: " + e, DebugLogLevel.Detailed);
  198. // debugLogger.Add("\r\n PumpID = " + e.Fuelling.Pump.Id +
  199. // "\r\n Nozzle = " + e.Fuelling.Nozzle.Id +
  200. // "\r\n Amount = $" + e.Fuelling.Amount +
  201. // "\r\n State = " + e.State +
  202. // "\r\n FuelGrade = " + e.Fuelling.FuelGrade +
  203. // "\r\n ReservingDeviceId = " + e.Fuelling.ReservingDeviceId +
  204. // "\r\n Quantity = " + e.Fuelling.Quantity +
  205. // "\r\n ReservedBy = " + e.Fuelling.ReservedBy +
  206. // "\r\n FuelPeriodID = " + e.Fuelling.FuelPeriodId +
  207. // "\r\n FuellingSeqNumber = " + e.Fuelling.FuellingSequenceNumber +
  208. // "\r\n Price = $" + e.Fuelling.Price);
  209. // if (e.State == FuellingState.PayableTransaction)
  210. // {
  211. // /* 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*/
  212. // this.forecourtControl.Pumps[e.Fuelling.Pump.Id - 1].Fuellings.ToList().ForEach(f =>
  213. // {
  214. // var fsn = f.FuellingSequenceNumber;
  215. // debugLogger.Add("Sending SetAsPaidAsync for pumpId: " + f.Pump.Id + ", FuellingSequenceNumber: " + fsn,
  216. // DebugLogLevel.Detailed);
  217. // f.SetAsPaidAsync((_, arg) =>
  218. // {
  219. // var pumpId = (int)(arg.UserToken);
  220. // if (arg.Success)
  221. // {
  222. // debugLogger.Add(
  223. // "SetAsPaidAsync finished successfully for pumpId: " + pumpId + ", FuellingSequenceNumber: " + fsn,
  224. // DebugLogLevel.Detailed);
  225. // }
  226. // else
  227. // {
  228. // debugLogger.Add(
  229. // "SetAsPaidAsync failed for pumpId: " + pumpId + ", FuellingSequenceNumber: " + fsn,
  230. // DebugLogLevel.Normal);
  231. // }
  232. // }, f.Pump.Id);
  233. // });
  234. // }
  235. // else if (e.State == FuellingState.Paid)
  236. // {
  237. // var posSqlConnection =
  238. // new SqlConnection(ConfigurationManager.ConnectionStrings["PosDatabaseConnStr"].ConnectionString);
  239. // int sitewiseNozzleId = SiteConfigUtility.Default.GetSiteLevelNozzleIdByLogicalNozzleId(e.Fuelling.Pump.Id, e.Fuelling.Nozzle.Id);
  240. // using (posSqlConnection)
  241. // {
  242. // try
  243. // {
  244. // var totalizer = SiteConfigUtility.Default.GetTotalizer(e.Fuelling.Pump.Id, e.Fuelling.Nozzle.Id);
  245. // var updateFuelingTrxDoneCommand =
  246. // new SqlCommand(
  247. // string.Format(
  248. // "insert xiaofei2 (jihao, youpin, qty, danjia, amount, xf_date, xf_time, liushuino, fzqty, fzamount)" +
  249. // " values({0}, N'{1}', {2}, {3}, {4}, '{5}', '{6}', '{7}', '{8}', {9})",
  250. // sitewiseNozzleId,
  251. // Translator.GetFriendlyGradeName(SiteConfigUtility.Default.GetGradeNameByGradeId(e.Fuelling.FuelGrade)),
  252. // e.Fuelling.Quantity,
  253. // e.Fuelling.Price,
  254. // e.Fuelling.Amount,
  255. // DateTime.Now.Date.ToString("yyyy-MM-dd"),
  256. // DateTime.Now.ToString("HH:mm:ss"),
  257. // e.Fuelling.FuellingSequenceNumber,
  258. // totalizer.Item1,
  259. // totalizer.Item2),
  260. // posSqlConnection);
  261. // debugLogger.Add("updateFuelingTrxDoneCommand: " + updateFuelingTrxDoneCommand.CommandText,
  262. // DebugLogLevel.Maximized);
  263. // posSqlConnection.Open();
  264. // updateFuelingTrxDoneCommand.ExecuteNonQuery();
  265. // }
  266. // catch (Exception ex)
  267. // {
  268. // debugLogger.Add("executing updateFuelingTrxDoneCommand failed, exception detail: " + ex,
  269. // DebugLogLevel.Normal);
  270. // }
  271. // }
  272. // FuelingDone?.Invoke
  273. // (sitewiseNozzleId, e.Fuelling.FuellingSequenceNumber, e.Fuelling.Amount, e.Fuelling.Quantity, e.Fuelling.AuthorizationId);
  274. // }
  275. //}
  276. //public void Dispose()
  277. //{
  278. // this.forecourtControl.Dispose();
  279. // this.debugLogger.Dispose();
  280. //}
  281. //public bool Start()
  282. //{
  283. // if (0 == Interlocked.CompareExchange(ref this.isStarted, 1, 0))
  284. // {
  285. // debugLogger.Add("Connecting to FDC server with connStr: " + this.concreteFdcServerConnString, DebugLogLevel.Normal);
  286. // this.forecourtControl.Connect(this.concreteFdcServerConnString);
  287. // return true;
  288. // }
  289. // else
  290. // {
  291. // throw new InvalidOperationException("Already started.");
  292. // }
  293. //}
  294. public bool IsStarted
  295. {
  296. get { return this.isStarted == 1; }
  297. }
  298. }
  299. }