Add mock heart rate simulator flow
This commit is contained in:
134
miniprogram/engine/sensor/mockHeartRateBridge.ts
Normal file
134
miniprogram/engine/sensor/mockHeartRateBridge.ts
Normal file
@@ -0,0 +1,134 @@
|
||||
export const DEFAULT_MOCK_HEART_RATE_BRIDGE_URL = 'wss://gs.gotomars.xyz/mock-gps'
|
||||
|
||||
export interface MockHeartRateBridgeCallbacks {
|
||||
onOpen: () => void
|
||||
onClose: (message: string) => void
|
||||
onError: (message: string) => void
|
||||
onBpm: (bpm: number) => void
|
||||
}
|
||||
|
||||
type RawMockHeartRateMessage = {
|
||||
type?: string
|
||||
timestamp?: number
|
||||
bpm?: number
|
||||
}
|
||||
|
||||
function safeParseMessage(data: string): RawMockHeartRateMessage | null {
|
||||
try {
|
||||
return JSON.parse(data) as RawMockHeartRateMessage
|
||||
} catch (_error) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
function toHeartRateValue(message: RawMockHeartRateMessage): number | null {
|
||||
if (message.type !== 'mock_heart_rate' || !Number.isFinite(message.bpm)) {
|
||||
return null
|
||||
}
|
||||
|
||||
const bpm = Math.round(Number(message.bpm))
|
||||
if (bpm <= 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
return bpm
|
||||
}
|
||||
|
||||
export class MockHeartRateBridge {
|
||||
callbacks: MockHeartRateBridgeCallbacks
|
||||
socketTask: WechatMiniprogram.SocketTask | null
|
||||
connected: boolean
|
||||
connecting: boolean
|
||||
url: string
|
||||
|
||||
constructor(callbacks: MockHeartRateBridgeCallbacks) {
|
||||
this.callbacks = callbacks
|
||||
this.socketTask = null
|
||||
this.connected = false
|
||||
this.connecting = false
|
||||
this.url = DEFAULT_MOCK_HEART_RATE_BRIDGE_URL
|
||||
}
|
||||
|
||||
connect(url = DEFAULT_MOCK_HEART_RATE_BRIDGE_URL): void {
|
||||
if (this.connected || this.connecting) {
|
||||
return
|
||||
}
|
||||
|
||||
this.url = url
|
||||
this.connecting = true
|
||||
|
||||
try {
|
||||
const socketTask = wx.connectSocket({
|
||||
url,
|
||||
})
|
||||
this.socketTask = socketTask
|
||||
|
||||
socketTask.onOpen(() => {
|
||||
this.connected = true
|
||||
this.connecting = false
|
||||
this.callbacks.onOpen()
|
||||
})
|
||||
|
||||
socketTask.onClose((result) => {
|
||||
const reason = result && result.reason ? result.reason : '模拟心率源连接已关闭'
|
||||
this.connected = false
|
||||
this.connecting = false
|
||||
this.socketTask = null
|
||||
this.callbacks.onClose(reason)
|
||||
})
|
||||
|
||||
socketTask.onError((result) => {
|
||||
const message = result && result.errMsg ? result.errMsg : '模拟心率源连接失败'
|
||||
this.connected = false
|
||||
this.connecting = false
|
||||
this.socketTask = null
|
||||
this.callbacks.onError(message)
|
||||
})
|
||||
|
||||
socketTask.onMessage((result) => {
|
||||
if (!result || typeof result.data !== 'string') {
|
||||
return
|
||||
}
|
||||
|
||||
const parsed = safeParseMessage(result.data)
|
||||
if (!parsed) {
|
||||
this.callbacks.onError('模拟心率消息不是合法 JSON')
|
||||
return
|
||||
}
|
||||
|
||||
const bpm = toHeartRateValue(parsed)
|
||||
if (bpm === null) {
|
||||
return
|
||||
}
|
||||
|
||||
this.callbacks.onBpm(bpm)
|
||||
})
|
||||
} catch (error) {
|
||||
this.connected = false
|
||||
this.connecting = false
|
||||
this.socketTask = null
|
||||
const message = error && (error as Error).message ? (error as Error).message : '模拟心率源连接创建失败'
|
||||
this.callbacks.onError(message)
|
||||
}
|
||||
}
|
||||
|
||||
disconnect(): void {
|
||||
if (!this.socketTask) {
|
||||
if (this.connected || this.connecting) {
|
||||
this.connected = false
|
||||
this.connecting = false
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const socketTask = this.socketTask
|
||||
this.socketTask = null
|
||||
this.connected = false
|
||||
this.connecting = false
|
||||
socketTask.close({})
|
||||
}
|
||||
|
||||
destroy(): void {
|
||||
this.disconnect()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user