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