Module: StateMate::Adapters::PMSet

Includes:
StateMate::Adapters
Defined in:
lib/state_mate/adapters/pmset.rb

Constant Summary collapse

MODES =

whitelist of modes we handle mapped to their pmset flag

there is also a UPS mode, but i don't know what it looks like

{
  'Battery Power' => 'b',
  'AC Power' => 'c',
}
SETTINGS =

a whitelist of settings to parse, since the output of pmset -g custom can include lines like

Sleep On Power Button 1

which makes it hard to parse in general (spaces in key name and between key name and value).

from

[
  # display sleep timer; replaces 'dim' argument in 10.4 (value in minutes,
  # or 0 to disable)
  'displaysleep',
  
  # disk spindown timer; replaces 'spindown' argument in 10.4 (value in 
  # minutes, or 0 to dis-able)
  'disksleep',
  
  # system sleep timer (value in minutes, or 0 to disable)
  'sleep',
  
  # wake on ethernet magic packet (value = 0/1)
  'womp',
  
  # wake on modem ring (value = 0/1)
  'ring',
  
  # automatic restart on power loss (value = 0/1)
  'autorestart',
  
  # wake the machine when the laptop lid (or clamshell) is opened
  # (value = 0/1)
  'lidwake',
  
  # wake the machine when power source (AC/battery) is changed (value = 0/1)
  'acwake',
  
  # slightly turn down display brightness when switching to this power source
  # (value = 0/1)
  'lessbright',
  
  # display sleep will use an intermediate half-brightness state between full 
  # brightness and fully off  (value = 0/1)
  'halfdim',
  
  # use Sudden Motion Sensor to park disk heads on sudden changes in G force
  # (value = 0/1)
  'sms',
  
   # change hibernation mode. Please use caution. (value = integer)
  'hibernatemode',
  
  # change hibernation image file location. Image may only be located on the 
  # root volume. Please use caution. (value = path)
  'hibernatefile',
  
  # prevent idle system sleep when any tty (e.g. remote login session) is 
  # 'active'. A tty is 'inactive' only when its idle time exceeds the system 
  # sleep timer. (value = 0/1)
  'ttyskeepawake',          
  
  # this setting affects how OS X networking presents shared network services 
  # during system sleep. This setting is not used by all platforms; changing 
  # its value is unsupported.
  # 
  # ...so we won't support it
  # 'networkoversleep',
  
  # Destroy File Vault Key when going to standby mode. By default File vault
  # keys are retained even when system goes to standby. If the keys are
  # destroyed, user will be prompted to enter the password while coming out
  # of standby mode.(value: 1 - Destroy, 0 - Retain)
  'destroyfvkeyonstandby',
  
  # Where supported, enabled per default as an implementation of Lot 6 to the 
  # European Energy-related Products Directive. After sleeping for 
  # <autopoweroffdelay> minutes, the system will write a hibernation image 
  # and go into a lower power chipset sleep. Wakeups from this state will take
  # longer than wakeups from regular sleep. The system will not auto power
  # off if any external devices are connected, if the system is on battery 
  # power, or if the system is bound to a network and wake for net-work
  # network work access is enabled.
  'autopoweroff',
  
  # delay before entering autopoweroff mode. (Value = integer, in minutes)
  'autopoweroffdelay',
  
  # STANDBY ARGUMENTS
  
  # standby causes kernel power management to automatically hibernate a
  # machine after it has slept for a specified time period. This saves power
  # while asleep. This setting defaults to ON for supported hardware.
  # The setting standby will be visible in pmset -g if the feature is 
  # supported on this machine.
  # 
  # only works if hibernation is turned on to hibernatemode 3 or 25.
  'standby', 
  
  # specifies the delay, in seconds, before writing the hibernation image
  # to disk and powering off memory for Standby.
  'standbydelay',
  
  # UNDOCUMENTED ARGUMENTS
  
  # the "Power Nap" feature..?
  # 
  # http://apple.stackexchange.com/questions/116348/how-can-i-enable-and-or-disable-os-xs-power-nap-feature-from-within-terminal
  # 
  'darkwakes',
  
  # unknown
  # 'gpuswitch',
  
  # shows up on my imac. not even sure you can set it with pmset, so ignoring
  # for now
  # 'Sleep On Power Button',
]
MODE_RE =

regexp to pick the mode headers out of pmset -g custom output

/^(#{ MODES.keys.map {|_| Regexp.escape _ }.join('|') })\:$/
SETTING_RE =

regexp to pick the settings and values out of other lines of pmset -g custom

/^\s(#{ SETTINGS.map {|_| Regexp.escape _ }.join '|' })\s+(.*)$/

Constants included from StateMate::Adapters

API_METHOD_NAMES, DEFAULT_KEY_SEP

Class Method Summary collapse

Methods included from StateMate::Adapters

get, included, register

Class Method Details

.parse(input) ⇒ Hash<String, Hash<String, String>>

pure

parse the output of pmset -g custom.

since keys can apparently have spaces in them (like "Sleep On Power Button") and are seperated by spaces, it uses the SETTINGS whitelist.

settings are saved at

/Library/Preferences/SystemConfiguration/com.apple.PowerManagement.plist

which might be a possible site for reading and writing, but seems safer to use pmset, and should satify needs for now.

Parameters:

  • input (String)

    output of pmset -g custom. on my mbp it looks like

    Battery Power:
      lidwake              1
      autopoweroff         1
      autopoweroffdelay    14400
      standbydelay         10800
      standby              1
      ttyskeepawake        1
      hibernatemode        3
      darkwakes            0
      gpuswitch            2
      hibernatefile        /var/vm/sleepimage
      displaysleep         5
      sleep                5
      acwake               0
      halfdim              1
      lessbright           0
      disksleep            10
    AC Power:
      lidwake              1
      autopoweroff         0
      autopoweroffdelay    0
      standbydelay         0
      standby              0
      ttyskeepawake        1
      hibernatemode        3
      darkwakes            1
      gpuswitch            0
      hibernatefile        /var/vm/sleepimage
      womp                 0
      displaysleep         5
      networkoversleep     0
      sleep                10
      acwake               0
      halfdim              1
      disksleep            10
    

Returns:

  • (Hash<String, Hash<String, String>>)

    hash of section titles (like "Battery Power") to hashes of string keys to sting values (does not turn numeric strings into integers).



210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/state_mate/adapters/pmset.rb', line 210

def self.parse input
  sections = {}
  section = {}
  
  input.lines.each do |line|
    if m = line.match(MODE_RE)
      section = {}
      sections[m[1]] = section
    else
      if m = line.match(SETTING_RE)
        section[m[1]] = m[2]
      end
    end
  end
  sections
end

.read(key, options = {}) ⇒ Hash<String, Hash<String, String>>, ...

reads pm settings.

Parameters:

  • key (Array<String>)

    key path to read:

    • [] gets everything, returning a hash {<mode> => {<setting> => <value>}}.

      PMSet.read [] looks something like:

      {"Battery Power"=>
        {"lidwake"=>"1",
         "autopoweroff"=>"1",
         ...},
       "AC Power"=>
        {"lidwake"=>"1",
         "autopoweroff"=>"1",
         ...}}
      
    • [<mode>] gets a hash of {<setting> => <value>} for that mode.

      PMSet.read ["AC Power"] looks something like:

      {"lidwake"=>"1",
       "autopoweroff"=>"1",
       ...}
      
    • [<mode>, <setting>] gets a string value.

      PMSet.read ["AC Power", "lidwake"] looks something like "1"

    in addition

    • <mode> must be in the keys of MODES
    • <setting> must be in SETTINGS

Returns:

  • (Hash<String, Hash<String, String>>)

    hash of everything when key is []

  • (Hash<String, String>)

    hash of values for mode when key is [<mode>]

  • (String)

    value when key is [<mode>, <setting>]

Raises:

  • (ArgumentError)

    if the key is not found.



271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
# File 'lib/state_mate/adapters/pmset.rb', line 271

def self.read key, options = {}
  # read all the settings.
  settings = parse Cmds.out!('pmset -g custom')
  
  value = settings
  key.each do |seg|
    unless value.key? seg
      raise ArgumentError.new binding.erb "        bad segment \#{ seg.inspect } in key \#{ key }.\n        \n        pm settings:\n        \n        <%= settings.pretty_inspect %>\n      END\n    end\n    value = value[seg]\n  end\n  \n  value\nend\n"

.write(key, value, options = {}) ⇒ Object

writes pm settings.

Parameters:

  • key (Array<String>)

    must be a two-element array of strings where the first element is a key of MODES and the second is in SETTINGS.

  • value (String)

    value to write.

Returns:

  • nil

Raises:

  • (ArgumentError)

    if key is bad.



304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
# File 'lib/state_mate/adapters/pmset.rb', line 304

def self.write key, value, options = {}
  unless key.is_a?(Array) && key.length == 2
    raise ArgumentError.new binding.erb "      key must be a pair [mode, setting], not <%= key.inspect %>.\n    END\n  end\n  \n  mode, setting = key\n  \n  if MODES[mode].nil?\n    raise ArgumentError.new binding.erb <<-END\n      first key element must be one of\n      \n      <%= MODES.keys.pretty_inspect %>\n      \n      found <%= mode.inspect %>\n    END\n  end\n  \n  unless SETTINGS.include? setting\n    raise ArgumentError.new binding.erb <<-END\n      second key element must be one of\n      \n      <%= SETTINGS.pretty_inspect %>\n      \n      found <%= setting.inspect %>\n    END\n  end\n  \n  Cmds! \"sudo pmset -\#{ MODES[mode] } %{setting} %{value}\",\n    setting: setting,\n    value: value\n  \n  nil\nend\n"