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
196 lines
9.1 KiB
|
|
using MySql.Data.MySqlClient;
|
|
using Quartz;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Data;
|
|
using System.Net;
|
|
using System.Net.Sockets;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
|
|
namespace POSCorePrint.Jobs
|
|
{
|
|
/// <summary>
|
|
/// edit by liuwz 2019-09-18 修改防止重复打印的方法
|
|
/// 打印任务
|
|
/// </summary>
|
|
[DisallowConcurrentExecution]
|
|
public class PrintJob : IJob
|
|
{
|
|
private readonly ManualResetEvent TimeoutObject = new ManualResetEvent(false);
|
|
private int Timeout = 2500;//连接打印机超时时间,毫秒。
|
|
private int TimeoutSend = 5000;//连接打印机超时时间,毫秒。
|
|
|
|
public Task Execute(IJobExecutionContext context)
|
|
{
|
|
//查询最近N分钟需要打印的数据,同时删除N天前的打印数据。
|
|
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
|
|
where task.status = 0 and print.isdelete=0 and task.CreateTime >'{DateTime.Now.AddMinutes(-Constant.PrintBackTime).ToString("yyyy-MM-dd HH:mm:ss")}';
|
|
delete from pos_store_printtask where CreateTime <'{DateTime.Now.AddDays(-Constant.SaveHisDataDays).ToString("yyyy-MM-dd HH:mm:ss")}';";
|
|
// TODO 查询数据库获取打印任务列表
|
|
DataTable dataTable;
|
|
try
|
|
{
|
|
dataTable = MySqlHelper.ExecuteDataset(Constant.ConnectionString, sql).Tables[0];
|
|
//无打印任务
|
|
if (dataTable.Rows.Count == 0)
|
|
return Task.CompletedTask;
|
|
//有打印任务,按打印机分组
|
|
var dicPrints = new Dictionary<string, List<Content>>();
|
|
foreach (DataRow row in dataTable.Rows)
|
|
{
|
|
var newContent = new Content() { ID = row["Id"].ToString(), ContentVal = row["Content"].ToString() };
|
|
if (!dicPrints.ContainsKey(row["PrintIP"].ToString()))
|
|
{
|
|
dicPrints.Add(
|
|
row["PrintIP"].ToString(),
|
|
new List<Content> { newContent }
|
|
);
|
|
}
|
|
else
|
|
dicPrints[row["PrintIP"].ToString()].Add(newContent);
|
|
}
|
|
//按打印机并行异步发送
|
|
Console.WriteLine($"{DateTime.Now.ToString()}:打印开始");
|
|
List<Task> taskList = new List<Task>();
|
|
foreach (KeyValuePair<string, List<Content>> p in dicPrints)
|
|
{
|
|
taskList.Add(Send(p));
|
|
}
|
|
//等所有异步打印完再返回
|
|
Task.WhenAll(taskList).Wait();
|
|
Console.WriteLine($"{DateTime.Now.ToString()}:打印结束");
|
|
return Task.CompletedTask;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"{DateTime.Now.ToString()}:获取打印任务失败", ex);
|
|
return Task.CompletedTask;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 异步发送打印任务
|
|
/// </summary>
|
|
/// <param name="p"></param>
|
|
private async Task Send(KeyValuePair<string, List<Content>> p)
|
|
{
|
|
string idSuccess = "";
|
|
string idFail = "";
|
|
await Task.Run(() =>
|
|
{
|
|
IPAddress iPAddress = IPAddress.Parse(p.Key);
|
|
IPEndPoint iPEndPoint = new IPEndPoint(iPAddress, Constant.port);
|
|
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
|
|
try
|
|
{
|
|
TimeoutObject.Reset();
|
|
socket.BeginConnect(iPEndPoint, CallBackMethod,socket);
|
|
//阻塞当前线程
|
|
if (!TimeoutObject.WaitOne(Timeout, false))
|
|
{
|
|
//处理连接不成功的动作
|
|
socket.Close();
|
|
Console.WriteLine($"{DateTime.Now.ToString()}: 打印失败:{p.Key}【连接超时】");
|
|
return;
|
|
}
|
|
if (!socket.Connected)
|
|
{
|
|
//处理连接不成功的动作
|
|
socket.Close();
|
|
Console.WriteLine($"{DateTime.Now.ToString()}: 打印失败:{p.Key} socket【连接超时】");
|
|
return;
|
|
}
|
|
foreach (Content content in p.Value)
|
|
{
|
|
////判断打印机状态:是否在线,是否有纸
|
|
//byte[] dataSatus = new byte[3];
|
|
//for (int i = 0; i < dataSatus.Length; i++)
|
|
//{
|
|
// dataSatus[i] = byte.Parse(content.ContentVal.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber);
|
|
//}
|
|
//int iRes = socket.Send(dataSatus, 0);
|
|
|
|
//打印内容
|
|
byte[] data = new byte[content.ContentVal.Length / 2];
|
|
try
|
|
{
|
|
for (int i = 0; i < data.Length; i++)
|
|
{
|
|
data[i] = byte.Parse(content.ContentVal.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"{DateTime.Now.ToString()}:转换打印数据失败 {ex.Message}", ex);
|
|
}
|
|
|
|
try
|
|
{
|
|
//byte[] mData = new byte[data.Length];
|
|
//Array.Copy(data, 0, mData, 0, data.Length);
|
|
SocketError errorCode;
|
|
//edit by liuwz 2020-04-03 增加超时
|
|
socket.SendTimeout= TimeoutSend;
|
|
|
|
int iResult = socket.Send(data, 0, out errorCode);
|
|
//add by liuwz 2020-01-13增加打印发送长度判断。
|
|
if (SocketError.Success != errorCode || iResult !=data.Length)
|
|
{
|
|
//add by liuwz 2019-11-29失败时增加打印次数。
|
|
idFail += string.IsNullOrEmpty(idFail) ? $"'{content.ID}'" : $",'{content.ID}'";
|
|
Console.WriteLine($"{DateTime.Now.ToString()}: ip:{p.Key},id:{content.ID} 打印返回失败:【{errorCode.ToString()}】");
|
|
}
|
|
else
|
|
idSuccess += string.IsNullOrEmpty(idSuccess) ? $"'{content.ID}'" : $",'{content.ID}'";
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
//add by liuwz 2019-11-29失败时增加打印次数。
|
|
idFail += string.IsNullOrEmpty(idFail) ? $"'{content.ID}'" : $",'{content.ID}'";
|
|
Console.WriteLine($"{DateTime.Now.ToString()}: ip:{p.Key},id:{content.ID} 发送打印命令失败:【{ex.Message}】", ex);
|
|
}
|
|
}
|
|
|
|
// 操作数据库更新状态
|
|
if (!string.IsNullOrEmpty(idSuccess))
|
|
{
|
|
var sql = $"update pos_store_printtask set status=1,PrintTime=NOW(),PrintTimes=ifnull(PrintTimes,0)+1 where Id in({idSuccess});";
|
|
Console.WriteLine($"{DateTime.Now.ToString()}:打印成功更新记录:{iPAddress};{idSuccess}");
|
|
|
|
MySqlHelper.ExecuteNonQueryAsync(Constant.ConnectionString, sql);
|
|
}
|
|
if (!string.IsNullOrEmpty(idFail))
|
|
{
|
|
Console.WriteLine($"{DateTime.Now.ToString()}:打失败更新记录:{iPAddress};{idFail}");
|
|
var sql = $"update pos_store_printtask set PrintTimes=ifnull(PrintTimes,0)+1 where Id in({idFail});";
|
|
MySqlHelper.ExecuteNonQueryAsync(Constant.ConnectionString, sql);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine($"{DateTime.Now.ToString()}: 打印失败:{p.Key}【{ex.Message}】{string.Join('|',p.Value.Select(m=>new {m.ID}))}", ex);
|
|
}
|
|
finally
|
|
{
|
|
socket.Close();
|
|
}
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// 异步回调方法
|
|
/// </summary>
|
|
/// <param name="asyncresult"></param>
|
|
private void CallBackMethod(IAsyncResult asyncresult)
|
|
{
|
|
//使阻塞的线程继续
|
|
TimeoutObject.Set();
|
|
}
|
|
|
|
}
|
|
}
|