From 56ddca53a456653d71c38585b34839bce517d941 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?PontualTech=20/=20Karl=C3=A3o?= Date: Wed, 29 Apr 2026 09:02:10 -0300 Subject: [PATCH] =?UTF-8?q?fix(ble):=20dispatcher=20rotea=20chunks=20JBD?= =?UTF-8?q?=20de=20continua=C3=A7=C3=A3o=20v1.10.15?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🎉 BMS RESPONDEU! Log v1.10.14 mostrou 3 chunks chegando do BMS do Karlão: - Chunk 1 (20b): dd 03 00 22 05 2b 02 8a... (header JBD + dados) - Chunk 2 (20b): 00 00 d0 15 03 04 01 0b b7... (continuação) - Chunk 3 (1b): 77 (end-of-frame) Decoded: 13.23V (4S LiFePO4), +6.50A carregando, 21% SoC, 175 ciclos, 4 células, 27°C. PROTOCOLO JBD CORRETO. Bug do parser: dispatcher só chamava bmsHandleChunk se primeiro byte do chunk atual era 0xDD. Chunks 2 e 3 começam com 0x00 e 0x77 — não roteados → reassembly nunca completou → dev.bms.voltage ficou null → bmsTryProtocols viu '✗ JBD-0x03 sem RX'. Fix em ambos os paths (Web Bluetooth + Capacitor): - Se _bmsBuffers.has(deviceId), é continuação → roteia direto pra bmsHandleChunk - Buffer vazio: primeiro byte determina protocolo Próxima rodada deve mostrar 'BMS lido · 13.23V · 6.50A · 21%...' + dashboard cheio. Co-Authored-By: Claude Opus 4.7 (1M context) --- app/diario-bordo.html | 15 +++++++++++++-- server/public/index.html | 15 +++++++++++++-- server/public/sw.js | 2 +- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/app/diario-bordo.html b/app/diario-bordo.html index 384b412..d7d7385 100644 --- a/app/diario-bordo.html +++ b/app/diario-bordo.html @@ -6091,6 +6091,12 @@ async function bmsProbeWebBluetooth(deviceId,deviceName){ const dv=ev.target.value; const hex=Array.from(new Uint8Array(dv.buffer)).map(b=>b.toString(16).padStart(2,'0')).join(' '); setBleDiag(`← RX ${dv.byteLength}b: ${hex.slice(0,100)}${hex.length>100?'...':''}`,'ok'); + // Se há buffer pendente JBD, é chunk de continuação — roteia sempre + if(_bmsBuffers.has(deviceId)){ + bmsHandleChunk(deviceId,dv,deviceName); + return; + } + // Buffer vazio: primeiro byte determina protocolo (início de novo pacote) const first=new Uint8Array(dv.buffer)[0]; if(first===0xDD)bmsHandleChunk(deviceId,dv,deviceName); else if(first===0xAA)bmsHandleJK(deviceId,dv,deviceName); @@ -6192,7 +6198,12 @@ async function bmsProbeAndAttach(deviceId,deviceName){ const dv=parseDataView(ev.value); const hex=Array.from(new Uint8Array(dv.buffer)).map(b=>b.toString(16).padStart(2,'0')).join(' '); setBleDiag('← RX '+dv.byteLength+'b: '+hex.slice(0,100)+(hex.length>100?'...':''),'ok'); - // Detecta protocolo por byte de início + // Se buffer JBD pendente, é continuação — roteia sempre + if(_bmsBuffers.has(deviceId)){ + bmsHandleChunk(deviceId,dv,deviceName); + return; + } + // Detecta protocolo por byte de início (novo pacote) const first=new Uint8Array(dv.buffer)[0]; if(first===0xDD)bmsHandleChunk(deviceId,dv,deviceName); // JBD else if(first===0xAA)bmsHandleJK(deviceId,dv,deviceName); // JK BMS @@ -6446,7 +6457,7 @@ async function removeBluetoothDevice(id){ renderBluetoothCard(); } -const APP_VERSION='1.10.14'; +const APP_VERSION='1.10.15'; function renderBluetoothCard(){ const el=document.getElementById('bt-list'); const supportEl=document.getElementById('bt-support'); diff --git a/server/public/index.html b/server/public/index.html index 384b412..d7d7385 100644 --- a/server/public/index.html +++ b/server/public/index.html @@ -6091,6 +6091,12 @@ async function bmsProbeWebBluetooth(deviceId,deviceName){ const dv=ev.target.value; const hex=Array.from(new Uint8Array(dv.buffer)).map(b=>b.toString(16).padStart(2,'0')).join(' '); setBleDiag(`← RX ${dv.byteLength}b: ${hex.slice(0,100)}${hex.length>100?'...':''}`,'ok'); + // Se há buffer pendente JBD, é chunk de continuação — roteia sempre + if(_bmsBuffers.has(deviceId)){ + bmsHandleChunk(deviceId,dv,deviceName); + return; + } + // Buffer vazio: primeiro byte determina protocolo (início de novo pacote) const first=new Uint8Array(dv.buffer)[0]; if(first===0xDD)bmsHandleChunk(deviceId,dv,deviceName); else if(first===0xAA)bmsHandleJK(deviceId,dv,deviceName); @@ -6192,7 +6198,12 @@ async function bmsProbeAndAttach(deviceId,deviceName){ const dv=parseDataView(ev.value); const hex=Array.from(new Uint8Array(dv.buffer)).map(b=>b.toString(16).padStart(2,'0')).join(' '); setBleDiag('← RX '+dv.byteLength+'b: '+hex.slice(0,100)+(hex.length>100?'...':''),'ok'); - // Detecta protocolo por byte de início + // Se buffer JBD pendente, é continuação — roteia sempre + if(_bmsBuffers.has(deviceId)){ + bmsHandleChunk(deviceId,dv,deviceName); + return; + } + // Detecta protocolo por byte de início (novo pacote) const first=new Uint8Array(dv.buffer)[0]; if(first===0xDD)bmsHandleChunk(deviceId,dv,deviceName); // JBD else if(first===0xAA)bmsHandleJK(deviceId,dv,deviceName); // JK BMS @@ -6446,7 +6457,7 @@ async function removeBluetoothDevice(id){ renderBluetoothCard(); } -const APP_VERSION='1.10.14'; +const APP_VERSION='1.10.15'; function renderBluetoothCard(){ const el=document.getElementById('bt-list'); const supportEl=document.getElementById('bt-support'); diff --git a/server/public/sw.js b/server/public/sw.js index cbab32c..1ad12bf 100644 --- a/server/public/sw.js +++ b/server/public/sw.js @@ -1,7 +1,7 @@ // Shivao Service Worker — offline real // Estratégia: shell precachado, tiles cache-first, windy network-first, /api passa direto. // Versão usada nos cache names — bumpa essa string pra invalidar caches antigos em deploys. -const VERSION = 'shivao-v1.10.14'; +const VERSION = 'shivao-v1.10.15'; const SHELL_CACHE = `shivao-shell-${VERSION}`; const TILES_CACHE = 'shivao-tiles-v1'; // separado pra não invalidar tiles em update do shell const WINDY_CACHE = `shivao-windy-${VERSION}`;