Compare commits

...

10 Commits

Author SHA1 Message Date
shark219-hub
9958dd0cf8 커밋3 2025-06-23 18:18:20 +09:00
shark219-hub
00683decda 재커밋 2025-06-23 17:52:18 +09:00
shark219-hub
891b394854 Frm_trend.cs, 'Parallel.For(0, this.ChartListData.Length - 1' -> 'Parallel.For(0, this.ChartListData.Length' 변경 2025-06-23 17:35:45 +09:00
shark219-hub
bdd929a984 20250623 커밋 2025-06-23 09:25:42 +09:00
Arin(asus)
e46b1c709b arMaskterK 프로젝트를 vms2016_cs 레포에서 현 레포로 이동 2025-06-21 11:43:19 +09:00
Arin(asus)
229ec8be66 백업파일제거 2025-06-21 11:42:01 +09:00
Arin(asus)
b189af27c3 1. 알람 AUTO설정 時, 관련 오류수정 후 적용
2.    NullBalance 관련 요청사항(절대치로 비교) 적용

3.    알람목록의 '비고'컬럼에 알람수치 입력 기능 추가
2025-06-21 11:24:18 +09:00
shark219-hub
d4c6715811 Merge branch 'master' of https://gitlab.com/jd-tek/vms2016_kadisp 2025-06-12 10:09:13 +09:00
shark219-hub
c1ba388b5a 재커밋 2025-06-12 10:09:01 +09:00
shark219
6e777e9599 재커밋 2025-06-12 09:40:47 +09:00
32 changed files with 3090 additions and 221 deletions

6
Sub/arMasterK/.gitignore vendored Normal file
View File

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

View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" 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>{D92246F1-981A-452C-9E0A-09CD9F68B102}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Demo</RootNamespace>
<AssemblyName>Demo</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</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="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.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Project\arMasterK.csproj">
<Project>{e0133085-e5f9-4275-9db8-f8f20ef8561f}</Project>
<Name>arMasterK</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

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

View File

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

28
Sub/arMasterK/MasterK.sln Normal file
View File

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

2
Sub/arMasterK/Project/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
/MasterK.v12.suo
/MasterK.sln

View File

@@ -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,
}
/// <summary>
/// digital input/output direction
/// </summary>
public enum eIOPINDIR : byte
{
[Description("Digital Input")]
INPUT = 0,
[Description("Digital Output")]
OUTPUT = 1,
}
/// <summary>
/// error code list
/// </summary>
public enum eErrorCode : byte
{
[Description("포트가사용중입니다.")]
PortBusy = 0,
[Description("열려있지않습니다.")]
NotOpen,
[Description("쓰기오류")]
WriteError,
[Description("읽기오류")]
ReadError,
[Description("프레임오류")]
FrameError,
[Description("체크섬오류")]
ChecksumError
}
/// <summary>
/// message frame
/// </summary>
public struct sRecvMessage
{
/// <summary>
/// 국번
/// </summary>
public string Device;
/// <summary>
/// 명령어
/// </summary>
public char Command;
/// <summary>
/// 명령어타입
/// </summary>
public string CmdType;
/// <summary>
/// 블록수
/// </summary>
public int BlockCount;
/// <summary>
/// 데이터갯수
/// </summary>
public int DataLen;
/// <summary>
/// 데이터
/// </summary>
public string Data;
public string FullString;
/// <summary>
/// full message frame
/// </summary>
[Description("전체 메세지 영역")]
public byte[] Buffer;
/// <summary>
/// check byte (crc16)
/// </summary>
[Description("체크섬 2byte(CRC 16)")]
public byte[] checksum;
/// <summary>
/// checksum error
/// </summary>
[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
{
/// <summary>
/// 국번
/// </summary>
public string Device;
/// <summary>
/// 명령어
/// </summary>
public char Command;
/// <summary>
/// 명령어타입
/// </summary>
public string CmdType;
/// <summary>
/// 변수길이
/// </summary>
public int DeviceLength;
public int NumberofBlock;
/// <summary>
/// 변수명
/// </summary>
public string VarName;
/// <summary>
/// 데이터갯수
/// </summary>
public int DataLen;
public string Data;
/// <summary>
/// full message frame
/// </summary>
[Description("전체 메세지 영역")]
public byte[] Buffer;
public string Strbuffer;
/// <summary>
/// check byte (crc16)
/// </summary>
[Description("체크섬 2byte(CRC 16)")]
public byte[] checksum;
/// <summary>
/// checksum error
/// </summary>
[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;
}
}
}
}
}

View File

@@ -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;
/// <summary>
/// 바이트배열의 버퍼값
/// </summary>
public byte[] Value { get { return _buffer; } }
public eMsgType Direction { get; set; }
/// <summary>
/// 버퍼(바이트배열)의 데이터를 문자로 반환합니다.
/// </summary>
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"
/// <summary>
/// 일반적인 메세지 혹은 오류메세지 이벤트
/// </summary>
public event EventHandler<MessageEventArgs> Message;
/// <summary>
/// 데이터메시이벤트 (Rx,Tx) 별로 구분됩니다.
/// </summary>
public event EventHandler<DataEventArgs> DataMessage;
/// <summary>
/// 가공되어진 최종 메세지 형태값을 가지고 있습니다.
/// </summary>
public event EventHandler<FrameEventArgs> ReceiveFrame;
/// <summary>
/// ReadProcess에의해서 감시되며 포트의 상태값이 바뀐다면 발생함
/// </summary>
public event EventHandler<IOValueEventArgs> IOValueChanged;
/// <summary>
/// AI의 값을 이벤트로 발생합니다.발생주기는 AIInterval을 참고합니다.
/// </summary>
public event EventHandler<AIValueEventArgs> AIValueChanged;
/// <summary>
/// 오류발생시 메세지가 발생함
/// </summary>
public event EventHandler<MessageEventArgs> IOErrorMessage;
/// <summary>
/// anlog 관련한 오류 메세지
/// </summary>
/// <remarks>Analog Data Error Message</remarks>
public event EventHandler<MessageEventArgs> AIErrorMessage;
#endregion
}
}

View File

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

View File

@@ -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;
/// <summary>
/// device index
/// </summary>
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");
}
}
}
/// <summary>
/// 개체를 해제합니다.
/// </summary>
[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"
/// <summary>
/// 입력핀 상태값을 확인합니다.
/// </summary>
/// <param name="arridx">0부터 시작하는 인덱스값</param>
/// <returns></returns>
[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];
}
/// <summary>
/// 입력핀 상태를 모두 반환합니다.
/// </summary>
[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);
}
}
/// <summary>
/// 출력핀 상태를 모두 반환합니다.
/// </summary>
[Description("")]
public Boolean[] getOutputArray
{
get
{
return (Boolean[])this._valueO.Clone();
}
}
/// <summary>
/// 출력핀 상태 값을 확인합니다.
/// </summary>
/// <param name="arridx">0부터 시작하는 인덱스값</param>
/// <returns></returns>
[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];
}
/// <summary>
/// read digital input port state
/// </summary>
/// <returns></returns>
[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();
}
/// <summary>
/// read digital output port state
/// </summary>
/// <returns></returns>
[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"
/// <summary>
/// 오류메세지 반환
/// </summary>
/// <returns></returns>
[Description("")]
public string GetErrorMessage()
{
return this.errorMessage;
}
#region "raise Message"
/// <summary>
/// 일반메세지륿 라생시킵니다.
/// </summary>
/// <param name="isError"></param>
/// <param name="message"></param>
[Description("")]
public void RaiseMessage(Boolean isError, string message)
{
if (isError) errorMessage = message; //170920
if (Message != null) Message(this, new MessageEventArgs(isError, message));
}
/// <summary>
/// 지정한 데이터로 바코드가 수신된것처럼 발생시킵니다.(Parser를 사용함)
/// </summary>
/// <param name="b"></param>
[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
/// <summary>
/// Input / Output 핀 상태를 지속적으로 읽는 쓰레드작업을 시작합니다.
/// </summary>
[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();
}
}
/// <summary>
/// INPUT/OUPUT 핀 상태를 모니터링하는 쓰레드를 종료시킵니다.
/// </summary>
/// <returns></returns>
[Description("")]
public bool StopMonitor()
{
try
{
this.bRunMonitor = false;
RaiseMessage(false, "Stop Monitor");
return true;
}
catch (Exception ex)
{
RaiseMessage(true, ex.Message);
return false;
}
}
/// <summary>
/// 지정한 출력포트의 값을 반전 시킵니다.
/// </summary>
/// <param name="arrIndex"></param>
/// <returns></returns>
[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);
}
/// <summary>
/// 출력을 설정합니다.
/// </summary>
/// <param name="arrIndex"></param>
/// <param name="Value"></param>
/// <param name="Duration"></param>
/// <returns></returns>
[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;
}
/// <summary>
/// 이벤트를 강제 생성합니다.
/// </summary>
/// <param name="Direction"></param>
/// <param name="ArrIDX"></param>
/// <param name="newvalue"></param>
[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;
/// <summary>
/// I/O상태를 모니터링 하여 내부 변수에 값을 저장합니다.
/// </summary>
[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;
}
/// <summary>
///
/// </summary>
/// <param name="Station">0~9</param>
/// <param name="Command">R,W</param>
/// <param name="CmdType">SB,SW ??</param>
/// <param name="Device">%PW000</param>
/// <param name="NumberofData">1</param>
/// <param name="data">HexString</param>
/// <returns></returns>
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
}
}

View File

@@ -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;
}
/// <summary>
/// 수신된 데이터를 분석하고 관련 메세지를 생성합니다.
/// </summary>
/// <param name="opCode"></param>
/// <param name="dataBuffer"></param>
[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;
}
}
}
}
}
}

View File

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

View File

@@ -0,0 +1,63 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 이 코드는 도구를 사용하여 생성되었습니다.
// 런타임 버전:4.0.30319.42000
//
// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면
// 이러한 변경 내용이 손실됩니다.
// </auto-generated>
//------------------------------------------------------------------------------
namespace arDev.Properties {
using System;
/// <summary>
/// 지역화된 문자열 등을 찾기 위한 강력한 형식의 리소스 클래스입니다.
/// </summary>
// 이 클래스는 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() {
}
/// <summary>
/// 이 클래스에서 사용하는 캐시된 ResourceManager 인스턴스를 반환합니다.
/// </summary>
[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;
}
}
/// <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>

View File

@@ -0,0 +1,26 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 이 코드는 도구를 사용하여 생성되었습니다.
// 런타임 버전:4.0.30319.42000
//
// 파일 내용을 변경하면 잘못된 동작이 발생할 수 있으며, 코드를 다시 생성하면
// 이러한 변경 내용이 손실됩니다.
// </auto-generated>
//------------------------------------------------------------------------------
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;
}
}
}
}

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,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;
}
/// <summary>
/// IO모니터가 실행중인지 확인합니다.
/// </summary>
[Description("I/O보드 핀 상태를 쓰레드를 이용하여 읽고 있는지 여부"), Browsable(false)]
public Boolean isRunMonitor
{
get
{
if (thMonitor == null) return false;
return this.thMonitor.IsAlive;
}
}
/// <summary>
/// 16진수 문자열 형태로 반환합니다.
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[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();
}
/// <summary>
/// 현재 시스템이 x64 인지 확인합니다.
/// </summary>
[Description("")]
protected Boolean isX64
{
get
{
if (IntPtr.Size == 8) return true;
else return false;
}
}
/// <summary>
/// 초기화가 되어잇는지 체크합니다.
/// </summary>
[Description("")]
public bool IsInit
{
get
{
if (!IsOpen() || !this._isInit) return false;
else return true;
}
}
/// <summary>
/// 해당 버퍼가 NAK 응답인지 체크합니다.
/// </summary>
/// <param name="buffer"></param>
/// <returns></returns>
[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();
}
}
/// <summary>
/// io모니터창을 표시합니다.
/// </summary>
[Description("")]
public void ShowIOMonitor()
{
fIOMonitor f = new fIOMonitor(this);
f.Show();
}
#region "html generate"
private string getHtmlHeader()
{
return "<html>" +
"<head>" +
"<script src=\"https://rawgit.com/google/code-prettify/master/loader/run_prettify.js?autoload=true&amp;skin=sunburst&amp;lang=css\" defer></script>" +
"<link rel=\"stylesheet\" href=\"styles.css\">" +
"</head>" +
"<body>";
}
private string getHtmlTail()
{
return "</body></html>";
}
private string getTableHeadStr()
{
return "<table> <thead> <tr> <td>Type</td> <td>Name</td> <td>Return</td> <td>Description</td> </tr> </thead> <tbody>";
}
private string getTableHead()
{
return "<table> <thead> <tr> <td>Type</td> <td>Name</td><td>Description</td> </tr> </thead> <tbody>";
}
private string getTableHeadEnum()
{
return "<table> <thead> <tr> <td>Return</td> <td>Name</td> <td>Description</td> </tr> </thead> <tbody>";
}
private string getTableTail()
{
return "</tbody></table>";
}
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 "";
}
/// <summary>
/// HTML 메뉴얼작성용 코드를 생성합니다.(0==command,1==enum,2==structure)
/// </summary>
public string MakeHTML(byte type = 0)
{
System.Text.StringBuilder sb = new StringBuilder();
sb.AppendLine(getHtmlHeader());
if (type == 2)
{
var typeSmsg = typeof(sRecvMessage);
sb.AppendLine("<h4 class=\"structure\">[ " + typeSmsg.Name + " ]</h4>");
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("<tr>");
sb.AppendLine(" <td>" + member.MemberType.ToString() + "</td>");
sb.AppendLine(" <td class=\"tleft\">" + member.Name + "</td>");
sb.AppendLine(" <td>" + getMethodReturnType(typeSmsg, member) + "</td>");
sb.AppendLine(" <td class=\"tleft\">" + member.Name + "</td>");
sb.AppendLine("</tr>");
}
sb.AppendLine(getTableTail());
}
else if (type == 1)
{
//enum list
var typeeIO = typeof(eIOPINDIR);
sb.AppendLine("<h4 class=\"enum\">[ " + typeeIO.Name + " ]</h4>");
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("<tr>");
sb.AppendLine(" <td>Byte</td>");
sb.AppendLine(" <td class=\"tleft\">" + member.Name + "</td>");
sb.AppendLine(" <td class=\"tleft\">" + member.Name + "</td>");
sb.AppendLine("</tr>");
}
sb.AppendLine(getTableTail());
typeeIO = typeof(eErrorCode);
sb.AppendLine("<h4 class=\"enum\">[ " + typeeIO.Name + " ]</h4>");
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("<tr>");
sb.AppendLine(" <td>Byte</td>");
sb.AppendLine(" <td class=\"tleft\">" + member.Name + "</td>");
sb.AppendLine(" <td class=\"tleft\">" + member.Name + "</td>");
sb.AppendLine("</tr>");
}
sb.AppendLine(getTableTail());
typeeIO = typeof(eOpCode);
sb.AppendLine("<h4 class=\"enum\">[ " + typeeIO.Name + " ]</h4>");
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("<tr>");
sb.AppendLine(" <td>Byte</td>");
sb.AppendLine(" <td class=\"tleft\">" + member.Name + "</td>");
sb.AppendLine(" <td class=\"tleft\">" + member.Name + "</td>");
sb.AppendLine("</tr>");
}
sb.AppendLine(getTableTail());
}
else
{
//main
sb.AppendLine("<h4 class=\"method\">[ Methods ]</h4>");
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("<tr>");
sb.AppendLine(" <td>" + findReturnType(member.ReturnType.ToString().Substring(7)) + "</td>");
sb.AppendLine(" <td class=\"tleft\">" + member.Name + "</td>");
sb.AppendLine(" <td class=\"tleft\">" + member.Name + "</td>");
sb.AppendLine("</tr>");
}
sb.AppendLine(getTableTail());
sb.AppendLine("<h4 class=\"method\">[ Properties ]</h4>");
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("<tr>");
sb.AppendLine(" <td>" + findReturnType(member.PropertyType.FullName.Substring(7)) + "</td>");
sb.AppendLine(" <td class=\"tleft\">" + member.Name + "</td>");
sb.AppendLine(" <td class=\"tleft\">" + member.Name + "</td>");
sb.AppendLine("</tr>");
}
sb.AppendLine(getTableTail());
sb.AppendLine("<h4 class=\"method\">[ Events ]</h4>");
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("<tr>");
sb.AppendLine(" <td>" + "" + "</td>");
sb.AppendLine(" <td class=\"tleft\">" + member.Name + "</td>");
sb.AppendLine(" <td class=\"tleft\">" + member.Name + "</td>");
sb.AppendLine("</tr>");
}
sb.AppendLine(getTableTail());
sb.AppendLine("<h4 class=\"method\">[ Fields ]</h4>");
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("<tr>");
sb.AppendLine(" <td>" + findReturnType(member.FieldType.FullName.Substring(7)) + "</td>");
sb.AppendLine(" <td class=\"tleft\">" + member.Name + "</td>");
sb.AppendLine(" <td class=\"tleft\">" + member.Name + "</td>");
sb.AppendLine("</tr>");
}
sb.AppendLine(getTableTail());
}
sb.AppendLine(getHtmlTail());
return sb.ToString();
}
#endregion
}
}

View File

@@ -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<byte> packet = new List<byte>();
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<byte> _buffer = new List<byte>();
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;
}
}
}
}
}

View File

@@ -0,0 +1,100 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" 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>{E0133085-E5F9-4275-9DB8-F8F20EF8561F}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>arDev</RootNamespace>
<AssemblyName>arMasterK</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</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>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\..\DLL\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<StartupObject />
</PropertyGroup>
<ItemGroup>
<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.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Util.cs" />
<Compile Include="Parser.cs" />
<Compile Include="EventArgs.cs" />
<Compile Include="EnumAStruct.cs" />
<Compile Include="fIOMonitor.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="fIOMonitor.Designer.cs">
<DependentUpon>fIOMonitor.cs</DependentUpon>
</Compile>
<Compile Include="Write.cs" />
<Compile Include="MasterK.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="fIOMonitor.resx">
<DependentUpon>fIOMonitor.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>
<DesignTime>True</DesignTime>
</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>
<Content Include="History.txt" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,144 @@
namespace arDev
{
partial class fIOMonitor
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
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;
}
}

View File

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

View File

@@ -0,0 +1,120 @@
<?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>
</root>

View File

@@ -180,7 +180,6 @@ namespace vmsnet
// //
this.BindingNavigatorPositionItem.AccessibleName = "위치"; this.BindingNavigatorPositionItem.AccessibleName = "위치";
this.BindingNavigatorPositionItem.AutoSize = false; this.BindingNavigatorPositionItem.AutoSize = false;
this.BindingNavigatorPositionItem.Font = new System.Drawing.Font("맑은 고딕", 9F);
this.BindingNavigatorPositionItem.Name = "BindingNavigatorPositionItem"; this.BindingNavigatorPositionItem.Name = "BindingNavigatorPositionItem";
this.BindingNavigatorPositionItem.Size = new System.Drawing.Size(50, 23); this.BindingNavigatorPositionItem.Size = new System.Drawing.Size(50, 23);
this.BindingNavigatorPositionItem.Text = "0"; this.BindingNavigatorPositionItem.Text = "0";
@@ -223,7 +222,6 @@ namespace vmsnet
// //
this.tb_search.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(192))))); this.tb_search.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(255)))), ((int)(((byte)(192)))));
this.tb_search.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.tb_search.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.tb_search.Font = new System.Drawing.Font("맑은 고딕", 9F);
this.tb_search.Name = "tb_search"; this.tb_search.Name = "tb_search";
this.tb_search.Size = new System.Drawing.Size(100, 38); this.tb_search.Size = new System.Drawing.Size(100, 38);
this.tb_search.KeyUp += new System.Windows.Forms.KeyEventHandler(this.ToolStripTextBox1_KeyUp); this.tb_search.KeyUp += new System.Windows.Forms.KeyEventHandler(this.ToolStripTextBox1_KeyUp);

View File

@@ -191,7 +191,9 @@ namespace vmsnet
lv.SubItems.Add(item.MAXVOLT.ToString()); lv.SubItems.Add(item.MAXVOLT.ToString());
lv.SubItems.Add(item.MINVOLT.ToString()); lv.SubItems.Add(item.MINVOLT.ToString());
lv.SubItems.Add(item.ATYPESTR); lv.SubItems.Add(item.ATYPESTR);
lv.SubItems.Add(item.REMARK); var remark = item.REMARK;
if (remark.isEmpty()) remark = item.AM2;
lv.SubItems.Add(remark);
switch (item.RTYPESTR.ToUpper()) switch (item.RTYPESTR.ToUpper())
{ {

View File

@@ -361,7 +361,10 @@ namespace vmsnet
var sttdate = PUB.TREND.graph_time_start; var sttdate = PUB.TREND.graph_time_start;
var enddate = PUB.TREND.graph_time_end; var enddate = PUB.TREND.graph_time_end;
//각 파일 그룹별 대상 파일을 수집합니다. //각 파일 그룹별 대상 파일을 수집합니다.
Parallel.For(0, this.ChartListData.Length - 1, i => /* 작성자: 이재웅, 작성일: 2025-06-23, 내용: 0 ~ this.ChartListData.Length - 1 */
// Parallel.For(시작값, 종료값, ...) 형태라고 했을 때, 루프 진행은 '시작값 ~ 종료값-1' 실행된다.
// 'this.ChartListData.Length - 1' -> 'this.ChartListData.Length' 변경
Parallel.For(0, this.ChartListData.Length, i =>
{ {
var DataFileName = $"DATAB{i + 1}"; var DataFileName = $"DATAB{i + 1}";
if (ChartListData[i].ChannelList.Any() == true) this.ChartListData[i].FileList = PUB.DB.GetfileS(DataFileName, sttdate, enddate); if (ChartListData[i].ChannelList.Any() == true) this.ChartListData[i].FileList = PUB.DB.GetfileS(DataFileName, sttdate, enddate);
@@ -496,6 +499,7 @@ namespace vmsnet
//대상파일의 자료를 읽어와서 차트데이터를 구축한다. //대상파일의 자료를 읽어와서 차트데이터를 구축한다.
RecordCount = 0; RecordCount = 0;
// Parallel.For(시작값, 종료값, ...) 형태라고 했을 때, 루프 진행은 '시작값 ~ 종료값-1' 실행된다.
Parallel.For(0, this.ChartListData.Length, i => Parallel.For(0, this.ChartListData.Length, i =>
{ {
ParseChDataToChart(i, ChartListData[i], DTCHLIST); ParseChDataToChart(i, ChartListData[i], DTCHLIST);

View File

@@ -13,13 +13,13 @@ namespace vmsnet
/// </summary> /// </summary>
public byte SlaveID { get; set; } = 1; // Slave No public byte SlaveID { get; set; } = 1; // Slave No
public DigitalIndicator(byte slaveID = 0) : base("", new RtuConfigure { BaudRate = 9600, DataBits = 8, StopBits = System.IO.Ports.StopBits.One, Parity = System.IO.Ports.Parity.None }) public DigitalIndicator(byte slaveID = 1) : base("", new RtuConfigure { BaudRate = 9600, DataBits = 8, StopBits = System.IO.Ports.StopBits.One, Parity = System.IO.Ports.Parity.None })
{ {
SlaveID = slaveID; SlaveID = slaveID;
} }
public DigitalIndicator(string comPort, RtuConfigure configure, byte slaveId = 0) : base(comPort, configure) public DigitalIndicator(string comPort, RtuConfigure configure, byte slaveId = 1) : base(comPort, configure)
{ {
SlaveID = slaveId; SlaveID = slaveId;
} }
@@ -45,13 +45,6 @@ namespace vmsnet
//return WriteValue(buffer); //return WriteValue(buffer);
} }
UInt16[] splitI32(Int32 value)
{
var hValue = (UInt16)(value >> 16); // 상위 16 Bit
var lValue = (UInt16)(value & 0xFFFF); // 하위 16 Bit
return new ushort[] { hValue, lValue };
}
public bool WriteValue(UInt16[] values) public bool WriteValue(UInt16[] values)
{ {
if (IsOpen == false) if (IsOpen == false)
@@ -77,5 +70,11 @@ namespace vmsnet
} }
} }
UInt16[] splitI32(Int32 value)
{
var hValue = (UInt16)(value >> 16); // 상위 16 Bit
var lValue = (UInt16)(value & 0xFFFF); // 하위 16 Bit
return new ushort[] { hValue, lValue };
}
} }
} }

View File

@@ -1589,12 +1589,12 @@ namespace vmsnet
} }
} }
private void DispCtrl1_OnAlamChangeL(int ch, COMM.EALAMRAISETYPE ison, COMM.EALAMTYPE atype, string AM, float value, float maxvalue, float minvalue) private void DispCtrl1_OnAlamChangeL(int ch, COMM.EALAMRAISETYPE ison, COMM.EALAMTYPE atype, string AM, float value, float maxvalue, float minvalue, string remark)
{ {
TimeSpan ts = DateTime.Now - PUB.StartupTime; TimeSpan ts = DateTime.Now - PUB.StartupTime;
if (ts.TotalSeconds < PUB.CONFIG.Startup_DelayTime_Alam) return; if (ts.TotalSeconds < PUB.CONFIG.Startup_DelayTime_Alam) return;
bool rlt = PUB.Alarm.InsertData(DateTime.Now, ch, ison, value, atype, maxvalue, minvalue, AM, ""); bool rlt = PUB.Alarm.InsertData(DateTime.Now, ch, ison, value, atype, maxvalue, minvalue, AM, remark);
PUB.log.Add(AR.Log.ETYPE.NORMAL, "알람이 발생되었습니다(ch=" + ch.ToString() + ",type=" + ison.ToString() + ", value=" + value.ToString() + ", min=:" + minvalue.ToString() + ",max=" + maxvalue.ToString() + ",atype=" + atype.ToString() + " ,am=" + AM); PUB.log.Add(AR.Log.ETYPE.NORMAL, "알람이 발생되었습니다(ch=" + ch.ToString() + ",type=" + ison.ToString() + ", value=" + value.ToString() + ", min=:" + minvalue.ToString() + ",max=" + maxvalue.ToString() + ",atype=" + atype.ToString() + " ,am=" + AM);
} }
@@ -2249,7 +2249,7 @@ namespace vmsnet
if (PUB.indicator != null && PUB.indicator.IsOpen) if (PUB.indicator != null && PUB.indicator.IsOpen)
{ {
this.lbINDI.ForeColor = Color.green; this.lbINDI.ForeColor = Color.Green;
} }
else if (PUB.CONFIG.indicator_port.isEmpty()) else if (PUB.CONFIG.indicator_port.isEmpty())
{ {

View File

@@ -72,9 +72,9 @@ namespace vmsnet
this.lb_status, this.lb_status,
this.lb_lasttime, this.lb_lasttime,
this.lb_alarm}); this.lb_alarm});
this.StatusStrip1.Location = new System.Drawing.Point(0, 750); this.StatusStrip1.Location = new System.Drawing.Point(0, 744);
this.StatusStrip1.Name = "StatusStrip1"; this.StatusStrip1.Name = "StatusStrip1";
this.StatusStrip1.Size = new System.Drawing.Size(929, 26); this.StatusStrip1.Size = new System.Drawing.Size(929, 32);
this.StatusStrip1.TabIndex = 1; this.StatusStrip1.TabIndex = 1;
this.StatusStrip1.Text = "StatusStrip1"; this.StatusStrip1.Text = "StatusStrip1";
// //
@@ -83,7 +83,7 @@ namespace vmsnet
this.lb_status.Font = new System.Drawing.Font("맑은 고딕", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(129))); this.lb_status.Font = new System.Drawing.Font("맑은 고딕", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(129)));
this.lb_status.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(64)))), ((int)(((byte)(0))))); this.lb_status.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(192)))), ((int)(((byte)(64)))), ((int)(((byte)(0)))));
this.lb_status.Name = "lb_status"; this.lb_status.Name = "lb_status";
this.lb_status.Size = new System.Drawing.Size(130, 20); this.lb_status.Size = new System.Drawing.Size(155, 25);
this.lb_status.Text = "<SUBWINDOW>"; this.lb_status.Text = "<SUBWINDOW>";
// //
// lb_lasttime // lb_lasttime
@@ -91,14 +91,14 @@ namespace vmsnet
this.lb_lasttime.Font = new System.Drawing.Font("맑은 고딕", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(129))); this.lb_lasttime.Font = new System.Drawing.Font("맑은 고딕", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(129)));
this.lb_lasttime.ForeColor = System.Drawing.Color.Gray; this.lb_lasttime.ForeColor = System.Drawing.Color.Gray;
this.lb_lasttime.Name = "lb_lasttime"; this.lb_lasttime.Name = "lb_lasttime";
this.lb_lasttime.Size = new System.Drawing.Size(103, 20); this.lb_lasttime.Size = new System.Drawing.Size(123, 25);
this.lb_lasttime.Text = "<LASTTIME>"; this.lb_lasttime.Text = "<LASTTIME>";
// //
// lb_alarm // lb_alarm
// //
this.lb_alarm.ForeColor = System.Drawing.Color.Silver; this.lb_alarm.ForeColor = System.Drawing.Color.Silver;
this.lb_alarm.Name = "lb_alarm"; this.lb_alarm.Name = "lb_alarm";
this.lb_alarm.Size = new System.Drawing.Size(24, 20); this.lb_alarm.Size = new System.Drawing.Size(30, 25);
this.lb_alarm.Text = "●"; this.lb_alarm.Text = "●";
// //
// Timer1 // Timer1
@@ -151,7 +151,7 @@ namespace vmsnet
this.TableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 35F)); this.TableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 35F));
this.TableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); this.TableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.TableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); this.TableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
this.TableLayoutPanel1.Size = new System.Drawing.Size(929, 706); this.TableLayoutPanel1.Size = new System.Drawing.Size(929, 700);
this.TableLayoutPanel1.TabIndex = 6; this.TableLayoutPanel1.TabIndex = 6;
// //
// panel1 // panel1
@@ -172,7 +172,7 @@ namespace vmsnet
this.cmb_tanks.FormattingEnabled = true; this.cmb_tanks.FormattingEnabled = true;
this.cmb_tanks.Location = new System.Drawing.Point(0, 0); this.cmb_tanks.Location = new System.Drawing.Point(0, 0);
this.cmb_tanks.Name = "cmb_tanks"; this.cmb_tanks.Name = "cmb_tanks";
this.cmb_tanks.Size = new System.Drawing.Size(341, 38); this.cmb_tanks.Size = new System.Drawing.Size(341, 45);
this.cmb_tanks.TabIndex = 5; this.cmb_tanks.TabIndex = 5;
this.cmb_tanks.SelectedIndexChanged += new System.EventHandler(this.cmb_group_SelectedIndexChanged); this.cmb_tanks.SelectedIndexChanged += new System.EventHandler(this.cmb_group_SelectedIndexChanged);
// //
@@ -229,7 +229,7 @@ namespace vmsnet
this.bt_fullscreen.Image = ((System.Drawing.Image)(resources.GetObject("bt_fullscreen.Image"))); this.bt_fullscreen.Image = ((System.Drawing.Image)(resources.GetObject("bt_fullscreen.Image")));
this.bt_fullscreen.ImageTransparentColor = System.Drawing.Color.Magenta; this.bt_fullscreen.ImageTransparentColor = System.Drawing.Color.Magenta;
this.bt_fullscreen.Name = "bt_fullscreen"; this.bt_fullscreen.Name = "bt_fullscreen";
this.bt_fullscreen.Size = new System.Drawing.Size(97, 41); this.bt_fullscreen.Size = new System.Drawing.Size(112, 39);
this.bt_fullscreen.Text = "개별보기"; this.bt_fullscreen.Text = "개별보기";
this.bt_fullscreen.Click += new System.EventHandler(this.bt_fullscreen_Click); this.bt_fullscreen.Click += new System.EventHandler(this.bt_fullscreen_Click);
// //
@@ -239,7 +239,7 @@ namespace vmsnet
this.bt_tviewr.Image = ((System.Drawing.Image)(resources.GetObject("bt_tviewr.Image"))); this.bt_tviewr.Image = ((System.Drawing.Image)(resources.GetObject("bt_tviewr.Image")));
this.bt_tviewr.ImageTransparentColor = System.Drawing.Color.Magenta; this.bt_tviewr.ImageTransparentColor = System.Drawing.Color.Magenta;
this.bt_tviewr.Name = "bt_tviewr"; this.bt_tviewr.Name = "bt_tviewr";
this.bt_tviewr.Size = new System.Drawing.Size(152, 41); this.bt_tviewr.Size = new System.Drawing.Size(177, 39);
this.bt_tviewr.Text = "실시간트렌드(F1)"; this.bt_tviewr.Text = "실시간트렌드(F1)";
this.bt_tviewr.Click += new System.EventHandler(this.bt_tviewr_Click); this.bt_tviewr.Click += new System.EventHandler(this.bt_tviewr_Click);
// //
@@ -249,7 +249,7 @@ namespace vmsnet
this.bt_save.Image = ((System.Drawing.Image)(resources.GetObject("bt_save.Image"))); this.bt_save.Image = ((System.Drawing.Image)(resources.GetObject("bt_save.Image")));
this.bt_save.ImageTransparentColor = System.Drawing.Color.Magenta; this.bt_save.ImageTransparentColor = System.Drawing.Color.Magenta;
this.bt_save.Name = "bt_save"; this.bt_save.Name = "bt_save";
this.bt_save.Size = new System.Drawing.Size(92, 41); this.bt_save.Size = new System.Drawing.Size(105, 39);
this.bt_save.Text = "저장(F5)"; this.bt_save.Text = "저장(F5)";
this.bt_save.Click += new System.EventHandler(this.bt_save_Click); this.bt_save.Click += new System.EventHandler(this.bt_save_Click);
// //
@@ -263,7 +263,7 @@ namespace vmsnet
this.ToolStripButton2.Image = ((System.Drawing.Image)(resources.GetObject("ToolStripButton2.Image"))); this.ToolStripButton2.Image = ((System.Drawing.Image)(resources.GetObject("ToolStripButton2.Image")));
this.ToolStripButton2.ImageTransparentColor = System.Drawing.Color.Magenta; this.ToolStripButton2.ImageTransparentColor = System.Drawing.Color.Magenta;
this.ToolStripButton2.Name = "ToolStripButton2"; this.ToolStripButton2.Name = "ToolStripButton2";
this.ToolStripButton2.Size = new System.Drawing.Size(122, 41); this.ToolStripButton2.Size = new System.Drawing.Size(141, 39);
this.ToolStripButton2.Text = "소리끄기(F2)"; this.ToolStripButton2.Text = "소리끄기(F2)";
this.ToolStripButton2.Click += new System.EventHandler(this.ToolStripButton2_Click); this.ToolStripButton2.Click += new System.EventHandler(this.ToolStripButton2_Click);
// //
@@ -279,7 +279,7 @@ namespace vmsnet
// //
// Frm_Sub // Frm_Sub
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 18F); this.AutoScaleDimensions = new System.Drawing.SizeF(10F, 22F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(929, 776); this.ClientSize = new System.Drawing.Size(929, 776);
this.Controls.Add(this.TableLayoutPanel1); this.Controls.Add(this.TableLayoutPanel1);

View File

@@ -844,13 +844,13 @@ namespace vmsnet
//Me.bt_window.Text = Me.DispCtrl1.WINDOW.이름 & "(윈도우속성)" //Me.bt_window.Text = Me.DispCtrl1.WINDOW.이름 & "(윈도우속성)"
} }
private void DispCtrl1_OnAlamChangeL(int ch, COMM.EALAMRAISETYPE raisetype, COMM.EALAMTYPE atype, string AM, float value, float maxvalue, float minvalue) private void DispCtrl1_OnAlamChangeL(int ch, COMM.EALAMRAISETYPE raisetype, COMM.EALAMTYPE atype, string AM, float value, float maxvalue, float minvalue, string remark)
{ {
TimeSpan ts = DateTime.Now - PUB.StartupTime; TimeSpan ts = DateTime.Now - PUB.StartupTime;
if (ts.TotalSeconds < 7) return; if (ts.TotalSeconds < PUB.CONFIG.Startup_DelayTime_Alam) return;
bool rlt = PUB.Alarm.InsertData(DateTime.Now, ch, raisetype, value, atype, maxvalue, minvalue, AM, ""); bool rlt = PUB.Alarm.InsertData(DateTime.Now, ch, raisetype, value, atype, maxvalue, minvalue, AM, remark);
PUB.log.Add(AR.Log.ETYPE.NORMAL, "알람이 발생되었습니다(ch=" + ch.ToString() + ",type=" + raisetype.ToString() + ", value=" + value.ToString() + ", min=:" + minvalue.ToString() + ",max=" + maxvalue.ToString() + ",atype=" + atype.ToString() + " ,am=" + AM); PUB.log.Add(AR.Log.ETYPE.NORMAL, "알람이 발생되었습니다(ch=" + ch.ToString() + ",type=" + raisetype.ToString() + ", value=" + value.ToString() + ", min=:" + minvalue.ToString() + ",max=" + maxvalue.ToString() + ",atype=" + atype.ToString() + " ,am=" + AM + " ,remark=" + remark);
} }
public void DispCtrl1_OnSetNullbalance(HMI.CGROUP grp, float value) public void DispCtrl1_OnSetNullbalance(HMI.CGROUP grp, float value)

View File

@@ -488,190 +488,191 @@
<data name="bt_fullscreen.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="bt_fullscreen.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
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
C5OMes1Y4DvuAAAAAElFTkSuQmCC bA3j8tWrN2jfeqf1/AKTjHrN6L0l5gAAAABJRU5ErkJggg==
</value> </value>
</data> </data>
<data name="bt_tviewr.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="bt_tviewr.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
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
RU5ErkJggg== JIfPNiDJsoENpwwJ/BbUd+E/j4JoCBPL9rMFEhQKxVt/ATRX8TO8ZzhJn31RwgAAAABJRU5ErkJggg==
</value> </value>
</data> </data>
<data name="bt_save.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="bt_save.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
YQUAAAAJcEhZcwAAEnQAABJ0Ad5mH3gAAARcSURBVFhH7ZVJU2NVFMepcu9HcNGSOSEDgRBCRgIxgNA0 YQUAAAAJcEhZcwAAFiUAABYlAUlSJPAAAARxSURBVFhH7ZdLU5tVGMffGfd+BBeV3BNyIRBCSEIuJAYw
YUiA7nbt8BncuVE/gOzc6Lq7yi9gpx1K7TA0YFpdWW0SZodVqDqe/333vPfSL9V2UY1uvFW/OsO993/+ NCUEEgLFta2fwZ0b9QPIzo2u2xm/gE21jtpAKFCqrhzMmwsJWlfJzN95znvOe81ohym6MTO/eS7nOc//
vCSPgf+XrNrmW1uFyWnKM4jVjbs0XZpV+RcPHlyJX//4k+LxhKmJWKms1kqlNwN6rLVw4MOPPqa333lP z5sQBkn6/8Vftd33DtKZHFKZHChW6/vI5VdZ/tWjR9fi1z9eIhyOqDsplstbtXz+XY9ZX6KBjz/5FO/f
IQaQ/9XtXplKZcXUhL6Y0GOtlS9MUXX9rhpc0xEGaht36OeLC/rl4lxHO+c9eSgcMZE706UZ1rujNGus +4AhDFD+52h0bcrlirqT9gsTZn0plV5GdWefCdd4JAO1+l38fHWFX66GPOoZGnKfP6Ai7uTyK6jt3GU7
CSOYpcdaK5cv0tr6barWbtMaIwZQN8/P6Mfzc0XzDPFM9Zpn0ufIOQYXim8oUDd5b2q6rHQF6GGWHmut a/V9ZoS0zPrSUiqL7Z09VGt72K7tqQaoPh8O8Hw4ZJwPKA5Y73wg+gM8HwyYcDr7DoPq8+EQy7kC2yug
bH6SVqobtLrGcBQDK9VNenx6+kLYDUhvcqrMeptalyNrZ3OTTgOZbIGWV9c1NdMA6sbxMXNC2ycn1GC2 faRl1peSqQwq1Tq2tuvYqtZVA5XqLp5dXr4SegOil1kuYKu6y/fust3JpYzVQCKZxubWDqemGqC62euh
uVY5+rpunBz3GECNfqFYsukyKzXCLD3WWulsnpaW10zEAPLvjo7oewaxh2Mjyp7dgJzB5720XO3RTmdz 2evjsN9Hs9/HYa+n5NTndbPfMxigmvrpbF63dweblRpIy6wvxZMpbGxuqwgDlH/f7eKHbpdFAz0lijO9
TgOpdI4Wl1YUNxkxgPrrTkfxTZvptM3a3ke0GzD6bfW4RVe0U5k+BsZTGZq/WaH5xQotMGIAPGy3qN5q ATFD7/fGZtWwO55cshqIxZdQ2qgwbm9UVANUf9vpMJ7IHTzpyGqt71PUG1D6MnvcYq/YHUtMMLAQS6B4
U50FhYcqcl/gfbsB7IN0psCaSz3aqYmM00ByPE1z84s0t8DM3zLfBeDTe/foy1brSqTSWUPXRjKVdhpI u4xiqYz1Ulk1QDyW22i0ZTRkjccstjXassEAnRPxRBrF0oZhd2wxYTUQXYhjrVjC2noJa8U76ncB8fmD
JCdoZm6BZmYXqIyoQZ7kp4MnNM4XAWqISA+5cca+b90pz84bWqw9wzlm6bHWGh1LUak894LM/kP+/P3R B/i63b4WsXhS2asjGotbDUSii1hZW8fK6joKFDmUR2MJ0BNaiMUZVNMS0aNcmdGfa3cKq0Vl1yrtL4K0
sXGngZFEkoqlsuKTz+/T4dHlS2Xrs/tU5JcSGEmMOQ0MjyT4y8P/MPh3e3DUpYNO17x8oHm2tvft+4ed zPrS3HwM+cLaK7L6D/mknpbPzS9YDcxGosjmC4zPvnyIs+74tXLwxUNkcwXGbGTeamBmNoJ0NodUNo/T
Z3JdQx9glh5rrVh8lLL8isQb8clunX4CexqdP9G5inbkvNyRyJhaDLQxIxYfcRqIxuI0kckrDtjxvgZP 7ginnZF6+ZRjrvV9/flZx5TzmvYTpGXWl0LhOSRTWdA34otWAz8Rxxyev+A5i3rEvLiju6vuajXYbtII
wsoNpO7FOmfVgnFP6fMLLzocdxoIR2KU5N8nvrX77Ut6DPgS4n7bEJIaUZ1BRM+GGo47OK8i+si7NA59 hWetBoKhMBYTKcZpZ4wTDj0JLVcQtRFtTqsFyj22P5lCcCZsNeAPhBBdVD61J/IYz4iOEk9kZZGoKbIZ
JhwddhoIhaP880gpmjv1Xvjx9cR+PG9PI/qYpcdaK8hvsZHRMcUeO99rdWmXXSPfbUmNyLXqGXt7OIM9 Lsb6HCZOd2ieRepTPsIC7V9MwB+csRrw+YOIRGOM86OGkZYpTuLvzjhiP2mZ9SWvP4DZuXnGsTzGcXuE
fV766qza02c54pcW519AaCjiNBAIDfGXY1SBgTv6InLEHVsu+0bPvif7Vl9ALfqYpcdayx8IUZi/iJHY ljxieastaopjFltt5eyYZuiMz4s+m2VnfLY9Bv2mhSPz8E0HrAY8vmnQB5EgwSN+kXKKR7pcnCs9/Zk4
MB1u1+kANDQ6P9S1ityTc/aIPYmqJ+eZSJT1GX8w5DTg9QfVZzPEbP/WpYbi0gQ9o2/lcs6eW7VxTs6j 1/oCqsV+0jLrS26PD/5QGIHQDM4OGzglmhyen/GaxcOGOqePdCYi6+nuBYJhhtvrsxpwur3svZn2B3H4
D/1QJEreQLCfAT8FhsKKxlMtxvGRxKcwYvSlB/FHiGpf9np71v2uevTA6ws4Dbi9PvLxx+Bjd+qiwhDr 2whNxliFekpfy8WcPtdqZU7MU5/2+wJBOD3eSQbc8Ez7Gc0LvuxihKciXpARpS96tPwpRXYuzow97f6I
V//Q0++PcebSPAttXzBImKXHWsvl8ZLH5ycPP4nT91+5Frz+gJqBWXqstQbdHnKxM5fX2/fyy8CtBw+6 PXrC6fJYDdidLrg8Prg8XuUiF9VyY/2joT8ZZWasztJul9cL0jLrSzaHEw6XGw63G5cfvnEjON0epkFa
+xh43eVmZx6Ckd8/ePVacOGPZDBLj7XWjcHBLWyAb98duBZE/4bL/ZUeq9ZrTIzJMbf+JTDLw2D2f7kG Zn1pyu6AzemCzem0XHxd2LnwlH2CgbdtdtgcDpCR3z9680aw0Q9pd4C0zPrSrampAzogvrsv3Qhi/y2b
Bv4GtT2Ldl7X4kgAAAAASUVORK5CYII= /Ru99lv0x5D+N5Ek6c6/BGk5uPZ/+/oLtT2Ldn0m2N0AAAAASUVORK5CYII=
</value> </value>
</data> </data>
<data name="ToolStripButton2.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="ToolStripButton2.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>
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
KOQU/Q+Qx3HtqiuXvQAAAABJRU5ErkJggg==
</value> </value>
</data> </data>
<metadata name="ds1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <metadata name="ds1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">

View File

@@ -197,7 +197,7 @@ namespace vmsnet.HMI
public delegate void OnSetNBHandler(CGROUP grp, Single value); public delegate void OnSetNBHandler(CGROUP grp, Single value);
public event OnAlamChangeHHandler OnAlamChange; //알람이 변경되었을경우(활성/비활성) public event OnAlamChangeHHandler OnAlamChange; //알람이 변경되었을경우(활성/비활성)
public delegate void OnAlamChangeHHandler(int ch, COMM.EALAMRAISETYPE raisetype, COMM.EALAMTYPE atype, String AM, Single value, Single maxvalue, Single minvalue); public delegate void OnAlamChangeHHandler(int ch, COMM.EALAMRAISETYPE raisetype, COMM.EALAMTYPE atype, String AM, Single value, Single maxvalue, Single minvalue, string remark);
public event OnRaiseAlamChangeHHandler RaiseAlarm; //알람이 변경되었을경우(활성/비활성) public event OnRaiseAlamChangeHHandler RaiseAlarm; //알람이 변경되었을경우(활성/비활성)
public delegate void OnRaiseAlamChangeHHandler(Boolean On); public delegate void OnRaiseAlamChangeHHandler(Boolean On);
@@ -615,7 +615,7 @@ namespace vmsnet.HMI
Item.alaml = grp.LOW; Item.alaml = grp.LOW;
Item.aalamh = grp.UP; Item.aalamh = grp.UP;
Item.aalaml = grp.UP; Item.aalaml = grp.UP;
Item.alamv = -999; /* 작성자: 이재웅, 작성일: 2025-06-11, 작성내용: 알람발생 원인으로 의심 -> 'Item.alamv = -999' 주석해제 */ //Item.alamv = -999; /* 작성자: 이재웅, 작성일: 2025-06-11, 작성내용: 알람발생 원인으로 의심 -> 'Item.alamv = -999' 주석해제 했다가 다시 원복 */
break; break;
case COMM.EALAMTYPE.: case COMM.EALAMTYPE.:
Item.alamh = -999; Item.alamh = -999;
@@ -669,6 +669,7 @@ namespace vmsnet.HMI
//값의 저장소가 아에없다면? //값의 저장소가 아에없다면?
//Boolean OverDATA = false; //Boolean OverDATA = false;
var alarmRemark = string.Empty;
if (this.Values == null) if (this.Values == null)
{ {
Item.value2 = 0; Item.value2 = 0;
@@ -728,7 +729,7 @@ namespace vmsnet.HMI
if (TimeStr != "" && TimeStr != "Not USE" && Item._p_onalamover == false) if (TimeStr != "" && TimeStr != "Not USE" && Item._p_onalamover == false)
{ {
String alamtimes = DateTime.Parse(TimeStr).ToString("yy-MM-dd HH:mm:ss"); String alamtimes = DateTime.Parse(TimeStr).ToString("yy-MM-dd HH:mm:ss");
OnAlamChange(Item.idx, COMM.EALAMRAISETYPE.OVER_ON, Item., "--", Item.CurValue, Item.alamh, Item.alaml); OnAlamChange(Item.idx, COMM.EALAMRAISETYPE.OVER_ON, Item., "--", Item.CurValue, Item.alamh, Item.alaml, "over 32000");
Item._p_onalamover = true; Item._p_onalamover = true;
} }
Item.CurValue = 0f; Item.CurValue = 0f;
@@ -744,7 +745,7 @@ namespace vmsnet.HMI
if (TimeStr != "" && TimeStr != "Not USE" && Item._p_onalamover == true) if (TimeStr != "" && TimeStr != "Not USE" && Item._p_onalamover == true)
{ {
String alamtimes = DateTime.Parse(TimeStr).ToString("yy-MM-dd HH:mm:ss"); String alamtimes = DateTime.Parse(TimeStr).ToString("yy-MM-dd HH:mm:ss");
OnAlamChange(Item.idx, COMM.EALAMRAISETYPE.OVER_OFF, Item., "--", Item.CurValue, Item.alamh, Item.alaml); OnAlamChange(Item.idx, COMM.EALAMRAISETYPE.OVER_OFF, Item., "--", Item.CurValue, Item.alamh, Item.alaml, "");
Item._p_onalamover = false; Item._p_onalamover = false;
} }
} }
@@ -785,8 +786,9 @@ namespace vmsnet.HMI
case COMM.EALAMTYPE.: case COMM.EALAMTYPE.:
if (grp.AlarmType == "AUTO") if (grp.AlarmType == "AUTO")
{ {
/* 작성자: 이재웅, 작성일: 2025-06-11, 작성내용: 알람발생 원인으로 의심 -> '알람타입:그룹설정을따름' 일때 'Item.alamv == -999' 주석해제 */ //if (Item.alamv == -999) Item.alamv = Item.CurValue;
if (Item.alamv == -999) Item.alamv = Item.CurValue; /* 작성자: 이재웅, 작성일: 2025-06-17, 작성내용: 'Item.alamv == 0' OR조건 추가 */
if (Item.alamv == -999 || Item.alamv == 0) Item.alamv = Item.CurValue;
Item. = "AUTO"; Item. = "AUTO";
if (Item.CurValue > Item.alamv) //큰값이 있을경우 상한선을 확인한다. if (Item.CurValue > Item.alamv) //큰값이 있을경우 상한선을 확인한다.
@@ -797,6 +799,7 @@ namespace vmsnet.HMI
Item.onalamh = true; Item.onalamh = true;
Item.onalaml = false; Item.onalaml = false;
BackColor = Color.Orange; //BackColor0 = Color.LightPink; BackColor = Color.Orange; //BackColor0 = Color.LightPink;
alarmRemark = $"ref({Item.alamv})";
} }
} }
else if (Item.CurValue < Item.alamv) else if (Item.CurValue < Item.alamv)
@@ -807,6 +810,7 @@ namespace vmsnet.HMI
Item.onalamh = false; Item.onalamh = false;
Item.onalaml = true; Item.onalaml = true;
BackColor = Color.SkyBlue; //BackColor0 = Color.LightBlue; BackColor = Color.SkyBlue; //BackColor0 = Color.LightBlue;
alarmRemark = $"ref({Item.alamv})";
} }
} }
@@ -819,12 +823,14 @@ namespace vmsnet.HMI
Item.onalamh = true; Item.onalamh = true;
Item.onalaml = false; Item.onalaml = false;
BackColor = Color.Orange;// BackColor0 = Color.LightPink; BackColor = Color.Orange;// BackColor0 = Color.LightPink;
alarmRemark = $"ref({Item.alamh})";
} }
else if (Item.CurValue < Item.alaml) else if (Item.CurValue < Item.alaml)
{ {
Item.onalamh = false; Item.onalamh = false;
Item.onalaml = true; Item.onalaml = true;
BackColor = Color.SkyBlue; //BackColor0 = Color.LightBlue; BackColor = Color.SkyBlue; //BackColor0 = Color.LightBlue;
alarmRemark = $"ref({Item.alaml})";
} }
} }
else else
@@ -841,18 +847,22 @@ namespace vmsnet.HMI
Item.onalamh = true; Item.onalamh = true;
Item.onalaml = false; Item.onalaml = false;
BackColor = Color.Orange; //BackColor0 = Color.LightPink; BackColor = Color.Orange; //BackColor0 = Color.LightPink;
alarmRemark = $"ref({Item.alamh})";
} }
else if (Item.CurValue < Item.alaml) else if (Item.CurValue < Item.alaml)
{ {
Item.onalamh = false; Item.onalamh = false;
Item.onalaml = true; Item.onalaml = true;
BackColor = Color.SkyBlue;// BackColor0 = Color.LightBlue; BackColor = Color.SkyBlue;// BackColor0 = Color.LightBlue;
alarmRemark = $"ref({Item.alaml})";
} }
break; break;
case COMM.EALAMTYPE.: case COMM.EALAMTYPE.:
Item. = "AUTO"; Item. = "AUTO";
if (Item.alamv == -999) Item.alamv = Item.CurValue; //if (Item.alamv == -999) Item.alamv = Item.CurValue; // 이전 코드
/* 작성자: 이재웅, 작성일: 2025-06-17, 작성내용: 'Item.alamv == 0' OR조건 추가 */
if (Item.alamv == -999 || Item.alamv == 0) Item.alamv = Item.CurValue;
if (Item.CurValue > Item.alamv) //큰값이 있을경우 상한선을 확인한다. if (Item.CurValue > Item.alamv) //큰값이 있을경우 상한선을 확인한다.
{ {
@@ -862,6 +872,7 @@ namespace vmsnet.HMI
Item.onalamh = true; Item.onalamh = true;
Item.onalaml = false; Item.onalaml = false;
BackColor = Color.Orange; //BackColor0 = Color.LightPink; BackColor = Color.Orange; //BackColor0 = Color.LightPink;
alarmRemark = $"ref({Item.alamv})";
} }
} }
else if (Item.CurValue < Item.alamv) else if (Item.CurValue < Item.alamv)
@@ -872,6 +883,7 @@ namespace vmsnet.HMI
Item.onalamh = false; Item.onalamh = false;
Item.onalaml = true; Item.onalaml = true;
BackColor = Color.SkyBlue; //BackColor0 = Color.LightBlue; BackColor = Color.SkyBlue; //BackColor0 = Color.LightBlue;
alarmRemark = $"ref({Item.alamv})";
} }
} }
break; break;
@@ -883,9 +895,10 @@ namespace vmsnet.HMI
if (Item. && init == true && (Item.onalaml != Item._p_onalaml || Item._p_onalamh != Item.onalamh)) //이전과 알람상태가 변경된경우다. if (Item. && init == true && (Item.onalaml != Item._p_onalaml || Item._p_onalamh != Item.onalamh)) //이전과 알람상태가 변경된경우다.
{ {
String alamtimes; String alamtimes = "";
if (TimeStr != "" && TimeStr != "Not USE") alamtimes = DateTime.Parse(TimeStr).ToString("yy-MM-dd HH:mm:ss"); if (TimeStr != "" && TimeStr != "Not USE")
alamtimes = DateTime.Parse(TimeStr).ToString("yy-MM-dd HH:mm:ss");
else alamtimes = ""; else alamtimes = "";
Single AH, AL; Single AH, AL;
@@ -901,23 +914,22 @@ namespace vmsnet.HMI
} }
if (Item.onalamh && !Item._p_onalamh) if (Item.onalamh && !Item._p_onalamh)
{ {
OnAlamChange(Item.idx, COMM.EALAMRAISETYPE.HIGH_ON, Item., Item., Item.CurValue, AH, AL, alarmRemark);
OnAlamChange(Item.idx, COMM.EALAMRAISETYPE.HIGH_ON, Item., Item., Item.CurValue, AH, AL);
Item._p_onalamh = true; Item._p_onalamh = true;
} }
else if (Item.onalaml && !Item._p_onalaml) else if (Item.onalaml && !Item._p_onalaml)
{ {
OnAlamChange(Item.idx, COMM.EALAMRAISETYPE.LOW_ON, Item., Item., Item.CurValue, AH, AL); OnAlamChange(Item.idx, COMM.EALAMRAISETYPE.LOW_ON, Item., Item., Item.CurValue, AH, AL, alarmRemark);
Item._p_onalaml = true; Item._p_onalaml = true;
} }
else if (!Item.onalamh && Item._p_onalamh) else if (!Item.onalamh && Item._p_onalamh)
{ {
OnAlamChange(Item.idx, COMM.EALAMRAISETYPE.HIGH_OFF, Item., Item., Item.CurValue, AH, AL); OnAlamChange(Item.idx, COMM.EALAMRAISETYPE.HIGH_OFF, Item., Item., Item.CurValue, AH, AL, "");
Item._p_onalamh = false; Item._p_onalamh = false;
} }
else if (!Item.onalaml && Item._p_onalaml) else if (!Item.onalaml && Item._p_onalaml)
{ {
OnAlamChange(Item.idx, COMM.EALAMRAISETYPE.LOW_OFF, Item., Item., Item.CurValue, AH, AL); OnAlamChange(Item.idx, COMM.EALAMRAISETYPE.LOW_OFF, Item., Item., Item.CurValue, AH, AL, "");
Item._p_onalamh = false; Item._p_onalamh = false;
} }
} }
@@ -1338,12 +1350,15 @@ namespace vmsnet.HMI
Single imgheight = 30; Single imgheight = 30;
if (!(grp.nbh == 0 && grp.nbl == 0)) if (!(grp.nbh == 0 && grp.nbl == 0))
{ {
if (Math.Abs(nullvalue) > grp.nbl) //if (Math.Abs(nullvalue) > grp.nbl) // a2영역보다 크다면
/* 작성자: 이재웅, 작성일: 2025-06-17, 작성내용: 'a2영역 절대값보다 클 경우'로 변경 */
if (Math.Abs(nullvalue) > Math.Abs(grp.nbl)) // a2영역 절대값보다 크다면
{ {
grp._nbalam_l = true; //a2 on grp._nbalam_l = true; //a2 on
if (!grp._pre_nbalam_l) if (!grp._pre_nbalam_l)
{ {
if (grp.AlarmType != "STOP") OnAlamChange(grp.IDX, COMM.EALAMRAISETYPE.A2_ON, COMM.EALAMTYPE., "NB", (Single)nullvalue, (Single)grp.nbl, (Single)grp.nbl); if (grp.AlarmType != "STOP") OnAlamChange(grp.IDX, COMM.EALAMRAISETYPE.A2_ON, COMM.EALAMTYPE., "NB",
(Single)nullvalue, (Single)grp.nbl, (Single)grp.nbl, $"> {grp.nbl}");
grp._pre_nbalam_l = true; grp._pre_nbalam_l = true;
A2 = false; A2 = false;
blink2 = 0; blink2 = 0;
@@ -1376,18 +1391,21 @@ namespace vmsnet.HMI
if (grp._pre_nbalam_l) //이전에 a2알람이 켜져잇엇다면 알람을 끈다. if (grp._pre_nbalam_l) //이전에 a2알람이 켜져잇엇다면 알람을 끈다.
{ {
OnAlamChange(grp.IDX, COMM.EALAMRAISETYPE.A2_OFF, COMM.EALAMTYPE., "NB", (Single)nullvalue, (Single)grp.nbl, (Single)grp.nbl); OnAlamChange(grp.IDX, COMM.EALAMRAISETYPE.A2_OFF, COMM.EALAMTYPE., "NB", (Single)nullvalue, (Single)grp.nbl, (Single)grp.nbl, "");
grp._pre_nbalam_l = false; grp._pre_nbalam_l = false;
blink1 = 0; blink1 = 0;
} }
if (Math.Abs(nullvalue) > grp.nbh) //a1영역보다 크다면 //if (Math.Abs(nullvalue) > grp.nbh) // a1영역보다 크다면
/* 작성자: 이재웅, 작성일: 2025-06-17, 작성내용: 'a1영역 절대값보다 클 경우'로 변경 */
if (Math.Abs(nullvalue) > Math.Abs(grp.nbh)) // a1영역 절대값보다 크다면
{ {
grp._nbalam_h = true; grp._nbalam_h = true;
if (!grp._pre_nbalam_h) //이전에 발생안햇다면 if (!grp._pre_nbalam_h) //이전에 발생안햇다면
{ {
if (grp.AlarmType != "STOP") OnAlamChange(grp.IDX, COMM.EALAMRAISETYPE.A1_ON, COMM.EALAMTYPE., "NB", (Single)nullvalue, (Single)grp.nbh, (Single)grp.nbh); if (grp.AlarmType != "STOP") OnAlamChange(grp.IDX, COMM.EALAMRAISETYPE.A1_ON, COMM.EALAMTYPE., "NB",
(Single)nullvalue, (Single)grp.nbh, (Single)grp.nbh, $"> {grp.nbh}");
grp._pre_nbalam_h = true; grp._pre_nbalam_h = true;
blink1 = 0; blink1 = 0;
} }
@@ -1418,7 +1436,7 @@ namespace vmsnet.HMI
grp._nbalam_h = false; //a1 off grp._nbalam_h = false; //a1 off
if (grp._pre_nbalam_h) //이전에 a1알람이 켜져잇엇다면 알람을 끈다. if (grp._pre_nbalam_h) //이전에 a1알람이 켜져잇엇다면 알람을 끈다.
{ {
OnAlamChange(grp.IDX, COMM.EALAMRAISETYPE.A1_OFF, COMM.EALAMTYPE., "NB", (Single)nullvalue, (Single)grp.nbl, (Single)grp.nbl); OnAlamChange(grp.IDX, COMM.EALAMRAISETYPE.A1_OFF, COMM.EALAMTYPE., "NB", (Single)nullvalue, (Single)grp.nbl, (Single)grp.nbl, "");
grp._pre_nbalam_h = false; grp._pre_nbalam_h = false;
} }
blink1 = 0; blink1 = 0;

View File

@@ -1,3 +1,7 @@
..\
1) DesignSetting.xml
2) Setting.xml
..\Database\Config ..\Database\Config
위 경로에 아래 설정파일들이 존재한다. 위 경로에 아래 설정파일들이 존재한다.