1
0
mirror of https://github.com/zhaopeiym/IoTClient synced 2025-10-26 22:15:44 +08:00
IoTClient/IoTServer/Servers/ModBus/ModBusAsciiServer.cs
BennyZhao 665724aff4 fix ModbusRtu、ModBusAscii、串口等 奇偶校验。
ModBusTcp读写操作使用说明。
西门子S7 300 beta
2019-11-13 08:29:39 +08:00

172 lines
7.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
{
public class ModBusAsciiServer
{
private SerialPort serialPort;
DataPersist dataPersist;
public ModBusAsciiServer(string portName, int baudRate, int dataBits, StopBits stopBits, Parity parity)
{
if (serialPort == null) serialPort = new SerialPort();
serialPort.PortName = portName;
serialPort.BaudRate = baudRate;
serialPort.DataBits = dataBits;
serialPort.StopBits = stopBits;
serialPort.Encoding = Encoding.ASCII;
serialPort.Parity = parity;
#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[5]}-{requetData[6]}-{requetData[7]}-{requetData[8]}";
byte[] tempData = new byte[requetData.Length - 3];
Buffer.BlockCopy(requetData, 1, tempData, 0, tempData.Length);
var requetAsciiData = DataConvert.AsciiArrayToByteArray(tempData);
var type = $"{requetData[3].ToString("X2")}{requetData[4].ToString("X2")}";
switch (type)
{
//读取线圈
case "3031":
{
var value = dataPersist.Read(address);
var bytes = JsonConvert.DeserializeObject<byte[]>(value);
byte[] data = null;
//没有存储过的数据的默认响应false
if (bytes == null)
{
data = DataConvert.StringToByteArray("01 01 01 00");
}
else
{
if (bytes[0].ToString("X2") != "3A" ||
bytes[bytes.Length - 2].ToString("X2") != "0D" ||
bytes[bytes.Length - 1].ToString("X2") != "0A")
{
throw new Exception("标记验证失败");
}
byte[] asciiData = new byte[bytes.Length - 3];
Buffer.BlockCopy(bytes, 1, asciiData, 0, asciiData.Length);
var byteDataArray = DataConvert.AsciiArrayToByteArray(asciiData);
//true
if (byteDataArray[4].ToString("X2") == "FF" && byteDataArray[5].ToString("X2") == "00")
data = DataConvert.StringToByteArray("01 01 01 01");
else//false
data = DataConvert.StringToByteArray("01 01 01 00");
}
var dataString = string.Join("", LRC.GetLRC(data).Select(t => t.ToString("X2")));
var databyte = Encoding.ASCII.GetBytes(dataString);
var responseData = new byte[databyte.Length + 3];
Buffer.BlockCopy(databyte, 0, responseData, 1, databyte.Length);
responseData[0] = 0x3A;
responseData[responseData.Length - 2] = 0x0D;
responseData[responseData.Length - 1] = 0x0A;
serialPort.Write(responseData, 0, responseData.Length);
}
break;
//写入线圈
case "3035":
{
dataPersist.Write(address, JsonConvert.SerializeObject(requetData));
serialPort.Write(requetData, 0, requetData.Length);
}
break;
//读取
case "3033":
{
var value = dataPersist.Read(address);
var bytes = JsonConvert.DeserializeObject<byte[]>(value);
byte[] data = null;
if (bytes == null)
{
data = new byte[2 + 3];
data[2] = 2;//数据长度
}
else
{
if (bytes[0].ToString("X2") != "3A" ||
bytes[bytes.Length - 2].ToString("X2") != "0D" ||
bytes[bytes.Length - 1].ToString("X2") != "0A")
{
throw new Exception("标记验证失败");
}
byte[] asciiData = new byte[bytes.Length - 3];
Buffer.BlockCopy(bytes, 1, asciiData, 0, asciiData.Length);
var byteDataArray = DataConvert.AsciiArrayToByteArray(asciiData);
data = new byte[byteDataArray[6] + 3];
data[2] = byteDataArray[6];//数据长度
Buffer.BlockCopy(byteDataArray, 7, data, 3, data.Length - 3);
}
data[0] = requetAsciiData[0];//站号
data[1] = 0x03;//功能码
var dataString = string.Join("", LRC.GetLRC(data).Select(t => t.ToString("X2")));
var databyte = Encoding.ASCII.GetBytes(dataString);
var responseData = new byte[databyte.Length + 3];
Buffer.BlockCopy(databyte, 0, responseData, 1, databyte.Length);
responseData[0] = 0x3A;
responseData[responseData.Length - 2] = 0x0D;
responseData[responseData.Length - 1] = 0x0A;
serialPort.Write(responseData, 0, responseData.Length);
}
break;
//写入3130 对应十进制16 十六进制 10
case "3130":
{
dataPersist.Write(address, JsonConvert.SerializeObject(requetData));
serialPort.Write(requetData, 0, requetData.Length);
}
break;
}
}
catch (Exception ex)
{ }
}
}
}