From 86f7a3921bcf9bc665fb34cc0b3a93f4fd98665c Mon Sep 17 00:00:00 2001 From: syneffort Date: Thu, 1 Feb 2024 15:24:11 +0900 Subject: [PATCH] first commit --- ModbusTester/ModbusTester.sln | 25 ++ ModbusTester/ModbusTester/App.config | 6 + ModbusTester/ModbusTester/App.xaml | 22 ++ ModbusTester/ModbusTester/App.xaml.cs | 17 ++ ModbusTester/ModbusTester/MainWindow.xaml | 98 +++++++ ModbusTester/ModbusTester/MainWindow.xaml.cs | 126 +++++++++ ModbusTester/ModbusTester/ModbusTester.csproj | 111 ++++++++ ModbusTester/ModbusTester/Model/DataModel.cs | 53 ++++ .../ModbusTester/Model/ModbusModel.cs | 250 ++++++++++++++++++ .../ModbusTester/Properties/AssemblyInfo.cs | 55 ++++ .../Properties/Resources.Designer.cs | 71 +++++ .../ModbusTester/Properties/Resources.resx | 117 ++++++++ .../Properties/Settings.Designer.cs | 30 +++ .../ModbusTester/Properties/Settings.settings | 7 + ModbusTester/ModbusTester/Resources/Logo.png | Bin 0 -> 35923 bytes ModbusTester/ModbusTester/packages.config | 4 + 16 files changed, 992 insertions(+) create mode 100644 ModbusTester/ModbusTester.sln create mode 100644 ModbusTester/ModbusTester/App.config create mode 100644 ModbusTester/ModbusTester/App.xaml create mode 100644 ModbusTester/ModbusTester/App.xaml.cs create mode 100644 ModbusTester/ModbusTester/MainWindow.xaml create mode 100644 ModbusTester/ModbusTester/MainWindow.xaml.cs create mode 100644 ModbusTester/ModbusTester/ModbusTester.csproj create mode 100644 ModbusTester/ModbusTester/Model/DataModel.cs create mode 100644 ModbusTester/ModbusTester/Model/ModbusModel.cs create mode 100644 ModbusTester/ModbusTester/Properties/AssemblyInfo.cs create mode 100644 ModbusTester/ModbusTester/Properties/Resources.Designer.cs create mode 100644 ModbusTester/ModbusTester/Properties/Resources.resx create mode 100644 ModbusTester/ModbusTester/Properties/Settings.Designer.cs create mode 100644 ModbusTester/ModbusTester/Properties/Settings.settings create mode 100644 ModbusTester/ModbusTester/Resources/Logo.png create mode 100644 ModbusTester/ModbusTester/packages.config diff --git a/ModbusTester/ModbusTester.sln b/ModbusTester/ModbusTester.sln new file mode 100644 index 0000000..fd5f9f5 --- /dev/null +++ b/ModbusTester/ModbusTester.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.8.34511.84 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModbusTester", "ModbusTester\ModbusTester.csproj", "{D99D07AC-3477-4DEB-9B02-A2EA30996ED3}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D99D07AC-3477-4DEB-9B02-A2EA30996ED3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D99D07AC-3477-4DEB-9B02-A2EA30996ED3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D99D07AC-3477-4DEB-9B02-A2EA30996ED3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D99D07AC-3477-4DEB-9B02-A2EA30996ED3}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {115AF6A3-8669-4F9F-AB65-52AC409AB907} + EndGlobalSection +EndGlobal diff --git a/ModbusTester/ModbusTester/App.config b/ModbusTester/ModbusTester/App.config new file mode 100644 index 0000000..193aecc --- /dev/null +++ b/ModbusTester/ModbusTester/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/ModbusTester/ModbusTester/App.xaml b/ModbusTester/ModbusTester/App.xaml new file mode 100644 index 0000000..fbeef22 --- /dev/null +++ b/ModbusTester/ModbusTester/App.xaml @@ -0,0 +1,22 @@ + + + #d4eaf7 + #b6ccd8 + #3b3c3d + #71c4ef + #00668c + #1d1c1c + #313d44 + #fffefb + #f5f4f1 + #cccbc8 + + orangeRed + #ffdf80 + #a5d46a + + diff --git a/ModbusTester/ModbusTester/App.xaml.cs b/ModbusTester/ModbusTester/App.xaml.cs new file mode 100644 index 0000000..e8ac76a --- /dev/null +++ b/ModbusTester/ModbusTester/App.xaml.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Threading.Tasks; +using System.Windows; + +namespace ModbusTester +{ + /// + /// App.xaml에 대한 상호 작용 논리 + /// + public partial class App : Application + { + } +} diff --git a/ModbusTester/ModbusTester/MainWindow.xaml b/ModbusTester/ModbusTester/MainWindow.xaml new file mode 100644 index 0000000..7be4372 --- /dev/null +++ b/ModbusTester/ModbusTester/MainWindow.xaml @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ModbusTester/ModbusTester/MainWindow.xaml.cs b/ModbusTester/ModbusTester/MainWindow.xaml.cs new file mode 100644 index 0000000..de3d5d9 --- /dev/null +++ b/ModbusTester/ModbusTester/MainWindow.xaml.cs @@ -0,0 +1,126 @@ +using ModbusTester.Model; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace ModbusTester +{ + /// + /// MainWindow.xaml에 대한 상호 작용 논리 + /// + public partial class MainWindow : Window + { + private ModbusModel _pmsModbus; + private DataModel _pmsData; + public MainWindow() + { + InitializeComponent(); + InitInstance(); + } + + private void InitInstance() + { + _pmsModbus = new ModbusModel(); + _pmsModbus.OnConnectionChanged += _pmsModbus_OnConnectionChanged; + _pmsModbus.OnSendDataChanged += _pmsModbus_OnSendDataChanged; + _pmsModbus.OnReceiveDataChanged += _pmsModbus_OnReceiveDataChanged; + _pmsModbus.OnDataRead += _pmsModbus_OnDataRead; + _pmsModbus.Port = 502; + + _pmsData = DataContext as DataModel; + } + + private void _pmsModbus_OnDataRead(object sender, DataModel e) + { + Application.Current.Dispatcher.Invoke(() => + { + DataContext = e; + _pmsData = DataContext as DataModel; + }); + } + + private string GetDataString(float[] data) + { + string result = ""; + foreach (float item in data) + { + result += $"{item.ToString("N2")}, "; + } + + return result; + } + + private void _pmsModbus_OnReceiveDataChanged(object sender, byte[] e) + { + + } + + private void _pmsModbus_OnSendDataChanged(object sender, byte[] e) + { + + } + + private void _pmsModbus_OnConnectionChanged(object sender, bool e) + { + Application.Current.Dispatcher.Invoke(() => + { + if (_pmsModbus.IsConnected == true) + { + lblStatus.Background = (SolidColorBrush)Application.Current.FindResource("traffic_green"); + tbtConnect.IsChecked = true; + } + else + { + lblStatus.Background = (SolidColorBrush)Application.Current.FindResource("traffic_red"); + tbtConnect.IsChecked= false; + } + }); + } + + private void SetModbus() + { + _pmsModbus.IP = _pmsData.IP; + _pmsModbus.Interval = _pmsData.Interval; + } + + private void tbtConnect_Checked(object sender, RoutedEventArgs e) + { + + try + { + SetModbus(); + _pmsModbus.Connect(); + + } + catch (Exception ex) + { + tbtConnect.IsChecked = false; + MessageBox.Show($"Error: {ex.Message}"); + } + } + + private void tbtConnect_Unchecked(object sender, RoutedEventArgs e) + { + try + { + _pmsModbus.Disconnect(); + } + catch (Exception ex) + { + tbtConnect.IsChecked = true; + MessageBox.Show($"Error: {ex.Message}"); + } + } + } +} diff --git a/ModbusTester/ModbusTester/ModbusTester.csproj b/ModbusTester/ModbusTester/ModbusTester.csproj new file mode 100644 index 0000000..1049934 --- /dev/null +++ b/ModbusTester/ModbusTester/ModbusTester.csproj @@ -0,0 +1,111 @@ + + + + + Debug + AnyCPU + {D99D07AC-3477-4DEB-9B02-A2EA30996ED3} + WinExe + PMSModbusTester + PMSModbusTester + v4.8 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + true + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\EasyModbusTCP.5.6.0\lib\net40\EasyModbus.dll + + + + + + + + + + + + 4.0 + + + + + + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + App.xaml + Code + + + MainWindow.xaml + Code + + + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + + + Always + + + + + \ No newline at end of file diff --git a/ModbusTester/ModbusTester/Model/DataModel.cs b/ModbusTester/ModbusTester/Model/DataModel.cs new file mode 100644 index 0000000..009f24c --- /dev/null +++ b/ModbusTester/ModbusTester/Model/DataModel.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ModbusTester.Model +{ + public class DataModel : INotifyPropertyChanged + { + public event PropertyChangedEventHandler PropertyChanged; + + public string IP { get; set; } + public int Interval { get; set; } + + public float ConfigFlowrate { get; set; } + public float ActualFlowrate { get; set; } + public int NumberOfChannel { get; set; } + + private ObservableCollection _data; + public ObservableCollection Data + { + get { return _data; } + set + { + _data = value; + OnPropertyChanged(nameof(Data)); + } + } + + public DataModel() + { + IP = "200.200.200.200"; + Interval = 60; + + _data = new ObservableCollection(); + } + + private void OnPropertyChanged(string propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + } + + public class PMSChannelData + { + public string Name { get; set; } + public DateTime TimeStamp { get; set; } + public int CummulativeRaw { get; set; } + } +} diff --git a/ModbusTester/ModbusTester/Model/ModbusModel.cs b/ModbusTester/ModbusTester/Model/ModbusModel.cs new file mode 100644 index 0000000..fde1bd6 --- /dev/null +++ b/ModbusTester/ModbusTester/Model/ModbusModel.cs @@ -0,0 +1,250 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Timers; +using EasyModbus; + +namespace ModbusTester.Model +{ + public class ModbusModel + { + private readonly int COIL_ADDR_DATA_SAMPLING = 1 - 1; + private readonly int COIL_ADDR_DATA_AVAILABLE = 2 - 1; + private readonly int COIL_ADDR_DATA_CLEAR = 3 - 1; + + private readonly int HOLDING_RESISTER_SAMPLING_INTERVAL = 3 - 1; + private readonly int HOLDING_RESISTER_TARE_TIME = 4 - 1; + private readonly int HOLDING_RESISTER_REPEAT_COUNT = 5 - 1; + + private readonly int INPUT_RESISTER_CONFIG_FLOW_RATE = 13 - 1; // length: 2 + private readonly int INPUT_RESISTER_FLOW_RATE = 222 - 1; // length: 2 + private readonly int INPUT_RESISTER_ADDR_NUM_OF_CHANNEL = 227 - 1; // length: 1 + private readonly int INPUT_RESISTER_CHANNEL_SIZE_START = 17 - 1; // length: 2 for each + private readonly int INPUT_RESISTER_CHANNEL_START = 229 - 1; // length: 2 for each + + private ModbusClient _master; + + private Timer _timer; + + public string IP { get; set; } + public int Port { get; set; } + + public int Interval { get; set; } + + public bool? IsConnected { get { return _master?.Connected; } } + + public event EventHandler OnConnectionChanged; + public event EventHandler OnSendDataChanged; + public event EventHandler OnReceiveDataChanged; + public event EventHandler OnDataRead; + + public ModbusModel() + { + Port = 502; + + _master = new ModbusClient(); + _master.ReceiveDataChanged += _master_ReceiveDataChanged; + _master.SendDataChanged += _master_SendDataChanged; + _master.ConnectedChanged += _master_ConnectedChanged; + + _timer = new Timer(); + _timer.Interval = 1000; + _timer.Elapsed += _timer_Elapsed; + _timer.Stop(); + } + + private void _timer_Elapsed(object sender, ElapsedEventArgs e) + { + if (_master == null || !_master.Connected) + return; + + // data available check + bool available = _master.ReadCoils(COIL_ADDR_DATA_AVAILABLE, 1)[0]; + if (!available) + return; + + // get data + ReadData(); + + // pop queued data + _master.WriteSingleCoil(COIL_ADDR_DATA_AVAILABLE, false); + } + + private void _master_ConnectedChanged(object sender) + { + if (OnConnectionChanged != null) + OnConnectionChanged(this, _master.Connected); + + if (_master.Connected) + _timer.Start(); + else + _timer.Stop(); + } + + private void _master_SendDataChanged(object sender) + { + if (OnSendDataChanged != null) + OnSendDataChanged(this, _master.sendData); + } + + private void _master_ReceiveDataChanged(object sender) + { + if (OnReceiveDataChanged != null) + OnReceiveDataChanged(this, _master.receiveData); + } + + public void Connect() + { + Disconnect(); + + _master.IPAddress = IP; + _master.Port = Port; + _master.UnitIdentifier = 1; + _master.Connect(); + + // clear queue + _master.WriteSingleCoil(COIL_ADDR_DATA_CLEAR, true); + + // write interval + _master.WriteSingleRegister(HOLDING_RESISTER_SAMPLING_INTERVAL, Interval); + + // write tare + _master.WriteSingleRegister(HOLDING_RESISTER_TARE_TIME, 0); + + // set repeat count + _master.WriteSingleRegister(HOLDING_RESISTER_REPEAT_COUNT, 0); + + // read basic information + ReadData(); + + // Sampling Start + StartSampling(); + } + + public void Disconnect() + { + if (!_master.Connected) + return; + + StopSampling(); + + _master.Disconnect(); + } + + public void StartSampling() + { + if (_master == null || !_master.Connected) + return; + + // coil check + bool samping = _master.ReadCoils(COIL_ADDR_DATA_SAMPLING, 1)[0]; + if (!samping) + _master.WriteSingleCoil(COIL_ADDR_DATA_SAMPLING, true); + } + + public void StopSampling() + { + if (_master == null || !_master.Connected) + return; + + // coil check + bool samping = _master.ReadCoils(COIL_ADDR_DATA_SAMPLING, 1)[0]; + if (samping) + _master.WriteSingleCoil(COIL_ADDR_DATA_SAMPLING, false); + } + + public DataModel ReadData() + { + if (_master == null || !_master.Connected) + return null; + + // interval + int interval = _master.ReadHoldingRegisters(HOLDING_RESISTER_SAMPLING_INTERVAL, 1)[0]; + + // config flowrate + int[] configFlowratePacket = _master.ReadInputRegisters(INPUT_RESISTER_CONFIG_FLOW_RATE, 2); + float configFlowrate = ConvertHighLowToFloat(configFlowratePacket)[0]; + + // actual flowrate + int[] acturalFlowratePacket = _master.ReadInputRegisters(INPUT_RESISTER_FLOW_RATE, 2); + float acturalFlowrate = ConvertHighLowToFloat(acturalFlowratePacket)[0]; + + // channel data + DateTime now = DateTime.Now; + int channelLength = _master.ReadInputRegisters(INPUT_RESISTER_ADDR_NUM_OF_CHANNEL, 1)[0]; + int[] channetSizePacket = _master.ReadInputRegisters(INPUT_RESISTER_CHANNEL_SIZE_START, channelLength * 2); + int[] channelDataPacket = _master.ReadInputRegisters(INPUT_RESISTER_CHANNEL_START, channelLength * 2); + + // channel data converting + int[] channelSizeData = ConvertHighLowToInt(channetSizePacket); + int[] channelData = ConvertHighLowToInt(channelDataPacket); + PMSChannelData[] data = new PMSChannelData[channelData.Length]; + for (int i = 0; i < channelData.Length; i++) + { + data[i] = new PMSChannelData() + { + Name = $"Ch{i + 1} ({channelSizeData[i]})", + TimeStamp = now, + CummulativeRaw = channelData[i] + }; + } + + DataModel read = new DataModel() + { + IP = IP, + Interval = interval, + ConfigFlowrate = configFlowrate, + ActualFlowrate = acturalFlowrate, + NumberOfChannel = channelLength, + Data = new ObservableCollection(data) + }; + + + if (OnDataRead != null) + OnDataRead(this, read); + + return read; + } + + private float[] ConvertHighLowToFloat(int[] input) + { + if (input.Length % 2 != 0) + throw new ArgumentException("Input array is not even."); + + float[] output = new float[input.Length / 2]; + for (int i = 0; i < input.Length; i += 2) + { + ushort high = (ushort)input[i]; + ushort low = (ushort)input[i + 1]; + // big-endian to little-endian + byte[] bytes = BitConverter.GetBytes(low).Concat(BitConverter.GetBytes(high)).ToArray(); + float convertedValue = BitConverter.ToSingle(bytes, 0); + output[i / 2] = convertedValue; + } + + return output; + } + + private int[] ConvertHighLowToInt(int[] input) + { + if (input.Length % 2 != 0) + throw new ArgumentException("Input array is not even."); + + int[] output = new int[input.Length / 2]; + for (int i = 0; i < input.Length; i += 2) + { + ushort high = (ushort)input[i]; + ushort low = (ushort)input[i + 1]; + // big-endian to little-endian + byte[] bytes = BitConverter.GetBytes(low).Concat(BitConverter.GetBytes(high)).ToArray(); + int convertedValue = BitConverter.ToInt32(bytes, 0); + output[i / 2] = convertedValue; + } + + return output; + } + } +} diff --git a/ModbusTester/ModbusTester/Properties/AssemblyInfo.cs b/ModbusTester/ModbusTester/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..8674ebd --- /dev/null +++ b/ModbusTester/ModbusTester/Properties/AssemblyInfo.cs @@ -0,0 +1,55 @@ +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; + +// 어셈블리에 대한 일반 정보는 다음 특성 집합을 통해 +// 제어됩니다. 어셈블리와 관련된 정보를 수정하려면 +// 이러한 특성 값을 변경하세요. +[assembly: AssemblyTitle("PMSModbusTester")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("PMSModbusTester")] +[assembly: AssemblyCopyright("Copyright © 2024")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에 +// 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면 +// 해당 형식에 대해 ComVisible 특성을 true로 설정하세요. +[assembly: ComVisible(false)] + +//지역화 가능 애플리케이션 빌드를 시작하려면 다음을 설정하세요. +//.csproj 파일의 CultureYouAreCodingWith +// 내부. 예를 들어 미국 영어를 사용하는 경우 +//사용하는 경우 를 en-US로 설정합니다. 그런 다음 아래 +//NeutralResourceLanguage 특성의 주석 처리를 제거합니다. 아래 줄의 "en-US"를 업데이트하여 +//프로젝트 파일의 UICulture 설정과 일치시킵니다. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //테마별 리소스 사전의 위치 + //(페이지 또는 응용 프로그램 리소스 사진에 + // 리소스가 없는 경우에 사용됨) + ResourceDictionaryLocation.SourceAssembly //제네릭 리소스 사전의 위치 + //(페이지 또는 응용 프로그램 리소스 사진에 + // 리소스가 없는 경우에 사용됨) +)] + + +// 어셈블리의 버전 정보는 다음 네 가지 값으로 구성됩니다. +// +// 주 버전 +// 부 버전 +// 빌드 번호 +// 수정 버전 +// +// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호를 +// 기본값으로 할 수 있습니다. +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/ModbusTester/ModbusTester/Properties/Resources.Designer.cs b/ModbusTester/ModbusTester/Properties/Resources.Designer.cs new file mode 100644 index 0000000..db313b0 --- /dev/null +++ b/ModbusTester/ModbusTester/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// 이 코드는 도구를 사용하여 생성되었습니다. +// 런타임 버전:4.0.30319.42000 +// +// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면 +// 이러한 변경 내용이 손실됩니다. +// +//------------------------------------------------------------------------------ + +namespace ModbusTester.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("PMSModbusTester.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/ModbusTester/ModbusTester/Properties/Resources.resx b/ModbusTester/ModbusTester/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/ModbusTester/ModbusTester/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/ModbusTester/ModbusTester/Properties/Settings.Designer.cs b/ModbusTester/ModbusTester/Properties/Settings.Designer.cs new file mode 100644 index 0000000..d64df03 --- /dev/null +++ b/ModbusTester/ModbusTester/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 ModbusTester.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/ModbusTester/ModbusTester/Properties/Settings.settings b/ModbusTester/ModbusTester/Properties/Settings.settings new file mode 100644 index 0000000..033d7a5 --- /dev/null +++ b/ModbusTester/ModbusTester/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/ModbusTester/ModbusTester/Resources/Logo.png b/ModbusTester/ModbusTester/Resources/Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..1be13266229f987186ccef7b1545facf5f25ffce GIT binary patch literal 35923 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 Ib4q9e0L&S2p#T5? literal 0 HcmV?d00001 diff --git a/ModbusTester/ModbusTester/packages.config b/ModbusTester/ModbusTester/packages.config new file mode 100644 index 0000000..574c664 --- /dev/null +++ b/ModbusTester/ModbusTester/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file