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

1807 lines
100 KiB

using System;
using System.Collections.Generic;
using System.Text;
using Opc.Ua;
using Opc.Ua.Client;
using System.Data;
using DBFactory;
using CommonLib;
using Siemens.OpcUA;
using CommLayerFactory;
using ICommLayer;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
namespace OPCClient
{
public class WorkItem
{
public object Parameter1 { get; set; }
public DataValue Parameter2 { get; set; }
// 可以添加更多的属性和参数
public WorkItem(object param1, DataValue param2)
{
Parameter1 = param1;
Parameter2 = param2;
}
}
public static class CCommonOPCClient
{
static Model.MDevice _device = null;
private static ushort S7NameSpace = 2;//20151120,默认值是32位系统的值2,64位系统的值是3
private static Model.MDevice devinfo;
private static Object thisLock = new Object();
static ISendDeviceOrder sdo;
static Model.MDevice modifypathdevinfo;
static Model.MDevice askDevinfo;
static StringBuilder[] wv = { new StringBuilder("2") };
static StringBuilder[] witemnames = { new StringBuilder("") };
/// <summary>
/// 一个周期内一个订阅组发送所有标签的个数
/// </summary>
static Dictionary<string, int> _opcSubsTagCount = new Dictionary<string, int>();
/// <summary>
/// 每个订阅组里对应设备发送标签名称集合
/// </summary>
static Dictionary<string, Dictionary<int, StringBuilder[]>> _opcItemNamesDicInfo = new Dictionary<string, Dictionary<int, StringBuilder[]>>();
/// <summary>
/// 每个订阅组里对应设备发送标签数值集合
/// </summary>
static Dictionary<string, Dictionary<int, StringBuilder[]>> _opcItemValuesDicInfo = new Dictionary<string, Dictionary<int, StringBuilder[]>>();
public static event RefreshMonitorEventHandler RefreshMonitor;
public static void OnRefreshMonitor(RefreshMonitorEventArgs e)
{
if (RefreshMonitor != null)
{
RefreshMonitor(e);
}
}
public static event CUpdateDBEventHandler DealSQLExe;
public static void OnDealSQLExe(object sender, CUpdateDBChangeEventArgs e)
{
DealSQLExe?.Invoke(sender, e);
}
public static event CUpdateDBEventHandler PublishDeviceState;
public static void OnPublishDeviceState(object sender,CUpdateDBChangeEventArgs e)
{
PublishDeviceState?.Invoke(sender, e);
}
public static DBOperator dbo =new DBOperator(); //20130510
//20110726
private static Dictionary<string, int> _connectCount = new Dictionary<string, int>();
//20110726
public static Dictionary<string, int> ConnectCount
{
get { return CCommonOPCClient._connectCount; }
set { CCommonOPCClient._connectCount = value; }
}
private static int[] _plcStates=null ;
public static int[] PlcStates
{
get { return CCommonOPCClient._plcStates; }
//set { CCommonOPCClient._plcStates = value; }
}
private static Server m_Server = null;
private static Siemens.OpcUA.Subscription m_Subscription;
public static BlockingCollection<WorkItem> buffer = new BlockingCollection<WorkItem>();
private static Task pollingTask = Task.Run(() => PollMethod());
/// <summary>
/// 20110309订阅的组内标签数据变化事件
/// </summary>
/// <param name="subscriptionHandle">客户端句柄</param>
/// <param name="requestHandle">请求句柄</param>
/// <param name="values">标签值数组</param>
public static void OnDataChange(object clientHandle, DataValue value)
{
buffer.Add(new WorkItem(clientHandle, value));
}
public static void kkkk()
{
if (buffer.Count > 0)
{
foreach (WorkItem item in buffer.GetConsumingEnumerable())
{
lock (thisLock)
{
//根据subscriptionHandle对应设备索引,依据设备种类(不同类型设备通讯数据帧不同)
//分别处理:完成,报警,光电开关,PLC发起的请求
int deviceindex = 0;
try
{
if (item.Parameter1.ToString().IndexOf("split") >= 0)
{
deviceindex = System.Convert.ToInt32(item.Parameter1.ToString().Substring(5));
}
else
{
deviceindex = System.Convert.ToInt32(item.Parameter1);
}
devinfo = Model.CGetInfo.GetDeviceInfo(deviceindex);
if (StatusCode.IsNotGood(item.Parameter2.StatusCode))
{
if (devinfo == null)
{
OpcError = string.Format("设备索引{0}在数据库不存在!", item.Parameter1);
return;
}
//触发一个特殊事件提示PLC断开连接
if (ConnectCount.ContainsKey(devinfo.S7Connection) == false)//20110726
{
ConnectCount.Add(devinfo.S7Connection, 0);
}
OpcError = string.Format("{0}所在的PLC已经离线!订阅标签状态:" + item.Parameter2.StatusCode.ToString(), item.Parameter1);
if (ConnectCount[devinfo.S7Connection] > 3)//20150204
{
_opcError = "订阅返回数据时:OPC Server没连接到PLC:" + devinfo.S7Connection.ToString() + ",人工确认后进行【PLC初始化】";//20150204
return;
}
ConnectCount[devinfo.S7Connection]++;//20150204
return;
}
ConnectCount[devinfo.S7Connection] = 0;
if (item.Parameter1.ToString().IndexOf("split") >= 0)
{
Array arr = (Array)item.Parameter2.Value;
byte[] GDKG = null;
GDKG = new byte[arr.GetLength(0)];
Array.Copy(arr, GDKG, arr.GetLength(0));
#region 解析订阅返回光电开关数据
DealWithDeviceState(out string errText, deviceindex, GDKG, null);
#endregion
}
else
{
Array arr = (Array)item.Parameter2.Value;
byte[] itemnamevalue = new byte[arr.GetLength(0)];
Array.Copy(arr, itemnamevalue, arr.GetLength(0));
int head = 0;
head = itemnamevalue[0];//读写标志
#region 解析订阅返回状态数据,并发布主线程可订阅的事件
DealWithDeviceState(out string errText, deviceindex, null, itemnamevalue);
#endregion
}
}
catch (Exception ex)
{//20120420
OpcError = string.Format("OPC服务器订阅事件异常:{0},{1}", ex.Message, ex.StackTrace);
}
}
}
}
}
static void PollMethod()
{
while (true) // 无限循环,模拟轮询
{
// 这里放置你的轮询逻辑
kkkk();
// 休眠一段时间,例如1秒
Thread.Sleep(1000);
}
}
static bool DealWithDeviceState(out string errtext, int deviceindex, byte[] splitbyteValue, byte[] devicestates)
{//deviceindex设备组代表的订阅,首先把设备组按照F_DBW2Address由小到大排序,拆分到具体每个设备
//20230811richard.liu周期内按S7连接批量发送,重构CControl.cs,CCommonOPCClient.cs\DealWithDeviceState;文件夹Communication、Common内通讯CSendDeviceOrder: ISendDeviceOrder相关文件
lock (thisLock)
{
_opcSubsTagCount.Clear();
_opcItemNamesDicInfo.Clear();
_opcItemValuesDicInfo.Clear();
Dictionary<int, StringBuilder> DeviceStateInfos=new Dictionary<int, StringBuilder>();
errtext = string.Empty;
DataView dvDevice = new DataView();//device表的设备信息
DataView dvPLCASK = new DataView();//PLCASK表数据不能更改
DataView dvbc = new DataView();//临时表可随意用
int devicebegin = 0; int DBW2Addressbegin = 0; string S7Connection = string.Empty;//int SplitBytebegin = 0;
int SplitByteLength = 0;
try
{
StringBuilder sql = new StringBuilder(string.Format("SELECT F_DeviceIndex, F_DBW2Address, F_DBWGetLength, F_SplitByte,F_S7Connection FROM T_Base_Device WHERE f_controldevice='1' and (F_DeviceKindIndex !=33) AND (F_ReadSubscription = '{0}') AND (F_DBW2Address IS NOT NULL) ORDER BY F_DBW2Address", deviceindex));//20151120,增加字段是否需要服务端处理设备的订阅
dvDevice = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
if (dvDevice.Count > 0)
{//订阅组第一个设备,设备编码是订阅组ID
devicebegin = Convert.ToInt32(dvDevice[0]["F_DeviceIndex"]);
DBW2Addressbegin = Convert.ToInt32(dvDevice[0]["F_DBW2Address"]);
//SplitBytebegin = Convert.ToInt32(dvDevice[0]["F_SplitByte"]);
S7Connection = dvDevice[0]["F_S7Connection"].ToString();
//sql.Clear();
//sql.Append(string.Format("SELECT F_DeviceIndex, F_DBW2Address, F_DBWGetLength, F_SplitByte,F_S7Connection FROM T_Base_Device WHERE (F_DeviceKindIndex =33) AND (F_ReadSubscription = '{0}') ORDER BY F_DBW2Address", deviceindex));
//dvPLCASK = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
//if (dvPLCASK.Count > 0)
//{
// SplitByteLength = Convert.ToInt32(dvPLCASK[0]["F_DBWGetLength"]);
//}
}
else
{//非订阅组第一个设备
sql = new StringBuilder(string.Format("SELECT F_DeviceIndex, F_DBW2Address, F_DBWGetLength, F_SplitByte,F_S7Connection FROM T_Base_Device WHERE (F_DeviceIndex = '{0}') AND (F_DBW2Address IS NOT NULL) ORDER BY F_DBW2Address", deviceindex));
dvDevice = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
if (dvDevice.Count > 0)
{
devicebegin = Convert.ToInt32(dvDevice[0]["F_DeviceIndex"]);
DBW2Addressbegin = Convert.ToInt32(dvDevice[0]["F_DBW2Address"]);
//SplitBytebegin = Convert.ToInt32(dvDevice[0]["F_SplitByte"]);
S7Connection = dvDevice[0]["F_S7Connection"].ToString();
sql = new StringBuilder(string.Format("SELECT F_DeviceIndex, F_DBW2Address, F_DBWGetLength, F_SplitByte,F_S7Connection FROM T_Base_Device WHERE (F_DeviceKindIndex =33) AND (F_ReadSubscription = '{0}') ORDER BY F_DBW2Address", deviceindex));
dvPLCASK = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
if (dvPLCASK.Count > 0)
{
SplitByteLength = Convert.ToInt32(dvPLCASK[0]["F_DBWGetLength"]);
}
}
else
{//20120420
RefreshMonitorEventArgs rmea = new RefreshMonitorEventArgs("tsStatus", string.Format("CCommonOPCClient.DealWithDeviceState时,订阅组:{0}对应的设备索引不存在!", deviceindex));
OnRefreshMonitor(rmea);
errtext = string.Format("CCommonOPCClient.DealWithDeviceState时,订阅组:{0}对应的设备索引不存在!", deviceindex);
return false;
}
}
#region 设备状态采集分解
int tempdb2addr = 0; StringBuilder sss = new StringBuilder(); StringBuilder barcode = new StringBuilder();
if (devicestates != null)
{
//遍历订阅内所有设备
for (int di = 0; di < dvDevice.Count; di++)
{
int devidx = Convert.ToInt32(dvDevice[di]["F_DeviceIndex"]);
devinfo = Model.CGetInfo.GetDeviceInfo(devidx);
if (DeviceStateInfos.ContainsKey(devidx) == false)
{
DeviceStateInfos.Add(devidx, new StringBuilder(devidx.ToString() + "#"));
}
witemnames[0].Clear();
witemnames[0].Append(Model.CGeneralFunction.DBGet).Append(".").Append(Convert.ToString(devinfo.Dbw2Address + 0)).Append(",b");//20141201张磊发现误写为Dbw1Address
sdo = CommModeCreate.CreateSendDeviceOrder(devidx);
int taskindex = 0; int state = 0;
int xc = 0; int yc = 0;
int devkind = devinfo.DeviceKind;
//以下代码重新开发CStaticClass.MutiS7ConnReturns改为按照F_ReadSubscription
tempdb2addr = Convert.ToInt32(dvDevice[di]["F_DBW2Address"]) - DBW2Addressbegin;
if (3 < devinfo.Dbw2Getlength&&devkind!=5&& devkind != 13)
{
//state = devicestates[tempdb2addr + 1];
taskindex = (devicestates[tempdb2addr + 2] << 8) + devicestates[tempdb2addr + 3];
}
if (1 < devinfo.Dbw2Getlength&&devkind!=7)
{
state = devicestates[tempdb2addr + 1];
}
if (1 == devinfo.Dbw2Getlength )
{
state = devicestates[tempdb2addr];
}
if (devkind == 13 && devinfo.UnControl!="1")
{//richard.liu20230718鸿安环穿0-1是心跳单独订阅;2是可下任务状态0:不可下命令,1:可下命令
state = devicestates[tempdb2addr + 1] == 0 ? 1 : 0;//可下任务状态
taskindex = (devicestates[tempdb2addr + 2] << 8) + devicestates[tempdb2addr + 3];
}
#region 通用物流设备状态
devinfo = Model.CGetInfo.GetDeviceInfo(devidx);
if (devinfo.RunState != 4)//20121203
{
string errText = string.Empty;
if (state >= 30)
{
#region 20160501故障信息变化,上一故障结束,新故障开始
Model.MError errs;
if (devinfo.ErrorCode != state && devinfo.ErrorCode >= 30)
{
if (taskindex == 0 || taskindex >= 30000)
{
DeviceStateInfos[devidx].Append(string.Format("{0}#{1}", taskindex, state));
}
#region 上一次报警或者故障时间分别统计记录
errs = Model.CGetInfo.GetErrorInfo(Convert.ToInt32(devkind.ToString() + devinfo.ErrorCode.ToString()));
if (errs != null)
{
DataView dverr = dbo.ExceSQL(string.Format("SELECT F_ManageTaskNo,F_DeviceIndex,F_ErrorIndex,F_DateTime FROM T_Base_Device_Error_Log where F_DeviceIndex={0} and F_ErrorIndex={1} order by F_DateTime desc", devidx, errs.ErrorIndex)).Tables[0].DefaultView;
if (dverr.Count > 0)
{//richard.liu20181212对报警记录更新最近一个的修复时间
sql.Remove(0, sql.Length);
sql.Append("UPDATE T_Base_Device_Error_Log SET F_FixDateTime ='").Append(DateTime.Now.ToString("u")).Append("' Where F_DeviceIndex=")
.Append(devidx).Append(" and F_ErrorIndex=").Append(errs.ErrorIndex).Append(" and F_ManageTaskNo=").Append(Convert.ToInt32(dverr[0]["F_ManageTaskNo"]));
//dbo.ExceSQL(sql.ToString());
StringBuilder[] dboArrary = new StringBuilder[1] { new StringBuilder("DBFactory") };
StringBuilder[] sqlArrary = new StringBuilder[1] { sql };
CUpdateDBChangeEventArgs exeSql = new CUpdateDBChangeEventArgs(dboArrary, sqlArrary);
OnDealSQLExe("OPCClient.CCommonOPCClient.OnDataChange", exeSql);
}
if (errs.IfAlarm == '1')
{
//CStaticClass.UpdateDeviceOEE(devidx, DateTime.Now.Date, 0, 0, 0, 0
//, 0, ccf.GetAlarmTimeSpan(devidx),errs.ErrorKind, 0, out errText);//统计上次报警
//dbo.ExecuteSql(string.Format("update T_Base_Device set F_AlarmStartTime='-' where F_DeviceIndex ={0}", devidx));
}
else
{
//CStaticClass.UpdateDeviceOEE(devidx, DateTime.Now.Date, 0, 0, 0, 0
//, ccf.GetErrorTimeSpan(devidx), 0,errs.ErrorKind, 0, out errText);//统计上次故障
//dbo.ExecuteSql(string.Format("update T_Base_Device set F_ErrorStartTime='-' where F_DeviceIndex ={0}", devidx));
}
}
#endregion
//新的报警或故障开始计时
errs = Model.CGetInfo.GetErrorInfo(Convert.ToInt32(devkind.ToString() + state.ToString()));
if (errs != null)
{
if (errs.IfAlarm == '1')
{
//dbo.ExecuteSql(string.Format("update T_Base_Device set F_AlarmStartTime='{1}' where F_DeviceIndex ={0}", devidx, DateTime.Now.ToString("u").Substring(0, 19)));
//CStaticClass.UpdateDeviceOEE(devinfo.DeviceIndex, DateTime.Now.Date, 0, 0, 1,
// 0, 0, 0, 'O', 0, out errText);//richard.liu20181212报警数量增加1
}
else
{
//dbo.ExecuteSql(string.Format("update T_Base_Device set F_ErrorStartTime='{1}' where F_DeviceIndex ={0}", devidx, DateTime.Now.ToString("u").Substring(0, 19)));
//CStaticClass.UpdateDeviceOEE(devinfo.DeviceIndex, DateTime.Now.Date, 0, 1, 0,
// 0, 0, 0, 'O', 0, out errText);//richard.liu20181212故障数量增加1
}
}
}
else if (devinfo.ErrorCode != state && devinfo.ErrorCode < 30)
{
if (taskindex == 0 || taskindex >= 30000)
{
DeviceStateInfos[devidx].Append(string.Format("{0}#{1}", taskindex, state));
}
//求上一次运行时间
//CStaticClass.UpdateDeviceOEE(devidx, DateTime.Now.Date, 0, 0, 0, ccf.GetConveyorRunTimeSpan(devidx)
// ,0,0,'O',0, out errText);//统计上次运行时间
//dbo.ExecuteSql(string.Format("update T_Base_Device set F_ConveyorRunStartTime='-' where F_DeviceIndex ={0}", devidx));
//新的报警或故障开始计时
errs = Model.CGetInfo.GetErrorInfo(Convert.ToInt32(devkind.ToString() + state.ToString()));
if (errs != null)
{
if (errs.IfAlarm == '1')
{
//dbo.ExecuteSql(string.Format("update T_Base_Device set F_AlarmStartTime='{1}' where F_DeviceIndex ={0}", devidx, DateTime.Now.ToString("u").Substring(0, 19)));
//CStaticClass.UpdateDeviceOEE(devinfo.DeviceIndex, DateTime.Now.Date, 0, 0, 1,
// 0, 0, 0, 'O', 0, out errText);//richard.liu20181212报警数量增加1
}
else
{
//dbo.ExecuteSql(string.Format("update T_Base_Device set F_ErrorStartTime='{1}' where F_DeviceIndex ={0}", devidx, DateTime.Now.ToString("u").Substring(0, 19)));
//CStaticClass.UpdateDeviceOEE(devinfo.DeviceIndex, DateTime.Now.Date, 0, 1, 0,
// 0, 0, 0, 'O', 0, out errText);//richard.liu20181212故障数量增加1
}
}
}
#endregion
devinfo.ErrorCode = state;
devinfo.RunState = 2;
}
else
{//0,1,2
#region 20160501上一故障结束,输送机任务变化:任务数增加1
//输送机状态变化:0->1开始运行;1->0运行结束,运行时间增加
if (devinfo.ErrorCode >= 30)
{
#region 如果上一次报警或者故障结束,清除时间,改为运行时间
Model.MError errs = Model.CGetInfo.GetErrorInfo(Convert.ToInt32(devkind.ToString() + devinfo.ErrorCode.ToString()));
if (errs != null)
{
DataView dverr = dbo.ExceSQL(string.Format("SELECT F_ManageTaskNo,F_DeviceIndex,F_ErrorIndex,F_DateTime FROM T_Base_Device_Error_Log where F_DeviceIndex={0} and F_ErrorIndex={1} order by F_DateTime desc", devidx, errs.ErrorIndex)).Tables[0].DefaultView;
if (dverr.Count > 0)
{//richard.liu20181212对报警记录更新最近一个的修复时间
sql.Remove(0, sql.Length);
sql.Append("UPDATE T_Base_Device_Error_Log SET F_FixDateTime ='").Append(DateTime.Now.ToString("u")).Append("' Where F_DeviceIndex=")
.Append(devidx).Append(" and F_ErrorIndex=").Append(errs.ErrorIndex).Append(" and F_ManageTaskNo=").Append(Convert.ToInt32(dverr[0]["F_ManageTaskNo"]));
//dbo.ExceSQL(sql.ToString());
StringBuilder[] dboArrary = new StringBuilder[1] { new StringBuilder("DBFactory") };
StringBuilder[] sqlArrary = new StringBuilder[1] { sql };
CUpdateDBChangeEventArgs exeSql = new CUpdateDBChangeEventArgs(dboArrary, sqlArrary);
OnDealSQLExe("OPCClient.CCommonOPCClient.OnDataChange", exeSql);
}
if (errs.IfAlarm == '1')
{
//CStaticClass.UpdateDeviceOEE(devidx, DateTime.Now.Date, 0, 0, 0, 0
//, 0, ccf.GetAlarmTimeSpan(devidx),errs.ErrorKind, 0, out errText);
//dbo.ExecuteSql(string.Format("update T_Base_Device set F_AlarmStartTime='-' where F_DeviceIndex ={0}", devidx));
}
else
{
//CStaticClass.UpdateDeviceOEE(devidx, DateTime.Now.Date, 0, 0, 0, 0
//, ccf.GetErrorTimeSpan(devidx), 0,errs.ErrorKind, 0, out errText);
//dbo.ExecuteSql(string.Format("update T_Base_Device set F_ErrorStartTime='-' where F_DeviceIndex ={0}", devidx));
}
//开始记录运行时间
if (devkind == 2)
{
//dbo.ExecuteSql(string.Format("update T_Base_Device set F_ConveyorRunStartTime='{1}' where F_DeviceIndex ={0}", devidx, DateTime.Now.ToString("u").Substring(0, 19)));
}
}
#endregion
}
else
{//状态变化:0->1开始运行;1->0()运行结束,运行时间增加
if (devinfo.ErrorCode == 0 && state == 1 && devkind == 2)
{
//开始记录运行时间
//dbo.ExecuteSql(string.Format("update T_Base_Device set F_ConveyorRunStartTime='{1}' where F_DeviceIndex ={0}", devidx, DateTime.Now.ToString("u").Substring(0, 19)));
}
else if (devinfo.ErrorCode == 1 && (state == 0 || state == 2) && devkind == 2)
{
//CStaticClass.UpdateDeviceOEE(devidx, DateTime.Now.Date, 0, 0, 0, ccf.GetConveyorRunTimeSpan(devidx)
//, 0, 0,'O', 0, out errText);//统计上次运行时间
//dbo.ExecuteSql(string.Format("update T_Base_Device set F_ConveyorRunStartTime='-' where F_DeviceIndex ={0}", devidx));
}
}
//任务变化
if (devinfo.TaskNo != taskindex && devkind == 2 && taskindex > 0)
{
//CStaticClass.UpdateDeviceOEE(devidx, DateTime.Now.Date,1, 0, 0, 0
// ,0, 0,'O', 0, out errText);
}
#endregion
if (state == 2)
{
devinfo.RunState = 5;
}
else
{
devinfo.RunState = state;
}
devinfo.ErrorCode = state;
}
}
devinfo.TaskNo = taskindex;
if ((devinfo.DeviceKind == 1) || (devinfo.DeviceKind == 4) || (devinfo.DeviceKind == 14))
{
devinfo.XCoor = devicestates[tempdb2addr + 7] + (devicestates[tempdb2addr + 6] << 8) + (devicestates[tempdb2addr + 5] << 16) + (devicestates[tempdb2addr + 4] << 32);//X坐标
if (devinfo.DeviceKind == 1)
{
devinfo.YCoor = devicestates[tempdb2addr + 11] + (devicestates[tempdb2addr + 10] << 8) + (devicestates[tempdb2addr + 9] << 16) + (devicestates[tempdb2addr + 8] << 32);//Y坐标
devinfo.ZCoor = devicestates[tempdb2addr + 12];//Z相对坐标(1或2\3)
}
}
Model.CGetInfo.SetDeviceInfo(devinfo);
modifypathdevinfo = Model.CGetInfo.GetModifyPathDeviceInfo(devidx);
if (modifypathdevinfo != null)
{
modifypathdevinfo.RunState = devinfo.RunState;
modifypathdevinfo.ErrorCode = devinfo.ErrorCode;
modifypathdevinfo.TaskNo = devinfo.TaskNo;
Model.CGetInfo.SetModifyPathDeviceInfo(modifypathdevinfo);
}
#endregion
#region 处理设备完成、报警、运行状态;条码信息
string bc = string.Empty;
int[] states = new int[(int)devinfo.Dbw2Getlength];
Array.Copy(devicestates, tempdb2addr, states, 0, (int)devinfo.Dbw2Getlength);
switch (devkind)
{
#region 堆垛机
case 1:
if (devicestates[tempdb2addr + 0] != 1) continue;
#region 更新堆垛机光电开关状态
devinfo.SplitByte_0 = (devicestates[tempdb2addr + 13] & 1) == 1 ? 1 : 0;
devinfo.SplitByte_1 = (devicestates[tempdb2addr + 13] & 2) == 2 ? 1 : 0;
devinfo.SplitByte_2 = (devicestates[tempdb2addr + 13] & 4) == 4 ? 1 : 0;
devinfo.SplitByte_3 = (devicestates[tempdb2addr + 13] & 8) == 8 ? 1 : 0;
devinfo.SplitByte_4 = (devicestates[tempdb2addr + 13] & 16) == 16 ? 1 : 0;
devinfo.SplitByte_5 = (devicestates[tempdb2addr + 13] & 32) == 32 ? 1 : 0;
devinfo.SplitByte_6 = (devicestates[tempdb2addr + 13] & 64) == 64 ? 1 : 0;
devinfo.SplitByte_7 = (devicestates[tempdb2addr + 13] & 128) == 128 ? 1 : 0;
Model.CGetInfo.SetDeviceInfo(devinfo);
#endregion
if (IsEquals(devinfo.ReturnMessage, states, 4) == false)
{
bc = GetBarcodeFromMonitorIndex(taskindex);
xc = devicestates[tempdb2addr + 7] + (devicestates[tempdb2addr + 6] << 8) + (devicestates[tempdb2addr + 5] << 16) + (devicestates[tempdb2addr + 4] << 32);//X坐标
yc = devicestates[tempdb2addr + 11] + (devicestates[tempdb2addr + 10] << 8) + (devicestates[tempdb2addr + 9] << 16) + (devicestates[tempdb2addr + 8] << 32);//Y坐标
devinfo.ReturnMessage = states;
Model.CGetInfo.SetDeviceMessage(devinfo);
sss.Remove(0, sss.Length);
sss.Append("**条码:").Append(bc).Append("**读标志" + devicestates[tempdb2addr + 0]).Append("**状态" + state).Append("**任务号" + taskindex)
.Append("**列坐标" + xc).Append("**层坐标" + yc);
CommonClassLib.CCarryConvert.WriteDarkCasket("OPCClient", "收到堆垛机状态", devidx.ToString(), sss.ToString());
if (devicestates[tempdb2addr + 0] != 1) continue;
if ((state <= 0) || (taskindex <= 0))
{
continue;
}
AddBatchReponse(Model.CGeneralFunction.DBSend, taskindex, devidx, state);
DeviceStateInfos[devidx].Append(string.Format("{0}#{1}", taskindex, state));
//cgs.GetKindDeviceState(taskindex, devidx, state);
}
break;
#endregion
#region 类输送机
case 2:
#region 更新输送机光电开关状态
devinfo.SplitByte_0 = (devicestates[tempdb2addr + 4] & 1) == 1 ? 1 : 0;
devinfo.SplitByte_1 = (devicestates[tempdb2addr + 4] & 2) == 2 ? 1 : 0;
devinfo.SplitByte_2 = (devicestates[tempdb2addr + 4] & 4) == 4 ? 1 : 0;
devinfo.SplitByte_3 = (devicestates[tempdb2addr + 4] & 8) == 8 ? 1 : 0;
devinfo.SplitByte_4 = (devicestates[tempdb2addr + 4] & 16) == 16 ? 1 : 0;
devinfo.SplitByte_5 = (devicestates[tempdb2addr + 4] & 32) == 32 ? 1 : 0;
devinfo.SplitByte_6 = (devicestates[tempdb2addr + 4] & 64) == 64 ? 1 : 0;
devinfo.SplitByte_7 = (devicestates[tempdb2addr + 4] & 128) == 128 ? 1 : 0;
Model.CGetInfo.SetDeviceInfo(devinfo);
#endregion
if (IsEquals(devinfo.ReturnMessage, states, 4) == false)
{
bc = GetBarcodeFromMonitorIndex(taskindex);
devinfo.ReturnMessage = states;
Model.CGetInfo.SetDeviceMessage(devinfo);
sss.Remove(0, sss.Length);
sss.Append("**条码:").Append(bc).Append("**读标志" + devicestates[tempdb2addr + 0]).Append("**状态" + state).Append("**任务号:" + taskindex);
CommonClassLib.CCarryConvert.WriteDarkCasket("OPCClient", "收到输送机机状态", devidx.ToString(), sss.ToString());
//if (devicestates[tempdb2addr + 0] != 1) continue;
if (state <= 0 || taskindex <= 0)//20140305
{
continue;
}
if (taskindex > 0)
{
AddBatchReponse(Model.CGeneralFunction.DBSend, taskindex, devidx, state);
DeviceStateInfos[devidx].Append(string.Format("{0}#{1}", taskindex, state));
//cgs.GetKindDeviceState(taskindex, devidx, state);
}
}
break;
#endregion
#region 穿梭车RGV
case 4:
if (devicestates[tempdb2addr + 0] != 1) continue;
#region 更新穿梭车光电开关状态
devinfo.SplitByte_0 = (devicestates[tempdb2addr + 8] & 1) == 1 ? 1 : 0;
devinfo.SplitByte_1 = (devicestates[tempdb2addr + 8] & 2) == 2 ? 1 : 0;
devinfo.SplitByte_2 = (devicestates[tempdb2addr + 8] & 4) == 4 ? 1 : 0;
devinfo.SplitByte_3 = (devicestates[tempdb2addr + 8] & 8) == 8 ? 1 : 0;
devinfo.SplitByte_4 = (devicestates[tempdb2addr + 8] & 16) == 16 ? 1 : 0;
devinfo.SplitByte_5 = (devicestates[tempdb2addr + 8] & 32) == 32 ? 1 : 0;
devinfo.SplitByte_6 = (devicestates[tempdb2addr + 8] & 64) == 64 ? 1 : 0;
devinfo.SplitByte_7 = (devicestates[tempdb2addr + 8] & 128) == 128 ? 1 : 0;
#endregion
Model.CGetInfo.SetDeviceInfo(devinfo);
if (IsEquals(devinfo.ReturnMessage, states, 4) == false)
{
bc = GetBarcodeFromMonitorIndex(taskindex);
xc = devicestates[tempdb2addr + 7] + (devicestates[tempdb2addr + 6] << 8) + (devicestates[tempdb2addr + 5] << 16) + (devicestates[tempdb2addr + 4] << 32);//X坐标
devinfo.ReturnMessage = states;
devinfo.XCoor = xc;
Model.CGetInfo.SetDeviceMessage(devinfo);
sss.Remove(0, sss.Length);
sss.Append("**条码:").Append(bc).Append("**读标志" + devicestates[tempdb2addr + 0]).Append("**状态" + state).Append("**任务号" + taskindex)
.Append("**列坐标" + xc);
CommonClassLib.CCarryConvert.WriteDarkCasket("OPCClient", "收到RGV状态", devidx.ToString(), sss.ToString());
if (devicestates[tempdb2addr + 0] != 1) continue;
if ((state <= 0) || (taskindex <= 0))
{
continue;
}
AddBatchReponse(Model.CGeneralFunction.DBSend, taskindex, devidx, state);
DeviceStateInfos[devidx].Append(string.Format("{0}#{1}", taskindex, state));
//cgs.GetKindDeviceState(taskindex, devidx, state);
}
break;
#endregion
#region 条形码字符串信息
case 7:
if (devicestates[tempdb2addr + 0] != 1) continue;
int BoxInspection = devicestates[tempdb2addr + 1]; //尺寸检测/数量
//20140109申请任务(任务不存在)或者条码比对(任务已经存在)
dvPLCASK = dbo.ExceSQL(string.Format("select F_BarCode,F_Time, F_PalletBarcodeLength,F_PalletBarcodeReservedLength,F_BarcodeReservedLength,F_WareHouse,F_ManageAskkind,F_BarcodeForkAmount,F_BarcodeLength,F_BindingDevice,F_Askkind,F_Remark from T_Base_PLC_Ask WHERE (F_DeviceIndex = {0}) ", devidx)).Tables[0].DefaultView; //20130510F_ManageAskkind
if (dvPLCASK.Count > 0)
{
StringBuilder warehouse = new StringBuilder(dvPLCASK[0]["F_WareHouse"].ToString());
int dcode = Convert.ToInt32(dvPLCASK[0]["F_BindingDevice"]);
int apptype = Convert.ToInt32(dvPLCASK[0]["F_ManageAskkind"]);//20130510
int BarcodeForkAmount = Convert.ToInt32(dvPLCASK[0]["F_BarcodeForkAmount"]); //多叉堆垛机存放箱条码的最大组数
byte[] weightbyte = new byte[4] { devicestates[tempdb2addr + 2], devicestates[tempdb2addr + 3], devicestates[tempdb2addr + 4], devicestates[tempdb2addr + 5] };
float weights = CommonClassLib.CCarryConvert.ByteToFloat(weightbyte);//重量信息
int BarcodeLength = Convert.ToInt32(dvPLCASK[0]["F_BarcodeLength"]);//多叉堆垛机取货站台上报条码、周转箱叠箱、托盘码垛
int BarcodeReservedLength = Convert.ToInt32(dvPLCASK[0]["F_BarcodeReservedLength"]);//多叉堆垛机取货站台上报条码、周转箱叠箱、托盘码垛
if (BarcodeReservedLength < BarcodeLength)
{
BarcodeReservedLength = BarcodeLength;
}
//int BarcodeTotalLength = BarcodeReservedLength * BoxInspection;
int PalletBarcodeLength = Convert.ToInt32(dvPLCASK[0]["F_PalletBarcodeLength"]);//托盘条码
int PalletBarcodeReservedLength = Convert.ToInt32(dvPLCASK[0]["F_PalletBarcodeReservedLength"]);
if (PalletBarcodeReservedLength < PalletBarcodeLength)
{
PalletBarcodeReservedLength = PalletBarcodeLength;
}
StringBuilder incompleteBarcode = new StringBuilder();// 1111111111111111.......
StringBuilder noneBarcode = new StringBuilder();// \0\0\0\0..........
StringBuilder appbarcode = new StringBuilder();
StringBuilder[] appbarArray = new StringBuilder[BarcodeForkAmount];
StringBuilder parameter = new StringBuilder();//存放给管理上报的纸箱条码组
#region 初始化接收条码
//for (int j = 1; j <= BarcodeLength; j++)
//{
// incompleteBarcode.Append("1");//PLC扫到残码,但是有货物,转换为字符'1'
// noneBarcode.Append("0");//PLC没扫描,没货物,保留的空值0,转换为字符'\0'
//}
//for (int j = 0; j < BarcodeForkAmount; j++)
//{//多叉堆垛机,在取货前上报条码格式:头+数量+条码//20140218
// appbarArray[j] = new StringBuilder(ASCIIEncoding.ASCII.GetString(devicestates, tempdb2addr + 2 + j * BarcodeReservedLength, BarcodeReservedLength).Substring(0, BarcodeLength));
//}
barcode.Clear();
if (PalletBarcodeLength > 0)
{//普通扫描单箱的条码申请\机器人码垛的托盘条码
incompleteBarcode.Clear();//20150103
noneBarcode.Clear();//20150103
for (int j = 1; j <= PalletBarcodeLength; j++)
{//20150103
incompleteBarcode.Append("1");//PLC扫到残码,但是有货物,转换为字符'1'
noneBarcode.Append("0");//PLC没扫描,没货物,保留的空值0,转换为字符'\0'
}
for (int j = 4; j < PalletBarcodeLength + 4; j++)
{
barcode.Append(Convert.ToChar(devicestates[tempdb2addr + j]).ToString().ToUpper());
}
}
if (IsEquals(devinfo.ReturnMessage, states, states.Length) == false)
{
devinfo.ReturnMessage = states;
Model.CGetInfo.SetDeviceMessage(devinfo);
CommonClassLib.CCarryConvert.WriteDarkCasket("OPCClient", "读PLC条码", devidx.ToString(), "读标志1**条码:" + barcode.ToString().Trim('\0').ToUpper()+"高度:"+ BoxInspection.ToString()+"任务号:"+taskindex);
}
#endregion
//20130831richard
DateTime appdt = new DateTime();
if (dvPLCASK[0]["F_Time"] == DBNull.Value)
{
appdt = DateTime.Now.AddSeconds(-10);
}
else
{
DateTime.TryParse(dvPLCASK[0]["F_Time"].ToString(), out appdt);
}
if (dvPLCASK[0]["F_BarCode"] != DBNull.Value)
{
if ((appdt.AddSeconds(15) > DateTime.Now) && (dvPLCASK[0]["F_BarCode"].ToString() == barcode.ToString()))
{
CommonClassLib.CCarryConvert.WriteDarkCasket("OPCClient", "PLC重复上报条码:", devidx.ToString(), ",站台:" + dcode + ",条码:" + barcode.ToString().ToUpper());
break;
}
}
switch (dvPLCASK[0]["F_Askkind"].ToString())
{
case "4":
//普通条码申请任务
DeviceStateInfos[devidx].Append(string.Format("{0}#{1}#{2}#{3}#{4}", 0, 0, 4, barcode.ToString().Trim('\0'), BoxInspection));
break;
case "6":
//103合托后申请入库
DeviceStateInfos[devidx].Append(string.Format("{0}#{1}#{2}#{3}#{4}", taskindex, 0, 6, barcode.ToString().Trim('\0'), BoxInspection));
break;
case "8":
//二合一
DeviceStateInfos[devidx].Append(string.Format("{0}#{1}#{2}#{3}#{4}", taskindex, 0, 8, barcode.ToString().Trim('\0'), BoxInspection));
break;
case "5":
//比对任务报完成,申请任务
DeviceStateInfos[devidx].Append(string.Format("{0}#{1}#{2}#{3}#{4}", taskindex, 0, 5, barcode.ToString().Trim('\0'), BoxInspection));
break;
case "7":
//组件扫码成品入库
#region 组件条码申请任务
barcode.Clear();
for (int j = 2; j < PalletBarcodeLength; j++)
{
if (devicestates[tempdb2addr + j] == 13)
{
break;
}
barcode.Append(Convert.ToChar(devicestates[tempdb2addr + j]).ToString().ToUpper());
}
DeviceStateInfos[devidx].Append(string.Format("{0}#{1}#{2}#{3}#{4}", 0, 0, 7, barcode.ToString().Trim('\0'), BoxInspection));
#endregion
break;
case "9":
//大叠托机申请离开
DeviceStateInfos[devidx].Append(string.Format("{0}#{1}#{2}#{3}#{4}", 0, 0, 5, barcode.ToString().Trim('\0'), BoxInspection));
break;
case "13":
//条码报告完成,考虑第一个扫描器没扫到,但是第二个扫描器却扫到
//没扫到或者有码无对应任务的改道异常口
#region 条码报告完成
DeviceStateInfos[devidx].Append(string.Format("{0}#{1}#{2}#{3}#{4}", 0, 0, 13, barcode.ToString(), BoxInspection));
CommonClassLib.CCarryConvert.WriteDarkCasket("OPCClient", "写条码应答", devidx.ToString(), "写标志:2" + "**源条码:" + barcode.ToString().ToUpper());
#endregion
break;
case "17":
#region 叠箱机上报个数和箱条码
if (parameter.ToString().Length > 0)
{
#region 向管理申请叠箱后入库任务
CommonClassLib.CCarryConvert.WriteDarkCasket("OPCClient", "向管理申请叠箱入库任务", devidx.ToString(), dcode + "条码" + barcode.ToString().ToUpper() + "垛条码:" + parameter.ToString());
DeviceStateInfos[devidx].Append(string.Format("{0}#{1}#{2}#{3}#{4}", 0, 0, 17, barcode.ToString(), BoxInspection));
#endregion
}
#endregion
break;
default:
//无类型,条码比对或者记录条码
break;
}
AddBatchReponse(Model.CGeneralFunction.DBGet, 0, devidx, 2);
CommonClassLib.CCarryConvert.WriteDarkCasket("OPCClient", "写条码应答", devidx.ToString(), "写标志2" + "**源条码:" + barcode.ToString().ToUpper());
}
break;
#endregion
#region 落地机按钮申请空母托对应设备
case 36:
if (devicestates[tempdb2addr + 0] != 1) continue;
//0字节代表命令字:1表示PLC上报,2表示PC应答
//1字节:1申请空母托
AddBatchReponse(Model.CGeneralFunction.DBGet, 0, devidx, 2);
CommonClassLib.CCarryConvert.WriteDarkCasket("OPCClient", "写落地机按钮申请空母托应答", devidx.ToString(), "写标志2**申请空母托标识:" + devicestates[tempdb2addr + 1].ToString() + ";" + witemnames[0].ToString());
DeviceStateInfos[devidx].Append(string.Format("{0}#{1}#{2}", 0, 0, devicestates[tempdb2addr + 1]));
break;
#endregion
#region 拆叠盘机申请出入库对应设备
case 38:
if (devicestates[tempdb2addr + 0] != 1) continue;
//0字节代表命令字:1表示PLC上报,2表示PC应答
//1字节:1申请入库;2申请出库
AddBatchReponse(Model.CGeneralFunction.DBGet, 0, devidx, 2);
CommonClassLib.CCarryConvert.WriteDarkCasket("OPCClient", "写拆叠盘机申请出入库应答", devidx.ToString(), "写标志2**出入库任务类型:" + devicestates[tempdb2addr + 1].ToString() + ";" + witemnames[0].ToString());
DeviceStateInfos[devidx].Append(string.Format("{0}#{1}#{2}", 0, 0, devicestates[tempdb2addr + 1]));
break;
#endregion
#region 出入库方向电气申请变更
case 39:
if (devicestates[tempdb2addr + 0] != 1) continue;
break;
#endregion
#region 鸿安环穿主站
case 13:
//if (devicestates[tempdb2addr + 0] != 1) continue;
if (devinfo.UnControl == "1")
{//主站心跳
#region 心跳反馈和判断,把电气值+1
int xt = (devicestates[tempdb2addr + 0] << 8) + devicestates[tempdb2addr + 1];
//发送心跳
if (xt >= 30000) xt = 0;
devinfo.SendInterval = xt;
StringBuilder[] itemname; StringBuilder[] itemvalue;
itemname = new StringBuilder[1] { new StringBuilder("") };
itemname[0].Append(Model.CGeneralFunction.DBSend).Append(".").Append(devinfo.Dbw1Address).Append(",i");
itemvalue = new StringBuilder[1] { new StringBuilder("") };
itemvalue[0].Append(xt + 1);
CCommonOPCClient.Hostname = CommonClassLib.AppSettings.GetValue("HostName");
CCommonOPCClient.ProgID = CommonClassLib.AppSettings.GetValue("OPCProgID");
AsyncWriteAllItemValue(devinfo.S7Connection, itemname, itemvalue);
//AddBatchReponse(Model.CGeneralFunction.DBSend, 0, devidx, xt+1);
//CommonClassLib.CCarryConvert.WriteDarkCasket("OPCClient", "发送环穿主站心跳", devidx.ToString(), string.Format("收到心跳:{0},发送心跳:{1}",xt,xt+1));
#endregion
}
else
{
if (IsEquals(devinfo.ReturnMessage, states, states.Length) == false)
{//主站
#region 更新主站故障报警状态
int ies = (devicestates[tempdb2addr + 4] << 8) + devicestates[tempdb2addr + 5];
int isd = (devicestates[tempdb2addr + 6] << 8) + devicestates[tempdb2addr + 7];
int islg = (devicestates[tempdb2addr + 8] << 8) + devicestates[tempdb2addr + 9];
for (int hi = 0; hi <= 15; hi++)
{
devinfo.EmergencyStop[hi] = (ies & Convert.ToUInt16(Math.Pow(2, hi))) == Math.Pow(2, hi);//BIT0--BIT15代表#1..#16紧急停止状态BIT=0表示正常,BIT=1表示异常
devinfo.SafetyDoor[hi] = (isd & Convert.ToUInt16(Math.Pow(2, hi))) == Math.Pow(2, hi);//BIT0--BIT15代表#1..#16安全门状态BIT=0表示正常,BIT=1表示异常
devinfo.SafetyLightGrid[hi] = (islg & Convert.ToUInt16(Math.Pow(2, hi))) == Math.Pow(2, hi);// BIT0--BIT15代表#1..#16安全光栅状态BIT=0表示正常,BIT=1表示异常
}
#endregion
bc = GetBarcodeFromMonitorIndex(taskindex);
devinfo.ReturnMessage = states;
Model.CGetInfo.SetDeviceMessage(devinfo);
sss.Remove(0, sss.Length);
sss.Append("**条码:").Append(bc).Append("**读标志" + devicestates[tempdb2addr + 0]).Append("**状态" + state).Append("**任务号" + taskindex).Append("接收结果:").Append(devicestates[tempdb2addr + 3])
.Append("**列坐标" + xc);
CommonClassLib.CCarryConvert.WriteDarkCasket("OPCClient", "收到环穿主站状态", devidx.ToString(), sss.ToString());
//if (devicestates[tempdb2addr + 0] != 1) continue;//WCS可下命令
if ((devicestates[tempdb2addr + 1] <= 0) || (taskindex <= 0))
{//1:正常接收,解锁主站,接收下一个命令;2:任务异常
continue;
}
DeviceStateInfos[devidx].Append(string.Format("{0}#{1}", taskindex, devicestates[tempdb2addr + 1]));
//不需要回复数据AddBatchReponse("DB1", taskindex, devidx, state);
//cgs.GetKindDeviceState(taskindex, devidx, devicestates[tempdb2addr + 3]);
}
}
break;
#endregion
#region 鸿安环形穿梭车RGV
case 14:
if (devicestates[tempdb2addr + 0] != 1) continue;
#region 更新环形穿梭车光电开关状态
devinfo.SplitByte_0 = (devicestates[tempdb2addr + 8] & 1) == 1 ? 1 : 0;
devinfo.SplitByte_1 = (devicestates[tempdb2addr + 8] & 2) == 2 ? 1 : 0;
devinfo.SplitByte_2 = (devicestates[tempdb2addr + 8] & 4) == 4 ? 1 : 0;
devinfo.SplitByte_3 = (devicestates[tempdb2addr + 8] & 8) == 8 ? 1 : 0;
devinfo.SplitByte_4 = (devicestates[tempdb2addr + 8] & 16) == 16 ? 1 : 0;
devinfo.SplitByte_5 = (devicestates[tempdb2addr + 8] & 32) == 32 ? 1 : 0;
devinfo.SplitByte_6 = (devicestates[tempdb2addr + 8] & 64) == 64 ? 1 : 0;
devinfo.SplitByte_7 = (devicestates[tempdb2addr + 8] & 128) == 128 ? 1 : 0;
#endregion
Model.CGetInfo.SetDeviceInfo(devinfo);
if (IsEquals(devinfo.ReturnMessage, states, 4) == false)
{
bc = GetBarcodeFromMonitorIndex(taskindex);
xc = devicestates[tempdb2addr + 7] + (devicestates[tempdb2addr + 6] << 8) + (devicestates[tempdb2addr + 5] << 16) + (devicestates[tempdb2addr + 4] << 32);//X坐标
devinfo.ReturnMessage = states;
Model.CGetInfo.SetDeviceMessage(devinfo);
sss.Remove(0, sss.Length);
sss.Append("**条码:").Append(bc).Append("**读标志" + devicestates[tempdb2addr + 0]).Append("**状态" + state).Append("**任务号" + taskindex)
.Append("**列坐标" + xc);
CommonClassLib.CCarryConvert.WriteDarkCasket("OPCClient", "收到环穿RGV状态", devidx.ToString(), sss.ToString());
if (devicestates[tempdb2addr + 0] != 1) continue;
if ((state <= 0) || (taskindex <= 0))
{
continue;
}
AddBatchReponse(Model.CGeneralFunction.DBSend, taskindex, devidx, state);
DeviceStateInfos[devidx].Append(string.Format("{0}#{1}", taskindex, state));
//cgs.GetKindDeviceState(taskindex, devidx, state);
}
break;
#endregion
}
#endregion
}
#region 一个订阅组内设备按订阅ID deviceindex一批发送应答20230811richard.liu
StringBuilder[] itmenames = null; StringBuilder[] itmevalues = null;
StringBuilder[] sbDdeviceStateInfos = new StringBuilder[DeviceStateInfos.Count];
if (_opcSubsTagCount.ContainsKey(deviceindex.ToString()) == true)
{
itmenames = new StringBuilder[_opcSubsTagCount[deviceindex.ToString()]];
itmevalues = new StringBuilder[_opcSubsTagCount[deviceindex.ToString()]];
int deviceTagCount = 0;
if (_opcItemNamesDicInfo.Count > 0)
{
foreach (int devidx in _opcItemNamesDicInfo[deviceindex.ToString()].Keys)
{
Array.Copy(_opcItemNamesDicInfo[deviceindex.ToString()][devidx], 0, itmenames, deviceTagCount, _opcItemNamesDicInfo[deviceindex.ToString()][devidx].Length);
Array.Copy(_opcItemValuesDicInfo[deviceindex.ToString()][devidx], 0, itmevalues, deviceTagCount, _opcItemValuesDicInfo[deviceindex.ToString()][devidx].Length);
deviceTagCount += _opcItemNamesDicInfo[deviceindex.ToString()][devidx].Length;
}
}
}
int i = 0;
foreach (int devidx in DeviceStateInfos.Keys)
{
if (DeviceStateInfos[devidx].ToString().Split('#').Length > 2)
{
sbDdeviceStateInfos[i] = DeviceStateInfos[devidx];
i++;
}
}
if (i > 0 || itmenames != null)
{
StringBuilder[] sbDdeviceStateInfosNew = new StringBuilder[i];
Array.Copy(sbDdeviceStateInfos, sbDdeviceStateInfosNew, i);
CUpdateDBChangeEventArgs udbe = new CUpdateDBChangeEventArgs(deviceindex, sbDdeviceStateInfosNew, itmenames, itmevalues);
string ss = "";
for (int kk = 0; kk < sbDdeviceStateInfosNew.Length; kk++)
{
ss += sbDdeviceStateInfosNew[kk].ToString();
}
//CommonClassLib.CCarryConvert.WriteDarkCasket("OPCClient", "调用on", deviceindex.ToString(), ss);
OnPublishDeviceState("OPCClient.CCommonOPCClient.OnDataChange", udbe);
}
#endregion
}
#endregion
return true;
}
catch (Exception ex)
{
RefreshMonitorEventArgs rmea = new RefreshMonitorEventArgs("tsStatus", "CCommonOPCClient.DealWithDeviceState时" + ex.Message + ex.StackTrace);
OnRefreshMonitor(rmea);
errtext = ex.Message + ex.StackTrace;
return false;
}
finally
{
dvDevice.Dispose();
dvbc.Dispose();
dvPLCASK.Dispose();
}
}
}
#region 自定义方法
static string _stockCodeCheck = "^[B|D|G|P][A-Z][0-9]{4}$";
/// <summary>
/// 条码格式检查
/// </summary>
public static string StockCodeCheck
{
get { return _stockCodeCheck; }
set
{
int aa;
if (int.TryParse(_stockCodeCheck, out aa) == true)
{
_stockCodeCheck = value;
}
else
{
_stockCodeCheck = "^[B|D|G|P][A-Z][0-9]{4}$";
}
}
}
private static void AddBatchReponse(string DBBlock, int taskindex, int devidx, int state)
{
StringBuilder[] itemnames = new StringBuilder[0]; StringBuilder[] itemvalues = new StringBuilder[0];
try
{
devinfo = Model.CGetInfo.GetDeviceInfo(devidx);
int devKind = devinfo.DeviceKind;
if (DBBlock == "DB1")
{//根据devidx类型和state判断发送应答
if (state == 1)
{//运行
if ((devKind == 1)) //堆垛机
{
int[] sendmes = new int[10] { 0, 0, 0, devidx, 0, 0, 0, 0, 0, 0 };
devinfo = Model.CGetInfo.GetDeviceInfo(devidx);
if (IsEquals(devinfo.SendMessage, sendmes, 10) == false)
{
sdo = CommModeCreate.CreateSendDeviceOrder(devidx);
sdo.SendDeviceOrder(0, 0, 0, devidx, 0, 0, 0, 0, 0, 0, out itemnames, out itemvalues);
}
}
else if (devKind == 4 || devKind == 2)
{//输送机、RGV运行清零
int[] sendmes = new int[5] { 0, 0, 0, devidx, 0 };
devinfo = Model.CGetInfo.GetDeviceInfo(devidx);
if (devinfo.IfClearDB1 == "1" && IsEquals(devinfo.SendMessage, sendmes, 5) == false)
{
sdo = CommModeCreate.CreateSendDeviceOrder(devidx);
sdo.SendDeviceOrder(0, 0, 0, devidx, 0, out itemnames, out itemvalues);
}
}
}
else if (state == 2)
{//完成
if ((devKind == 1)) //堆垛机
{
sdo = CommModeCreate.CreateSendDeviceOrder(devidx);
sdo.SendDeviceOrder(2, 0, 0, devidx, 0, 0, 0, 0, 0, 0, out itemnames, out itemvalues);
}
else if (devKind == 14)
{//环穿小车应答任务号richard.liu20230718
sdo = CommModeCreate.CreateSendDeviceOrder(devidx);
sdo.SendDeviceOrder(2, taskindex, 99, devidx, 0, 0, 0, 0, 0, 0, out itemnames, out itemvalues);
}
else if (devKind == 4 || devKind == 2)
{//输送机、RGV
int taskRGV = 0;
//richard.liu20230718,增加给取货输送机发送环穿取货指令索引
object obt = dbo.GetSingle(string.Format("select F_CHANNELSINDEX from T_BASE_RGV_GATE, t_base_device where F_CHANNELSINDEX=f_deviceindex and f_devicekindindex=13 and F_RGVGATEDEVICEINDEX={0}", devidx));
if (obt != null)
{
obt = dbo.GetSingle(string.Format("select f_monitorindex from t_monitor_task where f_monitorindex >{0} and f_deviceindex= {1} order by f_monitorindex asc", taskindex, Convert.ToInt32(obt)));
if (obt != null)
{
taskRGV = Convert.ToInt32(obt);
}
}
sdo = CommModeCreate.CreateSendDeviceOrder(devidx);
sdo.SendDeviceOrder(2, taskRGV, 0, devidx, 0, out itemnames, out itemvalues);
}
else
{
//按state值发送应答
itemnames = new StringBuilder[1] { new StringBuilder() };
itemvalues = new StringBuilder[1] { new StringBuilder() };
itemnames[0].Append(DBBlock).Append(".").Append(Convert.ToString(devinfo.Dbw2Address + 0)).Append(",b");
itemvalues[0].Append(state);
}
}
else
{
if (devKind == 1) //堆垛机
{//报警,堆垛机清零去掉残留任务
int[] sendmes = new int[10] { 0, 0, 0, devidx, 0, 0, 0, 0, 0, 0 };
if (IsEquals(devinfo.SendMessage, sendmes, 10) == false)
{
sdo = CommModeCreate.CreateSendDeviceOrder(devidx);
sdo.SendDeviceOrder(0, 0, 0, devidx, 0, 0, 0, 0, 0, 0, out itemnames, out itemvalues);
}
}
else if (devKind == 13)
{//发送心跳,头99
sdo = CommModeCreate.CreateSendDeviceOrder(devidx);
sdo.SendDeviceOrder(99, 0, state, devidx, 0, 0, 0, 0, 0, 0, out itemnames, out itemvalues);
}
}
}
else if (DBBlock == "DB2")
{//按state值发送应答
itemnames = new StringBuilder[1] { new StringBuilder()};
itemvalues = new StringBuilder[1] { new StringBuilder() };
itemnames[0].Append(DBBlock).Append(".").Append(Convert.ToString(devinfo.Dbw2Address + 0)).Append(",b");
itemvalues[0].Append(state);
}
else
{
return;
}
//20230811richard.liu暂存标签数据
if (itemnames.Length > 0)
{
AddOPCSendData(devidx, itemnames, itemvalues);
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
}
}
/// <summary>
/// 暂存标签数据
/// </summary>
/// <param name="deviceIndex">设备编号</param>
/// <param name="itemnames">地址区标签名称数组</param>
/// <param name="itemvalues">标签值数组</param>
private static void AddOPCSendData(int deviceIndex, StringBuilder[] itemnames, StringBuilder[] itemvalues)
{//20230811richard.liu周期内按S7连接批量发送,重构CControl.cs,CCommonOPCClient.cs\DealWithDeviceState;文件夹Communication、Common内通讯CSendDeviceOrder: ISendDeviceOrder相关文件
try
{
devinfo = Model.CGetInfo.GetDeviceInfo(deviceIndex);
if (_opcItemNamesDicInfo.ContainsKey(devinfo.ReadSubscription))
{//添加OPC订阅组+dic 设备编码+数组 发送数据
if (_opcItemNamesDicInfo[devinfo.ReadSubscription].ContainsKey(devinfo.DeviceIndex) == false)
{
_opcSubsTagCount[devinfo.ReadSubscription] += itemnames.Length;
_opcItemNamesDicInfo[devinfo.ReadSubscription].Add(devinfo.DeviceIndex, itemnames);
_opcItemValuesDicInfo[devinfo.ReadSubscription].Add(devinfo.DeviceIndex, itemvalues);
}
}
else
{
Dictionary<int, StringBuilder[]> OPCDeviceSendtagNamedic = new Dictionary<int, StringBuilder[]>();
Dictionary<int, StringBuilder[]> OPCDeviceSendtagValuedic = new Dictionary<int, StringBuilder[]>();
OPCDeviceSendtagNamedic.Add(devinfo.DeviceIndex, itemnames);
OPCDeviceSendtagValuedic.Add(devinfo.DeviceIndex, itemvalues);
_opcSubsTagCount.Add(devinfo.ReadSubscription, itemnames.Length);
_opcItemNamesDicInfo.Add(devinfo.ReadSubscription, OPCDeviceSendtagNamedic);
_opcItemValuesDicInfo.Add(devinfo.ReadSubscription, OPCDeviceSendtagValuedic);
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
}
}
/// <summary>
/// 比较两个值型一维数组变量是否值相等
/// </summary>
/// <param name="array1">值型一维数组1</param>
/// <param name="array2">值型一维数组2</param>
/// <returns>比较结果,相等则true,否则false</returns>
static public bool IsEquals(Array array1, Array array2, int arraylength)
{//20090902新增加arraylength
//比较类型是否一样
if ((array1 == null) || (array2 == null)) return false;
if (!Object.ReferenceEquals(array1.GetType(), array2.GetType()))
{
return false;
}
//比较长度是否一样
if (array1.GetLength(0) != array2.GetLength(0))
{
return false;
}
//比较成员是否对应相等
ValueType v1, v2;
for (int i = 0; i < arraylength; i++)
{
v1 = (ValueType)array1.GetValue(i);
v2 = (ValueType)array2.GetValue(i);
if (!v1.Equals(v2))
{
return false;
}
}
return true;
}
static string GetBarcodeFromMonitorIndex(int taskindex)
{
DataView dvb = new DataView(); StringBuilder sss = new StringBuilder("");
try
{
sss.Append("SELECT F_TxtParam FROM T_Monitor_Task WHERE (F_MonitorIndex = ").Append(taskindex).Append(")");
dvb = dbo.ExceSQL(sss.ToString()).Tables[0].DefaultView;
if (dvb.Count > 0)
{
return dvb[0]["F_TxtParam"].ToString();
}
else
{
return "-";
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
dvb.Dispose();
}
}
#endregion
static private string _PLCconnectionID = "S7 connection_1";//OPC.UA的新写法"ns=2,S7 connection_1.db2.0,b,5"表示:"S7:[S7 connection_1]的db2.DBB0开始5个字节"
/// <summary>
/// 建立PLC连接的ID,例如:"S7:[S7 connection_1]"
/// 或者"S7:[@LOCALSERVER]"
/// </summary>
public static string PlcConnectionID
{
get { return CCommonOPCClient._PLCconnectionID; }
set { CCommonOPCClient._PLCconnectionID = value; }
}
static private string _opcError;
static private bool _IfConnectOPCServer=false ;
static private string _hostname;
/// <summary>
/// OPC Server的机器名称或者IP地址
/// </summary>
public static string Hostname
{
get { return CCommonOPCClient._hostname; }
set { CCommonOPCClient._hostname = value; }
}
static private string _progID;
/// <summary>
/// OPC Server的程序标识,例如:OPC.SimaticNET
/// </summary>
public static string ProgID
{
get { return CCommonOPCClient._progID; }
set { CCommonOPCClient._progID = value; }
}
public static string OpcError
{
get { return CCommonOPCClient._opcError; }
set {
CCommonOPCClient._opcError = value;
RefreshMonitorEventArgs rme = new RefreshMonitorEventArgs("tsStatus", _opcError);
OnRefreshMonitor(rme);
}
}
/// <summary>
/// 《设备索引,对应设备订阅》
/// </summary>
public static SubscriptionCollection SubscriptionGroup = new SubscriptionCollection();//定义组对象集合(订阅者集合)//20110309
/// <summary>
/// 20110309每个设备创建一个订阅和DataChange事件
/// </summary>
public static void CreateSubscriptionGroup()
{
if (_IfConnectOPCServer == false)
{
_hostname = CommonClassLib.AppSettings.GetValue("HostName");
_progID = CommonClassLib.AppSettings.GetValue("OPCProgID");
if (ConnectOPCServer(_hostname, _progID) == false) return ;
}
//DataView dv = dbo.ExceSQL("SELECT F_ReadSubscription, F_DeviceIndex, F_DBW2Address, F_DBWGetLength, F_S7Connection, F_SplitByte FROM T_Base_Device WHERE (F_ReadSubscription IS NOT NULL) AND (F_ReadSubscription =F_DeviceIndex) and ((f_localport!=3 and f_localport!=4 and f_localport!=7 and f_localport!=10) or f_devicekindindex=2) ORDER BY F_ReadSubscription").Tables[0].DefaultView;
DataView dv = dbo.ExceSQL("SELECT F_ReadSubscription, F_DeviceIndex, F_DBW2Address, F_DBWGetLength, F_S7Connection, F_SplitByte FROM T_Base_Device WHERE (F_ReadSubscription IS NOT NULL) AND (F_ReadSubscription =F_DeviceIndex) ORDER BY F_ReadSubscription").Tables[0].DefaultView;
if (dv.Count > 0)
{
if (dv.Count < SubscriptionGroup.Count) return;
}
DataView dvx;
for (int i = 0; i < dv.Count; i++)
{
string dt = DateTime.Now.Minute.ToString() + "-" + DateTime.Now.Second.ToString() + "-" + DateTime.Now.Millisecond.ToString();
dvx = dbo.ExceSQL(string.Format("SELECT (MAX(F_DBW2Address) + F_DBWGetLength) as maxdbw2 FROM T_Base_Device WHERE (F_ReadSubscription = {0}) AND (F_DeviceKindIndex != 33) GROUP BY F_DBWGetLength ORDER BY maxdbw2 DESC", dv[i]["F_ReadSubscription"])).Tables[0].DefaultView;
if (dvx.Count > 0)
{
NodeId nodeId;
if (dv[i]["F_S7Connection"].ToString() == "@localserver"|| (Convert.ToInt32(dv[i]["F_DeviceIndex"])>=34091&& Convert.ToInt32(dv[i]["F_DeviceIndex"]) <= 34100))
{
nodeId = new NodeId(dv[i]["F_S7Connection"].ToString() + "." +
"DB1" + "." +
dv[i]["F_DBW2Address"].ToString() + ",b," +
(System.Convert.ToInt32(System.Convert.ToInt32(dvx[0]["maxdbw2"]) - System.Convert.ToInt32(dv[i]["F_DBW2Address"]))).ToString(), S7NameSpace);
}
else
{
nodeId = new NodeId(dv[i]["F_S7Connection"].ToString() + "." +
Model.CGeneralFunction.DBGet + "." +
dv[i]["F_DBW2Address"].ToString() + ",b," +
(System.Convert.ToInt32(System.Convert.ToInt32(dvx[0]["maxdbw2"]) - System.Convert.ToInt32(dv[i]["F_DBW2Address"]))).ToString(), S7NameSpace);//20151120
}
// Add the attribute name/value to the list view.
object serverHandle = null;
try
{
// Add the item and apply any changes to it.
m_Subscription.AddDataMonitoredItem(nodeId, dv[i]["F_ReadSubscription"].ToString(), OnDataChange, 700, out serverHandle);
}
catch (ServiceResultException monitoredItemResult)
{
OpcError = "建立OPC订阅组时:" + monitoredItemResult.Message;
if (ConnectCount.ContainsKey(dv[i]["F_S7Connection"].ToString()) == false)//20110726
{
ConnectCount.Add(dv[i]["F_S7Connection"].ToString(), 1);
}
else
{
ConnectCount[dv[i]["F_S7Connection"].ToString()]++;
}
}
}
}
dv = dbo.ExceSQL("SELECT F_ReadSubscription, F_DeviceIndex, F_DBW2Address, F_DBWGetLength, F_S7Connection, F_SplitByte FROM T_Base_Device WHERE (F_ReadSubscription IS NOT NULL) AND (F_DeviceKindIndex=33) ORDER BY F_ReadSubscription").Tables[0].DefaultView;
for (int i = 0; i < dv.Count; i++)
{
NodeId nodeId = new NodeId(dv[i]["F_S7Connection"].ToString() + "." +
Model.CGeneralFunction.DBGet + "." +
dv[i]["F_DBW2Address"].ToString() + ",b," + System.Convert.ToInt32(dv[i]["F_DBWGetLength"]).ToString(), S7NameSpace);//20151120
// Add the attribute name/value to the list view.
object serverHandle = null;
try
{
// Add the item and apply any changes to it.
m_Subscription.AddDataMonitoredItem(nodeId, "split" + dv[i]["F_ReadSubscription"].ToString(), OnDataChange, 100, out serverHandle);
}
catch (ServiceResultException monitoredItemResult)
{
OpcError = "建立OPC订阅组时:" + monitoredItemResult.Message;
if (ConnectCount.ContainsKey(dv[i]["F_S7Connection"].ToString()) == false)//20110726
{
ConnectCount.Add(dv[i]["F_S7Connection"].ToString(), 1);
}
else
{
ConnectCount[dv[i]["F_S7Connection"].ToString()]++;
}
}
}
}
/// <summary>
/// 通过设置订阅的监控模式,刷新订阅
/// </summary>
/// <returns></returns>
public static bool RefreshMonitoringMode()
{//20150103增加断网恢复
if (m_Subscription != null)
{
m_Subscription.RefreshMonitoringMode();
}
return true;
}
/// <summary>
/// 连接指定主机的OPC服务器
/// </summary>
/// <param name="hostname">主机名称</param>
/// <param name="ProgID">OPC服务器程序标识例如:"OPC.SimaticNET"</param>
/// <returns></returns>
public static bool ConnectOPCServer(string hostname, string ProgID)
{
try
{
if (ConnectCount.ContainsKey(_PLCconnectionID) == false)//20110726
{
ConnectCount.Add(_PLCconnectionID, 0);
}
if (ConnectCount[_PLCconnectionID] > 1)//20150204
{
_opcError = "WCS没连接到OPC Server:" + _PLCconnectionID.ToString() + ",人工确认后进行【PLC初始化】";//20150204
return false ;
}
//Uri discoveryUrl = new Uri("opc.tcp://" + hostname + ":4845");
Uri discoveryUrl = new Uri("opc.tcp://" + hostname + ":55101");
Discovery discovery = new Discovery();
EndpointDescriptionCollection endpoints = null;
string rr = discovery.GetEndpoints(discoveryUrl, ref endpoints);
if(endpoints == null)
{
if (ConnectCount.ContainsKey(_PLCconnectionID) == false)//20110726
{
ConnectCount.Add(_PLCconnectionID, 0);
}
ConnectCount[_PLCconnectionID]++;
OpcError = "连接OPC数据存取服务器时:GetEndpoints没找到OPC服务器!";
_IfConnectOPCServer = false;
return false;
}
for (int i = 0; i < endpoints.Count; i++)
{
endpoints[i].EndpointUrl = discoveryUrl.ToString();
if ((endpoints[i].Server.ApplicationName.Text.IndexOf( ProgID)>-1)
&& (endpoints[i].SecurityMode == MessageSecurityMode.None))//20151120
{
m_Server = new Server();
m_Server.CertificateEvent += new certificateValidation(m_Server_CertificateEvent);
m_Server.Connect(endpoints[i]);
_IfConnectOPCServer = true;
if (m_Subscription == null)
{
m_Subscription = m_Server.AddSubscription(100);
}
#region 自动读取“S7:”的命名空间索引//20151120
DataValueCollection m_currentValues;
NodeId nodeId=new NodeId(2255);
NodeIdCollection nodesToRead = new NodeIdCollection(1);
nodesToRead.Add(nodeId);
m_Server.ReadValues(nodesToRead, out m_currentValues);
if (m_currentValues.Count > 0)
{
string[] arr;
arr =(string[]) m_currentValues[0].Value;
S7NameSpace =(ushort) Array.IndexOf(arr, "S7:");
}
#endregion
return true;
}
}
if (ConnectCount.ContainsKey(_PLCconnectionID) == false)//20110726
{
ConnectCount.Add(_PLCconnectionID, 0);
}
ConnectCount[_PLCconnectionID]++;
OpcError = "连接OPC数据存取服务器时:配置项OPCProgID和HostName不准确!";
_IfConnectOPCServer = false;
return false;
}
catch (Exception ex)
{
if (ConnectCount.ContainsKey(_PLCconnectionID) == false)//20110726
{
ConnectCount.Add(_PLCconnectionID, 0);
}
ConnectCount[_PLCconnectionID]++;
OpcError = "连接OPC数据存取服务器时:" + ex.Message;
_IfConnectOPCServer = false;
return false;
}
}
public static DataValueCollection SyncReadAllItemValue(StringBuilder[] itemnames)
{
DataValueCollection m_currentValues;
if (_IfConnectOPCServer == false)
{
if (ConnectOPCServer(_hostname, _progID) == false) return null;
}
NodeIdCollection nodesToRead = new NodeIdCollection(itemnames.GetLength(0));
foreach (StringBuilder item in itemnames)
{
// NodeIds.
String sNodeId = _PLCconnectionID + "." + item.ToString();
NodeId nodeId = new NodeId(sNodeId,S7NameSpace);//20151120
nodesToRead.Add(nodeId);
}
// Call to ClientAPI.
m_Server.ReadValues(
nodesToRead,
out m_currentValues);
return m_currentValues;
}
public static bool SyncWriteAllItemValue(StringBuilder[] itemnames, StringBuilder[] itemvalues)
{
try
{
if (ConnectCount.ContainsKey(_PLCconnectionID) == false)//20110726
{
ConnectCount.Add(_PLCconnectionID, 0);
}
if (ConnectCount[_PLCconnectionID] > 1)//20150204
{
return false;
}
if (_IfConnectOPCServer == false)
{
if (ConnectOPCServer(_hostname, _progID) == false) return false;
}
NodeIdCollection nodesToWrite = new NodeIdCollection(itemnames.GetLength(0));
DataValueCollection values = new DataValueCollection(itemnames.GetLength(0));
StatusCodeCollection results = null;
int i = 0;
foreach (StringBuilder item in itemnames)
{
// Values to write.
String sValue = itemvalues[i].ToString();
// Leave current value if write value is empty.
if (sValue.Length == 0)
{
i++;
continue;
}
#region win7等64位操作系统需要指定确切的数据类型//20151120
Type gt = typeof(byte);
if (item.ToString().IndexOf(",b") >= 0)//无符号字节型0--255
{
gt = typeof(byte);
}
else if (item.ToString().IndexOf(",i") >= 0)//short:有符号两个字节的单字-32768至32767
{
gt = typeof(short);
}
else if (item.ToString().IndexOf(",w") >= 0)//ushort:无符号两个字节的单字0至65535
{
gt = typeof(ushort);
}
else if (item.ToString().IndexOf(",di") >= 0)//int:有符号四个字节的双字-2147483648至2147483647
{
gt = typeof(int);
}
else if (item.ToString().IndexOf(",dw") >= 0)//uint:无符号四个字节的双字0至4294967295
{
gt = typeof(uint);
}
else if (item.ToString().IndexOf(",dt") >= 0)//DateTime:日期和时间类型:05/31/2016 08:21:10.123 PM
{
gt = typeof(DateTime);
}
Variant variant = new Variant(Convert.ChangeType(sValue, gt));
#endregion
DataValue value = new DataValue(variant);
values.Add(value);
// NodeIds.
String sNodeId =_PLCconnectionID+"."+ item.ToString();
NodeId nodeId = new NodeId(sNodeId, S7NameSpace); //20151120
nodesToWrite.Add(nodeId);
i++;
}
// Call to ClientAPI.
m_Server.WriteValues(
nodesToWrite,
values,
out results);
int ia = 0;//richard.liu20141110
foreach (StatusCode sc in results)
{//richard.liu20141110
if (sc.Code != StatusCodes.Good)
{
ConnectCount[_PLCconnectionID]++;//20150204
OpcError =string.Format( "向OPC数据存取服务器写数据时,WriteValues:{0},{1}" ,nodesToWrite[ia].ToString() , "的返回值有错误!"+sc.ToString());
return false;
}
ia++;
}
ConnectCount[_PLCconnectionID] = 0;//20150204
return true;
}
catch (Exception ex)
{
ConnectCount[_PLCconnectionID]++;//20150204
OpcError =string.Format( "向OPC数据存取服务器写数据时:{0},{1}" , ex.Message,ex.StackTrace);
_IfConnectOPCServer = false;
return false;
}
}
//以异步的方式写入OPC数据
public static bool AsyncWriteAllItemValue(string _PLCconnectionID,StringBuilder[] itemnames, StringBuilder[] itemvalues)
{
lock (thisLock)////20130306richard.liu
{
try
{
if (_IfConnectOPCServer == false)
{
if (ConnectOPCServer(_hostname, _progID) == false) return false;
}
if (ConnectCount.ContainsKey(_PLCconnectionID) == false)//20110726
{
ConnectCount.Add(_PLCconnectionID, 0);
}
if (ConnectCount[_PLCconnectionID] > 3)//20150204
{
_opcError = "写数据时:OPC Server没连接到PLC:" + _PLCconnectionID.ToString() + ",人工确认后进行【PLC初始化】";//20150204
return false;
}
NodeIdCollection nodesToWrite = new NodeIdCollection(itemnames.GetLength(0));
DataValueCollection values = new DataValueCollection(itemnames.GetLength(0));
StatusCodeCollection results = null;
int i = 0;
foreach (StringBuilder item in itemnames)
{
// Values to write.
String sValue = itemvalues[i].ToString();
// Leave current value if write value is empty.
if (sValue.Length == 0)
{
i++;
continue;
}
#region win7等64位操作系统需要指定确切的数据类型//20151120
Type gt = typeof(byte);
if (item.ToString().IndexOf(",b") >= 0)//无符号字节型0--255
{
gt = typeof(byte);
}
else if (item.ToString().IndexOf(",i") >= 0)//short:有符号两个字节的单字-32768至32767
{
gt = typeof(short);
}
else if (item.ToString().IndexOf(",w") >= 0)//ushort:无符号两个字节的单字0至65535
{
gt = typeof(ushort);
}
else if (item.ToString().IndexOf(",di") >= 0)//int:有符号四个字节的双字-2147483648至2147483647
{
gt = typeof(int);
}
else if (item.ToString().IndexOf(",dw") >= 0)//uint:无符号四个字节的双字0至4294967295
{
gt = typeof(uint);
}
else if (item.ToString().IndexOf(",dt") >= 0)//DateTime:日期和时间类型:05/31/2016 08:21:10.123 PM
{
gt = typeof(DateTime);
}
Variant variant = new Variant(Convert.ChangeType(sValue, gt));
#endregion
DataValue value = new DataValue(variant);
values.Add(value);
// NodeIds.
String sNodeId = _PLCconnectionID + "." + item.ToString();
NodeId nodeId = new NodeId(sNodeId, S7NameSpace); //20151120
nodesToWrite.Add(nodeId);
i++;
}
// Call to ClientAPI.
m_Server.BeginWriteValues(
nodesToWrite,
values,
out results);
//results返回值一直为null,异常在ClientAPI writeCallBack处理后赋给OpcError
ConnectCount[_PLCconnectionID] = 0;//20150204
return true;
}
catch (Exception ex)
{
ConnectCount[_PLCconnectionID]++;//20150204
OpcError =string.Format( "向OPC数据存取服务器写数据时:{0},{1}", ex.Message,ex.StackTrace);
_IfConnectOPCServer = false;
return false;
}
}
}
/// <summary>
/// 获得设备类型索引
/// </summary>
/// <param name="devIdx">设备索引</param>
/// <returns>设备类型索引</returns>
static int GetDeviceKindIdx(int devIdx)
{
System.Object lockThis = new System.Object();
lock (lockThis)
{
try
{
DataView dv= dbo.ExceSQL(string.Format("SELECT F_DeviceKindIndex FROM T_Base_Device WHERE F_DeviceIndex={0}", devIdx)).Tables[0].DefaultView;
if (dv.Count > 0)
{
return System.Convert.ToInt32(dv[0]["F_DeviceKindIndex"]);
}
else
return 0;
}
catch (Exception ex)
{
throw ex;
}
}
}
public static void DisConnectOPCServer()
{
try
{
int result;
if (m_Server == null) return;
result = m_Server.Disconnect();
// Disconnect succeeded.
if (result == 0)
{
m_Subscription.RemoveAllMonitoredItems();//20150103增加断网恢复
m_Server.RemoveSubscription(m_Subscription);
m_Subscription = null;
}
_IfConnectOPCServer = false;//20140514张博在山东电力发现此问题
}
catch (Exception ex)
{
OpcError = "关闭OPC数据存取服务器时:" + ex.Message;
}
}
static void m_Server_CertificateEvent(CertificateValidator validator, CertificateValidationEventArgs e)
{
e.Accept = true;
}
}
}