package I2C import ( "fmt" "os/exec" "bytes" "strings" "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 { /* I2CConnect takes an integer specifying the bus to search as input Returns a slice of type I2Cdev */ b := strconv.Itoa(bus) cmd := exec.Command("i2cdetect", "-y", "-r", b) var out bytes.Buffer cmd.Stdout = &out err:= cmd.Run() if err != nil { fmt.Println(err) } outString := out.String() // could split by \n too split := strings.SplitAfter(outString,":") // 1st entry is garbage headers and ending is always \n##: split = split[1:] // create empty slice for all the devices //var devices []i2cdev devices := map[int]bool{} //maps device addresses to active bool for i,v := range split { lst := strings.Index(v,"\n") trimmed := v[:lst] trimmed = strings.Trim(trimmed," ") // trimmed now holds just possible sensor addresses count := strings.Split(trimmed," ") for j,d := range count { // the first row has to be offset by 3 but after its just i*16 + j offset := 0 if i == 0 { offset = 3 } addr := i*16 + j + offset if strings.Contains(d,"--") || strings.Contains(d,"UU") { // address is unconnected or reserved //devices = append(devices, I2Cdev{Addr:addr,Active:false}) devices[addr] = false } else { //devices = append(devices, I2Cdev{Addr:addr,Active:true,LastSeen:now}) devices[addr] = true } } } return devices }