GlobalTool.cs 15 KB

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