1
0
mirror of https://github.com/zhaopeiym/IoTClient synced 2025-10-26 22:15:44 +08:00
IoTClient/IoTServer/Servers/ModBus/ModBusRtuServer.cs
2019-12-17 16:11:22 +08:00

136 lines
5.9 KiB
C#

using IoTClient.Common.Helpers;
using IoTServer.Common;
using Newtonsoft.Json;
using System;
using System.IO.Ports;
using System.Linq;
using System.Text;
namespace IoTServer.Servers.ModBus
{
/// <summary>
/// ModBusRtu 服务端模拟
/// </summary>
public class ModBusRtuServer
{
private SerialPort serialPort;
DataPersist dataPersist;
public ModBusRtuServer(string portName, int baudRate, int dataBits, StopBits stopBits)
{
if (serialPort == null) serialPort = new SerialPort();
serialPort.PortName = portName;
serialPort.BaudRate = baudRate;
serialPort.DataBits = dataBits;
serialPort.StopBits = stopBits;
serialPort.Encoding = Encoding.ASCII;
#if !DEBUG
serialPort.ReadTimeout = 1000;//1秒
#endif
serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceived);
dataPersist = new DataPersist("ModBusTcpServer");
}
/// <summary>
/// 启动服务
/// </summary>
public void Start()
{
serialPort.Open();
}
/// <summary>
/// 停止服务
/// </summary>
public void Stop()
{
serialPort.Close();
serialPort.Dispose();
}
/// <summary>
/// 接收数据回调用
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
byte[] requetData = new byte[serialPort.BytesToRead];
serialPort.Read(requetData, 0, requetData.Length);
var address = requetData[2] * 256 + requetData[3];
var stationNumberKey = $"{requetData[0]}-key";//站号
switch (requetData[1])
{
//读取线圈
case 1:
{
var value = dataPersist.Read(stationNumberKey + "-Coil");
var byteArray = JsonConvert.DeserializeObject<byte[]>(value) ?? new byte[65536];
var registerLenght = requetData[4] * 256 + requetData[5];
var blenght = (byte)Math.Ceiling(registerLenght / 8f);
var tempData = new byte[registerLenght];
Buffer.BlockCopy(byteArray, address, tempData, 0, tempData.Length);
var rData = new byte[3 + registerLenght];
rData[0] = 1;
rData[1] = 1;
rData[2] = (byte)registerLenght;
for (int i = 0; i < blenght; i++)
{
rData[3 + i] = (byte)DataConvert.BinaryArrayToInt(string.Join("", tempData.Skip(i * 8).Take(8).Reverse()));
}
var responseData = CRC16.GetCRC16(rData);
serialPort.Write(responseData, 0, responseData.Length);
}
break;
//写入线圈
case 5:
{
var value = new byte[2];
Buffer.BlockCopy(requetData, requetData.Length - 4, value, 0, value.Length);
var byteArray = JsonConvert.DeserializeObject<byte[]>(dataPersist.Read(stationNumberKey + "-Coil")) ?? new byte[65536];
if (value[0] == 0 && value[1] == 0)
byteArray[address] = 0;
else
byteArray[address] = 1;
dataPersist.Write(stationNumberKey + "-Coil", JsonConvert.SerializeObject(byteArray));
serialPort.Write(requetData, 0, requetData.Length);
}
break;
//读取
case 3:
{
var value = dataPersist.Read(stationNumberKey);
var byteArray = JsonConvert.DeserializeObject<byte[]>(value) ?? new byte[65536];
var dlength = requetData[4] * 256 + requetData[5];
var dataHead = new byte[] { 1, 3, (byte)(dlength * 2) };
var dataContent = new byte[dlength * 2];
Buffer.BlockCopy(byteArray, address * 2, dataContent, 0, dataContent.Length);
var tempData = dataHead.Concat(dataContent).ToArray();
var responseData = CRC16.GetCRC16(tempData);
serialPort.Write(responseData, 0, responseData.Length);
}
break;
//写入
case 16:
{
var value = new byte[requetData[6]];
Buffer.BlockCopy(requetData, 7, value, 0, value.Length);
var byteArray = JsonConvert.DeserializeObject<byte[]>(dataPersist.Read(stationNumberKey)) ?? new byte[65536];
value.CopyTo(byteArray, address * 2);
dataPersist.Write(stationNumberKey, JsonConvert.SerializeObject(byteArray));
var tempData = new byte[6];
Buffer.BlockCopy(requetData, 0, tempData, 0, tempData.Length);
var responseData = CRC16.GetCRC16(tempData);
serialPort.Write(responseData, 0, responseData.Length);
}
break;
}
}
catch (Exception ex)
{ }
}
}
}