libuav original
Dependents: UAVCAN UAVCAN_Subscriber
data_type_info_provider.hpp
00001 /* 00002 * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com> 00003 */ 00004 00005 #ifndef UAVCAN_PROTOCOL_DATA_TYPE_INFO_PROVIDER_HPP_INCLUDED 00006 #define UAVCAN_PROTOCOL_DATA_TYPE_INFO_PROVIDER_HPP_INCLUDED 00007 00008 #include <uavcan/node/service_server.hpp> 00009 #include <uavcan/util/method_binder.hpp> 00010 #include <uavcan/build_config.hpp> 00011 #include <uavcan/protocol/GetDataTypeInfo.hpp> 00012 #include <uavcan/debug.hpp> 00013 00014 namespace uavcan 00015 { 00016 /** 00017 * This class implements the standard services for data type introspection. 00018 * Once started it does not require any attention from the application. 00019 * The user does not need to deal with it directly - it's started by the node class. 00020 */ 00021 class UAVCAN_EXPORT DataTypeInfoProvider : Noncopyable 00022 { 00023 typedef MethodBinder<DataTypeInfoProvider*, 00024 void (DataTypeInfoProvider::*)(const protocol::GetDataTypeInfo::Request&, 00025 protocol::GetDataTypeInfo::Response&)> GetDataTypeInfoCallback; 00026 00027 ServiceServer<protocol::GetDataTypeInfo, GetDataTypeInfoCallback> gdti_srv_; 00028 00029 INode& getNode() { return gdti_srv_.getNode(); } 00030 00031 static bool isValidDataTypeKind(DataTypeKind kind) 00032 { 00033 return (kind == DataTypeKindMessage) || (kind == DataTypeKindService); 00034 } 00035 00036 void handleGetDataTypeInfoRequest(const protocol::GetDataTypeInfo::Request& request, 00037 protocol::GetDataTypeInfo::Response& response) 00038 { 00039 /* 00040 * Asking the Global Data Type Registry for the matching type descriptor, either by name or by ID 00041 */ 00042 const DataTypeDescriptor* desc = UAVCAN_NULLPTR; 00043 00044 if (request.name.empty()) 00045 { 00046 response.id = request.id; // Pre-setting the fields so they have meaningful values even in 00047 response.kind = request.kind; // ...case of failure. 00048 00049 if (!isValidDataTypeKind(DataTypeKind(request.kind.value))) 00050 { 00051 UAVCAN_TRACE("DataTypeInfoProvider", "GetDataTypeInfo request with invalid DataTypeKind %i", 00052 static_cast<int>(request.kind.value)); 00053 return; 00054 } 00055 00056 desc = GlobalDataTypeRegistry::instance().find(DataTypeKind(request.kind.value), request.id); 00057 } 00058 else 00059 { 00060 response.name = request.name; 00061 00062 desc = GlobalDataTypeRegistry::instance().find(request.name.c_str()); 00063 } 00064 00065 if (desc == UAVCAN_NULLPTR) 00066 { 00067 UAVCAN_TRACE("DataTypeInfoProvider", 00068 "Cannot process GetDataTypeInfo for nonexistent type: dtid=%i dtk=%i name='%s'", 00069 static_cast<int>(request.id), static_cast<int>(request.kind.value), request.name.c_str()); 00070 return; 00071 } 00072 00073 UAVCAN_TRACE("DataTypeInfoProvider", "GetDataTypeInfo request for %s", desc->toString().c_str()); 00074 00075 /* 00076 * Filling the response struct 00077 */ 00078 response.signature = desc->getSignature().get(); 00079 response.id = desc->getID().get(); 00080 response.kind.value = desc->getKind(); 00081 response.flags = protocol::GetDataTypeInfo::Response::FLAG_KNOWN; 00082 response.name = desc->getFullName(); 00083 00084 const Dispatcher& dispatcher = getNode().getDispatcher(); 00085 00086 if (desc->getKind() == DataTypeKindService) 00087 { 00088 if (dispatcher.hasServer(desc->getID().get())) 00089 { 00090 response.flags |= protocol::GetDataTypeInfo::Response::FLAG_SERVING; 00091 } 00092 } 00093 else if (desc->getKind() == DataTypeKindMessage) 00094 { 00095 if (dispatcher.hasSubscriber(desc->getID().get())) 00096 { 00097 response.flags |= protocol::GetDataTypeInfo::Response::FLAG_SUBSCRIBED; 00098 } 00099 if (dispatcher.hasPublisher(desc->getID().get())) 00100 { 00101 response.flags |= protocol::GetDataTypeInfo::Response::FLAG_PUBLISHING; 00102 } 00103 } 00104 else 00105 { 00106 UAVCAN_ASSERT(0); // That means that GDTR somehow found a type of an unknown kind. The horror. 00107 } 00108 } 00109 00110 public: 00111 explicit DataTypeInfoProvider(INode& node) : 00112 gdti_srv_(node) 00113 { } 00114 00115 int start() 00116 { 00117 int res = 0; 00118 00119 res = gdti_srv_.start(GetDataTypeInfoCallback(this, &DataTypeInfoProvider::handleGetDataTypeInfoRequest)); 00120 if (res < 0) 00121 { 00122 goto fail; 00123 } 00124 00125 UAVCAN_ASSERT(res >= 0); 00126 return res; 00127 00128 fail: 00129 UAVCAN_ASSERT(res < 0); 00130 gdti_srv_.stop(); 00131 return res; 00132 } 00133 }; 00134 00135 } 00136 00137 #endif // UAVCAN_PROTOCOL_DATA_TYPE_INFO_PROVIDER_HPP_INCLUDED
Generated on Tue Jul 12 2022 17:17:31 by 1.7.2