Skip to content

Commit 013328f

Browse files
committed
Added command-response interface
- Parse incoming data from rmaker_cmd_resp and call insights_config_update - Publish a message to rmaker that we support command resp - Subscribe to command response topic Two command response APIs: init and enable - The init part is only used by ESP-Insights and is not needed by RainMaker. This is because, RainMaker already does this.
1 parent 129d8a2 commit 013328f

10 files changed

+756
-1
lines changed

components/esp_diagnostics/include/esp_diagnostics.h

+1
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ typedef enum {
103103
ESP_DIAG_DATA_TYPE_STR, /*!< Data type string */
104104
ESP_DIAG_DATA_TYPE_IPv4, /*!< Data type IPv4 address */
105105
ESP_DIAG_DATA_TYPE_MAC, /*!< Data type MAC address */
106+
ESP_DIAG_DATA_TYPE_INVALID, /*!< Not supported by diagnostics */
106107
} esp_diag_data_type_t;
107108

108109
/**

components/esp_insights/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ set(srcs "src/esp_insights.c"
33
"src/esp_insights_transport.c"
44
"src/esp_insights_client_data.c"
55
"src/esp_insights_encoder.c"
6+
"src/esp_insights_cmd_resp.c"
67
"src/esp_insights_cbor_decoder.c"
78
"src/esp_insights_cbor_encoder.c")
89

components/esp_insights/Kconfig

+10
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,16 @@ menu "ESP Insights"
4141

4242
endchoice
4343

44+
config ESP_INSIGHTS_CMD_RESP_ENABLED
45+
depends on (ESP_INSIGHTS_ENABLED && ESP_INSIGHTS_TRANSPORT_MQTT)
46+
bool "Enable command response module"
47+
default n
48+
help
49+
Enabling this option adds control of certain insights options remotely.
50+
When enabled, the available configurations, should be shown on the dashboard
51+
and controllable from there.
52+
Please note, the feature is only available with RainMaker MQTT nodes for now.
53+
4454
config ESP_INSIGHTS_TRANSPORT_HTTPS_HOST
4555
depends on ESP_INSIGHTS_TRANSPORT_HTTPS
4656
string "Insights https host"

components/esp_insights/include/esp_insights.h

+23
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66

77
#pragma once
8+
89
#include <stdint.h>
910
#include <esp_err.h>
1011
#include <esp_event_base.h>
@@ -200,6 +201,28 @@ void esp_insights_disable(void);
200201
* @return Pointer to a NULL terminated Node ID string.
201202
*/
202203
const char *esp_insights_get_node_id(void);
204+
205+
/**
206+
* @brief Encode and parse the command directly using esp-insight's parser
207+
*
208+
* This tests only if the parser is working as expected.
209+
*/
210+
esp_err_t esp_insights_test_cmd_handler();
211+
212+
/**
213+
* @brief Enable esp-insights command-response module
214+
*
215+
* This API registers esp-insights command parser which when data is received,
216+
* parses it to filter out insights specific data, modifies configs accordingly,
217+
* and prepares and gives response data to the module
218+
*
219+
* The \ref esp_insights_init takes care of initializing command response and
220+
* enabling the same. In cases where, only esp_insights_enable is called, e.g.,
221+
* ESP Rainmaker's app_insights module, user needs to call this API, before or
222+
* after \ref esp_insights_enable
223+
*/
224+
esp_err_t esp_insights_cmd_resp_enable(void);
225+
203226
#ifdef __cplusplus
204227
}
205228
#endif

components/esp_insights/src/esp_insights.c

+8
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060

6161
#define SEND_INSIGHTS_META (CONFIG_DIAG_ENABLE_METRICS || CONFIG_DIAG_ENABLE_VARIABLES)
6262

63+
/* TAG for reporting generic miscellaneous insights. Different from ESP_LOGx tag */
6364
#define TAG_DIAG "diag"
6465
#define KEY_LOG_WR_FAIL "log_wr_fail"
6566

@@ -105,6 +106,8 @@ static const char *TAG = "esp_insights";
105106
static esp_insights_data_t s_insights_data;
106107
static esp_insights_entry_t *s_periodic_insights_entry;
107108

109+
extern esp_err_t esp_insights_cmd_resp_init(void);
110+
108111
static void esp_insights_first_call(void *priv_data)
109112
{
110113
if (!priv_data) {
@@ -927,6 +930,11 @@ esp_err_t esp_insights_init(esp_insights_config_t *config)
927930
}
928931

929932
s_insights_data.init_done = true;
933+
934+
err = esp_insights_cmd_resp_init() || esp_insights_cmd_resp_enable();
935+
if (err != ESP_OK) { /* device can keep working neverthless */
936+
ESP_LOGE(TAG, "Failed to enable insights_cmd_resp");
937+
}
930938
return ESP_OK;
931939
init_err:
932940
if (s_insights_data.node_id) {

components/esp_insights/src/esp_insights_cbor_decoder.c

+99
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <esp_rmaker_utils.h>
1212

1313
#include <cbor.h>
14+
#include "esp_insights_cbor_decoder.h"
1415

1516
static const char *TAG = "insight_cbor_dec";
1617

@@ -281,3 +282,101 @@ esp_err_t esp_insights_cbor_decode_dump(const uint8_t *buffer, int len)
281282

282283
return ESP_OK;
283284
}
285+
286+
bool esp_insights_cbor_decoder_at_end(cbor_parse_ctx_t *ctx)
287+
{
288+
return cbor_value_at_end(&ctx->it[ctx->curr_itr]);
289+
}
290+
291+
esp_err_t esp_insights_cbor_decoder_advance(cbor_parse_ctx_t *ctx)
292+
{
293+
if (CborNoError == cbor_value_advance(&ctx->it[ctx->curr_itr])) {
294+
return ESP_OK;
295+
}
296+
return ESP_FAIL;
297+
}
298+
299+
CborType esp_insights_cbor_decode_get_value_type(cbor_parse_ctx_t *ctx)
300+
{
301+
return cbor_value_get_type(&ctx->it[ctx->curr_itr]);
302+
}
303+
304+
char *esp_insights_cbor_decoder_get_string(CborValue *val)
305+
{
306+
CborError ret = CborNoError;
307+
char *buf = NULL;
308+
size_t n;
309+
if (cbor_value_get_type(val) != CborTextStringType) {
310+
return NULL;
311+
}
312+
ret = cbor_value_dup_text_string(val, &buf, &n, val);
313+
if (ret == CborNoError) {
314+
return (char *) buf;
315+
}
316+
return NULL;
317+
}
318+
319+
esp_err_t esp_insights_cbor_decoder_enter_container(cbor_parse_ctx_t *ctx)
320+
{
321+
CborError ret = CborNoError;
322+
int curr_itr = ctx->curr_itr;
323+
if (curr_itr >= INS_CBOR_MAX_DEPTH) {
324+
ESP_LOGE(TAG, "Cannot parse depth more than %d", INS_CBOR_MAX_DEPTH);
325+
return ESP_FAIL;
326+
}
327+
ret = cbor_value_enter_container(&ctx->it[curr_itr], &ctx->it[curr_itr + 1]);
328+
if (ret != CborNoError) {
329+
ESP_LOGE(TAG, "error entering container");
330+
return ESP_FAIL;
331+
}
332+
if (esp_insights_cbor_decoder_at_end(ctx)) {
333+
return ESP_FAIL;
334+
}
335+
ctx->curr_itr++;
336+
337+
return ESP_OK;
338+
}
339+
340+
esp_err_t esp_insights_cbor_decoder_exit_container(cbor_parse_ctx_t *ctx)
341+
{
342+
CborError ret = CborNoError;
343+
if (ctx->curr_itr <= 0) {
344+
ESP_LOGE(TAG, "cannot exit, already at top");
345+
return ESP_FAIL;
346+
}
347+
ctx->curr_itr--;
348+
int curr_itr = ctx->curr_itr;
349+
ret = cbor_value_leave_container(&ctx->it[curr_itr], &ctx->it[curr_itr + 1]);
350+
if (ret != CborNoError) {
351+
ESP_LOGE(TAG, "error leaving container");
352+
return ESP_FAIL;
353+
}
354+
return ESP_OK;
355+
}
356+
357+
esp_err_t esp_insights_cbor_decoder_done(cbor_parse_ctx_t *ctx)
358+
{
359+
if (ctx) {
360+
free(ctx);
361+
}
362+
return ESP_OK;
363+
}
364+
365+
cbor_parse_ctx_t *esp_insights_cbor_decoder_start(const uint8_t *buffer, int len)
366+
{
367+
if (!buffer || len == 0) {
368+
return NULL;
369+
}
370+
cbor_parse_ctx_t *ctx = calloc(1, sizeof(cbor_parse_ctx_t));
371+
if (!ctx) {
372+
ESP_LOGE(TAG, "failed to allocate cbor ctx");
373+
return NULL;
374+
}
375+
CborParser root_parser = ctx->root_parser;
376+
CborValue *it = &ctx->it[0];
377+
if (cbor_parser_init(buffer, len, 0, &root_parser, it) != CborNoError) {
378+
ESP_LOGE(TAG, "Error initializing cbor parser");
379+
return NULL;
380+
}
381+
return ctx;
382+
}

components/esp_insights/src/esp_insights_cbor_decoder.h

+24
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,30 @@
1515

1616
#include <cbor.h>
1717

18+
#include <esp_err.h>
19+
20+
#define INS_CBOR_MAX_DEPTH 12 // depth to which we can traverse
21+
22+
typedef struct cbor_parse_ctx {
23+
CborParser root_parser;
24+
CborValue it[INS_CBOR_MAX_DEPTH + 1];
25+
int curr_itr;
26+
} cbor_parse_ctx_t;
27+
28+
cbor_parse_ctx_t *esp_insights_cbor_decoder_start(const uint8_t *buffer, int len);
29+
esp_err_t esp_insights_cbor_decoder_enter_and_check_value(cbor_parse_ctx_t *ctx, const char *val);
30+
bool esp_insights_cbor_decoder_at_end(cbor_parse_ctx_t *ctx);
31+
32+
esp_err_t esp_insights_cbor_decoder_advance(cbor_parse_ctx_t *ctx);
33+
CborType esp_insights_cbor_decode_get_value_type(cbor_parse_ctx_t *ctx);
34+
char *esp_insights_cbor_decoder_get_string(CborValue *val);
35+
36+
esp_err_t esp_insights_cbor_decoder_enter_container(cbor_parse_ctx_t *ctx);
37+
esp_err_t esp_insights_cbor_decoder_exit_container(cbor_parse_ctx_t *ctx);
38+
39+
/* Do cleanups if any */
40+
esp_err_t esp_insights_cbor_decoder_done(cbor_parse_ctx_t *ctx);
41+
1842
/**
1943
* @brief decodes a cbor message and prints into json format
2044
*

0 commit comments

Comments
 (0)