using HMI.Core.Util; using HslCommunication; using HslCommunication.Core.Pipe; using HslCommunication.Profinet.Siemens; using PLCHelper.Entity; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; namespace PLCHelper { public class S7Context { private static ConcurrentDictionary cache = new ConcurrentDictionary(); private static ConcurrentDictionary failedCount = new ConcurrentDictionary(); private static Dictionary dataCache = new Dictionary(); public static ObservableCollection Datasource = new ObservableCollection(); private static string Ip; private static int Port; private static readonly object lockObj = new object(); public static void Init(string ip, int port) { Ip = ip; Port = port; LoadTagData(); } public static void LoadTagData() { lock (lockObj) { dataCache.Clear(); try { string path = Path.Combine(PathHelper.ConfigFolder, "CurrentSensorControl", "BurnInSettingData.data"); if (File.Exists(path)) { Datasource = XmlHelper.DeserializeFromXml>(path); } else { Datasource = new ObservableCollection(); } } catch (Exception ex) { Datasource = new ObservableCollection(); } foreach (var data in Datasource) { dataCache[data.Name] = data; } } } public static SiemensS7Net Get(string name) { if (!cache.ContainsKey(name)) { var client = new SiemensS7Net(SiemensPLCS.S1500); cache[name] = client; PipeTcpNet pipeTcpNet = new PipeTcpNet(Ip, Port); pipeTcpNet.ConnectTimeOut = 200; pipeTcpNet.ReceiveTimeOut = 200; client.CommunicationPipe = pipeTcpNet; client.ConnectServer(); failedCount[client] = 0; } return cache[name]; } private static bool GetS7Data(SiemensS7Net api, PLCTagData data, string name, out object val) { val = null; string address = data.Address; if (data.Type == PLCTagType.BOOL) { var res = api.ReadBool(address); val = res.Content; return res.IsSuccess; } else if (data.Type == PLCTagType.SHORT) { var res = api.ReadInt16(address); val = res.Content; return res.IsSuccess; } else if (data.Type == PLCTagType.INT) { var res = api.ReadInt32(address); val = res.Content; return res.IsSuccess; } else if (data.Type == PLCTagType.FLOAT) { var res = api.ReadFloat(address); val = res.Content; return res.IsSuccess; } return false; } public static bool GetData(SiemensS7Net api, string name, out object val) { val = null; if (dataCache.ContainsKey(name)) { var data = dataCache[name]; if (data.ConnectionType == ConnectionType.PLC_S7) { if (failedCount[api] >= 3) { return false; } var res = GetS7Data(api, data, name, out val); if (!res) failedCount[api]++; return res; } else if (data.ConnectionType == ConnectionType.MODBUS) { return ModbusHelper.ReadData(data, out val, out _); } else if (data.ConnectionType == ConnectionType.NXI_5010) { return NXI_5010Helper.ReadData(data, name, out val); } return false; } else { return false; } } public static bool GetData(string apiName, string name, out object val) { val = null; if (dataCache.ContainsKey(name)) { var data = dataCache[name]; if (data.ConnectionType == ConnectionType.PLC_S7) { var api = Get(apiName); if (failedCount[api] >= 3) { return false; } var res = GetS7Data(api, data, name, out val); if (!res) failedCount[api]++; return res; } else if (data.ConnectionType == ConnectionType.MODBUS) { return ModbusHelper.ReadData(data, out val, out _); } else if (data.ConnectionType == ConnectionType.NXI_5010) { return NXI_5010Helper.ReadData(data, name, out val); } return false; } else { return false; } } private static bool WriteS7Data(SiemensS7Net api, PLCTagData data, string name, object val) { string address = data.Address; OperateResult res; switch (data.Type) { case PLCTagType.BOOL: res = api.Write(address, (bool)val); break; case PLCTagType.SHORT: res = api.Write(address, (short)val); break; case PLCTagType.USHORT: res = api.Write(address, (ushort)val); break; case PLCTagType.INT: res = api.Write(address, (int)val); break; case PLCTagType.FLOAT: res = api.Write(address, (float)val); break; default: return false; } return res.IsSuccess; } private static bool WriteS7Data2(SiemensS7Net api, PLCTagData data, string name, object val, out string errMsg) { errMsg = string.Empty; string address = data.Address; OperateResult res; switch (data.Type) { case PLCTagType.BOOL: res = api.Write(address, (bool)val); break; case PLCTagType.SHORT: res = api.Write(address, (short)val); break; case PLCTagType.USHORT: res = api.Write(address, (ushort)val); break; case PLCTagType.INT: res = api.Write(address, (int)val); break; case PLCTagType.FLOAT: res = api.Write(address, (float)val); break; default: return false; } errMsg = res.Message; return res.IsSuccess; } public static bool WriteData(SiemensS7Net api, string name, object val) { if (dataCache.ContainsKey(name)) { var data = dataCache[name]; string address = data.Address; if (data.ConnectionType == ConnectionType.PLC_S7) { if (failedCount[api] >= 3) { return false; } var res = WriteS7Data(api, data, name, val); if (!res) failedCount[api]++; return res; } else if (data.ConnectionType == ConnectionType.MODBUS) { return ModbusHelper.WriteData(data, val, out _); } return false; } else { return false; } } public static bool WriteData(string apiName, string name, object val, out string errMsg) { errMsg = string.Empty; if (dataCache.ContainsKey(name)) { var data = dataCache[name]; string address = data.Address; if (data.ConnectionType == ConnectionType.PLC_S7) { var api = Get(apiName); if (failedCount[api] >= 3) { errMsg = "超过重试次数"; return false; } var res = WriteS7Data2(api, data, name, val, out errMsg); if (!res) failedCount[api]++; return res; } else if (data.ConnectionType == ConnectionType.MODBUS) { return ModbusHelper.WriteData(data, val, out errMsg); } errMsg = "不支持的类型"; return false; } else { errMsg = $"未找到标签[{name}]"; return false; } } public static void Release() { foreach (var client in cache.Values) { client.Dispose(); } cache.Clear(); ModbusHelper.Release(); NXI_5010Helper.Release(); } public static void ResetFailCount() { foreach (var client in failedCount.Keys) { failedCount[client] = 0; } } } }