FreeOpcUa / opcua-asyncio

OPC UA library for python >= 3.7
GNU Lesser General Public License v3.0
1.04k stars 346 forks source link

OPC-UA datatype Float interpreted as Double by server #1559

Closed mloumi closed 4 months ago

mloumi commented 5 months ago

Describe the bug

When defining a variable with the data type 'float' in asyncua opcua, the server interprets it as a 'double', leading to a typing inconsistency on the client side.

To Reproduce

  1. create an opcua server with a variable of type "float":
    my_object = await server.nodes.objects.add_object(idx, “MyObjects”)
    ns = “ns=1;s=TagName”
    my_var = await my_object.add_variable(ns, “MyVariable”, 0.0, datatype=ua.NodeId(ua.ObjectIds.Float))
    await my_var.set_writable()
  2. Use a client to push data to the server using the "float" type
  3. Error faced :
    Variant: Variant(Value=3.200000047683716, VariantType=<VariantType.Float: 10>, Dimensions=None, is_array=False) with type VariantType.Float does not have expected type: VariantType.Double

    Upon investigating the root cause of the issue, we found in the file "asyncua/ua/uatypes.py," specifically within the method "_guess_type" of the "Variant" class, the code causing the issue is:

    if isinstance(val, float):
            return VariantType.Double

    To address the issue, we attempted to replace the above code with the following snippet:

    if isinstance(val, float):
    return VariantType.Float

    This modification successfully resolved the problem, ensuring proper handling of the "float" type, and rectifying the typing inconsistency observed in the previous code

Expected behavior
When declaring a float variable, it is interpreted by the server as such.

Version
Python-Version: 3.11
opcua-asyncio Version: 1.0.6

oroulet commented 5 months ago

I am really sure this is NOT fixable without changing API. This is due to our API having grown over time to become a bit of a monster.

Specify a Vairant instead of a python float and you will get the type you want. Then you probbaly do not need to precise the datattype node, although it might be safer to do it

schroeder- commented 5 months ago

The best way to set values is to use the corresponding ua Datatypes. If you want a double: ua.Double(0.3) If you want a float: ua.Float(0.3)

mloumi commented 5 months ago

Thank you very much for your feedback I tried the ua.Float(0.3) method and it works fine but I finally decided to define the variables using the VariantType this way: my_var = await my_object.add_variable(ns, “MyVariable”, ua.Variant([], ua.VariantType.Float)) it works perfectly