How can I trigger a message when the value goes past one value and then past another?

The Suzuki engine interface in my boat sends tilt/trim to SignalK, which I forward to the MQTT broker, where it's read by Node-RED. What I need is a way to trigger an MQTT message (to an ESP Home-device, but that doesn't really matter) when the value on the MQTT message ins go from above 60 to below 50. So send a message for instance on 49 in this one: 64 - 58 - 55 - 49

Or on 45 in this one: 72 - 45

Is that clear? It is in my head, but many things are clear in my head, but doesn't really work when it comes out. Must be my age... :smile:

You will need to keep track of the latest value using a context variable. Then when a new msg comes in, you can compare against the previous. Personally, I would do this in a function node but that's because I use JavaScript a lot. It is possible to do with just nodes if you prefer.

There are lots of ways to do the logic, hard to pick out which might make most sense to you.

You could test each incoming value and if over 60, set a flag in a context variable to TRUE. But before that, check the flag and if it is >60, check the current value to see if it is <50.

const over60 = context.get('over60') ?? false // default to false if flag not yet set
if (over60) {
  if (msg.payload < 50) {
    // .... do stuff ....
  }
}

if (msg.payload > 60) {
  context.set('over60', true)
}

Something like that anyway.

1 Like

You can also set a range not to pass in a switch node and a bool or even a string to filter.
e.g.

[{"id":"a70496e41c71d110","type":"inject","z":"b779de97.b1b46","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[64,58,55,49]","payloadType":"json","x":150,"y":4780,"wires":[["fa4a3fca5738f1da"]]},{"id":"fa4a3fca5738f1da","type":"split","z":"b779de97.b1b46","name":"simulate speed changes","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":390,"y":4780,"wires":[["3c1fc4ff0598b7b3"]]},{"id":"3c1fc4ff0598b7b3","type":"switch","z":"b779de97.b1b46","name":"","property":"payload","propertyType":"msg","rules":[{"t":"btwn","v":"60","vt":"num","v2":"50","v2t":"num"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":310,"y":4840,"wires":[[],["1f38ba6803dbcf03"]]},{"id":"1f38ba6803dbcf03","type":"change","z":"b779de97.b1b46","name":"","rules":[{"t":"set","p":"bool","pt":"msg","to":"$$.payload > 60 ? true : ($$.payload < 50 ? false)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":470,"y":4840,"wires":[["8d65345979d30c4a"]]},{"id":"8d65345979d30c4a","type":"rbe","z":"b779de97.b1b46","name":"","func":"rbe","gap":"","start":"","inout":"out","septopics":true,"property":"bool","topi":"topic","x":610,"y":4840,"wires":[["45aaa8beff28855d"]]},{"id":"45aaa8beff28855d","type":"debug","z":"b779de97.b1b46","name":"debug 2479","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":550,"y":4880,"wires":[]}]
1 Like

You could always save the value in a context variable and then check it against the next value coming in.

You will probably want to set up a method to reset the context variable at some point in time or when some event happens.

[posted to slowly :joy:]

1 Like

Thank you for the quick answers! I will look at the methods now! I forgot to say one thing: The transition must happen within 10 seconds, showing that the ouboard is actively tilting.

@E1cid I think that will not work, if I'm not mistaken this method assumes that the range of numbers come in one mesage. They come in separate messages one by one, I was probably not clear enough about that.

No, the inject and split are just to demo 4 separate numbers coming in, they are a simulation..

But you have now moved the goal posts, with a time limit

1 Like

Aha, I see! I will have another look at that. And Yes, I have moved them. Sorry, as I said I forgot that...

Edit: And the trim sensor messages come in every second even if there is no change. But that I can filter out with a filter node.

Edit 2: Maybe using the constant and then invalidate it after 10 seconds would do this? I just don't know how to do that.

Edit 3: Getting closer, I think, with a function node that's triggered after 12 seconds, blocked by set message reset if a new message above 60 comes in.

Maybe this will help

[{"id":"a70496e41c71d110","type":"inject","z":"d1395164b4eec73e","name":"slow tilt","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[64,58,55,49]","payloadType":"json","x":310,"y":7200,"wires":[["fa4a3fca5738f1da"]]},{"id":"fa4a3fca5738f1da","type":"split","z":"d1395164b4eec73e","name":"simulate speed changes","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":550,"y":7200,"wires":[["e3e72375d646925f"]]},{"id":"e3e72375d646925f","type":"delay","z":"d1395164b4eec73e","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"5","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":780,"y":7200,"wires":[["3c1fc4ff0598b7b3"]]},{"id":"3c1fc4ff0598b7b3","type":"switch","z":"d1395164b4eec73e","name":"","property":"payload","propertyType":"msg","rules":[{"t":"gt","v":"60","vt":"num"},{"t":"lt","v":"50","vt":"num"}],"checkall":"false","repair":false,"outputs":2,"x":490,"y":7300,"wires":[["e84c0f5e13faa838"],["e3ec97dc52d519bc"]]},{"id":"8aa338c4514c1bd3","type":"delay","z":"d1395164b4eec73e","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":810,"y":7240,"wires":[["3c1fc4ff0598b7b3"]]},{"id":"e84c0f5e13faa838","type":"change","z":"d1395164b4eec73e","name":"","rules":[{"t":"set","p":"above","pt":"flow","to":"","tot":"date"}],"action":"","property":"","from":"","to":"","reg":false,"x":660,"y":7280,"wires":[[]]},{"id":"e3ec97dc52d519bc","type":"change","z":"d1395164b4eec73e","name":"","rules":[{"t":"set","p":"tilt_time","pt":"msg","to":"","tot":"date"},{"t":"set","p":"payload","pt":"msg","to":" $$.tilt_time - $flowContext(\"above\") < 10000\t","tot":"jsonata"},{"t":"delete","p":"above","pt":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":660,"y":7320,"wires":[["45aaa8beff28855d"]]},{"id":"1cd30ce26ea7e5c4","type":"split","z":"d1395164b4eec73e","name":"simulate speed changes","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":550,"y":7240,"wires":[["8aa338c4514c1bd3"]]},{"id":"45aaa8beff28855d","type":"debug","z":"d1395164b4eec73e","name":"debug 2479","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":850,"y":7340,"wires":[]},{"id":"59929ae29e3cc13e","type":"inject","z":"d1395164b4eec73e","name":"fast tilt","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[64,58,55,49]","payloadType":"json","x":330,"y":7240,"wires":[["1cd30ce26ea7e5c4"]]}]

It seems to do exactly what I need it to, thank you very much!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.