vert-x3 / vertx-mqtt

Vert.x MQTT
Apache License 2.0
184 stars 87 forks source link

Vert.X MQTT Router #55

Open alexgtn opened 6 years ago

alexgtn commented 6 years ago

What is your opinion on adding a Router for handling MQTT messages from clients?

Something very similar to the Vert.X Web Router.

Potential usage:

MqttServer mqttServer = MqttServer.create(vertx, options);

MqttEndpoint mqttEndpoint;

Router router = Router.router(vertx);

mqttServer.endpointHandler(endpoint -> {

      endpoint
            .publishHandler(router::accept)
            .publishReleaseHandler(endpoint::publishComplete);
      mqttEndpoint = endpoint;
      endpoint.accept(true);

}).listen( ... );

Route tempsGroup1 = router.route().path("/groupOne/temperatureSensor/:deviceId");
Route lightGroup2 = router.route().path("/groupTwo/lightSensor/:deviceId");

tempsGroup1.handler(routingContext -> {

  String deviceId = routingContext.message().getParam("deviceId");
  Buffer payload = routingContext.message().payload();
  // handle temperature data

  if (routingContext.message.qosLevel() == MqttQoS.AT_LEAST_ONCE) {
    mqttEndpoint.publishAcknowledge(routingContext.message.messageId());
  } else if (routingContext.message.qosLevel() == MqttQoS.EXACTLY_ONCE) {
    mqttEndpoint.publishRelease(routingContext.message.messageId());
  }

});

I think it will add a ton of convenience instead of manually handling every published message.

My use case requires an API, but I prefer MQTT instead of HTTP since it is IoT based.

ppatierno commented 6 years ago

I really think that it's a cool idea ! What I'm concerned on your example is the "non" standard way to have parameters on the MQTT topic (i.e. :deviceId). It's not something defined by the MQTT spec and I'd like to have the component more MQTT compliant. It means that the only thing that a routingContext could expose should be the underlying MQTT message. Do you think to work on a proposal for that with a PR ? :-)

alexgtn commented 6 years ago

@ppatierno sure. My project kind of requires this functionality anyway, so I'll work on that and submit a pr. Also, what about wildcards? As descibed here. I'm particularly interested in single-level "+" wildcards and to be able to get the value of the single-level wildcard in the handler. What do you think?

ppatierno commented 6 years ago

Good to know, waiting for your PR ! :) Regarding the wildcard feature can you give me an example of what you need ? Remember that wildcard works only on the subscription side and not on publishing side. Only a subscriber can specify a topic like "foo/+/bar" or "/foo/#" but a publisher can publish only to a well defined topic i.e. "foo/a/bar" (and not to "foo/+/bar")

vietj commented 6 years ago

@pmlopes as we do have a new implementation of router for vertx-web wouldn't it make sense to share common bits with this forthcoming router ? i.e have a component like vertx-uri-router

alexgtn commented 6 years ago

@ppatierno yes the client will publish to a well defined topic.

suppose the route definition is like this: Route fooBarRoute = router.route().path("foo/+/bar");

and a client publishes a message on the topic "foo/whatever/bar"

I want to get the value of the + in a variable. In the above case the value of the wildcard is "whatever".

But if the route is

Route fooBarRoute = router.route().path("foo/+/+/bar");

I want to be able to identify the 2 wildcards.

That is why I initially suggested

Route fooBarRoute = router.route().path("foo/:param1/:param2/bar");

This way we can identify between both parameters. If the client publishes a message to the topic "foo/x/y/bar" I can get the x,y values like this:

String x = routingContext.message().getParam("param1"); // "x"
String x = routingContext.message().getParam("param2"); // "y"
ppatierno commented 6 years ago

As I said I don't agree on having a non standard MQTT support for this feature. The ":param1" syntax isn't defined by the MQTT standard and I'd like to have the component to be compliant with the specification. From the routingContext you will have the published topic isn't it enough for you for getting the value of "x" and "y" ? I know that it could be simpler with your idea but it's not something standard.

alexgtn commented 6 years ago

@ppatierno ok let's follow the standards. Then I'll implement the wildcards like this

Route fooBarRoute = router.route().path("foo/+/bar");

and if there is need to get the value of the wildcard, one will need to split the topic name

alexgtn commented 6 years ago

@vietj could you make a separate package for the router files from the vertx-web? A common router package that will be used in vertx-web and vertx-mqtt. I think I've done the most part of the MQTT Router, but I've added the entire vertx-web to my vertx-mqtt. I'll update the new router package with the changes I made.

vietj commented 6 years ago

@AGutan that's something we need to discuss with @pmlopes and see how best we can address this

alexgtn commented 6 years ago

@vietj @pmlopes any updates on this?

vaIgarashi commented 5 years ago

Ping from 2019

vietj commented 5 years ago

@vagola unfortunately there is no progress on this issue yet