Files
2026-07-27 14:07:26 +08:00

2 lines
7.4 KiB
JavaScript

"use strict";const e=require("../common/vendor.js");let t="",o="",i="",r="",s=null;const c=t=>new Promise((i,r)=>{e.index.getBLEDeviceServices({deviceId:t,success:e=>{console.log("=== Available Services ==="),e.services.forEach((e,t)=>{console.log(`${t+1}. UUID: ${e.uuid}, Primary: ${e.isPrimary}`)});const s=["0000FFE0","0000ffe0","0000180a","00001800","0000ffe5","0000fff0","fff0","0000ffe3","ffe3","0000ffe1","ffe1"];let c=e.services.find(e=>s.some(t=>e.uuid.toLowerCase().startsWith(t.toLowerCase())));!c&&e.services.length>0&&(c=e.services.find(e=>e.isPrimary)||e.services.find(e=>4===e.uuid.length||8===e.uuid.length)||e.services[0],console.log("Using fallback service:",c.uuid)),c?(o=c.uuid,console.log("Selected service:",o),n(t,c.uuid).then(()=>i()).catch(r)):r(new Error("Service not found"))},fail:r})}),n=(t,o)=>new Promise((s,c)=>{e.index.getBLEDeviceCharacteristics({deviceId:t,serviceId:o,success:e=>{console.log("=== Available Characteristics ==="),e.characteristics.forEach((e,t)=>{console.log(`${t+1}. UUID: ${e.uuid}`),console.log(` - Properties: notify=${e.properties.notify}, read=${e.properties.read}, write=${e.properties.write}, writeWithoutResponse=${e.properties.writeWithoutResponse}`)});const n=["0000FFE1","0000ffe1","0000ffe2","0000ffe4","0000fff1","fff1","0000ffe3","ffe3","00002a00","00002a01","00002a04","00002a05"];let l=e.characteristics.find(e=>n.some(t=>e.uuid.toLowerCase().startsWith(t.toLowerCase()))&&(e.properties.notify||e.properties.read));const d=e.characteristics.find(e=>e.properties.write||e.properties.writeWithoutResponse);d&&(r=d.uuid,console.log("Found write characteristic:",r)),l||(l=e.characteristics.find(e=>e.properties.notify)),l||(l=e.characteristics.find(e=>e.properties.read)),!l&&e.characteristics.length>0&&(l=e.characteristics.find(e=>4===e.uuid.length||8===e.uuid.length)||e.characteristics[0],console.log("Using fallback characteristic:",l.uuid)),l?(i=l.uuid,console.log("Selected characteristic for read/notify:",i),console.log("Properties:",l.properties),a(t,o),l.properties.notify?g(t,o,l.uuid).then(()=>s()).catch(c):l.properties.read?h(t,o,l.uuid).then(()=>{u(t,o,l.uuid),s()}).catch(c):s()):c(new Error("Characteristic not found"))},fail:c})}),a=(e,t)=>{if(!r)return void console.log("No write characteristic found, skipping init commands");[d("START"),d("ON"),d("WEIGH"),d("GET"),d("1"),new Uint8Array([1]).buffer,new Uint8Array([2]).buffer,new Uint8Array([3]).buffer,new Uint8Array([85]).buffer,new Uint8Array([170,85]).buffer,new Uint8Array([254,1]).buffer,new Uint8Array([255,1]).buffer,new Uint8Array([0,0,0,1]).buffer].forEach((o,i)=>{setTimeout(()=>{l(e,t,r,o)},200*i)})},l=(t,o,i,r)=>{e.index.writeBLECharacteristicValue({deviceId:t,serviceId:o,characteristicId:i,value:r,success:()=>{console.log("Wrote command:",m(r))},fail:e=>{console.log("Write failed (may be normal for read-only chars):",e.errMsg)}})},d=e=>(new TextEncoder).encode(e).buffer;let f=null;const u=(t,o,i)=>{f&&clearInterval(f),f=setInterval(()=>{e.index.readBLECharacteristicValue({deviceId:t,serviceId:o,characteristicId:i,success:e=>{p(e.value)},fail:e=>{console.log("Periodic read failed:",e.errMsg)}})},300),console.log("Started periodic read every 300ms")},g=(t,o,i)=>new Promise((r,s)=>{e.index.notifyBLECharacteristicValueChange({deviceId:t,serviceId:o,characteristicId:i,state:!0,success:()=>{console.log("Notify enabled for:",i),r()},fail:e=>{console.log("Notify failed, trying read mode:",e.errMsg),h(t,o,i).then(()=>{u(t,o,i),r()}).catch(s)}})}),h=(t,o,i)=>new Promise((r,s)=>{e.index.readBLECharacteristicValue({deviceId:t,serviceId:o,characteristicId:i,success:e=>{console.log("Read characteristic value received"),p(e.value),r()},fail:e=>{console.error("Read failed:",e),s(e)}})}),p=e=>{console.log("=== BLE Data Received ==="),console.log("Data length:",e.byteLength,"bytes"),console.log("Hex:",m(e));const t=y(e);console.log("ASCII:",JSON.stringify(t));const o=v(e);console.log("Parsed weight:",o,"kg"),o>0&&o<1e3&&s&&(s(o),console.log("Weight sent to callback:",o))},v=e=>{if(0===e.byteLength)return console.log("Empty buffer received"),0;const t=new DataView(e),o=y(e).replace(/[\r\n\s\x00-\x1F]+/g,"");console.log("Cleaned ASCII:",JSON.stringify(o));const i=[/[+-]?\d+\.\d{1,3}\s*[kK][gG]?/,/[+-]?\d+\.\d{1,3}/,/[+-]?\d+\,\d{1,3}/,/[+-]?\d+\.?\d*/];for(const r of i){const e=o.match(r);if(e){const t=e[0].replace(",",".").replace(/[^0-9.-]/g,""),o=parseFloat(t);if(!isNaN(o)&&o>0&&o<1e3)return console.log("Parsed from text:",o),o}}if(e.byteLength>=2){const o=[];if(e.byteLength>=4&&(o.push(t.getInt32(0,!0)/1e3),o.push(t.getInt32(0,!1)/1e3),o.push(t.getFloat32(0,!0)),o.push(t.getFloat32(0,!1)),o.push(t.getUint32(0,!0)/1e3),o.push(t.getUint32(0,!1)/1e3)),e.byteLength>=2&&(o.push(t.getInt16(0,!0)/10),o.push(t.getInt16(0,!1)/10),o.push(t.getUint16(0,!0)/10),o.push(t.getUint16(0,!1)/10),o.push(t.getInt16(0,!0)/100),o.push(t.getInt16(0,!1)/100),o.push(t.getInt16(0,!0)/1e3),o.push(t.getInt16(0,!1)/1e3)),e.byteLength>=3){const e=t.getUint8(0),i=t.getUint8(1),r=t.getUint8(2);o.push((e<<16|i<<8|r)/1e3),o.push((r<<16|i<<8|e)/1e3),o.push((i<<16|e<<8|r)/1e3)}console.log("Testing binary values:",o.filter(e=>e>0&&e<1e3));for(const e of o)if(e>0&&e<1e3&&!isNaN(e))return console.log("Parsed from binary:",e),e}if(e.byteLength>=4){const t=new Uint8Array(e);let o="";for(let e=0;e<t.length;e++){const i=t[e]>>4&15,r=15&t[e];i>=0&&i<=9&&(o+=i.toString()),r>=0&&r<=9&&(o+=r.toString())}if(console.log("BCD value:",o),o.length>=1){let e=parseFloat(o)/1e3;if(e>0&&e<1e3)return console.log("Parsed from BCD:",e),e;const t=o.length-3;if(t>0){const i=o.slice(0,t)+"."+o.slice(t);if(e=parseFloat(i),e>0&&e<1e3)return console.log("Parsed from BCD with decimal:",e),e}}}return console.log("No valid weight found, returning 0"),0},y=e=>{try{const t=new Uint8Array(e);let o="";for(let e=0;e<t.length;e++)t[e]>=32&&t[e]<=126?o+=String.fromCharCode(t[e]):10!==t[e]&&13!==t[e]||(o+=10===t[e]?"\n":"\r");return o}catch{return""}},m=e=>{const t=new Uint8Array(e);return Array.from(t).map(e=>e.toString(16).padStart(2,"0")).join(" ")};exports.connectDevice=o=>new Promise((i,r)=>{t=o,e.index.createBLEConnection({deviceId:o,success:()=>{console.log("Connected to device:",o),c(o).then(()=>i()).catch(r)},fail:e=>{console.error("Connection failed:",e),r(e)}})}),exports.disconnectDevice=()=>new Promise((c,n)=>{f&&(clearInterval(f),f=null,console.log("Stopped periodic read")),t?e.index.closeBLEConnection({deviceId:t,success:()=>{console.log("Disconnected successfully"),t="",o="",i="",r="",s=null,c()},fail:e=>{console.log("Disconnect failed but clearing state:",e.errMsg),t="",o="",i="",r="",s=null,c()}}):c()}),exports.initBluetooth=()=>new Promise((t,o)=>{e.index.openBluetoothAdapter({success:()=>{console.log("Bluetooth adapter initialized"),t()},fail:e=>{console.error("Bluetooth init failed:",e),o(e)}})}),exports.listenWeightData=t=>{s=t,console.log("Weight callback registered"),e.index.onBLECharacteristicValueChange(e=>{console.log("BLE characteristic value changed event"),p(e.value)})},exports.startDiscovery=t=>new Promise(o=>{const i=[];e.index.startBluetoothDevicesDiscovery({services:[],success:()=>{console.log("Started discovery"),e.index.onBluetoothDeviceFound(e=>{e.devices.filter(e=>e.name&&(e.name.includes("Scale")||e.name.includes("秤")||e.name.includes("WXL"))).forEach(e=>{i.find(t=>t.deviceId===e.deviceId)||i.push({deviceId:e.deviceId,name:e.name,RSSI:e.RSSI||0})}),t([...i])}),setTimeout(()=>{e.index.stopBluetoothDevicesDiscovery(),o()},1e4)}})}),exports.stopDiscovery=()=>{e.index.stopBluetoothDevicesDiscovery()};