Skip to content

Commit

Permalink
add function for RPC calls
Browse files Browse the repository at this point in the history
  • Loading branch information
twendtland committed Nov 14, 2024
1 parent db8f36e commit 89919b9
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 0 deletions.
14 changes: 14 additions & 0 deletions include/thingsboard.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,20 @@ time_t thingsboard_time_msec(void);
*/
int thingsboard_send_telemetry(const void *payload, size_t sz);

/**
* This callback will be called when the response for an RPC call
* was received from the Thingsboard server.
*/
typedef void (*rpc_callback_t)(const uint8_t *data, size_t len);

/**
* Send RPC call.
* 'method' is required, a callback in case the call returns data, too.
* Parameters are an optional string in JSON format as the variadic arguments
* See https://thingsboard.io/docs/reference/coap-api/#client-side-rpc for details.
*/
void thingsboard_rpc(const char *method, rpc_callback_t cb, ...);

struct tb_fw_id {
/** Title of your firmware, e.g. <project>-prod. This
* must match to what you configure on your thingsboard
Expand Down
66 changes: 66 additions & 0 deletions src/thingsboard.c
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#include "thingsboard.h"

#include <string.h>
#include <stdio.h>

#include <zephyr/kernel.h>
#include <zephyr/net/coap.h>
#include <zephyr/net/http/client.h>
#include <thingsboard_attr_parser.h>

#include "coap_client.h"
Expand All @@ -22,6 +24,7 @@ static struct {
K_SEM_DEFINE(time_sem, 0, 1);

static attr_write_callback_t attribute_cb;
static rpc_callback_t rpc_cb;

static void client_request_time(struct k_work *work);
K_WORK_DELAYABLE_DEFINE(work_time, client_request_time);
Expand Down Expand Up @@ -189,6 +192,69 @@ static void client_request_time(struct k_work *work)
k_work_reschedule(k_work_delayable_from_work(work), K_SECONDS(10));
}

static int client_handle_rpc_response(struct coap_client_request *req, struct coap_packet *response)
{
const uint8_t *payload;
uint16_t payload_len;
uint8_t code;
char code_str[5];
char expected_code_str[5];

LOG_INF("%s", __func__);

code = coap_header_get_code(response);
if (code != COAP_RESPONSE_CODE_CONTENT) {
coap_response_code_to_str(code, code_str);
coap_response_code_to_str(COAP_RESPONSE_CODE_CONTENT, expected_code_str);
LOG_ERR("Unexpected response code for RPC request: got %s, expected %s", code_str,
expected_code_str);
return -1;
}

payload = coap_packet_get_payload(response, &payload_len);
if (!payload_len) {
LOG_ERR("Received an empty RCP response");
return payload_len;
}

if (rpc_cb) {
rpc_cb(payload, payload_len);
}

return 0;
}

void thingsboard_rpc(const char *method, rpc_callback_t cb, ...)
{
int err;
va_list param;
char params[64];
char payload[128];

if (method == NULL) {
LOG_ERR("method name must not be 'NULL'");
return;
}

va_start(param, cb);
bool params_exist = vsnprintf(params, sizeof(params), "%s", param) > 0 ? true : false;
if (!params_exist) {
strcpy(params, "{}");
}
va_end(param);

// TODO: check length of params
snprintf(payload, sizeof(payload), "{\"method\":\"%s\", \"params\": %s}", method, params);
const uint8_t *uri[] = {"api", "v1", access_token, "rpc", NULL};

err = coap_client_make_request(uri, payload, strlen(payload), COAP_TYPE_CON,
COAP_METHOD_POST, client_handle_rpc_response);
if (err) {
LOG_ERR("Failed to perform RPC");
}
rpc_cb = cb;
}

int thingsboard_send_telemetry(const void *payload, size_t sz)
{
int err;
Expand Down

0 comments on commit 89919b9

Please sign in to comment.