Compare commits
No commits in common. "461bfc748bc223ccdbafe5735dde6b56f7c2ed62" and "fda1f144fccda2207916658a88a873d4815fcba3" have entirely different histories.
461bfc748b
...
fda1f144fc
|
|
@ -291,16 +291,7 @@ export function createBleCore(options = {}) {
|
||||||
|
|
||||||
const runConnect = async () => {
|
const runConnect = async () => {
|
||||||
setStage(BLE_STAGE.CONNECTING);
|
setStage(BLE_STAGE.CONNECTING);
|
||||||
try {
|
await promisifyApi(platform, 'createBLEConnection', { deviceId, timeout });
|
||||||
await promisifyApi(platform, 'createBLEConnection', { deviceId, timeout });
|
|
||||||
} catch (error) {
|
|
||||||
// Android 报 already connect / iOS 报 already connected:
|
|
||||||
// 目标连接已存在(如配网页返回后再次发起),按幂等成功处理
|
|
||||||
const msg = String(error?.errMsg || '');
|
|
||||||
if (!/already\s*connect/i.test(msg)) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
patchState({ connected: true, deviceId });
|
patchState({ connected: true, deviceId });
|
||||||
setStage(BLE_STAGE.CONNECTED);
|
setStage(BLE_STAGE.CONNECTED);
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -106,9 +106,9 @@ export function createBluetoothDiscovery(options = {}) {
|
||||||
return left.hasTargetService ? -1 : 1
|
return left.hasTargetService ? -1 : 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// 同组内保持首次发现顺序(对象键插入序稳定)。
|
const leftSignal = typeof left.RSSI === 'number' ? left.RSSI : -999
|
||||||
// 不按 RSSI 排序:信号强度逐包抖动会让卡片反复换位跳动
|
const rightSignal = typeof right.RSSI === 'number' ? right.RSSI : -999
|
||||||
return 0
|
return rightSignal - leftSignal
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -248,13 +248,13 @@ export function createBluetoothDiscovery(options = {}) {
|
||||||
function getDeviceStableSignature(device = {}) {
|
function getDeviceStableSignature(device = {}) {
|
||||||
return [
|
return [
|
||||||
device.deviceId || '',
|
device.deviceId || '',
|
||||||
|
device.RSSI ?? '',
|
||||||
device.name || '',
|
device.name || '',
|
||||||
device.localName || '',
|
device.localName || '',
|
||||||
Array.isArray(device.advertisServiceUUIDs)
|
Array.isArray(device.advertisServiceUUIDs)
|
||||||
? device.advertisServiceUUIDs.map((item) => normalizeUuid(item)).sort().join('|')
|
? device.advertisServiceUUIDs.map((item) => normalizeUuid(item)).sort().join('|')
|
||||||
: '',
|
: '',
|
||||||
device.advertisData ? JSON.stringify(Array.from(new Uint8Array(device.advertisData))) : ''
|
device.advertisData ? JSON.stringify(Array.from(new Uint8Array(device.advertisData))) : ''
|
||||||
// RSSI 逐包抖动,不参与变更签名:避免同一设备反复触发列表刷新
|
|
||||||
].join('#')
|
].join('#')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,59 +0,0 @@
|
||||||
import { describe, it, expect, vi } from 'vitest'
|
|
||||||
// 纯 JS 资产未类型化,关闭该文件类型检查
|
|
||||||
// @ts-ignore
|
|
||||||
import { createBleCore } from '@/ble/core/bleCore'
|
|
||||||
|
|
||||||
// bleCore → adapter → @tarojs/taro 在 node 环境会触发 dom-external 的
|
|
||||||
// ENABLE_INNER_HTML 编译期常量未定义;测试直接 mock 掉该模块
|
|
||||||
vi.mock('@tarojs/taro', () => ({}))
|
|
||||||
vi.mock('@/ble/adapter', () => ({ taroPlatform: {} }))
|
|
||||||
|
|
||||||
// platform mock:按用例切换 createBLEConnection 的 fail/success 行为
|
|
||||||
// @ts-ignore 无类型平台对象,与 bleCore 注入签名一致
|
|
||||||
function makePlatform({ connectFail }: { connectFail?: { errMsg?: string; errCode?: number } }) {
|
|
||||||
return {
|
|
||||||
openBluetoothAdapter: (opt: { success?: (r: unknown) => void }) => opt.success?.({}),
|
|
||||||
closeBluetoothAdapter: (opt: { success?: (r: unknown) => void }) => opt.success?.({}),
|
|
||||||
onBluetoothAdapterStateChange: vi.fn(),
|
|
||||||
offBluetoothAdapterStateChange: vi.fn(),
|
|
||||||
onBLEConnectionStateChange: vi.fn(),
|
|
||||||
offBLEConnectionStateChange: vi.fn(),
|
|
||||||
onBLECharacteristicValueChange: vi.fn(),
|
|
||||||
offBLECharacteristicValueChange: vi.fn(),
|
|
||||||
onBluetoothDeviceFound: vi.fn(),
|
|
||||||
offBluetoothDeviceFound: vi.fn(),
|
|
||||||
createBLEConnection: vi.fn((opt: { success?: (r: unknown) => void; fail?: (e: unknown) => void }) => {
|
|
||||||
if (connectFail) opt.fail?.(connectFail)
|
|
||||||
else opt.success?.({})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('bleCore.connect already connect 幂等', () => {
|
|
||||||
it('Android already connect 形态:按已连接成功处理,状态进入 CONNECTED', async () => {
|
|
||||||
const platform = makePlatform({ connectFail: { errCode: 10003, errMsg: 'createBLEConnection:fail:already connect' } })
|
|
||||||
const core = createBleCore({ platform, reconnect: { enabled: false } })
|
|
||||||
|
|
||||||
const ok = await core.connect('dev-1')
|
|
||||||
expect(ok).toBe(true)
|
|
||||||
expect(core.getState().connected).toBe(true)
|
|
||||||
expect(core.getState().deviceId).toBe('dev-1')
|
|
||||||
expect(core.getState().stage).toBe('CONNECTED')
|
|
||||||
})
|
|
||||||
|
|
||||||
it('iOS already connected 形态:同样幂等成功', async () => {
|
|
||||||
const platform = makePlatform({ connectFail: { errMsg: 'createBLEConnection:fail:already connected' } })
|
|
||||||
const core = createBleCore({ platform, reconnect: { enabled: false } })
|
|
||||||
|
|
||||||
await core.connect('dev-2')
|
|
||||||
expect(core.getState().connected).toBe(true)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('其他连接错误不吞:原样抛出且 connected 保持 false', async () => {
|
|
||||||
const platform = makePlatform({ connectFail: { errCode: 10012, errMsg: 'createBLEConnection:fail:timeout' } })
|
|
||||||
const core = createBleCore({ platform, reconnect: { enabled: false } })
|
|
||||||
|
|
||||||
await expect(core.connect('dev-3')).rejects.toThrow()
|
|
||||||
expect(core.getState().connected).toBe(false)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
Loading…
Reference in New Issue