fix: conectar com BT 4.0
This commit is contained in:
parent
f5da209d22
commit
d573476c70
@ -2,7 +2,10 @@
|
|||||||
"permissions": {
|
"permissions": {
|
||||||
"allow": [
|
"allow": [
|
||||||
"Bash(go build:*)",
|
"Bash(go build:*)",
|
||||||
"Bash(git:*)"
|
"Bash(git:*)",
|
||||||
|
"Bash(cmd.exe *)",
|
||||||
|
"Bash(go env *)",
|
||||||
|
"Bash(go install *)"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -263,6 +263,7 @@ void setup() {
|
|||||||
|
|
||||||
// BLE — NUS
|
// BLE — NUS
|
||||||
BLEDevice::init("KVMote");
|
BLEDevice::init("KVMote");
|
||||||
|
|
||||||
pServer = BLEDevice::createServer();
|
pServer = BLEDevice::createServer();
|
||||||
pServer->setCallbacks(new ServerCallbacks());
|
pServer->setCallbacks(new ServerCallbacks());
|
||||||
|
|
||||||
9
frontend/dist/index.html
vendored
9
frontend/dist/index.html
vendored
@ -162,17 +162,12 @@
|
|||||||
|
|
||||||
<div class="is-flex is-align-items-center mb-4" style="font-size: 0.85rem; color: #888;">
|
<div class="is-flex is-align-items-center mb-4" style="font-size: 0.85rem; color: #888;">
|
||||||
<span class="status-dot" :style="{ backgroundColor: detected ? '#3498db' : '#555' }"></span>
|
<span class="status-dot" :style="{ backgroundColor: detected ? '#3498db' : '#555' }"></span>
|
||||||
<span x-text="detected ? 'KVMote (BLE) detectado' : 'Buscando dispositivo...'"></span>
|
<span x-text="detected ? 'KVMote (BLE) detectado' : ''"></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="columns is-mobile is-gapless mb-2">
|
<div class="mb-2">
|
||||||
<div class="column pr-1">
|
|
||||||
<button class="btn-action" @click="detect()">Detectar</button>
|
|
||||||
</div>
|
|
||||||
<div class="column pl-1">
|
|
||||||
<button class="btn-action btn-connect" @click="toggleConnect()" x-text="connected ? 'Desconectar' : 'Conectar'"></button>
|
<button class="btn-action btn-connect" @click="toggleConnect()" x-text="connected ? 'Desconectar' : 'Conectar'"></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="field mb-4">
|
<div class="field mb-4">
|
||||||
<div class="is-flex is-align-items-center is-justify-content-space-between">
|
<div class="is-flex is-align-items-center is-justify-content-space-between">
|
||||||
|
|||||||
@ -4,12 +4,24 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"tinygo.org/x/bluetooth"
|
"tinygo.org/x/bluetooth"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func bleLog(msg string) {
|
||||||
|
line := fmt.Sprintf("[BLE] %s | %s\n", time.Now().Format("15:04:05.000"), msg)
|
||||||
|
fmt.Print(line)
|
||||||
|
f, err := os.OpenFile("kvmote_debug.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
f.WriteString(line)
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
NusServiceUUID = bluetooth.NewUUID([16]byte{0x6e, 0x40, 0x00, 0x01, 0xb5, 0xa3, 0xf3, 0x93, 0xe0, 0xa9, 0xe5, 0x0e, 0x24, 0xdc, 0xca, 0x9e})
|
NusServiceUUID = bluetooth.NewUUID([16]byte{0x6e, 0x40, 0x00, 0x01, 0xb5, 0xa3, 0xf3, 0x93, 0xe0, 0xa9, 0xe5, 0x0e, 0x24, 0xdc, 0xca, 0x9e})
|
||||||
NusRxUUID = bluetooth.NewUUID([16]byte{0x6e, 0x40, 0x00, 0x02, 0xb5, 0xa3, 0xf3, 0x93, 0xe0, 0xa9, 0xe5, 0x0e, 0x24, 0xdc, 0xca, 0x9e})
|
NusRxUUID = bluetooth.NewUUID([16]byte{0x6e, 0x40, 0x00, 0x02, 0xb5, 0xa3, 0xf3, 0x93, 0xe0, 0xa9, 0xe5, 0x0e, 0x24, 0xdc, 0xca, 0x9e})
|
||||||
@ -45,15 +57,19 @@ func (t *RealBleTransport) Detect(ctx context.Context) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
foundChan := make(chan bluetooth.Address, 1)
|
foundChan := make(chan bluetooth.Address, 1)
|
||||||
err := t.adapter.Scan(func(adapter *bluetooth.Adapter, result bluetooth.ScanResult) {
|
go func() {
|
||||||
if result.LocalName() == "KVMote" {
|
t.adapter.Scan(func(adapter *bluetooth.Adapter, result bluetooth.ScanResult) {
|
||||||
|
hasUUID := result.HasServiceUUID(NusServiceUUID)
|
||||||
|
bleLog(fmt.Sprintf("visto: nome=%q hasNUS=%v addr=%s", result.LocalName(), hasUUID, result.Address.String()))
|
||||||
|
if result.LocalName() == "KVMote" || hasUUID {
|
||||||
adapter.StopScan()
|
adapter.StopScan()
|
||||||
foundChan <- result.Address
|
select {
|
||||||
|
case foundChan <- result.Address:
|
||||||
|
default:
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
if err != nil {
|
}()
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case addr := <-foundChan:
|
case addr := <-foundChan:
|
||||||
@ -77,24 +93,65 @@ func (t *RealBleTransport) Connect(ctx context.Context) error {
|
|||||||
addr := t.address
|
addr := t.address
|
||||||
t.mu.Unlock()
|
t.mu.Unlock()
|
||||||
|
|
||||||
fmt.Println("[BLE] Conectando...")
|
var device bluetooth.Device
|
||||||
device, err := t.adapter.Connect(addr, bluetooth.ConnectionParams{})
|
var services []bluetooth.DeviceService
|
||||||
|
var err error
|
||||||
|
|
||||||
|
for cycle := 1; cycle <= 3; cycle++ {
|
||||||
|
if cycle > 1 {
|
||||||
|
bleLog(fmt.Sprintf("Reconectando (ciclo %d)...", cycle))
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
}
|
||||||
|
|
||||||
|
bleLog(fmt.Sprintf("Conectando (ciclo %d)...", cycle))
|
||||||
|
device, err = t.adapter.Connect(addr, bluetooth.ConnectionParams{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
bleLog(fmt.Sprintf(" Connect erro: %v", err))
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
t.mu.Lock()
|
t.mu.Lock()
|
||||||
t.device = device
|
t.device = device
|
||||||
t.mu.Unlock()
|
t.mu.Unlock()
|
||||||
|
|
||||||
fmt.Println("[BLE] Buscando Serviço...")
|
// Delay crucial para BT 4.0 estabilizar a conexão antes de pedir serviços
|
||||||
services, err := device.DiscoverServices([]bluetooth.UUID{NusServiceUUID})
|
bleLog("Aguardando estabilização (2s)...")
|
||||||
if err != nil || len(services) == 0 {
|
time.Sleep(2 * time.Second)
|
||||||
return errors.New("serviço não encontrado")
|
|
||||||
|
bleLog("DiscoverServices...")
|
||||||
|
services, err = device.DiscoverServices(nil)
|
||||||
|
if err != nil {
|
||||||
|
bleLog(fmt.Sprintf(" DiscoverServices erro: %v", err))
|
||||||
|
// Tenta mais uma vez após um pequeno delay antes de desistir do ciclo
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
bleLog("DiscoverServices (retry)...")
|
||||||
|
services, err = device.DiscoverServices(nil)
|
||||||
|
if err != nil {
|
||||||
|
bleLog(fmt.Sprintf(" DiscoverServices retry erro: %v", err))
|
||||||
|
go func() { defer func() { recover() }(); device.Disconnect() }()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("erro ao descobrir serviços: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println("[BLE] Buscando RX...")
|
bleLog(fmt.Sprintf("Serviços encontrados: %d", len(services)))
|
||||||
chars, err := services[0].DiscoverCharacteristics([]bluetooth.UUID{NusRxUUID})
|
nusIdx := -1
|
||||||
|
for i, s := range services {
|
||||||
|
bleLog(fmt.Sprintf(" [%d] %s", i, s.UUID().String()))
|
||||||
|
if s.UUID() == NusServiceUUID {
|
||||||
|
nusIdx = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if nusIdx < 0 {
|
||||||
|
return errors.New("serviço NUS não encontrado")
|
||||||
|
}
|
||||||
|
|
||||||
|
bleLog("Buscando característica RX...")
|
||||||
|
chars, err := services[nusIdx].DiscoverCharacteristics([]bluetooth.UUID{NusRxUUID})
|
||||||
if err != nil || len(chars) == 0 {
|
if err != nil || len(chars) == 0 {
|
||||||
return errors.New("característica não encontrada")
|
return errors.New("característica não encontrada")
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user