wall < "openHAB: Put Mac to sleep"

Broadcast message from spillerm@unixe.de (pts/1) (Fr Feb 27 13:54:10 2015):
4
Diesen Beitrag schrieb ich vor 4 Jahren. Behalte das beim Lesen bitte im Hinterkopf.

Einige von euch kennen das Problem sicherlich auch: du hast dich gerade gemütlich ins Bett gelegt (oder auch das Haus verlassen), und dann fällt dir ein, dass du den Rechner nicht in den Sleep-Mode geschickt hast. Man hat diverse Möglichkeiten:

  • Aufstehen bzw. umkehren. Die unattraktivste Option, das steht ausser Frage.
  • Sich per SSH einloggen und die Kiste schlafen schicken; das erfordert aber, dass auf dem Rechner der SSH-Port offen und der Rechner — gegebenenfalls auch von aussen — erreichbar ist. Das ist nicht in jeder Umgebung gewünscht beziehungsweise möglich.
  • Mail.app missbrauchen. In den Mail-Filtern von Mail.app kann man sich eine Regel definieren, die beim Eintreffen einer Mail mit spezifischem Subject, beispielsweise »Put me to sleep, darling«, ein AppleScript ausführt, das den Rechner in den Sleep-Mode versetzt. Erfordert lediglich ein laufendes Mail.app, das in regelmässigen Abständen Mails checkt. Da ich inzwischen aber auf allen Maschinen auf mutt umgestiegen bin (vgl. hier und hier), kam auch das für mich nicht in Frage.
  • Es gibt lustige Ansätze mit Hazel, Dropbox und AppleScript — fragt mal Google, ich hab diesen Weg nicht getestet.
  • Und wenn sowieso schon ein openHAB läuft, kann man auch dieses zu dem Zweck heranziehen.

Um diesen Weg zu gehen, sind sowohl exec binding als auch network health binding in addons/ benötigt. Für die Demo lege ich eine eigene rechner.itemsGITHUB nach configurations/items.

Group:Switch:OR(ON, OFF)        Rechner                         "Rechner [(%d)]"                <network>               (All)
Switch  Petzi   "Petzi (MacPro)"        (Rechner)       { nh="petzi", exec="OFF:ssh spillerm@petzi osascript -e 'tell application \"System Events\" to sleep'" }
Switch  Pingo   "Pingo (iMac)"          (Rechner)       { nh="pingo", exec="OFF:ssh mane@pingo osascript -e 'tell application \"System Events\" to sleep'" }

Sleep Mode - RechnerWas passiert hier? Ich definiere mir eine Gruppe namens »Rechner«, die in meiner Sitemap angezeigt werden soll. In der Übersicht wird die Anzahl der aktiven Hosts angezeigt werden ([(%d)]), mit einem möglichst passenden Symbol (<network>). Meine Gruppe hat derzeit zwei Items (Switch Petzi und Switch Pingo), deren Netzwerkstatus in regelmässigen Abständen geprüft wird (nh="hostname"). Meine Rechner haben jeweils eine feste IP, und hier läuft ein interner bind, der für die Namensauflösung zuständig ist. Alternativ könnte man die Hosts auf der openHAB-Schüssel in die /etc/hosts eintragen beziehungsweise IP-Adressen in der openHAB-Konfiguration verwenden.

Für die Demo bauen wir uns dann noch eine rechner.sitemapGITHUB und legen diese nach configurations/sitemaps. Aufrufen können wir das Ganze nun per http://$SERVERNAME:8080/openhab.app?sitemap=rechner. Reagiert der Host auf die nh-Überprüfung, springt der Switch auf ON:

12:01:31.826 [DEBUG] [o.o.b.n.i.NetworkHealthBinding:75   ] - established connection [host 'pingo' port '0' timeout '5000']
12:01:31.848 [INFO ] [runtime.busevents             :26   ] - Pingo state updated to OFF
12:02:34.871 [DEBUG] [o.o.b.n.i.NetworkHealthBinding:75   ] - established connection [host 'petzi' port '0' timeout '5000']
12:02:34.915 [INFO ] [runtime.busevents             :26   ] - Petzi state updated to ON

Setzt man den Switch Petzi nun im Webinterface auf OFF, so wird das hinterlegte Kommando ausgeführt:

ssh spillerm@petzi osascript -e 'tell application \"System Events\" to sleep'

Erforderlich ist hierzu, dass sich der User spillerm auf petzi einloggen darf, ohne ein Passwort eingeben zu müssen — ich habe den passenden SSH-Key hinterlegt. Nun kann ich, egal wo ich bin, meinen Rechner einschlafen lassen. Aufwecken wäre sicherlich auch möglich, aber damit habe ich mich nicht weiter beschäftigt, da ich das nicht möchte — die Rechner müssten auf Wake on LAN konfiguriert werden, und das verursacht hier üblicherweise Stress.

Gerade der Pro zickt ganz gerne mal und will partout nicht schlafen; zur Eingrenzung, was da gerade quersteckt, ist das folgende Kommando recht hilfreich:

$ pmset -g assertions
27/02/15 12:50:21 GMT+1
Assertion status system-wide:
   BackgroundTask                 0
   PreventDiskIdle                0
   ApplePushServiceTask           0
   UserIsActive                   1
   PreventUserIdleDisplaySleep    1
   InteractivePushServiceTask     0
   PreventSystemSleep             0
   ExternalMedia                  1
   PreventUserIdleSystemSleep     1
   NetworkClientActive            0
Listed by owning process:
   pid 16(powerd): [0x000000090000012e] 04:28:33 ExternalMedia named: "com.apple.powermanagement.externalmediamounted"
   pid 208(coreaudiod): [0x000000010000033e] 01:17:27 NoIdleSleepAssertion named: "com.apple.audio.'AppleHDAEngineOutput:1B,0,1,2:0'.noidlesleep"
   pid 86(hidd): [0x0000000a0000033c] 01:17:29 UserIsActive named: "com.apple.iohideventsystem.queue.tickle"
	Timeout will fire in 1143 secs Action=TimeoutActionRelease
   pid 291(iTunes): [0x000000010000033f] 01:17:27 PreventUserIdleSystemSleep named: "com.apple.iTunes.playback"
   pid 291(iTunes): [0x000000050000033d] 01:17:27 PreventUserIdleDisplaySleep named: "Nameless (via IOPMAssertionCreate)"
Kernel Assertions: 0xc=USB,BT-HID
   id=500  level=255 0x4=USB mod=27/02/15 08:25 description=EHCI owner=AppleUSBEHCI
   id=503  level=255 0x4=USB mod=27/02/15 08:37 description=UHC3 owner=AppleUSBUHCI
   id=505  level=255 0x8=BT-HID mod=01/01/70 01:00 description=com.apple.driver.IOBluetoothHIDDriver owner=BNBMouseDevice
   id=506  level=255 0x8=BT-HID mod=01/01/70 01:00 description=com.apple.driver.IOBluetoothHIDDriver owner=BNBTrackpadDevice

UnterschriftUnd damit verabschiede ich mich ins Wochenende und wünsche euch eine tolle Zeit :)

4