Skip to content

Commit c1e3016

Browse files
committed
Merge branch 'task/group-topics' into 'master'
esp_rmaker_groups: Add handling for group ids for direct MQTT messaging See merge request app-frameworks/esp-rainmaker!607
2 parents c1089bd + a60204b commit c1e3016

17 files changed

+379
-13
lines changed

components/esp_rainmaker/CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
# Changelog
22

3+
## 1.8.6
4+
5+
### New Feature
6+
7+
- Added Groups service to enable direct MQTT communication between nodes and clients (phone apps/controllers).
8+
- Setting group_id via the Groups service routes local param updates to group-specific topics
9+
(`node/<node_id>/params/local/<group_id>`) for lower latency.
10+
- Also added `esp_rmaker_publish_direct()` API to publish messages on `node/<node_id>/direct/params/local/<group_id>`
11+
for direct client-to-node communication, bypassing cloud processing for reduced cost and latency.
12+
- Clients can also publish param updates directly to `node/<node_id>/params/remote/<group_id>` instead of
13+
using the set params API.
14+
315
## 1.8.5
416

517
### Changes

components/esp_rainmaker/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ set(core_srcs "src/core/esp_rmaker_core.c"
1212
"src/core/esp_rmaker_node_auth.c"
1313
"src/core/esp_rmaker_schedule.c"
1414
"src/core/esp_rmaker_scenes.c"
15+
"src/core/esp_rmaker_groups.c"
1516
"src/core/esp_rmaker_secure_boot_digest.c"
1617
"src/core/esp_rmaker_aws_credentials.c"
1718
)

components/esp_rainmaker/idf_component.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
version: "1.8.5"
1+
## IDF Component Manager Manifest File
2+
version: "1.8.6"
23
description: ESP RainMaker firmware agent
34
url: https://github.com/espressif/esp-rainmaker/tree/master/components/esp_rainmaker
45
repository: https://github.com/espressif/esp-rainmaker.git

components/esp_rainmaker/include/esp_rmaker_core.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,6 +1181,33 @@ esp_rmaker_aws_credentials_t* esp_rmaker_get_aws_security_token(const char *role
11811181
*/
11821182
void esp_rmaker_free_aws_credentials(esp_rmaker_aws_credentials_t *credentials);
11831183

1184+
/** Store group_id in NVS
1185+
*
1186+
* @param[in] group_id The group_id to store
1187+
*
1188+
* @return ESP_OK on success
1189+
* @return error in case of failure
1190+
*/
1191+
esp_err_t esp_rmaker_store_group_id(const char *group_id);
1192+
1193+
/** Retrieve group_id from NVS
1194+
*
1195+
* @param[out] group_id The group_id to retrieve. Should be freed by the caller.
1196+
*
1197+
* @return ESP_OK on success
1198+
* @return error in case of failure
1199+
*/
1200+
esp_err_t esp_rmaker_get_stored_group_id(char **group_id);
1201+
1202+
/**
1203+
* @brief Publish a string message to direct params topic
1204+
*
1205+
* @param[in] message The message to publish
1206+
*
1207+
* @return ESP_OK on success
1208+
*/
1209+
esp_err_t esp_rmaker_publish_direct(const char *message);
1210+
11841211
#ifdef __cplusplus
11851212
}
11861213
#endif
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#pragma once
8+
9+
#ifdef __cplusplus
10+
extern "C"
11+
{
12+
#endif
13+
14+
/** Enable Groups Service
15+
*
16+
* This API enables the groups service for the node. This allows phone apps to
17+
* set the parent group ID (pgrp_id) in which the node is added.
18+
*
19+
* Once set, all local params will be reported on
20+
* node/<node_id>/params/local/<pgrp_id> instead of node/<node_id>/params/local/
21+
*
22+
* Additionally, application code can use the esp_rmaker_publish_direct()
23+
* API to publish any message on node/<node_id>/direct/params/local/<pgrp_id>
24+
*
25+
* Phone apps can subscribe to these topics to get these messages directly
26+
* from the MQTT broker:
27+
* - node/+/params/local/<pgrp_id>
28+
* - node/+/direct/params/local/<pgrp_id>
29+
*
30+
* For local params update, this change helps to improve the latency
31+
* of param reporting.
32+
*
33+
* The direct reporting allows to bypass the cloud side processing to send
34+
* messages directly to phone apps at very low cost.
35+
*
36+
* Phone apps can also publish param updates directly to
37+
* node/<node_id>/params/remote/<pgrp_id> instead of using the set params API.
38+
*
39+
* @note This API should be called after esp_rmaker_node_init() but before esp_rmaker_start().
40+
*
41+
* @return ESP_OK on success.
42+
* @return error in case of failure.
43+
*/
44+
esp_err_t esp_rmaker_groups_service_enable(void);
45+
46+
#ifdef __cplusplus
47+
}
48+
#endif

components/esp_rainmaker/include/esp_rmaker_standard_params.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,11 +380,12 @@ esp_rmaker_param_t *esp_rmaker_base_url_param_create(const char *param_name);
380380
* This will create the standard Group ID parameter.
381381
*
382382
* @param[in] param_name Name of the parameter
383+
* @param[in] val Default Value of the parameter
383384
*
384385
* @return Parameter handle on success.
385386
* @return NULL in case of failures.
386387
*/
387-
esp_rmaker_param_t *esp_rmaker_group_id_param_create(const char *param_name);
388+
esp_rmaker_param_t *esp_rmaker_group_id_param_create(const char *param_name, const char *val);
388389

389390
#ifdef __cplusplus
390391
}

components/esp_rainmaker/include/esp_rmaker_standard_services.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,21 @@ esp_rmaker_device_t *esp_rmaker_create_local_control_service(const char *serv_na
135135
*/
136136
esp_rmaker_device_t *esp_rmaker_create_user_auth_service(const char *serv_name, esp_rmaker_device_bulk_write_cb_t bulk_write_cb, esp_rmaker_device_bulk_read_cb_t read_cb, void *priv_data);
137137

138+
/** Create a standard Groups service
139+
*
140+
* This creates a Groups service with the mandatory parameters. The default parameter names will be used.
141+
* Refer \ref esp_rmaker_standard_params.h for default names.
142+
*
143+
* @param[in] serv_name The unique service name
144+
* @param[in] write_cb Bulk write callback.
145+
* @param[in] priv_data (Optional) Private data associated with the service. This should stay
146+
* allocated throughout the lifetime of the service.
147+
*
148+
* @return service_handle on success.
149+
* @return NULL in case of any error.
150+
*/
151+
esp_rmaker_device_t *esp_rmaker_create_groups_service(const char *serv_name, esp_rmaker_device_bulk_write_cb_t write_cb, char *group_id, void *priv_data);
152+
138153
#ifdef __cplusplus
139154
}
140155
#endif

components/esp_rainmaker/include/esp_rmaker_standard_types.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,6 @@ extern "C"
6767
#define ESP_RMAKER_PARAM_BASE_URL "esp.param.base-url"
6868
#define ESP_RMAKER_PARAM_GROUP_ID "esp.param.group-id"
6969

70-
71-
7270
/********** STANDARD DEVICE TYPES **********/
7371

7472
#define ESP_RMAKER_DEVICE_SWITCH "esp.device.switch"
@@ -101,6 +99,7 @@ extern "C"
10199
#define ESP_RMAKER_SERVICE_SYSTEM "esp.service.system"
102100
#define ESP_RMAKER_SERVICE_LOCAL_CONTROL "esp.service.local_control"
103101
#define ESP_RMAKER_SERVICE_USER_AUTH "esp.service.rmaker-user-auth"
102+
#define ESP_RMAKER_SERVICE_GROUPS "esp.service.groups"
104103

105104
#ifdef __cplusplus
106105
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <string.h>
8+
#include <esp_log.h>
9+
#include <esp_err.h>
10+
#include <esp_rmaker_core.h>
11+
#include <esp_rmaker_standard_services.h>
12+
#include <esp_rmaker_standard_params.h>
13+
#include <esp_rmaker_groups.h>
14+
#include "esp_rmaker_internal.h"
15+
16+
static const char *TAG = "esp_rmaker_groups";
17+
18+
static esp_err_t groups_write_cb(const esp_rmaker_device_t *device, const esp_rmaker_param_write_req_t write_req[],
19+
uint8_t count, void *priv_data, esp_rmaker_write_ctx_t *ctx)
20+
{
21+
if (ctx) {
22+
ESP_LOGI(TAG, "Received write request via : %s", esp_rmaker_device_cb_src_to_str(ctx->src));
23+
}
24+
for (uint8_t i = 0; i < count; i++) {
25+
if (strcmp(esp_rmaker_param_get_name(write_req[i].param), ESP_RMAKER_DEF_GROUP_ID_NAME) == 0) {
26+
esp_rmaker_param_update(write_req[i].param, write_req[i].val);
27+
esp_rmaker_register_for_group_params(write_req[i].val.val.s);
28+
}
29+
}
30+
return ESP_OK;
31+
}
32+
33+
esp_err_t esp_rmaker_groups_service_enable(void)
34+
{
35+
char *group_id = NULL;
36+
esp_rmaker_device_t *service = NULL;
37+
esp_err_t err = esp_rmaker_get_stored_group_id(&group_id);
38+
if (err == ESP_OK && group_id) {
39+
service = esp_rmaker_create_groups_service("Groups", groups_write_cb, group_id, NULL);
40+
free(group_id);
41+
} else {
42+
service = esp_rmaker_create_groups_service("Groups", groups_write_cb, "", NULL);
43+
}
44+
if (!service) {
45+
return ESP_ERR_NO_MEM;
46+
}
47+
err = esp_rmaker_node_add_device(esp_rmaker_get_node(), service);
48+
if (err != ESP_OK) {
49+
ESP_LOGE(TAG, "Failed to add Groups service to node");
50+
esp_rmaker_device_delete(service);
51+
return err;
52+
}
53+
ESP_LOGD(TAG, "Groups Service Enabled");
54+
return ESP_OK;
55+
}

components/esp_rainmaker/src/core/esp_rmaker_internal.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,15 @@ static inline esp_err_t esp_rmaker_post_event(esp_rmaker_event_t event_id, void*
135135
}
136136
esp_rmaker_state_t esp_rmaker_get_state(void);
137137
esp_err_t esp_rmaker_cmd_response_enable(void);
138+
139+
/** Register for group parameter updates
140+
*
141+
* This function handles group subscriptions and manages MQTT topics for group communication.
142+
* If there's an existing group subscription, it will be unsubscribed before subscribing to the new group.
143+
*
144+
* @param[in] pgrp The group identifier string
145+
*
146+
* @return ESP_OK on success
147+
* @return error in case of failure
148+
*/
149+
esp_err_t esp_rmaker_register_for_group_params(const char *pgrp);

0 commit comments

Comments
 (0)