using Cowain.Base.Helpers; using Cowain.Base.Models; using HslCommunication; using HslCommunication.BasicFramework; using HslCommunication.Core; using HslCommunication.Profinet.Siemens; using Microsoft.Extensions.Logging; using System.Text; namespace Plugin.Cowain.Driver; public static class ReadWriteExtensions { private static readonly ILogger _logger = ServiceLocator.GetRequiredService(); public static ResultModel ToResultModel(OperateResult read) where T1 : notnull where T2 : notnull { if (!read.IsSuccess) return ResultModel.Error(read.Message); return ResultModel.Success((T1)(object)read.Content); } public static ResultModel ToResultModel(this OperateResult operate) { if (!operate.IsSuccess) return ResultModel.Error(operate.Message); return ResultModel.Success(); } /// /// 如果S7读取的字符串不对,使用这个方法读取 /// public static async Task> ReadS7StringAsync(SiemensS7Net plc, string address, ushort length) { var readBytes = await plc.ReadAsync(address, length); if (!readBytes.IsSuccess) { return new OperateResult(readBytes.Message); } byte[] data = readBytes.Content; if (data.Length > 2) { byte[] strData = new byte[data[1]]; Array.Copy(data, 2, strData, 0, strData.Length); return OperateResult.CreateSuccessResult(Encoding.ASCII.GetString(strData)); } else { //读取错误 return new OperateResult("数据长度错误"); } } public static string GetS7String(this byte[] data) { if (data.Length > 2) { if (data.Length < data[1] + 2) { return string.Empty; // 数据长度不足 } byte[] strData = new byte[data[1]]; Array.Copy(data, 2, strData, 0, strData.Length); return Encoding.ASCII.GetString(strData); } else { //读取错误 return string.Empty; } } public static string GetS7WString(this byte[] data) { if (data.Length > 4) { ushort len = (ushort)(4 + (data[2] * 256 + data[3]) * 2); if (data.Length < len + 4) { return string.Empty; // 数据长度不足 } byte[] strData = new byte[len]; Array.Copy(data, 4, strData, 0, strData.Length); return Encoding.Unicode.GetString(SoftBasic.BytesReverseByWord(strData)); } else { //读取错误 return string.Empty; } } public static async Task WriteValuesAysnc(this IReadWriteDevice plc, string address, short[] value, int retryCount = 5) { byte[] bytes = new byte[value.Length * 2]; for (int i = 0; i < value.Length; i++) { plc.ByteTransform.TransByte(value[i]).CopyTo(bytes, i * 2); } return await plc.WriteValuesAysnc(address, bytes, retryCount); } public static async Task WriteValuesAysnc(this IReadWriteDevice plc, string address, byte[] value, int retryCount = 5) { int baseDelay = 100; // 基础延迟100ms var random = new Random(); ResultModel? result = null; for (int retry = 0; retry < retryCount; retry++) { try { result = ToResultModel(await plc.WriteAsync(address, value)); if (result.IsSuccess) { if (retry > 1) { _logger.LogInformation($"ReadWriteExtensions写PLC地址:{address} 数据成功,第{retry + 1}次尝试"); } return result; } else { _logger.LogWarning($"ReadWriteExtensions写PLC地址:{address} 数据失败:{result.ErrorMessage},第{retry + 1}次尝试"); } } catch (Exception ex) { result = ResultModel.Error(ex.Message); _logger.LogError(ex, $"ReadWriteExtensions写PLC地址:{address} 数据失败:{ex.Message},第{retry + 1}次尝试"); } // 计算指数退避+抖动 int jitter = random.Next(0, 100); // 0~100ms int delay = baseDelay * (int)Math.Pow(2, retry) + jitter; await Task.Delay(delay); } return result ?? ResultModel.Error("未知错误"); } /// /// 只支持常规数据类型,不支持字符串 /// public static async Task> ReadValuesAsync(this IReadWriteDevice plc, string address, ushort count = 1) where T : notnull { Type type = typeof(T); // 处理数组类型 if (count > 1) { return await ReadArrayAsync(plc, address, count); } // 处理单个值类型 return type switch { Type t when t == typeof(bool) => ToResultModel(await plc.ReadBoolAsync(address)), Type t when t == typeof(byte) => await ReadByteAsync(plc, address), Type t when t == typeof(short) => ToResultModel(await plc.ReadInt16Async(address)), Type t when t == typeof(ushort) => ToResultModel(await plc.ReadUInt16Async(address)), Type t when t == typeof(int) => ToResultModel(await plc.ReadInt32Async(address)), Type t when t == typeof(uint) => ToResultModel(await plc.ReadUInt32Async(address)), Type t when t == typeof(long) => ToResultModel(await plc.ReadInt64Async(address)), Type t when t == typeof(ulong) => ToResultModel(await plc.ReadUInt64Async(address)), Type t when t == typeof(float) => ToResultModel(await plc.ReadFloatAsync(address)), Type t when t == typeof(double) => ToResultModel(await plc.ReadDoubleAsync(address)), _ => ResultModel.Error("不支持的类型: " + type.Name) }; } // 处理byte类型的特殊读取逻辑 private static async Task> ReadByteAsync(IReadWriteDevice plc, string address) where T : notnull { var result = await plc.ReadAsync(address, 1); if (!result.IsSuccess) return ResultModel.Error(result.Message); return ResultModel.Success((T)(object)result.Content[0]); } // 处理数组读取的辅助方法 private static async Task> ReadArrayAsync(IReadWriteDevice plc, string address, ushort count) where T : notnull { Type type = typeof(T); // 处理数组类型 return type switch { Type t when t == typeof(bool[]) => ToResultModel(await plc.ReadBoolAsync(address, (ushort)count)), Type t when t == typeof(byte[]) => ToResultModel(await plc.ReadAsync(address, (ushort)count)), Type t when t == typeof(short[]) => ToResultModel(await plc.ReadInt16Async(address, (ushort)count)), Type t when t == typeof(ushort[]) => ToResultModel(await plc.ReadUInt16Async(address, (ushort)count)), Type t when t == typeof(int[]) => ToResultModel(await plc.ReadInt32Async(address, (ushort)count)), Type t when t == typeof(uint[]) => ToResultModel(await plc.ReadUInt32Async(address, (ushort)count)), Type t when t == typeof(long[]) => ToResultModel(await plc.ReadInt64Async(address, (ushort)count)), Type t when t == typeof(ulong[]) => ToResultModel(await plc.ReadUInt64Async(address, (ushort)count)), Type t when t == typeof(float[]) => ToResultModel(await plc.ReadFloatAsync(address, (ushort)count)), Type t when t == typeof(double[]) => ToResultModel(await plc.ReadDoubleAsync(address, (ushort)count)), _ => ResultModel.Error("不支持的数组类型: " + type.Name) }; } }