summaryrefslogtreecommitdiff
path: root/datalogger.go
blob: 6cd51063b7eb150cfc01b46b5c2d7ae9622991b6 (plain)
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
}