|
using Newtonsoft.Json.Linq;
|
using Sodao.FastSocket.Server.Messaging;
|
using System;
|
using System.Collections.Concurrent;
|
using System.Collections.Generic;
|
using System.Linq;
|
using System.Text;
|
using System.Threading;
|
using System.Threading.Tasks;
|
using BiosenSocketService.Exceptions;
|
using XImaging.Automation.Library.HxDriverLib;
|
using XImaging.Automation.Service;
|
using XImaging.Automation.Service.Instruction;
|
using Sodao.FastSocket.SocketBase.Utils;
|
using System.Xml.Linq;
|
|
namespace XImaging.Automation.Service.Instruction
|
{
|
public delegate void TroubleShootDelegate();
|
public delegate void OnTaskFinishDelegate(TaskInstruction tIns, JObject data, int status);
|
public delegate void OnTaskAbortDelegate(TaskInstruction tIns, string errCode, string errString);
|
public delegate void QueryDataDelegate(JObject data);
|
/*
|
* HxTroubleShoot
|
* 记录并处理任务指令中途错误的类
|
*/
|
public class HxTroubleShoot
|
{
|
public const int TS_Ignore = 1; // 错误处理方式:忽略
|
public const int TS_Retry = 2; // 错误处理方式:重试
|
public const int TS_Abort = 4; // 错误处理方式:中断
|
|
private string str_errCode; // 错误码
|
private int p_Troubleshoot=7; // 可能的错误处理方式,0-7
|
private string str_Message; // 错误信息
|
private int nDealwithtype = 0;
|
|
public event TroubleShootDelegate IgnoreTrigger; // Ignore事件
|
public event TroubleShootDelegate RetryTrigger; // Retry事件
|
public event TroubleShootDelegate AbortTrigger; // Abort事件
|
|
private bool b_onWaiting = false;
|
private int r_Troubleshoot = -1; // 用户反馈的错误处理方式
|
|
/// <summary>
|
/// 记录新错误的信息
|
/// </summary>
|
/// <param name="errCode">错误码</param>
|
/// <param name="TroubleshootPossibility">可行的处理方式</param>
|
/// <param name="message">错误信息</param>
|
public void Error(HxMessage hxMessage, string errCode, int TroubleshootPossibility, string MsgText, int nDealwithtype)
|
{
|
//while (b_onWaiting)
|
//{
|
// Thread.Sleep(1000);
|
//}
|
this.str_errCode = errCode;
|
this.p_Troubleshoot = TroubleshootPossibility;
|
this.str_Message = MsgText;
|
this.nDealwithtype = nDealwithtype;
|
|
JObject err = JObject.FromObject(
|
new
|
{
|
error_code = str_errCode,
|
error_text = str_Message,
|
troubleshoot = p_Troubleshoot,
|
dealwithtype= nDealwithtype,
|
}
|
);
|
HxTcpHandler.ReplyErrorMessage(hxMessage, err , str_errCode, str_Message, nDealwithtype, p_Troubleshoot);
|
}
|
|
/// <summary>
|
/// 记录新错误的信息
|
/// </summary>
|
/// <param name="errCode">错误码</param>
|
/// <param name="TroubleshootPossibility">可行的处理方式</param>
|
/// <param name="message">错误信息</param>
|
public void Abort(HxMessage hxMessage, string errCode, int TroubleshootPossibility, string MsgText, int nDealwithtype)
|
{
|
while (b_onWaiting)
|
{
|
Thread.Sleep(1000);
|
}
|
this.str_errCode = errCode;
|
this.p_Troubleshoot = TroubleshootPossibility;
|
this.str_Message = MsgText;
|
this.nDealwithtype = nDealwithtype;
|
HxTcpHandler.ReplyFailedMessage(hxMessage, hxMessage.OriginJSON, str_errCode, str_Message, nDealwithtype, p_Troubleshoot, nDealwithtype);
|
}
|
|
public bool MatchTSCode(int TS_Code)
|
{
|
return (p_Troubleshoot & TS_Code) > 0;
|
}
|
|
/// <summary>
|
/// 阻塞等待用户反馈
|
/// </summary>
|
public void Wait()
|
{
|
b_onWaiting = true;
|
while (r_Troubleshoot < 0)
|
{
|
Thread.Sleep(500);
|
}
|
b_onWaiting = false;
|
}
|
|
/// <summary>
|
/// 异步等待用户反馈
|
/// </summary>
|
public async void WaitAsync()
|
{
|
b_onWaiting = true;
|
await Task.Run(() =>
|
{
|
while (r_Troubleshoot < 0)
|
{
|
Thread.Sleep(500);
|
}
|
});
|
b_onWaiting = false;
|
}
|
|
/// <summary>
|
/// 同步处理用户反馈
|
/// </summary>
|
/// <param name="TroubleshootReply"></param>
|
public void Reply(int TroubleshootReply)
|
{
|
r_Troubleshoot = TroubleshootReply;
|
if (TroubleshootReply == TS_Ignore)
|
IgnoreTrigger.Invoke();
|
else if (TroubleshootReply == TS_Retry)
|
RetryTrigger.Invoke();
|
else if (TroubleshootReply == TS_Abort)
|
AbortTrigger.Invoke();
|
}
|
|
/// <summary>
|
/// 异步处理用户反馈
|
/// </summary>
|
/// <param name="TroubleshootReply"></param>
|
public async void ReplyAsync(int TroubleshootReply)
|
{
|
r_Troubleshoot = TroubleshootReply;
|
if (TroubleshootReply == TS_Ignore)
|
await Task.Run(() => { IgnoreTrigger.Invoke(); });
|
else if (TroubleshootReply == TS_Retry)
|
await Task.Run(() => { RetryTrigger.Invoke(); });
|
else if (TroubleshootReply == TS_Abort)
|
await Task.Run(() => { AbortTrigger.Invoke(); });
|
}
|
|
~HxTroubleShoot()
|
{
|
Delegate[] dels;
|
if (IgnoreTrigger != null)
|
{
|
dels = IgnoreTrigger.GetInvocationList();
|
foreach (Delegate del in dels)
|
{
|
object delObj = del.GetType().GetProperty("Method").GetValue(del, null);
|
string funcName = (string)delObj.GetType().GetProperty("Name").GetValue(delObj, null);
|
Console.WriteLine(funcName);
|
IgnoreTrigger -= del as TroubleShootDelegate;
|
}
|
}
|
|
if (RetryTrigger != null)
|
{
|
dels = RetryTrigger.GetInvocationList();
|
foreach (Delegate del in dels)
|
{
|
object delObj = del.GetType().GetProperty("Method").GetValue(del, null);
|
string funcName = (string)delObj.GetType().GetProperty("Name").GetValue(delObj, null);
|
Console.WriteLine(funcName);
|
RetryTrigger -= del as TroubleShootDelegate;
|
}
|
}
|
|
if (AbortTrigger != null)
|
{
|
dels = AbortTrigger.GetInvocationList();
|
foreach (Delegate del in dels)
|
{
|
object delObj = del.GetType().GetProperty("Method").GetValue(del, null);
|
string funcName = (string)delObj.GetType().GetProperty("Name").GetValue(delObj, null);
|
Console.WriteLine(funcName);
|
AbortTrigger -= del as TroubleShootDelegate;
|
}
|
}
|
}
|
}
|
|
interface IInstruction
|
{
|
}
|
|
public class HxInstruction: IInstruction
|
{
|
public const int INSTYPE_HeartBeat = 0; // 类型:心跳包
|
public const int INSTYPE_Task = 1; // 类型:任务,指有较长执行时间的指令
|
public const int INSTYPE_Query = 2; // 类型:查询,指即时返回的指令
|
public const int INSTYPE_Troubleshoot = 3; // 类型:错误处理,指客户端返回的问题处理指令
|
|
public const int TASKSTAT_Scheduled = 0; // 状态:准备执行
|
public const int TASKSTAT_InProgress = 1; // 状态:正在执行
|
public const int TASKSTAT_Completed = 2; // 状态:执行完成
|
public const int TASKSTAT_Failed = 3; // 状态:执行失败
|
public const int TASKSTAT_Canceled = 4; // 状态:任务取消
|
|
protected HxMessage m_Message; // 接收到的Socket信息包
|
protected int n_TaskStatus; // 任务状态
|
|
public HxInstruction(HxMessage message)
|
{
|
m_Message = message;
|
n_TaskStatus = -1; // HxInstruction.TASKSTAT_Scheduled;
|
}
|
|
public string InsId { get { return m_Message.MessageID; } } // 指令ID,唯一
|
public string InsName { get { return m_Message.Method; } } // 指令名
|
public int Type { get { return m_Message.MessageType; } } // 指令类型
|
public int Status { get { return n_TaskStatus; } } // 指令执行状态
|
|
public HxMessage Message { get { return m_Message; } }
|
}
|
|
/*
|
* 心跳包指令
|
*/
|
public class HeartBeatInstruction : HxInstruction
|
{
|
public HeartBeatInstruction(HxMessage message) : base(message) { }
|
}
|
|
/*
|
* 任务指令
|
*/
|
public class TaskInstruction : HxInstruction
|
{
|
HxInsParser command = null;
|
public HxTroubleShoot ErrorHandler;
|
|
public TaskInstruction(HxMessage message)
|
: base(message)
|
{
|
ErrorHandler = new HxTroubleShoot();
|
}
|
|
public TaskInstruction(HxMessage message, HxInsParser cmd)
|
: base(message)
|
{
|
ErrorHandler = new HxTroubleShoot();
|
command = cmd;
|
}
|
|
public void OnTaskError(Object objMsg, string errCode, int TroubleshootPossibility, string message, int dealwithtype)
|
{
|
LogConstant.logger.Print($"OnTaskError: {message}");
|
JObject jObj = objMsg as JObject;
|
string id = jObj["message_id"].ToString();
|
if (Message.MessageID == id)
|
ErrorHandler.Error(this.Message, errCode, TroubleshootPossibility, message, dealwithtype);
|
//ErrorHandler.WaitAsync();
|
}
|
public void OnTaskAbort(Object objMsg, string errCode, int TroubleshootPossibility, string message, int dealwithtype)
|
{
|
ErrorHandler.Abort(this.Message, errCode, TroubleshootPossibility, message, dealwithtype);
|
//ErrorHandler.WaitAsync();
|
}
|
|
public void OnFinishTest(Dictionary<string,int> result)
|
{
|
JObject data = new JObject();// StartExperimentInsArgs.ReturnDataWrapper(result);
|
HxTcpHandler.ReplyFinishMessage(this.Message, data);
|
}
|
|
// 指令已收到,执行状态转为Scheduled
|
public void Standby()
|
{
|
n_TaskStatus = TASKSTAT_Scheduled;
|
}
|
|
// 指令下发设备,开始正式执行
|
public void Execute()
|
{
|
n_TaskStatus = TASKSTAT_InProgress;
|
}
|
|
// 指令已经执行完毕,并正常结束
|
public void Finish()
|
{
|
n_TaskStatus = TASKSTAT_Completed;
|
}
|
|
// 指令已经执行但被迫中断或执行失败
|
public void Abort()
|
{
|
n_TaskStatus = TASKSTAT_Failed;
|
}
|
}
|
|
/*
|
* 查询指令
|
*/
|
public class QueryInstruction : HxInstruction
|
{
|
HxInsParser command = null;
|
public QueryDataDelegate OnDataReturned;
|
|
public QueryInstruction(HxMessage message)
|
: base(message){}
|
|
public QueryInstruction(HxMessage message, HxInsParser cmd)
|
: base(message)
|
{
|
command = cmd;
|
}
|
}
|
|
/*
|
* 错误处理指令
|
*/
|
public class TroubleshootInstruction : HxInstruction
|
{
|
public TroubleshootInstruction(HxMessage message) : base(message) { }
|
|
public int TSCode
|
{
|
get
|
{
|
return m_Message.Troubleshoot;
|
}
|
}
|
}
|
|
public class InstructionManager
|
{
|
TaskInstruction t_Instrction = null; // 任务指令
|
//ConcurrentQueue<QueryInstruction> q_Instructions; // 查询指令队列
|
readonly static object qryLock = new object(); // 查询指令队列锁
|
|
System.Threading.Timer qTimer;
|
private InsProtocol insProtocol;
|
|
/// <summary>
|
/// 监控查询指令队列
|
/// </summary>
|
/// <param name="state">占位参数</param>
|
/*protected void QueueObserver(object state)
|
{
|
QueryInstruction qIns = null;
|
bool deqFlag = false;
|
lock (qryLock)
|
{
|
// 当查询队列中有指令未处理时取出
|
if (q_Instructions.Count > 0)
|
deqFlag = q_Instructions.TryDequeue(out qIns);
|
else
|
return;
|
}
|
|
try
|
{
|
if (deqFlag && qIns != null)
|
{
|
// 执行查询指令
|
JObject data = insProtocol.Query(qIns);
|
if (data == null)
|
data = new JObject();
|
HxTcpHandler.ReplyFinishMessage(qIns.Message,data);
|
}
|
}
|
catch (Exception ex)
|
{
|
HxTcpHandler.ReplyFailedMessage(qIns.Message, new JObject(), "ERROR", qIns.InsName+" error", 4);
|
}
|
}*/
|
|
public InstructionManager()
|
{
|
//q_Instructions = new ConcurrentQueue<QueryInstruction>();
|
insProtocol = new InsProtocol();
|
|
// 启动定时器,每100ms查看一次查询队列中是否有新的查询任务
|
//qTimer = new System.Threading.Timer(QueueObserver, null, 0, 100);
|
}
|
|
public void OnConnect(bool isConnect)
|
{
|
insProtocol.OnConnect(isConnect);
|
}
|
/// <summary>
|
/// 当任务指令完成时调用该函数反馈给客户端
|
/// </summary>
|
/// <param name="data">任务产生的数据</param>
|
/// <param name="status">任务完成时的状态</param>
|
public void OnTaskFinish(TaskInstruction tIns, JObject data, int status)
|
{
|
if (tIns != null)
|
{
|
if (status == HxMessage.METHOD_STATUS_COMPLETED)
|
{
|
tIns.Finish();
|
// 返回任务结束信息
|
HxTcpHandler.ReplyFinishMessage(
|
tIns.Message,
|
data);
|
}
|
else
|
{
|
tIns.Abort();
|
|
HxTcpHandler.ReplyFailedMessage(tIns.Message,data,"EC-00-000", "OnTaskFinish status=failed");
|
}
|
}
|
}
|
|
/// <summary>
|
/// 当任务指令完成时调用该函数反馈给客户端
|
/// </summary>
|
/// <param name="data">任务产生的数据</param>
|
/// <param name="status">任务完成时的状态</param>
|
public void OnTaskAbort(TaskInstruction tIns, string errCode, string errString)
|
{
|
if (tIns != null)
|
{
|
tIns.Abort();
|
|
HxTcpHandler.ReplyFailedMessage(tIns.Message, ResponseMessagePackage.NullData, "EC-00-000", errString);
|
}
|
}
|
|
/// <summary>
|
/// 设置当前设备的查任务指令
|
/// </summary>
|
/// <param name="tIns">任务指令</param>
|
/// <exception cref="TaskUncompletedException">上一个任务指令还未完成</exception>
|
public void Add(TaskInstruction tIns)
|
{
|
// 当前没有任务指令的时候
|
//if (t_Instrction == null)
|
//{
|
// t_Instrction = tIns;
|
//}
|
// 当前有任务指令的时候,需要判断该任务是否已完成
|
//else
|
{
|
|
string msg = string.Format("收到指令:{0},{1}", tIns.InsName, tIns.InsId);
|
LogConstant.logger.Print(msg);
|
//// 如果任务准备进行或正在进行中,则抛出任务冲突的错误
|
//if (t_Instrction.Status == TaskInstruction.TASKSTAT_Scheduled ||
|
// t_Instrction.Status == TaskInstruction.TASKSTAT_InProgress)
|
// throw new TaskUncompletedException(
|
// string.Format("执行冲突:任务\"{0}:{1}\"正在运行中", t_Instrction.InsName, t_Instrction.InsId));
|
|
//// 如果设备处于TASKSTAT_Completed, TASKSTAT_Failed或TASKSTAT_Cancel状态,则重新将其设为准备态
|
//else
|
{
|
//t_Instrction = tIns;
|
//t_Instrction.Standby();
|
}
|
}
|
// 异步执行任务
|
insProtocol.AsyncTask(ref tIns, OnTaskFinish, OnTaskAbort);
|
}
|
|
/// <summary>
|
/// 设置当前设备的查询指令
|
/// </summary>
|
/// <param name="qIns">查询指令</param>
|
public void Add(QueryInstruction qIns)
|
{
|
lock (qryLock)
|
{
|
//q_Instructions.Enqueue(qIns);
|
}
|
}
|
|
/// <summary>
|
/// 设置当前设备的错误处理指令
|
/// </summary>
|
/// <param name="tsIns">错误处理指令</param>
|
/// <exception cref="TaskUncompletedException">上一个任务指令还未完成</exception>
|
public void Add(TroubleshootInstruction tsIns)
|
{
|
// 只有在当前任务存在,且当前任务正在执行过程中,且当前任务与错误处理的ID相同的情况下
|
if (t_Instrction == null)
|
{
|
LogConstant.logger.Print("没有前置错误可以处理");
|
return;
|
}
|
if (t_Instrction.Status != TaskInstruction.TASKSTAT_InProgress)
|
{
|
LogConstant.logger.Print(string.Format("任务状态不符合错误处理要求,当前状态为:{0}", t_Instrction.Status));
|
return;
|
}
|
if (!tsIns.InsId.Equals(t_Instrction.InsId))
|
{
|
LogConstant.logger.Print(string.Format("任务ID不一致,当前需要处理的任务ID为:{0}", t_Instrction.InsId));
|
return;
|
}
|
if (!t_Instrction.ErrorHandler.MatchTSCode(tsIns.TSCode))
|
{
|
LogConstant.logger.Print(string.Format("错误处理方式{0}不符合要求", tsIns.TSCode));
|
return;
|
}
|
|
LogConstant.logger.Print(string.Format("开始处理错误,TS Code={0}", tsIns.TSCode));
|
t_Instrction.ErrorHandler.ReplyAsync(tsIns.TSCode);
|
}
|
|
}
|
}
|