@@ -1,16 +1,16 @@
import { get } from '../utils/request/index'
import type {
RawDevice ,
LeFuPlugin ,
ScannedDevice ,
LeFuWifiItem ,
ProgressData ,
LockData ,
LeFuConfig ,
DeviceSetting ,
DeviceMember ,
DeviceInfo ,
FirmwareVersion ,
RawDevice ,
LeFuPlugin ,
ScannedDevice ,
LeFuWifiItem ,
ProgressData ,
LockData ,
LeFuConfig ,
DeviceSetting ,
DeviceMember ,
DeviceInfo ,
FirmwareVersion ,
} from './types'
/** 顶层加载插件(对齐 demo, requirePlugin 必须在文件顶层调用) */
@@ -18,441 +18,441 @@ const plugin = requirePlugin('ppScale-plugin') as LeFuPlugin
/** 乐福 SDK 配置 */
const LEFU_CONFIG : LeFuConfig = {
key : 'lefudc91611833e18d94' ,
secret : 'eQ50JYimMp0X7uhNLj6D3lTEk4TUUvEG7dvaqKM9t1U=' ,
// domain1: 'http://10.10.10.10:8889',
// domain2: 'http://10.10.10.10:8889/weight',
domain1 : 'http://device.shuziweidao.com:80/gateway' ,
domain2 : 'http://device.shuziweidao.com:80/weight' ,
key : 'lefudc91611833e18d94' ,
secret : 'eQ50JYimMp0X7uhNLj6D3lTEk4TUUvEG7dvaqKM9t1U=' ,
// domain1: 'http://10.10.10.10:8889',
// domain2: 'http://10.10.10.10:8889/weight',
domain1 : 'http://device.shuziweidao.com:80/gateway' ,
domain2 : 'http://device.shuziweidao.com:80/weight' ,
}
/** 支持的设备型号配置列表(5款) */
const DEVICE_SETTINGS : DeviceSetting [ ] = [
{
advLength : 999 , calorieStatus : 0 , createBy : null ,
deviceAccuracyType : 2 , deviceCalcuteType : 3 , deviceConnectType : 2 ,
deviceFuncType : 223 , deviceName : 'CF568_G' , devicePowerType : 3 ,
deviceProtocolType : 3 , deviceType : 1 , deviceUnitType : '0,1,11' ,
id : 65 , imgUrl : null , macAddressStart : 6 , remark : null ,
sign : 'FF' , status : 0 , uhStatus : 1 , updateBy : null ,
} ,
{
advLength : 999 , calorieStatus : 0 , createBy : null ,
deviceAccuracyType : 2 , deviceCalcuteType : 3 , deviceConnectType : 2 ,
deviceFuncType : 223 , deviceName : 'YX-B4-568-BW' , devicePowerType : 3 ,
deviceProtocolType : 3 , deviceType : 1 , deviceUnitType : '0,1,11' ,
id : 65 , imgUrl : null , macAddressStart : 6 , remark : null ,
sign : 'FF' , status : 0 , uhStatus : 1 , updateBy : null ,
} ,
{
advLength : 999 , calorieStatus : 0 , createBy : null ,
deviceAccuracyType : 2 , deviceCalcuteType : 4 , deviceConnectType : 2 ,
deviceFuncType : 65759 , deviceName : 'CF636_G' , devicePowerType : 3 ,
deviceProtocolType : 3 , deviceType : 1 , deviceUnitType : '0,1,2' ,
id : 216 , imgUrl : null , macAddressStart : 6 , remark : null ,
sign : 'FF' , status : 0 , uhStatus : 1 , updateBy : null ,
} ,
{
advLength : 999 , calorieStatus : 0 , createBy : null ,
deviceAccuracyType : 2 , deviceCalcuteType : 4 , deviceConnectType : 2 ,
deviceFuncType : 65759 , deviceName : 'YX-B8-636-BW' , devicePowerType : 3 ,
deviceProtocolType : 3 , deviceType : 1 , deviceUnitType : '0,1,2' ,
id : 216 , imgUrl : null , macAddressStart : 6 , remark : null ,
sign : 'FF' , status : 0 , uhStatus : 1 , updateBy : null ,
} ,
{
advLength : 999 , calorieStatus : 0 , createBy : null ,
deviceAccuracyType : 2 , deviceCalcuteType : 4 , deviceConnectType : 2 ,
deviceFuncType : 223 , deviceName : 'CF577' , devicePowerType : 3 ,
deviceProtocolType : 3 , deviceType : 1 , deviceUnitType : '0,1,11' ,
id : 51 , imgUrl : null , macAddressStart : 6 , remark : null ,
sign : 'FF' , status : 0 , uhStatus : 1 , updateBy : null ,
} ,
{
advLength : 999 , calorieStatus : 0 , createBy : null ,
deviceAccuracyType : 2 , deviceCalcuteType : 3 , deviceConnectType : 2 ,
deviceFuncType : 223 , deviceName : 'CF568_G' , devicePowerType : 3 ,
deviceProtocolType : 3 , deviceType : 1 , deviceUnitType : '0,1,11' ,
id : 65 , imgUrl : null , macAddressStart : 6 , remark : null ,
sign : 'FF' , status : 0 , uhStatus : 1 , updateBy : null ,
} ,
{
advLength : 999 , calorieStatus : 0 , createBy : null ,
deviceAccuracyType : 2 , deviceCalcuteType : 3 , deviceConnectType : 2 ,
deviceFuncType : 223 , deviceName : 'YX-B4-568-BW' , devicePowerType : 3 ,
deviceProtocolType : 3 , deviceType : 1 , deviceUnitType : '0,1,11' ,
id : 65 , imgUrl : null , macAddressStart : 6 , remark : null ,
sign : 'FF' , status : 0 , uhStatus : 1 , updateBy : null ,
} ,
{
advLength : 999 , calorieStatus : 0 , createBy : null ,
deviceAccuracyType : 2 , deviceCalcuteType : 4 , deviceConnectType : 2 ,
deviceFuncType : 65759 , deviceName : 'CF636_G' , devicePowerType : 3 ,
deviceProtocolType : 3 , deviceType : 1 , deviceUnitType : '0,1,2' ,
id : 216 , imgUrl : null , macAddressStart : 6 , remark : null ,
sign : 'FF' , status : 0 , uhStatus : 1 , updateBy : null ,
} ,
{
advLength : 999 , calorieStatus : 0 , createBy : null ,
deviceAccuracyType : 2 , deviceCalcuteType : 4 , deviceConnectType : 2 ,
deviceFuncType : 65759 , deviceName : 'YX-B8-636-BW' , devicePowerType : 3 ,
deviceProtocolType : 3 , deviceType : 1 , deviceUnitType : '0,1,2' ,
id : 216 , imgUrl : null , macAddressStart : 6 , remark : null ,
sign : 'FF' , status : 0 , uhStatus : 1 , updateBy : null ,
} ,
{
advLength : 999 , calorieStatus : 0 , createBy : null ,
deviceAccuracyType : 2 , deviceCalcuteType : 4 , deviceConnectType : 2 ,
deviceFuncType : 223 , deviceName : 'CF577' , devicePowerType : 3 ,
deviceProtocolType : 3 , deviceType : 1 , deviceUnitType : '0,1,11' ,
id : 51 , imgUrl : null , macAddressStart : 6 , remark : null ,
sign : 'FF' , status : 0 , uhStatus : 1 , updateBy : null ,
} ,
]
const TAG = '[LeFuService]'
class LeFuService {
private _activeProtocol : any = null
private _connectState = ''
private _deviceInfo : DeviceInfo | null = null
private _busSubscribed = false
private _intentionalConnect = false
private _activeProtocol : any = null
private _connectState = ''
private _deviceInfo : DeviceInfo | null = null
private _busSubscribed = false
private _intentionalConnect = false
private _reconnectCount = 0
private readonly _maxReconnect = 3
private _reconnectTimer : number | null = null
private _keepAliveTimer : number | null = null
private _lastRawDevice : RawDevice | null = null
private _reconnectCount = 0
private readonly _maxReconnect = 3
private _reconnectTimer : number | null = null
private _keepAliveTimer : number | null = null
private _lastRawDevice : RawDevice | null = null
private _onDevicesListCb : ( ( devices : ScannedDevice [ ] ) = > void ) | null = null
private _onConnectStateCb : ( ( state : string ) = > void ) | null = null
private _onDeviceConnectCb : ( ( ) = > void ) | null = null
private _onProgressCb : ( ( data : ProgressData ) = > void ) | null = null
private _onLockedCb : ( ( data : LockData ) = > void ) | null = null
private _onDisconnectedCb : ( ( ) = > void ) | null = null
private _onDeviceInfoCb : ( ( info : DeviceInfo ) = > void ) | null = null
private _onDevicesListCb : ( ( devices : ScannedDevice [ ] ) = > void ) | null = null
private _onConnectStateCb : ( ( state : string ) = > void ) | null = null
private _onDeviceConnectCb : ( ( ) = > void ) | null = null
private _onProgressCb : ( ( data : ProgressData ) = > void ) | null = null
private _onLockedCb : ( ( data : LockData ) = > void ) | null = null
private _onDisconnectedCb : ( ( ) = > void ) | null = null
private _onDeviceInfoCb : ( ( info : DeviceInfo ) = > void ) | null = null
get config ( ) : LeFuConfig { return LEFU_CONFIG }
get isConnected ( ) : boolean { return ! ! this . _activeProtocol }
get connectState ( ) : string { return this . _connectState }
get BLUE_STATE ( ) : Record < string , string > { return plugin . BLUE_STATE ? ? { } }
get deviceInfo ( ) : DeviceInfo | null { return this . _deviceInfo }
get config ( ) : LeFuConfig { return LEFU_CONFIG }
get isConnected ( ) : boolean { return ! ! this . _activeProtocol }
get connectState ( ) : string { return this . _connectState }
get BLUE_STATE ( ) : Record < string , string > { return plugin . BLUE_STATE ? ? { } }
get deviceInfo ( ) : DeviceInfo | null { return this . _deviceInfo }
// ─── 回调注册 ─────────────────────────────────
onDevicesList ( cb : ( devices : ScannedDevice [ ] ) = > void ) : void { this . _onDevicesListCb = cb }
onConnectState ( cb : ( state : string ) = > void ) : void { this . _onConnectStateCb = cb }
onDeviceConnect ( cb : ( ) = > void ) : void { this . _onDeviceConnectCb = cb }
onMeasuring ( cb : ( data : ProgressData ) = > void ) : void { this . _onProgressCb = cb }
onLocked ( cb : ( data : LockData ) = > void ) : void { this . _onLockedCb = cb }
onDisconnected ( cb : ( ) = > void ) : void { this . _onDisconnectedCb = cb }
onDeviceInfo ( cb : ( info : DeviceInfo ) = > void ) : void { this . _onDeviceInfoCb = cb }
// ─── 回调注册 ─────────────────────────────────
onDevicesList ( cb : ( devices : ScannedDevice [ ] ) = > void ) : void { this . _onDevicesListCb = cb }
onConnectState ( cb : ( state : string ) = > void ) : void { this . _onConnectStateCb = cb }
onDeviceConnect ( cb : ( ) = > void ) : void { this . _onDeviceConnectCb = cb }
onMeasuring ( cb : ( data : ProgressData ) = > void ) : void { this . _onProgressCb = cb }
onLocked ( cb : ( data : LockData ) = > void ) : void { this . _onLockedCb = cb }
onDisconnected ( cb : ( ) = > void ) : void { this . _onDisconnectedCb = cb }
onDeviceInfo ( cb : ( info : DeviceInfo ) = > void ) : void { this . _onDeviceInfoCb = cb }
// ─── 扫描与连接 ───────────────────────────────
startScan ( ) : void {
console . log ( TAG , 'startScan()' )
plugin . Blue . setDeviceSetting ( DEVICE_SETTINGS )
this . _subscribeBus ( )
plugin . Blue . start ( DEVICE_SETTINGS . map ( s = > s . deviceName ) , false )
}
// ─── 扫描与连接 ───────────────────────────────
startScan ( ) : void {
console . log ( TAG , 'startScan()' )
plugin . Blue . setDeviceSetting ( DEVICE_SETTINGS )
this . _subscribeBus ( )
plugin . Blue . start ( DEVICE_SETTINGS . map ( s = > s . deviceName ) , false )
}
private _subscribeBus ( ) : void {
if ( this . _busSubscribed ) {
console . log ( TAG , 'bus 已订阅,跳过' )
return
}
this . _busSubscribed = true
private _subscribeBus ( ) : void {
if ( this . _busSubscribed ) {
console . log ( TAG , 'bus 已订阅,跳过' )
return
}
this . _busSubscribed = true
plugin . bus . subscribe ( 'devicesList' , ( devList : RawDevice [ ] ) = > {
console . log ( TAG , 'bus[devicesList],设备数:' , devList ? . length , devList )
if ( ! devList ? . length ) {
this . _onDevicesListCb ? . ( [ ] )
return
}
const devices : ScannedDevice [ ] = devList . map ( ( item : RawDevice ) = > ( {
name : item.name || item . deviceName || '未知设备' ,
raw : item ,
model : { } ,
} ) )
this . _onDevicesListCb ? . ( devices )
} )
plugin . bus . subscribe ( 'devicesList' , ( devList : RawDevice [ ] ) = > {
console . log ( TAG , 'bus[devicesList],设备数:' , devList ? . length , devList )
if ( ! devList ? . length ) {
this . _onDevicesListCb ? . ( [ ] )
return
}
const devices : ScannedDevice [ ] = devList . map ( ( item : RawDevice ) = > ( {
name : item.name || item . deviceName || '未知设备' ,
raw : item ,
model : { } ,
} ) )
this . _onDevicesListCb ? . ( devices )
} )
plugin . bus . subscribe ( 'devicesModel' , ( res : any ) = > {
console . log ( TAG , 'bus[devicesModel] 完整数据:' , JSON . stringify ( res ) )
} )
plugin . bus . subscribe ( 'devicesModel' , ( res : any ) = > {
console . log ( TAG , 'bus[devicesModel] 完整数据:' , JSON . stringify ( res ) )
} )
plugin . bus . subscribe ( 'deviceInfo' , ( res : DeviceInfo ) = > {
console . log ( TAG , 'bus[deviceInfo]:' , res )
this . _deviceInfo = res
this . _onDeviceInfoCb ? . ( res )
} )
plugin . bus . subscribe ( 'deviceInfo' , ( res : DeviceInfo ) = > {
console . log ( TAG , 'bus[deviceInfo]:' , res )
this . _deviceInfo = res
this . _onDeviceInfoCb ? . ( res )
} )
plugin . bus . subscribe ( 'deviceConnect' , ( ) = > {
console . log ( TAG , 'bus[deviceConnect]' )
this . _intentionalConnect = false
this . _reconnectCount = 0
plugin . ScaleAction . startDataProgress ( true )
this . _activeProtocol = plugin . ScaleAction . getActiveProtocol ( )
this . _connectState = plugin . BLUE_STATE . CONNECTSUCCESS
this . _activeProtocol . codeUpdateMTU ( ( mtuRes : any ) = > {
console . log ( TAG , 'codeUpdateMTU:' , mtuRes )
this . _activeProtocol . codeSyncTime ( ( syncRes : any ) = > {
console . log ( TAG , 'codeSyncTime:' , syncRes )
this . _onDeviceConnectCb ? . ( )
} )
} )
} )
plugin . bus . subscribe ( 'deviceConnect' , ( ) = > {
console . log ( TAG , 'bus[deviceConnect]' )
this . _intentionalConnect = false
this . _reconnectCount = 0
plugin . ScaleAction . startDataProgress ( true )
this . _activeProtocol = plugin . ScaleAction . getActiveProtocol ( )
this . _connectState = plugin . BLUE_STATE . CONNECTSUCCESS
this . _activeProtocol . codeUpdateMTU ( ( mtuRes : any ) = > {
console . log ( TAG , 'codeUpdateMTU:' , mtuRes )
this . _activeProtocol . codeSyncTime ( ( syncRes : any ) = > {
console . log ( TAG , 'codeSyncTime:' , syncRes )
this . _onDeviceConnectCb ? . ( )
} )
} )
} )
plugin . bus . subscribe ( 'connectState' , ( res : string ) = > {
console . log ( TAG , 'bus[connectState]:' , res )
this . _connectState = res
this . _onConnectStateCb ? . ( res )
if ( res === plugin . BLUE_STATE . CONNECTSUCCESS ) {
this . _startKeepAlive ( )
}
if ( res === plugin . BLUE_STATE . CONNECTFAILED ) {
this . _stopKeepAlive ( )
if ( ! this . _intentionalConnect ) {
this . _doReconnect ( )
}
}
} )
plugin . bus . subscribe ( 'connectState' , ( res : string ) = > {
console . log ( TAG , 'bus[connectState]:' , res )
this . _connectState = res
this . _onConnectStateCb ? . ( res )
if ( res === plugin . BLUE_STATE . CONNECTSUCCESS ) {
this . _startKeepAlive ( )
}
if ( res === plugin . BLUE_STATE . CONNECTFAILED ) {
this . _stopKeepAlive ( )
if ( ! this . _intentionalConnect ) {
this . _doReconnect ( )
}
}
} )
plugin . bus . subscribe ( 'progressData' , ( res : ProgressData ) = > {
this . _onProgressCb ? . ( res )
} )
plugin . bus . subscribe ( 'progressData' , ( res : ProgressData ) = > {
this . _onProgressCb ? . ( res )
} )
plugin . bus . subscribe ( 'lockData' , ( res : LockData ) = > {
this . _onLockedCb ? . ( res )
} )
plugin . bus . subscribe ( 'lockData' , ( res : LockData ) = > {
this . _onLockedCb ? . ( res )
} )
plugin . bus . subscribe ( 'deviceWillDisconnect' , ( ) = > {
console . warn ( TAG , 'bus[deviceWillDisconnect], intentionalConnect:' , this . _intentionalConnect )
this . _activeProtocol = null
this . _stopKeepAlive ( )
this . _onDisconnectedCb ? . ( )
if ( ! this . _intentionalConnect ) {
this . _doReconnect ( )
}
} )
}
plugin . bus . subscribe ( 'deviceWillDisconnect' , ( ) = > {
console . warn ( TAG , 'bus[deviceWillDisconnect], intentionalConnect:' , this . _intentionalConnect )
this . _activeProtocol = null
this . _stopKeepAlive ( )
this . _onDisconnectedCb ? . ( )
if ( ! this . _intentionalConnect ) {
this . _doReconnect ( )
}
} )
}
connect ( rawDevice : RawDevice ) : void {
console . log ( TAG , 'connect():' , rawDevice . name )
this . _lastRawDevice = rawDevice
this . _intentionalConnect = true
this . _stopKeepAlive ( )
this . _stopReconnectTimer ( )
this . _activeProtocol = null
this . _connectState = ''
this . _deviceInfo = null
// 直连缓存设备时不走 startScan,需手动初始化插件设备配置和总线订阅
plugin . Blue . setDeviceSetting ( DEVICE_SETTINGS )
this . _subscribeBus ( )
plugin . Blue . stopBluetoothDevicesDiscovery ( )
// 0.0.25 新增:重新连接前必须清除协议缓存
plugin . Blue . clearProtocol ( )
plugin . Blue . createBLEConnection ( rawDevice )
}
connect ( rawDevice : RawDevice ) : void {
console . log ( TAG , 'connect():' , rawDevice . name )
this . _lastRawDevice = rawDevice
this . _intentionalConnect = true
this . _stopKeepAlive ( )
this . _stopReconnectTimer ( )
this . _activeProtocol = null
this . _connectState = ''
this . _deviceInfo = null
// 直连缓存设备时不走 startScan,需手动初始化插件设备配置和总线订阅
plugin . Blue . setDeviceSetting ( DEVICE_SETTINGS )
this . _subscribeBus ( )
plugin . Blue . stopBluetoothDevicesDiscovery ( )
// 0.0.25 新增:重新连接前必须清除协议缓存
plugin . Blue . clearProtocol ( )
plugin . Blue . createBLEConnection ( rawDevice )
}
disconnect ( ) : void {
console . log ( TAG , 'disconnect()' )
this . _stopKeepAlive ( )
plugin . Blue . disconnect ( )
}
disconnect ( ) : void {
console . log ( TAG , 'disconnect()' )
this . _stopKeepAlive ( )
plugin . Blue . disconnect ( )
}
/** 读缓存设备信息,自动扫描匹配后连接,已连接或无缓存时直接返回 */
autoConnect ( ) : void {
if ( this . isConnected ) return
const cached = wx . getStorageSync ( 'connectDeviceInfo' ) as RawDevice | null
const targetDeviceId = cached ? . deviceId as string | undefined
if ( ! targetDeviceId ) return
/** 读缓存设备信息,自动扫描匹配后连接,已连接或无缓存时直接返回 */
autoConnect ( ) : void {
if ( this . isConnected ) return
const cached = wx . getStorageSync ( 'connectDeviceInfo' ) as RawDevice | null
const targetDeviceId = cached ? . deviceId as string | undefined
if ( ! targetDeviceId ) return
let scanTimer : number | null = null
let scanTimer : number | null = null
wx . openBluetoothAdapter ( {
success : ( ) = > {
scanTimer = setTimeout ( ( ) = > {
this . stopScan ( )
} , 15000 )
wx . openBluetoothAdapter ( {
success : ( ) = > {
scanTimer = setTimeout ( ( ) = > {
this . stopScan ( )
} , 15000 )
this . onDevicesList ( ( devices ) = > {
const matched = devices . find ( d = > d . raw . deviceId === targetDeviceId )
if ( ! matched ) return
if ( scanTimer !== null ) { clearTimeout ( scanTimer ) ; scanTimer = null }
this . stopScan ( )
wx . setStorageSync ( 'connectDeviceInfo' , matched . raw )
this . connect ( matched . raw )
} )
this . startScan ( )
} ,
fail : ( ) = > {
if ( scanTimer !== null ) { clearTimeout ( scanTimer ) ; scanTimer = null }
} ,
} )
}
this . onDevicesList ( ( devices ) = > {
const matched = devices . find ( d = > d . raw . deviceId === targetDeviceId )
if ( ! matched ) return
if ( scanTimer !== null ) { clearTimeout ( scanTimer ) ; scanTimer = null }
this . stopScan ( )
wx . setStorageSync ( 'connectDeviceInfo' , matched . raw )
this . connect ( matched . raw )
} )
this . startScan ( )
} ,
fail : ( ) = > {
if ( scanTimer !== null ) { clearTimeout ( scanTimer ) ; scanTimer = null }
} ,
} )
}
stopScan ( ) : void {
console . log ( TAG , 'stopScan()' )
this . _stopReconnectTimer ( )
wx . stopBluetoothDevicesDiscovery ( )
this . _onDevicesListCb = null
}
stopScan ( ) : void {
console . log ( TAG , 'stopScan()' )
this . _stopReconnectTimer ( )
wx . stopBluetoothDevicesDiscovery ( )
this . _onDevicesListCb = null
}
// ─── WiFi 配网 ────────────────────────────────
getWifiList ( ) : Promise < LeFuWifiItem [ ] > {
console . log ( TAG , 'getWifiList()' )
return new Promise ( ( resolve , reject ) = > {
if ( ! this . _activeProtocol ) {
reject ( new Error ( '设备未连接,无法获取 WiFi 列表' ) )
return
}
const timer = setTimeout ( ( ) = > reject ( new Error ( '获取 WiFi 列表超时' ) ) , 15000 )
setTimeout ( ( ) = > {
this . _activeProtocol . dataFindSurroundDevice ( ( res : any [ ] ) = > {
clearTimeout ( timer )
console . log ( TAG , 'getWifiList 结果:' , res )
if ( ! res ? . length ) {
this . _activeProtocol . dataExitWifiConfig ( ( ) = > { } )
resolve ( [ ] )
return
}
resolve ( res . map ( ( item : any ) = > ( { ssid : item.ssid || item . name || '' , signal : item.signal } ) ) )
} )
} , 2000 )
} )
}
// ─── WiFi 配网 ────────────────────────────────
getWifiList ( ) : Promise < LeFuWifiItem [ ] > {
console . log ( TAG , 'getWifiList()' )
return new Promise ( ( resolve , reject ) = > {
if ( ! this . _activeProtocol ) {
reject ( new Error ( '设备未连接,无法获取 WiFi 列表' ) )
return
}
const timer = setTimeout ( ( ) = > reject ( new Error ( '获取 WiFi 列表超时' ) ) , 15000 )
setTimeout ( ( ) = > {
this . _activeProtocol . dataFindSurroundDevice ( ( res : any [ ] ) = > {
clearTimeout ( timer )
console . log ( TAG , 'getWifiList 结果:' , res )
if ( ! res ? . length ) {
this . _activeProtocol . dataExitWifiConfig ( ( ) = > { } )
resolve ( [ ] )
return
}
resolve ( res . map ( ( item : any ) = > ( { ssid : item.ssid || item . name || '' , signal : item.signal } ) ) )
} )
} , 2000 )
} )
}
configWifi ( ssid : string , password : string ) : Promise < void > {
const version = ( this . _deviceInfo ? . modelNumber ? ? '' ) . split ( '-' ) . length === 5 ? 'domain2' : 'domain1'
const startTs = Date . now ( )
console . log ( TAG , 'configWifi():' , ssid , version , 'ts=' , startTs , 'activeProtocol=' , ! ! this . _activeProtocol )
return new Promise ( ( resolve , reject ) = > {
if ( ! this . _activeProtocol ) {
console . warn ( TAG , 'configWifi 早期 reject: _activeProtocol 为空' )
reject ( new Error ( '设备未连接,无法配网' ) )
return
}
let settled = false
const timer = setTimeout ( ( ) = > {
console . warn ( TAG , 'configWifi 超时触发 elapsed=' , Date . now ( ) - startTs , 'settled=' , settled )
if ( settled ) return
settled = true
reject ( new Error ( '配网超时,请重试' ) )
} , 20000 )
console . log ( TAG , 'configWifi 已注册 20s 定时器 timerId=' , timer )
const callback = ( res : number , . . . extra : any [ ] ) = > {
console . log ( TAG , 'configWifi 回调 res=' , res , 'extra=' , extra , 'elapsed=' , Date . now ( ) - startTs , 'settled=' , settled )
if ( settled ) return
settled = true
clearTimeout ( timer )
res === 23 ? resolve ( ) : reject ( new Error ( ` 配网失败,错误码: ${ res } ` ) )
}
if ( version === 'domain1' ) {
console . log ( TAG , 'domain1 dataConfigNetWork' )
this . _activeProtocol . dataConfigNetWork ( { domain : LEFU_CONFIG.domain1 , ssid , password } , callback )
} else {
console . log ( TAG , 'domain2 dataConfigUserNetWork' )
this . _activeProtocol . dataConfigUserNetWork (
{ domain : LEFU_CONFIG.domain2 , ssid , password , userName : 'apiUser' , userPassword : '3acebb95eb49577e9c2a2082589b9bd6' } ,
callback ,
)
}
} )
}
configWifi ( ssid : string , password : string ) : Promise < void > {
const version = ( this . _deviceInfo ? . modelNumber ? ? '' ) . split ( '-' ) . length === 5 ? 'domain2' : 'domain1'
const startTs = Date . now ( )
console . log ( TAG , 'configWifi():' , ssid , version , 'ts=' , startTs , 'activeProtocol=' , ! ! this . _activeProtocol )
return new Promise ( ( resolve , reject ) = > {
if ( ! this . _activeProtocol ) {
console . warn ( TAG , 'configWifi 早期 reject: _activeProtocol 为空' )
reject ( new Error ( '设备未连接,无法配网' ) )
return
}
let settled = false
const timer = setTimeout ( ( ) = > {
console . warn ( TAG , 'configWifi 超时触发 elapsed=' , Date . now ( ) - startTs , 'settled=' , settled )
if ( settled ) return
settled = true
reject ( new Error ( '配网超时,请重试' ) )
} , 20000 )
console . log ( TAG , 'configWifi 已注册 20s 定时器 timerId=' , timer )
const callback = ( res : number , . . . extra : any [ ] ) = > {
console . log ( TAG , 'configWifi 回调 res=' , res , 'extra=' , extra , 'elapsed=' , Date . now ( ) - startTs , 'settled=' , settled )
if ( settled ) return
settled = true
clearTimeout ( timer )
res === 23 ? resolve ( ) : reject ( new Error ( ` 配网失败,错误码: ${ res } ` ) )
}
if ( version === 'domain1' ) {
console . log ( TAG , 'domain1 dataConfigNetWork' )
this . _activeProtocol . dataConfigNetWork ( { domain : LEFU_CONFIG.domain1 , ssid , password } , callback )
} else {
console . log ( TAG , 'domain2 dataConfigUserNetWork' )
this . _activeProtocol . dataConfigUserNetWork (
{ domain : LEFU_CONFIG.domain2 , ssid , password , userName : 'apiUser' , userPassword : '3acebb95eb49577e9c2a2082589b9bd6' } ,
callback ,
)
}
} )
}
checkWifiConfig ( ) : Promise < boolean > {
return new Promise ( ( resolve , reject ) = > {
if ( ! this . _activeProtocol ) { reject ( new Error ( '设备未连接' ) ) ; return }
this . _activeProtocol . codeFetchWifiConfig ( ( res : number | undefined | null ) = > {
resolve ( res === 0x01 )
} )
} )
}
checkWifiConfig ( ) : Promise < boolean > {
return new Promise ( ( resolve , reject ) = > {
if ( ! this . _activeProtocol ) { reject ( new Error ( '设备未连接' ) ) ; return }
this . _activeProtocol . codeFetchWifiConfig ( ( res : number | undefined | null ) = > {
resolve ( res === 0x01 )
} )
} )
}
// ─── OTA 升级 ─────────────────────────────────
checkAndUpgrade ( ) : Promise < boolean > {
return new Promise ( ( resolve , reject ) = > {
if ( ! this . _activeProtocol ) { reject ( new Error ( '设备未连接' ) ) ; return }
if ( ! this . _deviceInfo ) { reject ( new Error ( '固件信息未就绪' ) ) ; return }
// ─── OTA 升级 ─────────────────────────────────
checkAndUpgrade ( ) : Promise < boolean > {
return new Promise ( ( resolve , reject ) = > {
if ( ! this . _activeProtocol ) { reject ( new Error ( '设备未连接' ) ) ; return }
if ( ! this . _deviceInfo ) { reject ( new Error ( '固件信息未就绪' ) ) ; return }
const { firmwareRevision , modelNumber } = this . _deviceInfo
const [ mcuVer , bleVer , wifiVer , resVer ] = ( firmwareRevision || '' ) . split ( '.' )
const isServerNewer = ( dv : string , sv : string ) = > {
const dn = parseInt ( dv , 10 )
const sn = ( sv || '' ) . split ( '.' ) . map ( v = > parseInt ( v , 10 ) ) . reduce ( ( a , v ) = > a * 1000 + v , 0 )
return sn > dn
}
const { firmwareRevision , modelNumber } = this . _deviceInfo
const [ mcuVer , bleVer , wifiVer , resVer ] = ( firmwareRevision || '' ) . split ( '.' )
const isServerNewer = ( dv : string , sv : string ) = > {
const dn = parseInt ( dv , 10 )
const sn = ( sv || '' ) . split ( '.' ) . map ( v = > parseInt ( v , 10 ) ) . reduce ( ( a , v ) = > a * 1000 + v , 0 )
return sn > dn
}
get < FirmwareVersion > ( 'weighingScale/v2/firmware/version' , { type : modelNumber } , { loading : false } )
. then ( res = > {
const { mcuVersion , bleVersion , wifiVersion , resVersion } = res . result
const needUpdate = isServerNewer ( mcuVer , mcuVersion ) || isServerNewer ( bleVer , bleVersion )
|| isServerNewer ( wifiVer , wifiVersion ) || isServerNewer ( resVer , resVersion )
if ( ! needUpdate ) { resolve ( false ) ; return }
this . _activeProtocol . codeOtaUpdate ( ( status : number ) = > {
console . log ( ` codeOtaUpdatecodeOtaUpdatecodeOtaUpdate ${ status } ` )
status != 0 ? reject ( new Error ( 'OTA 升级失败' ) ) : resolve ( true )
} )
} )
. catch ( reject )
} )
}
get < FirmwareVersion > ( 'weighingScale/v2/firmware/version' , { type : modelNumber } , { loading : false } )
. then ( res = > {
const { mcuVersion , bleVersion , wifiVersion , resVersion } = res . result
const needUpdate = isServerNewer ( mcuVer , mcuVersion ) || isServerNewer ( bleVer , bleVersion )
|| isServerNewer ( wifiVer , wifiVersion ) || isServerNewer ( resVer , resVersion )
if ( ! needUpdate ) { resolve ( false ) ; return }
this . _activeProtocol . codeOtaUpdate ( ( status : number ) = > {
console . log ( ` codeOtaUpdatecodeOtaUpdatecodeOtaUpdate ${ status } ` )
status != 0 ? reject ( new Error ( 'OTA 升级失败' ) ) : resolve ( true )
} )
} )
. catch ( reject )
} )
}
// ─── 私有:保活与重连 ─────────────────────────
private _startKeepAlive ( ) : void {
this . _stopKeepAlive ( )
this . _keepAliveTimer = setInterval ( ( ) = > { this . _activeProtocol ? . sendKeepAliveCode ? . ( ) } , 15000 )
}
// ─── 私有:保活与重连 ─────────────────────────
private _startKeepAlive ( ) : void {
this . _stopKeepAlive ( )
this . _keepAliveTimer = setInterval ( ( ) = > { this . _activeProtocol ? . sendKeepAliveCode ? . ( ) } , 15000 )
}
private _stopKeepAlive ( ) : void {
if ( this . _keepAliveTimer !== null ) {
clearInterval ( this . _keepAliveTimer )
this . _keepAliveTimer = null
}
}
private _stopKeepAlive ( ) : void {
if ( this . _keepAliveTimer !== null ) {
clearInterval ( this . _keepAliveTimer )
this . _keepAliveTimer = null
}
}
private _stopReconnectTimer ( ) : void {
if ( this . _reconnectTimer !== null ) {
clearTimeout ( this . _reconnectTimer )
this . _reconnectTimer = null
}
this . _reconnectCount = 0
}
private _stopReconnectTimer ( ) : void {
if ( this . _reconnectTimer !== null ) {
clearTimeout ( this . _reconnectTimer )
this . _reconnectTimer = null
}
this . _reconnectCount = 0
}
private _doReconnect ( ) : void {
if ( this . _reconnectCount >= this . _maxReconnect ) {
console . warn ( TAG , '重连次数已达上限' )
this . _onDisconnectedCb ? . ( )
return
}
if ( ! this . _lastRawDevice ) {
console . warn ( TAG , '无缓存设备,放弃重连' )
return
}
this . _reconnectCount ++
console . log ( TAG , ` _doReconnect 第 ${ this . _reconnectCount } 次 ` )
this . _stopReconnectTimer ( )
this . _reconnectTimer = setTimeout ( ( ) = > {
plugin . Blue . clearProtocol ( )
plugin . Blue . createBLEConnection ( this . _lastRawDevice ! )
} , 2000 )
}
private _doReconnect ( ) : void {
if ( this . _reconnectCount >= this . _maxReconnect ) {
console . warn ( TAG , '重连次数已达上限' )
this . _onDisconnectedCb ? . ( )
return
}
if ( ! this . _lastRawDevice ) {
console . warn ( TAG , '无缓存设备,放弃重连' )
return
}
this . _reconnectCount ++
console . log ( TAG , ` _doReconnect 第 ${ this . _reconnectCount } 次 ` )
this . _stopReconnectTimer ( )
this . _reconnectTimer = setTimeout ( ( ) = > {
plugin . Blue . clearProtocol ( )
plugin . Blue . createBLEConnection ( this . _lastRawDevice ! )
} , 2000 )
}
// ─── 清除设备成员 (不下发) ─────────────────────
clearDeviceMembers ( ) : Promise < void > {
return new Promise ( ( resolve , reject ) = > {
if ( ! this . _activeProtocol ) { reject ( new Error ( '设备未连接' ) ) ; return }
const timer = setTimeout ( ( ) = > reject ( new Error ( '清除设备成员 超时' ) ) , 15000 )
this . _activeProtocol . codeClearDeviceData ( '01' , ( res : number ) = > {
clearTimeout ( timer )
res === 0 ? resolve ( ) : reject ( new Error ( '清除设备成员 失败' ) )
} )
} )
}
// ─── 清除设备用户 (不下发) ─────────────────────
clearDeviceMembers ( ) : Promise < void > {
return new Promise ( ( resolve , reject ) = > {
if ( ! this . _activeProtocol ) { reject ( new Error ( '设备未连接' ) ) ; return }
const timer = setTimeout ( ( ) = > reject ( new Error ( '清除设备用户 超时' ) ) , 15000 )
this . _activeProtocol . codeClearDeviceData ( '01' , ( res : number ) = > {
clearTimeout ( timer )
res === 0 ? resolve ( ) : reject ( new Error ( '清除设备用户 失败' ) )
} )
} )
}
// ─── 成员 同步 ─────────────────────────────────
syncMembersToDevice ( members : DeviceMember [ ] , onProgress ? : ( current : number , total : number ) = > void ) : Promise < void > {
return new Promise ( ( resolve , reject ) = > {
if ( ! this . _activeProtocol ) { reject ( new Error ( '设备未连接' ) ) ; return }
const mainUser = members . find ( m = > m . isSelf )
if ( ! mainUser ) { reject ( new Error ( '缺少主用户' ) ) ; return }
// ─── 用户 同步 ─────────────────────────────────
syncMembersToDevice ( members : DeviceMember [ ] , onProgress ? : ( current : number , total : number ) = > void ) : Promise < void > {
return new Promise ( ( resolve , reject ) = > {
if ( ! this . _activeProtocol ) { reject ( new Error ( '设备未连接' ) ) ; return }
const mainUser = members . find ( m = > m . isSelf )
if ( ! mainUser ) { reject ( new Error ( '缺少主用户' ) ) ; return }
const clearTimer = setTimeout ( ( ) = > reject ( new Error ( '清除设备成员 超时' ) ) , 15000 )
this . _activeProtocol . codeClearDeviceData ( '01' , ( clearRes : number ) = > {
clearTimeout ( clearTimer )
if ( clearRes != 0 ) { reject ( new Error ( '清除设备成员 失败' ) ) ; return }
const clearTimer = setTimeout ( ( ) = > reject ( new Error ( '清除设备用户 超时' ) ) , 15000 )
this . _activeProtocol . codeClearDeviceData ( '01' , ( clearRes : number ) = > {
clearTimeout ( clearTimer )
if ( clearRes != 0 ) { reject ( new Error ( '清除设备用户 失败' ) ) ; return }
let index = 0
let syncTimer : number | null = null
const resetTimer = ( ) = > {
if ( syncTimer !== null ) clearTimeout ( syncTimer )
syncTimer = setTimeout ( ( ) = > reject ( new Error ( ` 第 ${ index + 1 } 个成员 下发超时 ` ) ) , 15000 )
}
const syncNext = ( ) = > {
if ( index >= members . length ) {
if ( syncTimer !== null ) clearTimeout ( syncTimer )
resolve ( )
return
}
const member = members [ index ]
onProgress ? . ( index + 1 , members . length )
resetTimer ( )
this . _activeProtocol . dataSyncUserInfo (
{
userID : mainUser.id , userName : member.name ,
memberID : member.isSelf ? '' : member . id ,
age : member.age , gender : member.gender , height : member.height ,
isAthleteMode : 0 , deviceHeaderIndex : index ,
currentWeight : '' , targetWeight : '' , idealWeight : '' , recentData : [ ] ,
} ,
( res : number ) = > { if ( res === 0 ) index ++ ; syncNext ( ) } ,
)
}
syncNext ( )
} )
} )
}
let index = 0
let syncTimer : number | null = null
const resetTimer = ( ) = > {
if ( syncTimer !== null ) clearTimeout ( syncTimer )
syncTimer = setTimeout ( ( ) = > reject ( new Error ( ` 第 ${ index + 1 } 个用户 下发超时 ` ) ) , 15000 )
}
const syncNext = ( ) = > {
if ( index >= members . length ) {
if ( syncTimer !== null ) clearTimeout ( syncTimer )
resolve ( )
return
}
const member = members [ index ]
onProgress ? . ( index + 1 , members . length )
resetTimer ( )
this . _activeProtocol . dataSyncUserInfo (
{
userID : mainUser.id , userName : member.name ,
memberID : member.isSelf ? '' : member . id ,
age : member.age , gender : member.gender , height : member.height ,
isAthleteMode : 0 , deviceHeaderIndex : index ,
currentWeight : '' , targetWeight : '' , idealWeight : '' , recentData : [ ] ,
} ,
( res : number ) = > { if ( res === 0 ) index ++ ; syncNext ( ) } ,
)
}
syncNext ( )
} )
} )
}
}
export const lefuService = new LeFuService ( )