OPC Server Example Tutorial: OPC Client - C#. NET Example

Keywords: ASP.NET

OPC Server It is a framework that uses Microsoft COM/DCOM technology to achieve industrial automation data acquisition. OPC Server provides an OPC interface, which returns the information value of the connected physical device (PLC) to the client application through the interface. That is to say, through these interfaces, the client can get the information o. F The physical devices are connected to the OPC Server. For integrated applications, as long as the OPC interface is supported, physical devices can be easily accessed without the need for relevant technical information.

[OPC Server Latest Edition Download]

If you access OPC Server from. NET, you need to exchange COM and. NET wrappers. It explains how C#. NET uses RCW (Runtime Callable Wrapper) to access the OPC server here.

Connect to OPC Server via COM

Create an instance of a COM connection, specify the CLSD of the OPC server, and you can get each interface pointer of the OPC, such as the OPC server object and browsing object.

IOPCServerList svrList = (IOPCServerList)CreateInstance(CLSID_SERVERLIST, null);
Guid clsidList;
svrList.CLSIDFromProgID(sSvrName, out clsidList);
m_OPCServer = (IOPCServer)CreateInstance(clsidList, sNodeName);
AddGroup(sGrpName, iUpdateRate);
IOPCCommon m_com = (IOPCCommon)m_OPCServer;

Create an OPC group and add labels

Group objects need to be created in the OPC server to retrieve actual data from outside. Data update cycles can be set as group objects, and are typically registered with the same synchronously accessed device. Because each group's threads are created in the OPC server, please note that CPU load increases by too many subdivisions.

// Add OPCGroup
guidGroupStateMgt = Marshal.GenerateGuidForType(typeof(IOPCGroupStateMgt2));
m_OPCServer.AddGroup(sGrpName, (bActive) ? 1 : 0, iUpdateRate,
                        iClientGroup, ptrTimeBias, ptrDeadBand, iLCID,
                        out m_iServerGroup, out iRevisedUpdateRate,
                        ref guidGroupStateMgt, out group);
m_OPCGroup2 = (IOPCGroupStateMgt2)group;
m_OPCGroup2.SetKeepAlive(iKeepAliveTime, out iKeepAliveTime);
m_OPCConnPointCntnr = (IConnectionPointContainer)m_OPCGroup2;
guidDataCallback = Marshal.GenerateGuidForType(typeof(IOPCDataCallback));
m_OPCConnPointCntnr.FindConnectionPoint(ref guidDataCallback, out m_OPCConnPoint);

// Add OPCItems
for (i = 0; i < iItemCount; i++)
{
  itemDef[i].szItemID = ItemName[i];
  itemDef[i].bActive = 1;
  itemDef[i].hClient = ClientHd[i];
}
m_OPCItem = (IOPCItemMgt)m_OPCGroup2;
m_OPCItem.AddItems(iItemCount, itemDef, out ppResult, out ppErrors);	

Synchronized Reading/Writing and ASync Reading/Writing

OPC has two data access modes, Synchronize and Asynchronous. In Synchronize, the client application must wait for the server to complete its work. However, the client application can confirm that the server transaction is completed properly, because the OPC server returns the result when it completes the communication work. This is a normal procedure.

In asynchronous mode, the OPC server will transfer the handle to the client immediately after receiving the request, and continue to execute the transaction in the background. After that, call the handler of the client application. Asynchronous mode reduces the waiting time of communication and can run client applications.

Tip: Enable asynchronous access in recommended mode.

// Read by IOPCSyncIO
OPCSyncIO2 = (IOPCSyncIO2)m_OPCGroup2;
OPCSyncIO2.Read(OPC_DS_DEVICE /*OPC_DS_CACHE*/, iItemCount, ServerHd, out ppItemVal, out ppErrors);
Marshal.Copy(ppErrors, Errors, 0, iItemCount);
posItem = ppItemVal;
for (i=0; i<iItemCount; i++)
{
  ItemState = (OPCITEMSTATE)Marshal.PtrToStructure(posItem, typeof(OPCITEMSTATE));
  if (Errors[i] == 0)
  {
    Values[i] = ItemState.vDataValue;
    TimeStamps[i] = ItemState.ftTimeStamp;
    Qualities[i] = ItemState.wQuality;
  }
  Marshal.DestroyStructure(posItem, typeof(OPCITEMSTATE));
  posItem = new IntPtr(posItem.ToInt32() + Marshal.SizeOf(typeof(OPCITEMSTATE)));
}

// Write by IOPCSyncIO.
OPCSyncIO2.Write(iItemCount, ServerHd, Value, out ppErrors);
Marshal.Copy(ppErrors, errors, 0, iItemCount);
Marshal.FreeCoTaskMem(ppErrors);

The cache read (OPC_DS_CACHE) immediately returns the latest data values in the server memory without communication. The OPC server automatically updates the data according to the registration update cycle of each group. It can be accessed at high speed when it may not be the latest data.

// Read by IOPCASyncIO
OPCAsyncIO3 = (IOPCAsyncIO3)m_OPCGroup2;
OPCAsyncIO3.Read(iItemCount, ServerHd, wTransID, out wCancelID, out ppErrors);

// Write by IOPCASyncIO
OPCAsyncIO3 = (IOPCAsyncIO3)m_OPCGroup2;
OPCAsyncIO3.Write(iItemCount, ServerHd, Value, wTransID, out wCancelID, out ppErrors);
Marshal.FreeCoTaskMem(ppErrors);


Posted by kidbrax on Wed, 08 May 2019 18:42:40 -0700