How to compare date/time?

Hi!
I’m using node-red to make some HTTP call’s on boocked schedulling API. The idea is to get a schedule for a given room and them, if it’s 10 minutes before scheduled time, turn on the light in this room.
I have success in HTTP calls to login and get current schedule for rooms, the result is a JSON string which is converted to object using JSON node. Everything ok here.

What I don’t have any idea is how do I compare the current date/time to the returned date/time?
This is the format of datetime returned by API: 2021-12-09T02:30:00+0000. It’s contained in a property of object.
ex:

{......"scheduleStartTime":"2021-12-09T02:30:00+0000",....}

My gues is: add a crontab node running everyminute…make this request every minute and compare the property of result with current date/time+10…but how to acomplish this?

Making API calls every minute sounds like a ban in progress.

I think a better solution is probably to only poll less frequent, say every half hour at xx:49 and xx:19 this is eleven minutes before the time and therefore enough time to turn the lights on in time.
The issue is if someone reserve a room xx:55 or even past the hour.

But are talking about meeting rooms or hotel rooms? Meeting rooms will probably be a nightmare, hotel rooms is more likely to be in advance.

Actually, ban is not a problem. Everything is locally (including booked software). It’s a university and i’m automating class rooms. We have this ope-source software called Boocked that we use to make room reservations and the idea is to turn lights and air conditioner on about 10 minutes before scheduled time.

But is the rooms generally booked more than 10 minutes in advance.
Will it be an issue if the lights did not come on in case someone made a late booking?

Even though you can poll every minute it’s perhaps not a good idea.
It will clog the network

No, it wont be an issue if we have a last time reservation…the user will just need to turn on the switch in the wall LOL
The idea is to automate most of reservations…but I’m sure we will have problems sometimes.

About pooling every minute and network related problems, this is ok for US, not problem at all.

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

Tks Hellis81, that worked!
I have removed delay and got the expected results…a number that is decreasing while getting closer to target time.

About multiple rooms, we have about 20 rooms…I’m not sure if I’ll create one flow for each room or just one flow that proccess all rooms.
I can make a call to get schedulle for all rooms at once (returning a list of schedules in only one API call) or make one call for each room.

I’m thinking of one call for all schedules and proccess this list using a function node, processing each schedule there.
The main problem is that I was planing to call the service to turn on the light and use a delay after that to present multiple commands to the same light every minute…but doing this in a function node will block the other schedules while waiting for delay node.
Unless I use an exactly value in this function node. Ex: if returned time is exactly 10 minutes, turn on the light…in the next minute, the returned time will not be 10 minutes anymore, will be less…therefore will not trigger turn on again.

But your example helped a lot! That’s what I need to compare dates/time!

I’d say get them all at once.

You can send multiple commands in to the same sequence and have them do different things at the other end. Just make sure to pass all the data in the message.

This is my “stop that noise” sequence that triggers when a timer is set on a google home. Then a variable delay is delaying until the time has passed + five seconds, then it stops the ringing.
I can set multiple timers on multiple devices and the same sequence will take care of them all.
They don’t have to be set in a particular order to work, the delay will delay each message the time it needs to be delayed.

I suppose your json will be something like:

[
   {
      "room: "1", 
      "scheduleStartTime":"2021-12-09T02:30:00+0000"
    },
    {
      "room: "2", 
      "scheduleStartTime":"2021-12-09T04:30:00+0000"
    }
]

As long as the json is sent along with the message, meaning, after the json node add a change node to change the place of the json to a different variable.

image

That way you always have the json with you.
Or just keep the room number and time, and discard all the other rooms in the message, perhaps better so that you’re not confused with what you are getting in the messages.

But I still believe a better solution is to take the rest call in HA.
That should give you a sensor in HA with attributes of all the rooms and the next time they need to trigger (?) or all the times they trigger?

Then use the time node and use this as the start of the sequence.

Here the entity will be the rest sensor and the property will should be attributes.0.scheduleStartTime (I guess?) for the first room.

Sounds a good idea, but I don’t have any idea how to achieve this in HA. A single call, ok, I found documentation for that…but Boocked API works this way:

  • Make a call, sending user and password
  • Get responde (json in body reply), property called sessionToken and userId.
  • In the subsequent calls, set two request headers: sessionToken and userId, both with preivous values returned from first call.

I managed to get this working in node-red, but I’m not sure if it’s possible with REST sensor in HA.

I see your point.
You could create a entity from Node red in HA (meaning creating a sensor just like a rest sensor, but from Node red).
I’m a bit busy right now.

But please post an example of the complete (or complet-ish) json of several rooms. That way I could perhaps help you with the sensor and how to handle this with a time node.