ni.measurementlink.sessionmanagement.v1.client 0.1.0.dev0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ni.measurementlink.sessionmanagement.v1.client might be problematic. Click here for more details.
- ni/measurementlink/sessionmanagement/v1/client/__init__.py +107 -0
- ni/measurementlink/sessionmanagement/v1/client/_client.py +405 -0
- ni/measurementlink/sessionmanagement/v1/client/_constants.py +32 -0
- ni/measurementlink/sessionmanagement/v1/client/_drivers/__init__.py +46 -0
- ni/measurementlink/sessionmanagement/v1/client/_drivers/_configuration.py +111 -0
- ni/measurementlink/sessionmanagement/v1/client/_drivers/_dotenvpath.py +73 -0
- ni/measurementlink/sessionmanagement/v1/client/_drivers/_grpcdevice.py +96 -0
- ni/measurementlink/sessionmanagement/v1/client/_drivers/_nidaqmx.py +54 -0
- ni/measurementlink/sessionmanagement/v1/client/_drivers/_nidcpower.py +63 -0
- ni/measurementlink/sessionmanagement/v1/client/_drivers/_nidigital.py +64 -0
- ni/measurementlink/sessionmanagement/v1/client/_drivers/_nidmm.py +64 -0
- ni/measurementlink/sessionmanagement/v1/client/_drivers/_nifgen.py +63 -0
- ni/measurementlink/sessionmanagement/v1/client/_drivers/_niscope.py +64 -0
- ni/measurementlink/sessionmanagement/v1/client/_drivers/_niswitch.py +82 -0
- ni/measurementlink/sessionmanagement/v1/client/_reservation.py +2769 -0
- ni/measurementlink/sessionmanagement/v1/client/_types.py +507 -0
- ni/measurementlink/sessionmanagement/v1/client/py.typed +0 -0
- ni_measurementlink_sessionmanagement_v1_client-0.1.0.dev0.dist-info/METADATA +80 -0
- ni_measurementlink_sessionmanagement_v1_client-0.1.0.dev0.dist-info/RECORD +20 -0
- ni_measurementlink_sessionmanagement_v1_client-0.1.0.dev0.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"""Public API for accessing the measurement plug-in management service."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import warnings
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from deprecation import DeprecatedWarning
|
|
9
|
+
|
|
10
|
+
from ni.measurementlink.sessionmanagement.v1.client._client import (
|
|
11
|
+
SessionManagementClient,
|
|
12
|
+
)
|
|
13
|
+
from ni.measurementlink.sessionmanagement.v1.client._constants import (
|
|
14
|
+
GRPC_SERVICE_CLASS,
|
|
15
|
+
GRPC_SERVICE_INTERFACE_NAME,
|
|
16
|
+
INSTRUMENT_TYPE_NI_DAQMX,
|
|
17
|
+
INSTRUMENT_TYPE_NI_DCPOWER,
|
|
18
|
+
INSTRUMENT_TYPE_NI_DIGITAL_PATTERN,
|
|
19
|
+
INSTRUMENT_TYPE_NI_DMM,
|
|
20
|
+
INSTRUMENT_TYPE_NI_FGEN,
|
|
21
|
+
INSTRUMENT_TYPE_NI_HSDIO,
|
|
22
|
+
INSTRUMENT_TYPE_NI_MODEL_BASED_INSTRUMENT,
|
|
23
|
+
INSTRUMENT_TYPE_NI_RELAY_DRIVER,
|
|
24
|
+
INSTRUMENT_TYPE_NI_RFMX,
|
|
25
|
+
INSTRUMENT_TYPE_NI_RFPM,
|
|
26
|
+
INSTRUMENT_TYPE_NI_RFSA,
|
|
27
|
+
INSTRUMENT_TYPE_NI_RFSG,
|
|
28
|
+
INSTRUMENT_TYPE_NI_SCOPE,
|
|
29
|
+
INSTRUMENT_TYPE_NI_SWITCH_EXECUTIVE_VIRTUAL_DEVICE,
|
|
30
|
+
INSTRUMENT_TYPE_NONE,
|
|
31
|
+
SITE_SYSTEM_PINS,
|
|
32
|
+
)
|
|
33
|
+
from ni.measurementlink.sessionmanagement.v1.client._reservation import (
|
|
34
|
+
BaseReservation,
|
|
35
|
+
MultiplexerSessionContainer,
|
|
36
|
+
MultiSessionReservation,
|
|
37
|
+
SingleSessionReservation,
|
|
38
|
+
)
|
|
39
|
+
from ni.measurementlink.sessionmanagement.v1.client._types import (
|
|
40
|
+
ChannelMapping,
|
|
41
|
+
Connection,
|
|
42
|
+
MultiplexerSessionInformation,
|
|
43
|
+
PinMapContext,
|
|
44
|
+
SessionInformation,
|
|
45
|
+
SessionInitializationBehavior,
|
|
46
|
+
TypedConnection,
|
|
47
|
+
TypedConnectionWithMultiplexer,
|
|
48
|
+
TypedMultiplexerSessionInformation,
|
|
49
|
+
TypedSessionInformation,
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
__all__ = [
|
|
53
|
+
"BaseReservation",
|
|
54
|
+
"ChannelMapping",
|
|
55
|
+
"Client",
|
|
56
|
+
"Connection",
|
|
57
|
+
"GRPC_SERVICE_CLASS",
|
|
58
|
+
"GRPC_SERVICE_INTERFACE_NAME",
|
|
59
|
+
"INSTRUMENT_TYPE_NI_DAQMX",
|
|
60
|
+
"INSTRUMENT_TYPE_NI_DCPOWER",
|
|
61
|
+
"INSTRUMENT_TYPE_NI_DIGITAL_PATTERN",
|
|
62
|
+
"INSTRUMENT_TYPE_NI_DMM",
|
|
63
|
+
"INSTRUMENT_TYPE_NI_FGEN",
|
|
64
|
+
"INSTRUMENT_TYPE_NI_HSDIO",
|
|
65
|
+
"INSTRUMENT_TYPE_NI_MODEL_BASED_INSTRUMENT",
|
|
66
|
+
"INSTRUMENT_TYPE_NI_RELAY_DRIVER",
|
|
67
|
+
"INSTRUMENT_TYPE_NI_RFMX",
|
|
68
|
+
"INSTRUMENT_TYPE_NI_RFPM",
|
|
69
|
+
"INSTRUMENT_TYPE_NI_RFSA",
|
|
70
|
+
"INSTRUMENT_TYPE_NI_RFSG",
|
|
71
|
+
"INSTRUMENT_TYPE_NI_SCOPE",
|
|
72
|
+
"INSTRUMENT_TYPE_NI_SWITCH_EXECUTIVE_VIRTUAL_DEVICE",
|
|
73
|
+
"INSTRUMENT_TYPE_NONE",
|
|
74
|
+
"MultiSessionReservation",
|
|
75
|
+
"PinMapContext",
|
|
76
|
+
"MultiplexerSessionContainer",
|
|
77
|
+
"MultiplexerSessionInformation",
|
|
78
|
+
"SessionInformation",
|
|
79
|
+
"SessionInitializationBehavior",
|
|
80
|
+
"SessionManagementClient",
|
|
81
|
+
"SingleSessionReservation",
|
|
82
|
+
"SITE_SYSTEM_PINS",
|
|
83
|
+
"TypedConnection",
|
|
84
|
+
"TypedConnectionWithMultiplexer",
|
|
85
|
+
"TypedMultiplexerSessionInformation",
|
|
86
|
+
"TypedSessionInformation",
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def __getattr__(name: str) -> Any:
|
|
91
|
+
if name == "Reservation":
|
|
92
|
+
warnings.warn(
|
|
93
|
+
DeprecatedWarning(
|
|
94
|
+
name,
|
|
95
|
+
deprecated_in="1.1.0",
|
|
96
|
+
removed_in=None,
|
|
97
|
+
details="Use MultiSessionReservation instead.",
|
|
98
|
+
),
|
|
99
|
+
stacklevel=2,
|
|
100
|
+
)
|
|
101
|
+
return MultiSessionReservation
|
|
102
|
+
else:
|
|
103
|
+
raise AttributeError(f"module {__name__} has no attribute {name}")
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
Client = SessionManagementClient
|
|
107
|
+
"""Alias for compatibility with code that uses session_management.Client."""
|
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
"""Session management client class."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
import threading
|
|
7
|
+
import warnings
|
|
8
|
+
from collections.abc import Iterable, Mapping
|
|
9
|
+
|
|
10
|
+
import google.protobuf.internal.containers
|
|
11
|
+
import grpc
|
|
12
|
+
import ni.measurementlink.sessionmanagement.v1.session_management_service_pb2 as session_management_service_pb2
|
|
13
|
+
import ni.measurementlink.sessionmanagement.v1.session_management_service_pb2_grpc as session_management_service_pb2_grpc
|
|
14
|
+
from ni.measurementlink.discovery.v1.client import DiscoveryClient
|
|
15
|
+
from ni_grpc_extensions.channelpool import GrpcChannelPool
|
|
16
|
+
|
|
17
|
+
from ni.measurementlink.sessionmanagement.v1.client._constants import (
|
|
18
|
+
GRPC_SERVICE_CLASS,
|
|
19
|
+
GRPC_SERVICE_INTERFACE_NAME,
|
|
20
|
+
)
|
|
21
|
+
from ni.measurementlink.sessionmanagement.v1.client._reservation import (
|
|
22
|
+
MultiplexerSessionContainer,
|
|
23
|
+
MultiSessionReservation,
|
|
24
|
+
SingleSessionReservation,
|
|
25
|
+
)
|
|
26
|
+
from ni.measurementlink.sessionmanagement.v1.client._types import (
|
|
27
|
+
MultiplexerSessionInformation,
|
|
28
|
+
PinMapContext,
|
|
29
|
+
SessionInformation,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
_logger = logging.getLogger(__name__)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class SessionManagementClient:
|
|
36
|
+
"""Client for accessing the measurement plug-in session management service."""
|
|
37
|
+
|
|
38
|
+
def __init__(
|
|
39
|
+
self,
|
|
40
|
+
*,
|
|
41
|
+
discovery_client: DiscoveryClient | None = None,
|
|
42
|
+
grpc_channel: grpc.Channel | None = None,
|
|
43
|
+
grpc_channel_pool: GrpcChannelPool | None = None,
|
|
44
|
+
) -> None:
|
|
45
|
+
"""Initialize session management client.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
discovery_client: An optional discovery client (recommended).
|
|
49
|
+
|
|
50
|
+
grpc_channel: An optional session management gRPC channel.
|
|
51
|
+
|
|
52
|
+
grpc_channel_pool: An optional gRPC channel pool (recommended).
|
|
53
|
+
"""
|
|
54
|
+
self._initialization_lock = threading.Lock()
|
|
55
|
+
self._discovery_client = discovery_client
|
|
56
|
+
self._grpc_channel_pool = grpc_channel_pool
|
|
57
|
+
self._stub: session_management_service_pb2_grpc.SessionManagementServiceStub | None = None
|
|
58
|
+
|
|
59
|
+
if grpc_channel is not None:
|
|
60
|
+
self._stub = session_management_service_pb2_grpc.SessionManagementServiceStub(
|
|
61
|
+
grpc_channel
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
def _get_stub(self) -> session_management_service_pb2_grpc.SessionManagementServiceStub:
|
|
65
|
+
if self._stub is None:
|
|
66
|
+
with self._initialization_lock:
|
|
67
|
+
if self._grpc_channel_pool is None:
|
|
68
|
+
_logger.debug("Creating unshared GrpcChannelPool.")
|
|
69
|
+
self._grpc_channel_pool = GrpcChannelPool()
|
|
70
|
+
if self._discovery_client is None:
|
|
71
|
+
_logger.debug("Creating unshared DiscoveryClient.")
|
|
72
|
+
self._discovery_client = DiscoveryClient(
|
|
73
|
+
grpc_channel_pool=self._grpc_channel_pool
|
|
74
|
+
)
|
|
75
|
+
if self._stub is None:
|
|
76
|
+
compute_nodes = self._discovery_client.enumerate_compute_nodes()
|
|
77
|
+
remote_compute_nodes = [node for node in compute_nodes if not node.is_local]
|
|
78
|
+
# Use remote node URL as deployment target if only one remote node is found.
|
|
79
|
+
# If more than one remote node exists, use empty string for deployment target.
|
|
80
|
+
first_remote_node_url = (
|
|
81
|
+
remote_compute_nodes[0].url if len(remote_compute_nodes) == 1 else ""
|
|
82
|
+
)
|
|
83
|
+
service_location = self._discovery_client.resolve_service(
|
|
84
|
+
provided_interface=GRPC_SERVICE_INTERFACE_NAME,
|
|
85
|
+
deployment_target=first_remote_node_url,
|
|
86
|
+
service_class=GRPC_SERVICE_CLASS,
|
|
87
|
+
)
|
|
88
|
+
channel = self._grpc_channel_pool.get_channel(service_location.insecure_address)
|
|
89
|
+
self._stub = session_management_service_pb2_grpc.SessionManagementServiceStub(
|
|
90
|
+
channel
|
|
91
|
+
)
|
|
92
|
+
return self._stub
|
|
93
|
+
|
|
94
|
+
def reserve_session(
|
|
95
|
+
self,
|
|
96
|
+
context: PinMapContext,
|
|
97
|
+
pin_or_relay_names: str | Iterable[str] | None = None,
|
|
98
|
+
instrument_type_id: str | None = None,
|
|
99
|
+
timeout: float | None = 0.0,
|
|
100
|
+
) -> SingleSessionReservation:
|
|
101
|
+
"""Reserve a single session.
|
|
102
|
+
|
|
103
|
+
Reserve the session matching the given pins, sites, and instrument type ID and return the
|
|
104
|
+
information needed to create or access the session.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
context: Includes the pin map ID for the pin map in the Pin Map Service,
|
|
108
|
+
as well as the list of sites for the measurement.
|
|
109
|
+
|
|
110
|
+
pin_or_relay_names: One or multiple pins, pin groups, relays, or relay groups to use
|
|
111
|
+
for the measurement.
|
|
112
|
+
|
|
113
|
+
If unspecified, reserve sessions for all pins and relays in the registered pin map
|
|
114
|
+
resource.
|
|
115
|
+
|
|
116
|
+
instrument_type_id: Instrument type ID for the measurement.
|
|
117
|
+
|
|
118
|
+
If unspecified, this method reserve sessions for all instrument types connected
|
|
119
|
+
in the registered pin map resource.
|
|
120
|
+
|
|
121
|
+
For NI instruments, use instrument type id constants, such as
|
|
122
|
+
:py:const:`INSTRUMENT_TYPE_NI_DCPOWER` or :py:const:`INSTRUMENT_TYPE_NI_DMM`.
|
|
123
|
+
|
|
124
|
+
For custom instruments, use the instrument type id defined in the pin map file.
|
|
125
|
+
|
|
126
|
+
timeout: Timeout in seconds.
|
|
127
|
+
|
|
128
|
+
Allowed values: 0 (non-blocking, fails immediately if resources cannot be
|
|
129
|
+
reserved), -1 (infinite timeout), or any other positive numeric value (wait for
|
|
130
|
+
that number of seconds)
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
A reservation object with which you can query information about the session and
|
|
134
|
+
unreserve it.
|
|
135
|
+
"""
|
|
136
|
+
response = self._reserve_sessions(context, pin_or_relay_names, instrument_type_id, timeout)
|
|
137
|
+
if len(response.sessions) == 0:
|
|
138
|
+
raise ValueError("No sessions reserved. Expected single session, got 0 sessions.")
|
|
139
|
+
elif len(response.sessions) > 1:
|
|
140
|
+
self._unreserve_sessions(response.sessions)
|
|
141
|
+
raise ValueError(
|
|
142
|
+
"Too many sessions reserved. Expected single session, got "
|
|
143
|
+
f"{len(response.sessions)} sessions."
|
|
144
|
+
)
|
|
145
|
+
else:
|
|
146
|
+
return SingleSessionReservation(
|
|
147
|
+
session_management_client=self,
|
|
148
|
+
session_info=response.sessions,
|
|
149
|
+
multiplexer_session_info=response.multiplexer_sessions,
|
|
150
|
+
pin_or_relay_group_mappings=_to_group_mappings_dict(response.group_mappings),
|
|
151
|
+
reserved_pin_or_relay_names=pin_or_relay_names,
|
|
152
|
+
reserved_sites=context.sites,
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
def reserve_sessions(
|
|
156
|
+
self,
|
|
157
|
+
context: PinMapContext,
|
|
158
|
+
pin_or_relay_names: str | Iterable[str] | None = None,
|
|
159
|
+
instrument_type_id: str | None = None,
|
|
160
|
+
timeout: float | None = 0.0,
|
|
161
|
+
) -> MultiSessionReservation:
|
|
162
|
+
"""Reserve multiple sessions.
|
|
163
|
+
|
|
164
|
+
Reserve sessions matching the given pins, sites, and instrument type ID and return the
|
|
165
|
+
information needed to create or access the sessions.
|
|
166
|
+
|
|
167
|
+
Args:
|
|
168
|
+
context: Includes the pin map ID for the pin map in the Pin Map Service,
|
|
169
|
+
as well as the list of sites for the measurement.
|
|
170
|
+
|
|
171
|
+
pin_or_relay_names: One or multiple pins, pin groups, relays, or relay groups to use
|
|
172
|
+
for the measurement.
|
|
173
|
+
|
|
174
|
+
If unspecified, reserve sessions for all pins and relays in the registered pin map
|
|
175
|
+
resource.
|
|
176
|
+
|
|
177
|
+
instrument_type_id: Instrument type ID for the measurement.
|
|
178
|
+
|
|
179
|
+
If unspecified, this method reserves sessions for all instrument types connected
|
|
180
|
+
in the registered pin map resource.
|
|
181
|
+
|
|
182
|
+
For NI instruments, use instrument type id constants, such as
|
|
183
|
+
:py:const:`INSTRUMENT_TYPE_NI_DCPOWER` or :py:const:`INSTRUMENT_TYPE_NI_DMM`.
|
|
184
|
+
|
|
185
|
+
For custom instruments, use the instrument type id defined in the pin map file.
|
|
186
|
+
|
|
187
|
+
timeout: Timeout in seconds.
|
|
188
|
+
|
|
189
|
+
Allowed values: 0 (non-blocking, fails immediately if resources cannot be
|
|
190
|
+
reserved), -1 (infinite timeout), or any other positive numeric value (wait for
|
|
191
|
+
that number of seconds)
|
|
192
|
+
|
|
193
|
+
Returns:
|
|
194
|
+
A reservation object with which you can query information about the sessions and
|
|
195
|
+
unreserve them.
|
|
196
|
+
"""
|
|
197
|
+
response = self._reserve_sessions(context, pin_or_relay_names, instrument_type_id, timeout)
|
|
198
|
+
return MultiSessionReservation(
|
|
199
|
+
session_management_client=self,
|
|
200
|
+
session_info=response.sessions,
|
|
201
|
+
multiplexer_session_info=response.multiplexer_sessions,
|
|
202
|
+
pin_or_relay_group_mappings=_to_group_mappings_dict(response.group_mappings),
|
|
203
|
+
reserved_pin_or_relay_names=pin_or_relay_names,
|
|
204
|
+
reserved_sites=context.sites,
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
def _reserve_sessions(
|
|
208
|
+
self,
|
|
209
|
+
context: PinMapContext,
|
|
210
|
+
pin_or_relay_names: str | Iterable[str] | None = None,
|
|
211
|
+
instrument_type_id: str | None = None,
|
|
212
|
+
timeout: float | None = 0.0,
|
|
213
|
+
) -> session_management_service_pb2.ReserveSessionsResponse:
|
|
214
|
+
request = session_management_service_pb2.ReserveSessionsRequest(
|
|
215
|
+
pin_map_context=context._to_grpc(),
|
|
216
|
+
timeout_in_milliseconds=_timeout_to_milliseconds(timeout),
|
|
217
|
+
)
|
|
218
|
+
if instrument_type_id is not None:
|
|
219
|
+
request.instrument_type_id = instrument_type_id
|
|
220
|
+
if isinstance(pin_or_relay_names, str):
|
|
221
|
+
request.pin_or_relay_names.append(pin_or_relay_names)
|
|
222
|
+
elif pin_or_relay_names is not None:
|
|
223
|
+
request.pin_or_relay_names.extend(pin_or_relay_names)
|
|
224
|
+
|
|
225
|
+
return self._get_stub().ReserveSessions(request)
|
|
226
|
+
|
|
227
|
+
def _unreserve_sessions(
|
|
228
|
+
self, session_info: Iterable[session_management_service_pb2.SessionInformation]
|
|
229
|
+
) -> None:
|
|
230
|
+
"""Unreserves sessions so they can be accessed by other clients."""
|
|
231
|
+
request = session_management_service_pb2.UnreserveSessionsRequest(sessions=session_info)
|
|
232
|
+
self._get_stub().UnreserveSessions(request)
|
|
233
|
+
|
|
234
|
+
def register_sessions(self, session_info: Iterable[SessionInformation]) -> None:
|
|
235
|
+
"""Register sessions with the session management service.
|
|
236
|
+
|
|
237
|
+
Indicates that the sessions are open and will need to be closed later.
|
|
238
|
+
|
|
239
|
+
Args:
|
|
240
|
+
session_info: Sessions to register.
|
|
241
|
+
"""
|
|
242
|
+
request = session_management_service_pb2.RegisterSessionsRequest(
|
|
243
|
+
sessions=(info._to_grpc_v1() for info in session_info),
|
|
244
|
+
)
|
|
245
|
+
self._get_stub().RegisterSessions(request)
|
|
246
|
+
|
|
247
|
+
def unregister_sessions(self, session_info: Iterable[SessionInformation]) -> None:
|
|
248
|
+
"""Unregisters sessions from the session management service.
|
|
249
|
+
|
|
250
|
+
Indicates that the sessions have been closed and will need to be reopened before they can be
|
|
251
|
+
used again.
|
|
252
|
+
|
|
253
|
+
Args:
|
|
254
|
+
session_info: Sessions to unregister.
|
|
255
|
+
"""
|
|
256
|
+
request = session_management_service_pb2.UnregisterSessionsRequest(
|
|
257
|
+
sessions=(info._to_grpc_v1() for info in session_info),
|
|
258
|
+
)
|
|
259
|
+
self._get_stub().UnregisterSessions(request)
|
|
260
|
+
|
|
261
|
+
def reserve_all_registered_sessions(
|
|
262
|
+
self, instrument_type_id: str | None = None, timeout: float | None = 10.0
|
|
263
|
+
) -> MultiSessionReservation:
|
|
264
|
+
"""Reserve all sessions currently registered with the session management service.
|
|
265
|
+
|
|
266
|
+
Args:
|
|
267
|
+
instrument_type_id: Instrument type ID for the measurement.
|
|
268
|
+
|
|
269
|
+
If unspecified, reserve sessions for all instrument types connected in the
|
|
270
|
+
registered pin map resource.
|
|
271
|
+
|
|
272
|
+
For NI instruments, use instrument type id constants, such as
|
|
273
|
+
:py:const:`INSTRUMENT_TYPE_NI_DCPOWER` or :py:const:`INSTRUMENT_TYPE_NI_DMM`.
|
|
274
|
+
|
|
275
|
+
For custom instruments, use the instrument type id defined in the pin map file.
|
|
276
|
+
|
|
277
|
+
timeout: Timeout in seconds.
|
|
278
|
+
|
|
279
|
+
An arbitrary timeout to wait for the measurement to complete or be canceled.
|
|
280
|
+
|
|
281
|
+
Allowed values: 0 (non-blocking, fails immediately if resources cannot be
|
|
282
|
+
reserved), -1 (infinite timeout), or any other positive numeric value (wait for
|
|
283
|
+
that number of seconds)
|
|
284
|
+
|
|
285
|
+
Returns:
|
|
286
|
+
A reservation object with which you can query information about the sessions and
|
|
287
|
+
unreserve them.
|
|
288
|
+
"""
|
|
289
|
+
request = session_management_service_pb2.ReserveAllRegisteredSessionsRequest(
|
|
290
|
+
timeout_in_milliseconds=_timeout_to_milliseconds(timeout)
|
|
291
|
+
)
|
|
292
|
+
if instrument_type_id is not None:
|
|
293
|
+
request.instrument_type_id = instrument_type_id
|
|
294
|
+
|
|
295
|
+
response = self._get_stub().ReserveAllRegisteredSessions(request)
|
|
296
|
+
return MultiSessionReservation(
|
|
297
|
+
session_management_client=self, session_info=response.sessions
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
def register_multiplexer_sessions(
|
|
301
|
+
self, multiplexer_session_info: Iterable[MultiplexerSessionInformation]
|
|
302
|
+
) -> None:
|
|
303
|
+
"""Register multiplexer sessions with the session management service.
|
|
304
|
+
|
|
305
|
+
Indicates that the sessions are open and will need to be closed later.
|
|
306
|
+
|
|
307
|
+
Args:
|
|
308
|
+
multiplexer_session_info: Sessions to register.
|
|
309
|
+
"""
|
|
310
|
+
request = session_management_service_pb2.RegisterMultiplexerSessionsRequest(
|
|
311
|
+
multiplexer_sessions=(info._to_grpc_v1() for info in multiplexer_session_info),
|
|
312
|
+
)
|
|
313
|
+
self._get_stub().RegisterMultiplexerSessions(request)
|
|
314
|
+
|
|
315
|
+
def unregister_multiplexer_sessions(
|
|
316
|
+
self, multiplexer_session_info: Iterable[MultiplexerSessionInformation]
|
|
317
|
+
) -> None:
|
|
318
|
+
"""Unregisters multiplexer sessions from the session management service.
|
|
319
|
+
|
|
320
|
+
Indicates that the sessions have been closed and will need to be reopened before they can be
|
|
321
|
+
used again.
|
|
322
|
+
|
|
323
|
+
Args:
|
|
324
|
+
multiplexer_session_info: Sessions to unregister.
|
|
325
|
+
"""
|
|
326
|
+
request = session_management_service_pb2.UnregisterMultiplexerSessionsRequest(
|
|
327
|
+
multiplexer_sessions=(info._to_grpc_v1() for info in multiplexer_session_info),
|
|
328
|
+
)
|
|
329
|
+
self._get_stub().UnregisterMultiplexerSessions(request)
|
|
330
|
+
|
|
331
|
+
def get_multiplexer_sessions(
|
|
332
|
+
self, pin_map_context: PinMapContext, multiplexer_type_id: str | None = None
|
|
333
|
+
) -> MultiplexerSessionContainer:
|
|
334
|
+
"""Get all multiplexer session infos matching the specified criteria.
|
|
335
|
+
|
|
336
|
+
Returns the information needed to create or access the multiplexer sessions
|
|
337
|
+
without reserving the connected instruments.
|
|
338
|
+
|
|
339
|
+
Args:
|
|
340
|
+
pin_map_context: Includes the pin map ID for the pin map in the pin map service,
|
|
341
|
+
as well as the list of sites for the measurement.
|
|
342
|
+
|
|
343
|
+
multiplexer_type_id: User-defined identifier for the multiplexer
|
|
344
|
+
type in the pin map editor. If not specified, the multiplexer
|
|
345
|
+
type id is ignored when matching multiplexer sessions.
|
|
346
|
+
|
|
347
|
+
Returns:
|
|
348
|
+
The multiplexer session container with the matching session infos.
|
|
349
|
+
"""
|
|
350
|
+
request = session_management_service_pb2.GetMultiplexerSessionsRequest(
|
|
351
|
+
pin_map_context=pin_map_context._to_grpc()
|
|
352
|
+
)
|
|
353
|
+
if multiplexer_type_id is not None:
|
|
354
|
+
request.multiplexer_type_id = multiplexer_type_id
|
|
355
|
+
|
|
356
|
+
response = self._get_stub().GetMultiplexerSessions(request)
|
|
357
|
+
session_infos = [session for session in response.multiplexer_sessions]
|
|
358
|
+
return MultiplexerSessionContainer(self, session_infos)
|
|
359
|
+
|
|
360
|
+
def get_all_registered_multiplexer_sessions(
|
|
361
|
+
self, multiplexer_type_id: str | None = None
|
|
362
|
+
) -> MultiplexerSessionContainer:
|
|
363
|
+
"""Get all multiplexer session infos registered with the session management service.
|
|
364
|
+
|
|
365
|
+
Args:
|
|
366
|
+
multiplexer_type_id: User-defined identifier for the multiplexer
|
|
367
|
+
type in the pin map editor. If not specified, the multiplexer
|
|
368
|
+
type id is ignored when matching multiplexer sessions.
|
|
369
|
+
|
|
370
|
+
Returns:
|
|
371
|
+
The multiplexer session container with the matching session infos registered
|
|
372
|
+
with the session management service.
|
|
373
|
+
"""
|
|
374
|
+
request = session_management_service_pb2.GetAllRegisteredMultiplexerSessionsRequest()
|
|
375
|
+
if multiplexer_type_id is not None:
|
|
376
|
+
request.multiplexer_type_id = multiplexer_type_id
|
|
377
|
+
|
|
378
|
+
response = self._get_stub().GetAllRegisteredMultiplexerSessions(request)
|
|
379
|
+
session_infos = [session for session in response.multiplexer_sessions]
|
|
380
|
+
return MultiplexerSessionContainer(self, session_infos)
|
|
381
|
+
|
|
382
|
+
|
|
383
|
+
def _timeout_to_milliseconds(timeout: float | None) -> int:
|
|
384
|
+
if timeout is None:
|
|
385
|
+
return 0
|
|
386
|
+
elif timeout == -1:
|
|
387
|
+
return -1
|
|
388
|
+
elif timeout < 0:
|
|
389
|
+
warnings.warn("Specify -1 for an infinite timeout.", RuntimeWarning)
|
|
390
|
+
return -1
|
|
391
|
+
else:
|
|
392
|
+
return round(timeout * 1000)
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
def _to_group_mappings_dict(
|
|
396
|
+
mappings: google.protobuf.internal.containers.MessageMap[
|
|
397
|
+
str, session_management_service_pb2.ResolvedPinsOrRelays
|
|
398
|
+
],
|
|
399
|
+
) -> Mapping[str, Iterable[str]]:
|
|
400
|
+
group_mappings: dict[str, Iterable[str]] = {}
|
|
401
|
+
if mappings is not None:
|
|
402
|
+
for key, value in mappings.items():
|
|
403
|
+
group_mappings[key] = value.pin_or_relay_names
|
|
404
|
+
|
|
405
|
+
return group_mappings
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""Session management constants."""
|
|
2
|
+
|
|
3
|
+
GRPC_SERVICE_INTERFACE_NAME = "ni.measurementlink.sessionmanagement.v1.SessionManagementService"
|
|
4
|
+
GRPC_SERVICE_CLASS = "ni.measurementlink.sessionmanagement.v1.SessionManagementService"
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# Constants for instrument_type_id parameters
|
|
8
|
+
INSTRUMENT_TYPE_NONE = ""
|
|
9
|
+
INSTRUMENT_TYPE_NI_DCPOWER = "niDCPower"
|
|
10
|
+
INSTRUMENT_TYPE_NI_HSDIO = "niHSDIO"
|
|
11
|
+
INSTRUMENT_TYPE_NI_RFSA = "niRFSA"
|
|
12
|
+
INSTRUMENT_TYPE_NI_RFMX = "niRFmx"
|
|
13
|
+
INSTRUMENT_TYPE_NI_RFSG = "niRFSG"
|
|
14
|
+
INSTRUMENT_TYPE_NI_RFPM = "niRFPM"
|
|
15
|
+
INSTRUMENT_TYPE_NI_DMM = "niDMM"
|
|
16
|
+
INSTRUMENT_TYPE_NI_DIGITAL_PATTERN = "niDigitalPattern"
|
|
17
|
+
INSTRUMENT_TYPE_NI_SCOPE = "niScope"
|
|
18
|
+
INSTRUMENT_TYPE_NI_FGEN = "niFGen"
|
|
19
|
+
INSTRUMENT_TYPE_NI_DAQMX = "niDAQmx"
|
|
20
|
+
INSTRUMENT_TYPE_NI_RELAY_DRIVER = "niRelayDriver"
|
|
21
|
+
INSTRUMENT_TYPE_NI_MODEL_BASED_INSTRUMENT = "niModelBasedInstrument"
|
|
22
|
+
INSTRUMENT_TYPE_NI_SWITCH_EXECUTIVE_VIRTUAL_DEVICE = "niSwitchExecutiveVirtualDevice"
|
|
23
|
+
|
|
24
|
+
SITE_SYSTEM_PINS = -1
|
|
25
|
+
"""Site number used to identify and filter by system pins.
|
|
26
|
+
|
|
27
|
+
Pins that have a site number of ``SITE_SYSTEM_PINS`` are system pins and do not
|
|
28
|
+
belong to a specific site.
|
|
29
|
+
|
|
30
|
+
When querying connections, you can specify a site number of ``SITE_SYSTEM_PINS``
|
|
31
|
+
to restrict the query to return only system pins.
|
|
32
|
+
"""
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""Shared code for interfacing with driver APIs."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import contextlib
|
|
6
|
+
from typing import ContextManager, TypeVar
|
|
7
|
+
|
|
8
|
+
from ni.measurementlink.sessionmanagement.v1.client._types import (
|
|
9
|
+
SessionInitializationBehavior,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
TSession = TypeVar("TSession")
|
|
13
|
+
|
|
14
|
+
_EXISTING_BEHAVIORS = [
|
|
15
|
+
SessionInitializationBehavior.AUTO,
|
|
16
|
+
SessionInitializationBehavior.ATTACH_TO_SERVER_SESSION,
|
|
17
|
+
SessionInitializationBehavior.INITIALIZE_SERVER_SESSION,
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def closing_session_with_ts_code_module_support(
|
|
22
|
+
initialization_behavior: SessionInitializationBehavior,
|
|
23
|
+
session: TSession,
|
|
24
|
+
) -> ContextManager[TSession]:
|
|
25
|
+
"""Create a context manager that closes the session.
|
|
26
|
+
|
|
27
|
+
Emulates the behavior of INITIALIZE_SESSION_THEN_DETACH and ATTACH_TO_SESSION_THEN_CLOSE.
|
|
28
|
+
"""
|
|
29
|
+
if not hasattr(session, "close"):
|
|
30
|
+
raise TypeError("Session must have a close() method.")
|
|
31
|
+
|
|
32
|
+
if initialization_behavior in _EXISTING_BEHAVIORS:
|
|
33
|
+
return closing_session(session)
|
|
34
|
+
elif initialization_behavior == SessionInitializationBehavior.INITIALIZE_SESSION_THEN_DETACH:
|
|
35
|
+
return contextlib.nullcontext(session)
|
|
36
|
+
elif initialization_behavior == SessionInitializationBehavior.ATTACH_TO_SESSION_THEN_CLOSE:
|
|
37
|
+
return contextlib.closing(session) # pyright: ignore[reportArgumentType]
|
|
38
|
+
else:
|
|
39
|
+
raise ValueError(f"Invalid initialization behavior: '{initialization_behavior}'.")
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def closing_session(session: TSession) -> ContextManager[TSession]:
|
|
43
|
+
"""A context manager that yields the session and closes it."""
|
|
44
|
+
if not isinstance(session, contextlib.AbstractContextManager):
|
|
45
|
+
raise TypeError("Session must be a context manager.")
|
|
46
|
+
return session
|