593 lines
28 KiB
C#
593 lines
28 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Globalization;
|
||
using System.Text;
|
||
|
||
namespace Modbus.Net.Modbus
|
||
{
|
||
/// <summary>
|
||
/// Modbus 协议字节伸缩类 / Modbus Protocol Bytes Extend Classes
|
||
/// <remarks>
|
||
/// 实现各种 Modbus 协议的字节扩展和收缩功能
|
||
/// Implements bytes extend and reduce functionality for various Modbus protocols
|
||
/// <para>
|
||
/// 主要类 / Main Classes:
|
||
/// <list type="bullet">
|
||
/// <item><strong>ModbusTcpProtocolLinkerBytesExtend</strong> - TCP 协议 MBAP 头处理 / TCP protocol MBAP header handling</item>
|
||
/// <item><strong>ModbusRtuProtocolLinkerBytesExtend</strong> - RTU 协议 CRC16 处理 / RTU protocol CRC16 handling</item>
|
||
/// <item><strong>ModbusAsciiProtocolLinkerBytesExtend</strong> - ASCII 协议 LRC 和格式处理 / ASCII protocol LRC and format handling</item>
|
||
/// <item><strong>ModbusRtuInTcpProtocolLinkerBytesExtend</strong> - RTU over TCP 透传 / RTU over TCP tunneling</item>
|
||
/// <item><strong>ModbusAsciiInTcpProtocolLinkerBytesExtend</strong> - ASCII over TCP 透传 / ASCII over TCP tunneling</item>
|
||
/// <item><strong>ModbusUdpProtocolLinkerBytesExtend</strong> - UDP 协议处理 / UDP protocol handling</item>
|
||
/// </list>
|
||
/// </para>
|
||
/// </remarks>
|
||
/// </summary>
|
||
|
||
#region UDP 协议字节伸缩 / UDP Protocol Bytes Extend
|
||
|
||
/// <summary>
|
||
/// Modbus RTU over UDP 字节伸缩 / Modbus RTU over UDP Bytes Extend
|
||
/// <remarks>
|
||
/// 继承自 ModbusRtuProtocolLinkerBytesExtend,处理 RTU over UDP 协议
|
||
/// Inherits from ModbusRtuProtocolLinkerBytesExtend, handles RTU over UDP protocol
|
||
/// <para>
|
||
/// 特点 / Characteristics:
|
||
/// <list type="bullet">
|
||
/// <item>RTU 帧原样传输 / RTU frames transmitted as-is</item>
|
||
/// <item>无 MBAP 头 / No MBAP header</item>
|
||
/// <item>保留 CRC16 校验 / CRC16 checksum preserved</item>
|
||
/// <item>适用于 UDP 广播 / Suitable for UDP broadcast</item>
|
||
/// </list>
|
||
/// </para>
|
||
/// </remarks>
|
||
/// </summary>
|
||
public class ModbusRtuInUdpProtocolLinkerBytesExtend : ModbusRtuProtocolLinkerBytesExtend
|
||
{
|
||
// 使用 RTU 协议的字节伸缩方法 / Use RTU protocol bytes extend methods
|
||
}
|
||
|
||
/// <summary>
|
||
/// Modbus ASCII over UDP 字节伸缩 / Modbus ASCII over UDP Bytes Extend
|
||
/// <remarks>
|
||
/// 继承自 ModbusAsciiProtocolLinkerBytesExtend,处理 ASCII over UDP 协议
|
||
/// Inherits from ModbusAsciiProtocolLinkerBytesExtend, handles ASCII over UDP protocol
|
||
/// </remarks>
|
||
/// </summary>
|
||
public class ModbusAsciiInUdpProtocolLinkerBytesExtend : ModbusAsciiProtocolLinkerBytesExtend
|
||
{
|
||
// 使用 ASCII 协议的字节伸缩方法 / Use ASCII protocol bytes extend methods
|
||
}
|
||
|
||
/// <summary>
|
||
/// Modbus UDP 协议字节伸缩 / Modbus UDP Protocol Bytes Extend
|
||
/// <remarks>
|
||
/// 继承自 ModbusTcpProtocolLinkerBytesExtend,处理 UDP 协议
|
||
/// Inherits from ModbusTcpProtocolLinkerBytesExtend, handles UDP protocol
|
||
/// <para>
|
||
/// 特点 / Characteristics:
|
||
/// <list type="bullet">
|
||
/// <item>添加 MBAP 头 / Adds MBAP header</item>
|
||
/// <item>无连接模式 / Connectionless mode</item>
|
||
/// <item>适用于广播查询 / Suitable for broadcast query</item>
|
||
/// </list>
|
||
/// </para>
|
||
/// </remarks>
|
||
/// </summary>
|
||
public class ModbusUdpProtocolLinkerBytesExtend : ModbusTcpProtocolLinkerBytesExtend
|
||
{
|
||
// 使用 TCP 协议的字节伸缩方法 / Use TCP protocol bytes extend methods
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region TCP 透传协议字节伸缩 / TCP Tunneling Protocol Bytes Extend
|
||
|
||
/// <summary>
|
||
/// Modbus RTU over TCP 字节伸缩 / Modbus RTU over TCP Bytes Extend
|
||
/// <remarks>
|
||
/// 继承自 ModbusRtuProtocolLinkerBytesExtend,处理 RTU over TCP 透传协议
|
||
/// Inherits from ModbusRtuProtocolLinkerBytesExtend, handles RTU over TCP tunneling protocol
|
||
/// <para>
|
||
/// 使用场景 / Use Cases:
|
||
/// <list type="bullet">
|
||
/// <item>串口服务器 / Serial device server</item>
|
||
/// <item>通过 TCP 传输 RTU 帧 / Transmit RTU frames over TCP</item>
|
||
/// <item>远程串口访问 / Remote serial access</item>
|
||
/// </list>
|
||
/// </para>
|
||
/// <para>
|
||
/// 特点 / Characteristics:
|
||
/// <list type="bullet">
|
||
/// <item>RTU 帧原样传输 / RTU frames transmitted as-is</item>
|
||
/// <item>无 MBAP 头 / No MBAP header</item>
|
||
/// <item>保留 CRC16 校验 / CRC16 checksum preserved</item>
|
||
/// </list>
|
||
/// </para>
|
||
/// </remarks>
|
||
/// </summary>
|
||
public class ModbusRtuInTcpProtocolLinkerBytesExtend : ModbusRtuProtocolLinkerBytesExtend
|
||
{
|
||
// 使用 RTU 协议的字节伸缩方法 / Use RTU protocol bytes extend methods
|
||
}
|
||
|
||
/// <summary>
|
||
/// Modbus ASCII over TCP 字节伸缩 / Modbus ASCII over TCP Bytes Extend
|
||
/// <remarks>
|
||
/// 继承自 ModbusAsciiProtocolLinkerBytesExtend,处理 ASCII over TCP 透传协议
|
||
/// Inherits from ModbusAsciiProtocolLinkerBytesExtend, handles ASCII over TCP tunneling protocol
|
||
/// <para>
|
||
/// 使用场景 / Use Cases:
|
||
/// <list type="bullet">
|
||
/// <item>串口服务器 / Serial device server</item>
|
||
/// <item>通过 TCP 传输 ASCII 帧 / Transmit ASCII frames over TCP</item>
|
||
/// </list>
|
||
/// </para>
|
||
/// </remarks>
|
||
/// </summary>
|
||
public class ModbusAsciiInTcpProtocolLinkerBytesExtend : ModbusAsciiProtocolLinkerBytesExtend
|
||
{
|
||
// 使用 ASCII 协议的字节伸缩方法 / Use ASCII protocol bytes extend methods
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region TCP 协议字节伸缩 / TCP Protocol Bytes Extend
|
||
|
||
/// <summary>
|
||
/// Modbus/TCP 协议字节伸缩 / Modbus/TCP Protocol Bytes Extend
|
||
/// <remarks>
|
||
/// 实现 Modbus TCP 协议的 MBAP 头添加和移除功能
|
||
/// Implements MBAP header addition and removal for Modbus TCP protocol
|
||
/// <para>
|
||
/// MBAP 头格式 / MBAP Header Format:
|
||
/// <code>
|
||
/// [Transaction ID (2)][Protocol ID (2)][Length (2)][Unit ID (1)]
|
||
/// │ │ │ │ │ │
|
||
/// └─ 事务标识,用于匹配请求响应
|
||
/// └─ 协议标识,Modbus=0
|
||
/// └─ 后续字节长度
|
||
/// └─ 从站地址
|
||
/// </code>
|
||
/// </para>
|
||
/// <para>
|
||
/// 使用示例 / Usage Example:
|
||
/// <code>
|
||
/// var bytesExtend = new ModbusTcpProtocolLinkerBytesExtend();
|
||
///
|
||
/// // 扩展 (发送前) / Extend (before sending)
|
||
/// byte[] rawData = [0x01, 0x03, 0x00, 0x00, 0x00, 0x0A]; // Modbus RTU 帧
|
||
/// byte[] extendedData = bytesExtend.BytesExtend(rawData);
|
||
/// // 结果:[0x00 0x01 0x00 0x00 0x00 0x06 0x01 0x03 0x00 0x00 0x00 0x0A]
|
||
/// // │ 事务 ID │ 协议 ID │ 长度 │RTU 帧...
|
||
/// ///
|
||
/// // 收缩 (接收后) / Reduce (after receiving)
|
||
/// byte[] receivedData = [0x00 0x01 0x00 0x00 0x00 0x06 0x01 0x03 0x04 0x00 0x64 0x00 0xC8];
|
||
/// byte[] reducedData = bytesExtend.BytesDecact(receivedData);
|
||
/// // 结果:[0x01, 0x03, 0x04, 0x00, 0x64, 0x00, 0xC8] // 移除 MBAP 头
|
||
/// </code>
|
||
/// </para>
|
||
/// </remarks>
|
||
/// </summary>
|
||
public class ModbusTcpProtocolLinkerBytesExtend : IProtocolLinkerBytesExtend<byte[], byte[]>
|
||
{
|
||
private static ushort _sendCount = 0;
|
||
private static readonly object _counterLock = new object();
|
||
|
||
/// <summary>
|
||
/// 协议扩展 (发送前调用) / Protocol Extend (Called Before Sending)
|
||
/// <remarks>
|
||
/// 在 Modbus TCP 协议数据前添加 MBAP 头 (6 字节)
|
||
/// Add MBAP header (6 bytes) before Modbus TCP protocol data
|
||
/// <para>
|
||
/// MBAP 头结构 / MBAP Header Structure:
|
||
/// <list type="bullet">
|
||
/// <item>Transaction ID (2 字节) - 事务标识,用于匹配请求响应 / Transaction identifier for matching request-response</item>
|
||
/// <item>Protocol ID (2 字节) - 协议标识,Modbus=0 / Protocol identifier, Modbus=0</item>
|
||
/// <item>Length (2 字节) - 后续字节长度 / Length of following bytes</item>
|
||
/// <item>Unit ID (1 字节) - 从站地址 / Unit identifier (slave address)</item>
|
||
/// </list>
|
||
/// </para>
|
||
/// <para>
|
||
/// 事务计数 / Transaction Counting:
|
||
/// <list type="bullet">
|
||
/// <item>使用静态计数器 / Uses static counter</item>
|
||
/// <item>每次发送递增 / Increments on each send</item>
|
||
/// <item>模 65536 循环 (ushort 范围) / Cycles mod 65536 (ushort range)</item>
|
||
/// <item>线程安全 (使用锁) / Thread-safe (uses lock)</item>
|
||
/// </list>
|
||
/// </para>
|
||
/// </remarks>
|
||
/// </summary>
|
||
/// <param name="content">
|
||
/// 扩展前的原始协议内容 / Original Protocol Content Before Extension
|
||
/// <remarks>
|
||
/// Modbus RTU 帧 (包含从站地址、功能码、数据、CRC)
|
||
/// Modbus RTU frame (contains slave address, function code, data, CRC)
|
||
/// </remarks>
|
||
/// </param>
|
||
/// <returns>
|
||
/// 扩展后的协议内容 / Extended Protocol Content
|
||
/// <remarks>
|
||
/// 添加了 MBAP 头的完整 TCP 帧
|
||
/// Complete TCP frame with MBAP header added
|
||
/// </remarks>
|
||
/// </returns>
|
||
public byte[] BytesExtend(byte[] content)
|
||
{
|
||
// Modbus/TCP 协议扩展,前面加 6 个字节
|
||
// Modbus/TCP protocol extension, add 6 bytes at the front
|
||
// 前面 2 个为事务编号,中间两个为 0,后面两个为协议整体内容的长度
|
||
// First 2: transaction ID, middle 2: 0, last 2: total length
|
||
var newFormat = new byte[6 + content.Length];
|
||
|
||
lock (_counterLock)
|
||
{
|
||
// 生成事务 ID (循环计数) / Generate transaction ID (cyclic count)
|
||
var transaction = (ushort)(_sendCount % 65536 + 1);
|
||
var tag = (ushort)0; // 协议标识,Modbus=0 / Protocol ID, Modbus=0
|
||
var leng = (ushort)content.Length; // 后续字节长度 / Length of following bytes
|
||
|
||
// 复制事务 ID (大端格式) / Copy transaction ID (big-endian)
|
||
Array.Copy(BigEndianLsbValueHelper.Instance.GetBytes(transaction), 0, newFormat, 0, 2);
|
||
// 复制协议标识 / Copy protocol ID
|
||
Array.Copy(BigEndianLsbValueHelper.Instance.GetBytes(tag), 0, newFormat, 2, 2);
|
||
// 复制长度 / Copy length
|
||
Array.Copy(BigEndianLsbValueHelper.Instance.GetBytes(leng), 0, newFormat, 4, 2);
|
||
// 复制原始内容 / Copy original content
|
||
Array.Copy(content, 0, newFormat, 6, content.Length);
|
||
|
||
_sendCount++; // 递增计数器 / Increment counter
|
||
}
|
||
return newFormat;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 协议收缩 (接收后调用) / Protocol Reduce (Called After Receiving)
|
||
/// <remarks>
|
||
/// 移除 Modbus TCP 协议数据的 MBAP 头 (6 字节)
|
||
/// Remove MBAP header (6 bytes) from Modbus TCP protocol data
|
||
/// <para>
|
||
/// 处理流程 / Processing Flow:
|
||
/// <list type="number">
|
||
/// <item>创建新数组,长度 = 原长度 - 6 / Create new array, length = original length - 6</item>
|
||
/// <item>从第 7 个字节开始复制 / Copy starting from 7th byte</item>
|
||
/// <item>返回纯 Modbus RTU 帧 / Return pure Modbus RTU frame</item>
|
||
/// </list>
|
||
/// </para>
|
||
/// </remarks>
|
||
/// </summary>
|
||
/// <param name="content">
|
||
/// 收缩前的完整协议内容 / Complete Protocol Content Before Reduction
|
||
/// <remarks>
|
||
/// 包含 MBAP 头的完整 TCP 帧
|
||
/// Complete TCP frame with MBAP header
|
||
/// </remarks>
|
||
/// </param>
|
||
/// <returns>
|
||
/// 收缩后的协议内容 / Reduced Protocol Content
|
||
/// <remarks>
|
||
/// 移除 MBAP 头后的 Modbus RTU 帧
|
||
/// Modbus RTU frame with MBAP header removed
|
||
/// </remarks>
|
||
/// </returns>
|
||
public byte[] BytesDecact(byte[] content)
|
||
{
|
||
// Modbus/TCP 协议收缩,抛弃前面 6 个字节的内容
|
||
// Modbus/TCP protocol reduction, discard first 6 bytes
|
||
var newContent = new byte[content.Length - 6];
|
||
Array.Copy(content, 6, newContent, 0, newContent.Length);
|
||
return newContent;
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region RTU 协议字节伸缩 / RTU Protocol Bytes Extend
|
||
|
||
/// <summary>
|
||
/// Modbus/RTU 协议字节伸缩 / Modbus/RTU Protocol Bytes Extend
|
||
/// <remarks>
|
||
/// 实现 Modbus RTU 协议的 CRC16 校验码添加和移除功能
|
||
/// Implements CRC16 checksum addition and removal for Modbus RTU protocol
|
||
/// <para>
|
||
/// CRC16 校验 / CRC16 Checksum:
|
||
/// <list type="bullet">
|
||
/// <item>多项式:0xA001 / Polynomial: 0xA001</item>
|
||
/// <item>初始值:0xFFFF / Initial value: 0xFFFF</item>
|
||
/// <item>2 字节,低字节在前 / 2 bytes, low byte first</item>
|
||
/// <item>覆盖从站地址到数据的所有字节 / Covers all bytes from slave address to data</item>
|
||
/// </list>
|
||
/// </para>
|
||
/// <para>
|
||
/// 使用示例 / Usage Example:
|
||
/// <code>
|
||
/// var bytesExtend = new ModbusRtuProtocolLinkerBytesExtend();
|
||
///
|
||
/// // 扩展 (发送前) / Extend (before sending)
|
||
/// byte[] rawData = [0x01, 0x03, 0x00, 0x00, 0x00, 0x0A]; // Modbus 请求
|
||
/// byte[] extendedData = bytesExtend.BytesExtend(rawData);
|
||
/// // 结果:[0x01, 0x03, 0x00, 0x00, 0x00, 0x0A, 0xC4, 0x0B]
|
||
/// // │ CRC16 │
|
||
/// ///
|
||
/// // 收缩 (接收后) / Reduce (after receiving)
|
||
/// byte[] receivedData = [0x01, 0x03, 0x04, 0x00, 0x64, 0x00, 0xC8, 0xB9, 0x0A];
|
||
/// byte[] reducedData = bytesExtend.BytesDecact(receivedData);
|
||
/// // 结果:[0x01, 0x03, 0x04, 0x00, 0x64, 0x00, 0xC8] // 移除 CRC
|
||
/// </code>
|
||
/// </para>
|
||
/// </remarks>
|
||
/// </summary>
|
||
public class ModbusRtuProtocolLinkerBytesExtend : IProtocolLinkerBytesExtend<byte[], byte[]>
|
||
{
|
||
/// <summary>
|
||
/// 协议扩展 (发送前调用) / Protocol Extend (Called Before Sending)
|
||
/// <remarks>
|
||
/// 在 Modbus RTU 协议数据后添加 CRC16 校验码 (2 字节)
|
||
/// Add CRC16 checksum (2 bytes) after Modbus RTU protocol data
|
||
/// <para>
|
||
/// 处理流程 / Processing Flow:
|
||
/// <list type="number">
|
||
/// <item>创建新数组,长度 = 原长度 + 2 / Create new array, length = original length + 2</item>
|
||
/// <item>计算原始数据的 CRC16 / Calculate CRC16 of original data</item>
|
||
/// <item>复制原始数据到新数组 / Copy original data to new array</item>
|
||
/// <item>在末尾添加 CRC16 (低字节在前) / Add CRC16 at end (low byte first)</item>
|
||
/// </list>
|
||
/// </para>
|
||
/// </remarks>
|
||
/// </summary>
|
||
/// <param name="content">
|
||
/// 扩展前的原始协议内容 / Original Protocol Content Before Extension
|
||
/// <remarks>
|
||
/// 不包含 CRC 的 Modbus RTU 帧
|
||
/// Modbus RTU frame without CRC
|
||
/// </remarks>
|
||
/// </param>
|
||
/// <returns>
|
||
/// 扩展后的协议内容 / Extended Protocol Content
|
||
/// <remarks>
|
||
/// 添加了 CRC16 校验码的完整 RTU 帧
|
||
/// Complete RTU frame with CRC16 checksum added
|
||
/// </remarks>
|
||
/// </returns>
|
||
public byte[] BytesExtend(byte[] content)
|
||
{
|
||
var crc = new byte[2];
|
||
// Modbus/RTU 协议扩展,增加 CRC 校验
|
||
// Modbus/RTU protocol extension, add CRC checksum
|
||
var newFormat = new byte[content.Length + 2];
|
||
|
||
// 计算 CRC16 / Calculate CRC16
|
||
Crc16.GetInstance().GetCRC(content, ref crc);
|
||
|
||
// 复制原始内容 / Copy original content
|
||
Array.Copy(content, 0, newFormat, 0, content.Length);
|
||
// 在末尾添加 CRC (低字节在前) / Add CRC at end (low byte first)
|
||
Array.Copy(crc, 0, newFormat, newFormat.Length - 2, crc.Length);
|
||
|
||
return newFormat;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 协议收缩 (接收后调用) / Protocol Reduce (Called After Receiving)
|
||
/// <remarks>
|
||
/// 移除 Modbus RTU 协议数据的 CRC16 校验码 (2 字节)
|
||
/// Remove CRC16 checksum (2 bytes) from Modbus RTU protocol data
|
||
/// <para>
|
||
/// 处理流程 / Processing Flow:
|
||
/// <list type="number">
|
||
/// <item>创建新数组,长度 = 原长度 - 2 / Create new array, length = original length - 2</item>
|
||
/// <item>复制除最后 2 字节外的所有数据 / Copy all data except last 2 bytes</item>
|
||
/// <item>返回不含 CRC 的数据 / Return data without CRC</item>
|
||
/// </list>
|
||
/// </para>
|
||
/// <para>
|
||
/// 注意 / Note:
|
||
/// <list type="bullet">
|
||
/// <item>CRC 校验在收缩前已完成 / CRC check is done before reduction</item>
|
||
/// <item>此方法仅移除 CRC 字节 / This method only removes CRC bytes</item>
|
||
/// </list>
|
||
/// </para>
|
||
/// </remarks>
|
||
/// </summary>
|
||
/// <param name="content">
|
||
/// 收缩前的完整协议内容 / Complete Protocol Content Before Reduction
|
||
/// <remarks>
|
||
/// 包含 CRC16 校验码的完整 RTU 帧
|
||
/// Complete RTU frame with CRC16 checksum
|
||
/// </remarks>
|
||
/// </param>
|
||
/// <returns>
|
||
/// 收缩后的协议内容 / Reduced Protocol Content
|
||
/// <remarks>
|
||
/// 移除 CRC16 校验码后的 Modbus RTU 帧
|
||
/// Modbus RTU frame with CRC16 checksum removed
|
||
/// </remarks>
|
||
/// </returns>
|
||
public byte[] BytesDecact(byte[] content)
|
||
{
|
||
// Modbus/RTU 协议收缩,抛弃最后 2 个字节的内容 (CRC)
|
||
// Modbus/RTU protocol reduction, discard last 2 bytes (CRC)
|
||
var newContent = new byte[content.Length - 2];
|
||
Array.Copy(content, 0, newContent, 0, newContent.Length);
|
||
return newContent;
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
#region ASCII 协议字节伸缩 / ASCII Protocol Bytes Extend
|
||
|
||
/// <summary>
|
||
/// Modbus/ASCII 协议字节伸缩 / Modbus/ASCII Protocol Bytes Extend
|
||
/// <remarks>
|
||
/// 实现 Modbus ASCII 协议的格式转换和 LRC 校验功能
|
||
/// Implements format conversion and LRC checksum for Modbus ASCII protocol
|
||
/// <para>
|
||
/// ASCII 协议格式 / ASCII Protocol Format:
|
||
/// <code>
|
||
/// : [从站地址][功能码][数据][LRC][CR][LF]
|
||
/// │ │ │ │ │ │
|
||
/// │ │ │ │ │ └─ 换行符 (0x0A)
|
||
/// │ │ │ │ └─ 回车符 (0x0D)
|
||
/// │ │ │ └─ LRC 校验 (2 字符十六进制)
|
||
/// │ │ └─ 数据 (十六进制 ASCII 字符)
|
||
/// │ └─ 功能码 (2 字符十六进制)
|
||
/// └─ 起始符 (冒号 0x3A)
|
||
/// </code>
|
||
/// </para>
|
||
/// <para>
|
||
/// 编码规则 / Encoding Rules:
|
||
/// <list type="bullet">
|
||
/// <item>每个字节转换为 2 个十六进制 ASCII 字符 / Each byte converted to 2 hex ASCII characters</item>
|
||
/// <item>例如:0x1A → "1A" (0x31, 0x41) / e.g., 0x1A → "1A" (0x31, 0x41)</item>
|
||
/// <item>LRC 校验:纵向冗余校验 / LRC checksum: Longitudinal Redundancy Check</item>
|
||
/// </list>
|
||
/// </para>
|
||
/// </remarks>
|
||
/// </summary>
|
||
public class ModbusAsciiProtocolLinkerBytesExtend : IProtocolLinkerBytesExtend<byte[], byte[]>
|
||
{
|
||
/// <summary>
|
||
/// 协议扩展 (发送前调用) / Protocol Extend (Called Before Sending)
|
||
/// <remarks>
|
||
/// 将二进制数据转换为 ASCII 格式,添加起始符、LRC 校验和结束符
|
||
/// Convert binary data to ASCII format, add start marker, LRC checksum and end marker
|
||
/// <para>
|
||
/// 处理流程 / Processing Flow:
|
||
/// <list type="number">
|
||
/// <item>添加起始符 ':' (0x3A) / Add start marker ':' (0x3A)</item>
|
||
/// <item>将每个字节转换为 2 个十六进制 ASCII 字符 / Convert each byte to 2 hex ASCII characters</item>
|
||
/// <item>计算 LRC 校验码并转换为 ASCII / Calculate LRC checksum and convert to ASCII</item>
|
||
/// <item>添加结束符 CR LF (0x0D 0x0A) / Add end marker CR LF (0x0D 0x0A)</item>
|
||
/// </list>
|
||
/// </para>
|
||
/// <para>
|
||
/// 示例 / Example:
|
||
/// <code>
|
||
/// 原始数据 / Raw data: [0x01, 0x03, 0x00, 0x00]
|
||
/// 扩展后 / Extended: [0x3A, 0x30, 0x31, 0x30, 0x33, 0x30, 0x30, 0x30, 0x30, LRC, 0x0D, 0x0A]
|
||
/// ASCII: ":01030000[LRC][CR][LF]"
|
||
/// </code>
|
||
/// </para>
|
||
/// </remarks>
|
||
/// </summary>
|
||
/// <param name="content">
|
||
/// 扩展前的原始协议内容 / Original Protocol Content Before Extension
|
||
/// <remarks>
|
||
/// 二进制格式的 Modbus 数据
|
||
/// Binary format Modbus data
|
||
/// </remarks>
|
||
/// </param>
|
||
/// <returns>
|
||
/// 扩展后的协议内容 / Extended Protocol Content
|
||
/// <remarks>
|
||
/// ASCII 格式的完整帧
|
||
/// Complete frame in ASCII format
|
||
/// </remarks>
|
||
/// </returns>
|
||
public byte[] BytesExtend(byte[] content)
|
||
{
|
||
// Modbus/ASCII 协议扩张,前面增加:,后面增加 LRC 校验和尾字符
|
||
// Modbus/ASCII protocol extension, add ':' at front, LRC and tail characters at end
|
||
var newContent = new List<byte>();
|
||
|
||
// 添加起始符 ':' / Add start marker ':'
|
||
newContent.AddRange(Encoding.ASCII.GetBytes(":"));
|
||
|
||
// 将每个字节转换为 2 个十六进制 ASCII 字符 / Convert each byte to 2 hex ASCII characters
|
||
foreach (var number in content)
|
||
newContent.AddRange(Encoding.ASCII.GetBytes(number.ToString("X2")));
|
||
|
||
// 计算并添加 LRC 校验 / Calculate and add LRC checksum
|
||
newContent.AddRange(Encoding.ASCII.GetBytes(Crc16.GetInstance().GetLRC(content)));
|
||
|
||
// 添加结束符 CR LF / Add end marker CR LF
|
||
newContent.Add(0x0d);
|
||
newContent.Add(0x0a);
|
||
|
||
return newContent.ToArray();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 协议收缩 (接收后调用) / Protocol Reduce (Called After Receiving)
|
||
/// <remarks>
|
||
/// 将 ASCII 格式数据转换回二进制格式,移除起始符、LRC 校验和结束符
|
||
/// Convert ASCII format data back to binary format, remove start marker, LRC checksum and end marker
|
||
/// <para>
|
||
/// 处理流程 / Processing Flow:
|
||
/// <list type="number">
|
||
/// <item>转换为字符串 / Convert to string</item>
|
||
/// <item>查找换行符位置 / Find newline position</item>
|
||
/// <item>移除起始符 ':' 和结束符 CRLF / Remove start marker ':' and end marker CRLF</item>
|
||
/// <item>每 2 个字符解析为一个字节 / Parse every 2 characters as one byte</item>
|
||
/// <item>移除 LRC 校验字节 / Remove LRC checksum byte</item>
|
||
/// </list>
|
||
/// </para>
|
||
/// <para>
|
||
/// 示例 / Example:
|
||
/// <code>
|
||
/// ASCII: ":01030000000AF8[CR][LF]"
|
||
/// 移除头尾 / Remove head and tail: "01030000000AF8"
|
||
/// 解析字节 / Parse bytes: [0x01, 0x03, 0x00, 0x00, 0x00, 0x0A, 0xF8]
|
||
/// 移除 LRC / Remove LRC: [0x01, 0x03, 0x00, 0x00, 0x00, 0x0A]
|
||
/// </code>
|
||
/// </para>
|
||
/// </remarks>
|
||
/// </summary>
|
||
/// <param name="content">
|
||
/// 收缩前的完整协议内容 / Complete Protocol Content Before Reduction
|
||
/// <remarks>
|
||
/// ASCII 格式的完整帧
|
||
/// Complete frame in ASCII format
|
||
/// </remarks>
|
||
/// </param>
|
||
/// <returns>
|
||
/// 收缩后的协议内容 / Reduced Protocol Content
|
||
/// <remarks>
|
||
/// 二进制格式的 Modbus 数据
|
||
/// Binary format Modbus data
|
||
/// </remarks>
|
||
/// </returns>
|
||
public byte[] BytesDecact(byte[] content)
|
||
{
|
||
// Modbus/ASCII 协议收缩,抛弃头尾
|
||
// Modbus/ASCII protocol reduction, discard head and tail
|
||
var newContent = new List<byte>();
|
||
var ans = Encoding.ASCII.GetString(content);
|
||
|
||
// 查找换行符位置 / Find newline position
|
||
var index = ans.IndexOf(Environment.NewLine);
|
||
|
||
// 移除起始符 ':' 和结束符 CRLF / Remove start marker ':' and end marker CRLF
|
||
ans = ans.Substring(1, index - 1);
|
||
|
||
// 每 2 个字符解析为一个字节 / Parse every 2 characters as one byte
|
||
for (var i = 0; i < ans.Length; i += 2)
|
||
{
|
||
var number = byte.Parse(ans.Substring(i, 2), NumberStyles.HexNumber);
|
||
newContent.Add(number);
|
||
}
|
||
|
||
// 移除最后一个字节 (LRC 校验) / Remove last byte (LRC checksum)
|
||
newContent.RemoveAt(newContent.Count - 1);
|
||
|
||
return newContent.ToArray();
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
|
||
/// <summary>
|
||
/// Modbus RTU 协议接收器字节伸缩 / Modbus RTU Protocol Receiver Bytes Extend
|
||
/// <remarks>
|
||
/// 继承自 ModbusRtuProtocolLinkerBytesExtend,用于服务器端
|
||
/// Inherits from ModbusRtuProtocolLinkerBytesExtend, for server-side use
|
||
/// </remarks>
|
||
/// </summary>
|
||
public class ModbusRtuProtocolReceiverBytesExtend : ModbusRtuProtocolLinkerBytesExtend
|
||
{
|
||
// 使用 RTU 协议的字节伸缩方法 / Use RTU protocol bytes extend methods
|
||
}
|
||
}
|