SiemensHelp.cs 11.1 KB
using HslCommunication;
using HslCommunication.Profinet.Siemens;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace HH_WCS_Standard
{
    public class SiemensHelp : I_OpcHelp
    {
        private HslCommunication.Core.IByteTransform ByteTransform = new HslCommunication.Core.ReverseBytesTransform();
        private SiemensS7Net siemensS7Net;

        public SiemensHelp(SiemensPLCS siemensPLCS, string ip)
        {
            this.ip = ip;
            siemensS7Net = new SiemensS7Net(siemensPLCS, ip) { ConnectTimeOut = 5000, ReceiveTimeOut = 5000 };
        }

        /// <summary>
        /// 打开S7 Net长连接
        /// </summary>
        /// <returns></returns>
        public override BllResult OpenConn()
        {
            try
            {
                if (!ConnectB)
                {
                    OperateResult connect = siemensS7Net.ConnectServer();
                    if (!connect.IsSuccess)
                    {
                        return BllResult.Error(connect.Message);
                    }
                    else
                    {
                        ConnectB = true;
                        return BllResult.Sucess();
                    }
                }
                else
                {
                    return BllResult.Sucess();
                }
            }
            catch (Exception ex)
            {
                return BllResult.Error(ex);
            }
        }

        /// <summary>
        /// 关闭S7 Net长连接
        /// </summary>
        /// <returns></returns>
        public override BllResult CloseConn()
        {
            try
            {
                if (ConnectB)
                {
                    OperateResult connect = siemensS7Net.ConnectClose();
                    if (connect.IsSuccess)
                    {
                        ConnectB = false;
                        return BllResult.Sucess();
                    }
                    else
                    {
                        return BllResult.Error(connect.Message);
                    }
                }
                else
                {
                    return BllResult.Sucess();
                }
            }
            catch (Exception ex)
            {
                return BllResult.Error(ex);
            }
        }

        //获取各数据类型长度
        public override ushort GetTypeLength(string addresstype)
        {
            switch (addresstype)
            {
                case "BYTE": return 1;
                case "LWORD": return 8;
                case "BOOL": return 1;
                case "INT": return 2;
                case "DINT": return 4;
                case "REAL": return 4;
                case "CHAR": return 20;
                case "STRING": return 20;
                default: return 0;
            }
        }

        private BllResult ReadOneDB(List<I_Device_Address> address)
        {
            address = address.OrderBy(a => a.Address).ToList();
            OperateResult<byte[]> read;
            if (address.Count == 1)
            {
                string startaddress = address[0].Db + "." + address[0].Address.ToString();
                read = siemensS7Net.Read(startaddress, GetTypeLength(address[0].AddressType));
            }
            else
            {
                double admax = address.Select(a => a.Address).Max();
                double admin = address.Select(a => a.Address).Min();
                ushort length = (ushort)(Math.Floor(admax - admin) + GetTypeLength(address.Last().AddressType));
                string startaddress = address[0].Db + "." + admin.ToString();
                read = siemensS7Net.Read(startaddress, length);
            }
            if (read.IsSuccess)
            {
                if (TransforWCSDataToAddressData(address, read).Success)
                {
                    return BllResult.Sucess(address, "成功");
                }
                else
                {
                    return BllResult.Sucess(address, "成功");
                }
            }
            else
            {
                return BllResult.Error(read.Message);
            }
        }

        public override BllResult ReadAddress(List<I_Device_Address> address)
        {
            List<List<I_Device_Address>> i_Device_s = new List<List<I_Device_Address>>();
            var ulist = address.GroupBy(a => a.Db).ToList();
            foreach (var u in ulist)
            {
                var readresult = ReadOneDB(u.ToList());
                if (!readresult.Success)
                {
                    return BllResult.Error(readresult.Msg);
                }
            }
            return BllResult.Sucess(address, "成功");
        }

        public override BllResult WriteAddress(List<I_Device_Address> address)
        {
            address = address.OrderBy(a => a.Address).ToList();
            string startaddress = address[0].Db + "." + address[0].Address.ToString();
            BllResult bllResult = TransforAddressDataToWCSData(address);
            if (bllResult.Success)
            {
                OperateResult operate = siemensS7Net.Write(startaddress, (byte[])bllResult.Data);
                if (operate.IsSuccess)
                {
                    return BllResult.Sucess();
                }
                else
                {
                    return BllResult.Error(operate.Message);
                }
            }
            else
            {
                return BllResult.Error(bllResult.Msg);
            }
        }

        public BllResult WriteBool(I_Device_Address address)
        {
            string startaddress = address.Db + "." + address.Address.ToString() + "." + address.Address_decimal;
            OperateResult operate = siemensS7Net.Write(startaddress, bool.Parse(address.value));
            if (operate.IsSuccess)
            {
                return BllResult.Sucess();
            }
            else
            {
                return BllResult.Error(operate.Message);
            }
        }

        public override BllResult TransforWCSDataToAddressData(List<I_Device_Address> address, OperateResult<byte[]> read)
        {
            try
            {
                //按偏移量排序
                address = address.OrderBy(a => a.Address).ToList();
                int startindex = address[0].Address;
                for (int i = 0; i < address.Count; i++)
                {
                    int index = address[i].Address - startindex;
                    switch (address[i].AddressType)
                    {
                        case "BYTE":
                            address[i].value = ByteTransform.TransByte(read.Content, index).ToString();
                            break;

                        case "REAL":
                            address[i].value = ByteTransform.TransSingle(read.Content, index).ToString();
                            break;

                        case "LWORD":
                            address[i].value = Convert.ToString(ByteTransform.TransInt64(read.Content, index), 16); ;
                            break;

                        case "BOOL":
                            address[i].value = ByteTransform.TransBool(read.Content, index, 1)[address[i].Address_decimal].ToString();
                            break;

                        case "INT":
                            address[i].value = ByteTransform.TransInt16(read.Content, index).ToString();
                            break;

                        case "DINT":
                            address[i].value = Convert.ToString(ByteTransform.TransInt32(read.Content, index), 10);
                            break;

                        case "CHAR":
                            address[i].value = Encoding.ASCII.GetString(read.Content, index, 20).Replace(" ", "").Replace("\0", "").Replace("\u0003", "");
                            break;

                        default:
                            return BllResult.Error("找不到未知的数据类型");
                    }
                }
                return BllResult.Sucess(address);
            }
            catch (Exception ex)
            {
                return BllResult.Error($"转换WCS数据失败{ex.Message}");
            }
        }

        public override BllResult TransforAddressDataToWCSData(List<I_Device_Address> address) //返回一个byte[]
        {
            try
            {
                address = address.OrderBy(a => a.Address).ToList();
                double admax = address.Select(a => a.Address).Max();
                double admin = address.Select(a => a.Address).Min();
                ushort length = (ushort)(Math.Floor(admax - admin) + GetTypeLength(address.Last().AddressType));
                int startindex = address[0].Address;
                byte[] writebyte = new byte[length];
                for (int i = 0; i < address.Count; i++)
                {
                    int index = address[i].Address - startindex;
                    object value = address[i].value;
                    switch (address[i].AddressType)
                    {
                        case "BYTE":
                            byte tobyte = Convert.ToByte(value);
                            ByteTransform.TransByte(tobyte).CopyTo(writebyte, index);
                            break;

                        case "LWORD":
                            if ((string)value == "") value = null;
                            long tolong = Convert.ToInt64((string)value, 16);
                            ByteTransform.TransByte(tolong).CopyTo(writebyte, index);
                            break;

                        case "BOOL":
                            bool[] tobool = ByteTransform.TransBool(writebyte, index, 1);
                            tobool[address[i].Address_decimal] = bool.Parse(address[i].value);
                            ByteTransform.TransByte(tobool).CopyTo(writebyte, index);
                            break;

                        case "INT":
                            short toint = Convert.ToInt16(value);
                            ByteTransform.TransByte(toint).CopyTo(writebyte, index);
                            break;

                        case "DINT":
                            int todint = Convert.ToInt32(value);
                            ByteTransform.TransByte(todint).CopyTo(writebyte, index);
                            break;

                        case "REAL":
                            float todreal = Convert.ToSingle(value);
                            ByteTransform.TransByte(todreal).CopyTo(writebyte, index);
                            break;

                        case "CHAR":
                            byte[] tochar = Encoding.ASCII.GetBytes(((string)value).PadRight(20, ' '));
                            tochar.CopyTo(writebyte, index);
                            break;

                        default:
                            return BllResult.Error("找不到未知的数据类型");
                    }
                }
                return BllResult.Sucess(writebyte);
            }
            catch (Exception ex)
            {
                return BllResult.Error($"转换WCS数据失败{ex.Message}");
            }
        }
    }
}