SiemensS7Communication.cs 7.37 KB
using DataAcquisition.Common.Enums;
using DataAcquisition.Models;
using HHECS.BllModel;
using HslCommunication;
using HslCommunication.Core.Address;
using HslCommunication.Profinet.Siemens;
using System.Diagnostics;
using System.Text;

namespace DataAcquisition.Common.Communications
{
    /// <summary>
    /// 西门子通信
    /// </summary>
    public class SiemensS7Communication : ICommunication
    {
        public readonly SiemensS7Net Siemens = null!;

        public string IpAddress => Siemens.IpAddress;

        public int CommunicationId { get; set; }

        private SiemensS7Communication() { }

        public SiemensS7Communication(int communicationId, SiemensPLCS siemens, string ipAddress) : this()
        {
            CommunicationId = communicationId;
            Siemens = new SiemensS7Net(siemens, ipAddress);
            Siemens.SetPersistentConnection();
        }
        public BllResult ConnectServer()
        {
            try
            {
                var result = Siemens.ConnectServer();
                if (!result.IsSuccess)
                {
                    return BllResultFactory.Error(result.Message);
                }
                return BllResultFactory.Success();
            }
            catch (Exception ex)
            {
                return BllResultFactory.Error(ex.Message);
            }
        }

        public BllResult ConnectClose()
        {
            Siemens.ConnectClose();
            return BllResultFactory.Success();
        }

        public BllResult Read(IEnumerable<EquipmentProperty> equipmentProperties)
        {
            try
            {
                var addressDatas = new List<S7AddressData>();
                foreach (var item in equipmentProperties)
                {
                    ushort byteLength = GetByteLength(item);
                    var i = item.DataAddress.IndexOf(',');
                    var address = i > 0 ? item.DataAddress[..i] : item.DataAddress;
                    var parseResult = S7AddressData.ParseFrom(address, byteLength);
                    if (!parseResult.IsSuccess)
                    {
                        return BllResultFactory.Error(parseResult.Message);
                    }
                    addressDatas.Add(parseResult.Content);
                }
                var result = Siemens.Read(addressDatas.ToArray());
                if (!result.IsSuccess)
                {
                    return BllResultFactory.Error(result.Message);
                }
                var buffer = result.Content;
                var byteIndex = 0;
                foreach (var item in equipmentProperties)
                {
                    _ = ushort.TryParse(item.DataAddress.Split('.').LastOrDefault(), out var bitIndex);
                    _ = ushort.TryParse(item.DataAddress.Split(',').LastOrDefault() ?? "1", out var dataLength);
                    item.Value = item.DataType switch
                    {
                        DataTypeConst.Float => Siemens.ByteTransform.TransSingle(buffer, byteIndex).ToString(),
                        DataTypeConst.Bool => Convert.ToBoolean(buffer[byteIndex] & 1 << bitIndex).ToString(),
                        DataTypeConst.Byte => Siemens.ByteTransform.TransByte(buffer, byteIndex).ToString(),
                        DataTypeConst.Int16 => Siemens.ByteTransform.TransInt16(buffer, byteIndex).ToString(),
                        DataTypeConst.UInt16 => Siemens.ByteTransform.TransUInt16(buffer, byteIndex).ToString(),
                        DataTypeConst.Int32 => Siemens.ByteTransform.TransInt32(buffer, byteIndex).ToString(),
                        DataTypeConst.UInt32 => Siemens.ByteTransform.TransUInt32(buffer, byteIndex).ToString(),
                        DataTypeConst.Int64 => Siemens.ByteTransform.TransInt64(buffer, byteIndex).ToString(),
                        DataTypeConst.UInt64 => Siemens.ByteTransform.TransUInt64(buffer, byteIndex).ToString(),
                        DataTypeConst.String => Siemens.ByteTransform.TransString(buffer, byteIndex, dataLength, Encoding.ASCII).Replace("\u0003", "").Trim(),
                        _ => string.Empty,
                    };
                    item.UpdateTime = DateTime.Now;
                    byteIndex += GetByteLength(item);
                }
                return BllResultFactory.Success();
            }
            catch (Exception ex)
            {
                return BllResultFactory.Error($"读取PLC[{Siemens.IpAddress}]数据出现异常:{ex.Message}");
            }
        }

        public BllResult Read(EquipmentProperty equipmentProperty)
        {
            return Read([equipmentProperty]);
        }

        public BllResult Write(IEnumerable<EquipmentProperty> equipmentProperties)
        {
            try
            {
                var result = new OperateResult();
                var stopwatch = Stopwatch.StartNew();
                foreach (var item in equipmentProperties)
                {
                    if (item.DataType == DataTypeConst.Bool)
                    {
                        _ = bool.TryParse(item.Value, out bool val);
                        result = Siemens.Write(item.DataAddress, val);
                    }
                    else if (item.DataType == DataTypeConst.Int16)
                    {
                        _ = short.TryParse(item.Value, out short val);
                        result = Siemens.Write(item.DataAddress, val);
                    }
                    else if (item.DataType == DataTypeConst.Float)
                    {
                        _ = float.TryParse(item.Value, out var val);
                        result = Siemens.Write(item.DataAddress, val);
                    }
                    else
                    {
                        var bytes = Encoding.Default.GetBytes(item.Value ?? string.Empty);
                        result = Siemens.Write(item.DataAddress, bytes);
                    }
                    if (!result.IsSuccess)
                    {
                        return BllResultFactory.Error($"写入PLC[{Siemens.IpAddress}]_{item.DataAddress}地址数据失败:{result.Message}");
                    }
                }
                stopwatch.Stop();
                return BllResultFactory.Success($"写入PLC[{Siemens.IpAddress}]地址数据成功,数量{equipmentProperties.Count()},耗时:{stopwatch.Elapsed}");
            }
            catch (Exception ex)
            {
                return BllResultFactory.Error($"写入PLC[{Siemens.IpAddress}]数据出现异常:{ex.Message}");
            }
        }

        public BllResult Write(EquipmentProperty equipmentProperty)
        {
            return Write([equipmentProperty]);
        }

        private static ushort GetByteLength(EquipmentProperty data)
        {
            _ = ushort.TryParse(data.DataAddress.Split(',').LastOrDefault() ?? "1", out var dataLength);

            return data.DataType switch
            {
                DataTypeConst.Bool => 1,
                DataTypeConst.Byte or
                DataTypeConst.String => dataLength,
                DataTypeConst.Int16 => 2,//INT
                DataTypeConst.Int32 => 4,//DINT
                DataTypeConst.UInt16 => 2,//WORD
                DataTypeConst.UInt32 => 4,//DWORD
                DataTypeConst.Int64 => 8,
                DataTypeConst.UInt64 => 8,
                DataTypeConst.Float => 4,//REAL
                _ => dataLength
            };
        }
    }
}