PumpHandler.cs 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.ObjectModel;
  4. using System.Configuration;
  5. using System.IO.Ports;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading;
  9. using log4net;
  10. using Timer = System.Timers.Timer;
  11. using Common;
  12. using System.Collections;
  13. using HengShan_Pump_NonIC.MessageEntity;
  14. using DeviceProcessor;
  15. using Wayne.FDCPOSLibrary;
  16. using Common.Config;
  17. using System.Xml;
  18. namespace HengShan_Pump_NonIC
  19. {
  20. public class PumpHandler : IFdcPumpController, IHandler<byte[], NonICMessageTemplateBase>
  21. {
  22. private object syncObject = new object();
  23. private System.Timers.Timer polling;
  24. //static ILog fdcLogger = log4net.LogManager.GetLogger("FdcServer");
  25. static ILog logger = log4net.LogManager.GetLogger("PumpHandler");
  26. protected IContext<byte[], NonICMessageTemplateBase> context;
  27. public event EventHandler<FdcPumpControllerOnStateChangeEventArg> OnStateChange;
  28. /// <summary>
  29. /// fired on fueling process is on going, the fuel amount should keep changing.
  30. /// </summary>
  31. public event EventHandler<FdcTransactionDoneEventArg> OnCurrentFuellingStatusChange;
  32. protected LogicalDeviceState lastLogicalDeviceState = LogicalDeviceState.FDC_CLOSED;
  33. protected DateTime lastLogicalDeviceStateReceivedTime;
  34. // by seconds
  35. public const int lastLogicalDeviceStateExpiredTime = 6;
  36. private AutoResetEvent waitResponseBlocker = new AutoResetEvent(false);
  37. private int waitResponseBlockerTime = 11 * 1000;
  38. private StartResponse lastStartResponse;
  39. private SetFuelPriceResponse lastSetFuelPriceResponse;
  40. private GetAccumulateResponse lastGetAccumulateResponse;
  41. private AuthPumpWithAmountResponse lastAuthPumpWithAmountResponse;
  42. private AuthPumpWithGallonResponse lastAuthPumpWithGallonResponse;
  43. private AuthPumpWithKiloResponse lastAuthPumpWithKiloResponse;
  44. private RoundUpByAmountResponse lastRoundUpByAmountResponse;
  45. private Guid uniqueId = Guid.NewGuid();
  46. private int pumpId = -1;
  47. protected int pollingInterval = 600;
  48. protected List<LogicalNozzle> nozzles = new List<LogicalNozzle>();
  49. /// <summary>
  50. /// this type of pump state change is detected by FC actively polling, then state is always delay reported, so there's a corner case that in a fueling process,
  51. /// the attendants put back and pull out nozzle very quickly and it happened exactly in the middle of a polling, meanwhile,
  52. /// an auth request was done to auth the pump again(most likely the autoAuthCallingPump set with True),
  53. /// then the pump state returned from physical pump will still be read as a fueling state, but actually the
  54. /// 2nd fueling process is started, so detect the pump state is not enough, need detect if the fueling seq number reset to null(if place back nozzle detected) or not.
  55. /// </summary>
  56. protected GetNozzleStatusResponse previousUnfinishedFuelingNozzleStatus;
  57. public IEnumerable<LogicalNozzle> Nozzles => this.nozzles;
  58. protected void FireOnStateChangeEvent(LogicalDeviceState state)
  59. {
  60. var safe = this.OnStateChange;
  61. safe?.Invoke(this, new FdcPumpControllerOnStateChangeEventArg(state, this.nozzles.First()));
  62. }
  63. protected void FireOnCurrentFuellingStatusChangeEvent(FdcTransaction trx)
  64. {
  65. var safe = this.OnCurrentFuellingStatusChange;
  66. safe?.Invoke(this, new FdcTransactionDoneEventArg(trx));
  67. }
  68. /// <summary>
  69. /// 恒山非IC油机
  70. /// </summary>
  71. /// <param name="pumpId"></param>
  72. /// <param name="nozzlesXmlConfiguration"></param>
  73. public PumpHandler(int pumpId, string nozzlesXmlConfiguration)
  74. {
  75. this.pumpId = pumpId;
  76. // real nozzle Id put hardcode 1 here since HengShan_pump_nonIC only have 1 nozzle per pump.
  77. // price is not dectected yet, put Null.
  78. this.nozzles.Add(new LogicalNozzle(pumpId, 1, 1, null));
  79. }
  80. private void ResetAllCachedResponse()
  81. {
  82. this.lastStartResponse = null;
  83. this.lastSetFuelPriceResponse = null;
  84. this.lastGetAccumulateResponse = null;
  85. this.lastAuthPumpWithAmountResponse = null;
  86. this.lastAuthPumpWithGallonResponse = null;
  87. this.lastAuthPumpWithKiloResponse = null;
  88. this.lastRoundUpByAmountResponse = null;
  89. }
  90. protected bool isSafeForSend = false;
  91. public void Init(IContext<byte[], NonICMessageTemplateBase> context)
  92. {
  93. this.context = context;
  94. this.polling = new Timer(this.pollingInterval);
  95. this.polling.Elapsed += (_, __) =>
  96. {
  97. lock (this.syncObject)
  98. {
  99. this.isSafeForSend = false;
  100. context.Outgoing.Write(new GetNozzleStatusRequest());
  101. }
  102. };
  103. this.polling.Start();
  104. }
  105. public virtual void Process(IContext<byte[], NonICMessageTemplateBase> context)
  106. {
  107. this.context = context;
  108. this.ResetAllCachedResponse();
  109. if (context.Incoming.Message is GetNozzleStatusResponse getNozzleStatusResponse)
  110. {
  111. this.isSafeForSend = true;
  112. this.lastLogicalDeviceStateReceivedTime = DateTime.Now;
  113. // put the price by reading the real price.
  114. this.nozzles.First().RealPriceOnPhysicalPump = getNozzleStatusResponse.单价;
  115. var latestStatus = getNozzleStatusResponse.GetPumpStatus();
  116. if (latestStatus.Any(f => f == GetNozzleStatusResponse.PumpStatus.油枪打开)
  117. && latestStatus.Any(f => f == GetNozzleStatusResponse.PumpStatus.加油结束)
  118. && latestStatus.Any(f => f == GetNozzleStatusResponse.PumpStatus.不允许加油)
  119. && latestStatus.Any(f => f == GetNozzleStatusResponse.PumpStatus.电机关)
  120. && !latestStatus.Any(f => f == GetNozzleStatusResponse.PumpStatus.加油过程))
  121. {
  122. logger.Debug("非加油状态下的提枪");
  123. /* 非加油状态下的提枪 */
  124. if (this.lastLogicalDeviceState == LogicalDeviceState.FDC_AUTHORISED)
  125. {
  126. //说明是未提枪时就已经auth成功了,所以还是保持发送 FDC_AUTHORISED 的状态给FdcClient。
  127. logger.Debug(" 未提枪时就已经auth成功了");
  128. }
  129. else
  130. {
  131. if (this.previousUnfinishedFuelingNozzleStatus != null)
  132. {
  133. // no data loss since getNozzleStatusResponse will still carry last trx data until an auth.
  134. logger.Info("Detected a fast put back and pull out nozzle case(action time < polling time cause nozzle place back not detected)," +
  135. "\r\n will fire the trx done event for earlier trx(no data loss)->\r\n "
  136. + "seqNo: " + getNozzleStatusResponse.流水号
  137. + ", amount: " + getNozzleStatusResponse.加油金额
  138. + ", volume: " + getNozzleStatusResponse.加油金额
  139. + ", price: " + getNozzleStatusResponse.单价);
  140. logger.Info(" State switched to FDC_READY(simulate)");
  141. this.lastLogicalDeviceState = LogicalDeviceState.FDC_READY;
  142. this.FireOnStateChangeEvent(LogicalDeviceState.FDC_READY);
  143. this.FireOnCurrentFuellingStatusChangeEvent(new FdcTransaction()
  144. {
  145. // 恒山油机只有一把枪
  146. Nozzle = this.nozzles.First(),
  147. Amount = getNozzleStatusResponse.加油金额,
  148. Volumn = getNozzleStatusResponse.加油量,
  149. Price = getNozzleStatusResponse.单价,
  150. SequenceNumberGeneratedOnPhysicalPump = getNozzleStatusResponse.流水号,
  151. Finished = true,
  152. });
  153. }
  154. if (this.lastLogicalDeviceState != LogicalDeviceState.FDC_CALLING)
  155. {
  156. logger.Debug(" State switched to FDC_CALLING");
  157. //直接提枪了
  158. this.lastLogicalDeviceState = LogicalDeviceState.FDC_CALLING;
  159. var safe = this.OnStateChange;
  160. safe?.Invoke(this, new FdcPumpControllerOnStateChangeEventArg(LogicalDeviceState.FDC_CALLING, this.nozzles.First()));
  161. }
  162. }
  163. }
  164. else if (latestStatus.Any(f => f == GetNozzleStatusResponse.PumpStatus.允许加油)
  165. && latestStatus.Any(f => f == GetNozzleStatusResponse.PumpStatus.油枪打开)
  166. && (latestStatus.Any(f => f == GetNozzleStatusResponse.PumpStatus.加油过程)
  167. || latestStatus.Any(f => f == GetNozzleStatusResponse.PumpStatus.电机打开)))
  168. {
  169. //status code: B1
  170. logger.Debug("正处于加油状态下");
  171. /* 正处于加油状态下 */
  172. this.previousUnfinishedFuelingNozzleStatus = getNozzleStatusResponse;
  173. if (this.lastLogicalDeviceState != LogicalDeviceState.FDC_FUELLING)
  174. {
  175. logger.Debug(" State switched to FDC_FUELLING");
  176. this.lastLogicalDeviceState = LogicalDeviceState.FDC_FUELLING;
  177. var safe0 = this.OnStateChange;
  178. safe0?.Invoke(this, new FdcPumpControllerOnStateChangeEventArg(LogicalDeviceState.FDC_FUELLING, this.nozzles.First()));
  179. }
  180. //fire fuelling progress.
  181. var safe1 = this.OnCurrentFuellingStatusChange;
  182. safe1?.Invoke(this, new FdcTransactionDoneEventArg(new FdcTransaction()
  183. {
  184. // 恒山油机只有一把枪
  185. Nozzle = this.nozzles.First(),
  186. Amount = getNozzleStatusResponse.加油金额,
  187. Volumn = getNozzleStatusResponse.加油量,
  188. Price = getNozzleStatusResponse.单价,
  189. SequenceNumberGeneratedOnPhysicalPump = getNozzleStatusResponse.流水号,
  190. Finished = false,
  191. }));
  192. }
  193. else if (latestStatus.Any(f => f == GetNozzleStatusResponse.PumpStatus.加油结束))
  194. {
  195. /* 油机首次上电也会进入此处,并不断发送上一次的加油记录,这种情况下的交易记录并无法判断其之前是否已经发送至系统(并存入数据库),
  196. 所以继续往系统里送入,由系统判断重复情况。 而其它正常加油过程中的交易记录仅在油机状态变化时才送入系统。*/
  197. // status code: 40
  198. logger.Debug("收到状态: 加油结束");
  199. this.previousUnfinishedFuelingNozzleStatus = null;
  200. if (this.lastLogicalDeviceState != LogicalDeviceState.FDC_READY)
  201. {
  202. logger.Debug(" State switched to FDC_READY");
  203. lastLogicalDeviceState = LogicalDeviceState.FDC_READY;
  204. var safe0 = this.OnStateChange;
  205. safe0?.Invoke(this, new FdcPumpControllerOnStateChangeEventArg(LogicalDeviceState.FDC_READY, null));
  206. if (getNozzleStatusResponse.加油量 != 0 || getNozzleStatusResponse.加油金额 != 0)
  207. {
  208. var safe1 = this.OnCurrentFuellingStatusChange;
  209. safe1?.Invoke(this, new FdcTransactionDoneEventArg(new FdcTransaction()
  210. {
  211. // 恒山油机 一个加油点只有一把枪
  212. Nozzle = this.nozzles.First(),
  213. Amount = getNozzleStatusResponse.加油金额,
  214. Volumn = getNozzleStatusResponse.加油量,
  215. Price = getNozzleStatusResponse.单价,
  216. SequenceNumberGeneratedOnPhysicalPump = getNozzleStatusResponse.流水号,
  217. Finished = true,
  218. }));
  219. }
  220. }
  221. }
  222. }
  223. else if (context.Incoming.Message is GetAccumulateResponse)
  224. {
  225. logger.Info(" incoming GetAccumulateResponse, will Set() a signal");
  226. var _ = context.Incoming.Message as GetAccumulateResponse;
  227. this.lastGetAccumulateResponse = _;
  228. this.waitResponseBlocker.Set();
  229. }
  230. else if (context.Incoming.Message is SetFuelPriceResponse)
  231. {
  232. logger.Info(" incoming SetFuelPriceResponse, will Set() a signal");
  233. var _ = context.Incoming.Message as SetFuelPriceResponse;
  234. this.lastSetFuelPriceResponse = _;
  235. this.waitResponseBlocker.Set();
  236. }
  237. else if (context.Incoming.Message is StartResponse)
  238. {
  239. logger.Info(" incoming StartResponse, will Set() a signal");
  240. var _ = context.Incoming.Message as StartResponse;
  241. this.lastStartResponse = _;
  242. this.waitResponseBlocker.Set();
  243. //if (this.lastLogicalDeviceState != LogicalDeviceState.FDC_AUTHORISED)
  244. //{
  245. // // switch state
  246. // this.lastLogicalDeviceState = LogicalDeviceState.FDC_AUTHORISED;
  247. // var safe = this.OnStateChange;
  248. // safe?.Invoke(this, new FdcPumpControllerOnStateChangeEventArg(LogicalDeviceState.FDC_AUTHORISED));
  249. //}
  250. }
  251. else if (context.Incoming.Message is AuthPumpWithAmountResponse)
  252. {
  253. logger.Info(" incoming AuthPumpWithAmountResponse, will Set() a signal");
  254. var _ = context.Incoming.Message as AuthPumpWithAmountResponse;
  255. this.lastAuthPumpWithAmountResponse = _;
  256. this.waitResponseBlocker.Set();
  257. }
  258. else if (context.Incoming.Message is AuthPumpWithGallonResponse)
  259. {
  260. logger.Info(" incoming AuthPumpWithGallonResponse, will Set() a signal");
  261. var _ = context.Incoming.Message as AuthPumpWithGallonResponse;
  262. this.lastAuthPumpWithGallonResponse = _;
  263. this.waitResponseBlocker.Set();
  264. }
  265. else if (context.Incoming.Message is AuthPumpWithKiloResponse)
  266. {
  267. logger.Info(" incoming AuthPumpWithKiloResponse, will Set() a signal");
  268. var _ = context.Incoming.Message as AuthPumpWithKiloResponse;
  269. this.lastAuthPumpWithKiloResponse = _;
  270. this.waitResponseBlocker.Set();
  271. }
  272. else if (context.Incoming.Message is RoundUpByAmountResponse)
  273. {
  274. logger.Info(" incoming RoundUpByAmountResponse, will Set() a signal");
  275. var _ = context.Incoming.Message as RoundUpByAmountResponse;
  276. this.lastRoundUpByAmountResponse = _;
  277. this.waitResponseBlocker.Set();
  278. }
  279. }
  280. public void Dispose()
  281. {
  282. this.polling.Stop();
  283. }
  284. public string Name => this.GetType().FullName;
  285. public Guid Id => this.uniqueId;
  286. /// <summary>
  287. /// Gets the Identification of the pump for the system. Is the logical number of the pump
  288. /// </summary>
  289. public int PumpId => this.pumpId;
  290. /// <summary>
  291. /// this pump have no way to share same comport since this HengShan protocol content does not contains
  292. /// any id info, so always static 0 here.
  293. /// 地址面地址
  294. /// </summary>
  295. public int PumpPhysicalId => 0;
  296. public int AmountDecimalDigits => 2;
  297. public int VolumeDecimalDigits => 2;
  298. public int PriceDecimalDigits => 2;
  299. public int VolumeTotalizerDecimalDigits => 2;
  300. public virtual LogicalDeviceState QueryStatus()
  301. {
  302. // if last state is expired, we return a OFFLINE here to FdcClient.
  303. if (DateTime.Now.Subtract(this.lastLogicalDeviceStateReceivedTime).TotalSeconds > lastLogicalDeviceStateExpiredTime)
  304. {
  305. if (this.lastLogicalDeviceState != LogicalDeviceState.FDC_OFFLINE)
  306. {
  307. this.lastLogicalDeviceState = LogicalDeviceState.FDC_OFFLINE;
  308. logger.Info(" State switched to FDC_OFFLINE due to cached state expired");
  309. var safe0 = this.OnStateChange;
  310. safe0?.Invoke(this, new FdcPumpControllerOnStateChangeEventArg(LogicalDeviceState.FDC_OFFLINE, null));
  311. }
  312. return LogicalDeviceState.FDC_OFFLINE;
  313. }
  314. return this.lastLogicalDeviceState;
  315. }
  316. private const int safeWaitMaxWaitTimes = 10;
  317. protected bool SafeWait()
  318. {
  319. int waitedTimes = 0;
  320. while (!this.isSafeForSend)
  321. {
  322. waitedTimes++;
  323. if (waitedTimes >= safeWaitMaxWaitTimes)
  324. {
  325. logger.Info("safe wait failed!");
  326. return false;
  327. }
  328. Thread.Sleep(300);
  329. }
  330. return true;
  331. }
  332. /// <summary>
  333. ///
  334. /// </summary>
  335. /// <returns>MoneyTotalizer:VolumnTotalizer</returns>
  336. public Tuple<int, int> QueryTotalizer(byte logicalNozzleId)
  337. {
  338. lock (this.syncObject)
  339. {
  340. if (this.lastLogicalDeviceState == LogicalDeviceState.FDC_CLOSED
  341. || this.lastLogicalDeviceState == LogicalDeviceState.FDC_OFFLINE)
  342. return new Tuple<int, int>(-1, -1);
  343. if (!this.SafeWait()) return new Tuple<int, int>(-2, -2);
  344. this.context.Outgoing.Write(new GetAccumulateRequest());
  345. logger.Info(" QueryTotalizer waitOne");
  346. var got = this.waitResponseBlocker.WaitOne(this.waitResponseBlockerTime);
  347. if (got)
  348. {
  349. if (this.lastGetAccumulateResponse == null)
  350. {
  351. logger.Info("lastGetAccumulateResponse is Null");
  352. return new Tuple<int, int>(-1, -1);
  353. }
  354. else
  355. return new Tuple<int, int>(this.lastGetAccumulateResponse.金额累计, this.lastGetAccumulateResponse.升累计);
  356. }
  357. logger.Info("QueryTotalizer timed out");
  358. return new Tuple<int, int>(-1, -1);
  359. }
  360. }
  361. public virtual bool ChangeFuelPrice(int newPriceWithoutDecimalPoint, byte logicalNozzleId)
  362. {
  363. //fdcLogger.Info(this.GetType().Name + "with id: " + this.pumpId + " is trying to change fuel price to: " + newPrice);
  364. /* this type of pump only have 1 nozzle, so logicalNozzleId is meaningless */
  365. lock (this.syncObject)
  366. {
  367. if (this.lastLogicalDeviceState == LogicalDeviceState.FDC_CLOSED
  368. || this.lastLogicalDeviceState == LogicalDeviceState.FDC_OFFLINE)
  369. return false;
  370. if (!this.SafeWait()) return false;
  371. this.context.Outgoing.Write(new SetFuelPriceRequest() { FuelPrice = newPriceWithoutDecimalPoint });
  372. logger.Info(" ChangeFuelPrice waitOne");
  373. var got = this.waitResponseBlocker.WaitOne(this.waitResponseBlockerTime);
  374. if (got)
  375. {
  376. if (this.lastSetFuelPriceResponse == null)
  377. {
  378. logger.Info("lastSetFuelPriceResponse is Null");
  379. return false;
  380. }
  381. else if (this.lastSetFuelPriceResponse.EnumResult != NonICMessageTemplateBase.Result.成功)
  382. {
  383. logger.Info("lastSetFuelPriceResponse is 失败");
  384. return false;
  385. }
  386. return true;
  387. }
  388. return false;
  389. }
  390. }
  391. /// <summary>
  392. ///
  393. /// </summary>
  394. /// <param name="logicalNozzleId">useless for this type of pump, it always one pump one nozzle</param>
  395. /// <returns></returns>
  396. public virtual bool Authorize(byte logicalNozzleId)
  397. {
  398. lock (this.syncObject)
  399. {
  400. if (!this.SafeWait()) return false;
  401. this.context.Outgoing.Write(new StartRequest());
  402. logger.Info(" Authorize waitOne");
  403. var got = this.waitResponseBlocker.WaitOne(this.waitResponseBlockerTime);
  404. if (got)
  405. {
  406. if (this.lastStartResponse == null)
  407. {
  408. logger.Info("lastStartResponse is Null");
  409. return false;
  410. }
  411. else if (this.lastStartResponse.EnumResult != NonICMessageTemplateBase.Result.成功)
  412. {
  413. logger.Info("lastStartResponse is 失败");
  414. return false;
  415. }
  416. else
  417. {
  418. if (this.lastLogicalDeviceState != LogicalDeviceState.FDC_AUTHORISED)
  419. {
  420. this.lastLogicalDeviceState = LogicalDeviceState.FDC_AUTHORISED;
  421. var safe = this.OnStateChange;
  422. safe?.Invoke(this, new FdcPumpControllerOnStateChangeEventArg(LogicalDeviceState.FDC_AUTHORISED, this.nozzles.First()));
  423. }
  424. return true;
  425. }
  426. }
  427. return false;
  428. }
  429. }
  430. /// <summary>
  431. ///
  432. /// </summary>
  433. /// <param name="moneyAmount"></param>
  434. /// <param name="logicalNozzleId">useless for this type of pump, it always one pump one nozzle</param>
  435. /// <returns></returns>
  436. public virtual bool AuthorizeWithAmount(int moneyAmountWithoutDecimalPoint, byte logicalNozzleId)
  437. {
  438. lock (this.syncObject)
  439. {
  440. if (!this.SafeWait()) return false;
  441. this.context.Outgoing.Write(new AuthPumpWithAmountRequest() { Amount = moneyAmountWithoutDecimalPoint });
  442. logger.Info(" Authorize(amount) waitOne");
  443. var got = this.waitResponseBlocker.WaitOne(this.waitResponseBlockerTime);
  444. if (got)
  445. {
  446. if (this.lastAuthPumpWithAmountResponse == null)
  447. { logger.Info("lastAuthPumpWithAmountResponse is Null"); return false; }
  448. else if (this.lastAuthPumpWithAmountResponse.EnumResult != NonICMessageTemplateBase.Result.成功)
  449. { logger.Info("lastAuthPumpWithAmountResponse is 失败"); return false; }
  450. else
  451. {
  452. if (this.lastLogicalDeviceState != LogicalDeviceState.FDC_AUTHORISED)
  453. {
  454. lastLogicalDeviceState = LogicalDeviceState.FDC_AUTHORISED;
  455. var safe = this.OnStateChange;
  456. safe?.Invoke(this, new FdcPumpControllerOnStateChangeEventArg(LogicalDeviceState.FDC_AUTHORISED, this.nozzles.First()));
  457. }
  458. Thread.Sleep(500);
  459. return this.Authorize(logicalNozzleId);
  460. };
  461. }
  462. else
  463. return false;
  464. }
  465. }
  466. /// <summary>
  467. ///
  468. /// </summary>
  469. /// <param name="volumn"></param>
  470. /// <param name="logicalNozzleId">useless for this type of pump, it always one pump one nozzle</param>
  471. /// <returns></returns>
  472. public virtual bool AuthorizeWithVolumn(int volumnWithoutDecimalPoint, byte logicalNozzleId)
  473. {
  474. lock (this.syncObject)
  475. {
  476. if (!this.SafeWait()) return false;
  477. this.context.Outgoing.Write(new AuthPumpWithGallonRequest() { Gallon = volumnWithoutDecimalPoint });
  478. logger.Info(" Authorize(vol) waitOne");
  479. var got = this.waitResponseBlocker.WaitOne(this.waitResponseBlockerTime);
  480. if (got)
  481. {
  482. if (this.lastAuthPumpWithGallonResponse == null)
  483. {
  484. logger.Info("lastAuthPumpWithGallonResponse is Null");
  485. return false;
  486. }
  487. else if (this.lastAuthPumpWithGallonResponse.EnumResult != NonICMessageTemplateBase.Result.成功)
  488. {
  489. logger.Info("lastAuthPumpWithGallonResponse is 失败");
  490. return false;
  491. }
  492. else
  493. {
  494. if (this.lastLogicalDeviceState != LogicalDeviceState.FDC_AUTHORISED)
  495. {
  496. lastLogicalDeviceState = LogicalDeviceState.FDC_AUTHORISED;
  497. var safe = this.OnStateChange;
  498. safe?.Invoke(this, new FdcPumpControllerOnStateChangeEventArg(LogicalDeviceState.FDC_AUTHORISED, this.nozzles.First()));
  499. }
  500. Thread.Sleep(500);
  501. return this.Authorize(logicalNozzleId);
  502. }
  503. }
  504. return false;
  505. }
  506. }
  507. public virtual bool FuelingRoundUpByAmount()
  508. {
  509. lock (this.syncObject)
  510. {
  511. if (!this.SafeWait()) return false;
  512. this.context.Outgoing.Write(new RoundUpByAmountRequest());
  513. logger.Info(" FuelingRoundUpByAmount(vol) waitOne");
  514. var got = this.waitResponseBlocker.WaitOne(this.waitResponseBlockerTime);
  515. if (got)
  516. {
  517. if (this.lastRoundUpByAmountResponse == null)
  518. {
  519. logger.Info("lastRoundUpByAmountResponse is Null");
  520. return false;
  521. }
  522. else if (this.lastRoundUpByAmountResponse.EnumResult != NonICMessageTemplateBase.Result.成功)
  523. {
  524. logger.Info("lastRoundUpByAmountResponse is 失败");
  525. return false;
  526. }
  527. return true;
  528. }
  529. return false;
  530. }
  531. }
  532. #region not implemented
  533. public bool TerminateFuelling()
  534. {
  535. throw new NotImplementedException();
  536. }
  537. public bool SuspendFuelling()
  538. {
  539. throw new NotImplementedException();
  540. }
  541. public bool ResumeFuelling()
  542. {
  543. throw new NotImplementedException();
  544. }
  545. public bool FuelingRoundUpByVolumn()
  546. { throw new NotImplementedException(); }
  547. public void OnFdcServerInit(Dictionary<string, object> parameters)
  548. {
  549. //throw new NotImplementedException();
  550. }
  551. #endregion
  552. }
  553. }