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.
370 lines
15 KiB
370 lines
15 KiB
1 month ago
|
using System;
|
||
|
using System.Collections.Generic;
|
||
|
using System.Linq;
|
||
|
using System.Text;
|
||
|
using Snap7;
|
||
|
using Model;
|
||
|
using DBFactory;
|
||
|
using System.Data;
|
||
|
using Snap7Client;
|
||
|
|
||
|
namespace Snap7Server
|
||
|
{
|
||
|
public static class CSnap7Server
|
||
|
{
|
||
|
public static object obj = new object();
|
||
|
private static S7Server.TSrvCallback TheEventCallBack; // <== Static var containig the callback
|
||
|
private static S7Server.TSrvCallback TheReadCallBack;
|
||
|
|
||
|
private static Dictionary<string, S7Server> server_dic = new Dictionary<string, S7Server>();//ip与s7server
|
||
|
private static Dictionary<string, int> callback_para = new Dictionary<string, int>();//plc名与ip
|
||
|
private static Dictionary<string, byte[]> db1_dic = new Dictionary<string, byte[]>();//ip与db1
|
||
|
private static Dictionary<string, byte[]> db2_dic = new Dictionary<string, byte[]>();//ip与db2
|
||
|
private static Dictionary<string, int[]> db_length = new Dictionary<string, int[]>();//ip与每个设备的db长度
|
||
|
|
||
|
|
||
|
public static Dictionary<string, List<int>> conveyorRouteList = new Dictionary<string, List<int>>();//Task 的所有输送机
|
||
|
public static Dictionary<string, Queue<MDevice>> taskDeviceList = new Dictionary<string, Queue<MDevice>>();//Task 的所有设备
|
||
|
|
||
|
public static DBOperator dbo = new DBOperator();
|
||
|
static StringBuilder sql = new StringBuilder();
|
||
|
|
||
|
public static void InitSnap7Server()
|
||
|
{
|
||
|
//根据数据库初始化字典,
|
||
|
sql.Remove(0, sql.Length);
|
||
|
sql.Append("select distinct F_RemoteIP from T_Base_Device where (F_RemoteIP is not null) ");
|
||
|
DataView dv = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
|
||
|
|
||
|
for (int i=0; i<dv.Count; i++)
|
||
|
{
|
||
|
Callback_para.Add(dv[i]["F_RemoteIP"].ToString(), i);
|
||
|
initServer(dv[i]["F_RemoteIP"].ToString());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private static void initServer(string IP)
|
||
|
{
|
||
|
//数据库中 db1 / db2 的长度
|
||
|
int db1_length = 0, db2_length = 0;
|
||
|
db1_length = Snap7Client.CCommonSnap7Client.GetDB1Length(IP);
|
||
|
db2_length = Snap7Client.CCommonSnap7Client.GetDB2Length(IP);
|
||
|
|
||
|
//选择最大的值进行初始化
|
||
|
if (db1_length != 0 || db2_length != 0)
|
||
|
{
|
||
|
int len = db1_length > db2_length ? db1_length : db2_length;
|
||
|
byte[] db1_temp = new byte[len];
|
||
|
byte[] db2_temp = new byte[len];
|
||
|
for (int i=0; i<len; i++)
|
||
|
{
|
||
|
db1_temp[i] = 0;
|
||
|
db2_temp[i] = 0;
|
||
|
}
|
||
|
|
||
|
Db1_dic.Add(IP, db1_temp);
|
||
|
Db2_dic.Add(IP, db2_temp);
|
||
|
}
|
||
|
|
||
|
// 对堆垛机的 XY 坐标初始化
|
||
|
sql.Remove(0, sql.Length);
|
||
|
sql.Append("SELECT F_DeviceIndex, F_DBW2Address FROM T_Base_Device WHERE F_DeviceKindIndex = 1 and F_RemoteIP = '" + IP + "' order by F_DBW2Address");
|
||
|
DataView dv = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
|
||
|
for (int i = 0; i < dv.Count; i++)
|
||
|
{
|
||
|
Db2_dic[IP][Convert.ToInt32(dv[i]["F_DBW2Address"].ToString()) + 7] = 1; //X坐标为1
|
||
|
Db2_dic[IP][Convert.ToInt32(dv[i]["F_DBW2Address"].ToString()) + 11] = 1; //Y坐标为1
|
||
|
|
||
|
//Db2_dic[IP][Convert.ToInt32(dv[i]["F_DBW2Address"].ToString()) + 12] = 1;
|
||
|
//Db2_dic[IP][Convert.ToInt32(dv[i]["F_DBW2Address"].ToString()) + 13] = 1;
|
||
|
}
|
||
|
// 对取放货站台的光电信息初始化,.3,.4
|
||
|
sql.Remove(0, sql.Length);
|
||
|
sql.Append("SELECT F_DeviceIndex, F_DBW2Address FROM T_Base_Device WHERE F_DeviceIndex in (SELECT F_LaneGateDeviceIndex FROM T_Base_Lane_Gate ) order by F_DBW2Address");
|
||
|
dv = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
|
||
|
for (int i = 0; i < dv.Count; i++)
|
||
|
{
|
||
|
Db2_dic[IP][Convert.ToInt32(dv[i]["F_DBW2Address"].ToString()) + 4] = 8 + 16; //X坐标为1
|
||
|
|
||
|
}
|
||
|
|
||
|
sql.Remove(0, sql.Length);
|
||
|
sql.Append("SELECT F_DBW2Address, F_DBWGetLength FROM T_Base_Device WHERE F_DBW2Address is not NULL and F_RemoteIP = '" + IP + "' order by F_DBW2Address");
|
||
|
dv = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
|
||
|
int[] length = new int[dv.Count];
|
||
|
for (int i=0; i< dv.Count; i++)
|
||
|
{
|
||
|
if (i != dv.Count-1)
|
||
|
{
|
||
|
length[i] = Convert.ToInt32(dv[i + 1]["F_DBW2Address"]) - Convert.ToInt32(dv[i]["F_DBW2Address"]);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
length[i] = Convert.ToInt32(dv[i]["F_DBWGetLength"]);
|
||
|
}
|
||
|
}
|
||
|
Db_length.Add(IP, length);
|
||
|
|
||
|
S7Server s7 = createSnap7Server(IP);
|
||
|
Server_dic.Add(IP, s7);
|
||
|
}
|
||
|
|
||
|
private static S7Server createSnap7Server(string IP)
|
||
|
{
|
||
|
S7Server s7 = new S7Server();
|
||
|
byte[] DB1 = Db1_dic[IP];
|
||
|
byte[] DB2 = Db2_dic[IP];
|
||
|
|
||
|
// Share some resources with our virtual PLC
|
||
|
s7.RegisterArea(S7Server.srvAreaDB, // We are registering a DB
|
||
|
1, // Its number is 1 (DB1)
|
||
|
ref DB1, // Our buffer for DB1
|
||
|
DB1.Length); // Its size
|
||
|
// Do the same for DB2 and DB3
|
||
|
s7.RegisterArea(S7Server.srvAreaDB, 2, ref DB2, DB2.Length);
|
||
|
|
||
|
// Exclude read event to avoid the double report
|
||
|
// Set the callbacks (using the static var to avoid the garbage collect)
|
||
|
TheEventCallBack = new S7Server.TSrvCallback(EventCallback);
|
||
|
TheReadCallBack = new S7Server.TSrvCallback(ReadEventCallback);
|
||
|
s7.EventMask = ~S7Server.evcDataRead;
|
||
|
//int num = 0;
|
||
|
|
||
|
s7.SetEventsCallBack(TheEventCallBack, new IntPtr(Callback_para[IP]));
|
||
|
s7.SetReadEventsCallBack(TheReadCallBack, new IntPtr(Callback_para[IP]));
|
||
|
|
||
|
|
||
|
|
||
|
string _ip = IP.Split(':')[0];
|
||
|
string local = "127.0.0.1";
|
||
|
int Error = s7.StartTo(_ip);
|
||
|
|
||
|
return s7;
|
||
|
}
|
||
|
static Model.MDevice askDevinfo;
|
||
|
|
||
|
public static Dictionary<string, S7Server> Server_dic { get => server_dic; set => server_dic = value; }
|
||
|
public static Dictionary<string, byte[]> Db1_dic { get => db1_dic; set => db1_dic = value; }
|
||
|
public static Dictionary<string, byte[]> Db2_dic { get => db2_dic; set => db2_dic = value; }
|
||
|
public static Dictionary<string, int[]> Db_length { get => db_length; set => db_length = value; }
|
||
|
public static Dictionary<string, int> Callback_para { get => callback_para; set => callback_para = value; }
|
||
|
public static Dictionary<string, List<int>> ConveyorRouteList { get => conveyorRouteList; set => conveyorRouteList = value; }
|
||
|
|
||
|
|
||
|
|
||
|
//根据设备号,获取DB1
|
||
|
|
||
|
//根据设备号,获取DB2
|
||
|
|
||
|
//根据设备号,返回设备信息
|
||
|
public static Model.MDevice GetDeviceInfo(int DeviceIndex)
|
||
|
{
|
||
|
return Model.CGetInfo.GetDeviceInfo(DeviceIndex);
|
||
|
}
|
||
|
|
||
|
//根据设备号,自动改变状态,
|
||
|
public static bool AutoChangeAllState(int DeviceIndex)
|
||
|
{
|
||
|
foreach(var ip in Db2_dic.Keys)
|
||
|
{
|
||
|
foreach(var device in CGetInfo.DeviceInfo.Values)
|
||
|
{
|
||
|
if(device.RemoteIP == ip)
|
||
|
{
|
||
|
//if
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
//根据设备号,清零 DB2
|
||
|
public static void ClearDeviceDB2(int DeviceIndex)
|
||
|
{
|
||
|
askDevinfo = GetDeviceInfo(DeviceIndex);
|
||
|
|
||
|
//for (int i=askDevinfo.Dbw2Address; i<askDevinfo.Dbw2Address+askDevinfo.Dbw2Getlength; i++)
|
||
|
for (int i=askDevinfo.Dbw2Address; i<askDevinfo.Dbw2Address+4; i++)
|
||
|
{
|
||
|
Db2_dic[askDevinfo.RemoteIP][i] = 0;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
//根据设备号,改变设备状态(参数)
|
||
|
public static void ChangeDeviceDate(int DeviceIndex, int State)
|
||
|
{
|
||
|
askDevinfo = GetDeviceInfo(DeviceIndex);
|
||
|
Db2_dic[askDevinfo.RemoteIP][askDevinfo.Dbw2Address + 1] = (byte)State;
|
||
|
}
|
||
|
|
||
|
|
||
|
static void EventCallback(IntPtr usrPtr, ref S7Server.USrvEvent Event, int Size)
|
||
|
{
|
||
|
//Console.WriteLine(Server.EventText(ref Event));
|
||
|
//var temp = Server.EventText(ref Event);
|
||
|
//Form1.MainForm.listBox1.Items.Add(num2server[usrPtr.ToInt32()].EventText(ref Event));
|
||
|
|
||
|
}
|
||
|
|
||
|
static void ReadEventCallback(IntPtr usrPtr, ref S7Server.USrvEvent Event, int Size)
|
||
|
{
|
||
|
//Console.WriteLine(Server.EventText(ref Event));
|
||
|
}
|
||
|
|
||
|
// 将 DB1 的信息复制到 DB2
|
||
|
//public static void
|
||
|
|
||
|
// 根据 IP 和 db2 的开始地址,从数据库中找到该设备
|
||
|
public static int getDevice(string ip, int dbAddress, out int devKind)
|
||
|
{
|
||
|
devKind = 0;
|
||
|
sql.Remove(0, sql.Length);
|
||
|
sql.Append("select F_DeviceIndex, F_DeviceKindIndex from T_Base_Device where (F_RemoteIP='" + ip + "' and F_DBW2Address=" + dbAddress + ")");
|
||
|
DataView dv = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
|
||
|
if (dv.Count > 0)
|
||
|
{
|
||
|
devKind = Convert.ToInt32(dv[0]["F_DeviceKindIndex"].ToString());
|
||
|
return Convert.ToInt32(dv[0]["F_DeviceIndex"].ToString());
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
public static void initTaskRoute(string task)
|
||
|
{
|
||
|
if (ConveyorRouteList.ContainsKey(task) == true) return;
|
||
|
sql.Remove(0, sql.Length);
|
||
|
sql.Append("select FCONTROLTASKTYPE from T_Manage_Task, T_Monitor_task where fid = F_ManageTaskIndex and F_MonitorIndex = '" + task + "'");
|
||
|
DataView dv = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
|
||
|
string nextDeviceName = "";
|
||
|
if (dv.Count > 0)
|
||
|
{
|
||
|
int type = Convert.ToInt32(dv[0]["FCONTROLTASKTYPE"].ToString());
|
||
|
if (type == 1)
|
||
|
{
|
||
|
nextDeviceName = "F_InputNextDevice";
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
nextDeviceName = "F_OutputNextDevice";
|
||
|
}
|
||
|
}
|
||
|
sql.Remove(0, sql.Length);
|
||
|
sql.Append("select F_NumParam1,F_NumParam4 from T_Monitor_Task where F_MonitorIndex = '" + task + "'");
|
||
|
dv = dbo.ExceSQL(sql.ToString()).Tables[0].DefaultView;
|
||
|
int startDev = 0; int endDev = 0;
|
||
|
if (dv.Count > 0)
|
||
|
{
|
||
|
startDev = Convert.ToInt32(dv[0]["F_NumParam1"].ToString());
|
||
|
endDev = Convert.ToInt32(dv[0]["F_NumParam4"].ToString());
|
||
|
List<List<int>> devs = RecursionDevices(startDev, endDev, nextDeviceName);
|
||
|
|
||
|
if (devs.Count > 0)
|
||
|
{
|
||
|
if (conveyorRouteList.ContainsKey(task.ToString()) == false)
|
||
|
{
|
||
|
conveyorRouteList.Add(task.ToString(), devs[0]);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
|
||
|
public static List<List<int>> RecursionDevices(int startdev, int enddev, string IONextDevice)
|
||
|
{
|
||
|
string sql = "";
|
||
|
DataView dv;
|
||
|
string nextdev = "";
|
||
|
string[] spl;
|
||
|
char[] cc = new char[1] { ';' };
|
||
|
List<List<int>> routedevs = new List<List<int>>();
|
||
|
sql = "SELECT " + IONextDevice + " FROM T_Base_Device where F_DeviceIndex=" + startdev;
|
||
|
dv = dbo.ExceSQL(sql).Tables[0].DefaultView;
|
||
|
if (dv.Count > 0)
|
||
|
{
|
||
|
nextdev = dv[0][IONextDevice].ToString();
|
||
|
|
||
|
if (nextdev.Length > 0)
|
||
|
{
|
||
|
spl = nextdev.Split(cc);
|
||
|
for (int i = spl.GetLowerBound(0); i <= spl.GetUpperBound(0); i++)
|
||
|
{
|
||
|
if (routedevs.Count != 0 && routedevs[0].Contains(enddev) == true)
|
||
|
return routedevs;
|
||
|
List<List<int>> rs = RecursionSingle(Convert.ToInt32(spl[i]), enddev, IONextDevice);
|
||
|
if (rs.Count > 0)
|
||
|
{
|
||
|
//返回多条路经设备集合的集合
|
||
|
List<int> rss = new List<int>();
|
||
|
for (int ii = 0; ii < rs.Count; ii++)
|
||
|
{
|
||
|
rss = rs[ii];
|
||
|
if (rss.Contains(Convert.ToInt32(spl[i])) == false)
|
||
|
{
|
||
|
rss.Add(Convert.ToInt32(spl[i]));
|
||
|
}
|
||
|
if (rss.Contains(startdev) == false)
|
||
|
{
|
||
|
rss.Add(startdev);
|
||
|
}
|
||
|
if (routedevs.Contains(rss) == false)
|
||
|
{
|
||
|
routedevs.Add(rss);
|
||
|
}
|
||
|
} //Predicate<List<int>> FindValue = delegate(List<int> obj) { return obj.Contains(Convert.ToInt32(spl[i])); };
|
||
|
}
|
||
|
}
|
||
|
return routedevs;
|
||
|
}
|
||
|
}
|
||
|
return routedevs;
|
||
|
}
|
||
|
static List<List<int>> RecursionSingle(int startdev, int enddev, string IONextDevice)
|
||
|
{
|
||
|
|
||
|
char[] cc = new char[1] { ';' };
|
||
|
List<int> routedevs = new List<int>();
|
||
|
List<List<int>> mutiRoute = new List<List<int>>();
|
||
|
|
||
|
#region 递归获得多条路径详细设备集合
|
||
|
|
||
|
if (startdev == enddev)//找到了终点设备
|
||
|
{
|
||
|
if (routedevs.Contains(enddev) == false)
|
||
|
{
|
||
|
routedevs.Add(enddev);
|
||
|
}
|
||
|
if (routedevs.Contains(startdev) == false)
|
||
|
{
|
||
|
routedevs.Add(startdev);
|
||
|
}
|
||
|
mutiRoute.Add(routedevs);
|
||
|
return mutiRoute;
|
||
|
}
|
||
|
else//接着找
|
||
|
{
|
||
|
|
||
|
List<List<int>> mutireturndevs = RecursionDevices(startdev, enddev, IONextDevice);
|
||
|
if (mutireturndevs.Count > 0)
|
||
|
{
|
||
|
for (int k = 0; k < mutireturndevs.Count; k++)
|
||
|
{
|
||
|
|
||
|
if (mutireturndevs[k].Contains(startdev) == false)
|
||
|
{
|
||
|
mutireturndevs[k].Add(startdev);
|
||
|
|
||
|
}
|
||
|
mutiRoute.Add(mutireturndevs[k]);
|
||
|
}
|
||
|
}
|
||
|
return mutiRoute;
|
||
|
|
||
|
}
|
||
|
#endregion
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|