fix(ble): força write em ff02 mesmo sem property declarada v1.10.14
Some checks are pending
Build Android (APK + AAB) / build-android (push) Waiting to run

BMS chinês declara ff02 com property [read] apenas, MAS aceita writes
em background. Plugin Capacitor força através (Android stack permite).
Web Bluetooth do Chrome respeita spec — recusa writeValue se char
não tem write/wnr declarado.

Workaround: se nenhuma char tem write declarada, força usar primeira
não-notify (geralmente ff02). Tenta writeValue mesmo assim.
Browser pode lançar SecurityError, mas se BMS aceitar = funciona.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
PontualTech / Karlão 2026-04-29 08:56:52 -03:00
parent 0999da3b51
commit 4cf670ae76
3 changed files with 17 additions and 5 deletions

View file

@ -6079,7 +6079,13 @@ async function bmsProbeWebBluetooth(deviceId,deviceName){
if(!notifyChar&&(p.notify||p.indicate))notifyChar=c; if(!notifyChar&&(p.notify||p.indicate))notifyChar=c;
if(!writeChar&&(p.write||p.writeWithoutResponse))writeChar=c; if(!writeChar&&(p.write||p.writeWithoutResponse))writeChar=c;
} }
if(!notifyChar||!writeChar){setBleDiag('Sem chars notify+write','err');return false} if(!notifyChar){setBleDiag('Sem char notify','err');return false}
if(!writeChar){
// Workaround: BMS chinês declara ff02 só [read] mas aceita writes (firmware permissivo).
// Força usar primeira char não-notify e tenta writeValue mesmo assim.
writeChar=chars.find(c=>c.uuid.toLowerCase()!==notifyChar.uuid.toLowerCase())||chars[0];
setBleDiag(`⚠ Sem property write · forçando ${writeChar.uuid.slice(4,8)}`,'warn');
}
setBleDiag(`Notify=${notifyChar.uuid.slice(4,8)} Write=${writeChar.uuid.slice(4,8)}`,'ok'); setBleDiag(`Notify=${notifyChar.uuid.slice(4,8)} Write=${writeChar.uuid.slice(4,8)}`,'ok');
notifyChar.addEventListener('characteristicvaluechanged',(ev)=>{ notifyChar.addEventListener('characteristicvaluechanged',(ev)=>{
const dv=ev.target.value; const dv=ev.target.value;
@ -6440,7 +6446,7 @@ async function removeBluetoothDevice(id){
renderBluetoothCard(); renderBluetoothCard();
} }
const APP_VERSION='1.10.13'; const APP_VERSION='1.10.14';
function renderBluetoothCard(){ function renderBluetoothCard(){
const el=document.getElementById('bt-list'); const el=document.getElementById('bt-list');
const supportEl=document.getElementById('bt-support'); const supportEl=document.getElementById('bt-support');

View file

@ -6079,7 +6079,13 @@ async function bmsProbeWebBluetooth(deviceId,deviceName){
if(!notifyChar&&(p.notify||p.indicate))notifyChar=c; if(!notifyChar&&(p.notify||p.indicate))notifyChar=c;
if(!writeChar&&(p.write||p.writeWithoutResponse))writeChar=c; if(!writeChar&&(p.write||p.writeWithoutResponse))writeChar=c;
} }
if(!notifyChar||!writeChar){setBleDiag('Sem chars notify+write','err');return false} if(!notifyChar){setBleDiag('Sem char notify','err');return false}
if(!writeChar){
// Workaround: BMS chinês declara ff02 só [read] mas aceita writes (firmware permissivo).
// Força usar primeira char não-notify e tenta writeValue mesmo assim.
writeChar=chars.find(c=>c.uuid.toLowerCase()!==notifyChar.uuid.toLowerCase())||chars[0];
setBleDiag(`⚠ Sem property write · forçando ${writeChar.uuid.slice(4,8)}`,'warn');
}
setBleDiag(`Notify=${notifyChar.uuid.slice(4,8)} Write=${writeChar.uuid.slice(4,8)}`,'ok'); setBleDiag(`Notify=${notifyChar.uuid.slice(4,8)} Write=${writeChar.uuid.slice(4,8)}`,'ok');
notifyChar.addEventListener('characteristicvaluechanged',(ev)=>{ notifyChar.addEventListener('characteristicvaluechanged',(ev)=>{
const dv=ev.target.value; const dv=ev.target.value;
@ -6440,7 +6446,7 @@ async function removeBluetoothDevice(id){
renderBluetoothCard(); renderBluetoothCard();
} }
const APP_VERSION='1.10.13'; const APP_VERSION='1.10.14';
function renderBluetoothCard(){ function renderBluetoothCard(){
const el=document.getElementById('bt-list'); const el=document.getElementById('bt-list');
const supportEl=document.getElementById('bt-support'); const supportEl=document.getElementById('bt-support');

View file

@ -1,7 +1,7 @@
// Shivao Service Worker — offline real // Shivao Service Worker — offline real
// Estratégia: shell precachado, tiles cache-first, windy network-first, /api passa direto. // 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. // Versão usada nos cache names — bumpa essa string pra invalidar caches antigos em deploys.
const VERSION = 'shivao-v1.10.13'; const VERSION = 'shivao-v1.10.14';
const SHELL_CACHE = `shivao-shell-${VERSION}`; const SHELL_CACHE = `shivao-shell-${VERSION}`;
const TILES_CACHE = 'shivao-tiles-v1'; // separado pra não invalidar tiles em update do shell const TILES_CACHE = 'shivao-tiles-v1'; // separado pra não invalidar tiles em update do shell
const WINDY_CACHE = `shivao-windy-${VERSION}`; const WINDY_CACHE = `shivao-windy-${VERSION}`;