Skip to content

Instantly share code, notes, and snippets.

@0x5e
Created March 4, 2024 14:41
Show Gist options
  • Save 0x5e/dfb03f2ae7335bf03bb4b9cf59971597 to your computer and use it in GitHub Desktop.
Save 0x5e/dfb03f2ae7335bf03bb4b9cf59971597 to your computer and use it in GitHub Desktop.
bambu-go2rtc
// golang version of https://github.com/synman/bambu-go2rtc
// usage: ./camera-stream <accessCode> <hostname>
// with ffplay: ./camera-stream <accessCode> <hostname> | ffplay -hide_banner -fflags nobuffer -analyzeduration 10 -probesize 32 -i -
// tested on bambu lab a1 mini, the fps is really low for this device :(
package main
import (
"bytes"
"crypto/tls"
"encoding/binary"
"fmt"
"io"
"net"
"os"
)
const username = "bblp"
const port = 6000
func main() {
if len(os.Args) != 3 {
fmt.Println("Usage: <executable> <accessCode> <hostname>")
os.Exit(1)
}
accessCode := os.Args[1]
hostname := os.Args[2]
authData := []byte{
0x40, 0x00, 0x00, 0x00, // '@'\0\0\0
0x00, 0x30, 0x00, 0x00, // \0'0'\0\0
0x00, 0x00, 0x00, 0x00, // \0\0\0\0
0x00, 0x00, 0x00, 0x00, // \0\0\0\0
}
authData = append(authData, []byte(username)...)
authData = append(authData, make([]byte, 32-len(username))...)
authData = append(authData, []byte(accessCode)...)
authData = append(authData, make([]byte, 32-len(accessCode))...)
// fmt.Fprintf(os.Stderr, "authData: %q\n", authData)
connect(hostname, port, authData)
}
func connect(hostname string, port int, authData []byte) error {
conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", hostname, port))
if err != nil {
fmt.Fprintf(os.Stderr, "Connection attempt failed: %s\n", err)
return err
}
defer conn.Close()
tlsConn := tls.Client(conn, &tls.Config{
InsecureSkipVerify: true,
})
err = tlsConn.Handshake()
if err != nil {
fmt.Fprintf(os.Stderr, "TLS handshake failed: %s\n", err)
return err
}
defer tlsConn.Close()
_, err = tlsConn.Write(authData)
if err != nil {
fmt.Fprintf(os.Stderr, "Write to socket failed: %s\n", err)
return err
}
for true {
header := make([]byte, 16)
_, err = io.ReadFull(tlsConn, header)
if err != nil {
fmt.Fprintf(os.Stderr, "Read error: %s\n", err)
return err
}
length := binary.LittleEndian.Uint32(header[0:4])
// fmt.Fprintf(os.Stderr, "packet header: %v\n", header)
if !bytes.Equal(header[4:], []byte{
0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
}) {
// skip invalid packet
continue
}
img := make([]byte, length)
_, err = io.ReadFull(tlsConn, img)
if err != nil {
fmt.Fprintf(os.Stderr, "Read error: %s\n", err)
return err
}
if bytes.Equal([]byte{0xff, 0xd8, 0xff, 0xe0}, img[0:4]) &&
bytes.Equal([]byte{0xff, 0xd9}, img[length-2:]) {
// fmt.Fprintf(os.Stderr, "Img size: %d\n", len(img))
os.Stdout.Write(img)
}
}
return nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment