diff --git a/cmake/prefix_defs.txt b/cmake/prefix_defs.txt index 1908e738..e541d08a 100644 --- a/cmake/prefix_defs.txt +++ b/cmake/prefix_defs.txt @@ -24,3 +24,16 @@ QDMI_Site QDMI_Site_impl_d QDMI_Operation QDMI_Operation_impl_d +QDMI_TelemetrySensor +QDMI_TelemetrySensor_impl_d +QDMI_Device_TelemetrySensor_Query +QDMI_Device_TelemetrySensor_Query_impl_d +QDMI_device_session_query_telemetrysensor_property +QDMI_device_session_create_device_telemetrysensor_query +QDMI_device_telemetrysensor_query_set_parameter +QDMI_device_telemetrysensor_query_submit +QDMI_device_telemetrysensor_query_get_results +QDMI_device_telemetrysensor_query_check_status +QDMI_device_telemetrysensor_query_wait +QDMI_device_telemetrysensor_query_cancel +QDMI_device_telemetrysensor_query_free diff --git a/examples/device/device.cpp b/examples/device/device.cpp index 4f451723..6ede7781 100644 --- a/examples/device/device.cpp +++ b/examples/device/device.cpp @@ -28,12 +28,16 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include #include #include +#include #include +#include #include +#include #include #include #include #include +#include #include #include #include @@ -77,6 +81,23 @@ struct CXX_QDMI_Operation_impl_d { std::string name; }; +struct CXX_QDMI_TelemetrySensor_impl_d { + std::string id; + std::string unit; + time_t sampling_rate; +}; + +struct CXX_QDMI_Device_TelemetrySensor_Query_impl_d { + std::unique_ptr start_time = nullptr; + std::unique_ptr end_time = nullptr; + size_t timeout = 0; + CXX_QDMI_TelemetrySensor telemetry_sensor = nullptr; + std::vector result_timestamps; + std::vector result_values; + QDMI_TelemetrySensor_Query_Status status = + QDMI_TELEMETRYSENSOR_QUERY_STATUS_CREATED; +}; + namespace { /** * @brief Static function to maintain the device state. @@ -159,6 +180,11 @@ constexpr CXX_QDMI_Site_impl_d SITE4{4}; constexpr std::array CXX_DEVICE_SITES = { &SITE0, &SITE1, &SITE2, &SITE3, &SITE4}; +const CXX_QDMI_TelemetrySensor_impl_d ENVSEN{"t4k", "K", 60}; + +constexpr std::array + CXX_DEVICE_TELEMETRYSENSORS{&ENVSEN}; + constexpr std::array // clang-format off DEVICE_COUPLING_MAP = { @@ -773,6 +799,9 @@ int CXX_QDMI_device_session_query_device_property( ADD_SINGLE_VALUE_PROPERTY(QDMI_DEVICE_PROPERTY_NEEDSCALIBRATION, size_t, 0, prop, size, value, size_ret) + ADD_LIST_PROPERTY(QDMI_DEVICE_PROPERTY_TELEMETRYSENSORS, + CXX_QDMI_TelemetrySensor, CXX_DEVICE_TELEMETRYSENSORS, prop, + size, value, size_ret) ADD_SINGLE_VALUE_PROPERTY( QDMI_DEVICE_PROPERTY_PULSESUPPORT, QDMI_Device_Pulse_Support_Level, QDMI_DEVICE_PULSE_SUPPORT_LEVEL_NONE, prop, size, value, size_ret) @@ -889,3 +918,226 @@ int CXX_QDMI_device_session_query_operation_property( } return QDMI_ERROR_NOTSUPPORTED; } /// [DOXYGEN FUNCTION END] + +int CXX_QDMI_device_session_query_telemetrysensor_property( + CXX_QDMI_Device_Session session, CXX_QDMI_TelemetrySensor telemetry_sensor, + const QDMI_TelemetrySensor_Property prop, const size_t size, void *value, + size_t *size_ret) { + if (session == nullptr || telemetry_sensor == nullptr || + (value != nullptr && size == 0) || + (prop >= QDMI_TELEMETRYSENSOR_PROPERTY_MAX && + prop != QDMI_TELEMETRYSENSOR_PROPERTY_CUSTOM1 && + prop != QDMI_TELEMETRYSENSOR_PROPERTY_CUSTOM2 && + prop != QDMI_TELEMETRYSENSOR_PROPERTY_CUSTOM3 && + prop != QDMI_TELEMETRYSENSOR_PROPERTY_CUSTOM4 && + prop != QDMI_TELEMETRYSENSOR_PROPERTY_CUSTOM5)) { + return QDMI_ERROR_INVALIDARGUMENT; + } + ADD_STRING_PROPERTY(QDMI_TELEMETRYSENSOR_PROPERTY_ID, + telemetry_sensor->id.c_str(), prop, size, value, size_ret) + ADD_STRING_PROPERTY(QDMI_TELEMETRYSENSOR_PROPERTY_UNIT, + telemetry_sensor->unit.c_str(), prop, size, value, + size_ret) + ADD_SINGLE_VALUE_PROPERTY(QDMI_TELEMETRYSENSOR_PROPERTY_SAMPLINGRATE, time_t, + telemetry_sensor->sampling_rate, prop, size, value, + size_ret) + return QDMI_ERROR_NOTSUPPORTED; +} + +int CXX_QDMI_device_session_create_device_telemetrysensor_query( + CXX_QDMI_Device_Session session, + CXX_QDMI_Device_TelemetrySensor_Query *query) { + + if (session == nullptr || query == nullptr) { + return QDMI_ERROR_INVALIDARGUMENT; + } + if (session->status != CXX_QDMI_DEVICE_SESSION_STATUS::INITIALIZED) { + return QDMI_ERROR_BADSTATE; + } + *query = new CXX_QDMI_Device_TelemetrySensor_Query_impl_d(); + (*query)->start_time = nullptr; + (*query)->end_time = nullptr; + (*query)->telemetry_sensor = nullptr; + (*query)->status = QDMI_TELEMETRYSENSOR_QUERY_STATUS_CREATED; + + return QDMI_SUCCESS; +} + +int CXX_QDMI_device_telemetrysensor_query_set_parameter( + CXX_QDMI_Device_TelemetrySensor_Query query, + const QDMI_Device_TelemetrySensor_Query_Parameter param, const size_t size, + const void *value) { + + if (query == nullptr || (value != nullptr && size == 0) || + (param >= QDMI_DEVICE_TELEMETRYSENSOR_QUERY_PARAMETER_MAX && + param != QDMI_DEVICE_TELEMETRYSENSOR_QUERY_PARAMETER_CUSTOM1 && + param != QDMI_DEVICE_TELEMETRYSENSOR_QUERY_PARAMETER_CUSTOM2 && + param != QDMI_DEVICE_TELEMETRYSENSOR_QUERY_PARAMETER_CUSTOM3 && + param != QDMI_DEVICE_TELEMETRYSENSOR_QUERY_PARAMETER_CUSTOM4 && + param != QDMI_DEVICE_TELEMETRYSENSOR_QUERY_PARAMETER_CUSTOM5) || + value == nullptr) { + return QDMI_ERROR_INVALIDARGUMENT; + } + switch (param) { + case QDMI_DEVICE_TELEMETRYSENSOR_QUERY_PARAMETER_STARTTIME: { + if (size < sizeof(time_t)) { + return QDMI_ERROR_INVALIDARGUMENT; + } + query->start_time = + std::make_unique(*static_cast(value)); + return QDMI_SUCCESS; + } + case QDMI_DEVICE_TELEMETRYSENSOR_QUERY_PARAMETER_ENDTIME: { + if (size < sizeof(time_t)) { + return QDMI_ERROR_INVALIDARGUMENT; + } + query->end_time = + std::make_unique(*static_cast(value)); + return QDMI_SUCCESS; + } + case QDMI_DEVICE_TELEMETRYSENSOR_QUERY_PARAMETER_TELEMETRYSENSOR: { + if (size < sizeof(CXX_QDMI_TelemetrySensor)) { + return QDMI_ERROR_INVALIDARGUMENT; + } + query->telemetry_sensor = + *static_cast(value); + return QDMI_SUCCESS; + } + default: + return QDMI_ERROR_NOTSUPPORTED; + } +} + +int CXX_QDMI_device_telemetrysensor_query_submit( + CXX_QDMI_Device_TelemetrySensor_Query query) { + + if (query == nullptr || query->telemetry_sensor == nullptr || + query->start_time == nullptr || query->end_time == nullptr) { + return QDMI_ERROR_INVALIDARGUMENT; + } + + // here, the actual submission. + + // for demonstration purposes + query->status = QDMI_TELEMETRYSENSOR_QUERY_STATUS_RUNNING; + + time_t time_difference = *query->end_time - *query->start_time; + + const auto sampling_rate = query->telemetry_sensor->sampling_rate; + + const auto result_length = + static_cast(time_difference / sampling_rate); + query->result_timestamps.clear(); + query->result_timestamps.reserve(result_length); + + query->result_values.clear(); + query->result_values.reserve(result_length); + + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_real_distribution<> dis(0.0, RAND_MAX); + for (unsigned int i = 0; i < result_length; i++) { + + time_t next_time = *query->start_time + sampling_rate * i; + query->result_timestamps.emplace_back(next_time); + + query->result_values.emplace_back(dis(gen)); + } + + return QDMI_SUCCESS; +} + +int CXX_QDMI_device_telemetrysensor_query_get_results( + CXX_QDMI_Device_TelemetrySensor_Query query, + const QDMI_TelemetrySensor_Query_Result result, const size_t size, + void *data, size_t *size_ret) { + + if (query == nullptr || (data != nullptr && size == 0) || + (result >= QDMI_TELEMETRYSENSOR_QUERY_RESULT_MAX && + result != QDMI_TELEMETRYSENSOR_QUERY_RESULT_CUSTOM1 && + result != QDMI_TELEMETRYSENSOR_QUERY_RESULT_CUSTOM2 && + result != QDMI_TELEMETRYSENSOR_QUERY_RESULT_CUSTOM3 && + result != QDMI_TELEMETRYSENSOR_QUERY_RESULT_CUSTOM4 && + result != QDMI_TELEMETRYSENSOR_QUERY_RESULT_CUSTOM5)) { + return QDMI_ERROR_INVALIDARGUMENT; + } + size_t required_size = query->result_values.size(); + switch (result) { + case QDMI_TELEMETRYSENSOR_QUERY_RESULT_TIMESTAMPS: + required_size *= sizeof(time_t); + if (data != nullptr) { + if (size < required_size) { + return QDMI_ERROR_INVALIDARGUMENT; + } + memcpy(data, query->result_timestamps.data(), required_size); + } + + if ((size_ret) != nullptr) { + *(size_ret) = required_size; + } + return QDMI_SUCCESS; + case QDMI_TELEMETRYSENSOR_QUERY_RESULT_VALUES: + + required_size *= sizeof(double); + if (data != nullptr) { + if (size < required_size) { + return QDMI_ERROR_INVALIDARGUMENT; + } + memcpy(data, query->result_values.data(), required_size); + } + if ((size_ret) != nullptr) { + *(size_ret) = required_size; + } + return QDMI_SUCCESS; + + default: + return QDMI_ERROR_NOTSUPPORTED; + } +} + +int CXX_QDMI_device_telemetrysensor_query_check_status( + CXX_QDMI_Device_TelemetrySensor_Query query, + QDMI_TelemetrySensor_Query_Status *status) { + if (query == nullptr || status == nullptr) { + return QDMI_ERROR_INVALIDARGUMENT; + } + + // randomly decide whether job is done or not + if (query->status == QDMI_TELEMETRYSENSOR_QUERY_STATUS_RUNNING && + CXX_QDMI_generate_bit()) { + query->status = QDMI_TELEMETRYSENSOR_QUERY_STATUS_DONE; + } + + *status = query->status; + return QDMI_SUCCESS; +} + +int CXX_QDMI_device_telemetrysensor_query_wait( + CXX_QDMI_Device_TelemetrySensor_Query query, const size_t timeout) { + + if (query == nullptr) { + return QDMI_ERROR_INVALIDARGUMENT; + } + + query->status = QDMI_TELEMETRYSENSOR_QUERY_STATUS_DONE; + query->timeout = timeout; + return QDMI_SUCCESS; +} + +int CXX_QDMI_device_telemetrysensor_query_cancel( + CXX_QDMI_Device_TelemetrySensor_Query query) { + + if (query == nullptr || + query->status == QDMI_TELEMETRYSENSOR_QUERY_STATUS_DONE) { + return QDMI_ERROR_INVALIDARGUMENT; + } + + query->status = QDMI_TELEMETRYSENSOR_QUERY_STATUS_CANCELED; + + return QDMI_SUCCESS; +} + +void CXX_QDMI_device_telemetrysensor_query_free( + CXX_QDMI_Device_TelemetrySensor_Query query) { + delete query; +} diff --git a/examples/driver/qdmi_example_driver.cpp b/examples/driver/qdmi_example_driver.cpp index 5303c032..45a4dd26 100644 --- a/examples/driver/qdmi_example_driver.cpp +++ b/examples/driver/qdmi_example_driver.cpp @@ -102,6 +102,35 @@ struct QDMI_Library { /// Function pointer to @ref QDMI_device_session_query_operation_property. decltype(QDMI_device_session_query_operation_property) *device_session_query_operation_property{}; + /// Function pointer to @ref + /// QDMI_device_session_query_telemetrysensor_property. + decltype(QDMI_device_session_query_telemetrysensor_property) + *device_session_query_telemetrysensor_property{}; + /// Function pointer to @ref QDMI_device_telemetrysensor_query_set_parameter. + decltype(QDMI_device_telemetrysensor_query_set_parameter) + *device_telemetrysensor_query_set_parameter{}; + /// Function pointer to @ref + /// QDMI_device_session_create_device_telemetrysensor_query. + decltype(QDMI_device_session_create_device_telemetrysensor_query) + *device_session_create_device_telemetrysensor_query{}; + /// Function pointer to @ref QDMI_device_telemetrysensor_query_submit. + decltype(QDMI_device_telemetrysensor_query_submit) + *device_telemetrysensor_query_submit{}; + /// Function pointer to @ref QDMI_device_telemetrysensor_query_get_results. + decltype(QDMI_device_telemetrysensor_query_get_results) + *device_telemetrysensor_query_get_results{}; + /// Function pointer to @ref QDMI_device_telemetrysensor_query_check_status. + decltype(QDMI_device_telemetrysensor_query_check_status) + *device_telemetrysensor_query_check_status{}; + /// Function pointer to @ref QDMI_device_telemetrysensor_query_wait. + decltype(QDMI_device_telemetrysensor_query_wait) + *device_telemetrysensor_query_wait{}; + /// Function pointer to @ref QDMI_device_telemetrysensor_query_cancel. + decltype(QDMI_device_telemetrysensor_query_cancel) + *device_telemetrysensor_query_cancel{}; + /// Function pointer to @ref QDMI_device_telemetrysensor_query_free. + decltype(QDMI_device_telemetrysensor_query_free) + *device_telemetrysensor_query_free{}; // default constructor QDMI_Library() = default; @@ -158,6 +187,11 @@ struct QDMI_Driver_State { std::unordered_set sessions; }; +struct QDMI_TelemetrySensor_Query_impl_d { + QDMI_Device device = nullptr; + QDMI_Device_TelemetrySensor_Query env_query = nullptr; +}; + namespace { /** * @brief Returns a pointer to the global driver state. @@ -219,6 +253,17 @@ void QDMI_library_load(const std::string &lib_name, const std::string &prefix) { LOAD_SYMBOL(library, prefix, device_session_query_device_property) LOAD_SYMBOL(library, prefix, device_session_query_site_property) LOAD_SYMBOL(library, prefix, device_session_query_operation_property) + LOAD_SYMBOL(library, prefix, device_session_query_telemetrysensor_property) + // device telemetry sensor interface + LOAD_SYMBOL(library, prefix, + device_session_create_device_telemetrysensor_query) + LOAD_SYMBOL(library, prefix, device_telemetrysensor_query_set_parameter) + LOAD_SYMBOL(library, prefix, device_telemetrysensor_query_submit) + LOAD_SYMBOL(library, prefix, device_telemetrysensor_query_get_results) + LOAD_SYMBOL(library, prefix, device_telemetrysensor_query_check_status) + LOAD_SYMBOL(library, prefix, device_telemetrysensor_query_wait) + LOAD_SYMBOL(library, prefix, device_telemetrysensor_query_cancel) + LOAD_SYMBOL(library, prefix, device_telemetrysensor_query_free) // NOLINTEND(cppcoreguidelines-pro-type-reinterpret-cast) } catch (const std::exception &) { @@ -531,3 +576,106 @@ int QDMI_device_query_operation_property( device->device_session, operation, num_sites, sites, num_params, params, prop, size, value, size_ret); } + +int QDMI_device_query_telemetrysensor_property( + QDMI_Device device, QDMI_TelemetrySensor telemetry_sensor, + const QDMI_TelemetrySensor_Property prop, const size_t size, void *value, + size_t *size_ret) { + if (device == nullptr) { + return QDMI_ERROR_INVALIDARGUMENT; + } + return device->library->device_session_query_telemetrysensor_property( + device->device_session, telemetry_sensor, prop, size, value, size_ret); +} + +int QDMI_device_create_telemetrysensor_query( + QDMI_Device dev, QDMI_TelemetrySensor *telemetry_sensor, + QDMI_TelemetrySensor_Query *query) { + if (dev == nullptr || query == nullptr || telemetry_sensor == nullptr) { + return QDMI_ERROR_INVALIDARGUMENT; + } + + if ((dev->session->mode & QDMI_SESSION_MODE_READWRITE) == 0) { + return QDMI_ERROR_PERMISSIONDENIED; + } + + *query = new QDMI_TelemetrySensor_Query_impl_d(); + (*query)->device = dev; + int err = dev->library->device_session_create_device_telemetrysensor_query( + dev->device_session, &(*query)->env_query); + if (err != QDMI_SUCCESS) { + return err; + } + + return QDMI_telemetrysensor_query_set_parameter( + *query, QDMI_TELEMETRYSENSOR_QUERY_PARAMETER_TELEMETRY, + sizeof(QDMI_TelemetrySensor), static_cast(telemetry_sensor)); +} + +int QDMI_telemetrysensor_query_set_parameter( + QDMI_TelemetrySensor_Query query, + const QDMI_TelemetrySensor_Query_Parameter param, const size_t size, + const void *value) { + if (query == nullptr) { + return QDMI_ERROR_INVALIDARGUMENT; + } + return query->device->library->device_telemetrysensor_query_set_parameter( + query->env_query, + static_cast(param), size, + value); +} + +int QDMI_telemetrysensor_query_submit(QDMI_TelemetrySensor_Query query) { + if (query == nullptr) { + return QDMI_ERROR_INVALIDARGUMENT; + } + return query->device->library->device_telemetrysensor_query_submit( + query->env_query); +} + +int QDMI_telemetrysensor_query_get_results( + QDMI_TelemetrySensor_Query query, + const QDMI_TelemetrySensor_Query_Result result, const size_t size, + void *data, size_t *size_ret) { + if (query == nullptr) { + return QDMI_ERROR_INVALIDARGUMENT; + } + return query->device->library->device_telemetrysensor_query_get_results( + query->env_query, result, size, data, size_ret); +} + +int QDMI_telemetrysensor_query_check_status( + QDMI_TelemetrySensor_Query query, + QDMI_TelemetrySensor_Query_Status *status) { + + if (query == nullptr) { + return QDMI_ERROR_INVALIDARGUMENT; + } + return query->device->library->device_telemetrysensor_query_check_status( + query->env_query, status); +} + +int QDMI_telemetrysensor_query_wait(QDMI_TelemetrySensor_Query query, + const size_t timeout) { + if (query == nullptr) { + return QDMI_ERROR_INVALIDARGUMENT; + } + return query->device->library->device_telemetrysensor_query_wait( + query->env_query, timeout); +} + +int QDMI_telemetrysensor_query_cancel(QDMI_TelemetrySensor_Query query) { + + if (query == nullptr) { + return QDMI_ERROR_INVALIDARGUMENT; + } + return query->device->library->device_telemetrysensor_query_cancel( + query->env_query); +} + +void QDMI_telemetrysensor_query_free(QDMI_TelemetrySensor_Query query) { + if (query != nullptr) { + query->device->library->device_telemetrysensor_query_free(query->env_query); + delete query; + } +} diff --git a/examples/fomac/example_fomac.cpp b/examples/fomac/example_fomac.cpp index 93393ab5..fb694774 100644 --- a/examples/fomac/example_fomac.cpp +++ b/examples/fomac/example_fomac.cpp @@ -224,3 +224,64 @@ auto FoMaC::get_parameters_num(const QDMI_Operation &op) const -> size_t { throw_if_error(ret, "Failed to query the parameter number"); return parameters_num; } + +auto FoMaC::get_telemetry_sensors() const -> std::vector { + size_t telemetry_sensor_size = 0; + int ret = QDMI_device_query_device_property( + device, QDMI_DEVICE_PROPERTY_TELEMETRYSENSORS, 0, nullptr, + &telemetry_sensor_size); + throw_if_error(ret, "Failed to get the telemetry sensor list size."); + std::vector telemetry_sensors(telemetry_sensor_size / + sizeof(QDMI_Site)); + ret = QDMI_device_query_device_property( + device, QDMI_DEVICE_PROPERTY_TELEMETRYSENSORS, telemetry_sensor_size, + static_cast(telemetry_sensors.data()), nullptr); + throw_if_error(ret, "Failed to get the telemetry sensors."); + return telemetry_sensors; +} + +auto FoMaC::get_telemetry_id(QDMI_TelemetrySensor telemetry_sensor) const + -> std::string { + size_t telemetrysensor_id_size = 0; + + int ret = QDMI_device_query_telemetrysensor_property( + device, telemetry_sensor, QDMI_TELEMETRYSENSOR_PROPERTY_ID, 0, nullptr, + &telemetrysensor_id_size); + throw_if_error(ret, "Failed to query the size for telemetry ID"); + std::string telemetrysensor_id(telemetrysensor_id_size - 1, '\0'); + ret = QDMI_device_query_telemetrysensor_property( + device, telemetry_sensor, QDMI_TELEMETRYSENSOR_PROPERTY_ID, + telemetrysensor_id.size() + 1, telemetrysensor_id.data(), nullptr); + throw_if_error(ret, "Failed to query the telemetry ID"); + + return telemetrysensor_id; +} + +auto FoMaC::get_telemetry_unit(QDMI_TelemetrySensor telemetry_sensor) const + -> std::string { + size_t telemetrysensor_unit_size = 0; + + int ret = QDMI_device_query_telemetrysensor_property( + device, telemetry_sensor, QDMI_TELEMETRYSENSOR_PROPERTY_UNIT, 0, nullptr, + &telemetrysensor_unit_size); + throw_if_error(ret, "Failed to query the size for telemetry unit"); + + std::string telemetrysensor_unit(telemetrysensor_unit_size - 1, '\0'); + ret = QDMI_device_query_telemetrysensor_property( + device, telemetry_sensor, QDMI_TELEMETRYSENSOR_PROPERTY_UNIT, + telemetrysensor_unit.size() + 1, telemetrysensor_unit.data(), nullptr); + throw_if_error(ret, "Failed to query the telemetry unit"); + + return telemetrysensor_unit; +} + +auto FoMaC::get_telemetry_sampling_rate( + QDMI_TelemetrySensor telemetry_sensor) const -> uint64_t { + uint64_t sampling_rate = 0; + const int ret = QDMI_device_query_telemetrysensor_property( + device, telemetry_sensor, QDMI_TELEMETRYSENSOR_PROPERTY_SAMPLINGRATE, + sizeof(uint64_t), &sampling_rate, nullptr); + throw_if_error(ret, "Failed to query the sampling rate"); + + return sampling_rate; +} diff --git a/examples/fomac/example_fomac.hpp b/examples/fomac/example_fomac.hpp index 57732687..57f60b72 100644 --- a/examples/fomac/example_fomac.hpp +++ b/examples/fomac/example_fomac.hpp @@ -65,4 +65,16 @@ class FoMaC { [[nodiscard]] auto get_parameters_num(const QDMI_Operation &op) const -> size_t; + + [[nodiscard]] auto get_telemetry_sensors() const + -> std::vector; + + [[nodiscard]] auto get_telemetry_id(QDMI_TelemetrySensor telemetry) const + -> std::string; + + [[nodiscard]] auto get_telemetry_unit(QDMI_TelemetrySensor telemetry) const + -> std::string; + + [[nodiscard]] auto + get_telemetry_sampling_rate(QDMI_TelemetrySensor telemetry) const -> uint64_t; }; diff --git a/include/qdmi/client.h b/include/qdmi/client.h index 7027d32f..32abadce 100644 --- a/include/qdmi/client.h +++ b/include/qdmi/client.h @@ -50,6 +50,9 @@ extern "C" { * properties of devices. * - The @ref client_job_interface "client job interface" for submitting jobs * to devices. + * - The @ref client_telemetrysensor_query_interface + * "client telemetry sensor query interface" for querying telemetry sensors from + * devices. * * @{ */ @@ -574,6 +577,77 @@ int QDMI_device_query_operation_property( const QDMI_Site *sites, size_t num_params, const double *params, QDMI_Operation_Property prop, size_t size, void *value, size_t *size_ret); +/** + * @brief Query a telemetry sensor property. + * @param[in] device The device to query. Must not be @c NULL. + * @param[in] telemetry_sensor The telemetry sensor to query. Must not be @c + * NULL. + * @param[in] prop The property to query. Must be one of the values specified + * for @ref QDMI_TelemetrySensor_Property. + * @param[in] size The size of the memory pointed to by @p value in bytes. Must + * be greater or equal to the size of the return type specified for @p prop, + * except when @p value is @c NULL, in which case it is ignored. + * @param[out] value A pointer to the memory location where the value of the + * property will be stored. If this is @c NULL, it is ignored. + * @param[out] size_ret The actual size of the data being queried in bytes. If + * this is @c NULL, it is ignored. + * @return @ref QDMI_SUCCESS if the device supports the specified property and, + * when @p value is not @c NULL, the property was successfully retrieved. + * @return @ref QDMI_ERROR_NOTSUPPORTED if the device does not support the + * property. + * @return @ref QDMI_ERROR_INVALIDARGUMENT if + * - @p device or @p telemetry_sensor is @c NULL, + * - @p prop is invalid, or + * - @p value is not @c NULL and @p size is less than the size of the data + * being queried. + * @return @ref QDMI_ERROR_FATAL if an unexpected error occurred. + * + * @note By calling this function with @p value set to @c NULL, the function can + * be used to check if the telemetry sensor supports the specified property + * without retrieving the property and without the need to provide a buffer for + * it. + * Additionally, the size of the buffer needed to retrieve the property is + * returned in @p size_ret if @p size_ret is not @c NULL. + * + * @note For example, to query the unit of a telemetry sensor, the following + * code pattern + * can be used: + * ``` + * // Check if the device supports the property. + * auto ret = QDMI_device_query_telemetrysensor_property( + * device, telemetry_sensor, QDMI_TELEMETRYSENSOR_PROPERTY_UNIT, 0, + * nullptr, nullptr); + * if (ret == QDMI_ERROR_NOTSUPPORTED) { + * // The device does not support the property. + * ... + * } + * + * // Query the size of the property and the property. + * size_t telemetrysensor_unit_size = 0; + * auto ret = QDMI_device_query_telemetrysensor_property( + * device, telemetry_sensor, QDMI_TELEMETRYSENSOR_PROPERTY_UNIT, 0, + * nullptr, + * &telemetrysensor_unit_size); + * if (ret != QDMI_SUCCESS) { + * // An error occurred. + * ... + * } + * std::string telemetrysensor_unit(telemetrysensor_unit_size - 1, '\0'); + * ret = QDMI_device_query_telemetrysensor_property( + * device, telemetry_sensor, QDMI_TELEMETRYSENSOR_PROPERTY_UNIT, + * telemetrysensor_unit.size() + 1, telemetrysensor_unit.data(), + * nullptr); + * ``` + * + * @remark @ref QDMI_TelemetrySensor handles may be queried via @ref + * QDMI_device_query_device_property with @ref + * QDMI_DEVICE_PROPERTY_TELEMETRYSENSORS. + */ +int QDMI_device_query_telemetrysensor_property( + QDMI_Device device, QDMI_TelemetrySensor telemetry_sensor, + QDMI_TelemetrySensor_Property prop, size_t size, void *value, + size_t *size_ret); + /** @} */ // end of client_query_interface /** @defgroup client_job_interface QDMI Client Job Interface @@ -981,6 +1055,355 @@ void QDMI_job_free(QDMI_Job job); /** @} */ // end of client_job_interface +/** @defgroup client_telemetrysensor_query_interface \ + * QDMI Client Telemetry Sensor Query Interface + * @brief Provides functions to query data from telemetry sensors. + * @details An telemetry sensor query is a task submitted by a client to a + * device for querying data from telemetry sensors, i.e. temperature or power. + * + * The typical workflow for a client telemetry sensor query is as follows: + * - Create a telemetry sensor query with @ref + * QDMI_device_create_telemetrysensor_query. + * - Set parameters for the telemetry sensor query with @ref + * QDMI_telemetrysensor_query_set_parameter + * - Submit the telemetry query to the device with @ref + * QDMI_telemetrysensor_query_submit. + * - Check the status of the telemetry sensor query with @ref + * QDMI_telemetrysensor_query_check_status. + * - Wait for the telemetry sensor query to finish with @ref + * QDMI_telemetrysensor_query_wait. + * - Retrieve the results of the telemetry sensor query with @ref + * QDMI_telemetrysensor_query_get_results. + * - Free the telemetry sensor query with @ref + * QDMI_telemetrysensor_query_free when it is no longer used. + * + * @{ + */ + +/** + * @brief A handle for a client-side telemetry sensor query. + * @details An opaque pointer to a type defined by the driver that encapsulates + * all information about a telemetry sensor query submitted to a device by a + * client. + * @remark Implementations of the underlying type will want to store the device + * handle used to create the telemetry sensor query in the handle to be able + * to access the device when needed. + * @see QDMI_Device_TelemetrySensor_Query for the device-side telemetry + * sensor query handle. + */ +typedef struct QDMI_TelemetrySensor_Query_impl_d *QDMI_TelemetrySensor_Query; + +/** + * @brief Create a telemetry sensor query. + * @details This is the main entry point for a client to submit a telemetry + * sensor query to a device. The returned handle can be used throughout the + * @ref client_telemetrysensor_query_interface + * "client telemetry sensor query interface" to refer to the telemetry + * sensor query. + * @param[in] device The device to create the telemetry sensor query on. Must + * not be @c NULL. + * @param[in] telemetry_sensor The telemetry sensor to query data from. Must + * not be @c NULL. + * @param[out] query A pointer to a handle that will store the created + * telemetry sensor query. Must not be @c NULL. The query must be freed by + * calling @ref QDMI_telemetrysensor_query_free when it is no longer used. + * @return @ref QDMI_SUCCESS if the query was successfully created. + * @return @ref QDMI_ERROR_INVALIDARGUMENT if @p device, @p telemetry_sensor or + * @p query are @c NULL. + * @return @ref QDMI_ERROR_PERMISSIONDENIED if the driver does not allow using + * the @ref client_telemetrysensor_query_interface + * "client telemetry sensor query interface" for the device in the current + * session. + * @return @ref QDMI_ERROR_FATAL if the telemetry sensor query creation failed + * due to a fatal error. + */ +int QDMI_device_create_telemetrysensor_query( + QDMI_Device device, QDMI_TelemetrySensor *telemetry_sensor, + QDMI_TelemetrySensor_Query *query); + +/** + * @brief Enum of the telemetry sensor query parameters that can be set. + * @details If not noted otherwise, parameters are mandatory and drivers must + * require them to be set. + */ + +enum QDMI_TELEMETRYSENSOR_QUERY_PARAMETER_T { + /** + * @brief `time_t` The start time of the telemetry query interval. + * @details This parameter is required. It specifies the start time of the + * telemetry query interval as a UNIX timestamp. If the value is invalid, the + * @ref QDMI_telemetrysensor_query_set_parameter function must return @ref + * QDMI_ERROR_INVALIDARGUMENT. + */ + QDMI_TELEMETRYSENSOR_QUERY_PARAMETER_STARTTIME = 0, + /** + * @brief `time_t` The end time of the telemetry query interval. + * @details This parameter is required. It specifies the end time of the + * telemetry query interval as a UNIX timestamp. If the value is invalid, the + * @ref QDMI_telemetrysensor_query_set_parameter function must return @ref + * QDMI_ERROR_INVALIDARGUMENT. + */ + QDMI_TELEMETRYSENSOR_QUERY_PARAMETER_ENDTIME = 1, + /** + * @brief `QDMI_TelemetrySensor` The telemetry sensor to query data from. + * @details This parameter is required. It specifies the telemetry sensor to + * query data from. If the value is invalid, the @ref + * QDMI_telemetrysensor_query_set_parameter function must return @ref + * QDMI_ERROR_INVALIDARGUMENT. end time of the telemetry query interval. + */ + QDMI_TELEMETRYSENSOR_QUERY_PARAMETER_TELEMETRY = 2, + + /** + * @brief The maximum value of the enum. + * @details It can be used by drivers for bounds checking and validation of + * function parameters. + * @attention This value must remain the last regular member of the enum + * besides the custom members and must be updated when new members are added. + */ + QDMI_TELEMETRYSENSOR_QUERY_PARAMETER_MAX = 3, + + /** + * @brief This enum value is reserved for a custom parameter. + * @details The driver defines the meaning and the type of this parameter. + * @attention The value of this enum member must not be changed to maintain + * binary compatibility. + */ + QDMI_TELEMETRYSENSOR_QUERY_PARAMETER_CUSTOM1 = 999999995, + + /// @see QDMI_TELEMETRYSENSOR_QUERY_PARAMETER_CUSTOM1 + QDMI_TELEMETRYSENSOR_QUERY_PARAMETER_CUSTOM2 = 999999996, + + /// @see QDMI_TELEMETRYSENSOR_QUERY_PARAMETER_CUSTOM1 + QDMI_TELEMETRYSENSOR_QUERY_PARAMETER_CUSTOM3 = 999999997, + + /// @see QDMI_TELEMETRYSENSOR_QUERY_PARAMETER_CUSTOM1 + QDMI_TELEMETRYSENSOR_QUERY_PARAMETER_CUSTOM4 = 999999998, + + /// @see QDMI_TELEMETRYSENSOR_QUERY_PARAMETER_CUSTOM1 + QDMI_TELEMETRYSENSOR_QUERY_PARAMETER_CUSTOM5 = 999999999 +}; + +/// Telemetry sensor query parameter type. +typedef enum QDMI_TELEMETRYSENSOR_QUERY_PARAMETER_T + QDMI_TelemetrySensor_Query_Parameter; +/** + * @brief Set a parameter for a telemetry sensor. + * @param[in] query A handle to a query for which to set @p param. Must not be + * @c NULL. + * @param[in] param The parameter whose value will be set. Must be one of the + * values specified for @ref QDMI_TelemetrySensor_Query_Parameter. + * @param[in] size The size of the data pointed to by @p value in bytes. Must + * not be zero, except when @p value is @c NULL, in which case it is ignored. + * @param[in] value A pointer to the memory location that contains the value of + * the parameter to be set. The data pointed to by @p value is copied and can be + * safely reused after this function returns. If this is @c NULL, it is ignored. + * @return @ref QDMI_SUCCESS if the driver supports the specified @ref + * QDMI_TelemetrySensor_Query_Parameter @p param and, when @p value is not @c + * NULL, the parameter was successfully set. + * @return @ref QDMI_ERROR_NOTSUPPORTED if the driver does not support the + * parameter or the value of the parameter. + * @return @ref QDMI_ERROR_INVALIDARGUMENT if + * - @p query is @c NULL, + * - @p param is invalid, or + * - @p value is not @c NULL and @p size is zero or not the expected size for + * the parameter (if specified by the @ref + * QDMI_TelemetrySensor_Query_Parameter documentation). + * @return @ref QDMI_ERROR_BADSTATE if the parameter cannot be set in the + * current state of the query, for example, because the query is already + * submitted. + * @return @ref QDMI_ERROR_PERMISSIONDENIED if the driver does not allow using + * the @ref client_telemetrysensor_query_interface + * "client telemetry sensor query interface" for the device in the current + * session. + * @return @ref QDMI_ERROR_FATAL if setting the parameter failed due to a fatal + * error. + * + * @note By calling this function with @p value set to @c NULL, the function can + * be used to check if the driver supports the specified parameter without + * setting the parameter and without the need to provide a value. + * + * @note For example, to check whether the device supports setting the start + * time for an envronment query, the following code pattern can be + * used: + * ``` + * // Check if the device supports setting the start time + * auto ret = QDMI_telemetrysensor_query_set_parameter( + * query, QDMI_TELEMETRYSENSOR_QUERY_PARAMETER_START_TIME, 0, nullptr); + * if (ret == QDMI_ERROR_NOTSUPPORTED) { + * // The device does not support setting the start time. + * ... + * } + * + * // Set the start time. + * time_t start_ts = 1744970400; + * QDMI_telemetrysensor_query_set_parameter( + * query, QDMI_TELEMETRYSENSOR_QUERY_PARAMETER_START_TIME, sizeof(time_t), + * &start_ts); + * ``` + */ +int QDMI_telemetrysensor_query_set_parameter( + QDMI_TelemetrySensor_Query query, + QDMI_TelemetrySensor_Query_Parameter param, size_t size, const void *value); +/** + * @brief Submit a telemetry sensor query to the device. + * @details This function can either be blocking until the telemetry sensor + * query is finished or non-blocking and return while the telemetry sensor + * query is running. In the latter case, the functions @ref + * QDMI_telemetrysensor_query_check_status and @ref + * QDMI_telemetrysensor_query_wait can be used to check the status and wait + * for the telemetry sensor query to finish. + * @param[in] query The telemetry sensor query to submit. Must not be @c NULL. + * @return @ref QDMI_SUCCESS if the telemetry sensor query was successfully + * submitted. + * @return @ref QDMI_ERROR_INVALIDARGUMENT if telemetry sensor query is @c + * NULL. + * @return @ref QDMI_ERROR_BADSTATE if the telemetry sensor query is in an + * invalid state. + * @return @ref QDMI_ERROR_PERMISSIONDENIED if the driver does not allow using + * the @ref client_telemetrysensor_query_interface + * "client telemetry sensor query interface" for the device in the current + * session. + * @return @ref QDMI_ERROR_FATAL if the telemetry sensor query submission + * failed. + */ +int QDMI_telemetrysensor_query_submit(QDMI_TelemetrySensor_Query query); + +/** + * @brief Cancel an already submitted telemetry sensor query. + * @details Remove the telemetry sensor query from the queue of waiting + * telemetry sensor query. This changes the status of the telemetry sensor + * query to @ref QDMI_TELEMETRYSENSOR_QUERY_STATUS_CANCELED. + * @param[in] query The telemetry sensor query to cancel. Must not be @c NULL. + * @return @ref QDMI_SUCCESS if the telemetry sensor query was successfully + * canceled. + * @return @ref QDMI_ERROR_INVALIDARGUMENT if @p query is @c NULL or the + * telemetry sensor query already has the status @ref + * QDMI_TELEMETRYSENSOR_QUERY_STATUS_DONE. + * @return @ref QDMI_ERROR_PERMISSIONDENIED if the driver does not allow using + * the @ref client_telemetrysensor_query_interface + * "client telemetry sensor query interface" for the device in the current + * session. + * @return @ref QDMI_ERROR_FATAL if the telemetry sensor query could not be + * canceled. + */ +int QDMI_telemetrysensor_query_cancel(QDMI_TelemetrySensor_Query query); + +/** + * @brief Check the status of a telemetry sensor query. + * @details This function is non-blocking and returns immediately with the + * telemetry sensor query status. It is not required to call this function + * before calling @ref QDMI_telemetrysensor_query_get_results. + * @param[in] query The telemetry sensor query to check the status of. Must + * not be @c NULL. + * @param[out] status The status of the telemetry sensor query. Must not be @c + * NULL. + * @return @ref QDMI_SUCCESS if the telemetry sensor query status was + * successfully checked. + * @return @ref QDMI_ERROR_INVALIDARGUMENT if @p query or @p status is @c NULL. + * @return @ref QDMI_ERROR_PERMISSIONDENIED if the driver does not allow using + * the @ref client_telemetrysensor_query_interface + * "client telemetry sensor query interface" for the device in the current + * session. + * @return @ref QDMI_ERROR_FATAL if the telemetry sensor query status could + * not be checked. + */ +int QDMI_telemetrysensor_query_check_status( + QDMI_TelemetrySensor_Query query, + QDMI_TelemetrySensor_Query_Status *status); + +/** + * @brief Wait for a telemetry sensor query to finish. + * @details This function blocks until the telemetry sensor query has either + * finished or has been canceled, or the timeout has been reached. + * @param[in] query The telemetry sensor query to wait for. Must not be @c + * NULL. + * @param[in] timeout The timeout in seconds. + * If this is zero, the function waits indefinitely until the telemetry sensor + * query has finished. + * @return @ref QDMI_SUCCESS if the telemetry sensor query is finished or + * canceled. + * @return @ref QDMI_ERROR_INVALIDARGUMENT if @p query is @c NULL. + * @return @ref QDMI_ERROR_PERMISSIONDENIED if the driver does not allow using + * the @ref client_telemetrysensor_query_interface + * "client telemetry sensor query interface" for the device in the current + * session. + * @return @ref QDMI_ERROR_TIMEOUT if @p timeout is not zero and the query did + * not finish within the specified time. + * @return @ref QDMI_ERROR_FATAL if the telemetry sensor query could not be + * waited for and this function returns before the telemetry sensor query has + * finished or has been canceled. + */ +int QDMI_telemetrysensor_query_wait(QDMI_TelemetrySensor_Query query, + size_t timeout); + +/** + * @brief Retrieve the results of a telemetry sensor query. + * @param[in] query The telemetry sensor query to retrieve the results from. + * Must not be @c NULL. + * @param[in] result The result to retrieve. Must be one of the values specified + * for @ref QDMI_TelemetrySensor_Query_Result. + * @param[in] size The size of the buffer pointed to by @p data in bytes. Must + * be greater or equal to the size of the return type specified for the @ref + * QDMI_TelemetrySensor_Query_Result @p result, except when @p data is @c + * NULL, in which case it is ignored. + * @param[out] data A pointer to the memory location where the results will be + * stored. If this is @c NULL, it is ignored. + * @param[out] size_ret The actual size of the data being queried in bytes. If + * this is @c NULL, it is ignored. + * @return @ref QDMI_SUCCESS if the device supports the specified result and, + * when @p data is not @c NULL, the results were successfully retrieved. + * @return @ref QDMI_ERROR_INVALIDARGUMENT if + * - @p query is @c NULL, + * - @p query has not finished, + * - @p query was canceled, + * - @p result is invalid, or + * - @p data is not @c NULL and @p size is smaller than the size of the data + * being queried. + * @return @ref QDMI_ERROR_PERMISSIONDENIED if the driver does not allow using + * the @ref client_telemetrysensor_query_interface + * "client telemetry sensor query interface" for the device in the current + * session. + * @return @ref QDMI_ERROR_FATAL if an error occurred during the retrieval. + * + * @note By calling this function with @p data set to @c NULL, the function can + * be used to check if the device supports the specified result without + * retrieving the result and without the need to provide a buffer for the + * result. + * Additionally, the size of the buffer needed to retrieve the result is + * returned in @p size_ret if @p size_ret is not @c NULL. + * + * @note For example, to query the results of a telemetry sensor query, + * the following code pattern can be used: + * ``` + * // Query the size of the result. + * size_t size; + * auto ret = QDMI_telemetrysensor_query_get_results( + * query, QDMI_TELEMETRYSENSOR_QUERY_RESULT_VALUES, 0, nullptr, &size); + * + * // Allocate memory for the result. + * std::vector values; + * values.reserve(size); + * + * // Query the result. + * QDMI_telemetrysensor_query_get_results( + * query, QDMI_TELEMETRYSENSOR_QUERY_RESULT_VALUES, size, values.data(), + * nullptr); + * ``` + */ +int QDMI_telemetrysensor_query_get_results( + QDMI_TelemetrySensor_Query query, QDMI_TelemetrySensor_Query_Result result, + size_t size, void *data, size_t *size_ret); +/** + * @brief Free a telemetry sensor query. + * @details Free the resources associated with a telemetry sensor query. Using + * a telemetry sensor query handle after it has been freed is undefined + * behavior. + * @param[in] query The telemetry sensor query to free. + */ +void QDMI_telemetrysensor_query_free(QDMI_TelemetrySensor_Query query); + +/** @} */ // end of client_telemetrysensor_query_interface + /** @} */ // end of client_interface // NOLINTEND(performance-enum-size, modernize-use-using) diff --git a/include/qdmi/constants.h b/include/qdmi/constants.h index a6b2ec48..e8d06250 100644 --- a/include/qdmi/constants.h +++ b/include/qdmi/constants.h @@ -393,6 +393,13 @@ enum QDMI_DEVICE_PROPERTY_T { * @see QDMI_DEVICE_PROPERTY_LENGTSCALEFACTOR */ QDMI_DEVICE_PROPERTY_MINATOMDISTANCE = 14, + /** + * @brief `QDMI_TelemetrySensor*` (@ref QDMI_TelemetrySensor list) The + * telemetry sensors of the device. + * @details The returned @ref QDMI_TelemetrySensor handles may be used to + * query telemetry sensors. + */ + QDMI_DEVICE_PROPERTY_TELEMETRYSENSORS = 15, /** * @brief The maximum value of the enum. * @details It can be used by devices for bounds checking and validation of @@ -401,7 +408,7 @@ enum QDMI_DEVICE_PROPERTY_T { * @attention This value must remain the last regular member of the enum * besides the custom members and must be updated when new members are added. */ - QDMI_DEVICE_PROPERTY_MAX = 15, + QDMI_DEVICE_PROPERTY_MAX = 16, /** * @brief This enum value is reserved for a custom property. * @details The device defines the meaning and the type of this property. @@ -1132,6 +1139,187 @@ enum QDMI_DEVICE_PULSE_SUPPORT_LEVEL_T { /// Pulse support level type. typedef enum QDMI_DEVICE_PULSE_SUPPORT_LEVEL_T QDMI_Device_Pulse_Support_Level; +/** + * Enum of the telemetry sensor properties that can be queried via @ref + * QDMI_device_session_query_telemetrysensor_property as part of the @ref + * device_interface "device interface" and via @ref + * QDMI_device_query_telemetrysensor_property as part of the @ref + * client_interface "client interface". + */ +enum QDMI_TELEMETRYSENSOR_PROPERTY_T { + /** + * @brief `char*` (string) The unique ID to identify the telemetry sensor. + * @details The ID of a telemetry sensor is used to identify the sensors. The + * sensors collect telemetry data in the environments that the quantum devices + * are hosted, such as HPCQC Labs, i.e., temperature and pressure. + */ + QDMI_TELEMETRYSENSOR_PROPERTY_ID = 0, + /** + * `char*` (string) The unit of a telemetry sensor, e.g., Kelvin for + * temperature. + */ + QDMI_TELEMETRYSENSOR_PROPERTY_UNIT = 1, + /** + * `uint64_t` The samples per second of a telemetry sensor. + */ + QDMI_TELEMETRYSENSOR_PROPERTY_SAMPLINGRATE = 2, + /** + * @brief The maximum value of the enum. + * @details It can be used by devices for bounds checking and + * validation of function parameters. + * + * @attention This value must remain the last regular member of the + * enum besides the custom members and must be updated when new + * members are added. + */ + QDMI_TELEMETRYSENSOR_PROPERTY_MAX = 3, + /** + * @brief This enum value is reserved for a custom property. + * @details The device defines the meaning and the type of this + * property. + * @attention The value of this enum member must not be changed to + * maintain binary compatibility. + */ + QDMI_TELEMETRYSENSOR_PROPERTY_CUSTOM1 = 999999995, + /// @see QDMI_TELEMETRYSENSOR_PROPERTY_CUSTOM1 + QDMI_TELEMETRYSENSOR_PROPERTY_CUSTOM2 = 999999996, + /// @see QDMI_TELEMETRYSENSOR_PROPERTY_CUSTOM1 + QDMI_TELEMETRYSENSOR_PROPERTY_CUSTOM3 = 999999997, + /// @see QDMI_TELEMETRYSENSOR_PROPERTY_CUSTOM1 + QDMI_TELEMETRYSENSOR_PROPERTY_CUSTOM4 = 999999998, + /// @see QDMI_TELEMETRYSENSOR_PROPERTY_CUSTOM1 + QDMI_TELEMETRYSENSOR_PROPERTY_CUSTOM5 = 999999999 +}; + +/// Telemetry property type. +typedef enum QDMI_TELEMETRYSENSOR_PROPERTY_T QDMI_TelemetrySensor_Property; + +/** + * @brief Enum of the device telemetrysensor query parameters that can be set + * via + * @ref QDMI_device_telemetrysensor_query_set_parameter. + * @details If not noted otherwise, parameters are mandatory and devices must + * require them to be set. + */ +enum QDMI_DEVICE_TELEMETRYSENSOR_QUERY_PARAMETER_T { + /** + * `time_t` The start time of the telemetry sensor query interval. + */ + QDMI_DEVICE_TELEMETRYSENSOR_QUERY_PARAMETER_STARTTIME = 0, + /** + * `time_t` The end time of the telemetry sensor query interval. + */ + QDMI_DEVICE_TELEMETRYSENSOR_QUERY_PARAMETER_ENDTIME = 1, + /** + * `QDMI_TelemetrySensor *` The telemetry sensor for the telemetry sensor + * query. + */ + QDMI_DEVICE_TELEMETRYSENSOR_QUERY_PARAMETER_TELEMETRYSENSOR = 2, + /** + * The maximum value of the enum. + */ + QDMI_DEVICE_TELEMETRYSENSOR_QUERY_PARAMETER_MAX = 3, + /** + * @brief This enum value is reserved for a custom parameter. + * @details The devices defines the meaning and the type of this parameter. + * @attention The value of this enum member must not be changed to maintain + * binary compatibility. + */ + QDMI_DEVICE_TELEMETRYSENSOR_QUERY_PARAMETER_CUSTOM1 = 999999995, + /// @see QDMI_DEVICE_TELEMETRYSENSOR_QUERY_PARAMETER_CUSTOM1 + QDMI_DEVICE_TELEMETRYSENSOR_QUERY_PARAMETER_CUSTOM2 = 999999996, + /// @see QDMI_DEVICE_TELEMETRYSENSOR_QUERY_PARAMETER_CUSTOM1 + QDMI_DEVICE_TELEMETRYSENSOR_QUERY_PARAMETER_CUSTOM3 = 999999997, + /// @see QDMI_DEVICE_TELEMETRYSENSOR_QUERY_PARAMETER_CUSTOM1 + QDMI_DEVICE_TELEMETRYSENSOR_QUERY_PARAMETER_CUSTOM4 = 999999998, + /// @see QDMI_DEVICE_TELEMETRYSENSOR_QUERY_PARAMETER_CUSTOM1 + QDMI_DEVICE_TELEMETRYSENSOR_QUERY_PARAMETER_CUSTOM5 = 999999999 +}; + +/// Device telemetry query parameter type. +typedef enum QDMI_DEVICE_TELEMETRYSENSOR_QUERY_PARAMETER_T + QDMI_Device_TelemetrySensor_Query_Parameter; + +/** + * @brief Enum of the formats the telemetry sensor query results can be + * returned in. + */ +enum QDMI_TELEMETRYSENSOR_QUERY_RESULT_T { + /** + * @brief `time_t*` (`unsigned 64 bit integer` list) The UNIX timestamps at + * which the corresponding values in the results were recorded by a sensor. + * @details The result of a telemetry sensor query is represented as a + * key-value mapping. This mapping is returned as a list of keys and an + * equal-length list of values. The corresponding partners of the keys and + * values can be found at the same index in the lists. + * + * This constant denotes the list of keys, @ref + * QDMI_TELEMETRYSENSOR_QUERY_RESULT_VALUES denotes the list of values. + */ + QDMI_TELEMETRYSENSOR_QUERY_RESULT_TIMESTAMPS = 0, + /** + * @brief `double*` (`double` list) The values of the result. + * @see QDMI_TELEMETRYSENSOR_QUERY_RESULT_TIMESTAMPS + */ + QDMI_TELEMETRYSENSOR_QUERY_RESULT_VALUES = 1, + /** + * @brief The maximum value of the enum. + * @details It can be used by devices for bounds checking and validation of + * function parameters. + * + * @attention This value must remain the last regular member of the enum + * besides the custom members and must be updated when new members are added. + */ + QDMI_TELEMETRYSENSOR_QUERY_RESULT_MAX = 2, + /** + * @brief This enum value is reserved for a custom result. + * @details The device defines the meaning and the type of this result. + * @attention The value of this enum member must not be changed to maintain + * binary compatibility. + */ + QDMI_TELEMETRYSENSOR_QUERY_RESULT_CUSTOM1 = 999999995, + /// @see QDMI_TELEMETRYSENSOR_QUERY_RESULT_CUSTOM1 + QDMI_TELEMETRYSENSOR_QUERY_RESULT_CUSTOM2 = 999999996, + /// @see QDMI_TELEMETRYSENSOR_QUERY_RESULT_CUSTOM1 + QDMI_TELEMETRYSENSOR_QUERY_RESULT_CUSTOM3 = 999999997, + /// @see QDMI_TELEMETRYSENSOR_QUERY_RESULT_CUSTOM1 + QDMI_TELEMETRYSENSOR_QUERY_RESULT_CUSTOM4 = 999999998, + /// @see QDMI_TELEMETRYSENSOR_QUERY_RESULT_CUSTOM1 + QDMI_TELEMETRYSENSOR_QUERY_RESULT_CUSTOM5 = 999999999 +}; +/// Telemetry query result type. +typedef enum QDMI_TELEMETRYSENSOR_QUERY_RESULT_T + QDMI_TelemetrySensor_Query_Result; + +/** + * @brief Enum of the status a telemetry sensor query can have. + * @details See also @ref client_telemetrysensor_query_interface for a + * description of the telemetry sensor query's lifecycle. + */ + +enum QDMI_TELEMETRYSENSOR_QUERY_STATUS_T { + /** + * @brief The telemetry sensor query was created and can be configured via + * @ref QDMI_telemetrysensor_query_set_parameter. + */ + QDMI_TELEMETRYSENSOR_QUERY_STATUS_CREATED = 0, + /// The telemetry sensor query was submitted. + QDMI_TELEMETRYSENSOR_QUERY_STATUS_SUBMITTED = 1, + /// The telemetry query was received and is waiting to be executed. + QDMI_TELEMETRYSENSOR_QUERY_STATUS_QUEUED = 2, + /// The telemetry query is running, and the result is not yet available. + QDMI_TELEMETRYSENSOR_QUERY_STATUS_RUNNING = 3, + /// The telemetry query is done, and the result can be retrieved. + QDMI_TELEMETRYSENSOR_QUERY_STATUS_DONE = 4, + /// The telemetry query was canceled, and the result is not available. + QDMI_TELEMETRYSENSOR_QUERY_STATUS_CANCELED = 5, + /// An error occurred in the telemetry sensor query's lifecycle. + QDMI_TELEMETRYSENSOR_QUERY_STATUS_FAILED = 6 +}; +/// Telemetry query status type. +typedef enum QDMI_TELEMETRYSENSOR_QUERY_STATUS_T + QDMI_TelemetrySensor_Query_Status; + // NOLINTEND(performance-enum-size, modernize-use-using) #ifdef __cplusplus diff --git a/include/qdmi/device.h b/include/qdmi/device.h index ed9a4b84..76f013ad 100644 --- a/include/qdmi/device.h +++ b/include/qdmi/device.h @@ -43,7 +43,8 @@ extern "C" { * @details This is an interface between the QDMI driver and the device. * It includes functions to initialize and finalize a device, as well as to * manage sessions between a QDMI driver and a device, query properties of the - * device, and submit jobs to the device. + * device, submit jobs to the device, and query telemetry sensor + * data from the device. * * The device interface is split into three parts: * - The @ref device_session_interface "device session interface" for managing @@ -52,6 +53,9 @@ extern "C" { * properties of the device. * - The @ref device_job_interface "device job interface" for submitting jobs * to the device. + * - The @ref device_telemetrysensor_query_interface + * " device telemetry sensor query interface" for querying telemetry sensor + * data from the device. * * @{ */ @@ -352,6 +356,51 @@ int QDMI_device_session_query_operation_property( const QDMI_Site *sites, size_t num_params, const double *params, QDMI_Operation_Property prop, size_t size, void *value, size_t *size_ret); +/** + * @brief Query a telemetry sensor property. + * @param[in] session The session used for the query. Must not be @c NULL. + * @param[in] telemetry_sensor The telemetry sensor to query. Must not be @c + * NULL. + * @param[in] prop The property to query. Must be one of the values specified + * for @ref QDMI_TelemetrySensor_Property. + * @param[in] size The size of the memory pointed to by @p value in bytes. Must + * be greater or equal to the size of the return type specified for @p prop, + * except when @p value is @c NULL, in which case it is ignored. + * @param[out] value A pointer to the memory location where the value of the + * property will be stored. If this is @c NULL, it is ignored. + * @param[out] size_ret The actual size of the data being queried in bytes. If + * this is @c NULL, it is ignored. + * @return @ref QDMI_SUCCESS if the device supports the specified property and, + * when @p value is not @c NULL, the property was successfully retrieved. + * @return @ref QDMI_ERROR_NOTSUPPORTED if the device does not support the + * property. + * @return @ref QDMI_ERROR_INVALIDARGUMENT if + * - @p session or @p query is @c NULL, + * - @p prop is invalid, or + * - @p value is not @c NULL and @p size is less than the size of the data + * being queried. + * @return @ref QDMI_ERROR_BADSTATE if the property cannot be queried in the + * current state of the session, for example, because the session is not + * initialized. + * @return @ref QDMI_ERROR_FATAL if an unexpected error occurred. + * + * @remark Calling this function with @p value set to @c NULL is expected to + * allow checking if the device supports the specified property without + * retrieving the property and without the need to provide a buffer for it. + * Additionally, the size of the buffer needed to retrieve the property is + * returned in @p size_ret if @p size_ret is not @c NULL. + * See the @ref QDMI_device_query_telemetrysensor_property documentation for + * an example. + * + * @attention May only be called after the session has been initialized with + * @ref QDMI_device_session_init. + */ + +int QDMI_device_session_query_telemetrysensor_property( + QDMI_Device_Session session, QDMI_TelemetrySensor telemetry_sensor, + QDMI_TelemetrySensor_Property prop, size_t size, void *value, + size_t *size_ret); + /** @} */ // end of device_query_interface /** @defgroup device_job_interface QDMI Device Job Interface @@ -593,6 +642,250 @@ void QDMI_device_job_free(QDMI_Device_Job job); /** @} */ // end of device_job_interface +/** @defgroup device_telemetrysensor_query_interface \ + * QDMI Device Telemetry Sensor Query Interface + * @brief Provides functions to manage telemetry sensor queries on a device. + * @details A telemetry sensor query is a task submitted to a device for + * querying telemetry sensors, i.e. temperature or power. + * + * The typical workflow for a device telemetry sensor query is as follows: + * - Create a telemetry sensor query with @ref + * QDMI_device_session_create_device_telemetrysensor_query. + * - Set parameters for the telemetry sensor query with @ref + * QDMI_device_telemetrysensor_query_set_parameter + * - Submit the telemetry sensor query to the device with @ref + * QDMI_device_telemetrysensor_query_submit. + * - Check the status of the telemetry sensor query with @ref + * QDMI_device_telemetrysensor_query_check_status. + * - Wait for the telemetry sensor query to finish with @ref + * QDMI_device_telemetrysensor_query_wait. + * - Retrieve the results of the telemetry sensor query with @ref + * QDMI_telemetrysensor_query_get_results. + * - Free the telemetry sensor query with @ref + * QDMI_device_telemetrysensor_query_free when it is no longer used. + * + * @{ + */ + +/** + * @brief A handle for a device telemetry sensor query. + * @details An opaque pointer to a type defined by the device that encapsulates + * all information about a telemetry sensor query on a device. + * @remark Implementations of the underlying type will want to store the session + * handle used to create the telemetry sensor query in the telemetry sensor + * query handle to be able to access the session information when needed. + * @see QDMI_TelemetrySensor_Query for the client-side job handle. + */ +typedef struct QDMI_Device_TelemetrySensor_Query_impl_d + *QDMI_Device_TelemetrySensor_Query; +/** + * @brief Create a telemetry sensor query. + * @details This is the main entry point for a driver to create a telemetry + * sensor query for a device. The returned handle can be used throughout the + * @ref device_telemetrysensor_query_interface + * "device telemetry sensor query interface" to refer to the telemetry + * query. + * @param[in] session The session to create the telemetry sensor query on. + * Must not be @c NULL. + * @param[out] query A pointer to a handle that will store the created + * telemetry sensor query. Must not be @c NULL. The telemetry sensor query + * must be freed by calling + * @ref QDMI_device_telemetrysensor_query_free when it is no longer used. + * @return @ref QDMI_SUCCESS if the telemetry sensor query was successfully + * created. + * @return @ref QDMI_ERROR_INVALIDARGUMENT if @p session or @p query are @c + * NULL. + * @return @ref QDMI_ERROR_BADSTATE if the session is not in a state allowing + * the creation of a telemetry sensor query, for example, because the session + * is not initialized. + * @return @ref QDMI_ERROR_PERMISSIONDENIED if the device does not allow using + * the @ref device_telemetrysensor_query_interface + * "device telemetry sensor query interface" for the current session. + * @return @ref QDMI_ERROR_FATAL if the telemetry sensor query creation failed + * due to a fatal error. + * + * @attention May only be called after the session has been initialized with + * @ref QDMI_device_session_init. + */ +int QDMI_device_session_create_device_telemetrysensor_query( + QDMI_Device_Session session, QDMI_Device_TelemetrySensor_Query *query); +/** + * @brief Set a parameter for a telemetry sensor query. + * @param[in] query A handle to a telemetry sensor query for which to set @p + * param. Must not be @c NULL. + * @param[in] param The parameter whose value will be set. Must be one of the + * values specified for @ref QDMI_Device_TelemetrySensor_Query_Parameter. + * @param[in] size The size of the data pointed to by @p value in bytes. Must + * not be zero, except when @p value is @c NULL, in which case it is ignored. + * @param[in] value A pointer to the memory location that contains the value of + * the parameter to be set. The data pointed to by @p value is copied and can be + * safely reused after this function returns. If this is @c NULL, it is ignored. + * @return @ref QDMI_SUCCESS if the device supports the specified @ref + * QDMI_Device_TelemetrySensor_Query_Parameter @p param and, when @p value is + * not @c NULL, the parameter was successfully set. + * @return @ref QDMI_ERROR_NOTSUPPORTED if the device does not support the + * parameter or the value of the parameter. + * @return @ref QDMI_ERROR_INVALIDARGUMENT if + * - @p query is @c NULL, + * - @p param is invalid, or + * - @p value is not @c NULL and @p size is zero or not the expected size for + * the parameter (if specified by the @ref + * QDMI_Device_TelemetrySensor_Query_Parameter documentation). + * @return @ref QDMI_ERROR_BADSTATE if the parameter cannot be set in the + * current state of the telemetry sensor query, for example, because the + * telemetry sensor query is already submitted. + * @return @ref QDMI_ERROR_PERMISSIONDENIED if the device does not allow using + * the @ref device_telemetrysensor_query_interface + * "device telemetry sensor query interface" for the current session. + * @return @ref QDMI_ERROR_FATAL if setting the parameter failed due to a fatal + * error. + * + * @remark Calling this function with @p value set to @c NULL is expected to + * allow checking if the device supports the specified parameter without setting + * the parameter and without the need to provide a value. + * See the @ref QDMI_telemetrysensor_query_set_parameter documentation for an + * example. + */ +int QDMI_device_telemetrysensor_query_set_parameter( + QDMI_Device_TelemetrySensor_Query query, + QDMI_Device_TelemetrySensor_Query_Parameter param, size_t size, + const void *value); +/** + * @brief Submit a telemetry sensor query to the device. + * @details This function can either be blocking until the job is finished or + * non-blocking and return while the job is running. In the latter case, the + * functions @ref QDMI_device_telemetrysensor_query_check_status and @ref + * QDMI_device_telemetrysensor_query_wait can be used to check the status and + * wait for the telemetry sensor query to finish. + * @param[in] query The telemetry sensor query to submit. Must not be @c NULL. + * @return @ref QDMI_SUCCESS if the job was successfully submitted. + * @return @ref QDMI_ERROR_INVALIDARGUMENT if @p job is @c NULL. + * @return @ref QDMI_ERROR_BADSTATE if the job is in an invalid state. + * @return @ref QDMI_ERROR_PERMISSIONDENIED if the device does not allow using + * the @ref device_telemetrysensor_query_interface + * "device telemetry sensor query interface" for the current session. + * @return @ref QDMI_ERROR_FATAL if the job submission failed. + */ +int QDMI_device_telemetrysensor_query_submit( + QDMI_Device_TelemetrySensor_Query query); + +/** + * @brief Cancel an already submitted telemetry sensor query. + * @details Remove the telemetry sensor query from the queue of waiting + * telemetry sensor query. This changes the status of the telemetry query to + * @ref QDMI_TELEMETRYSENSOR_QUERY_STATUS_CANCELED. + * @param[in] query The telemetry sensor query to cancel. Must not be @c NULL. + * @return @ref QDMI_SUCCESS if the telemetry sensor query was successfully + * canceled. + * @return @ref QDMI_ERROR_INVALIDARGUMENT if @p query is @c NULL or the job + * already has the status @ref QDMI_TELEMETRYSENSOR_QUERY_STATUS_DONE. + * @return @ref QDMI_ERROR_PERMISSIONDENIED if the device does not allow using + * the @ref device_telemetrysensor_query_interface + * "device telemetry sensor query interface" for the current session. + * @return @ref QDMI_ERROR_FATAL if the telemetry sensor query could not be + * canceled. + */ +int QDMI_device_telemetrysensor_query_cancel( + QDMI_Device_TelemetrySensor_Query query); + +/** + * @brief Check the status of a telemetry sensor query. + * @details This function is non-blocking and returns immediately with the + * telemetry sensor query status. It is not required to call this function + * before calling @ref QDMI_telemetrysensor_query_get_results. + * @param[in] query The telemetry sensor query to check the status of. Must + * not be @c NULL. + * @param[out] status The status of the telemetry sensor query. Must not be @c + * NULL. + * @return @ref QDMI_SUCCESS if the telemetry sensor query status was + * successfully checked. + * @return @ref QDMI_ERROR_INVALIDARGUMENT if @p query or @p status is @c NULL. + * @return @ref QDMI_ERROR_PERMISSIONDENIED if the device does not allow using + * the @ref device_telemetrysensor_query_interface + * "client telemetry sensor query interface" for the device in the current + * session. + * @return @ref QDMI_ERROR_FATAL if the telemetry sensor query status could + * not be checked. + */ +int QDMI_device_telemetrysensor_query_check_status( + QDMI_Device_TelemetrySensor_Query query, + QDMI_TelemetrySensor_Query_Status *status); +/** + * @brief Wait for a telemetry sensor query to finish. + * @details This function blocks until the telemetry sensor query has either + * finished, has been canceled, or the timeout has been reached. + * @param[in] query The telemetry sensor query to wait for. Must not be @c + * NULL. + * @param[in] timeout The timeout in seconds. + * If this is zero, the function waits indefinitely until the job has finished. + * @return @ref QDMI_SUCCESS if the telemetry sensor query is finished or + * canceled. + * @return @ref QDMI_ERROR_INVALIDARGUMENT if @p query is @c NULL. + * @return @ref QDMI_ERROR_PERMISSIONDENIED if the device does not allow using + * the @ref device_telemetrysensor_query_interface + * "device telemetry sensor query interface" for the current session. + * @return @ref QDMI_ERROR_TIMEOUT if @p timeout is not zero and the job did not + * finish within the specified time. + * @return @ref QDMI_ERROR_FATAL if the telemetry sensor query could not be + * waited for and this function returns before the telemetry sensor query has + * finished or has been canceled. + */ +int QDMI_device_telemetrysensor_query_wait( + QDMI_Device_TelemetrySensor_Query query, size_t timeout); + +/** + * @brief Retrieve the results of a telemetry sensor query. + * @param[in] query The telemetry sensor query to retrieve the results from. + * Must not be @c NULL. + * @param[in] result The result to retrieve. Must be one of the values specified + * for @ref QDMI_TelemetrySensor_Query_Result. + * @param[in] size The size of the buffer pointed to by @p data in bytes. Must + * be greater or equal to the size of the return type specified for the @ref + * QDMI_TelemetrySensor_Query_Result @p result, except when @p data is @c + * NULL, in which case it is ignored. + * @param[out] data A pointer to the memory location where the results will be + * stored. If this is @c NULL, it is ignored. + * @param[out] size_ret The actual size of the data being queried in bytes. If + * this is @c NULL, it is ignored. + * @return @ref QDMI_SUCCESS if the device supports the specified result and, + * when @p data is not @c NULL, the results were successfully retrieved. + * @return @ref QDMI_ERROR_BADSTATE if the @p query has not finished or was + * canceled. + * @return @ref QDMI_ERROR_INVALIDARGUMENT if + * - @p query is @c NULL, + * - @p result is invalid, or + * - @p data is not @c NULL and @p size is smaller than the size of the data + * being queried. + * @return @ref QDMI_ERROR_PERMISSIONDENIED if the device does not allow using + * the @ref device_telemetrysensor_query_interface + * "device telemetry sensor query interface" for the current session. + * @return @ref QDMI_ERROR_FATAL if an error occurred during the retrieval. + * + * @remark Calling this function with @p data set to @c NULL is expected to + * allow checking if the device supports the specified result without + * retrieving the result and without the need to provide a buffer for the + * result. + * Additionally, the size of the buffer required to retrieve the result is + * returned in @p size_ret if @p size_ret is not @c NULL. + * See the @ref QDMI_telemetrysensor_query_get_results documentation for an + * example. + */ +int QDMI_device_telemetrysensor_query_get_results( + QDMI_Device_TelemetrySensor_Query query, + QDMI_TelemetrySensor_Query_Result result, size_t size, void *data, + size_t *size_ret); +/** + * @brief Free a telemetry sensor query. + * @details Free the resources associated with a telemetry sensor query. + * Using a telemetry sensor query handle after it has been freed is undefined + * behavior. + * @param[in] query The telemetry sensor query to free. + */ +void QDMI_device_telemetrysensor_query_free( + QDMI_Device_TelemetrySensor_Query query); + +/** @} */ // end of device_telemetrysensor_query_interface + /** @} */ // end of device_interface // NOLINTEND(performance-enum-size,modernize-use-using,modernize-redundant-void-arg) diff --git a/include/qdmi/types.h b/include/qdmi/types.h index 5bdd1c9b..f9bec388 100644 --- a/include/qdmi/types.h +++ b/include/qdmi/types.h @@ -71,6 +71,26 @@ typedef struct QDMI_Site_impl_d *QDMI_Site; */ typedef struct QDMI_Operation_impl_d *QDMI_Operation; +/** + * @brief A handle for a telemetry sensor. + * @details An opaque pointer to an implementation of the QDMI telemetry + * sensor concept. The environment can affect the and measurement results + * of quantum devices. Therefore, the environment is closely monitored by + * telemetry sensors. A telemetry sensor generally represents any sensor whose + * recorded data can be queried. There might be sensors for temperature, noise, + * etc. Each implementation of the @ref device_interface "QDMI Device Interface" + * defines the actual implementation of the concept. + * + * A simple example of an implementation is a struct that merely contains the + * telemetry sensor ID, which can be used to identify the site. + * ``` + * struct QDMI_TelemetrySensor_impl_d { + * char* id; + * }; + * ``` + */ +typedef struct QDMI_TelemetrySensor_impl_d *QDMI_TelemetrySensor; + // NOLINTEND(modernize-use-using) #ifdef __cplusplus diff --git a/test/test_qdmi.cpp b/test/test_qdmi.cpp index 28524d6e..b0105e76 100644 --- a/test/test_qdmi.cpp +++ b/test/test_qdmi.cpp @@ -25,6 +25,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include #include #include +#include #include #include #include @@ -1123,3 +1124,100 @@ TEST_P(QDMIImplementationTest, QueryPulseSupportLevel) { EXPECT_EQ(ret, QDMI_SUCCESS); EXPECT_EQ(pulse_support_level, QDMI_DEVICE_PULSE_SUPPORT_LEVEL_NONE); } + +TEST_P(QDMIImplementationTest, QueryEveryTelemetryProperties) { + + const auto fomac = FoMaC(device); + + auto telemetries = fomac.get_telemetry_sensors(); + + ASSERT_GT(telemetries.size(), 0); + + for (const auto &telemetry : telemetries) { + + auto telemetry_id = fomac.get_telemetry_id(telemetry); + EXPECT_STRNE(telemetry_id.c_str(), ""); + + auto telemetry_unit = fomac.get_telemetry_unit(telemetry); + EXPECT_STRNE(telemetry_unit.c_str(), ""); + + auto sampling_rate = fomac.get_telemetry_sampling_rate(telemetry); + EXPECT_GT(sampling_rate, 0); + } +} + +TEST_P(QDMIImplementationTest, TelemetryQuery) { + if (mode == TEST_SESSION_MODE::READONLY) { + GTEST_SKIP() << "Skipping test for read-only session"; + } + + const auto fomac = FoMaC(device); + + const std::vector telemetry_sensors = + fomac.get_telemetry_sensors(); + + ASSERT_GT(telemetry_sensors.size(), 0); + + for (QDMI_TelemetrySensor telemetry_sensor : telemetry_sensors) { + QDMI_TelemetrySensor_Query query = nullptr; + QDMI_TelemetrySensor_Query_Status status = + QDMI_TELEMETRYSENSOR_QUERY_STATUS_CREATED; + + time_t start_timestamp = time(nullptr); + time_t end_timestamp = time(nullptr) + 600; // 10 minutes later + + EXPECT_EQ(QDMI_device_create_telemetrysensor_query( + device, &telemetry_sensor, &query), + QDMI_SUCCESS); + + EXPECT_EQ(QDMI_telemetrysensor_query_set_parameter( + query, QDMI_TELEMETRYSENSOR_QUERY_PARAMETER_STARTTIME, + sizeof(time_t), &start_timestamp), + QDMI_SUCCESS); + + EXPECT_EQ(QDMI_telemetrysensor_query_set_parameter( + query, QDMI_TELEMETRYSENSOR_QUERY_PARAMETER_ENDTIME, + sizeof(time_t), &end_timestamp), + QDMI_SUCCESS); + + EXPECT_EQ(QDMI_telemetrysensor_query_submit(query), QDMI_SUCCESS); + + EXPECT_EQ(QDMI_telemetrysensor_query_wait(query, 0), QDMI_SUCCESS); + + EXPECT_EQ(QDMI_telemetrysensor_query_check_status(query, &status), + QDMI_SUCCESS); + + EXPECT_EQ(status, QDMI_TELEMETRYSENSOR_QUERY_STATUS_DONE); + + size_t timestamps_size = 0; + EXPECT_EQ(QDMI_telemetrysensor_query_get_results( + query, QDMI_TELEMETRYSENSOR_QUERY_RESULT_TIMESTAMPS, 0, + nullptr, ×tamps_size), + QDMI_SUCCESS); + + size_t timestamp_length = timestamps_size / sizeof(time_t); + std::vector timestamps(timestamp_length); + + EXPECT_EQ(QDMI_telemetrysensor_query_get_results( + query, QDMI_TELEMETRYSENSOR_QUERY_RESULT_TIMESTAMPS, + timestamps_size, static_cast(timestamps.data()), + nullptr), + QDMI_SUCCESS); + + size_t size_values = 0; + EXPECT_EQ(QDMI_telemetrysensor_query_get_results( + query, QDMI_TELEMETRYSENSOR_QUERY_RESULT_VALUES, 0, nullptr, + &size_values), + QDMI_SUCCESS); + + size_t values_length = timestamps_size / sizeof(time_t); + std::vector values(values_length); + + EXPECT_EQ(QDMI_telemetrysensor_query_get_results( + query, QDMI_TELEMETRYSENSOR_QUERY_RESULT_VALUES, size_values, + values.data(), nullptr), + QDMI_SUCCESS); + + QDMI_telemetrysensor_query_free(query); + } +}