Skip to content
Snippets Groups Projects
Aljaž Starc's avatar
Aljaž Starc authored
e5c445b7
History

protobuf

Source github.com/meshtastic/protobufs converted to golang using protoc with protoc-gen-go from pkg.go.dev/google.golang.org/protobuf.

Intallation and fully working example usage

go get gitplac.si/gomeshtastic/protobuf/v2@v2.5.5
package main

import (
	"bytes"
	"log"
	"math/rand"

	pb "gitplac.si/gomeshtastic/protobuf/v2"

	"go.bug.st/serial"
	"google.golang.org/protobuf/proto"
)

func main() {
	serialPort, err := serial.Open("/dev/ttyACM0", &serial.Mode{
		BaudRate: 115200,
		DataBits: 8,
		Parity:   serial.MarkParity,
	})
	if err != nil {
		panic(err)
	}

	//
	// Create protobuf packet requesting radio configuration
	//

	rndConfigCompleteId := uint32(rand.Intn(100))
	getConfigPacket, err := proto.Marshal(&pb.ToRadio{PayloadVariant: &pb.ToRadio_WantConfigId{WantConfigId: rndConfigCompleteId}})
	if err != nil {
		panic(nil)
	}

	packageLength := len(string(getConfigPacket))
	writePacket := []byte{0x94, 0xc3, byte(packageLength>>8) & 0xff, byte(packageLength) & 0xff}
	writePacket = append(writePacket, getConfigPacket...)

	//
	// Write the packet to the serial device
	//

	_, err = serialPort.Write(writePacket)
	if err != nil {
		panic(err)
	}

	//
	// Read packets from serial device and log them
	// until a packet with the same ID (uint32) that
	// we generated above is returned
	//
	for {
		buffer_bytes := []byte{}
		for {
			p := make([]byte, 128)
			n, err := serialPort.Read(p)
			if err != nil {
				panic(err)
			}
			buffer_bytes = append(buffer_bytes, p[:n]...)

			// In search of packet start
			for i := 0; i+3 < len(buffer_bytes); i++ {

				if !bytes.Equal(buffer_bytes[i:i+2], []byte{0x94, 0xc3}) {
					continue
				}

				packetLength := int((buffer_bytes[i+2] << 8) + buffer_bytes[i+3])

				potential_packet_bytes := buffer_bytes[i+4 : min(len(buffer_bytes), i+4+packetLength)]
				for {
					bytesMissing := packetLength - len(potential_packet_bytes)
					if bytesMissing <= 0 {
						break
					}

					p := make([]byte, bytesMissing)
					n, err := serialPort.Read(p)
					if err != nil {
						panic(err)
					}

					buffer_bytes = append(buffer_bytes, p[:n]...)
					potential_packet_bytes = buffer_bytes[i+4:]
				}

				fromRadio := pb.FromRadio{}
				if errUnMarshal := proto.Unmarshal(potential_packet_bytes, &fromRadio); errUnMarshal != nil {
					continue
				}

				log.Print(&fromRadio)

				if configCompletePacket, ok := fromRadio.GetPayloadVariant().(*pb.FromRadio_ConfigCompleteId); ok {
					if configCompletePacket.ConfigCompleteId == rndConfigCompleteId {
						log.Print("Got valid ConfigCompleteId packet")
						return
					}
				}
			}

			// Always keep at most last 4 bytes between runs
			// discard everything in front of those bytes
			buffer_bytes = buffer_bytes[max(len(buffer_bytes), 4)-4:]
		}

	}
}

Update protobufs

go install google.golang.org/protobuf/cmd/protoc-gen-go@latest

rm *.go # remove all protobuf definitions
git clone https://github.com/meshtastic/protobufs/
cd protobufs/
git checkout v2.5.3 # change the version of protobuf definitions you want to commit

PATH=$PATH:~/go/bin/ protoc --proto_path=./ --go_out=../ --go_opt=Mnanopb.proto=./ meshtastic/*.proto

cd ..
mv github.com/meshtastic/go/generated/*.pb.go .
rm -r protobufs github.com


# Remove possible dynamic import from generated source files
# REMOVE THIS if it exists: _ "./"

go mod tidy