mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-31 11:01:36 +08:00
GetDataTypeInfo now can be requested either by dtid/id, or by name
This commit is contained in:
@@ -1,13 +1,23 @@
|
|||||||
#
|
#
|
||||||
# Get the implementation details of a given data type.
|
# Get the implementation details of a given data type.
|
||||||
#
|
#
|
||||||
|
# Request is interpreted as follows:
|
||||||
|
# - If the field 'name' is empty, the fields 'kind' and 'id' will be used to identify the data type.
|
||||||
|
# - If the field 'name' is non-empty, it will be used to identify the data type; the
|
||||||
|
# fields 'kind' and 'id' will be ignored.
|
||||||
|
#
|
||||||
|
|
||||||
uint16 id
|
uint16 id # Ignored if 'name' is non-empty
|
||||||
DataTypeKind kind
|
DataTypeKind kind # Ignored if 'name' is non-empty
|
||||||
|
|
||||||
|
uint8[<=80] name # Full data type name, e.g. "uavcan.protocol.GetDataTypeInfo"
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
uint64 signature # Data type signature
|
uint64 signature # Data type signature; valid only if the data type is known (see MASK_KNOWN)
|
||||||
|
|
||||||
|
uint16 id # Valid only if the data type is known (see MASK_KNOWN)
|
||||||
|
DataTypeKind kind # Ditto
|
||||||
|
|
||||||
uint8 MASK_KNOWN = 1 # This data type is defined
|
uint8 MASK_KNOWN = 1 # This data type is defined
|
||||||
uint8 MASK_SUBSCRIBED = 2 # Subscribed to messages of this type
|
uint8 MASK_SUBSCRIBED = 2 # Subscribed to messages of this type
|
||||||
@@ -15,4 +25,4 @@ uint8 MASK_PUBLISHING = 4 # Publishing messages of this type
|
|||||||
uint8 MASK_SERVING = 8 # Providing service of this type
|
uint8 MASK_SERVING = 8 # Providing service of this type
|
||||||
uint8 mask
|
uint8 mask
|
||||||
|
|
||||||
uint8[<=80] name # Full data type name, e.g. "uavcan.protocol.GetDataTypeInfo"
|
uint8[<=80] name # Full data type name; valid only if the data type is known (see MASK_KNOWN)
|
||||||
|
|||||||
@@ -2,6 +2,6 @@
|
|||||||
# Data type kind (message or service).
|
# Data type kind (message or service).
|
||||||
#
|
#
|
||||||
|
|
||||||
uint2 SERVICE = 0
|
uint8 SERVICE = 0
|
||||||
uint2 MESSAGE = 1
|
uint8 MESSAGE = 1
|
||||||
uint2 value
|
uint8 value
|
||||||
|
|||||||
@@ -35,43 +35,67 @@ void DataTypeInfoProvider::handleComputeAggregateTypeSignatureRequest(
|
|||||||
void DataTypeInfoProvider::handleGetDataTypeInfoRequest(const protocol::GetDataTypeInfo::Request& request,
|
void DataTypeInfoProvider::handleGetDataTypeInfoRequest(const protocol::GetDataTypeInfo::Request& request,
|
||||||
protocol::GetDataTypeInfo::Response& response)
|
protocol::GetDataTypeInfo::Response& response)
|
||||||
{
|
{
|
||||||
const DataTypeKind kind = DataTypeKind(request.kind.value);
|
/*
|
||||||
if (!isValidDataTypeKind(kind))
|
* Asking the Global Data Type Registry for the matching type descriptor, either by name or by ID
|
||||||
|
*/
|
||||||
|
const DataTypeDescriptor* desc = NULL;
|
||||||
|
|
||||||
|
if (request.name.empty())
|
||||||
{
|
{
|
||||||
UAVCAN_TRACE("DataTypeInfoProvider", "GetDataTypeInfo request with invalid DataTypeKind %i", kind);
|
response.id = request.id; // Pre-setting the fields so they have meaningful values even in
|
||||||
return;
|
response.kind = request.kind; // ...case of failure.
|
||||||
|
|
||||||
|
if (!isValidDataTypeKind(DataTypeKind(request.kind.value)))
|
||||||
|
{
|
||||||
|
UAVCAN_TRACE("DataTypeInfoProvider", "GetDataTypeInfo request with invalid DataTypeKind %i",
|
||||||
|
static_cast<int>(request.kind.value));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
desc = GlobalDataTypeRegistry::instance().find(DataTypeKind(request.kind.value), request.id);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
response.name = request.name;
|
||||||
|
|
||||||
|
desc = GlobalDataTypeRegistry::instance().find(request.name.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
const DataTypeDescriptor* const desc = GlobalDataTypeRegistry::instance().find(kind, request.id);
|
if (desc == NULL)
|
||||||
if (!desc)
|
|
||||||
{
|
{
|
||||||
UAVCAN_TRACE("DataTypeInfoProvider", "Cannot process GetDataTypeInfo for nonexistent type dtid=%i dtk=%i",
|
UAVCAN_TRACE("DataTypeInfoProvider",
|
||||||
int(request.id), int(request.kind.value));
|
"Cannot process GetDataTypeInfo for nonexistent type: dtid=%i dtk=%i name='%s'",
|
||||||
|
static_cast<int>(request.id), static_cast<int>(request.kind.value), request.name.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
UAVCAN_TRACE("DataTypeInfoProvider", "GetDataTypeInfo request for %s", desc->toString().c_str());
|
UAVCAN_TRACE("DataTypeInfoProvider", "GetDataTypeInfo request for %s", desc->toString().c_str());
|
||||||
|
|
||||||
response.signature = desc->getSignature().get();
|
/*
|
||||||
response.name = desc->getFullName();
|
* Filling the response struct
|
||||||
response.mask = protocol::GetDataTypeInfo::Response::MASK_KNOWN;
|
*/
|
||||||
|
response.signature = desc->getSignature().get();
|
||||||
|
response.id = desc->getID().get();
|
||||||
|
response.kind.value = desc->getKind();
|
||||||
|
response.mask = protocol::GetDataTypeInfo::Response::MASK_KNOWN;
|
||||||
|
response.name = desc->getFullName();
|
||||||
|
|
||||||
const Dispatcher& dispatcher = getNode().getDispatcher();
|
const Dispatcher& dispatcher = getNode().getDispatcher();
|
||||||
|
|
||||||
if (request.kind.value == protocol::DataTypeKind::SERVICE)
|
if (desc->getKind() == DataTypeKindService)
|
||||||
{
|
{
|
||||||
if (dispatcher.hasServer(request.id))
|
if (dispatcher.hasServer(desc->getID().get()))
|
||||||
{
|
{
|
||||||
response.mask |= protocol::GetDataTypeInfo::Response::MASK_SERVING;
|
response.mask |= protocol::GetDataTypeInfo::Response::MASK_SERVING;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (request.kind.value == protocol::DataTypeKind::MESSAGE)
|
else if (desc->getKind() == DataTypeKindMessage)
|
||||||
{
|
{
|
||||||
if (dispatcher.hasSubscriber(request.id))
|
if (dispatcher.hasSubscriber(desc->getID().get()))
|
||||||
{
|
{
|
||||||
response.mask |= protocol::GetDataTypeInfo::Response::MASK_SUBSCRIBED;
|
response.mask |= protocol::GetDataTypeInfo::Response::MASK_SUBSCRIBED;
|
||||||
}
|
}
|
||||||
if (dispatcher.hasPublisher(request.id))
|
if (dispatcher.hasPublisher(desc->getID().get()))
|
||||||
{
|
{
|
||||||
response.mask |= protocol::GetDataTypeInfo::Response::MASK_PUBLISHING;
|
response.mask |= protocol::GetDataTypeInfo::Response::MASK_PUBLISHING;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,22 +23,39 @@ static bool validateDataTypeInfoResponse(const std::auto_ptr<ServiceCallResult<G
|
|||||||
{
|
{
|
||||||
if (!resp.get())
|
if (!resp.get())
|
||||||
{
|
{
|
||||||
|
std::cout << "Null response" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!resp->isSuccessful())
|
if (!resp->isSuccessful())
|
||||||
{
|
{
|
||||||
|
std::cout << "Request was not successful" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (resp->response.name != DataType::getDataTypeFullName())
|
if (resp->response.name != DataType::getDataTypeFullName())
|
||||||
{
|
{
|
||||||
|
std::cout << "Type name mismatch: '"
|
||||||
|
<< resp->response.name.c_str() << "' '"
|
||||||
|
<< DataType::getDataTypeFullName() << "'" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (DataType::getDataTypeSignature().get() != resp->response.signature)
|
if (DataType::getDataTypeSignature().get() != resp->response.signature)
|
||||||
{
|
{
|
||||||
|
std::cout << "Signature mismatch" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (resp->response.mask != mask)
|
if (resp->response.mask != mask)
|
||||||
{
|
{
|
||||||
|
std::cout << "Mask mismatch" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (resp->response.kind.value != DataType::DataTypeKind)
|
||||||
|
{
|
||||||
|
std::cout << "Kind mismatch" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (resp->response.id != DataType::DefaultDataTypeID)
|
||||||
|
{
|
||||||
|
std::cout << "DTID mismatch" << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -75,9 +92,25 @@ TEST(DataTypeInfoProvider, Basic)
|
|||||||
GetDataTypeInfo::Response::MASK_SERVING));
|
GetDataTypeInfo::Response::MASK_SERVING));
|
||||||
ASSERT_EQ(1, gdti_cln.collector.result->server_node_id.get());
|
ASSERT_EQ(1, gdti_cln.collector.result->server_node_id.get());
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GetDataTypeInfo request for GetDataTypeInfo by name
|
||||||
|
*/
|
||||||
|
gdti_request = GetDataTypeInfo::Request();
|
||||||
|
gdti_request.id = 999; // Intentionally wrong
|
||||||
|
gdti_request.kind.value = DataTypeKind::MESSAGE; // Intentionally wrong
|
||||||
|
gdti_request.name = "uavcan.protocol.GetDataTypeInfo";
|
||||||
|
ASSERT_LE(0, gdti_cln.call(1, gdti_request));
|
||||||
|
nodes.spinBoth(MonotonicDuration::fromMSec(10));
|
||||||
|
|
||||||
|
ASSERT_TRUE(validateDataTypeInfoResponse<GetDataTypeInfo>(gdti_cln.collector.result,
|
||||||
|
GetDataTypeInfo::Response::MASK_KNOWN |
|
||||||
|
GetDataTypeInfo::Response::MASK_SERVING));
|
||||||
|
ASSERT_EQ(1, gdti_cln.collector.result->server_node_id.get());
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* GetDataTypeInfo request for NodeStatus - not used yet
|
* GetDataTypeInfo request for NodeStatus - not used yet
|
||||||
*/
|
*/
|
||||||
|
gdti_request = GetDataTypeInfo::Request();
|
||||||
gdti_request.id = NodeStatus::DefaultDataTypeID;
|
gdti_request.id = NodeStatus::DefaultDataTypeID;
|
||||||
gdti_request.kind.value = DataTypeKind::MESSAGE;
|
gdti_request.kind.value = DataTypeKind::MESSAGE;
|
||||||
ASSERT_LE(0, gdti_cln.call(1, gdti_request));
|
ASSERT_LE(0, gdti_cln.call(1, gdti_request));
|
||||||
@@ -107,15 +140,37 @@ TEST(DataTypeInfoProvider, Basic)
|
|||||||
/*
|
/*
|
||||||
* Requesting a non-existent type
|
* Requesting a non-existent type
|
||||||
*/
|
*/
|
||||||
|
gdti_request = GetDataTypeInfo::Request();
|
||||||
gdti_request.id = ComputeAggregateTypeSignature::DefaultDataTypeID;
|
gdti_request.id = ComputeAggregateTypeSignature::DefaultDataTypeID;
|
||||||
gdti_request.kind.value = 0xFF; // INVALID VALUE
|
gdti_request.kind.value = 3; // INVALID VALUE
|
||||||
ASSERT_LE(0, gdti_cln.call(1, gdti_request));
|
ASSERT_LE(0, gdti_cln.call(1, gdti_request));
|
||||||
nodes.spinBoth(MonotonicDuration::fromMSec(10));
|
nodes.spinBoth(MonotonicDuration::fromMSec(10));
|
||||||
|
|
||||||
ASSERT_TRUE(gdti_cln.collector.result.get());
|
ASSERT_TRUE(gdti_cln.collector.result.get());
|
||||||
ASSERT_TRUE(gdti_cln.collector.result->isSuccessful());
|
ASSERT_TRUE(gdti_cln.collector.result->isSuccessful());
|
||||||
ASSERT_EQ(1, gdti_cln.collector.result->server_node_id.get());
|
ASSERT_EQ(1, gdti_cln.collector.result->server_node_id.get());
|
||||||
ASSERT_TRUE(gdti_cln.collector.result->response == GetDataTypeInfo::Response()); // Empty response
|
ASSERT_EQ(0, gdti_cln.collector.result->response.mask);
|
||||||
|
ASSERT_TRUE(gdti_cln.collector.result->response.name.empty()); // Empty name
|
||||||
|
ASSERT_EQ(gdti_request.id, gdti_cln.collector.result->response.id);
|
||||||
|
ASSERT_EQ(gdti_request.kind.value, gdti_cln.collector.result->response.kind.value);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Requesting a non-existent type by name
|
||||||
|
*/
|
||||||
|
gdti_request = GetDataTypeInfo::Request();
|
||||||
|
gdti_request.id = 999; // Intentionally wrong
|
||||||
|
gdti_request.kind.value = 3; // Intentionally wrong
|
||||||
|
gdti_request.name = "uavcan.equipment.gnss.Fix";
|
||||||
|
ASSERT_LE(0, gdti_cln.call(1, gdti_request));
|
||||||
|
nodes.spinBoth(MonotonicDuration::fromMSec(10));
|
||||||
|
|
||||||
|
ASSERT_TRUE(gdti_cln.collector.result.get());
|
||||||
|
ASSERT_TRUE(gdti_cln.collector.result->isSuccessful());
|
||||||
|
ASSERT_EQ(1, gdti_cln.collector.result->server_node_id.get());
|
||||||
|
ASSERT_EQ(0, gdti_cln.collector.result->response.mask);
|
||||||
|
ASSERT_EQ("uavcan.equipment.gnss.Fix", gdti_cln.collector.result->response.name);
|
||||||
|
ASSERT_EQ(0, gdti_cln.collector.result->response.id);
|
||||||
|
ASSERT_EQ(0, gdti_cln.collector.result->response.kind.value);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ComputeAggregateTypeSignature test
|
* ComputeAggregateTypeSignature test
|
||||||
|
|||||||
Reference in New Issue
Block a user