StatePumpHandler.cs 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. //using Common.Models;
  2. //using DeviceProcessor;
  3. //using DeviceProcessor.UniversalApi;
  4. //using FR_Pump_HaoSheng.MessageEntity;
  5. //using Microsoft.Extensions.DependencyInjection;
  6. //using Microsoft.Extensions.Logging;
  7. //using Microsoft.Extensions.Logging.Abstractions;
  8. //using NLog.Fluent;
  9. //using Parser.BinaryParser.Util;
  10. //using Stateless;
  11. //using System;
  12. //using System.Collections.Generic;
  13. //using System.Linq;
  14. //using System.Text;
  15. //using System.Threading;
  16. //using System.Threading.Tasks;
  17. //using System.Xml;
  18. //using Wayne.FDCPOSLibrary;
  19. //namespace FR_Pump_HaoSheng
  20. //{
  21. // public class StatePumpHandler : IFdcPumpController, IHandler<byte[], MessageBase>
  22. // {
  23. // private IServiceProvider services;
  24. // static ILogger logger = NullLogger.Instance;
  25. // private LogicalDeviceState lastLogicalDeviceState = LogicalDeviceState.FDC_OFFLINE;
  26. // private DateTime lastLogicalDeviceStateReceivedTime;
  27. // // by seconds, change this value need change the correlated deviceOfflineCountdownTimer's interval as well
  28. // public const int lastLogicalDeviceStateExpiredTime = 6;
  29. // private List<LogicalNozzle> nozzles = new List<LogicalNozzle>();
  30. // private System.Timers.Timer deviceOfflineCountdownTimer;
  31. // private IContext<byte[], MessageBase> context;
  32. // private bool isOnFdcServerInitCalled = false;
  33. // private int pumpId;
  34. // /// <summary>
  35. // /// hardware address value of this pump, must be set in physical dispenser side.
  36. // /// </summary>
  37. // private byte address;
  38. // private PumpModelEnum pumpModel;
  39. // private PumpAuthorizeModeEnum pumpAuthorizeMode;
  40. // protected enum Trigger
  41. // {
  42. // //AnyPumpMsgReceived,
  43. // AnyPumpMsgHaveNotReceivedForWhile,
  44. // NozzleLifted_And_开机,
  45. // NozzleLifted_And_停机,
  46. // NozzleReplaced_And_开机,
  47. // NozzleReplaced_And_停机,
  48. // NozzleFuelNumbersIsRunning,
  49. // //PumpAuthorizedByFC,
  50. // }
  51. // StateMachine<LogicalDeviceState, Trigger> stateless
  52. // = new StateMachine<LogicalDeviceState, Trigger>(LogicalDeviceState.FDC_OFFLINE);
  53. // private int amountDecimalDigits;
  54. // private int volumeDecimalDigits;
  55. // private int priceDecimalDigits;
  56. // private int volumeTotalizerDecimalDigits;
  57. // private StateMachine<LogicalDeviceState, Trigger>.TriggerWithParameters<FdcTransaction> nozzleFuelNumbersIsRunningTrigger;
  58. // /// <summary>
  59. // /// for avoid a case that FC may miss a pump status change event(pump side issue? or wire issue?),
  60. // /// we timely actively request the pump state.
  61. // /// </summary>
  62. // //private System.Timers.Timer pollingPumpStatus;
  63. // //private int pollingPumpStatusInterval = 30000;
  64. // #region
  65. // public string Name => "LanTian_Pump_664_Or_886";
  66. // public int PumpId => this.pumpId;
  67. // public IEnumerable<LogicalNozzle> Nozzles => this.nozzles;
  68. // public int AmountDecimalDigits => this.amountDecimalDigits;
  69. // public int VolumeDecimalDigits => this.volumeDecimalDigits;
  70. // public int PriceDecimalDigits => this.priceDecimalDigits;
  71. // public int VolumeTotalizerDecimalDigits => this.volumeDecimalDigits;
  72. // public Guid Id => Guid.NewGuid();
  73. // public int PumpPhysicalId => this.address;
  74. // public event EventHandler<FdcPumpControllerOnStateChangeEventArg> OnStateChange;
  75. // public event EventHandler<FdcTransactionDoneEventArg> OnCurrentFuellingStatusChange;
  76. // public async Task<global::Wayne.FDCPOSLibrary.LogicalDeviceState> QueryStatusAsync()
  77. // {
  78. // return this.lastLogicalDeviceState;
  79. // }
  80. // public async Task<bool> LockNozzleAsync(byte logicalNozzleId)
  81. // {
  82. // return false;
  83. // }
  84. // public async Task<bool> UnlockNozzleAsync(byte logicalNozzleId)
  85. // {
  86. // return false;
  87. // }
  88. // #endregion
  89. // public StatePumpHandler(int pumpId, byte address,
  90. // PumpModelEnum pumpModel, PumpAuthorizeModeEnum pumpAuthorizeMode,
  91. // int amountDecimalDigits, int volumeDecimalDigits,
  92. // int priceDecimalDigits, int volumeTotalizerDecimalDigits,
  93. // IServiceProvider services)
  94. // {
  95. // this.services = services;
  96. // var loggerFactory = services.GetRequiredService<ILoggerFactory>();
  97. // logger = loggerFactory.CreateLogger("PumpHandler");
  98. // try
  99. // {
  100. // this.pumpId = pumpId;
  101. // this.address = address;
  102. // this.pumpModel = pumpModel;
  103. // this.pumpAuthorizeMode = pumpAuthorizeMode;
  104. // this.amountDecimalDigits = amountDecimalDigits;
  105. // this.volumeDecimalDigits = volumeDecimalDigits;
  106. // this.priceDecimalDigits = priceDecimalDigits;
  107. // this.volumeTotalizerDecimalDigits = volumeTotalizerDecimalDigits;
  108. // this.pumpId = pumpId;
  109. // // real nozzle Id put hardcode 1 here since HengShan_pump_nonIC only have 1 nozzle per pump.
  110. // // price is not dectected yet, put Null.
  111. // this.nozzles.Add(new LogicalNozzle(pumpId, this.address, 1, null));
  112. // this.deviceOfflineCountdownTimer = new System.Timers.Timer(2000);
  113. // this.deviceOfflineCountdownTimer.Elapsed += async (_, __) =>
  114. // {
  115. // if (DateTime.Now.Subtract(this.lastLogicalDeviceStateReceivedTime).TotalSeconds
  116. // >= lastLogicalDeviceStateExpiredTime)
  117. // await this.stateless.FireAsync(Trigger.AnyPumpMsgHaveNotReceivedForWhile);
  118. // };
  119. // this.deviceOfflineCountdownTimer.Start();
  120. // this.stateless.OnTransitioned(async (transition) =>
  121. // {
  122. // if (transition.Destination != transition.Source)
  123. // {
  124. // this.lastLogicalDeviceState = transition.Destination;
  125. // logger.LogInformation("Pump: " + this.pumpId + ", " + " State switched from: " + transition.Source + " to " + transition.Destination);
  126. // this.OnStateChange?.Invoke(this, new FdcPumpControllerOnStateChangeEventArg(transition.Destination, this.nozzles.FirstOrDefault()));
  127. // }
  128. // if (transition.Destination != LogicalDeviceState.FDC_OFFLINE)
  129. // {
  130. // //always send a query to try to align latest price.
  131. // this.context.Outgoing.Write(new ReadPriceRequest() { Adrs = this.address });
  132. // }
  133. // });
  134. // this.stateless.Configure(LogicalDeviceState.FDC_OFFLINE)
  135. // .OnEntryAsync(async () => { })
  136. // .OnEntryAsync(async () => { })
  137. // //.Ignore(Trigger.AnyPumpMsgReceived)
  138. // .Ignore(Trigger.AnyPumpMsgHaveNotReceivedForWhile)
  139. // .PermitIf(Trigger.NozzleLifted_And_停机, LogicalDeviceState.FDC_CALLING, () => true)
  140. // .PermitIf(Trigger.NozzleLifted_And_开机, LogicalDeviceState.FDC_AUTHORISED, () => true)
  141. // .PermitIf(Trigger.NozzleReplaced_And_停机, LogicalDeviceState.FDC_READY, () => true)
  142. // .PermitIf(Trigger.NozzleReplaced_And_开机, LogicalDeviceState.FDC_AUTHORISED, () => true);
  143. // //once a fule sale is done, a retrieving process is triggered, before the process done, new pump Calling will be blocked.
  144. // bool isOnRetrievingLastFuelSale = false;
  145. // this.stateless.Configure(LogicalDeviceState.FDC_READY)
  146. // .OnEntryFromAsync(Trigger.NozzleReplaced_And_停机, async (transition) =>
  147. // {
  148. // if (transition.Source == LogicalDeviceState.FDC_FUELLING)
  149. // {
  150. // isOnRetrievingLastFuelSale = true;
  151. // ReadFuelDataResponse finalTrxDataReading;
  152. // try
  153. // {
  154. // logger.LogInformation("Pump: " + this.pumpId + ", A fueling just done, Retrieving last fuel sale trx...");
  155. // finalTrxDataReading =
  156. // await this.context.Outgoing.WriteAsync(new ReadFuelDataRequest() { Adrs = this.address },
  157. // (_, testResponse) => testResponse is ReadFuelDataResponse rp && rp.Adrs == this.address, 3000) as ReadFuelDataResponse;
  158. // if (finalTrxDataReading == null)
  159. // {
  160. // finalTrxDataReading =
  161. // await this.context.Outgoing.WriteAsync(new ReadFuelDataRequest() { Adrs = this.address },
  162. // (_, testResponse) => testResponse is ReadFuelDataResponse rp && rp.Adrs == this.address, 2000) as ReadFuelDataResponse;
  163. // if (finalTrxDataReading == null)
  164. // {
  165. // logger.LogWarning("Pump: " + this.pumpId + ", fuel sale trx is missing for final read(auto tried one more time and still failed), trx will lost");
  166. // return;
  167. // }
  168. // }
  169. // }
  170. // finally
  171. // {
  172. // isOnRetrievingLastFuelSale = false;
  173. // }
  174. // // at least within 65 years, exception will not throw here
  175. // int newTrxSeqNumber = (int)(DateTime.Now.Subtract(new DateTime(2020, 6, 5)).TotalSeconds);
  176. // logger.LogDebug("Pump: " + this.pumpId + ", Retrieved fuel sale trx, amt: " + finalTrxDataReading.Amount + ", vol: " + finalTrxDataReading.Volume + ", seqNo.: " + newTrxSeqNumber);
  177. // var newTrx = new FdcTransaction()
  178. // {
  179. // // 只有一把枪
  180. // Nozzle = this.nozzles.First(),
  181. // Amount = finalTrxDataReading.Amount,
  182. // Volumn = finalTrxDataReading.Volume,
  183. // Price = this.nozzles.First().RealPriceOnPhysicalPump ?? -1,
  184. // SequenceNumberGeneratedOnPhysicalPump = newTrxSeqNumber,
  185. // Finished = true,
  186. // };
  187. // this.OnCurrentFuellingStatusChange?.Invoke(this, new FdcTransactionDoneEventArg(newTrx));
  188. // }
  189. // })
  190. // .OnEntryAsync(async () => { })
  191. // //.Ignore(Trigger.AnyPumpMsgReceived)
  192. // .Ignore(Trigger.NozzleReplaced_And_停机)
  193. // .Ignore(Trigger.NozzleFuelNumbersIsRunning)
  194. // .PermitIf(Trigger.NozzleLifted_And_停机, LogicalDeviceState.FDC_CALLING, () => !isOnRetrievingLastFuelSale)
  195. // .PermitIf(Trigger.NozzleLifted_And_开机, LogicalDeviceState.FDC_AUTHORISED, () => true)
  196. // .PermitIf(Trigger.AnyPumpMsgHaveNotReceivedForWhile, LogicalDeviceState.FDC_OFFLINE, () => true);
  197. // this.stateless.Configure(LogicalDeviceState.FDC_CALLING)
  198. // .OnEntryAsync(async () => { })
  199. // .OnEntryAsync(async () => { })
  200. // //.Ignore(Trigger.AnyPumpMsgReceived)
  201. // .Ignore(Trigger.NozzleLifted_And_停机)
  202. // .PermitIf(Trigger.NozzleReplaced_And_停机, LogicalDeviceState.FDC_READY, () => true)
  203. // .PermitIf(Trigger.NozzleLifted_And_开机, LogicalDeviceState.FDC_AUTHORISED, () => true)
  204. // .PermitIf(Trigger.AnyPumpMsgHaveNotReceivedForWhile, LogicalDeviceState.FDC_OFFLINE, () => true);
  205. // this.nozzleFuelNumbersIsRunningTrigger =
  206. // this.stateless.SetTriggerParameters<FdcTransaction>(Trigger.NozzleFuelNumbersIsRunning);
  207. // this.stateless.Configure(LogicalDeviceState.FDC_AUTHORISED)
  208. // .OnEntryAsync(() =>
  209. // Task.Run(() => this.context.Outgoing.Write(new ReadFuelDataRequest() { Adrs = this.address }))
  210. // )
  211. // .OnExitAsync(async () => { })
  212. // //.Ignore(Trigger.AnyPumpMsgReceived)
  213. // .Ignore(Trigger.NozzleLifted_And_开机)
  214. // .PermitIf(Trigger.NozzleFuelNumbersIsRunning, LogicalDeviceState.FDC_FUELLING, () => true)
  215. // .PermitIf(Trigger.AnyPumpMsgHaveNotReceivedForWhile, LogicalDeviceState.FDC_OFFLINE, () => true);
  216. // this.stateless.Configure(LogicalDeviceState.FDC_FUELLING)
  217. // .OnEntryFromAsync(this.nozzleFuelNumbersIsRunningTrigger, async (arg) =>
  218. // {
  219. // this.OnCurrentFuellingStatusChange?.Invoke(this, new FdcTransactionDoneEventArg(arg));
  220. // this.context.Outgoing.Write(new ReadFuelDataRequest() { Adrs = this.address });
  221. // //for detecting nozzle placed back.
  222. // this.context.Outgoing.Write(new ReadPumpStateRequest() { Adrs = this.address });
  223. // })
  224. // .OnEntryAsync(async () => { })
  225. // .OnExitAsync(async () => { })
  226. // .PermitReentry(Trigger.NozzleFuelNumbersIsRunning)
  227. // //.Ignore(Trigger.AnyPumpMsgReceived)
  228. // .Ignore(Trigger.NozzleLifted_And_开机)
  229. // .PermitIf(Trigger.NozzleReplaced_And_停机, LogicalDeviceState.FDC_READY, () => true)
  230. // .PermitIf(Trigger.NozzleReplaced_And_开机, LogicalDeviceState.FDC_AUTHORISED, () => true)
  231. // .PermitIf(Trigger.AnyPumpMsgHaveNotReceivedForWhile, LogicalDeviceState.FDC_OFFLINE, () => true);
  232. // }
  233. // catch (Exception exxx)
  234. // {
  235. // logger.LogError("Constructing LanTian_Pump_664_Or_886.StatePumpHanlder exceptioned: " + exxx);
  236. // }
  237. // }
  238. // public void OnFdcServerInit(Dictionary<string, object> parameters)
  239. // {
  240. // if (parameters.ContainsKey("LastPriceChange"))
  241. // {
  242. // // nozzle logical id:rawPrice
  243. // var lastPriceChanges = parameters["LastPriceChange"] as Dictionary<byte, int>;
  244. // foreach (var priceChange in lastPriceChanges)
  245. // {
  246. // logger.LogInformation("Pump: " + this.pumpId + ", " + "Pump " + this.pumpId + " OnFdcServerInit, load last price change " +
  247. // "on logical nozzle: " + priceChange.Key + " with price: " + priceChange.Value);
  248. // this.nozzles.First(n => n.LogicalId == priceChange.Key).ExpectingPriceOnFcSide = priceChange.Value;
  249. // }
  250. // }
  251. // /* Load Last sale trx(from db) for void the case of FC accidently disconnect from Pump in fueling,
  252. // and may cause a fueling trx gone from FC control */
  253. // if (parameters.ContainsKey("LastFuelSaleTrx"))
  254. // {
  255. // // nozzle logical id:LastSale
  256. // var lastFuelSaleTrxes = parameters["LastFuelSaleTrx"] as Dictionary<byte, FuelSaleTransaction>;
  257. // foreach (var lastFuelSaleTrx in lastFuelSaleTrxes)
  258. // {
  259. // logger.LogInformation("Pump: " + this.pumpId + ", OnFdcServerInit, load last volume Totalizer " +
  260. // "on logical nozzle: " + lastFuelSaleTrx.Key + " with volume value: " + lastFuelSaleTrx.Value.VolumeTotalizer);
  261. // this.nozzles.First(n => n.LogicalId == lastFuelSaleTrx.Key).VolumeTotalizer = lastFuelSaleTrx.Value.VolumeTotalizer;
  262. // }
  263. // }
  264. // this.isOnFdcServerInitCalled = true;
  265. // }
  266. // public void Init(IContext<byte[], MessageBase> context)
  267. // {
  268. // this.context = context;
  269. // var timeWindowWithActivePollingOutgoing =
  270. // this.context.Outgoing as TimeWindowWithActivePollingOutgoing<byte[], MessageBase>;
  271. // timeWindowWithActivePollingOutgoing.PollingMsgProducer = () => new ReadPumpStateRequest();
  272. // }
  273. // public async Task Process(IContext<byte[], MessageBase> context)
  274. // {
  275. // try
  276. // {
  277. // if (!isOnFdcServerInitCalled) return;
  278. // this.lastLogicalDeviceStateReceivedTime = DateTime.Now;
  279. // //await this.stateless.FireAsync(Trigger.AnyPumpMsgReceived);
  280. // if (context.Incoming.Message is ReadPumpStateResponse readPumpStateResponse)
  281. // {
  282. // #region AcquireControl if pump authorize mode is FC_Authorize
  283. // if (readPumpStateResponse.ControlState == ReadPumpStateResponse.ControlStateEnum.自控
  284. // && this.pumpAuthorizeMode == PumpAuthorizeModeEnum.FC_Authorize)
  285. // {
  286. // var acquireControlResponse = await this.context.Outgoing.WriteAsync(
  287. // new AcquireControlRequest() { Adrs = this.address },
  288. // (request, response) => response is AcquireControlResponse rp && rp.Adrs == this.address, 3000).ConfigureAwait(false) as AcquireControlResponse;
  289. // if (acquireControlResponse == null)
  290. // {
  291. // logger.LogInformation("Pump: " + this.pumpId + ", " + " AcquireControlResponse first time timedout, will send 2nd time...");
  292. // acquireControlResponse = await this.context.Outgoing.WriteAsync(
  293. // new AcquireControlRequest() { Adrs = this.address },
  294. // (request, response) => response is AcquireControlResponse rp && rp.Adrs == this.address, 3000).ConfigureAwait(false) as AcquireControlResponse;
  295. // if (acquireControlResponse == null)
  296. // logger.LogInformation("Pump: " + this.pumpId + ", " + " AcquireControlResponse 2nd time timedout, will ignore this error, then the pump may have wrong authorize mode");
  297. // }
  298. // }
  299. // #endregion
  300. // if (readPumpStateResponse.NozzleState == ReadPumpStateResponse.NozzleStateEnum.提枪)
  301. // {
  302. // if (readPumpStateResponse.StartOrStopState == ReadPumpStateResponse.StartOrStopStateEnum.开机)
  303. // await this.stateless.FireAsync(Trigger.NozzleLifted_And_开机);
  304. // else
  305. // await this.stateless.FireAsync(Trigger.NozzleLifted_And_停机);
  306. // }
  307. // else
  308. // {
  309. // if (readPumpStateResponse.StartOrStopState == ReadPumpStateResponse.StartOrStopStateEnum.开机)
  310. // await this.stateless.FireAsync(Trigger.NozzleReplaced_And_开机);
  311. // else
  312. // await this.stateless.FireAsync(Trigger.NozzleReplaced_And_停机);
  313. // }
  314. // }
  315. // else if (context.Incoming.Message is ReadFuelDataResponse readFuelDataResponse)
  316. // {
  317. // //await this.stateless.FireAsync(Trigger.NozzleFuelNumbersIsRunning);
  318. // await this.stateless.FireAsync(this.nozzleFuelNumbersIsRunningTrigger,
  319. // new FdcTransaction()
  320. // {
  321. // // 只有一把枪
  322. // Nozzle = this.nozzles.First(),
  323. // Amount = readFuelDataResponse.Amount,
  324. // Volumn = readFuelDataResponse.Volume,
  325. // Price = this.nozzles.First().RealPriceOnPhysicalPump ?? -1,
  326. // Finished = false,
  327. // });
  328. // }
  329. // else if (context.Incoming.Message is ReadPriceResponse readPriceResponse)
  330. // {
  331. // if (!this.nozzles.First().RealPriceOnPhysicalPump.HasValue ||
  332. // this.nozzles.First().RealPriceOnPhysicalPump.Value != readPriceResponse.Price)
  333. // logger.LogInformation("Pump " + this.pumpId + ", detected the pump side price changed from: "
  334. // + (this.nozzles.First().RealPriceOnPhysicalPump ?? -1) + " to: " + readPriceResponse.Price + ", will updating to local");
  335. // this.nozzles.First().RealPriceOnPhysicalPump = readPriceResponse.Price;
  336. // }
  337. // }
  338. // catch (Exception eee)
  339. // {
  340. // logger.LogInformation("Process(...) exceptioned: " + eee);
  341. // }
  342. // }
  343. // /// <summary>
  344. // /// no decimal point value.
  345. // /// </summary>
  346. // /// <returns>MoneyTotalizer:VolumnTotalizer</returns>
  347. // public async Task<System.Tuple<int, int>> QueryTotalizerAsync(byte logicalNozzleId)
  348. // {
  349. // var readTotalizerResponse = await this.context.Outgoing.WriteAsync(new ReadTotalizerRequest() { Adrs = this.address },
  350. // (_, testResponse) => testResponse is ReadTotalizerResponse rp && rp.Adrs == this.address, 3000) as ReadTotalizerResponse;
  351. // if (readTotalizerResponse == null) return new System.Tuple<int, int>(-1, -1);
  352. // return new System.Tuple<int, int>((int)readTotalizerResponse.AmountTotalizer, (int)readTotalizerResponse.VolumeTotalizer);
  353. // }
  354. // public async Task<bool> SuspendFuellingAsync()
  355. // {
  356. // logger.LogDebug("Pump " + this.pumpId + ", SuspendFuellingAsync...");
  357. // var suspendFuelResponse = await this.context.Outgoing.WriteAsync(new SuspendFuelRequest() { Adrs = this.address },
  358. // (_, testResponse) => testResponse is SuspendFuelResponse rp && rp.Adrs == this.address, 3000) as SuspendFuelResponse;
  359. // var result = suspendFuelResponse != null;
  360. // logger.LogDebug("Pump " + this.pumpId + ", SuspendFuellingAsync result: " + result);
  361. // return result;
  362. // }
  363. // public async Task<bool> ResumeFuellingAsync()
  364. // {
  365. // logger.LogDebug("Pump " + this.pumpId + ", ResumeFuellingAsync...");
  366. // var resumeFuelResponse = await this.context.Outgoing.WriteAsync(new ResumeFuelRequest() { Adrs = this.address },
  367. // (_, testResponse) => testResponse is ResumeFuelResponse rp && rp.Adrs == this.address, 3000) as ResumeFuelResponse;
  368. // var result = resumeFuelResponse != null;
  369. // logger.LogDebug("Pump " + this.pumpId + ", ResumeFuellingAsync result: " + result);
  370. // return result;
  371. // }
  372. // public async Task<bool> ChangeFuelPriceAsync(int newPriceWithoutDecimalPoint, byte logicalNozzleId)
  373. // {
  374. // logger.LogInformation("Pump: " + this.pumpId + ", " + " ChangeFuelPriceAsync, new price: " + newPriceWithoutDecimalPoint);
  375. // var readPriceResponse = await this.context.Outgoing.WriteAsync(new ReadPriceRequest() { Adrs = this.address },
  376. // (request, response) => response is ReadPriceResponse rp && rp.Adrs == this.address, 3000).ConfigureAwait(false) as ReadPriceResponse;
  377. // if (readPriceResponse == null)
  378. // {
  379. // logger.LogInformation("Pump: " + this.pumpId + ", " + " Reading pump side price timedout, will ignore this error and won't send a ChangePriceRequest here but may need a manual Price change if find price discrepancy");
  380. // return false;
  381. // }
  382. // this.nozzles.First().RealPriceOnPhysicalPump = readPriceResponse.Price;
  383. // if (readPriceResponse.Price != newPriceWithoutDecimalPoint)
  384. // {
  385. // //logger.LogInformation("Pump: " + this.pumpId + ", "
  386. // // + " Read the pump side price(without decimal points): " + readPriceResponse.Price + " which NOT Equals with the price as FC expect, will start a change price internally...");
  387. // var changePriceResponse = await this.context.Outgoing.WriteAsync(
  388. // new ChangePriceRequest(newPriceWithoutDecimalPoint, this.pumpModel == PumpModelEnum.Model_664 ? (byte)2 : (byte)3) { Adrs = this.address },
  389. // (request, response) => response is ChangePriceResponse rp && rp.Adrs == this.address, 3000).ConfigureAwait(false) as ChangePriceResponse;
  390. // if (changePriceResponse == null || !changePriceResponse.Succeed)
  391. // {
  392. // logger.LogInformation("Pump: " + this.pumpId + ", " + " change price timedout or failed, may need a manual price change later if find price discrepancy");
  393. // return false;
  394. // }
  395. // var doubleConfirm_readPriceResponse = await this.context.Outgoing.WriteAsync(new ReadPriceRequest() { Adrs = this.address },
  396. // (request, response) => response is ReadPriceResponse rp && rp.Adrs == this.address, 3000).ConfigureAwait(false) as ReadPriceResponse;
  397. // if (doubleConfirm_readPriceResponse == null)
  398. // {
  399. // logger.LogInformation("Pump: " + this.pumpId + ", " + " Double confirm change price timedout, so FC can't sure if the new price applied, or a manual Price change is needed if find price discrepancy");
  400. // return false;
  401. // }
  402. // else if (doubleConfirm_readPriceResponse.Price == newPriceWithoutDecimalPoint)
  403. // {
  404. // this.nozzles.First().RealPriceOnPhysicalPump = doubleConfirm_readPriceResponse.Price;
  405. // logger.LogInformation("Pump: " + this.pumpId + ", " + " Double confirm succeed for new FC price(without decimal points): " + newPriceWithoutDecimalPoint + " have been applied to pump.");
  406. // return true;
  407. // }
  408. // else
  409. // {
  410. // logger.LogInformation("Pump: " + this.pumpId + ", " + " Double confirm failed for new FC price(without decimal points): " + newPriceWithoutDecimalPoint + " failed applying to pump as pump side still report its price(without decimal point): " + doubleConfirm_readPriceResponse.Price + ", a manual Change Price is needed");
  411. // return false;
  412. // }
  413. // }
  414. // else
  415. // {
  416. // logger.LogInformation("Pump: " + this.pumpId + ", " + " Read the pump side price(without decimal points): " + readPriceResponse.Price + ", no need to align with FC(FC has no expecting price)");
  417. // return true;
  418. // }
  419. // }
  420. // public async Task<bool> AuthorizeAsync(byte logicalNozzleId)
  421. // {
  422. // logger.LogDebug("Pump " + this.pumpId + ", AuthorizeAsync...");
  423. // var openResponse = await this.context.Outgoing.WriteAsync(new OpenRequest() { Adrs = this.address },
  424. // (_, testResponse) => testResponse is OpenResponse rp && rp.Adrs == this.address, 3000) as OpenResponse;
  425. // if (openResponse == null)
  426. // {
  427. // logger.LogInformation("Pump " + this.pumpId + ", AuthorizeAsync failed due to timedout");
  428. // return false;
  429. // }
  430. // logger.LogInformation("Pump " + this.pumpId + ", AuthorizeAsync result: " + openResponse.Succeed);
  431. // return openResponse.Succeed;
  432. // }
  433. // public async Task<bool> UnAuthorizeAsync(byte logicalNozzleId)
  434. // {
  435. // return false;
  436. // }
  437. // public async Task<bool> AuthorizeWithAmountAsync(int moneyAmountWithoutDecimalPoint, byte logicalNozzleId)
  438. // {
  439. // logger.LogDebug("Pump " + this.pumpId + ", AuthorizeWithAmountAsync(amt: " + moneyAmountWithoutDecimalPoint + ")...");
  440. // var presetAmountResponse = await this.context.Outgoing.WriteAsync(
  441. // new PresetAmountRequest(moneyAmountWithoutDecimalPoint,
  442. // this.pumpModel == PumpModelEnum.Model_664 ? (byte)3 : (byte)4)
  443. // { Adrs = this.address },
  444. // (_, testResponse) => testResponse is PresetAmountResponse rp && rp.Adrs == this.address, 3000) as PresetAmountResponse;
  445. // if (presetAmountResponse == null)
  446. // {
  447. // logger.LogInformation("Pump " + this.pumpId + ", AuthorizeWithAmountAsync failed due to PresetAmountRequest timedout");
  448. // return false;
  449. // }
  450. // logger.LogInformation("Pump " + this.pumpId + ", AuthorizeWithAmountAsync PresetAmountRequest succeed, will AuthorizePump...");
  451. // return await this.AuthorizeAsync(logicalNozzleId);
  452. // }
  453. // public async Task<bool> AuthorizeWithVolumeAsync(int volumnWithoutDecimalPoint, byte logicalNozzleId)
  454. // {
  455. // logger.LogDebug("Pump " + this.pumpId + ", AuthorizeWithVolumeAsync(amt: " + volumnWithoutDecimalPoint + ")...");
  456. // var presetVolumeResponse = await this.context.Outgoing.WriteAsync(
  457. // new PresetVolumeRequest(volumnWithoutDecimalPoint,
  458. // this.pumpModel == PumpModelEnum.Model_664 ? (byte)3 : (byte)4)
  459. // { Adrs = this.address },
  460. // (_, testResponse) => testResponse is PresetVolumeResponse rp && rp.Adrs == this.address, 3000) as PresetVolumeResponse;
  461. // if (presetVolumeResponse == null)
  462. // {
  463. // logger.LogInformation("Pump " + this.pumpId + ", AuthorizeWithVolumeAsync failed due to PresetVolumeRequest timedout");
  464. // return false;
  465. // }
  466. // logger.LogInformation("Pump " + this.pumpId + ", AuthorizeWithVolumeAsync PresetVolumeRequest succeed, will AuthorizePump...");
  467. // return await this.AuthorizeAsync(logicalNozzleId);
  468. // }
  469. // public Task<bool> FuelingRoundUpByAmountAsync(int amount)
  470. // {
  471. // return Task.FromResult(false);
  472. // }
  473. // public Task<bool> FuelingRoundUpByVolumeAsync(int volume)
  474. // {
  475. // return Task.FromResult(false);
  476. // }
  477. // }
  478. //}