# How configure node params?

**URL:** <https://forum.opencyphal.org/t/how-configure-node-params/227>\
**Category:** LibCyphal\
**Created:** [November 3, 2018, 4:49pm UTC](https://forum.opencyphal.org/t/how-configure-node-params/227 "2018-11-03T16:49:38Z")\
**Posts on this page:** 16\
**Page:** 1

<div class="post-metadata">

**Author:** ![SergeyF1987](https://forum.opencyphal.org/user_avatar/forum.opencyphal.org/sergeyf1987/32/68_2.png) [@SergeyF1987](https://forum.opencyphal.org/u/SergeyF1987)\
**Post date:** [November 3, 2018, 4:49pm UTC](https://forum.opencyphal.org/t/how-configure-node-params/227/1 "2018-11-03T16:49:38Z")

</div>

I fixed my troubles, that I described below, but now I have a question about one thing, that I still cannot understand completely.  
I want define some inner params for node (configure node). I read this tutorial.  
[https://uavcan.org/Implementations/Libuavcan/Tutorials/7.\_Remote\_node\_reconfiguration/](https://uavcan.org/Implementations/Libuavcan/Tutorials/7._Remote_node_reconfiguration/)  
Did I understand right, that I must initialize and launch ParamServer (Remote node section) and then set (or read) params through uavcan::protocol::param::GetSet::Request (Response);  
I need add (define) a new param in node (in node space) for reconfiguring it at next. How can do I this?

I got answer as…  
" The library is interfaced with your application via the `uavcan::IParamManager` interface:  
It is entirely up to you to decide how to handle your configuration parameters, how to add a new one, how to modify them, and so on."

But… How??? RRRRR!!! If I had not tried to do this, I would not have written this post. My program still cannot configure params.

---

<div class="post-metadata">

**Author:** ![pavel.kirienko](https://forum.opencyphal.org/user_avatar/forum.opencyphal.org/pavel.kirienko/32/9_2.png) [@pavel.kirienko](https://forum.opencyphal.org/u/pavel.kirienko)\
**Post date:** [November 5, 2018, 1:07pm UTC](https://forum.opencyphal.org/t/how-configure-node-params/227/2 "2018-11-05T13:07:17Z")

</div>

> [@SergeyF1987](#):
>
> My program still cannot configure params.

Let’s have a look at your program. Particularly, let us have a look at your implementation of the `uavcan::IParamManager` interface.

---

<div class="post-metadata">

**Author:** ![SergeyF1987](https://forum.opencyphal.org/user_avatar/forum.opencyphal.org/sergeyf1987/32/68_2.png) [@SergeyF1987](https://forum.opencyphal.org/u/SergeyF1987)\
**Post date:** [November 6, 2018, 7:23am UTC](https://forum.opencyphal.org/t/how-configure-node-params/227/3 "2018-11-06T07:23:23Z")

</div>

Hello.  
I try to write value to new param in my node. After I want to get it back.

I try to add param ‘frequence’ to space of node. I defined it in struct before:

```auto
static struct Params
{
    int freq = 0;
} configuration;

```

Then I defined all methods for virtual class IParamManager. One of them is assigning:

```auto
void assignParamValue(const Name& name, const Value& value) override
{
    if (name == "freq")
    {
        if (value.is(uavcan::protocol::param::Value::Tag::integer_value))
        {
            configuration.freq = *value.as<uavcan::protocol::param::Value::Tag::integer_value>();
        }
    }
}

```

And then I try to write value to ‘freq’-named param. First I started server:

```auto
uavcan::ParamServer server(node);
er_code = server.start(&p_man);
if(er_code < 0)
{
    HAL_GPIO_WritePin(GPIOD, GPIO_PIN_13, GPIO_PIN_SET);
}
node.setRestartRequestHandler(&restart_handler);

```

Server starts with er\_code=0, that I think is OK (not \<0)  
After I set my node to Operational mode, init response and request

```auto
//set node to active mode
node.setModeOperational();
//Init standart service operations
uavcan::protocol::param::GetSet::Response resp;
uavcan::protocol::param::GetSet::Request req;

```

Setting request index and name (‘freq’). I try to write new value to my ‘freq’ param and read it back from node. But first.value of result returns (in performBlockingServiceCall) with error (\<0), and I cannot read value to frequency variable

```auto
req.index=1; //set my index
req.name="freq"; //set valid name
req.value=resp.value; //not sure in it
//try to write value from defined UPDATE_RATE_HZ
req.value.to<uavcan::protocol::param::Value::Tag::integer_value>()=UPDATE_RATE_HZ; //set param
//get result of service
auto result = performBlockingServiceCall<uavcan::protocol::param::GetSet>(node,node_id,req);
//get frequency from params (read value FAIL)
frequency=result.second.value.to<uavcan::protocol::param::Value::Tag::integer_value>();

```

---

<div class="post-metadata">

**Author:** ![pavel.kirienko](https://forum.opencyphal.org/user_avatar/forum.opencyphal.org/pavel.kirienko/32/9_2.png) [@pavel.kirienko](https://forum.opencyphal.org/u/pavel.kirienko)\
**Post date:** [November 6, 2018, 9:47am UTC](https://forum.opencyphal.org/t/how-configure-node-params/227/4 "2018-11-06T09:47:23Z")

</div>

> [@SergeyF1987](#):
>
> But first.value of result returns (in performBlockingServiceCall) with error (\<0), and I cannot read value to frequency variable

What is the value of the returned error code?

_P.S. This is not directly related to your problem, but you might want to know that closures use heap memory, which is probably not what you want on an embedded system. Consider avoiding them; use plain functions, member functions, or non-capturing lambdas instead._

---

<div class="post-metadata">

**Author:** ![SergeyF1987](https://forum.opencyphal.org/user_avatar/forum.opencyphal.org/sergeyf1987/32/68_2.png) [@SergeyF1987](https://forum.opencyphal.org/u/SergeyF1987)\
**Post date:** [November 7, 2018, 1:36pm UTC](https://forum.opencyphal.org/t/how-configure-node-params/227/5 "2018-11-07T13:36:44Z")

</div>

I get result.first == -2  
As in ‘performBlockingServiceCall’ func I get:

```auto
success = result.isSuccessful(); // false returned

```

and call\_res == -2 in:

```auto
const int call_res = client.call(remote_node_id, request); // -2

```

And I have global FAIL result for ‘performBlockingServiceCall’ calling

But server starts with ‘0’ code, that is means OK (not \< 0)

I tried even only read params according to: [https://uavcan.org/Implementations/Libuavcan/Tutorials/7.\_Remote\_node\_reconfiguration/](https://uavcan.org/Implementations/Libuavcan/Tutorials/7._Remote_node_reconfiguration/)  
But it also returns with fail:

```auto
auto res = performBlockingServiceCall<uavcan::protocol::param::GetSet>(node, remote_node_id, req);
        if (res.first < 0)
        {
            throw std::runtime_error("Failed to get param: " + std::to_string(res.first));
        }

```

I have also res.first == -2, as in my task before (result.first == -2)

---

<div class="post-metadata">

**Author:** ![pavel.kirienko](https://forum.opencyphal.org/user_avatar/forum.opencyphal.org/pavel.kirienko/32/9_2.png) [@pavel.kirienko](https://forum.opencyphal.org/u/pavel.kirienko)\
**Post date:** [November 7, 2018, 2:06pm UTC](https://forum.opencyphal.org/t/how-configure-node-params/227/6 "2018-11-07T14:06:10Z")

</div>

As you can see in [`error.hpp`, error code 2 means `ErrInvalidParam`](https://github.com/UAVCAN/libuavcan/blob/dfcdf22eda16ff06847976fd6c7f40671fc92eb5/libuavcan/include/uavcan/error.hpp#L26). Most likely the value of `node_id` is invalid, check that.

---

<div class="post-metadata">

**Author:** ![SergeyF1987](https://forum.opencyphal.org/user_avatar/forum.opencyphal.org/sergeyf1987/32/68_2.png) [@SergeyF1987](https://forum.opencyphal.org/u/SergeyF1987)\
**Post date:** [November 8, 2018, 1:24am UTC](https://forum.opencyphal.org/t/how-configure-node-params/227/7 "2018-11-08T01:24:21Z")

</div>

Ok… But before I init my node directly with id=1:  
int node\_id=1; //node id  
uint32\_t v\_adc; //var for value from ADC  
int frequency; //var of frequency for Airspeed sending  
auto& node = getNode(); //get node  
node.setNodeID(node\_id); //set node ID  
node.setName(“AirSensor”); //set name

When I start node, it’s returns OK. So I can suggest that node\_id set to ‘1’

---

<div class="post-metadata">

**Author:** ![pavel.kirienko](https://forum.opencyphal.org/user_avatar/forum.opencyphal.org/pavel.kirienko/32/9_2.png) [@pavel.kirienko](https://forum.opencyphal.org/u/pavel.kirienko)\
**Post date:** [November 8, 2018, 8:35am UTC](https://forum.opencyphal.org/t/how-configure-node-params/227/8 "2018-11-08T08:35:21Z")

</div>

Sorry, I was referring to the server node ID that you are passing to `performBlockingServiceCall()`:

```auto
auto result = performBlockingServiceCall<uavcan::protocol::param::GetSet>(node,node_id,req);

```

---

<div class="post-metadata">

**Author:** ![SergeyF1987](https://forum.opencyphal.org/user_avatar/forum.opencyphal.org/sergeyf1987/32/68_2.png) [@SergeyF1987](https://forum.opencyphal.org/u/SergeyF1987)\
**Post date:** [November 10, 2018, 9:04am UTC](https://forum.opencyphal.org/t/how-configure-node-params/227/9 "2018-11-10T09:04:03Z")

</div>

I m a little confuset. I wrote a test little code.  
I wrote in ‘int main’ func

```auto
   int node_id=4 //node id
   int remote_node_id=5; //remote node id
   auto& node = getNode(); //get node
   node.setNodeID(node_id); //set node ID
   node.setName("Config"); //set name
   er_code = node.start(); //start node
   if(er_code < 0) {} //if error

```

‘node’ starts with ‘0’ code (OK).  
Then I defined ‘p\_man’ class directly: ( I hid code inside functions)

```auto
  //Params for Configuration Server
    static struct Params
        {
  	    unsigned freq = 1;
        } configuration;
   class : public uavcan::IParamManager
   {
  	 void getParamNameByIndex(Index index, Name& out_name) const override
  	         {
  	             if (index == 0) { out_name = "freq"; }
  	         }
  	         void assignParamValue(const Name& name, const Value& value) override{.....}
  	         void readParamValue(const Name& name, Value& out_value) const override{.....}
  	         int saveAllParams() override{ .....}
  	         int eraseAllParams() override{.....}
  	         void readParamDefaultMaxMin(const Name& name, Value& out_def,
  	                                     NumericValue& out_max, NumericValue& out_min) const override{.....}
   }p_man;

```

After this I wrote:

```auto
   uavcan::ParamServer server(node);
   er_code = server.start(&p_man);
   if(er_code < 0) {} //if error
   node.setRestartRequestHandler(&restart_handler);
   node.setModeOperational();
   //set vector for remote params
   std::vector<uavcan::protocol::param::GetSet::Response> remote_params;
   uavcan::protocol::param::GetSet::Request req;
   req.index=remote_params.size();
   auto result = performBlockingServiceCall<uavcan::protocol::param::GetSet>(node,remote_node_id,req);

```

Getting a vector size in req.index=remote\_params.size() returns ‘0’; Is it true for this?  
result.first now returns with ‘-1’  
Also… Should node\_id and remote\_node\_id must be different? When ‘remote\_node\_id==node\_id’ I get ‘-2’. When ‘remote\_node\_id!=node\_id’ I get ‘-1’.  
I suspect that I defined node with something wrong…

---

<div class="post-metadata">

**Author:** ![pavel.kirienko](https://forum.opencyphal.org/user_avatar/forum.opencyphal.org/pavel.kirienko/32/9_2.png) [@pavel.kirienko](https://forum.opencyphal.org/u/pavel.kirienko)\
**Post date:** [November 10, 2018, 5:27pm UTC](https://forum.opencyphal.org/t/how-configure-node-params/227/10 "2018-11-10T17:27:02Z")

</div>

> Should node\_id and remote\_node\_id must be different? When ‘remote\_node\_id==node\_id’ I get ‘-2’.

Of course. You can’t send a request to your local node.

I don’t see where are you updating `remote_params`. Please post the code of both nodes here.

P.S. please format your listings properly; there is a button for that in the post editor:

 ![image](https://forum.opencyphal.org/uploads/default/original/1X/d189a187e27040975092f3e22e119419305c78eb.png)

---

<div class="post-metadata">

**Author:** ![SergeyF1987](https://forum.opencyphal.org/user_avatar/forum.opencyphal.org/sergeyf1987/32/68_2.png) [@SergeyF1987](https://forum.opencyphal.org/u/SergeyF1987)\
**Post date:** [November 11, 2018, 10:45pm UTC](https://forum.opencyphal.org/t/how-configure-node-params/227/11 "2018-11-11T22:45:19Z")

</div>

Ok. I read that I need two nodes: (1-configuration, 2-remote)  
At first I init both od them (c\_node - configurator, r\_node - remote node):

```auto
  //....................................................
  int c_node_id=4; //config node id
  auto& c_node = getNode(); //get node
  c_node.setNodeID(c_node_id); //set node ID
  c_node.setName("Config"); //set name
  er_code = c_node.start(); //start node
  if(er_code < 0) {...}
  //..................................
  int r_node_id=5;
  auto& r_node = getNode(); //get node
  r_node.setNodeID(r_node_id); //set node ID
  r_node.setName("Remote"); //set name
  er_code = r_node.start(); //start node
  if(er_code < 0) {...}
  //....................................................

```

Both starts with OK (e\_code=0)  
Then I define params for manager (hidden body for IParamManager, for reduce reply):

```auto
    static struct Params
        {
  	    unsigned freq = 1;
  	    unsigned amendment = 0;
        } configuration;
   class : public uavcan::IParamManager {....(functions, bla-bla-bla)...}p_manager;

```

Then I simply starts server for remote node (r\_node). After I directly set to operational-mode both nodes:

```auto
 //Init and start config-server
   uavcan::ParamServer server(r_node);
   er_code = server.start(&p_manager);
   if(er_code < 0) {...}
  //restart and set remote node to operational-mode
   r_node.setRestartRequestHandler(&restart_handler);
   r_node.setModeOperational();
  //set config-node to operational-mode too
  c_node.setModeOperational();

```

It’s seems, they starts with OK (er\_code=0)  
And now I do:

```auto
   std::vector<uavcan::protocol::param::GetSet::Response> remote_params;
   uavcan::protocol::param::GetSet::Request req;
   req.index=remote_params.size();
   auto result = performBlockingServiceCall<uavcan::protocol::param::GetSet>(c_node,r_node_id,req);

```

result.first returns with -1  
I define vector of Response-struct (labeled as ‘remote-params’) with default size (=0). I understood, that I need initialize remote\_params somehow according to:

```auto
    static struct Params
        {
  	    unsigned freq = 1;
  	    unsigned amendment = 0;
        } configuration;

```

But I stiil confused, how I can do it.

---

<div class="post-metadata">

**Author:** ![pavel.kirienko](https://forum.opencyphal.org/user_avatar/forum.opencyphal.org/pavel.kirienko/32/9_2.png) [@pavel.kirienko](https://forum.opencyphal.org/u/pavel.kirienko)\
**Post date:** [November 11, 2018, 11:05pm UTC](https://forum.opencyphal.org/t/how-configure-node-params/227/12 "2018-11-11T23:05:19Z")

</div>

Apparently, your nodes can’t communicate with each other. How your CAN bus is set up?

---

<div class="post-metadata">

**Author:** ![SergeyF1987](https://forum.opencyphal.org/user_avatar/forum.opencyphal.org/sergeyf1987/32/68_2.png) [@SergeyF1987](https://forum.opencyphal.org/u/SergeyF1987)\
**Post date:** [November 11, 2018, 11:16pm UTC](https://forum.opencyphal.org/t/how-configure-node-params/227/13 "2018-11-11T23:16:57Z")

</div>

Oh… It seems, I begin understand my troubles. So… We can build net with one configuration node and some remote nodes? Right? But I tried to unite configuration-node and remote-node in one global node. But i see, that is unavailable. ?! I wanted to regulate params for my remote node as it was also configuration node.

---

<div class="post-metadata">

**Author:** ![pavel.kirienko](https://forum.opencyphal.org/user_avatar/forum.opencyphal.org/pavel.kirienko/32/9_2.png) [@pavel.kirienko](https://forum.opencyphal.org/u/pavel.kirienko)\
**Post date:** [November 12, 2018, 9:23am UTC](https://forum.opencyphal.org/t/how-configure-node-params/227/14 "2018-11-12T09:23:43Z")

</div>

UAVCAN does not define any means of node-local communication (although it doesn’t really prohibit that either; it is just omitted from the spec). That means that you can’t send a request, or a message, to your own local node – the transfer would just disappear into nowhere. You can only communicate with remote nodes.

---

<div class="post-metadata">

**Author:** ![SergeyF1987](https://forum.opencyphal.org/user_avatar/forum.opencyphal.org/sergeyf1987/32/68_2.png) [@SergeyF1987](https://forum.opencyphal.org/u/SergeyF1987)\
**Post date:** [November 12, 2018, 11:25am UTC](https://forum.opencyphal.org/t/how-configure-node-params/227/15 "2018-11-12T11:25:31Z")

</div>

Thanks. I check this. But now I have another question. So… I starts my remote node. Configurator-node sends a some value to remote node (to me) for parameter named as ‘freq’. How can I read this (get received value) inside remote-node? I’m able to read data through basic HAL functions for CAN periph. But now libuavcan installed. Are this steps will right?  
(This Remote-node is already started with OK):

```auto
  uavcan::protocol::param::GetSet::Response resp;
  uavcan::protocol::param::GetSet::Request req;
  req.index=1;
  req.name="freq";
  req.value=resp.value;
  //get result of service
  auto result = performBlockingServiceCall<uavcan::protocol::param::GetSet>(node,node_id,req);
  //get frequency from params
  frequency=result.second.value.to<uavcan::protocol::param::Value::Tag::integer_value>();

```

I need get value from ‘freq’ param inside this remote-node (value was send from ‘configurator’ before with OK)

---

<div class="post-metadata">

**Author:** ![pavel.kirienko](https://forum.opencyphal.org/user_avatar/forum.opencyphal.org/pavel.kirienko/32/9_2.png) [@pavel.kirienko](https://forum.opencyphal.org/u/pavel.kirienko)\
**Post date:** [November 12, 2018, 12:20pm UTC](https://forum.opencyphal.org/t/how-configure-node-params/227/16 "2018-11-12T12:20:43Z")

</div>

You should use methods `as` and `is` instead of `to`:

```auto
/**
 * Whether the union is set to the given type.
 * Access by tag; this will work even if there are non-unique types within the union.
 */
bool is(typename Tag::Type x) const { return typename Tag::Type(_tag_) == x; }

/**
 * If the union is currently set to the type T, returns pointer to the appropriate field.
 * If the union is set to another type, returns null pointer.
 */
template <typename Tag::Type T>
inline const typename TagToType<T>::StorageType* as() const;

/**
 * Switches the union to the given type and returns a mutable reference to the appropriate field.
 * If the previous type was different, a default constructor will be called first.
 */
template <typename Tag::Type T>
inline typename TagToType<T>::StorageType& to();

```
