waking from sleep repetitively

I would like to be able to wake my Powerbook (OS 10.4) repetitively every 10 minutes, continue a running program, then go back to sleep for another 10 minutes.
The freeware program SleepWatcher will run a program on Mac sleep or Mac wake, so my idea was to run a compiled script on wake up.
The script would use the shell command pmset to set the next wake up time to be current_time + 10 minutes. But I have never used applescript. Can someone help me get started?

Thanks

AppleScript supports what are called “on idle” scripts that automatically repeat every n seconds + their running time. They go like this:

on run
	(*do setup - this runs when the application is started to set things up. It is not necessary to have an 'on run' handler because the on idle handler runs immediately after this anyway. If you want this to run all the time after every login, list it your startup items. You quit it from it's dock icon.*)
end run

(*'on idle' runs immediately following the 'run' handler if there is one, and thereafter on the interval specified in the return at the end. (An 'on run' handler is not required, so omit if there is no setup)*)
on idle
	-- In this section, you do your script operations every interval
	return xx -- do this every xx *seconds*.
end idle

on quit
	(*do stuff - assumes you want to clean things up or save preferences or variables before the program quits. This section runs only if the application is quit from the dock, or by any other means. It is not necessary to have one.*)
	
	(*if there is an on quit handler, then 'continue quit' must be the last statement or the script will not stop! The presence of an 'on quit' handler 'grabs' the system command to stop, so it will not complete the quit process until notified to do so. 'continue quit' does that.*)
	continue quit
end quit

You save them as stay-open applications (settings at the bottom of the save dialog box), quit them from the dock. They can be made into background applications if they don’t have a gui. They don’t use much in the way of resources between calls – they just idle.

Thanks. Sounds like this will do the job. I will post a script when I get it to work, and am sure the list will find ways to improve it.
This list is great. Sorry I didn’t start using it before.

The idle routine will work fine. Before implementing that, I am developing a script that puts the Mac to sleep right away and then wakes it up automatically a few minutes later. It is close to working, but as you will see, I can’t pass a variable defined in Applescript (WakeNow) to the shell command pmset. How do I do that?

I realize the way I am formatting the date is ugly, but I haven’t found a simpler way. It works, so I would like to get the whole thing working and then go back and make it more elegant.

Also, how does one use the Applescript button here to paste in a script? I just cut and paste, and it does not look right.

Thanks again.


set wake_time to ((current date) + 120)

set WakeNow to date_format(wake_time)

do shell script "pmset -a displaysleep 1 sleep 1" password "YourPW" with administrator privileges

-- I would like to do pmset schedule sleep date/time here instead of setting sleep delay in the Energy
-- Control Panel (to put the computer to sleep right away)
-- but then a window comes up saying it will go to sleep 10 minutes from then unless I hit
-- the button named sleep.  Any way of avoiding this and just going to sleep right then?
delay 1
do shell script "pmset schedule wake '09/22/07 15:12:00'" password "Your PW" with administrator privileges
-- This works if you insert a specific date and time according the the format "mm/dd/yy hy:min:sec"

--do shell script "pmset schedule wake 'WakeNow'" password "YourPW" with administrator privileges
-- This doesn't work. How do I pass the string "WakeNow" to the shell command pmset?

delay 1
do shell script "sudo -k" -- timeout sudo ability

on date_format(user_date)
	set {year:y, month:m, day:d, time:total_time} to user_date
	set ymd to (y * 10000 + m * 100 + d) as string
	set new_date to (text items 5 thru 6 of ymd as string) & "/" & (text items 7 thru 8 of ymd as string) & "/" & (text items 3 thru 4 of ymd as string)
	set hr to round total_time / 3600 rounding down
	set min to round ((total_time - hr * 3600) / 60) rounding down
	set sec to (total_time - hr * 3600 - min * 60)
	set hms to (1000000 + 10000 * hr + 100 * min + sec) as string
	set new_date to ((((new_date & " " & text items 2 thru 3 of hms as string) & ":" & text items 4 thru 5 of hms as string) & ":" & text items 6 thru 7 of hms as string))
	return new_date
end date_format

EDIT (Adam Bell): Reformatted – AppleScript tags go before and after the script.

Hi Frank,

a suggestion for the date format routine :wink:

on date_format(user_date)
	tell ((user_date) as «class isot» as string) to return (text 6 thru 7 & "/" & text 9 thru 10 & "/" & text 3 thru 4 & space & text 12 thru -1) as Unicode text
end date_format

Thanks. SO much neater. I have to learn about classes. The “as Unicode text” at the end did not seem to do anything I could see, though

Any ideas about passing Applescript variables to shell scripts?

AppleScript is often very nice and coerces classes silently, if necessary.
I prefer to pass the value in the proper class. A shell script call expects actually Unicode text,
that’s the reason for the explicit coercion

of course, for example

set wakeup to date_format((current date) + hours)
do shell script "pmset schedule wake " & quoted form of wakeup password "Your PW" with administrator privileges

on date_format(user_date)
	tell ((user_date) as «class isot» as string) to return (text 6 thru 7 & "/" & text 9 thru 10 & "/" & text 3 thru 4 & space & text 12 thru -1) as Unicode text
end date_format

note: quoted form is necessary, if there are space characters in the argument or path

Works beautifully. Here is the script. CycleMinutes sets the total time for one cycle. Note that IDLE counts only the time when the MAC is awake - sleep time is not counted. So set the Return time to just the number of seconds needed for doing the job you want done repetitively. Note I have also set WakeNow to occur at an integral # of minutes - this could be changed. Many thanks to the Applescript folks who showed me how to do this.

Still don’t know how to paste the script into the Applescript prompt!

on run
	--Opening statements here; none required
end run

on idle
	set CycleMinutes to 5 -- Total cycle time; always wakes on an integer minute:  hh/mm/00
	set wake_time to ((current date) + 60 * CycleMinutes)
	set WakeNow to date_format(wake_time)
	do shell script "pmset schedule wake " & quoted form of WakeNow password "YourPasswordHere" with administrator privileges
	delay 1
	do shell script "sudo -k" -- timeout sudo ability
	tell application "Finder" to sleep
	return 45 --IDLE does not count sleeping time!
end idle

on quit
	--Closing statements here   --none needed
	continue quit
end quit

on date_format(user_date)
	--tell ((user_date) as «class isot» as string) to return (text 6 thru 7 & "/" & text 9 thru 10 & "/" & text 3 thru 4 & space & text 12 thru -1) as Unicode text
	tell ((user_date) as «class isot» as string) to return (text 6 thru 7 & "/" & text 9 thru 10 & "/" & text 3 thru 4 & space & text 12 thru 17 & "00") as Unicode text  	-- round down to whole minute
end date_format

Model: Powerbook G4 and Intel Powerbook
Browser: Firefox 2.0.0.7
Operating System: Mac OS X (10.4)

Just wanted to pass along a further improvement. Basically, how does one quit this program? If you choose “Quit” from the menu, then the Mac still goes to sleep one more time. So you need to interrupt the process. On non-Intel Macs, you can do that with “keys pressed” from Jon’s additions. But on an Intel, the only way I have found is to use the similar command in Extra Suites. BTW, I have tried to purchase that program ($10 US) from Kagi, but the author has never sent me the license. Anyone tried to buy Extra Suites recently? So I am asking if there is another way to escape from my program. Perhaps the new Applescript options in Leopard will make this possible without add-on programs?

The other question is how to make the program work for other people. The command pmset requires an administrator password, so I just enter mine into the script. But if I share the program, others will need to enter their pw into the script - a nuisance. If they don’t, they get a prompt to enter it each time they run the program - worse, they must keep entering it every 5-10 minutes while the program is running. Since the goal of this program is to run (on idle) for a long time (waking up every 5 or 10 minutes to record another GPS position while sailing long distances), that is a real nuisance. Is there a way to write the script so that a new user uses his/her admin pw once, and then that is remembered forever? Store it in a hidden file for example. Suggestions welcome.

Here is the script, for the few of you who are long distance sailors!


global CycleTime
global QuitNow
global WakeTime
property PW : "XXX"

on run
	set CycleTime to choose from list {1.5, 2, 5, 10, 20} with prompt ("Choose cycle time in minutes" & return & "Press and hold  key to quit") default items {1.5}
	set CycleTime to minutes * CycleTime
	set WakeTime to current date
end run

on idle
	set QuitNow to false
	set WakeTime to WakeTime + CycleTime
	set WakeNow to date_format(WakeTime)
	--	set WakeNow to format date WakeTime with format "%D %T"
	do shell script "pmset schedule wake " & quoted form of WakeNow password PW with administrator privileges
	do shell script "sudo -k" -- timeout sudo ability
	repeat 25 times
		tell application "Extra Suites" to ES command down
		if result then
			set QuitNow to true
			exit repeat
		end if
		delay 1
	end repeat
	
	if QuitNow is true then
		say "all done."
		do shell script "killall 'Extra Suites'"
		quit
	else
		tell application "Finder" to sleep
	end if
	return 0.1 --IDLE does not count sleeping time! start as soon as wakeup
end idle

on date_format(user_date)
	tell ((user_date) as «class isot» as string) to return (text 6 thru 7 & "/" & text 9 thru 10 & "/" & text 3 thru 4 & space & text 12 thru -1) as Unicode text
end date_format


You might try mailing the author directly: info -at- kanzu -dot- com

Yes. Did that and also called kagi on the phone. They gave me his name (David Lloyd) and also his mac.com address. But no answer from either one. Perhaps he is no longer interested in selling it, but then kagi should take it off their sales page.

Agree with that – there’s nothing more annoying than vaporware.