diff --git a/components/esp_rainmaker/include/esp_rmaker_core.h b/components/esp_rainmaker/include/esp_rmaker_core.h index 20cfb98..41a3f09 100644 --- a/components/esp_rainmaker/include/esp_rmaker_core.h +++ b/components/esp_rainmaker/include/esp_rmaker_core.h @@ -74,6 +74,10 @@ typedef enum { RMAKER_VAL_TYPE_FLOAT, /** NULL terminated string */ RMAKER_VAL_TYPE_STRING, + /** NULL terminated JSON Object string Eg. {"name":"value"} */ + RMAKER_VAL_TYPE_OBJECT, + /** NULL terminated JSON Array string Eg. [1,2,3] */ + RMAKER_VAL_TYPE_ARRAY, } esp_rmaker_val_type_t; /** ESP RainMaker Value */ @@ -210,6 +214,33 @@ esp_rmaker_param_val_t esp_rmaker_float(float fval); */ esp_rmaker_param_val_t esp_rmaker_str(const char *sval); +/** + * Initialise a json object value + * + * @note the object will not be validated internally. it is the application's + * responsibility to ensure that the object is a valid json object. + * eg. esp_rmaker_obj("{\"name\":\"value\"}"); + * + * param[in] val initialising value + * + * return value structure + */ +esp_rmaker_param_val_t esp_rmaker_obj(const char *val); + +/** + * Initialise a json array value + * + * @note the array will not be validated internally. it is the application's + * responsibility to ensure that the array is a valid json array. + * eg. esp_rmaker_array("[1,2,3]"); + * + * param[in] val initialising value + * + * return value structure + */ +esp_rmaker_param_val_t esp_rmaker_array(const char *val); + + /** Initialize ESP RainMaker Node * * This initializes the ESP RainMaker agent and creates the node. diff --git a/components/esp_rainmaker/src/core/esp_rmaker_device.c b/components/esp_rainmaker/src/core/esp_rmaker_device.c index 20c3f93..cfbc62d 100644 --- a/components/esp_rainmaker/src/core/esp_rmaker_device.c +++ b/components/esp_rainmaker/src/core/esp_rmaker_device.c @@ -129,7 +129,8 @@ esp_err_t esp_rmaker_device_add_param(const esp_rmaker_device_t *device, const e stored_val.type = _new_param->val.type; if (_new_param->prop_flags & PROP_FLAG_PERSIST) { if (esp_rmaker_param_get_stored_value(_new_param, &stored_val) == ESP_OK) { - if (_new_param->val.type == RMAKER_VAL_TYPE_STRING) { + if ((_new_param->val.type == RMAKER_VAL_TYPE_STRING) || (_new_param->val.type == RMAKER_VAL_TYPE_OBJECT) + || (_new_param->val.type == RMAKER_VAL_TYPE_ARRAY)) { if (_new_param->val.val.s) { free(_new_param->val.val.s); } diff --git a/components/esp_rainmaker/src/core/esp_rmaker_node_config.c b/components/esp_rainmaker/src/core/esp_rmaker_node_config.c index 9b09f24..f8be2f9 100644 --- a/components/esp_rainmaker/src/core/esp_rmaker_node_config.c +++ b/components/esp_rainmaker/src/core/esp_rmaker_node_config.c @@ -83,6 +83,12 @@ esp_err_t esp_rmaker_report_value(const esp_rmaker_param_val_t *val, char *key, case RMAKER_VAL_TYPE_STRING: json_gen_obj_set_string(jptr, key, val->val.s); break; + case RMAKER_VAL_TYPE_OBJECT: + json_gen_push_object_str(jptr, key, val->val.s); + break; + case RMAKER_VAL_TYPE_ARRAY: + json_gen_push_array_str(jptr, key, val->val.s); + break; default: break; } @@ -104,6 +110,12 @@ esp_err_t esp_rmaker_report_data_type(esp_rmaker_val_type_t type, json_gen_str_t case RMAKER_VAL_TYPE_STRING: json_gen_obj_set_string(jptr, "data_type", "string"); break; + case RMAKER_VAL_TYPE_OBJECT: + json_gen_obj_set_string(jptr, "data_type", "object"); + break; + case RMAKER_VAL_TYPE_ARRAY: + json_gen_obj_set_string(jptr, "data_type", "array"); + break; default: json_gen_obj_set_string(jptr, "data_type", "invalid"); break; diff --git a/components/esp_rainmaker/src/core/esp_rmaker_param.c b/components/esp_rainmaker/src/core/esp_rmaker_param.c index 0bd1f0b..3dd748a 100644 --- a/components/esp_rainmaker/src/core/esp_rmaker_param.c +++ b/components/esp_rainmaker/src/core/esp_rmaker_param.c @@ -75,6 +75,24 @@ esp_rmaker_param_val_t esp_rmaker_str(const char *val) return param_val; } +esp_rmaker_param_val_t esp_rmaker_obj(const char *val) +{ + esp_rmaker_param_val_t param_val = { + .type = RMAKER_VAL_TYPE_OBJECT, + .val.s = (char *)val + }; + return param_val; +} + +esp_rmaker_param_val_t esp_rmaker_array(const char *val) +{ + esp_rmaker_param_val_t param_val = { + .type = RMAKER_VAL_TYPE_ARRAY, + .val.s = (char *)val + }; + return param_val; +} + static esp_err_t esp_rmaker_report_params(uint8_t flags, bool init) { json_gen_str_t jstr; @@ -158,12 +176,43 @@ static esp_err_t esp_rmaker_handle_get_params(_esp_rmaker_device_t *device, jpar if (json_obj_get_strlen(jptr, param->name, &val_size) == 0) { val_size++; /* For NULL termination */ new_val.val.s = calloc(1, val_size); + if (!new_val.val.s) { + return ESP_ERR_NO_MEM; + } json_obj_get_string(jptr, param->name, new_val.val.s, val_size); new_val.type = RMAKER_VAL_TYPE_STRING; param_found = true; } break; } + case RMAKER_VAL_TYPE_OBJECT: { + int val_size = 0; + if (json_obj_get_object_strlen(jptr, param->name, &val_size) == 0) { + val_size++; /* For NULL termination */ + new_val.val.s = calloc(1, val_size); + if (!new_val.val.s) { + return ESP_ERR_NO_MEM; + } + json_obj_get_object_str(jptr, param->name, new_val.val.s, val_size); + new_val.type = RMAKER_VAL_TYPE_OBJECT; + param_found = true; + } + break; + } + case RMAKER_VAL_TYPE_ARRAY: { + int val_size = 0; + if (json_obj_get_array_strlen(jptr, param->name, &val_size) == 0) { + val_size++; /* For NULL termination */ + new_val.val.s = calloc(1, val_size); + if (!new_val.val.s) { + return ESP_ERR_NO_MEM; + } + json_obj_get_array_str(jptr, param->name, new_val.val.s, val_size); + new_val.type = RMAKER_VAL_TYPE_ARRAY; + param_found = true; + } + break; + } default: break; } @@ -177,11 +226,13 @@ static esp_err_t esp_rmaker_handle_get_params(_esp_rmaker_device_t *device, jpar esp_rmaker_write_ctx_t ctx = { .src = ESP_RMAKER_REQ_SRC_CLOUD, }; - if (device->write_cb((esp_rmaker_device_t *)device, (esp_rmaker_param_t *)param, new_val, device->priv_data, &ctx) != ESP_OK) { + if (device->write_cb((esp_rmaker_device_t *)device, (esp_rmaker_param_t *)param, + new_val, device->priv_data, &ctx) != ESP_OK) { ESP_LOGE(TAG, "Remote update to param %s - %s failed", device->name, param->name); } } - if (new_val.type == RMAKER_VAL_TYPE_STRING) { + if ((new_val.type == RMAKER_VAL_TYPE_STRING) || (new_val.type == RMAKER_VAL_TYPE_OBJECT || + (new_val.type == RMAKER_VAL_TYPE_ARRAY))) { if (new_val.val.s) { free(new_val.val.s); } @@ -234,7 +285,8 @@ esp_err_t esp_rmaker_param_get_stored_value(_esp_rmaker_param_t *param, esp_rmak if (err != ESP_OK) { return err; } - if (param->val.type == RMAKER_VAL_TYPE_STRING) { + if ((param->val.type == RMAKER_VAL_TYPE_STRING) || (param->val.type == RMAKER_VAL_TYPE_OBJECT) || + (param->val.type == RMAKER_VAL_TYPE_ARRAY)) { size_t len = 0; if ((err = nvs_get_str(handle, param->name, NULL, &len)) == ESP_OK) { char *s_val = calloc(1, len); @@ -264,7 +316,8 @@ esp_err_t esp_rmaker_param_store_value(_esp_rmaker_param_t *param) if (err != ESP_OK) { return err; } - if (param->val.type == RMAKER_VAL_TYPE_STRING) { + if ((param->val.type == RMAKER_VAL_TYPE_STRING) || (param->val.type == RMAKER_VAL_TYPE_OBJECT) || + (param->val.type == RMAKER_VAL_TYPE_ARRAY)) { /* Store only if value is not NULL */ if (param->val.val.s) { err = nvs_set_str(handle, param->name, param->val.val.s); @@ -324,7 +377,8 @@ esp_rmaker_param_t *esp_rmaker_param_create(const char *param_name, const char * } param->val.type = val.type; param->prop_flags = properties; - if (val.type == RMAKER_VAL_TYPE_STRING) { + if ((val.type == RMAKER_VAL_TYPE_STRING) || (val.type == RMAKER_VAL_TYPE_OBJECT) || + (val.type == RMAKER_VAL_TYPE_ARRAY)) { if (val.val.s) { param->val.val.s = strdup(val.val.s); if (!param->val.val.s) { @@ -392,7 +446,9 @@ esp_err_t esp_rmaker_param_update(const esp_rmaker_param_t *param, esp_rmaker_pa return ESP_ERR_INVALID_ARG; } switch (_param->val.type) { - case RMAKER_VAL_TYPE_STRING: { + case RMAKER_VAL_TYPE_STRING: + case RMAKER_VAL_TYPE_OBJECT: + case RMAKER_VAL_TYPE_ARRAY: { char *new_val = NULL; if (val.val.s) { new_val = strdup(val.val.s);