131 lines
5.8 KiB
C#
131 lines
5.8 KiB
C#
using Aurora.Api;
|
|
using AuroraPLC;
|
|
using System;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace AuroraMelsecNet
|
|
{
|
|
public class MelsecNet : PLCNetwork
|
|
{
|
|
private readonly Logger Log = new Logger("PLC MelsecNet");
|
|
|
|
#region MelsecNet DLL import
|
|
// MelsecNet data link library
|
|
// For C#
|
|
// C:\Windows\SysWOW64 경로에 mdfunc32W.dll 파일 존재함
|
|
// 일단은 mdfunc32 로 검증후, mdfunc32w 검토...mdfunc32w 는 64비트를 의미하는걸까?
|
|
|
|
// Charset: 문자열 관련, 인자로 string 사용안하니, 중요하지 않을 것 같은데..???
|
|
// SetLastError: 에러를 셋 여부로 에러 처리 관련인듯한데..
|
|
|
|
[DllImport("MDFUNC32.DLL", EntryPoint = "mdOpen", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
|
|
private static extern short mdOpen(short chan, short mode, ref long path);
|
|
[DllImport("MDFUNC32.DLL", EntryPoint = "mdClose", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
|
|
private static extern short mdClose(long path);
|
|
[DllImport("MDFUNC32.DLL", EntryPoint = "mdSend", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
|
|
private static extern short mdSend(long path, short stno, short devtyp, short devno, ref short size, ref short data);
|
|
[DllImport("MDFUNC32.DLL", EntryPoint = "mdReceive", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
|
|
private static extern short mdReceive(long path, short stno, short devtyp, short devno, ref short size, ref short data);
|
|
/* // 현재 주기적 배치 Read/Write 방식상, 개별적인 콜이 불필요하여 일단 주석처리..
|
|
[DllImport("MDFUNC32.DLL", EntryPoint = "mdreceiveex", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
|
|
private static extern short mdReceiveEx(int path, short Netno, short Stno, short Devtyp, short DevNo, ref short Size_Renamed, ref short Buf);
|
|
[DllImport("MDFUNC32.DLL", EntryPoint = "mdsendex", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
|
|
private static extern short mdSendEx(int path, short Netno, short Stno, short Devtyp, short DevNo, ref short Size_Renamed, ref short Buf);
|
|
|
|
[DllImport("MDFUNC32.DLL", EntryPoint = "mddevset", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
|
|
private static extern short mdDevSet(int path, short Stno, short Devtyp, short DevNo);
|
|
|
|
[DllImport("MDFUNC32.DLL", EntryPoint = "mddevrst", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
|
|
private static extern short mdDevRst(int path, short Stno, short Devtyp, short DevNo);
|
|
*/
|
|
#endregion
|
|
|
|
|
|
#region 네트워크 설정 관련
|
|
// 채널: 51 for NET-H, 151 for NET-G
|
|
|
|
// owner station: 0xFF
|
|
// remote station: 0x102 .... 0xFF ??
|
|
|
|
#endregion
|
|
|
|
//public short StationNo { get; private set; }
|
|
//public short ChannelNo { get; private set; }
|
|
|
|
// 통신 연결된 path 포인터 (C++ 경우); Melsec 용
|
|
private long _pathForOpenedLine;
|
|
private short _channelNo;
|
|
private short _mode;
|
|
private short _stationNo;
|
|
|
|
private const int _success = 0;
|
|
private bool IsConnected = false;
|
|
|
|
public MelsecNet()
|
|
{
|
|
//_isSimul = isSimul;
|
|
}
|
|
|
|
public override void SetInitParams(short channelNo, short mode, short stationNo)
|
|
{
|
|
_channelNo = channelNo;
|
|
_mode = mode;
|
|
_stationNo = stationNo;
|
|
}
|
|
|
|
public override bool OpenToPLC()
|
|
{
|
|
try { // 장비가 없을 때 에러를 막기 위한 용...
|
|
// Repair 코드에서도 1회 재시도를 하고 있음...
|
|
|
|
// MX Component 와 비슷하게~~~
|
|
if (IsConnected) {
|
|
var result = mdClose(_pathForOpenedLine);
|
|
IsConnected = !result.Equals(_success);
|
|
Log.I($"mdClose: 0x{result:x8} [Hex]");
|
|
//Thread.Sleep(500); // Melsec 문서보고 재검토..
|
|
}
|
|
var res = mdOpen(_channelNo, _mode, ref _pathForOpenedLine);
|
|
IsConnected = res.Equals(_success);
|
|
Log.I($"mdOpen: 0x{res:x8} [Hex]");
|
|
|
|
// 1회 재시도..
|
|
if (IsConnected == false) {
|
|
// TODO : 리턴코드 확인 후...
|
|
}
|
|
return IsConnected;
|
|
} catch (Exception ex) { // 일단 무조건 장비가 없을 경우를 가정한다.
|
|
Log.E($"Exception from mdOpen: {ex.Message}");
|
|
IsConnected = false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public override bool CloseToPLC()
|
|
{
|
|
try {
|
|
var res = mdClose(_pathForOpenedLine);
|
|
IsConnected = !res.Equals(_success); // 닫기 성공이면, false
|
|
Log.I($"mdClose: 0x{res:x8} [Hex]");
|
|
// Need 딜레이 ??
|
|
} catch (Exception ex) {
|
|
Log.E($"Exception from mdClose: {ex.Message}");
|
|
return !IsConnected;
|
|
}
|
|
|
|
return !IsConnected;
|
|
}
|
|
|
|
public override bool ReceiveFromPLC(short devType, short startDevNo, ref short readByteSize, ref short readData)
|
|
{
|
|
// 여긴 굳이 try-catch 가 불필요할듯..
|
|
return mdReceive(_pathForOpenedLine, _stationNo, devType, startDevNo, ref readByteSize, ref readData).Equals(_success);
|
|
}
|
|
|
|
public override bool SendToPLC(short devType, short startDevNo, ref short writtenByteSize, ref short writtenData)
|
|
{
|
|
return mdSend(_pathForOpenedLine, _stationNo, devType, startDevNo, ref writtenByteSize, ref writtenData).Equals(_success);
|
|
}
|
|
}
|
|
}
|