You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

699 lines
28 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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_DoWorkHWKC_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("方法SendMessageHWKC_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("方法SendMessageHWKC_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("方法SendMessageHWKC_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("方法SendMessageHWKC_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();
}
}
}