Subscriptionsare used to report Notificationsto the Client. Their general behaviour is summarized below. Their precise behaviour is described in 5.13.1.2.

  1. Subscriptionshave a set of MonitoredItemsassigned to them by the Client. MonitoredItemsgenerate Notificationsthat are to be reported to the Clientby the Subscription(see 5.12.1for a description of MonitoredItems).
  2. Subscriptionshave a publishing interval. The publishing interval of a Subscriptiondefines the cyclic rate at which the Subscriptionexecutes. Each time it executes, it attempts to send a NotificationMessageto the Client. NotificationMessagescontain Notificationsthat have not yet been reported to Client.
  3. NotificationMessagesare sent to the Clientin response to Publishrequests. Publishrequests are normally queued to the Session as they are received, and one is de-queued and processed by a Subscriptionrelated to this Sessionfor each publishing cycle, if there are Notificationsto report. When there are not, the Publishrequest is not de-queued from the Session, and the Serverwaits until the next cycle and checks again for Notifications.
  4. At the beginning of a cycle, if there are Notificationsto send but there are no Publishrequests queued, the Serverenters a wait state for a Publishrequest to be received. When one is received, it is processed immediately without waiting for the next publishing cycle.
  5. NotificationMessagesare uniquely identified by sequence numbers that enable Clientsto detect missed Messages. The publishing interval also defines the default sampling interval for its MonitoredItems.
  6. Subscriptionshave a keep-alive counter that counts the number of consecutive publishing cycles in which there have been no Notificationsto report to the Client. When the maximum keep-alive count is reached, a Publishrequest is de-queued and used to return a keep-alive Message. This keep-alive Messageinforms the Clientthat the Subscriptionis still active. Each keep-alive Messageis a response to a Publishrequest in which the notificationMessageparameter does not contain any Notificationsand that contains the sequence number of the next NotificationMessagethat is to be sent. In the clauses that follow, the term NotificationMessagerefers to a response to a Publishrequest in which the notificationMessageparameter actually contains one or more Notifications, as opposed to a keep-alive Messagein which this parameter contains no Notifications. The maximum keep-alive count is set by the Clientduring Subscriptioncreation and may be subsequently modified using the ModifySubscription Service. Similar to Notificationprocessing described in (c) above, if there are no Publishrequests queued, the Serverwaits for the next one to be received and sends the keep-alive immediately without waiting for the next publishing cycle.
  7. Publishing by a Subscriptionmay be enabled or disabled by the Clientwhen created, or subsequently using the SetPublishingMode Service. Disabling causes the Subscriptionto cease sending NotificationMessagesto the Client. However, the Subscriptioncontinues to execute cyclically and continues to send keep-alive Messagesto the Client.
  8. Subscriptionshave a lifetime counter that counts the number of consecutive publishing cycles in which there have been no Publishrequests available to send a Publishresponse for the Subscription. Any Servicecall that uses the SubscriptionIdor the processing of a Publishresponse resets the lifetime counter of this Subscription. When this counter reaches the value calculated for the lifetime of a Subscriptionbased on the MaxKeepAliveCount parameter in the CreateSubscription Service(5.13.2), the Subscriptionis closed. Closing the Subscriptioncauses its MonitoredItemsto be deleted. In addition the Servershall issue a StatusChangeNotification notificationMessagewith the status code Bad_Timeout. The StatusChangeNotification notificationMessagetype is defined in 7.25.4.
  9. Sessionsmaintain a retransmission queue of sent NotificationMessages. NotificationMessagesare retained in this queue until they are acknowledged. The Sessionshall maintain a retransmission queue size of at least two times the number of Publishrequests per Sessionthe Serversupports. A Profilein OPC 10000-7may make the retransmission queue support optional. The minimum number of Publishrequests per Sessionthe Servershall support is defined in OPC 10000-7. Clientsare required to acknowledge NotificationMessagesas they are received if the Publishresponse parameter availableSequenceNumbersis not an empty array. An empty array in availableSequenceNumbersindicates that the Serverdoes not support a retransmission queue and acknowledgement of NotificationMessages. In the case of a retransmission queue overflow, the oldest sent NotificationMessagegets deleted. If a Subscriptionis transferred to another Session, the queued NotificationMessagesfor this Subscriptionare moved from the old to the new Session.

The sequence number is an unsigned 32-bit integer that is incremented by one for each NotificationMessagesent. The value 0 is never used for the sequence number. The first NotificationMessagesent on a Subscriptionhas a sequence number of 1. If the sequence number rolls over, it rolls over to 1.

When a Subscriptionis created, the first Messageis sent at the end of the first publishing cycle to inform the Clientthat the Subscriptionis operational. A NotificationMessageis sent if there are Notificationsready to be reported. If there are none, a keep-alive Messageis sent instead that contains a sequence number of 1, indicating that the first NotificationMessagehas not yet been sent. This is the only time a keep-alive Messageis sent without waiting for the maximum keep-alive count to be reached, as specified in (f) above.

A Clientshall be prepared for receiving Publishresponses for a Subscriptionmore frequently than the corresponding publishing interval. One example is the situation where the number of available notifications exceeds the Subscriptionsetting maxNotificationsPerPublish. A Clientis always able to control the timing of the Publishresponses by not queueing Publishrequests. If a Clientdoes not queue Publishrequests in the Server, the Servercan only send a Publishresponse if it receives a new Publishrequest. This would increase latency for delivery of notifications but allows a Clientto throttle the number of received Publishresponses in high load situations.

The value of the sequence number is never reset during the lifetime of a Subscription. Therefore, the same sequence number shall not be reused on a Subscriptionuntil over four billion NotificationMessageshave been sent. At a continuous rate of one thousand NotificationMessagesper second on a given Subscription, it would take roughly fifty days for the same sequence number to be reused. This allows Clientsto safely treat sequence numbers as unique.

Sequence numbers are also used by Clientsto acknowledge the receipt of NotificationMessages. Publishrequests allow the Clientto acknowledge all Notificationsup to a specific sequence number and to acknowledge the sequence number of the last NotificationMessagereceived. One or more gaps may exist in between. Acknowledgements allow the Serverto delete NotificationMessagesfrom its retransmission queue.

Clientsmay ask for retransmission of selected NotificationMessagesusing the Republish Service. This Servicereturns the requested Message.

Subscriptionsare designed to work independent of the actual communication connection between OPC UA Clientand Serverand independent of a Session. Short communication interruptions can be handled without losing data or events. To make sure that longer communication interruptions or planned disconnects can be handled without losing data or events, an OPC UA Servermay support durable Subscriptions. If this feature is supported, the Serveraccepts a high Subscription RequestedLifetimeCountand large MonitoredItem QueueSizeparameter settings. Subclause 6.8describes how durable Subscriptionscan be created and used.

The state table formally describes the operation of the Subscription. The following model of operations is described by this state table. This description applies when publishing is enabled or disabled for the Subscription.

After creation of the Subscription, the Serverstarts the publishing timer and restarts it whenever it expires. If the timer expires the number of times defined for the Subscriptionlifetime without having received a Subscription Servicerequest from the Client, the Subscriptionassumes that the Clientis no longer present, and terminates.

Clientssend Publishrequests to Serversto receive Notifications. Publishrequests are not directed to any one Subscriptionand, therefore, may be used by any Subscription. Each contains acknowledgements for one or more Subscriptions. These acknowledgements are processed when the Publishrequest is received. The Serverthen queues the request in a queue shared by all Subscriptions, except in the following cases.

  1. The previous Publishresponse indicated that there were still more Notificationsready to be transferred and there were no more Publishrequests queued to transfer them.
  2. The publishing timer of a Subscriptionexpired and there were either Notificationsto be sent or a keep-alive Messageto be sent.

In these cases, the newly received Publishrequest is processed immediately by the first Subscriptionto encounter either case (a) or case (b).

Each time the publishing timer expires, it is immediately reset. If there are Notificationsor a keep-alive Messageto be sent, it de-queues and processes a Publishrequest. When a Subscriptionprocesses a Publishrequest, it accesses the queues of its MonitoredItemsand de-queues its Notifications, if any. It returns these Notificationsin the response, setting the moreNotificationsflag if it was not able to return all available Notificationsin the response.

If there were Notificationsor a keep-alive Messageto be sent but there were no Publishrequests queued, the Subscriptionassumes that the Publishrequest is late and waits for the next Publishrequest to be received, as described in case (b).

If the Subscriptionis disabled when the publishing timer expires or if there are no Notificationsavailable, it enters the keep-alive state and sets the keep-alive counter to its maximum value as defined for the Subscription.

While in the keep-alive state, it checks for Notificationseach time the publishing timer expires. If one or more Notificationshave been generated, a Publishrequest is de-queued and a NotificationMessageis returned in the response. However, if the publishing timer expires without a Notificationbecoming available, a Publishrequest is de-queued and a keep-alive Messageis returned in the response. The Subscriptionthen returns to the normal state of waiting for the publishing timer to expire again. If, in either of these cases, there are no Publishrequests queued, the Subscriptionwaits for the next Publishrequest to be received, as described in case (b).

The Subscriptionstates are defined in Table 84.

Table 84– Subscription States

State

Description

CLOSED

The Subscriptionhas not yet been created or has terminated.

CREATING

The Subscriptionis being created.

NORMAL

The Subscriptionis cyclically checking for Notificationsfrom its MonitoredItems. The keep-alive counter is not used in this state.

LATE

The publishing timer has expired and there are Notificationsavailable or a keep-alive Messageis ready to be sent, but there are no Publishrequests queued. When in this state, the next Publishrequest is processed when it is received. The keep-alive counter is not used in this state.

KEEPALIVE

The Subscriptionis cyclically checking for Notificationsfrom its MonitoredItemsor for the keep-alive counter to count down to 0 from its maximum.

The state table is described in Table 85. The following rules and conventions apply.

  1. Eventsrepresent the receipt of Servicerequests and the occurrence internal Events, such as timer expirations.
  2. Servicerequests Eventsmay be accompanied by conditions that test Serviceparameter values. Parameter names begin with a lower case letter.
  3. Internal Eventsmay be accompanied by conditions that test state Variablevalues. State Variablesare defined in 5.13.1.3. They begin with an upper case letter.
  4. Servicerequest and internal Eventsmay be accompanied by conditions represented by functions whose return value is tested. Functions are identified by “()” after their name. They are described in 5.13.1.4.
  5. When an Eventis received, the first transition for the current state is located and the transitions are searched sequentially for the first transition that meets the Eventor conditions criteria. If none are found, the Eventis ignored.
  6. Actions are described by functions and state Variablemanipulations.
  7. The LifetimeTimerExpires Eventis triggered when its corresponding counter reaches zero.

Table 85– Subscription State Table

#

Current State

Event/Conditions

Action

Next State

1

CLOSED

Receive CreateSubscription Request

CreateSubscription()

CREATING

2

CREATING

CreateSubscription fails

ReturnNegativeResponse()

CLOSED

3

CREATING

CreateSubscription succeeds

InitializeSubscription()

MessageSent = FALSE

ReturnResponse()

NORMAL

4

NORMAL

Receive PublishRequest

&&

(

PublishingEnabled == FALSE

||

(PublishingEnabled == TRUE

&& MoreNotifications == FALSE)

)

DeleteAckedNotificationMsgs()

EnqueuePublishingReq()

NORMAL

5

NORMAL

Receive PublishRequest

&& PublishingEnabled == TRUE

&& MoreNotifications == TRUE

ResetLifetimeCounter()

DeleteAckedNotificationMsgs()

ReturnNotifications()

MessageSent = TRUE

NORMAL

6

NORMAL

PublishingTimer Expires

&& PublishingReqQueued == TRUE

&& PublishingEnabled == TRUE

&& NotificationsAvailable == TRUE

ResetLifetimeCounter()

StartPublishingTimer()

DequeuePublishReq()

ReturnNotifications()

MessageSent == TRUE

NORMAL

7

NORMAL

PublishingTimer Expires

&& PublishingReqQueued == TRUE

&& MessageSent == FALSE

&&

(

PublishingEnabled == FALSE

||

(PublishingEnabled == TRUE

&& NotificationsAvailable == FALSE)

)

ResetLifetimeCounter()

StartPublishingTimer()

DequeuePublishReq()

ReturnKeepAlive()

MessageSent == TRUE

NORMAL

8

NORMAL

PublishingTimer Expires

&& PublishingReqQueued == FALSE

&&

(

MessageSent == FALSE

||

(PublishingEnabled == TRUE

&& NotificationsAvailable == TRUE)

)

StartPublishingTimer()

LATE

9

NORMAL

PublishingTimer Expires

&& MessageSent == TRUE

&&

(

PublishingEnabled == FALSE

||

(PublishingEnabled == TRUE

&& NotificationsAvailable == FALSE)

)

StartPublishingTimer()

ResetKeepAliveCounter()

KeepAliveCounter--

KEEPALIVE

10

LATE

Receive PublishRequest

&& PublishingEnabled == TRUE

&& (NotificationsAvailable == TRUE

|| MoreNotifications == TRUE)

ResetLifetimeCounter()

DeleteAckedNotificationMsgs()

ReturnNotifications()

MessageSent = TRUE

NORMAL

11

LATE

Receive PublishRequest

&&

(

PublishingEnabled == FALSE

||

(PublishingEnabled == TRUE

&& NotificationsAvailable == FALSE

&& MoreNotifications == FALSE)

)

ResetLifetimeCounter()

DeleteAckedNotificationMsgs()

ReturnKeepAlive()

MessageSent = TRUE

KEEPALIVE

12

LATE

PublishingTimer Expires

StartPublishingTimer()

LATE

13

KEEPALIVE

Receive PublishRequest

DeleteAckedNotificationMsgs()

EnqueuePublishingReq()

KEEPALIVE

14

KEEPALIVE

PublishingTimer Expires

&& PublishingEnabled == TRUE

&& NotificationsAvailable == TRUE

&& PublishingReqQueued == TRUE

ResetLifetimeCounter()

StartPublishingTimer()

DequeuePublishReq()

ReturnNotifications()

MessageSent == TRUE

NORMAL

15

KEEPALIVE

PublishingTimer Expires

&& PublishingReqQueued == TRUE

&& KeepAliveCounter <= 1

&&

(

PublishingEnabled == FALSE

||

(PublishingEnabled == TRUE

&& NotificationsAvailable == FALSE

)

StartPublishingTimer()

DequeuePublishReq()

ReturnKeepAlive()

ResetKeepAliveCounter()

KEEPALIVE

16

KEEPALIVE

PublishingTimer Expires

&& KeepAliveCounter > 1

&&

(

PublishingEnabled == FALSE

||

(PublishingEnabled == TRUE

&& NotificationsAvailable == FALSE)

)

StartPublishingTimer()

KeepAliveCounter--

KEEPALIVE

17

KEEPALIVE

PublishingTimer Expires

&& PublishingReqQueued == FALSE

&&

(

KeepAliveCounter == 1

||

(KeepAliveCounter > 1

&& PublishingEnabled == TRUE

&& NotificationsAvailable == TRUE)

)

StartPublishingTimer()

LATE

18

NORMAL

|| LATE

|| KEEPALIVE

Receive ModifySubscription Request

ResetLifetimeCounter()

UpdateSubscriptionParams()

ReturnResponse()

SAME

19

NORMAL

|| LATE

|| KEEPALIVE

Receive SetPublishingMode Request

ResetLifetimeCounter()

SetPublishingEnabled()

MoreNotifications = FALSE

ReturnResponse()

SAME

20

NORMAL

|| LATE

|| KEEPALIVE

Receive Republish Request

&& RequestedMessageFound == TRUE

ResetLifetimeCounter()

ReturnResponse()

SAME

21

NORMAL

|| LATE

|| KEEPALIVE

Receive Republish Request

&& RequestedMessageFound == FALSE

ResetLifetimeCounter()

ReturnNegativeResponse()

SAME

22

NORMAL

|| LATE

|| KEEPALIVE

Receive TransferSubscriptions Request

&& SessionChanged() == FALSE

ResetLifetimeCounter()

ReturnNegativeResponse ()

SAME

23

NORMAL

|| LATE

|| KEEPALIVE

Receive TransferSubscriptions Request

&& SessionChanged() == TRUE

&& ClientValidated() ==TRUE

SetSession()

ResetLifetimeCounter()

ReturnResponse()

IssueStatusChangeNotification()

SAME

24

NORMAL

|| LATE

|| KEEPALIVE

Receive TransferSubscriptions Request

&& SessionChanged() == TRUE

&& ClientValidated() == FALSE

ReturnNegativeResponse()

SAME

25

NORMAL

|| LATE

|| KEEPALIVE

Receive DeleteSubscriptions Request

&& SubscriptionAssignedToClient ==TRUE

DeleteMonitoredItems()

DeleteClientPublReqQueue()

CLOSED

26

NORMAL

|| LATE

|| KEEPALIVE

Receive DeleteSubscriptions Request

&& SubscriptionAssignedToClient ==FALSE

ResetLifetimeCounter()

ReturnNegativeResponse()

SAME

27

NORMAL

|| LATE

|| KEEPALIVE

LifetimeCounter == 1

The LifetimeCounter is decremented if PublishingTimer expires and PublishingReqQueued == FALSE

The LifetimeCounter is reset if PublishingReqQueued == TRUE.

DeleteMonitoredItems()

IssueStatusChangeNotification()

CLOSED

The state variables are defined alphabetically in Table 86.

Table 86– State variables and parameters

State Variable

Description

MoreNotifications

A boolean value that is set to TRUE only by the CreateNotificationMsg() when there were too many Notificationsfor a single NotificationMessage.

LatePublishRequest

A boolean value that is set to TRUE to reflect that, the last time the publishing timer expired, there were no Publishrequests queued.

LifetimeCounter

A value that contains the number of consecutive publishing timer expirations without Clientactivity before the Subscriptionis terminated.

MessageSent

A boolean value that is set to TRUE to mean that either a NotificationMessageor a keep-alive Messagehas been sent on the Subscription. It is a flag that is used to ensure that either a NotificationMessageor a keep-alive Messageis sent out the first time the publishing timer expires.

NotificationsAvailable

A boolean value that is set to TRUE only when there is at least one MonitoredItemthat is in the reporting mode and that has a Notificationqueued or there is at least one item to report whose triggering item has triggered and that has a Notificationqueued. The transition of this state Variablefrom FALSE to TRUE creates the “New NotificationQueued” Eventin the state table.

PublishingEnabled

The parameter that requests publishing to be enabled or disabled.

PublishingReqQueued

A boolean value that is set to TRUE only when there is a Publishrequest Messagequeued to the Subscription.

RequestedMessageFound

A boolean value that is set to TRUE only when the Messagerequested to be retransmitted was found in the retransmission queue.

SeqNum

The value that records the value of the sequence number used in NotificationMessages.

SubscriptionAssignedToClient

A boolean value that is set to TRUE only when the Subscriptionrequested to be deleted is assigned to the Clientthat issued the request. A Subscriptionis assigned to the Clientthat created it. That assignment can only be changed through successful completion of the TransferSubscriptions Service.

The action functions are defined alphabetically in Table 87.

Table 87– Functions

Function

Description

ClientValidated()

A boolean function that returns TRUE only when the Clientthat is submitting a TransferSubscriptions request is operating on behalf of the same user and supports the same Profilesas the Clientof the previous Session.

CreateNotificationMsg()

Increment the SeqNum and create a NotificationMessagefrom the MonitoredItemsassigned to the Subscription.

Save the newly-created NotificationMessagein the retransmission queue.

If all available Notificationscan be sent in the Publishresponse, the MoreNotifications state Variableis set to FALSE. Otherwise, it is set to TRUE.

CreateSubscription()

Attempt to create the Subscription.

DeleteAckedNotificationMsgs()

Delete the NotificationMessagesfrom the retransmission queue that were acknowledged by the request.

DeleteClientPublReqQueue()

Clear the Publishrequest queue for the Clientthat is sending the DeleteSubscriptions request, if there are no more Subscriptionsassigned to that Client.

DeleteMonitoredItems()

Delete all MonitoredItemsassigned to the Subscription.

DequeuePublishReq()

De-queue a publishing request in first-in first-out order.

Validate if the publish request is still valid by checking the timeoutHint in the RequestHeader.

If the request timed out, send a Bad_Timeoutservice result for the request and de-queue another publish request.

ResetLifetimeCounter()

EnqueuePublishingReq()

Enqueue the publishing request.

InitializeSubscription()

ResetLifetimeCounter()

MoreNotifications = FALSE

PublishRateChange = FALSE

PublishingEnabled = value of publishingEnabled parameter in the CreateSubscription request

PublishingReqQueued = FALSE

SeqNum = 0

SetSession()

StartPublishingTimer()

IssueStatusChangeNotification()

Issue a StatusChangeNotification notificationMessagewith a status code for the status change of the Subscription. The StatusChangeNotification notificationMessagetype is defined in 7.25.4. Bad_Timeout status code is used if the lifetime expires and Good_SubscriptionTransferred is used if the Subscriptionswas transferred to another Session.

ResetKeepAliveCounter()

Reset the keep-alive counter to the maximum keep-alive count of the Subscription. The maximum keep-alive count is set by the Clientwhen the Subscriptionis created and may be modified using the ModifySubscription Service.

ResetLifetimeCounter()

Reset the LifetimeCounter Variableto the value specified for the lifetime of a Subscriptionin the CreateSubscription Service(5.13.2).

ReturnKeepAlive()

CreateKeepAliveMsg()

ReturnResponse()

ReturnNegativeResponse ()

Return a Serviceresponse indicating the appropriate Servicelevel error. No parameters are returned other than the responseHeader that contains the Servicelevel StatusCode.

ReturnNotifications()

CreateNotificationMsg()

ReturnResponse()

If (MoreNotifications == TRUE) && (PublishingReqQueued == TRUE)

{

DequeuePublishReq()

Loop through this function again

}

ReturnResponse()

Return the appropriate response, setting the appropriate parameter values and StatusCodesdefined for the Service.

SessionChanged()

A boolean function that returns TRUE only when the Sessionused to send a TransferSubscriptions request is different from the Client Sessioncurrently associated with the Subscription.

SetPublishingEnabled ()

Set the PublishingEnabled state Variableto the value of the publishingEnabled parameter received in the request.

SetSession

Set the Sessioninformation for the Subscriptionto match the Sessionon which the TransferSubscriptions request was issued.

StartPublishingTimer()

Start or restart the publishing timer and decrement the LifetimeCounter Variable.

UpdateSubscriptionParams()

Negotiate and update the Subscriptionparameters. If the new keep-alive interval is less than the current value of the keep-alive counter, perform ResetKeepAliveCounter() and ResetLifetimeCounter().