ModbusInfo.cs
7.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
using HslCommunication.Core.Address;
using System;
namespace HslCommunication.ModBus
{
/// <summary>
/// Modbus协议相关的一些信息
/// </summary>
public class ModbusInfo
{
#region Function Declaration
/// <summary>
/// 读取线圈
/// </summary>
public const byte ReadCoil = 0x01;
/// <summary>
/// 读取离散量
/// </summary>
public const byte ReadDiscrete = 0x02;
/// <summary>
/// 读取寄存器
/// </summary>
public const byte ReadRegister = 0x03;
/// <summary>
/// 读取输入寄存器
/// </summary>
public const byte ReadInputRegister = 0x04;
/// <summary>
/// 写单个线圈
/// </summary>
public const byte WriteOneCoil = 0x05;
/// <summary>
/// 写单个寄存器
/// </summary>
public const byte WriteOneRegister = 0x06;
/// <summary>
/// 写多个线圈
/// </summary>
public const byte WriteCoil = 0x0F;
/// <summary>
/// 写多个寄存器
/// </summary>
public const byte WriteRegister = 0x10;
#endregion
#region ErrCode Declaration
/// <summary>
/// 不支持该功能码
/// </summary>
public const byte FunctionCodeNotSupport = 0x01;
/// <summary>
/// 该地址越界
/// </summary>
public const byte FunctionCodeOverBound = 0x02;
/// <summary>
/// 读取长度超过最大值
/// </summary>
public const byte FunctionCodeQuantityOver = 0x03;
/// <summary>
/// 读写异常
/// </summary>
public const byte FunctionCodeReadWriteException = 0x04;
#endregion
#region Static Helper Method
/// <summary>
/// 将modbus指令打包成Modbus-Tcp指令
/// </summary>
/// <param name="value">Modbus指令</param>
/// <param name="id">消息的序号</param>
/// <returns>Modbus-Tcp指令</returns>
public static byte[] PackCommandToTcp(byte[] value, ushort id)
{
byte[] buffer = new byte[value.Length + 6];
buffer[0] = BitConverter.GetBytes(id)[1];
buffer[1] = BitConverter.GetBytes(id)[0];
buffer[4] = BitConverter.GetBytes(value.Length)[1];
buffer[5] = BitConverter.GetBytes(value.Length)[0];
value.CopyTo(buffer, 6);
return buffer;
}
#if !NETSTANDARD2_0
/// <summary>
/// 将modbus指令打包成Modbus-Rtu指令
/// </summary>
/// <param name="value">Modbus指令</param>
/// <returns>Modbus-Rtu指令</returns>
public static byte[] PackCommandToRtu( byte[] value )
{
return Serial.SoftCRC16.CRC16( value );
}
/// <summary>
/// 将一个modbus-rtu的数据报文,转换成modbus-ascii的数据报文
/// </summary>
/// <param name="value">modbus-rtu的完整报文,携带相关的校验码</param>
/// <returns>可以用于直接发送的modbus-ascii的报文</returns>
public static byte[] TransRtuToAsciiPackCommand( byte[] value )
{
// remove crc check
byte[] modbus = BasicFramework.SoftBasic.BytesArrayRemoveLast( value, 2 );
// add LRC check
byte[] modbus_lrc = Serial.SoftLRC.LRC( modbus );
// Translate to ascii information
byte[] modbus_ascii = BasicFramework.SoftBasic.BytesToAsciiBytes( modbus_lrc );
// add head and end informarion
return BasicFramework.SoftBasic.SpliceTwoByteArray( BasicFramework.SoftBasic.SpliceTwoByteArray( new byte[] { 0x3A }, modbus_ascii ), new byte[] { 0x0D, 0x0A } );
}
/// <summary>
/// 将一个modbus-ascii的数据报文,转换成的modbus核心数据报文
/// </summary>
/// <param name="value">modbus-ascii的完整报文,携带相关的校验码</param>
/// <returns>可以用于直接发送的modbus的报文</returns>
public static OperateResult<byte[]> TransAsciiPackCommandToRtu( byte[] value )
{
try
{
// response check
if (value[0] != 0x3A || value[value.Length - 2] != 0x0D || value[value.Length - 1] != 0x0A)
return new OperateResult<byte[]>( ) { Message = StringResources.Language.ModbusAsciiFormatCheckFailed + BasicFramework.SoftBasic.ByteToHexString( value ) };
// remove head and end
byte[] modbus_ascii = BasicFramework.SoftBasic.BytesArrayRemoveDouble( value, 1, 2 );
// get modbus core
byte[] modbus_core = BasicFramework.SoftBasic.AsciiBytesToBytes( modbus_ascii );
if (!Serial.SoftLRC.CheckLRC( modbus_core ))
return new OperateResult<byte[]>( ) { Message = StringResources.Language.ModbusLRCCheckFailed + BasicFramework.SoftBasic.ByteToHexString( modbus_core ) };
// remove the last info
return OperateResult.CreateSuccessResult( BasicFramework.SoftBasic.BytesArrayRemoveLast( modbus_core, 1 ) );
}
catch(Exception ex)
{
return new OperateResult<byte[]>( ) { Message = ex.Message + BasicFramework.SoftBasic.ByteToHexString( value ) };
}
}
#endif
/// <summary>
/// 分析Modbus协议的地址信息,该地址适应于tcp及rtu模式
/// </summary>
/// <param name="address">带格式的地址,比如"100","x=4;100","s=1;100","s=1;x=4;100"</param>
/// <param name="isStartWithZero">起始地址是否从0开始</param>
/// <param name="defaultFunction">默认的功能码信息</param>
/// <returns>转换后的地址信息</returns>
public static OperateResult<ModbusAddress> AnalysisAddress(string address, bool isStartWithZero, byte defaultFunction)
{
try
{
ModbusAddress mAddress = new ModbusAddress(address, defaultFunction);
if (!isStartWithZero)
{
if (mAddress.Address < 1) throw new Exception(StringResources.Language.ModbusAddressMustMoreThanOne);
mAddress.Address = (ushort)(mAddress.Address - 1);
}
return OperateResult.CreateSuccessResult(mAddress);
}
catch (Exception ex)
{
return new OperateResult<ModbusAddress>() { Message = ex.Message };
}
}
/// <summary>
/// 通过错误码来获取到对应的文本消息
/// </summary>
/// <param name="code">错误码</param>
/// <returns>错误的文本描述</returns>
public static string GetDescriptionByErrorCode(byte code)
{
switch (code)
{
case ModbusInfo.FunctionCodeNotSupport: return StringResources.Language.ModbusTcpFunctionCodeNotSupport;
case ModbusInfo.FunctionCodeOverBound: return StringResources.Language.ModbusTcpFunctionCodeOverBound;
case ModbusInfo.FunctionCodeQuantityOver: return StringResources.Language.ModbusTcpFunctionCodeQuantityOver;
case ModbusInfo.FunctionCodeReadWriteException: return StringResources.Language.ModbusTcpFunctionCodeReadWriteException;
default: return StringResources.Language.UnknownError;
}
}
#endregion
}
}