Compare commits

...

2 Commits

Author SHA1 Message Date
Ricardo Carneiro
621723ca83 fix: Ajustes de conexao 2026-05-12 11:38:48 -03:00
Ricardo Carneiro
d573476c70 fix: conectar com BT 4.0 2026-05-12 10:36:28 -03:00
5 changed files with 91 additions and 35 deletions

View File

@ -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 *)"
] ]
} }
} }

View File

@ -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());

View File

@ -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">

View File

@ -258,8 +258,8 @@ func (e *Engine) shouldReturnToHost() bool {
switch e.clientPos { switch e.clientPos {
case PosLeft: return e.virtualX > 600 case PosLeft: return e.virtualX > 600
case PosRight: return e.virtualX < -500 case PosRight: return e.virtualX < -500
case PosBelow: return e.virtualY < -150 case PosBelow: return e.virtualY < -300
case PosAbove: return e.virtualY > 150 case PosAbove: return e.virtualY > 300
} }
return false return false
} }

View File

@ -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")
} }