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
066c61eb
Commit
066c61eb
authored
Sep 13, 2023
by
Yuta Okamoto
Committed by
oroulet
Sep 14, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add type hints to Subscription
parent
39e07108
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
174 additions
and
45 deletions
+174
-45
asyncua/client/client.py
asyncua/client/client.py
+2
-2
asyncua/common/subscription.py
asyncua/common/subscription.py
+164
-38
asyncua/server/history.py
asyncua/server/history.py
+7
-4
asyncua/server/internal_session.py
asyncua/server/internal_session.py
+1
-1
No files found.
asyncua/client/client.py
View file @
066c61eb
...
@@ -14,7 +14,7 @@ from ..common.xmlimporter import XmlImporter
...
@@ -14,7 +14,7 @@ from ..common.xmlimporter import XmlImporter
from
..common.xmlexporter
import
XmlExporter
from
..common.xmlexporter
import
XmlExporter
from
..common.node
import
Node
from
..common.node
import
Node
from
..common.manage_nodes
import
delete_nodes
from
..common.manage_nodes
import
delete_nodes
from
..common.subscription
import
Sub
Handler
,
Subscription
from
..common.subscription
import
Sub
scription
,
SubscriptionHandler
from
..common.shortcuts
import
Shortcuts
from
..common.shortcuts
import
Shortcuts
from
..common.structures
import
load_type_definitions
,
load_enums
from
..common.structures
import
load_type_definitions
,
load_enums
from
..common.structures104
import
load_data_type_definitions
from
..common.structures104
import
load_data_type_definitions
...
@@ -719,7 +719,7 @@ class Client:
...
@@ -719,7 +719,7 @@ class Client:
return
Node
(
self
.
uaclient
,
nodeid
)
return
Node
(
self
.
uaclient
,
nodeid
)
async
def
create_subscription
(
async
def
create_subscription
(
self
,
period
:
Union
[
ua
.
CreateSubscriptionParameters
,
float
],
handler
:
SubHandler
,
publishing
:
bool
=
True
self
,
period
:
Union
[
ua
.
CreateSubscriptionParameters
,
float
],
handler
:
Sub
scription
Handler
,
publishing
:
bool
=
True
)
->
Subscription
:
)
->
Subscription
:
"""
"""
Create a subscription.
Create a subscription.
...
...
asyncua/common/subscription.py
View file @
066c61eb
"""
"""
high level interface to subscriptions
high level interface to subscriptions
"""
"""
from
__future__
import
annotations
import
asyncio
import
asyncio
import
logging
import
collections.abc
import
collections.abc
from
typing
import
Tuple
,
Union
,
List
,
Iterable
,
Optional
import
logging
from
asyncua.common.ua_utils
import
copy_dataclass_attr
import
sys
from
typing
import
TYPE_CHECKING
,
Any
,
Tuple
,
Union
,
List
,
Iterable
,
Optional
,
overload
if
sys
.
version_info
>=
(
3
,
8
):
from
typing
import
Protocol
else
:
from
typing_extensions
import
Protocol
from
asyncua
import
ua
from
asyncua
import
ua
from
asyncua.client.ua_client
import
UaClient
from
asyncua.common.ua_utils
import
copy_dataclass_attr
if
TYPE_CHECKING
:
from
asyncua.server.internal_session
import
InternalSession
from
.events
import
Event
,
get_filter_from_event_type
from
.events
import
Event
,
get_filter_from_event_type
from
.node
import
Node
from
.node
import
Node
...
@@ -44,25 +57,55 @@ class DataChangeNotif:
...
@@ -44,25 +57,55 @@ class DataChangeNotif:
__repr__
=
__str__
__repr__
=
__str__
class
DataChangeNotificationHandler
(
Protocol
):
def
datachange_notification
(
self
,
node
:
Node
,
val
:
Any
,
data
:
DataChangeNotif
)
->
None
:
"""
called for every datachange notification from server
"""
...
class
EventNotificationHandler
(
Protocol
):
def
event_notification
(
self
,
event
:
ua
.
EventNotificationList
)
->
None
:
"""
called for every event notification from server
"""
...
class
StatusChangeNotificationHandler
(
Protocol
):
def
status_change_notification
(
self
,
status
:
ua
.
StatusChangeNotification
)
->
None
:
"""
called for every status change notification from server
"""
...
SubscriptionHandler
=
Union
[
DataChangeNotificationHandler
,
EventNotificationHandler
,
StatusChangeNotificationHandler
]
"""
Protocol class representing subscription handlers to receive events from server.
"""
class
SubHandler
:
class
SubHandler
:
"""
"""
Subscription Handler. To receive events from server for a subscription
Subscription Handler. To receive events from server for a subscription
This class is just a sample class. Whatever class having these methods can be used
This class is just a sample class. Whatever class having these methods can be used
"""
"""
def
datachange_notification
(
self
,
node
:
Node
,
val
,
data
:
DataChangeNotif
)
:
def
datachange_notification
(
self
,
node
:
Node
,
val
:
Any
,
data
:
DataChangeNotif
)
->
None
:
"""
"""
called for every datachange notification from server
called for every datachange notification from server
"""
"""
pass
pass
def
event_notification
(
self
,
event
:
ua
.
EventNotificationList
):
def
event_notification
(
self
,
event
:
ua
.
EventNotificationList
)
->
None
:
"""
"""
called for every event notification from server
called for every event notification from server
"""
"""
pass
pass
def
status_change_notification
(
self
,
status
:
ua
.
StatusChangeNotification
):
def
status_change_notification
(
self
,
status
:
ua
.
StatusChangeNotification
)
->
None
:
"""
"""
called for every status change notification from server
called for every status change notification from server
"""
"""
...
@@ -75,14 +118,19 @@ class Subscription:
...
@@ -75,14 +118,19 @@ class Subscription:
The object represent a subscription to an opc-ua server.
The object represent a subscription to an opc-ua server.
This is a high level class, especially `subscribe_data_change` and `subscribe_events methods`.
This is a high level class, especially `subscribe_data_change` and `subscribe_events methods`.
If more control is necessary look at code and/or use `create_monitored_items method`.
If more control is necessary look at code and/or use `create_monitored_items method`.
:param server: `InternalSession` or `U
A
Client`
:param server: `InternalSession` or `U
a
Client`
"""
"""
def
__init__
(
self
,
server
,
params
:
ua
.
CreateSubscriptionParameters
,
handler
:
SubHandler
):
def
__init__
(
self
,
server
:
Union
[
InternalSession
,
UaClient
],
params
:
ua
.
CreateSubscriptionParameters
,
handler
:
SubscriptionHandler
,
):
self
.
logger
=
logging
.
getLogger
(
__name__
)
self
.
logger
=
logging
.
getLogger
(
__name__
)
self
.
server
=
server
self
.
server
:
Union
[
InternalSession
,
UaClient
]
=
server
self
.
_client_handle
=
200
self
.
_client_handle
=
200
self
.
_handler
:
SubHandler
=
handler
self
.
_handler
:
Sub
scription
Handler
=
handler
self
.
parameters
:
ua
.
CreateSubscriptionParameters
=
params
# move to data class
self
.
parameters
:
ua
.
CreateSubscriptionParameters
=
params
# move to data class
self
.
_monitored_items
=
{}
self
.
_monitored_items
=
{}
self
.
subscription_id
:
Optional
[
int
]
=
None
self
.
subscription_id
:
Optional
[
int
]
=
None
...
@@ -99,14 +147,16 @@ class Subscription:
...
@@ -99,14 +147,16 @@ class Subscription:
async
def
update
(
async
def
update
(
self
,
self
,
params
:
ua
.
ModifySubscriptionParameters
params
:
ua
.
ModifySubscriptionParameters
)
->
ua
.
ModifySubscriptionResponse
:
)
->
ua
.
ModifySubscriptionResult
:
if
not
isinstance
(
self
.
server
,
UaClient
):
raise
ua
.
uaerrors
.
UaError
(
f"update() is not supported in
{
self
.
server
}
."
)
response
=
await
self
.
server
.
update_subscription
(
params
)
response
=
await
self
.
server
.
update_subscription
(
params
)
self
.
logger
.
info
(
'Subscription updated %s'
,
params
.
SubscriptionId
)
self
.
logger
.
info
(
'Subscription updated %s'
,
params
.
SubscriptionId
)
# update the self.parameters attr with the updated values
# update the self.parameters attr with the updated values
copy_dataclass_attr
(
params
,
self
.
parameters
)
copy_dataclass_attr
(
params
,
self
.
parameters
)
return
response
return
response
async
def
publish_callback
(
self
,
publish_result
:
ua
.
PublishResult
):
async
def
publish_callback
(
self
,
publish_result
:
ua
.
PublishResult
)
->
None
:
"""
"""
Handle `PublishResult` callback.
Handle `PublishResult` callback.
"""
"""
...
@@ -122,14 +172,14 @@ class Subscription:
...
@@ -122,14 +172,14 @@ class Subscription:
else
:
else
:
self
.
logger
.
warning
(
"Notification type not supported yet for notification %s"
,
notif
)
self
.
logger
.
warning
(
"Notification type not supported yet for notification %s"
,
notif
)
async
def
delete
(
self
):
async
def
delete
(
self
)
->
None
:
"""
"""
Delete subscription on server. This is automatically done by Client and Server classes on exit.
Delete subscription on server. This is automatically done by Client and Server classes on exit.
"""
"""
results
=
await
self
.
server
.
delete_subscriptions
([
self
.
subscription_id
])
results
=
await
self
.
server
.
delete_subscriptions
([
self
.
subscription_id
])
results
[
0
].
check
()
results
[
0
].
check
()
async
def
_call_datachange
(
self
,
datachange
:
ua
.
DataChangeNotification
):
async
def
_call_datachange
(
self
,
datachange
:
ua
.
DataChangeNotification
)
->
None
:
if
not
hasattr
(
self
.
_handler
,
"datachange_notification"
):
if
not
hasattr
(
self
.
_handler
,
"datachange_notification"
):
self
.
logger
.
error
(
"DataChange subscription created but handler has no datachange_notification method"
)
self
.
logger
.
error
(
"DataChange subscription created but handler has no datachange_notification method"
)
return
return
...
@@ -153,7 +203,7 @@ class Subscription:
...
@@ -153,7 +203,7 @@ class Subscription:
except
Exception
as
ex
:
except
Exception
as
ex
:
self
.
logger
.
exception
(
"Exception calling data change handler. Error: %s"
,
ex
)
self
.
logger
.
exception
(
"Exception calling data change handler. Error: %s"
,
ex
)
async
def
_call_event
(
self
,
eventlist
:
ua
.
EventNotificationList
):
async
def
_call_event
(
self
,
eventlist
:
ua
.
EventNotificationList
)
->
None
:
for
event
in
eventlist
.
Events
:
for
event
in
eventlist
.
Events
:
if
event
.
ClientHandle
not
in
self
.
_monitored_items
:
if
event
.
ClientHandle
not
in
self
.
_monitored_items
:
self
.
logger
.
warning
(
"Received a notification for unknown handle: %s"
,
event
.
ClientHandle
)
self
.
logger
.
warning
(
"Received a notification for unknown handle: %s"
,
event
.
ClientHandle
)
...
@@ -172,7 +222,7 @@ class Subscription:
...
@@ -172,7 +222,7 @@ class Subscription:
else
:
else
:
self
.
logger
.
error
(
"Event subscription created but handler has no event_notification method"
)
self
.
logger
.
error
(
"Event subscription created but handler has no event_notification method"
)
async
def
_call_status
(
self
,
status
:
ua
.
StatusChangeNotification
):
async
def
_call_status
(
self
,
status
:
ua
.
StatusChangeNotification
)
->
None
:
if
not
hasattr
(
self
.
_handler
,
"status_change_notification"
):
if
not
hasattr
(
self
.
_handler
,
"status_change_notification"
):
self
.
logger
.
error
(
"DataChange subscription has no status_change_notification method"
)
self
.
logger
.
error
(
"DataChange subscription has no status_change_notification method"
)
return
return
...
@@ -184,6 +234,28 @@ class Subscription:
...
@@ -184,6 +234,28 @@ class Subscription:
except
Exception
:
except
Exception
:
self
.
logger
.
exception
(
"Exception calling status change handler"
)
self
.
logger
.
exception
(
"Exception calling status change handler"
)
@
overload
async
def
subscribe_data_change
(
self
,
nodes
:
Node
,
attr
:
ua
.
AttributeIds
=
ua
.
AttributeIds
.
Value
,
queuesize
:
int
=
0
,
monitoring
=
ua
.
MonitoringMode
.
Reporting
,
sampling_interval
:
ua
.
Duration
=
0.0
)
->
int
:
...
@
overload
async
def
subscribe_data_change
(
self
,
nodes
:
Union
[
Node
,
Iterable
[
Node
]],
attr
:
ua
.
AttributeIds
=
ua
.
AttributeIds
.
Value
,
queuesize
:
int
=
0
,
monitoring
=
ua
.
MonitoringMode
.
Reporting
,
sampling_interval
:
ua
.
Duration
=
0.0
)
->
List
[
Union
[
int
,
ua
.
StatusCode
]]:
...
async
def
subscribe_data_change
(
async
def
subscribe_data_change
(
self
,
self
,
nodes
:
Union
[
Node
,
Iterable
[
Node
]],
nodes
:
Union
[
Node
,
Iterable
[
Node
]],
...
@@ -213,8 +285,10 @@ class Subscription:
...
@@ -213,8 +285,10 @@ class Subscription:
nodes
,
attr
,
queuesize
=
queuesize
,
monitoring
=
monitoring
,
sampling_interval
=
sampling_interval
nodes
,
attr
,
queuesize
=
queuesize
,
monitoring
=
monitoring
,
sampling_interval
=
sampling_interval
)
)
async
def
_create_eventfilter
(
self
,
evtypes
:
Union
[
ua
.
ObjectIds
,
List
[
ua
.
ObjectIds
],
ua
.
NodeId
,
List
[
ua
.
NodeId
]],
where_clause_generation
:
bool
=
True
):
async
def
_create_eventfilter
(
if
not
isinstance
(
evtypes
,
(
list
,
tuple
)):
self
,
evtypes
:
Union
[
int
,
ua
.
NodeId
,
Iterable
[
Union
[
int
,
ua
.
NodeId
]]],
where_clause_generation
:
bool
=
True
)
->
ua
.
EventFilter
:
if
isinstance
(
evtypes
,
(
int
,
ua
.
NodeId
)):
evtypes
=
[
evtypes
]
evtypes
=
[
evtypes
]
evtypes
=
[
Node
(
self
.
server
,
evtype
)
for
evtype
in
evtypes
]
# type: ignore[union-attr]
evtypes
=
[
Node
(
self
.
server
,
evtype
)
for
evtype
in
evtypes
]
# type: ignore[union-attr]
evfilter
=
await
get_filter_from_event_type
(
evtypes
,
where_clause_generation
)
# type: ignore[union-attr]
evfilter
=
await
get_filter_from_event_type
(
evtypes
,
where_clause_generation
)
# type: ignore[union-attr]
...
@@ -222,9 +296,9 @@ class Subscription:
...
@@ -222,9 +296,9 @@ class Subscription:
async
def
subscribe_events
(
async
def
subscribe_events
(
self
,
self
,
sourcenode
:
Node
=
ua
.
ObjectIds
.
Server
,
sourcenode
:
Union
[
Node
,
ua
.
NodeId
,
str
,
int
]
=
ua
.
ObjectIds
.
Server
,
evtypes
:
Union
[
ua
.
ObjectIds
,
List
[
ua
.
ObjectIds
],
ua
.
NodeId
,
List
[
ua
.
NodeId
]]
=
ua
.
ObjectIds
.
BaseEventType
,
evtypes
:
Union
[
int
,
ua
.
NodeId
,
Iterable
[
Union
[
ua
.
NodeId
,
int
]
]]
=
ua
.
ObjectIds
.
BaseEventType
,
evfilter
:
ua
.
EventFilter
=
None
,
evfilter
:
Optional
[
ua
.
EventFilter
]
=
None
,
queuesize
:
int
=
0
,
queuesize
:
int
=
0
,
where_clause_generation
:
bool
=
True
where_clause_generation
:
bool
=
True
)
->
int
:
)
->
int
:
...
@@ -245,7 +319,7 @@ class Subscription:
...
@@ -245,7 +319,7 @@ class Subscription:
"""
"""
sourcenode
=
Node
(
self
.
server
,
sourcenode
)
sourcenode
=
Node
(
self
.
server
,
sourcenode
)
if
evfilter
is
None
:
if
evfilter
is
None
:
if
not
isinstance
(
evtypes
,
(
list
,
tuple
))
and
evtypes
==
ua
.
ObjectIds
.
BaseEventType
:
if
evtypes
==
ua
.
ObjectIds
.
BaseEventType
or
evtypes
==
ua
.
NodeId
(
ua
.
ObjectIds
.
BaseEventType
)
:
# Remove where clause for base event type, for servers that have problems with long WhereClauses.
# Remove where clause for base event type, for servers that have problems with long WhereClauses.
# Also because BaseEventType wants every event we can ommit it. Issue: #1205
# Also because BaseEventType wants every event we can ommit it. Issue: #1205
where_clause_generation
=
False
where_clause_generation
=
False
...
@@ -254,9 +328,9 @@ class Subscription:
...
@@ -254,9 +328,9 @@ class Subscription:
async
def
subscribe_alarms_and_conditions
(
async
def
subscribe_alarms_and_conditions
(
self
,
self
,
sourcenode
:
Node
=
ua
.
ObjectIds
.
Server
,
sourcenode
:
Union
[
Node
,
ua
.
NodeId
,
str
,
int
]
=
ua
.
ObjectIds
.
Server
,
evtypes
:
Union
[
ua
.
ObjectIds
,
List
[
ua
.
ObjectIds
],
ua
.
NodeId
,
List
[
ua
.
NodeId
]]
=
ua
.
ObjectIds
.
ConditionType
,
evtypes
:
Union
[
int
,
ua
.
NodeId
,
Iterable
[
Union
[
int
,
ua
.
NodeId
]
]]
=
ua
.
ObjectIds
.
ConditionType
,
evfilter
:
ua
.
EventFilter
=
None
,
evfilter
:
Optional
[
ua
.
EventFilter
]
=
None
,
queuesize
:
int
=
0
queuesize
:
int
=
0
)
->
int
:
)
->
int
:
"""
"""
...
@@ -275,11 +349,35 @@ class Subscription:
...
@@ -275,11 +349,35 @@ class Subscription:
"""
"""
return
await
self
.
subscribe_events
(
sourcenode
,
evtypes
,
evfilter
,
queuesize
)
return
await
self
.
subscribe_events
(
sourcenode
,
evtypes
,
evfilter
,
queuesize
)
@
overload
async
def
_subscribe
(
self
,
nodes
:
Node
,
attr
=
ua
.
AttributeIds
.
Value
,
mfilter
:
Optional
[
ua
.
MonitoringFilter
]
=
None
,
queuesize
:
int
=
0
,
monitoring
:
ua
.
MonitoringMode
=
ua
.
MonitoringMode
.
Reporting
,
sampling_interval
:
ua
.
Duration
=
0.0
)
->
int
:
...
@
overload
async
def
_subscribe
(
self
,
nodes
:
Iterable
[
Node
],
attr
=
ua
.
AttributeIds
.
Value
,
mfilter
:
Optional
[
ua
.
MonitoringFilter
]
=
None
,
queuesize
:
int
=
0
,
monitoring
:
ua
.
MonitoringMode
=
ua
.
MonitoringMode
.
Reporting
,
sampling_interval
:
ua
.
Duration
=
0.0
)
->
List
[
Union
[
int
,
ua
.
StatusCode
]]:
...
async
def
_subscribe
(
async
def
_subscribe
(
self
,
self
,
nodes
:
Union
[
Node
,
Iterable
[
Node
]],
nodes
:
Union
[
Node
,
Iterable
[
Node
]],
attr
=
ua
.
AttributeIds
.
Value
,
attr
=
ua
.
AttributeIds
.
Value
,
mfilter
:
ua
.
MonitoringFilter
=
None
,
mfilter
:
Optional
[
ua
.
MonitoringFilter
]
=
None
,
queuesize
:
int
=
0
,
queuesize
:
int
=
0
,
monitoring
:
ua
.
MonitoringMode
=
ua
.
MonitoringMode
.
Reporting
,
monitoring
:
ua
.
MonitoringMode
=
ua
.
MonitoringMode
.
Reporting
,
sampling_interval
:
ua
.
Duration
=
0.0
sampling_interval
:
ua
.
Duration
=
0.0
...
@@ -344,14 +442,14 @@ class Subscription:
...
@@ -344,14 +442,14 @@ class Subscription:
mir
.
RequestedParameters
=
mparams
mir
.
RequestedParameters
=
mparams
return
mir
return
mir
async
def
create_monitored_items
(
self
,
monitored_items
:
List
[
ua
.
MonitoredItemCreateRequest
])
->
List
[
Union
[
int
,
ua
.
StatusCode
]]:
async
def
create_monitored_items
(
self
,
monitored_items
:
Iterable
[
ua
.
MonitoredItemCreateRequest
])
->
List
[
Union
[
int
,
ua
.
StatusCode
]]:
"""
"""
low level method to have full control over subscription parameters.
low level method to have full control over subscription parameters.
Client handle must be unique since it will be used as key for internal registration of data.
Client handle must be unique since it will be used as key for internal registration of data.
"""
"""
params
=
ua
.
CreateMonitoredItemsParameters
()
params
=
ua
.
CreateMonitoredItemsParameters
()
params
.
SubscriptionId
=
self
.
subscription_id
params
.
SubscriptionId
=
self
.
subscription_id
params
.
ItemsToCreate
=
monitored_items
params
.
ItemsToCreate
=
list
(
monitored_items
)
params
.
TimestampsToReturn
=
ua
.
TimestampsToReturn
.
Both
params
.
TimestampsToReturn
=
ua
.
TimestampsToReturn
.
Both
# insert monitored item into map to avoid notification arrive before result return
# insert monitored item into map to avoid notification arrive before result return
# server_handle is left as None in purpose as we don't get it yet.
# server_handle is left as None in purpose as we don't get it yet.
...
@@ -378,18 +476,18 @@ class Subscription:
...
@@ -378,18 +476,18 @@ class Subscription:
mids
.
append
(
result
.
MonitoredItemId
)
mids
.
append
(
result
.
MonitoredItemId
)
return
mids
return
mids
async
def
unsubscribe
(
self
,
handle
:
Union
[
int
,
List
[
int
]])
:
async
def
unsubscribe
(
self
,
handle
:
Union
[
int
,
Iterable
[
int
]])
->
None
:
"""
"""
Unsubscribe from datachange or events using the handle returned while subscribing.
Unsubscribe from datachange or events using the handle returned while subscribing.
If you delete the subscription, you do not need to unsubscribe.
If you delete the subscription, you do not need to unsubscribe.
:param handle: The handle that was returned when subscribing to the node/nodes
:param handle: The handle that was returned when subscribing to the node/nodes
"""
"""
handles
:
List
[
int
]
=
[
handle
]
if
isinstance
(
handle
,
int
)
else
handle
handles
:
Iterable
[
int
]
=
[
handle
]
if
isinstance
(
handle
,
int
)
else
handle
if
not
handles
:
if
not
handles
:
return
return
params
=
ua
.
DeleteMonitoredItemsParameters
()
params
=
ua
.
DeleteMonitoredItemsParameters
()
params
.
SubscriptionId
=
self
.
subscription_id
params
.
SubscriptionId
=
self
.
subscription_id
params
.
MonitoredItemIds
=
handles
params
.
MonitoredItemIds
=
list
(
handles
)
results
=
await
self
.
server
.
delete_monitored_items
(
params
)
results
=
await
self
.
server
.
delete_monitored_items
(
params
)
results
[
0
].
check
()
results
[
0
].
check
()
handle_map
=
{
v
.
server_handle
:
k
for
k
,
v
in
self
.
_monitored_items
.
items
()}
handle_map
=
{
v
.
server_handle
:
k
for
k
,
v
in
self
.
_monitored_items
.
items
()}
...
@@ -397,7 +495,9 @@ class Subscription:
...
@@ -397,7 +495,9 @@ class Subscription:
if
handle
in
handle_map
:
if
handle
in
handle_map
:
del
self
.
_monitored_items
[
handle_map
[
handle
]]
del
self
.
_monitored_items
[
handle_map
[
handle
]]
async
def
modify_monitored_item
(
self
,
handle
:
int
,
new_samp_time
:
ua
.
Duration
,
new_queuesize
:
int
=
0
,
mod_filter_val
:
int
=
-
1
):
async
def
modify_monitored_item
(
self
,
handle
:
int
,
new_samp_time
:
ua
.
Duration
,
new_queuesize
:
int
=
0
,
mod_filter_val
:
int
=
-
1
)
->
List
[
ua
.
MonitoredItemModifyResult
]:
"""
"""
Modify a monitored item.
Modify a monitored item.
:param handle: Handle returned when originally subscribing
:param handle: Handle returned when originally subscribing
...
@@ -439,7 +539,7 @@ class Subscription:
...
@@ -439,7 +539,7 @@ class Subscription:
new_samp_time
:
ua
.
Duration
,
new_samp_time
:
ua
.
Duration
,
mod_filter
:
ua
.
DataChangeFilter
,
mod_filter
:
ua
.
DataChangeFilter
,
client_handle
:
ua
.
IntegerId
client_handle
:
ua
.
IntegerId
):
)
->
ua
.
MonitoringParameters
:
req_params
=
ua
.
MonitoringParameters
()
req_params
=
ua
.
MonitoringParameters
()
req_params
.
ClientHandle
=
client_handle
req_params
.
ClientHandle
=
client_handle
req_params
.
QueueSize
=
new_queuesize
req_params
.
QueueSize
=
new_queuesize
...
@@ -447,14 +547,36 @@ class Subscription:
...
@@ -447,14 +547,36 @@ class Subscription:
req_params
.
SamplingInterval
=
new_samp_time
req_params
.
SamplingInterval
=
new_samp_time
return
req_params
return
req_params
def
deadband_monitor
(
@
overload
async
def
deadband_monitor
(
self
,
var
:
Node
,
deadband_val
:
ua
.
Double
,
deadbandtype
:
ua
.
UInt32
=
1
,
queuesize
:
int
=
0
,
attr
:
ua
.
AttributeIds
=
ua
.
AttributeIds
.
Value
)
->
int
:
...
@
overload
async
def
deadband_monitor
(
self
,
var
:
Iterable
[
Node
],
deadband_val
:
ua
.
Double
,
deadbandtype
:
ua
.
UInt32
=
1
,
queuesize
:
int
=
0
,
attr
:
ua
.
AttributeIds
=
ua
.
AttributeIds
.
Value
)
->
List
[
Union
[
int
,
ua
.
StatusCode
]]:
...
async
def
deadband_monitor
(
self
,
self
,
var
:
Union
[
Node
,
Iterable
[
Node
]],
var
:
Union
[
Node
,
Iterable
[
Node
]],
deadband_val
:
ua
.
Double
,
deadband_val
:
ua
.
Double
,
deadbandtype
:
ua
.
UInt32
=
1
,
deadbandtype
:
ua
.
UInt32
=
1
,
queuesize
:
int
=
0
,
queuesize
:
int
=
0
,
attr
:
ua
.
AttributeIds
=
ua
.
AttributeIds
.
Value
attr
:
ua
.
AttributeIds
=
ua
.
AttributeIds
.
Value
):
)
->
Union
[
int
,
List
[
Union
[
int
,
ua
.
StatusCode
]]]
:
"""
"""
Method to create a subscription with a Deadband Value.
Method to create a subscription with a Deadband Value.
Default deadband value type is absolute.
Default deadband value type is absolute.
...
@@ -471,9 +593,9 @@ class Subscription:
...
@@ -471,9 +593,9 @@ class Subscription:
deadband_filter
.
DeadbandType
=
deadbandtype
deadband_filter
.
DeadbandType
=
deadbandtype
# absolute float value or from 0 to 100 for percentage deadband
# absolute float value or from 0 to 100 for percentage deadband
deadband_filter
.
DeadbandValue
=
deadband_val
deadband_filter
.
DeadbandValue
=
deadband_val
return
self
.
_subscribe
(
var
,
attr
,
deadband_filter
,
queuesize
)
return
await
self
.
_subscribe
(
var
,
attr
,
deadband_filter
,
queuesize
)
async
def
set_monitoring_mode
(
self
,
monitoring
:
ua
.
MonitoringMode
)
->
ua
.
uatypes
.
StatusCode
:
async
def
set_monitoring_mode
(
self
,
monitoring
:
ua
.
MonitoringMode
)
->
List
[
ua
.
uatypes
.
StatusCode
]
:
"""
"""
The monitoring mode parameter is used
The monitoring mode parameter is used
to enable/disable the sampling of MonitoredItems
to enable/disable the sampling of MonitoredItems
...
@@ -482,6 +604,8 @@ class Subscription:
...
@@ -482,6 +604,8 @@ class Subscription:
:param monitoring: The monitoring mode to apply
:param monitoring: The monitoring mode to apply
:return: Return a Set Monitoring Mode Result
:return: Return a Set Monitoring Mode Result
"""
"""
if
not
isinstance
(
self
.
server
,
UaClient
):
raise
ua
.
uaerrors
.
UaError
(
f"set_monitoring_mode() is not supported in
{
self
.
server
}
."
)
node_handles
=
[]
node_handles
=
[]
for
mi
in
self
.
_monitored_items
.
values
():
for
mi
in
self
.
_monitored_items
.
values
():
node_handles
.
append
(
mi
.
server_handle
)
node_handles
.
append
(
mi
.
server_handle
)
...
@@ -492,7 +616,7 @@ class Subscription:
...
@@ -492,7 +616,7 @@ class Subscription:
params
.
MonitoringMode
=
monitoring
params
.
MonitoringMode
=
monitoring
return
await
self
.
server
.
set_monitoring_mode
(
params
)
return
await
self
.
server
.
set_monitoring_mode
(
params
)
async
def
set_publishing_mode
(
self
,
publishing
:
bool
)
->
ua
.
uatypes
.
StatusCode
:
async
def
set_publishing_mode
(
self
,
publishing
:
bool
)
->
List
[
ua
.
uatypes
.
StatusCode
]
:
"""
"""
Disable publishing of NotificationMessages for the subscription,
Disable publishing of NotificationMessages for the subscription,
but doesn't discontinue the sending of keep-alive Messages,
but doesn't discontinue the sending of keep-alive Messages,
...
@@ -502,6 +626,8 @@ class Subscription:
...
@@ -502,6 +626,8 @@ class Subscription:
:return: Return a Set Publishing Mode Result
:return: Return a Set Publishing Mode Result
"""
"""
self
.
logger
.
info
(
"set_publishing_mode"
)
self
.
logger
.
info
(
"set_publishing_mode"
)
if
not
isinstance
(
self
.
server
,
UaClient
):
raise
ua
.
uaerrors
.
UaError
(
f"set_publishing_mode() is not supported in
{
self
.
server
}
."
)
params
=
ua
.
SetPublishingModeParameters
()
params
=
ua
.
SetPublishingModeParameters
()
params
.
SubscriptionIds
=
[
self
.
subscription_id
]
# type: ignore
params
.
SubscriptionIds
=
[
self
.
subscription_id
]
# type: ignore
params
.
PublishingEnabled
=
publishing
params
.
PublishingEnabled
=
publishing
...
...
asyncua/server/history.py
View file @
066c61eb
from
__future__
import
annotations
import
asyncio
import
asyncio
import
logging
import
logging
from
datetime
import
timedelta
from
datetime
import
timedelta
from
datetime
import
datetime
from
datetime
import
datetime
from
asyncua
import
ua
from
asyncua
import
ua
from
..common.subscription
import
Subscription
,
SubHandler
from
asyncua.common
import
subscription
from
asyncua.common.subscription
import
Subscription
,
SubscriptionHandler
from
..common.utils
import
Buffer
from
..common.utils
import
Buffer
...
@@ -213,8 +216,8 @@ class HistoryDict(HistoryStorageInterface):
...
@@ -213,8 +216,8 @@ class HistoryDict(HistoryStorageInterface):
pass
pass
class
SubHandler
(
SubHandler
):
# type: ignore
class
SubHandler
(
subscription
.
SubHandler
):
def
__init__
(
self
,
storage
):
def
__init__
(
self
,
storage
:
HistoryStorageInterface
):
self
.
storage
=
storage
self
.
storage
=
storage
def
datachange_notification
(
self
,
node
,
val
,
data
):
def
datachange_notification
(
self
,
node
,
val
,
data
):
...
@@ -240,7 +243,7 @@ class HistoryManager:
...
@@ -240,7 +243,7 @@ class HistoryManager:
"""
"""
self
.
storage
=
storage
self
.
storage
=
storage
async
def
_create_subscription
(
self
,
handler
):
async
def
_create_subscription
(
self
,
handler
:
SubscriptionHandler
):
params
=
ua
.
CreateSubscriptionParameters
()
params
=
ua
.
CreateSubscriptionParameters
()
params
.
RequestedPublishingInterval
=
10
params
.
RequestedPublishingInterval
=
10
params
.
RequestedLifetimeCount
=
3000
params
.
RequestedLifetimeCount
=
3000
...
...
asyncua/server/internal_session.py
View file @
066c61eb
...
@@ -59,7 +59,7 @@ class InternalSession(AbstractSession):
...
@@ -59,7 +59,7 @@ class InternalSession(AbstractSession):
def
is_activated
(
self
)
->
bool
:
def
is_activated
(
self
)
->
bool
:
return
self
.
state
==
SessionState
.
Activated
return
self
.
state
==
SessionState
.
Activated
async
def
create_session
(
self
,
params
:
ua
.
CreateSessionParameters
,
sockname
:
Optional
[
Tuple
[
str
,
int
]]
=
None
):
async
def
create_session
(
self
,
params
:
ua
.
CreateSessionParameters
,
sockname
:
Optional
[
Tuple
[
str
,
int
]]
=
None
):
self
.
logger
.
info
(
'Create session request'
)
self
.
logger
.
info
(
'Create session request'
)
result
=
ua
.
CreateSessionResult
()
result
=
ua
.
CreateSessionResult
()
result
.
SessionId
=
self
.
session_id
result
.
SessionId
=
self
.
session_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