.. _program_listing_file_src_iio_node.cpp: Program Listing for File iio_node.cpp ===================================== |exhale_lsh| :ref:`Return to documentation for file ` (``src/iio_node.cpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp // Copyright 2025 Analog Devices, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "adi_iio/iio_node.hpp" #include "adi_iio/iio_attr_topic.hpp" #include "adi_iio/iio_buffer.hpp" #include using namespace std::chrono_literals; #define MAX_ATTR_SIZE 4095 /* BufferTopic.srv string buffer_path int buffer_size bool enable --- bool success string message parameter ---- "URI" */ IIONode::IIONode() : Node("adi_iio_node") { m_initialized = false; this->declare_parameter("uri", "local:"); m_uri = this->get_parameter("uri").as_string(); m_ctx = iio_create_context_from_uri(m_uri.c_str()); if (m_ctx != nullptr) { RCLCPP_INFO( rclcpp::get_logger( "rclcpp"), "creating context %p from uri %s", (void *)m_ctx, m_uri.c_str()); m_initialized = true; } else { RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "cannot create context from uri %s", m_uri.c_str()); } } void IIONode::initBuffers() { for (unsigned int i = 0; i < iio_context_get_devices_count(m_ctx); i++) { iio_device * dev = iio_context_get_device(m_ctx, i); std::string dev_name = iio_device_get_name(dev); for (unsigned int j = 0; j < iio_device_get_channels_count(dev); j++) { iio_channel * ch = iio_device_get_channel(dev, j); if (!iio_channel_is_output(ch) && iio_channel_is_scan_element(ch)) { m_bufferMap.insert( {dev_name, std::make_shared( std::dynamic_pointer_cast(shared_from_this()), dev_name)}); break; } } } } IIONode::~IIONode() { } bool IIONode::initialized() { return m_initialized; } std::string IIONode::convertAttrPathToTopicName(std::string path) { std::replace(path.begin(), path.end(), '-', '_'); return path; } bool IIONode::rwAttrPath(std::string path, std::string & result, bool write, std::string value) { bool ret = false; std::string str = path; std::stringstream ss(str); std::string segment; std::vector segments; iio_device * dev = nullptr; iio_channel * ch = nullptr; while (std::getline(ss, segment, '/')) { segments.push_back(segment); // Push each part of the string into the vector } char * val; char attr_val[MAX_ATTR_SIZE]; int ret1; switch (segments.size()) { case 1: // context_attribute val = const_cast(iio_context_get_attr_value(m_ctx, segments[0].c_str())); if (val) { ret = true; result = val; RCLCPP_INFO( rclcpp::get_logger("rclcpp"), "read context attribute \"%s\" with value \"%s\"", segments[0].c_str(), val); } else { ret = false; result = ""; RCLCPP_WARN( rclcpp::get_logger( "rclcpp"), "could not find context attribute \"%s\"", segments[0].c_str()); } if (write) { ret = false; RCLCPP_WARN(rclcpp::get_logger("rclcpp"), "context attributes cannot be written"); } break; case 2: // device_attribute dev = iio_context_find_device(m_ctx, segments[0].c_str()); if (!dev) { RCLCPP_WARN( rclcpp::get_logger("rclcpp"), "could not find device \"%s\"", segments[0].c_str()); break; } if (write) { ret1 = iio_device_attr_write(dev, segments[1].c_str(), value.c_str()); if (ret1 > 0) { RCLCPP_INFO( rclcpp::get_logger("rclcpp"), "wrote device attribute \"%s\" from device \"%s\" with value \"%s\"", segments[1].c_str(), segments[0].c_str(), value.c_str()); } else { result = strerror(-ret1); ret = false; RCLCPP_WARN( rclcpp::get_logger("rclcpp"), "could not write attribute \"%s\" in device \"%s\" with value \"%s\" - errno %d - %s", segments[1].c_str(), segments[0].c_str(), value.c_str(), ret1, result.c_str()); break; } } ret1 = iio_device_attr_read(dev, segments[1].c_str(), attr_val, MAX_ATTR_SIZE); if (ret1 > 0) { result = attr_val; ret = true; RCLCPP_INFO( rclcpp::get_logger( "rclcpp"), "read device attribute \"%s\" from device \"%s\" with value \"%s\"", segments[1].c_str(), segments[0].c_str(), attr_val); } else { result = strerror(-ret1); ret = false; RCLCPP_WARN( rclcpp::get_logger( "rclcpp"), "could not read attribute \"%s\" in device \"%s\" - errno %d - %s", segments[1].c_str(), segments[0].c_str(), ret1, result.c_str()); } break; case 3: // channel_attribute dev = iio_context_find_device(m_ctx, segments[0].c_str()); if (!dev) { RCLCPP_WARN( rclcpp::get_logger("rclcpp"), "could not find device \"%s\"", segments[0].c_str()); break; } if (segments[1].find("input_") == 0) { ch = iio_device_find_channel(dev, segments[1].substr(strlen("input_")).c_str(), false); } else if (segments[1].find("output_") == 0) { ch = iio_device_find_channel(dev, segments[1].substr(strlen("output_")).c_str(), true); } else { ch = iio_device_find_channel(dev, segments[1].c_str(), false); if (!ch) { ch = iio_device_find_channel(dev, segments[1].c_str(), true); } } if (!ch) { RCLCPP_WARN( rclcpp::get_logger("rclcpp"), "could not find channel \"%s\"", segments[1].c_str()); break; } if (write) { ret1 = iio_channel_attr_write(ch, segments[2].c_str(), value.c_str()); if (ret1 > 0) { RCLCPP_INFO( rclcpp::get_logger("rclcpp"), "wrote channel attribute \"%s\" from channel \"%s\" device \"%s\" with value \"%s\"", segments[2].c_str(), segments[1].c_str(), segments[0].c_str(), value.c_str()); } else { result = strerror(-ret1); ret = false; RCLCPP_WARN( rclcpp::get_logger( "rclcpp"), "could not write attribute \"%s\" from channel \"%s\" device \"%s\" with value \"%s\"- errno %d " "- %s", segments[2].c_str(), segments[1].c_str(), segments[0].c_str(), value.c_str(), ret1, result.c_str()); break; } } ret1 = iio_channel_attr_read(ch, segments[2].c_str(), attr_val, MAX_ATTR_SIZE); if (ret1 > 0) { result = attr_val; ret = true; RCLCPP_INFO( rclcpp::get_logger("rclcpp"), "read channel attribute \"%s\" from channel \"%s\" device \"%s\" with value \"%s\"", segments[2].c_str(), segments[1].c_str(), segments[0].c_str(), attr_val); } else { result = strerror(-ret1); ret = false; RCLCPP_WARN( rclcpp::get_logger("rclcpp"), "could not read attribute \"%s\" from channel \"%s\" device \"%s\" - errno %d - %s", segments[2].c_str(), segments[1].c_str(), segments[0].c_str(), ret1, result.c_str()); } break; default: result = "Service requires attr_path"; ret = false; break; } return ret; } void IIONode::attrReadSrv( const std::shared_ptr request, // CHANGE std::shared_ptr response) { RCLCPP_INFO( rclcpp::get_logger( "rclcpp"), "Service request read attr: %s", request->attr_path.c_str()); std::string result; response->success = rwAttrPath(request->attr_path, result); response->message = result; } void IIONode::attrWriteSrv( const std::shared_ptr request, // CHANGE std::shared_ptr response) { RCLCPP_INFO( rclcpp::get_logger("rclcpp"), "Service request write attr %s value %s", request->attr_path.c_str(), request->value.c_str()); std::string result; response->success = rwAttrPath(request->attr_path, result, true, request->value); response->message = result; } /*AttrTopicEnable.srv string topic_name string attr_path int loop_rate int type --------------- bool success string message*/ void IIONode::attrEnableTopicSrv( const std::shared_ptr request, std::shared_ptr response) { RCLCPP_INFO( rclcpp::get_logger( "rclcpp"), "Service request enable topic %s with type %s with loop_rate %d Hz", request->attr_path.c_str(), request->attr_path.c_str(), request->loop_rate); std::string result; response->success = rwAttrPath(request->attr_path, result); response->message = result; std::string local_topic_name = request->topic_name; if (local_topic_name == "") { local_topic_name = convertAttrPathToTopicName(request->attr_path); } if (response->success) { if (m_attrTopicMap.find(local_topic_name) != m_attrTopicMap.end()) { m_attrTopicMap.erase(local_topic_name); } m_attrTopicMap.insert( {local_topic_name, std::make_shared( std::dynamic_pointer_cast(shared_from_this()), local_topic_name, request->attr_path, static_cast(request->type), request->loop_rate)}); response->success = true; response->message = "Success"; } } /* AttrTopicDisable.srv string topic_name --- bool success string message */ void IIONode::attrDisableTopicSrv( const std::shared_ptr request, std::shared_ptr response) { RCLCPP_INFO( rclcpp::get_logger( "rclcpp"), "Service request disable topic %s ", request->topic_name.c_str()); std::string local_topic_name = request->topic_name; local_topic_name = convertAttrPathToTopicName(request->topic_name); // for compatibility with enable if (m_attrTopicMap.find(local_topic_name) != m_attrTopicMap.end()) { m_attrTopicMap.erase(local_topic_name); response->success = true; response->message = "Success"; } else { response->success = false; response->message = "Topic not found"; } } void IIONode::buffRefillSrv( const std::shared_ptr request, std::shared_ptr response) { if (m_bufferMap.find(request->device_path) == m_bufferMap.end()) { response->success = false; response->message = "Buffer not found"; } else { std::string message; if (m_bufferMap[request->device_path]->topic_enabled()) { } else { response->success = m_bufferMap[request->device_path]->refill(message); response->message = message; } response->buffer = m_bufferMap[request->device_path]->data(); } } void IIONode::buffReadSrv( const std::shared_ptr request, std::shared_ptr response) { std::string channels; for (auto & channel : request->channels) { channels += channel + " "; } RCLCPP_INFO( rclcpp::get_logger("rclcpp"), "Service request buffer read %s - %s - %d samples", request->device_path.c_str(), channels.c_str(), request->samples_count); std::string message; std::shared_ptr buffer; if (m_bufferMap.find(request->device_path) == m_bufferMap.end()) { response->success = false; response->message = "Device or buffer not found"; return; } buffer = m_bufferMap[request->device_path]; buffer->destroyIIOBuffer(); buffer->set_samples_count(request->samples_count); buffer->set_channels(request->channels); response->success = buffer->createIIOBuffer(message); if (!response->success) { response->message = message; return; } response->success = buffer->refill(message); response->buffer = buffer->data(); response->message = message; } void IIONode::buffWriteSrv( const std::shared_ptr request, std::shared_ptr response) { std::string channels; for (auto & channel : request->channels) { channels += channel + " "; } RCLCPP_INFO( rclcpp::get_logger("rclcpp"), "Service request buffer read %s - %s - %d samples", request->device_path.c_str(), channels.c_str(), request->buffer.layout.dim[0].size); std::string message; std::shared_ptr buffer; if (m_bufferMap.find(request->device_path) == m_bufferMap.end()) { response->success = false; response->message = "Device or buffer not found"; return; } buffer = m_bufferMap[request->device_path]; buffer->destroyIIOBuffer(); buffer->set_samples_count(request->buffer.layout.dim[0].size); buffer->set_channels(request->channels); response->success = buffer->createIIOBuffer(message); if (!response->success) { response->message = message; return; } response->success = buffer->push(message, request->buffer); } void IIONode::buffCreateSrv( const std::shared_ptr request, std::shared_ptr response) { std::string channels; for (auto & channel : request->channels) { channels += channel + " "; } RCLCPP_INFO( rclcpp::get_logger("rclcpp"), "Service request buffer create %s - %s - %d samples", request->device_path.c_str(), channels.c_str(), request->samples_count); std::string message; std::shared_ptr buffer; if (m_bufferMap.find(request->device_path) == m_bufferMap.end()) { response->success = false; response->message = "Buffer not found"; } buffer = m_bufferMap[request->device_path]; buffer->destroyIIOBuffer(); buffer->set_samples_count(request->samples_count); buffer->set_channels(request->channels); response->success = buffer->createIIOBuffer(message); response->message = message; } void IIONode::buffDestroySrv( const std::shared_ptr request, std::shared_ptr response) { RCLCPP_INFO( rclcpp::get_logger( "rclcpp"), "Service request buffer destroy %s", request->device_path.c_str()); if (m_bufferMap.find(request->device_path) != m_bufferMap.end()) { if (m_bufferMap[request->device_path]->buffer()) { m_bufferMap[request->device_path]->destroyIIOBuffer(); response->success = true; response->message = "Success"; return; } } response->success = false; response->message = "Buffer not found"; } void IIONode::buffEnableTopicSrv( const std::shared_ptr request, std::shared_ptr response) { if (m_bufferMap.find(request->device_path) != m_bufferMap.end()) { m_bufferMap[request->device_path]->enableTopic(request->topic_name); response->success = true; response->message = "Success"; } else { response->success = false; response->message = "Buffer not found"; } } void IIONode::buffDisableTopicSrv( const std::shared_ptr request, std::shared_ptr response) { if (m_bufferMap.find(request->device_path) != m_bufferMap.end()) { m_bufferMap[request->device_path]->disableTopic(); response->success = true; response->message = "Success"; } else { response->success = false; response->message = "Buffer not found"; } } std::string IIONode::uri() { return m_uri; } iio_context * IIONode::ctx() { return m_ctx; }