@@ -31,8 +31,32 @@ typedef struct mqtt_client_t {
31
31
mrb_bool ssl ;
32
32
esp_mqtt_client_handle_t client ;
33
33
QueueHandle_t queue ;
34
+ TaskHandle_t main_task_handle ;
35
+ mrb_value message_proc ;
34
36
} mqtt_client_t ;
35
37
38
+ 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 );
43
+
44
+ // Check message_proc is a a proc?
45
+ mrb_assert (mrb_type (client -> message_proc ) == MRB_TT_PROC );
46
+
47
+ // Prep arguments to pass.
48
+ mrb_value args [2 ];
49
+ args [0 ] = mrb_str_new_static (client -> mrb , event -> topic , event -> topic_len );
50
+ args [1 ] = mrb_str_new_static (client -> mrb , event -> data , event -> data_len );
51
+
52
+ // Call message_proc.
53
+ mrb_yield_argv (client -> mrb , client -> message_proc , 2 , & args [0 ]);
54
+
55
+ // Resume main task.
56
+ mrb_gc_arena_restore (client -> mrb , arena_index );
57
+ vTaskResume (client -> main_task_handle );
58
+ }
59
+
36
60
static void mqtt_event_handler (void * arg , esp_event_base_t base , int32_t event_id , void * event_data )
37
61
{
38
62
ESP_LOGD (TAG , "Event dispatched from event loop base=%s, event_id=%d" , base , event_id );
@@ -61,7 +85,7 @@ static void mqtt_event_handler(void *arg, esp_event_base_t base, int32_t event_i
61
85
break ;
62
86
case MQTT_EVENT_DATA :
63
87
ESP_LOGI (TAG , "MQTT_EVENT_DATA" );
64
- xQueueSend (client -> queue , event_data , ( TickType_t ) 0 );
88
+ mqtt_message_handler (client , event );
65
89
break ;
66
90
case MQTT_EVENT_ERROR :
67
91
ESP_LOGI (TAG , "MQTT_EVENT_ERROR" );
@@ -88,17 +112,6 @@ mqtt_wait_for_event(mrb_state *mrb, mrb_value self, int32_t event_id) {
88
112
mrb_raise (mrb , error_class , "Timeout wait for mqtt event." );
89
113
}
90
114
91
- static void
92
- mqtt_wait_for_data (mrb_state * mrb , mrb_value self , esp_mqtt_event_t * event ) {
93
- mqtt_client_t * client = (mqtt_client_t * ) DATA_PTR (self );
94
-
95
- while (true) {
96
- if (xQueueReceive (client -> queue , (void * )event , (TickType_t )(1000 / portTICK_PERIOD_MS ))) {
97
- if (event -> event_id == MQTT_EVENT_DATA ) break ;
98
- }
99
- }
100
- }
101
-
102
115
static void
103
116
mrb_mqtt_client_free (mrb_state * mrb , void * p ) {
104
117
mqtt_client_t * client = (mqtt_client_t * )p ;
@@ -110,13 +123,14 @@ mrb_mqtt_client_free(mrb_state *mrb, void *p) {
110
123
}
111
124
112
125
static mrb_value
113
- mrb_mqtt_client_init (mrb_state * mrb , mrb_value self ) {
126
+ mrb_mqtt_client_initialize (mrb_state * mrb , mrb_value self ) {
114
127
mqtt_client_t * client = mrb_malloc (mrb , sizeof (mqtt_client_t ));
115
128
116
129
mrb_value host ;
117
130
mrb_int port ;
131
+ mrb_value block ;
118
132
119
- mrb_get_args (mrb , "Si" , & host , & port );
133
+ mrb_get_args (mrb , "Si& " , & host , & port , & block );
120
134
121
135
client -> mrb = mrb ;
122
136
client -> host = mrb_malloc (mrb , strlen (mrb_str_to_cstr (mrb , host )));
@@ -125,6 +139,11 @@ mrb_mqtt_client_init(mrb_state *mrb, mrb_value self) {
125
139
client -> ssl = FALSE;
126
140
client -> queue = xQueueCreate (WAIT_EVENT_QUEUE_LEN , sizeof (esp_mqtt_event_t ));
127
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
+
128
147
mrb_data_init (self , client , & mrb_mqtt_client );
129
148
ESP_LOGI (TAG , "initialize(%s, %d)" , client -> host , client -> port );
130
149
@@ -270,24 +289,6 @@ mrb_mqtt_client_unsubscribe(mrb_state *mrb, mrb_value self) {
270
289
return self ;
271
290
}
272
291
273
- static mrb_value
274
- mrb_mqtt_client_get (mrb_state * mrb , mrb_value self ) {
275
- esp_mqtt_event_t event ;
276
-
277
- mqtt_wait_for_data (mrb , self , & event );
278
-
279
- mrb_value topic = mrb_str_new_static (mrb , event .topic , event .topic_len );
280
- mrb_value message = mrb_str_new_static (mrb , event .data , event .data_len );
281
-
282
- mrb_value ary = mrb_ary_new (mrb );
283
- mrb_ary_push (mrb , ary , topic );
284
- mrb_ary_push (mrb , ary , message );
285
-
286
- ESP_LOGI (TAG , "get()" );
287
-
288
- return ary ;
289
- }
290
-
291
292
static mrb_value
292
293
mrb_mqtt_client_disconnect (mrb_state * mrb , mrb_value self ) {
293
294
mqtt_client_t * client = (mqtt_client_t * ) DATA_PTR (self );
@@ -312,13 +313,12 @@ mrb_mruby_esp32_mqtt_gem_init(mrb_state* mrb) {
312
313
struct RClass * mqtt_module = mrb_define_module_under (mrb , esp32_module , "MQTT" );
313
314
struct RClass * client_class = mrb_define_class_under (mrb , mqtt_module , "Client" , mrb -> object_class );
314
315
315
- mrb_define_method (mrb , client_class , "initialize " , mrb_mqtt_client_init , MRB_ARGS_REQ (2 ));
316
+ mrb_define_method (mrb , client_class , "_initialize " , mrb_mqtt_client_initialize , MRB_ARGS_REQ (2 )| MRB_ARGS_BLOCK ( ));
316
317
mrb_define_method (mrb , client_class , "ssl=" , mrb_mqtt_client_set_ssl , MRB_ARGS_REQ (1 ));
317
318
mrb_define_method (mrb , client_class , "connect" , mrb_mqtt_client_connect , MRB_ARGS_NONE ());
318
319
mrb_define_method (mrb , client_class , "publish" , mrb_mqtt_client_publish , MRB_ARGS_REQ (2 ));
319
- mrb_define_method (mrb , client_class , "subscribe " , mrb_mqtt_client_subscribe , MRB_ARGS_REQ (1 ));
320
+ mrb_define_method (mrb , client_class , "_subscribe " , mrb_mqtt_client_subscribe , MRB_ARGS_REQ (1 ));
320
321
mrb_define_method (mrb , client_class , "unsubscribe" , mrb_mqtt_client_unsubscribe , MRB_ARGS_REQ (1 ));
321
- mrb_define_method (mrb , client_class , "get" , mrb_mqtt_client_get , MRB_ARGS_NONE ());
322
322
mrb_define_method (mrb , client_class , "disconnect" , mrb_mqtt_client_disconnect , MRB_ARGS_NONE ());
323
323
324
324
mrb_define_class_under (mrb , mqtt_module , "TimeoutError" , mrb -> eStandardError_class );
0 commit comments