mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-07-04 12:00:35 +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.
|
||||
#
|
||||
# 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
|
||||
DataTypeKind kind
|
||||
uint16 id # Ignored if 'name' is non-empty
|
||||
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_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
|
||||
|
||||
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).
|
||||
#
|
||||
|
||||
uint2 SERVICE = 0
|
||||
uint2 MESSAGE = 1
|
||||
uint2 value
|
||||
uint8 SERVICE = 0
|
||||
uint8 MESSAGE = 1
|
||||
uint8 value
|
||||
|
||||
@@ -35,43 +35,67 @@ void DataTypeInfoProvider::handleComputeAggregateTypeSignatureRequest(
|
||||
void DataTypeInfoProvider::handleGetDataTypeInfoRequest(const protocol::GetDataTypeInfo::Request& request,
|
||||
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);
|
||||
return;
|
||||
response.id = request.id; // Pre-setting the fields so they have meaningful values even in
|
||||
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)
|
||||
if (desc == NULL)
|
||||
{
|
||||
UAVCAN_TRACE("DataTypeInfoProvider", "Cannot process GetDataTypeInfo for nonexistent type dtid=%i dtk=%i",
|
||||
int(request.id), int(request.kind.value));
|
||||
UAVCAN_TRACE("DataTypeInfoProvider",
|
||||
"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;
|
||||
}
|
||||
|
||||
UAVCAN_TRACE("DataTypeInfoProvider", "GetDataTypeInfo request for %s", desc->toString().c_str());
|
||||
|
||||
response.signature = desc->getSignature().get();
|
||||
response.name = desc->getFullName();
|
||||
response.mask = protocol::GetDataTypeInfo::Response::MASK_KNOWN;
|
||||
/*
|
||||
* Filling the response struct
|
||||
*/
|
||||
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();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
if (dispatcher.hasPublisher(request.id))
|
||||
if (dispatcher.hasPublisher(desc->getID().get()))
|
||||
{
|
||||
response.mask |= protocol::GetDataTypeInfo::Response::MASK_PUBLISHING;
|
||||
}
|
||||
|
||||
@@ -23,22 +23,39 @@ static bool validateDataTypeInfoResponse(const std::auto_ptr<ServiceCallResult<G
|
||||
{
|
||||
if (!resp.get())
|
||||
{
|
||||
std::cout << "Null response" << std::endl;
|
||||
return false;
|
||||
}
|
||||
if (!resp->isSuccessful())
|
||||
{
|
||||
std::cout << "Request was not successful" << std::endl;
|
||||
return false;
|
||||
}
|
||||
if (resp->response.name != DataType::getDataTypeFullName())
|
||||
{
|
||||
std::cout << "Type name mismatch: '"
|
||||
<< resp->response.name.c_str() << "' '"
|
||||
<< DataType::getDataTypeFullName() << "'" << std::endl;
|
||||
return false;
|
||||
}
|
||||
if (DataType::getDataTypeSignature().get() != resp->response.signature)
|
||||
{
|
||||
std::cout << "Signature mismatch" << std::endl;
|
||||
return false;
|
||||
}
|
||||
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 true;
|
||||
@@ -75,9 +92,25 @@ TEST(DataTypeInfoProvider, Basic)
|
||||
GetDataTypeInfo::Response::MASK_SERVING));
|
||||
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
|
||||
*/
|
||||
gdti_request = GetDataTypeInfo::Request();
|
||||
gdti_request.id = NodeStatus::DefaultDataTypeID;
|
||||
gdti_request.kind.value = DataTypeKind::MESSAGE;
|
||||
ASSERT_LE(0, gdti_cln.call(1, gdti_request));
|
||||
@@ -107,15 +140,37 @@ TEST(DataTypeInfoProvider, Basic)
|
||||
/*
|
||||
* Requesting a non-existent type
|
||||
*/
|
||||
gdti_request = GetDataTypeInfo::Request();
|
||||
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));
|
||||
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_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
|
||||
|
||||
Reference in New Issue
Block a user