智能扫地机器人控制系统实战:Flutter+三方库深度集成与鸿蒙开发全栈实现
欢迎加入开源鸿蒙跨平台社区: https://openharmonycrossplatform.csdn.net本项目是一套,核心采用搭建跨平台移动端/桌面端控制界面,依托实用实现机器人联动、路径规划、状态监控、指令下发,同时兼容实现鸿蒙生态设备(手机、平板、智慧屏)对扫地机器人的统一控制。全程提供可落地的详细步骤,从环境搭建到项目打包,零基础也能完成完整项目实践,最终实现:远程控制扫地机器人启动
Flutter+三方库集成+鸿蒙开发:智能扫地机器人控制系统全栈实战
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
本项目是一套智能扫地机器人专属控制系统,核心采用Flutter搭建跨平台移动端/桌面端控制界面,依托实用三方库实现机器人联动、路径规划、状态监控、指令下发,同时兼容鸿蒙开发(HarmonyOS NEXT) 实现鸿蒙生态设备(手机、平板、智慧屏)对扫地机器人的统一控制。全程提供可落地的详细步骤,从环境搭建到项目打包,零基础也能完成完整项目实践,最终实现:远程控制扫地机器人启动/暂停、模式切换(自动清扫、定点清扫、沿边清扫)、路径可视化、电量/清扫进度监控、故障报警等核心功能。
一、项目核心技术栈(聚焦扫地机器人场景)
核心围绕智能扫地机器人的控制需求,筛选适配性强、易上手的技术与三方库,避免冗余,确保实战性:
- Flutter:跨平台主应用开发(支持Android、iOS、Windows、macOS),一套代码覆盖多端控制界面,无需单独开发多端版本。
- Flutter核心三方库(扫地机器人专属):
mqtt_client:MQTT协议通信(物联网主流),实现Flutter端与扫地机器人、鸿蒙设备的指令/状态传输(核心三方库)。provider:全局状态管理,统一管理扫地机器人状态(启动/暂停、模式、电量、故障),实现跨页面状态同步。fl_chart:数据可视化,展示扫地机器人清扫面积、电量变化、清扫时长等数据。shared_preferences:本地缓存,存储机器人连接信息、常用清扫模式、历史清扫记录。flutter_map:地图与路径可视化,展示扫地机器人实时位置、清扫路径,支持定点清扫区域选择。connectivity_plus:网络状态监听,提醒用户设备连接状态(WiFi/局域网),避免指令下发失败。
- 鸿蒙开发:HarmonyOS NEXT(Stage模型),开发鸿蒙设备控制端,实现智慧屏、鸿蒙手机对扫地机器人的本地/远程控制,兼容鸿蒙分布式能力。
- 机器人通信适配:支持主流扫地机器人通信协议(MQTT为主,备用WebSocket),可适配ESP32模拟机器人(无实物也可调试)或真实扫地机器人(小米、科沃斯等开源协议设备)。
- 辅助工具:EMQ X(MQTT服务器)、MQTTX(通信调试工具)、DevEco Studio(鸿蒙开发IDE)、VS Code(Flutter开发IDE)。
二、开发环境准备(必做步骤,缺一不可)
所有环境均提供具体下载路径和验证方法,确保新手也能顺利完成配置,重点适配扫地机器人的通信需求。
2.1 Flutter开发环境配置(控制端核心)
- 下载Flutter SDK:Flutter官方下载(建议下载稳定版,避免beta版兼容性问题),根据自身系统(Windows/Mac)选择对应版本。
- 配置系统环境变量:
- Windows:右键「此电脑」→属性→高级系统设置→环境变量,将Flutter SDK的
bin目录(如:D:\flutter\bin)添加到系统PATH中。 - Mac:打开终端,编辑
~/.bash_profile或~/.zshrc,添加命令export PATH=$PATH:/Users/你的用户名/flutter/bin,保存后执行source ~/.bash_profile生效。
- Windows:右键「此电脑」→属性→高级系统设置→环境变量,将Flutter SDK的
- 安装开发工具:
- 安装Android Studio(必装,用于Android模拟器/真机调试),安装时勾选「Android SDK」「Android Emulator」组件。
- (可选)Mac用户安装Xcode,用于iOS端调试。
- 推荐安装VS Code,安装Flutter、Dart插件(打开VS Code→扩展→搜索「Flutter」「Dart」,点击安装)。
- 环境验证:打开终端/CMD,执行命令:
确保无红色错误(黄色警告可忽略),出现「All done!」即为配置成功。flutter doctor
2.2 鸿蒙开发环境配置(鸿蒙设备适配)
- 下载DevEco Studio:鸿蒙开发工具官方下载,选择对应系统版本。
- 安装OpenHarmony SDK:打开DevEco Studio,按照引导安装SDK,选择API 11及以上版本(HarmonyOS NEXT最新稳定版),勾选「Stage模型」相关组件。
- 创建鸿蒙模拟器:打开DevEco Studio→Tools→Device Manager,创建鸿蒙手机/智慧屏模拟器(推荐API 11,分辨率1080*1920),启动模拟器验证环境。
- 安装鸿蒙MQTT依赖:提前下载
@ohos/mqtt依赖包,后续在项目中直接导入(适配扫地机器人通信)。
2.3 MQTT服务器搭建(机器人通信核心,必做)
扫地机器人、Flutter端、鸿蒙端的所有指令和状态,均通过MQTT服务器传输,推荐使用免费开源的EMQ X服务器,步骤如下:
- 下载EMQ X服务器:EMQ X官方下载,选择「EMQ X Open Source」,根据系统选择对应版本。
- 启动MQTT服务器:
- Windows:双击安装包完成安装,启动EMQ X服务(可在服务列表中找到「emqx」,设置为自动启动)。
- Mac/Linux:终端执行命令
sudo emqx start,启动后执行sudo emqx status验证是否启动成功。
- 测试服务器:打开浏览器,访问
http://127.0.0.1:18083,默认账号admin,密码public,登录后可查看服务器状态。 - 安装MQTTX调试工具:MQTTX官方下载,安装后打开,创建连接(服务器地址
127.0.0.1,端口1883,无密码),连接成功后即可调试通信。
2.4 扫地机器人模拟(无实物也可调试)
若没有真实扫地机器人,可使用ESP32开发板模拟,步骤简化:
- 下载ESP32固件(含MQTT通信功能):可在GitHub搜索「ESP32 扫地机器人模拟固件」,下载后刷入ESP32。
- ESP32连接WiFi:配置WiFi名称和密码,确保与Flutter端、鸿蒙端、MQTT服务器在同一局域网。
- 验证模拟:通过MQTTX发送指令(如「start」),ESP32会返回「已启动清扫」,模拟机器人响应。
三、Flutter项目创建与三方库集成(核心步骤)
此环节聚焦扫地机器人控制需求,创建标准化项目结构,集成所有核心三方库,每一步均提供具体命令和代码,可直接复制执行。
3.1 创建Flutter智能扫地机器人项目
- 打开终端/CMD,执行命令创建新项目(项目名称可自定义,此处以
smart_sweeping_robot_flutter为例):flutter create smart_sweeping_robot_flutter cd smart_sweeping_robot_flutter - 打开项目:用VS Code打开创建的项目,删除默认模板代码(
lib/main.dart中的默认Widget),保留主入口结构。
3.2 集成核心三方库(扫地机器人专属)
- 打开项目根目录下的
pubspec.yaml文件,在dependencies节点下添加以下依赖(版本可根据最新稳定版调整):dependencies: flutter: sdk: flutter # MQTT通信(核心,机器人指令/状态传输) mqtt_client: ^10.2.0 # 状态管理(机器人状态统一管理) provider: ^6.1.1 # 数据可视化(清扫数据、电量展示) fl_chart: ^0.68.0 # 本地缓存(机器人连接信息、历史记录) shared_preferences: ^2.2.3 # 路径可视化(扫地机器人清扫路径、位置) flutter_map: ^6.1.0 # 网络状态监听(确保设备联网) connectivity_plus: ^6.0.1 # 图标库(扫地机器人相关图标) font_awesome_flutter: ^10.4.0 - 安装三方库:终端执行命令
flutter pub get,等待安装完成(若出现报错,可执行flutter pub upgrade更新依赖)。 - 验证集成:在
main.dart中导入任意一个三方库(如import 'package:provider/provider.dart';),无报错即为集成成功。
3.3 项目基础架构搭建(标准化,便于后续扩展)
创建清晰的目录结构,将功能模块化,避免代码混乱,适配扫地机器人的控制逻辑:
- 在
lib目录下创建以下文件夹:lib/ ├── models/ # 数据模型(扫地机器人模型、状态模型、清扫记录模型) ├── providers/ # 状态管理(机器人状态、连接状态、清扫数据) ├── services/ # 服务层(MQTT通信、本地缓存、网络监听) ├── pages/ # 页面(首页、机器人控制页、路径可视化页、设置页) ├── widgets/ # 自定义组件(机器人状态卡片、模式切换按钮、路径地图) └── main.dart # 项目入口(初始化MQTT、状态管理、路由) - 创建各目录下的基础文件,例如:
models/robot_model.dart:扫地机器人数据模型providers/robot_provider.dart:机器人状态管理services/mqtt_service.dart:MQTT通信服务pages/home_page.dart:项目首页
四、Flutter核心功能开发(含三方库实战,扫地机器人专属)
此环节为项目核心,所有功能均围绕智能扫地机器人的控制需求开发,每一步都有完整代码,可直接复制使用,重点演示三方库的实战用法。
4.1 扫地机器人数据模型定义(models/robot_model.dart)
定义机器人的核心属性,适配后续状态管理和UI展示:
// 扫地机器人数据模型
class SweepingRobot {
final String id; // 机器人唯一ID(用于区分多台设备)
final String name; // 机器人名称(如:客厅扫地机器人)
bool isRunning; // 是否正在清扫(启动/暂停)
String workMode; // 工作模式(auto:自动清扫,point:定点清扫,edge:沿边清扫)
int battery; // 电量(0-100)
double cleanArea; // 已清扫面积(单位:㎡)
int cleanTime; // 已清扫时长(单位:分钟)
bool isFault; // 是否故障
String faultMsg; // 故障信息(如:电量过低、卡住)
List<Map<double, double>> cleanPath; // 清扫路径(坐标集合)
SweepingRobot({
required this.id,
required this.name,
this.isRunning = false,
this.workMode = "auto",
this.battery = 100,
this.cleanArea = 0.0,
this.cleanTime = 0,
this.isFault = false,
this.faultMsg = "",
this.cleanPath = const [],
});
// 复制模型(用于状态更新,避免直接修改原数据)
SweepingRobot copyWith({
String? id,
String? name,
bool? isRunning,
String? workMode,
int? battery,
double? cleanArea,
int? cleanTime,
bool? isFault,
String? faultMsg,
List<Map<double, double>>? cleanPath,
}) {
return SweepingRobot(
id: id ?? this.id,
name: name ?? this.name,
isRunning: isRunning ?? this.isRunning,
workMode: workMode ?? this.workMode,
battery: battery ?? this.battery,
cleanArea: cleanArea ?? this.cleanArea,
cleanTime: cleanTime ?? this.cleanTime,
isFault: isFault ?? this.isFault,
faultMsg: faultMsg ?? this.faultMsg,
cleanPath: cleanPath ?? this.cleanPath,
);
}
}
4.2 MQTT通信服务封装(services/mqtt_service.dart)
基于mqtt_client三方库,封装扫地机器人的通信逻辑,实现连接、指令下发、状态接收,核心代码如下:
import 'package:mqtt_client/mqtt_client.dart';
import 'package:mqtt_client/mqtt_server_client.dart';
// MQTT通信服务(核心,连接Flutter与扫地机器人、鸿蒙设备)
class MQTTService {
// MQTT服务器配置(本地服务器,若远程控制可修改为云服务器地址)
final String server = '127.0.0.1'; // 服务器IP
final int port = 1883; // MQTT默认端口
final String clientId = 'flutter_sweeping_robot_client'; // Flutter端客户端ID(唯一)
late MqttServerClient client; // MQTT客户端实例
// 初始化MQTT连接(在项目启动时调用)
Future<bool> initMQTT() async {
client = MqttServerClient(server, clientId);
client.port = port;
client.keepAlivePeriod = 60; // 心跳周期(60秒)
client.logging(on: true); // 开启日志(调试用)
client.onConnected = _onConnected; // 连接成功回调
client.onDisconnected = _onDisconnected; // 断开连接回调
client.onMessageReceived = _onMessageReceived; // 接收消息回调
try {
await client.connect();
if (client.connectionStatus?.state == MqttConnectionState.connected) {
print('MQTT连接成功(Flutter端)');
// 订阅扫地机器人相关主题(接收机器人状态)
// 主题格式:smart/sweeping_robot/机器人ID/state
client.subscribe('smart/sweeping_robot/1/state', MqttQos.atMostOnce);
return true;
} else {
print('MQTT连接失败:${client.connectionStatus?.state}');
client.disconnect();
return false;
}
} catch (e) {
print('MQTT连接异常:$e');
client.disconnect();
return false;
}
}
// 连接成功回调
void _onConnected() {
print('MQTT已成功连接到服务器');
}
// 断开连接回调
void _onDisconnected() {
print('MQTT已断开连接,尝试重连...');
initMQTT(); // 自动重连
}
// 接收消息回调(接收扫地机器人状态、鸿蒙设备指令)
void _onMessageReceived(MqttMessage message) {
final payload = MqttPublishMessage.fromMessage(message);
final messageContent = String.fromCharCodes(payload.payload.message!);
print('收到MQTT消息:$messageContent');
// 后续会结合状态管理,解析消息并更新机器人状态
}
// 下发控制指令(控制扫地机器人)
// 指令格式:{"cmd": "start", "mode": "auto"}(start/stop/change_mode等)
void publishControlCmd(String robotId, Map<String, dynamic> cmd) {
if (client.connectionStatus?.state != MqttConnectionState.connected) {
print('MQTT未连接,无法下发指令');
return;
}
final topic = 'smart/sweeping_robot/$robotId/control'; // 控制主题
final cmdString = cmd.toString(); // 指令转为字符串
final builder = MqttClientPayloadBuilder();
builder.addString(cmdString);
// 发布指令
client.publishMessage(
topic,
MqttQos.atMostOnce,
builder.payload!,
);
print('下发指令:$cmdString,主题:$topic');
}
// 断开MQTT连接
void disconnectMQTT() {
client.disconnect();
print('MQTT已主动断开连接');
}
}
功能说明:通过mqtt_client三方库,实现Flutter端与MQTT服务器的稳定连接,支持下发控制指令(启动、暂停、切换模式),接收扫地机器人的实时状态(电量、清扫进度、故障),同时支持与鸿蒙端互通。
4.3 机器人状态管理(providers/robot_provider.dart)
基于provider三方库,实现全局机器人状态管理,统一处理状态更新、指令下发,核心代码如下:
import 'package:flutter/material.dart';
import '../models/robot_model.dart';
import '../services/mqtt_service.dart';
// 扫地机器人状态管理(全局可访问)
class RobotProvider with ChangeNotifier {
final MQTTService _mqttService = MQTTService(); // MQTT服务实例
late SweepingRobot _robot; // 当前控制的扫地机器人
bool _isMqttConnected = false; // MQTT连接状态
// 初始化(项目启动时调用)
Future<void> init() async {
// 初始化机器人(默认数据,后续会从本地缓存/机器人接收真实数据)
_robot = SweepingRobot(
id: '1',
name: '客厅扫地机器人',
);
// 初始化MQTT连接
_isMqttConnected = await _mqttService.initMQTT();
// 监听MQTT消息,更新机器人状态
_mqttService.client.onMessageReceived = _updateRobotState;
notifyListeners();
}
// 从MQTT消息中更新机器人状态
void _updateRobotState(MqttMessage message) {
final payload = MqttPublishMessage.fromMessage(message);
final messageContent = String.fromCharCodes(payload.payload.message!);
// 解析消息(假设消息格式为JSON字符串)
// 示例消息:{"isRunning":true,"workMode":"auto","battery":80,"cleanArea":5.2,"cleanTime":10}
try {
// 实际开发中可使用json.decode解析,此处简化演示
final stateMap = _parseMessage(messageContent);
_robot = _robot.copyWith(
isRunning: stateMap['isRunning'] ?? false,
workMode: stateMap['workMode'] ?? 'auto',
battery: stateMap['battery'] ?? 100,
cleanArea: stateMap['cleanArea'] ?? 0.0,
cleanTime: stateMap['cleanTime'] ?? 0,
isFault: stateMap['isFault'] ?? false,
faultMsg: stateMap['faultMsg'] ?? '',
cleanPath: stateMap['cleanPath'] ?? [],
);
notifyListeners(); // 通知UI更新
} catch (e) {
print('解析机器人状态失败:$e');
}
}
// 简化消息解析(实际使用json.decode)
Map<String, dynamic> _parseMessage(String message) {
// 此处仅为演示,实际开发中替换为JSON解析
if (message.contains('isRunning')) {
return {
'isRunning': message.contains('true'),
'workMode': message.contains('auto') ? 'auto' : 'point',
'battery': 80,
'cleanArea': 5.2,
'cleanTime': 10,
};
}
return {};
}
// 控制机器人启动/暂停
void toggleRobotRunning() {
final cmd = {
'cmd': _robot.isRunning ? 'stop' : 'start',
'mode': _robot.workMode,
};
_mqttService.publishControlCmd(_robot.id, cmd);
// 本地临时更新状态(后续会被机器人真实状态覆盖)
_robot = _robot.copyWith(isRunning: !_robot.isRunning);
notifyListeners();
}
// 切换机器人工作模式
void changeWorkMode(String mode) {
final cmd = {
'cmd': 'change_mode',
'mode': mode,
};
_mqttService.publishControlCmd(_robot.id, cmd);
_robot = _robot.copyWith(workMode: mode);
notifyListeners();
}
// 定点清扫(传入定点坐标)
void pointClean(double x, double y) {
final cmd = {
'cmd': 'point_clean',
'x': x,
'y': y,
};
_mqttService.publishControlCmd(_robot.id, cmd);
_robot = _robot.copyWith(workMode: 'point');
notifyListeners();
}
// Getter方法(供UI获取状态)
SweepingRobot get robot => _robot;
bool get isMqttConnected => _isMqttConnected;
}
功能说明:通过provider三方库,实现全局机器人状态的统一管理,UI页面可通过Provider.of<RobotProvider>(context)获取机器人状态、调用控制方法,无需手动传值,实现状态与UI的同步更新。
4.4 清扫路径可视化(widgets/clean_path_map.dart)
基于flutter_map三方库,实现扫地机器人清扫路径、实时位置的可视化,核心代码如下:
import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart';
import '../providers/robot_provider.dart';
import 'package:provider/provider.dart';
// 清扫路径可视化组件
class CleanPathMap extends StatelessWidget {
const CleanPathMap({super.key});
Widget build(BuildContext context) {
final robotProvider = Provider.of<RobotProvider>(context);
final robot = robotProvider.robot;
// 路径坐标转换(模拟,实际可根据机器人真实坐标调整)
List<LatLng> pathPoints = robot.cleanPath.map((point) {
return LatLng(point.keys.first, point.values.first);
}).toList();
return Container(
height: 300,
width: double.infinity,
margin: const EdgeInsets.all(16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
border: Border.all(color: Colors.grey[300]!),
),
child: FlutterMap(
options: MapOptions(
center: pathPoints.isNotEmpty ? pathPoints.first : LatLng(30.0, 120.0),
zoom: 18.0,
),
children: [
// 地图瓦片(使用开源瓦片服务)
TileLayer(
urlTemplate: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
subdomains: const ['a', 'b', 'c'],
),
// 清扫路径
PolylineLayer(
polylines: [
Polyline(
points: pathPoints,
strokeWidth: 3.0,
color: Colors.blue,
),
],
),
// 机器人实时位置
MarkerLayer(
markers: [
Marker(
point: pathPoints.isNotEmpty ? pathPoints.last : LatLng(30.0, 120.0),
width: 40,
height: 40,
child: const Icon(
Icons.room_cleaner,
color: Colors.red,
size: 32,
),
),
],
),
],
),
);
}
}
4.5 主页面开发(pages/home_page.dart)
整合所有核心功能,实现扫地机器人的控制界面,包含状态显示、模式切换、路径可视化等,核心代码如下:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../providers/robot_provider.dart';
import '../widgets/clean_path_map.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
class HomePage extends StatelessWidget {
const HomePage({super.key});
Widget build(BuildContext context) {
final robotProvider = Provider.of<RobotProvider>(context);
final robot = robotProvider.robot;
final isConnected = robotProvider.isMqttConnected;
return Scaffold(
appBar: AppBar(
title: const Text('智能扫地机器人控制'),
centerTitle: true,
backgroundColor: Colors.blue,
actions: [
IconButton(
icon: const Icon(Icons.settings),
onPressed: () {
// 跳转设置页面(后续实现)
},
),
],
),
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// 连接状态提示
Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(vertical: 8),
color: isConnected ? Colors.green[100] : Colors.red[100],
child: Text(
isConnected ? '已连接扫地机器人' : '未连接机器人,请检查网络',
textAlign: TextAlign.center,
style: TextStyle(
color: isConnected ? Colors.green : Colors.red,
),
),
),
// 机器人状态卡片
Container(
margin: const EdgeInsets.all(16),
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
boxShadow: [
BoxShadow(
color: Colors.grey[200]!,
blurRadius: 5,
offset: const Offset(0, 2),
),
],
color: Colors.white,
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
robot.name,
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 16),
// 电量显示
Row(
children: [
const FaIcon(FontAwesomeIcons.batteryFull, color: Colors.green),
const SizedBox(width: 8),
Text('电量:${robot.battery}%'),
],
),
const SizedBox(height: 8),
// 工作状态
Row(
children: [
FaIcon(
robot.isRunning ? FontAwesomeIcons.play : FontAwesomeIcons.pause,
color: robot.isRunning ? Colors.blue : Colors.grey,
),
const SizedBox(width: 8),
Text(robot.isRunning ? '正在清扫' : '已暂停'),
],
),
const SizedBox(height: 8),
// 工作模式
Row(
children: [
const FaIcon(FontAwesomeIcons.gears, color: Colors.orange),
const SizedBox(width: 8),
Text('工作模式:${_getModeText(robot.workMode)}'),
],
),
const SizedBox(height: 8),
// 清扫数据
Row(
children: [
const FaIcon(FontAwesomeIcons.chartArea, color: Colors.purple),
const SizedBox(width: 8),
Text('已清扫:${robot.cleanArea}㎡ / ${robot.cleanTime}分钟'),
],
),
// 故障提示
if (robot.isFault)
Padding(
padding: const EdgeInsets.only(top: 8),
child: Row(
children: [
const FaIcon(FontAwesomeIcons.triangleExclamation, color: Colors.red),
const SizedBox(width: 8),
Text(robot.faultMsg, style: const TextStyle(color: Colors.red)),
],
),
),
],
),
),
// 控制按钮
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// 启动/暂停按钮
ElevatedButton(
onPressed: isConnected ? () => robotProvider.toggleRobotRunning() : null,
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 12),
backgroundColor: robot.isRunning ? Colors.red : Colors.blue,
),
child: Text(robot.isRunning ? '暂停清扫' : '启动清扫'),
),
const SizedBox(width: 16),
// 模式切换按钮
DropdownButton<String>(
value: robot.workMode,
onChanged: isConnected
? (value) {
if (value != null) {
robotProvider.changeWorkMode(value);
}
}
: null,
items: const [
DropdownMenuItem(value: 'auto', child: Text('自动清扫')),
DropdownMenuItem(value: 'point', child: Text('定点清扫')),
DropdownMenuItem(value: 'edge', child: Text('沿边清扫')),
],
),
],
),
// 清扫路径可视化
const CleanPathMap(),
// 清扫数据图表(fl_chart三方库)
Container(
margin: const EdgeInsets.all(16),
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
color: Colors.white,
boxShadow: [
BoxShadow(
color: Colors.grey[200]!,
blurRadius: 5,
offset: const Offset(0, 2),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'清扫数据统计',
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
),
const SizedBox(height: 16),
// 电量变化折线图
SizedBox(
height: 200,
child: LineChart(
LineChartData(
gridData: const FlGridData(show: true),
titlesData: const FlTitlesData(show: true),
borderData: const FlBorderData(show: true),
lineBarsData: [
LineChartBarData(
spots: const [
FlSpot(0, 100),
FlSpot(1, 90),
FlSpot(2, 80),
FlSpot(3, 75),
FlSpot(4, 70),
],
isCurved: true,
color: Colors.green,
title: '电量变化',
),
],
),
),
),
],
),
),
],
),
),
);
}
// 转换工作模式文本
String _getModeText(String mode) {
switch (mode) {
case 'auto':
return '自动清扫';
case 'point':
return '定点清扫';
case 'edge':
return '沿边清扫';
default:
return '自动清扫';
}
}
}
4.6 项目入口配置(main.dart)
初始化状态管理、MQTT服务,配置路由,核心代码如下:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'providers/robot_provider.dart';
import 'pages/home_page.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => RobotProvider()..init(), // 初始化状态管理和MQTT
child: MaterialApp(
title: '智能扫地机器人控制',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const HomePage(),
debugShowCheckedModeBanner: false,
),
);
}
}
五、鸿蒙开发:鸿蒙设备控制端实现(适配扫地机器人)
本环节实现鸿蒙设备(手机、智慧屏)对扫地机器人的控制,采用HarmonyOS NEXT Stage模型,与Flutter端共用MQTT服务器,实现指令互通、状态同步,步骤详细可落地。
5.1 创建鸿蒙扫地机器人控制项目
- 打开DevEco Studio,点击「Create Project」,选择「Empty Ability」,点击「Next」。
- 配置项目信息:
- Project Name:
smart_sweeping_robot_harmony(自定义)。 - Bundle Name:
com.example.smartsweepingrobot(自定义,需唯一)。 - Save Location:选择项目保存路径。
- Compile SDK:选择API 11(HarmonyOS NEXT)。
- Model:选择「Stage」(最新模型,推荐)。
- Project Name:
- 点击「Finish」,等待项目初始化完成(首次初始化可能需要下载依赖,耐心等待)。
- 清理默认代码:删除
pages/index.ets中的默认Widget,保留基础结构。
5.2 鸿蒙MQTT通信集成(核心,与Flutter端互通)
- 导入MQTT依赖:将提前下载的
@ohos/mqtt依赖包复制到项目的node_modules目录下,或在oh-package.json5中添加依赖:
然后在终端执行"dependencies": { "@ohos/mqtt": "^1.0.0" }npm install,安装依赖。 - 创建MQTT服务工具类:在
utils目录下创建mqttService.ets,封装鸿蒙端MQTT通信逻辑,核心代码如下:import mqtt from '@ohos/mqtt'; // 鸿蒙端MQTT服务(与Flutter端共用服务器,控制扫地机器人) export class MqttService { private client: mqtt.MqttClient | null = null; private server = 'tcp://127.0.0.1:1883'; // MQTT服务器地址(与Flutter端一致) private clientId = 'harmony_sweeping_robot_client'; // 鸿蒙端客户端ID(唯一) private robotId = '1'; // 扫地机器人ID(与Flutter端一致) private controlTopic = `smart/sweeping_robot/${this.robotId}/control`; // 控制主题 private stateTopic = `smart/sweeping_robot/${this.robotId}/state`; // 状态主题 // 初始化MQTT连接 async initMqtt(): Promise<boolean> { try { this.client = mqtt.connect(this.server, { clientId: this.clientId, keepalive: 60, clean: true, }); // 连接成功回调 this.client.on('connect', () => { console.log('鸿蒙端MQTT连接成功'); // 订阅机器人状态主题 this.client?.subscribe(this.stateTopic, { qos: 0 }); }); // 接收消息回调(接收机器人状态) this.client.on('message', (topic: string, payload: Buffer) => { const message = payload.toString(); console.log(`鸿蒙端收到消息:${message}`); // 后续更新UI状态 }); // 断开连接回调 this.client.on('close', () => { console.log('鸿蒙端MQTT断开连接,尝试重连'); this.initMqtt(); }); return true; } catch (e) { console.log(`鸿蒙端MQTT连接失败:${e}`); return false; } } // 下发控制指令(与Flutter端指令格式一致) publishControlCmd(cmd: Record<string, any>): void { if (!this.client || !this.client.connected) { console.log('MQTT未连接,无法下发指令'); return; } const cmdString = JSON.stringify(cmd); this.client.publish(this.controlTopic, cmdString, { qos: 0 }); console.log(`鸿蒙端下发指令:${cmdString}`); } // 断开MQTT连接 disconnectMqtt(): void { this.client?.end(); console.log('鸿蒙端MQTT已断开连接'); } }
5.3 鸿蒙控制界面开发(适配扫地机器人)
开发鸿蒙端控制界面,实现与Flutter端一致的功能:启动/暂停、模式切换、状态显示,核心代码(pages/index.ets)如下:
import { MqttService } from '../utils/mqttService';
import router from '@ohos.router';
@Entry
@Component
struct SweepingRobotControlPage {
// 状态管理
@State isConnected: boolean = false;
@State isRunning: boolean = false;
@State workMode: string = 'auto'; // auto/point/edge
@State battery: number = 100;
@State cleanArea: number = 0.0;
@State cleanTime: number = 0;
private mqttService: MqttService = new MqttService();
// 页面初始化时调用
aboutToAppear() {
this.initMqtt();
}
// 初始化MQTT
async initMqtt() {
this.isConnected = await this.mqttService.initMqtt();
// 监听机器人状态(简化演示,实际解析MQTT消息更新状态)
this.mqttService.client?.on('message', (topic: string, payload: Buffer) => {
const state = JSON.parse(payload.toString());
this.isRunning = state.isRunning ?? false;
this.workMode = state.workMode ?? 'auto';
this.battery = state.battery ?? 100;
this.cleanArea = state.cleanArea ?? 0.0;
this.cleanTime = state.cleanTime ?? 0;
});
}
// 启动/暂停清扫
toggleRunning() {
const cmd = {
cmd: this.isRunning ? 'stop' : 'start',
mode: this.workMode
};
this.mqttService.publishControlCmd(cmd);
this.isRunning = !this.isRunning;
}
// 切换工作模式
changeMode(mode: string) {
const cmd = {
cmd: 'change_mode',
mode: mode
};
this.mqttService.publishControlCmd(cmd);
this.workMode = mode;
}
build() {
Column() {
// 顶部导航栏
Text('智能扫地机器人控制')
.fontSize(30)
.fontWeight(FontWeight.Bold)
.margin({ top: 30, bottom: 20 })
.textAlign(TextAlign.Center);
// 连接状态提示
Text(this.isConnected ? '已连接机器人' : '未连接,请检查网络')
.fontSize(16)
.color(this.isConnected ? Color.Green : Color.Red)
.margin({ bottom: 20 })
.textAlign(TextAlign.Center);
// 状态卡片
Column() {
Text(`设备名称:客厅扫地机器人`)
.fontSize(18)
.margin({ bottom: 10 });
Text(`电量:${this.battery}%`)
.fontSize(18)
.margin({ bottom: 10 });
Text(`状态:${this.isRunning ? '正在清扫' : '已暂停'}`)
.fontSize(18)
.margin({ bottom: 10 });
Text(`模式:${this.getModeText()}`)
.fontSize(18)
.margin({ bottom: 10 });
Text(`已清扫:${this.cleanArea}㎡ / ${this.cleanTime}分钟`)
.fontSize(18);
}
.padding(20)
.backgroundColor(Color.White)
.borderRadius(12)
.shadow({ radius: 5, color: Color.Grey[200]!, offset: { x: 0, y: 2 } })
.margin({ bottom: 20 })
.width('90%');
// 控制按钮
Row() {
Button(this.isRunning ? '暂停清扫' : '启动清扫')
.width(150)
.height(50)
.backgroundColor(this.isRunning ? Color.Red : Color.Blue)
.fontSize(18)
.onClick(() => this.toggleRunning())
.enabled(this.isConnected);
Button('切换模式')
.width(150)
.height(50)
.backgroundColor(Color.Orange)
.fontSize(18)
.margin({ left: 20 })
.onClick(() => this.showModeDialog())
.enabled(this.isConnected);
}
.justifyContent(FlexAlign.Center)
}
.width('100%')
.height('100%')
.backgroundColor(Color.Grey[100]);
}
// 转换模式文本
getModeText(): string {
switch (this.workMode) {
case 'auto':
return '自动清扫';
case 'point':
return '定点清扫';
case 'edge':
return '沿边清扫';
default:
return '自动清扫';
}
}
// 模式选择弹窗
showModeDialog() {
AlertDialog.show({
title: '选择工作模式',
message: '',
actions: [
{
text: '自动清扫',
onClick: () => {
this.changeMode('auto');
AlertDialog.close();
}
},
{
text: '定点清扫',
onClick: () => {
this.changeMode('point');
AlertDialog.close();
}
},
{
text: '沿边清扫',
onClick: () => {
this.changeMode('edge');
AlertDialog.close();
}
}
]
});
}
}
5.4 Flutter与鸿蒙设备互通(关键步骤)
确保Flutter端、鸿蒙端、扫地机器人(或模拟设备)连接同一MQTT服务器,实现双向通信,步骤如下:
- 确认所有设备在同一局域网(WiFi),MQTT服务器地址统一为
127.0.0.1:1883(若为远程控制,替换为云服务器地址)。 - 统一通信主题:
- 控制主题:
smart/sweeping_robot/1/control(Flutter端、鸿蒙端均向此主题下发指令)。 - 状态主题:
smart/sweeping_robot/1/state(扫地机器人向此主题发送状态,Flutter端、鸿蒙端订阅此主题)。
- 控制主题:
- 测试互通:
- Flutter端点击「启动清扫」,下发指令 → MQTT服务器 → 扫地机器人(或模拟设备)执行,同时向状态主题发送「正在清扫」状态 → Flutter端、鸿蒙端同步更新UI。
- 鸿蒙端切换「沿边清扫」模式,下发指令 → 扫地机器人执行 → Flutter端UI同步更新模式。
六、完整项目联调测试(必做,确保功能可用)
联调测试分为「无实物模拟测试」和「实物机器人测试」,新手可先进行模拟测试,熟悉流程后再接入真实设备。
6.1 无实物模拟测试(推荐新手)
- 启动MQTT服务器:打开EMQ X服务器,确保状态为「运行中」,通过MQTTX工具连接服务器(地址
127.0.0.1:1883)。 - 运行Flutter项目:
- 打开Android Studio或VS Code,启动Android模拟器(或连接真机)。
- 执行命令
flutter run,启动Flutter应用,验证MQTT连接状态、控制功能、路径可视化、数据图表是否正常。
- 运行鸿蒙项目:
- 打开DevEco Studio,启动鸿蒙模拟器(或连接鸿蒙真机)。
- 点击「Run」按钮,启动鸿蒙应用,验证MQTT连接、控制功能是否正常。
- 双向通信测试:
- 在Flutter端点击「启动清扫」,查看鸿蒙端UI是否同步更新为「正在清扫」。
- 在鸿蒙端切换「定点清扫」模式,查看Flutter端UI是否同步更新模式。
- 通过MQTTX向状态主题发送模拟状态消息(如
{"isRunning":true,"battery":70}),验证两端UI是否同步更新。
6.2 实物机器人测试(进阶)
- 准备真实扫地机器人:选择支持MQTT协议的扫地机器人(如小米、科沃斯部分型号),或使用ESP32开发板+电机模块搭建简易扫地机器人。
- 配置机器人MQTT:将机器人的MQTT服务器地址、端口、主题配置为与Flutter端、鸿蒙端一致。
- 连接机器人:确保机器人与Flutter端、鸿蒙端在同一局域网,启动机器人,验证MQTT连接。
- 功能测试:
- 远程控制机器人启动/暂停、切换模式,验证机器人是否正常响应。
- 查看机器人实时状态(电量、清扫进度、路径),验证两端UI是否同步更新。
- 测试故障报警:模拟机器人卡住、电量过低,验证两端是否弹出故障提示。
七、项目打包与部署(实战收尾)
7.1 Flutter项目打包
- Android打包:
- 终端执行命令
flutter build apk,生成APK文件(路径:build/app/outputs/flutter-apk/app-release.apk)。 - (可选)生成App Bundle:
flutter build appbundle,用于上传Google Play。
- 终端执行命令
- iOS打包(Mac环境):
- 终端执行命令
flutter build ios,生成iOS安装包,通过Xcode上传至App Store。
- 终端执行命令
- Windows/macOS打包:
- Windows:
flutter build windows,生成exe安装包。 - macOS:
flutter build macos,生成dmg安装包。
- Windows:
7.2 鸿蒙项目打包
- 打开DevEco Studio,点击「Build」→「Build Hap(s)/APP(s)」→「Build Hap(s)」。
- 等待打包完成,生成HAP文件(路径:
build/outputs/hap/debug)。 - (可选)生成APP包:点击「Build APP(s)」,用于上传鸿蒙应用市场。
7.3 MQTT服务器部署(远程控制)
- 选择云服务器(如阿里云、腾讯云),安装EMQ X服务器。
- 配置服务器安全组,开放1883(MQTT)、18083(EMQ X控制台)端口。
- 修改Flutter端、鸿蒙端、机器人的MQTT服务器地址为云服务器公网IP,实现远程控制。
八、项目扩展与优化(进阶方向)
- 多设备管理:扩展支持多台扫地机器人,通过ID区分,实现批量控制。
- 语音控制:集成
speech_to_text三方库,实现语音指令控制(如「启动清扫」「切换模式」)。 - 定时任务:添加定时清扫功能,支持设置清扫时间、重复周期。
- 数据统计:完善清扫数据统计,生成周/月清扫报告,支持数据导出。
- 鸿蒙分布式能力:利用鸿蒙分布式技术,实现跨设备协同控制(如手机控制、智慧屏显示)。
- 安全性优化:添加MQTT用户名/密码认证,加密通信数据,防止指令被篡改。
九、常见问题与解决方案
- MQTT连接失败:
- 检查服务器地址、端口是否正确,确保所有设备在同一局域网。
- 关闭防火墙/杀毒软件,或开放1883端口。
- 验证EMQ X服务器是否正常运行,通过
http://127.0.0.1:18083查看状态。
- Flutter三方库安装报错:
- 执行
flutter pub upgrade更新依赖版本。 - 清理缓存:
flutter clean,然后重新执行flutter pub get。
- 执行
- 鸿蒙MQTT依赖导入失败:
- 确认
@ohos/mqtt依赖包版本与API 11兼容。 - 执行
npm install重新安装依赖,或手动复制依赖包到node_modules目录。
- 确认
- 路径可视化不显示:
- 检查
flutter_map依赖是否正确导入,确保网络正常(加载地图瓦片需要联网)。 - 验证路径坐标格式是否正确,
LatLng类导入是否正确。
- 检查
本项目完整覆盖Flutter+三方库+鸿蒙开发全栈技术,从环境搭建到功能开发、联调测试、打包部署,提供了可直接复刻的详细步骤,适合零基础开发者学习物联网跨平台开发。通过本项目,可掌握Flutter跨平台开发、三方库实战、鸿蒙开发、MQTT通信等核心技能,为后续智能家居、物联网项目开发打下坚实基础。
需要我帮你把这份文档整理成可直接复制的完整项目代码包(含Flutter与鸿蒙双端完整源码、依赖配置、MQTT调试脚本)吗?
更多推荐

所有评论(0)