cancel
Showing results for 
Search instead for 
Did you mean: 
SOLVED

Read/Write DataLayer Structure for OPC UA Client from PLC

Read/Write DataLayer Structure for OPC UA Client from PLC

ctrlXnovo
New Contributor

I would like to control the OPC UA Client App connect/disconnect from the PLC.  I also want to read the client state to verify that the connect/disconnect occured.  I have tried various fbs like DL_ReadNode, DL_ReadNodeValue, etc. but the data types are not correct and I get errors.  When I try to write, to trigger the connect or disconnect commands, I get an error, 16#0D0A0201 that I cannot find in the documentation:

ctrlXnovo_1-1668186308295.png

Are there any examples of how to do this?  I have seen some other examples in the forum but they are associated with other function blocks that exist, like motion function blocks.  How can I read/write objects (they look like JSON objects) in the datalayer from the PLC?

ctrlXnovo_0-1668186046610.png

 

4 REPLIES 4

JHU1XI1
Long-established Member

Although I have not tested, I see the document R911403768_ 06. There are related contents and cases for your reference.

CodeShepherd
Community Moderator
Community Moderator

After adding a client, in my case done via ctrlX CORE WebUI using:

{
"name":"Test",
"endpointUrl":"opc.tcp://127.0.0.1",
"sessionConfiguration":{
    "userToken":{"userIdentityToken_type":"TokenAnonymous",
    "userIdentityToken":{}},
"messageSecurityMode":{
    "messageSecurityMode":"BESTAVAILABLE"},
    "securityPolicy":{"securityPolicy":"BESTAVAILABLE"},
    "localeIds":["en-US"]}
}

You can see for each method which data type needs to send to this node and how it is structured. For "Connect" and "Disconnect" it is just an empty write. See "Operations" = "write" and "References" = "":

Data Layer UI opcuaclient connectData Layer UI opcuaclient connect

Declaration:

PROGRAM OPCUa_Client
VAR
	fbDL_WriteNode : DL_WriteNode;
	bExecute: BOOL;
	bDone: BOOL;
	bActive: BOOL;
	bError: BOOL;
	ErrorID: CXA_Datalayer.ERROR_CODE;
	ErrorIdent: CXA_Datalayer.ERROR_STRUCT;
	strNodeName: STRING(255) := 'opcuaclient/Test/connect'; //'opcuaclient/Test/disconnect'
END_VAR

Implementation:

fbDL_WriteNode(
	Execute:= bExecute, 
	Done=> bDone, 
	Active=> bActive, 
	Error=> bError, 
	ErrorID=> ErrorID, 
	ErrorIdent=> ErrorIdent, 
	ClientId:= , 
	NodeName:= strNodeName, 
	Value:= );

 

Reading the state means reading an object of the type "types/opcuaclient/state". This is done via a flatbuffer:

Data Layer UI opcuaclient stateData Layer UI opcuaclient state

Declaration:

PROGRAM OPCUa_Client
VAR
	fbClientState: CXA_OpcUaClient_fbs.comm_opcua_client_State; //Flatbuffer function out of CXA_Automationcore_fbs
	fbDL_ReadNodeValue: DL_ReadNodeValue; //Funktion block to read an flatbuffer out of CXA_Datalayer	
	bReadExecute: BOOL;
	bReadDone: BOOL;
	bReadActive: BOOL;
	bReadError: BOOL;
	ReadErrorID: CXA_Datalayer.ERROR_CODE;
	ReadErrorIdent: CXA_Datalayer.ERROR_STRUCT;
	DataRead: CXA_Datalayer.DL_NodeValue;
	strState: CXA_OpcUaClient_fbs.comm_opcua_client_ConnectionState;
END_VAR

Implementation:

fbDL_ReadNodeValue(
	Execute:= bReadExecute, 
	Done=> bReadDone, 
	Active=> bReadActive, 
	Error=> bReadError, 
	ErrorID=> ReadErrorID, 
	ErrorIdent=> ReadErrorIdent, 
	ClientId:= , 
	NodeName:= 'opcuaclient/Test/state', 
	NodeValue:= DataRead);
	
IF fbDL_ReadNodeValue.Done THEN	
	fbClientState.getRootAsState(data:= DataRead.GetData(), size:= DataRead.GetSize());
	strState := fbClientState.getState();
END_IF

 

See also other examples of reading and writing flatbuffer.

The read of the state works well.  Thank you!

I am still having a problem with the Write of the Connect or Disconnect.  It seems from your example that there is no value needed for the "Value" input, that simply writing to 'opcuaclient/xxxx/connect' is enough.  But when this did not work, I tried a boolean value. This resulted in the same errors displayed below.  The error codes, 0D0A0201 with 80E50000, are not documented that I can find.  This is the same problem I had in my previous attempt though the error codes are now different.

 

ctrlXnovo_0-1674071618181.png

Can you suggest what is wrong here?  I attached an XML export of my POU.

This error stopped occurring after a power cycle.  I cannot explain it past that.  The system had been powered on for months and this was probably the first power cycle in some time.  The original code in the solution above works now and the "write" to 'connect' or 'disconnect' does not require an actual value or variable in the "Value" input of the function block.

Icon--AD-black-48x48Icon--address-consumer-data-black-48x48Icon--appointment-black-48x48Icon--back-left-black-48x48Icon--calendar-black-48x48Icon--center-alignedIcon--Checkbox-checkIcon--clock-black-48x48Icon--close-black-48x48Icon--compare-black-48x48Icon--confirmation-black-48x48Icon--dealer-details-black-48x48Icon--delete-black-48x48Icon--delivery-black-48x48Icon--down-black-48x48Icon--download-black-48x48Ic-OverlayAlertIcon--externallink-black-48x48Icon-Filledforward-right_adjustedIcon--grid-view-black-48x48IC_gd_Check-Circle170821_Icons_Community170823_Bosch_Icons170823_Bosch_Icons170821_Icons_CommunityIC-logout170821_Icons_Community170825_Bosch_Icons170821_Icons_CommunityIC-shopping-cart2170821_Icons_CommunityIC-upIC_UserIcon--imageIcon--info-i-black-48x48Icon--left-alignedIcon--Less-minimize-black-48x48Icon-FilledIcon--List-Check-grennIcon--List-Check-blackIcon--List-Cross-blackIcon--list-view-mobile-black-48x48Icon--list-view-black-48x48Icon--More-Maximize-black-48x48Icon--my-product-black-48x48Icon--newsletter-black-48x48Icon--payment-black-48x48Icon--print-black-48x48Icon--promotion-black-48x48Icon--registration-black-48x48Icon--Reset-black-48x48Icon--right-alignedshare-circle1Icon--share-black-48x48Icon--shopping-bag-black-48x48Icon-shopping-cartIcon--start-play-black-48x48Icon--store-locator-black-48x48Ic-OverlayAlertIcon--summary-black-48x48tumblrIcon-FilledvineIc-OverlayAlertwhishlist