Skip to content
Open
Show file tree
Hide file tree
Changes from 46 commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
0887df6
✨ Initial QDMI Environment impl
kayaercument Mar 24, 2025
302c416
🎨 pre-commit fixes
pre-commit-ci[bot] Mar 24, 2025
3aab49e
🎨 renaming definitions for qdmi environment
kayaercument Apr 4, 2025
52bd8d7
🎨 pre-commit fixes
pre-commit-ci[bot] Apr 4, 2025
49cc0bf
🚚 rename environment to environmentvariable
kayaercument Apr 8, 2025
3ba8a92
✨ Implemention of QDMI Enviroment functions in example C device
kayaercument Apr 8, 2025
6f658f6
🎨 pre-commit fixes
pre-commit-ci[bot] Apr 8, 2025
25abdd4
✏️ fix typo
kayaercument Apr 8, 2025
98971ba
✨ additional functions and their implementations in example c device
kayaercument Apr 9, 2025
98a8659
🎨 pre-commit fixes
pre-commit-ci[bot] Apr 9, 2025
c2b2935
✨ additional definations in the client interface
kayaercument Apr 9, 2025
f88b60c
🎨 pre-commit fixes
pre-commit-ci[bot] Apr 9, 2025
c1591fe
✨ Implemention of QDMI Enviroment functions in example CXX device
kayaercument Apr 9, 2025
4e7b8f8
🎨 pre-commit fixes
pre-commit-ci[bot] Apr 9, 2025
bd849ae
✨ implementation of qdmi environment function in example driver, foma…
kayaercument Apr 9, 2025
3858563
🎨 pre-commit fixes
pre-commit-ci[bot] Apr 9, 2025
3929d0a
🎨 minor changes
kayaercument Apr 9, 2025
16afe77
🎨 pre-commit fixes
pre-commit-ci[bot] Apr 9, 2025
9bbc775
Merge branch 'develop' into 152-env-prop
burgholzer May 2, 2025
7b3e8df
✏️ initial documentation for qdmi_environment
kayaercument May 9, 2025
ba5a676
🎨 pre-commit fixes
pre-commit-ci[bot] May 9, 2025
e67355f
✏️ updates on documentation
kayaercument May 19, 2025
67312db
Merge branch 'Munich-Quantum-Software-Stack:develop' into 152-env-prop
kayaercument Jun 5, 2025
94e4b25
✏️ Better naming
kayaercument Jun 13, 2025
20a2841
🎨 pre-commit fixes
pre-commit-ci[bot] Jun 13, 2025
e239964
🎨 timeout parameter for environmentsensor_query_wait functions
kayaercument Jun 16, 2025
7474cbe
🎨 consisting parameter naming
kayaercument Jun 16, 2025
83a6b18
Merge branch 'develop' into 152-env-prop
kayaercument Jun 16, 2025
c71b2c3
🚨 fix linter warnings
kayaercument Jun 16, 2025
d0db550
🚨 Fixing linter warnings
kayaercument Jun 16, 2025
0e9bcb2
🎨 pre-commit fixes
pre-commit-ci[bot] Jun 16, 2025
d2218d5
🚨 linter fix
kayaercument Jun 16, 2025
889b27c
🚨 lint fix
kayaercument Jun 16, 2025
a83cbf4
🎨 pre-commit fixes
pre-commit-ci[bot] Jun 16, 2025
709ac33
Merge branch 'develop' into 152-env-prop
kayaercument Jun 17, 2025
4572c14
Merge remote-tracking branch 'upstream/develop' into 152-env-prop
Jul 31, 2025
123d2e6
🩹 minor fix
Jul 31, 2025
f562d03
Apply suggestions from code review
kayaercument Aug 1, 2025
64ea415
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 1, 2025
6df7dee
📝 improvements on the documentation
kayaercument Aug 4, 2025
e3e6694
🎨 renaming QDMI_Environment to QDMI_Telemetry
kayaercument Aug 5, 2025
04a8218
Merge branch 'develop' into 152-env-prop
kayaercument Aug 5, 2025
0bda557
🎨 minor change in example
kayaercument Aug 5, 2025
56ba00d
✏️ fix minor typos
kayaercument Aug 5, 2025
aff6f1e
📝 minor documentation extension
kayaercument Aug 5, 2025
10710d0
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 5, 2025
e305c46
Apply suggestions from code review
kayaercument Aug 13, 2025
9f38ad9
🎨 improvements based on the suggestions
kayaercument Aug 14, 2025
248a112
Merge remote-tracking branch 'upstream/develop' into 152-env-prop
kayaercument Aug 14, 2025
aba1df1
🎨 pre-commit fixes
pre-commit-ci[bot] Aug 14, 2025
80cd577
🚨 lint fix
kayaercument Aug 14, 2025
ab49391
Merge branch 'develop' into 152-env-prop
kayaercument Aug 18, 2025
3234155
Merge branch 'develop' into 152-env-prop
burgholzer Aug 29, 2025
2f2e03e
Merge branch 'develop' into 152-env-prop
burgholzer Aug 29, 2025
4ef85b5
⚗️ try with codecov token
burgholzer Aug 29, 2025
0202474
Merge branch 'develop' into 152-env-prop
burgholzer Aug 29, 2025
34718bc
🎨 minor refactor
kayaercument Sep 3, 2025
5a121c5
💚 codecov fix attempt using oidc
kayaercument Sep 17, 2025
f8eb819
💚 codecov fix attempt usind oidc
kayaercument Sep 17, 2025
d2f3321
Merge branch 'develop' into 152-env-prop
kayaercument Sep 17, 2025
8c747b3
Merge branch 'develop' into 152-env-prop
burgholzer Sep 17, 2025
3a3576d
🎨 Clean-up example implementation
ystade Sep 26, 2025
35dc853
🎨 Minor improvements in example driver
ystade Sep 26, 2025
c7ffdc3
⏪ revert codecov fix attempt
kayaercument Sep 30, 2025
e3467e6
✏️ fix typos in the documents
kayaercument Sep 30, 2025
b4c416d
📝 additional documentations
kayaercument Sep 30, 2025
d61e4e7
🚨 fix lint warning
kayaercument Sep 30, 2025
abe1b30
✏️ fix typos
kayaercument Sep 30, 2025
891abf3
✏️ corrects weird line breaks
kayaercument Sep 30, 2025
abbbbd5
🎨 improve consistent usage
kayaercument Sep 30, 2025
c7432aa
Apply suggestions from code review
kayaercument Sep 30, 2025
ecc8fcd
🎨 pre-commit fixes
pre-commit-ci[bot] Sep 30, 2025
b88ff2f
🎨 use ctime instead of chrono
kayaercument Oct 1, 2025
72cf9eb
🎨 minor change
kayaercument Oct 1, 2025
ddd73a1
Merge branch 'develop' into 152-env-prop
burgholzer Oct 8, 2025
80628dd
Merge branch 'develop' into 152-env-prop
burgholzer Oct 29, 2025
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
13 changes: 13 additions & 0 deletions cmake/prefix_defs.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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_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
255 changes: 255 additions & 0 deletions examples/device/device.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,14 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <algorithm>
#include <array>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <functional>
#include <iterator>
#include <limits>
Expand Down Expand Up @@ -77,6 +81,24 @@ struct CXX_QDMI_Operation_impl_d {
std::string name;
};

struct CXX_QDMI_TelemetrySensor_impl_d {
std::string id;
std::string unit;
std::chrono::seconds sampling_rate;
};

struct CXX_QDMI_Device_TelemetrySensor_Query_impl_d {
std::chrono::time_point<std::chrono::system_clock> start_time;
std::chrono::time_point<std::chrono::system_clock> end_time;
size_t timeout{};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could that be seconds, i.e.

Suggested change
size_t timeout{};
[size_t](std::chrono::seconds) timeout{};

?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
size_t timeout{};
size_t timeout;

and size_t (same as std::chrono::seconds) does not need a {} initialiser.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe it cannot. However, we can std::chrono::seconds instead of size_t, leading to additional casting in the CXX_QDMI_device_telemetrysensor_query_wait. If you suggest that it will improve the readability of the code, we can change it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Done

CXX_QDMI_TelemetrySensor telemetry_sensor{};
std::vector<std::chrono::time_point<std::chrono::system_clock>>
result_timestamps;
std::vector<float> result_values;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a specific reason for float? For most others floating point values, we use double. I do not have a strong opinion here, just want to raise it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make it consistent ✅

size_t result_length{};
QDMI_TelemetrySensor_Query_Status status{};
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
size_t result_length{};
QDMI_TelemetrySensor_Query_Status status{};
size_t result_length;
QDMI_TelemetrySensor_Query_Status status;

If I am not mistaken, if you want to initialize those members, you need to assign values, i.e., 0 for the length and some enum value for the status. However, I think it should be just fine without {}.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even though they need {}, clang-tidy raises a cppcoreguidelines-pro-type-member-init warning.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Done

};

namespace {
/**
* @brief Static function to maintain the device state.
Expand Down Expand Up @@ -159,6 +181,12 @@ constexpr CXX_QDMI_Site_impl_d SITE4{4};
constexpr std::array<const CXX_QDMI_Site_impl_d *, 5> CXX_DEVICE_SITES = {
&SITE0, &SITE1, &SITE2, &SITE3, &SITE4};

const CXX_QDMI_TelemetrySensor_impl_d ENVSEN{"t4k", "K",
std::chrono::duration<int>{60}};

constexpr std::array<const CXX_QDMI_TelemetrySensor_impl_d *, 1>
CXX_DEVICE_TELEMETRYSENSORS{&ENVSEN};

constexpr std::array<const CXX_QDMI_Site_impl_d *, 20>
// clang-format off
DEVICE_COUPLING_MAP = {
Expand Down Expand Up @@ -773,6 +801,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)
Expand Down Expand Up @@ -872,3 +903,227 @@ 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,
QDMI_TelemetrySensor_Property prop, 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,
long int, telemetry_sensor->sampling_rate.count(),
prop, size, value, size_ret)
return QDMI_ERROR_NOTSUPPORTED;
}

int CXX_QDMI_device_session_create_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 = std::chrono::system_clock::now();
(*query)->end_time = std::chrono::system_clock::now();

return QDMI_SUCCESS;
}

int CXX_QDMI_device_telemetrysensor_query_set_parameter(
CXX_QDMI_Device_TelemetrySensor_Query query,
QDMI_Device_TelemetrySensor_Query_Parameter param, 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: {
query->start_time = std::chrono::system_clock::from_time_t(
*static_cast<const time_t *>(value));
return QDMI_SUCCESS;
}
case QDMI_DEVICE_TELEMETRYSENSOR_QUERY_PARAMETER_ENDTIME: {
query->end_time = std::chrono::system_clock::from_time_t(
*static_cast<const time_t *>(value));
return QDMI_SUCCESS;
}

case QDMI_DEVICE_TELEMETRYSENSOR_QUERY_PARAMETER_TELEMETRYSENSOR: {
query->telemetry_sensor =
*(static_cast<const CXX_QDMI_TelemetrySensor *>(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) {
return QDMI_ERROR_INVALIDARGUMENT;
}

// here, the actual submission.

// for demonstration purposes

// Clang-tidy generates a warning due to a known bug
// https://github.com/llvm/llvm-project/issues/98122
auto time_difference =
std::chrono::round<std::chrono::seconds>( // NOLINT(misc-include-cleaner)
query->end_time - query->start_time);

auto sampling_rate = query->telemetry_sensor->sampling_rate;

auto result_length =
static_cast<size_t>(time_difference.count() / sampling_rate.count());

query->result_timestamps.clear();
query->result_timestamps.reserve(result_length);

query->result_values.clear();
query->result_values.reserve(result_length);

query->result_length = result_length;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the attribute result_length required, or would result_values.size() suffice in the end?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed from CXX_QDMI_Device_TelemetrySensor_Query_impl_d as well. ✅


for (unsigned int i = 0; i < result_length; i++) {
auto duration_to_add =
std::chrono::duration_cast<std::chrono::system_clock::duration>(
query->telemetry_sensor->sampling_rate * i);
auto next_time = query->start_time + duration_to_add;
query->result_timestamps.emplace_back(next_time);
query->result_values[i] =
static_cast<float>(rand()) / (static_cast<float>(RAND_MAX / 100));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think for the random number generation of float in a given interval, there is a more elegant way:

    // Create a random device and seed the generator
    std::random_device rd;
    std::mt19937 gen(rd());

    // Define the range: e.g., between 0.0 and 1.0
    std::uniform_real_distribution<> dis(0.0, 1.0);

    // all variables above could be implemented centrally as part of the `device_session`.

    // Generate a random float
    double random_value = dis(gen);

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done ✅

}

return QDMI_SUCCESS;
}

int CXX_QDMI_device_telemetrysensor_query_get_results(
CXX_QDMI_Device_TelemetrySensor_Query query,
QDMI_TelemetrySensor_Query_Result result, 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 req_size = query->result_length;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very minor: Maybe it is obvious but I cannot decipher what req stands for. Is there a more descriptive name?

Copy link
Collaborator Author

@kayaercument kayaercument Aug 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Renamed as required_size

switch (result) {
case QDMI_TELEMETRYSENSOR_QUERY_RESULT_TIMESTAMPS:
req_size *= sizeof(time_t);
if (data != nullptr) {
if (size < req_size) {
return QDMI_ERROR_INVALIDARGUMENT;
}
auto *data_ptr = static_cast<time_t *>(data);
for (size_t i = 0; i < query->result_length; i++) {
data_ptr[i] =
std::chrono::system_clock::to_time_t(query->result_timestamps[i]);
}
}

if ((size_ret) != nullptr) {
*(size_ret) = req_size;
}
return QDMI_SUCCESS;
case QDMI_TELEMETRYSENSOR_QUERY_RESULT_VALUES:

req_size *= sizeof(float);
if (data != nullptr) {
if (size < req_size) {
return QDMI_ERROR_INVALIDARGUMENT;
}
memcpy(data, query->result_values.data(), req_size);
}
if ((size_ret) != nullptr) {
*(size_ret) = req_size;
}
return QDMI_SUCCESS;

default:
return QDMI_ERROR_NOTSUPPORTED;
}

return QDMI_SUCCESS;
}

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, 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;
}
Loading
Loading