OPC Studio User's Guide and Reference
Pull Data Provision Model
Concepts > OPC Wizard Concepts > OPC Wizard Operation Model > Data Provision And Consumption Models > Pull Data Provision Model
In This Topic

General

In the pull data provision model, you write a method that fulfills the OPC Read requests (and optionally subscription updates) by interrogating the underlying system, and returns the data that should be given to the OPC client. The OPC Wizard calls your method when needed (pulls the data).

This is the more common data provision model.

Your task as a developer is to provide the code for handling the Read request by either adding an event handler for the Read Event, or overriding the OnRead Method. The code for handling the data pull can be attached to each data variable separately, or you can use a common code on some higher level in the tree of the server nodes - for example, a folder can have code that handles all Reads for the data variables contained in the folder.

In order to indicate that you have handled the Read request, your code will call the HandleAndReturn Method on the event arguments object. Note that if you use the extension methods for configuration of data variables, the event handler added by the extension methods already does this for you.

The following picture illustrates how the pull data provision model works.

 

Extension Methods for Configuration

The OPC Wizard provides extension methods that allow you to define data variables that use the pull data provision model easily, without having to deal with method overrides, or handle events. This is described in the Data Variable Configuration article. Typically, you will use some overload of the ReadFunction or ReadValueFunction method to configure the data variable for the pull data provision model. With these methods, you use .NET functions (Func Delegate) to specify the code that handles the request. The following example illustrates the use of the ReadValueAction method.

.NET

// This example shows how to create a data variable and implement reading its value using a function.
// You can use any OPC UA client, including our Connectivity Explorer and OpcCmd utility, to connect to the server. 
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
// OPC client, server and subscriber examples in C# on GitHub: https://github.com/OPCLabs/Examples-OPCStudio-CSharp .
// Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
// a commercial license in order to use Online Forums, and we reply to every post.

using System;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.NodeSpace;

namespace UAServerDocExamples._UADataVariable
{
    partial class ReadValueFunction
    {
        public static void Main1()
        {
            // Instantiate the server object.
            // By default, the server will run on endpoint URL "opc.tcp://localhost:48040/".
            var server = new EasyUAServer();

            // Create a data variable, defining its read values by a function.
            // The type of the data variable (Int32, in this case) is inferred from the type returned by the function.
            var random = new Random();
            server.Add(new UADataVariable("ReadThisVariable").ReadValueFunction(() => random.Next()));

            // Start the server.
            Console.WriteLine("The server is starting...");
            server.Start();

            Console.WriteLine("The server is started.");
            Console.WriteLine();

            // Let the user decide when to stop.
            Console.WriteLine("Press Enter to stop the server...");
            Console.ReadLine();

            // Stop the server.
            Console.WriteLine("The server is stopping...");
            server.Stop();

            Console.WriteLine("The server is stopped.");
        }
    }
}
' This example shows how to create a data variable and implement reading its value using a function.
' You can use any OPC UA client, including our Connectivity Explorer and OpcCmd utility, to connect to the server. 
'
' Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
' OPC client and subscriber examples in VB.NET on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-VBNET .
' Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
' a commercial license in order to use Online Forums, and we reply to every post.

Imports System
Imports OpcLabs.EasyOpc.UA
Imports OpcLabs.EasyOpc.UA.NodeSpace

Namespace _UADataVariable
    Partial Friend Class ReadValueFunction
        Shared Sub Main1()
            ' Instantiate the server object.
            ' By default, the server will run on endpoint URL "opc.tcp://localhost:48040/".
            Dim server = New EasyUAServer()

            ' Create a data variable, defining its read values by a function.
            ' The type of the data variable (Int32, in this case) is inferred from the type returned by the function.
            Dim random = New Random()
            server.Add(New UADataVariable("ReadThisVariable").ReadValueFunction(Function() random.Next()))

            ' Start the server.
            Console.WriteLine("The server is starting...")
            server.Start()

            Console.WriteLine("The server is started.")
            Console.WriteLine()

            ' Let the user decide when to stop.
            Console.WriteLine("Press Enter to stop the server...")
            Console.ReadLine()

            ' Stop the server.
            Console.WriteLine("The server is stopping...")
            server.Stop()

            Console.WriteLine("The server is stopped.")
        End Sub
    End Class
End Namespace

How do you choose between these extension methods?

The following example illustrates the use of the ReadFunction method for returning data with a timestamp specified in your code.

.NET

// This example shows how to create a data variable and implement reading its attribute data using a function.
// You can use any OPC UA client, including our Connectivity Explorer and OpcCmd utility, to connect to the server. 
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
// OPC client, server and subscriber examples in C# on GitHub: https://github.com/OPCLabs/Examples-OPCStudio-CSharp .
// Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
// a commercial license in order to use Online Forums, and we reply to every post.

using System;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.Generic;
using OpcLabs.EasyOpc.UA.NodeSpace;

namespace UAServerDocExamples._UADataVariable
{
    partial class ReadFunction
    {
        public static void Main1()
        {
            // Instantiate the server object.
            // By default, the server will run on endpoint URL "opc.tcp://localhost:48040/".
            var server = new EasyUAServer();

            // Create a data variable, defining its read attribute data (including status code and source timestamp) by a
            // function.
            // The type of the data variable (Int32, in this case) is inferred from the type returned by the function.
            var random = new Random();
            server.Add(new UADataVariable("ReadThisVariable").ReadFunction(() => new UAAttributeData<int>(
                random.Next(), DateTime.UtcNow.AddMinutes(-10))));

            // Start the server.
            Console.WriteLine("The server is starting...");
            server.Start();

            Console.WriteLine("The server is started.");
            Console.WriteLine();

            // Let the user decide when to stop.
            Console.WriteLine("Press Enter to stop the server...");
            Console.ReadLine();

            // Stop the server.
            Console.WriteLine("The server is stopping...");
            server.Stop();

            Console.WriteLine("The server is stopped.");
        }
    }
}
' This example shows how to create a data variable and implement reading its attribute data using a function.
' You can use any OPC UA client, including our Connectivity Explorer and OpcCmd utility, to connect to the server. 
'
' Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
' OPC client and subscriber examples in VB.NET on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-VBNET .
' Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
' a commercial license in order to use Online Forums, and we reply to every post.

Imports System
Imports OpcLabs.EasyOpc.UA
Imports OpcLabs.EasyOpc.UA.Generic
Imports OpcLabs.EasyOpc.UA.NodeSpace

Namespace _UADataVariable
    Partial Friend Class ReadFunction
        Shared Sub Main1()
            ' Instantiate the server object.
            ' By default, the server will run on endpoint URL "opc.tcp://localhost:48040/".
            Dim server = New EasyUAServer()

            ' Create a data variable, defining its read attribute data (including status code and source timestamp) by a
            ' function.
            ' The type of the data variable (Int32, in this case) is inferred from the type returned by the function.
            Dim random = New Random()
            server.Add(New UADataVariable("ReadThisVariable").ReadFunction(Function() New UAAttributeData(Of Integer)(
                random.Next(), DateTime.UtcNow.AddMinutes(-10))))

            ' Start the server.
            Console.WriteLine("The server is starting...")
            server.Start()

            Console.WriteLine("The server is started.")
            Console.WriteLine()

            ' Let the user decide when to stop.
            Console.WriteLine("Press Enter to stop the server...")
            Console.ReadLine()

            ' Stop the server.
            Console.WriteLine("The server is stopping...")
            server.Stop()

            Console.WriteLine("The server is stopped.")
        End Sub
    End Class
End Namespace

The following example illustrates the use of the ReadFunction method for returning data with a status code generated in your code.

.NET

// This example shows how to create a data variable and implement reading its attribute data using a function, providing
// "Good" or "Bad" status code as needed.
// You can use any OPC UA client, including our Connectivity Explorer and OpcCmd utility, to connect to the server. 
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
// OPC client, server and subscriber examples in C# on GitHub: https://github.com/OPCLabs/Examples-OPCStudio-CSharp .
// Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
// a commercial license in order to use Online Forums, and we reply to every post.

using System;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.Generic;
using OpcLabs.EasyOpc.UA.NodeSpace;

namespace UAServerDocExamples._UADataVariable
{
    partial class ReadFunction
    {
        public static void Unreliable()
        {
            // Instantiate the server object.
            // By default, the server will run on endpoint URL "opc.tcp://localhost:48040/".
            var server = new EasyUAServer();

            // Create a data variable, defining its read attribute data (including status code and source timestamp) by a
            // function. Alternate "Good" and "Bad" status codes randomly.
            // The type of the data variable (Int32, in this case) is inferred from the type returned by the function.
            var random = new Random();
            server.Add(new UADataVariable("ReadThisVariable").ReadFunction(() => new UAAttributeData<int>(
                value: 42,
                (random.Next(2) != 0) ? UACodeBits.Good : UACodeBits.BadNoCommunication,
                DateTime.UtcNow)));

            // Start the server.
            Console.WriteLine("The server is starting...");
            server.Start();

            Console.WriteLine("The server is started.");
            Console.WriteLine();

            // Let the user decide when to stop.
            Console.WriteLine("Press Enter to stop the server...");
            Console.ReadLine();

            // Stop the server.
            Console.WriteLine("The server is stopping...");
            server.Stop();

            Console.WriteLine("The server is stopped.");
        }
    }
}
' This example shows how to create a data variable and implement reading its attribute data using a function, providing
' "Good" or "Bad" status code as needed.
' You can use any OPC UA client, including our Connectivity Explorer and OpcCmd utility, to connect to the server. 
'
' Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
' OPC client and subscriber examples in VB.NET on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-VBNET .
' Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
' a commercial license in order to use Online Forums, and we reply to every post.

Imports System
Imports Newtonsoft.Json.Linq
Imports OpcLabs.EasyOpc.UA
Imports OpcLabs.EasyOpc.UA.Generic
Imports OpcLabs.EasyOpc.UA.NodeSpace

Namespace _UADataVariable
    Partial Friend Class ReadFunction
        Shared Sub Unreliable()
            ' Instantiate the server object.
            ' By default, the server will run on endpoint URL "opc.tcp://localhost:48040/".
            Dim server = New EasyUAServer()

            ' Create a data variable, defining its read attribute data (including status code and source timestamp) by a
            ' function. Alternate "Good" and "Bad" status codes randomly.
            ' The type of the data variable (Int32, in this case) is inferred from the type returned by the function.
            Dim random = New Random()
            server.Add(New UADataVariable("ReadThisVariable").ReadFunction(Function() New UAAttributeData(Of Integer)(
                42,
                If(random.Next(2) <> 0, UACodeBits.Good, UACodeBits.BadNoCommunication),
                DateTime.UtcNow)))

            ' Start the server.
            Console.WriteLine("The server is starting...")
            server.Start()

            Console.WriteLine("The server is started.")
            Console.WriteLine()

            ' Let the user decide when to stop.
            Console.WriteLine("Press Enter to stop the server...")
            Console.ReadLine()

            ' Stop the server.
            Console.WriteLine("The server is stopping...")
            server.Stop()

            Console.WriteLine("The server is stopped.")
        End Sub
    End Class
End Namespace

Handling Requests at Higher Levels

If your OPC server has groups of data variables with basically the same behavior, and organized in such a way that it corresponds to the node space hierarchy, you would probably want to specify the behavior just once, e.g. on the level of the folder that holds all data variables of the same kind. In such case, you cannot use the extension methods for data variable configuration (described above), and need to define the behavior by handling the Read Event, or overriding the OnRead Method, on the higher level - in our example, the level of the folder. The following examples illustrate these approaches.

Example: Examples - Server OPC UA - Implement variable reading on folder level, with an event

Example: Examples - Server OPC UA - Implement variable reading on folder level, with inheritance

Data Type Considerations

See Variable Data Type Considerations.

See Also

Examples - Server OPC Unified Architecture

Reference

Installed Examples - Server Library