Online Forums
Technical support is provided through Support Forums below. Anybody can view them; you need to Register/Login to our site (see links in upper right corner) in order to Post questions. You do not have to be a licensed user of our product.
Please read Rules for forum posts before reporting your issue or asking a question. OPC Labs team is actively monitoring the forums, and replies as soon as possible. Various technical information can also be found in our Knowledge Base. For your convenience, we have also assembled a Frequently Asked Questions page.
Do not use the Contact page for technical issues.
New Version old bug
With State as an integer:
// This example shows how to subscribe to changes of a single monitored item
// and display each change, identifying the different subscription by an
// integer.
type
TIntegerClientEventHandlers = class
procedure OnDataChangeNotification(
ASender: TObject;
sender: OleVariant;
const eventArgs: _EasyUADataChangeNotificationEventArgs);
end;
procedure TIntegerClientEventHandlers.OnDataChangeNotification(
ASender: TObject;
sender: OleVariant;
const eventArgs: _EasyUADataChangeNotificationEventArgs);
var
stateAsInteger: Integer;
begin
// Obtain the integer state we have passed in.
stateAsInteger := eventArgs.Arguments.State;
// Display the data
// Remark: Production code would check eventArgs.Exception before accessing
// eventArgs.AttributeData.
WriteLn(stateAsInteger, ': ', eventArgs.AttributeData.ToString);
end;
class procedure SubscribeMultipleMonitoredItems.StateAsInteger;
var
Arguments: OleVariant;
Client: TEasyUAClient;
ClientEventHandlers: TIntegerClientEventHandlers;
Handle: Cardinal;
HandleArray: OleVariant;
I: Cardinal;
MonitoredItemArguments1, MonitoredItemArguments2, MonitoredItemArguments3:
_EasyUAMonitoredItemArguments;
MonitoringParameters: _UAMonitoringParameters;
begin
// Instantiate the client object and hook events
Client := TEasyUAClient.Create(nil);
ClientEventHandlers := TIntegerClientEventHandlers.Create;
Client.OnDataChangeNotification := ClientEventHandlers.OnDataChangeNotification;
WriteLn('Subscribing...');
MonitoringParameters := CoUAMonitoringParameters.Create;
MonitoringParameters.SamplingInterval := 1000;
MonitoredItemArguments1 := CoEasyUAMonitoredItemArguments.Create;
MonitoredItemArguments1.EndpointDescriptor.UrlString := 'http://opcua.demo-this.com:51211/UA/SampleServer';
MonitoredItemArguments1.NodeDescriptor.NodeId.ExpandedText := 'nsu=http://test.org/UA/Data/;i=10845';
MonitoredItemArguments1.MonitoringParameters := MonitoringParameters;
MonitoredItemArguments1.SetState(1); // An integer we have chosen to identify the subscription
MonitoredItemArguments2 := CoEasyUAMonitoredItemArguments.Create;
MonitoredItemArguments2.EndpointDescriptor.UrlString := 'http://opcua.demo-this.com:51211/UA/SampleServer';
MonitoredItemArguments2.NodeDescriptor.NodeId.ExpandedText := 'nsu=http://test.org/UA/Data/;i=10853';
MonitoredItemArguments2.MonitoringParameters := MonitoringParameters;
MonitoredItemArguments2.SetState(2); // An integer we have chosen to identify the subscription
MonitoredItemArguments3 := CoEasyUAMonitoredItemArguments.Create;
MonitoredItemArguments3.EndpointDescriptor.UrlString := 'http://opcua.demo-this.com:51211/UA/SampleServer';
MonitoredItemArguments3.NodeDescriptor.NodeId.ExpandedText := 'nsu=http://test.org/UA/Data/;i=10855';
MonitoredItemArguments3.MonitoringParameters := MonitoringParameters;
MonitoredItemArguments3.SetState(3); // An integer we have chosen to identify the subscription
Arguments := VarArrayCreate([0, 2], varVariant);
Arguments[0] := MonitoredItemArguments1;
Arguments[1] := MonitoredItemArguments2;
Arguments[2] := MonitoredItemArguments3;
TVarData(HandleArray).VType := varArray or varVariant;
TVarData(HandleArray).VArray := PVarArray(
Client.SubscribeMultipleMonitoredItems(PSafeArray(TVarData(Arguments).VArray)));
for I := VarArrayLowBound(HandleArray, 1) to VarArrayHighBound(HandleArray, 1) do
begin
Handle := Cardinal(HandleArray[I]);
WriteLn('HandleArray[', I, ']: ', Handle);
end;
WriteLn('Processing monitored item changed events for 10 seconds...');
PumpSleep(10*1000);
WriteLn('Unsubscribing...');
Client.UnsubscribeAllMonitoredItems;
WriteLn('Waiting for 5 seconds...');
Sleep(5*1000);
WriteLn('Done...');
end;
With State as an arbitrary Delphi object:
// This example shows how to subscribe to changes of a single monitored item
// and display each change, identifying the different subscription by an
// object.
type
TCustomObject = class
Name: string;
constructor Create(name: string);
end;
constructor TCustomObject.Create(name: string);
begin
Self.Name := name;
end;
type
TObjectClientEventHandlers = class
procedure OnDataChangeNotification(
ASender: TObject;
sender: OleVariant;
const eventArgs: _EasyUADataChangeNotificationEventArgs);
end;
procedure TObjectClientEventHandlers.OnDataChangeNotification(
ASender: TObject;
sender: OleVariant;
const eventArgs: _EasyUADataChangeNotificationEventArgs);
var
stateAsObject: TCustomObject;
begin
// Obtain the custom object we have passed in.
stateAsObject := TCustomObject(INT_PTR(eventArgs.Arguments.State));
// Display the data
// Remark: Production code would check eventArgs.Exception before accessing
// eventArgs.AttributeData.
WriteLn(stateAsObject.Name, ': ', eventArgs.AttributeData.ToString);
end;
class procedure SubscribeMultipleMonitoredItems.StateAsObject;
var
Arguments: OleVariant;
Client: TEasyUAClient;
ClientEventHandlers: TObjectClientEventHandlers;
Handle: Cardinal;
HandleArray: OleVariant;
I: Cardinal;
MonitoredItemArguments1, MonitoredItemArguments2, MonitoredItemArguments3:
_EasyUAMonitoredItemArguments;
MonitoringParameters: _UAMonitoringParameters;
begin
// Instantiate the client object and hook events
Client := TEasyUAClient.Create(nil);
ClientEventHandlers := TObjectClientEventHandlers.Create;
Client.OnDataChangeNotification := ClientEventHandlers.OnDataChangeNotification;
WriteLn('Subscribing...');
MonitoringParameters := CoUAMonitoringParameters.Create;
MonitoringParameters.SamplingInterval := 1000;
MonitoredItemArguments1 := CoEasyUAMonitoredItemArguments.Create;
MonitoredItemArguments1.EndpointDescriptor.UrlString := 'http://opcua.demo-this.com:51211/UA/SampleServer';
MonitoredItemArguments1.NodeDescriptor.NodeId.ExpandedText := 'nsu=http://test.org/UA/Data/;i=10845';
MonitoredItemArguments1.MonitoringParameters := MonitoringParameters;
MonitoredItemArguments1.SetState(INT_PTR(TCustomObject.Create('First'))); // A custom object that corresponds to the subscription
MonitoredItemArguments2 := CoEasyUAMonitoredItemArguments.Create;
MonitoredItemArguments2.EndpointDescriptor.UrlString := 'http://opcua.demo-this.com:51211/UA/SampleServer';
MonitoredItemArguments2.NodeDescriptor.NodeId.ExpandedText := 'nsu=http://test.org/UA/Data/;i=10853';
MonitoredItemArguments2.MonitoringParameters := MonitoringParameters;
MonitoredItemArguments2.SetState(INT_PTR(TCustomObject.Create('Second'))); // A custom object that corresponds to the subscription
MonitoredItemArguments3 := CoEasyUAMonitoredItemArguments.Create;
MonitoredItemArguments3.EndpointDescriptor.UrlString := 'http://opcua.demo-this.com:51211/UA/SampleServer';
MonitoredItemArguments3.NodeDescriptor.NodeId.ExpandedText := 'nsu=http://test.org/UA/Data/;i=10855';
MonitoredItemArguments3.MonitoringParameters := MonitoringParameters;
MonitoredItemArguments3.SetState(INT_PTR(TCustomObject.Create('Third'))); // A custom object that corresponds to the subscription
Arguments := VarArrayCreate([0, 2], varVariant);
Arguments[0] := MonitoredItemArguments1;
Arguments[1] := MonitoredItemArguments2;
Arguments[2] := MonitoredItemArguments3;
TVarData(HandleArray).VType := varArray or varVariant;
TVarData(HandleArray).VArray := PVarArray(
Client.SubscribeMultipleMonitoredItems(PSafeArray(TVarData(Arguments).VArray)));
for I := VarArrayLowBound(HandleArray, 1) to VarArrayHighBound(HandleArray, 1) do
begin
Handle := Cardinal(HandleArray[I]);
WriteLn('HandleArray[', I, ']: ', Handle);
end;
WriteLn('Processing monitored item changed events for 10 seconds...');
PumpSleep(10*1000);
WriteLn('Unsubscribing...');
Client.UnsubscribeAllMonitoredItems;
WriteLn('Waiting for 5 seconds...');
Sleep(5*1000);
WriteLn('Done...');
end;
In the above code snippet, INT_PTR comes from the Windows unit, so you need to add that to your 'uses' list.
In my opinion, non-trivial real-world projects will typically use the latter approach, i.e. with some object being passed as State. The use of other types (integers) usually leads to some kind of value tests and/or switch statements, which is both ugly and inefficient. On the other hand, passing in an object fits well into the OOP scheme of things, as you may already have such an object in your project anyway, and it can have properties and methods that do reasonable things with the data that has arrived, without need to write extra code to find a correspondence between "something" that is incoming in the notification, and the "other thing" you actually need. You'd just pass in "the thing" you need as State, and you will also get it in the notifications (leaving aside the typecasting to and from, which is technical detail only).
Best regards
Please Log in or Create an account to join the conversation.
I need to convert
Olevariant to tobject,tobject to olevariant
Olevariant to int,int to olevariant
I need it because i want test state
Please Log in or Create an account to join the conversation.
Ad 1) As with all errors that occur within a subscription, you should receive an OnDataChangeNotification where Exception is non-null and contains information about the problem.
Ad 2) I will answer later (probably tomorrow) and provide some examples.
Ad 3) Can you please describe your use case? Typically the variable type is fixed and the application knows to expect for a particular node, or you find the type upfront in the app (I can provide some guidance for this too).
Please Log in or Create an account to join the conversation.
1)if i insert an wrong nodedescriptionstring in subscribemultimonitoritems there is a way that subscription is incorrect?
2)how can i insert in setstate a tobject or/and a number?
3)how can i understand variable type in ondatachange?
Thank you very much for tour help
Please Log in or Create an account to join the conversation.
Please Log in or Create an account to join the conversation.
Please Log in or Create an account to join the conversation.
Some relevant piece of it:
- Changes in member names are as follows:
- The IEasyUAClient.MonitoredItemChanged event has been renamed to DataChangeNotification.
- Some overloads of the extension method IEasyUAClient.SubscribeMonitoredItem have been renamed to SubscribeDataChange.
- Some overloads of the extension methods IEasyUAClient.ChangeMonitoredItemSubscription and IEasyUAClient.ChangeMultipleMonitoredItemSubscriptions have been renamed to ChangeDataChangeSubscription and ChangeMultipleDataChangesSubscriptions, respectively.
- The EasyUAMonitoredItemArguments.Callback property has been renamed to DataChangeCallback.
- In .NET, backward compatibility is provided for the most commonly used renamed types and members. This means that if your existing code uses them, you will get a compiler warning recommending you to use a different type or member, but the code will still compile. For the remaining types and members, you need to perform a manual renaming in your code, using the correspondences outlined above. We plan to remove the obsoleted types and members from the product with a version that will come approx. 1 year after the release of this version.
- For COM development, where applicable, the corresponding types and members have been renamed in an identical manner. Backward compatible types and members are not provided for COM development.
The documentation and examples to the affected version are all updated. If you have a preexisting code, you need to change things according to the descriptions in the knowledge base article and the newest doc. In your case:
- Use OnDataChangeNotification instead of OnMonitoredItemChanged.
- Use SubscribeDataChange instead of SubscribeMonitoredItem if possible. Where not possible, use SubscribeMultipleMonitoredItems.
Regards
Please Log in or Create an account to join the conversation.
You will therefore find yourself generally using SubscribeMultipleMonitoredItems instead.
Please Log in or Create an account to join the conversation.
var
client :IEasyUAClient;
begin
Client := TEasyUAClient.Create(nil);
Client.OnDataChangeNotification
Client.OnServerConditionChanged
Client.OnEventNotification
Client.OnMonitoredItemChanged
Client.SubscribeEvent
Client.SubscribeDataChange
Client. SubscribeMultipleMonitoredItems
Client.SubscribeMonitoredItem
end;
I m using Delphi 2010
Please Log in or Create an account to join the conversation.
Please Log in or Create an account to join the conversation.