104 lines
2.3 KiB
Go

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:"-"`
Interface string `json:"-"`
Icon string `json:"icon"`
Online bool `json:"-"`
}
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
}