|
|
using System;
|
|
|
using System.IO;
|
|
|
using Mesnac.Equips;
|
|
|
using Mesnac.Equips.BaseInfo;
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
|
namespace Mesnac.Equip.AllenBradley.AB500.Default
|
|
|
{
|
|
|
public class Equip : BaseEquip
|
|
|
{
|
|
|
private IntPtr structToIntPtr<T>(T[] lst)
|
|
|
{
|
|
|
int nSizeOfT = Marshal.SizeOf(typeof(T));
|
|
|
int nSizeOfIntPtr = Marshal.SizeOf(typeof(IntPtr));
|
|
|
IntPtr Result = Marshal.AllocHGlobal(nSizeOfIntPtr * lst.Length);
|
|
|
for (int i = 0; i < lst.Length; i++)
|
|
|
{
|
|
|
Marshal.StructureToPtr(lst[i], (IntPtr)((UInt32)Result + i * nSizeOfIntPtr), true);
|
|
|
}
|
|
|
return Result;
|
|
|
}
|
|
|
private T[] IntPtrTostruct<T>(IntPtr p, T[] lst)
|
|
|
{
|
|
|
int nSizeOfIntPtr = Marshal.SizeOf(typeof(IntPtr));
|
|
|
for (int i = 0; i < lst.Length; i++)
|
|
|
{
|
|
|
T r = (T)Marshal.PtrToStructure((IntPtr)((UInt32)p + i * nSizeOfIntPtr), typeof(T));
|
|
|
lst[i] = r;
|
|
|
}
|
|
|
return lst;
|
|
|
}
|
|
|
private string getDriveNameFileFullName()
|
|
|
{
|
|
|
return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Log", "AB500.DriverName.bin");
|
|
|
}
|
|
|
private void saveDriveName(string name)
|
|
|
{
|
|
|
if (string.IsNullOrWhiteSpace(name))
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
string path = getDriveNameFileFullName();
|
|
|
FileInfo fi = new FileInfo(path);
|
|
|
if (!fi.Directory.Exists)
|
|
|
{
|
|
|
fi.Directory.Create();
|
|
|
}
|
|
|
if (fi.Exists)
|
|
|
{
|
|
|
fi.Delete();
|
|
|
}
|
|
|
System.IO.StreamWriter sw = new System.IO.StreamWriter(fi.FullName, false);
|
|
|
sw.WriteLine(name);
|
|
|
sw.Close();
|
|
|
}
|
|
|
private string getDriveName()
|
|
|
{
|
|
|
string path = getDriveNameFileFullName();
|
|
|
FileInfo fi = new FileInfo(path);
|
|
|
if (!fi.Directory.Exists)
|
|
|
{
|
|
|
fi.Directory.Create();
|
|
|
}
|
|
|
if (!fi.Exists)
|
|
|
{
|
|
|
return string.Empty;
|
|
|
}
|
|
|
System.IO.StreamReader sw = new System.IO.StreamReader(fi.FullName);
|
|
|
string ss = sw.ReadToEnd();
|
|
|
sw.Close();
|
|
|
return ss;
|
|
|
}
|
|
|
public override bool Open()
|
|
|
{
|
|
|
lock (this)
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
this.State = false;
|
|
|
Logger.Instance.Info("DTL_INIT");
|
|
|
int iResult = 0;
|
|
|
uint id = 0;
|
|
|
iResult = DTL32.DTL_INIT(2048);
|
|
|
Logger.Instance.Info("DTL_INIT Result=" + iResult.ToString());
|
|
|
if ((iResult != 0) && (iResult != 39)) // 39已经初始化
|
|
|
{
|
|
|
this.State = false;
|
|
|
return this.State;
|
|
|
}
|
|
|
string driveName = getDriveName();
|
|
|
if (string.IsNullOrWhiteSpace(driveName))
|
|
|
{
|
|
|
Logger.Instance.Info("get szDriverName");
|
|
|
uint drivers = 0;
|
|
|
DTL32.DtlDriver[] dtlDriver = new DTL32.DtlDriver[16];
|
|
|
IntPtr pDriver = structToIntPtr<DTL32.DtlDriver>(dtlDriver);
|
|
|
Logger.Instance.Info("DTL_DRIVER_LIST");
|
|
|
iResult = DTL32.DTL_DRIVER_LIST(pDriver, ref drivers, 1000);
|
|
|
Logger.Instance.Info("DTL_DRIVER_LIST Result=" + iResult.ToString());
|
|
|
dtlDriver = IntPtrTostruct<DTL32.DtlDriver>(pDriver, dtlDriver);
|
|
|
Logger.Instance.Info("IntPtrTostruct");
|
|
|
driveName = new string(dtlDriver[id].szDriverName);
|
|
|
Logger.Instance.Info("szDriverName=" + driveName);
|
|
|
saveDriveName(driveName);
|
|
|
Marshal.FreeHGlobal(pDriver);
|
|
|
Logger.Instance.Info("FreeHGlobal");
|
|
|
if ((iResult != 0))
|
|
|
{
|
|
|
this.State = false;
|
|
|
return this.State;
|
|
|
}
|
|
|
}
|
|
|
iResult = DTL32.DTL_DRIVER_OPEN(id, driveName, 5000);
|
|
|
Logger.Instance.Info("DTL_DRIVER_OPEN Result=" + iResult.ToString());
|
|
|
if ((iResult == 0) || (iResult == 47)) // 47已经连接上
|
|
|
{
|
|
|
this.State = true;
|
|
|
}
|
|
|
return this.State;
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
ICSharpCode.Core.LoggingService.Error(String.Format("打开PLC(AB500)设备连接失败-({0})!", ex.Message));
|
|
|
this.State = false;
|
|
|
return this.State;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
/// <summary>
|
|
|
/// PLC数据读取方法
|
|
|
/// </summary>
|
|
|
/// <param name="block">要读取的块号</param>
|
|
|
/// <param name="start">要读取的起始字</param>
|
|
|
/// <param name="len">要读取的长度,最大255,超过255则不读取</param>
|
|
|
/// <param name="buff"></param>
|
|
|
/// <returns></returns>
|
|
|
public override bool Read(string block, int start, int len, out object[] buff)
|
|
|
{
|
|
|
lock (this)
|
|
|
{
|
|
|
buff = new object[len];
|
|
|
try
|
|
|
{
|
|
|
if (len > 256)
|
|
|
{
|
|
|
for (int i = 0; i < len; i++)
|
|
|
{
|
|
|
buff[i] = 0;
|
|
|
}
|
|
|
base.State = false;
|
|
|
return false;
|
|
|
}
|
|
|
int maxOneLen = 100; //单次允许读取的最大长度,AB500限制为100个字
|
|
|
int count = len / maxOneLen; //要读取的次数
|
|
|
int mod = len % maxOneLen; //剩余的长度
|
|
|
bool flag = true; //保存读取标志
|
|
|
for (int i = 0; i < count; i++)
|
|
|
{
|
|
|
object[] _buff = new object[maxOneLen];
|
|
|
flag = this.ReadByLen(block, start + i * maxOneLen, maxOneLen, out _buff);
|
|
|
if (flag == false)
|
|
|
{
|
|
|
base.State = flag;
|
|
|
return false;
|
|
|
}
|
|
|
for (int k = i * maxOneLen; k < (i + 1) * maxOneLen; k++)
|
|
|
{
|
|
|
buff[k] = _buff[k - i * maxOneLen];
|
|
|
}
|
|
|
}
|
|
|
if (mod > 0)
|
|
|
{
|
|
|
object[] _buff = new object[mod];
|
|
|
flag = this.ReadByLen(block, start + count * maxOneLen, mod, out _buff);
|
|
|
if (flag == false)
|
|
|
{
|
|
|
base.State = flag;
|
|
|
return false;
|
|
|
}
|
|
|
for (int k = count * maxOneLen; k < count * maxOneLen + mod; k++)
|
|
|
{
|
|
|
buff[k] = _buff[k - count * maxOneLen];
|
|
|
}
|
|
|
}
|
|
|
base.State = flag;
|
|
|
return flag;
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
//ICSharpCode.Core.LoggingService.Error(String.Format("读取PLC(AB500)设备失败-({0})!", ex.Message));
|
|
|
base.State = false;
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
/// 单次读取最长100个字的方法
|
|
|
/// </summary>
|
|
|
/// <param name="block">块号</param>
|
|
|
/// <param name="start">起始字</param>
|
|
|
/// <param name="len">长度,最长不超过100</param>
|
|
|
/// <param name="buff">数据缓冲区,存放读取的数据</param>
|
|
|
/// <returns>读取成功返回true,读取失败返回false</returns>
|
|
|
private bool ReadByLen(string block, int start, int len, out object[] buff)
|
|
|
{
|
|
|
lock (this)
|
|
|
{
|
|
|
buff = new object[len];
|
|
|
if (!this.Open())
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
int state = 0;
|
|
|
ushort[] _buff = new ushort[len];
|
|
|
string ss = "$N" + block.ToString() + ":" + start.ToString() + "," +
|
|
|
len.ToString() + ",WORD,READ,AB:LOCAL,1,SLC500,0";
|
|
|
//ICSharpCode.Core.LoggingService.Info("DTL_C_DEFINE=" + ss);
|
|
|
uint id = 0;
|
|
|
int iResult = DTL32.DTL_C_DEFINE(ref id, ss);
|
|
|
//ICSharpCode.Core.LoggingService.Info("DTL_C_DEFINE Result=" + iResult.ToString());
|
|
|
if (iResult != 0)
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
iResult = DTL32.DTL_READ_W(id, _buff, ref state, 1000);
|
|
|
//ICSharpCode.Core.LoggingService.Info("DTL_READ_W Result=" + iResult.ToString());
|
|
|
DTL32.DTL_UNDEF(id);
|
|
|
if (iResult != 0)
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
for (int i = 0; i < len; i++)
|
|
|
{
|
|
|
int value = _buff[i];
|
|
|
if (value > ushort.MaxValue)
|
|
|
{
|
|
|
value = ushort.MaxValue - value;
|
|
|
}
|
|
|
buff[i] = value;
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
|
}
|
|
|
private ushort ToValue(object obj, ushort defaultValue)
|
|
|
{
|
|
|
ushort result = 0;
|
|
|
if (obj != null
|
|
|
&& obj != DBNull.Value
|
|
|
&& ushort.TryParse(obj.ToString(), out result))
|
|
|
{
|
|
|
return result;
|
|
|
}
|
|
|
return defaultValue;
|
|
|
}
|
|
|
/// <summary>
|
|
|
/// PLC数据写入方法
|
|
|
/// </summary>
|
|
|
/// <param name="block">要写入的块号</param>
|
|
|
/// <param name="start">起始字</param>
|
|
|
/// <param name="buff">要写入PLC的数据</param>
|
|
|
/// <returns>写入成功返回true,失败返回false</returns>
|
|
|
public override bool Write(int block, int start, object[] buff)
|
|
|
{
|
|
|
lock (this)
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
if (buff.Length > 256)
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
int len = buff.Length;
|
|
|
int maxOneLen = 100; //单次允许读取的最大长度,AB500限制为100个字
|
|
|
int count = len / maxOneLen; //要读取的次数
|
|
|
int mod = len % maxOneLen; //剩余的长度
|
|
|
bool flag = true; //保存写入标志
|
|
|
for (int i = 0; i < count; i++)
|
|
|
{
|
|
|
object[] _buff = new object[maxOneLen];
|
|
|
for (int k = i * maxOneLen; k < (i + 1) * maxOneLen; k++)
|
|
|
{
|
|
|
_buff[k - i * maxOneLen] = buff[k];
|
|
|
}
|
|
|
flag = this.WriteMax100(block, start + i * maxOneLen, _buff);
|
|
|
if (flag == false)
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
if (mod > 0)
|
|
|
{
|
|
|
object[] _buff = new object[mod];
|
|
|
for (int k = count * maxOneLen; k < count * maxOneLen + mod; k++)
|
|
|
{
|
|
|
_buff[k - count * maxOneLen] = buff[k];
|
|
|
}
|
|
|
flag = this.WriteMax100(block, start + count * maxOneLen, _buff);
|
|
|
|
|
|
}
|
|
|
return flag;
|
|
|
}
|
|
|
catch (Exception ex)
|
|
|
{
|
|
|
//ICSharpCode.Core.LoggingService.Error(String.Format("写入PLC(AB500)设备失败-({0})!", ex.Message));
|
|
|
return false;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
/// <summary>
|
|
|
/// 单次写入最多100个字至PLC
|
|
|
/// </summary>
|
|
|
/// <param name="block">要写入的块号</param>
|
|
|
/// <param name="start">要写入的起始字</param>
|
|
|
/// <param name="buff">要写入的数据</param>
|
|
|
/// <returns>写入成功返回true,失败返回false</returns>
|
|
|
private bool WriteMax100(int block, int start, object[] buff)
|
|
|
{
|
|
|
lock (this)
|
|
|
{
|
|
|
if (buff.Length == 0)
|
|
|
{
|
|
|
return true;
|
|
|
}
|
|
|
Logger.Instance.Info("Open");
|
|
|
if (!this.Open())
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
int state = 0;
|
|
|
ushort[] _buff = new ushort[buff.Length];
|
|
|
for (int i = 0; i < buff.Length; i++)
|
|
|
{
|
|
|
_buff[i] = ToValue(buff[i], 0);
|
|
|
}
|
|
|
string ss = "$N" + block.ToString() + ":" + start.ToString() + "," +
|
|
|
buff.Length.ToString() + ",WORD,MODIFY,AB:LOCAL,1,SLC500,0";
|
|
|
uint id = 0;
|
|
|
int iResult = DTL32.DTL_C_DEFINE(ref id, ss);
|
|
|
if (iResult != 0)
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
iResult = DTL32.DTL_WRITE_W(id, _buff, ref state, 1000);
|
|
|
DTL32.DTL_UNDEF(id);
|
|
|
if (iResult != 0)
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
return true;
|
|
|
}
|
|
|
}
|
|
|
public override void Close()
|
|
|
{
|
|
|
lock (this)
|
|
|
{
|
|
|
try
|
|
|
{
|
|
|
DTL32.DTL_UNINIT(0);
|
|
|
DTL32.DTL_UNDEF(0);
|
|
|
DTL32.DTL_DRIVER_CLOSE(0, 100);
|
|
|
this.State = false;
|
|
|
}
|
|
|
catch(Exception ex)
|
|
|
{
|
|
|
this.State = false;
|
|
|
ICSharpCode.Core.LoggingService.Error(String.Format("关闭PLC(AB500)设备连接失败-({0})!", ex.Message));
|
|
|
//ICSharpCode.Core.LoggingService.Error(ex.StackTrace);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|