I'm searching for creating a program in python which reads a CSV file and writes in a wanted PLC the value we have chosen. Here is what I have for the moment:
import csv
from xmlrpc.client import Boolean
from opcua import Client, ua, uamethod
# Libraries I have created
from Definitions import *
from Connexion import *
def default_f(x: str) -> str:
"""Returns x as-is, a string; used when type is not declared in Transformer."""
return x
Transformer = {
"VariantType.String": lambda x: x,
"VariantType.StatusCode": lambda x: ua.DataValue(ua.Variant(
x, ua.VariantType.StatusCode)),
"VariantType.Boolean": lambda x: x=='True',
"VariantType.SByte": lambda x: ua.DataValue(ua.Variant(
x, ua.VariantType.SByte)),
"VariantType.Byte": lambda x: str.encode(x),
"VariantType.ByteString": lambda x: ua.DataValue(ua.Variant(
x, ua.VariantType.ByteString)),
...........
"VariantType.ExpandedNodeId": lambda x: ua.DataValue(ua.Variant(
x, ua.VariantType.ExpandedNodeId)),
"VariantType.ExtensionObject": lambda x: ua.DataValue(ua.Variant(
x, ua.VariantType.ExtensionObject)),
"VariantType.Guid": lambda x: ua.DataValue(ua.Variant(
x, ua.VariantType.Guid)),
...........
"VariantType.UInt64": lambda x: ua.DataValue(ua.Variant(
x, ua.VariantType.UInt64)),
}
try:
connection(client)
with open("Variables.csv", "r") as file:
reader = csv.reader(file)
for line in reader:
try:
# Writing
this_node, this_type, this_val = line[1], line[2], line[3]
transformer_func = Transformer.get(this_type, default_f)
val_transformed = transformer_func(this_val)
if transformer_func == default_f:
print(f"warning: found undeclared type {this_type} with value {this_val}")
else:
write_value(this_node, val_transformed) # A function I created which uses set_value()
finally:
disconnection(client)
My problem is: The program work for different types, in this example, I can do strings, boolean, float, and maybe Byte (I didn't try yet). But when I use the line I found on the internet: ua.DataValue(ua.Variant(x, ua.VariantType.WantedType))
I need the value to be already converted in the fitting type. But I don't know how to do it in all those different types. I change the code for the ones I knew but for the less used, like ExtensionObject or Guid, I don't know how to proceed. (I think my program will deal with every type of the OPC UA architecture) Do you have an idea of how to change the datatypes for each value?
The possible types of a variant:
:ivar Null:
:ivar Boolean:
:ivar SByte:
:ivar Byte:
:ivar Int16:
:ivar UInt16:
:ivar Int32:
:ivar UInt32:
:ivar Int64:
:ivar UInt64:
:ivar Float:
:ivar Double:
:ivar String:
:ivar DateTime:
:ivar Guid:
:ivar ByteString:
:ivar XmlElement:
:ivar NodeId:
:ivar ExpandedNodeId:
:ivar StatusCode:
:ivar QualifiedName:
:ivar LocalizedText:
:ivar ExtensionObject:
:ivar DataValue:
:ivar Variant:
:ivar DiagnosticInfo: