From 6e88d2392fc4eaa1ecb5f20714b0ac6bbe403dda Mon Sep 17 00:00:00 2001 From: master <727475183@qq.com> Date: Fri, 8 May 2026 16:26:10 +0800 Subject: [PATCH] feat: add dynamic config reload, unique device identity (UUID), and MQTT support - New StreamManager for dynamic RTSP/FLV stream lifecycle - Dynamic worker scaling for inference - Device UUID generation and persistence - Telegraf config and NPU monitoring scripts - .gitignore for build artifacts --- .gitignore | 7 ++ cmd/edge-agent/main.go | 25 ++++-- config/edge.yaml | 12 ++- config/telegraf.conf | 32 ++++++++ go.mod | 14 +++- go.sum | 8 ++ internal/config/config.go | 50 ++++++++++-- internal/control/mqtt_manager.go | 123 +++++++++++++++++++++++++++++ internal/infer/client.go | 77 +++++++++++++----- internal/stream/ingestor.go | 129 ++++++++++++++++++++++--------- model/model.om | Bin 7439090 -> 7439509 bytes scripts/npu_info.sh | 26 +++++++ 12 files changed, 433 insertions(+), 70 deletions(-) create mode 100644 .gitignore create mode 100644 config/telegraf.conf create mode 100644 internal/control/mqtt_manager.go create mode 100644 scripts/npu_info.sh diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2e506fc --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +build/ +logs/ +*.om +*.onnx +test.jpg +fusion_result.json +device.uuid diff --git a/cmd/edge-agent/main.go b/cmd/edge-agent/main.go index 664342d..c54e29a 100644 --- a/cmd/edge-agent/main.go +++ b/cmd/edge-agent/main.go @@ -21,13 +21,14 @@ func main() { flag.Parse() cfg := config.Load(*cfgPath) - log.Printf("edge-agent start id=%s cloud=%s", cfg.EdgeID, cfg.CloudURL) + log.Printf("edge-agent start id=%s uuid=%s cloud=%s mqtt=%s", + cfg.EdgeID, cfg.GetDeviceIdentity(), cfg.CloudURL, cfg.MqttBroker) ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer cancel() - frames := make(chan stream.Frame, 50) - events := make(chan event.SuspectedEvent, 200) + frames := make(chan stream.Frame, 100) + events := make(chan event.SuspectedEvent, 500) var wg sync.WaitGroup run := func(fn func(context.Context)) { @@ -38,11 +39,23 @@ func main() { }() } - run(stream.NewIngestor(cfg, frames).Run) - run(infer.NewClient(cfg, frames, events).Run) + // 1. Cloud Communication + mqttMgr := control.NewMqttManager(cfg) + run(mqttMgr.Run) + + // 2. Stream Ingestion (Dynamic) + run(stream.NewStreamManager(cfg, frames, mqttMgr.GetUpdates()).Run) + + // 3. Inference (Dynamic Workers) + run(infer.NewClient(cfg, frames, events, mqttMgr.GetUpdates()).Run) + + // 4. Event Upload run(event.NewUploader(cfg, events).Run) + + // 5. Heartbeat run(control.NewHeartbeat(cfg).Run) - run(control.NewConfigAgent(cfg).Run) + + // 6. OTA Update run(control.NewOTAAgent(cfg).Run) wg.Wait() diff --git a/config/edge.yaml b/config/edge.yaml index 784978e..32b6093 100644 --- a/config/edge.yaml +++ b/config/edge.yaml @@ -1,13 +1,21 @@ edge_id: edge-demo-001 cloud_url: http://101.36.73.102:8004 +mqtt_broker: "tcp://101.36.73.102:1883" +mqtt_user: "" +mqtt_pass: "" edge_token: "" -# RTSP 流地址(留空使用演示模式) +# 视频流配置 rtsp_urls: [] +# 推理配置 infer_socket: /tmp/edge-infer.sock infer_fps: 5 infer_workers: 3 conf_threshold: 0.5 dedup_window_sec: 30 -version: 1.0.0 + +# OTA 配置 (可选: Hawkbit URL 或 Nginx URL) +ota_url: http://101.36.73.102:8087 + +version: 1.0.0 \ No newline at end of file diff --git a/config/telegraf.conf b/config/telegraf.conf new file mode 100644 index 0000000..49f871a --- /dev/null +++ b/config/telegraf.conf @@ -0,0 +1,32 @@ +[agent] + interval = "10s" + round_interval = true + metric_batch_size = 1000 + metric_buffer_limit = 10000 + flush_interval = "10s" + hostname = "edge-001" # 启动时替换为实际 edge_id + +# 输出到云端 InfluxDB +[[outputs.influxdb_v2]] + urls = ["http://101.36.73.102:18086"] + token = "my-super-secret-token" # 替换为实际 token + organization = "tianyan" + bucket = "edge_metrics" + +# 基础硬件监控 +[[inputs.cpu]] + percpu = false + totalcpu = true + +[[inputs.mem]] + +[[inputs.disk]] + ignore_fs = ["tmpfs", "devtmpfs", "devfs", "overlay", "aufs", "squashfs"] + +[[inputs.net]] + +# NPU 自定义监控 +[[inputs.exec]] + commands = ["/opt/tianyan-edge/scripts/npu_info.sh"] + timeout = "5s" + data_format = "influx" \ No newline at end of file diff --git a/go.mod b/go.mod index 4bb9890..bba98a7 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,15 @@ module tianyan-edge -go 1.22 +go 1.18 -require gopkg.in/yaml.v3 v3.0.1 +require ( + github.com/eclipse/paho.mqtt.golang v1.4.3 + gopkg.in/yaml.v3 v3.0.1 +) -require gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect +require ( + github.com/gorilla/websocket v1.5.0 // indirect + golang.org/x/net v0.8.0 // indirect + golang.org/x/sync v0.1.0 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect +) diff --git a/go.sum b/go.sum index 33d593e..084e15e 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,16 @@ +github.com/eclipse/paho.mqtt.golang v1.4.3 h1:2kwcUGn8seMUfWndX0hGbvH8r7crgcJguQNCyp70xik= +github.com/eclipse/paho.mqtt.golang v1.4.3/go.mod h1:CSYvoAlsMkhYOXh/oKyxa8EcBci6dVkLCbo5tTC1RIE= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/internal/config/config.go b/internal/config/config.go index ced1260..ea2b8d3 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -1,14 +1,21 @@ package config import ( + "crypto/rand" + "encoding/hex" "os" + "path/filepath" "gopkg.in/yaml.v3" ) type Config struct { + DeviceUUID string `yaml:"device_uuid"` EdgeID string `yaml:"edge_id"` CloudURL string `yaml:"cloud_url"` + MqttBroker string `yaml:"mqtt_broker"` + MqttUser string `yaml:"mqtt_user"` + MqttPass string `yaml:"mqtt_pass"` EdgeToken string `yaml:"edge_token"` RTSPURLs []string `yaml:"rtsp_urls"` InferSocket string `yaml:"infer_socket"` @@ -16,12 +23,14 @@ type Config struct { InferWorkers int `yaml:"infer_workers"` ConfThreshold float64 `yaml:"conf_threshold"` DedupWindowSec int `yaml:"dedup_window_sec"` + OTAUrl string `yaml:"ota_url"` Version string `yaml:"version"` + configPath string `json:"-"` } func Load(path string) *Config { cfg := &Config{ - EdgeID: "edge-demo-001", + EdgeID: "edge-unknown", CloudURL: "http://localhost:8004", InferSocket: "/tmp/edge-infer.sock", InferFPS: 5, @@ -29,12 +38,15 @@ func Load(path string) *Config { ConfThreshold: 0.5, DedupWindowSec: 30, Version: "1.0.0", + configPath: path, } - data, err := os.ReadFile(path) - if err != nil { - return cfg + + cfg.loadUUID() + + if data, err := os.ReadFile(path); err == nil { + _ = yaml.Unmarshal(data, cfg) } - _ = yaml.Unmarshal(data, cfg) + if cfg.InferWorkers <= 0 { cfg.InferWorkers = 1 } @@ -43,3 +55,31 @@ func Load(path string) *Config { } return cfg } + +func (c *Config) loadUUID() { + uuidPath := "/opt/tianyan-edge/device.uuid" + if data, err := os.ReadFile(uuidPath); err == nil { + c.DeviceUUID = string(data) + } else { + b := make([]byte, 16) + rand.Read(b) + c.DeviceUUID = hex.EncodeToString(b) + os.MkdirAll(filepath.Dir(uuidPath), 0755) + os.WriteFile(uuidPath, []byte(c.DeviceUUID), 0644) + } +} + +func (c *Config) Save() error { + data, err := yaml.Marshal(c) + if err != nil { + return err + } + return os.WriteFile(c.configPath, data, 0644) +} + +func (c *Config) GetDeviceIdentity() string { + if c.DeviceUUID != "" { + return c.DeviceUUID + } + return c.EdgeID +} diff --git a/internal/control/mqtt_manager.go b/internal/control/mqtt_manager.go new file mode 100644 index 0000000..6c27de3 --- /dev/null +++ b/internal/control/mqtt_manager.go @@ -0,0 +1,123 @@ +package control + +import ( + "context" + "encoding/json" + "fmt" + "log" + "time" + + mqtt "github.com/eclipse/paho.mqtt.golang" + "tianyan-edge/internal/config" +) + +type MqttManager struct { + client mqtt.Client + cfg *config.Config + updates chan *config.Config // Channel to broadcast config updates +} + +func NewMqttManager(cfg *config.Config) *MqttManager { + return &MqttManager{ + cfg: cfg, + updates: make(chan *config.Config, 10), + } +} + +func (m *MqttManager) Run(ctx context.Context) { + if m.cfg.MqttBroker == "" { + log.Println("mqtt: no broker configured, skipping") + return + } + + opts := mqtt.NewClientOptions() + opts.AddBroker(m.cfg.MqttBroker) + opts.SetClientID(m.cfg.GetDeviceIdentity()) + opts.SetUsername(m.cfg.MqttUser) + opts.SetPassword(m.cfg.MqttPass) + opts.SetAutoReconnect(true) + opts.SetMaxReconnectInterval(1 * time.Minute) + + // LWT + willTopic := fmt.Sprintf("tianyan/edge/%s/status", m.cfg.GetDeviceIdentity()) + opts.SetWill(willTopic, "offline", 1, true) + + opts.SetOnConnectHandler(func(c mqtt.Client) { + log.Println("mqtt: connected to broker") + c.Publish(willTopic, 1, true, "online") + configTopic := fmt.Sprintf("tianyan/edge/%s/config", m.cfg.GetDeviceIdentity()) + token := c.Subscribe(configTopic, 1, m.handleConfigUpdate) + token.Wait() + if token.Error() != nil { + log.Printf("mqtt: subscribe failed: %v", token.Error()) + } else { + log.Printf("mqtt: subscribed to %s", configTopic) + } + }) + + m.client = mqtt.NewClient(opts) + if token := m.client.Connect(); token.Wait() && token.Error() != nil { + log.Printf("mqtt: connect error: %v", token.Error()) + } + + <-ctx.Done() + m.client.Disconnect(1000) + log.Println("mqtt: disconnected") +} + +func (m *MqttManager) handleConfigUpdate(c mqtt.Client, msg mqtt.Message) { + log.Printf("mqtt: received config update on %s", msg.Topic()) + var newCfg map[string]interface{} + if err := json.Unmarshal(msg.Payload(), &newCfg); err != nil { + log.Printf("mqtt: config parse error: %v", err) + return + } + + // Update local config struct + if v, ok := newCfg["infer_fps"].(float64); ok { + m.cfg.InferFPS = int(v) + } + if v, ok := newCfg["conf_threshold"].(float64); ok { + m.cfg.ConfThreshold = v + } + if v, ok := newCfg["infer_workers"].(float64); ok { + m.cfg.InferWorkers = int(v) + } + if v, ok := newCfg["rtsp_urls"]; ok { + if urls, ok := v.([]interface{}); ok { + var s []string + for _, u := range urls { + if str, ok := u.(string); ok { + s = append(s, str) + } + } + m.cfg.RTSPURLs = s + } + } + + // Save to disk + if err := m.cfg.Save(); err != nil { + log.Printf("mqtt: failed to save config: %v", err) + } else { + log.Println("mqtt: config saved to disk") + } + + // Broadcast update to other components + select { + case m.updates <- m.cfg: + default: + log.Println("mqtt: update channel full, dropping update") + } +} + +func (m *MqttManager) GetUpdates() <-chan *config.Config { + return m.updates +} + +func (m *MqttManager) Publish(topic string, payload interface{}) { + if m.client == nil || !m.client.IsConnected() { + return + } + data, _ := json.Marshal(payload) + m.client.Publish(topic, 1, false, data) +} diff --git a/internal/infer/client.go b/internal/infer/client.go index 97b61a3..c1c2a9b 100644 --- a/internal/infer/client.go +++ b/internal/infer/client.go @@ -46,31 +46,75 @@ type dedupState struct { } type Client struct { - cfg *config.Config - frames <-chan stream.Frame - events chan<- event.SuspectedEvent - dedup *dedupState + cfg *config.Config + frames <-chan stream.Frame + events chan<- event.SuspectedEvent + dedup *dedupState + updates <-chan *config.Config } -func NewClient(cfg *config.Config, frames <-chan stream.Frame, events chan<- event.SuspectedEvent) *Client { +func NewClient(cfg *config.Config, frames <-chan stream.Frame, events chan<- event.SuspectedEvent, updates <-chan *config.Config) *Client { return &Client{ - cfg: cfg, - frames: frames, - events: events, - dedup: &dedupState{seen: make(map[string]float64)}, + cfg: cfg, + frames: frames, + events: events, + dedup: &dedupState{seen: make(map[string]float64)}, + updates: updates, } } func (c *Client) Run(ctx context.Context) { var wg sync.WaitGroup - for i := 0; i < c.cfg.InferWorkers; i++ { + + // Worker management loop + numWorkers := c.cfg.InferWorkers + activeWorkers := make([]context.CancelFunc, numWorkers) + + for i := 0; i < numWorkers; i++ { + workerCtx, cancel := context.WithCancel(ctx) + activeWorkers[i] = cancel wg.Add(1) - go func(workerID int) { + go func(id int, wCtx context.Context) { defer wg.Done() - c.workerLoop(ctx, workerID) - }(i) + c.workerLoop(wCtx, id) + }(i, workerCtx) + } + + for { + select { + case <-ctx.Done(): + for _, cancel := range activeWorkers { + cancel() + } + wg.Wait() + return + case newCfg := <-c.updates: + c.cfg = newCfg + target := c.cfg.InferWorkers + if target < 0 { + target = 0 + } + + // Scale up + for i := len(activeWorkers); i < target; i++ { + workerCtx, cancel := context.WithCancel(ctx) + activeWorkers = append(activeWorkers, cancel) + wg.Add(1) + go func(id int, wCtx context.Context) { + defer wg.Done() + c.workerLoop(wCtx, id) + }(i, workerCtx) + } + // Scale down + if target < len(activeWorkers) { + for i := target; i < len(activeWorkers); i++ { + activeWorkers[i]() + } + activeWorkers = activeWorkers[:target] + } + log.Printf("infer: workers scaled to %d", target) + } } - wg.Wait() } func (c *Client) workerLoop(ctx context.Context, workerID int) { @@ -89,10 +133,9 @@ func (c *Client) workerLoop(ctx context.Context, workerID int) { log.Printf("infer[w%d]: socket connected", workerID) if !c.loop(ctx, conn, workerID) { conn.Close() - return + time.Sleep(1 * time.Second) } conn.Close() - time.Sleep(500 * time.Millisecond) } } @@ -103,12 +146,10 @@ func (c *Client) loop(ctx context.Context, conn net.Conn, workerID int) bool { return false case f := <-c.frames: if err := c.send(conn, f); err != nil { - log.Printf("infer[w%d]: send error: %v", workerID, err) return true } res, err := c.recv(conn) if err != nil { - log.Printf("infer[w%d]: recv error: %v", workerID, err) return true } c.emitEvents(f, res) diff --git a/internal/stream/ingestor.go b/internal/stream/ingestor.go index 38825a1..5e55ebd 100644 --- a/internal/stream/ingestor.go +++ b/internal/stream/ingestor.go @@ -1,7 +1,6 @@ package stream import ( - "bytes" "context" "fmt" "io" @@ -10,6 +9,8 @@ import ( "sync" "time" + "bytes" + "tianyan-edge/internal/config" ) @@ -21,63 +22,109 @@ type Frame struct { TS float64 } -type Ingestor struct { - cfg *config.Config - frames chan<- Frame +type StreamManager struct { + cfg *config.Config + frames chan<- Frame + processes map[string]*exec.Cmd + mu sync.Mutex + updates <-chan *config.Config } -func NewIngestor(cfg *config.Config, frames chan<- Frame) *Ingestor { - return &Ingestor{cfg: cfg, frames: frames} -} - -func (ing *Ingestor) Run(ctx context.Context) { - if len(ing.cfg.RTSPURLs) == 0 { - log.Println("stream: no RTSP URLs configured, idle") - <-ctx.Done() - return +func NewStreamManager(cfg *config.Config, frames chan<- Frame, updates <-chan *config.Config) *StreamManager { + return &StreamManager{ + cfg: cfg, + frames: frames, + processes: make(map[string]*exec.Cmd), + updates: updates, } - var wg sync.WaitGroup - for i, url := range ing.cfg.RTSPURLs { - wg.Add(1) - go func(idx int, u string) { - defer wg.Done() - ing.streamLoop(ctx, idx, u) - }(i, url) - } - wg.Wait() } -func (ing *Ingestor) streamLoop(ctx context.Context, idx int, url string) { +func (sm *StreamManager) Run(ctx context.Context) { + // Initial start + sm.applyStreams(ctx, sm.cfg.RTSPURLs) + + for { + select { + case <-ctx.Done(): + sm.stopAll() + return + case newCfg := <-sm.updates: + log.Printf("stream: applying new config, urls=%d", len(newCfg.RTSPURLs)) + sm.applyStreams(ctx, newCfg.RTSPURLs) + } + } +} + +func (sm *StreamManager) applyStreams(ctx context.Context, urls []string) { + sm.mu.Lock() + defer sm.mu.Unlock() + + // Identify URLs to remove (present in sm.processes but not in new urls) + toRemove := map[string]*exec.Cmd{} + for url, cmd := range sm.processes { + found := false + for _, u := range urls { + if u == url { + found = true + break + } + } + if !found { + toRemove[url] = cmd + } + } + + // Stop removed streams + for url, cmd := range toRemove { + log.Printf("stream: stopping %s", url) + cmd.Process.Kill() + cmd.Wait() + delete(sm.processes, url) + } + + // Start new streams + for i, url := range urls { + if _, exists := sm.processes[url]; !exists { + go sm.streamLoop(ctx, i, url) + } + } +} + +func (sm *StreamManager) streamLoop(ctx context.Context, idx int, url string) { deviceID := fmt.Sprintf("cam-%03d", idx) - fps := ing.cfg.InferFPS - if fps <= 0 { - fps = 5 - } for { select { case <-ctx.Done(): return default: } + cmd := exec.CommandContext(ctx, "ffmpeg", - "-rtsp_transport", "tcp", "-i", url, - "-vf", fmt.Sprintf("fps=%d", fps), + "-i", url, + "-vf", fmt.Sprintf("fps=%d", sm.cfg.InferFPS), "-f", "image2pipe", "-vcodec", "mjpeg", "-q:v", "5", "-", ) stdout, err := cmd.StdoutPipe() if err != nil { - log.Printf("stream[%d] stdout pipe failed: %v, retry 10s", idx, err) - time.Sleep(10 * time.Second) + log.Printf("stream[%d] stdout pipe failed: %v", idx, err) + time.Sleep(5 * time.Second) continue } + + sm.mu.Lock() + sm.processes[url] = cmd + sm.mu.Unlock() + if err := cmd.Start(); err != nil { - log.Printf("stream[%d] ffmpeg start failed: %v, retry 10s", idx, err) - time.Sleep(10 * time.Second) + log.Printf("stream[%d] start failed: %v", idx, err) + time.Sleep(5 * time.Second) continue } + log.Printf("stream[%d] connected url=%s", idx, url) - ing.readFrames(ctx, stdout, idx, deviceID, url) + sm.readFrames(ctx, stdout, idx, deviceID, url) cmd.Wait() + select { case <-ctx.Done(): return @@ -88,7 +135,7 @@ func (ing *Ingestor) streamLoop(ctx context.Context, idx int, url string) { } } -func (ing *Ingestor) readFrames(ctx context.Context, r io.Reader, idx int, deviceID, url string) { +func (sm *StreamManager) readFrames(ctx context.Context, r io.Reader, idx int, deviceID, url string) { soi, eoi := []byte{0xFF, 0xD8}, []byte{0xFF, 0xD9} buf, tmp := make([]byte, 0, 1<<20), make([]byte, 32768) for { @@ -116,7 +163,7 @@ func (ing *Ingestor) readFrames(ctx context.Context, r io.Reader, idx int, devic copy(frame, buf[:end]) buf = buf[end:] select { - case ing.frames <- Frame{StreamID: idx, DeviceID: deviceID, URL: url, + case sm.frames <- Frame{StreamID: idx, DeviceID: deviceID, URL: url, JPEG: frame, TS: float64(time.Now().UnixMilli()) / 1000.0}: default: } @@ -127,3 +174,13 @@ func (ing *Ingestor) readFrames(ctx context.Context, r io.Reader, idx int, devic } } } + +func (sm *StreamManager) stopAll() { + sm.mu.Lock() + defer sm.mu.Unlock() + for url, cmd := range sm.processes { + log.Printf("stream: stopping all %s", url) + cmd.Process.Kill() + delete(sm.processes, url) + } +} diff --git a/model/model.om b/model/model.om index 90a245604ad13e849ed6e0a255a79da81e00972a..fd5912b1aac47d9ffee5d8a94a67d03e5a58f7bd 100644 GIT binary patch delta 101054 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 v4v7^zR4S*mD5XOs3Yx%m`8PfOy!xXY&}WwV$/dev/null) +MEM_OUTPUT=$(/usr/local/sbin/npu-smi info -t memory -i 0 2>/dev/null) + +TEMP=$(echo "$COMMON_OUTPUT" | grep "Temperature(C)" | awk '{print $NF}') +UTIL=$(echo "$COMMON_OUTPUT" | grep "Aicore Usage Rate" | awk '{print $NF}') +MEM_TOTAL_MB=$(echo "$MEM_OUTPUT" | grep "Capacity(MB)" | awk '{print $NF}') +MEM_RATE=$(echo "$COMMON_OUTPUT" | grep "Memory Usage Rate" | awk '{print $NF}') + +# 计算实际使用量 (使用 awk 代替 bc) +if [ -n "$MEM_TOTAL_MB" ] && [ -n "$MEM_RATE" ]; then + MEM_USED_MB=$(awk "BEGIN {printf \"%d\", $MEM_TOTAL_MB * $MEM_RATE / 100}") +else + MEM_TOTAL_MB=0 + MEM_USED_MB=0 + UTIL=0 + TEMP=0 +fi + +# 默认值保护 +TEMP=${TEMP:-0} +UTIL=${UTIL:-0} + +echo "npu_status,device=0 temp=${TEMP},utilization=${UTIL},memory_used=${MEM_USED_MB:-0},memory_total=${MEM_TOTAL_MB:-0}"