FreeOpcUa / freeopcua

Open Source C++ OPC-UA Server and Client Library
http://freeopcua.github.io/
GNU Lesser General Public License v3.0
712 stars 341 forks source link

Wrong types in Python #112

Open destogl opened 9 years ago

destogl commented 9 years ago

Following the discussion in mailing list (Thread: "Setting correct types in OPC-UA server") I made a bit research through Python binding code and concluded the following.

The proposal to create new nodes with correct type using DataValue and than getting the value from it fails because while getting the value property it would be converted to Python object (e.g. int for all integer types in OpcUa (int16, uint16, int32...)). This happens in the line 198 of file py_opcua_module.cpp. This is probably what @oroulet tried to tell me but I didn't understand it.

Than I tried to enable Python access to Variant object uncommenting lines 421-428 in the py_opcua_module.cpp file. Also I added following line to enable setting a Variant type in the constructor:

//--------------------------------------------------------------------------
// Variant helpers
//--------------------------------------------------------------------------

static boost::shared_ptr<Variant> Variant_constructor1(const object & obj, VariantType vtype)
{return boost::shared_ptr<Variant>(ToVariant2(obj, vtype));}

and also

.def("__init__", make_constructor(Variant_constructor1)) //object, VariantType

into line 422.

I took the same approach as it is made for DataValue object. But than I got following runtime warning: RuntimeWarning: to-Python converter for OpcUa::Variant already registered; second conversion method ignored. This is probably because the "opc/ua/protocol/variant_visitor.h" file is included from py_opcua_variant.h file therefore also "opc/ua/protocol/variant.h".

Ok, all this was to understand a problem and what I tried to do. Now something about possible solutions.

IMO the best approach would be to model Variant object in python bindings, maybe it has to be called different (e.g. VariantPy) so it would enable also work with variants in Python.

Second option is work with DataValue objects and creating following additional functions into bindings and, probably, c++ code:

.def("add_variable", (Node(Node::*)(const NodeID &, const QualifiedName &, const DataValue &) const) &Node::AddVariable)
.def("add_property", (Node(Node::*)(const NodeID &, const QualifiedName &, const DataValue &) const) &Node::AddProperty)

What solution would make more sense to you? Which approach would be more according to the library?

Thanks!

oroulet commented 9 years ago

Following the discussion in mailing list (Thread: "Setting correct types in OPC-UA server") I made a bit research through Python binding code

Unfortunaltely fixing this can be done in few lines but requires quite an understanding of the binding...

IMO the best approach would be to model Variant object in python bindings,

I am really really against it. It have used tons of binding exposing all kinds of strange framework specific variants and they are really cumbersome to use in python

The correct fix here would be to 1- Add AddVariable overload accepting DataValue, where the DataValue type is used to create the Node type 2- expose that method to python 3- Add add_variable overload accepting an extra VariantType and us the variant type to internaly create a DataValue and send to C++

You can do it or I can have a look at it in a few days.

destogl commented 9 years ago

Sorry for answering now... I was a bit out of it for a few days. I understand Idea about fix so I'll look at it in a next few days...

oroulet commented 9 years ago

Great! Don't hesitate to ask if you have issues. I am currently looking at the automatic protocol generation, this will take a while. I have something that works by itself but the integration with the existing code needs thinking....