Best way to run a script every midnight

I have to generate a text file to reproduce something used by an accounting package done by others. I have worked out how to create the file correctly, but now I need to trigger it to occur once at midnight each night.

I have looked through some examples that are similar but I am not sure what is the best approach to handle this.

Also, at the moment, my script file is located under Project > Scripts > Script Library. I am not 100% sure I am clear on the scope of this or whether it might be better placed in another area. This is a standalone system (gateway and single client all on one PC).

Thanks!

Hi Okie,

On a standalone system like this, the only hiccup I can see is if you are getting anything from the client (vision components or client tags, etc.). In those instances, you’d be tied to the client scope. Otherwise, using the gateway scope should work just as well.

EDIT: Sorry, just took another look at what you posted. My personal preference would be to put it in the gateway scripts. That way the script should run, regardless of whether the client is running or not.

Hi Okie,
I’m new at this, but I would probably put something like this into an expression tag. Just make a new boolean expression tag anywhere in your tag tree (I would probably create a folder like ‘Scheduled reports’ or something, just for housekeeping). In the expression of the tag, put:

dateExtract(now(),"hour") = 00

In the tag change script section, I would have something like:

if initialChange == False: if currentValue.value == True and previousValue.value == False: doThatThingYouDo()

The only hiccup I can foresee is if you restart your server just prior to midnight and the system comes back online just after midnight. It won’t catch the tag transition as the system will also fire the initialChange event. In this case, you might be able to leave that portion out if you are ok with the script executing when the tag is edited.

Brian

It depends a bit how you want to handle the situation when you’ve had your system down when midnight passes. Do you want to just skip it, or run it as soon as possible?
The former is relatively easy: Create an integer expression tag with this expression:dateExtract(now(), "hour")Then in your project, under “Gateway Event Scripts”, create a tag change event script pointing at that tag with this code:if not initialChange and newValue.value==0: project.myScript.myFunction()That’s it. The function will be called at midnight every night that the server is running, in gateway scope (the service), whether any client is running or not. Even if no-one is even logged into the machine.
If you want to run the script as soon as possible after startup if you missed one, you will need another tag to hold the last midnight timestamp you’ve successfully processed. Then replace the “not initialChange and” part of the event script with “initialChange or” and add another check of the content of that tag. The function, if called, would write a timestamp back to that tag when successful.

2 Likes

[quote=“pturmel”]It depends a bit how you want to handle the situation when you’ve had your system down when midnight passes. Do you want to just skip it, or run it as soon as possible?
The former is relatively easy: Create an integer expression tag with this expression:dateExtract(now(), "hour")Then in your project, under “Gateway Event Scripts”, create a tag change event script pointing at that tag with this code:if not initialChange and newValue.value==0: project.myScript.myFunction()That’s it. The function will be called at midnight every night that the server is running, in gateway scope (the service), whether any client is running or not. Even if no-one is even logged into the machine.
If you want to run the script as soon as possible after startup if you missed one, you will need another tag to hold the last midnight timestamp you’ve successfully processed. Then replace the “not initialChange and” part of the event script with “initialChange or” and add another check of the content of that tag. The function, if called, would write a timestamp back to that tag when successful.[/quote]
Phil,
Any reason you recommend putting the execution code under the Gateway Event Scripts section instead of simply in the Tag Events area of the tag itself? As I mentioned, I’m a bit new to this and am wondering if there’s a difference that I’m not aware of…

Thanks,
Brian

[quote=“Brian”]Any reason you recommend putting the execution code under the Gateway Event Scripts section instead of simply in the Tag Events area of the tag itself? As I mentioned, I’m a bit new to this and am wondering if there’s a difference that I’m not aware of…[/quote]Tag events can’t access the project.* scripts, so I chose the Gateway event scripts for this case. However, I generally do anyways, as the scripts are then part of the project, not part of the gateway as a whole. You can disable a project to keep its event scripts from running without disturbing other items in your server. Also, changes to the the events themselves don’t take effect until you save/publish the project. That can be important if you are restructuring related code on multiple tags, and need it to take effect in one transaction.
However, if a particular tag’s change scripts are critical and must always run, then I put them on the tag itself. Possibly after debugging as a Gateway Event Script for a while.

Interesting, thanks for the explanation Phil.

Great info, Thank you all!

I created two tags Hour and HourRPT. Hour is an expression tag using the suggested expression to retrieve the PC clock hour. HourRPT is an integer memory tag.

I put the script under Gateway Event Scripts > Tag Change and added both tags to the list to be checked. In the script I used the compare with the system.tag.read(“HourRPT”) as the compare instead of “==0”.

This let me change the hour of the day at which the script runs by writing a value into HourRPT so I could test it. Now I don’t have to wait til tomorrow to see if the file was created, I can simply change the value of HourRPT and when it matches my script is called and voila, a new report is generated.

Thanks again!
Paul