Skip to content
Draft
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
6 changes: 2 additions & 4 deletions src/ni/datastore/data/_data_store_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@
from ni_grpc_extensions.channelpool import GrpcChannelPool

from ni.datastore.data._grpc_conversion import (
convert_measurement_timestamp_to_protobuf,
convert_read_condition_response_from_protobuf,
convert_read_measurement_response_from_protobuf,
get_publish_measurement_timestamp,
populate_publish_condition_batch_request_values,
populate_publish_condition_request_value,
populate_publish_measurement_batch_request_values,
Expand Down Expand Up @@ -275,11 +275,9 @@ def publish_measurement(
test_adapter_ids=test_adapter_ids,
software_item_ids=software_item_ids,
notes=notes,
timestamp=convert_measurement_timestamp_to_protobuf(timestamp),
)
populate_publish_measurement_request_value(publish_request, value)
publish_request.timestamp.CopyFrom(
get_publish_measurement_timestamp(publish_request, timestamp)
)
publish_response = self._get_data_store_client().publish_measurement(publish_request)
return publish_response.measurement_id

Expand Down
36 changes: 7 additions & 29 deletions src/ni/datastore/data/_grpc_conversion.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

from __future__ import annotations

import datetime as std_datetime
import logging
from itertools import chain
from typing import Any, Callable, cast, Iterable
Expand Down Expand Up @@ -364,32 +363,11 @@ def convert_read_condition_response_from_protobuf(response: ReadConditionValueRe
raise TypeError(f"Invalid read type: {read_data_type}")


def get_publish_measurement_timestamp(
publish_request: PublishMeasurementRequest, client_provided_timestamp: ht.datetime | None
) -> PrecisionTimestamp:
"""Determine the correct timestamp to use for publishing a measurement."""
no_client_timestamp_provided = client_provided_timestamp is None
if no_client_timestamp_provided:
publish_time = hightime_datetime_to_protobuf(ht.datetime.now(std_datetime.timezone.utc))
def convert_measurement_timestamp_to_protobuf(
client_provided_timestamp: ht.datetime | None,
) -> PrecisionTimestamp | None:
"""Convert the provided timestamp to PrecisionTimestamp if it's not None."""
if client_provided_timestamp is not None:
return hightime_datetime_to_protobuf(client_provided_timestamp)
else:
publish_time = hightime_datetime_to_protobuf(cast(ht.datetime, client_provided_timestamp))

waveform_t0: PrecisionTimestamp | None = None
value_case = publish_request.WhichOneof("value")
if value_case == "double_analog_waveform":
waveform_t0 = publish_request.double_analog_waveform.t0
elif value_case == "i16_analog_waveform":
waveform_t0 = publish_request.i16_analog_waveform.t0
elif value_case == "double_complex_waveform":
waveform_t0 = publish_request.double_complex_waveform.t0
elif value_case == "i16_complex_waveform":
waveform_t0 = publish_request.i16_complex_waveform.t0
elif value_case == "digital_waveform":
waveform_t0 = publish_request.digital_waveform.t0

# If an initialized waveform t0 value is present and no client timestamp was provided,
# use the waveform t0 as the measurement start time.
if waveform_t0 is not None and waveform_t0 != PrecisionTimestamp():
if no_client_timestamp_provided:
publish_time = waveform_t0
return publish_time
return None
11 changes: 6 additions & 5 deletions tests/unit/data/test_publish_measurement.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from ni.protobuf.types.precision_timestamp_conversion import (
hightime_datetime_to_protobuf,
)
from ni.protobuf.types.precision_timestamp_pb2 import PrecisionTimestamp
from ni.protobuf.types.vector_conversion import vector_to_protobuf
from ni.protobuf.types.vector_pb2 import Vector as VectorProto
from ni.protobuf.types.waveform_conversion import float64_analog_waveform_to_protobuf
Expand Down Expand Up @@ -65,7 +66,7 @@ def test___publish_boolean_data___calls_data_store_service_client(
assert request.step_id == "step_id"
assert request.name == "name"
assert request.notes == "notes"
assert request.timestamp == unittest.mock.ANY
assert request.timestamp == hightime_datetime_to_protobuf(timestamp)
assert request.scalar.bool_value == value
assert request.outcome == OutcomeProto.OUTCOME_PASSED
assert request.error_information == ErrorInformationProto()
Expand Down Expand Up @@ -184,7 +185,7 @@ def test___unsupported_list___publish_measurement___raises_type_error(
assert exc.value.args[0].startswith("Unsupported iterable:")


def test___publish_analog_waveform_data_without_timestamp_parameter___uses_waveform_t0(
def test___publish_analog_waveform_data_without_timestamp_parameter___timestamp_is_default(
data_store_client: DataStoreClient,
mocked_data_store_service_client: NonCallableMock,
) -> None:
Expand All @@ -203,7 +204,7 @@ def test___publish_analog_waveform_data_without_timestamp_parameter___uses_wavef
args, __ = mocked_data_store_service_client.publish_measurement.call_args
request = cast(PublishMeasurementRequest, args[0]) # The PublishMeasurementRequest object
assert measurement_id == "response_id"
assert request.timestamp == hightime_datetime_to_protobuf(timestamp)
assert request.timestamp == PrecisionTimestamp()


def test___publish_analog_waveform_data_without_t0___uses_timestamp_parameter(
Expand Down Expand Up @@ -251,7 +252,7 @@ def test___publish_analog_waveform_data_with_mismatched_timestamp_parameter___us
assert request.timestamp == hightime_datetime_to_protobuf(mismatched_timestamp)


def test___publish_analog_waveform_data_without_t0_or_timestamp___uses_now(
def test___publish_analog_waveform_data_without_t0_or_timestamp___timestamp_is_default(
data_store_client: DataStoreClient,
mocked_data_store_service_client: NonCallableMock,
) -> None:
Expand All @@ -267,7 +268,7 @@ def test___publish_analog_waveform_data_without_t0_or_timestamp___uses_now(

args, __ = mocked_data_store_service_client.publish_measurement.call_args
request = cast(PublishMeasurementRequest, args[0])
assert request.timestamp == hightime_datetime_to_protobuf(now)
assert request.timestamp == PrecisionTimestamp()


def test___none___publish_measurement___raises_type_error(
Expand Down
Loading