Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/run_system_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
88 changes: 88 additions & 0 deletions docs/grpc_session_options.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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 <nidaqmx.task.Task>`,
:py:class:`nidaqmx.Scale <nidaqmx.scale.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() <nitlsconfig.grpc_channel.create_grpc_device_channel>`
Comment thread
alexdubois-ni marked this conversation as resolved.
from the `nitlsconfig <https://nitlsconfig-python.readthedocs.io/en/latest/>`_ package, which the
``grpc`` extra installs for you. It reads the nitlsconfig client configuration installed with the
Comment thread
alexdubois-ni marked this conversation as resolved.
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 <https://www.ni.com/docs/en-US/bundle/hardwaremanager/page/mtls-manage.html>`_ 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 <https://github.com/ni/grpc-device#bind-address-support>`_ and
`NI TLS Config Integration <https://github.com/ni/grpc-device#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() <nitlsconfig.grpc_channel.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 <https://www.ni.com/docs/en-US/bundle/hardwaremanager/page/mtls-manage.html>`_ 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 <https://github.com/ni/grpc-device#ni-tls-config-integration>`_ for details.

If you are writing a
`measurement plug-in <https://www.ni.com/docs/en-US/bundle/measurementplugins/page/measurement-plugins.html>`_,
you do not create the channel at all. The
`session management service <https://www.ni.com/docs/en-US/bundle/measurementplugins/page/session-manager-src.html>`_
tracks the lifetimes of NI-DAQmx tasks on the NI gRPC Device Server, and the
`session management client <https://nimeasurementlinksessionmanagementclient.readthedocs.io/en/latest/autoapi/ni/measurementlink/sessionmanagement/v1/client/index.html#ni.measurementlink.sessionmanagement.v1.client.BaseReservation.create_nidaqmx_task>`_
creates a :py:class:`nidaqmx.Task <nidaqmx.task.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 <https://github.com/ni/measurement-plugin-python/tree/main/examples/nidaqmx_analog_input>`_.

SessionInitializationBehavior
-----------------------------

.. py:class:: SessionInitializationBehavior
:canonical: nidaqmx.grpc_session_options.SessionInitializationBehavior

Expand Down Expand Up @@ -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

Expand Down
Loading