很多人第一次接触智能割草机 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 查询,但设备当前位置和任务进度属于高频实时数据,如果完全依赖轮询接口,会产生较大的延迟和请求压力。
设备运行过程中可能持续上报:
当前坐标
当前电量
工作状态
任务进度
RTK 状态
故障信息
充电状态
这些数据更适合通过 MQTT 或 WebSocket 推送。
移动端架构需要把不同通信方式统一到业务层,而不是让页面直接操作 MQTT、蓝牙或者 WebSocket。
理想的数据流应该是:
MQTT / WebSocket / HTTP / BLE↓DataSource↓Repository↓ViewModel↓UI
这样页面只关心业务状态,而不需要知道数据来自哪个协议。
六、实时状态:页面不是接口结果,而是设备当前状态
设备类 App 最重要的数据之一,就是设备实时状态。
一台割草机可能处于:
离线在线空闲准备中割草中暂停中返回充电充电中升级中故障中
如果使用多个 Boolean 表示状态,很快就会出现冲突。
例如:
val isOnline: Booleanval isWorking: Booleanval isCharging: Booleanval isReturning: Booleanval hasError: Boolean
一旦同时出现:
isWorking = trueisCharging = true
业务就会变得难以判断。
因此,更合理的方式是将设备状态设计成明确的状态模型:
sealed interface DeviceWorkingState {data object Offline : DeviceWorkingStatedata object Idle : DeviceWorkingStatedata object Preparing : DeviceWorkingStatedata object Mowing : DeviceWorkingStatedata object Paused : DeviceWorkingStatedata object Returning : DeviceWorkingStatedata object Charging : DeviceWorkingStatedata object Updating : DeviceWorkingStatedata 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↓RemoteDataSourceLocalDataSourceDeviceDataSource
其中:
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 如何连接一台真实设备?从扫码绑定到蓝牙配网》
下一篇将重点讨论:
为什么扫码后还需要蓝牙;
手机、服务器和设备分别承担什么职责;
配网过程如何设计成状态机;
手机连接成功为什么不等于设备上线;
配网失败后如何定位具体问题。
夜雨聆风