initial commit

This commit is contained in:
chi
2025-04-22 11:36:27 +09:00
commit 5d286d5179
24 changed files with 1754 additions and 0 deletions

13
.gitignore vendored Normal file
View File

@@ -0,0 +1,13 @@
obj
bin
*.user
*.v12
*.suo
.git
.vs
Debug
__vm
*.pdb
desktop.ini
packages
~*.xlsx

3
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,3 @@
{
"dotnet.preferCSharpExtension": true
}

View File

@@ -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);
}
}
}

View File

@@ -0,0 +1,33 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.0.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.4">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\enigprotocol\enigprotocol.csproj" />
</ItemGroup>
<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,10 @@
namespace ENIGProtocol.Tests;
public class UnitTest1
{
[Fact]
public void Test1()
{
}
}

37
ENIGProtocol.sln Normal file
View File

@@ -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

160
ReadMe.MD Normal file
View File

@@ -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;
}
```
## 라이센스

8
enigprotocol/.gitignore vendored Normal file
View File

@@ -0,0 +1,8 @@
################################################################################
# 이 .gitignore 파일은 Microsoft(R) Visual Studio에서 자동으로 만들어졌습니다.
################################################################################
/obj
/bin
/.vs
/.git

223
enigprotocol/EEProtocol.cs Normal file
View File

@@ -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<DataEventArgs> OnDataReceived;
public event EventHandler<MessageEventArgs> 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<byte> packetData = new List<byte>();
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<byte> buffer = new List<byte>();
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);
}
}
}
}

View File

@@ -0,0 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
</Project>

18
enigprotocol/EventArgs.cs Normal file
View File

@@ -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; }
}
}
}

20
enigprotocol/Packet.cs Normal file
View File

@@ -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];
}
}
}

6
sample/App.config Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
</startup>
</configuration>

447
sample/Form1.Designer.cs generated Normal file
View File

@@ -0,0 +1,447 @@
namespace SampleProject
{
partial class Form1
{
/// <summary>
/// 필수 디자이너 변수입니다.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// 사용 중인 모든 리소스를 정리합니다.
/// </summary>
/// <param name="disposing">관리되는 리소스를 삭제해야 하면 true이고, 그렇지 않으면 false입니다.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form
/// <summary>
/// 디자이너 지원에 필요한 메서드입니다.
/// 이 메서드의 내용을 코드 편집기로 수정하지 마세요.
/// </summary>
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;
}
}

216
sample/Form1.cs Normal file
View File

@@ -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<string, byte> 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<string, byte>();
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;
}
}
}

126
sample/Form1.resx Normal file
View File

@@ -0,0 +1,126 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="timer1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>134, 17</value>
</metadata>
</root>

22
sample/Program.cs Normal file
View File

@@ -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
{
/// <summary>
/// 해당 애플리케이션의 주 진입점입니다.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}

View File

@@ -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")]

71
sample/Properties/Resources.Designer.cs generated Normal file
View File

@@ -0,0 +1,71 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 이 코드는 도구를 사용하여 생성되었습니다.
// 런타임 버전:4.0.30319.42000
//
// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면
// 이러한 변경 내용이 손실됩니다.
// </auto-generated>
//------------------------------------------------------------------------------
namespace SampleProject.Properties
{
/// <summary>
/// 지역화된 문자열 등을 찾기 위한 강력한 형식의 리소스 클래스입니다.
/// </summary>
// 이 클래스는 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()
{
}
/// <summary>
/// 이 클래스에서 사용하는 캐시된 ResourceManager 인스턴스를 반환합니다.
/// </summary>
[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;
}
}
/// <summary>
/// 이 강력한 형식의 리소스 클래스를 사용하여 모든 리소스 조회에 대해 현재 스레드의 CurrentUICulture 속성을
/// 재정의합니다.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture
{
get
{
return resourceCulture;
}
set
{
resourceCulture = value;
}
}
}
}

View File

@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

30
sample/Properties/Settings.Designer.cs generated Normal file
View File

@@ -0,0 +1,30 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 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.
// </auto-generated>
//------------------------------------------------------------------------------
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;
}
}
}
}

View File

@@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

View File

@@ -0,0 +1,92 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{FAB31C8A-7DCF-4152-8A82-76F3C10BABA4}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>SampleProject</RootNamespace>
<AssemblyName>SampleProject</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="arCommUtil">
<HintPath>.\arCommUtil.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Form1.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Form1.Designer.cs">
<DependentUpon>Form1.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="Form1.resx">
<DependentUpon>Form1.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\enigprotocol\ENIGProtocol.csproj">
<Project>{b6fca1b0-c9d1-4159-ab86-25e4bc598c01}</Project>
<Name>ENIGProtocol</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

BIN
sample/arCommUtil.dll Normal file

Binary file not shown.