diff --git a/cmd/client/main.go b/cmd/client/main.go index 0e2ad46..15e4329 100644 --- a/cmd/client/main.go +++ b/cmd/client/main.go @@ -143,12 +143,16 @@ type GPUInfo struct { MemClock float64 `json:"mem_clock_mhz"` Power float64 `json:"power"` PowerLimit float64 `json:"power_limit"` + PowerMax float64 `json:"power_max"` FanSpeed float64 `json:"fan_speed"` PState string `json:"pstate"` - Persistence string `json:"persistence_mode"` ComputeMode string `json:"compute_mode"` DriverVersion string `json:"driver_version"` - CudaVersion string `json:"cuda_version"` + UtilMemory float64 `json:"util_memory"` + UtilEncoder float64 `json:"util_encoder"` + UtilDecoder float64 `json:"util_decoder"` + ClocksMaxGfx float64 `json:"clocks_max_graphics"` + ClocksMaxMem float64 `json:"clocks_max_memory"` } // ═══════════════════════════════════════════════ @@ -1220,20 +1224,33 @@ func tryNvidiaSMI() []GPUInfo { parts[i] = strings.Trim(parts[i], "[]") } + // 0:index 1:name 2:uuid 3:bus_id 4:driver 5:vbios + // 6:temp_gpu 7:temp_mem 8:fan 9:power 10:power_limit + // 11:power_default 12:power_min 13:power_max + // 14:clk_gfx 15:clk_sm 16:clk_mem 17:clk_max_gfx 18:clk_max_mem + // 19:util_gpu 20:util_mem 21:util_enc 22:util_dec + // 23:vram_total 24:vram_used 25:vram_free + // 26:ecc_corr 27:ecc_uncorr 28:compute_mode 29:pstate gpus = append(gpus, GPUInfo{ - Name: cleanStr(parts[1]), - VRAMTotalMB: parseFloat(parts[23]), - VRAMUsedMB: parseFloat(parts[24]), - Temperature: parseFloat(parts[6]), - LoadPercent: parseFloat(parts[19]), - CoreClock: parseFloat(parts[14]), - MemClock: parseFloat(parts[16]), - Power: parseFloatSafe(parts[9]), - PowerLimit: parseFloatSafe(parts[10]), - FanSpeed: parseFloatSafe(parts[8]), - PState: cleanStr(parts[29]), - ComputeMode: cleanStr(parts[28]), - DriverVersion: cleanStr(parts[4]), + Name: cleanStr(parts[1]), + DriverVersion: cleanStr(parts[4]), + Temperature: parseFloat(parts[6]), + FanSpeed: parseFloat(parts[8]), + Power: parseFloat(parts[9]), + PowerLimit: parseFloat(parts[10]), + PowerMax: parseFloat(parts[13]), + CoreClock: parseFloat(parts[14]), + MemClock: parseFloat(parts[16]), + ClocksMaxGfx: parseFloat(parts[17]), + ClocksMaxMem: parseFloat(parts[18]), + LoadPercent: parseFloat(parts[19]), + UtilMemory: parseFloat(parts[20]), + UtilEncoder: parseFloat(parts[21]), + UtilDecoder: parseFloat(parts[22]), + VRAMTotalMB: parseFloat(parts[23]), + VRAMUsedMB: parseFloat(parts[24]), + ComputeMode: cleanStr(parts[28]), + PState: cleanStr(parts[29]), }) } return gpus diff --git a/cmd/server/main.go b/cmd/server/main.go index 1b39f2b..214fa80 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -11,6 +11,7 @@ import ( "path/filepath" "runtime" "strconv" + "strings" "sync" "time" @@ -374,6 +375,55 @@ func (h *Hub) saveYAML() { os.WriteFile(h.devicesAbs, append([]byte(hdr), out...), 0644) } +func filterGPURaw(raw json.RawMessage) json.RawMessage { + var data map[string]interface{} + if json.Unmarshal(raw, &data) != nil { + return raw + } + gpusRaw, ok := data["gpus"] + if !ok { + return raw + } + gpus, ok := gpusRaw.([]interface{}) + if !ok { + return raw + } + var filtered []interface{} + for _, g := range gpus { + gpu, ok := g.(map[string]interface{}) + if !ok { + continue + } + gpuName, _ := gpu["name"].(string) + if isVirtualGPU(gpuName) { + continue + } + filtered = append(filtered, g) + } + data["gpus"] = filtered + out, _ := json.Marshal(data) + return out +} + +func isVirtualGPU(name string) bool { + name = strings.ToLower(name) + blacklist := []string{ + "microsoft", + "basic render", + "vmware", + "virtual", + "hyper-v", + "parallels", + "virtualbox", + } + for _, v := range blacklist { + if strings.Contains(name, v) { + return true + } + } + return false +} + func (h *Hub) UpdateDevice(raw json.RawMessage) { var p AgentPayload if json.Unmarshal(raw, &p) != nil || p.MachineName == "" { @@ -398,7 +448,7 @@ func (h *Hub) UpdateDevice(raw json.RawMessage) { rec.GPUs = append(rec.GPUs, GPURec{Name: g.Name, VRAM: g.VRAM}) } cp := *rec - h.live[name] = raw + h.live[name] = filterGPURaw(raw) var md *MiningData var hist []HashratePoint if m, ok := h.miningData[name]; ok { @@ -416,10 +466,23 @@ func (h *Hub) UpdateDevice(raw json.RawMessage) { h.saveYAML() h.broadcast(BrowserMsg{ Type: "device", Machine: name, - Device: &BrowserDevice{Info: &cp, Live: raw, Online: true, Mining: md, History: hist}, + Device: &BrowserDevice{Info: &cp, Live: filterGPURaw(raw), Online: true, Mining: md, History: hist}, }) } +func (h *Hub) DeleteDevice(name string) { + h.mu.Lock() + _, ok := h.records[name] + delete(h.records, name) + delete(h.live, name) + h.mu.Unlock() + if ok { + h.saveYAML() + h.broadcast(BrowserMsg{Type: "remove", Machine: name}) + logInfo("delete", "%s", name) + } +} + func (h *Hub) MarkOffline(name string) { h.mu.Lock() _, had := h.live[name] @@ -449,19 +512,6 @@ func (h *Hub) MarkOffline(name string) { } } -func (h *Hub) DeleteDevice(name string) { - h.mu.Lock() - _, ok := h.records[name] - delete(h.records, name) - delete(h.live, name) - h.mu.Unlock() - if ok { - h.saveYAML() - h.broadcast(BrowserMsg{Type: "remove", Machine: name}) - logInfo("delete", "%s", name) - } -} - func (h *Hub) AddMonitor(c *websocket.Conn) { h.mu.Lock() h.monitors[c] = struct{}{} diff --git a/cmd/server/templates/index.html b/cmd/server/templates/index.html index 4c19abb..d3b9a84 100644 --- a/cmd/server/templates/index.html +++ b/cmd/server/templates/index.html @@ -4,9 +4,9 @@ Hardware Monitor - - - + + +