From 742928a93df6022bb1233197a39c2243ebfd3322 Mon Sep 17 00:00:00 2001 From: ngfchl Date: Fri, 19 Jun 2026 16:46:41 +0800 Subject: [PATCH] feat: client config from yaml with interval/reconnect settings --- client.yaml | 13 +++++++ cmd/client/main.go | 88 ++++++++++++++++++++++++++++++++++------------ 2 files changed, 78 insertions(+), 23 deletions(-) create mode 100644 client.yaml diff --git a/client.yaml b/client.yaml new file mode 100644 index 0000000..26445d6 --- /dev/null +++ b/client.yaml @@ -0,0 +1,13 @@ +# Hardware Monitor Client 配置 +# +# machine_name : 设备名称 (默认使用主机名) +# server : 服务端地址 (ip:port) +# interval : 采集间隔 (秒, 默认 3) +# reconnect_delay : 断线重连间隔 (秒, 默认 3) +# +# 删除此文件可重新配置 + +machine_name: my-pc +server: 192.168.1.100:8080 +interval: 3 +reconnect_delay: 3 diff --git a/cmd/client/main.go b/cmd/client/main.go index a8ce741..3de857b 100644 --- a/cmd/client/main.go +++ b/cmd/client/main.go @@ -33,34 +33,56 @@ var ( // ═══════════════════════════════════════════════ type ClientConfig struct { - MachineName string `yaml:"machine_name"` - Server string `yaml:"server"` + MachineName string `yaml:"machine_name"` + Server string `yaml:"server"` + Interval int `yaml:"interval"` + ReconnectDelay int `yaml:"reconnect_delay"` +} + +func defaultConfig() ClientConfig { + return ClientConfig{ + Interval: 3, + ReconnectDelay: 3, + } } func configPath() string { - exe, err := os.Executable() - if err != nil { - return "client.yaml" + // 优先: 当前工作目录 + if wd, err := os.Getwd(); err == nil { + p := filepath.Join(wd, "client.yaml") + if _, err := os.Stat(p); err == nil { + return p + } } - return filepath.Join(filepath.Dir(exe), "client.yaml") + // 其次: 可执行文件目录 + if exe, err := os.Executable(); err == nil { + return filepath.Join(filepath.Dir(exe), "client.yaml") + } + return "client.yaml" } func loadConfig() (ClientConfig, bool) { p := configPath() raw, err := os.ReadFile(p) if err != nil { - return ClientConfig{}, false + return defaultConfig(), false } - var c ClientConfig - if yaml.Unmarshal(raw, &c) != nil { - return ClientConfig{}, false + cfg := defaultConfig() + if yaml.Unmarshal(raw, &cfg) != nil { + return defaultConfig(), false } - c.MachineName = strings.TrimSpace(c.MachineName) - c.Server = strings.TrimSpace(c.Server) - if c.MachineName == "" || c.Server == "" { - return ClientConfig{}, false + cfg.MachineName = strings.TrimSpace(cfg.MachineName) + cfg.Server = strings.TrimSpace(cfg.Server) + if cfg.MachineName == "" || cfg.Server == "" { + return defaultConfig(), false } - return c, true + if cfg.Interval <= 0 { + cfg.Interval = 3 + } + if cfg.ReconnectDelay <= 0 { + cfg.ReconnectDelay = 3 + } + return cfg, true } func saveConfig(c ClientConfig) error { @@ -68,7 +90,14 @@ func saveConfig(c ClientConfig) error { if err != nil { return err } - hdr := "# Monitor Client 配置\n# 删除此文件可重新输入设备信息\n\n" + hdr := "# Hardware Monitor Client 配置\n" + hdr += "#\n" + hdr += "# machine_name : 设备名称 (默认使用主机名)\n" + hdr += "# server : 服务端地址 (ip:port)\n" + hdr += "# interval : 采集间隔 (秒, 默认 3)\n" + hdr += "# reconnect_delay : 断线重连间隔 (秒, 默认 3)\n" + hdr += "#\n" + hdr += "# 删除此文件可重新配置\n\n" p := configPath() os.MkdirAll(filepath.Dir(p), 0755) return os.WriteFile(p, append([]byte(hdr), out...), 0644) @@ -414,7 +443,10 @@ func (m model) handleEnter() (tea.Model, tea.Cmd) { addr += ":8080" } - m.cfg = ClientConfig{MachineName: name, Server: addr} + cfg := defaultConfig() + cfg.MachineName = name + cfg.Server = addr + m.cfg = cfg saveConfig(m.cfg) // 切换到监控阶段 @@ -869,6 +901,15 @@ func runCollector(done <-chan struct{}, cfg ClientConfig, dataCh chan<- MachineD // 预热 cpu.Percent(500*time.Millisecond, true) + interval := time.Duration(cfg.Interval) * time.Second + if interval < time.Second { + interval = 3 * time.Second + } + reconnect := time.Duration(cfg.ReconnectDelay) * time.Second + if reconnect < time.Second { + reconnect = 3 * time.Second + } + for { select { case <-done: @@ -877,7 +918,7 @@ func runCollector(done <-chan struct{}, cfg ClientConfig, dataCh chan<- MachineD } wsURL := "ws://" + cfg.Server + "/ws/agent" - err := collectLoop(done, wsURL, cfg.MachineName, dataCh, statCh) + err := collectLoop(done, wsURL, cfg.MachineName, interval, dataCh, statCh) if err != nil { select { case statCh <- false: @@ -889,12 +930,12 @@ func runCollector(done <-chan struct{}, cfg ClientConfig, dataCh chan<- MachineD select { case <-done: return - case <-time.After(3 * time.Second): + case <-time.After(reconnect): } } } -func collectLoop(done <-chan struct{}, wsURL, name string, dataCh chan<- MachineData, statCh chan<- bool) error { +func collectLoop(done <-chan struct{}, wsURL, name string, interval time.Duration, dataCh chan<- MachineData, statCh chan<- bool) error { conn, _, err := websocket.DefaultDialer.Dial(wsURL, nil) if err != nil { return err @@ -913,8 +954,8 @@ func collectLoop(done <-chan struct{}, wsURL, name string, dataCh chan<- Machine default: } - // 采集 CPU 使用率 (阻塞 ~3s) - perCore, _ := cpu.Percent(3*time.Second, true) + // 采集 CPU 使用率 + perCore, _ := cpu.Percent(interval, true) data := collectAll(name, perCore) @@ -1130,9 +1171,10 @@ func main() { cfg, loaded := loadConfig() if loaded { - fmt.Printf(" [✓] 加载配置: %s\n", configPath()) + fmt.Printf(" [✓] 配置文件: %s\n", configPath()) fmt.Printf(" [✓] 设备名称: %s\n", cfg.MachineName) fmt.Printf(" [✓] 服务端 : %s\n", cfg.Server) + fmt.Printf(" [✓] 采集间隔: %ds\n", cfg.Interval) fmt.Println() }