You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

374 lines
14 KiB
C#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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("打开PLCAB500设备连接失败-({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("读取PLCAB500设备失败-({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("写入PLCAB500设备失败-({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);
}
}
}
}
}