open62541pp / open62541pp

C++ wrapper of the open62541 OPC UA library
https://open62541pp.github.io/open62541pp/
Mozilla Public License 2.0
86 stars 30 forks source link

Writing bulk of scalar data to unrelated nodes/async #250

Open pemartin2 opened 3 months ago

pemartin2 commented 3 months ago

Hello @lukasberbuer,

First of all thank you very much for your work on this great lib.

I am playing around with current master version. My goal is to write multiple unrelated scalar data of which I hold the nodeId in a collection (configuration data). I am not happy with doing this synchronously node by node because performance becomes quite slow. Basically what I want is a "synchronous" write of multiple nodes without that blocking but did not find something like that, i.e. write all nodes and then wait for all to be written.

That's why I had a look at writeValueAsync implementation. While the future implementation for readValueAsync is really handed to do bulk operations, I need to handle this on my own in the callback for writeValueAsync because I can't use e.g. a future<void> here.

:opcua::services::writeValueAsync (myClient,
           myNodeId,
            ::opcua::Variant::fromScalar (myData),
            [] (::opcua::StatusCode code) {
                errorHandlingAndEnsuringAllWriteOperationsFinished(code)
            });

I just wanted to ask if I am missing something and if there is a more convenient way to do this with async implementation for my use case than handling this on my own inside the callback? Or am I even missing some synchronous way to achieve my goal?

I am working on master on current master commit d0ffcc7ffbb888640af91cc996f4799f3c158ad0

lukasberbuer commented 3 months ago

Hi @pemartin2,

If you want to write multiple attributes efficiently at once, I would recommend to use the generic services::writeAsync function. There are two overloads: https://github.com/open62541pp/open62541pp/blob/d0ffcc7ffbb888640af91cc996f4799f3c158ad0/include/open62541pp/services/Attribute.h#L159-L185

You have to populate the WriteRequest (or WriteValues) and get a WriteResponse object back. Each write request of the bulk request will get a status code, which can be checked in the callback: https://open62541pp.github.io/open62541pp/classopcua_1_1WriteResponse.html

The async API is currently in development and will be part of the next release, so I would like to get some feedback. Any issues, ideas, problems? Btw, @chandryan is working on the public Result<T> in #207 to encapsulate both the result and the status code, similar to std::expected or Rust's Result type. Please let us know if you like the concept.

lukasberbuer commented 3 months ago

If you prefer synchronous operations, you can use the generic services::write functions. The overloads match the async implementations:

https://github.com/open62541pp/open62541pp/blob/d0ffcc7ffbb888640af91cc996f4799f3c158ad0/include/open62541pp/services/Attribute.h#L147-L157

pemartin2 commented 3 months ago

Hi Lucas. Thank you very much. I'll check as soon as I can find some time. I am a bit busy at the moment.

lukasberbuer commented 2 months ago

Hi @pemartin2, did you test this? Can we close the issue?

pemartin2 commented 2 months ago

Hi @lukasberbuer, sorry for the late reply. I did not have time to test this yet. Hope I will have time to test this within the next week.