#region MC协议
/// <summary>
/// MC协议
/// </summary>
public class MCClient
{
#region 对象
/*定义连接的Socket*/
Socket ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //---通讯的socket
/*定义socket线程*/
Thread receiveTh; //-----------------------接收socket线程
#endregion
#region 事件
public del LogInfoDisplay; //-------------------委托变量-信息显示
public Action<long[]> returnReceiveEvent; //------接收返回数据事件
#endregion
#region 变量
/*运行中的状态*/
string nameClient; //--------------------------客户端名称
public bool connecte; //-----------------------连接状态
public InfoMsg info = new InfoMsg("", ""); //---显示信息
public bool isWriteSuccess; //-----------------写入成功
public bool isReadSuccess; //------------------读取成功
public bool debugDisplay; //-------------------调试信息显示:true.显示;false.不显示;
public bool isWriteHandshake; //---------------写入握手信号:true.写入有握手信号;false.写入没有握手信号;
/*数据*/
int readType; //-------读取类型:1.按8位读取;2.按16位读取;4按32位读取;
string[] readStr; //---读取数据string类型
long[] readData; //----读取数据long类型
/*时间*/
DateTime startTime, stopTime;
DateTime stopTime1, stopTime2;
#endregion
#region 客户端初始化
/// <summary>
/// 客户端初始化
/// </summary>
/// <param name="name">客户端名称</param>
/// <param name="receiveData">接收数据事件</param>
/// <param name="info">消息显示事件</param>
public void Initial(string name = "客户端", Action<long[]> receiveData = null, del info = null)
{
nameClient = name; //-------------------客户端名称
returnReceiveEvent += receiveData; //---接收数据事件
LogInfoDisplay += info; //--------------消息事件
this.info.msgType = nameClient; //---log消息类型
}
#endregion
#region 断开连接
/*关闭客户端*/
/// <summary>
/// 断开连接
/// </summary>
public void Disconnect()
{
try
{
if (ClientSocket != null)
{
if (ClientSocket.Connected == true)
{
ClientSocket.Close();
ClientSocket.Dispose();
connecte = false; //---连接成功
info.msg = "Socket连接关闭成功!";
if (LogInfoDisplay != null) //------判断委托不为空时执行委托
LogInfoDisplay(info);
}
else
{
info.msg = "Socket连接不存在!";
if (LogInfoDisplay != null) //------判断委托不为空时执行委托
LogInfoDisplay(info);
}
}
}
catch { }
try
{
if (receiveTh != null)
{
if (receiveTh.IsAlive == true)
{
ClientSocket.Close();
receiveTh.Abort(); //-----------------------接收socket线程关闭
receiveTh.DisableComObjectEagerCleanup();
connecte = false; //---连接成功
info.msg = "客户端关闭成功";
if (LogInfoDisplay != null) //------判断委托不为空时执行委托
LogInfoDisplay(info);
}
else
{
info.msg = "客户端不存在!";
if (LogInfoDisplay != null) //------判断委托不为空时执行委托
LogInfoDisplay(info);
}
}
}
catch { }
Thread.Sleep(100);
}
#endregion
#region 连接的Socket
/*连接的Socket*/
/// <summary>
/// 连接的Socket
/// </summary>
/// <param name="IP">IP地址</param>
/// <param name="Port">端口号</param>
public void Connection(string IP, string Port)
{
try
{
IPAddress ip = IPAddress.Parse(IP.Trim());
IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(Port.Trim()));
if (ClientSocket != null)
{
ClientSocket.Dispose();
}
Disconnect();
ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
ClientSocket.Connect(point);
connecte = true; //---连接成功
info.msgType = nameClient;
info.msg = "连接成功";
if (LogInfoDisplay != null) //------判断委托不为空时执行委托
LogInfoDisplay(info);
/*开启一个新线程负责不停的接收服务器发过来的数据*/
if (receiveTh == null)
{
receiveTh = new Thread(Receive); //-----------------------接收socket线程
receiveTh.IsBackground = true;
receiveTh.Start();
}
else
{
if (receiveTh.IsAlive != true)
{
receiveTh = new Thread(Receive); //-----------------------接收socket线程
receiveTh.IsBackground = true;
receiveTh.Start();
}
}
}
catch { }
}
#endregion
#region MC读取命令固定格式
/// <summary>
/// MC读取命令固定格式
/// </summary>
/// <param name="addr">地址</param>
/// <param name="length">读取数据长度</param>
/// <param name="type">读取类型:1.按8位读取;2.按16位读取;4按32位读取;</param>
public void CommandRead(string addr, int length, int type = 2)
{
#region 读取命令说明
/*
* buffer[0] = 0x50; 网络副标题L--固定值
* buffer[1] = 0x00; 网络副标题H--固定值
* buffer[2] = 0x00; 网络编号--固定值
* buffer[3] = 0xFF; PLC编号--固定值
* buffer[4] = 0xFF; 目标模块IO编号L--固定值
* buffer[5] = 0x03; 目标模块IO编号H--固定值
* buffer[6] = 0x00; 模块站编号--固定值
* buffer[7] = 0x0C; 请求数据长度L
* buffer[8] = 0x00; 请求数据长度H
* buffer[9] = 0x01; 时钟L //---(cpu监视定时器) : 表示等待PLC响应的timeout时间;这里 值是0010,十进制是16 ;相当与最大等待时间250ms*16=4秒;实际上PLC一般2,3个毫秒内就响应了;
* buffer[10] = 0x00; 时钟H
* buffer[11] = 0x01; 命令L
* buffer[12] = 0x04; 命令H
* buffer[13] = 0x00; 子命令L //---00 00 (子命令) : 值是0表示按字读取(1个字=16位),如果值是1就按位读取;
* buffer[14] = 0x64; 子命令H
* buffer[15] = 0x00; 首地址
* buffer[16] = 0x00; 首地址
* buffer[17] = 0x00; 首地址
* buffer[18] = 0xA8; 软元件 0xA8-D;0x90-M;0x9C-X;0x9D-Y
* buffer[19] = 0x01; 读取数据长度L
* buffer[20] = 0x00; 读取数据长度H
*/
#endregion
startTime = DateTime.Now; //---读取开始时间
byte[] addrBuffer = MCReadDecode(addr);
readType = type; //------读取类型:1.按8位读取;2.按16位读取;4按32位读取;
/*BIN指令*/
byte[] buffer = new byte[256];
buffer[0] = 0x50; /*网络副标题L--固定值*/
buffer[1] = 0x00; /*网络副标题H--固定值*/
buffer[2] = 0x00; /*网络编号--固定值*/
buffer[3] = 0xFF; /*PLC编号--固定值*/
buffer[4] = 0xFF; /*目标模块IO编号L--固定值*/
buffer[5] = 0x03; /*目标模块IO编号H--固定值*/
buffer[6] = 0x00; /*模块站编号--固定值*/
buffer[7] = 0x0C; /*请求数据长度L*/
buffer[8] = 0x00; /*请求数据长度H*/
buffer[9] = 0x01; /*时钟L*/ //---(cpu监视定时器) : 表示等待PLC响应的timeout时间;这里 值是0010,十进制是16 ;相当与最大等待时间250ms*16=4秒;实际上PLC一般2,3个毫秒内就响应了;
buffer[10] = 0x00; /*时钟H*/
buffer[11] = 0x01; /*命令L*/
buffer[12] = 0x04; /*命令H*/
buffer[13] = addrBuffer[4]; /*子命令L*/ //---00 00 (子命令) : 值是0表示按字读取(1个字=16位),如果值是1就按位读取;
buffer[14] = 0x00; /*子命令H*/
buffer[15] = addrBuffer[0]; /*首地址*/
buffer[16] = addrBuffer[1]; /*首地址*/
buffer[17] = addrBuffer[2]; /*首地址*/
buffer[18] = addrBuffer[3]; /*软元件 0xA8-D;0x90-M;0x9C-X;0x9D-Y*/
buffer[19] = (byte)length; /*读取数据长度L*/
buffer[20] = 0x00; /*读取数据长度H*/
try
{
int r = ClientSocket.Send(buffer, buffer.Length, 0);
isReadSuccess = false; //---接收完成
}
catch { isReadSuccess = false; } //---发送完成
#region 调试信息显示
if (debugDisplay) //---调试信息显示
{
stopTime1 = DateTime.Now; //------读取发送指令时间
info.msg = "发送指令时间(毫秒):" + stopTime1.Subtract(startTime).TotalMilliseconds;
if (LogInfoDisplay != null) //------判断委托不为空时执行委托
LogInfoDisplay(info);
}
#endregion
}
#endregion
#region MC写入命令固定格式
/// <summary>
/// MC写入命令固定格式
/// </summary>
/// <param name="addr">地址</param>
/// <param name="data">写入数据数组</param>
/// <param name="length">写入数据长度</param>
/// <param name="type">写入类型:0.按字节写入(8位写入);1.按字写入(16位写入);2.按双字写入(32位写入);</param>
public void CommandWrite(string addr, string[] data, int length, ushort type = 1)
{
#region BIN指令屏蔽
/*BIN指令*/
//byte[] buffer = new byte[255];
//buffer[0] = 0x50; /*网络副标题L--固定值*/
//buffer[1] = 0x00; /*网络副标题H--固定值*/
//buffer[2] = 0x00; /*网络编号--固定值*/
//buffer[3] = 0xFF; /*PLC编号--固定值*/
//buffer[4] = 0xFF; /*目标模块IO编号--固定值L*/
//buffer[5] = 0x03; /*目标模块IO编号H--固定值*/
//buffer[6] = 0x00; /*模块站编号--固定值*/
//buffer[7] = 0x0E; /*请求数据长度L*/
//buffer[8] = 0x00; /*请求数据长度H*/
//buffer[9] = 0x01; /*时钟L*/
//buffer[10] = 0x00; /*时钟H*/
//buffer[11] = 0x01; /*命令L*/
//buffer[12] = 0x14; /*命令H*/
////buffer[13] = addrBuffer[4]; /*子命令L*/
//buffer[13] = 0x00; /*子命令L*/
//buffer[14] = 0x00; /*子命令H*/
//buffer[15] = addrBuffer[0]; /*首地址LL*/
//buffer[16] = addrBuffer[1]; /*首地址L*/
//buffer[17] = addrBuffer[2]; /*首地址H*/
//buffer[18] = addrBuffer[3]; /*软元件 0xA8-D;0x90-M;0x0C-X;0x9D-Y*/
//buffer[19] = 0x01; /*数据长度L*/
//buffer[20] = 0x00; /*数据长度H*/
//buffer[21] = dataBuffer[0]; /*写入第一个数据L*/
//buffer[22] = dataBuffer[1]; /*写入第一个数据H*/
////buffer[21] = 0x7B; /*写入第二个数据L*/
////buffer[22] = 0x01; /*写入第二个数据H*/
#endregion
isWriteSuccess = false; //---发送完成
byte[] buffer = MCWriteDecode(addr, data, (short)length, type);
int r = ClientSocket.Send(buffer, buffer.Length, 0);
if (!isWriteHandshake) //---写入握手信号
isWriteSuccess = true; //---写入成功标志
}
#endregion
#region MC读取命令解析
/// <summary>
/// MC读取命令解析
/// </summary>
/// <param name="addr">读取数据长度</param>
/// <returns>指令数组</returns>
private byte[] MCReadDecode(string addr)
{
/*MC读取命令固定格式
addrBuffer[0]-----地址HH
addrBuffer[1]-----地址H
addrBuffer[2]-----地址L
addrBuffer[3]-----软件件
addrBuffer[4]-----子指令L
*/
char[] addrChar = addr.ToArray();
string addrStr = "";
byte[] addrBuffer = new byte[5];
try
{
for (int i = 1; i < addrChar.Length; i++)
{
addrStr += addrChar[i];
}
//int addrInt = Convert.ToInt32(addrStr);
int addrInt = int.Parse(addrStr);
string addrStr2 = addrInt.ToString("x");
string addrStr3 = "";
switch (addrStr2.Length)
{
case 1:
addrStr3 = "0" + "0" + "0" + "0" + "0" + addrStr2;
break;
case 2:
addrStr3 = "0" + "0" + "0" + "0" + addrStr2;
break;
case 3:
addrStr3 = "0" + "0" + "0" + addrStr2;
break;
case 4:
addrStr3 = "0" + "0" + addrStr2;
break;
case 5:
addrStr3 = "0" + addrStr2;
break;
}
char[] addrChar2 = addrStr3.ToArray();
addrBuffer[0] = byte.Parse(addrChar2[4].ToString() + addrChar2[5].ToString(), System.Globalization.NumberStyles.HexNumber);
addrBuffer[1] = byte.Parse(addrChar2[2].ToString() + addrChar2[3].ToString(), System.Globalization.NumberStyles.HexNumber);
addrBuffer[2] = byte.Parse(addrChar2[0].ToString() + addrChar2[1].ToString(), System.Globalization.NumberStyles.HexNumber);
if (addrChar[0] == 'D' || addrChar[0] == 'd')
{
addrBuffer[3] = 0xA8;
addrBuffer[4] = 0x00;
}
if (addrChar[0] == 'M' || addrChar[0] == 'm')
{
addrBuffer[3] = 0x90;
addrBuffer[4] = 0x01;
}
if (addrChar[0] == 'X' || addrChar[0] == 'x')
{
addrBuffer[3] = 0x9C;
addrBuffer[4] = 0x01;
}
if (addrChar[0] == 'Y' || addrChar[0] == 'y')
{
addrBuffer[3] = 0x9D;
addrBuffer[4] = 0x01;
}
}
catch { }
return addrBuffer;
}
#endregion
#region MC写入命令解析
/// <summary>
/// MC写入命令解析
/// </summary>
/// <param name="addr">地址</param>
/// <param name="data">写入数据数组</param>
/// <param name="length">写入数据长度</param>
/// <param name="type">写入类型:0.按字节写入(8位写入);1.按字写入(16位写入);2.按双字写入(32位写入);</param>
/// <returns></returns>
private byte[] MCWriteDecode(string addr, string[] data, short length, ushort type)
{
#region 读取命令固定格式
/*读取命令固定格式
* 形参 addr-------地址
* 形参 data-------数据
* 形参 number-----个数
* addrBuffer[0]-----地址HH
* addrBuffer[1]-----地址H
* addrBuffer[2]-----地址L
* addrBuffer[3]-----软元件
* addrBuffer[4]-----子指令L
*/
#endregion
#region MC写入命令固定格式
/*MC写入命令固定格式
* buffer[0] = 0x50 网络副标题L--固定值
* buffer[1] = 0x00; 网络副标题H--固定值
* buffer[2] = 0x00; 网络编号--固定值
* buffer[3] = 0xFF; PLC编号--固定值
* buffer[4] = 0xFF; 目标模块IO编号--固定值L
* buffer[6] = 0x00; 模块站编号--固定值
* buffer[7] = 0x0E; 请求数据长度L
* buffer[8] = 0x00; 请求通讯数据长度H
* buffer[9] = 0x01; 时钟L
* buffer[10] = 0x00; 时钟H
* buffer[11] = 0x01; 命令L
* buffer[12] = 0x14; 命令H
* buffer[13] = 0x00; 子命令L
* buffer[14] = 0x00; 子命令H
* buffer[15] = addrBuffer[0]; 地址LL
* buffer[16] = addrBuffer[1]; 地址L
* buffer[17] = addrBuffer[2]; 地址H
* buffer[18] = 0xA8; 软元件 0xA8-D;0x90-M;0x0C-X;0x9D-Y
* buffer[19] = 0x01; 写入数据长度L
* buffer[20] = 0x00; 写入数据长度H
* buffer[21] = 0x12; 写入第一个数据L
* buffer[22] = 0x11; 写入第一个数据H
* buffer[23] = 0x3; 写入第二个数据L
* buffer[24] = 0x4; 写入第二个数据H
*/
#endregion
#region MC协议数据地址解析
char[] addrChar = addr.ToArray();
string addrStr = "";
byte[] addrBuffer = new byte[5];
for (int i = 1; i < addrChar.Length; i++)
{
addrStr += addrChar[i];
}
int addrInt = int.Parse(addrStr);
string addrStr2 = addrInt.ToString("x");
string addrStr3 = "";
switch (addrStr2.Length)
{
case 1:
addrStr3 = "0" + "0" + "0" + "0" + "0" + addrStr2;
break;
case 2:
addrStr3 = "0" + "0" + "0" + "0" + addrStr2;
break;
case 3:
addrStr3 = "0" + "0" + "0" + addrStr2;
break;
case 4:
addrStr3 = "0" + "0" + addrStr2;
break;
case 5:
addrStr3 = "0" + addrStr2;
break;
}
char[] addrChar2 = addrStr3.ToArray();
addrBuffer[0] = byte.Parse(addrChar2[4].ToString() + addrChar2[5].ToString(), System.Globalization.NumberStyles.HexNumber);
addrBuffer[1] = byte.Parse(addrChar2[2].ToString() + addrChar2[3].ToString(), System.Globalization.NumberStyles.HexNumber);
addrBuffer[2] = byte.Parse(addrChar2[0].ToString() + addrChar2[1].ToString(), System.Globalization.NumberStyles.HexNumber);
#endregion
#region 地址类型解析
if (addrChar[0] == 'D' || addrChar[0] == 'd')
{
addrBuffer[3] = 0xA8;
addrBuffer[4] = 0x00;
}
if (addrChar[0] == 'M' || addrChar[0] == 'm')
{
addrBuffer[3] = 0x90;
addrBuffer[4] = 0x01;
}
if (addrChar[0] == 'X' || addrChar[0] == 'x')
{
addrBuffer[3] = 0x9C;
addrBuffer[4] = 0x01;
}
if (addrChar[0] == 'Y' || addrChar[0] == 'y')
{
addrBuffer[3] = 0x9D;
addrBuffer[4] = 0x01;
}
#endregion
#region MC协议固定值
byte[] buffer = new byte[256];
buffer[0] = 0x50; /*网络副标题L--固定值*/
buffer[1] = 0x00; /*网络副标题H--固定值*/
buffer[2] = 0x00; /*网络编号--固定值*/
buffer[3] = 0xFF; /*PLC编号--固定值*/
buffer[4] = 0xFF; /*目标模块IO编号--固定值L*/
buffer[5] = 0x03; /*目标模块IO编号H--固定值*/
buffer[6] = 0x00; /*模块站编号--固定值*/
#endregion
#region MC协议变动值
if (addrChar[0] == 'D' || addrChar[0] == 'd')
{
byte[] dataBuffer = DataDecode(data, length, type); /*data数据解析*/
/*BIN指令*/
buffer[7] = (byte)(0x0C + 2 * (dataBuffer.Length / 2)); /*数据长度L*/
//buffer[7] = 0x0E; /*应答数据长度L*/
buffer[8] = 0x00; /*应答数据长度H*/
buffer[9] = 0x01; /*时钟L*/
buffer[10] = 0x00; /*时钟H*/
buffer[11] = 0x01; /*命令L*/
buffer[12] = 0x14; /*命令H*/
buffer[13] = 0x00; /*子命令L*/
buffer[14] = 0x00; /*子命令H*/
buffer[15] = addrBuffer[0]; /*起始软元件地址LL*/
buffer[16] = addrBuffer[1]; /*起始软元件地址L*/
buffer[17] = addrBuffer[2]; /*起始软元件地址H*/
buffer[18] = addrBuffer[3]; /*软元件 0xA8-D;0x90-M;0x0C-X;0x9D-Y*/
buffer[19] = (byte)(dataBuffer.Length / 2); /*写入数据长度L*/
buffer[20] = 0x00; /*写入数据长度H*/
//buffer[21] = dataBuffer[0]; /*写入第一个数据L*/
//buffer[22] = dataBuffer[1]; /*写入第一个数据H*/
//buffer[23] = dataBuffer[2]; /*写入第二个数据L*/
//buffer[24] = dataBuffer[3]; /*写入第二个数据H*/
for (int i = 0; i < dataBuffer.Length; i++)
{
buffer[21 + i] = dataBuffer[i]; /*循环写入数据*/
}
}
else
{
byte newData = byte.Parse(data[0]);
buffer[7] = 0x0C; /*数据长度L*/
buffer[8] = 0x00; /*数据长度H*/
buffer[9] = 0x01; /*时钟L*/
buffer[10] = 0x00; /*时钟H*/
buffer[11] = 0x02; /*命令L*/
buffer[12] = 0x14; /*命令H*/
buffer[13] = addrBuffer[4]; /*子命令L*/
buffer[14] = 0x00; /*子命令H*/
buffer[15] = 0x01; /*位访问点数*/
buffer[16] = addrBuffer[0]; /*地址*/
buffer[17] = addrBuffer[1]; /*地址*/
buffer[18] = addrBuffer[2]; /*地址*/
buffer[19] = addrBuffer[3]; /*软元件 0xA8-D;0x90-M;0x0C-X;0x9D-Y*/
buffer[20] = newData; /*数据设置&复位L*/
}
#endregion
return buffer;
}
#endregion
#region Data数据解析
#region Data数据解析
/// <summary>
/// Data数据解析
/// </summary>
/// <param name="data">写入数据数组</param>
/// <param name="length">写入数据长度</param>
/// <param name="type">写入类型:0.按字节写入(8位写入);1.按字写入(16位写入);2.按双字写入(32位写入);</param>
/// <returns></returns>
private byte[] DataDecode(string[] data, short length, ushort type)
{
byte[] dataBuffer = null; //---------返回写入指令数组定义
char[] dataChar = null; //-----------写入数据_字符数组
char[] dataChar2 = null; //----------写入数据_字符数组2
char[] dataChar3 = null; //----------写入数据_字符数组3
string dataStr = ""; //--------------写入数据_字符串
string dataStr2 = ""; //-------------写入数据_字符串2
string dataStr3 = ""; //-------------写入数据_字符串3
string dataStr4 = ""; //-------------写入数据_字符串4
Int32 dataInt32; //------------------写入数据_整数
Int64 dataInt64; //------------------写入数据_整数
switch (type)
{
case 0: //---------------按字节写入(8位写入)
#region 按字节写入(8位写入)
dataBuffer = new byte[length]; //--------返回写入指令数组实例化
for (int i = 0; i < length; i++)
{
dataBuffer[i] = byte.Parse(GetComplementer(data[i], 1), System.Globalization.NumberStyles.HexNumber);
}
#endregion
break;
case 1: //---------------按字写入(16位写入)
#region 按字写入(16位写入)
dataBuffer = new byte[length * 2]; //--------返回写入指令数组实例化
for (int i = 0; i < length; i++)
{
dataChar = GetComplementer(data[i], 2).ToArray(); //-------------写入数据_转化为字符数组
#region 10进制数据转换为字符串
for (int j = 0; j < dataChar.Length; j++)
{
dataStr += dataChar[j]; //---------------写入数据_转化为字符串
}
#endregion
#region 字符串数据转换为16进制
dataInt32 = Convert.ToInt32(dataStr); //-------写入数据_转化为长整形
dataStr2 = dataInt32.ToString("x"); //---------写入数据_转化为字符串2
#endregion
#region 字符长度补齐
dataChar2 = dataStr2.ToArray(); //-----------写入数据_转化为字符数组2
if (dataChar2.Length % 2 == 1)
{
dataStr3 = "0";
for (int j = 0; j < dataChar2.Length; j++)
{
dataStr3 += dataChar2[j]; //---------写入数据_转化为字符串3
}
}
else
{
for (int j = 0; j < dataChar2.Length; j++)
{
dataStr3 += dataChar2[j]; //---------写入数据_转化为字符串3
}
}
#endregion
#region 16进制数据长度补齐
if (dataStr3.Length < 4)
{
for (int j = 0; j < 4 - dataStr3.Length; j++)
{
dataStr4 += "0";
}
}
dataStr4 += dataStr3;
#endregion
#region 16进制数据按MC协议格式排列
/*16进制数据按MC协议格式排列*/
dataChar3 = dataStr4.ToArray();
for (int j = 0; j < dataStr4.Length / 2; j++)
{
dataBuffer[2 * i + j] = byte.Parse(dataChar3[dataStr4.Length - 2 - 2 * j].ToString() +
dataChar3[dataStr4.Length - 1 - 2 * j].ToString(),
System.Globalization.NumberStyles.HexNumber);
}
#endregion
#region 数据清除
dataStr = ""; //--------------写入数据_字符串
dataStr2 = ""; //-------------写入数据_字符串2
dataStr3 = ""; //-------------写入数据_字符串3
dataStr4 = ""; //-------------写入数据_字符串4
#endregion
}
#endregion
break;
case 2: //---------------按双字写入(32位写入)
#region 按双字写入(32位写入)
dataBuffer = new byte[length * 4]; //--------返回写入指令数组实例化
for (int i = 0; i < length; i++)
{
dataChar = GetComplementer(data[i], 4).ToArray(); //-------------写入数据_转化为字符数组
#region 10进制数据转换为字符串
for (int j = 0; j < dataChar.Length; j++)
{
dataStr += dataChar[j]; //---------------写入数据_转化为字符串
}
#endregion
#region 字符串数据转换为16进制
dataInt64 = Convert.ToInt64(dataStr); //-------写入数据_转化为长整形
dataStr2 = dataInt64.ToString("x"); //---------写入数据_转化为字符串2
#endregion
#region 字符长度补齐
dataChar2 = dataStr2.ToArray(); //-----------写入数据_转化为字符数组2
if (dataChar2.Length % 2 == 1)
{
dataStr3 = "0";
for (int j = 0; j < dataChar2.Length; j++)
{
dataStr3 += dataChar2[j]; //---------写入数据_转化为字符串3
}
}
else
{
for (int j = 0; j < dataChar2.Length; j++)
{
dataStr3 += dataChar2[j]; //---------写入数据_转化为字符串3
}
}
#endregion
#region 16进制数据长度补齐
if (dataStr3.Length < 8)
{
for (int j = 0; j < 8 - dataStr3.Length; j++)
{
dataStr4 += "0";
}
}
dataStr4 += dataStr3;
#endregion
#region 16进制数据按MC协议格式排列
/*16进制数据按MC协议格式排列*/
dataChar3 = dataStr4.ToArray();
for (int j = 0; j < dataStr4.Length / 2; j++)
{
dataBuffer[4 * i + j] = byte.Parse(dataChar3[dataStr4.Length - 2 - 2 * j].ToString() +
dataChar3[dataStr4.Length - 1 - 2 * j].ToString(),
System.Globalization.NumberStyles.HexNumber);
}
#endregion
#region 数据清除
dataStr = ""; //--------------写入数据_字符串
dataStr2 = ""; //-------------写入数据_字符串2
dataStr3 = ""; //-------------写入数据_字符串3
dataStr4 = ""; //-------------写入数据_字符串4
#endregion
}
#endregion
break;
}
return dataBuffer;
}
#endregion
#region data数据解析_屏蔽
/// <summary>
/// data数据解析
/// </summary>
/// <param name="data">写入数据数组</param>
/// <param name="length">写入数据长度</param>
/// <param name="type">写入类型:0.按字节写入(8位写入);1.按字写入(16位写入);2.按双字写入(32位写入);</param>
/// <returns></returns>
//private byte[] DataDecode(string[] data, short length, ushort type)
//{
// #region 10进制数据转换为字符串
// /*10进制数据转换为字符串*/
// char[] dataChar = data[0].ToArray();
// string dataStr = "";
// byte[] dataBuffer = new byte[length * 2];
// for (int i = 0; i < dataChar.Length; i++)
// {
// dataStr += dataChar[i];
// }
// #endregion
// #region 字符串数据转换为16进制
// /*字符串数据转换为16进制*/
// long dataInt = Convert.ToInt64(dataStr);
// string dataStr2 = dataInt.ToString("x");
// #endregion
// #region 字符长度补齐
// /*字符长度补齐*/
// string dataStr3 = "";
// char[] dataChar2 = dataStr2.ToArray();
// if (dataChar2.Length % 2 == 1)
// {
// dataStr3 = "0";
// for (int i = 0; i < dataChar2.Length; i++)
// {
// dataStr3 += dataChar2[i];
// }
// }
// else
// {
// for (int i = 0; i < dataChar2.Length; i++)
// {
// dataStr3 += dataChar2[i];
// }
// }
// #endregion
// #region 16进制数据长度补齐
// /*16进制数据长度补齐*/
// string dataStr4 = "";
// for (int i = 0; i < length * 4 - dataStr3.Length; i++)
// {
// dataStr4 += "0";
// }
// #endregion
// #region 16进制数据按MC协议格式排列
// /*16进制数据按MC协议格式排列*/
// dataStr4 += dataStr3;
// char[] dataChar3 = dataStr4.ToArray();
// for (int i = 0; i < dataStr4.Length / 2; i++)
// {
// dataBuffer[i] = byte.Parse(dataChar3[dataStr4.Length - 2 - 2 * i].ToString() +
// dataChar3[dataStr4.Length - 1 - 2 * i].ToString(),
// System.Globalization.NumberStyles.HexNumber);
// }
// #endregion
// return dataBuffer;
//}
#endregion
#region data数据解析备份屏蔽
/*data数据解析备份*/
//private byte[] DataDecode2(string data)
//{
// char[] dataChar = data.ToArray();
// string dataStr = "";
// byte[] dataBuffer = new byte[2];
// for (int i = 0; i < dataChar.Length; i++)
// {
// dataStr += dataChar[i];
// }
// int dataInt = Convert.ToInt32(dataStr);
// string dataStr2 = dataInt.ToString("x");
// string dataStr3 = "";
// switch (dataStr2.Length)
// {
// case 1:
// dataStr3 = "0" + "0" + "0" + dataStr2;
// break;
// case 2:
// dataStr3 = "0" + "0" + dataStr2;
// break;
// case 3:
// dataStr3 = "0" + dataStr2;
// break;
// }
// char[] dataChar2 = dataStr3.ToArray();
// dataBuffer[0] = byte.Parse(dataChar2[2].ToString() + dataChar2[3].ToString(), System.Globalization.NumberStyles.HexNumber);
// dataBuffer[1] = byte.Parse(dataChar2[0].ToString() + dataChar2[1].ToString(), System.Globalization.NumberStyles.HexNumber);
// return dataBuffer;
//}
#endregion
#endregion
#region 负数求补码
/// <summary>
/// 负数求补码string类型
/// </summary>
/// <param name="data">数据</param>
/// <param name="length">长度</param>
/// <returns></returns>
private string GetComplementer(string data, int length)
{
long iData = int.Parse(data);
if (iData < 0)
{
iData = Math.Abs(iData);
switch (length)
{
case 1: //------字节
iData = iData ^ 0xFF;
iData++;
break;
case 2: //------字
iData = iData ^ 0xFFFF;
iData++;
break;
case 4: //------双字
iData = iData ^ 0xFFFFFFFF;
iData++;
break;
}
}
return iData.ToString();
}
/// <summary>
/// 负数求补码long类型
/// </summary>
/// <param name="data">数据</param>
/// <param name="length">长度</param>
/// <returns></returns>
private long GetComplementer(long data, int length)
{
long lData = data;
long mark = 0;
switch (length)
{
case 1:
mark = 0x80;
break;
case 2:
mark = 0x8000;
break;
case 4:
mark = 0x80000000;
break;
}
if (lData > mark)
{
lData = Math.Abs(lData);
switch (length)
{
case 1: //------字节
lData = data ^ 0xFF;
lData++;
break;
case 2: //------字
lData = data ^ 0xFFFF;
lData++;
break;
case 4: //------双字
lData = data ^ 0xFFFFFFFF;
lData++;
break;
}
lData = -lData;
}
return lData;
}
#endregion
#region MC协议数据接收----------开启一个新线程负责不停的接收服务器发过来的数据
/// <summary>
/// MC协议数据接收
/// </summary>
private void Receive()
{
#region 读取返回命令说明
/*
* buffer[0] = D0 网络副标题L--固定值
* buffer[1] = 00 网络副标题H--固定值
* buffer[2] = 00 网络编号--固定值
* buffer[3] = FF PLC编号--固定值
* buffer[4] = FF 目标模块IO编号L--固定值
* buffer[5] = 03 目标模块IO编号H--固定值
* buffer[6] = 00 模块站编号--固定值
* buffer[7] = 06 应答数据长度L
* buffer[8] = 00 应答数据长度H
* buffer[9] = 00 结束代码L //---(结束代码) :可以理解成异常代码,如果正常的话,就是0000
* buffer[10] = 00 结束代码H
* buffer[11] = 00 读取第一个数据L
* buffer[12] = 00 读取第一个数据H
* buffer[13] = 00 读取第二个数据L
* buffer[14] = 00 读取第二个数据H
*/
#endregion
#region 写入返回命令说明
/*
* buffer[0] = D0 网络副标题L--固定值
* buffer[1] = 00 网络副标题H--固定值
* buffer[2] = 00 网络编号--固定值
* buffer[3] = FF PLC编号--固定值
* buffer[4] = FF 目标模块IO编号L--固定值
* buffer[5] = 03 目标模块IO编号H--固定值
* buffer[6] = 00 模块站编号--固定值
* buffer[7] = 02 应答数据长度L
* buffer[8] = 00 应答数据长度H
* buffer[9] = 00 结束代码L
* buffer[10] = 00 结束代码H
*/
#endregion
while (true)
{
try
{
byte[] buffer = new byte[1024];
int r = ClientSocket.Receive(buffer);
long[] dataBuffer = new long[256];
int dataLength = buffer[7] - 2; //---数据长度(buffer[7]:数据长度)
#region 调试信息显示
if (debugDisplay) //---调试信息显示
{
stopTime2 = DateTime.Now;
info.msg = "接收指令时间(毫秒):" + stopTime2.Subtract(stopTime1).TotalMilliseconds;
if (LogInfoDisplay != null) //------判断委托不为空时执行委托
LogInfoDisplay(info);
}
#endregion
/*判断结束代码是:0x0000,正常结束;不是0x0000*/
if (buffer[9] == 0x00 && buffer[10] == 0x00) /*判断结束代码是:0x0000;正常结束*/
{
if (dataLength > 0) /*读取原始数据--(buffer[7]:读取数据长度)*/
{
#region 读取原始数据
/*读取数据命令*/
string[] dataBufferStr = DataBufferDecode(buffer, r);
string dataStr = "";
for (int i = dataLength; i > 0; i--)
{
dataStr += dataBufferStr[11 + i - 1]; /*数据结构:低位在前,高位在后;*/
}
if (debugDisplay) //---调试信息显示
{
info.msg = "读取数据(16进制):" + dataStr + "";
if (LogInfoDisplay != null) //------判断委托不为空时执行委托
LogInfoDisplay(info);
}
readStr = new string[dataLength / readType]; //---读取数据string类型
string[] readStr2 = new string[dataLength / readType]; //--读取数据string类型2
readData = new long[dataLength / readType]; //------读取数据long类型
for (int i = 0; i < dataLength / readType; i++)
{
for (int j = readType; j > 0; j--)
{
readStr[i] += dataBufferStr[11 + readType * i + j - 1];
}
}
#endregion
#region 10进制数据按MC协议格式排列
#region for循环解码---屏蔽
///*16进制数据按MC协议格式排列*/
//string infoStr = null;
//long infoLong = 0;
//int m = 0;
//foreach (var item in readStr)
//{
// char[] dataChar3 = item.ToArray();
// foreach (var cItem in dataChar3)
// {
// readStr2[m] += cItem.ToString();
// }
// readData[m] = int.Parse(readStr2[m],
// System.Globalization.NumberStyles.HexNumber);
// infoStr = readData[m].ToString();
// infoLong = GetComplementer(long.Parse(infoStr), readType);
// state = "读取数据(10进制" + readType + "位):" + infoStr + "; 补码:" + infoLong;
// Infomation(state); /*回调方法---状态显示*/
// m++;
//}
#endregion
#region for循环解码
/*16进制数据按MC协议格式排列*/
string data_decimalStr = null;
long data_decimalLong = 0;
for (int i = 0; i < readStr.Length; i++)
{
char[] dataChar3 = readStr[i].ToArray();
for (int j = 0; j < 2 * readType; j++)
{
readStr2[i] += dataChar3[j].ToString();
}
readData[i] = int.Parse(readStr2[i],
System.Globalization.NumberStyles.HexNumber);
data_decimalStr = readData[i].ToString();
data_decimalLong = GetComplementer(long.Parse(data_decimalStr), readType);
if (debugDisplay) //---调试信息显示
{
info.msg = "读取数据(10进制" + readType + "位):" + data_decimalStr + "; 补码:" + data_decimalLong;
if (LogInfoDisplay != null) //------判断委托不为空时执行委托
LogInfoDisplay(info);
}
}
#endregion
#endregion
#region 接收数据赋值
long[] readData_long = new long[readData.Length + 1];
for (int i = 0; i < readData.Length; i++)
{
readData_long[i] = readData[i];
}
readData_long[readData.Length] = readType;
readData = readData_long;
#endregion
if (returnReceiveEvent != null)
returnReceiveEvent(readData_long); //------接收返回数据事件
//isReceiveSuccess = true; //---接收完成
#region 调试信息显示
if (debugDisplay) //---调试信息显示
{
stopTime = DateTime.Now;
info.msg = "数据解析时间(毫秒):" + stopTime.Subtract(stopTime2).TotalMilliseconds;
if (LogInfoDisplay != null) //------判断委托不为空时执行委托
LogInfoDisplay(info);
info.msg = "读取总时间(毫秒):" + stopTime.Subtract(startTime).TotalMilliseconds;
if (LogInfoDisplay != null) //------判断委托不为空时执行委托
LogInfoDisplay(info);
}
#endregion
}
else /*写入反馈解析*/
{
if (isWriteHandshake) //---写入握手信号
isWriteSuccess = true; //---写入成功标志
#region 写入反馈
if (debugDisplay) //---调试信息显示
{
/*写入反馈*/
string dataStr = buffer[10].ToString("x") + buffer[9].ToString("x");
info.msg = "写入反馈结束代码(16进制):" + dataStr + "";
if (LogInfoDisplay != null) //------判断委托不为空时执行委托
LogInfoDisplay(info);
int dataInt = int.Parse(dataStr, System.Globalization.NumberStyles.HexNumber);
info.msg = "写入反馈结束代码(10进制):" + dataInt + "";
if (LogInfoDisplay != null) //------判断委托不为空时执行委托
LogInfoDisplay(info);
//status = "写入反馈命令:" + newBuffer + "";
//Infomation(status); /*回调方法---状态显示*/
}
#endregion
}
}
else /*判断结束代码不是:0x0000;异常结束*/
{
#region 异常结束
if (debugDisplay) //---调试信息显示
{
string dataStr = buffer[10].ToString("x") + buffer[9].ToString("x");
info.msg = "异常结束(16进制):" + dataStr + "";
if (LogInfoDisplay != null) //------判断委托不为空时执行委托
LogInfoDisplay(info);
int dataInt = int.Parse(dataStr, System.Globalization.NumberStyles.HexNumber);
info.msg = "异常结束(10进制):" + dataInt + "";
if (LogInfoDisplay != null) //------判断委托不为空时执行委托
LogInfoDisplay(info);
}
#endregion
}
}
catch { }
}
}
#endregion
#region 读出数据解码
/// <summary>
/// 读出数据解码
/// </summary>
/// <param name="buffer">反馈命令--type[]数组类型</param>
/// <param name="length">长度</param>
/// <returns>返回命令--16进制string[]数组类型;每位2个数据</returns>
private string[] DataBufferDecode(byte[] buffer, int length = 0)
{
if (length <= 0)
length = buffer.Length;
string[] dataBuffer = new string[length];
for (int i = 0; i < length; i++)
{
if (buffer[i].ToString("x").Length == 1)
{
dataBuffer[i] = "0" + buffer[i].ToString("x");
}
else
{
dataBuffer[i] = buffer[i].ToString("x");
}
}
return dataBuffer;
}
#endregion
#region 获取读取数据
/// <summary>
/// 获取读取数据
/// </summary>
/// <returns>long类型数据</returns>
public long[] GetReceiveData_long()
{
return readData;
}
/// <summary>
/// 获取读取数据
/// </summary>
/// <returns>string类型数据</returns>
public string[] GetReceiveData_string()
{
return readStr;
}
#endregion
}
#endregion
最新发布