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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ All notable changes to this project will be documented in this file.

* ### Resolved Issues
* [843: read methods use task.in_stream.channels_to_read, which is slow](https://github.com/ni/nidaqmx-python/issues/843)
* [639: first_samp_timestamp_val property does not work because LibraryInterpreter is missing a method](https://github.com/ni/nidaqmx-python/issues/639)

* ### Major Changes
* (IN PROGRESS behind "WAVEFORM_SUPPORT" feature toggle) Added support for reading and writing Waveform data.
Expand Down
4 changes: 4 additions & 0 deletions generated/nidaqmx/_base_interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -1093,6 +1093,10 @@ def get_timing_attribute_int32(self, task, attribute):
def get_timing_attribute_string(self, task, attribute):
raise NotImplementedError

@abc.abstractmethod
def get_timing_attribute_timestamp(self, task, attribute):
raise NotImplementedError

@abc.abstractmethod
def get_timing_attribute_uint32(self, task, attribute):
raise NotImplementedError
Expand Down
6 changes: 6 additions & 0 deletions generated/nidaqmx/_grpc_interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -2181,6 +2181,12 @@ def get_timing_attribute_string(self, task, attribute):
grpc_types.GetTimingAttributeStringRequest(task=task, attribute_raw=attribute))
return response.value

def get_timing_attribute_timestamp(self, task, attribute):
response = self._invoke(
self._client.GetTimingAttributeTimestamp,
grpc_types.GetTimingAttributeTimestampRequest(task=task, attribute_raw=attribute))
return convert_timestamp_to_time(response.value)

def get_timing_attribute_uint32(self, task, attribute):
response = self._invoke(
self._client.GetTimingAttributeUInt32,
Expand Down
15 changes: 15 additions & 0 deletions generated/nidaqmx/_library_interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -3730,6 +3730,21 @@ def get_timing_attribute_string(self, task, attribute):
self.check_for_error(size_or_code)
return value.value.decode(lib_importer.encoding)

def get_timing_attribute_timestamp(self, task, attribute):
value = AbsoluteTime()

cfunc = lib_importer.cdll.DAQmxGetTimingAttribute
if cfunc.argtypes is None:
with cfunc.arglock:
if cfunc.argtypes is None:
cfunc.argtypes = [
lib_importer.task_handle, ctypes.c_int32]

error_code = cfunc(
task, attribute, ctypes.byref(value))
self.check_for_error(error_code)
return value.to_datetime()

def get_timing_attribute_uint32(self, task, attribute):
value = ctypes.c_uint32()

Expand Down
3 changes: 2 additions & 1 deletion src/codegen/utilities/interpreter_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
"SetRealTimeAttributeUInt32",
"WaitForNextSampleClock",
# Time triggers
# Single-attribute get/set functions are not used
# Generic Get/SetTimingAttribute{Type} functions are used instead
"GetArmStartTrigTimestampVal",
"GetArmStartTrigTrigWhen",
"GetFirstSampClkWhen",
Expand All @@ -53,7 +55,6 @@
"GetStartTrigTrigWhen",
"GetSyncPulseTimeWhen",
"GetTimingAttributeExTimestamp",
"GetTimingAttributeTimestamp",
"SetArmStartTrigTrigWhen",
"SetFirstSampClkWhen",
"SetStartTrigTrigWhen",
Expand Down
29 changes: 29 additions & 0 deletions tests/component/task/test_timing_properties.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from datetime import datetime as std_datetime

import pytest

from nidaqmx import DaqError
Expand Down Expand Up @@ -470,3 +472,30 @@ def test___timing___set_unint64_property_out_of_range_value___throws_daqerror(
with pytest.raises(DaqError) as e:
_ = task.timing.samp_quant_samp_per_chan
assert e.value.error_type == DAQmxErrors.INVALID_ATTRIBUTE_VALUE


def test___timing___get_timestamp_property___returns_value(task, sim_9205_device):
task.ai_channels.add_ai_voltage_chan(sim_9205_device.ai_physical_chans[0].name)
task.timing.cfg_samp_clk_timing(1000, samps_per_chan=100)

task.start()
timestamp = task.timing.first_samp_timestamp_val

assert isinstance(timestamp, std_datetime)

task.stop()


def test___timing___get_timestamp_property_with_device_context___throws_daqerror(
task, sim_9205_device
):
task.ai_channels.add_ai_voltage_chan(sim_9205_device.ai_physical_chans[0].name)
task.timing.cfg_samp_clk_timing(1000, samps_per_chan=100)
task.start()

with pytest.raises(DaqError) as e:
_ = task.timing[sim_9205_device].first_samp_timestamp_val

assert e.value.error_type == DAQmxErrors.M_STUDIO_OPERATION_DOES_NOT_SUPPORT_DEVICE_CONTEXT

task.stop()