fixed hwinfo to use global var and repaired reactor side interfaces

main
KeeganForelight 2 years ago
parent 88e70503d1
commit 9392892ede

@ -17,13 +17,16 @@ type reactorCoordinator interface {
Start()
}
func NewReactorCoordinator(config *viper.Viper, ch chan error) reactorCoordinator {
func NewReactorCoordinator(
config *viper.Viper,
ch chan error,
) (reactorCoordinator, error) {
// allows interface checking as opposed to calling directly
return reactor.NewCoordinator(config, ch)
}
func NewConfig(fname string) *viper.Viper {
return config.LoadConfig(fname)
func NewConfig(file, path, ext string) (*viper.Viper, error) {
return config.LoadConfig(file, path, ext)
}
func main() {
@ -32,10 +35,26 @@ func main() {
signal.Notify(gracefulShutdown, syscall.SIGINT, syscall.SIGTERM)
// load any stored configs
conf := NewConfig("reactor")
home, err := os.UserHomeDir()
if err != nil {
panic(err)
}
configPath := fmt.Sprintf("%s/.config/FRMS", home)
configFile := "reactor"
configExt := "yaml"
conf, err := NewConfig(configFile, configPath, configExt)
if err != nil {
panic(err)
}
ch := make(chan error)
rlc := NewReactorCoordinator(conf, ch) // passing conf and err
rlc, err := NewReactorCoordinator(conf, ch) // passing conf and err
if err != nil {
panic(err)
}
go rlc.Start()
logging.Debug(logging.DStart, "Reactor Started")

@ -3,7 +3,6 @@ module FRMS
go 1.18
require (
github.com/gorilla/websocket v1.5.0
github.com/influxdata/influxdb-client-go/v2 v2.9.1
github.com/spf13/viper v1.12.0
github.com/stretchr/testify v1.7.1
@ -29,12 +28,9 @@ require (
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.3.0 // indirect
github.com/yuin/goldmark v1.4.13 // indirect
golang.org/x/mod v0.10.0 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/text v0.9.0 // indirect
golang.org/x/tools v0.9.3 // indirect
google.golang.org/genproto v0.0.0-20220519153652-3a47de7e79bd // indirect
gopkg.in/ini.v1 v1.66.4 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect

@ -139,8 +139,6 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
@ -217,8 +215,6 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
@ -268,8 +264,6 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -303,8 +297,6 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2 h1:NWy5+hlRbC7HK+PmcXVUmW1IMyFce7to56IUvhUFm7Y=
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@ -369,8 +361,6 @@ golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b h1:2n253B2r0pYSmEV+UNCQoPfU/FiaizQEK5Gu4Bq4JE8=
golang.org/x/sys v0.0.0-20220627191245-f75cf1eec38b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
@ -382,8 +372,6 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -438,8 +426,6 @@ golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM=
golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

@ -13,8 +13,8 @@ type ControllerManager struct {
Enabled bool // turn controller on or off
}
func NewControllerManager() *ControllerManager {
return &ControllerManager{}
func NewControllerManager() (*ControllerManager, error) {
return &ControllerManager{}, nil
}
func (c *ControllerManager) SetDeviceManager(d *DeviceManager) {

@ -14,7 +14,7 @@ type DOManager struct {
sync.RWMutex
}
func NewDOManager() *DOManager {
func NewDOManager() (*DOManager, error) {
// atlas delays
a := &Atlas{
CalDelay: 1300,
@ -23,11 +23,10 @@ func NewDOManager() *DOManager {
sm := NewSensorManager()
m := &DOManager{
return &DOManager{
Atlas: a,
SensorManager: sm,
}
return m
}, nil
}
func (m *DOManager) Start() error {

@ -14,12 +14,12 @@ import (
type Manager interface {
// core manager
Start() error
Exit() error
IsActive() int
Stop() error
IsActive() manager.Status
HeartBeat(chan struct{}, int, int, time.Duration)
}
func NewManager() Manager {
func NewManager() (Manager, error) {
// no timeouts needed
return manager.New(0)
}
@ -36,21 +36,26 @@ type DeviceManager struct {
Manager
// config
Config *viper.Viper
// gRPC server
pb.UnimplementedDeviceServer
}
func NewDeviceManager(bus, addr int, config *viper.Viper, defaultName string) *DeviceManager {
func NewDeviceManager(
bus, addr int,
config *viper.Viper,
defaultName string,
) (*DeviceManager, error) {
// new base dm
m := NewManager()
dm := &DeviceManager{
m, err := NewManager()
if err != nil {
return &DeviceManager{}, err
}
return &DeviceManager{
Address: addr,
Bus: bus,
defaultName: defaultName,
Manager: m,
Config: config,
}
return dm
}, nil
}
func (m *DeviceManager) LoadConfig() error {

@ -1,6 +1,7 @@
package device
import (
"FRMS/internal/pkg/manager"
"errors"
"fmt"
@ -10,8 +11,8 @@ import (
// Returns the correct manager for sensor/controller
type Device interface {
Start() error
Exit() error
IsActive() int
Stop() error
IsActive() manager.Status
SetDeviceManager(*DeviceManager)
}
@ -25,26 +26,33 @@ func New(bus, addr int, config *viper.Viper) (Device, error) {
case 97:
// DO
defaultName = "DO Sensor"
m = NewDOManager()
m, err = NewDOManager()
case 99:
// pH
defaultName = "pH Sensor"
m = NewPHManager()
m, err = NewPHManager()
case 102:
// RTD
defaultName = "RTD Sensor"
m = NewRTDManager()
m, err = NewRTDManager()
case 256:
// PWM
defaultName = "PWM Controller"
m = NewPWMManager()
m, err = NewPWMManager()
default:
err = errors.New(fmt.Sprintf("Error: device id %d unrecognized!", addr))
}
// setting device manager
dm := NewDeviceManager(bus, addr, config, defaultName)
if err != nil {
return m, err
}
dm, err := NewDeviceManager(bus, addr, config, defaultName)
if err != nil {
return m, err
}
m.SetDeviceManager(dm)
// setting up gRPC server functionality
return m, err
}

@ -14,7 +14,7 @@ type PHManager struct {
sync.RWMutex
}
func NewPHManager() *PHManager {
func NewPHManager() (*PHManager, error) {
// atlas delays
a := &Atlas{
CalDelay: 900,
@ -22,11 +22,10 @@ func NewPHManager() *PHManager {
}
sm := NewSensorManager()
m := &PHManager{
return &PHManager{
Atlas: a,
SensorManager: sm,
}
return m
}, nil
}
func (m *PHManager) Start() error {

@ -14,9 +14,12 @@ type PWMManager struct {
DutyCycle int
}
func NewPWMManager() *PWMManager {
cm := NewControllerManager()
return &PWMManager{ControllerManager: cm}
func NewPWMManager() (*PWMManager, error) {
cm, err := NewControllerManager()
return &PWMManager{
ControllerManager: cm,
}, err
}
// freq changing

@ -13,7 +13,7 @@ type RTDManager struct {
sync.RWMutex
}
func NewRTDManager() *RTDManager {
func NewRTDManager() (*RTDManager, error) {
// atlas delays
a := &Atlas{
CalDelay: 600,
@ -21,11 +21,10 @@ func NewRTDManager() *RTDManager {
}
sm := NewSensorManager()
m := &RTDManager{
return &RTDManager{
Atlas: a,
SensorManager: sm,
}
return m
}, nil
}
func (m *RTDManager) Start() error {

@ -16,9 +16,6 @@ type SensorManager struct {
SampleTimestamp int64
*DeviceManager `mapstructure:",squash"`
// gRPC server
pb.UnimplementedSensorServer
}
func NewSensorManager() *SensorManager {
@ -86,7 +83,7 @@ func (s *SensorManager) Monitor(f takeReading) {
fmt.Printf("Got %f\n", reading)
s.sampleMu.Lock()
s.LatestSample = float32(reading)
s.SampleTimestamp = time.Now.Unix()
s.SampleTimestamp = time.Now().Unix()
s.sampleMu.Unlock()
}
}

@ -1,7 +1,7 @@
// package i2c wraps the [i2c-tools] commands to interact
// with devices on the buss
// package i2c wraps the [i2c package] to interact with the i2c
// with devices on the bus
//
// [i2c-tools]: https://manpages.debian.org/unstable/i2c-tools/index.html
// [i2c package]: https://pkg.go.dev/periph.io/x/conn/v3/i2c#pkg-overview
package i2c
import (

@ -17,13 +17,13 @@ var (
ErrMaxAttemptsExceeded = errors.New("max connection attempts exceeded")
)
// ManagerStatus is used as an enum for the current status.
// Status is used as an enum for the current status.
// Could be expanded to include others such as killed, sleeping, etc.
type ManagerStatus int
type Status int
const (
Inactive ManagerStatus = 0
Active ManagerStatus = 1
Inactive Status = 0
Active Status = 1
)
// MaxConnAttempts is the maximum allowable connection attempts.
@ -77,8 +77,8 @@ func (m *Manager) Stop() error {
}
// IsActive returns the current ManagerStatus.
func (m *Manager) IsActive() ManagerStatus {
return ManagerStatus(atomic.LoadInt32(&m.active))
func (m *Manager) IsActive() Status {
return Status(atomic.LoadInt32(&m.active))
}
// HeartBeat will send an empty struct over ping every hb (scale).

@ -22,12 +22,12 @@ import (
// I dont think I actually need this interface, package manager has a point
type Manager interface {
Start() error
Exit() error
Stop() error
Timeout() (time.Duration, error)
HeartBeat(chan struct{}, int, int, time.Duration) // creates a hb
}
func NewManager(max int) Manager {
func NewManager(max int) (Manager, error) {
return manager.New(max)
}
@ -71,10 +71,22 @@ type ReactorCoordinator struct {
Err chan error
}
func NewCoordinator(config *viper.Viper, errCh chan error) *ReactorCoordinator {
func NewCoordinator(
config *viper.Viper,
errCh chan error,
) (*ReactorCoordinator, error) {
m := NewManager(6) // max 6 attempts
dc := NewDeviceCoordinator(config)
m, err := NewManager(6) // max 6 attempts
if err != nil {
return &ReactorCoordinator{}, err
}
dc, err := NewDeviceCoordinator(config)
if err != nil {
return &ReactorCoordinator{}, err
}
c := &ReactorCoordinator{
Manager: m,
@ -83,10 +95,7 @@ func NewCoordinator(config *viper.Viper, errCh chan error) *ReactorCoordinator {
Err: errCh,
}
// this is going to be scuffed
//c.DB = &DB{Bucket: "bb", Org: "ForeLight", URL: url, Token: "S1UZssBu6KPfHaQCt34pZFpyc5lzbH9XanYJWCkOI5FqLY7gq205C6FTH-CmugiPH6o2WoKlTkEuPgIfaJjAhw=="}
return c
return c, nil
}
func (c *ReactorCoordinator) Start() {
@ -129,7 +138,7 @@ func (c *ReactorCoordinator) LoadConfig() error {
if !c.Config.IsSet("reactor.id") {
// get from hw
var id int
if id, err = system.GetId("eth0"); err != nil {
if id, err = system.GetID(); err != nil {
return err
}
c.Config.Set("reactor.id", id)

@ -4,6 +4,7 @@ import (
"FRMS/internal/pkg/device"
pb "FRMS/internal/pkg/grpc"
"FRMS/internal/pkg/i2c"
"FRMS/internal/pkg/manager"
"fmt"
"sync"
"time"
@ -16,8 +17,8 @@ import (
// device manager
type DeviceManager interface {
Start() error
Exit() error
IsActive() int
Stop() error
IsActive() manager.Status
}
func NewDeviceManager(bus, addr int, config *viper.Viper) (DeviceManager, error) {
@ -35,15 +36,16 @@ type DeviceCoordinator struct {
DeviceManagers map[int]DeviceManager
}
func NewDeviceCoordinator(config *viper.Viper) *DeviceCoordinator {
func NewDeviceCoordinator(config *viper.Viper) (*DeviceCoordinator, error) {
dm := make(map[int]DeviceManager)
m := NewManager(0)
c := &DeviceCoordinator{
m, err := NewManager(0)
return &DeviceCoordinator{
Manager: m,
DeviceManagers: dm,
Config: config,
}
return c
}, err
}
func (c *DeviceCoordinator) Start(bus int) error {
@ -83,14 +85,14 @@ func (c *DeviceCoordinator) UpdateManagers(active map[int]bool) {
for addr, dm := range c.DeviceManagers {
_, ok := active[addr]
if ok && dm.IsActive() == 0 {
if ok && dm.IsActive() == manager.Inactive {
// active and dm not
if err := dm.Start(); err != nil {
panic(err)
}
} else if !ok && dm.IsActive() == 1 {
} else if !ok && dm.IsActive() == manager.Active {
// not active and dm is
if err := dm.Exit(); err != nil {
if err := dm.Stop(); err != nil {
panic(err)
}
}

@ -1,118 +1,145 @@
// package system uses linux commands to get hardware info from devices
// package system uses linux ip command to get hardware info from devices
package system
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"hash/fnv"
"net"
"os/exec"
"strings"
)
func GetId() (int, error) {
// gets the mac address and hashes into consistent id
maccmd := fmt.Sprintf("ifconfig %v | awk '/ether / {print $2}'", et)
var stderr bytes.Buffer
var out bytes.Buffer
cmd := exec.Command("bash", "-c", maccmd)
cmd.Stdout = &out
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
return 0, err
}
hash := fnv.New32a()
hash.Write(out.Bytes())
id := hash.Sum32()
return int(id), nil
var (
ErrBusNotFound = errors.New("bus not found for device")
ErrNoNetworkInterface = errors.New("no default network found")
)
var HardwareInfo = &hardwareInfo{}
type hardwareInfo struct {
MAC string
IP string
ID int
Model string
}
// NetInterfaces is a struct to unmarshal the ip command json.
type netInterfaces []network
// Networks holds relevant information for each network interface.
// Used to unmarshal ip command json.
type network struct {
Subnets []netInfo `json:"addr_info"`
Mac string `json:"address"`
Group string `json:"group"`
State string `json:"operstate"`
}
type netInfo struct {
Family string `json:"family"`
Ip string `json:"local"`
}
func GetIp() (string, error) {
ipcmd := "ip route get 1 | sed 's/^.*src \([^ ]*\).*$/\1/;q'"
var stderr bytes.Buffer
var out bytes.Buffer
cmd := exec.Command("bash", "-c", ipcmd)
cmd.Stdout = &out
func getInfo() error {
var stderr, stdout bytes.Buffer
cmd := exec.Command("ip", "-j", "a")
cmd.Stdout = &stdout
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
return "", err
return err
}
ip := strings.Trim(out.String(), " \n")
return ip, nil
}
var networks netInterfaces
func GetPort() (int, error) {
// obsolete
if addr, err := net.ResolveTCPAddr("tcp", ":0"); err != nil {
return 0, err
} else if lis, err := net.ListenTCP("tcp", addr); err != nil {
return 0, err
} else {
defer lis.Close()
return lis.Addr().(*net.TCPAddr).Port, nil
if err := json.Unmarshal(stdout.Bytes(), &networks); err != nil {
return err
}
// loop over found networks finding first default, IPv4 network currently
// UP (active).
// Eventually need to look only at wg interface which simplifies
// implementation.
for _, network := range networks {
if network.Group == "default" && network.State == "UP" {
for _, subnet := range network.Subnets {
if subnet.Family == "inet" {
hash := fnv.New32a()
hash.Write([]byte(network.Mac))
id := hash.Sum32()
HardwareInfo.MAC = network.Mac
HardwareInfo.IP = subnet.Ip
HardwareInfo.ID = int(id)
return nil
}
}
}
}
return nil
}
func GetBus() (int, error) {
// preset busses
busList := map[string]int{"raspberrypi": 1, "beaglebone": 2}
// vars
var bus int
var ok bool
func GetID() (int, error) {
if name, err =: GetModel(); err != nil {
return bus, err
} else if bus, ok = busList[b]; !ok {
return 0, errors.New(fmt.Sprintf("No bus for dev %s", b))
if HardwareInfo.ID == 0 {
if err := getInfo(); err != nil {
return 0, err
}
}
// returns correct bus
return bus, nil
return HardwareInfo.ID, nil
}
func GetModel() (string, error) {
var stderr, out bytes.Buffer
cmd := exec.Command("bash", "-c", "hostname")
cmd.Stdout = &out
cmd.Stderr = &stderr
if err := cmd.Run(); err != nil {
return "", err
func GetIP() (string, error) {
if HardwareInfo.IP == "" {
if err := getInfo(); err != nil {
return "", err
}
}
b := out.String()
b = strings.Trim(b, " \n")
return b, nil
return HardwareInfo.IP, nil
}
func Get() error {
// responsible for filling out struct
//bus := map[string]int{"raspberrypi":1,"beaglebone":2} // eventually will replace this with a config file
func GetModel() (string, error) {
ipcmd := "ifconfig eth0 | awk '/inet / {print $2}'"
maccmd := "ifconfig eth0 | awk '/ether / {print $2}'"
devcmd := "lshw -C system 2>/dev/null | head -n 1"
if HardwareInfo.Model == "" {
res := [3]bytes.Buffer{}
var stderr bytes.Buffer
cmds := []string{ipcmd, maccmd, devcmd}
for i, c := range cmds {
cmd := exec.Command("bash", "-c", c)
cmd.Stdout = &res[i]
var stderr, out bytes.Buffer
cmd := exec.Command("uname", "-n")
cmd.Stdout = &out
cmd.Stderr = &stderr
err := cmd.Run()
if err != nil {
return err
if err := cmd.Run(); err != nil {
return "", err
}
b := out.String()
HardwareInfo.Model = strings.Trim(b, " \n")
}
// formatting
ip := res[0].String()
ip = strings.Trim(ip, " \n")
hash := fnv.New32a()
hash.Write(res[1].Bytes())
return HardwareInfo.Model, nil
}
b := res[2].String()
b = strings.Trim(b, " \n")
return nil
func GetBus() (int, error) {
// preset busses
busList := map[string]int{"raspberrypi": 1, "beaglebone": 2}
// vars
var bus int
var ok bool
if name, err := GetModel(); err != nil {
return bus, err
} else if bus, ok = busList[name]; !ok {
return 0, ErrBusNotFound
}
return bus, nil
}

@ -0,0 +1,12 @@
package system
import (
"testing"
)
func TestGetInfo(t *testing.T) {
info, err := GetInfo()
if err != nil {
panic(err)
}
}
Loading…
Cancel
Save