Commit 37f69181 authored by Olivier R-D's avatar Olivier R-D

autopep8

parent e6300bec
......@@ -3,10 +3,13 @@ import logging
from opcua import Client
from opcua import uaprotocol as ua
class SubHandler(object):
"""
Client to subscription. It will receive events from server
"""
def data_change(self, handle, node, val, attr):
print("Python: New data change event", handle, node, val, attr)
......@@ -14,8 +17,7 @@ class SubHandler(object):
print("Python: New event", handle, event)
if __name__ == "__main__":
if __name__ == "__main__":
from IPython import embed
logging.basicConfig(level=logging.WARN)
client = Client("opc.tcp://localhost:53530/OPCUA/SimulationServer/")
......@@ -33,7 +35,7 @@ if __name__ == "__main__":
myuint64 = client.get_node("ns=4;s=UInt64")
myint32 = client.get_node("ns=4;s=Int32")
myuint32 = client.get_node("ns=4;s=UInt32")
var = client.get_node(ua.NodeId("Random1", 5))
print("var is: ", var)
print("value of var is: ", var.get_value())
......@@ -42,7 +44,6 @@ if __name__ == "__main__":
myfloat.set_value(ua.Variant(1.234, ua.VariantType.Float))
print("reading float value: ", myfloat.get_value())
handler = SubHandler()
sub = client.create_subscription(500, handler)
sub.subscribe_data_change(var)
......@@ -52,7 +53,6 @@ if __name__ == "__main__":
result = device.call_method(method, ua.Variant("sin"), ua.Variant(180, ua.VariantType.Double))
print("Mehtod result is: ", result)
embed()
client.close_session()
finally:
......
......@@ -5,6 +5,7 @@ try:
from IPython import embed
except ImportError:
import code
def embed():
vars = globals()
vars.update(locals())
......@@ -15,10 +16,13 @@ except ImportError:
from opcua import Client
from opcua import uaprotocol as ua
class SubHandler(object):
"""
Client to subscription. It will receive events from server
"""
def data_change(self, handle, node, val, attr):
print("Python: New data change event", handle, node, val, attr)
......@@ -26,11 +30,10 @@ class SubHandler(object):
print("Python: New event", handle, event)
if __name__ == "__main__":
if __name__ == "__main__":
logging.basicConfig(level=logging.WARN)
#logger = logging.getLogger("KeepAlive")
#logger.setLevel(logging.DEBUG)
# logger.setLevel(logging.DEBUG)
client = Client("opc.tcp://localhost:4841/freeopcua/server/")
try:
client.connect()
......@@ -39,8 +42,8 @@ if __name__ == "__main__":
print(root.get_children())
print(root.get_browse_name())
#var = client.get_node(ua.NodeId(1002, 2))
#print(var)
#print(var.get_value())
# print(var)
# print(var.get_value())
#var.set_value(ua.Variant([23], ua.VariantType.Int64))
state = root.get_child(["0:Objects", "0:Server"])
print(state)
......@@ -52,10 +55,10 @@ if __name__ == "__main__":
handle = sub.subscribe_data_change(myvar)
time.sleep(0.1)
sub.subscribe_events()
#sub.unsubscribe(handle)
#sub.delete()
#calling a method on server
# sub.unsubscribe(handle)
# sub.delete()
# calling a method on server
res = obj.call_method("2:multiply", 3, "klk")
print("method result is: ", res)
......
......@@ -5,6 +5,7 @@ try:
from IPython import embed
except ImportError:
import code
def embed():
vars = globals()
vars.update(locals())
......@@ -16,38 +17,43 @@ from opcua import ua, uamethod, Server, Event, ObjectIds
class SubHandler(object):
"""
Client to subscription. It will receive events from server
"""
def data_change(self, handle, node, val, attr):
print("Python: New data change event", handle, node, val, attr)
def event(self, handle, event):
print("Python: New event", handle, event)
#method to be exposed through server
# method to be exposed through server
def func(parent, variant):
return [variant.Value * 2]
#method to be exposed through server
# method to be exposed through server
# uses a decorator to automatically convert to and from variants
@uamethod
def multiply(parent, x, y):
print("multiply method call with parameters: ", x, y)
return x*y
return x * y
if __name__ == "__main__":
#optional setup logging
# optional setup logging
logging.basicConfig(level=logging.WARN)
#logger = logging.getLogger("opcua.address_space")
#logger = logging.getLogger("opcua.internal_server")
#logger.setLevel(logging.DEBUG)
# logger.setLevel(logging.DEBUG)
#logger = logging.getLogger("opcua.subscription_server")
#logger.setLevel(logging.DEBUG)
# logger.setLevel(logging.DEBUG)
# now setup our server
# now setup our server
server = Server()
server.set_endpoint("opc.tcp://localhost:4841/freeopcua/server/")
server.set_server_name("FreeOpcUa Example Server")
......@@ -73,13 +79,13 @@ if __name__ == "__main__":
myevent = server.get_event_object(ObjectIds.BaseEventType)
myevent.Message.Text = "This is my event"
myevent.Severity = 300
# starting!
server.start()
print("Available loggers are: ", logging.Logger.manager.loggerDict.keys())
try:
handler = SubHandler()
#enable following if you want to subscribe to nodes on server side
# enable following if you want to subscribe to nodes on server side
sub = server.create_subscription(500, handler)
handle = sub.subscribe_data_change(myvar)
# trigger event, all subscribed clients wil receive it
......@@ -88,4 +94,3 @@ if __name__ == "__main__":
embed()
finally:
server.stop()
......@@ -15,7 +15,7 @@ from opcua.server import Server
def uamethod(func):
"""
Method decorator to automatically convert
Method decorator to automatically convert
arguments and output to and from variants
"""
def wrapper(parent, *args):
......@@ -23,10 +23,9 @@ def uamethod(func):
return to_variant(result)
return wrapper
def to_variant(*args):
uaargs = []
for arg in args:
uaargs.append(ua.Variant(arg))
return uaargs
......@@ -4,17 +4,21 @@ import pickle
from opcua import ua
class AttributeValue(object):
def __init__(self, value):
self.value = value
self.value_callback = None
self.datachange_callbacks = {}
self.value_callback = None
self.datachange_callbacks = {}
def __str__(self):
return "AttributeValue({})".format(self.value)
__repr__ = __str__
class NodeData(object):
def __init__(self, nodeid):
self.nodeid = nodeid
self.attributes = {}
......@@ -27,6 +31,7 @@ class NodeData(object):
class AttributeService(object):
def __init__(self, aspace):
self.logger = logging.getLogger(__name__)
self._aspace = aspace
......@@ -45,7 +50,9 @@ class AttributeService(object):
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
......@@ -132,7 +139,7 @@ class ViewService(object):
current = nodeid
target = ua.BrowsePathTarget()
target.TargetId = current
target.RemainingPathIndex = 4294967295
target.RemainingPathIndex = 4294967295
res.Targets = [target]
return res
......@@ -140,7 +147,7 @@ class ViewService(object):
with self._aspace.lock:
nodedata = self._aspace.nodes[nodeid]
for ref in nodedata.references:
#FIXME: here we should check other arguments!!
# FIXME: here we should check other arguments!!
if ref.BrowseName == el.TargetName:
return ref.NodeId
self.logger.info("element %s was not found in node %s", el, nodeid)
......@@ -148,6 +155,7 @@ class ViewService(object):
class NodeManagementService(object):
def __init__(self, aspace):
self.logger = logging.getLogger(__name__)
self._aspace = aspace
......@@ -167,19 +175,19 @@ class NodeManagementService(object):
result.StatusCode = ua.StatusCode(ua.StatusCodes.BadNodeIdExists)
return result
nodedata = NodeData(item.RequestedNewNodeId)
#add common attrs
# add common attrs
nodedata.attributes[ua.AttributeIds.NodeId] = AttributeValue(ua.DataValue(ua.Variant(item.RequestedNewNodeId, ua.VariantType.NodeId)))
nodedata.attributes[ua.AttributeIds.BrowseName] = AttributeValue(ua.DataValue(ua.Variant(item.BrowseName, ua.VariantType.QualifiedName)))
nodedata.attributes[ua.AttributeIds.NodeClass] = AttributeValue(ua.DataValue(ua.Variant(item.NodeClass, ua.VariantType.Int32)))
#add requested attrs
# add requested attrs
self._add_nodeattributes(item.NodeAttributes, nodedata)
#add parent
# add parent
if item.ParentNodeId == ua.NodeId():
#self.logger.warning("add_node: creating node %s without parent", item.RequestedNewNodeId)
#self.logger.warning("add_node: creating node %s without parent", item.RequestedNewNodeId)
pass
elif not item.ParentNodeId in self._aspace.nodes:
#self.logger.warning("add_node: while adding node %s, requested parent node %s does not exists", item.RequestedNewNodeId, item.ParentNodeId)
#self.logger.warning("add_node: while adding node %s, requested parent node %s does not exists", item.RequestedNewNodeId, item.ParentNodeId)
result.StatusCode = ua.StatusCode(ua.StatusCodes.BadParentNodeIdInvalid)
return result
else:
......@@ -192,11 +200,11 @@ class NodeManagementService(object):
desc.TypeDefinition = item.TypeDefinition
desc.IsForward = True
self._aspace.nodes[item.ParentNodeId].references.append(desc)
#now add our node to db
# now add our node to db
self._aspace.nodes[item.RequestedNewNodeId] = nodedata
#add type definition
# add type definition
if item.TypeDefinition != ua.NodeId():
addref = ua.AddReferencesItem()
addref.SourceNodeId = item.RequestedNewNodeId
......@@ -230,10 +238,10 @@ class NodeManagementService(object):
rdesc.NodeClass = addref.TargetNodeClass
bname = self._aspace.get_attribute_value(addref.TargetNodeId, ua.AttributeIds.BrowseName).Value.Value
if bname:
rdesc.BrowseName = bname
rdesc.BrowseName = bname
dname = self._aspace.get_attribute_value(addref.TargetNodeId, ua.AttributeIds.DisplayName).Value.Value
if dname:
rdesc.DisplayName = dname
rdesc.DisplayName = dname
self._aspace.nodes[addref.SourceNodeId].references.append(rdesc)
return ua.StatusCode()
......@@ -241,7 +249,7 @@ class NodeManagementService(object):
if item.SpecifiedAttributes & getattr(ua.NodeAttributesMask, name):
dv = ua.DataValue(ua.Variant(getattr(item, name), vtype))
nodedata.attributes[getattr(ua.AttributeIds, name)] = AttributeValue(dv)
def _add_nodeattributes(self, item, nodedata):
item = ua.downcast_extobject(item)
self._add_node_attr(item, nodedata, "AccessLevel", ua.VariantType.Byte)
......@@ -270,6 +278,7 @@ class NodeManagementService(object):
class MethodService(object):
def __init__(self, aspace):
self.logger = logging.getLogger(__name__)
self._aspace = aspace
......@@ -281,9 +290,9 @@ class MethodService(object):
results.append(self._call(method))
return results
def _call(self, method):
def _call(self, method):
res = ua.CallMethodResult()
if method.ObjectId not in self._aspace.nodes or method.MethodId not in self._aspace.nodes:
if method.ObjectId not in self._aspace.nodes or method.MethodId not in self._aspace.nodes:
res.StatusCode = ua.StatusCode(ua.StatusCodes.BadNodeIdInvalid)
else:
node = self._aspace.nodes[method.MethodId]
......@@ -298,19 +307,21 @@ class MethodService(object):
self.logger.exception("Error executing method call %s, an exception was raised: ", method)
res.StatusCode = ua.StatusCode(ua.StatusCodes.BadUnexpectedError)
return res
class AddressSpace(object):
"""
The address space object stores all the nodes og the OPC-UA server
and helper methods.
It is NOT threadsafe, lock the lock object before reading of modifying
a node
"""
def __init__(self):
self.logger = logging.getLogger(__name__)
self.nodes = {}
self.lock = RLock() #FIXME: should use multiple reader, one writter pattern
self.lock = RLock() # FIXME: should use multiple reader, one writter pattern
self._datachange_callback_counter = 200
self._handle_to_attribute_map = {}
......@@ -386,13 +397,3 @@ class AddressSpace(object):
with self.lock:
node = self.nodes[methodid]
node.call = callback
......@@ -12,6 +12,7 @@ import opcua.utils as utils
class BinaryClient(object):
"""
low level OPC-UA client.
implement all(well..one day) methods defined in opcua spec
......@@ -19,11 +20,12 @@ class BinaryClient(object):
in python most of the structures are defined in
uaprotocol_auto.py and uaprotocol_hand.py
"""
def __init__(self):
self.logger = logging.getLogger(__name__)
self._socket = None
self._do_stop = False
self._security_token = ua.ChannelSecurityToken()
self._security_token = ua.ChannelSecurityToken()
self._authentication_token = ua.NodeId()
self._sequence_number = 0
self._request_id = 0
......@@ -43,9 +45,9 @@ class BinaryClient(object):
self._thread.start()
def _send_request(self, request, callback=None, timeout=1000):
#HACK to make sure we can convert our request to binary before increasing request counter etc ...
# HACK to make sure we can convert our request to binary before increasing request counter etc ...
request.to_binary()
#END HACK
# END HACK
with self._lock:
request.RequestHeader = self._create_request_header(timeout)
hdr = ua.Header(ua.MessageType.SecureMessage, ua.ChunkType.Single, self._security_token.ChannelId)
......@@ -62,7 +64,7 @@ class BinaryClient(object):
return data
def _check_answer(self, data, context):
data = data.copy(50)#FIXME check max length nodeid + responseheader
data = data.copy(50) # FIXME check max length nodeid + responseheader
typeid = ua.NodeId.from_binary(data)
if typeid == ua.FourByteNodeId(ua.ObjectIds.ServiceFault_Encoding_DefaultBinary):
self.logger.warning("ServiceFault from server received %s", context)
......@@ -159,14 +161,13 @@ class BinaryClient(object):
hdr.RequestId = self._request_id
return hdr
def connect_socket(self, host, port):
"""
connect to server socket and start receiving thread
"""
self.logger.info("opening connection")
self._socket = socket.create_connection((host, port))
self._socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)#nodelay ncessary to avoid packing in one frame, some servers do not like it
self._socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) # nodelay ncessary to avoid packing in one frame, some servers do not like it
self.start()
def disconnect_socket(self):
......@@ -183,7 +184,7 @@ class BinaryClient(object):
self._callbackmap[0] = future
self._write_socket(header, hello)
return ua.Acknowledge.from_binary(future.result())
def open_secure_channel(self, params):
self.logger.info("open_secure_channel")
request = ua.OpenSecureChannelRequest()
......@@ -229,7 +230,7 @@ class BinaryClient(object):
request.DeleteSubscriptions = deletesubscriptions
data = self._send_request(request)
ua.CloseSessionResponse.from_binary(data)
#response.ResponseHeader.ServiceResult.check() #disabled, it seems we sent wrong session Id, but where is the sessionId supposed to be sent???
# response.ResponseHeader.ServiceResult.check() #disabled, it seems we sent wrong session Id, but where is the sessionId supposed to be sent???
def browse(self, parameters):
self.logger.info("browse")
......@@ -281,7 +282,7 @@ class BinaryClient(object):
seqhdr = self._create_sequence_header()
self._write_socket(hdr, symhdr, seqhdr, request)
#some servers send a response here, most do not ... so we ignore
# some servers send a response here, most do not ... so we ignore
def translate_browsepaths_to_nodeids(self, browsepaths):
self.logger.info("translate_browsepath_to_nodeid")
......@@ -315,7 +316,7 @@ class BinaryClient(object):
def publish(self, acks=None):
self.logger.info("publish")
if acks is None:
if acks is None:
acks = []
request = ua.PublishRequest()
request.Parameters.SubscriptionAcknowledgements = acks
......@@ -326,10 +327,9 @@ class BinaryClient(object):
response = ua.PublishResponse.from_binary(future.result())
try:
self._publishcallbacks[response.Parameters.SubscriptionId](response.Parameters)
except Exception as ex: #we call client code, catch everything!
except Exception as ex: # we call client code, catch everything!
self.logger.exception("Exception while calling user callback")
def create_monitored_items(self, params):
self.logger.info("create_monitored_items")
request = ua.CreateMonitoredItemsRequest()
......@@ -356,14 +356,11 @@ class BinaryClient(object):
response = ua.AddNodesResponse.from_binary(data)
response.ResponseHeader.ServiceResult.check()
return response.Results
def call(self, methodstocall):
request = ua.CallRequest()
request.Parameters.MethodsToCall = methodstocall
request.Parameters.MethodsToCall = methodstocall
data = self._send_request(request)
response = ua.CallResponse.from_binary(data)
response.ResponseHeader.ServiceResult.check()
return response.Results
......@@ -14,10 +14,13 @@ from opcua.uaprocessor import UAProcessor
logger = logging.getLogger(__name__)
class BinaryServer(Thread):
"""
Socket server forwarding request to internal server
"""
def __init__(self, internal_server, hostname, port):
Thread.__init__(self)
self.socket_server = None
......@@ -33,10 +36,10 @@ class BinaryServer(Thread):
def run(self):
logger.warning("Listening on %s:%s", self.hostname, self.port)
socketserver.TCPServer.allow_reuse_address = True #get rid of address already in used warning
socketserver.TCPServer.allow_reuse_address = True # get rid of address already in used warning
self.socket_server = ThreadingTCPServer((self.hostname, self.port), UAHandler)
#self.socket_server.daemon_threads = True # this will force a shutdown of all threads, maybe too hard
self.socket_server.internal_server = self.iserver #allow handler to acces server properties
# self.socket_server.daemon_threads = True # this will force a shutdown of all threads, maybe too hard
self.socket_server.internal_server = self.iserver # allow handler to acces server properties
with self._cond:
self._cond.notify_all()
self.socket_server.serve_forever()
......@@ -47,6 +50,7 @@ class BinaryServer(Thread):
class UAHandler(socketserver.BaseRequestHandler):
"""
The RequestHandler class for our server.
......@@ -65,5 +69,3 @@ class UAHandler(socketserver.BaseRequestHandler):
class ThreadingTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass
from __future__ import division #support for python2
from __future__ import division # support for python2
from threading import Thread, Condition
import logging
try:
from urllib.parse import urlparse
except ImportError: #support for python2
except ImportError: # support for python2
from urlparse import urlparse
from opcua import uaprotocol as ua
......@@ -12,14 +12,16 @@ from opcua import utils
class KeepAlive(Thread):
"""
Used by Client to keep session opened.
OPCUA defines timeout both for sessions and secure channel
"""
def __init__(self, client, timeout):
Thread.__init__(self)
self.logger = logging.getLogger(__name__)
if timeout == 0: # means no timeout bu we do not trust such servers
if timeout == 0: # means no timeout bu we do not trust such servers
timeout = 360000
self.timeout = timeout
self.client = client
......@@ -31,7 +33,7 @@ class KeepAlive(Thread):
server_state = self.client.get_node(ua.FourByteNodeId(ua.ObjectIds.Server_ServerStatus_State))
while not self._dostop:
with self._cond:
self._cond.wait(self.timeout/1000)
self._cond.wait(self.timeout / 1000)
if self._dostop:
break
self.logger.debug("renewing channel")
......@@ -48,8 +50,9 @@ class KeepAlive(Thread):
class Client(object):
"""
High level client to connect to an OPC-UA server.
High level client to connect to an OPC-UA server.
This class makes it easy to connect and browse address space.
It attemps to expose as much functionality as possible
but if you want to do to special things you will probably need
......@@ -57,6 +60,7 @@ class Client(object):
which offers a raw OPC-UA interface.
"""
def __init__(self, url):
"""
used url argument to connect to server.
......@@ -65,8 +69,8 @@ class Client(object):
"""
self.logger = logging.getLogger(__name__)
self.server_url = urlparse(url)
self.name = "Pure Python Client"
self.description = self.name
self.name = "Pure Python Client"
self.description = self.name
self.application_uri = "urn:freeopcua:client"
self.product_uri = "urn:freeopcua.github.no:client"
self.security_policy_uri = "http://opcfoundation.org/UA/SecurityPolicy#None"
......@@ -124,7 +128,7 @@ class Client(object):
Send OPC-UA hello to server
"""
ack = self.bclient.send_hello(self.server_url.geturl())
#FIXME check ack
# FIXME check ack
def open_secure_channel(self, renew=False):
"""
......@@ -161,14 +165,14 @@ class Client(object):
params = ua.CreateSessionParameters()
params.ClientNonce = utils.create_nonce()
params.ClientCertificate = b''
params.ClientDescription = desc
params.ClientDescription = desc
params.EndpointUrl = self.server_url.geturl()
params.SessionName = self.description + " Session" + str(self._session_counter)
params.RequestedSessionTimeout = 3600000
params.MaxResponseMessageSize = 0 #means not max size
params.MaxResponseMessageSize = 0 # means not max size
response = self.bclient.create_session(params)
self.session_timeout = response.RevisedSessionTimeout
self.keepalive = KeepAlive(self, min(self.session_timeout, self.secure_channel_timeout) * 0.7) #0.7 is from spec
self.keepalive = KeepAlive(self, min(self.session_timeout, self.secure_channel_timeout) * 0.7) # 0.7 is from spec
self.keepalive.start()
return response
......@@ -224,8 +228,3 @@ class Client(object):
def get_namespace_index(self, uri):
uries = self.get_namespace_array()
return uries.index(uri)
......@@ -9,6 +9,7 @@ import uuid
class Event(object):
"""
Create an event based on an event type. Per default is BaseEventType used.
arguments are:
......@@ -16,6 +17,7 @@ class Event(object):
source: The emiting source for the node, either an objectId, NodeId or a Node
etype: The event type, either an objectId, a NodeId or a Node object
"""
def __init__(self, isession, etype=ObjectIds.BaseEventType, source=ObjectIds.Server):
self.isession = isession
......@@ -25,16 +27,16 @@ class Event(object):
self.node = Node(self.isession, etype)
else:
self.node = Node(self.isession, ua.NodeId(etype))
self.set_members_from_node(self.node)
if isinstance(source, Node):
self.SourceNode = source.NodeId
self.SourceNode = source.NodeId
elif isinstance(etype, ua.NodeId):
self.SourceNode = source.NodeId
self.SourceNode = source.NodeId
else:
self.SourceNode = ua.NodeId(source)
#set some default values for attributes from BaseEventType, thus that all event must have
# set some default values for attributes from BaseEventType, thus that all event must have
self.EventId = uuid.uuid4().bytes
self.EventType = self.node.nodeid
self.LocaleTime = datetime.now()
......@@ -44,7 +46,7 @@ class Event(object):
self.Severity = ua.Variant(1, ua.VariantType.UInt16)
self.SourceName = "Server"
#og set some node attributed we also are expected to have
# og set some node attributed we also are expected to have
self.BrowseName = self.node.get_browse_name()
self.DisplayName = self.node.get_display_name()
self.NodeId = self.node.nodeid
......@@ -63,5 +65,3 @@ class Event(object):
for desc in references:
node = Node(self.isession, desc.NodeId)
setattr(self, desc.BrowseName.Name, node.get_value())
......@@ -10,7 +10,7 @@ from threading import Thread
from enum import Enum
import functools
try:
#we prefer to use bundles asyncio version, otherwise fallback to trollius
# we prefer to use bundles asyncio version, otherwise fallback to trollius
import asyncio
except ImportError:
import trollius as asyncio
......@@ -30,6 +30,7 @@ from opcua import standard_address_space
class ThreadLoop(Thread):
def __init__(self):
Thread.__init__(self)
self.logger = logging.getLogger(__name__)
......@@ -69,7 +70,9 @@ class SessionState(Enum):
Activated = 1
Closed = 2
class InternalServer(object):
def __init__(self):
self.logger = logging.getLogger(__name__)
self.endpoints = []
......@@ -81,13 +84,13 @@ class InternalServer(object):
self.method_service = MethodService(self.aspace)
self.node_mgt_service = NodeManagementService(self.aspace)
standard_address_space.fill_address_space(self.node_mgt_service)
#standard_address_space.fill_address_space_from_disk(self.aspace)
# standard_address_space.fill_address_space_from_disk(self.aspace)
self.loop = ThreadLoop()
self.subcsription_service = SubscriptionService(self.loop, self.aspace)
# create a session to use on server side
self.isession = InternalSession(self, self.aspace, self.subcsription_service, "Internal")
self.isession = InternalSession(self, self.aspace, self.subcsription_service, "Internal")
self._timer = None
self.current_time_node = Node(self.isession, ua.NodeId(ua.ObjectIds.Server_ServerStatus_CurrentTime))
uries = ["http://opcfoundation.org/UA/"]
......@@ -100,7 +103,7 @@ class InternalServer(object):
def dump_address_space(self, path):
self.aspace.dump(path)
def start(self):
def start(self):
self.logger.info("starting internal server")
self.loop.start()
Node(self.isession, ua.NodeId(ua.ObjectIds.Server_ServerStatus_State)).set_value(0)
......@@ -124,15 +127,17 @@ class InternalServer(object):
def get_endpoints(self, params=None):
self.logger.info("get endpoint")
#FIXME check params
# FIXME check params
return self.endpoints[:]
def create_session(self, name):
return InternalSession(self, self.aspace, self.subcsription_service, name)
class InternalSession(object):
_counter = 10
_auth_counter = 1000
def __init__(self, internal_server, aspace, submgr, name):
self.logger = logging.getLogger(__name__)
self.iserver = internal_server
......@@ -144,14 +149,14 @@ class InternalSession(object):
InternalSession._counter += 1
self.authentication_token = ua.NodeId(self._auth_counter)
InternalSession._auth_counter += 1
self.nonce = utils.create_nonce()
self.nonce = utils.create_nonce()
self.subscriptions = []
self.logger.warning("Created internal session %s", self.name)
self._lock = Lock()
def __str__(self):
return "InternalSession(name:{}, id:{}, auth_token:{})".format(self.name, self.session_id, self.authentication_token)
def get_endpoints(self, params=None):
return self.iserver.get_endpoints(params)
......@@ -160,7 +165,7 @@ class InternalSession(object):
result = ua.CreateSessionResult()
result.SessionId = self.session_id
result.AuthenticationToken = self.authentication_token
result.AuthenticationToken = self.authentication_token
result.RevisedSessionTimeout = params.RequestedSessionTimeout
result.MaxRequestMessageSize = 65536
result.ServerNonce = self.nonce
......@@ -230,10 +235,8 @@ class InternalSession(object):
def delete_monitored_items(self, params):
return self.subscription_service.delete_monitored_items(params)
def publish(self, acks=None):
if acks is None:
acks = []
return self.subscription_service.publish(acks)
"""
High level node object, to access node attribute
High level node object, to access node attribute
and browse address space
"""
import opcua.uaprotocol as ua
class Node(object):
"""
High level node object, to access node attribute,
browse and populate address space
"""
def __init__(self, server, nodeid):
self.server = server
self.nodeid = None
......@@ -21,6 +24,7 @@ class Node(object):
self.nodeid = ua.NodeId(nodeid, 0)
else:
raise Exception("argument to node must be a NodeId object or a string defining a nodeid found {} of type {}".format(nodeid, type(nodeid)))
def __eq__(self, other):
if isinstance(other, Node) and self.nodeid == other.nodeid:
return True
......@@ -61,7 +65,7 @@ class Node(object):
def get_value(self):
"""
Get value of a node. Only variables(properties) have values.
Get value of a node. Only variables(properties) have values.
An exception will be generated for other node types.
"""
result = self.get_attribute(ua.AttributeIds.Value)
......@@ -69,11 +73,11 @@ class Node(object):
def set_value(self, value, varianttype=None):
"""
Set value of a node. Only variables(properties) have values.
Set value of a node. Only variables(properties) have values.
An exception will be generated for other node types.
"""
variant = None
if type(value) == ua.Variant:
if isinstance(value, ua.Variant):
variant = value
else:
variant = ua.Variant(value, varianttype)
......@@ -148,7 +152,7 @@ class Node(object):
desc.IncludeSubtypes = includesubtypes
desc.NodeClassMask = nodeclassmask
desc.ResultMask = ua.BrowseResultMask.All
desc.NodeId = self.nodeid
params = ua.BrowseParameters()
params.NodesToBrowse.append(desc)
......@@ -172,7 +176,7 @@ class Node(object):
el.ReferenceTypeId = ua.TwoByteNodeId(ua.ObjectIds.HierarchicalReferences)
el.IsInverse = False
el.IncludeSubtypes = True
if type(item) == ua.QualifiedName:
if isinstance(item, ua.QualifiedName):
el.TargetName = item
else:
el.TargetName = ua.QualifiedName.from_string(item)
......@@ -183,7 +187,7 @@ class Node(object):
result = self.server.translate_browsepaths_to_nodeids([bpath])
result = result[0]
result.StatusCode.check()
#FIXME: seems this method may return several nodes
# FIXME: seems this method may return several nodes
return Node(self.server, result.Targets[0].TargetId)
def add_folder(self, *args):
......@@ -194,11 +198,11 @@ class Node(object):
"""
nodeid, qname = self._parse_add_args(*args)
return self._add_folder(nodeid, qname)
def _add_folder(self, nodeid, qname):
node = ua.AddNodesItem()
node.RequestedNewNodeId = nodeid
node.BrowseName = qname
node.RequestedNewNodeId = nodeid
node.BrowseName = qname
node.NodeClass = ua.NodeClass.Object
node.ParentNodeId = self.nodeid
node.ReferenceTypeId = ua.NodeId.from_string("i=35")
......@@ -211,7 +215,7 @@ class Node(object):
results = self.server.add_nodes([node])
results[0].StatusCode.check()
return Node(self.server, nodeid)
def add_object(self, *args):
"""
create a child node object
......@@ -220,13 +224,13 @@ class Node(object):
"""
nodeid, qname = self._parse_add_args(*args)
return self._add_object(nodeid, qname)
def _add_object(self, nodeid, qname):
node = ua.AddNodesItem()
node.RequestedNewNodeId = nodeid
node.BrowseName = qname
node.RequestedNewNodeId = nodeid
node.BrowseName = qname
node.NodeClass = ua.NodeClass.Object
node.ParentNodeId = self.nodeid
node.ParentNodeId = self.nodeid
node.ReferenceTypeId = ua.NodeId.from_string("i=35")
node.TypeDefinition = ua.NodeId(ua.ObjectIds.BaseObjectType)
attrs = ua.ObjectAttributes()
......@@ -247,7 +251,7 @@ class Node(object):
nodeid, qname = self._parse_add_args(*args[:2])
val = self._to_variant(*args[2:])
return self._add_variable(nodeid, qname, val, isproperty=True)
def add_variable(self, *args):
"""
create a child node variable
......@@ -266,10 +270,10 @@ class Node(object):
def _add_variable(self, nodeid, qname, val, isproperty=False):
node = ua.AddNodesItem()
node.RequestedNewNodeId = nodeid
node.BrowseName = qname
node.RequestedNewNodeId = nodeid
node.BrowseName = qname
node.NodeClass = ua.NodeClass.Variable
node.ParentNodeId = self.nodeid
node.ParentNodeId = self.nodeid
if isproperty:
node.ReferenceTypeId = ua.NodeId(ua.ObjectIds.HasProperty)
node.TypeDefinition = ua.NodeId(ua.ObjectIds.PropertyType)
......@@ -281,7 +285,7 @@ class Node(object):
attrs.DisplayName = ua.LocalizedText(qname.Name)
attrs.DataType = self._guess_uatype(val)
attrs.Value = val
attrs.ValueRank = 0
attrs.ValueRank = 0
attrs.WriteMask = 0
attrs.UserWriteMask = 0
attrs.Historizing = 0
......@@ -302,17 +306,17 @@ class Node(object):
nodeid, qname = self._parse_add_args(*args[:2])
callback = args[2]
if len(args) > 3:
inputs = args[3]
inputs = args[3]
if len(args) > 4:
outputs = args[4]
outputs = args[4]
return self._add_method(nodeid, qname, callback, inputs, outputs)
def _add_method(self, nodeid, qname, callback, inputs, outputs):
node = ua.AddNodesItem()
node.RequestedNewNodeId = nodeid
node.BrowseName = qname
node.RequestedNewNodeId = nodeid
node.BrowseName = qname
node.NodeClass = ua.NodeClass.Method
node.ParentNodeId = self.nodeid
node.ParentNodeId = self.nodeid
node.ReferenceTypeId = ua.NodeId.from_string("i=47")
#node.TypeDefinition = ua.NodeId(ua.ObjectIds.BaseObjectType)
attrs = ua.MethodAttributes()
......@@ -332,19 +336,18 @@ class Node(object):
method.add_property(qname.NamespaceIndex, "OutputArguments", [self._vtype_to_argument(vtype) for vtype in outputs])
self.server.add_method_callback(method.nodeid, callback)
return method
def call_method(self, methodid, *args):
"""
Call an OPC-UA method. methodid is browse name of child method or the
nodeid of method as a NodeId object
Call an OPC-UA method. methodid is browse name of child method or the
nodeid of method as a NodeId object
arguments are variants or python object convertible to variants.
which may be of different types
returns a list of variants which are output of the method
returns a list of variants which are output of the method
"""
if type(methodid) is str:
if isinstance(methodid, str):
methodid = self.get_child(methodid).nodeid
elif type(methodid) is Node:
elif isinstance(methodid, Node):
methodid = methodid.nodeid
arguments = []
......@@ -391,21 +394,20 @@ class Node(object):
return ua.NodeId(getattr(ua.ObjectIds, variant.VariantType.name))
def _parse_add_args(self, *args):
if type(args[0]) is ua.NodeId:
if isinstance(args[0], ua.NodeId):
return args[0], args[1]
elif type(args[0]) is str:
elif isinstance(args[0], str):
return ua.NodeId.from_string(args[0]), ua.QualifiedName.from_string(args[1])
elif type(args[0]) is int:
elif isinstance(args[0], int):
return generate_nodeid(args[0]), ua.QualifiedName(args[1], args[0])
else:
raise TypeError("Add methods takes a nodeid and a qualifiedname as argument, received %s" % args)
__nodeid_counter = 2000
def generate_nodeid(idx):
global __nodeid_counter
__nodeid_counter += 1
return ua.NodeId(__nodeid_counter, idx)
......@@ -16,6 +16,7 @@ from opcua import Node, Subscription, ObjectIds, Event
class Server(object):
def __init__(self):
self.logger = logging.getLogger(__name__)
self.endpoint = "opc.tcp://localhost:4841/freeopcua/server/"
......@@ -26,7 +27,7 @@ class Server(object):
self.iserver = InternalServer()
self.bserver = None
#setup some expected values
# setup some expected values
self.register_namespace(self.server_uri)
sa_node = self.get_node(ua.NodeId(ua.ObjectIds.Server_ServerArray))
sa_node.set_value([self.server_uri])
......@@ -38,7 +39,7 @@ class Server(object):
return self.iserver.get_endpoints()
def _setup_server_nodes(self):
#to be called just before starting server since it needs all parameters to be setup
# to be called just before starting server since it needs all parameters to be setup
self._set_endpoints()
def _set_endpoints(self):
......@@ -48,9 +49,9 @@ class Server(object):
appdesc = ua.ApplicationDescription()
appdesc.ApplicationName = ua.LocalizedText(self.name)
appdesc.ApplicationUri = self.server_uri
appdesc.ApplicationUri = self.server_uri
appdesc.ApplicationType = ua.ApplicationType.Server
appdesc.ProductUri = self.product_uri
appdesc.ProductUri = self.product_uri
appdesc.DiscoveryUrls.append(self.endpoint.geturl())
edp = ua.EndpointDescription()
......@@ -116,7 +117,7 @@ class Server(object):
uries = ns_node.get_value()
uries.append(uri)
ns_node.set_value(uries)
return (len(uries)-1)
return (len(uries) - 1)
def get_namespace_index(self, uri):
uries = self.get_namespace_array()
......@@ -124,8 +125,3 @@ class Server(object):
def get_event_object(self, etype=ObjectIds.BaseEventType, source=ObjectIds.Server):
return Event(self.iserver.isession, etype, source)
......@@ -23,9 +23,8 @@ def fill_address_space(nodeservice):
create_standard_address_space_Part11(nodeservice)
create_standard_address_space_Part13(nodeservice)
def fill_address_space_from_disk(aspace):
dirname = os.path.dirname(opcua.__file__)
path = os.path.join(dirname, "binary_address_space.pickle")
aspace.load(path)
......@@ -12,14 +12,16 @@ from opcua import ObjectIds
from opcua import AttributeIds
from opcua import Event
class EventResult():
def __str__(self):
return "EventResult({})".format([str(k) + ":" + str(v) for k, v in self.__dict__.items()])
__repr__ = __str__
class SubscriptionItemData():
def __init__(self):
self.node = None
self.client_handle = None
......@@ -27,18 +29,20 @@ class SubscriptionItemData():
self.attribute = None
self.mfilter = None
class Subscription(object):
def __init__(self, server, params, handler):
self.logger = logging.getLogger(__name__)
self.server = server
self._client_handle = 200
self._handler = handler
self.parameters = params #move to data class
self.parameters = params # move to data class
self._monitoreditems_map = {}
self._lock = RLock()
self.subscription_id = None
response = self.server.create_subscription(params, self.publish_callback)
self.subscription_id = response.SubscriptionId #move to data class
self.subscription_id = response.SubscriptionId # move to data class
self.server.publish()
self.server.publish()
......@@ -63,7 +67,7 @@ class Subscription(object):
self._call_status(statuschange)
else:
self.logger.warn("Notification type not supported yet for notification %s", notif)
ack = ua.SubscriptionAcknowledgement()
ack.SubscriptionId = self.subscription_id
ack.SequenceNumber = publishresult.NotificationMessage.SequenceNumber
......@@ -133,7 +137,7 @@ class Subscription(object):
rv = ua.ReadValueId()
rv.NodeId = node.nodeid
rv.AttributeId = attr
#rv.IndexRange //We leave it null, then the entire array is returned
# rv.IndexRange //We leave it null, then the entire array is returned
mparams = ua.MonitoringParameters()
self._client_handle += 1
mparams.ClientHandle = self._client_handle
......@@ -143,7 +147,7 @@ class Subscription(object):
if mfilter:
mparams.Filter = mfilter
mir = ua.MonitoredItemCreateRequest()
mir = ua.MonitoredItemCreateRequest()
mir.ItemToMonitor = rv
mir.MonitoringMode = ua.MonitoringMode.Reporting
mir.RequestedParameters = mparams
......@@ -156,7 +160,7 @@ class Subscription(object):
results = self.server.create_monitored_items(params)
result = results[0]
result.StatusCode.check()
data = SubscriptionItemData()
data.client_handle = mparams.ClientHandle
data.node = node
......@@ -176,6 +180,3 @@ class Subscription(object):
params.MonitoredItemIds = [handle]
results = self.server.delete_monitored_items(params)
results[0].check()
......@@ -8,7 +8,9 @@ import logging
from opcua import ua
class SubscriptionService(object):
def __init__(self, loop, aspace):
self.logger = logging.getLogger(__name__)
self.loop = loop
......@@ -90,7 +92,7 @@ class SubscriptionService(object):
def republish(self, params):
with self._lock:
if not params.SubscriptionId in self.subscriptions:
#what should I do?
# what should I do?
return ua.NotificationMessage()
return self.subscriptions[params.SubscriptionId].republish(params.RetransmitSequenceNumber)
......@@ -100,17 +102,18 @@ class SubscriptionService(object):
sub.trigger_event(event)
class MonitoredItemData(object):
def __init__(self):
self.client_handle = None
self.callback_handle = None
self.monitored_item_id = None
self.parameters = None
self.mode = None
class InternalSubscription(object):
def __init__(self, manager, data, addressspace, callback):
self.logger = logging.getLogger(__name__)
self.aspace = addressspace
......@@ -128,18 +131,18 @@ class InternalSubscription(object):
self._triggered_statuschanges = []
self._notification_seq = 1
self._not_acknowledged_results = {}
self._startup = True
self._startup = True
self._keep_alive_count = 0
self._publish_cycles_count = 0
self._stopev = False
def __str__(self):
return "Subscription(id:{})".format(self.data.SubscriptionId)
def start(self):
self.logger.debug("starting subscription %s", self.data.SubscriptionId)
self._subscription_loop()
def stop(self):
self.logger.debug("stopping subscription %s", self.data.SubscriptionId)
self._stopev = True
......@@ -151,7 +154,7 @@ class InternalSubscription(object):
def _subscription_loop(self):
#self.logger.debug("%s loop", self)
if not self._stopev:
self.manager.loop.call_later(self.data.RevisedPublishingInterval/1000.0, self._sub_loop)
self.manager.loop.call_later(self.data.RevisedPublishingInterval / 1000.0, self._sub_loop)
def _sub_loop(self):
self.publish_results()
......@@ -167,14 +170,14 @@ class InternalSubscription(object):
self._keep_alive_count += 1
return False
def publish_results(self):
def publish_results(self):
if self._publish_cycles_count > self.data.RevisedLifetimeCount:
self.logger.warn("Subscription %s has expired, publish cycle count(%s) > lifetime count (%s)", self, self._publish_cycles_count, self.data.RevisedLifetimeCount)
#FIXME this will never be send since we do not have publish request anyway
self.trigger_statuschange(ua.StatusCode(ua.StatusCodes.BadTimeout))
# FIXME this will never be send since we do not have publish request anyway
self.trigger_statuschange(ua.StatusCode(ua.StatusCodes.BadTimeout))
self._stopev = True
with self._lock:
if self.has_published_results(): #FIXME: should we pop a publish request here? or we do not care?
if self.has_published_results(): # FIXME: should we pop a publish request here? or we do not care?
self._publish_cycles_count += 1
result = self._pop_publish_result()
self.callback(result)
......@@ -185,7 +188,7 @@ class InternalSubscription(object):
if self._triggered_datachanges:
notif = ua.DataChangeNotification()
notif.MonitoredItems = self._triggered_datachanges[:]
self._triggered_datachanges = []
self._triggered_datachanges = []
self.logger.debug("sending datachanges nontification with %s events", len(notif.MonitoredItems))
result.NotificationMessage.NotificationData.append(notif)
if self._triggered_events:
......@@ -205,7 +208,7 @@ class InternalSubscription(object):
result.AvailableSequenceNumbers = list(self._not_acknowledged_results.keys())
self._not_acknowledged_results[result.NotificationMessage.SequenceNumber] = result
return result
def trigger_statuschange(self, code):
self._triggered_statuschanges.append(code)
......@@ -248,11 +251,11 @@ class InternalSubscription(object):
result = ua.MonitoredItemCreateResult()
if mdata.monitored_item_id == params.MonitoredItemId:
result.RevisedSamplingInterval = self.data.RevisedPublishingInterval
result.RevisedQueueSize = ua.downcast_extobject(params.RequestedParameters.QueueSize) #FIXME check and use value
result.RevisedQueueSize = ua.downcast_extobject(params.RequestedParameters.QueueSize) # FIXME check and use value
result.FilterResult = params.RequestedParameters.Filter
mdata.parameters = result
return result
#FIXME modify event subscriptions
# FIXME modify event subscriptions
result = ua.MonitoredItemCreateResult()
result.StatusCode(ua.StatusCodes.BadMonitoredItemIdInvalid)
return result
......@@ -261,7 +264,7 @@ class InternalSubscription(object):
with self._lock:
result = ua.MonitoredItemCreateResult()
result.RevisedSamplingInterval = self.data.RevisedPublishingInterval
result.RevisedQueueSize = params.RequestedParameters.QueueSize #FIXME check and use value
result.RevisedQueueSize = params.RequestedParameters.QueueSize # FIXME check and use value
result.FilterResult = ua.downcast_extobject(params.RequestedParameters.Filter)
self._monitored_item_counter += 1
result.MonitoredItemId = self._monitored_item_counter
......@@ -271,7 +274,7 @@ class InternalSubscription(object):
mdata.parameters = result
mdata.mode = params.MonitoringMode
mdata.client_handle = params.RequestedParameters.ClientHandle
mdata.monitored_item_id = result.MonitoredItemId
mdata.monitored_item_id = result.MonitoredItemId
self._monitored_items[result.MonitoredItemId] = mdata
......@@ -284,7 +287,7 @@ class InternalSubscription(object):
self.logger.debug("adding callback return status %s and handle %s", result.StatusCode, handle)
mdata.callback_handle = handle
self._monitored_datachange[handle] = result.MonitoredItemId
#force data change event generation
# force data change event generation
self.trigger_datachange(handle, params.ItemToMonitor.NodeId, params.ItemToMonitor.AttributeId)
return result
......@@ -312,7 +315,6 @@ class InternalSubscription(object):
self._monitored_items.pop(mid)
return ua.StatusCode()
def datachange_callback(self, handle, value):
self.logger.info("subscription %s: datachange callback called with handle '%s' and value '%s'", self, handle, value.Value)
event = ua.MonitoredItemNotification()
......@@ -354,9 +356,3 @@ class InternalSubscription(object):
except AttributeError:
fields.append(ua.Variant())
return fields
This diff is collapsed.
......@@ -5,7 +5,6 @@ from opcua.uaprotocol_auto import *
from opcua.uaprotocol_hand import *
# FIXME: this is really crappy, should thing about a better implementation
# maybe never inherit extensionobject and parse only body....
def downcast_extobject(item):
......@@ -15,5 +14,3 @@ def downcast_extobject(item):
classname = objectidname.split("_")[0]
cmd = "{}.from_binary(utils.Buffer(item.to_binary()))".format(classname)
return eval(cmd)
import io
import struct
import struct
import logging
import opcua.uaprotocol_auto as auto
import opcua.uatypes as uatypes
import opcua.uatypes as uatypes
import opcua.utils as utils
from opcua.object_ids import ObjectIds
from opcua.attribute_ids import AttributeIds
......@@ -14,14 +14,16 @@ logger = logging.getLogger('opcua.uaprotocol')
class SocketClosedException(Exception):
pass
def get_bytes_from_sock(sock, size):
data = utils.recv_all(sock, size)
if len(data) < size: #socket has closed!
if len(data) < size: # socket has closed!
raise SocketClosedException("Server socket has closed")
return io.BytesIO(data)
class Hello(uatypes.FrozenClass):
def __init__(self):
self.ProtocolVersion = 0
self.ReceiveBufferSize = 65536
......@@ -53,9 +55,8 @@ class Hello(uatypes.FrozenClass):
return hello
class MessageType(object):
Invalid = b"INV" #FIXME: check value
Invalid = b"INV" # FIXME: check value
Hello = b"HEL"
Acknowledge = b"ACK"
Error = b"ERR"
......@@ -63,15 +64,16 @@ class MessageType(object):
SecureClose = b"CLO"
SecureMessage = b"MSG"
class ChunkType(object):
Invalid = b"0" #FIXME check
Invalid = b"0" # FIXME check
Single = b"F"
Intermediate = b"C"
Final = b"A"
class Header(uatypes.FrozenClass):
def __init__(self, msgType=None, chunkType=None, channelid=0):
self.MessageType = msgType
self.ChunkType = chunkType
......@@ -113,6 +115,7 @@ class Header(uatypes.FrozenClass):
class ErrorMessage(uatypes.FrozenClass):
def __init__(self):
self.Error = uatypes.StatusCode()
self.Reason = ""
......@@ -137,12 +140,13 @@ class ErrorMessage(uatypes.FrozenClass):
class Acknowledge(uatypes.FrozenClass):
def __init__(self):
self.ProtocolVersion = 0
self.ReceiveBufferSize = 65536
self.SendBufferSize = 65536
self.MaxMessageSize = 0 #No limits
self.MaxChunkCount = 0 #No limits
self.MaxMessageSize = 0 # No limits
self.MaxChunkCount = 0 # No limits
self._freeze()
def to_binary(self):
......@@ -154,8 +158,6 @@ class Acknowledge(uatypes.FrozenClass):
b.append(struct.pack("<I", self.MaxChunkCount))
return b"".join(b)
@staticmethod
def from_binary(data):
ack = Acknowledge()
......@@ -166,7 +168,9 @@ class Acknowledge(uatypes.FrozenClass):
ack.MaxChunkCount = struct.unpack("<I", data.read(4))[0]
return ack
class AsymmetricAlgorithmHeader(uatypes.FrozenClass):
def __init__(self):
self.SecurityPolicyURI = "http://opcfoundation.org/UA/SecurityPolicy#None"
self.SenderCertificate = b""
......@@ -194,6 +198,7 @@ class AsymmetricAlgorithmHeader(uatypes.FrozenClass):
class SymmetricAlgorithmHeader(uatypes.FrozenClass):
def __init__(self):
self.TokenId = 0
self._freeze()
......@@ -213,6 +218,7 @@ class SymmetricAlgorithmHeader(uatypes.FrozenClass):
class SequenceHeader(uatypes.FrozenClass):
def __init__(self):
self.SequenceNumber = None
self.RequestId = None
......@@ -235,54 +241,64 @@ class SequenceHeader(uatypes.FrozenClass):
return "{}(SequenceNumber:{}, RequestId:{} )".format(self.__class__.__name__, self.SequenceNumber, self.RequestId)
__repr__ = __str__
###FIXES for missing switchfield in NodeAttributes classes
# FIXES for missing switchfield in NodeAttributes classes
ana = auto.NodeAttributesMask
class ObjectAttributes(auto.ObjectAttributes):
def __init__(self):
auto.ObjectAttributes.__init__(self)
self.SpecifiedAttributes = ana.DisplayName | ana.Description | ana.WriteMask | ana.UserWriteMask | ana.EventNotifier
class ObjectTypeAttributes(auto.ObjectTypeAttributes):
def __init__(self):
auto.ObjectTypeAttributes.__init__(self)
self.SpecifiedAttributes = ana.DisplayName | ana.Description | ana.WriteMask | ana.UserWriteMask | ana.IsAbstract
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
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
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
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
self.SpecifiedAttributes = ana.DisplayName | ana.Description | ana.WriteMask | ana.UserWriteMask | ana.Executable | ana.UserExecutable
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
self.SpecifiedAttributes = ana.DisplayName | ana.Description | ana.WriteMask | ana.UserWriteMask | ana.IsAbstract | ana.Symmetric | ana.InverseName
class DataTypeAttributes(auto.DataTypeAttributes):
def __init__(self):
auto.DataTypeAttributes.__init__(self)
self.SpecifiedAttributes = ana.DisplayName | ana.Description | ana.WriteMask | ana.UserWriteMask | ana.IsAbstract
self.SpecifiedAttributes = ana.DisplayName | ana.Description | ana.WriteMask | ana.UserWriteMask | ana.IsAbstract
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
self.SpecifiedAttributes = ana.DisplayName | ana.Description | ana.WriteMask | ana.UserWriteMask | ana.ContainsNoLoops | ana.EventNotifier
ObjectIdsInv = {v: k for k, v in ObjectIds.__dict__.items()}
AttributeIdsInv = {v: k for k, v in AttributeIds.__dict__.items()}
This diff is collapsed.
......@@ -3,10 +3,12 @@ import uuid
class Buffer(object):
"""
alternative to io.BytesIO making debug easier
and added a few conveniance methods
"""
def __init__(self, data):
self.logger = logging.getLogger(__name__)
self.data = data
......@@ -45,8 +47,6 @@ class Buffer(object):
return self.data[:size]
def recv_all(socket, size):
"""
Receive up to size bytes from socket
......@@ -60,6 +60,6 @@ def recv_all(socket, size):
size -= len(chunk)
return data
def create_nonce():
return uuid.uuid4().bytes + uuid.uuid4().bytes #seems we need at least 32 bytes not 16 as python gives us...
def create_nonce():
return uuid.uuid4().bytes + uuid.uuid4().bytes # seems we need at least 32 bytes not 16 as python gives us...
This diff is collapsed.
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