Skip to content

Commit d76e4d2

Browse files
committed
fix: Slave 온전한 패킷 수신을 위한 버퍼 추가
- 리스트로 버퍼 관리 - 예상 길이로 대기 혹은 처리 - Helper 함수에 추가
1 parent 2a2db66 commit d76e4d2

File tree

2 files changed

+81
-30
lines changed

2 files changed

+81
-30
lines changed

ModBusSimulatorSlave/Data/PacketHelpers.cs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
{
33
internal static class PacketHelpers
44
{
5-
65
public static ushort CalcCRC(byte[] data, int offset, int count)
76
{
87
ushort crc = 0xFFFF;
@@ -27,5 +26,34 @@ public static ushort CalcCRC(byte[] data, int offset, int count)
2726

2827
return crc;
2928
}
29+
30+
public static bool CheckCRC(byte[] buffer)
31+
{
32+
ushort crc = CalcCRC(buffer, 0, buffer.Length - 2);
33+
return crc == (ushort)(buffer[buffer.Length - 2] | (buffer[buffer.Length - 1] << 8));
34+
}
35+
36+
public static int GetExpectedRequestPKLength(byte[] buffer)
37+
{
38+
int functionCode = buffer[1];
39+
return functionCode switch
40+
{
41+
0x01 or 0x02 or 0x03 or 0x04 or 0x05 or 0x06 => 8,
42+
0x0F or 0x10 => 9 + buffer[6], // Write Multiple 패킷 길이
43+
_ => 8
44+
45+
};
46+
}
47+
48+
public static int GetExpectedResponsePKLength(byte[] buffer)
49+
{
50+
int functionCode = buffer[1];
51+
return functionCode switch
52+
{
53+
0x01 or 0x02 or 0x03 or 0x04 => 5 + buffer[2], // Read 패킷 길이
54+
0x05 or 0x06 or 0x0F or 0x10 => 8, // Write 패킷 길이
55+
_ => 5,
56+
};
57+
}
3058
}
3159
}

ModBusSimulatorSlave/SerialPortConnector.cs

Lines changed: 52 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ public class SerialPortConnector
88
{
99
private SerialPort seriallPort = new();
1010
private VirtualDevice device = new(1, 10, 10);
11-
private Service service;
11+
private readonly Service service;
12+
13+
private readonly Object packBufferLock = new();
1214
private readonly List<byte> packetBuffer = [];
1315

1416
public SerialPortConnector()
@@ -41,39 +43,60 @@ private async void DataReceivedHandler(object sender, SerialDataReceivedEventArg
4143
sp.Read(buffer, 0, buffer.Length);
4244

4345
Debug.WriteLine($"버퍼 {buffer}");
44-
buffer.ToList().ForEach(e => Debug.Write($"{e.ToString("X2")} "));
45-
Debug.WriteLine("");
46-
47-
packetBuffer.AddRange(buffer);
48-
49-
var packet = new RequestPacket(buffer);
50-
byte[] crc = new byte[2];
51-
Array.Copy(buffer, buffer.Length - 2, crc, 0, 2);
52-
53-
if (crc[0] != packet.Crc[0] && crc[1] != packet.Crc[1])
54-
{
55-
Console.Error.WriteLine("CRC 불일치");
56-
return;
57-
}
58-
59-
Debug.WriteLine("수신 데이터");
60-
Debug.WriteLine($"SlaveAddr: {packet.SlaveAddr} FunctioanCode: {packet.FunctionCode}");
61-
packet.Data.ToList().ForEach(e => Debug.Write($"{e.ToString("X2")} "));
46+
buffer.ToList().ForEach(e => Debug.Write($"{e:X2} "));
6247
Debug.WriteLine("");
6348

64-
ResponsePacket? response = service.Response(packet);
49+
ProcessPacketBuffer(buffer);
50+
}
6551

66-
if (response == null)
52+
private void ProcessPacketBuffer(byte[] bytes)
53+
{
54+
lock(packBufferLock)
6755
{
68-
Debug.WriteLine("응답 데이터 없음");
69-
return;
56+
packetBuffer.AddRange(bytes);
57+
while(packetBuffer.Count >= 8)
58+
{
59+
int expectedLength = PacketHelpers.GetExpectedRequestPKLength(packetBuffer.ToArray());
60+
61+
if (packetBuffer.Count < expectedLength) break;
62+
63+
byte[] packetBytes = packetBuffer.GetRange(0, expectedLength).ToArray();
64+
65+
if (PacketHelpers.CheckCRC(packetBytes))
66+
{
67+
var packet = new RequestPacket(packetBytes);
68+
69+
Debug.WriteLine("수신 데이터");
70+
Debug.WriteLine($"SlaveAddr: {packet.SlaveAddr} FunctioanCode: {packet.FunctionCode}");
71+
packet.Data.ToList().ForEach(e => Debug.Write($"{e:X2} "));
72+
Debug.WriteLine("");
73+
74+
ResponsePacket? response = service.Response(packet);
75+
byte[] frame;
76+
77+
if (response == null)
78+
{
79+
Debug.WriteLine("응답 데이터 없음");
80+
frame = [1];
81+
}
82+
else
83+
{
84+
frame = response.Frame;
85+
Debug.WriteLine("응답 데이터");
86+
frame.ToList().ForEach(e => Debug.Write($"{e:X2} "));
87+
Debug.WriteLine("");
88+
}
89+
90+
seriallPort.Write(frame, 0, frame.Length);
91+
packetBuffer.RemoveRange(0, expectedLength);
92+
} else
93+
{
94+
Console.Error.WriteLine("CRC 불일치");
95+
packetBuffer.RemoveAt(0);
96+
}
97+
98+
}
7099
}
71-
72-
byte[] frame = response.Frame;
73-
Debug.WriteLine("응답 데이터");
74-
frame.ToList().ForEach(e => Debug.Write($"{e.ToString("X2")} "));
75-
Debug.WriteLine("");
76-
seriallPort.Write(frame, 0, frame.Length);
77100
}
78101

79102
public void Open(string portName)

0 commit comments

Comments
 (0)