PumpInOperationResponse.cs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. using Edge.Core.Parser.BinaryParser.Attributes;
  2. using Edge.Core.Parser.BinaryParser.Util;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. namespace ZhongSheng_NonIC_Pump
  9. {
  10. /// <summary>
  11. /// 加油实时数据命令格式和错误状态信息格式:
  12. /// (实时信息有时会一条枪有时会多条枪,每条枪用一个信息块表示)
  13. /// </summary>
  14. public class PumpInOperationResponse : MessageTemplateBase
  15. {
  16. private List<byte> dataRaw;
  17. private IEnumerable<FuellingDataBlock> fuellingDataBlocks;
  18. private IEnumerable<PumpStateBlock> pumpStateBlocks;
  19. /// <summary>
  20. /// </summary>
  21. [EnumerableFormat("%cascade", 1, EncodingType = EncodingType.BIN)]
  22. public List<byte> DataRaw
  23. {
  24. get { return this.dataRaw; }
  25. set
  26. {
  27. this.dataRaw = value;
  28. this.fuellingDataBlocks = this.ParseFuellingDataBlocks();
  29. this.pumpStateBlocks = this.ParsePumpStateBlocks();
  30. }
  31. }
  32. private IEnumerable<FuellingDataBlock> ParseFuellingDataBlocks()
  33. {
  34. if (this.DataRaw == null || !this.DataRaw.Any()) throw new ArgumentException("DataRaw is null or empty");
  35. List<FuellingDataBlock> results = null;
  36. int elapsedCount = 0;
  37. //skip the 信息计数n(1字节)
  38. var blocks = this.DataRaw.Skip(1);
  39. while (true)
  40. {
  41. var nxt = blocks.Skip(elapsedCount).ToArray();
  42. if (!nxt.Any()) return results;
  43. if (nxt.Length < 12)
  44. return results;
  45. if (nxt[0] == 0x01)
  46. {
  47. if (results == null) results = new List<FuellingDataBlock>();
  48. elapsedCount += 12;
  49. var block = new FuellingDataBlock()
  50. {
  51. NozzleNumber = nxt[1],
  52. Amount = nxt.Skip(2).Take(4).ToInt32(),
  53. Volume = nxt.Skip(6).Take(3).ToInt32(),
  54. Price = nxt.Skip(9).Take(3).ToInt32()
  55. };
  56. results.Add(block);
  57. }
  58. else
  59. elapsedCount += 7;
  60. }
  61. }
  62. private IEnumerable<PumpStateBlock> ParsePumpStateBlocks()
  63. {
  64. if (this.DataRaw == null || !this.DataRaw.Any()) throw new ArgumentException("DataRaw is null or empty");
  65. List<PumpStateBlock> results = null;
  66. int elapsedCount = 0;
  67. //skip the 信息计数n(1字节)
  68. var blocks = this.DataRaw.Skip(1);
  69. while (true)
  70. {
  71. var nxt = blocks.Skip(elapsedCount).ToArray();
  72. if (!nxt.Any()) return results;
  73. if (nxt.Length < 7)
  74. return results;
  75. //throw new ArgumentException("block data should either have length with times of 12 or 4, please check the full DataRaw: 0x" + this.DataRaw.ToHexLogString());
  76. if (nxt[0] == 0x01)
  77. {
  78. elapsedCount += 12;
  79. }
  80. else
  81. {
  82. if (results == null) results = new List<PumpStateBlock>();
  83. elapsedCount += 7;
  84. var paymentMode = (PumpAuthModeEnum)Enum.ToObject(typeof(PumpAuthModeEnum), nxt[2]);
  85. var pumpState = (NozzleLiftStateEnum)Enum.ToObject(typeof(NozzleLiftStateEnum), nxt[5]);
  86. var pumpAuthorizeState = (PumpAuthorizeStateEnum)Enum.ToObject(typeof(PumpAuthorizeStateEnum), nxt[6]);
  87. var block = new PumpStateBlock()
  88. {
  89. NozzleNumber = nxt[1],
  90. AuthMode = paymentMode,
  91. NozzleLiftState = pumpState,
  92. PumpAuthorizeState = pumpAuthorizeState
  93. };
  94. results.Add(block);
  95. }
  96. }
  97. }
  98. public IEnumerable<FuellingDataBlock> FuellingDataBlocks => this.fuellingDataBlocks;
  99. public IEnumerable<PumpStateBlock> PumpStateBlocks => this.pumpStateBlocks;
  100. public override string ToLogString()
  101. {
  102. string innerLog = "";
  103. if (this.PumpStateBlocks?.Any() ?? false)
  104. innerLog += "PumpStateBlocks -> " + this.PumpStateBlocks.Select(b => "Pump side nozzle No.: " + b.NozzleNumber +
  105. ", authMode: " + b.AuthMode +
  106. ", authState: " + b.PumpAuthorizeState +
  107. ", nzlState: " + b.NozzleLiftState).Aggregate((acc, n) => acc + " | " + n) + "; ";
  108. if (this.FuellingDataBlocks?.Any() ?? false)
  109. innerLog += "FuellingDataBlocks -> " + this.FuellingDataBlocks.Select(b => "Pump side nozzle No.: " + b.NozzleNumber +
  110. ", amt: " + b.Amount +
  111. ", vol: " + b.Volume +
  112. ", price: " + b.Price).Aggregate((acc, n) => acc + " | " + n);
  113. return base.ToLogString() + Environment.NewLine + innerLog;
  114. }
  115. }
  116. /// <summary>
  117. /// 状态字为0x01, 枪号为以整个加油站为基础的油枪顺序编号
  118. /// </summary>
  119. public class FuellingDataBlock
  120. {
  121. /// <summary>
  122. /// 枪号为以整个加油站为基础的油枪顺序编号
  123. /// </summary>
  124. public byte NozzleNumber { get; set; }
  125. /// <summary>
  126. /// 金额(带2位小数)(HEX)高位在前
  127. /// </summary>
  128. public int Amount { get; set; }
  129. /// <summary>
  130. /// 升数(带2位小数)(HEX)高位在前
  131. /// </summary>
  132. public int Volume { get; set; }
  133. /// <summary>
  134. /// 价格(带2位小数)(HEX)高位在前
  135. /// </summary>
  136. public int Price { get; set; }
  137. public override string ToString()
  138. {
  139. return "amt: " + this.Amount +
  140. ", vol: " + this.Volume +
  141. ", price: " + this.Price;
  142. }
  143. }
  144. public enum NozzleLiftStateEnum
  145. {
  146. 未提 = 0,
  147. /// <summary>
  148. /// 如果单面双单价模式,第一条枪提起为1,第二条枪提起为2
  149. /// </summary>
  150. 已提 = 1,
  151. 第二条枪提起 = 2,
  152. }
  153. public enum PumpAuthModeEnum
  154. {
  155. /// <summary>
  156. /// 油枪提枪后自动开始加油的模式,此模式下中控无法控制油机授权与否,于油机端设置。
  157. /// </summary>
  158. 自授权模式 = 0,
  159. /// <summary>
  160. /// 油枪需要中控授权才可以出油的模式,于油机端设置。
  161. /// 在油机被中控授权并完成一笔交易后,将自动解除授权状态,即下一笔提枪还需要中控再次发送授权命令。
  162. /// </summary>
  163. 需中控授权模式 = 4
  164. }
  165. public enum PumpAuthorizeStateEnum
  166. {
  167. /// <summary>
  168. /// 如果为中控授权模式,此值一直为'未授权'
  169. /// </summary>
  170. 未授权 = 0,
  171. /// <summary>
  172. /// 如果为中控授权模式,在油机获得授权后,将保持此状态,再完成一笔加油后,油机将自动进入'未授权'状态,从而下一次加油需要中控再次授权。
  173. /// </summary>
  174. 授权成功 = 1
  175. }
  176. public class PumpStateBlock
  177. {
  178. /// <summary>
  179. /// 枪号为以整个加油站为基础的油枪顺序编号
  180. /// </summary>
  181. public byte NozzleNumber { get; set; }
  182. /// <summary>
  183. /// 0表示非授权状态加油模式,4表示授权状态加油模式
  184. /// </summary>
  185. public PumpAuthModeEnum AuthMode { get; set; }
  186. /// <summary>
  187. /// 枪状态
  188. /// </summary>
  189. public NozzleLiftStateEnum NozzleLiftState { get; set; }
  190. /// <summary>
  191. /// 授权状态
  192. /// </summary>
  193. public PumpAuthorizeStateEnum PumpAuthorizeState { get; set; }
  194. public override string ToString()
  195. {
  196. return this.NozzleLiftState +
  197. ", " + this.AuthMode + "(" + this.PumpAuthorizeState + ")";
  198. }
  199. }
  200. }