using HslCommunication.BasicFramework;
using HslCommunication.Core;
using HslCommunication.Core.IMessage;
using HslCommunication.Core.Net;
using System;
using System.Collections.Generic;
#if !NETSTANDARD2_0
using System.IO.Ports;
#endif
using System.Net.Sockets;
using System.Text;
namespace HslCommunication.Profinet.LSIS
{
///
/// LSisServer
///
public class LSisServer : NetworkDataServerBase
{
#region Constructor
///
/// LSisServer
///
public LSisServer()
{
pBuffer = new SoftBuffer(DataPoolLength);
qBuffer = new SoftBuffer(DataPoolLength);
mBuffer = new SoftBuffer(DataPoolLength);
dBuffer = new SoftBuffer(DataPoolLength);
WordLength = 2;
ByteTransform = new RegularByteTransform();
#if !NETSTANDARD2_0
serialPort = new SerialPort();
#endif
}
#endregion
#region NetworkDataServerBase Override
///
/// 读取自定义的寄存器的值
///
/// 起始地址,示例:"I100","M100"
/// 数据长度
///
/// byte数组值
public override OperateResult Read(string address, ushort length)
{
OperateResult analysis = XGBFastEnet.AnalysisAddress(address, true);
if (!analysis.IsSuccess) return OperateResult.CreateFailedResult(analysis);
int startIndex = CheckAddress(analysis.Content.Substring(3));
switch (analysis.Content[1])
{
case 'P': return OperateResult.CreateSuccessResult(pBuffer.GetBytes(startIndex, length));
case 'Q': return OperateResult.CreateSuccessResult(qBuffer.GetBytes(startIndex, length));
case 'M': return OperateResult.CreateSuccessResult(SoftBasic.BoolArrayToByte(mBuffer.GetBool(startIndex , length *= 8)));
case 'D': return OperateResult.CreateSuccessResult(dBuffer.GetBytes(startIndex==0 ? startIndex : startIndex*=2, length));
default: return new OperateResult(StringResources.Language.NotSupportedDataType);
}
}
///
/// 写入自定义的数据到数据内存中去
///
/// 地址
/// 数据值
/// 是否写入成功的结果对象
public override OperateResult Write(string address, byte[] value)
{
OperateResult analysis = XGBFastEnet.AnalysisAddress(address, false);
if (!analysis.IsSuccess) return OperateResult.CreateFailedResult(analysis);
int startIndex = CheckAddress(analysis.Content.Substring(3));
switch (analysis.Content[1])
{
case 'P': pBuffer.SetBytes(value, startIndex); return OperateResult.CreateSuccessResult();
case 'Q': qBuffer.SetBytes(value, startIndex); return OperateResult.CreateSuccessResult();
case 'M': mBuffer.SetBool(value[0]==1 ? true:false, startIndex); return OperateResult.CreateSuccessResult();
case 'D': dBuffer.SetBytes(value, startIndex == 0 ? startIndex : startIndex *= 2); return OperateResult.CreateSuccessResult();
default: return new OperateResult(StringResources.Language.NotSupportedDataType);
}
}
#endregion
#region Byte Read Write Operate
///
/// 读取指定地址的字节数据
///
/// 西门子的地址信息
/// 带有成功标志的结果对象
public OperateResult ReadByte(string address)
{
OperateResult read = Read(address, 2);
if (!read.IsSuccess) return OperateResult.CreateFailedResult(read);
return OperateResult.CreateSuccessResult(read.Content[0]);
}
///
/// 将byte数据信息写入到指定的地址当中
///
/// 西门子的地址信息
/// 字节数据信息
/// 是否成功的结果
public OperateResult Write(string address, byte value)
{
return Write(address, new byte[] { value });
}
#endregion
#region Bool Read Write Operate
///
/// 读取指定地址的bool数据对象
///
/// 西门子的地址信息
/// 带有成功标志的结果对象
public OperateResult ReadBool(string address)
{
OperateResult analysis = XGBFastEnet.AnalysisAddress(address, true);
if (!analysis.IsSuccess) return OperateResult.CreateFailedResult(analysis);
// to do, this is not right
int startIndex = CheckAddress(analysis.Content.Substring(3));
switch (analysis.Content[1])
{
case 'P': return OperateResult.CreateSuccessResult(pBuffer.GetBool(startIndex));
case 'Q': return OperateResult.CreateSuccessResult(qBuffer.GetBool(startIndex));
case 'M': return OperateResult.CreateSuccessResult(mBuffer.GetBool(startIndex));
case 'D': return OperateResult.CreateSuccessResult(dBuffer.GetBool(startIndex));
default: return new OperateResult(StringResources.Language.NotSupportedDataType);
}
}
///
/// 往指定的地址里写入bool数据对象
///
/// 西门子的地址信息
/// 值
/// 是否成功的结果
public OperateResult Write(string address, bool value)
{
OperateResult analysis = XGBFastEnet.AnalysisAddress(address, false);
if (!analysis.IsSuccess) return analysis;
// to do, this is not right
int startIndex = CheckAddress(analysis.Content.Substring(3));
switch (analysis.Content[1])
{
case 'P': pBuffer.SetBool(value, startIndex); return OperateResult.CreateSuccessResult();
case 'Q': qBuffer.SetBool(value, startIndex); return OperateResult.CreateSuccessResult();
case 'M': mBuffer.SetBool(value, startIndex); return OperateResult.CreateSuccessResult();
case 'D': dBuffer.SetBool(value, startIndex); return OperateResult.CreateSuccessResult();
default: return new OperateResult(StringResources.Language.NotSupportedDataType);
}
}
#endregion
#region NetServer Override
///
/// 当客户端登录后,进行Ip信息的过滤,然后触发本方法,也就是说之后的客户端需要
///
/// 网络套接字
/// 终端节点
protected override void ThreadPoolLoginAfterClientCheck(Socket socket, System.Net.IPEndPoint endPoint)
{
// 开始接收数据信息
AppSession appSession = new AppSession();
appSession.IpEndPoint = endPoint;
appSession.WorkSocket = socket;
try
{
socket.BeginReceive(new byte[0], 0, 0, SocketFlags.None, new AsyncCallback(SocketAsyncCallBack), appSession);
AddClient(appSession);
}
catch
{
socket.Close();
LogNet?.WriteDebug(ToString(), string.Format(StringResources.Language.ClientOfflineInfo, endPoint));
}
}
private void SocketAsyncCallBack(IAsyncResult ar)
{
if (ar.AsyncState is AppSession session)
{
try
{
int receiveCount = session.WorkSocket.EndReceive(ar);
LsisFastEnetMessage fastEnetMessage = new LsisFastEnetMessage();
OperateResult read1 = ReceiveByMessage(session.WorkSocket, 5000, fastEnetMessage);
if (!read1.IsSuccess)
{
LogNet?.WriteDebug(ToString(), string.Format(StringResources.Language.ClientOfflineInfo, session.IpEndPoint));
RemoveClient(session);
return;
};
byte[] receive = read1.Content;
byte[] SendData = null;
if (receive[20] == 0x54)
{
// 读数据
SendData = ReadByMessage(receive);
RaiseDataReceived(SendData);
session.WorkSocket.Send(SendData);
}
else if (receive[20] == 0x58)
{
SendData = WriteByMessage(receive);
RaiseDataReceived(SendData);
session.WorkSocket.Send(SendData);
}
else
{
session.WorkSocket.Close();
}
RaiseDataSend(receive);
session.WorkSocket.BeginReceive(new byte[0], 0, 0, SocketFlags.None, new AsyncCallback(SocketAsyncCallBack), session);
}
catch
{
// 关闭连接,记录日志
session.WorkSocket?.Close();
LogNet?.WriteDebug(ToString(), string.Format(StringResources.Language.ClientOfflineInfo, session.IpEndPoint));
RemoveClient(session);
return;
}
}
}
private byte[] ReadByMessage(byte[] packCommand)
{
List content = new List();
content.AddRange(ReadByCommand(packCommand));
return content.ToArray();
}
private byte[] ReadByCommand(byte[] command)
{
var result = new List();
result.AddRange(SoftBasic.BytesArraySelectBegin(command, 20));
result[9] = 0x11;
result[10] = 0x01;
result[12] = 0xA0;
result[13] = 0x11;
result[18] = 0x03;
result.AddRange(new byte[] { 0x55, 0x00, 0x14, 0x00, 0x08, 0x01, 0x00, 0x00, 0x01, 0x00 });
int NameLength = command[28];
ushort RequestCount = BitConverter.ToUInt16(command, 30 + NameLength);
string DeviceAddress = Encoding.ASCII.GetString(command, 31, NameLength - 1);
byte[] data = Read(DeviceAddress, RequestCount).Content;
result.AddRange(BitConverter.GetBytes((ushort)data.Length));
result.AddRange(data);
result[16] = (byte)(result.Count - 20);
return result.ToArray();
}
private byte[] WriteByMessage(byte[] packCommand)
{
var result = new List();
result.AddRange(SoftBasic.BytesArraySelectBegin(packCommand, 20));
result[9] = 0x11;
result[10] = 0x01;
result[12] = 0xA0;
result[13] = 0x11;
result[18] = 0x03;
result.AddRange(new byte[] { 0x59, 0x00, 0x14, 0x00, 0x08, 0x01, 0x00, 0x00, 0x01, 0x00 });
int NameLength = packCommand[28];
var DeviceAddress = Encoding.ASCII.GetString(packCommand, 31, NameLength - 1);
int RequestCount = BitConverter.ToUInt16(packCommand, 30 + NameLength);
byte[] data = ByteTransform.TransByte(packCommand, 32 + NameLength, RequestCount);
Write(DeviceAddress, data);
result[16] = (byte)(result.Count - 20);
return result.ToArray();
}
#endregion
#region Data Save Load Override
///
/// 从字节数据加载数据信息
///
/// 字节数据
protected override void LoadFromBytes(byte[] content)
{
if (content.Length < DataPoolLength * 4) throw new Exception("File is not correct");
pBuffer.SetBytes(content, 0, 0, DataPoolLength);
qBuffer.SetBytes(content, DataPoolLength, 0, DataPoolLength);
mBuffer.SetBytes(content, DataPoolLength * 2, 0, DataPoolLength);
dBuffer.SetBytes(content, DataPoolLength * 3, 0, DataPoolLength);
}
///
/// 将数据信息存储到字节数组去
///
/// 所有的内容
protected override byte[] SaveToBytes()
{
byte[] buffer = new byte[DataPoolLength * 4];
Array.Copy(pBuffer.GetBytes(), 0, buffer, 0, DataPoolLength);
Array.Copy(qBuffer.GetBytes(), 0, buffer, DataPoolLength, DataPoolLength);
Array.Copy(mBuffer.GetBytes(), 0, buffer, DataPoolLength * 2, DataPoolLength);
Array.Copy(dBuffer.GetBytes(), 0, buffer, DataPoolLength * 3, DataPoolLength);
return buffer;
}
public static int CheckAddress(string address)
{
int bitSelacdetAddress;
switch (address)
{
case "A":
bitSelacdetAddress = 10;
break;
case "B":
bitSelacdetAddress = 11;
break;
case "C":
bitSelacdetAddress = 12;
break;
case "D":
bitSelacdetAddress = 13;
break;
case "E":
bitSelacdetAddress = 14;
break;
case "F":
bitSelacdetAddress = 15;
break;
default:
bitSelacdetAddress = int.Parse(address);
break;
}
return bitSelacdetAddress;
}
#endregion
#region Private Member
private SoftBuffer pBuffer; // p data type
private SoftBuffer qBuffer; // q data type
private SoftBuffer mBuffer; // 寄存器的数据池
private SoftBuffer dBuffer; // 输入寄存器的数据池
private const int DataPoolLength = 65536; // 数据的长度
#endregion
#region Serial Support
private int station = 1;
#if !NETSTANDARD2_0
private SerialPort serialPort; // 核心的串口对象
///
/// 使用默认的参数进行初始化串口,9600波特率,8位数据位,无奇偶校验,1位停止位
///
/// 串口信息
public void StartSerialPort(string com)
{
StartSerialPort(com, 9600);
}
///
/// 使用默认的参数进行初始化串口,8位数据位,无奇偶校验,1位停止位
///
/// 串口信息
/// 波特率
public void StartSerialPort(string com, int baudRate)
{
StartSerialPort(sp =>
{
sp.PortName = com;
sp.BaudRate = baudRate;
sp.DataBits = 8;
sp.Parity = Parity.None;
sp.StopBits = StopBits.One;
});
}
///
/// 使用自定义的初始化方法初始化串口的参数
///
/// 初始化信息的委托
public void StartSerialPort(Action inni)
{
if (!serialPort.IsOpen)
{
inni?.Invoke(serialPort);
serialPort.ReadBufferSize = 1024;
serialPort.ReceivedBytesThreshold = 1;
serialPort.Open();
serialPort.DataReceived += SerialPort_DataReceived;
}
}
///
/// 关闭串口
///
public void CloseSerialPort()
{
if (serialPort.IsOpen)
{
serialPort.Close();
}
}
///
/// 接收到串口数据的时候触发
///
/// 串口对象
/// 消息
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
var sp = (SerialPort)sender;
int rCount = 0;
byte[] buffer = new byte[1024];
byte[] receive = null;
while (true)
{
System.Threading.Thread.Sleep(20);
int count = sp.Read(buffer, rCount, sp.BytesToRead);
rCount += count;
if (count == 0) break;
receive = new byte[rCount];
Array.Copy(buffer, 0, receive, 0, count);
}
if (receive == null) return;
byte[] modbusCore = SoftBasic.BytesArrayRemoveLast(receive, 2);
byte[] SendData = null;
if (modbusCore[3] == 0x72)
{
// Read
SendData = ReadSerialByCommand(modbusCore);
RaiseDataReceived(SendData);
serialPort.Write(SendData, 0, SendData.Length);
}
else if (modbusCore[3] == 0x77)
{
// Write
SendData = WriteSerialByMessage(modbusCore);
RaiseDataReceived(SendData);
serialPort.Write(SendData, 0, SendData.Length);
}
else
{
serialPort.Close();
}
if (IsStarted) RaiseDataSend(receive);
}
public byte[] HexToBytes(string hex)
{
if (hex == null)
throw new ArgumentNullException("The data is null");
if (hex.Length % 2 != 0)
throw new FormatException("Hex Character Count Not Even");
var bytes = new byte[hex.Length / 2];
for (var i = 0; i < bytes.Length; i++)
bytes[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
return bytes;
}
private byte[] ReadSerialByCommand(byte[] command)
{
var result = new List();
result.Add(0x06); // ENQ
result.AddRange(SoftBasic.BuildAsciiBytesFrom((byte)station));
result.Add(0x72); // command r
result.Add(0x53); // command type: SB
result.Add(0x42);
result.AddRange(Encoding.ASCII.GetBytes("01"));
int NameLength =int.Parse(Encoding.ASCII.GetString(command, 6, 2));
int RequestCount = Convert.ToInt32(Encoding.ASCII.GetString(command, 8 + NameLength, 2),16);
string DeviceAddress = Encoding.ASCII.GetString(command, 9, NameLength - 1);
byte[] data = Read(DeviceAddress,(ushort) RequestCount).Content;
result.AddRange(SoftBasic.BuildAsciiBytesFrom((byte)data.Length));
result.AddRange(SoftBasic.BytesToAsciiBytes(data));
result.Add(0x03); // ETX
int sum1 = 0;
for (int i = 0; i < result.Count; i++)
{
sum1 += result[i];
}
result.AddRange(SoftBasic.BuildAsciiBytesFrom((byte)sum1));
return result.ToArray();
}
private byte[] WriteSerialByMessage(byte[] packCommand)
{
var result = new List();
string NameLength, DeviceAddress;
var Read = Encoding.ASCII.GetString(packCommand, 3, 3);
result.Add(0x06); // ENQ
result.AddRange(SoftBasic.BuildAsciiBytesFrom((byte)station));
result.Add(0x77); // command w
result.Add(0x53); // command type: SB
result.Add(0x42);
result.Add(0x03); // EOT
if (Read == "wSS")
{
NameLength = Encoding.ASCII.GetString(packCommand, 8, 2);
DeviceAddress = Encoding.ASCII.GetString(packCommand, 11, int.Parse(NameLength) - 1);
string data = Encoding.ASCII.GetString(packCommand, 10 + int.Parse(NameLength), 2);
Write(DeviceAddress, new byte[] { (byte)(data == "01" ? 0x01 : 0x00) });
}
else
{
NameLength = Encoding.ASCII.GetString(packCommand, 6, 2);
DeviceAddress = Encoding.ASCII.GetString(packCommand,9, int.Parse(NameLength)-1);
int RequestCount = int.Parse( Encoding.ASCII.GetString(packCommand, 8 + int.Parse(NameLength), 2));
string Value = Encoding.ASCII.GetString(packCommand, 8 + int.Parse(NameLength) + RequestCount, RequestCount * 2);
var wdArys = HexToBytes(Value);
Write(DeviceAddress, wdArys);
}
return result.ToArray();
}
#endif
#endregion
#region Object Override
///
/// 返回表示当前对象的字符串
///
/// 字符串信息
public override string ToString()
{
return $"LSisServer[{Port}]";
}
#endregion
}
}