RPC behaving differently on previously working functions

Description

Some RPC functions are able to send data to functions but do not send data back through golioth and output errors on both the device and the webpage/api call. These commands were previously working just fine but at some point in the past month or so they stopped functioning as expected. It is only some of the functions that aren’t working as expected.

Expected Behavior

The RPC call should occur without error sending the data to the device and receiving it back.

Actual Behavior

RPC call sends data to the device successfully however the device outputs an error and never responds back to the RPC call. On the webpage the RPC waits until timeout and then outputs an error.

Environment

Using ESP-IDF 5.1.6 and Golioth SDK 0.18.1

Logs and Console Output

Webpage output: Error (No response):
set_state(“00000.CON.X”)

Device output:
W (796656) golioth_coap_client_libcoap: 4.00 (req type: 3, path: .rpc/status), len 0

Attempts to Resolve

I have tried going back to previous versions of the firmware but the problem persists. This is why I think the issue is due to some kind of change on Golioth’s end.

Additional Information

Here are the RPC functions that are working with no errors:

static enum golioth_rpc_status on_multiply(
zcbor_state_t* request_params_array,
zcbor_state_t* response_detail_map,
void* callback_arg) {
double a, b;
double value;
bool ok;

ok = zcbor_float_decode(request_params_array, &a)
        && zcbor_float_decode(request_params_array, &b);
if (!ok) {
    GLTH_LOGE(TAG, "Failed to decode array items");
    return GOLIOTH_RPC_INVALID_ARGUMENT;
}

value = a * b;

GLTH_LOGD(TAG, "%lf * %lf = %lf", a, b, value);

ok = zcbor_tstr_put_lit(response_detail_map, "value")
        && zcbor_float64_put(response_detail_map, value);
if (!ok) {
    GLTH_LOGE(TAG, "Failed to encode value");
    return GOLIOTH_RPC_RESOURCE_EXHAUSTED;
}

return GOLIOTH_RPC_OK;

}

static enum golioth_rpc_status update_firmware(
zcbor_state_t* request_params_array,
zcbor_state_t* response_detail_map,
void* callback_arg) {

nvs_write_str("g_upd","1");

nvs_write_str("g_com","00000.RES.");
return GOLIOTH_RPC_OK;

}

static enum golioth_rpc_status accept_payment(
zcbor_state_t* request_params_array,
zcbor_state_t* response_detail_map,
void* callback_arg) {

nvs_write_str("g_pay","1");
return GOLIOTH_RPC_OK;

}

static enum golioth_rpc_status reject_payment(
zcbor_state_t* request_params_array,
zcbor_state_t* response_detail_map,
void* callback_arg) {
nvs_write_str(“g_pay”,“0”);
return GOLIOTH_RPC_OK;
}

Here are the RPC functions that are throwing the error:

static enum golioth_rpc_status set_state(
zcbor_state_t* request_params_array,
zcbor_state_t* response_detail_map,
void* callback_arg) {
struct zcbor_string value;
bool ok;
ok = zcbor_tstr_decode(request_params_array, &value);
if (!ok) {
GLTH_LOGE(TAG, “Failed to decode array items”);
return GOLIOTH_RPC_INVALID_ARGUMENT;
}
ok = zcbor_bool_put(response_detail_map, true)
&& zcbor_tstr_put_lit(response_detail_map, “test”);

if (!ok) {
    GLTH_LOGE(TAG, "Failed to encode value");
    return GOLIOTH_RPC_RESOURCE_EXHAUSTED;
}


char sendme[value.len+1];
sendme[value.len] = '\0';
for(int i = 0; i < value.len;i++){
    sendme[i] = value.value[i];
}
char* nvs_string = strdup(sendme);
nvs_write_str("g_com",nvs_string);
free(nvs_string);
GLTH_LOGI(TAG,"Received Remote command: %s", sendme);
return GOLIOTH_RPC_OK;

}

static enum golioth_rpc_status receive_state(
zcbor_state_t* request_params_array,
zcbor_state_t* response_detail_map,
void* callback_arg) {
char* value = strdup(nvs_read_golioth_com());
bool ok;
int i = 0;
int size = 0;
while(value[size] != ‘\0’){
size = size+1;
}
size = size+1;
char state[size];
while(i < size){
state[i] = value[i];
i = i+1;
}

@nathanael thank you for reporting this behavior! We are looking into it and will follow up with more information.

@nathanael it appears as though the receive_state RPC handler you shared may be incomplete – are you able to share the response you are attempting to return (similar to how you have shared the full handler for set_state)?

@nathanael We have deployed a fix that should address the issue you were experiencing. We believe the source of the issue was the use of a non-string key in the response detail in the failing RPCs (i.e. {true: “test”} rather than {“test”: true}). Though these RPCs should no longer fail, we typically see this when keys and values are accidentally flipped in firmware, so I wanted to make sure to point it out .

Thanks again for the detailed report!

The fix seems to be working on our end. Also the boolean key in the JSON response was a bit of janky engineering on my end. Thanks for pointing it out.

1 Like