cesanta / mongoose-wizard

2 stars 1 forks source link

Implement JSON-RPC support #16

Closed cpq closed 4 months ago

cpq commented 4 months ago

Handling RPC-JSON. Initialising the mg_rpc_req struct (when I receive an MQTT RPC message) requires the mg_mgr, which is inaccessible in the glue_mqtt_message_received() function.

@dvosully could you elaborate on your use case please? What RPC services do you implement?

dvosully commented 4 months ago

I implement the following RPC services:

I wrongly had it in my mind (possibly from copying and cloning the example without considering alternatives) that the mg_mgr was a required argument of mg_rpc_req. I DO use the mg_mgr via the req_data in the Firmware upload RPC function to add a timer to schedule a reboot once the update is complete, but the requirement is not as strict as I had recalled.

I have made the following changes to mongoose_impl.c in mqtt_event_handler() to implement RPC (but if I instead refactor the reboot somehow, I could put this into mongoose_glue.c without changing mongoose_impl.c)

  } else if (ev == MG_EV_MQTT_MSG) {
    // Handle the Rx message as RPC-JSON
    struct mg_mqtt_message *mm = (struct mg_mqtt_message *) ev_data;
    struct mg_iobuf io = {0, 0, 0, 512};
    struct mg_rpc_req r = {glue_get_rpc(), NULL, mg_pfn_iobuf,
                           &io,    c->mgr, mm->data};
    size_t clipped_len = mm->data.len > 512 ? 512 : mm->data.len;
    MG_DEBUG(("%lu RECEIVED %.*s <- %.*s", c->id, clipped_len, mm->data.buf,
             mm->topic.len, mm->topic.buf));
    // Process the received message
    mg_rpc_process(&r);
    // Publish the response if there is one
    if (io.buf) {
      MG_INFO(("RPC Response: %.*s", io.len, io.buf));
      struct mg_mqtt_opts pub_opts;
      char topic[100] = WIZARD_MQTT_TX_TOPIC;
      memset(&pub_opts, 0, sizeof(pub_opts));
      pub_opts.topic = expandvar(topic, sizeof(topic));
      pub_opts.message = mg_str_n((char*)io.buf, io.len);
      pub_opts.qos = 0;
      mg_mqtt_pub(c, &pub_opts);
    }
    mg_iobuf_free(&io);
}

Losing the ability to call mg_timer_add() in user code is a bit of a pain... On reflection, perhaps the simple fix there is actually just to wrap mg_timer_add() with a glue function which supplies the mg_mgr option?? Eg just add the following function to mongoose_impl.c, then the whole issue disappears...

struct mg_timer *glue_timer_add(uint64_t milliseconds, unsigned flags, void (*fn)(void *), void *arg) {
  return mg_timer_add(s_mgr, milliseconds, flags, fn, arg);
}
dvosully commented 4 months ago

The recent updates for MQTT, exposing the mg_mgr, have resolved the challenges listed above. Good to close.