As denoted above, ESD does not provide equivalent functionality to OPC subscriptions. Therefore the OPC server has to implement this subscription architecture by itself. One way to do this is to periodically poll the ESD for a value of a fieldbus datapoint via an ESD READ command. However, OPC subscriptions are quite complicated issues and provide the following features:
Due to these difficulties a suitable architecture had to be designed and implemented.
When a client subscribes to one or more OPC items, a subscription object is created, as depicted in figure 64.
The function ``Subscribe'' first reads all requested items in a deferred style and adds a callback called ``addSubscription'' to prevent blocking of the server due to the read command. The callback function creates a subscription object, which is able to store all attributes and methods associated with this subscription. Then for every item the previously read value is cached and the two functions ``SampleItem'' and ``HandleSampledItem'' are created139, where the second function will handle the output of the first. Next a so-called ``LoopingCall'' is started and stored in the subscription object, which periodically calls the sampling functions. The last step is to set up a delayed call that cancels this subscription and all related sampling functions. This way, subscriptions will automatically be canceled in case the OPC client does not query the server within the ``ping rate''.
Figure 65 depicts how caching and buffering of OPC Items are implemented in the current design.
The function ``SampleItem'' first reads the fieldbus value in a deferred style. The result is handled by the callback function ``HandleSampledItem'', which stores the new value in the ``subscription cache'' in case it has changed140. If buffering is enabled for this subscribed item, the old value will be stored in the ``item buffer''. This FIFO-style buffer is not subscription specific and can store a predefined amount of items. If the buffer is full, the oldest entry will be deleted. In case a buffered item is lost, this event will be recorded by the subscription object so that it may notify OPC clients which retrieve buffered data from the server.
Figure 66 depicts an OPC ``Subscription Polled Request'' (SPR) which queries the OPC server for new values. An OPC SPR may query multiple subscriptions in one request.
After checking whether the specified subscriptions are valid, the polling of the subscription is blocked to guarantee that no other client may poll data from this subscription141. The next step is to cancel all automatic unsubscriptions, so that the subscription object is not deleted while a poll is taking place. Then the function creates a deferred and adds the callback ``PollWait'' in case the client specified a wait time and the callback function ``PollItems''. Then the server waits for the specified hold time and calls the next function in the callback chain.
If a client specifies a wait time, the server waits for the given time and returns immediately in case a value has changed or after the wait time has exceeded. Therefore the PollWait function first creates a deferred that is stored in the subscription object and sets up a WaitCancel function. This deferred will either be fired by the function ``HandleSampledItem'', which periodically checks for value changes and fires all deferreds in a subscription object, or by the WaitCancel function that is executed when the wait time has elapsed.
The function ``PollItems'' reads all changed values from the subscription cache and from the item buffer, denotes whether a buffer overflow has occurred and returns this data. Moreover, it establishes the automatic unsubscription function, so that the subscription is canceled in case the ping rate is exceeded.