首页 > 其他分享 >使用HslCommunication类库读取Siemens PLC DATA

使用HslCommunication类库读取Siemens PLC DATA

时间:2025-01-05 09:23:01浏览次数:1  
标签:类库 case HslCommunication type SiemensS7 Siemens pLCPoint result SamplePreparatio

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` 接口,便于日志的配置和输出。
- 代码中包含了一些异常处理逻辑,确保在发生错误时能够记录日志并重新抛出异常以触发重试。

 

标签:类库,case,HslCommunication,type,SiemensS7,Siemens,pLCPoint,result,SamplePreparatio
From: https://www.cnblogs.com/Leo_wl/p/18653031

相关文章

  • 使用 WPF HelixToolkit类库实现多个 SEG-Y 数据文件的三维地震模型渲染
    一、背景在地震勘探和数据可视化中,三维地震数据的渲染对于理解地下结构至关重要。随着地震数据量的增加,如何高效地渲染多个SEG-Y文件,并通过三维模型展现其振幅信息,成为一个值得研究的课题。本文将展示如何利用WPF和HelixToolkit工具包,加载和渲染多个SEG-Y文件,生成三维地......
  • GeneticSharp 遗传算法类库
    GeneticSharp是什么GeneticSharp是一个C#的遗传算法类库,遗传算法Java著名的JMetal,Python也有JMetalPy和PyMoo,C#相对差一截,稍微有名的是GeneticSharp库.GeneticSharp的弱点:不支持多目标优化没有实现流行的NSGAII算法,缺少拥挤度等计算,所以解的多样性要差一些......
  • 基础类库
    基础类库consoleconsole.log方法用于在console窗口输出信息。它可以接受多个参数,将它们的结果连接起来输出。Math属性ELN10LN2LOG2ELOG10EPISQRT1_2SQRT2以上属性的具体使用请参考ES5标准。方法absacosasinatanatan2ceilcosexpfloorlogmaxmin......
  • AWC2406分类库配置
    1)新版本的分类库视图:节点视图:前端用户可见的视图;类视图:实际存储分类对象的视图,同原来胖客户端的分类管理的视图;2)在Linux环境启动cmd命令窗口:TC_ROOT=/usr/Siemens/Teamcenterversion; export TC_ROOTTC_DATA=/usr/Siemens/Teamcenterversion/teamcenterdata; export TC_D......
  • 你有阅读过哪些类库的源码吗?你是如何阅读的?
    一、选择合适的类库在开始阅读源码之前,首先要选择一个合适的类库。可以根据自己的工作需求、技术兴趣或学习目标来选择。一些流行的前端类库如React、Vue、Angular等,它们的源码都是公开可查的,而且有着丰富的社区资源和文档支持。二、了解类库的整体架构在开始深入阅读源码之前,......
  • 现如今面对如层出不穷的类库,说说你的感受
    在前端开发领域,随着技术的快速发展,我们确实看到了层出不穷的类库和框架。这些工具为开发者提供了更多的选择和可能性,但同时也带来了一些挑战和考虑。以下是我对当前前端开发中众多类库的感受:选择多样性:如今,前端开发者可以从众多的类库中选择,以满足特定的项目需求。这种多样性使......
  • 你有看过哪些框架或者类库的源码吗?通过看源码可以收获什么?
    我看过不少前端框架和类库的源码,主要集中在一些比较流行和核心的库,例如:React:重点关注过ReactDOM.render、useState、useEffect、fiber架构、reconciliation算法等部分的实现。Vue:研究过响应式系统reactive、ref、computed的实现,模板编译原理,以及v-dom的diff算法。Redux:......
  • Python 客户端类库之paho-mqtt学习总结
    实践环境Python3.9.13paho-mqtt2.1.0简介EclipsePahoMQTTPython客户端类库实现了MQTT协议版本5.0,3.1.1,和3.1。该类库提供一个客户端类,允许应用连接到MQTT代理并发布消息,订阅主题并检索发布的消息。同时还提供了一个写其它辅助函数,使向MQTT服务器发布一次性消息变......
  • .NET 开源高性能 MQTT 类库
    目录前言项目介绍功能说明客户端功能服务器功能功能特点应用场景使用方法1、安装MQTTnet2、服务端代码3、客户端代码项目地址总结最后前言随着物联网(IoT)技术的迅猛发展,MQTT(消息队列遥测传输)协议凭借其轻量级和高效性,已成为众多物联网应用的首选通信标准。......
  • 3款C#开源且实用的工具类库,工作效率提升利器!
    前言在日常工作开发中工具类库是软件开发中不可或缺的一部分,它们通过提供代码重用、通用功能、隐藏复杂性、提高代码质量、扩展性等方面的优势,帮助开发者更高效、更稳定地构建软件应用程序。今天大姚给大家分享3款C#开源且实用的工具类库,希望能帮助到有需要的小伙伴。Masuit.Tools......