MessageBase.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. using Edge.Core.Parser.BinaryParser.Attributes;
  2. using Edge.Core.Parser.BinaryParser;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Text;
  7. using Edge.Core.Parser.BinaryParser.MessageEntity;
  8. using static VeederRoot_ATG_Console.MessageEntity.MessageBase;
  9. namespace VeederRoot_ATG_Console.MessageEntity
  10. {
  11. public static class FunctionCodeWrapper
  12. {
  13. private static List<Tuple<string, FuncCode, MessageFormat>> map
  14. = new List<Tuple<string, FuncCode, MessageFormat>>()
  15. {
  16. new Tuple<string, FuncCode, MessageFormat>("i201",
  17. FuncCode.QueryInTankInventoryReport, MessageFormat.Computer ),
  18. new Tuple<string, FuncCode, MessageFormat>("I201",
  19. FuncCode.QueryInTankInventoryReport, MessageFormat.Display),
  20. new Tuple<string, FuncCode, MessageFormat>("i501",
  21. FuncCode.QueryTimeOfDay, MessageFormat.Computer),
  22. new Tuple<string, FuncCode, MessageFormat>("I501",
  23. FuncCode.QueryTimeOfDay, MessageFormat.Display),
  24. new Tuple<string, FuncCode, MessageFormat>("s501",
  25. FuncCode.SetTimeOfDay, MessageFormat.Computer),
  26. new Tuple<string, FuncCode, MessageFormat>("S501",
  27. FuncCode.SetTimeOfDay, MessageFormat.Display),
  28. new Tuple<string, FuncCode, MessageFormat>("i205",
  29. FuncCode.QueryInTankStatusReport, MessageFormat.Computer),
  30. new Tuple<string, FuncCode, MessageFormat>("I205",
  31. FuncCode.QueryInTankStatusReport, MessageFormat.Display),
  32. new Tuple<string, FuncCode, MessageFormat>("i20C",
  33. FuncCode.QueryInTankMostRecentDeliveryReport, MessageFormat.Computer),
  34. new Tuple<string, FuncCode, MessageFormat>("I20C",
  35. FuncCode.QueryInTankMostRecentDeliveryReport, MessageFormat.Display),
  36. new Tuple<string, FuncCode, MessageFormat>("i505",
  37. FuncCode.QuerySystemTypeAndLanguageFlags, MessageFormat.Computer),
  38. new Tuple<string, FuncCode, MessageFormat>("I505",
  39. FuncCode.QuerySystemTypeAndLanguageFlags, MessageFormat.Display),
  40. new Tuple<string, FuncCode, MessageFormat>("i517",
  41. FuncCode.QuerySystemTypeAndLanguageFlags_Extended, MessageFormat.Computer),
  42. new Tuple<string, FuncCode, MessageFormat>("I517",
  43. FuncCode.QuerySystemTypeAndLanguageFlags_Extended, MessageFormat.Display),
  44. new Tuple<string, FuncCode, MessageFormat>("s505",
  45. FuncCode.SetSystemTypeAndLanguageFlags, MessageFormat.Computer),
  46. new Tuple<string, FuncCode, MessageFormat>("S505",
  47. FuncCode.SetSystemTypeAndLanguageFlags, MessageFormat.Display),
  48. new Tuple<string, FuncCode, MessageFormat>("i602",
  49. FuncCode.QueryTankProductLabel, MessageFormat.Computer),
  50. new Tuple<string, FuncCode, MessageFormat>("I602",
  51. FuncCode.QueryTankProductLabel, MessageFormat.Display),
  52. new Tuple<string, FuncCode, MessageFormat>("s602",
  53. FuncCode.SetTankProductLabel, MessageFormat.Computer),
  54. new Tuple<string, FuncCode, MessageFormat>("S602",
  55. FuncCode.SetTankProductLabel, MessageFormat.Display),
  56. new Tuple<string, FuncCode, MessageFormat>("i607",
  57. FuncCode.QueryTankDiameter, MessageFormat.Computer),
  58. new Tuple<string, FuncCode, MessageFormat>("I607",
  59. FuncCode.QueryTankDiameter, MessageFormat.Display),
  60. new Tuple<string, FuncCode, MessageFormat>("s607",
  61. FuncCode.SetTankDiameter, MessageFormat.Computer),
  62. new Tuple<string, FuncCode, MessageFormat>("S607",
  63. FuncCode.SetTankDiameter, MessageFormat.Display),
  64. new Tuple<string, FuncCode, MessageFormat>("i101",
  65. FuncCode.QuerySystemStatusReport, MessageFormat.Computer),
  66. new Tuple<string, FuncCode, MessageFormat>("I101",
  67. FuncCode.QuerySystemStatusReport, MessageFormat.Display),
  68. new Tuple<string, FuncCode, MessageFormat>("iA01",
  69. FuncCode.QueryInTankDiagnosticReport, MessageFormat.Computer),
  70. new Tuple<string, FuncCode, MessageFormat>("IA01",
  71. FuncCode.QueryInTankDiagnosticReport, MessageFormat.Display)
  72. };
  73. /// <summary>
  74. /// Convert 6 digits raw code into a pre-defined function code and its format.
  75. /// </summary>
  76. /// <param name="rawCode">Length is 6, started with an upper or lower case alphabet, like i00100, I00100, s00200, S00200</param>
  77. /// <returns>null indicates could not find correlated pre-defined function code</returns>
  78. public static Tuple<MessageFormat, FuncCode> FromRawCode(string rawCode)
  79. {
  80. return map.Where(c => rawCode.StartsWith(c.Item1))
  81. .Select(s => new Tuple<MessageFormat, FuncCode>(s.Item3, s.Item2)).FirstOrDefault();
  82. }
  83. /// <summary>
  84. /// Get a length 4 raw code string.
  85. /// </summary>
  86. /// <param name="messageFormat"></param>
  87. /// <param name="functionCode"></param>
  88. /// <returns>length 4 string with an 1 digit alphabet + 3 digits numbers</returns>
  89. public static string ToRawCode(MessageFormat messageFormat, FuncCode functionCode)
  90. {
  91. return map.Where(c => c.Item2 == functionCode && c.Item3 == messageFormat)
  92. .Select(s => s.Item1).FirstOrDefault();
  93. }
  94. }
  95. public abstract class MessageBase : MessageBaseGeneric
  96. {
  97. public enum MessageFormat
  98. {
  99. /// <summary>
  100. /// started with a lower case alphabet.
  101. /// indicates the message is a stream of numbers without any formatting characters, no carriage return,
  102. /// line feed, spaces, labels and etc.
  103. ///
  104. /// SOH + FunctionCode + DataField + && + Checksum + ETX
  105. /// </summary>
  106. Computer,
  107. /// <summary>
  108. /// started with a upper case alphabet.
  109. /// indicates the message is intended for display to a CRT or printer, it includes all the necessary
  110. /// formatting characters such as carriage returns, line feeds, nulls, spaces, labels and etc.
  111. ///
  112. /// SOH + FunctionCode + DataField + ETX
  113. /// </summary>
  114. Display,
  115. }
  116. public enum FuncCode
  117. {
  118. /// <summary>
  119. /// i|I50500
  120. /// </summary>
  121. QuerySystemTypeAndLanguageFlags,
  122. /// <summary>
  123. /// i|I51700
  124. /// </summary>
  125. QuerySystemTypeAndLanguageFlags_Extended,
  126. /// <summary>
  127. /// s|S50500UL, U is system units, L is system language.
  128. /// </summary>
  129. SetSystemTypeAndLanguageFlags,
  130. /// <summary>
  131. /// Append i|I, response function code is i|I201.
  132. /// </summary>
  133. QueryInTankInventoryReport,
  134. /// <summary>
  135. /// Append i|I, response function code is i|I501.
  136. /// </summary>
  137. QueryTimeOfDay,
  138. /// <summary>
  139. /// Append s|S, response function code is s|S501.
  140. /// </summary>
  141. SetTimeOfDay,
  142. /// <summary>
  143. /// Append i|I, response function code is i|I205.
  144. /// </summary>
  145. QueryInTankStatusReport,
  146. /// <summary>
  147. /// Append i|I, response functin code is i|I20C.
  148. /// </summary>
  149. QueryInTankMostRecentDeliveryReport,
  150. /// <summary>
  151. /// Append i|I, response functin code is i|I602.
  152. /// </summary>
  153. QueryTankProductLabel,
  154. /// <summary>
  155. /// Append s|S, response functin code is i|I602.
  156. /// </summary>
  157. SetTankProductLabel,
  158. /// <summary>
  159. /// Append i|I, response functin code is i|I607.
  160. /// </summary>
  161. QueryTankDiameter,
  162. /// <summary>
  163. /// Append s|S, response functin code is i|I607.
  164. /// </summary>
  165. SetTankDiameter,
  166. /// <summary>
  167. /// Append i|I, response functin code is i|I10100.
  168. /// </summary>
  169. QuerySystemStatusReport,
  170. /// <summary>
  171. /// Append i|I, response functin code is i|IA01.
  172. /// Probe Type and Serial Number
  173. /// </summary>
  174. QueryInTankDiagnosticReport,
  175. Undefined,
  176. }
  177. [Format(1, EncodingType.BIN, -9999)]
  178. public byte SOH { get; set; } = 0x01;
  179. /// <summary>
  180. /// Gets or sets the function code raw value for the message, it's a 6 digits string, like S60201
  181. /// In most case you should not use this property directly, try use more friendly property `FunctionCode`
  182. /// </summary>
  183. [Format(6, EncodingType.ASCII, -9000)]
  184. public string FunctionCodeRaw { get; set; }
  185. /// <summary>
  186. /// Gets or sets the function code, it include 3 parts:
  187. /// MessageFormat(1st digits) + functionCode(3 digits) + appendix(2 digits)
  188. /// </summary>
  189. public Tuple<MessageFormat, FuncCode, string> FunctionCode
  190. {
  191. get
  192. {
  193. var c = FunctionCodeWrapper.FromRawCode(this.FunctionCodeRaw);
  194. return new Tuple<MessageFormat,
  195. FuncCode,
  196. string>(
  197. c.Item1,
  198. c.Item2,
  199. this.FunctionCodeRaw.Substring(4, 2));
  200. }
  201. set
  202. {
  203. var raw = FunctionCodeWrapper.ToRawCode(value.Item1, value.Item2);
  204. if (string.IsNullOrEmpty(raw))
  205. throw new ArgumentException("Can't find raw function code for: " + value.Item1 + " - " + value.Item2);
  206. if (!string.IsNullOrEmpty(value.Item3))
  207. raw += value.Item3.PadLeft(2, '0');
  208. else
  209. raw = raw.PadRight(6, '0');
  210. if (raw.Length != 6) throw new ArgumentException("Function code must have length 6, but now is " + raw.Length);
  211. this.FunctionCodeRaw = raw;
  212. }
  213. }
  214. }
  215. }