libuav original

Dependents:   UAVCAN UAVCAN_Subscriber

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers param_server.hpp Source File

param_server.hpp

00001 /*
00002  * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
00003  */
00004 
00005 #ifndef UAVCAN_PROTOCOL_PARAM_SERVER_HPP_INCLUDED
00006 #define UAVCAN_PROTOCOL_PARAM_SERVER_HPP_INCLUDED
00007 
00008 #include <uavcan/debug.hpp>
00009 #include <uavcan/protocol/param/GetSet.hpp>
00010 #include <uavcan/protocol/param/ExecuteOpcode.hpp>
00011 #include <uavcan/node/service_server.hpp>
00012 #include <uavcan/util/method_binder.hpp>
00013 #include <cassert>
00014 #include <cstdlib>
00015 
00016 namespace uavcan
00017 {
00018 /**
00019  * Implement this interface in the application to support the standard remote reconfiguration services.
00020  * Refer to @ref ParamServer.
00021  */
00022 class UAVCAN_EXPORT IParamManager
00023 {
00024 public:
00025     typedef typename StorageType<typename protocol::param::GetSet::Response::FieldTypes::name>::Type Name;
00026     typedef typename StorageType<typename protocol::param::GetSet::Request::FieldTypes::index>::Type Index;
00027     typedef protocol::param::Value Value;
00028     typedef protocol::param::NumericValue NumericValue;
00029 
00030     virtual ~IParamManager() { }
00031 
00032     /**
00033      * Copy the parameter name to @ref out_name if it exists, otherwise do nothing.
00034      */
00035     virtual void getParamNameByIndex(Index index, Name& out_name) const = 0;
00036 
00037     /**
00038      * Assign by name if exists.
00039      */
00040     virtual void assignParamValue(const Name& name, const Value& value) = 0;
00041 
00042     /**
00043      * Read by name if exists, otherwise do nothing.
00044      */
00045     virtual void readParamValue(const Name& name, Value& out_value) const = 0;
00046 
00047     /**
00048      * Read param's default/max/min if available.
00049      * Note that min/max are only applicable to numeric params.
00050      * Implementation is optional.
00051      */
00052     virtual void readParamDefaultMaxMin(const Name& name, Value& out_default,
00053                                         NumericValue& out_max, NumericValue& out_min) const
00054     {
00055         (void)name;
00056         (void)out_default;
00057         (void)out_max;
00058         (void)out_min;
00059     }
00060 
00061     /**
00062      * Save all params to non-volatile storage.
00063      * @return Negative if failed.
00064      */
00065     virtual int saveAllParams() = 0;
00066 
00067     /**
00068      * Clear the non-volatile storage.
00069      * @return Negative if failed.
00070      */
00071     virtual int eraseAllParams() = 0;
00072 };
00073 
00074 /**
00075  * Convenience class for supporting the standard configuration services.
00076  * Highly recommended to use.
00077  */
00078 class UAVCAN_EXPORT ParamServer
00079 {
00080     typedef MethodBinder<ParamServer*, void (ParamServer::*)(const protocol::param::GetSet::Request&,
00081                                                              protocol::param::GetSet::Response&)> GetSetCallback;
00082 
00083     typedef MethodBinder<ParamServer*,
00084                          void (ParamServer::*)(const protocol::param::ExecuteOpcode::Request&,
00085                                                protocol::param::ExecuteOpcode::Response&)> ExecuteOpcodeCallback;
00086 
00087     ServiceServer<protocol::param::GetSet, GetSetCallback> get_set_srv_;
00088     ServiceServer<protocol::param::ExecuteOpcode, ExecuteOpcodeCallback> save_erase_srv_;
00089     IParamManager* manager_;
00090 
00091     void handleGetSet(const protocol::param::GetSet::Request& in, protocol::param::GetSet::Response& out)
00092     {
00093         UAVCAN_ASSERT(manager_ != UAVCAN_NULLPTR);
00094 
00095         // Recover the name from index
00096         if (in.name.empty())
00097         {
00098             manager_->getParamNameByIndex(in.index, out.name);
00099             UAVCAN_TRACE("ParamServer", "GetSet: Index %i --> '%s'", int(in.index), out.name.c_str());
00100         }
00101         else
00102         {
00103             out.name = in.name;
00104         }
00105 
00106         if (out.name.empty())
00107         {
00108             UAVCAN_TRACE("ParamServer", "GetSet: Can't resolve parameter name, index=%i", int(in.index));
00109             return;
00110         }
00111 
00112         // Assign if needed, read back
00113         if (!in.value.is(protocol::param::Value::Tag::empty))
00114         {
00115             manager_->assignParamValue(out.name, in.value);
00116         }
00117         manager_->readParamValue(out.name, out.value);
00118 
00119         // Check if the value is OK, otherwise reset the name to indicate that we have no idea what is it all about
00120         if (!out.value.is(protocol::param::Value::Tag::empty))
00121         {
00122             manager_->readParamDefaultMaxMin(out.name, out.default_value, out.max_value, out.min_value);
00123         }
00124         else
00125         {
00126             UAVCAN_TRACE("ParamServer", "GetSet: Unknown param: index=%i name='%s'", int(in.index), out.name.c_str());
00127             out.name.clear();
00128         }
00129     }
00130 
00131     void handleExecuteOpcode(const protocol::param::ExecuteOpcode::Request& in,
00132                              protocol::param::ExecuteOpcode::Response& out)
00133     {
00134         UAVCAN_ASSERT(manager_ != UAVCAN_NULLPTR);
00135 
00136         if (in.opcode == protocol::param::ExecuteOpcode::Request::OPCODE_SAVE)
00137         {
00138             out.ok = manager_->saveAllParams() >= 0;
00139         }
00140         else if (in.opcode == protocol::param::ExecuteOpcode::Request::OPCODE_ERASE)
00141         {
00142             out.ok = manager_->eraseAllParams() >= 0;
00143         }
00144         else
00145         {
00146             UAVCAN_TRACE("ParamServer", "ExecuteOpcode: invalid opcode %i", int(in.opcode));
00147             out.ok = false;
00148         }
00149     }
00150 
00151 public:
00152     explicit ParamServer(INode& node)
00153         : get_set_srv_(node)
00154         , save_erase_srv_(node)
00155         , manager_(UAVCAN_NULLPTR)
00156     { }
00157 
00158     /**
00159      * Starts the parameter server with given param manager instance.
00160      * Returns negative error code.
00161      */
00162     int start(IParamManager* manager)
00163     {
00164         if (manager == UAVCAN_NULLPTR)
00165         {
00166             return -ErrInvalidParam;
00167         }
00168         manager_ = manager;
00169 
00170         int res = get_set_srv_.start(GetSetCallback(this, &ParamServer::handleGetSet));
00171         if (res < 0)
00172         {
00173             return res;
00174         }
00175 
00176         res = save_erase_srv_.start(ExecuteOpcodeCallback(this, &ParamServer::handleExecuteOpcode));
00177         if (res < 0)
00178         {
00179             get_set_srv_.stop();
00180         }
00181         return res;
00182     }
00183 
00184     /**
00185      * @ref IParamManager
00186      */
00187     IParamManager* getParamManager() const { return manager_; }
00188 };
00189 
00190 }
00191 
00192 #endif // UAVCAN_PROTOCOL_PARAM_SERVER_HPP_INCLUDED