org-arl / unet-contrib

Unet user contributions
BSD 3-Clause "New" or "Revised" License
11 stars 15 forks source link

C API support for setting parameters which are arrays #60

Open prasadtiru opened 3 years ago

prasadtiru commented 3 years ago

In UnetSocket C APIs, we currently do not have support for setting parameters that are arrays. In order to do this, here is a suggested implementation of API:

int unetsocket_ext_fset_array(unetsocket_t sock, int index, char *target_name, char *param_name, float* value, int len)
{
    if (sock == NULL) return -1;
    _unetsocket_t *usock = sock;
    fjage_msg_t msg;
    fjage_aid_t aid;
    aid = agent_for_service(usock, target_name);
    if (aid == NULL) aid = fjage_aid_create(target_name);
    msg = fjage_msg_create(parameterreq, FJAGE_REQUEST);
    fjage_msg_set_recipient(msg, aid);
    if (index == 0) index = -1;
    fjage_msg_add_int(msg, "index", index);
    fjage_msg_add_string(msg, "param", param_name);
    fjage_msg_add_float_array(msg, "value", value, len);
    msg = request(usock, msg, 5 * TIMEOUT);
    if (msg != NULL && fjage_msg_get_performative(msg) == FJAGE_INFORM)
    {
        fjage_msg_destroy(msg);
        fjage_aid_destroy(aid);
        return 0;
    }
    fjage_msg_destroy(msg);
    fjage_aid_destroy(aid);
    return -1;
}

Currently, this implementation of API creates a JSON message which is incorrect. This is because of the way fjage_msg_add_float_array() adds the array. The array is base64 encoded but its type information is not included in the JSON.

mchitre commented 3 years ago

So this should be an issue on fjåge to fix?

prasadtiru commented 3 years ago

The corresponding issue in fjage is captured here: https://github.com/org-arl/fjage/issues/210

This issue is just to capture the need for implementing the API unetsocket_ext_fset_array().

mchitre commented 3 years ago

https://github.com/org-arl/fjage/commit/c6a3b8d3171ef1c86f558d842b26985ab7c1678a adds type information in JSON now. However, not including it should have worked, as the specification allows it and the regression tests for it pass.

What was the problem you were facing? Was it only on the latest fjåge dev version? If so, it might be related to another bug recently introduced in the dev version, and fixed in https://github.com/org-arl/fjage/commit/bbb369133e0562ffc12938467f447c57e1ddafbd. Check with the latest dev version of fjåge.

prasadtiru commented 3 years ago

The problem was when I was trying to set the node.location using the unetsocket_ext_fset_array() (implementation shown above), the parameter was not getting set. I looked at JSON message and found that the array was base64 encoded but without type information included in it. However, when I used groovy shell remotely and tried to set node.location, it was successful and the only difference was the JSON message, in this case, did not have array base64 encoded.

I was testing this earlier with the latest dev. However, I will test it out again with your recent above-mentioned fixes.

mchitre commented 3 years ago

Was there any error in the logs when you set it using unetsocket_ext_fset_array()?

prasadtiru commented 3 years ago

I did not see any error in the log file when I set it using unetsocket_ext_fset_array(). I have now created a branch setfloatarray from where we can reproduce this problem.

Steps to reproduce

  1. Checkout setfloatarray branch in unet-contrib repo.
  2. Go to the folder unetsocket/c
  3. Build the sample files by typing in
    make 
    make samples
  4. Run unet audio (use the latest fjage dev build to pick up the above fixes)
  5. Run the C program to set node.location
    samples/setfloatarray localhost 1100

Expected result:

node.location value must be set to [1.0, 2.0, 3.0]

Actual result:

node.location is empty

JSON message sent out to master container:

The JSON message (ParameterReq) that is sent out to master container to set the node.location is following:

{
   "action":"send",
   "relay":true,
   "message":{
      "clazz":"org.arl.fjage.param.ParameterReq",
      "data":{
         "msgID":"hpx3MLYv/yzMtIQeIbtPvxxAfXyTe0ExbUWo",
         "perf":"REQUEST",
         "recipient":"node",
         "sender":"CGatewayAgent@000041a7",
         "index":-1,
         "param":"location",
         "value":{
            "clazz":"[F",
            "data":"AACAPwAAAEAAAEBA"
         }
      }
   }

Response JSON message from master container:

The JSON message (ParameterRsp) that is sent out from master container is following:

{
   "action":"send",
   "message":{
      "clazz":"org.arl.fjage.param.ParameterRsp",
      "data":{
         "index":-1,
         "values":null,
         "param":null,
         "value":null,
         "readonly":[

         ],
         "msgID":"bcc9aa17-1430-4523-bd81-f0f3b7fd7e70",
         "perf":"INFORM",
         "recipient":"CGatewayAgent@000041a7",
         "sender":"node",
         "inReplyTo":"hpx3MLYv/yzMtIQeIbtPvxxAfXyTe0ExbUWo",
         "sentAt":1627011849399
      }
   },
   "relay":false
}
mchitre commented 3 years ago

The problem is the data type. NodeInfo.location is double[], whereas @prasadtiru you're trying to set a float[]. Try changing the data type in the C API.