13
13
#include "esp_log.h"
14
14
#include "mqtt_client.h"
15
15
16
-
17
16
#define TAG ("mruby-esp32-mqtt")
18
- #define WAIT_EVENT_TIMEOUT_SEC (20)
19
- #define WAIT_EVENT_QUEUE_LEN (10)
20
17
21
18
static void mrb_mqtt_client_free (mrb_state * mrb , void * p );
22
19
@@ -30,31 +27,62 @@ typedef struct mqtt_client_t {
30
27
mrb_int port ;
31
28
mrb_bool ssl ;
32
29
esp_mqtt_client_handle_t client ;
33
- QueueHandle_t queue ;
34
- TaskHandle_t main_task_handle ;
35
- mrb_value message_proc ;
30
+
31
+ TaskHandle_t mruby_task_handle ;
32
+ mrb_value connected_proc ;
33
+ mrb_value disconnected_proc ;
34
+ mrb_value unsubscribed_proc ;
35
+ mrb_value data_proc ;
36
36
} mqtt_client_t ;
37
37
38
+
39
+ static void
40
+ mqtt_connected_handler (mqtt_client_t * client , esp_mqtt_event_handle_t event ) {
41
+ // Get semaphore.
42
+
43
+ // Call @connected_proc.
44
+ mrb_assert (mrb_type (client -> connected_proc ) == MRB_TT_PROC );
45
+ mrb_yield_argv (client -> mrb , client -> connected_proc , 0 , NULL );
46
+
47
+ // Release semaphore.
48
+ }
49
+
50
+ static void
51
+ mqtt_disconnected_handler (mqtt_client_t * client , esp_mqtt_event_handle_t event ) {
52
+ // Get semaphore.
53
+
54
+ // Call @disconnected_proc.
55
+ mrb_assert (mrb_type (client -> disconnected_proc ) == MRB_TT_PROC );
56
+ mrb_yield_argv (client -> mrb , client -> disconnected_proc , 0 , NULL );
57
+
58
+ // Release semaphore.
59
+ }
60
+
38
61
static void
39
- mqtt_message_handler (mqtt_client_t * client , esp_mqtt_event_handle_t event ) {
40
- // Suspend main task.
41
- vTaskSuspend (client -> main_task_handle );
42
- int arena_index = mrb_gc_arena_save (client -> mrb );
62
+ mqtt_unsubscribed_handler (mqtt_client_t * client , esp_mqtt_event_handle_t event ) {
63
+ // Get semaphore.
43
64
44
- // Check message_proc is a a proc?
45
- mrb_assert (mrb_type (client -> message_proc ) == MRB_TT_PROC );
65
+ // Call @unsubscribed_proc.
66
+ mrb_assert (mrb_type (client -> unsubscribed_proc ) == MRB_TT_PROC );
67
+ mrb_yield_argv (client -> mrb , client -> unsubscribed_proc , 0 , NULL );
68
+
69
+ // Release semaphore.
70
+ }
71
+
72
+ static void
73
+ mqtt_data_handler (mqtt_client_t * client , esp_mqtt_event_handle_t event ) {
74
+ // Get semaphore.
46
75
47
76
// Prep arguments to pass.
48
77
mrb_value args [2 ];
49
78
args [0 ] = mrb_str_new_static (client -> mrb , event -> topic , event -> topic_len );
50
79
args [1 ] = mrb_str_new_static (client -> mrb , event -> data , event -> data_len );
51
80
52
- // Call message_proc.
53
- mrb_yield_argv (client -> mrb , client -> message_proc , 2 , & args [0 ]);
81
+ // Call @data_proc
82
+ mrb_assert (mrb_type (client -> data_proc ) == MRB_TT_PROC );
83
+ mrb_yield_argv (client -> mrb , client -> data_proc , 2 , & args [0 ]);
54
84
55
- // Resume main task.
56
- mrb_gc_arena_restore (client -> mrb , arena_index );
57
- vTaskResume (client -> main_task_handle );
85
+ // Release semaphore.
58
86
}
59
87
60
88
static void mqtt_event_handler (void * arg , esp_event_base_t base , int32_t event_id , void * event_data )
@@ -64,54 +92,40 @@ static void mqtt_event_handler(void *arg, esp_event_base_t base, int32_t event_i
64
92
esp_mqtt_event_handle_t event = event_data ;
65
93
66
94
switch ((esp_mqtt_event_id_t )event_id ) {
95
+ case MQTT_EVENT_ERROR :
96
+ ESP_LOGI (TAG , "MQTT_EVENT_ERROR" );
97
+ break ;
67
98
case MQTT_EVENT_CONNECTED :
68
- ESP_LOGD (TAG , "MQTT_EVENT_CONNECTED" );
69
- xQueueSend (client -> queue , event_data , ( TickType_t ) 0 );
99
+ ESP_LOGI (TAG , "MQTT_EVENT_CONNECTED" );
100
+ mqtt_connected_handler (client , event );
70
101
break ;
71
102
case MQTT_EVENT_DISCONNECTED :
72
103
ESP_LOGI (TAG , "MQTT_EVENT_DISCONNECTED" );
73
- xQueueSend (client -> queue , event_data , ( TickType_t ) 0 );
104
+ mqtt_disconnected_handler (client , event );
74
105
break ;
75
106
case MQTT_EVENT_SUBSCRIBED :
76
107
ESP_LOGI (TAG , "MQTT_EVENT_SUBSCRIBED, msg_id=%d" , event -> msg_id );
77
- xQueueSend (client -> queue , event_data , (TickType_t )0 );
78
108
break ;
79
109
case MQTT_EVENT_UNSUBSCRIBED :
80
110
ESP_LOGI (TAG , "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d" , event -> msg_id );
81
- xQueueSend (client -> queue , event_data , ( TickType_t ) 0 );
111
+ mqtt_unsubscribed_handler (client , event );
82
112
break ;
83
113
case MQTT_EVENT_PUBLISHED :
84
114
ESP_LOGI (TAG , "MQTT_EVENT_PUBLISHED, msg_id=%d" , event -> msg_id );
85
115
break ;
86
116
case MQTT_EVENT_DATA :
87
117
ESP_LOGI (TAG , "MQTT_EVENT_DATA" );
88
- mqtt_message_handler (client , event );
118
+ mqtt_data_handler (client , event );
89
119
break ;
90
- case MQTT_EVENT_ERROR :
91
- ESP_LOGI (TAG , "MQTT_EVENT_ERROR " );
120
+ case MQTT_EVENT_BEFORE_CONNECT :
121
+ ESP_LOGI (TAG , "MQTT_EVENT_BEFORE_CONNECT " );
92
122
break ;
93
123
default :
94
124
ESP_LOGI (TAG , "Other event id:%d" , event -> event_id );
95
125
break ;
96
126
}
97
127
}
98
128
99
- static void
100
- mqtt_wait_for_event (mrb_state * mrb , mrb_value self , int32_t event_id ) {
101
- mqtt_client_t * client = (mqtt_client_t * ) DATA_PTR (self );
102
- esp_mqtt_event_t event ;
103
- int wait_count ;
104
- struct RClass * error_class ;
105
-
106
- for (wait_count = 0 ; wait_count < WAIT_EVENT_TIMEOUT_SEC ; wait_count ++ ) {
107
- if (xQueueReceive (client -> queue , (void * )& event , (TickType_t )(1000 / portTICK_PERIOD_MS ))) {
108
- if (event .event_id == event_id ) return ;
109
- }
110
- }
111
- error_class = mrb_exc_get_id (mrb , MRB_ERROR_SYM (ESP32 ::MQTT ::TimeoutError ));
112
- mrb_raise (mrb , error_class , "Timeout wait for mqtt event." );
113
- }
114
-
115
129
static void
116
130
mrb_mqtt_client_free (mrb_state * mrb , void * p ) {
117
131
mqtt_client_t * client = (mqtt_client_t * )p ;
@@ -128,21 +142,14 @@ mrb_mqtt_client_initialize(mrb_state *mrb, mrb_value self) {
128
142
129
143
mrb_value host ;
130
144
mrb_int port ;
131
- mrb_value block ;
132
-
133
- mrb_get_args (mrb , "Si&" , & host , & port , & block );
145
+ mrb_get_args (mrb , "Si" , & host , & port );
134
146
147
+ client -> mruby_task_handle = xTaskGetCurrentTaskHandle ();
135
148
client -> mrb = mrb ;
136
149
client -> host = mrb_malloc (mrb , strlen (mrb_str_to_cstr (mrb , host )));
137
150
strcpy (client -> host , mrb_str_to_cstr (mrb , host ));
138
151
client -> port = port ;
139
152
client -> ssl = FALSE;
140
- client -> queue = xQueueCreate (WAIT_EVENT_QUEUE_LEN , sizeof (esp_mqtt_event_t ));
141
-
142
- // Save block given and main task for handling incoming messages.
143
- mrb_iv_set (mrb , self , mrb_intern_lit (mrb , "@message_proc" ), block );
144
- client -> message_proc = block ;
145
- client -> main_task_handle = xTaskGetCurrentTaskHandle ();
146
153
147
154
mrb_data_init (self , client , & mrb_mqtt_client );
148
155
ESP_LOGI (TAG , "initialize(%s, %d)" , client -> host , client -> port );
@@ -199,7 +206,6 @@ mrb_mqtt_client_connect(mrb_state *mrb, mrb_value self) {
199
206
200
207
client -> client = mqtt_client ;
201
208
202
- mqtt_wait_for_event (mrb , self , MQTT_EVENT_CONNECTED );
203
209
ESP_LOGI (
204
210
TAG ,
205
211
"connect(%s://%s:%d)" ,
@@ -245,7 +251,6 @@ mrb_mqtt_client_subscribe(mrb_state *mrb, mrb_value self) {
245
251
struct RClass * error_class ;
246
252
247
253
mrb_value topic ;
248
-
249
254
mrb_get_args (mrb , "S" , & topic );
250
255
251
256
ret = esp_mqtt_client_subscribe (
@@ -258,7 +263,6 @@ mrb_mqtt_client_subscribe(mrb_state *mrb, mrb_value self) {
258
263
mrb_raise (mrb , error_class , "Failed to subscribe." );
259
264
return self ;
260
265
}
261
- mqtt_wait_for_event (mrb , self , MQTT_EVENT_SUBSCRIBED );
262
266
ESP_LOGI (TAG , "subscribe(%s)" , mrb_str_to_cstr (mrb , topic ));
263
267
264
268
return self ;
@@ -283,7 +287,6 @@ mrb_mqtt_client_unsubscribe(mrb_state *mrb, mrb_value self) {
283
287
mrb_raise (mrb , error_class , "Failed to unsubscribe." );
284
288
return self ;
285
289
}
286
- mqtt_wait_for_event (mrb , self , MQTT_EVENT_UNSUBSCRIBED );
287
290
ESP_LOGI (TAG , "unsubscribe(%s)" , mrb_str_to_cstr (mrb , topic ));
288
291
289
292
return self ;
@@ -301,12 +304,63 @@ mrb_mqtt_client_disconnect(mrb_state *mrb, mrb_value self) {
301
304
mrb_raise (mrb , error_class , "Failed to disconnect." );
302
305
return self ;
303
306
}
304
- mqtt_wait_for_event (mrb , self , MQTT_EVENT_DISCONNECTED );
305
307
ESP_LOGI (TAG , "disconnect" );
306
308
307
309
return self ;
308
310
}
309
311
312
+ static mrb_value
313
+ mrb_mqtt_client_set_connected_handler (mrb_state * mrb , mrb_value self ) {
314
+ mqtt_client_t * client = (mqtt_client_t * ) DATA_PTR (self );
315
+
316
+ mrb_value block ;
317
+ mrb_get_args (mrb , "&" , & block );
318
+
319
+ mrb_iv_set (mrb , self , mrb_intern_lit (mrb , "@connected_proc" ), block );
320
+ client -> connected_proc = block ;
321
+
322
+ return self ;
323
+ }
324
+
325
+ static mrb_value
326
+ mrb_mqtt_client_set_disconnected_handler (mrb_state * mrb , mrb_value self ) {
327
+ mqtt_client_t * client = (mqtt_client_t * ) DATA_PTR (self );
328
+
329
+ mrb_value block ;
330
+ mrb_get_args (mrb , "&" , & block );
331
+
332
+ mrb_iv_set (mrb , self , mrb_intern_lit (mrb , "@disconnected_proc" ), block );
333
+ client -> disconnected_proc = block ;
334
+
335
+ return self ;
336
+ }
337
+
338
+ static mrb_value
339
+ mrb_mqtt_client_set_unsubscribed_handler (mrb_state * mrb , mrb_value self ) {
340
+ mqtt_client_t * client = (mqtt_client_t * ) DATA_PTR (self );
341
+
342
+ mrb_value block ;
343
+ mrb_get_args (mrb , "&" , & block );
344
+
345
+ mrb_iv_set (mrb , self , mrb_intern_lit (mrb , "@unsubscribed_proc" ), block );
346
+ client -> unsubscribed_proc = block ;
347
+
348
+ return self ;
349
+ }
350
+
351
+ static mrb_value
352
+ mrb_mqtt_client_set_data_handler (mrb_state * mrb , mrb_value self ) {
353
+ mqtt_client_t * client = (mqtt_client_t * ) DATA_PTR (self );
354
+
355
+ mrb_value block ;
356
+ mrb_get_args (mrb , "&" , & block );
357
+
358
+ mrb_iv_set (mrb , self , mrb_intern_lit (mrb , "@data_proc" ), block );
359
+ client -> data_proc = block ;
360
+
361
+ return self ;
362
+ }
363
+
310
364
void
311
365
mrb_mruby_esp32_mqtt_gem_init (mrb_state * mrb ) {
312
366
struct RClass * esp32_module = mrb_define_module (mrb , "ESP32" );
@@ -320,8 +374,12 @@ mrb_mruby_esp32_mqtt_gem_init(mrb_state* mrb) {
320
374
mrb_define_method (mrb , client_class , "_subscribe" , mrb_mqtt_client_subscribe , MRB_ARGS_REQ (1 ));
321
375
mrb_define_method (mrb , client_class , "unsubscribe" , mrb_mqtt_client_unsubscribe , MRB_ARGS_REQ (1 ));
322
376
mrb_define_method (mrb , client_class , "disconnect" , mrb_mqtt_client_disconnect , MRB_ARGS_NONE ());
377
+
378
+ mrb_define_method (mrb , client_class , "set_connected_handler" , mrb_mqtt_client_set_connected_handler , MRB_ARGS_BLOCK ());
379
+ mrb_define_method (mrb , client_class , "set_disconnected_handler" , mrb_mqtt_client_set_disconnected_handler , MRB_ARGS_BLOCK ());
380
+ mrb_define_method (mrb , client_class , "set_unsubscribed_handler" , mrb_mqtt_client_set_unsubscribed_handler , MRB_ARGS_BLOCK ());
381
+ mrb_define_method (mrb , client_class , "set_data_handler" , mrb_mqtt_client_set_data_handler , MRB_ARGS_BLOCK ());
323
382
324
- mrb_define_class_under (mrb , mqtt_module , "TimeoutError" , mrb -> eStandardError_class );
325
383
mrb_define_class_under (mrb , mqtt_module , "ConnectError" , mrb -> eStandardError_class );
326
384
mrb_define_class_under (mrb , mqtt_module , "PublishError" , mrb -> eStandardError_class );
327
385
mrb_define_class_under (mrb , mqtt_module , "SubscribeError" , mrb -> eStandardError_class );
0 commit comments