I was hoping that the Power Status Changed Trigger would help with what I want to accomplish, but it might not, so I'd appreciate a correction if I'm wrong, or alternative ideas, if anyone has them.
I have a Thunderbolt hub attached to my Mac Book Pro. I also have the dedicated AC MagSafe power cable connected. The Thunderbolt dock is on my UPS, while the MacBook itself is not. My intention was that, if the MacBook notices that AC power has gone away, it will trigger a macro that ejects all executable disks. That way, they are cleanly ejected before the UPS runs out of power.
But there is a problem: the Thunderbolt hub provides power to the MacBook. So, it seems like the Power Status doesn't actually change. I tried connecting and disconnecting the AC power cable with Debugging turned on, and the Keyboard Maestro macro never triggered.
It's a bit tricky to even figure out whether or not the AC power cable is attached or not when the MacBook never switches (even briefly, it seems) to battery power. But, there is a shell command in which I can see a difference between whether or not the AC power cable is attached: ioreg -r -n AppleSmartBattery -w0
In the plist-formatted result, the value for AppleRawAdapterDetails has the difference. With the AC power cable attached, it includes more details, including: "Description"="pd charger"
So, right now, I'm thinking the only way I can accomplish what I want is to have a macro that runs every X seconds checking for that. And, as I've seen elsewhere here in the forums, I'd probably want to set up some top-level "every X seconds" macro that activates this monitor macro, so that a Cancel All Macros won't kill this.
Is there any other way I can do this with an actual trigger, rather than a polling macro? As you would think, the AC power cable does not show up as a USB device, but is there a KM trigger I'm missing?
That's interesting. It might help, although my UPS is set up in a fairly simple way. Also, I was hoping that I could have this macro work for the situation where I want to grab my MacBook to take it somewhere else. So, I could just unplug the power cord, and then wait a few seconds while the KM macro ejects all the disks, then disconnect the Thunderbolt hub and carry the MacBook away.
I might be better off giving myself a manually-triggered macro for that scenario.
What about the other direction? Does anything on the Thunderbolt hub show up as a USB device when it's connected? If so, you could trigger on that device being removed.
Yes, but the Thunderbolt dock's status won't change as a trigger event. So, for example, the drives I want to have the macro eject all show, but their status won't change before the macro runs.
...may be enough. Test with the dialogs, then replace the first with your eject routine and delete the second.
I'd still go with a manually-triggered macro for when you grab-and-go. If your external disks have data of any value on them you should be checking they are unmounted before pulling the plug, not trusting to luck -- and since you'll be there checking, you might as well be there firing...
I think you're right. I'll have the manual macro for grab-and-go.
The other periodic macro will work like you say, although I realized I needed to a "was it connected before" test. Otherwise, I wouldn't be able to connect any external disks while on battery power.
So, there are two macros. One is the macro that actually does the ejecting, which can be called manually. The other is the periodic-trigger macro, which calls the Eject macro IF: the AC power cable is now disconnected, but was connected the last time it checked. Once the AC power cable is reconnected, that resets the "was it previously?" variable, so the periodic check can eject again.
This does have the downside of cluttering up the macros debugger.
I guess an alternative would be to have some other process regularly running that shell script, and that process calls the KM macro. Eject External Volumes.kmmacros (18.9 KB)
You don't need two, although two may be more convenient. Macros can have multiple triggers, and you can test which trigger caused a particular instance to execute.
So... There's 4 combos here:
If triggered manually -- eject the disks
Periodic trigger: If MagSafe is not connected, but was on the last check -- eject the disks
Periodic trigger: If MagSafe is not connected and wasn't on the last check -- do nothing
Periodic trigger: If MagSafe is connected -- do nothing
...and, as you mentioned, you need to track the "last checked" MagSafe connection status.
So something like this -- completely untested, as I'm on a desktop Mac, so tread carefully! I'm assuming your scripts are correct (though I did correct the AppleScript):
Edit: Fixed mistaken use of %TriggerValue% -- it should be %TriggerBase%
The ioreg script is so fast and light-weight and will be needed for 99.99% of executions anyway, so it probably costs more to not run it when the macro is manually executed than to run it every time
I've included a semaphore lock so you don't get the problem of multiple instances being run via the periodic trigger while the first instance's AS is trying to unmount the volumes...
That all makes sense. I like merging them into a single macro.
I didn't know about the Semaphore Lock command - that looks good, too.
I tweaked the AppleScript so that it only does the attempt to eject and delay 20 if there are ejectable disks.
But, the strange thing I'm running into is that when it is triggered by Periodic Trigger, it looks like that does not get set into %TriggerValue%.
The conditional %TriggerValue% is not Periodic Trigger is thus always true, so the While loop always happens.
I checked this by adding a Display Text %TriggerValue% at the start of the macro. When triggered by the 5-second period, that display is empty, while when I trigger it by hotkey, I see โโฅโงโE.