Last active
April 16, 2024 19:39
-
-
Save wheresalice/26b0902f407bec1bd47f5db17cc65824 to your computer and use it in GitHub Desktop.
Decode meshtastic messages from mqtt using meshtastic-go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"encoding/base64" | |
"encoding/hex" | |
"fmt" | |
"github.com/charmbracelet/log" | |
pb "github.com/meshnet-gophers/meshtastic-go/meshtastic" | |
"github.com/meshnet-gophers/meshtastic-go/mqtt" | |
"github.com/meshnet-gophers/meshtastic-go/radio" | |
"google.golang.org/protobuf/proto" | |
"strings" | |
) | |
func main() { | |
client := mqtt.NewClient("tcp://mqtt.meshtastic.org:1883", "meshdev", "large4cats", "msh") | |
err := client.Connect() | |
if err != nil { | |
log.Fatal(err) | |
} | |
client.Handle("LongFast", channelHandler("LongFast")) | |
log.Info("Started") | |
select {} | |
} | |
func channelHandler(channel string) mqtt.HandlerFunc { | |
return func(m mqtt.Message) { | |
var env pb.ServiceEnvelope | |
err := proto.Unmarshal(m.Payload, &env) | |
if err != nil { | |
log.Fatal("failed unmarshalling to service envelope", "err", err, "payload", hex.EncodeToString(m.Payload)) | |
return | |
} | |
key, err := generateKey("1PG7OiApB1nwvP+rz05pAQ==") | |
if err != nil { | |
log.Fatal(err) | |
} | |
decodedMessage, err := radio.XOR(env.Packet.GetEncrypted(), key, env.Packet.Id, env.Packet.From) | |
if err != nil { | |
log.Error(err) | |
} | |
var message pb.Data | |
err = proto.Unmarshal(decodedMessage, &message) | |
log.Info(processMessage(message), "topic", m.Topic, "channel", channel, "portnum", message.Portnum.String()) | |
} | |
} | |
func processMessage(message pb.Data) string { | |
if message.Portnum == pb.PortNum_NODEINFO_APP { | |
var user = pb.User{} | |
proto.Unmarshal(message.Payload, &user) | |
return user.String() | |
} | |
if message.Portnum == pb.PortNum_POSITION_APP { | |
var pos = pb.Position{} | |
proto.Unmarshal(message.Payload, &pos) | |
return pos.String() | |
} | |
if message.Portnum == pb.PortNum_TELEMETRY_APP { | |
var t = pb.Telemetry{} | |
proto.Unmarshal(message.Payload, &t) | |
return t.String() | |
} | |
if message.Portnum == pb.PortNum_NEIGHBORINFO_APP { | |
var n = pb.NeighborInfo{} | |
proto.Unmarshal(message.Payload, &n) | |
return n.String() | |
} | |
if message.Portnum == pb.PortNum_STORE_FORWARD_APP { | |
var s = pb.StoreAndForward{} | |
proto.Unmarshal(message.Payload, &s) | |
return s.String() | |
} | |
return fmt.Sprintf("unknown message type") | |
} | |
func generateKey(key string) ([]byte, error) { | |
// Pad the key with '=' characters to ensure it's a valid base64 string | |
padding := (4 - len(key)%4) % 4 | |
paddedKey := key + strings.Repeat("=", padding) | |
// Replace '-' with '+' and '_' with '/' | |
replacedKey := strings.ReplaceAll(paddedKey, "-", "+") | |
replacedKey = strings.ReplaceAll(replacedKey, "_", "/") | |
// Decode the base64-encoded key | |
return base64.StdEncoding.DecodeString(replacedKey) | |
} |
No I don't. This could probably be made easier by adding some helper functions to the library, especially for text messages.
But essentially, you'll want to:
- move client out to a separate var (
var client *mqtt.Client
) so that it's available outside ofmain()
- do all the serializing of protobufs to byte[] arrays that generating an mqtt.Message requires
- use
client.Publish()
to publish the mqtt.Message
Ok, but in Meshtastic MQTT does not work that
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Do you have example to reply msg receive in this handle?