From e46b1c709bab427f7d4cf6b2b87002cecf5a92ed Mon Sep 17 00:00:00 2001 From: "Arin(asus)" Date: Sat, 21 Jun 2025 11:43:19 +0900 Subject: [PATCH] =?UTF-8?q?arMaskterK=20=ED=94=84=EB=A1=9C=EC=A0=9D?= =?UTF-8?q?=ED=8A=B8=EB=A5=BC=20vms2016=5Fcs=20=EB=A0=88=ED=8F=AC=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=ED=98=84=20=EB=A0=88=ED=8F=AC=EB=A1=9C=20=EC=9D=B4?= =?UTF-8?q?=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Sub/arMasterK/.gitignore | 6 + Sub/arMasterK/Demo/Demo.csproj | 61 ++ Sub/arMasterK/Demo/Program.cs | 86 +++ Sub/arMasterK/Demo/Properties/AssemblyInfo.cs | 36 + Sub/arMasterK/MasterK.sln | 28 + Sub/arMasterK/Project/.gitignore | 2 + Sub/arMasterK/Project/EnumAStruct.cs | 236 ++++++ Sub/arMasterK/Project/EventArgs.cs | 131 ++++ Sub/arMasterK/Project/History.txt | 13 + Sub/arMasterK/Project/MasterK.cs | 686 ++++++++++++++++++ Sub/arMasterK/Project/Parser.cs | 230 ++++++ .../Project/Properties/AssemblyInfo.cs | 36 + .../Project/Properties/Resources.Designer.cs | 63 ++ .../Project/Properties/Resources.resx | 117 +++ .../Project/Properties/Settings.Designer.cs | 26 + .../Project/Properties/Settings.settings | 7 + Sub/arMasterK/Project/Util.cs | 425 +++++++++++ Sub/arMasterK/Project/Write.cs | 213 ++++++ Sub/arMasterK/Project/arMasterK.csproj | 100 +++ Sub/arMasterK/Project/fIOMonitor.Designer.cs | 144 ++++ Sub/arMasterK/Project/fIOMonitor.cs | 77 ++ Sub/arMasterK/Project/fIOMonitor.resx | 120 +++ 22 files changed, 2843 insertions(+) create mode 100644 Sub/arMasterK/.gitignore create mode 100644 Sub/arMasterK/Demo/Demo.csproj create mode 100644 Sub/arMasterK/Demo/Program.cs create mode 100644 Sub/arMasterK/Demo/Properties/AssemblyInfo.cs create mode 100644 Sub/arMasterK/MasterK.sln create mode 100644 Sub/arMasterK/Project/.gitignore create mode 100644 Sub/arMasterK/Project/EnumAStruct.cs create mode 100644 Sub/arMasterK/Project/EventArgs.cs create mode 100644 Sub/arMasterK/Project/History.txt create mode 100644 Sub/arMasterK/Project/MasterK.cs create mode 100644 Sub/arMasterK/Project/Parser.cs create mode 100644 Sub/arMasterK/Project/Properties/AssemblyInfo.cs create mode 100644 Sub/arMasterK/Project/Properties/Resources.Designer.cs create mode 100644 Sub/arMasterK/Project/Properties/Resources.resx create mode 100644 Sub/arMasterK/Project/Properties/Settings.Designer.cs create mode 100644 Sub/arMasterK/Project/Properties/Settings.settings create mode 100644 Sub/arMasterK/Project/Util.cs create mode 100644 Sub/arMasterK/Project/Write.cs create mode 100644 Sub/arMasterK/Project/arMasterK.csproj create mode 100644 Sub/arMasterK/Project/fIOMonitor.Designer.cs create mode 100644 Sub/arMasterK/Project/fIOMonitor.cs create mode 100644 Sub/arMasterK/Project/fIOMonitor.resx diff --git a/Sub/arMasterK/.gitignore b/Sub/arMasterK/.gitignore new file mode 100644 index 0000000..362a4b4 --- /dev/null +++ b/Sub/arMasterK/.gitignore @@ -0,0 +1,6 @@ +################################################################################ +# 이 .gitignore 파일은 Microsoft(R) Visual Studio에서 자동으로 만들어졌습니다. +################################################################################ + +/Project/bin/Debug +/Project/.vs diff --git a/Sub/arMasterK/Demo/Demo.csproj b/Sub/arMasterK/Demo/Demo.csproj new file mode 100644 index 0000000..23882fd --- /dev/null +++ b/Sub/arMasterK/Demo/Demo.csproj @@ -0,0 +1,61 @@ + + + + + Debug + AnyCPU + {D92246F1-981A-452C-9E0A-09CD9F68B102} + Exe + Properties + Demo + Demo + v4.0 + 512 + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + {e0133085-e5f9-4275-9db8-f8f20ef8561f} + arMasterK + + + + + \ No newline at end of file diff --git a/Sub/arMasterK/Demo/Program.cs b/Sub/arMasterK/Demo/Program.cs new file mode 100644 index 0000000..c31d945 --- /dev/null +++ b/Sub/arMasterK/Demo/Program.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Demo +{ + class Program + { + static arDev.MasterK dev; + static void Main(string[] args) + { + dev = new arDev.MasterK(); + dev.Message += dev_Message; + if (!dev.Init("COM8", 9600)) + { + Console.WriteLine("init error"); + Console.ReadKey(); + return; + } + + System.Text.StringBuilder sb = new StringBuilder(); + sb.AppendLine("====================="); + sb.AppendLine("Master K Protocol Test"); + sb.AppendLine("Version : 0.1"); + sb.AppendLine("Author : tindevil@nate.com"); + sb.AppendLine("====================="); + sb.AppendLine("1. Port 40 - ON"); + sb.AppendLine("2. Port 40 - OFF"); + sb.AppendLine("3. Port 41 - ON"); + sb.AppendLine("4. Port 41 - OFF"); + sb.AppendLine("5. Read Port"); + sb.AppendLine("9. Exit"); + sb.AppendLine("====================="); + sb.Append("Select Menu = "); + + while (true) + { + Console.Write(sb.ToString()); + var key = Console.ReadKey(true); + + //program end + if (key.Key == ConsoleKey.D9) break; + + switch (key.Key) + { + case ConsoleKey.D1: + dev.SetOutput(0, true); + break; + case ConsoleKey.D2: + dev.SetOutput(0, false); + break; + case ConsoleKey.D3: + dev.SetOutput(1, true); + break; + case ConsoleKey.D4: + dev.SetOutput(1, false); + break; + case ConsoleKey.D5: + dev.Read_RelayPort(); + Console.WriteLine(); + Console.WriteLine("========================"); + Console.WriteLine("DI:" + dev.GetInputState()); + Console.WriteLine("DO:" + dev.GetOutputState()); + Console.WriteLine("========================"); + Console.WriteLine("Press any key"); + Console.ReadKey(); + break; + default: + Console.WriteLine("unknown menu number"); + break; + } + Console.Clear(); + } + + Console.WriteLine("Press any key : Exit"); + Console.ReadKey(true); + } + + static void dev_Message(object sender, arDev.MasterK.MessageEventArgs e) + { + Console.WriteLine((e.IsError ? "[ERR]" : "") + e.Message); + } + + } +} diff --git a/Sub/arMasterK/Demo/Properties/AssemblyInfo.cs b/Sub/arMasterK/Demo/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..36c16fb --- /dev/null +++ b/Sub/arMasterK/Demo/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 어셈블리의 일반 정보는 다음 특성 집합을 통해 제어됩니다. +// 어셈블리와 관련된 정보를 수정하려면 +// 이 특성 값을 변경하십시오. +[assembly: AssemblyTitle("Demo")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Demo")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에 +// 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면 +// 해당 형식에 대해 ComVisible 특성을 true로 설정하십시오. +[assembly: ComVisible(false)] + +// 이 프로젝트가 COM에 노출되는 경우 다음 GUID는 typelib의 ID를 나타냅니다. +[assembly: Guid("d649cb64-a01f-4f2b-99b2-a2797844f375")] + +// 어셈블리의 버전 정보는 다음 네 가지 값으로 구성됩니다. +// +// 주 버전 +// 부 버전 +// 빌드 번호 +// 수정 버전 +// +// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 버전이 자동으로 +// 지정되도록 할 수 있습니다. +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Sub/arMasterK/MasterK.sln b/Sub/arMasterK/MasterK.sln new file mode 100644 index 0000000..9ea00b8 --- /dev/null +++ b/Sub/arMasterK/MasterK.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.40629.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "arMasterK", ".\Project\arMasterK.csproj", "{E0133085-E5F9-4275-9DB8-F8F20EF8561F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demo", ".\Demo\Demo.csproj", "{D92246F1-981A-452C-9E0A-09CD9F68B102}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E0133085-E5F9-4275-9DB8-F8F20EF8561F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E0133085-E5F9-4275-9DB8-F8F20EF8561F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E0133085-E5F9-4275-9DB8-F8F20EF8561F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E0133085-E5F9-4275-9DB8-F8F20EF8561F}.Release|Any CPU.Build.0 = Release|Any CPU + {D92246F1-981A-452C-9E0A-09CD9F68B102}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D92246F1-981A-452C-9E0A-09CD9F68B102}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D92246F1-981A-452C-9E0A-09CD9F68B102}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D92246F1-981A-452C-9E0A-09CD9F68B102}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Sub/arMasterK/Project/.gitignore b/Sub/arMasterK/Project/.gitignore new file mode 100644 index 0000000..d1a4b4d --- /dev/null +++ b/Sub/arMasterK/Project/.gitignore @@ -0,0 +1,2 @@ +/MasterK.v12.suo +/MasterK.sln diff --git a/Sub/arMasterK/Project/EnumAStruct.cs b/Sub/arMasterK/Project/EnumAStruct.cs new file mode 100644 index 0000000..6ad7976 --- /dev/null +++ b/Sub/arMasterK/Project/EnumAStruct.cs @@ -0,0 +1,236 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace arDev +{ + public partial class MasterK + { + + + [Description("")] + public enum eMsgType + { + [Description("")] + Rx = 0, + [Description("")] + Tx, + RxRaw, + } + + [Description("Operation Code , 이 코드값으로 컨트롤 보드에 명령합니다.")] + public enum eOpCode : byte + { + GET_IO_DATA = 0, + RELAY_OUTPUT, + } + + /// + /// digital input/output direction + /// + public enum eIOPINDIR : byte + { + [Description("Digital Input")] + INPUT = 0, + [Description("Digital Output")] + OUTPUT = 1, + } + + /// + /// error code list + /// + public enum eErrorCode : byte + { + [Description("포트가사용중입니다.")] + PortBusy = 0, + [Description("열려있지않습니다.")] + NotOpen, + [Description("쓰기오류")] + WriteError, + [Description("읽기오류")] + ReadError, + [Description("프레임오류")] + FrameError, + [Description("체크섬오류")] + ChecksumError + } + + + /// + /// message frame + /// + public struct sRecvMessage + { + /// + /// 국번 + /// + public string Device; + + /// + /// 명령어 + /// + public char Command; + + /// + /// 명령어타입 + /// + public string CmdType; + + /// + /// 블록수 + /// + public int BlockCount; + + /// + /// 데이터갯수 + /// + public int DataLen; + + /// + /// 데이터 + /// + public string Data; + + + public string FullString; + + /// + /// full message frame + /// + [Description("전체 메세지 영역")] + public byte[] Buffer; + + /// + /// check byte (crc16) + /// + [Description("체크섬 2byte(CRC 16)")] + public byte[] checksum; + + /// + /// checksum error + /// + [Description("체크섬에 오류가 있는지 확인합니다.(true일경우 오류)")] + public Boolean isCSError; + + [Description("기타메세지")] + public string Message; + + [Description("정보를 삭제합니다.")] + public void Clear() + { + Message = "NOTSET"; + Data = null; + Buffer = null; + checksum = null; + isCSError = false; + BlockCount = 0; + DataLen = 0; + FullString = string.Empty; + } + + [Description("응답코드가 NAK인지확인합니다. NAK응답은 컨트롤러로부터 오류가 수신되었음을 의미합니다.")] + public Boolean isNAK + { + get + { + if (Buffer[0] == 0x15) return true; + else return false; + } + } + + [Description("오류가 있는지 체크합니다. 버퍼가 없거나 체크섬 오류 , DLC오류등을 체크 합니다.")] + public Boolean isError + { + get + { + if (Buffer == null || isCSError || BlockCount == 0 || isNAK) return true; + else return false; + } + } + } + public struct sSendMessage + { + /// + /// 국번 + /// + public string Device; + + /// + /// 명령어 + /// + public char Command; + + /// + /// 명령어타입 + /// + public string CmdType; + + /// + /// 변수길이 + /// + public int DeviceLength; + + public int NumberofBlock; + + /// + /// 변수명 + /// + public string VarName; + + /// + /// 데이터갯수 + /// + public int DataLen; + public string Data; + + /// + /// full message frame + /// + [Description("전체 메세지 영역")] + public byte[] Buffer; + public string Strbuffer; + + /// + /// check byte (crc16) + /// + [Description("체크섬 2byte(CRC 16)")] + public byte[] checksum; + + /// + /// checksum error + /// + [Description("체크섬에 오류가 있는지 확인합니다.(true일경우 오류)")] + public Boolean isCSError; + + [Description("기타메세지")] + public string Message; + + [Description("정보를 삭제합니다.")] + public void Clear() + { + Data = string.Empty; + Message = "NOTSET"; + Buffer = null; + checksum = null; + isCSError = false; + DeviceLength = 0; + NumberofBlock = 0; + DataLen = 0; + Strbuffer = string.Empty; + } + + [Description("오류가 있는지 체크합니다. 버퍼가 없거나 체크섬 오류 , DLC오류등을 체크 합니다.")] + public Boolean isError + { + get + { + if (Buffer == null || isCSError || DeviceLength == 0) return true; + else return false; + } + } + } + } +} diff --git a/Sub/arMasterK/Project/EventArgs.cs b/Sub/arMasterK/Project/EventArgs.cs new file mode 100644 index 0000000..a7cc7fe --- /dev/null +++ b/Sub/arMasterK/Project/EventArgs.cs @@ -0,0 +1,131 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace arDev +{ + public partial class MasterK + { + public class DataEventArgs : EventArgs + { + private byte[] _buffer = null; + + /// + /// 바이트배열의 버퍼값 + /// + public byte[] Value { get { return _buffer; } } + + public eMsgType Direction { get; set; } + + /// + /// 버퍼(바이트배열)의 데이터를 문자로 반환합니다. + /// + public string StrValue + { + get + { + if (_buffer == null || _buffer.Length < 1) return string.Empty; + return System.Text.Encoding.Default.GetString(_buffer); + } + } + public DataEventArgs(eMsgType dir_, byte[] buffer) + { + _buffer = buffer; + Direction = dir_; + } + } + public class MessageEventArgs : EventArgs + { + protected Boolean _isError = false; + public Boolean IsError { get { return _isError; } } + protected string _message = string.Empty; + public string Message { get { return _message; } } + public MessageEventArgs(Boolean isError, string Message) + { + _isError = isError; + _message = Message; + } + } + public class FrameEventArgs : EventArgs + { + public eOpCode OpCode { get; set; } + public FrameEventArgs(eOpCode opCode_) + { + OpCode = opCode_; + } + } + public class IOValueEventArgs : EventArgs + { + protected eIOPINDIR _direction; + protected int _arridx; + protected Boolean _oldvalue; + protected Boolean _newvalue; + + public eIOPINDIR Direction { get { return _direction; } } + public int ArrIDX { get { return _arridx; } } + public Boolean OldValue { get { return _oldvalue; } } + public Boolean NewValue { get { return _newvalue; } } + + public IOValueEventArgs(eIOPINDIR dir, int arridx, Boolean oldvalue, Boolean newvalue) + { + _direction = dir; + _arridx = arridx; + _oldvalue = oldvalue; + _newvalue = newvalue; + } + } + public class AIValueEventArgs : EventArgs + { + public float[] Value { get; protected set; } + + public AIValueEventArgs(float[] value_) + { + Value = value_; + } + } + + #region "Events" + + /// + /// 일반적인 메세지 혹은 오류메세지 이벤트 + /// + public event EventHandler Message; + + /// + /// 데이터메시이벤트 (Rx,Tx) 별로 구분됩니다. + /// + public event EventHandler DataMessage; + + /// + /// 가공되어진 최종 메세지 형태값을 가지고 있습니다. + /// + public event EventHandler ReceiveFrame; + + /// + /// ReadProcess에의해서 감시되며 포트의 상태값이 바뀐다면 발생함 + /// + public event EventHandler IOValueChanged; + + /// + /// AI의 값을 이벤트로 발생합니다.발생주기는 AIInterval을 참고합니다. + /// + public event EventHandler AIValueChanged; + + /// + /// 오류발생시 메세지가 발생함 + /// + public event EventHandler IOErrorMessage; + + /// + /// anlog 관련한 오류 메세지 + /// + /// Analog Data Error Message + public event EventHandler AIErrorMessage; + + #endregion + + } +} diff --git a/Sub/arMasterK/Project/History.txt b/Sub/arMasterK/Project/History.txt new file mode 100644 index 0000000..f5b5a6b --- /dev/null +++ b/Sub/arMasterK/Project/History.txt @@ -0,0 +1,13 @@ +181005 chi init 시 baudrate 를 기본값 19200 설정 +180802 chi init 시에 baudrate 도 입력하도록 함 +180625 chi TestVersion 0.1; + RunMonitor 가 중복실행되지 않도록 수정 + makepacket 수정 + +00RSB06%PW00001 +00WSS0107%PX004001 + +[18-03-29 06:45:38] RAW: 06 30 30 52 53 42 30 31 30 32 30 30 30 30 03 +00RSB01020000 + +180329 Create \ No newline at end of file diff --git a/Sub/arMasterK/Project/MasterK.cs b/Sub/arMasterK/Project/MasterK.cs new file mode 100644 index 0000000..71bfa85 --- /dev/null +++ b/Sub/arMasterK/Project/MasterK.cs @@ -0,0 +1,686 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.ComponentModel; +using System.Windows.Forms; +using System.Drawing; +using System.Drawing.Design; +using System.Reflection; +using System.Runtime; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +namespace arDev +{ + public partial class MasterK : IDisposable + { + #region "Variable" + + public bool bRunMonitor; //쓰레드작동시그널 + public Boolean bAIMonitor=false; //배경쓰레드에서 아날로그값을 모니터링 합니다.\ + public Boolean bDIOMonitor=true; //배경쓰레드에서 dIO를 모니터링 할것인가? + public string errorMessage = string.Empty; + + System.Diagnostics.Stopwatch aiMonWatch = new System.Diagnostics.Stopwatch(); + public long LoopDelay; + + protected byte wSTX = 0x05; + protected byte wETX = 0x04; + protected byte rSTX = 0x06; + protected byte rETX = 0x03; + protected int interchar_delay; + protected Boolean bSyncRecvOK = false;// 메세지를 수신할 경우 설정됩니다. + protected Boolean _isInit = false;// 보드가 초기화가 되었는지 확인합니다. + public Boolean disposed = false;// Dipose 되었는가? + protected byte _CommandCode = 0x00;// recv command code + + protected Boolean _bDlc = false; + protected int _dlc = 0; + protected Boolean _bStx = false; //stx를 찾앗는지? + protected Boolean _bEtx = false; //etx를 찾앗는지? + + protected Boolean[] _valueI; //입력접점 + protected Boolean[] _valueO; //출력접점 + protected Boolean[] OldvalueI; + protected Boolean[] OldvalueO; + + protected Thread thMonitor; //배경쓰레드(상태체크 및 이벤트 발생) + protected ManualResetEvent _mre; + protected string _mreowner = string.Empty; + protected System.Diagnostics.Stopwatch wat = new System.Diagnostics.Stopwatch(); + protected System.IO.Ports.SerialPort _device; + + public int DOCount { get; protected set; } + public int DICount { get; protected set; } + public double ThreadSpeed = 0; + + public sRecvMessage LastRecvMessage; + public sSendMessage lastSendMessage; + public DateTime lastSendTime; + public byte[] lastSendBuffer; + + /// + /// device index + /// + public byte IDX = 0; + + #endregion + + public MasterK() + { + //serial port + _device = new System.IO.Ports.SerialPort(); + _device.BaudRate = 9600; + _device.DtrEnable = false; + _device.WriteTimeout = 2000; + _device.ReadTimeout = 2000; + _device.DiscardNull = true; + + //autoreset events + _mre = new System.Threading.ManualResetEvent(true); + bRunMonitor = false; + + LoopDelay = 150; + + //모든ls산전은 논리적으로 64개가 지정되어있다. + this.DICount = 64; + this.DOCount = 64; + + //변수초기화 + this._valueI = new bool[DICount]; + this._valueO = new bool[DOCount]; + this.OldvalueI = new bool[_valueI.Length]; + this.OldvalueO = new bool[_valueO.Length]; + + //초기값설정(인풋) + for (int i = 0; i < _valueI.Length; i++) + { + this._valueI[i] = false; + this.OldvalueI[i] = false; + } + + //초기값설정(아웃풋) + for (int i = 0; i < _valueO.Length; i++) + { + this._valueO[i] = false; + this.OldvalueO[i] = false; + } + } + + ~MasterK() + { + Dispose(false); + } + + public void Close() + { + if (_device.IsOpen) + { + if (_mre.WaitOne(3000)) + { + _mre.Reset(); + _mreowner = "Close"; + _device.Close(); + _mre.Set(); + } + else + { + RaiseMessage(true, "close error timeout"); + } + } + } + + /// + /// 개체를 해제합니다. + /// + [Description("")] + public virtual void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + // Protected implementation of Dispose pattern. + protected virtual void Dispose(bool disposing) + { + if (disposed) + return; + + if (disposing) + { + // Dispose managed resources. + } + + StopMonitor(); + + // Call the appropriate methods to clean up + // unmanaged resources here. + // If disposing is false, + // only the following code is executed. + + // Note disposing has been done. + disposed = true; + + } + + + public string PortName + { + get + { + return _device.PortName; + } + set + { + _device.PortName = value; + } + } + + public Boolean Init(string port,int baud = 19200) + { + Close(); + + errorMessage = string.Empty; + + _device.PortName = port; + _device.BaudRate = baud; + + try + { + _device.Open(); + _device.DiscardInBuffer(); + _device.DiscardOutBuffer(); + + _isInit = true; + sw_ch = new System.Diagnostics.Stopwatch(); + interchar_delay = GetIntercharDelay(); + interframe_delay = GetInterframeDelay(); + + } + catch (Exception ex) + { + _isInit = false; + errorMessage = ex.Message; + RaiseMessage(true, ex.Message); + } + return _isInit; + } + + + + + #region "Properties" + + /// + /// 입력핀 상태값을 확인합니다. + /// + /// 0부터 시작하는 인덱스값 + /// + [Description("")] + public Boolean INPUT(int arridx) + { + if (arridx < 0 || arridx > DICount - 1) + { + if (IOErrorMessage != null) + IOErrorMessage(this, new MessageEventArgs(true, "INPUT Command : ArrayIndex Error Value=" + arridx.ToString())); + return false; + } + return this._valueI[arridx]; + } + + /// + /// 입력핀 상태를 모두 반환합니다. + /// + [Description("")] + public Boolean[] getInputArray + { + get + { + return (Boolean[])this._valueI.Clone(); + } + } + + public byte getInputValueToByte(int startindex) + { + System.Collections.BitArray ba = new System.Collections.BitArray(this._valueI); + byte[] value = new byte[8]; + ba.CopyTo(value, startindex); + return value[0]; + } + public Int64 getInputValue + { + get + { + System.Collections.BitArray ba = new System.Collections.BitArray(this._valueI); + byte[] value = new byte[8]; + ba.CopyTo(value, 0); + return BitConverter.ToInt64(value, 0); + } + } + + /// + /// 출력핀 상태를 모두 반환합니다. + /// + [Description("")] + public Boolean[] getOutputArray + { + get + { + return (Boolean[])this._valueO.Clone(); + } + } + + /// + /// 출력핀 상태 값을 확인합니다. + /// + /// 0부터 시작하는 인덱스값 + /// + [Description("")] + public Boolean OUTPUT(int arridx) + { + // get { return (Boolean[])this._valueO.Clone(); } + if (arridx < 0 || arridx > DOCount - 1) + { + if (IOErrorMessage != null) + IOErrorMessage(this, new MessageEventArgs(true, "OUTPUT Command : ArrayIndex Error Value=" + arridx.ToString())); + return false; + } + return this._valueO[arridx]; + } + + + /// + /// read digital input port state + /// + /// + [Description("")] + public string GetInputState() + { + System.Text.StringBuilder sb = new StringBuilder(); + for (int i = 0; i < OldvalueI.Length; i++) + sb.Append(OldvalueI[i] ? "1" : "0"); + return sb.ToString(); + } + /// + /// read digital output port state + /// + /// + [Description("")] + public string GetOutputState() + { + System.Text.StringBuilder sb = new StringBuilder(); + for (int i = 0; i < OldvalueO.Length; i++) + sb.Append(OldvalueO[i] ? "1" : "0"); + return sb.ToString(); + } + + #endregion + + #region "Method" + + + /// + /// 오류메세지 반환 + /// + /// + [Description("")] + public string GetErrorMessage() + { + return this.errorMessage; + } + + + #region "raise Message" + + /// + /// 일반메세지륿 라생시킵니다. + /// + /// + /// + [Description("")] + public void RaiseMessage(Boolean isError, string message) + { + if (isError) errorMessage = message; //170920 + if (Message != null) Message(this, new MessageEventArgs(isError, message)); + } + + /// + /// 지정한 데이터로 바코드가 수신된것처럼 발생시킵니다.(Parser를 사용함) + /// + /// + [Description("")] + public void RaiseDataMessage(eMsgType dir, byte[] Data) + { + try + { + if (dir == eMsgType.Rx) Parse_RecvBuffer(Data); + if (DataMessage != null) DataMessage(this, new DataEventArgs(dir,Data)); + } + catch (Exception ex) + { + errorMessage = ex.Message; + RaiseMessage(true, "RaiseDataMessage:" + ex.Message); + } + } + + #endregion + + /// + /// Input / Output 핀 상태를 지속적으로 읽는 쓰레드작업을 시작합니다. + /// + [Description("")] + public void RunMonitor(int loopDelay_ = 150) + { + this.LoopDelay = loopDelay_; + if(!this.bRunMonitor) + { + this.bRunMonitor = true; + this.thMonitor = new Thread(new ThreadStart(this.bwMonitor)); + this.thMonitor.IsBackground = true; + this.thMonitor.Start(); + } + } + + /// + /// INPUT/OUPUT 핀 상태를 모니터링하는 쓰레드를 종료시킵니다. + /// + /// + [Description("")] + public bool StopMonitor() + { + try + { + this.bRunMonitor = false; + RaiseMessage(false, "Stop Monitor"); + return true; + } + catch (Exception ex) + { + RaiseMessage(true, ex.Message); + return false; + } + } + + /// + /// 지정한 출력포트의 값을 반전 시킵니다. + /// + /// + /// + [Description("")] + public Boolean SetToggle(int arrIndex) + { + if (!IsInit) return false; + if (arrIndex < 0 || (arrIndex + 1) > DOCount) + throw new Exception(string.Format("IDX Range Errror({0}~{1})", 0, DOCount-1)); + + Boolean currentValue = OUTPUT(arrIndex); + return SetOutput(arrIndex, !currentValue); + } + + /// + /// 출력을 설정합니다. + /// + /// + /// + /// + /// + [Description("")] + public Boolean SetOutput(int arrIndex, Boolean Value, int Duration = 0) + { + errorMessage = string.Empty; + if (!IsInit) + { + //RaiseMessage(true, "SetOutput:No Init"); + return false; + } + + //RaiseMessage(false, "Set Output Index=" + arrIndex.ToString() + ",Value=" + Value.ToString()); + + if (arrIndex < 0 || (arrIndex + 1) > DOCount) + { + RaiseMessage(true, "SetOutput:ArrIndex Error = " + arrIndex.ToString()); + return false; + } + + if (!_mre.WaitOne(1000)) + { + RaiseMessage(true, "SetOutput Wait on timeout"); + return false; + } + _mre.Reset(); + + if (Duration < 0) Duration = 0; + int Port = 0x40 + arrIndex; //출력포트는 64번부터 시작한다. + string cmd = "00WSS0107%PX00" + Port.ToString("X2") + (Value ? "01":"00"); + + //해당라인에 그값을 쓴다. + Boolean bRet = true; + + try + { + var buffer = WriteSync(cmd); + string strBuffer = System.Text.Encoding.Default.GetString(buffer); + if (buffer == null) + { + RaiseMessage(true, "SetOutput:No Response"); + bRet= false; + } + else + { + if(buffer[0] == 0x06) + { + if (Duration != 0) + { + var task = new Task(() => + { + Thread.Sleep(Duration); + + string cmd2 = "00WSS0107%PX00" + Port.ToString("X2") + (Value ? "00" : "01"); + var buffer2 = WriteSync(cmd2); + if (buffer2 == null) + { + RaiseMessage(true, "SetOutput:Duration toggle Error:No Reponse"); + } + }); + task.Start(); //비동기로 실행한다. + } + } + else + { + RaiseMessage(true, "SetOutput:Nak response"); + bRet = false; + } + + } + } + catch (Exception ex) + { + RaiseMessage(true, "SetOutput:"+ex.Message); + bRet = false; + } + _mre.Set(); + return bRet; + } + + + /// + /// 이벤트를 강제 생성합니다. + /// + /// + /// + /// + [Description("")] + public void RaiseEvent(eIOPINDIR Direction, int ArrIDX, Boolean newvalue) + { + if (IOValueChanged != null) + { + //mre.WaitOne(); + //mre.Reset(); + + //171226 + if (Direction == eIOPINDIR.INPUT) + { + _valueI[ArrIDX] = newvalue; + OldvalueI[ArrIDX] = newvalue; + } + else + { + _valueO[ArrIDX] = newvalue; + OldvalueO[ArrIDX] = newvalue; + } + + try + { + if (IOValueChanged != null) + IOValueChanged(this, new IOValueEventArgs(Direction, ArrIDX, !newvalue, newvalue)); + + } + catch (Exception ex) + { + if (IOErrorMessage != null) + this.IOErrorMessage(this, new MessageEventArgs(true , string.Format( "{0},{1}:{2}:{3}",ex.Message,Direction,ArrIDX,newvalue))); + } + //mre.Set(); + } + + } + + + public virtual void UserMonitorCode() { } + + private byte loopIndex = 0; + /// + /// I/O상태를 모니터링 하여 내부 변수에 값을 저장합니다. + /// + [Description("")] + protected void bwMonitor() + { + DateTime lastaitime = DateTime.Now; + DateTime lastmottime = DateTime.Now; + System.Diagnostics.Stopwatch wat = new System.Diagnostics.Stopwatch(); + while (this.bRunMonitor) + { + wat.Restart(); + //170905 + if (!IsInit) + { + aiMonWatch.Stop(); + System.Threading.Thread.Sleep(1000); + continue; + } + else + { + if (!aiMonWatch.IsRunning) aiMonWatch.Reset(); + } + + //read dio status + if (loopIndex == 0) + { + //RaiseMessage(false,"Run IOMonitor"); + if (bDIOMonitor) + Read_RelayPort(); + loopIndex += 1; + } + else + { + //RaiseMessage(false, "Run AIMonitor"); + UserMonitorCode(); + loopIndex = 0; + } + + wat.Stop(); + ThreadSpeed = wat.ElapsedMilliseconds; + if(wat.ElapsedMilliseconds < LoopDelay) + { + Thread.Sleep((int)(LoopDelay- wat.ElapsedMilliseconds)); + } + } + wat.Stop(); + } + + #endregion + + #region "Send Method" + + //public Boolean Read_AIPort() + //{ + // if (!_mre.WaitOne(1000)) + // { + // RaiseMessage(true, "Read_AIPort Wait on timeout"); + // return false; + // } + // //RaiseMessage(false, "Read_AIPort"); + // _mre.Reset(); + // System.Threading.Thread.Sleep(25); + // _mre.Set(); + // return true; + //} + + public Boolean isValid + { + get + { + var ts = DateTime.Now - lastrecvTime; + if (ts.TotalSeconds > 5) return false; + else return true; + } + } + private DateTime lastrecvTime = DateTime.Now; + + public Boolean Read_RelayPort() + { + if(!_mre.WaitOne(1000)) + { + RaiseMessage(true, "Read_RelayPort Wait on timeout"); + return false; + } + + // RaiseMessage(false, "Read_RelayPort"); + + _mre.Reset(); + var packet = MakePacket(0, 'R', "SB","%PW000", 8); //"00RSB06%PW00008" + var buffer = WriteSync(packet); + if(buffer != null) + { + var frame = Parse_RecvBuffer(buffer); + if(!frame.isError) + { + this.Run_RelayPortData(ref frame); + lastrecvTime = DateTime.Now; + } + + LastRecvMessage = frame; + } + _mre.Set(); + return buffer != null; + } + + /// + /// + /// + /// 0~9 + /// R,W + /// SB,SW ?? + /// %PW000 + /// 1 + /// HexString + /// + public string MakePacket(byte Station,char Command,string CmdType,string Device,byte NumberofData,string data = "") + { + string buffer = Station.ToString("X2").PadLeft(2, '0') + + Command + + CmdType + + Device.Length.ToString("X2").PadLeft(2, '0') + + Device + + NumberofData.ToString("X2").PadLeft(2, '0'); + if (data != "") buffer += data; + return buffer; + } + + #endregion + + } + +} diff --git a/Sub/arMasterK/Project/Parser.cs b/Sub/arMasterK/Project/Parser.cs new file mode 100644 index 0000000..8246a48 --- /dev/null +++ b/Sub/arMasterK/Project/Parser.cs @@ -0,0 +1,230 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace arDev +{ + public partial class MasterK + { + public sRecvMessage Parse_RecvBuffer(byte[] buffer) + { + sRecvMessage frame = new sRecvMessage(); + frame.Clear(); + frame.Message = string.Empty; + if(buffer==null) + { + frame.Message = "null buffer"; + return frame; + } + frame.FullString = System.Text.Encoding.Default.GetString(buffer); + if (buffer == null || buffer.Length < 5) + { + frame.Message = "No Buffer"; + errorMessage = frame.Message; + return frame; + } + + //buffer copy + frame.Buffer = new byte[buffer.Length]; + buffer.CopyTo(frame.Buffer, 0); + + if ((buffer[0] != 0x06 && buffer[0] != 0x15) || buffer[buffer.Length - 1] != 0x03) + { + frame.Message = "No STX,ETX"; + errorMessage = frame.Message; + return frame; + } + + try + { + frame.checksum = new byte[2]; + frame.isCSError = false;// !CheckCrc(buffer); + frame.Device = System.Text.Encoding.Default.GetString(buffer, 1, 2); + frame.Command = (char)buffer[3]; + frame.CmdType = System.Text.Encoding.Default.GetString(buffer, 4, 2); + + //쓰기명령은 데이터가 없다. + if (frame.Command == 'W') + { + frame.BlockCount = 0; + frame.DataLen = 0; + frame.Data = null; + } + else + { + if (!frame.isNAK) + { + frame.BlockCount = Convert.ToInt32(System.Text.Encoding.Default.GetString(buffer, 6, 2), 16); + frame.DataLen = Convert.ToInt32(System.Text.Encoding.Default.GetString(buffer, 8, 2), 16); + int stringDataLen = frame.BlockCount * frame.DataLen * 2; + if (frame.FullString.Length < stringDataLen + 10) + { + frame.BlockCount = 0; + frame.Data = string.Empty; + errorMessage = "Frame length Error:" + frame.FullString; + } + else + { + frame.Data = frame.FullString.Substring(10, stringDataLen); //, 10, DataBufferLen); + } + } + } + } catch(Exception ex) //180706 + { + frame.BlockCount = 0; + errorMessage = ex.Message; + } + + if (frame.isError && errorMessage == "") errorMessage = "Recvbuffer Has Error"; + return frame; + } + + public sSendMessage Parse_SendBuffer(byte[] buffer) + { + sSendMessage msg = new sSendMessage(); + msg.Clear(); + msg.Message = string.Empty; + if (buffer == null || buffer.Length < 5) + { + msg.Message = "No Buffer"; + errorMessage = msg.Message; + return msg; + } + + //buffer copy + msg.Buffer = new byte[buffer.Length]; + msg.Strbuffer = System.Text.Encoding.Default.GetString(buffer); + buffer.CopyTo(msg.Buffer, 0); + + if ((buffer[0] != wSTX) || buffer[buffer.Length - 1] != wETX) + { + msg.Message = "No STX,ETX"; + errorMessage = msg.Message; + return msg; + } + + msg.checksum = new byte[2]; + msg.isCSError = false;// !CheckCrc(buffer); + + msg.Device = System.Text.Encoding.Default.GetString(buffer, 1, 2); + msg.Command = (char)buffer[3]; + if (msg.Command == 'R') + { + msg.CmdType = msg.Strbuffer.Substring(4, 2); + msg.DeviceLength = int.Parse(msg.Strbuffer.Substring( 6, 2)); + msg.VarName = msg.Strbuffer.Substring( 8, msg.DeviceLength); + msg.DataLen = int.Parse(msg.Strbuffer.Substring( 8 + msg.DeviceLength, 2)); + } else if (msg.Command == 'W') + { + msg.CmdType = System.Text.Encoding.Default.GetString(buffer, 4, 2); + if(msg.CmdType == "SB") + { + //블록수가 없다. + msg.NumberofBlock = 0; + msg.DeviceLength = int.Parse(msg.Strbuffer.Substring(6, 2)); + msg.VarName = msg.Strbuffer.Substring(8, msg.DeviceLength); + msg.DataLen = Convert.ToByte(msg.Strbuffer.Substring(8 + msg.DeviceLength, 2),16); + int remain = msg.Strbuffer.Length - 2 - 10 - msg.DeviceLength+1; + msg.Data = msg.Strbuffer.Substring(10 + msg.DeviceLength, remain); + } + else + { + msg.NumberofBlock = int.Parse(msg.Strbuffer.Substring(6, 2)); + msg.DeviceLength = int.Parse(msg.Strbuffer.Substring(8, 2)); + msg.VarName = msg.Strbuffer.Substring(10, msg.DeviceLength); + msg.Data = msg.Strbuffer.Substring(10 + msg.DeviceLength, 2); + msg.DataLen = (int)(msg.Data.Length / 2.0); + } + + } + + return msg; + } + + /// + /// 수신된 데이터를 분석하고 관련 메세지를 생성합니다. + /// + /// + /// + [Description("")] + protected void Run_RelayPortData(ref sRecvMessage message) + { + if (message.isNAK) return; //req nak process + if (message.Command == 'R') + { + if (message.CmdType == "SB") + { + var Port = lastSendMessage.VarName.Substring(1, 1); + var DataType = lastSendMessage.VarName.Substring(2, 1); + //int DataLen = 0; + //if (DataType == "W") DataLen = 16; + switch (Port) + { + case "P": //relay + //들어온값이 16진수 문자형태이므로 숫자로 변경 + var InBufferStrH = message.Data.Substring(0, 8); + var InBufferStrL = message.Data.Substring(8, 8); + var OtBufferStrH = message.Data.Substring(16, 8); + var OtBufferStrL = message.Data.Substring(24, 8); + + Int32 numvalueHI = Convert.ToInt32(InBufferStrL, 16); + Int32 numvalueLI = Convert.ToInt32(InBufferStrH, 16); + Int32 numvalueHO = Convert.ToInt32(OtBufferStrL, 16); + Int32 numvalueLO = Convert.ToInt32(OtBufferStrH, 16); + + var bufHI = BitConverter.GetBytes(numvalueHI).ToArray(); + var bufLI = BitConverter.GetBytes(numvalueLI).ToArray(); + var bufHO = BitConverter.GetBytes(numvalueHO).ToArray(); + var bufLO = BitConverter.GetBytes(numvalueLO).ToArray(); + + System.Collections.BitArray b = new System.Collections.BitArray(new byte[] { bufLI[2], bufLI[3], bufLI[0], bufLI[1] }); + for (int i = 0; i < b.Length; i++) + { + this._valueI[i] = b.Get(i); + if (OldvalueI[i] != this._valueI[i]) + { + try + { + if (IOValueChanged != null) + IOValueChanged(this, new IOValueEventArgs(eIOPINDIR.INPUT, i, OldvalueI[i], _valueI[i])); + } + catch (Exception ex) + { + if (IOErrorMessage != null) + IOErrorMessage(this, new MessageEventArgs(true, ex.Message)); + } + + this.OldvalueI[i] = this._valueI[i]; + } + } + System.Collections.BitArray bO = new System.Collections.BitArray(new byte[] { bufLO[2], bufLO[3], bufLO[0], bufLO[1] }); + for (int i = 0; i < bO.Length; i++) + { + this._valueO[i] = bO.Get(i); + if (OldvalueO[i] != this._valueO[i]) + { + try + { + if (IOValueChanged != null) + IOValueChanged(this, new IOValueEventArgs(eIOPINDIR.OUTPUT, i, OldvalueO[i], _valueO[i])); + } + catch (Exception ex) + { + if (IOErrorMessage != null) + IOErrorMessage(this, new MessageEventArgs(true, ex.Message)); + } + + this.OldvalueO[i] = this._valueO[i]; + } + } + break; + } + } + } + } + + } +} diff --git a/Sub/arMasterK/Project/Properties/AssemblyInfo.cs b/Sub/arMasterK/Project/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..bace5d3 --- /dev/null +++ b/Sub/arMasterK/Project/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 어셈블리의 일반 정보는 다음 특성 집합을 통해 제어됩니다. +// 어셈블리와 관련된 정보를 수정하려면 +// 이 특성 값을 변경하십시오. +[assembly: AssemblyTitle("MasterK PLC I/O DLL")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("SIMP")] +[assembly: AssemblyProduct("MasterKDLL")] +[assembly: AssemblyCopyright("Copyright © SIMP 2018")] +[assembly: AssemblyTrademark("SimpleSoft")] +[assembly: AssemblyCulture("")] + +// ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에 +// 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면 +// 해당 형식에 대해 ComVisible 특성을 true로 설정하십시오. +[assembly: ComVisible(false)] + +// 이 프로젝트가 COM에 노출되는 경우 다음 GUID는 typelib의 ID를 나타냅니다. +[assembly: Guid("59413cb9-8a6a-4a66-92c1-94d7baea812d")] + +// 어셈블리의 버전 정보는 다음 네 가지 값으로 구성됩니다. +// +// 주 버전 +// 부 버전 +// 빌드 번호 +// 수정 버전 +// +// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 버전이 자동으로 +// 지정되도록 할 수 있습니다. +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("18.08.02.1730")] +[assembly: AssemblyFileVersion("18.08.02.1730")] diff --git a/Sub/arMasterK/Project/Properties/Resources.Designer.cs b/Sub/arMasterK/Project/Properties/Resources.Designer.cs new file mode 100644 index 0000000..ed45ed3 --- /dev/null +++ b/Sub/arMasterK/Project/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// 이 코드는 도구를 사용하여 생성되었습니다. +// 런타임 버전:4.0.30319.42000 +// +// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면 +// 이러한 변경 내용이 손실됩니다. +// +//------------------------------------------------------------------------------ + +namespace arDev.Properties { + using System; + + + /// + /// 지역화된 문자열 등을 찾기 위한 강력한 형식의 리소스 클래스입니다. + /// + // 이 클래스는 ResGen 또는 Visual Studio와 같은 도구를 통해 StronglyTypedResourceBuilder + // 클래스에서 자동으로 생성되었습니다. + // 멤버를 추가하거나 제거하려면 .ResX 파일을 편집한 다음 /str 옵션을 사용하여 ResGen을 + // 다시 실행하거나 VS 프로젝트를 다시 빌드하십시오. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.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 (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("arDev.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/Sub/arMasterK/Project/Properties/Resources.resx b/Sub/arMasterK/Project/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/Sub/arMasterK/Project/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/Sub/arMasterK/Project/Properties/Settings.Designer.cs b/Sub/arMasterK/Project/Properties/Settings.Designer.cs new file mode 100644 index 0000000..ad000cb --- /dev/null +++ b/Sub/arMasterK/Project/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// 이 코드는 도구를 사용하여 생성되었습니다. +// 런타임 버전:4.0.30319.42000 +// +// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면 +// 이러한 변경 내용이 손실됩니다. +// +//------------------------------------------------------------------------------ + +namespace arDev.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.11.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/Sub/arMasterK/Project/Properties/Settings.settings b/Sub/arMasterK/Project/Properties/Settings.settings new file mode 100644 index 0000000..3964565 --- /dev/null +++ b/Sub/arMasterK/Project/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Sub/arMasterK/Project/Util.cs b/Sub/arMasterK/Project/Util.cs new file mode 100644 index 0000000..4d9e2a5 --- /dev/null +++ b/Sub/arMasterK/Project/Util.cs @@ -0,0 +1,425 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; + +namespace arDev +{ + public partial class MasterK + { + protected int ReceiveByte() + { + bool done = false; + int ret_val; + + // Await 1 char... + if (!sw_ch.IsRunning) + sw_ch.Start(); + + do + { + if (_device.BytesToRead > 0) + { + ret_val = _device.ReadByte(); + done = true; + } + else + ret_val = -1; + } while ((!done) && ((sw_ch.ElapsedMilliseconds - char_tmo) < 10)); + + if (done) + char_tmo = sw_ch.ElapsedMilliseconds; // Char received with no errors...reset timeout counter for next char! + + return ret_val; + } + + + protected int GetInterframeDelay() + { + int ret_val; + + if (_device.BaudRate > 19200) + ret_val = 2; // Fixed value = 1.75ms up rounded + else + { + int nbits = 1 + _device.DataBits; + nbits += _device.Parity == System.IO.Ports.Parity.None ? 0 : 1; + switch (_device.StopBits) + { + case System.IO.Ports.StopBits.One: + nbits += 1; + break; + + case System.IO.Ports.StopBits.OnePointFive: // Ceiling + case System.IO.Ports.StopBits.Two: + nbits += 2; + break; + } + ret_val = Convert.ToInt32(Math.Ceiling(1 / (((double)_device.BaudRate / ((double)nbits * 3.5d)) / 1000))); + } + + return ret_val; + } + protected int GetIntercharDelay() + { + int ret_val; + + if (_device.BaudRate > 19200) + ret_val = 1; // Fixed value = 0.75 ms up rounded + else + { + int nbits = 1 + _device.DataBits; + nbits += _device.Parity == System.IO.Ports.Parity.None ? 0 : 1; + switch (_device.StopBits) + { + case System.IO.Ports.StopBits.One: + nbits += 1; + break; + + case System.IO.Ports.StopBits.OnePointFive: // Ceiling + case System.IO.Ports.StopBits.Two: + nbits += 2; + break; + } + ret_val = Convert.ToInt32(Math.Ceiling(1 / (((double)_device.BaudRate / ((double)nbits * 1.5d)) / 1000))); + } + + return ret_val; + } + + /// + /// IO모니터가 실행중인지 확인합니다. + /// + [Description("I/O보드 핀 상태를 쓰레드를 이용하여 읽고 있는지 여부"), Browsable(false)] + public Boolean isRunMonitor + { + get + { + if (thMonitor == null) return false; + return this.thMonitor.IsAlive; + } + } + + /// + /// 16진수 문자열 형태로 반환합니다. + /// + /// + /// + [Description("")] + protected string GetHexString(Byte[] input) + { + if (input == null || input.Length < 1) return string.Empty; + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + foreach (byte b in input) + sb.Append(" " + b.ToString("X2")); + return sb.ToString(); + } + + + /// + /// 현재 시스템이 x64 인지 확인합니다. + /// + [Description("")] + protected Boolean isX64 + { + get + { + if (IntPtr.Size == 8) return true; + else return false; + } + } + + + /// + /// 초기화가 되어잇는지 체크합니다. + /// + [Description("")] + public bool IsInit + { + get + { + if (!IsOpen() || !this._isInit) return false; + else return true; + } + } + + /// + /// 해당 버퍼가 NAK 응답인지 체크합니다. + /// + /// + /// + [Description("")] + protected Boolean isNak(byte[] buffer) + { + if (buffer[0] == 0x15) + { + string hexString = GetHexString(buffer); + RaiseMessage(true, "NAK Response : " + hexString); + return true; + } + return false; + } + + + public bool IsOpen() + { + if (_device == null) return false; + return _device.IsOpen; + } + + protected void ClearBuffer(Boolean ClearDeviceBuffer=false) + { + _dlc = 0; + _bDlc = false; + _bStx = false; + _CommandCode = 0x00; + if (ClearDeviceBuffer) + { + this._device.DiscardInBuffer(); + this._device.DiscardOutBuffer(); + } + } + + /// + /// io모니터창을 표시합니다. + /// + [Description("")] + public void ShowIOMonitor() + { + fIOMonitor f = new fIOMonitor(this); + f.Show(); + } + + #region "html generate" + + private string getHtmlHeader() + { + return "" + + "" + + "" + + "" + + "" + + ""; + } + + private string getHtmlTail() + { + return ""; + } + private string getTableHeadStr() + { + return ""; + } + private string getTableHead() + { + return "
Type Name Return Description
"; + } + private string getTableHeadEnum() + { + return "
Type NameDescription
"; + } + private string getTableTail() + { + return "
Return Name Description
"; + } + private string findReturnType(string fieldname) + { + if (fieldname.IndexOf('+') >= 0) + { + return fieldname.Split('+')[1]; + } + else return fieldname; + } + + private string getMethodReturnType(Type source, MemberInfo member) + { + switch (member.MemberType) + { + case MemberTypes.Method: + var met = source.GetMethod(member.Name); + return source.GetMethod(member.Name).ReturnType.ToString().Substring(7); + case MemberTypes.Property: + var pt = source.GetProperty(member.Name); + if (pt != null) + return pt.PropertyType.FullName.Substring(7); + break; + case MemberTypes.Field: + var fd = source.GetField(member.Name); + string fieldname = fd.FieldType.FullName.Substring(7); + return findReturnType(fieldname); + } + return ""; + + } + /// + /// HTML 메뉴얼작성용 코드를 생성합니다.(0==command,1==enum,2==structure) + /// + public string MakeHTML(byte type = 0) + { + System.Text.StringBuilder sb = new StringBuilder(); + + sb.AppendLine(getHtmlHeader()); + + if (type == 2) + { + + var typeSmsg = typeof(sRecvMessage); + sb.AppendLine("

[ " + typeSmsg.Name + " ]

"); + sb.AppendLine(getTableHeadStr()); + foreach (var member in typeSmsg.GetMembers()) + { + if (member.Name.StartsWith("get_") || member.Name.StartsWith("set_") || + member.Name.StartsWith("Equals") || member.Name.StartsWith("GetHashCode") || + member.Name.StartsWith("GetType")) continue; + + sb.AppendLine(""); + sb.AppendLine(" " + member.MemberType.ToString() + ""); + sb.AppendLine(" " + member.Name + ""); + sb.AppendLine(" " + getMethodReturnType(typeSmsg, member) + ""); + sb.AppendLine(" " + member.Name + ""); + sb.AppendLine(""); + } + sb.AppendLine(getTableTail()); + + } + else if (type == 1) + { + //enum list + + var typeeIO = typeof(eIOPINDIR); + sb.AppendLine("

[ " + typeeIO.Name + " ]

"); + sb.AppendLine(getTableHeadEnum()); + foreach (var member in typeeIO.GetFields()) + { + if (member.Name.StartsWith("get_") || member.Name.StartsWith("set_") || + member.Name.StartsWith("Equals") || member.Name.StartsWith("GetHashCode") || + member.Name.StartsWith("GetType") || member.Name.EndsWith("__")) continue; + + sb.AppendLine(""); + sb.AppendLine(" Byte"); + sb.AppendLine(" " + member.Name + ""); + sb.AppendLine(" " + member.Name + ""); + sb.AppendLine(""); + } + sb.AppendLine(getTableTail()); + + typeeIO = typeof(eErrorCode); + sb.AppendLine("

[ " + typeeIO.Name + " ]

"); + sb.AppendLine(getTableHeadEnum()); + foreach (var member in typeeIO.GetFields()) + { + if (member.Name.StartsWith("get_") || member.Name.StartsWith("set_") || + member.Name.StartsWith("Equals") || member.Name.StartsWith("GetHashCode") || + member.Name.StartsWith("GetType") || member.Name.EndsWith("__")) continue; + + sb.AppendLine(""); + sb.AppendLine(" Byte"); + sb.AppendLine(" " + member.Name + ""); + sb.AppendLine(" " + member.Name + ""); + sb.AppendLine(""); + } + sb.AppendLine(getTableTail()); + + typeeIO = typeof(eOpCode); + sb.AppendLine("

[ " + typeeIO.Name + " ]

"); + sb.AppendLine(getTableHeadEnum()); + foreach (var member in typeeIO.GetFields()) + { + if (member.Name.StartsWith("get_") || member.Name.StartsWith("set_") || + member.Name.StartsWith("Equals") || member.Name.StartsWith("GetHashCode") || + member.Name.StartsWith("GetType") || member.Name.EndsWith("__")) continue; + + sb.AppendLine(""); + sb.AppendLine(" Byte"); + sb.AppendLine(" " + member.Name + ""); + sb.AppendLine(" " + member.Name + ""); + sb.AppendLine(""); + } + sb.AppendLine(getTableTail()); + } + else + { + //main + sb.AppendLine("

[ Methods ]

"); + sb.AppendLine(getTableHead()); + foreach (var member in GetType().GetMethods()) + { + if (member.Name.StartsWith("get_") || member.Name.StartsWith("set_") || + member.Name.StartsWith("Equals") || member.Name.StartsWith("GetHashCode") || + member.Name.StartsWith("GetType") || member.Name.StartsWith("add_") || + member.Name.StartsWith("remove_")) continue; + + sb.AppendLine(""); + sb.AppendLine(" " + findReturnType(member.ReturnType.ToString().Substring(7)) + ""); + sb.AppendLine(" " + member.Name + ""); + sb.AppendLine(" " + member.Name + ""); + sb.AppendLine(""); + } + sb.AppendLine(getTableTail()); + + + sb.AppendLine("

[ Properties ]

"); + sb.AppendLine(getTableHead()); + foreach (var member in GetType().GetProperties()) + { + if (member.Name.StartsWith("get_") || member.Name.StartsWith("set_") || + member.Name.StartsWith("Equals") || member.Name.StartsWith("GetHashCode") || + member.Name.StartsWith("GetType") || member.Name.StartsWith("add_") || + member.Name.StartsWith("remove_")) continue; + sb.AppendLine(""); + sb.AppendLine(" " + findReturnType(member.PropertyType.FullName.Substring(7)) + ""); + sb.AppendLine(" " + member.Name + ""); + sb.AppendLine(" " + member.Name + ""); + sb.AppendLine(""); + } + sb.AppendLine(getTableTail()); + + + sb.AppendLine("

[ Events ]

"); + sb.AppendLine(getTableHead()); + foreach (var member in GetType().GetEvents()) + { + if (member.Name.StartsWith("get_") || member.Name.StartsWith("set_") || + member.Name.StartsWith("Equals") || member.Name.StartsWith("GetHashCode") || + member.Name.StartsWith("GetType") || member.Name.StartsWith("add_") || + member.Name.StartsWith("remove_")) continue; + + sb.AppendLine(""); + sb.AppendLine(" " + "" + ""); + sb.AppendLine(" " + member.Name + ""); + sb.AppendLine(" " + member.Name + ""); + sb.AppendLine(""); + } + sb.AppendLine(getTableTail()); + + + + sb.AppendLine("

[ Fields ]

"); + sb.AppendLine(getTableHead()); + foreach (var member in GetType().GetFields()) + { + if (member.Name.StartsWith("get_") || member.Name.StartsWith("set_") || + member.Name.StartsWith("Equals") || member.Name.StartsWith("GetHashCode") || + member.Name.StartsWith("GetType") || member.Name.StartsWith("add_") || + member.Name.StartsWith("remove_")) continue; + + sb.AppendLine(""); + sb.AppendLine(" " + findReturnType(member.FieldType.FullName.Substring(7)) + ""); + sb.AppendLine(" " + member.Name + ""); + sb.AppendLine(" " + member.Name + ""); + sb.AppendLine(""); + } + sb.AppendLine(getTableTail()); + } + + sb.AppendLine(getHtmlTail()); + return sb.ToString(); + } + #endregion + + + } +} diff --git a/Sub/arMasterK/Project/Write.cs b/Sub/arMasterK/Project/Write.cs new file mode 100644 index 0000000..8e8d87d --- /dev/null +++ b/Sub/arMasterK/Project/Write.cs @@ -0,0 +1,213 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.ComponentModel; +using System.Windows.Forms; +using System.Drawing; +using System.Drawing.Design; +using System.Reflection; +using System.Runtime; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +//for tcp,udp +using System.Net.Sockets; +using System.Net; + +namespace arDev +{ + public partial class MasterK + { + + protected Boolean Send(byte[] packet) + { + try + { + _device.DiscardInBuffer(); + System.Threading.Thread.Sleep(1); + _device.DiscardOutBuffer(); + System.Threading.Thread.Sleep(1); + _device.Write(packet, 0, packet.Length); + char_tmo = 0; + return true; + } + catch (Exception ex) + { + RaiseMessage(true, "Device Send Error : " + ex.Message); + return false; + } + } + + protected Boolean Write(byte[] packet) + { + bSyncRecvOK = false; + errorMessage = string.Empty; + lastSendTime = DateTime.Now; + lastSendMessage = Parse_SendBuffer(packet); + Boolean retval = Send(packet); + if (!retval) RaiseMessage(true, "Tx Error : " + System.Text.Encoding.Default.GetString(packet)); + else RaiseDataMessage(eMsgType.Tx, packet); + return retval; + } + public byte[] UserWrite(string command) + { + _mre.Reset(); + var buffer = WriteSync(command); + _mre.Set(); + return buffer; + } + + protected byte[] WriteSync(string command) + { + var bytes = System.Text.Encoding.Default.GetBytes(command); + if (command[0] == (char)wSTX) + { + return WriteSync(bytes); + } + else + { + List packet = new List(); + packet.Add(wSTX); + packet.AddRange(bytes); + packet.Add(wETX); + return WriteSync(packet.ToArray()); + } + } + protected int interframe_delay; + System.Diagnostics.Stopwatch sw_ch; + long char_tmo; + + string savefil = string.Empty; + + // Int64 writeCnt = 0; + protected byte[] WriteSync(byte[] command) + { + //writeCnt += 1; + //RaiseMessage(false, ">> WriteSync Enter " + writeCnt.ToString()); + if (savefil == "") + { + savefil = Environment.CurrentDirectory + "\rxBuffer.txt"; + } + // if (!mre.WaitOne(500)) + // { + // errorMessage = "WaitOne error 500ms"; + // return null; + // } + + //// RaiseMessage(false, "write data sync"); + + // mre.Reset(); + + + //Boolean isComplete = false; + Boolean isTimeOut = false; + errorMessage = "Wait Data #2"; + + LastRecvMessage.Clear(); + List _buffer = new List(); + wat.Restart(); + + System.Threading.Thread.Sleep(interframe_delay); + + //send data + if (!Write(command)) + { + errorMessage = "sync Buffer is null(1)"; + //mre.Set(); + //RaiseMessage(false, "<< WriteSync Out " + writeCnt.ToString()); + return null; + } + + bool done = false; + System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch(); + sw.Start(); + int rcv ; + long tmo = 0; + do + { + int buffercnt = 0; + try + { + buffercnt = _device.BytesToRead; + } + catch (Exception ex) + { + RaiseMessage(true, ex.Message); + } + + if (buffercnt > 0) + { + try + { + rcv = _device.ReadByte(); + // System.IO.File.WriteAllBytes(savefil, new byte[] { (byte)rcv }); + RaiseDataMessage(eMsgType.RxRaw, new byte[(byte)rcv]); + + if (rcv == 0x06 || rcv == 0x015) + { + _buffer.Clear(); + _buffer.Add((byte)rcv); + //isComplete = false; + } + else if (rcv == 0x03) //endtext + { + //모두 수신한경우이다. + _buffer.Add((byte)rcv); + //isComplete = true; + done = true; + break; + } + else + { + _buffer.Add((byte)rcv); + } + } + catch { + + } + } + tmo = sw.ElapsedMilliseconds; + } while ((!done) && (_device.ReadTimeout > tmo)); + sw_ch.Stop(); + sw.Stop(); + + if (tmo >= _device.ReadTimeout) + { + errorMessage = string.Format("Writesync TimeOut({0})", _device.ReadTimeout); + isTimeOut = true; + } + + byte[] Dummy = new byte[_buffer.Count]; + _buffer.CopyTo(Dummy); + + // mre.Set(); + if (isTimeOut) + { + RaiseMessage(true, errorMessage); + //RaiseMessage(false, "<< WriteSync Out " + writeCnt.ToString()); + return null; + } + else + { + RaiseDataMessage(eMsgType.Rx, Dummy); + var frame = Parse_RecvBuffer(Dummy); + if (frame.Buffer == null) + { + errorMessage = "sync buffer is null(2)"; + RaiseMessage(true, errorMessage); + // RaiseMessage(false, "<< WriteSync Out " + writeCnt.ToString()); + return null; + } + else + { + // RaiseMessage(false, "<< WriteSync Out " + writeCnt.ToString()); + return frame.Buffer; + } + } + } + + } + +} diff --git a/Sub/arMasterK/Project/arMasterK.csproj b/Sub/arMasterK/Project/arMasterK.csproj new file mode 100644 index 0000000..18f658e --- /dev/null +++ b/Sub/arMasterK/Project/arMasterK.csproj @@ -0,0 +1,100 @@ + + + + + Debug + AnyCPU + {E0133085-E5F9-4275-9DB8-F8F20EF8561F} + Library + Properties + arDev + arMasterK + v4.8 + 512 + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + + + AnyCPU + pdbonly + true + ..\..\DLL\ + TRACE + prompt + 4 + false + + + + + + + + + + + + + + + + + + + + + + + Form + + + fIOMonitor.cs + + + + + + fIOMonitor.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + \ No newline at end of file diff --git a/Sub/arMasterK/Project/fIOMonitor.Designer.cs b/Sub/arMasterK/Project/fIOMonitor.Designer.cs new file mode 100644 index 0000000..1a29023 --- /dev/null +++ b/Sub/arMasterK/Project/fIOMonitor.Designer.cs @@ -0,0 +1,144 @@ +namespace arDev +{ + partial class fIOMonitor + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.tblOutput = new System.Windows.Forms.TableLayoutPanel(); + this.tblINput = new System.Windows.Forms.TableLayoutPanel(); + this.tableLayoutPanel1.SuspendLayout(); + this.SuspendLayout(); + // + // 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.label1, 0, 0); + this.tableLayoutPanel1.Controls.Add(this.label2, 1, 0); + this.tableLayoutPanel1.Controls.Add(this.tblOutput, 1, 1); + this.tableLayoutPanel1.Controls.Add(this.tblINput, 0, 1); + this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 2; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 36F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(582, 480); + this.tableLayoutPanel1.TabIndex = 0; + // + // label1 + // + this.label1.Dock = System.Windows.Forms.DockStyle.Fill; + this.label1.Location = new System.Drawing.Point(3, 0); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(285, 36); + this.label1.TabIndex = 0; + this.label1.Text = "INPUT"; + this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // label2 + // + this.label2.Dock = System.Windows.Forms.DockStyle.Fill; + this.label2.Location = new System.Drawing.Point(294, 0); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(285, 36); + this.label2.TabIndex = 0; + this.label2.Text = "OUTPUT"; + this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; + // + // tblOutput + // + this.tblOutput.ColumnCount = 4; + this.tblOutput.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F)); + this.tblOutput.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F)); + this.tblOutput.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F)); + this.tblOutput.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F)); + this.tblOutput.Dock = System.Windows.Forms.DockStyle.Fill; + this.tblOutput.Location = new System.Drawing.Point(294, 39); + this.tblOutput.Name = "tblOutput"; + this.tblOutput.RowCount = 8; + this.tblOutput.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 12.5F)); + this.tblOutput.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 12.5F)); + this.tblOutput.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 12.5F)); + this.tblOutput.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 12.5F)); + this.tblOutput.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 12.5F)); + this.tblOutput.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 12.5F)); + this.tblOutput.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 12.5F)); + this.tblOutput.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 12.5F)); + this.tblOutput.Size = new System.Drawing.Size(285, 438); + this.tblOutput.TabIndex = 1; + // + // tblINput + // + this.tblINput.ColumnCount = 4; + this.tblINput.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F)); + this.tblINput.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F)); + this.tblINput.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F)); + this.tblINput.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 25F)); + this.tblINput.Dock = System.Windows.Forms.DockStyle.Fill; + this.tblINput.Location = new System.Drawing.Point(3, 39); + this.tblINput.Name = "tblINput"; + this.tblINput.RowCount = 8; + this.tblINput.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 12.5F)); + this.tblINput.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 12.5F)); + this.tblINput.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 12.5F)); + this.tblINput.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 12.5F)); + this.tblINput.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 12.5F)); + this.tblINput.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 12.5F)); + this.tblINput.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 12.5F)); + this.tblINput.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 12.5F)); + this.tblINput.Size = new System.Drawing.Size(285, 438); + this.tblINput.TabIndex = 1; + // + // fIOMonitor + // + this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 12F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(582, 480); + this.Controls.Add(this.tableLayoutPanel1); + this.Name = "fIOMonitor"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "fIOMonitor"; + this.Load += new System.EventHandler(this.fIOMonitor_Load); + this.tableLayoutPanel1.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TableLayoutPanel tblOutput; + private System.Windows.Forms.TableLayoutPanel tblINput; + } +} \ No newline at end of file diff --git a/Sub/arMasterK/Project/fIOMonitor.cs b/Sub/arMasterK/Project/fIOMonitor.cs new file mode 100644 index 0000000..de728ca --- /dev/null +++ b/Sub/arMasterK/Project/fIOMonitor.cs @@ -0,0 +1,77 @@ +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 arDev +{ + public partial class fIOMonitor : Form + { + MasterK dio; + public fIOMonitor(MasterK _device) + { + InitializeComponent(); + dio = _device; + } + + Button[] btInput; + Button[] btOutput; + private void fIOMonitor_Load(object sender, EventArgs e) + { + btInput = new Button[dio.DICount]; + btOutput = new Button[dio.DOCount]; + for(int i = 0; i< dio.DICount;i++) + { + Button lb = new Button(); + lb.Text = string.Format("{0}",i+1); + lb.Tag = i; + lb.Click += lb_ClickI; + lb.Dock = DockStyle.Fill; + lb.BackColor = dio.INPUT(i) ? Color.Lime : Color.White; + btInput[i] = lb; + this.tblINput.Controls.Add(lb); + } + for (int i = 0; i < dio.DOCount; i++) + { + Button lb = new Button(); + lb.Text = string.Format("{0}", i + 1); + lb.Tag = i; + lb.Click += lb_ClickO; + lb.Dock = DockStyle.Fill; + lb.BackColor = dio.OUTPUT(i) ? Color.Lime : Color.White; + btOutput[i] = lb; + this.tblOutput.Controls.Add(lb); + } + + dio.IOValueChanged += dio_IOValueChanged; + } + + void dio_IOValueChanged(object sender, MasterK.IOValueEventArgs e) + { + if(e.Direction == MasterK.eIOPINDIR.INPUT) + { + btInput[e.ArrIDX].BackColor = e.NewValue ? Color.Lime : Color.White; + } + else + { + btOutput[e.ArrIDX].BackColor = e.NewValue ? Color.Lime : Color.White; + } + } + void lb_ClickI(object sender, EventArgs e) + { + var bt = sender as Button; + //MessageBox.Show("input click : " + bt.Tag.ToString()); + } + void lb_ClickO(object sender, EventArgs e) + { + var bt = sender as Button; + var idx = int.Parse(bt.Tag.ToString()); + dio.SetToggle(idx); + } + } +} diff --git a/Sub/arMasterK/Project/fIOMonitor.resx b/Sub/arMasterK/Project/fIOMonitor.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/Sub/arMasterK/Project/fIOMonitor.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + \ No newline at end of file