package networking import ( "bytes" "encoding/json" "os" "os/exec" "strings" "time" "github.com/prometheus-community/pro-bing" ) const deviceFile = "devices.json" type Device struct { Name string `json:"name"` IP string `json:"ip"` Interface string `json:"interface"` Icon string `json:"icon"` Online bool `json:"online"` } func GetDevices() map[string]Device { result := make(map[string]Device) devices := make(map[string]Device) arpDevices := arpDevices() knownDevices := knownDevices() for mac, device := range arpDevices { if strings.HasPrefix(device.Interface, "br") { continue } if known, ok := knownDevices[mac]; ok { devices[mac] = Device{Name: known.Name, IP: device.IP, Icon: known.Icon} } else { devices[mac] = device } } for mac, device := range knownDevices { if _, ok := devices[mac]; !ok { devices[mac] = Device{Name: device.Name, IP: device.IP, Icon: device.Icon} } } writeDevices(devices) for mac, device := range devices { if device.Icon == "" { device.Icon = "\U000F0C8A" } pinger, err := probing.NewPinger(device.IP) if err == nil { pinger.Count = 1 pinger.Timeout = 500 * time.Millisecond if err := pinger.Run(); err == nil { if pinger.Statistics().PacketsRecv > 0 { device.Online = true } } } result[mac] = device } return result } func writeDevices(devices map[string]Device) { marshal, err := json.MarshalIndent(devices, "", " ") if err != nil { } if err := os.WriteFile(deviceFile, marshal, 0644); err != nil { panic(err) } } func knownDevices() map[string]Device { knownDevices := make(map[string]Device) file, err := os.ReadFile(deviceFile) if err == nil { if err := json.Unmarshal(file, &knownDevices); err != nil { panic(err) } } return knownDevices } func arpDevices() map[string]Device { arp := exec.Command("arp", "-a") var out bytes.Buffer arp.Stdout = &out if err := arp.Run(); err != nil { panic(err) } res := out.String() lines := strings.Split(res, "\n") devices := make(map[string]Device) for l := range lines { entry := strings.Fields(lines[l]) if len(entry) > 6 { devices[entry[3]] = Device{Name: entry[0], IP: strings.ReplaceAll(strings.ReplaceAll(entry[1], "(", ""), ")", ""), Interface: entry[6]} } } return devices }