c# 使用OPC服务 读取数据

c#连接opc协议,基础配置搞定后,即可进行编码开发
推荐开发前可以使用可视化工具进行测试下,确定下OPC Client端是否和服务器网络是否通常
可以使用 OPCExplorer.exe工具来进行测试,免费的工具
而且网上资料也挺多的

调用OPC,解决方案需要添加如下的dll,我的c# 开发环境是.net FrameWork4.5.2

这两个dll的获取方式,推荐大家安装免费的MatrikonOPC Server for Simulation
安装完成后,在这个程序的目录包中即可找到这两个dll,而且这个软件还会为你注册这几个dll和对应的服务,大大省事!!!

下来就是贴代码了,

Helper帮助类

using System;
using System.Collections.Generic;
using OPCAutomation;//需要手动添加
using System.Security.Cryptography;
using System.Linq;
using Newtonsoft.Json;

namespace OPCAPI
{
    class OPC_client
    {
        public OPCServer Server;//服务器对象
        public OPCGroups Groups;//组列表
        public OPCGroup Group;//组对象
        public OPCItems Items;//节点列表
                              //public OPCItem Item;//节点对象
        public bool ConnectedState { get; private set; }
        public delegate string ServerShutDown(string Reason);
        /// <summary>
        /// 服务器断开连接事件
        /// </summary>
        public event ServerShutDown OnServerShutDown;
        /// <summary>
        /// 连接
        /// </summary>
        /// <param name="ServerName"></param>
        /// <param name="ServerIP"></param>
        /// <returns></returns>
        public bool Connect(string ServerName, string ServerIP, out string Message)
        {
            try
            {
                if (Server == null) Server = new OPCServer();
                Server.Connect(ServerName, ServerIP);
                if (Server.ServerState == (int)OPCServerState.OPCRunning)
                {
                    Server.ServerShutDown += Server_ServerShutDown;
                    Message = "连接成功";
                    ConnectedState = true;
                    IniServer();
                    return true;
                }
                else
                {
                    Message = "连接失败。状态码:" + Server.ServerState.ToString();
                    ConnectedState = false;
                    return false;
                }
            }
            catch (Exception ex)
            {
                Message = ex.Message;
                return false;
            }
        }
        /// <summary>
        /// 服务器异常断开连接
        /// </summary>
        /// <param name="Reason"></param>
        private void Server_ServerShutDown(string Reason)
        {
            ConnectedState = false;
            OnServerShutDown?.Invoke(Reason);
        }
        /// <summary>
        /// 断开连接
        /// </summary>
        public void DisConnect()
        {
            Server?.Disconnect();
        }
        /// <summary>
        /// 添加一个测试组,之后读取都在这个测试组中添加或者删除item
        /// </summary>
        private void IniServer()
        {
            Groups = Server.OPCGroups;
            Group = Server.OPCGroups.Add("AncnRobot");
            Items = Group.OPCItems;
        }
        /// <summary>
        /// 获取OPCDA服务器中所有的节点<br/>
        /// 有一些节点服务器自带有Write的,不能读取。
        /// </summary>
        /// <returns></returns>
        public List<string> GetBrowser()
        {
            try
            {
                List<string> result = new List<string>();
                OPCBrowser browser = Server.CreateBrowser();
                browser.ShowBranches();
                browser.ShowLeafs(true);
                foreach (var item in browser)
                {
                    result.Add(item.ToString());
                }
                return result;
            }
            catch (Exception)
            {
                return null;
            }
        }
        /// <summary>
        /// 读取一条数据
        /// </summary>
        /// <param name="tagAddress"></param>
        /// <returns></returns>
        public OPCResponse ReadOne(string tagAddress)
        {
            try
            {
                var model = Items.AddItem(tagAddress, 1);
                model.Read(1,
                                out object ItemValues,
                                out object Qualities,
                                out object TimeStamps);
                var read_ = new OPCResponse()
                {
                    Tag = tagAddress,
                    Value = ItemValues.ToString(),
                    Quanlity = Qualities.ToString(),
                    Time = TimeStamps.ToString()
                };
                return read_;
            }
            catch (Exception ex)
            {
                Logger.Info($"读取指定数据异常,读取的数据内容是:{tagAddress}错误原因是:{JsonConvert.SerializeObject(ex)}");
            }
            return null;
        }

        /// <summary>
        /// 读取节点数据
        /// </summary>
        /// <param name="tagAddress">需要读取的节点</param>
        /// <returns></returns>
        public List<OPCResponse> Read(List<string> tagAddress)
        {
            List<OPCResponse> results = new List<OPCResponse>();
            try
            {
                OPCItem[] items = new OPCItem[tagAddress.Count];
                int[] temp = new int[items.Length + 1];
                temp[0] = 0;//这个第一个数据一定不能为空,索引是从1开始的
                for (int i = 0; i < items.Length; i++)
                {
                    items[i] = Items.AddItem(tagAddress[i], i);
                    OPCResponse read_;
                    try
                    {
                        items[i].Read(1,
                            out object ItemValues,
                            out object Qualities,
                            out object TimeStamps);
                        read_ = new OPCResponse()
                        {
                            Tag = tagAddress[i],
                            Value = ItemValues.ToString(),
                            Quanlity = Qualities.ToString(),
                            Time = TimeStamps.ToString()
                        };
                    }
                    catch (Exception)
                    {
                        read_ = new OPCResponse()
                        {
                            Tag = tagAddress[i],
                            Value = "--",
                            Quanlity = "--",
                            Time = "--"
                        };
                        results.Add(read_);
                        continue;
                    }
                    results.Add(read_);
                    temp[i + 1] = items[i].ServerHandle;
                }
                try
                {
                    Array serverHandles = (Array)temp;
                    Array errors;
                    Items.Remove(1, serverHandles, out errors);
                }
                catch (Exception) { }
                return results;
            }
            catch (Exception ee)
            {
                return null;
            }
        }
        /// <summary>
        /// 数据变化之后推送事件
        /// </summary>
        /// <param name="TransactionID"></param>
        /// <param name="NumItems"></param>
        /// <param name="ClientHandles"></param>
        /// <param name="ItemValues"></param>
        /// <param name="Qualities"></param>
        /// <param name="TimeStamps"></param>
        private void Group_DataChange(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps)
        {
            Console.ForegroundColor = ConsoleColor.Green;
            for (int i = 1; i <= NumItems; i++)
            {
                int tmpClientHandle = Convert.ToInt32(ClientHandles.GetValue(i));
                string tmpValue = ItemValues.GetValue(i).ToString();
                string tmpTime = ((DateTime)(TimeStamps.GetValue(i))).ToString();
                Console.WriteLine("Time:" + tmpTime);
                Console.WriteLine("ClientHandle : " + tmpClientHandle.ToString());
                Console.WriteLine("tag value " + tmpValue);
            }
        }
    }
}

返回参数数据(我这个是业务上要求写的,大家参考就行)

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

namespace OPCAPI.Models
{
    public class OPCRequest
    {
        public string TagId { get; set; }
    }
}

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

namespace OPCAPI
{
    public class OPCResponse
    {
        /// <summary>
        /// OPCIterm变量名称
        /// </summary>
        public string Tag { get; set; }
        /// <summary>
        /// OPCIterm数值
        /// </summary>
        public string Value { get; set; }
        /// <summary>
        /// OPCIterm质量
        /// </summary>
        public string Quanlity { get; set; }
        /// <summary>
        /// OPCIterm时间戳
        /// </summary>
        public string Time { get; set; }
    }
}

调用去读取一条数据

static bool OPCInit()
        {
            try
            {
                if (_client == null || !_client.ConnectedState)
                {
                    if (_client != null)
                    {
                        Logger.Info($"当前连接状态是:{_client.ConnectedState},准备重新初始化!");
                    }
                    _client = new OPC_client();
                    var config = AppConfig.GetInstance();
                    if (config != null)
                    {
                    	//这里需要修改 去填 组id,opc服务器ip
                        bool con = _client.Connect(config.ProgId, config.OPCIp, out string msg);
                        Logger.Info($"连接结果是:{con},连接返回内容是:{msg}");
                        return con;
                    }
                }
                else
                {

                    Logger.Info($"当前连接状态是:{_client.ConnectedState},初始化成功!");
                    return _client.ConnectedState;
                }

            }
            catch (Exception ex)
            {
                Logger.Info("初始化OPC服务异常:" + JsonConvert.SerializeObject(ex));
            }
            return false;
        }
 public static OPCResponse Read(OPCRequest request)
        {
            OPCResponse response = null;
            try
            {
                if (OPCInit())
                {//opc初始化
                    var config = AppConfig.GetInstance();
                    //这里需要修改 key改为dcs系统中的唯一主键,我这里是我自己业务逻辑的拼接
                    string key = config.TagPrefix + request.TagId + config.TagValueAttribute;
                    var result = _client.ReadOne(key);
                    if (result != null)
                    {
                        return result;
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Info("opc服务读取异常:" + JsonConvert.SerializeObject(ex));
                response = null;
            }
            return response;
        }

  • 8
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: C#OPC(OLE for Process Control)是一种用于处理控制系统的标准通信协议。使用C#编程语言可以实现与OPC服务器的交互,并同步读取数据。 要同步读取数据,首先需要确保已经安装了OPC服务器,并且已知其名称和位置。然后,在C#程序中引用OPC组件,并创建一个OPCServer对象来连接到OPC服务器。 接下来,通过OPCServer对象的Connect方法来连接到OPC服务器。连接成功后,可以使用OPC服务器对象的Browse方法来获取OPC服务器上所有可用的项(变量)列表。 通过查找需要读取的变量的名称,可以获取到相应的OPCItem对象。然后,使用OPCItem对象的Read方法进行同步读取操作。 读取数据后,可以使用OPCItem对象的Value属性来获取变量的值。 最后,使用OPCServer对象的Disconnect方法断开与OPC服务器的连接。 以下是一个简单的C#代码示例: ```csharp using OPCAutomation; class Program { static void Main(string[] args) { OPCServer opcServer = new OPCServer(); opcServer.Connect("OPCServerName"); OPCBrowser opcBrowser = opcServer.CreateBrowser(); OPCItems opcItems = opcServer.GetOPCItems(opcBrowser); string itemName = "ItemName"; OPCItem opcItem = opcItems.GetOPCItem(itemName); object itemValue = opcItem.Value; Console.WriteLine("Item Value: " + itemValue); opcServer.Disconnect(); } } ``` 以上代码通过OPCAutomation命名空间中的OPCServer类和OPCItem类实现了与OPC服务器的交互,并同步读取了指定变量的值。请注意,实际使用时需要替换"OPCServerName"和"ItemName"为相应的实际值。 ### 回答2: 在C#中,使用OPC(OLE for Process Control)来同步读取数据十分简单。首先,需要引用OPC相关的程序集,通常为OPC Foundation提供的OPC插件。这些程序集包含了操作OPC服务器的必要方法和类。 首先,需要创建一个OPC服务器对象。可以使用OPC Foundation提供的OpcCom.Server类来实例化一个OPC服务器对象,然后调用其Connect方法连接到OPC服务器。 接下来,需要创建一个OPC组对象,用于读取数据。可以使用Opc.Da.Group类来创建一个组对象,并使用服务器对象的CreateGroup方法。在创建组对象时,可以指定读取数据的频率和其他参数。 然后,可以使用组对象的AddItems方法添加要读取OPC项。OPC项是一个标识符,用于唯一标识OPC服务器上的一个数据点。可以通过Opc.Da.Item类来创建一个OPC项,并设置其标识符和其他属性。 之后,可以调用组对象的Read方法来同步读取数据。Read方法将返回一个Opc.Da.ItemValueCollection对象,其中包含了所有读取数据项及其对应的值。可以遍历该集合来获取每个数据项的值。 最后,可以调用服务器对象的Disconnect方法来断开与OPC服务器的连接。这样,就完成了OPC同步读取数据的过程。 需要注意的是,OPC是一种标准化的通信协议,可以连接到各种不同的设备和系统。因此,在实际使用中,需要根据具体的OPC服务器数据点进行相应的配置和调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值