1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
package main
import (
"fmt"
"os"
"path/filepath"
"time"
"github.com/meshnet-gophers/meshtastic-go"
pb "github.com/meshnet-gophers/meshtastic-go/meshtastic"
)
type DataLogger struct {
data *os.File
text *os.File
}
func NewDataLogger(logsDir string) (*DataLogger, error) {
var err error
var d DataLogger
d.data, err = os.OpenFile(filepath.Join(logsDir, "data.log"), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644)
if err != nil {
d.Close()
return nil, err
}
d.text, err = os.OpenFile(filepath.Join(logsDir, "text.log"), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644)
if err != nil {
d.Close()
return nil, err
}
return &d, nil
}
func (d *DataLogger) Close() error {
if d.data != nil {
d.data.Close()
}
if d.text != nil {
d.text.Close()
}
return nil
}
func formatNodeInfo(ni *pb.NodeInfo) string {
var str string
if ni != nil {
if ni.User != nil && ni.User.Id != "" {
str = fmt.Sprintf("%s (%s) %s", ni.User.Id, ni.User.ShortName, ni.User.LongName)
} else {
str = meshtastic.NodeID(ni.Num).String()
}
} else {
str = "???"
}
return str
}
func (d *DataLogger) LogPacket(p *pb.MeshPacket, c *pb.ChannelSettings, src *pb.NodeInfo, dst *pb.NodeInfo, data *pb.Data, payload any) error {
source := formatNodeInfo(src)
destination := formatNodeInfo(dst)
header := fmt.Sprintf("%s | #%d:%s '%s' >> '%s' [rssi:%d snr:%f hs:%d, hl:%d]", time.Unix(int64(p.RxTime), 0), c.ChannelNum, c.Name, source, destination, p.RxRssi, p.RxSnr, p.HopStart, p.HopLimit)
var s fmt.Stringer
var log string
var logfile *os.File = d.data
switch data.Portnum {
case pb.PortNum_NODEINFO_APP:
s, _ = payload.(*pb.User)
case pb.PortNum_TELEMETRY_APP:
s, _ = payload.(*pb.Telemetry)
case pb.PortNum_POSITION_APP:
s, _ = payload.(*pb.Position)
case pb.PortNum_ROUTING_APP:
s, _ = payload.(*pb.Routing)
case pb.PortNum_TRACEROUTE_APP:
s, _ = payload.(*pb.RouteDiscovery)
case pb.PortNum_AUDIO_APP:
log = fmt.Sprintf("Audio message (%dB, %.2fs@800bps)", len(data.Payload), (float32(len(data.Payload)) / 100.0))
case pb.PortNum_TEXT_MESSAGE_APP:
log = string(data.Payload)
logfile = d.text
default:
log = p.String()
}
if log == "" && s != nil {
log = s.String()
}
if log != "" && logfile != nil {
output := fmt.Sprintf("%s : [%s] %T{ %s }\n", header, data.Portnum, payload, log)
if _, err := logfile.Write([]byte(output)); err != nil {
return err
}
return logfile.Sync()
}
return nil
}
|