diff --git a/app/diario-bordo.html b/app/diario-bordo.html
index d65063b..43731dc 100644
--- a/app/diario-bordo.html
+++ b/app/diario-bordo.html
@@ -6057,7 +6057,18 @@ async function bmsProbeAndAttach(deviceId,deviceName){
setBleDiag('Não achei chars notify+write em services vendor','err');
return false;
}
- setBleDiag(`Notify=${notifyChar.slice(4,8)} Write=${writeChar.slice(4,8)} Svc=${foundService.slice(4,8)}`,'ok');
+ // Detecta se write char só aceita writeWithoutResponse
+ let writeOnlyWnr=false;
+ for(const svc of allSvcs){
+ if((svc.uuid||'').toLowerCase()!==foundService)continue;
+ for(const c of (svc.characteristics||[])){
+ if((c.uuid||'').toLowerCase()===writeChar){
+ const p=c.properties||{};
+ writeOnlyWnr=(!p.write&&p.writeWithoutResponse);
+ }
+ }
+ }
+ setBleDiag(`Notify=${notifyChar.slice(4,8)} Write=${writeChar.slice(4,8)}${writeOnlyWnr?' (force-wnr)':''} Svc=${foundService.slice(4,8)}`,'ok');
// Subscribe + handler
const listenerKey='notification|'+deviceId+'|'+foundService+'|'+notifyChar;
ble.addListener(listenerKey,(ev)=>{
@@ -6079,6 +6090,7 @@ async function bmsProbeAndAttach(deviceId,deviceName){
dev.bmsService=foundService;
dev.bmsNotifyChar=notifyChar;
dev.bmsWriteChar=writeChar;
+ dev.bmsForceWnr=writeOnlyWnr;
dev.isJBD=true;
saveState();
}
@@ -6094,7 +6106,9 @@ async function bmsWriteCmd(deviceId,bytes,withoutResponse){
const ble=window.Capacitor?.Plugins?.BluetoothLe;
const dev=state.btDevices?.find(d=>d.id===deviceId);
if(!ble||!dev?.bmsService||!dev?.bmsWriteChar)throw new Error('config BMS ausente');
- const fn=withoutResponse?'writeWithoutResponse':'write';
+ // Se a write char só aceita wnr, força writeWithoutResponse independente do parâmetro
+ const useWnr=withoutResponse||dev.bmsForceWnr;
+ const fn=useWnr?'writeWithoutResponse':'write';
await ble[fn]({deviceId,service:dev.bmsService,characteristic:dev.bmsWriteChar,value:bytesToBase64(bytes)});
}
@@ -6289,7 +6303,7 @@ async function removeBluetoothDevice(id){
renderBluetoothCard();
}
-const APP_VERSION='1.10.6';
+const APP_VERSION='1.10.7';
function renderBluetoothCard(){
const el=document.getElementById('bt-list');
const supportEl=document.getElementById('bt-support');
diff --git a/mobile/android/app/build.gradle b/mobile/android/app/build.gradle
index 4df6605..f69740d 100644
--- a/mobile/android/app/build.gradle
+++ b/mobile/android/app/build.gradle
@@ -7,8 +7,8 @@ android {
applicationId "br.com.pontualtech.shivao"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
- versionCode 22
- versionName "1.10.6"
+ versionCode 23
+ versionName "1.10.7"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
aaptOptions {
// Files and dirs to omit from the packaged assets dir, modified to accommodate modern web apps.
diff --git a/mobile/package.json b/mobile/package.json
index 82c8e32..1b3a604 100644
--- a/mobile/package.json
+++ b/mobile/package.json
@@ -1,6 +1,6 @@
{
"name": "shivao-mobile",
- "version": "1.10.6",
+ "version": "1.10.7",
"description": "Shivao app nativo (Capacitor wrapper Android/iOS)",
"main": "index.js",
"type": "module",
diff --git a/server/public/index.html b/server/public/index.html
index d65063b..43731dc 100644
--- a/server/public/index.html
+++ b/server/public/index.html
@@ -6057,7 +6057,18 @@ async function bmsProbeAndAttach(deviceId,deviceName){
setBleDiag('Não achei chars notify+write em services vendor','err');
return false;
}
- setBleDiag(`Notify=${notifyChar.slice(4,8)} Write=${writeChar.slice(4,8)} Svc=${foundService.slice(4,8)}`,'ok');
+ // Detecta se write char só aceita writeWithoutResponse
+ let writeOnlyWnr=false;
+ for(const svc of allSvcs){
+ if((svc.uuid||'').toLowerCase()!==foundService)continue;
+ for(const c of (svc.characteristics||[])){
+ if((c.uuid||'').toLowerCase()===writeChar){
+ const p=c.properties||{};
+ writeOnlyWnr=(!p.write&&p.writeWithoutResponse);
+ }
+ }
+ }
+ setBleDiag(`Notify=${notifyChar.slice(4,8)} Write=${writeChar.slice(4,8)}${writeOnlyWnr?' (force-wnr)':''} Svc=${foundService.slice(4,8)}`,'ok');
// Subscribe + handler
const listenerKey='notification|'+deviceId+'|'+foundService+'|'+notifyChar;
ble.addListener(listenerKey,(ev)=>{
@@ -6079,6 +6090,7 @@ async function bmsProbeAndAttach(deviceId,deviceName){
dev.bmsService=foundService;
dev.bmsNotifyChar=notifyChar;
dev.bmsWriteChar=writeChar;
+ dev.bmsForceWnr=writeOnlyWnr;
dev.isJBD=true;
saveState();
}
@@ -6094,7 +6106,9 @@ async function bmsWriteCmd(deviceId,bytes,withoutResponse){
const ble=window.Capacitor?.Plugins?.BluetoothLe;
const dev=state.btDevices?.find(d=>d.id===deviceId);
if(!ble||!dev?.bmsService||!dev?.bmsWriteChar)throw new Error('config BMS ausente');
- const fn=withoutResponse?'writeWithoutResponse':'write';
+ // Se a write char só aceita wnr, força writeWithoutResponse independente do parâmetro
+ const useWnr=withoutResponse||dev.bmsForceWnr;
+ const fn=useWnr?'writeWithoutResponse':'write';
await ble[fn]({deviceId,service:dev.bmsService,characteristic:dev.bmsWriteChar,value:bytesToBase64(bytes)});
}
@@ -6289,7 +6303,7 @@ async function removeBluetoothDevice(id){
renderBluetoothCard();
}
-const APP_VERSION='1.10.6';
+const APP_VERSION='1.10.7';
function renderBluetoothCard(){
const el=document.getElementById('bt-list');
const supportEl=document.getElementById('bt-support');
diff --git a/server/src/index.js b/server/src/index.js
index 7e2d730..ebd6fe0 100644
--- a/server/src/index.js
+++ b/server/src/index.js
@@ -347,7 +347,7 @@ app.get('/.well-known/assetlinks.json', (req, res) => {
});
// Atalho: /apk redireciona pra última APK release no Forgejo
-const LATEST_APK_URL = 'https://git.pontualtech.work/karlao/shivao-projeto/releases/download/v1.10.6/Shivao-v1.10.6.apk';
+const LATEST_APK_URL = 'https://git.pontualtech.work/karlao/shivao-projeto/releases/download/v1.10.7/Shivao-v1.10.7.apk';
app.get('/apk', (req, res) => res.redirect(302, LATEST_APK_URL));
// Página A4 imprimível com QR Code + instruções (cola no barco/marina)