Add mock GPS simulator and configurable location sources

This commit is contained in:
2026-03-24 14:24:53 +08:00
parent 0295893b56
commit 2cf0bb76b4
16 changed files with 2575 additions and 122 deletions

View File

@@ -18,6 +18,7 @@ type MapPageData = MapEngineViewState & {
statusBarHeight: number
topInsetHeight: number
hudPanelIndex: number
mockBridgeUrlDraft: string
panelTimerText: string
panelMileageText: string
panelDistanceValueText: string
@@ -30,7 +31,7 @@ type MapPageData = MapEngineViewState & {
showRightButtonGroups: boolean
showBottomDebugButton: boolean
}
const INTERNAL_BUILD_VERSION = 'map-build-166'
const INTERNAL_BUILD_VERSION = 'map-build-172'
const REMOTE_GAME_CONFIG_URL = 'https://oss-mbh5.colormaprun.com/wxmini/test/game.json'
let mapEngine: MapEngine | null = null
function buildSideButtonVisibility(mode: SideButtonMode) {
@@ -105,6 +106,14 @@ Page({
panelProgressText: '0/0',
gameSessionStatus: 'idle',
gameModeText: '顺序赛',
locationSourceMode: 'real',
locationSourceText: '真实定位',
mockBridgeConnected: false,
mockBridgeStatusText: '未连接',
mockBridgeUrlText: 'wss://gs.gotomars.xyz/mock-gps',
mockBridgeUrlDraft: 'wss://gs.gotomars.xyz/mock-gps',
mockCoordText: '--',
mockSpeedText: '--',
panelSpeedValueText: '0',
panelTelemetryTone: 'blue',
panelHeartRateZoneNameText: '--',
@@ -151,7 +160,19 @@ Page({
mapEngine = new MapEngine(INTERNAL_BUILD_VERSION, {
onData: (patch) => {
this.setData(patch)
const nextPatch = patch as Partial<MapPageData>
if (
typeof nextPatch.mockBridgeUrlText === 'string'
&& this.data.mockBridgeUrlDraft === this.data.mockBridgeUrlText
) {
this.setData({
...nextPatch,
mockBridgeUrlDraft: nextPatch.mockBridgeUrlText,
})
return
}
this.setData(nextPatch)
},
})
@@ -170,6 +191,14 @@ Page({
panelProgressText: '0/0',
gameSessionStatus: 'idle',
gameModeText: '顺序赛',
locationSourceMode: 'real',
locationSourceText: '真实定位',
mockBridgeConnected: false,
mockBridgeStatusText: '未连接',
mockBridgeUrlText: 'wss://gs.gotomars.xyz/mock-gps',
mockBridgeUrlDraft: 'wss://gs.gotomars.xyz/mock-gps',
mockCoordText: '--',
mockSpeedText: '--',
panelSpeedValueText: '0',
panelTelemetryTone: 'blue',
panelHeartRateZoneNameText: '--',
@@ -382,6 +411,42 @@ Page({
}
},
handleSetRealLocationMode() {
if (mapEngine) {
mapEngine.handleSetRealLocationMode()
}
},
handleSetMockLocationMode() {
if (mapEngine) {
mapEngine.handleSetMockLocationMode()
}
},
handleConnectMockLocationBridge() {
if (mapEngine) {
mapEngine.handleConnectMockLocationBridge()
}
},
handleMockBridgeUrlInput(event: WechatMiniprogram.Input) {
this.setData({
mockBridgeUrlDraft: event.detail.value,
})
},
handleSaveMockBridgeUrl() {
if (mapEngine) {
mapEngine.handleSetMockLocationBridgeUrl(this.data.mockBridgeUrlDraft)
}
},
handleDisconnectMockLocationBridge() {
if (mapEngine) {
mapEngine.handleDisconnectMockLocationBridge()
}
},
handleConnectHeartRate() {
if (mapEngine) {
mapEngine.handleConnectHeartRate()

View File

@@ -285,10 +285,42 @@
<text class="info-panel__label">GPS</text>
<text class="info-panel__value">{{gpsTrackingText}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Location Source</text>
<text class="info-panel__value">{{locationSourceText}}</text>
</view>
<view class="info-panel__row info-panel__row--stack">
<text class="info-panel__label">GPS Coord</text>
<text class="info-panel__value">{{gpsCoordText}}</text>
</view>
<view class="info-panel__row info-panel__row--stack">
<text class="info-panel__label">Mock Bridge</text>
<text class="info-panel__value">{{mockBridgeStatusText}}</text>
</view>
<view class="info-panel__row info-panel__row--stack">
<text class="info-panel__label">Mock URL</text>
<view class="debug-inline-stack">
<input
class="debug-input"
value="{{mockBridgeUrlDraft}}"
placeholder="ws://192.168.x.x:17865/mock-gps"
bindinput="handleMockBridgeUrlInput"
/>
<view class="control-row control-row--compact">
<view class="control-chip control-chip--secondary" bindtap="handleSaveMockBridgeUrl">保存地址</view>
<view class="control-chip {{mockBridgeConnected ? 'control-chip--active' : 'control-chip--secondary'}}" bindtap="handleConnectMockLocationBridge">连接模拟源</view>
<view class="control-chip control-chip--secondary" bindtap="handleDisconnectMockLocationBridge">断开模拟源</view>
</view>
</view>
</view>
<view class="info-panel__row info-panel__row--stack">
<text class="info-panel__label">Mock Coord</text>
<text class="info-panel__value">{{mockCoordText}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Mock Speed</text>
<text class="info-panel__value">{{mockSpeedText}}</text>
</view>
<view class="info-panel__row">
<text class="info-panel__label">Heart Rate</text>
<text class="info-panel__value">{{heartRateStatusText}}</text>
@@ -313,6 +345,10 @@
<view class="control-chip {{gpsTracking ? 'control-chip--active' : 'control-chip--secondary'}}" bindtap="handleToggleGpsTracking">{{gpsTracking ? '停止定位' : '开启定位'}}</view>
<view class="control-chip {{heartRateConnected ? 'control-chip--active' : 'control-chip--secondary'}}" bindtap="handleConnectHeartRate">{{heartRateConnected ? '心率带已连接' : '连接心率带'}}</view>
</view>
<view class="control-row">
<view class="control-chip {{locationSourceMode === 'real' ? 'control-chip--active' : 'control-chip--secondary'}}" bindtap="handleSetRealLocationMode">真实定位</view>
<view class="control-chip {{locationSourceMode === 'mock' ? 'control-chip--active' : 'control-chip--secondary'}}" bindtap="handleSetMockLocationMode">模拟定位</view>
</view>
<view class="control-row">
<view class="control-chip control-chip--secondary" bindtap="handleDisconnectHeartRate">断开心率带</view>
<view class="control-chip control-chip--secondary" bindtap="handleCycleNorthReferenceMode">{{northReferenceButtonText}}</view>

View File

@@ -1175,12 +1175,45 @@
color: #45624b;
}
.debug-input {
flex: 1;
min-height: 72rpx;
padding: 0 22rpx;
border-radius: 18rpx;
background: rgba(255, 255, 255, 0.92);
box-shadow: inset 0 0 0 2rpx rgba(22, 48, 32, 0.08);
font-size: 24rpx;
color: #244132;
text-align: left;
}
.debug-inline-stack {
flex: 1;
display: flex;
flex-direction: column;
gap: 14rpx;
}
.control-row {
display: flex;
gap: 14rpx;
margin-top: 18rpx;
}
.control-row--compact {
margin-top: 0;
}
.control-row--compact .control-chip {
padding: 16rpx 10rpx;
font-size: 22rpx;
}
.control-row--single .control-chip {
flex: none;
width: 100%;
}
.debug-section .control-row:last-child {
margin-bottom: 0;
}