1616#include <esp_log.h>
1717#include <esp_event.h>
1818#include <nvs.h>
19+ #include <freertos/FreeRTOS.h>
20+ #include <freertos/semphr.h>
1921#include <wifi_provisioning/manager.h>
2022#include <json_generator.h>
2123#include <esp_rmaker_work_queue.h>
@@ -35,14 +37,21 @@ static const char *TAG = "esp_rmaker_user_mapping";
3537#define USER_RESET_ID "esp-rmaker"
3638#define USER_RESET_KEY "failed"
3739
40+ /* A delay large enough to allow the tasks to get the semaphore, but small
41+ * enough to prevent tasks getting blocked for long.
42+ */
43+ #define SEMAPHORE_DELAY_MSEC 5000
44+
3845typedef struct {
3946 char * user_id ;
4047 char * secret_key ;
4148 int mqtt_msg_id ;
49+ bool sent ;
4250} esp_rmaker_user_mapping_data_t ;
4351
4452static esp_rmaker_user_mapping_data_t * rmaker_user_mapping_data ;
4553esp_rmaker_user_mapping_state_t rmaker_user_mapping_state ;
54+ SemaphoreHandle_t esp_rmaker_user_mapping_lock = NULL ;
4655
4756static void esp_rmaker_user_mapping_cleanup_data (void )
4857{
@@ -82,10 +91,13 @@ static void esp_rmaker_user_mapping_event_handler(void* arg, esp_event_base_t ev
8291 * has indeed reached the RainMaker cloud.
8392 */
8493 int msg_id = * ((int * )event_data );
85- if (msg_id == rmaker_user_mapping_data -> mqtt_msg_id ) {
94+ if (xSemaphoreTake (esp_rmaker_user_mapping_lock , SEMAPHORE_DELAY_MSEC /portTICK_PERIOD_MS ) != pdTRUE ) {
95+ ESP_LOGE (TAG , "Failed to take semaphore." );
96+ return ;
97+ }
98+ if ((rmaker_user_mapping_data != NULL ) && (msg_id == rmaker_user_mapping_data -> mqtt_msg_id )) {
8699 ESP_LOGI (TAG , "User Node association message published successfully." );
87- esp_rmaker_user_mapping_data_t * data = (esp_rmaker_user_mapping_data_t * )arg ;
88- if (data && (strcmp (data -> user_id , USER_RESET_ID ) == 0 )) {
100+ if (strcmp (rmaker_user_mapping_data -> user_id , USER_RESET_ID ) == 0 ) {
89101 rmaker_user_mapping_state = ESP_RMAKER_USER_MAPPING_RESET ;
90102 esp_rmaker_post_event (RMAKER_EVENT_USER_NODE_MAPPING_RESET , NULL , 0 );
91103 } else {
@@ -106,36 +118,47 @@ static void esp_rmaker_user_mapping_event_handler(void* arg, esp_event_base_t ev
106118 esp_event_handler_unregister (RMAKER_COMMON_EVENT , RMAKER_MQTT_EVENT_PUBLISHED ,
107119 & esp_rmaker_user_mapping_event_handler );
108120 }
121+ xSemaphoreGive (esp_rmaker_user_mapping_lock );
109122 }
110123}
111124
112125static void esp_rmaker_user_mapping_cb (void * priv_data )
113126{
114- esp_rmaker_user_mapping_data_t * data = (esp_rmaker_user_mapping_data_t * )priv_data ;
115- if (!data ) {
127+ if (xSemaphoreTake (esp_rmaker_user_mapping_lock , SEMAPHORE_DELAY_MSEC /portTICK_PERIOD_MS ) != pdTRUE ) {
128+ ESP_LOGE (TAG , "Failed to take semaphore." );
129+ return ;
130+ }
131+ /* If there is no user node mapping data, or if the data is already sent, just return */
132+ if (rmaker_user_mapping_data == NULL || rmaker_user_mapping_data -> sent == true) {
133+ xSemaphoreGive (esp_rmaker_user_mapping_lock );
116134 return ;
117135 }
118136 esp_event_handler_register (RMAKER_COMMON_EVENT , RMAKER_MQTT_EVENT_PUBLISHED ,
119- & esp_rmaker_user_mapping_event_handler , data );
137+ & esp_rmaker_user_mapping_event_handler , NULL );
120138 char publish_payload [200 ];
121139 json_gen_str_t jstr ;
122140 json_gen_str_start (& jstr , publish_payload , sizeof (publish_payload ), NULL , NULL );
123141 json_gen_start_object (& jstr );
124142 char * node_id = esp_rmaker_get_node_id ();
125143 json_gen_obj_set_string (& jstr , "node_id" , node_id );
126- json_gen_obj_set_string (& jstr , "user_id" , data -> user_id );
127- json_gen_obj_set_string (& jstr , "secret_key" , data -> secret_key );
144+ json_gen_obj_set_string (& jstr , "user_id" , rmaker_user_mapping_data -> user_id );
145+ json_gen_obj_set_string (& jstr , "secret_key" , rmaker_user_mapping_data -> secret_key );
128146 if (esp_rmaker_user_node_mapping_get_state () != ESP_RMAKER_USER_MAPPING_DONE ) {
129147 json_gen_obj_set_bool (& jstr , "reset" , true);
130148 }
131149 json_gen_end_object (& jstr );
132150 json_gen_str_end (& jstr );
133151 char publish_topic [100 ];
134152 snprintf (publish_topic , sizeof (publish_topic ), "node/%s/%s" , node_id , USER_MAPPING_TOPIC_SUFFIX );
135- esp_err_t err = esp_rmaker_mqtt_publish (publish_topic , publish_payload , strlen (publish_payload ), RMAKER_MQTT_QOS1 , & data -> mqtt_msg_id );
153+ esp_err_t err = esp_rmaker_mqtt_publish (publish_topic , publish_payload , strlen (publish_payload ), RMAKER_MQTT_QOS1 , & rmaker_user_mapping_data -> mqtt_msg_id );
154+ ESP_LOGI (TAG , "MQTT Publish: %s" , publish_payload );
136155 if (err != ESP_OK ) {
137156 ESP_LOGE (TAG , "MQTT Publish Error %d" , err );
157+ } else {
158+ rmaker_user_mapping_state = ESP_RMAKER_USER_MAPPING_REQ_SENT ;
159+ rmaker_user_mapping_data -> sent = true;
138160 }
161+ xSemaphoreGive (esp_rmaker_user_mapping_lock );
139162 return ;
140163}
141164
@@ -175,20 +198,32 @@ static bool esp_rmaker_user_mapping_detect_reset(const char *user_id)
175198
176199esp_err_t esp_rmaker_start_user_node_mapping (char * user_id , char * secret_key )
177200{
201+ if (esp_rmaker_user_mapping_lock == NULL ) {
202+ ESP_LOGE (TAG , "User Node mapping not initialised." );
203+ return ESP_FAIL ;
204+ }
205+ if (xSemaphoreTake (esp_rmaker_user_mapping_lock , SEMAPHORE_DELAY_MSEC /portTICK_PERIOD_MS ) != pdTRUE ) {
206+ ESP_LOGE (TAG , "Failed to take semaphore." );
207+ return ESP_FAIL ;
208+ }
178209 if (rmaker_user_mapping_data ) {
179210 esp_rmaker_user_mapping_cleanup_data ();
180211 }
181212
182213 rmaker_user_mapping_data = calloc (1 , sizeof (esp_rmaker_user_mapping_data_t ));
183214 if (!rmaker_user_mapping_data ) {
184- return ESP_FAIL ;
215+ ESP_LOGE (TAG , "Failed to allocate memory for rmaker_user_mapping_data." );
216+ xSemaphoreGive (esp_rmaker_user_mapping_lock );
217+ return ESP_ERR_NO_MEM ;
185218 }
186219 rmaker_user_mapping_data -> user_id = strdup (user_id );
187220 if (!rmaker_user_mapping_data -> user_id ) {
221+ ESP_LOGE (TAG , "Failed to allocate memory for user_id." );
188222 goto user_mapping_error ;
189223 }
190224 rmaker_user_mapping_data -> secret_key = strdup (secret_key );
191225 if (!rmaker_user_mapping_data -> secret_key ) {
226+ ESP_LOGE (TAG , "Failed to allocate memory for secret_key." );
192227 goto user_mapping_error ;
193228 }
194229 if (esp_rmaker_user_mapping_detect_reset (user_id )) {
@@ -197,14 +232,17 @@ esp_err_t esp_rmaker_start_user_node_mapping(char *user_id, char *secret_key)
197232 } else {
198233 rmaker_user_mapping_state = ESP_RMAKER_USER_MAPPING_DONE ;
199234 }
200- if (esp_rmaker_work_queue_add_task (esp_rmaker_user_mapping_cb , rmaker_user_mapping_data ) != ESP_OK ) {
235+ if (esp_rmaker_work_queue_add_task (esp_rmaker_user_mapping_cb , NULL ) != ESP_OK ) {
236+ ESP_LOGE (TAG , "Failed to queue user mapping task." );
201237 goto user_mapping_error ;
202238 }
203239 esp_rmaker_user_mapping_prov_deinit ();
240+ xSemaphoreGive (esp_rmaker_user_mapping_lock );
204241 return ESP_OK ;
205242
206243user_mapping_error :
207244 esp_rmaker_user_mapping_cleanup_data ();
245+ xSemaphoreGive (esp_rmaker_user_mapping_lock );
208246 return ESP_FAIL ;
209247}
210248
@@ -311,5 +349,21 @@ esp_err_t esp_rmaker_user_node_mapping_init(void)
311349#else
312350 rmaker_user_mapping_state = ESP_RMAKER_USER_MAPPING_DONE ;
313351#endif
352+ if (!esp_rmaker_user_mapping_lock ) {
353+ esp_rmaker_user_mapping_lock = xSemaphoreCreateMutex ();
354+ if (!esp_rmaker_user_mapping_lock ) {
355+ ESP_LOGE (TAG , "Failed to create Mutex" );
356+ return ESP_FAIL ;
357+ }
358+ }
359+ return ESP_OK ;
360+ }
361+
362+ esp_err_t esp_rmaker_user_node_mapping_deinit (void )
363+ {
364+ if (esp_rmaker_user_mapping_lock ) {
365+ vSemaphoreDelete (esp_rmaker_user_mapping_lock );
366+ esp_rmaker_user_mapping_lock = NULL ;
367+ }
314368 return ESP_OK ;
315369}
0 commit comments