libuav original
Dependents: UAVCAN UAVCAN_Subscriber
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
Generated on Tue Jul 12 2022 17:17:33 by 1.7.2