using System; using 常用工具集.Base; using System.Collections.Generic; using MES.Utility.Core; using System.Text; using System.Linq; using TwinCAT.Ads.TypeSystem; using TwinCAT.Ads; namespace 常用工具集.ViewModel._01PLC通信调试 { public class 倍福ADS调试ViewModel : ViewModelBase { public bool Enabled1 { get; set; } = true; public bool Enabled2 { get; set; } = false; public string NetId { get; set; } = "192.168.1.10.1.1"; public int Port { get; set; } = 851; public string VarName { get; set; } = "Global_LaserCutting.gHmiPlc.Output.Mes.DeviceStatus.bEMG"; public int StringLength { get; set; } = 80; public string DataType { get; set; } = ""; public string ReadedValue { get; set; } = ""; public string Message1 { get; set; } = ""; public string Message2 { get; set; } = ""; public string BoolValue { get; set; } = ""; private AdsServer ads; public DelegateCommand ConnectCmd { get; set; } public DelegateCommand DisconnectCmd { get; set; } public DelegateCommand WriteCmd { get; set; } public DelegateCommand ReadCmd { get; set; } public 倍福ADS调试ViewModel() { ConnectCmd = new DelegateCommand(ConnectCmdFunc); DisconnectCmd = new DelegateCommand(DisconnectCmdFunc); ReadCmd = new DelegateCommand(ReadCmdFunc); WriteCmd = new DelegateCommand(WriteCmdFunc); } private void ConnectCmdFunc(object obj) { try { ads = new AdsServer(NetId, Port); ads.Connect(); Enabled1 = false; Enabled2 = true; } catch { GlobalValues.Error("连接失败"); return; } } private void DisconnectCmdFunc(object obj) { ads.Disconnect(); ads = null; Enabled1 = true; Enabled2 = false; } private void ReadCmdFunc(object obj) { string cmd = obj.ToString(); ReadedValue = ""; Message1 = ""; DataType = ""; try { object value = ads.Read(VarName, out string type); Message1 = "读取成功"; DataType = type; if (value.GetType().IsArray) { Array array = value as Array; List list = new List(); for (int i = 0; i < array.Length; i++) { list.Add(array.GetValue(i).ToString()); } ReadedValue = list.GetStrArray(" "); } else { ReadedValue = value.ToString(); } } catch (Exception ex) { Message1 = $"读取失败:{ex.Message}"; return; } } private void WriteCmdFunc(object obj) { string cmd = obj.ToString(); try { if (string.IsNullOrEmpty(BoolValue)) { Message2 = "请输入数据"; return; } ads.Write(VarName, BoolValue); Message2 = $"写入成功"; } catch (Exception ex) { Message2 = $"写入失败:{ex.Message}"; } } } public class AdsServer { Dictionary symbolDict = new Dictionary(); public delegate void TcAdsStateChangedEventHandler(AdsState state); public delegate void TcAdsRouteChangedEventHandler(AmsRouterState state); public AmsRouterState AsmRouteState { get; set; } = AmsRouterState.Stop; public AdsState AdsState { get; set; } = AdsState.Stop; public AdsClient ads; public bool SystemIsRunning => ads.IsConnected; private TcAdsRouteChangedEventHandler tcAdsSystemStateChangedHandler; public event TcAdsRouteChangedEventHandler TcSystemStateChanged { add { this.tcAdsSystemStateChangedHandler = (TcAdsRouteChangedEventHandler)Delegate.Combine(this.tcAdsSystemStateChangedHandler, value); value(AsmRouteState); } remove { this.tcAdsSystemStateChangedHandler = (TcAdsRouteChangedEventHandler)Delegate.Remove(this.tcAdsSystemStateChangedHandler, value); } } private TcAdsStateChangedEventHandler tcAdsClientStateChangedHandler; public event TcAdsStateChangedEventHandler TcPlcStateChanged { add { this.tcAdsClientStateChangedHandler = (TcAdsStateChangedEventHandler)Delegate.Combine(this.tcAdsClientStateChangedHandler, value); value(AdsState); } remove { this.tcAdsClientStateChangedHandler = (TcAdsStateChangedEventHandler)Delegate.Remove(this.tcAdsClientStateChangedHandler, value); } } private int _clientPortNr = 801; private string _netId = ""; public AdsServer(string netId, int portNr) { this._netId = netId; this._clientPortNr = portNr; ads = new AdsClient(); ads.RouterStateChanged += Client_AmsRouterNotification; ads.AdsStateChanged += Client_AdsStateChanged; } private void Client_AmsRouterNotification(object sender, AmsRouterNotificationEventArgs e) { AsmRouteState = e.State; tcAdsSystemStateChangedHandler?.Invoke(AsmRouteState); } public void Connect() { ads.Connect(this._netId, this._clientPortNr); } public void Disconnect() { ads.Disconnect(); ads.Dispose(); } private void Client_AdsStateChanged(object sender, AdsStateChangedEventArgs e) { AdsState = e.State.AdsState; tcAdsClientStateChangedHandler?.Invoke(AdsState); } public object Read(string symbolPath, out string oDataType) { if (!SystemIsRunning) { throw new Exception("PLC链接失败"); } //bool isArray = symbolPath.Contains("[") && symbolPath.Contains("]"); //int index1 = symbolPath.IndexOf("["); int index2 = symbolPath.IndexOf("]"); //uint index = uint.Parse(symbolPath.Substring(index1 + 1, index2 - index1 - 1)); //symbolPath = symbolPath.Substring(0, index1); IAdsSymbol symbol = null; if (symbolDict.ContainsKey(symbolPath)) { symbol = symbolDict[symbolPath]; } else { symbol = ads.ReadSymbol(symbolPath); if (symbol == null) throw new Exception("找不到该变量"); symbolDict.Add(symbolPath, symbol); } oDataType = symbol.TypeName; if (symbol.TypeName.Substring(0, 3) != "ARR") { AdsDataTypeId datatype = symbol.DataTypeId; //BOOL if (datatype == AdsDataTypeId.ADST_BIT) return ads.ReadAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset, typeof(bool)); //byte if (datatype == AdsDataTypeId.ADST_UINT8) return ads.ReadAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset, typeof(byte)); //sbyte if (datatype == AdsDataTypeId.ADST_INT8) return ads.ReadAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset, typeof(sbyte)); //ushort if (datatype == AdsDataTypeId.ADST_UINT16) return ads.ReadAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset, typeof(ushort)); //short if (datatype == AdsDataTypeId.ADST_INT16) return ads.ReadAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset, typeof(short)); if (datatype == AdsDataTypeId.ADST_UINT32) return ads.ReadAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset, typeof(uint)); if (datatype == AdsDataTypeId.ADST_INT32) return ads.ReadAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset, typeof(int)); if (datatype == AdsDataTypeId.ADST_REAL32) return ads.ReadAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset, typeof(float)); if (datatype == AdsDataTypeId.ADST_REAL64) return ads.ReadAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset, typeof(double)); if (datatype == AdsDataTypeId.ADST_STRING) return ads.ReadAnyString((uint)symbol.IndexGroup, (uint)symbol.IndexOffset, symbol.Size, Encoding.Default); if (datatype == AdsDataTypeId.ADST_WSTRING) { Memory stream = new Memory(new byte[symbol.Size]); int readLength = ads.Read((uint)symbol.IndexGroup, (uint)symbol.IndexOffset, stream); byte[] bytes = stream.ToArray().ToList().Take(readLength).ToArray(); int charCount = readLength / 2; char[] charArray = new char[charCount]; for (int i = 0; i < charCount; i++) { char value = (char)(bytes[i * 2 + 1] << 8 | bytes[i * 2]); charArray[i] = value; if (value == 0) break; } return new String(charArray).Trim('\0'); } if (datatype == AdsDataTypeId.ADST_BIGTYPE) { if (symbol.TypeName.StartsWith("TIME") || symbol.TypeName.StartsWith("DATE") || symbol.TypeName.StartsWith("TOD")) { return ads.ReadAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset, typeof(DateTime)); } } } else { AdsDataTypeId datatype = symbol.DataTypeId; if (datatype == AdsDataTypeId.ADST_BIT) { //if (isArray) //{ // return (bool)ads.ReadAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset + index, typeof(bool)); //} bool[] values = new bool[symbol.Size]; for (uint i = 0; i < symbol.Size; i++) { values[i] = (bool)ads.ReadAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset + i, typeof(bool)); } return values; } //byte if (datatype == AdsDataTypeId.ADST_UINT8) { //if (isArray) //{ // return (byte)ads.ReadAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset + index, typeof(byte)); ; //} byte[] values = new byte[symbol.Size]; for (uint i = 0; i < symbol.Size; i++) { values[i] = (byte)ads.ReadAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset + i, typeof(byte)); } return values; } //sbyte if (datatype == AdsDataTypeId.ADST_INT8) { //if (isArray) //{ // return (sbyte)ads.ReadAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset + index, typeof(sbyte)); //} sbyte[] values = new sbyte[symbol.Size]; for (uint i = 0; i < symbol.Size; i++) { values[i] = (sbyte)ads.ReadAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset + i, typeof(sbyte)); } return values; } //ushort if (datatype == AdsDataTypeId.ADST_UINT16) { //if (isArray) //{ // return (ushort)ads.ReadAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset + (index * 2U), typeof(ushort)); //} int count = symbol.Size / 2; ushort[] values = new ushort[count]; for (uint i = 0; i < count; i++) { values[i] = (ushort)ads.ReadAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset + (i * 2U), typeof(ushort)); } return values; } //short if (datatype == AdsDataTypeId.ADST_INT16) { //if (isArray) //{ // return (short)ads.ReadAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset + (index * 2U), typeof(short)); //} int count = symbol.Size / 2; short[] values = new short[count]; for (uint i = 0; i < count; i++) { values[i] = (short)ads.ReadAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset + (i * 2U), typeof(short)); } return values; } if (datatype == AdsDataTypeId.ADST_UINT32) { //if (isArray) //{ // return (uint)ads.ReadAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset + (index * 4U), typeof(uint)); //} int count = symbol.Size / 4; uint[] values = new uint[count]; for (uint i = 0; i < count; i++) { values[i] = (uint)ads.ReadAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset + (i * 4U), typeof(uint)); } return values; } if (datatype == AdsDataTypeId.ADST_INT32) { //if (isArray) //{ // return (int)ads.ReadAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset + (index * 4U), typeof(int)); //} int count = symbol.Size / 4; int[] values = new int[count]; for (uint i = 0; i < count; i++) { values[i] = (int)ads.ReadAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset + (i * 4U), typeof(int)); } return values; } if (datatype == AdsDataTypeId.ADST_REAL32) { //if (isArray) //{ // return (float)ads.ReadAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset + (index * 4U), typeof(float)); //} int count = symbol.Size / 4; float[] values = new float[count]; for (uint i = 0; i < count; i++) { values[i] = (float)ads.ReadAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset + (i * 4U), typeof(float)); } return values; } if (datatype == AdsDataTypeId.ADST_REAL64) { //if (isArray) //{ // return (double)ads.ReadAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset + (index * 8U), typeof(double)); //} int count = symbol.Size / 8; double[] values = new double[count]; for (uint i = 0; i < count; i++) { values[i] = (double)ads.ReadAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset + (i * 8U), typeof(double)); } return values; } //TC3 字符串数组为 ADST_STRING if (datatype == AdsDataTypeId.ADST_STRING) { int every = 81; if (symbol.TypeName.Contains("OF STRING")) { int index = symbol.TypeName.IndexOf("OF STRING("); if (index != 1) { int index2 = symbol.TypeName.LastIndexOf(")"); every = Convert.ToInt32(symbol.TypeName.Substring(index + 10, index2 - index - 10)) + 1; } int count = symbol.Size / every; string[] values = new string[count]; for (uint i = 0; i < count; i++) { values[i] = ads.ReadAnyString((uint)symbol.IndexGroup, (uint)(symbol.IndexOffset + (i * every)), every, Encoding.Default); } return values; } } if (datatype == AdsDataTypeId.ADST_WSTRING) { int every = 512; if (symbol.TypeName.Contains("OF WSTRING")) { int index = symbol.TypeName.IndexOf("OF WSTRING("); if (index != 1) { int index2 = symbol.TypeName.LastIndexOf(")"); every = (Convert.ToInt32(symbol.TypeName.Substring(index + 11, index2 - index - 11)) + 1) * 2; } int count = symbol.Size / every; string[] values = new string[count]; for (uint i = 0; i < count; i++) { Memory stream = new Memory(new byte[every]); int readLength = ads.Read((uint)symbol.IndexGroup, (uint)(symbol.IndexOffset + (i * every)), stream); byte[] bytes = stream.ToArray().ToList().Take(readLength).ToArray(); int charCount = readLength / 2; char[] charArray = new char[charCount]; for (int j = 0; j < charCount; j++) { char value = (char)(bytes[j * 2 + 1] << 8 | bytes[j * 2]); charArray[j] = value; if (value == 0) break; } values[i] = new String(charArray).Trim('\0'); } return values; } } if (datatype == AdsDataTypeId.ADST_BIGTYPE) { //TC2 字符串为ADST_BIGTYPE if (symbol.TypeName.Contains("OF STRING")) { //if (isArray) //{ // return ads.ReadAnyString((uint)symbol.IndexGroup, (uint)symbol.IndexOffset + (index * 81U), 81, Encoding.Default); //} int count = symbol.Size / 81; string[] values = new string[count]; for (uint i = 0; i < count; i++) { values[i] = ads.ReadAnyString((uint)symbol.IndexGroup, (uint)symbol.IndexOffset + (i * 81U), 81, Encoding.Default); } return values; } if (symbol.TypeName.Contains("OF TIME") || symbol.TypeName.Contains("OF DATE")) { //if (isArray) //{ // return (DateTime)ads.ReadAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset + (index * 4), typeof(DateTime)); //} int count = symbol.Size / 4; DateTime[] values = new DateTime[count]; for (uint i = 0; i < count; i++) { values[i] = (DateTime)ads.ReadAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset + (i * 4), typeof(DateTime)); } return values; } if (symbol.TypeName.Contains("OF TOD")) { //if (isArray) //{ // return (DateTime)ads.ReadAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset + (index * 4), typeof(DateTime)); //} int count = symbol.Size / 4; DateTime[] values = new DateTime[count]; for (uint i = 0; i < count; i++) { values[i] = (DateTime)ads.ReadAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset + (i * 4), typeof(DateTime)); } return values; } } } throw new Exception("不支持的数据类型"); } public void Write(string symbolPath, string value) { if (!SystemIsRunning) { throw new Exception("PLC链接失败"); } IAdsSymbol symbol = null; if (symbolDict.ContainsKey(symbolPath)) { symbol = symbolDict[symbolPath]; } else { symbol = ads.ReadSymbol(symbolPath); if (symbol == null) throw new Exception("找不到该变量"); symbolDict.Add(symbolPath, symbol); } if (symbol.TypeName.Substring(0, 3) != "ARR") { AdsDataTypeId datatype = symbol.DataTypeId; //BOOL if (datatype == AdsDataTypeId.ADST_BIT) { ads.WriteAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset, bool.Parse(value)); return; } //byte if (datatype == AdsDataTypeId.ADST_UINT8) { ads.WriteAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset, byte.Parse(value)); return; } //sbyte if (datatype == AdsDataTypeId.ADST_INT8) { ads.WriteAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset, sbyte.Parse(value)); return; } //ushort if (datatype == AdsDataTypeId.ADST_UINT16) { ads.WriteAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset, ushort.Parse(value)); return; } if (datatype == AdsDataTypeId.ADST_INT16) { ads.WriteAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset, short.Parse(value)); return; } if (datatype == AdsDataTypeId.ADST_UINT32) { ads.WriteAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset, uint.Parse(value)); return; } if (datatype == AdsDataTypeId.ADST_INT32) { ads.WriteAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset, int.Parse(value)); return; } if (datatype == AdsDataTypeId.ADST_REAL32) { ads.WriteAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset, float.Parse(value)); return; } if (datatype == AdsDataTypeId.ADST_REAL64) { ads.WriteAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset, double.Parse(value)); return; } if (datatype == AdsDataTypeId.ADST_STRING) { ads.WriteAnyString(symbolPath, value, symbol.Size,Encoding.Default); //ads.WriteAnyString((uint)symbol.IndexGroup, (uint)symbol.IndexOffset, value, symbol.Size, Encoding.Default); return; } if (datatype == AdsDataTypeId.ADST_WSTRING) { char[] charArray = value.ToCharArray(); byte[] bytes = new byte[charArray.Length * 2]; for (int i = 0; i < charArray.Length; i++) { bytes[i * 2] = (byte)(charArray[i] & 0xFF); bytes[i * 2 + 1] = (byte)(charArray[i] >> 8 & 0xFF); } if (bytes.Length > symbol.Size) { ads.Write((uint)symbol.IndexGroup, (uint)symbol.IndexOffset, new ReadOnlyMemory(bytes)); } else { byte[] newBytes = new byte[symbol.Size]; for (int i = 0; i < bytes.Length; i++) { newBytes[i] = bytes[i]; } ads.Write((uint)symbol.IndexGroup, (uint)symbol.IndexOffset, new ReadOnlyMemory(newBytes)); } return; } if (datatype == AdsDataTypeId.ADST_BIGTYPE) { if (symbol.TypeName.StartsWith("TIME") || symbol.TypeName.StartsWith("DATE") || symbol.TypeName.StartsWith("TOD")) { bool flag = DateTime.TryParse(value, out DateTime result); if (!flag) throw new Exception("格式转换失败"); ads.WriteAny((uint)symbol.IndexGroup, (uint)symbol.IndexOffset, result); return; } } throw new Exception("不支持的数据类型"); } else { throw new Exception("不支持数组批量写入"); } } } }