GlobalTool.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. using EasyTemplate.Tool.Entity;
  2. using System.Collections.Concurrent;
  3. using System.Globalization;
  4. using System.Net.Sockets;
  5. using System.Runtime.InteropServices;
  6. using System.Text;
  7. using System.IO.Ports;
  8. namespace EasyTemplate.Service
  9. {
  10. public class GlobalTool
  11. {
  12. public const int NozzleState_Offline = 0;
  13. public const int NozzleState_Idle = 1;
  14. public const int NozzleState_Filling = 2;
  15. public const int WarningState_Normal = 0;
  16. public const int WarningState_Prewarning = 1;
  17. public const int WarningState_Warning = 2;
  18. public static Dictionary<int, NozzleState> g_mNozzleState = new Dictionary<int, NozzleState>();
  19. public static ConcurrentQueue<BufferData> g_dataQueue = new ConcurrentQueue<BufferData>();
  20. const int DIT_BUFSIZE = 1024;
  21. // 计算单个字节的CRC
  22. public static ushort calccrc(byte crcbuf, ushort crc)
  23. {
  24. byte i;
  25. crc = (ushort)(crc ^ crcbuf);
  26. for (i = 0; i < 8; i++)
  27. {
  28. byte chk;
  29. chk = (byte)(crc & 1);
  30. crc = (ushort)(crc >> 1);
  31. crc = (ushort)(crc & 0x7fff);
  32. if (chk == 1)
  33. crc = (ushort)(crc ^ 0xa001); /* CRC polynom=0xa001 */
  34. crc = (ushort)(crc & 0xffff);
  35. }
  36. return crc;
  37. }
  38. // 带自定义多项式的CRC计算
  39. public static ushort calccrc(byte crcbuf, ushort crc, ushort polynom)
  40. {
  41. byte i;
  42. crc = (ushort)(crc ^ crcbuf);
  43. for (i = 0; i < 8; i++)
  44. {
  45. byte chk;
  46. chk = (byte)(crc & 1);
  47. crc = (ushort)(crc >> 1);
  48. crc = (ushort)(crc & 0x7fff);
  49. if (chk == 1)
  50. crc = (ushort)(crc ^ polynom);
  51. crc = (ushort)(crc & 0xffff);
  52. }
  53. return crc;
  54. }
  55. // 标准CRC校验
  56. public static ushort chkcrc(byte[] buf, ushort len)
  57. {
  58. ushort i;
  59. ushort crc;
  60. crc = 0x0000; /* Initial crc value=0x0000 */
  61. for (i = 0; i < len; i++)
  62. {
  63. crc = calccrc(buf[i], crc);
  64. }
  65. return crc;
  66. }
  67. // 带多项式的CRC校验
  68. public static ushort chkcrc(byte[] buf, ushort len, ushort polynom)
  69. {
  70. ushort i;
  71. ushort crc;
  72. crc = 0x0000;
  73. for (i = 0; i < len; i++)
  74. {
  75. crc = calccrc(buf[i], crc, polynom);
  76. }
  77. return crc;
  78. }
  79. // Modbus CRC校验
  80. public static ushort chkcrc_modbus(byte[] buf, ushort len, ushort polynom)
  81. {
  82. ushort i;
  83. ushort crc;
  84. crc = 0xffff;
  85. for (i = 0; i < len; i++)
  86. {
  87. crc = calccrc(buf[i], crc, polynom);
  88. }
  89. return crc;
  90. }
  91. public static void crc_calc_sinopec(byte[] ptr_buffer, ushort length)
  92. {
  93. ushort crc_result;
  94. /* calculate CRC */
  95. crc_result = chkcrc(ptr_buffer, length);
  96. /* ... and store it */
  97. ptr_buffer[length] = (byte)(crc_result >> 8);
  98. ptr_buffer[length + 1] = (byte)crc_result;
  99. }
  100. public static string BytesToBcd(byte[] Bytes)
  101. {
  102. if (Bytes == null || Bytes.Length == 0)
  103. return string.Empty;
  104. StringBuilder result = new StringBuilder();
  105. foreach (byte b in Bytes)
  106. {
  107. // 提取高4位和低4位
  108. byte highNibble = (byte)((b >> 4) & 0x0F);
  109. byte lowNibble = (byte)(b & 0x0F);
  110. // 转换为字符
  111. result.Append((char)('0' + highNibble));
  112. result.Append((char)('0' + lowNibble));
  113. }
  114. return result.ToString();
  115. }
  116. public static T ByteToStructure<T>(Byte[] dataBuffer)
  117. {
  118. object structure = null;
  119. int size = Marshal.SizeOf(typeof(T));
  120. IntPtr allocIntPtr = Marshal.AllocHGlobal(size);
  121. try
  122. {
  123. Marshal.Copy(dataBuffer, 0, allocIntPtr, size);
  124. structure = Marshal.PtrToStructure(allocIntPtr, typeof(T));
  125. }
  126. catch (Exception e)
  127. {
  128. }
  129. finally
  130. {
  131. Marshal.FreeHGlobal(allocIntPtr);
  132. }
  133. return (T)structure;
  134. }
  135. public static byte[] StructToBytes(object structObj)
  136. {
  137. //得到结构体的大小
  138. int size = Marshal.SizeOf(structObj);
  139. //创建byte数组
  140. byte[] bytes = new byte[size];
  141. //分配结构体大小的内存空间
  142. IntPtr structPtr = Marshal.AllocHGlobal(size);
  143. //将结构体拷到分配好的内存空间
  144. Marshal.StructureToPtr(structObj, structPtr, false);
  145. //从内存空间拷到byte数组
  146. Marshal.Copy(structPtr, bytes, 0, size);
  147. //释放内存空间
  148. Marshal.FreeHGlobal(structPtr);
  149. //返回byte数组
  150. return bytes;
  151. }
  152. /// <summary>
  153. /// 将字节数组按大端序转换为整数
  154. /// </summary>
  155. /// <param name="bytes">字节数组</param>
  156. /// <returns>转换后的整数</returns>
  157. public static int BytesToInt(byte[] bytes)
  158. {
  159. if (bytes == null)
  160. throw new ArgumentNullException(nameof(bytes));
  161. if (bytes.Length == 0)
  162. return 0;
  163. if (bytes.Length > 4)
  164. throw new ArgumentException("字节数组长度不能超过4个字节");
  165. int result = 0;
  166. for (int i = 0; i < bytes.Length; i++)
  167. {
  168. result = (result << 8) | bytes[i];
  169. }
  170. return result;
  171. }
  172. public static bool checkEscapeCharacter(ref byte[] buf, ref int len, byte ch)
  173. {
  174. bool ischeck = false;
  175. byte[] tmpData = new byte[DIT_BUFSIZE];
  176. int j = 0;
  177. for (int i = 0; i < len && j < DIT_BUFSIZE; i++)
  178. {
  179. if (i < len - 1 && buf[i] == ch && buf[i + 1] == ch)
  180. {
  181. tmpData[j] = ch;
  182. i += 1; // 跳过下一个字符
  183. ischeck = true;
  184. j++;
  185. }
  186. else
  187. {
  188. tmpData[j] = buf[i];
  189. j++;
  190. }
  191. }
  192. // 更新长度和缓冲区内容
  193. len = j;
  194. Array.Copy(tmpData, buf, len);
  195. return ischeck;
  196. }
  197. public static bool calcEscapeLength(byte[] buf, ref int len, byte ch)
  198. {
  199. bool ischeck = false;
  200. // 确保数组足够大,如果不够大则调整循环次数
  201. int loopCount = Math.Min(DIT_BUFSIZE, buf.Length);
  202. for (int i = 0; i < loopCount; i++)
  203. {
  204. if (i < loopCount - 1 && buf[i] == ch && buf[i + 1] == ch)
  205. {
  206. i += 1; // 跳过下一个字符
  207. len--; // 长度减1
  208. ischeck = true;
  209. }
  210. }
  211. return ischeck;
  212. }
  213. public static int BCDtoDec(byte[] data, int length)
  214. {
  215. // BCD转十进制实现
  216. int result = 0;
  217. for (int i = 0; i < length; i++)
  218. {
  219. result = result * 100 + ((data[i] >> 4) * 10 + (data[i] & 0x0F));
  220. }
  221. return result;
  222. }
  223. /// <summary>
  224. /// 将BCD码转换回十进制数值
  225. /// </summary>
  226. /// <param name="bcdValue">BCD码值</param>
  227. /// <returns>对应的十进制数值</returns>
  228. public static int ConvertBCDToDecimalSingle(byte bcdValue)
  229. {
  230. // 提取高四位(十位数字)
  231. byte tens = (byte)((bcdValue >> 4) & 0x0F);
  232. // 提取低四位(个位数字)
  233. byte units = (byte)(bcdValue & 0x0F);
  234. // 组合得到十进制数值
  235. return tens * 10 + units;
  236. }
  237. /// <summary>
  238. /// 将多个BCD码转换为可变长度的十进制数值 如0x1234转成1234
  239. /// </summary>
  240. /// <param name="bcdBytes">BCD码字节数组</param>
  241. /// <returns>对应的十进制数值</returns>
  242. public static long ConvertBCDToDecimal(byte[] bcdBytes)
  243. {
  244. long result = 0;
  245. foreach (byte bcd in bcdBytes)
  246. {
  247. byte tens = (byte)((bcd >> 4) & 0x0F);
  248. byte units = (byte)(bcd & 0x0F);
  249. result = result * 100 + tens * 10 + units;
  250. }
  251. return result;
  252. }
  253. public static filling_nozzleup extractFillingNozzleUP(byte[] Buffer, int startIndex)
  254. {
  255. filling_nozzleup data = new filling_nozzleup();
  256. BufferHandler handler = new BufferHandler(Buffer, startIndex);
  257. data.board = handler.getData(1);
  258. data.noz = handler.getData(1);
  259. data.fip = data.board;
  260. data.time = handler.getDataString_BCD(7);
  261. return data;
  262. }
  263. public static filling_nozzledown extractFillingNozzleDown(byte[] Buffer, int startIndex)
  264. {
  265. filling_nozzledown data = new filling_nozzledown();
  266. BufferHandler handler = new BufferHandler(Buffer, startIndex);
  267. data.board = handler.getData(1);
  268. data.noz = handler.getData(1);
  269. data.fip = data.board;
  270. data.time = handler.getDataString_BCD(7);
  271. return data;
  272. }
  273. public static filling_process extractFillingProcess(byte[] Buffer, int startIndex)
  274. {
  275. filling_process data = new filling_process();
  276. BufferHandler handler = new BufferHandler(Buffer, startIndex);
  277. data.board = handler.getData(1);
  278. data.noz = handler.getData(1);
  279. data.fip = data.board;
  280. data.liquidVL = handler.getData(3);
  281. data.vaporVL = handler.getData(3);
  282. data.vaporFR = handler.getData(2);
  283. data.VLR = handler.getData(2);
  284. data.vaporPA = handler.getData(2);
  285. data.errornum = handler.getData(2);
  286. data.liquidFR = handler.getData(2);
  287. data.pwm = handler.getData(2);
  288. data.current = handler.getData(2);
  289. return data;
  290. }
  291. public static filling_record extractFillingRecord(byte[] Buffer, int startIndex)
  292. {
  293. int bufferlen = Buffer.Length;
  294. filling_record data = new filling_record();
  295. BufferHandler handler = new BufferHandler(Buffer, startIndex);
  296. data.board = handler.getData(1);
  297. data.noz = handler.getData(1);
  298. data.fip = data.board;
  299. if (bufferlen != 22)//兼容旧协议,解析顺序改变
  300. {
  301. data.ttc = handler.getData(4);
  302. }
  303. data.liquidVL = handler.getData(3);
  304. data.liquidFR = handler.getData(2);
  305. data.vaporVL = handler.getData(3);
  306. data.vaporFR = handler.getData(2);
  307. data.VLR = handler.getData(2);
  308. data.tmBegin = handler.getDataString_BCD(7);
  309. data.tmEnd = handler.getDataString_BCD(7);
  310. data.errornum = handler.getData(2);
  311. data.vaporPA = handler.getData(2);
  312. data.pwm = handler.getData(2);
  313. return data;
  314. }
  315. public static void vr_log(string log)
  316. {
  317. }
  318. public static void vr_log_error(string log)
  319. {
  320. }
  321. }
  322. public class BufferHandler
  323. {
  324. public byte[] buffer = Array.Empty<byte>();
  325. public int startIndex = 0;
  326. public int length = 0;
  327. public BufferHandler(byte[] buf, int startindex = 0)
  328. {
  329. buffer = buf;
  330. startIndex = startindex;
  331. length = buf.Length;
  332. }
  333. public string getDataString_BCD(int len)
  334. {
  335. if (startIndex + len > length)
  336. {
  337. return "";
  338. }
  339. byte[] segment = new byte[len];
  340. Array.Copy(buffer, startIndex, segment, 0, len);
  341. string result = GlobalTool.BytesToBcd(segment);
  342. startIndex += len;
  343. return result;
  344. }
  345. public int getData(int len)
  346. {
  347. if (startIndex + len > length)
  348. {
  349. return 0;
  350. }
  351. byte[] segment = new byte[len];
  352. Array.Copy(buffer, startIndex, segment, 0, len);
  353. int val = GlobalTool.BytesToInt(segment);
  354. startIndex += len;
  355. return val;
  356. }
  357. }
  358. public class NozzleState
  359. {
  360. public int noz = 0;
  361. public string VLR = "0";
  362. public string oil = string.Empty;
  363. public int nozzlestate = GlobalTool.NozzleState_Offline;
  364. public int warnstate = GlobalTool.WarningState_Normal;
  365. }
  366. public struct filling_nozzleup
  367. {
  368. public int fip;
  369. public int board;
  370. public int noz;
  371. public string time;
  372. /* byte cmd;
  373. byte fip;
  374. byte noz;
  375. byte time[7];
  376. byte product[4];*/
  377. /* auto& cmd = src->data.CMD1;
  378. dst.target = cmd.noz;
  379. _ubcd_to_str (dst.time, sizeof dst.time, cmd.time, sizeof cmd.time);
  380. _ubcd_to_str (dst.product, sizeof dst.product, cmd.product, sizeof cmd.product);*/
  381. }
  382. public struct filling_nozzledown
  383. {
  384. public int fip;
  385. public int board;
  386. public int noz;
  387. public string time;
  388. }
  389. public struct filling_record
  390. {
  391. public int fip;
  392. public int board;
  393. public int noz;
  394. public int liquidVL;
  395. public int vaporVL;
  396. public int liquidFR;
  397. public int vaporFR;
  398. public int VLR;
  399. public int vaporPA;
  400. public int ttc;
  401. public int VLR_BEFORE;
  402. public int VLR_OFFSET;
  403. public int pwm;
  404. public string tmBegin;
  405. public string tmEnd;
  406. public int overproof;
  407. public int uploadflag;
  408. public int uploadflag2;
  409. public int uploadflag3;
  410. public int downloadflag1;
  411. public int yz;
  412. public int tankpressure;
  413. public int refuelingseconds;
  414. public int errorcontrolvalue;
  415. public int errornum;
  416. public int callbackflag;
  417. public string vccerrorinfo;
  418. }
  419. public struct filling_process
  420. {
  421. public int fip;
  422. public int board;
  423. public int noz;
  424. public int liquidVL;
  425. public int vaporVL;
  426. public int liquidFR;
  427. public int vaporFR;
  428. public int VLR;
  429. public int vaporPA;
  430. public int ttc;
  431. public int VLR_BEFORE;
  432. public int VLR_OFFSET;
  433. public int errornum;
  434. public int pwm;
  435. public int current;
  436. }
  437. public class BufferData
  438. {
  439. public int type = 0;
  440. public byte[] buffer = Array.Empty<byte>();
  441. public System.Net.IPEndPoint endpoint;
  442. public UdpClient udpClient;
  443. public SerialPort serialPort;
  444. }
  445. }