AsOpcUac: clean error handling for real application

Hello Community,

I have a question regarding a proper error handling regarding OPC UA C/S communication.

There is in the AS Help some error handling recommandations:

Error handling

Monitoring a connection

Restoring a connection

there is basically the recommandation that the application should avoid UA_Disconnect and a new UA_Connect if Timeouts like the SessionTimeout are not reached. Restoring a connection

On a standard application where the client subscribes to monitored items, we call dose FBS asynchronously until done and then basically nothing must be programmed except UA_ConnectGetStatus to monitor the connection.

  1. UA_Connect (SessionTimeout = 1m)

  2. UA_GetNSIndex

  3. UA_GetHandleList

  4. UA_SubscriptionCreate (PunblisingIntervall=50ms)

  5. UA_MonitoredItemAddList (QueueSize=0,Sampling=50ms)

  6. UA_ConnectionGetStatus (cyclically)

In case we get a status no connection with the server on UA_ConnectionGetStatus, how to react to it resp. how to know that we are still within the session timeout and we would therefore not need to repeat the all state machine?

What are your best practises?

Looking forward to your feedback.

Filipe

Hi @filipe.costa

I didn’t use AsOpcUac in AS6.X but I can share you my experience with AS4.

So in my experience the complexe things to handle was transfer, there is 2 cases when you transfer on your own PLC and the other one is when the transfer occurs on the remote PLC.

1. Transfer on your own PLC
When you transfer the program to your own PLC, you need to handle case of pointers getting invalid, AsOpcUac lib use “hidden pointers”. To handle this case, we just use the EXIT routine where we do:

  • RemoveMonitoredItems
  • DeleteSubscription
  • Disconnect

This was done inside of a FUB, so basicly in the EXIT routine we used a WHILE until all our client OpcUa where clearly disconnected.
Here an example of what can be in the EXIT routine in ST. (note that OpcUaClient variable is not a FUB from B&R it’s a customer one)

PROGRAM _EXIT
	
	(* Check if all FB are disabled *)
	FOR i:=0 TO MAX_OPCUA_CLIENT DO
		OpcUaClient[i].Enable := FALSE;
		
		WHILE OpcUaClient[i].Status <> ERR_FUB_ENABLE_FALSE DO
			OpcUaClient[i]();
		END_WHILE
		
	END_FOR
	
END_PROGRAM

2. Transfer occurs on the remote PLC
When a transfer occurs on the remote PLC you can detect it using the monitoring item operate FUB. This will return an errorId per Node (Bad_RessourceUnavailable) but you can follow same process for other errors.
For example, if a datatype difference is detected you didn’t want to let your OpcUa client connected you just need to log it, like this you can easily diagnose what append.
MonitoringItemOperate FUB was call every second when the OpcUaClient didn’t have error.
When we detect an error first we log it to the logger with the error code, then we:

  • RemoveMonitoredItems
  • DeleteSubscription
  • Disconnect
  • Connect
  • CreateSubscription
  • AddMonitoredItems

If the error (Bad_RessourceUnavailable) is still here we didn’t log again the error we wait until we reconnect and OperateMonitoringItem successfully.

For AS6.X I didn’t really know if you need to Disconnect and Reconnect but as we see in AS4 if the remote PLC warmrestart or the OpcUa server restart during the transfer it will be detected too.

Also I don’t know if UA_ConnectionGetStatus FUB return errors from MonitoringItems and all others FUB or if it’s only from connection (Connect/Disconnect errors), maybe someone else got this info!

Hope it could help!

Regards,
Florent

Hello Florent,

Thanks for your feedback.

Transfering SW is I believe a special use case. I’m using AS 4.12 in this context. Your input is any way really good.

What I mean here is really connection interruption (physically) between opc ua client and server. Which error handling should be done on the client programming?
The AS Help states that UA_Disconnect / UA_Connect should be avoided….so I’m confused

For instance: my understanding of the SessionTimeout of UA_Connect is that he server tries to re-establish a connection automatically within a session timeout. If the session timeout is reached, the client has to create a new connection with all its subscription again from scratch.

When do we know on the client side that sessiontimeout is expired and (most likely) we need to perform the all state machine again (UA_Connect etc). Do wee need to perform some kind of dummy ReadRequest(UA_Read) on the server and if we get as Result the ErrorId = Bad_SessionInvalid then we know connection has to be re-established by the client over UA_Connect etc…

Filipe

To be honest I never really check about the SessionTimeout and reconnect thing, I thing the FUB was not there ^^’

So to handle Bad_Disconnect, Bad_ConnectionClosed, in my case it was the same that for my point 2 “Transfer occurs on the remote PLC”. But by doing that we know that a session will stay on the OpcUa server until timeout occurs and it was ok for us.

Based on the help page you shared it seems that it’s a bit hard to know. Maybe someone has more experiences about this, I would be interested in infos about this too!

1 Like

Hi all,

I could figure out how it works by doing several tests and wireshark traces. UA_Disconnect is not needed. The client takes care of automatic reconnection, creating new session Id after session expiration and transferring subscriptions of this new session. This is done without any programming needed!

1 Connection Monitoring

  • Once the client has established a connection to the server, it performs active connection monitoring.

  • Controlled by the parameter UASessionConnectInfo.MonitorConnection (interval in ms).

  • At each interval:

    • The client sends a ReadRequest for ServerStatus.State (NodeId = ns=0;i=2259).

    • The read timeout is set equal to the interval.

  • Example:

    • MonitorConnection = 2000 ms

    • A read occurs every 2000 ms.

    • If no response is received, detection of an aborted connection occurs after max. 2 Ă— interval = 4000 ms.

2. Automatic Reconnection

  • If the connection is lost, the client runtime itself handles reconnection — the PLC application doesn’t need to intervene.

  • The client can always re-establish the connection as soon as the server is reachable again.

3. Session Expiry Case

  • If reconnection occurs before SessionTimeout has elapsed, the client reuses the existing session.

  • If reconnection occurs after SessionTimeout (server deleted the session due to inactivity):

    • The client automatically creates a new session.

    • It also re-creates all subscriptions and re-adds monitored items.

    • From the PLC application’s perspective, the session restoration is seamless.


:white_check_mark: Conclusion:
The AsOpcUa library handles connection monitoring and session recovery transparently, which simplifies PLC application code. The application only sees a temporary disconnect but does not need explicit logic for session recreation or subscription rebuild.

1 Like