using System; using System.Collections; //using System.Threading.Tasks; using System.ComponentModel; using System.Net; using System.Net.Sockets; using System.Text; using System.Threading; namespace Mesnac.DeviceAdapter.HWKC_81600 { public enum RecvState { //HWKC_81600 读取返回数据 01 02 02 00 41 79 88 //HWKC_81600 写入返回数据 01 05 00 05 FF 00 9C 3B WaitingBeginChar_State = 1, //等待接收设备地址 WaitingForFunctionCode_State = 2, //等待接收功能码 WaitingFor_Channel1_State = 3, WaitingFor_Channel2_State = 4, WaitingForData1_State = 5, WaitingForAddr_State = 6, WaitingForXor1_State = 7, WaitingForXor2_State = 8, }; class BgTcpClient : ICommunicateService { RecvState enumRecvState = RecvState.WaitingBeginChar_State; int m_iPosition = 0; UInt16 m_iFullMessageLength = 0; byte m_iVerify = 0; byte[] m_szFullMessage = new byte[1024]; //此数组用于状态机 HWKC_81600Adapter m_HWKC_81600Adapter = null; private BackgroundWorker m_bgwReceive = new BackgroundWorker(); private BackgroundWorker m_bgwDeal = new BackgroundWorker(); private string m_FsIP = ""; private Int32 m_FnPort = 0; private Socket m_ClientSock = null; private ArrayList m_FrecvData = new ArrayList(); private Semaphore m_Fsem = new Semaphore(0, 100000); private ManualResetEvent Exitevent = new ManualResetEvent(false); //接收线程 private void bgwReceive_DoWork(object sender, DoWorkEventArgs e) { //LogService.Instance.Debug("HWKC_81600 进入 bgwReceive_DoWork 线程函数:"); int nPackLen = 1024; byte[] buff = new byte[nPackLen]; while (true) { try { if (m_ClientSock != null && m_ClientSock.Connected) { int nCount = m_ClientSock.Receive(buff, nPackLen, 0); if (nCount > 0) { //if (buff[0] != 0X01 && buff[1] != 0X04 && buff[2]!= 00 && buff[3] != 0X05) //{ m_HWKC_81600Adapter.LogInfo.Info("方法:bgwReceive_DoWork,HWKC_81600设备:" + m_FsIP + ":" + m_FnPort + "接收原始报文:" + bytesToHexStr(buff, nCount)); //} PareReceiveData(buff, nCount); //调用状态机函数 continue; } else //接收错误 { if (m_ClientSock != null) { m_ClientSock.Close(); m_ClientSock = null; } e.Cancel = true; m_Fsem.Release(); } } else { e.Cancel = true; if (m_ClientSock != null) { m_ClientSock.Close(); m_ClientSock = null; } m_Fsem.Release(); return; } Thread.Sleep(10); } catch (Exception ex) { e.Cancel = true; if (m_ClientSock != null) { m_ClientSock.Close(); m_ClientSock = null; } m_HWKC_81600Adapter.LogInfo.Info("Socket接收数据线程退出" + ex.ToString()); m_Fsem.Release(); return; } if (this.m_bgwReceive.CancellationPending) { e.Cancel = true; if (m_ClientSock != null) { m_ClientSock.Close(); m_ClientSock = null; } m_Fsem.Release(); return; } } } //发送线程(包括接收后的处理) private void bgwDeal_DoWork(object sender, DoWorkEventArgs e) { //LogService.Instance.Debug("HWKC_81600 进入 bgwDeal_DoWork 线程:"); while (true) { try { m_Fsem.WaitOne(); lock (m_FrecvData) { if (m_FrecvData.Count > 0) { byte[] buff = (byte[])m_FrecvData[0]; if (m_HWKC_81600Adapter != null) { m_HWKC_81600Adapter.Device_DealValidPack(buff); //处理函数 } m_FrecvData.RemoveAt(0); } } if (Exitevent.WaitOne(0, false)) { e.Cancel = true; m_HWKC_81600Adapter.LogInfo.Info("Socket处理数据线程正常退出"); Exitevent.Reset(); return; } Thread.Sleep(10); } catch (Exception ex) { e.Cancel = true; m_HWKC_81600Adapter.LogInfo.Info("Socket处理数据异常: " + ex.ToString()); return; } if (this.m_bgwDeal.CancellationPending) { m_HWKC_81600Adapter.LogInfo.Info("Socket处理数据线程异常退出"); e.Cancel = true; return; } } } //发送函数 public bool SendMessage(MessagePack pMessagePack) { UInt16 iPos = 0; byte[] u16byte = new byte[2]; byte[] m_iVerify = new byte[2]; try { if (pMessagePack.m_FunctionCode == 0x07 || pMessagePack.m_FunctionCode == 0x09) { byte[] SendBuffer = new byte[10]; SendBuffer[iPos] = pMessagePack.m_BeginChar; //起始字符1 iPos += 1; SendBuffer[iPos] = pMessagePack.m_FunctionCode; //报文长度 iPos += 1; SendBuffer[iPos] = pMessagePack.m_Channel1; //命令码 iPos += 1; SendBuffer[iPos] = pMessagePack.m_Channel2; //通道号 iPos += 1; SendBuffer[iPos] = pMessagePack.m_Data1[0]; //数据位1 iPos += 1; SendBuffer[iPos] = pMessagePack.m_Data1[1]; //数据位1 iPos += 1; SendBuffer[iPos] = pMessagePack.m_Data2[0]; //数据位2 iPos += 1; SendBuffer[iPos] = pMessagePack.m_Data2[1]; //数据位2 iPos += 1; pMessagePack.m_CRC = StringChange.ToModbus(SendBuffer, 8); SendBuffer[iPos] = pMessagePack.m_CRC[0]; //校验码低位在前 iPos += 1; SendBuffer[iPos] = pMessagePack.m_CRC[1]; //校验码高位在后 //if (SendBuffer[0] != 0X01 && SendBuffer[1] != 0X04 && SendBuffer[2] != 00 && SendBuffer[3] != 0X05) //{ m_HWKC_81600Adapter.LogInfo.Info("方法:SendMessage,HWKC_81600设备:" + m_FsIP + ":" + m_FnPort + "发送原始报文:" + bytesToHexStr(SendBuffer, 10)); //} int nCount = m_ClientSock.Send(SendBuffer, SendBuffer.Length, SocketFlags.None); if (nCount > 0) //发送成功 { //LogService.Instance.Info("m_ClientSock.Send函数发送成功"); return true; } else { m_HWKC_81600Adapter.LogInfo.Info("方法:SendMessage,连接已断开,数据发送失败"); return false; } } else if (pMessagePack.m_FunctionCode == 0x83) { byte[] SendBuffer = new byte[7]; SendBuffer[iPos] = pMessagePack.m_BeginChar; //起始字符1 iPos += 1; SendBuffer[iPos] = pMessagePack.m_FunctionCode; //报文长度 iPos += 1; SendBuffer[iPos] = pMessagePack.m_Channel1; //命令码 iPos += 1; SendBuffer[iPos] = pMessagePack.m_Channel2; //通道号 iPos += 1; SendBuffer[iPos] = pMessagePack.m_Data1[0]; //数据位1 iPos += 1; pMessagePack.m_CRC = StringChange.ToModbus(SendBuffer, 5); SendBuffer[iPos] = pMessagePack.m_CRC[0]; //校验码低位在前 iPos += 1; SendBuffer[iPos] = pMessagePack.m_CRC[1]; //校验码高位在后 m_HWKC_81600Adapter.LogInfo.Info("方法:SendMessage,HWKC_81600设备:" + m_FsIP + ":" + m_FnPort + "发送原始报文:" + bytesToHexStr(SendBuffer, 7)); int nCount = m_ClientSock.Send(SendBuffer, SendBuffer.Length, SocketFlags.None); if (nCount > 0) //发送成功 { //LogService.Instance.Info("m_ClientSock.Send函数发送成功"); return true; } else { m_HWKC_81600Adapter.LogInfo.Info("方法:SendMessage,连接已断开,数据发送失败"); return false; } } else { byte[] SendBuffer = new byte[8]; SendBuffer[iPos] = pMessagePack.m_BeginChar; //起始字符1 iPos += 1; SendBuffer[iPos] = pMessagePack.m_FunctionCode; //报文长度 iPos += 1; SendBuffer[iPos] = pMessagePack.m_Channel1; //命令码 iPos += 1; SendBuffer[iPos] = pMessagePack.m_Channel2; //通道号 iPos += 1; SendBuffer[iPos] = pMessagePack.m_Data1[0]; //数据位1 iPos += 1; SendBuffer[iPos] = pMessagePack.m_Data2[0]; //数据位2 iPos += 1; pMessagePack.m_CRC = StringChange.ToModbus(SendBuffer, 6); SendBuffer[iPos] = pMessagePack.m_CRC[0]; //校验码低位在前 iPos += 1; SendBuffer[iPos] = pMessagePack.m_CRC[1]; //校验码高位在后 m_HWKC_81600Adapter.LogInfo.Info("方法:SendMessage,HWKC_81600设备:" + m_FsIP + ":" + m_FnPort + "发送原始报文:" + bytesToHexStr(SendBuffer, 8)); int nCount = m_ClientSock.Send(SendBuffer, SendBuffer.Length, SocketFlags.None); if (nCount > 0) //发送成功 { //LogService.Instance.Info("m_ClientSock.Send函数发送成功"); return true; } else { m_HWKC_81600Adapter.LogInfo.Info("方法:SendMessage,连接已断开,数据发送失败"); return false; } } } catch (Exception ex) { m_HWKC_81600Adapter.LogInfo.Info("方法:SendMessage,HWKC_81600设备:" + m_FsIP + ":" + m_FnPort + "发送报文失败,请检查网络连接!"); return false; } } #region 初始化一套函数 public bool Connect() { //连接 try { Exitevent.Reset(); if (m_FsIP == "" || m_FnPort == 0) { m_HWKC_81600Adapter.LogInfo.Info("IP和端口号不能为空,连接失败"); return false; } if (m_ClientSock != null && GetState()) { //LogService.Instance.Debug("已经连接了"); return true; } m_ClientSock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPEndPoint iep = new IPEndPoint(IPAddress.Parse(m_FsIP), m_FnPort); m_ClientSock.Connect(iep); if (m_ClientSock.Connected) { try { //启动接收线程 m_bgwReceive.DoWork += new DoWorkEventHandler(bgwReceive_DoWork); m_bgwReceive.RunWorkerAsync(); //启动处理线程 m_bgwDeal.DoWork += new DoWorkEventHandler(bgwDeal_DoWork); m_bgwDeal.RunWorkerAsync(); return true; } catch (Exception ex) { m_HWKC_81600Adapter.LogInfo.Info("创建后台线程异常 " + ex.ToString()); return true; } } else { return false; } } catch (Exception ex) { //LogService.Instance.Info("Socket连接异常 " + ex.ToString()); m_HWKC_81600Adapter.LogInfo.Info("IP:" + m_FsIP + ",端口号:" + m_FnPort + ",Socket连接异常!"); return false; } } public bool DisConnect() { try { Exitevent.Set(); Thread.Sleep(100); m_Fsem.Release(); if (m_ClientSock != null) { m_ClientSock.Disconnect(false); m_ClientSock.Close(); m_ClientSock = null; } return true; } catch (Exception ex) { m_HWKC_81600Adapter.LogInfo.Info("Socket连接异常 " + ex.ToString()); return false; } } public bool GetState() { bool bResult = false; bool blockingState = false; try { if (m_ClientSock != null) { blockingState = m_ClientSock.Blocking; byte[] tmp = new byte[1]; m_ClientSock.Blocking = false; m_ClientSock.Send(tmp, 0, 0); bResult = true; Console.WriteLine("Connected!"); } else { bResult = false; } } catch (SocketException e) { // 10035 == WSAEWOULDBLOCK if (e.NativeErrorCode.Equals(10035)) { bResult = true; Console.WriteLine("Still Connected, but the Send would block"); } else { bResult = false; Console.WriteLine("Disconnected: error code {0}!", e.NativeErrorCode); } } finally { if (m_ClientSock != null) { m_ClientSock.Blocking = blockingState; } } return bResult; } public void Init(string strIp, int iPort, object objetcter) { Exitevent.Reset(); m_FsIP = strIp; m_FnPort = iPort; m_HWKC_81600Adapter = objetcter as HWKC_81600Adapter; } #endregion //状态机函数 public void PareReceiveData(byte[] buffer, int iLen) { Array.Clear(m_szFullMessage, 0, 1024);//清空为0 switch (buffer[1]) { case 0X02://读取DI状态 Deal_ReadDI(buffer, iLen); break; case 0X03://IO自报数据 Deal_IdentifyData(buffer, iLen); break; case 0X04://心跳包 Deal_HeartPack(buffer, iLen); break; case 0X05://写入单个DO Deal_WriteDO(buffer, iLen); break; case 0X07://写入DO保持一段时间后自动关闭 Deal_WriteDOtoTime(buffer, iLen); break; case 0X09://写入DO并闪亮 Deal_WriteDOBulingBuling(buffer, iLen); break; } } private void Deal_WriteDOBulingBuling(byte[] buffer, int iLen) { Array.Copy(buffer, 0, m_szFullMessage, 0, iLen); lock (m_FrecvData) { m_FrecvData.Add(m_szFullMessage); } m_Fsem.Release(); } private void Deal_WriteDOtoTime(byte[] buffer, int iLen) { Array.Copy(buffer, 0, m_szFullMessage, 0, iLen); lock (m_FrecvData) { m_FrecvData.Add(m_szFullMessage); } m_Fsem.Release(); } private void Deal_WriteDO(byte[] buffer, int iLen) { Array.Copy(buffer, 0, m_szFullMessage, 0, iLen); lock (m_FrecvData) { m_FrecvData.Add(m_szFullMessage); } m_Fsem.Release(); } private void Deal_ReadDI(byte[] buffer, int iLen) { Array.Copy(buffer, 0, m_szFullMessage, 0, iLen); lock (m_FrecvData) { m_FrecvData.Add(m_szFullMessage); } m_Fsem.Release(); } private void Deal_IdentifyData(byte[] buffer, int iLen) { Array.Copy(buffer, 0, m_szFullMessage, 0, iLen); lock (m_FrecvData) { m_FrecvData.Add(m_szFullMessage); } m_Fsem.Release(); } private void Deal_HeartPack(byte[] buffer, int iLen) { Array.Copy(buffer, 0, m_szFullMessage, 0, iLen); lock (m_FrecvData) { m_FrecvData.Add(m_szFullMessage); } m_Fsem.Release(); } #region add by baogq 2019年11月22日 15:06:26 //public void PareReceiveData(byte[] buffer, int iLen) //{ // //LogService.Instance.Debug("HWKC_81600进入状态机:"); // for (int i = 0; i < iLen; i++) // { // switch (enumRecvState) // { // case RecvState.WaitingBeginChar_State: //开始接受数据帧1 0x01 // //LogService.Instance.Debug("HWKC_81600等待接收帧同步字符WaitingBeginChar_State:0X01" + buffer[i]); // Array.Clear(m_szFullMessage, 0, 1024);//清空为0 // //LogService.Instance.Debug("Buffer数据为: " + StringChange.bytesToHexStr(buffer, buffer.Length)); // m_szFullMessage[m_iPosition] = buffer[i]; // m_iPosition++; // enumRecvState = RecvState.WaitingForFunctionCode_State; // break; // case RecvState.WaitingForFunctionCode_State: //开始接受功能码 0x03 // //LogService.Instance.Debug("HWKC_81600等待接收帧同步字符WaitingForFunctionCode_State:0X03" + buffer[i]); // if (buffer[i] == 0x07 || buffer[i] == 0x09) // { // Array.Copy(buffer, 1, m_szFullMessage, 1, 8); // m_iPosition = 9; // i = 8; // enumRecvState = RecvState.WaitingForXor2_State; // } // else // { // m_szFullMessage[m_iPosition] = buffer[i]; // m_iPosition++; // enumRecvState = RecvState.WaitingForAddr_State; // } // //if (buffer[i] == 0x03) //自动获取DI1-DI8的触发状态 // //{ // // m_szFullMessage[m_iPosition] = buffer[i]; // // m_iPosition++; // // enumRecvState = RecvState.WaitingForAddr_State; // //} // //else if(buffer[i] == 0x05) //获取DO1-DO8的触发状态 // //{ // // m_szFullMessage[m_iPosition] = buffer[i]; // // m_iPosition++; // // enumRecvState = RecvState.WaitingForAddr_State; // //} // break; // case RecvState.WaitingForAddr_State: //开始接收高位寄存器地址 // //LogService.Instance.Debug("HWKC_81600等待接收帧同步字符WaitingForAddr_State:" + buffer[i]); // if (buffer[i] == 0x02) // { // m_szFullMessage[m_iPosition] = buffer[i]; // m_iPosition++; // enumRecvState = RecvState.WaitingFor_Channel2_State; // } // else // { // m_szFullMessage[m_iPosition] = buffer[i]; // m_iPosition++; // enumRecvState = RecvState.WaitingFor_Channel1_State; // } // break; // case RecvState.WaitingFor_Channel1_State: //开始接受通道号1-8 // //LogService.Instance.Debug("HWKC_81600等待接收帧同步字符WaitingFor_Channel1_State:" + buffer[i]); // m_szFullMessage[m_iPosition] = buffer[i]; // m_iPosition++; // enumRecvState = RecvState.WaitingFor_Channel2_State; // break; // case RecvState.WaitingFor_Channel2_State: //开始接受触发类型:FF、00 // //LogService.Instance.Debug("HWKC_81600等待接收帧同步字符WaitingFor_Channel2_State:" + buffer[i]); // m_szFullMessage[m_iPosition] = buffer[i]; // m_iPosition++; // enumRecvState = RecvState.WaitingForData1_State; // break; // case RecvState.WaitingForData1_State: //开始接受触发类型:FF、00 // //LogService.Instance.Debug("HWKC_81600等待接收帧同步字符WaitingForData1_State:" + buffer[i]); // m_szFullMessage[m_iPosition] = buffer[i]; // m_iPosition++; // enumRecvState = RecvState.WaitingForXor1_State; // break; // case RecvState.WaitingForXor1_State: //开始接收CRC低校验位 // m_szFullMessage[m_iPosition] = buffer[i]; // m_iPosition++; // enumRecvState = RecvState.WaitingForXor2_State; // break; // case RecvState.WaitingForXor2_State: //开始比对校验位 Rfly160 // byte[] CRCbuffer = new byte[2]; //此数组用于存放高低校验位 // byte[] m_CRCVerify = new byte[1024]; //此数组用于校验位计算 // byte[] CRC = new byte[2]; // Array.Clear(m_CRCVerify, 0, m_CRCVerify.Length); // Array.Clear(CRCbuffer, 0, CRCbuffer.Length); // m_szFullMessage[m_iPosition] = buffer[i]; // //if (buffer[1] == 0x03) // //{ // // Array.Copy(m_szFullMessage, 0, m_CRCVerify, 0, 5); //校验位计算是从设备地址开始到触发类型结束 // // Array.Copy(m_szFullMessage, 5, CRCbuffer, 0, 2); //将高低校验位存放到比对数组中 // // CRC = StringChange.ToModbus(m_CRCVerify, 5); // //} // if (buffer[1] == 0x05) // { // Array.Copy(m_szFullMessage, 0, m_CRCVerify, 0, 6); //校验位计算是从设备地址开始到触发类型结束 // Array.Copy(m_szFullMessage, 6, CRCbuffer, 0, 2); //将高低校验位存放到比对数组中 // CRC = StringChange.ToModbus(m_CRCVerify, 6); // } // else if (buffer[1] == 0x07 || buffer[1] == 0x09) //0x07设置DO闭合,带时间; 0x09控制 单个 输出 翻转 时间 // { // Array.Copy(m_szFullMessage, 0, m_CRCVerify, 0, 8); //校验位计算是从设备地址开始到触发类型结束 // Array.Copy(m_szFullMessage, 8, CRCbuffer, 0, 2); //将高低校验位存放到比对数组中 // CRC = StringChange.ToModbus(m_CRCVerify, 8); // } // else // { // Array.Copy(m_szFullMessage, 0, m_CRCVerify, 0, 5); //校验位计算是从设备地址开始到触发类型结束 // Array.Copy(m_szFullMessage, 5, CRCbuffer, 0, 2); //将高低校验位存放到比对数组中 // CRC = StringChange.ToModbus(m_CRCVerify, 5); // } // if (CRCbuffer[0] == CRC[0] && CRCbuffer[1] == CRC[1])//校验 // { // //LogService.Instance.Debug("HWKC_81600准备发送"); // lock (m_FrecvData) // { // m_FrecvData.Add(m_szFullMessage); // m_Fsem.Release(); // } // } // m_iFullMessageLength = 0; // m_iPosition = 0; // enumRecvState = RecvState.WaitingBeginChar_State; // //LogService.Instance.Debug("HWKC_81600状态机结束。"); // break; // } // } //} #endregion //CRC异或校验 public byte CalculateVerify(byte[] pMessage, int iLength) { UInt16 i; byte iVerify = 0; iVerify = pMessage[0]; for (i = 1; i < iLength; i++) { iVerify = (byte)(iVerify ^ pMessage[i]); } return iVerify; } private byte[] Swap16Bytes(byte[] OldU16) { byte[] ReturnBytes = new byte[2]; ReturnBytes[1] = OldU16[0]; ReturnBytes[0] = OldU16[1]; return ReturnBytes; } public static string bytesToHexStr(byte[] bytes, int iLen) { StringBuilder sb = new StringBuilder(); if (bytes != null) { for (int i = 0; i < iLen; i++) { sb.Append(bytes[i].ToString("X2")); } } return sb.ToString(); } } }