Commit e0ee31df authored by gokuldheep's avatar gokuldheep

Temp Server OPC UA

We have tried to implement all the functionalities that are provided by the OPC UA information model to its users as individual blocks. The acknowledgement of the server and client code is in progress.
parent 0da5f6e3
# Default ignored files
/shelf/
/workspace.xml
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/new_server" />
<excludeFolder url="file://$MODULE_DIR$/tempserver" />
<excludeFolder url="file://$MODULE_DIR$/tempserver_test" />
</content>
<orderEntry type="jdk" jdkName="Python 3.7 (TempServer) (2)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
\ No newline at end of file
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ignoredPackages">
<value>
<list size="58">
<item index="0" class="java.lang.String" itemvalue="auditlogslib" />
<item index="1" class="java.lang.String" itemvalue="saltlib" />
<item index="2" class="java.lang.String" itemvalue="commonlib" />
<item index="3" class="java.lang.String" itemvalue="userrolevalidationlib" />
<item index="4" class="java.lang.String" itemvalue="python_docx" />
<item index="5" class="java.lang.String" itemvalue="PyYAML" />
<item index="6" class="java.lang.String" itemvalue="pytz" />
<item index="7" class="java.lang.String" itemvalue="extensions_lib" />
<item index="8" class="java.lang.String" itemvalue="docx" />
<item index="9" class="java.lang.String" itemvalue="Pillow" />
<item index="10" class="java.lang.String" itemvalue="pkm-entities-lib" />
<item index="11" class="java.lang.String" itemvalue="pandas" />
<item index="12" class="java.lang.String" itemvalue="PyJWT" />
<item index="13" class="java.lang.String" itemvalue="Flask_JWT_Extended" />
<item index="14" class="java.lang.String" itemvalue="arrow" />
<item index="15" class="java.lang.String" itemvalue="jsonpath_rw" />
<item index="16" class="java.lang.String" itemvalue="logginglib" />
<item index="17" class="java.lang.String" itemvalue="pysaml2" />
<item index="18" class="java.lang.String" itemvalue="errorlib" />
<item index="19" class="java.lang.String" itemvalue="tx_manager_lib" />
<item index="20" class="java.lang.String" itemvalue="Jinja2" />
<item index="21" class="java.lang.String" itemvalue="licencecontrollerutilslib" />
<item index="22" class="java.lang.String" itemvalue="flask-compress" />
<item index="23" class="java.lang.String" itemvalue="elasticsearch" />
<item index="24" class="java.lang.String" itemvalue="lxml" />
<item index="25" class="java.lang.String" itemvalue="uploaderlib" />
<item index="26" class="java.lang.String" itemvalue="mongolib" />
<item index="27" class="java.lang.String" itemvalue="xmltodict" />
<item index="28" class="java.lang.String" itemvalue="Flask_Cors" />
<item index="29" class="java.lang.String" itemvalue="excellib" />
<item index="30" class="java.lang.String" itemvalue="comtypes" />
<item index="31" class="java.lang.String" itemvalue="concurrent-log-handler" />
<item index="32" class="java.lang.String" itemvalue="itsdangerous" />
<item index="33" class="java.lang.String" itemvalue="aeslib" />
<item index="34" class="java.lang.String" itemvalue="xlrd" />
<item index="35" class="java.lang.String" itemvalue="Flask" />
<item index="36" class="java.lang.String" itemvalue="coverage" />
<item index="37" class="java.lang.String" itemvalue="Werkzeug" />
<item index="38" class="java.lang.String" itemvalue="versionlib" />
<item index="39" class="java.lang.String" itemvalue="kafkalib" />
<item index="40" class="java.lang.String" itemvalue="paho_mqtt" />
<item index="41" class="java.lang.String" itemvalue="orjson" />
<item index="42" class="java.lang.String" itemvalue="xlsxwriter" />
<item index="43" class="java.lang.String" itemvalue="gunicorn" />
<item index="44" class="java.lang.String" itemvalue="kafka-python" />
<item index="45" class="java.lang.String" itemvalue="simplejson" />
<item index="46" class="java.lang.String" itemvalue="bcrypt" />
<item index="47" class="java.lang.String" itemvalue="customexceptionslib" />
<item index="48" class="java.lang.String" itemvalue="docxtpl" />
<item index="49" class="java.lang.String" itemvalue="pycryptodome" />
<item index="50" class="java.lang.String" itemvalue="uuidlib" />
<item index="51" class="java.lang.String" itemvalue="jsonpatch" />
<item index="52" class="java.lang.String" itemvalue="esprima" />
<item index="53" class="java.lang.String" itemvalue="openpyxl" />
<item index="54" class="java.lang.String" itemvalue="numpy" />
<item index="55" class="java.lang.String" itemvalue="pkm_changecontrol_lib" />
<item index="56" class="java.lang.String" itemvalue="pkm_entities_lib" />
<item index="57" class="java.lang.String" itemvalue="pkm_calculationbuilder_lib" />
</list>
</value>
</option>
</inspection_tool>
</profile>
</component>
\ No newline at end of file
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.7 (TempServer) (2)" project-jdk-type="Python SDK" />
<component name="PyCharmProfessionalAdvertiser">
<option name="shown" value="true" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/../TempServer/.idea/TempServicer.iml" filepath="$PROJECT_DIR$/../TempServer/.idea/TempServicer.iml" />
</modules>
</component>
</project>
\ No newline at end of file
import datetime
from enum import IntEnum
from KL.types import *
from KL.constants import ObjectIds
class ApplicationType(IntEnum):
"""
:ivar Server:
:vartype Server: 0
:ivar Client:
:vartype Client: 1
:ivar ClientAndServer:
:vartype ClientAndServer: 2
:ivar DiscoveryServer:
:vartype DiscoveryServer: 3
"""
Server = 0
Client = 1
ClientAndServer = 2
DiscoveryServer = 3
class BrowseDirection(IntEnum):
"""
:ivar Forward:
:vartype Forward: 0
:ivar Inverse:
:vartype Inverse: 1
:ivar Both:
:vartype Both: 2
:ivar Invalid:
:vartype Invalid: 3
"""
Forward = 0
Inverse = 1
Both = 2
Invalid = 3
class BrowseResultMask(IntEnum):
"""
:ivar None_:
:vartype None_: 0
:ivar ReferenceTypeId:
:vartype ReferenceTypeId: 1
:ivar IsForward:
:vartype IsForward: 2
:ivar NodeClass:
:vartype NodeClass: 4
:ivar BrowseName:
:vartype BrowseName: 8
:ivar DisplayName:
:vartype DisplayName: 16
:ivar TypeDefinition:
:vartype TypeDefinition: 32
:ivar All:
:vartype All: 63
:ivar ReferenceTypeInfo:
:vartype ReferenceTypeInfo: 3
:ivar TargetInfo:
:vartype TargetInfo: 60
"""
None_ = 0
ReferenceTypeId = 1
IsForward = 2
NodeClass = 4
BrowseName = 8
DisplayName = 16
TypeDefinition = 32
All = 63
ReferenceTypeInfo = 3
TargetInfo = 60
class ApplicationDescription(FrozenClass):
"""
:ivar ApplicationUri:
:vartype ApplicationUri: String
:ivar ProductUri:
:vartype ProductUri: String
:ivar ApplicationName:
:vartype ApplicationName: LocalizedText
:ivar ApplicationType:
:vartype ApplicationType: ApplicationType
:ivar GatewayServerUri:
:vartype GatewayServerUri: String
:ivar DiscoveryProfileUri:
:vartype DiscoveryProfileUri: String
:ivar DiscoveryUrls:
:vartype DiscoveryUrls: String
"""
types = [
('ApplicationUri', 'String'),
('ProductUri', 'String'),
('ApplicationName', 'LocalizedText'),
('ApplicationType', 'ApplicationType'),
('GatewayServerUri', 'String'),
('DiscoveryProfileUri', 'String'),
('DiscoveryUrls', 'ListOfString'),
]
def __init__(self):
self.ApplicationUri = None
self.ProductUri = None
self.ApplicationName = LocalizedText()
self.ApplicationType = ApplicationType(0)
self.GatewayServerUri = None
self.DiscoveryProfileUri = None
self.DiscoveryUrls = []
self._freeze = True
def __str__(self):
return 'ApplicationDescription(ApplicationUri:{self.ApplicationUri}, ProductUri:{self.ProductUri}, ApplicationName:{self.ApplicationName}, ApplicationType:{self.ApplicationType}, GatewayServerUri:{self.GatewayServerUri}, DiscoveryProfileUri:{self.DiscoveryProfileUri}, DiscoveryUrls:{self.DiscoveryUrls})'
__repr__ = __str__
class EndpointDescription(FrozenClass):
"""
:ivar EndpointUrl:
:vartype EndpointUrl: String
:ivar Server:
:vartype Server: ApplicationDescription
:ivar ServerCertificate:
:vartype ServerCertificate: ByteString
:ivar SecurityMode:
:vartype SecurityMode: MessageSecurityMode
:ivar SecurityPolicyUri:
:vartype SecurityPolicyUri: String
:ivar UserIdentityTokens:
:vartype UserIdentityTokens: UserTokenPolicy
:ivar TransportProfileUri:
:vartype TransportProfileUri: String
:ivar SecurityLevel:
:vartype SecurityLevel: Byte
"""
types = [
('EndpointUrl', 'String'),
('Server', 'ApplicationDescription'),
('ServerCertificate', 'ByteString'),
('SecurityMode', 'MessageSecurityMode'),
('SecurityPolicyUri', 'String'),
('UserIdentityTokens', 'ListOfUserTokenPolicy'),
('TransportProfileUri', 'String'),
('SecurityLevel', 'Byte'),
]
def __init__(self):
self.EndpointUrl = None
self.Server = ApplicationDescription()
self.ServerCertificate = None
self.SecurityMode = MessageSecurityMode(0)
self.SecurityPolicyUri = None
self.UserIdentityTokens = []
self.TransportProfileUri = None
self.SecurityLevel = 0
self._freeze = True
def __str__(self):
return 'EndpointDescription(EndpointUrl:{self.EndpointUrl}, Server:{self.Server}, ServerCertificate:{self.ServerCertificate}, SecurityMode:{self.SecurityMode}, SecurityPolicyUri:{self.SecurityPolicyUri}, UserIdentityTokens:{self.UserIdentityTokens}, TransportProfileUri:{self.TransportProfileUri}, SecurityLevel:{self.SecurityLevel})'
__repr__ = __str__
class AddReferencesItem(FrozenClass):
"""
:ivar SourceNodeId:
:vartype SourceNodeId: NodeId
:ivar ReferenceTypeId:
:vartype ReferenceTypeId: NodeId
:ivar IsForward:
:vartype IsForward: Boolean
:ivar TargetServerUri:
:vartype TargetServerUri: String
:ivar TargetNodeId:
:vartype TargetNodeId: ExpandedNodeId
:ivar TargetNodeClass:
:vartype TargetNodeClass: NodeClass
"""
types = [
('SourceNodeId', 'NodeId'),
('ReferenceTypeId', 'NodeId'),
('IsForward', 'Boolean'),
('TargetServerUri', 'String'),
('TargetNodeId', 'ExpandedNodeId'),
('TargetNodeClass', 'NodeClass'),
]
def __init__(self):
self.SourceNodeId = NodeId()
self.ReferenceTypeId = NodeId()
self.IsForward = True
self.TargetServerUri = None
self.TargetNodeId = ExpandedNodeId()
self.TargetNodeClass = NodeClass(0)
self._freeze = True
class MessageSecurityMode(IntEnum):
"""
:ivar Invalid:
:vartype Invalid: 0
:ivar None_:
:vartype None_: 1
:ivar Sign:
:vartype Sign: 2
:ivar SignAndEncrypt:
:vartype SignAndEncrypt: 3
"""
Invalid = 0
None_ = 1
Sign = 2
SignAndEncrypt = 3
class UserTokenType(IntEnum):
"""
:ivar Anonymous:
:vartype Anonymous: 0
:ivar UserName:
:vartype UserName: 1
:ivar Certificate:
:vartype Certificate: 2
:ivar IssuedToken:
:vartype IssuedToken: 3
"""
Anonymous = 0
UserName = 1
Certificate = 2
IssuedToken = 3
class UserTokenPolicy(FrozenClass):
"""
:ivar PolicyId:
:vartype PolicyId: String
:ivar TokenType:
:vartype TokenType: UserTokenType
:ivar IssuedTokenType:
:vartype IssuedTokenType: String
:ivar IssuerEndpointUrl:
:vartype IssuerEndpointUrl: String
:ivar SecurityPolicyUri:
:vartype SecurityPolicyUri: String
"""
types = [
('PolicyId', 'String'),
('TokenType', 'UserTokenType'),
('IssuedTokenType', 'String'),
('IssuerEndpointUrl', 'String'),
('SecurityPolicyUri', 'String'),
]
def __init__(self):
self.PolicyId = None
self.TokenType = UserTokenType(0)
self.IssuedTokenType = None
self.IssuerEndpointUrl = None
self.SecurityPolicyUri = None
self._freeze = True
def __str__(self):
return 'UserTokenPolicy(PolicyId:{self.PolicyId}, TokenType:{self.TokenType}, IssuedTokenType:{self.IssuedTokenType}, IssuerEndpointUrl:{self.IssuerEndpointUrl}, SecurityPolicyUri:{self.SecurityPolicyUri})'
__repr__ = __str__
class ServerState(IntEnum):
"""
:ivar Running:
:vartype Running: 0
:ivar Failed:
:vartype Failed: 1
:ivar NoConfiguration:
:vartype NoConfiguration: 2
:ivar Suspended:
:vartype Suspended: 3
:ivar Shutdown:
:vartype Shutdown: 4
:ivar Test:
:vartype Test: 5
:ivar CommunicationFault:
:vartype CommunicationFault: 6
:ivar Unknown:
:vartype Unknown: 7
"""
Running = 0
Failed = 1
NoConfiguration = 2
Suspended = 3
Shutdown = 4
Test = 5
CommunicationFault = 6
Unknown = 7
class ServerStatusDataType(FrozenClass):
"""
:ivar StartTime:
:vartype StartTime: DateTime
:ivar CurrentTime:
:vartype CurrentTime: DateTime
:ivar State:
:vartype State: ServerState
:ivar BuildInfo:
:vartype BuildInfo: BuildInfo
:ivar SecondsTillShutdown:
:vartype SecondsTillShutdown: UInt32
:ivar ShutdownReason:
:vartype ShutdownReason: LocalizedText
"""
types = [
('StartTime', 'DateTime'),
('CurrentTime', 'DateTime'),
('State', 'ServerState'),
('BuildInfo', 'BuildInfo'),
('SecondsTillShutdown', 'UInt32'),
('ShutdownReason', 'LocalizedText'),
]
def __init__(self):
self.StartTime = datetime.datetime.utcnow()
self.CurrentTime = datetime.datetime.utcnow()
self.State = ServerState(0)
self.BuildInfo = BuildInfo()
self.SecondsTillShutdown = 0
self.ShutdownReason = LocalizedText()
self._freeze = True
def __str__(self):
return 'ServerStatusDataType(StartTime:{self.StartTime}, CurrentTime:{self.CurrentTime}, State:{self.State}, BuildInfo:{self.BuildInfo}, SecondsTillShutdown:{self.SecondsTillShutdown}, ShutdownReason:{self.ShutdownReason})'
__repr__ = __str__
class BuildInfo(FrozenClass):
"""
:ivar ProductUri:
:vartype ProductUri: String
:ivar ManufacturerName:
:vartype ManufacturerName: String
:ivar ProductName:
:vartype ProductName: String
:ivar SoftwareVersion:
:vartype SoftwareVersion: String
:ivar BuildNumber:
:vartype BuildNumber: String
:ivar BuildDate:
:vartype BuildDate: DateTime
"""
types = [
('ProductUri', 'String'),
('ManufacturerName', 'String'),
('ProductName', 'String'),
('SoftwareVersion', 'String'),
('BuildNumber', 'String'),
('BuildDate', 'DateTime'),
]
def __init__(self):
self.ProductUri = None
self.ManufacturerName = None
self.ProductName = None
self.SoftwareVersion = None
self.BuildNumber = None
self.BuildDate = datetime.datetime.utcnow()
self._freeze = True
def __str__(self):
return 'BuildInfo(ProductUri:{self.ProductUri}, ManufacturerName:{self.ManufacturerName}, ProductName:{self.ProductName}, SoftwareVersion:{self.SoftwareVersion}, BuildNumber:{self.BuildNumber}, BuildDate:{self.BuildDate})'
__repr__ = __str__
class ReferenceTypeAttributes(FrozenClass):
"""
:ivar SpecifiedAttributes:
:vartype SpecifiedAttributes: UInt32
:ivar DisplayName:
:vartype DisplayName: LocalizedText
:ivar Description:
:vartype Description: LocalizedText
:ivar WriteMask:
:vartype WriteMask: UInt32
:ivar UserWriteMask:
:vartype UserWriteMask: UInt32
:ivar IsAbstract:
:vartype IsAbstract: Boolean
:ivar Symmetric:
:vartype Symmetric: Boolean
:ivar InverseName:
:vartype InverseName: LocalizedText
"""
types = [
('SpecifiedAttributes', 'UInt32'),
('DisplayName', 'LocalizedText'),
('Description', 'LocalizedText'),
('WriteMask', 'UInt32'),
('UserWriteMask', 'UInt32'),
('IsAbstract', 'Boolean'),
('Symmetric', 'Boolean'),
('InverseName', 'LocalizedText'),
]
def __init__(self):
self.SpecifiedAttributes = 0
self.DisplayName = LocalizedText()
self.Description = LocalizedText()
self.WriteMask = 0
self.UserWriteMask = 0
self.IsAbstract = True
self.Symmetric = True
self.InverseName = LocalizedText()
self._freeze = True
def __str__(self):
return 'ReferenceTypeAttributes(SpecifiedAttributes:{self.SpecifiedAttributes}, DisplayName:{' \
'self.DisplayName}, Description:{self.Description}, WriteMask:{self.WriteMask}, UserWriteMask:{' \
'self.UserWriteMask}, IsAbstract:{self.IsAbstract}, Symmetric:{self.Symmetric}, InverseName:{' \
'self.InverseName}) '
__repr__ = __str__
ExpandedNodeId = NodeId
class NodeClass(IntEnum):
"""
:ivar Unspecified:
:vartype Unspecified: 0
:ivar Object:
:vartype Object: 1
:ivar Variable:
:vartype Variable: 2
:ivar Method:
:vartype Method: 4
:ivar ObjectType:
:vartype ObjectType: 8
:ivar VariableType:
:vartype VariableType: 16
:ivar ReferenceType:
:vartype ReferenceType: 32
:ivar DataType:
:vartype DataType: 64
:ivar View:
:vartype View: 128
"""
Unspecified = 0
Object = 1
Variable = 2
Method = 4
ObjectType = 8
VariableType = 16
ReferenceType = 32
DataType = 64
View = 128
class NodeAttributes(FrozenClass):
"""
:ivar SpecifiedAttributes:
:vartype SpecifiedAttributes: UInt32
:ivar DisplayName:
:vartype DisplayName: LocalizedText
:ivar Description:
:vartype Description: LocalizedText
:ivar WriteMask:
:vartype WriteMask: UInt32
:ivar UserWriteMask:
:vartype UserWriteMask: UInt32
"""
types = [
('SpecifiedAttributes', 'UInt32'),
('DisplayName', 'LocalizedText'),
('Description', 'LocalizedText'),
('WriteMask', 'UInt32'),
('UserWriteMask', 'UInt32'),
]
def __init__(self):
self.SpecifiedAttributes = 0
self.DisplayName = LocalizedText()
self.Description = LocalizedText()
self.WriteMask = 0
self.UserWriteMask = 0
self._freeze = True
def __str__(self):
return 'NodeAttributes(SpecifiedAttributes:{self.SpecifiedAttributes}, DisplayName:{self.DisplayName}, ' \
'Description:{self.Description}, WriteMask:{self.WriteMask}, UserWriteMask:{self.UserWriteMask}) '
__repr__ = __str__
class NodeAttributesMask(IntEnum):
"""
:ivar None_:
:vartype None_: 0
:ivar AccessLevel:
:vartype AccessLevel: 1
:ivar ArrayDimensions:
:vartype ArrayDimensions: 2
:ivar BrowseName:
:vartype BrowseName: 4
:ivar ContainsNoLoops:
:vartype ContainsNoLoops: 8
:ivar DataType:
:vartype DataType: 16
:ivar Description:
:vartype Description: 32
:ivar DisplayName:
:vartype DisplayName: 64
:ivar EventNotifier:
:vartype EventNotifier: 128
:ivar Executable:
:vartype Executable: 256
:ivar Historizing:
:vartype Historizing: 512
:ivar InverseName:
:vartype InverseName: 1024
:ivar IsAbstract:
:vartype IsAbstract: 2048
:ivar MinimumSamplingInterval:
:vartype MinimumSamplingInterval: 4096
:ivar NodeClass:
:vartype NodeClass: 8192
:ivar NodeId:
:vartype NodeId: 16384
:ivar Symmetric:
:vartype Symmetric: 32768
:ivar UserAccessLevel:
:vartype UserAccessLevel: 65536
:ivar UserExecutable:
:vartype UserExecutable: 131072
:ivar UserWriteMask:
:vartype UserWriteMask: 262144
:ivar ValueRank:
:vartype ValueRank: 524288
:ivar WriteMask:
:vartype WriteMask: 1048576
:ivar Value:
:vartype Value: 2097152
:ivar DataTypeDefinition:
:vartype DataTypeDefinition: 4194304
:ivar RolePermissions:
:vartype RolePermissions: 8388608
:ivar AccessRestrictions:
:vartype AccessRestrictions: 16777216
:ivar All:
:vartype All: 33554431
:ivar BaseNode:
:vartype BaseNode: 26501220
:ivar Object:
:vartype Object: 26501348
:ivar ObjectType:
:vartype ObjectType: 26503268
:ivar Variable:
:vartype Variable: 26571383
:ivar VariableType:
:vartype VariableType: 28600438
:ivar Method:
:vartype Method: 26632548
:ivar ReferenceType:
:vartype ReferenceType: 26537060
:ivar View:
:vartype View: 26501356
"""
None_ = 0
AccessLevel = 1
ArrayDimensions = 2
BrowseName = 4
ContainsNoLoops = 8
DataType = 16
Description = 32
DisplayName = 64
EventNotifier = 128
Executable = 256
Historizing = 512
InverseName = 1024
IsAbstract = 2048
MinimumSamplingInterval = 4096
NodeClass = 8192
NodeId = 16384
Symmetric = 32768
UserAccessLevel = 65536
UserExecutable = 131072
UserWriteMask = 262144
ValueRank = 524288
WriteMask = 1048576
Value = 2097152
DataTypeDefinition = 4194304
RolePermissions = 8388608
AccessRestrictions = 16777216
All = 33554431
BaseNode = 26501220
Object = 26501348
ObjectType = 26503268
Variable = 26571383
VariableType = 28600438
Method = 26632548
ReferenceType = 26537060
View = 26501356
class AddNodesItem(FrozenClass):
"""
:ivar ParentNodeId:
:vartype ParentNodeId: ExpandedNodeId
:ivar ReferenceTypeId:
:vartype ReferenceTypeId: NodeId
:ivar RequestedNewNodeId:
:vartype RequestedNewNodeId: ExpandedNodeId
:ivar BrowseName:
:vartype BrowseName: QualifiedName
:ivar NodeClass:
:vartype NodeClass: NodeClass
:ivar NodeAttributes:
:vartype NodeAttributes: ExtensionObject
:ivar TypeDefinition:
:vartype TypeDefinition: ExpandedNodeId
"""
types = [
('ParentNodeId', 'ExpandedNodeId'),
('ReferenceTypeId', 'NodeId'),
('RequestedNewNodeId', 'ExpandedNodeId'),
('BrowseName', 'QualifiedName'),
('NodeClass', 'NodeClass'),
('NodeAttributes', 'ExtensionObject'),
('TypeDefinition', 'ExpandedNodeId'),
]
def __init__(self):
self.ParentNodeId = ExpandedNodeId()
self.ReferenceTypeId = NodeId()
self.RequestedNewNodeId = ExpandedNodeId()
self.BrowseName = QualifiedName()
self.NodeClass = NodeClass(0)
self.NodeAttributes = ExtensionObject()
self.TypeDefinition = ExpandedNodeId()
self._freeze = True
def __str__(self):
return 'AddNodesItem(ParentNodeId:{self.ParentNodeId}, ReferenceTypeId:{self.ReferenceTypeId}, RequestedNewNodeId:{self.RequestedNewNodeId}, BrowseName:{self.BrowseName}, NodeClass:{self.NodeClass}, NodeAttributes:{self.NodeAttributes}, TypeDefinition:{self.TypeDefinition})'
__repr__ = __str__
class ReadParameters(FrozenClass):
"""
:ivar MaxAge:
:vartype MaxAge: Double
:ivar TimestampsToReturn:
:vartype TimestampsToReturn: TimestampsToReturn
:ivar NodesToRead:
:vartype NodesToRead: ReadValueId
"""
types = [
('MaxAge', 'Double'),
('TimestampsToReturn', 'TimestampsToReturn'),
('NodesToRead', 'ListOfReadValueId'),
]
def __init__(self):
self.MaxAge = 0
self.TimestampsToReturn = TimestampsToReturn(0)
self.NodesToRead = []
self._freeze = True
def __str__(self):
return 'ReadParameters(MaxAge:{self.MaxAge}, TimestampsToReturn:{self.TimestampsToReturn}, NodesToRead:{self.NodesToRead})'
__repr__ = __str__
class WriteParameters(FrozenClass):
"""
:ivar NodesToWrite:
:vartype NodesToWrite: WriteValue
"""
ua_types = [
('NodesToWrite', 'ListOfWriteValue'),
]
def __init__(self):
self.NodesToWrite = []
self._freeze = True
def __str__(self):
return 'WriteParameters(NodesToWrite:{self.NodesToWrite})'
__repr__ = __str__
class ReadValueId(FrozenClass):
"""
:ivar NodeId:
:vartype NodeId: NodeId
:ivar AttributeId:
:vartype AttributeId: UInt32
:ivar IndexRange:
:vartype IndexRange: String
:ivar DataEncoding:
:vartype DataEncoding: QualifiedName
"""
types = [
('NodeId', 'NodeId'),
('AttributeId', 'UInt32'),
('IndexRange', 'String'),
('DataEncoding', 'QualifiedName'),
]
def __init__(self):
self.NodeId = NodeId()
self.AttributeId = 0
self.IndexRange = None
self.DataEncoding = QualifiedName()
self._freeze = True
def __str__(self):
return 'ReadValueId(NodeId:{self.NodeId}, AttributeId:{self.AttributeId}, IndexRange:{self.IndexRange}, DataEncoding:{self.DataEncoding})'
__repr__ = __str__
class TimestampsToReturn(IntEnum):
"""
:ivar Source:
:vartype Source: 0
:ivar Server:
:vartype Server: 1
:ivar Both:
:vartype Both: 2
:ivar Neither:
:vartype Neither: 3
:ivar Invalid:
:vartype Invalid: 4
"""
Source = 0
Server = 1
Both = 2
Neither = 3
Invalid = 4
class ReferenceDescription(FrozenClass):
"""
:ivar ReferenceTypeId:
:vartype ReferenceTypeId: NodeId
:ivar IsForward:
:vartype IsForward: Boolean
:ivar NodeId:
:vartype NodeId: ExpandedNodeId
:ivar BrowseName:
:vartype BrowseName: QualifiedName
:ivar DisplayName:
:vartype DisplayName: LocalizedText
:ivar NodeClass:
:vartype NodeClass: NodeClass
:ivar TypeDefinition:
:vartype TypeDefinition: ExpandedNodeId
"""
types = [
('ReferenceTypeId', 'NodeId'),
('IsForward', 'Boolean'),
('NodeId', 'ExpandedNodeId'),
('BrowseName', 'QualifiedName'),
('DisplayName', 'LocalizedText'),
('NodeClass', 'NodeClass'),
('TypeDefinition', 'ExpandedNodeId'),
]
def __init__(self):
self.ReferenceTypeId = NodeId()
self.IsForward = True
self.NodeId = ExpandedNodeId()
self.BrowseName = QualifiedName()
self.DisplayName = LocalizedText()
self.NodeClass = NodeClass(0)
self.TypeDefinition = ExpandedNodeId()
self._freeze = True
def __str__(self):
return 'ReferenceDescription(ReferenceTypeId:{self.ReferenceTypeId}, IsForward:{self.IsForward}, NodeId:{self.NodeId}, BrowseName:{self.BrowseName}, DisplayName:{self.DisplayName}, NodeClass:{self.NodeClass}, TypeDefinition:{self.TypeDefinition})'
__repr__ = __str__
class VariableAttributes(FrozenClass):
"""
:ivar SpecifiedAttributes:
:vartype SpecifiedAttributes: UInt32
:ivar DisplayName:
:vartype DisplayName: LocalizedText
:ivar Description:
:vartype Description: LocalizedText
:ivar WriteMask:
:vartype WriteMask: UInt32
:ivar UserWriteMask:
:vartype UserWriteMask: UInt32
:ivar Value:
:vartype Value: Variant
:ivar DataType:
:vartype DataType: NodeId
:ivar ValueRank:
:vartype ValueRank: Int32
:ivar ArrayDimensions:
:vartype ArrayDimensions: UInt32
:ivar AccessLevel:
:vartype AccessLevel: Byte
:ivar UserAccessLevel:
:vartype UserAccessLevel: Byte
:ivar MinimumSamplingInterval:
:vartype MinimumSamplingInterval: Double
:ivar Historizing:
:vartype Historizing: Boolean
"""
types = [
('SpecifiedAttributes', 'UInt32'),
('DisplayName', 'LocalizedText'),
('Description', 'LocalizedText'),
('WriteMask', 'UInt32'),
('UserWriteMask', 'UInt32'),
('Value', 'Variant'),
('DataType', 'NodeId'),
('ValueRank', 'Int32'),
('ArrayDimensions', 'ListOfUInt32'),
('AccessLevel', 'Byte'),
('UserAccessLevel', 'Byte'),
('MinimumSamplingInterval', 'Double'),
('Historizing', 'Boolean'),
]
def __init__(self):
self.SpecifiedAttributes = 0
self.DisplayName = LocalizedText()
self.Description = LocalizedText()
self.WriteMask = 0
self.UserWriteMask = 0
self.Value = Variant()
self.DataType = NodeId()
self.ValueRank = 0
self.ArrayDimensions = []
self.AccessLevel = 0
self.UserAccessLevel = 0
self.MinimumSamplingInterval = 0
self.Historizing = True
self._freeze = True
def __str__(self):
return 'VariableAttributes(SpecifiedAttributes:{self.SpecifiedAttributes}, DisplayName:{self.DisplayName}, ' \
'Description:{self.Description}, WriteMask:{self.WriteMask}, UserWriteMask:{self.UserWriteMask}, ' \
'Value:{self.Value}, DataType:{self.DataType}, ValueRank:{self.ValueRank}, ArrayDimensions:{' \
'self.ArrayDimensions}, AccessLevel:{self.AccessLevel}, UserAccessLevel:{self.UserAccessLevel}, ' \
'MinimumSamplingInterval:{self.MinimumSamplingInterval}, Historizing:{self.Historizing}) '
__repr__ = __str__
class VariableTypeAttributes(FrozenClass):
"""
:ivar SpecifiedAttributes:
:vartype SpecifiedAttributes: UInt32
:ivar DisplayName:
:vartype DisplayName: LocalizedText
:ivar Description:
:vartype Description: LocalizedText
:ivar WriteMask:
:vartype WriteMask: UInt32
:ivar UserWriteMask:
:vartype UserWriteMask: UInt32
:ivar Value:
:vartype Value: Variant
:ivar DataType:
:vartype DataType: NodeId
:ivar ValueRank:
:vartype ValueRank: Int32
:ivar ArrayDimensions:
:vartype ArrayDimensions: UInt32
:ivar IsAbstract:
:vartype IsAbstract: Boolean
"""
types = [
('SpecifiedAttributes', 'UInt32'),
('DisplayName', 'LocalizedText'),
('Description', 'LocalizedText'),
('WriteMask', 'UInt32'),
('UserWriteMask', 'UInt32'),
('Value', 'Variant'),
('DataType', 'NodeId'),
('ValueRank', 'Int32'),
('ArrayDimensions', 'ListOfUInt32'),
('IsAbstract', 'Boolean'),
]
def __init__(self):
self.SpecifiedAttributes = 0
self.DisplayName = LocalizedText()
self.Description = LocalizedText()
self.WriteMask = 0
self.UserWriteMask = 0
self.Value = Variant()
self.DataType = NodeId()
self.ValueRank = 0
self.ArrayDimensions = []
self.IsAbstract = True
self._freeze = True
def __str__(self):
return 'VariableTypeAttributes(SpecifiedAttributes:{self.SpecifiedAttributes}, DisplayName:{self.DisplayName}, Description:{self.Description}, WriteMask:{self.WriteMask}, UserWriteMask:{self.UserWriteMask}, Value:{self.Value}, DataType:{self.DataType}, ValueRank:{self.ValueRank}, ArrayDimensions:{self.ArrayDimensions}, IsAbstract:{self.IsAbstract})'
__repr__ = __str__
class ObjectAttributes(FrozenClass):
"""
:ivar SpecifiedAttributes:
:vartype SpecifiedAttributes: UInt32
:ivar DisplayName:
:vartype DisplayName: LocalizedText
:ivar Description:
:vartype Description: LocalizedText
:ivar WriteMask:
:vartype WriteMask: UInt32
:ivar UserWriteMask:
:vartype UserWriteMask: UInt32
:ivar EventNotifier:
:vartype EventNotifier: Byte
"""
types = [
('SpecifiedAttributes', 'UInt32'),
('DisplayName', 'LocalizedText'),
('Description', 'LocalizedText'),
('WriteMask', 'UInt32'),
('UserWriteMask', 'UInt32'),
('EventNotifier', 'Byte'),
]
def __init__(self):
self.SpecifiedAttributes = 0
self.DisplayName = LocalizedText()
self.Description = LocalizedText()
self.WriteMask = 0
self.UserWriteMask = 0
self.EventNotifier = 0
self._freeze = True
def __str__(self):
return 'ObjectAttributes(SpecifiedAttributes:{self.SpecifiedAttributes}, DisplayName:{self.DisplayName}, ' \
'Description:{self.Description}, WriteMask:{self.WriteMask}, UserWriteMask:{self.UserWriteMask}, ' \
'EventNotifier:{self.EventNotifier}) '
__repr__ = __str__
class DataTypeAttributes(FrozenClass):
"""
:ivar SpecifiedAttributes:
:vartype SpecifiedAttributes: UInt32
:ivar DisplayName:
:vartype DisplayName: LocalizedText
:ivar Description:
:vartype Description: LocalizedText
:ivar WriteMask:
:vartype WriteMask: UInt32
:ivar UserWriteMask:
:vartype UserWriteMask: UInt32
:ivar IsAbstract:
:vartype IsAbstract: Boolean
"""
types = [
('SpecifiedAttributes', 'UInt32'),
('DisplayName', 'LocalizedText'),
('Description', 'LocalizedText'),
('WriteMask', 'UInt32'),
('UserWriteMask', 'UInt32'),
('IsAbstract', 'Boolean'),
]
def __init__(self):
self.SpecifiedAttributes = 0
self.DisplayName = LocalizedText()
self.Description = LocalizedText()
self.WriteMask = 0
self.UserWriteMask = 0
self.IsAbstract = True
self._freeze = True
def __str__(self):
return 'DataTypeAttributes(SpecifiedAttributes:{self.SpecifiedAttributes}, DisplayName:{self.DisplayName}, Description:{self.Description}, WriteMask:{self.WriteMask}, UserWriteMask:{self.UserWriteMask}, IsAbstract:{self.IsAbstract})'
__repr__ = __str__
class ObjectTypeAttributes(FrozenClass):
"""
:ivar SpecifiedAttributes:
:vartype SpecifiedAttributes: UInt32
:ivar DisplayName:
:vartype DisplayName: LocalizedText
:ivar Description:
:vartype Description: LocalizedText
:ivar WriteMask:
:vartype WriteMask: UInt32
:ivar UserWriteMask:
:vartype UserWriteMask: UInt32
:ivar IsAbstract:
:vartype IsAbstract: Boolean
"""
types = [
('SpecifiedAttributes', 'UInt32'),
('DisplayName', 'LocalizedText'),
('Description', 'LocalizedText'),
('WriteMask', 'UInt32'),
('UserWriteMask', 'UInt32'),
('IsAbstract', 'Boolean'),
]
def __init__(self):
self.SpecifiedAttributes = 0
self.DisplayName = LocalizedText()
self.Description = LocalizedText()
self.WriteMask = 0
self.UserWriteMask = 0
self.IsAbstract = True
self._freeze = True
def __str__(self):
return 'ObjectTypeAttributes(SpecifiedAttributes:{self.SpecifiedAttributes}, DisplayName:{self.DisplayName}, ' \
'Description:{self.Description}, WriteMask:{self.WriteMask}, UserWriteMask:{self.UserWriteMask}, ' \
'IsAbstract:{self.IsAbstract}) '
__repr__ = __str__
class AddNodesResult(FrozenClass):
"""
:ivar StatusCode:
:vartype StatusCode: StatusCode
:ivar AddedNodeId:
:vartype AddedNodeId: NodeId
"""
types = [
('StatusCode', 'StatusCode'),
('AddedNodeId', 'NodeId'),
]
def __init__(self):
self.StatusCode = StatusCode()
self.AddedNodeId = NodeId()
self._freeze = True
def __str__(self):
return 'AddNodesResult(StatusCode:{self.StatusCode}, AddedNodeId:{self.AddedNodeId})'
__repr__ = __str__
class GenericAttributes(FrozenClass):
"""
:ivar SpecifiedAttributes:
:vartype SpecifiedAttributes: UInt32
:ivar DisplayName:
:vartype DisplayName: LocalizedText
:ivar Description:
:vartype Description: LocalizedText
:ivar WriteMask:
:vartype WriteMask: UInt32
:ivar UserWriteMask:
:vartype UserWriteMask: UInt32
:ivar AttributeValues:
:vartype AttributeValues: GenericAttributeValue
"""
types = [
('SpecifiedAttributes', 'UInt32'),
('DisplayName', 'LocalizedText'),
('Description', 'LocalizedText'),
('WriteMask', 'UInt32'),
('UserWriteMask', 'UInt32'),
('AttributeValues', 'ListOfGenericAttributeValue'),
]
def __init__(self):
self.SpecifiedAttributes = 0
self.DisplayName = LocalizedText()
self.Description = LocalizedText()
self.WriteMask = 0
self.UserWriteMask = 0
self.AttributeValues = []
self._freeze = True
def __str__(self):
return 'GenericAttributes(SpecifiedAttributes:{self.SpecifiedAttributes}, DisplayName:{self.DisplayName}, Description:{self.Description}, WriteMask:{self.WriteMask}, UserWriteMask:{self.UserWriteMask}, AttributeValues:{self.AttributeValues})'
__repr__ = __str__
class ViewAttributes(FrozenClass):
"""
:ivar SpecifiedAttributes:
:vartype SpecifiedAttributes: UInt32
:ivar DisplayName:
:vartype DisplayName: LocalizedText
:ivar Description:
:vartype Description: LocalizedText
:ivar WriteMask:
:vartype WriteMask: UInt32
:ivar UserWriteMask:
:vartype UserWriteMask: UInt32
:ivar ContainsNoLoops:
:vartype ContainsNoLoops: Boolean
:ivar EventNotifier:
:vartype EventNotifier: Byte
"""
types = [
('SpecifiedAttributes', 'UInt32'),
('DisplayName', 'LocalizedText'),
('Description', 'LocalizedText'),
('WriteMask', 'UInt32'),
('UserWriteMask', 'UInt32'),
('ContainsNoLoops', 'Boolean'),
('EventNotifier', 'Byte'),
]
def __init__(self):
self.SpecifiedAttributes = 0
self.DisplayName = LocalizedText()
self.Description = LocalizedText()
self.WriteMask = 0
self.UserWriteMask = 0
self.ContainsNoLoops = True
self.EventNotifier = 0
self._freeze = True
def __str__(self):
return 'ViewAttributes(SpecifiedAttributes:{self.SpecifiedAttributes}, DisplayName:{self.DisplayName}, Description:{self.Description}, WriteMask:{self.WriteMask}, UserWriteMask:{self.UserWriteMask}, ContainsNoLoops:{self.ContainsNoLoops}, EventNotifier:{self.EventNotifier})'
__repr__ = __str__
class WriteValue(FrozenClass):
"""
:ivar NodeId:
:vartype NodeId: NodeId
:ivar AttributeId:
:vartype AttributeId: UInt32
:ivar IndexRange:
:vartype IndexRange: String
:ivar Value:
:vartype Value: DataValue
"""
types = [
('NodeId', 'NodeId'),
('AttributeId', 'UInt32'),
('IndexRange', 'String'),
('Value', 'DataValue'),
]
def __init__(self):
self.NodeId = NodeId()
self.AttributeId = 0
self.IndexRange = None
self.Value = DataValue()
self._freeze = True
def __str__(self):
return 'WriteValue(NodeId:{self.NodeId}, AttributeId:{self.AttributeId}, IndexRange:{self.IndexRange}, Value:{self.Value})'
__repr__ = __str__
class KeyValuePair(FrozenClass):
"""
:ivar Key:
:vartype Key: QualifiedName
:ivar Value:
:vartype Value: Variant
"""
types = [
('Key', 'QualifiedName'),
('Value', 'Variant'),
]
def __init__(self):
self.Key = QualifiedName()
self.Value = Variant()
self._freeze = True
def __str__(self):
return 'KeyValuePair(Key:{self.Key}, Value:{self.Value})'
__repr__ = __str__
class OpenSecureChannelResponse(FrozenClass):
"""
:ivar TypeId:
:vartype TypeId: NodeId
:ivar ResponseHeader:
:vartype ResponseHeader: ResponseHeader
:ivar Parameters:
:vartype Parameters: OpenSecureChannelResult
"""
types = [
('TypeId', 'NodeId'),
('ResponseHeader', 'ResponseHeader'),
('Parameters', 'OpenSecureChannelResult'),
]
def __init__(self):
self.TypeId = FourByteNodeId(ObjectIds.OpenSecureChannelResponse_Encoding_DefaultBinary)
self.ResponseHeader = ResponseHeader()
self.Parameters = OpenSecureChannelResult()
self._freeze = True
def __str__(self):
return 'OpenSecureChannelResponse(TypeId:{self.TypeId}, ResponseHeader:{self.ResponseHeader}, Parameters:{self.Parameters})'
__repr__ = __str__
class OpenSecureChannelResult(FrozenClass):
types = [
('ServerProtocolVersion', 'UInt32'),
('SecurityToken', 'ChannelSecurityToken'),
('ServerNonce', 'ByteString'),
]
def __init__(self):
self.ServerProtocolVersion = 0
self.SecurityToken = ChannelSecurityToken()
self.ServerNonce = None
self._freeze = True
def __str__(self):
return 'OpenSecureChannelResult(ServerProtocolVersion:{self.ServerProtocolVersion}, SecurityToken:{' \
'self.SecurityToken}, ServerNonce:{self.ServerNonce}) '
__repr__ = __str__
class ChannelSecurityToken(FrozenClass):
types = [
('ChannelId', 'UInt32'),
('TokenId', 'UInt32'),
('CreatedAt', 'DateTime'),
('RevisedLifetime', 'UInt32'),
]
def __init__(self):
self.ChannelId = 0
self.TokenId = 0
self.CreatedAt = datetime.datetime.utcnow()
self.RevisedLifetime = 0
self._freeze = True
def __str__(self):
return 'ChannelSecurityToken(ChannelId:{self.ChannelId}, TokenId:{self.TokenId}, CreatedAt:{self.CreatedAt}, ' \
'RevisedLifetime:{self.RevisedLifetime}) '
__repr__ = __str__
class SecurityTokenRequestType(IntEnum):
Issue = 0
Renew = 1
class ServiceFault(FrozenClass):
types = [
('TypeId', 'NodeId'),
('ResponseHeader', 'ResponseHeader'),
]
def __init__(self):
self.TypeId = FourByteNodeId(ObjectIds.ServiceFault_Encoding_DefaultBinary)
self.ResponseHeader = ResponseHeader()
self._freeze = True
def __str__(self):
return 'ServiceFault(TypeId:{self.TypeId}, ResponseHeader:{self.ResponseHeader})'
__repr__ = __str__
class RequestHeader(FrozenClass):
"""
:ivar AuthenticationToken:
:vartype AuthenticationToken: NodeId
:ivar Timestamp:
:vartype Timestamp: DateTime
:ivar RequestHandle:
:vartype RequestHandle: UInt32
:ivar ReturnDiagnostics:
:vartype ReturnDiagnostics: UInt32
:ivar AuditEntryId:
:vartype AuditEntryId: String
:ivar TimeoutHint:
:vartype TimeoutHint: UInt32
:ivar AdditionalHeader:
:vartype AdditionalHeader: ExtensionObject
"""
ua_types = [
('AuthenticationToken', 'NodeId'),
('Timestamp', 'DateTime'),
('RequestHandle', 'UInt32'),
('ReturnDiagnostics', 'UInt32'),
('AuditEntryId', 'String'),
('TimeoutHint', 'UInt32'),
('AdditionalHeader', 'ExtensionObject'),
]
def __init__(self):
self.AuthenticationToken = NodeId()
self.Timestamp = datetime.utcnow()
self.RequestHandle = 0
self.ReturnDiagnostics = 0
self.AuditEntryId = None
self.TimeoutHint = 0
self.AdditionalHeader = ExtensionObject()
self._freeze = True
def __str__(self):
return 'RequestHeader(AuthenticationToken:{self.AuthenticationToken}, Timestamp:{self.Timestamp}, RequestHandle:{self.RequestHandle}, ReturnDiagnostics:{self.ReturnDiagnostics}, AuditEntryId:{self.AuditEntryId}, TimeoutHint:{self.TimeoutHint}, AdditionalHeader:{self.AdditionalHeader})'
__repr__ = __str__
class ResponseHeader(FrozenClass):
types = [
('Timestamp', 'DateTime'),
('RequestHandle', 'UInt32'),
('ServiceResult', 'StatusCode'),
('ServiceDiagnostics', 'DiagnosticInfo'),
('StringTable', 'ListOfString'),
('AdditionalHeader', 'ExtensionObject'),
]
def __init__(self):
self.Timestamp = datetime.datetime.utcnow()
self.RequestHandle = 0
self.ServiceResult = StatusCode()
self.ServiceDiagnostics = DiagnosticInfo()
self.StringTable = []
self.AdditionalHeader = ExtensionObject()
self._freeze = True
def __str__(self):
return 'ResponseHeader(Timestamp:{self.Timestamp}, RequestHandle:{self.RequestHandle}, ServiceResult:{self.ServiceResult}, ServiceDiagnostics:{self.ServiceDiagnostics}, StringTable:{self.StringTable}, AdditionalHeader:{self.AdditionalHeader})'
__repr__ = __str__
class SignatureData(FrozenClass):
types = [
('Algorithm', 'String'),
('Signature', 'ByteString'),
]
def __init__(self):
self.Algorithm = None
self.Signature = None
self._freeze = True
def __str__(self):
return 'SignatureData(Algorithm:{self.Algorithm}, Signature:{self.Signature})'
__repr__ = __str__
class CreateSessionResult(FrozenClass):
types = [
('SessionId', 'NodeId'),
('AuthenticationToken', 'NodeId'),
('RevisedSessionTimeout', 'Double'),
('ServerNonce', 'ByteString'),
('ServerCertificate', 'ByteString'),
('ServerEndpoints', 'ListOfEndpointDescription'),
('ServerSoftwareCertificates', 'ListOfSignedSoftwareCertificate'),
('ServerSignature', 'SignatureData'),
('MaxRequestMessageSize', 'UInt32'),
]
def __init__(self):
self.SessionId = NodeId()
self.AuthenticationToken = NodeId()
self.RevisedSessionTimeout = 0
self.ServerNonce = None
self.ServerCertificate = None
self.ServerEndpoints = []
self.ServerSoftwareCertificates = []
self.ServerSignature = SignatureData()
self.MaxRequestMessageSize = 0
self._freeze = True
def __str__(self):
return 'CreateSessionResult(SessionId:{self.SessionId}, AuthenticationToken:{self.AuthenticationToken}, RevisedSessionTimeout:{self.RevisedSessionTimeout}, ServerNonce:{self.ServerNonce}, ServerCertificate:{self.ServerCertificate}, ServerEndpoints:{self.ServerEndpoints}, ServerSoftwareCertificates:{self.ServerSoftwareCertificates}, ServerSignature:{self.ServerSignature}, MaxRequestMessageSize:{self.MaxRequestMessageSize})'
__repr__ = __str__
class CreateSessionParameters(FrozenClass):
types = [
('ClientDescription', 'ApplicationDescription'),
('ServerUri', 'String'),
('EndpointUrl', 'String'),
('SessionName', 'String'),
('ClientNonce', 'ByteString'),
('ClientCertificate', 'ByteString'),
('RequestedSessionTimeout', 'Double'),
('MaxResponseMessageSize', 'UInt32'),
]
def __init__(self):
self.ClientDescription = ApplicationDescription()
self.ServerUri = None
self.EndpointUrl = None
self.SessionName = None
self.ClientNonce = None
self.ClientCertificate = None
self.RequestedSessionTimeout = 0
self.MaxResponseMessageSize = 0
self._freeze = True
def __str__(self):
return 'CreateSessionParameters(ClientDescription:{self.ClientDescription}, ServerUri:{self.ServerUri}, EndpointUrl:{self.EndpointUrl}, SessionName:{self.SessionName}, ClientNonce:{self.ClientNonce}, ClientCertificate:{self.ClientCertificate}, RequestedSessionTimeout:{self.RequestedSessionTimeout}, MaxResponseMessageSize:{self.MaxResponseMessageSize})'
__repr__ = __str__
class CreateSessionResponse(FrozenClass):
types = [
('TypeId', 'NodeId'),
('ResponseHeader', 'ResponseHeader'),
('Parameters', 'CreateSessionResult'),
]
def __init__(self):
self.TypeId = FourByteNodeId(ObjectIds.CreateSessionResponse_Encoding_DefaultBinary)
self.ResponseHeader = ResponseHeader()
self.Parameters = CreateSessionResult()
self._freeze = True
def __str__(self):
return 'CreateSessionResponse(TypeId:{self.TypeId}, ResponseHeader:{self.ResponseHeader}, Parameters:{self.Parameters})'
__repr__ = __str__
class DiagnosticInfo(FrozenClass):
switches = {
'SymbolicId': ('Encoding', 0),
'NamespaceURI': ('Encoding', 1),
'Locale': ('Encoding', 3),
'LocalizedText': ('Encoding', 2),
'AdditionalInfo': ('Encoding', 4),
'InnerStatusCode': ('Encoding', 5),
'InnerDiagnosticInfo': ('Encoding', 6),
}
types = [
('Encoding', 'Byte'),
('SymbolicId', 'Int32'),
('NamespaceURI', 'Int32'),
('Locale', 'Int32'),
('LocalizedText', 'Int32'),
('AdditionalInfo', 'String'),
('InnerStatusCode', 'StatusCode'),
('InnerDiagnosticInfo', 'DiagnosticInfo'),
]
def __init__(self):
self.Encoding = 0
self.SymbolicId = None
self.NamespaceURI = None
self.Locale = None
self.LocalizedText = None
self.AdditionalInfo = None
self.InnerStatusCode = None
self.InnerDiagnosticInfo = None
self._freeze = True
def __str__(self):
return 'DiagnosticInfo(Encoding:{self.Encoding}, SymbolicId:{self.SymbolicId}, NamespaceURI:{' \
'self.NamespaceURI}, Locale:{self.Locale}, LocalizedText:{self.LocalizedText}, AdditionalInfo:{' \
'self.AdditionalInfo}, InnerStatusCode:{self.InnerStatusCode}, InnerDiagnosticInfo:{' \
'self.InnerDiagnosticInfo}) '
__repr__ = __str__
class GenericAttributeValue(FrozenClass):
"""
:ivar AttributeId:
:vartype AttributeId: UInt32
:ivar Value:
:vartype Value: Variant
"""
ua_types = [
('AttributeId', 'UInt32'),
('Value', 'Variant'),
]
def __init__(self):
self.AttributeId = 0
self.Value = Variant()
self._freeze = True
def __str__(self):
return 'GenericAttributeValue(AttributeId:{self.AttributeId}, Value:{self.Value})'
__repr__ = __str__
class EnumValueType(FrozenClass):
"""
:ivar Value:
:vartype Value: Int64
:ivar DisplayName:
:vartype DisplayName: LocalizedText
:ivar Description:
:vartype Description: LocalizedText
"""
types = [
('Value', 'Int64'),
('DisplayName', 'LocalizedText'),
('Description', 'LocalizedText'),
]
def __init__(self):
self.Value = 0
self.DisplayName = LocalizedText()
self.Description = LocalizedText()
self._freeze = True
def __str__(self):
return 'EnumValueType(Value:{self.Value}, DisplayName:{self.DisplayName}, Description:{self.Description})'
__repr__ = __str__
class Argument(FrozenClass):
"""
:ivar Name:
:vartype Name: String
:ivar DataType:
:vartype DataType: NodeId
:ivar ValueRank:
:vartype ValueRank: Int32
:ivar ArrayDimensions:
:vartype ArrayDimensions: UInt32
:ivar Description:
:vartype Description: LocalizedText
"""
types = [
('Name', 'String'),
('DataType', 'NodeId'),
('ValueRank', 'Int32'),
('ArrayDimensions', 'ListOfUInt32'),
('Description', 'LocalizedText'),
]
def __init__(self):
self.Name = None
self.DataType = NodeId()
self.ValueRank = 0
self.ArrayDimensions = []
self.Description = LocalizedText()
self._freeze = True
def __str__(self):
return 'Argument(Name:{self.Name}, DataType:{self.DataType}, ValueRank:{self.ValueRank}, ArrayDimensions:{self.ArrayDimensions}, Description:{self.Description})'
__repr__ = __str__
class MethodAttributes(FrozenClass):
types = [
('SpecifiedAttributes', 'UInt32'),
('DisplayName', 'LocalizedText'),
('Description', 'LocalizedText'),
('WriteMask', 'UInt32'),
('UserWriteMask', 'UInt32'),
('Executable', 'Boolean'),
('UserExecutable', 'Boolean'),
]
def __init__(self):
self.SpecifiedAttributes = 0
self.DisplayName = LocalizedText()
self.Description = LocalizedText()
self.WriteMask = 0
self.UserWriteMask = 0
self.Executable = True
self.UserExecutable = True
self._freeze = True
def __str__(self):
return 'MethodAttributes(SpecifiedAttributes:{self.SpecifiedAttributes}, DisplayName:{self.DisplayName}, Description:{self.Description}, WriteMask:{self.WriteMask}, UserWriteMask:{self.UserWriteMask}, Executable:{self.Executable}, UserExecutable:{self.UserExecutable})'
__repr__ = __str__
extension_object_classes = {}
extension_object_ids = {}
class BrowseNextParameters(FrozenClass):
types = [
('ReleaseContinuationPoints', 'Boolean'),
('ContinuationPoints', 'ListOfByteString'),
]
def __init__(self):
self.ReleaseContinuationPoints = True
self.ContinuationPoints = []
self._freeze = True
def __str__(self):
return 'BrowseNextParameters(ReleaseContinuationPoints:{self.ReleaseContinuationPoints}, ContinuationPoints:{self.ContinuationPoints})'
__repr__ = __str__
class BrowseDescription(FrozenClass):
types = [
('NodeId', 'NodeId'),
('BrowseDirection', 'BrowseDirection'),
('ReferenceTypeId', 'NodeId'),
('IncludeSubtypes', 'Boolean'),
('NodeClassMask', 'UInt32'),
('ResultMask', 'UInt32'),
]
def __init__(self):
self.NodeId = NodeId()
self.BrowseDirection = BrowseDirection(0)
self.ReferenceTypeId = NodeId()
self.IncludeSubtypes = True
self.NodeClassMask = 0
self.ResultMask = 0
self._freeze = True
def __str__(self):
return 'BrowseDescription(NodeId:{self.NodeId}, BrowseDirection:{self.BrowseDirection}, ReferenceTypeId:{self.ReferenceTypeId}, IncludeSubtypes:{self.IncludeSubtypes}, NodeClassMask:{self.NodeClassMask}, ResultMask:{self.ResultMask})'
__repr__ = __str__
class BrowseParameters(FrozenClass):
types = [
('View', 'ViewDescription'),
('RequestedMaxReferencesPerNode', 'UInt32'),
('NodesToBrowse', 'ListOfBrowseDescription'),
]
def __init__(self):
self.View = ViewDescription()
self.RequestedMaxReferencesPerNode = 0
self.NodesToBrowse = []
self._freeze = True
def __str__(self):
return 'BrowseParameters(View:{self.View}, RequestedMaxReferencesPerNode:{self.RequestedMaxReferencesPerNode}, NodesToBrowse:{self.NodesToBrowse})'
__repr__ = __str__
class BrowseResult(FrozenClass):
types = [
('StatusCode', 'StatusCode'),
('ContinuationPoint', 'ByteString'),
('References', 'ListOfReferenceDescription'),
]
def __init__(self):
self.StatusCode = StatusCode()
self.ContinuationPoint = None
self.References = []
self._freeze = True
def __str__(self):
return 'BrowseResult(StatusCode:{self.StatusCode}, ContinuationPoint:{self.ContinuationPoint}, References:{self.References})'
__repr__ = __str__
class ViewDescription(FrozenClass):
types = [
('ViewId', 'NodeId'),
('Timestamp', 'DateTime'),
('ViewVersion', 'UInt32'),
]
def __init__(self):
self.ViewId = NodeId()
self.Timestamp = datetime.datetime.utcnow()
self.ViewVersion = 0
self._freeze = True
def __str__(self):
return 'ViewDescription(ViewId:{self.ViewId}, Timestamp:{self.Timestamp}, ViewVersion:{self.ViewVersion})'
__repr__ = __str__
# nid = FourByteNodeId(ObjectIds.NodeAttributes_Encoding_DefaultBinary)
# extension_object_classes[nid] = NodeAttributes
# extension_object_ids['NodeAttributes'] = nid
# nid = FourByteNodeId(ObjectIds.WriteValue_Encoding_DefaultBinary)
# extension_object_classes[nid] = WriteValue
# extension_object_ids['WriteValue'] = nid
# nid = FourByteNodeId(ObjectIds.EnumValueType_Encoding_DefaultBinary)
# extension_object_classes[nid] = EnumValueType
# extension_object_ids['EnumValueType'] = nid
# nid = FourByteNodeId(ObjectIds.VariableAttributes_Encoding_DefaultBinary)
# extension_object_classes[nid] = VariableAttributes
# extension_object_ids['VariableAttributes'] = nid
# nid = FourByteNodeId(ObjectIds.GenericAttributeValue_Encoding_DefaultBinary)
# extension_object_classes[nid] = GenericAttributeValue
# extension_object_ids['GenericAttributeValue'] = nid
# nid = FourByteNodeId(ObjectIds.GenericAttributes_Encoding_DefaultBinary)
# extension_object_classes[nid] = GenericAttributes
# extension_object_ids['GenericAttributes'] = nid
# nid = FourByteNodeId(ObjectIds.ServerStatusDataType_Encoding_DefaultBinary)
# extension_object_classes[nid] = ServerStatusDataType
# extension_object_ids['ServerStatusDataType'] = nid
from enum import IntEnum
class AttributeIds(IntEnum):
NodeId = 1
NodeClass = 2
BrowseName = 3
DisplayName = 4
Description = 5
WriteMask = 6
UserWriteMask = 7
IsAbstract = 8
Symmetric = 9
InverseName = 10
ContainsNoLoops = 11
EventNotifier = 12
Value = 13
DataType = 14
ValueRank = 15
ArrayDimensions = 16
AccessLevel = 17
UserAccessLevel = 18
MinimumSamplingInterval = 19
Historizing = 20
Executable = 21
UserExecutable = 22
DataTypeDefinition = 23
RolePermissions = 24
UserRolePermissions = 25
AccessRestrictions = 26
AccessLevelEx = 27
import sys
import struct
import logging
import uuid
from enum import IntEnum, Enum
import KL
from KL import hand_protocol, types
from common.utils import Buffer
if sys.version_info.major > 2:
unicode = str
logger = logging.getLogger('__name__')
def test_bit(data, offset):
mask = 1 << offset
return data & mask
def set_bit(data, offset):
mask = 1 << offset
return data | mask
class _Primitive1(object):
def __init__(self, fmt):
self._fmt = fmt
st = struct.Struct(fmt.format(1))
self.size = st.size
self.format = st.format
def pack(self, data):
return struct.pack(self.format, data)
def unpack(self, data):
return struct.unpack(self.format, data.read(self.size))[0]
def pack_array(self, data):
if data is None:
return Primitives.Int32.pack(-1)
if not isinstance(data, list):
logger.warning(
'binary.py > _Primitive1 > pack_array > data: {0} is not a instance of "list"!'.format(data))
return Primitives.Int32.pack(-1) # to prevent crashing while runtime
sizedata = Primitives.Int32.pack(len(data))
return sizedata + struct.pack(self._fmt.format(len(data)), *data)
def unpack_array(self, data, length):
if length == -1:
return None
if length == 0:
return ()
return struct.unpack(self._fmt.format(length), data.read(self.size * length))
class Primitives1(object):
SByte = _Primitive1("<{:d}b")
Int16 = _Primitive1("<{:d}h")
Int32 = _Primitive1("<{:d}i")
Int64 = _Primitive1("<{:d}q")
Byte = _Primitive1("<{:d}B")
Char = Byte
UInt16 = _Primitive1("<{:d}H")
UInt32 = _Primitive1("<{:d}I")
UInt64 = _Primitive1("<{:d}Q")
Boolean = _Primitive1("<{:d}?")
Double = _Primitive1("<{:d}d")
Float = _Primitive1("<{:d}f")
# class _DateTime(object):
# @staticmethod
# def pack(dt):
# epch = KL.datetime_to_win_epoch(dt)
# return Primitives.Int64.pack(epch)
#
# @staticmethod
# def unpack(data):
# epch = Primitives.Int64.unpack(data)
# return ua.win_epoch_to_datetime(epch)
class _Bytes(object):
@staticmethod
def pack(data):
if data is None:
return Primitives.Int32.pack(-1)
length = len(data)
return Primitives.Int32.pack(length) + data
@staticmethod
def unpack(data):
length = Primitives.Int32.unpack(data)
if length == -1:
return None
return data.read(length)
class _String(object):
@staticmethod
def pack(string):
if string is not None:
if sys.version_info.major > 2:
string = string.encode('utf-8')
else:
# we do not want this test to happen with python3
if isinstance(string, unicode):
string = string.encode('utf-8')
return _Bytes.pack(string)
@staticmethod
def unpack(data):
b = _Bytes.unpack(data)
if sys.version_info.major < 3:
# return unicode(b) #might be correct for python2 but would complicate tests for python3
return b
else:
if b is None:
return b
return b.decode("utf-8")
class _Null(object):
@staticmethod
def pack(data):
return b""
@staticmethod
def unpack(data):
return None
class _Guid(object):
@staticmethod
def pack(guid):
# convert python UUID 6 field format to OPC UA 4 field format
f1 = Primitives.UInt32.pack(guid.time_low)
f2 = Primitives.UInt16.pack(guid.time_mid)
f3 = Primitives.UInt16.pack(guid.time_hi_version)
f4a = Primitives.Byte.pack(guid.clock_seq_hi_variant)
f4b = Primitives.Byte.pack(guid.clock_seq_low)
f4c = struct.pack('>Q', guid.node)[2:8] # no primitive .pack available for 6 byte int
f4 = f4a + f4b + f4c
# concat byte fields
b = f1 + f2 + f3 + f4
return b
@staticmethod
def unpack(data):
# convert OPC UA 4 field format to python UUID bytes
f1 = struct.pack('>I', Primitives.UInt32.unpack(data))
f2 = struct.pack('>H', Primitives.UInt16.unpack(data))
f3 = struct.pack('>H', Primitives.UInt16.unpack(data))
f4 = data.read(8)
# concat byte fields
b = f1 + f2 + f3 + f4
return uuid.UUID(bytes=b)
class Primitives(Primitives1):
Null = _Null()
String = _String()
Bytes = _Bytes()
ByteString = _Bytes()
CharArray = _String()
# DateTime = _DateTime()
Guid = _Guid()
def header_to_binary(hdr):
b = []
b.append(struct.pack("<3ss", hdr.MessageType, hdr.ChunkType))
size = hdr.body_size + 8
if hdr.MessageType in (hand_protocol.MessageType.SecureOpen, hand_protocol.MessageType.SecureClose,
hand_protocol.MessageType.SecureMessage):
size += 4
b.append(Primitives.UInt32.pack(size))
if hdr.MessageType in (hand_protocol.MessageType.SecureOpen, hand_protocol.MessageType.SecureClose,
hand_protocol.MessageType.SecureMessage):
b.append(Primitives.UInt32.pack(hdr.ChannelId))
return b"".join(b)
def struct_to_binary(obj):
packet = []
has_switch = hasattr(obj, "switches")
if has_switch:
for name, switch in obj.switches.items():
member = getattr(obj, name)
container_name, idx = switch
if member is not None:
container_val = getattr(obj, container_name)
container_val = container_val | 1 << idx
setattr(obj, container_name, container_val)
for name, utype in obj.types:
val = getattr(obj, name)
if utype.startswith("ListOf"):
packet.append(list_to_binary(utype[6:], val))
else:
if has_switch and val is None and name in obj.switches:
pass
else:
packet.append(to_binary(utype, val))
return b''.join(packet)
def to_binary(utype, val):
if utype.startswith("ListOf"):
# if isinstance(val, (list, tuple)):
return list_to_binary(utype[6:], val)
elif isinstance(utype, (str, unicode)) and hasattr(types.VariantType, utype):
vtype = getattr(types.VariantType, utype)
return pack_utype(vtype, val)
elif isinstance(utype, (str, unicode)) and hasattr(Primitives, utype):
return getattr(Primitives, utype).pack(val)
elif isinstance(val, (IntEnum, Enum)):
return Primitives.UInt32.pack(val.value)
elif isinstance(val, types.NodeId):
return nodeid_to_binary(val)
elif isinstance(val, types.Variant):
return variant_to_binary(val)
elif hasattr(val, "ua_types"):
return struct_to_binary(val)
else:
raise Exception("No known way to pack {} of type {} to ua binary".format(val, utype))
def nodeid_to_binary(nodeid):
data = None
if nodeid.NodeIdType == types.NodeIdType.TwoByte:
return struct.pack("<BB", nodeid.NodeIdType.value, nodeid.Identifier)
elif nodeid.NodeIdType == types.NodeIdType.FourByte:
return struct.pack("<BBH", nodeid.NodeIdType.value, nodeid.NamespaceIndex, nodeid.Identifier)
elif nodeid.NodeIdType == types.NodeIdType.Numeric:
data = struct.pack("<BHI", nodeid.NodeIdType.value, nodeid.NamespaceIndex, nodeid.Identifier)
elif nodeid.NodeIdType == types.NodeIdType.String:
data = struct.pack("<BH", nodeid.NodeIdType.value, nodeid.NamespaceIndex) + \
Primitives.String.pack(nodeid.Identifier)
elif nodeid.NodeIdType == types.NodeIdType.ByteString:
data = struct.pack("<BH", nodeid.NodeIdType.value, nodeid.NamespaceIndex) + \
Primitives.Bytes.pack(nodeid.Identifier)
elif nodeid.NodeIdType == types.NodeIdType.Guid:
data = struct.pack("<BH", nodeid.NodeIdType.value, nodeid.NamespaceIndex) + \
Primitives.Guid.pack(nodeid.Identifier)
else:
raise Exception("Unknown NodeIdType: {} for NodeId: {}".format(nodeid.NodeIdType, nodeid))
# Add NamespaceUri and ServerIndex in case we have an ExpandedNodeId
if nodeid.NamespaceUri:
data = bytearray(data)
data[0] = set_bit(data[0], 7)
data.extend(Primitives.String.pack(nodeid.NamespaceUri))
if nodeid.ServerIndex:
if not isinstance(data, bytearray):
data = bytearray(data)
data[0] = set_bit(data[0], 6)
data.extend(Primitives.UInt32.pack(nodeid.ServerIndex))
return data
def variant_to_binary(var):
b = []
encoding = var.VariantType.value & 0b111111
if var.is_array or isinstance(var.Value, (list, tuple)):
var.is_array = True
encoding = set_bit(encoding, 7)
if var.Dimensions is not None:
encoding = set_bit(encoding, 6)
b.append(Primitives.Byte.pack(encoding))
b.append(pack_utype_array(var.VariantType, types.flatten(var.Value)))
if var.Dimensions is not None:
b.append(pack_utype_array(types.VariantType.Int32, var.Dimensions))
else:
b.append(Primitives.Byte.pack(encoding))
b.append(pack_utype_array(var.VariantType, var.Value))
return b"".join(b)
def pack_utype_array(vtype, array):
if hasattr(Primitives1, vtype.name):
dataType = getattr(Primitives1, vtype.name)
return dataType.pack_array(array)
if array is None:
return b'\xff\xff\xff\xff'
length = len(array)
b = [pack_utype(vtype, val) for val in array]
b.insert(0, Primitives.Int32.pack(length))
return b"".join(b)
def pack_utype(vtype, value):
if hasattr(Primitives, vtype.name):
return getattr(Primitives, vtype.name).pack(value)
elif vtype.value > 25:
return Primitives.Bytes.pack(value)
elif vtype == types.VariantType.ExtensionObject:
return extensionobject_to_binary(value)
elif vtype in (types.VariantType.NodeId, types.VariantType.ExpandedNodeId):
return nodeid_to_binary(value)
elif vtype == types.VariantType.Variant:
return variant_to_binary(value)
else:
return struct_to_binary(value)
def extensionobject_to_binary(obj):
"""
Convert Python object to binary-coded ExtensionObject.
If obj is None, convert to empty ExtensionObject (TypeId=0, no Body).
Returns a binary string
"""
if isinstance(obj, types.ExtensionObject):
return struct_to_binary(obj)
if obj is None:
TypeId = types.NodeId()
Encoding = 0
Body = None
else:
TypeId = types.extension_object_ids[obj.__class__.__name__]
Encoding = 0x01
Body = struct_to_binary(obj)
packet = []
packet.append(nodeid_to_binary(TypeId))
packet.append(Primitives.Byte.pack(Encoding))
if Body:
packet.append(Primitives.Bytes.pack(Body))
return b''.join(packet)
def list_to_binary(utype, val):
if val is None:
return Primitives.Int32.pack(-1)
if hasattr(Primitives1, utype):
dataType = getattr(Primitives1, utype)
return dataType.pack_array(val)
datasize = Primitives.Int32.pack(len(val))
pack = [to_binary(utype, el) for el in val]
pack.insert(0, datasize)
return b''.join(pack)
def struct_from_binary(objtype, data):
"""
unpack an ua struct. Arguments are an objtype as Python class or string
"""
if isinstance(objtype, (unicode, str)):
objtype = getattr(KL, objtype)
if issubclass(objtype, Enum):
return objtype(Primitives.UInt32.unpack(data))
obj = objtype()
for name, utype in obj.types:
# if our member has a swtich and it is not set we skip it
if hasattr(obj, "ua_switches") and name in obj.switches:
container_name, idx = obj.switches[name]
val = getattr(obj, container_name)
if not test_bit(val, idx):
continue
val = from_binary(utype, data)
setattr(obj, name, val)
return obj
def from_binary(utype, data):
"""
unpack data given an uatype as a string or a python class having a ua_types memeber
"""
if isinstance(utype, (str, unicode)) and utype.startswith("ListOf"):
type = utype[6:]
if hasattr(types.VariantType, type):
vtype = getattr(types.VariantType, utype)
return unpack_utype_array(vtype, data)
size = Primitives.Int32.unpack(data)
return [from_binary(utype, data) for _ in range(size)]
elif isinstance(utype, (str, unicode)) and hasattr(types.VariantType, utype):
vtype = getattr(types.VariantType, utype)
return unpack_utype(vtype, data)
elif isinstance(utype, (str, unicode)) and hasattr(Primitives, utype):
return getattr(Primitives, utype).unpack(data)
else:
return struct_from_binary(utype, data)
def unpack_utype_array(vtype, data):
length = Primitives.Int32.unpack(data)
if length == -1:
return None
elif hasattr(Primitives1, vtype.name):
dataType = getattr(Primitives1, vtype.name)
# Remark: works without tuple conversion to list.
return list(dataType.unpack_array(data, length))
else:
# Revert to slow serial unpacking.
return [unpack_utype(vtype, data) for _ in range(length)]
def unpack_utype(vtype, data):
if hasattr(Primitives, vtype.name):
st = getattr(Primitives, vtype.name)
return st.unpack(data)
elif vtype.value > 25:
return Primitives.Bytes.unpack(data)
elif vtype == types.VariantType.ExtensionObject:
return extensionobject_from_binary(data)
elif vtype in (types.VariantType.NodeId, types.VariantType.ExpandedNodeId):
return nodeid_from_binary(data)
elif vtype == types.VariantType.Variant:
return variant_from_binary(data)
else:
if hasattr(KL, vtype.name):
klass = getattr(KL, vtype.name)
return struct_from_binary(klass, data)
else:
raise Exception("Cannot unpack unknown variant type {0!s}".format(vtype))
def extensionobject_from_binary(data):
typeid = nodeid_from_binary(data)
Encoding = ord(data.read(1))
body = None
if Encoding & (1 << 0):
length = Primitives.Int32.unpack(data)
if length < 1:
body = Buffer(b"")
else:
body = data.copy(length)
data.skip(length)
if typeid.Identifier == 0:
return None
elif typeid in types.extension_object_classes:
klass = types.extension_object_classes[typeid]
if body is None:
raise Exception("parsing ExtensionObject {0} without data".format(klass.__name__))
return from_binary(klass, body)
else:
e = types.ExtensionObject()
e.TypeId = typeid
e.Encoding = Encoding
if body is not None:
e.Body = body.read(len(body))
return e
def nodeid_from_binary(data):
nid = types.NodeId()
encoding = ord(data.read(1))
nid.NodeIdType = types.NodeIdType(encoding & 0b00111111)
if nid.NodeIdType == types.NodeIdType.TwoByte:
nid.Identifier = ord(data.read(1))
elif nid.NodeIdType == types.NodeIdType.FourByte:
nid.NamespaceIndex, nid.Identifier = struct.unpack("<BH", data.read(3))
elif nid.NodeIdType == types.NodeIdType.Numeric:
nid.NamespaceIndex, nid.Identifier = struct.unpack("<HI", data.read(6))
elif nid.NodeIdType == types.NodeIdType.String:
nid.NamespaceIndex = Primitives.UInt16.unpack(data)
nid.Identifier = Primitives.String.unpack(data)
elif nid.NodeIdType == types.NodeIdType.ByteString:
nid.NamespaceIndex = Primitives.UInt16.unpack(data)
nid.Identifier = Primitives.Bytes.unpack(data)
elif nid.NodeIdType == types.NodeIdType.Guid:
nid.NamespaceIndex = Primitives.UInt16.unpack(data)
nid.Identifier = Primitives.Guid.unpack(data)
else:
raise Exception("Unknown NodeId encoding: " + str(nid.NodeIdType))
if test_bit(encoding, 7):
nid.NamespaceUri = Primitives.String.unpack(data)
if test_bit(encoding, 6):
nid.ServerIndex = Primitives.UInt32.unpack(data)
return nid
def variant_from_binary(data):
dimensions = None
array = False
encoding = ord(data.read(1))
int_type = encoding & 0b00111111
vtype = types.datatype_to_varianttype(int_type)
if test_bit(encoding, 7):
value = unpack_utype_array(vtype, data)
array = True
else:
value = unpack_utype(vtype, data)
if test_bit(encoding, 6):
dimensions = unpack_utype_array(types.VariantType.Int32, data)
value = _reshape(value, dimensions)
return types.Variant(value, vtype, dimensions, is_array=array)
def _reshape(flat, dims):
subdims = dims[1:]
subsize = 1
for i in subdims:
if i == 0:
i = 1
subsize *= i
while dims[0] * subsize > len(flat):
flat.append([])
if not subdims or subdims == [0]:
return flat
return [_reshape(flat[i:i + subsize], subdims) for i in range(0, len(flat), subsize)]
This source diff could not be displayed because it is too large. You can view the blob instead.
from KL import application_protocol as auto, application_protocol
from KL.types import AccessLevel, FrozenClass, StatusCode
import struct
class Hello(FrozenClass):
types = (('ProtocolVersion', 'UInt32'), ('ReceiveBufferSize', 'UInt32'), ('SendBufferSize', 'UInt32'),
('MaxMessageSize', 'UInt32'), ('MaxChunkCount', 'UInt32'), ('EndpointUrl', 'String'),)
def __init__(self):
self.ProtocolVersion = 0
self.ReceiveBufferSize = 2 ** 31 - 1
self.SendBufferSize = 2 ** 31 - 1
self.MaxMessageSize = 0 # No limits
self.MaxChunkCount = 0 # No limits
self.EndpointUrl = ""
self._freeze = True
class MessageType(object):
Invalid = b"INV" # FIXME: check value
Hello = b"HEL"
Acknowledge = b"ACK"
Error = b"ERR"
SecureOpen = b"OPN"
SecureClose = b"CLO"
SecureMessage = b"MSG"
class ChunkType(object):
Invalid = b"0" # FIXME check
Single = b"F"
Intermediate = b"C"
Abort = b"A" # when an error occurred and the Message is aborted (body is ErrorMessage)
class Header(FrozenClass):
def __init__(self, msgType=None, chunkType=None, channelid=0):
self.MessageType = msgType
self.ChunkType = chunkType
self.ChannelId = channelid
self.body_size = 0
self.packet_size = 0
self._freeze = True
def add_size(self, size):
self.body_size += size
@staticmethod
def max_size():
return struct.calcsize("<3scII")
def __str__(self):
return "Header(type:{0}, chunk_type:{1}, body_size:{2}, channel:{3})".format(
self.MessageType, self.ChunkType, self.body_size, self.ChannelId)
__repr__ = __str__
class ErrorMessage(FrozenClass):
types = (('Error', 'StatusCode'), ('Reason', 'String'),)
def __init__(self):
self.Error = StatusCode()
self.Reason = ""
self._freeze = True
def __str__(self):
return "MessageAbort(error:{0}, reason:{1})".format(self.Error, self.Reason)
__repr__ = __str__
class Acknowledge(FrozenClass):
types = [
("ProtocolVersion", "UInt32"),
("ReceiveBufferSize", "UInt32"),
("SendBufferSize", "UInt32"),
("MaxMessageSize", "UInt32"),
("MaxChunkCount", "UInt32"),
]
def __init__(self):
self.ProtocolVersion = 0
self.ReceiveBufferSize = 65536
self.SendBufferSize = 65536
self.MaxMessageSize = 0 # No limits
self.MaxChunkCount = 0 # No limits
self._freeze = True
class AsymmetricAlgorithmHeader(FrozenClass):
types = [
("SecurityPolicyURI", "String"),
("SenderCertificate", "ByteString"),
("ReceiverCertificateThumbPrint", "ByteString"),
]
def __init__(self):
self.SecurityPolicyURI = "http://opcfoundation.org/UA/SecurityPolicy#None"
self.SenderCertificate = None
self.ReceiverCertificateThumbPrint = None
self._freeze = True
def __str__(self):
size1 = len(self.SenderCertificate) if self.SenderCertificate is not None else None
size2 = len(self.ReceiverCertificateThumbPrint) if self.ReceiverCertificateThumbPrint is not None else None
return "{0}(SecurityPolicy:{1}, certificatesize:{2}, receiverCertificatesize:{3} )".format(
self.__class__.__name__, self.SecurityPolicyURI, size1, size2)
__repr__ = __str__
class SymmetricAlgorithmHeader(FrozenClass):
types = [
("TokenId", "UInt32"),
]
def __init__(self):
self.TokenId = 0
self._freeze = True
# @staticmethod
# def max_size():
# return struct.calcsize("<I")
def __str__(self):
return "{0}(TokenId:{1} )".format(self.__class__.__name__, self.TokenId)
__repr__ = __str__
class SequenceHeader(FrozenClass):
types = [
("SequenceNumber", "UInt32"),
("RequestId", "UInt32"),
]
def __init__(self):
self.SequenceNumber = None
self.RequestId = None
self._freeze = True
# @staticmethod
# def max_size():
# return struct.calcsize("<II")
def __str__(self):
return "{0}(SequenceNumber:{1}, RequestId:{2} )".format(self.__class__.__name__, self.SequenceNumber,
self.RequestId)
__repr__ = __str__
class CryptographyNone:
"""
Base class for symmetric/asymmetric cryprography
"""
def __init__(self):
pass
def plain_block_size(self):
"""
Size of plain text block for block cipher.
"""
return 1
def encrypted_block_size(self):
"""
Size of encrypted text block for block cipher.
"""
return 1
def padding(self, size):
"""
Create padding for a block of given size.
plain_size = size + len(padding) + signature_size()
plain_size = N * plain_block_size()
"""
return b''
def min_padding_size(self):
return 0
def signature_size(self):
return 0
def signature(self, data):
return b''
def encrypt(self, data):
return data
def decrypt(self, data):
return data
def vsignature_size(self):
return 0
def verify(self, data, signature):
"""
Verify signature and raise exception if signature is invalid
"""
pass
def remove_padding(self, data):
return data
class SecurityPolicy(object):
"""
Base class for security policy
"""
URI = "http://opcfoundation.org/UA/SecurityPolicy#None"
AsymmetricSignatureURI = ""
signature_key_size = 0
symmetric_key_size = 0
def __init__(self):
self.asymmetric_cryptography = CryptographyNone()
self.symmetric_cryptography = CryptographyNone()
self.Mode = auto.MessageSecurityMode.None_
self.server_certificate = None
self.client_certificate = None
def make_local_symmetric_key(self, secret, seed):
pass
def make_remote_symmetric_key(self, secret, seed):
pass
class SecurityPolicyFactory(object):
"""
Helper class for creating server-side SecurityPolicy.
Server has one certificate and private key, but needs a separate
SecurityPolicy for every client and client's certificate
"""
def __init__(self, cls=SecurityPolicy, mode= application_protocol.MessageSecurityMode.None_, certificate=None, private_key=None):
self.cls = cls
self.mode = mode
self.certificate = certificate
self.private_key = private_key
def matches(self, uri, mode=None):
return self.cls.URI == uri and (mode is None or self.mode == mode)
def create(self, peer_certificate):
if self.cls is SecurityPolicy:
return self.cls()
else:
return self.cls(peer_certificate, self.certificate, self.private_key, self.mode)
class Message(object):
def __init__(self, chunks):
self._chunks = chunks
def __str__(self):
return 'Message(' + str(self._chunks) + ')'
__repr__ = __str__
def message_type(self):
return self._chunks[0].MessageHeader.MessageType
def request_id(self):
return self._chunks[0].SequenceHeader.RequestId
def SequenceHeader(self):
return self._chunks[0].SequenceHeader
def SecurityHeader(self):
return self._chunks[0].SecurityHeader
# def body(self):
# body = b"".join([c.Body for c in self._chunks])
# return utils.Buffer(body)
ana = auto.NodeAttributesMask
class ReferenceTypeAttributes(auto.ReferenceTypeAttributes):
def __init__(self):
auto.ReferenceTypeAttributes.__init__(self)
self.SpecifiedAttributes = ana.DisplayName | ana.Description | ana.WriteMask | ana.UserWriteMask | ana.IsAbstract | ana.Symmetric | ana.InverseName
print("1", self.SpecifiedAttributes)
class VariableAttributes(auto.VariableAttributes):
def __init__(self):
auto.VariableAttributes.__init__(self)
self.SpecifiedAttributes = ana.DisplayName | ana.Description | ana.WriteMask | ana.UserWriteMask | ana.Value | ana.DataType | ana.ValueRank | ana.ArrayDimensions | ana.AccessLevel | ana.UserAccessLevel | ana.MinimumSamplingInterval | ana.Historizing
print("2", self.SpecifiedAttributes)
self.Historizing = False
self.AccessLevel = AccessLevel.CurrentRead.mask
self.UserAccessLevel = AccessLevel.CurrentRead.mask
class DataTypeAttributes(auto.DataTypeAttributes):
def __init__(self):
auto.DataTypeAttributes.__init__(self)
self.SpecifiedAttributes = ana.DisplayName | ana.Description | ana.WriteMask | ana.UserWriteMask | ana.IsAbstract
print("3", self.SpecifiedAttributes)
class VariableTypeAttributes(auto.VariableTypeAttributes):
def __init__(self):
auto.VariableTypeAttributes.__init__(self)
self.SpecifiedAttributes = ana.DisplayName | ana.Description | ana.WriteMask | ana.UserWriteMask | ana.Value | ana.DataType | ana.ValueRank | ana.ArrayDimensions | ana.IsAbstract
print("4", self.SpecifiedAttributes)
class ObjectTypeAttributes(auto.ObjectTypeAttributes):
def __init__(self):
auto.ObjectTypeAttributes.__init__(self)
self.SpecifiedAttributes = ana.DisplayName | ana.Description | ana.WriteMask | ana.UserWriteMask | ana.IsAbstract
print("5", self.SpecifiedAttributes)
class ObjectAttributes(auto.ObjectAttributes):
def __init__(self):
auto.ObjectAttributes.__init__(self)
self.SpecifiedAttributes = ana.DisplayName | ana.Description | ana.WriteMask | ana.UserWriteMask | ana.EventNotifier
print("6", self.SpecifiedAttributes)
class MethodAttributes(auto.MethodAttributes):
def __init__(self):
auto.MethodAttributes.__init__(self)
self.SpecifiedAttributes = ana.DisplayName | ana.Description | ana.WriteMask | ana.UserWriteMask | ana.Executable | ana.UserExecutable
print("8", self.SpecifiedAttributes)
class ViewAttributes(auto.ViewAttributes):
def __init__(self):
auto.ViewAttributes.__init__(self)
self.SpecifiedAttributes = ana.DisplayName | ana.Description | ana.WriteMask | ana.UserWriteMask | ana.ContainsNoLoops | ana.EventNotifier
print("9", self.SpecifiedAttributes)
class Argument(auto.Argument):
def __init__(self):
auto.Argument.__init__(self)
self.ValueRank = -2
class XmlElement(FrozenClass):
'''
An XML element encoded as a UTF-8 string.
:ivar Value:
:vartype Value: String
'''
types = [
('Value', 'String'),
]
def __init__(self, xml=""):
self.Value = xml
self._freeze = True
def __str__(self):
return 'XmlElement(' + 'Value:' + str(self.Value) + ')'
__repr__ = __str__
def __eq__(self, el):
return isinstance(el, XmlElement) and self.Value == el.Value
from KL.constants import ObjectIds
from common.node import Node
class Shortcuts(object):
"""
This object contains Node objects to some commonly used nodes
"""
def __init__(self, server):
self.root = Node(server, ObjectIds.RootFolder)
self.objects = Node(server, ObjectIds.ObjectsFolder)
self.server = Node(server, ObjectIds.Server)
self.types = Node(server, ObjectIds.TypesFolder)
self.base_object_type = Node(server, ObjectIds.BaseObjectType)
self.base_data_type = Node(server, ObjectIds.BaseDataType)
self.base_event_type = Node(server, ObjectIds.BaseEventType)
self.base_variable_type = Node(server, ObjectIds.BaseVariableType)
self.folder_type = Node(server, ObjectIds.FolderType)
self.enum_data_type = Node(server, ObjectIds.Enumeration)
self.types = Node(server, ObjectIds.TypesFolder)
self.data_types = Node(server, ObjectIds.DataTypesFolder)
self.event_types = Node(server, ObjectIds.EventTypesFolder)
self.reference_types = Node(server, ObjectIds.ReferenceTypesFolder)
self.variable_types = Node(server, ObjectIds.VariableTypesFolder)
self.object_types = Node(server, ObjectIds.ObjectTypesFolder)
self.namespace_array = Node(server, ObjectIds.Server_NamespaceArray)
self.opc_binary = Node(server, ObjectIds.OPCBinarySchema_TypeSystem)
self.base_structure_type = Node(server, ObjectIds.Structure)
\ No newline at end of file
class StatusCodes:
Good = 0
Uncertain = 0x40000000
Bad = 0x80000000
BadUnexpectedError = 0x80010000
BadInternalError = 0x80020000
BadOutOfMemory = 0x80030000
BadResourceUnavailable = 0x80040000
BadCommunicationError = 0x80050000
BadEncodingError = 0x80060000
BadDecodingError = 0x80070000
BadEncodingLimitsExceeded = 0x80080000
BadRequestTooLarge = 0x80B80000
BadResponseTooLarge = 0x80B90000
BadUnknownResponse = 0x80090000
BadTimeout = 0x800A0000
BadServiceUnsupported = 0x800B0000
BadShutdown = 0x800C0000
BadServerNotConnected = 0x800D0000
BadServerHalted = 0x800E0000
BadNothingToDo = 0x800F0000
BadTooManyOperations = 0x80100000
BadTooManyMonitoredItems = 0x80DB0000
BadDataTypeIdUnknown = 0x80110000
BadCertificateInvalid = 0x80120000
BadSecurityChecksFailed = 0x80130000
BadCertificatePolicyCheckFailed = 0x81140000
BadCertificateTimeInvalid = 0x80140000
BadCertificateIssuerTimeInvalid = 0x80150000
BadCertificateHostNameInvalid = 0x80160000
BadCertificateUriInvalid = 0x80170000
BadCertificateUseNotAllowed = 0x80180000
BadCertificateIssuerUseNotAllowed = 0x80190000
BadCertificateUntrusted = 0x801A0000
BadCertificateRevocationUnknown = 0x801B0000
BadCertificateIssuerRevocationUnknown = 0x801C0000
BadCertificateRevoked = 0x801D0000
BadCertificateIssuerRevoked = 0x801E0000
BadCertificateChainIncomplete = 0x810D0000
BadUserAccessDenied = 0x801F0000
BadIdentityTokenInvalid = 0x80200000
BadIdentityTokenRejected = 0x80210000
BadSecureChannelIdInvalid = 0x80220000
BadInvalidTimestamp = 0x80230000
BadNonceInvalid = 0x80240000
BadSessionIdInvalid = 0x80250000
BadSessionClosed = 0x80260000
BadSessionNotActivated = 0x80270000
BadSubscriptionIdInvalid = 0x80280000
BadRequestHeaderInvalid = 0x802A0000
BadTimestampsToReturnInvalid = 0x802B0000
BadRequestCancelledByClient = 0x802C0000
BadTooManyArguments = 0x80E50000
BadLicenseExpired = 0x810E0000
BadLicenseLimitsExceeded = 0x810F0000
BadLicenseNotAvailable = 0x81100000
GoodSubscriptionTransferred = 0x002D0000
GoodCompletesAsynchronously = 0x002E0000
GoodOverload = 0x002F0000
GoodClamped = 0x00300000
BadNoCommunication = 0x80310000
BadWaitingForInitialData = 0x80320000
BadNodeIdInvalid = 0x80330000
BadNodeIdUnknown = 0x80340000
BadAttributeIdInvalid = 0x80350000
BadIndexRangeInvalid = 0x80360000
BadIndexRangeNoData = 0x80370000
BadDataEncodingInvalid = 0x80380000
BadDataEncodingUnsupported = 0x80390000
BadNotReadable = 0x803A0000
BadNotWritable = 0x803B0000
BadOutOfRange = 0x803C0000
BadNotSupported = 0x803D0000
BadNotFound = 0x803E0000
BadObjectDeleted = 0x803F0000
BadNotImplemented = 0x80400000
BadMonitoringModeInvalid = 0x80410000
BadMonitoredItemIdInvalid = 0x80420000
BadMonitoredItemFilterInvalid = 0x80430000
BadMonitoredItemFilterUnsupported = 0x80440000
BadFilterNotAllowed = 0x80450000
BadStructureMissing = 0x80460000
BadEventFilterInvalid = 0x80470000
BadContentFilterInvalid = 0x80480000
BadFilterOperatorInvalid = 0x80C10000
BadFilterOperatorUnsupported = 0x80C20000
BadFilterOperandCountMismatch = 0x80C30000
BadFilterOperandInvalid = 0x80490000
BadFilterElementInvalid = 0x80C40000
BadFilterLiteralInvalid = 0x80C50000
BadContinuationPointInvalid = 0x804A0000
BadNoContinuationPoints = 0x804B0000
BadReferenceTypeIdInvalid = 0x804C0000
BadBrowseDirectionInvalid = 0x804D0000
BadNodeNotInView = 0x804E0000
BadNumericOverflow = 0x81120000
BadServerUriInvalid = 0x804F0000
BadServerNameMissing = 0x80500000
BadDiscoveryUrlMissing = 0x80510000
BadSempahoreFileMissing = 0x80520000
BadRequestTypeInvalid = 0x80530000
BadSecurityModeRejected = 0x80540000
BadSecurityPolicyRejected = 0x80550000
BadTooManySessions = 0x80560000
BadUserSignatureInvalid = 0x80570000
BadApplicationSignatureInvalid = 0x80580000
BadNoValidCertificates = 0x80590000
BadIdentityChangeNotSupported = 0x80C60000
BadRequestCancelledByRequest = 0x805A0000
BadParentNodeIdInvalid = 0x805B0000
BadReferenceNotAllowed = 0x805C0000
BadNodeIdRejected = 0x805D0000
BadNodeIdExists = 0x805E0000
BadNodeClassInvalid = 0x805F0000
BadBrowseNameInvalid = 0x80600000
BadBrowseNameDuplicated = 0x80610000
BadNodeAttributesInvalid = 0x80620000
BadTypeDefinitionInvalid = 0x80630000
BadSourceNodeIdInvalid = 0x80640000
BadTargetNodeIdInvalid = 0x80650000
BadDuplicateReferenceNotAllowed = 0x80660000
BadInvalidSelfReference = 0x80670000
BadReferenceLocalOnly = 0x80680000
BadNoDeleteRights = 0x80690000
UncertainReferenceNotDeleted = 0x40BC0000
BadServerIndexInvalid = 0x806A0000
BadViewIdUnknown = 0x806B0000
BadViewTimestampInvalid = 0x80C90000
BadViewParameterMismatch = 0x80CA0000
BadViewVersionInvalid = 0x80CB0000
UncertainNotAllNodesAvailable = 0x40C00000
GoodResultsMayBeIncomplete = 0x00BA0000
BadNotTypeDefinition = 0x80C80000
UncertainReferenceOutOfServer = 0x406C0000
BadTooManyMatches = 0x806D0000
BadQueryTooComplex = 0x806E0000
BadNoMatch = 0x806F0000
BadMaxAgeInvalid = 0x80700000
BadSecurityModeInsufficient = 0x80E60000
BadHistoryOperationInvalid = 0x80710000
BadHistoryOperationUnsupported = 0x80720000
BadInvalidTimestampArgument = 0x80BD0000
BadWriteNotSupported = 0x80730000
BadTypeMismatch = 0x80740000
BadMethodInvalid = 0x80750000
BadArgumentsMissing = 0x80760000
BadNotExecutable = 0x81110000
BadTooManySubscriptions = 0x80770000
BadTooManyPublishRequests = 0x80780000
BadNoSubscription = 0x80790000
BadSequenceNumberUnknown = 0x807A0000
BadMessageNotAvailable = 0x807B0000
BadInsufficientClientProfile = 0x807C0000
BadStateNotActive = 0x80BF0000
BadAlreadyExists = 0x81150000
BadTcpServerTooBusy = 0x807D0000
BadTcpMessageTypeInvalid = 0x807E0000
BadTcpSecureChannelUnknown = 0x807F0000
BadTcpMessageTooLarge = 0x80800000
BadTcpNotEnoughResources = 0x80810000
BadTcpInternalError = 0x80820000
BadTcpEndpointUrlInvalid = 0x80830000
BadRequestInterrupted = 0x80840000
BadRequestTimeout = 0x80850000
BadSecureChannelClosed = 0x80860000
BadSecureChannelTokenUnknown = 0x80870000
BadSequenceNumberInvalid = 0x80880000
BadProtocolVersionUnsupported = 0x80BE0000
BadConfigurationError = 0x80890000
BadNotConnected = 0x808A0000
BadDeviceFailure = 0x808B0000
BadSensorFailure = 0x808C0000
BadOutOfService = 0x808D0000
BadDeadbandFilterInvalid = 0x808E0000
UncertainNoCommunicationLastUsableValue = 0x408F0000
UncertainLastUsableValue = 0x40900000
UncertainSubstituteValue = 0x40910000
UncertainInitialValue = 0x40920000
UncertainSensorNotAccurate = 0x40930000
UncertainEngineeringUnitsExceeded = 0x40940000
UncertainSubNormal = 0x40950000
GoodLocalOverride = 0x00960000
BadRefreshInProgress = 0x80970000
BadConditionAlreadyDisabled = 0x80980000
BadConditionAlreadyEnabled = 0x80CC0000
BadConditionDisabled = 0x80990000
BadEventIdUnknown = 0x809A0000
BadEventNotAcknowledgeable = 0x80BB0000
BadDialogNotActive = 0x80CD0000
BadDialogResponseInvalid = 0x80CE0000
BadConditionBranchAlreadyAcked = 0x80CF0000
BadConditionBranchAlreadyConfirmed = 0x80D00000
BadConditionAlreadyShelved = 0x80D10000
BadConditionNotShelved = 0x80D20000
BadShelvingTimeOutOfRange = 0x80D30000
BadNoData = 0x809B0000
BadBoundNotFound = 0x80D70000
BadBoundNotSupported = 0x80D80000
BadDataLost = 0x809D0000
BadDataUnavailable = 0x809E0000
BadEntryExists = 0x809F0000
BadNoEntryExists = 0x80A00000
BadTimestampNotSupported = 0x80A10000
GoodEntryInserted = 0x00A20000
GoodEntryReplaced = 0x00A30000
UncertainDataSubNormal = 0x40A40000
GoodNoData = 0x00A50000
GoodMoreData = 0x00A60000
BadAggregateListMismatch = 0x80D40000
BadAggregateNotSupported = 0x80D50000
BadAggregateInvalidInputs = 0x80D60000
BadAggregateConfigurationRejected = 0x80DA0000
GoodDataIgnored = 0x00D90000
BadRequestNotAllowed = 0x80E40000
BadRequestNotComplete = 0x81130000
GoodEdited = 0x00DC0000
GoodPostActionFailed = 0x00DD0000
UncertainDominantValueChanged = 0x40DE0000
GoodDependentValueChanged = 0x00E00000
BadDominantValueChanged = 0x80E10000
UncertainDependentValueChanged = 0x40E20000
BadDependentValueChanged = 0x80E30000
GoodEdited_DependentValueChanged = 0x01160000
GoodEdited_DominantValueChanged = 0x01170000
GoodEdited_DominantValueChanged_DependentValueChanged = 0x01180000
BadEdited_OutOfRange = 0x81190000
BadInitialValue_OutOfRange = 0x811A0000
BadOutOfRange_DominantValueChanged = 0x811B0000
BadEdited_OutOfRange_DominantValueChanged = 0x811C0000
BadOutOfRange_DominantValueChanged_DependentValueChanged = 0x811D0000
BadEdited_OutOfRange_DominantValueChanged_DependentValueChanged = 0x811E0000
GoodCommunicationEvent = 0x00A70000
GoodShutdownEvent = 0x00A80000
GoodCallAgain = 0x00A90000
GoodNonCriticalTimeout = 0x00AA0000
BadInvalidArgument = 0x80AB0000
BadConnectionRejected = 0x80AC0000
BadDisconnect = 0x80AD0000
BadConnectionClosed = 0x80AE0000
BadInvalidState = 0x80AF0000
BadEndOfStream = 0x80B00000
BadNoDataAvailable = 0x80B10000
BadWaitingForResponse = 0x80B20000
BadOperationAbandoned = 0x80B30000
BadExpectedStreamToBlock = 0x80B40000
BadWouldBlock = 0x80B50000
BadSyntaxError = 0x80B60000
BadMaxConnectionsReached = 0x80B70000
code_to_name_doc = {
0: ('Good', 'The operation completed successfully.'),
0x40000000: ('Uncertain', 'The operation completed however its outputs may not be usable.'),
0x80000000: ('Bad', 'The operation failed.'),
0x80010000: ('BadUnexpectedError', '"An unexpected error occurred."'),
0x80020000: ('BadInternalError', '"An internal error occurred as a result of a programming or configuration error."'),
0x80030000: ('BadOutOfMemory', '"Not enough memory to complete the operation."'),
0x80040000: ('BadResourceUnavailable', '"An operating system resource is not available."'),
0x80050000: ('BadCommunicationError', '"A low level communication error occurred."'),
0x80060000: ('BadEncodingError', '"Encoding halted because of invalid data in the objects being serialized."'),
0x80070000: ('BadDecodingError', '"Decoding halted because of invalid data in the stream."'),
0x80080000: ('BadEncodingLimitsExceeded', '"The message encoding/decoding limits imposed by the stack have been exceeded."'),
0x80B80000: ('BadRequestTooLarge', '"The request message size exceeds limits set by the server."'),
0x80B90000: ('BadResponseTooLarge', '"The response message size exceeds limits set by the client."'),
0x80090000: ('BadUnknownResponse', '"An unrecognized response was received from the server."'),
0x800A0000: ('BadTimeout', '"The operation timed out."'),
0x800B0000: ('BadServiceUnsupported', '"The server does not support the requested service."'),
0x800C0000: ('BadShutdown', '"The operation was cancelled because the application is shutting down."'),
0x800D0000: ('BadServerNotConnected', '"The operation could not complete because the client is not connected to the server."'),
0x800E0000: ('BadServerHalted', '"The server has stopped and cannot process any requests."'),
0x800F0000: ('BadNothingToDo', '"There was nothing to do because the client passed a list of operations with no elements."'),
0x80100000: ('BadTooManyOperations', '"The request could not be processed because it specified too many operations."'),
0x80DB0000: ('BadTooManyMonitoredItems', '"The request could not be processed because there are too many monitored items in the subscription."'),
0x80110000: ('BadDataTypeIdUnknown', '"The extension object cannot be (de)serialized because the data type id is not recognized."'),
0x80120000: ('BadCertificateInvalid', '"The certificate provided as a parameter is not valid."'),
0x80130000: ('BadSecurityChecksFailed', '"An error occurred verifying security."'),
0x81140000: ('BadCertificatePolicyCheckFailed', '"The certificate does not meet the requirements of the security policy."'),
0x80140000: ('BadCertificateTimeInvalid', '"The certificate has expired or is not yet valid."'),
0x80150000: ('BadCertificateIssuerTimeInvalid', '"An issuer certificate has expired or is not yet valid."'),
0x80160000: ('BadCertificateHostNameInvalid', '"The HostName used to connect to a server does not match a HostName in the certificate."'),
0x80170000: ('BadCertificateUriInvalid', '"The URI specified in the ApplicationDescription does not match the URI in the certificate."'),
0x80180000: ('BadCertificateUseNotAllowed', '"The certificate may not be used for the requested operation."'),
0x80190000: ('BadCertificateIssuerUseNotAllowed', '"The issuer certificate may not be used for the requested operation."'),
0x801A0000: ('BadCertificateUntrusted', '"The certificate is not trusted."'),
0x801B0000: ('BadCertificateRevocationUnknown', '"It was not possible to determine if the certificate has been revoked."'),
0x801C0000: ('BadCertificateIssuerRevocationUnknown', '"It was not possible to determine if the issuer certificate has been revoked."'),
0x801D0000: ('BadCertificateRevoked', '"The certificate has been revoked."'),
0x801E0000: ('BadCertificateIssuerRevoked', '"The issuer certificate has been revoked."'),
0x810D0000: ('BadCertificateChainIncomplete', '"The certificate chain is incomplete."'),
0x801F0000: ('BadUserAccessDenied', '"User does not have permission to perform the requested operation."'),
0x80200000: ('BadIdentityTokenInvalid', '"The user identity token is not valid."'),
0x80210000: ('BadIdentityTokenRejected', '"The user identity token is valid but the server has rejected it."'),
0x80220000: ('BadSecureChannelIdInvalid', '"The specified secure channel is no longer valid."'),
0x80230000: ('BadInvalidTimestamp', '"The timestamp is outside the range allowed by the server."'),
0x80240000: ('BadNonceInvalid', '"The nonce does appear to be not a random value or it is not the correct length."'),
0x80250000: ('BadSessionIdInvalid', '"The session id is not valid."'),
0x80260000: ('BadSessionClosed', '"The session was closed by the client."'),
0x80270000: ('BadSessionNotActivated', '"The session cannot be used because ActivateSession has not been called."'),
0x80280000: ('BadSubscriptionIdInvalid', '"The subscription id is not valid."'),
0x802A0000: ('BadRequestHeaderInvalid', '"The header for the request is missing or invalid."'),
0x802B0000: ('BadTimestampsToReturnInvalid', '"The timestamps to return parameter is invalid."'),
0x802C0000: ('BadRequestCancelledByClient', '"The request was cancelled by the client."'),
0x80E50000: ('BadTooManyArguments', '"Too many arguments were provided."'),
0x810E0000: ('BadLicenseExpired', '"The server requires a license to operate in general or to perform a service or operation, but existing license is expired."'),
0x810F0000: ('BadLicenseLimitsExceeded', '"The server has limits on number of allowed operations / objects, based on installed licenses, and these limits where exceeded."'),
0x81100000: ('BadLicenseNotAvailable', '"The server does not have a license which is required to operate in general or to perform a service or operation."'),
0x002D0000: ('GoodSubscriptionTransferred', '"The subscription was transferred to another session."'),
0x002E0000: ('GoodCompletesAsynchronously', '"The processing will complete asynchronously."'),
0x002F0000: ('GoodOverload', '"Sampling has slowed down due to resource limitations."'),
0x00300000: ('GoodClamped', '"The value written was accepted but was clamped."'),
0x80310000: ('BadNoCommunication', '"Communication with the data source is defined, but not established, and there is no last known value available."'),
0x80320000: ('BadWaitingForInitialData', '"Waiting for the server to obtain values from the underlying data source."'),
0x80330000: ('BadNodeIdInvalid', '"The syntax of the node id is not valid."'),
0x80340000: ('BadNodeIdUnknown', '"The node id refers to a node that does not exist in the server address space."'),
0x80350000: ('BadAttributeIdInvalid', '"The attribute is not supported for the specified Node."'),
0x80360000: ('BadIndexRangeInvalid', '"The syntax of the index range parameter is invalid."'),
0x80370000: ('BadIndexRangeNoData', '"No data exists within the range of indexes specified."'),
0x80380000: ('BadDataEncodingInvalid', '"The data encoding is invalid."'),
0x80390000: ('BadDataEncodingUnsupported', '"The server does not support the requested data encoding for the node."'),
0x803A0000: ('BadNotReadable', '"The access level does not allow reading or subscribing to the Node."'),
0x803B0000: ('BadNotWritable', '"The access level does not allow writing to the Node."'),
0x803C0000: ('BadOutOfRange', '"The value was out of range."'),
0x803D0000: ('BadNotSupported', '"The requested operation is not supported."'),
0x803E0000: ('BadNotFound', '"A requested item was not found or a search operation ended without success."'),
0x803F0000: ('BadObjectDeleted', '"The object cannot be used because it has been deleted."'),
0x80400000: ('BadNotImplemented', '"Requested operation is not implemented."'),
0x80410000: ('BadMonitoringModeInvalid', '"The monitoring mode is invalid."'),
0x80420000: ('BadMonitoredItemIdInvalid', '"The monitoring item id does not refer to a valid monitored item."'),
0x80430000: ('BadMonitoredItemFilterInvalid', '"The monitored item filter parameter is not valid."'),
0x80440000: ('BadMonitoredItemFilterUnsupported', '"The server does not support the requested monitored item filter."'),
0x80450000: ('BadFilterNotAllowed', '"A monitoring filter cannot be used in combination with the attribute specified."'),
0x80460000: ('BadStructureMissing', '"A mandatory structured parameter was missing or null."'),
0x80470000: ('BadEventFilterInvalid', '"The event filter is not valid."'),
0x80480000: ('BadContentFilterInvalid', '"The content filter is not valid."'),
0x80C10000: ('BadFilterOperatorInvalid', '"An unrecognized operator was provided in a filter."'),
0x80C20000: ('BadFilterOperatorUnsupported', '"A valid operator was provided, but the server does not provide support for this filter operator."'),
0x80C30000: ('BadFilterOperandCountMismatch', '"The number of operands provided for the filter operator was less then expected for the operand provided."'),
0x80490000: ('BadFilterOperandInvalid', '"The operand used in a content filter is not valid."'),
0x80C40000: ('BadFilterElementInvalid', '"The referenced element is not a valid element in the content filter."'),
0x80C50000: ('BadFilterLiteralInvalid', '"The referenced literal is not a valid value."'),
0x804A0000: ('BadContinuationPointInvalid', '"The continuation point provide is longer valid."'),
0x804B0000: ('BadNoContinuationPoints', '"The operation could not be processed because all continuation points have been allocated."'),
0x804C0000: ('BadReferenceTypeIdInvalid', '"The reference type id does not refer to a valid reference type node."'),
0x804D0000: ('BadBrowseDirectionInvalid', '"The browse direction is not valid."'),
0x804E0000: ('BadNodeNotInView', '"The node is not part of the view."'),
0x81120000: ('BadNumericOverflow', '"The number was not accepted because of a numeric overflow."'),
0x804F0000: ('BadServerUriInvalid', '"The ServerUri is not a valid URI."'),
0x80500000: ('BadServerNameMissing', '"No ServerName was specified."'),
0x80510000: ('BadDiscoveryUrlMissing', '"No DiscoveryUrl was specified."'),
0x80520000: ('BadSempahoreFileMissing', '"The semaphore file specified by the client is not valid."'),
0x80530000: ('BadRequestTypeInvalid', '"The security token request type is not valid."'),
0x80540000: ('BadSecurityModeRejected', '"The security mode does not meet the requirements set by the server."'),
0x80550000: ('BadSecurityPolicyRejected', '"The security policy does not meet the requirements set by the server."'),
0x80560000: ('BadTooManySessions', '"The server has reached its maximum number of sessions."'),
0x80570000: ('BadUserSignatureInvalid', '"The user token signature is missing or invalid."'),
0x80580000: ('BadApplicationSignatureInvalid', '"The signature generated with the client certificate is missing or invalid."'),
0x80590000: ('BadNoValidCertificates', '"The client did not provide at least one software certificate that is valid and meets the profile requirements for the server."'),
0x80C60000: ('BadIdentityChangeNotSupported', '"The server does not support changing the user identity assigned to the session."'),
0x805A0000: ('BadRequestCancelledByRequest', '"The request was cancelled by the client with the Cancel service."'),
0x805B0000: ('BadParentNodeIdInvalid', '"The parent node id does not to refer to a valid node."'),
0x805C0000: ('BadReferenceNotAllowed', '"The reference could not be created because it violates constraints imposed by the data model."'),
0x805D0000: ('BadNodeIdRejected', '"The requested node id was reject because it was either invalid or server does not allow node ids to be specified by the client."'),
0x805E0000: ('BadNodeIdExists', '"The requested node id is already used by another node."'),
0x805F0000: ('BadNodeClassInvalid', '"The node class is not valid."'),
0x80600000: ('BadBrowseNameInvalid', '"The browse name is invalid."'),
0x80610000: ('BadBrowseNameDuplicated', '"The browse name is not unique among nodes that share the same relationship with the parent."'),
0x80620000: ('BadNodeAttributesInvalid', '"The node attributes are not valid for the node class."'),
0x80630000: ('BadTypeDefinitionInvalid', '"The type definition node id does not reference an appropriate type node."'),
0x80640000: ('BadSourceNodeIdInvalid', '"The source node id does not reference a valid node."'),
0x80650000: ('BadTargetNodeIdInvalid', '"The target node id does not reference a valid node."'),
0x80660000: ('BadDuplicateReferenceNotAllowed', '"The reference type between the nodes is already defined."'),
0x80670000: ('BadInvalidSelfReference', '"The server does not allow this type of self reference on this node."'),
0x80680000: ('BadReferenceLocalOnly', '"The reference type is not valid for a reference to a remote server."'),
0x80690000: ('BadNoDeleteRights', '"The server will not allow the node to be deleted."'),
0x40BC0000: ('UncertainReferenceNotDeleted', '"The server was not able to delete all target references."'),
0x806A0000: ('BadServerIndexInvalid', '"The server index is not valid."'),
0x806B0000: ('BadViewIdUnknown', '"The view id does not refer to a valid view node."'),
0x80C90000: ('BadViewTimestampInvalid', '"The view timestamp is not available or not supported."'),
0x80CA0000: ('BadViewParameterMismatch', '"The view parameters are not consistent with each other."'),
0x80CB0000: ('BadViewVersionInvalid', '"The view version is not available or not supported."'),
0x40C00000: ('UncertainNotAllNodesAvailable', '"The list of references may not be complete because the underlying system is not available."'),
0x00BA0000: ('GoodResultsMayBeIncomplete', '"The server should have followed a reference to a node in a remote server but did not. The result set may be incomplete."'),
0x80C80000: ('BadNotTypeDefinition', '"The provided Nodeid was not a type definition nodeid."'),
0x406C0000: ('UncertainReferenceOutOfServer', '"One of the references to follow in the relative path references to a node in the address space in another server."'),
0x806D0000: ('BadTooManyMatches', '"The requested operation has too many matches to return."'),
0x806E0000: ('BadQueryTooComplex', '"The requested operation requires too many resources in the server."'),
0x806F0000: ('BadNoMatch', '"The requested operation has no match to return."'),
0x80700000: ('BadMaxAgeInvalid', '"The max age parameter is invalid."'),
0x80E60000: ('BadSecurityModeInsufficient', '"The operation is not permitted over the current secure channel."'),
0x80710000: ('BadHistoryOperationInvalid', '"The history details parameter is not valid."'),
0x80720000: ('BadHistoryOperationUnsupported', '"The server does not support the requested operation."'),
0x80BD0000: ('BadInvalidTimestampArgument', '"The defined timestamp to return was invalid."'),
0x80730000: ('BadWriteNotSupported', '"The server does not support writing the combination of value, status and timestamps provided."'),
0x80740000: ('BadTypeMismatch', '"The value supplied for the attribute is not of the same type as the attribute"s value."'),
0x80750000: ('BadMethodInvalid', '"The method id does not refer to a method for the specified object."'),
0x80760000: ('BadArgumentsMissing', '"The client did not specify all of the input arguments for the method."'),
0x81110000: ('BadNotExecutable', '"The executable attribute does not allow the execution of the method."'),
0x80770000: ('BadTooManySubscriptions', '"The server has reached its maximum number of subscriptions."'),
0x80780000: ('BadTooManyPublishRequests', '"The server has reached the maximum number of queued publish requests."'),
0x80790000: ('BadNoSubscription', '"There is no subscription available for this session."'),
0x807A0000: ('BadSequenceNumberUnknown', '"The sequence number is unknown to the server."'),
0x807B0000: ('BadMessageNotAvailable', '"The requested notification message is no longer available."'),
0x807C0000: ('BadInsufficientClientProfile', '"The client of the current session does not support one or more Profiles that are necessary for the subscription."'),
0x80BF0000: ('BadStateNotActive', '"The sub-state machine is not currently active."'),
0x81150000: ('BadAlreadyExists', '"An equivalent rule already exists."'),
0x807D0000: ('BadTcpServerTooBusy', '"The server cannot process the request because it is too busy."'),
0x807E0000: ('BadTcpMessageTypeInvalid', '"The type of the message specified in the header invalid."'),
0x807F0000: ('BadTcpSecureChannelUnknown', '"The SecureChannelId and/or TokenId are not currently in use."'),
0x80800000: ('BadTcpMessageTooLarge', '"The size of the message specified in the header is too large."'),
0x80810000: ('BadTcpNotEnoughResources', '"There are not enough resources to process the request."'),
0x80820000: ('BadTcpInternalError', '"An internal error occurred."'),
0x80830000: ('BadTcpEndpointUrlInvalid', '"The server does not recognize the QueryString specified."'),
0x80840000: ('BadRequestInterrupted', '"The request could not be sent because of a network interruption."'),
0x80850000: ('BadRequestTimeout', '"Timeout occurred while processing the request."'),
0x80860000: ('BadSecureChannelClosed', '"The secure channel has been closed."'),
0x80870000: ('BadSecureChannelTokenUnknown', '"The token has expired or is not recognized."'),
0x80880000: ('BadSequenceNumberInvalid', '"The sequence number is not valid."'),
0x80BE0000: ('BadProtocolVersionUnsupported', '"The applications do not have compatible protocol versions."'),
0x80890000: ('BadConfigurationError', '"There is a problem with the configuration that affects the usefulness of the value."'),
0x808A0000: ('BadNotConnected', '"The variable should receive its value from another variable, but has never been configured to do so."'),
0x808B0000: ('BadDeviceFailure', '"There has been a failure in the device/data source that generates the value that has affected the value."'),
0x808C0000: ('BadSensorFailure', '"There has been a failure in the sensor from which the value is derived by the device/data source."'),
0x808D0000: ('BadOutOfService', '"The source of the data is not operational."'),
0x808E0000: ('BadDeadbandFilterInvalid', '"The deadband filter is not valid."'),
0x408F0000: ('UncertainNoCommunicationLastUsableValue', '"Communication to the data source has failed. The variable value is the last value that had a good quality."'),
0x40900000: ('UncertainLastUsableValue', '"Whatever was updating this value has stopped doing so."'),
0x40910000: ('UncertainSubstituteValue', '"The value is an operational value that was manually overwritten."'),
0x40920000: ('UncertainInitialValue', '"The value is an initial value for a variable that normally receives its value from another variable."'),
0x40930000: ('UncertainSensorNotAccurate', '"The value is at one of the sensor limits."'),
0x40940000: ('UncertainEngineeringUnitsExceeded', '"The value is outside of the range of values defined for this parameter."'),
0x40950000: ('UncertainSubNormal', '"The value is derived from multiple sources and has less than the required number of Good sources."'),
0x00960000: ('GoodLocalOverride', '"The value has been overridden."'),
0x80970000: ('BadRefreshInProgress', '"This Condition refresh failed, a Condition refresh operation is already in progress."'),
0x80980000: ('BadConditionAlreadyDisabled', '"This condition has already been disabled."'),
0x80CC0000: ('BadConditionAlreadyEnabled', '"This condition has already been enabled."'),
0x80990000: ('BadConditionDisabled', '"Property not available, this condition is disabled."'),
0x809A0000: ('BadEventIdUnknown', '"The specified event id is not recognized."'),
0x80BB0000: ('BadEventNotAcknowledgeable', '"The event cannot be acknowledged."'),
0x80CD0000: ('BadDialogNotActive', '"The dialog condition is not active."'),
0x80CE0000: ('BadDialogResponseInvalid', '"The response is not valid for the dialog."'),
0x80CF0000: ('BadConditionBranchAlreadyAcked', '"The condition branch has already been acknowledged."'),
0x80D00000: ('BadConditionBranchAlreadyConfirmed', '"The condition branch has already been confirmed."'),
0x80D10000: ('BadConditionAlreadyShelved', '"The condition has already been shelved."'),
0x80D20000: ('BadConditionNotShelved', '"The condition is not currently shelved."'),
0x80D30000: ('BadShelvingTimeOutOfRange', '"The shelving time not within an acceptable range."'),
0x809B0000: ('BadNoData', '"No data exists for the requested time range or event filter."'),
0x80D70000: ('BadBoundNotFound', '"No data found to provide upper or lower bound value."'),
0x80D80000: ('BadBoundNotSupported', '"The server cannot retrieve a bound for the variable."'),
0x809D0000: ('BadDataLost', '"Data is missing due to collection started/stopped/lost."'),
0x809E0000: ('BadDataUnavailable', '"Expected data is unavailable for the requested time range due to an un-mounted volume, an off-line archive or tape, or similar reason for temporary unavailability."'),
0x809F0000: ('BadEntryExists', '"The data or event was not successfully inserted because a matching entry exists."'),
0x80A00000: ('BadNoEntryExists', '"The data or event was not successfully updated because no matching entry exists."'),
0x80A10000: ('BadTimestampNotSupported', '"The client requested history using a timestamp format the server does not support (i.e requested ServerTimestamp when server only supports SourceTimestamp)."'),
0x00A20000: ('GoodEntryInserted', '"The data or event was successfully inserted into the historical database."'),
0x00A30000: ('GoodEntryReplaced', '"The data or event field was successfully replaced in the historical database."'),
0x40A40000: ('UncertainDataSubNormal', '"The value is derived from multiple values and has less than the required number of Good values."'),
0x00A50000: ('GoodNoData', '"No data exists for the requested time range or event filter."'),
0x00A60000: ('GoodMoreData', '"The data or event field was successfully replaced in the historical database."'),
0x80D40000: ('BadAggregateListMismatch', '"The requested number of Aggregates does not match the requested number of NodeIds."'),
0x80D50000: ('BadAggregateNotSupported', '"The requested Aggregate is not support by the server."'),
0x80D60000: ('BadAggregateInvalidInputs', '"The aggregate value could not be derived due to invalid data inputs."'),
0x80DA0000: ('BadAggregateConfigurationRejected', '"The aggregate configuration is not valid for specified node."'),
0x00D90000: ('GoodDataIgnored', '"The request specifies fields which are not valid for the EventType or cannot be saved by the historian."'),
0x80E40000: ('BadRequestNotAllowed', '"The request was rejected by the server because it did not meet the criteria set by the server."'),
0x81130000: ('BadRequestNotComplete', '"The request has not been processed by the server yet."'),
0x00DC0000: ('GoodEdited', '"The value does not come from the real source and has been edited by the server."'),
0x00DD0000: ('GoodPostActionFailed', '"There was an error in execution of these post-actions."'),
0x40DE0000: ('UncertainDominantValueChanged', '"The related EngineeringUnit has been changed but the Variable Value is still provided based on the previous unit."'),
0x00E00000: ('GoodDependentValueChanged', '"A dependent value has been changed but the change has not been applied to the device."'),
0x80E10000: ('BadDominantValueChanged', '"The related EngineeringUnit has been changed but this change has not been applied to the device. The Variable Value is still dependent on the previous unit but its status is currently Bad."'),
0x40E20000: ('UncertainDependentValueChanged', '"A dependent value has been changed but the change has not been applied to the device. The quality of the dominant variable is uncertain."'),
0x80E30000: ('BadDependentValueChanged', '"A dependent value has been changed but the change has not been applied to the device. The quality of the dominant variable is Bad."'),
0x01160000: ('GoodEdited_DependentValueChanged', '"It is delivered with a dominant Variable value when a dependent Variable has changed but the change has not been applied."'),
0x01170000: ('GoodEdited_DominantValueChanged', '"It is delivered with a dependent Variable value when a dominant Variable has changed but the change has not been applied."'),
0x01180000: ('GoodEdited_DominantValueChanged_DependentValueChanged', '"It is delivered with a dependent Variable value when a dominant or dependent Variable has changed but change has not been applied."'),
0x81190000: ('BadEdited_OutOfRange', '"It is delivered with a Variable value when Variable has changed but the value is not legal."'),
0x811A0000: ('BadInitialValue_OutOfRange', '"It is delivered with a Variable value when a source Variable has changed but the value is not legal."'),
0x811B0000: ('BadOutOfRange_DominantValueChanged', '"It is delivered with a dependent Variable value when a dominant Variable has changed and the value is not legal."'),
0x811C0000: ('BadEdited_OutOfRange_DominantValueChanged', '"It is delivered with a dependent Variable value when a dominant Variable has changed, the value is not legal and the change has not been applied."'),
0x811D0000: ('BadOutOfRange_DominantValueChanged_DependentValueChanged', '"It is delivered with a dependent Variable value when a dominant or dependent Variable has changed and the value is not legal."'),
0x811E0000: ('BadEdited_OutOfRange_DominantValueChanged_DependentValueChanged', '"It is delivered with a dependent Variable value when a dominant or dependent Variable has changed, the value is not legal and the change has not been applied."'),
0x00A70000: ('GoodCommunicationEvent', '"The communication layer has raised an event."'),
0x00A80000: ('GoodShutdownEvent', '"The system is shutting down."'),
0x00A90000: ('GoodCallAgain', '"The operation is not finished and needs to be called again."'),
0x00AA0000: ('GoodNonCriticalTimeout', '"A non-critical timeout occurred."'),
0x80AB0000: ('BadInvalidArgument', '"One or more arguments are invalid."'),
0x80AC0000: ('BadConnectionRejected', '"Could not establish a network connection to remote server."'),
0x80AD0000: ('BadDisconnect', '"The server has disconnected from the client."'),
0x80AE0000: ('BadConnectionClosed', '"The network connection has been closed."'),
0x80AF0000: ('BadInvalidState', '"The operation cannot be completed because the object is closed, uninitialized or in some other invalid state."'),
0x80B00000: ('BadEndOfStream', '"Cannot move beyond end of the stream."'),
0x80B10000: ('BadNoDataAvailable', '"No data is currently available for reading from a non-blocking stream."'),
0x80B20000: ('BadWaitingForResponse', '"The asynchronous operation is waiting for a response."'),
0x80B30000: ('BadOperationAbandoned', '"The asynchronous operation was abandoned by the caller."'),
0x80B40000: ('BadExpectedStreamToBlock', '"The stream did not return all data requested (possibly because it is a non-blocking stream)."'),
0x80B50000: ('BadWouldBlock', '"Non blocking behaviour is required and the operation would block."'),
0x80B60000: ('BadSyntaxError', '"A value had an invalid syntax."'),
0x80B70000: ('BadMaxConnectionsReached', '"The operation could not be finished because all available connections are in use."'),
}
def get_name_and_doc(val):
if val in code_to_name_doc:
return code_to_name_doc[val]
else:
if val & 1 << 31:
return 'Bad', 'Unknown StatusCode value: {}'.format(val)
elif val & 1 << 30:
return 'UncertainIn', 'Unknown StatusCode value: {}'.format(val)
else:
return 'Good', 'Unknown StatusCode value: {}'.format(val)
\ No newline at end of file
import datetime
import itertools
import os
import sys
import uuid
import logging
from enum import Enum, IntEnum
import re
from KL import status_codes
from datetime import timedelta, MAXYEAR
logger = logging.getLogger(__name__)
if sys.version_info.major > 2:
unicode = str
from KL.status_codes import StatusCodes
class SecurityPolicyType(IntEnum):
"""
The supported types of SecurityPolicy.
"None"
"Basic128Rsa15_Sign"
"Basic128Rsa15_SignAndEncrypt"
"Basic256_Sign"
"Basic256_SignAndEncrypt"
"Basic256Sha256_Sign"
"Basic256Sha256_SignAndEncrypt"
"""
NoSecurity = 0
Basic128Rsa15_Sign = 1
Basic128Rsa15_SignAndEncrypt = 2
Basic256_Sign = 3
Basic256_SignAndEncrypt = 4
Basic256Sha256_Sign = 5
Basic256Sha256_SignAndEncrypt = 6
class NodeIdType(IntEnum):
TwoByte = 0
FourByte = 1
Numeric = 2
String = 3
Guid = 4
ByteString = 5
class NodeId(object):
"""
NodeId Object
Args:
identifier: The identifier might be an int, a string, bytes or a Guid
namespaceidx(int): The index of the namespace
nodeidtype(NodeIdType): The type of the nodeid if it cannor be guess or you want something special like twobyte nodeid or fourbytenodeid
:ivar Identifier:
:vartype Identifier: NodeId
:ivar NamespaceIndex:
:vartype NamespaceIndex: Int
:ivar NamespaceUri:
:vartype NamespaceUri: String
:ivar ServerIndex:
:vartype ServerIndex: Int
"""
def __init__(self, identifier=None, namespaceidx=0, nodeidtype=None):
self.Identifier = identifier
self.NamespaceIndex = namespaceidx
self.NodeIdType = nodeidtype
self.NamespaceUri = ""
self.ServerIndex = 0
self._freeze = True
if self.Identifier is None:
self.Identifier = 0
if namespaceidx == 0:
self.NodeIdType = NodeIdType.TwoByte
else: # TwoByte NodeId does not encode namespace.
self.NodeIdType = NodeIdType.Numeric
return
if self.NodeIdType is None:
if isinstance(self.Identifier, int):
self.NodeIdType = NodeIdType.Numeric
elif isinstance(self.Identifier, str):
self.NodeIdType = NodeIdType.String
elif isinstance(self.Identifier, bytes):
self.NodeIdType = NodeIdType.ByteString
elif isinstance(self.Identifier, uuid.UUID):
self.NodeIdType = NodeIdType.Guid
else:
raise Exception("NodeId: Could not guess type of NodeId, set NodeIdType")
def __eq__(self, node):
return isinstance(node,
NodeId) and self.NamespaceIndex == node.NamespaceIndex and self.Identifier == node.Identifier
def __ne__(self, other):
return not self.__eq__(other)
def __hash__(self):
return hash((self.NamespaceIndex, self.Identifier))
def __lt__(self, other):
if not isinstance(other, NodeId):
raise AttributeError("Can only compare to NodeId")
return (self.NodeIdType, self.NamespaceIndex, self.Identifier) < (
other.NodeIdType, other.NamespaceIndex, other.Identifier)
def is_null(self):
if self.NamespaceIndex != 0:
return False
return self.has_null_identifier()
def has_null_identifier(self):
if not self.Identifier:
return True
if self.NodeIdType == NodeIdType.Guid and re.match(b'\x00+', self.Identifier.bytes):
return True
return False
@staticmethod
def from_string(string):
try:
return NodeId._from_string(string)
except ValueError as ex:
raise Exception("Error parsing string {0}".format(string), ex)
@staticmethod
def _from_string(string):
l = string.split(";")
identifier = None
namespace = 0
ntype = None
srv = None
nsu = None
for el in l:
if not el:
continue
k, v = el.split("=", 1)
k = k.strip()
v = v.strip()
if k == "ns":
namespace = int(v)
elif k == "i":
ntype = NodeIdType.Numeric
identifier = int(v)
elif k == "s":
ntype = NodeIdType.String
identifier = v
elif k == "g":
ntype = NodeIdType.Guid
identifier = v
elif k == "b":
ntype = NodeIdType.ByteString
identifier = v
elif k == "srv":
srv = v
elif k == "nsu":
nsu = v
if identifier is None:
raise Exception("Could not find identifier in string: " + string)
nodeid = NodeId(identifier, namespace, ntype)
nodeid.NamespaceUri = nsu
nodeid.ServerIndex = srv
return nodeid
def to_string(self):
string = []
if self.NamespaceIndex != 0:
string.append("ns={0}".format(self.NamespaceIndex))
ntype = None
if self.NodeIdType == NodeIdType.Numeric:
ntype = "i"
elif self.NodeIdType == NodeIdType.String:
ntype = "s"
elif self.NodeIdType == NodeIdType.TwoByte:
ntype = "i"
elif self.NodeIdType == NodeIdType.FourByte:
ntype = "i"
elif self.NodeIdType == NodeIdType.Guid:
ntype = "g"
elif self.NodeIdType == NodeIdType.ByteString:
ntype = "b"
string.append("{0}={1}".format(ntype, self.Identifier))
if self.ServerIndex:
string.append("srv={}".format(self.ServerIndex))
if self.NamespaceUri:
string.append("nsu={0}".format(self.NamespaceUri))
return ";".join(string)
def __str__(self):
return "{0}NodeId({1})".format(self.NodeIdType.name, self.to_string())
__repr__ = __str__
# def to_binary(self):
# # return nodeid_to_binary(self)
# data = self.nodeid.Identifier
class NumericNodeId(NodeId):
def __init__(self, identifier, namespace=0):
NodeId.__init__(self, identifier, namespace, NodeIdType.Numeric)
class TwoByteNodeId(NodeId):
def __init__(self, identifier):
NodeId.__init__(self, identifier, 0, NodeIdType.TwoByte)
class FourByteNodeId(NodeId):
def __init__(self, identifier, namespace=0):
NodeId.__init__(self, identifier, namespace, NodeIdType.FourByte)
class ByteStringNodeId(NodeId):
def __init__(self, identifier, namespace=0):
NodeId.__init__(self, identifier, namespace, NodeIdType.ByteString)
class GuidNodeId(NodeId):
def __init__(self, identifier, namespace=0):
NodeId.__init__(self, identifier, namespace, NodeIdType.Guid)
class StringNodeId(NodeId):
def __init__(self, identifier, namespace=0):
NodeId.__init__(self, identifier, namespace, NodeIdType.String)
class _FrozenClass(object):
"""
Make it impossible to add members to a class.
Not pythonic at all but we found out it prevents many many
bugs in use of protocol structures
"""
_freeze = False
def __setattr__(self, key, value):
if self._freeze and not hasattr(self, key):
raise TypeError("Error adding member '{0}' to class '{1}', class is frozen, members are {2}".format(
key, self.__class__.__name__, self.__dict__.keys()))
object.__setattr__(self, key, value)
if "PYOPCUA_TYPO_CHECK" in os.environ:
# typo check is cpu consuming, but it will make debug easy.
# set PYOPCUA_TYPO_CHECK will make all uatype classes inherit from _FrozenClass
FrozenClass = _FrozenClass
else:
FrozenClass = object
class ValueRank(IntEnum):
"""
Defines dimensions of a variable.
This enum does not support all cases since ValueRank support any n>0
but since it is an IntEnum it can be replace by a normal int
"""
ScalarOrOneDimension = -3
Any = -2
Scalar = -1
OneOrMoreDimensions = 0
OneDimension = 1
# the next names are not in spec but so common we express them here
TwoDimensions = 2
ThreeDimensions = 3
FourDimensions = 4
class WriteParameters(FrozenClass):
"""
:ivar NodesToWrite:
:vartype NodesToWrite: WriteValue
"""
types = [
('NodesToWrite', 'ListOfWriteValue'),
]
def __init__(self):
self.NodesToWrite = []
self._freeze = True
def __str__(self):
return 'WriteParameters(NodesToWrite:{self.NodesToWrite})'
__repr__ = __str__
class WriteValue(FrozenClass):
"""
:ivar NodeId:
:vartype NodeId: NodeId
:ivar AttributeId:
:vartype AttributeId: UInt32
:ivar IndexRange:
:vartype IndexRange: String
:ivar Value:
:vartype Value: DataValue
"""
types = [
('NodeId', 'NodeId'),
('AttributeId', 'UInt32'),
('IndexRange', 'String'),
('Value', 'DataValue'),
]
def __init__(self):
self.NodeId = NodeId()
self.AttributeId = 0
self.IndexRange = None
self.Value = DataValue()
self._freeze = True
def __str__(self):
return 'WriteValue(NodeId:{self.NodeId}, AttributeId:{self.AttributeId}, IndexRange:{self.IndexRange}, ' \
'Value:{self.Value}) '
__repr__ = __str__
class DataValue(FrozenClass):
switches = {
'Value': ('Encoding', 0),
'StatusCode': ('Encoding', 1),
'SourceTimestamp': ('Encoding', 2),
'ServerTimestamp': ('Encoding', 3),
'SourcePicoseconds': ('Encoding', 4),
'ServerPicoseconds': ('Encoding', 5),
}
types = (
('Encoding', 'Byte'),
('Value', 'Variant'),
('StatusCode', 'StatusCode'),
('SourceTimestamp', 'DateTime'),
('SourcePicoseconds', 'UInt16'),
('ServerTimestamp', 'DateTime'),
('ServerPicoseconds', 'UInt16'),
)
def __init__(self, variant=None, status=None, sourceTimestamp=None, sourcePicoseconds=None,
serverTimestamp=None,
serverPicoseconds=None):
self.Encoding = 0
if not isinstance(variant, Variant):
variant = Variant(variant)
self.Value = variant
if status is None:
self.StatusCode = StatusCode()
else:
self.StatusCode = status
self.SourceTimestamp = sourceTimestamp
self.SourcePicoseconds = sourcePicoseconds
self.ServerTimestamp = serverTimestamp
self.ServerPicoseconds = serverPicoseconds
self._freeze = True
def __str__(self):
s = 'DataValue(Value:{0}'.format(self.Value)
if self.StatusCode is not None:
s += ', StatusCode:{0}'.format(self.StatusCode)
if self.SourceTimestamp is not None:
s += ', SourceTimestamp:{0}'.format(self.SourceTimestamp)
if self.ServerTimestamp is not None:
s += ', ServerTimestamp:{0}'.format(self.ServerTimestamp)
if self.SourcePicoseconds is not None:
s += ', SourcePicoseconds:{0}'.format(self.SourcePicoseconds)
if self.ServerPicoseconds is not None:
s += ', ServerPicoseconds:{0}'.format(self.ServerPicoseconds)
s += ')'
return s
__repr__ = __str__
class Variant(FrozenClass):
"""
Create an OPC-UA Variant object.
if no argument a Null Variant is created.
if not variant type is given, attemps to guess type from python type
if a variant is given as value, the new objects becomes a copy of the argument
:ivar Value:
:vartype Value: Any supported type
:ivar VariantType:
:vartype VariantType: VariantType
:ivar Dimension:
:vartype Dimensions: The length of each dimensions. Usually guessed from value.
:ivar is_array:
:vartype is_array: If the variant is an array. Usually guessed from value.
"""
def __init__(self, value=None, varianttype=None, dimensions=None, is_array=None):
self._freeze = False # defers validation until ready.
# Value, VariantType
self._value = None
self._variantType = None
if isinstance(value, Variant):
self.Value = value.Value
self.VariantType = value.VariantType
else:
self.Value = value
self.VariantType = varianttype
# Dimensions
self.Dimensions = dimensions
if dimensions is None and isinstance(self.Value, (list, tuple)):
dims = get_shape(self.Value)
if len(dims) > 1:
self.Dimensions = dims
# is_array
if is_array is not None:
self.is_array = bool(is_array)
else:
self.is_array = isinstance(self.Value, (list, tuple))
# Validation check
self._freeze = True
self._validate()
@property
def Value(self):
return self._value
@Value.setter
def Value(self, value):
if not (self._value is None or isinstance(value, type(self._value))):
logger.warning("Datatype changed from {} to {} in Variant {}.".format(type(self._value), type(value), self))
self._value = value
self._validate()
@property
def VariantType(self):
return self._variantType
@VariantType.setter
def VariantType(self, variantType):
if variantType is not None:
self._variantType = variantType
else:
self._variantType = self._guess_type(self.Value)
self._validate()
def _validate(self):
self._freeze = False
if self._freeze is False:
return
elif isinstance(self._value, int) and self.VariantType in (VariantType.Float, VariantType.Double):
self._value = float(self._value)
elif self._value is None and not self.is_array and \
self.VariantType not in (VariantType.Null, VariantType.String, VariantType.DateTime):
raise Exception("Non array Variant of type {0} cannot have value None".format(self.VariantType))
def __eq__(self, other):
if isinstance(other, Variant) and self.VariantType == other.VariantType and self.Value == other.Value:
return True
return False
def __ne__(self, other):
return not self.__eq__(other)
def _guess_type(self, val):
if isinstance(val, (list, tuple)):
error_val = val
while val and isinstance(val[0], (list, tuple)):
val = val[0]
types = {type(el) for el in val}
if len(types) == 0:
raise Exception("List of zero length. Could not guess UA type of variable {0}".format(error_val))
elif types == set([int, float]):
logger.debug(
"Variable {0} has ints and floats. UA type will be {1}".format(error_val, VariantType.Double)
)
val = float()
elif len(types) > 1:
raise Exception("List of multiple types. Could not guess UA type of variable {0}".format(error_val))
else:
val = val[0]
if val is None:
return VariantType.Null
elif isinstance(val, bool):
return VariantType.Boolean
elif isinstance(val, float):
return VariantType.Double
elif isinstance(val, IntEnum):
return VariantType.Int32
elif isinstance(val, int):
return VariantType.Int64
elif isinstance(val, (str, unicode)):
return VariantType.String
elif isinstance(val, bytes):
return VariantType.ByteString
elif isinstance(val, datetime.datetime):
return VariantType.DateTime
elif isinstance(val, uuid.UUID):
return VariantType.Guid
else:
if isinstance(val, object):
try:
return getattr(VariantType, val.__class__.__name__)
except AttributeError:
return VariantType.ExtensionObject
else:
raise Exception("Could not guess UA type of {0} with type {1}, specify UA type".format(val, type(val)))
def __str__(self):
return "Variant(val:{0!s},type:{1})".format(self.Value, self.VariantType)
__repr__ = __str__
class StatusCode(FrozenClass):
"""
:ivar value:
:vartype value: int
:ivar name:
:vartype name: string
:ivar doc:
:vartype doc: string
"""
types = [("value", "UInt32")]
def __init__(self, value=0):
if isinstance(value, str):
self.value = getattr(StatusCodes, value)
else:
self.value = value
self._freeze = True
def is_good(self):
"""
return True if status is Good.
"""
mask = 3 << 30
if mask & self.value:
return False
else:
return True
def check(self):
"""
Raises an exception if the status code is anything else than 0 (good).
Use the is_good() method if you do not want an exception.
"""
if not self.is_good():
raise ValueError(self.value)
@property
def name(self):
name, _ = status_codes.get_name_and_doc(self.value)
return name
def __str__(self):
return 'StatusCode({0})'.format(self.name)
__repr__ = __str__
def get_shape(mylist):
dims = []
while isinstance(mylist, (list, tuple)):
dims.append(len(mylist))
if len(mylist) == 0:
break
mylist = mylist[0]
return dims
class VariantType(Enum):
"""
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:
"""
Null = 0
Boolean = 1
SByte = 2
Byte = 3
Int16 = 4
UInt16 = 5
Int32 = 6
UInt32 = 7
Int64 = 8
UInt64 = 9
Float = 10
Double = 11
String = 12
DateTime = 13
Guid = 14
ByteString = 15
XmlElement = 16
NodeId = 17
ExpandedNodeId = 18
StatusCode = 19
QualifiedName = 20
LocalizedText = 21
ExtensionObject = 22
DataValue = 23
Variant = 24
DiagnosticInfo = 25
class QualifiedName(FrozenClass):
"""
A string qualified with a namespace index.
"""
types = [
('NamespaceIndex', 'UInt16'),
('Name', 'String'),
]
def __init__(self, name=None, namespaceidx=0):
if not isinstance(namespaceidx, int):
raise Exception("namespaceidx must be an int")
self.NamespaceIndex = namespaceidx
self.Name = name
self._freeze = True
def __str__(self):
return 'QualifiedName({0}:{1})'.format(self.NamespaceIndex, self.Name)
__repr__ = __str__
@staticmethod
def from_string(string):
if ":" in string:
try:
idx, name = string.split(":", 1)
idx = int(idx)
except (TypeError, ValueError) as ex:
raise Exception("Error parsing string {0}".format(string), ex)
else:
idx = 0
name = string
return QualifiedName(name, idx)
class LocalizedText(FrozenClass):
"""
A string qualified with a namespace index.
"""
switches = {
'Locale': ('Encoding', 0),
'Text': ('Encoding', 1),
}
types = (
('Encoding', 'Byte'),
('Locale', 'String'),
('Text', 'String'),)
def __init__(self, text=None, locale=None):
self.Encoding = 0
self._text = None
self._locale = None
if text:
self.Text = text
if locale:
self.Locale = locale
self._freeze = True
@property
def Text(self):
return self._text
@property
def Locale(self):
return self._locale
@Text.setter
def Text(self, text):
if isinstance(text, str):
pass
elif isinstance(text, bytes):
text = text.decode()
else:
raise ValueError("A LocalizedText object takes a string as argument, not a {}, {}".format(type(text), text))
self._text = text
if self._text:
self.Encoding |= (1 << 1)
@Locale.setter
def Locale(self, locale):
if not isinstance(locale, str):
raise ValueError(
"A LocalizedText object takes a string as argument, not a {}, {}".format({type(locale)}, {locale}))
self._locale = locale
if self._locale:
self.Encoding |= (1)
def to_string(self):
if self.Text is None:
return ""
if self.Locale is None:
return self.Text
return self.__str__()
@staticmethod
def from_string(string):
m = re.match(r"^LocalizedText\(Encoding:(.*), Locale:(.*), Text:(.*)\)$", string)
if m:
text = m.group(3) if m.group(3) != str(None) else None
locale = m.group(2) if m.group(2) != str(None) else None
return LocalizedText(text=text, locale=locale)
else:
return LocalizedText(string)
def __str__(self):
return 'LocalizedText(' + 'Encoding:' + str(self.Encoding) + ', ' + \
'Locale:' + str(self.Locale) + ', ' + \
'Text:' + str(self.Text) + ')'
__repr__ = __str__
def __eq__(self, other):
if isinstance(other, LocalizedText) and self.Locale == other.Locale and self.Text == other.Text:
return True
return False
def __ne__(self, other):
return not self.__eq__(other)
class _MaskEnum(IntEnum):
@classmethod
def parse_bitfield(cls, the_int):
""" Take an integer and interpret it as a set of enum values. """
if not isinstance(the_int, int):
raise ValueError("Argument should be an int, we received {} fo type {}".format(the_int, type(the_int)))
return {cls(b) for b in cls._bits(the_int)}
@classmethod
def to_bitfield(cls, collection):
""" Takes some enum values and creates an integer from them. """
# make sure all elements are of the correct type (use itertools.tee in case we get passed an
# iterator)
iter1, iter2 = itertools.tee(iter(collection))
assert all(isinstance(x, cls) for x in iter1)
return sum(x.mask for x in iter2)
@property
def mask(self):
return 1 << self.value
@staticmethod
def _bits(n):
""" Iterate over the bits in n.
e.g. bits(44) yields at 2, 3, 5
"""
assert n >= 0 # avoid infinite recursion
pos = 0
while n:
if n & 0x1:
yield pos
n = n // 2
pos += 1
class AccessLevel(_MaskEnum):
"""
Bit index to indicate what the access level is.
Spec Part 3, appears multiple times, e.g. paragraph 5.6.2 Variable NodeClass
"""
CurrentRead = 0
CurrentWrite = 1
HistoryRead = 2
HistoryWrite = 3
SemanticChange = 4
StatusWrite = 5
TimestampWrite = 6
class ExtensionObject(FrozenClass):
"""
Any UA object packed as an ExtensionObject
:ivar TypeId:
:vartype TypeId: NodeId
:ivar Body:
:vartype Body: bytes
"""
switches = {
'Body': ('Encoding', 0),
}
types = (
("TypeId", "NodeId"),
("Encoding", "Byte"),
("Body", "ByteString"),
)
def __init__(self):
self.TypeId = NodeId()
self.Encoding = 0
self.Body = None
self._freeze = True
def __bool__(self):
return self.Body is not None
__nonzero__ = __bool__
def __str__(self):
size = len(self.Body) if self.Body is not None else None
return 'ExtensionObject(' + 'TypeId:' + str(self.TypeId) + ', ' + \
'Encoding:' + str(self.Encoding) + ', ' + str(size) + ' bytes)'
__repr__ = __str__
def get_default_value(vtype):
"""
Given a variant type return default value for this type
"""
if vtype == VariantType.Null:
return None
elif vtype == VariantType.Boolean:
return False
elif vtype in (VariantType.SByte, VariantType.Byte):
return 0
elif vtype == VariantType.ByteString:
return b""
elif 4 <= vtype.value <= 9:
return 0
elif vtype in (VariantType.Float, VariantType.Double):
return 0.0
elif vtype == VariantType.String:
return None # a string can be null
elif vtype == VariantType.DateTime:
return datetime.datetime.utcnow()
elif vtype == VariantType.Guid:
return uuid.uuid4()
elif vtype == VariantType.XmlElement:
return None # Not sure this is correct
elif vtype == VariantType.NodeId:
return NodeId()
elif vtype == VariantType.ExpandedNodeId:
return NodeId()
elif vtype == VariantType.StatusCode:
return StatusCode()
elif vtype == VariantType.QualifiedName:
return QualifiedName()
elif vtype == VariantType.LocalizedText:
return LocalizedText()
elif vtype == VariantType.ExtensionObject:
return ExtensionObject()
elif vtype == VariantType.DataValue:
return DataValue()
elif vtype == VariantType.Variant:
return Variant()
else:
raise RuntimeError("function take a uatype as argument, got:", vtype)
extension_object_classes = {}
extension_object_ids = {}
def flatten(mylist):
if mylist is None:
return None
elif len(mylist) == 0:
return mylist
while isinstance(mylist[0], (list, tuple)):
mylist = [item for sublist in mylist for item in sublist]
if len(mylist) == 0:
break
return mylist
def datatype_to_varianttype(int_type):
"""
Takes a NodeId or int and return a VariantType
This is only supported if int_type < 63 due to VariantType encoding
At low level we do not have access to address space thus decoding is limited
a better version of this method can be find in ua_utils.py
"""
if isinstance(int_type, NodeId):
int_type = int_type.Identifier
if int_type <= 25:
return VariantType(int_type)
else:
return VariantTypeCustom(int_type)
class VariantTypeCustom(object):
def __init__(self, val):
self.name = "Custom"
self.value = val
if self.value > 0b00111111:
raise Exception(
"Cannot create VariantType. VariantType must be {0} > x > {1}, received {2}".format(0b111111, 25, val))
def __str__(self):
return "VariantType.Custom:{0}".format(self.value)
__repr__ = __str__
def __eq__(self, other):
return self.value == other.value
def get_win_epoch():
return win_epoch_to_datetime(0)
FILETIME_EPOCH_AS_DATETIME = datetime.datetime(1601, 1, 1)
def win_epoch_to_datetime(epch):
try:
return FILETIME_EPOCH_AS_DATETIME + timedelta(microseconds=epch // 10)
except OverflowError:
# FILETIMEs after 31 Dec 9999 can't be converted to datetime
logger.warning("datetime overflow: %s", epch)
return datetime.datetime(MAXYEAR, 12, 31, 23, 59, 59, 999999)
from KL.hand_protocol import SecurityPolicy
class SecurityPolicyBasic256Sha256(SecurityPolicy):
URI = "http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256"
signature_key_size = 32
symmetric_key_size = 32
AsymmetricEncryptionURI = "http://www.w3.org/2001/04/xmlenc#rsa-oaep"
AsymmetricSignatureURI = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"
\ No newline at end of file
class CallbackDispatcher(object):
def __init__(self):
self._listeners = {}
\ No newline at end of file
import logging
from KL.binary import struct_from_binary, header_to_binary, struct_to_binary
from common import utils
from datetime import datetime
import copy
from KL import application_protocol, hand_protocol, types
logger = logging.getLogger('protocol')
class SecureConnection(object):
def __init__(self, security_policy):
self._sequence_number = 0
self._peer_sequence_number = None
self._incoming_parts = []
self.security_policy = security_policy
self._policies = []
self.security_token = application_protocol.ChannelSecurityToken()
self.next_security_token = application_protocol.ChannelSecurityToken()
self.prev_security_token = application_protocol.ChannelSecurityToken()
self.local_nonce = 0
self.remote_nonce = 0
self._open = False
self._allow_prev_token = False
self._max_chunk_size = 65536
def receive_from_header_and_body(self, header, body):
if header.MessageType == hand_protocol.MessageType.SecureOpen:
data = body.copy(header.body_size)
security_header = struct_from_binary(hand_protocol.AsymmetricAlgorithmHeader, data)
if not self.is_open():
# Only call select_policy if the channel isn't open. Otherwise
# it will break the Secure channel renewal.
self.select_policy(security_header.SecurityPolicyURI, security_header.SenderCertificate)
elif header.MessageType in (hand_protocol.MessageType.SecureMessage, hand_protocol.MessageType.SecureClose):
data = body.copy(header.body_size)
security_header = struct_from_binary(hand_protocol.SymmetricAlgorithmHeader, data)
self._check_sym_header(security_header)
if header.MessageType in (hand_protocol.MessageType.SecureMessage, hand_protocol.MessageType.SecureOpen,
hand_protocol.MessageType.SecureClose):
chunk = MessageChunk.from_header_and_body(self.security_policy, header, body)
return self._receive(chunk)
elif header.MessageType == hand_protocol.MessageType.Hello:
msg = struct_from_binary(hand_protocol.Hello, body)
self._max_chunk_size = msg.ReceiveBufferSize
return msg
elif header.MessageType == hand_protocol.MessageType.Acknowledge:
msg = struct_from_binary(hand_protocol.Acknowledge, body)
self._max_chunk_size = msg.SendBufferSize
return msg
elif header.MessageType == hand_protocol.MessageType.Error:
msg = struct_from_binary(hand_protocol.ErrorMessage, body)
logger.warning("Received an error: %s", msg)
return msg
else:
raise Exception("Unsupported message type {0}".format(header.MessageType))
def open(self, params, server):
"""
called on server side to open secure channel
"""
self.local_nonce = utils.create_nonce(self.security_policy.symmetric_key_size)
self.remote_nonce = params.ClientNonce
response = application_protocol.OpenSecureChannelResult()
response.ServerNonce = self.local_nonce
if not self._open or params.RequestType == application_protocol.SecurityTokenRequestType.Issue:
self._open = True
self.security_token.TokenId = 13 # random value
self.security_token.ChannelId = server.get_new_channel_id()
self.security_token.RevisedLifetime = params.RequestedLifetime
self.security_token.CreatedAt = datetime.utcnow()
response.SecurityToken = self.security_token
self.security_policy.make_local_symmetric_key(self.remote_nonce, self.local_nonce)
self.security_policy.make_remote_symmetric_key(self.local_nonce, self.remote_nonce)
else:
self.next_security_token = copy.deepcopy(self.security_token)
self.next_security_token.TokenId += 1
self.next_security_token.RevisedLifetime = params.RequestedLifetime
self.next_security_token.CreatedAt = datetime.utcnow()
response.SecurityToken = self.next_security_token
return response
def close(self):
self._open = False
def is_open(self):
return self._open
def set_policy_factories(self, policies):
self._policies = policies
def message_to_binary(self, message, message_type=hand_protocol.MessageType.SecureMessage, request_id=0):
"""
Convert OPC UA secure message to binary.
The only supported types are SecureOpen, SecureMessage, SecureClose
if message_type is SecureMessage, the AlgoritmHeader should be passed as arg
"""
chunks = MessageChunk.message_to_chunks(self.security_policy, message, self._max_chunk_size,
message_type=message_type, channel_id=self.security_token.ChannelId,
request_id=request_id, token_id=self.security_token.TokenId)
for chunk in chunks:
self._sequence_number += 1
if self._sequence_number >= (1 << 32):
logger.debug("Wrapping sequence number: %d -> 1", self._sequence_number)
self._sequence_number = 1
chunk.SequenceHeader.SequenceNumber = self._sequence_number
return b"".join([chunk.to_binary() for chunk in chunks])
class MessageChunk(types.FrozenClass):
def __init__(self, security_policy, body=b'', msg_type=hand_protocol.MessageType.SecureMessage,
chunk_type=hand_protocol.ChunkType.Single):
self.MessageHeader = hand_protocol.Header(msg_type, chunk_type)
if msg_type in (hand_protocol.MessageType.SecureMessage, hand_protocol.MessageType.SecureClose):
self.SecurityHeader = hand_protocol.SymmetricAlgorithmHeader()
elif msg_type == hand_protocol.MessageType.SecureOpen:
self.SecurityHeader = hand_protocol.AsymmetricAlgorithmHeader()
else:
raise Exception("Unsupported message type: {0}".format(msg_type))
self.SequenceHeader = hand_protocol.SequenceHeader()
self.Body = body
self.security_policy = security_policy
@staticmethod
def from_header_and_body(security_policy, header, buf):
assert len(buf) >= header.body_size, 'Full body expected here'
data = buf.copy(header.body_size)
buf.skip(header.body_size)
if header.MessageType in (hand_protocol.MessageType.SecureMessage, hand_protocol.MessageType.SecureClose):
security_header = struct_from_binary(hand_protocol.SymmetricAlgorithmHeader, data)
crypto = security_policy.symmetric_cryptography
elif header.MessageType == hand_protocol.MessageType.SecureOpen:
security_header = struct_from_binary(hand_protocol.AsymmetricAlgorithmHeader, data)
crypto = security_policy.asymmetric_cryptography
else:
raise Exception("Unsupported message type: {0}".format(header.MessageType))
obj = MessageChunk(crypto)
obj.MessageHeader = header
obj.SecurityHeader = security_header
decrypted = crypto.decrypt(data.read(len(data)))
signature_size = crypto.vsignature_size()
if signature_size > 0:
signature = decrypted[-signature_size:]
decrypted = decrypted[:-signature_size]
crypto.verify(header_to_binary(obj.MessageHeader) + struct_to_binary(obj.SecurityHeader) + decrypted,
signature)
data = utils.Buffer(crypto.remove_padding(decrypted))
obj.SequenceHeader = struct_from_binary(hand_protocol.SequenceHeader, data)
obj.Body = data.read(len(data))
return obj
import logging
from KL.attribute_ids import AttributeIds
from KL.types import NodeId, QualifiedName, NodeIdType
from KL.constants import ObjectIds
from KL.application_protocol import AddNodesItem, NodeClass, ReferenceDescription
from KL.hand_protocol import ObjectAttributes, VariableAttributes, MethodAttributes, DataTypeAttributes
import common.utils
logger = logging.getLogger(__name__)
def instantiate(parent, node_type, nodeid=None, bname=None, dname=None, idx=0, instantiate_optional=True):
rdesc = _rdesc_from_node(parent, node_type)
rdesc.TypeDefinition = node_type.nodeid
from common.node import Node
if nodeid is None:
nodeid = NodeId(namespaceidx=idx) # will trigger automatic node generation in namespace idx
if bname is None:
bname = rdesc.BrowseName
elif isinstance(bname, str):
bname = QualifiedName.from_string(bname)
nodeids = _instantiate_node(
parent.server,
Node(parent.server, rdesc.NodeId),
parent.nodeid,
rdesc,
nodeid,
bname,
dname=dname,
instantiate_optional=instantiate_optional)
return [Node(parent.server, nid) for nid in nodeids]
def _instantiate_node(server,
node_type,
parentid,
rdesc,
nodeid,
bname,
dname=None,
recursive=True,
instantiate_optional=True):
"""
instantiate a node type under parent
"""
addnode = AddNodesItem()
addnode.RequestedNewNodeId = nodeid
addnode.BrowseName = bname
addnode.ParentNodeId = parentid
addnode.ReferenceTypeId = rdesc.ReferenceTypeId
addnode.TypeDefinition = rdesc.TypeDefinition
if rdesc.NodeClass in (NodeClass.Object, NodeClass.ObjectType):
addnode.NodeClass = NodeClass.Object
_read_and_copy_attrs(node_type, ObjectAttributes(), addnode)
elif rdesc.NodeClass in (NodeClass.Variable, NodeClass.VariableType):
addnode.NodeClass = NodeClass.Variable
_read_and_copy_attrs(node_type, VariableAttributes(), addnode)
elif rdesc.NodeClass in (NodeClass.Method, ):
addnode.NodeClass = NodeClass.Method
_read_and_copy_attrs(node_type, MethodAttributes(), addnode)
elif rdesc.NodeClass in (NodeClass.DataType, ):
addnode.NodeClass = NodeClass.DataType
_read_and_copy_attrs(node_type, DataTypeAttributes(), addnode)
else:
logger.error("Instantiate: Node class not supported: %s", rdesc.NodeClass)
raise RuntimeError("Instantiate: Node class not supported")
return
if dname is not None:
addnode.NodeAttributes.DisplayName = dname
res = server.add_nodes([addnode])[0]
res.StatusCode.check()
added_nodes = [res.AddedNodeId]
if recursive:
from common.node import Node
parents = utils.get_node_supertypes(node_type, includeitself=True)
node = Node(server, res.AddedNodeId)
for parent in parents:
descs = parent.get_children_descriptions(includesubtypes=False)
for c_rdesc in descs:
# skip items that already exists, prefer the 'lowest' one in object hierarchy
if not utils.is_child_present(node, c_rdesc.BrowseName):
c_node_type = Node(server, c_rdesc.NodeId)
refs = c_node_type.get_referenced_nodes(refs=ObjectIds.HasModellingRule)
if not refs:
# spec says to ignore nodes without modelling rules
logger.info("Instantiate: Skip node without modelling rule %s as part of %s", c_rdesc.BrowseName, addnode.BrowseName)
continue
# exclude nodes with optional ModellingRule if requested
if not instantiate_optional and refs[0].nodeid in (NodeId(ObjectIds.ModellingRule_Optional), NodeId(ObjectIds.ModellingRule_OptionalPlaceholder)):
logger.info("Instantiate: Skip optional node %s as part of %s", c_rdesc.BrowseName, addnode.BrowseName)
continue
# if root node being instantiated has a String NodeId, create the children with a String NodeId
if res.AddedNodeId.NodeIdType is NodeIdType.String:
inst_nodeid = res.AddedNodeId.Identifier + "." + c_rdesc.BrowseName.Name
nodeids = _instantiate_node(
server,
c_node_type,
res.AddedNodeId,
c_rdesc,
nodeid=NodeId(identifier=inst_nodeid, namespaceidx=res.AddedNodeId.NamespaceIndex),
bname=c_rdesc.BrowseName,
instantiate_optional=instantiate_optional)
else:
nodeids = _instantiate_node(
server,
c_node_type,
res.AddedNodeId,
c_rdesc,
nodeid=NodeId(namespaceidx=res.AddedNodeId.NamespaceIndex),
bname=c_rdesc.BrowseName,
instantiate_optional=instantiate_optional)
added_nodes.extend(nodeids)
return added_nodes
def _rdesc_from_node(parent, node):
results = node.get_attributes([AttributeIds.NodeClass, AttributeIds.BrowseName, AttributeIds.DisplayName])
nclass, qname, dname = [res.Value.Value for res in results]
rdesc = ReferenceDescription()
rdesc.NodeId = node.nodeid
rdesc.BrowseName = qname
rdesc.DisplayName = dname
rdesc.NodeClass = nclass
if parent.get_type_definition() == NodeId(ObjectIds.FolderType):
rdesc.ReferenceTypeId = NodeId(ObjectIds.Organizes)
else:
rdesc.ReferenceTypeId = NodeId(ObjectIds.HasComponent)
typedef = node.get_type_definition()
if typedef:
rdesc.TypeDefinition = typedef
return rdesc
def _read_and_copy_attrs(node_type, struct, addnode):
names = [name for name in struct.__dict__.keys() if not name.startswith("_") and name not in ("BodyLength", "TypeId", "SpecifiedAttributes", "Encoding", "IsAbstract", "EventNotifier")]
attrs = [getattr(AttributeIds, name) for name in names]
for name in names:
results = node_type.get_attributes(attrs)
for idx, name in enumerate(names):
if results[idx].StatusCode.is_good():
if name == "Value":
setattr(struct, name, results[idx].Value)
else:
setattr(struct, name, results[idx].Value.Value)
else:
logger.warning("Instantiate: while copying attributes from node type {0!s}, attribute {1!s}, statuscode is {2!s}".format(node_type, name, results[idx].StatusCode))
addnode.NodeAttributes = struct
\ No newline at end of file
from common import node
from KL.types import NodeId, LocalizedText, ValueRank, AccessLevel, QualifiedName
from KL.constants import ObjectIds
from KL.application_protocol import AddNodesItem, NodeClass, VariableAttributes, Variant, VariantType, ObjectAttributes
from common import instantiate
def _parse_nodeid_qname(*args):
try:
if isinstance(args[0], int):
nodeid = NodeId(0, int(args[0]))
qname = QualifiedName(args[1], int(args[0]))
return nodeid, qname
if isinstance(args[0], NodeId):
nodeid = args[0]
elif isinstance(args[0], str):
nodeid = NodeId.from_string(args[0])
else:
raise RuntimeError()
if isinstance(args[1], QualifiedName):
qname = args[1]
elif isinstance(args[1], str):
qname = QualifiedName.from_string(args[1])
else:
raise RuntimeError()
return nodeid, qname
except Exception as ex:
raise TypeError(
"This method takes either a namespace index and a string as argument or a nodeid and a qualifiedname. Received arguments {0} and got exception {1}".format(
args, ex))
def create_object(parent, nodeid, bname, objecttype=None):
nodeid, qname = _parse_nodeid_qname(nodeid, bname)
if objecttype is not None:
objecttype = node.Node(parent.server, objecttype)
dname = LocalizedText(qname.Name)
nodes = instantiate.instantiate(parent, objecttype, nodeid, bname=qname, dname=dname)[0]
return nodes
else:
return node.Node(parent.server,
_create_object(parent.server, parent.nodeid, nodeid, qname, ObjectIds.BaseObjectType))
def create_variable(parent, nodeid, bname, val, varianttype=None, datatype=None):
nodeid, qname = _parse_nodeid_qname(nodeid, bname)
var = Variant(val, varianttype)
if datatype and isinstance(datatype, int):
datatype = NodeId(datatype, 0)
if datatype and not isinstance(datatype, NodeId):
raise RuntimeError("datatype argument must be a nodeid or an int refering to a nodeid")
return node.Node(parent.server,
_create_variable(parent.server, parent.nodeid, nodeid, qname, var, datatype=datatype,
isproperty=False))
def _create_variable(server, parentnodeid, nodeid, qname, var, datatype=None, isproperty=False):
addnode = AddNodesItem()
addnode.RequestedNewNodeId = nodeid
addnode.BrowseName = qname
addnode.NodeClass = NodeClass.Variable
addnode.ParentNodeId = parentnodeid
if isproperty:
addnode.ReferenceTypeId = NodeId(ObjectIds.HasProperty)
addnode.TypeDefinition = NodeId(ObjectIds.PropertyType)
else:
addnode.ReferenceTypeId = NodeId(ObjectIds.HasComponent)
addnode.TypeDefinition = NodeId(ObjectIds.BaseDataVariableType)
attrs = VariableAttributes()
attrs.Description = LocalizedText(qname.Name)
attrs.DisplayName = LocalizedText(qname.Name)
if datatype:
attrs.DataType = datatype
else:
attrs.DataType = _guess_datatype(var)
attrs.Value = var
if not isinstance(var.Value, (list, tuple)):
attrs.ValueRank = ValueRank.Scalar
else:
if var.Dimensions:
attrs.ValueRank = len(var.Dimensions)
attrs.ArrayDimensions = var.Dimensions
attrs.WriteMask = 0
attrs.UserWriteMask = 0
attrs.Historizing = False
attrs.AccessLevel = AccessLevel.CurrentRead.mask
attrs.UserAccessLevel = AccessLevel.CurrentRead.mask
addnode.NodeAttributes = attrs
results = server.add_nodes([addnode])
results[0].StatusCode.check()
return results[0].AddedNodeId
def _create_object(server, parentnodeid, nodeid, qname, objecttype):
addnode = AddNodesItem()
addnode.RequestedNewNodeId = nodeid
addnode.BrowseName = qname
addnode.ParentNodeId = parentnodeid
if node.Node(server, parentnodeid).get_type_definition() == NodeId(ObjectIds.FolderType):
addnode.ReferenceTypeId = NodeId(ObjectIds.Organizes)
else:
addnode.ReferenceTypeId = NodeId(ObjectIds.HasComponent)
addnode.NodeClass = NodeClass.Object
if isinstance(objecttype, int):
addnode.TypeDefinition = NodeId(objecttype)
else:
addnode.TypeDefinition = objecttype
attrs = ObjectAttributes()
attrs.EventNotifier = 0
attrs.Description = LocalizedText(qname.Name)
attrs.DisplayName = LocalizedText(qname.Name)
attrs.WriteMask = 0
attrs.UserWriteMask = 0
addnode.NodeAttributes = attrs
results = server.add_nodes([addnode])
results[0].StatusCode.check()
return results[0].AddedNodeId
def _guess_datatype(variant):
if variant.VariantType == VariantType.ExtensionObject:
if variant.Value is None:
raise Exception("Cannot guess DataType from Null ExtensionObject")
if type(variant.Value) in (list, tuple):
if len(variant.Value) == 0:
raise Exception("Cannot guess DataType from Null ExtensionObject")
extobj = variant.Value[0]
else:
extobj = variant.Value
classname = extobj.__class__.__name__
return NodeId(getattr(ObjectIds, classname))
else:
return NodeId(getattr(ObjectIds, variant.VariantType.name))
from KL.constants import ObjectIds
from KL.types import *
from KL.attribute_ids import AttributeIds
from datetime import datetime
from KL.application_protocol import ReadValueId, ReadParameters, BrowseDirection, NodeClass, BrowseNextParameters, \
BrowseDescription, BrowseParameters, BrowseResultMask
from common import manage_nodes
def _to_nodeid(nodeid):
if isinstance(nodeid, int):
return TwoByteNodeId(nodeid)
elif isinstance(nodeid, Node):
return nodeid.nodeid
elif isinstance(nodeid, NodeId):
return nodeid
elif type(nodeid) in (str, bytes):
return NodeId.from_string(nodeid)
else:
raise Exception("Could not resolve '{0}' to a type id".format(nodeid))
class Node(object):
"""
High level node object, to access node attribute,
browse and populate address space.
Node objects are usefull as-is but they do not expose the entire
OPC-UA protocol. Feel free to look at the code of this class and call
directly UA services methods to optimize your code
"""
def __init__(self, server, nodeid):
self.server = server
self.nodeid = None
if isinstance(nodeid, Node):
self.nodeid = nodeid.nodeid
elif isinstance(nodeid, NodeId):
self.nodeid = nodeid
elif type(nodeid) in (str, bytes):
self.nodeid = NodeId.from_string(nodeid)
elif isinstance(nodeid, int):
self.nodeid = NodeId(nodeid, 0)
else:
raise Exception(
"argument to node must be a NodeId object or a string defining a nodeid found {0} of type {1}".format(
nodeid, type(nodeid)))
self.basenodeid = None
def __eq__(self, other):
if isinstance(other, Node) and self.nodeid == other.nodeid:
return True
return False
def __ne__(self, other):
return not self.__eq__(other)
def __str__(self):
return self.nodeid.to_string()
def __repr__(self):
return "Node({0})".format(self.nodeid)
def __hash__(self):
return self.nodeid.__hash__()
def set_value(self, value, varianttype=None):
datavalue = None
if isinstance(value, DataValue):
datavalue = value
elif isinstance(value, Variant):
datavalue = DataValue(value)
datavalue.SourceTimestamp = datetime.utcnow()
else:
datavalue = DataValue(Variant(value, varianttype))
datavalue.SourceTimestamp = datetime.utcnow()
self.set_attribute(AttributeIds.Value, datavalue)
set_data_value = set_value
def get_value(self):
"""
Get value of a node as a python type. Only variables ( and properties) have values.
An exception will be generated for other node types.
WARNING: on server side, this function returns a ref to object in ua database. Do not modify it if it is a mutable
object unless you know what you are doing
"""
result = self.get_data_value()
return result.Value.Value
def set_attribute(self, attributeid, datavalue):
"""
Set an attribute of a node
attributeid is a member of AttributeIds
datavalue is a DataValue object
"""
attr = WriteValue()
attr.NodeId = self.nodeid
attr.AttributeId = attributeid
attr.Value = datavalue
params = WriteParameters()
params.NodesToWrite = [attr]
result = self.server.write(params)
result[0].check()
def get_data_value(self):
"""
Get value of a node as a DataValue object. Only variables (and properties) have values.
An exception will be generated for other node types.
DataValue contain a variable value as a variant as well as server and source timestamps
"""
return self.get_attribute(AttributeIds.Value)
def get_attribute(self, attr):
"""
Read one attribute of a node
result code from server is checked and an exception is raised in case of error
"""
rv = ReadValueId()
rv.NodeId = self.nodeid
rv.AttributeId = attr
params = ReadParameters()
params.NodesToRead.append(rv)
result = self.server.read(params)
result[0].StatusCode.check()
return result[0]
def add_object(self, nodeid, bname, objecttype=None):
return manage_nodes.create_object(self, nodeid, bname, objecttype)
def add_variable(self, nodeid, bname, val, varianttype=None, datatype=None):
return manage_nodes.create_variable(self, nodeid, bname, val, varianttype, datatype)
def get_type_definition(self):
references = self.get_references(refs=ObjectIds.HasTypeDefinition, direction=BrowseDirection.Forward)
if len(references) == 0:
return None
return references[0].NodeId
def get_references(self, refs=ObjectIds.References, direction=BrowseDirection.Both,
nodeclassmask=NodeClass.Unspecified, includesubtypes=True):
desc = BrowseDescription()
desc.BrowseDirection = direction
desc.ReferenceTypeId = _to_nodeid(refs)
desc.IncludeSubtypes = includesubtypes
desc.NodeClassMask = nodeclassmask
desc.ResultMask = BrowseResultMask.All
desc.NodeId = self.nodeid
params = BrowseParameters()
params.View.Timestamp = get_win_epoch()
params.NodesToBrowse.append(desc)
params.RequestedMaxReferencesPerNode = 0
results = self.server.browse(params)
references = self._browse_next(results)
return references
def _browse_next(self, results):
references = results[0].References
while results[0].ContinuationPoint:
params = BrowseNextParameters()
params.ContinuationPoints = [results[0].ContinuationPoint]
params.ReleaseContinuationPoints = False
results = self.server.browse_next(params)
references.extend(results[0].References)
return references
def get_referenced_nodes(self, refs=ObjectIds.References, direction=BrowseDirection.Both,
nodeclassmask=NodeClass.Unspecified, includesubtypes=True):
"""
returns referenced nodes based on specific filter
Paramters are the same as for get_references
"""
references = self.get_references(refs, direction, nodeclassmask, includesubtypes)
nodes = []
for desc in references:
node = Node(self.server, desc.NodeId)
nodes.append(node)
return nodes
def get_children_descriptions(self, refs=ObjectIds.HierarchicalReferences, nodeclassmask=NodeClass.Unspecified,
includesubtypes=True):
return self.get_references(refs, BrowseDirection.Forward, nodeclassmask, includesubtypes)
import asyncio
import logging
import os
from concurrent.futures import Future
import functools
import threading
from socket import error as SocketError
from KL.constants import ObjectIds
from KL.application_protocol import BrowseDirection
class Buffer(object):
"""
alternative to io.BytesIO making debug easier
and added a few conveniance methods
"""
def __init__(self, data, start_pos=0, size=-1):
# self.logger = logging.getLogger(__name__)
self._data = data
self._cur_pos = start_pos
if size == -1:
size = len(data) - start_pos
self._size = size
def __str__(self):
return "Buffer(size:{0}, data:{1})".format(
self._size,
self._data[self._cur_pos:self._cur_pos + self._size])
__repr__ = __str__
def __len__(self):
return self._size
def read(self, size):
"""
read and pop number of bytes for buffer
"""
if size > self._size:
raise Exception("Not enough data left in buffer, request for {0}, we have {1}".format(size, self))
# self.logger.debug("Request for %s bytes, from %s", size, self)
self._size -= size
pos = self._cur_pos
self._cur_pos += size
data = self._data[pos:self._cur_pos]
# self.logger.debug("Returning: %s ", data)
return data
def copy(self, size=-1):
"""
return a shadow copy, optionnaly only copy 'size' bytes
"""
if size == -1 or size > self._size:
size = self._size
return Buffer(self._data, self._cur_pos, size)
def skip(self, size):
"""
skip size bytes in buffer
"""
if size > self._size:
raise Exception("Not enough data left in buffer, request for {0}, we have {1}".format(size, self))
self._size -= size
self._cur_pos += size
class ThreadLoop(threading.Thread):
"""
run an asyncio loop in a thread
"""
def __init__(self):
threading.Thread.__init__(self)
self.logger = logging.getLogger(__name__)
self.loop = None
self._cond = threading.Condition()
def start(self):
with self._cond:
threading.Thread.start(self)
self._cond.wait()
def run(self):
self.logger.debug("Starting subscription thread")
self.loop = asyncio.new_event_loop()
asyncio.set_event_loop(self.loop)
with self._cond:
self._cond.notify_all()
self.loop.run_forever()
self.logger.debug("subscription thread ended")
def create_server(self, proto, hostname, port):
return self.loop.create_server(proto, hostname, port)
def stop(self):
"""
stop subscription loop, thus the subscription thread
"""
self.loop.call_soon_threadsafe(self.loop.stop)
def close(self):
self.loop.close()
self.loop = None
def call_soon(self, callback):
self.loop.call_soon_threadsafe(callback)
def call_later(self, delay, callback):
"""
threadsafe call_later from asyncio
"""
p = functools.partial(self.loop.call_later, delay, callback)
self.loop.call_soon_threadsafe(p)
def _create_task(self, future, coro, cb=None):
# task = self.loop.create_task(coro)
task = asyncio.ensure_future(coro, loop=self.loop)
if cb:
task.add_done_callback(cb)
future.set_result(task)
def create_task(self, coro, cb=None):
"""
threadsafe create_task from asyncio
"""
future = Future()
p = functools.partial(self._create_task, future, coro, cb)
self.loop.call_soon_threadsafe(p)
return future.result()
def run_coro_and_wait(self, coro):
cond = threading.Condition()
def cb(_):
with cond:
cond.notify_all()
with cond:
task = self.create_task(coro, cb)
cond.wait()
return task.result()
def _run_until_complete(self, future, coro):
task = self.loop.run_until_complete(coro)
future.set_result(task)
def run_until_complete(self, coro):
"""
threadsafe run_until_completed from asyncio
"""
future = Future()
p = functools.partial(self._run_until_complete, future, coro)
self.loop.call_soon_threadsafe(p)
return future.result()
def create_nonce(size=32):
return os.urandom(size)
def get_node_supertypes(node, includeitself=False, skipbase=True):
parents = []
if includeitself:
parents.append(node)
parents.extend(_get_node_supertypes(node))
if skipbase and len(parents) > 1:
parents = parents[:-1]
return parents
def _get_node_supertypes(node):
"""
recursive implementation of get_node_derived_from_types
"""
basetypes = []
parent = get_node_supertype(node)
if parent:
basetypes.append(parent)
basetypes.extend(_get_node_supertypes(parent))
return basetypes
def get_node_supertype(node):
"""
return node supertype or None
"""
supertypes = node.get_referenced_nodes(refs=ObjectIds.HasSubtype,
direction=BrowseDirection.Inverse,
includesubtypes=True)
if supertypes:
return supertypes[0]
else:
return None
def is_child_present(node, browsename):
"""
return if a browsename is present a child from the provide node
:param node: node wherein to find the browsename
:param browsename: browsename to search
:returns returne True if the browsename is present else False
"""
child_descs = node.get_children_descriptions()
for child_desc in child_descs:
if child_desc.BrowseName == browsename:
return True
return False
\ No newline at end of file
import random
import time
import logging
from mainserver.server import Server
# try:
# from urllib.parse import urlparse, urljoin
# except ImportError:
# from urlparse import urlparse
logging.basicConfig(level=logging.INFO)
_logger = logging.getLogger('opcua')
if __name__ == '__main__':
# setup our server
server = Server()
print("Server configured")
server.start()
server.set_endpoint('opc.tcp://localhost:4841/opcua/')
print("Server Started")
idx = server.register_namespace("mynamespace")
# populating our address space
# server.nodes, contains links to very common nodes like objects and root
obj_vplc = server.nodes.objects.add_object(idx, 'vPLC')
var_temperature = obj_vplc.add_variable(idx, 'temperature', 0)
var_pressure = obj_vplc.add_variable(idx, 'pressure', 0)
var_pumpsetting = obj_vplc.add_variable(idx, 'pumpsetting', 0)
# _logger.info("starting server...")
server.start()
# run forever every 5 secs
try:
# def update_value():
while True:
# Writing Variables
var_temperature.set_value(random.randint(25, 35))
var_pressure.set_value(random.randint(55, 75))
var_pumpsetting.set_value(random.randint(0, 1))
time.sleep(5)
# sub = server.create_subscription(1, update_value())
# sub.subscribe_data_change(var_temperature)
finally:
server.stop()
import logging
import asyncio
import threading
from struct import unpack
from common import utils
from KL import hand_protocol
from mainserver.processor import Processor
logger = logging.getLogger(__name__)
def header_from_binary(data):
hdr = hand_protocol.Header()
hdr.MessageType, hdr.ChunkType, hdr.packet_size = unpack("<3scI", data.read(8))
hdr.body_size = hdr.packet_size - 8
if hdr.MessageType in (hand_protocol.MessageType.SecureOpen, hand_protocol.MessageType.SecureClose,
hand_protocol.MessageType.SecureMessage):
hdr.body_size -= 4
hdr.ChannelId = unpack("<{:d}I", data)
return hdr
class Protocol(asyncio.Protocol):
iserver = None
loop = None
logger = None
policies = None
clients = None
def __str__(self):
return "Protocol({}, {})".format(self.peername, self.processor.session)
__repr__ = __str__
def connection_made(self, transport):
self.peername = transport.get_extra_info('peername')
self.logger.info('New connection from %s', self.peername)
self.transport = transport
self.processor = Processor(self.iserver, self.transport)
self.processor.set_policies(self.policies)
self.data = b""
self.iserver.asyncio_transports.append(transport)
self.clients.append(self)
def connection_lost(self, ex):
self.logger.info('Lost connection from %s, %s', self.peername, ex)
self.transport.close()
self.iserver.asyncio_transports.remove(self.transport)
self.processor.close()
if self in self.clients:
self.clients.remove(self)
def data_received(self, data):
logger.debug("received %s bytes from socket", len(data))
if self.data:
data = self.data + data
self.data = b""
self._process_data(data)
def _process_data(self, data):
buf = utils.Buffer(data)
while True:
try:
backup_buf = buf.copy()
try:
hdr = header_from_binary(buf)
except Exception:
logger.info("We did not receive enough data from client, waiting for more")
self.data = backup_buf.read(len(backup_buf))
return
if len(buf) < hdr.body_size:
logger.info("We did not receive enough data from client, waiting for more")
self.data = backup_buf.read(len(backup_buf))
return
ret = self.processor.process(hdr, buf)
if not ret:
logger.info("processor returned False, we close connection from %s", self.peername)
self.transport.close()
return
if len(buf) == 0:
return
except Exception:
logger.exception("Exception raised while parsing message from client, closing")
return
class BinaryServer(object):
def __init__(self, internal_server, hostname, port):
self.logger = logging.getLogger(__name__)
self.hostname = hostname
self.port = port
self.iserver = internal_server
self.loop = None
self._server = None
self._policies = []
self.clients = []
def set_policies(self, policies):
self._policies = policies
def set_loop(self, loop):
self.loop = loop
def start(self):
prop = dict(
iserver=self.iserver,
loop=self.loop,
logger=self.logger,
policies=self._policies,
clients=self.clients
)
protocol_factory = type('Protocol', (Protocol,), prop)
coro = self.loop.create_server(protocol_factory, self.hostname, self.port)
self._server = self.loop.run_coro_and_wait(coro)
# get the port and the hostname from the created server socket
# only relevant for dynamic port asignment (when self.port == 0)
if self.port == 0 and len(self._server.sockets) == 1:
# will work for AF_INET and AF_INET6 socket names
# these are to only families supported by the create_server call
sockname = self._server.sockets[0].getsockname()
self.hostname = sockname[0]
self.port = sockname[1]
self.logger.warning('Listening on {0}:{1}'.format(self.hostname, self.port))
def stop(self):
self.logger.info("Closing asyncio socket server")
for transport in self.iserver.asyncio_transports:
transport.close()
if self._server:
self.loop.call_soon(self._server.close)
self.loop.run_coro_and_wait(self._server.wait_closed())
self.loop = None
import collections
import logging
import shelve
from datetime import datetime
from threading import RLock
import pickle
from mainserver.user_manager import UserManager
from KL.status_codes import StatusCodes
from KL.types import *
from KL.application_protocol import NodeClass, ReferenceDescription, AddNodesResult, AddReferencesItem, \
NodeAttributesMask, BrowseResult
from KL.attribute_ids import AttributeIds
from KL.constants import ObjectIds
class AttributeValue(object):
def __init__(self, value):
self.value = value
self.value_callback = None
self.datachange_callbacks = {}
def __str__(self):
return "AttributeValue({0})".format(self.value)
__repr__ = __str__
def test_bit(data, offset):
mask = 1 << offset
return data & mask
class AttributeService(object):
def __init__(self, aspace):
self.logger = logging.getLogger(__name__)
self._aspace = aspace
def read(self, params):
self.logger.debug("read %s", params)
res = []
for readvalue in params.NodesToRead:
res.append(self._aspace.get_attribute_value(readvalue.NodeId, readvalue.AttributeId))
return res
def write(self, params, user=UserManager.User.Admin):
self.logger.debug("write %s as user %s", params, user)
res = []
for writevalue in params.NodesToWrite:
if user != UserManager.User.Admin:
if writevalue.AttributeId != AttributeIds.Value:
res.append(StatusCode(StatusCodes.BadUserAccessDenied))
continue
al = self._aspace.get_attribute_value(writevalue.NodeId, AttributeIds.AccessLevel)
ual = self._aspace.get_attribute_value(writevalue.NodeId, AttributeIds.UserAccessLevel)
if not test_bit(al.Value.Value, AccessLevel.CurrentWrite) or not test_bit(
ual.Value.Value, AccessLevel.CurrentWrite):
res.append(StatusCode(StatusCodes.BadUserAccessDenied))
continue
res.append(self._aspace.set_attribute_value(writevalue.NodeId, writevalue.AttributeId, writevalue.Value))
return res
class ViewService(object):
def __init__(self, aspace):
self.logger = logging.getLogger(__name__)
self._aspace = aspace
def browse(self, params):
self.logger.debug("browse %s", params)
res = []
for desc in params.NodesToBrowse:
res.append(self._browse(desc))
return res
def _browse(self, desc):
res = BrowseResult()
if desc.NodeId not in self._aspace:
res.StatusCode = StatusCode(StatusCodes.BadNodeIdInvalid)
return res
node = self._aspace[desc.NodeId]
for ref in node.references:
if not self._is_suitable_ref(desc, ref):
continue
res.References.append(ref)
return res
def _is_suitable_ref(self, desc, ref):
pass
class NodeData(object):
def __init__(self, nodeid):
self.nodeid = nodeid
self.attributes = {}
self.references = []
self.call = None
def __str__(self):
return "NodeData(id:{0}, attrs:{1}, refs:{2})".format(self.nodeid, self.attributes, self.references)
__repr__ = __str__
class NodeManagementService(object):
def __init__(self, aspace):
self.logger = logging.getLogger(__name__)
self._aspace = aspace
def add_nodes(self, addnodeitems, user=UserManager.User.Admin):
results = []
for item in addnodeitems:
results.append(self._add_node(item, user))
return results
def try_add_nodes(self, addnodeitems, user=UserManager.User.Admin, check=True):
for item in addnodeitems:
ret = self._add_node(item, user, check=check)
if not ret.StatusCode.is_good():
yield item
def _add_node(self, item, user, check=True):
self.logger.debug("Adding node %s %s", item.RequestedNewNodeId, item.BrowseName)
result = AddNodesResult()
if not user == UserManager.User.Admin:
result.StatusCode = StatusCode(StatusCodes.BadUserAccessDenied)
return result
if item.RequestedNewNodeId.has_null_identifier():
# If Identifier of requested NodeId is null we generate a new NodeId using
# the namespace of the nodeid, this is an extention of the spec to allow
# to requests the server to generate a new nodeid in a specified namespace
self.logger.debug("RequestedNewNodeId has null identifier, generating Identifier")
item.RequestedNewNodeId = self._aspace.generate_nodeid(item.RequestedNewNodeId.NamespaceIndex)
else:
if item.RequestedNewNodeId in self._aspace:
self.logger.warning("AddNodesItem: Requested NodeId %s already exists", item.RequestedNewNodeId)
result.StatusCode = StatusCode(StatusCodes.BadNodeIdExists)
return result
if item.ParentNodeId.is_null():
self.logger.info("add_node: while adding node %s, requested parent node is null %s %s",
item.RequestedNewNodeId, item.ParentNodeId, item.ParentNodeId.is_null())
if check:
result.StatusCode = StatusCode(StatusCodes.BadParentNodeIdInvalid)
return result
parentdata = self._aspace.get(item.ParentNodeId)
if parentdata is None and not item.ParentNodeId.is_null():
self.logger.info("add_node: while adding node %s, requested parent node %s does not exists",
item.RequestedNewNodeId, item.ParentNodeId)
result.StatusCode = StatusCode(StatusCodes.BadParentNodeIdInvalid)
return result
nodedata = NodeData(item.RequestedNewNodeId)
self._add_node_attributes(nodedata, item, add_timestamps=check)
# now add our node to db
self._aspace[nodedata.nodeid] = nodedata
if parentdata is not None:
self._add_ref_from_parent(nodedata, item, parentdata)
self._add_ref_to_parent(nodedata, item, parentdata)
# add type definition
if item.TypeDefinition != NodeId():
self._add_type_definition(nodedata, item)
result.StatusCode = StatusCode()
result.AddedNodeId = nodedata.nodeid
return result
def _add_node_attributes(self, nodedata, item, add_timestamps):
# add common attrs
if nodedata.nodeid.Identifier == 2256 or nodedata.nodeid.Identifier == 2255:
print("Found node 2256 or 2255")
nodedata.attributes[AttributeIds.NodeId] = AttributeValue(
DataValue(Variant(nodedata.nodeid, VariantType.NodeId))
)
nodedata.attributes[AttributeIds.BrowseName] = AttributeValue(
DataValue(Variant(item.BrowseName, VariantType.QualifiedName))
)
nodedata.attributes[AttributeIds.NodeClass] = AttributeValue(
DataValue(Variant(item.NodeClass, VariantType.Int32))
)
# add requested attrs
self._add_nodeattributes(item.NodeAttributes, nodedata, add_timestamps)
def _add_unique_reference(self, nodedata, desc):
for r in nodedata.references:
if r.ReferenceTypeId == desc.ReferenceTypeId and r.NodeId == desc.NodeId:
if r.IsForward != desc.IsForward:
self.logger.error("Cannot add conflicting reference %s ", str(desc))
return StatusCode(StatusCodes.BadReferenceNotAllowed)
break # ref already exists
else:
nodedata.references.append(desc)
return StatusCode()
def _add_ref_from_parent(self, nodedata, item, parentdata):
desc = ReferenceDescription()
desc.ReferenceTypeId = item.ReferenceTypeId
desc.NodeId = nodedata.nodeid
desc.NodeClass = item.NodeClass
desc.BrowseName = item.BrowseName
desc.DisplayName = item.NodeAttributes.DisplayName
desc.TypeDefinition = item.TypeDefinition
desc.IsForward = True
self._add_unique_reference(parentdata, desc)
def _add_ref_to_parent(self, nodedata, item, parentdata):
addref = AddReferencesItem()
addref.ReferenceTypeId = item.ReferenceTypeId
addref.SourceNodeId = nodedata.nodeid
addref.TargetNodeId = item.ParentNodeId
addref.TargetNodeClass = parentdata.attributes[AttributeIds.NodeClass].value.Value.Value
addref.IsForward = False
self._add_reference_no_check(nodedata, addref)
def _add_type_definition(self, nodedata, item):
addref = AddReferencesItem()
addref.SourceNodeId = nodedata.nodeid
addref.IsForward = True
addref.ReferenceTypeId = NodeId(ObjectIds.HasTypeDefinition)
addref.TargetNodeId = item.TypeDefinition
addref.TargetNodeClass = NodeClass.DataType
self._add_reference_no_check(nodedata, addref)
def delete_nodes(self, deletenodeitems, user=UserManager.User.Admin):
results = []
for item in deletenodeitems.NodesToDelete:
results.append(self._delete_node(item, user))
return results
def _delete_node(self, item, user):
if user != UserManager.User.Admin:
return StatusCode(StatusCodes.BadUserAccessDenied)
if item.NodeId not in self._aspace:
self.logger.warning("DeleteNodesItem: NodeId %s does not exists", item.NodeId)
return StatusCode(StatusCodes.BadNodeIdUnknown)
if item.DeleteTargetReferences:
for elem in self._aspace.keys():
for rdesc in self._aspace[elem].references[:]:
if rdesc.NodeId == item.NodeId:
self._aspace[elem].references.remove(rdesc)
self._delete_node_callbacks(self._aspace[item.NodeId])
del (self._aspace[item.NodeId])
return StatusCode()
def _delete_node_callbacks(self, nodedata):
if AttributeIds.Value in nodedata.attributes:
for handle, callback in list(nodedata.attributes[AttributeIds.Value].datachange_callbacks.items()):
try:
callback(handle, None, StatusCode(StatusCodes.BadNodeIdUnknown))
self._aspace.delete_datachange_callback(handle)
except Exception as ex:
self.logger.exception("Error calling delete node callback callback %s, %s, %s", nodedata,
AttributeIds.Value, ex)
def add_references(self, refs, user=UserManager.User.Admin):
result = []
for ref in refs:
result.append(self._add_reference(ref, user))
return result
def try_add_references(self, refs, user=UserManager.User.Admin):
for ref in refs:
if not self._add_reference(ref, user).is_good():
yield ref
def _add_reference(self, addref, user):
sourcedata = self._aspace.get(addref.SourceNodeId)
if sourcedata is None:
return StatusCode(StatusCodes.BadSourceNodeIdInvalid)
if addref.TargetNodeId not in self._aspace:
return StatusCode(StatusCodes.BadTargetNodeIdInvalid)
if user != UserManager.User.Admin:
return StatusCode(StatusCodes.BadUserAccessDenied)
return self._add_reference_no_check(sourcedata, addref)
def _add_reference_no_check(self, sourcedata, addref):
rdesc = ReferenceDescription()
rdesc.ReferenceTypeId = addref.ReferenceTypeId
rdesc.IsForward = addref.IsForward
rdesc.NodeId = addref.TargetNodeId
if addref.TargetNodeClass == NodeClass.Unspecified:
rdesc.NodeClass = self._aspace.get_attribute_value(addref.TargetNodeId, AttributeIds.NodeClass).Value.Value
else:
rdesc.NodeClass = addref.TargetNodeClass
bname = self._aspace.get_attribute_value(addref.TargetNodeId, AttributeIds.BrowseName).Value.Value
if bname:
rdesc.BrowseName = bname
dname = self._aspace.get_attribute_value(addref.TargetNodeId, AttributeIds.DisplayName).Value.Value
if dname:
rdesc.DisplayName = dname
return self._add_unique_reference(sourcedata, rdesc)
def delete_references(self, refs, user=UserManager.User.Admin):
result = []
for ref in refs:
result.append(self._delete_reference(ref, user))
return result
def _delete_unique_reference(self, item, invert=False):
if invert:
source, target, forward = item.TargetNodeId, item.SourceNodeId, not item.IsForward
else:
source, target, forward = item.SourceNodeId, item.TargetNodeId, item.IsForward
for rdesc in self._aspace[source].references:
if rdesc.NodeId == target and rdesc.ReferenceTypeId == item.ReferenceTypeId:
if rdesc.IsForward == forward:
self._aspace[source].references.remove(rdesc)
return StatusCode()
return StatusCode(StatusCodes.BadNotFound)
def _delete_reference(self, item, user):
if item.SourceNodeId not in self._aspace:
return StatusCode(StatusCodes.BadSourceNodeIdInvalid)
if item.TargetNodeId not in self._aspace:
return StatusCode(StatusCodes.BadTargetNodeIdInvalid)
if item.ReferenceTypeId not in self._aspace:
return StatusCode(StatusCodes.BadReferenceTypeIdInvalid)
if user != UserManager.User.Admin:
return StatusCode(StatusCodes.BadUserAccessDenied)
if item.DeleteBidirectional:
self._delete_unique_reference(item, True)
return self._delete_unique_reference(item)
def _add_node_attr(self, item, nodedata, name, vtype=None, add_timestamps=False):
if name == 'Value' and (nodedata.nodeid.Identifier == 2255 or nodedata.nodeid.Identifier == 11705 or
nodedata.nodeid.Identifier == 2254 or nodedata.nodeid.Identifier == 2259 or
nodedata.nodeid.Identifier == 2257 or nodedata.nodeid.Identifier == 2258 or
nodedata.nodeid.Identifier == 2256):
item.SpecifiedAttributes = 4002419
if item.SpecifiedAttributes & getattr(NodeAttributesMask, name):
dv = DataValue(Variant(getattr(item, name), vtype))
if add_timestamps:
# dv.ServerTimestamp = datetime.utcnow() # Disabled until someone explains us it should be there
dv.SourceTimestamp = datetime.utcnow()
nodedata.attributes[getattr(AttributeIds, name)] = AttributeValue(dv)
def _add_nodeattributes(self, item, nodedata, add_timestamps):
self._add_node_attr(item, nodedata, "AccessLevel", VariantType.Byte)
self._add_node_attr(item, nodedata, "ArrayDimensions", VariantType.UInt32)
self._add_node_attr(item, nodedata, "BrowseName", VariantType.QualifiedName)
self._add_node_attr(item, nodedata, "ContainsNoLoops", VariantType.Boolean)
self._add_node_attr(item, nodedata, "DataType", VariantType.NodeId)
self._add_node_attr(item, nodedata, "Description", VariantType.LocalizedText)
self._add_node_attr(item, nodedata, "DisplayName", VariantType.LocalizedText)
self._add_node_attr(item, nodedata, "EventNotifier", VariantType.Byte)
self._add_node_attr(item, nodedata, "Executable", VariantType.Boolean)
self._add_node_attr(item, nodedata, "Historizing", VariantType.Boolean)
self._add_node_attr(item, nodedata, "InverseName", VariantType.LocalizedText)
self._add_node_attr(item, nodedata, "IsAbstract", VariantType.Boolean)
self._add_node_attr(item, nodedata, "MinimumSamplingInterval", VariantType.Double)
self._add_node_attr(item, nodedata, "NodeClass", VariantType.Int32)
self._add_node_attr(item, nodedata, "NodeId", VariantType.NodeId)
self._add_node_attr(item, nodedata, "Symmetric", VariantType.Boolean)
self._add_node_attr(item, nodedata, "UserAccessLevel", VariantType.Byte)
self._add_node_attr(item, nodedata, "UserExecutable", VariantType.Boolean)
self._add_node_attr(item, nodedata, "UserWriteMask", VariantType.Byte)
self._add_node_attr(item, nodedata, "ValueRank", VariantType.Int32)
self._add_node_attr(item, nodedata, "WriteMask", VariantType.UInt32)
self._add_node_attr(item, nodedata, "UserWriteMask", VariantType.UInt32)
self._add_node_attr(item, nodedata, "Value", add_timestamps=add_timestamps)
class MethodService(object):
def __init__(self, aspace):
self.logger = logging.getLogger(__name__)
self._aspace = aspace
class AddressSpace(object):
"""
The address space object stores all the nodes of the OPC-UA server
and helper methods.
The methods are thread safe
"""
def __init__(self):
self.logger = logging.getLogger(__name__)
self._nodes = {}
self._lock = RLock() # FIXME: should use multiple reader, one writter pattern
self._datachange_callback_counter = 200
self._handle_to_attribute_map = {}
self._default_idx = 2
self._nodeid_counter = {0: 20000, 1: 2000}
def __getitem__(self, nodeid):
with self._lock:
return self._nodes.__getitem__(nodeid)
def get(self, nodeid):
with self._lock:
return self._nodes.get(nodeid, None)
def __setitem__(self, nodeid, value):
with self._lock:
return self._nodes.__setitem__(nodeid, value)
def __contains__(self, nodeid):
with self._lock:
return self._nodes.__contains__(nodeid)
def __delitem__(self, nodeid):
with self._lock:
self._nodes.__delitem__(nodeid)
def generate_nodeid(self, idx=None):
if idx is None:
idx = self._default_idx
if idx in self._nodeid_counter:
self._nodeid_counter[idx] += 1
else:
# get the biggest identifier number from the existed nodes in address space
identifier_list = sorted([nodeid.Identifier for nodeid in self._nodes.keys()
if nodeid.NamespaceIndex == idx and nodeid.NodeIdType
in (NodeIdType.Numeric, NodeIdType.TwoByte, NodeIdType.FourByte)])
if identifier_list:
self._nodeid_counter[idx] = identifier_list[-1]
else:
self._nodeid_counter[idx] = 1
nodeid = NodeId(self._nodeid_counter[idx], idx)
with self._lock: # OK since reentrant lock
while True:
if nodeid in self._nodes:
nodeid = self.generate_nodeid(idx)
else:
return nodeid
def load_aspace_shelf(self, path):
"""
Load the standard address space nodes from a python shelve via LazyLoadingDict as needed.
The dump() method can no longer be used if the address space is being loaded from a shelf
Note: Intended for slow devices, such as Raspberry Pi, to greatly improve start up time
"""
class LazyLoadingDict(collections.MutableMapping):
"""
Special dict that only loads nodes as they are accessed. If a node is accessed it gets copied from the
shelve to the cache dict. All user nodes are saved in the cache ONLY. Saving data back to the shelf
is currently NOT supported
"""
def __init__(self, source):
self.source = source # python shelf
self.cache = {} # internal dict
def __getitem__(self, key):
# try to get the item (node) from the cache, if it isn't there get it from the shelf
try:
return self.cache[key]
except KeyError:
node = self.cache[key] = self.source[key.to_string()]
return node
def __setitem__(self, key, value):
# add a new item to the cache; if this item is in the shelf it is not updated
self.cache[key] = value
def __contains__(self, key):
return key in self.cache or key.to_string() in self.source
def __delitem__(self, key):
# only deleting items from the cache is allowed
del self.cache[key]
def __iter__(self):
# only the cache can be iterated over
return iter(self.cache.keys())
def __len__(self):
# only returns the length of items in the cache, not unaccessed items in the shelf
return len(self.cache)
self._nodes = LazyLoadingDict(shelve.open(path, "r"))
def make_aspace_shelf(self, path):
"""
Make a shelf for containing the nodes from the standard address space; this is typically only done on first
start of the server. Subsequent server starts will load the shelf, nodes are then moved to a cache
by the LazyLoadingDict class when they are accessed. Saving data back to the shelf
is currently NOT supported, it is only used for the default OPC UA standard address space
Note: Intended for slow devices, such as Raspberry Pi, to greatly improve start up time
"""
s = shelve.open(path, "n", protocol=pickle.HIGHEST_PROTOCOL)
for nodeid, ndata in self._nodes.items():
s[nodeid.to_string()] = ndata
s.close()
def get_attribute_value(self, nodeid, attr):
with self._lock:
self.logger.debug("get attr val: %s %s", nodeid, attr)
if nodeid not in self._nodes:
dv = DataValue()
dv.StatusCode = StatusCode(StatusCodes.BadNodeIdUnknown)
return dv
node = self._nodes[nodeid]
if attr not in node.attributes:
self.logger.warning("Tried to read attribute '%s' in %s, but the attribute is missing", attr, nodeid)
dv = DataValue()
dv.StatusCode = StatusCode(StatusCodes.BadAttributeIdInvalid)
return dv
attval = node.attributes[attr]
if attval.value_callback:
return attval.value_callback()
return attval.value
def set_attribute_value(self, nodeid, attr, value):
with self._lock:
self.logger.debug("set attr val: %s %s %s", nodeid, attr, value)
node = self._nodes.get(nodeid, None)
if node is None:
return StatusCode(StatusCodes.BadNodeIdUnknown)
attval = node.attributes.get(attr, None)
if attval is None:
self.logger.warning("Tried to write attribute '%s' in %s, but the attribute is missing", attr, nodeid)
return StatusCode(StatusCodes.BadAttributeIdInvalid)
old = attval.value
attval.value = value
cbs = []
if old.Value != value.Value: # only send call callback when a value change has happend
cbs = list(attval.datachange_callbacks.items())
for k, v in cbs:
try:
v(k, value)
except Exception as ex:
self.logger.exception("Error calling datachange callback %s, %s, %s", k, v, ex)
return StatusCode()
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
from KL.constants import ObjectIds
from KL.types import NumericNodeId, QualifiedName, NodeId, Variant, VariantType
from KL.application_protocol import NodeClass, LocalizedText, ObjectTypeAttributes, \
AddNodesItem, AddReferencesItem, ReferenceTypeAttributes, VariableAttributes, ObjectAttributes, DataTypeAttributes, EnumValueType
from KL import constants
def create_standard_address_space_Part13(server):
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(11187, 0)
node.BrowseName = QualifiedName('AggregateConfigurationType', 0)
node.NodeClass = NodeClass.ObjectType
node.ParentNodeId = NumericNodeId(58, 0)
node.ReferenceTypeId = NumericNodeId(45, 0)
attrs = ObjectTypeAttributes()
attrs.DisplayName = LocalizedText("AggregateConfigurationType")
attrs.IsAbstract = False
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(11187, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(11188, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(11187, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(11189, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(11187, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(11190, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(11187, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(11191, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(45, 0)
ref.SourceNodeId = NumericNodeId(11187, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(58, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(11188, 0)
node.BrowseName = QualifiedName('TreatUncertainAsBad', 0)
node.NodeClass = NodeClass.Variable
node.ParentNodeId = NumericNodeId(11187, 0)
node.ReferenceTypeId = NumericNodeId(46, 0)
node.TypeDefinition = NumericNodeId(68, 0)
attrs = VariableAttributes()
attrs.DisplayName = LocalizedText("TreatUncertainAsBad")
attrs.DataType = NodeId(ObjectIds.Boolean)
attrs.ValueRank = -1
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(11188, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(68, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(37, 0)
ref.SourceNodeId = NumericNodeId(11188, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(78, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(11188, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(11187, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(11189, 0)
node.BrowseName = QualifiedName('PercentDataBad', 0)
node.NodeClass = NodeClass.Variable
node.ParentNodeId = NumericNodeId(11187, 0)
node.ReferenceTypeId = NumericNodeId(46, 0)
node.TypeDefinition = NumericNodeId(68, 0)
attrs = VariableAttributes()
attrs.DisplayName = LocalizedText("PercentDataBad")
attrs.DataType = NodeId(ObjectIds.Byte)
attrs.ValueRank = -1
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(11189, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(68, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(37, 0)
ref.SourceNodeId = NumericNodeId(11189, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(78, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(11189, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(11187, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(11190, 0)
node.BrowseName = QualifiedName('PercentDataGood', 0)
node.NodeClass = NodeClass.Variable
node.ParentNodeId = NumericNodeId(11187, 0)
node.ReferenceTypeId = NumericNodeId(46, 0)
node.TypeDefinition = NumericNodeId(68, 0)
attrs = VariableAttributes()
attrs.DisplayName = LocalizedText("PercentDataGood")
attrs.DataType = NodeId(ObjectIds.Byte)
attrs.ValueRank = -1
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(11190, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(68, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(37, 0)
ref.SourceNodeId = NumericNodeId(11190, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(78, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(11190, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(11187, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(11191, 0)
node.BrowseName = QualifiedName('UseSlopedExtrapolation', 0)
node.NodeClass = NodeClass.Variable
node.ParentNodeId = NumericNodeId(11187, 0)
node.ReferenceTypeId = NumericNodeId(46, 0)
node.TypeDefinition = NumericNodeId(68, 0)
attrs = VariableAttributes()
attrs.DisplayName = LocalizedText("UseSlopedExtrapolation")
attrs.DataType = NodeId(ObjectIds.Boolean)
attrs.ValueRank = -1
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(11191, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(68, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(37, 0)
ref.SourceNodeId = NumericNodeId(11191, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(78, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(11191, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(11187, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(2341, 0)
node.BrowseName = QualifiedName('Interpolative', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("Interpolative")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(2341, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(2342, 0)
node.BrowseName = QualifiedName('Average', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("Average")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(2342, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(2343, 0)
node.BrowseName = QualifiedName('TimeAverage', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("TimeAverage")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(2343, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(11285, 0)
node.BrowseName = QualifiedName('TimeAverage2', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("TimeAverage2")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(11285, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(2344, 0)
node.BrowseName = QualifiedName('Total', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("Total")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(2344, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(11304, 0)
node.BrowseName = QualifiedName('Total2', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("Total2")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(11304, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(2346, 0)
node.BrowseName = QualifiedName('Minimum', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("Minimum")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(2346, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(2347, 0)
node.BrowseName = QualifiedName('Maximum', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("Maximum")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(2347, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(2348, 0)
node.BrowseName = QualifiedName('MinimumActualTime', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("MinimumActualTime")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(2348, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(2349, 0)
node.BrowseName = QualifiedName('MaximumActualTime', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("MaximumActualTime")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(2349, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(2350, 0)
node.BrowseName = QualifiedName('Range', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("Range")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(2350, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(11286, 0)
node.BrowseName = QualifiedName('Minimum2', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("Minimum2")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(11286, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(11287, 0)
node.BrowseName = QualifiedName('Maximum2', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("Maximum2")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(11287, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(11305, 0)
node.BrowseName = QualifiedName('MinimumActualTime2', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("MinimumActualTime2")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(11305, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(11306, 0)
node.BrowseName = QualifiedName('MaximumActualTime2', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("MaximumActualTime2")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(11306, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(11288, 0)
node.BrowseName = QualifiedName('Range2', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("Range2")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(11288, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(2351, 0)
node.BrowseName = QualifiedName('AnnotationCount', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("AnnotationCount")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(2351, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(2352, 0)
node.BrowseName = QualifiedName('Count', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("Count")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(2352, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(11307, 0)
node.BrowseName = QualifiedName('DurationInStateZero', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("DurationInStateZero")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(11307, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(11308, 0)
node.BrowseName = QualifiedName('DurationInStateNonZero', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("DurationInStateNonZero")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(11308, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(2355, 0)
node.BrowseName = QualifiedName('NumberOfTransitions', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("NumberOfTransitions")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(2355, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(2357, 0)
node.BrowseName = QualifiedName('Start', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("Start")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(2357, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(2358, 0)
node.BrowseName = QualifiedName('End', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("End")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(2358, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(2359, 0)
node.BrowseName = QualifiedName('Delta', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("Delta")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(2359, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(11505, 0)
node.BrowseName = QualifiedName('StartBound', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("StartBound")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(11505, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(11506, 0)
node.BrowseName = QualifiedName('EndBound', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("EndBound")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(11506, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(11507, 0)
node.BrowseName = QualifiedName('DeltaBounds', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("DeltaBounds")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(11507, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(2360, 0)
node.BrowseName = QualifiedName('DurationGood', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("DurationGood")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(2360, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(2361, 0)
node.BrowseName = QualifiedName('DurationBad', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("DurationBad")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(2361, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(2362, 0)
node.BrowseName = QualifiedName('PercentGood', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("PercentGood")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(2362, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(2363, 0)
node.BrowseName = QualifiedName('PercentBad', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("PercentBad")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(2363, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(2364, 0)
node.BrowseName = QualifiedName('WorstQuality', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("WorstQuality")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(2364, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(11292, 0)
node.BrowseName = QualifiedName('WorstQuality2', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("WorstQuality2")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(11292, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(11426, 0)
node.BrowseName = QualifiedName('StandardDeviationSample', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("StandardDeviationSample")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(11426, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(11427, 0)
node.BrowseName = QualifiedName('StandardDeviationPopulation', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("StandardDeviationPopulation")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(11427, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(11428, 0)
node.BrowseName = QualifiedName('VarianceSample', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("VarianceSample")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(11428, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(11429, 0)
node.BrowseName = QualifiedName('VariancePopulation', 0)
node.NodeClass = NodeClass.Object
node.TypeDefinition = NumericNodeId(2340, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("VariancePopulation")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(11429, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2340, 0)
refs.append(ref)
server.add_references(refs)
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
from KL.constants import ObjectIds
from KL.types import NumericNodeId, QualifiedName, NodeId, Variant, VariantType
from KL.application_protocol import NodeClass, LocalizedText, ObjectTypeAttributes, \
AddNodesItem, AddReferencesItem, ReferenceTypeAttributes, VariableAttributes, ObjectAttributes, DataTypeAttributes, VariableTypeAttributes, EnumValueType
from KL import constants
def create_standard_address_space_Part8(server):
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(2365, 0)
node.BrowseName = QualifiedName('DataItemType', 0)
node.NodeClass = NodeClass.VariableType
node.ParentNodeId = NumericNodeId(63, 0)
node.ReferenceTypeId = NumericNodeId(45, 0)
attrs = VariableTypeAttributes()
attrs.DisplayName = LocalizedText("DataItemType")
attrs.DisplayName = LocalizedText("DataItemType")
attrs.DataType = NodeId(ObjectIds.String)
attrs.ValueRank = -2
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(2365, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2366, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(2365, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2367, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(45, 0)
ref.SourceNodeId = NumericNodeId(2365, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(63, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(2366, 0)
node.BrowseName = QualifiedName('Definition', 0)
node.NodeClass = NodeClass.Variable
node.ParentNodeId = NumericNodeId(2365, 0)
node.ReferenceTypeId = NumericNodeId(46, 0)
node.TypeDefinition = NumericNodeId(68, 0)
attrs = VariableAttributes()
attrs.DisplayName = LocalizedText("Definition")
attrs.DataType = NodeId(ObjectIds.String)
attrs.ValueRank = -1
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(2366, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(68, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(37, 0)
ref.SourceNodeId = NumericNodeId(2366, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(80, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(2366, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2365, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(2367, 0)
node.BrowseName = QualifiedName('ValuePrecision', 0)
node.NodeClass = NodeClass.Variable
node.ParentNodeId = NumericNodeId(2365, 0)
node.ReferenceTypeId = NumericNodeId(46, 0)
node.TypeDefinition = NumericNodeId(68, 0)
attrs = VariableAttributes()
attrs.DisplayName = LocalizedText("ValuePrecision")
attrs.DataType = NodeId(ObjectIds.Double)
attrs.ValueRank = -1
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(2367, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(68, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(37, 0)
ref.SourceNodeId = NumericNodeId(2367, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(80, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(2367, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2365, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(15318, 0)
node.BrowseName = QualifiedName('BaseAnalogType', 0)
node.NodeClass = NodeClass.VariableType
node.ParentNodeId = NumericNodeId(2365, 0)
node.ReferenceTypeId = NumericNodeId(45, 0)
attrs = VariableTypeAttributes()
attrs.DisplayName = LocalizedText("BaseAnalogType")
attrs.DisplayName = LocalizedText("BaseAnalogType")
attrs.DataType = NodeId(ObjectIds.Number)
attrs.ValueRank = -2
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(15318, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(17567, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(15318, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(17568, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(15318, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(17569, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(45, 0)
ref.SourceNodeId = NumericNodeId(15318, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2365, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(17567, 0)
node.BrowseName = QualifiedName('InstrumentRange', 0)
node.NodeClass = NodeClass.Variable
node.ParentNodeId = NumericNodeId(15318, 0)
node.ReferenceTypeId = NumericNodeId(46, 0)
node.TypeDefinition = NumericNodeId(68, 0)
attrs = VariableAttributes()
attrs.DisplayName = LocalizedText("InstrumentRange")
attrs.DataType = NumericNodeId(884, 0)
attrs.ValueRank = -1
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(17567, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(68, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(37, 0)
ref.SourceNodeId = NumericNodeId(17567, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(80, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(17567, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(15318, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(17568, 0)
node.BrowseName = QualifiedName('EURange', 0)
node.NodeClass = NodeClass.Variable
node.ParentNodeId = NumericNodeId(15318, 0)
node.ReferenceTypeId = NumericNodeId(46, 0)
node.TypeDefinition = NumericNodeId(68, 0)
attrs = VariableAttributes()
attrs.DisplayName = LocalizedText("EURange")
attrs.DataType = NumericNodeId(884, 0)
attrs.ValueRank = -1
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(17568, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(68, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(37, 0)
ref.SourceNodeId = NumericNodeId(17568, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(80, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(17568, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(15318, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(17569, 0)
node.BrowseName = QualifiedName('EngineeringUnits', 0)
node.NodeClass = NodeClass.Variable
node.ParentNodeId = NumericNodeId(15318, 0)
node.ReferenceTypeId = NumericNodeId(46, 0)
node.TypeDefinition = NumericNodeId(68, 0)
attrs = VariableAttributes()
attrs.DisplayName = LocalizedText("EngineeringUnits")
attrs.DataType = NumericNodeId(887, 0)
attrs.ValueRank = -1
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(17569, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(68, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(37, 0)
ref.SourceNodeId = NumericNodeId(17569, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(80, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(17569, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(15318, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(2368, 0)
node.BrowseName = QualifiedName('AnalogItemType', 0)
node.NodeClass = NodeClass.VariableType
node.ParentNodeId = NumericNodeId(15318, 0)
node.ReferenceTypeId = NumericNodeId(45, 0)
attrs = VariableTypeAttributes()
attrs.DisplayName = LocalizedText("AnalogItemType")
attrs.DisplayName = LocalizedText("AnalogItemType")
attrs.DataType = NodeId(ObjectIds.Number)
attrs.ValueRank = -2
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(2368, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2369, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(45, 0)
ref.SourceNodeId = NumericNodeId(2368, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(15318, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(2369, 0)
node.BrowseName = QualifiedName('EURange', 0)
node.NodeClass = NodeClass.Variable
node.ParentNodeId = NumericNodeId(2368, 0)
node.ReferenceTypeId = NumericNodeId(46, 0)
node.TypeDefinition = NumericNodeId(68, 0)
attrs = VariableAttributes()
attrs.DisplayName = LocalizedText("EURange")
attrs.DataType = NumericNodeId(884, 0)
attrs.ValueRank = -1
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(2369, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(68, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(37, 0)
ref.SourceNodeId = NumericNodeId(2369, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(78, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(2369, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2368, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(17497, 0)
node.BrowseName = QualifiedName('AnalogUnitType', 0)
node.NodeClass = NodeClass.VariableType
node.ParentNodeId = NumericNodeId(15318, 0)
node.ReferenceTypeId = NumericNodeId(45, 0)
attrs = VariableTypeAttributes()
attrs.DisplayName = LocalizedText("AnalogUnitType")
attrs.DisplayName = LocalizedText("AnalogUnitType")
attrs.DataType = NodeId(ObjectIds.Number)
attrs.ValueRank = -2
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(17497, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(17502, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(45, 0)
ref.SourceNodeId = NumericNodeId(17497, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(15318, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(17502, 0)
node.BrowseName = QualifiedName('EngineeringUnits', 0)
node.NodeClass = NodeClass.Variable
node.ParentNodeId = NumericNodeId(17497, 0)
node.ReferenceTypeId = NumericNodeId(46, 0)
node.TypeDefinition = NumericNodeId(68, 0)
attrs = VariableAttributes()
attrs.DisplayName = LocalizedText("EngineeringUnits")
attrs.DataType = NumericNodeId(887, 0)
attrs.ValueRank = -1
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(17502, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(68, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(37, 0)
ref.SourceNodeId = NumericNodeId(17502, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(78, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(17502, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(17497, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(17570, 0)
node.BrowseName = QualifiedName('AnalogUnitRangeType', 0)
node.NodeClass = NodeClass.VariableType
node.ParentNodeId = NumericNodeId(2368, 0)
node.ReferenceTypeId = NumericNodeId(45, 0)
attrs = VariableTypeAttributes()
attrs.DisplayName = LocalizedText("AnalogUnitRangeType")
attrs.DisplayName = LocalizedText("AnalogUnitRangeType")
attrs.DataType = NodeId(ObjectIds.Number)
attrs.ValueRank = -2
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(17570, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(17575, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(45, 0)
ref.SourceNodeId = NumericNodeId(17570, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2368, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(17575, 0)
node.BrowseName = QualifiedName('EngineeringUnits', 0)
node.NodeClass = NodeClass.Variable
node.ParentNodeId = NumericNodeId(17570, 0)
node.ReferenceTypeId = NumericNodeId(46, 0)
node.TypeDefinition = NumericNodeId(68, 0)
attrs = VariableAttributes()
attrs.DisplayName = LocalizedText("EngineeringUnits")
attrs.DataType = NumericNodeId(887, 0)
attrs.ValueRank = -1
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(17575, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(68, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(37, 0)
ref.SourceNodeId = NumericNodeId(17575, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(78, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(17575, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(17570, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(2372, 0)
node.BrowseName = QualifiedName('DiscreteItemType', 0)
node.NodeClass = NodeClass.VariableType
node.ParentNodeId = NumericNodeId(2365, 0)
node.ReferenceTypeId = NumericNodeId(45, 0)
attrs = VariableTypeAttributes()
attrs.DisplayName = LocalizedText("DiscreteItemType")
attrs.IsAbstract = True
attrs.DisplayName = LocalizedText("DiscreteItemType")
attrs.DataType = NodeId(ObjectIds.String)
attrs.ValueRank = -2
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(45, 0)
ref.SourceNodeId = NumericNodeId(2372, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2365, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(2373, 0)
node.BrowseName = QualifiedName('TwoStateDiscreteType', 0)
node.NodeClass = NodeClass.VariableType
node.ParentNodeId = NumericNodeId(2372, 0)
node.ReferenceTypeId = NumericNodeId(45, 0)
attrs = VariableTypeAttributes()
attrs.DisplayName = LocalizedText("TwoStateDiscreteType")
attrs.DisplayName = LocalizedText("TwoStateDiscreteType")
attrs.DataType = NodeId(ObjectIds.Boolean)
attrs.ValueRank = -2
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(2373, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2374, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(2373, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2375, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(45, 0)
ref.SourceNodeId = NumericNodeId(2373, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2372, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(2374, 0)
node.BrowseName = QualifiedName('FalseState', 0)
node.NodeClass = NodeClass.Variable
node.ParentNodeId = NumericNodeId(2373, 0)
node.ReferenceTypeId = NumericNodeId(46, 0)
node.TypeDefinition = NumericNodeId(68, 0)
attrs = VariableAttributes()
attrs.DisplayName = LocalizedText("FalseState")
attrs.DataType = NodeId(ObjectIds.LocalizedText)
attrs.ValueRank = -1
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(2374, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(68, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(37, 0)
ref.SourceNodeId = NumericNodeId(2374, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(78, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(2374, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2373, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(2375, 0)
node.BrowseName = QualifiedName('TrueState', 0)
node.NodeClass = NodeClass.Variable
node.ParentNodeId = NumericNodeId(2373, 0)
node.ReferenceTypeId = NumericNodeId(46, 0)
node.TypeDefinition = NumericNodeId(68, 0)
attrs = VariableAttributes()
attrs.DisplayName = LocalizedText("TrueState")
attrs.DataType = NodeId(ObjectIds.LocalizedText)
attrs.ValueRank = -1
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(2375, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(68, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(37, 0)
ref.SourceNodeId = NumericNodeId(2375, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(78, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(2375, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2373, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(2376, 0)
node.BrowseName = QualifiedName('MultiStateDiscreteType', 0)
node.NodeClass = NodeClass.VariableType
node.ParentNodeId = NumericNodeId(2372, 0)
node.ReferenceTypeId = NumericNodeId(45, 0)
attrs = VariableTypeAttributes()
attrs.DisplayName = LocalizedText("MultiStateDiscreteType")
attrs.DisplayName = LocalizedText("MultiStateDiscreteType")
attrs.DataType = NodeId(ObjectIds.UInteger)
attrs.ValueRank = -2
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(2376, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2377, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(45, 0)
ref.SourceNodeId = NumericNodeId(2376, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2372, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(2377, 0)
node.BrowseName = QualifiedName('EnumStrings', 0)
node.NodeClass = NodeClass.Variable
node.ParentNodeId = NumericNodeId(2376, 0)
node.ReferenceTypeId = NumericNodeId(46, 0)
node.TypeDefinition = NumericNodeId(68, 0)
attrs = VariableAttributes()
attrs.DisplayName = LocalizedText("EnumStrings")
attrs.DataType = NodeId(ObjectIds.LocalizedText)
attrs.ValueRank = 1
attrs.ArrayDimensions = [0]
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(2377, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(68, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(37, 0)
ref.SourceNodeId = NumericNodeId(2377, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(78, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(2377, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2376, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(11238, 0)
node.BrowseName = QualifiedName('MultiStateValueDiscreteType', 0)
node.NodeClass = NodeClass.VariableType
node.ParentNodeId = NumericNodeId(2372, 0)
node.ReferenceTypeId = NumericNodeId(45, 0)
attrs = VariableTypeAttributes()
attrs.DisplayName = LocalizedText("MultiStateValueDiscreteType")
attrs.DisplayName = LocalizedText("MultiStateValueDiscreteType")
attrs.DataType = NodeId(ObjectIds.Number)
attrs.ValueRank = -2
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(11238, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(11241, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(11238, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(11461, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(45, 0)
ref.SourceNodeId = NumericNodeId(11238, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2372, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(11241, 0)
node.BrowseName = QualifiedName('EnumValues', 0)
node.NodeClass = NodeClass.Variable
node.ParentNodeId = NumericNodeId(11238, 0)
node.ReferenceTypeId = NumericNodeId(46, 0)
node.TypeDefinition = NumericNodeId(68, 0)
attrs = VariableAttributes()
attrs.DisplayName = LocalizedText("EnumValues")
attrs.DataType = NumericNodeId(7594, 0)
attrs.ValueRank = 1
attrs.ArrayDimensions = [0]
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(11241, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(68, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(37, 0)
ref.SourceNodeId = NumericNodeId(11241, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(78, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(11241, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(11238, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(11461, 0)
node.BrowseName = QualifiedName('ValueAsText', 0)
node.NodeClass = NodeClass.Variable
node.ParentNodeId = NumericNodeId(11238, 0)
node.ReferenceTypeId = NumericNodeId(46, 0)
node.TypeDefinition = NumericNodeId(68, 0)
attrs = VariableAttributes()
attrs.DisplayName = LocalizedText("ValueAsText")
attrs.DataType = NodeId(ObjectIds.LocalizedText)
attrs.ValueRank = -1
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(11461, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(68, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(37, 0)
ref.SourceNodeId = NumericNodeId(11461, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(78, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(11461, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(11238, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(12021, 0)
node.BrowseName = QualifiedName('ArrayItemType', 0)
node.NodeClass = NodeClass.VariableType
node.ParentNodeId = NumericNodeId(2365, 0)
node.ReferenceTypeId = NumericNodeId(45, 0)
attrs = VariableTypeAttributes()
attrs.DisplayName = LocalizedText("ArrayItemType")
attrs.IsAbstract = True
attrs.DisplayName = LocalizedText("ArrayItemType")
attrs.DataType = NodeId(ObjectIds.String)
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(12021, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12024, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(12021, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12025, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(12021, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12026, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(12021, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12027, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(12021, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12028, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(45, 0)
ref.SourceNodeId = NumericNodeId(12021, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(2365, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(12024, 0)
node.BrowseName = QualifiedName('InstrumentRange', 0)
node.NodeClass = NodeClass.Variable
node.ParentNodeId = NumericNodeId(12021, 0)
node.ReferenceTypeId = NumericNodeId(46, 0)
node.TypeDefinition = NumericNodeId(68, 0)
attrs = VariableAttributes()
attrs.DisplayName = LocalizedText("InstrumentRange")
attrs.DataType = NumericNodeId(884, 0)
attrs.ValueRank = -1
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(12024, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(68, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(37, 0)
ref.SourceNodeId = NumericNodeId(12024, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(80, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(12024, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12021, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(12025, 0)
node.BrowseName = QualifiedName('EURange', 0)
node.NodeClass = NodeClass.Variable
node.ParentNodeId = NumericNodeId(12021, 0)
node.ReferenceTypeId = NumericNodeId(46, 0)
node.TypeDefinition = NumericNodeId(68, 0)
attrs = VariableAttributes()
attrs.DisplayName = LocalizedText("EURange")
attrs.DataType = NumericNodeId(884, 0)
attrs.ValueRank = -1
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(12025, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(68, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(37, 0)
ref.SourceNodeId = NumericNodeId(12025, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(78, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(12025, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12021, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(12026, 0)
node.BrowseName = QualifiedName('EngineeringUnits', 0)
node.NodeClass = NodeClass.Variable
node.ParentNodeId = NumericNodeId(12021, 0)
node.ReferenceTypeId = NumericNodeId(46, 0)
node.TypeDefinition = NumericNodeId(68, 0)
attrs = VariableAttributes()
attrs.DisplayName = LocalizedText("EngineeringUnits")
attrs.DataType = NumericNodeId(887, 0)
attrs.ValueRank = -1
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(12026, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(68, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(37, 0)
ref.SourceNodeId = NumericNodeId(12026, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(78, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(12026, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12021, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(12027, 0)
node.BrowseName = QualifiedName('Title', 0)
node.NodeClass = NodeClass.Variable
node.ParentNodeId = NumericNodeId(12021, 0)
node.ReferenceTypeId = NumericNodeId(46, 0)
node.TypeDefinition = NumericNodeId(68, 0)
attrs = VariableAttributes()
attrs.DisplayName = LocalizedText("Title")
attrs.DataType = NodeId(ObjectIds.LocalizedText)
attrs.ValueRank = -1
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(12027, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(68, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(37, 0)
ref.SourceNodeId = NumericNodeId(12027, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(78, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(12027, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12021, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(12028, 0)
node.BrowseName = QualifiedName('AxisScaleType', 0)
node.NodeClass = NodeClass.Variable
node.ParentNodeId = NumericNodeId(12021, 0)
node.ReferenceTypeId = NumericNodeId(46, 0)
node.TypeDefinition = NumericNodeId(68, 0)
attrs = VariableAttributes()
attrs.DisplayName = LocalizedText("AxisScaleType")
attrs.DataType = NumericNodeId(12077, 0)
attrs.ValueRank = -1
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(12028, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(68, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(37, 0)
ref.SourceNodeId = NumericNodeId(12028, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(78, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(12028, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12021, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(12029, 0)
node.BrowseName = QualifiedName('YArrayItemType', 0)
node.NodeClass = NodeClass.VariableType
node.ParentNodeId = NumericNodeId(12021, 0)
node.ReferenceTypeId = NumericNodeId(45, 0)
attrs = VariableTypeAttributes()
attrs.DisplayName = LocalizedText("YArrayItemType")
attrs.DisplayName = LocalizedText("YArrayItemType")
attrs.DataType = NodeId(ObjectIds.String)
attrs.ValueRank = 1
attrs.ArrayDimensions = [0]
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(12029, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12037, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(45, 0)
ref.SourceNodeId = NumericNodeId(12029, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12021, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(12037, 0)
node.BrowseName = QualifiedName('XAxisDefinition', 0)
node.NodeClass = NodeClass.Variable
node.ParentNodeId = NumericNodeId(12029, 0)
node.ReferenceTypeId = NumericNodeId(46, 0)
node.TypeDefinition = NumericNodeId(68, 0)
attrs = VariableAttributes()
attrs.DisplayName = LocalizedText("XAxisDefinition")
attrs.DataType = NumericNodeId(12079, 0)
attrs.ValueRank = -1
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(12037, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(68, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(37, 0)
ref.SourceNodeId = NumericNodeId(12037, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(78, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(12037, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12029, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(12038, 0)
node.BrowseName = QualifiedName('XYArrayItemType', 0)
node.NodeClass = NodeClass.VariableType
node.ParentNodeId = NumericNodeId(12021, 0)
node.ReferenceTypeId = NumericNodeId(45, 0)
attrs = VariableTypeAttributes()
attrs.DisplayName = LocalizedText("XYArrayItemType")
attrs.DisplayName = LocalizedText("XYArrayItemType")
attrs.DataType = NumericNodeId(12080, 0)
attrs.ValueRank = 1
attrs.ArrayDimensions = [0]
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(12038, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12046, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(45, 0)
ref.SourceNodeId = NumericNodeId(12038, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12021, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(12046, 0)
node.BrowseName = QualifiedName('XAxisDefinition', 0)
node.NodeClass = NodeClass.Variable
node.ParentNodeId = NumericNodeId(12038, 0)
node.ReferenceTypeId = NumericNodeId(46, 0)
node.TypeDefinition = NumericNodeId(68, 0)
attrs = VariableAttributes()
attrs.DisplayName = LocalizedText("XAxisDefinition")
attrs.DataType = NumericNodeId(12079, 0)
attrs.ValueRank = -1
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(12046, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(68, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(37, 0)
ref.SourceNodeId = NumericNodeId(12046, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(78, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(12046, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12038, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(12047, 0)
node.BrowseName = QualifiedName('ImageItemType', 0)
node.NodeClass = NodeClass.VariableType
node.ParentNodeId = NumericNodeId(12021, 0)
node.ReferenceTypeId = NumericNodeId(45, 0)
attrs = VariableTypeAttributes()
attrs.DisplayName = LocalizedText("ImageItemType")
attrs.DisplayName = LocalizedText("ImageItemType")
attrs.DataType = NodeId(ObjectIds.String)
attrs.ValueRank = 2
attrs.ArrayDimensions = [0, 0]
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(12047, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12055, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(12047, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12056, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(45, 0)
ref.SourceNodeId = NumericNodeId(12047, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12021, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(12055, 0)
node.BrowseName = QualifiedName('XAxisDefinition', 0)
node.NodeClass = NodeClass.Variable
node.ParentNodeId = NumericNodeId(12047, 0)
node.ReferenceTypeId = NumericNodeId(46, 0)
node.TypeDefinition = NumericNodeId(68, 0)
attrs = VariableAttributes()
attrs.DisplayName = LocalizedText("XAxisDefinition")
attrs.DataType = NumericNodeId(12079, 0)
attrs.ValueRank = -1
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(12055, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(68, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(37, 0)
ref.SourceNodeId = NumericNodeId(12055, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(78, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(12055, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12047, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(12056, 0)
node.BrowseName = QualifiedName('YAxisDefinition', 0)
node.NodeClass = NodeClass.Variable
node.ParentNodeId = NumericNodeId(12047, 0)
node.ReferenceTypeId = NumericNodeId(46, 0)
node.TypeDefinition = NumericNodeId(68, 0)
attrs = VariableAttributes()
attrs.DisplayName = LocalizedText("YAxisDefinition")
attrs.DataType = NumericNodeId(12079, 0)
attrs.ValueRank = -1
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(12056, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(68, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(37, 0)
ref.SourceNodeId = NumericNodeId(12056, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(78, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(12056, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12047, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(12057, 0)
node.BrowseName = QualifiedName('CubeItemType', 0)
node.NodeClass = NodeClass.VariableType
node.ParentNodeId = NumericNodeId(12021, 0)
node.ReferenceTypeId = NumericNodeId(45, 0)
attrs = VariableTypeAttributes()
attrs.DisplayName = LocalizedText("CubeItemType")
attrs.DisplayName = LocalizedText("CubeItemType")
attrs.DataType = NodeId(ObjectIds.String)
attrs.ValueRank = 3
attrs.ArrayDimensions = [0, 0, 0]
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(12057, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12065, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(12057, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12066, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(12057, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12067, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(45, 0)
ref.SourceNodeId = NumericNodeId(12057, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12021, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(12065, 0)
node.BrowseName = QualifiedName('XAxisDefinition', 0)
node.NodeClass = NodeClass.Variable
node.ParentNodeId = NumericNodeId(12057, 0)
node.ReferenceTypeId = NumericNodeId(46, 0)
node.TypeDefinition = NumericNodeId(68, 0)
attrs = VariableAttributes()
attrs.DisplayName = LocalizedText("XAxisDefinition")
attrs.DataType = NumericNodeId(12079, 0)
attrs.ValueRank = -1
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(12065, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(68, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(37, 0)
ref.SourceNodeId = NumericNodeId(12065, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(78, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(12065, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12057, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(12066, 0)
node.BrowseName = QualifiedName('YAxisDefinition', 0)
node.NodeClass = NodeClass.Variable
node.ParentNodeId = NumericNodeId(12057, 0)
node.ReferenceTypeId = NumericNodeId(46, 0)
node.TypeDefinition = NumericNodeId(68, 0)
attrs = VariableAttributes()
attrs.DisplayName = LocalizedText("YAxisDefinition")
attrs.DataType = NumericNodeId(12079, 0)
attrs.ValueRank = -1
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(12066, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(68, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(37, 0)
ref.SourceNodeId = NumericNodeId(12066, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(78, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(12066, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12057, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(12067, 0)
node.BrowseName = QualifiedName('ZAxisDefinition', 0)
node.NodeClass = NodeClass.Variable
node.ParentNodeId = NumericNodeId(12057, 0)
node.ReferenceTypeId = NumericNodeId(46, 0)
node.TypeDefinition = NumericNodeId(68, 0)
attrs = VariableAttributes()
attrs.DisplayName = LocalizedText("ZAxisDefinition")
attrs.DataType = NumericNodeId(12079, 0)
attrs.ValueRank = -1
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(12067, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(68, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(37, 0)
ref.SourceNodeId = NumericNodeId(12067, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(78, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(12067, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12057, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(12068, 0)
node.BrowseName = QualifiedName('NDimensionArrayItemType', 0)
node.NodeClass = NodeClass.VariableType
node.ParentNodeId = NumericNodeId(12021, 0)
node.ReferenceTypeId = NumericNodeId(45, 0)
attrs = VariableTypeAttributes()
attrs.DisplayName = LocalizedText("NDimensionArrayItemType")
attrs.DisplayName = LocalizedText("NDimensionArrayItemType")
attrs.DataType = NodeId(ObjectIds.String)
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(12068, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12076, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(45, 0)
ref.SourceNodeId = NumericNodeId(12068, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12021, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(12076, 0)
node.BrowseName = QualifiedName('AxisDefinition', 0)
node.NodeClass = NodeClass.Variable
node.ParentNodeId = NumericNodeId(12068, 0)
node.ReferenceTypeId = NumericNodeId(46, 0)
node.TypeDefinition = NumericNodeId(68, 0)
attrs = VariableAttributes()
attrs.DisplayName = LocalizedText("AxisDefinition")
attrs.DataType = NumericNodeId(12079, 0)
attrs.ValueRank = 1
attrs.ArrayDimensions = [0]
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(12076, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(68, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(37, 0)
ref.SourceNodeId = NumericNodeId(12076, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(78, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(12076, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12068, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(884, 0)
node.BrowseName = QualifiedName('Range', 0)
node.NodeClass = NodeClass.DataType
node.ParentNodeId = NumericNodeId(22, 0)
node.ReferenceTypeId = NumericNodeId(45, 0)
attrs = DataTypeAttributes()
attrs.DisplayName = LocalizedText("Range")
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(45, 0)
ref.SourceNodeId = NumericNodeId(884, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(22, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(887, 0)
node.BrowseName = QualifiedName('EUInformation', 0)
node.NodeClass = NodeClass.DataType
node.ParentNodeId = NumericNodeId(22, 0)
node.ReferenceTypeId = NumericNodeId(45, 0)
attrs = DataTypeAttributes()
attrs.DisplayName = LocalizedText("EUInformation")
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(45, 0)
ref.SourceNodeId = NumericNodeId(887, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(22, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(12077, 0)
node.BrowseName = QualifiedName('AxisScaleEnumeration', 0)
node.NodeClass = NodeClass.DataType
node.ParentNodeId = NumericNodeId(29, 0)
node.ReferenceTypeId = NumericNodeId(45, 0)
attrs = DataTypeAttributes()
attrs.DisplayName = LocalizedText("AxisScaleEnumeration")
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(12077, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12078, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(45, 0)
ref.SourceNodeId = NumericNodeId(12077, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(29, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(12078, 0)
node.BrowseName = QualifiedName('EnumStrings', 0)
node.NodeClass = NodeClass.Variable
node.ParentNodeId = NumericNodeId(12077, 0)
node.ReferenceTypeId = NumericNodeId(46, 0)
node.TypeDefinition = NumericNodeId(68, 0)
attrs = VariableAttributes()
attrs.DisplayName = LocalizedText("EnumStrings")
attrs.DataType = NodeId(ObjectIds.LocalizedText)
attrs.Value = [LocalizedText('Linear'), LocalizedText('Log'), LocalizedText('Ln')]
attrs.ValueRank = 1
attrs.ArrayDimensions = [0]
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(12078, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(68, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(37, 0)
ref.SourceNodeId = NumericNodeId(12078, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(78, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(46, 0)
ref.SourceNodeId = NumericNodeId(12078, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12077, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(12171, 0)
node.BrowseName = QualifiedName('ComplexNumberType', 0)
node.NodeClass = NodeClass.DataType
node.ParentNodeId = NumericNodeId(22, 0)
node.ReferenceTypeId = NumericNodeId(45, 0)
attrs = DataTypeAttributes()
attrs.DisplayName = LocalizedText("ComplexNumberType")
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(45, 0)
ref.SourceNodeId = NumericNodeId(12171, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(22, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(12172, 0)
node.BrowseName = QualifiedName('DoubleComplexNumberType', 0)
node.NodeClass = NodeClass.DataType
node.ParentNodeId = NumericNodeId(22, 0)
node.ReferenceTypeId = NumericNodeId(45, 0)
attrs = DataTypeAttributes()
attrs.DisplayName = LocalizedText("DoubleComplexNumberType")
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(45, 0)
ref.SourceNodeId = NumericNodeId(12172, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(22, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(12079, 0)
node.BrowseName = QualifiedName('AxisInformation', 0)
node.NodeClass = NodeClass.DataType
node.ParentNodeId = NumericNodeId(22, 0)
node.ReferenceTypeId = NumericNodeId(45, 0)
attrs = DataTypeAttributes()
attrs.DisplayName = LocalizedText("AxisInformation")
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(45, 0)
ref.SourceNodeId = NumericNodeId(12079, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(22, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(12080, 0)
node.BrowseName = QualifiedName('XVType', 0)
node.NodeClass = NodeClass.DataType
node.ParentNodeId = NumericNodeId(22, 0)
node.ReferenceTypeId = NumericNodeId(45, 0)
attrs = DataTypeAttributes()
attrs.DisplayName = LocalizedText("XVType")
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(45, 0)
ref.SourceNodeId = NumericNodeId(12080, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(22, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(886, 0)
node.BrowseName = QualifiedName('Default Binary', 0)
node.NodeClass = NodeClass.Object
node.ParentNodeId = NumericNodeId(884, 0)
node.ReferenceTypeId = NumericNodeId(38, 0)
node.TypeDefinition = NumericNodeId(76, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("Default Binary")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(38, 0)
ref.SourceNodeId = NumericNodeId(886, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(884, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(39, 0)
ref.SourceNodeId = NumericNodeId(886, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(8238, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(886, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(76, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(889, 0)
node.BrowseName = QualifiedName('Default Binary', 0)
node.NodeClass = NodeClass.Object
node.ParentNodeId = NumericNodeId(887, 0)
node.ReferenceTypeId = NumericNodeId(38, 0)
node.TypeDefinition = NumericNodeId(76, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("Default Binary")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(38, 0)
ref.SourceNodeId = NumericNodeId(889, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(887, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(39, 0)
ref.SourceNodeId = NumericNodeId(889, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(8241, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(889, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(76, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(12181, 0)
node.BrowseName = QualifiedName('Default Binary', 0)
node.NodeClass = NodeClass.Object
node.ParentNodeId = NumericNodeId(12171, 0)
node.ReferenceTypeId = NumericNodeId(38, 0)
node.TypeDefinition = NumericNodeId(76, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("Default Binary")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(38, 0)
ref.SourceNodeId = NumericNodeId(12181, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12171, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(39, 0)
ref.SourceNodeId = NumericNodeId(12181, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12183, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(12181, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(76, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(12182, 0)
node.BrowseName = QualifiedName('Default Binary', 0)
node.NodeClass = NodeClass.Object
node.ParentNodeId = NumericNodeId(12172, 0)
node.ReferenceTypeId = NumericNodeId(38, 0)
node.TypeDefinition = NumericNodeId(76, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("Default Binary")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(38, 0)
ref.SourceNodeId = NumericNodeId(12182, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12172, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(39, 0)
ref.SourceNodeId = NumericNodeId(12182, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12186, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(12182, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(76, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(12089, 0)
node.BrowseName = QualifiedName('Default Binary', 0)
node.NodeClass = NodeClass.Object
node.ParentNodeId = NumericNodeId(12079, 0)
node.ReferenceTypeId = NumericNodeId(38, 0)
node.TypeDefinition = NumericNodeId(76, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("Default Binary")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(38, 0)
ref.SourceNodeId = NumericNodeId(12089, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12079, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(39, 0)
ref.SourceNodeId = NumericNodeId(12089, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12091, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(12089, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(76, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(12090, 0)
node.BrowseName = QualifiedName('Default Binary', 0)
node.NodeClass = NodeClass.Object
node.ParentNodeId = NumericNodeId(12080, 0)
node.ReferenceTypeId = NumericNodeId(38, 0)
node.TypeDefinition = NumericNodeId(76, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("Default Binary")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(38, 0)
ref.SourceNodeId = NumericNodeId(12090, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12080, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(39, 0)
ref.SourceNodeId = NumericNodeId(12090, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12094, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(12090, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(76, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(885, 0)
node.BrowseName = QualifiedName('Default XML', 0)
node.NodeClass = NodeClass.Object
node.ParentNodeId = NumericNodeId(884, 0)
node.ReferenceTypeId = NumericNodeId(38, 0)
node.TypeDefinition = NumericNodeId(76, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("Default XML")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(38, 0)
ref.SourceNodeId = NumericNodeId(885, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(884, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(39, 0)
ref.SourceNodeId = NumericNodeId(885, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(8873, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(885, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(76, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(888, 0)
node.BrowseName = QualifiedName('Default XML', 0)
node.NodeClass = NodeClass.Object
node.ParentNodeId = NumericNodeId(887, 0)
node.ReferenceTypeId = NumericNodeId(38, 0)
node.TypeDefinition = NumericNodeId(76, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("Default XML")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(38, 0)
ref.SourceNodeId = NumericNodeId(888, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(887, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(39, 0)
ref.SourceNodeId = NumericNodeId(888, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(8876, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(888, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(76, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(12173, 0)
node.BrowseName = QualifiedName('Default XML', 0)
node.NodeClass = NodeClass.Object
node.ParentNodeId = NumericNodeId(12171, 0)
node.ReferenceTypeId = NumericNodeId(38, 0)
node.TypeDefinition = NumericNodeId(76, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("Default XML")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(38, 0)
ref.SourceNodeId = NumericNodeId(12173, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12171, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(39, 0)
ref.SourceNodeId = NumericNodeId(12173, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12175, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(12173, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(76, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(12174, 0)
node.BrowseName = QualifiedName('Default XML', 0)
node.NodeClass = NodeClass.Object
node.ParentNodeId = NumericNodeId(12172, 0)
node.ReferenceTypeId = NumericNodeId(38, 0)
node.TypeDefinition = NumericNodeId(76, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("Default XML")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(38, 0)
ref.SourceNodeId = NumericNodeId(12174, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12172, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(39, 0)
ref.SourceNodeId = NumericNodeId(12174, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12178, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(12174, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(76, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(12081, 0)
node.BrowseName = QualifiedName('Default XML', 0)
node.NodeClass = NodeClass.Object
node.ParentNodeId = NumericNodeId(12079, 0)
node.ReferenceTypeId = NumericNodeId(38, 0)
node.TypeDefinition = NumericNodeId(76, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("Default XML")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(38, 0)
ref.SourceNodeId = NumericNodeId(12081, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12079, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(39, 0)
ref.SourceNodeId = NumericNodeId(12081, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12083, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(12081, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(76, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(12082, 0)
node.BrowseName = QualifiedName('Default XML', 0)
node.NodeClass = NodeClass.Object
node.ParentNodeId = NumericNodeId(12080, 0)
node.ReferenceTypeId = NumericNodeId(38, 0)
node.TypeDefinition = NumericNodeId(76, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("Default XML")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(38, 0)
ref.SourceNodeId = NumericNodeId(12082, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12080, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(39, 0)
ref.SourceNodeId = NumericNodeId(12082, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12086, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(12082, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(76, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(15375, 0)
node.BrowseName = QualifiedName('Default JSON', 0)
node.NodeClass = NodeClass.Object
node.ParentNodeId = NumericNodeId(884, 0)
node.ReferenceTypeId = NumericNodeId(38, 0)
node.TypeDefinition = NumericNodeId(76, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("Default JSON")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(38, 0)
ref.SourceNodeId = NumericNodeId(15375, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(884, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(15375, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(76, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(15376, 0)
node.BrowseName = QualifiedName('Default JSON', 0)
node.NodeClass = NodeClass.Object
node.ParentNodeId = NumericNodeId(887, 0)
node.ReferenceTypeId = NumericNodeId(38, 0)
node.TypeDefinition = NumericNodeId(76, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("Default JSON")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(38, 0)
ref.SourceNodeId = NumericNodeId(15376, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(887, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(15376, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(76, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(15377, 0)
node.BrowseName = QualifiedName('Default JSON', 0)
node.NodeClass = NodeClass.Object
node.ParentNodeId = NumericNodeId(12171, 0)
node.ReferenceTypeId = NumericNodeId(38, 0)
node.TypeDefinition = NumericNodeId(76, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("Default JSON")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(38, 0)
ref.SourceNodeId = NumericNodeId(15377, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12171, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(15377, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(76, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(15378, 0)
node.BrowseName = QualifiedName('Default JSON', 0)
node.NodeClass = NodeClass.Object
node.ParentNodeId = NumericNodeId(12172, 0)
node.ReferenceTypeId = NumericNodeId(38, 0)
node.TypeDefinition = NumericNodeId(76, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("Default JSON")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(38, 0)
ref.SourceNodeId = NumericNodeId(15378, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12172, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(15378, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(76, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(15379, 0)
node.BrowseName = QualifiedName('Default JSON', 0)
node.NodeClass = NodeClass.Object
node.ParentNodeId = NumericNodeId(12079, 0)
node.ReferenceTypeId = NumericNodeId(38, 0)
node.TypeDefinition = NumericNodeId(76, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("Default JSON")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(38, 0)
ref.SourceNodeId = NumericNodeId(15379, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12079, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(15379, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(76, 0)
refs.append(ref)
server.add_references(refs)
node = AddNodesItem()
node.RequestedNewNodeId = NumericNodeId(15380, 0)
node.BrowseName = QualifiedName('Default JSON', 0)
node.NodeClass = NodeClass.Object
node.ParentNodeId = NumericNodeId(12080, 0)
node.ReferenceTypeId = NumericNodeId(38, 0)
node.TypeDefinition = NumericNodeId(76, 0)
attrs = ObjectAttributes()
attrs.DisplayName = LocalizedText("Default JSON")
attrs.EventNotifier = 0
node.NodeAttributes = attrs
server.add_nodes([node])
refs = []
ref = AddReferencesItem()
ref.IsForward = False
ref.ReferenceTypeId = NumericNodeId(38, 0)
ref.SourceNodeId = NumericNodeId(15380, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(12080, 0)
refs.append(ref)
ref = AddReferencesItem()
ref.IsForward = True
ref.ReferenceTypeId = NumericNodeId(40, 0)
ref.SourceNodeId = NumericNodeId(15380, 0)
ref.TargetNodeClass = NodeClass.DataType
ref.TargetNodeId = NumericNodeId(76, 0)
refs.append(ref)
server.add_references(refs)
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
import logging
class HistoryManager(object):
def __init__(self, iserver):
self.logger = logging.getLogger(__name__)
self.iserver = iserver
self.storage = HistoryDict()
self._sub = None
self._handlers = {}
class HistoryStorageInterface(object):
pass
class HistoryDict(HistoryStorageInterface):
"""
Very minimal history backend storing data in memory using a Python dictionary
"""
def __init__(self):
self._datachanges = {}
self._datachanges_period = {}
self._events = {}
self._events_periods = {}
self.logger = logging.getLogger(__name__)
import logging
import os
from KL import application_protocol
from common.node import Node, NodeId
from KL.constants import ObjectIds
from mainserver.user_manager import UserManager
from threading import Lock
from enum import Enum
from mainserver.address_space import AddressSpace, AttributeService, ViewService, MethodService, NodeManagementService
from mainserver.subscription_service import SubscriptionService
from mainserver.history import HistoryManager
from common.callback import CallbackDispatcher
from KL.application_protocol import *
from KL.attribute_ids import *
from mainserver import standard_address_space
from datetime import datetime
from common import utils
class SessionState(Enum):
Created = 0
Activated = 1
Closed = 2
class InternalServer(object):
def __init__(self, shelffile=None, user_manager=None, session_cls=None):
self.logger = logging.getLogger(__name__)
self.server_callback_dispatcher = CallbackDispatcher()
self.endpoints = []
self._channel_id_counter = 5
self.disabled_clock = False # for debugging we may want to disable clock that writes too much in log
self._local_discovery_service = None # lazy-loading
self.aspace = AddressSpace()
self.attribute_service = AttributeService(self.aspace)
self.view_service = ViewService(self.aspace)
self.method_service = MethodService(self.aspace)
self.node_mgt_service = NodeManagementService(self.aspace)
self.load_standard_address_space(shelffile)
self.loop = None
self.asyncio_transports = []
self.subscription_service = SubscriptionService(self.aspace)
self.history_manager = HistoryManager(self)
self.user_manager = user_manager
# create a session to use on server side
self.session_cls = session_cls or InternalSession
self.isession = self.session_cls(self, self.aspace,
self.subscription_service, "Internal", user=UserManager.User.Admin)
local_value = application_protocol.ServerStatusDataType()
self.server_status_node = Node(self.isession, NodeId(ObjectIds.Server_ServerStatus))
self.server_status_node.set_value(local_value)
self.current_time_node = Node(self.isession, NodeId(ObjectIds.Server_ServerStatus_CurrentTime))
self._address_space_fixes()
self.setup_nodes()
def setup_nodes(self):
"""
Set up some nodes as defined by spec
"""
uries = ["http://opcfoundation.org/UA/"]
ns_node = Node(self.isession, NodeId(ObjectIds.Server_NamespaceArray))
ns_node.set_value(uries)
def load_standard_address_space(self, shelffile=None):
if (shelffile is not None) and (os.path.isfile(shelffile) or os.path.isfile(shelffile + ".db")):
# import address space from shelf
self.aspace.load_aspace_shelf(shelffile)
else:
# import address space from code generated from xml
standard_address_space.fill_address_space(self.node_mgt_service)
# import address space directly from xml, this has performance impact so disabled
# importer = xmlimporter.XmlImporter(self.node_mgt_service)
# importer.import_xml("/path/to/python-opcua/schemas/Opc.Ua.NodeSet2.xml", self)
# if a cache file was supplied a shelve of the standard address space can now be built for next start up
if shelffile:
self.aspace.make_aspace_shelf(shelffile)
def _address_space_fixes(self):
"""
Looks like the xml definition of address space has some error. This is a good place to fix them
"""
it = AddReferencesItem()
it.SourceNodeId = NodeId(ObjectIds.BaseObjectType)
it.ReferenceTypeId = NodeId(ObjectIds.Organizes)
it.IsForward = False
it.TargetNodeId = NodeId(ObjectIds.ObjectTypesFolder)
it.TargetNodeClass = NodeClass.Object
it2 = AddReferencesItem()
it2.SourceNodeId = NodeId(ObjectIds.BaseDataType)
it2.ReferenceTypeId = NodeId(ObjectIds.Organizes)
it2.IsForward = False
it2.TargetNodeId = NodeId(ObjectIds.DataTypesFolder)
it2.TargetNodeClass = NodeClass.Object
results = self.isession.add_references([it, it2])
params = WriteParameters()
for nodeid in (ObjectIds.Server_ServerCapabilities_OperationLimits_MaxNodesPerRead,
ObjectIds.Server_ServerCapabilities_OperationLimits_MaxNodesPerHistoryReadData,
ObjectIds.Server_ServerCapabilities_OperationLimits_MaxNodesPerHistoryReadEvents,
ObjectIds.Server_ServerCapabilities_OperationLimits_MaxNodesPerWrite,
ObjectIds.Server_ServerCapabilities_OperationLimits_MaxNodesPerHistoryUpdateData,
ObjectIds.Server_ServerCapabilities_OperationLimits_MaxNodesPerHistoryUpdateEvents,
ObjectIds.Server_ServerCapabilities_OperationLimits_MaxNodesPerMethodCall,
ObjectIds.Server_ServerCapabilities_OperationLimits_MaxNodesPerBrowse,
ObjectIds.Server_ServerCapabilities_OperationLimits_MaxNodesPerRegisterNodes,
ObjectIds.Server_ServerCapabilities_OperationLimits_MaxNodesPerTranslateBrowsePathsToNodeIds,
ObjectIds.Server_ServerCapabilities_OperationLimits_MaxNodesPerNodeManagement,
ObjectIds.Server_ServerCapabilities_OperationLimits_MaxMonitoredItemsPerCall):
attr = WriteValue()
attr.NodeId = NodeId(nodeid)
attr.AttributeId = AttributeIds.Value
attr.Value = DataValue(Variant(10000, VariantType.UInt32), StatusCode(StatusCodes.Good))
attr.Value.ServerTimestamp = datetime.utcnow()
params.NodesToWrite.append(attr)
result = self.isession.write(params)
result[0].check()
def add_endpoint(self, endpoint):
self.endpoints.append(endpoint)
def start(self):
self.logger.info("starting internal server")
self.loop = utils.ThreadLoop()
self.loop.start()
# self.subscription_service.set_loop(self.loop)
serverState = Node(self.isession, NodeId(ObjectIds.Server_ServerStatus_State))
serverState.set_value(application_protocol.ServerState.Running, VariantType.Int32)
Node(self.isession, NodeId(ObjectIds.Server_ServerStatus_StartTime)).set_value(datetime.utcnow())
if not self.disabled_clock:
self._set_current_time()
def stop(self):
self.logger.info("stopping internal server")
self.isession.close_session()
# self.subscription_service.set_loop(None)
# self.history_manager.stop()
if self.loop:
self.loop.stop()
# wait for ThreadLoop to finish before proceeding
self.loop.join()
self.loop.close()
self.loop = None
def _set_current_time(self):
self.current_time_node.set_value(datetime.utcnow())
ssdata = self.server_status_node.get_value()
ssdata.CurrentTime = datetime.utcnow()
self.server_status_node.set_value(ssdata)
self.loop.call_later(1, self._set_current_time)
class InternalSession(object):
_counter = 10
_auth_counter = 1000
def __init__(self, internal_server, aspace, submgr, name, user=UserManager.User.Anonymous):
self.logger = logging.getLogger(__name__)
self.iserver = internal_server
self.aspace = aspace
self.subscription_service = submgr
self.name = name
self.user = user
self.nonce = None
self.state = SessionState.Created
self.session_id = NodeId(self._counter)
InternalSession._counter += 1
self.authentication_token = NodeId(self._auth_counter)
InternalSession._auth_counter += 1
self.subscriptions = []
self.logger.info("Created internal session %s", self.name)
self._lock = Lock()
def __str__(self):
return "InternalSession(name:{0}, user:{1}, id:{2}, auth_token:{3})".format(
self.name, self.user, self.session_id, self.authentication_token)
def add_references(self, params):
return self.iserver.node_mgt_service.add_references(params, self.user)
def write(self, params):
return self.iserver.attribute_service.write(params, self.user)
def read(self, params):
results = self.iserver.attribute_service.read(params)
return results
def close_session(self):
# self.logger.info("close session %s with subscriptions %s", self, self.subscriptions)
self.state = SessionState.Closed
# self.delete_subscriptions(self.subscriptions[:])
def browse(self, params):
return self.iserver.view_service.browse(params)
def add_nodes(self, params):
return self.iserver.node_mgt_service.add_nodes(params, self.user)
import logging
from threading import RLock, Lock
import time
from KL import hand_protocol, application_protocol
from KL.status_codes import StatusCodes
from KL.types import VariantType, StatusCode, NodeId
import struct
from enum import Enum
import sys
import KL
from common.connection import SecureConnection
from KL.binary import header_to_binary, struct_from_binary, nodeid_from_binary, struct_to_binary
from KL.constants import ObjectIds
from KL import binary
if sys.version_info.major > 2:
unicode = str
class PublishRequestData(object):
def __init__(self):
self.requesthdr = None
self.seqhdr = None
self.timestamp = time.time()
class Processor(object):
def __init__(self, internal_server, socket):
self.logger = logging.getLogger(__name__)
self.iserver = internal_server
self.name = socket.get_extra_info('peername')
self.sockname = socket.get_extra_info('sockname')
self.session = None
self.socket = socket
self._socketlock = Lock()
self._datalock = RLock()
self._publishdata_queue = []
self._publish_result_queue = [] # used when we need to wait for PublishRequest
self._connection = SecureConnection(hand_protocol.SecurityPolicy())
def set_policies(self, policies):
# self._connection.set_policy_factories(policies)
pass
def send_response(self, requesthandle, seqhdr, response, msgtype=hand_protocol.MessageType.SecureMessage):
with self._socketlock:
response.ResponseHeader.RequestHandle = requesthandle
data = self._connection.message_to_binary(
struct_to_binary(response), message_type=msgtype, request_id=seqhdr.RequestId)
self.socket.write(data)
def process(self, header, body):
msg = self._connection.receive_from_header_and_body(header, body)
if isinstance(msg, hand_protocol.Message):
if header.MessageType == hand_protocol.MessageType.SecureOpen:
self.open_secure_channel(msg.SecurityHeader(), msg.SequenceHeader(), msg.body())
elif header.MessageType == hand_protocol.MessageType.SecureClose:
self._connection.close()
return False
elif header.MessageType == hand_protocol.MessageType.SecureMessage:
return self.process_message(msg.SequenceHeader(), msg.body())
elif isinstance(msg, hand_protocol.Hello):
ack = hand_protocol.Acknowledge()
ack.ReceiveBufferSize = msg.ReceiveBufferSize
ack.SendBufferSize = msg.SendBufferSize
data = tcp_to_binary(hand_protocol.MessageType.Acknowledge, ack)
self.socket.write(data)
# elif isinstance(msg, ua.ErrorMessage):
# self.logger.warning("Received an error message type")
elif msg is None:
pass # msg is a ChunkType.Intermediate of an ua.MessageType.SecureMessage
else:
self.logger.warning("Unsupported message type: %s", header.MessageType)
raise Exception(StatusCodes.BadTcpMessageTypeInvalid)
return True
def process_message(self, seqhdr, body):
typeid = nodeid_from_binary(body)
requesthdr = struct_from_binary(application_protocol.RequestHeader, body)
try:
return self._process_message(typeid, requesthdr, seqhdr, body)
except Exception as e:
status = StatusCode(e)
response = application_protocol.ServiceFault()
response.ResponseHeader.ServiceResult = status
self.logger.info("sending service fault response: %s (%s)", status, status.name)
self.send_response(requesthdr.RequestHandle, seqhdr, response)
return True
def _process_message(self, typeid, requesthdr, seqhdr, body):
if typeid == NodeId(ObjectIds.CreateSessionRequest_Encoding_DefaultBinary):
self.logger.info("Create session request")
params = struct_from_binary(application_protocol.CreateSessionParameters, body)
# create the session on server
self.session = self.iserver.create_session(self.name)
# get a session creation result to send back
sessiondata = self.session.create_session(params, sockname=self.sockname)
response = application_protocol.CreateSessionResponse()
response.Parameters = sessiondata
response.Parameters.ServerCertificate = self._connection.security_policy.client_certificate
if self._connection.security_policy.server_certificate is None:
data = params.ClientNonce
else:
data = self._connection.security_policy.server_certificate + params.ClientNonce
response.Parameters.ServerSignature.Signature = \
self._connection.security_policy.asymmetric_cryptography.signature(data)
response.Parameters.ServerSignature.Algorithm = self._connection.security_policy.AsymmetricSignatureURI
self.logger.info("sending create session response")
self.send_response(requesthdr.RequestHandle, seqhdr, response)
elif typeid == NodeId(ObjectIds.CloseSessionRequest_Encoding_DefaultBinary):
self.logger.info("Close session request")
if self.session:
deletesubs = binary.Primitives.Boolean.unpack(body)
self.session.close_session(deletesubs)
else:
self.logger.info("Request to close non-existing session")
response = application_protocol.CloseSessionResponse()
self.logger.info("sending close session response")
self.send_response(requesthdr.RequestHandle, seqhdr, response)
elif typeid == NodeId(ObjectIds.ActivateSessionRequest_Encoding_DefaultBinary):
self.logger.info("Activate session request")
params = struct_from_binary(application_protocol.ActivateSessionParameters, body)
if not self.session:
self.logger.info("request to activate non-existing session")
raise Exception(StatusCodes.BadSessionIdInvalid)
if self._connection.security_policy.client_certificate is None:
data = self.session.nonce
else:
data = self._connection.security_policy.client_certificate + self.session.nonce
self._connection.security_policy.asymmetric_cryptography.verify(data, params.ClientSignature.Signature)
result = self.session.activate_session(params)
response = application_protocol.ActivateSessionResponse()
response.Parameters = result
self.logger.info("sending read response")
self.send_response(requesthdr.RequestHandle, seqhdr, response)
elif typeid == NodeId(ObjectIds.ReadRequest_Encoding_DefaultBinary):
self.logger.info("Read request")
params = struct_from_binary(application_protocol.ReadParameters, body)
results = self.session.read(params)
response = application_protocol.ReadResponse()
response.Results = results
self.logger.info("sending read response")
self.send_response(requesthdr.RequestHandle, seqhdr, response)
elif typeid == NodeId(ObjectIds.WriteRequest_Encoding_DefaultBinary):
self.logger.info("Write request")
params = struct_from_binary(application_protocol.WriteParameters, body)
results = self.session.write(params)
response = application_protocol.WriteResponse()
response.Results = results
self.logger.info("sending write response")
self.send_response(requesthdr.RequestHandle, seqhdr, response)
elif typeid == NodeId(ObjectIds.BrowseRequest_Encoding_DefaultBinary):
self.logger.info("Browse request")
params = struct_from_binary(application_protocol.BrowseParameters, body)
results = self.session.browse(params)
response = application_protocol.BrowseResponse()
response.Results = results
self.logger.info("sending browse response")
self.send_response(requesthdr.RequestHandle, seqhdr, response)
elif typeid == NodeId(ObjectIds.GetEndpointsRequest_Encoding_DefaultBinary):
self.logger.info("get endpoints request")
params = struct_from_binary(application_protocol.GetEndpointsParameters, body)
endpoints = self.iserver.get_endpoints(params, sockname=self.sockname)
response = application_protocol.GetEndpointsResponse()
response.Endpoints = endpoints
self.logger.info("sending get endpoints response")
self.send_response(requesthdr.RequestHandle, seqhdr, response)
elif typeid == NodeId(ObjectIds.FindServersRequest_Encoding_DefaultBinary):
self.logger.info("find servers request")
params = struct_from_binary(application_protocol.FindServersParameters, body)
servers = self.local_discovery_service.find_servers(params)
response = application_protocol.FindServersResponse()
response.Servers = servers
self.logger.info("sending find servers response")
self.send_response(requesthdr.RequestHandle, seqhdr, response)
elif typeid == NodeId(ObjectIds.RegisterServerRequest_Encoding_DefaultBinary):
self.logger.info("register server request")
serv = struct_from_binary(application_protocol.RegisteredServer, body)
self.local_discovery_service.register_server(serv)
response = application_protocol.RegisterServerResponse()
self.logger.info("sending register server response")
self.send_response(requesthdr.RequestHandle, seqhdr, response)
elif typeid == NodeId(ObjectIds.RegisterServer2Request_Encoding_DefaultBinary):
self.logger.info("register server 2 request")
params = struct_from_binary(application_protocol.RegisterServer2Parameters, body)
results = self.local_discovery_service.register_server2(params)
response = application_protocol.RegisterServer2Response()
response.ConfigurationResults = results
self.logger.info("sending register server 2 response")
self.send_response(requesthdr.RequestHandle, seqhdr, response)
elif typeid == NodeId(ObjectIds.TranslateBrowsePathsToNodeIdsRequest_Encoding_DefaultBinary):
self.logger.info("translate browsepaths to nodeids request")
params = struct_from_binary(application_protocol.TranslateBrowsePathsToNodeIdsParameters, body)
paths = self.session.translate_browsepaths_to_nodeids(params.BrowsePaths)
response = application_protocol.TranslateBrowsePathsToNodeIdsResponse()
response.Results = paths
self.logger.info("sending translate browsepaths to nodeids response")
self.send_response(requesthdr.RequestHandle, seqhdr, response)
elif typeid == NodeId(ObjectIds.AddNodesRequest_Encoding_DefaultBinary):
self.logger.info("add nodes request")
params = struct_from_binary(application_protocol.AddNodesParameters, body)
results = self.session.add_nodes(params.NodesToAdd)
response = application_protocol.AddNodesResponse()
response.Results = results
self.logger.info("sending add node response")
self.send_response(requesthdr.RequestHandle, seqhdr, response)
elif typeid == NodeId(ObjectIds.DeleteNodesRequest_Encoding_DefaultBinary):
self.logger.info("delete nodes request")
params = struct_from_binary(application_protocol.DeleteNodesParameters, body)
results = self.session.delete_nodes(params)
response = application_protocol.DeleteNodesResponse()
response.Results = results
self.logger.info("sending delete node response")
self.send_response(requesthdr.RequestHandle, seqhdr, response)
elif typeid == NodeId(ObjectIds.AddReferencesRequest_Encoding_DefaultBinary):
self.logger.info("add references request")
params = struct_from_binary(application_protocol.AddReferencesParameters, body)
results = self.session.add_references(params.ReferencesToAdd)
response = application_protocol.AddReferencesResponse()
response.Results = results
self.logger.info("sending add references response")
self.send_response(requesthdr.RequestHandle, seqhdr, response)
elif typeid == NodeId(ObjectIds.DeleteReferencesRequest_Encoding_DefaultBinary):
self.logger.info("delete references request")
params = struct_from_binary(application_protocol.DeleteReferencesParameters, body)
results = self.session.delete_references(params.ReferencesToDelete)
response = application_protocol.DeleteReferencesResponse()
response.Parameters.Results = results
self.logger.info("sending delete references response")
self.send_response(requesthdr.RequestHandle, seqhdr, response)
elif typeid == NodeId(ObjectIds.CreateSubscriptionRequest_Encoding_DefaultBinary):
self.logger.info("create subscription request")
params = struct_from_binary(application_protocol.CreateSubscriptionParameters, body)
result = self.session.create_subscription(params, self.forward_publish_response)
response = application_protocol.CreateSubscriptionResponse()
response.Parameters = result
self.logger.info("sending create subscription response")
self.send_response(requesthdr.RequestHandle, seqhdr, response)
elif typeid == NodeId(ObjectIds.ModifySubscriptionRequest_Encoding_DefaultBinary):
self.logger.info("modify subscription request")
params = struct_from_binary(application_protocol.ModifySubscriptionParameters, body)
result = self.session.modify_subscription(params, self.forward_publish_response)
response = application_protocol.ModifySubscriptionResponse()
response.Parameters = result
self.logger.info("sending modify subscription response")
self.send_response(requesthdr.RequestHandle, seqhdr, response)
elif typeid == NodeId(ObjectIds.DeleteSubscriptionsRequest_Encoding_DefaultBinary):
self.logger.info("delete subscriptions request")
params = struct_from_binary(application_protocol.DeleteSubscriptionsParameters, body)
results = self.session.delete_subscriptions(params.SubscriptionIds)
response = application_protocol.DeleteSubscriptionsResponse()
response.Results = results
self.logger.info("sending delte subscription response")
self.send_response(requesthdr.RequestHandle, seqhdr, response)
elif typeid == NodeId(ObjectIds.CreateMonitoredItemsRequest_Encoding_DefaultBinary):
self.logger.info("create monitored items request")
params = struct_from_binary(application_protocol.CreateMonitoredItemsParameters, body)
results = self.session.create_monitored_items(params)
response = application_protocol.CreateMonitoredItemsResponse()
response.Results = results
self.logger.info("sending create monitored items response")
self.send_response(requesthdr.RequestHandle, seqhdr, response)
elif typeid == NodeId(ObjectIds.ModifyMonitoredItemsRequest_Encoding_DefaultBinary):
self.logger.info("modify monitored items request")
params = struct_from_binary(application_protocol.ModifyMonitoredItemsParameters, body)
results = self.session.modify_monitored_items(params)
response = application_protocol.ModifyMonitoredItemsResponse()
response.Results = results
self.logger.info("sending modify monitored items response")
self.send_response(requesthdr.RequestHandle, seqhdr, response)
elif typeid == NodeId(ObjectIds.DeleteMonitoredItemsRequest_Encoding_DefaultBinary):
self.logger.info("delete monitored items request")
params = struct_from_binary(application_protocol.DeleteMonitoredItemsParameters, body)
results = self.session.delete_monitored_items(params)
response = application_protocol.DeleteMonitoredItemsResponse()
response.Results = results
self.logger.info("sending delete monitored items response")
self.send_response(requesthdr.RequestHandle, seqhdr, response)
elif typeid == NodeId(ObjectIds.HistoryReadRequest_Encoding_DefaultBinary):
self.logger.info("history read request")
params = struct_from_binary(application_protocol.HistoryReadParameters, body)
results = self.session.history_read(params)
response = application_protocol.HistoryReadResponse()
response.Results = results
self.logger.info("sending history read response")
self.send_response(requesthdr.RequestHandle, seqhdr, response)
elif typeid == NodeId(ObjectIds.RegisterNodesRequest_Encoding_DefaultBinary):
self.logger.info("register nodes request")
params = struct_from_binary(application_protocol.RegisterNodesParameters, body)
self.logger.info("Node registration not implemented")
response = application_protocol.RegisterNodesResponse()
response.Parameters.RegisteredNodeIds = params.NodesToRegister
self.logger.info("sending register nodes response")
self.send_response(requesthdr.RequestHandle, seqhdr, response)
elif typeid == NodeId(ObjectIds.UnregisterNodesRequest_Encoding_DefaultBinary):
self.logger.info("unregister nodes request")
params = struct_from_binary(application_protocol.UnregisterNodesParameters, body)
response = application_protocol.UnregisterNodesResponse()
self.logger.info("sending unregister nodes response")
self.send_response(requesthdr.RequestHandle, seqhdr, response)
elif typeid == NodeId(ObjectIds.PublishRequest_Encoding_DefaultBinary):
self.logger.info("publish request")
if not self.session:
return False
params = struct_from_binary(application_protocol.PublishParameters, body)
data = PublishRequestData()
data.requesthdr = requesthdr
data.seqhdr = seqhdr
with self._datalock:
self._publishdata_queue.append(data) # will be used to send publish answers from server
if self._publish_result_queue:
result = self._publish_result_queue.pop(0)
self.forward_publish_response(result)
self.session.publish(params.SubscriptionAcknowledgements)
self.logger.info("publish forward to server")
elif typeid == NodeId(ObjectIds.RepublishRequest_Encoding_DefaultBinary):
self.logger.info("re-publish request")
params = struct_from_binary(application_protocol.RepublishParameters, body)
msg = self.session.republish(params)
response = application_protocol.RepublishResponse()
response.NotificationMessage = msg
self.send_response(requesthdr.RequestHandle, seqhdr, response)
elif typeid == NodeId(ObjectIds.CloseSecureChannelRequest_Encoding_DefaultBinary):
self.logger.info("close secure channel request")
self._connection.close()
response = application_protocol.CloseSecureChannelResponse()
self.send_response(requesthdr.RequestHandle, seqhdr, response)
return False
elif typeid == NodeId(ObjectIds.CallRequest_Encoding_DefaultBinary):
self.logger.info("call request")
params = struct_from_binary(application_protocol.CallParameters, body)
results = self.session.call(params.MethodsToCall)
response = application_protocol.CallResponse()
response.Results = results
self.send_response(requesthdr.RequestHandle, seqhdr, response)
elif typeid == NodeId(ObjectIds.SetMonitoringModeRequest_Encoding_DefaultBinary):
self.logger.info("set monitoring mode request")
params = struct_from_binary(application_protocol.SetMonitoringModeParameters, body)
# FIXME: Implement SetMonitoringMode
# Send dummy results to keep clients happy
response = application_protocol.SetMonitoringModeResponse()
results = application_protocol.SetMonitoringModeResult()
ids = params.MonitoredItemIds
statuses = [StatusCode(StatusCodes.Good) for node_id in ids]
results.Results = statuses
response.Parameters = results
self.logger.info("sending set monitoring mode response")
self.send_response(requesthdr.RequestHandle, seqhdr, response)
elif typeid == NodeId(ObjectIds.SetPublishingModeRequest_Encoding_DefaultBinary):
self.logger.info("set publishing mode request")
params = struct_from_binary(application_protocol.SetPublishingModeParameters, body)
# FIXME: Implement SetPublishingMode
# Send dummy results to keep clients happy
response = application_protocol.SetPublishingModeResponse()
results = application_protocol.SetPublishingModeResult()
ids = params.SubscriptionIds
statuses = [application_protocol.StatusCode(application_protocol.StatusCodes.Good) for node_id in ids]
results.Results = statuses
response.Parameters = results
self.logger.info("sending set publishing mode response")
self.send_response(requesthdr.RequestHandle, seqhdr, response)
else:
self.logger.warning("Unknown message received %s", typeid)
raise Exception(application_protocol.StatusCodes.BadServiceUnsupported)
return True
def close(self):
"""
to be called when client has disconnected to ensure we really close
everything we should
"""
self.logger.info("Cleanup client connection: %s", self.name)
if self.session:
self.session.close_session(True)
def tcp_to_binary(message_type, message):
packet = []
header = hand_protocol.Header(message_type, b"F")
for name, types in message.types:
val = getattr(message, name)
k = Primitives1.UInt32.pack(val)
packet.append(k)
binmsg = b''.join(packet)
header.body_size = len(binmsg)
# return TCPHeader.to_binary(header) + binmsg
return header_to_binary(header) + binmsg
class _Primitive1(object):
def __init__(self, fmt):
self._fmt = fmt
st = struct.Struct(fmt.format(1))
self.size = st.size
self.format = st.format
def pack(self, data):
return struct.pack(self.format, data)
def unpack(self, data):
return struct.unpack(self.format, data.read(self.size))[0]
class Primitives1(object):
UInt32 = _Primitive1("<{:d}I")
# def header_to_binary(hdr):
# b = []
# b.append(struct.pack("<3ss", hdr.MessageType, hdr.ChunkType))
# size = hdr.body_size + 8
# b.append(Primitives1.UInt32.pack(size))
# return b"".join(b)
# def header_from_binary(data):
# hdr = hand_protocol.Header()
# hdr.MessageType, hdr.ChunkType, hdr.packet_size = struct.unpack("<3scI", data.read(8))
# hdr.body_size = hdr.packet_size - 8
# if hdr.MessageType in (hand_protocol.MessageType.SecureOpen, hand_protocol.MessageType.SecureClose, hand_protocol.MessageType.SecureMessage):
# hdr.body_size -= 4
# hdr.ChannelId = Primitives1.UInt32.unpack(data)
# return hdr
# class TCPHeader:
#
# def __init__(self, source_port, dest_port, seq_num, ack_num, flags):
# self.source_port = source_port
# self.dest_port = dest_port
# self.seq_num = seq_num
# self.ack_num = ack_num
# self.flags = flags
#
# def to_binary(self):
# format_string = "<3ss" # Format string for struct.pack
# binary_data = struct.pack(format_string, self.source_port, self.dest_port,
# self.seq_num, self.ack_num, self.flags)
# return binary_data
# Example TCP header values
# source_port = 12345
# dest_port = 80
# seq_num = 1000
# ack_num = 2000
# flags = 0b0101010101010101
#
# # Create TCP header instance
# tcp_header = TCPHeader(source_port, dest_port, seq_num, ack_num, flags)
#
# # Convert TCP header to binary
# tcp_binary = tcp_header.to_binary()
import logging
from datetime import datetime
from urllib.parse import urlparse
from cryptography.hazmat.primitives import serialization
from KL.application_protocol import ApplicationType, MessageSecurityMode, UserTokenType, UserTokenPolicy, \
ApplicationDescription, EndpointDescription
from KL.types import SecurityPolicyType, NodeId, LocalizedText
from KL.constants import ObjectIds
from common.node import Node
from mainserver.user_manager import UserManager
from mainserver.internal_server import InternalServer
from mainserver.BinaryServer import BinaryServer
from KL.hand_protocol import *
from cryptography import x509
from cryptography.hazmat.backends import default_backend
from Security import security_policies
from KL.shortcuts import Shortcuts
class Server(object):
def __init__(self, shelffile=None, iserver=None):
self.logger = logging.getLogger(__name__)
self.endpoint = urlparse("opc.tcp://localhost:4842/freeopcua/server/")
self._application_uri = "urn:freeopcua:python:server"
self.product_uri = "urn:freeopcua.github.io:python:server"
self.name = "FreeOpcUa Python Server"
self.manufacturer_name = "FreeOpcUa"
self.application_type = ApplicationType.ClientAndServer
self.default_timeout = 3600000
if iserver is not None:
self.iserver = iserver
else:
self.iserver = InternalServer(shelffile=shelffile)
self.bserver = None
self._policies = []
self.nodes = Shortcuts(self.iserver.isession)
# setup some expected values
self.set_application_uri(self._application_uri)
sa_node = self.get_node(NodeId(ObjectIds.Server_ServerArray))
sa_node.set_value([self._application_uri])
# self.set_build_info(self.product_uri, self.manufacturer_name, self.name, "1.0pre", "0", datetime.now())
# enable all endpoints by default
self.certificate = None
self.private_key = None
self.user_manager = UserManager(parent=self)
self._security_policy = [
SecurityPolicyType.NoSecurity,
SecurityPolicyType.Basic256Sha256_SignAndEncrypt,
SecurityPolicyType.Basic256Sha256_Sign
]
self._policyIDs = ["Anonymous", "Basic256Sha256", "Username"]
def set_application_uri(self, uri):
"""
Set application/server URI.
This uri is supposed to be unique. If you intent to register
your server to a discovery server, it really should be unique in
your system!
default is : "urn:freeopcua:python:server"
"""
self._application_uri = uri
ns_node = self.get_node(NodeId(ObjectIds.Server_NamespaceArray))
uries = ns_node.get_value()
if len(uries) > 1:
uries[1] = uri # application uri is always namespace 1
else:
uries.append(uri)
ns_node.set_value(uries)
def get_node(self, nodeid):
"""
Get a specific node using NodeId object or a string representing a NodeId
"""
return Node(self.iserver.isession, nodeid)
def start(self):
"""
Start to listen on network
"""
self._setup_server_nodes()
self.iserver.start()
try:
if not self.bserver:
self.bserver = BinaryServer(self.iserver, self.endpoint.hostname, self.endpoint.port)
self.bserver.set_policies(self._policies)
self.bserver.set_loop(self.iserver.loop)
self.bserver.start()
except Exception as exp:
self.iserver.stop()
raise exp
def stop(self):
"""
Stop server
"""
self.bserver.stop()
self.iserver.stop()
def _setup_server_nodes(self):
# to be called just before starting server since it needs all parameters to be setup
if SecurityPolicyType.NoSecurity in self._security_policy:
self._set_endpoints()
self._policies = [SecurityPolicyFactory()]
if self._security_policy != [SecurityPolicyType.NoSecurity]:
if not (self.certificate and self.private_key):
self.logger.warning("Endpoints other than open requested but private key and certificate are not set.")
return
if SecurityPolicyType.NoSecurity in self._security_policy:
self.logger.warning(
"Creating an open endpoint to the server, although encrypted endpoints are enabled.")
if SecurityPolicyType.Basic256Sha256_SignAndEncrypt in self._security_policy:
self._set_endpoints(security_policies.SecurityPolicyBasic256Sha256,
MessageSecurityMode.SignAndEncrypt)
self._policies.append(SecurityPolicyFactory(security_policies.SecurityPolicyBasic256Sha256,
MessageSecurityMode.SignAndEncrypt,
self.certificate,
self.private_key)
)
if SecurityPolicyType.Basic256Sha256_Sign in self._security_policy:
self._set_endpoints(security_policies.SecurityPolicyBasic256Sha256,
MessageSecurityMode.Sign)
self._policies.append(SecurityPolicyFactory(security_policies.SecurityPolicyBasic256Sha256,
MessageSecurityMode.Sign,
self.certificate,
self.private_key)
)
def _set_endpoints(self, policy=SecurityPolicy, mode=MessageSecurityMode.None_):
idtokens = []
if "Anonymous" in self._policyIDs:
idtoken = UserTokenPolicy()
idtoken.PolicyId = 'anonymous'
idtoken.TokenType = UserTokenType.Anonymous
idtokens.append(idtoken)
if "Basic256Sha256" in self._policyIDs:
idtoken = UserTokenPolicy()
idtoken.PolicyId = 'certificate_basic256sha256'
idtoken.TokenType = UserTokenType.Certificate
idtokens.append(idtoken)
if "Username" in self._policyIDs:
idtoken = UserTokenPolicy()
idtoken.PolicyId = 'username'
idtoken.TokenType = UserTokenType.UserName
idtokens.append(idtoken)
appdesc = ApplicationDescription()
appdesc.ApplicationName = LocalizedText(self.name)
appdesc.ApplicationUri = self._application_uri
appdesc.ApplicationType = self.application_type
appdesc.ProductUri = self.product_uri
appdesc.DiscoveryUrls.append(self.endpoint.geturl())
edp = EndpointDescription()
edp.EndpointUrl = self.endpoint.geturl()
edp.Server = appdesc
if self.certificate:
cert = x509.load_pem_x509_certificate(self.certificate.encode(), default_backend())
edp.ServerCertificate = cert.public_bytes(serialization.Encoding.DER)
# edp.ServerCertificate = uacrypto.der_from_x509(self.certificate)
edp.SecurityMode = mode
edp.SecurityPolicyUri = policy.URI
edp.UserIdentityTokens = idtokens
edp.TransportProfileUri = 'http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary'
edp.SecurityLevel = 0
self.iserver.add_endpoint(edp)
def set_endpoint(self, url):
self.endpoint = urlparse(url)
def register_namespace(self, uri):
"""
Register a new namespace. Nodes should in custom namespace, not 0.
"""
ns_node = self.get_node(NodeId(ObjectIds.Server_NamespaceArray))
uries = ns_node.get_value()
if uri in uries:
return uries.index(uri)
uries.append(uri)
ns_node.set_value(uries)
return len(uries) - 1
from mainserver.create_standard_address_space_Part3 import create_standard_address_space_Part3
from mainserver.create_standard_address_space_Part4 import create_standard_address_space_Part4
from mainserver.create_standard_address_space_Part5 import create_standard_address_space_Part5
from mainserver.create_standard_address_space_Part8 import create_standard_address_space_Part8
from mainserver.create_standard_address_space_Part9 import create_standard_address_space_Part9
from mainserver.create_standard_address_space_Part10 import create_standard_address_space_Part10
from mainserver.create_standard_address_space_Part11 import create_standard_address_space_Part11
from mainserver.create_standard_address_space_Part13 import create_standard_address_space_Part13
class PostponeReferences(object):
def __init__(self, server):
self.server = server
self.postponed_refs = None
self.postponed_nodes = None
# self.add_nodes = self.server.add_nodes
def __enter__(self):
self.postponed_refs = []
self.postponed_nodes = []
return self
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type is None and exc_val is None:
remaining_nodes = list(self.server.try_add_nodes(self.postponed_nodes, check=False))
assert len(remaining_nodes) == 0, remaining_nodes
remaining_refs = list(self.server.try_add_references(self.postponed_refs))
assert len(remaining_refs) == 0, remaining_refs
def add_nodes(self, nodes):
self.postponed_nodes.extend(self.server.try_add_nodes(nodes, check=False))
def add_references(self, refs):
self.postponed_refs.extend(self.server.try_add_references(refs))
def fill_address_space(nodeservice):
with PostponeReferences(nodeservice) as server:
create_standard_address_space_Part3(server)
create_standard_address_space_Part4(server)
create_standard_address_space_Part5(server)
create_standard_address_space_Part8(server)
create_standard_address_space_Part9(server)
create_standard_address_space_Part10(server)
create_standard_address_space_Part11(server)
create_standard_address_space_Part13(server)
import logging
from threading import RLock
class SubscriptionService(object):
def __init__(self, aspace):
self.logger = logging.getLogger(__name__)
self.loop = None
self.aspace = aspace
self.subscriptions = {}
self._sub_id_counter = 77
self._lock = RLock()
\ No newline at end of file
import logging
from enum import Enum
class UserManager(object):
class User(Enum):
"""
Define some default users.
"""
Admin = 0
Anonymous = 1
User = 3
def __init__(self, parent):
self.logger = logging.getLogger(__name__)
assert(hasattr(parent, 'private_key'))
self._parent = parent
self.user_manager = self.default_user_manager
self.allow_remote_admin = True
def default_user_manager(self, isession, userName, password):
"""
Default user_manager, does nothing much but check for admin
"""
if self.allow_remote_admin and userName in ("admin", "Admin"):
isession.user = UserManager.User.Admin
return True
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment