-
Notifications
You must be signed in to change notification settings - Fork 52
Sideband Streaming Example
This page contains an example of how to use sideband streaming with the DAQmx or FPGA APIs.
Follow the instructions on Setup a Client for Streaming for the initial setup required to proceed with sideband streaming.
For this example, we will use the BeginWriteArrayI16
and BeginReadArrayI16
APIs, which are part of the sideband streaming functionality.
These APIs utilize sideband streaming to transfer data between the client and the server. To see an example that uses gRPC streaming, refer to the Setup a Client for Streaming.
Below is the client code for initiating a sideband stream using these APIs:
auto session = std::make_unique<nidevice_grpc::Session>();
std::vector<pb::int16> write_data_int16 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
std::vector<pb::int16> read_data_int16 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
auto request_write = BeginWriteArrayI16Request{};
request_write.mutable_session()->CopyFrom(*session);
request_write.set_control(1);
auto response = BeginWriteArrayI16Response{};
stub->BeginWriteArrayI16(&context, request_write, &response);
auto request_read = BeginReadArrayI16Request{};
request_read.mutable_session()->CopyFrom(*session);
request_read.set_indicator(0);
request_read.set_size(read_data_int16 .size());
auto response_read = BeginReadArrayI16Response{};
stub->BeginReadArrayI16(&context, request_read, &response_read);
auto write_moniker_i16 = new ni::data_monikers::Moniker(response.moniker());
auto read_moniker_i16 = new ni::data_monikers::Moniker(response_read.moniker());
grpc::ClientContext moniker_context;
ni::data_monikers::BeginMonikerSidebandStreamRequest sideband_request;
ni::data_monikers::BeginMonikerSidebandStreamResponse sideband_response;
sideband_request.set_strategy(ni::data_monikers::SidebandStrategy::SOCKETS);
sideband_request.mutable_monikers()->mutable_read_monikers()->AddAllocated(read_moniker_i16);
sideband_request.mutable_monikers()->mutable_write_monikers()->AddAllocated(write_moniker_i16);
auto write_stream = moniker_stub().get()->BeginSidebandStream(&moniker_context, sideband_request, &sideband_response);
auto sideband_token = InitClientSidebandData(sideband_response);
for (int i = 0; i < 5; i++) {
nifpga_grpc::MonikerWriteArrayI16Request write_values_array_i16;
write_values_array_i16.mutable_array()->Add(write_data_int16.begin(), write_data_int16.end());
ni::data_monikers::SidebandWriteRequest write_data_request;
write_data_request.mutable_values()->add_values()->PackFrom(write_values_array_i16);
WriteSidebandMessage(sideband_token, write_data_request);
nifpga_grpc::MonikerReadArrayI16Response read_values_i16;
ni::data_monikers::SidebandReadResponse read_result;
ReadSidebandMessage(sideband_token, &read_result);
read_result.values().values(0).UnpackTo(&read_values_i16);
}
ni::data_monikers::SidebandWriteRequest cancel_request;
cancel_request.set_cancel(true);
WriteSidebandMessage(sideband_token, cancel_request);
CloseSidebandData(sideband_token);auto request_read = BeginReadArrayI16Request{};
We will now break down the client code into smaller parts, explaining each component:
a. Initialize the Session
This line creates a new instance of a Session object, which represents the connection to the NI device. It is required for any communication between the client and the device. This session will be passed to the requests for both write and read operations.
b. Sample Data
std::vector<pb::int16> write_data_int16 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
std::vector<pb::int16> read_data_int16 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
Here, vector of integers is initialized with sample read and write data.
c. Prepare Write Request
auto request_write = BeginWriteArrayI16Request{};
request_write.mutable_session()->CopyFrom(*session);
request_write.set_control(1);
-
auto request_write = BeginWriteArrayI16Request{};
: This creates an object ofBeginWriteArrayI16Request
which is defined in thegrpc.pb.h
file (generated from the.proto
file). -
BeginWriteArrayI16Request
defines the structure of the request for writing a 16-bit integer array. -
The session is copied from the previously created session object, and the control value is set to guide the write operation.
d. Call BeginWriteArrayI16 API
auto response = BeginWriteArrayI16Response{};
stub->BeginWriteArrayI16(&context, request_write, &response);
-
This sends the write request to the server using the
BeginWriteArrayI16
API, -
The response is stored in the response object. The stub represents the gRPC client connection to the server, which processes the request.
e. Prepare Read Request
auto request_read = BeginReadArrayI16Request{};
request_read.mutable_session()->CopyFrom(*session);
request_read.set_indicator(0);
request_read.set_size(read_data_int16.size());
Similarly, we will create an object of BeginReadArrayI16Request
.
The session
is copied, the indicator
is set (which could be used to determine which data to read), and the size of the data to be read is set to match the size of read_data_int16
.
f. Call BeginReadArrayI16
auto response_read = BeginReadArrayI16Response{};
stub->BeginReadArrayI16(&context, request_read, &response_read);
Just like BeginWriteArrayI16
API, we will call BeginReadArrayI16
and store the response. This will initiate the reading of data from the device based on the session and size parameters.
g. Create Monikers for Write and Read
auto write_moniker_i16 = new ni::data_monikers::Moniker(response.moniker());
auto read_moniker_i16 = new ni::data_monikers::Moniker(response_read.moniker());
Here, we create two Moniker
objects: one for the write data and one for the read data. These monikers are created from the responses received from the write and read operations.
h. Prepare Sideband Stream Request
grpc::ClientContext moniker_context;
ni::data_monikers::BeginMonikerSidebandStreamRequest sideband_request;
ni::data_monikers::BeginMonikerSidebandStreamResponse sideband_response;
sideband_request.set_strategy(ni::data_monikers::SidebandStrategy::SOCKETS);
sideband_request.mutable_monikers()->mutable_read_monikers()->AddAllocated(read_moniker_i16);
sideband_request.mutable_monikers()->mutable_write_monikers()->AddAllocated(write_moniker_i16);
-
A
BeginMonikerSidebandStreamRequest
is created to initiate a sideband stream. This request includes the monikers for both the read and write data, which were created earlier. The strategy is set toSOCKETS
, indicating the use of sockets for the sideband stream. -
The
mutable_monikers()
method accesses the Monikers field of the request. -
The
mutable_read_monikers()
andmutable_write_monikers()
methods add the previously created monikers for the read and write streams, respectively. These monikers uniquely identify the data streams to be associated with the sideband connection. -
The
AddAllocated()
method transfers ownership of theread_moniker_i16
andwrite_moniker_i16
to the request, ensuring they are properly managed during the request's lifecycle.
i. Start the Sideband Stream
auto write_stream = moniker_stub().get()->BeginSidebandStream(&moniker_context, sideband_request, &sideband_response);
auto sideband_token = InitClientSidebandData(sideband_response);
The sideband stream is initiated by calling BeginSidebandStream
. The response contains information about the stream, and a sideband token is generated using InitClientSidebandData
, which will be used to manage the data during streaming.
j. Streaming in a Loop
for (int i = 0; i < 5; i++) {
nifpga_grpc::MonikerWriteArrayI16Request write_values_array_i16;
write_values_array_i16.mutable_array()->Add(write_data_int16.begin(),
write_data_int16.end());
ni::data_monikers::SidebandWriteRequest write_data_request;
write_data_request.mutable_values()->add_values()->PackFrom(write_values_array_i16);
WriteSidebandMessage(sideband_token, write_data_request);
nifpga_grpc::MonikerReadArrayI16Response read_values_i16;
ni::data_monikers::SidebandReadResponse read_result;
ReadSidebandMessage(sideband_token, &read_result);
read_result.values().values(0).UnpackTo(&read_values_i16);
}
-
Prepare the data to be written
- A
MonikerWriteArrayI16Request
object is created to hold the write data for the current iteration. - The
mutable_array()
method provides access to the data array, and theAdd()
function appends the contents ofwrite_data_int16
(a pre-defined vector) to this array. This prepares the data to be streamed to the server.
- A
-
Pack the write data into a sideband write request
- A
SidebandWriteRequest
object is created to encapsulate the write data for the sideband stream. - The
mutable_values()
method provides access to thevalues
field, which is used to store the packed data. *PackFrom()
serializes thewrite_values_array_i16
data into a format that the server can understand and process.
- A
-
Send the packed write data to the sideband stream
- The
WriteSidebandMessage()
function sends thewrite_data_request
to the server using the sideband stream identified bysideband_token
.
- The
-
Prepare a container for the read response
-
read_values_i16
: This will store the unpacked read data in a format that the client can process. -
read_result
: This will store the raw response data from the server's sideband stream.
-
-
Read the response data from the sideband stream
- The
ReadSidebandMessage()
function fetches data from the sideband stream, using thesideband_token
to identify the stream. - The server sends the data it has read, which is stored in
read_result
in its raw packed form.
- The
-
Unpack the read response
- The
values()
method ofread_result
accesses the packed data from the sideband stream. - The
UnpackTo()
method deserializes the packed data fromread_result
and stores it inread_values_i16
. - At this point, the client has successfully read and unpacked the data sent by the server.
- The
Creating and Setting Up a gRPC Server
Session Utilities API Reference
gRPC API Differences From C API
Sharing Driver Sessions Between Clients
C API Docs
NI-DAQmx
- gRPC API Differences From C API
- Task Configuration And Control
- Channel Configuration And Creation
- Timing
- Triggering
- Read Functions
- Write Functions
- Export Hardware Signals
- Scale Configuration
- Internal Buffer Configuration
- Advanced Functions
- System Configuration
- Error Handling
- Buffer Attributes
- Calibration Info Attributes
- Channel Attributes
- Device Attributes
- Export Signal Attributes
- Persisted Channel Attributes
- Persisted Scale Attributes
- Persisted Task Attributes
- Physical Channel Attributes
- Read Attributes
- Scale Attributes
- System Attributes
- Task Attributes
- Timing Attributes
- Trigger Attributes
- Watchdog Attributes
- Write Attributes
NI-DCPOWER
- Setup Functions
- Configure Functions
- Measurement Functions
- Control Functions
- Trigger And Event
- Attribute Functions
- Query Functions
- Calibration Functions
- Utility Functions
- Supported Device
- Source Attributes
- Transient Attributes
- Voltage Attributes
- Current Attributes
- Pulse Voltage Attributes
- Pulse Current Attributes
- Cutoff Attributes
- Measurement Attributes
- Trigger Attributes Functions
- Event Attributes
- Advanced Attributes
- Inherent Ivi Attributes
- Supported Device Attributes
NI-DIGITAL PATTERN DRIVER
- Init And Close Functions
- Session Locking Functions
- Utility Functions
- Error Handling Functions
- Calibration Functions
- Attributes Functions
- Pin Map Functions
- Low Level Functions
- Low Level Action Functions
- Pin Control Functions
- Static IO Functions
- Clock Generator Functions
- Levels And Timing Functions
- TDR Functions
- PPMU Configuration Functions
- DC Voltage Functions
- DC Current Functions
- PPMU Action Functions
- Pattern Configuration Functions
- Pattern Action Functions
- History Ram Functions
- Source Memory Functions
- Capture Memory Functions
- Triggers And Events Functions
- Conditional Jump Trigger Functions
- Sequencer Flag Functions
- Sequencer Register Functions
- Match Fail Combination Functions
- Pattern Results Functions
- Sort Results Functions
- Frequency Measurement Functions
- IVI Inherent Attributes
- Specific Driver Information Attributes, Read Only
- Driver Setup Information Attributes
- Device Attributes
- Pin Control Attributes
- Level Configuration Attributes
- Trigger Configuration Attributes
- PPMU Attributes
- Patterns Attributes
- Pattern Opcode Event Attributes
- Timing Offset Attributes
- Keep Alive Attributes
- Frequency Measurement Attributes
- Clock Generator Attributes
- History RAM
- Synchronization Attributes
- TDR Endpoint Termination Attributes
NI-FGEN
- Setup Functions
- Configuration Functions
- Standard Output Functions
- Arbitrary Waveform Output Functions
- Arbitrary Sequence Output Functions
- Incremental Waveform Write Functions
- Configure Clock Functions
- Trigger And Syncronizations Functions
- 5404 Routing Functions
- Script Output Functions
- Configure Onboard Signal Processing Functions
- Configure Peer To Peer Functions
- Attribute Functions
- Waveform Control Functions
- Error Functions
- Output Attributes
- Arbitrary Waveform Attributes
- Data Transfer Attributes
- Onboard Signal Processing Attributes
- Peer To Peer Attributes
- Standard Function Attributes
- Clock Attributes
- Event Attributes
- Triggering Attributes
- Instrument Specific Attributes
- Inherent IVI Attributes
- 5401 5411 5431
NI-RFmx Bluetooth
- gRPC API Differences From C API
- General Functions
- Configuration Functions
- Set And Get Attribute Functions
- Fetch Results Functions
- Utility Functions
- Build String Functions
- Advanced Functions
- General Attributes
- Trigger Attributes
- Packet Attributes
- Auto Detect Signal Attributes
- Modacc Attributes
- ACP Attributes
- Twenty dB Attributes
- Frequency Range Attributes
- TXP Attributes
- Advanced Attributes
NI-RFmx NR
- gRPC API Differences From C API
- General Functions
- Configuration Functions
- Set And Get Attributes Functions
- Fetch Results Functions
- Utility Functions
- Build String Functions
- Advanced Functions
- General Attributes
- Trigger Attributes
- Signal Detection Attributes
- Component Carrier Attributes
- List Attributes
- Modacc Attributes
- ACP Attributes
- CHP Attributes
- OBW Attributes
- SEM Attributes
- TXP Attributes
- Pvt Attributes
- Advanced Attributes
NI-RFmx LTE
- gRPC API Differences From C API
- General Functions
- Configuration Functions
- Ch Configuration Functions
- NB IoT Configuration Functions
- ModAcc Configuration Functions
- ACP Configuration Functions
- CHP Configuration Functions
- OBW Configuration Functions
- SEM Configuration Functions
- PVT Configuration Functions
- SlotPhase Configuration Functions
- SlotPower Configuration Functions
- Set And Get Attribute Functions
- ModAcc Fetch Functions
- ACP Fetch Functions
- CHP Fetch Functions
- OBW Fetch Functions
- SEM Fetch Functions
- PVT Fetch Functions
- SlotPhase Fetch Functions
- SlotPower Fetch Functions
- Utility Functions
- Build String Functions
- Advanced Functions
- General Attributes
- Trigger Attributes
- Component Carrier Attributes
- ModAcc Attributes
- ACP Attributes
- CHP Attributes
- OBW Attributes
- SEM Attributes
- PVT Attributes
- SlotPhase Attributes
- SlotPower Attributes
- Advanced Attributes
NI-RFmx SpecAn
- gRPC API Differences From C API
- General Functions
- Configuration Functions
- Set And Get Attribute Functions
- Read Functions
- Fetch Functions
- Utility Functions
- Marker Functions
- Build String Functions
- Advanced Functions
- General Attributes
- Trigger Attributes
- ACP Attributes
- Cdf Attributes
- CHP Attributes
- Fcnt Attributes
- Harm Attributes
- OBW Attributes
- SEM Attributes
- Spectrum Attributes
- Spur Attributes
- TXP Attributes
- AMPM Attributes
- Dpd Attributes
- IQ Attributes
- IM Attributes
- NF Attributes
- Phasenoise Attributes
- PAVT Attributes
- Advanced Attributes
NI-RFmx WLAN
- gRPC API Differences From C API
- General Functions
- Configuration Functions
- Set And Get Attribute Functions
- Fetch DSSS ModAcc Functions
- Fetch OFDM ModAcc Functions
- Fetch SEM Functions
- Fetch TXP Functions
- Fetch PowerRamp Functions
- Utility Functions
- Build String Functions
- Advanced Functions
- General Attributes
- Trigger Attributes
- OFDM Attributes
- Auto Detect Signal Attributes
- DSSS ModAcc Attributes
- OFDM ModAcc Attributes
- SEM Attributes
- TXP Attributes
- PowerRamp Attributes
- Advanced Attributes
NI-RFSA
- General Functions
- Configuration Functions
- Acquisition Functions
- Utility Functions
- Calibration Functions
- General Attributes
- Vertical Attributes
- Signal Path Attributes
- Acquisition Attributes
- Acquisition Attributes
- Triggers Attributes
- Events Attributes
- Device Characteristics Attributes
- Peer To Peer Streaming Attributes
- Configuration List Attributes
- Inherent IVI Properties Attributes
- De-embedding Attributes
- Self Calibration Attributes
- Factory Calibration Attributes
- External Alignment Attributes
- Device Specific Attributes
NI-RFSG
- General Functions
- Generation Configuration
- Utility Functions
- Calibration Functions
- Arb Attributes
- Clock Attributes
- Configuration List Attributes
- De-embedding Attributes
- Device Characteristics Attributes
- Device Specific Attributes
- Events Attributes
- External Calibration Attributes
- Inherent IVI Attributes Attributes
- IQ Impairment Attributes
- Load Configurations Attributes
- Modulation Attributes
- Obsolete Attributes
- Peer To Peer Attributes
- RF Attributes
- Self Calibration Attributes
- Triggers Attributes
NI-SCOPE
- Setup Functions
- Configure Functions
- Attribute Functions
- Acquisition Functions
- Measurement Functions
- Calibrate Functions
- Utility Funcitons
- Error Handling Functions
- IVI Compliance Or Obsolete Functions
- Vertical Attributes
- Horizontal Attributes
- Trigger Attributes
- Clocking Attributes
- Synchronization Attributes
- Acquisition Attributes
- Waveform Measurements Attributes
- Onboard Signal Processing Attributes
- Peer To Peer Streaming Attributes
- Device Attributes
- IVI Or Obsolete Attributes
- Instrument Capabilities Attributes
- If Digitizer Attributes
NI-XNET
- gRPC API differences from C APIs
- General Functions
- Cluster Properties
- Database Properties
- Device Properties
- ECU Properties
- Frame Properties
- Interface Properties
- LIN Schedule Entry Properties
- LIN Schedule Properties
- PDU Properties
- Session Ethernet Properties
- Session Frame Properties
- Session Interface Properties
- Session Properties
- Session SAE J1939 Properties
- Signal Properties
- Subframe Properties
- System Properties
- IP-Stack Functions
- Socket Options
- Socket Functions