# White Paper ## Obtaining Data and Detecting Status Changes in OPC UA Asynchronous Workflows ### Polling, Subscriptions, and Result-Based Synchronization --- # Abstract This white paper examines the best way to obtain data and detect status changes in an OPC UA asynchronous workflow. In OPC UA systems, a write request or method call often starts a process, but the expected result may appear later. That result can be: - a status change - a new value - a new job entry - processed data becoming available - confirmation that a configuration change has taken effect Because of this asynchronous behavior, fixed delays are a weak primary synchronization method. A more reliable approach is based on waiting for the expected result through polling or subscriptions. As a general rule: - polling is usually the best choice for one-time workflow steps - subscriptions are usually the best choice for continuous monitoring This document explains why deterministic delays are weak, how asynchronous OPC UA workflows behave, and how more reliable synchronization can be built with documented nodes, timeouts, polling, and subscriptions. --- # 1. Introduction OPC UA is widely used to connect software systems, machines, controllers, and automation platforms. It provides access to operational data, job information, configuration values, and workflow control methods. In many real integrations, the workflow includes: - sending a command - waiting for processing - reading produced data - detecting status changes - continuing only when the system is ready This is a synchronization problem. OPC UA workflows are often asynchronous. A server may accept a command immediately, while the real work continues in the background. For this reason, reliable synchronization is based on the server result rather than on a guessed delay. --- # 2. Understanding the Asynchronous Workflow In an asynchronous OPC UA workflow, the following sequence is common: 1. A value is written or a method is called. 2. The server accepts the request. 3. Internal processing starts. 4. Data or status changes appear later. 5. The resulting information is read or received. This means that a successful method call does not always mean the full operation is complete. Examples in SmartDFE and SPC include: - a job appears in `AllJobs/WaitingQueue` only after import processing - `PreprocessorStatus` changes over time until it becomes `Complete` - `PrintRun/IsActive` becomes `true` after the print run really starts - a media change may require `App.ApplySettings()` before the new configuration takes effect In all of these cases, a reliable mechanism is needed to determine when the expected result is actually available. --- # 3. Why a Deterministic Delay Approach Does Not Work Well The simplest idea is often: 1. send a command 2. wait a fixed number of seconds 3. assume the result is ready This deterministic delay approach looks easy, but it is not a strong design. ## 3.1 Processing time is not constant Real systems do not always behave with the same timing. Processing time can change because of: - server load - job complexity - network latency - configuration differences - connected device readiness - temporary resource contention A delay that works today may fail tomorrow. ## 3.2 A delay can be too short If the delay is shorter than the real processing time: - the data may not yet be available - the expected status may not yet be reached - the next operation may fail - the workflow may become unstable ## 3.3 A delay can be too long If the delay is longer than necessary: - the workflow becomes slower - throughput is reduced - user experience becomes worse - time is wasted without technical benefit ## 3.4 Delays hide real failure conditions A fixed delay cannot explain what happened during the wait. It does not indicate whether: - the process completed successfully - the process is still running - the process failed - the result is invalid - the server never started the requested action Because of this, deterministic delays are weak both for reliability and for diagnostics. --- # 4. Result-Based Synchronization The underlying model is simple: 1. a command is sent 2. the node or nodes that prove completion are identified 3. the expected data or status is awaited 4. processing continues only when the expected result is available 5. a timeout or error condition ends the wait if the result does not arrive This model is stronger because it is based on real server behavior. The expected result may be: - a node value changing to a target value - a new item appearing in a queue - processed data becoming readable - a boolean flag becoming `true` - a configuration readback matching the written value This is the core principle of reliable OPC UA synchronization. --- # 5. Two Recommended Techniques There are two main ways to wait for the expected result in OPC UA: 1. polling 2. subscriptions ## 5.1 Polling Polling means one or more nodes are read repeatedly until: - the expected result is found - an error state is found - a timeout is reached Polling is simple and very useful when a single result is expected after a specific action. Typical examples: - wait for a new job GUID to appear - wait for preprocessing to complete - wait for a print run to become active - wait for a value to be updated by server-side processing ## 5.2 Subscriptions Subscriptions mean the server is asked to notify the consumer when a value changes. This technique is usually preferred when values must be observed continuously over time. Typical examples: - monitor print run status - monitor counters or alarms - drive a live dashboard - react to long-running machine or process changes --- # 6. Choosing Between Polling and Subscription The choice depends on the workflow goal. | Situation | Recommended Technique | | --- | --- | | One command followed by one expected result | Polling | | Import or processing workflow with clear checkpoints | Polling | | Continuous live monitoring | Subscription | | UI dashboards and alarms | Subscription | | Long-running observation of machine values | Subscription | ## 6.1 Polling for one-time workflow steps Polling is often the easiest and most practical solution for steps such as: - submit a job, then wait until the job exists - request processing, then wait until the data is available - start a run, then wait until the run is active In these situations, permanent monitoring is not required. Only one confirmed result is needed before the next step. ## 6.2 Subscription for continuous monitoring Subscriptions are usually preferred when status or data must be observed over a longer period. In these cases, repeated reads are less efficient than receiving change notifications from the server. --- # 7. Polling Is Not the Same as a Blind Delay This distinction is important. A short sleep inside a polling loop is acceptable because it is only the interval between checks. It is not the main synchronization method. Example: - delay-based approach: always wait 10 seconds after `StartPrintRun()` - polling approach: read `PrintRun/IsActive` every 1 second and continue immediately when it becomes `true` In the second approach, waiting is still present, but it is controlled by the observed result: - it can finish early - it can detect errors - it can stop with a timeout - it can log the last known status This is why polling is deterministic in control, but not blind in timing. --- # 8. Examples from SmartDFE and SPC Workflows The Smart Connectivity documentation and the reviewed C# samples show several practical examples of result-based synchronization. ## 8.1 External control before modifying the system Before writes or method calls, external control availability is confirmed. Relevant node: - `App/IsExternalControlActive` This is not only a permission check. It is also a workflow checkpoint before control operations begin. ## 8.2 Waiting for an imported job to become visible After a job is submitted, the job may not be visible immediately. A typical result-based sequence is: 1. submit the job 2. monitor `AllJobs/WaitingQueue` 3. detect the new GUID 4. continue with that GUID The workflow waits for the actual data to appear, not for an estimated import delay. ## 8.3 Waiting for processed job data After job import, preprocessing may continue for some time. Observation can be based on: - `AllJobs//PreprocessorStatus` - `AllJobs//Printability` The workflow continues only when: - preprocessing is complete - the produced result is valid for the next step ## 8.4 Waiting for configuration changes to take effect Some changes require `App.ApplySettings()` before they take effect. A typical result-based flow is: 1. write the new value 2. call `App.ApplySettings()` 3. wait until the readback or dependent node shows the expected result This is more reliable than waiting for an arbitrary delay after the method call. ## 8.5 Waiting for a print run to start After `StartPrintRun()`, the run is not assumed to be active immediately. A typical result-based flow is: 1. call `StartPrintRun()` 2. monitor `PrintRun/IsActive` 3. optionally read `PrintRun/Status` 4. continue when the run is really active This is a good example of waiting for status and readiness together. --- # 9. C# Reference with the Traeger OPC UA Library The reviewed samples use the Traeger OPC UA .NET client library: ```csharp using Opc.UaFx; using Opc.UaFx.Client; ``` ## 9.1 Polling example for a one-time asynchronous result This example waits until processing completes and the expected result becomes available. ```csharp using System; using System.Threading; using Opc.UaFx.Client; using var client = new OpcClient("opc.tcp://server:26542/spc"); client.Connect(); var jobGuid = "example-job-guid"; var deadline = DateTime.UtcNow.AddMinutes(5); while (DateTime.UtcNow < deadline) { var status = client.ReadNode($"ns=2;s=AllJobs/{jobGuid}/PreprocessorStatus").Value?.ToString(); var printability = client.ReadNode($"ns=2;s=AllJobs/{jobGuid}/Printability").Value?.ToString(); if (string.Equals(status, "Complete", StringComparison.OrdinalIgnoreCase)) break; if (string.Equals(status, "Failed", StringComparison.OrdinalIgnoreCase) || string.Equals(printability, "Error", StringComparison.OrdinalIgnoreCase)) { throw new InvalidOperationException( $"Processing failed. Status={status}, Printability={printability}"); } Thread.Sleep(500); } ``` This is better than a fixed delay because: - it finishes as soon as the result is ready - it detects an error condition - it fails with a clear timeout if the result never arrives ## 9.2 Subscription example for continuous status monitoring This example listens for status changes continuously. ```csharp using System; using Opc.UaFx.Client; using var client = new OpcClient("opc.tcp://server:26542/spc"); client.Connect(); var subscription = client.SubscribeDataChange( "ns=2;s=PrintRun/Status", (sender, e) => { Console.WriteLine($"PrintRun/Status = {e.Item.Value}"); }); subscription.PublishingInterval = 1000; subscription.ApplyChanges(); Console.ReadLine(); ``` This is a good model when live updates are needed over time. --- # 10. Design Recommendations For asynchronous OPC UA workflows, the following design principles are recommended: 1. Define the exact result that proves completion. 2. Use documented nodes as workflow checkpoints. 3. Use polling for discrete one-time steps. 4. Use subscriptions for continuous monitoring. 5. Always use timeouts. 6. Check for explicit failure conditions, not only success conditions. 7. Log the last known data or status on timeout. 8. Verify external control before writes and method calls when required. 9. After configuration changes, confirm the effective result instead of assuming it. --- # 11. Conclusion The most reliable way to obtain data and detect status changes in an OPC UA asynchronous workflow is to synchronize on the expected result. That result may be: - a status change - a new data value - a new queue entry - processed output becoming available - confirmation that a write or method call has taken effect For this reason, fixed deterministic delays are not a strong primary workflow design. The stronger design is: - poll for one-time results - subscribe for continuous monitoring - continue only when the expected data or status is actually available This approach is more reliable, faster, easier to diagnose, and better aligned with real OPC UA behavior. --- # References ## Public documentation - Smart Connectivity OPC UA Interface Guide - Smart Print Controller overview - Traeger OPC UA .NET Client Development Guide