1.发送数据和接收数据用2个状态机实现;
2.增加了当数据发送以后指定的间隔内连续发送3次,如果没有收到下位机的回复则放弃;
3.取消使用定时器Timer类,自己写定时器;
using System;
using System.Collections;
using System.Threading;
using System.Xml;
using NLog;
using System.Timers;
using System.IO;
using System.Runtime.InteropServices;
using MSCommLib;
namespace equipment
{
/// <summary>
/// Desc:还书箱模块(用2个状态机实现)
/// Author:周陶
/// Date:2006-9-11
/// Version:1.0
/// </summary>
public class RestoreBook : ThreadBase,EquipmentIF
{
#region 配置文件
private const string m_config_file = "..//configure//equipment//RestoreBook_config.xml";
private const string m_const_node_name = "/configure/restorebooks/restorebook";
private const string m_const_comport = "/configure/restorebooks/restorebook/communication";
private static Logger logger = LogManager.GetCurrentClassLogger();
#endregion
#region 指令
private const string TCU_BOX_STATUS = "41";
private const string TCU_BOOK_STATUS = "40";
private const string TCU_CHECKMAG_STATUS = "42";
private const string TCU_DOOR_STATUS = "43";
private const string TCU_BOOK_MOVE = "23";
private const string TCU_RUN = "22";
private const string TCU_RESET = "21";
private const string TCU_END = "26";
private const string TCU_CHECK_STATE = "24";
#endregion
#region 响应码
private const string CE_OK = "0";
private const string CE_CHECKERROR = "1";
private const string CE_BADCOMMAND = "2"; //命令错误
private const string CE_BADPARAM = "3"; //参数错误
private const string CE_EXECUTE = "4"; //执行命令条件不足
private const string CE_UNKNOWN = "5";
private const string CE_NOCOMM = "6";
#endregion
#region 维护门状态
private const string TCU_DOOR_OPENED = "1";
private const string TCU_DOOR_CLOSED = "0";
#endregion
#region 检磁
private const string E_ERROR = "1";
private const string E_OK = "0";
#endregion
#region 书运行位置状态
private const string E_READER_POSITION = "1";
private const string E_WITHDRAW = "2";
private const string E_READY_WITHDRAW = "3";
private const string E_FORWARD = "4";
private const string E_BOOK_ENTRY_ALL = "5";
private const string E_BLOCK_BEFORE_READER = "11";
private const string E_BLOCK_BEFORE_BOX = "12";
private const string E_TIMEOUT_READER_POSITION = "13";
private const string E_TIMEOUT_WAITING_ENTRY = "14";
private const string E_TIMEOUT_ENTRY = "15";
#endregion
#region 还书箱状态
private const string E_BOX_FULL = "1";
private const string E_BOX_OK = "0";
#endregion
/*****************************************************************************/
MSCommLib.MSCommClass mc = new MSCommLib.MSCommClass();
ArrayList m_bytelist = new ArrayList();
byte[] m_data = new byte[11];
/*****************************************************************************/
/*****************************系统定时器**************************************/
private bool IS_RESPONSED = true;//是否已经应答
private int m_counter = 0;//用于计算3次消息发送
private string m_name = "";//响应指令名称
/*****************************************************************************/
/******************************自定义定时器***********************************/
BatchTimer t_time = null;//分片定时器
ResponseTimer m_responsetimer = null;//响应定时器
/*****************************************************************************/
/****************************状态机*******************************************/
#region 接收数据状态机
private const string R_WAITING = "等待";
private const string R_RECEIVING = "接收中";
private const string R_RECEIVEALL = "全部接收";
private const string R_BATCHTIMEOUT = "分片超时";
private const string R_RESPONSETIMEOUT = "响应超时";
private const string R_ERRORCOMMAND = "错误命令";
private const string R_ERRORSTATUS = "错误状态";
#endregion
#region 发送数据状态机
private const string S_WAITING = "等待";
private const string S_RECEIVEALL = "全部接收";
private const string S_RESPONSETIMEOUT = "响应超时";
private const string S_SEND = "已发送";
private const string S_RESEND = "重复发送";
private const string S_SENDCOUNT = "超过3次发送次数";
private const string S_BATCHTIMEOUT = "分片超时";
#endregion
/*****************************************************************************/
/****************************初始化状态机状态*********************************/
string state1=S_WAITING,state2=R_WAITING;
byte [] m_byte = new byte[11];
/*****************************************************************************/
[DllImport("user32.dll",EntryPoint="MessageBox")]
public static extern void MsgBox(int hWnd,String text,String caption,uint type);
/// <summary>
/// 构造函数
/// </summary>
/// <param name="i_name"></param>
public RestoreBook(string i_name):base(i_name)
{
this.InitCommonPort();
t_time = new BatchTimer();
m_responsetimer = new ResponseTimer();
}
/// <summary>
/// 从配置文件中读取配置端口号
/// </summary>
/// <param name="t_config"></param>
/// <returns></returns>
private string getComPortConfig(string t_config)
{
XmlTextReader reader = new XmlTextReader(m_config_file);
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(reader);
reader.Close();
XmlNode t_node = xmldoc.SelectSingleNode(t_config);
string port = t_node.InnerText;
return port;
}
/// <summary>
/// 取出指定长度的数据
/// </summary>
/// <param name="o_bytelist"></param>
/// <param name="length"></param>
private void GetReceiveData(ref byte[] o_bytelist,int length)
{
for(int i=0;i<length;i++)
{
o_bytelist[i] = (byte)m_bytelist[i];
}
m_bytelist.RemoveRange(0,length);
}
/// <summary>
/// 接收MCU主动发送的消息、解析、封装成对象消息发送给Session层
/// </summary>
protected override void process()
{
//以40,41,42,43开头的指令属于主动上报状态的命令
int count = 0;
lock(state2)//接收数据状态机
{
switch(state2)
{
#region 接收中
case R_RECEIVING:
{
count = m_bytelist.Count;//计算缓冲区中接收到的数据长度
if(count == 0)
{
state2 = R_WAITING;
}
else if(count < 11)//如果长度<11 接收不完整,启动分片定时器
{
#region 分片定时器
if(!t_time.IsStart)
{
t_time.Start();
t_time.Intenal = 2000;
logger.Debug("\n分片定时器已启动!");
}
else
{
if(t_time.IsTimeOut)
{
state1 = S_BATCHTIMEOUT;
}
}
#endregion
}
else if(count >= 11)
{
this.GetReceiveData(ref m_byte,11);
byte t_command = m_byte[2];//获得消息的命令用来判断是主动上报消息还是响应消息
if(m_byte[0] == 0x82)
{
if(m_byte[10] == 0x83)
{
if(verifyCRC(m_byte))
{
if(t_command == 0x40 || t_command == 0x41 || t_command == 0x42 || t_command == 0x43)
{
logger.Debug("\n正确的状态指令 : [" + Utilities.ByteArrayToHexString(m_byte) + "]");
}
else
{
logger.Debug("\n正确的响应指令 : [" + Utilities.ByteArrayToHexString(m_byte) + "]");
m_counter = 0;
m_responsetimer.Stop();
}
state1 = S_RECEIVEALL;//将发送状态机状态改为全部接收
state2 = R_RECEIVING;//将接收状态机状态改为接收中
}
else
{
if(t_command == 0x40 || t_command == 0x41 || t_command == 0x42 || t_command == 0x43)
{
state2 = R_ERRORSTATUS;
}
else
{
state2 = R_ERRORCOMMAND;
}
}
}
else
{
if(t_command == 0x40 || t_command == 0x41 || t_command == 0x42 || t_command == 0x43)
{
state2 = R_ERRORSTATUS;
}
else
{
state2 = R_ERRORCOMMAND;
}
}
}
else
{
if(t_command == 0x40 || t_command == 0x41 || t_command == 0x42 || t_command == 0x43)
{
state2 = R_ERRORSTATUS;
}
else
{
state2 = R_ERRORCOMMAND;
}
}
}
break;
}
#endregion
#region 接收命令错误
case R_ERRORCOMMAND:
{
state2 = R_RECEIVING;//接收中
logger.Debug("\n响应命令格式错误![" + Utilities.ByteArrayToHexString(m_byte) + "]");
this.clearArray(ref m_byte);
break;
}
#endregion
#region 接收状态错误
case R_ERRORSTATUS:
{
state2 = R_RECEIVING;//接收中
logger.Debug("\n接收状态格式错误! [" + Utilities.ByteArrayToHexString(m_byte) + "]");
this.clearArray(ref m_byte);
break;
}
#endregion
}
}
lock(state1)//发送数据状态机
{
switch(state1)
{
#region 已发送
case S_SEND:
{
if(!m_responsetimer.IsStart)
{
m_responsetimer.Start();
m_responsetimer.Intenal = 3000;
IS_RESPONSED = false;
logger.Debug("\n响应超时定时器已启动!");
}
break;
}
#endregion
#region 接收完毕并通过验证
case S_RECEIVEALL:
{
sendMail(m_byte);//通知上层
state1 = S_WAITING;
logger.Debug("\n已接收 : " + Utilities.ByteArrayToHexString(m_byte) + "]");
this.clearArray(ref m_byte);
break;
}
#endregion
#region 重复发送3次
case S_RESEND:
{
Thread.Sleep(1000);
mc.Output = m_data;
state1 = S_WAITING;
logger.Debug("\n重复发送指令 : [" + Utilities.ByteArrayToHexString(m_data) + "] "+m_counter+"次!");
break;
}
#endregion
#region 响应超时
case S_RESPONSETIMEOUT:
{
state1 = S_WAITING;
m_responsetimer.Stop();
m_counter = 0;
IS_RESPONSED = true;
this.clearArray(ref m_data);
logger.Debug("\n响应已超时!");
break;
}
#endregion
#region 发送次数超过3次
case S_SENDCOUNT:
{
m_counter = 0;
m_responsetimer.Stop();
IS_RESPONSED = true;
state1 = S_WAITING;//将状态设为等待状态
logger.Debug("命令无应答,定时器已停止!");
MsgBox(0,"命令无应答!","提醒",0);
break;
}
#endregion
#region 分片超时
case S_BATCHTIMEOUT:
{
state1 = S_WAITING;//将接收状态机改为等待状态
this.GetReceiveData(ref m_byte,count);
//m_bytelist.RemoveRange(0,count);//清除缓冲区
IS_RESPONSED = true;
t_time.Stop();
logger.Debug("\n不完整的"+m_name+"响应指令 : ["+Utilities.ByteArrayToHexString(m_byte) + "],分片定时器已停止!");
this.clearArray(ref m_byte);
break;
}
#endregion
}
}
#region 响应定时器
if(IS_RESPONSED == false)//没有响应
{
if(m_responsetimer.IsStart)//超时定时器已启动
{
if(m_counter < 3)//发送次数小于3
{
if(m_responsetimer.IsTimeOut)//超时
{
state1 = S_RESPONSETIMEOUT;//通知发送状态机响应超时
}
else//没有超时但没有收到响应
{
state1 = S_RESEND;//通知发送状态机再发一次
m_counter ++;//次数+1
}
}
else//超过3次
{
state1 = S_SENDCOUNT;//通知发送状态机停止发送,关闭定时器
}
}
}
#endregion
}
/// <summary>
/// check the data CRC
/// </summary>
/// <returns></returns>
private bool verifyCRC(byte[] i_byte)
{
#region 接收
byte t1 = i_byte[8];
byte t2 = i_byte[9];
byte [] data = {0x08,i_byte[2],i_byte[4],i_byte[5],i_byte[6],i_byte[7]};
byte [] crcData = Utilities.CRC(data,data.Length);
if(t1==crcData[0] && t2==crcData[1])
{
return true;
}
else
{
return false;
}
#endregion
}
/// <summary>
/// clear array
/// </summary>
/// <param name="o_data"></param>
private void clearArray(ref byte[]o_data)
{
for(int i=0;i<o_data.Length;i++)
{
o_data[i] =0;
}
}
/// <summary>
/// send mail to session
/// </summary>
/// <param name="inData"></param>
private void sendMail(byte[] inData)
{
//构造命令
Mail t_mail = null;
MailHandlerIF t_mail_handler = new RestoreBookMailHandler();
string t_cmd = inData[2].ToString("X");//指令
string t_paramter = inData[7].ToString("X");//参数
#region
switch(t_cmd)
{
case TCU_BOX_STATUS: //主 动 上 报 回 收 箱 状 态
{
#region
switch(t_paramter)
{
case E_BOX_FULL:
{
//箱满
t_mail = t_mail_handler.CreateMail(MailInfo.Type.RestoreBook,MailInfo.Name.E_TCU_BOX_STATUS,this.m_send_mailbox,this.m_receive_mailbox,MailInfo.E_TCU_Parameter.E_BOX_FULL);
response("BOX",E_BOX_FULL);
break;
}
case E_BOX_OK:
{
//正常
t_mail = t_mail_handler.CreateMail(MailInfo.Type.RestoreBook,MailInfo.Name.E_TCU_BOX_STATUS,this.m_send_mailbox,this.m_receive_mailbox,MailInfo.E_TCU_Parameter.E_BOX_OK);
response("BOX",E_BOX_OK);
break;
}
}
this.m_send_mailbox.delivery(t_mail);
break;
#endregion
}
case TCU_BOOK_STATUS: //TCU 主 动 上 报 书 运 行 位 置 状 态
{
#region
switch(t_paramter)
{
case E_READER_POSITION:
{
//书已到读卡位置
t_mail = t_mail_handler.CreateMail(MailInfo.Type.RestoreBook,MailInfo.Name.E_TCU_BOOK_STATUS,this.m_send_mailbox,this.m_receive_mailbox,MailInfo.E_TCU_Parameter.E_READER_POSITION);
response("BOOK_STATUS",E_READER_POSITION);
break;
}
case E_WITHDRAW:
{
//书已经从入口被取走
t_mail = t_mail_handler.CreateMail(MailInfo.Type.RestoreBook,MailInfo.Name.E_TCU_BOOK_STATUS,this.m_send_mailbox,this.m_receive_mailbox,MailInfo.E_TCU_Parameter.E_WITHDRAW);
response("BOOK_STATUS",E_WITHDRAW);
break;
}
case E_READY_WITHDRAW:
{
//书已在入口处等待被取走
t_mail = t_mail_handler.CreateMail(MailInfo.Type.RestoreBook,MailInfo.Name.E_TCU_BOOK_STATUS,this.m_send_mailbox,this.m_receive_mailbox,MailInfo.E_TCU_Parameter.E_READY_WITHDRAW);
response("BOOK_STATUS",E_READY_WITHDRAW);
break;
}
case E_FORWARD:
{
//书已收入回收箱
t_mail = t_mail_handler.CreateMail(MailInfo.Type.RestoreBook,MailInfo.Name.E_TCU_BOOK_STATUS,this.m_send_mailbox,this.m_receive_mailbox,MailInfo.E_TCU_Parameter.E_FORWARD);
response("BOOK_STATUS",E_FORWARD);
break;
}
case E_BOOK_ENTRY_ALL:
{
//书完全进入
t_mail = t_mail_handler.CreateMail(MailInfo.Type.RestoreBook,MailInfo.Name.E_TCU_BOOK_STATUS,this.m_send_mailbox,this.m_receive_mailbox,MailInfo.E_TCU_Parameter.E_BOOK_ENTRY_ALL);
response("BOOK_STATUS",E_BOOK_ENTRY_ALL);
break;
}
case E_BLOCK_BEFORE_READER:
{
//读卡位置到入口之间发生堵塞故障
t_mail = t_mail_handler.CreateMail(MailInfo.Type.RestoreBook,MailInfo.Name.E_TCU_BOOK_STATUS,this.m_send_mailbox,this.m_receive_mailbox,MailInfo.E_TCU_Parameter.E_BLOCK_BEFORE_READER);
response("BOOK_STATUS",E_BLOCK_BEFORE_READER);
break;
}
case E_BLOCK_BEFORE_BOX:
{
//读卡位置到回收箱之间发生堵塞故障
t_mail = t_mail_handler.CreateMail(MailInfo.Type.RestoreBook,MailInfo.Name.E_TCU_BOOK_STATUS,this.m_send_mailbox,this.m_receive_mailbox,MailInfo.E_TCU_Parameter.E_BLOCK_BEFORE_BOX);
response("BOOK_STATUS",E_BLOCK_BEFORE_BOX);
break;
}
case E_TIMEOUT_READER_POSITION:
{
//读卡位置等待超时
t_mail = t_mail_handler.CreateMail(MailInfo.Type.RestoreBook,MailInfo.Name.E_TCU_BOOK_STATUS,this.m_send_mailbox,this.m_receive_mailbox,MailInfo.E_TCU_Parameter.E_TIMEOUT_READER_POSITION);
response("BOOK_STATUS",E_TIMEOUT_READER_POSITION);
break;
}
case E_TIMEOUT_WAITING_ENTRY:
{
//书等待进入超时
t_mail = t_mail_handler.CreateMail(MailInfo.Type.RestoreBook,MailInfo.Name.E_TCU_BOOK_STATUS,this.m_send_mailbox,this.m_receive_mailbox,MailInfo.E_TCU_Parameter.E_TIMEOUT_WAITING_ENTRY);
response("BOOK_STATUS",E_TIMEOUT_WAITING_ENTRY);
break;
}
case E_TIMEOUT_ENTRY:
{
//书在入口处等待超时
t_mail = t_mail_handler.CreateMail(MailInfo.Type.RestoreBook,MailInfo.Name.E_TCU_BOOK_STATUS,this.m_send_mailbox,this.m_receive_mailbox,MailInfo.E_TCU_Parameter.E_TIMEOUT_ENTRY);
response("BOOK_STATUS",E_TIMEOUT_ENTRY);
break;
}
}
this.m_send_mailbox.delivery(t_mail);
break;
#endregion
}
case TCU_CHECKMAG_STATUS: //主 动 上 报 检 磁 状 态
{
#region
switch(t_paramter)
{
case E_ERROR:
{
//检磁失败
t_mail = t_mail_handler.CreateMail(MailInfo.Type.RestoreBook,MailInfo.Name.E_TCU_CHECKMAG_STATUS,this.m_send_mailbox,this.m_receive_mailbox,MailInfo.E_TCU_Parameter.E_ERROR);
response("CHECKMAG",E_ERROR);
break;
}
case E_OK:
{
//检磁成功
t_mail = t_mail_handler.CreateMail(MailInfo.Type.RestoreBook,MailInfo.Name.E_TCU_CHECKMAG_STATUS,this.m_send_mailbox,this.m_receive_mailbox,MailInfo.E_TCU_Parameter.E_OK);
response("CHECKMAG",E_OK);
break;
}
}
this.m_send_mailbox.delivery(t_mail);
break;
#endregion
}
case TCU_DOOR_STATUS: //主 动 上 报 维 护 门 状 态
{
#region
switch(t_paramter)
{
case TCU_DOOR_OPENED:
{
//门被打开
t_mail = t_mail_handler.CreateMail(MailInfo.Type.RestoreBook,MailInfo.Name.E_TCU_DOOR_STATUS,this.m_send_mailbox,this.m_receive_mailbox,MailInfo.E_TCU_Parameter.E_DOOR_OPEN);
response("DOOR_STATUS",TCU_DOOR_OPENED);
break;
}
case TCU_DOOR_CLOSED:
{
//门关闭
t_mail = t_mail_handler.CreateMail(MailInfo.Type.RestoreBook,MailInfo.Name.E_TCU_DOOR_STATUS,this.m_send_mailbox,this.m_receive_mailbox,MailInfo.E_TCU_Parameter.E_DOOR_CLOSE);
response("DOOR_STATUS",TCU_DOOR_CLOSED);
break;
}
}
this.m_send_mailbox.delivery(t_mail);
break;
#endregion
}
case TCU_BOOK_MOVE: //指 导 书 运 行 状 态
{
#region
switch(t_paramter)
{
case CE_OK://正常
{
t_mail = t_mail_handler.CreateMail(MailInfo.Type.RestoreBook,MailInfo.Name.E_TCU_BOOK_MOVE,this.m_send_mailbox,this.m_receive_mailbox,MailInfo.ErrorParameter.E_TCU_OK);
break;
}
case CE_CHECKERROR://校验错误
{
t_mail = t_mail_handler.CreateMail(MailInfo.Type.RestoreBook,MailInfo.Name.E_TCU_BOOK_MOVE,this.m_send_mailbox,this.m_receive_mailbox,MailInfo.ErrorParameter.E_TCU_CHECKERROR);
break;
}
case CE_BADCOMMAND://命令错误
{
t_mail = t_mail_handler.CreateMail(MailInfo.Type.RestoreBook,MailInfo.Name.E_TCU_BOOK_MOVE,this.m_send_mailbox,this.m_receive_mailbox,MailInfo.ErrorParameter.E_TCU_BADCOMMAND);
break;
}
case CE_BADPARAM://参数错误
{
t_mail = t_mail_handler.CreateMail(MailInfo.Type.RestoreBook,MailInfo.Name.E_TCU_BOOK_MOVE,this.m_send_mailbox,this.m_receive_mailbox,MailInfo.ErrorParameter.E_TCU_BADPARAM);
break;
}
case CE_EXECUTE://命令执行条件不足
{
t_mail = t_mail_handler.CreateMail(MailInfo.Type.RestoreBook,MailInfo.Name.E_TCU_BOOK_MOVE,this.m_send_mailbox,this.m_receive_mailbox,MailInfo.ErrorParameter.E_TCU_EXECUTE);
break;
}
case CE_UNKNOWN://其他错误
{
t_mail = t_mail_handler.CreateMail(MailInfo.Type.RestoreBook,MailInfo.Name.E_TCU_BOOK_MOVE,this.m_send_mailbox,this.m_receive_mailbox,MailInfo.ErrorParameter.E_TCU_UNKNOWN);
break;
}
case CE_NOCOMM://通讯故障
{
t_mail = t_mail_handler.CreateMail(MailInfo.Type.RestoreBook,MailInfo.Name.E_TCU_BOOK_MOVE,this.m_send_mailbox,this.m_receive_mailbox,MailInfo.ErrorParameter.E_TCU_NOCOMM);
break;
}
}
this.m_send_mailbox.delivery(t_mail);
break;
#endregion
}
case TCU_RUN: //登 陆 成 功
{
#region
switch(t_paramter)
{
case CE_OK://正常
{
t_mail = t_mail_handler.CreateMail(MailInfo.Type.RestoreBook,MailInfo.Name.E_TCU_RUN,this.m_send_mailbox,this.m_receive_mailbox,MailInfo.ErrorParameter.E_TCU_OK);
this.m_send_mailbox.delivery(t_mail);
break;
}
}
break;
#endregion
}
case TCU_RESET: //复 位
{
#region
switch(t_paramter)
{
case CE_OK://正常
{
t_mail = t_mail_handler.CreateMail(MailInfo.Type.RestoreBook,MailInfo.Name.E_TCU_RESET,this.m_send_mailbox,this.m_receive_mailbox,MailInfo.ErrorParameter.E_TCU_OK);
this.m_send_mailbox.delivery(t_mail);
break;
}
}
break;
#endregion
}
case TCU_END: //结 束
{
#region
switch(t_paramter)
{
case CE_OK://正常
{
t_mail = t_mail_handler.CreateMail(MailInfo.Type.RestoreBook,MailInfo.Name.E_TCU_END,this.m_send_mailbox,this.m_receive_mailbox,MailInfo.ErrorParameter.E_TCU_OK);
this.m_send_mailbox.delivery(t_mail);
break;
}
}
break;
#endregion
}
case TCU_CHECK_STATE://检 查 设 备 状 态
{
byte p4 = inData[7];
if((p4 & 0x02) == 0)
{
t_mail = t_mail_handler.CreateMail(MailInfo.Type.RestoreBook,MailInfo.Name.E_TCU_CHECK_STATE,this.m_send_mailbox,this.m_receive_mailbox,MailInfo.E_TCU_Parameter.E_BOX_COVER);
this.m_send_mailbox.delivery(t_mail);
}
if((p4 & 0x04) == 0)
{
t_mail = t_mail_handler.CreateMail(MailInfo.Type.RestoreBook,MailInfo.Name.E_TCU_CHECK_STATE,this.m_send_mailbox,this.m_receive_mailbox,MailInfo.E_TCU_Parameter.E_DOOR_COVER);
this.m_send_mailbox.delivery(t_mail);
}
if((p4 & 0x08) == 0)
{
t_mail = t_mail_handler.CreateMail(MailInfo.Type.RestoreBook,MailInfo.Name.E_TCU_CHECK_STATE,this.m_send_mailbox,this.m_receive_mailbox,MailInfo.E_TCU_Parameter.E_CHECKMAG_CONVER);
this.m_send_mailbox.delivery(t_mail);
}
if((p4 & 0x10) == 0)
{
t_mail = t_mail_handler.CreateMail(MailInfo.Type.RestoreBook,MailInfo.Name.E_TCU_CHECK_STATE,this.m_send_mailbox,this.m_receive_mailbox,MailInfo.E_TCU_Parameter.E_READER_CONVER);
this.m_send_mailbox.delivery(t_mail);
}
if((p4 & 0x20) == 0)
{
t_mail = t_mail_handler.CreateMail(MailInfo.Type.RestoreBook,MailInfo.Name.E_TCU_CHECK_STATE,this.m_send_mailbox,this.m_receive_mailbox,MailInfo.E_TCU_Parameter.E_BOX_ENTRY1_CONVER);
this.m_send_mailbox.delivery(t_mail);
}
if((p4 & 0x40) == 0)
{
t_mail = t_mail_handler.CreateMail(MailInfo.Type.RestoreBook,MailInfo.Name.E_TCU_CHECK_STATE,this.m_send_mailbox,this.m_receive_mailbox,MailInfo.E_TCU_Parameter.E_BOX_ENTRY2_COVER);
this.m_send_mailbox.delivery(t_mail);
}
break;
}
}
#endregion
//发送命令
//this.m_send_mailbox.delivery(t_mail);
}
/// <summary>
/// init com
/// </summary>
private void InitCommonPort()
{
try
{
string [] t_comport = this.getComPortConfig(m_const_comport).Split(':');
mc.CommPort = Convert.ToInt16( t_comport[0].Substring(3,1) );//4
mc.Settings = t_comport[1] ;//38400,n,8,1
mc.RThreshold = 1;//每接收一个字符则激发OnComm()事件
mc.DTREnable = true;
mc.Handshaking = MSCommLib.HandshakeConstants.comNone;
mc.InputMode = MSCommLib.InputModeConstants.comInputModeBinary; //二进制
mc.InBufferSize = 1024;
mc.InputLen = 0;//决定每次Input读入的字符个数,缺省为0,表示读取接收缓冲区的全部内容
//mc.InputLen = 1;//一次读取一个
mc.NullDiscard = false;
mc.OnComm +=new MSCommLib.DMSCommEvents_OnCommEventHandler(mc_OnComm);//注册一个OnComm事件
try
{
mc.PortOpen = true; //打开串口
logger.Debug("串口已打开!");
}
catch
{
logger.Debug("串口打开失败!");
}
}
catch(Exception ex)
{
logger.Debug(ex.Message);
}
}
/// <summary>
/// release resource
/// </summary>
public override void shutDown()
{
if(mc.PortOpen)
mc.PortOpen = false;
}
/// <summary>
/// receive the data from session layer then parse、create com data and send to MCU
/// </summary>
/// <param name="i_mail"></param>
protected override void commonMailArriveProcess(Mail i_mail)
{
MailInfo.Name t_mail_name = i_mail.m_mail_name; //mail name(command)
string t_book_parameter = (string)i_mail.m_parameter; //parameter
byte [] data = {0x08,0x00,0x00,0x00,0x00,0x00};
byte [] outData = {0x02,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03};
byte [] crcData = null;
byte [] cData = null;
#region
switch(t_mail_name)
{
case MailInfo.Name.E_TCU_RESET: //复位
{
#region
data[1] = 0x21;
crcData = Utilities.CRC(data,data.Length);
outData[2] = 0x21;
outData[8] = crcData[0];
outData[9] = crcData[1];
mc.Output = outData;
logger.Debug("\n复位 : [" + Utilities.ByteArrayToHexString(outData) + "]");
break;
#endregion
}
case MailInfo.Name.E_TCU_RUN: //登陆成功
{
#region
data[1] = 0x22;
crcData = Utilities.CRC(data,data.Length);
outData[2] = 0x22;
outData[8] = crcData[0];
outData[9] = crcData[1];
mc.Output = outData;
m_name = "登陆成功";
logger.Debug("\n发送登陆成功指令 : [" + Utilities.ByteArrayToHexString(outData) + "]");
/***********************************************************************************/
outData.CopyTo(m_data,0);//将消息复制到全局变量数组中,以后用来判断改消息是否回复
state1 = S_SEND;//将发送状态机的状态改为已发送
/***********************************************************************************/
break;
#endregion
}
case MailInfo.Name.E_TCU_CHECK_STATE: //检查设备状态
{
#region
data[1] = 0x24;
crcData = Utilities.CRC(data,data.Length);
outData[2] = 0x24;
outData[8] = crcData[0];
outData[9] = crcData[1];
mc.Output = outData;
m_name = "检查设备状态";
logger.Debug("\n检查设备状态 : [" + Utilities.ByteArrayToHexString(outData) + "]");
/************************************************************************************/
outData.CopyTo(m_data,0);//将消息复制到全局变量数组中,以后用来判断改消息是否回复
state1 = S_SEND;//将发送状态机的状态改为已发送
/************************************************************************************/
break;
#endregion
}
case MailInfo.Name.E_TCU_BOOK_MOVE: //指导书运动
{
#region
switch(t_book_parameter)
{
case "E_BACK": //书已退到入口
{
#region
data[1] = 0x23;
data[5] = 0x01;
crcData = Utilities.CRC(data,data.Length);
outData[2] = 0x23;
outData[7] = 0x01;
outData[8] = crcData[0];
outData[9] = crcData[1];
logger.Debug("\n书已退到入口 : ["+ Utilities.ByteArrayToHexString(outData) + "]");
break;
#endregion
}
case "E_FORWARD": //收入回收箱
{
#region
data[1] = 0x23;
data[5] = 0x02;
crcData = Utilities.CRC(data,data.Length);
outData[2] = 0x23;
outData[7] = 0x02;
outData[8] = crcData[0];
outData[9] = crcData[1];
logger.Debug("\n收入回收箱 : ["+ Utilities.ByteArrayToHexString(outData) + "]");
break;
#endregion
}
}
mc.Output = outData;
/************************************************************************************/
outData.CopyTo(m_data,0);//将消息复制到全局变量数组中,以后用来判断改消息是否回复
state1 = S_SEND;//将发送状态机的状态改为已发送
/************************************************************************************/
break;
#endregion
}
case MailInfo.Name.E_TCU_BOOK_STATUS: //主动上报书运行位置状态
{
#region
switch(t_book_parameter)
{
case "E_READER_POSITION"://书已到读卡位置
{
#region
data[1] = 0x40;
data[5] = 0x01;
cData = Utilities.CRC(data,data.Length);
outData[0] = 0x82;
outData[2] = 0x40;
outData[7] = 0x01;
outData[8] = cData[0];
outData[9] = cData[1];
outData[10] = 0x83;
logger.Debug("\n书已到读卡位置 : [" + Utilities.ByteArrayToHexString(outData) + "]");
break;
#endregion
}
case "E_WITHDRAW"://书已从入口被取走
{
#region
data[1] = 0x40;
data[5] = 0x02;
cData = Utilities.CRC(data,data.Length);
outData[0] = 0x82;
outData[2] = 0x40;
outData[7] = 0x02;
outData[8] = cData[0];
outData[9] = cData[1];
outData[10] = 0x83;
logger.Debug("\n书已从入口被取走 : [" + Utilities.ByteArrayToHexString(outData) + "]");
break;
#endregion
}
case "E_READY_WITHDRAW"://书已在入口处等待被取走
{
#region
data[1] = 0x40;
data[5] = 0x03;
cData = Utilities.CRC(data,data.Length);
outData[0] = 0x82;
outData[2] = 0x40;
outData[7] = 0x03;
outData[8] = cData[0];
outData[9] = cData[1];
outData[10] = 0x83;
logger.Debug("\n书已在入口处等待被取走 : [" + Utilities.ByteArrayToHexString(outData) +"]");
break;
#endregion
}
case "E_FORWARD"://书已收入回收箱
{
#region
data[1] = 0x40;
data[5] = 0x04;
cData = Utilities.CRC(data,data.Length);
outData[0] = 0x82;
outData[2] = 0x40;
outData[7] = 0x04;
outData[8] = cData[0];
outData[9] = cData[1];
outData[10] = 0x83;
logger.Debug("\n书已收入回收箱 : [" + Utilities.ByteArrayToHexString(outData) +"]");
break;
#endregion
}
case "E_BLOCK_BEFORE_READER"://读卡位置到入口之间发生堵塞故障
{
#region
data[1] = 0x40;
data[5] = 0x011;
cData = Utilities.CRC(data,data.Length);
outData[0] = 0x82;
outData[2] = 0x40;
outData[7] = 0x11;
outData[8] = cData[0];
outData[9] = cData[1];
outData[10] = 0x83;
logger.Debug("\n读卡位置到入口之间发生堵塞故障 : [" + Utilities.ByteArrayToHexString(outData) +"]");
break;
#endregion
}
case "E_BLOCK_BEFORE_BOX"://读卡位置到回收箱之间发生堵塞故障
{
#region
data[1] = 0x40;
data[5] = 0x12;
cData = Utilities.CRC(data,data.Length);
outData[0] = 0x82;
outData[2] = 0x40;
outData[7] = 0x12;
outData[8] = cData[0];
outData[9] = cData[1];
outData[10] = 0x83;
logger.Debug("\n读卡位置到回收箱之间发生堵塞故障 : [" + Utilities.ByteArrayToHexString(outData) +"]");
break;
#endregion
}
case "E_TIMEOUT_READER_POSITION": //读卡位置等待超时
{
#region
data[1] = 0x40;
data[5] = 0x13;
cData = Utilities.CRC(data,data.Length);
outData[0] = 0x82;
outData[2] = 0x40;
outData[7] = 0x13;
outData[8] = cData[0];
outData[9] = cData[1];
outData[10] = 0x83;
logger.Debug("\n读卡位置等待超时 : [" + Utilities.ByteArrayToHexString(outData)+"]");
break;
#endregion
}
case "E_TIMEOUT_WAITING_ENTRY"://书等待进入超时
{
#region
data[1] = 0x40;
data[5] = 0x14;
cData = Utilities.CRC(data,data.Length);
outData[0] = 0x82;
outData[2] = 0x40;
outData[7] = 0x14;
outData[8] = cData[0];
outData[9] = cData[1];
outData[10] = 0x83;
logger.Debug("\n书等待进入超时 : [" + Utilities.ByteArrayToHexString(outData)+"]");
break;
#endregion
}
case "E_TIMEOUT_ENTRY"://书在入口处等待超时
{
#region
data[1] = 0x40;
data[5] = 0x15;
cData = Utilities.CRC(data,data.Length);
outData[0] = 0x82;
outData[2] = 0x40;
outData[7] = 0x15;
outData[8] = cData[0];
outData[9] = cData[1];
outData[10] = 0x83;
logger.Debug("\n书在入口处等待超时 : [" + Utilities.ByteArrayToHexString(outData) + "]");
break;
#endregion
}
default://书已进入还书箱
{
#region
data[1] = 0x23;
cData = Utilities.CRC(data,data.Length);
outData[2] = 0x23;
outData[8] = cData[0];
outData[9] = cData[1];
logger.Debug("\n书已进入还书箱 : [" + Utilities.ByteArrayToHexString(outData) + "]");
break;
#endregion
}
}
mc.Output = outData;
break;
#endregion
}
case MailInfo.Name.E_TCU_END: //结束
{
#region
data[1] = 0x26;
crcData = Utilities.CRC(data,data.Length);
outData[2] = 0x26;
outData[8] = crcData[0];
outData[9] = crcData[1];
mc.Output = outData;
m_name = "结束";
logger.Debug("\n结束 : [" + Utilities.ByteArrayToHexString(outData) + "]");
/*************************************************************************************/
outData.CopyTo(m_data,0);//将消息复制到全局变量数组中,以后用来判断改消息是否回复
state1 = S_SEND;//将发送状态机的状态改为已发送
/*************************************************************************************/
break;
#endregion
}
}
#endregion
}
/// <summary>
/// 对下位机主动发送的命令的响应
/// </summary>
/// <param name="command">命令</param>
/// <param name="parameter">参数</param>
private void response(string command,string parameter)
{
byte [] crcData = null;//校验码
byte [] data = null;//参与计算校验码值参数
byte [] outData = null;//响应消息
switch(command)
{
case "BOX"://还书箱状态
{
switch(parameter)
{
#region
case E_BOX_FULL://还书箱已满
{
data = new byte[]{0x08,0x41,0x00,0x00,0x00,0x00};
crcData = Utilities.CRC(data,data.Length);
outData = new byte[]{0x02,0x08,0x41,0x00,0x00,0x00,0x00,0x00,crcData[0],crcData[1],0x03};
break;
}
case E_BOX_OK://还书箱正常
{
data = new byte[]{0x08,0x41,0x00,0x00,0x00,0x00};
crcData = Utilities.CRC(data,data.Length);
outData = new byte[]{0x02,0x08,0x41,0x00,0x00,0x00,0x00,0x00,crcData[0],crcData[1],0x03};
break;
}
#endregion
}
break;
}
case "BOOK_STATUS"://书运行状态
{
switch(parameter)
{
#region
case E_READER_POSITION://书已到读卡位置
{
data = new byte[]{0x08,0x40,0x00,0x00,0x00,0x00};
crcData = Utilities.CRC(data,data.Length);
outData = new byte[]{0x02,0x08,0x40,0x00,0x00,0x00,0x00,0x00,crcData[0],crcData[1],0x03};
break;
}
case E_WITHDRAW://书从入口被取走
{
data = new byte[]{0x08,0x40,0x00,0x00,0x00,0x00};
crcData = Utilities.CRC(data,data.Length);
outData = new byte[]{0x02,0x08,0x40,0x00,0x00,0x00,0x00,0x00,crcData[0],crcData[1],0x03};
break;
}
case E_READY_WITHDRAW://书已在入口处被等待取走
{
data = new byte[]{0x08,0x40,0x00,0x00,0x00,0x00};
crcData = Utilities.CRC(data,data.Length);
outData = new byte[]{0x02,0x08,0x40,0x00,0x00,0x00,0x00,0x00,crcData[0],crcData[1],0x03};
break;
}
case E_FORWARD://书已进入回收箱
{
data = new byte[]{0x08,0x40,0x00,0x00,0x00,0x00};
crcData = Utilities.CRC(data,data.Length);
outData = new byte[]{0x02,0x08,0x40,0x00,0x00,0x00,0x00,0x00,crcData[0],crcData[1],0x03};
break;
}
case E_BOOK_ENTRY_ALL://书已完全进入
{
data = new byte[]{0x08,0x40,0x00,0x00,0x00,0x00};
crcData = Utilities.CRC(data,data.Length);
outData = new byte[]{0x02,0x08,0x40,0x00,0x00,0x00,0x00,0x00,crcData[0],crcData[1],0x03};
break;
}
case E_BLOCK_BEFORE_READER://读卡位置到入口之间发生堵塞故障
{
data = new byte[]{0x08,0x40,0x00,0x00,0x00,0x00};
crcData = Utilities.CRC(data,data.Length);
outData = new byte[]{0x02,0x08,0x40,0x00,0x00,0x00,0x00,0x00,crcData[0],crcData[1],0x03};
break;
}
case E_BLOCK_BEFORE_BOX://读卡位置到回收箱之间发生堵塞故障
{
data = new byte[]{0x08,0x40,0x00,0x00,0x00,0x00};
crcData = Utilities.CRC(data,data.Length);
outData = new byte[]{0x02,0x08,0x40,0x00,0x00,0x00,0x00,0x00,crcData[0],crcData[1],0x03};
break;
}
case E_TIMEOUT_READER_POSITION://读卡位置等待超时
{
data = new byte[]{0x08,0x40,0x00,0x00,0x00,0x00};
crcData = Utilities.CRC(data,data.Length);
outData = new byte[]{0x02,0x08,0x40,0x00,0x00,0x00,0x00,0x00,crcData[0],crcData[1],0x03};
break;
}
case E_TIMEOUT_WAITING_ENTRY://书等待进入超时
{
data = new byte[]{0x08,0x40,0x00,0x00,0x00,0x00};
crcData = Utilities.CRC(data,data.Length);
outData = new byte[]{0x02,0x08,0x40,0x00,0x00,0x00,0x00,0x00,crcData[0],crcData[1],0x03};
break;
}
case E_TIMEOUT_ENTRY://书在入口处等待超时
{
data = new byte[]{0x08,0x40,0x00,0x00,0x00,0x00};
crcData = Utilities.CRC(data,data.Length);
outData = new byte[]{0x02,0x08,0x40,0x00,0x00,0x00,0x00,0x00,crcData[0],crcData[1],0x03};
break;
}
#endregion
}
break;
}
case "CHECKMAG"://检磁状态
{
switch(parameter)
{
#region
case E_ERROR:
{
data = new byte[]{0x08,0x42,0x00,0x00,0x00,0x00};
crcData = Utilities.CRC(data,data.Length);
outData = new byte[]{0x02,0x08,0x42,0x00,0x00,0x00,0x00,0x00,crcData[0],crcData[1],0x03};
break;
}
case E_OK:
{
data = new byte[]{0x08,0x42,0x00,0x00,0x00,0x00};
crcData = Utilities.CRC(data,data.Length);
outData = new byte[]{0x02,0x08,0x42,0x00,0x00,0x00,0x00,0x00,crcData[0],crcData[1],0x03};
break;
}
#endregion
}
break;
}
case "DOOR_STATUS"://维护门状态
{
switch(parameter)
{
#region
case TCU_DOOR_OPENED:
{
data = new byte[]{0x08,0x43,0x00,0x00,0x00,0x00};
crcData = Utilities.CRC(data,data.Length);
outData = new byte[]{0x02,0x08,0x43,0x00,0x00,0x00,0x00,0x00,crcData[0],crcData[1],0x03};
break;
}
case TCU_DOOR_CLOSED:
{
data = new byte[]{0x08,0x43,0x00,0x00,0x00,0x00};
crcData = Utilities.CRC(data,data.Length);
outData = new byte[]{0x02,0x08,0x43,0x00,0x00,0x00,0x00,0x00,crcData[0],crcData[1],0x03};
break;
}
#endregion
}
break;
}
}
mc.Output = outData;
}
/// <summary>
/// receive data from com
/// </summary>
private void mc_OnComm()
{
byte [] t_byte = (byte[])mc.Input;//接收数据清空缓冲区
for(int i = 0;i<t_byte.Length;i++)
{
Monitor.Enter(m_bytelist);
m_bytelist.Add(t_byte[i]);
Monitor.Exit(m_bytelist);
}
lock(state2)
{
if(t_byte.Length > 0)
{
state2 = R_RECEIVING;//有数据到达把状态改成正在接收
}
}
}
}
}