diff options
| author | Marin Ivanov <[email protected]> | 2025-09-04 10:23:46 +0300 |
|---|---|---|
| committer | Marin Ivanov <[email protected]> | 2025-09-04 12:00:31 +0300 |
| commit | b551c87b9671d3dc2c5a4b807f9b252cc7fc38b0 (patch) | |
| tree | 1c4d9f3712321be9bd2506aa012e1303924ae62a /node.go | |
| parent | 9897dc711a8e3e1be51a72d5f68f50692b289eeb (diff) | |
Device metrics command and telemetry fix
* feat: execute command to retrieve device metrics
* bugfix: add requestid to (telemetry) reply data
Diffstat (limited to 'node.go')
| -rw-r--r-- | node.go | 91 |
1 files changed, 29 insertions, 62 deletions
@@ -1,18 +1,17 @@ package main import ( - "bufio" "bytes" "context" "crypto/aes" "crypto/rand" "crypto/sha256" "encoding/binary" + "encoding/json" "errors" "fmt" "io" "os/exec" - "strconv" "sync" "time" @@ -81,7 +80,8 @@ type NodeConfig struct { TCPListenAddr string DeviceMetricsBroadcastInterval time.Duration - DeviceMetricsUPSAddress string + DeviceMetricsCommand string + DeviceMetricsCommandArgs []string X25519SecretKey []byte X25519PublicKey []byte } @@ -338,19 +338,17 @@ func (n *Node) nextPacketID() uint32 { return n.packetID } -func (n *Node) txPortnumMessage(channelID uint32, to uint32, portNum pb.PortNum, message proto.Message) error { - payload, err := proto.Marshal(message) - if err != nil { +func (n *Node) txDataMessage(channelID uint32, to uint32, dataIn *pb.Data, message proto.Message) error { + data := proto.Clone(dataIn).(*pb.Data) + var err error + if data.Payload, err = proto.Marshal(message); err != nil { return err } return n.txPacket(&pb.MeshPacket{ - From: n.nodeID, - To: to, - Channel: channelID, - PayloadVariant: &pb.MeshPacket_Decoded{Decoded: &pb.Data{ - Portnum: portNum, - Payload: payload, - }}, + From: n.nodeID, + To: to, + Channel: channelID, + PayloadVariant: &pb.MeshPacket_Decoded{Decoded: data}, }) } @@ -477,7 +475,7 @@ func (n *Node) txPacket(p *pb.MeshPacket) error { func (n *Node) broadcastNodeInfo(ctx context.Context) error { n.logger.Info("(( NodeInfo") - return n.txPortnumMessage(0, broadcastID, pb.PortNum_NODEINFO_APP, n.user) + return n.txDataMessage(0, broadcastID, &pb.Data{Portnum: pb.PortNum_NODEINFO_APP}, n.user) } func (n *Node) getPosition() *pb.Position { @@ -497,59 +495,30 @@ func (n *Node) broadcastPosition(ctx context.Context) error { nodeInfo.Position = position return true }) - return n.txPortnumMessage(0, broadcastID, pb.PortNum_POSITION_APP, position) + return n.txDataMessage(0, broadcastID, &pb.Data{Portnum: pb.PortNum_POSITION_APP}, position) } func (n *Node) getDeviceMetrics() (*pb.DeviceMetrics, error) { + metrics := &pb.DeviceMetrics{ + BatteryLevel: Ptr[uint32](101), + UptimeSeconds: Ptr(uint32(time.Since(n.start).Seconds())), + } + if n.cfg.DeviceMetricsCommand == "" { + return metrics, nil + } cmdStdout := bytes.NewBuffer(nil) - cmd := exec.Command("upsc", n.cfg.DeviceMetricsUPSAddress) + cmd := exec.Command(n.cfg.DeviceMetricsCommand, n.cfg.DeviceMetricsCommandArgs...) cmd.Stdout = cmdStdout - err := cmd.Run() - if err != nil { - n.logger.Error("failed to get UPS data", "err", err) + if err := cmd.Run(); err != nil { + n.logger.Error("failed to get execute DeviceMetrics command", "err", err) return nil, err } stdoutBytes := cmdStdout.Bytes() - stdout := bufio.NewReader(bytes.NewReader(stdoutBytes)) - var batteryLevel uint32 - var voltage float32 - var channelUtilization float32 - var airUtilTx float32 - for { - line, _, err := stdout.ReadLine() - if errors.Is(err, io.EOF) { - break - } - lineValue := bytes.SplitN(line, []byte(": "), 2) - if len(lineValue) != 2 { - continue - } - if bytes.Equal(lineValue[0], []byte("battery.voltage")) { - v, err := strconv.ParseFloat(string(lineValue[1]), 64) - if err != nil { - continue - } - voltage = float32(v) - } - if bytes.Equal(lineValue[0], []byte("battery.charge")) { - charge, err := strconv.ParseUint(string(lineValue[1]), 10, 64) - if err != nil { - continue - } - batteryLevel = uint32(charge) - } - } - if batteryLevel == 100 && voltage > 0 { - batteryLevel = 101 + if err := json.Unmarshal(stdoutBytes, metrics); err != nil { + n.logger.Error("failed to get decode DeviceMetrics json", "err", err) + return nil, err } - uptime := uint32(time.Since(n.start).Seconds()) - return &pb.DeviceMetrics{ - BatteryLevel: &batteryLevel, - Voltage: &voltage, - ChannelUtilization: &channelUtilization, - AirUtilTx: &airUtilTx, - UptimeSeconds: &uptime, - }, nil + return metrics, nil } func (n *Node) broadcastDeviceMetrics(ctx context.Context) error { n.logger.Info("(( DeviceMetrics") @@ -561,10 +530,8 @@ func (n *Node) broadcastDeviceMetrics(ctx context.Context) error { nodeInfo.DeviceMetrics = deviceMetrics return true }) - return n.txPortnumMessage(0, broadcastID, pb.PortNum_TELEMETRY_APP, &pb.Telemetry{ - Variant: &pb.Telemetry_DeviceMetrics{ - DeviceMetrics: deviceMetrics, - }, + return n.txDataMessage(0, broadcastID, &pb.Data{Portnum: pb.PortNum_TELEMETRY_APP}, &pb.Telemetry{ + Variant: &pb.Telemetry_DeviceMetrics{DeviceMetrics: deviceMetrics}, }) } |
