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
3552cccf
Commit
3552cccf
authored
Jul 13, 2023
by
Christoph Ziebuhr
Committed by
oroulet
Jul 31, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add ConditionRefresh methods
parent
42889db6
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
69 additions
and
25 deletions
+69
-25
asyncua/server/event_generator.py
asyncua/server/event_generator.py
+17
-18
asyncua/server/internal_server.py
asyncua/server/internal_server.py
+16
-0
asyncua/server/monitored_item_service.py
asyncua/server/monitored_item_service.py
+7
-3
asyncua/server/subscription_service.py
asyncua/server/subscription_service.py
+29
-4
No files found.
asyncua/server/event_generator.py
View file @
3552cccf
...
@@ -2,7 +2,6 @@ import logging
...
@@ -2,7 +2,6 @@ import logging
from
datetime
import
datetime
from
datetime
import
datetime
import
time
import
time
import
uuid
import
uuid
from
typing
import
Optional
import
sys
import
sys
from
asyncua
import
ua
from
asyncua
import
ua
...
@@ -25,9 +24,8 @@ class EventGenerator:
...
@@ -25,9 +24,8 @@ class EventGenerator:
self
.
logger
=
logging
.
getLogger
(
__name__
)
self
.
logger
=
logging
.
getLogger
(
__name__
)
self
.
isession
=
isession
self
.
isession
=
isession
self
.
event
:
event_objects
.
BaseEvent
=
None
self
.
event
:
event_objects
.
BaseEvent
=
None
self
.
emitting_node
:
Optional
[
Node
]
=
None
async
def
init
(
self
,
etype
=
None
,
emitting_node
=
ua
.
ObjectIds
.
Server
):
async
def
init
(
self
,
etype
=
None
,
emitting_node
=
ua
.
ObjectIds
.
Server
,
add_generates_event
=
True
):
node
=
None
node
=
None
if
isinstance
(
etype
,
event_objects
.
BaseEvent
):
if
isinstance
(
etype
,
event_objects
.
BaseEvent
):
...
@@ -56,26 +54,27 @@ class EventGenerator:
...
@@ -56,26 +54,27 @@ class EventGenerator:
self
.
event
.
SourceName
=
(
await
Node
(
self
.
isession
,
self
.
event
.
SourceNode
).
read_browse_name
()).
Name
self
.
event
.
SourceName
=
(
await
Node
(
self
.
isession
,
self
.
event
.
SourceNode
).
read_browse_name
()).
Name
await
emitting_node
.
set_event_notifier
([
ua
.
EventNotifier
.
SubscribeToEvents
])
await
emitting_node
.
set_event_notifier
([
ua
.
EventNotifier
.
SubscribeToEvents
])
refs
=
[]
ref
=
ua
.
AddReferencesItem
()
if
add_generates_event
:
ref
.
IsForward
=
True
refs
=
[]
ref
.
ReferenceTypeId
=
ua
.
NodeId
(
ua
.
ObjectIds
.
GeneratesEvent
)
ref
=
ua
.
AddReferencesItem
()
ref
.
SourceNodeId
=
emitting_node
.
nodeid
ref
.
IsForward
=
True
ref
.
TargetNodeClass
=
ua
.
NodeClass
.
ObjectType
ref
.
ReferenceTypeId
=
ua
.
NodeId
(
ua
.
ObjectIds
.
GeneratesEvent
)
ref
.
TargetNodeId
=
self
.
event
.
EventType
ref
.
SourceNodeId
=
emitting_node
.
nodeid
refs
.
append
(
ref
)
ref
.
TargetNodeClass
=
ua
.
NodeClass
.
ObjectType
await
self
.
isession
.
add_references
(
refs
)
ref
.
TargetNodeId
=
self
.
event
.
EventType
# result.StatusCode.check()
refs
.
append
(
ref
)
results
=
await
self
.
isession
.
add_references
(
refs
)
self
.
emitting_node
=
emitting_node
for
result
in
results
:
result
.
check
()
def
__str__
(
self
):
def
__str__
(
self
):
return
f"EventGenerator(Type:
{
self
.
event
.
EventType
}
, Emitting Node:
{
self
.
e
mitting_node
}
, "
\
return
f"EventGenerator(Type:
{
self
.
event
.
EventType
}
, Emitting Node:
{
self
.
e
vent
.
emitting_node
.
to_string
()
}
, "
\
f"Time:
{
self
.
event
.
Time
}
, Message:
{
self
.
event
.
Message
}
)"
f"Time:
{
self
.
event
.
Time
}
, Message:
{
self
.
event
.
Message
}
)"
__repr__
=
__str__
__repr__
=
__str__
async
def
trigger
(
self
,
time_attr
=
None
,
message
=
None
):
async
def
trigger
(
self
,
time_attr
=
None
,
message
=
None
,
subscription_id
=
None
):
"""
"""
Trigger the event. This will send a notification to all subscribed clients
Trigger the event. This will send a notification to all subscribed clients
"""
"""
...
@@ -100,4 +99,4 @@ class EventGenerator:
...
@@ -100,4 +99,4 @@ class EventGenerator:
elif
not
self
.
event
.
Message
:
elif
not
self
.
event
.
Message
:
self
.
event
.
Message
=
ua
.
LocalizedText
((
await
Node
(
self
.
isession
,
self
.
event
.
SourceNode
).
read_browse_name
()).
Name
).
Text
self
.
event
.
Message
=
ua
.
LocalizedText
((
await
Node
(
self
.
isession
,
self
.
event
.
SourceNode
).
read_browse_name
()).
Name
).
Text
await
self
.
isession
.
subscription_service
.
trigger_event
(
self
.
event
)
await
self
.
isession
.
subscription_service
.
trigger_event
(
self
.
event
,
subscription_id
=
subscription_id
)
asyncua/server/internal_server.py
View file @
3552cccf
...
@@ -22,6 +22,7 @@ from .subscription_service import SubscriptionService
...
@@ -22,6 +22,7 @@ from .subscription_service import SubscriptionService
from
.standard_address_space
import
standard_address_space
from
.standard_address_space
import
standard_address_space
from
.users
import
User
,
UserRole
from
.users
import
User
,
UserRole
from
.internal_session
import
InternalSession
from
.internal_session
import
InternalSession
from
.event_generator
import
EventGenerator
try
:
try
:
from
asyncua.crypto
import
uacrypto
from
asyncua.crypto
import
uacrypto
...
@@ -49,6 +50,7 @@ class InternalServer:
...
@@ -49,6 +50,7 @@ class InternalServer:
self
.
endpoints
=
[]
self
.
endpoints
=
[]
self
.
_channel_id_counter
=
5
self
.
_channel_id_counter
=
5
self
.
allow_remote_admin
=
True
self
.
allow_remote_admin
=
True
self
.
bind_condition_methods
=
False
self
.
disabled_clock
=
False
# for debugging, we may want to disable clock that writes too much in log
self
.
disabled_clock
=
False
# for debugging, we may want to disable clock that writes too much in log
self
.
_known_servers
=
{}
# used if we are a discovery server
self
.
_known_servers
=
{}
# used if we are a discovery server
self
.
certificate
=
None
self
.
certificate
=
None
...
@@ -81,6 +83,20 @@ class InternalServer:
...
@@ -81,6 +83,20 @@ class InternalServer:
await
self
.
_address_space_fixes
()
await
self
.
_address_space_fixes
()
await
self
.
setup_nodes
()
await
self
.
setup_nodes
()
await
self
.
history_manager
.
init
()
await
self
.
history_manager
.
init
()
if
self
.
bind_condition_methods
:
await
self
.
setup_condition_methods
()
async
def
setup_condition_methods
(
self
):
for
etype
in
(
ua
.
ObjectIds
.
RefreshStartEventType
,
ua
.
ObjectIds
.
RefreshEndEventType
):
evgen
=
EventGenerator
(
self
.
isession
)
await
evgen
.
init
(
etype
,
add_generates_event
=
False
)
# don't use isinstance(int), it also matches bool
if
type
(
self
.
bind_condition_methods
)
is
int
:
evgen
.
event
.
Severity
=
self
.
bind_condition_methods
self
.
subscription_service
.
standard_events
[
etype
]
=
evgen
self
.
isession
.
add_method_callback
(
ua
.
NodeId
(
ua
.
ObjectIds
.
ConditionType_ConditionRefresh
),
self
.
subscription_service
.
condition_refresh
)
self
.
isession
.
add_method_callback
(
ua
.
NodeId
(
ua
.
ObjectIds
.
ConditionType_ConditionRefresh2
),
self
.
subscription_service
.
condition_refresh
)
async
def
setup_nodes
(
self
):
async
def
setup_nodes
(
self
):
"""
"""
...
...
asyncua/server/monitored_item_service.py
View file @
3552cccf
...
@@ -235,14 +235,18 @@ class MonitoredItemService:
...
@@ -235,14 +235,18 @@ class MonitoredItemService:
return
True
return
True
return
False
return
False
async
def
trigger_event
(
self
,
event
):
async
def
trigger_event
(
self
,
event
,
mid
=
None
):
if
event
.
emitting_node
not
in
self
.
_monitored_events
:
if
event
.
emitting_node
not
in
self
.
_monitored_events
:
self
.
logger
.
debug
(
"%s has NO subscription for events %s from node: %s"
,
self
,
event
,
event
.
emitting_node
)
self
.
logger
.
debug
(
"%s has NO subscription for events %s from node: %s"
,
self
,
event
,
event
.
emitting_node
)
return
False
return
False
self
.
logger
.
debug
(
"%s has subscription for events %s from node: %s"
,
self
,
event
,
event
.
emitting_node
)
self
.
logger
.
debug
(
"%s has subscription for events %s from node: %s"
,
self
,
event
,
event
.
emitting_node
)
mids
=
self
.
_monitored_events
[
event
.
emitting_node
]
if
mid
is
not
None
:
for
mid
in
mids
:
await
self
.
_trigger_event
(
event
,
mid
)
await
self
.
_trigger_event
(
event
,
mid
)
else
:
mids
=
self
.
_monitored_events
[
event
.
emitting_node
]
for
mid
in
mids
:
await
self
.
_trigger_event
(
event
,
mid
)
return
True
return
True
async
def
_trigger_event
(
self
,
event
,
mid
:
int
):
async
def
_trigger_event
(
self
,
event
,
mid
:
int
):
...
...
asyncua/server/subscription_service.py
View file @
3552cccf
...
@@ -7,7 +7,7 @@ import logging
...
@@ -7,7 +7,7 @@ import logging
from
typing
import
Dict
,
Iterable
from
typing
import
Dict
,
Iterable
from
asyncua
import
ua
from
asyncua
import
ua
from
asyncua.common
import
utils
from
asyncua.common
import
utils
,
uamethod
from
.address_space
import
AddressSpace
from
.address_space
import
AddressSpace
from
.internal_subscription
import
InternalSubscription
from
.internal_subscription
import
InternalSubscription
...
@@ -23,6 +23,8 @@ class SubscriptionService:
...
@@ -23,6 +23,8 @@ class SubscriptionService:
self
.
aspace
:
AddressSpace
=
aspace
self
.
aspace
:
AddressSpace
=
aspace
self
.
subscriptions
:
Dict
[
int
,
InternalSubscription
]
=
{}
self
.
subscriptions
:
Dict
[
int
,
InternalSubscription
]
=
{}
self
.
_sub_id_counter
=
77
self
.
_sub_id_counter
=
77
self
.
standard_events
=
{}
self
.
_conditions
=
{}
async
def
create_subscription
(
self
,
params
,
callback
,
request_callback
=
None
):
async
def
create_subscription
(
self
,
params
,
callback
,
request_callback
=
None
):
self
.
logger
.
info
(
"create subscription"
)
self
.
logger
.
info
(
"create subscription"
)
...
@@ -113,6 +115,29 @@ class SubscriptionService:
...
@@ -113,6 +115,29 @@ class SubscriptionService:
return
ua
.
NotificationMessage
()
return
ua
.
NotificationMessage
()
return
self
.
subscriptions
[
params
.
SubscriptionId
].
republish
(
params
.
RetransmitSequenceNumber
)
return
self
.
subscriptions
[
params
.
SubscriptionId
].
republish
(
params
.
RetransmitSequenceNumber
)
async
def
trigger_event
(
self
,
event
):
async
def
trigger_event
(
self
,
event
,
subscription_id
=
None
):
for
sub
in
self
.
subscriptions
.
values
():
if
hasattr
(
event
,
'Retain'
)
and
hasattr
(
event
,
'NodeId'
):
await
sub
.
monitored_item_srv
.
trigger_event
(
event
)
if
event
.
Retain
:
self
.
_conditions
[
event
.
NodeId
]
=
event
elif
event
.
NodeId
in
self
.
_conditions
:
del
self
.
_conditions
[
event
.
NodeId
]
if
subscription_id
is
not
None
:
if
subscription_id
in
self
.
subscriptions
:
await
self
.
subscriptions
[
subscription_id
].
monitored_item_srv
.
trigger_event
(
event
)
else
:
for
sub
in
self
.
subscriptions
.
values
():
await
sub
.
monitored_item_srv
.
trigger_event
(
event
)
@
uamethod
async
def
condition_refresh
(
self
,
parent
,
subscription_id
,
mid
=
None
):
if
subscription_id
not
in
self
.
subscriptions
:
return
ua
.
StatusCode
(
ua
.
StatusCodes
.
BadSubscriptionIdInvalid
)
sub
=
self
.
subscriptions
[
subscription_id
]
if
mid
is
not
None
and
mid
not
in
sub
.
monitored_item_srv
.
_monitored_items
:
return
ua
.
StatusCode
(
ua
.
StatusCodes
.
BadMonitoredItemIdInvalid
)
if
ua
.
ObjectIds
.
RefreshStartEventType
in
self
.
standard_events
:
await
self
.
standard_events
[
ua
.
ObjectIds
.
RefreshStartEventType
].
trigger
(
subscription_id
=
subscription_id
)
for
event
in
self
.
_conditions
.
values
():
await
sub
.
monitored_item_srv
.
trigger_event
(
event
,
mid
)
if
ua
.
ObjectIds
.
RefreshEndEventType
in
self
.
standard_events
:
await
self
.
standard_events
[
ua
.
ObjectIds
.
RefreshEndEventType
].
trigger
(
subscription_id
=
subscription_id
)
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