Refactor protos

This commit is contained in:
Daniel Pupius
2025-04-21 15:40:10 -07:00
parent 41ee61b59a
commit 86380cccf9
59 changed files with 1477 additions and 1283 deletions

2
.gitignore vendored
View File

@@ -72,4 +72,4 @@ temp/
# Binary output type
meshstream
#meshstream

View File

@@ -1,3 +1,6 @@
{
"cSpell.words": ["meshstream", "Motherlode", "mqtt"]
"cSpell.words": ["meshstream", "Motherlode", "mqtt"],
"protoc": {
"options": ["-Iproto"]
}
}

View File

@@ -1,11 +1,14 @@
.PHONY: build run gen-proto clean tools
ROOT_DIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
# Build directories
BIN_DIR := bin
TOOLS_DIR := $(BIN_DIR)/tools
# Tool commands
# Proto compilation
PROTOC_GEN_GO := $(TOOLS_DIR)/protoc-gen-go
PROTO_FILES := $(shell find $(ROOT_DIR) -name "*.proto" | sed 's|$(ROOT_DIR)/||' )
# Build the application
build:
@@ -18,12 +21,13 @@ run: build
# Generate Go code from Protocol Buffers
gen-proto: tools
mkdir -p proto/generated
@mkdir -p $(ROOT_DIR)/generated
PATH="$(TOOLS_DIR):$$PATH" protoc \
-I./proto \
--go_out=./proto/generated \
-Iproto/ \
--go_out=generated/ \
--go_opt=paths=source_relative \
./proto/meshtastic/*.proto
$(PROTO_FILES)
@echo "Generated Go code from Protocol Buffers"
# Clean generated files
clean:

View File

@@ -1,62 +1,18 @@
package decoder
import (
"encoding/json"
"fmt"
"strings"
"google.golang.org/protobuf/proto"
mesh "meshstream/proto/generated"
pb "meshstream/proto/generated/meshtastic"
)
// DecodedPacket provides a simplified structure for decoded Meshtastic packets
type DecodedPacket struct {
// From Service Envelope
ChannelID string
GatewayID string
// From Mesh Packet
ID uint32
From uint32
To uint32
HopLimit uint32
HopStart uint32
WantACK bool
Priority string
ViaMQTT bool
NextHop uint32
RelayNode uint32
// From Data
PortNum pb.PortNum
Payload interface{}
// Additional Data fields
RequestID uint32
ReplyID uint32
Emoji uint32
Dest uint32
Source uint32
WantResponse bool
// Error tracking
DecodeError error
}
// TopicInfo contains parsed information about a Meshtastic MQTT topic
type TopicInfo struct {
FullTopic string
RegionPath string
Version string
Format string
Channel string
UserID string
}
// ParseTopic parses a Meshtastic MQTT topic into its components
func ParseTopic(topic string) (*TopicInfo, error) {
info := &TopicInfo{
func ParseTopic(topic string) (*mesh.TopicInfo, error) {
info := &mesh.TopicInfo{
FullTopic: topic,
}
@@ -71,7 +27,7 @@ func ParseTopic(topic string) (*TopicInfo, error) {
// Find protocol version and format indices by looking for "2" followed by "e" or "json"
versionIndex := -1
formatIndex := -1
for i := 1; i < len(parts)-1; i++ {
if parts[i] == "2" {
// Found the version
@@ -80,33 +36,33 @@ func ParseTopic(topic string) (*TopicInfo, error) {
break
}
}
if versionIndex == -1 || formatIndex >= len(parts) {
// Could not find proper version/format markers
return info, fmt.Errorf("invalid topic format, missing version/format: %s", topic)
}
// Extract region path (all segments between "msh" and version)
if versionIndex > 1 {
info.RegionPath = strings.Join(parts[1:versionIndex], "/")
}
// Extract version and format
info.Version = parts[versionIndex]
info.Format = parts[formatIndex]
// Extract channel and user ID
channelIndex := formatIndex + 1
userIdIndex := channelIndex + 1
if channelIndex < len(parts) {
info.Channel = parts[channelIndex]
}
if userIdIndex < len(parts) {
info.UserID = parts[userIdIndex]
info.UserId = parts[userIdIndex]
}
return info, nil
}
@@ -120,43 +76,39 @@ func DecodeEncodedMessage(payload []byte) (*pb.ServiceEnvelope, error) {
}
// DecodeMessage creates a DecodedPacket from a binary encoded message
func DecodeMessage(payload []byte, topicInfo *TopicInfo) *DecodedPacket {
decoded := &DecodedPacket{}
func DecodeMessage(payload []byte, topicInfo *mesh.TopicInfo) *mesh.DecodedPacket {
decoded := &mesh.DecodedPacket{}
// First decode the envelope
envelope, err := DecodeEncodedMessage(payload)
if err != nil {
decoded.DecodeError = err
decoded.DecodeError = err.Error()
return decoded
}
// Extract envelope fields without storing raw envelope
// Extract envelope fields
decoded.ChannelID = envelope.GetChannelId()
decoded.GatewayID = envelope.GetGatewayId()
decoded.ChannelId = envelope.GetChannelId()
decoded.GatewayId = envelope.GetGatewayId()
// Extract mesh packet fields if available
packet := envelope.GetPacket()
if packet == nil {
decoded.DecodeError = fmt.Errorf("no mesh packet in envelope")
decoded.DecodeError = "no mesh packet in envelope"
return decoded
}
// Extract mesh packet fields without storing raw packet
// Extract mesh packet fields
decoded.ID = packet.GetId()
decoded.Id = packet.GetId()
decoded.From = packet.GetFrom()
decoded.To = packet.GetTo()
decoded.HopLimit = packet.GetHopLimit()
decoded.HopStart = packet.GetHopStart()
decoded.WantACK = packet.GetWantAck()
decoded.WantAck = packet.GetWantAck()
decoded.Priority = packet.GetPriority().String()
decoded.ViaMQTT = packet.GetViaMqtt()
decoded.ViaMqtt = packet.GetViaMqtt()
decoded.NextHop = packet.GetNextHop()
decoded.RelayNode = packet.GetRelayNode()
// Process the payload
if packet.GetDecoded() != nil {
// Packet has already been decoded
@@ -165,132 +117,153 @@ func DecodeMessage(payload []byte, topicInfo *TopicInfo) *DecodedPacket {
// Packet is encrypted, try to decrypt it
decodeEncryptedPayload(decoded, packet.GetEncrypted(), envelope.GetChannelId(), packet.GetId(), packet.GetFrom())
} else {
decoded.DecodeError = fmt.Errorf("packet has no payload")
decoded.DecodeError = "packet has no payload"
}
return decoded
}
// decodeDataPayload extracts information from a Data message
func decodeDataPayload(decoded *DecodedPacket, data *pb.Data) {
// Extract data fields without storing raw data
func decodeDataPayload(decoded *mesh.DecodedPacket, data *pb.Data) {
// Extract data fields
decoded.PortNum = data.GetPortnum()
decoded.RequestID = data.GetRequestId()
decoded.ReplyID = data.GetReplyId()
decoded.RequestId = data.GetRequestId()
decoded.ReplyId = data.GetReplyId()
decoded.Emoji = data.GetEmoji()
decoded.Dest = data.GetDest()
decoded.Source = data.GetSource()
decoded.WantResponse = data.GetWantResponse()
// Process the payload based on port type
payload := data.GetPayload()
switch data.GetPortnum() {
case pb.PortNum_TEXT_MESSAGE_APP:
// Text message - just use the string
decoded.Payload = string(payload)
// Text message - store as string
decoded.Payload = &mesh.DecodedPacket_TextMessage{
TextMessage: string(payload),
}
case pb.PortNum_TEXT_MESSAGE_COMPRESSED_APP:
// Compressed text - just store the raw bytes for now
// TODO: Add decompression support
decoded.Payload = payload
// Compressed text - store the raw bytes
decoded.Payload = &mesh.DecodedPacket_CompressedText{
CompressedText: payload,
}
case pb.PortNum_POSITION_APP:
// Position data
var position pb.Position
if err := proto.Unmarshal(payload, &position); err != nil {
decoded.DecodeError = fmt.Errorf("failed to unmarshal Position data: %v", err)
decoded.DecodeError = fmt.Sprintf("failed to unmarshal Position data: %v", err)
} else {
decoded.Payload = &position
decoded.Payload = &mesh.DecodedPacket_Position{
Position: &position,
}
}
case pb.PortNum_NODEINFO_APP:
// Node information
var user pb.User
if err := proto.Unmarshal(payload, &user); err != nil {
decoded.DecodeError = fmt.Errorf("failed to unmarshal User data: %v", err)
decoded.DecodeError = fmt.Sprintf("failed to unmarshal User data: %v", err)
} else {
decoded.Payload = &user
decoded.Payload = &mesh.DecodedPacket_NodeInfo{
NodeInfo: &user,
}
}
case pb.PortNum_TELEMETRY_APP:
// Telemetry data
var telemetry pb.Telemetry
if err := proto.Unmarshal(payload, &telemetry); err != nil {
decoded.DecodeError = fmt.Errorf("failed to unmarshal Telemetry data: %v", err)
decoded.DecodeError = fmt.Sprintf("failed to unmarshal Telemetry data: %v", err)
} else {
decoded.Payload = &telemetry
decoded.Payload = &mesh.DecodedPacket_Telemetry{
Telemetry: &telemetry,
}
}
case pb.PortNum_WAYPOINT_APP:
// Waypoint data
var waypoint pb.Waypoint
if err := proto.Unmarshal(payload, &waypoint); err != nil {
decoded.DecodeError = fmt.Errorf("failed to unmarshal Waypoint data: %v", err)
decoded.DecodeError = fmt.Sprintf("failed to unmarshal Waypoint data: %v", err)
} else {
decoded.Payload = &waypoint
decoded.Payload = &mesh.DecodedPacket_Waypoint{
Waypoint: &waypoint,
}
}
case pb.PortNum_MAP_REPORT_APP:
// Map report data
var mapReport pb.MapReport
if err := proto.Unmarshal(payload, &mapReport); err != nil {
decoded.DecodeError = fmt.Errorf("failed to unmarshal MapReport data: %v", err)
decoded.DecodeError = fmt.Sprintf("failed to unmarshal MapReport data: %v", err)
} else {
decoded.Payload = &mapReport
decoded.Payload = &mesh.DecodedPacket_MapReport{
MapReport: &mapReport,
}
}
case pb.PortNum_TRACEROUTE_APP:
// Traceroute data
var routeDiscovery pb.RouteDiscovery
if err := proto.Unmarshal(payload, &routeDiscovery); err != nil {
decoded.DecodeError = fmt.Errorf("failed to unmarshal RouteDiscovery data: %v", err)
decoded.DecodeError = fmt.Sprintf("failed to unmarshal RouteDiscovery data: %v", err)
} else {
decoded.Payload = &routeDiscovery
decoded.Payload = &mesh.DecodedPacket_RouteDiscovery{
RouteDiscovery: &routeDiscovery,
}
}
case pb.PortNum_NEIGHBORINFO_APP:
// Neighbor information data
var neighborInfo pb.NeighborInfo
if err := proto.Unmarshal(payload, &neighborInfo); err != nil {
decoded.DecodeError = fmt.Errorf("failed to unmarshal NeighborInfo data: %v", err)
decoded.DecodeError = fmt.Sprintf("failed to unmarshal NeighborInfo data: %v", err)
} else {
decoded.Payload = &neighborInfo
decoded.Payload = &mesh.DecodedPacket_NeighborInfo{
NeighborInfo: &neighborInfo,
}
}
default:
// For other types, just store the raw bytes
decoded.Payload = payload
decoded.Payload = &mesh.DecodedPacket_BinaryData{
BinaryData: payload,
}
}
}
// decodeEncryptedPayload tries to decrypt and decode encrypted payloads
func decodeEncryptedPayload(decoded *DecodedPacket, encrypted []byte, channelId string, packetId, fromNode uint32) {
func decodeEncryptedPayload(decoded *mesh.DecodedPacket, encrypted []byte, channelId string, packetId, fromNode uint32) {
// Attempt to decrypt the payload using the channel key
if channelId == "" {
decoded.DecodeError = fmt.Errorf("encrypted packet has no channel ID")
decoded.DecodeError = "encrypted packet has no channel ID"
return
}
channelKey := GetChannelKey(channelId)
decrypted, err := XOR(encrypted, channelKey, packetId, fromNode)
if err != nil {
decoded.DecodeError = fmt.Errorf("failed to decrypt payload: %v", err)
decoded.DecodeError = fmt.Sprintf("failed to decrypt payload: %v", err)
return
}
// Try to parse as a Data message
var data pb.Data
if err := proto.Unmarshal(decrypted, &data); err != nil {
// If we can't parse as Data, check if it's ASCII text
if IsASCII(decrypted) {
decoded.PortNum = pb.PortNum_TEXT_MESSAGE_APP
decoded.Payload = string(decrypted)
decoded.Payload = &mesh.DecodedPacket_TextMessage{
TextMessage: string(decrypted),
}
} else {
decoded.DecodeError = fmt.Errorf("failed to parse decrypted data: %v", err)
decoded.Payload = decrypted // Store raw bytes anyway
decoded.DecodeError = fmt.Sprintf("failed to parse decrypted data: %v", err)
decoded.Payload = &mesh.DecodedPacket_BinaryData{
BinaryData: decrypted,
}
}
} else {
// Successfully decoded the payload
@@ -298,15 +271,6 @@ func decodeEncryptedPayload(decoded *DecodedPacket, encrypted []byte, channelId
}
}
// DecodeJSONMessage decodes a JSON message (format "json")
func DecodeJSONMessage(payload []byte) (map[string]interface{}, error) {
var jsonData map[string]interface{}
if err := json.Unmarshal(payload, &jsonData); err != nil {
return nil, fmt.Errorf("failed to parse JSON: %v", err)
}
return jsonData, nil
}
// IsASCII checks if the given byte array contains only ASCII characters
func IsASCII(data []byte) bool {
for _, b := range data {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -4,7 +4,7 @@
// protoc v5.29.3
// source: meshtastic/admin.proto
package generated
package meshtastic
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
@@ -1408,8 +1408,8 @@ const file_meshtastic_admin_proto_rawDesc = "" +
"\n" +
"short_name\x18\x04 \x01(\tR\tshortName\"~\n" +
"\x1eNodeRemoteHardwarePinsResponse\x12\\\n" +
"\x19node_remote_hardware_pins\x18\x01 \x03(\v2!.meshtastic.NodeRemoteHardwarePinR\x16nodeRemoteHardwarePinsB`\n" +
"\x13com.geeksville.meshB\vAdminProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
"\x19node_remote_hardware_pins\x18\x01 \x03(\v2!.meshtastic.NodeRemoteHardwarePinR\x16nodeRemoteHardwarePinsB]\n" +
"\x13com.geeksville.meshB\vAdminProtosZ\x1fmeshstream/generated/meshtastic\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
var (
file_meshtastic_admin_proto_rawDescOnce sync.Once

View File

@@ -4,7 +4,7 @@
// protoc v5.29.3
// source: meshtastic/apponly.proto
package generated
package meshtastic
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
@@ -90,8 +90,8 @@ const file_meshtastic_apponly_proto_rawDesc = "" +
"ChannelSet\x127\n" +
"\bsettings\x18\x01 \x03(\v2\x1b.meshtastic.ChannelSettingsR\bsettings\x12>\n" +
"\vlora_config\x18\x02 \x01(\v2\x1d.meshtastic.Config.LoRaConfigR\n" +
"loraConfigBb\n" +
"\x13com.geeksville.meshB\rAppOnlyProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
"loraConfigB_\n" +
"\x13com.geeksville.meshB\rAppOnlyProtosZ\x1fmeshstream/generated/meshtastic\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
var (
file_meshtastic_apponly_proto_rawDescOnce sync.Once

View File

@@ -4,7 +4,7 @@
// protoc v5.29.3
// source: meshtastic/atak.proto
package generated
package meshtastic
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
@@ -720,9 +720,9 @@ const file_meshtastic_atak_proto_rawDesc = "" +
"\x05Medic\x10\x05\x12\x13\n" +
"\x0fForwardObserver\x10\x06\x12\a\n" +
"\x03RTO\x10\a\x12\x06\n" +
"\x02K9\x10\bB_\n" +
"\x02K9\x10\bB\\\n" +
"\x13com.geeksville.meshB\n" +
"ATAKProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
"ATAKProtosZ\x1fmeshstream/generated/meshtastic\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
var (
file_meshtastic_atak_proto_rawDescOnce sync.Once

View File

@@ -4,7 +4,7 @@
// protoc v5.29.3
// source: meshtastic/cannedmessages.proto
package generated
package meshtastic
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
@@ -74,8 +74,8 @@ const file_meshtastic_cannedmessages_proto_rawDesc = "" +
"\x1fmeshtastic/cannedmessages.proto\x12\n" +
"meshtastic\"7\n" +
"\x19CannedMessageModuleConfig\x12\x1a\n" +
"\bmessages\x18\x01 \x01(\tR\bmessagesBn\n" +
"\x13com.geeksville.meshB\x19CannedMessageConfigProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
"\bmessages\x18\x01 \x01(\tR\bmessagesBk\n" +
"\x13com.geeksville.meshB\x19CannedMessageConfigProtosZ\x1fmeshstream/generated/meshtastic\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
var (
file_meshtastic_cannedmessages_proto_rawDescOnce sync.Once

View File

@@ -4,7 +4,7 @@
// protoc v5.29.3
// source: meshtastic/channel.proto
package generated
package meshtastic
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
@@ -373,8 +373,8 @@ const file_meshtastic_channel_proto_rawDesc = "" +
"\x04Role\x12\f\n" +
"\bDISABLED\x10\x00\x12\v\n" +
"\aPRIMARY\x10\x01\x12\r\n" +
"\tSECONDARY\x10\x02Bb\n" +
"\x13com.geeksville.meshB\rChannelProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
"\tSECONDARY\x10\x02B_\n" +
"\x13com.geeksville.meshB\rChannelProtosZ\x1fmeshstream/generated/meshtastic\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
var (
file_meshtastic_channel_proto_rawDescOnce sync.Once

View File

@@ -4,7 +4,7 @@
// protoc v5.29.3
// source: meshtastic/clientonly.proto
package generated
package meshtastic
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
@@ -156,8 +156,8 @@ const file_meshtastic_clientonly_proto_rawDesc = "" +
"\x0e_module_configB\x11\n" +
"\x0f_fixed_positionB\v\n" +
"\t_ringtoneB\x12\n" +
"\x10_canned_messagesBe\n" +
"\x13com.geeksville.meshB\x10ClientOnlyProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
"\x10_canned_messagesBb\n" +
"\x13com.geeksville.meshB\x10ClientOnlyProtosZ\x1fmeshstream/generated/meshtastic\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
var (
file_meshtastic_clientonly_proto_rawDescOnce sync.Once

View File

@@ -4,7 +4,7 @@
// protoc v5.29.3
// source: meshtastic/config.proto
package generated
package meshtastic
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
@@ -2742,8 +2742,8 @@ const file_meshtastic_config_proto_rawDesc = "" +
"\x15debug_log_api_enabled\x18\x06 \x01(\bR\x12debugLogApiEnabled\x122\n" +
"\x15admin_channel_enabled\x18\b \x01(\bR\x13adminChannelEnabled\x1a\x12\n" +
"\x10SessionkeyConfigB\x11\n" +
"\x0fpayload_variantBa\n" +
"\x13com.geeksville.meshB\fConfigProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
"\x0fpayload_variantB^\n" +
"\x13com.geeksville.meshB\fConfigProtosZ\x1fmeshstream/generated/meshtastic\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
var (
file_meshtastic_config_proto_rawDescOnce sync.Once

View File

@@ -4,7 +4,7 @@
// protoc v5.29.3
// source: meshtastic/connection_status.proto
package generated
package meshtastic
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
@@ -429,8 +429,8 @@ const file_meshtastic_connection_status_proto_rawDesc = "" +
"\fis_connected\x18\x03 \x01(\bR\visConnected\"O\n" +
"\x16SerialConnectionStatus\x12\x12\n" +
"\x04baud\x18\x01 \x01(\rR\x04baud\x12!\n" +
"\fis_connected\x18\x02 \x01(\bR\visConnectedBe\n" +
"\x13com.geeksville.meshB\x10ConnStatusProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
"\fis_connected\x18\x02 \x01(\bR\visConnectedBb\n" +
"\x13com.geeksville.meshB\x10ConnStatusProtosZ\x1fmeshstream/generated/meshtastic\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
var (
file_meshtastic_connection_status_proto_rawDescOnce sync.Once

View File

@@ -4,7 +4,7 @@
// protoc v5.29.3
// source: meshtastic/device_ui.proto
package generated
package meshtastic
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
@@ -743,8 +743,8 @@ const file_meshtastic_device_ui_proto_rawDesc = "" +
"\tSLOVENIAN\x10\x0f\x12\r\n" +
"\tUKRAINIAN\x10\x10\x12\x16\n" +
"\x12SIMPLIFIED_CHINESE\x10\x1e\x12\x17\n" +
"\x13TRADITIONAL_CHINESE\x10\x1fBc\n" +
"\x13com.geeksville.meshB\x0eDeviceUIProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
"\x13TRADITIONAL_CHINESE\x10\x1fB`\n" +
"\x13com.geeksville.meshB\x0eDeviceUIProtosZ\x1fmeshstream/generated/meshtastic\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
var (
file_meshtastic_device_ui_proto_rawDescOnce sync.Once

View File

@@ -4,7 +4,7 @@
// protoc v5.29.3
// source: meshtastic/deviceonly.proto
package generated
package meshtastic
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
@@ -773,9 +773,9 @@ const file_meshtastic_deviceonly_proto_rawDesc = "" +
"\x06config\x18\x03 \x01(\v2\x17.meshtastic.LocalConfigR\x06config\x12B\n" +
"\rmodule_config\x18\x04 \x01(\v2\x1d.meshtastic.LocalModuleConfigR\fmoduleConfig\x123\n" +
"\bchannels\x18\x05 \x01(\v2\x17.meshtastic.ChannelFileR\bchannels\x12&\n" +
"\x05owner\x18\x06 \x01(\v2\x10.meshtastic.UserR\x05ownerBm\x92?\v\xc2\x01\b<vector>\n" +
"\x05owner\x18\x06 \x01(\v2\x10.meshtastic.UserR\x05ownerBj\x92?\v\xc2\x01\b<vector>\n" +
"\x13com.geeksville.meshB\n" +
"DeviceOnlyZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
"DeviceOnlyZ\x1fmeshstream/generated/meshtastic\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
var (
file_meshtastic_deviceonly_proto_rawDescOnce sync.Once

View File

@@ -4,7 +4,7 @@
// protoc v5.29.3
// source: meshtastic/interdevice.proto
package generated
package meshtastic
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
@@ -306,8 +306,8 @@ const file_meshtastic_interdevice_proto_rawDesc = "" +
"AHT20_TEMP\x10\xb3\x01\x12\x13\n" +
"\x0eAHT20_HUMIDITY\x10\xb4\x01\x12\x0f\n" +
"\n" +
"TVOC_INDEX\x10\xb5\x01Bf\n" +
"\x13com.geeksville.meshB\x11InterdeviceProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
"TVOC_INDEX\x10\xb5\x01Bc\n" +
"\x13com.geeksville.meshB\x11InterdeviceProtosZ\x1fmeshstream/generated/meshtastic\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
var (
file_meshtastic_interdevice_proto_rawDescOnce sync.Once

View File

@@ -4,7 +4,7 @@
// protoc v5.29.3
// source: meshtastic/localonly.proto
package generated
package meshtastic
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
@@ -338,8 +338,8 @@ const file_meshtastic_localonly_proto_rawDesc = "" +
"\n" +
"paxcounter\x18\x0e \x01(\v2).meshtastic.ModuleConfig.PaxcounterConfigR\n" +
"paxcounter\x12\x18\n" +
"\aversion\x18\b \x01(\rR\aversionBd\n" +
"\x13com.geeksville.meshB\x0fLocalOnlyProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
"\aversion\x18\b \x01(\rR\aversionBa\n" +
"\x13com.geeksville.meshB\x0fLocalOnlyProtosZ\x1fmeshstream/generated/meshtastic\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
var (
file_meshtastic_localonly_proto_rawDescOnce sync.Once

View File

@@ -4,7 +4,7 @@
// protoc v5.29.3
// source: meshtastic/mesh.proto
package generated
package meshtastic
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
@@ -4589,9 +4589,9 @@ const file_meshtastic_mesh_proto_rawDesc = "" +
"\x16DETECTIONSENSOR_CONFIG\x10\x80\x10\x12\x16\n" +
"\x11PAXCOUNTER_CONFIG\x10\x80 \x12\x15\n" +
"\x10BLUETOOTH_CONFIG\x10\x80@\x12\x14\n" +
"\x0eNETWORK_CONFIG\x10\x80\x80\x01B_\n" +
"\x0eNETWORK_CONFIG\x10\x80\x80\x01B\\\n" +
"\x13com.geeksville.meshB\n" +
"MeshProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
"MeshProtosZ\x1fmeshstream/generated/meshtastic\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
var (
file_meshtastic_mesh_proto_rawDescOnce sync.Once

View File

@@ -4,7 +4,7 @@
// protoc v5.29.3
// source: meshtastic/module_config.proto
package generated
package meshtastic
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
@@ -2439,8 +2439,8 @@ const file_meshtastic_module_config_proto_rawDesc = "" +
"\x15RemoteHardwarePinType\x12\v\n" +
"\aUNKNOWN\x10\x00\x12\x10\n" +
"\fDIGITAL_READ\x10\x01\x12\x11\n" +
"\rDIGITAL_WRITE\x10\x02Bg\n" +
"\x13com.geeksville.meshB\x12ModuleConfigProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
"\rDIGITAL_WRITE\x10\x02Bd\n" +
"\x13com.geeksville.meshB\x12ModuleConfigProtosZ\x1fmeshstream/generated/meshtastic\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
var (
file_meshtastic_module_config_proto_rawDescOnce sync.Once

View File

@@ -4,7 +4,7 @@
// protoc v5.29.3
// source: meshtastic/mqtt.proto
package generated
package meshtastic
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
@@ -272,9 +272,9 @@ const file_meshtastic_mqtt_proto_rawDesc = "" +
"longitudeI\x12\x1a\n" +
"\baltitude\x18\v \x01(\x05R\baltitude\x12-\n" +
"\x12position_precision\x18\f \x01(\rR\x11positionPrecision\x123\n" +
"\x16num_online_local_nodes\x18\r \x01(\rR\x13numOnlineLocalNodesB_\n" +
"\x16num_online_local_nodes\x18\r \x01(\rR\x13numOnlineLocalNodesB\\\n" +
"\x13com.geeksville.meshB\n" +
"MQTTProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
"MQTTProtosZ\x1fmeshstream/generated/meshtastic\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
var (
file_meshtastic_mqtt_proto_rawDescOnce sync.Once

View File

@@ -11,7 +11,7 @@
// protoc v5.29.3
// source: meshtastic/nanopb.proto
package generated
package meshtastic
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
@@ -771,8 +771,8 @@ const file_meshtastic_nanopb_proto_rawDesc = "" +
"\x0enanopb_fileopt\x12\x1c.google.protobuf.FileOptions\x18\xf2\a \x01(\v2\x0e.NanoPBOptionsR\rnanopbFileopt:U\n" +
"\rnanopb_msgopt\x12\x1f.google.protobuf.MessageOptions\x18\xf2\a \x01(\v2\x0e.NanoPBOptionsR\fnanopbMsgopt:T\n" +
"\x0enanopb_enumopt\x12\x1c.google.protobuf.EnumOptions\x18\xf2\a \x01(\v2\x0e.NanoPBOptionsR\rnanopbEnumopt:F\n" +
"\x06nanopb\x12\x1d.google.protobuf.FieldOptions\x18\xf2\a \x01(\v2\x0e.NanoPBOptionsR\x06nanopbB>\n" +
"\x18fi.kapsi.koti.jpa.nanopbZ\"github.com/meshtastic/go/generated"
"\x06nanopb\x12\x1d.google.protobuf.FieldOptions\x18\xf2\a \x01(\v2\x0e.NanoPBOptionsR\x06nanopbB;\n" +
"\x18fi.kapsi.koti.jpa.nanopbZ\x1fmeshstream/generated/meshtastic"
var (
file_meshtastic_nanopb_proto_rawDescOnce sync.Once

View File

@@ -4,7 +4,7 @@
// protoc v5.29.3
// source: meshtastic/paxcount.proto
package generated
package meshtastic
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
@@ -94,8 +94,8 @@ const file_meshtastic_paxcount_proto_rawDesc = "" +
"\bPaxcount\x12\x12\n" +
"\x04wifi\x18\x01 \x01(\rR\x04wifi\x12\x10\n" +
"\x03ble\x18\x02 \x01(\rR\x03ble\x12\x16\n" +
"\x06uptime\x18\x03 \x01(\rR\x06uptimeBc\n" +
"\x13com.geeksville.meshB\x0ePaxcountProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
"\x06uptime\x18\x03 \x01(\rR\x06uptimeB`\n" +
"\x13com.geeksville.meshB\x0ePaxcountProtosZ\x1fmeshstream/generated/meshtastic\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
var (
file_meshtastic_paxcount_proto_rawDescOnce sync.Once

View File

@@ -4,7 +4,7 @@
// protoc v5.29.3
// source: meshtastic/portnums.proto
package generated
package meshtastic
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
@@ -288,8 +288,8 @@ const file_meshtastic_portnums_proto_rawDesc = "" +
"\x14RETICULUM_TUNNEL_APP\x10L\x12\x10\n" +
"\vPRIVATE_APP\x10\x80\x02\x12\x13\n" +
"\x0eATAK_FORWARDER\x10\x81\x02\x12\b\n" +
"\x03MAX\x10\xff\x03B]\n" +
"\x13com.geeksville.meshB\bPortnumsZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
"\x03MAX\x10\xff\x03BZ\n" +
"\x13com.geeksville.meshB\bPortnumsZ\x1fmeshstream/generated/meshtastic\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
var (
file_meshtastic_portnums_proto_rawDescOnce sync.Once

View File

@@ -4,7 +4,7 @@
// protoc v5.29.3
// source: meshtastic/powermon.proto
package generated
package meshtastic
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
@@ -360,8 +360,8 @@ const file_meshtastic_powermon_proto_rawDesc = "" +
"\aWIFI_ON\x10a\x12\v\n" +
"\aGPS_OFF\x10p\x12\n" +
"\n" +
"\x06GPS_ON\x10qBc\n" +
"\x13com.geeksville.meshB\x0ePowerMonProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
"\x06GPS_ON\x10qB`\n" +
"\x13com.geeksville.meshB\x0ePowerMonProtosZ\x1fmeshstream/generated/meshtastic\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
var (
file_meshtastic_powermon_proto_rawDescOnce sync.Once

View File

@@ -4,7 +4,7 @@
// protoc v5.29.3
// source: meshtastic/remote_hardware.proto
package generated
package meshtastic
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
@@ -179,8 +179,8 @@ const file_meshtastic_remote_hardware_proto_rawDesc = "" +
"\rGPIOS_CHANGED\x10\x03\x12\x0e\n" +
"\n" +
"READ_GPIOS\x10\x04\x12\x14\n" +
"\x10READ_GPIOS_REPLY\x10\x05Bc\n" +
"\x13com.geeksville.meshB\x0eRemoteHardwareZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
"\x10READ_GPIOS_REPLY\x10\x05B`\n" +
"\x13com.geeksville.meshB\x0eRemoteHardwareZ\x1fmeshstream/generated/meshtastic\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
var (
file_meshtastic_remote_hardware_proto_rawDescOnce sync.Once

View File

@@ -4,7 +4,7 @@
// protoc v5.29.3
// source: meshtastic/rtttl.proto
package generated
package meshtastic
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
@@ -74,8 +74,8 @@ const file_meshtastic_rtttl_proto_rawDesc = "" +
"\x16meshtastic/rtttl.proto\x12\n" +
"meshtastic\")\n" +
"\vRTTTLConfig\x12\x1a\n" +
"\bringtone\x18\x01 \x01(\tR\bringtoneBf\n" +
"\x13com.geeksville.meshB\x11RTTTLConfigProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
"\bringtone\x18\x01 \x01(\tR\bringtoneBc\n" +
"\x13com.geeksville.meshB\x11RTTTLConfigProtosZ\x1fmeshstream/generated/meshtastic\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
var (
file_meshtastic_rtttl_proto_rawDescOnce sync.Once

View File

@@ -4,7 +4,7 @@
// protoc v5.29.3
// source: meshtastic/storeforward.proto
package generated
package meshtastic
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
@@ -545,8 +545,8 @@ const file_meshtastic_storeforward_proto_rawDesc = "" +
"\vCLIENT_PING\x10C\x12\x0f\n" +
"\vCLIENT_PONG\x10D\x12\x10\n" +
"\fCLIENT_ABORT\x10jB\t\n" +
"\avariantBj\n" +
"\x13com.geeksville.meshB\x15StoreAndForwardProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
"\avariantBg\n" +
"\x13com.geeksville.meshB\x15StoreAndForwardProtosZ\x1fmeshstream/generated/meshtastic\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
var (
file_meshtastic_storeforward_proto_rawDescOnce sync.Once

View File

@@ -4,7 +4,7 @@
// protoc v5.29.3
// source: meshtastic/telemetry.proto
package generated
package meshtastic
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
@@ -1405,8 +1405,8 @@ const file_meshtastic_telemetry_proto_rawDesc = "" +
"\fDFROBOT_RAIN\x10#\x12\n" +
"\n" +
"\x06DPS310\x10$\x12\f\n" +
"\bRAK12035\x10%Bd\n" +
"\x13com.geeksville.meshB\x0fTelemetryProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
"\bRAK12035\x10%Ba\n" +
"\x13com.geeksville.meshB\x0fTelemetryProtosZ\x1fmeshstream/generated/meshtastic\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
var (
file_meshtastic_telemetry_proto_rawDescOnce sync.Once

View File

@@ -4,7 +4,7 @@
// protoc v5.29.3
// source: meshtastic/xmodem.proto
package generated
package meshtastic
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
@@ -172,8 +172,8 @@ const file_meshtastic_xmodem_proto_rawDesc = "" +
"\x03ACK\x10\x06\x12\a\n" +
"\x03NAK\x10\x15\x12\a\n" +
"\x03CAN\x10\x18\x12\t\n" +
"\x05CTRLZ\x10\x1aBa\n" +
"\x13com.geeksville.meshB\fXmodemProtosZ\"github.com/meshtastic/go/generated\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
"\x05CTRLZ\x10\x1aB^\n" +
"\x13com.geeksville.meshB\fXmodemProtosZ\x1fmeshstream/generated/meshtastic\xaa\x02\x14Meshtastic.Protobufs\xba\x02\x00b\x06proto3"
var (
file_meshtastic_xmodem_proto_rawDescOnce sync.Once

2
go.mod
View File

@@ -4,6 +4,8 @@ go 1.24.1
tool github.com/dpup/logista
replace github.com/meshtastic/go/ => ./generated/
require (
github.com/dpup/prefab v0.2.0
github.com/eclipse/paho.mqtt.golang v1.5.0

View File

@@ -8,6 +8,7 @@ import (
mqtt "github.com/eclipse/paho.mqtt.golang"
"meshstream/decoder"
mesh "meshstream/proto/generated"
)
// Config holds configuration for the MQTT client
@@ -32,7 +33,7 @@ type Client struct {
func NewClient(config Config, logger logging.Logger) *Client {
return &Client{
config: config,
decodedMessages: make(chan *Packet, 100), // Buffer up to 100 messages
decodedMessages: make(chan *Packet, 100),
done: make(chan struct{}),
logger: logger.Named("mqtt.client"),
}
@@ -79,8 +80,6 @@ func (c *Client) Messages() <-chan *Packet {
return c.decodedMessages
}
// These are intentionally left empty as we'll use the instance methods below
// messageHandler processes incoming MQTT messages
func (c *Client) messageHandler(client mqtt.Client, msg mqtt.Message) {
c.logger.Debugf("Received message from topic: %s", msg.Topic())
@@ -103,10 +102,7 @@ func (c *Client) messageHandler(client mqtt.Client, msg mqtt.Message) {
decodedPacket := decoder.DecodeMessage(msg.Payload(), topicInfo)
// Create packet with both the decoded packet and topic info
packet := &Packet{
DecodedPacket: decodedPacket,
TopicInfo: topicInfo,
}
packet := NewPacket(decodedPacket, topicInfo)
// Send the decoded message to the channel, but don't block if buffer is full
select {
@@ -138,4 +134,4 @@ func (c *Client) connectHandler(client mqtt.Client) {
// connectionLostHandler is called when the client loses connection
func (c *Client) connectionLostHandler(client mqtt.Client, err error) {
c.logger.Errorw("Connection lost", "error", err)
}
}

View File

@@ -1,11 +1,151 @@
package mqtt
import (
"meshstream/decoder"
mesh "meshstream/proto/generated"
)
// Packet extends the DecodedPacket with MQTT topic information
type Packet struct {
*decoder.DecodedPacket
*decoder.TopicInfo
*mesh.Packet
}
// NewPacket creates a Packet from a decoded packet and topic info
func NewPacket(decoded *mesh.DecodedPacket, topicInfo *mesh.TopicInfo) *Packet {
return &Packet{
Packet: &mesh.Packet{
DecodedPacket: decoded,
TopicInfo: topicInfo,
},
}
}
// Helper accessors to maintain backward compatibility with existing code
func (p *Packet) GetChannelID() string {
if p.DecodedPacket != nil {
return p.DecodedPacket.ChannelId
}
return ""
}
func (p *Packet) GetGatewayID() string {
if p.DecodedPacket != nil {
return p.DecodedPacket.GatewayId
}
return ""
}
func (p *Packet) GetID() uint32 {
if p.DecodedPacket != nil {
return p.DecodedPacket.Id
}
return 0
}
func (p *Packet) GetFrom() uint32 {
if p.DecodedPacket != nil {
return p.DecodedPacket.From
}
return 0
}
func (p *Packet) GetTo() uint32 {
if p.DecodedPacket != nil {
return p.DecodedPacket.To
}
return 0
}
func (p *Packet) GetPortNum() int32 {
if p.DecodedPacket != nil {
return int32(p.DecodedPacket.PortNum)
}
return 0
}
func (p *Packet) GetPortNumString() string {
if p.DecodedPacket != nil {
return p.DecodedPacket.PortNum.String()
}
return "UNKNOWN"
}
func (p *Packet) GetPayload() interface{} {
if p.DecodedPacket == nil {
return nil
}
// Depending on the payload type, return the appropriate value
switch x := p.DecodedPacket.Payload.(type) {
case *mesh.DecodedPacket_TextMessage:
return x.TextMessage
case *mesh.DecodedPacket_BinaryData:
return x.BinaryData
case *mesh.DecodedPacket_Position:
return x.Position
case *mesh.DecodedPacket_NodeInfo:
return x.NodeInfo
case *mesh.DecodedPacket_Telemetry:
return x.Telemetry
case *mesh.DecodedPacket_Waypoint:
return x.Waypoint
case *mesh.DecodedPacket_RouteDiscovery:
return x.RouteDiscovery
case *mesh.DecodedPacket_NeighborInfo:
return x.NeighborInfo
case *mesh.DecodedPacket_CompressedText:
return x.CompressedText
case *mesh.DecodedPacket_MapReport:
return x.MapReport
default:
return nil
}
}
func (p *Packet) GetHopLimit() uint32 {
if p.DecodedPacket != nil {
return p.DecodedPacket.HopLimit
}
return 0
}
func (p *Packet) GetHopStart() uint32 {
if p.DecodedPacket != nil {
return p.DecodedPacket.HopStart
}
return 0
}
func (p *Packet) HasDecodeError() bool {
return p.DecodedPacket != nil && p.DecodedPacket.DecodeError != ""
}
func (p *Packet) GetDecodeError() string {
if p.DecodedPacket != nil {
return p.DecodedPacket.DecodeError
}
return ""
}
// GetFullTopic returns the MQTT topic this packet was received on
func (p *Packet) GetFullTopic() string {
if p.TopicInfo != nil {
return p.TopicInfo.FullTopic
}
return ""
}
// GetRegionPath returns the region path from the topic
func (p *Packet) GetRegionPath() string {
if p.TopicInfo != nil {
return p.TopicInfo.RegionPath
}
return ""
}
// GetChannel returns the channel name from the topic
func (p *Packet) GetChannel() string {
if p.TopicInfo != nil {
return p.TopicInfo.Channel
}
return ""
}

View File

@@ -0,0 +1,94 @@
syntax = "proto3";
package meshstream;
import "meshtastic/mesh.proto";
import "meshtastic/portnums.proto";
import "meshtastic/telemetry.proto";
import "meshtastic/mqtt.proto";
import "meshtastic/remote_hardware.proto";
import "meshtastic/admin.proto";
import "meshtastic/paxcount.proto";
option go_package = "proto/generated/meshstream;meshtreampb";
// Packet represents a complete decoded MQTT message
message Packet {
TopicInfo info = 2;
Data data = 1;
}
// TopicInfo contains parsed information about a Meshtastic MQTT topic
message TopicInfo {
string full_topic = 1;
string region_path = 2;
string version = 3;
string format = 4;
string channel = 5;
string user_id = 6;
}
// Data provides a flattened structure for decoded Meshtastic packets
message Data {
// From Service Envelope
string channel_id = 1;
string gateway_id = 2;
// From Mesh Packet
uint32 id = 3;
uint32 from = 4;
uint32 to = 5;
uint32 hop_limit = 6;
uint32 hop_start = 7;
bool want_ack = 8;
string priority = 9;
bool via_mqtt = 10;
uint32 next_hop = 11;
uint32 relay_node = 12;
// From Data
meshtastic.PortNum port_num = 13;
// Payload is one of these types, depending on port_num
oneof payload {
string text_message = 14; // TEXT_MESSAGE_APP
bytes binary_data = 15; // Generic binary data for other port types
meshtastic.Position position = 16; // POSITION_APP
meshtastic.User node_info = 17; // NODEINFO_APP
meshtastic.Telemetry telemetry = 18; // TELEMETRY_APP
meshtastic.Waypoint waypoint = 19; // WAYPOINT_APP
meshtastic.RouteDiscovery route_discovery = 20; // TRACEROUTE_APP
meshtastic.NeighborInfo neighbor_info = 21; // NEIGHBORINFO_APP
bytes compressed_text = 22; // TEXT_MESSAGE_COMPRESSED_APP
meshtastic.MapReport map_report = 23; // MAP_REPORT_APP
meshtastic.HardwareMessage remote_hardware = 24; // REMOTE_HARDWARE_APP
meshtastic.Routing routing = 25; // ROUTING_APP
meshtastic.AdminMessage admin = 26; // ADMIN_APP
bytes audio_data = 27; // AUDIO_APP
string alert = 28; // ALERT_APP
string reply = 29; // REPLY_APP
bytes ip_tunnel = 30; // IP_TUNNEL_APP
meshtastic.Paxcount paxcounter = 31; // PAXCOUNTER_APP
bytes serial_app = 32; // SERIAL_APP
bytes store_forward = 33; // STORE_FORWARD_APP
string range_test = 34; // RANGE_TEST_APP
bytes zps_app = 35; // ZPS_APP
bytes simulator = 36; // SIMULATOR_APP
bytes atak_plugin = 37; // ATAK_PLUGIN
bytes powerstress = 38; // POWERSTRESS_APP
bytes reticulum_tunnel = 39; // RETICULUM_TUNNEL_APP
bytes private_app = 40; // PRIVATE_APP, ATAK_FORWARDER
string detection_sensor = 41; // DETECTION_SENSOR_APP
}
// Additional Data fields
uint32 request_id = 50;
uint32 reply_id = 51;
uint32 emoji = 52;
uint32 dest = 53;
uint32 source = 54;
bool want_response = 55;
// Error tracking
string decode_error = 60;
}

View File

@@ -10,7 +10,7 @@ import "meshtastic/module_config.proto";
import "meshtastic/device_ui.proto";
option csharp_namespace = "Meshtastic.Protobufs";
option go_package = "github.com/meshtastic/go/generated";
option go_package = "meshstream/generated/meshtastic";
option java_outer_classname = "AdminProtos";
option java_package = "com.geeksville.mesh";
option swift_prefix = "";

View File

@@ -6,7 +6,7 @@ import "meshtastic/channel.proto";
import "meshtastic/config.proto";
option csharp_namespace = "Meshtastic.Protobufs";
option go_package = "github.com/meshtastic/go/generated";
option go_package = "meshstream/generated/meshtastic";
option java_outer_classname = "AppOnlyProtos";
option java_package = "com.geeksville.mesh";
option swift_prefix = "";

View File

@@ -3,7 +3,7 @@ syntax = "proto3";
package meshtastic;
option csharp_namespace = "Meshtastic.Protobufs";
option go_package = "github.com/meshtastic/go/generated";
option go_package = "meshstream/generated/meshtastic";
option java_outer_classname = "ATAKProtos";
option java_package = "com.geeksville.mesh";
option swift_prefix = "";

View File

@@ -3,7 +3,7 @@ syntax = "proto3";
package meshtastic;
option csharp_namespace = "Meshtastic.Protobufs";
option go_package = "github.com/meshtastic/go/generated";
option go_package = "meshstream/generated/meshtastic";
option java_outer_classname = "CannedMessageConfigProtos";
option java_package = "com.geeksville.mesh";
option swift_prefix = "";

View File

@@ -3,7 +3,7 @@ syntax = "proto3";
package meshtastic;
option csharp_namespace = "Meshtastic.Protobufs";
option go_package = "github.com/meshtastic/go/generated";
option go_package = "meshstream/generated/meshtastic";
option java_outer_classname = "ChannelProtos";
option java_package = "com.geeksville.mesh";
option swift_prefix = "";

View File

@@ -6,7 +6,7 @@ import "meshtastic/localonly.proto";
import "meshtastic/mesh.proto";
option csharp_namespace = "Meshtastic.Protobufs";
option go_package = "github.com/meshtastic/go/generated";
option go_package = "meshstream/generated/meshtastic";
option java_outer_classname = "ClientOnlyProtos";
option java_package = "com.geeksville.mesh";
option swift_prefix = "";

View File

@@ -5,7 +5,7 @@ package meshtastic;
import "meshtastic/device_ui.proto";
option csharp_namespace = "Meshtastic.Protobufs";
option go_package = "github.com/meshtastic/go/generated";
option go_package = "meshstream/generated/meshtastic";
option java_outer_classname = "ConfigProtos";
option java_package = "com.geeksville.mesh";
option swift_prefix = "";

View File

@@ -3,7 +3,7 @@ syntax = "proto3";
package meshtastic;
option csharp_namespace = "Meshtastic.Protobufs";
option go_package = "github.com/meshtastic/go/generated";
option go_package = "meshstream/generated/meshtastic";
option java_outer_classname = "ConnStatusProtos";
option java_package = "com.geeksville.mesh";
option swift_prefix = "";

View File

@@ -3,7 +3,7 @@ syntax = "proto3";
package meshtastic;
option csharp_namespace = "Meshtastic.Protobufs";
option go_package = "github.com/meshtastic/go/generated";
option go_package = "meshstream/generated/meshtastic";
option java_outer_classname = "DeviceUIProtos";
option java_package = "com.geeksville.mesh";
option swift_prefix = "";

View File

@@ -10,7 +10,7 @@ import "meshtastic/localonly.proto";
import "meshtastic/nanopb.proto";
option csharp_namespace = "Meshtastic.Protobufs";
option go_package = "github.com/meshtastic/go/generated";
option go_package = "meshstream/generated/meshtastic";
option java_outer_classname = "DeviceOnly";
option java_package = "com.geeksville.mesh";
option swift_prefix = "";

View File

@@ -3,7 +3,7 @@ syntax = "proto3";
package meshtastic;
option csharp_namespace = "Meshtastic.Protobufs";
option go_package = "github.com/meshtastic/go/generated";
option go_package = "meshstream/generated/meshtastic";
option java_outer_classname = "InterdeviceProtos";
option java_package = "com.geeksville.mesh";
option swift_prefix = "";

View File

@@ -6,7 +6,7 @@ import "meshtastic/config.proto";
import "meshtastic/module_config.proto";
option csharp_namespace = "Meshtastic.Protobufs";
option go_package = "github.com/meshtastic/go/generated";
option go_package = "meshstream/generated/meshtastic";
option java_outer_classname = "LocalOnlyProtos";
option java_package = "com.geeksville.mesh";
option swift_prefix = "";

View File

@@ -11,7 +11,7 @@ import "meshtastic/xmodem.proto";
import "meshtastic/device_ui.proto";
option csharp_namespace = "Meshtastic.Protobufs";
option go_package = "github.com/meshtastic/go/generated";
option go_package = "meshstream/generated/meshtastic";
option java_outer_classname = "MeshProtos";
option java_package = "com.geeksville.mesh";
option swift_prefix = "";

View File

@@ -3,7 +3,7 @@ syntax = "proto3";
package meshtastic;
option csharp_namespace = "Meshtastic.Protobufs";
option go_package = "github.com/meshtastic/go/generated";
option go_package = "meshstream/generated/meshtastic";
option java_outer_classname = "ModuleConfigProtos";
option java_package = "com.geeksville.mesh";
option swift_prefix = "";

View File

@@ -6,7 +6,7 @@ import "meshtastic/config.proto";
import "meshtastic/mesh.proto";
option csharp_namespace = "Meshtastic.Protobufs";
option go_package = "github.com/meshtastic/go/generated";
option go_package = "meshstream/generated/meshtastic";
option java_outer_classname = "MQTTProtos";
option java_package = "com.geeksville.mesh";
option swift_prefix = "";

View File

@@ -9,7 +9,7 @@ syntax = "proto2";
import "google/protobuf/descriptor.proto";
option go_package = "github.com/meshtastic/go/generated";
option go_package = "meshstream/generated/meshtastic";
option java_package = "fi.kapsi.koti.jpa.nanopb";
enum FieldType {

View File

@@ -3,7 +3,7 @@ syntax = "proto3";
package meshtastic;
option csharp_namespace = "Meshtastic.Protobufs";
option go_package = "github.com/meshtastic/go/generated";
option go_package = "meshstream/generated/meshtastic";
option java_outer_classname = "PaxcountProtos";
option java_package = "com.geeksville.mesh";
option swift_prefix = "";

View File

@@ -3,7 +3,7 @@ syntax = "proto3";
package meshtastic;
option csharp_namespace = "Meshtastic.Protobufs";
option go_package = "github.com/meshtastic/go/generated";
option go_package = "meshstream/generated/meshtastic";
option java_outer_classname = "Portnums";
option java_package = "com.geeksville.mesh";
option swift_prefix = "";

View File

@@ -1,7 +1,7 @@
syntax = "proto3";
option csharp_namespace = "Meshtastic.Protobufs";
option go_package = "github.com/meshtastic/go/generated";
option go_package = "meshstream/generated/meshtastic";
option java_outer_classname = "PowerMonProtos";
option java_package = "com.geeksville.mesh";
option swift_prefix = "";

View File

@@ -3,7 +3,7 @@ syntax = "proto3";
package meshtastic;
option csharp_namespace = "Meshtastic.Protobufs";
option go_package = "github.com/meshtastic/go/generated";
option go_package = "meshstream/generated/meshtastic";
option java_outer_classname = "RemoteHardware";
option java_package = "com.geeksville.mesh";
option swift_prefix = "";

View File

@@ -3,7 +3,7 @@ syntax = "proto3";
package meshtastic;
option csharp_namespace = "Meshtastic.Protobufs";
option go_package = "github.com/meshtastic/go/generated";
option go_package = "meshstream/generated/meshtastic";
option java_outer_classname = "RTTTLConfigProtos";
option java_package = "com.geeksville.mesh";
option swift_prefix = "";

View File

@@ -3,7 +3,7 @@ syntax = "proto3";
package meshtastic;
option csharp_namespace = "Meshtastic.Protobufs";
option go_package = "github.com/meshtastic/go/generated";
option go_package = "meshstream/generated/meshtastic";
option java_outer_classname = "StoreAndForwardProtos";
option java_package = "com.geeksville.mesh";
option swift_prefix = "";

View File

@@ -3,7 +3,7 @@ syntax = "proto3";
package meshtastic;
option csharp_namespace = "Meshtastic.Protobufs";
option go_package = "github.com/meshtastic/go/generated";
option go_package = "meshstream/generated/meshtastic";
option java_outer_classname = "TelemetryProtos";
option java_package = "com.geeksville.mesh";
option swift_prefix = "";

View File

@@ -3,7 +3,7 @@ syntax = "proto3";
package meshtastic;
option csharp_namespace = "Meshtastic.Protobufs";
option go_package = "github.com/meshtastic/go/generated";
option go_package = "meshstream/generated/meshtastic";
option java_outer_classname = "XmodemProtos";
option java_package = "com.geeksville.mesh";
option swift_prefix = "";

View File

@@ -6,10 +6,10 @@ import (
"net/http"
"strconv"
"sync/atomic"
"time"
"github.com/dpup/prefab"
"github.com/dpup/prefab/logging"
"google.golang.org/protobuf/encoding/protojson"
"meshstream/mqtt"
)
@@ -174,24 +174,19 @@ func (s *Server) handleStream(w http.ResponseWriter, r *http.Request) {
continue
}
// Create a serializable wrapper for the packet
// That includes both the entire packet and some extra fields for convenience
packetWrapper := struct {
*mqtt.Packet
ReceivedAt int64 `json:"received_at"`
PortString string `json:"port_string"`
}{
Packet: packet,
ReceivedAt: time.Now().Unix(),
PortString: packet.PortNum.String(),
// Use protojson Marshaler for the protobuf parts of the packet
// Create a marshaler with pretty printing enabled
marshaler := protojson.MarshalOptions{
EmitUnpopulated: true,
Indent: " ",
UseProtoNames: false, // Use camelCase names
}
// Convert the entire packet to JSON
data, err := json.Marshal(packetWrapper)
data, err := marshaler.Marshal(packet)
if err != nil {
logger.Errorw("Error marshaling packet to JSON", "error", err)
continue
http.Error(w, "Error marshaling packet", http.StatusInternalServerError)
return
}
// Send the event