I need a message payload to be the opposite (on or off) based on the current state of a sonoff device. Using (in my case) an mqtt state of tasmota/SonoffLamp1/cmnd/Power I am able to ascertain the current status of the lamp. I have come across if(msg.payload.match(find)) and believe it best suits my requirements, but I am unable to construct the javascript to get the state and send on the opposite payload.
It's a little more complicated than that, let me explain.
I have a rf toggle switch which is being read by a sonoff bridge. When pressed I want to send an 0 or 1 to the MQTT broker to switch the light on, but it needs to establish the status from the point of receiving the rf code to committing the correct 0 or 1. Hopefully the nodes above will help understand what I am doing
You showed 2 flows the switch flow and the state flow. Where are you putting this?
If it is the function in the switch flow, where are you getting the current state from?
If I understand what you are trying to do you need to store the lamp state and then use that when the switch flow is triggered. If you want to share between the two flows you cannot use context, but you could use global or flow ( see the page I linked to). You can also set and get global. and flow. using the change node ( use drop down where it normally say msg.)
Then as I said before,
You need to store the lamp state which you can only do in the lamp state flow, and then use that in the switch flow.
If you want to share between the two flows you cannot use context. , but you could use global. or flow. ( see the page I linked to). You can also set and get global. and flow. using the change node ( use drop down where it normally say msg.)
In your switch flow you can then add a SWITCH node based on the value of the global. or flow. and then a change node
Based on what I see in your change node, I donât think this will do what you wantâŚ
You have two rules set to
change 0 -> 1, and
change 1 -> 0
So if your global lamp1payload is a 0, it first get set to 1, then then next rule will change it back to 0⌠But if the global var is already 1, the first rule will do nothing, and the second will still change it back to 0. So either way you end up with a 0 in your global var.
Besides that logic flaw, using a string replace operation to modify your numbers is not ideal (true, it should work with your limited inputs of 0 and 1, but what happens if you get the number 100? or undefined? or any JS object/array?)
Instead, I would either use a JS function with a ternary if ? then : else expression:
var last = global.get("lamp1payload") || 0;
var stat = stat == 0 ? 1 : 0;
global.set("lamp1payload", last);
return null;
or always increment the âstateâ value, and use the â%â modulo operator to keep the value in range (more general technique to use when you have more than 2 states):
var scnt = 2; // two states only for this example
var last = global.get("lamp1payload") || 0;
var stat = (stat + 1) % scnt;
global.set("lamp1payload", last);
return null;
I have been unable to physically try this until yesterday and both the change nodes method and the JS Function node method failed to work.
I was wondering if it has something to do with the fact that there is no node after the change node on the âlamp stateâ flow which sets the global.lamp1payload above, as there is an output on that node? However, if this is the case, I am unsure what node would be required?
Setting global.lamp1payload in a change node will set the global variable, but you must pick that up somewhere and use it at some point after setting it. Generally it is much better to avoid global and flow variables and instead set a value in the payload and pass it on to do whatever you want it to do in subsequent nodes.
Arugh I should read better before I post (need more coffeeâŚ)
When you set the global in the change node, it is set, but until some other node looks at that global nothing will happen.
For example, lets say you have an inject node (A) that runs only when you press it and it sets global.X to ânightâ. You have another flow that has a inject node (B) that also only runs when you press it, connected to a function node (which test global.X = ânightâ - if yes it send a 1) which is connected to a GPIO node which is wired to a lamp.
You do a deploy at noon, and the lamp is off and you wait, the sun goes down and the house gets dark. You press inject(A), but the light remains off. Even though the global.X has been set, the function node will not run till you press the second inject (B).