<<<<<<< HEAD:reactor/needs_port/system/hwinfo.go // package system uses linux commands to get hardware info for identifation ======= // package system uses linux ip command to get hardware info from devices >>>>>>> origin/wrapup:internal/pkg/system/hwinfo.go package system import ( "bytes" "encoding/json" "errors" "hash/fnv" "os/exec" "strings" ) 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 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 } var networks netInterfaces 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 GetID() (int, error) { if HardwareInfo.ID == 0 { if err := getInfo(); err != nil { return 0, err } } return HardwareInfo.ID, nil } func GetIP() (string, error) { if HardwareInfo.IP == "" { if err := getInfo(); err != nil { return "", err } } return HardwareInfo.IP, nil } func GetModel() (string, error) { if HardwareInfo.Model == "" { var stderr, out bytes.Buffer cmd := exec.Command("uname", "-n") cmd.Stdout = &out cmd.Stderr = &stderr if err := cmd.Run(); err != nil { return "", err } b := out.String() HardwareInfo.Model = strings.Trim(b, " \n") } return HardwareInfo.Model, 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 }