joshuar-go-hass-agent/internal/linux/context.go

136 lines
3.7 KiB
Go

// Copyright (c) 2024 Joshua Rich <joshua.rich@gmail.com>
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
package linux
import (
"context"
"errors"
"log/slog"
"time"
"github.com/tklauser/go-sysconf"
"github.com/joshuar/go-hass-agent/pkg/linux/dbusx"
)
type contextKey string
const (
dbusSessionContextKey contextKey = "sessionBus"
dbusSystemContextKey contextKey = "systemBus"
clktckContextKey contextKey = "clktck"
boottimeContextKey contextKey = "boottime"
sessionPathContextKey contextKey = "sessionPath"
desktopPortalContextKey contextKey = "desktopPortal"
)
var (
ErrInvalidCtx = errors.New("invalid context")
ErrNoSessionBus = errors.New("no session bus connection in context")
ErrNoSystemBus = errors.New("no system bus connection in context")
ErrNoDesktopPortal = errors.New("no desktop portal in context")
ErrNoSessionPath = errors.New("no session path in context")
)
func NewContext(ctx context.Context) context.Context {
// Add clock ticks value.
if clktck, err := sysconf.Sysconf(sysconf.SC_CLK_TCK); err != nil {
slog.Warn("Unable to add system clock ticks to context. Some sensors requring it may not be available", slog.Any("error", err))
} else {
ctx = context.WithValue(ctx, clktckContextKey, clktck)
}
// Add boot time value.
if boottime, err := getBootTime(); err != nil {
slog.Warn("Unable to add boot time to context. Some sensors requring it may not be available", slog.Any("error", err))
} else {
ctx = context.WithValue(ctx, boottimeContextKey, boottime)
}
// Add portal interface
if portal, err := findPortal(); err != nil {
slog.Warn("Unable to add desktop portal to context. Some sensors requring it may not be available.", slog.Any("error", err))
} else {
ctx = context.WithValue(ctx, desktopPortalContextKey, portal)
}
// Add D-Bus system bus connection.
if systemBus, err := dbusx.NewBus(ctx, dbusx.SystemBus); err != nil {
slog.Warn("Unable to set up D-Bus system bus connection.", slog.Any("error", err))
} else {
ctx = context.WithValue(ctx, dbusSystemContextKey, systemBus)
// Add session path value.
if sessionPath, err := systemBus.GetSessionPath(); err != nil {
slog.Warn("Unable to determine user session path from D-Bus. Some sensors requring it may not be available.", slog.Any("error", err))
} else {
ctx = context.WithValue(ctx, sessionPathContextKey, sessionPath)
}
}
// Add D-Bus session bus connection.
if sessionBus, err := dbusx.NewBus(ctx, dbusx.SessionBus); err != nil {
slog.Warn("Unable to set up D-Bus session bus connection.", slog.Any("error", err))
} else {
ctx = context.WithValue(ctx, dbusSessionContextKey, sessionBus)
}
return ctx
}
func CtxGetClkTck(ctx context.Context) (int64, bool) {
clktck, ok := ctx.Value(clktckContextKey).(int64)
if !ok {
return 0, false
}
return clktck, true
}
func CtxGetBoottime(ctx context.Context) (time.Time, bool) {
boottime, ok := ctx.Value(boottimeContextKey).(time.Time)
if !ok {
return time.Now(), false
}
return boottime, true
}
func CtxGetDesktopPortal(ctx context.Context) (string, bool) {
portal, ok := ctx.Value(desktopPortalContextKey).(string)
if !ok {
return portal, false
}
return portal, true
}
func CtxGetSystemBus(ctx context.Context) (*dbusx.Bus, bool) {
bus, ok := ctx.Value(dbusSystemContextKey).(*dbusx.Bus)
if !ok {
return bus, false
}
return bus, true
}
func CtxGetSessionBus(ctx context.Context) (*dbusx.Bus, bool) {
bus, ok := ctx.Value(dbusSessionContextKey).(*dbusx.Bus)
if !ok {
return bus, false
}
return bus, true
}
func CtxGetSessionPath(ctx context.Context) (string, bool) {
path, ok := ctx.Value(sessionPathContextKey).(string)
if !ok {
return path, false
}
return path, true
}