168 lines
6.7 KiB
C#
168 lines
6.7 KiB
C#
using Aurora.Api;
|
|
using AuroraPLC;
|
|
using System;
|
|
using System.Threading;
|
|
using ActUtlType64Lib;
|
|
|
|
namespace AuroraMXComponent
|
|
{
|
|
public class MXComponent : PLCNetwork
|
|
{
|
|
private readonly Logger Log = new Logger("PLC MXComponent");
|
|
|
|
private ActUtlType64Class _actUtlType;
|
|
//private DotUtlType64.DotUtlType64 _dotUtlType;
|
|
|
|
private const int _success = 0;
|
|
private bool IsConnected = false;
|
|
|
|
public MXComponent()
|
|
{
|
|
_actUtlType = new ActUtlType64Class();
|
|
//_dotUtlType = new DotUtlType64.DotUtlType64();
|
|
}
|
|
|
|
public override void SetInitParams(int logicalStationNo)
|
|
{
|
|
_actUtlType.ActLogicalStationNumber = logicalStationNo;
|
|
}
|
|
|
|
public override bool OpenToPLC()
|
|
{
|
|
try {
|
|
if (IsConnected) {
|
|
var result = _actUtlType.Close();
|
|
IsConnected = !result.Equals(_success);
|
|
Log.I($"Close: 0x{result:x8} [Hex]");
|
|
Thread.Sleep(500); // 미츠비시 MxComponent 문서의 최소 500 [ms] 간격
|
|
}
|
|
//================================================
|
|
//_actUtlType.ActLogicalStationNumber = stationNo;
|
|
var res = _actUtlType.Open();
|
|
IsConnected = res.Equals(_success);
|
|
Log.I($"Open: 0x{res:x8} [Hex]");
|
|
|
|
if (IsConnected == false) { // 연결 실패
|
|
// 타임 아웃 에러이면, 1회 재시도
|
|
if (res == 0x0180840B) {
|
|
Thread.Sleep(500); // 딜레이를 얼마를 줄까...
|
|
res = _actUtlType.Open();
|
|
IsConnected = res.Equals(_success);
|
|
Log.I($"Open: 2nd trial: 0x{res:x8} [Hex]");
|
|
}
|
|
}
|
|
return IsConnected;
|
|
} catch (Exception ex) {
|
|
Log.E($"Exception from Open: {ex.Message}");
|
|
IsConnected = false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public override bool CloseToPLC()
|
|
{
|
|
try {
|
|
var res = _actUtlType.Close();
|
|
IsConnected = !res.Equals(_success); // 닫기 성공이면, false
|
|
Log.I($"Close: 0x{res:x8} [Hex]");
|
|
Thread.Sleep(500); // 그냥 500 ms 딜레이를 항상 주자
|
|
/*
|
|
if (res == _success) {
|
|
// 문서상, Close 후, 다시 Open 실행할 때까지 최소 500 ms 이상 간격을 두라고 함
|
|
Thread.Sleep(500);
|
|
}
|
|
*/
|
|
} catch (Exception ex) {
|
|
Log.E($"Exception from Close: {ex.Message}");
|
|
// 실패이므로, 연결 flag 도 off 해놓자.
|
|
IsConnected = false;
|
|
return false;
|
|
}
|
|
// Disconnected --> 성공
|
|
return !IsConnected;
|
|
}
|
|
|
|
// Aurora 프로그램이 종료할 때만 호출이 필요함...(필요없을 것 같은데, 삭제 검토)
|
|
public override void Terminate()
|
|
{
|
|
// Aurora 의 비활성화가 완료된 후에 널 포인터로 정리하자..
|
|
// CloseToPLC 에서 널 포인터를 해버리면, 데이터 프로세싱 스레드에서 문제가 발생한다.
|
|
// 프로그램이 완전히 종료할 때 널을 할까?? 흠... 굳이 필요없을 것 같기도 하고....
|
|
_actUtlType = null;
|
|
Log.I("_actUtlType = null");
|
|
}
|
|
|
|
// (out 대신) 지역변수를 생성하지 않기 위해서, ref 로 readData 를 받음
|
|
public override bool ReceiveFromPLC(in string devLabel, int readByteSize, ref short[] readData)
|
|
{
|
|
/*
|
|
// 여긴 굳이 try-catch 가 불필요할 것 같은데..
|
|
//return mdReceive(pathOfChannel, stationNo, devType, startDevNo, ref readByteSize, ref readData).Equals(_success);
|
|
// 일단 그냥 테스트용....
|
|
// 2 바이트 단위로 읽음 (접미사 2 가 없으면 받는변수는 4바이트여서 post processing 필요, 메뉴얼 참고)
|
|
var res = _dotUtlType.ReadDeviceBlock2(ref devLabel, readByteSize, ref readData);
|
|
*/
|
|
int res = -1;
|
|
try {
|
|
res = _actUtlType.ReadDeviceBlock2(devLabel, readByteSize, out readData[0]);
|
|
} catch (Exception ex) {
|
|
#if DEBUG
|
|
//Log.E($"Exception (ReadDeviceBlock2): {ex.StackTrace}; {ex.Message}");
|
|
Log.E($"Exception (ReadDeviceBlock2): {ex.Message}");
|
|
//Console.WriteLine($"Exception is occured: {ex.StackTrace}; {ex.Message}");
|
|
#endif
|
|
}
|
|
return res.Equals(_success);
|
|
}
|
|
|
|
public override bool SendToPLC(in string devLabel, int writeSize, ref short[] writeData)
|
|
{
|
|
int res = -1;
|
|
try {
|
|
res = _actUtlType.WriteDeviceBlock2(devLabel, writeSize, ref writeData[0]);
|
|
} catch (Exception ex) {
|
|
#if DEBUG
|
|
Log.E($"Exception (WriteDeviceBlock2): {ex.Message}");
|
|
#endif
|
|
}
|
|
return res.Equals(_success);
|
|
}
|
|
|
|
//============================================================================
|
|
//-------- data update 스레드 이외에서 사용하는 API ------------//
|
|
//------------ B/W 이외의 장치 수신
|
|
public override bool ReceiveDeviceBlock2FromPLC(in string szDevice, int readSize, ref short[] readData)
|
|
{
|
|
if (IsConnected) {
|
|
// 솔더링: 멀티 스레드로 호출되는데, 문제 없었음
|
|
return ReceiveFromPLC(in szDevice, readSize, ref readData);
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//===============================================
|
|
//-------- MX Component 한정
|
|
// 솔더링 코드에서 비트 입력에 write 하는 경우 때문에 업데이트 스레드에서 잠깐 사용 (코드 수정 후 사용안함)
|
|
public override bool SetDevice2(in string devLabel, short writeData)
|
|
{
|
|
int res = -1;
|
|
try {
|
|
res = _actUtlType.SetDevice2(devLabel, writeData);
|
|
} catch (Exception ex) {
|
|
#if DEBUG
|
|
Log.E($"Exception (SetDevice2): {ex.Message}");
|
|
//Console.WriteLine($"Exception is occured: {ex.StackTrace}; {ex.Message}");
|
|
#endif
|
|
}
|
|
// 실패에 대한 로그를 남겨야 할까??
|
|
if (res.Equals(_success) != true) { // 에러 발생
|
|
Log.E($"SetDevice2 fail: 0x{res:x8} [HEX]");
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|