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
e084325f
Commit
e084325f
authored
Apr 29, 2016
by
Denis Štogl
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'event_proposal' into events_fixing
parents
d5519ae9
986cf74d
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
56 additions
and
95 deletions
+56
-95
examples/server-events.py
examples/server-events.py
+20
-80
opcua/common/event.py
opcua/common/event.py
+10
-0
opcua/common/manage_nodes.py
opcua/common/manage_nodes.py
+9
-4
tests/tests_server.py
tests/tests_server.py
+17
-11
No files found.
examples/server-events.py
View file @
e084325f
import
sys
sys
.
path
.
insert
(
0
,
".."
)
import
logging
try
:
from
IPython
import
embed
except
ImportError
:
import
code
def
embed
():
vars
=
globals
()
vars
.
update
(
locals
())
shell
=
code
.
InteractiveConsole
(
vars
)
shell
.
interact
()
from
opcua
import
ua
,
uamethod
,
Server
,
EventGenerator
class
SubHandler
(
object
):
"""
Subscription Handler. To receive events from server for a subscription
"""
def
datachange_notification
(
self
,
node
,
val
,
data
):
print
(
"Python: New data change event"
,
node
,
val
)
def
event_notification
(
self
,
event
):
print
(
"Python: New event"
,
event
)
# method to be exposed through server
def
func
(
parent
,
variant
):
ret
=
False
if
variant
.
Value
%
2
==
0
:
ret
=
True
return
[
ua
.
Variant
(
ret
,
ua
.
VariantType
.
Boolean
)]
# method to be exposed through server
# uses a decorator to automatically convert to and from variants
@
uamethod
def
multiply
(
parent
,
x
,
y
):
print
(
"multiply method call with parameters: "
,
x
,
y
)
return
x
*
y
from
opcua
import
ua
,
Server
if
__name__
==
"__main__"
:
# optional: setup logging
logging
.
basicConfig
(
level
=
logging
.
WARN
)
#logger = logging.getLogger("opcua.address_space")
# logger.setLevel(logging.DEBUG)
#logger = logging.getLogger("opcua.internal_server")
# logger.setLevel(logging.DEBUG)
#logger = logging.getLogger("opcua.binary_server_asyncio")
# logger.setLevel(logging.DEBUG)
#logger = logging.getLogger("opcua.uaprocessor")
# logger.setLevel(logging.DEBUG)
logger
=
logging
.
getLogger
(
"opcua.subscription_service"
)
logger
.
setLevel
(
logging
.
DEBUG
)
#
now
setup our server
# setup our server
server
=
Server
()
#server.disable_clock()
#server.set_endpoint("opc.tcp://localhost:4840/freeopcua/server/")
server
.
set_endpoint
(
"opc.tcp://0.0.0.0:4840/freeopcua/server/"
)
server
.
set_server_name
(
"FreeOpcUa Example Server"
)
# setup our own namespace
# setup our own namespace
, not really necessary but should as spec
uri
=
"http://examples.freeopcua.github.io"
idx
=
server
.
register_namespace
(
uri
)
...
...
@@ -77,37 +19,35 @@ if __name__ == "__main__":
objects
=
server
.
get_objects_node
()
# populating our address space
myfolder
=
objects
.
add_folder
(
idx
,
"myEmptyFolder"
)
myobj
=
objects
.
add_object
(
idx
,
"MyObject"
)
myvar
=
myobj
.
add_variable
(
idx
,
"MyVariable"
,
6.7
)
myvar
.
set_writable
()
# Set MyVariable to be writable by clients
myarrayvar
=
myobj
.
add_variable
(
idx
,
"myarrayvar"
,
[
6.7
,
7.9
])
myarrayvar
=
myobj
.
add_variable
(
idx
,
"myStronglytTypedVariable"
,
ua
.
Variant
([],
ua
.
VariantType
.
UInt32
))
myprop
=
myobj
.
add_property
(
idx
,
"myproperty"
,
"I am a property"
)
mymethod
=
myobj
.
add_method
(
idx
,
"mymethod"
,
func
,
[
ua
.
VariantType
.
Int64
],
[
ua
.
VariantType
.
Boolean
])
multiply_node
=
myobj
.
add_method
(
idx
,
"multiply"
,
multiply
,
[
ua
.
VariantType
.
Int64
,
ua
.
VariantType
.
Int64
],
[
ua
.
VariantType
.
Int64
])
#
creating an custom event object
#
Creating a custom event: Approach 1
# The custom event object automatically will have members from its parent (BaseEventType)
etype
=
server
.
create_custom_event_type
(
2
,
'MyEvent'
,
ua
.
ObjectIds
.
BaseEventType
,
[(
'MyNumericProperty'
,
ua
.
VariantType
.
Float
),
(
'MyStringProperty'
,
ua
.
VariantType
.
String
)])
etype
=
server
.
create_custom_event_type
(
2
,
'My
First
Event'
,
ua
.
ObjectIds
.
BaseEventType
,
[(
'MyNumericProperty'
,
ua
.
VariantType
.
Float
),
(
'MyStringProperty'
,
ua
.
VariantType
.
String
)])
myevgen
=
server
.
get_event_generator
(
etype
,
myobj
)
myevgen
.
event
.
Severity
=
500
# Creating a custom event: Approach 2
base_etype
=
server
.
get_node
(
ua
.
ObjectIds
.
BaseEventType
)
custom_etype
=
base_etype
.
add_subtype
(
2
,
'MySecondEvent'
)
custom_etype
.
add_property
(
2
,
'MyIntProperty'
,
ua
.
Variant
(
None
,
ua
.
VariantType
.
Int32
))
custom_etype
.
add_property
(
2
,
'MyBoolProperty'
,
ua
.
Variant
(
None
,
ua
.
VariantType
.
Boolean
))
mysecondevgen
=
server
.
get_event_generator
(
custom_etype
,
myobj
)
# starting!
server
.
start
()
print
(
"Available loggers are: "
,
logging
.
Logger
.
manager
.
loggerDict
.
keys
())
try
:
# enable following if you want to subscribe to nodes on server side
#handler = SubHandler()
#sub = server.create_subscription(500, handler)
#handle = sub.subscribe_data_change(myvar)
# trigger event, all subscribed clients wil receive it
# time.sleep is here just because we want to see events in UaExpert
import
time
time
.
sleep
(
10
)
print
"Triggering event..."
myevgen
.
trigger
(
message
=
"This is MyEvent with MyNumericProperty and MyStringProperty."
)
embed
()
myevgen
.
trigger
(
message
=
"This is MyFirstEvent with MyNumericProperty and MyStringProperty."
)
mysecondevgen
.
trigger
(
message
=
"This is MySecondEvent with MyIntProperty and MyBoolProperty."
)
time
.
sleep
(
20
)
finally
:
#close connection, remove subcsriptions, etc
server
.
stop
()
opcua/common/event.py
View file @
e084325f
...
...
@@ -59,6 +59,16 @@ class EventGenerator(object):
self
.
event
.
SourceName
=
source
.
get_display_name
().
Text
source
.
set_attribute
(
ua
.
AttributeIds
.
EventNotifier
,
ua
.
DataValue
(
ua
.
Variant
(
1
,
ua
.
VariantType
.
Byte
)))
refs
=
[]
ref
=
ua
.
AddReferencesItem
()
ref
.
IsForward
=
True
ref
.
ReferenceTypeId
=
ua
.
NodeId
(
ua
.
ObjectIds
.
GeneratesEvent
)
ref
.
SourceNodeId
=
source
.
nodeid
ref
.
TargetNodeClass
=
ua
.
NodeClass
.
ObjectType
ref
.
TargetNodeId
=
self
.
event
.
EventType
refs
.
append
(
ref
)
results
=
self
.
isession
.
add_references
(
refs
)
#result.StatusCode.check()
def
__str__
(
self
):
return
"EventGenerator(Type:{}, Source:{}, Time:{}, Message: {})"
.
format
(
self
.
EventType
,
self
.
SourceNode
,
self
.
Time
,
self
.
Message
)
...
...
opcua/common/manage_nodes.py
View file @
e084325f
...
...
@@ -108,21 +108,26 @@ def _create_object(server, parentnodeid, nodeid, qname, objecttype):
addnode
=
ua
.
AddNodesItem
()
addnode
.
RequestedNewNodeId
=
nodeid
addnode
.
BrowseName
=
qname
addnode
.
NodeClass
=
ua
.
NodeClass
.
Object
addnode
.
ParentNodeId
=
parentnodeid
#TODO: maybe move to address_space.py and implement for all node types?
if
not
objecttype
:
addnode
.
ReferenceTypeId
=
ua
.
NodeId
(
ua
.
ObjectIds
.
HasSubtype
)
addnode
.
NodeClass
=
ua
.
NodeClass
.
ObjectType
attrs
=
ua
.
ObjectTypeAttributes
()
attrs
.
IsAbstract
=
True
else
:
addnode
.
TypeDefinition
=
ua
.
NodeId
(
objecttype
)
if
node
.
Node
(
server
,
parentnodeid
).
get_type_definition
()
==
ua
.
ObjectIds
.
FolderType
:
addnode
.
ReferenceTypeId
=
ua
.
NodeId
(
ua
.
ObjectIds
.
Organizes
)
else
:
addnode
.
ReferenceTypeId
=
ua
.
NodeId
(
ua
.
ObjectIds
.
HasComponent
)
attrs
=
ua
.
ObjectAttributes
()
addnode
.
NodeClass
=
ua
.
NodeClass
.
Object
addnode
.
TypeDefinition
=
ua
.
NodeId
(
objecttype
)
attrs
=
ua
.
ObjectAttributes
()
attrs
.
EventNotifier
=
0
attrs
.
Description
=
ua
.
LocalizedText
(
qname
.
Name
)
attrs
.
DisplayName
=
ua
.
LocalizedText
(
qname
.
Name
)
attrs
.
EventNotifier
=
0
attrs
.
WriteMask
=
0
attrs
.
UserWriteMask
=
0
addnode
.
NodeAttributes
=
attrs
...
...
tests/tests_server.py
View file @
e084325f
...
...
@@ -228,9 +228,7 @@ class TestServer(unittest.TestCase, CommonTests):
o
=
objects
.
add_object
(
3
,
'MyObject'
)
evgen
=
self
.
opc
.
get_event_generator
(
source
=
o
)
check_eventgenerator_BaseEvent
(
self
,
evgen
)
self
.
assertEqual
(
evgen
.
event
.
SourceName
,
b'MyObject'
)
self
.
assertEqual
(
evgen
.
event
.
SourceNode
,
o
.
nodeid
)
self
.
assertEqual
(
o
.
get_attribute
(
ua
.
AttributeIds
.
EventNotifier
).
Value
,
ua
.
Variant
(
1
,
ua
.
VariantType
.
Byte
))
check_event_generator_object
(
self
,
evgen
,
o
)
def
test_eventgenerator_source_collision
(
self
):
objects
=
self
.
opc
.
get_objects_node
()
...
...
@@ -238,9 +236,7 @@ class TestServer(unittest.TestCase, CommonTests):
event
=
ua
.
BaseEvent
(
sourcenode
=
o
.
nodeid
)
evgen
=
self
.
opc
.
get_event_generator
(
event
,
ua
.
ObjectIds
.
Server
)
check_eventgenerator_BaseEvent
(
self
,
evgen
)
self
.
assertEqual
(
evgen
.
event
.
SourceName
,
b'MyObject'
)
self
.
assertEqual
(
evgen
.
event
.
SourceNode
,
o
.
nodeid
)
self
.
assertEqual
(
o
.
get_attribute
(
ua
.
AttributeIds
.
EventNotifier
).
Value
,
ua
.
Variant
(
1
,
ua
.
VariantType
.
Byte
))
check_event_generator_object
(
self
,
evgen
,
o
)
def
test_eventgenerator_InheritedEvent
(
self
):
evgen
=
self
.
opc
.
get_event_generator
(
ua
.
ObjectIds
.
AuditEventType
)
...
...
@@ -313,18 +309,28 @@ class TestServer(unittest.TestCase, CommonTests):
evgen
=
self
.
opc
.
get_event_generator
(
etype
,
o
)
check_eventgenerator_CustomEvent
(
self
,
evgen
,
etype
)
self
.
assertEqual
(
evgen
.
event
.
SourceName
,
b'MyObject'
)
self
.
assertEqual
(
evgen
.
event
.
SourceNode
,
o
.
nodeid
)
self
.
assertEqual
(
o
.
get_attribute
(
ua
.
AttributeIds
.
EventNotifier
).
Value
,
ua
.
Variant
(
1
,
ua
.
VariantType
.
Byte
))
check_event_generator_object
(
self
,
evgen
,
o
)
self
.
assertEqual
(
evgen
.
event
.
PropertyNum
,
None
)
self
.
assertEqual
(
evgen
.
event
.
PropertyString
,
None
)
def
check_eventgenerator_SourceServer
(
test
,
evgen
):
test
.
assertEqual
(
evgen
.
event
.
SourceName
,
test
.
opc
.
get_server_node
().
get_display_name
().
Text
)
server
=
test
.
opc
.
get_server_node
()
test
.
assertEqual
(
evgen
.
event
.
SourceName
,
server
.
get_display_name
().
Text
)
test
.
assertEqual
(
evgen
.
event
.
SourceNode
,
ua
.
NodeId
(
ua
.
ObjectIds
.
Server
))
test
.
assertEqual
(
test
.
opc
.
get_server_node
().
get_attribute
(
ua
.
AttributeIds
.
EventNotifier
).
Value
,
ua
.
Variant
(
1
,
ua
.
VariantType
.
Byte
))
test
.
assertEqual
(
server
.
get_attribute
(
ua
.
AttributeIds
.
EventNotifier
).
Value
,
ua
.
Variant
(
1
,
ua
.
VariantType
.
Byte
))
refs
=
server
.
get_referenced_nodes
(
ua
.
ObjectIds
.
GeneratesEvent
,
ua
.
BrowseDirection
.
Forward
,
ua
.
NodeClass
.
ObjectType
,
False
)
test
.
assertGreaterEqual
(
len
(
refs
),
1
)
def
check_event_generator_object
(
test
,
evgen
,
obj
):
test
.
assertEqual
(
evgen
.
event
.
SourceName
,
obj
.
get_display_name
().
Text
)
test
.
assertEqual
(
evgen
.
event
.
SourceNode
,
obj
.
nodeid
)
test
.
assertEqual
(
obj
.
get_attribute
(
ua
.
AttributeIds
.
EventNotifier
).
Value
,
ua
.
Variant
(
1
,
ua
.
VariantType
.
Byte
))
refs
=
obj
.
get_referenced_nodes
(
ua
.
ObjectIds
.
GeneratesEvent
,
ua
.
BrowseDirection
.
Forward
,
ua
.
NodeClass
.
ObjectType
,
False
)
test
.
assertEqual
(
len
(
refs
),
1
)
test
.
assertEqual
(
refs
[
0
].
nodeid
,
evgen
.
event
.
EventType
)
def
check_eventgenerator_BaseEvent
(
test
,
evgen
):
...
...
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