Presence Simulation with tasmota (record and playback messages)

Hello,

I try to get a Presence Simulation. It should record 24h or 48h and than if i start this, it should do exact the same that was record for the next 24h or 48h.

i can get all status, no problem. but can i them store in a way that the delay between is record too, and how can i do a playback?

anyone an idea?

i use all lights as Tasmota switch.

If you store the topics/payloads (or whatever you need) inside objects in an array, you can add a timestamp. Then when you playback the array, you can adjust the timestamps of all items by the difference of now minus the timestamp of the 1st message.

Then you can send that array to node-red-contrib-cron-plus and it will dynamically add these as scheduled entries and send the values at the specified time.

demo...

chrome_D1MNxpCFeq

demo flow ...

[{"id":"3852ef38911058af","type":"cronplus","z":"a4633311d1bf470d","name":"","outputField":"payload","timeZone":"","persistDynamic":false,"commandResponseMsgOutput":"output2","outputs":2,"options":[],"x":1680,"y":480,"wires":[["4af4fd6aeb97ff22","8fb5483e3cf5e486"],[]]},{"id":"c1499213e51ec5fc","type":"inject","z":"a4633311d1bf470d","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"topic 1","payload":"payload 1","payloadType":"str","x":1440,"y":140,"wires":[["5df070b0c3b59100"]]},{"id":"2736245fa940ceaf","type":"inject","z":"a4633311d1bf470d","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"topic 1","payload":"payload 2","payloadType":"str","x":1440,"y":180,"wires":[["5df070b0c3b59100"]]},{"id":"44fc61ea423c0de7","type":"inject","z":"a4633311d1bf470d","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"topic 2","payload":"payload 1","payloadType":"str","x":1440,"y":240,"wires":[["5df070b0c3b59100"]]},{"id":"2fa09290425699a7","type":"inject","z":"a4633311d1bf470d","name":"topic 2: 2 (number payload)","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"topic 2","payload":"2","payloadType":"num","x":1410,"y":280,"wires":[["5df070b0c3b59100"]]},{"id":"5df070b0c3b59100","type":"function","z":"a4633311d1bf470d","name":"message recorder","func":"let message_store = flow.get(\"message_store\") || [];\n\nif(msg.topic == \"CLEAR-STORE\") {\n    message_store = [];\n} else {\n    const clone = {\n        timestamp: Date.now(),\n        topic: msg.topic,\n        payload: RED.util.cloneMessage(msg.payload),\n    };\n    message_store.push(clone);\n}\n\nflow.set(\"message_store\", message_store);\n\nmsg.payload = message_store;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1690,"y":220,"wires":[["c89ba12007b13be6"]]},{"id":"9073e6e9a25a3da0","type":"inject","z":"a4633311d1bf470d","name":"playback","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1460,"y":400,"wires":[["2e2bdc612970a754"]]},{"id":"2e2bdc612970a754","type":"function","z":"a4633311d1bf470d","name":"prepare playback","func":"const message_store = flow.get(\"message_store\") || [];\n// debugger\nif(message_store.length == 0) {\n    node.warn(\"flow.message_store has no data\");\n    return null;\n}\nconst now = Date.now();\nconst ts = message_store[0].timestamp\nconst diff = now - ts;\nconst start_offset_ms = 200;\n\nif(diff < 0) {\n    node.warn(\"flow.message_store data is invalid\");\n    return null;\n}\n\nconst schedules = message_store.map((e, i) => {\n    let ptype = \"default\";\n    switch (typeof e.payload) {\n        case \"string\":\n            ptype = \"str\";\n            break;\n        case \"boolean\":\n            ptype = \"bool\";\n            break;\n        case \"object\":\n            ptype = \"json\";\n            break;\n        case \"number\":\n            ptype = \"num\";\n            break;\n        default:\n    }\n    return {\n        \"command\": \"add\",\n        \"name\": \"schedule\" + (i+1),\n        \"expression\": e.timestamp + diff + start_offset_ms,\n        \"expressionType\": \"dates\",\n        \"payloadType\": ptype,\n        \"payload\": e.payload,\n        \"topic\": e.topic\n    }\n})\n\nschedules.unshift({ \"command\": \"remove-all-dynamic\" });\n\nmsg.topic = \"\";\nmsg.payload = schedules;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1710,"y":400,"wires":[["3852ef38911058af","256c50f56a0f3eb5"]]},{"id":"4af4fd6aeb97ff22","type":"debug","z":"a4633311d1bf470d","name":"","active":true,"tosidebar":false,"console":false,"tostatus":true,"complete":"topic","targetType":"msg","statusVal":"payload","statusType":"auto","x":1960,"y":420,"wires":[]},{"id":"8fb5483e3cf5e486","type":"debug","z":"a4633311d1bf470d","name":"","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":1970,"y":480,"wires":[]},{"id":"e0b94a823c96e466","type":"inject","z":"a4633311d1bf470d","name":"","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"CLEAR-STORE","x":1440,"y":80,"wires":[["5df070b0c3b59100"]]},{"id":"256c50f56a0f3eb5","type":"debug","z":"a4633311d1bf470d","name":"","active":false,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"payload","statusType":"auto","x":1970,"y":340,"wires":[]},{"id":"19d6e675cf1cd4fd","type":"inject","z":"a4633311d1bf470d","name":"topic 2: { object payload }","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"topic 2","payload":"{\"prop\": \"i am a prop in a JS object\"}","payloadType":"json","x":1410,"y":320,"wires":[["5df070b0c3b59100"]]},{"id":"c89ba12007b13be6","type":"debug","z":"a4633311d1bf470d","name":"store count","active":false,"tosidebar":false,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","statusVal":"\"Store count: \" & $count(msg.payload)","statusType":"jsonata","x":1910,"y":220,"wires":[]}]
1 Like

That look great!

i will test! Thanks for the good replay

The idea is good, also the Work.

BUT it stores only the Output:
stat/tasmota_116C9B/RESULT

the tasmota ID is an unic for each device.

But to toggle the command needs to be
cmnd/tasmota_116C9B/Power

so i may ne4ed to filter that :smiley:
but that should possable. i will try a little bit and let you know how it works.

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