5 from enum
import Enum, IntEnum, EnumMeta
6 from datetime
import datetime
13 from opcua.ua import ua_binary
as uabin
21 if sys.version_info.major > 2:
24 return uabin.win_epoch_to_datetime(0)
30 Make it impossible to add members to a class. 31 Not pythonic at all but we found out it prevents many many 32 bugs in use of protocol structures 37 if self.
_freeze and not hasattr(self, key):
38 raise TypeError(
"Error adding member '{0}' to class '{1}', class is frozen, members are {2}".format(
39 key, self.__class__.__name__, self.__dict__.keys()))
40 object.__setattr__(self, key, value)
43 if "PYOPCUA_NO_TYPO_CHECK" in os.environ:
50 FrozenClass = _FrozenClass
55 Defines dimensions of a variable. 56 This enum does not support all cases since ValueRank support any n>0 57 but since it is an IntEnum it can be replace by a normal int 59 ScalarOrOneDimension = -3
62 OneOrMoreDimensions = 0
74 """ Take an integer and interpret it as a set of enum values. """ 75 assert isinstance(the_int, int)
77 return {cls(b)
for b
in cls.
_bits(the_int)}
81 """ Takes some enum values and creates an integer from them. """ 84 iter1, iter2 = itertools.tee(iter(collection))
85 assert all(isinstance(x, cls)
for x
in iter1)
87 return sum(x.mask
for x
in iter2)
91 return 1 << self.value
95 """ Iterate over the bits in n. 97 e.g. bits(44) yields at 2, 3, 5 111 Bit index to indicate what the access level is. 113 Spec Part 3, appears multiple times, e.g. paragraph 5.6.2 Variable NodeClass 126 Bit index to indicate which attribute of a node is writable 128 Spec Part 3, Paragraph 5.2.7 WriteMask 142 MinimumSamplingInterval = 12
151 ValueForVariableType = 21
156 Bit index to indicate how a node can be used for events. 158 Spec Part 3, appears multiple times, e.g. Paragraph 5.4 View NodeClass 160 SubscribeToEvents = 0
171 :vartype name: string 177 if isinstance(value, str):
182 self.
name, self.
doc = status_codes.get_name_and_doc(value)
186 return uabin.Primitives.UInt32.pack(self.
value)
190 val = uabin.Primitives.UInt32.unpack(data)
196 Raises an exception if the status code is anything else than 0 (good). 198 Use the is_good() method if you do not want an exception. 201 raise UaStatusCodeError(self.
value)
205 return True if status is Good. 208 if mask & self.
value:
214 return 'StatusCode({0})'.format(self.
name)
218 return self.
value == other.value
221 return not self.
__eq__(other)
238 identifier: The identifier might be an int, a string, bytes or a Guid 239 namespaceidx(int): The index of the namespace 240 nodeidtype(NodeIdType): The type of the nodeid if it cannor be guess or you want something special like twobyte nodeid or fourbytenodeid 244 :vartype Identifier: NodeId 245 :ivar NamespaceIndex: 246 :vartype NamespaceIndex: Int 248 :vartype NamespaceUri: String 250 :vartype ServerIndex: Int 253 def __init__(self, identifier=None, namespaceidx=0, nodeidtype=None):
262 raise UaError(
"NamespaceIndex must be an int")
277 raise UaError(
"NodeId: Could not guess type of NodeId, set NodeIdType")
280 if self.
NodeIdType in (NodeIdType.TwoByte, NodeIdType.FourByte, NodeIdType.Numeric):
286 return isinstance(node, NodeId)
and self.
_key() == node._key()
289 return not self.
__eq__(other)
292 return hash(self.
_key())
295 if not isinstance(other, NodeId):
296 raise AttributeError(
"Can only compare to NodeId")
297 return self.
_key() < other._key()
314 return NodeId._from_string(string)
315 except ValueError
as ex:
316 raise UaStringParsingError(
"Error parsing string {0}".format(string), ex)
320 l = string.split(
";")
329 k, v = el.split(
"=", 1)
335 ntype = NodeIdType.Numeric
338 ntype = NodeIdType.String
341 ntype = NodeIdType.Guid
344 ntype = NodeIdType.ByteString
350 if identifier
is None:
351 raise UaStringParsingError(
"Could not find identifier in string: " + string)
352 nodeid =
NodeId(identifier, namespace, ntype)
353 nodeid.NamespaceUri = nsu
354 nodeid.ServerIndex = srv
372 elif self.
NodeIdType == NodeIdType.ByteString:
374 string +=
"{0}={1}".format(ntype, self.
Identifier)
382 return "{0}NodeId({1})".format(self.NodeIdType.name, self.
to_string())
387 return struct.pack(
"<BB", self.NodeIdType.value, self.
Identifier)
393 return struct.pack(
"<BH", self.NodeIdType.value, self.
NamespaceIndex) + \
395 elif self.
NodeIdType == NodeIdType.ByteString:
396 return struct.pack(
"<BH", self.NodeIdType.value, self.
NamespaceIndex) + \
399 return struct.pack(
"<BH", self.NodeIdType.value, self.
NamespaceIndex) + \
402 return struct.pack(
"<BH", self.NodeIdType.value, self.
NamespaceIndex) + \
403 self.Identifier.to_binary()
409 encoding = ord(data.read(1))
410 nid.NodeIdType =
NodeIdType(encoding & 0b00111111)
412 if nid.NodeIdType == NodeIdType.TwoByte:
413 nid.Identifier = ord(data.read(1))
414 elif nid.NodeIdType == NodeIdType.FourByte:
415 nid.NamespaceIndex, nid.Identifier = struct.unpack(
"<BH", data.read(3))
416 elif nid.NodeIdType == NodeIdType.Numeric:
417 nid.NamespaceIndex, nid.Identifier = struct.unpack(
"<HI", data.read(6))
418 elif nid.NodeIdType == NodeIdType.String:
419 nid.NamespaceIndex = uabin.Primitives.UInt16.unpack(data)
420 nid.Identifier = uabin.Primitives.String.unpack(data)
421 elif nid.NodeIdType == NodeIdType.ByteString:
422 nid.NamespaceIndex = uabin.Primitives.UInt16.unpack(data)
423 nid.Identifier = uabin.Primitives.Bytes.unpack(data)
424 elif nid.NodeIdType == NodeIdType.Guid:
425 nid.NamespaceIndex = uabin.Primitives.UInt16.unpack(data)
426 nid.Identifier = uabin.Primitives.Guid.unpack(data)
428 raise UaError(
"Unknown NodeId encoding: " + str(nid.NodeIdType))
430 if uabin.test_bit(encoding, 7):
431 nid.NamespaceUri = uabin.Primitives.String.unpack(data)
432 if uabin.test_bit(encoding, 6):
433 nid.ServerIndex = uabin.Primitives.UInt32.unpack(data)
441 NodeId.__init__(self, identifier, 0, NodeIdType.TwoByte)
447 NodeId.__init__(self, identifier, namespace, NodeIdType.FourByte)
453 NodeId.__init__(self, identifier, namespace, NodeIdType.Numeric)
459 NodeId.__init__(self, identifier, namespace, NodeIdType.ByteString)
465 NodeId.__init__(self, identifier, namespace, NodeIdType.Guid)
471 NodeId.__init__(self, identifier, namespace, NodeIdType.String)
474 ExpandedNodeId = NodeId
479 A string qualified with a namespace index. 483 if not isinstance(namespaceidx, int):
484 raise UaError(
"namespaceidx must be an int")
496 idx, name = string.split(
":", 1)
498 except (TypeError, ValueError)
as ex:
499 raise UaStringParsingError(
"Error parsing string {0}".format(string), ex)
508 packet.append(uabin.Primitives.String.pack(self.
Name))
509 return b
''.join(packet)
514 obj.NamespaceIndex = uabin.Primitives.UInt16.unpack(data)
515 obj.Name = uabin.Primitives.String.unpack(data)
519 return isinstance(bname, QualifiedName)
and self.
Name == bname.Name
and self.
NamespaceIndex == bname.NamespaceIndex
522 return not self.
__eq__(other)
525 if not isinstance(other, QualifiedName):
526 raise TypeError(
"Cannot compare QualifiedName and {0}".format(other))
528 return self.
Name < other.Name
540 A string qualified with a namespace index. 544 "Text":
"ByteString",
545 "Locale":
"ByteString" 551 if isinstance(self.
Text, unicode):
552 self.
Text = self.Text.encode(
'utf-8')
564 packet.append(uabin.Primitives.UInt8.pack(self.
Encoding))
566 packet.append(uabin.Primitives.Bytes.pack(self.
Locale))
568 packet.append(uabin.Primitives.Bytes.pack(self.
Text))
569 return b
''.join(packet)
574 obj.Encoding = ord(data.read(1))
575 if obj.Encoding & (1 << 0):
576 obj.Locale = uabin.Primitives.Bytes.unpack(data)
577 if obj.Encoding & (1 << 1):
578 obj.Text = uabin.Primitives.Bytes.unpack(data)
583 if self.
Text is None:
585 return self.Text.decode(
'utf-8')
588 return 'LocalizedText(' +
'Encoding:' + str(self.
Encoding) +
', ' + \
589 'Locale:' + str(self.
Locale) +
', ' + \
590 'Text:' + str(self.
Text) +
')' 594 if isinstance(other, LocalizedText)
and self.
Locale == other.Locale
and self.
Text == other.Text:
599 return not self.
__eq__(other)
604 Any UA object packed as an ExtensionObject 607 :vartype TypeId: NodeId 622 packet.append(self.TypeId.to_binary())
623 packet.append(uabin.Primitives.UInt8.pack(self.
Encoding))
625 packet.append(uabin.Primitives.ByteString.pack(self.
Body))
626 return b
''.join(packet)
631 obj.TypeId = NodeId.from_binary(data)
632 obj.Encoding = uabin.Primitives.UInt8.unpack(data)
633 if obj.Encoding & (1 << 0):
634 obj.Body = uabin.Primitives.ByteString.unpack(data)
640 oid = getattr(ObjectIds,
"{0}_Encoding_DefaultBinary".format(obj.__class__.__name__))
642 ext.Body = obj.to_binary()
646 return 'ExtensionObject(' +
'TypeId:' + str(self.
TypeId) +
', ' + \
647 'Encoding:' + str(self.
Encoding) +
', ' + str(len(self.
Body)) +
' bytes)' 654 The possible types of a variant. 674 :ivar ExpandedNodeId: 678 :ivar ExtensionObject: 681 :ivar DiagnosticInfo: 714 Looks like sometime we get variant with other values than those 715 defined in VariantType. 716 FIXME: We should not need this class, as far as I iunderstand the spec 717 variants can only be of VariantType 723 if self.
value > 0b00111111:
724 raise UaError(
"Cannot create VariantType. VariantType must be {0} > x > {1}, received {2}".format(0b111111, 25, val))
727 return "VariantType.Custom:{0}".format(self.
value)
731 return self.
value == other.value
736 Create an OPC-UA Variant object. 737 if no argument a Null Variant is created. 738 if not variant type is given, attemps to guess type from python type 739 if a variant is given as value, the new objects becomes a copy of the argument 742 :vartype Value: Any supported type 744 :vartype VariantType: VariantType 747 def __init__(self, value=None, varianttype=None, dimensions=None):
752 if isinstance(value, Variant):
753 self.
Value = value.Value
760 VariantType.DateTime):
761 raise UaError(
"Variant of type {0} cannot have value None".format(self.
VariantType))
768 if isinstance(other, Variant)
and self.
VariantType == other.VariantType
and self.
Value == other.Value:
773 return not self.
__eq__(other)
776 if isinstance(val, (list, tuple)):
778 while isinstance(val, (list, tuple)):
780 raise UaError(
"could not guess UA type of variable {0}".format(error_val))
783 return VariantType.Null
784 elif isinstance(val, bool):
785 return VariantType.Boolean
786 elif isinstance(val, float):
787 return VariantType.Double
788 elif isinstance(val, int):
789 return VariantType.Int64
790 elif type(val)
in (str, unicode):
791 return VariantType.String
792 elif isinstance(val, bytes):
793 return VariantType.ByteString
794 elif isinstance(val, datetime):
795 return VariantType.DateTime
796 elif isinstance(val, uuid.UUID):
797 return VariantType.Guid
799 if isinstance(val, object):
801 return getattr(VariantType, val.__class__.__name__)
802 except AttributeError:
803 return VariantType.ExtensionObject
805 raise UaError(
"Could not guess UA type of {0} with type {1}, specify UA type".format(val, type(val)))
813 encoding = self.VariantType.value & 0b111111
814 if type(self.
Value)
in (list, tuple):
816 encoding = uabin.set_bit(encoding, 6)
817 encoding = uabin.set_bit(encoding, 7)
818 b.append(uabin.Primitives.UInt8.pack(encoding))
821 b.append(uabin.pack_uatype_array(VariantType.Int32, self.
Dimensions))
823 b.append(uabin.Primitives.UInt8.pack(encoding))
831 encoding = ord(data.read(1))
832 int_type = encoding & 0b00111111
834 if vtype == VariantType.Null:
835 return Variant(
None, vtype, encoding)
836 if uabin.test_bit(encoding, 7):
837 value = uabin.unpack_uatype_array(vtype, data)
839 value = uabin.unpack_uatype(vtype, data)
840 if uabin.test_bit(encoding, 6):
841 dimensions = uabin.unpack_uatype_array(VariantType.Int32, data)
842 value =
reshape(value, dimensions)
844 return Variant(value, vtype, dimensions)
854 while dims[0] * subsize > len(flat):
856 if not subdims
or subdims == [0]:
858 return [
reshape(flat[i: i + subsize], subdims)
for i
in range(0, len(flat), subsize)]
863 return [l[i:i + n]
for i
in range(0, len(l), n)]
868 dims.append(len(mylist))
869 while isinstance(mylist[0], (list, tuple)):
870 dims.append(len(mylist[0]))
871 mylist = [item
for sublist
in mylist
for item
in sublist]
880 while isinstance(mylist[0], (list, tuple)):
881 mylist = [item
for sublist
in mylist
for item
in sublist]
889 while isinstance(mylist, (list, tuple)):
890 dims.append(len(mylist))
899 An XML element encoded as an UTF-8 string. 903 if binary
is not None:
911 return uabin.Primitives.String.pack(self.
Value)
918 self.
Value = uabin.Primitives.String.unpack(data)
921 return 'XmlElement(Value:' + str(self.
Value) +
')' 928 A value with an associated timestamp, and quality. 929 Automatically generated from xml , copied and modified here to fix errors in xml spec 932 :vartype Value: Variant 934 :vartype StatusCode: StatusCode 935 :ivar SourceTimestamp: 936 :vartype SourceTimestamp: datetime 937 :ivar SourcePicoSeconds: 938 :vartype SourcePicoSeconds: int 939 :ivar ServerTimestamp: 940 :vartype ServerTimestamp: datetime 941 :ivar ServerPicoseconds: 942 :vartype ServerPicoseconds: int 947 if not isinstance(variant, Variant):
974 packet.append(uabin.Primitives.UInt8.pack(self.
Encoding))
976 packet.append(self.Value.to_binary())
978 packet.append(self.StatusCode.to_binary())
987 return b
''.join(packet)
991 encoding = ord(data.read(1))
992 if encoding & (1 << 0):
993 value = Variant.from_binary(data)
996 if encoding & (1 << 1):
997 status = StatusCode.from_binary(data)
1001 obj.Encoding = encoding
1002 if obj.Encoding & (1 << 2):
1003 obj.SourceTimestamp = uabin.Primitives.DateTime.unpack(data)
1004 if obj.Encoding & (1 << 3):
1005 obj.ServerTimestamp = uabin.Primitives.DateTime.unpack(data)
1006 if obj.Encoding & (1 << 4):
1007 obj.SourcePicoseconds = uabin.Primitives.UInt16.unpack(data)
1008 if obj.Encoding & (1 << 5):
1009 obj.ServerPicoseconds = uabin.Primitives.UInt16.unpack(data)
1013 s =
'DataValue(Value:{0}'.format(self.
Value)
1015 s +=
', StatusCode:{0}'.format(self.
StatusCode)
1032 Takes a NodeId or int and return a VariantType 1033 This is only supported if int_type < 63 due to VariantType encoding 1034 At low level we do not have access to address space thus decoding is limited 1035 a better version of this method can be find in ua_utils.py 1037 if isinstance(int_type, NodeId):
1038 int_type = int_type.Identifier
1048 Given a variant type return default value for this type 1050 if vtype == VariantType.Null:
1052 elif vtype == VariantType.Boolean:
1054 elif vtype
in (VariantType.SByte, VariantType.Byte, VariantType.ByteString):
1056 elif 4 <= vtype.value <= 9:
1058 elif vtype
in (VariantType.Float, VariantType.Double):
1060 elif vtype == VariantType.String:
1062 elif vtype == VariantType.DateTime:
1063 return datetime.now()
1064 elif vtype == VariantType.Guid:
1066 elif vtype == VariantType.XmlElement:
1068 elif vtype == VariantType.NodeId:
1070 elif vtype == VariantType.ExpandedNodeId:
1072 elif vtype == VariantType.StatusCode:
1074 elif vtype == VariantType.QualifiedName:
1076 elif vtype == VariantType.LocalizedText:
1078 elif vtype == VariantType.ExtensionObject:
1080 elif vtype == VariantType.DataValue:
1082 elif vtype == VariantType.Variant:
1085 raise RuntimeError(
"function take a uatype as argument, got:", vtype)
def _guess_type(self, val)
def __init__(self, binary=None)
def has_null_identifier(self)
def parse_bitfield(cls, the_int)
def __init__(self, identifier, namespace=0)
def __setattr__(self, key, value)
def __init__(self, identifier=None, namespaceidx=0, nodeidtype=None)
def __init__(self, variant=None, status=None)
def flatten_and_get_shape(mylist)
def __init__(self, identifier, namespace=0)
def __init__(self, identifier)
def get_default_value(vtype)
def __init__(self, value=None, varianttype=None, dimensions=None)
def __init__(self, name=None, namespaceidx=0)
def __init__(self, text=None)
def datatype_to_varianttype(int_type)
def __init__(self, identifier, namespace=0)
def _binary_init(self, data)
def __init__(self, identifier, namespace=0)
def __init__(self, identifier, namespace=0)
def __init__(self, value=0)
def to_bitfield(cls, collection)