Skip to content

Commit

Permalink
Merge branch 'task/bulk_write' into 'master'
Browse files Browse the repository at this point in the history
esp_rmaker_param: Handle multiple params simultaneously in a single callback

See merge request app-frameworks/esp-rainmaker!356
  • Loading branch information
shahpiyushv committed Jun 21, 2024
2 parents 8da28b0 + b6ca97d commit a3bdac0
Show file tree
Hide file tree
Showing 14 changed files with 231 additions and 102 deletions.
2 changes: 1 addition & 1 deletion components/esp_rainmaker/idf_component.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
## IDF Component Manager Manifest File
version: "1.1.0"
version: "1.2.0"
description: ESP RainMaker firmware agent
url: https://github.com/espressif/esp-rainmaker/tree/master/components/esp_rainmaker
repository: https://github.com/espressif/esp-rainmaker.git
Expand Down
76 changes: 73 additions & 3 deletions components/esp_rainmaker/include/esp_rmaker_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -211,14 +211,44 @@ typedef struct {
int8_t reset_reboot_seconds;
} esp_rmaker_system_serv_config_t;


/** Parameter write request payload */
typedef struct {
/** Parameter handle */
esp_rmaker_param_t *param;
/** Value to write */
esp_rmaker_param_val_t val;
} esp_rmaker_param_write_req_t;

/** Callback for bulk parameter value write requests.
*
*
* This callback is recommended over esp_rmaker_device_write_cb_t since it gives all values of a given device together,
* which will help if the parameters are related to each other.
*
* The callback should call the esp_rmaker_param_update_and_report() API if the new value is to be set
* and reported back.
*
* @param[in] device Device handle.
* @param[in] write_reqs Array of parameter write request payloads.
* @param[in] count Count of parameters and their values passed to this callback
* @param[in] priv_data Pointer to the private data paassed while creating the device.
* @param[in] ctx Context associated with the request.
*
* @return ESP_OK on success.
* @return error in case of failure.
*/
typedef esp_err_t (*esp_rmaker_device_bulk_write_cb_t)(const esp_rmaker_device_t *device, const esp_rmaker_param_write_req_t write_req[],
uint8_t count, void *priv_data, esp_rmaker_write_ctx_t *ctx);

/** Callback for parameter value write requests.
*
* The callback should call the esp_rmaker_param_update_and_report() API if the new value is to be set
* and reported back.
*
* @param[in] device Device handle.
* @param[in] param Parameter handle.
* @param[in] param Pointer to \ref esp_rmaker_param_val_t. Use appropriate elements as per the value type.
* @param[in] val Pointer to \ref esp_rmaker_param_val_t. Use appropriate elements as per the value type.
* @param[in] priv_data Pointer to the private data paassed while creating the device.
* @param[in] ctx Context associated with the request.
*
Expand All @@ -228,13 +258,33 @@ typedef struct {
typedef esp_err_t (*esp_rmaker_device_write_cb_t)(const esp_rmaker_device_t *device, const esp_rmaker_param_t *param,
const esp_rmaker_param_val_t val, void *priv_data, esp_rmaker_write_ctx_t *ctx);

/** Callback for parameter value changes
/** Callback for bulk parameter value reads
*
* The callback should call the esp_rmaker_param_update_and_report() API if the new value is to be set
* and reported back.
*
* @note Currently, the read callback never gets invoked as the communication between clients (mobile phones, CLI, etc.)
* and node is asynchronous. So, the read request does not reach the node. This callback will however be used in future.
* and node is asynchronous. So, the read request does not reach the node. This callback may however be used in future.
*
* @param[in] device Device handle.
* @param[in] params Array of Parameter handles.
* @param[in] count Count of parameters passed to this callback.
* @param[in] priv_data Pointer to the private data passed while creating the device.
* @param[in] ctx Context associated with the request.
*
* @return ESP_OK on success.
* @return error in case of failure.
*/
typedef esp_err_t (*esp_rmaker_device_bulk_read_cb_t)(const esp_rmaker_device_t *device, const esp_rmaker_param_t *params[],
uint8_t count, void *priv_data, esp_rmaker_read_ctx_t *ctx);

/** Callback for parameter value reads
*
* The callback should call the esp_rmaker_param_update_and_report() API if the new value is to be set
* and reported back.
*
* @note Currently, the read callback never gets invoked as the communication between clients (mobile phones, CLI, etc.)
* and node is asynchronous. So, the read request does not reach the node. This callback may however be used in future.
*
* @param[in] device Device handle.
* @param[in] param Parameter handle.
Expand Down Expand Up @@ -528,6 +578,24 @@ esp_err_t esp_rmaker_device_delete(const esp_rmaker_device_t *device);
*/
esp_err_t esp_rmaker_device_add_cb(const esp_rmaker_device_t *device, esp_rmaker_device_write_cb_t write_cb, esp_rmaker_device_read_cb_t read_cb);

/**
* Add bulk callbacks for a device/service
*
* Add bulk read/write callbacks for a device that will be invoked as per requests received from the cloud (or other paths
* as may be added in future).
*
* This is an improvement over the earlier callbacks registered using esp_rmaker_device_add_cb() so that all parameters
* received in a single request are passed to the callback together, instead of one by one.
*
* @param[in] device Device handle.
* @param[in] write_cb Bulk Write callback.
* @param[in] read_cb Bulk Read callback.
*
* @return ESP_OK on success.
* @return error in case of failure.
*/
esp_err_t esp_rmaker_device_add_bulk_cb(const esp_rmaker_device_t *device, esp_rmaker_device_bulk_write_cb_t write_cb, esp_rmaker_device_bulk_read_cb_t read_cb);

/**
* Add a device to a node
*
Expand Down Expand Up @@ -785,6 +853,8 @@ esp_err_t esp_rmaker_param_add_array_max_count(const esp_rmaker_param_t *param,
* and the last one can be updated using esp_rmaker_param_update_and_report().
* This will report all parameters which were updated prior to this call.
*
* @note This does not report to time series even if PROP_FLAG_TIME_SERIES is set.
*
* Sample:
*
* esp_rmaker_param_update(param1, esp_rmaker_float(10.2));
Expand Down
47 changes: 47 additions & 0 deletions components/esp_rainmaker/src/core/esp_rmaker_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,37 @@ esp_err_t esp_rmaker_device_delete(const esp_rmaker_device_t *device)
return ESP_ERR_INVALID_ARG;
}

static esp_err_t esp_rmaker_default_bulk_write_cb(const esp_rmaker_device_t *device, const esp_rmaker_param_write_req_t write_req[],
uint8_t count, void *priv_data, esp_rmaker_write_ctx_t *ctx)
{
_esp_rmaker_device_t *_device = (_esp_rmaker_device_t *)device;
_esp_rmaker_param_t *param;
if (_device) {
for (int i = 0; i < count; i++) {
param = (_esp_rmaker_param_t *)(write_req[i].param);
if (param->type && (strcmp(param->type, ESP_RMAKER_PARAM_NAME) == 0)) {
#ifndef CONFIG_RMAKER_NAME_PARAM_CB
esp_rmaker_param_update(write_req[i].param, write_req[i].val);
continue;
#else
if (!_device->write_cb) {
esp_rmaker_param_update(write_req[i].param, write_req[i].val);
continue;
}
#endif
}
if (_device->write_cb) {
if (_device->write_cb(device, write_req[i].param, write_req[i].val, priv_data, ctx) != ESP_OK) {
ESP_LOGE(TAG, "Remote update to param %s - %s failed", _device->name, ((_esp_rmaker_param_t *)(write_req[i].param))->name);
}
} else {
ESP_LOGW(TAG, "No write callback for device %s", _device->name);
}
}
}
return ESP_OK;
}

static esp_rmaker_device_t *__esp_rmaker_device_create(const char *name, const char *type, void *priv, bool is_service)
{
if (!name) {
Expand All @@ -85,6 +116,8 @@ static esp_rmaker_device_t *__esp_rmaker_device_create(const char *name, const c
}
_device->priv_data = priv;
_device->is_service = is_service;
/* Adding a default bulk write callback for backward compatibility with application code using single param write callback */
_device->bulk_write_cb = esp_rmaker_default_bulk_write_cb;

return (esp_rmaker_device_t *)_device;

Expand Down Expand Up @@ -129,6 +162,7 @@ esp_err_t esp_rmaker_device_add_param(const esp_rmaker_device_t *device, const e
} else {
_device->params = _new_param;
}
_device->param_count++;
/* We check the stored value here, and not during param creation, because a parameter
* in itself isn't unique. However, it is unique within a given device and hence can
* be uniquely represented in storage only when added to a device.
Expand Down Expand Up @@ -267,6 +301,19 @@ esp_err_t esp_rmaker_device_add_cb(const esp_rmaker_device_t *device, esp_rmaker
return ESP_OK;
}

esp_err_t esp_rmaker_device_add_bulk_cb(const esp_rmaker_device_t *device, esp_rmaker_device_bulk_write_cb_t write_cb,
esp_rmaker_device_bulk_read_cb_t read_cb)
{
if (!device) {
ESP_LOGE(TAG, "Device handle cannot be NULL");
return ESP_ERR_INVALID_ARG;
}
_esp_rmaker_device_t *_device = (_esp_rmaker_device_t *)device;
_device->bulk_write_cb = write_cb;
_device->bulk_read_cb = read_cb;
return ESP_OK;
}

char *esp_rmaker_device_get_name(const esp_rmaker_device_t *device)
{
if (!device) {
Expand Down
3 changes: 3 additions & 0 deletions components/esp_rainmaker/src/core/esp_rmaker_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,11 @@ struct esp_rmaker_device {
char *type;
char *subtype;
char *model;
uint8_t param_count;
esp_rmaker_device_write_cb_t write_cb;
esp_rmaker_device_read_cb_t read_cb;
esp_rmaker_device_bulk_write_cb_t bulk_write_cb;
esp_rmaker_device_bulk_read_cb_t bulk_read_cb;
void *priv_data;
bool is_service;
esp_rmaker_attr_t *attributes;
Expand Down
Loading

0 comments on commit a3bdac0

Please sign in to comment.