[AI Generated]: feat(*): 修复连接设备页及配网页交互逻辑、蓝牙状态显示与设备名获取

This commit is contained in:
17792275749
2026-05-14 17:18:10 +08:00
parent 29680cb7a4
commit 00a1529256
14 changed files with 402 additions and 155 deletions
+127 -41
View File
@@ -68,6 +68,8 @@ const DEVICE_SETTINGS: DeviceSetting[] = [
},
]
const TAG = '[LeFuService]'
class LeFuService {
private _plugin: LeFuPlugin | null = null
/** 设备协议对象,devicesModel 事件返回,用于 WiFi 配网等高级操作 */
@@ -84,16 +86,23 @@ class LeFuService {
/** 连接后从 deviceInfo 事件获取的固件信息 */
private _deviceInfo: DeviceInfo | null = null
/** bus 事件是否已订阅(防止多次 startScan 重复 subscribe 累积) */
private _busSubscribed = false
/** 回调注册(页面通过 on* 方法注册,stopScan 时清空) */
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
/** 在 app.ts onLaunch 中调用,加载 ppScale-plugin */
init(): void {
console.log(TAG, 'init() 开始加载插件')
this._plugin = requirePlugin('ppScale-plugin') as LeFuPlugin
console.log(TAG, 'init() 插件加载完成:', !!this._plugin)
}
/** 获取插件(未初始化时抛出) */
@@ -111,14 +120,45 @@ class LeFuService {
/** 注册设备列表回调(扫描到设备时触发) */
onDevicesList(cb: (devices: ScannedDevice[]) => void): void {
console.log(TAG, 'onDevicesList 回调已注册')
this._onDevicesListCb = cb
}
/** 注册蓝牙连接状态回调 */
onConnectState(cb: (state: string) => void): void {
console.log(TAG, 'onConnectState 回调已注册')
this._onConnectStateCb = cb
}
/** 注册设备连接就绪回调(activeProtocol 可用时触发) */
onDeviceConnect(cb: () => void): void {
console.log(TAG, 'onDeviceConnect 回调已注册')
this._onDeviceConnectCb = cb
}
/** 当前蓝牙连接状态(connectState bus 事件实时更新) */
private _connectState = ''
/** 设备是否已连接(activeProtocol 就绪) */
get isConnected(): boolean {
return !!this._activeProtocol
}
/** 当前蓝牙连接状态字符串 */
get connectState(): string {
return this._connectState
}
/** 插件 BLUE_STATE 常量对象(供页面 wxml 条件判断用) */
get BLUE_STATE(): Record<string, string> {
return this._plugin?.BLUE_STATE ?? {}
}
/** 连接后从 deviceInfo 事件获取的设备信息(含 modelNumber / serialNumber 等) */
get deviceInfo(): DeviceInfo | null {
return this._deviceInfo
}
/** 注册实时测量回调(测量过程中多次触发) */
onMeasuring(cb: (data: ProgressData) => void): void {
this._onProgressCb = cb
@@ -134,57 +174,84 @@ class LeFuService {
this._onDisconnectedCb = cb
}
/** 注册 deviceInfo 就绪回调(设备名/固件信息可用时触发) */
onDeviceInfo(cb: (info: DeviceInfo) => void): void {
this._onDeviceInfoCb = cb
}
// ─── 扫描与连接 ───────────────────────────────
/**
* 开始蓝牙扫描
* 先注册所有 bus 事件再调用 plugin.Blue.start()
* 页面 onShow 时调用
* 对齐 master:先 setDeviceSetting → start,再 subscribemaster searchDevice.js 顺序)
*/
startScan(): void {
console.log(TAG, 'startScan() 开始,busSubscribed:', this._busSubscribed)
const plugin = this._p
// 扫描到设备列表
plugin.bus.subscribe('devicesList', (devList: RawDevice[]) => {
// 广播秤(BleAdv)自动调用 setbroadcastDev,无需用户手动点击连接
const advDev = devList.find((item: RawDevice) => {
const model = plugin.Blue.getDeviceModel(item)
return model?.deviceConnectType === plugin.PPBluetoothDefine.PPDeviceConnectType.PPDeviceConnectTypeBleAdv
})
if (advDev) {
plugin.Blue.setbroadcastDev(advDev)
}
// ① 先设置设备配置并启动扫描(必须在 subscribe 之前,与 master 一致)
plugin.Blue.setDeviceSetting(DEVICE_SETTINGS)
const deviceNames = DEVICE_SETTINGS.map(s => s.deviceName)
console.log(TAG, 'plugin.Blue.start() 调用,设备名称:', deviceNames)
plugin.Blue.start(deviceNames, false)
// 转换为展示层数据
// bus 订阅只注册一次,stopScan 时重置,避免多次搜索导致订阅累积
if (this._busSubscribed) {
console.log(TAG, 'bus 已订阅,跳过重复注册')
return
}
this._busSubscribed = true
// ② 启动后再订阅设备列表(master 也是 start 后才 subscribe
plugin.bus.subscribe('devicesList', (devList: RawDevice[]) => {
console.log(TAG, 'bus[devicesList] 触发,原始设备数:', devList?.length, devList?.map((d: RawDevice) => d.name || d.deviceName))
if (!devList || !devList.length) {
this._onDevicesListCb?.([])
return
}
// 直接用原始列表转换,不调用 getDeviceModelmaster 也是直接传 res
const devices: ScannedDevice[] = devList.map((item: RawDevice) => ({
name: item.name || item.deviceName || '未知设备',
raw: item,
model: plugin.Blue.getDeviceModel(item) || {},
model: {},
}))
console.log(TAG, '转换后设备列表:', devices.map(d => d.name))
this._onDevicesListCb?.(devices)
})
// 协议对象(持有 activeProtocolWiFi 配网等高级操作依赖它
// 设备模型信息(含 mac 等,仅用于日志/调试
plugin.bus.subscribe('devicesModel', (res: any) => {
this._activeProtocol = res
console.log(TAG, 'bus[devicesModel] 触发,deviceMac:', res?.deviceMac)
})
// 连接成功后获取固件信息(用于后续 OTA 版本比对)
plugin.bus.subscribe('deviceInfo', (res: DeviceInfo) => {
console.log(TAG, 'bus[deviceInfo] 触发:',res, res?.firmwareRevision, res?.modelNumber)
this._deviceInfo = res
this._onDeviceInfoCb?.(res)
})
// 连接成功
// 连接建立:从 ScaleAction 获取 activeProtocol,启动数据进度(对齐 master configureDevice.js
plugin.bus.subscribe('deviceConnect', () => {
console.log(TAG, 'bus[deviceConnect] 触发,获取 activeProtocol,启动数据进度')
this._reconnectCount = 0
plugin.ScaleAction.startDataProgress()
this._startKeepAlive()
plugin.ScaleAction.startDataProgress(true)
this._activeProtocol = plugin.ScaleAction.getActiveProtocol()
this._connectState = plugin.BLUE_STATE.CONNECTSUCCESS
this._onDeviceConnectCb?.()
})
// 连接状态变化
// 连接状态变化CONNECTSUCCESS 时启动保活,CONNECTFAILED 时重连
plugin.bus.subscribe('connectState', (res: string) => {
console.log(TAG, 'bus[connectState] 触发:', res)
this._connectState = res
this._onConnectStateCb?.(res)
if (res === plugin.BLUE_STATE.CONNECTSUCCESS) {
console.log(TAG, '连接成功,启动保活心跳')
this._startKeepAlive()
}
if (res === plugin.BLUE_STATE.CONNECTFAILED) {
console.warn(TAG, '连接失败,触发重连逻辑')
this._stopKeepAlive()
this._doReconnect()
}
@@ -192,58 +259,51 @@ class LeFuService {
// 实时测量数据
plugin.bus.subscribe('progressData', (res: ProgressData) => {
console.log(TAG, 'bus[progressData] 体重(g):', res?.weight)
this._onProgressCb?.(res)
})
// 测量锁定(完成)
plugin.bus.subscribe('lockData', (res: LockData) => {
console.log(TAG, 'bus[lockData] 测量完成,体重(g):', res?.weight, '阻抗:', res?.resistance)
this._onLockedCb?.(res)
})
// 设备自动断开
plugin.bus.subscribe('deviceWillDisconnect', () => {
console.warn(TAG, 'bus[deviceWillDisconnect] 设备断开,触发重连')
this._stopKeepAlive()
this._onDisconnectedCb?.()
this._doReconnect()
})
// 开始扫描,传入设备配置过滤列表
plugin.Blue.start(DEVICE_SETTINGS)
}
/**
* 主动连接指定设备
* BleAdv 类型已在 devicesList 中自动处理,无需调用此方法
* BleConnect 类型需要用户点击后调用
* 主动连接指定设备(对齐 master:直接调 createBLEConnection,不判断 deviceConnectType
*/
connect(device: ScannedDevice): void {
const connectType = this._p.PPBluetoothDefine.PPDeviceConnectType
if (device.model?.deviceConnectType === connectType.PPDeviceConnectTypeBleConnect) {
this._p.Blue.createBLEConnection(device.raw)
}
console.log(TAG, 'connect() 设备:', device.name)
this._p.Blue.createBLEConnection(device.raw)
}
/** 主动断开当前连接 */
disconnect(): void {
console.log(TAG, 'disconnect() 主动断开')
this._stopKeepAlive()
this._p.Blue.disconnect()
}
/**
* 停止扫描,清理所有 bus 订阅与回调
* 页面 onUnload / onHide 时调用
* 停止扫描(仅停止设备发现,不清连接态)
* connectedDevice onHide / onUnload 时调用
*/
stopScan(): void {
this._stopKeepAlive()
console.log(TAG, 'stopScan() 停止扫描')
this._stopReconnectTimer()
this._p.Blue.stop()
this._activeProtocol = null
this._deviceInfo = null
this._busSubscribed = false
wx.stopBluetoothDevicesDiscovery()
this._onDevicesListCb = null
this._onConnectStateCb = null
this._onProgressCb = null
this._onLockedCb = null
this._onDisconnectedCb = null
this._onDeviceConnectCb = null
}
// ─── WiFi 配网 ────────────────────────────────
@@ -253,6 +313,7 @@ class LeFuService {
* 内部延迟 2 秒后调用,15 秒超时
*/
getWifiList(): Promise<LeFuWifiItem[]> {
console.log(TAG, 'getWifiList() 开始')
return new Promise((resolve, reject) => {
if (!this._activeProtocol) {
reject(new Error('[LeFu] 设备未连接,无法获取 WiFi 列表'))
@@ -267,6 +328,7 @@ class LeFuService {
setTimeout(() => {
this._activeProtocol.dataFindSurroundDevice((res: any[]) => {
clearTimeout(timer)
console.log(TAG, 'getWifiList 原始结果:', res)
if (!res || res.length === 0) {
this._activeProtocol.dataExitWifiConfig(() => {})
resolve([])
@@ -276,6 +338,7 @@ class LeFuService {
ssid: item.ssid || item.name || '',
signal: item.signal,
}))
console.log(TAG, 'getWifiList 解析结果:', list.map(w => w.ssid))
resolve(list)
})
}, 2000)
@@ -290,6 +353,7 @@ class LeFuService {
* 返回码 23 = 配网成功
*/
configWifi(ssid: string, password: string, version: WifiVersion): Promise<void> {
console.log(TAG, 'configWifi() ssid:', ssid, 'version:', version)
return new Promise((resolve, reject) => {
if (!this._activeProtocol) {
reject(new Error('[LeFu] 设备未连接,无法配网'))
@@ -297,9 +361,12 @@ class LeFuService {
}
const callback = (res: number) => {
console.log(TAG, 'configWifi 回调 res:', res)
if (res === 23) {
console.log(TAG, 'configWifi 成功')
resolve()
} else {
console.error(TAG, 'configWifi 失败,错误码:', res)
reject(new Error(`[LeFu] 配网失败,错误码:${res}`))
}
}
@@ -329,12 +396,14 @@ class LeFuService {
* 返回 true = 已配网(0x01),false = 未配网
*/
checkWifiConfig(): Promise<boolean> {
console.log(TAG, 'checkWifiConfig() 查询配网状态')
return new Promise((resolve, reject) => {
if (!this._activeProtocol) {
reject(new Error('[LeFu] 设备未连接'))
return
}
this._activeProtocol.codeFetchWifiConfig((res: number | undefined | null) => {
console.log(TAG, 'checkWifiConfig 回调 res:', res, '已配网:', res === 0x01)
resolve(res === 0x01)
})
})
@@ -348,6 +417,7 @@ class LeFuService {
* 调用时机由业务层决定,不自动触发
*/
checkAndUpgrade(): Promise<boolean> {
console.log(TAG, 'checkAndUpgrade() 开始检查固件版本')
return new Promise((resolve, reject) => {
if (!this._activeProtocol) {
reject(new Error('[LeFu] 设备未连接'))
@@ -359,6 +429,7 @@ class LeFuService {
}
const { firmwareRevision, modelNumber } = this._deviceInfo
console.log(TAG, '当前固件:', firmwareRevision, '型号:', modelNumber)
const [mcuVer, bleVer, wifiVer, resVer] = (firmwareRevision || '').split('.')
// 设备单段版本(如 "006"vs 服务端 x.y.z 格式(如 "0.0.6")比对
@@ -371,12 +442,14 @@ class LeFuService {
get<FirmwareVersion>('weighingScale/v2/firmware/version', { type: modelNumber }, { loading: false })
.then(res => {
const { mcuVersion, bleVersion, wifiVersion, resVersion } = res.result
console.log(TAG, '服务端固件版本:', { mcuVersion, bleVersion, wifiVersion, resVersion })
const needUpdate =
isServerNewer(mcuVer, mcuVersion) ||
isServerNewer(bleVer, bleVersion) ||
isServerNewer(wifiVer, wifiVersion) ||
isServerNewer(resVer, resVersion)
console.log(TAG, '需要 OTA 升级:', needUpdate)
if (!needUpdate) {
resolve(false)
return
@@ -384,6 +457,7 @@ class LeFuService {
// status: false = 成功,true = 失败
this._activeProtocol.codeOtaUpdate((status: boolean) => {
console.log(TAG, 'OTA 升级回调 status:', status)
if (!status) {
resolve(true)
} else {
@@ -399,6 +473,7 @@ class LeFuService {
private _startKeepAlive(): void {
this._stopKeepAlive()
console.log(TAG, '_startKeepAlive 保活心跳启动')
this._keepAliveTimer = setInterval(() => {
this._activeProtocol?.sendKeepAliveCode?.()
}, 15000)
@@ -408,6 +483,7 @@ class LeFuService {
if (this._keepAliveTimer !== null) {
clearInterval(this._keepAliveTimer)
this._keepAliveTimer = null
console.log(TAG, '_stopKeepAlive 保活心跳停止')
}
}
@@ -421,11 +497,16 @@ class LeFuService {
/** 自动重连,最多 _maxReconnect 次,超限后等待用户手动重试 */
private _doReconnect(): void {
if (this._reconnectCount >= this._maxReconnect) return
if (this._reconnectCount >= this._maxReconnect) {
console.warn(TAG, '重连次数已达上限:', this._maxReconnect)
return
}
this._reconnectCount++
console.log(TAG, `_doReconnect 第 ${this._reconnectCount} 次重连`)
this._stopReconnectTimer()
this._reconnectTimer = setTimeout(() => {
this._plugin?.Blue?.disconnect((res: any) => {
console.log(TAG, '重连 disconnect 回调:', res?.errCode)
if (res?.errCode === 0) {
this._plugin?.Blue?.startBluetoothDevicesDiscovery()
}
@@ -442,6 +523,7 @@ class LeFuService {
* @param members 成员列表,必须包含且仅包含一个 isSelf=true 的主用户
*/
syncMembersToDevice(members: DeviceMember[]): Promise<void> {
console.log(TAG, 'syncMembersToDevice() 成员数:', members.length)
return new Promise((resolve, reject) => {
if (!this._activeProtocol) {
reject(new Error('[LeFu] 设备未连接,无法同步成员'))
@@ -461,6 +543,7 @@ class LeFuService {
this._activeProtocol.codeClearDeviceData('01', (clearRes: number) => {
clearTimeout(clearTimer)
console.log(TAG, 'codeClearDeviceData 回调:', clearRes)
if (clearRes !== 0x00) {
reject(new Error('[LeFu] 清除设备成员失败'))
return
@@ -480,11 +563,13 @@ class LeFuService {
const syncNext = () => {
if (index >= members.length) {
if (syncTimer !== null) clearTimeout(syncTimer)
console.log(TAG, 'syncMembersToDevice 全部同步完成')
resolve()
return
}
const member = members[index]
console.log(TAG, `下发第 ${index + 1}/${members.length} 个成员:`, member.name)
resetTimer()
this._activeProtocol.dataSyncUserInfo(
@@ -504,6 +589,7 @@ class LeFuService {
recentData: [],
},
(res: number) => {
console.log(TAG, `${index + 1} 个成员同步回调:`, res)
if (res === 0) {
index++
}