Getting OPC UA array object values (Byte, UInt16) in python client

256 views Asked by At

I am creating a python OPC UA client based on opcua-asyncio github (https://github.com/FreeOpcUa/opcua-asyncio) to read values in an instrument that has a server already set up.

My problem lies in reading array values of data type byte or UInt16. What I expect is something similar to the values shown in UaExpert/DataFeed below.

UaExpert Byte array

However if I use python client, I get Value = 0 inside each variant object.

val:  [Variant(Value=0, VariantType=<VariantType.UInt16: 5>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.UInt16: 5>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.UInt16: 5>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.UInt16: 5>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.UInt16: 5>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.UInt16: 5>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.UInt16: 5>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.UInt16: 5>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.UInt16: 5>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.UInt16: 5>, Dimensions=None, is_array=False)]

val:  [Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False)]

I have tried some other functions as well, with the results below.

import asyncio
import logging
import sys
import common
from asyncua import ua

sys.path.insert(0, "..")

async def main():
    client = await common.connectViaUsername()
    try:
        async with client:
            while True:
                # Getting a variable nodes
                pi_node = client.get_node("ns=1;i=57")

                val = await pi_node.read_value()

                print("val: ", val)
                print("type of val: ", type(val))

                att = await pi_node.read_attribute(ua.AttributeIds.DataType)
                print("att: ", att)
                print("type of att: ", type(att))
                print("att value value: ", att.Value.Value)

                dataval = await pi_node.read_data_value()
                print("dataval: ", dataval)
                print("variant type: ", dataval.Value.Value[0].VariantType)

                rv = ua.ReadValueId()
                rv.NodeId = pi_node.nodeid
                rv.AttributeId = ua.AttributeIds.DataType
                params = ua.ReadParameters()
                params.NodesToRead.append(rv)
                result = await pi_node.session.read(params)
                print("result: ", result)
                print(type(result[0]))
                print(type(result[0].Value))
                print(type(result[0].data_type))
                print(type(result[0].Encoding))
                print((result[0].Value))
                print((result[0].data_type))
                print((result[0].Encoding))

                print("node_class: ", await pi_node.read_node_class())
                print("att.value: ", await pi_node.read_attribute(ua.AttributeIds.Value))
                print("data type: ", await pi_node.read_data_type())
                print("array dim: ", await pi_node.read_array_dimensions())
                print("data values: ", await pi_node.read_data_value())
                print("variant type: ", await pi_node.read_data_type_as_variant_type())
                print("_______")

                await asyncio.sleep(100)
    except ua.UaError as err:
        _logger.error(err)
    finally:
        await client.disconnect()


if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO)  # configure at info level
    _logger = logging.getLogger(__name__)

    # filter out the logs from asynua logger
    logging.getLogger('asyncua').setLevel(logging.CRITICAL + 1)

    # formate log messages with the file path of the log, comment out if not needed
    fh = common.configureLogs("logs/OPC Status - InstrumentSensor (Pulse Sensors).log")
    _logger.addHandler(fh)

    asyncio.run(main())

These are the results of the print statements.

val:  [Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False)]
type of val:  <class 'list'>
att:  DataValue(Value=Variant(Value=NodeId(Identifier=3, NamespaceIndex=0, NodeIdType=<NodeIdType.TwoByte: 0>), VariantType=<VariantType.NodeId: 17>, Dimensions=None, is_array=False), StatusCode_=StatusCode(value=0), SourceTimestamp=None, ServerTimestamp=None, SourcePicoseconds=None, ServerPicoseconds=None)
type of att:  <class 'asyncua.ua.uatypes.DataValue'>
att value value:  NodeId(Identifier=3, NamespaceIndex=0, NodeIdType=<NodeIdType.TwoByte: 0>)
dataval:  DataValue(Value=Variant(Value=[Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False)], VariantType=<VariantType.Variant: 24>, Dimensions=None, is_array=True), StatusCode_=StatusCode(value=0), SourceTimestamp=datetime.datetime(2023, 10, 27, 1, 48, 35, 270000), ServerTimestamp=None, SourcePicoseconds=None, ServerPicoseconds=None)
variant type:  VariantType.Byte
result:  [DataValue(Value=Variant(Value=NodeId(Identifier=3, NamespaceIndex=0, NodeIdType=<NodeIdType.TwoByte: 0>), VariantType=<VariantType.NodeId: 17>, Dimensions=None, is_array=False), StatusCode_=StatusCode(value=0), SourceTimestamp=None, ServerTimestamp=None, SourcePicoseconds=None, ServerPicoseconds=None)]
<class 'asyncua.ua.uatypes.DataValue'>
<class 'asyncua.ua.uatypes.Variant'>
<class 'asyncua.ua.uatypes.NodeId'>
<class 'int'>
Variant(Value=NodeId(Identifier=3, NamespaceIndex=0, NodeIdType=<NodeIdType.TwoByte: 0>), VariantType=<VariantType.NodeId: 17>, Dimensions=None, is_array=False)
NodeId(Identifier=25, NamespaceIndex=0, NodeIdType=<NodeIdType.TwoByte: 0>)
0
node_class:  2
att.value:  DataValue(Value=Variant(Value=[Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False)], VariantType=<VariantType.Variant: 24>, Dimensions=None, is_array=True), StatusCode_=StatusCode(value=0), SourceTimestamp=datetime.datetime(2023, 10, 27, 1, 48, 35, 270000), ServerTimestamp=None, SourcePicoseconds=None, ServerPicoseconds=None)
data type:  NodeId(Identifier=3, NamespaceIndex=0, NodeIdType=<NodeIdType.TwoByte: 0>)
array dim:  [10]
data values:  DataValue(Value=Variant(Value=[Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False), Variant(Value=0, VariantType=<VariantType.Byte: 3>, Dimensions=None, is_array=False)], VariantType=<VariantType.Variant: 24>, Dimensions=None, is_array=True), StatusCode_=StatusCode(value=0), SourceTimestamp=datetime.datetime(2023, 10, 27, 1, 48, 35, 270000), ServerTimestamp=None, SourcePicoseconds=None, ServerPicoseconds=None)
variant type:  VariantType.Byte

My thoughts are that the python client is decoding the byte/UInt16 values into int of value 0 as it is unable to print such bytes/UInt16.

Note: I am able to read the arrays of strings/floats without any problems. Below is the example for array of float

[Variant(Value=1002.32, VariantType=<VariantType.Double: 11>, Dimensions=None, is_array=False), Variant(Value=1002.01, VariantType=<VariantType.Double: 11>, Dimensions=None, is_array=False), Variant(Value=1002.16, VariantType=<VariantType.Double: 11>, Dimensions=None, is_array=False), Variant(Value=1002.4, VariantType=<VariantType.Double: 11>, Dimensions=None, is_array=False), Variant(Value=0.0, VariantType=<VariantType.Double: 11>, Dimensions=None, is_array=False), Variant(Value=0.0, VariantType=<VariantType.Double: 11>, Dimensions=None, is_array=False), Variant(Value=0.0, VariantType=<VariantType.Double: 11>, Dimensions=None, is_array=False), Variant(Value=0.0, VariantType=<VariantType.Double: 11>, Dimensions=None, is_array=False), Variant(Value=0.0, VariantType=<VariantType.Double: 11>, Dimensions=None, is_array=False), Variant(Value=0.0, VariantType=<VariantType.Double: 11>, Dimensions=None, is_array=False)]

Is there any way I am able to read the byte/UInt16 array values?

Best regards, opc Beginner

0

There are 0 answers