打印服务
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

196 lines
9.1 KiB

3 years ago
  1. 
  2. using MySql.Data.MySqlClient;
  3. using Quartz;
  4. using System;
  5. using System.Collections;
  6. using System.Collections.Generic;
  7. using System.Data;
  8. using System.Net;
  9. using System.Net.Sockets;
  10. using System.Text;
  11. using System.Threading.Tasks;
  12. using System.Linq;
  13. using System.Threading;
  14. namespace POSCorePrint.Jobs
  15. {
  16. /// <summary>
  17. /// edit by liuwz 2019-09-18 修改防止重复打印的方法
  18. /// 打印任务
  19. /// </summary>
  20. [DisallowConcurrentExecution]
  21. public class PrintJob : IJob
  22. {
  23. private readonly ManualResetEvent TimeoutObject = new ManualResetEvent(false);
  24. private int Timeout = 1500;//连接打印机超时时间,毫秒。
  25. private int TimeoutSend = 5000;//连接打印机超时时间,毫秒。
  26. public Task Execute(IJobExecutionContext context)
  27. {
  28. //查询最近N分钟需要打印的数据,同时删除N天前的打印数据。
  29. string sql = $@"select task.Id,task.content,print.PrintIP from pos_store_printtask task inner join pos_store_print print on task.code=print.Id
  30. where task.status = 0 and print.isdelete=0 and task.CreateTime >'{DateTime.Now.AddMinutes(-Constant.PrintBackTime).ToString("yyyy-MM-dd HH:mm:ss")}';
  31. delete from pos_store_printtask where CreateTime <'{DateTime.Now.AddDays(-Constant.SaveHisDataDays).ToString("yyyy-MM-dd HH:mm:ss")}';";
  32. // TODO 查询数据库获取打印任务列表
  33. DataTable dataTable;
  34. try
  35. {
  36. dataTable = MySqlHelper.ExecuteDataset(Constant.ConnectionString, sql).Tables[0];
  37. //无打印任务
  38. if (dataTable.Rows.Count == 0)
  39. return Task.CompletedTask;
  40. //有打印任务,按打印机分组
  41. var dicPrints = new Dictionary<string, List<Content>>();
  42. foreach (DataRow row in dataTable.Rows)
  43. {
  44. var newContent = new Content() { ID = row["Id"].ToString(), ContentVal = row["Content"].ToString() };
  45. if (!dicPrints.ContainsKey(row["PrintIP"].ToString()))
  46. {
  47. dicPrints.Add(
  48. row["PrintIP"].ToString(),
  49. new List<Content> { newContent }
  50. );
  51. }
  52. else
  53. dicPrints[row["PrintIP"].ToString()].Add(newContent);
  54. }
  55. //按打印机并行异步发送
  56. Console.WriteLine($"{DateTime.Now.ToString()}:打印开始");
  57. List<Task> taskList = new List<Task>();
  58. foreach (KeyValuePair<string, List<Content>> p in dicPrints)
  59. {
  60. taskList.Add(Send(p));
  61. }
  62. //等所有异步打印完再返回
  63. Task.WhenAll(taskList).Wait();
  64. Console.WriteLine($"{DateTime.Now.ToString()}:打印结束");
  65. return Task.CompletedTask;
  66. }
  67. catch (Exception ex)
  68. {
  69. Console.WriteLine($"{DateTime.Now.ToString()}:获取打印任务失败", ex);
  70. return Task.CompletedTask;
  71. }
  72. }
  73. /// <summary>
  74. /// 异步发送打印任务
  75. /// </summary>
  76. /// <param name="p"></param>
  77. private async Task Send(KeyValuePair<string, List<Content>> p)
  78. {
  79. string idSuccess = "";
  80. string idFail = "";
  81. await Task.Run(() =>
  82. {
  83. IPAddress iPAddress = IPAddress.Parse(p.Key);
  84. IPEndPoint iPEndPoint = new IPEndPoint(iPAddress, Constant.port);
  85. Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  86. try
  87. {
  88. TimeoutObject.Reset();
  89. socket.BeginConnect(iPEndPoint, CallBackMethod,socket);
  90. //阻塞当前线程             
  91. if (!TimeoutObject.WaitOne(Timeout, false))
  92. {
  93. //处理连接不成功的动作
  94. socket.Close();
  95. Console.WriteLine($"{DateTime.Now.ToString()}: 打印失败:{p.Key}【连接超时】");
  96. return;
  97. }
  98. if (!socket.Connected)
  99. {
  100. //处理连接不成功的动作
  101. socket.Close();
  102. Console.WriteLine($"{DateTime.Now.ToString()}: 打印失败:{p.Key} socket【连接超时】");
  103. return;
  104. }
  105. { foreach (Content content in p.Value)
  106. {
  107. ////判断打印机状态:是否在线,是否有纸
  108. //byte[] dataSatus = new byte[3];
  109. //for (int i = 0; i < dataSatus.Length; i++)
  110. //{
  111. // dataSatus[i] = byte.Parse(content.ContentVal.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber);
  112. //}
  113. //int iRes = socket.Send(dataSatus, 0);
  114. //打印内容
  115. byte[] data = new byte[content.ContentVal.Length / 2];
  116. try
  117. {
  118. for (int i = 0; i < data.Length; i++)
  119. {
  120. data[i] = byte.Parse(content.ContentVal.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber);
  121. }
  122. }
  123. catch (Exception ex)
  124. {
  125. Console.WriteLine($"{DateTime.Now.ToString()}:转换打印数据失败 {ex.Message}", ex);
  126. }
  127. try
  128. {
  129. //byte[] mData = new byte[data.Length];
  130. //Array.Copy(data, 0, mData, 0, data.Length);
  131. SocketError errorCode;
  132. //edit by liuwz 2020-04-03 增加超时
  133. socket.SendTimeout= TimeoutSend;
  134. int iResult = socket.Send(data, 0, out errorCode);
  135. //add by liuwz 2020-01-13增加打印发送长度判断。
  136. if (SocketError.Success != errorCode || iResult !=data.Length)
  137. {
  138. //add by liuwz 2019-11-29失败时增加打印次数。
  139. idFail += string.IsNullOrEmpty(idFail) ? $"'{content.ID}'" : $",'{content.ID}'";
  140. Console.WriteLine($"{DateTime.Now.ToString()}: ip:{p.Key},id:{content.ID} 打印返回失败:【{errorCode.ToString()}】");
  141. }
  142. else
  143. idSuccess += string.IsNullOrEmpty(idSuccess) ? $"'{content.ID}'" : $",'{content.ID}'";
  144. }
  145. catch (Exception ex)
  146. {
  147. //add by liuwz 2019-11-29失败时增加打印次数。
  148. idFail += string.IsNullOrEmpty(idFail) ? $"'{content.ID}'" : $",'{content.ID}'";
  149. Console.WriteLine($"{DateTime.Now.ToString()}: ip:{p.Key},id:{content.ID} 发送打印命令失败:【{ex.Message}】", ex);
  150. }
  151. }
  152. // 操作数据库更新状态
  153. if (!string.IsNullOrEmpty(idSuccess))
  154. {
  155. var sql = $"update pos_store_printtask set status=1,PrintTime=NOW(),PrintTimes=ifnull(PrintTimes,0)+1 where Id in({idSuccess});";
  156. Console.WriteLine($"{DateTime.Now.ToString()}:打印成功更新记录:{iPAddress};{idSuccess}");
  157. MySqlHelper.ExecuteNonQueryAsync(Constant.ConnectionString, sql);
  158. }
  159. if (!string.IsNullOrEmpty(idFail))
  160. {
  161. Console.WriteLine($"{DateTime.Now.ToString()}:打失败更新记录:{iPAddress};{idFail}");
  162. var sql = $"update pos_store_printtask set PrintTimes=ifnull(PrintTimes,0)+1 where Id in({idFail});";
  163. MySqlHelper.ExecuteNonQueryAsync(Constant.ConnectionString, sql);
  164. }
  165. }
  166. catch (Exception ex)
  167. {
  168. Console.WriteLine($"{DateTime.Now.ToString()}: 打印失败:{p.Key}【{ex.Message}】{string.Join('|',p.Value.Select(m=>new {m.ID}))}", ex);
  169. }
  170. finally
  171. {
  172. socket.Close();
  173. }
  174. });
  175. }
  176. /// <summary>
  177. /// 异步回调方法 
  178. /// </summary>
  179. /// <param name="asyncresult"></param>
  180. private void CallBackMethod(IAsyncResult asyncresult)
  181. {
  182. //使阻塞的线程继续          
  183. TimeoutObject.Set();
  184. }
  185. }
  186. }