building locally

main
KeeganForelight 2 years ago
parent c013330b81
commit e975cb984b

@ -9,12 +9,15 @@ type coordinator interface {
Start() error
}
func NewCoordinator(s string) coordinator {
// allows interface checking as opposed to calling directly
return reactor.NewCoordinator(s)
}
func main() {
id:= "192.1.168.81"
port:= 2000
bus:=1
go reactor.Start(id,port,bus)
fmt.Printf("Starting reactor %v\n",id)
rlc := NewCoordinator("192.1.168.__:____") // host port
go rlc.Start()
fmt.Printf("Starting reactor")
for true {
// endless loop to keep main alive
}

Binary file not shown.

@ -1,13 +0,0 @@
package api
import "time"
type Reactor struct {
ID string
Sensors []Sensor
}
type Sensor struct {
id string
}

@ -1,52 +1,32 @@
package I2C
import (
"fmt"
"net"
"context"
"time"
"google.golang.org/grpc"
pb "FRMS/internal/pkg/grpc"
"fmt"
)
func Start(id string, port,bus int) []int {
/*
Start creates an I2C monitor object and returns the initially connected devices
*/
m := I2CMonitor{Bus:bus,Port:port,Id:id,Devices:map[int]I2Cdev{}}
devices := I2Cconnected(m.Bus)
// m is still new so we don't have to lock yet
now := time.Now()
connected := []int{}
for k,v := range devices {
if v {
m.Devices[k] = I2Cdev{Active:true, LastSeen:now}
connected = append(connected,k)
}
}
fmt.Printf("starting gRPC service\n")
lis, err := net.Listen("tcp",fmt.Sprintf("%v:%v",m.Id,m.Port))
if err != nil {
fmt.Println(err)
}
grpcServer := grpc.NewServer()
pb.RegisterMonitoringServer(grpcServer, &m)
go grpcServer.Serve(lis)
go m.Monitor()
return connected
func NewMonitor(b int) *I2CMonitor{
m := new(I2CMonitor)
m.Devices = make(map[int]I2Cdev)
m.Bus = b
m.Update() //ensure that devices get updated before it gets locked by connected
return m
}
func (m *I2CMonitor) Update() {
/*
gets newly connected sensors and updates any currently dead sensors
*/
connected := I2Cconnected(m.Bus)
m.mu.Lock()
defer m.mu.Unlock()
// locking right away should be fine
fmt.Printf("Getting devices on bus %v\n",m.Bus)
connected := I2Cconnected(m.Bus)
// m.mu.Lock()
// defer m.mu.Unlock()
now := time.Now()
for k,v := range connected {
if _, ok := m.Devices[k]; ok { // if address existed
if _, ok := m.Devices[k]; ok { // if address existed
entry := m.Devices[k]
entry.Active = v // update the value
if v {
@ -54,31 +34,25 @@ func (m *I2CMonitor) Update() {
}
m.Devices[k] = entry
} else if v { // else theres a chance its new
fmt.Printf("adding device %v\n",k)
m.Devices[k] = I2Cdev{Active:true, LastSeen:now} // add new sensors
}
}
}
func (m *I2CMonitor) Remove(addr int) {
m.mu.Lock()
defer m.mu.Unlock()
delete(m.Devices, addr)
}
func (m *I2CMonitor) Monitor () {
/*
long running process responsible for keeping accurate record of devices
*/
for true {
fmt.Printf("Monitoring Sensors\n")
time.Sleep(5*time.Second)
func (m *I2CMonitor) Connected() []int {
// returns list of addresses of connected devices
m.mu.Lock()
defer m.mu.Unlock()
connected := []int{}
for a,_ := range m.Devices {
connected = append(connected, a)
}
}
// grpc stuff
func (m *I2CMonitor) SensorStatusHandler (ctx context.Context, ping *pb.SensorStatusRequest) (*pb.SensorStatusResponse, error) {
now := time.Now()
fmt.Printf("ping rcvd at %v\n",now.Format("15:04:05"))
return &pb.SensorStatusResponse{Id: m.Id}, nil
return connected
}

@ -8,23 +8,17 @@ import (
"time"
"sync"
"strconv"
pb "FRMS/internal/pkg/grpc"
)
type I2Cdev struct {
Addr int
Active bool
Bus int // may be redundant but need to see if I can get around central struct
LastSeen time.Time
}
type I2CMonitor struct { // used in RLC to synchronize accesses
Bus int // bus to use {0,1,2}
Devices map[int]I2Cdev // mapping to quickly index addresses to their device structs
Id string //ip for gRPC
Port int
mu sync.Mutex
pb.UnimplementedMonitoringServer
}
func I2Cconnected(bus int) map[int]bool {
@ -37,7 +31,7 @@ func I2Cconnected(bus int) map[int]bool {
var out bytes.Buffer
cmd.Stdout = &out
err:= cmd.Run()
if err != nil {
fmt.Println(err)
}

@ -0,0 +1,19 @@
syntax = "proto3";
package grpc;
option go_package = "internal/pkg/grpc";
service discovery {
rpc ReactorDiscoveryHandler(ReactorInfoRequest) returns (SuccessResponse);
}
message ReactorInfoRequest {
string Id = 1;
uint32 Ip = 2;
int32 Port = 3;
}
message ServerResponse {
string Id = 1;
bool Success = 2;
}

@ -1,55 +0,0 @@
package reactor
import (
"fmt"
"FRMS/internal/pkg/I2C"
)
type Coordinator struct {
Id string
Port int
}
func Start(id string, port, bus int) error {
// start a gRPC server to respond to pings from central server
//fmt.Printf("Starting gRPC server on %v:%v\n",c.Id,c.Port)
//lis, err := net.Listen("tcp",fmt.Sprintf("%v:%v",c.Id,c.Port))
//if err != nil {
// return err
//}
//grpcServer := grpc.NewServer()
//pb.RegisterCoordinatorServer(grpcServer, newServer())
//go grpcServer.Serve(lis)
// now setting up sensor managers
c := &Coordinator{Id:id,Port:port}
activeDevices := I2C.Start(c.Id,c.Port,bus) //returns list of active sensor addr and starts I2C monitoring software
for _,v := range activeDevices {
// create a goroutine for each active sensor
//go sensor.NewManager(v)
fmt.Printf("Sensor at addr %v initialized\n",v)
}
return nil
}
// grpc stuff
/*
func newServer() *coordinatorServer {
return &coordinatorServer{}
}
type coordinatorServer struct {
pb.UnimplementedCoordinatorServer
id string
}
func (s *coordinatorServer) PingHandler(ctx context.Context, ping *pb.PingRequest) (*pb.PingResponse, error){
now := time.Now()
fmt.Printf("Ping from server recieved at time %v\n", now.Format("15:04:05"))
return &pb.PingResponse{Id: s.id}, nil
}
*/

@ -0,0 +1,75 @@
package reactor
// file describes reactor level coordinator and associated implementation
import (
"fmt"
"FRMS/internal/pkg/system"
"FRMS/internal/pkg/I2C"
)
type Hardware interface {
GetIp() string
GetId() uint32
GetBus() int
}
type I2CMonitor interface {
Connected() []int
}
type Coordinator struct {
Server string
HW Hardware // object to keep track of reactor hw info
I2C I2CMonitor // I2C monitor to keep track of I2C devices
}
//type SensorManager interface {
// Start()
//}
func NewCoordinator(s string) *Coordinator {
return &Coordinator{Server:s}
}
func NewI2CMonitor(b int) I2CMonitor {
return I2C.NewMonitor(b)
}
//func NewSensorManager() SensorManager {
//return sensor.NewManager()
//}
func NewHWMonitor() Hardware {
return system.NewHWMonitor()
}
func (c *Coordinator) Start() error {
// should discover hwinfo and sensors on its own
// now setting up sensor managers
c.HW = NewHWMonitor()
fmt.Printf("Reactor at IP addr %v using I2C bus %v\n",c.HW.GetIp(),c.HW.GetBus())
response := c.Connect()
for response != nil {
// wait to set up the rest of the system until we get a connection
fmt.Println("Connection failed!")
response = c.Connect()
}
c.I2C = NewI2CMonitor(c.HW.GetBus())
devs := c.I2C.Connected()
for _,d := range devs {
// create a goroutine for each active sensor
//sm := NewSensorManager(d)
//go sm.Start()
fmt.Printf("Sensor Manager for addr %v Started!\n",d)
}
return nil
}
func (c *Coordinator) Connect() error {
// function connects to central server and passes hwinfo
return nil
}

@ -0,0 +1,9 @@
package server
import (
"fmt"
)
// the goal here is to set up a gRPC handler to respond to reactor pings with their IP and to establish a new coordinator for that specific reactor

@ -0,0 +1,7 @@
package server
import (
"fmt"
)
// this package will implement a reactor coordinator and associated go routines

@ -0,0 +1,95 @@
package system
import (
"fmt"
"sync"
"os/exec"
"bytes"
"hash/fnv"
"strings"
)
// this package serves to add in wrappers for system commands to get hwinfo from the board
// this package does not actually use the hwinfo command, but rather gathers hardware info from a variety of commands
// command for model :
// lshw -C system 2>/dev/null | head -n 1
// command for ip && mac address :
// ifconfig eth0 | awk '/inet |ether / {print $2}'
// can combine and dump into file using
// lshw -C system 2>/dev/null | head -n 1 > hwinfo.txt && ifconfig eth0 | awk '/inet |ether / {print $2}' >> hwinfo.txt
// *** will just replace info in file everytime
type HWMonitor struct {
Ip string
Id uint32
Bus int
mu sync.Mutex
}
func NewHWMonitor() *HWMonitor {
h := &HWMonitor{}
err := h.Start()
if err != nil {
fmt.Println("hw setup failed " + fmt.Sprint(err))
}
return h
}
func (h *HWMonitor) GetIp() string {
h.mu.Lock()
defer h.mu.Unlock()
return h.Ip
}
func (h *HWMonitor) GetId() uint32 {
h.mu.Lock()
defer h.mu.Unlock()
return h.Id
}
func (h *HWMonitor) GetBus() int {
h.mu.Lock()
defer h.mu.Unlock()
return h.Bus
}
func (h *HWMonitor) Start() error {
// responsible for filling out struct
h.mu.Lock()
defer h.mu.Unlock() // want to ensure we get all values before the RLC reads
bus := map[string]int{"raspberrypi":1,"beaglebone":2} // eventually will replace this with a config file
ipcmd := "ifconfig eth0 | awk '/inet / {print $2}'"
maccmd := "ifconfig eth0 | awk '/ether / {print $2}'"
devcmd := "lshw -C system 2>/dev/null | head -n 1"
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]
cmd.Stderr = &stderr
err := cmd.Run()
if err != nil {
fmt.Println(fmt.Sprint(err)+": "+stderr.String())
return err
}
}
// formatting
ip := res[0].String()
ip = strings.Trim(ip," \n")
h.Ip = ip
hash := fnv.New32a()
hash.Write(res[1].Bytes())
h.Id = hash.Sum32()
b := res[2].String()
b = strings.Trim(b," \n")
h.Bus = bus[b]
return nil
}
Loading…
Cancel
Save