You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
135 lines
2.5 KiB
Go
135 lines
2.5 KiB
Go
2 years ago
|
package reactor
|
||
2 years ago
|
|
||
2 years ago
|
import (
|
||
2 years ago
|
"FRMS/internal/pkg/device"
|
||
2 years ago
|
pb "FRMS/internal/pkg/grpc"
|
||
2 years ago
|
"FRMS/internal/pkg/i2c"
|
||
2 years ago
|
"fmt"
|
||
|
"sync"
|
||
|
"time"
|
||
2 years ago
|
|
||
2 years ago
|
"github.com/spf13/viper"
|
||
|
)
|
||
2 years ago
|
|
||
2 years ago
|
// Created by rlc to manage devices
|
||
2 years ago
|
|
||
2 years ago
|
// device manager
|
||
|
type DeviceManager interface {
|
||
2 years ago
|
Start() error
|
||
|
Exit() error
|
||
2 years ago
|
IsActive() int
|
||
2 years ago
|
}
|
||
|
|
||
2 years ago
|
func NewDeviceManager(bus, addr int, config *viper.Viper) (DeviceManager, error) {
|
||
|
return device.New(bus, addr, config)
|
||
2 years ago
|
}
|
||
|
|
||
|
// device coordinator itself
|
||
2 years ago
|
type DeviceCoordinator struct {
|
||
2 years ago
|
// base level manager for heartbeat
|
||
|
Bus int // i2c bus
|
||
2 years ago
|
Manager
|
||
|
Config *viper.Viper
|
||
|
|
||
2 years ago
|
managersMu sync.RWMutex
|
||
|
DeviceManagers map[int]DeviceManager
|
||
2 years ago
|
}
|
||
|
|
||
2 years ago
|
func NewDeviceCoordinator(config *viper.Viper) *DeviceCoordinator {
|
||
|
dm := make(map[int]DeviceManager)
|
||
|
m := NewManager(0)
|
||
2 years ago
|
c := &DeviceCoordinator{
|
||
2 years ago
|
Manager: m,
|
||
|
DeviceManagers: dm,
|
||
|
Config: config,
|
||
2 years ago
|
}
|
||
|
return c
|
||
|
}
|
||
|
|
||
2 years ago
|
func (c *DeviceCoordinator) Start(bus int) error {
|
||
2 years ago
|
var err error
|
||
|
|
||
|
if err = c.Manager.Start(); err != nil {
|
||
|
return err
|
||
|
}
|
||
2 years ago
|
// i2c bus
|
||
|
c.Bus = bus
|
||
2 years ago
|
|
||
|
go c.Monitor()
|
||
|
return err
|
||
2 years ago
|
}
|
||
|
|
||
2 years ago
|
func (c *DeviceCoordinator) Monitor() {
|
||
|
// monitor I2C for new devices
|
||
|
ch := make(chan struct{})
|
||
|
go c.HeartBeat(ch, 10, 0, time.Second)
|
||
|
|
||
|
for range ch {
|
||
|
// on notification (10s)
|
||
2 years ago
|
devs, err := i2c.GetConnected(c.Bus)
|
||
2 years ago
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
// update list
|
||
|
go c.UpdateManagers(devs)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (c *DeviceCoordinator) UpdateManagers(active map[int]bool) {
|
||
|
// updates managers
|
||
|
c.managersMu.Lock()
|
||
|
defer c.managersMu.Unlock()
|
||
|
|
||
2 years ago
|
for addr, dm := range c.DeviceManagers {
|
||
2 years ago
|
_, ok := active[addr]
|
||
|
|
||
|
if ok && dm.IsActive() == 0 {
|
||
|
// active and dm not
|
||
|
if err := dm.Start(); err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
2 years ago
|
} else if !ok && dm.IsActive() == 1 {
|
||
2 years ago
|
// not active and dm is
|
||
|
if err := dm.Exit(); err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
}
|
||
|
// remove from map
|
||
|
delete(active, addr)
|
||
|
}
|
||
|
|
||
|
for addr, _ := range active {
|
||
|
// no manager, create one
|
||
|
fmt.Printf("New device %d!\n", addr)
|
||
|
|
||
2 years ago
|
dm, err := NewDeviceManager(c.Bus, addr, c.Config)
|
||
2 years ago
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
|
||
|
if err := dm.Start(); err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
|
||
2 years ago
|
c.DeviceManagers[addr] = dm
|
||
2 years ago
|
}
|
||
|
}
|
||
|
|
||
|
func (c *DeviceCoordinator) GetDeviceInfo() ([]*pb.Device, error) {
|
||
|
// gets device info for monitoring
|
||
|
c.managersMu.RLock()
|
||
|
defer c.managersMu.RUnlock()
|
||
|
|
||
|
var devices []*pb.Device
|
||
|
|
||
2 years ago
|
for addr, dm := range c.DeviceManagers {
|
||
2 years ago
|
// looping over devices
|
||
|
devices = append(devices, &pb.Device{
|
||
|
Addr: int32(addr),
|
||
|
Status: pb.Status(dm.IsActive()),
|
||
|
})
|
||
|
}
|
||
|
|
||
|
return devices, nil
|
||
2 years ago
|
}
|