| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147 |
- import { type LocationSample } from './locationSource'
- export const DEFAULT_MOCK_LOCATION_BRIDGE_URL = 'wss://gs.gotomars.xyz/mock-gps'
- export interface MockLocationBridgeCallbacks {
- onOpen: () => void
- onClose: (message: string) => void
- onError: (message: string) => void
- onSample: (sample: LocationSample) => void
- }
- type RawMockGpsMessage = {
- type?: string
- timestamp?: number
- lat?: number
- lon?: number
- accuracyMeters?: number
- speedMps?: number
- headingDeg?: number
- }
- function safeParseMessage(data: string): RawMockGpsMessage | null {
- try {
- return JSON.parse(data) as RawMockGpsMessage
- } catch (_error) {
- return null
- }
- }
- function toLocationSample(message: RawMockGpsMessage): LocationSample | null {
- if (message.type !== 'mock_gps') {
- return null
- }
- if (!Number.isFinite(message.lat) || !Number.isFinite(message.lon)) {
- return null
- }
- return {
- latitude: Number(message.lat),
- longitude: Number(message.lon),
- accuracy: Number.isFinite(message.accuracyMeters) ? Number(message.accuracyMeters) : undefined,
- speed: Number.isFinite(message.speedMps) ? Number(message.speedMps) : null,
- headingDeg: Number.isFinite(message.headingDeg) ? Number(message.headingDeg) : null,
- timestamp: Number.isFinite(message.timestamp) ? Number(message.timestamp) : Date.now(),
- sourceMode: 'mock',
- }
- }
- export class MockLocationBridge {
- callbacks: MockLocationBridgeCallbacks
- socketTask: WechatMiniprogram.SocketTask | null
- connected: boolean
- connecting: boolean
- url: string
- constructor(callbacks: MockLocationBridgeCallbacks) {
- this.callbacks = callbacks
- this.socketTask = null
- this.connected = false
- this.connecting = false
- this.url = DEFAULT_MOCK_LOCATION_BRIDGE_URL
- }
- connect(url = DEFAULT_MOCK_LOCATION_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 sample = toLocationSample(parsed)
- if (!sample) {
- return
- }
- this.callbacks.onSample(sample)
- })
- } 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()
- }
- }
|