Fork me on GitHub
使用HslCommunication类库读取Siemens PLC DATA

using HslCommunication.Profinet.Siemens;
using HslCommunication;

using System;
using System.Threading;
using Microsoft.Extensions.Logging;
using HslCommunication.Profinet.Siemens;
using HslCommunication;
using SamplePreparation_System.Common;
using SamplePreparation_System.Models;
using System.Collections.Generic;
using System.Text.Json;
using System.Text;
using HslCommunication.LogNet;
using System.Windows.Interop;
using System.Threading.Tasks;
using System.Runtime.CompilerServices;

namespace System.PLC
{
    public class Plc
    {
        private readonly object Lockobj = new object(); // 用于PLC写入时先锁定再写入
        private readonly ExponentialBackoff _backoff;
        private readonly int _maxRetryCount = 5; // 最大重试次数
        private readonly int _maxRetryDelay = 100; // 最大重试延迟时间(毫秒)
        private readonly int _baseConnectTimeOutDelay = 500; // 基础延迟时间(毫秒)
        // private readonly string ipAddress_SamplePreparationPLC = "192.168.1.1";
        private readonly string ipAddress_SamplePreparationPLC = System.Configuration.ConfigurationManager.AppSettings["ZyPlcIp"] ?? "172.21.38.100";

        // HslCommunication.LogNet.
        //private readonly ILogNet logNet = new LogNetDateTime(AppContext.BaseDirectory + "PLCLogs", GenerateMode.ByEveryDay);//按每天; // 日志
        public SiemensS7Net SiemensS7_SamplePreparation { get; set; }

        readonly ILogger<SamplePreparationPlc> _logger;
        public SamplePreparationPlc(ILogger<SamplePreparationPlc> logger)
        {
            _logger = logger;
            SiemensS7_SamplePreparation = new SiemensS7Net(SiemensPLCS.S1200, ipAddress_SamplePreparationPLC) { ConnectTimeOut = _baseConnectTimeOutDelay };
            SiemensS7_SamplePreparation.ConnectServer();
            _backoff = new ExponentialBackoff(_maxRetryDelay, logger); // 基础延迟 100 毫秒  
        }

        /// <summary>
        /// 读取PLC
        /// </summary>
        /// <param name="address">点位</param>
        /// <param name="type">类型</param>
        /// <returns></returns>
        public string PlcRead(string address, string type)
        {
            string data = "";
            _backoff.SendWithBackoff(() =>
            {
                switch (type.ToLower())
                {
                    case "bool":
                        var result = SiemensS7_SamplePreparation.ReadBool(address);
                        if (!result.IsSuccess)
                        {
                            _logger.LogError(result.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result.Message); // 抛出异常以触发重试 
                        }

                        data = result.Content.ToString();
                        break;
                    case "float":
                        var result1 = SiemensS7_SamplePreparation.ReadFloat(address);
                        if (!result1.IsSuccess)
                        {
                            _logger.LogError(result1.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result1.Message); // 抛出异常以触发重试 
                        }

                        data = result1.Content.ToString();
                        break;
                    case "datetime":
                        var result2 = SiemensS7_SamplePreparation.ReadDateTime(address);
                        if (!result2.IsSuccess)
                        {
                            _logger.LogError(result2.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result2.Message); // 抛出异常以触发重试 
                        }

                        data = result2.Content.ToString();
                        break;
                    case "int32":
                    case "int":
                        var result3 = SiemensS7_SamplePreparation.ReadInt32(address);
                        if (!result3.IsSuccess)
                        {
                            _logger.LogError(result3.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result3.Message); // 抛出异常以触发重试 
                        }

                        data = result3.Content.ToString();
                        break;
                    case "int16":
                        var result4 = SiemensS7_SamplePreparation.ReadInt16(address);
                        if (!result4.IsSuccess)
                        {
                            _logger.LogError(result4.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result4.Message); // 抛出异常以触发重试 
                        }

                        data = result4.Content.ToString();
                        break;
                    case "string":
                        var result5 = SiemensS7_SamplePreparation.ReadString(address);
                        if (!result5.IsSuccess)
                        {
                            _logger.LogError(result5.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result5.Message); // 抛出异常以触发重试 
                        }

                        data = result5.Content.ToString();
                        break;
                    case "double":
                        var result6 = SiemensS7_SamplePreparation.ReadDouble(address);
                        if (!result6.IsSuccess)
                        {
                            _logger.LogError(result6.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result6.Message); // 抛出异常以触发重试 
                        }

                        data = result6.Content.ToString();
                        break;
                    case "byte":
                        var result7 = SiemensS7_SamplePreparation.ReadByte(address);
                        if (!result7.IsSuccess)
                        {
                            _logger.LogError(result7.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result7.Message); // 抛出异常以触发重试 
                        }

                        data = result7.Content.ToString();
                        break;
                    default:
                        throw new ArgumentException("Unsupported type");

                }

            }, maxRetries: _maxRetryCount); // 最大重试次数  

            return data;
        }

        /// <summary>
        /// 读取PLC
        /// </summary>
        /// <param name="address">点位</param>
        /// <param name="type">类型</param>
        /// <returns></returns>
        public async Task<string> PlcReadAsync(string address, string type)
        {
            string data = "";
            _backoff.SendWithBackoff(async () =>
            {
                switch (type.ToLower())
                {
                    case "bool":
                        var result = await SiemensS7_SamplePreparation.ReadBoolAsync(address);
                        if (!result.IsSuccess)
                        {
                            _logger.LogError(result.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result.Message); // 抛出异常以触发重试 
                        }

                        data = result.Content.ToString();
                        break;
                    case "float":
                        var result1 = await SiemensS7_SamplePreparation.ReadFloatAsync(address);
                        if (!result1.IsSuccess)
                        {
                            _logger.LogError(result1.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result1.Message); // 抛出异常以触发重试 
                        }

                        data = result1.Content.ToString();
                        break;
                    case "datetime":
                        var result2 = await SiemensS7_SamplePreparation.ReadDateTimeAsync(address);
                        if (!result2.IsSuccess)
                        {
                            _logger.LogError(result2.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result2.Message); // 抛出异常以触发重试 
                        }

                        data = result2.Content.ToString();
                        break;
                    case "int32":
                    case "int":
                        var result3 = await SiemensS7_SamplePreparation.ReadInt32Async(address);
                        if (!result3.IsSuccess)
                        {
                            _logger.LogError(result3.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result3.Message); // 抛出异常以触发重试 
                        }

                        data = result3.Content.ToString();
                        break;
                    case "int16":
                        var result4 = await SiemensS7_SamplePreparation.ReadInt16Async(address);
                        if (!result4.IsSuccess)
                        {
                            _logger.LogError(result4.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result4.Message); // 抛出异常以触发重试 
                        }

                        data = result4.Content.ToString();
                        break;
                    case "string":
                        var result5 = await SiemensS7_SamplePreparation.ReadStringAsync(address);
                        if (!result5.IsSuccess)
                        {
                            _logger.LogError(result5.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result5.Message); // 抛出异常以触发重试 
                        }

                        data = result5.Content.ToString();
                        break;
                    case "double":
                        var result6 = await SiemensS7_SamplePreparation.ReadDoubleAsync(address);
                        if (!result6.IsSuccess)
                        {
                            _logger.LogError(result6.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result6.Message); // 抛出异常以触发重试 
                        }

                        data = result6.Content.ToString();
                        break;
                    case "byte":
                        var result7 = await SiemensS7_SamplePreparation.ReadByteAsync(address);
                        if (!result7.IsSuccess)
                        {
                            _logger.LogError(result7.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result7.Message); // 抛出异常以触发重试 
                        }

                        data = result7.Content.ToString();
                        break;
                    default:
                        throw new ArgumentException("Unsupported type");

                }

            }, maxRetries: _maxRetryCount); // 最大重试次数  

            return data;
        }

        /// <summary>
        /// 写入PLC
        /// </summary>
        /// <param name="address">点位</param>
        /// <param name="value">值</param>
        /// <param name="type">类型</param>
        /// <returns></returns>
        public OperateResult PlcWrite(string address, object value, string type)
        {
            lock(Lockobj)
            {
                var result = new OperateResult();
                //while (true)
                //{
                _backoff.SendWithBackoff(() =>
                {
                    try
                    {
                        switch (type.ToLower())
                        {
                            case "bool":
                                result = SiemensS7_SamplePreparation.Write(address, Convert.ToBoolean(value));
                                break;
                            case "float":
                                result = SiemensS7_SamplePreparation.Write(address, Convert.ToSingle(value));
                                break;
                            case "datetime":
                                result = SiemensS7_SamplePreparation.Write(address, Convert.ToDateTime(value));
                                break;
                            case "int32":
                            case "int":
                                result = SiemensS7_SamplePreparation.Write(address, Convert.ToInt32(value));
                                break;
                            case "int16":
                                result = SiemensS7_SamplePreparation.Write(address, Convert.ToInt16(value));
                                break;
                            case "string":
                                result = SiemensS7_SamplePreparation.Write(address, Convert.ToString(value));
                                break;
                            case "byte":
                                result = SiemensS7_SamplePreparation.Write(address, Convert.ToByte(value));
                                break;
                            default:
                                throw new ArgumentException("Unsupported type");
                        }

                        if (!result.IsSuccess)
                        {
                            _logger.LogError(result.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result.Message); // 抛出异常以触发重试 
                        }

                        //return result;
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex.Message + ex.StackTrace);
                        throw; // 重新抛出异常以便重试
                    }
                }, maxRetries: _maxRetryCount); // 最大重试次数  
                return result;
                //Thread.Sleep(1000);
                //}
            }
        }

        /// <summary>
        /// 写入PLC
        /// </summary>
        /// <param name="address">点位</param>
        /// <param name="value">值</param>
        /// <param name="type">类型</param>
        /// <returns></returns>
        public async Task<OperateResult> PlcWriteAsync(string address, object value, string type)
        {
            //lock (Lockobj)
            //{
            var result = new OperateResult();
            //while (true)
            //{
            _backoff.SendWithBackoff(async () =>
            {
                try
                {
                    switch (type.ToLower())
                    {
                        case "bool":
                            result = await SiemensS7_SamplePreparation.WriteAsync(address, Convert.ToBoolean(value));
                            break;
                        case "float":
                            result = await SiemensS7_SamplePreparation.WriteAsync(address, Convert.ToSingle(value));
                            break;
                        case "datetime":
                            result = await SiemensS7_SamplePreparation.WriteAsync(address, Convert.ToDateTime(value));
                            break;
                        case "int32":
                        case "int":
                            result = await SiemensS7_SamplePreparation.WriteAsync(address, Convert.ToInt32(value));
                            break;
                        case "int16":
                            result = await SiemensS7_SamplePreparation.WriteAsync(address, Convert.ToInt16(value));
                            break;
                        case "string":
                            result = await SiemensS7_SamplePreparation.WriteAsync(address, Convert.ToString(value));
                            break;
                        case "byte":
                            result = await SiemensS7_SamplePreparation.WriteAsync(address, Convert.ToByte(value));
                            break;
                        default:
                            throw new ArgumentException("Unsupported type");
                    }

                    if (!result.IsSuccess)
                    {
                        _logger.LogError(result.Message);
                        //Thread.Sleep(1000);
                        //continue;
                        throw new Exception(result.Message); // 抛出异常以触发重试 
                    }

                    //return result;
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex.Message + ex.StackTrace);
                    throw; // 重新抛出异常以便重试
                }
            }, maxRetries: _maxRetryCount); // 最大重试次数  
            return result;
            //Thread.Sleep(1000);
            //}
            //}
        }

        /// <summary>
        /// 批量读取PLC点位值.
        /// Batches the read.
        /// </summary>
        /// <param name="pointList">The point list.</param>
        /// <returns></returns>
        public List<PLCPointData> BatchRead(List<PLCPointData> pointList)
        {
            List<string> plcAddress = new List<string>();
            ushort[]  dataLength = new ushort[pointList.Count];
            int index = 0;
            foreach (var point in pointList)
            {
                dataLength[index] = (ushort)point.DataLength;
                index++;
                plcAddress.Add(point.Address);
            }

            OperateResult<byte[]> resultData = SiemensS7_SamplePreparation.Read(plcAddress.ToArray(), dataLength);
            if (resultData.IsSuccess)
            {
                index = 0;
                for (int i = 0; i < pointList.Count; i++)
                {
                    ByteTrans(resultData.Content, pointList[i], index);
                    index += pointList[i].DataLength;
                }
            }
            else
            {
                PLCPointData pointData = new PLCPointData();
                pointData = pointList[0];
                pointData.ResultMsg = resultData.Message;

                pointList.Clear();

                pointList.Add(pointData);
            }

            return pointList;
        }

        /// <summary>
        /// 批量读取PLC点位值.
        /// Batches the read.
        /// </summary>
        /// <param name="pointList">The point list.</param>
        /// <returns></returns>
        public async Task<List<PLCPointData>> BatchReadAsync(List<PLCPointData> pointList)
        {
            List<string> plcAddress = new List<string>();
            ushort[] dataLength = new ushort[pointList.Count];
            int index = 0;
            foreach (var point in pointList)
            {
                dataLength[index] = (ushort)point.DataLength;
                index++;
                plcAddress.Add(point.Address);
            }

            OperateResult<byte[]> resultData = await SiemensS7_SamplePreparation.ReadAsync(plcAddress.ToArray(), dataLength);
            if (resultData.IsSuccess)
            {
                index = 0;
                for (int i = 0; i < pointList.Count; i++)
                {
                    ByteTrans(resultData.Content, pointList[i], index);
                    index += pointList[i].DataLength;
                }
            }
            else
            {
                PLCPointData pointData = new PLCPointData();
                pointData = pointList[0];
                pointData.ResultMsg = resultData.Message;

                pointList.Clear();

                pointList.Add(pointData);
            }

            return pointList;
        }

        /// <summary>
        /// 写入PLC点位值.
        /// the write.
        /// </summary>
        /// <param name="pLCPoint">The p lc point.</param>
        /// <returns></returns>
        public PLCPointData Write(PLCPointData pLCPoint)
        {
            lock (Lockobj)
            {
                if (pLCPoint.ResultData is JsonElement)
                {
                    pLCPoint.ResultData = ConvertValueKind(pLCPoint.ResultData);
                }

                if (pLCPoint.ResultData == null)
                {
                    pLCPoint.ResultCode = 0;
                    pLCPoint.ResultMsg = $"参数中缺少ResultData值";
                    return pLCPoint;
                }

                var result = new OperateResult();
                try
                {
                    Type type = ConvertPointDataType(pLCPoint.DataType);
                    string value = pLCPoint.ResultData.ToString();
                    if (type == typeof(bool))
                    {
                        result = SiemensS7_SamplePreparation.Write(pLCPoint.Address, bool.Parse(value));
                    }
                    else if (type == typeof(byte))
                    {
                        result = SiemensS7_SamplePreparation.Write(pLCPoint.Address, byte.Parse(value));
                    }
                    else if (type == typeof(float))
                    {
                        result = SiemensS7_SamplePreparation.Write(pLCPoint.Address, float.Parse(value));
                    }
                    else if (type == typeof(double))
                    {
                        result = SiemensS7_SamplePreparation.Write(pLCPoint.Address, double.Parse(value));
                    }
                    else if (type == typeof(DateTime))
                    {
                        result = SiemensS7_SamplePreparation.Write(pLCPoint.Address, DateTime.Parse(value));
                    }
                    else if (type == typeof(int))
                    {
                        result = SiemensS7_SamplePreparation.Write(pLCPoint.Address, int.Parse(value));
                    }
                    else if (type == typeof(short))
                    {
                        result = SiemensS7_SamplePreparation.Write(pLCPoint.Address, Convert.ToInt16(value));
                    }
                    else
                    {
                        result = SiemensS7_SamplePreparation.Write(pLCPoint.Address, value, pLCPoint.DataLength);
                    }

                    pLCPoint.ResultCode = result.IsSuccess ? 1 : 0;
                    pLCPoint.ResultMsg = result.IsSuccess ? "Success" : result.Message;
                    return pLCPoint;
                }
                catch (Exception ex)
                {
                    pLCPoint.ResultCode = 0;
                    pLCPoint.ResultMsg = $"(写入)失败:{ex.Message}{ex.StackTrace}";
                    return pLCPoint;
                }
            }
        }

        /// <summary>
        /// 写入PLC点位值.
        /// the write.
        /// </summary>
        /// <param name="pLCPoint">The p lc point.</param>
        /// <returns></returns>
        public async Task<PLCPointData> WriteAsync(PLCPointData pLCPoint)
        {
            //lock (Lockobj)
            //{
                if (pLCPoint.ResultData is JsonElement)
                {
                    pLCPoint.ResultData = ConvertValueKind(pLCPoint.ResultData);
                }

                if (pLCPoint.ResultData == null)
                {
                    pLCPoint.ResultCode = 0;
                    pLCPoint.ResultMsg = $"参数中缺少ResultData值";
                    return pLCPoint;
                }

                var result = new OperateResult();
                try
                {
                    Type type = ConvertPointDataType(pLCPoint.DataType);
                    string value = pLCPoint.ResultData.ToString();
                    if (type == typeof(bool))
                    {
                        result = await SiemensS7_SamplePreparation.WaitAsync(pLCPoint.Address, bool.Parse(value));
                    }
                    else if (type == typeof(byte))
                    {
                        result = await SiemensS7_SamplePreparation.WriteAsync(pLCPoint.Address, byte.Parse(value));
                    }
                    else if (type == typeof(float))
                    {
                        result = await SiemensS7_SamplePreparation.WriteAsync(pLCPoint.Address, float.Parse(value));
                    }
                    else if (type == typeof(double))
                    {
                        result = await SiemensS7_SamplePreparation.WriteAsync(pLCPoint.Address, double.Parse(value));
                    }
                    else if (type == typeof(DateTime))
                    {
                        result = await SiemensS7_SamplePreparation.WriteAsync(pLCPoint.Address, DateTime.Parse(value));
                    }
                    else if (type == typeof(int))
                    {
                        result = await SiemensS7_SamplePreparation.WriteAsync(pLCPoint.Address, int.Parse(value));
                    }
                    else if (type == typeof(short))
                    {
                        result = await SiemensS7_SamplePreparation.WriteAsync(pLCPoint.Address, Convert.ToInt16(value));
                    }
                    else
                    {
                        result = await SiemensS7_SamplePreparation.WriteAsync(pLCPoint.Address, value, pLCPoint.DataLength);
                    }

                    pLCPoint.ResultCode = result.IsSuccess ? 1 : 0;
                    pLCPoint.ResultMsg = result.IsSuccess ? "Success" : result.Message;
                    return pLCPoint;
                }
                catch (Exception ex)
                {
                    pLCPoint.ResultCode = 0;
                    pLCPoint.ResultMsg = $"(写入)失败:{ex.Message}{ex.StackTrace}";
                    return pLCPoint;
                }
            //}
        }

        /// <summary>
        /// Bytes the trans.
        /// </summary>
        /// <param name="content">The content.</param>
        /// <param name="pLCPoint">The p lc point.</param>
        /// <param name="index">The index.</param>
        private void ByteTrans(byte[] content, PLCPointData pLCPoint, int index)
        {
            try
            {
                Type type = ConvertPointDataType(pLCPoint.DataType);
                if (type == typeof(bool))
                {
                    pLCPoint.ResultCode = 1;
                    pLCPoint.ResultMsg = "Success";
                    pLCPoint.ResultData = SiemensS7_SamplePreparation.ByteTransform.TransBool(content, index);
                }
                else if (type == typeof(byte))
                {
                    pLCPoint.ResultCode = 1;
                    pLCPoint.ResultMsg = "Success";
                    pLCPoint.ResultData = SiemensS7_SamplePreparation.ByteTransform.TransByte(content, index);
                }
                else if (type == typeof(float))
                {
                    pLCPoint.ResultCode = 1;
                    pLCPoint.ResultMsg = "Success";
                    pLCPoint.ResultData = SiemensS7_SamplePreparation.ByteTransform.TransSingle(content, index);
                }
                else if (type == typeof(double))
                {
                    pLCPoint.ResultCode = 1;
                    pLCPoint.ResultMsg = "Success";
                    pLCPoint.ResultData = SiemensS7_SamplePreparation.ByteTransform.TransDouble(content, index);
                }
                else if (type == typeof(int))
                {
                    pLCPoint.ResultCode = 1;
                    pLCPoint.ResultMsg = "Success";
                    pLCPoint.ResultData = SiemensS7_SamplePreparation.ByteTransform.TransInt32(content, index);
                }
                else
                {
                    pLCPoint.ResultCode = 1;
                    pLCPoint.ResultMsg = "Success";
                    pLCPoint.ResultData = SiemensS7_SamplePreparation.ByteTransform.TransString(content, index, pLCPoint.DataLength, Encoding.ASCII).Replace("\0", "").Replace("\u0001", "");
                }
            }
            catch (Exception ex)
            {
                pLCPoint.ResultCode = 0;
                pLCPoint.ResultMsg = $"(读取)错误:{ex.Message}{ex.StackTrace}";
            }
        }

        /// <summary>
        /// 数据类型转换
        /// </summary>
        /// <param name="dataType"></param>
        /// <returns></returns>
        private Type ConvertPointDataType(string dataType)
        {
            Type type = null;
            switch (dataType.Trim().ToLower())
            {
                case "bool":
                    type = typeof(bool);
                    break;
                case "byte":
                    type = typeof(byte);
                    break;
                case "int":
                    type = typeof(int);
                    break;
                case "datetime":
                    type = typeof(DateTime);
                    break;
                case "dint":
                    type = typeof(int);
                    break;
                case "real":
                    type = typeof(float);
                    break;
                case "lreal":
                    type = typeof(double);
                    break;
                case "lint":
                    type = typeof(long);
                    break;
                case "string":
                    type = typeof(string);
                    break;
                case "short":
                    type = typeof(short);
                    break;
                default:
                    {
                        AddSysError(SiemensS7_SamplePreparation.IpAddress, $"{dataType}数据类型不存在");
                        //throw new ArgumentOutOfRangeException(dataType, "数据类型不存在");
                        break;
                    }

            }

            return type;
        }

        /// <summary>
        /// Converts the kind of the value.
        /// </summary>
        /// <param name="element">The element.</param>
        /// <returns></returns>
        private object? ConvertValueKind(JsonElement element)
        {
            switch (element.ValueKind)
            {
                case JsonValueKind.String: return element.GetString();
                case JsonValueKind.Null: return null;
                case JsonValueKind.False: return false;
                case JsonValueKind.True: return true;
                case JsonValueKind.Number: return element.GetDouble();
                case JsonValueKind.Object: return element.ValueKind.ToString();
                default: break;
            }

            return element;
        }

        /// <summary>
        /// Adds the system message.
        /// </summary>
        /// <param name="msg">The MSG.</param>
        private void AddSysMessage(string msg)
        {
            //logNet.WriteInfo(msg);
            _logger.LogInformation(msg);
        }

        /// <summary>
        /// Adds the system error.
        /// </summary>
        /// <param name="plcIp">The PLC ip.</param>
        /// <param name="error">The error.</param>
        private void AddSysError(string plcIp, string error)
        {
            //logNet.WriteError(plcIp, error);
            _logger.LogError(plcIp + ", error:" + error);
        }
    }


    public class PlcEx
    {
        private readonly object Lockobj = new object(); // 用于PLC写入时先锁定再写入
        private readonly ExponentialBackoff _backoff;
        private readonly int _maxRetryCount = 5; // 最大重试次数
        private readonly int _maxRetryDelay = 100; // 最大重试延迟时间(毫秒)
        private readonly int _baseConnectTimeOutDelay = 500; // 基础延迟时间(毫秒)
        // private readonly string ipAddress_SamplePreparationPLC = "192.168.1.1";
        private readonly string ipAddress_SamplePreparationPLC = System.Configuration.ConfigurationManager.AppSettings["HygpPlcIp"] ?? "172.21.38.101";

        // HslCommunication.LogNet.
        //private readonly ILogNet logNet = new LogNetDateTime(AppContext.BaseDirectory + "PLCLogs", GenerateMode.ByEveryDay);//按每天; // 日志
        public SiemensS7Net SiemensS7_SamplePreparation { get; set; }

        readonly ILogger<SamplePreparationPlc> _logger;
        public Hygp_SamplePreparationPlc(ILogger<SamplePreparationPlc> logger)
        {
            _logger = logger;
            SiemensS7_SamplePreparation = new SiemensS7Net(SiemensPLCS.S1200, ipAddress_SamplePreparationPLC) { ConnectTimeOut = _baseConnectTimeOutDelay };
            SiemensS7_SamplePreparation.ConnectServer();
            _backoff = new ExponentialBackoff(_maxRetryDelay, logger); // 基础延迟 100 毫秒  
        }

        /// <summary>
        /// 读取PLC
        /// </summary>
        /// <param name="address">点位</param>
        /// <param name="type">类型</param>
        /// <returns></returns>
        public string PlcRead(string address, string type)
        {
            string data = "";
            _backoff.SendWithBackoff(() =>
            {
                switch (type.ToLower())
                {
                    case "bool":
                        var result = SiemensS7_SamplePreparation.ReadBool(address);
                        if (!result.IsSuccess)
                        {
                            _logger.LogError(result.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result.Message); // 抛出异常以触发重试 
                        }

                        data = result.Content.ToString();
                        break;
                    case "float":
                        var result1 = SiemensS7_SamplePreparation.ReadFloat(address);
                        if (!result1.IsSuccess)
                        {
                            _logger.LogError(result1.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result1.Message); // 抛出异常以触发重试 
                        }

                        data = result1.Content.ToString();
                        break;
                    case "datetime":
                        var result2 = SiemensS7_SamplePreparation.ReadDateTime(address);
                        if (!result2.IsSuccess)
                        {
                            _logger.LogError(result2.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result2.Message); // 抛出异常以触发重试 
                        }

                        data = result2.Content.ToString();
                        break;
                    case "int32":
                    case "int":
                        var result3 = SiemensS7_SamplePreparation.ReadInt32(address);
                        if (!result3.IsSuccess)
                        {
                            _logger.LogError(result3.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result3.Message); // 抛出异常以触发重试 
                        }

                        data = result3.Content.ToString();
                        break;
                    case "int16":
                        var result4 = SiemensS7_SamplePreparation.ReadInt16(address);
                        if (!result4.IsSuccess)
                        {
                            _logger.LogError(result4.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result4.Message); // 抛出异常以触发重试 
                        }

                        data = result4.Content.ToString();
                        break;
                    case "string":
                        var result5 = SiemensS7_SamplePreparation.ReadString(address);
                        if (!result5.IsSuccess)
                        {
                            _logger.LogError(result5.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result5.Message); // 抛出异常以触发重试 
                        }

                        data = result5.Content.ToString();
                        break;
                    case "double":
                        var result6 = SiemensS7_SamplePreparation.ReadDouble(address);
                        if (!result6.IsSuccess)
                        {
                            _logger.LogError(result6.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result6.Message); // 抛出异常以触发重试 
                        }

                        data = result6.Content.ToString();
                        break;
                    case "byte":
                        var result7 = SiemensS7_SamplePreparation.ReadByte(address);
                        if (!result7.IsSuccess)
                        {
                            _logger.LogError(result7.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result7.Message); // 抛出异常以触发重试 
                        }

                        data = result7.Content.ToString();
                        break;
                    default:
                        throw new ArgumentException("Unsupported type");

                }

            }, maxRetries: _maxRetryCount); // 最大重试次数  

            return data;
        }

        /// <summary>
        /// 读取PLC
        /// </summary>
        /// <param name="address">点位</param>
        /// <param name="type">类型</param>
        /// <returns></returns>
        public async Task<string> PlcReadAsync(string address, string type)
        {
            string data = "";
            _backoff.SendWithBackoff(async () =>
            {
                switch (type.ToLower())
                {
                    case "bool":
                        var result = await SiemensS7_SamplePreparation.ReadBoolAsync(address);
                        if (!result.IsSuccess)
                        {
                            _logger.LogError(result.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result.Message); // 抛出异常以触发重试 
                        }

                        data = result.Content.ToString();
                        break;
                    case "float":
                        var result1 = await SiemensS7_SamplePreparation.ReadFloatAsync(address);
                        if (!result1.IsSuccess)
                        {
                            _logger.LogError(result1.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result1.Message); // 抛出异常以触发重试 
                        }

                        data = result1.Content.ToString();
                        break;
                    case "datetime":
                        var result2 = await SiemensS7_SamplePreparation.ReadDateTimeAsync(address);
                        if (!result2.IsSuccess)
                        {
                            _logger.LogError(result2.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result2.Message); // 抛出异常以触发重试 
                        }

                        data = result2.Content.ToString();
                        break;
                    case "int32":
                    case "int":
                        var result3 = await SiemensS7_SamplePreparation.ReadInt32Async(address);
                        if (!result3.IsSuccess)
                        {
                            _logger.LogError(result3.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result3.Message); // 抛出异常以触发重试 
                        }

                        data = result3.Content.ToString();
                        break;
                    case "int16":
                        var result4 = await SiemensS7_SamplePreparation.ReadInt16Async(address);
                        if (!result4.IsSuccess)
                        {
                            _logger.LogError(result4.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result4.Message); // 抛出异常以触发重试 
                        }

                        data = result4.Content.ToString();
                        break;
                    case "string":
                        var result5 = await SiemensS7_SamplePreparation.ReadStringAsync(address);
                        if (!result5.IsSuccess)
                        {
                            _logger.LogError(result5.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result5.Message); // 抛出异常以触发重试 
                        }

                        data = result5.Content.ToString();
                        break;
                    case "double":
                        var result6 = await SiemensS7_SamplePreparation.ReadDoubleAsync(address);
                        if (!result6.IsSuccess)
                        {
                            _logger.LogError(result6.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result6.Message); // 抛出异常以触发重试 
                        }

                        data = result6.Content.ToString();
                        break;
                    case "byte":
                        var result7 = await SiemensS7_SamplePreparation.ReadByteAsync(address);
                        if (!result7.IsSuccess)
                        {
                            _logger.LogError(result7.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result7.Message); // 抛出异常以触发重试 
                        }

                        data = result7.Content.ToString();
                        break;
                    default:
                        throw new ArgumentException("Unsupported type");

                }

            }, maxRetries: _maxRetryCount); // 最大重试次数  

            return data;
        }

        /// <summary>
        /// 写入PLC
        /// </summary>
        /// <param name="address">点位</param>
        /// <param name="value">值</param>
        /// <param name="type">类型</param>
        /// <returns></returns>
        public OperateResult PlcWrite(string address, object value, string type)
        {
            lock (Lockobj)
            {
                var result = new OperateResult();
                //while (true)
                //{
                _backoff.SendWithBackoff(() =>
                {
                    try
                    {
                        switch (type.ToLower())
                        {
                            case "bool":
                                result = SiemensS7_SamplePreparation.Write(address, Convert.ToBoolean(value));
                                break;
                            case "float":
                                result = SiemensS7_SamplePreparation.Write(address, Convert.ToSingle(value));
                                break;
                            case "datetime":
                                result = SiemensS7_SamplePreparation.Write(address, Convert.ToDateTime(value));
                                break;
                            case "int32":
                            case "int":
                                result = SiemensS7_SamplePreparation.Write(address, Convert.ToInt32(value));
                                break;
                            case "int16":
                                result = SiemensS7_SamplePreparation.Write(address, Convert.ToInt16(value));
                                break;
                            case "string":
                                result = SiemensS7_SamplePreparation.Write(address, Convert.ToString(value));
                                break;
                            case "byte":
                                result = SiemensS7_SamplePreparation.Write(address, Convert.ToByte(value));
                                break;
                            default:
                                throw new ArgumentException("Unsupported type");
                        }

                        if (!result.IsSuccess)
                        {
                            _logger.LogError(result.Message);
                            //Thread.Sleep(1000);
                            //continue;
                            throw new Exception(result.Message); // 抛出异常以触发重试 
                        }

                        //return result;
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex.Message + ex.StackTrace);
                        throw; // 重新抛出异常以便重试
                    }
                }, maxRetries: _maxRetryCount); // 最大重试次数  
                return result;
                //Thread.Sleep(1000);
                //}
            }
        }

        /// <summary>
        /// 写入PLC
        /// </summary>
        /// <param name="address">点位</param>
        /// <param name="value">值</param>
        /// <param name="type">类型</param>
        /// <returns></returns>
        public async Task<OperateResult> PlcWriteAsync(string address, object value, string type)
        {
            //lock (Lockobj)
            //{
            var result = new OperateResult();
            //while (true)
            //{
            _backoff.SendWithBackoff(async () =>
            {
                try
                {
                    switch (type.ToLower())
                    {
                        case "bool":
                            result = await SiemensS7_SamplePreparation.WriteAsync(address, Convert.ToBoolean(value));
                            break;
                        case "float":
                            result = await SiemensS7_SamplePreparation.WriteAsync(address, Convert.ToSingle(value));
                            break;
                        case "datetime":
                            result = await SiemensS7_SamplePreparation.WriteAsync(address, Convert.ToDateTime(value));
                            break;
                        case "int32":
                        case "int":
                            result = await SiemensS7_SamplePreparation.WriteAsync(address, Convert.ToInt32(value));
                            break;
                        case "int16":
                            result = await SiemensS7_SamplePreparation.WriteAsync(address, Convert.ToInt16(value));
                            break;
                        case "string":
                            result = await SiemensS7_SamplePreparation.WriteAsync(address, Convert.ToString(value));
                            break;
                        case "byte":
                            result = await SiemensS7_SamplePreparation.WriteAsync(address, Convert.ToByte(value));
                            break;
                        default:
                            throw new ArgumentException("Unsupported type");
                    }

                    if (!result.IsSuccess)
                    {
                        _logger.LogError(result.Message);
                        //Thread.Sleep(1000);
                        //continue;
                        throw new Exception(result.Message); // 抛出异常以触发重试 
                    }

                    //return result;
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex.Message + ex.StackTrace);
                    throw; // 重新抛出异常以便重试
                }
            }, maxRetries: _maxRetryCount); // 最大重试次数  
            return result;
            //Thread.Sleep(1000);
            //}
            //}
        }

        /// <summary>
        /// 批量读取PLC点位值.
        /// Batches the read.
        /// </summary>
        /// <param name="pointList">The point list.</param>
        /// <returns></returns>
        public List<PLCPointData> BatchRead(List<PLCPointData> pointList)
        {
            List<string> plcAddress = new List<string>();
            ushort[] dataLength = new ushort[pointList.Count];
            int index = 0;
            foreach (var point in pointList)
            {
                dataLength[index] = (ushort)point.DataLength;
                index++;
                plcAddress.Add(point.Address);
            }

            OperateResult<byte[]> resultData = SiemensS7_SamplePreparation.Read(plcAddress.ToArray(), dataLength);
            if (resultData.IsSuccess)
            {
                index = 0;
                for (int i = 0; i < pointList.Count; i++)
                {
                    ByteTrans(resultData.Content, pointList[i], index);
                    index += pointList[i].DataLength;
                }
            }
            else
            {
                PLCPointData pointData = new PLCPointData();
                pointData = pointList[0];
                pointData.ResultMsg = resultData.Message;

                pointList.Clear();

                pointList.Add(pointData);
            }

            return pointList;
        }

        /// <summary>
        /// 批量读取PLC点位值.
        /// Batches the read.
        /// </summary>
        /// <param name="pointList">The point list.</param>
        /// <returns></returns>
        public async Task<List<PLCPointData>> BatchReadAsync(List<PLCPointData> pointList)
        {
            List<string> plcAddress = new List<string>();
            ushort[] dataLength = new ushort[pointList.Count];
            int index = 0;
            foreach (var point in pointList)
            {
                dataLength[index] = (ushort)point.DataLength;
                index++;
                plcAddress.Add(point.Address);
            }

            OperateResult<byte[]> resultData = await SiemensS7_SamplePreparation.ReadAsync(plcAddress.ToArray(), dataLength);
            if (resultData.IsSuccess)
            {
                index = 0;
                for (int i = 0; i < pointList.Count; i++)
                {
                    ByteTrans(resultData.Content, pointList[i], index);
                    index += pointList[i].DataLength;
                }
            }
            else
            {
                PLCPointData pointData = new PLCPointData();
                pointData = pointList[0];
                pointData.ResultMsg = resultData.Message;

                pointList.Clear();

                pointList.Add(pointData);
            }

            return pointList;
        }

        /// <summary>
        /// 写入PLC点位值.
        /// the write.
        /// </summary>
        /// <param name="pLCPoint">The p lc point.</param>
        /// <returns></returns>
        public PLCPointData Write(PLCPointData pLCPoint)
        {
            lock (Lockobj)
            {
                if (pLCPoint.ResultData is JsonElement)
                {
                    pLCPoint.ResultData = ConvertValueKind(pLCPoint.ResultData);
                }

                if (pLCPoint.ResultData == null)
                {
                    pLCPoint.ResultCode = 0;
                    pLCPoint.ResultMsg = $"参数中缺少ResultData值";
                    return pLCPoint;
                }

                var result = new OperateResult();
                try
                {
                    Type type = ConvertPointDataType(pLCPoint.DataType);
                    string value = pLCPoint.ResultData.ToString();
                    if (type == typeof(bool))
                    {
                        result = SiemensS7_SamplePreparation.Write(pLCPoint.Address, bool.Parse(value));
                    }
                    else if (type == typeof(byte))
                    {
                        result = SiemensS7_SamplePreparation.Write(pLCPoint.Address, byte.Parse(value));
                    }
                    else if (type == typeof(float))
                    {
                        result = SiemensS7_SamplePreparation.Write(pLCPoint.Address, float.Parse(value));
                    }
                    else if (type == typeof(double))
                    {
                        result = SiemensS7_SamplePreparation.Write(pLCPoint.Address, double.Parse(value));
                    }
                    else if (type == typeof(DateTime))
                    {
                        result = SiemensS7_SamplePreparation.Write(pLCPoint.Address, DateTime.Parse(value));
                    }
                    else if (type == typeof(int))
                    {
                        result = SiemensS7_SamplePreparation.Write(pLCPoint.Address, int.Parse(value));
                    }
                    else if (type == typeof(short))
                    {
                        result = SiemensS7_SamplePreparation.Write(pLCPoint.Address, Convert.ToInt16(value));
                    }
                    else
                    {
                        result = SiemensS7_SamplePreparation.Write(pLCPoint.Address, value, pLCPoint.DataLength);
                    }

                    pLCPoint.ResultCode = result.IsSuccess ? 1 : 0;
                    pLCPoint.ResultMsg = result.IsSuccess ? "Success" : result.Message;
                    return pLCPoint;
                }
                catch (Exception ex)
                {
                    pLCPoint.ResultCode = 0;
                    pLCPoint.ResultMsg = $"(写入)失败:{ex.Message}{ex.StackTrace}";
                    return pLCPoint;
                }
            }
        }

        /// <summary>
        /// 写入PLC点位值.
        /// the write.
        /// </summary>
        /// <param name="pLCPoint">The p lc point.</param>
        /// <returns></returns>
        public async Task<PLCPointData> WriteAsync(PLCPointData pLCPoint)
        {
            //lock (Lockobj)
            //{
            if (pLCPoint.ResultData is JsonElement)
            {
                pLCPoint.ResultData = ConvertValueKind(pLCPoint.ResultData);
            }

            if (pLCPoint.ResultData == null)
            {
                pLCPoint.ResultCode = 0;
                pLCPoint.ResultMsg = $"参数中缺少ResultData值";
                return pLCPoint;
            }

            var result = new OperateResult();
            try
            {
                Type type = ConvertPointDataType(pLCPoint.DataType);
                string value = pLCPoint.ResultData.ToString();
                if (type == typeof(bool))
                {
                    result = await SiemensS7_SamplePreparation.WaitAsync(pLCPoint.Address, bool.Parse(value));
                }
                else if (type == typeof(byte))
                {
                    result = await SiemensS7_SamplePreparation.WriteAsync(pLCPoint.Address, byte.Parse(value));
                }
                else if (type == typeof(float))
                {
                    result = await SiemensS7_SamplePreparation.WriteAsync(pLCPoint.Address, float.Parse(value));
                }
                else if (type == typeof(double))
                {
                    result = await SiemensS7_SamplePreparation.WriteAsync(pLCPoint.Address, double.Parse(value));
                }
                else if (type == typeof(DateTime))
                {
                    result = await SiemensS7_SamplePreparation.WriteAsync(pLCPoint.Address, DateTime.Parse(value));
                }
                else if (type == typeof(int))
                {
                    result = await SiemensS7_SamplePreparation.WriteAsync(pLCPoint.Address, int.Parse(value));
                }
                else if (type == typeof(short))
                {
                    result = await SiemensS7_SamplePreparation.WriteAsync(pLCPoint.Address, Convert.ToInt16(value));
                }
                else
                {
                    result = await SiemensS7_SamplePreparation.WriteAsync(pLCPoint.Address, value, pLCPoint.DataLength);
                }

                pLCPoint.ResultCode = result.IsSuccess ? 1 : 0;
                pLCPoint.ResultMsg = result.IsSuccess ? "Success" : result.Message;
                return pLCPoint;
            }
            catch (Exception ex)
            {
                pLCPoint.ResultCode = 0;
                pLCPoint.ResultMsg = $"(写入)失败:{ex.Message}{ex.StackTrace}";
                return pLCPoint;
            }
            //}
        }

        /// <summary>
        /// Bytes the trans.
        /// </summary>
        /// <param name="content">The content.</param>
        /// <param name="pLCPoint">The p lc point.</param>
        /// <param name="index">The index.</param>
        private void ByteTrans(byte[] content, PLCPointData pLCPoint, int index)
        {
            try
            {
                Type type = ConvertPointDataType(pLCPoint.DataType);
                if (type == typeof(bool))
                {
                    pLCPoint.ResultCode = 1;
                    pLCPoint.ResultMsg = "Success";
                    pLCPoint.ResultData = SiemensS7_SamplePreparation.ByteTransform.TransBool(content, index);
                }
                else if (type == typeof(byte))
                {
                    pLCPoint.ResultCode = 1;
                    pLCPoint.ResultMsg = "Success";
                    pLCPoint.ResultData = SiemensS7_SamplePreparation.ByteTransform.TransByte(content, index);
                }
                else if (type == typeof(float))
                {
                    pLCPoint.ResultCode = 1;
                    pLCPoint.ResultMsg = "Success";
                    pLCPoint.ResultData = SiemensS7_SamplePreparation.ByteTransform.TransSingle(content, index);
                }
                else if (type == typeof(double))
                {
                    pLCPoint.ResultCode = 1;
                    pLCPoint.ResultMsg = "Success";
                    pLCPoint.ResultData = SiemensS7_SamplePreparation.ByteTransform.TransDouble(content, index);
                }
                else if (type == typeof(int))
                {
                    pLCPoint.ResultCode = 1;
                    pLCPoint.ResultMsg = "Success";
                    pLCPoint.ResultData = SiemensS7_SamplePreparation.ByteTransform.TransInt32(content, index);
                }
                else
                {
                    pLCPoint.ResultCode = 1;
                    pLCPoint.ResultMsg = "Success";
                    pLCPoint.ResultData = SiemensS7_SamplePreparation.ByteTransform.TransString(content, index, pLCPoint.DataLength, Encoding.ASCII).Replace("\0", "").Replace("\u0001", "");
                }
            }
            catch (Exception ex)
            {
                pLCPoint.ResultCode = 0;
                pLCPoint.ResultMsg = $"(读取)错误:{ex.Message}{ex.StackTrace}";
            }
        }

        /// <summary>
        /// 数据类型转换
        /// </summary>
        /// <param name="dataType"></param>
        /// <returns></returns>
        private Type ConvertPointDataType(string dataType)
        {
            Type type = null;
            switch (dataType.Trim().ToLower())
            {
                case "bool":
                    type = typeof(bool);
                    break;
                case "byte":
                    type = typeof(byte);
                    break;
                case "int":
                    type = typeof(int);
                    break;
                case "datetime":
                    type = typeof(DateTime);
                    break;
                case "dint":
                    type = typeof(int);
                    break;
                case "real":
                    type = typeof(float);
                    break;
                case "lreal":
                    type = typeof(double);
                    break;
                case "lint":
                    type = typeof(long);
                    break;
                case "string":
                    type = typeof(string);
                    break;
                case "short":
                    type = typeof(short);
                    break;
                default:
                    {
                        AddSysError(SiemensS7_SamplePreparation.IpAddress, $"{dataType}数据类型不存在");
                        //throw new ArgumentOutOfRangeException(dataType, "数据类型不存在");
                        break;
                    }

            }

            return type;
        }

        /// <summary>
        /// Converts the kind of the value.
        /// </summary>
        /// <param name="element">The element.</param>
        /// <returns></returns>
        private object? ConvertValueKind(JsonElement element)
        {
            switch (element.ValueKind)
            {
                case JsonValueKind.String: return element.GetString();
                case JsonValueKind.Null: return null;
                case JsonValueKind.False: return false;
                case JsonValueKind.True: return true;
                case JsonValueKind.Number: return element.GetDouble();
                case JsonValueKind.Object: return element.ValueKind.ToString();
                default: break;
            }

            return element;
        }

        /// <summary>
        /// Adds the system message.
        /// </summary>
        /// <param name="msg">The MSG.</param>
        private void AddSysMessage(string msg)
        {
            //logNet.WriteInfo(msg);
            _logger.LogInformation(msg);
        }

        /// <summary>
        /// Adds the system error.
        /// </summary>
        /// <param name="plcIp">The PLC ip.</param>
        /// <param name="error">The error.</param>
        private void AddSysError(string plcIp, string error)
        {
            //logNet.WriteError(plcIp, error);
            _logger.LogError(plcIp + ", error:" + error);
        }
    }
}

 

这段代码定义了一个名为 `SamplePreparationPlc` 的类,用于与西门子S7-1200 PLC进行通信。该类提供了读取和写入PLC点位的方法,并支持异步操作。下面是对代码的详细解释:

### 类成员变量

- `Lockobj`:一个 `object` 类型的对象,用于在写入PLC时进行锁定,防止多线程同时写入。
- `_backoff`:一个 `ExponentialBackoff` 对象,用于实现指数退避重试机制。
- `_maxRetryCount`:最大重试次数。
- `_maxRetryDelay`:最大重试延迟时间(毫秒)。
- `_baseConnectTimeOutDelay`:基础连接超时时间(毫秒)。
- `ipAddress_SamplePreparationPLC`:PLC的IP地址,从配置文件中读取,如果没有配置则使用默认值。
- `SiemensS7_SamplePreparation`:一个 `SiemensS7Net` 对象,用于与PLC进行通信。
- `_logger`:一个 `ILogger<SamplePreparationPlc>` 对象,用于记录日志。

### 构造函数

- 在构造函数中,初始化 `_logger` 对象,并创建 `SiemensS7Net` 对象,并尝试连接到PLC。如果连接失败,则记录错误日志。

### 方法

1. **PlcRead(string address, string type)**:同步读取PLC点位数据。
- 根据点位类型(如 `bool`、`float` 等)调用相应的 `Read` 方法。
- 如果读取失败,记录错误日志并抛出异常以触发重试。
- 返回读取到的数据。

2. **PlcReadAsync(string address, string type)**:异步读取PLC点位数据。
- 与 `PlcRead` 方法类似,但使用异步方法进行读取。

3. **PlcWrite(string address, object value, string type)**:同步写入PLC点位数据。
- 使用 `lock` 确保写入操作的线程安全。
- 根据点位类型调用相应的 `Write` 方法。
- 如果写入失败,记录错误日志并抛出异常以触发重试。
- 返回操作结果。

4. **PlcWriteAsync(string address, object value, string type)**:异步写入PLC点位数据。
- 与 `PlcWrite` 方法类似,但使用异步方法进行写入。

5. **BatchRead(List<PLCPointData> pointList)**:批量读取PLC点位数据。
- 将点位地址和数据长度转换为数组,调用 `Read` 方法进行批量读取。
- 根据读取到的数据,填充 `PLCPointData` 对象并返回。

6. **BatchReadAsync(List<PLCPointData> pointList)**:异步批量读取PLC点位数据。
- 与 `BatchRead` 方法类似,但使用异步方法进行读取。

7. **Write(PLCPointData pLCPoint)**:同步写入PLC点位数据。
- 使用 `lock` 确保写入操作的线程安全。
- 根据点位类型调用相应的 `Write` 方法。
- 返回操作结果。

8. **WriteAsync(PLCPointData pLCPoint)**:异步写入PLC点位数据。
- 与 `Write` 方法类似,但使用异步方法进行写入。

9. **ByteTrans(byte[] content, PLCPointData pLCPoint, int index)**:字节转换方法。
- 根据点位类型,将字节数组转换为相应的数据类型,并填充到 `PLCPointData` 对象中。

10. **ConvertPointDataType(string dataType)**:数据类型转换方法。
- 将字符串类型的数据类型转换为 `Type` 对象。

11. **ConvertValueKind(JsonElement element)**:值类型转换方法。
- 将 `JsonElement` 对象转换为相应的值类型。

12. **AddSysMessage(string msg)**:添加系统消息日志。
- 记录系统消息日志。

13. **AddSysError(string plcIp, string error)**:添加系统错误日志。
- 记录系统错误日志。

### 注意事项

- 代码中使用了 `lock` 关键字来确保写入操作的线程安全。
- 使用了指数退避重试机制来处理读取和写入操作中的异常情况。
- 日志记录使用了 `ILogger` 接口,便于日志的配置和输出。
- 代码中包含了一些异常处理逻辑,确保在发生错误时能够记录日志并重新抛出异常以触发重试。

 

posted on 2025-01-05 09:19  HackerVirus  阅读(730)  评论(0)    收藏  举报