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

2 years ago
package reactor
import (
2 years ago
"FRMS/internal/pkg/device"
pb "FRMS/internal/pkg/grpc"
2 years ago
"FRMS/internal/pkg/i2c"
"fmt"
"sync"
"time"
"github.com/spf13/viper"
)
// Created by rlc to manage devices
2 years ago
// device manager
type DeviceManager interface {
Start() error
Exit() error
2 years ago
IsActive() int
}
2 years ago
func NewDeviceManager(bus, addr int, config *viper.Viper) (DeviceManager, error) {
return device.New(bus, addr, config)
}
// device coordinator itself
type DeviceCoordinator struct {
2 years ago
// base level manager for heartbeat
Bus int // i2c bus
Manager
Config *viper.Viper
2 years ago
managersMu sync.RWMutex
DeviceManagers map[int]DeviceManager
}
2 years ago
func NewDeviceCoordinator(config *viper.Viper) *DeviceCoordinator {
dm := make(map[int]DeviceManager)
m := NewManager(0)
c := &DeviceCoordinator{
2 years ago
Manager: m,
DeviceManagers: dm,
Config: config,
}
return c
}
2 years ago
func (c *DeviceCoordinator) Start(bus int) error {
var err error
if err = c.Manager.Start(); err != nil {
return err
}
2 years ago
// i2c bus
c.Bus = bus
go c.Monitor()
return err
}
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)
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 {
_, 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 {
// 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)
if err != nil {
panic(err)
}
if err := dm.Start(); err != nil {
panic(err)
}
2 years ago
c.DeviceManagers[addr] = dm
}
}
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 {
// looping over devices
devices = append(devices, &pb.Device{
Addr: int32(addr),
Status: pb.Status(dm.IsActive()),
})
}
return devices, nil
}