OmronFinsNetHelper.cs
14.2 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
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
using HslCommunication.BasicFramework;
using System;
namespace HslCommunication.Profinet.Omron
{
/// <summary>
/// Omron PLC的FINS协议相关的辅助类
/// </summary>
public class OmronFinsNetHelper
{
#region Static Method Helper
/// <summary>
/// 解析数据地址,Omron手册第188页
/// </summary>
/// <param name="address">数据地址</param>
/// <param name="isBit">是否是位地址</param>
/// <returns>解析后的结果地址对象</returns>
public static OperateResult<OmronFinsDataType, byte[]> AnalysisAddress(string address, bool isBit)
{
var result = new OperateResult<OmronFinsDataType, byte[]>();
try
{
switch (address[0])
{
case 'D':
case 'd':
{
// DM区数据
result.Content1 = OmronFinsDataType.DM;
break;
}
case 'C':
case 'c':
{
// CIO区数据
result.Content1 = OmronFinsDataType.CIO;
break;
}
case 'W':
case 'w':
{
// WR区
result.Content1 = OmronFinsDataType.WR;
break;
}
case 'H':
case 'h':
{
// HR区
result.Content1 = OmronFinsDataType.HR;
break;
}
case 'A':
case 'a':
{
// AR区
result.Content1 = OmronFinsDataType.AR;
break;
}
case 'E':
case 'e':
{
// E区,比较复杂,需要专门的计算
string[] splits = address.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
int block = Convert.ToInt32(splits[0].Substring(1), 16);
if (block < 16)
{
result.Content1 = new OmronFinsDataType((byte)(0x20 + block), (byte)(0xA0 + block));
}
else
{
result.Content1 = new OmronFinsDataType((byte)(0xE0 + block - 16), (byte)(0x60 + block - 16));
}
break;
}
default: throw new Exception(StringResources.Language.NotSupportedDataType);
}
if (address[0] == 'E' || address[0] == 'e')
{
string[] splits = address.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
if (isBit)
{
// 位操作
ushort addr = ushort.Parse(splits[1]);
result.Content2 = new byte[3];
result.Content2[0] = BitConverter.GetBytes(addr)[1];
result.Content2[1] = BitConverter.GetBytes(addr)[0];
if (splits.Length > 2)
{
result.Content2[2] = byte.Parse(splits[2]);
if (result.Content2[2] > 15)
{
throw new Exception(StringResources.Language.OmronAddressMustBeZeroToFiveteen);
}
}
}
else
{
// 字操作
ushort addr = ushort.Parse(splits[1]);
result.Content2 = new byte[3];
result.Content2[0] = BitConverter.GetBytes(addr)[1];
result.Content2[1] = BitConverter.GetBytes(addr)[0];
}
}
else
{
if (isBit)
{
// 位操作
string[] splits = address.Substring(1).Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);
ushort addr = ushort.Parse(splits[0]);
result.Content2 = new byte[3];
result.Content2[0] = BitConverter.GetBytes(addr)[1];
result.Content2[1] = BitConverter.GetBytes(addr)[0];
if (splits.Length > 1)
{
result.Content2[2] = byte.Parse(splits[1]);
if (result.Content2[2] > 15)
{
throw new Exception(StringResources.Language.OmronAddressMustBeZeroToFiveteen);
}
}
}
else
{
// 字操作
ushort addr = ushort.Parse(address.Substring(1));
result.Content2 = new byte[3];
result.Content2[0] = BitConverter.GetBytes(addr)[1];
result.Content2[1] = BitConverter.GetBytes(addr)[0];
}
}
}
catch (Exception ex)
{
result.Message = ex.Message;
return result;
}
result.IsSuccess = true;
return result;
}
/// <summary>
/// 根据读取的地址,长度,是否位读取创建Fins协议的核心报文
/// </summary>
/// <param name="address">地址,具体格式请参照示例说明</param>
/// <param name="length">读取的数据长度</param>
/// <param name="isBit">是否使用位读取</param>
/// <returns>带有成功标识的Fins核心报文</returns>
public static OperateResult<byte[]> BuildReadCommand(string address, ushort length, bool isBit)
{
var analysis = OmronFinsNetHelper.AnalysisAddress(address, isBit);
if (!analysis.IsSuccess) return OperateResult.CreateFailedResult<byte[]>(analysis);
byte[] _PLCCommand = new byte[8];
_PLCCommand[0] = 0x01; // 读取存储区数据
_PLCCommand[1] = 0x01;
if (isBit)
{
_PLCCommand[2] = analysis.Content1.BitCode;
}
else
{
_PLCCommand[2] = analysis.Content1.WordCode;
}
analysis.Content2.CopyTo(_PLCCommand, 3);
_PLCCommand[6] = (byte)(length / 256); // 长度
_PLCCommand[7] = (byte)(length % 256);
return OperateResult.CreateSuccessResult(_PLCCommand);
}
/// <summary>
/// 根据写入的地址,数据,是否位写入生成Fins协议的核心报文
/// </summary>
/// <param name="address">地址内容,具体格式请参照示例说明</param>
/// <param name="value">实际的数据</param>
/// <param name="isBit">是否位数据</param>
/// <returns>带有成功标识的Fins核心报文</returns>
public static OperateResult<byte[]> BuildWriteWordCommand(string address, byte[] value, bool isBit)
{
var analysis = OmronFinsNetHelper.AnalysisAddress(address, isBit);
if (!analysis.IsSuccess) return OperateResult.CreateFailedResult<byte[]>(analysis);
byte[] _PLCCommand = new byte[8 + value.Length];
_PLCCommand[0] = 0x01;
_PLCCommand[1] = 0x02;
if (isBit)
{
_PLCCommand[2] = analysis.Content1.BitCode;
}
else
{
_PLCCommand[2] = analysis.Content1.WordCode;
}
analysis.Content2.CopyTo(_PLCCommand, 3);
if (isBit)
{
_PLCCommand[6] = (byte)(value.Length / 256);
_PLCCommand[7] = (byte)(value.Length % 256);
}
else
{
_PLCCommand[6] = (byte)(value.Length / 2 / 256);
_PLCCommand[7] = (byte)(value.Length / 2 % 256);
}
value.CopyTo(_PLCCommand, 8);
return OperateResult.CreateSuccessResult(_PLCCommand);
}
/// <summary>
/// 验证欧姆龙的Fins-TCP返回的数据是否正确的数据,如果正确的话,并返回所有的数据内容
/// </summary>
/// <param name="response">来自欧姆龙返回的数据内容</param>
/// <param name="isRead">是否读取</param>
/// <returns>带有是否成功的结果对象</returns>
public static OperateResult<byte[]> ResponseValidAnalysis(byte[] response, bool isRead)
{
if (response.Length >= 16)
{
// 提取错误码 -> Extracting error Codes
byte[] buffer = new byte[4];
buffer[0] = response[15];
buffer[1] = response[14];
buffer[2] = response[13];
buffer[3] = response[12];
int err = BitConverter.ToInt32(buffer, 0);
if (err > 0) return new OperateResult<byte[]>(err, GetStatusDescription(err));
byte[] result = new byte[response.Length - 16];
Array.Copy(response, 16, result, 0, result.Length);
return UdpResponseValidAnalysis(result, isRead);
//if (response.Length >= 30)
//{
// err = response[28] * 256 + response[29];
// // if (err > 0) return new OperateResult<byte[]>( err, StringResources.Language.OmronReceiveDataError );
// if (!isRead)
// {
// OperateResult<byte[]> success = OperateResult.CreateSuccessResult( new byte[0] );
// success.ErrorCode = err;
// success.Message = GetStatusDescription( err );
// return success;
// }
// else
// {
// // 读取操作 -> read operate
// byte[] content = new byte[response.Length - 30];
// if (content.Length > 0) Array.Copy( response, 30, content, 0, content.Length );
// OperateResult<byte[]> success = OperateResult.CreateSuccessResult( content );
// if (content.Length == 0) success.IsSuccess = false;
// success.ErrorCode = err;
// success.Message = GetStatusDescription( err );
// return success;
// }
//}
}
return new OperateResult<byte[]>(StringResources.Language.OmronReceiveDataError);
}
/// <summary>
/// 验证欧姆龙的Fins-Udp返回的数据是否正确的数据,如果正确的话,并返回所有的数据内容
/// </summary>
/// <param name="response">来自欧姆龙返回的数据内容</param>
/// <param name="isRead">是否读取</param>
/// <returns>带有是否成功的结果对象</returns>
public static OperateResult<byte[]> UdpResponseValidAnalysis(byte[] response, bool isRead)
{
if (response.Length >= 14)
{
int err = response[12] * 256 + response[13];
// if (err > 0) return new OperateResult<byte[]>( err, StringResources.Language.OmronReceiveDataError );
if (!isRead)
{
OperateResult<byte[]> success = OperateResult.CreateSuccessResult(new byte[0]);
success.ErrorCode = err;
success.Message = GetStatusDescription(err) + " Received:" + SoftBasic.ByteToHexString(response, ' ');
return success;
}
else
{
// 读取操作 -> read operate
byte[] content = new byte[response.Length - 14];
if (content.Length > 0) Array.Copy(response, 14, content, 0, content.Length);
OperateResult<byte[]> success = OperateResult.CreateSuccessResult(content);
if (content.Length == 0) success.IsSuccess = false;
success.ErrorCode = err;
success.Message = GetStatusDescription(err) + " Received:" + SoftBasic.ByteToHexString(response, ' ');
return success;
}
}
return new OperateResult<byte[]>(StringResources.Language.OmronReceiveDataError);
}
/// <summary>
/// 获取错误信息的字符串描述文本
/// </summary>
/// <param name="err">错误码</param>
/// <returns>文本描述</returns>
public static string GetStatusDescription(int err)
{
switch (err)
{
case 0: return StringResources.Language.OmronStatus0;
case 1: return StringResources.Language.OmronStatus1;
case 2: return StringResources.Language.OmronStatus2;
case 3: return StringResources.Language.OmronStatus3;
case 20: return StringResources.Language.OmronStatus20;
case 21: return StringResources.Language.OmronStatus21;
case 22: return StringResources.Language.OmronStatus22;
case 23: return StringResources.Language.OmronStatus23;
case 24: return StringResources.Language.OmronStatus24;
case 25: return StringResources.Language.OmronStatus25;
default: return StringResources.Language.UnknownError;
}
}
#endregion
}
}