refactor: 统一术语「成员」→「用户」,代码格式化

- 页面文案、注释、Toast 提示统一改为"用户"
- lefu 模块缩进格式化(空格→Tab)
- selectMemberDrawer 组件注释统一

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
17792275749
2026-06-10 15:18:58 +08:00
co-authored by Claude Opus 4.7
parent 97c135786c
commit 485725a486
15 changed files with 443 additions and 445 deletions
+402 -402
View File
@@ -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'
/** 顶层加载插件(对齐 demorequirePlugin 必须在文件顶层调用) */
@@ -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()
+2 -2
View File
@@ -95,9 +95,9 @@ export interface FirmwareVersion {
resVersion: string
}
/** 下发给设备的成员信息(lefu 层使用,业务层转换后传入) */
/** 下发给设备的用户信息(lefu 层使用,业务层转换后传入) */
export interface DeviceMember {
/** 成员唯一 ID */
/** 用户唯一 ID */
id: string
/** 姓名 */
name: string