csminer/osx/csminer.go
2020-08-20 20:42:42 -07:00

114 lines
2.9 KiB
Go

// Copyright 2020 cryptonote.social. All rights reserved. Use of this source code is governed by
// the license found in the LICENSE file.
package main
// main() for the osx version of csminer with OSX lock screen & battery state polling.
import (
"context"
"github.com/cryptonote-social/csminer"
"github.com/cryptonote-social/csminer/crylog"
"os/exec"
"strings"
"time"
)
type OSXMachineStater struct {
}
// The OSX implementation of the screen & batter state notification channel is based on polling the
// state every 10 seconds. It would be better to figure out how to get notified of state changes
// when they happen.
func (s OSXMachineStater) GetMachineStateChannel(saver bool) (chan csminer.MachineState, error) {
ret := make(chan csminer.MachineState)
go func() {
screenActive := true
batteryPower := false
for {
time.Sleep(time.Second * 5)
if saver {
screenActiveNow, err := getScreenActiveState()
if err != nil {
crylog.Error("getScreenActiveState failed:", err)
continue
}
if screenActiveNow != screenActive {
screenActive = screenActiveNow
if screenActive {
ret <- csminer.MachineState(csminer.SCREEN_ACTIVE)
} else {
ret <- csminer.MachineState(csminer.SCREEN_IDLE)
}
}
}
time.Sleep(time.Second * 5)
batteryPowerNow, err := getBatteryPowerState()
if err != nil {
crylog.Error("getBatteryPowerState failed:", err)
continue
}
if batteryPower != batteryPowerNow {
batteryPower = batteryPowerNow
if batteryPower {
ret <- csminer.MachineState(csminer.BATTERY_POWER)
} else {
ret <- csminer.MachineState(csminer.AC_POWER)
}
}
}
}()
return ret, nil
}
// getScreenActiveState gets the OSX lockscreen status. Current implementation
// invokes a python script; this should be improved.
func getScreenActiveState() (bool, error) {
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()
cmd := exec.CommandContext(
ctx,
"python",
"-c",
"import sys,Quartz; d=Quartz.CGSessionCopyCurrentDictionary(); print d",
)
b, err := cmd.CombinedOutput()
if err != nil {
crylog.Error("Error in cmd.CombinedOutput:", err)
return false, err
}
if strings.Contains(string(b), "CGSSessionScreenIsLocked = 1") {
return false, nil
}
return true, nil
}
// getBatteryPowerState returns true if the machine is running on battery power.
// Current implementation invokes "pmset -g ps"
func getBatteryPowerState() (bool, error) {
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()
cmd := exec.CommandContext(
ctx,
"pmset",
"-g",
"ps",
)
b, err := cmd.CombinedOutput()
if err != nil {
crylog.Error("Error in cmd.CombinedOutput:", err)
return false, err
}
if strings.Contains(string(b), "Battery Power") {
return true, nil
}
return false, nil
}
func main() {
csminer.MultiMain(OSXMachineStater{}, "csminer "+csminer.VERSION_STRING+" (osx)")
}