diff --git a/Project.toml b/Project.toml index 151846f..560268e 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "Open62541" uuid = "e9b70463-8ccb-4e30-a2e2-0d1ec8db6536" authors = ["Martin Kosch and contributors"] -version = "0.2.1" +version = "0.3.0" [deps] CEnum = "fa961155-64e5-5f13-b03f-caf6b980ea82" diff --git a/README.md b/README.md index 4ec8d3a..a099892 100644 --- a/README.md +++ b/README.md @@ -34,12 +34,14 @@ accidental breakage and evolutions of the API have to be expected. Documentation is also a work in progress. ## How to contribute + There is many ways one can contribute to the development of Open62541.jl (in order of increasing complexity): -- Reporting bugs, issues and suggestions on the Github repository. -- Improving the clarity of the existing documentation. -- Adding new tutorials for more advanced functionality. -- Adding/Improving docstrings, especially in the main file of the library src/Open62541.jl. It would be best if these are added automatically in the right spot during the code generation using Clang.jl (see gen/generator.jl). But improvements are welcome also if they are directly done in the src/Open62541.jl (existing contributors can help keeping things aligned). -- Adding improvements to the high-level interface. It would be best to discuss ideas on this topic via the Github repository before embarking on larger changes. + + - Reporting bugs, issues and suggestions on the Github repository. + - Improving the clarity of the existing documentation. + - Adding new tutorials for more advanced functionality. + - Adding/Improving docstrings, especially in the main file of the library src/Open62541.jl. It would be best if these are added automatically in the right spot during the code generation using Clang.jl (see gen/generator.jl). But improvements are welcome also if they are directly done in the src/Open62541.jl (existing contributors can help keeping things aligned). + - Adding improvements to the high-level interface. It would be best to discuss ideas on this topic via the Github repository before embarking on larger changes. ## Installation diff --git a/docs/Project.toml b/docs/Project.toml index 15bd1db..1d429cb 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -4,4 +4,4 @@ Open62541 = "e9b70463-8ccb-4e30-a2e2-0d1ec8db6536" [compat] Documenter = "1" -Open62541 = "0.1, 0.2" +Open62541 = "0.1, 0.2, 0.3" diff --git a/docs/make.jl b/docs/make.jl index 5f836f4..bd4820e 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -23,6 +23,7 @@ makedocs(; "tutorials/combined_variables.md", "tutorials/combined_username_password_login.md", "tutorials/combined_encrypted_un_pw_login.md", + "tutorials/combined_methodnode.md", "tutorials/further_resources.md" ], "Manual" => [ @@ -33,7 +34,7 @@ makedocs(; "manual/client.md" ], "Reference" => ["Low level interface" => "reference_lowlevel.md", - "High level interface" => "reference_highlevel.md"] + "High level interface" => "reference_highlevel.md"] ], warnonly = Documenter.except( :autodocs_block, diff --git a/docs/src/index.md b/docs/src/index.md index 5d7cff8..f79f430 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -1,5 +1,6 @@ # Open62541.jl -Welcome to the documentation of Open62541.jl. + +Welcome to the documentation of Open62541.jl. Open62541.jl is a [Julia](https://julialang.org) package that interfaces with the [open62541](https://www.open62541.org/) library written in C ([source](https://github.com/open62541/open62541)). @@ -20,13 +21,13 @@ At its current development stage the high level interface is implemented for a level interface that wraps all functionality of open62541 is, however, available. !!! warning + Note that Open62541.jl is still under active development and has not reached a maturity that would make it safe to use in a production environment. - + The developers aim to observe [semantic versioning](https://semver.org/), but accidental breakage and evolutions of the API have to be expected. - ## Installation Open62541.jl is registered in Julia's General registry. @@ -40,29 +41,34 @@ Pkg.add("Open62541") ``` ## Structure of the documentation -The documentation has the following structure: -- Tutorials: Provides a few brief instructions that showcase basic functionality. -- Manual: Currently only slightly more than a reference, but intended to be more explanatory than the reference. -- Reference: Low level interface: Contains a list of functions and types that ship with open62541. -- Reference: High level interface: Contains a list of functions and types that constitute the higher level interface generated for Open62541.jl. +The documentation has the following structure: -!!! note - The documentation is still a work in progress. To be concrete, many functions - within src/Open62541.jl are still without docstrings. These are thin wrappers - to functions in open62541 generated through Clang.jl. Therefore, users who - are familiar with open62541 should be aware of the functions; users unfamilar - with open62541 will have to resort to the source code for the time being. + - Tutorials: Provides a few brief instructions that showcase basic functionality. + - Manual: Currently only slightly more than a reference, but intended to be more explanatory than the reference. + - Reference: Low level interface: Contains a list of functions and types that ship with open62541. + - Reference: High level interface: Contains a list of functions and types that constitute the higher level interface generated for Open62541.jl. - Docstrings will be added (pull requests welcome!). +!!! note + +The documentation is still a work in progress. To be concrete, many functions +within src/Open62541.jl are still without docstrings. These are thin wrappers +to functions in open62541 generated through Clang.jl. Therefore, users who +are familiar with open62541 should be aware of the functions; users unfamilar +with open62541 will have to resort to the source code for the time being. + + Docstrings will be added over time (pull requests welcome!). + The docstring situation is better on the handwritten functions contained in the other source files. ## How to contribute + There is many ways one can contribute to the development of Open62541.jl (in order of increasing complexity): -- Reporting bugs, issues and suggestions on the Github repository. -- Improving the clarity of the existing documentation. -- Adding new tutorials for more advanced functionality. -- Adding/Improving docstrings, especially in the main file of the library src/Open62541.jl. It would be best if these are added automatically in the right spot during the code generation using Clang.jl (see gen/generator.jl). But improvements are welcome also if they are directly done in the src/Open62541.jl (existing contributors can help keeping things aligned). -- Adding improvements to the high-level interface. It would be best to discuss ideas on this topic via the Github repository before embarking on larger changes. + + - Reporting bugs, issues and suggestions on the Github repository. + - Improving the clarity of the existing documentation. + - Adding new tutorials for more advanced functionality. + - Adding/Improving docstrings, especially in the main file of the library src/Open62541.jl. It would be best if these are added automatically in the right spot during the code generation using Clang.jl (see gen/generator.jl). But improvements are welcome also if they are directly done in the src/Open62541.jl (existing contributors can help keeping things aligned). + - Adding improvements to the high-level interface. It would be best to discuss ideas on this topic via the Github repository before embarking on larger changes. diff --git a/docs/src/manual/attributegeneration.md b/docs/src/manual/attributegeneration.md index b93a99c..97d4eee 100644 --- a/docs/src/manual/attributegeneration.md +++ b/docs/src/manual/attributegeneration.md @@ -1,7 +1,7 @@ # Attribute generation -This page lists docstrings of functions used for the convenient generation of -node attribute structures. Their main use is when adding nodes to a server through +This page lists docstrings of functions used for the convenient generation of +node attribute structures. Their main use is when adding nodes to a server through client API (see [`JUA_Client_addNode`](@ref)) or the server API (see [`JUA_Server_addNode`](@ref)). ## Convenience functions that allow generating values for specific attributes: @@ -16,6 +16,7 @@ UA_EVENTNOTIFIER ``` ## High level generators for attribute blocks: + ```@docs; canonical = false JUA_DataTypeAttributes JUA_MethodAttributes diff --git a/docs/src/manual/client.md b/docs/src/manual/client.md index 60e65e2..e18b21b 100644 --- a/docs/src/manual/client.md +++ b/docs/src/manual/client.md @@ -70,8 +70,9 @@ UA_Client_writeWriteMaskAttribute ``` ## Asynchronous Client API + ```@autodocs; canonical = false Modules = [Open62541] Order = [:function] Filter = t -> startswith(string(t), "UA_ClientAsync") && !endswith(string(t), "_generate") -``` +``` diff --git a/docs/src/manual/numbertypes.md b/docs/src/manual/numbertypes.md index bbf5016..6bbb36a 100644 --- a/docs/src/manual/numbertypes.md +++ b/docs/src/manual/numbertypes.md @@ -1,29 +1,32 @@ # Supported number types -It is noteworthy that the open62541 library does not support all number types + +It is noteworthy that the open62541 library does not support all number types included within Julia natively. Open62541.jl supports the same number types as its -C counterpart. Julia types that are not supported will throw an exception, rather +C counterpart. Julia types that are not supported will throw an exception, rather than silently performing an automated conversion for you. -If you want to store a Julia type that is not on the list below (for example: -`Float32`, `Complex{Int64}` or `Rational{Bool}`) in an OPC UA server, you should -consciously convert it to a supported number type beforehand. +If you want to store a Julia type that is not on the list below (for example: +`Float32`, `Complex{Int64}` or `Rational{Bool}`) in an OPC UA server, you should +consciously convert it to a supported number type beforehand. -Furthermore `JUA_Client_readValueAttribute(client, nodeid)` will return numbers -in one of the supported formats below. You can specify the conversion to be used -via its typed equivalent if you know a `Float16` value should be returned, you -can call `JUA_Client_readValueAttribute(client, nodeid, Float16)`. This conversion -obviously only works if implemented in Julia. +Furthermore `JUA_Client_readValueAttribute(client, nodeid)` will return numbers +in one of the supported formats below. You can specify the conversion to be used +via its typed equivalent if you know a `Float16` value should be returned, you +can call `JUA_Client_readValueAttribute(client, nodeid, Float16)`. This conversion +obviously only works if implemented in Julia. -Adding other number types is possible, but relies on introducing a custom -datatype. See the [open62541 documentation](https://github.com/open62541/open62541/tree/master/examples/custom_datatype) +Adding other number types is possible, but relies on introducing a custom +datatype. See the [open62541 documentation](https://github.com/open62541/open62541/tree/master/examples/custom_datatype) for details about this. ## Real numbers: + - Boolean: Bool - Integers: Int8, Int16, Int32, Int64, UInt8, UInt16, UInt32, UInt64 - Float: Float32, Float64 - Rational: Rational{Int32}, Rational{UInt32} ## Complex numbers: + - Complex{Float32} - Complex{Float64} diff --git a/docs/src/reference_highlevel.md b/docs/src/reference_highlevel.md index 8944b33..0d2bea7 100644 --- a/docs/src/reference_highlevel.md +++ b/docs/src/reference_highlevel.md @@ -1,9 +1,9 @@ -# Reference: High level interface +# Reference: High level interface -Lists higher level functions that have been introduced to Open62541.jl for -convenience reasons. +Lists higher level functions that have been introduced to Open62541.jl for +convenience reasons. ```@autodocs Modules = [Open62541] Filter = t -> startswith(string(t), "JUA_") -``` +``` diff --git a/docs/src/reference_lowlevel.md b/docs/src/reference_lowlevel.md index 5207d28..3305442 100644 --- a/docs/src/reference_lowlevel.md +++ b/docs/src/reference_lowlevel.md @@ -1,23 +1,25 @@ -# Reference: Low level interface +# Reference: Low level interface Lists types and functions that are part of the open62541 standard interface. ## open62541 types + ```@autodocs Modules = [Open62541] Order = [:type] Filter = t -> startswith(string(t), "UA_") -``` +``` ## Memory allocation and management for open62541 types -These are low level functions allowing to allocate and free (etc.) memory for + +These are low level functions allowing to allocate and free (etc.) memory for open62541 types ("UA_...") on the C-side. ```@autodocs Modules = [Open62541] Order = [:function] Filter = t -> startswith(string(t), "UA_") && any(endswith.(string(t), ["_new", "_init", "_delete", "_clear", "_copy", "_deleteMembers"])) -``` +``` ## Convenience functions for generating strings/bytestrings & associated functions @@ -33,26 +35,27 @@ UA_ByteString_equal ``` ## Generation of (Expanded)NodeIds & associated functions + ```@autodocs Modules = [Open62541] Order = [:function] Filter = t -> startswith(string(t), "UA_NODEID") -``` +``` ```@autodocs Modules = [Open62541] Order = [:function] Filter = t -> startswith(string(t), "UA_EXPANDEDNODEID") -``` +``` ```@docs UA_NodeId_equal -``` +``` ## Attribute generation Functions that allow generating attributes (used in node creation) in a convenient - fashion: +fashion: ```@docs UA_DataTypeAttributes_generate @@ -66,6 +69,7 @@ UA_ViewAttributes_generate ``` Helper functions for readmasks, valueranks, etc.: + ```@docs UA_ACCESSLEVEL UA_EVENTNOTIFIER @@ -81,7 +85,7 @@ UA_WRITEMASK Modules = [Open62541] Order = [:function] Filter = t -> startswith(string(t), "UA_Server_") || startswith(string(t), "UA_ServerConfig") -``` +``` ## Client API @@ -89,7 +93,7 @@ Filter = t -> startswith(string(t), "UA_Server_") || startswith(string(t), "UA_S Modules = [Open62541] Order = [:function] Filter = t -> startswith(string(t), "UA_Client_") -``` +``` ## Asynchronous Client API @@ -97,18 +101,18 @@ Filter = t -> startswith(string(t), "UA_Client_") Modules = [Open62541] Order = [:function] Filter = t -> startswith(string(t), "UA_ClientAsync") && !endswith(string(t), "_generate") -``` +``` ## Callback generation ```@autodocs Modules = [Open62541] Pages = ["callbacks.jl"] -``` +``` ## Miscellaneous ```@docs UA_CreateSubscriptionRequest_default UA_MonitoredItemCreateRequest_default -``` \ No newline at end of file +``` diff --git a/docs/src/tutorials/combined_encrypted_un_pw_login.md b/docs/src/tutorials/combined_encrypted_un_pw_login.md index 6b8d304..788d1fb 100644 --- a/docs/src/tutorials/combined_encrypted_un_pw_login.md +++ b/docs/src/tutorials/combined_encrypted_un_pw_login.md @@ -1,11 +1,12 @@ # Encrypted username/password authentication using basic access control -In this tutorial, we will showcase how authentication using a username and password can be -accomplished using Open62541.jl. Following up from [Username/password authentication using basic access control](@ref) -the server and client will now be configured to use encryption, so that usernames and +In this tutorial, we will showcase how authentication using a username and password can be +accomplished using Open62541.jl. Following up from [Username/password authentication using basic access control](@ref) +the server and client will now be configured to use encryption, so that usernames and passwords are transmitted safely across the network. ## Configuring the server + Here we configure the server to accept a username/password combination. We will also set up encryption and disallow anonymous logins. The code block is commented line by line. @@ -16,26 +17,28 @@ using Open62541 #generate a basic server certificate certificate = UA_ByteString_new() privateKey = UA_ByteString_new() -subject = UA_String_Array_new([UA_String_fromChars("C=DE"), - UA_String_fromChars("O=SampleOrganization"), +subject = UA_String_Array_new([UA_String_fromChars("C=DE"), + UA_String_fromChars("O=SampleOrganization"), UA_String_fromChars("CN=Open62541Server@localhost")]) lenSubject = UA_UInt32(3) -subjectAltName = UA_String_Array_new([UA_String_fromChars("DNS:localhost"), +subjectAltName = UA_String_Array_new([UA_String_fromChars("DNS:localhost"), UA_String_fromChars("URI:urn:open62541.server.application")]) lenSubjectAltName = UA_UInt32(2) kvm = UA_KeyValueMap_new() expiresIn = UA_UInt16(14) -retval0 = UA_KeyValueMap_setScalar(kvm, JUA_QualifiedName(0, "expires-in-days"), Ref(expiresIn), +retval0 = UA_KeyValueMap_setScalar( + kvm, JUA_QualifiedName(0, "expires-in-days"), Ref(expiresIn), UA_TYPES_PTRS[UA_TYPES_UINT16]) -retval1 = UA_CreateCertificate(UA_Log_Stdout_new(UA_LOGLEVEL_FATAL), subject.ptr, lenSubject, - subjectAltName.ptr, lenSubjectAltName, UA_CERTIFICATEFORMAT_DER, kvm, privateKey, +retval1 = UA_CreateCertificate( + UA_Log_Stdout_new(UA_LOGLEVEL_FATAL), subject.ptr, lenSubject, + subjectAltName.ptr, lenSubjectAltName, UA_CERTIFICATEFORMAT_DER, kvm, privateKey, certificate) #configure the open62541 server; we choose a default config on port 4840. server = JUA_Server() config = JUA_ServerConfig(server) JUA_ServerConfig_setDefault(config) -JUA_ServerConfig_addSecurityPolicyBasic256Sha256(config, certificate, +JUA_ServerConfig_addSecurityPolicyBasic256Sha256(config, certificate, privateKey) JUA_ServerConfig_addAllEndpoints(config) config.securityPolicyNoneDiscoveryOnly = true @@ -47,8 +50,9 @@ JUA_Server_runUntilInterrupt(server) #start the server, shut it down by pressing ``` ## Using the client -Start a new Julia session and run the program shown below. Once you are finished, -you may want to return to the first Julia session and stop the server (press + +Start a new Julia session and run the program shown below. Once you are finished, +you may want to return to the first Julia session and stop the server (press CTRL + C repeatedly). Again, the code block is commented line by line. ```julia @@ -61,18 +65,19 @@ config = UA_Client_getConfig(client) #generate a client certificate certificate = UA_ByteString_new() privateKey = UA_ByteString_new() -subject = UA_String_Array_new([UA_String_fromChars("C=DE"), - UA_String_fromChars("O=SampleOrganization"), +subject = UA_String_Array_new([UA_String_fromChars("C=DE"), + UA_String_fromChars("O=SampleOrganization"), UA_String_fromChars("CN=Open62541Client@localhost")]) lenSubject = UA_UInt32(3) -subjectAltName = UA_String_Array_new([UA_String_fromChars("DNS:localhost"), +subjectAltName = UA_String_Array_new([UA_String_fromChars("DNS:localhost"), UA_String_fromChars("URI:urn:open62541.client.application")]) lenSubjectAltName = UA_UInt32(2) kvm = UA_KeyValueMap_new() expiresIn = UA_UInt16(14) -UA_KeyValueMap_setScalar(kvm, JUA_QualifiedName(0, "expires-in-days"), Ref(expiresIn), UA_TYPES_PTRS[UA_TYPES_UINT16]) -UA_CreateCertificate(UA_Log_Stdout_new(UA_LOGLEVEL_FATAL), subject.ptr, lenSubject, - subjectAltName.ptr, lenSubjectAltName, UA_CERTIFICATEFORMAT_DER, kvm, privateKey, +UA_KeyValueMap_setScalar(kvm, JUA_QualifiedName(0, "expires-in-days"), + Ref(expiresIn), UA_TYPES_PTRS[UA_TYPES_UINT16]) +UA_CreateCertificate(UA_Log_Stdout_new(UA_LOGLEVEL_FATAL), subject.ptr, lenSubject, + subjectAltName.ptr, lenSubjectAltName, UA_CERTIFICATEFORMAT_DER, kvm, privateKey, certificate) revocationList = UA_ByteString_new() revocationListSize = 0 @@ -95,9 +100,9 @@ JUA_Client_disconnect(client) #disconnect #now let us try to connect with the wrong login credentials. retval2 = JUA_Client_connectUsername(client, - "opc.tcp://localhost:4840", - "PeterParker", - "IamSpiderman") #try connecting using a wrong username/password + "opc.tcp://localhost:4840", + "PeterParker", + "IamSpiderman") #try connecting using a wrong username/password #now let us try connecting as an anonymous user retval3 = JUA_Client_connect(client, "opc.tcp://localhost:4840") @@ -106,14 +111,15 @@ retval3 = JUA_Client_connect(client, "opc.tcp://localhost:4840") client = JUA_Client() JUA_ClientConfig_setDefault(JUA_ClientConfig(client)) retval4 = JUA_Client_connectUsername(client, - "opc.tcp://localhost:4840", - "BruceWayne", - "IamBatman") #try connecting using a wrong username/password + "opc.tcp://localhost:4840", + "BruceWayne", + "IamBatman") #try connecting using a wrong username/password ``` + `retval1` should be `UA_STATUSCODE_GOOD` (= 0) indicating that authentication was sucessful, -whereas `retval2` and `retval3` should be `UA_STATUSCODE_BADUSERACCESSDENIED` (= 2149515264) -indicating that the second login and third login attempt were rejected (wrong user -credentials). The fourth login attempt returns `retval4`, which should be -`UA_STATUSCODE_BADIDENTITYTOKENREJECTED` (= 2149646336), because we tried using an -unencrypted connection to a server that demands an encrypted one. Therefore, the server has +whereas `retval2` and `retval3` should be `UA_STATUSCODE_BADUSERACCESSDENIED` (= 2149515264) +indicating that the second login and third login attempt were rejected (wrong user +credentials). The fourth login attempt returns `retval4`, which should be +`UA_STATUSCODE_BADIDENTITYTOKENREJECTED` (= 2149646336), because we tried using an +unencrypted connection to a server that demands an encrypted one. Therefore, the server has rejected the identity token. diff --git a/docs/src/tutorials/combined_methodnode.md b/docs/src/tutorials/combined_methodnode.md new file mode 100644 index 0000000..e32164b --- /dev/null +++ b/docs/src/tutorials/combined_methodnode.md @@ -0,0 +1,237 @@ +# Simple Method Nodes + +In this tutorial, we will add method nodes to a server. A method node takes input(s), calls +a function (or method) on the server side and calculates output(s) based on the input(s). We +will then proceed to call the new method nodes using the client API. + +In Open62541.jl there is a convenient high level interface for this that simplifies these +operations, at the price of some flexibility when defining the methods. In the +final section of this tutorial, we will show how more flexible methods can be defined and +used by employing the low level interface. + +## Configuring the server + +Here we configure the server to accept a username/password combination. We will also disallow +anonymous logins. The code block is commented line by line. + +```julia +using Open62541 +using Pkg.BinaryPlatforms + +#configure the open62541 server; we choose a default config on port 4840. +server = JUA_Server() +config = JUA_ServerConfig(server) +JUA_ServerConfig_setDefault(config) + +#define Julia functions that will be used within the method nodes +#A one input, one output method. Classical "Hello World!". +function simple_one_in_one_out(name) + assembledstring = "Hello " * name * "." + return assembledstring +end + +#A two input, two output method. It will say hello and square a number. +function simple_two_in_two_out(name, number) + out1 = "Hello " * name * "." + out2 = number * number + return (out1, out2) +end + +#prepare method attributes +attr1 = JUA_MethodAttributes(description = "Simple One in One Out", + displayname = "Simple One in One Out", + executable = true, #makes the method node executable via server API + userexecutable = true) #makes the method executable via client API +attr2 = JUA_MethodAttributes(description = "Simple Two in Two Out - Mixed Types", + displayname = "Simple Two in Two Out - Mixed Types", + executable = true, + userexecutable = true) + +#define nodeids for the two methods: +methodid1 = JUA_NodeId(1, 62541) +methodid2 = JUA_NodeId(1, 62542) + +#parent and reference nodeid: +parentnodeid = JUA_NodeId(0, UA_NS0ID_OBJECTSFOLDER) #method nodes will appear in "Objects" +parentreferencenodeid = JUA_NodeId(0, UA_NS0ID_HASCOMPONENT) + +#define browsenames for the two method nodes +browsename1 = JUA_QualifiedName(1, "Simple One in One Out") +browsename2 = JUA_QualifiedName(1, "Simple Two in Two Out") + +#prepare method callbacks +#the following code is necessary, because Apple silicon does not currently support closures +#within @cfunction, see ?@cfunction. If you are on Windows/*nix, you can just use the +#UA_MethodCallback_wrap(...) part; on Apple Silicon, the longer and more cumbersome part is +#used instead. +@static if !Sys.isapple() || platform_key_abi().tags["arch"] != "aarch64" + m1 = UA_MethodCallback_generate(UA_MethodCallback_wrap(simple_one_in_one_out)) + m2 = UA_MethodCallback_generate(UA_MethodCallback_wrap(simple_two_in_two_out)) +else #we are on Apple Silicon and can't use a closure in @cfunction, have to do more work. + function c1(server, sessionId, sessionHandle, methodId, methodContext, objectId, + objectContext, inputSize, input, outputSize, output) + arr_input = UA_Array(input, Int64(inputSize)) + arr_output = UA_Array(output, Int64(outputSize)) + input_julia = Open62541.__get_juliavalues_from_variant.(arr_input, Any) + output_julia = simple_one_in_one_out(input_julia...) + if !isa(output_julia, Tuple) + output_julia = (output_julia,) + end + for i in 1:outputSize + j = JUA_Variant(output_julia[i]) + UA_Variant_copy(Open62541.Jpointer(j), arr_output[i]) + end + return UA_STATUSCODE_GOOD + end + function c2(server, sessionId, sessionHandle, methodId, methodContext, objectId, + objectContext, inputSize, input, outputSize, output) + arr_input = UA_Array(input, Int64(inputSize)) + arr_output = UA_Array(output, Int64(outputSize)) + input_julia = Open62541.__get_juliavalues_from_variant.(arr_input, Any) + output_julia = simple_two_in_two_out(input_julia...) + if !isa(output_julia, Tuple) + output_julia = (output_julia,) + end + for i in 1:outputSize + j = JUA_Variant(output_julia[i]) + UA_Variant_copy(Open62541.Jpointer(j), arr_output[i]) + end + return UA_STATUSCODE_GOOD + end + m1 = @cfunction(c1, UA_StatusCode, + (Ptr{UA_Server}, Ptr{UA_NodeId}, Ptr{Cvoid}, + Ptr{UA_NodeId}, Ptr{Cvoid}, Ptr{UA_NodeId}, Ptr{Cvoid}, + Csize_t, Ptr{UA_Variant}, Csize_t, Ptr{UA_Variant})) + m2 = @cfunction(c2, UA_StatusCode, + (Ptr{UA_Server}, Ptr{UA_NodeId}, Ptr{Cvoid}, + Ptr{UA_NodeId}, Ptr{Cvoid}, Ptr{UA_NodeId}, Ptr{Cvoid}, + Csize_t, Ptr{UA_Variant}, Csize_t, Ptr{UA_Variant})) +end + +#create example input and output arguments +oneinputarg = JUA_Argument("examplestring", name = "One input", description = "One input") +j1 = JUA_Argument("examplestring", name = "Name", description = "Number") +j2 = JUA_Argument(25, name = "Number", description = "Number") +twoinputarg = [j1, j2] + +oneoutputarg = JUA_Argument( + "examplestring", name = "One output", description = "One output") +j3 = JUA_Argument("examplestring", name = "Name", description = "Name") +j4 = JUA_Argument(25, name = "Number", description = "Number") +twooutputarg = [j3, j4] + +#Add the method nodes to the server +retval1 = JUA_Server_addNode(server, methodid1, parentnodeid, parentreferencenodeid, + browsename1, attr1, m1, oneinputarg, oneoutputarg, + JUA_NodeId(), JUA_NodeId()) +retval2 = JUA_Server_addNode(server, methodid2, parentnodeid, parentreferencenodeid, + browsename2, attr2, m2, twoinputarg, twooutputarg, + JUA_NodeId(), JUA_NodeId()) + +#For testing purposes, let's call the methods using the Server API. The more common use case, +#that is calling the method node on a remote server via the Client API is shown below. +testinput1 = "Peter" +testinput2 = ("Claudia", 25) +res1 = JUA_Server_call(server, parentnodeid, methodid1, testinput1) # "Hello Peter." +res2 = JUA_Server_call(server, parentnodeid, methodid2, testinput2) # ("Hello Claudia.", 625) + +#start the server, shut it down by pressing CTRL+C repeatedly once you are finished with it. +JUA_Server_runUntilInterrupt(server) +``` + +You can verify that the server has been correctly configured using, for example, a graphical +client, such as [UA Expert](https://www.unified-automation.com/products/development-tools/uaexpert.html). + +In the following, we will access the server by calling the newly added method nodes through +the client API. + +## Method calling using client API + +In the following, we use the client API to call the newly established method nodes on the +server. In order to do so, start a new Julia session and run the program shown below. +Once you are finished, you may want to return to the first Julia session and stop the server +(press CTRL + C repeatedly). + +```julia +using Open62541 + +#initiate client, configure it and connect to server +client = JUA_Client() +config = JUA_ClientConfig(client) +JUA_ClientConfig_setDefault(config) +JUA_Client_connect(client, "opc.tcp://localhost:4840") + +#re-define methodids and parentnodeid; remember, we are in a new Julia session. +methodid1 = JUA_NodeId(1, 62541) +methodid2 = JUA_NodeId(1, 62542) +parentnodeid = JUA_NodeId(0, UA_NS0ID_OBJECTSFOLDER) + +#Define the input arguments +one_input = "Peter" +two_inputs = ("Claudia", 25) + +#Call the method nodes +response1 = JUA_Client_call(client, parentnodeid, methodid1, one_input) +response2 = JUA_Client_call(client, parentnodeid, methodid2, two_inputs) + +JUA_Client_disconnect(client) #disconnect +``` + +`response1` should be a string "Hello Peter.", whereas `response2` should be the tuple +`("Hello Claudia.", 625)`. + +## More flexibility in method definitions + +When configuring the server, expect for the case of Apple Silicon (see server section above), +we have employed the high level functions `UA_MethodCallback_wrap` and `UA_MethodCallback_generate`. +The former assumes that the output of the method your are calling solely depends on the user +inputs provided, but *not* on the state of the server, the session id, etc. + +The Apple Silicon part of the server section above details how methods with more flexibility +can be defined (which is more cumbersome, because the lower level interface is used). It is +repeated below with more explanations. + +```julia +using Open62541 + +#Define a more flexible method where one can also access server state, session id, etc. +#The function signature expected is: +#ret::UA_StatusCode = c2(server::Ptr{UA_Server}, sessionId::Ptr{UA_NodeId}, +# sessionHandle::Ptr{Cvoid}, methodId::Ptr{UA_NodeId}, methodContext::Ptr{Cvoid}, +# objectId::Ptr{UA_NodeId}, objectContext::Ptr{Cvoid}, inputSize::Csize_t, +# input::Ptr{UA_Variant}, outputSize::Csize_t, output::Ptr{UA_Variant})) + +function c2(server, sessionId, sessionHandle, methodId, methodContext, objectId, + objectContext, inputSize, input, outputSize, output) + #define array wrappers for easier access of the corresponding memory + arr_input = UA_Array(input, Int64(inputSize)) + arr_output = UA_Array(output, Int64(outputSize)) + + #get input values in the form of a Julia tuple. + input_julia = Open62541.__get_juliavalues_from_variant.(arr_input, Any) + + #prepare outputs + output_julia = ... #whatever you want to do with all the input arguments + + #wraps singular output into tuple to process below. + if !isa(output_julia, Tuple) + output_julia = (output_julia,) + end + + #copy Julia outputs into the memory where open62541 expects the results to be. + for i in 1:outputSize + j = JUA_Variant(output_julia[i]) + UA_Variant_copy(Open62541.Jpointer(j), arr_output[i]) + end + + #return a statuscode; obviously, might want to do some error catching if things don't work. + return UA_STATUSCODE_GOOD +end + +#create Ptr{Cvoid} expected when adding the method node to the server (if *not* on Apple +#Silicon, this part can also be done with UA_MethodCallback_generate) +m2 = @cfunction(c2, UA_StatusCode, + (Ptr{UA_Server}, Ptr{UA_NodeId}, Ptr{Cvoid}, + Ptr{UA_NodeId}, Ptr{Cvoid}, Ptr{UA_NodeId}, Ptr{Cvoid}, + Csize_t, Ptr{UA_Variant}, Csize_t, Ptr{UA_Variant})) +``` diff --git a/docs/src/tutorials/combined_username_password_login.md b/docs/src/tutorials/combined_username_password_login.md index eb87217..d41660f 100644 --- a/docs/src/tutorials/combined_username_password_login.md +++ b/docs/src/tutorials/combined_username_password_login.md @@ -4,12 +4,14 @@ In this tutorial, we will showcase how authentication using a username and passw (rather than an anonymous user) can be accomplished using Open62541.jl. !!! warning - Note that in this basic configuration the login credentials are transmitted unencrypted - over the network, which is obviously *not recommended* when network traffic is + + Note that in this basic configuration the login credentials are transmitted unencrypted + over the network, which is obviously *not recommended* when network traffic is potentially exposed to unwanted listeners. ## Configuring the server -Here we configure the server to accept a username/password combination. We will also disallow + +Here we configure the server to accept a username/password combination. We will also disallow anonymous logins. The code block is commented line by line. ```julia @@ -27,8 +29,9 @@ JUA_Server_runUntilInterrupt(server) #start the server, shut it down by pressing ``` ## Using the client -Start a new Julia session and run the program shown below. Once you are finished, -you may want to return to the first Julia session and stop the server (press + +Start a new Julia session and run the program shown below. Once you are finished, +you may want to return to the first Julia session and stop the server (press CTRL + C repeatedly). ```julia @@ -41,19 +44,20 @@ config.allowNonePolicyPassword = true #allow logging in with username/password o JUA_ClientConfig_setDefault(config) retval1 = JUA_Client_connectUsername(client, - "opc.tcp://localhost:4840", - "BruceWayne", - "IamBatman") #connect using the username and password + "opc.tcp://localhost:4840", + "BruceWayne", + "IamBatman") #connect using the username and password JUA_Client_disconnect(client) #disconnect retval2 = JUA_Client_connectUsername(client, - "opc.tcp://localhost:4840", - "PeterParker", - "IamSpiderman") #try connecting using a wrong username/password + "opc.tcp://localhost:4840", + "PeterParker", + "IamSpiderman") #try connecting using a wrong username/password JUA_Client_disconnect(client) #disconnect ``` + `retval1` should be `UA_STATUSCODE_GOOD` (= 0) indicating that authentication was sucessful, -whereas `retval2` should be `UA_STATUSCODE_BADUSERACCESSDENIED` (= 2149515264) indicating +whereas `retval2` should be `UA_STATUSCODE_BADUSERACCESSDENIED` (= 2149515264) indicating that the second login attempt was rejected. diff --git a/docs/src/tutorials/combined_variables.md b/docs/src/tutorials/combined_variables.md index f1f7c19..746e99b 100644 --- a/docs/src/tutorials/combined_variables.md +++ b/docs/src/tutorials/combined_variables.md @@ -1,11 +1,12 @@ # Adding and reading/writing variables -In this tutorial, we will add three variables to an open62541 server. The first -variable will contain a floating point number, the second an array of floating +In this tutorial, we will add three variables to an open62541 server. The first +variable will contain a floating point number, the second an array of floating point numbers and the third will be an array of two strings. ## Configuring the server -This will detail how to add the variables mentioned above to the server. The + +This will detail how to add the variables mentioned above to the server. The code block is commented line by line. ```julia @@ -58,15 +59,15 @@ browsename3 = JUA_QualifiedName(1, name3) #Add the variables to the server retval1 = JUA_Server_addNode(server, id1, parentnodeid, - parentreferencenodeid, browsename1, attr1, nodecontext, outnewnodeid, + parentreferencenodeid, browsename1, attr1, nodecontext, outnewnodeid, typedefinition) retval2 = JUA_Server_addNode(server, id2, parentnodeid, - parentreferencenodeid, browsename2, attr2, nodecontext, outnewnodeid, + parentreferencenodeid, browsename2, attr2, nodecontext, outnewnodeid, typedefinition) retval3 = JUA_Server_addNode(server, id3, parentnodeid, - parentreferencenodeid, browsename3, attr3, nodecontext, outnewnodeid, + parentreferencenodeid, browsename3, attr3, nodecontext, outnewnodeid, typedefinition) #retval1-3 should all be UA_STATUSCODE_GOOD (== 0) @@ -77,8 +78,9 @@ JUA_Server_runUntilInterrupt(server) ``` ## Using the client -Start a new Julia session and run the program shown below. Once you are finished, -you may want to return to the first Julia session and stop the server (press + +Start a new Julia session and run the program shown below. Once you are finished, +you may want to return to the first Julia session and stop the server (press CTRL + C repeatedly). ```julia @@ -113,14 +115,14 @@ retval2 = JUA_Client_writeValueAttribute(client, id2, new2) retval3 = JUA_Client_writeValueAttribute(client, id3, new3) ``` -Inspecting the return values (`retval1,2,3`) and the log and error messages in the -terminal (both server and client), you will see that writing `new2` to `id2` -failed with the statuscode "BadTypeMismatch" (`retval2`). +Inspecting the return values (`retval1,2,3`) and the log and error messages in the +terminal (both server and client), you will see that writing `new2` to `id2` +failed with the statuscode "BadTypeMismatch" (`retval2`). -This is because in open62541 arrays are statically sized, both in terms of the -number of dimensions, as well as the number of elements along each dimension. -In order for this to work, one first has to specify the new array dimensions -(and the write mask property of the variable has to allow altering this value; +This is because in open62541 arrays are statically sized, both in terms of the +number of dimensions, as well as the number of elements along each dimension. +In order for this to work, one first has to specify the new array dimensions +(and the write mask property of the variable has to allow altering this value; see the server code above!). ```julia @@ -132,10 +134,10 @@ retval5 = JUA_Client_writeValueAttribute(client, id2, new2) JUA_Client_disconnect(client) ``` -Note that changing the dimensionality of the array **additionally** requires -setting the `valuerank` attribute either to `UA_VALUERANK_ONE_OR_MORE_DIMENSIONS` -when defining the variable attributes in the server setup code above, or, one -can use `UA_Client_writeValueRankAttribute` (and the writemask of the variable - attributes has to allow changing the valuerank property) to first change the - valuerank of the variable, before proceeding to change the array dimensions and - then finally setting the variable. +Note that changing the dimensionality of the array **additionally** requires +setting the `valuerank` attribute either to `UA_VALUERANK_ONE_OR_MORE_DIMENSIONS` +when defining the variable attributes in the server setup code above, or, one +can use `UA_Client_writeValueRankAttribute` (and the writemask of the variable +attributes has to allow changing the valuerank property) to first change the +valuerank of the variable, before proceeding to change the array dimensions and +then finally setting the variable. diff --git a/docs/src/tutorials/further_resources.md b/docs/src/tutorials/further_resources.md index 125776f..67b3b03 100644 --- a/docs/src/tutorials/further_resources.md +++ b/docs/src/tutorials/further_resources.md @@ -1,18 +1,22 @@ -# Further resources -The tutorials and documentation currently included with Open62541.jl is very slim -(pull request welcome!). This will be gradually improved over time. Meanwhile, it -is important to realize that other resources exist that can be helpful in answering -questions. +# Further resources + +The tutorials and documentation currently included with Open62541.jl is very slim +(pull request welcome!). This will be gradually improved over time. Meanwhile, it +is important to realize that other resources exist that can be helpful in answering +questions. ## Tutorials in the open62541 documentation -The [tutorials of the open62541 C-library](https://www.open62541.org/doc/master/tutorials.html), -as well as its documentation, are a good starting point. While the code in these -tutorials is of course written in C, many of the function names and approaches + +The [tutorials of the open62541 C-library](https://www.open62541.org/doc/master/tutorials.html), +as well as its documentation, are a good starting point. While the code in these +tutorials is of course written in C, many of the function names and approaches directly transfer over to Open62541.jl and are thus very useful to know. ## Examples in the open62541 source repository on Github + The [examples](https://github.com/open62541/open62541/tree/master/examples) provided in Github repository of the open62541 C-library can also be instructive. Many of the tests of the Julia library have been adapted from examples found in this folder, so it is useful to compare the two codes against each other. ## Tests in Open62541.jl -Code changes implemented in Open62541.jl are continuously tested against a growing + +Code changes implemented in Open62541.jl are continuously tested against a growing [set of tests](https://github.com/martinkosch/Open62541.jl/tree/main/test). In the absence of more step-by-step guidance, the code for these test sets can be instructive. diff --git a/gen/callbacks_base.jl b/gen/callbacks_base.jl index 2d1b163..b4a58a7 100644 --- a/gen/callbacks_base.jl +++ b/gen/callbacks_base.jl @@ -79,11 +79,17 @@ creates a `UA_MethodCallback` that can be attached to a method node using `UA_Server_addMethodNode`. `f` must be a Julia function with the following signature: + ``` f(server::Ptr{UA_Server}, sessionId::Ptr{UA_NodeId}), sessionContext::Ptr{Cvoid}`, methodId::Ptr{UA_NodeId}, methodContext::Ptr{Cvoid}, objectId::Ptr{UA_NodeId}, objectContext::Ptr{Cvoid}, inputSize::Csize_t, input::Ptr{UA_Variant}, outputSize::Csize_t, output::Ptr{UA_Variant})::UA_StatusCode +``` + +If the output of `f` only depends on the inputs, but not on any session state variables, +consider using [`UA_MethodCallback_wrap`](@ref). + """ function UA_MethodCallback_generate(f::Function) argtuple = (Ptr{UA_Server}, Ptr{UA_NodeId}, Ptr{Cvoid}, Ptr{UA_NodeId}, @@ -104,6 +110,59 @@ function UA_MethodCallback_generate(f::Function) end end +""" +``` +UA_MethodCallback_wrap(f::Function) +``` + +wraps a simple Julia function that operates on inputs into the correct format to be supplied +to `UA_MethodCallback_generate`. + +`f` must be a Julia function with the following signature: + +``` +f(input1::Any, input2::Any, input3::Any, ...) -> output::Union{Any, Tuple{Any, ...}} +``` + +where `Any` means that in principle any type is allowed. However, since Open62541 is based +on C the corresponding method node is *always* configured to only work with a specific +combination of input types. + +If larger flexibility is needed than just working on the inputs given to a method node, see +`UA_MethodCallback_generate`. + +See also: + +[`UA_MethodCallback_generate`](@ref) + +[`JUA_Argument`](@ref) + +[`JUA_Server_addNode`](@ref) + +Example: + +``` +function simple_hello(name, adjective) + assembledstring = "Hello "*name*", you are "*adjective + return assembledstring +end +``` + +which can be attached to a a method node that expects a function that takes two strings as +inputs and one string as output. +""" +function UA_MethodCallback_wrap(fsimple) + function (server, sessionId, sessionHandle, methodId, methodContext, objectId, + objectContext, inputSize, input, outputSize, output) + arr = UA_Array(input, Int64(inputSize)) + input_julia = Open62541.__get_juliavalues_from_variant.(arr, Any) + output_julia = fsimple(input_julia...) + j = JUA_Variant(output_julia) + UA_Variant_copy(Jpointer(j), output) + return UA_STATUSCODE_GOOD + end +end + """ ``` UA_ValueCallback_onRead_generate(f::Function) @@ -284,7 +343,6 @@ function UA_ClientCallback_generate(f::Function) end end - """ ``` UA_ClientAsyncServiceCallback_generate(f::Function) @@ -325,7 +383,8 @@ function UA_ClientAsyncReadCallback_generate(f::Function) ret = Base.return_types(f, argtuple) if length(methods(f)) == 1 && hasmethod(f, argtuple) && !isempty(ret) && ret[1] == returntype - callback = @cfunction($f, Nothing, (Ptr{UA_Client}, Ptr{Cvoid}, UInt32, Ptr{UA_ReadResponse})) + callback = @cfunction($f, Nothing, + (Ptr{UA_Client}, Ptr{Cvoid}, UInt32, Ptr{UA_ReadResponse})) return callback else err = CallbackGeneratorArgumentError(f, argtuple, returntype) @@ -349,7 +408,8 @@ function UA_ClientAsyncWriteCallback_generate(f::Function) ret = Base.return_types(f, argtuple) if length(methods(f)) == 1 && hasmethod(f, argtuple) && !isempty(ret) && ret[1] == returntype - callback = @cfunction($f, Nothing, (Ptr{UA_Client}, Ptr{Cvoid}, UInt32, Ptr{UA_WriteResponse})) + callback = @cfunction($f, Nothing, + (Ptr{UA_Client}, Ptr{Cvoid}, UInt32, Ptr{UA_WriteResponse})) return callback else err = CallbackGeneratorArgumentError(f, argtuple, returntype) @@ -373,7 +433,8 @@ function UA_ClientAsyncBrowseCallback_generate(f::Function) ret = Base.return_types(f, argtuple) if length(methods(f)) == 1 && hasmethod(f, argtuple) && !isempty(ret) && ret[1] == returntype - callback = @cfunction($f, Nothing, (Ptr{UA_Client}, Ptr{Cvoid}, UInt32, Ptr{UA_BrowseResponse})) + callback = @cfunction($f, Nothing, + (Ptr{UA_Client}, Ptr{Cvoid}, UInt32, Ptr{UA_BrowseResponse})) return callback else err = CallbackGeneratorArgumentError(f, argtuple, returntype) @@ -397,7 +458,8 @@ function UA_ClientAsyncAddNodesCallback_generate(f::Function) ret = Base.return_types(f, argtuple) if length(methods(f)) == 1 && hasmethod(f, argtuple) && !isempty(ret) && ret[1] == returntype - callback = @cfunction($f, Nothing, (Ptr{UA_Client}, Ptr{Cvoid}, UInt32, Ptr{UA_AddNodesResponse})) + callback = @cfunction($f, Nothing, + (Ptr{UA_Client}, Ptr{Cvoid}, UInt32, Ptr{UA_AddNodesResponse})) return callback else err = CallbackGeneratorArgumentError(f, argtuple, returntype) @@ -421,7 +483,8 @@ function UA_ClientAsyncCallCallback_generate(f::Function) ret = Base.return_types(f, argtuple) if length(methods(f)) == 1 && hasmethod(f, argtuple) && !isempty(ret) && ret[1] == returntype - callback = @cfunction($f, Nothing, (Ptr{UA_Client}, Ptr{Cvoid}, UInt32, Ptr{UA_CallResponse})) + callback = @cfunction($f, Nothing, + (Ptr{UA_Client}, Ptr{Cvoid}, UInt32, Ptr{UA_CallResponse})) return callback else err = CallbackGeneratorArgumentError(f, argtuple, returntype) diff --git a/gen/callbacks_generator.jl b/gen/callbacks_generator.jl index 06f18fe..0f27e26 100644 --- a/gen/callbacks_generator.jl +++ b/gen/callbacks_generator.jl @@ -63,22 +63,22 @@ f(client::Ptr{UA_Client}, userdata::Ptr{Cvoid}, requestid::UA_UInt32, ``` \"\"\"\n" global addedString = addedString * docstring * - "function $(fun_name)(f) - argtuple = (Ptr{UA_Client}, Ptr{Cvoid}, UA_UInt32, UA_StatusCode, - $attr_type) - returntype = Nothing - ret = Base.return_types(f, argtuple) - if length(methods(f)) == 1 && hasmethod(f, argtuple) && !isempty(ret) && ret[1] == returntype - callback = @cfunction(\$f, Cvoid, - (Ptr{UA_Client}, Ptr{Cvoid}, UA_UInt32, UA_StatusCode, $attr_type)) - return callback - else - err = CallbackGeneratorArgumentError(f, argtuple, returntype) - throw(err) - end - end + "function $(fun_name)(f) + argtuple = (Ptr{UA_Client}, Ptr{Cvoid}, UA_UInt32, UA_StatusCode, + $attr_type) + returntype = Nothing + ret = Base.return_types(f, argtuple) + if length(methods(f)) == 1 && hasmethod(f, argtuple) && !isempty(ret) && ret[1] == returntype + callback = @cfunction(\$f, Cvoid, + (Ptr{UA_Client}, Ptr{Cvoid}, UA_UInt32, UA_StatusCode, $attr_type)) + return callback + else + err = CallbackGeneratorArgumentError(f, argtuple, returntype) + throw(err) + end + end - " + " end write(f, orig_content * addedString) close(f) diff --git a/gen/docstrings_types.jl b/gen/docstrings_types.jl index a11a9be..d2902e2 100644 --- a/gen/docstrings_types.jl +++ b/gen/docstrings_types.jl @@ -2,8 +2,7 @@ standard_type_docstring = "\"\"\"\n\$(TYPEDEF)\nFields:\n\$(TYPEDFIELDS)\n\"\"\" docstrings_types_ignore_keywords = ["_", "static", "aa"] #types for which we don't make a docstring, because they are normally not to be accessed by a user #union type types that just have "data" fields (for which we need to write our own docstrings) -docstrings_types_special = [ - "UA_NodeId" "\$(TYPEDEF)\n\nFields:\n\n- `nameSpaceIndex`\n\n- `identifierType`\n\n- `identifier`\n"; +docstrings_types_special = ["UA_NodeId" "\$(TYPEDEF)\n\nFields:\n\n- `nameSpaceIndex`\n\n- `identifierType`\n\n- `identifier`\n"; "UA_DataTypeMember" "\n\$(TYPEDEF)\n\nFields:\n\n- `memberName`\n\n- `memberType`\n- `padding`\n- `isArray`\n- `isOptional`\n" "UA_DataType" "\n\$(TYPEDEF)\n\nFields:\n\n- `typeName`\n\n- `typeId`\n\n- `binaryEncodingId`\n\n- `memSize`\n\n- `typeKind`\n\n- `pointerFree`\n\n- `overlayable`\n\n- `membersSize`\n\n- `members`\n" "UA_ValueBackend" "\n\$(TYPEDEF)\n\nFields:\n\n- `backendType`\n\n- `backend`\n" @@ -14,8 +13,7 @@ docstrings_types_special = [ "UA_VariableTypeNode" "\n\$(TYPEDEF)\n\nFields:\n\n- `head`\n\n- `dataType`\n\n- `valueRank`\n\n- `arrayDimensionsSize`\n\n- `arrayDimensions`\n\n- `valueBackend`\n\n- `valueSource`\n\n- `value`\n\n- `isAbstract`\n\n- `lifecycle`\n" "UA_Node" "\n\$(TYPEDEF)\n\nFields:\n\n- `head`\n\n- `variableNode`\n\n- `variableTypeNode`\n\n- `methodNode`\n\n- `objectNode`\n\n- `objectTypeNode`\n\n- `referenceTypeNode`\n\n- `dataTypeNode`\n\n- `viewNode`\n" "UA_AsyncOperationRequest" "\n\$(TYPEDEF)\n\nFields:\n\n- `callMethodRequest`\n" - "UA_AsyncOperationResponse" "\n\$(TYPEDEF)\n\nFields:\n\n- `callMethodResult`\n" - ] + "UA_AsyncOperationResponse" "\n\$(TYPEDEF)\n\nFields:\n\n- `callMethodResult`\n"] uniontype_warning = "Note that this type is defined as a union type in C; therefore, setting fields of a Ptr of this type requires special care.\n" #splice docstrings into Open62541.jl @@ -24,15 +22,18 @@ f = open(fn, "r") data = read(f, String) close(f) -typenames = getfield.(collect(eachmatch(r"struct (\S*)\n", data)), :captures) #gets all typenames within Open62541.jl +typenames = getfield.(collect(eachmatch(r"struct (\S*)\n", data)), :captures) #gets all typenames within Open62541.jl for type in typenames @show type[1] - if !any(startswith.(type[1], docstrings_types_ignore_keywords)) && !any(contains.(type[1], docstrings_types_special)) #standard docstring - global data = replace(data, "struct $(type[1])\n" => "$standard_type_docstring\nstruct $(type[1])\n") - elseif any(contains.(type[1], docstrings_types_special[:,1])) - i = findfirst(t -> t == type[1], docstrings_types_special[:,1]) + if !any(startswith.(type[1], docstrings_types_ignore_keywords)) && + !any(contains.(type[1], docstrings_types_special)) #standard docstring + global data = replace( + data, "struct $(type[1])\n" => "$standard_type_docstring\nstruct $(type[1])\n") + elseif any(contains.(type[1], docstrings_types_special[:, 1])) + i = findfirst(t -> t == type[1], docstrings_types_special[:, 1]) if !isnothing(i) - data = replace(data, "struct $(type[1])\n" => "\"\"\"\n$(docstrings_types_special[i,2])\n$uniontype_warning\"\"\"\nstruct $(type[1])\n") + data = replace(data, + "struct $(type[1])\n" => "\"\"\"\n$(docstrings_types_special[i,2])\n$uniontype_warning\"\"\"\nstruct $(type[1])\n") end end end @@ -41,4 +42,3 @@ fn = joinpath(@__DIR__, "../src/Open62541.jl") f = open(fn, "w") write(f, data) close(f) - diff --git a/gen/epilogue.jl b/gen/epilogue.jl index 7734418..b819452 100644 --- a/gen/epilogue.jl +++ b/gen/epilogue.jl @@ -5,8 +5,8 @@ const UA_EXPANDEDNODEID_NULL = UA_ExpandedNodeId(UA_NODEID_NULL, UA_STRING_NULL, #Julia number types that are built directly into open62541 #Does NOT include ComplexF32/64 - these have to be treated differently. -const UA_NUMBER_TYPES = Union{Bool, Int8, Int16, Int32, Int64, UInt8, UInt16, - UInt32, UInt64, Float32, Float64} +const UA_NUMBER_TYPES = Union{Bool, Int8, Int16, Int32, Int64, UInt8, UInt16, + UInt32, UInt64, Float32, Float64} include("generated_defs.jl") include("helper_functions.jl") @@ -20,7 +20,7 @@ include("highlevel_client.jl") include("attribute_generation.jl") include("exceptions.jl") include("init.jl") - + # exports const PREFIXES = ["UA_", "JUA_"] for name in names(@__MODULE__; all = true), prefix in PREFIXES diff --git a/gen/generator.jl b/gen/generator.jl index a890919..34685e6 100644 --- a/gen/generator.jl +++ b/gen/generator.jl @@ -59,22 +59,22 @@ build!(ctx) function write_generated_defs(generated_defs_dir::String, headers, - type_names, - julia_types) - julia_types = replace("$julia_types", Regex("Main\\.Open62541\\.") => "") - types_ambiguous_ignorelist = type_names[1:end .∉ [unique_julia_types_ind]] + TYPE_NAMES, + JULIA_TYPES) + JULIA_TYPES = replace("$JULIA_TYPES", Regex("Main\\.Open62541\\.") => "") + types_ambiguous_ignorelist = TYPE_NAMES[1:end .∉ [UNIQUE_JULIA_TYPES_IND]] type_string = """ # Vector of all UA types - const type_names = $type_names + const TYPE_NAMES = $TYPE_NAMES - # Julia types corresponding to the UA types in vector type_names - const julia_types = $julia_types + # Julia types corresponding to the UA types in vector TYPE_NAMES + const JULIA_TYPES = $JULIA_TYPES # Unique julia types - const unique_julia_types_ind = unique(i -> julia_types[i], eachindex(julia_types)) + const UNIQUE_JULIA_TYPES_IND = unique(i -> JULIA_TYPES[i], eachindex(JULIA_TYPES)) # Vector of types that are ambiguously defined via typedef and are not to be used as default type - types_ambiguous_ignorelist = type_names[1:end .∉ [unique_julia_types_ind]] + types_ambiguous_ignorelist = TYPE_NAMES[1:end .∉ [UNIQUE_JULIA_TYPES_IND]] """ @@ -82,9 +82,12 @@ function write_generated_defs(generated_defs_dir::String, # Vector of all inlined function names listed in the open62541 header files const inlined_funcs = $(extract_inlined_funcs(headers)) """ - - client_write = extract_header_data(r"UA_INLINE[\s\S]{0,50}\s(UA_Client_write(\w*)Attribute)\((?:[\s\S]*?,\s*){2}const\s(\S*)", headers) - push!(client_write, ["UA_Client_writeUserAccessLevelAttribute", "UserAccessLevel", "UA_Byte"]) + + client_write = extract_header_data( + r"UA_INLINE[\s\S]{0,50}\s(UA_Client_write(\w*)Attribute)\((?:[\s\S]*?,\s*){2}const\s(\S*)", + headers) + push!(client_write, + ["UA_Client_writeUserAccessLevelAttribute", "UserAccessLevel", "UA_Byte"]) push!(client_write, ["UA_Client_writeValueAttribute_scalar", "Value", "UA_DataType"]) push!(client_write, ["UA_Client_writeValueAttributeEx", "Value", "UA_DataValue"]) data_UA_Client = """ @@ -152,7 +155,7 @@ close(f) #remove inlined functions inlined_funcs = extract_inlined_funcs(headers) -for i in eachindex(inlined_funcs) +for i in eachindex(inlined_funcs) @show i r = Regex("function $(inlined_funcs[i])\\(.*\\)\n(.*)\nend\n\n") global data = replace(data, r => "") @@ -192,7 +195,7 @@ guid_src = @ccall libopen62541.UA_Guid_random()::UA_Guid UA_Guid_copy(guid_src, guid_dst) return guid_dst end" -data = replace(data, orig=>new) +data = replace(data, orig => new) #need to remove some buggy lines replacestring = "const UA_INT32_MIN = int32_t - Clonglong(2147483648) @@ -211,7 +214,7 @@ const UA_DOUBLE_MIN = \$(Expr(:toplevel, :DBL_MIN)) const UA_DOUBLE_MAX = \$(Expr(:toplevel, :DBL_MAX))" -data = replace(data, replacestring=>"") +data = replace(data, replacestring => "") #need to remove some buggy lines replacestring = "const UA_INT32_MIN = int32_t - Clonglong(2147483648) @@ -230,7 +233,7 @@ const UA_DOUBLE_MIN = \$(Expr(:toplevel, :DBL_MIN)) const UA_DOUBLE_MAX = \$(Expr(:toplevel, :DBL_MAX))" -data = replace(data, replacestring=>"") +data = replace(data, replacestring => "") #replace version number code (make the constants express the version of the _jll #rather than hard coded numbers) @@ -248,7 +251,6 @@ f = open(fn, "w") write(f, data) close(f) - @warn "If errors occur at this stage, check start section of Open62541.jl for system-dependent symbols; may have to resolve manually." @show "loading module" include("../src/Open62541.jl") @@ -266,7 +268,7 @@ for i in eachindex(UA_TYPES_PTRS) UA_TYPES_MAP[i + 1] = getglobal(Open62541, Symbol(typename)) end -type_names = [Symbol("UA_", unsafe_string(unsafe_load(type_ptr).typeName)) +TYPE_NAMES = [Symbol("UA_", unsafe_string(unsafe_load(type_ptr).typeName)) for type_ptr in UA_TYPES_PTRS] # Get corresponding Julia Types @@ -274,14 +276,14 @@ function juliadatatype(p, start, UA_TYPES_MAP) ind = Int(Int((p - start)) / sizeof(Open62541.UA_DataType)) return UA_TYPES_MAP[ind + 1] end -julia_types = [juliadatatype(type_ptr, UA_TYPES_PTRS[0], UA_TYPES_MAP) +JULIA_TYPES = [juliadatatype(type_ptr, UA_TYPES_PTRS[0], UA_TYPES_MAP) for type_ptr in UA_TYPES_PTRS] # Write static definitions to file generated_defs.jl write_generated_defs(joinpath(@__DIR__, "../src/generated_defs.jl"), headers, - type_names, - julia_types) + TYPE_NAMES, + JULIA_TYPES) # Now let's get the epilogue into the Open62541.jl filter # 1. Read original file content @@ -342,4 +344,3 @@ format(joinpath(@__DIR__, "../src/callbacks.jl")) #delete headers directory Base.Filesystem.rm("headers", recursive = true) - diff --git a/src/attribute_generation.jl b/src/attribute_generation.jl index f8bf9b4..a1e09f9 100644 --- a/src/attribute_generation.jl +++ b/src/attribute_generation.jl @@ -173,12 +173,7 @@ function UA_EVENTNOTIFIER(; end #function that allows setting attributes that occur in all node types -function __set_generic_attributes!(attr, - name, - desc, - localization, - writemask, - userwritemask) +function __set_generic_attributes!(attr, name, desc, localization, writemask, userwritemask) displayname = UA_LOCALIZEDTEXT(localization, name) description = UA_LOCALIZEDTEXT(localization, desc) UA_LocalizedText_copy(displayname, attr.displayName) @@ -237,7 +232,7 @@ end function __set_array_attributes!(attr, value::AbstractArray{<:Complex{T}}, valuerank) where {T <: Union{Float32, Float64}} - f = T == Float32 ? UA_ComplexNumberType : UA_DoubleComplexNumberType + f = T == Float32 ? UA_ComplexNumberType : UA_DoubleComplexNumberType a = similar(value, f) for i in eachindex(a) a[i] = f(reim(value[i])...) #implicit conversion to Float32/64 @@ -254,7 +249,7 @@ function __set_array_attributes!(attr, value::AbstractArray{<:Rational{T}}, a[i] = f(value[i].num, value[i].den) #implicit conversion to (U)Int32 end __set_array_attributes!(attr, a, valuerank) -return nothing + return nothing end function __set_array_attributes!(attr, value::AbstractArray{T, N}, @@ -268,7 +263,7 @@ function __set_array_attributes!(attr, value::AbstractArray{T, N}, #Note: need array dims twice, once to put into the variant, i.e., attr.value #and once for the attr structure itself. If the same array is put into both #places, using for example UA_VariableAttributes_delete(attr) leads to free-ing - #the same memory twice --> julia crash (hard to track down!) + #the same memory twice --> julia crash arraydims_variant = UA_UInt32_Array_new(reverse(size(value))) arraydims_attr = UA_UInt32_Array_new(reverse(size(value))) attr.arrayDimensions = arraydims_attr @@ -316,18 +311,18 @@ function UA_VariableAttributes_generate(; value::Union{AbstractArray{T}, T}, useraccesslevel::Union{Nothing, UInt8} = nothing, minimumsamplinginterval::Union{Nothing, Float64} = nothing, historizing::Union{Nothing, Bool} = nothing, - valuerank::Union{Nothing, Integer} = nothing) where {T <: Union{Number, AbstractString}} - if T <: Union{UA_NUMBER_TYPES, Complex{Float32}, Complex{Float64}, Rational{Int32}, Rational{UInt32}, AbstractString} + valuerank::Union{Nothing, Integer} = nothing) where {T <: + Union{Number, AbstractString}} + if T <: Union{UA_NUMBER_TYPES, Complex{Float32}, Complex{Float64}, + Rational{Int32}, Rational{UInt32}, AbstractString} attr = __generate_variable_attributes(value, displayname, description, - localization, writemask, userwritemask, accesslevel, useraccesslevel, - minimumsamplinginterval, historizing, valuerank) + localization, writemask, userwritemask, accesslevel, useraccesslevel, + minimumsamplinginterval, historizing, valuerank) else #if number type not specifically reported (see union above) throw an informative exception. err = UnsupportedNumberTypeError(T) - throw(err) + throw(err) end - - return attr end @@ -377,19 +372,7 @@ function __generic_variable_attributes(displayname, description, localization, if !isnothing(historizing) attr.historizing = historizing end - if type <: AbstractString - attr.dataType = unsafe_load(UA_TYPES_PTRS[UA_TYPES_STRING].typeId) - elseif type == Complex{Float32} - attr.dataType = unsafe_load(UA_TYPES_PTRS[UA_TYPES_COMPLEXNUMBERTYPE].typeId) - elseif type == Complex{Float64} - attr.dataType = unsafe_load(UA_TYPES_PTRS[UA_TYPES_DOUBLECOMPLEXNUMBERTYPE].typeId) - elseif type == Rational{Int32} - attr.dataType = unsafe_load(UA_TYPES_PTRS[UA_TYPES_RATIONALNUMBER].typeId) - elseif type == Rational{UInt32} - attr.dataType = unsafe_load(UA_TYPES_PTRS[UA_TYPES_UNSIGNEDRATIONALNUMBER].typeId) - else - attr.dataType = unsafe_load(ua_data_type_ptr_default(type).typeId) - end + attr.dataType = __determinetype(type) return attr else err = AttributeCopyError(statuscode) @@ -427,24 +410,27 @@ function UA_VariableTypeAttributes_generate(; value::Union{AbstractArray{T}, T} writemask::Union{Nothing, UInt32} = nothing, userwritemask::Union{Nothing, UInt32} = nothing, valuerank::Union{Nothing, Integer} = nothing, - isabstract::Union{Nothing, Bool} = nothing) where {T <: Union{Nothing, Number, AbstractString}} - if T <: Union{Nothing, UA_NUMBER_TYPES, Complex{Float32}, Complex{Float64}, Rational{Int32}, Rational{UInt32}, AbstractString} + isabstract::Union{Nothing, Bool} = nothing) where {T <: Union{ + Nothing, Number, AbstractString}} + if T <: Union{Nothing, UA_NUMBER_TYPES, Complex{Float32}, Complex{Float64}, + Rational{Int32}, Rational{UInt32}, AbstractString} attr = __generate_variabletype_attributes(value, displayname, description, - localization, writemask, userwritemask, valuerank, isabstract) + localization, writemask, userwritemask, valuerank, isabstract) return attr else #if number type not specifically reported (see union above) throw an informative exception. err = UnsupportedNumberTypeError(T) - throw(err) + throw(err) end end function __generate_variabletype_attributes(value::AbstractArray{T, N}, displayname, description, localization, writemask, userwritemask, valuerank, - isabstract) where {T <: Union{UA_NUMBER_TYPES, Complex{Float32}, - Complex{Float64}, Rational{Int32}, Rational{UInt32}, - AbstractString}, - N} + isabstract) where { + T <: Union{UA_NUMBER_TYPES, Complex{Float32}, + Complex{Float64}, Rational{Int32}, Rational{UInt32}, + AbstractString}, + N} if isnothing(valuerank) valuerank = UA_VALUERANK(N) end @@ -456,9 +442,9 @@ end function __generate_variabletype_attributes(value::T, displayname, description, localization, writemask, userwritemask, valuerank, - isabstract) where {T <: Union{Nothing, UA_NUMBER_TYPES, Complex{Float32}, - Complex{Float64}, Rational{Int32}, Rational{UInt32}, - AbstractString}} + isabstract) where {T <: Union{Nothing, UA_NUMBER_TYPES, Complex{Float32}, + Complex{Float64}, Rational{Int32}, Rational{UInt32}, + AbstractString}} if isnothing(valuerank) valuerank = UA_VALUERANK_SCALAR end @@ -489,19 +475,7 @@ function __generic_variabletype_attributes(displayname, description, localizatio attr.isAbstract = isabstract end if !isnothing(type) - if type <: AbstractString - attr.dataType = unsafe_load(UA_TYPES_PTRS[UA_TYPES_STRING].typeId) - elseif type == Complex{Float32} - attr.dataType = unsafe_load(UA_TYPES_PTRS[UA_TYPES_COMPLEXNUMBERTYPE].typeId) - elseif type == Complex{Float64} - attr.dataType = unsafe_load(UA_TYPES_PTRS[UA_TYPES_DOUBLECOMPLEXNUMBERTYPE].typeId) - elseif type == Rational{Int32} - attr.dataType = unsafe_load(UA_TYPES_PTRS[UA_TYPES_RATIONALNUMBER].typeId) - elseif type == Rational{UInt32} - attr.dataType = unsafe_load(UA_TYPES_PTRS[UA_TYPES_UNSIGNEDRATIONALNUMBER].typeId) - else - attr.dataType = unsafe_load(ua_data_type_ptr_default(type).typeId) - end + attr.dataType = __determinetype(type) end return attr else diff --git a/src/callbacks.jl b/src/callbacks.jl index 62b9434..a049be2 100644 --- a/src/callbacks.jl +++ b/src/callbacks.jl @@ -86,6 +86,10 @@ f(server::Ptr{UA_Server}, sessionId::Ptr{UA_NodeId}), sessionContext::Ptr{Cvoid} objectContext::Ptr{Cvoid}, inputSize::Csize_t, input::Ptr{UA_Variant}, outputSize::Csize_t, output::Ptr{UA_Variant})::UA_StatusCode ``` + +If the output of `f` only depends on the inputs, but not on any session state variables, +consider using [`UA_MethodCallback_wrap`](@ref). + """ function UA_MethodCallback_generate(f::Function) argtuple = (Ptr{UA_Server}, Ptr{UA_NodeId}, Ptr{Cvoid}, Ptr{UA_NodeId}, @@ -93,8 +97,8 @@ function UA_MethodCallback_generate(f::Function) Csize_t, Ptr{UA_Variant}) returntype = UA_StatusCode ret = Base.return_types(f, argtuple) - if length(methods(f)) == 1 && hasmethod(f, argtuple) && !isempty(ret) && - ret[1] == returntype + if length(methods(f)) == 1 && hasmethod(f, argtuple) && !isempty(ret) + ret[1] == returntype callback = @cfunction($f, UA_StatusCode, (Ptr{UA_Server}, Ptr{UA_NodeId}, Ptr{Cvoid}, Ptr{UA_NodeId}, Ptr{Cvoid}, Ptr{UA_NodeId}, Ptr{Cvoid}, @@ -106,6 +110,65 @@ function UA_MethodCallback_generate(f::Function) end end +""" +``` +UA_MethodCallback_wrap(f::Function) +``` + +wraps a simple Julia function that operates on inputs into the correct format to be supplied +to `UA_MethodCallback_generate`. + +`f` must be a Julia function with the following signature: + +``` +f(input1::Any, input2::Any, input3::Any, ...) -> output::Union{Any, Tuple{Any, ...}} +``` + +where `Any` means that in principle any type is allowed. However, since Open62541 is based +on C the corresponding method node is *always* configured to only work with a specific +combination of input types. + +If larger flexibility is needed than just working on the inputs given to a method node, see +`UA_MethodCallback_generate`. + +See also: + +[`UA_MethodCallback_generate`](@ref) + +[`JUA_Argument`](@ref) + +[`JUA_Server_addNode`](@ref) + +Example: + +``` +function simple_hello(name, adjective) + assembledstring = "Hello "*name*", you are "*adjective + return assembledstring +end +``` + +which can be attached to a a method node that expects a function that takes two strings as +inputs and one string as output. +""" +function UA_MethodCallback_wrap(fsimple) + function (server, sessionId, sessionHandle, methodId, methodContext, objectId, + objectContext, inputSize, input, outputSize, output) + arr_input = UA_Array(input, Int64(inputSize)) + arr_output = UA_Array(output, Int64(outputSize)) + input_julia = __get_juliavalues_from_variant.(arr_input, Any) + output_julia = fsimple(input_julia...) + if !isa(output_julia, Tuple) + output_julia = (output_julia,) + end + for i in 1:outputSize + j = JUA_Variant(output_julia[i]) + UA_Variant_copy(Jpointer(j), arr_output[i]) + end + return UA_STATUSCODE_GOOD + end +end + """ ``` UA_ValueCallback_onRead_generate(f::Function) diff --git a/src/client.jl b/src/client.jl index 9e211e8..d172b4f 100644 --- a/src/client.jl +++ b/src/client.jl @@ -3,7 +3,7 @@ # * implemented as a plugin (as it can be based on different crypto # * libraries). */ ##TODO: ADD DOCSTRING -function UA_ClientConfig_setAuthenticationUsername(config, username, password) +function UA_ClientConfig_setAuthenticationUsername(config, username, password) identityToken = UA_UserNameIdentityToken_new() if identityToken == C_NULL return UA_STATUSCODE_BADOUTOFMEMORY @@ -13,20 +13,20 @@ function UA_ClientConfig_setAuthenticationUsername(config, username, password) UA_ExtensionObject_clear(config.userIdentityToken) UA_ExtensionObject_setValue(config.userIdentityToken, identityToken, - UA_TYPES_PTRS[UA_TYPES_USERNAMEIDENTITYTOKEN]) + UA_TYPES_PTRS[UA_TYPES_USERNAMEIDENTITYTOKEN]) return UA_STATUSCODE_GOOD end end -# /* Connect to the server. First a SecureChannel is opened, then a Session. The -# * client configuration restricts the SecureChannel selection and contains the -# * UserIdentityToken for the Session. -# * -# * @param client to use -# * @param endpointURL to connect (for example "opc.tcp://localhost:4840") -# * @return Indicates whether the operation succeeded or returns an error code */ - ##TODO: ADD DOCSTRING +""" +``` +UA_Client_connect(client::Ptr{UA_Client}, endpointurl::AbstractString)::UA_StatusCode +``` + +connect the `client` to the server with `endpointurl`. This is an anonymous connection, i.e., +no username or password are used (some servers do not allow this). +""" function UA_Client_connect(client, endpointUrl) cc = UA_Client_getConfig(client) cc.noSession = false @@ -40,7 +40,7 @@ end # * established. You can set a callback to client->config.stateCallback to be # * notified when the connection status changes. Or use UA_Client_getState to get # * the state manually. */ - ##TODO: ADD DOCSTRING +##TODO: ADD DOCSTRING function UA_Client_connectAsync(client::Ptr{UA_Client}, endpointUrl::AbstractString) cc = UA_Client_getConfig(client) cc.noSession = false @@ -49,13 +49,12 @@ function UA_Client_connectAsync(client::Ptr{UA_Client}, endpointUrl::AbstractStr return __UA_Client_connect(client, true) end - # /* Connect to the server without creating a session # * # * @param client to use # * @param endpointURL to connect (for example "opc.tcp://localhost:4840") # * @return Indicates whether the operation succeeded or returns an error code */ - ##TODO: ADD DOCSTRING +##TODO: ADD DOCSTRING function UA_Client_connectSecureChannel(client::Ptr{UA_Client}, endpointUrl::AbstractString) cc = UA_Client_getConfig(client) cc.noSession = true @@ -65,7 +64,8 @@ function UA_Client_connectSecureChannel(client::Ptr{UA_Client}, endpointUrl::Abs end # /* Connect async (non-blocking) only the SecureChannel */ -function UA_Client_connectSecureChannelAsync(client::Ptr{UA_Client}, endpointUrl::AbstractString) +function UA_Client_connectSecureChannelAsync( + client::Ptr{UA_Client}, endpointUrl::AbstractString) cc = UA_Client_getConfig(client) cc.noSession = true UA_String_clear(cc.endpointUrl) @@ -106,7 +106,7 @@ for att in attributes_UA_Client_Service fun_name = Symbol(att[1]) req_type = Symbol("UA_", uppercasefirst(att[2]), "Request") resp_type = Symbol("UA_", uppercasefirst(att[2]), "Response") - resp_gen = Symbol(resp_type, "_new") + resp_gen = Symbol(resp_type, "_new") resp_del = Symbol(resp_type, "_delete") req_type_ptr = Symbol("UA_TYPES_", uppercase(String(att[2])), "REQUEST") resp_type_ptr = Symbol("UA_TYPES_", uppercase(String(att[2])), "RESPONSE") @@ -126,7 +126,7 @@ for att in attributes_UA_Client_Service !!! This is a low-level function within open62541. It is normally much better and more convenient to use a more specific, high level function. - + See also: [`$($resp_type)`](@ref) @@ -136,7 +136,7 @@ for att in attributes_UA_Client_Service """ function $(fun_name)(client, request) response = $(resp_gen)() - statuscode = __UA_Client_Service(client, request, + statuscode = __UA_Client_Service(client, request, UA_TYPES_PTRS[$(req_type_ptr)], response, UA_TYPES_PTRS[$(resp_type_ptr)]) if statuscode == UA_STATUSCODE_GOOD || isnothing(statuscode) @@ -156,8 +156,8 @@ response::Ptr{UA_SetMonitoringModeResponse} = UA_Client_MonitoredItems_setMonito request::Ptr{UA_SetMonitoringModeRequest}) ``` -uses the client API to set the monitoring mode on monitored items. Note that -memory for the response is allocated by C and needs to be cleaned up using +uses the client API to set the monitoring mode on monitored items. Note that +memory for the response is allocated by C and needs to be cleaned up using `UA_SetMonitoringModeResponse_delete(response)` after its use. See also: @@ -185,8 +185,8 @@ response::Ptr{UA_SetTriggeringResponse} = UA_Client_MonitoredItems_setTriggering request::Ptr{UA_SetTriggeringRequest}) ``` -uses the client API to set the monitoring mode on monitored items. Note that -memory for the response is allocated by C and needs to be cleaned up using +uses the client API to set the monitoring mode on monitored items. Note that +memory for the response is allocated by C and needs to be cleaned up using `UA_SetTriggeringResponse_delete(response)` after its use. See also: @@ -199,7 +199,7 @@ See also: [`UA_SetTriggeringResponse`](@ref) """ -function UA_Client_MonitoredItems_setTriggering(client, request) +function UA_Client_MonitoredItems_setTriggering(client, request) response = UA_SetTriggeringResponse_new() __UA_Client_Service(client, request, UA_TYPES_PTRS[UA_TYPES_SETTRIGGERINGREQUEST], @@ -214,8 +214,8 @@ response::Ptr{UA_SetPublishingModeResponse} = UA_Client_Subscriptions_setPublish request::Ptr{UA_SetPublishingModeRequest}) ``` -uses the client API to set the publishing mode on subscriptions. Note that -memory for the response is allocated by C and needs to be cleaned up using +uses the client API to set the publishing mode on subscriptions. Note that +memory for the response is allocated by C and needs to be cleaned up using `UA_SetPublishingModeResponse_delete(response)` after its use. See also: @@ -274,11 +274,11 @@ for nodeclass in instances(UA_NodeClass) See [`$($(attributetype_sym))_generate`](@ref) on how to define valid attributes. """ - function $(funname_sym)(client, requestedNewNodeId, parentNodeId, + function $(funname_sym)(client, requestedNewNodeId, parentNodeId, referenceTypeId, browseName, typeDefinition, attributes, outNewNodeId) return __UA_Client_addNode(client, $(nodeclass_sym), - requestedNewNodeId, parentNodeId, referenceTypeId, + requestedNewNodeId, parentNodeId, referenceTypeId, browseName, typeDefinition, attributes, UA_TYPES_PTRS[$(attributeptr_sym)], outNewNodeId) end @@ -299,13 +299,13 @@ for nodeclass in instances(UA_NodeClass) attributes. """ function $(funname_sym_async)(client, requestedNewNodeId, - parentNodeId, referenceTypeId, browseName, typeDefinition, + parentNodeId, referenceTypeId, browseName, typeDefinition, attributes, outNewNodeId, callback, userdata, reqId) return __UA_Client_addNode_async(client, $(nodeclass_sym), - requestedNewNodeId, parentNodeId, referenceTypeId, - browseName, typeDefinition, attributes, + requestedNewNodeId, parentNodeId, referenceTypeId, + browseName, typeDefinition, attributes, UA_TYPES_PTRS[$(attributeptr_sym)], outNewNodeId, - reinterpret(UA_ClientAsyncServiceCallback, callback), + reinterpret(UA_ClientAsyncServiceCallback, callback), userdata, reqId) end end @@ -328,8 +328,8 @@ for nodeclass in instances(UA_NodeClass) function $(funname_sym)(client, requestedNewNodeId, parentNodeId, referenceTypeId, browseName, attributes, outNewNodeId) return __UA_Client_addNode(client, $(nodeclass_sym), - requestedNewNodeId, parentNodeId, referenceTypeId, - browseName, UA_NODEID_NULL, attributes, + requestedNewNodeId, parentNodeId, referenceTypeId, + browseName, UA_NODEID_NULL, attributes, UA_TYPES_PTRS[$(attributeptr_sym)], outNewNodeId) end @@ -349,11 +349,11 @@ for nodeclass in instances(UA_NodeClass) attributes. """ function $(funname_sym_async)(client, requestedNewNodeId, parentNodeId, - referenceTypeId, browseName, attributes, outNewNodeId, + referenceTypeId, browseName, attributes, outNewNodeId, callback, userdata, reqId) - return __UA_Client_addNode_async(client, $(nodeclass_sym), - requestedNewNodeId, parentNodeId, referenceTypeId, - browseName, UA_NODEID_NULL, attributes, + return __UA_Client_addNode_async(client, $(nodeclass_sym), + requestedNewNodeId, parentNodeId, referenceTypeId, + browseName, UA_NODEID_NULL, attributes, UA_TYPES_PTRS[$(attributeptr_sym)], outNewNodeId, reinterpret(UA_ClientAsyncServiceCallback, callback), userdata, reqId) @@ -452,7 +452,8 @@ for att in attributes_UA_Client_write_async attr_type = Symbol(att[3]) attr_type_ptr = Symbol("UA_TYPES_", uppercase(String(attr_type)[4:end])) ua_attr_name = Symbol("UA_ATTRIBUTEID_", uppercase(att[2])) - cbtype = attr_name == :Value ? "UA_ClientAsyncWriteCallback" : "UA_ClientAsyncServiceCallback" + cbtype = attr_name == :Value ? "UA_ClientAsyncWriteCallback" : + "UA_ClientAsyncServiceCallback" @eval begin """ @@ -468,7 +469,7 @@ for att in attributes_UA_Client_write_async """ function $(fun_name)(client, nodeId, newValue, callback, userdata, reqId) data_type_ptr = UA_TYPES_PTRS[$(attr_type_ptr)] - statuscode = __UA_Client_writeAttribute_async(client, nodeId, + statuscode = __UA_Client_writeAttribute_async(client, nodeId, $(ua_attr_name), newValue, data_type_ptr, callback, userdata, reqId) if statuscode == UA_STATUSCODE_GOOD return statuscode @@ -522,7 +523,7 @@ UA_Client_MonitoredItems_setMonitoringMode_async(client::Ptr{UA_Client}, userdata::Ptr{Cvoid}, requestId::UInt32)::UA_StatusCode ``` -uses the asynchronous client API to set the monitoring mode on monitored items. +uses the asynchronous client API to set the monitoring mode on monitored items. See also: @@ -550,7 +551,7 @@ UA_Client_MonitoredItems_setTriggering_async(client::Ptr{UA_Client}, userdata::Ptr{Cvoid}, requestId::UInt32)::UA_StatusCode ``` -uses the asynchronous client API to set the triggering on monitored items. +uses the asynchronous client API to set the triggering on monitored items. See also: @@ -578,7 +579,7 @@ UA_Client_sendAsyncReadRequest(client::Ptr{UA_Client}, userdata::Ptr{Cvoid}, requestId::UInt32)::UA_StatusCode ``` -uses the asynchronous client API to send a read request. +uses the asynchronous client API to send a read request. See also: @@ -602,7 +603,7 @@ UA_Client_sendAsyncWriteRequest(client::Ptr{UA_Client}, userdata::Ptr{Cvoid}, requestId::UInt32)::UA_StatusCode ``` -uses the asynchronous client API to send a write request. +uses the asynchronous client API to send a write request. See also: @@ -626,7 +627,7 @@ UA_Client_sendAsyncBrowseRequest(client::Ptr{UA_Client}, userdata::Ptr{Cvoid}, requestId::UInt32)::UA_StatusCode ``` -uses the asynchronous client API to send a browse request. +uses the asynchronous client API to send a browse request. See also: @@ -669,8 +670,8 @@ UA_Client_call_async(client::Ptr{UA_Client}, objectId::Ptr{UA_NodeId}, methodId: userdata::Ptr{Cvoid}, requestId::UInt32)::UA_StatusCode ``` -uses the asynchronous client API to call the method `methodId` on the server the -client is connected with. +uses the asynchronous client API to call the method `methodId` on the server the +client is connected with. See also: [`UA_ClientAsyncCallCallback_generate`](@ref) @@ -701,4 +702,4 @@ end # client, request, &UA_TYPES[UA_TYPES_BROWSENEXTREQUEST], # (UA_ClientAsyncServiceCallback)browseNextCallback, # &UA_TYPES[UA_TYPES_BROWSENEXTRESPONSE], userdata, reqId); -# } \ No newline at end of file +# } diff --git a/src/exceptions.jl b/src/exceptions.jl index 4384e91..bafa532 100644 --- a/src/exceptions.jl +++ b/src/exceptions.jl @@ -58,10 +58,56 @@ function Base.showerror(io::IO, e::CallbackGeneratorArgumentError) msg = "The provided function ($(e.f)) has more than one method; it is unclear which one should be used as basis of the callback." else - args_in = fieldtypes(getmethodindex(methods(e.f),1).sig) + args_in = fieldtypes(getmethodindex(methods(e.f), 1).sig) ret = Base.return_types(e.f, args_in[2:end])[1] msg = "Callback generator expected a method with f($(join([e.argtuple...], ", ")))::$(string(e.returntype)), but received a method f($(join(args_in[2:end], ", ")))::$(string(ret))." end print(io, msg) end + +#valuerank, arraysize error +struct ValueRankArraySizeConsistencyError <: Exception + valuerank::Int64 + arraydimensions::Any +end + +function Base.showerror(io::IO, e::ValueRankArraySizeConsistencyError) + vr = e.valuerank + arrdim = e.arraydimensions + if vr < -3 + msg = "A valuerank of $vr has been provided, but valuerank must be >= -3. For further + details see: https://reference.opcfoundation.org/Core/Part3/v105/docs/8.6" + elseif vr >= -3 && vr <= 0 + if vr == -3 + t = " scalar or one-dimensional array" + elseif vr == -2 + t = " scalar or an array of any dimensionality" + elseif vr == -1 + t = " scalar" + else + t = "n array of one OR more dimensions" + end + msg = "A valuerank of -3 has been provided, which indicates a$t. Therefore, no + array dimensions should be provided, but $arrdim has been provided." + else + msg = "A valuerank of $vr has been provided, which indicates a $vr-dimensional array. + Therefore, array dimensions should be a $vr-element vector, but $arrdim has been + provided." + end + print(io, msg) +end + +#MethodNodeInputError +struct MethodNodeInputError <: Exception + ninputsupplied::Int64 + ninputnode::Int64 +end + +function Base.showerror(io::IO, e::MethodNodeInputError) + n1 = e.ninputsupplied + n2 = e.ninputnode + p1 = n1 > 1 ? "s have" : " has" + msg = "MethodNode expects $n2 input, but $n1 input$p1 been supplied." + print(io, msg) +end diff --git a/src/generated_defs.jl b/src/generated_defs.jl index 82f721f..4f8fc49 100644 --- a/src/generated_defs.jl +++ b/src/generated_defs.jl @@ -1,14 +1,14 @@ # Vector of all UA types -const type_names = [:UA_Boolean, :UA_SByte, :UA_Byte, :UA_Int16, :UA_UInt16, :UA_Int32, :UA_UInt32, :UA_Int64, :UA_UInt64, :UA_Float, :UA_Double, :UA_String, :UA_DateTime, :UA_Guid, :UA_ByteString, :UA_XmlElement, :UA_NodeId, :UA_ExpandedNodeId, :UA_StatusCode, :UA_QualifiedName, :UA_LocalizedText, :UA_ExtensionObject, :UA_DataValue, :UA_Variant, :UA_DiagnosticInfo, :UA_NamingRuleType, :UA_Enumeration, :UA_ImageBMP, :UA_ImageGIF, :UA_ImageJPG, :UA_ImagePNG, :UA_AudioDataType, :UA_UriString, :UA_BitFieldMaskDataType, :UA_SemanticVersionString, :UA_KeyValuePair, :UA_AdditionalParametersType, :UA_EphemeralKeyType, :UA_RationalNumber, :UA_ThreeDVector, :UA_ThreeDCartesianCoordinates, :UA_ThreeDOrientation, :UA_ThreeDFrame, :UA_OpenFileMode, :UA_IdentityCriteriaType, :UA_IdentityMappingRuleType, :UA_CurrencyUnitType, :UA_TrustListMasks, :UA_TrustListDataType, :UA_DecimalDataType, :UA_DataTypeDescription, :UA_SimpleTypeDescription, :UA_PortableQualifiedName, :UA_PortableNodeId, :UA_UnsignedRationalNumber, :UA_PubSubState, :UA_DataSetFieldFlags, :UA_ConfigurationVersionDataType, :UA_PublishedVariableDataType, :UA_PublishedDataItemsDataType, :UA_PublishedDataSetCustomSourceDataType, :UA_DataSetFieldContentMask, :UA_DataSetWriterDataType, :UA_NetworkAddressDataType, :UA_NetworkAddressUrlDataType, :UA_OverrideValueHandling, :UA_StandaloneSubscribedDataSetRefDataType, :UA_DataSetOrderingType, :UA_UadpNetworkMessageContentMask, :UA_UadpWriterGroupMessageDataType, :UA_UadpDataSetMessageContentMask, :UA_UadpDataSetWriterMessageDataType, :UA_UadpDataSetReaderMessageDataType, :UA_JsonNetworkMessageContentMask, :UA_JsonWriterGroupMessageDataType, :UA_JsonDataSetMessageContentMask, :UA_JsonDataSetWriterMessageDataType, :UA_JsonDataSetReaderMessageDataType, :UA_TransmitQosPriorityDataType, :UA_ReceiveQosPriorityDataType, :UA_DatagramConnectionTransportDataType, :UA_DatagramConnectionTransport2DataType, :UA_DatagramWriterGroupTransportDataType, :UA_DatagramWriterGroupTransport2DataType, :UA_DatagramDataSetReaderTransportDataType, :UA_BrokerConnectionTransportDataType, :UA_BrokerTransportQualityOfService, :UA_BrokerWriterGroupTransportDataType, :UA_BrokerDataSetWriterTransportDataType, :UA_BrokerDataSetReaderTransportDataType, :UA_PubSubConfigurationRefMask, :UA_PubSubConfigurationRefDataType, :UA_PubSubConfigurationValueDataType, :UA_DiagnosticsLevel, :UA_PubSubDiagnosticsCounterClassification, :UA_AliasNameDataType, :UA_PasswordOptionsMask, :UA_UserConfigurationMask, :UA_UserManagementDataType, :UA_Duplex, :UA_InterfaceAdminStatus, :UA_InterfaceOperStatus, :UA_NegotiationStatus, :UA_TsnFailureCode, :UA_TsnStreamState, :UA_TsnTalkerStatus, :UA_TsnListenerStatus, :UA_PriorityMappingEntryType, :UA_IdType, :UA_NodeClass, :UA_PermissionType, :UA_AccessLevelType, :UA_AccessLevelExType, :UA_EventNotifierType, :UA_AccessRestrictionType, :UA_RolePermissionType, :UA_StructureType, :UA_StructureField, :UA_StructureDefinition, :UA_ReferenceNode, :UA_Argument, :UA_EnumValueType, :UA_EnumField, :UA_OptionSet, :UA_NormalizedString, :UA_DecimalString, :UA_DurationString, :UA_TimeString, :UA_DateString, :UA_Duration, :UA_UtcTime, :UA_LocaleId, :UA_TimeZoneDataType, :UA_Index, :UA_IntegerId, :UA_ApplicationType, :UA_ApplicationDescription, :UA_RequestHeader, :UA_ResponseHeader, :UA_VersionTime, :UA_ServiceFault, :UA_SessionlessInvokeRequestType, :UA_SessionlessInvokeResponseType, :UA_FindServersRequest, :UA_FindServersResponse, :UA_ServerOnNetwork, :UA_FindServersOnNetworkRequest, :UA_FindServersOnNetworkResponse, :UA_ApplicationInstanceCertificate, :UA_MessageSecurityMode, :UA_UserTokenType, :UA_UserTokenPolicy, :UA_EndpointDescription, :UA_GetEndpointsRequest, :UA_GetEndpointsResponse, :UA_RegisteredServer, :UA_RegisterServerRequest, :UA_RegisterServerResponse, :UA_MdnsDiscoveryConfiguration, :UA_RegisterServer2Request, :UA_RegisterServer2Response, :UA_SecurityTokenRequestType, :UA_ChannelSecurityToken, :UA_OpenSecureChannelRequest, :UA_OpenSecureChannelResponse, :UA_CloseSecureChannelRequest, :UA_CloseSecureChannelResponse, :UA_SignedSoftwareCertificate, :UA_SessionAuthenticationToken, :UA_SignatureData, :UA_CreateSessionRequest, :UA_CreateSessionResponse, :UA_UserIdentityToken, :UA_AnonymousIdentityToken, :UA_UserNameIdentityToken, :UA_X509IdentityToken, :UA_IssuedIdentityToken, :UA_RsaEncryptedSecret, :UA_EccEncryptedSecret, :UA_ActivateSessionRequest, :UA_ActivateSessionResponse, :UA_CloseSessionRequest, :UA_CloseSessionResponse, :UA_CancelRequest, :UA_CancelResponse, :UA_NodeAttributesMask, :UA_NodeAttributes, :UA_ObjectAttributes, :UA_VariableAttributes, :UA_MethodAttributes, :UA_ObjectTypeAttributes, :UA_VariableTypeAttributes, :UA_ReferenceTypeAttributes, :UA_DataTypeAttributes, :UA_ViewAttributes, :UA_GenericAttributeValue, :UA_GenericAttributes, :UA_AddNodesItem, :UA_AddNodesResult, :UA_AddNodesRequest, :UA_AddNodesResponse, :UA_AddReferencesItem, :UA_AddReferencesRequest, :UA_AddReferencesResponse, :UA_DeleteNodesItem, :UA_DeleteNodesRequest, :UA_DeleteNodesResponse, :UA_DeleteReferencesItem, :UA_DeleteReferencesRequest, :UA_DeleteReferencesResponse, :UA_AttributeWriteMask, :UA_BrowseDirection, :UA_ViewDescription, :UA_BrowseDescription, :UA_BrowseResultMask, :UA_ReferenceDescription, :UA_ContinuationPoint, :UA_BrowseResult, :UA_BrowseRequest, :UA_BrowseResponse, :UA_BrowseNextRequest, :UA_BrowseNextResponse, :UA_RelativePathElement, :UA_RelativePath, :UA_BrowsePath, :UA_BrowsePathTarget, :UA_BrowsePathResult, :UA_TranslateBrowsePathsToNodeIdsRequest, :UA_TranslateBrowsePathsToNodeIdsResponse, :UA_RegisterNodesRequest, :UA_RegisterNodesResponse, :UA_UnregisterNodesRequest, :UA_UnregisterNodesResponse, :UA_Counter, :UA_OpaqueNumericRange, :UA_EndpointConfiguration, :UA_QueryDataDescription, :UA_NodeTypeDescription, :UA_FilterOperator, :UA_QueryDataSet, :UA_NodeReference, :UA_ContentFilterElement, :UA_ContentFilter, :UA_ElementOperand, :UA_LiteralOperand, :UA_AttributeOperand, :UA_SimpleAttributeOperand, :UA_ContentFilterElementResult, :UA_ContentFilterResult, :UA_ParsingResult, :UA_QueryFirstRequest, :UA_QueryFirstResponse, :UA_QueryNextRequest, :UA_QueryNextResponse, :UA_TimestampsToReturn, :UA_ReadValueId, :UA_ReadRequest, :UA_ReadResponse, :UA_HistoryReadValueId, :UA_HistoryReadResult, :UA_ReadRawModifiedDetails, :UA_ReadAtTimeDetails, :UA_ReadAnnotationDataDetails, :UA_HistoryData, :UA_HistoryReadRequest, :UA_HistoryReadResponse, :UA_WriteValue, :UA_WriteRequest, :UA_WriteResponse, :UA_HistoryUpdateDetails, :UA_HistoryUpdateType, :UA_PerformUpdateType, :UA_UpdateDataDetails, :UA_UpdateStructureDataDetails, :UA_DeleteRawModifiedDetails, :UA_DeleteAtTimeDetails, :UA_DeleteEventDetails, :UA_HistoryUpdateResult, :UA_HistoryUpdateRequest, :UA_HistoryUpdateResponse, :UA_CallMethodRequest, :UA_CallMethodResult, :UA_CallRequest, :UA_CallResponse, :UA_MonitoringMode, :UA_DataChangeTrigger, :UA_DeadbandType, :UA_DataChangeFilter, :UA_EventFilter, :UA_AggregateConfiguration, :UA_AggregateFilter, :UA_EventFilterResult, :UA_AggregateFilterResult, :UA_MonitoringParameters, :UA_MonitoredItemCreateRequest, :UA_MonitoredItemCreateResult, :UA_CreateMonitoredItemsRequest, :UA_CreateMonitoredItemsResponse, :UA_MonitoredItemModifyRequest, :UA_MonitoredItemModifyResult, :UA_ModifyMonitoredItemsRequest, :UA_ModifyMonitoredItemsResponse, :UA_SetMonitoringModeRequest, :UA_SetMonitoringModeResponse, :UA_SetTriggeringRequest, :UA_SetTriggeringResponse, :UA_DeleteMonitoredItemsRequest, :UA_DeleteMonitoredItemsResponse, :UA_CreateSubscriptionRequest, :UA_CreateSubscriptionResponse, :UA_ModifySubscriptionRequest, :UA_ModifySubscriptionResponse, :UA_SetPublishingModeRequest, :UA_SetPublishingModeResponse, :UA_NotificationMessage, :UA_MonitoredItemNotification, :UA_EventFieldList, :UA_HistoryEventFieldList, :UA_StatusChangeNotification, :UA_SubscriptionAcknowledgement, :UA_PublishRequest, :UA_PublishResponse, :UA_RepublishRequest, :UA_RepublishResponse, :UA_TransferResult, :UA_TransferSubscriptionsRequest, :UA_TransferSubscriptionsResponse, :UA_DeleteSubscriptionsRequest, :UA_DeleteSubscriptionsResponse, :UA_BuildInfo, :UA_RedundancySupport, :UA_ServerState, :UA_RedundantServerDataType, :UA_EndpointUrlListDataType, :UA_NetworkGroupDataType, :UA_SamplingIntervalDiagnosticsDataType, :UA_ServerDiagnosticsSummaryDataType, :UA_ServerStatusDataType, :UA_SessionSecurityDiagnosticsDataType, :UA_ServiceCounterDataType, :UA_StatusResult, :UA_SubscriptionDiagnosticsDataType, :UA_ModelChangeStructureVerbMask, :UA_ModelChangeStructureDataType, :UA_SemanticChangeStructureDataType, :UA_Range, :UA_EUInformation, :UA_AxisScaleEnumeration, :UA_ComplexNumberType, :UA_DoubleComplexNumberType, :UA_AxisInformation, :UA_XVType, :UA_ProgramDiagnosticDataType, :UA_ProgramDiagnostic2DataType, :UA_Annotation, :UA_ExceptionDeviationFormat, :UA_EndpointType, :UA_StructureDescription, :UA_FieldMetaData, :UA_PublishedEventsDataType, :UA_PubSubGroupDataType, :UA_WriterGroupDataType, :UA_FieldTargetDataType, :UA_SubscribedDataSetMirrorDataType, :UA_SecurityGroupDataType, :UA_PubSubKeyPushTargetDataType, :UA_EnumDefinition, :UA_ReadEventDetails, :UA_ReadProcessedDetails, :UA_ModificationInfo, :UA_HistoryModifiedData, :UA_HistoryEvent, :UA_UpdateEventDetails, :UA_DataChangeNotification, :UA_EventNotificationList, :UA_SessionDiagnosticsDataType, :UA_EnumDescription, :UA_UABinaryFileDataType, :UA_DataSetMetaDataType, :UA_PublishedDataSetDataType, :UA_DataSetReaderDataType, :UA_TargetVariablesDataType, :UA_StandaloneSubscribedDataSetDataType, :UA_DataTypeSchemaHeader, :UA_ReaderGroupDataType, :UA_PubSubConnectionDataType, :UA_PubSubConfigurationDataType, :UA_PubSubConfiguration2DataType] +const TYPE_NAMES = [:UA_Boolean, :UA_SByte, :UA_Byte, :UA_Int16, :UA_UInt16, :UA_Int32, :UA_UInt32, :UA_Int64, :UA_UInt64, :UA_Float, :UA_Double, :UA_String, :UA_DateTime, :UA_Guid, :UA_ByteString, :UA_XmlElement, :UA_NodeId, :UA_ExpandedNodeId, :UA_StatusCode, :UA_QualifiedName, :UA_LocalizedText, :UA_ExtensionObject, :UA_DataValue, :UA_Variant, :UA_DiagnosticInfo, :UA_NamingRuleType, :UA_Enumeration, :UA_ImageBMP, :UA_ImageGIF, :UA_ImageJPG, :UA_ImagePNG, :UA_AudioDataType, :UA_UriString, :UA_BitFieldMaskDataType, :UA_SemanticVersionString, :UA_KeyValuePair, :UA_AdditionalParametersType, :UA_EphemeralKeyType, :UA_RationalNumber, :UA_ThreeDVector, :UA_ThreeDCartesianCoordinates, :UA_ThreeDOrientation, :UA_ThreeDFrame, :UA_OpenFileMode, :UA_IdentityCriteriaType, :UA_IdentityMappingRuleType, :UA_CurrencyUnitType, :UA_TrustListMasks, :UA_TrustListDataType, :UA_DecimalDataType, :UA_DataTypeDescription, :UA_SimpleTypeDescription, :UA_PortableQualifiedName, :UA_PortableNodeId, :UA_UnsignedRationalNumber, :UA_PubSubState, :UA_DataSetFieldFlags, :UA_ConfigurationVersionDataType, :UA_PublishedVariableDataType, :UA_PublishedDataItemsDataType, :UA_PublishedDataSetCustomSourceDataType, :UA_DataSetFieldContentMask, :UA_DataSetWriterDataType, :UA_NetworkAddressDataType, :UA_NetworkAddressUrlDataType, :UA_OverrideValueHandling, :UA_StandaloneSubscribedDataSetRefDataType, :UA_DataSetOrderingType, :UA_UadpNetworkMessageContentMask, :UA_UadpWriterGroupMessageDataType, :UA_UadpDataSetMessageContentMask, :UA_UadpDataSetWriterMessageDataType, :UA_UadpDataSetReaderMessageDataType, :UA_JsonNetworkMessageContentMask, :UA_JsonWriterGroupMessageDataType, :UA_JsonDataSetMessageContentMask, :UA_JsonDataSetWriterMessageDataType, :UA_JsonDataSetReaderMessageDataType, :UA_TransmitQosPriorityDataType, :UA_ReceiveQosPriorityDataType, :UA_DatagramConnectionTransportDataType, :UA_DatagramConnectionTransport2DataType, :UA_DatagramWriterGroupTransportDataType, :UA_DatagramWriterGroupTransport2DataType, :UA_DatagramDataSetReaderTransportDataType, :UA_BrokerConnectionTransportDataType, :UA_BrokerTransportQualityOfService, :UA_BrokerWriterGroupTransportDataType, :UA_BrokerDataSetWriterTransportDataType, :UA_BrokerDataSetReaderTransportDataType, :UA_PubSubConfigurationRefMask, :UA_PubSubConfigurationRefDataType, :UA_PubSubConfigurationValueDataType, :UA_DiagnosticsLevel, :UA_PubSubDiagnosticsCounterClassification, :UA_AliasNameDataType, :UA_PasswordOptionsMask, :UA_UserConfigurationMask, :UA_UserManagementDataType, :UA_Duplex, :UA_InterfaceAdminStatus, :UA_InterfaceOperStatus, :UA_NegotiationStatus, :UA_TsnFailureCode, :UA_TsnStreamState, :UA_TsnTalkerStatus, :UA_TsnListenerStatus, :UA_PriorityMappingEntryType, :UA_IdType, :UA_NodeClass, :UA_PermissionType, :UA_AccessLevelType, :UA_AccessLevelExType, :UA_EventNotifierType, :UA_AccessRestrictionType, :UA_RolePermissionType, :UA_StructureType, :UA_StructureField, :UA_StructureDefinition, :UA_ReferenceNode, :UA_Argument, :UA_EnumValueType, :UA_EnumField, :UA_OptionSet, :UA_NormalizedString, :UA_DecimalString, :UA_DurationString, :UA_TimeString, :UA_DateString, :UA_Duration, :UA_UtcTime, :UA_LocaleId, :UA_TimeZoneDataType, :UA_Index, :UA_IntegerId, :UA_ApplicationType, :UA_ApplicationDescription, :UA_RequestHeader, :UA_ResponseHeader, :UA_VersionTime, :UA_ServiceFault, :UA_SessionlessInvokeRequestType, :UA_SessionlessInvokeResponseType, :UA_FindServersRequest, :UA_FindServersResponse, :UA_ServerOnNetwork, :UA_FindServersOnNetworkRequest, :UA_FindServersOnNetworkResponse, :UA_ApplicationInstanceCertificate, :UA_MessageSecurityMode, :UA_UserTokenType, :UA_UserTokenPolicy, :UA_EndpointDescription, :UA_GetEndpointsRequest, :UA_GetEndpointsResponse, :UA_RegisteredServer, :UA_RegisterServerRequest, :UA_RegisterServerResponse, :UA_MdnsDiscoveryConfiguration, :UA_RegisterServer2Request, :UA_RegisterServer2Response, :UA_SecurityTokenRequestType, :UA_ChannelSecurityToken, :UA_OpenSecureChannelRequest, :UA_OpenSecureChannelResponse, :UA_CloseSecureChannelRequest, :UA_CloseSecureChannelResponse, :UA_SignedSoftwareCertificate, :UA_SessionAuthenticationToken, :UA_SignatureData, :UA_CreateSessionRequest, :UA_CreateSessionResponse, :UA_UserIdentityToken, :UA_AnonymousIdentityToken, :UA_UserNameIdentityToken, :UA_X509IdentityToken, :UA_IssuedIdentityToken, :UA_RsaEncryptedSecret, :UA_EccEncryptedSecret, :UA_ActivateSessionRequest, :UA_ActivateSessionResponse, :UA_CloseSessionRequest, :UA_CloseSessionResponse, :UA_CancelRequest, :UA_CancelResponse, :UA_NodeAttributesMask, :UA_NodeAttributes, :UA_ObjectAttributes, :UA_VariableAttributes, :UA_MethodAttributes, :UA_ObjectTypeAttributes, :UA_VariableTypeAttributes, :UA_ReferenceTypeAttributes, :UA_DataTypeAttributes, :UA_ViewAttributes, :UA_GenericAttributeValue, :UA_GenericAttributes, :UA_AddNodesItem, :UA_AddNodesResult, :UA_AddNodesRequest, :UA_AddNodesResponse, :UA_AddReferencesItem, :UA_AddReferencesRequest, :UA_AddReferencesResponse, :UA_DeleteNodesItem, :UA_DeleteNodesRequest, :UA_DeleteNodesResponse, :UA_DeleteReferencesItem, :UA_DeleteReferencesRequest, :UA_DeleteReferencesResponse, :UA_AttributeWriteMask, :UA_BrowseDirection, :UA_ViewDescription, :UA_BrowseDescription, :UA_BrowseResultMask, :UA_ReferenceDescription, :UA_ContinuationPoint, :UA_BrowseResult, :UA_BrowseRequest, :UA_BrowseResponse, :UA_BrowseNextRequest, :UA_BrowseNextResponse, :UA_RelativePathElement, :UA_RelativePath, :UA_BrowsePath, :UA_BrowsePathTarget, :UA_BrowsePathResult, :UA_TranslateBrowsePathsToNodeIdsRequest, :UA_TranslateBrowsePathsToNodeIdsResponse, :UA_RegisterNodesRequest, :UA_RegisterNodesResponse, :UA_UnregisterNodesRequest, :UA_UnregisterNodesResponse, :UA_Counter, :UA_OpaqueNumericRange, :UA_EndpointConfiguration, :UA_QueryDataDescription, :UA_NodeTypeDescription, :UA_FilterOperator, :UA_QueryDataSet, :UA_NodeReference, :UA_ContentFilterElement, :UA_ContentFilter, :UA_ElementOperand, :UA_LiteralOperand, :UA_AttributeOperand, :UA_SimpleAttributeOperand, :UA_ContentFilterElementResult, :UA_ContentFilterResult, :UA_ParsingResult, :UA_QueryFirstRequest, :UA_QueryFirstResponse, :UA_QueryNextRequest, :UA_QueryNextResponse, :UA_TimestampsToReturn, :UA_ReadValueId, :UA_ReadRequest, :UA_ReadResponse, :UA_HistoryReadValueId, :UA_HistoryReadResult, :UA_ReadRawModifiedDetails, :UA_ReadAtTimeDetails, :UA_ReadAnnotationDataDetails, :UA_HistoryData, :UA_HistoryReadRequest, :UA_HistoryReadResponse, :UA_WriteValue, :UA_WriteRequest, :UA_WriteResponse, :UA_HistoryUpdateDetails, :UA_HistoryUpdateType, :UA_PerformUpdateType, :UA_UpdateDataDetails, :UA_UpdateStructureDataDetails, :UA_DeleteRawModifiedDetails, :UA_DeleteAtTimeDetails, :UA_DeleteEventDetails, :UA_HistoryUpdateResult, :UA_HistoryUpdateRequest, :UA_HistoryUpdateResponse, :UA_CallMethodRequest, :UA_CallMethodResult, :UA_CallRequest, :UA_CallResponse, :UA_MonitoringMode, :UA_DataChangeTrigger, :UA_DeadbandType, :UA_DataChangeFilter, :UA_EventFilter, :UA_AggregateConfiguration, :UA_AggregateFilter, :UA_EventFilterResult, :UA_AggregateFilterResult, :UA_MonitoringParameters, :UA_MonitoredItemCreateRequest, :UA_MonitoredItemCreateResult, :UA_CreateMonitoredItemsRequest, :UA_CreateMonitoredItemsResponse, :UA_MonitoredItemModifyRequest, :UA_MonitoredItemModifyResult, :UA_ModifyMonitoredItemsRequest, :UA_ModifyMonitoredItemsResponse, :UA_SetMonitoringModeRequest, :UA_SetMonitoringModeResponse, :UA_SetTriggeringRequest, :UA_SetTriggeringResponse, :UA_DeleteMonitoredItemsRequest, :UA_DeleteMonitoredItemsResponse, :UA_CreateSubscriptionRequest, :UA_CreateSubscriptionResponse, :UA_ModifySubscriptionRequest, :UA_ModifySubscriptionResponse, :UA_SetPublishingModeRequest, :UA_SetPublishingModeResponse, :UA_NotificationMessage, :UA_MonitoredItemNotification, :UA_EventFieldList, :UA_HistoryEventFieldList, :UA_StatusChangeNotification, :UA_SubscriptionAcknowledgement, :UA_PublishRequest, :UA_PublishResponse, :UA_RepublishRequest, :UA_RepublishResponse, :UA_TransferResult, :UA_TransferSubscriptionsRequest, :UA_TransferSubscriptionsResponse, :UA_DeleteSubscriptionsRequest, :UA_DeleteSubscriptionsResponse, :UA_BuildInfo, :UA_RedundancySupport, :UA_ServerState, :UA_RedundantServerDataType, :UA_EndpointUrlListDataType, :UA_NetworkGroupDataType, :UA_SamplingIntervalDiagnosticsDataType, :UA_ServerDiagnosticsSummaryDataType, :UA_ServerStatusDataType, :UA_SessionSecurityDiagnosticsDataType, :UA_ServiceCounterDataType, :UA_StatusResult, :UA_SubscriptionDiagnosticsDataType, :UA_ModelChangeStructureVerbMask, :UA_ModelChangeStructureDataType, :UA_SemanticChangeStructureDataType, :UA_Range, :UA_EUInformation, :UA_AxisScaleEnumeration, :UA_ComplexNumberType, :UA_DoubleComplexNumberType, :UA_AxisInformation, :UA_XVType, :UA_ProgramDiagnosticDataType, :UA_ProgramDiagnostic2DataType, :UA_Annotation, :UA_ExceptionDeviationFormat, :UA_EndpointType, :UA_StructureDescription, :UA_FieldMetaData, :UA_PublishedEventsDataType, :UA_PubSubGroupDataType, :UA_WriterGroupDataType, :UA_FieldTargetDataType, :UA_SubscribedDataSetMirrorDataType, :UA_SecurityGroupDataType, :UA_PubSubKeyPushTargetDataType, :UA_EnumDefinition, :UA_ReadEventDetails, :UA_ReadProcessedDetails, :UA_ModificationInfo, :UA_HistoryModifiedData, :UA_HistoryEvent, :UA_UpdateEventDetails, :UA_DataChangeNotification, :UA_EventNotificationList, :UA_SessionDiagnosticsDataType, :UA_EnumDescription, :UA_UABinaryFileDataType, :UA_DataSetMetaDataType, :UA_PublishedDataSetDataType, :UA_DataSetReaderDataType, :UA_TargetVariablesDataType, :UA_StandaloneSubscribedDataSetDataType, :UA_DataTypeSchemaHeader, :UA_ReaderGroupDataType, :UA_PubSubConnectionDataType, :UA_PubSubConfigurationDataType, :UA_PubSubConfiguration2DataType] # Julia types corresponding to the UA types in vector type_names -const julia_types = DataType[Bool, Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Float32, Float64, UA_String, Int64, UA_Guid, UA_String, UA_String, UA_NodeId, UA_ExpandedNodeId, UInt32, UA_QualifiedName, UA_LocalizedText, UA_ExtensionObject, UA_DataValue, UA_Variant, UA_DiagnosticInfo, UA_NamingRuleType, UA_Enumeration, UA_String, UA_String, UA_String, UA_String, UA_String, UA_String, UInt64, UA_String, UA_KeyValuePair, UA_AdditionalParametersType, UA_EphemeralKeyType, UA_RationalNumber, UA_ThreeDVector, UA_ThreeDCartesianCoordinates, UA_ThreeDOrientation, UA_ThreeDFrame, UA_OpenFileMode, UA_IdentityCriteriaType, UA_IdentityMappingRuleType, UA_CurrencyUnitType, UA_TrustListMasks, UA_TrustListDataType, UA_DecimalDataType, UA_DataTypeDescription, UA_SimpleTypeDescription, UA_PortableQualifiedName, UA_PortableNodeId, UA_UnsignedRationalNumber, UA_PubSubState, UInt16, UA_ConfigurationVersionDataType, UA_PublishedVariableDataType, UA_PublishedDataItemsDataType, UA_PublishedDataSetCustomSourceDataType, UInt32, UA_DataSetWriterDataType, UA_NetworkAddressDataType, UA_NetworkAddressUrlDataType, UA_OverrideValueHandling, UA_StandaloneSubscribedDataSetRefDataType, UA_DataSetOrderingType, UInt32, UA_UadpWriterGroupMessageDataType, UInt32, UA_UadpDataSetWriterMessageDataType, UA_UadpDataSetReaderMessageDataType, UInt32, UA_JsonWriterGroupMessageDataType, UInt32, UA_JsonDataSetWriterMessageDataType, UA_JsonDataSetReaderMessageDataType, UA_TransmitQosPriorityDataType, UA_ReceiveQosPriorityDataType, UA_DatagramConnectionTransportDataType, UA_DatagramConnectionTransport2DataType, UA_DatagramWriterGroupTransportDataType, UA_DatagramWriterGroupTransport2DataType, UA_DatagramDataSetReaderTransportDataType, UA_BrokerConnectionTransportDataType, UA_BrokerTransportQualityOfService, UA_BrokerWriterGroupTransportDataType, UA_BrokerDataSetWriterTransportDataType, UA_BrokerDataSetReaderTransportDataType, UInt32, UA_PubSubConfigurationRefDataType, UA_PubSubConfigurationValueDataType, UA_DiagnosticsLevel, UA_PubSubDiagnosticsCounterClassification, UA_AliasNameDataType, UInt32, UInt32, UA_UserManagementDataType, UA_Duplex, UA_InterfaceAdminStatus, UA_InterfaceOperStatus, UA_NegotiationStatus, UA_TsnFailureCode, UA_TsnStreamState, UA_TsnTalkerStatus, UA_TsnListenerStatus, UA_PriorityMappingEntryType, UA_IdType, UA_NodeClass, UInt32, UInt8, UInt32, UInt8, UInt16, UA_RolePermissionType, UA_StructureType, UA_StructureField, UA_StructureDefinition, UA_ReferenceNode, UA_Argument, UA_EnumValueType, UA_EnumField, UA_OptionSet, UA_String, UA_String, UA_String, UA_String, UA_String, Float64, Int64, UA_String, UA_TimeZoneDataType, UA_String, UInt32, UA_ApplicationType, UA_ApplicationDescription, UA_RequestHeader, UA_ResponseHeader, UA_String, UA_ServiceFault, UA_SessionlessInvokeRequestType, UA_SessionlessInvokeResponseType, UA_FindServersRequest, UA_FindServersResponse, UA_ServerOnNetwork, UA_FindServersOnNetworkRequest, UA_FindServersOnNetworkResponse, UA_String, UA_MessageSecurityMode, UA_UserTokenType, UA_UserTokenPolicy, UA_EndpointDescription, UA_GetEndpointsRequest, UA_GetEndpointsResponse, UA_RegisteredServer, UA_RegisterServerRequest, UA_RegisterServerResponse, UA_MdnsDiscoveryConfiguration, UA_RegisterServer2Request, UA_RegisterServer2Response, UA_SecurityTokenRequestType, UA_ChannelSecurityToken, UA_OpenSecureChannelRequest, UA_OpenSecureChannelResponse, UA_CloseSecureChannelRequest, UA_CloseSecureChannelResponse, UA_SignedSoftwareCertificate, UA_NodeId, UA_SignatureData, UA_CreateSessionRequest, UA_CreateSessionResponse, UA_UserIdentityToken, UA_AnonymousIdentityToken, UA_UserNameIdentityToken, UA_X509IdentityToken, UA_IssuedIdentityToken, UA_String, UA_String, UA_ActivateSessionRequest, UA_ActivateSessionResponse, UA_CloseSessionRequest, UA_CloseSessionResponse, UA_CancelRequest, UA_CancelResponse, UA_NodeAttributesMask, UA_NodeAttributes, UA_ObjectAttributes, UA_VariableAttributes, UA_MethodAttributes, UA_ObjectTypeAttributes, UA_VariableTypeAttributes, UA_ReferenceTypeAttributes, UA_DataTypeAttributes, UA_ViewAttributes, UA_GenericAttributeValue, UA_GenericAttributes, UA_AddNodesItem, UA_AddNodesResult, UA_AddNodesRequest, UA_AddNodesResponse, UA_AddReferencesItem, UA_AddReferencesRequest, UA_AddReferencesResponse, UA_DeleteNodesItem, UA_DeleteNodesRequest, UA_DeleteNodesResponse, UA_DeleteReferencesItem, UA_DeleteReferencesRequest, UA_DeleteReferencesResponse, UInt32, UA_BrowseDirection, UA_ViewDescription, UA_BrowseDescription, UA_BrowseResultMask, UA_ReferenceDescription, UA_String, UA_BrowseResult, UA_BrowseRequest, UA_BrowseResponse, UA_BrowseNextRequest, UA_BrowseNextResponse, UA_RelativePathElement, UA_RelativePath, UA_BrowsePath, UA_BrowsePathTarget, UA_BrowsePathResult, UA_TranslateBrowsePathsToNodeIdsRequest, UA_TranslateBrowsePathsToNodeIdsResponse, UA_RegisterNodesRequest, UA_RegisterNodesResponse, UA_UnregisterNodesRequest, UA_UnregisterNodesResponse, UInt32, UA_String, UA_EndpointConfiguration, UA_QueryDataDescription, UA_NodeTypeDescription, UA_FilterOperator, UA_QueryDataSet, UA_NodeReference, UA_ContentFilterElement, UA_ContentFilter, UA_ElementOperand, UA_LiteralOperand, UA_AttributeOperand, UA_SimpleAttributeOperand, UA_ContentFilterElementResult, UA_ContentFilterResult, UA_ParsingResult, UA_QueryFirstRequest, UA_QueryFirstResponse, UA_QueryNextRequest, UA_QueryNextResponse, UA_TimestampsToReturn, UA_ReadValueId, UA_ReadRequest, UA_ReadResponse, UA_HistoryReadValueId, UA_HistoryReadResult, UA_ReadRawModifiedDetails, UA_ReadAtTimeDetails, UA_ReadAnnotationDataDetails, UA_HistoryData, UA_HistoryReadRequest, UA_HistoryReadResponse, UA_WriteValue, UA_WriteRequest, UA_WriteResponse, UA_HistoryUpdateDetails, UA_HistoryUpdateType, UA_PerformUpdateType, UA_UpdateDataDetails, UA_UpdateStructureDataDetails, UA_DeleteRawModifiedDetails, UA_DeleteAtTimeDetails, UA_DeleteEventDetails, UA_HistoryUpdateResult, UA_HistoryUpdateRequest, UA_HistoryUpdateResponse, UA_CallMethodRequest, UA_CallMethodResult, UA_CallRequest, UA_CallResponse, UA_MonitoringMode, UA_DataChangeTrigger, UA_DeadbandType, UA_DataChangeFilter, UA_EventFilter, UA_AggregateConfiguration, UA_AggregateFilter, UA_EventFilterResult, UA_AggregateFilterResult, UA_MonitoringParameters, UA_MonitoredItemCreateRequest, UA_MonitoredItemCreateResult, UA_CreateMonitoredItemsRequest, UA_CreateMonitoredItemsResponse, UA_MonitoredItemModifyRequest, UA_MonitoredItemModifyResult, UA_ModifyMonitoredItemsRequest, UA_ModifyMonitoredItemsResponse, UA_SetMonitoringModeRequest, UA_SetMonitoringModeResponse, UA_SetTriggeringRequest, UA_SetTriggeringResponse, UA_DeleteMonitoredItemsRequest, UA_DeleteMonitoredItemsResponse, UA_CreateSubscriptionRequest, UA_CreateSubscriptionResponse, UA_ModifySubscriptionRequest, UA_ModifySubscriptionResponse, UA_SetPublishingModeRequest, UA_SetPublishingModeResponse, UA_NotificationMessage, UA_MonitoredItemNotification, UA_EventFieldList, UA_HistoryEventFieldList, UA_StatusChangeNotification, UA_SubscriptionAcknowledgement, UA_PublishRequest, UA_PublishResponse, UA_RepublishRequest, UA_RepublishResponse, UA_TransferResult, UA_TransferSubscriptionsRequest, UA_TransferSubscriptionsResponse, UA_DeleteSubscriptionsRequest, UA_DeleteSubscriptionsResponse, UA_BuildInfo, UA_RedundancySupport, UA_ServerState, UA_RedundantServerDataType, UA_EndpointUrlListDataType, UA_NetworkGroupDataType, UA_SamplingIntervalDiagnosticsDataType, UA_ServerDiagnosticsSummaryDataType, UA_ServerStatusDataType, UA_SessionSecurityDiagnosticsDataType, UA_ServiceCounterDataType, UA_StatusResult, UA_SubscriptionDiagnosticsDataType, UA_ModelChangeStructureVerbMask, UA_ModelChangeStructureDataType, UA_SemanticChangeStructureDataType, UA_Range, UA_EUInformation, UA_AxisScaleEnumeration, UA_ComplexNumberType, UA_DoubleComplexNumberType, UA_AxisInformation, UA_XVType, UA_ProgramDiagnosticDataType, UA_ProgramDiagnostic2DataType, UA_Annotation, UA_ExceptionDeviationFormat, UA_EndpointType, UA_StructureDescription, UA_FieldMetaData, UA_PublishedEventsDataType, UA_PubSubGroupDataType, UA_WriterGroupDataType, UA_FieldTargetDataType, UA_SubscribedDataSetMirrorDataType, UA_SecurityGroupDataType, UA_PubSubKeyPushTargetDataType, UA_EnumDefinition, UA_ReadEventDetails, UA_ReadProcessedDetails, UA_ModificationInfo, UA_HistoryModifiedData, UA_HistoryEvent, UA_UpdateEventDetails, UA_DataChangeNotification, UA_EventNotificationList, UA_SessionDiagnosticsDataType, UA_EnumDescription, UA_UABinaryFileDataType, UA_DataSetMetaDataType, UA_PublishedDataSetDataType, UA_DataSetReaderDataType, UA_TargetVariablesDataType, UA_StandaloneSubscribedDataSetDataType, UA_DataTypeSchemaHeader, UA_ReaderGroupDataType, UA_PubSubConnectionDataType, UA_PubSubConfigurationDataType, UA_PubSubConfiguration2DataType] +const JULIA_TYPES = DataType[Bool, Int8, UInt8, Int16, UInt16, Int32, UInt32, Int64, UInt64, Float32, Float64, UA_String, Int64, UA_Guid, UA_String, UA_String, UA_NodeId, UA_ExpandedNodeId, UInt32, UA_QualifiedName, UA_LocalizedText, UA_ExtensionObject, UA_DataValue, UA_Variant, UA_DiagnosticInfo, UA_NamingRuleType, UA_Enumeration, UA_String, UA_String, UA_String, UA_String, UA_String, UA_String, UInt64, UA_String, UA_KeyValuePair, UA_AdditionalParametersType, UA_EphemeralKeyType, UA_RationalNumber, UA_ThreeDVector, UA_ThreeDCartesianCoordinates, UA_ThreeDOrientation, UA_ThreeDFrame, UA_OpenFileMode, UA_IdentityCriteriaType, UA_IdentityMappingRuleType, UA_CurrencyUnitType, UA_TrustListMasks, UA_TrustListDataType, UA_DecimalDataType, UA_DataTypeDescription, UA_SimpleTypeDescription, UA_PortableQualifiedName, UA_PortableNodeId, UA_UnsignedRationalNumber, UA_PubSubState, UInt16, UA_ConfigurationVersionDataType, UA_PublishedVariableDataType, UA_PublishedDataItemsDataType, UA_PublishedDataSetCustomSourceDataType, UInt32, UA_DataSetWriterDataType, UA_NetworkAddressDataType, UA_NetworkAddressUrlDataType, UA_OverrideValueHandling, UA_StandaloneSubscribedDataSetRefDataType, UA_DataSetOrderingType, UInt32, UA_UadpWriterGroupMessageDataType, UInt32, UA_UadpDataSetWriterMessageDataType, UA_UadpDataSetReaderMessageDataType, UInt32, UA_JsonWriterGroupMessageDataType, UInt32, UA_JsonDataSetWriterMessageDataType, UA_JsonDataSetReaderMessageDataType, UA_TransmitQosPriorityDataType, UA_ReceiveQosPriorityDataType, UA_DatagramConnectionTransportDataType, UA_DatagramConnectionTransport2DataType, UA_DatagramWriterGroupTransportDataType, UA_DatagramWriterGroupTransport2DataType, UA_DatagramDataSetReaderTransportDataType, UA_BrokerConnectionTransportDataType, UA_BrokerTransportQualityOfService, UA_BrokerWriterGroupTransportDataType, UA_BrokerDataSetWriterTransportDataType, UA_BrokerDataSetReaderTransportDataType, UInt32, UA_PubSubConfigurationRefDataType, UA_PubSubConfigurationValueDataType, UA_DiagnosticsLevel, UA_PubSubDiagnosticsCounterClassification, UA_AliasNameDataType, UInt32, UInt32, UA_UserManagementDataType, UA_Duplex, UA_InterfaceAdminStatus, UA_InterfaceOperStatus, UA_NegotiationStatus, UA_TsnFailureCode, UA_TsnStreamState, UA_TsnTalkerStatus, UA_TsnListenerStatus, UA_PriorityMappingEntryType, UA_IdType, UA_NodeClass, UInt32, UInt8, UInt32, UInt8, UInt16, UA_RolePermissionType, UA_StructureType, UA_StructureField, UA_StructureDefinition, UA_ReferenceNode, UA_Argument, UA_EnumValueType, UA_EnumField, UA_OptionSet, UA_String, UA_String, UA_String, UA_String, UA_String, Float64, Int64, UA_String, UA_TimeZoneDataType, UA_String, UInt32, UA_ApplicationType, UA_ApplicationDescription, UA_RequestHeader, UA_ResponseHeader, UA_String, UA_ServiceFault, UA_SessionlessInvokeRequestType, UA_SessionlessInvokeResponseType, UA_FindServersRequest, UA_FindServersResponse, UA_ServerOnNetwork, UA_FindServersOnNetworkRequest, UA_FindServersOnNetworkResponse, UA_String, UA_MessageSecurityMode, UA_UserTokenType, UA_UserTokenPolicy, UA_EndpointDescription, UA_GetEndpointsRequest, UA_GetEndpointsResponse, UA_RegisteredServer, UA_RegisterServerRequest, UA_RegisterServerResponse, UA_MdnsDiscoveryConfiguration, UA_RegisterServer2Request, UA_RegisterServer2Response, UA_SecurityTokenRequestType, UA_ChannelSecurityToken, UA_OpenSecureChannelRequest, UA_OpenSecureChannelResponse, UA_CloseSecureChannelRequest, UA_CloseSecureChannelResponse, UA_SignedSoftwareCertificate, UA_NodeId, UA_SignatureData, UA_CreateSessionRequest, UA_CreateSessionResponse, UA_UserIdentityToken, UA_AnonymousIdentityToken, UA_UserNameIdentityToken, UA_X509IdentityToken, UA_IssuedIdentityToken, UA_String, UA_String, UA_ActivateSessionRequest, UA_ActivateSessionResponse, UA_CloseSessionRequest, UA_CloseSessionResponse, UA_CancelRequest, UA_CancelResponse, UA_NodeAttributesMask, UA_NodeAttributes, UA_ObjectAttributes, UA_VariableAttributes, UA_MethodAttributes, UA_ObjectTypeAttributes, UA_VariableTypeAttributes, UA_ReferenceTypeAttributes, UA_DataTypeAttributes, UA_ViewAttributes, UA_GenericAttributeValue, UA_GenericAttributes, UA_AddNodesItem, UA_AddNodesResult, UA_AddNodesRequest, UA_AddNodesResponse, UA_AddReferencesItem, UA_AddReferencesRequest, UA_AddReferencesResponse, UA_DeleteNodesItem, UA_DeleteNodesRequest, UA_DeleteNodesResponse, UA_DeleteReferencesItem, UA_DeleteReferencesRequest, UA_DeleteReferencesResponse, UInt32, UA_BrowseDirection, UA_ViewDescription, UA_BrowseDescription, UA_BrowseResultMask, UA_ReferenceDescription, UA_String, UA_BrowseResult, UA_BrowseRequest, UA_BrowseResponse, UA_BrowseNextRequest, UA_BrowseNextResponse, UA_RelativePathElement, UA_RelativePath, UA_BrowsePath, UA_BrowsePathTarget, UA_BrowsePathResult, UA_TranslateBrowsePathsToNodeIdsRequest, UA_TranslateBrowsePathsToNodeIdsResponse, UA_RegisterNodesRequest, UA_RegisterNodesResponse, UA_UnregisterNodesRequest, UA_UnregisterNodesResponse, UInt32, UA_String, UA_EndpointConfiguration, UA_QueryDataDescription, UA_NodeTypeDescription, UA_FilterOperator, UA_QueryDataSet, UA_NodeReference, UA_ContentFilterElement, UA_ContentFilter, UA_ElementOperand, UA_LiteralOperand, UA_AttributeOperand, UA_SimpleAttributeOperand, UA_ContentFilterElementResult, UA_ContentFilterResult, UA_ParsingResult, UA_QueryFirstRequest, UA_QueryFirstResponse, UA_QueryNextRequest, UA_QueryNextResponse, UA_TimestampsToReturn, UA_ReadValueId, UA_ReadRequest, UA_ReadResponse, UA_HistoryReadValueId, UA_HistoryReadResult, UA_ReadRawModifiedDetails, UA_ReadAtTimeDetails, UA_ReadAnnotationDataDetails, UA_HistoryData, UA_HistoryReadRequest, UA_HistoryReadResponse, UA_WriteValue, UA_WriteRequest, UA_WriteResponse, UA_HistoryUpdateDetails, UA_HistoryUpdateType, UA_PerformUpdateType, UA_UpdateDataDetails, UA_UpdateStructureDataDetails, UA_DeleteRawModifiedDetails, UA_DeleteAtTimeDetails, UA_DeleteEventDetails, UA_HistoryUpdateResult, UA_HistoryUpdateRequest, UA_HistoryUpdateResponse, UA_CallMethodRequest, UA_CallMethodResult, UA_CallRequest, UA_CallResponse, UA_MonitoringMode, UA_DataChangeTrigger, UA_DeadbandType, UA_DataChangeFilter, UA_EventFilter, UA_AggregateConfiguration, UA_AggregateFilter, UA_EventFilterResult, UA_AggregateFilterResult, UA_MonitoringParameters, UA_MonitoredItemCreateRequest, UA_MonitoredItemCreateResult, UA_CreateMonitoredItemsRequest, UA_CreateMonitoredItemsResponse, UA_MonitoredItemModifyRequest, UA_MonitoredItemModifyResult, UA_ModifyMonitoredItemsRequest, UA_ModifyMonitoredItemsResponse, UA_SetMonitoringModeRequest, UA_SetMonitoringModeResponse, UA_SetTriggeringRequest, UA_SetTriggeringResponse, UA_DeleteMonitoredItemsRequest, UA_DeleteMonitoredItemsResponse, UA_CreateSubscriptionRequest, UA_CreateSubscriptionResponse, UA_ModifySubscriptionRequest, UA_ModifySubscriptionResponse, UA_SetPublishingModeRequest, UA_SetPublishingModeResponse, UA_NotificationMessage, UA_MonitoredItemNotification, UA_EventFieldList, UA_HistoryEventFieldList, UA_StatusChangeNotification, UA_SubscriptionAcknowledgement, UA_PublishRequest, UA_PublishResponse, UA_RepublishRequest, UA_RepublishResponse, UA_TransferResult, UA_TransferSubscriptionsRequest, UA_TransferSubscriptionsResponse, UA_DeleteSubscriptionsRequest, UA_DeleteSubscriptionsResponse, UA_BuildInfo, UA_RedundancySupport, UA_ServerState, UA_RedundantServerDataType, UA_EndpointUrlListDataType, UA_NetworkGroupDataType, UA_SamplingIntervalDiagnosticsDataType, UA_ServerDiagnosticsSummaryDataType, UA_ServerStatusDataType, UA_SessionSecurityDiagnosticsDataType, UA_ServiceCounterDataType, UA_StatusResult, UA_SubscriptionDiagnosticsDataType, UA_ModelChangeStructureVerbMask, UA_ModelChangeStructureDataType, UA_SemanticChangeStructureDataType, UA_Range, UA_EUInformation, UA_AxisScaleEnumeration, UA_ComplexNumberType, UA_DoubleComplexNumberType, UA_AxisInformation, UA_XVType, UA_ProgramDiagnosticDataType, UA_ProgramDiagnostic2DataType, UA_Annotation, UA_ExceptionDeviationFormat, UA_EndpointType, UA_StructureDescription, UA_FieldMetaData, UA_PublishedEventsDataType, UA_PubSubGroupDataType, UA_WriterGroupDataType, UA_FieldTargetDataType, UA_SubscribedDataSetMirrorDataType, UA_SecurityGroupDataType, UA_PubSubKeyPushTargetDataType, UA_EnumDefinition, UA_ReadEventDetails, UA_ReadProcessedDetails, UA_ModificationInfo, UA_HistoryModifiedData, UA_HistoryEvent, UA_UpdateEventDetails, UA_DataChangeNotification, UA_EventNotificationList, UA_SessionDiagnosticsDataType, UA_EnumDescription, UA_UABinaryFileDataType, UA_DataSetMetaDataType, UA_PublishedDataSetDataType, UA_DataSetReaderDataType, UA_TargetVariablesDataType, UA_StandaloneSubscribedDataSetDataType, UA_DataTypeSchemaHeader, UA_ReaderGroupDataType, UA_PubSubConnectionDataType, UA_PubSubConfigurationDataType, UA_PubSubConfiguration2DataType] # Unique julia types -const unique_julia_types_ind = unique(i -> julia_types[i], eachindex(julia_types)) +const UNIQUE_JULIA_TYPES_IND = unique(i -> JULIA_TYPES[i], eachindex(JULIA_TYPES)) # Vector of types that are ambiguously defined via typedef and are not to be used as default type -types_ambiguous_ignorelist = type_names[1:end .∉ [unique_julia_types_ind]] +types_ambiguous_ignorelist = TYPE_NAMES[1:end .∉ [UNIQUE_JULIA_TYPES_IND]] # Vector of all inlined function names listed in the open62541 header files const inlined_funcs = ["UA_ClientConfig_setAuthenticationUsername", "UA_Client_getContext", "UA_Client_connect", "UA_Client_connectAsync", "UA_Client_connectSecureChannel", "UA_Client_connectSecureChannelAsync", "UA_Client_connectUsername", "UA_Client_Service_read", "UA_Client_Service_write", "UA_Client_Service_historyRead", "UA_Client_Service_historyUpdate", "UA_Client_Service_call", "UA_Client_Service_addNodes", "UA_Client_Service_addReferences", "UA_Client_Service_deleteNodes", "UA_Client_Service_deleteReferences", "UA_Client_Service_browse", "UA_Client_Service_browseNext", "UA_Client_Service_translateBrowsePathsToNodeIds", "UA_Client_Service_registerNodes", "UA_Client_Service_unregisterNodes", "UA_Client_Service_queryFirst", "UA_Client_Service_queryNext", "UA_Client_readNodeIdAttribute", "UA_Client_readNodeClassAttribute", "UA_Client_readBrowseNameAttribute", "UA_Client_readDisplayNameAttribute", "UA_Client_readDescriptionAttribute", "UA_Client_readWriteMaskAttribute", "UA_Client_readUserWriteMaskAttribute", "UA_Client_readIsAbstractAttribute", "UA_Client_readSymmetricAttribute", "UA_Client_readInverseNameAttribute", "UA_Client_readContainsNoLoopsAttribute", "UA_Client_readEventNotifierAttribute", "UA_Client_readValueAttribute", "UA_Client_readDataTypeAttribute", "UA_Client_readValueRankAttribute", "UA_Client_readAccessLevelAttribute", "UA_Client_readAccessLevelExAttribute", "UA_Client_readUserAccessLevelAttribute", "UA_Client_readMinimumSamplingIntervalAttribute", "UA_Client_readHistorizingAttribute", "UA_Client_readExecutableAttribute", "UA_Client_readUserExecutableAttribute", "UA_Client_writeNodeIdAttribute", "UA_Client_writeNodeClassAttribute", "UA_Client_writeBrowseNameAttribute", "UA_Client_writeDisplayNameAttribute", "UA_Client_writeDescriptionAttribute", "UA_Client_writeWriteMaskAttribute", "UA_Client_writeUserWriteMaskAttribute", "UA_Client_writeIsAbstractAttribute", "UA_Client_writeSymmetricAttribute", "UA_Client_writeInverseNameAttribute", "UA_Client_writeContainsNoLoopsAttribute", "UA_Client_writeEventNotifierAttribute", "UA_Client_writeValueAttribute", "UA_Client_writeValueAttribute_scalar", "UA_Client_writeValueAttributeEx", "UA_Client_writeDataTypeAttribute", "UA_Client_writeValueRankAttribute", "UA_Client_writeAccessLevelAttribute", "UA_Client_writeAccessLevelExAttribute", "UA_Client_writeUserAccessLevelAttribute", "UA_Client_writeMinimumSamplingIntervalAttribute", "UA_Client_writeHistorizingAttribute", "UA_Client_writeExecutableAttribute", "UA_Client_writeUserExecutableAttribute", "UA_Client_addVariableNode", "UA_Client_addVariableTypeNode", "UA_Client_addObjectNode", "UA_Client_addObjectTypeNode", "UA_Client_addViewNode", "UA_Client_addReferenceTypeNode", "UA_Client_addDataTypeNode", "UA_Client_addMethodNode", "UA_Client_sendAsyncReadRequest", "UA_Client_sendAsyncWriteRequest", "UA_Client_sendAsyncBrowseRequest", "UA_Client_sendAsyncBrowseNextRequest", "UA_Client_writeValueAttribute_async", "UA_Client_writeNodeIdAttribute_async", "UA_Client_writeNodeClassAttribute_async", "UA_Client_writeBrowseNameAttribute_async", "UA_Client_writeDisplayNameAttribute_async", "UA_Client_writeDescriptionAttribute_async", "UA_Client_writeWriteMaskAttribute_async", "UA_Client_writeUserWriteMaskAttribute_async", "UA_Client_writeIsAbstractAttribute_async", "UA_Client_writeSymmetricAttribute_async", "UA_Client_writeInverseNameAttribute_async", "UA_Client_writeContainsNoLoopsAttribute_async", "UA_Client_writeEventNotifierAttribute_async", "UA_Client_writeDataTypeAttribute_async", "UA_Client_writeValueRankAttribute_async", "UA_Client_writeAccessLevelAttribute_async", "UA_Client_writeAccessLevelExAttribute_async", "UA_Client_writeUserAccessLevelAttribute_async", "UA_Client_writeMinimumSamplingIntervalAttribute_async", "UA_Client_writeHistorizingAttribute_async", "UA_Client_writeExecutableAttribute_async", "UA_Client_writeUserExecutableAttribute_async", "UA_Client_call_async", "UA_Client_addVariableNode_async", "UA_Client_addVariableTypeNode_async", "UA_Client_addObjectNode_async", "UA_Client_addObjectTypeNode_async", "UA_Client_addViewNode_async", "UA_Client_addReferenceTypeNode_async", "UA_Client_addDataTypeNode_async", "UA_Client_addMethodNode_async", "UA_CreateSubscriptionRequest_default", "UA_Client_Subscriptions_setPublishingMode", "UA_MonitoredItemCreateRequest_default", "UA_Client_MonitoredItems_setMonitoringMode", "UA_Client_MonitoredItems_setMonitoringMode_async", "UA_Client_MonitoredItems_setTriggering", "UA_Client_MonitoredItems_setTriggering_async", "UA_atomic_xchg", "UA_atomic_cmpxchg", "UA_LOCK_INIT", "UA_LOCK_DESTROY", "UA_LOCK", "UA_UNLOCK", "UA_LOCK_ASSERT", "UA_LOCK_INIT", "UA_LOCK_DESTROY", "UA_LOCK", "UA_UNLOCK", "UA_LOCK_ASSERT", "UA_Server_readNodeId", "UA_Server_readNodeClass", "UA_Server_readBrowseName", "UA_Server_readDisplayName", "UA_Server_readDescription", "UA_Server_readWriteMask", "UA_Server_readIsAbstract", "UA_Server_readSymmetric", "UA_Server_readInverseName", "UA_Server_readContainsNoLoops", "UA_Server_readEventNotifier", "UA_Server_readValue", "UA_Server_readDataType", "UA_Server_readValueRank", "UA_Server_readArrayDimensions", "UA_Server_readAccessLevel", "UA_Server_readAccessLevelEx", "UA_Server_readMinimumSamplingInterval", "UA_Server_readHistorizing", "UA_Server_readExecutable", "UA_Server_writeBrowseName", "UA_Server_writeDisplayName", "UA_Server_writeDescription", "UA_Server_writeWriteMask", "UA_Server_writeIsAbstract", "UA_Server_writeInverseName", "UA_Server_writeEventNotifier", "UA_Server_writeValue", "UA_Server_writeDataValue", "UA_Server_writeDataType", "UA_Server_writeValueRank", "UA_Server_writeArrayDimensions", "UA_Server_writeAccessLevel", "UA_Server_writeAccessLevelEx", "UA_Server_writeMinimumSamplingInterval", "UA_Server_writeHistorizing", "UA_Server_writeExecutable", "UA_Server_addVariableNode", "UA_Server_addVariableTypeNode", "UA_Server_addObjectNode", "UA_Server_addObjectTypeNode", "UA_Server_addViewNode", "UA_Server_addReferenceTypeNode", "UA_Server_addDataTypeNode", "UA_Server_addMethodNode", "UA_ServerConfig_setMinimal", "UA_ServerConfig_setDefault", "UA_StatusCode_isBad", "UA_StatusCode_isUncertain", "UA_StatusCode_isGood", "UA_StatusCode_isEqualTop", "UA_STRING", "UA_DateTime_toUnixTime", "UA_DateTime_fromUnixTime", "UA_GUID", "UA_NODEID", "UA_NODEID_NUMERIC", "UA_NODEID_STRING", "UA_NODEID_STRING_ALLOC", "UA_NODEID_GUID", "UA_NODEID_BYTESTRING", "UA_NODEID_BYTESTRING_ALLOC", "UA_EXPANDEDNODEID", "UA_EXPANDEDNODEID_NUMERIC", "UA_EXPANDEDNODEID_STRING", "UA_EXPANDEDNODEID_STRING_ALLOC", "UA_EXPANDEDNODEID_STRING_GUID", "UA_EXPANDEDNODEID_BYTESTRING", "UA_EXPANDEDNODEID_BYTESTRING_ALLOC", "UA_EXPANDEDNODEID_NODEID", "UA_QualifiedName_isNull", "UA_QUALIFIEDNAME", "UA_QUALIFIEDNAME_ALLOC", "UA_LOCALIZEDTEXT", "UA_LOCALIZEDTEXT_ALLOC", "UA_NUMERICRANGE", "UA_Variant_isEmpty", "UA_Variant_isScalar", "UA_Variant_hasScalarType", "UA_Variant_hasArrayType", "UA_init", "UA_equal", "UA_Boolean_init", "UA_Boolean_new", "UA_Boolean_copy", "UA_Boolean_deleteMembers", "UA_Boolean_clear", "UA_Boolean_delete", "UA_Boolean_equal", "UA_SByte_init", "UA_SByte_new", "UA_SByte_copy", "UA_SByte_deleteMembers", "UA_SByte_clear", "UA_SByte_delete", "UA_SByte_equal", "UA_Byte_init", "UA_Byte_new", "UA_Byte_copy", "UA_Byte_deleteMembers", "UA_Byte_clear", "UA_Byte_delete", "UA_Byte_equal", "UA_Int16_init", "UA_Int16_new", "UA_Int16_copy", "UA_Int16_deleteMembers", "UA_Int16_clear", "UA_Int16_delete", "UA_Int16_equal", "UA_UInt16_init", "UA_UInt16_new", "UA_UInt16_copy", "UA_UInt16_deleteMembers", "UA_UInt16_clear", "UA_UInt16_delete", "UA_UInt16_equal", "UA_Int32_init", "UA_Int32_new", "UA_Int32_copy", "UA_Int32_deleteMembers", "UA_Int32_clear", "UA_Int32_delete", "UA_Int32_equal", "UA_UInt32_init", "UA_UInt32_new", "UA_UInt32_copy", "UA_UInt32_deleteMembers", "UA_UInt32_clear", "UA_UInt32_delete", "UA_UInt32_equal", "UA_Int64_init", "UA_Int64_new", "UA_Int64_copy", "UA_Int64_deleteMembers", "UA_Int64_clear", "UA_Int64_delete", "UA_Int64_equal", "UA_UInt64_init", "UA_UInt64_new", "UA_UInt64_copy", "UA_UInt64_deleteMembers", "UA_UInt64_clear", "UA_UInt64_delete", "UA_UInt64_equal", "UA_Float_init", "UA_Float_new", "UA_Float_copy", "UA_Float_deleteMembers", "UA_Float_clear", "UA_Float_delete", "UA_Float_equal", "UA_Double_init", "UA_Double_new", "UA_Double_copy", "UA_Double_deleteMembers", "UA_Double_clear", "UA_Double_delete", "UA_Double_equal", "UA_String_init", "UA_String_new", "UA_String_copy", "UA_String_deleteMembers", "UA_String_clear", "UA_String_delete", "UA_String_equal", "UA_DateTime_init", "UA_DateTime_new", "UA_DateTime_copy", "UA_DateTime_deleteMembers", "UA_DateTime_clear", "UA_DateTime_delete", "UA_DateTime_equal", "UA_Guid_init", "UA_Guid_new", "UA_Guid_copy", "UA_Guid_deleteMembers", "UA_Guid_clear", "UA_Guid_delete", "UA_Guid_equal", "UA_ByteString_init", "UA_ByteString_new", "UA_ByteString_copy", "UA_ByteString_deleteMembers", "UA_ByteString_clear", "UA_ByteString_delete", "UA_ByteString_equal", "UA_XmlElement_init", "UA_XmlElement_new", "UA_XmlElement_copy", "UA_XmlElement_deleteMembers", "UA_XmlElement_clear", "UA_XmlElement_delete", "UA_XmlElement_equal", "UA_NodeId_init", "UA_NodeId_new", "UA_NodeId_copy", "UA_NodeId_deleteMembers", "UA_NodeId_clear", "UA_NodeId_delete", "UA_NodeId_equal", "UA_ExpandedNodeId_init", "UA_ExpandedNodeId_new", "UA_ExpandedNodeId_copy", "UA_ExpandedNodeId_deleteMembers", "UA_ExpandedNodeId_clear", "UA_ExpandedNodeId_delete", "UA_ExpandedNodeId_equal", "UA_StatusCode_init", "UA_StatusCode_new", "UA_StatusCode_copy", "UA_StatusCode_deleteMembers", "UA_StatusCode_clear", "UA_StatusCode_delete", "UA_StatusCode_equal", "UA_QualifiedName_init", "UA_QualifiedName_new", "UA_QualifiedName_copy", "UA_QualifiedName_deleteMembers", "UA_QualifiedName_clear", "UA_QualifiedName_delete", "UA_QualifiedName_equal", "UA_LocalizedText_init", "UA_LocalizedText_new", "UA_LocalizedText_copy", "UA_LocalizedText_deleteMembers", "UA_LocalizedText_clear", "UA_LocalizedText_delete", "UA_LocalizedText_equal", "UA_ExtensionObject_init", "UA_ExtensionObject_new", "UA_ExtensionObject_copy", "UA_ExtensionObject_deleteMembers", "UA_ExtensionObject_clear", "UA_ExtensionObject_delete", "UA_ExtensionObject_equal", "UA_DataValue_init", "UA_DataValue_new", "UA_DataValue_copy", "UA_DataValue_deleteMembers", "UA_DataValue_clear", "UA_DataValue_delete", "UA_DataValue_equal", "UA_Variant_init", "UA_Variant_new", "UA_Variant_copy", "UA_Variant_deleteMembers", "UA_Variant_clear", "UA_Variant_delete", "UA_Variant_equal", "UA_DiagnosticInfo_init", "UA_DiagnosticInfo_new", "UA_DiagnosticInfo_copy", "UA_DiagnosticInfo_deleteMembers", "UA_DiagnosticInfo_clear", "UA_DiagnosticInfo_delete", "UA_DiagnosticInfo_equal", "UA_NamingRuleType_init", "UA_NamingRuleType_new", "UA_NamingRuleType_copy", "UA_NamingRuleType_deleteMembers", "UA_NamingRuleType_clear", "UA_NamingRuleType_delete", "UA_NamingRuleType_equal", "UA_Enumeration_init", "UA_Enumeration_new", "UA_Enumeration_copy", "UA_Enumeration_deleteMembers", "UA_Enumeration_clear", "UA_Enumeration_delete", "UA_Enumeration_equal", "UA_ImageBMP_init", "UA_ImageBMP_new", "UA_ImageBMP_copy", "UA_ImageBMP_deleteMembers", "UA_ImageBMP_clear", "UA_ImageBMP_delete", "UA_ImageBMP_equal", "UA_ImageGIF_init", "UA_ImageGIF_new", "UA_ImageGIF_copy", "UA_ImageGIF_deleteMembers", "UA_ImageGIF_clear", "UA_ImageGIF_delete", "UA_ImageGIF_equal", "UA_ImageJPG_init", "UA_ImageJPG_new", "UA_ImageJPG_copy", "UA_ImageJPG_deleteMembers", "UA_ImageJPG_clear", "UA_ImageJPG_delete", "UA_ImageJPG_equal", "UA_ImagePNG_init", "UA_ImagePNG_new", "UA_ImagePNG_copy", "UA_ImagePNG_deleteMembers", "UA_ImagePNG_clear", "UA_ImagePNG_delete", "UA_ImagePNG_equal", "UA_AudioDataType_init", "UA_AudioDataType_new", "UA_AudioDataType_copy", "UA_AudioDataType_deleteMembers", "UA_AudioDataType_clear", "UA_AudioDataType_delete", "UA_AudioDataType_equal", "UA_UriString_init", "UA_UriString_new", "UA_UriString_copy", "UA_UriString_deleteMembers", "UA_UriString_clear", "UA_UriString_delete", "UA_UriString_equal", "UA_BitFieldMaskDataType_init", "UA_BitFieldMaskDataType_new", "UA_BitFieldMaskDataType_copy", "UA_BitFieldMaskDataType_deleteMembers", "UA_BitFieldMaskDataType_clear", "UA_BitFieldMaskDataType_delete", "UA_BitFieldMaskDataType_equal", "UA_SemanticVersionString_init", "UA_SemanticVersionString_new", "UA_SemanticVersionString_copy", "UA_SemanticVersionString_deleteMembers", "UA_SemanticVersionString_clear", "UA_SemanticVersionString_delete", "UA_SemanticVersionString_equal", "UA_KeyValuePair_init", "UA_KeyValuePair_new", "UA_KeyValuePair_copy", "UA_KeyValuePair_deleteMembers", "UA_KeyValuePair_clear", "UA_KeyValuePair_delete", "UA_KeyValuePair_equal", "UA_AdditionalParametersType_init", "UA_AdditionalParametersType_new", "UA_AdditionalParametersType_copy", "UA_AdditionalParametersType_deleteMembers", "UA_AdditionalParametersType_clear", "UA_AdditionalParametersType_delete", "UA_AdditionalParametersType_equal", "UA_EphemeralKeyType_init", "UA_EphemeralKeyType_new", "UA_EphemeralKeyType_copy", "UA_EphemeralKeyType_deleteMembers", "UA_EphemeralKeyType_clear", "UA_EphemeralKeyType_delete", "UA_EphemeralKeyType_equal", "UA_RationalNumber_init", "UA_RationalNumber_new", "UA_RationalNumber_copy", "UA_RationalNumber_deleteMembers", "UA_RationalNumber_clear", "UA_RationalNumber_delete", "UA_RationalNumber_equal", "UA_ThreeDVector_init", "UA_ThreeDVector_new", "UA_ThreeDVector_copy", "UA_ThreeDVector_deleteMembers", "UA_ThreeDVector_clear", "UA_ThreeDVector_delete", "UA_ThreeDVector_equal", "UA_ThreeDCartesianCoordinates_init", "UA_ThreeDCartesianCoordinates_new", "UA_ThreeDCartesianCoordinates_copy", "UA_ThreeDCartesianCoordinates_deleteMembers", "UA_ThreeDCartesianCoordinates_clear", "UA_ThreeDCartesianCoordinates_delete", "UA_ThreeDCartesianCoordinates_equal", "UA_ThreeDOrientation_init", "UA_ThreeDOrientation_new", "UA_ThreeDOrientation_copy", "UA_ThreeDOrientation_deleteMembers", "UA_ThreeDOrientation_clear", "UA_ThreeDOrientation_delete", "UA_ThreeDOrientation_equal", "UA_ThreeDFrame_init", "UA_ThreeDFrame_new", "UA_ThreeDFrame_copy", "UA_ThreeDFrame_deleteMembers", "UA_ThreeDFrame_clear", "UA_ThreeDFrame_delete", "UA_ThreeDFrame_equal", "UA_OpenFileMode_init", "UA_OpenFileMode_new", "UA_OpenFileMode_copy", "UA_OpenFileMode_deleteMembers", "UA_OpenFileMode_clear", "UA_OpenFileMode_delete", "UA_OpenFileMode_equal", "UA_IdentityCriteriaType_init", "UA_IdentityCriteriaType_new", "UA_IdentityCriteriaType_copy", "UA_IdentityCriteriaType_deleteMembers", "UA_IdentityCriteriaType_clear", "UA_IdentityCriteriaType_delete", "UA_IdentityCriteriaType_equal", "UA_IdentityMappingRuleType_init", "UA_IdentityMappingRuleType_new", "UA_IdentityMappingRuleType_copy", "UA_IdentityMappingRuleType_deleteMembers", "UA_IdentityMappingRuleType_clear", "UA_IdentityMappingRuleType_delete", "UA_IdentityMappingRuleType_equal", "UA_CurrencyUnitType_init", "UA_CurrencyUnitType_new", "UA_CurrencyUnitType_copy", "UA_CurrencyUnitType_deleteMembers", "UA_CurrencyUnitType_clear", "UA_CurrencyUnitType_delete", "UA_CurrencyUnitType_equal", "UA_TrustListMasks_init", "UA_TrustListMasks_new", "UA_TrustListMasks_copy", "UA_TrustListMasks_deleteMembers", "UA_TrustListMasks_clear", "UA_TrustListMasks_delete", "UA_TrustListMasks_equal", "UA_TrustListDataType_init", "UA_TrustListDataType_new", "UA_TrustListDataType_copy", "UA_TrustListDataType_deleteMembers", "UA_TrustListDataType_clear", "UA_TrustListDataType_delete", "UA_TrustListDataType_equal", "UA_DecimalDataType_init", "UA_DecimalDataType_new", "UA_DecimalDataType_copy", "UA_DecimalDataType_deleteMembers", "UA_DecimalDataType_clear", "UA_DecimalDataType_delete", "UA_DecimalDataType_equal", "UA_DataTypeDescription_init", "UA_DataTypeDescription_new", "UA_DataTypeDescription_copy", "UA_DataTypeDescription_deleteMembers", "UA_DataTypeDescription_clear", "UA_DataTypeDescription_delete", "UA_DataTypeDescription_equal", "UA_SimpleTypeDescription_init", "UA_SimpleTypeDescription_new", "UA_SimpleTypeDescription_copy", "UA_SimpleTypeDescription_deleteMembers", "UA_SimpleTypeDescription_clear", "UA_SimpleTypeDescription_delete", "UA_SimpleTypeDescription_equal", "UA_PortableQualifiedName_init", "UA_PortableQualifiedName_new", "UA_PortableQualifiedName_copy", "UA_PortableQualifiedName_deleteMembers", "UA_PortableQualifiedName_clear", "UA_PortableQualifiedName_delete", "UA_PortableQualifiedName_equal", "UA_PortableNodeId_init", "UA_PortableNodeId_new", "UA_PortableNodeId_copy", "UA_PortableNodeId_deleteMembers", "UA_PortableNodeId_clear", "UA_PortableNodeId_delete", "UA_PortableNodeId_equal", "UA_UnsignedRationalNumber_init", "UA_UnsignedRationalNumber_new", "UA_UnsignedRationalNumber_copy", "UA_UnsignedRationalNumber_deleteMembers", "UA_UnsignedRationalNumber_clear", "UA_UnsignedRationalNumber_delete", "UA_UnsignedRationalNumber_equal", "UA_PubSubState_init", "UA_PubSubState_new", "UA_PubSubState_copy", "UA_PubSubState_deleteMembers", "UA_PubSubState_clear", "UA_PubSubState_delete", "UA_PubSubState_equal", "UA_DataSetFieldFlags_init", "UA_DataSetFieldFlags_new", "UA_DataSetFieldFlags_copy", "UA_DataSetFieldFlags_deleteMembers", "UA_DataSetFieldFlags_clear", "UA_DataSetFieldFlags_delete", "UA_DataSetFieldFlags_equal", "UA_ConfigurationVersionDataType_init", "UA_ConfigurationVersionDataType_new", "UA_ConfigurationVersionDataType_copy", "UA_ConfigurationVersionDataType_deleteMembers", "UA_ConfigurationVersionDataType_clear", "UA_ConfigurationVersionDataType_delete", "UA_ConfigurationVersionDataType_equal", "UA_PublishedVariableDataType_init", "UA_PublishedVariableDataType_new", "UA_PublishedVariableDataType_copy", "UA_PublishedVariableDataType_deleteMembers", "UA_PublishedVariableDataType_clear", "UA_PublishedVariableDataType_delete", "UA_PublishedVariableDataType_equal", "UA_PublishedDataItemsDataType_init", "UA_PublishedDataItemsDataType_new", "UA_PublishedDataItemsDataType_copy", "UA_PublishedDataItemsDataType_deleteMembers", "UA_PublishedDataItemsDataType_clear", "UA_PublishedDataItemsDataType_delete", "UA_PublishedDataItemsDataType_equal", "UA_PublishedDataSetCustomSourceDataType_init", "UA_PublishedDataSetCustomSourceDataType_new", "UA_PublishedDataSetCustomSourceDataType_copy", "UA_PublishedDataSetCustomSourceDataType_deleteMembers", "UA_PublishedDataSetCustomSourceDataType_clear", "UA_PublishedDataSetCustomSourceDataType_delete", "UA_PublishedDataSetCustomSourceDataType_equal", "UA_DataSetFieldContentMask_init", "UA_DataSetFieldContentMask_new", "UA_DataSetFieldContentMask_copy", "UA_DataSetFieldContentMask_deleteMembers", "UA_DataSetFieldContentMask_clear", "UA_DataSetFieldContentMask_delete", "UA_DataSetFieldContentMask_equal", "UA_DataSetWriterDataType_init", "UA_DataSetWriterDataType_new", "UA_DataSetWriterDataType_copy", "UA_DataSetWriterDataType_deleteMembers", "UA_DataSetWriterDataType_clear", "UA_DataSetWriterDataType_delete", "UA_DataSetWriterDataType_equal", "UA_NetworkAddressDataType_init", "UA_NetworkAddressDataType_new", "UA_NetworkAddressDataType_copy", "UA_NetworkAddressDataType_deleteMembers", "UA_NetworkAddressDataType_clear", "UA_NetworkAddressDataType_delete", "UA_NetworkAddressDataType_equal", "UA_NetworkAddressUrlDataType_init", "UA_NetworkAddressUrlDataType_new", "UA_NetworkAddressUrlDataType_copy", "UA_NetworkAddressUrlDataType_deleteMembers", "UA_NetworkAddressUrlDataType_clear", "UA_NetworkAddressUrlDataType_delete", "UA_NetworkAddressUrlDataType_equal", "UA_OverrideValueHandling_init", "UA_OverrideValueHandling_new", "UA_OverrideValueHandling_copy", "UA_OverrideValueHandling_deleteMembers", "UA_OverrideValueHandling_clear", "UA_OverrideValueHandling_delete", "UA_OverrideValueHandling_equal", "UA_StandaloneSubscribedDataSetRefDataType_init", "UA_StandaloneSubscribedDataSetRefDataType_new", "UA_StandaloneSubscribedDataSetRefDataType_copy", "UA_StandaloneSubscribedDataSetRefDataType_deleteMembers", "UA_StandaloneSubscribedDataSetRefDataType_clear", "UA_StandaloneSubscribedDataSetRefDataType_delete", "UA_StandaloneSubscribedDataSetRefDataType_equal", "UA_DataSetOrderingType_init", "UA_DataSetOrderingType_new", "UA_DataSetOrderingType_copy", "UA_DataSetOrderingType_deleteMembers", "UA_DataSetOrderingType_clear", "UA_DataSetOrderingType_delete", "UA_DataSetOrderingType_equal", "UA_UadpNetworkMessageContentMask_init", "UA_UadpNetworkMessageContentMask_new", "UA_UadpNetworkMessageContentMask_copy", "UA_UadpNetworkMessageContentMask_deleteMembers", "UA_UadpNetworkMessageContentMask_clear", "UA_UadpNetworkMessageContentMask_delete", "UA_UadpNetworkMessageContentMask_equal", "UA_UadpWriterGroupMessageDataType_init", "UA_UadpWriterGroupMessageDataType_new", "UA_UadpWriterGroupMessageDataType_copy", "UA_UadpWriterGroupMessageDataType_deleteMembers", "UA_UadpWriterGroupMessageDataType_clear", "UA_UadpWriterGroupMessageDataType_delete", "UA_UadpWriterGroupMessageDataType_equal", "UA_UadpDataSetMessageContentMask_init", "UA_UadpDataSetMessageContentMask_new", "UA_UadpDataSetMessageContentMask_copy", "UA_UadpDataSetMessageContentMask_deleteMembers", "UA_UadpDataSetMessageContentMask_clear", "UA_UadpDataSetMessageContentMask_delete", "UA_UadpDataSetMessageContentMask_equal", "UA_UadpDataSetWriterMessageDataType_init", "UA_UadpDataSetWriterMessageDataType_new", "UA_UadpDataSetWriterMessageDataType_copy", "UA_UadpDataSetWriterMessageDataType_deleteMembers", "UA_UadpDataSetWriterMessageDataType_clear", "UA_UadpDataSetWriterMessageDataType_delete", "UA_UadpDataSetWriterMessageDataType_equal", "UA_UadpDataSetReaderMessageDataType_init", "UA_UadpDataSetReaderMessageDataType_new", "UA_UadpDataSetReaderMessageDataType_copy", "UA_UadpDataSetReaderMessageDataType_deleteMembers", "UA_UadpDataSetReaderMessageDataType_clear", "UA_UadpDataSetReaderMessageDataType_delete", "UA_UadpDataSetReaderMessageDataType_equal", "UA_JsonNetworkMessageContentMask_init", "UA_JsonNetworkMessageContentMask_new", "UA_JsonNetworkMessageContentMask_copy", "UA_JsonNetworkMessageContentMask_deleteMembers", "UA_JsonNetworkMessageContentMask_clear", "UA_JsonNetworkMessageContentMask_delete", "UA_JsonNetworkMessageContentMask_equal", "UA_JsonWriterGroupMessageDataType_init", "UA_JsonWriterGroupMessageDataType_new", "UA_JsonWriterGroupMessageDataType_copy", "UA_JsonWriterGroupMessageDataType_deleteMembers", "UA_JsonWriterGroupMessageDataType_clear", "UA_JsonWriterGroupMessageDataType_delete", "UA_JsonWriterGroupMessageDataType_equal", "UA_JsonDataSetMessageContentMask_init", "UA_JsonDataSetMessageContentMask_new", "UA_JsonDataSetMessageContentMask_copy", "UA_JsonDataSetMessageContentMask_deleteMembers", "UA_JsonDataSetMessageContentMask_clear", "UA_JsonDataSetMessageContentMask_delete", "UA_JsonDataSetMessageContentMask_equal", "UA_JsonDataSetWriterMessageDataType_init", "UA_JsonDataSetWriterMessageDataType_new", "UA_JsonDataSetWriterMessageDataType_copy", "UA_JsonDataSetWriterMessageDataType_deleteMembers", "UA_JsonDataSetWriterMessageDataType_clear", "UA_JsonDataSetWriterMessageDataType_delete", "UA_JsonDataSetWriterMessageDataType_equal", "UA_JsonDataSetReaderMessageDataType_init", "UA_JsonDataSetReaderMessageDataType_new", "UA_JsonDataSetReaderMessageDataType_copy", "UA_JsonDataSetReaderMessageDataType_deleteMembers", "UA_JsonDataSetReaderMessageDataType_clear", "UA_JsonDataSetReaderMessageDataType_delete", "UA_JsonDataSetReaderMessageDataType_equal", "UA_TransmitQosPriorityDataType_init", "UA_TransmitQosPriorityDataType_new", "UA_TransmitQosPriorityDataType_copy", "UA_TransmitQosPriorityDataType_deleteMembers", "UA_TransmitQosPriorityDataType_clear", "UA_TransmitQosPriorityDataType_delete", "UA_TransmitQosPriorityDataType_equal", "UA_ReceiveQosPriorityDataType_init", "UA_ReceiveQosPriorityDataType_new", "UA_ReceiveQosPriorityDataType_copy", "UA_ReceiveQosPriorityDataType_deleteMembers", "UA_ReceiveQosPriorityDataType_clear", "UA_ReceiveQosPriorityDataType_delete", "UA_ReceiveQosPriorityDataType_equal", "UA_DatagramConnectionTransportDataType_init", "UA_DatagramConnectionTransportDataType_new", "UA_DatagramConnectionTransportDataType_copy", "UA_DatagramConnectionTransportDataType_deleteMembers", "UA_DatagramConnectionTransportDataType_clear", "UA_DatagramConnectionTransportDataType_delete", "UA_DatagramConnectionTransportDataType_equal", "UA_DatagramConnectionTransport2DataType_init", "UA_DatagramConnectionTransport2DataType_new", "UA_DatagramConnectionTransport2DataType_copy", "UA_DatagramConnectionTransport2DataType_deleteMembers", "UA_DatagramConnectionTransport2DataType_clear", "UA_DatagramConnectionTransport2DataType_delete", "UA_DatagramConnectionTransport2DataType_equal", "UA_DatagramWriterGroupTransportDataType_init", "UA_DatagramWriterGroupTransportDataType_new", "UA_DatagramWriterGroupTransportDataType_copy", "UA_DatagramWriterGroupTransportDataType_deleteMembers", "UA_DatagramWriterGroupTransportDataType_clear", "UA_DatagramWriterGroupTransportDataType_delete", "UA_DatagramWriterGroupTransportDataType_equal", "UA_DatagramWriterGroupTransport2DataType_init", "UA_DatagramWriterGroupTransport2DataType_new", "UA_DatagramWriterGroupTransport2DataType_copy", "UA_DatagramWriterGroupTransport2DataType_deleteMembers", "UA_DatagramWriterGroupTransport2DataType_clear", "UA_DatagramWriterGroupTransport2DataType_delete", "UA_DatagramWriterGroupTransport2DataType_equal", "UA_DatagramDataSetReaderTransportDataType_init", "UA_DatagramDataSetReaderTransportDataType_new", "UA_DatagramDataSetReaderTransportDataType_copy", "UA_DatagramDataSetReaderTransportDataType_deleteMembers", "UA_DatagramDataSetReaderTransportDataType_clear", "UA_DatagramDataSetReaderTransportDataType_delete", "UA_DatagramDataSetReaderTransportDataType_equal", "UA_BrokerConnectionTransportDataType_init", "UA_BrokerConnectionTransportDataType_new", "UA_BrokerConnectionTransportDataType_copy", "UA_BrokerConnectionTransportDataType_deleteMembers", "UA_BrokerConnectionTransportDataType_clear", "UA_BrokerConnectionTransportDataType_delete", "UA_BrokerConnectionTransportDataType_equal", "UA_BrokerTransportQualityOfService_init", "UA_BrokerTransportQualityOfService_new", "UA_BrokerTransportQualityOfService_copy", "UA_BrokerTransportQualityOfService_deleteMembers", "UA_BrokerTransportQualityOfService_clear", "UA_BrokerTransportQualityOfService_delete", "UA_BrokerTransportQualityOfService_equal", "UA_BrokerWriterGroupTransportDataType_init", "UA_BrokerWriterGroupTransportDataType_new", "UA_BrokerWriterGroupTransportDataType_copy", "UA_BrokerWriterGroupTransportDataType_deleteMembers", "UA_BrokerWriterGroupTransportDataType_clear", "UA_BrokerWriterGroupTransportDataType_delete", "UA_BrokerWriterGroupTransportDataType_equal", "UA_BrokerDataSetWriterTransportDataType_init", "UA_BrokerDataSetWriterTransportDataType_new", "UA_BrokerDataSetWriterTransportDataType_copy", "UA_BrokerDataSetWriterTransportDataType_deleteMembers", "UA_BrokerDataSetWriterTransportDataType_clear", "UA_BrokerDataSetWriterTransportDataType_delete", "UA_BrokerDataSetWriterTransportDataType_equal", "UA_BrokerDataSetReaderTransportDataType_init", "UA_BrokerDataSetReaderTransportDataType_new", "UA_BrokerDataSetReaderTransportDataType_copy", "UA_BrokerDataSetReaderTransportDataType_deleteMembers", "UA_BrokerDataSetReaderTransportDataType_clear", "UA_BrokerDataSetReaderTransportDataType_delete", "UA_BrokerDataSetReaderTransportDataType_equal", "UA_PubSubConfigurationRefMask_init", "UA_PubSubConfigurationRefMask_new", "UA_PubSubConfigurationRefMask_copy", "UA_PubSubConfigurationRefMask_deleteMembers", "UA_PubSubConfigurationRefMask_clear", "UA_PubSubConfigurationRefMask_delete", "UA_PubSubConfigurationRefMask_equal", "UA_PubSubConfigurationRefDataType_init", "UA_PubSubConfigurationRefDataType_new", "UA_PubSubConfigurationRefDataType_copy", "UA_PubSubConfigurationRefDataType_deleteMembers", "UA_PubSubConfigurationRefDataType_clear", "UA_PubSubConfigurationRefDataType_delete", "UA_PubSubConfigurationRefDataType_equal", "UA_PubSubConfigurationValueDataType_init", "UA_PubSubConfigurationValueDataType_new", "UA_PubSubConfigurationValueDataType_copy", "UA_PubSubConfigurationValueDataType_deleteMembers", "UA_PubSubConfigurationValueDataType_clear", "UA_PubSubConfigurationValueDataType_delete", "UA_PubSubConfigurationValueDataType_equal", "UA_DiagnosticsLevel_init", "UA_DiagnosticsLevel_new", "UA_DiagnosticsLevel_copy", "UA_DiagnosticsLevel_deleteMembers", "UA_DiagnosticsLevel_clear", "UA_DiagnosticsLevel_delete", "UA_DiagnosticsLevel_equal", "UA_PubSubDiagnosticsCounterClassification_init", "UA_PubSubDiagnosticsCounterClassification_new", "UA_PubSubDiagnosticsCounterClassification_copy", "UA_PubSubDiagnosticsCounterClassification_deleteMembers", "UA_PubSubDiagnosticsCounterClassification_clear", "UA_PubSubDiagnosticsCounterClassification_delete", "UA_PubSubDiagnosticsCounterClassification_equal", "UA_AliasNameDataType_init", "UA_AliasNameDataType_new", "UA_AliasNameDataType_copy", "UA_AliasNameDataType_deleteMembers", "UA_AliasNameDataType_clear", "UA_AliasNameDataType_delete", "UA_AliasNameDataType_equal", "UA_PasswordOptionsMask_init", "UA_PasswordOptionsMask_new", "UA_PasswordOptionsMask_copy", "UA_PasswordOptionsMask_deleteMembers", "UA_PasswordOptionsMask_clear", "UA_PasswordOptionsMask_delete", "UA_PasswordOptionsMask_equal", "UA_UserConfigurationMask_init", "UA_UserConfigurationMask_new", "UA_UserConfigurationMask_copy", "UA_UserConfigurationMask_deleteMembers", "UA_UserConfigurationMask_clear", "UA_UserConfigurationMask_delete", "UA_UserConfigurationMask_equal", "UA_UserManagementDataType_init", "UA_UserManagementDataType_new", "UA_UserManagementDataType_copy", "UA_UserManagementDataType_deleteMembers", "UA_UserManagementDataType_clear", "UA_UserManagementDataType_delete", "UA_UserManagementDataType_equal", "UA_Duplex_init", "UA_Duplex_new", "UA_Duplex_copy", "UA_Duplex_deleteMembers", "UA_Duplex_clear", "UA_Duplex_delete", "UA_Duplex_equal", "UA_InterfaceAdminStatus_init", "UA_InterfaceAdminStatus_new", "UA_InterfaceAdminStatus_copy", "UA_InterfaceAdminStatus_deleteMembers", "UA_InterfaceAdminStatus_clear", "UA_InterfaceAdminStatus_delete", "UA_InterfaceAdminStatus_equal", "UA_InterfaceOperStatus_init", "UA_InterfaceOperStatus_new", "UA_InterfaceOperStatus_copy", "UA_InterfaceOperStatus_deleteMembers", "UA_InterfaceOperStatus_clear", "UA_InterfaceOperStatus_delete", "UA_InterfaceOperStatus_equal", "UA_NegotiationStatus_init", "UA_NegotiationStatus_new", "UA_NegotiationStatus_copy", "UA_NegotiationStatus_deleteMembers", "UA_NegotiationStatus_clear", "UA_NegotiationStatus_delete", "UA_NegotiationStatus_equal", "UA_TsnFailureCode_init", "UA_TsnFailureCode_new", "UA_TsnFailureCode_copy", "UA_TsnFailureCode_deleteMembers", "UA_TsnFailureCode_clear", "UA_TsnFailureCode_delete", "UA_TsnFailureCode_equal", "UA_TsnStreamState_init", "UA_TsnStreamState_new", "UA_TsnStreamState_copy", "UA_TsnStreamState_deleteMembers", "UA_TsnStreamState_clear", "UA_TsnStreamState_delete", "UA_TsnStreamState_equal", "UA_TsnTalkerStatus_init", "UA_TsnTalkerStatus_new", "UA_TsnTalkerStatus_copy", "UA_TsnTalkerStatus_deleteMembers", "UA_TsnTalkerStatus_clear", "UA_TsnTalkerStatus_delete", "UA_TsnTalkerStatus_equal", "UA_TsnListenerStatus_init", "UA_TsnListenerStatus_new", "UA_TsnListenerStatus_copy", "UA_TsnListenerStatus_deleteMembers", "UA_TsnListenerStatus_clear", "UA_TsnListenerStatus_delete", "UA_TsnListenerStatus_equal", "UA_PriorityMappingEntryType_init", "UA_PriorityMappingEntryType_new", "UA_PriorityMappingEntryType_copy", "UA_PriorityMappingEntryType_deleteMembers", "UA_PriorityMappingEntryType_clear", "UA_PriorityMappingEntryType_delete", "UA_PriorityMappingEntryType_equal", "UA_IdType_init", "UA_IdType_new", "UA_IdType_copy", "UA_IdType_deleteMembers", "UA_IdType_clear", "UA_IdType_delete", "UA_IdType_equal", "UA_NodeClass_init", "UA_NodeClass_new", "UA_NodeClass_copy", "UA_NodeClass_deleteMembers", "UA_NodeClass_clear", "UA_NodeClass_delete", "UA_NodeClass_equal", "UA_PermissionType_init", "UA_PermissionType_new", "UA_PermissionType_copy", "UA_PermissionType_deleteMembers", "UA_PermissionType_clear", "UA_PermissionType_delete", "UA_PermissionType_equal", "UA_AccessLevelType_init", "UA_AccessLevelType_new", "UA_AccessLevelType_copy", "UA_AccessLevelType_deleteMembers", "UA_AccessLevelType_clear", "UA_AccessLevelType_delete", "UA_AccessLevelType_equal", "UA_AccessLevelExType_init", "UA_AccessLevelExType_new", "UA_AccessLevelExType_copy", "UA_AccessLevelExType_deleteMembers", "UA_AccessLevelExType_clear", "UA_AccessLevelExType_delete", "UA_AccessLevelExType_equal", "UA_EventNotifierType_init", "UA_EventNotifierType_new", "UA_EventNotifierType_copy", "UA_EventNotifierType_deleteMembers", "UA_EventNotifierType_clear", "UA_EventNotifierType_delete", "UA_EventNotifierType_equal", "UA_AccessRestrictionType_init", "UA_AccessRestrictionType_new", "UA_AccessRestrictionType_copy", "UA_AccessRestrictionType_deleteMembers", "UA_AccessRestrictionType_clear", "UA_AccessRestrictionType_delete", "UA_AccessRestrictionType_equal", "UA_RolePermissionType_init", "UA_RolePermissionType_new", "UA_RolePermissionType_copy", "UA_RolePermissionType_deleteMembers", "UA_RolePermissionType_clear", "UA_RolePermissionType_delete", "UA_RolePermissionType_equal", "UA_StructureType_init", "UA_StructureType_new", "UA_StructureType_copy", "UA_StructureType_deleteMembers", "UA_StructureType_clear", "UA_StructureType_delete", "UA_StructureType_equal", "UA_StructureField_init", "UA_StructureField_new", "UA_StructureField_copy", "UA_StructureField_deleteMembers", "UA_StructureField_clear", "UA_StructureField_delete", "UA_StructureField_equal", "UA_StructureDefinition_init", "UA_StructureDefinition_new", "UA_StructureDefinition_copy", "UA_StructureDefinition_deleteMembers", "UA_StructureDefinition_clear", "UA_StructureDefinition_delete", "UA_StructureDefinition_equal", "UA_ReferenceNode_init", "UA_ReferenceNode_new", "UA_ReferenceNode_copy", "UA_ReferenceNode_deleteMembers", "UA_ReferenceNode_clear", "UA_ReferenceNode_delete", "UA_ReferenceNode_equal", "UA_Argument_init", "UA_Argument_new", "UA_Argument_copy", "UA_Argument_deleteMembers", "UA_Argument_clear", "UA_Argument_delete", "UA_Argument_equal", "UA_EnumValueType_init", "UA_EnumValueType_new", "UA_EnumValueType_copy", "UA_EnumValueType_deleteMembers", "UA_EnumValueType_clear", "UA_EnumValueType_delete", "UA_EnumValueType_equal", "UA_EnumField_init", "UA_EnumField_new", "UA_EnumField_copy", "UA_EnumField_deleteMembers", "UA_EnumField_clear", "UA_EnumField_delete", "UA_EnumField_equal", "UA_OptionSet_init", "UA_OptionSet_new", "UA_OptionSet_copy", "UA_OptionSet_deleteMembers", "UA_OptionSet_clear", "UA_OptionSet_delete", "UA_OptionSet_equal", "UA_NormalizedString_init", "UA_NormalizedString_new", "UA_NormalizedString_copy", "UA_NormalizedString_deleteMembers", "UA_NormalizedString_clear", "UA_NormalizedString_delete", "UA_NormalizedString_equal", "UA_DecimalString_init", "UA_DecimalString_new", "UA_DecimalString_copy", "UA_DecimalString_deleteMembers", "UA_DecimalString_clear", "UA_DecimalString_delete", "UA_DecimalString_equal", "UA_DurationString_init", "UA_DurationString_new", "UA_DurationString_copy", "UA_DurationString_deleteMembers", "UA_DurationString_clear", "UA_DurationString_delete", "UA_DurationString_equal", "UA_TimeString_init", "UA_TimeString_new", "UA_TimeString_copy", "UA_TimeString_deleteMembers", "UA_TimeString_clear", "UA_TimeString_delete", "UA_TimeString_equal", "UA_DateString_init", "UA_DateString_new", "UA_DateString_copy", "UA_DateString_deleteMembers", "UA_DateString_clear", "UA_DateString_delete", "UA_DateString_equal", "UA_Duration_init", "UA_Duration_new", "UA_Duration_copy", "UA_Duration_deleteMembers", "UA_Duration_clear", "UA_Duration_delete", "UA_Duration_equal", "UA_UtcTime_init", "UA_UtcTime_new", "UA_UtcTime_copy", "UA_UtcTime_deleteMembers", "UA_UtcTime_clear", "UA_UtcTime_delete", "UA_UtcTime_equal", "UA_LocaleId_init", "UA_LocaleId_new", "UA_LocaleId_copy", "UA_LocaleId_deleteMembers", "UA_LocaleId_clear", "UA_LocaleId_delete", "UA_LocaleId_equal", "UA_TimeZoneDataType_init", "UA_TimeZoneDataType_new", "UA_TimeZoneDataType_copy", "UA_TimeZoneDataType_deleteMembers", "UA_TimeZoneDataType_clear", "UA_TimeZoneDataType_delete", "UA_TimeZoneDataType_equal", "UA_Index_init", "UA_Index_new", "UA_Index_copy", "UA_Index_deleteMembers", "UA_Index_clear", "UA_Index_delete", "UA_Index_equal", "UA_IntegerId_init", "UA_IntegerId_new", "UA_IntegerId_copy", "UA_IntegerId_deleteMembers", "UA_IntegerId_clear", "UA_IntegerId_delete", "UA_IntegerId_equal", "UA_ApplicationType_init", "UA_ApplicationType_new", "UA_ApplicationType_copy", "UA_ApplicationType_deleteMembers", "UA_ApplicationType_clear", "UA_ApplicationType_delete", "UA_ApplicationType_equal", "UA_ApplicationDescription_init", "UA_ApplicationDescription_new", "UA_ApplicationDescription_copy", "UA_ApplicationDescription_deleteMembers", "UA_ApplicationDescription_clear", "UA_ApplicationDescription_delete", "UA_ApplicationDescription_equal", "UA_RequestHeader_init", "UA_RequestHeader_new", "UA_RequestHeader_copy", "UA_RequestHeader_deleteMembers", "UA_RequestHeader_clear", "UA_RequestHeader_delete", "UA_RequestHeader_equal", "UA_ResponseHeader_init", "UA_ResponseHeader_new", "UA_ResponseHeader_copy", "UA_ResponseHeader_deleteMembers", "UA_ResponseHeader_clear", "UA_ResponseHeader_delete", "UA_ResponseHeader_equal", "UA_VersionTime_init", "UA_VersionTime_new", "UA_VersionTime_copy", "UA_VersionTime_deleteMembers", "UA_VersionTime_clear", "UA_VersionTime_delete", "UA_VersionTime_equal", "UA_ServiceFault_init", "UA_ServiceFault_new", "UA_ServiceFault_copy", "UA_ServiceFault_deleteMembers", "UA_ServiceFault_clear", "UA_ServiceFault_delete", "UA_ServiceFault_equal", "UA_SessionlessInvokeRequestType_init", "UA_SessionlessInvokeRequestType_new", "UA_SessionlessInvokeRequestType_copy", "UA_SessionlessInvokeRequestType_deleteMembers", "UA_SessionlessInvokeRequestType_clear", "UA_SessionlessInvokeRequestType_delete", "UA_SessionlessInvokeRequestType_equal", "UA_SessionlessInvokeResponseType_init", "UA_SessionlessInvokeResponseType_new", "UA_SessionlessInvokeResponseType_copy", "UA_SessionlessInvokeResponseType_deleteMembers", "UA_SessionlessInvokeResponseType_clear", "UA_SessionlessInvokeResponseType_delete", "UA_SessionlessInvokeResponseType_equal", "UA_FindServersRequest_init", "UA_FindServersRequest_new", "UA_FindServersRequest_copy", "UA_FindServersRequest_deleteMembers", "UA_FindServersRequest_clear", "UA_FindServersRequest_delete", "UA_FindServersRequest_equal", "UA_FindServersResponse_init", "UA_FindServersResponse_new", "UA_FindServersResponse_copy", "UA_FindServersResponse_deleteMembers", "UA_FindServersResponse_clear", "UA_FindServersResponse_delete", "UA_FindServersResponse_equal", "UA_ServerOnNetwork_init", "UA_ServerOnNetwork_new", "UA_ServerOnNetwork_copy", "UA_ServerOnNetwork_deleteMembers", "UA_ServerOnNetwork_clear", "UA_ServerOnNetwork_delete", "UA_ServerOnNetwork_equal", "UA_FindServersOnNetworkRequest_init", "UA_FindServersOnNetworkRequest_new", "UA_FindServersOnNetworkRequest_copy", "UA_FindServersOnNetworkRequest_deleteMembers", "UA_FindServersOnNetworkRequest_clear", "UA_FindServersOnNetworkRequest_delete", "UA_FindServersOnNetworkRequest_equal", "UA_FindServersOnNetworkResponse_init", "UA_FindServersOnNetworkResponse_new", "UA_FindServersOnNetworkResponse_copy", "UA_FindServersOnNetworkResponse_deleteMembers", "UA_FindServersOnNetworkResponse_clear", "UA_FindServersOnNetworkResponse_delete", "UA_FindServersOnNetworkResponse_equal", "UA_ApplicationInstanceCertificate_init", "UA_ApplicationInstanceCertificate_new", "UA_ApplicationInstanceCertificate_copy", "UA_ApplicationInstanceCertificate_deleteMembers", "UA_ApplicationInstanceCertificate_clear", "UA_ApplicationInstanceCertificate_delete", "UA_ApplicationInstanceCertificate_equal", "UA_MessageSecurityMode_init", "UA_MessageSecurityMode_new", "UA_MessageSecurityMode_copy", "UA_MessageSecurityMode_deleteMembers", "UA_MessageSecurityMode_clear", "UA_MessageSecurityMode_delete", "UA_MessageSecurityMode_equal", "UA_UserTokenType_init", "UA_UserTokenType_new", "UA_UserTokenType_copy", "UA_UserTokenType_deleteMembers", "UA_UserTokenType_clear", "UA_UserTokenType_delete", "UA_UserTokenType_equal", "UA_UserTokenPolicy_init", "UA_UserTokenPolicy_new", "UA_UserTokenPolicy_copy", "UA_UserTokenPolicy_deleteMembers", "UA_UserTokenPolicy_clear", "UA_UserTokenPolicy_delete", "UA_UserTokenPolicy_equal", "UA_EndpointDescription_init", "UA_EndpointDescription_new", "UA_EndpointDescription_copy", "UA_EndpointDescription_deleteMembers", "UA_EndpointDescription_clear", "UA_EndpointDescription_delete", "UA_EndpointDescription_equal", "UA_GetEndpointsRequest_init", "UA_GetEndpointsRequest_new", "UA_GetEndpointsRequest_copy", "UA_GetEndpointsRequest_deleteMembers", "UA_GetEndpointsRequest_clear", "UA_GetEndpointsRequest_delete", "UA_GetEndpointsRequest_equal", "UA_GetEndpointsResponse_init", "UA_GetEndpointsResponse_new", "UA_GetEndpointsResponse_copy", "UA_GetEndpointsResponse_deleteMembers", "UA_GetEndpointsResponse_clear", "UA_GetEndpointsResponse_delete", "UA_GetEndpointsResponse_equal", "UA_RegisteredServer_init", "UA_RegisteredServer_new", "UA_RegisteredServer_copy", "UA_RegisteredServer_deleteMembers", "UA_RegisteredServer_clear", "UA_RegisteredServer_delete", "UA_RegisteredServer_equal", "UA_RegisterServerRequest_init", "UA_RegisterServerRequest_new", "UA_RegisterServerRequest_copy", "UA_RegisterServerRequest_deleteMembers", "UA_RegisterServerRequest_clear", "UA_RegisterServerRequest_delete", "UA_RegisterServerRequest_equal", "UA_RegisterServerResponse_init", "UA_RegisterServerResponse_new", "UA_RegisterServerResponse_copy", "UA_RegisterServerResponse_deleteMembers", "UA_RegisterServerResponse_clear", "UA_RegisterServerResponse_delete", "UA_RegisterServerResponse_equal", "UA_MdnsDiscoveryConfiguration_init", "UA_MdnsDiscoveryConfiguration_new", "UA_MdnsDiscoveryConfiguration_copy", "UA_MdnsDiscoveryConfiguration_deleteMembers", "UA_MdnsDiscoveryConfiguration_clear", "UA_MdnsDiscoveryConfiguration_delete", "UA_MdnsDiscoveryConfiguration_equal", "UA_RegisterServer2Request_init", "UA_RegisterServer2Request_new", "UA_RegisterServer2Request_copy", "UA_RegisterServer2Request_deleteMembers", "UA_RegisterServer2Request_clear", "UA_RegisterServer2Request_delete", "UA_RegisterServer2Request_equal", "UA_RegisterServer2Response_init", "UA_RegisterServer2Response_new", "UA_RegisterServer2Response_copy", "UA_RegisterServer2Response_deleteMembers", "UA_RegisterServer2Response_clear", "UA_RegisterServer2Response_delete", "UA_RegisterServer2Response_equal", "UA_SecurityTokenRequestType_init", "UA_SecurityTokenRequestType_new", "UA_SecurityTokenRequestType_copy", "UA_SecurityTokenRequestType_deleteMembers", "UA_SecurityTokenRequestType_clear", "UA_SecurityTokenRequestType_delete", "UA_SecurityTokenRequestType_equal", "UA_ChannelSecurityToken_init", "UA_ChannelSecurityToken_new", "UA_ChannelSecurityToken_copy", "UA_ChannelSecurityToken_deleteMembers", "UA_ChannelSecurityToken_clear", "UA_ChannelSecurityToken_delete", "UA_ChannelSecurityToken_equal", "UA_OpenSecureChannelRequest_init", "UA_OpenSecureChannelRequest_new", "UA_OpenSecureChannelRequest_copy", "UA_OpenSecureChannelRequest_deleteMembers", "UA_OpenSecureChannelRequest_clear", "UA_OpenSecureChannelRequest_delete", "UA_OpenSecureChannelRequest_equal", "UA_OpenSecureChannelResponse_init", "UA_OpenSecureChannelResponse_new", "UA_OpenSecureChannelResponse_copy", "UA_OpenSecureChannelResponse_deleteMembers", "UA_OpenSecureChannelResponse_clear", "UA_OpenSecureChannelResponse_delete", "UA_OpenSecureChannelResponse_equal", "UA_CloseSecureChannelRequest_init", "UA_CloseSecureChannelRequest_new", "UA_CloseSecureChannelRequest_copy", "UA_CloseSecureChannelRequest_deleteMembers", "UA_CloseSecureChannelRequest_clear", "UA_CloseSecureChannelRequest_delete", "UA_CloseSecureChannelRequest_equal", "UA_CloseSecureChannelResponse_init", "UA_CloseSecureChannelResponse_new", "UA_CloseSecureChannelResponse_copy", "UA_CloseSecureChannelResponse_deleteMembers", "UA_CloseSecureChannelResponse_clear", "UA_CloseSecureChannelResponse_delete", "UA_CloseSecureChannelResponse_equal", "UA_SignedSoftwareCertificate_init", "UA_SignedSoftwareCertificate_new", "UA_SignedSoftwareCertificate_copy", "UA_SignedSoftwareCertificate_deleteMembers", "UA_SignedSoftwareCertificate_clear", "UA_SignedSoftwareCertificate_delete", "UA_SignedSoftwareCertificate_equal", "UA_SessionAuthenticationToken_init", "UA_SessionAuthenticationToken_new", "UA_SessionAuthenticationToken_copy", "UA_SessionAuthenticationToken_deleteMembers", "UA_SessionAuthenticationToken_clear", "UA_SessionAuthenticationToken_delete", "UA_SessionAuthenticationToken_equal", "UA_SignatureData_init", "UA_SignatureData_new", "UA_SignatureData_copy", "UA_SignatureData_deleteMembers", "UA_SignatureData_clear", "UA_SignatureData_delete", "UA_SignatureData_equal", "UA_CreateSessionRequest_init", "UA_CreateSessionRequest_new", "UA_CreateSessionRequest_copy", "UA_CreateSessionRequest_deleteMembers", "UA_CreateSessionRequest_clear", "UA_CreateSessionRequest_delete", "UA_CreateSessionRequest_equal", "UA_CreateSessionResponse_init", "UA_CreateSessionResponse_new", "UA_CreateSessionResponse_copy", "UA_CreateSessionResponse_deleteMembers", "UA_CreateSessionResponse_clear", "UA_CreateSessionResponse_delete", "UA_CreateSessionResponse_equal", "UA_UserIdentityToken_init", "UA_UserIdentityToken_new", "UA_UserIdentityToken_copy", "UA_UserIdentityToken_deleteMembers", "UA_UserIdentityToken_clear", "UA_UserIdentityToken_delete", "UA_UserIdentityToken_equal", "UA_AnonymousIdentityToken_init", "UA_AnonymousIdentityToken_new", "UA_AnonymousIdentityToken_copy", "UA_AnonymousIdentityToken_deleteMembers", "UA_AnonymousIdentityToken_clear", "UA_AnonymousIdentityToken_delete", "UA_AnonymousIdentityToken_equal", "UA_UserNameIdentityToken_init", "UA_UserNameIdentityToken_new", "UA_UserNameIdentityToken_copy", "UA_UserNameIdentityToken_deleteMembers", "UA_UserNameIdentityToken_clear", "UA_UserNameIdentityToken_delete", "UA_UserNameIdentityToken_equal", "UA_X509IdentityToken_init", "UA_X509IdentityToken_new", "UA_X509IdentityToken_copy", "UA_X509IdentityToken_deleteMembers", "UA_X509IdentityToken_clear", "UA_X509IdentityToken_delete", "UA_X509IdentityToken_equal", "UA_IssuedIdentityToken_init", "UA_IssuedIdentityToken_new", "UA_IssuedIdentityToken_copy", "UA_IssuedIdentityToken_deleteMembers", "UA_IssuedIdentityToken_clear", "UA_IssuedIdentityToken_delete", "UA_IssuedIdentityToken_equal", "UA_RsaEncryptedSecret_init", "UA_RsaEncryptedSecret_new", "UA_RsaEncryptedSecret_copy", "UA_RsaEncryptedSecret_deleteMembers", "UA_RsaEncryptedSecret_clear", "UA_RsaEncryptedSecret_delete", "UA_RsaEncryptedSecret_equal", "UA_EccEncryptedSecret_init", "UA_EccEncryptedSecret_new", "UA_EccEncryptedSecret_copy", "UA_EccEncryptedSecret_deleteMembers", "UA_EccEncryptedSecret_clear", "UA_EccEncryptedSecret_delete", "UA_EccEncryptedSecret_equal", "UA_ActivateSessionRequest_init", "UA_ActivateSessionRequest_new", "UA_ActivateSessionRequest_copy", "UA_ActivateSessionRequest_deleteMembers", "UA_ActivateSessionRequest_clear", "UA_ActivateSessionRequest_delete", "UA_ActivateSessionRequest_equal", "UA_ActivateSessionResponse_init", "UA_ActivateSessionResponse_new", "UA_ActivateSessionResponse_copy", "UA_ActivateSessionResponse_deleteMembers", "UA_ActivateSessionResponse_clear", "UA_ActivateSessionResponse_delete", "UA_ActivateSessionResponse_equal", "UA_CloseSessionRequest_init", "UA_CloseSessionRequest_new", "UA_CloseSessionRequest_copy", "UA_CloseSessionRequest_deleteMembers", "UA_CloseSessionRequest_clear", "UA_CloseSessionRequest_delete", "UA_CloseSessionRequest_equal", "UA_CloseSessionResponse_init", "UA_CloseSessionResponse_new", "UA_CloseSessionResponse_copy", "UA_CloseSessionResponse_deleteMembers", "UA_CloseSessionResponse_clear", "UA_CloseSessionResponse_delete", "UA_CloseSessionResponse_equal", "UA_CancelRequest_init", "UA_CancelRequest_new", "UA_CancelRequest_copy", "UA_CancelRequest_deleteMembers", "UA_CancelRequest_clear", "UA_CancelRequest_delete", "UA_CancelRequest_equal", "UA_CancelResponse_init", "UA_CancelResponse_new", "UA_CancelResponse_copy", "UA_CancelResponse_deleteMembers", "UA_CancelResponse_clear", "UA_CancelResponse_delete", "UA_CancelResponse_equal", "UA_NodeAttributesMask_init", "UA_NodeAttributesMask_new", "UA_NodeAttributesMask_copy", "UA_NodeAttributesMask_deleteMembers", "UA_NodeAttributesMask_clear", "UA_NodeAttributesMask_delete", "UA_NodeAttributesMask_equal", "UA_NodeAttributes_init", "UA_NodeAttributes_new", "UA_NodeAttributes_copy", "UA_NodeAttributes_deleteMembers", "UA_NodeAttributes_clear", "UA_NodeAttributes_delete", "UA_NodeAttributes_equal", "UA_ObjectAttributes_init", "UA_ObjectAttributes_new", "UA_ObjectAttributes_copy", "UA_ObjectAttributes_deleteMembers", "UA_ObjectAttributes_clear", "UA_ObjectAttributes_delete", "UA_ObjectAttributes_equal", "UA_VariableAttributes_init", "UA_VariableAttributes_new", "UA_VariableAttributes_copy", "UA_VariableAttributes_deleteMembers", "UA_VariableAttributes_clear", "UA_VariableAttributes_delete", "UA_VariableAttributes_equal", "UA_MethodAttributes_init", "UA_MethodAttributes_new", "UA_MethodAttributes_copy", "UA_MethodAttributes_deleteMembers", "UA_MethodAttributes_clear", "UA_MethodAttributes_delete", "UA_MethodAttributes_equal", "UA_ObjectTypeAttributes_init", "UA_ObjectTypeAttributes_new", "UA_ObjectTypeAttributes_copy", "UA_ObjectTypeAttributes_deleteMembers", "UA_ObjectTypeAttributes_clear", "UA_ObjectTypeAttributes_delete", "UA_ObjectTypeAttributes_equal", "UA_VariableTypeAttributes_init", "UA_VariableTypeAttributes_new", "UA_VariableTypeAttributes_copy", "UA_VariableTypeAttributes_deleteMembers", "UA_VariableTypeAttributes_clear", "UA_VariableTypeAttributes_delete", "UA_VariableTypeAttributes_equal", "UA_ReferenceTypeAttributes_init", "UA_ReferenceTypeAttributes_new", "UA_ReferenceTypeAttributes_copy", "UA_ReferenceTypeAttributes_deleteMembers", "UA_ReferenceTypeAttributes_clear", "UA_ReferenceTypeAttributes_delete", "UA_ReferenceTypeAttributes_equal", "UA_DataTypeAttributes_init", "UA_DataTypeAttributes_new", "UA_DataTypeAttributes_copy", "UA_DataTypeAttributes_deleteMembers", "UA_DataTypeAttributes_clear", "UA_DataTypeAttributes_delete", "UA_DataTypeAttributes_equal", "UA_ViewAttributes_init", "UA_ViewAttributes_new", "UA_ViewAttributes_copy", "UA_ViewAttributes_deleteMembers", "UA_ViewAttributes_clear", "UA_ViewAttributes_delete", "UA_ViewAttributes_equal", "UA_GenericAttributeValue_init", "UA_GenericAttributeValue_new", "UA_GenericAttributeValue_copy", "UA_GenericAttributeValue_deleteMembers", "UA_GenericAttributeValue_clear", "UA_GenericAttributeValue_delete", "UA_GenericAttributeValue_equal", "UA_GenericAttributes_init", "UA_GenericAttributes_new", "UA_GenericAttributes_copy", "UA_GenericAttributes_deleteMembers", "UA_GenericAttributes_clear", "UA_GenericAttributes_delete", "UA_GenericAttributes_equal", "UA_AddNodesItem_init", "UA_AddNodesItem_new", "UA_AddNodesItem_copy", "UA_AddNodesItem_deleteMembers", "UA_AddNodesItem_clear", "UA_AddNodesItem_delete", "UA_AddNodesItem_equal", "UA_AddNodesResult_init", "UA_AddNodesResult_new", "UA_AddNodesResult_copy", "UA_AddNodesResult_deleteMembers", "UA_AddNodesResult_clear", "UA_AddNodesResult_delete", "UA_AddNodesResult_equal", "UA_AddNodesRequest_init", "UA_AddNodesRequest_new", "UA_AddNodesRequest_copy", "UA_AddNodesRequest_deleteMembers", "UA_AddNodesRequest_clear", "UA_AddNodesRequest_delete", "UA_AddNodesRequest_equal", "UA_AddNodesResponse_init", "UA_AddNodesResponse_new", "UA_AddNodesResponse_copy", "UA_AddNodesResponse_deleteMembers", "UA_AddNodesResponse_clear", "UA_AddNodesResponse_delete", "UA_AddNodesResponse_equal", "UA_AddReferencesItem_init", "UA_AddReferencesItem_new", "UA_AddReferencesItem_copy", "UA_AddReferencesItem_deleteMembers", "UA_AddReferencesItem_clear", "UA_AddReferencesItem_delete", "UA_AddReferencesItem_equal", "UA_AddReferencesRequest_init", "UA_AddReferencesRequest_new", "UA_AddReferencesRequest_copy", "UA_AddReferencesRequest_deleteMembers", "UA_AddReferencesRequest_clear", "UA_AddReferencesRequest_delete", "UA_AddReferencesRequest_equal", "UA_AddReferencesResponse_init", "UA_AddReferencesResponse_new", "UA_AddReferencesResponse_copy", "UA_AddReferencesResponse_deleteMembers", "UA_AddReferencesResponse_clear", "UA_AddReferencesResponse_delete", "UA_AddReferencesResponse_equal", "UA_DeleteNodesItem_init", "UA_DeleteNodesItem_new", "UA_DeleteNodesItem_copy", "UA_DeleteNodesItem_deleteMembers", "UA_DeleteNodesItem_clear", "UA_DeleteNodesItem_delete", "UA_DeleteNodesItem_equal", "UA_DeleteNodesRequest_init", "UA_DeleteNodesRequest_new", "UA_DeleteNodesRequest_copy", "UA_DeleteNodesRequest_deleteMembers", "UA_DeleteNodesRequest_clear", "UA_DeleteNodesRequest_delete", "UA_DeleteNodesRequest_equal", "UA_DeleteNodesResponse_init", "UA_DeleteNodesResponse_new", "UA_DeleteNodesResponse_copy", "UA_DeleteNodesResponse_deleteMembers", "UA_DeleteNodesResponse_clear", "UA_DeleteNodesResponse_delete", "UA_DeleteNodesResponse_equal", "UA_DeleteReferencesItem_init", "UA_DeleteReferencesItem_new", "UA_DeleteReferencesItem_copy", "UA_DeleteReferencesItem_deleteMembers", "UA_DeleteReferencesItem_clear", "UA_DeleteReferencesItem_delete", "UA_DeleteReferencesItem_equal", "UA_DeleteReferencesRequest_init", "UA_DeleteReferencesRequest_new", "UA_DeleteReferencesRequest_copy", "UA_DeleteReferencesRequest_deleteMembers", "UA_DeleteReferencesRequest_clear", "UA_DeleteReferencesRequest_delete", "UA_DeleteReferencesRequest_equal", "UA_DeleteReferencesResponse_init", "UA_DeleteReferencesResponse_new", "UA_DeleteReferencesResponse_copy", "UA_DeleteReferencesResponse_deleteMembers", "UA_DeleteReferencesResponse_clear", "UA_DeleteReferencesResponse_delete", "UA_DeleteReferencesResponse_equal", "UA_AttributeWriteMask_init", "UA_AttributeWriteMask_new", "UA_AttributeWriteMask_copy", "UA_AttributeWriteMask_deleteMembers", "UA_AttributeWriteMask_clear", "UA_AttributeWriteMask_delete", "UA_AttributeWriteMask_equal", "UA_BrowseDirection_init", "UA_BrowseDirection_new", "UA_BrowseDirection_copy", "UA_BrowseDirection_deleteMembers", "UA_BrowseDirection_clear", "UA_BrowseDirection_delete", "UA_BrowseDirection_equal", "UA_ViewDescription_init", "UA_ViewDescription_new", "UA_ViewDescription_copy", "UA_ViewDescription_deleteMembers", "UA_ViewDescription_clear", "UA_ViewDescription_delete", "UA_ViewDescription_equal", "UA_BrowseDescription_init", "UA_BrowseDescription_new", "UA_BrowseDescription_copy", "UA_BrowseDescription_deleteMembers", "UA_BrowseDescription_clear", "UA_BrowseDescription_delete", "UA_BrowseDescription_equal", "UA_BrowseResultMask_init", "UA_BrowseResultMask_new", "UA_BrowseResultMask_copy", "UA_BrowseResultMask_deleteMembers", "UA_BrowseResultMask_clear", "UA_BrowseResultMask_delete", "UA_BrowseResultMask_equal", "UA_ReferenceDescription_init", "UA_ReferenceDescription_new", "UA_ReferenceDescription_copy", "UA_ReferenceDescription_deleteMembers", "UA_ReferenceDescription_clear", "UA_ReferenceDescription_delete", "UA_ReferenceDescription_equal", "UA_ContinuationPoint_init", "UA_ContinuationPoint_new", "UA_ContinuationPoint_copy", "UA_ContinuationPoint_deleteMembers", "UA_ContinuationPoint_clear", "UA_ContinuationPoint_delete", "UA_ContinuationPoint_equal", "UA_BrowseResult_init", "UA_BrowseResult_new", "UA_BrowseResult_copy", "UA_BrowseResult_deleteMembers", "UA_BrowseResult_clear", "UA_BrowseResult_delete", "UA_BrowseResult_equal", "UA_BrowseRequest_init", "UA_BrowseRequest_new", "UA_BrowseRequest_copy", "UA_BrowseRequest_deleteMembers", "UA_BrowseRequest_clear", "UA_BrowseRequest_delete", "UA_BrowseRequest_equal", "UA_BrowseResponse_init", "UA_BrowseResponse_new", "UA_BrowseResponse_copy", "UA_BrowseResponse_deleteMembers", "UA_BrowseResponse_clear", "UA_BrowseResponse_delete", "UA_BrowseResponse_equal", "UA_BrowseNextRequest_init", "UA_BrowseNextRequest_new", "UA_BrowseNextRequest_copy", "UA_BrowseNextRequest_deleteMembers", "UA_BrowseNextRequest_clear", "UA_BrowseNextRequest_delete", "UA_BrowseNextRequest_equal", "UA_BrowseNextResponse_init", "UA_BrowseNextResponse_new", "UA_BrowseNextResponse_copy", "UA_BrowseNextResponse_deleteMembers", "UA_BrowseNextResponse_clear", "UA_BrowseNextResponse_delete", "UA_BrowseNextResponse_equal", "UA_RelativePathElement_init", "UA_RelativePathElement_new", "UA_RelativePathElement_copy", "UA_RelativePathElement_deleteMembers", "UA_RelativePathElement_clear", "UA_RelativePathElement_delete", "UA_RelativePathElement_equal", "UA_RelativePath_init", "UA_RelativePath_new", "UA_RelativePath_copy", "UA_RelativePath_deleteMembers", "UA_RelativePath_clear", "UA_RelativePath_delete", "UA_RelativePath_equal", "UA_BrowsePath_init", "UA_BrowsePath_new", "UA_BrowsePath_copy", "UA_BrowsePath_deleteMembers", "UA_BrowsePath_clear", "UA_BrowsePath_delete", "UA_BrowsePath_equal", "UA_BrowsePathTarget_init", "UA_BrowsePathTarget_new", "UA_BrowsePathTarget_copy", "UA_BrowsePathTarget_deleteMembers", "UA_BrowsePathTarget_clear", "UA_BrowsePathTarget_delete", "UA_BrowsePathTarget_equal", "UA_BrowsePathResult_init", "UA_BrowsePathResult_new", "UA_BrowsePathResult_copy", "UA_BrowsePathResult_deleteMembers", "UA_BrowsePathResult_clear", "UA_BrowsePathResult_delete", "UA_BrowsePathResult_equal", "UA_TranslateBrowsePathsToNodeIdsRequest_init", "UA_TranslateBrowsePathsToNodeIdsRequest_new", "UA_TranslateBrowsePathsToNodeIdsRequest_copy", "UA_TranslateBrowsePathsToNodeIdsRequest_deleteMembers", "UA_TranslateBrowsePathsToNodeIdsRequest_clear", "UA_TranslateBrowsePathsToNodeIdsRequest_delete", "UA_TranslateBrowsePathsToNodeIdsRequest_equal", "UA_TranslateBrowsePathsToNodeIdsResponse_init", "UA_TranslateBrowsePathsToNodeIdsResponse_new", "UA_TranslateBrowsePathsToNodeIdsResponse_copy", "UA_TranslateBrowsePathsToNodeIdsResponse_deleteMembers", "UA_TranslateBrowsePathsToNodeIdsResponse_clear", "UA_TranslateBrowsePathsToNodeIdsResponse_delete", "UA_TranslateBrowsePathsToNodeIdsResponse_equal", "UA_RegisterNodesRequest_init", "UA_RegisterNodesRequest_new", "UA_RegisterNodesRequest_copy", "UA_RegisterNodesRequest_deleteMembers", "UA_RegisterNodesRequest_clear", "UA_RegisterNodesRequest_delete", "UA_RegisterNodesRequest_equal", "UA_RegisterNodesResponse_init", "UA_RegisterNodesResponse_new", "UA_RegisterNodesResponse_copy", "UA_RegisterNodesResponse_deleteMembers", "UA_RegisterNodesResponse_clear", "UA_RegisterNodesResponse_delete", "UA_RegisterNodesResponse_equal", "UA_UnregisterNodesRequest_init", "UA_UnregisterNodesRequest_new", "UA_UnregisterNodesRequest_copy", "UA_UnregisterNodesRequest_deleteMembers", "UA_UnregisterNodesRequest_clear", "UA_UnregisterNodesRequest_delete", "UA_UnregisterNodesRequest_equal", "UA_UnregisterNodesResponse_init", "UA_UnregisterNodesResponse_new", "UA_UnregisterNodesResponse_copy", "UA_UnregisterNodesResponse_deleteMembers", "UA_UnregisterNodesResponse_clear", "UA_UnregisterNodesResponse_delete", "UA_UnregisterNodesResponse_equal", "UA_Counter_init", "UA_Counter_new", "UA_Counter_copy", "UA_Counter_deleteMembers", "UA_Counter_clear", "UA_Counter_delete", "UA_Counter_equal", "UA_OpaqueNumericRange_init", "UA_OpaqueNumericRange_new", "UA_OpaqueNumericRange_copy", "UA_OpaqueNumericRange_deleteMembers", "UA_OpaqueNumericRange_clear", "UA_OpaqueNumericRange_delete", "UA_OpaqueNumericRange_equal", "UA_EndpointConfiguration_init", "UA_EndpointConfiguration_new", "UA_EndpointConfiguration_copy", "UA_EndpointConfiguration_deleteMembers", "UA_EndpointConfiguration_clear", "UA_EndpointConfiguration_delete", "UA_EndpointConfiguration_equal", "UA_QueryDataDescription_init", "UA_QueryDataDescription_new", "UA_QueryDataDescription_copy", "UA_QueryDataDescription_deleteMembers", "UA_QueryDataDescription_clear", "UA_QueryDataDescription_delete", "UA_QueryDataDescription_equal", "UA_NodeTypeDescription_init", "UA_NodeTypeDescription_new", "UA_NodeTypeDescription_copy", "UA_NodeTypeDescription_deleteMembers", "UA_NodeTypeDescription_clear", "UA_NodeTypeDescription_delete", "UA_NodeTypeDescription_equal", "UA_FilterOperator_init", "UA_FilterOperator_new", "UA_FilterOperator_copy", "UA_FilterOperator_deleteMembers", "UA_FilterOperator_clear", "UA_FilterOperator_delete", "UA_FilterOperator_equal", "UA_QueryDataSet_init", "UA_QueryDataSet_new", "UA_QueryDataSet_copy", "UA_QueryDataSet_deleteMembers", "UA_QueryDataSet_clear", "UA_QueryDataSet_delete", "UA_QueryDataSet_equal", "UA_NodeReference_init", "UA_NodeReference_new", "UA_NodeReference_copy", "UA_NodeReference_deleteMembers", "UA_NodeReference_clear", "UA_NodeReference_delete", "UA_NodeReference_equal", "UA_ContentFilterElement_init", "UA_ContentFilterElement_new", "UA_ContentFilterElement_copy", "UA_ContentFilterElement_deleteMembers", "UA_ContentFilterElement_clear", "UA_ContentFilterElement_delete", "UA_ContentFilterElement_equal", "UA_ContentFilter_init", "UA_ContentFilter_new", "UA_ContentFilter_copy", "UA_ContentFilter_deleteMembers", "UA_ContentFilter_clear", "UA_ContentFilter_delete", "UA_ContentFilter_equal", "UA_ElementOperand_init", "UA_ElementOperand_new", "UA_ElementOperand_copy", "UA_ElementOperand_deleteMembers", "UA_ElementOperand_clear", "UA_ElementOperand_delete", "UA_ElementOperand_equal", "UA_LiteralOperand_init", "UA_LiteralOperand_new", "UA_LiteralOperand_copy", "UA_LiteralOperand_deleteMembers", "UA_LiteralOperand_clear", "UA_LiteralOperand_delete", "UA_LiteralOperand_equal", "UA_AttributeOperand_init", "UA_AttributeOperand_new", "UA_AttributeOperand_copy", "UA_AttributeOperand_deleteMembers", "UA_AttributeOperand_clear", "UA_AttributeOperand_delete", "UA_AttributeOperand_equal", "UA_SimpleAttributeOperand_init", "UA_SimpleAttributeOperand_new", "UA_SimpleAttributeOperand_copy", "UA_SimpleAttributeOperand_deleteMembers", "UA_SimpleAttributeOperand_clear", "UA_SimpleAttributeOperand_delete", "UA_SimpleAttributeOperand_equal", "UA_ContentFilterElementResult_init", "UA_ContentFilterElementResult_new", "UA_ContentFilterElementResult_copy", "UA_ContentFilterElementResult_deleteMembers", "UA_ContentFilterElementResult_clear", "UA_ContentFilterElementResult_delete", "UA_ContentFilterElementResult_equal", "UA_ContentFilterResult_init", "UA_ContentFilterResult_new", "UA_ContentFilterResult_copy", "UA_ContentFilterResult_deleteMembers", "UA_ContentFilterResult_clear", "UA_ContentFilterResult_delete", "UA_ContentFilterResult_equal", "UA_ParsingResult_init", "UA_ParsingResult_new", "UA_ParsingResult_copy", "UA_ParsingResult_deleteMembers", "UA_ParsingResult_clear", "UA_ParsingResult_delete", "UA_ParsingResult_equal", "UA_QueryFirstRequest_init", "UA_QueryFirstRequest_new", "UA_QueryFirstRequest_copy", "UA_QueryFirstRequest_deleteMembers", "UA_QueryFirstRequest_clear", "UA_QueryFirstRequest_delete", "UA_QueryFirstRequest_equal", "UA_QueryFirstResponse_init", "UA_QueryFirstResponse_new", "UA_QueryFirstResponse_copy", "UA_QueryFirstResponse_deleteMembers", "UA_QueryFirstResponse_clear", "UA_QueryFirstResponse_delete", "UA_QueryFirstResponse_equal", "UA_QueryNextRequest_init", "UA_QueryNextRequest_new", "UA_QueryNextRequest_copy", "UA_QueryNextRequest_deleteMembers", "UA_QueryNextRequest_clear", "UA_QueryNextRequest_delete", "UA_QueryNextRequest_equal", "UA_QueryNextResponse_init", "UA_QueryNextResponse_new", "UA_QueryNextResponse_copy", "UA_QueryNextResponse_deleteMembers", "UA_QueryNextResponse_clear", "UA_QueryNextResponse_delete", "UA_QueryNextResponse_equal", "UA_TimestampsToReturn_init", "UA_TimestampsToReturn_new", "UA_TimestampsToReturn_copy", "UA_TimestampsToReturn_deleteMembers", "UA_TimestampsToReturn_clear", "UA_TimestampsToReturn_delete", "UA_TimestampsToReturn_equal", "UA_ReadValueId_init", "UA_ReadValueId_new", "UA_ReadValueId_copy", "UA_ReadValueId_deleteMembers", "UA_ReadValueId_clear", "UA_ReadValueId_delete", "UA_ReadValueId_equal", "UA_ReadRequest_init", "UA_ReadRequest_new", "UA_ReadRequest_copy", "UA_ReadRequest_deleteMembers", "UA_ReadRequest_clear", "UA_ReadRequest_delete", "UA_ReadRequest_equal", "UA_ReadResponse_init", "UA_ReadResponse_new", "UA_ReadResponse_copy", "UA_ReadResponse_deleteMembers", "UA_ReadResponse_clear", "UA_ReadResponse_delete", "UA_ReadResponse_equal", "UA_HistoryReadValueId_init", "UA_HistoryReadValueId_new", "UA_HistoryReadValueId_copy", "UA_HistoryReadValueId_deleteMembers", "UA_HistoryReadValueId_clear", "UA_HistoryReadValueId_delete", "UA_HistoryReadValueId_equal", "UA_HistoryReadResult_init", "UA_HistoryReadResult_new", "UA_HistoryReadResult_copy", "UA_HistoryReadResult_deleteMembers", "UA_HistoryReadResult_clear", "UA_HistoryReadResult_delete", "UA_HistoryReadResult_equal", "UA_ReadRawModifiedDetails_init", "UA_ReadRawModifiedDetails_new", "UA_ReadRawModifiedDetails_copy", "UA_ReadRawModifiedDetails_deleteMembers", "UA_ReadRawModifiedDetails_clear", "UA_ReadRawModifiedDetails_delete", "UA_ReadRawModifiedDetails_equal", "UA_ReadAtTimeDetails_init", "UA_ReadAtTimeDetails_new", "UA_ReadAtTimeDetails_copy", "UA_ReadAtTimeDetails_deleteMembers", "UA_ReadAtTimeDetails_clear", "UA_ReadAtTimeDetails_delete", "UA_ReadAtTimeDetails_equal", "UA_ReadAnnotationDataDetails_init", "UA_ReadAnnotationDataDetails_new", "UA_ReadAnnotationDataDetails_copy", "UA_ReadAnnotationDataDetails_deleteMembers", "UA_ReadAnnotationDataDetails_clear", "UA_ReadAnnotationDataDetails_delete", "UA_ReadAnnotationDataDetails_equal", "UA_HistoryData_init", "UA_HistoryData_new", "UA_HistoryData_copy", "UA_HistoryData_deleteMembers", "UA_HistoryData_clear", "UA_HistoryData_delete", "UA_HistoryData_equal", "UA_HistoryReadRequest_init", "UA_HistoryReadRequest_new", "UA_HistoryReadRequest_copy", "UA_HistoryReadRequest_deleteMembers", "UA_HistoryReadRequest_clear", "UA_HistoryReadRequest_delete", "UA_HistoryReadRequest_equal", "UA_HistoryReadResponse_init", "UA_HistoryReadResponse_new", "UA_HistoryReadResponse_copy", "UA_HistoryReadResponse_deleteMembers", "UA_HistoryReadResponse_clear", "UA_HistoryReadResponse_delete", "UA_HistoryReadResponse_equal", "UA_WriteValue_init", "UA_WriteValue_new", "UA_WriteValue_copy", "UA_WriteValue_deleteMembers", "UA_WriteValue_clear", "UA_WriteValue_delete", "UA_WriteValue_equal", "UA_WriteRequest_init", "UA_WriteRequest_new", "UA_WriteRequest_copy", "UA_WriteRequest_deleteMembers", "UA_WriteRequest_clear", "UA_WriteRequest_delete", "UA_WriteRequest_equal", "UA_WriteResponse_init", "UA_WriteResponse_new", "UA_WriteResponse_copy", "UA_WriteResponse_deleteMembers", "UA_WriteResponse_clear", "UA_WriteResponse_delete", "UA_WriteResponse_equal", "UA_HistoryUpdateDetails_init", "UA_HistoryUpdateDetails_new", "UA_HistoryUpdateDetails_copy", "UA_HistoryUpdateDetails_deleteMembers", "UA_HistoryUpdateDetails_clear", "UA_HistoryUpdateDetails_delete", "UA_HistoryUpdateDetails_equal", "UA_HistoryUpdateType_init", "UA_HistoryUpdateType_new", "UA_HistoryUpdateType_copy", "UA_HistoryUpdateType_deleteMembers", "UA_HistoryUpdateType_clear", "UA_HistoryUpdateType_delete", "UA_HistoryUpdateType_equal", "UA_PerformUpdateType_init", "UA_PerformUpdateType_new", "UA_PerformUpdateType_copy", "UA_PerformUpdateType_deleteMembers", "UA_PerformUpdateType_clear", "UA_PerformUpdateType_delete", "UA_PerformUpdateType_equal", "UA_UpdateDataDetails_init", "UA_UpdateDataDetails_new", "UA_UpdateDataDetails_copy", "UA_UpdateDataDetails_deleteMembers", "UA_UpdateDataDetails_clear", "UA_UpdateDataDetails_delete", "UA_UpdateDataDetails_equal", "UA_UpdateStructureDataDetails_init", "UA_UpdateStructureDataDetails_new", "UA_UpdateStructureDataDetails_copy", "UA_UpdateStructureDataDetails_deleteMembers", "UA_UpdateStructureDataDetails_clear", "UA_UpdateStructureDataDetails_delete", "UA_UpdateStructureDataDetails_equal", "UA_DeleteRawModifiedDetails_init", "UA_DeleteRawModifiedDetails_new", "UA_DeleteRawModifiedDetails_copy", "UA_DeleteRawModifiedDetails_deleteMembers", "UA_DeleteRawModifiedDetails_clear", "UA_DeleteRawModifiedDetails_delete", "UA_DeleteRawModifiedDetails_equal", "UA_DeleteAtTimeDetails_init", "UA_DeleteAtTimeDetails_new", "UA_DeleteAtTimeDetails_copy", "UA_DeleteAtTimeDetails_deleteMembers", "UA_DeleteAtTimeDetails_clear", "UA_DeleteAtTimeDetails_delete", "UA_DeleteAtTimeDetails_equal", "UA_DeleteEventDetails_init", "UA_DeleteEventDetails_new", "UA_DeleteEventDetails_copy", "UA_DeleteEventDetails_deleteMembers", "UA_DeleteEventDetails_clear", "UA_DeleteEventDetails_delete", "UA_DeleteEventDetails_equal", "UA_HistoryUpdateResult_init", "UA_HistoryUpdateResult_new", "UA_HistoryUpdateResult_copy", "UA_HistoryUpdateResult_deleteMembers", "UA_HistoryUpdateResult_clear", "UA_HistoryUpdateResult_delete", "UA_HistoryUpdateResult_equal", "UA_HistoryUpdateRequest_init", "UA_HistoryUpdateRequest_new", "UA_HistoryUpdateRequest_copy", "UA_HistoryUpdateRequest_deleteMembers", "UA_HistoryUpdateRequest_clear", "UA_HistoryUpdateRequest_delete", "UA_HistoryUpdateRequest_equal", "UA_HistoryUpdateResponse_init", "UA_HistoryUpdateResponse_new", "UA_HistoryUpdateResponse_copy", "UA_HistoryUpdateResponse_deleteMembers", "UA_HistoryUpdateResponse_clear", "UA_HistoryUpdateResponse_delete", "UA_HistoryUpdateResponse_equal", "UA_CallMethodRequest_init", "UA_CallMethodRequest_new", "UA_CallMethodRequest_copy", "UA_CallMethodRequest_deleteMembers", "UA_CallMethodRequest_clear", "UA_CallMethodRequest_delete", "UA_CallMethodRequest_equal", "UA_CallMethodResult_init", "UA_CallMethodResult_new", "UA_CallMethodResult_copy", "UA_CallMethodResult_deleteMembers", "UA_CallMethodResult_clear", "UA_CallMethodResult_delete", "UA_CallMethodResult_equal", "UA_CallRequest_init", "UA_CallRequest_new", "UA_CallRequest_copy", "UA_CallRequest_deleteMembers", "UA_CallRequest_clear", "UA_CallRequest_delete", "UA_CallRequest_equal", "UA_CallResponse_init", "UA_CallResponse_new", "UA_CallResponse_copy", "UA_CallResponse_deleteMembers", "UA_CallResponse_clear", "UA_CallResponse_delete", "UA_CallResponse_equal", "UA_MonitoringMode_init", "UA_MonitoringMode_new", "UA_MonitoringMode_copy", "UA_MonitoringMode_deleteMembers", "UA_MonitoringMode_clear", "UA_MonitoringMode_delete", "UA_MonitoringMode_equal", "UA_DataChangeTrigger_init", "UA_DataChangeTrigger_new", "UA_DataChangeTrigger_copy", "UA_DataChangeTrigger_deleteMembers", "UA_DataChangeTrigger_clear", "UA_DataChangeTrigger_delete", "UA_DataChangeTrigger_equal", "UA_DeadbandType_init", "UA_DeadbandType_new", "UA_DeadbandType_copy", "UA_DeadbandType_deleteMembers", "UA_DeadbandType_clear", "UA_DeadbandType_delete", "UA_DeadbandType_equal", "UA_DataChangeFilter_init", "UA_DataChangeFilter_new", "UA_DataChangeFilter_copy", "UA_DataChangeFilter_deleteMembers", "UA_DataChangeFilter_clear", "UA_DataChangeFilter_delete", "UA_DataChangeFilter_equal", "UA_EventFilter_init", "UA_EventFilter_new", "UA_EventFilter_copy", "UA_EventFilter_deleteMembers", "UA_EventFilter_clear", "UA_EventFilter_delete", "UA_EventFilter_equal", "UA_AggregateConfiguration_init", "UA_AggregateConfiguration_new", "UA_AggregateConfiguration_copy", "UA_AggregateConfiguration_deleteMembers", "UA_AggregateConfiguration_clear", "UA_AggregateConfiguration_delete", "UA_AggregateConfiguration_equal", "UA_AggregateFilter_init", "UA_AggregateFilter_new", "UA_AggregateFilter_copy", "UA_AggregateFilter_deleteMembers", "UA_AggregateFilter_clear", "UA_AggregateFilter_delete", "UA_AggregateFilter_equal", "UA_EventFilterResult_init", "UA_EventFilterResult_new", "UA_EventFilterResult_copy", "UA_EventFilterResult_deleteMembers", "UA_EventFilterResult_clear", "UA_EventFilterResult_delete", "UA_EventFilterResult_equal", "UA_AggregateFilterResult_init", "UA_AggregateFilterResult_new", "UA_AggregateFilterResult_copy", "UA_AggregateFilterResult_deleteMembers", "UA_AggregateFilterResult_clear", "UA_AggregateFilterResult_delete", "UA_AggregateFilterResult_equal", "UA_MonitoringParameters_init", "UA_MonitoringParameters_new", "UA_MonitoringParameters_copy", "UA_MonitoringParameters_deleteMembers", "UA_MonitoringParameters_clear", "UA_MonitoringParameters_delete", "UA_MonitoringParameters_equal", "UA_MonitoredItemCreateRequest_init", "UA_MonitoredItemCreateRequest_new", "UA_MonitoredItemCreateRequest_copy", "UA_MonitoredItemCreateRequest_deleteMembers", "UA_MonitoredItemCreateRequest_clear", "UA_MonitoredItemCreateRequest_delete", "UA_MonitoredItemCreateRequest_equal", "UA_MonitoredItemCreateResult_init", "UA_MonitoredItemCreateResult_new", "UA_MonitoredItemCreateResult_copy", "UA_MonitoredItemCreateResult_deleteMembers", "UA_MonitoredItemCreateResult_clear", "UA_MonitoredItemCreateResult_delete", "UA_MonitoredItemCreateResult_equal", "UA_CreateMonitoredItemsRequest_init", "UA_CreateMonitoredItemsRequest_new", "UA_CreateMonitoredItemsRequest_copy", "UA_CreateMonitoredItemsRequest_deleteMembers", "UA_CreateMonitoredItemsRequest_clear", "UA_CreateMonitoredItemsRequest_delete", "UA_CreateMonitoredItemsRequest_equal", "UA_CreateMonitoredItemsResponse_init", "UA_CreateMonitoredItemsResponse_new", "UA_CreateMonitoredItemsResponse_copy", "UA_CreateMonitoredItemsResponse_deleteMembers", "UA_CreateMonitoredItemsResponse_clear", "UA_CreateMonitoredItemsResponse_delete", "UA_CreateMonitoredItemsResponse_equal", "UA_MonitoredItemModifyRequest_init", "UA_MonitoredItemModifyRequest_new", "UA_MonitoredItemModifyRequest_copy", "UA_MonitoredItemModifyRequest_deleteMembers", "UA_MonitoredItemModifyRequest_clear", "UA_MonitoredItemModifyRequest_delete", "UA_MonitoredItemModifyRequest_equal", "UA_MonitoredItemModifyResult_init", "UA_MonitoredItemModifyResult_new", "UA_MonitoredItemModifyResult_copy", "UA_MonitoredItemModifyResult_deleteMembers", "UA_MonitoredItemModifyResult_clear", "UA_MonitoredItemModifyResult_delete", "UA_MonitoredItemModifyResult_equal", "UA_ModifyMonitoredItemsRequest_init", "UA_ModifyMonitoredItemsRequest_new", "UA_ModifyMonitoredItemsRequest_copy", "UA_ModifyMonitoredItemsRequest_deleteMembers", "UA_ModifyMonitoredItemsRequest_clear", "UA_ModifyMonitoredItemsRequest_delete", "UA_ModifyMonitoredItemsRequest_equal", "UA_ModifyMonitoredItemsResponse_init", "UA_ModifyMonitoredItemsResponse_new", "UA_ModifyMonitoredItemsResponse_copy", "UA_ModifyMonitoredItemsResponse_deleteMembers", "UA_ModifyMonitoredItemsResponse_clear", "UA_ModifyMonitoredItemsResponse_delete", "UA_ModifyMonitoredItemsResponse_equal", "UA_SetMonitoringModeRequest_init", "UA_SetMonitoringModeRequest_new", "UA_SetMonitoringModeRequest_copy", "UA_SetMonitoringModeRequest_deleteMembers", "UA_SetMonitoringModeRequest_clear", "UA_SetMonitoringModeRequest_delete", "UA_SetMonitoringModeRequest_equal", "UA_SetMonitoringModeResponse_init", "UA_SetMonitoringModeResponse_new", "UA_SetMonitoringModeResponse_copy", "UA_SetMonitoringModeResponse_deleteMembers", "UA_SetMonitoringModeResponse_clear", "UA_SetMonitoringModeResponse_delete", "UA_SetMonitoringModeResponse_equal", "UA_SetTriggeringRequest_init", "UA_SetTriggeringRequest_new", "UA_SetTriggeringRequest_copy", "UA_SetTriggeringRequest_deleteMembers", "UA_SetTriggeringRequest_clear", "UA_SetTriggeringRequest_delete", "UA_SetTriggeringRequest_equal", "UA_SetTriggeringResponse_init", "UA_SetTriggeringResponse_new", "UA_SetTriggeringResponse_copy", "UA_SetTriggeringResponse_deleteMembers", "UA_SetTriggeringResponse_clear", "UA_SetTriggeringResponse_delete", "UA_SetTriggeringResponse_equal", "UA_DeleteMonitoredItemsRequest_init", "UA_DeleteMonitoredItemsRequest_new", "UA_DeleteMonitoredItemsRequest_copy", "UA_DeleteMonitoredItemsRequest_deleteMembers", "UA_DeleteMonitoredItemsRequest_clear", "UA_DeleteMonitoredItemsRequest_delete", "UA_DeleteMonitoredItemsRequest_equal", "UA_DeleteMonitoredItemsResponse_init", "UA_DeleteMonitoredItemsResponse_new", "UA_DeleteMonitoredItemsResponse_copy", "UA_DeleteMonitoredItemsResponse_deleteMembers", "UA_DeleteMonitoredItemsResponse_clear", "UA_DeleteMonitoredItemsResponse_delete", "UA_DeleteMonitoredItemsResponse_equal", "UA_CreateSubscriptionRequest_init", "UA_CreateSubscriptionRequest_new", "UA_CreateSubscriptionRequest_copy", "UA_CreateSubscriptionRequest_deleteMembers", "UA_CreateSubscriptionRequest_clear", "UA_CreateSubscriptionRequest_delete", "UA_CreateSubscriptionRequest_equal", "UA_CreateSubscriptionResponse_init", "UA_CreateSubscriptionResponse_new", "UA_CreateSubscriptionResponse_copy", "UA_CreateSubscriptionResponse_deleteMembers", "UA_CreateSubscriptionResponse_clear", "UA_CreateSubscriptionResponse_delete", "UA_CreateSubscriptionResponse_equal", "UA_ModifySubscriptionRequest_init", "UA_ModifySubscriptionRequest_new", "UA_ModifySubscriptionRequest_copy", "UA_ModifySubscriptionRequest_deleteMembers", "UA_ModifySubscriptionRequest_clear", "UA_ModifySubscriptionRequest_delete", "UA_ModifySubscriptionRequest_equal", "UA_ModifySubscriptionResponse_init", "UA_ModifySubscriptionResponse_new", "UA_ModifySubscriptionResponse_copy", "UA_ModifySubscriptionResponse_deleteMembers", "UA_ModifySubscriptionResponse_clear", "UA_ModifySubscriptionResponse_delete", "UA_ModifySubscriptionResponse_equal", "UA_SetPublishingModeRequest_init", "UA_SetPublishingModeRequest_new", "UA_SetPublishingModeRequest_copy", "UA_SetPublishingModeRequest_deleteMembers", "UA_SetPublishingModeRequest_clear", "UA_SetPublishingModeRequest_delete", "UA_SetPublishingModeRequest_equal", "UA_SetPublishingModeResponse_init", "UA_SetPublishingModeResponse_new", "UA_SetPublishingModeResponse_copy", "UA_SetPublishingModeResponse_deleteMembers", "UA_SetPublishingModeResponse_clear", "UA_SetPublishingModeResponse_delete", "UA_SetPublishingModeResponse_equal", "UA_NotificationMessage_init", "UA_NotificationMessage_new", "UA_NotificationMessage_copy", "UA_NotificationMessage_deleteMembers", "UA_NotificationMessage_clear", "UA_NotificationMessage_delete", "UA_NotificationMessage_equal", "UA_MonitoredItemNotification_init", "UA_MonitoredItemNotification_new", "UA_MonitoredItemNotification_copy", "UA_MonitoredItemNotification_deleteMembers", "UA_MonitoredItemNotification_clear", "UA_MonitoredItemNotification_delete", "UA_MonitoredItemNotification_equal", "UA_EventFieldList_init", "UA_EventFieldList_new", "UA_EventFieldList_copy", "UA_EventFieldList_deleteMembers", "UA_EventFieldList_clear", "UA_EventFieldList_delete", "UA_EventFieldList_equal", "UA_HistoryEventFieldList_init", "UA_HistoryEventFieldList_new", "UA_HistoryEventFieldList_copy", "UA_HistoryEventFieldList_deleteMembers", "UA_HistoryEventFieldList_clear", "UA_HistoryEventFieldList_delete", "UA_HistoryEventFieldList_equal", "UA_StatusChangeNotification_init", "UA_StatusChangeNotification_new", "UA_StatusChangeNotification_copy", "UA_StatusChangeNotification_deleteMembers", "UA_StatusChangeNotification_clear", "UA_StatusChangeNotification_delete", "UA_StatusChangeNotification_equal", "UA_SubscriptionAcknowledgement_init", "UA_SubscriptionAcknowledgement_new", "UA_SubscriptionAcknowledgement_copy", "UA_SubscriptionAcknowledgement_deleteMembers", "UA_SubscriptionAcknowledgement_clear", "UA_SubscriptionAcknowledgement_delete", "UA_SubscriptionAcknowledgement_equal", "UA_PublishRequest_init", "UA_PublishRequest_new", "UA_PublishRequest_copy", "UA_PublishRequest_deleteMembers", "UA_PublishRequest_clear", "UA_PublishRequest_delete", "UA_PublishRequest_equal", "UA_PublishResponse_init", "UA_PublishResponse_new", "UA_PublishResponse_copy", "UA_PublishResponse_deleteMembers", "UA_PublishResponse_clear", "UA_PublishResponse_delete", "UA_PublishResponse_equal", "UA_RepublishRequest_init", "UA_RepublishRequest_new", "UA_RepublishRequest_copy", "UA_RepublishRequest_deleteMembers", "UA_RepublishRequest_clear", "UA_RepublishRequest_delete", "UA_RepublishRequest_equal", "UA_RepublishResponse_init", "UA_RepublishResponse_new", "UA_RepublishResponse_copy", "UA_RepublishResponse_deleteMembers", "UA_RepublishResponse_clear", "UA_RepublishResponse_delete", "UA_RepublishResponse_equal", "UA_TransferResult_init", "UA_TransferResult_new", "UA_TransferResult_copy", "UA_TransferResult_deleteMembers", "UA_TransferResult_clear", "UA_TransferResult_delete", "UA_TransferResult_equal", "UA_TransferSubscriptionsRequest_init", "UA_TransferSubscriptionsRequest_new", "UA_TransferSubscriptionsRequest_copy", "UA_TransferSubscriptionsRequest_deleteMembers", "UA_TransferSubscriptionsRequest_clear", "UA_TransferSubscriptionsRequest_delete", "UA_TransferSubscriptionsRequest_equal", "UA_TransferSubscriptionsResponse_init", "UA_TransferSubscriptionsResponse_new", "UA_TransferSubscriptionsResponse_copy", "UA_TransferSubscriptionsResponse_deleteMembers", "UA_TransferSubscriptionsResponse_clear", "UA_TransferSubscriptionsResponse_delete", "UA_TransferSubscriptionsResponse_equal", "UA_DeleteSubscriptionsRequest_init", "UA_DeleteSubscriptionsRequest_new", "UA_DeleteSubscriptionsRequest_copy", "UA_DeleteSubscriptionsRequest_deleteMembers", "UA_DeleteSubscriptionsRequest_clear", "UA_DeleteSubscriptionsRequest_delete", "UA_DeleteSubscriptionsRequest_equal", "UA_DeleteSubscriptionsResponse_init", "UA_DeleteSubscriptionsResponse_new", "UA_DeleteSubscriptionsResponse_copy", "UA_DeleteSubscriptionsResponse_deleteMembers", "UA_DeleteSubscriptionsResponse_clear", "UA_DeleteSubscriptionsResponse_delete", "UA_DeleteSubscriptionsResponse_equal", "UA_BuildInfo_init", "UA_BuildInfo_new", "UA_BuildInfo_copy", "UA_BuildInfo_deleteMembers", "UA_BuildInfo_clear", "UA_BuildInfo_delete", "UA_BuildInfo_equal", "UA_RedundancySupport_init", "UA_RedundancySupport_new", "UA_RedundancySupport_copy", "UA_RedundancySupport_deleteMembers", "UA_RedundancySupport_clear", "UA_RedundancySupport_delete", "UA_RedundancySupport_equal", "UA_ServerState_init", "UA_ServerState_new", "UA_ServerState_copy", "UA_ServerState_deleteMembers", "UA_ServerState_clear", "UA_ServerState_delete", "UA_ServerState_equal", "UA_RedundantServerDataType_init", "UA_RedundantServerDataType_new", "UA_RedundantServerDataType_copy", "UA_RedundantServerDataType_deleteMembers", "UA_RedundantServerDataType_clear", "UA_RedundantServerDataType_delete", "UA_RedundantServerDataType_equal", "UA_EndpointUrlListDataType_init", "UA_EndpointUrlListDataType_new", "UA_EndpointUrlListDataType_copy", "UA_EndpointUrlListDataType_deleteMembers", "UA_EndpointUrlListDataType_clear", "UA_EndpointUrlListDataType_delete", "UA_EndpointUrlListDataType_equal", "UA_NetworkGroupDataType_init", "UA_NetworkGroupDataType_new", "UA_NetworkGroupDataType_copy", "UA_NetworkGroupDataType_deleteMembers", "UA_NetworkGroupDataType_clear", "UA_NetworkGroupDataType_delete", "UA_NetworkGroupDataType_equal", "UA_SamplingIntervalDiagnosticsDataType_init", "UA_SamplingIntervalDiagnosticsDataType_new", "UA_SamplingIntervalDiagnosticsDataType_copy", "UA_SamplingIntervalDiagnosticsDataType_deleteMembers", "UA_SamplingIntervalDiagnosticsDataType_clear", "UA_SamplingIntervalDiagnosticsDataType_delete", "UA_SamplingIntervalDiagnosticsDataType_equal", "UA_ServerDiagnosticsSummaryDataType_init", "UA_ServerDiagnosticsSummaryDataType_new", "UA_ServerDiagnosticsSummaryDataType_copy", "UA_ServerDiagnosticsSummaryDataType_deleteMembers", "UA_ServerDiagnosticsSummaryDataType_clear", "UA_ServerDiagnosticsSummaryDataType_delete", "UA_ServerDiagnosticsSummaryDataType_equal", "UA_ServerStatusDataType_init", "UA_ServerStatusDataType_new", "UA_ServerStatusDataType_copy", "UA_ServerStatusDataType_deleteMembers", "UA_ServerStatusDataType_clear", "UA_ServerStatusDataType_delete", "UA_ServerStatusDataType_equal", "UA_SessionSecurityDiagnosticsDataType_init", "UA_SessionSecurityDiagnosticsDataType_new", "UA_SessionSecurityDiagnosticsDataType_copy", "UA_SessionSecurityDiagnosticsDataType_deleteMembers", "UA_SessionSecurityDiagnosticsDataType_clear", "UA_SessionSecurityDiagnosticsDataType_delete", "UA_SessionSecurityDiagnosticsDataType_equal", "UA_ServiceCounterDataType_init", "UA_ServiceCounterDataType_new", "UA_ServiceCounterDataType_copy", "UA_ServiceCounterDataType_deleteMembers", "UA_ServiceCounterDataType_clear", "UA_ServiceCounterDataType_delete", "UA_ServiceCounterDataType_equal", "UA_StatusResult_init", "UA_StatusResult_new", "UA_StatusResult_copy", "UA_StatusResult_deleteMembers", "UA_StatusResult_clear", "UA_StatusResult_delete", "UA_StatusResult_equal", "UA_SubscriptionDiagnosticsDataType_init", "UA_SubscriptionDiagnosticsDataType_new", "UA_SubscriptionDiagnosticsDataType_copy", "UA_SubscriptionDiagnosticsDataType_deleteMembers", "UA_SubscriptionDiagnosticsDataType_clear", "UA_SubscriptionDiagnosticsDataType_delete", "UA_SubscriptionDiagnosticsDataType_equal", "UA_ModelChangeStructureVerbMask_init", "UA_ModelChangeStructureVerbMask_new", "UA_ModelChangeStructureVerbMask_copy", "UA_ModelChangeStructureVerbMask_deleteMembers", "UA_ModelChangeStructureVerbMask_clear", "UA_ModelChangeStructureVerbMask_delete", "UA_ModelChangeStructureVerbMask_equal", "UA_ModelChangeStructureDataType_init", "UA_ModelChangeStructureDataType_new", "UA_ModelChangeStructureDataType_copy", "UA_ModelChangeStructureDataType_deleteMembers", "UA_ModelChangeStructureDataType_clear", "UA_ModelChangeStructureDataType_delete", "UA_ModelChangeStructureDataType_equal", "UA_SemanticChangeStructureDataType_init", "UA_SemanticChangeStructureDataType_new", "UA_SemanticChangeStructureDataType_copy", "UA_SemanticChangeStructureDataType_deleteMembers", "UA_SemanticChangeStructureDataType_clear", "UA_SemanticChangeStructureDataType_delete", "UA_SemanticChangeStructureDataType_equal", "UA_Range_init", "UA_Range_new", "UA_Range_copy", "UA_Range_deleteMembers", "UA_Range_clear", "UA_Range_delete", "UA_Range_equal", "UA_EUInformation_init", "UA_EUInformation_new", "UA_EUInformation_copy", "UA_EUInformation_deleteMembers", "UA_EUInformation_clear", "UA_EUInformation_delete", "UA_EUInformation_equal", "UA_AxisScaleEnumeration_init", "UA_AxisScaleEnumeration_new", "UA_AxisScaleEnumeration_copy", "UA_AxisScaleEnumeration_deleteMembers", "UA_AxisScaleEnumeration_clear", "UA_AxisScaleEnumeration_delete", "UA_AxisScaleEnumeration_equal", "UA_ComplexNumberType_init", "UA_ComplexNumberType_new", "UA_ComplexNumberType_copy", "UA_ComplexNumberType_deleteMembers", "UA_ComplexNumberType_clear", "UA_ComplexNumberType_delete", "UA_ComplexNumberType_equal", "UA_DoubleComplexNumberType_init", "UA_DoubleComplexNumberType_new", "UA_DoubleComplexNumberType_copy", "UA_DoubleComplexNumberType_deleteMembers", "UA_DoubleComplexNumberType_clear", "UA_DoubleComplexNumberType_delete", "UA_DoubleComplexNumberType_equal", "UA_AxisInformation_init", "UA_AxisInformation_new", "UA_AxisInformation_copy", "UA_AxisInformation_deleteMembers", "UA_AxisInformation_clear", "UA_AxisInformation_delete", "UA_AxisInformation_equal", "UA_XVType_init", "UA_XVType_new", "UA_XVType_copy", "UA_XVType_deleteMembers", "UA_XVType_clear", "UA_XVType_delete", "UA_XVType_equal", "UA_ProgramDiagnosticDataType_init", "UA_ProgramDiagnosticDataType_new", "UA_ProgramDiagnosticDataType_copy", "UA_ProgramDiagnosticDataType_deleteMembers", "UA_ProgramDiagnosticDataType_clear", "UA_ProgramDiagnosticDataType_delete", "UA_ProgramDiagnosticDataType_equal", "UA_ProgramDiagnostic2DataType_init", "UA_ProgramDiagnostic2DataType_new", "UA_ProgramDiagnostic2DataType_copy", "UA_ProgramDiagnostic2DataType_deleteMembers", "UA_ProgramDiagnostic2DataType_clear", "UA_ProgramDiagnostic2DataType_delete", "UA_ProgramDiagnostic2DataType_equal", "UA_Annotation_init", "UA_Annotation_new", "UA_Annotation_copy", "UA_Annotation_deleteMembers", "UA_Annotation_clear", "UA_Annotation_delete", "UA_Annotation_equal", "UA_ExceptionDeviationFormat_init", "UA_ExceptionDeviationFormat_new", "UA_ExceptionDeviationFormat_copy", "UA_ExceptionDeviationFormat_deleteMembers", "UA_ExceptionDeviationFormat_clear", "UA_ExceptionDeviationFormat_delete", "UA_ExceptionDeviationFormat_equal", "UA_EndpointType_init", "UA_EndpointType_new", "UA_EndpointType_copy", "UA_EndpointType_deleteMembers", "UA_EndpointType_clear", "UA_EndpointType_delete", "UA_EndpointType_equal", "UA_StructureDescription_init", "UA_StructureDescription_new", "UA_StructureDescription_copy", "UA_StructureDescription_deleteMembers", "UA_StructureDescription_clear", "UA_StructureDescription_delete", "UA_StructureDescription_equal", "UA_FieldMetaData_init", "UA_FieldMetaData_new", "UA_FieldMetaData_copy", "UA_FieldMetaData_deleteMembers", "UA_FieldMetaData_clear", "UA_FieldMetaData_delete", "UA_FieldMetaData_equal", "UA_PublishedEventsDataType_init", "UA_PublishedEventsDataType_new", "UA_PublishedEventsDataType_copy", "UA_PublishedEventsDataType_deleteMembers", "UA_PublishedEventsDataType_clear", "UA_PublishedEventsDataType_delete", "UA_PublishedEventsDataType_equal", "UA_PubSubGroupDataType_init", "UA_PubSubGroupDataType_new", "UA_PubSubGroupDataType_copy", "UA_PubSubGroupDataType_deleteMembers", "UA_PubSubGroupDataType_clear", "UA_PubSubGroupDataType_delete", "UA_PubSubGroupDataType_equal", "UA_WriterGroupDataType_init", "UA_WriterGroupDataType_new", "UA_WriterGroupDataType_copy", "UA_WriterGroupDataType_deleteMembers", "UA_WriterGroupDataType_clear", "UA_WriterGroupDataType_delete", "UA_WriterGroupDataType_equal", "UA_FieldTargetDataType_init", "UA_FieldTargetDataType_new", "UA_FieldTargetDataType_copy", "UA_FieldTargetDataType_deleteMembers", "UA_FieldTargetDataType_clear", "UA_FieldTargetDataType_delete", "UA_FieldTargetDataType_equal", "UA_SubscribedDataSetMirrorDataType_init", "UA_SubscribedDataSetMirrorDataType_new", "UA_SubscribedDataSetMirrorDataType_copy", "UA_SubscribedDataSetMirrorDataType_deleteMembers", "UA_SubscribedDataSetMirrorDataType_clear", "UA_SubscribedDataSetMirrorDataType_delete", "UA_SubscribedDataSetMirrorDataType_equal", "UA_SecurityGroupDataType_init", "UA_SecurityGroupDataType_new", "UA_SecurityGroupDataType_copy", "UA_SecurityGroupDataType_deleteMembers", "UA_SecurityGroupDataType_clear", "UA_SecurityGroupDataType_delete", "UA_SecurityGroupDataType_equal", "UA_PubSubKeyPushTargetDataType_init", "UA_PubSubKeyPushTargetDataType_new", "UA_PubSubKeyPushTargetDataType_copy", "UA_PubSubKeyPushTargetDataType_deleteMembers", "UA_PubSubKeyPushTargetDataType_clear", "UA_PubSubKeyPushTargetDataType_delete", "UA_PubSubKeyPushTargetDataType_equal", "UA_EnumDefinition_init", "UA_EnumDefinition_new", "UA_EnumDefinition_copy", "UA_EnumDefinition_deleteMembers", "UA_EnumDefinition_clear", "UA_EnumDefinition_delete", "UA_EnumDefinition_equal", "UA_ReadEventDetails_init", "UA_ReadEventDetails_new", "UA_ReadEventDetails_copy", "UA_ReadEventDetails_deleteMembers", "UA_ReadEventDetails_clear", "UA_ReadEventDetails_delete", "UA_ReadEventDetails_equal", "UA_ReadProcessedDetails_init", "UA_ReadProcessedDetails_new", "UA_ReadProcessedDetails_copy", "UA_ReadProcessedDetails_deleteMembers", "UA_ReadProcessedDetails_clear", "UA_ReadProcessedDetails_delete", "UA_ReadProcessedDetails_equal", "UA_ModificationInfo_init", "UA_ModificationInfo_new", "UA_ModificationInfo_copy", "UA_ModificationInfo_deleteMembers", "UA_ModificationInfo_clear", "UA_ModificationInfo_delete", "UA_ModificationInfo_equal", "UA_HistoryModifiedData_init", "UA_HistoryModifiedData_new", "UA_HistoryModifiedData_copy", "UA_HistoryModifiedData_deleteMembers", "UA_HistoryModifiedData_clear", "UA_HistoryModifiedData_delete", "UA_HistoryModifiedData_equal", "UA_HistoryEvent_init", "UA_HistoryEvent_new", "UA_HistoryEvent_copy", "UA_HistoryEvent_deleteMembers", "UA_HistoryEvent_clear", "UA_HistoryEvent_delete", "UA_HistoryEvent_equal", "UA_UpdateEventDetails_init", "UA_UpdateEventDetails_new", "UA_UpdateEventDetails_copy", "UA_UpdateEventDetails_deleteMembers", "UA_UpdateEventDetails_clear", "UA_UpdateEventDetails_delete", "UA_UpdateEventDetails_equal", "UA_DataChangeNotification_init", "UA_DataChangeNotification_new", "UA_DataChangeNotification_copy", "UA_DataChangeNotification_deleteMembers", "UA_DataChangeNotification_clear", "UA_DataChangeNotification_delete", "UA_DataChangeNotification_equal", "UA_EventNotificationList_init", "UA_EventNotificationList_new", "UA_EventNotificationList_copy", "UA_EventNotificationList_deleteMembers", "UA_EventNotificationList_clear", "UA_EventNotificationList_delete", "UA_EventNotificationList_equal", "UA_SessionDiagnosticsDataType_init", "UA_SessionDiagnosticsDataType_new", "UA_SessionDiagnosticsDataType_copy", "UA_SessionDiagnosticsDataType_deleteMembers", "UA_SessionDiagnosticsDataType_clear", "UA_SessionDiagnosticsDataType_delete", "UA_SessionDiagnosticsDataType_equal", "UA_EnumDescription_init", "UA_EnumDescription_new", "UA_EnumDescription_copy", "UA_EnumDescription_deleteMembers", "UA_EnumDescription_clear", "UA_EnumDescription_delete", "UA_EnumDescription_equal", "UA_UABinaryFileDataType_init", "UA_UABinaryFileDataType_new", "UA_UABinaryFileDataType_copy", "UA_UABinaryFileDataType_deleteMembers", "UA_UABinaryFileDataType_clear", "UA_UABinaryFileDataType_delete", "UA_UABinaryFileDataType_equal", "UA_DataSetMetaDataType_init", "UA_DataSetMetaDataType_new", "UA_DataSetMetaDataType_copy", "UA_DataSetMetaDataType_deleteMembers", "UA_DataSetMetaDataType_clear", "UA_DataSetMetaDataType_delete", "UA_DataSetMetaDataType_equal", "UA_PublishedDataSetDataType_init", "UA_PublishedDataSetDataType_new", "UA_PublishedDataSetDataType_copy", "UA_PublishedDataSetDataType_deleteMembers", "UA_PublishedDataSetDataType_clear", "UA_PublishedDataSetDataType_delete", "UA_PublishedDataSetDataType_equal", "UA_DataSetReaderDataType_init", "UA_DataSetReaderDataType_new", "UA_DataSetReaderDataType_copy", "UA_DataSetReaderDataType_deleteMembers", "UA_DataSetReaderDataType_clear", "UA_DataSetReaderDataType_delete", "UA_DataSetReaderDataType_equal", "UA_TargetVariablesDataType_init", "UA_TargetVariablesDataType_new", "UA_TargetVariablesDataType_copy", "UA_TargetVariablesDataType_deleteMembers", "UA_TargetVariablesDataType_clear", "UA_TargetVariablesDataType_delete", "UA_TargetVariablesDataType_equal", "UA_StandaloneSubscribedDataSetDataType_init", "UA_StandaloneSubscribedDataSetDataType_new", "UA_StandaloneSubscribedDataSetDataType_copy", "UA_StandaloneSubscribedDataSetDataType_deleteMembers", "UA_StandaloneSubscribedDataSetDataType_clear", "UA_StandaloneSubscribedDataSetDataType_delete", "UA_StandaloneSubscribedDataSetDataType_equal", "UA_DataTypeSchemaHeader_init", "UA_DataTypeSchemaHeader_new", "UA_DataTypeSchemaHeader_copy", "UA_DataTypeSchemaHeader_deleteMembers", "UA_DataTypeSchemaHeader_clear", "UA_DataTypeSchemaHeader_delete", "UA_DataTypeSchemaHeader_equal", "UA_ReaderGroupDataType_init", "UA_ReaderGroupDataType_new", "UA_ReaderGroupDataType_copy", "UA_ReaderGroupDataType_deleteMembers", "UA_ReaderGroupDataType_clear", "UA_ReaderGroupDataType_delete", "UA_ReaderGroupDataType_equal", "UA_PubSubConnectionDataType_init", "UA_PubSubConnectionDataType_new", "UA_PubSubConnectionDataType_copy", "UA_PubSubConnectionDataType_deleteMembers", "UA_PubSubConnectionDataType_clear", "UA_PubSubConnectionDataType_delete", "UA_PubSubConnectionDataType_equal", "UA_PubSubConfigurationDataType_init", "UA_PubSubConfigurationDataType_new", "UA_PubSubConfigurationDataType_copy", "UA_PubSubConfigurationDataType_deleteMembers", "UA_PubSubConfigurationDataType_clear", "UA_PubSubConfigurationDataType_delete", "UA_PubSubConfigurationDataType_equal", "UA_PubSubConfiguration2DataType_init", "UA_PubSubConfiguration2DataType_new", "UA_PubSubConfiguration2DataType_copy", "UA_PubSubConfiguration2DataType_deleteMembers", "UA_PubSubConfiguration2DataType_clear", "UA_PubSubConfiguration2DataType_delete", "UA_PubSubConfiguration2DataType_equal", "UA_FORMAT", "UA_FORMAT", "UA_FORMAT", "UA_FORMAT", "UA_FORMAT", "UA_FORMAT", "UA_ReferenceTypeSet_init", "UA_REFTYPESET", "UA_ReferenceTypeSet_union", "UA_ReferenceTypeSet_contains", "UA_NodePointer_init", "UA_NodePointer_equal"] diff --git a/src/helper_functions.jl b/src/helper_functions.jl index 5cab632..29375ec 100644 --- a/src/helper_functions.jl +++ b/src/helper_functions.jl @@ -30,14 +30,73 @@ function __get_juliavalues_from_variant(v, type) elseif typeof(wrapped) <: Union{UA_RationalNumber, UA_UnsignedRationalNumber} r = Rational(wrapped) elseif typeof(wrapped) <: Array && - eltype(wrapped) <: Union{UA_RationalNumber, UA_UnsignedRationalNumber} + eltype(wrapped) <: Union{UA_RationalNumber, UA_UnsignedRationalNumber} r = Rational.(wrapped) elseif typeof(wrapped) == UA_String r = unsafe_string(wrapped) elseif typeof(wrapped) <: Array && eltype(wrapped) == UA_String r = unsafe_string.(wrapped) else - r = deepcopy(wrapped) #TODO: do I need to copy here? test for memory safety! + r = wrapped end + # r2 = deepcopy(r) #don't need to copy due to Base.unsafe_wrap(p::Ptr{UA_Variant}) + # using unsafe_load, which already copies (see types.jl) return r -end +end + +function __determinetype(type) + if type <: AbstractString + t = unsafe_load(UA_TYPES_PTRS[UA_TYPES_STRING].typeId) + elseif type == Complex{Float32} + t = unsafe_load(UA_TYPES_PTRS[UA_TYPES_COMPLEXNUMBERTYPE].typeId) + elseif type == Complex{Float64} + t = unsafe_load(UA_TYPES_PTRS[UA_TYPES_DOUBLECOMPLEXNUMBERTYPE].typeId) + elseif type == Rational{Int32} + t = unsafe_load(UA_TYPES_PTRS[UA_TYPES_RATIONALNUMBER].typeId) + elseif type == Rational{UInt32} + t = unsafe_load(UA_TYPES_PTRS[UA_TYPES_UNSIGNEDRATIONALNUMBER].typeId) + else + t = unsafe_load(ua_data_type_ptr_default(type).typeId) + end + return t +end + +function __callback_wrap(method::Function) + #detect whether we need to apply UA_MethodCallback_generate or UA_MethodCallback_wrap, + #then ..._generate. + f = try UA_MethodCallback_generate(method) + catch + UA_MethodCallback_generate(UA_MethodCallback_wrap(method)) + end + return f +end + +function __callback_wrap(method) + return method +end + +#checks the consistency of arraydimensionssize, arraydimensions and valuerank +function __check_valuerank_arraydimensions_consistency(valuerank, arraydimensions) + #see here for specification: https://reference.opcfoundation.org/Core/Part3/v105/docs/8.6 + if valuerank >= -3 && valuerank <= 0 && length(arraydimensions) == 0 #scalar or array of one dimension + consistent = true + elseif valuerank > 0 && length(arraydimensions) == valuerank #array of valuerank dimension + consistent = true + else + consistent = false + end + return consistent +end + +#TODO: This is quite similar to UA_Array_new (types.jl), but works element by element and also for +#AbstractOpen62541Wrapper's; could we merge functionality? +function __AbstractArray_to_UA_Array(A::AbstractArray, + type_ptr = ua_data_type_ptr_default(eltype(Jpointer(A[1])))) + type = eltype(Jpointer(A[1])) + arr_ptr = convert(Ptr{type}, UA_Array_new(length(A), type_ptr)) + UA_A = UA_Array(arr_ptr, length(A)) + for i in eachindex(A) + UA_copy(Jpointer(A[i]), UA_A[i], type_ptr) + end + return UA_A +end \ No newline at end of file diff --git a/src/highlevel_client.jl b/src/highlevel_client.jl index e8bfdda..2b73986 100644 --- a/src/highlevel_client.jl +++ b/src/highlevel_client.jl @@ -24,8 +24,34 @@ mutable struct JUA_ClientConfig <: AbstractOpen62541Wrapper end const JUA_ClientConfig_setDefault = UA_ClientConfig_setDefault -const JUA_Client_connect = UA_Client_connect -const JUA_Client_connectUsername = UA_Client_connectUsername +""" +``` +JUA_Client_connect(client::JUA_Client, endpointurl::AbstractString)::UA_StatusCode +``` + +connect the `client` to the server with `endpointurl`. This is an anonymous connection, i.e., +no username or password are used (some servers do not allow this). + +""" +function JUA_Client_connect(client::JUA_Client, endpointurl::AbstractString) + UA_Client_connect(client, endpointurl) +end + +""" +``` +JUA_Client_connectUsername(client::JUA_Client, endpointurl::AbstractString, + username::AbstractString, password::AbstractString)::UA_StatusCode +``` + +connects the `client` to the server with endpoint URL `endpointurl` and supplies +`username` and `password` as login credentials. + +""" +function JUA_Client_connectUsername(client::JUA_Client, endpointurl::AbstractString, + username::AbstractString, password::AbstractString) + UA_Client_connectUsername(client, endpointurl, username, password) +end + const JUA_Client_disconnect = UA_Client_disconnect #Add node functions @@ -37,10 +63,10 @@ JUA_Client_addNode(client::JUA_Client, requestedNewNodeId::JUA_NodeId, outNewNodeId::JUA_NodeId, typeDefinition::JUA_NodeId)::UA_StatusCode ``` -uses the client API to add a Variable or Object node to the server +uses the client API to add a Variable or Object node to the server to which the client is connected to. -See [`JUA_VariableAttributes`](@ref), [`JUA_VariableTypeAttributes`](@ref), and [`JUA_ObjectAttributes`](@ref) +See [`JUA_VariableAttributes`](@ref), [`JUA_VariableTypeAttributes`](@ref), and [`JUA_ObjectAttributes`](@ref) on how to define valid attributes. ``` @@ -51,12 +77,12 @@ JUA_Client_addNode(client::JUA_Client, requestedNewNodeId::JUA_NodeId, outNewNodeId::JUA_NodeId)::UA_StatusCode ``` -uses the client API to add a ObjectType, ReferenceType, DataType or View node +uses the client API to add a ObjectType, ReferenceType, DataType or View node to the server to which the client is connected to. See [`JUA_VariableTypeAttributes](@ref), [`JUA_ObjectTypeAttributes`](@ref), [`JUA_ReferenceTypeAttributes`](@ref), [`JUA_DataTypeAttributes`](@ref), and [`JUA_ViewAttributes`](@ref) on how to define valid attributes. """ -function JUA_Client_addNode end +function JUA_Client_addNode end """ ``` @@ -67,10 +93,10 @@ JUA_Client_addNode_async(client::JUA_Client, requestedNewNodeId::JUA_NodeId, userdata::Ptr{Cvoid}, requestId::UInt32, typeDefinition::JUA_NodeId)::UA_StatusCode ``` -uses the **asynchronous** client API to add a Variable or Object node to the server +uses the **asynchronous** client API to add a Variable or Object node to the server to which the client is connected to. -See [`JUA_VariableAttributes`](@ref) or [`JUA_ObjectAttributes`](@ref) +See [`JUA_VariableAttributes`](@ref) or [`JUA_ObjectAttributes`](@ref) on how to define valid attributes. ``` @@ -82,14 +108,14 @@ JUA_Client_addNode_async(client::JUA_Client, requestedNewNodeId::JUA_NodeId, userdata::Ptr{Cvoid}, requestId::UInt32, typeDefinition::JUA_NodeId)::UA_StatusCode ``` -uses the **asynchronous** client API to add a VariableType, ObjectType, ReferenceType, DataType +uses the **asynchronous** client API to add a VariableType, ObjectType, ReferenceType, DataType or View node to the server to which the client is connected to. -See [`JUA_VariableTypeAttributes`](@ref), [`JUA_ObjectTypeAttributes`](@ref), -[`JUA_ReferenceTypeAttributes`](@ref), [`JUA_DataTypeAttributes`](@ref), +See [`JUA_VariableTypeAttributes`](@ref), [`JUA_ObjectTypeAttributes`](@ref), +[`JUA_ReferenceTypeAttributes`](@ref), [`JUA_DataTypeAttributes`](@ref), and [`JUA_ViewAttributes`](@ref) on how to define valid attributes. """ -function JUA_Client_addNode_async end +function JUA_Client_addNode_async end for nodeclass in instances(UA_NodeClass) if nodeclass != __UA_NODECLASS_FORCE32BIT && nodeclass != UA_NODECLASS_UNSPECIFIED @@ -106,13 +132,14 @@ for nodeclass in instances(UA_NodeClass) "type" => "Type") * "_async") attributeptr_sym = Symbol(uppercase("UA_TYPES_" * string(nodeclass_sym)[14:end] * "ATTRIBUTES")) - attributetype_sym_J = Symbol("J"*replace( + attributetype_sym_J = Symbol("J" * replace( "UA_" * titlecase(string(nodeclass_sym)[14:end]) * "Attributes", "type" => "Type")) - if funname_sym == :UA_Client_addVariableNode || funname_sym == :UA_Client_addObjectNode - @eval begin + if funname_sym == :UA_Client_addVariableNode || + funname_sym == :UA_Client_addObjectNode + @eval begin function JUA_Client_addNode(client, requestedNewNodeId, parentNodeId, referenceTypeId, browseName, attributes::$(attributetype_sym_J), @@ -121,13 +148,13 @@ for nodeclass in instances(UA_NodeClass) parentNodeId, referenceTypeId, browseName, typeDefinition, attributes, outNewNodeId) end - function JUA_Client_addNode_async(client, - requestedNewNodeId, parentNodeId, referenceTypeId, - browseName, attributes::$(attributetype_sym_J), + function JUA_Client_addNode_async(client, + requestedNewNodeId, parentNodeId, referenceTypeId, + browseName, attributes::$(attributetype_sym_J), outNewNodeId, callback, userdata, reqId, typeDefinition) - return $(funname_sym_async)(client, requestedNewNodeId, parentNodeId, - referenceTypeId, browseName, typeDefinition, attributes, - outNewNodeId, callback, userdata, reqId) + return $(funname_sym_async)(client, requestedNewNodeId, parentNodeId, + referenceTypeId, browseName, typeDefinition, attributes, + outNewNodeId, callback, userdata, reqId) end end elseif funname_sym != :UA_Client_addMethodNode #can't add method node via client. @@ -140,13 +167,13 @@ for nodeclass in instances(UA_NodeClass) outNewNodeId) end function JUA_Client_addNode_async(client, requestedNewNodeId, - parentNodeId, referenceTypeId, browseName, - attributes::$(attributetype_sym_J), outNewNodeId, - callback, userdata, reqId) - return $(funname_sym_async)(client, requestedNewNodeId, - parentNodeId, referenceTypeId, browseName, attributes, - outNewNodeId, callback, userdata, reqId) - end + parentNodeId, referenceTypeId, browseName, + attributes::$(attributetype_sym_J), outNewNodeId, + callback, userdata, reqId) + return $(funname_sym_async)(client, requestedNewNodeId, + parentNodeId, referenceTypeId, browseName, attributes, + outNewNodeId, callback, userdata, reqId) + end end end end @@ -158,19 +185,18 @@ end value = JUA_Client_readValueAttribute(client::JUA_Client, nodeId::JUA_NodeId, type = Any) ``` -uses the client API to read the value of `nodeId` from the server that the `client` -is connected to. +uses the client API to read the value of `nodeId` from the server that the `client` +is connected to. -The output `value` is automatically converted to a Julia type (such as Float64, String, Vector{String}, +The output `value` is automatically converted to a Julia type (such as Float64, String, Vector{String}, etc.) if possible. Otherwise, open62541 composite types are returned. -Note: Since it is unknown what type of value is stored within `nodeId` before reading -it, this function is inherently type unstable. +Note: Since it is unknown what type of value is stored within `nodeId` before reading +it, this function is inherently type unstable. -Type stability is improved if the optional argument `type` is provided, for example, -if you know that you have stored a Matrix{Float64} in `nodeId`, then you should +Type stability is improved if the optional argument `type` is provided, for example, +if you know that you have stored a Matrix{Float64} in `nodeId`, then you should specify this. If the wrong type is specified, the function will throw a TypeError. - """ function JUA_Client_readValueAttribute(client, nodeId, type::T = Any) where {T} v = UA_Variant_new() @@ -185,14 +211,13 @@ end JUA_Client_writeValueAttribute(server::JUA_Client, nodeId::JUA_NodeId, newvalue)::UA_StatusCode ``` -uses the client API to write the value `newvalue` to `nodeId` to the server that -the `client` is connected to. +uses the client API to write the value `newvalue` to `nodeId` to the server that +the `client` is connected to. -`new_value` must either be a `JUA_Variant` or a Julia value/array compatible with -any of its constructors. +`new_value` must either be a `JUA_Variant` or a Julia value/array compatible with +any of its constructors. See also [`JUA_Variant`](@ref) - """ function JUA_Client_writeValueAttribute(client, nodeId, newvalue) newvariant = JUA_Variant(newvalue) @@ -203,3 +228,97 @@ function JUA_Client_writeValueAttribute(client, nodeId, newvalue::JUA_Variant) statuscode = UA_Client_writeValueAttribute(client, nodeId, newvalue) return statuscode end + +#Client call wrapper +""" +``` +output::Union{Any, Tuple{Any, ...}} = JUA_Client_call(client::JUA_Client, + parentnodeid::JUA_NodeId, methodid::JUA_NodeId, inputs::Union{Any, Tuple{Any, ...}}) +``` + +uses the client API to call a method node (`methodid`) on the server the `client` is +connected with. `inputs` can either be a single argument or a tuple of arguments. Depending +on the method called an apporpriate output or tuple of output arguments is returned. +""" +function JUA_Client_call( + client::JUA_Client, parentnodeid::JUA_NodeId, methodid::JUA_NodeId, + inputs) + JUA_Client_call(client, parentnodeid, methodid, (inputs,)) +end + +function JUA_Client_call( + client::JUA_Client, parentnodeid::JUA_NodeId, methodid::JUA_NodeId, + inputs::Tuple) + #browse children nodes of methodid to infer properties of input and output arguments + e = nothing + breq = UA_BrowseRequest_new() + UA_BrowseRequest_init(breq) + breq.requestedMaxReferencesPerNode = 0 + bd = UA_BrowseDescription_new() + bd.nodeId = methodid + bd.resultMask = UA_BROWSERESULTMASK_ALL + breq.nodesToBrowse = bd + breq.nodesToBrowseSize = 1 + + bresp = UA_Client_Service_browse(client, breq) + nresults = unsafe_load(bresp.resultsSize) + if nresults == 1 + results = unsafe_load(bresp.results) + nrefs = unsafe_load(results.referencesSize) #should be 2 (in and output arguments) + if nrefs == 2 + refs = UA_Array(unsafe_load(results.references), 2) + if unsafe_string(refs[1].browseName.name) == "InputArguments" + j = 1 + else + j = 2 + end + k = j == 1 ? 2 : 1 + nodeid_inputargs = refs[j].nodeId.nodeId + nodeid_outputargs = refs[k].nodeId.nodeId + else + e = "something went wrong while browsing the nodes." + end + else + e = "something went wrong while browsing the nodes." + end + + inputarguments = JUA_Client_readValueAttribute(client, nodeid_inputargs) + outputarguments = JUA_Client_readValueAttribute(client, nodeid_outputargs) + + if length(inputarguments) != length(inputs) + e = MethodNodeInputError(length(inputs), length(inputarguments)) + throw(e) + end + + input_variants = UA_Variant_Array_new(length(inputs)) + for i in 1:length(inputs) + UA_Variant_copy(Jpointer(JUA_Variant(inputs[i])), input_variants[i]) + end + + arr_output = UA_Variant_Array_new(length(outputarguments)) + ref = Ref(arr_output[1]) + sc = UA_Client_call(client, parentnodeid, methodid, length(inputs), + input_variants.ptr, Ref(UInt64(length(outputarguments))), ref) + + UA_BrowseRequest_delete(breq) + UA_BrowseResponse_delete(bresp) + UA_Variant_Array_delete(input_variants) + + if !isnothing(e) + error(e) + end + + if sc != UA_STATUSCODE_GOOD + throw(ClientServiceRequestError("Calling method via Client API failed with statuscode \"$(UA_StatusCode_name_print(sc))\".")) + else + arr_output2 = UA_Array(ref[], length(outputarguments)) + r = __get_juliavalues_from_variant.(arr_output2, Any) + + UA_Variant_Array_delete(arr_output) + if length(outputarguments) == 1 + return r[1] + else + return tuple(r...) + end + end +end diff --git a/src/highlevel_server.jl b/src/highlevel_server.jl index 896246b..92a7a7a 100644 --- a/src/highlevel_server.jl +++ b/src/highlevel_server.jl @@ -27,7 +27,7 @@ mutable struct JUA_ServerConfig <: AbstractOpen62541Wrapper end #aliasing functions that interact with server and serverconfig -const JUA_ServerConfig_setMinimalCustomBuffer = UA_ServerConfig_setMinimalCustomBuffer +const JUA_ServerConfig_setMinimalCustomBuffer = UA_ServerConfig_setMinimalCustomBuffer const JUA_ServerConfig_setDefaultWithSecurityPolicies = UA_ServerConfig_setDefaultWithSecurityPolicies const JUA_ServerConfig_setDefaultWithSecureSecurityPolicies = UA_ServerConfig_setDefaultWithSecureSecurityPolicies const JUA_ServerConfig_setBasics = UA_ServerConfig_setBasics @@ -54,7 +54,8 @@ network layer to the given port and adds a single endpoint with the security policy ``SecurityPolicy#None`` to the server. A server certificate may be supplied but is optional. """ -JUA_ServerConfig_setMinimal(config, portNumber, certificate = C_NULL) = UA_ServerConfig_setMinimal(config, portNumber, certificate) +JUA_ServerConfig_setMinimal(config, portNumber, certificate = C_NULL) = UA_ServerConfig_setMinimal( + config, portNumber, certificate) const JUA_ServerConfig_setDefault = UA_ServerConfig_setDefault const JUA_ServerConfig_clean = UA_ServerConfig_clean @@ -70,32 +71,35 @@ sets default access control options in a server configuration. """ -function JUA_AccessControl_default(config::JUA_ServerConfig, allowAnonymous::Bool, - usernamePasswordLogin::Union{JUA_UsernamePasswordLogin,AbstractArray{JUA_UsernamePasswordLogin}}) - JUA_AccessControl_default(config, allowAnonymous, usernamePasswordLogin, - Ref(unsafe_load(unsafe_load(config.securityPolicies)).policyUri)) +function JUA_AccessControl_default(config::JUA_ServerConfig, allowAnonymous::Bool, + usernamePasswordLogin::Union{ + JUA_UsernamePasswordLogin, AbstractArray{JUA_UsernamePasswordLogin}}) + JUA_AccessControl_default(config, allowAnonymous, usernamePasswordLogin, + Ref(unsafe_load(unsafe_load(config.securityPolicies)).policyUri)) end -function JUA_AccessControl_default(config::JUA_ServerConfig, allowAnonymous::Bool, - usernamePasswordLogin::Union{JUA_UsernamePasswordLogin,AbstractArray{JUA_UsernamePasswordLogin}}, userTokenPolicyUri::AbstractString) +function JUA_AccessControl_default(config::JUA_ServerConfig, allowAnonymous::Bool, + usernamePasswordLogin::Union{ + JUA_UsernamePasswordLogin, AbstractArray{JUA_UsernamePasswordLogin}}, userTokenPolicyUri::AbstractString) ua_s = UA_STRING(userTokenPolicyUri) JUA_AccessControl_default(config, allowAnonymous, usernamePasswordLogin, ua_s) end -function JUA_AccessControl_default(config::JUA_ServerConfig, allowAnonymous::Bool, - usernamePasswordLogin::JUA_UsernamePasswordLogin, +function JUA_AccessControl_default(config::JUA_ServerConfig, allowAnonymous::Bool, + usernamePasswordLogin::JUA_UsernamePasswordLogin, userTokenPolicyUri::Union{Ref{UA_String}, Ptr{UA_String}}) - UA_AccessControl_default(config, allowAnonymous, userTokenPolicyUri, 1, Ref(usernamePasswordLogin.login)) + UA_AccessControl_default( + config, allowAnonymous, userTokenPolicyUri, 1, Ref(usernamePasswordLogin.login)) end -function JUA_AccessControl_default(config::JUA_ServerConfig, allowAnonymous::Bool, - usernamePasswordLogin::AbstractArray{JUA_UsernamePasswordLogin}, +function JUA_AccessControl_default(config::JUA_ServerConfig, allowAnonymous::Bool, + usernamePasswordLogin::AbstractArray{JUA_UsernamePasswordLogin}, userTokenPolicyUri::Union{Ref{UA_String}, Ptr{UA_String}}) logins = [usernamePasswordLogin[i].login for i in eachindex(usernamePasswordLogin)] - UA_AccessControl_default(config, allowAnonymous, userTokenPolicyUri, length(logins), logins) + UA_AccessControl_default( + config, allowAnonymous, userTokenPolicyUri, length(logins), logins) end - #const JUA_AccessControl_defaultWithLoginCallback = UA_AccessControl_defaultWithLoginCallback #TODO: complete this function JUA_Server_runUntilInterrupt(server::JUA_Server) @@ -122,12 +126,12 @@ JUA_Server_addNode(server::JUA_Server, requestedNewNodeId::JUA_NodeId, uses the server API to add a Variable, VariableType, or Object node to the `server`. -See [`JUA_VariableAttributes`](@ref), [`JUA_VariableTypeAttributes`](@ref), and [`JUA_ObjectAttributes`](@ref) +See [`JUA_VariableAttributes`](@ref), [`JUA_VariableTypeAttributes`](@ref), and [`JUA_ObjectAttributes`](@ref) on how to define valid attributes. ``` JUA_Server_addNode(server::JUA_Server, requestedNewNodeId::JUA_NodeId, - parentNodeId, referenceTypeId::JUA_NodeId, browseName::JUA_QualifiedName, + parentNodeId::JUA_NodeId, referenceTypeId::JUA_NodeId, browseName::JUA_QualifiedName, attributes::Union{JUA_ObjectTypeAttributes, JUA_ReferenceTypeAttributes, JUA_DataTypeAttributes, JUA_ViewAttributes}, outNewNodeId::JUA_NodeId, nodeContext::JUA_NodeId)::UA_StatusCode ``` @@ -136,29 +140,56 @@ uses the server API to add a ObjectType, ReferenceType, DataType, or View node t See [`JUA_ObjectTypeAttributes`](@ref), [`JUA_ReferenceTypeAttributes`](@ref), [`JUA_DataTypeAttributes`](@ref), and [`JUA_ViewAttributes`](@ref) on how to define valid attributes. -TODO: Need to add docstring for method node addition once I have thought about the interface. -""" -function JUA_Server_addNode(server, requestedNewNodeId, - parentNodeId, referenceTypeId, browseName, - attributes::JUA_MethodAttributes, - method, inputArgumentsSize, inputArguments, outputArgumentsSize, - outputArguments, nodeContext, outNewNodeId) - return UA_Server_addMethodNode(server, requestedNewNodeId, parentNodeId, - referenceTypeId, browseName, Jpointer(attributes), method, - inputArgumentsSize, inputArguments, outputArgumentsSize, - outputArguments, nodeContext, outNewNodeId) -end +``` +JUA_Server_addNode(server::JUA_Server, requestedNewNodeId::JUA_NodeId, + parentNodeId::JUA_NodeId, referenceTypeId::JUA_NodeId, browseName::JUA_QualifiedName, + attributes::JUA_MethodAttributes, method::Union{Function, Ptr{Cvoid}, Base.CFunction}, + inputArguments::Union{AbstractArray{JUA_Argument}, JUA_Argument}, + outputArguments::Union{AbstractArray{JUA_Argument}, JUA_Argument}, + outNewNodeId::JUA_NodeId, nodeContext::JUA_NodeId)::UA_StatusCode +``` + +uses the server API to add a Method node to the `server`. +The `method` supplied can either be a Julia function that fulfills the requirements for +`UA_MethodCallback_wrap` or `UA_MethodCallback_generate`. + +See also: +- [`JUA_MethodAttributes`](@ref) for how to define valid attributes. +- [`JUA_MethodCallback_generate`](@ref) for requirements on `method`. +- [`JUA_MethodCallback_wrap`](@ref) for requirements on `method`. +""" function JUA_Server_addNode(server, requestedNewNodeId, parentNodeId, referenceTypeId, browseName, - attributes::JUA_MethodAttributes, - method::Function, inputArgumentsSize, inputArguments, outputArgumentsSize, - outputArguments, nodeContext, outNewNodeId) #TODO: consider whether we would like to go even higher level here (automatically generate inputArguments of the correct size etc.) - methodcb = UA_MethodCallback_generate(method) - return JUA_Server_addNode(server, requestedNewNodeId, parentNodeId, - referenceTypeId, browseName, attributes, methodcb, - inputArgumentsSize, inputArguments, outputArgumentsSize, - outputArguments, nodeContext, outNewNodeId) + attributes::JUA_MethodAttributes, method, + inputArguments::Union{AbstractArray{JUA_Argument}, JUA_Argument}, + outputArguments::Union{AbstractArray{JUA_Argument}, JUA_Argument}, + nodeContext, outNewNodeId) + #todo: this if-else stuff could be done more elegantly with multiple dispatch (orthogonal + #design) + if inputArguments isa AbstractArray + inputargs_arr = __AbstractArray_to_UA_Array(inputArguments) + inputargs = inputargs_arr + else + inputargs = inputArguments + end + if outputArguments isa AbstractArray + outputargs_arr = __AbstractArray_to_UA_Array(outputArguments) + outputargs = outputargs_arr + else + outputargs = outputArguments + end + sc = UA_Server_addMethodNode(server, requestedNewNodeId, parentNodeId, + referenceTypeId, browseName, Jpointer(attributes), __callback_wrap(method), + __argsize(inputArguments), inputargs, __argsize(outputArguments), + outputargs, nodeContext, outNewNodeId) + if inputArguments isa AbstractArray + UA_Array_delete(inputargs.ptr, length(inputArguments), UA_TYPES_PTRS[UA_TYPES_ARGUMENT]) + end + if outputArguments isa AbstractArray + UA_Array_delete(outputargs.ptr, length(outputArguments), UA_TYPES_PTRS[UA_TYPES_ARGUMENT]) + end + return sc end for nodeclass in instances(UA_NodeClass) @@ -168,8 +199,8 @@ for nodeclass in instances(UA_NodeClass) "UA_Server_add" * titlecase(string(nodeclass_sym)[14:end]) * "Node", - "type" => "Type")) - attributetype_sym_J = Symbol("J"*replace( + "type" => "Type")) + attributetype_sym_J = Symbol("J" * replace( "UA_" * titlecase(string(nodeclass_sym)[14:end]) * "Attributes", @@ -212,17 +243,16 @@ end value = JUA_Server_readValue(server::JUA_Server, nodeId::JUA_NodeId, type = Any) ``` -uses the server API to read the value of `nodeId` from `server`. Output is -automatically converted to a Julia type (such as Float64, String, Vector{String}, +uses the server API to read the value of `nodeId` from `server`. Output is +automatically converted to a Julia type (such as Float64, String, Vector{String}, etc.) if possible. Otherwise, open62541 composite types are returned. -Note: Since it is unknown what type of value is stored within `nodeId` before reading -it, this function is inherently type unstable. +Note: Since it is unknown what type of value is stored within `nodeId` before reading +it, this function is inherently type unstable. -Type stability is improved if the optional argument `type` is provided, for example, -if you know that you have stored a Matrix{Float64} in `nodeId`, then you should +Type stability is improved if the optional argument `type` is provided, for example, +if you know that you have stored a Matrix{Float64} in `nodeId`, then you should specify this. If the wrong type is specified, the function will throw a TypeError. - """ function JUA_Server_readValue(server, nodeId, type::T = Any) where {T} v = UA_Variant_new() @@ -237,12 +267,11 @@ end JUA_Server_writeValue(server::JUA_Server, nodeId::JUA_NodeId, newvalue)::UA_StatusCode ``` -uses the server API to write the value `newvalue` to `nodeId` on `server`. -`new_value` must either be a `JUA_Variant` or a Julia value/array compatible with -any of its constructors. +uses the server API to write the value `newvalue` to `nodeId` on `server`. +`new_value` must either be a `JUA_Variant` or a Julia value/array compatible with +any of its constructors. See also [`JUA_Variant`](@ref) - """ function JUA_Server_writeValue(server, nodeId, newvalue) newvariant = JUA_Variant(newvalue) @@ -253,3 +282,51 @@ function JUA_Server_writeValue(server, nodeId, newvalue::JUA_Variant) statuscode = UA_Server_writeValue(server, nodeId, unsafe_load(Jpointer(newvalue))) #Yes, this is black magic; necessary due to how the function is defined in open62541 return statuscode end + +""" +``` +result::Union{Any, Tuple{Any, ...}} = JUA_Server_call(server::JUA_Server, request::JUA_CallMethodRequest) +``` + +uses the server API to process the method call request `request` on the `server`. `result` +is the outputs generated by the method called. This is typically a number or a string (or an +Array thereof). If the method produces multiple outputs, they are returned as a tuple. + +``` +result::Union{Any, Tuple{Any, ...}} = JUA_Server_call(server::JUA_Server, objectid::JUA_NodeId, + methodid::JUA_NodeId, inputarg) +``` + +An even higher level method that creates the `JUA_CallMethodRequest` internally. Equivalent to +`JUA_Client_call` on the client side. + +See also: + + - [`JUA_CallMethodRequest`](@ref) + - [`JUA_Client_call`](@ref) +""" +function JUA_Server_call(server::JUA_Server, request::JUA_CallMethodRequest) + answer = JUA_CallMethodResult() + UA_Server_call(server, request, answer) + sc = unsafe_load(answer.statusCode) + + if sc != UA_STATUSCODE_GOOD + error("Calling method via Server API failed with statuscode \"$(UA_StatusCode_name_print(sc))\".") + else + nargs = Int64(unsafe_load(answer.outputArgumentsSize)) + args = unsafe_load(answer.outputArguments) + arr_output = UA_Array(args, nargs) + r = __get_juliavalues_from_variant.(arr_output, Any) + + if nargs == 1 + return r[1] + else + return tuple(r...) + end + end +end + +function JUA_Server_call(server, parentnodeid, methodid, inputarg) + req = JUA_CallMethodRequest(parentnodeid, methodid, inputarg) + return JUA_Server_call(server, req) +end diff --git a/src/highlevel_types.jl b/src/highlevel_types.jl index 8030db4..5c2f23c 100644 --- a/src/highlevel_types.jl +++ b/src/highlevel_types.jl @@ -18,9 +18,10 @@ end #Sets a field of JUA_XXX object to a JUA_YYY object, calls the next method, i.e., #will create a copy of the JUA_YYY object. -function Base.setproperty!(x::AbstractOpen62541Wrapper, f::Symbol, v::AbstractOpen62541Wrapper) +function Base.setproperty!( + x::AbstractOpen62541Wrapper, f::Symbol, v::AbstractOpen62541Wrapper) @warn "Assigning a $(typeof(v)) as content of field $(String(f)) in a $(typeof(x)) leads to a copy of - the $(typeof(v)) being generated. Avoid repeated assignments without finalizing the $(typeof(x))." maxlog = 1 + the $(typeof(v)) being generated. Avoid repeated assignments without finalizing the $(typeof(x))." maxlog=1 setproperty!(Jpointer(x), f, v, true) end @@ -28,22 +29,23 @@ end #This creates a copy of the object to be assigned, so that the JUA_YYY object #can be safely used multiple times in assignments without getting freed multiple #times. -for i in unique_julia_types_ind +for i in UNIQUE_JULIA_TYPES_IND @eval begin - function Base.setproperty!(x::Ptr{$(julia_types[i])}, f::Symbol, v::T, nowarn::Bool = false) where T <: AbstractOpen62541Wrapper + function Base.setproperty!(x::Ptr{$(JULIA_TYPES[i])}, f::Symbol, v::T, + nowarn::Bool = false) where {T <: AbstractOpen62541Wrapper} type_ptr = ua_data_type_ptr_default(typeof(Jpointer(v))) UA_clear(getproperty(x, f), type_ptr) - UA_copy(Jpointer(v), getproperty(x, f), type_ptr) + UA_copy(Jpointer(v), getproperty(x, f), type_ptr) if nowarn == false @warn "Assigning a $(typeof(v)) as content of field $(String(f)) in a $(typeof(x)) leads to a copy of - the $(typeof(v)) being generated. Avoid repeated assignments without finalizing the $(typeof(x))." maxlog = 1 + the $(typeof(v)) being generated. Avoid repeated assignments without finalizing the $(typeof(x))." maxlog=1 end end end end function Base.show(io::IO, a::MIME"text/plain", v::AbstractOpen62541Wrapper) - print(io, "$(typeof(v)):\npointer: "*string(Jpointer(v))*"\ncontent: ") + print(io, "$(typeof(v)):\npointer: " * string(Jpointer(v)) * "\ncontent: ") Base.show(io, a, unsafe_load(Jpointer(v))) end @@ -54,7 +56,7 @@ end JUA_String ``` -a mutable struct that defines a string type usable with open62541. It is the equivalent +a mutable struct that defines a string type usable with open62541. It is the equivalent of a `UA_String`, but with memory managed by Julia rather than C. The following constructor methods are defined: @@ -69,19 +71,18 @@ creates an empty `JUA_String`, equivalent to calling `UA_String_new()`. JUA_String(s::AbstractString) ``` -creates a `JUA_String` containing the string `s`. +creates a `JUA_String` containing the string `s`. ``` JUA_String(ptr::Ptr{UA_String}) ``` -creates a `JUA_String` based on the pointer `ptr`. This is a fallback -method that can be used to pass `UA_Guid`s generated via the low level interface -to the higher level functions. Note that memory management remains on the C side -when using this method, i.e., `ptr` needs to be manually cleaned up with -`UA_String_delete(ptr)` after the object is not needed anymore. It is up +creates a `JUA_String` based on the pointer `ptr`. This is a fallback +method that can be used to pass `UA_Guid`s generated via the low level interface +to the higher level functions. Note that memory management remains on the C side +when using this method, i.e., `ptr` needs to be manually cleaned up with +`UA_String_delete(ptr)` after the object is not needed anymore. It is up to the user to ensure this. - """ mutable struct JUA_String <: AbstractOpen62541Wrapper ptr::Ptr{UA_String} @@ -115,7 +116,7 @@ end JUA_Guid ``` -a mutable struct that defines a globally unique identifier. It is the equivalent +a mutable struct that defines a globally unique identifier. It is the equivalent of a `UA_Guid`, but with memory managed by Julia rather than C. The following constructor methods are defined: @@ -130,20 +131,19 @@ creates an empty `JUA_Guid`, equivalent to calling `UA_Guid_new()`. JUA_Guid(guidstring::AbstractString) ``` -creates a `JUA_Guid` by parsing the string `guidstring`. The string should be -formatted according to the OPC standard defined in Part 6, 5.1.3. +creates a `JUA_Guid` by parsing the string `guidstring`. The string should be +formatted according to the OPC standard defined in Part 6, 5.1.3. ``` JUA_Guid(ptr::Ptr{UA_Guid}) ``` -creates a `JUA_Guid` based on the pointer `ptr`. This is a fallback -method that can be used to pass `UA_Guid`s generated via the low level interface -to the higher level functions. Note that memory management remains on the C side -when using this method, i.e., `ptr` needs to be manually cleaned up with -`UA_Guid_delete(ptr)` after the object is not needed anymore. It is up +creates a `JUA_Guid` based on the pointer `ptr`. This is a fallback +method that can be used to pass `UA_Guid`s generated via the low level interface +to the higher level functions. Note that memory management remains on the C side +when using this method, i.e., `ptr` needs to be manually cleaned up with +`UA_Guid_delete(ptr)` after the object is not needed anymore. It is up to the user to ensure this. - """ mutable struct JUA_Guid <: AbstractOpen62541Wrapper ptr::Ptr{UA_Guid} @@ -157,7 +157,7 @@ mutable struct JUA_Guid <: AbstractOpen62541Wrapper finalizer(release_handle, obj) return obj end - + function JUA_Guid(ptr::Ptr{UA_Guid}) return new(ptr) end @@ -217,11 +217,11 @@ creates a `JUA_NodeId` with namespace index `nsIndex` and global unique id ident JUA_NodeId(nptr::Ptr{UA_NodeId}) ``` -creates a `JUA_NodeId` based on the pointer `nptr`. This is a fallback -method that can be used to pass `UA_NodeId`s generated via the low level interface -to the higher level functions. Note that memory management remains on the C side -when using this method, i.e., `nptr` needs to be manually cleaned up with -`UA_NodeId_delete(nptr)` after the object is not needed anymore. It is up +creates a `JUA_NodeId` based on the pointer `nptr`. This is a fallback +method that can be used to pass `UA_NodeId`s generated via the low level interface +to the higher level functions. Note that memory management remains on the C side +when using this method, i.e., `nptr` needs to be manually cleaned up with +`UA_NodeId_delete(nptr)` after the object is not needed anymore. It is up to the user to ensure this. Examples: @@ -261,7 +261,8 @@ mutable struct JUA_NodeId <: AbstractOpen62541Wrapper return obj end - function JUA_NodeId(nsIndex::Integer, identifier::Union{AbstractString, JUA_String, Ptr{UA_String}}) + function JUA_NodeId( + nsIndex::Integer, identifier::Union{AbstractString, JUA_String, Ptr{UA_String}}) obj = new(UA_NODEID_STRING_ALLOC(nsIndex, Jpointer(identifier))) finalizer(release_handle, obj) return obj @@ -290,7 +291,6 @@ returns `true` if `j1` and `j2` are `JUA_NodeId`s with identical content. JUA_NodeId_equal(j1, j2) = UA_NodeId_equal(j1, j2) """ - ``` JUA_UsernamePasswordLogin ``` @@ -310,24 +310,21 @@ Example: j = JUA_UsernamePasswordLogin("PeterParker", "IamSpiderman") ``` - """ -mutable struct JUA_UsernamePasswordLogin #TODO: this is rather ugly, but prevents memory-leaking. +mutable struct JUA_UsernamePasswordLogin #This is rather ugly, but prevents memory-leaking. login::UA_UsernamePasswordLogin username::Ptr{UA_String} password::Ptr{UA_String} function JUA_UsernamePasswordLogin(username::AbstractString, password::AbstractString) un = UA_STRING(username) - pw = UA_STRING(password) + pw = UA_STRING(password) obj = new(UA_UsernamePasswordLogin(un, pw), un, pw) finalizer(release_handle, obj) return obj end end - - function Base.show(io::IO, a::MIME"text/plain", v::JUA_UsernamePasswordLogin) print("JUA_UsernamePasswordLogin:\n") print(io, "Username: ") @@ -342,8 +339,9 @@ function release_handle(obj::JUA_UsernamePasswordLogin) UA_String_delete(obj.password) end -Base.unsafe_convert(::Type{UA_UsernamePasswordLogin}, x::JUA_UsernamePasswordLogin) = x.login - +function Base.unsafe_convert(::Type{UA_UsernamePasswordLogin}, x::JUA_UsernamePasswordLogin) + x.login +end #ExpandedNodeId """ @@ -351,7 +349,7 @@ Base.unsafe_convert(::Type{UA_UsernamePasswordLogin}, x::JUA_UsernamePasswordLog JUA_NodeId ``` -creates a `JUA_ExpandedNodeId` object - the equivalent of a `UA_ExpandedNodeId`, +creates a `JUA_ExpandedNodeId` object - the equivalent of a `UA_ExpandedNodeId`, but with memory managed by Julia rather than C. See also: [OPC Foundation Website](https://reference.opcfoundation.org/Core/Part6/v105/docs/5.2.2.10) @@ -369,28 +367,28 @@ JUA_ExpandedNodeId(s::Union{AbstractString, JUA_String, Ptr{UA_String}}) ``` creates a `JUA_ExpandedNodeId` based on String `s` that is parsed into the relevant -properties. +properties. ``` JUA_ExpandedNodeId(nsIndex::Integer, identifier::Integer) ``` -creates a `JUA_ExpandedNodeId` with namespace index `nsIndex`, numeric NodeId identifier +creates a `JUA_ExpandedNodeId` with namespace index `nsIndex`, numeric NodeId identifier `identifier`, serverIndex = 0 and empty nameSpaceUri. ``` JUA_ExpandedNodeId(nsIndex::Integer, identifier::Union{AbstractString, JUA_String, Ptr{UA_String}}) ``` -creates a `JUA_ExpandedNodeId` with namespace index `nsIndex`, string NodeId identifier +creates a `JUA_ExpandedNodeId` with namespace index `nsIndex`, string NodeId identifier `identifier`, serverIndex = 0 and empty nameSpaceUri. ``` JUA_ExpandedNodeId(nodeId::Union{Ptr{UA_NodeId}, JUA_NodeId}) ``` -creates a `JUA_ExpandedNodeId` with empty namespaceUri, serverIndex = 0 and the -content of `nodeId` in the nodeId field. +creates a `JUA_ExpandedNodeId` with empty namespaceUri, serverIndex = 0 and the +content of `nodeId` in the nodeId field. ``` JUA_ExpandedNodeId(identifier::Integer, ns_uri::AbstractString, server_ind::Integer) @@ -402,12 +400,14 @@ creates a `JUA_ExpandedNodeId` with namespace index `nsIndex` and global unique ``` JUA_ExpandedNodeId(identifier::Union{Ptr{UA_String}, AbstractString, JUA_String}, ns_uri::AbstractString, server_ind::Integer) ``` -creates a `JUA_ExpandedNodeId` with a string `identifier` for the nodeid, namespacUri + +creates a `JUA_ExpandedNodeId` with a string `identifier` for the nodeid, namespacUri `ns_uri` and server index `server_ind`. ``` JUA_ExpandedNodeId(guid::Union{Ptr{UA_Guid}, JUA_Guid}, ns_uri::AbstractString, server_ind::Integer) ``` + creates a `JUA_ExpandedNodeId` with its nodeid having the global unique identifier `guid`, namespaceUri `ns_uri` and server index `server_ind`. @@ -421,11 +421,11 @@ creates a `JUA_ExpandedNodeId` from the JUA_NodeId `nodeid`, namespaceUri `ns_ur JUA_ExpandedNodeId(nptr::Ptr{UA_ExpandedNodeId}) ``` -creates a `JUA_ExpandedNodeId` based on the pointer `nptr`. This is a fallback -method that can be used to pass `UA_NodeId`s generated via the low level interface -to the higher level functions. Note that memory management remains on the C side -when using this method, i.e., `nptr` needs to be manually cleaned up with -`UA_ExpandedNodeId_delete(nptr)` after the object is not needed anymore. It is up +creates a `JUA_ExpandedNodeId` based on the pointer `nptr`. This is a fallback +method that can be used to pass `UA_NodeId`s generated via the low level interface +to the higher level functions. Note that memory management remains on the C side +when using this method, i.e., `nptr` needs to be manually cleaned up with +`UA_ExpandedNodeId_delete(nptr)` after the object is not needed anymore. It is up to the user to ensure this. Examples: @@ -465,12 +465,13 @@ mutable struct JUA_ExpandedNodeId <: AbstractOpen62541Wrapper return obj end - function JUA_ExpandedNodeId(nsIndex::Integer, identifier::Union{AbstractString, JUA_String, Ptr{UA_String}}) + function JUA_ExpandedNodeId( + nsIndex::Integer, identifier::Union{AbstractString, JUA_String, Ptr{UA_String}}) obj = new(UA_EXPANDEDNODEID_STRING_ALLOC(nsIndex, Jpointer(identifier))) finalizer(release_handle, obj) return obj end - + function JUA_ExpandedNodeId(nodeId::Union{Ptr{UA_NodeId}, JUA_NodeId}) obj = new(UA_EXPANDEDNODEID_NODEID(Jpointer(nodeId))) finalizer(release_handle, obj) @@ -483,25 +484,30 @@ mutable struct JUA_ExpandedNodeId <: AbstractOpen62541Wrapper return obj end - function JUA_ExpandedNodeId(identifier::Integer, ns_uri::AbstractString, server_ind::Integer) + function JUA_ExpandedNodeId( + identifier::Integer, ns_uri::AbstractString, server_ind::Integer) obj = new(UA_EXPANDEDNODEID_NUMERIC(identifier, ns_uri, server_ind)) finalizer(release_handle, obj) return obj end - function JUA_ExpandedNodeId(identifier::Union{Ptr{UA_String}, AbstractString, JUA_String}, ns_uri::AbstractString, server_ind::Integer) + function JUA_ExpandedNodeId( + identifier::Union{Ptr{UA_String}, AbstractString, JUA_String}, + ns_uri::AbstractString, server_ind::Integer) obj = new(UA_EXPANDEDNODEID_STRING_ALLOC(Jpointer(identifier), ns_uri, server_ind)) finalizer(release_handle, obj) return obj end - function JUA_ExpandedNodeId(guid::Union{Ptr{UA_Guid}, JUA_Guid}, ns_uri::AbstractString, server_ind::Integer) + function JUA_ExpandedNodeId(guid::Union{Ptr{UA_Guid}, JUA_Guid}, + ns_uri::AbstractString, server_ind::Integer) obj = new(UA_EXPANDEDNODEID_STRING_GUID(Jpointer(guid), ns_uri, server_ind)) finalizer(release_handle, obj) return obj end - function JUA_ExpandedNodeId(nodeid::Union{Ptr{UA_NodeId}, JUA_NodeId}, ns_uri::AbstractString, server_ind::Integer) + function JUA_ExpandedNodeId(nodeid::Union{Ptr{UA_NodeId}, JUA_NodeId}, + ns_uri::AbstractString, server_ind::Integer) obj = new(UA_EXPANDEDNODEID_NODEID(Jpointer(nodeid), ns_uri, server_ind)) finalizer(release_handle, obj) return obj @@ -529,8 +535,8 @@ JUA_ExpandedNodeId_equal(j1, j2) = UA_ExpandedNodeId_equal(j1, j2) JUA_QualifiedName ``` -A mutable struct that defines a qualified name comprised of a namespace index -and a text portion (a name). It is the equivalent of a `UA_QualifiedName`, but +A mutable struct that defines a qualified name comprised of a namespace index +and a text portion (a name). It is the equivalent of a `UA_QualifiedName`, but with memory managed by Julia rather than C. The following constructor methods are defined: @@ -545,20 +551,19 @@ creates an empty `JUA_QualifiedName`, equivalent to calling `UA_QualifiedName_ne JUA_QualifiedName(nsIndex::Integer, identifier::AbstractString) ``` -creates a `JUA_QualifiedName` with namespace index `nsIndex` and text identifier -`identifier`. +creates a `JUA_QualifiedName` with namespace index `nsIndex` and text identifier +`identifier`. ``` JUA_QualifiedName(ptr::Ptr{UA_QualifiedName}) ``` -creates a `JUA_QualifiedName` based on the pointer `ptr`. This is a fallback -method that can be used to pass `UA_QualifiedName`s generated via the low level -interface to the higher level functions. Note that memory management remains on -the C side when using this method, i.e., `ptr` needs to be manually cleaned up with -`UA_QualifiedName_delete(ptr)` after the object is not needed anymore. It is up +creates a `JUA_QualifiedName` based on the pointer `ptr`. This is a fallback +method that can be used to pass `UA_QualifiedName`s generated via the low level +interface to the higher level functions. Note that memory management remains on +the C side when using this method, i.e., `ptr` needs to be manually cleaned up with +`UA_QualifiedName_delete(ptr)` after the object is not needed anymore. It is up to the user to ensure this. - """ mutable struct JUA_QualifiedName <: AbstractOpen62541Wrapper ptr::Ptr{UA_QualifiedName} @@ -593,8 +598,8 @@ Base.convert(::Type{UA_QualifiedName}, x::JUA_QualifiedName) = unsafe_load(Jpoin JUA_LocalizedText ``` -A mutable struct that defines a localized text comprised of a locale specifier -and a text portion. It is the equivalent of a `UA_QualifiedName`, but +A mutable struct that defines a localized text comprised of a locale specifier +and a text portion. It is the equivalent of a `UA_QualifiedName`, but with memory managed by Julia rather than C. The following constructor methods are defined: @@ -615,13 +620,12 @@ creates a `JUA_LocalizedText` with localization `locale` and text `text`. JUA_LocalizedText(ptr::Ptr{UA_LocalizedText}) ``` -creates a `JUA_LocalizedText` based on the pointer `ptr`. This is a fallback -method that can be used to pass `UA_LocalizedText`s generated via the low level -interface to the higher level functions. Note that memory management remains on -the C side when using this method, i.e., `ptr` needs to be manually cleaned up with -`UA_LocalizedText_delete(ptr)` after the object is not needed anymore. It is up +creates a `JUA_LocalizedText` based on the pointer `ptr`. This is a fallback +method that can be used to pass `UA_LocalizedText`s generated via the low level +interface to the higher level functions. Note that memory management remains on +the C side when using this method, i.e., `ptr` needs to be manually cleaned up with +`UA_LocalizedText_delete(ptr)` after the object is not needed anymore. It is up to the user to ensure this. - """ mutable struct JUA_LocalizedText <: AbstractOpen62541Wrapper ptr::Ptr{UA_LocalizedText} @@ -632,7 +636,8 @@ mutable struct JUA_LocalizedText <: AbstractOpen62541Wrapper return obj end - function JUA_LocalizedText(locale::Union{AbstractString, JUA_String, Ptr{UA_String}}, text::Union{AbstractString, JUA_String, Ptr{UA_String}}) + function JUA_LocalizedText(locale::Union{AbstractString, JUA_String, Ptr{UA_String}}, + text::Union{AbstractString, JUA_String, Ptr{UA_String}}) obj = new(UA_LOCALIZEDTEXT_ALLOC(Jpointer(locale), Jpointer(text))) finalizer(release_handle, obj) return obj @@ -656,9 +661,9 @@ end JUA_Variant ``` -A mutable struct that defines a `JUA_Variant` object - the equivalent of a -`UA_Variant`, but with memory managed by Julia rather than C (exceptions below). -`JUA_Variant`s can hold any datatype either as a scalar or in array form. +A mutable struct that defines a `JUA_Variant` object - the equivalent of a +`UA_Variant`, but with memory managed by Julia rather than C (exceptions below). +`JUA_Variant`s can hold any datatype either as a scalar or in array form. The following constructor methods are defined: @@ -672,20 +677,20 @@ creates an empty `JUA_Variant`, equivalent to calling `UA_Variant_new()`. JUA_Variant(value::Union{T, AbstractArray{T}}) where T <: Union{UA_NUMBER_TYPES, AbstractString, ComplexF32, ComplexF64, Rational{<:Integer}}) ``` -creates a `JUA_Variant` containing `value`. All properties of the variant are set -automatically. For example, if `value` is an array, then the arrayDimensions and -arrayDimensionsSize properties are set based on the number of dimensions and -number of elements across each dimension contained in `value`. +creates a `JUA_Variant` containing `value`. All properties of the variant are set +automatically. For example, if `value` is an array, then the arrayDimensions and +arrayDimensionsSize properties are set based on the number of dimensions and +number of elements across each dimension contained in `value`. ``` JUA_Variant(variantptr::Ptr{UA_Variant}) ``` -creates a `JUA_Variant` based on the pointer `variantptr`. This is a fallback -method that can be used to pass `UA_Variant`s generated via the low level interface -to the higher level functions. Note that memory management remains on the C side -when using this method, i.e., `variantptr` needs to be manually cleaned up with -`UA_Variant_delete(variantptr)` after the object is not needed anymore. It is up +creates a `JUA_Variant` based on the pointer `variantptr`. This is a fallback +method that can be used to pass `UA_Variant`s generated via the low level interface +to the higher level functions. Note that memory management remains on the C side +when using this method, i.e., `variantptr` needs to be manually cleaned up with +`UA_Variant_delete(variantptr)` after the object is not needed anymore. It is up to the user to ensure this. Examples: @@ -713,16 +718,17 @@ mutable struct JUA_Variant <: AbstractOpen62541Wrapper return obj end - function JUA_Variant(value::Union{AbstractArray{T}, T}) where T <: Number + function JUA_Variant(value::Union{AbstractArray{T}, T}) where {T <: Number} #if not specifically handled by one of the methods below, the number type #is not natively supported; hence throw an informative exception. err = UnsupportedNumberTypeError(T) - throw(err) + throw(err) end function JUA_Variant(value::AbstractArray{T, N}, type_ptr::Ptr{UA_DataType} = ua_data_type_ptr_default(T)) where { - T <: Union{UA_NUMBER_TYPES, UA_String, UA_ComplexNumberType, UA_DoubleComplexNumberType, UA_RationalNumber, UA_UnsignedRationalNumber}, N} + T <: Union{UA_NUMBER_TYPES, UA_String, UA_ComplexNumberType, + UA_DoubleComplexNumberType, UA_RationalNumber, UA_UnsignedRationalNumber}, N} var = UA_Variant_new() var.type = type_ptr var.storageType = UA_VARIANT_DATA @@ -737,7 +743,9 @@ mutable struct JUA_Variant <: AbstractOpen62541Wrapper end function JUA_Variant(value::T, - type_ptr::Ptr{UA_DataType} = ua_data_type_ptr_default(T)) where {T <: Union{UA_NUMBER_TYPES, Ptr{UA_String}, UA_ComplexNumberType, UA_DoubleComplexNumberType, UA_RationalNumber, UA_UnsignedRationalNumber}} + type_ptr::Ptr{UA_DataType} = ua_data_type_ptr_default(T)) where {T <: Union{ + UA_NUMBER_TYPES, Ptr{UA_String}, UA_ComplexNumberType, + UA_DoubleComplexNumberType, UA_RationalNumber, UA_UnsignedRationalNumber}} var = UA_Variant_new() var.type = type_ptr var.storageType = UA_VARIANT_DATA @@ -759,7 +767,7 @@ mutable struct JUA_Variant <: AbstractOpen62541Wrapper f = UA_ComplexNumberType else f = UA_DoubleComplexNumberType - end + end ua_c = f(reim(value)...) return JUA_Variant(ua_c) end @@ -782,7 +790,8 @@ mutable struct JUA_Variant <: AbstractOpen62541Wrapper return JUA_Variant(a) end - function JUA_Variant(value::AbstractArray{<:Complex{T}}) where {T <: Union{Float32, Float64}} + function JUA_Variant(value::AbstractArray{<:Complex{T}}) where {T <: + Union{Float32, Float64}} f = T == Float32 ? UA_ComplexNumberType : UA_DoubleComplexNumberType a = similar(value, f) for i in eachindex(a) @@ -791,8 +800,9 @@ mutable struct JUA_Variant <: AbstractOpen62541Wrapper return JUA_Variant(a) end - function JUA_Variant(value::AbstractArray{<:Rational{T}}) where {T <: Union{Int32, UInt32}} - f = T == Int32 ? UA_RationalNumber : UA_UnsignedRationalNumber + function JUA_Variant(value::AbstractArray{<:Rational{T}}) where {T <: + Union{Int32, UInt32}} + f = T == Int32 ? UA_RationalNumber : UA_UnsignedRationalNumber a = similar(value, f) for i in eachindex(a) a[i] = f(value[i].num, value[i].den) @@ -805,15 +815,285 @@ function release_handle(obj::JUA_Variant) UA_Variant_delete(Jpointer(obj)) end +#Argument +const ARG_TYPEUNION = Union{ + JULIA_TYPES..., Complex{Float32}, Complex{Float64}, Rational{Int32}, + Rational{UInt32}, AbstractString} + +""" +``` +JUA_Argument +``` + +A mutable struct that defines a `JUA_Argument` object - the equivalent of a +`UA_Argument`, but with memory managed by Julia rather than C (exceptions below). + +The following constructor methods are defined: + +``` +JUA_Argument() +``` + +creates an empty `JUA_Argument`, equivalent to calling `UA_Argument_new()`. + +``` +JUA_Argument(examplearg::Union{Nothing, AbstractArray{<: ARG_TYPEUNION}, ARG_TYPEUNION} = nothing; + name::Union{Nothing, AbstractString} = nothing, + description::Union{AbstractString, Nothing} = nothing, + localization::AbstractString = "en-US", + datatype::Union{Nothing, ARG_TYPEUNION} = nothing, + valuerank::Union{Integer, Nothing} = nothing, + arraydimensions::Union{Integer, AbstractArray{<: Integer}, Nothing} = nothing) +``` + +creates a `JUA_Argument` based on the properties of `examplearg`. Specifically, the `datatype`, +`valuerank`, and `arraydimensions` are automatically determined from `examplearg`. The `name`, +`description` and `localization` keyword arguments can be used to describe the `JUA_Argument` +further. + +The `valuerank` and `arraydimensions` properties are explained here: [OPC Foundation Website](https://reference.opcfoundation.org/Core/Part3/v105/docs/8.6) + +``` +JUA_Argument(argumentptr::Ptr{UA_Argument}) +``` + +creates a `JUA_Argument` based on the pointer `argumentptr`. This is a fallback +method that can be used to pass `UA_Argument`s generated via the low level interface +to the higher level functions. Note that memory management remains on the C side +when using this method, i.e., `argumentptr` needs to be manually cleaned up with +`UA_Argument_delete(argumentptr)` after the object is not needed anymore. It is up +to the user to ensure this. + +Examples: + +``` +j = JUA_Argument() +j = JUA_Argument(1.0) #will accept a Float64 scalar +j = JUA_Argument(zeros(Float32, 2, 2)) #will exclusively accept Float32 arrays of size 2x2 +j = JUA_Argument(zeros(Float32, 2, 2), arraydimensions = [0, 0]) #will accept any 2D Float32 array. +j = JUA_Argument(datatype = Int8, valuerank = 1, arraydimensions = [2, 2]) #will accept a Int8 array of size 2 x 2. +j = JUA_Argument(datatype = Float64, valuerank = 1, arraydimensions = 4) #will accept a Float64 vector with 4 elements. +j = JUA_Argument(datatype = Float64, valuerank = 1, arraydimensions = 0) #will accept a Float64 vector of any length. +``` +""" +mutable struct JUA_Argument <: AbstractOpen62541Wrapper + ptr::Ptr{UA_Argument} + #Actually placing the type restrictions on examplearg and datatype like in the docstring + #places a large burden on the VS code interpreter and the compiler (large union); to avoid + #this, we keep the arguments untyped. + function JUA_Argument(examplearg = nothing; + name::Union{Nothing, AbstractString} = nothing, + description::Union{AbstractString, Nothing} = nothing, + localization::AbstractString = "en-US", + datatype = nothing, + valuerank::Union{Integer, Nothing} = nothing, + arraydimensions::Union{Integer, AbstractArray{<:Integer}, Nothing} = nothing) + arg = UA_Argument_new() + if isa(arraydimensions, Integer) + arraydimensions = [arraydimensions] + end + if !isnothing(name) + ua_s = UA_STRING(name) + UA_String_copy(ua_s, arg.name) + UA_String_delete(ua_s) + end + if !isnothing(description) + lt = UA_LOCALIZEDTEXT(localization, description) + UA_LocalizedText_copy(lt, arg.description) + UA_LocalizedText_delete(lt) + end + + #determine type and array parameters based on example arg if given + if !isnothing(examplearg) + if isa(examplearg, AbstractArray) + s = size(examplearg) + if isnothing(valuerank) || valuerank == length(s) + arg.arrayDimensionsSize = length(s) + arg.arrayDimensions = UA_UInt32_Array_new(s) + arg.valueRank = length(s) + end + arg.dataType = __determinetype(eltype(examplearg)) + else + arg.valueRank = -1 + arg.dataType = __determinetype(typeof(examplearg)) + end + end + + #allow type to be overwritten + if !isnothing(datatype) + arg.dataType = datatype + end + + #allow array fields to be overwritten (to allow flexibility in terms of dimensions etc.) + if !isnothing(valuerank) + arg.valueRank = valuerank + end + if !isnothing(arraydimensions) + arg.arrayDimensionsSize = length(arraydimensions) + arg.arrayDimensions = UA_UInt32_Array_new(arraydimensions) + end + + #consistency check + ads = unsafe_load(arg.arrayDimensionsSize) + ad = unsafe_wrap(Array, unsafe_load(arg.arrayDimensions), ads) + vr = unsafe_load(arg.valueRank) + consistent = __check_valuerank_arraydimensions_consistency(vr, ad) + if consistent == true + obj = new(arg) + finalizer(release_handle, obj) + return obj + else + #clean up and throw exception + UA_Argument_delete(arg) + err = ValueRankArraySizeConsistencyError(arg.valueRank, arg.arrayDimensions) + throw(err) + end + end + + function JUA_Argument(argumentptr::Ptr{UA_Argument}) + obj = new(argumentptr) + return obj + end +end + +function release_handle(obj::JUA_Argument) + UA_Argument_delete(Jpointer(obj)) +end + +function __argsize(a::JUA_Argument) + return 1 +end + +function __argsize(a) + return length(a) +end + +#CallMethodRequest +""" +``` +JUA_CallMethodRequest +``` + +A mutable struct that defines a `JUA_CallMethodRequest` object - the equivalent of a +`UA_CallMethodRequest`, but with memory managed by Julia rather than C (exceptions below). + +The following constructor methods are defined: + +``` +JUA_CallMethodRequest() +``` + +creates an empty `JUA_CallMethodRequest`, equivalent to calling `UA_CallMethodRequest_new()`. + +``` +JUA_CallMethodRequest(objectid::JUA_NodeId, methodid::JUA_NodeId, inputarg::Union{Any, Tuple{Any, ...}}) +``` + +creates a `JUA_CallMethodRequest` taking the context nodeid (`objectid`), the nodeid of the +method to be called (`methodid`)`, as well as the `inputarg` that the method is called with. + +`inputarg` can be any type that is compatible within Open62541.jl, particularly builtin number +types, strings, as well as UA_XXX types. Input arguments can also be arrays (for example a +Vector{Float64}). Multiple arguments should be provided as a tuple. + +``` +JUA_CallMethodRequest(methodrequestptr::Ptr{UA_CallMethodRequest}) +``` + +creates a `JUA_CallMethodRequest` based on the pointer `methodrequestptr`. This is a fallback +method that can be used to pass `UA_CallMethodRequest`s generated via the low level interface +to the higher level functions. Note that memory management remains on the C side +when using this method, i.e., `methodrequestptr` needs to be manually cleaned up with +`UA_CallMethodRequest_delete(methodrequestptr)` after the object is not needed anymore. It is up +to the user to ensure this. + +Examples: + +``` +j = JUA_CallMethodRequest() +j = JUA_CallMethodRequest(JUA_NodeId(0, UA_NS0ID_OBJECTSFOLDER), JUA_NodeId(1, 1234), ["Peter", "Julia"]) #one vector of strings inputarg +j = JUA_CallMethodRequest(JUA_NodeId(0, UA_NS0ID_OBJECTSFOLDER), JUA_NodeId(1, 1234), ("Claudia", 1234)]) #two input args +``` + +See also: + + - [`UA_MethodCallback_generate`](@ref) + + - [`UA_MethodCallback_wrap`](@ref) + - [`JUA_Server_addNode`](@ref) +""" +mutable struct JUA_CallMethodRequest <: AbstractOpen62541Wrapper + ptr::Ptr{UA_CallMethodRequest} + + function JUA_CallMethodRequest() + req = UA_CallMethodRequest_new() + obj = new(req) + finalizer(release_handle, obj) + return obj + end + + function JUA_CallMethodRequest(objectid::JUA_NodeId, methodid::JUA_NodeId, inputarg) + req = UA_CallMethodRequest_new() + req.objectId = objectid + req.methodId = methodid + if inputarg isa Tuple + variants = UA_Variant_Array_new(length(inputarg)) + for i in eachindex(variants) + j = JUA_Variant(inputarg[i]) + UA_Variant_copy(Jpointer(j), variants[i]) + end + req.inputArguments = variants + req.inputArgumentsSize = length(inputarg) + else + j = JUA_Variant(inputarg) + v = UA_Variant_new() + UA_Variant_copy(Jpointer(j), v) + req.inputArguments = v + req.inputArgumentsSize = 1 + end + obj = new(req) + finalizer(release_handle, obj) + return obj + end + + function JUA_CallMethodRequest(ptr::Ptr{UA_CallMethodRequest}) + return new(ptr) #no finalizer, see docstring + end +end + +function release_handle(obj::JUA_CallMethodRequest) + UA_CallMethodRequest_delete(Jpointer(obj)) +end + +#CallMethodResult +mutable struct JUA_CallMethodResult <: AbstractOpen62541Wrapper + ptr::Ptr{UA_CallMethodResult} + + function JUA_CallMethodResult() + res = UA_CallMethodResult_new() + obj = new(res) + finalizer(release_handle, obj) + return obj + end + + function JUA_CallMethodResult(ptr::Ptr{UA_CallMethodResult}) + return new(ptr) #no finalizer, see docstring + end +end + +function release_handle(obj::JUA_CallMethodResult) + UA_CallMethodResult_delete(Jpointer(obj)) +end + #VariableAttributes """ ``` JUA_VariableAttributes ``` -A mutable struct that defines a `JUA_VariableAttributes` object - the equivalent -of a `UA_VariableAttributes`, but with memory managed by Julia rather than C (see -below for exceptions) +A mutable struct that defines a `JUA_VariableAttributes` object - the equivalent +of a `UA_VariableAttributes`, but with memory managed by Julia rather than C (see +below for exceptions) The following constructor methods are defined: @@ -827,17 +1107,17 @@ For valid keyword arguments `kwargs` see [`UA_VariableAttributes_generate`](@ref JUA_VariableAttributes(ptr:Ptr{UA_VariableAttributes}) ``` -creates a `JUA_VariableAttributes` based on the pointer `ptr`. This is a -fallback method that can be used to pass `UA_VariableAttributes`s generated via +creates a `JUA_VariableAttributes` based on the pointer `ptr`. This is a +fallback method that can be used to pass `UA_VariableAttributes`s generated via the low level interface to the higher level functions. See also [`UA_VariableAttributes_generate`](@ref). -Note that memory management remains on the C side when using this method, i.e., -`ptr` needs to be manually cleaned up with `UA_VariableAttributes_delete(ptr)` +Note that memory management remains on the C side when using this method, i.e., +`ptr` needs to be manually cleaned up with `UA_VariableAttributes_delete(ptr)` after the object is not needed anymore. It is up to the user to ensure this. """ mutable struct JUA_VariableAttributes <: AbstractOpen62541Wrapper ptr::Ptr{UA_VariableAttributes} - + function JUA_VariableAttributes(; kwargs...) obj = new(UA_VariableAttributes_generate(; kwargs...)) finalizer(release_handle, obj) @@ -859,9 +1139,9 @@ end JUA_VariableTypeAttributes ``` -A mutable struct that defines a `JUA_VariableTypeAttributes` object - the equivalent -of a `UA_VariableTypeAttributes`, but with memory managed by Julia rather than C (see -below for exceptions) +A mutable struct that defines a `JUA_VariableTypeAttributes` object - the equivalent +of a `UA_VariableTypeAttributes`, but with memory managed by Julia rather than C (see +below for exceptions) The following constructor methods are defined: @@ -875,12 +1155,12 @@ For valid keyword arguments `kwargs` see [`UA_VariableTypeAttributes_generate`]( JUA_VariableTypeAttributes(ptr::Ptr{UA_VariableTypeAttributes}) ``` -creates a `JUA_VariableTypeAttributes` based on the pointer `ptr`. -This is a fallback method that can be used to pass `UA_VariableAttributes`s +creates a `JUA_VariableTypeAttributes` based on the pointer `ptr`. +This is a fallback method that can be used to pass `UA_VariableAttributes`s generated via the low level interface to the higher level functions. See also [`UA_VariableAttributes_generate`](@ref). -Note that memory management remains on the C side when using this method, i.e., -`ptr` needs to be manually cleaned up with `UA_VariableTypeAttributes_delete(ptr)` +Note that memory management remains on the C side when using this method, i.e., +`ptr` needs to be manually cleaned up with `UA_VariableTypeAttributes_delete(ptr)` after the object is not needed anymore. It is up to the user to ensure this. """ mutable struct JUA_VariableTypeAttributes <: AbstractOpen62541Wrapper @@ -907,9 +1187,9 @@ end JUA_ObjectAttributes ``` -A mutable struct that defines a `JUA_ObjectAttributes` object - the equivalent -of a `UA_ObjectAttributes`, but with memory managed by Julia rather than C (see -below for exceptions) +A mutable struct that defines a `JUA_ObjectAttributes` object - the equivalent +of a `UA_ObjectAttributes`, but with memory managed by Julia rather than C (see +below for exceptions) The following constructor methods are defined: @@ -923,12 +1203,12 @@ For valid keyword arguments `kwargs` see [`UA_ObjectAttributes_generate`](@ref). JUA_ObjectAttributes(ptr::Ptr{UA_ObjectAttributes}) ``` -creates a `JUA_ObjectAttributes` based on the pointer `ptr`. -This is a fallback method that can be used to pass `UA_ObjectAttributes`s +creates a `JUA_ObjectAttributes` based on the pointer `ptr`. +This is a fallback method that can be used to pass `UA_ObjectAttributes`s generated via the low level interface to the higher level functions. See also [`UA_ObjectAttributes_generate`](@ref). -Note that memory management remains on the C side when using this method, i.e., -`ptr` needs to be manually cleaned up with `UA_ObjectAttributes_delete(ptr)` +Note that memory management remains on the C side when using this method, i.e., +`ptr` needs to be manually cleaned up with `UA_ObjectAttributes_delete(ptr)` after the object is not needed anymore. It is up to the user to ensure this. """ mutable struct JUA_ObjectAttributes <: AbstractOpen62541Wrapper @@ -955,8 +1235,8 @@ end JUA_ObjectTypeAttributes ``` -A mutable struct that defines a `JUA_ObjectTypeAttributes` object - the equivalent -of a `UA_ObjectTypeAttributes`, but with memory managed by Julia rather than C (see +A mutable struct that defines a `JUA_ObjectTypeAttributes` object - the equivalent +of a `UA_ObjectTypeAttributes`, but with memory managed by Julia rather than C (see below for exceptions). The following constructor methods are defined: @@ -971,12 +1251,12 @@ For valid keyword arguments `kwargs` see [`UA_ObjectTypeAttributes_generate`](@r JUA_ObjectTypeAttributes(ptr::Ptr{UA_ObjectTypeAttributes}) ``` -creates a `JUA_ObjectTypeAttributes` based on the pointer `ptr`. This is a -fallback method that can be used to pass `UA_ObjectTypeAttributes`s generated via +creates a `JUA_ObjectTypeAttributes` based on the pointer `ptr`. This is a +fallback method that can be used to pass `UA_ObjectTypeAttributes`s generated via the low level interface to the higher level functions. See also [`UA_ObjectTypeAttributes_generate`](@ref). -Note that memory management remains on the C side when using this method, i.e., -`ptr` needs to be manually cleaned up with `UA_ObjectTypeAttributes_delete(ptr)` +Note that memory management remains on the C side when using this method, i.e., +`ptr` needs to be manually cleaned up with `UA_ObjectTypeAttributes_delete(ptr)` after the object is not needed anymore. It is up to the user to ensure this. """ mutable struct JUA_ObjectTypeAttributes <: AbstractOpen62541Wrapper @@ -1003,9 +1283,9 @@ end JUA_ReferenceTypeAttributes ``` -A mutable struct that defines a `JUA_ReferenceTypeAttributes` object - the equivalent -of a `UA_ReferenceTypeAttributes`, but with memory managed by Julia rather than C (see -below for exceptions) +A mutable struct that defines a `JUA_ReferenceTypeAttributes` object - the equivalent +of a `UA_ReferenceTypeAttributes`, but with memory managed by Julia rather than C (see +below for exceptions) The following constructor methods are defined: @@ -1019,13 +1299,13 @@ For valid keyword arguments `kwargs` see [`UA_ReferenceTypeAttributes_generate`] JUA_ReferenceTypeAttributes(ptr::Ptr{UA_ReferenceTypeAttributes}) ``` -creates a `JUA_ReferenceTypeAttributes` based on the pointer `ptr`. -This is a fallback method that can be used to pass `UA_ReferenceTypeAttributes`s +creates a `JUA_ReferenceTypeAttributes` based on the pointer `ptr`. +This is a fallback method that can be used to pass `UA_ReferenceTypeAttributes`s generated via the low level interface to the higher level functions. See also [`UA_ReferenceTypeAttributes_generate`](@ref). -Note that memory management remains on the C side when using this method, i.e., -`ptr` needs to be manually cleaned up with -`UA_ReferenceTypeAttributes_delete(ptr)` after the object is not +Note that memory management remains on the C side when using this method, i.e., +`ptr` needs to be manually cleaned up with +`UA_ReferenceTypeAttributes_delete(ptr)` after the object is not needed anymore. It is up to the user to ensure this. """ mutable struct JUA_ReferenceTypeAttributes <: AbstractOpen62541Wrapper @@ -1052,9 +1332,9 @@ end JUA_DataTypeAttributes ``` -A mutable struct that defines a `JUA_DataTypeAttributes` object - the equivalent -of a `UA_DataTypeAttributes`, but with memory managed by Julia rather than C (see -below for exceptions) +A mutable struct that defines a `JUA_DataTypeAttributes` object - the equivalent +of a `UA_DataTypeAttributes`, but with memory managed by Julia rather than C (see +below for exceptions) The following constructor methods are defined: @@ -1068,13 +1348,13 @@ For valid keyword arguments `kwargs` see [`UA_DataTypeAttributes_generate`](@ref JUA_DataTypeAttributes(ptr::Ptr{UA_DataTypeAttributes}) ``` -creates a `JUA_DataTypeAttributes` based on the pointer `ptr`. -This is a fallback method that can be used to pass `UA_VariableAttributes`s +creates a `JUA_DataTypeAttributes` based on the pointer `ptr`. +This is a fallback method that can be used to pass `UA_VariableAttributes`s generated via the low level interface to the higher level functions. See also [`UA_VariableAttributes_generate`](@ref). -Note that memory management remains on the C side when using this method, i.e., -`ptr` needs to be manually cleaned up with -`UA_DataTypeAttributes_delete(ptr)` after the object is not +Note that memory management remains on the C side when using this method, i.e., +`ptr` needs to be manually cleaned up with +`UA_DataTypeAttributes_delete(ptr)` after the object is not needed anymore. It is up to the user to ensure this. """ mutable struct JUA_DataTypeAttributes <: AbstractOpen62541Wrapper @@ -1101,9 +1381,9 @@ end JUA_ViewAttributes ``` -A mutable struct that defines a `JUA_ViewAttributes` object - the equivalent -of a `UA_ViewAttributes`, but with memory managed by Julia rather than C (see -below for exceptions) +A mutable struct that defines a `JUA_ViewAttributes` object - the equivalent +of a `UA_ViewAttributes`, but with memory managed by Julia rather than C (see +below for exceptions) The following constructor methods are defined: @@ -1117,12 +1397,12 @@ For valid keyword arguments `kwargs` see [`UA_ViewAttributes_generate`](@ref). JUA_ViewAttributes(ptr::Ptr{UA_ViewAttributes}) ``` -creates a `JUA_ViewAttributes` based on the pointer `ptr`. -This is a fallback method that can be used to pass `UA_VariableAttributes`s +creates a `JUA_ViewAttributes` based on the pointer `ptr`. +This is a fallback method that can be used to pass `UA_VariableAttributes`s generated via the low level interface to the higher level functions. See also [`UA_VariableAttributes_generate`](@ref). -Note that memory management remains on the C side when using this method, i.e., -`ptr` needs to be manually cleaned up with `UA_ViewAttributes_delete(ptr)` after +Note that memory management remains on the C side when using this method, i.e., +`ptr` needs to be manually cleaned up with `UA_ViewAttributes_delete(ptr)` after the object is not needed anymore. It is up to the user to ensure this. """ mutable struct JUA_ViewAttributes <: AbstractOpen62541Wrapper @@ -1149,9 +1429,9 @@ end JUA_MethodAttributes ``` -A mutable struct that defines a `JUA_MethodAttributes` object - the equivalent -of a `UA_MethodAttributes`, but with memory managed by Julia rather than C (see -below for exceptions) +A mutable struct that defines a `JUA_MethodAttributes` object - the equivalent +of a `UA_MethodAttributes`, but with memory managed by Julia rather than C (see +below for exceptions) The following constructor methods are defined: @@ -1165,12 +1445,12 @@ For valid keyword arguments `kwargs` see [`UA_MethodAttributes_generate`](@ref). JUA_MethodAttributes(ptr::Ptr{UA_MethodAttributes}) ``` -creates a `JUA_MethodAttributes` based on the pointer `ptr`. -This is a fallback method that can be used to pass `UA_MethodAttributes`s +creates a `JUA_MethodAttributes` based on the pointer `ptr`. +This is a fallback method that can be used to pass `UA_MethodAttributes`s generated via the low level interface to the higher level functions. See also [`UA_MethodAttributes_generate`](@ref). -Note that memory management remains on the C side when using this method, i.e., -`ptr` needs to be manually cleaned up with `UA_MethodAttributes_delete(ptr)` +Note that memory management remains on the C side when using this method, i.e., +`ptr` needs to be manually cleaned up with `UA_MethodAttributes_delete(ptr)` after the object is not needed anymore. It is up to the user to ensure this. """ mutable struct JUA_MethodAttributes <: AbstractOpen62541Wrapper diff --git a/src/server.jl b/src/server.jl index 963c9c4..0a62d91 100644 --- a/src/server.jl +++ b/src/server.jl @@ -41,14 +41,12 @@ See also: [`UA_MethodAttributes_generate`](@ref) to define valid attributes. -[`UA_MethodAttributes_generate`](@ref) to generate a valid callback. - +[`UA_MethodAttributes_generate`](@ref) to generate a valid callback. """ function UA_Server_addMethodNode(server, requestedNewNodeId, parentNodeId, referenceTypeId, browseName, attr, method, inputArgumentsSize, inputArguments, outputArgumentsSize, outputArguments, nodeContext, outNewNodeId) - return UA_Server_addMethodNodeEx(server, requestedNewNodeId, parentNodeId, referenceTypeId, browseName, unsafe_load(attr), method, inputArgumentsSize, inputArguments, @@ -97,7 +95,7 @@ for nodeclass in instances(UA_NodeClass) requestedNewNodeId, parentNodeId, referenceTypeId, browseName, typeDefinition, attributes, UA_TYPES_PTRS[$(attributeptr_sym)], nodeContext, outNewNodeId) - end + end end elseif funname_sym != :UA_Server_addMethodNode @eval begin @@ -146,7 +144,7 @@ for att in attributes_UA_Server_read Uses the Server API to read the value of the attribute $($(String(attr_name))) from the NodeId `nodeId` located on server `server`. The result is saved into `out`. - + Note that memory for `out` must be allocated by C before using this function. This can be accomplished with `out = $($(String(ret_type)))()`. The resulting object must be cleaned up via `$($(String(att[3])))_delete(out::Ptr{$($(String(att[3])))})` @@ -211,7 +209,9 @@ uses the server API to process the method call request `request` on the `server` Note that `result` is mutated. """ function UA_Server_call(server, request, result) - r = UA_Server_call(server, request) #TODO: introduce memory leak test to check whether r is correctly GC-ed or not. - UA_CallMethodResult_copy(r, result) + #XXX - this leaks memory, repeated use will lead to memory not being released. + #no workaround found yet. + r = UA_Server_call(server, request) + UA_CallMethodResult_copy(r, Jpointer(result)) return nothing end diff --git a/src/types.jl b/src/types.jl index 8ca8433..56c734b 100644 --- a/src/types.jl +++ b/src/types.jl @@ -30,6 +30,7 @@ struct UA_Array{T <: Ptr} <: AbstractArray{T, 1} length::Int64 end +#todo: is this used anywhere?= function UA_Array(s::T, field::Symbol) where {T} size_fieldname = Symbol(field, :Size) ptr = getfield(s, field) @@ -50,6 +51,9 @@ Base.setindex!(a::UA_Array, v, i::Int) = unsafe_store!(a.ptr, v, i) Base.unsafe_wrap(a::UA_Array) = unsafe_wrap(Array, a[begin], size(a)) Base.pointer(a::UA_Array) = a[begin] Base.convert(::Type{Ptr{T}}, a::UA_Array{Ptr{T}}) where {T} = a[begin] +function Base.unsafe_convert(::Type{Ptr{T}}, a::UA_Array) where {T} + Base.unsafe_convert(Ptr{T}, a.ptr) +end Base.convert(::Type{Ptr{Nothing}}, a::UA_Array) = Base.unsafe_convert(Ptr{Nothing}, a) Base.convert(::Type{Ptr{Nothing}}, a::UA_Array{Ptr{Nothing}}) = a[begin] # Avoid method ambigutiy function Base.unsafe_convert(::Type{Ptr{Nothing}}, a::UA_Array) @@ -88,15 +92,15 @@ function UA_print(p::T, return s end -for (i, type_name) in enumerate(type_names) +for (i, type_name) in enumerate(TYPE_NAMES) type_ind_name = Symbol("UA_TYPES_", uppercase(String(type_name)[4:end])) - julia_type = julia_types[i] + julia_type = JULIA_TYPES[i] val_type = Val{type_name} @eval begin # Datatype map functions ua_data_type_ptr(::$(val_type)) = UA_TYPES_PTRS[$(i - 1)] - if type_names[$(i)] ∉ types_ambiguous_ignorelist + if TYPE_NAMES[$(i)] ∉ types_ambiguous_ignorelist ua_data_type_ptr_default(::Type{$(julia_type)}) = UA_TYPES_PTRS[$(i - 1)] function ua_data_type_ptr_default(::Type{Ptr{$julia_type}}) ua_data_type_ptr_default($julia_type) @@ -325,7 +329,7 @@ function Base.Rational(x::UA_RationalNumber) # (which errors for negative numerator) since typemax of UInt32 is larger # than typemax(Int32), this can be out of range... Could also convert to Int64 # of course... - Rational(x.numerator, Int32(x.denominator)) + Rational(x.numerator, Int32(x.denominator)) end function Base.Rational(x::UA_UnsignedRationalNumber) @@ -427,7 +431,7 @@ UA_NODEID_NUMERIC(nsIndex::Integer, identifier::Integer)::Ptr{UA_NodeId} ``` creates a `UA_NodeId` object with namespace index `nsIndex` and numerical identifier `identifier`. -Memory is allocated by C and needs to be cleaned up using `UA_NodeId_delete(x::Ptr{UA_NodeId})` +Memory is allocated by C and needs to be cleaned up using `UA_NodeId_delete(x::Ptr{UA_NodeId})` after the object is not used anymore. """ function UA_NODEID_NUMERIC(nsIndex::Integer, identifier::Integer) @@ -804,7 +808,7 @@ function Base.unsafe_wrap(v::UA_Variant) values_row_major = reshape(values, unsafe_size(v)) if v.arrayDimensionsSize == 0 return values_row_major - else + else return permutedims(values_row_major, reverse(1:(Int64(v.arrayDimensionsSize)))) # To column major format; TODO: Which permutation is right? TODO: can make allocation free using PermutedDimsArray? end end @@ -838,8 +842,8 @@ end request::Ptr{UA_CreateSubscriptionRequest} = UA_CreateSubscriptionRequest_default() ``` -create a subscription create request to which monitored items can be added -subsequently. The subscription properties are set to their default values. +create a subscription create request to which monitored items can be added +subsequently. The subscription properties are set to their default values. Note that memory for the response is allocated by C and needs to be cleaned up by using `UA_CreateSubscriptionRequest_delete(request)` after its use. @@ -865,10 +869,10 @@ end request::Ptr{UA_MonitoredItemCreateRequest} = UA_MonitoredItemCreateRequest_default(nodeId::Ptr{UA_NodeId}) ``` -create a monitored item create request that monitors `nodeId`. The monitored item -properties are set to their default values. +create a monitored item create request that monitors `nodeId`. The monitored item +properties are set to their default values. -Note that memory for the request is allocated by C and needs to be cleaned up by +Note that memory for the request is allocated by C and needs to be cleaned up by using `UA_MonitoredItemCreateRequest_delete(request)` after its use. See also: @@ -892,8 +896,8 @@ end UA_equal(p1::T, p2::T, T)::Bool ``` -compares `p1` and `p2` and returns `true` if they are equal. This is a basic -functionality and it is usually more appropriate to use the fully typed versions, +compares `p1` and `p2` and returns `true` if they are equal. This is a basic +functionality and it is usually more appropriate to use the fully typed versions, for example `UA_String_equal` to compare to ´UA_String´s. """ function UA_equal(p1, p2, type) diff --git a/test/attribute_generation.jl b/test/attribute_generation.jl index 59f81d6..209ad3d 100644 --- a/test/attribute_generation.jl +++ b/test/attribute_generation.jl @@ -88,12 +88,13 @@ include("test_helpers.jl") #UA_VariableAttributes_generate #define different sized input cases to test both scalar and array codes array_sizes = [1, 2, (2, 3), (2, 3, 4)] -types = [Bool, Int8, Int16, Int32, Int64, UInt8, UInt16, UInt32, UInt64, - Float32, Float64, String, ComplexF32, ComplexF64, Rational{Int32}, - Rational{UInt32}] +types = [Bool, Int8, Int16, Int32, Int64, UInt8, UInt16, UInt32, UInt64, + Float32, Float64, String, ComplexF32, ComplexF64, Rational{Int32}, + Rational{UInt32}] #TODO: Add tests for an unsupported number type, showing that exception is thrown and checking dispatch. -inputs = Tuple(Tuple(customrand(type, array_size) for array_size in array_sizes) for type in types) +inputs = Tuple(Tuple(customrand(type, array_size) for array_size in array_sizes) +for type in types) valueranks = [-1, 1, 2, 3] displayname = "whatever" description = "this is a whatever variable" @@ -151,10 +152,11 @@ end #UA_VariableTypeAttributes_generate #define different sized input cases to test both scalar and array codes array_sizes = [1, 2, (2, 3), (2, 3, 4)] -types = [Bool, Int8, Int16, Int32, Int64, UInt8, UInt16, UInt32, UInt64, - Float32, Float64, String, ComplexF32, ComplexF64, Rational{Int32}, - Rational{UInt32}] -inputs = Tuple(Tuple(customrand(type, array_size) for array_size in array_sizes) for type in types) +types = [Bool, Int8, Int16, Int32, Int64, UInt8, UInt16, UInt32, UInt64, + Float32, Float64, String, ComplexF32, ComplexF64, Rational{Int32}, + Rational{UInt32}] +inputs = Tuple(Tuple(customrand(type, array_size) for array_size in array_sizes) +for type in types) valueranks = [-1, 1, 2, 3] displayname = "whatever" description = "this is a whatever variable" diff --git a/test/callbacks.jl b/test/callbacks.jl index 8d32f07..9bd10d8 100644 --- a/test/callbacks.jl +++ b/test/callbacks.jl @@ -44,4 +44,4 @@ if !Sys.isapple() #closures not supported on Apple M1 processors, LLVM limitatio Base.delete_method(Open62541.getmethodindex(methods(prot), 1)) end end -end \ No newline at end of file +end diff --git a/test/add_change_var_array.jl b/test/client_add_change_var_array.jl similarity index 96% rename from test/add_change_var_array.jl rename to test/client_add_change_var_array.jl index 8dd9211..17343c5 100644 --- a/test/add_change_var_array.jl +++ b/test/client_add_change_var_array.jl @@ -16,17 +16,17 @@ Distributed.@everywhere begin include("test_helpers.jl") #this will cause method re-definition warnings, because it has been included already in the scalar case, but it's not important here. # What types and sizes we are testing for: - types = [Bool, Int8, Int16, Int32, Int64, UInt8, UInt16, UInt32, UInt64, - Float32, Float64, String, ComplexF32, ComplexF64, Rational{Int32}, + types = [Bool, Int8, Int16, Int32, Int64, UInt8, UInt16, UInt32, UInt64, + Float32, Float64, String, ComplexF32, ComplexF64, Rational{Int32}, Rational{UInt32}] array_sizes = (11, (2, 5), (3, 4, 5), (3, 4, 5, 6)) # Generate random input values and generate nodeid names - input_data = Tuple(Tuple(customrand(type, array_size) for array_size in array_sizes) - for type in types) + input_data = Tuple(Tuple(customrand(type, array_size) for array_size in array_sizes) + for type in types) - input_data2 = Tuple(Tuple(customrand(type, array_size) for array_size in array_sizes) - for type in types) + input_data2 = Tuple(Tuple(customrand(type, array_size) for array_size in array_sizes) + for type in types) varnode_ids = ["$(string(array_size)) $(Symbol(type)) array variable" for type in types, array_size in array_sizes] end @@ -151,7 +151,7 @@ for type_ind in eachindex(types) type = Rational{Int32} elseif types[type_ind] <: Rational{<:Signed} type = Rational{UInt32} - elseif types[type_ind] <: Union{ComplexF16,ComplexF32} + elseif types[type_ind] <: Union{ComplexF16, ComplexF32} type = ComplexF64 elseif types[type_ind] <: ComplexF64 type = ComplexF32 diff --git a/test/add_change_var_scalar.jl b/test/client_add_change_var_scalar.jl similarity index 98% rename from test/add_change_var_scalar.jl rename to test/client_add_change_var_scalar.jl index ed25497..421d39d 100644 --- a/test/add_change_var_scalar.jl +++ b/test/client_add_change_var_scalar.jl @@ -16,8 +16,8 @@ Distributed.@everywhere begin include("test_helpers.jl") # What types we are testing for: - types = [Bool, Int8, Int16, Int32, Int64, UInt8, UInt16, UInt32, UInt64, - Float32, Float64, String, ComplexF32, ComplexF64, Rational{Int32}, + types = [Bool, Int8, Int16, Int32, Int64, UInt8, UInt16, UInt32, UInt64, + Float32, Float64, String, ComplexF32, ComplexF64, Rational{Int32}, Rational{UInt32}] # Generate random input values and generate nodeid names @@ -124,7 +124,7 @@ for type_ind in eachindex(types) type = Rational{Int32} elseif types[type_ind] <: Rational{<:Signed} type = Rational{UInt32} - elseif types[type_ind] <: Union{ComplexF16,ComplexF32} + elseif types[type_ind] <: Union{ComplexF16, ComplexF32} type = ComplexF64 elseif types[type_ind] <: ComplexF64 type = ComplexF32 diff --git a/test/client_callmethod.jl b/test/client_callmethod.jl new file mode 100644 index 0000000..4a0b1df --- /dev/null +++ b/test/client_callmethod.jl @@ -0,0 +1,287 @@ +# Check whether calling method nodes via the client works. + +using Distributed +Distributed.addprocs(1) # Add a single worker process to run the server + +Distributed.@everywhere begin + using Open62541 + using Test + using Pkg + using Pkg.BinaryPlatforms + + #create methods that will be used later + function simple_one_in_one_out(name) + assembledstring = "Hello " * name * "." + return assembledstring + end + function simple_two_in_one_out(name, adjective) + assembledstring = "Hello " * name * ", you are " * adjective * "." + return assembledstring + end + function simple_one_in_two_out(name) + out1 = "Hello " * name * "." + out2 = reverse(name) * " is " * name * " reversed." + return (out1, out2) + end + function simple_two_in_two_out(name, adjective) + out1 = "Hello " * name * ", you are " * adjective * "." + out2 = adjective * " is the adjective." + return (out1, out2) + end + function simple_two_in_two_out_mixed_type(name, number) + out1 = "Hello " * name * "." + out2 = number * number + return (out1, out2) + end + + function c1(server, sessionId, sessionHandle, methodId, methodContext, objectId, + objectContext, inputSize, input, outputSize, output) + arr_input = UA_Array(input, Int64(inputSize)) + arr_output = UA_Array(output, Int64(outputSize)) + input_julia = Open62541.__get_juliavalues_from_variant.(arr_input, Any) + output_julia = simple_one_in_one_out(input_julia...) + if !isa(output_julia, Tuple) + output_julia = (output_julia,) + end + for i in 1:outputSize + j = JUA_Variant(output_julia[i]) + UA_Variant_copy(Open62541.Jpointer(j), arr_output[i]) + end + return UA_STATUSCODE_GOOD + end + function c2(server, sessionId, sessionHandle, methodId, methodContext, objectId, + objectContext, inputSize, input, outputSize, output) + arr_input = UA_Array(input, Int64(inputSize)) + arr_output = UA_Array(output, Int64(outputSize)) + input_julia = Open62541.__get_juliavalues_from_variant.(arr_input, Any) + output_julia = simple_two_in_one_out(input_julia...) + if !isa(output_julia, Tuple) + output_julia = (output_julia,) + end + for i in 1:outputSize + j = JUA_Variant(output_julia[i]) + UA_Variant_copy(Open62541.Jpointer(j), arr_output[i]) + end + return UA_STATUSCODE_GOOD + end + function c3(server, sessionId, sessionHandle, methodId, methodContext, objectId, + objectContext, inputSize, input, outputSize, output) + arr_input = UA_Array(input, Int64(inputSize)) + arr_output = UA_Array(output, Int64(outputSize)) + input_julia = Open62541.__get_juliavalues_from_variant.(arr_input, Any) + output_julia = simple_one_in_two_out(input_julia...) + if !isa(output_julia, Tuple) + output_julia = (output_julia,) + end + for i in 1:outputSize + j = JUA_Variant(output_julia[i]) + UA_Variant_copy(Open62541.Jpointer(j), arr_output[i]) + end + return UA_STATUSCODE_GOOD + end + function c4(server, sessionId, sessionHandle, methodId, methodContext, objectId, + objectContext, inputSize, input, outputSize, output) + arr_input = UA_Array(input, Int64(inputSize)) + arr_output = UA_Array(output, Int64(outputSize)) + input_julia = Open62541.__get_juliavalues_from_variant.(arr_input, Any) + output_julia = simple_two_in_two_out(input_julia...) + if !isa(output_julia, Tuple) + output_julia = (output_julia,) + end + for i in 1:outputSize + j = JUA_Variant(output_julia[i]) + UA_Variant_copy(Open62541.Jpointer(j), arr_output[i]) + end + return UA_STATUSCODE_GOOD + end + function c5(server, sessionId, sessionHandle, methodId, methodContext, objectId, + objectContext, inputSize, input, outputSize, output) + arr_input = UA_Array(input, Int64(inputSize)) + arr_output = UA_Array(output, Int64(outputSize)) + input_julia = Open62541.__get_juliavalues_from_variant.(arr_input, Any) + output_julia = simple_two_in_two_out_mixed_type(input_julia...) + if !isa(output_julia, Tuple) + output_julia = (output_julia,) + end + for i in 1:outputSize + j = JUA_Variant(output_julia[i]) + UA_Variant_copy(Open62541.Jpointer(j), arr_output[i]) + end + return UA_STATUSCODE_GOOD + end +end + +Distributed.@spawnat Distributed.workers()[end] begin + #prepare method callbacks + @static if !Sys.isapple() || platform_key_abi().tags["arch"] != "aarch64" + w1 = UA_MethodCallback_wrap(simple_one_in_one_out) + w2 = UA_MethodCallback_wrap(simple_two_in_one_out) + w3 = UA_MethodCallback_wrap(simple_one_in_two_out) + w4 = UA_MethodCallback_wrap(simple_two_in_two_out) + w5 = UA_MethodCallback_wrap(simple_two_in_two_out_mixed_type) + m1 = UA_MethodCallback_generate(w1) + m2 = UA_MethodCallback_generate(w2) + m3 = UA_MethodCallback_generate(w3) + m4 = UA_MethodCallback_generate(w4) + m5 = UA_MethodCallback_generate(w5) + else #we are on Apple Silicon and can't use a closure in @cfunction, have to do MUCH more work. + m1 = @cfunction(c1, UA_StatusCode, + (Ptr{UA_Server}, Ptr{UA_NodeId}, Ptr{Cvoid}, + Ptr{UA_NodeId}, Ptr{Cvoid}, Ptr{UA_NodeId}, Ptr{Cvoid}, + Csize_t, Ptr{UA_Variant}, Csize_t, Ptr{UA_Variant})) + m2 = @cfunction(c2, UA_StatusCode, + (Ptr{UA_Server}, Ptr{UA_NodeId}, Ptr{Cvoid}, + Ptr{UA_NodeId}, Ptr{Cvoid}, Ptr{UA_NodeId}, Ptr{Cvoid}, + Csize_t, Ptr{UA_Variant}, Csize_t, Ptr{UA_Variant})) + m3 = @cfunction(c3, UA_StatusCode, + (Ptr{UA_Server}, Ptr{UA_NodeId}, Ptr{Cvoid}, + Ptr{UA_NodeId}, Ptr{Cvoid}, Ptr{UA_NodeId}, Ptr{Cvoid}, + Csize_t, Ptr{UA_Variant}, Csize_t, Ptr{UA_Variant})) + m4 = @cfunction(c4, UA_StatusCode, + (Ptr{UA_Server}, Ptr{UA_NodeId}, Ptr{Cvoid}, + Ptr{UA_NodeId}, Ptr{Cvoid}, Ptr{UA_NodeId}, Ptr{Cvoid}, + Csize_t, Ptr{UA_Variant}, Csize_t, Ptr{UA_Variant})) + m5 = @cfunction(c5, UA_StatusCode, + (Ptr{UA_Server}, Ptr{UA_NodeId}, Ptr{Cvoid}, + Ptr{UA_NodeId}, Ptr{Cvoid}, Ptr{UA_NodeId}, Ptr{Cvoid}, + Csize_t, Ptr{UA_Variant}, Csize_t, Ptr{UA_Variant})) + end + + #configure server + server = JUA_Server() + retval0 = JUA_ServerConfig_setMinimalCustomBuffer(JUA_ServerConfig(server), + 4842, C_NULL, 0, 0) + + #prepare method attributes + attr1 = JUA_MethodAttributes(description = "Simple One in One Out", + displayname = "Simple One in One Out", + executable = true, + userexecutable = true) + attr2 = JUA_MethodAttributes(description = "Simple Two in One Out", + displayname = "Simple Two in One Out", + executable = true, + userexecutable = true) + attr3 = JUA_MethodAttributes(description = "Simple One in Two Out", + displayname = "Simple One in Two Out", + executable = true, + userexecutable = true) + attr4 = JUA_MethodAttributes(description = "Simple Two in Two Out", + displayname = "Simple Two in Two Out", + executable = true, + userexecutable = true) + attr5 = JUA_MethodAttributes(description = "Simple Two in Two Out - Mixed Types", + displayname = "Simple Two in Two Out - Mixed Types", + executable = true, + userexecutable = true) + + #prepare method nodeids + methodid1 = JUA_NodeId(1, 62541) + methodid2 = JUA_NodeId(1, 62542) + methodid3 = JUA_NodeId(1, 62543) + methodid4 = JUA_NodeId(1, 62544) + methodid5 = JUA_NodeId(1, 62545) + + parentnodeid = JUA_NodeId(0, UA_NS0ID_OBJECTSFOLDER) + parentreferencenodeid = JUA_NodeId(0, UA_NS0ID_HASCOMPONENT) + + #prepare browsenames + browsename1 = JUA_QualifiedName(1, "Simple One in One Out") + browsename2 = JUA_QualifiedName(1, "Simple Two in One Out") + browsename3 = JUA_QualifiedName(1, "Simple One in Two Out") + browsename4 = JUA_QualifiedName(1, "Simple Two in Two Out") + browsename5 = JUA_QualifiedName(1, "Simple Two in Two Out Mixed Type") + + #prepare input arguments + oneinputarg = JUA_Argument("examplestring", name = "One input", + description = "One input") + j1 = JUA_Argument("examplestring", name = "First input", description = "First input") + j2 = JUA_Argument("examplestring", name = "Second input", description = "Second input") + twoinputarg = [j1, j2] + j3 = JUA_Argument("examplestring", name = "Name", description = "Number") + j4 = JUA_Argument(25, name = "Number", description = "Number") + twoinputarg_mixed = [j3, j4] + + #prepare output arguments + oneoutputarg = JUA_Argument( + "examplestring", name = "One output", description = "One output") + j1 = JUA_Argument("examplestring", name = "First output", description = "First output") + j2 = JUA_Argument( + "examplestring", name = "Second output", description = "Second output") + twooutputarg = [j1, j2] + j3 = JUA_Argument("examplestring", name = "Name", description = "Name") + j4 = JUA_Argument(25, name = "Number", description = "Number") + twooutputarg_mixed = [j3, j4] + + #add the nodes + retval1 = JUA_Server_addNode(server, methodid1, parentnodeid, parentreferencenodeid, + browsename1, attr1, m1, oneinputarg, oneoutputarg, + JUA_NodeId(), JUA_NodeId()) + retval2 = JUA_Server_addNode(server, methodid2, parentnodeid, parentreferencenodeid, + browsename2, attr2, m2, twoinputarg, oneoutputarg, + JUA_NodeId(), JUA_NodeId()) + retval3 = JUA_Server_addNode(server, methodid3, parentnodeid, parentreferencenodeid, + browsename3, attr3, m3, oneinputarg, twooutputarg, + JUA_NodeId(), JUA_NodeId()) + retval4 = JUA_Server_addNode(server, methodid4, parentnodeid, parentreferencenodeid, + browsename4, attr4, m4, twoinputarg, twooutputarg, + JUA_NodeId(), JUA_NodeId()) + retval5 = JUA_Server_addNode(server, methodid5, parentnodeid, parentreferencenodeid, + browsename5, attr5, m5, twoinputarg_mixed, twooutputarg_mixed, + JUA_NodeId(), JUA_NodeId()) + + # Start up the server + Distributed.@spawnat Distributed.workers()[end] redirect_stderr() # Turn off all error messages + println("Starting up the server...") + JUA_Server_runUntilInterrupt(server) +end + +client = JUA_Client() +JUA_ClientConfig_setDefault(JUA_ClientConfig(client)) +max_duration = 90.0 # Maximum waiting time for server startup +sleep_time = 3.0 # Sleep time in seconds between each connection trial +let trial + trial = 0 + while trial < max_duration / sleep_time + retval3 = JUA_Client_connect(client, "opc.tcp://localhost:4842") + if retval3 == UA_STATUSCODE_GOOD + println("Connection established.") + break + end + sleep(sleep_time) + trial = trial + 1 + end + @test trial < max_duration / sleep_time # Check if maximum number of trials has been exceeded +end + +#calling the method node with high level interface +methodid1 = JUA_NodeId(1, 62541) +methodid2 = JUA_NodeId(1, 62542) +methodid3 = JUA_NodeId(1, 62543) +methodid4 = JUA_NodeId(1, 62544) +methodid5 = JUA_NodeId(1, 62545) +parentnodeid = JUA_NodeId(0, UA_NS0ID_OBJECTSFOLDER) + +one_input = "Peter" +two_inputs = ("Bruce", "amazing") +two_inputs_mixed = ("Claudia", 25) +response1 = JUA_Client_call(client, parentnodeid, methodid1, one_input) +response2 = JUA_Client_call(client, parentnodeid, methodid2, two_inputs) +response3 = JUA_Client_call(client, parentnodeid, methodid3, one_input) +response4 = JUA_Client_call(client, parentnodeid, methodid4, two_inputs) +response5 = JUA_Client_call(client, parentnodeid, methodid5, two_inputs_mixed) + +@test response1 == "Hello Peter." +@test response2 == "Hello Bruce, you are amazing." +@test all(response3 .== ("Hello Peter.", "reteP is Peter reversed.")) +@test all(response4 .== ("Hello Bruce, you are amazing.", "amazing is the adjective.")) +@test all(response5 .== ("Hello Claudia.", 625)) +#test whether supplying wrong number of arguments throws: +@test_throws Open62541.MethodNodeInputError JUA_Client_call( + client, parentnodeid, methodid1, two_inputs) + +# Disconnect client +JUA_Client_disconnect(client) + +println("Ungracefully kill server process...") +Distributed.interrupt(Distributed.workers()[end]) +Distributed.rmprocs(Distributed.workers()[end]; waitfor = 0) diff --git a/test/client_encryption.jl b/test/client_encryption.jl index f8332af..30b77e7 100644 --- a/test/client_encryption.jl +++ b/test/client_encryption.jl @@ -12,25 +12,26 @@ Distributed.@spawnat Distributed.workers()[end] begin #generate a basic server certificate certificate = UA_ByteString_new() privateKey = UA_ByteString_new() - subject = UA_String_Array_new([UA_String_fromChars("C=DE"), - UA_String_fromChars("O=SampleOrganization"), + subject = UA_String_Array_new([UA_String_fromChars("C=DE"), + UA_String_fromChars("O=SampleOrganization"), UA_String_fromChars("CN=Open62541Server@localhost")]) lenSubject = UA_UInt32(3) - subjectAltName = UA_String_Array_new([UA_String_fromChars("DNS:localhost"), + subjectAltName = UA_String_Array_new([UA_String_fromChars("DNS:localhost"), UA_String_fromChars("URI:urn:open62541.server.application")]) lenSubjectAltName = UA_UInt32(2) kvm = UA_KeyValueMap_new() expiresIn = UA_UInt16(14) - retval0 = UA_KeyValueMap_setScalar(kvm, JUA_QualifiedName(0, "expires-in-days"), Ref(expiresIn), UA_TYPES_PTRS[UA_TYPES_UINT16]) + retval0 = UA_KeyValueMap_setScalar(kvm, JUA_QualifiedName(0, "expires-in-days"), + Ref(expiresIn), UA_TYPES_PTRS[UA_TYPES_UINT16]) retval1 = UA_CreateCertificate( - UA_Log_Stdout_new(UA_LOGLEVEL_FATAL), subject.ptr, lenSubject, subjectAltName.ptr, lenSubjectAltName, - UA_CERTIFICATEFORMAT_DER, kvm, privateKey, certificate) + UA_Log_Stdout_new(UA_LOGLEVEL_FATAL), subject.ptr, lenSubject, subjectAltName.ptr, lenSubjectAltName, + UA_CERTIFICATEFORMAT_DER, kvm, privateKey, certificate) #configure server server = JUA_Server() config = JUA_ServerConfig(server) retval2 = JUA_ServerConfig_setDefault(config) - retval3 = JUA_ServerConfig_addSecurityPolicyBasic256Sha256(config, certificate, + retval3 = JUA_ServerConfig_addSecurityPolicyBasic256Sha256(config, certificate, privateKey) retval4 = JUA_ServerConfig_addAllEndpoints(config) config.securityPolicyNoneDiscoveryOnly = true @@ -58,27 +59,28 @@ config = UA_Client_getConfig(client) #generate a client certificate certificate = UA_ByteString_new() privateKey = UA_ByteString_new() -subject = UA_String_Array_new([UA_String_fromChars("C=DE"), - UA_String_fromChars("O=SampleOrganization"), +subject = UA_String_Array_new([UA_String_fromChars("C=DE"), + UA_String_fromChars("O=SampleOrganization"), UA_String_fromChars("CN=Open62541Client@localhost")]) lenSubject = UA_UInt32(3) -subjectAltName = UA_String_Array_new([UA_String_fromChars("DNS:localhost"), +subjectAltName = UA_String_Array_new([UA_String_fromChars("DNS:localhost"), UA_String_fromChars("URI:urn:open62541.client.application")]) lenSubjectAltName = UA_UInt32(2) kvm = UA_KeyValueMap_new() expiresIn = UA_UInt16(14) -retval0 = UA_KeyValueMap_setScalar(kvm, JUA_QualifiedName(0, "expires-in-days"), Ref(expiresIn), UA_TYPES_PTRS[UA_TYPES_UINT16]) +retval0 = UA_KeyValueMap_setScalar(kvm, JUA_QualifiedName(0, "expires-in-days"), + Ref(expiresIn), UA_TYPES_PTRS[UA_TYPES_UINT16]) retval1 = UA_CreateCertificate( - UA_Log_Stdout_new(UA_LOGLEVEL_FATAL), subject.ptr, lenSubject, subjectAltName.ptr, lenSubjectAltName, - UA_CERTIFICATEFORMAT_DER, kvm, privateKey, certificate) + UA_Log_Stdout_new(UA_LOGLEVEL_FATAL), subject.ptr, lenSubject, subjectAltName.ptr, lenSubjectAltName, + UA_CERTIFICATEFORMAT_DER, kvm, privateKey, certificate) revocationList = UA_ByteString_new() revocationListSize = 0 trustList = UA_ByteString_new() trustListSize = 0 retval2 = UA_ClientConfig_setDefaultEncryption(config, certificate, privateKey, - trustList, trustListSize, - revocationList, revocationListSize) + trustList, trustListSize, + revocationList, revocationListSize) #clean up UA_ByteString_delete(revocationList) @@ -144,4 +146,4 @@ retval5 = JUA_Client_connect(client, "opc.tcp://localhost:4840") println("Ungracefully kill server process...") Distributed.interrupt(Distributed.workers()[end]) -Distributed.rmprocs(Distributed.workers()[end]; waitfor = 0) \ No newline at end of file +Distributed.rmprocs(Distributed.workers()[end]; waitfor = 0) diff --git a/test/client_memoryleaks.jl b/test/client_memoryleaks.jl new file mode 100644 index 0000000..1b7db8c --- /dev/null +++ b/test/client_memoryleaks.jl @@ -0,0 +1,134 @@ +using Open62541 +using Test + +function meminfo_julia() + Float64(Sys.maxrss() / 2^20) #gives memory use of the whole julia process in MBs +end + +#Client Call + +using Distributed +Distributed.addprocs(1) # Add a single worker process to run the server + +Distributed.@everywhere begin + using Open62541 + using Test + using Pkg + using Pkg.BinaryPlatforms + + #create methods that will be used later + function simple_two_in_two_out_mixed_type(name, number) + out1 = "Hello " * name * "." + out2 = number * number + return (out1, out2) + end + + function c5(server, sessionId, sessionHandle, methodId, methodContext, objectId, + objectContext, inputSize, input, outputSize, output) + arr_input = UA_Array(input, Int64(inputSize)) + arr_output = UA_Array(output, Int64(outputSize)) + input_julia = Open62541.__get_juliavalues_from_variant.(arr_input, Any) + output_julia = simple_two_in_two_out_mixed_type(input_julia...) + if !isa(output_julia, Tuple) + output_julia = (output_julia,) + end + for i in 1:outputSize + j = JUA_Variant(output_julia[i]) + UA_Variant_copy(Open62541.Jpointer(j), arr_output[i]) + end + return UA_STATUSCODE_GOOD + end +end + +Distributed.@spawnat Distributed.workers()[end] begin + #prepare method callbacks + @static if !Sys.isapple() || platform_key_abi().tags["arch"] != "aarch64" + w5 = UA_MethodCallback_wrap(simple_two_in_two_out_mixed_type) + m5 = UA_MethodCallback_generate(w5) + else #we are on Apple Silicon and can't use a closure in @cfunction, have to do MUCH more work. + m5 = @cfunction(c5, UA_StatusCode, + (Ptr{UA_Server}, Ptr{UA_NodeId}, Ptr{Cvoid}, + Ptr{UA_NodeId}, Ptr{Cvoid}, Ptr{UA_NodeId}, Ptr{Cvoid}, + Csize_t, Ptr{UA_Variant}, Csize_t, Ptr{UA_Variant})) + end + + #configure server + server = JUA_Server() + retval0 = JUA_ServerConfig_setMinimalCustomBuffer(JUA_ServerConfig(server), + 4842, C_NULL, 0, 0) + + #prepare method attributes + attr5 = JUA_MethodAttributes(description = "Simple Two in Two Out - Mixed Types", + displayname = "Simple Two in Two Out - Mixed Types", + executable = true, + userexecutable = true) + + #prepare method nodeids + methodid5 = JUA_NodeId(1, 62545) + + parentnodeid = JUA_NodeId(0, UA_NS0ID_OBJECTSFOLDER) + parentreferencenodeid = JUA_NodeId(0, UA_NS0ID_HASCOMPONENT) + + #prepare browsenames + browsename5 = JUA_QualifiedName(1, "Simple Two in Two Out Mixed Type") + + #prepare input arguments + j3 = JUA_Argument("examplestring", name = "Name", description = "Number") + j4 = JUA_Argument(25, name = "Number", description = "Number") + twoinputarg_mixed = [j3, j4] + + #prepare output arguments + j3 = JUA_Argument("examplestring", name = "Name", description = "Name") + j4 = JUA_Argument(25, name = "Number", description = "Number") + twooutputarg_mixed = [j3, j4] + + #add the nodes + retval5 = JUA_Server_addNode(server, methodid5, parentnodeid, parentreferencenodeid, + browsename5, attr5, m5, twoinputarg_mixed, twooutputarg_mixed, + JUA_NodeId(), JUA_NodeId()) + + # Start up the server + Distributed.@spawnat Distributed.workers()[end] redirect_stderr() # Turn off all error messages + println("Starting up the server...") + JUA_Server_runUntilInterrupt(server) +end + + +client = JUA_Client() +JUA_ClientConfig_setDefault(JUA_ClientConfig(client)) +max_duration = 90.0 # Maximum waiting time for server startup +sleep_time = 3.0 # Sleep time in seconds between each connection trial +let trial + trial = 0 + while trial < max_duration / sleep_time + retval3 = JUA_Client_connect(client, "opc.tcp://localhost:4842") + if retval3 == UA_STATUSCODE_GOOD + println("Connection established.") + break + end + sleep(sleep_time) + trial = trial + 1 + end + @test trial < max_duration / sleep_time # Check if maximum number of trials has been exceeded +end + +#calling the method node with high level interface +methodid5 = JUA_NodeId(1, 62545) +parentnodeid = JUA_NodeId(0, UA_NS0ID_OBJECTSFOLDER) +two_inputs_mixed = ("Claudia", 25) + +#the actual memory leak tests +mem_start = meminfo_julia() +for i in 1:1_000_000 + response5 = JUA_Client_call(client, parentnodeid, methodid5, two_inputs_mixed) +end +GC.gc() +mem_end = meminfo_julia() +@test (mem_end - mem_start) < 100.0 + + +# Disconnect client & kill the server +JUA_Client_disconnect(client) +println("Ungracefully kill server process...") +Distributed.interrupt(Distributed.workers()[end]) +Distributed.rmprocs(Distributed.workers()[end]; waitfor = 0) diff --git a/test/client_read.jl b/test/client_read.jl index d145dfd..f4652c6 100644 --- a/test/client_read.jl +++ b/test/client_read.jl @@ -21,7 +21,7 @@ Distributed.@spawnat Distributed.workers()[end] begin server = UA_Server_new() retval = UA_ServerConfig_setMinimalCustomBuffer(UA_Server_getConfig(server), - 4842, C_NULL, 0, 0) + 4842, C_NULL, 0, 0) @test retval == UA_STATUSCODE_GOOD # Add variable node containing a scalar to the server @@ -38,13 +38,13 @@ Distributed.@spawnat Distributed.workers()[end] begin nodecontext1 = C_NULL outnewnodeid1 = C_NULL retval = UA_Server_addVariableNode(server, variablenodeid, parentnodeid1, - parentreferencenodeid1, browsename1, typedefinition1, attr1, nodecontext1, + parentreferencenodeid1, browsename1, typedefinition1, attr1, nodecontext1, outnewnodeid1) #test whether adding node to the server worked @test retval == UA_STATUSCODE_GOOD #add a variabletype node - input = zeros(2) + input = zeros(2) accesslevel = UA_ACCESSLEVEL(read = true) displayname = "2D point type" description = "This is a 2D point type." @@ -58,9 +58,9 @@ Distributed.@spawnat Distributed.workers()[end] begin nodecontext2 = C_NULL outnewnodeid2 = C_NULL retval = UA_Server_addVariableTypeNode(server, variabletypenodeid, parentnodeid2, - parentreferencenodeid2, browsename2, typedefinition2, attr2, nodecontext2, + parentreferencenodeid2, browsename2, typedefinition2, attr2, nodecontext2, outnewnodeid2) - + #test whether adding node to the server worked @test retval == UA_STATUSCODE_GOOD @@ -103,7 +103,6 @@ let trial @test trial < max_duration / sleep_time # Check if maximum number of trials has been exceeded end - #gather the previously defined nodes variablenodeid = UA_NODEID_STRING_ALLOC(1, "scalar variable") variabletypenodeid = UA_NODEID_STRING_ALLOC(1, "variabletype 2Dpoint") @@ -118,14 +117,15 @@ for node in nodes attributeset = UA_VariableAttributes elseif nodeclass == UA_NODECLASS_VARIABLETYPE attributeset = UA_VariableTypeAttributes - end + end for att in Open62541.attributes_UA_Client_read fun_name = Symbol(att[1]) attr_type = Symbol(att[3]) - generator = Symbol(att[3]*"_new") - cleaner = Symbol(att[3]*"_delete") + generator = Symbol(att[3] * "_new") + cleaner = Symbol(att[3] * "_delete") out2 = eval(generator)() - if in(Symbol(lowercasefirst(att[2])), fieldnames(attributeset)) || in(Symbol(lowercasefirst(att[2])), fieldnames(UA_NodeHead)) + if in(Symbol(lowercasefirst(att[2])), fieldnames(attributeset)) || + in(Symbol(lowercasefirst(att[2])), fieldnames(UA_NodeHead)) @test isa(eval(fun_name)(client, node, out2), UA_StatusCode) end # else #TODO: re-consider this diff --git a/test/client_service.jl b/test/client_service.jl index b07da04..a2309be 100644 --- a/test/client_service.jl +++ b/test/client_service.jl @@ -13,7 +13,7 @@ end Distributed.@spawnat Distributed.workers()[end] begin server = UA_Server_new() retval = UA_ServerConfig_setMinimalCustomBuffer(UA_Server_getConfig(server), - 4842, C_NULL, 0, 0) + 4842, C_NULL, 0, 0) @test retval == UA_STATUSCODE_GOOD # Start up the server diff --git a/test/simple_server_client.jl b/test/client_simple.jl similarity index 100% rename from test/simple_server_client.jl rename to test/client_simple.jl diff --git a/test/client_subscriptions.jl b/test/client_subscriptions.jl index 518d2a3..6cd4714 100644 --- a/test/client_subscriptions.jl +++ b/test/client_subscriptions.jl @@ -1,7 +1,10 @@ #adapted from: https://github.com/open62541/open62541/blob/master/examples/client_subscription_loop.c +#the example (as of 2024-11-20) wants to create a subscription from within the +#callback, which is not allowed, see here: +#https://github.com/open62541/open62541/issues/5816 +#Unmerged PR addressing this: https://github.com/open62541/open62541/pull/5905 using Distributed -using Printf Distributed.addprocs(1) # Add a single worker process to run the server Distributed.@everywhere begin @@ -13,7 +16,7 @@ Distributed.@spawnat Distributed.workers()[end] begin #configure the server server = UA_Server_new() retval = UA_ServerConfig_setMinimalCustomBuffer(UA_Server_getConfig(server), - 4842, C_NULL, 0, 0) + 4843, C_NULL, 0, 0) # Start up the server Distributed.@spawnat Distributed.workers()[end] redirect_stderr() # Turn off all error messages @@ -23,13 +26,25 @@ end # Specify client and connect to server after server startup client = UA_Client_new() -UA_ClientConfig_setDefault(UA_Client_getConfig(client)) +config = UA_Client_getConfig(client) +UA_ClientConfig_setDefault(config) + +#define callbacks +function handler_simple(client, subId, subContext, monId, monContext, + value) + push!(container, rand()) #we just collect a bunch of random numbers here. + return nothing +end +handlercb = @cfunction(handler_simple, Cvoid, + (Ptr{UA_Client}, UInt32, Ptr{Cvoid}, UInt32, Ptr{Cvoid}, UA_DataValue)) + +#connect the client max_duration = 90.0 # Maximum waiting time for server startup sleep_time = 3.0 # Sleep time in seconds between each connection trial let trial trial = 0 while trial < max_duration / sleep_time - retval = UA_Client_connect(client, "opc.tcp://localhost:4842") + retval = UA_Client_connect(client, "opc.tcp://localhost:4843") if retval == UA_STATUSCODE_GOOD println("Connection established.") break @@ -40,92 +55,23 @@ let trial @test trial < max_duration / sleep_time # Check if maximum number of trials has been exceeded end -container = String[] - -function handler_currentTimeChanged(client, subId, subContext, monId, monContext, - value) - if UA_Variant_hasScalarType(value.value, UA_TYPES_PTRS[UA_TYPES_DATETIME]) - raw_date = unsafe_wrap(value.value) - dts = UA_DateTime_toStruct(raw_date) - push!(container, Printf.@sprintf("current date and time (UTC) is: %u-%u-%u %u:%u:%u.%03u\n", - dts.day, dts.month, dts.year, dts.hour, dts.min, dts.sec, dts.milliSec)) - - end - return nothing -end - -function deleteSubscriptionCallback(client, subscriptionId, subscriptionContext) - println("Subscription Id $subscriptionId was deleted") - return nothing -end - -function subscriptionInactivityCallback(client, subId, subContext) - println("Inactivity for subscription $subId.") - return nothing -end - -function stateCallback(client, channelState, sessionState, recoveryStatus) - if channelState == UA_SECURECHANNELSTATE_CLOSED - println("The client is disconnected") - elseif channelState == UA_SECURECHANNELSTATE_HEL_SENT - println("Waiting for ack") - elseif channelState == UA_SECURECHANNELSTATE_OPN_SENT - println("Waiting for OPN Response") - elseif channelState == UA_SECURECHANNELSTATE_OPEN - println("A SecureChannel to the server is open") - else - #donothing - end - - if sessionState == UA_SESSIONSTATE_ACTIVATED - println("A session with the server is activated") - # A new session was created. We need to create the subscription. - # Create a subscription - request = UA_CreateSubscriptionRequest_default() - delcb = @cfunction(deleteSubscriptionCallback, Cvoid, (Ptr{UA_Client}, UInt32, Ptr{Cvoid})) - response = UA_Client_Subscriptions_create(client, unsafe_load(request), C_NULL, C_NULL, delcb) - if response.responseHeader.serviceResult == UA_STATUSCODE_GOOD - println("Create subscription succeeded, id $(response.subscriptionId)") - else - #something failed? - end - - # Add a MonitoredItem - currentTimeNode = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME) - monRequest = UA_MonitoredItemCreateRequest_default(currentTimeNode) - handlercb = @cfunction(handler_currentTimeChanged, Cvoid, (Ptr{UA_Client}, UInt32, Ptr{Cvoid}, UInt32, Ptr{Cvoid}, UA_DataValue)) - monResponse = UA_Client_MonitoredItems_createDataChange(client, response.subscriptionId, - UA_TIMESTAMPSTORETURN_BOTH, unsafe_load(monRequest), - C_NULL, handlercb, C_NULL) - if monResponse.statusCode == UA_STATUSCODE_GOOD - println("Monitoring UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME, id: $(monResponse.monitoredItemId)") - end - elseif sessionState == UA_SESSIONSTATE_CLOSED - println("Session disconnected") - else - #donothing - end - return nothing -end - - -client = UA_Client_new() -cc = UA_Client_getConfig(client) -UA_ClientConfig_setDefault(cc) - -# Set callbacks -cbstate = @cfunction(stateCallback, Cvoid, (Ptr{UA_Client}, UA_SecureChannelState, UA_SessionState, UA_StatusCode)) -cc.stateCallback = cbstate -subcb = @cfunction(subscriptionInactivityCallback, Cvoid, (Ptr{UA_Client}, UInt32, Ptr{Cvoid})) -cc.subscriptionInactivityCallback = subcb +#create a subscription +request = UA_CreateSubscriptionRequest_default() +response = UA_Client_Subscriptions_create( + client, unsafe_load(request), C_NULL, C_NULL, C_NULL) -#connect client -ret = UA_Client_connect(client, "opc.tcp://localhost:4842") -@test ret == UA_STATUSCODE_GOOD +#create a monitored item +currentTimeNode = UA_NODEID_NUMERIC(0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME) +monRequest = UA_MonitoredItemCreateRequest_default(currentTimeNode) +monResponse = UA_Client_MonitoredItems_createDataChange(client, response.subscriptionId, + UA_TIMESTAMPSTORETURN_BOTH, unsafe_load(monRequest), + C_NULL, handlercb, C_NULL) -UA_Client_run_iterate(client, 1000) -sleep(7) -container = String[] +#now interrogate the thing +container = Float64[] #need to initialize variable here, otherwise error (use in handler_currentTimeChanged(...)) +UA_Client_run_iterate(client, 1000) +container = Float64[] +sleep(7) UA_Client_run_iterate(client, 1000) #see UA_CreateSubscriptionRequest_default(); # requestedPublishingInterval = 500.0 @@ -134,4 +80,8 @@ UA_Client_run_iterate(client, 1000) @test length(container) == 10 UA_Client_disconnect(client) -UA_Client_delete(client) +UA_Client_delete(client) + +println("Ungracefully kill server process...") +Distributed.interrupt(Distributed.workers()[end]) +Distributed.rmprocs(Distributed.workers()[end]; waitfor = 0) diff --git a/test/username_password_login_accesscontrol.jl b/test/client_username_password_login_accesscontrol.jl similarity index 100% rename from test/username_password_login_accesscontrol.jl rename to test/client_username_password_login_accesscontrol.jl diff --git a/test/client_write.jl b/test/client_write.jl index 895022d..34a38e9 100644 --- a/test/client_write.jl +++ b/test/client_write.jl @@ -21,17 +21,17 @@ Distributed.@spawnat Distributed.workers()[end] begin server = UA_Server_new() retval = UA_ServerConfig_setMinimalCustomBuffer(UA_Server_getConfig(server), - 4842, C_NULL, 0, 0) + 4842, C_NULL, 0, 0) @test retval == UA_STATUSCODE_GOOD # Add variable node containing a scalar to the server #add a variable node accesslevel = UA_ACCESSLEVEL(read = true, write = true) writemask = UA_WRITEMASK(; accesslevel = true, arraydimensions = true, - datatype = true, - description = true, displayname = true, isabstract = true, minimumsamplinginterval = true, - userwritemask = true, valuerank = true, historizing = true, - writemask = true) + datatype = true, + description = true, displayname = true, isabstract = true, minimumsamplinginterval = true, + userwritemask = true, valuerank = true, historizing = true, + writemask = true) userwritemask = writemask input = rand(Float64) attr1 = UA_VariableAttributes_generate(value = input, displayname = "scalar variable", @@ -46,21 +46,22 @@ Distributed.@spawnat Distributed.workers()[end] begin nodecontext1 = C_NULL outnewnodeid1 = C_NULL retval = UA_Server_addVariableNode(server, variablenodeid, parentnodeid1, - parentreferencenodeid1, browsename1, typedefinition1, attr1, nodecontext1, + parentreferencenodeid1, browsename1, typedefinition1, attr1, nodecontext1, outnewnodeid1) #test whether adding node to the server worked @test retval == UA_STATUSCODE_GOOD #add a variabletype node - input = zeros(2) + input = zeros(2) accesslevel = UA_ACCESSLEVEL(read = true) displayname = "2D point type" description = "This is a 2D point type." writemask = UA_WRITEMASK(; arraydimensions = true, - datatype = true, - description = true, displayname = true, isabstract = true, minimumsamplinginterval = false, nodeclass = false, - userwritemask = true, valuerank = true, - writemask = true, valueforvariabletype = true) + datatype = true, + description = true, displayname = true, isabstract = true, + minimumsamplinginterval = false, nodeclass = false, + userwritemask = true, valuerank = true, + writemask = true, valueforvariabletype = true) userwritemask = writemask attr2 = UA_VariableTypeAttributes_generate(value = input, displayname = displayname, @@ -74,9 +75,9 @@ Distributed.@spawnat Distributed.workers()[end] begin nodecontext2 = C_NULL outnewnodeid2 = C_NULL retval = UA_Server_addVariableTypeNode(server, variabletypenodeid, parentnodeid2, - parentreferencenodeid2, browsename2, typedefinition2, attr2, nodecontext2, + parentreferencenodeid2, browsename2, typedefinition2, attr2, nodecontext2, outnewnodeid2) - + #test whether adding node to the server worked @test retval == UA_STATUSCODE_GOOD @@ -120,7 +121,6 @@ let trial @test trial < max_duration / sleep_time # Check if maximum number of trials has been exceeded end - #gather the previously defined nodes variablenodeid = UA_NODEID_STRING_ALLOC(1, "scalar variable") variabletypenodeid = UA_NODEID_STRING_ALLOC(1, "variabletype 2Dpoint") @@ -139,16 +139,17 @@ for node in nodes elseif nodeclass == UA_NODECLASS_VARIABLETYPE attributeset = UA_VariableTypeAttributes nonvalidattr = (:NodeId, :NodeClass, :BrowseName, :UserWriteMask) #as above - end + end for att in Open62541.attributes_UA_Client_write fun_write = Symbol(att[1]) fun_read = Symbol(replace(att[1], "write" => "read")) attr_name = Symbol(att[2]) - generator = Symbol(att[3]*"_new") - cleaner = Symbol(att[3]*"_delete") + generator = Symbol(att[3] * "_new") + cleaner = Symbol(att[3] * "_delete") if (in(Symbol(lowercasefirst(att[2])), fieldnames(attributeset)) || - in(Symbol(lowercasefirst(att[2])), fieldnames(UA_NodeHead))) && att[3] != "UA_DataType" && - att[1] != "UA_Client_writeValueAttributeEx" + in(Symbol(lowercasefirst(att[2])), fieldnames(UA_NodeHead))) && + att[3] != "UA_DataType" && + att[1] != "UA_Client_writeValueAttributeEx" out2 = eval(generator)() statuscode1 = eval(fun_read)(client, node, out2) #read @test statuscode1 == UA_STATUSCODE_GOOD diff --git a/test/exceptions.jl b/test/exceptions.jl index 577e421..fdbc953 100644 --- a/test/exceptions.jl +++ b/test/exceptions.jl @@ -45,7 +45,8 @@ var1 = UA_Variant_new() #AttributeReadWriteError - UA_Client_readX function out2 = UA_Variant_new() -@test_throws Open62541.AttributeReadWriteError UA_Client_readValueAttribute(client, bogusid, out2) +@test_throws Open62541.AttributeReadWriteError UA_Client_readValueAttribute( + client, bogusid, out2) #AttributeReadWriteError - UA_Client_readX function var2 = UA_Variant_new() diff --git a/test/highlevel_types.jl b/test/highlevel_types.jl index 26b2f99..c1daa5a 100644 --- a/test/highlevel_types.jl +++ b/test/highlevel_types.jl @@ -27,10 +27,13 @@ j2 = JUA_Variant(v) @test j2 isa JUA_Variant UA_Variant_delete(v) @test_throws Open62541.UnsupportedNumberTypeError JUA_Variant(Rational(true, false)) -@test_throws Open62541.UnsupportedNumberTypeError JUA_Variant([Complex(Rational(1, 2), Rational(3, 4)), Complex(Rational(5, 6), Rational(7, 8))]) -@test_throws Open62541.UnsupportedNumberTypeError JUA_Variant([Complex(Int16(1), Int16(3)), Complex(Int32(4), Int32(5))]) +@test_throws Open62541.UnsupportedNumberTypeError JUA_Variant([ + Complex(Rational(1, 2), Rational(3, 4)), Complex(Rational(5, 6), Rational(7, 8))]) +@test_throws Open62541.UnsupportedNumberTypeError JUA_Variant([ + Complex(Int16(1), Int16(3)), Complex(Int32(4), Int32(5))]) @test_throws Open62541.UnsupportedNumberTypeError JUA_Variant(Complex(Int16(1), Int16(3))) -@test_throws Open62541.UnsupportedNumberTypeError JUA_Variant(Complex(Rational(1, 2), Rational(3, 4))) +@test_throws Open62541.UnsupportedNumberTypeError JUA_Variant(Complex( + Rational(1, 2), Rational(3, 4))) #JUA_NodeId j1 = JUA_NodeId() @@ -135,3 +138,76 @@ UA_ReferenceTypeAttributes_delete(u5) UA_DataTypeAttributes_delete(u6) UA_ViewAttributes_delete(u7) UA_MethodAttributes_delete(u8) + +## JUA_Argument +siz_a = [4, 4, 4] +siz_b = [11, 2] +siz_c = 3 +a = zeros(Float32, siz_a...) +b = zeros(UInt8, siz_b...) +c = ["first", "second", "third"] +ja = JUA_Argument(a) +jb = JUA_Argument(b) +jc = JUA_Argument(c) +jd = JUA_Argument(a, valuerank = -2) + +#check data types +@test UA_NodeId_equal(ja.dataType, UA_NODEID("i=" * string(UA_TYPES_FLOAT + 1))) +@test UA_NodeId_equal(jb.dataType, UA_NODEID("i=" * string(UA_TYPES_BYTE + 1))) +@test UA_NodeId_equal(jc.dataType, UA_NODEID("i=" * string(UA_TYPES_STRING + 1))) + +#check array size information +@test all(siz_a .== unsafe_wrap( + Array, unsafe_load(ja.arrayDimensions), unsafe_load(ja.arrayDimensionsSize))) +@test all(siz_b .== unsafe_wrap( + Array, unsafe_load(jb.arrayDimensions), unsafe_load(jb.arrayDimensionsSize))) +@test all(siz_c .== unsafe_wrap( + Array, unsafe_load(jc.arrayDimensions), unsafe_load(jc.arrayDimensionsSize))) + +#check value rank +@test length(siz_a) == unsafe_load(ja.valueRank) +@test length(siz_b) == unsafe_load(jb.valueRank) +@test length(siz_c) == unsafe_load(jc.valueRank) +@test -2 == unsafe_load(jd.valueRank) + +#check the consistency check function in helper_functions.jl +@test isa(JUA_Argument(), JUA_Argument) +@test isa(JUA_Argument(valuerank = -3), JUA_Argument) +@test isa(JUA_Argument(valuerank = -2), JUA_Argument) +@test isa(JUA_Argument(valuerank = -1), JUA_Argument) +@test isa(JUA_Argument(valuerank = -3), JUA_Argument) + +#valurank = -3; scalar or one dim array +@test isa(JUA_Argument("test", valuerank = -3), JUA_Argument) +@test isa(JUA_Argument(ones(3), valuerank = -3), JUA_Argument) + +#valuerank = -2; scalar or array of any dim +@test isa(JUA_Argument(1, valuerank = -2), JUA_Argument) +@test isa(JUA_Argument(ones(3), valuerank = -2), JUA_Argument) +@test isa(JUA_Argument(ones(3, 2), valuerank = -2), JUA_Argument) +@test isa(JUA_Argument(ones(3, 2, 4), valuerank = -2), JUA_Argument) + +#valuerank = -1; scalar +@test isa(JUA_Argument(1, valuerank = -1), JUA_Argument) + +#valuerank = 0; array of one or more dimensions +@test isa(JUA_Argument(ones(3), valuerank = 0), JUA_Argument) +@test isa(JUA_Argument(ones(3, 2), valuerank = 0), JUA_Argument) + +#valuerank = 1,2,3; array with num dimensions equal to valuerank +@test isa(JUA_Argument(valuerank = 1, arraydimensions = 1), JUA_Argument) +@test isa(JUA_Argument([1], valuerank = 1), JUA_Argument) +@test isa(JUA_Argument(ones(3, 2), valuerank = 2), JUA_Argument) +@test isa(JUA_Argument(ones(3, 2, 3), valuerank = 3), JUA_Argument) + +#Now test combinations that should throw an exception +@test_throws Open62541.ValueRankArraySizeConsistencyError JUA_Argument(valuerank = -3, + arraydimensions = [1]) +@test_throws Open62541.ValueRankArraySizeConsistencyError JUA_Argument(valuerank = -3, + arraydimensions = [1, 2]) +@test_throws Open62541.ValueRankArraySizeConsistencyError JUA_Argument(valuerank = -2, + arraydimensions = [1, 2]) +@test_throws Open62541.ValueRankArraySizeConsistencyError JUA_Argument(valuerank = -1, + arraydimensions = [1, 2]) +@test_throws Open62541.ValueRankArraySizeConsistencyError JUA_Argument(valuerank = 1, + arraydimensions = [1, 2]) diff --git a/test/nodeids.jl b/test/nodeids.jl index 704076b..423ace8 100644 --- a/test/nodeids.jl +++ b/test/nodeids.jl @@ -197,7 +197,7 @@ j16 = JUA_ExpandedNodeId(nod) j17 = JUA_ExpandedNodeId(jod) j18 = JUA_ExpandedNodeId(1, guid) j19 = JUA_ExpandedNodeId(1, jguid) -j20 = JUA_ExpandedNodeId(1234, ns_uri, 1) +j20 = JUA_ExpandedNodeId(1234, ns_uri, 1) j21 = JUA_ExpandedNodeId(s2, ns_uri, 1) j22 = JUA_ExpandedNodeId(ua_s2, ns_uri, 1) j23 = JUA_ExpandedNodeId(jua_s2, ns_uri, 1) diff --git a/test/runtests.jl b/test/runtests.jl index 86c63a6..356e0dd 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,6 +1,8 @@ using SafeTestsets using Test +const MEMLEAK = get(ENV, "MEMLEAK", false) + @safetestset "Aqua" begin include("aqua.jl") end @@ -65,13 +67,30 @@ end include("server_add_nodes_highlevelinterface.jl") end -@safetestset "Memory leaks" begin - include("memoryleaks.jl") +if MEMLEAK == true + @safetestset "Server Memory leaks" begin + include("server_memoryleaks.jl") + end end #Testsets below here use Distributed; normal testsets required # !!! Leakage of variables must be assessed manually. !!! #see: https://github.com/YingboMa/SafeTestsets.jl/issues/13 + +if MEMLEAK == true + @testset "Client Memory Leaks" begin + include("client_memoryleaks.jl") + end +end + +@testset "Simple Server/Client" begin + include("client_simple.jl") +end + +@testset "Client subscriptions" begin + include("client_subscriptions.jl") +end + @testset "Client read functions" begin include("client_read.jl") end @@ -84,24 +103,20 @@ end include("client_service.jl") end -@testset "Client subscriptions" begin - include("client_service.jl") -end - -@testset "Simple Server/Client" begin - include("simple_server_client.jl") +@testset "Client call method" begin + include("client_callmethod.jl") end -@testset "Add, read, change scalar variables" begin - include("add_change_var_scalar.jl") +@testset "Client Add, read, change scalar variables" begin + include("client_add_change_var_scalar.jl") end -@testset "Add, read, change array variables" begin - include("add_change_var_array.jl") +@testset "Client Add, read, change array variables" begin + include("client_add_change_var_array.jl") end -@testset "Username/password login & access control" begin - include("username_password_login_accesscontrol.jl") +@testset "Client Username/password login & access control" begin + include("client_username_password_login_accesscontrol.jl") end @testset "Encryption" begin diff --git a/test/server_accesscontrol.jl b/test/server_accesscontrol.jl index 54fda5c..e2cf003 100644 --- a/test/server_accesscontrol.jl +++ b/test/server_accesscontrol.jl @@ -9,17 +9,17 @@ config = JUA_ServerConfig(server) JUA_ServerConfig_setDefault(config) #define some access control features and username, password combinations -allowAnonymous = false +allowAnonymous = false batmanlogin = JUA_UsernamePasswordLogin("BruceWayne", "IamBatman") -spidermanlogin = JUA_UsernamePasswordLogin("PeterParker", "IamSpiderman") +spidermanlogin = JUA_UsernamePasswordLogin("PeterParker", "IamSpiderman") logins = [batmanlogin, spidermanlogin] -retval1 = JUA_AccessControl_default(config, allowAnonymous, batmanlogin) -retval2 = JUA_AccessControl_default(config, allowAnonymous, logins) -retval3 = JUA_AccessControl_default(config, allowAnonymous, batmanlogin, "http://test.org") -retval4 = JUA_AccessControl_default(config, allowAnonymous, logins, "http://test.org") +retval1 = JUA_AccessControl_default(config, allowAnonymous, batmanlogin) +retval2 = JUA_AccessControl_default(config, allowAnonymous, logins) +retval3 = JUA_AccessControl_default(config, allowAnonymous, batmanlogin, "http://test.org") +retval4 = JUA_AccessControl_default(config, allowAnonymous, logins, "http://test.org") -@test retval1 == 0 -@test retval2 == 0 -@test retval3 == 0 -@test retval4 == 0 +@test retval1 == UA_STATUSCODE_GOOD +@test retval2 == UA_STATUSCODE_GOOD +@test retval3 == UA_STATUSCODE_GOOD +@test retval4 == UA_STATUSCODE_GOOD diff --git a/test/server_add_nodes.jl b/test/server_add_nodes.jl index 9fc7534..b9ae653 100644 --- a/test/server_add_nodes.jl +++ b/test/server_add_nodes.jl @@ -260,8 +260,8 @@ requestednewnodeid = UA_NodeId_new() parentreferencenodeid = UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT) browsename = UA_QUALIFIEDNAME(1, "ManufacturerName") typedefinition = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE) -retval9 = UA_Server_addVariableNode(server, requestednewnodeid, - deviceTypeId, parentreferencenodeid, browsename, typedefinition, +retval9 = UA_Server_addVariableNode(server, requestednewnodeid, + deviceTypeId, parentreferencenodeid, browsename, typedefinition, mnAttr, C_NULL, manufacturerNameId) @test retval9 == UA_STATUSCODE_GOOD @@ -293,7 +293,7 @@ requestednewnodeid = UA_NodeId_new() parentreferencenodeid = UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT) browsename = UA_QUALIFIEDNAME(1, "ModelName") typedefinition = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE) -retval11 = UA_Server_addVariableNode(server, requestednewnodeid, +retval11 = UA_Server_addVariableNode(server, requestednewnodeid, deviceTypeId, parentreferencenodeid, browsename, typedefinition, modelAttr, C_NULL, C_NULL) @test retval11 == UA_STATUSCODE_GOOD @@ -332,8 +332,8 @@ requestednewnodeid = UA_NodeId_new() parentreferencenodeid = UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT) browsename = UA_QUALIFIEDNAME(1, "Status") typedefinition = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE) -retval13 = UA_Server_addVariableNode(server, requestednewnodeid, - pumpTypeId, parentreferencenodeid, browsename, typedefinition, +retval13 = UA_Server_addVariableNode(server, requestednewnodeid, + pumpTypeId, parentreferencenodeid, browsename, typedefinition, statusAttr, C_NULL, statusId) @test retval13 == UA_STATUSCODE_GOOD @@ -365,8 +365,8 @@ requestednewnodeid = UA_NodeId_new() parentreferencenodeid = UA_NODEID_NUMERIC(0, UA_NS0ID_HASCOMPONENT) browsename = UA_QUALIFIEDNAME(1, "MotorRPMs") typedefinition = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE) -retval15 = UA_Server_addVariableNode(server, requestednewnodeid, - pumpTypeId, parentreferencenodeid, browsename, +retval15 = UA_Server_addVariableNode(server, requestednewnodeid, + pumpTypeId, parentreferencenodeid, browsename, typedefinition, rpmAttr, C_NULL, C_NULL) @test retval15 == UA_STATUSCODE_GOOD @@ -454,17 +454,17 @@ r2 = addPumpObjectInstance(server, "pump3", pumpTypeId) #should have status = fa addPumpTypeConstructor(server, pumpTypeId) r3 = addPumpObjectInstance(server, "pump4", pumpTypeId) #should have status = true r4 = addPumpObjectInstance(server, "pump5", pumpTypeId) #should have status = true -@test r1 == UA_STATUSCODE_GOOD -@test r2 == UA_STATUSCODE_GOOD -@test r3 == UA_STATUSCODE_GOOD -@test r4 == UA_STATUSCODE_GOOD +@test r1 == UA_STATUSCODE_GOOD +@test r2 == UA_STATUSCODE_GOOD +@test r3 == UA_STATUSCODE_GOOD +@test r4 == UA_STATUSCODE_GOOD #TODO: should actually check the status value and not just whether adding things went ok. #clean up pumpTypeId UA_NodeId_delete(pumpTypeId) - #add method node - #follows this: https://www.open62541.org/doc/1.3/tutorial_server_method.html +#add method node +#follows this: https://www.open62541.org/doc/1.3/tutorial_server_method.html function helloWorld(server, sessionId, sessionHandle, methodId, methodContext, objectId, objectContext, inputSize, input, outputSize, output) diff --git a/test/server_add_nodes_highlevelinterface.jl b/test/server_add_nodes_highlevelinterface.jl index 86c1ead..b989945 100644 --- a/test/server_add_nodes_highlevelinterface.jl +++ b/test/server_add_nodes_highlevelinterface.jl @@ -55,7 +55,7 @@ browsename = JUA_QualifiedName(1, varnodetext) nodecontext = JUA_NodeId() outnewnodeid = JUA_NodeId() retval2 = JUA_Server_addNode(server, varnodeid, parentnodeid, - parentreferencenodeid, browsename, attr, nodecontext, outnewnodeid, + parentreferencenodeid, browsename, attr, nodecontext, outnewnodeid, typedefinition) # Test whether adding node to the server worked @test retval2 == UA_STATUSCODE_GOOD @@ -102,7 +102,7 @@ browsename = JUA_QualifiedName(1, "2DPoint variable") nodecontext = JUA_NodeId() retval4 = JUA_Server_addNode(server, JUA_NodeId(), parentnodeid, - parentreferencenodeid, browsename, attr, nodecontext, pointvariableid1, + parentreferencenodeid, browsename, attr, nodecontext, pointvariableid1, pointtypeid) # Test whether adding the variable type node to the server worked @test retval4 == UA_STATUSCODE_GOOD @@ -196,7 +196,7 @@ referenceTypeId = JUA_NodeId(0, UA_NS0ID_HASCOMPONENT) browseName = JUA_QualifiedName(1, "ManufacturerName") typeDefinition = JUA_NodeId(0, UA_NS0ID_BASEDATAVARIABLETYPE) nodeContext = JUA_NodeId() -retval9 = JUA_Server_addNode(server, requestedNewNodeid, deviceTypeId, +retval9 = JUA_Server_addNode(server, requestedNewNodeid, deviceTypeId, referenceTypeId, browseName, mnAttr, nodeContext, manufacturerNameId, typeDefinition) @test retval9 == UA_STATUSCODE_GOOD @@ -237,11 +237,11 @@ retval12 = JUA_Server_addNode(server, JUA_NodeId(), pumpTypeId, statusAttr, JUA_NodeId(), statusId, JUA_NodeId(0, UA_NS0ID_BASEDATAVARIABLETYPE)) @test retval12 == UA_STATUSCODE_GOOD -#TODO: would need to introduce JUA_ExpandedNodeId in highlevel_types.jl before revising this +#TODO: Check out UA_Server_addReference # Make the status variable mandatory */ retval13 = UA_Server_addReference(server, Open62541.Jpointer(statusId), - UA_NODEID_NUMERIC(0, UA_NS0ID_HASMODELLINGRULE), - UA_EXPANDEDNODEID_NUMERIC(0, UA_NS0ID_MODELLINGRULE_MANDATORY), true) + JUA_NodeId(0, UA_NS0ID_HASMODELLINGRULE), + JUA_ExpandedNodeId(0, UA_NS0ID_MODELLINGRULE_MANDATORY), true) @test retval13 == UA_STATUSCODE_GOOD rpmAttr = JUA_VariableAttributes(displayname = "MotorRPM", @@ -321,10 +321,10 @@ r2 = addPumpObjectInstance(server, "pump3", pumpTypeId) #should have status = fa addPumpTypeConstructor(server, pumpTypeId) r3 = addPumpObjectInstance(server, "pump4", pumpTypeId) #should have status = true r4 = addPumpObjectInstance(server, "pump5", pumpTypeId) #should have status = true -@test r1 == UA_STATUSCODE_GOOD -@test r2 == UA_STATUSCODE_GOOD -@test r3 == UA_STATUSCODE_GOOD -@test r4 == UA_STATUSCODE_GOOD +@test r1 == UA_STATUSCODE_GOOD +@test r2 == UA_STATUSCODE_GOOD +@test r3 == UA_STATUSCODE_GOOD +@test r4 == UA_STATUSCODE_GOOD #TODO: should actually check the status value and not just whether adding things went ok. #add method node @@ -339,62 +339,100 @@ function helloWorld(server, sessionId, sessionHandle, methodId, return UA_STATUSCODE_GOOD end -#TODO: code here is not yet part of the high level interface, but a mixture... -inputArgument = UA_Argument_new() -lt = JUA_LocalizedText("en-US", "A String") -ua_s = JUA_String("MyInput") -inputArgument.description = lt -inputArgument.name = ua_s -inputArgument.dataType = UA_TYPES_PTRS[UA_TYPES_STRING].typeId -inputArgument.valueRank = UA_VALUERANK_SCALAR - -outputArgument = UA_Argument_new() -lt = JUA_LocalizedText("en-US", "A String") -ua_s = JUA_String("MyOutput") -outputArgument.description = lt -outputArgument.name = ua_s -outputArgument.dataType = UA_TYPES_PTRS[UA_TYPES_STRING].typeId -outputArgument.valueRank = UA_VALUERANK_SCALAR +inputArgument = JUA_Argument("examplestring", name = "MyInput", description = "A String") +outputArgument = JUA_Argument("examplestring", name = "MyOutput", description = "A String") + +j3 = JUA_Argument("examplestring", name = "Name", description = "Number") +j4 = JUA_Argument(25, name = "Number", description = "Number") +twoinputarg_mixed = [j3, j4] + +j5 = JUA_Argument("examplestring", name = "Name", description = "Name") +j6 = JUA_Argument(25, name = "Number", description = "Number") +twooutputarg_mixed = [j5, j6] + helloAttr = JUA_MethodAttributes(description = "Say Hello World", displayname = "Hello World", executable = true, userexecutable = true) +m2Attr = JUA_MethodAttributes(description = "method 2 in 2 out mixed", + displayname = "method 2 in 2 out mixed", + executable = true, + userexecutable = true) + +function simple_two_in_two_out_mixed_type(name, number) + out1 = "Hello " * name * "." + out2 = number * number + return (out1, out2) +end + +function c5(server, sessionId, sessionHandle, methodId, methodContext, objectId, + objectContext, inputSize, input, outputSize, output) + arr_input = UA_Array(input, Int64(inputSize)) + arr_output = UA_Array(output, Int64(outputSize)) + input_julia = Open62541.__get_juliavalues_from_variant.(arr_input, Any) + output_julia = simple_two_in_two_out_mixed_type(input_julia...) + if !isa(output_julia, Tuple) + output_julia = (output_julia,) + end + for i in 1:outputSize + j = JUA_Variant(output_julia[i]) + UA_Variant_copy(Open62541.Jpointer(j), arr_output[i]) + end + return UA_STATUSCODE_GOOD +end + methodid = JUA_NodeId(1, 62541) +methodid2 = JUA_NodeId(1, 62542) parentnodeid = JUA_NodeId(0, UA_NS0ID_OBJECTSFOLDER) parentreferencenodeid = JUA_NodeId(0, UA_NS0ID_HASCOMPONENT) @static if !Sys.isapple() || platform_key_abi().tags["arch"] != "aarch64" helloWorldMethodCallback = UA_MethodCallback_generate(helloWorld) + method2 = UA_MethodCallback_generate(UA_MethodCallback_wrap(simple_two_in_two_out_mixed_type)) else #we are on Apple Silicon and can't use a closure in @cfunction, have to do more work. helloWorldMethodCallback = @cfunction(helloWorld, UA_StatusCode, (Ptr{UA_Server}, Ptr{UA_NodeId}, Ptr{Cvoid}, Ptr{UA_NodeId}, Ptr{Cvoid}, Ptr{UA_NodeId}, Ptr{Cvoid}, Csize_t, Ptr{UA_Variant}, Csize_t, Ptr{UA_Variant})) + method2 = @cfunction(c5, UA_StatusCode, + (Ptr{UA_Server}, Ptr{UA_NodeId}, Ptr{Cvoid}, + Ptr{UA_NodeId}, Ptr{Cvoid}, Ptr{UA_NodeId}, Ptr{Cvoid}, + Csize_t, Ptr{UA_Variant}, Csize_t, Ptr{UA_Variant})) end + browsename = JUA_QualifiedName(1, "hello world") -retval = JUA_Server_addNode(server, methodid, - parentnodeid, parentreferencenodeid, browsename, - helloAttr, helloWorldMethodCallback, - 1, inputArgument, 1, outputArgument, JUA_NodeId(), JUA_NodeId()) +browsename2 = JUA_QualifiedName(1, "mixed") + +retval = JUA_Server_addNode(server, methodid, parentnodeid, parentreferencenodeid, + browsename, helloAttr, helloWorldMethodCallback, inputArgument, outputArgument, + JUA_NodeId(), JUA_NodeId()) + +retval2 = JUA_Server_addNode(server, methodid2, parentnodeid, parentreferencenodeid, + browsename2, m2Attr, method2, twoinputarg_mixed, twooutputarg_mixed, + JUA_NodeId(), JUA_NodeId()) @test retval == UA_STATUSCODE_GOOD +@test retval2 == UA_STATUSCODE_GOOD -inputArguments = UA_Variant_new() -ua_s = UA_STRING("Peter") -UA_Variant_setScalar(inputArguments, ua_s, UA_TYPES_PTRS[UA_TYPES_STRING]) -req = UA_CallMethodRequest_new() -req.objectId = parentnodeid -req.methodId = methodid -req.inputArgumentsSize = 1 -req.inputArguments = inputArguments +inputarg = "Peter" +two_inputs_mixed = ("Claudia", 25) -answer = UA_CallMethodResult_new() +req = JUA_CallMethodRequest(parentnodeid, methodid, inputarg) +answer = JUA_CallMethodResult() UA_Server_call(server, req, answer) @test unsafe_load(answer.statusCode) == UA_STATUSCODE_GOOD +#The ugly way of doing it @test unsafe_string(unsafe_wrap(unsafe_load(answer.outputArguments))) == "Hello Peter" -#clean up -UA_Argument_delete(inputArgument) -UA_Argument_delete(outputArgument) -UA_CallMethodRequest_delete(req) -UA_CallMethodResult_delete(answer) +#Higher level with JUA_Server_call +res1 = JUA_Server_call(server, req) +@test res1 == "Hello Peter" + +#Even easier: +res2 = JUA_Server_call(server, parentnodeid, methodid, inputarg) +@test res2 == "Hello Peter" + +#two input, two output +res3 = JUA_Server_call(server, parentnodeid, methodid2, two_inputs_mixed) +@test res3[1] == "Hello Claudia." +@test res3[2] == 625 diff --git a/test/memoryleaks.jl b/test/server_memoryleaks.jl similarity index 98% rename from test/memoryleaks.jl rename to test/server_memoryleaks.jl index 7e028cb..1f04b60 100644 --- a/test/memoryleaks.jl +++ b/test/server_memoryleaks.jl @@ -155,7 +155,8 @@ for j in eachindex(inputs) accesslevel = UA_ACCESSLEVEL(read = true, write = true) attr1 = UA_VariableAttributes_generate(value = inputs[j], displayname = "variable", description = "this is a variable", accesslevel = accesslevel) - attr2 = UA_VariableTypeAttributes_generate(value = inputs[j], displayname = "variabletype", + attr2 = UA_VariableTypeAttributes_generate( + value = inputs[j], displayname = "variabletype", description = "this is variabletype variable") UA_VariableAttributes_delete(attr1) UA_VariableTypeAttributes_delete(attr2) diff --git a/test/server_monitoreditems.jl b/test/server_monitoreditems.jl index 558c619..fd83847 100644 --- a/test/server_monitoreditems.jl +++ b/test/server_monitoreditems.jl @@ -4,7 +4,7 @@ using Open62541 using Test function dataChangeNotificationCallback(server, monitoredItemId, - monitoredItemContext, nodeId, nodeContext, attributeId, value) + monitoredItemContext, nodeId, nodeContext, attributeId, value) println("Received notification") return nothing end @@ -12,14 +12,14 @@ end #configure server server = JUA_Server() JUA_ServerConfig_setMinimalCustomBuffer(JUA_ServerConfig(server), -4842, C_NULL, 0, 0) + 4842, C_NULL, 0, 0) currentTimeNodeId = JUA_NodeId(0, UA_NS0ID_SERVER_SERVERSTATUS_CURRENTTIME) monRequest = UA_MonitoredItemCreateRequest_default(currentTimeNodeId) monRequest.requestedParameters.samplingInterval = 500.0 #time in ms cb = @cfunction(dataChangeNotificationCallback, Cvoid, - (Ptr{UA_Server}, UInt32, Ptr{Cvoid}, Ptr{UA_NodeId}, Ptr{Cvoid}, - UInt32, Ptr{UA_DataValue})) + (Ptr{UA_Server}, UInt32, Ptr{Cvoid}, Ptr{UA_NodeId}, Ptr{Cvoid}, + UInt32, Ptr{UA_DataValue})) result = UA_Server_createDataChangeMonitoredItem(server, UA_TIMESTAMPSTORETURN_SOURCE, unsafe_load(monRequest), C_NULL, cb) diff --git a/test/server_read.jl b/test/server_read.jl index 13a8e97..f7ff0ac 100644 --- a/test/server_read.jl +++ b/test/server_read.jl @@ -41,7 +41,7 @@ description = "This is a 2D point type." attr2 = UA_VariableTypeAttributes_generate(value = input, displayname = displayname, description = description) -reqnewnodeid = UA_NodeId_new() +reqnewnodeid = UA_NodeId_new() parent2 = UA_NODEID_NUMERIC(0, UA_NS0ID_BASEDATAVARIABLETYPE) ref2 = UA_NODEID_NUMERIC(0, UA_NS0ID_HASSUBTYPE) browse2 = UA_QUALIFIEDNAME_ALLOC(1, "2DPoint Type") @@ -63,20 +63,21 @@ for node in nodes attributeset = UA_VariableAttributes elseif nodeclass == UA_NODECLASS_VARIABLETYPE attributeset = UA_VariableTypeAttributes - end + end for att in Open62541.attributes_UA_Server_read fun_name = Symbol(att[1]) attr_type = Symbol(att[3]) - generator = Symbol(att[3]*"_new") - cleaner = Symbol(att[3]*"_delete") + generator = Symbol(att[3] * "_new") + cleaner = Symbol(att[3] * "_delete") out2 = eval(generator)() if in(Symbol(lowercasefirst(att[2])), fieldnames(attributeset)) || - in(Symbol(lowercasefirst(att[2])), fieldnames(UA_NodeHead)) + in(Symbol(lowercasefirst(att[2])), fieldnames(UA_NodeHead)) @test isa(eval(fun_name)(server, node, out2), UA_StatusCode) elseif "AccessLevelEx" == att[2] #donothing else - @test_throws Open62541.AttributeReadWriteError eval(fun_name)(server, node, out2) + @test_throws Open62541.AttributeReadWriteError eval(fun_name)( + server, node, out2) end eval(cleaner)(out2) end @@ -86,15 +87,15 @@ end #clean up UA_Server_delete(server) UA_VariableAttributes_delete(attr) -UA_NodeId_delete(variablenodeid) -UA_NodeId_delete(parentnodeid) +UA_NodeId_delete(variablenodeid) +UA_NodeId_delete(parentnodeid) UA_NodeId_delete(parentreferencenodeid) UA_NodeId_delete(typedefinition) -UA_QualifiedName_delete(browsename) -UA_NodeId_delete(variabletypenodeid) -UA_VariableTypeAttributes_delete(attr2) -UA_NodeId_delete(reqnewnodeid) -UA_NodeId_delete(parent2) -UA_NodeId_delete(ref2) -UA_QualifiedName_delete(browse2) +UA_QualifiedName_delete(browsename) +UA_NodeId_delete(variabletypenodeid) +UA_VariableTypeAttributes_delete(attr2) +UA_NodeId_delete(reqnewnodeid) +UA_NodeId_delete(parent2) +UA_NodeId_delete(ref2) +UA_QualifiedName_delete(browse2) UA_NodeId_delete(t2) diff --git a/test/server_write.jl b/test/server_write.jl index 9a6a925..e86663b 100644 --- a/test/server_write.jl +++ b/test/server_write.jl @@ -64,16 +64,16 @@ for node in nodes attributeset = UA_VariableAttributes elseif nodeclass == UA_NODECLASS_VARIABLETYPE attributeset = UA_VariableTypeAttributes - end + end for att in Open62541.attributes_UA_Server_write fun_write = Symbol(att[1]) fun_read = Symbol(replace(att[1], "write" => "read")) attr_name = Symbol(att[2]) - generator = Symbol(att[3]*"_new") - cleaner = Symbol(att[3]*"_delete") + generator = Symbol(att[3] * "_new") + cleaner = Symbol(att[3] * "_delete") out2 = eval(generator)() if in(Symbol(lowercasefirst(att[2])), fieldnames(attributeset)) || - in(Symbol(lowercasefirst(att[2])), fieldnames(UA_NodeHead)) + in(Symbol(lowercasefirst(att[2])), fieldnames(UA_NodeHead)) statuscode1 = eval(fun_read)(server, node, out2) #read @test statuscode1 == UA_STATUSCODE_GOOD if attr_name != :BrowseName #can't write browsename, see here: https://github.com/open62541/open62541/issues/3545 diff --git a/test/test_helpers.jl b/test/test_helpers.jl index c2c2f86..54aeacc 100644 --- a/test/test_helpers.jl +++ b/test/test_helpers.jl @@ -11,14 +11,14 @@ function customrand(type::Type{String}) end #rational numbers -function customrand(::Type{Rational{T}}, array_size) where T +function customrand(::Type{Rational{T}}, array_size) where {T} num = rand(T, array_size) den = rand(T, array_size) r = Rational.(num, den) return r end -function customrand(::Type{Rational{T}}) where T +function customrand(::Type{Rational{T}}) where {T} num = rand(T) den = rand(T) r = Rational(num, den) @@ -26,10 +26,10 @@ function customrand(::Type{Rational{T}}) where T end #For all other number types -function customrand(type::Type{<:Number}, array_size) +function customrand(type::Type{<:Number}, array_size) return rand(type, array_size) end -function customrand(type::Type{<:Number}) +function customrand(type::Type{<:Number}) return rand(type) -end \ No newline at end of file +end