本文是 Uber 的客户端工程师团队讲述了如何开发最新版本司机端系列文章中的第七篇,该系列代号 Carbon ,是咱们共享出行业务的核心。包括其它功能在内,Uber 司机端使得超过 300 万名司机能够查看费用、里程以及收益状况。2017 年咱们结合司机的反馈开始对司机端进行从新设计,并在 2018 年 9 月份启动了该项目。html
因为技术和物理因素,接驾对于乘客和司机来讲都是一个特别难的痛点。技术方面,咱们须要司乘两端达成相对的同步。物理方面,例如在一个夜间拥挤的街道,司机、乘客将彼此很难找寻到对方。对于平台来讲,帮助乘客轻松辨识车辆是成功开启愉快行程的关键。react
指示灯 是咱们应用程序进入现实世界的一种扩展,这是一个给司乘 2 方提供直观颜色匹配的设备,乘客能够选择光谱中的任何颜色进行设置。在黑暗和暴风雨的夜晚,选择一种颜色照亮司机车辆的挡风玻璃,可让你更快速方便的找寻到车辆。事实上推进这种体验的工程设计并不简单。接下来让咱们深刻了解一下如何利用咱们的 APP 实现这种体验。编程
乘客经过指示灯功能来选择一种颜色,而后将其传输给汽车上的指示灯设备,这样乘客就能够快速方便的知道哪辆车是来接他的。后端
指示灯的大部分功能是在咱们司机端 APP 上使用。实现须要使用 2 组资源:Beacon SDK:负责经过蓝牙跟指示灯设备进行通讯。RIBs架构 中的一系列功能模块利用 Beacon SDK 实现司机端的功能。安全
Beacon SDK 几乎实现了指示灯设备的全部用户体验功能,它利用蓝牙实现了司机端 APP 和指示灯设备之间链接跟数据沟通的功能。在设计 Beacon SDK 时,咱们遵循了三个原理:服务器
由于 Uber 的移动端架构是跨平台的,同时支持 iOS 跟安卓设备,因此 Beacon SDK 的架构设计也必须是跨平台的。在跨平台方面以后,咱们能够更快速的迭代并提供给其余团队更方便的接入方式。网络
SDK 开发最关键的原则是去掉 SDK 对应用的依赖。随着咱们逐步开发新司机端 APP,这点显得尤为重要。SDK 的独立性使得咱们在新旧司机端 APP 同时开发中能够经过迭代 SDK 的方式同步进行,避免中断。架构
为了兼容 Uber 移动端响应式编程架构,在设计 Beacon SDK 时,必须暴露可观察对象(Observable)。使用这个 SDK 的工程师能够直接经过观察反应的方式与指示灯进行交互。使用这个 SDK 的工程师能够直接经过观察反应的方式与指示灯进行交互。蓝牙 API 的使用复杂性被抽象掉了。app
咱们设计的 Beacon SDK 具备一系列的管理器对象(Manager),其中每一个管理器负责指示灯功能的一部分,例如链接、LED 控制、无线下载(OTA)更新和传感器。每组管理器负责与指示灯设备的某个功能互通,司机端 APP 控制这些的管理器来操做指示灯设备。框架
图 1:Beacon 被分解成多个逻辑管理器,管理器用来反映 Beacon 状态并提供特定功能。
管理器(Manager)定义了接口,SDK 提供了对应接口的实现。这些管理器封装了蓝牙 API 将命令从司机端传递到指示灯设备。
因为 Beacon SDK 并无提供专用的用户界面,所以几乎全部的 Beacon 功能都是经过 worker 提供的。Worker 是本质上是没有专用UI组件的交互者,所以逻辑与 APP 中的视图无关。在须要使用指定功能时,Carbon 将 worker 添加到 RIB 树中实现,当从 RIB 树中移除时,worker 被分离且被垃圾回收。
每一个 worker 都依赖于一个或多个 Beacon SDK 管理器(Manager)。 管理器被添加给 RIB 里面的 Worker 对象。当一个 worker 被实例化时,worker 会添加由上游范围提供的管理器对象。经过这种方式,Beacon 的管理器能够在全部 worker 之间共享,而且 worker 不负责这些管理器的生命周期。
图 2:在 Carbon 的 RIB 树的这一小节中,Beacon 的 Workers 都在 Active 和 Online 的时候才会生效。管理器在 Active 时被添加依赖并提供给下游 Workers。
RIB 树让咱们根据 worker 是否使用 Beacon 功能来决定是启用仍是禁用插件点(plugin points)。若是禁用 Beacon,插件点则禁用;若是 worker 不被建立,那么就不会初始化 Beacon SDK 的管理器,从根本上消除了 Beacon 运行时的内存空间。
若是启用 Beacon 功能,咱们须要遵循协议,worker 才会被添加到 RIB 树中。例如 Beacon Alert 管理器,它是在应用内提供例如“低电量”或“指示灯未找到”这种提示窗的管理器。想象一下当司机在家的时候打开 APP 查看他们的收入,此时司机的状态是离线状态,由于司机并无开始接单;此时司机并无使用指示灯的需求,所以不须要收到相似的弹窗。咱们只会在司机在路上接乘客的时候(在线时)才会接入 Beacon Alert 管理器,由于这个时候提示功能才有意义。
有了 Beacon 框架,咱们能够在司机端 APP 中实现颜色匹配功能。
如下流程都必须严格依赖司机端已链接到指示灯设备且此时是在线状态。当司机在线时,Beacon 的功能 worker 会添加到 RIB 树上,才能使用司机端的 Beacon 功能更新服务器。随着司机端的在线与离线,咱们会相应的更新状态。当司机端断线时,后端会自动关闭该功能。
当司机端接到乘客的订单后,乘客端的 APP 就会收到司机的名字、车辆信息以及他们是否具备指示灯的能力。若是具备指示灯功能,咱们会在乘客端 APP 中展现指示灯的图标。乘客端 APP 会自动给服务器发送以前选择过的颜色(如乘客从未选择颜色,则随机选择一种颜色),而后通知给司机端 APP 所选颜色。
在等待接驾时,乘客能够经过点击指示灯图标进入颜色选择页面(某些特定颜色由于安全合规被移除,例如红色、蓝色),在这里乘客能够选择任何他们中意的颜色。每当乘客选中了一个颜色,就会把这个色值传递给后端,后端又通知给司机端 APP。
图 3:当司机端与指示灯链接成功后,就会被通知给后端,当乘客匹配到这个车辆,乘客就能够选择一种指示灯颜色。
在司机端这边,当司机在线时,有个 Beacon Color Worker 一直在监听颜色变化的通知。当收到了一个新颜色,就会本地存储一份。这样,若是司机接受了多个调度,例如拼车场景,咱们会记录每一个被接驾的乘客所设置的颜色。
图 4:行程中有不少个拼车乘客,咱们会存储这些乘客每一个选择的颜色。
当后端通知咱们已经在去接某个乘客路上时,咱们会给 Beacon 控制颜色的管理器发送一条指令(-经过技术手段得到所匹配乘客选择的色值),告诉他显示这个乘客所选中的颜色。同时在接驾过程当中,车辆会不断更新显示乘客以后更改的任何颜色,保持乘客端跟司机端的同步。
图 5:当乘客被接驾时,咱们会检索他们所选择的最后一种颜色。
优步一直在寻找优化用户体验的方法。软硬件结合的方式将平台能力扩展到现实世界是一种天然的进步。软硬件结合的方式将平台能力扩展到现实世界带来了新的使人兴奋的挑战,优步指示灯只是如何在这个领域进行创新的一个例子。这也是优步的移动工程师最激动人心的时刻。