diff --git a/libuavcan/include/uavcan/node/generic_publisher.hpp b/libuavcan/include/uavcan/node/generic_publisher.hpp index d1c04e56e0..a2844e7932 100644 --- a/libuavcan/include/uavcan/node/generic_publisher.hpp +++ b/libuavcan/include/uavcan/node/generic_publisher.hpp @@ -67,6 +67,12 @@ public: sender_.allowAnonymousTransfers(); } + /** + * Priority of outgoing transfers. + */ + TransferPriority getPriority() const { return sender_.getPriority(); } + void setPriority(const TransferPriority prio) { sender_.setPriority(prio); } + INode& getNode() const { return node_; } }; diff --git a/libuavcan/include/uavcan/node/publisher.hpp b/libuavcan/include/uavcan/node/publisher.hpp index edd3674900..a79ba0ca5e 100644 --- a/libuavcan/include/uavcan/node/publisher.hpp +++ b/libuavcan/include/uavcan/node/publisher.hpp @@ -65,24 +65,6 @@ public: return BaseType::publish(message, TransferTypeMessageBroadcast, NodeID::Broadcast, tid); } - /** - * Returns priority of outgoing transfers. - */ - TransferPriority getPriority() const - { - return BaseType::getTransferSender().getPriority(); - } - - /** - * Allows to change the priority of outgoing transfers. - * Note that only High, Normal and Low priorities can be used; Service priority is not available for messages. - * If the priority value is invalid, an assertion failure will be generated, and the value will not be updated. - */ - void setPriority(const TransferPriority prio) - { - BaseType::getTransferSender().setPriority(prio); - } - static MonotonicDuration getDefaultTxTimeout() { return MonotonicDuration::fromMSec(10); } /** @@ -97,6 +79,8 @@ public: using BaseType::getMaxTxTimeout; using BaseType::getTxTimeout; using BaseType::setTxTimeout; + using BaseType::getPriority; + using BaseType::setPriority; using BaseType::getNode; }; diff --git a/libuavcan/include/uavcan/node/service_client.hpp b/libuavcan/include/uavcan/node/service_client.hpp index 2589be1f8f..f2c388d3be 100644 --- a/libuavcan/include/uavcan/node/service_client.hpp +++ b/libuavcan/include/uavcan/node/service_client.hpp @@ -208,6 +208,9 @@ public: * reference invalidates once the callback returns. If you want to use this object after the callback execution, * you need to copy it somewhere. * + * Note that by default, service client objects use lower priority than message publishers. Use @ref setPriority() + * to override the default if necessary. + * * @tparam DataType_ Service data type. * * @tparam Callback_ Service response will be delivered through the callback of this type. @@ -303,6 +306,7 @@ public: , publisher_(node, getDefaultRequestTimeout()) , callback_(callback) { + setPriority(TransferPriority::MiddleLower); setRequestTimeout(getDefaultRequestTimeout()); #if UAVCAN_DEBUG UAVCAN_ASSERT(getRequestTimeout() == getDefaultRequestTimeout()); // Making sure default values are OK @@ -398,6 +402,14 @@ public: publisher_.setTxTimeout(timeout); request_timeout_ = max(timeout, publisher_.getTxTimeout()); // No less than TX timeout } + + /** + * Priority of outgoing request transfers. + * The remote server is supposed to use the same priority for the response, but it's not guaranteed by + * the specification. + */ + TransferPriority getPriority() const { return publisher_.getPriority(); } + void setPriority(const TransferPriority prio) { publisher_.setPriority(prio); } }; // ---------------------------------------------------------------------------- diff --git a/libuavcan/include/uavcan/transport/transfer.hpp b/libuavcan/include/uavcan/transport/transfer.hpp index 411c8eb135..1edaf4368c 100644 --- a/libuavcan/include/uavcan/transport/transfer.hpp +++ b/libuavcan/include/uavcan/transport/transfer.hpp @@ -35,6 +35,7 @@ public: /// This priority is used by default static const TransferPriority Default; + static const TransferPriority MiddleLower; static const TransferPriority OneHigherThanLowest; static const TransferPriority OneLowerThanHighest; diff --git a/libuavcan/src/transport/uc_transfer.cpp b/libuavcan/src/transport/uc_transfer.cpp index 4bf0395228..d0c0f981d9 100644 --- a/libuavcan/src/transport/uc_transfer.cpp +++ b/libuavcan/src/transport/uc_transfer.cpp @@ -16,6 +16,7 @@ const uint8_t TransferPriority::NumericallyMax; const uint8_t TransferPriority::NumericallyMin; const TransferPriority TransferPriority::Default((1U << BitLen) / 2); +const TransferPriority TransferPriority::MiddleLower((1U << BitLen) / 2 + (1U << BitLen) / 4); const TransferPriority TransferPriority::OneHigherThanLowest(NumericallyMax - 1); const TransferPriority TransferPriority::OneLowerThanHighest(NumericallyMin + 1); diff --git a/libuavcan/test/node/service_client.cpp b/libuavcan/test/node/service_client.cpp index 8306ea1c16..9efe023e3a 100644 --- a/libuavcan/test/node/service_client.cpp +++ b/libuavcan/test/node/service_client.cpp @@ -387,6 +387,59 @@ TEST(ServiceClient, Empty) } +TEST(ServiceClient, Priority) +{ + InterlinkedTestNodesWithSysClock nodes; + + // Type registration + uavcan::GlobalDataTypeRegistry::instance().reset(); + uavcan::DefaultDataTypeRegistrator _registrator; + + // Initializing + typedef uavcan::ServiceClient::Binder > ClientType; + ServiceCallResultHandler handler; + ClientType client(nodes.b); + client.setCallback(handler.bind()); + + // Calling + root_ns_a::EmptyService::Request request; + + client.setPriority(0); + ASSERT_LT(0, client.call(1, request)); // OK + + client.setPriority(10); + ASSERT_LT(0, client.call(1, request)); // OK + + client.setPriority(20); + ASSERT_LT(0, client.call(1, request)); // OK + + client.setPriority(31); + ASSERT_LT(0, client.call(1, request)); // OK + + // Validating + ASSERT_EQ(4, nodes.can_a.read_queue.size()); + + uavcan::Frame frame; + + ASSERT_TRUE(frame.parse(nodes.can_a.read_queue.front())); + nodes.can_a.read_queue.pop(); + ASSERT_EQ(0, frame.getPriority().get()); + + ASSERT_TRUE(frame.parse(nodes.can_a.read_queue.front())); + nodes.can_a.read_queue.pop(); + ASSERT_EQ(10, frame.getPriority().get()); + + ASSERT_TRUE(frame.parse(nodes.can_a.read_queue.front())); + nodes.can_a.read_queue.pop(); + ASSERT_EQ(20, frame.getPriority().get()); + + ASSERT_TRUE(frame.parse(nodes.can_a.read_queue.front())); + nodes.can_a.read_queue.pop(); + ASSERT_EQ(31, frame.getPriority().get()); +} + + TEST(ServiceClient, Sizes) { using namespace uavcan;