Dreamine.PLC.Omron.Fins
1.0.1
Dreamine.PLC.Omron.Fins 산업 자동화 및 I/O 기능을 제공합니다.
Toggle main menu visibility
로딩중...
검색중...
일치하는것 없음
OmronFinsSimulatorProtocol.cs
이 파일의 문서화 페이지로 가기
1
using
Dreamine.PLC.Abstractions.Devices;
2
using
Dreamine.PLC.Abstractions.Results;
3
using
Dreamine.PLC.Core.Memory;
4
using
Dreamine.PLC.Omron.Fins.Devices
;
5
using
Dreamine.PLC.Omron.Fins.Protocol
;
6
7
namespace
Dreamine.PLC.Omron.Fins.Simulation
;
8
17
public
sealed
class
OmronFinsSimulatorProtocol
18
{
27
private
readonly InMemoryPlcMemory
_memory
;
36
private
readonly
OmronFinsSimulatorServerOptions
_options
;
37
70
public
OmronFinsSimulatorProtocol
(InMemoryPlcMemory memory,
OmronFinsSimulatorServerOptions
options)
71
{
72
_memory
= memory ??
throw
new
ArgumentNullException(nameof(memory));
73
_options
= options ??
throw
new
ArgumentNullException(nameof(options));
74
}
75
84
public
event
EventHandler<string>?
StatusChanged
;
85
118
public
byte
[]
HandleRequest
(IReadOnlyList<byte> requestFrame)
119
{
120
ArgumentNullException.ThrowIfNull(requestFrame);
121
var request = requestFrame as
byte
[] ?? requestFrame.ToArray();
122
123
if
(!
TryParseRequest
(request, out var parsed, out var errorMessage))
124
{
125
StatusChanged
?.Invoke(
this
, errorMessage ??
"Invalid FINS request."
);
126
return
BuildErrorResponse
(request, 0x1101);
127
}
128
129
return
parsed.Command
switch
130
{
131
(ushort)
OmronFinsCommand
.MemoryAreaRead =>
HandleRead
(request, parsed),
132
(ushort)
OmronFinsCommand
.MemoryAreaWrite =>
HandleWrite
(request, parsed),
133
_ =>
BuildErrorResponse
(request, 0x0101)
134
};
135
}
136
169
private
byte
[]
HandleRead
(
byte
[] requestFrame,
FinsRequest
request)
170
{
171
if
(request.
IsBitAccess
)
172
{
173
var readResult =
_memory
.ReadBits(request.Address, request.Count);
174
if
(!readResult.IsSuccess || readResult.Value is
null
)
175
{
176
return
BuildErrorResponse
(requestFrame, 0x2101);
177
}
178
179
var payload = readResult.Value.Select(value => value ? (
byte
)1 : (
byte
)0).ToArray();
180
return
BuildResponse
(requestFrame, request.Command, 0, payload);
181
}
182
183
var wordResult =
_memory
.ReadWords(request.Address, request.Count);
184
if
(!wordResult.IsSuccess || wordResult.Value is
null
)
185
{
186
return
BuildErrorResponse
(requestFrame, 0x2101);
187
}
188
189
var wordPayload =
new
byte
[wordResult.Value.Length * 2];
190
for
(var index = 0; index < wordResult.Value.Length; index++)
191
{
192
OmronFinsEndian
.
WriteInt16
(wordPayload, index * 2, wordResult.Value[index]);
193
}
194
195
return
BuildResponse
(requestFrame, request.Command, 0, wordPayload);
196
}
197
238
private
byte
[]
HandleWrite
(
byte
[] requestFrame,
FinsRequest
request)
239
{
240
if
(request.
IsBitAccess
)
241
{
242
if
(request.Data.Length < request.Count)
243
{
244
return
BuildErrorResponse
(requestFrame, 0x1101);
245
}
246
247
var values =
new
bool
[request.Count];
248
for
(var index = 0; index < request.Count; index++)
249
{
250
values[index] = request.Data[index] != 0;
251
}
252
253
var writeResult =
_memory
.WriteBits(request.Address, values);
254
if
(!writeResult.IsSuccess)
255
{
256
return
BuildErrorResponse
(requestFrame, 0x2101);
257
}
258
}
259
else
260
{
261
var expectedLength = checked(request.Count * 2);
262
if
(request.Data.Length < expectedLength)
263
{
264
return
BuildErrorResponse
(requestFrame, 0x1101);
265
}
266
267
var values =
new
short
[request.Count];
268
for
(var index = 0; index < request.Count; index++)
269
{
270
values[index] =
OmronFinsEndian
.
ReadInt16
(request.Data, index * 2);
271
}
272
273
var writeResult =
_memory
.WriteWords(request.Address, values);
274
if
(!writeResult.IsSuccess)
275
{
276
return
BuildErrorResponse
(requestFrame, 0x2101);
277
}
278
279
ApplyAutoWordResponse
(request.Address, values);
280
}
281
282
return
BuildResponse
(requestFrame, request.Command, 0, []);
283
}
284
309
private
void
ApplyAutoWordResponse
(PlcAddress writeAddress, IReadOnlyList<short> values)
310
{
311
if
(!
_options
.EnableAutoWordResponse || values.Count != 1)
312
{
313
return
;
314
}
315
316
if
(writeAddress.DeviceType != PlcDeviceType.D || writeAddress.Offset !=
_options
.AutoResponseTriggerOffset)
317
{
318
return
;
319
}
320
321
var rawResponseValue = values[0] +
_options
.AutoResponseIncrement;
322
if
(rawResponseValue is < short.MinValue or >
short
.MaxValue)
323
{
324
StatusChanged
?.Invoke(
this
, $
"FINS auto response skipped: value overflow. value={rawResponseValue}"
);
325
return
;
326
}
327
328
var responseValue = (short)rawResponseValue;
329
var responseAddress =
new
PlcAddress(PlcDeviceType.D,
_options
.AutoResponseOffset);
330
_memory
.WriteWords(responseAddress, [responseValue]);
331
StatusChanged
?.Invoke(
this
, $
"FINS auto response: D{_options.AutoResponseOffset}={responseValue}"
);
332
}
333
374
private
static
bool
TryParseRequest
(
byte
[] frame, out
FinsRequest
request, out
string
? errorMessage)
375
{
376
request =
default
;
377
errorMessage =
null
;
378
379
if
(frame.Length < 18)
380
{
381
errorMessage = $
"The FINS request frame is too short. Length={frame.Length}."
;
382
return
false
;
383
}
384
385
var command =
OmronFinsEndian
.
ReadUInt16
(frame, 10);
386
var areaCode = frame[12];
387
var offset =
OmronFinsEndian
.
ReadUInt16
(frame, 13);
388
var bitOffset = frame[15];
389
var count =
OmronFinsEndian
.
ReadUInt16
(frame, 16);
390
var data = frame.Length > 18 ? frame[18..] : [];
391
var deviceType =
OmronFinsMemoryAreaMapper
.
ToDeviceType
(areaCode);
392
393
if
(deviceType == PlcDeviceType.Unknown)
394
{
395
errorMessage = $
"Unsupported FINS memory area code: 0x{areaCode:X2}."
;
396
return
false
;
397
}
398
399
request =
new
FinsRequest
(
400
command,
401
areaCode,
402
new
PlcAddress(deviceType, offset,
OmronFinsMemoryAreaMapper
.
IsBitArea
(areaCode) ? bitOffset :
null
),
403
count,
404
data);
405
return
true
;
406
}
407
440
private
static
byte
[]
BuildErrorResponse
(
byte
[] requestFrame, ushort endCode)
441
{
442
var command = requestFrame.Length >= 12 ?
OmronFinsEndian
.
ReadUInt16
(requestFrame, 10) : (ushort)0;
443
return
BuildResponse
(requestFrame, command, endCode, []);
444
}
445
502
private
static
byte
[]
BuildResponse
(
byte
[] requestFrame, ushort command, ushort endCode, IReadOnlyList<byte> payload)
503
{
504
var response =
new
byte
[14 + payload.Count];
505
response[0] = requestFrame.Length > 0 ? requestFrame[0] : (byte)0xC0;
506
response[1] = requestFrame.Length > 1 ? requestFrame[1] : (byte)0x00;
507
response[2] = requestFrame.Length > 2 ? requestFrame[2] : (byte)0x02;
508
509
response[3] = requestFrame.Length > 6 ? requestFrame[6] : (byte)0x00;
510
response[4] = requestFrame.Length > 7 ? requestFrame[7] : (byte)0x00;
511
response[5] = requestFrame.Length > 8 ? requestFrame[8] : (byte)0x00;
512
response[6] = requestFrame.Length > 3 ? requestFrame[3] : (byte)0x00;
513
response[7] = requestFrame.Length > 4 ? requestFrame[4] : (byte)0x00;
514
response[8] = requestFrame.Length > 5 ? requestFrame[5] : (byte)0x00;
515
response[9] = requestFrame.Length > 9 ? requestFrame[9] : (byte)0x00;
516
517
OmronFinsEndian
.
WriteUInt16
(response, 10, command);
518
OmronFinsEndian
.
WriteUInt16
(response, 12, endCode);
519
520
for
(var index = 0; index < payload.Count; index++)
521
{
522
response[14 + index] = payload[index];
523
}
524
525
return
response;
526
}
527
576
private
readonly record
struct
FinsRequest
(
577
ushort Command,
578
byte AreaCode,
579
PlcAddress Address,
580
int Count,
581
byte[] Data)
582
{
591
public
bool
IsBitAccess
=>
OmronFinsMemoryAreaMapper
.
IsBitArea
(AreaCode);
592
}
593
}
Dreamine.PLC.Omron.Fins.Devices
Definition
OmronFinsMemoryAreaMapper.cs:4
Dreamine.PLC.Omron.Fins.Protocol
Definition
OmronFinsCommand.cs:1
Dreamine.PLC.Omron.Fins.Protocol.OmronFinsCommand
OmronFinsCommand
Definition
OmronFinsCommand.cs:12
Dreamine.PLC.Omron.Fins.Simulation
Definition
OmronFinsSimulatorProtocol.cs:7
Dreamine.PLC.Omron.Fins.Devices.OmronFinsMemoryAreaMapper
Definition
OmronFinsMemoryAreaMapper.cs:15
Dreamine.PLC.Omron.Fins.Devices.OmronFinsMemoryAreaMapper.ToDeviceType
static PlcDeviceType ToDeviceType(byte areaCode)
Definition
OmronFinsMemoryAreaMapper.cs:94
Dreamine.PLC.Omron.Fins.Devices.OmronFinsMemoryAreaMapper.IsBitArea
static bool IsBitArea(byte areaCode)
Definition
OmronFinsMemoryAreaMapper.cs:130
Dreamine.PLC.Omron.Fins.Protocol.OmronFinsEndian
Definition
OmronFinsEndian.cs:12
Dreamine.PLC.Omron.Fins.Protocol.OmronFinsEndian.WriteUInt16
static void WriteUInt16(Span< byte > buffer, int offset, ushort value)
Definition
OmronFinsEndian.cs:188
Dreamine.PLC.Omron.Fins.Protocol.OmronFinsEndian.ReadInt16
static short ReadInt16(ReadOnlySpan< byte > buffer, int offset)
Definition
OmronFinsEndian.cs:98
Dreamine.PLC.Omron.Fins.Protocol.OmronFinsEndian.WriteInt16
static void WriteInt16(Span< byte > buffer, int offset, short value)
Definition
OmronFinsEndian.cs:234
Dreamine.PLC.Omron.Fins.Protocol.OmronFinsEndian.ReadUInt16
static ushort ReadUInt16(ReadOnlySpan< byte > buffer, int offset)
Definition
OmronFinsEndian.cs:53
Dreamine.PLC.Omron.Fins.Simulation.OmronFinsSimulatorProtocol.OmronFinsSimulatorProtocol
OmronFinsSimulatorProtocol(InMemoryPlcMemory memory, OmronFinsSimulatorServerOptions options)
Definition
OmronFinsSimulatorProtocol.cs:70
Dreamine.PLC.Omron.Fins.Simulation.OmronFinsSimulatorProtocol.BuildResponse
static byte[] BuildResponse(byte[] requestFrame, ushort command, ushort endCode, IReadOnlyList< byte > payload)
Definition
OmronFinsSimulatorProtocol.cs:502
Dreamine.PLC.Omron.Fins.Simulation.OmronFinsSimulatorProtocol._options
readonly OmronFinsSimulatorServerOptions _options
Definition
OmronFinsSimulatorProtocol.cs:36
Dreamine.PLC.Omron.Fins.Simulation.OmronFinsSimulatorProtocol.ApplyAutoWordResponse
void ApplyAutoWordResponse(PlcAddress writeAddress, IReadOnlyList< short > values)
Definition
OmronFinsSimulatorProtocol.cs:309
Dreamine.PLC.Omron.Fins.Simulation.OmronFinsSimulatorProtocol.TryParseRequest
static bool TryParseRequest(byte[] frame, out FinsRequest request, out string? errorMessage)
Definition
OmronFinsSimulatorProtocol.cs:374
Dreamine.PLC.Omron.Fins.Simulation.OmronFinsSimulatorProtocol._memory
readonly InMemoryPlcMemory _memory
Definition
OmronFinsSimulatorProtocol.cs:27
Dreamine.PLC.Omron.Fins.Simulation.OmronFinsSimulatorProtocol.HandleRequest
byte[] HandleRequest(IReadOnlyList< byte > requestFrame)
Definition
OmronFinsSimulatorProtocol.cs:118
Dreamine.PLC.Omron.Fins.Simulation.OmronFinsSimulatorProtocol.BuildErrorResponse
static byte[] BuildErrorResponse(byte[] requestFrame, ushort endCode)
Definition
OmronFinsSimulatorProtocol.cs:440
Dreamine.PLC.Omron.Fins.Simulation.OmronFinsSimulatorProtocol.HandleWrite
byte[] HandleWrite(byte[] requestFrame, FinsRequest request)
Definition
OmronFinsSimulatorProtocol.cs:238
Dreamine.PLC.Omron.Fins.Simulation.OmronFinsSimulatorProtocol.HandleRead
byte[] HandleRead(byte[] requestFrame, FinsRequest request)
Definition
OmronFinsSimulatorProtocol.cs:169
Dreamine.PLC.Omron.Fins.Simulation.OmronFinsSimulatorProtocol.StatusChanged
EventHandler< string >? StatusChanged
Definition
OmronFinsSimulatorProtocol.cs:84
Dreamine.PLC.Omron.Fins.Simulation.OmronFinsSimulatorProtocol.FinsRequest
Definition
OmronFinsSimulatorProtocol.cs:582
Dreamine.PLC.Omron.Fins.Simulation.OmronFinsSimulatorProtocol.FinsRequest.IsBitAccess
bool IsBitAccess
Definition
OmronFinsSimulatorProtocol.cs:591
Dreamine.PLC.Omron.Fins.Simulation.OmronFinsSimulatorServerOptions
Definition
OmronFinsSimulatorServerOptions.cs:12
Simulation
OmronFinsSimulatorProtocol.cs
다음에 의해 생성됨 :
1.17.0