mirror of
https://github.com/cryptonote-social/csminer.git
synced 2024-09-11 05:35:23 +03:00
initial work for handling battery power detection + pausing
This commit is contained in:
parent
562af18129
commit
5de524a8a8
@ -18,7 +18,7 @@ func main() {
|
||||
type GnomeScreenStater struct {
|
||||
}
|
||||
|
||||
func (s GnomeScreenStater) GetScreenStateChannel() (chan bool, error) {
|
||||
func (s GnomeScreenStater) GetScreenStateChannel() (chan csminer.ScreenState, error) {
|
||||
bus, err := dbus.ConnectSessionBus()
|
||||
if err != nil {
|
||||
crylog.Fatal("dbus connection failed")
|
||||
@ -34,7 +34,7 @@ func (s GnomeScreenStater) GetScreenStateChannel() (chan bool, error) {
|
||||
dChan := make(chan *dbus.Message, 128)
|
||||
bus.Eavesdrop(dChan)
|
||||
|
||||
ret := make(chan bool)
|
||||
ret := make(chan csminer.ScreenState)
|
||||
|
||||
go func() {
|
||||
defer bus.Close()
|
||||
@ -47,11 +47,11 @@ func (s GnomeScreenStater) GetScreenStateChannel() (chan bool, error) {
|
||||
str := fmt.Sprintf("%v", m.Body[0])
|
||||
if str == "true" {
|
||||
crylog.Info("Gnome screensaver turned on")
|
||||
ret <- true
|
||||
ret <- csminer.ScreenState(csminer.SCREEN_ACTIVE)
|
||||
continue
|
||||
} else if str == "false" {
|
||||
crylog.Info("Gnome screensaver turned off")
|
||||
ret <- false
|
||||
ret <- csminer.ScreenState(csminer.SCREEN_IDLE)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
51
miner.go
51
miner.go
@ -35,23 +35,34 @@ var (
|
||||
lastStatsUpdateTime time.Time
|
||||
|
||||
screenIdle int32 // only mine when this is > 0
|
||||
batteryPower int32
|
||||
manualMinerToggle int32
|
||||
|
||||
SCREEN_IDLE_POKE client.MultiClientJob
|
||||
SCREEN_ON_POKE client.MultiClientJob
|
||||
PRINT_STATS_POKE client.MultiClientJob
|
||||
ENTER_HIT_POKE client.MultiClientJob
|
||||
SCREEN_IDLE_POKE client.MultiClientJob
|
||||
SCREEN_ON_POKE client.MultiClientJob
|
||||
BATTERY_POWER_POKE client.MultiClientJob
|
||||
AC_POWER_POKE client.MultiClientJob
|
||||
PRINT_STATS_POKE client.MultiClientJob
|
||||
ENTER_HIT_POKE client.MultiClientJob
|
||||
)
|
||||
|
||||
const (
|
||||
HANDLED = 1
|
||||
USE_CACHED = 2
|
||||
|
||||
// Valid screen states
|
||||
SCREEN_IDLE = 0
|
||||
SCREEN_ACTIVE = 1
|
||||
BATTERY_POWER = 2
|
||||
AC_POWER = 3
|
||||
)
|
||||
|
||||
type ScreenState int
|
||||
|
||||
type ScreenStater interface {
|
||||
// Returns a channel that produces true when state changes from screen off to screen on,
|
||||
// and false when it changes from on to off.
|
||||
GetScreenStateChannel() (chan bool, error)
|
||||
GetScreenStateChannel() (chan ScreenState, error)
|
||||
}
|
||||
|
||||
func Mine(s ScreenStater, threads int, uname, rigid string, saver bool, excludeHrStart int, excludeHrEnd int, startDiff int, useTLS bool) error {
|
||||
@ -65,6 +76,8 @@ func Mine(s ScreenStater, threads int, uname, rigid string, saver bool, excludeH
|
||||
seed := []byte{}
|
||||
|
||||
screenIdle = 1
|
||||
batteryPower = 0
|
||||
|
||||
manualMinerToggle = 0
|
||||
if saver {
|
||||
ch, err := s.GetScreenStateChannel()
|
||||
@ -295,14 +308,21 @@ func startKeyboardScanning() {
|
||||
}()
|
||||
}
|
||||
|
||||
func monitorScreenSaver(ch chan bool) {
|
||||
func monitorScreenSaver(ch chan ScreenState) {
|
||||
for state := range ch {
|
||||
if state {
|
||||
switch state {
|
||||
case SCREEN_IDLE:
|
||||
crylog.Info("Screen off")
|
||||
kickJobDispatcher(&SCREEN_IDLE_POKE)
|
||||
} else {
|
||||
case SCREEN_ACTIVE:
|
||||
crylog.Info("Screen on")
|
||||
kickJobDispatcher(&SCREEN_ON_POKE)
|
||||
case BATTERY_POWER:
|
||||
crylog.Info("Battery power")
|
||||
kickJobDispatcher(&BATTERY_POWER_POKE)
|
||||
case AC_POWER:
|
||||
crylog.Info("AC power")
|
||||
kickJobDispatcher(&AC_POWER_POKE)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -320,6 +340,9 @@ func kickJobDispatcher(job *client.MultiClientJob) bool {
|
||||
}
|
||||
|
||||
func miningActive(excludeHrStart, excludeHrEnd int) bool {
|
||||
if atomic.LoadInt32(&batteryPower) > 0 {
|
||||
return false
|
||||
}
|
||||
if atomic.LoadInt32(&manualMinerToggle) > 0 {
|
||||
// keyboard override to always mine no matter what
|
||||
return true
|
||||
@ -336,10 +359,16 @@ func miningActive(excludeHrStart, excludeHrEnd int) bool {
|
||||
}
|
||||
|
||||
func getActivityMessage(excludeHrStart, excludeHrEnd, threads int) string {
|
||||
battery := atomic.LoadInt32(&batteryPower) > 0
|
||||
if battery {
|
||||
return "PAUSED due to running on battery power"
|
||||
}
|
||||
|
||||
saver := atomic.LoadInt32(&screenIdle) > 0
|
||||
toggled := atomic.LoadInt32(&manualMinerToggle) > 0
|
||||
|
||||
onoff := ""
|
||||
|
||||
if timeExcluded(excludeHrStart, excludeHrEnd) {
|
||||
if !toggled {
|
||||
onoff = "PAUSED due to -exclude hour range. <enter> to mine anyway"
|
||||
@ -360,7 +389,11 @@ func getActivityMessage(excludeHrStart, excludeHrEnd, threads int) string {
|
||||
|
||||
func handlePoke(wasMining bool, job *client.MultiClientJob, excludeHrStart, excludeHrEnd int) int {
|
||||
var isMiningNow bool
|
||||
if job == &SCREEN_ON_POKE {
|
||||
if job == &BATTERY_POWER_POKE {
|
||||
atomic.StoreInt32(&batteryPower, 1)
|
||||
} else if job == &AC_POWER_POKE {
|
||||
atomic.StoreInt32(&batteryPower, 0)
|
||||
} else if job == &SCREEN_ON_POKE {
|
||||
atomic.StoreInt32(&screenIdle, 0) // mark the screen as no longer idle
|
||||
} else if job == &SCREEN_IDLE_POKE {
|
||||
atomic.StoreInt32(&screenIdle, 1) // mark screen as idle
|
||||
|
@ -7,8 +7,8 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/cryptonote-social/csminer/crylog"
|
||||
"github.com/cryptonote-social/csminer"
|
||||
"github.com/cryptonote-social/csminer/crylog"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
@ -20,15 +20,14 @@ type OSXScreenStater struct {
|
||||
// The OSX implementation of the screen 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 OSXScreenStater) GetScreenStateChannel() (chan bool, error) {
|
||||
ret := make(chan bool)
|
||||
func (s OSXScreenStater) GetScreenStateChannel() (chan csminer.ScreenState, error) {
|
||||
ret := make(chan csminer.ScreenState)
|
||||
|
||||
go func() {
|
||||
// We assume the screen is active when the miner is started. This may
|
||||
// not hold if someone is running the miner from an auto-start script?
|
||||
screenActive := true
|
||||
batteryPower := false
|
||||
for {
|
||||
time.Sleep(time.Second * 10)
|
||||
time.Sleep(time.Second * 5)
|
||||
screenActiveNow, err := getScreenActiveState()
|
||||
if err != nil {
|
||||
crylog.Error("getScreenActiveState failed:", err)
|
||||
@ -36,7 +35,25 @@ func (s OSXScreenStater) GetScreenStateChannel() (chan bool, error) {
|
||||
}
|
||||
if screenActiveNow != screenActive {
|
||||
screenActive = screenActiveNow
|
||||
ret <- !screenActive
|
||||
if screenActive {
|
||||
ret <- csminer.ScreenState(SCREEN_ACTIVE)
|
||||
} else {
|
||||
ret <- csminer.ScreenState(SCREEN_IDLE)
|
||||
}
|
||||
}
|
||||
time.Sleep(time.Second * 5)
|
||||
batteryPowerNow, err := getBatteryPowerState()
|
||||
if err != nil {
|
||||
crylog.Error("getBatteryPowerState failed:", err)
|
||||
continue
|
||||
}
|
||||
if batteryPower != batteryPowerNow {
|
||||
batteryPoser = batterPowerNow
|
||||
if batteryPower {
|
||||
ret <- csminer.ScreenState(BATTERY_POWER)
|
||||
} else {
|
||||
ret <- csminer.ScreenState(AC_POWER)
|
||||
}
|
||||
}
|
||||
}
|
||||
}()
|
||||
@ -67,6 +84,29 @@ func getScreenActiveState() (bool, error) {
|
||||
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(), 10*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") {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
csminer.MultiMain(OSXScreenStater{})
|
||||
}
|
||||
|
@ -13,7 +13,11 @@ import (
|
||||
type WinScreenStater struct {
|
||||
}
|
||||
|
||||
func (s WinScreenStater) GetScreenStateChannel() (chan bool, error) {
|
||||
// We assume the screen is active when the miner is started. This may
|
||||
// not hold if someone is running the miner from an auto-start script?
|
||||
// TODO: On startup check if someone is logged in and if not assume screen
|
||||
// is locked.
|
||||
func GetScreenStateChannel() (chan bool, error) {
|
||||
ret := make(chan bool)
|
||||
|
||||
chanMessages := make(chan session_notifications.Message, 100)
|
||||
|
Loading…
Reference in New Issue
Block a user