简体   繁体   中英

Node.js Mqtt client : matched topic

I have mqtt client, from mqtt node module.

I subscribe to topics for exemple topic1/#, topic2/#

When someone publish to topic2/165 (for exemple), I want to know that subscribed topic "topic2/#" matched.

Is there simple way to do that ?

Use a regular expression

client.on('message', function (topic, message) {
  var topic1_re = /^topic2\/.*/;
  var topic2_re = /^topic2\/.*/;

  if (topic.matches(topic1_re)) {
    //topic 1
  } else if (topic.matches(topic2_re)) {
    //topic 2
  }
}

I solved this with a generic function to create a regular expression from an MQTT subscription pattern. It essentially replaces + and /# with its regular-expression equivalent.

const sub2regex = (topic) => {
   return new RegExp(`^${topic}\$`
       .replaceAll('+', '[^/]*')
       .replace('/#', '(|/.*)')
   )
};

To demonstrate, tested on HiveMQ:

> let subTopic = 'home/+/light/#';
> let subRegex = sub2regex(subTopic);
> console.log(subRegex.toString()); 
/^home\/[^/]*\/light(|\/.*)$/

> subRegex.test('home/livingroom/light/north');
true
> subRegex.test('home/x/y/light/north');
false

More results:

testTrue = [  // These all test true
    'home/kitchen/light/north',
    'home/kitchen/light/fridge/upper', // multiple levels for #
    'home//light/north',  // + matches empty string
    'home/kitchen/light/',  // # matches empty string
    'home/kitchen/light',  // # matches no sub-topic
]
testFalse = [  // These all test false
    'home/x/y/light/north',  // multiple levels for +
    'home/kitchen/temperature',  // not a light
    'gerry/livingroom/light/north',  // not home
]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM