Deduplicate node with multiple inputs?

I have a flow that works on an array of Acurite thermo-hygrometer sensors. Everything to utilize these as I need works, but I have not properly implemented the battery low notification. Where I am stuck is in reducing the number of instances of the notifications being sent.

The portion in the "battery notification" region is intended to take the sensor json object and remove the values that change (temperature, humidity, time, etc) and just leave the critical things like unit ID, location, and battery_ok value. If battery_ok is less than 1, it means the battery is below Acurite's threshold and should be serviced soon. Since the individual sensors transmit at ~30 second intervals, I have a deduplicate node to filter out extraneous messages and only email periodically. This works fine if there is a single sensor that has a low battery. However, since I installed the batteries at basically the same time, I imagine that more than one sensor could be low at the same time. If that happened, then the deduplicate node would not trigger as intended. It would see sensor A with a low battery and notify, then sensor B would be detected as also unique and notify. Rinse, repeat and I end up with 2 emails every 30 seconds until I replace at least one sensor's batteries.

So, I'm wondering what my alternative would be to keep this module (not calling out each individual sensor in independent code blocks). The only thing I have come up with is to alter my approach to collect a list of bad sensors and email that list at scheduled times. I would have to check the list to remove sensors that have been fixed but at least I'd only have 1 email per period rather than the current flood.

Here's the snippet in the battery notification section if it helps.

[{"id":"95956d64.1c802","type":"switch","z":"b76701c5.7313f","name":"","property":"payload.battery_ok","propertyType":"msg","rules":[{"t":"lt","v":"1","vt":"num"}],"checkall":"true","repair":false,"outputs":1,"x":370,"y":340,"wires":[["9eee43be.5f0678","b55efabd.41ed8"]]},{"id":"47061126.bf4668","type":"comment","z":"b76701c5.7313f","name":"battery notification","info":"","x":410,"y":260,"wires":[]},{"id":"8682be55.2bce78","type":"debug","z":"b76701c5.7313f","name":"email","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":850,"y":340,"wires":[]},{"id":"9eee43be.5f0678","type":"debug","z":"b76701c5.7313f","name":"battery<1","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":500,"y":380,"wires":[]},{"id":"47cfdca2.e40a04","type":"function","z":"b76701c5.7313f","name":"create email","func":"let newmsg = {topic: \"Acurite-Tower battery low: (\"  + msg.payload.location + \")\" }\nnewmsg.payload = \"Acurite tower battery has dropped below lower threshold.  Replace at soonest convenience. \\n\\nLocation = \" + msg.payload.location + \"\\nID = \" + msg.payload.id;\n\nreturn newmsg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":690,"y":340,"wires":[["8682be55.2bce78","5d6db6.3652ca4c"]]},{"id":"f6e008da.ac0fc","type":"change","z":"b76701c5.7313f","name":"","rules":[{"t":"delete","p":"payload.time","pt":"msg"},{"t":"delete","p":"payload.tempF","pt":"msg"},{"t":"delete","p":"payload.temperature_C","pt":"msg"},{"t":"delete","p":"payload.humidity","pt":"msg"},{"t":"delete","p":"payload.moisture","pt":"msg"},{"t":"delete","p":"payload.moisture_offset","pt":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":650,"y":280,"wires":[["95956d64.1c802","8d57caa8.77f6b8"]]},{"id":"5466546f.eb0d74","type":"debug","z":"b76701c5.7313f","name":"unique","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":710,"y":420,"wires":[]},{"id":"dba2da92.e77c88","type":"debug","z":"b76701c5.7313f","name":"duplicate","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":690,"y":480,"wires":[]},{"id":"8d57caa8.77f6b8","type":"debug","z":"b76701c5.7313f","name":"","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":860,"y":300,"wires":[]},{"id":"b55efabd.41ed8","type":"deduplicate","z":"b76701c5.7313f","name":"Deduplicate","keyproperty":"","expirypolicy":"keep","registryclass":"","noderole":"standalone","expiry":"3600","x":510,"y":340,"wires":[["47cfdca2.e40a04","5466546f.eb0d74"],["dba2da92.e77c88"]],"inputLabels":["Eingang"],"outputLabels":["Einmal","Duplikat"]}]

And this is an example input into the change node:
image

{"time":"2023-01-04 20:28:47","model":"Acurite-Tower","id":9170,"channel":"C","battery_ok":0,"temperature_C":20.7,"humidity":35,"mic":"CHECKSUM","tempF":69.25999999999999,"moisture":6.299686434605598,"tag":"D","location":"Thermostat","moisture_offset":5.2711662003842745}

What is a deduplicate node, and when was the node last updated?

It's not clear if payload.battery_ok is an integer or a float, I have assumed it's an integer.

A Filter node can be set to block messages for each topic (put your device ID in msg.topic) unless msg.payload.battery_ok changes. Note: I got rid of your Switch node.

[{"id":"134e3f08233c7beb","type":"tab","label":"Flow 4","disabled":false,"info":"","env":[]},{"id":"47cfdca2.e40a04","type":"function","z":"134e3f08233c7beb","name":"create email","func":"let newmsg = {topic: \"Acurite-Tower battery low: (\"  + msg.payload.location + \")\" }\nnewmsg.payload = \"Acurite tower battery has dropped below lower threshold.  Replace at soonest convenience. \\n\\nLocation = \" + msg.payload.location + \"\\nID = \" + msg.payload.id;\n\nreturn newmsg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":850,"y":140,"wires":[["8682be55.2bce78"]]},{"id":"f6e008da.ac0fc","type":"change","z":"134e3f08233c7beb","name":"","rules":[{"t":"delete","p":"payload.time","pt":"msg"},{"t":"delete","p":"payload.tempF","pt":"msg"},{"t":"delete","p":"payload.temperature_C","pt":"msg"},{"t":"delete","p":"payload.humidity","pt":"msg"},{"t":"delete","p":"payload.moisture","pt":"msg"},{"t":"delete","p":"payload.moisture_offset","pt":"msg"},{"t":"set","p":"topic","pt":"msg","to":"payload.id","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":500,"y":140,"wires":[["8d57caa8.77f6b8","fcd5c085fffa2efe"]]},{"id":"8d57caa8.77f6b8","type":"debug","z":"134e3f08233c7beb","name":"New Data","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":500,"y":100,"wires":[]},{"id":"fcd5c085fffa2efe","type":"rbe","z":"134e3f08233c7beb","name":"","func":"rbei","gap":"","start":"","inout":"out","septopics":true,"property":"payload.battery_ok","topi":"topic","x":670,"y":140,"wires":[["47cfdca2.e40a04","8d0599c74e3d1ebd"]]},{"id":"c86ab344fd05e4bf","type":"function","z":"134e3f08233c7beb","name":"Bad Data 9170","func":"msg.payload = { \"time\": \"2023-01-04 20:28:47\", \"model\": \"Acurite-Tower\", \"id\": 9170, \"channel\": \"C\", \"battery_ok\": 0, \"temperature_C\": 20.7, \"humidity\": 35, \"mic\": \"CHECKSUM\", \"tempF\": 69.25999999999999, \"moisture\": 6.299686434605598, \"tag\": \"D\", \"location\": \"Thermostat\", \"moisture_offset\": 5.2711662003842745 }\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":260,"y":120,"wires":[["f6e008da.ac0fc"]]},{"id":"c18a8227a76dbfb3","type":"inject","z":"134e3f08233c7beb","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":100,"y":120,"wires":[["c86ab344fd05e4bf"]]},{"id":"31081034dca0f2dc","type":"function","z":"134e3f08233c7beb","name":"Good Data 9170","func":"msg.payload = { \"time\": \"2023-01-04 20:28:47\", \"model\": \"Acurite-Tower\", \"id\": 9170, \"channel\": \"C\", \"battery_ok\": 1, \"temperature_C\": 20.7, \"humidity\": 35, \"mic\": \"CHECKSUM\", \"tempF\": 69.25999999999999, \"moisture\": 6.299686434605598, \"tag\": \"D\", \"location\": \"Thermostat\", \"moisture_offset\": 5.2711662003842745 }\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":260,"y":80,"wires":[["f6e008da.ac0fc"]]},{"id":"7776524754e8a267","type":"inject","z":"134e3f08233c7beb","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":100,"y":80,"wires":[["31081034dca0f2dc"]]},{"id":"8d0599c74e3d1ebd","type":"debug","z":"134e3f08233c7beb","name":"debug 238","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":690,"y":180,"wires":[]},{"id":"8682be55.2bce78","type":"debug","z":"134e3f08233c7beb","name":"email","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":830,"y":100,"wires":[]},{"id":"49991f0f05cd31c8","type":"function","z":"134e3f08233c7beb","name":"Bad Data 9171","func":"msg.payload = { \"time\": \"2023-01-04 20:28:47\", \"model\": \"Acurite-Tower\", \"id\": 9171, \"channel\": \"C\", \"battery_ok\": 0, \"temperature_C\": 20.7, \"humidity\": 35, \"mic\": \"CHECKSUM\", \"tempF\": 69.25999999999999, \"moisture\": 6.299686434605598, \"tag\": \"D\", \"location\": \"Thermostat\", \"moisture_offset\": 5.2711662003842745 }\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":260,"y":200,"wires":[["f6e008da.ac0fc"]]},{"id":"66b65cf66ac4ab44","type":"inject","z":"134e3f08233c7beb","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":100,"y":200,"wires":[["49991f0f05cd31c8"]]},{"id":"0f1e623a99f36cf8","type":"function","z":"134e3f08233c7beb","name":"Good Data 9171","func":"msg.payload = { \"time\": \"2023-01-04 20:28:47\", \"model\": \"Acurite-Tower\", \"id\": 9171, \"channel\": \"C\", \"battery_ok\": 1, \"temperature_C\": 20.7, \"humidity\": 35, \"mic\": \"CHECKSUM\", \"tempF\": 69.25999999999999, \"moisture\": 6.299686434605598, \"tag\": \"D\", \"location\": \"Thermostat\", \"moisture_offset\": 5.2711662003842745 }\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":260,"y":160,"wires":[["f6e008da.ac0fc"]]},{"id":"0dcdadeae3f6902a","type":"inject","z":"134e3f08233c7beb","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":100,"y":160,"wires":[["0f1e623a99f36cf8"]]}]

I hadn't thought of a rbe node. I'm not sure it's working as expected though. I'll refer to your test inputs by number 1-4.

1 - no email (correct)
2 - mail (correct)
1 - email (incorrect)
3 - no email (correct)
4 - email (correct)
2 - email (correct)

I can switch back and forth between unit id and it seems to work. I think I just need it to only trigger on 1 -> 0 and not the other way. I would use the falling edge node with a threshold of 0.5 here, but I can't pick the part of the message to consider so that won't work.

You may need to experiment with the "ignore initial value" option.

Put your switch node back after the filter to only show 1 -> 0.

Ok, I'll try with the switch node back.

And for reference, the deduplication node is:
node-red-contrib-deduplicate-adv

Adding the switch back in after the rbe seems to do what I was hoping. I'll add it to my main flow and let it run for a while.

That seems to work well. It will only email the first time the sensor switches from 1 to 0, but that should be all I need. I just wanted to be notified at least once and not every time the sensor reported until dead. Thanks!

Yes, I thought only one notification per sensor might be a problem.

You could force a resend every day, week etc by injecting dummy messages with the IDs and battery_ok = 1.
There will be no notification of this message because of your switch; the next real message should trigger a fresh notification.

Interesting idea, I like it! I'll see if missed emails happen and update the code if I need to.

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