using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Text; namespace Sodao.FastSocket.Server.Messaging { /// /// /// public sealed class HxMessage : Messaging.IMessage, XImaging.Automation.Library.HxDriverLib.Messaging.IMessage { static private readonly string ENDOP = "#!HxSEP!#"; #region 消息类型定义 /// /// 消息类型-1: 网关心跳包 /// public static int MESSAGE_TYPE_HEARTBEAT_GW { get; } = -1; /// /// 消息类型0: 心跳包 /// public static int MESSAGE_TYPE_HEARTBEAT { get; } = 0; /// /// 消息类型1:方法消息(延迟返回消息) /// public static int MESSAGE_TYPE_TASK { get; } = 1; /// /// 消息类型2:查询方法消息(即时返回消息) /// public static int MESSAGE_TYPE_QUERY { get; } = 2; /// /// 消息类型3:错误处理消息(无返回消息) /// public static int MESSAGE_TYPE_TROUBLESHOOT { get; } = 3; /// /// 消息类型4:确认消息 /// public static int MESSAGE_TYPE_ACK { get; } = 4; /// /// 消息类型5:完成消息 /// public static int MESSAGE_TYPE_FINISH { get; } = 5; /// /// 消息类型6:错误消息(可被代替,兼容v1.6版本) /// public static int MESSAGE_TYPE_ERROR { get; } = 6; #endregion #region 方法状态定义 /// /// 方法状态0:准备执行(指令队列中) /// public static int METHOD_STATUS_SCHEDULED { get; } = 0; /// /// 方法状态1:正在执行 /// public static int METHOD_STATUS_INPROGRES { get; } = 1; /// /// 方法状态2:执行完成且成功 /// public static int METHOD_STATUS_COMPLETED { get; } = 2; /// /// 方法状态3:执行完成且失败 /// public static int METHOD_STATUS_FAILED { get; } = 3; /// /// 方法状态4:该方法在指令队列中被取消 /// public static int METHOD_STATUS_CANCELED { get; } = 4; /// /// 方法状态4:该方法在指令队列中被取消 /// public static int METHOD_STATUS_ERROR { get; } = 5; #endregion #region 私有成员 private JObject m_jsonOriginMessage; private string m_strMessageID; private int m_iMessageType; private string m_strMethod; private string m_strEquipmentID; private int m_iEquipmentStatus; private int m_iActualDeviceStatus; private string m_strWorkflowID; private string m_strExperimentID; private JObject m_jsonParameters; private int m_iTroubleshoot; private string m_strDescription; private JObject m_jsonProcessInfo; private int m_iEstimateTime; private int m_iConnected; private int m_iTimeout; private string m_strTimestamp; /// /// 原始消息 /// public JObject OriginJSON { get { return m_jsonOriginMessage; } } #endregion /// /// 消息ID,唯一 /// public string MessageID { get { return m_strMessageID; } } /// /// 消息类型,见定义 /// public int MessageType { get { return m_iMessageType; } } /// /// 方法名称 /// public string Method { get { return m_strMethod; } } /// /// 设备ID /// public string EquipmentID { get { return m_strEquipmentID; } } /// /// 设备状态 /// public int EquipmentStatus { set { this.m_iEquipmentStatus = value; } get { return m_iEquipmentStatus; } } /// /// 设备状态 /// public int ActualDeviceStatus { set { this.m_iActualDeviceStatus = value; } get { return m_iActualDeviceStatus; } } /// /// 工作流ID /// public string WorkflowID { set { this.m_strWorkflowID = value; } get { return m_strWorkflowID; } } /// /// 实验ID /// public string ExperimentID { get { return m_strExperimentID; } } /// /// 方法需要的参数 /// public JObject Parameters { get { return m_jsonParameters; } } /// /// /// public int Troubleshoot { get { return m_iTroubleshoot; } } /// /// 方法描述文字 /// public string Description { get { return m_strDescription; } } /// /// 任务信息,可以不需要 /// public JObject ProcessInfo { get { return m_jsonProcessInfo; } } /// /// 预估时间,可以不需要 /// public int EstimateTime { get { return m_iEstimateTime; } } /// /// 超时时间,可以不需要 /// public int Timeout { get { return m_iTimeout; } } /// /// 消息生成时间 /// public string Timestamp { get { return m_strTimestamp; } } /// /// 消息生成时间 /// public int Connected { set { this.m_iConnected = value; } get { return m_iConnected; } } /// /// 构造类1 /// /// public HxMessage(string message) { JObject obj = (JObject)JsonConvert.DeserializeObject(message); this.m_jsonOriginMessage = obj; this.m_strMessageID = obj["message_id"].ToString(); this.m_iMessageType = obj.Value("message_type"); this.m_strEquipmentID = obj["equipment_id"].ToString(); if (this.MessageType == MESSAGE_TYPE_HEARTBEAT) { this.m_iEquipmentStatus = obj.Value("equipment_status"); this.m_iActualDeviceStatus = obj.Value("actual_device_status"); this.m_strWorkflowID = obj.Value("workflow_id"); if (obj.ContainsKey("connected")) this.m_iConnected = obj.Value("connected"); else this.m_iConnected = 0; } if (this.MessageType != MESSAGE_TYPE_HEARTBEAT && this.MessageType != MESSAGE_TYPE_HEARTBEAT_GW) { this.m_strWorkflowID = obj["workflow_id"].ToString(); if (obj.ContainsKey("experiment_id")) this.m_strExperimentID = obj["experiment_id"].ToString(); else { this.m_strExperimentID = "Unknown"; this.m_jsonOriginMessage.Add("experiment_id", this.m_strExperimentID); } this.m_strMethod = obj["method"].ToString(); if (obj.ContainsKey("description")) this.m_strDescription = obj["description"].ToString(); else this.m_strDescription = ""; } if (this.MessageType == MESSAGE_TYPE_TASK || this.MessageType == MESSAGE_TYPE_QUERY) { this.m_jsonParameters = (JObject)obj["parameters"]; if (obj.ContainsKey("process_info")) this.m_jsonProcessInfo = (JObject)obj["process_info"]; else this.m_jsonProcessInfo = JObject.FromObject(new { processId = "", instanceId = "", taskId = "" }); if (obj.ContainsKey("estimate_time")) this.m_iEstimateTime = obj.Value("estimate_time"); else this.m_iEstimateTime = 5000; if (obj.ContainsKey("timeout")) this.m_iTimeout = obj.Value("timeout"); else this.m_iTimeout = this.m_iEstimateTime * 2; } else { this.m_jsonParameters = null; this.m_jsonProcessInfo = null; } if (this.MessageType == MESSAGE_TYPE_TROUBLESHOOT) this.m_iTroubleshoot = obj.Value("troubleshoot"); else this.m_iTroubleshoot = 0; this.m_strTimestamp = obj["timestamp"].ToString(); } public void Heartbeat(SocketBase.IConnection connection) { if (connection == null) throw new ArgumentNullException("connection"); connection.BeginSend(ToHeartbeatPacket( this.MessageID, MESSAGE_TYPE_HEARTBEAT, this.EquipmentID, this.EquipmentStatus, this.ActualDeviceStatus, this.WorkflowID, this.Connected)); } public void HeartbeatGW(SocketBase.IConnection connection) { if (connection == null) throw new ArgumentNullException("connection"); connection.BeginSend(ToHeartbeatPacket( this.MessageID, MESSAGE_TYPE_HEARTBEAT_GW, this.EquipmentID, this.EquipmentStatus, this.ActualDeviceStatus, this.WorkflowID, this.Connected)); } #region Public Methods /// /// /// /// public void Ack(SocketBase.IConnection connection) { if (connection == null) throw new ArgumentNullException("connection"); connection.BeginSend(ToAckPacket( this.MessageID, MESSAGE_TYPE_ACK, this.Method, this.EquipmentID, this.WorkflowID, this.ExperimentID, this.m_jsonProcessInfo)); } public void Error(SocketBase.IConnection connection, JObject data, string error_code, string error_text, int dealwithtype, int troubleshoot) { if (connection == null) throw new ArgumentNullException("connection"); connection.BeginSend(ToErrorPacket( this.MessageID, MESSAGE_TYPE_TROUBLESHOOT, this.Method, this.EquipmentID, this.WorkflowID, this.ExperimentID, data, this.m_jsonProcessInfo, METHOD_STATUS_ERROR, error_code, error_text, dealwithtype, troubleshoot)); } /// /// /// /// /// public void Finish(SocketBase.IConnection connection, JObject data) { if (connection == null) throw new ArgumentNullException("connection"); connection.BeginSend(ToFinishPacket( this.MessageID, MESSAGE_TYPE_FINISH, this.Method, this.EquipmentID, this.WorkflowID, this.ExperimentID, data, this.m_jsonProcessInfo, METHOD_STATUS_COMPLETED, "", "", 0, 0 )); } /// /// /// /// /// /// /// /// public void Failed(SocketBase.IConnection connection, JObject data, string error_code, string error_text, int dealwithtype, int troubleshoot) { if (connection == null) throw new ArgumentNullException("connection"); connection.BeginSend(ToFinishPacket( this.MessageID, MESSAGE_TYPE_FINISH, this.Method, this.EquipmentID, this.WorkflowID, this.ExperimentID, data, this.m_jsonProcessInfo, METHOD_STATUS_FAILED, error_code, error_text, dealwithtype, troubleshoot )); } static public SocketBase.Packet ToHeartbeatPacket( string p_MessageID, int p_MessageType, string p_EquipmentID, int p_EquipmentStatus, int p_ActualDeviceStatus, string p_WorkflowId, int p_Connected) { JObject obj = JObject.FromObject( new { message_id = p_MessageID, message_type = p_MessageType, equipment_id = p_EquipmentID, equipment_status = p_EquipmentStatus, actual_device_status = p_ActualDeviceStatus, workflow_id = p_WorkflowId, connected = p_Connected, timestamp = DateTime.Now } ); string trims = obj.ToString().Replace("\r\n", ""); return new SocketBase.Packet(Encoding.UTF8.GetBytes(string.Concat(trims, ENDOP))); } /// /// /// /// /// /// /// /// /// static public SocketBase.Packet ToAckPacket( string p_MessageID, int p_MessageType, string p_Method, string p_EquipmentID, string p_WorkflowID, string p_ExperimentID, JObject p_ProcessInfo) { JObject obj = JObject.FromObject( new { message_id = p_MessageID, message_type = p_MessageType, method = p_Method, equipment_id = p_EquipmentID, workflow_id = p_WorkflowID, experiment_id = p_ExperimentID, process_info = p_ProcessInfo, timestamp = DateTime.Now } ); string trims = obj.ToString().Replace("\r\n", ""); return new SocketBase.Packet(Encoding.UTF8.GetBytes(string.Concat(trims, ENDOP))); } /// /// /// /// /// /// /// /// /// /// /// /// /// /// static public SocketBase.Packet ToFinishPacket( string p_MessageID, int p_MessageType, string p_Method, string p_EquipmentID, string p_WorkflowID, string p_ExperimentID, JObject p_data, JObject p_ProcessInfo, int p_MethodStatus, string p_ErrorCode, string p_ErrorText, int p_Troubleshoot, int p_Dealwithtype) { JObject obj = JObject.FromObject( new { message_id = p_MessageID, message_type = p_MessageType, method = p_Method, equipment_id = p_EquipmentID, workflow_id = p_WorkflowID, experiment_id = p_ExperimentID, data = p_data, process_info = p_ProcessInfo, method_status = p_MethodStatus, error = new { error_code = p_ErrorCode,//by N error_text = p_ErrorText, troubleshoot = p_Troubleshoot, dealwithtype= p_Dealwithtype }, troubleshoot= p_Troubleshoot, //by N errorSource= 0,//by N timestamp = DateTime.Now } ); string trims = obj.ToString().Replace("\r\n", ""); return new SocketBase.Packet(Encoding.UTF8.GetBytes(string.Concat(trims, ENDOP))); } /// /// /// /// /// /// /// /// /// /// /// /// /// /// static public SocketBase.Packet ToErrorPacket( string p_MessageID, int p_MessageType, string p_Method, string p_EquipmentID, string p_WorkflowID, string p_ExperimentID, JObject p_data, JObject p_ProcessInfo, int p_MethodStatus, string p_ErrorCode, string p_ErrorText, int p_Dealwithtype, int p_Troubleshoot) { JObject obj = JObject.FromObject( new { message_id = p_MessageID, message_type = p_MessageType, method = p_Method, equipment_id = p_EquipmentID, workflow_id = p_WorkflowID, experiment_id = p_ExperimentID, data = p_data, process_info = p_ProcessInfo, method_status = p_MethodStatus, errorSource = 2, error = new { error_code = p_ErrorCode, error_text = p_ErrorText, troubleshoot = p_Troubleshoot, dealwithtype = p_Dealwithtype, }, timestamp = DateTime.Now } ); string trims = obj.ToString().Replace("\r\n", ""); return new SocketBase.Packet(Encoding.UTF8.GetBytes(string.Concat(trims, ENDOP))); } #endregion } }