libuav original

Dependents:   UAVCAN UAVCAN_Subscriber

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers data_type_info_provider.hpp Source File

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