diff --git a/.github/workflows/run_system_tests.yml b/.github/workflows/run_system_tests.yml index d95442668..8c51622e0 100644 --- a/.github/workflows/run_system_tests.yml +++ b/.github/workflows/run_system_tests.yml @@ -27,7 +27,7 @@ jobs: with: persist-credentials: false - name: Import DAQmx config - run: C:\nidaqmxconfig\targets\win64U\x64\msvc-14.0\release\nidaqmxconfig.exe --eraseconfig --import tests\max_config\nidaqmxMaxConfig.ini + run: C:\nidaqmxconfig\targets\win64U\x64\msvc2022\release\nidaqmxconfig.exe --eraseconfig --import tests\max_config\nidaqmxMaxConfig.ini - name: Set up Python uses: ni/python-actions/setup-python@dee640bba235ae28fdc6b7337c643bd06358ae90 # v0.9.0 - name: Set up Poetry diff --git a/docs/conf.py b/docs/conf.py index d51244514..1c1b99460 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -47,6 +47,8 @@ intersphinx_mapping = { "grpc": ("https://grpc.github.io/grpc/python/", None), + # Read the Docs project slug differs from the module name. + "nitlsconfig": ("https://nitlsconfig-python.readthedocs.io/en/latest/", None), "nitypes": ("https://nitypes.readthedocs.io/en/latest/", None), "numpy": ("https://numpy.org/doc/stable/", None), "protobuf": ("https://googleapis.dev/python/protobuf/latest/", None), diff --git a/docs/grpc_session_options.rst b/docs/grpc_session_options.rst index e3fe1c435..01498dcea 100644 --- a/docs/grpc_session_options.rst +++ b/docs/grpc_session_options.rst @@ -7,6 +7,91 @@ Support for using NI-DAQmx over gRPC .. py:currentmodule:: nidaqmx +Creating a gRPC channel +----------------------- + +Using NI-DAQmx over gRPC requires the ``grpc`` extra:: + + $ python -m pip install nidaqmx[grpc] + +Every NI-DAQmx gRPC object is created from a :py:class:`grpc.Channel` that you build and pass to +:py:class:`nidaqmx.GrpcSessionOptions`. The constructors for :py:class:`nidaqmx.Task `, +:py:class:`nidaqmx.Scale `, and other classes accept a ``grpc_options`` parameter, and +:py:meth:`nidaqmx.system.System.remote` accepts one to access the remote DAQmx system. You own the +channel, not the objects created from it, so you must close the gRPC channel only after every +NI-DAQmx gRPC object using it is closed. + +The recommended way to create the channel depends on where NI gRPC Device Server runs. The sections +below cover a remote system and the local system. In either case you can instead build the channel +yourself, with :py:func:`grpc.insecure_channel` for an insecure channel or +:py:func:`grpc.secure_channel` when you need full control over how credentials are supplied. + +Remote systems +~~~~~~~~~~~~~~ + +For a remote system, the recommended way is +:py:func:`nitlsconfig.create_grpc_device_channel() ` +from the `nitlsconfig `_ package, which the +``grpc`` extra installs for you. It reads the nitlsconfig client configuration installed with the +NI-DAQmx runtime and by default will attempt to build an encrypted gRPC channel using mTLS. Before +it can reach a remote system, you must use NI Hardware Manager to perform a certificate exchange +with that system. See +`Managing mTLS `_ for +additional information. + +For example:: + + import nidaqmx + import nitlsconfig + + with nitlsconfig.create_grpc_device_channel('remote_grpc_device', 31763) as channel: + options = nidaqmx.GrpcSessionOptions(channel, '') + with nidaqmx.Task(grpc_options=options) as task: + ... # Calls to task over the encrypted channel + +.. note:: From NI Hardware Manager, you can disable TLS to make ``create_grpc_device_channel`` + produce an insecure channel. + +.. note:: ``create_grpc_device_channel`` also accepts an ``options`` parameter for gRPC channel + arguments such as ``grpc.ssl_target_name_override``, and a ``retry_policy`` parameter. Channel + arguments cannot be changed after the channel is built, so they must be supplied here. + +.. note:: NI gRPC Device Server must be configured to accept remote connections and to take its + TLS settings from nitlsconfig. See + `Bind Address Support `_ and + `NI TLS Config Integration `_ for details. + +The local system +~~~~~~~~~~~~~~~~ + +For a simple local system setup, build the channel yourself with :py:func:`grpc.insecure_channel`. + +For a more complex but secure local system setup, create the channel with +:py:func:`nitlsconfig.create_grpc_device_channel() ` +and use the Manage client certificates and Manage server certificates dialog boxes in NI Hardware +Manager to add the certificates for the local system connection. See +`Managing mTLS `_ for +additional information. + +.. note:: This requires NI gRPC Device Server to be configured to take its TLS settings from + nitlsconfig. If it is not configured this way, do not use ``create_grpc_device_channel`` for + the local system. See + `NI TLS Config Integration `_ for details. + +If you are writing a +`measurement plug-in `_, +you do not create the channel at all. The +`session management service `_ +tracks the lifetimes of NI-DAQmx tasks on the NI gRPC Device Server, and the +`session management client `_ +creates a :py:class:`nidaqmx.Task ` for you, so you do not create +:py:class:`nidaqmx.GrpcSessionOptions` yourself. For working measurements that use NI-DAQmx this +way, see the +`NI-DAQmx measurement plug-in example `_. + +SessionInitializationBehavior +----------------------------- + .. py:class:: SessionInitializationBehavior :canonical: nidaqmx.grpc_session_options.SessionInitializationBehavior @@ -34,6 +119,9 @@ Support for using NI-DAQmx over gRPC and leave it open. +GrpcSessionOptions +------------------ + .. py:class:: GrpcSessionOptions(self, grpc_channel, session_name, initialization_behavior=SessionInitializationBehavior.AUTO) :canonical: nidaqmx.grpc_session_options.GrpcSessionOptions