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

133 lines
3.0 KiB
Go

// Copyright (c) 2023 Joshua Rich <joshua.rich@gmail.com>
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
package linux
import (
"context"
"encoding/json"
"os/user"
"strings"
"github.com/joshuar/go-hass-agent/internal/hass/api"
"github.com/rs/zerolog/log"
"github.com/shirou/gopsutil/v3/host"
)
type LinuxDevice struct {
appName string
appVersion string
appID string
hostname string
hwVendor string
hwModel string
osRelease string
osVersion string
machineID string
}
func (l *LinuxDevice) AppName() string {
return l.appName
}
func (l *LinuxDevice) AppVersion() string {
return l.appVersion
}
func (l *LinuxDevice) AppID() string {
return l.appID
}
func (l *LinuxDevice) DeviceName() string {
shortHostname, _, _ := strings.Cut(l.hostname, ".")
return shortHostname
}
func (l *LinuxDevice) DeviceID() string {
return l.machineID
}
func (l *LinuxDevice) Manufacturer() string {
return l.hwVendor
}
func (l *LinuxDevice) Model() string {
return l.hwModel
}
func (l *LinuxDevice) OsName() string {
return l.osRelease
}
func (l *LinuxDevice) OsVersion() string {
return l.osVersion
}
func (l *LinuxDevice) SupportsEncryption() bool {
return false
}
func (l *LinuxDevice) AppData() interface{} {
return &struct {
PushWebsocket bool `json:"push_websocket_channel"`
}{
PushWebsocket: true,
}
}
func (l *LinuxDevice) MarshalJSON() ([]byte, error) {
return json.Marshal(&api.RegistrationRequest{
DeviceID: l.DeviceID(),
AppID: l.AppID(),
AppName: l.AppName(),
AppVersion: l.AppVersion(),
DeviceName: l.DeviceName(),
Manufacturer: l.Manufacturer(),
Model: l.Model(),
OsName: l.OsName(),
OsVersion: l.OsVersion(),
SupportsEncryption: l.SupportsEncryption(),
AppData: l.AppData(),
})
}
func NewDevice(ctx context.Context, name string, version string) *LinuxDevice {
device := &LinuxDevice{
appName: name,
appVersion: version,
}
var err error
_, device.osRelease, device.osVersion, err = host.PlatformInformation()
if err != nil {
log.Fatal().Caller().
Msgf("Could not retrieve distribution details: %v", err.Error())
}
// Try to fetch hostname, vendor, model from DBus. Fall back to
// /sys/devices/virtual/dmi/id for vendor and model if DBus doesn't work.
// Ref:
// https://github.com/ansible/ansible/blob/devel/lib/ansible/module_utils/facts/hardware/linux.py
device.hostname = GetHostname(ctx)
device.hwVendor, device.hwModel = GetHardwareDetails(ctx)
// Use the current user's username to construct an app ID.
currentUser, err := user.Current()
if err != nil {
log.Fatal().Caller().
Msgf("Could not retrieve current user details: %v", err.Error())
}
device.appID = name + "-" + currentUser.Username
// Generate a semi-random machine ID.
device.machineID, err = host.HostID()
if err != nil {
log.Fatal().Caller().
Msgf("Could not retrieve a machine ID: %v", err)
}
return device
}