欢迎光临
我们一直在努力

【HarmonyOS】鸿蒙Flutter智能家居应用开发实战指南

鸿蒙Flutter智能家居应用开发实战指南

在这里插入图片描述

概述

智能家居是鸿蒙全场景生态的重要应用场景。本文讲解如何基于鸿蒙Flutter框架,开发一套完整的智能家居应用,实现设备发现、控制、场景联动、语音交互等核心功能。

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

系统架构设计

整体架构图

┌────────────────────────────────────────────────────────────┐
│ 用户交互层 (Flutter) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 设备控制面板 │ │ 场景编排 │ │ 语音交互 │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└───────────────────────┬────────────────────────────────────┘
│ RPC/事件总线
┌───────────────────────┴────────────────────────────────────┐
│ 智能家庭业务逻辑层 (Dart) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ 设备管理器 │ │ 场景引擎 │ │ 自动化规则 │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└───────────────────────┬────────────────────────────────────┘
│ 分布式软总线
┌───────────────────────┴────────────────────────────────────┐
│ 鸿蒙IoT服务层 (ArkTS) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ 设备发现 │ │ 协议适配 │ │ 分布式联动 │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└───────────────────────┬────────────────────────────────────┘
│ HiLink/WiFi/蓝牙
┌───────────────────────┴────────────────────────────────────┐
│ 智能设备层 │
│ 灯光 · 窗帘 · 空调 · 传感器 · 门锁 · 音响 · … │
└────────────────────────────────────────────────────────────┘

核心组件设计

组件技术方案职责
设备模型 抽象基类 + 具体实现 统一设备抽象
控制协议 统一命令格式 跨设备控制
状态同步 分布式数据对象 实时状态更新
场景引擎 规则匹配系统 自动化场景
语音交互 AI意图识别 自然语言控制

设备模型设计

基础设备抽象

/// 设备类型枚举
enum SmartDeviceType {
light('智能灯光', Icons.lightbulb),
curtain('智能窗帘', Icons.curtains),
ac('空调', Icons.ac_unit),
sensor('传感器', Icons.sensors),
lock('门锁', Icons.lock),
speaker('智能音箱', Icons.speaker),
camera('摄像头', Icons.videocam),
switch('智能开关', Icons.toggle_on),
thermostat('温控器', Icons.thermostat),
purifier('净化器', Icons.air);

final String displayName;
final IconData icon;
const SmartDeviceType(this.displayName, this.icon);
}

/// 设备状态基类
abstract class DeviceState {
Map<String, dynamic> toJson();
static DeviceState fromJson(Map<String, dynamic> json) {
final type = json['type'] as String;
switch (type) {
case 'light':
return LightState.fromJson(json);
case 'curtain':
return CurtainState.fromJson(json);
case 'ac':
return ACState.fromJson(json);
case 'sensor':
return SensorState.fromJson(json);
default:
throw ArgumentError('Unknown device type: $type');
}
}
}

/// 智能设备基类
abstract class SmartDevice {
final String deviceId;
final String deviceName;
final SmartDeviceType type;
final String roomId;
final bool isOnline;
final DateTime lastSeen;

const SmartDevice({
required this.deviceId,
required this.deviceName,
required this.type,
required this.roomId,
this.isOnline = true,
DateTime? lastSeen,
}) : lastSeen = lastSeen ?? const Duration();

/// 获取当前状态
DeviceState get currentState;

/// 执行控制命令
Future<bool> executeCommand(DeviceCommand command);

/// 订阅状态变化
Stream<DeviceState> get stateStream;

/// 工厂构造方法
static SmartDevice fromJson(Map<String, dynamic> json) {
final type = SmartDeviceType.values.firstWhere(
(e) => e.name == json['type'],
orElse: () => SmartDeviceType.switch,
);

switch (type) {
case SmartDeviceType.light:
return SmartLight.fromJson(json);
case SmartDeviceType.curtain:
return SmartCurtain.fromJson(json);
case SmartDeviceType.ac:
return SmartAC.fromJson(json);
case SmartDeviceType.sensor:
return SmartSensor.fromJson(json);
default:
return SmartSwitch.fromJson(json);
}
}

Map<String, dynamic> toJson();
}

/// 设备命令基类
abstract class DeviceCommand {
final String deviceId;
final DateTime timestamp;

DeviceCommand({required this.deviceId})
: timestamp = DateTime.now();

Map<String, dynamic> toJson();
}

/// 设备事件
class DeviceEvent {
final String deviceId;
final SmartDeviceType type;
final String eventType;
final Map<String, dynamic> data;
final DateTime timestamp;

DeviceEvent({
required this.deviceId,
required this.type,
required this.eventType,
required this.data,
}) : timestamp = DateTime.now();
}

具体设备实现

/// 灯光状态
()
class LightState extends DeviceState {
final bool isOn;
final int brightness; // 0-100
final int colorTemp; // 色温 2700-6500K
final int? hue; // 色相 0-360
final int? saturation; // 饱和度 0-100

const LightState({
this.isOn = false,
this.brightness = 100,
this.colorTemp = 4000,
this.hue,
this.saturation,
});


Map<String, dynamic> toJson() => _$LightStateToJson(this);

factory LightState.fromJson(Map<String, dynamic> json) =>
_$LightStateFromJson(json);

LightState copyWith({
bool? isOn,
int? brightness,
int? colorTemp,
int? hue,
int? saturation,
}) {
return LightState(
isOn: isOn ?? this.isOn,
brightness: brightness ?? this.brightness,
colorTemp: colorTemp ?? this.colorTemp,
hue: hue ?? this.hue,
saturation: saturation ?? this.saturation,
);
}
}

/// 灯光控制命令
class LightCommand extends DeviceCommand {
final bool? isOn;
final int? brightness;
final int? colorTemp;
final int? hue;
final int? saturation;

LightCommand({
required super.deviceId,
this.isOn,
this.brightness,
this.colorTemp,
this.hue,
this.saturation,
});


Map<String, dynamic> toJson() => {
'deviceId': deviceId,
'command': 'light_control',
'params': {
'isOn': isOn,
'brightness': brightness,
'colorTemp': colorTemp,
'hue': hue,
'saturation': saturation,
},
'timestamp': timestamp.toIso8601String(),
};
}

/// 智能灯光设备
class SmartLight extends SmartDevice {
LightState _state;

SmartLight({
required super.deviceId,
required super.deviceName,
required super.roomId,
LightState? state,
super.isOnline,
}) : _state = state ?? const LightState(),
super(type: SmartDeviceType.light);


LightState get currentState => _state;


Future<bool> executeCommand(DeviceCommand command) async {
if (command is! LightCommand) return false;
if (!isOnline) return false;

try {
// 通过鸿蒙分布式能力发送命令
final result = await HarmonyIotChannel.sendDeviceCommand(command.toJson());

if (result) {
// 更新本地状态
_state = _state.copyWith(
isOn: command.isOn,
brightness: command.brightness,
colorTemp: command.colorTemp,
hue: command.hue,
saturation: command.saturation,
);
return true;
}

return false;
} catch (e) {
debugPrint('灯光控制失败: $e');
return false;
}
}


Stream<LightState> get stateStream {
return HarmonyIotChannel.deviceStateStream
.where((event) => event.deviceId == deviceId)
.map((event) => LightState.fromJson(event.data));
}


Map<String, dynamic> toJson() => {
'deviceId': deviceId,
'deviceName': deviceName,
'type': type.name,
'roomId': roomId,
'isOnline': isOnline,
'lastSeen': lastSeen.toIso8601String(),
'state': _state.toJson(),
};

factory SmartLight.fromJson(Map<String, dynamic> json) {
return SmartLight(
deviceId: json['deviceId'] as String,
deviceName: json['deviceName'] as String,
roomId: json['roomId'] as String,
state: json['state'] != null
? LightState.fromJson(json['state'] as Map<String, dynamic>)
: null,
isOnline: json['isOnline'] as bool? ?? true,
);
}
}

/// 空调状态
()
class ACState extends DeviceState {
final bool isOn;
final int temperature; // 16-30
final String mode; // cool, heat, auto, dry, fan
final int fanSpeed; // 1-3
final bool swing;

const ACState({
this.isOn = false,
this.temperature = 26,
this.mode = 'cool',
this.fanSpeed = 2,
this.swing = false,
});


Map<String, dynamic> toJson() => _$ACStateToJson(this);

factory ACState.fromJson(Map<String, dynamic> json) =>
_$ACStateFromJson(json);

ACState copyWith({
bool? isOn,
int? temperature,
String? mode,
int? fanSpeed,
bool? swing,
}) {
return ACState(
isOn: isOn ?? this.isOn,
temperature: temperature ?? this.temperature,
mode: mode ?? this.mode,
fanSpeed: fanSpeed ?? this.fanSpeed,
swing: swing ?? this.swing,
);
}
}

/// 智能空调设备
class SmartAC extends SmartDevice {
ACState _state;

SmartAC({
required super.deviceId,
required super.deviceName,
required super.roomId,
ACState? state,
super.isOnline,
}) : _state = state ?? const ACState(),
super(type: SmartDeviceType.ac);


ACState get currentState => _state;


Future<bool> executeCommand(DeviceCommand command) async {
if (command is! ACCommand) return false;

_state = _state.copyWith(
isOn: command.isOn,
temperature: command.temperature,
mode: command.mode,
fanSpeed: command.fanSpeed,
swing: command.swing,
);

return await HarmonyIotChannel.sendDeviceCommand(command.toJson());
}


Stream<ACState> get stateStream {
return HarmonyIotChannel.deviceStateStream
.where((event) => event.deviceId == deviceId)
.map((event) => ACState.fromJson(event.data));
}


Map<String, dynamic> toJson() => {
'deviceId': deviceId,
'deviceName': deviceName,
'type': type.name,
'roomId': roomId,
'isOnline': isOnline,
'state': _state.toJson(),
};
}

/// 空调控制命令
class ACCommand extends DeviceCommand {
final bool? isOn;
final int? temperature;
final String? mode;
final int? fanSpeed;
final bool? swing;

ACCommand({
required super.deviceId,
this.isOn,
this.temperature,
this.mode,
this.fanSpeed,
this.swing,
});


Map<String, dynamic> toJson() => {
'deviceId': deviceId,
'command': 'ac_control',
'params': {
'isOn': isOn,
'temperature': temperature,
'mode': mode,
'fanSpeed': fanSpeed,
'swing': swing,
},
'timestamp': timestamp.toIso8601String(),
};
}

设备管理系统

设备管理器实现

/// 智能设备管理器
class SmartDeviceManager {
static final SmartDeviceManager _instance =
SmartDeviceManager._internal();
factory SmartDeviceManager() => _instance;
SmartDeviceManager._internal();

final Map<String, SmartDevice> _devices = {};
final Map<String, List<SmartDevice>> _roomDevices = {};
final StreamController<DeviceEvent> _eventController =
StreamController.broadcast();

/// 设备列表
List<SmartDevice> get devices => _devices.values.toList();

/// 设备事件流
Stream<DeviceEvent> get eventStream => _eventController.stream;

/// 初始化
Future<void> initialize() async {
// 订阅鸿蒙设备状态变化
HarmonyIotChannel.deviceStateStream.listen((event) {
_handleDeviceStateChange(event);
});

// 发现设备
await discoverDevices();
}

/// 发现设备
Future<void> discoverDevices() async {
try {
final deviceList = await HarmonyIotChannel.discoverDevices();

for (final deviceJson in deviceList) {
final device = SmartDevice.fromJson(deviceJson);
_addDevice(device);
}

debugPrint('发现 ${deviceList.length} 个智能设备');
} catch (e) {
debugPrint('设备发现失败: $e');
}
}

/// 添加设备
void _addDevice(SmartDevice device) {
_devices[device.deviceId] = device;

// 按房间分组
_roomDevices.putIfAbsent(device.roomId, () => []);
_roomDevices[device.roomId]!.add(device);

// 订阅设备状态变化
device.stateStream.listen((state) {
_eventController.add(DeviceEvent(
deviceId: device.deviceId,
type: device.type,
eventType: 'state_change',
data: state.toJson(),
));
});
}

/// 获取设备
SmartDevice? getDevice(String deviceId) {
return _devices[deviceId];
}

/// 获取房间设备
List<SmartDevice> getRoomDevices(String roomId) {
return _roomDevices[roomId] ?? [];
}

/// 按类型获取设备
List<SmartDevice> getDevicesByType(SmartDeviceType type) {
return _devices.values.where((d) => d.type == type).toList();
}

/// 控制设备
Future<bool> controlDevice(
String deviceId,
DeviceCommand command,
) async {
final device = _devices[deviceId];
if (device == null) return false;

final success = await device.executeCommand(command);

if (success) {
_eventController.add(DeviceEvent(
deviceId: deviceId,
type: device.type,
eventType: 'command_executed',
data: command.toJson(),
));
}

return success;
}

/// 批量控制
Future<Map<String, bool>> batchControl(
List<String> deviceIds,
DeviceCommand Function(String) commandBuilder,
) async {
final results = <String, bool>{};

await Future.wait(deviceIds.map((deviceId) async {
final command = commandBuilder(deviceId);
results[deviceId] = await controlDevice(deviceId, command);
}));

return results;
}

/// 处理设备状态变化
void _handleDeviceStateChange(DeviceEvent event) {
final device = _devices[event.deviceId];
if (device != null) {
// 更新设备状态
_eventController.add(event);
}
}

/// 释放资源
void dispose() {
_eventController.close();
}
}

房间管理

/// 房间模型
()
class SmartRoom {
final String roomId;
final String roomName;
final String icon;
final List<String> deviceIds;
final int temperature;
final int humidity;
final int brightness;

const SmartRoom({
required this.roomId,
required this.roomName,
this.icon = 'room',
this.deviceIds = const [],
this.temperature = 25,
this.humidity = 60,
this.brightness = 0,
});

/// 获取房间设备
List<SmartDevice> getDevices(SmartDeviceManager manager) {
return deviceIds
.map((id) => manager.getDevice(id))
.whereType<SmartDevice>()
.toList();
}

/// 获取在线设备数量
int getOnlineDeviceCount(SmartDeviceManager manager) {
return getDevices(manager).where((d) => d.isOnline).length;
}

/// 是否有灯光设备
bool hasLightDevices(SmartDeviceManager manager) {
return getDevices(manager).any((d) => d.type == SmartDeviceType.light);
}

SmartRoom copyWith({
String? roomId,
String? roomName,
String? icon,
List<String>? deviceIds,
int? temperature,
int? humidity,
int? brightness,
}) {
return SmartRoom(
roomId: roomId ?? this.roomId,
roomName: roomName ?? this.roomName,
icon: icon ?? this.icon,
deviceIds: deviceIds ?? this.deviceIds,
temperature: temperature ?? this.temperature,
humidity: humidity ?? this.humidity,
brightness: brightness ?? this.brightness,
);
}

Map<String, dynamic> toJson() => _$SmartRoomToJson(this);

factory SmartRoom.fromJson(Map<String, dynamic> json) =>
_$SmartRoomFromJson(json);
}

/// 房间管理器
class RoomManager {
final List<SmartRoom> _rooms = [
const SmartRoom(
roomId: 'living_room',
roomName: '客厅',
icon: 'sofa',
deviceIds: ['light_1', 'ac_1', 'curtain_1'],
),
const SmartRoom(
roomId: 'bedroom',
roomName: '卧室',
icon: 'bed',
deviceIds: ['light_2', 'ac_2', 'curtain_2'],
),
const SmartRoom(
roomId: 'kitchen',
roomName: '厨房',
icon: 'chef',
deviceIds: ['light_3', 'sensor_1'],
),
];

List<SmartRoom> get rooms => List.unmodifiable(_rooms);

SmartRoom? getRoom(String roomId) {
try {
return _rooms.firstWhere((r) => r.roomId == roomId);
} catch (e) {
return null;
}
}

void updateRoomEnvironment({
required String roomId,
int? temperature,
int? humidity,
int? brightness,
}) {
final index = _rooms.indexWhere((r) => r.roomId == roomId);
if (index >= 0) {
_rooms[index] = _rooms[index].copyWith(
temperature: temperature,
humidity: humidity,
brightness: brightness,
);
}
}
}

场景自动化

场景引擎

/// 智能场景
()
class SmartScene {
final String sceneId;
final String sceneName;
final String icon;
final List<SceneAction> actions;
final SceneTrigger? trigger;
final bool isEnabled;

const SmartScene({
required this.sceneId,
required this.sceneName,
this.icon = 'scene',
this.actions = const [],
this.trigger,
this.isEnabled = true,
});

/// 执行场景
Future<void> execute(SmartDeviceManager manager) async {
if (!isEnabled) return;

for (final action in actions) {
await action.execute(manager);
}
}

SmartScene copyWith({
String? sceneId,
String? sceneName,
String? icon,
List<SceneAction>? actions,
SceneTrigger? trigger,
bool? isEnabled,
}) {
return SmartScene(
sceneId: sceneId ?? this.sceneId,
sceneName: sceneName ?? this.sceneName,
icon: icon ?? this.icon,
actions: actions ?? this.actions,
trigger: trigger ?? this.trigger,
isEnabled: isEnabled ?? this.isEnabled,
);
}

Map<String, dynamic> toJson() => _$SmartSceneToJson(this);

factory SmartScene.fromJson(Map<String, dynamic> json) =>
_$SmartSceneFromJson(json);
}

/// 场景动作
abstract class SceneAction {
Future<void> execute(SmartDeviceManager manager);
Map<String, dynamic> toJson();
static SceneAction fromJson(Map<String, dynamic> json) {
final type = json['type'] as String;
switch (type) {
case 'device_control':
return DeviceControlAction.fromJson(json);
case 'delay':
return DelayAction.fromJson(json);
case 'scene':
return SceneCallAction.fromJson(json);
default:
throw ArgumentError('Unknown action type: $type');
}
}
}

/// 设备控制动作
()
class DeviceControlAction extends SceneAction {
final String deviceId;
final Map<String, dynamic> params;

const DeviceControlAction({
required this.deviceId,
required this.params,
});


Future<void> execute(SmartDeviceManager manager) async {
final command = _createCommand();
await manager.controlDevice(deviceId, command);
}

DeviceCommand _createCommand() {
final type = params['deviceType'] as String?;
if (type == 'light') {
return LightCommand(
deviceId: deviceId,
isOn: params['isOn'] as bool?,
brightness: params['brightness'] as int?,
colorTemp: params['colorTemp'] as int?,
);
}
throw UnimplementedError('Unknown device type');
}


Map<String, dynamic> toJson() => _$DeviceControlActionToJson(this);

factory DeviceControlAction.fromJson(Map<String, dynamic> json) =>
_$DeviceControlActionFromJson(json);
}

/// 延迟动作
()
class DelayAction extends SceneAction {
final int delayMs;

const DelayAction({required this.delayMs});


Future<void> execute(SmartDeviceManager manager) async {
await Future.delayed(Duration(milliseconds: delayMs));
}


Map<String, dynamic> toJson() => _$DelayActionToJson(this);

factory DelayAction.fromJson(Map<String, dynamic> json) =>
_$DelayActionFromJson(json);
}

/// 场景触发器
()
class SceneTrigger {
final TriggerType type;
final Map<String, dynamic> conditions;

const SceneTrigger({
required this.type,
required this.conditions,
});

/// 检查触发条件
bool check(Map<String, dynamic> eventData) {
switch (type) {
case TriggerType.time:
return _checkTimeTrigger();
case TriggerType.device:
return _checkDeviceTrigger(eventData);
case TriggerType.location:
return _checkLocationTrigger(eventData);
}
}

bool _checkTimeTrigger() {
final now = DateTime.now();
final hour = conditions['hour'] as int? ?? 1;
final minute = conditions['minute'] as int? ?? 0;

if (hour >= 0 && now.hour == hour && now.minute == minute) {
return true;
}

return false;
}

bool _checkDeviceTrigger(Map<String, dynamic> eventData) {
final deviceId = conditions['deviceId'] as String?;
final expectedState = conditions['state'] as Map<String, dynamic>?;

if (deviceId == null || expectedState == null) return false;

// 检查设备状态匹配
return true; // 简化实现
}

bool _checkLocationTrigger(Map<String, dynamic> eventData) {
// 位置触发检查
return false;
}

Map<String, dynamic> toJson() => _$SceneTriggerToJson(this);

factory SceneTrigger.fromJson(Map<String, dynamic> json) =>
_$SceneTriggerFromJson(json);
}

enum TriggerType { time, device, location }

/// 场景引擎
class SceneEngine {
final SmartDeviceManager _deviceManager;
final List<SmartScene> _scenes;
final StreamController<SmartScene> _triggerController =
StreamController.broadcast();

Stream<SmartScene> get triggerStream => _triggerController.stream;

SceneEngine(this._deviceManager, this._scenes) {
_initialize();
}

void _initialize() {
// 订阅设备事件
_deviceManager.eventStream.listen((event) {
_checkSceneTriggers(event);
});

// 启动定时检查
Timer.periodic(const Duration(minutes: 1), (_) {
_checkTimeTriggers();
});
}

/// 执行场景
Future<void> executeScene(String sceneId) async {
final scene = _scenes.firstWhere(
(s) => s.sceneId == sceneId,
orElse: () => throw ArgumentError('Scene not found: $sceneId'),
);

await scene.execute(_deviceManager);
_triggerController.add(scene);
}

/// 检查场景触发
void _checkSceneTriggers(DeviceEvent event) {
for (final scene in _scenes) {
if (scene.trigger?.check(event.toJson()) ?? false) {
executeScene(scene.sceneId);
}
}
}

/// 检查时间触发
void _checkTimeTriggers() {
for (final scene in _scenes) {
if (scene.trigger?.type == TriggerType.time) {
if (scene.trigger?.check({}) ?? false) {
executeScene(scene.sceneId);
}
}
}
}

void dispose() {
_triggerController.close();
}
}

语音控制集成

语音意图识别

/// 语音意图类型
enum VoiceIntent {
turnOnDevice, // 打开设备
turnOffDevice, // 关闭设备
setBrightness, // 设置亮度
setTemperature, // 设置温度
openCurtain, // 打开窗帘
closeCurtain, // 关闭窗帘
executeScene, // 执行场景
queryStatus, // 查询状态
}

/// 语音命令解析器
class VoiceCommandParser {
static const Map<String, VoiceIntent> _intentKeywords = {
'打开': VoiceIntent.turnOnDevice,
'开启': VoiceIntent.turnOnDevice,
'关闭': VoiceIntent.turnOffDevice,
'亮度': VoiceIntent.setBrightness,
'温度': VoiceIntent.setTemperature,
'拉开': VoiceIntent.openCurtain,
'拉上': VoiceIntent.closeCurtain,
'执行': VoiceIntent.executeScene,
'运行': VoiceIntent.executeScene,
'状态': VoiceIntent.queryStatus,
};

/// 解析语音命令
static ParsedCommand? parse(String text) {
// 简化的解析逻辑
for (final entry in _intentKeywords.entries) {
if (text.contains(entry.key)) {
final intent = entry.value;
final params = _extractParameters(text, intent);

return ParsedCommand(
intent: intent,
parameters: params,
originalText: text,
);
}
}

return null;
}

static Map<String, dynamic> _extractParameters(
String text,
VoiceIntent intent,
) {
final params = <String, dynamic>{};

switch (intent) {
case VoiceIntent.turnOnDevice:
case VoiceIntent.turnOffDevice:
params['deviceType'] = _extractDeviceType(text);
params['room'] = _extractRoom(text);
break;

case VoiceIntent.setBrightness:
params['value'] = _extractNumber(text);
break;

case VoiceIntent.setTemperature:
params['value'] = _extractNumber(text);
break;

default:
break;
}

return params;
}

static SmartDeviceType? _extractDeviceType(String text) {
if (text.contains('灯') || text.contains('照明')) {
return SmartDeviceType.light;
} else if (text.contains('空调')) {
return SmartDeviceType.ac;
} else if (text.contains('窗帘')) {
return SmartDeviceType.curtain;
}
return null;
}

static String? _extractRoom(String text) {
if (text.contains('客厅')) return 'living_room';
if (text.contains('卧室')) return 'bedroom';
if (text.contains('厨房')) return 'kitchen';
return null;
}

static int? _extractNumber(String text) {
final regex = RegExp(r'\\d+');
final match = regex.firstMatch(text);
return match != null ? int.tryParse(match.group(0)!) : null;
}
}

/// 解析后的命令
class ParsedCommand {
final VoiceIntent intent;
final Map<String, dynamic> parameters;
final String originalText;

ParsedCommand({
required this.intent,
required this.parameters,
required this.originalText,
});
}

/// 语音控制执行器
class VoiceController {
final SmartDeviceManager _deviceManager;
final SceneEngine _sceneEngine;

VoiceController(this._deviceManager, this._sceneEngine);

/// 执行语音命令
Future<VoiceResult> execute(String text) async {
final command = VoiceCommandParser.parse(text);

if (command == null) {
return VoiceResult(
success: false,
message: '抱歉,我没有理解您的指令',
);
}

try {
await _executeCommand(command);
return VoiceResult(
success: true,
message: _generateSuccessMessage(command),
);
} catch (e) {
return VoiceResult(
success: false,
message: '执行失败:$e',
);
}
}

Future<void> _executeCommand(ParsedCommand command) async {
switch (command.intent) {
case VoiceIntent.turnOnDevice:
await _handleTurnOn(command);
break;
case VoiceIntent.turnOffDevice:
await _handleTurnOff(command);
break;
case VoiceIntent.setBrightness:
await _handleSetBrightness(command);
break;
case VoiceIntent.executeScene:
await _handleExecuteScene(command);
break;
default:
throw UnimplementedError('Intent not implemented');
}
}

Future<void> _handleTurnOn(ParsedCommand command) async {
final room = command.parameters['room'] as String?;
final deviceType = command.parameters['deviceType'] as SmartDeviceType?;

final devices = _deviceManager.getDevicesByType(deviceType!);
final targetDevices = room == null
? devices
: devices.where((d) => d.roomId == room).toList();

for (final device in targetDevices) {
await _deviceManager.controlDevice(
device.deviceId,
LightCommand(deviceId: device.deviceId, isOn: true),
);
}
}

Future<void> _handleSetBrightness(ParsedCommand command) async {
final value = command.parameters['value'] as int?;
if (value == null) return;

final lights = _deviceManager.getDevicesByType(SmartDeviceType.light);
for (final light in lights) {
await _deviceManager.controlDevice(
light.deviceId,
LightCommand(deviceId: light.deviceId, brightness: value),
);
}
}

Future<void> _handleExecuteScene(ParsedCommand command) async {
final sceneName = command.parameters['sceneName'] as String?;
if (sceneName == null) return;

// 通过场景名称查找并执行
// await _sceneEngine.executeScene(sceneId);
}

String _generateSuccessMessage(ParsedCommand command) {
switch (command.intent) {
case VoiceIntent.turnOnDevice:
return '已为您打开设备';
case VoiceIntent.turnOffDevice:
return '已为您关闭设备';
case VoiceIntent.setBrightness:
return '已调整亮度';
default:
return '执行成功';
}
}
}

/// 语音执行结果
class VoiceResult {
final bool success;
final String message;

VoiceResult({required this.success, required this.message});
}

UI实现

主界面

/// 智能家居主页面
class SmartHomePage extends ConsumerStatefulWidget {
const SmartHomePage({super.key});


ConsumerState<SmartHomePage> createState() => _SmartHomePageState();
}

class _SmartHomePageState extends ConsumerState<SmartHomePage> {

Widget build(BuildContext context) {
final roomManager = ref.watch(roomManagerProvider);
final deviceManager = ref.watch(deviceManagerProvider);

return Scaffold(
body: CustomScrollView(
slivers: [
// 顶部AppBar
_buildAppBar(context),

// 房间卡片
SliverToBoxAdapter(
child: _buildRoomsSection(context, roomManager, deviceManager),
),

// 设备列表
_buildDevicesSection(deviceManager),

// 场景快捷方式
SliverToBoxAdapter(
child: _buildScenesSection(context),
),
],
),

// 语音按钮
floatingActionButton: _buildVoiceButton(context),
);
}

Widget _buildAppBar(BuildContext context) {
return SliverAppBar(
expandedHeight: 120,
floating: false,
pinned: true,
flexibleSpace: FlexibleSpaceBar(
title: const Text('智能家居'),
background: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
Colors.blue.shade400,
Colors.blue.shade700,
],
),
),
child: const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.home, size: 48, color: Colors.white70),
SizedBox(height: 8),
Text(
'欢迎回家',
style: TextStyle(color: Colors.white70),
),
],
),
),
),
),
actions: [
IconButton(
icon: const Icon(Icons.settings),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (_) => const SettingsPage()),
),
),
],
);
}

Widget _buildRoomsSection(
BuildContext context,
RoomManager roomManager,
SmartDeviceManager deviceManager,
) {
return Container(
padding: const EdgeInsets.symmetric(vertical: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Padding(
padding: EdgeInsets.symmetric(horizontal: 16),
child: Text(
'房间',
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
),
const SizedBox(height: 12),
SizedBox(
height: 120,
child: ListView.builder(
scrollDirection: Axis.horizontal,
padding: const EdgeInsets.symmetric(horizontal: 16),
itemCount: roomManager.rooms.length,
itemBuilder: (context, index) {
final room = roomManager.rooms[index];
return _buildRoomCard(context, room, deviceManager);
},
),
),
],
),
);
}

Widget _buildRoomCard(
BuildContext context,
SmartRoom room,
SmartDeviceManager deviceManager,
) {
final onlineCount = room.getOnlineDeviceCount(deviceManager);
final totalDevices = room.deviceIds.length;

return Container(
width: 160,
margin: const EdgeInsets.only(right: 12),
child: Card(
clipBehavior: Clip.antiAlias,
child: InkWell(
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (_) => RoomDetailPage(room: room),
),
),
child: Padding(
padding: const EdgeInsets.all(12),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Icon(_getRoomIcon(room.icon), size: 24),
const Spacer(),
Chip(
label: Text('$onlineCount/$totalDevices'),
visualDensity: VisualDensity.compact,
),
],
),
const Spacer(),
Text(
room.roomName,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
Text(
'${room.temperature}°C · ${room.humidity}%',
style: TextStyle(
fontSize: 12,
color: Colors.grey[600],
),
),
],
),
),
),
),
);
}

IconData _getRoomIcon(String icon) {
switch (icon) {
case 'sofa':
return Icons.weekend;
case 'bed':
return Icons.bed;
case 'chef':
return Icons.kitchen;
default:
return Icons.room;
}
}

Widget _buildDevicesSection(SmartDeviceManager deviceManager) {
return SliverPadding(
padding: const EdgeInsets.symmetric(horizontal: 16),
sliver: SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
final device = deviceManager.devices[index];
return _buildDeviceCard(context, device);
},
childCount: deviceManager.devices.length,
),
),
);
}

Widget _buildDeviceCard(BuildContext context, SmartDevice device) {
return Card(
margin: const EdgeInsets.only(bottom: 12),
child: ListTile(
leading: Icon(device.type.icon),
title: Text(device.deviceName),
subtitle: Text(device.isOnline ? '在线' : '离线'),
trailing: _buildDeviceControl(device),
onTap: () => Navigator.push(
context,
MaterialPageRoute(
builder: (_) => DeviceControlPage(device: device),
),
),
),
);
}

Widget _buildDeviceControl(SmartDevice device) {
if (device is SmartLight) {
final state = device.currentState;
return Switch(
value: state.isOn,
onChanged: (value) {
// 控制灯光
},
);
}
return const Icon(Icons.chevron_right);
}

Widget _buildScenesSection(BuildContext context) {
final scenes = ref.watch(sceneProvider);

return Container(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'场景',
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
const SizedBox(height: 12),
Wrap(
spacing: 12,
runSpacing: 12,
children: scenes.map((scene) {
return _buildSceneChip(context, scene);
}).toList(),
),
],
),
);
}

Widget _buildSceneChip(BuildContext context, SmartScene scene) {
return ActionChip(
avatar: const Icon(Icons.flash_on),
label: Text(scene.sceneName),
onPressed: () async {
await ref.read(sceneProvider.notifier).executeScene(scene.sceneId);
},
);
}

Widget _buildVoiceButton(BuildContext context) {
return FloatingActionButton.extended(
onPressed: () => _showVoiceDialog(context),
icon: const Icon(Icons.mic),
label: const Text('语音控制'),
);
}

void _showVoiceDialog(BuildContext context) {
showDialog(
context: context,
builder: (_) => const VoiceControlDialog(),
);
}
}

语音控制对话框

/// 语音控制对话框
class VoiceControlDialog extends ConsumerStatefulWidget {
const VoiceControlDialog({super.key});


ConsumerState<VoiceControlDialog> createState() => _VoiceControlDialogState();
}

class _VoiceControlDialogState extends ConsumerState<VoiceControlDialog> {
bool _isListening = false;
String _recognizedText = '';
VoiceResult? _result;


Widget build(BuildContext context) {
return AlertDialog(
title: const Text('语音控制'),
content: SizedBox(
width: 300,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// 麦克风动画
_buildMicrophoneAnimation(),

const SizedBox(height: 24),

// 识别文本
if (_recognizedText.isNotEmpty)
Text(
_recognizedText,
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 16),
),

const SizedBox(height: 16),

// 执行结果
if (_result != null)
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: _result!.success
? Colors.green.shade50
: Colors.red.shade50,
borderRadius: BorderRadius.circular(8),
),
child: Row(
children: [
Icon(
_result!.success ? Icons.check_circle : Icons.error,
color: _result!.success ? Colors.green : Colors.red,
),
const SizedBox(width: 8),
Expanded(child: Text(_result!.message)),
],
),
),

const SizedBox(height: 8),

// 提示文本
Text(
'说出指令,如:"打开客厅灯"',
style: TextStyle(
fontSize: 12,
color: Colors.grey[600],
),
),
],
),
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('关闭'),
),
],
);
}

Widget _buildMicrophoneAnimation() {
return GestureDetector(
onTap: _isListening ? null : _startListening,
child: AnimatedContainer(
duration: const Duration(milliseconds: 300),
width: 80,
height: 80,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: _isListening ? Colors.blue.shade100 : Colors.grey.shade200,
boxShadow: _isListening
? [
BoxShadow(
color: Colors.blue.withOpacity(0.3),
blurRadius: 20,
spreadRadius: 10,
),
]
: null,
),
child: Icon(
_isListening ? Icons.mic : Icons.mic_none,
size: 40,
color: _isListening ? Colors.blue : Colors.grey,
),
),
);
}

Future<void> _startListening() async {
setState(() => _isListening = true);
_result = null;

try {
// 调用鸿蒙语音识别
final text = await HarmonyVoiceChannel.startListening();

if (text != null) {
setState(() => _recognizedText = text);

// 执行语音命令
final voiceController = ref.read(voiceControllerProvider);
final result = await voiceController.execute(text);

setState(() => _result = result);
}
} catch (e) {
setState(() {
_result = VoiceResult(
success: false,
message: '识别失败:$e',
);
});
} finally {
setState(() => _isListening = false);
}
}
}

鸿蒙端IoT服务

设备通信实现

// HarmonyIotService.ets
import distributedDevice from '@ohos.distributedDevice';
import { MethodChannel } from '@ohos.flutter';

export class HarmonyIotService {
private flutterChannel: MethodChannel | null = null;
private deviceCallbacks: Map<string, (data: ESObject) => void> = new Map();

initialize(channel: MethodChannel): void {
this.flutterChannel = channel;
this._registerMethodChannel();
this._startDeviceDiscovery();
}

private _registerMethodChannel(): void {
this.flutterChannel?.setMethodCallHandler(
async (method: string, args: Record<string, Object>): Promise<Object> => {
switch (method) {
case 'discoverDevices':
return await this._handleDiscoverDevices();
case 'sendCommand':
return await this._handleSendCommand(args);
case 'startVoice':
return await this._handleStartVoice(args);
default:
return null;
}
}
);
}

private async _handleDiscoverDevices(): Promise<Object[]> {
const devices: Object[] = [];

try {
// 发现周边智能设备
const discoverInfo: distributedDevice.SubscribeInfo = {
subscribeId: 1,
mode: distributedDevice.DiscoveryMode.ACTIVE,
medium: distributedDevice.MediumType.WIFI,
freq: distributedDevice.FreqType.HIGH
};

distributedDevice.startDeviceDiscovery(discoverInfo, (err, data) => {
if (!err) {
devices.push({
'deviceId': data.deviceId,
'deviceName': data.deviceName,
'type': this._mapDeviceType(data.deviceType),
'isOnline': true
});
}
});

// 等待设备发现完成
await new Promise(resolve => setTimeout(resolve, 3000));

return devices;
} catch (e) {
console.error('设备发现失败:', e);
return [];
}
}

private _mapDeviceType(type: string): string {
// 映射鸿蒙设备类型到智能家居类型
const typeMap: Record<string, string> = {
'SMART_LIGHT': 'light',
'SMART_AC': 'ac',
'SMART_CURTAIN': 'curtain',
'SMART_SENSOR': 'sensor'
};

return typeMap[type] || 'switch';
}

private async _handleSendCommand(args: Record<string, Object>): Promise<boolean> {
try {
const deviceId = args['deviceId'] as string;
const command = args as Record<string, Object>;

// 通过HiLink协议发送控制命令
const success = await this._sendHiLinkCommand(deviceId, command);

// 通知Flutter命令结果
if (success) {
this._notifyStateChange(deviceId, command);
}

return success;
} catch (e) {
console.error('发送命令失败:', e);
return false;
}
}

private async _sendHiLinkCommand(
deviceId: string,
command: Record<string, Object>
): Promise<boolean> {
// HiLink协议实现
return true;
}

private _notifyStateChange(
deviceId: string,
command: Record<string, Object>
): void {
this.flutterChannel?.invokeMethod('onDeviceStateChanged', {
'deviceId': deviceId,
'data': command
});
}

private async _handleStartVoice(args: Record<string, Object>): Promise<string | null> {
// 调用鸿蒙语音识别
// 返回识别的文本
return '打开客厅灯';
}

private _startDeviceDiscovery(): void {
// 持续发现设备
}

destroy(): void {
distributedDevice.stopDeviceDiscovery(1);
this.flutterChannel = null;
}
}

总结

本文系统讲解了基于鸿蒙Flutter开发智能家居应用的完整方案:

  • 系统架构:四层分离的智能家居系统设计
  • 设备模型:统一抽象的智能设备模型
  • 设备管理:发现、控制、批量操作
  • 场景引擎:自动化场景编排与触发
  • 语音控制:自然语言理解与执行
  • UI实现:响应式的智能家居控制界面
  • 通过这套方案,开发者可以快速构建功能完整的智能家居应用,充分利用鸿蒙分布式能力实现全场景智慧生活体验。


    相关资源

    • 鸿蒙IoT开发指南
    • HiLink协议规范
    • 智能家居应用开发最佳实践
    赞(0)
    未经允许不得转载:171主机测评 » 【HarmonyOS】鸿蒙Flutter智能家居应用开发实战指南
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址