Extended Timed Scripts

Yet another newbie question… I’d like to build a feature in my app that runs a refresh subroutine anywhere from once every hour to once daily, and I’m trying to figure out how to do this in AppleScript Studio. The only thing I could come up with was using “delay” and “repeat,” which would seem to be an inefficient way of doing things, since this’d be an app that runs continually in the background. If anyone could help shine some light on this, I’d appreciate it.

BTW, thanks for the great AppleScript resource - this message board has been really helpful as I teach myself AS Studio… usually just searching the archives is good enough to find an answer to my questions. :smiley:

Hi,

One way might be to monitor the time with an idle handler. Here’s an example of a stay open script:

property unit_list : {“minutes”, “hours”, “days”}
global recur_unit, tar_date

on run
set u to choose from list unit_list
if u is false then return – user cancelled
set unit_string to item 1 of u
set recur_unit to run script unit_string
set cur_date to (current date)
set cur_time to time of cur_date
set t to cur_time div recur_unit
set date_mn to date (date string of cur_date)
set tar_date to date_mn + (t + 1) * recur_unit
end run

on idle
set cur_date to (current date)
if tar_date < cur_date then
set tar_date to tar_date + recur_unit
UpdateSomething(cur_date as string)
end if
– set the_delay to (tar_date - cur_date) div 2 – to vary idle time
return 2 – seconds
end idle

on UpdateSomething(p)
say p
return
end UpdateSomething

The run handler here is used to initialize the target date. In ASS you might do initialization in a launch handler or something else. Here the idle handler runs about every 2 seconds. You could vary the idle time for less cpu usage.

Another idea might be to create a crontab that sends an event to your ASS app. I’m not sure what would be the best way to do this.

gl,

Interesting… thanks for the sample code!

I thought of an option that might be easier than the other options - the refresh time in hours is stored in a property (read from defaults), and the time of each refresh (the action that I’m trying to automate every X hours) is stored in a property - is there any way I could use idle to put the current time into one variable, (I’ll call it timeTemp) then compare this variable with the one that’s updated every refresh (I’ll call it lastTime), and if the time difference between timetemp and last_time is X hours (depending on the refresh time variable), then move on to the refresh subroutine?

Thanks for the help, and sorry if this is something really obvious - I’m pretty much teaching myself AS Studio from scratch with this app, so I end up knowing mildly advanced things like how to read/write defaults, but not knowing how to do something simple like check to see if two variables contain the exact same string. :smiley:

Hi Me,

I don’t know know much about the user defaults, but what is the name of the default entry that stores the last refresh time? Is the value a string representing seconds?

Later,

Hi Me,

I reread your post and don’t understand what the refresh time in hours means. Say you read the property for refresh time and get “5” (hours). What does this mean? The second property you wrote about is the time of each refresh. It’s better to know the date and time especially around midnight.

Later,

Ah, good point… I guess what I’d like to do is something along these lines, in my rough and probably very incorrect AppleScript:

property refreshtime : "1"
-- refresh every hour

on refreshStats()
    -- refresh
    set refreshTime to (current date)
    idle
end refreshStats

on idle
    set idleTime to (current date)
    if refreshtime is equal to "1" then
        -- I don't know how I'd do this, but here's where I'd compare refreshTime to idleTime and see if they're an hour apart.
        if [this is the part where I don't know what to use] then
                refreshStats()
        end if
    end if
    return 60
end idle

Hi,

Here’s an example of your script modified. I tried to make it as close as I could. Again, you should do the initializing in some other handler other than the run handler in your AS Studio app. Note that the idle handler automatically runs and doesn’t need to be called.

property refreshHours : “1” – hours
property theStats : 0
global refreshTime, idleTime
– initialize
on run
set curDate to (current date)
set theSecs to (refreshHours * hours) – refreshHours (a string) is coerced to 1 (an integer)
set refreshTime to (curDate + theSecs)
end run
– The idle handler is the last handler automatically called in your AS Studio app
on idle
set curDate to (current date)
if refreshTime < curDate then
refreshStats()
set refreshTime to curDate + (refreshHours * hours)
– ‘hours’ is an AppleScript constant whose value is number of seconds in an hour
end if
set timeDifference to refreshTime - curDate
– the following cuts down cpu usage
– similar to crontabs I think
– you can change the 5 seconds minimum to some other integer
if timeDifference < 5 then
set idleTime to timeDifference
else
set idleTime to timeDifference div 2
end if
return idleTime
end idle
– This subroutine increments theStats when this subroutine is called
on refreshStats()
– refresh
set theStats to theStats + 1
beep theStats – for testing
return true
end refreshStats

I didn’t test it with hours yet, but it looks like it should work. Note that the idleTime variable is like a delay between calls to the idle handler. Here I made the stats just a counter of the number of times the refreshStats subroutine is called.

gl,

property refresh_time : hours

on idle
	
	-- perform actions
	
	return refresh_time - (time of (current date)) mod refresh_time
end idle

If you don’t want it to perform any actions when it first starts up then use this:

property refresh_time : hours

on run
	set wait_for_it to true
end run

on idle
	if wait_for_it then
		set wait_for_it to false
	else
		
		-- perform actions
		
	end if
	
	return refresh_time - (time of (current date)) mod refresh_time
end idle

To make the refresh time two hours you would change the refresh_time to 2 * hours and so on.

Thanks, Qwerty and kel… I really appreciate all the help.

Hi Qwerty Denzel,

I just tested it out for an hour and am surprised that using the return time as a timer is accurate here in OSX! I’m quite sure it wasn’t accurate in OS 8.6 where I did most of my testing. I guess using the target time must only be good for something like an alarm set to a certain time.

Thanks a lot,

I tried Qwerty’s code, but think I’m doing something really stupid… in my idle handler, I have:

refreshStats()
return prefs_refreshtime - (time of (current date)) mod prefs_refreshtime

with “idle” at the bottom of my “awake from nib” processing. It idles normally, but then it refreshes five times before stopping and proceeding normally (returning to idle an hour later.)

Here’s what my console log looks like:

[Session started at 2005-08-17 11:41:30 -0400.]
2005-08-17 11:41:31.999 OA10694] “awake from nib”
2005-08-17 11:41:32.075 OA[10694] “defaults registered”
2005-08-17 11:41:32.181 OA[10694] “defaults read”
2005-08-17 11:41:32.257 OA[10694] “idle”
2005-08-17 11:41:33.952 OA[10694] “refresh complete”
2005-08-17 11:41:33.960 OA[10694] “idle”
2005-08-17 11:41:36.058 OA[10694] “refresh complete”
2005-08-17 11:41:36.063 OA[10694] “awake from nib”
2005-08-17 11:41:36.081 OA[10694] “idle”
2005-08-17 11:41:37.408 OA[10694] “refresh complete”
2005-08-17 11:41:40.743 OA[10694] “awake from nib”
2005-08-17 11:41:40.775 OA[10694] “idle”
2005-08-17 11:41:42.196 OA[10694] “refresh complete”
2005-08-17 11:41:43.429 OA[10694] “awake from nib”
2005-08-17 11:41:43.442 OA[10694] “idle”
2005-08-17 11:41:45.357 OA[10694] “refresh completed”

Haha, the problem there was with my own stupidity - I put two “idle”'s in the code when there should have only been one.

Sorry to bring this thread back, but I can’t figure out what I’m doing wrong with this script. I have it set to refresh hourly, but it’s doing it seemingly randomly… here’s the code I’m using:

property prefs_refreshtime : 1 * hours

on awake from nib theObject
if the name of theObject is equal to “mainWindow” then
if firstlaunch is true then
show window “welcomeWindow”
else
idle
end if
growlRegister()
end if
end awake from nib

on idle
log “idle. refreshtime is " & prefs_refreshtime & " before modification, " & prefs_refreshtime - (time of (current date)) mod prefs_refreshtime & " after.”
refreshStats()
return prefs_refreshtime - (time of (current date)) mod prefs_refreshtime
end idle

And here’s what shows up in my log:

[Session started at 2005-09-06 18:23:01 -0400.]
2005-09-06 18:23:06.774 OA[386] “idle. refreshtime is 3600.0 before modification, 2214.0 after.”
2005-09-06 18:23:40.096 OA[386] “refresh”
2005-09-06 19:00:00.369 OA[386] “idle. refreshtime is 3600.0 before modification, 3600.0 after.”
2005-09-06 19:00:03.633 OA[386] “refresh”

EDIT: BTW, in case anyone’s interested in what this app is going to be, it’ll be a freeware tool to check Amazon.com sales rankings - for a screenshot, see http://makeashorterlink.com/?R29614FBB