16
16
#include <esp_log.h>
17
17
#include <esp_event.h>
18
18
#include <nvs.h>
19
+ #include <freertos/FreeRTOS.h>
20
+ #include <freertos/semphr.h>
19
21
#include <wifi_provisioning/manager.h>
20
22
#include <json_generator.h>
21
23
#include <esp_rmaker_work_queue.h>
@@ -35,14 +37,21 @@ static const char *TAG = "esp_rmaker_user_mapping";
35
37
#define USER_RESET_ID "esp-rmaker"
36
38
#define USER_RESET_KEY "failed"
37
39
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
+
38
45
typedef struct {
39
46
char * user_id ;
40
47
char * secret_key ;
41
48
int mqtt_msg_id ;
49
+ bool sent ;
42
50
} esp_rmaker_user_mapping_data_t ;
43
51
44
52
static esp_rmaker_user_mapping_data_t * rmaker_user_mapping_data ;
45
53
esp_rmaker_user_mapping_state_t rmaker_user_mapping_state ;
54
+ SemaphoreHandle_t esp_rmaker_user_mapping_lock = NULL ;
46
55
47
56
static void esp_rmaker_user_mapping_cleanup_data (void )
48
57
{
@@ -82,10 +91,13 @@ static void esp_rmaker_user_mapping_event_handler(void* arg, esp_event_base_t ev
82
91
* has indeed reached the RainMaker cloud.
83
92
*/
84
93
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 )) {
86
99
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 ) {
89
101
rmaker_user_mapping_state = ESP_RMAKER_USER_MAPPING_RESET ;
90
102
esp_rmaker_post_event (RMAKER_EVENT_USER_NODE_MAPPING_RESET , NULL , 0 );
91
103
} else {
@@ -106,36 +118,47 @@ static void esp_rmaker_user_mapping_event_handler(void* arg, esp_event_base_t ev
106
118
esp_event_handler_unregister (RMAKER_COMMON_EVENT , RMAKER_MQTT_EVENT_PUBLISHED ,
107
119
& esp_rmaker_user_mapping_event_handler );
108
120
}
121
+ xSemaphoreGive (esp_rmaker_user_mapping_lock );
109
122
}
110
123
}
111
124
112
125
static void esp_rmaker_user_mapping_cb (void * priv_data )
113
126
{
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 );
116
134
return ;
117
135
}
118
136
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 );
120
138
char publish_payload [200 ];
121
139
json_gen_str_t jstr ;
122
140
json_gen_str_start (& jstr , publish_payload , sizeof (publish_payload ), NULL , NULL );
123
141
json_gen_start_object (& jstr );
124
142
char * node_id = esp_rmaker_get_node_id ();
125
143
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 );
128
146
if (esp_rmaker_user_node_mapping_get_state () != ESP_RMAKER_USER_MAPPING_DONE ) {
129
147
json_gen_obj_set_bool (& jstr , "reset" , true);
130
148
}
131
149
json_gen_end_object (& jstr );
132
150
json_gen_str_end (& jstr );
133
151
char publish_topic [100 ];
134
152
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 );
136
155
if (err != ESP_OK ) {
137
156
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;
138
160
}
161
+ xSemaphoreGive (esp_rmaker_user_mapping_lock );
139
162
return ;
140
163
}
141
164
@@ -175,20 +198,32 @@ static bool esp_rmaker_user_mapping_detect_reset(const char *user_id)
175
198
176
199
esp_err_t esp_rmaker_start_user_node_mapping (char * user_id , char * secret_key )
177
200
{
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
+ }
178
209
if (rmaker_user_mapping_data ) {
179
210
esp_rmaker_user_mapping_cleanup_data ();
180
211
}
181
212
182
213
rmaker_user_mapping_data = calloc (1 , sizeof (esp_rmaker_user_mapping_data_t ));
183
214
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 ;
185
218
}
186
219
rmaker_user_mapping_data -> user_id = strdup (user_id );
187
220
if (!rmaker_user_mapping_data -> user_id ) {
221
+ ESP_LOGE (TAG , "Failed to allocate memory for user_id." );
188
222
goto user_mapping_error ;
189
223
}
190
224
rmaker_user_mapping_data -> secret_key = strdup (secret_key );
191
225
if (!rmaker_user_mapping_data -> secret_key ) {
226
+ ESP_LOGE (TAG , "Failed to allocate memory for secret_key." );
192
227
goto user_mapping_error ;
193
228
}
194
229
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)
197
232
} else {
198
233
rmaker_user_mapping_state = ESP_RMAKER_USER_MAPPING_DONE ;
199
234
}
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." );
201
237
goto user_mapping_error ;
202
238
}
203
239
esp_rmaker_user_mapping_prov_deinit ();
240
+ xSemaphoreGive (esp_rmaker_user_mapping_lock );
204
241
return ESP_OK ;
205
242
206
243
user_mapping_error :
207
244
esp_rmaker_user_mapping_cleanup_data ();
245
+ xSemaphoreGive (esp_rmaker_user_mapping_lock );
208
246
return ESP_FAIL ;
209
247
}
210
248
@@ -311,5 +349,21 @@ esp_err_t esp_rmaker_user_node_mapping_init(void)
311
349
#else
312
350
rmaker_user_mapping_state = ESP_RMAKER_USER_MAPPING_DONE ;
313
351
#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
+ }
314
368
return ESP_OK ;
315
369
}
0 commit comments