using HslCommunication.Core; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; using TeamAAS.Communication.Interfaces; namespace TeamAAS.Communication.Base { public abstract class PlcCommunicationBase : BindableCommunicationBase { [Browsable(false)] public override string TypeKey => GetType().FullName; public abstract string PlcVendor { get; } [JsonIgnore, Browsable(false)] protected IReadWriteNet Driver; private byte _station = 1; [Category("II.PLC配置"), DisplayName("从站号"), Description("Modbus 等多从站协议用")] public byte Station { get => _station; set => SetProperty(ref _station, value); } private ByteOrderType _byteOrder = ByteOrderType.ABCD; [Category("II.PLC配置"), DisplayName("字节序"), Description("多字节数据字节排列顺序")] public ByteOrderType ByteOrder { get => _byteOrder; set => SetProperty(ref _byteOrder, value); } protected virtual string ResolveAddress(string address) => address; public override object ReadValue(string address) => ReadValue(address, DebugDataType.Int, 1); public override Task ReadValueAsync(string address) => Task.Run(() => ReadValue(address)); public override void WriteValue(string address, object value) { if (value == null) throw new ArgumentNullException(nameof(value)); WriteValue(address, value, InferDataType(value), 1); } public override Task WriteValueAsync(string address, object value) => Task.Run(() => WriteValue(address, value)); private static DebugDataType InferDataType(object value) { if (value is bool) return DebugDataType.Bool; if (value is byte) return DebugDataType.Byte; if (value is short) return DebugDataType.Short; if (value is ushort) return DebugDataType.Ushort; if (value is int) return DebugDataType.Int; if (value is uint) return DebugDataType.Uint; if (value is long) return DebugDataType.Long; if (value is ulong) return DebugDataType.Ulong; if (value is float) return DebugDataType.Float; if (value is double) return DebugDataType.Double; return DebugDataType.String; } public virtual object ReadValue(string address, DebugDataType type, ushort length = 1) { if (Driver == null) throw new InvalidOperationException($"{PlcVendor} 底层驱动未初始化,请先连接。"); var addr = ResolveAddress(address); ushort len = Math.Max(length, (ushort)1); switch (type) { case DebugDataType.Bool: if (len == 1) { var r = Driver.ReadBool(addr); if (!r.IsSuccess) throw new InvalidOperationException(r.Message); return r.Content; } { var r = Driver.ReadBool(addr, len); if (!r.IsSuccess) throw new InvalidOperationException(r.Message); return r.Content; } case DebugDataType.Byte: { var r = Driver.Read(addr, len); if (!r.IsSuccess) throw new InvalidOperationException(r.Message); return r.Content; } case DebugDataType.Short: if (len == 1) { var r = Driver.ReadInt16(addr); if (!r.IsSuccess) throw new InvalidOperationException(r.Message); return r.Content; } { var r = Driver.ReadInt16(addr, len); if (!r.IsSuccess) throw new InvalidOperationException(r.Message); return r.Content; } case DebugDataType.Ushort: if (len == 1) { var r = Driver.ReadUInt16(addr); if (!r.IsSuccess) throw new InvalidOperationException(r.Message); return r.Content; } { var r = Driver.ReadUInt16(addr, len); if (!r.IsSuccess) throw new InvalidOperationException(r.Message); return r.Content; } case DebugDataType.Int: if (len == 1) { var r = Driver.ReadInt32(addr); if (!r.IsSuccess) throw new InvalidOperationException(r.Message); return r.Content; } { var r = Driver.ReadInt32(addr, len); if (!r.IsSuccess) throw new InvalidOperationException(r.Message); return r.Content; } case DebugDataType.Uint: if (len == 1) { var r = Driver.ReadUInt32(addr); if (!r.IsSuccess) throw new InvalidOperationException(r.Message); return r.Content; } { var r = Driver.ReadUInt32(addr, len); if (!r.IsSuccess) throw new InvalidOperationException(r.Message); return r.Content; } case DebugDataType.Long: if (len == 1) { var r = Driver.ReadInt64(addr); if (!r.IsSuccess) throw new InvalidOperationException(r.Message); return r.Content; } { var r = Driver.ReadInt64(addr, len); if (!r.IsSuccess) throw new InvalidOperationException(r.Message); return r.Content; } case DebugDataType.Ulong: if (len == 1) { var r = Driver.ReadUInt64(addr); if (!r.IsSuccess) throw new InvalidOperationException(r.Message); return r.Content; } { var r = Driver.ReadUInt64(addr, len); if (!r.IsSuccess) throw new InvalidOperationException(r.Message); return r.Content; } case DebugDataType.Float: if (len == 1) { var r = Driver.ReadFloat(addr); if (!r.IsSuccess) throw new InvalidOperationException(r.Message); return r.Content; } { var r = Driver.ReadFloat(addr, len); if (!r.IsSuccess) throw new InvalidOperationException(r.Message); return r.Content; } case DebugDataType.Double: if (len == 1) { var r = Driver.ReadDouble(addr); if (!r.IsSuccess) throw new InvalidOperationException(r.Message); return r.Content; } { var r = Driver.ReadDouble(addr, len); if (!r.IsSuccess) throw new InvalidOperationException(r.Message); return r.Content; } case DebugDataType.String: { var r = Driver.ReadString(addr, len); if (!r.IsSuccess) throw new InvalidOperationException(r.Message); return r.Content; } default: throw new ArgumentOutOfRangeException(nameof(type)); } } public virtual void WriteValue(string address, object value, DebugDataType type, ushort length = 1) { if (Driver == null) throw new InvalidOperationException($"{PlcVendor} 底层驱动未初始化,请先连接。"); var addr = ResolveAddress(address); HslCommunication.OperateResult result; switch (type) { case DebugDataType.Bool: result = value is bool[] bArr ? Driver.Write(addr, bArr) : Driver.Write(addr, Convert.ToBoolean(value)); break; case DebugDataType.Byte: result = value is byte[] byArr ? Driver.Write(addr, byArr) : Driver.Write(addr, new[] { Convert.ToByte(value) }); break; case DebugDataType.Short: result = value is short[] sArr ? Driver.Write(addr, sArr) : Driver.Write(addr, Convert.ToInt16(value)); break; case DebugDataType.Ushort: result = value is ushort[] usArr ? Driver.Write(addr, usArr) : Driver.Write(addr, Convert.ToUInt16(value)); break; case DebugDataType.Int: result = value is int[] iArr ? Driver.Write(addr, iArr) : Driver.Write(addr, Convert.ToInt32(value)); break; case DebugDataType.Uint: result = value is uint[] uiArr ? Driver.Write(addr, uiArr) : Driver.Write(addr, Convert.ToUInt32(value)); break; case DebugDataType.Long: result = value is long[] lArr ? Driver.Write(addr, lArr) : Driver.Write(addr, Convert.ToInt64(value)); break; case DebugDataType.Ulong: result = value is ulong[] ulArr ? Driver.Write(addr, ulArr) : Driver.Write(addr, Convert.ToUInt64(value)); break; case DebugDataType.Float: result = value is float[] fArr ? Driver.Write(addr, fArr) : Driver.Write(addr, Convert.ToSingle(value)); break; case DebugDataType.Double: result = value is double[] dArr ? Driver.Write(addr, dArr) : Driver.Write(addr, Convert.ToDouble(value)); break; case DebugDataType.String: result = Driver.Write(addr, value?.ToString() ?? ""); break; default: throw new ArgumentOutOfRangeException(nameof(type)); } if (!result.IsSuccess) throw new InvalidOperationException(result.Message); } public Task ReadValueAsync(string address, DebugDataType type, ushort length = 1) => Task.Run(() => ReadValue(address, type, length)); public Task WriteValueAsync(string address, object value, DebugDataType type, ushort length = 1) => Task.Run(() => WriteValue(address, value, type, length)); } }