MQTT topic messages to variable

I use 2 topics:

itho/state/sensor => {'temp":20,“hum”:41.9} goes into the script to pars the numbers and punt into 2 vars: IthoTemp & IthoHum.

itho/state => [number] (speed setting) and put into a var IthoState.

No other topics used.

And the value for itho/state/sensor ends up in the flows that are triggered for itho/state, correct? Do you know if both messages (for both topics) are published at the same time?

yes that is correct.

When having 2 flows and both are triggered by 2 different MQTT topics, the result is put in the one and same output label: Message received bij topic. I think the script delays the output a little bit and therefore this info ( {'temp":20,“hum”:41.9}) is always as last visible in the output.

When I look at the MQTT explorer it looks like that the information is published at the same time but I can not confirm this. Maybe this is something I have to ask the developer of the hardware/software.

I think I found the actual problem.

I have one flow that triggers on test/test and one that triggers on test/test/test.

The flow that triggers on test/test also triggers on messages sent to test/test/test, which is exactly the problem that you get as well (where the flow that triggers on itho/state also triggers on messages published to itho/state/sensor).

I think it’s an issue with the MQTT Client app (@scanno), but OTOH, using both itho/state and itho/state/sensor as separate topics isn’t really great design either.

This is exactly the same as I see.

Thanks for all the support and that the possible cause had been found.
In the mean time I have contacted the developer and asked him is he is willing to change the code and make a split in topic names. If he is willing to do then this will solve the MQTT Message issue.

Besides this, I hope that @scanno is willing to have a look too for future improvements of the MQTT app.

Willing yes, but being able to is something different :sunglasses:. I thought I tested that kind of scenario :thinking:.

As soon as work / study allows, I will have a look at it.

3 Likes

I spoke to the developer of the add-on print who developed the software. He told me that the different topics are not sent at the same time.

Therefore it looks like that the MQTT client is triggered by to the overlap of the topic names.

In my case:
itho/state
itho/state/sensor

This results in that the label: “Message received from topic” will be overwritten.

The developer of the add-on is willing to have a look if it will be possible to split the the names in different topic and I hope (when you find some time) to have a look to the MQTT client if this can be fixed.

In the mean time he provided me a firmware update with changed topic names:

itho/sensor
itho/state
itho/cmd
itho/lwt

With the changed topic names, the test results are te same.
Therefore I did a final test. I changed a topic name: itho/state into ithostate/state.

Result: every flow and output variable works fine. :relaxed::ok_hand:t2:

I am pretty sure that the MQTT client is not able to handle 2 different topics, beginning with the same name.

Thanks for your support @robertklep & @scanno … for now we have to wait for the fix and/or solution provided for the MQTT client. :crossed_fingers:t2:

Yeah matching topic is flawed

If one of you can create a better matching algorithm, let me know.
Below is the code that contains the current matching algorithm.

   processMessage(args, state) {
      var reconnectClient = false;

      // Make a connection to the broker. But only do this once. When the app is started, the connectedClient
      // variable is set to null, so there is no client connection yet to the broker. If so, then connect to the broker.
      // Otherwise, skip the connection.
      this.broker.connectToBroker(args, state);

      this.logmodule.writelog ('info', "state.topic = " + state.triggerTopic + " topic = " + args.mqttTopic)

      // MQTT subscription topics can contain "wildcards", i.e a + sign. However the topic returned
      // by MQTT brokers contain the topic where the message is posted on. In that topic, the wildcard
      // is replaced by the actual value. So we will have to take into account any wildcards when matching the topics.

      var arrTriggerTopic = state.triggerTopic.split('/');
      var arrMQTTTopic = args.mqttTopic.split('/');
      var matchTopic = true;
      var hashWildcard = false;

      for (var value in arrTriggerTopic) {
         this.logmodule.writelog('debug', "arrTriggerTopic["+value+"] = "+arrMQTTTopic[value]);
         if (arrMQTTTopic[value] === '#') {
            this.logmodule.writelog('debug', "hashWildcard set to true because # detected");
            hashWildcard = true;
         }
         if ((arrTriggerTopic[value] !== arrMQTTTopic[value]) && (arrMQTTTopic[value] !== '+')) {
            // This is a bit dirty because it would allow events to be delivered also to topics that do not have
            // the trailing event. In de future, when allowing the other message types, this would cause problems
            if ((arrMQTTTopic[value] !== undefined) && (hashWildcard == false)) {
               matchTopic = false;
            }
         }
      }

      // If the topic that triggered me the topic I was waiting for?
      if (matchTopic == true) {
         console.log ("triggerTopic = equal" )
         return true;
      }
      // This is not the topic I was waiting for and it is a known topic
      this.logmodule.writelog('info', "We are not waiting for this topic");
      return false;
   }

Quick and dirty (it allows for subscription patterns that aren’t valid, but I assume that those can’t be used anyway):

function topicMatches(topic, pattern) {
  const regex = new RegExp('^' + pattern.replace(/\+/, '[^/]+').replace(/#/, '.+') + '$');
  return regex.test(topic);
}

// use:
topicMatches('foo/bar/blah', 'foo/+/blah'); // => true
topicMatches('foo/bar/blah', 'foo/+'); // => false
topicMatches('foo/bar/blah', 'foo/#'); // => true

Thx.
Although cannot get the app to build anymore. Guess too many env changes. Going to take too much time to resolve all this.

I think I had to replace require("mqtt/node_modules/mqtt") with require("mqtt") in broker.js to get it working.

Link to test version that includes @robertklep his RegExp

1 Like

Seems to work as expected with my (limited) test :+1:t2:

Shall I test it too for my setup?

Why not? You can always revert back to the stable version of the app if it doesn’t work :smiley:

I don’t believe it… all the flows and scripts with the different MQTT topics and Messages are working. So far no issues. :relaxed::ok_hand:t2::+1:t2:

I am curious what has been changed in order to get this issue solved?

The code that matches between the topic that the flow was listening to and the topic that a message came in on was faulty, it allowed for prefixes to match as well (so listening on test/test would also allow for messages published to test/test/test to be matched, because test/test is a prefix for test/test/test).

1 Like

Thank you all for your effort and that this could have been solved very quickly. :+1:t2:

I am very happy that the MQTT issues have been solved. :relaxed::ok_hand:t2:

Good to know it works and thanks to the regex suggestion from @robertklep , this issue is resolved. Submitted the test version for certification.

@RobvandeGoor can you test a new test version to see if the problem is still absent?