作者:鲍潼
在如今的货运业务中,导航系统的重要性不言而喻。它不仅可以为司机提供准确的路线和路况信息,帮助他们降低运输成本、提高运输效率,同时其底层能力也在计价、交易等场景中发挥着重要支撑作用。然而,现实中的道路情况复杂多变,仅通过常规的测试手段难以全面评估导航系统的准确性和可靠性。因此,到实际道路当中去进行测试验收成为了产品迭代的重要一环。在这种情况下,为了更好的提高路测效率,我们的团队开启了如下一段创新实践之旅。
一、背景与挑战
路测并非简单的把工位搬到车内,之后把车子开到既定的道路当中去查看应用的状态是否符合预期。而是需要我们在颠簸的道路上时刻关注导航的每一次刷新和每一轮播报,并在飞驰过某个路口的瞬间把问题详尽的记录下来。为了让验证更加充分,我们还需要设计更多路线并配置更多测试机,这也使得整个过程变得更加手忙脚乱。以上描述仅仅是路测行中的一个画面,当我们再去关注行前的准备过程和行后的总结分析环节,真可谓"劳劳车马未离鞍,行事方知路测难 "。为了尝试改变这种局面,我们深入实践调研,最终将问题归纳为以下几个方面:
- 问题闪现难抓取: 导航实时更新,同时关注多台设备出现问题时很难快速发现和记录。
- 信息采集不全面: 问题出现的瞬间难以集中采集所有信息,简单的问题描述难以支撑后续问题跟进。
- 数据整理耗时长: 由于信息分散导致问题整理困难,8小时的路测需要额外再花上4小时进行数据整理。
正是由于上述因素的存在,路测的整体效率大打折扣,不仅让人疲惫不堪,也对产品的快速迭代产生了负面影响。
二、方案设计
基于对路测过程的全面拆解分析,我们将平台建设重点定位在数据采集 、数据上报 和控制面板三个模块,各模块能力简述如下:
- 数据采集:通过Scrcpy、WDA、OBS等方式连通路测设备,稳定获取视频、图像、日志信息。
- 数据上报:以消息卡片的方式将反馈信息推送至飞书群组和在线文档,融合质量管理平台能力对疑似问题进行规范管理、高效跟踪。
- 控制面板:通过任务配置、UI配置等交互能力构建面向不同测试场景的前端操作面板,给予用户高效、灵活的使用体验。
以上三个模块的设计为行中能力的快速搭建提供了保障。在此基础之上,我们结合内部已有的工具平台能力,进一步将相关数据整合利用,实现了以路测任务为基础的行前、行后能力建设。
三、能力建设
平台能力以数据采集为核心,通过消息卡片的方式开启数据上报和流转,下面按照这个过程逐个介绍各环节重点能力的设计和实现。
3.1 数据采集
数据采集的主要对象是 Android、iOS测试机和车载摄像头,如果能把手机的屏幕、日志信息和行车实况的影像在记录问题的一瞬间快速打包归档,将极大程度减少测试人员的工作量。我们首先考虑通过云直播能力在推流端对所有设备视频内容进行抓取,之后在播放端进行扩展开发实现监控上报能力。如下图所示,该方案中视频的直播、存储、实时截图等能力都能很好的满足路测平台的需要。
但上述方案开发周期长、运营成本昂贵 (直播费用、录制费用、点播费用......),且播放端无法远程操控手机设备,所以我们不得不另寻他法。
核心解决方案
在这种背景下我们参照云真机的方案(货拉拉云真机平台的演进与实践 - 掘金)在随车电脑中部署一套路测服务,利用它将路测设备投屏至浏览器中实现数据采集。这种方案下屏幕中的手机画面既可以查看也可以操控,很好的满足了测试需要。
Android 投屏方案
- 原理介绍
Scrcpy是一款开源的跨平台屏幕镜像工具,通过USB或 Wi-Fi将设备进行连接,Scrcpy将手机屏幕内容编码为视频流,并通过ADB通道传输至电脑。在Mac端,Scrcpy接收并解码视频流,实时显示在电脑屏幕上。同时将鼠标和键盘事件转换为 Android事件(如触摸、点击、滑动等)发送回 Android 设备以实现远程控制。
在 Scrcpy的源码中也可以看到,服务启动后在设备上建立了视频流,音频流,控制事件的LocalSocket等待使用。
java
public static DesktopConnection open(int scid, boolean tunnelForward, boolean video, boolean audio, boolean control, boolean sendDummyByte) throws IOException {
String socketName = getSocketName(scid);
LocalSocket videoSocket = null;
//LocalSocket audioSocket = null;
//LocalSocket controlSocket = null;
try {
LocalServerSocket localServerSocket = new LocalServerSocket(socketName)
if (video) {
videoSocket = localServerSocket.accept();
if (sendDummyByte) {
// send one byte so the client may read() to detect a connection error
videoSocket.getOutputStream().write(0);
sendDummyByte = false;
}
}
//...
} catch (IOException | RuntimeException e) {
if (videoSocket != null) {
videoSocket.close();
}
//...
throw e;
}
return new DesktopConnection(videoSocket, audioSocket, controlSocket);
}
- 接入方案
Scrcpy在多平台提供了可直接使用的客户端,而我们需要在 Web端展示手机画面。为了解决这个问题,我们需要将Scrcpy的Socket连接转换为可以通过Web访问的形式。因此,我们搭建了一个WebSocket服务,该服务从本地运行的Scrcpy接收数据,并转发到浏览器。实现逻辑简要如下:
ini
const express = require('express');
const http = require('http');
const WebSocket = require('ws');
// 启动scrcpy并设置端口转发
startScrcpyAndForward()
const app = express();
const server = http.createServer(app);
const wss = new WebSocket.Server({ server });
wss.on('connection', ws => {
console.log('Connected to client');
// 模拟定期获取数据并发送
setInterval(() => {
const screenData = getScreenData(); // 从scrcpy获取屏幕数据
if (screenData) {
ws.send(screenData);
}
}, 100);
ws.on('close', () => {
console.log('Client disconnected');
});
});
iOS 投屏方案
在 iOS端我们采用了 WebDriverAgent的接入方案,同样基于 WebSocket协议获取屏幕实时内容。由于这方面的案例较多就不展开介绍。
由于在车载环境稳定性较差,上述方案中iOS设备闪断后很难快速接入,为此我们也利用了 OBS视频推送能力在 iOS端补充了视频投屏的方案,保障了系统可靠性的同时音频的采集也得以实现。一种比较简单的搭建方式是在 Mac中安装并启动 OBS应用,启动后程序会默认打开一个WebSocket服务,利用这个服务我们可以在代码中方便的对视频、音频进行获取和控制,十分灵活。
typescript
//使用OBS同步iOS设备视频
const obsWeb=()=>{
const OBSWebSocket = require("obs-websocket-js").default;
const obs = new OBSWebSocket();
obs.connect('ws://127.0.0.1:4455', '******')
.then(() => {
console.log(`Success!`);
return obs.call('SetCurrentProgramScene',{sceneName:currentSceneName})
})
.catch((error)=>{
console.log("连接失败",error);
})
}
//同步iOS设备音频
const obsAudio=(val)=>{
const OBSWebSocket = require("obs-websocket-js").default;
const obs = new OBSWebSocket();
obs.connect('ws://127.0.0.1:4455', '******')
.then(()=>{
return obs.call('GetSceneList');
})
.then((data) => {
data.scenes.forEach((item)=>{
obs.call('GetSceneItemList',{sceneName:item.sceneName})
.then((data)=>{
let type;
if(val)
type='OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT';
else
type='OBS_MONITORING_TYPE_NONE';
data.sceneItems.forEach(item=>{
obs.call('SetInputAudioMonitorType',{inputName:item.sourceName,monitorType: type});
})
})
})
}).catch((error)=>{
console.log("连接失败",error);
})
}
上述方案综合接入后的效果如下图所示,通过随车电脑连接测试机,行车摄像头,将它们的画面实时投屏到电脑屏幕上,同时通过 adbkit可以读取Android设备的日志信息。在发现问题时,各设备的画面和日志信息都得以快速获取。
3.2 数据上报
此部分能力利用飞书开放接口将采集到的数据以消息卡片的形式推送到飞书群组当中,参与人根据专业的判断对反馈的问题进行处理,疑似为产品缺陷的问题将一键提交至货拉拉质量管理平台进行后续跟进。基于该设计的提效场景主要体现在以下三个方面:
- 消息卡片快速触达,快捷流转处理。
- 自动生成在线文档,集中评审更方便。
- 打通质量管理平台,缺陷管理更规范。
3.3 控制面板
为了满足不同类型路测任务,控制面板的能力为路测人员提供了一套完整、高效的操作台,在这里可以完成所有的基础信息配置,监视所有设备状态,并在问题发生的瞬间快速完成问题记录和上报。
3.4 视频直播及录制
将车载电脑的画面进行实时直播和录制,办公室内的同事就能实时远程协助外出路测人员,同时还能在事后进行问题回溯。实现上,我们首先考虑的还是云直播的方案,但在日常工作中我们观察到飞书会议具有桌面共享和会议录制功能,那么是否可以利用它来实现路测画面的直播呢?有了这个巧妙的想法,我们很快进行调研和尝试,并将其融入到平台的流程当中。现在,我们只需在控制面板上一键发起录制视频,系统就会自动进行任务关联和信息填充,并快速调起会议,启动共享和录制。
如下图所示,在路测过程中,随车电脑的画面被共享和记录,相关人员可以随时远程接入协助路测。同时,视频中的语音播报内容也以文字的形式顺序呈现,一定程度上也提升了问题定位和识别能力。
3.5 一键下单
与常规的导航软件测试不同,货运业务场景下的导航测试前置依赖较多,路测人员需要在不同客户端中进行下单、接单等操作,一系列步骤之后如果发现规划的路线与路测要求不符还需要重新再来一遍。在此背景下,我们融合数据工厂、LBS平台等能力,在行前提供了一套一键下单的解决方案。该功能涵盖了热点推荐、路线对比及自助下单功能,很大程度上减轻了路测人员的负担。
- 根据路测城市,自动推荐热点数据确保路测更贴合实际使用场景。
- 基于路型、里程、时间等参数综合判定路线相似度,避免反复人工比对提效显著。
- 融合数据工厂能力,快速批量创建订单,高效进入做单环节。
以上内容向大家介绍了路测平台在几个核心场景下的功能设计和实践创新,除此以外我们也在数据计算、问题分析、报告统计方面做了很多探索,后续会陆续整理输出与大家分享。
四、实践应用
路测平台在建设之初便投入使用,实践过程中针对出现的问题和挑战及时改进。通过深度挖掘货运路测场景,成功构建出一个与业务需求高度契合的工具平台。从实际效果来看,以下这些数字也充分证明了这一点。
4.1 提效数据
- 在采集问题信息更全面的情况下,记录和上报问题时间由分钟级提升至秒级。
- 每日路测整理报告时长节省 96% (4小时提升至10分钟)。
- 真实做单路测工具投入使用后,日反馈量提升 3倍 (5.5条/天提升至 17.25条/天)。
- 提升路测质量,标准化反馈内容信息更全面。
4.2 落地应用
平台化路测工具快速与业内拉齐,高效支持相关业务开展。过去的一年,我们的平台支持了产研团队在10余 个城市开展多次路测,累计行驶 10000 余公里,收集反馈 1520余条。工具的支撑让路测同学有更多的精力关注产品效果,大大提升了产研同学对业务场景和产品使用的理解。如下图所示,单月的里程就覆盖了全市大部分区域。
五、未来展望
我们充分的利用现有资源,基于务实的方案成功地控制了成本、确保了进度。接下来我们将继续着力探索更稳定、更便捷的服务方式,根据业务需要充分挖掘数据的潜在价值,实现更大的突破。
- 交互流程优化: 梳理现有流程中的不足,面向各个场景制定提升稳定性、易用性的改进方案。
- 路测追踪功能: 实时汇总当前车辆情况,便捷的提供远程入口,优化路测组织模式降低人力成本。
- 路测平台看板: 全景数据统计及指标展示,为产品方案和路测计划提供决策支撑。