Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to disconnect device or close adapter #247

Open
hgqcode opened this issue Mar 12, 2024 · 16 comments
Open

How to disconnect device or close adapter #247

hgqcode opened this issue Mar 12, 2024 · 16 comments
Labels

Comments

@hgqcode
Copy link

hgqcode commented Mar 12, 2024

It doesn't work when i use disconnect device. so What am I supposed to do

var adapter = bluetooth.DefaultAdapter

func main() {
	wait()

	println("enabling")

	// Enable BLE interface.
	must("enable BLE stack", adapter.Enable())

	ch := make(chan bluetooth.ScanResult, 1)

	// Start scanning.
	println("scanning...")
	err := adapter.Scan(func(adapter *bluetooth.Adapter, result bluetooth.ScanResult) {
		println("found device:", result.Address.String(), result.RSSI, result.LocalName())
		if result.Address.String() == "10:52:1C:69:DA:EE" {
			adapter.StopScan()
			ch <- result
		}
	})

	var device *bluetooth.Device
	select {
	case result := <-ch:
		device, err = adapter.Connect(result.Address, bluetooth.ConnectionParams{})
		if err != nil {
			println(err.Error())
			return
		}

		println("connected to ", result.Address.String())
	}

	// get services
	println("discovering services/characteristics")
	srvcs, err := device.DiscoverServices(nil)
	must("discover services", err)

	// buffer to retrieve characteristic data
	buf := make([]byte, 255)

	for _, srvc := range srvcs {
		println("- service", srvc.UUID().String())

		chars, err := srvc.DiscoverCharacteristics(nil)
		if err != nil {
			println(err)
		}
		for _, char := range chars {
			println("-- characteristic", char.UUID().String())
			n, err := char.Read(buf)
			if err != nil {
				println("    ", err.Error())
			} else {
				println("    data bytes", strconv.Itoa(n))
				println("    value =", string(buf[:n]))
			}
		}
	}

	err = device.Disconnect()
	if err != nil {
		println(err)
	}

	done()
}

func must(action string, err error) {
	if err != nil {
		panic("failed to " + action + ": " + err.Error())
	}
}

func wait() {
	time.Sleep(3 * time.Second)
}

// done just blocks forever, allows USB CDC reset for flashing new software.
func done() {
	println("Done.")

	time.Sleep(1 * time.Hour)
}
@roffe
Copy link

roffe commented Mar 12, 2024

I have the same issue. Disconnect on Windows doesn't actually seem to disconnect the device and i have to restart the software before i can connect to the same BT device again

@aykevl
Copy link
Member

aykevl commented Mar 12, 2024

It doesn't work when i use disconnect device

What is the error? What system are you on? How can I reproduce this issue?
It's impossible to help or fix the bug without more information.

@roffe
Copy link

roffe commented Mar 12, 2024

No errors are raised, the software next time around starts scanning fine and i can see other devices. but my OBDX Pro doesn't start announcing itself again until i close the test software. it's like even after i called Disconnect the device is not actually disconnected until i close the program.

Im on Windows 11 23H2 22631.3155, Go 1.22 and using tdm-gcc as C compiler if that helps. Code is compiled as 64 bit as 32 bit panics and i've raised a issue here about it saltosystems/winrt-go#83

Here is some uggly code to trigger the problem:

package main

import (
	"log"
	"time"

	"github.com/roffe/gocan/dvi"
	"tinygo.org/x/bluetooth"
)

var (
	uartService = bluetooth.NewUUID([16]byte{0x6e, 0x40, 0x00, 0x01, 0xb5, 0xa3, 0xf3, 0x93, 0xe0, 0xa9, 0xe5, 0x0e, 0x24, 0xdc, 0xca, 0x9e})

	gatUUID = map[string]string{
		"00001800-0000-1000-8000-00805f9b34fb": "Generic Access",
		"00001801-0000-1000-8000-00805f9b34fb": "Generic Attribute",
		"6e400001-b5a3-f393-e0a9-e50e24dcca9e": "UART service",
	}

	characteristicUUID = map[string]string{
		"6e400003-b5a3-f393-e0a9-e50e24dcca9e": "TX",
		"6e400002-b5a3-f393-e0a9-e50e24dcca9e": "RX",
	}
)

var adapter = bluetooth.DefaultAdapter

func init() {
	log.SetFlags(log.LstdFlags | log.Lshortfile)
}

func main() {

	must("enable BLE stack", adapter.Enable())
	for i := 0; i < 3; i++ {
		main2()
		time.Sleep(5 * time.Second)
	}
}

func main2() {
	// Enable BLE interface.

	ch := make(chan bluetooth.ScanResult, 1)

	// Start scanning.
	println("scanning...")
	err := adapter.Scan(func(adapter *bluetooth.Adapter, device bluetooth.ScanResult) {
		//println("found device:", device.Address.String(), device.RSSI, device.LocalName())
		log.Printf("found device: %s, %d, %s", device.Address.String(), device.RSSI, device.LocalName())
		if device.LocalName() == "OBDX Pro GT" {
			adapter.StopScan()
			ch <- device
		}
	})
	must("start scan", err)

	var device bluetooth.Device
	select {
	case d := <-ch:
		device, err = adapter.Connect(d.Address, bluetooth.ConnectionParams{})
		if err != nil {
			log.Fatal("failed to connect:", err)
		}
		log.Printf("connected to %s", d.Address.String())
	case <-time.After(10 * time.Second):
		log.Fatal("Did not find any OBDX Pro GT device")
	}

	svcs, err := device.DiscoverServices(nil)
	if err != nil {
		log.Fatal("failed to discover services:", err)
	}

	log.Println("services found:", len(svcs))
	for _, svc := range svcs {
		if name, ok := gatUUID[svc.UUID().String()]; ok {
			log.Printf("service: %s (%s)", svc.String(), name)
		} else {
			log.Printf("service: %s", svc.String())
		}
	}

	srvc := svcs[2]

	chars, err := srvc.DiscoverCharacteristics(nil)
	if err != nil {
		log.Fatal("failed to discover characteristics:", err)
	}

	for _, char := range chars {

		if name, ok := characteristicUUID[char.UUID().String()]; ok {
			log.Printf("characteristic: %s (%s)", char.String(), name)
		} else {
			log.Printf("characteristic: %s", char.String())
		}
	}

	rx := chars[0]
	tx := chars[1]

	err = rx.EnableNotifications(func(buf []byte) {
		log.Printf("received: %X %q", buf, buf)
	})

	if err != nil {
		log.Fatal("failed to enable notifications:", err)
	}

	for i := 0; i < 3; i++ {
		tx.Write([]byte("\r\n"))
		time.Sleep(50 * time.Millisecond)
	}

	//tx.Write([]byte("DXDP1\r"))
	//time.Sleep(150 * time.Millisecond)
	//tx.Write([]byte("AT@1\r"))

	payload := dvi.New(0x22, []byte{0x03}).Bytes()
	log.Printf("sending: %X", payload)

	for i := 0; i < 3; i++ {
		tx.Write(payload)
		time.Sleep(2 * time.Second)
	}

	if err := device.Disconnect(); err != nil {
		log.Fatal("failed to disconnect:", err)
	}
}

func must(action string, err error) {
	if err != nil {
		log.Fatal("failed to " + action + ": " + err.Error())
	}
}

I can see during the scans in the 2 and 3rd itteration that the EnableNotifications handler still is getting data from the device so it's indeed the "disconnect" that doesn't free the adapter properly

PS: 31 2024-03-12 14:06:31 bttest >go run .
scanning...
2024/03/12 14:06:33 main.go:50: found device: 40:A8:20:13:16:0A, -58, 
2024/03/12 14:06:33 main.go:50: found device: 40:A8:20:13:16:0A, -58, 
2024/03/12 14:06:33 main.go:50: found device: 4D:4D:4D:40:A4:8E, -68, 
2024/03/12 14:06:33 main.go:50: found device: 64:B7:08:5F:F6:9A, -92, 
2024/03/12 14:06:33 main.go:50: found device: E1:A1:83:A9:09:2A, -94, 
2024/03/12 14:06:33 main.go:50: found device: E1:A1:83:A9:09:2A, -94, S36 B64E LE
2024/03/12 14:06:33 main.go:50: found device: 49:92:32:66:14:17, -68, 
2024/03/12 14:06:33 main.go:50: found device: 49:92:32:66:14:17, -68, 
2024/03/12 14:06:33 main.go:50: found device: 4E:29:DB:25:BB:71, -88, 
2024/03/12 14:06:33 main.go:50: found device: 4E:29:DB:25:BB:71, -90, 
2024/03/12 14:06:33 main.go:50: found device: 4E:29:DB:25:BB:71, -88, S39 1D5C LE
2024/03/12 14:06:33 main.go:50: found device: 64:B7:08:5F:F6:9A, -86, 
2024/03/12 14:06:33 main.go:50: found device: 64:B7:08:5F:F6:9A, -86, OBDX Pro GT
2024/03/12 14:06:33 main.go:65: connected to 64:B7:08:5F:F6:9A
2024/03/12 14:06:35 main.go:75: services found: 3
2024/03/12 14:06:35 main.go:78: service: 00001801-0000-1000-8000-00805f9b34fb (Generic Attribute)
2024/03/12 14:06:35 main.go:78: service: 00001800-0000-1000-8000-00805f9b34fb (Generic Access)
2024/03/12 14:06:35 main.go:78: service: 6e400001-b5a3-f393-e0a9-e50e24dcca9e (UART service)
2024/03/12 14:06:36 main.go:94: characteristic: 6e400003-b5a3-f393-e0a9-e50e24dcca9e (TX)
2024/03/12 14:06:36 main.go:94: characteristic: 6e400002-b5a3-f393-e0a9-e50e24dcca9e (RX)
2024/03/12 14:06:36 main.go:104: received: 0D "\r"
2024/03/12 14:06:36 main.go:104: received: 0A "\n"
2024/03/12 14:06:36 main.go:104: received: 0D "\r"
2024/03/12 14:06:36 main.go:104: received: 0A "\n"
2024/03/12 14:06:36 main.go:104: received: 0D "\r"
2024/03/12 14:06:36 main.go:104: received: 0A "\n"
2024/03/12 14:06:36 main.go:121: sending: 220103D9
2024/03/12 14:06:36 main.go:104: received: 22 "\""
2024/03/12 14:06:36 main.go:104: received: 0103D9 "\x01\x03\xd9"
2024/03/12 14:06:38 main.go:104: received: 22 "\""
2024/03/12 14:06:38 main.go:104: received: 0103D9 "\x01\x03\xd9"
2024/03/12 14:06:40 main.go:104: received: 22 "\""
2024/03/12 14:06:40 main.go:104: received: 0103D9 "\x01\x03\xd9"
scanning...
2024/03/12 14:06:47 main.go:50: found device: 5F:55:B0:D7:0E:1B, -64, 
2024/03/12 14:06:47 main.go:50: found device: D0:03:DF:AB:78:6F, -76, 
2024/03/12 14:06:47 main.go:50: found device: 7A:64:4B:F5:60:35, -88,
2024/03/12 14:06:47 main.go:50: found device: 7A:64:4B:F5:60:35, -88,
2024/03/12 14:06:47 main.go:50: found device: 54:2F:57:62:A0:E9, -94, 
2024/03/12 14:06:48 main.go:50: found device: 4D:4D:4D:40:A4:8E, -70, 
2024/03/12 14:06:48 main.go:50: found device: 4D:4D:4D:40:A4:8E, -70,
2024/03/12 14:06:48 main.go:50: found device: 49:92:32:66:14:17, -68, 
2024/03/12 14:06:48 main.go:50: found device: 49:92:32:66:14:17, -70,
2024/03/12 14:06:48 main.go:50: found device: E1:A1:83:A9:09:2A, -92, 
2024/03/12 14:06:48 main.go:50: found device: E1:A1:83:A9:09:2A, -92, S36 B64E LE
2024/03/12 14:06:48 main.go:50: found device: 46:46:46:EC:DC:B7, -88,
2024/03/12 14:06:48 main.go:50: found device: 46:46:46:EC:DC:B7, -88,
2024/03/12 14:06:48 main.go:50: found device: D0:03:DF:AB:78:6F, -76, 
2024/03/12 14:06:48 main.go:50: found device: 7C:0A:3F:51:1B:09, -86, 
2024/03/12 14:06:48 main.go:50: found device: 5F:55:B0:D7:0E:1B, -72,
2024/03/12 14:06:49 main.go:50: found device: D0:03:DF:AB:78:6F, -72, 
2024/03/12 14:06:49 main.go:50: found device: 49:92:32:66:14:17, -72,
2024/03/12 14:06:49 main.go:50: found device: 49:92:32:66:14:17, -72,
2024/03/12 14:06:49 main.go:50: found device: 65:03:49:F6:3A:9C, -64, 
2024/03/12 14:06:49 main.go:50: found device: 65:03:49:F6:3A:9C, -64,
2024/03/12 14:06:49 main.go:50: found device: 79:C7:BA:28:33:33, -66, 
2024/03/12 14:06:49 main.go:50: found device: 79:C7:BA:28:33:33, -66,
2024/03/12 14:06:49 main.go:50: found device: 5F:55:B0:D7:0E:1B, -68, 
2024/03/12 14:06:50 main.go:50: found device: 49:92:32:66:14:17, -64, 
2024/03/12 14:06:50 main.go:50: found device: 49:92:32:66:14:17, -62,
2024/03/12 14:06:50 main.go:50: found device: 65:03:49:F6:3A:9C, -68, 
2024/03/12 14:06:50 main.go:50: found device: 65:03:49:F6:3A:9C, -68,
2024/03/12 14:06:50 main.go:50: found device: 7C:0A:3F:51:1B:09, -84, 
2024/03/12 14:06:50 main.go:50: found device: 46:46:46:EC:DC:B7, -90, 
2024/03/12 14:06:50 main.go:50: found device: 46:46:46:EC:DC:B7, -88,
2024/03/12 14:06:50 main.go:50: found device: 79:C7:BA:28:33:33, -56, 
2024/03/12 14:06:50 main.go:50: found device: 79:C7:BA:28:33:33, -56,
2024/03/12 14:06:51 main.go:50: found device: 79:C7:BA:28:33:33, -58, 
2024/03/12 14:06:51 main.go:50: found device: 79:C7:BA:28:33:33, -58,
2024/03/12 14:06:51 main.go:50: found device: D0:03:DF:AB:78:6F, -76,
2024/03/12 14:06:51 main.go:50: found device: 4E:29:DB:25:BB:71, -90, 
2024/03/12 14:06:51 main.go:50: found device: 49:92:32:66:14:17, -72, 
2024/03/12 14:06:51 main.go:50: found device: 40:A8:20:13:16:0A, -58, 
2024/03/12 14:06:51 main.go:50: found device: 65:03:49:F6:3A:9C, -64, 
2024/03/12 14:06:51 main.go:50: found device: 65:03:49:F6:3A:9C, -64,
2024/03/12 14:06:52 main.go:50: found device: E1:A1:83:A9:09:2A, -92, 
2024/03/12 14:06:52 main.go:50: found device: 79:C7:BA:28:33:33, -68, 
2024/03/12 14:06:52 main.go:50: found device: 79:C7:BA:28:33:33, -68,
2024/03/12 14:06:52 main.go:50: found device: 4D:4D:4D:40:A4:8E, -68, 
2024/03/12 14:06:52 main.go:50: found device: 4E:29:DB:25:BB:71, -90, 
2024/03/12 14:06:52 main.go:50: found device: 4E:29:DB:25:BB:71, -90, S39 1D5C LE
2024/03/12 14:06:52 main.go:50: found device: 4E:29:DB:25:BB:71, -90,
2024/03/12 14:06:52 main.go:50: found device: 5F:55:B0:D7:0E:1B, -72,
2024/03/12 14:06:52 main.go:50: found device: 40:A8:20:13:16:0A, -60, 
2024/03/12 14:06:52 main.go:50: found device: 40:A8:20:13:16:0A, -60,
2024/03/12 14:06:52 main.go:50: found device: 65:03:49:F6:3A:9C, -68, 
2024/03/12 14:06:52 main.go:50: found device: 65:03:49:F6:3A:9C, -70,
2024/03/12 14:06:52 main.go:50: found device: 79:C7:BA:28:33:33, -56, 
2024/03/12 14:06:52 main.go:50: found device: 79:C7:BA:28:33:33, -56,
2024/03/12 14:06:53 main.go:50: found device: 46:73:E9:39:29:76, -94, 
2024/03/12 14:06:53 main.go:50: found device: 5F:55:B0:D7:0E:1B, -68, 
2024/03/12 14:06:53 main.go:50: found device: 49:92:32:66:14:17, -70,
2024/03/12 14:06:53 main.go:50: found device: 49:92:32:66:14:17, -70,
2024/03/12 14:06:53 main.go:50: found device: 65:03:49:F6:3A:9C, -72, 
2024/03/12 14:06:53 main.go:50: found device: 65:03:49:F6:3A:9C, -72,
2024/03/12 14:06:53 main.go:50: found device: 4E:29:DB:25:BB:71, -90,
2024/03/12 14:06:53 main.go:50: found device: 4D:4D:4D:40:A4:8E, -68, 
2024/03/12 14:06:53 main.go:50: found device: 4D:4D:4D:40:A4:8E, -68,
2024/03/12 14:06:53 main.go:50: found device: 79:C7:BA:28:33:33, -58,
2024/03/12 14:06:53 main.go:50: found device: 79:C7:BA:28:33:33, -58,
2024/03/12 14:06:54 main.go:50: found device: 49:92:32:66:14:17, -70, 
2024/03/12 14:06:54 main.go:50: found device: 49:92:32:66:14:17, -72,
2024/03/12 14:06:54 main.go:50: found device: D0:03:DF:AB:78:6F, -70,
2024/03/12 14:06:54 main.go:50: found device: 65:03:49:F6:3A:9C, -64, 
2024/03/12 14:06:54 main.go:50: found device: 65:03:49:F6:3A:9C, -64,
2024/03/12 14:06:54 main.go:50: found device: 46:46:46:EC:DC:B7, -88, 
2024/03/12 14:06:54 main.go:50: found device: 46:46:46:EC:DC:B7, -88,
2024/03/12 14:06:54 main.go:50: found device: 7A:64:4B:F5:60:35, -88,
2024/03/12 14:06:54 main.go:50: found device: 7A:64:4B:F5:60:35, -88,
2024/03/12 14:06:54 main.go:50: found device: D0:03:DF:AB:78:6F, -84, 
2024/03/12 14:06:54 main.go:50: found device: 5F:55:B0:D7:0E:1B, -64,
2024/03/12 14:06:55 main.go:50: found device: D0:03:DF:AB:78:6F, -76, 
2024/03/12 14:06:55 main.go:50: found device: E1:A1:83:A9:09:2A, -92,
2024/03/12 14:06:55 main.go:50: found device: 65:03:49:F6:3A:9C, -68,
2024/03/12 14:06:55 main.go:50: found device: 65:03:49:F6:3A:9C, -68,
2024/03/12 14:06:55 main.go:50: found device: 79:C7:BA:28:33:33, -56, 
2024/03/12 14:06:55 main.go:50: found device: 79:C7:BA:28:33:33, -56,
2024/03/12 14:06:55 main.go:50: found device: E1:A1:83:A9:09:2A, -92, 
2024/03/12 14:06:55 main.go:50: found device: E1:A1:83:A9:09:2A, -92, S36 B64E LE
2024/03/12 14:06:55 main.go:50: found device: 49:92:32:66:14:17, -68,
2024/03/12 14:06:55 main.go:50: found device: 49:92:32:66:14:17, -70,
2024/03/12 14:06:56 main.go:50: found device: 5F:55:B0:D7:0E:1B, -70, 
2024/03/12 14:06:56 main.go:50: found device: 46:46:46:EC:DC:B7, -90,
2024/03/12 14:06:56 main.go:50: found device: 46:46:46:EC:DC:B7, -88,
2024/03/12 14:06:56 main.go:50: found device: 65:03:49:F6:3A:9C, -72,
2024/03/12 14:06:56 main.go:50: found device: 65:03:49:F6:3A:9C, -70,
2024/03/12 14:06:56 main.go:50: found device: 4E:A9:45:DC:4E:3A, -92, 
2024/03/12 14:06:56 main.go:50: found device: 4E:A9:45:DC:4E:3A, -92,
2024/03/12 14:06:56 main.go:50: found device: 79:C7:BA:28:33:33, -58, 
2024/03/12 14:06:56 main.go:50: found device: 79:C7:BA:28:33:33, -58,
2024/03/12 14:06:56 main.go:50: found device: 49:92:32:66:14:17, -70, 
2024/03/12 14:06:56 main.go:50: found device: 49:92:32:66:14:17, -70,
2024/03/12 14:06:56 main.go:50: found device: D0:03:DF:AB:78:6F, -70,
2024/03/12 14:06:56 main.go:50: found device: 65:03:49:F6:3A:9C, -64, 
2024/03/12 14:06:56 main.go:50: found device: 65:03:49:F6:3A:9C, -64,
2024/03/12 14:06:56 main.go:50: found device: 4D:4D:4D:40:A4:8E, -64,
2024/03/12 14:06:56 main.go:50: found device: 4D:4D:4D:40:A4:8E, -64,
2024/03/12 14:06:57 main.go:50: found device: 4E:A9:45:DC:4E:3A, -90, 
2024/03/12 14:06:57 main.go:50: found device: 4E:A9:45:DC:4E:3A, -90,
2024/03/12 14:06:57 main.go:50: found device: 79:C7:BA:28:33:33, -66, 
2024/03/12 14:06:57 main.go:50: found device: 79:C7:BA:28:33:33, -66,
2024/03/12 14:06:57 main.go:50: found device: 5F:55:B0:D7:0E:1B, -70, 
2024/03/12 14:06:57 main.go:50: found device: 49:92:32:66:14:17, -64, 
2024/03/12 14:06:57 main.go:50: found device: 49:92:32:66:14:17, -64,
2024/03/12 14:06:57 main.go:50: found device: 46:46:46:EC:DC:B7, -78,
2024/03/12 14:06:57 main.go:50: found device: 46:46:46:EC:DC:B7, -78,
2024/03/12 14:06:57 main.go:50: found device: 65:03:49:F6:3A:9C, -70, 
2024/03/12 14:06:57 main.go:50: found device: 65:03:49:F6:3A:9C, -68,
2024/03/12 14:06:57 main.go:50: found device: 4E:A9:45:DC:4E:3A, -90, 
2024/03/12 14:06:57 main.go:50: found device: 4E:A9:45:DC:4E:3A, -92,
2024/03/12 14:06:58 main.go:50: found device: D0:03:DF:AB:78:6F, -86, 
2024/03/12 14:06:58 main.go:50: found device: 49:92:32:66:14:17, -68, 
2024/03/12 14:06:58 main.go:50: found device: 49:92:32:66:14:17, -68,
2024/03/12 14:06:58 main.go:50: found device: 4E:29:DB:25:BB:71, -90, 
2024/03/12 14:06:58 main.go:50: found device: 4E:29:DB:25:BB:71, -90, S39 1D5C LE
2024/03/12 14:06:58 main.go:50: found device: 4E:29:DB:25:BB:71, -88,
2024/03/12 14:06:58 main.go:50: found device: 7C:0A:3F:51:1B:09, -84, 
2024/03/12 14:06:58 main.go:50: found device: 79:C7:BA:28:33:33, -58, 
2024/03/12 14:06:58 main.go:50: found device: E1:A1:83:A9:09:2A, -92,
2024/03/12 14:06:58 main.go:50: found device: E1:A1:83:A9:09:2A, -92, S36 B64E LE
2024/03/12 14:06:59 main.go:50: found device: D0:03:DF:AB:78:6F, -70, 
2024/03/12 14:06:59 main.go:50: found device: 49:92:32:66:14:17, -72,
2024/03/12 14:06:59 main.go:50: found device: 49:92:32:66:14:17, -72,
2024/03/12 14:06:59 main.go:50: found device: 79:C7:BA:28:33:33, -66, 
2024/03/12 14:06:59 main.go:50: found device: 5F:55:B0:D7:0E:1B, -70, 
2024/03/12 14:06:59 main.go:50: found device: 4D:4D:4D:40:A4:8E, -64, 
2024/03/12 14:06:59 main.go:50: found device: 40:A8:20:13:16:0A, -54, 
2024/03/12 14:06:59 main.go:50: found device: 40:A8:20:13:16:0A, -54,
2024/03/12 14:06:59 main.go:50: found device: 46:73:E9:39:29:76, -92,
2024/03/12 14:06:59 main.go:50: found device: 7C:0A:3F:51:1B:09, -84, 
2024/03/12 14:07:00 main.go:50: found device: 49:92:32:66:14:17, -64, 
2024/03/12 14:07:00 main.go:50: found device: 46:46:46:EC:DC:B7, -88, 
2024/03/12 14:07:00 main.go:50: found device: 7A:64:4B:F5:60:35, -90, 
2024/03/12 14:07:00 main.go:50: found device: 7A:64:4B:F5:60:35, -90,
2024/03/12 14:07:00 main.go:50: found device: 4A:76:EA:55:DF:68, -90, 
2024/03/12 14:07:00 main.go:50: found device: 4E:A9:45:DC:4E:3A, -90,
2024/03/12 14:07:00 main.go:50: found device: 79:C7:BA:28:33:33, -56, 
2024/03/12 14:07:00 main.go:50: found device: 79:C7:BA:28:33:33, -56,
2024/03/12 14:07:00 main.go:50: found device: 5F:55:B0:D7:0E:1B, -70, 
2024/03/12 14:07:00 main.go:104: received: 3F "?"
2024/03/12 14:07:00 main.go:104: received: 0D0A3E4E4F20444154410D0A3E "\r\n>NO DATA\r\n>" <-- this should not happend. the device.Disconnect was called 20 seconds ago
2024/03/12 14:07:00 main.go:50: found device: 40:A8:20:13:16:0A, -64, 
2024/03/12 14:07:00 main.go:50: found device: D0:03:DF:AB:78:6F, -86, 
2024/03/12 14:07:01 main.go:50: found device: 4D:4D:4D:40:A4:8E, -72, 
2024/03/12 14:07:01 main.go:50: found device: 4D:4D:4D:40:A4:8E, -72,
2024/03/12 14:07:01 main.go:50: found device: 7C:0A:3F:51:1B:09, -84,
2024/03/12 14:07:01 main.go:50: found device: D0:03:DF:AB:78:6F, -76, 

@aykevl
Copy link
Member

aykevl commented Mar 12, 2024

Unfortunately the only Windows system I have available is a Windows ARM VM, where I can't get Bluetooth to work well (not even with an external Bluetooth USB stick). So I can't debug this myself.

I looked at the code and we do correctly call Close, which says:

Closes this Bluetooth LE device. This may close the connection to the device if this is the only app with a connection.

If the device doesn't actually get disconnected, my guess would be that we hold on a reference somewhere.
Can you try removing/commenting the code that scans for services/characteristics/etc? So that the code only connects, and then attempts to disconnect. Does the issue still occur in that case?

@roffe
Copy link

roffe commented Mar 12, 2024

it seems that in the second time around in the loop it can connect again to the BT device, but now when i DiscoverCharacteristics on the UART service it says it has 0 characteristics so i can't get a rx or tx characteristic to communicate with

package main

import (
	"log"
	"time"

	"github.com/roffe/gocan/dvi"
	"tinygo.org/x/bluetooth"
)

var (
	uartService = bluetooth.NewUUID([16]byte{0x6e, 0x40, 0x00, 0x01, 0xb5, 0xa3, 0xf3, 0x93, 0xe0, 0xa9, 0xe5, 0x0e, 0x24, 0xdc, 0xca, 0x9e})

	gatUUID = map[string]string{
		"00001800-0000-1000-8000-00805f9b34fb": "Generic Access",
		"00001801-0000-1000-8000-00805f9b34fb": "Generic Attribute",
		"6e400001-b5a3-f393-e0a9-e50e24dcca9e": "UART service",
	}

	characteristicUUID = map[string]string{
		"6e400003-b5a3-f393-e0a9-e50e24dcca9e": "TX",
		"6e400002-b5a3-f393-e0a9-e50e24dcca9e": "RX",
	}
)

var adapter = bluetooth.DefaultAdapter

func init() {
	log.SetFlags(log.LstdFlags | log.Lshortfile)
}

func main() {
	// Enable BLE interface.
	must("enable BLE stack", adapter.Enable())
	for i := 0; i < 3; i++ {
		main2()
		time.Sleep(5 * time.Second)
	}
}

func main2() {
	ch := make(chan bluetooth.ScanResult, 1)

	addr := bluetooth.Address{}
	addr.Set("64:B7:08:5F:F6:9A")

	var err error
	ch <- bluetooth.ScanResult{Address: addr}

	var device bluetooth.Device
	select {
	case d := <-ch:
		device, err = adapter.Connect(d.Address, bluetooth.ConnectionParams{})
		if err != nil {
			log.Fatal("failed to connect:", err)
		}
		log.Printf("connected to %s", d.Address.String())
	case <-time.After(10 * time.Second):
		log.Fatal("Did not find any OBDX Pro GT device")
	}

	svcs, err := device.DiscoverServices(nil)
	if err != nil {
		log.Fatal("failed to discover services:", err)
	}

	log.Println("services found:", len(svcs))
	for _, svc := range svcs {
		if name, ok := gatUUID[svc.UUID().String()]; ok {
			log.Printf("service: %s (%s)", svc.String(), name)
		} else {
			log.Printf("service: %s", svc.String())
		}
	}

	srvc := svcs[2]

	chars, err := srvc.DiscoverCharacteristics(nil)
	if err != nil {
		log.Fatal("failed to discover characteristics:", err)
	}

	for _, char := range chars {
		if name, ok := characteristicUUID[char.UUID().String()]; ok {
			log.Printf("characteristic: %s (%s)", char.String(), name)
		} else {
			log.Printf("characteristic: %s", char.String())
		}
	}

	if len(chars) < 2 {
		log.Fatal("expected at least 2 characteristics got ", len(chars))
	}

	rx := chars[0]
	tx := chars[1]

	err = rx.EnableNotifications(func(buf []byte) {
		log.Printf("received: %X %q", buf, buf)
	})

	if err != nil {
		log.Fatal("failed to enable notifications:", err)
	}

	for i := 0; i < 3; i++ {
		tx.Write([]byte("\r\n"))
		time.Sleep(50 * time.Millisecond)
	}

	payload := dvi.New(0x22, []byte{0x03}).Bytes()
	log.Printf("sending: %X", payload)

	for i := 0; i < 3; i++ {
		tx.Write(payload)
		time.Sleep(2 * time.Second)
	}

	if err := device.Disconnect(); err != nil {
		log.Fatal("failed to disconnect:", err)
	}
}

func must(action string, err error) {
	if err != nil {
		log.Fatal("failed to " + action + ": " + err.Error())
	}
}
PS: 35 2024-03-12 18:10:53 bttest >go run .
2024/03/12 18:10:54 main.go:57: connected to 64:B7:08:5F:F6:9A
2024/03/12 18:10:56 main.go:67: services found: 3
2024/03/12 18:10:56 main.go:70: service: 00001801-0000-1000-8000-00805f9b34fb (Generic Attribute)
2024/03/12 18:10:56 main.go:70: service: 00001800-0000-1000-8000-00805f9b34fb (Generic Access)
2024/03/12 18:10:56 main.go:70: service: 6e400001-b5a3-f393-e0a9-e50e24dcca9e (UART service)
2024/03/12 18:10:56 main.go:85: characteristic: 6e400003-b5a3-f393-e0a9-e50e24dcca9e (TX)
2024/03/12 18:10:56 main.go:85: characteristic: 6e400002-b5a3-f393-e0a9-e50e24dcca9e (RX)
2024/03/12 18:10:56 main.go:99: received: 0D "\r"
2024/03/12 18:10:56 main.go:99: received: 0A "\n"
2024/03/12 18:10:57 main.go:99: received: 0D "\r"
2024/03/12 18:10:57 main.go:99: received: 0A "\n"
2024/03/12 18:10:57 main.go:99: received: 0D "\r"
2024/03/12 18:10:57 main.go:99: received: 0A "\n"
2024/03/12 18:10:57 main.go:112: sending: 220103D9
2024/03/12 18:10:57 main.go:99: received: 22 "\""
2024/03/12 18:10:57 main.go:99: received: 0103D9 "\x01\x03\xd9"
2024/03/12 18:10:59 main.go:99: received: 22 "\""
2024/03/12 18:10:59 main.go:99: received: 0103D9 "\x01\x03\xd9"
2024/03/12 18:11:01 main.go:99: received: 22 "\""
2024/03/12 18:11:01 main.go:99: received: 0103D9 "\x01\x03\xd9"
2024/03/12 18:11:08 main.go:57: connected to 64:B7:08:5F:F6:9A
2024/03/12 18:11:08 main.go:67: services found: 3
2024/03/12 18:11:08 main.go:70: service: 00001801-0000-1000-8000-00805f9b34fb (Generic Attribute)
2024/03/12 18:11:08 main.go:70: service: 00001800-0000-1000-8000-00805f9b34fb (Generic Access)
2024/03/12 18:11:08 main.go:70: service: 6e400001-b5a3-f393-e0a9-e50e24dcca9e (UART service)
2024/03/12 18:11:08 main.go:92: expected at least 2 characteristics got0
exit status 1

@hgqcode
Copy link
Author

hgqcode commented Mar 13, 2024

It doesn't work when i use disconnect device

What is the error? What system are you on? How can I reproduce this issue? It's impossible to help or fix the bug without more information.

I'm the same with Roffe.

@hgqcode
Copy link
Author

hgqcode commented Mar 13, 2024

Unfortunately the only Windows system I have available is a Windows ARM VM, where I can't get Bluetooth to work well (not even with an external Bluetooth USB stick). So I can't debug this myself.

I looked at the code and we do correctly call Close, which says:

Closes this Bluetooth LE device. This may close the connection to the device if this is the only app with a connection.

If the device doesn't actually get disconnected, my guess would be that we hold on a reference somewhere. Can you try removing/commenting the code that scans for services/characteristics/etc? So that the code only connects, and then attempts to disconnect. Does the issue still occur in that case?

I tried. Disconnect successfully when i removing the code that scans for characteristics. So I think you can check out this code.
chars, err := srvc.DiscoverCharacteristics(nil)

@roffe
Copy link

roffe commented Mar 13, 2024

I'm wildly speculating now as i don't know anything about bluetooth development but it feels like the characteristics we obtain after the scan is what's not being released, maybe there should be a .Close method on them to free them once you are done with a characteristic?

@hgqcode hgqcode closed this as completed Mar 14, 2024
@roffe
Copy link

roffe commented Mar 14, 2024

oh well, it's one of those projects, you close issues that is not solved :D.

Good thing i discovered this is not usable in my project before getting to invovled

@hgqcode hgqcode reopened this Mar 14, 2024
@hgqcode
Copy link
Author

hgqcode commented Mar 14, 2024

oh well, it's one of those projects, you close issues that is not solved :D.

Good thing i discovered this is not usable in my project before getting to invovled

oh sorry, It was an operational error.I don't want to close issues.

@aykevl
Copy link
Member

aykevl commented Mar 14, 2024

maybe there should be a .Close method on them to free them once you are done with a characteristic?

If that's the case, this is something the bluetooth library should do internally on disconnect. Not something the API user should have to worry about.

(Again, I'd like to help but don't have the right system available).

@hgqcode
Copy link
Author

hgqcode commented Mar 15, 2024

maybe there should be a .Close method on them to free them once you are done with a characteristic?

If that's the case, this is something the bluetooth library should do internally on disconnect. Not something the API user should have to worry about.

(Again, I'd like to help but don't have the right system available).

I think that could be one way. So what can i do if I want the function to work properly now.Can you give me some advice? Very anxious.Thank you.

@ansoni-san
Copy link
Contributor

ansoni-san commented Mar 15, 2024

Maybe just patch the code. It's fairly simple code underneath. You probably just need to free / uninitialise something properly.

Disconnection is working great for me on Windows, however it does not always truly disconnect the device immediately if it is being used for something.

@hgqcode
Copy link
Author

hgqcode commented Mar 15, 2024

Maybe just patch the code. It's fairly simple code underneath. You probably just need to free / uninitialise something properly.

Disconnection is working great for me on Windows, however it does not always truly disconnect the device immediately if it is being used for something.

Thany you! Can you show me what to change?As far as I know,the code has not free / uninitialise method.

@hellosqi
Copy link

I also encountered the same problem

@ansoni-san
Copy link
Contributor

ansoni-san commented Jul 13, 2024

@hgqcode @hellosqi You could narrow it down by disabling parts of DiscoverCharacteristics until it stops happening, and then dig into that.

I don't have time to help at the moment (and also we internally forked this project and haven't updated in a while), but if no-one has looked at it in the next week or so I can try to see if there's some way we can convince Windows to let go of the device sooner.

It may be possible or it may not, as with the WinRT Bluetooth API you don't own the device, you just own a session. It provides no guarantees that it will disconnect the physical device behind your session. But there probably is something that is making it hang around longer than it should.

I have a feeling that we see a variety of side-effects from this, but we have worked around it in our higher level code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

6 participants