Switch node - MQTT like wildcards for switching

Maybe something like this?

// 2 incoming mqtt topic paths:
//  known_devices/<devName>/outputs/+
//  wiser/environment/<roomName>/+

const known_devices = global.get('known_devices','file')

const splitTopic = msg.topic.split('/')

let room = 'undefined', measure = 'undefined'

if ( splitTopic[0] === 'known_devices') {
    // Try to get the room name
    try  {
        room = known_devices[ splitTopic[1] ].location
    } catch (e) {
        node.warn(`Device not found for device ${splitTopic[2]}, Input: ${msg.topic}`)
    }
    
    measure = splitTopic[3]
} else {
    room = splitTopic[2]
    
    measure = splitTopic[3]
}

// Temperatures for each room
if ( msg.topic.toLowerCase().includes('temperature') ) {
    let topicRoot = `environment/temperature/${room}/${measure}`
    node.send([{
        topic: topicRoot,
        payload: msg.payload
    }, null, null, null])
    publishUpdate(topicRoot)
}

// humidities for each room
if ( msg.topic.toLowerCase().includes('humidity') ) {
    let topicRoot = `environment/humidity/${room}/${measure}`
    node.send([null, {
        topic: topicRoot,
        payload: msg.payload
    }, null, null])
    publishUpdate(topicRoot)
    // Check for excessive humidity
    if ( msg.payload > 70 ) {
        let topicRoot = `environment/humidity/${room}/humidity_excessive`
        node.send([null, {
            topic: topicRoot,
            payload: true
        }, null, null])
        publishUpdate(topicRoot)
    } else {
        let topicRoot = `environment/humidity/${room}/humidity_excessive`
        node.send([null, {
            topic: topicRoot,
            payload: false
        }, null, null])
        publishUpdate(topicRoot)
    }
}

// light levels for each room
if ( msg.topic.toLowerCase().includes('light') ||  msg.topic.toLowerCase().includes('lux') ) {
    let topicRoot = `environment/light/${room}/${measure}`
    node.send([null, {
        topic: topicRoot,
        payload: msg.payload
    }, null, null])
    publishUpdate(topicRoot)
}


return [null,null,null,msg]

function publishUpdate(topicRoot) {

    node.send({
        topic: `${topicRoot}/updated`,
        payload: (new Date()).toISOString()
    })
    node.send({
        topic: `${topicRoot}/updated_by`,
        payload: 'nrmain/Heating/fnCopyToEnv'
    })
    
} // --- end of function publishUpdate --- //

Or this flow?

A work in progress so I won't bother to share the code.

..or simply to reduce the number of nodes...

simple

Fair enough people :slight_smile:

2 Likes

I actually have this working in my local fork.

If Dave or Nick are happy, I'll push it to Dev branch?

Though in Paul's example I would just use 4 MQTT in nodes wired 1 - 1 :slight_smile:

1 Like

By all means PR it - though we have other things more pressing for 2.0 - so don't hold your breath.

1 Like

4 + 4 = 8 nodes
My example = 6 nodes

I did say

Yes - I can count...
I'm just saying I think the simplicity and clarity of wiring "8" nodes in 1-1 pairs - would be easier than having to use a switch node with yet another syntax for just this specific use case.
Or indeed the existing contains rule would handle it as you have it.

1 Like

It comes down to user choice, and user abilities.
There are always different ways of achieving the same result in node-RED, and it's it's got to be good to expose those options to let users decide.

I should hope so :wink:

1 Like

Not necessarily - the burden of choice can make a tool harder to use. That's why we are always careful not to add multiple ways of achieving the same thing.

I'm very much on the fence about this proposal. It adds MQTT topic wildcard semantics to a non MQTT node. I'm not sure if that is good or not - given the multiple options for solving this problem that already exist using more 'standard' choices that aren't limited to just MQTT topics.

3 Likes

Yes I get that, but looking at this from the perspective of a amateur, with limited technical knowledge, and I wanted to filter the incoming MQTT messages, I may well look towards the switch node.

It's node description is "Route messages based on their property values or sequence position", so if I were routing MQTT messages based upon their topic properties, it's probably fair to say, that the switch node would be a viable consideration.

1 Like

Though again. In the example uses above where does the mqtt wildcard come into play in the switch ? You need to actually match. None of them seem to need wildcards

As a total fumbling programming novice I find @knolleary argument fairly compelling. I'm going to suggest that most of the discussion so far has been from people so advanced they can't remember not coding. To me since I only have a hammer everything looks like a nail and offering more choices would probably just confuse me further.
That is of course only my own totally ignorant opinion

When you wanted to send a topic1/# one way and topic2/# another.
or +/sensors/# one way and +/switches/# another

1 Like

Doesn't "contains" do that already ?

2 Likes

Hey @gerry I understand your point and Nick's but if you would let me flip that coin...

A novice who is learning MQTT might understand the whole #+ filtering of topics but get them to do that in a function node or regex or JSONata and they end up here asking "how do I do ..."

So I started this thread to canvas opinion and so far I see a 60/40 approach, 60 like it 40 are "um but you can do xyz".

The the guy who raised this originally posted an interesting comment that led me starting this thread...

... To which I was originally defensive but he did raise an interesting point.

Keep the comments coming. It's good to debate. :slight_smile:

2 Likes

So why do we have contains, if we have regex or JSONata.
But to answer your question, as it would make things simpler as some else pointed out if you are using mqtt topics already, it would not be a leap to use them in the switch node to for routing.
[edit would contains handle topic/+/sensors/# ?]

2 Likes

Well you need somewhere to keep the interesting data, and then probably somewhere to tell you what that data is. So yes we chose payload and topic as we started from Mqtt world. We do try to stick to payload being the main property so all nodes know where to look by default. These days lots of properties other than topic are used to describe other aspects of the message, so we are not so tied to topic.

Actually it was the other way round. We had the simple comparisons first and then the more complex ones were added later. Indeed another alternative would be to add an option to contains to treat * as a real wildcard. (Visually like the ignore case option in regex)

I was not arguing chicken or egg, just that we have other methods.

MQTT wildcard routing would complement the MQTT node.