I don't know if there exists something better, but I couldn't find it, and I was curious anyway, and so I wrote my own.
I need to wake my computer at 3 a.m. to run nightly backups (using Backup.app from mac.com), but if the computer is asleep, it doesn't work. IOPMSchedulePowerEvent() can wake the computer at a given time, but I had no existing Perl interface to it. I could have added it to a Mac:: module, but in this case, I didn't have the time, and I currently have no use for it other than this one script. Therefore, Inline.
One especially interesting thing about the code -- to me -- is that it uses the CFAbsoluteTime data type, which -- for reasons unknown to me -- is in seconds since January 1, 2001, GMT. So the C code keeps a constant to calculate the difference from perl's time().
use strict;
use warnings;
use Time::Local;
use Inline C => 'DATA',
LDDLFLAGS => '-bundle -flat_namespace -undefined suppress -framework Carbon',
INC => '-I/Developer/Headers/FlatCarbon';
my $now = time();
my @today = localtime($now);
@today[0, 1, 2] = (0, 55, 2);
my $then = timelocal(@today);
$then += 86400 if $now > $then;
schedule_event($then, 'wake');
__END__
__C__
#undef Move
#undef I_POLL
#undef DEBUG
#include
// "type" defines here
// can be sleep, wake, shutdown, poweron, and wakepoweron
//#include
// difference between Unix epoch and CFAbsoluteTime epoch
#define EPOCH_DIFF 978307200
long schedule_event(long seconds_time_to_wake, const char * event_name)
{
CFDateRef time_to_wake;
CFStringRef type;
IOReturn io_error;
seconds_time_to_wake -= EPOCH_DIFF;
time_to_wake = CFDateCreate(kCFAllocatorDefault, (CFAbsoluteTime)seconds_time_to_wake);
type = CFStringCreateWithCString(kCFAllocatorDefault, event_name, NULL);
io_error = IOPMSchedulePowerEvent(time_to_wake, NULL, type);
CFRelease(time_to_wake);
CFRelease(type);
if (io_error != 0) {
printf("system: 0x%x, subsystem: 0x%x, code: 0x%x\n",
err_get_system(io_error),
err_get_sub(io_error),
err_get_code(io_error)
);
}
return io_error;
}
Re:Missing something?
pudge on 2004-04-05T21:09:03
No... there's no way to tell it to wake up, only to startup, sleep, or shut down. In theory, the start up does a "wakepoweron", which should both wake and turn power on, but it doesn't work for me in practice. Go figure.
Re:You should have looked harder :)
pudge on 2004-04-27T22:35:29
Yes, I just saw that yesterday. I was going to ask you if you know why I would have something scheduled for wakeup, that sometimes it won't wake up at all.Re:You should have looked harder :)
GrayFox on 2004-04-27T22:48:38
If you look at the system log, I bet it will show the wakeup did take place, it probably went back to sleep before the task fired. I find that I have to fiddle a bit to get the wakeup close enought to task time. Cron only checks one a minute...
JerryRe:You should have looked harder :)
pudge on 2004-04-27T23:30:33
No, I had the wakeup scheduled hours before it went to sleep, then it went to sleep, and it never woke up hours later, when it was scheduled to.Re:You should have looked harder :)
GrayFox on 2004-04-28T00:11:34
This morning I had a wakeup scheduled for about 3:13:45 am
this was in my system log.
Apr 27 03:15:02 macjerry syslogd: restart
Apr 27 03:15:03 macjerry kernel: ApplePMUUserClient::setProperties AutoWake 0x00000000
Apr 27 03:15:03 macjerry kernel: ApplePMUUserClient::setProperties AutoPower 0x00000000
Apr 27 03:15:03 macjerry kernel: ApplePMUUserClient::setProperties AutoWake 0x00015123
Apr 27 03:15:03 macjerry osascript: LaunchApplication(/System/Library/CoreServices/System Events.app)
Apr 27 03:15:59 macjerry/usr/libexec/fix_prebinding: fix_prebinding quitting for now.
Apr 27 03:17:23 macjerry mDNSResponder[147]: mDNSResponder Sleeping at 567782354
Apr 27 03:17:24 macjerry kernel: ApplePMUUserClient::setProperties AutoWake 0x00015096
Apr 27 03:17:28 macjerry kernel: AppleNMI mask NMI
Apr 27 03:17:28 macjerry configd[92]: AppleTalk shutdown
Apr 27 03:17:28 macjerry configd[92]: AppleTalk shutdown complete
Apr 27 07:38:29 macjerry kernel: System Sleep
Note it went back to sleep after only four minutes even though
the Energy saver is set for 15 minutes. The autowake setting
referred to above is about 24 hours and is emplaced by my
cron job calling "dailyWakeup". Did you check the system log?
I think the Power Manager might still be a bit flakey.
My PMQueueManager shows the queue....
JerryRe:You should have looked harder :)
pudge on 2004-04-28T02:37:02
I'll get back to you hopefully tomorrow... I am setting it to wake up at 2:55 a.m. tomorrow. My cron job runs every 15 minutes to set it. [pudge@thornton pudge]$ date; pmset -g sched
Tue Apr 27 19:27:03 PDT 2004
No scheduled events.
[pudge@thornton pudge]$ date; pmset -g sched
Tue Apr 27 19:35:39 PDT 2004
Scheduled power events:
wake at 4/28/2004 2:55:00AM by wake.plxRe:You should have looked harder :)
pudge on 2004-04-28T14:41:49
The clock in the menu bar read 2:56 when I woke it up this morning at about 7:28 a.m. (I deleted log entries relating to my audio device drivers, the rest is there).Apr 28 02:55:08 localhost kernel: System Sleep
Apr 28 02:55:08 localhost kernel: System Wake
Apr 28 02:55:08 localhost kernel: Wake event 0040
Apr 28 02:55:09 localhost kernel: AppleNMI unmask NMI
Apr 28 02:55:09 localhost kernel: ^PAirPort: Link UP: "PudgeLAN" - xxxxxxx - chan 10
Apr 28 02:55:12 localhost mDNSResponder[174]: mDNSResponder Waking at 3704028
Apr 28 02:55:12 localhost kernel: ApplePMUUserClient::setProperties AutoWake 0x00000000
Apr 28 02:55:12 localhost kernel: ApplePMUUserClient::setProperties AutoPower 0x00000000
Apr 28 02:55:44 localhost/usr/libexec/fix_prebinding: fix_prebinding quitting for now.
Apr 28 02:56:57 localhost mDNSResponder[174]: mDNSResponder Sleeping at 3809175
Apr 28 02:57:01 localhost kernel: AppleNMI mask NMI
Apr 28 07:28:20 localhost kernel: ^PAirPort: Link DOWN
Apr 28 07:28:20 localhost kernel: System Sleep
Apr 28 07:28:20 localhost kernel: System Wake
I am still not convinced that this has been the problem all along; there is no system log at all for April 24 (when it should have woken up), for example. But here, man, it stayed awake for two minutes? Jeez.
Did you file a bug report yet?Re:You should have looked harder :)
GrayFox on 2004-04-28T15:02:19
Nope, I never thought about it:) I suspect each keydown, mousemotion probably sets a watchdog timer, since nothing gets moved/pressed it is not clear to me what would happen...
JerryRe:You should have looked harder :)
pudge on 2004-04-28T16:24:53
Yeah, if I get some time, I may try to see if I can't reset that timer.Re:You should have looked harder :)
GrayFox on 2004-04-28T16:30:49
Hmm,
Let's try a photosensor looking at the screen, when activated
by the wakeup, cut current to electromagnet holding weight
above keyboard, yeah that ought to do the trick:)
I have not tried (at any time) system events, do you think
simulating a key press would do the trick?
JerryRe:You should have looked harder :)
pudge on 2004-04-28T17:20:35
I dunno. My first attempt was going to be to look for the timer itself, to reset it. My next was going to be to try simulating it as you mentioned.Re:You should have looked harder :)
GrayFox on 2004-04-29T13:56:16
Got this from someone at apple...// cc -o keypress keypress.c -framework Carbon
#include
main() {
UpdateSystemActivity(OverallAct);
return 0;
}
He said it "might" work.
I got my full fifteen minutes last night...
JerryRe:You should have looked harder :)
GrayFox on 2004-04-29T13:59:26
Whoops, the include did not include...
// cc -o keypress keypress.c -framework Carbon
#include <Carbon/Carbon.h>
main() {
UpdateSystemActivity(OverallAct);
return 0;
}
JerryRe:You should have looked harder :)
pudge on 2004-04-29T21:08:19
I just added this to my perl script instead of making it a separate program, fwiw. And I tried it, and it woke the screen up after it had gone to sleep, so that's a good sign.:-) Re:You should have looked harder :)
GrayFox on 2004-04-30T16:44:53
I created 400.keypress containing:
#!/bin/sh
/usr/local/bin/keypress
and dumped it into
/etc/periodic/{daily | weekly | daily} ( and made sure it is executable )
It fired first when cron started and I got my 15 minutes of fame.
http://homepage.mac.com/Cocoa for the whole story/package
JerryRe:You should have looked harder :)
pudge on 2004-04-30T17:15:13
Last night the machine stayed awake for awhile, but then Backup.app didn't run at 3 a.m. like it was supposed to. Grrrr! Maybe I'll try waking it up earlier than 2:55 a.m.Re:You should have looked harder :)
pudge on 2004-04-29T14:33:07
This is with using it, you got your full 15? Excellent. Last night I got nothing:This time, when I woke up this morning, my clock still said 6 p.m. from the previous night.Apr 29 02:55:09 localhost kernel: AppleNMI mask NMI
Apr 29 02:55:09 localhost kernel: AirPort: Link DOWN
Apr 29 02:55:10 localhost kernel: System Sleep
Apr 29 02:55:10 localhost kernel: System Wake
Apr 29 02:55:10 localhost kernel: Wake event 0040
Apr 29 02:55:10 localhost kernel: AppleNMI unmask NMI
Apr 29 02:55:10 localhost kernel: ^PAirPort: Link UP: "PudgeLAN" - xxxxxxx - chan 10
Apr 29 02:55:13 localhost kernel: AFPSleepWakeHandler: waking up
Apr 29 02:55:13 localhost mDNSResponder[174]: mDNSResponder Waking at 9197583
Apr 29 02:55:13 localhost kernel: ApplePMUUserClient::setProperties AutoWake 0x00000000
Apr 29 02:55:13 localhost kernel: ApplePMUUserClient::setProperties AutoPower 0x00000000
Apr 29 02:57:24 localhost kernel: AFPSleepWakeHandler: going to sleep
Apr 29 02:57:24 localhost mDNSResponder[174]: mDNSResponder Sleeping at 9328729
Apr 29 02:57:28 localhost kernel: AppleNMI mask NMI
So the question I have is: how do you set it so this "keypress" happens before it goes back to sleep?
Re:You should have looked harder :)
GrayFox on 2004-04-29T14:59:20
He also told me that there was a problem if you use a password
protected screensaver, if a password is not entered in 90 seconds, the machine will go back to sleep.
JerryRe:You should have looked harder :)
pudge on 2004-04-29T15:17:08
I don't use a screen saver.
But how do I get that entered when the machine wakes up?Re:You should have looked harder :)
GrayFox on 2004-04-29T15:34:51
You can have cron execute it:) Last night I added one line
to my/etc/daily.local file. This gets executed by /etc/daily
which is in turn executed by periodic.
/usr/bin/mail -s Crontab jerry <<DOC
Cron ran at `date`
`/usr/local/bin/dailyWakeup`
`/usr/local/bin/keypress`
DOC
dailyWak eup queues a request for the following night, the
keypress code evidently extends the session.
Tonight I am going to create a 400.mystuff file that simply
executes the/usr/local/bin/keypress command and dump
it into/etc/periodic/daily. I believe that periodic will execute
the files in this directory in "ls" order.
JerryRe:You should have looked harder :)
pudge on 2004-04-29T15:53:05
Putting it in/etc/daily.local will guarantee it is run before the computer goes back to sleep? It looks to me (from looking at daily.out) that stuff from daily won't run unless the computer is awake at the time. Re:You should have looked harder :)
GrayFox on 2004-04-29T16:08:00
On my system, daily.local always fires, I guess that I don't
have that much extra to do...
However I am starting to do weekly backups of some big
folders and that is why I am going to have a seperate file
containing code that will execute the keypress function and
have periodic execute this file just before any of the longer
jobs...Are we on the same page?
dailyWakeup queues an event that causes the system to wake
a little before cron fires.
cron fires and executes a script that contains the keypress function. ( stashed in/etc/periodic/daily[weekly}{monthly})
the keypress function extends the wake time until the energy
panel limit
If more time is needed I might have to increase the time to sleep
or execute another "keypress".
JerryRe:You should have looked harder :)
pudge on 2004-04-29T16:15:30
dailyWakeup queues an event that causes the system to wake a little before cron fires.
That's the part that concerns me. Last night, the machine wasn't even awake long enough for the clock in the GUI to update. I guess I can try setting them a minute apart and see what happens.