commit 5d286d5179077e687fe53bbdb4c6a78b219ac429 Author: chi Date: Tue Apr 22 11:36:27 2025 +0900 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6f0598c --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +obj +bin +*.user +*.v12 +*.suo +.git +.vs +Debug +__vm +*.pdb +desktop.ini +packages +~*.xlsx diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..359cd76 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "dotnet.preferCSharpExtension": true +} \ No newline at end of file diff --git a/ENIGProtocol.Tests/EEProtocolTests.cs b/ENIGProtocol.Tests/EEProtocolTests.cs new file mode 100644 index 0000000..f54a8d7 --- /dev/null +++ b/ENIGProtocol.Tests/EEProtocolTests.cs @@ -0,0 +1,52 @@ +using Xunit; +using ENIG; + +namespace ENIGProtocol.Tests +{ + public class EEProtocolTests + { + [Fact] + public void TestCRC16Calculation() + { + // 테스트 데이터 + byte[] testData = new byte[] { 0x02,0x00,0xFF }; + + // CRC16 계산 + var protocol = new EEProtocol(); + ushort crc = protocol.CalculateCRC16(testData); + + // 예상 결과와 비교 + Assert.Equal(0x1789, crc); // 실제 예상값으로 수정 필요 + } + + [Fact] + public void TestPacketCreation() + { + // 패킷 생성 테스트 + var protocol = new EEProtocol(); + byte[] packet = protocol.CreatePacket(0x01, 0x02, new byte[] { 0x03, 0x04 }); + + // 패킷 구조 검증 + Assert.Equal(0x02, packet[0]); // STX + Assert.Equal(0x04, packet[1]); // Length + Assert.Equal(0x01, packet[2]); // ID + Assert.Equal(0x02, packet[3]); // Command + Assert.Equal(0x03, packet[4]); // Data[0] + Assert.Equal(0x04, packet[5]); // Data[1] + } + + [Fact] + public void TestPacketParsing() + { + // 패킷 파싱 테스트 + var protocol = new EEProtocol(); + //byte[] testPacket = new byte[] { 0x02, 0x04, 0x01, 0x02, 0x03, 0x04, 0x12, 0x34, 0x03 }; + byte[] testPacket = new byte[] { 0x02, 0x02, 0x00, 0xFF, 0x89, 0x17, 0x03 }; + + + bool result = protocol.ParsePacket(testPacket); + + Assert.True(result); + } + } +} \ No newline at end of file diff --git a/ENIGProtocol.Tests/ENIGProtocol.Tests.csproj b/ENIGProtocol.Tests/ENIGProtocol.Tests.csproj new file mode 100644 index 0000000..fcb8f69 --- /dev/null +++ b/ENIGProtocol.Tests/ENIGProtocol.Tests.csproj @@ -0,0 +1,33 @@ + + + + net6.0 + enable + enable + + false + true + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + + + diff --git a/ENIGProtocol.Tests/UnitTest1.cs b/ENIGProtocol.Tests/UnitTest1.cs new file mode 100644 index 0000000..5ed2225 --- /dev/null +++ b/ENIGProtocol.Tests/UnitTest1.cs @@ -0,0 +1,10 @@ +namespace ENIGProtocol.Tests; + +public class UnitTest1 +{ + [Fact] + public void Test1() + { + + } +} \ No newline at end of file diff --git a/ENIGProtocol.sln b/ENIGProtocol.sln new file mode 100644 index 0000000..3fc2298 --- /dev/null +++ b/ENIGProtocol.sln @@ -0,0 +1,37 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.9.34714.143 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ENIGProtocol", "enigprotocol\ENIGProtocol.csproj", "{B6FCA1B0-C9D1-4159-AB86-25E4BC598C01}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleProject", "sample\SampleProject.csproj", "{FAB31C8A-7DCF-4152-8A82-76F3C10BABA4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ENIGProtocol.Tests", "ENIGProtocol.Tests\ENIGProtocol.Tests.csproj", "{3A677629-1F08-49B2-BC75-58282E439FD4}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B6FCA1B0-C9D1-4159-AB86-25E4BC598C01}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B6FCA1B0-C9D1-4159-AB86-25E4BC598C01}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B6FCA1B0-C9D1-4159-AB86-25E4BC598C01}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B6FCA1B0-C9D1-4159-AB86-25E4BC598C01}.Release|Any CPU.Build.0 = Release|Any CPU + {FAB31C8A-7DCF-4152-8A82-76F3C10BABA4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FAB31C8A-7DCF-4152-8A82-76F3C10BABA4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FAB31C8A-7DCF-4152-8A82-76F3C10BABA4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FAB31C8A-7DCF-4152-8A82-76F3C10BABA4}.Release|Any CPU.Build.0 = Release|Any CPU + {3A677629-1F08-49B2-BC75-58282E439FD4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3A677629-1F08-49B2-BC75-58282E439FD4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3A677629-1F08-49B2-BC75-58282E439FD4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3A677629-1F08-49B2-BC75-58282E439FD4}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {07331835-C46C-4B93-965F-AD2714F97F88} + EndGlobalSection +EndGlobal diff --git a/ReadMe.MD b/ReadMe.MD new file mode 100644 index 0000000..cc3bb5a --- /dev/null +++ b/ReadMe.MD @@ -0,0 +1,160 @@ +# ENIG Protocol + +ENIG 프로토콜 통신 라이브러리 + +**Explanation of the README Content:** + +1. **Title and Overview:** Clearly states the purpose of the library. +2. **Key Components:** Explains the main building blocks: + * `DeviceType` enum: Lists the device types. + * `Packet` class: Describes the packet structure. + * `EEProtocol` class: Explains its role in packet handling. +3. **Key Features:** Details the core functionalities of the `EEProtocol` class: + * Packet creation. + * Packet parsing. + * Data reception. + * Event-driven nature. + * CRC16 calculation. +4. **Usage:** Provides code examples for: + * Creating a packet. + * Parsing a packet. + * Processing received data. +5. **Error Handling:** Explains how the library handles invalid data and incomplete packets. +6. **Dependencies:** Lists any required frameworks or libraries. +7. **License:** Placeholder for the project's license. + +This README provides a comprehensive overview of the `ENIGProtocol` library, making it easy for other developers to understand and use it. I hope this is helpful! + + +## 개발 환경 +- Frameworks : .NET Standard 2.0 +- Visual Studio 2022 또는 Visual Studio Code + +## 프로젝트 구조 + +- `EEProtocol.cs`: ENIG 프로토콜 구현 +- `EEProtocolTests.cs`: 단위 테스트 코드 +- `Sample`: C# Winform 샘플 프로젝트 + + +### 기본 패킷 구조 +``` +[STX][LEN][CMD][DATA][CRC16][ETX] +``` + +- **STX (Start of Text)**: 0x02 +- **LEN (Length)**: 데이터 길이 (1바이트) = {CMD+DATA} +- **CMD (Command)**: 명령어 코드 (1바이트) +- **DATA**: 명령어에 따른 데이터 (가변 길이) +- **CRC16**: 데이터 무결성 검사 (2바이트) +- **ETX (End of Text)**: 0x03 + +### 통신 방향 (호스트=ACS, 장비=agv,buffer,door) +- H -> E: 호스트에서 장비로 전송 +- E -> H: 장비에서 호스트로 전송 + +### 명령어 목록 +1. **ACS (AGV Control System)** + - cmd(1): 출입문 열기 + - cmd(2): 출입문 닫기 + - cmd(3): 출입문 상태 확인 (응답: 1=열림, 0=닫힘) + +2. **Buffer** + - 버퍼 관리 관련 명령어 + +3. **AGV** + - AGV 제어 관련 명령어 + +4. **Door** + - H -> E | cmd(1): 출입문 열기 + - H -> E | cmd(2): 출입문 닫기 + - E -> H | cmd(3): 출입문 상태 (data len=1 : 1=열림, 0=닫힘) + +### CRC16 계산 +- CRC16 다항식 사용 +- 초기값: 0xFFFF +- 데이터 무결성 검증에 사용 + + +#### CRC-16 테이블 값 +``` +0x0000, 0x408E, 0x73EF, 0x3361, 0x152D, 0x55A3, 0x66C2, 0x264C, +0x2A5A, 0x6AD4, 0x59B5, 0x193B, 0x3F77, 0x7FF9, 0x4C98, 0x0C16, +0x54B4, 0x143A, 0x275B, 0x67D5, 0x4199, 0x0117, 0x3276, 0x72F8, +0x7EEE, 0x3E60, 0x0D01, 0x4D8F, 0x6BC3, 0x2B4D, 0x182C, 0x58A2, +0x5B9B, 0x1B15, 0x2874, 0x68FA, 0x4EB6, 0x0E38, 0x3D59, 0x7DD7, +0x71C1, 0x314F, 0x022E, 0x42A0, 0x64EC, 0x2462, 0x1703, 0x578D, +0x0F2F, 0x4FA1, 0x7CC0, 0x3C4E, 0x1A02, 0x5A8C, 0x69ED, 0x2963, +0x2575, 0x65FB, 0x569A, 0x1614, 0x3058, 0x70D6, 0x43B7, 0x0339, +0x45C5, 0x054B, 0x362A, 0x76A4, 0x50E8, 0x1066, 0x2307, 0x6389, +0x6F9F, 0x2F11, 0x1C70, 0x5CFE, 0x7AB2, 0x3A3C, 0x095D, 0x49D3, +0x1171, 0x51FF, 0x629E, 0x2210, 0x045C, 0x44D2, 0x77B3, 0x373D, +0x3B2B, 0x7BA5, 0x48C4, 0x084A, 0x2E06, 0x6E88, 0x5DE9, 0x1D67, +0x1E5E, 0x5ED0, 0x6DB1, 0x2D3F, 0x0B73, 0x4BFD, 0x789C, 0x3812, +0x3404, 0x748A, 0x47EB, 0x0765, 0x2129, 0x61A7, 0x52C6, 0x1248, +0x4AEA, 0x0A64, 0x3905, 0x798B, 0x5FC7, 0x1F49, 0x2C28, 0x6CA6, +0x60B0, 0x203E, 0x135F, 0x53D1, 0x759D, 0x3513, 0x0672, 0x46FC, +0x7979, 0x39F7, 0x0A96, 0x4A18, 0x6C54, 0x2CDA, 0x1FBB, 0x5F35, +0x5323, 0x13AD, 0x20CC, 0x6042, 0x460E, 0x0680, 0x35E1, 0x756F, +0x2DCD, 0x6D43, 0x5E22, 0x1EAC, 0x38E0, 0x786E, 0x4B0F, 0x0B81, +0x0797, 0x4719, 0x7478, 0x34F6, 0x12BA, 0x5234, 0x6155, 0x21DB, +0x22E2, 0x626C, 0x510D, 0x1183, 0x37CF, 0x7741, 0x4420, 0x04AE, +0x08B8, 0x4836, 0x7B57, 0x3BD9, 0x1D95, 0x5D1B, 0x6E7A, 0x2EF4, +0x7656, 0x36D8, 0x05B9, 0x4537, 0x637B, 0x23F5, 0x1094, 0x501A, +0x5C0C, 0x1C82, 0x2FE3, 0x6F6D, 0x4921, 0x09AF, 0x3ACE, 0x7A40, +0x3CBC, 0x7C32, 0x4F53, 0x0FDD, 0x2991, 0x691F, 0x5A7E, 0x1AF0, +0x16E6, 0x5668, 0x6509, 0x2587, 0x03CB, 0x4345, 0x7024, 0x30AA, +0x6808, 0x2886, 0x1BE7, 0x5B69, 0x7D25, 0x3DAB, 0x0ECA, 0x4E44, +0x4252, 0x02DC, 0x31BD, 0x7133, 0x577F, 0x17F1, 0x2490, 0x641E, +0x6727, 0x27A9, 0x14C8, 0x5446, 0x720A, 0x3284, 0x01E5, 0x416B, +0x4D7D, 0x0DF3, 0x3E92, 0x7E1C, 0x5850, 0x18DE, 0x2BBF, 0x6B31, +0x3393, 0x731D, 0x407C, 0x00F2, 0x26BE, 0x6630, 0x5551, 0x15DF, +0x19C9, 0x5947, 0x6A26, 0x2AA8, 0x0CE4, 0x4C6A, 0x7F0B, 0x3F85, +``` + + +#### CRC16 계산 테이블 생성 코드 +```csharp +const ushort polynomial = 0x7979; +ushort[] CRC16_TABLE = new ushort[256]; + +for (ushort i = 0; i < CRC16_TABLE.Length; i++) +{ + ushort value = 0; + ushort temp = i; + for (byte j = 0; j < 8; j++) + { + if (((value ^ temp) & 0x0001) != 0) + { + value = (ushort)((value >> 1) ^ polynomial); + } + else + { + value >>= 1; + } + temp >>= 1; + } + CRC16_TABLE[i] = value; +} +``` + +#### CRC16 계산 예시 +```csharp +ushort CalculateCRC16(byte[] data) +{ + ushort crc = 0xFFFF; + for (int i = 0; i < data.Length; i++) + { + byte index = (byte)(crc ^ data[i]); + crc = (ushort)((crc >> 8) ^ CRC16_TABLE[index]); + } + return crc; +} +``` + +## 라이센스 + + + + + diff --git a/enigprotocol/.gitignore b/enigprotocol/.gitignore new file mode 100644 index 0000000..a06bae1 --- /dev/null +++ b/enigprotocol/.gitignore @@ -0,0 +1,8 @@ +################################################################################ +# 이 .gitignore 파일은 Microsoft(R) Visual Studio에서 자동으로 만들어졌습니다. +################################################################################ + +/obj +/bin +/.vs +/.git diff --git a/enigprotocol/EEProtocol.cs b/enigprotocol/EEProtocol.cs new file mode 100644 index 0000000..d3bea66 --- /dev/null +++ b/enigprotocol/EEProtocol.cs @@ -0,0 +1,223 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ENIG +{ + // 장비 타입 정의 + public enum DeviceType + { + ACS = 0, + AGV1 = 10, + AGV2 = 11, + BUFFER1 = 20, + BUFFER2 = 21, + BUFFER3 = 22, + BUFFER4 = 23, + BUFFER5 = 24, + DOOR = 30, + } + + public partial class EEProtocol + { + // 패킷 수신 이벤트 정의 + // 데이터 수신 이벤트 정의 + public event EventHandler OnDataReceived; + public event EventHandler OnMessage; + + // CRC16 계산을 위한 테이블 + private static readonly ushort[] CRC16_TABLE = new ushort[256]; + + // CRC16 테이블 초기화 + public EEProtocol() + { + const ushort polynomial = 0x7979; + for (ushort i = 0; i < CRC16_TABLE.Length; i++) + { + ushort value = 0; + ushort temp = i; + for (byte j = 0; j < 8; j++) + { + if (((value ^ temp) & 0x0001) != 0) + { + value = (ushort)((value >> 1) ^ polynomial); + } + else + { + value >>= 1; + } + temp >>= 1; + } + CRC16_TABLE[i] = value; + } + + //// CRC 테이블 출력 + //Console.WriteLine("CRC16 테이블 값:"); + //for (int i = 0; i < CRC16_TABLE.Length; i++) + //{ + // if (i % 8 == 0) + // { + // Console.WriteLine(); + // } + // Console.Write($"0x{CRC16_TABLE[i]:X4}, "); + //} + //Console.WriteLine(); + + + } + + // CRC16 계산 메서드 + public ushort CalculateCRC16(byte[] data) + { + ushort crc = 0xFFFF; + for (int i = 0; i < data.Length; i++) + { + byte index = (byte)(crc ^ data[i]); + crc = (ushort)((crc >> 8) ^ CRC16_TABLE[index]); + } + return crc; + } + + // 패킷 생성 메서드 + public byte[] CreatePacket(byte id, byte command, byte[] data) + { + var packet = new Packet + { + ID = id, + Command = command, + Data = data ?? new byte[0], + Length = (byte)(1 + 1 + (data?.Length ?? 0)) // ID + Command + Data 길이 + }; + + // 패킷 조립 + List packetData = new List(); + packetData.Add(Packet.STX); + packetData.Add(packet.Length); + packetData.Add(packet.ID); + packetData.Add(packet.Command); + if (packet.Data != null) + packetData.AddRange(packet.Data); + + // CRC16 계산 + packet.CRC16 = CalculateCRC16(packetData.Skip(1).ToArray()); // STX 제외하고 계산 + packetData.AddRange(BitConverter.GetBytes(packet.CRC16)); + packetData.Add(Packet.ETX); + + return packetData.ToArray(); + } + + //패킷테스트 + public void PacketTest(byte[] rawData) + { + var hexstr = string.Join(" ", rawData.Select(t => t.ToString("X2"))); + RaiseMessage( $"TestPacket : {hexstr}"); + ParsePacket(rawData); + } + + //메세지 발생 + public void RaiseMessage(string message, bool isError = false) + { + OnMessage?.Invoke(this, new MessageEventArgs { IsError = isError, Message = message }); + } + + // 패킷 파싱 메서드 + public bool ParsePacket(byte[] rawData) + { + try + { + if (rawData.Length < 7) // 최소 패킷 크기 + { + var hexstring = string.Join(" ", rawData.Select(t => t.ToString("X2"))); + RaiseMessage($"Too Short Data:{hexstring}"); + return false; + } + + + if (rawData[0] != Packet.STX || rawData[rawData.Length - 1] != Packet.ETX) + { + var hexstring = string.Join(" ", rawData.Select(t => t.ToString("X2"))); + RaiseMessage($"STX/ETX Error Data:{hexstring}"); + return false; + } + + + byte length = rawData[1]; + if (length + 5 != rawData.Length) // STX + Length + CRC16(2) + ETX = 5 + { + var hexstring = string.Join(" ", rawData.Select(t => t.ToString("X2"))); + RaiseMessage($"Length Error ({length+5} != {rawData.Length}) Data:{hexstring}"); + return false; + } + + + // CRC16 검증 + byte[] dataForCrc = rawData.Skip(1).Take(length + 1).ToArray(); + ushort calculatedCrc = CalculateCRC16(dataForCrc); + ushort receivedCrc = BitConverter.ToUInt16(rawData, rawData.Length - 3); + + if (receivedCrc != 0xFFFF && calculatedCrc != receivedCrc) //FF 무시 + { + RaiseMessage($"CRC Error ID:{rawData[2]:X2},CMD:{rawData[3]:X2}", true); + return false; + } + + + // 패킷 생성 + var packet = new Packet + { + Length = length, + ID = rawData[2], + Command = rawData[3], + Data = rawData.Skip(4).Take(length - 2).ToArray(), // ID와 Command 길이(2) 제외 + CRC16 = receivedCrc, + RawData = rawData, + }; + + // 이벤트 발생 + OnDataReceived?.Invoke(this, new DataEventArgs { ReceivedPacket = packet }); + return true; + } + catch + { + return false; + } + } + + // 데이터 수신 처리 메서드 (시리얼 포트에서 데이터를 받았을 때 호출) + private List buffer = new List(); + public void ProcessReceivedData(byte[] data) + { + buffer.AddRange(data); + + while (buffer.Count > 0) + { + // STX 찾기 + int stxIndex = buffer.FindIndex(b => b == Packet.STX); + if (stxIndex == -1) + { + buffer.Clear(); + break; + } + + // 불필요한 데이터 제거 + if (stxIndex > 0) + buffer.RemoveRange(0, stxIndex); + + // 패킷 길이 확인을 위한 최소 데이터 확인 + if (buffer.Count < 2) + break; + + int expectedLength = buffer[1] + 5; // 전체 패킷 길이 + if (buffer.Count < expectedLength) + break; + + // 패킷 추출 및 처리 + byte[] packetData = buffer.Take(expectedLength).ToArray(); + buffer.RemoveRange(0, expectedLength); + + ParsePacket(packetData); + } + } + } +} \ No newline at end of file diff --git a/enigprotocol/ENIGProtocol.csproj b/enigprotocol/ENIGProtocol.csproj new file mode 100644 index 0000000..dbdcea4 --- /dev/null +++ b/enigprotocol/ENIGProtocol.csproj @@ -0,0 +1,7 @@ + + + + netstandard2.0 + + + diff --git a/enigprotocol/EventArgs.cs b/enigprotocol/EventArgs.cs new file mode 100644 index 0000000..dc1e266 --- /dev/null +++ b/enigprotocol/EventArgs.cs @@ -0,0 +1,18 @@ +using System; + +namespace ENIG +{ + + public partial class EEProtocol + { + public class MessageEventArgs : EventArgs + { + public string Message { get; set; } + public bool IsError { get; set; } + } + public class DataEventArgs : EventArgs + { + public Packet ReceivedPacket { get; set; } + } + } +} \ No newline at end of file diff --git a/enigprotocol/Packet.cs b/enigprotocol/Packet.cs new file mode 100644 index 0000000..1eee804 --- /dev/null +++ b/enigprotocol/Packet.cs @@ -0,0 +1,20 @@ +namespace ENIG +{ + // 패킷 구조체 + public class Packet + { + public const byte STX = 0x02; + public const byte ETX = 0x03; + public byte Length { get; set; } + public byte ID { get; set; } + public byte Command { get; set; } + public byte[] Data { get; set; } + public ushort CRC16 { get; set; } + + public byte[] RawData { get; set; } + public Packet() + { + Data = new byte[0]; + } + } +} \ No newline at end of file diff --git a/sample/App.config b/sample/App.config new file mode 100644 index 0000000..3916e0e --- /dev/null +++ b/sample/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/sample/Form1.Designer.cs b/sample/Form1.Designer.cs new file mode 100644 index 0000000..ab4bb62 --- /dev/null +++ b/sample/Form1.Designer.cs @@ -0,0 +1,447 @@ +namespace SampleProject +{ + partial class Form1 + { + /// + /// 필수 디자이너 변수입니다. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// 사용 중인 모든 리소스를 정리합니다. + /// + /// 관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form 디자이너에서 생성한 코드 + + /// + /// 디자이너 지원에 필요한 메서드입니다. + /// 이 메서드의 내용을 코드 편집기로 수정하지 마세요. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.rtRx = new System.Windows.Forms.RichTextBox(); + this.rtTx = new System.Windows.Forms.RichTextBox(); + this.tbmsg = new System.Windows.Forms.TextBox(); + this.btsend = new System.Windows.Forms.Button(); + this.cmbport = new System.Windows.Forms.ComboBox(); + this.btconnect = new System.Windows.Forms.Button(); + this.tbbaud = new System.Windows.Forms.ComboBox(); + this.statusStrip1 = new System.Windows.Forms.StatusStrip(); + this.sbPort = new System.Windows.Forms.ToolStripStatusLabel(); + this.timer1 = new System.Windows.Forms.Timer(this.components); + this.cmbid = new System.Windows.Forms.ComboBox(); + this.btsim = new System.Windows.Forms.Button(); + this.rtMsg = new System.Windows.Forms.RichTextBox(); + this.tbCmd = new System.Windows.Forms.TextBox(); + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.panel1 = new System.Windows.Forms.Panel(); + this.panel2 = new System.Windows.Forms.Panel(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.tabControl1 = new System.Windows.Forms.TabControl(); + this.tabPage1 = new System.Windows.Forms.TabPage(); + this.tabPage2 = new System.Windows.Forms.TabPage(); + this.rtCmd = new System.Windows.Forms.RichTextBox(); + this.btload = new System.Windows.Forms.Button(); + this.btSave = new System.Windows.Forms.Button(); + this.statusStrip1.SuspendLayout(); + this.tableLayoutPanel1.SuspendLayout(); + this.panel1.SuspendLayout(); + this.panel2.SuspendLayout(); + this.tabControl1.SuspendLayout(); + this.tabPage1.SuspendLayout(); + this.tabPage2.SuspendLayout(); + this.SuspendLayout(); + // + // rtRx + // + this.rtRx.Dock = System.Windows.Forms.DockStyle.Fill; + this.rtRx.Font = new System.Drawing.Font("굴림", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(129))); + this.rtRx.Location = new System.Drawing.Point(4, 5); + this.rtRx.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.rtRx.Name = "rtRx"; + this.rtRx.Size = new System.Drawing.Size(462, 318); + this.rtRx.TabIndex = 0; + this.rtRx.Text = ""; + // + // rtTx + // + this.rtTx.Dock = System.Windows.Forms.DockStyle.Fill; + this.rtTx.Font = new System.Drawing.Font("굴림", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(129))); + this.rtTx.Location = new System.Drawing.Point(474, 5); + this.rtTx.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.rtTx.Name = "rtTx"; + this.rtTx.Size = new System.Drawing.Size(462, 318); + this.rtTx.TabIndex = 1; + this.rtTx.Text = ""; + // + // tbmsg + // + this.tbmsg.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(255)))), ((int)(((byte)(192))))); + this.tbmsg.Dock = System.Windows.Forms.DockStyle.Fill; + this.tbmsg.Font = new System.Drawing.Font("굴림", 24F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(129))); + this.tbmsg.Location = new System.Drawing.Point(436, 5); + this.tbmsg.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.tbmsg.Name = "tbmsg"; + this.tbmsg.Size = new System.Drawing.Size(273, 44); + this.tbmsg.TabIndex = 2; + this.tbmsg.Text = "mesage"; + this.tbmsg.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + this.tbmsg.TextChanged += new System.EventHandler(this.tbmsg_TextChanged); + // + // btsend + // + this.btsend.Dock = System.Windows.Forms.DockStyle.Right; + this.btsend.Font = new System.Drawing.Font("굴림", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(129))); + this.btsend.Location = new System.Drawing.Point(709, 5); + this.btsend.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.btsend.Name = "btsend"; + this.btsend.Size = new System.Drawing.Size(120, 42); + this.btsend.TabIndex = 3; + this.btsend.Text = "Send"; + this.btsend.UseVisualStyleBackColor = true; + this.btsend.Click += new System.EventHandler(this.btsend_Click); + // + // cmbport + // + this.cmbport.Dock = System.Windows.Forms.DockStyle.Left; + this.cmbport.Font = new System.Drawing.Font("굴림", 24F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(129))); + this.cmbport.FormattingEnabled = true; + this.cmbport.Location = new System.Drawing.Point(58, 3); + this.cmbport.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.cmbport.Name = "cmbport"; + this.cmbport.Size = new System.Drawing.Size(218, 40); + this.cmbport.TabIndex = 4; + // + // btconnect + // + this.btconnect.Dock = System.Windows.Forms.DockStyle.Right; + this.btconnect.Location = new System.Drawing.Point(765, 3); + this.btconnect.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.btconnect.Name = "btconnect"; + this.btconnect.Size = new System.Drawing.Size(186, 40); + this.btconnect.TabIndex = 5; + this.btconnect.Text = "connect"; + this.btconnect.UseVisualStyleBackColor = true; + this.btconnect.Click += new System.EventHandler(this.btconnect_Click); + // + // tbbaud + // + this.tbbaud.Dock = System.Windows.Forms.DockStyle.Left; + this.tbbaud.Font = new System.Drawing.Font("굴림", 24F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(129))); + this.tbbaud.FormattingEnabled = true; + this.tbbaud.Location = new System.Drawing.Point(331, 3); + this.tbbaud.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.tbbaud.Name = "tbbaud"; + this.tbbaud.Size = new System.Drawing.Size(171, 40); + this.tbbaud.TabIndex = 6; + this.tbbaud.Text = "9600"; + // + // statusStrip1 + // + this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.sbPort}); + this.statusStrip1.Location = new System.Drawing.Point(0, 583); + this.statusStrip1.Name = "statusStrip1"; + this.statusStrip1.Padding = new System.Windows.Forms.Padding(1, 0, 20, 0); + this.statusStrip1.Size = new System.Drawing.Size(954, 22); + this.statusStrip1.TabIndex = 7; + this.statusStrip1.Text = "statusStrip1"; + // + // sbPort + // + this.sbPort.Name = "sbPort"; + this.sbPort.Size = new System.Drawing.Size(121, 17); + this.sbPort.Text = "toolStripStatusLabel1"; + // + // timer1 + // + this.timer1.Tick += new System.EventHandler(this.timer1_Tick); + // + // cmbid + // + this.cmbid.Dock = System.Windows.Forms.DockStyle.Left; + this.cmbid.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.cmbid.Font = new System.Drawing.Font("굴림", 24F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(129))); + this.cmbid.FormattingEnabled = true; + this.cmbid.Location = new System.Drawing.Point(60, 5); + this.cmbid.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.cmbid.Name = "cmbid"; + this.cmbid.Size = new System.Drawing.Size(183, 40); + this.cmbid.TabIndex = 8; + // + // btsim + // + this.btsim.Dock = System.Windows.Forms.DockStyle.Right; + this.btsim.Font = new System.Drawing.Font("굴림", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(129))); + this.btsim.Location = new System.Drawing.Point(829, 5); + this.btsim.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.btsim.Name = "btsim"; + this.btsim.Size = new System.Drawing.Size(120, 42); + this.btsim.TabIndex = 9; + this.btsim.Text = "Test"; + this.btsim.UseVisualStyleBackColor = true; + this.btsim.Click += new System.EventHandler(this.btsim_Click); + // + // rtMsg + // + this.rtMsg.Dock = System.Windows.Forms.DockStyle.Bottom; + this.rtMsg.Location = new System.Drawing.Point(3, 331); + this.rtMsg.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.rtMsg.Name = "rtMsg"; + this.rtMsg.Size = new System.Drawing.Size(940, 118); + this.rtMsg.TabIndex = 10; + this.rtMsg.Text = ""; + // + // tbCmd + // + this.tbCmd.Dock = System.Windows.Forms.DockStyle.Left; + this.tbCmd.Font = new System.Drawing.Font("굴림", 24F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(129))); + this.tbCmd.Location = new System.Drawing.Point(298, 5); + this.tbCmd.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.tbCmd.Name = "tbCmd"; + this.tbCmd.Size = new System.Drawing.Size(83, 44); + this.tbCmd.TabIndex = 11; + this.tbCmd.Text = "cmd"; + this.tbCmd.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.ColumnCount = 2; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.tableLayoutPanel1.Controls.Add(this.rtRx, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.rtTx, 1, 0); + this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel1.Location = new System.Drawing.Point(3, 3); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 1; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(940, 328); + this.tableLayoutPanel1.TabIndex = 12; + // + // panel1 + // + this.panel1.Controls.Add(this.tbmsg); + this.panel1.Controls.Add(this.label5); + this.panel1.Controls.Add(this.tbCmd); + this.panel1.Controls.Add(this.label4); + this.panel1.Controls.Add(this.cmbid); + this.panel1.Controls.Add(this.label3); + this.panel1.Controls.Add(this.btsend); + this.panel1.Controls.Add(this.btsim); + this.panel1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.panel1.Location = new System.Drawing.Point(0, 531); + this.panel1.Name = "panel1"; + this.panel1.Padding = new System.Windows.Forms.Padding(5); + this.panel1.Size = new System.Drawing.Size(954, 52); + this.panel1.TabIndex = 13; + // + // panel2 + // + this.panel2.Controls.Add(this.tbbaud); + this.panel2.Controls.Add(this.label2); + this.panel2.Controls.Add(this.cmbport); + this.panel2.Controls.Add(this.btconnect); + this.panel2.Controls.Add(this.label1); + this.panel2.Dock = System.Windows.Forms.DockStyle.Top; + this.panel2.Location = new System.Drawing.Point(0, 0); + this.panel2.Name = "panel2"; + this.panel2.Padding = new System.Windows.Forms.Padding(3); + this.panel2.Size = new System.Drawing.Size(954, 46); + this.panel2.TabIndex = 14; + // + // label1 + // + this.label1.Dock = System.Windows.Forms.DockStyle.Left; + this.label1.Location = new System.Drawing.Point(3, 3); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(55, 40); + this.label1.TabIndex = 7; + this.label1.Text = "port"; + this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // label2 + // + this.label2.Dock = System.Windows.Forms.DockStyle.Left; + this.label2.Location = new System.Drawing.Point(276, 3); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(55, 40); + this.label2.TabIndex = 8; + this.label2.Text = "baud"; + this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // label3 + // + this.label3.Dock = System.Windows.Forms.DockStyle.Left; + this.label3.Font = new System.Drawing.Font("Arial", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label3.Location = new System.Drawing.Point(5, 5); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(55, 42); + this.label3.TabIndex = 12; + this.label3.Text = "ID\r\n(1)"; + this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // label4 + // + this.label4.Dock = System.Windows.Forms.DockStyle.Left; + this.label4.Font = new System.Drawing.Font("Arial", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label4.Location = new System.Drawing.Point(243, 5); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(55, 42); + this.label4.TabIndex = 13; + this.label4.Text = "CMD\r\n(1)"; + this.label4.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // label5 + // + this.label5.Dock = System.Windows.Forms.DockStyle.Left; + this.label5.Font = new System.Drawing.Font("Arial", 12F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.label5.Location = new System.Drawing.Point(381, 5); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(55, 42); + this.label5.TabIndex = 14; + this.label5.Text = "DATA\r\n(n)"; + this.label5.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // tabControl1 + // + this.tabControl1.Controls.Add(this.tabPage1); + this.tabControl1.Controls.Add(this.tabPage2); + this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tabControl1.Location = new System.Drawing.Point(0, 46); + this.tabControl1.Name = "tabControl1"; + this.tabControl1.SelectedIndex = 0; + this.tabControl1.Size = new System.Drawing.Size(954, 485); + this.tabControl1.TabIndex = 15; + // + // tabPage1 + // + this.tabPage1.Controls.Add(this.tableLayoutPanel1); + this.tabPage1.Controls.Add(this.rtMsg); + this.tabPage1.Location = new System.Drawing.Point(4, 29); + this.tabPage1.Name = "tabPage1"; + this.tabPage1.Padding = new System.Windows.Forms.Padding(3); + this.tabPage1.Size = new System.Drawing.Size(946, 452); + this.tabPage1.TabIndex = 0; + this.tabPage1.Text = "Test"; + this.tabPage1.UseVisualStyleBackColor = true; + // + // tabPage2 + // + this.tabPage2.Controls.Add(this.btSave); + this.tabPage2.Controls.Add(this.btload); + this.tabPage2.Controls.Add(this.rtCmd); + this.tabPage2.Location = new System.Drawing.Point(4, 29); + this.tabPage2.Name = "tabPage2"; + this.tabPage2.Padding = new System.Windows.Forms.Padding(3); + this.tabPage2.Size = new System.Drawing.Size(946, 452); + this.tabPage2.TabIndex = 1; + this.tabPage2.Text = "Command"; + this.tabPage2.UseVisualStyleBackColor = true; + // + // rtCmd + // + this.rtCmd.Dock = System.Windows.Forms.DockStyle.Fill; + this.rtCmd.Location = new System.Drawing.Point(3, 3); + this.rtCmd.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.rtCmd.Name = "rtCmd"; + this.rtCmd.Size = new System.Drawing.Size(940, 446); + this.rtCmd.TabIndex = 11; + this.rtCmd.Text = ""; + // + // btload + // + this.btload.Location = new System.Drawing.Point(820, 15); + this.btload.Name = "btload"; + this.btload.Size = new System.Drawing.Size(113, 29); + this.btload.TabIndex = 12; + this.btload.Text = "Load"; + this.btload.UseVisualStyleBackColor = true; + this.btload.Click += new System.EventHandler(this.btload_Click); + // + // btSave + // + this.btSave.Location = new System.Drawing.Point(820, 50); + this.btSave.Name = "btSave"; + this.btSave.Size = new System.Drawing.Size(113, 29); + this.btSave.TabIndex = 13; + this.btSave.Text = "Save"; + this.btSave.UseVisualStyleBackColor = true; + this.btSave.Click += new System.EventHandler(this.btSave_Click); + // + // Form1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(10F, 19F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(954, 605); + this.Controls.Add(this.tabControl1); + this.Controls.Add(this.panel2); + this.Controls.Add(this.panel1); + this.Controls.Add(this.statusStrip1); + this.Font = new System.Drawing.Font("굴림", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(129))); + this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); + this.Name = "Form1"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "!!"; + this.Load += new System.EventHandler(this.Form1_Load); + this.statusStrip1.ResumeLayout(false); + this.statusStrip1.PerformLayout(); + this.tableLayoutPanel1.ResumeLayout(false); + this.panel1.ResumeLayout(false); + this.panel1.PerformLayout(); + this.panel2.ResumeLayout(false); + this.tabControl1.ResumeLayout(false); + this.tabPage1.ResumeLayout(false); + this.tabPage2.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.RichTextBox rtRx; + private System.Windows.Forms.RichTextBox rtTx; + private System.Windows.Forms.TextBox tbmsg; + private System.Windows.Forms.Button btsend; + private System.Windows.Forms.ComboBox cmbport; + private System.Windows.Forms.Button btconnect; + private System.Windows.Forms.ComboBox tbbaud; + private System.Windows.Forms.StatusStrip statusStrip1; + private System.Windows.Forms.ToolStripStatusLabel sbPort; + private System.Windows.Forms.Timer timer1; + private System.Windows.Forms.ComboBox cmbid; + private System.Windows.Forms.Button btsim; + private System.Windows.Forms.RichTextBox rtMsg; + private System.Windows.Forms.TextBox tbCmd; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private System.Windows.Forms.Panel panel1; + private System.Windows.Forms.Panel panel2; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.TabControl tabControl1; + private System.Windows.Forms.TabPage tabPage1; + private System.Windows.Forms.TabPage tabPage2; + private System.Windows.Forms.RichTextBox rtCmd; + private System.Windows.Forms.Button btSave; + private System.Windows.Forms.Button btload; + } +} + diff --git a/sample/Form1.cs b/sample/Form1.cs new file mode 100644 index 0000000..e74cee2 --- /dev/null +++ b/sample/Form1.cs @@ -0,0 +1,216 @@ +using AR; +using ENIG; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace SampleProject +{ + enum messageType + { + rx, + tx, + normal, + error + } + public partial class Form1 : Form + { + + System.IO.Ports.SerialPort dev; + EEProtocol proto; + Dictionary idlist; + public Form1() + { + InitializeComponent(); + this.Text = $"Amkor ENIG Protocol Test (PanID:46A5, CH:17)"; + proto = new EEProtocol(); + proto.OnDataReceived += Proto_OnDataReceived; + proto.OnMessage += Proto_OnMessage; + dev = new System.IO.Ports.SerialPort(); + dev.ReadTimeout = 2000; + dev.WriteTimeout = 1000; + dev.DataReceived += (s1, e1) => + { + var buffer = new byte[dev.BytesToRead]; + dev.Read(buffer, 0, buffer.Length); + proto.ProcessReceivedData(buffer); + }; + + idlist = new Dictionary(); + idlist.Add("ACS", 0); + idlist.Add("AGV1", 10); + idlist.Add("AGV2", 11); + idlist.Add("BUFFER1", 20); + idlist.Add("BUFFER2", 21); + idlist.Add("BUFFER3", 22); + idlist.Add("BUFFER4", 23); + idlist.Add("BUFFER5", 24); + idlist.Add("DOOR", 30); + + this.cmbid.Items.Clear(); + foreach (var item in idlist) + cmbid.Items.Add($"{item.Key}"); + + tbCmd.Text = "FF"; + tbmsg.Text = string.Empty; + } + + private void Proto_OnDataReceived(object sender, EEProtocol.DataEventArgs e) + { + var hexstrRaw = e.ReceivedPacket.RawData.HexString(); + var hexstr = e.ReceivedPacket.Data.HexString(); + var cmd = e.ReceivedPacket.Command.ToString("X2"); + var id = e.ReceivedPacket.ID.ToString("X2"); + AddMessage($"{hexstrRaw}\nID:{id},CMD:{cmd},DATA:{hexstr}", messageType.rx); + } + private void Proto_OnMessage(object sender, EEProtocol.MessageEventArgs e) + { + AddMessage(e.Message); + } + + void AddMessage(string msg, messageType type = messageType.normal) + { + if(this.InvokeRequired) + { + this.BeginInvoke(new Action(() => AddMessage(msg, type))); + return; + } + + if (type == messageType.rx) + { + rtRx.AppendText($"<{DateTime.Now.ToString("HH:mm:ss")} RX> {msg}\r\n"); + rtRx.ScrollToCaret(); + } + else if (type == messageType.tx) + { + rtTx.AppendText($"<{DateTime.Now.ToString("HH:mm:ss")} TX> {msg}\r\n"); + rtTx.ScrollToCaret(); + } + else + { + rtMsg.AppendText($"<{DateTime.Now.ToString("HH:mm:ss")} > {msg}\r\n"); + rtMsg.ScrollToCaret(); + } + } + + private void Form1_Load(object sender, EventArgs e) + { + cmbport.Items.Clear(); + foreach (var item in System.IO.Ports.SerialPort.GetPortNames()) + { + cmbport.Items.Add(item); + } + cmbport.Text = "COM11"; + if (cmbport.Items.Count > 0) cmbport.SelectedIndex = 0; + if (cmbid.Items.Count > 0) cmbid.SelectedIndex = 0; + LoadCmds(); + this.timer1.Start(); + } + + private void btconnect_Click(object sender, EventArgs e) + { + var port = cmbport.Text.Trim(); + var buid = tbbaud.Text.toInt(); + if(dev.IsOpen) + { + dev.Close(); + AddMessage("port closed"); + } + else + { + try + { + this.dev.PortName = port; + this.dev.BaudRate = buid; + dev.Open(); + AddMessage("port opened"); + } + catch (Exception ex) + { + AddMessage(ex.Message, messageType.error); + } + } + + + } + + private void timer1_Tick(object sender, EventArgs e) + { + sbPort.Text = $"{dev.PortName}:{dev.BaudRate} {(dev.IsOpen ? "Open" : "Closed")}"; + } + + private void tbmsg_TextChanged(object sender, EventArgs e) + { + + } + + private void btsend_Click(object sender, EventArgs e) + { + //send to device + var msg = tbmsg.Text.Trim(); + var id = this.idlist[cmbid.Text]; + var cmdHex = this.tbCmd.Text.Trim(); + byte cmd = Convert.ToByte(cmdHex, 16); + byte[] msgBytes = Encoding.ASCII.GetBytes(msg); // 메시지를 byte 배열로 변환 + + var data = proto.CreatePacket(id, cmd, msgBytes); + SendToDevice(data); + } + + void SendToDevice(byte[] packet) + { + if (dev.IsOpen == false) + { + AddMessage("port closed", messageType.error); + } + else + { + dev.Write(packet, 0, packet.Length); + var hexstring = packet.HexString(); + AddMessage(hexstring, messageType.tx); + } + + } + + private void btsim_Click(object sender, EventArgs e) + { + //packet test + var msg = tbmsg.Text.Trim(); + var id = this.idlist[cmbid.Text]; + var cmdHex = this.tbCmd.Text.Trim(); + byte cmd = Convert.ToByte(cmdHex, 16); // 16진수 문자열을 byte로 변환 + byte[] msgBytes = Encoding.ASCII.GetBytes(msg); // 메시지를 byte 배열로 변환 + + var data = proto.CreatePacket(id, cmd, msgBytes); + this.proto.PacketTest(data); + } + string fn = "cmds.rtf"; + private void btSave_Click(object sender, EventArgs e) + { + System.IO.File.WriteAllText("cmds.rtf", rtCmd.Rtf, System.Text.Encoding.Default); + } + + private void btload_Click(object sender, EventArgs e) + { + LoadCmds(); + } + + void LoadCmds() + { + var fi = new System.IO.FileInfo("cmds.rtf"); + if (fi.Exists == false) + { + AddMessage("no cmds file", messageType.error); + return; + } + var data = System.IO.File.ReadAllText("cmds.rtf", System.Text.Encoding.Default); + rtCmd.Rtf = data; + } + } +} diff --git a/sample/Form1.resx b/sample/Form1.resx new file mode 100644 index 0000000..21e3296 --- /dev/null +++ b/sample/Form1.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + 134, 17 + + \ No newline at end of file diff --git a/sample/Program.cs b/sample/Program.cs new file mode 100644 index 0000000..b43a18e --- /dev/null +++ b/sample/Program.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace SampleProject +{ + internal static class Program + { + /// + /// 해당 애플리케이션의 주 진입점입니다. + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new Form1()); + } + } +} diff --git a/sample/Properties/AssemblyInfo.cs b/sample/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..1394d9c --- /dev/null +++ b/sample/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 어셈블리에 대한 일반 정보는 다음 특성 집합을 통해 +// 제어됩니다. 어셈블리와 관련된 정보를 수정하려면 +// 이러한 특성 값을 변경하세요. +[assembly: AssemblyTitle("SampleProject")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("ATK")] +[assembly: AssemblyProduct("SampleProject")] +[assembly: AssemblyCopyright("Copyright © ATK 2025")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에 +// 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면 +// 해당 형식에 대해 ComVisible 특성을 true로 설정하세요. +[assembly: ComVisible(false)] + +// 이 프로젝트가 COM에 노출되는 경우 다음 GUID는 typelib의 ID를 나타냅니다. +[assembly: Guid("fab31c8a-7dcf-4152-8a82-76f3c10baba4")] + +// 어셈블리의 버전 정보는 다음 네 가지 값으로 구성됩니다. +// +// 주 버전 +// 부 버전 +// 빌드 번호 +// 수정 버전 +// +// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호를 +// 기본값으로 할 수 있습니다. +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/sample/Properties/Resources.Designer.cs b/sample/Properties/Resources.Designer.cs new file mode 100644 index 0000000..86d726d --- /dev/null +++ b/sample/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// 이 코드는 도구를 사용하여 생성되었습니다. +// 런타임 버전:4.0.30319.42000 +// +// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면 +// 이러한 변경 내용이 손실됩니다. +// +//------------------------------------------------------------------------------ + +namespace SampleProject.Properties +{ + + + /// + /// 지역화된 문자열 등을 찾기 위한 강력한 형식의 리소스 클래스입니다. + /// + // 이 클래스는 ResGen 또는 Visual Studio와 같은 도구를 통해 StronglyTypedResourceBuilder + // 클래스에서 자동으로 생성되었습니다. + // 멤버를 추가하거나 제거하려면 .ResX 파일을 편집한 다음 /str 옵션을 사용하여 + // ResGen을 다시 실행하거나 VS 프로젝트를 다시 빌드하십시오. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// 이 클래스에서 사용하는 캐시된 ResourceManager 인스턴스를 반환합니다. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SampleProject.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 이 강력한 형식의 리소스 클래스를 사용하여 모든 리소스 조회에 대해 현재 스레드의 CurrentUICulture 속성을 + /// 재정의합니다. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/sample/Properties/Resources.resx b/sample/Properties/Resources.resx new file mode 100644 index 0000000..ffecec8 --- /dev/null +++ b/sample/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/sample/Properties/Settings.Designer.cs b/sample/Properties/Settings.Designer.cs new file mode 100644 index 0000000..6f4bb07 --- /dev/null +++ b/sample/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleProject.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/sample/Properties/Settings.settings b/sample/Properties/Settings.settings new file mode 100644 index 0000000..abf36c5 --- /dev/null +++ b/sample/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/sample/SampleProject.csproj b/sample/SampleProject.csproj new file mode 100644 index 0000000..ada82a2 --- /dev/null +++ b/sample/SampleProject.csproj @@ -0,0 +1,92 @@ + + + + + Debug + AnyCPU + {FAB31C8A-7DCF-4152-8A82-76F3C10BABA4} + WinExe + SampleProject + SampleProject + v4.8 + 512 + true + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + .\arCommUtil.dll + + + + + + + + + + + + + + + + Form + + + Form1.cs + + + + + Form1.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + {b6fca1b0-c9d1-4159-ab86-25e4bc598c01} + ENIGProtocol + + + + \ No newline at end of file diff --git a/sample/arCommUtil.dll b/sample/arCommUtil.dll new file mode 100644 index 0000000..3c26818 Binary files /dev/null and b/sample/arCommUtil.dll differ