C# 使用S7netplus读取西门子PLC的DB块-S7协议

news2025/1/16 21:19:42

在工业的设备监控领域,S7协议使用比较普遍下面简单教大家使用

1、添加包

2、添加帮助类(读写数据就研究该类即可,具体的理论就不多说了)

//plc中类型与c#类型 bool => Bit
//Byte => byte
//word => ushort
//DWord => uint
//Int => short
//DInt => int
//Real => float
//LReal => double
//String => string
//DateTimeLong=>datetime
//s7wstring=>string
//ReadTimeout,WriteTimeout,分别为读取和写入等待时间
/// <summary>
/// plc帮助类
/// </summary>
public class PlcHelper
{
    /// <summary>
    /// 是否连接
    /// </summary>
    /// <returns></returns>
    public bool IsConnected(Plc Plc)
    {
        if (Plc.IsConnected) { return true; }
        else return false;
    }
    /// <summary>
    /// 连接plc   
    /// </summary>
    /// <param name="cpuType">cpu型号</param>
    /// <param name="ip">plc的ip地址</param>
    /// <param name="rack">机架号</param>
    /// <param name="slot">插槽号</param>
    /// <returns>是否成功</returns>
    /// 默认值填充  在1200中机架号,插槽号通常为0和1。可根据实际情况赋值
    public Plc OpenPlc(Plc Plc, CpuType cpuType = CpuType.S71200, string ip = "127.0.0.1", short rack = 0, short slot = 1)
    {
        Plc = new Plc(cpuType, ip, rack, slot);
        Plc.Open();
        if (Plc.IsConnected) return Plc;
        else return null;
    }
    /// <summary>
    /// 关闭plc连接
    /// </summary>
    /// <param name="plc">引用的plc实例</param>
    public void ClosePlc(Plc plc)
    {
        plc.Close();
    }

    /// <summary>
    /// 读取bool类型
    /// </summary>
    /// <param name="dbBlock">所选择的数据库块</param>
    /// <param name="startByteAdr">数据偏移量</param>
    /// <param name="dataType">数据块类型</param>
    /// <returns></returns>
    public bool ReadBool(Plc Plc, int dbBlock, int startByteAdr, DataType dataType = DataType.DataBlock)
    {
        var result = Plc.Read(dataType, dbBlock, startByteAdr, VarType.Bit, 1);
        return (bool)result;
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="Plc"></param>
    /// <param name="dbBlock">所选择的数据库块</param>
    /// <param name="startByteAdr">数据偏移量</param>
    /// <param name="count">位偏移量</param>
    /// <param name="dataType">数据块类型</param>
    /// <returns></returns>
    public bool ReadBoolByte(Plc Plc, int dbBlock, int startByteAdr, byte count, DataType dataType = DataType.DataBlock)
    {
        var result = Plc.Read(dataType, dbBlock, startByteAdr, VarType.Bit, 1, count);
        return (bool)result;
    }
    /// <summary>
    /// 写入bool类型
    /// </summary>
    /// <param name="dbBlock">所选择的数据库块</param>
    /// <param name="startByteAdr">数据偏移量</param>
    /// <param name="Value">写入值</param>
    /// <param name="dataType">数据块类型</param>
    /// <returns></returns>
    public void WriteBool(Plc Plc, int dbBlock, int startByteAdr, bool Value, DataType dataType = DataType.DataBlock)
    {
        Plc.Write(dataType, dbBlock, startByteAdr, Value);
    }

    /// <summary>
    /// 读取int类型
    /// </summary>
    /// <param name="dbBlock">所选择的数据库块</param>
    /// <param name="startByteAdr">数据偏移量</param>
    /// <param name="dataType">数据块类型</param>
    /// <returns></returns>
    public short ReadInt(Plc Plc, int dbBlock, int startByteAdr, DataType dataType = DataType.DataBlock)
    {
        var result = Plc.Read(dataType, dbBlock, startByteAdr, VarType.Int, 1);
        return (short)result;
    }
    /// <summary>
    /// 写入int类型
    /// </summary>
    /// <param name="dbBlock">所选择的数据库块</param>
    /// <param name="startByteAdr">数据偏移量</param>
    /// <param name="Value">写入值</param>
    /// <param name="dataType">数据块类型</param>
    /// <returns></returns>
    public void WriteInt(Plc Plc, int dbBlock, int startByteAdr, short Value, DataType dataType = DataType.DataBlock)
    {
        Plc.Write(dataType, dbBlock, startByteAdr, Value);
    }

    /// <summary>
    /// 读取Dint类型
    /// </summary>
    /// <param name="dbBlock">所选择的数据库块</param>
    /// <param name="startByteAdr">数据偏移量</param>
    /// <param name="dataType">数据块类型</param>
    /// <returns></returns>
    public int ReadDInt(Plc Plc, int dbBlock, int startByteAdr, DataType dataType = DataType.DataBlock)
    {
        var result = Plc.Read(dataType, dbBlock, startByteAdr, VarType.Int, 1);
        return (int)result;
    }
    /// <summary>
    /// 写入Dint类型
    /// </summary>
    /// <param name="dbBlock">所选择的数据库块</param>
    /// <param name="startByteAdr">数据偏移量</param>
    /// <param name="Value">写入值</param>
    /// <param name="dataType">数据块类型</param>
    /// <returns></returns>
    public void WriteDInt(Plc Plc, int dbBlock, int startByteAdr, int Value, DataType dataType = DataType.DataBlock)
    {
        Plc.Write(dataType, dbBlock, startByteAdr, Value);
    }

    /// <summary>
    /// 读取char类型
    /// </summary>
    /// <param name="dbBlock">所选择的数据库块</param>
    /// <param name="startByteAdr">数据偏移量</param>
    /// <param name="dataType">数据块类型</param>
    /// <returns></returns>
    public char ReadChar(Plc Plc, int dbBlock, int startByteAdr, DataType dataType = DataType.DataBlock)
    {
        var result = Plc.Read(dataType, dbBlock, startByteAdr, VarType.String, 1);
        return (char)result;
    }
    /// <summary>
    /// 写入char类型
    /// </summary>
    /// <param name="dbBlock">所选择的数据库块</param>
    /// <param name="startByteAdr">数据偏移量</param>
    /// <param name="Value">写入值</param>
    /// <param name="dataType">数据块类型</param>
    /// <returns></returns>
    public void WriteChar(Plc Plc, int dbBlock, int startByteAdr, char Value, DataType dataType = DataType.DataBlock)
    {
        Plc.Write(dataType, dbBlock, startByteAdr, Value);
    }

    /// <summary>
    /// 读取byte类型
    /// </summary>
    /// <param name="dbBlock">所选择的数据库块</param>
    /// <param name="startByteAdr">数据偏移量</param>
    /// <param name="dataType">数据块类型</param>
    /// <returns></returns>
    public byte ReadByte(Plc Plc, int dbBlock, int startByteAdr, DataType dataType = DataType.DataBlock)
    {
        var result = Plc.Read(dataType, dbBlock, startByteAdr, VarType.Byte, 1);
        return (byte)result;
    }
    /// <summary>
    /// 写入byte类型
    /// </summary>
    /// <param name="dbBlock">所选择的数据库块</param>
    /// <param name="startByteAdr">数据偏移量</param>
    /// <param name="Value">写入值</param>
    /// <param name="dataType">数据块类型</param>
    /// <returns></returns>
    public void WriteByte(Plc Plc, int dbBlock, int startByteAdr, byte Value, DataType dataType = DataType.DataBlock)
    {
        Plc.Write(dataType, dbBlock, startByteAdr, Value);
    }

    /// <summary>
    /// 读取word类型
    /// </summary>
    /// <param name="dbBlock">所选择的数据库块</param>
    /// <param name="startByteAdr">数据偏移量</param>
    /// <param name="dataType">数据块类型</param>
    /// <returns></returns>
    public ushort ReadWord(Plc Plc, int dbBlock, int startByteAdr, DataType dataType = DataType.DataBlock)
    {
        var result = Plc.Read(dataType, dbBlock, startByteAdr, VarType.Word, 1);
        return (ushort)result;
    }
    /// <summary>
    /// 写入word类型
    /// </summary>
    /// <param name="dbBlock">所选择的数据库块</param>
    /// <param name="startByteAdr">数据偏移量</param>
    /// <param name="Value">写入值</param>
    /// <param name="dataType">数据块类型</param>
    /// <returns></returns>
    public void WriteWord(Plc Plc, int dbBlock, int startByteAdr, ushort Value, DataType dataType = DataType.DataBlock)
    {
        Plc.Write(dataType, dbBlock, startByteAdr, Value);
    }

    /// <summary>
    /// 读取Dword类型
    /// </summary>
    /// <param name="dbBlock">所选择的数据库块</param>
    /// <param name="startByteAdr">数据偏移量</param>
    /// <param name="dataType">数据块类型</param>
    /// <returns></returns>
    public uint ReadDWord(Plc Plc, int dbBlock, int startByteAdr, DataType dataType = DataType.DataBlock)
    {
        var result = Plc.Read(dataType, dbBlock, startByteAdr, VarType.Int, 1);
        return (uint)result;
    }
    /// <summary>
    /// 写入Dword类型
    /// </summary>
    /// <param name="dbBlock">所选择的数据库块</param>
    /// <param name="startByteAdr">数据偏移量</param>
    /// <param name="Value">写入值</param>
    /// <param name="dataType">数据块类型</param>
    /// <returns></returns>
    public void WriteDWord(Plc Plc, int dbBlock, int startByteAdr, uint Value, DataType dataType = DataType.DataBlock)
    {
        Plc.Write(dataType, dbBlock, startByteAdr, Value);
    }

    /// <summary>
    /// 读取real类型
    /// </summary>
    /// <param name="dbBlock">所选择的数据库块</param>
    /// <param name="startByteAdr">数据偏移量</param>
    /// <param name="dataType">数据块类型</param>
    /// <returns></returns>
    public float ReadReal(Plc Plc, int dbBlock, int startByteAdr, DataType dataType = DataType.DataBlock)
    {
        var result = Plc.Read(dataType, dbBlock, startByteAdr, VarType.Real, 1);
        return (float)result;
    }
    /// <summary>
    /// 写入real类型
    /// </summary>
    /// <param name="dbBlock">所选择的数据库块</param>
    /// <param name="startByteAdr">数据偏移量</param>
    /// <param name="Value">写入值</param>
    /// <param name="dataType">数据块类型</param>
    /// <returns></returns>
    public void WriteReal(Plc Plc, int dbBlock, int startByteAdr, float Value, DataType dataType = DataType.DataBlock)
    {
        Plc.Write(dataType, dbBlock, startByteAdr, Value);
    }

    /// <summary>
    /// 读取Lreal类型
    /// </summary>
    /// <param name="dbBlock">所选择的数据库块</param>
    /// <param name="startByteAdr">数据偏移量</param>
    /// <param name="dataType">数据块类型</param>
    /// <returns></returns>
    public double ReadLReal(Plc Plc, int dbBlock, int startByteAdr, DataType dataType = DataType.DataBlock)
    {
        var result = Plc.Read(dataType, dbBlock, startByteAdr, VarType.Int, 1);
        return (double)result;
    }
    /// <summary>
    /// 写入Lreal类型
    /// </summary>
    /// <param name="dbBlock">所选择的数据库块</param>
    /// <param name="startByteAdr">数据偏移量</param>
    /// <param name="Value">写入值</param>
    /// <param name="dataType">数据块类型</param>
    /// <returns></returns>
    public void WriteLReal(Plc Plc, int dbBlock, int startByteAdr, double Value, DataType dataType = DataType.DataBlock)
    {
        Plc.Write(dataType, dbBlock, startByteAdr, Value);
    }

    /// <summary>
    /// 读取dateandtime类型
    /// </summary>
    /// <param name="dbBlock">所选择的数据库块</param>
    /// <param name="startByteAdr">数据偏移量</param>
    /// <param name="dataType">数据块类型</param>
    /// <returns></returns>
    public DateTime ReadDateAndTime(Plc Plc, int dbBlock, int startByteAdr, DataType dataType = DataType.DataBlock)
    {
        var result = Plc.Read(dataType, dbBlock, startByteAdr, VarType.DateTime, 1);
        return (DateTime)result;
    }
    /// <summary>
    /// 写入dateandtime类型
    /// </summary>
    /// <param name="dbBlock">所选择的数据库块</param>
    /// <param name="startByteAdr">数据偏移量</param>
    /// <param name="Value">写入值</param>
    /// <param name="dataType">数据块类型</param>
    /// <returns></returns>
    public void WriteDateAndTime(Plc Plc, int dbBlock, int startByteAdr, DateTime Value, DataType dataType = DataType.DataBlock)
    {
        Plc.Write(dataType, dbBlock, startByteAdr, Value);
    }
    /// <summary>
    /// 读取任意值类型
    /// </summary>
    /// <param name="dbBlock">所选择的数据库块</param>
    /// <param name="startByteAdr">数据偏移量</param>
    /// <param name="type">数组类型</param>
    /// <param name="count">读取值</param>
    /// <param name="dataType">数据块类型</param>
    /// <returns></returns>
    public dynamic Read(Plc Plc, int dbBlock, int startByteAdr, VarType type, int count, DataType dataType = DataType.DataBlock)
    {
        switch (type)
        {
            case VarType.String:
                byte[] stringDemo = Plc.ReadBytes(DataType.DataBlock, dbBlock, startByteAdr + 2, (byte)Plc.Read(DataType.DataBlock, dbBlock, startByteAdr + 1, VarType.Byte, 1));//+2表示读取偏移值(跳过)的字符
                return Encoding.Default.GetString(stringDemo);
            case VarType.Bit:
                return (bool)Plc.Read(dataType, dbBlock, startByteAdr, VarType.Bit, count);
            case VarType.Int:
                return (short)Plc.Read(dataType, dbBlock, startByteAdr, VarType.Int, count);
            case VarType.DInt:
                return (int)Plc.Read(dataType, dbBlock, startByteAdr, VarType.DInt, count);
            case VarType.S7WString:
                return Plc.Read(dataType, dbBlock, startByteAdr, VarType.S7WString, count = 254).ToString();//254为wstring默认存储字符数
            case VarType.Byte:
                return (byte)Plc.Read(dataType, dbBlock, startByteAdr, VarType.Byte, count);
            case VarType.Word:
                return (ushort)Plc.Read(dataType, dbBlock, startByteAdr, VarType.Word, count);
            case VarType.DWord:
                return (uint)Plc.Read(dataType, dbBlock, startByteAdr, VarType.DWord, count);
            case VarType.Real:
                return (float)Plc.Read(dataType, dbBlock, startByteAdr, VarType.Real, count);
            case VarType.LReal:
                return (double)Plc.Read(dataType, dbBlock, startByteAdr, VarType.LReal, count);
            case VarType.DateTimeLong:
                return (DateTime)Plc.Read(dataType, dbBlock, startByteAdr, VarType.DateTimeLong, count);
            default:
                throw new Exception("数据类型不存在");
        }
    }

    /// <summary>
    /// 写入任意值类型
    /// </summary>
    /// <param name="dbBlock">所选择的数据库块</param>
    /// <param name="startByteAdr">数据偏移量</param>
    /// <param name="type">原数据类型</param>
    /// <param name="Value">写入值</param>
    /// <param name="dataType">数据块类型</param>
    /// <returns></returns>
    public void Write(Plc Plc, int dbBlock, int startByteAdr, VarType type, object Value, DataType dataType = DataType.DataBlock)
    {
        switch (type)
        {
            case VarType.String:
                Plc.Write(DataType.DataBlock, dbBlock, startByteAdr + 1, (byte)Value.ToString().Length);//长度需要改成byte类型
                Plc.Write(DataType.DataBlock, dbBlock, startByteAdr + 2, Value);
                break;
            case VarType.Bit:
                Plc.Write(dataType, dbBlock, startByteAdr, bool.Parse(Value.ToString()));
                break;
            case VarType.Int:
                Plc.Write(dataType, dbBlock, startByteAdr, short.Parse(Value.ToString()));
                break;
            case VarType.DInt:
                Plc.Write(dataType, dbBlock, startByteAdr, int.Parse(Value.ToString()));
                break;
            case VarType.Byte:
                Plc.Write(dataType, dbBlock, startByteAdr, byte.Parse(Value.ToString()));
                break;
            case VarType.Word:
                Plc.Write(dataType, dbBlock, startByteAdr, ushort.Parse(Value.ToString()));
                break;
            case VarType.DWord:
                Plc.Write(dataType, dbBlock, startByteAdr, uint.Parse(Value.ToString()));
                break;
            case VarType.Real:
                Plc.Write(dataType, dbBlock, startByteAdr, float.Parse(Value.ToString()));
                break;
            case VarType.LReal:
                Plc.Write(dataType, dbBlock, startByteAdr, double.Parse(Value.ToString()));
                break;
            case VarType.DateTimeLong:
                Plc.Write(dataType, dbBlock, startByteAdr, DateTime.Parse(Value.ToString()));
                break;
            default:
                throw new Exception("数据类型不存在");
        }
    }

    /// <summary>
    /// 读取array[]类型
    /// </summary>
    /// <param name="dbBlock">所选择的数据库块</param>
    /// <param name="startByteAdr">数据偏移量</param>
    /// <param name="type">数组类型</param>
    /// <param name="count">读取长度</param>
    /// <param name="dataType">数据块类型</param>
    /// <returns></returns>
    public dynamic ReadArray(Plc Plc, int dbBlock, int startByteAdr, VarType type, int count, DataType dataType = DataType.DataBlock)
    {
        switch (type)
        {
            case VarType.Bit:
                return (bool[])Plc.Read(dataType, dbBlock, startByteAdr, VarType.Bit, count);
            case VarType.Int:
                return (short[])Plc.Read(dataType, dbBlock, startByteAdr, VarType.Int, count);
            case VarType.DInt:
                return (int[])Plc.Read(dataType, dbBlock, startByteAdr, VarType.DInt, count);
            case VarType.Byte:
                return (byte[])Plc.Read(dataType, dbBlock, startByteAdr, VarType.Byte, count);
            case VarType.Word:
                return (ushort[])Plc.Read(dataType, dbBlock, startByteAdr, VarType.Word, count);
            case VarType.DWord:
                return (uint[])Plc.Read(dataType, dbBlock, startByteAdr, VarType.DWord, count);
            case VarType.Real:
                return (float[])Plc.Read(dataType, dbBlock, startByteAdr, VarType.Real, count);
            case VarType.LReal:
                return (double[])Plc.Read(dataType, dbBlock, startByteAdr, VarType.LReal, count);
            case VarType.DateTimeLong:
                return (DateTime[])Plc.Read(dataType, dbBlock, startByteAdr, VarType.DateTimeLong, count);
            default:
                throw new Exception("数据类型不存在");
        }
    }

    /// <summary>
    /// 写入array[]类型
    /// </summary>
    /// <param name="dbBlock">所选择的数据库块</param>
    /// <param name="startByteAdr">数据偏移量</param>
    /// <param name="Value">写入值</param>
    /// <param name="dataType">数据块类型</param>
    /// <returns></returns>
    public void WriteArray(Plc Plc, int dbBlock, int startByteAdr, object Value, DataType dataType = DataType.DataBlock)
    {
        Plc.Write(dataType, dbBlock, startByteAdr, Value);
    }

    /// <summary>
    /// 读取string类型
    /// </summary>
    /// <param name="dbBlock">所选择的数据库块</param>
    /// <param name="startByteAdr">数据偏移量</param>
    /// <param name="dataType">数据块类型</param>
    /// <returns></returns>
    public string ReadString(Plc Plc, int dbBlock, int startByteAdr, DataType dataType = DataType.DataBlock)
    {
        var count = Plc.Read(DataType.DataBlock, dbBlock, startByteAdr + 1, VarType.Byte, 1);//+1表示读取偏移值的长度
        byte[] stringDemo = Plc.ReadBytes(DataType.DataBlock, dbBlock, startByteAdr + 2, (byte)count);//+2表示读取偏移值(跳过)的字符
        return Encoding.Default.GetString(stringDemo);
    }
    /// <summary>
    /// 写入string类型
    /// </summary>
    /// <param name="dbBlock">所选择的数据库块</param>
    /// <param name="startByteAdr">数据偏移量</param>
    /// <param name="Value">写入值</param>
    /// <param name="dataType">数据块类型</param>
    /// <returns></returns>
    public void WriteString(Plc Plc, int dbBlock, int startByteAdr, string Value, DataType dataType = DataType.DataBlock)
    {
        Plc.Write(DataType.DataBlock, dbBlock, startByteAdr + 1, (byte)Value.Length);//长度需要改成byte类型
        Plc.Write(DataType.DataBlock, dbBlock, startByteAdr + 2, Value);
    }
    /// <summary>
    /// 读取wstring类型
    /// </summary>
    /// <param name="dbBlock">所选择的数据库块</param>
    /// <param name="startByteAdr">数据偏移量</param>
    /// <param name="dataType">数据块类型</param>
    /// <returns></returns>
    public string ReadWString(Plc Plc, int dbBlock, int startByteAdr, DataType dataType = DataType.DataBlock)
    {
        var result = Plc.Read(DataType.DataBlock, dbBlock, startByteAdr, VarType.S7WString, 254);
        return result.ToString();
    }

    /// <summary>  以下两种方式不推荐,会重复开启tcp连接占用资源
    /// 标签方式读取
    /// </summary>
    /// <param name="dbBlock">所选择的数据库块</param>
    /// <returns></returns>
    public dynamic ReadTags(Plc Plc, string dbBlock)
    {
        //例:Plc.Read("DB2.DBX0.0"); 其中db2表示数据库名称,0.0表示偏移量  dbx表示数据块
        return Plc.Read(dbBlock);
    }

    /// <summary>
    /// 标签方式写入
    /// </summary>
    /// <param name="dbBlock">所选择的数据库块</param>
    /// <param name="vaule">写入值</param>
    /// <returns></returns>
    public void WriteTags(Plc Plc, string dbBlock, object vaule)
    {
        //例:Plc.Read("DB2.DBX0.0",true); 其中db2表示数据库名称,0.0表示偏移量,true表示将其转换为true
        Plc.Write(dbBlock, vaule);
    }
    /// <summary>
    /// 获取西门子PLC字符串数组--WString
    /// </summary>
    /// <param name="str"></param>
    /// <returns></returns>
    public byte[] GetPLCWStringByteArray(Plc Plc, string str)
    {
        byte[] value = Encoding.BigEndianUnicode.GetBytes(str);
        byte[] head = BitConverter.GetBytes((short)254);
        byte[] length = BitConverter.GetBytes((short)str.Length);
        Array.Reverse(head);
        Array.Reverse(length);
        head = head.Concat(length).ToArray();
        value = head.Concat(value).ToArray();
        return value;
    }
}

 3、使用方法:

 public class UseItDemo
 {
     /// <summary>
     /// 西门子PLC的连接信息集合
     /// </summary>
     public static Dictionary<string, SiemensModel> SiemensPLCs = new Dictionary<string, SiemensModel>();
     /// <summary>
     /// 1、PLC连接初始化,把所有连接丢进连接池
     /// </summary>
     public void PLC_Init(List<DBInfo> infos)
     {
         try
         {
             for (int i = 0; i < infos.Count; i++)
             {
                 SiemensModel siemens = new SiemensModel();
                 if (infos[i].PLCType == "S1200")
                     siemens.SiemensClient = OpenPlc(CpuType.S71200, infos[i].PLCIP, (short)infos[i].PLCRack, (short)infos[i].PLCSlot);
                 else if (infos[i].PLCType == "S1500")
                     siemens.SiemensClient = OpenPlc(CpuType.S71500, infos[i].PLCIP, (short)infos[i].PLCRack, (short)infos[i].PLCSlot);
                 else if (infos[i].PLCType == "S200Smart")
                     siemens.SiemensClient = OpenPlc(CpuType.S7200Smart, infos[i].PLCIP, (short)infos[i].PLCRack, (short)infos[i].PLCSlot);
                 else if (infos[i].PLCType == "S300")
                     siemens.SiemensClient = OpenPlc(CpuType.S7300, infos[i].PLCIP, (short)infos[i].PLCRack, (short)infos[i].PLCSlot);
                 else if (infos[i].PLCType == "S400")
                     siemens.SiemensClient = OpenPlc(CpuType.S7400, infos[i].PLCIP, (short)infos[i].PLCRack, (short)infos[i].PLCSlot);
                 if (siemens.SiemensClient != null)
                 {
                     SiemensPLCs.Add(infos[i].PLCConnection, siemens);
                 }
                 else
                 {
                     // Log
                 }

             }

             // Log
         }
         catch (Exception ex)
         {

             // Log
         }
     }

     /// <summary>
     /// 打开连接
     /// </summary>
     /// <param name="cpuType"></param>
     /// <param name="ip"></param>
     /// <param name="rack"></param>
     /// <param name="slot"></param>
     /// <returns></returns>
     public Plc OpenPlc(CpuType cpuType = CpuType.S71200, string ip = "127.0.0.1", short rack = 0, short slot = 1)
     {
         Plc Plc = new Plc(cpuType, ip, rack, slot);
         Plc.Open();
         if (Plc.IsConnected) return Plc;
         else return null;
     }

     /// <summary>
     /// 2、读取数据、写入数据类似
     /// </summary>
     /// <param name="datatype">PLC的数据类型</param>
     /// <param name="Address">DB地址,例如:DB2030.DBX94.0</param>
     public void ReadPlcData(string datatype, string Address)
     {
         Task.Run(() =>
         {
             try
             {
                 foreach (var item in SiemensPLCs.Values)
                 {
                     if (!item.SiemensClient.IsConnected)
                     {
                         item.SiemensClient.Open();
                     }
                     //采集变量信息
                     int db = 1;//数据块
                     int start = 0;//字节偏移量
                     byte by = 0;//位偏移量"DB1.DBX2.7"中的7代表位偏移量为7
                     //将DB地址拆分-DB2030.DBX94.0(X是数据类型,具体的百度) 拆开后:2023-DB地址 94-字节偏移量 0--字节的偏移量
                     var arry = Address.Split(new char[] { '.', '%', 'D', 'B', 'X', 'W' }, StringSplitOptions.RemoveEmptyEntries);
                     db = int.Parse(arry[0]);
                     start = int.Parse(arry[1]);
                     if (arry.Length == 3)//代表小数点后还有
                     {
                         by = byte.Parse(arry[2]);
                     }
                     //根据数据类型的不同选择不同的读取方法
                     switch (datatype.ToUpper())//存入redis
                     {
                         case "WORD":
                             var result = item.SiemensClient.Read(DataType.DataBlock, db, start, VarType.Word, 1);
                             if (result != null)
                             {
                                 //取到数据做相应操作,此处我是存到缓存供客户端使用
                                 //redis.StringSet("Key", result.ToString());
                             }
                             break;
                         case "BYTE":
                             var result1 = item.SiemensClient.Read(DataType.DataBlock, db, start, VarType.Byte, 1);
                             if (result1 != null)
                             {
                                 //redis.StringSet("Key", result1.ToString());
                             }
                             break;
                         case "BOOL":
                             var result2 = item.SiemensClient.Read(DataType.DataBlock, db, start, VarType.Bit, 1, by);
                             if (result2 != null)
                             {
                                 // redis.StringSet("Key", result2.ToString());
                             }
                             break;
                         default:
                             break;
                     }
                 }
             }
             catch (Exception ex)
             {
                 //Log
             }
         });
     }
 }
 /// <summary>
 /// DB块的相关信息。
 /// </summary>
 public class DBInfo
 {
     /// <summary>
     /// PLC连接名
     /// </summary>
     public string PLCConnection { get; set; }
     /// <summary>
     /// PLCIp
     /// </summary>
     public string PLCIP { get; set; }
     /// <summary>
     /// 机架号
     /// </summary>
     public int PLCRack { get; set; }
     /// <summary>
     /// 插槽号
     /// </summary>
     public int PLCSlot { get; set; }
     /// <summary>
     /// PLC类型
     /// </summary>
     public string PLCType { get; set; }
 }

 //plc中类型与c#类型 bool => Bit
 //Byte => byte
 //word => ushort
 //DWord => uint
 //Int => short
 //DInt => int
 //Real => float
 //LReal => double
 //String => string
 //DateTimeLong=>datetime
 //s7wstring=>string
 /// <summary>
 /// 西门子连接信息
 /// </summary>
 public class SiemensModel
 {
     /// <summary>
     /// 西门子客户端
     /// </summary>
     public Plc SiemensClient { get; set; }
     /// <summary>
     /// 是否连接
     /// </summary>
     public bool IsConnected { get; set; }
     /// <summary>
     /// 是否运行
     /// </summary>
     public bool IsWorking { get; set; }

     /// <summary>
     /// 采集任务
     /// </summary>
     public Func<List<Tuple<PLC_DB, byte[]>>> ReadValueTask { get; set; }
     /// <summary>
     /// 解析任务
     /// </summary>
     public Action<List<Tuple<PLC_DB, byte[]>>> AnalysisTask { get; set; }

 }

到这就结束了。记录一下。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2214561.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【AI知识点】三种不同架构的大语言模型(LLMs)的区别

【AI论文解读】【AI知识点】【AI小项目】【AI战略思考】【AI大项目】【AI应用】 在自然语言处理&#xff08;NLP&#xff09;中&#xff0c;预训练语言模型&#xff08;LLMs, Large Language Models&#xff09;通常基于不同的架构&#xff0c;如仅编码器的模型&#xff08;Enc…

Java开发中知识点整理

正则表达式 测试网址 Git 分支和主分支有冲突 先checkout origin/分支把origin/master pull进本地分支 修改冲突MergeCommit and Push

Apache SeaTunnel 介绍

SeaTunnel是一个非常易用、超高性能的分布式数据集成平台&#xff0c;支持实时海量数据同步。 每天可稳定高效同步数百亿数据&#xff0c;已被近百家企业应用于生产。 为什么需要 SeaTunnel​ SeaTunnel专注于数据集成和数据同步&#xff0c;主要旨在解决数据集成领域的常见问…

【OSCP Proving Grounds 靶场系列】Slort

作者&#xff1a;Eason_LYC 悲观者预言失败&#xff0c;十言九中。 乐观者创造奇迹&#xff0c;一次即可。 一个人的价值&#xff0c;在于他所拥有的。可以不学无术&#xff0c;但不能一无所有&#xff01; 技术领域&#xff1a;WEB安全、网络攻防 关注WEB安全、网络攻防。我的…

121页满分PPT | XX集团SAP ERP业务蓝图规划方案

这份PPT是德勤的集团SAP ERP业务蓝图规划方案的详细介绍&#xff0c;涵盖了项目背景、总体目标、ERP总体蓝图规划、总体规划路线设计以及风险与保障措施。方案强调了在煤炭市场疲软的宏观背景下&#xff0c;集团如何通过ERP系统实施来加强管控、提升业财管理一体化&#xff0c;…

VSCode esp-idf环境搭建 报错 ERROR_INVALID_PIP

例如我的报错提示 D:\APP\Espressif\idf531\Espressif\tools\idf-python\3.11.2\python.exe -m pip" is not valid. (ERROR_INVALID_PIP)找到目录位置D:\APP\Espressif\idf531\Espressif\tools\idf-python\3.11.2 使用下面的指令更新pip python -m ensurepippython -m …

二叉搜索树(超详细+通俗易懂)

二叉搜索树定义: 二叉搜索树又被称为二叉排序树/二叉搜索树&#xff0c;为什么会被起这样的名字呢&#xff1f;我们先来看一张二叉搜索树的图片 这张图片里面的树就是二叉搜素树&#xff0c;那么二叉树有什么性质呢&#xff1f;我们从图中可以发现&#xff0c;每一个子树都是…

Flink05 Windows 操作轻松应对复杂的场景

Flink Windows 操作 上篇文章介绍了Flink 几种类型 Windows 本文介绍窗口操作相关API&#xff0c;以及各自使用场景 。 本期Flink Windows 相关操作apply/union/join/collect/CoMap/CoFlatMap Windows apply 通过实现WindowFunction或AllWindowFunction接口来完成的&#x…

工具篇:(三)MacOS 两种方式下载 Node.js 并进行测试教程

MacOS 两种方式下载 Node.js 并进行测试教程 1.Node.js 官网 下载 步骤 1: 访问 Node.js 官网 打开浏览器&#xff0c;访问 Node.js 的官方网站&#xff1a;https://nodejs.org。 在首页&#xff0c;你会看到两个版本可供下载&#xff1a; LTS&#xff08;长期支持版本&…

从0到1封装一个image/pdf预览组件

目录结构 content.vue <template><div class"no-content-block"><i class"iconfont icondocument large-file" /><div class"text-wrapper">{{ t(__ui__.siPreview.previewSupported) }}</div><div class&quo…

【CSS in Depth 2 精译_049】7.2 CSS 响应式设计中的媒体查询原则(下):响应式列的添加

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 【第七章 响应式设计】&#xff08;概述&#xff09; 7.1 移动端优先设计原则&#xff08;上篇&#xff09; 7.1.1 创建移动端菜单&#xff08;下篇&#xff09;7.1.2 给视口添加 meta 标签&#xf…

RabbitMQ 核心功能详解

引言 在现代分布式系统中&#xff0c;消息队列已经成为一种不可或缺的组件。它不仅能够实现应用之间的解耦&#xff0c;还能提高系统的灵活性和可扩展性。RabbitMQ 是一款基于 AMQP&#xff08;Advanced Message Queuing Protocol&#xff09;协议的消息中间件&#xff0c;以其…

香港举办AIHCIR 2024国际学术会议,领先人工智能、人机交互和机器人技术

第三届人工智能、人机交互和机器人国际学术会议 &#xff08;AIHCIR 2024&#xff09;将于2024年11月在中国香港举行&#xff0c;聚焦AI、人机交互与机器人领域&#xff0c;邀请知名学者演讲&#xff0c;促进学术交流。论文经评审后提交EI检索&#xff0c;投稿需全英文&#xf…

图解Redis 04 | Set数据类型的原理及应用场景

介绍 Redis 的 Set 类型是一个不允许重复元素的集合&#xff0c;元素存储的顺序不按照插入的顺序&#xff0c;因此属于无序集合。一个 Set 最多可以存储 2^32 - 1 个元素&#xff0c;这与数学中的集合概念类似。Set 类型不仅支持增、删、改、查等操作&#xff0c;还支持多个Se…

微软的 Drasi:一种轻量级的事件驱动编程方法

微软的开源数据变化处理平台有望提供一种全新的方式来构建和管理可产生持续事件流的云应用程序。 Microsoft Azure 孵化团队是微软超大规模云中比较有趣的组成部分之一。它介于传统软件开发团队和研究组织之间&#xff0c;致力于构建大规模分布式系统问题的解决方案。 这些解决…

使用拖拽生成活动海报(vue项目)

<template><div class"poster-editor"><div class"toolbar" v-if"edit 1"><div style"text-align: center;font-size: 14px;font-weight: 700;margin-bottom: 10px;">工具栏</div><div class"…

WPF组件的自定义模板和触发器全面解析

Windows Presentation Foundation&#xff08;WPF&#xff09;是微软提供的一个用于构建桌面客户端应用程序的UI框架。其依赖于XAML&#xff08;Extensible Application Markup Language&#xff09;进行用户界面设计&#xff0c;提供了一套强大的控件和组件模型。在WPF开发中&…

C++ 的存储类型与新的 thread_local

1 C 的存储类型 1.1 存储周期&#xff08;Storage duration&#xff09; 存储周期表示一个变量的存储空间持续的时间&#xff0c;它应该与对象的语义生命周期一致&#xff08;或至少不小于对象的语义生命周期&#xff09;。C 98从 C 继承了三种存储周期&#xff0c;分别是静态…

【黑马点评】项目知识点及面经整理

【黑马点评】项目知识点及面经整理 1 短信登录&#xff08;Session&#xff0c;Redis&#xff0c;JWT验证&#xff09;1.1 JWT和Session的区别1.2 Session1.3 Redis1.3.1 基于Redis实现登录验证1.3.2 登录拦截 1.4 JWT1.4.1 JWT的有效验证1.4.2 JWT定义 2 热点数据缓存2.1 缓存…

区块链-智能合约Solidity编程

文章目录 一、ubuntu安装二、FISCO BCOS安装五、 WeBASE安装5.1 WeBASE简介5.2 节点前置服务搭建5.3 调用HelloWorld合约 七、Solidity极简入门7.1. 值类型7.2. 变量数据存储和作用域7.3. 函数7.4 控制流7.5 数组&映射7.6 结构体7.7 修饰符7.8 事件7.9 面向对象7.10 抽象合…