OPC通信

OPC DA组件

基本读取

使用Regsvr32对OPCDAAuto.dll进行注册

Regsvr32 OPCDAAuto.dll

注册完成后OPCDAAuto.dll的位置不能随便移动

1、在c#控制台项目中,需要添加COM引用,名称:OPC DA Automation Wrapper

2、将项目修改为x86平台

3、创建OPCDAServer连接

//创建OPCServer:并不是创建一个服务器,而是一个服务器连接

OPCServer server = new OPCServer();

//参数ProgID

server.Connect("Kepware.KEPServerEX.V6");

server.Connect("Kepware.KEPServerEX.V6")硬编码,可修改为:

cs 复制代码
//获取本机所有的kepware服务器
var servers =  server.GetOPCServers();

//组件中获取的集合数组,索引都是从1开始的。servers集合,索引从1开始
server.Connect(servers[1]);

if (server.ServerState == (int)OPCServerState.OPCRunning)
{
    //标签浏览扫描
    var opcBrower = server.CreateBrowser();
    opcBrower.ShowBranches();
    opcBrower.ShowLeafs(true);
    foreach (var item in opcBrower)
    {
        Console.WriteLine(item);
    }
    OPCGroup ogp = server.OPCGroups.Add();
    //读取单个标签
    //System.Runtime.InteropServices.COMException:"0xC0040007":标签无法识别
    OPCItem oi1 = ogp.OPCItems.AddItem("数据类型示例.16 位设备.R 寄存器.Short1", 111);
    OPCItem oi2 = ogp.OPCItems.AddItem("数据类型示例.16 位设备.R 寄存器.Short2", 111);
    OPCItem oi3 = ogp.OPCItems.AddItem("数据类型示例.16 位设备.R 寄存器.Short3", 111);
    OPCItem oi4 = ogp.OPCItems.AddItem("数据类型示例.16 位设备.R 寄存器.Short4", 111);
    //OPCDataSource.OPCDevice:实时从设备读取数据;OPCDataSource.OPCCache:读取kepware中缓存的数据
    oi1.Read((short)OPCDataSource.OPCDevice, out object value1, out object quality1, out object ts1);
    oi2.Read((short)OPCDataSource.OPCDevice, out object value2, out object quality2, out object ts2);
    oi3.Read((short)OPCDataSource.OPCDevice, out object value3, out object quality3, out object ts3);
    oi4.Read((short)OPCDataSource.OPCDevice, out object value4, out object quality4, out object ts4);

    //批量读取数据
    Array serverHandles = new int[]
    {
        0,//OPCDA的组件,默认对数组的读取都是从1开始的,所有数组中的数据,要放到索引1之后
        oi1.ServerHandle,
        oi2.ServerHandle,
        oi3.ServerHandle,
        oi4.ServerHandle,
    };
    Array values = new Object[] { 0 };//读到的数据也是从索引1开始存储的
    Array errors = new Object[] { 0 };
    object qualitys = new object();
    object ts = new object();
    ogp.SyncRead(
        Source: (short)OPCDataSource.OPCDevice,
        NumItems: 4,//一次请求的标签数量
        ServerHandles: ref serverHandles,
        Values: out values,
        Errors: out errors,
        Qualities: out qualitys,
        TimeStamps: out ts
        );
}

异步读取

cs 复制代码
//异步读取
int transactionId = 123;//这个相当于请求的幂等性
ogp.IsSubscribed = true;//异步读取需要打开订阅标识
ogp.AsyncRead(NumItems: 4,
    ServerHandles: ref serverHandles,
    Errors: out errors,
    TransactionID: transactionId,
    CancelID: out int cancelId//将异步读取的任务分配一个编号
    );
//ogp.AsyncCancel(cancelId);//可以使用cancelId编号,手动取消那些耗时的操作
ogp.AsyncReadComplete += Ogp_AsyncReadComplete;//读取完成之后回调


/// <summary>
/// 异步读取回调
/// </summary>
/// <param name="TransactionID"></param>
/// <param name="NumItems"></param>
/// <param name="ClientHandles">和OPCItem设置的ClientHandle匹配,ClientHandles的顺序来确定OPCItem返回值的顺序</param>
/// <param name="ItemValues"></param>
/// <param name="Qualities"></param>
/// <param name="TimeStamps"></param>
/// <param name="Errors"></param>
private static void Ogp_AsyncReadComplete(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps, ref Array Errors)
{
	
}

OPCDA订阅模式

cs 复制代码
OPCItem oi1 = ogp.OPCItems.AddItem("数据类型示例.16 位设备.R 寄存器.Short1", 111);
OPCItem oi2 = ogp.OPCItems.AddItem("数据类型示例.16 位设备.R 寄存器.Short2", 222);
OPCItem oi3 = ogp.OPCItems.AddItem("数据类型示例.16 位设备.R 寄存器.Short3", 333);
OPCItem oi4 = ogp.OPCItems.AddItem("数据类型示例.16 位设备.R 寄存器.Short4", 444);
OPCItem oi5 = ogp.OPCItems.AddItem("数据类型示例.16 位设备.R 寄存器.ShortArray", 555);

ogp.IsSubscribed = true;//打开订阅标识
ogp.DataChange += Ogp_DataChange;//数据变化时,触发回调

/// <summary>
/// 监听ogp关联的OPCItem节点数据
/// </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 static void Ogp_DataChange(int TransactionID, int NumItems, ref Array ClientHandles, ref Array ItemValues, ref Array Qualities, ref Array TimeStamps)
{

}

OPCDA写入

cs 复制代码
OPCItem oi1 = ogp.OPCItems.AddItem("数据类型示例.16 位设备.R 寄存器.Short1", 111);
OPCItem oi2 = ogp.OPCItems.AddItem("数据类型示例.16 位设备.R 寄存器.Short2", 222);
OPCItem oi3 = ogp.OPCItems.AddItem("数据类型示例.16 位设备.R 寄存器.Short3", 333);
OPCItem oi4 = ogp.OPCItems.AddItem("数据类型示例.16 位设备.R 寄存器.Short4", 444);
OPCItem oi5 = ogp.OPCItems.AddItem("数据类型示例.16 位设备.R 寄存器.ShortArray", 555);//读取数组

oi1.Write(456);//单次写入

//批量写入
Array writeArray = new Object[] {
 0,
 111,
 222,
 333,
 444,
 new short[] { 123,456,789,666}//这个地方不需要使用0进行占位。写入的数组元素个数和kepware里数组的个数相同,否则写不进去
};
//同步写
ogp.SyncWrite(
 NumItems: 5,
ServerHandles: ref serverHandles,
Values: ref writeArray,
Errors: out errors
 );

ogp.IsSubscribed = true;
//ogp.AsyncWrite();异步写
ogp.AsyncWriteComplete += Ogp_AsyncWriteComplete;//异步写回调
相关推荐
DuHz1 天前
利用汽车雷达测试系统模拟多径效应——论文阅读
论文阅读·汽车·信息与通信·信号处理
通信小呆呆1 天前
收发分离多基地雷达椭圆联合定位:原理、算法与误差分析
算法·目标检测·信息与通信·信号处理
北京耐用通信2 天前
破解工业通信瓶颈:耐达讯自动化Modbus转Profinet网关连接驱动器的奥秘
人工智能·物联网·网络协议·自动化·信息与通信
北京耐用通信2 天前
电力自动化新突破:Modbus如何变身Profinet?智能仪表连接的终极解决方案
人工智能·物联网·网络安全·自动化·信息与通信
liulilittle2 天前
国际带宽增长与用户体验下降的悖论
网络·网络协议·信息与通信·ip·ux·带宽·通信
智奇数美2 天前
“成本减法”与“效率乘法”——AI智能重构企业通信格局
人工智能·智能手机·信息与通信
AORO20253 天前
防爆手机与普通手机有什么区别?防爆手机哪个牌子好?
运维·服务器·网络·5g·智能手机·信息与通信
XINVRY-FPGA3 天前
XC7A100T-2FGG484I Xilinx Artix-7 FPGA
arm开发·嵌入式硬件·fpga开发·硬件工程·信息与通信·信号处理·fpga
AORO20254 天前
卫星电话收费标准:每月10元起!
网络·5g·安全·智能手机·信息与通信
杂化轨道VSEPR5 天前
一个手机的奇幻之旅(手机在基站间的切换)
5g·智能手机·信息与通信