Here is one attempt.
It uses a variable delay. Not a good solution but a start.
[{"id":"b1664fd5d8d9d187","type":"json","z":"14ca354715bc92f3","name":"","property":"payload","action":"","pretty":false,"x":410,"y":740,"wires":[["1780f32f475e5176"]]},{"id":"f91c0961d1a8d7db","type":"inject","z":"14ca354715bc92f3","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"scheduleStartTime\":\"2021-12-08T20:20:00+0000\"}","payloadType":"str","x":240,"y":740,"wires":[["b1664fd5d8d9d187"]]},{"id":"1780f32f475e5176","type":"function","z":"14ca354715bc92f3","name":"","func":"\nmsg.delay = ((Date.parse(msg.payload.scheduleStartTime)-Date.now()) - 600000);\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":570,"y":740,"wires":[["2058311123542463"]]},{"id":"2058311123542463","type":"delay","z":"14ca354715bc92f3","name":"","pauseType":"delayv","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"x":720,"y":780,"wires":[["ed0a70bcd258ea58"]]},{"id":"ed0a70bcd258ea58","type":"debug","z":"14ca354715bc92f3","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":880,"y":740,"wires":[]}]
I believe a better method is probably to expose the datetimes in HA then use the time node to start the sequences. It will be safer.
How do you know what room to “trigger”?
If you need to stop a timer open the delay and click on the disable button at the bottom, deploy and enable - deploy again.
EDIT:
I just realised delay node wanted milliseconds and not seconds