当前位置: 代码网 > it编程>编程语言>Asp.net > C#实现OPC通讯编程详解

C#实现OPC通讯编程详解

2026年09月24日 Asp.net 我要评论
opc(ole for process control)是一种工业自动化领域的数据交换标准接口。文章深入探讨了使用c#实现opc通讯的基本原理、关键步骤和技巧。重点讨论了opc核心概念、c#中opc客

opc(ole for process control)是一种工业自动化领域的数据交换标准接口。文章深入探讨了使用c#实现opc通讯的基本原理、关键步骤和技巧。重点讨论了opc核心概念、c#中opc客户端库的使用,提供了c# opc通讯示例代码,并阐述了实现过程中应注意的认证、权限管理等细节问题。读者将通过本课程设计项目深入理解opc的三个主要部分(da、hda、ae)并掌握c#在opc通讯中的实践应用。

1. opc标准接口介绍

opc技术概览

opc(ole for process control)是一种开放的工业自动化和监控标准。它定义了一套用于工业设备之间通信的接口、功能和数据模型,使得不同厂商的软件和硬件能够无缝协作。opc分为多个子协议,包括 opc da(data access),opc hda(historical data access),opc ua(unified architecture)等,以满足实时数据访问、历史数据存储和高级功能如安全和事务处理的需求。

为什么选择opc

在工业自动化和信息技术领域,opc技术因其开放性和标准性成为了连接不同系统和设备的首选方法。它有助于降低系统集成的复杂性,提供了一种跨平台、跨语言的解决方案,使得系统维护和升级变得更加简单。

opc的工业应用

opc标准的应用涵盖了各种工业自动化场景,例如制造业、能源管理、环境监测等。通过opc,开发人员能够实现生产数据的高效获取和监控,优化生产过程,提升生产效率和产品质量。接下来,我们将探讨如何在c#中实现opc通讯,以进一步理解其技术细节和应用方式。

2. c#中实现opc通讯的基本原理

2.1 opc通讯的架构和组件

2.1.1 opc服务器与客户端的交互

opc通讯模型中,服务器(server)和客户端(client)是核心组件。服务器负责收集来自工厂自动化设备或系统的信息,并将其转换成统一的opc接口供客户端访问。客户端则是请求信息的应用程序,它可以是监控系统、数据库、甚至远程用户界面。

opc通讯遵循客户端-服务器模型,客户端通过标准的opc接口发起数据请求,服务器响应这些请求并提供相应的数据。这种交互通常涉及到网络通信,其中最常见的协议是opc da(data access)标准。通信流程如下:

  1. 初始化连接 :客户端首先识别并连接到opc服务器。
  2. 浏览 :客户端查询服务器中的可用数据项。
  3. 订阅与读取 :客户端订阅感兴趣的特定数据项,并定期读取这些数据的值。
  4. 更新与通知 :服务器根据数据项的变化,主动通知客户端数据更新。
  5. 写入与控制 :客户端可以向服务器写入数据值来控制相关设备。
  6. 断开连接 :通信结束后,客户端断开与服务器的连接。

2.1.2 opc数据访问模型

opc数据访问模型定义了客户端如何与服务器交互以访问数据。这一模型是基于com(component object model)技术,因此它依赖于微软的windows操作系统进行通信。

核心概念包括: - opc item :代表了服务器上的一个数据点,如温度传感器的读数。 - group :一组opc item的集合,用于管理相关的数据项。 - subscription :订阅机制,允许客户端接收关于opc item值变化的通知。 - data access server :提供opc item数据的标准接口。 - opc client :通过标准接口与opc server交互的应用程序。

一个典型的opc数据访问模型流程包含以下步骤: 1. 创建组(group) :客户端创建一个组来组织其感兴趣的opc item。 2. 添加项(add items) :在组中添加特定的opc item。 3. 读取数据(read data) :客户端请求读取组内opc item的当前值。 4. 写入数据(write data) :客户端请求更新组内opc item的值以控制设备。 5. 订阅数据(subscribe) :客户端订阅组内opc item的变化,并设置更新的频率。

2.2 c#实现opc通讯的api选择

2.2.1 标准的opc接口与c#绑定

c#作为.net框架中的一员,能够利用ole for process control (opc) automation接口。这些接口通过com自动化提供给.net应用程序。使用这些接口需要引入opc foundation提供的类型库(tlb文件),这样就可以在c#中调用相应的com对象和方法。

要使用标准的opc接口,首先必须在开发环境中注册opc automation库。注册后,可以通过 interop.opcautomation 命名空间访问opc对象和属性。需要注意的是,标准opc自动化接口主要支持同步操作,并且可能有性能上的限制。

2.2.2 第三方库的使用与集成

由于标准opc接口的限制,业界开发了许多第三方库以解决性能和功能上的不足。这些库包括: - opc foundation opc .net api :这个库提供了更高效的本地接口和异步操作支持。 - commercial opc servers :如kepware kepserverex、matrikon opc server等,它们提供了易于使用的api和更强大的功能集。 - 开源库 :如libopcua,这是一个c++库,也可以在.net环境中使用,其支持最新的opc ua标准。

集成第三方库到c#项目中通常包括以下几个步骤: 1. 下载并安装 :获取所需库的安装包或nuget包。 2. 添加引用 :在项目中添加库的引用。 3. 配置环境 :根据库的文档,配置必要的项目设置和运行时环境。 4. api文档 :阅读库提供的api文档,理解可用的方法和类。 5. 测试和验证 :编写简单的测试代码来验证库的集成。

2.2.3 代码示例

以下是一个使用opc foundation的opc .net api在c#中进行opc通讯的简单示例:

using opc.da;

public class simpleopcclient
{
    private opc.da.server server;
    private opc.da.itemresult[] itemresults;
    private object[] values;

    public void connect(string servername)
    {
        // create server object
        server = new opc.da.server(new opccom.factory(), servername);
        // initialize server and connect
        server.initialize();
        server.connect("opcserver", true);
    }

    public void readvalues()
    {
        // define the opc item identifiers
        itemidentifier[] itemstoread = new itemidentifier[2];
        itemstoread[0] = new itemidentifier("item1", opc.da.browsepath.geterged);
        itemstoread[1] = new itemidentifier("item2", opc.da.browsepath.geterged);

        // read the values for each item
        itemresults = server.read(itemstoread, out values);
    }
}

在此示例中, connect 方法创建了一个 opc.da.server 对象,并连接到了指定的opc服务器。 readvalues 方法定义了要读取的两个项,并使用 server.read 方法来获取它们的值。

请注意,实际开发过程中,需要根据具体的服务器和数据项,调整代码逻辑和异常处理,以确保opc通讯的稳定性和效率。

3. opc客户端库的使用

3.1 安装与配置opc客户端库

3.1.1 库的下载和安装步骤

在开始使用opc客户端库之前,首先需要了解如何下载和安装这些库。大多数的opc客户端库可以通过nuget包管理器进行安装,这是.net环境中管理和安装第三方库的标准方式。安装步骤通常如下:

  1. 打开visual studio,并选择你的项目。
  2. 在visual studio中,选择“工具”菜单,然后选择“nuget包管理器” -> “管理解决方案的nuget包”。
  3. 在打开的nuget窗口,选择“浏览”标签。
  4. 在搜索栏中输入你想要安装的opc客户端库的名字。
  5. 从结果列表中选择合适的库并点击“安装”。

确保在安装之前检查库的兼容性,确认它与你的.net版本匹配。安装过程中,系统可能会提示你接受许可协议,并可能需要你选择合适的配置(如debug或release模式)。

3.1.2 配置环境与依赖

安装完opc客户端库之后,需要配置环境并确保所有依赖项都已正确安装。这一步骤通常涉及以下内容:

  • 设置库的引用:确保你的项目已正确引用了安装的opc客户端库,这通常在项目属性的“引用”设置中完成。
  • 配置应用程序配置文件:如果库需要额外的配置,如代理设置或远程连接信息,则需要在应用程序的配置文件(如 app.config web.config )中进行设置。
  • 验证依赖项:有些库可能有额外的依赖项,例如某些版本的.net framework或某些特定的运行时组件。这些依赖项需要通过nuget包管理器安装或更新。

具体的配置方法会依赖于你所选择的opc客户端库,因此请参考相关库的官方文档进行配置。始终建议检查库的文档,了解有关配置的最新和最具体的信息。

3.2 常用opc客户端库功能解析

3.2.1 连接管理与监控

opc客户端库的核心功能之一是管理与opc服务器的连接。这一部分的功能涉及到建立、维护、监控以及在必要时断开与opc服务器的连接。大多数现代的opc客户端库都提供了连接管理的抽象,使得开发者能够更加专注于业务逻辑而不是底层细节。

例如,下面是一段用c#编写的伪代码,展示了如何使用opc客户端库连接到服务器,并且实现连接的监控:

// 创建客户端实例
var opcclient = new opcclient();

// 连接至服务器,url为服务器地址,用户名和密码用于认证
opcclient.connect("opc.tcp://server-address", "username", "password");

// 检查是否成功连接
if (opcclient.connected)
{
    // 连接成功,可以进行数据读写操作
}

// 监控连接状态的回调示例
opcclient.onconnectionchanged += (sender, args) =>
{
    if (args.connected)
    {
        console.writeline("连接成功!");
    }
    else
    {
        console.writeline("连接断开!");
    }
};

// 断开连接
opcclient.disconnect();

在上面的代码中,我们创建了一个 opcclient 实例,并使用 connect 方法与服务器建立连接。如果连接成功, connected 属性将为真。 onconnectionchanged 事件用于监控连接状态的变化,当连接成功或断开时,都会触发此事件。

3.2.2 数据读写与交换机制

数据读写是opc客户端库中另一个关键的功能。它允许开发者从opc服务器读取数据和向服务器写入数据,实现数据的实时交换。

下面是一个简单的示例,展示如何使用opc客户端库读取和写入数据:

// 假设我们已经建立了连接

// 读取数据项
var result = opcclient.read(itemstoread);
if (result.status == resultstatus.good)
{
    foreach (var item in result.items)
    {
        console.writeline($"{item.name}: {item.value}");
    }
}

// 写入数据项
var writevalues = new dictionary<string, object>
{
    { "item1", 123 },
    { "item2", 456 }
};

var writeresult = opcclient.write(writevalues);
if (writeresult.status == resultstatus.good)
{
    console.writeline("数据写入成功!");
}
else
{
    console.writeline("数据写入失败!");
}

在上面的示例中,我们使用 read 方法从服务器读取数据,并用 write 方法将数据写回服务器。读取的数据项以及写入的数据项通过字典( dictionary<string, object> )来传递。其中,键(key)代表服务器中的项名,值(value)代表项值。

这些操作通常都包含错误处理逻辑。例如,如果读取或写入操作失败,我们可以通过检查 result.status writeresult.status 来获取失败的原因。在实际应用中,错误处理机制需要更加完善,以应对各种潜在的运行时错误。

4. c# opc通讯示例代码

4.1 创建opc连接与读写示例

4.1.1 建立与opc服务器的连接

在 opc 的世界里,创建连接是实现通讯的基础。在 c# 中,我们通常使用第三方库如 opcfoundation.opccom 来与 opc 服务器交互。以下是一个示例代码块,展示如何使用该库创建与 opc 服务器的连接。

// 引入 opc 命名空间
using opccomrcw.hda;
using opc.da;

// 创建 com 连接对象
opccom.da.server server = new opccom.da.server();

// 初始化连接
string opcserverurl = "opc.da://localhost/yourserver";
server.connect(opcserverurl, true);

// 读取 opc 服务器信息
string servername = server.getstatus().szserver;
console.writeline("connected to server: " + servername);

连接逻辑分析

  • using opccomrcw.hda; 和 using opc.da; 这两行代码是为了引入 opc 相关的库和命名空间,以便使用相应的类和方法。
  • opccom.da.server server = new opccom.da.server(); 创建一个 opc 服务器对象,用于之后的操作。
  • server.connect(opcserverurl, true); 方法尝试连接到指定的 opc 服务器,其中 opcserverurl 是服务器的地址,第二个参数 true 表示连接操作需要同步执行。
  • server.getstatus().szserver 获取并打印服务器信息,确认连接成功。

4.1.2 数据项的读取与写入

读取数据项和写入数据项是 opc 客户端与服务器交互的两个基本动作。接下来,我们来演示如何在 c# 中进行这些操作。

// 定义要读取的 item
string itemid = "your.item.id";
itemvalueresult readresult = server.read(new object[] { itemid });
console.writeline("item value: " + readresult.value.tostring());

// 修改 item 的值并写入服务器
itemvalueresult writeresult = server.write(new object[] { itemid, "new value" });
console.writeline("write status: " + writeresult.error.tostring());

数据读写逻辑分析

  • itemvalueresult readresult = server.read(new object[] { itemid }); 通过 read 方法读取指定的 opc 服务器数据项。 itemid 是我们想要读取的数据项标识符。
  • console.writeline("item value: " + readresult.value.tostring()); 打印读取到的数据值。
  • itemvalueresult writeresult = server.write(new object[] { itemid, "new value" }); 通过 write 方法将新值写入到指定的数据项。这里我们使用了同样的 itemid ,但是提供了新的值 "new value" 。
  • console.writeline("write status: " + writeresult.error.tostring()); 打印写操作的结果状态。

4.2 实现动态数据监控与回调机制

4.2.1 数据变化的实时响应

实时监控数据变化并做出响应是 opc 客户端常见的需求。通过使用 opc 的订阅机制,可以实现动态数据监控。

// 创建订阅对象
subscription subscription = (subscription)server.createsubscription();
subscription.updaterate = 1000; // 更新周期设置为 1000 毫秒

// 添加项到订阅
itemstate itemstate = new itemstate();
itemstate.itemname = itemid;
subscription.additems(new itemstate[] { itemstate });

// 订阅数据变化事件
subscription.datachanged += new datachangedeventhandler(subscription_datachanged);
subscription.start();

// 等待事件触发
console.writeline("waiting for data change...");
console.readline(); // 暂停程序,等待用户输入以退出

// 停止订阅
subscription.stop();

实时响应逻辑分析

  • subscription subscription = (subscription)server.createsubscription(); 创建一个订阅对象。
  • subscription.updaterate = 1000; 设置订阅更新周期为 1000 毫秒。
  • itemstate itemstate = new itemstate(); 创建一个 itemstate 对象用于监控。
  • itemstate.itemname = itemid; 设置需要监控的数据项标识符。
  • subscription.additems(new itemstate[] { itemstate }); 将 itemstate 对象添加到订阅。
  • subscription.datachanged += new datachangedeventhandler(subscription_datachanged); 添加数据变化事件的处理函数。
  • subscription.start(); 开始订阅,开始监控数据变化。
// 事件处理函数
private static void subscription_datachanged(object sender, datachangedeventargs e)
{
    itemvalueresult[] results = e.itemresults;
    foreach (itemvalueresult result in results)
    {
        console.writeline("item: " + result.itemname + " value: " + result.value.tostring());
    }
}

事件处理逻辑分析

  • 事件处理函数 subscription_datachanged 被调用时,参数 e.itemresults 包含了所有变化的数据项和它们的新值。
  • foreach 循环遍历这些数据项,并打印出每个数据项的名称和值。

4.2.2 事件处理与回调函数

opc 数据项的变化可以触发事件处理函数,回调函数可以在数据变化时执行特定的代码逻辑。

// 定义回调函数
private static void itemcallback(itemstate item)
{
    console.writeline("item id: " + item.itemname + " value: " + item.value.tostring());
}

// 在订阅对象中注册回调函数
subscription.itemstatechange += new itemstatechangeeventhandler(itemcallback);

回调函数逻辑分析

  • itemcallback 函数定义了当数据项发生变化时,需要执行的逻辑。
  • subscription.itemstatechange += new itemstatechangeeventhandler(itemcallback); 将该函数注册为订阅对象的事件回调。

在本章节中,我们详细讲解了如何在 c# 中使用 opc 客户端库创建连接、读取和写入数据,以及如何实现数据的动态监控和处理回调事件。通过以上代码和解释,读者应该能够理解基本的 opc 通讯实现,并根据需要应用到实际的项目中。

在接下来的章节中,我们将深入探讨如何处理多个 opc 服务器、组或项,以及如何在通讯过程中实现异常处理、数据过滤和缓存机制,同时还会探讨服务器认证、权限管理及异步操作的实现。

5. 处理多个opc服务器、组或项

随着工业自动化的发展,实时数据的收集与处理变得越来越复杂。在这样的背景下,管理多个opc服务器、组和项成为了一项重要的任务。这一章节将深入探讨如何在c#环境中使用opc技术处理多个opc服务器实例,并组织管理它们的组和项,以实现高效的数据交互和管理。

5.1 管理多个opc服务器实例

在进行复杂的工业控制系统集成时,可能需要同时与多个opc服务器进行交互。为了有效地管理这些服务器实例,开发者需要采取特定的策略来维护服务器列表,并确保服务器之间的有效连接与重连。

5.1.1 服务器列表的创建与维护

创建一个服务器列表是管理多个opc服务器实例的首要步骤。开发者需要定义一个数据结构来存储服务器的地址、端口、名称等信息,同时还需要记录每个服务器的状态和连接信息。为了方便对服务器列表的管理,可以使用集合来动态添加或删除服务器实例。

// c# 代码示例:定义服务器信息类和服务器列表
public class opcserverinfo
{
    public string serverurl { get; set; }
    public bool isactive { get; set; }
    public opccomserver opcserver { get; set; }
    // 其他需要的信息
}

// 使用list来管理多个服务器实例
public class opcservermanager
{
    public list<opcserverinfo> servers { get; set; } = new list<opcserverinfo>();
    public void addserver(string url)
    {
        servers.add(new opcserverinfo { serverurl = url, isactive = false });
    }
    public void removeserver(string url)
    {
        var server = servers.firstordefault(s => s.serverurl == url);
        if (server != null)
        {
            servers.remove(server);
        }
    }
}

5.1.2 服务器断开重连策略

为了保证系统的稳定性和数据的实时性,服务器断开重连策略变得尤为重要。这需要开发者能够在服务器连接断开时检测到该状态,并尝试重新连接。可以使用定时器定期检查每个服务器的连接状态,或者设置事件监听服务器的连接状态变化。

public class opcservermanager
{
    // ... 已有代码 ...

    // 尝试连接服务器
    public void connecttoserver(opcserverinfo serverinfo)
    {
        try
        {
            if (serverinfo.opcserver == null || !serverinfo.isactive)
            {
                serverinfo.opcserver = new opccomserver(serverinfo.serverurl);
                // 连接成功后的操作
                serverinfo.isactive = true;
            }
        }
        catch (exception ex)
        {
            // 记录错误信息
            // 重新尝试连接或更新服务器状态
        }
    }

    // 定时检查服务器连接状态
    public void monitorservers()
    {
        foreach (var server in servers)
        {
            if (!server.isactive)
            {
                connecttoserver(server);
            }
        }
    }
}

5.2 组和项的组织管理

在opc通讯中,组和项的概念允许开发者以逻辑方式组织数据。分组管理提供了将相似或相关数据项组织在一起的能力,便于数据的管理和读写操作。

5.2.1 分组管理的意义与方法

分组管理可以基于不同的业务逻辑或物理设备来创建组,这使得数据的组织更加清晰和易于管理。开发者可以使用组来实现对数据的分类,比如按照生产线、工作单元或功能区进行分组。这样的管理方式能够提升数据查询和更新的效率。

public class opcgroupmanager
{
    public dictionary<string, opcgroup> groups { get; set; } = new dictionary<string, opcgroup>();
    public void creategroup(opcserverinfo serverinfo, string groupname)
    {
        if (!groups.containskey(groupname))
        {
            var group = serverinfo.opcserver.addgroup(groupname);
            groups[groupname] = group;
        }
    }
}

5.2.2 项的添加、删除和查询

在每个分组中,开发者可以添加、删除或查询数据项。添加项通常涉及到指定数据项的标识符,例如节点id或标签名。删除项时,需要确保该操作不会影响组内其他数据项的正常功能。查询项则允许开发者快速检索到特定的数据项,以便进行读取或写入操作。

public class opcitemmanager
{
    public list<opcitem> items { get; set; } = new list<opcitem>();
    public void additemtogroup(opcgroup group, opcitem item)
    {
        group.add(item);
    }
    public void removeitemfromgroup(opcgroup group, opcitem item)
    {
        group.remove(item);
    }
    public opcitem getitembyname(string itemname)
    {
        return items.firstordefault(item => item.name == itemname);
    }
}

为了将这些管理操作结合在一起,开发者可以创建一个综合的管理类,负责协调服务器、组和项的相互关系,并处理它们之间的交互。通过此类,可以更好地控制数据流,并保证系统的健壮性和扩展性。

通过本章节的介绍,开发者可以了解到如何在c#环境中高效地管理多个opc服务器实例,以及如何组织和管理分组和数据项。这些知识对于构建一个可扩展的、稳定的opc通讯系统至关重要,可以为未来进一步的开发和优化奠定坚实的基础。

6. 异常处理、数据过滤、数据缓存

6.1 opc通讯中的异常处理策略

在进行opc通讯时,网络波动、服务器不稳定或客户端错误等因素都可能导致通讯异常。因此,实现有效的异常处理策略对于确保系统稳定运行至关重要。

6.1.1 异常捕获与错误日志记录

在c#中,可以通过try-catch块来捕获在opc通讯过程中可能抛出的异常。对于每一个可能出错的地方,都应该有相对应的异常处理代码。

try
{
    // 尝试建立opc连接
    // ...
}
catch (comexception ex)
{
    // 特定于com异常的错误处理
    // ...
    logerror("opc com exception", ex);
}
catch (exception ex)
{
    // 捕获所有其他异常
    // ...
    logerror("generic opc exception", ex);
}

void logerror(string message, exception exception)
{
    // 实现错误日志记录逻辑
    // ...
}

在这个例子中,我们首先尝试建立opc连接。如果在过程中发生 comexception 异常,代码将执行特定的错误处理逻辑。而对于其他类型的异常,则通过通用的异常捕获块进行处理。

6.1.2 网络不稳定情况下的处理

网络不稳定是工业环境中常见的问题之一。在opc通讯中,需要设计一定的策略来处理网络中断和恢复的场景。

// 检查连接状态并尝试重连
if (!client.isconnected)
{
    try
    {
        client.connect();
    }
    catch (exception ex)
    {
        // 网络不稳定处理逻辑
        // ...
    }
}

在上述代码中,首先检查opc客户端是否已经连接。如果没有连接,则尝试重新建立连接。如果重连失败,则执行捕获块中的异常处理逻辑。

6.2 数据过滤与缓存机制

在数据密集型应用中,数据过滤与缓存是提高性能的关键。正确地设计数据过滤和缓存逻辑能够有效减少不必要的数据读取,降低网络负载,并提高应用程序的响应速度。

6.2.1 数据精度与采样率的设置

根据应用需求设置合适的数据精度和采样率非常重要。在实时监控系统中,过高的采样率可能会导致大量不必要的数据,而过低则可能丢失关键信息。

// 设置数据采样率与精度
client.readsamplingrate = 1000; // 采样率为1000毫秒
client.readprecision = 0.01;    // 读取精度为0.01

在这个示例中,我们设置了读取操作的采样率为1000毫秒,精度为0.01。这意味着每秒读取一次数据,并且数据值的最小变化为0.01。

6.2.2 缓存数据的读取与同步

缓存数据可以减少对服务器的重复读取请求,从而提高数据访问效率。对于动态变化的数据,实现一个时间戳机制来同步缓存数据与服务器数据是非常必要的。

// 读取缓存数据
if (cache.trygetvalue("temperature", out double cachedvalue))
{
    // 使用缓存数据
    // ...
}

// 更新缓存数据
void updatecache(string key, double newvalue)
{
    if (!cache.containskey(key))
    {
        cache.add(key, newvalue);
    }
    else
    {
        cache[key] = newvalue;
    }
    // 更新时间戳
    cachetimestamp[key] = datetime.utcnow;
}

// 检查数据是否过时
datetime currenttime = datetime.utcnow;
if ((currenttime - cachetimestamp["temperature"]).totalmilliseconds > 1000)
{
    // 数据过时,从服务器重新读取
    double freshvalue = client.readdata("temperature");
    updatecache("temperature", freshvalue);
}

上述代码段展示了如何通过一个字典 cache 来缓存数据,并记录每个数据项的时间戳。当需要读取数据时,会检查对应的时间戳以确定数据是否需要从服务器重新读取。通过这种方式,我们能够保证数据的时效性,同时减少不必要的网络流量。

在处理多个opc服务器、组或项时,数据过滤和缓存策略变得更加重要,特别是在数据量大和实时性要求高的工业系统中。本章节提供的策略和代码示例为实现高效和稳定的opc通讯提供了基础。在下一章,我们将探讨opc通讯的安全认证机制以及异步操作的优势和实现。

到此这篇关于c#实现opc通讯编程详解的文章就介绍到这了,更多相关c# opc通讯编程内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com