diff --git a/cmd/reactor/main.go b/cmd/reactor/main.go index 1db35e6..a7b4bdb 100644 --- a/cmd/reactor/main.go +++ b/cmd/reactor/main.go @@ -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") diff --git a/go.mod b/go.mod index 5c4d6d8..476454a 100644 --- a/go.mod +++ b/go.mod @@ -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 diff --git a/go.sum b/go.sum index b6dc52f..6e81e5d 100644 --- a/go.sum +++ b/go.sum @@ -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= diff --git a/internal/pkg/device/controller.go b/internal/pkg/device/controller.go index ca03bf1..feaef36 100644 --- a/internal/pkg/device/controller.go +++ b/internal/pkg/device/controller.go @@ -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) { diff --git a/internal/pkg/device/do.go b/internal/pkg/device/do.go index ade64e8..e64871b 100644 --- a/internal/pkg/device/do.go +++ b/internal/pkg/device/do.go @@ -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 { diff --git a/internal/pkg/device/manager.go b/internal/pkg/device/manager.go index 92c321e..77faaf4 100644 --- a/internal/pkg/device/manager.go +++ b/internal/pkg/device/manager.go @@ -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 { diff --git a/internal/pkg/device/mappings.go b/internal/pkg/device/mappings.go index 92c6ff7..143b27f 100644 --- a/internal/pkg/device/mappings.go +++ b/internal/pkg/device/mappings.go @@ -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 } diff --git a/internal/pkg/device/ph.go b/internal/pkg/device/ph.go index f6d8dde..f86646d 100644 --- a/internal/pkg/device/ph.go +++ b/internal/pkg/device/ph.go @@ -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 { diff --git a/internal/pkg/device/pwm.go b/internal/pkg/device/pwm.go index 130c17e..5840a3c 100644 --- a/internal/pkg/device/pwm.go +++ b/internal/pkg/device/pwm.go @@ -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 diff --git a/internal/pkg/device/rtd.go b/internal/pkg/device/rtd.go index 07ef3a4..eb82af4 100644 --- a/internal/pkg/device/rtd.go +++ b/internal/pkg/device/rtd.go @@ -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 { diff --git a/internal/pkg/device/sensor.go b/internal/pkg/device/sensor.go index 560b0da..b53393d 100644 --- a/internal/pkg/device/sensor.go +++ b/internal/pkg/device/sensor.go @@ -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() } } diff --git a/internal/pkg/i2c/bus.go b/internal/pkg/i2c/i2c.go similarity index 93% rename from internal/pkg/i2c/bus.go rename to internal/pkg/i2c/i2c.go index 7ba012e..867168c 100644 --- a/internal/pkg/i2c/bus.go +++ b/internal/pkg/i2c/i2c.go @@ -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 ( diff --git a/internal/pkg/manager/manager.go b/internal/pkg/manager/manager.go index 3a8db51..eaf4376 100644 --- a/internal/pkg/manager/manager.go +++ b/internal/pkg/manager/manager.go @@ -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). diff --git a/internal/pkg/reactor/coordinator.go b/internal/pkg/reactor/coordinator.go index 1d9dd8b..11b562c 100644 --- a/internal/pkg/reactor/coordinator.go +++ b/internal/pkg/reactor/coordinator.go @@ -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) diff --git a/internal/pkg/reactor/device.go b/internal/pkg/reactor/device.go index c2afc6c..76a2022 100644 --- a/internal/pkg/reactor/device.go +++ b/internal/pkg/reactor/device.go @@ -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) } } diff --git a/internal/pkg/system/hwinfo.go b/internal/pkg/system/hwinfo.go index dca66ed..50bf9de 100644 --- a/internal/pkg/system/hwinfo.go +++ b/internal/pkg/system/hwinfo.go @@ -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 } diff --git a/internal/pkg/system/hwinfo_test.go b/internal/pkg/system/hwinfo_test.go new file mode 100644 index 0000000..968e01a --- /dev/null +++ b/internal/pkg/system/hwinfo_test.go @@ -0,0 +1,12 @@ +package system + +import ( + "testing" +) + +func TestGetInfo(t *testing.T) { + info, err := GetInfo() + if err != nil { + panic(err) + } +}