Skip to content

Commit

Permalink
feat(linux): add sensors for tracking shutdown/suspend state via D-Bus
Browse files Browse the repository at this point in the history
  • Loading branch information
joshuar committed Nov 6, 2023
1 parent 7f7e01b commit cbcb8b5
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 3 deletions.
3 changes: 2 additions & 1 deletion internal/agent/device_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ func sensorWorkers() []func(context.Context, device.SensorTracker) {
linux.ScreenLockUpdater,
linux.UsersUpdater,
linux.Versions,
linux.TempUpdater)
linux.TempUpdater,
linux.PowerMgmtUpdater)
return workers
}
87 changes: 87 additions & 0 deletions internal/linux/powerMgmtSensor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// Copyright (c) 2023 Joshua Rich <[email protected]>
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT

package linux

import (
"context"

"github.com/godbus/dbus/v5"
"github.com/joshuar/go-hass-agent/internal/device"
"github.com/joshuar/go-hass-agent/internal/hass/sensor"
"github.com/rs/zerolog/log"
)

type powerMgmtSensor struct {
linuxSensor
}

func (s *powerMgmtSensor) SensorType() sensor.SensorType {
return sensor.TypeBinary
}

func (s *powerMgmtSensor) Icon() string {
if isTrue, ok := s.value.(bool); ok && isTrue {
switch s.sensorType {
case isSuspended:
return "mdi:power-sleep"
case isShutdown:
return "mdi:power-off"
}
}
return "mdi:power-on"
}

func PowerMgmtUpdater(ctx context.Context, tracker device.SensorTracker) {
r := NewBusRequest(ctx, SystemBus).
Path("/org/freedesktop/login1").
Match([]dbus.MatchOption{
dbus.WithMatchInterface("org.freedesktop.login1.Manager"),
})

err := NewBusRequest(ctx, SystemBus).
Path("/org/freedesktop/login1").
Match([]dbus.MatchOption{
dbus.WithMatchInterface("org.freedesktop.login1.Manager"),
}).Event("org.freedesktop.login1.Manager.PrepareForSleep").
Handler(func(s *dbus.Signal) {
if s.Name != "org.freedesktop.login1.Manager.PrepareForSleep" {
return
}
if err := tracker.UpdateSensors(ctx, newPowerMgmtSensor(isSuspended, s.Body[0].(bool))); err != nil {
log.Error().Err(err).Msg("Could not update suspended sensor.")
}
}).
AddWatch(ctx)
if err != nil {
log.Warn().Err(err).
Msg("Failed to create user D-Bus watch. Will not track suspend state.")
}
err = r.Event("org.freedesktop.login1.Manager.PrepareForShutdown").
Handler(func(s *dbus.Signal) {
if s.Name != "org.freedesktop.login1.Manager.PrepareForShutdown" {
return
}
if err = tracker.UpdateSensors(ctx, newPowerMgmtSensor(isShutdown, s.Body[0].(bool))); err != nil {
log.Error().Err(err).Msg("Could not update powered off sensor.")
}
}).
AddWatch(ctx)
if err != nil {
log.Warn().Err(err).
Msg("Failed to create user D-Bus watch. Will not track powered off state.")
}
}

func newPowerMgmtSensor(t sensorType, v interface{}) *powerMgmtSensor {
return &powerMgmtSensor{
linuxSensor: linuxSensor{
value: v,
sensorType: t,
source: srcDbus,
diagnostic: true,
},
}
}
2 changes: 2 additions & 0 deletions internal/linux/sensorType.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ const (
version // Distribution Version
users // Current Users
deviceTemp // Temperature
isSuspended // Suspended
isShutdown // Powered Off
)

// sensorType represents the unique type of sensor data being reported. Every
Expand Down
6 changes: 4 additions & 2 deletions internal/linux/sensorTypeStrings.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit cbcb8b5

Please sign in to comment.