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
f1e055b3
Commit
f1e055b3
authored
Apr 20, 2016
by
Denis Štogl
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Events implementation proposal
parent
33dd4565
Changes
10
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
128 additions
and
83 deletions
+128
-83
examples/server-example.py
examples/server-example.py
+1
-1
opcua/__init__.py
opcua/__init__.py
+1
-1
opcua/common/event.py
opcua/common/event.py
+59
-32
opcua/common/subscription.py
opcua/common/subscription.py
+0
-6
opcua/server/address_space.py
opcua/server/address_space.py
+1
-1
opcua/server/server.py
opcua/server/server.py
+12
-5
opcua/ua/__init__.py
opcua/ua/__init__.py
+2
-0
opcua/ua/uatypes.py
opcua/ua/uatypes.py
+0
-2
opcua/ua/uatypes_auto.py
opcua/ua/uatypes_auto.py
+41
-0
tests/tests_common.py
tests/tests_common.py
+11
-35
No files found.
examples/server-example.py
View file @
f1e055b3
...
...
@@ -14,7 +14,7 @@ except ImportError:
shell
.
interact
()
from
opcua
import
ua
,
uamethod
,
Server
,
Event
from
opcua
import
ua
,
uamethod
,
Server
,
Event
Generator
class
SubHandler
(
object
):
...
...
opcua/__init__.py
View file @
f1e055b3
...
...
@@ -10,7 +10,7 @@ Pure Python OPC-UA library
from
opcua.common.node
import
Node
from
opcua.common.methods
import
uamethod
from
opcua.common.event
import
Event
from
opcua.common.event
import
Event
Generator
from
opcua.common.subscription
import
Subscription
from
opcua.client.client
import
Client
from
opcua.server.server
import
Server
...
...
opcua/common/event.py
View file @
f1e055b3
...
...
@@ -6,7 +6,7 @@ from opcua import Node
import
uuid
class
Event
(
object
):
class
Event
Generator
(
object
):
"""
Create an event based on an event type. Per default is BaseEventType used.
...
...
@@ -24,51 +24,78 @@ class Event(object):
def
__init__
(
self
,
isession
,
etype
=
ua
.
ObjectIds
.
BaseEventType
,
source
=
ua
.
ObjectIds
.
Server
):
self
.
isession
=
isession
self
.
node
=
None
self
.
event
=
etype
if
isinstance
(
etype
,
Node
):
if
isinstance
(
etype
,
ua
.
BaseEvent
):
pass
elif
isinstance
(
etype
,
Node
):
self
.
node
=
etype
elif
isinstance
(
etype
,
ua
.
NodeId
):
self
.
node
=
Node
(
self
.
isession
,
etype
)
else
:
self
.
node
=
Node
(
self
.
isession
,
ua
.
NodeId
(
etype
))
self
.
_set_members_from_node
(
self
.
node
)
if
self
.
node
:
event
=
CustomEvent
()
references
=
node
.
get_children_descriptions
(
refs
=
ua
.
ObjectIds
.
HasProperty
)
for
desc
in
references
:
node
=
Node
(
self
.
isession
,
desc
.
NodeId
)
setattr
(
self
,
desc
.
BrowseName
.
Name
,
node
.
get_value
())
if
isinstance
(
source
,
Node
):
self
.
SourceNode
=
source
.
NodeId
elif
isinstance
(
etype
,
ua
.
NodeId
):
s
elf
.
SourceNode
=
source
.
NodeId
pass
elif
isinstance
(
source
,
NodeId
):
s
ource
=
ua
.
Node
(
isession
,
source
)
else
:
self
.
SourceNode
=
ua
.
NodeId
(
source
)
# set some default values for attributes from BaseEventType, thus that all event must have
self
.
EventId
=
uuid
.
uuid4
().
bytes
self
.
EventType
=
self
.
node
.
nodeid
self
.
LocaleTime
=
datetime
.
utcnow
()
self
.
ReceiveTime
=
datetime
.
utcnow
()
self
.
Time
=
datetime
.
utcnow
()
self
.
Message
=
ua
.
LocalizedText
()
self
.
Severity
=
ua
.
Variant
(
1
,
ua
.
VariantType
.
UInt16
)
self
.
SourceName
=
"Server"
# og set some node attributed we also are expected to have
self
.
BrowseName
=
self
.
node
.
get_browse_name
()
self
.
DisplayName
=
self
.
node
.
get_display_name
()
self
.
NodeId
=
self
.
node
.
nodeid
self
.
NodeClass
=
self
.
node
.
get_node_class
()
self
.
Description
=
self
.
node
.
get_description
()
source
=
Node
(
isession
,
ua
.
NodeId
(
source
))
if
self
.
event
.
SourceNode
.
Identifier
:
source
=
Node
(
self
.
iserver
.
isession
,
self
.
event
.
SourceNode
)
self
.
event
.
SourceName
=
source
.
get_display_name
().
Text
source
.
set_attribute
(
ua
.
AttributeIds
.
EventNotifier
,
ua
.
DataValue
(
ua
.
Variant
(
1
,
ua
.
VariantType
.
Byte
)))
def
__str__
(
self
):
return
"Event(Type:{}, Source:{}, Time:{}, Message: {})"
.
format
(
self
.
EventType
,
self
.
SourceNode
,
self
.
Time
,
self
.
Message
)
return
"Event
Generator
(Type:{}, Source:{}, Time:{}, Message: {})"
.
format
(
self
.
EventType
,
self
.
SourceNode
,
self
.
Time
,
self
.
Message
)
__repr__
=
__str__
def
trigger
(
self
):
def
trigger
(
self
,
time
=
None
,
message
=
None
):
"""
Trigger the event. This will send a notification to all subscribed clients
"""
self
.
isession
.
subscription_service
.
trigger_event
(
self
)
self
.
event
.
EventId
=
ua
.
Variant
(
uuid
.
uuid4
().
hex
,
ua
.
VariantType
.
ByteString
)
if
time
:
self
.
event
.
Time
=
time
else
:
self
.
event
.
Time
=
datetime
.
utcnow
()
self
.
event
.
ReciveTime
=
datetime
.
utcnow
()
#FIXME: LocalTime is wrong but currently know better. For description s. Part 5 page 18
self
.
event
.
LocaleTime
=
datetime
.
utcnow
()
if
message
:
self
.
Message
=
ua
.
LocalizedText
(
message
)
elif
not
self
.
event
.
Message
:
self
.
event
.
Message
=
ua
.
LocalizedText
(
self
.
source
.
get_browse_name
().
Text
)
self
.
isession
.
subscription_service
.
trigger_event
(
self
.
event
)
def
_set_members_from_node
(
self
,
node
):
references
=
node
.
get_children_descriptions
(
refs
=
ua
.
ObjectIds
.
HasProperty
)
for
desc
in
references
:
node
=
Node
(
self
.
isession
,
desc
.
NodeId
)
setattr
(
self
,
desc
.
BrowseName
.
Name
,
node
.
get_value
())
class
CustomEvent
(
ua
.
BaseEvent
):
def
__init__
(
self
,
etype
=
ua
.
ObjectIds
.
BaseEventType
,
sourcenode
=
ua
.
NodeId
(
ua
.
ObjectIds
.
Server
),
message
=
None
,
severity
=
1
):
super
(
ua
.
BaseEvent
,
self
).
__init__
(
sourcenode
,
message
,
severity
,
True
)
#TODO: Add fileds
#TODO: Extend to show all fields of CustomEvent
def
__str__
(
self
):
s
=
'CustomEvent(EventId:{}'
.
format
(
self
.
EventId
)
s
+=
', EventType:{}'
.
format
(
self
.
EventType
)
s
+=
', SourceNode:{}'
.
format
(
self
.
SourceNode
)
s
+=
', SourceName:{}'
.
format
(
self
.
SourceName
)
s
+=
', Time:{}'
.
format
(
self
.
Time
)
s
+=
', RecieveTime:{}'
.
format
(
self
.
RecieveTime
)
s
+=
', LocalTime:{}'
.
format
(
self
.
LocalTime
)
s
+=
', Message:{}'
.
format
(
self
.
Message
)
s
+=
', Severity:{}'
.
format
(
self
.
Severity
)
s
+=
')'
return
s
__repr__
=
__str__
opcua/common/subscription.py
View file @
f1e055b3
...
...
@@ -39,12 +39,6 @@ class SubHandler(object):
"""
pass
def
event
(
self
,
handle
,
event
):
"""
Deprecated use event_notification
"""
pass
class
EventResult
():
"""
...
...
opcua/server/address_space.py
View file @
f1e055b3
...
...
@@ -459,7 +459,7 @@ class AddressSpace(object):
def
get_attribute_value
(
self
,
nodeid
,
attr
):
with
self
.
_lock
:
#
self.logger.debug("get attr val: %s %s", nodeid, attr)
self
.
logger
.
debug
(
"get attr val: %s %s"
,
nodeid
,
attr
)
if
nodeid
not
in
self
.
_nodes
:
dv
=
ua
.
DataValue
()
dv
.
StatusCode
=
ua
.
StatusCode
(
ua
.
StatusCodes
.
BadNodeIdUnknown
)
...
...
opcua/server/server.py
View file @
f1e055b3
...
...
@@ -14,7 +14,7 @@ from opcua import ua
from
opcua.server.binary_server_asyncio
import
BinaryServer
from
opcua.server.internal_server
import
InternalServer
from
opcua.common.node
import
Node
from
opcua.common.event
import
Event
from
opcua.common.event
import
Event
Generator
from
opcua.common.subscription
import
Subscription
from
opcua.common
import
xmlimporter
from
opcua.common.manage_nodes
import
delete_nodes
...
...
@@ -322,12 +322,19 @@ class Server(object):
uries
=
self
.
get_namespace_array
()
return
uries
.
index
(
uri
)
def
get_event_
object
(
self
,
etype
=
ua
.
ObjectIds
.
BaseEventType
,
source
=
ua
.
ObjectIds
.
Server
):
def
get_event_
generator
(
self
,
etype
=
ua
.
ObjectIds
.
BaseEventType
,
source
=
ua
.
ObjectIds
.
Server
):
"""
Returns an event object using an event type from address space.
Use this object to fire events
"""
return
Event
(
self
.
iserver
.
isession
,
etype
,
source
)
return
EventGenerator
(
self
.
iserver
.
isession
,
etype
,
source
)
def
create_custom_event
(
self
,
name
,
baseetype
=
ua
.
ObjectIds
.
BaseEventType
,
properties
=
[]):
base_event
=
self
.
get_node
(
baseetype
)
custom_event
=
base_event
.
add_object
(
name
)
for
property
in
properties
:
custom_event
.
add_property
(
property
[
0
],
property
[
1
])
def
import_xml
(
self
,
path
):
"""
...
...
opcua/ua/__init__.py
View file @
f1e055b3
...
...
@@ -4,4 +4,6 @@ from opcua.ua.object_ids import ObjectIds
from
opcua.ua.status_codes
import
StatusCodes
from
opcua.ua.uaprotocol_auto
import
*
from
opcua.ua.uaprotocol_hand
import
*
from
opcua.ua.uatypes_auto
import
*
from
opcua.ua.uatypes
import
*
#TODO: This should be renamed to uatypes_hand
opcua/ua/uatypes.py
View file @
f1e055b3
...
...
@@ -1068,8 +1068,6 @@ class XmlElement(FrozenClass):
__repr__
=
__str__
class
DataValue
(
FrozenClass
):
'''
...
...
opcua/ua/uatypes_auto.py
0 → 100644
View file @
f1e055b3
'''
Example auto_generated file with UA Types
For now only events!
'''
from
opcua.ua
import
*
# TODO: This should be autogeneratd form XML description of EventTypes
class
BaseEvent
(
FrozenClass
):
'''
BaseEvent implements BaseEventType from which inherit all other events and it is used per default.
'''
def
__init__
(
self
,
sourcenode
=
NodeId
(
ObjectIds
.
Server
),
message
=
None
,
severity
=
1
,
extended
=
False
):
self
.
EventId
=
bytes
()
self
.
EventType
=
NodeId
(
ObjectIds
.
BaseEventType
)
self
.
SourceNode
=
sourcenode
self
.
SourceName
=
None
self
.
Time
=
None
self
.
RecieveTime
=
None
self
.
LocalTime
=
None
self
.
Message
=
LocalizedText
(
message
)
self
.
Severity
=
Variant
(
severity
,
VariantType
.
UInt16
)
if
not
extended
:
self
.
_freeze
=
True
def
__str__
(
self
):
s
=
'BaseEventType(EventId:{}'
.
format
(
self
.
EventId
)
s
+=
', EventType:{}'
.
format
(
self
.
EventType
)
s
+=
', SourceNode:{}'
.
format
(
self
.
SourceNode
)
s
+=
', SourceName:{}'
.
format
(
self
.
SourceName
)
s
+=
', Time:{}'
.
format
(
self
.
Time
)
s
+=
', RecieveTime:{}'
.
format
(
self
.
RecieveTime
)
s
+=
', LocalTime:{}'
.
format
(
self
.
LocalTime
)
s
+=
', Message:{}'
.
format
(
self
.
Message
)
s
+=
', Severity:{}'
.
format
(
self
.
Severity
)
s
+=
')'
return
s
__repr__
=
__str__
tests/tests_common.py
View file @
f1e055b3
...
...
@@ -23,7 +23,7 @@ def add_server_methods(srv):
def
func2
(
parent
,
methodname
,
value
):
return
math
.
sin
(
value
)
o
=
srv
.
get_objects_node
()
o
=
srv
.
get_objects_node
()
š
v
=
o
.
add_method
(
ua
.
NodeId
(
"ServerMethodArray"
,
2
),
ua
.
QualifiedName
(
'ServerMethodArray'
,
2
),
func2
,
[
ua
.
VariantType
.
String
,
ua
.
VariantType
.
Int64
],
[
ua
.
VariantType
.
Int64
])
@
uamethod
...
...
@@ -263,30 +263,6 @@ class CommonTests(object):
handle
=
sub
.
subscribe_events
(
v
)
sub
.
delete
()
def
test_events_deprecated
(
self
):
msclt
=
MySubHandlerDeprecated
()
sub
=
self
.
opc
.
create_subscription
(
100
,
msclt
)
handle
=
sub
.
subscribe_events
()
ev
=
Event
(
self
.
srv
.
iserver
.
isession
)
msg
=
b"this is my msg "
ev
.
Message
.
Text
=
msg
tid
=
datetime
.
utcnow
()
ev
.
Time
=
tid
ev
.
Severity
=
500
ev
.
trigger
()
clthandle
,
ev
=
msclt
.
future
.
result
()
self
.
assertIsNot
(
ev
,
None
)
# we did not receive event
self
.
assertEqual
(
ev
.
Message
.
Text
,
msg
)
#self.assertEqual(msclt.ev.Time, tid)
self
.
assertEqual
(
ev
.
Severity
,
500
)
self
.
assertEqual
(
ev
.
SourceNode
,
self
.
opc
.
get_server_node
().
nodeid
)
# time.sleep(0.1)
sub
.
unsubscribe
(
handle
)
sub
.
delete
()
def
test_events
(
self
):
msclt
=
MySubHandler
()
sub
=
self
.
opc
.
create_subscription
(
100
,
msclt
)
...
...
@@ -302,10 +278,10 @@ class CommonTests(object):
ev
=
msclt
.
future
.
result
()
self
.
assertIsNot
(
ev
,
None
)
# we did not receive event
self
.
assertEqual
(
ev
.
SourceNode
,
self
.
opc
.
get_server_node
().
nodeid
)
self
.
assertEqual
(
ev
.
Message
.
Text
,
msg
)
#self.assertEqual(msclt.ev.Time, tid)
self
.
assertEqual
(
ev
.
Severity
,
500
)
self
.
assertEqual
(
ev
.
SourceNode
,
self
.
opc
.
get_server_node
().
nodeid
)
# time.sleep(0.1)
sub
.
unsubscribe
(
handle
)
...
...
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