云计算百科
云计算领域专业知识百科平台

第一篇:智能割草机 App 到底复杂在哪里?移动端业务全景拆解

很多人第一次接触智能割草机 App,可能会觉得它和扫地机器人 App 差不多:

  • 绑定设备

  • 点击开始

  • 查看运行状态

  • 没电自动回充

从界面上看,功能似乎并不复杂。

但真正进入业务之后就会发现,智能割草机 App 并不是一个简单的“设备遥控器”。

它需要同时连接用户、云端服务、IoT 平台、割草机设备、庭院地图以及 RTK 定位系统。用户在 App 中点击一次“开始割草”,背后可能会触发设备状态校验、地图校验、任务创建、指令下发、设备执行、实时位置上报和异常监控等一整套流程。

这一篇先不讨论具体代码,而是从移动端角度,完整拆解智能割草机业务。


一、割草机 App 不是普通的接口型应用

普通的商城、资讯或者内容类 App,核心数据通常来自服务端。

移动端发送一个 HTTP 请求:

App

服务器

返回数据

页面展示

只要接口返回成功,页面通常就可以认为本次操作已经完成。

例如用户修改昵称,服务器返回成功后,App 就可以更新用户信息。

但设备类 App 不一样。

用户在割草机 App 中点击“开始割草”后,服务器返回成功,只能说明服务器收到了请求,并不能证明割草机已经真正开始工作。

完整链路可能是:

用户点击开始割草

App 检查当前设备状态

App 向服务器发送控制指令

服务器将指令发送给 IoT 平台

IoT 平台将指令转发给割草机

割草机接收并校验指令

割草机开始执行任务

割草机上报新的运行状态

App 收到状态后更新页面

这条链路中任何一个环节出现问题,都可能导致操作失败。

例如:

  • 手机网络正常,但设备已经离线;

  • 服务器成功接收指令,但设备没有收到;

  • 设备收到指令,但当前存在故障,无法执行;

  • 设备开始执行,但 RTK 定位状态不满足要求;

  • App 没有及时收到最新状态,页面仍然显示“准备中”。

因此,在设备业务中:

接口调用成功,不等于设备执行成功。

这是理解整个割草机移动端架构的第一个关键点。


二、移动端连接的不是一台设备,而是一套系统

从用户界面来看,App 操作的是一台割草机。

但从技术架构来看,移动端实际连接的是一套完整系统。

用户

割草机 App

业务服务器

IoT 平台

割草机设备

RTK 基站与定位系统

除此之外,还包括:

  • 用户账号

  • 家庭或者庭院

  • 设备

  • 庭院地图

  • 割草区域

  • 禁区

  • 充电桩

  • 割草任务

  • 实时轨迹

  • 故障告警

  • 固件升级

这些对象之间并不是孤立的。

一台割草机通常属于某个家庭或者庭院,一个庭院下可能有一张或多张地图,一张地图中又可能包含多个工作区域、禁区和连接通道。

可以将核心业务关系理解为:

用户

家庭 / 庭院

割草机设备

庭院地图

工作区域

割草任务

用户切换家庭后,设备列表会发生变化。

用户切换设备后,当前地图、任务状态、告警信息和设备设置也需要同时切换。

因此,移动端不能只维护一个简单的 deviceId,而是需要建立完整的业务上下文。

例如:

data class AppContextState(
val currentUser: User?,
val currentHome: Home?,
val currentDevice: MowerDevice?,
val currentMap: MowerMap?
)

这些上下文发生变化时,页面中的其他业务模块也需要同步更新。


三、割草机业务可以拆成哪些模块

从移动端视角,智能割草机业务大致可以拆成以下几个核心模块:

智能割草机 App
├── 用户与家庭
├── 设备接入
├── 设备通信
├── 设备实时状态
├── 地图与区域
├── 割草任务
├── RTK 与定位
├── 告警与故障
├── OTA 升级
└── 数据缓存与同步

这些模块之间又存在大量交叉。

例如“开始割草”这个功能,就会同时依赖:

  • 当前用户是否拥有设备控制权限;

  • 设备是否在线;

  • 设备是否正在升级;

  • 当前地图是否有效;

  • 是否选择了工作区域;

  • RTK 状态是否正常;

  • 电量是否满足要求;

  • 是否存在未处理的严重故障;

  • 当前是否已经存在其他任务。

因此,一个按钮背后,往往不是一个接口,而是一组业务规则。


四、设备接入:先让 App 找到一台真实设备

普通 App 安装完成后,用户登录就可以使用。

但割草机 App 在登录之后,还需要完成设备接入。

常见流程包括:

扫描设备二维码

获取设备编号

通过蓝牙发现设备

建立近场连接

向设备发送 Wi-Fi 信息

设备连接云端

服务器确认设备在线

账号绑定设备

这里至少涉及三种对象:

手机 App
割草机设备
业务服务器

配网失败时,也不能简单显示“连接失败”。

移动端需要判断失败发生在哪一步:

  • 没有扫描到设备;

  • 蓝牙权限未开启;

  • 手机与设备连接失败;

  • Wi-Fi 密码错误;

  • 设备无法连接路由器;

  • 设备已连接网络,但无法访问云端;

  • 设备已经被其他账号绑定;

  • 云端绑定接口失败。

这些失败原因对应的用户处理方式完全不同。

因此,设备接入本身就是一个完整的状态流程,而不是一个普通页面。


五、设备通信:不同协议负责不同事情

割草机 App 往往不会只使用 HTTP。

常见通信方式包括:

通信方式主要用途
HTTP 查询设备、地图、历史任务和设备设置
MQTT 设备状态上报、消息订阅和控制指令
WebSocket App 与服务端之间的实时数据同步
BLE 配网、近场控制和设备诊断
局域网通信 同一网络下的快速设备控制

不同通信方式解决的问题不同。

例如,设备列表可以通过 HTTP 查询,但设备当前位置和任务进度属于高频实时数据,如果完全依赖轮询接口,会产生较大的延迟和请求压力。

设备运行过程中可能持续上报:

  • 当前坐标

  • 当前电量

  • 工作状态

  • 任务进度

  • RTK 状态

  • 故障信息

  • 充电状态

这些数据更适合通过 MQTT 或 WebSocket 推送。

移动端架构需要把不同通信方式统一到业务层,而不是让页面直接操作 MQTT、蓝牙或者 WebSocket。

理想的数据流应该是:

MQTT / WebSocket / HTTP / BLE

DataSource

Repository

ViewModel

UI

这样页面只关心业务状态,而不需要知道数据来自哪个协议。


六、实时状态:页面不是接口结果,而是设备当前状态

设备类 App 最重要的数据之一,就是设备实时状态。

一台割草机可能处于:

离线
在线空闲
准备中
割草中
暂停中
返回充电
充电中
升级中
故障中

如果使用多个 Boolean 表示状态,很快就会出现冲突。

例如:

val isOnline: Boolean
val isWorking: Boolean
val isCharging: Boolean
val isReturning: Boolean
val hasError: Boolean

一旦同时出现:

isWorking = true
isCharging = true

业务就会变得难以判断。

因此,更合理的方式是将设备状态设计成明确的状态模型:

sealed interface DeviceWorkingState {
data object Offline : DeviceWorkingState
data object Idle : DeviceWorkingState
data object Preparing : DeviceWorkingState
data object Mowing : DeviceWorkingState
data object Paused : DeviceWorkingState
data object Returning : DeviceWorkingState
data object Charging : DeviceWorkingState
data object Updating : DeviceWorkingState
data class Fault(val code: String) : DeviceWorkingState
}

页面上的按钮、提示文案和交互方式,都应该由当前状态决定。

例如:

空闲:
显示“开始割草”

割草中:
显示“暂停”和“结束”

暂停中:
显示“继续”和“返回充电”

升级中:
禁止设备控制

故障中:
优先显示故障处理入口

这也是为什么设备业务非常依赖状态机设计。


七、割草任务不是一次简单的开始和结束

用户看到的割草任务,可能只是一次“开始割草”。

但设备真正执行时,任务会经历多个阶段:

任务创建

设备准备

离开充电桩

前往工作区域

开始割草

电量不足

返回充电

充电完成

继续割草

任务完成

在这个过程中,还可能出现:

  • 用户主动暂停;

  • 用户主动结束;

  • 设备被抬起;

  • 刀盘堵转;

  • 车轮被卡住;

  • RTK 定位丢失;

  • 设备超出电子围栏;

  • 天气不适合作业;

  • 设备突然离线。

因此,割草任务本身也需要一个状态机。

移动端需要根据任务状态解决三个问题:

第一,当前页面应该展示什么。

第二,当前用户可以执行哪些操作。

第三,App 被关闭再打开后,如何恢复任务状态。

这意味着任务状态不能只保存在当前页面的 ViewModel 中,而应该由 Repository 根据服务器数据和设备实时上报统一维护。


八、割草机地图不是普通地图

普通地图类 App 主要展示道路、地点和导航路线。

割草机地图展示的却是设备可以在哪里工作。

一张庭院地图可能包含:

工作区域
禁区
连接通道
充电桩
RTK 基站
割草机位置
实时轨迹
历史轨迹

例如,用户可能在同一个庭院中划分:

  • 前院

  • 后院

  • 草坪一区

  • 草坪二区

  • 花坛禁区

  • 水池禁区

  • 区域之间的连接通道

这些数据不是简单的地图覆盖物,而是实际参与设备工作决策的业务数据。

地图模块至少需要处理:

  • 区域边界绘制;

  • 禁区绘制;

  • 多边形闭合;

  • 边界点拖动;

  • 区域自相交校验;

  • 禁区是否位于工作区内部;

  • 通道是否有效连接两个区域;

  • 地图版本同步;

  • 本地编辑与云端地图冲突。

因此,地图在割草机 App 中不是一个 UI 组件,而是核心业务模块。


九、RTK 为什么会成为核心业务

传统 GPS 定位通常存在米级误差。

对于汽车导航来说,几米的误差大多数情况下可以接受,但对于割草机来说,几米误差可能意味着:

  • 割到花坛;

  • 冲出草坪;

  • 重复割草;

  • 漏掉大片区域;

  • 无法准确沿边;

  • 无法返回充电桩。

因此,智能割草机通常需要更高精度的定位能力,RTK 就成为其中非常关键的一部分。

移动端一般不会负责 RTK 定位算法本身,但需要负责:

  • 展示基站状态;

  • 展示设备定位状态;

  • 展示卫星或者信号信息;

  • 接收设备坐标;

  • 判断定位数据是否有效;

  • 在定位异常时引导用户处理。

RTK 状态也不是简单的“成功”和“失败”。

常见状态可能包括:

未连接
初始化中
单点解
浮点解
固定解
信号弱
定位丢失

当设备轨迹发生跳点时,移动端还需要结合:

  • 坐标时间戳;

  • 定位精度;

  • RTK 解状态;

  • 设备移动速度;

  • 前后坐标距离;

  • 当前任务状态;

共同判断这条坐标是否可信。


十、故障提示不能只显示错误码

实体设备运行在真实环境中,故障是不可避免的。

割草机常见异常包括:

  • 左轮或者右轮堵转;

  • 刀盘堵转;

  • 设备被抬起;

  • 设备倾斜;

  • 碰撞传感器异常;

  • 充电失败;

  • 电池温度异常;

  • RTK 信号弱;

  • 定位丢失;

  • 设备越界;

  • 设备离线。

设备上报的通常是一个错误码,例如:

ERROR_WHEEL_LEFT_BLOCKED

但普通用户无法理解这种错误。

移动端需要完成一层业务转换:

设备错误码

业务错误类型

用户可以理解的描述

具体处理步骤

最终展示给用户的内容应该类似:

左轮可能被异物卡住。

请关闭设备,并检查左轮周围是否存在树枝、
石块或者缠绕的杂草。

同时还要区分:

  • 普通提示;

  • 可恢复告警;

  • 严重故障;

  • 必须立即停止任务的故障。

这部分不仅是文案工作,也是业务架构的一部分。


十一、最难的问题:App、服务器和设备状态不一致

割草机业务中,同时存在三份状态:

App 本地状态
服务器记录状态
设备真实状态

这三份状态可能并不一致。

例如:

App 显示设备正在割草,
但设备实际已经离线。

服务器显示指令发送成功,
但设备没有真正执行。

用户在本地修改了地图,
但新地图还没有同步到设备。

因此,移动端必须明确不同数据的可信来源。

一般可以按照下面的原则处理:

账号、家庭和设备配置:
以服务器为准

设备实时运行状态:
以设备最新上报为准

地图编辑中的临时数据:
以本地编辑副本为准

历史任务和历史告警:
以服务器记录为准

此外,还需要结合消息时间戳和数据版本,避免旧消息覆盖新状态。

例如设备先上报“割草中”,随后上报“已暂停”,但由于网络延迟,“割草中”的消息最后才到达 App。

如果移动端不校验消息时间,就可能把页面错误地恢复成“割草中”。


十二、从移动端角度看整体架构

将前面的业务放在一起,可以得到一套基本架构:

┌─────────────────────────────────────┐
│ UI 层 │
│ 首页、地图、任务、告警、设置、OTA │
├─────────────────────────────────────┤
│ 状态管理层 │
│ 设备状态、任务状态、地图状态、连接状态│
├─────────────────────────────────────┤
│ 业务层 │
│ 设备控制、任务管理、地图管理、RTK 管理│
├─────────────────────────────────────┤
│ 数据层 │
│ Repository、Local、Remote、Device │
├─────────────────────────────────────┤
│ 通信层 │
│ HTTP、MQTT、WebSocket、BLE、局域网 │
└─────────────────────────────────────┘

对应到常见的移动端代码结构,可以是:

UI

ViewModel

UseCase / Manager

Repository

RemoteDataSource
LocalDataSource
DeviceDataSource

其中:

  • UI 只负责展示和接收用户操作;

  • ViewModel 负责页面状态;

  • UseCase 负责完整业务流程;

  • Repository 负责统一数据来源;

  • DataSource 负责具体通信和存储;

  • MQTT、BLE、HTTP 等细节被隔离在数据层以下。

这样的设计能够避免页面和设备协议强耦合。


十三、割草机业务真正考验的是什么

从移动端开发者角度看,割草机业务真正复杂的地方,并不是页面数量,也不是某一个地图 SDK 或通信框架。

它真正考验的是以下几种能力:

1. 业务建模能力

能否把设备、地图、区域、任务、定位和故障抽象成清晰的业务模型。

2. 状态管理能力

能否处理设备在线、割草、暂停、回充、充电、故障等复杂状态。

3. 多通信链路管理能力

能否将 HTTP、MQTT、WebSocket 和 BLE 统一到一套业务架构中。

4. 数据一致性能力

能否处理 App、服务器和设备状态不一致的问题。

5. 异常恢复能力

能否在断网、设备离线、App 重启和指令超时后恢复正确状态。

6. 模块边界设计能力

能否让地图、设备、任务、定位和通信模块保持清晰边界,而不是全部堆在一个 ViewModel 中。


总结

智能割草机 App 看起来像一个设备控制工具,实际上却是一个典型的复杂 IoT 移动端系统。

它同时需要处理:

用户与家庭
设备接入
多协议通信
实时状态
任务状态机
庭院地图
RTK 定位
异常告警
OTA 升级
多端数据一致性

普通接口型 App 关注的是:

接口返回了什么。

而设备型 App 更关注的是:

设备现在到底处于什么状态。

这也是整个割草机移动端架构的核心。

后续文章将从设备接入开始,逐步拆解蓝牙配网、设备绑定以及设备上线的完整链路。

下一篇预告

《割草机 App 如何连接一台真实设备?从扫码绑定到蓝牙配网》

下一篇将重点讨论:

  • 为什么扫码后还需要蓝牙;

  • 手机、服务器和设备分别承担什么职责;

  • 配网过程如何设计成状态机;

  • 手机连接成功为什么不等于设备上线;

  • 配网失败后如何定位具体问题。

赞(0)
未经允许不得转载:网硕互联帮助中心 » 第一篇:智能割草机 App 到底复杂在哪里?移动端业务全景拆解
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!