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

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

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

在这里插入图片描述

概述

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

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

系统架构设计

整体架构图

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

核心组件设计

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

设备模型设计

基础设备抽象

/// 设备类型枚举enumSmartDeviceType{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);finalString displayName;finalIconData icon;constSmartDeviceType(this.displayName,this.icon);}/// 设备状态基类abstractclassDeviceState{Map<String,dynamic>toJson();staticDeviceStatefromJson(Map<String,dynamic> json){final type = json['type']asString;switch(type){case'light':returnLightState.fromJson(json);case'curtain':returnCurtainState.fromJson(json);case'ac':returnACState.fromJson(json);case'sensor':returnSensorState.fromJson(json);default:throwArgumentError('Unknown device type: $type');}}}/// 智能设备基类abstractclassSmartDevice{finalString deviceId;finalString deviceName;finalSmartDeviceType type;finalString roomId;final bool isOnline;finalDateTime lastSeen;constSmartDevice({ required this.deviceId, required this.deviceName, required this.type, required this.roomId,this.isOnline =true,DateTime? lastSeen,}): lastSeen = lastSeen ??constDuration();/// 获取当前状态DeviceStateget currentState;/// 执行控制命令Future<bool>executeCommand(DeviceCommand command);/// 订阅状态变化Stream<DeviceState>get stateStream;/// 工厂构造方法staticSmartDevicefromJson(Map<String,dynamic> json){final type =SmartDeviceType.values.firstWhere((e)=> e.name == json['type'], orElse:()=>SmartDeviceType.switch,);switch(type){caseSmartDeviceType.light:returnSmartLight.fromJson(json);caseSmartDeviceType.curtain:returnSmartCurtain.fromJson(json);caseSmartDeviceType.ac:returnSmartAC.fromJson(json);caseSmartDeviceType.sensor:returnSmartSensor.fromJson(json);default:returnSmartSwitch.fromJson(json);}}Map<String,dynamic>toJson();}/// 设备命令基类abstractclassDeviceCommand{finalString deviceId;finalDateTime timestamp;DeviceCommand({required this.deviceId}): timestamp =DateTime.now();Map<String,dynamic>toJson();}/// 设备事件classDeviceEvent{finalString deviceId;finalSmartDeviceType type;finalString eventType;finalMap<String,dynamic> data;finalDateTime timestamp;DeviceEvent({ required this.deviceId, required this.type, required this.eventType, required this.data,}): timestamp =DateTime.now();}

具体设备实现

/// 灯光状态@JsonSerializable()classLightStateextendsDeviceState{final bool isOn;final int brightness;// 0-100final int colorTemp;// 色温 2700-6500Kfinal int? hue;// 色相 0-360final int? saturation;// 饱和度 0-100constLightState({this.isOn =false,this.brightness =100,this.colorTemp =4000,this.hue,this.saturation,});@overrideMap<String,dynamic>toJson()=> _$LightStateToJson(this);factoryLightState.fromJson(Map<String,dynamic> json)=> _$LightStateFromJson(json);LightStatecopyWith({ bool? isOn, int? brightness, int? colorTemp, int? hue, int? saturation,}){returnLightState( isOn: isOn ??this.isOn, brightness: brightness ??this.brightness, colorTemp: colorTemp ??this.colorTemp, hue: hue ??this.hue, saturation: saturation ??this.saturation,);}}/// 灯光控制命令classLightCommandextendsDeviceCommand{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,});@overrideMap<String,dynamic>toJson()=>{'deviceId': deviceId,'command':'light_control','params':{'isOn': isOn,'brightness': brightness,'colorTemp': colorTemp,'hue': hue,'saturation': saturation,},'timestamp': timestamp.toIso8601String(),};}/// 智能灯光设备classSmartLightextendsSmartDevice{LightState _state;SmartLight({ required super.deviceId, required super.deviceName, required super.roomId,LightState? state,super.isOnline,}): _state = state ??constLightState(),super(type:SmartDeviceType.light);@overrideLightStateget currentState => _state;@overrideFuture<bool>executeCommand(DeviceCommand command)async{if(command is!LightCommand)returnfalse;if(!isOnline)returnfalse;try{// 通过鸿蒙分布式能力发送命令final result =awaitHarmonyIotChannel.sendDeviceCommand(command.toJson());if(result){// 更新本地状态 _state = _state.copyWith( isOn: command.isOn, brightness: command.brightness, colorTemp: command.colorTemp, hue: command.hue, saturation: command.saturation,);returntrue;}returnfalse;}catch(e){debugPrint('灯光控制失败: $e');returnfalse;}}@overrideStream<LightState>get stateStream {returnHarmonyIotChannel.deviceStateStream .where((event)=> event.deviceId == deviceId).map((event)=>LightState.fromJson(event.data));}@overrideMap<String,dynamic>toJson()=>{'deviceId': deviceId,'deviceName': deviceName,'type': type.name,'roomId': roomId,'isOnline': isOnline,'lastSeen': lastSeen.toIso8601String(),'state': _state.toJson(),};factorySmartLight.fromJson(Map<String,dynamic> json){returnSmartLight( deviceId: json['deviceId']asString, deviceName: json['deviceName']asString, roomId: json['roomId']asString, state: json['state']!=null?LightState.fromJson(json['state']asMap<String,dynamic>):null, isOnline: json['isOnline']as bool???true,);}}/// 空调状态@JsonSerializable()classACStateextendsDeviceState{final bool isOn;final int temperature;// 16-30finalString mode;// cool, heat, auto, dry, fanfinal int fanSpeed;// 1-3final bool swing;constACState({this.isOn =false,this.temperature =26,this.mode ='cool',this.fanSpeed =2,this.swing =false,});@overrideMap<String,dynamic>toJson()=> _$ACStateToJson(this);factoryACState.fromJson(Map<String,dynamic> json)=> _$ACStateFromJson(json);ACStatecopyWith({ bool? isOn, int? temperature,String? mode, int? fanSpeed, bool? swing,}){returnACState( isOn: isOn ??this.isOn, temperature: temperature ??this.temperature, mode: mode ??this.mode, fanSpeed: fanSpeed ??this.fanSpeed, swing: swing ??this.swing,);}}/// 智能空调设备classSmartACextendsSmartDevice{ACState _state;SmartAC({ required super.deviceId, required super.deviceName, required super.roomId,ACState? state,super.isOnline,}): _state = state ??constACState(),super(type:SmartDeviceType.ac);@overrideACStateget currentState => _state;@overrideFuture<bool>executeCommand(DeviceCommand command)async{if(command is!ACCommand)returnfalse; _state = _state.copyWith( isOn: command.isOn, temperature: command.temperature, mode: command.mode, fanSpeed: command.fanSpeed, swing: command.swing,);returnawaitHarmonyIotChannel.sendDeviceCommand(command.toJson());}@overrideStream<ACState>get stateStream {returnHarmonyIotChannel.deviceStateStream .where((event)=> event.deviceId == deviceId).map((event)=>ACState.fromJson(event.data));}@overrideMap<String,dynamic>toJson()=>{'deviceId': deviceId,'deviceName': deviceName,'type': type.name,'roomId': roomId,'isOnline': isOnline,'state': _state.toJson(),};}/// 空调控制命令classACCommandextendsDeviceCommand{final bool? isOn;final int? temperature;finalString? mode;final int? fanSpeed;final bool? swing;ACCommand({ required super.deviceId,this.isOn,this.temperature,this.mode,this.fanSpeed,this.swing,});@overrideMap<String,dynamic>toJson()=>{'deviceId': deviceId,'command':'ac_control','params':{'isOn': isOn,'temperature': temperature,'mode': mode,'fanSpeed': fanSpeed,'swing': swing,},'timestamp': timestamp.toIso8601String(),};}

设备管理系统

设备管理器实现

/// 智能设备管理器classSmartDeviceManager{staticfinalSmartDeviceManager _instance =SmartDeviceManager._internal();factorySmartDeviceManager()=> _instance;SmartDeviceManager._internal();finalMap<String,SmartDevice> _devices ={};finalMap<String,List<SmartDevice>> _roomDevices ={};finalStreamController<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);});// 发现设备awaitdiscoverDevices();}/// 发现设备Future<void>discoverDevices()async{try{final deviceList =awaitHarmonyIotChannel.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)returnfalse;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,DeviceCommandFunction(String) commandBuilder,)async{final results =<String, bool>{};awaitFuture.wait(deviceIds.map((deviceId)async{final command =commandBuilder(deviceId); results[deviceId]=awaitcontrolDevice(deviceId, command);}));return results;}/// 处理设备状态变化void_handleDeviceStateChange(DeviceEvent event){final device = _devices[event.deviceId];if(device !=null){// 更新设备状态 _eventController.add(event);}}/// 释放资源voiddispose(){ _eventController.close();}}

房间管理

/// 房间模型@JsonSerializable()classSmartRoom{finalString roomId;finalString roomName;finalString icon;finalList<String> deviceIds;final int temperature;final int humidity;final int brightness;constSmartRoom({ 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){returngetDevices(manager).where((d)=> d.isOnline).length;}/// 是否有灯光设备 bool hasLightDevices(SmartDeviceManager manager){returngetDevices(manager).any((d)=> d.type ==SmartDeviceType.light);}SmartRoomcopyWith({String? roomId,String? roomName,String? icon,List<String>? deviceIds, int? temperature, int? humidity, int? brightness,}){returnSmartRoom( 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);factorySmartRoom.fromJson(Map<String,dynamic> json)=> _$SmartRoomFromJson(json);}/// 房间管理器classRoomManager{finalList<SmartRoom> _rooms =[constSmartRoom( roomId:'living_room', roomName:'客厅', icon:'sofa', deviceIds:['light_1','ac_1','curtain_1'],),constSmartRoom( roomId:'bedroom', roomName:'卧室', icon:'bed', deviceIds:['light_2','ac_2','curtain_2'],),constSmartRoom( 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){returnnull;}}voidupdateRoomEnvironment({ 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,);}}}

场景自动化

场景引擎

/// 智能场景@JsonSerializable()classSmartScene{finalString sceneId;finalString sceneName;finalString icon;finalList<SceneAction> actions;finalSceneTrigger? trigger;final bool isEnabled;constSmartScene({ 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);}}SmartScenecopyWith({String? sceneId,String? sceneName,String? icon,List<SceneAction>? actions,SceneTrigger? trigger, bool? isEnabled,}){returnSmartScene( 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);factorySmartScene.fromJson(Map<String,dynamic> json)=> _$SmartSceneFromJson(json);}/// 场景动作abstractclassSceneAction{Future<void>execute(SmartDeviceManager manager);Map<String,dynamic>toJson();staticSceneActionfromJson(Map<String,dynamic> json){final type = json['type']asString;switch(type){case'device_control':returnDeviceControlAction.fromJson(json);case'delay':returnDelayAction.fromJson(json);case'scene':returnSceneCallAction.fromJson(json);default:throwArgumentError('Unknown action type: $type');}}}/// 设备控制动作@JsonSerializable()classDeviceControlActionextendsSceneAction{finalString deviceId;finalMap<String,dynamic> params;constDeviceControlAction({ required this.deviceId, required this.params,});@overrideFuture<void>execute(SmartDeviceManager manager)async{final command =_createCommand();await manager.controlDevice(deviceId, command);}DeviceCommand_createCommand(){final type = params['deviceType']asString?;if(type =='light'){returnLightCommand( deviceId: deviceId, isOn: params['isOn']as bool?, brightness: params['brightness']as int?, colorTemp: params['colorTemp']as int?,);}throwUnimplementedError('Unknown device type');}@overrideMap<String,dynamic>toJson()=> _$DeviceControlActionToJson(this);factoryDeviceControlAction.fromJson(Map<String,dynamic> json)=> _$DeviceControlActionFromJson(json);}/// 延迟动作@JsonSerializable()classDelayActionextendsSceneAction{final int delayMs;constDelayAction({required this.delayMs});@overrideFuture<void>execute(SmartDeviceManager manager)async{awaitFuture.delayed(Duration(milliseconds: delayMs));}@overrideMap<String,dynamic>toJson()=> _$DelayActionToJson(this);factoryDelayAction.fromJson(Map<String,dynamic> json)=> _$DelayActionFromJson(json);}/// 场景触发器@JsonSerializable()classSceneTrigger{finalTriggerType type;finalMap<String,dynamic> conditions;constSceneTrigger({ required this.type, required this.conditions,});/// 检查触发条件 bool check(Map<String,dynamic> eventData){switch(type){caseTriggerType.time:return_checkTimeTrigger();caseTriggerType.device:return_checkDeviceTrigger(eventData);caseTriggerType.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){returntrue;}returnfalse;} bool _checkDeviceTrigger(Map<String,dynamic> eventData){final deviceId = conditions['deviceId']asString?;final expectedState = conditions['state']asMap<String,dynamic>?;if(deviceId ==null|| expectedState ==null)returnfalse;// 检查设备状态匹配returntrue;// 简化实现} bool _checkLocationTrigger(Map<String,dynamic> eventData){// 位置触发检查returnfalse;}Map<String,dynamic>toJson()=> _$SceneTriggerToJson(this);factorySceneTrigger.fromJson(Map<String,dynamic> json)=> _$SceneTriggerFromJson(json);}enumTriggerType{ time, device, location }/// 场景引擎classSceneEngine{finalSmartDeviceManager _deviceManager;finalList<SmartScene> _scenes;finalStreamController<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(constDuration(minutes:1),(_){_checkTimeTriggers();});}/// 执行场景Future<void>executeScene(String sceneId)async{final scene = _scenes.firstWhere((s)=> s.sceneId == sceneId, orElse:()=>throwArgumentError('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);}}}}voiddispose(){ _triggerController.close();}}

语音控制集成

语音意图识别

/// 语音意图类型enumVoiceIntent{ turnOnDevice,// 打开设备 turnOffDevice,// 关闭设备 setBrightness,// 设置亮度 setTemperature,// 设置温度 openCurtain,// 打开窗帘 closeCurtain,// 关闭窗帘 executeScene,// 执行场景 queryStatus,// 查询状态}/// 语音命令解析器classVoiceCommandParser{staticconstMap<String,VoiceIntent> _intentKeywords ={'打开':VoiceIntent.turnOnDevice,'开启':VoiceIntent.turnOnDevice,'关闭':VoiceIntent.turnOffDevice,'亮度':VoiceIntent.setBrightness,'温度':VoiceIntent.setTemperature,'拉开':VoiceIntent.openCurtain,'拉上':VoiceIntent.closeCurtain,'执行':VoiceIntent.executeScene,'运行':VoiceIntent.executeScene,'状态':VoiceIntent.queryStatus,};/// 解析语音命令staticParsedCommand?parse(String text){// 简化的解析逻辑for(final entry in _intentKeywords.entries){if(text.contains(entry.key)){final intent = entry.value;final params =_extractParameters(text, intent);returnParsedCommand( intent: intent, parameters: params, originalText: text,);}}returnnull;}staticMap<String,dynamic>_extractParameters(String text,VoiceIntent intent,){final params =<String,dynamic>{};switch(intent){caseVoiceIntent.turnOnDevice:caseVoiceIntent.turnOffDevice: params['deviceType']=_extractDeviceType(text); params['room']=_extractRoom(text);break;caseVoiceIntent.setBrightness: params['value']=_extractNumber(text);break;caseVoiceIntent.setTemperature: params['value']=_extractNumber(text);break;default:break;}return params;}staticSmartDeviceType?_extractDeviceType(String text){if(text.contains('灯')|| text.contains('照明')){returnSmartDeviceType.light;}elseif(text.contains('空调')){returnSmartDeviceType.ac;}elseif(text.contains('窗帘')){returnSmartDeviceType.curtain;}returnnull;}staticString?_extractRoom(String text){if(text.contains('客厅'))return'living_room';if(text.contains('卧室'))return'bedroom';if(text.contains('厨房'))return'kitchen';returnnull;}static int?_extractNumber(String text){final regex =RegExp(r'\d+');final match = regex.firstMatch(text);return match !=null? int.tryParse(match.group(0)!):null;}}/// 解析后的命令classParsedCommand{finalVoiceIntent intent;finalMap<String,dynamic> parameters;finalString originalText;ParsedCommand({ required this.intent, required this.parameters, required this.originalText,});}/// 语音控制执行器classVoiceController{finalSmartDeviceManager _deviceManager;finalSceneEngine _sceneEngine;VoiceController(this._deviceManager,this._sceneEngine);/// 执行语音命令Future<VoiceResult>execute(String text)async{final command =VoiceCommandParser.parse(text);if(command ==null){returnVoiceResult( success:false, message:'抱歉,我没有理解您的指令',);}try{await_executeCommand(command);returnVoiceResult( success:true, message:_generateSuccessMessage(command),);}catch(e){returnVoiceResult( success:false, message:'执行失败:$e',);}}Future<void>_executeCommand(ParsedCommand command)async{switch(command.intent){caseVoiceIntent.turnOnDevice:await_handleTurnOn(command);break;caseVoiceIntent.turnOffDevice:await_handleTurnOff(command);break;caseVoiceIntent.setBrightness:await_handleSetBrightness(command);break;caseVoiceIntent.executeScene:await_handleExecuteScene(command);break;default:throwUnimplementedError('Intent not implemented');}}Future<void>_handleTurnOn(ParsedCommand command)async{final room = command.parameters['room']asString?;final deviceType = command.parameters['deviceType']asSmartDeviceType?;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']asString?;if(sceneName ==null)return;// 通过场景名称查找并执行// await _sceneEngine.executeScene(sceneId);}String_generateSuccessMessage(ParsedCommand command){switch(command.intent){caseVoiceIntent.turnOnDevice:return'已为您打开设备';caseVoiceIntent.turnOffDevice:return'已为您关闭设备';caseVoiceIntent.setBrightness:return'已调整亮度';default:return'执行成功';}}}/// 语音执行结果classVoiceResult{final bool success;finalString message;VoiceResult({required this.success, required this.message});}

UI实现

主界面

/// 智能家居主页面classSmartHomePageextendsConsumerStatefulWidget{constSmartHomePage({super.key});@overrideConsumerState<SmartHomePage>createState()=>_SmartHomePageState();}class _SmartHomePageState extendsConsumerState<SmartHomePage>{@overrideWidgetbuild(BuildContext context){final roomManager = ref.watch(roomManagerProvider);final deviceManager = ref.watch(deviceManagerProvider);returnScaffold( 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){returnSliverAppBar( expandedHeight:120, floating:false, pinned:true, flexibleSpace:FlexibleSpaceBar( title:constText('智能家居'), background:Container( decoration:BoxDecoration( gradient:LinearGradient( begin:Alignment.topLeft, end:Alignment.bottomRight, colors:[Colors.blue.shade400,Colors.blue.shade700,],),), child:constCenter( 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:constIcon(Icons.settings), onPressed:()=>Navigator.push( context,MaterialPageRoute(builder:(_)=>constSettingsPage()),),),],);}Widget_buildRoomsSection(BuildContext context,RoomManager roomManager,SmartDeviceManager deviceManager,){returnContainer( padding:constEdgeInsets.symmetric(vertical:16), child:Column( crossAxisAlignment:CrossAxisAlignment.start, children:[constPadding( padding:EdgeInsets.symmetric(horizontal:16), child:Text('房间', style:TextStyle(fontSize:20, fontWeight:FontWeight.bold),),),constSizedBox(height:12),SizedBox( height:120, child:ListView.builder( scrollDirection:Axis.horizontal, padding:constEdgeInsets.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;returnContainer( width:160, margin:constEdgeInsets.only(right:12), child:Card( clipBehavior:Clip.antiAlias, child:InkWell( onTap:()=>Navigator.push( context,MaterialPageRoute( builder:(_)=>RoomDetailPage(room: room),),), child:Padding( padding:constEdgeInsets.all(12), child:Column( crossAxisAlignment:CrossAxisAlignment.start, children:[Row( children:[Icon(_getRoomIcon(room.icon), size:24),constSpacer(),Chip( label:Text('$onlineCount/$totalDevices'), visualDensity:VisualDensity.compact,),],),constSpacer(),Text( room.roomName, style:constTextStyle( 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':returnIcons.weekend;case'bed':returnIcons.bed;case'chef':returnIcons.kitchen;default:returnIcons.room;}}Widget_buildDevicesSection(SmartDeviceManager deviceManager){returnSliverPadding( padding:constEdgeInsets.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){returnCard( margin:constEdgeInsets.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 isSmartLight){final state = device.currentState;returnSwitch( value: state.isOn, onChanged:(value){// 控制灯光},);}returnconstIcon(Icons.chevron_right);}Widget_buildScenesSection(BuildContext context){final scenes = ref.watch(sceneProvider);returnContainer( padding:constEdgeInsets.all(16), child:Column( crossAxisAlignment:CrossAxisAlignment.start, children:[constText('场景', style:TextStyle(fontSize:20, fontWeight:FontWeight.bold),),constSizedBox(height:12),Wrap( spacing:12, runSpacing:12, children: scenes.map((scene){return_buildSceneChip(context, scene);}).toList(),),],),);}Widget_buildSceneChip(BuildContext context,SmartScene scene){returnActionChip( avatar:constIcon(Icons.flash_on), label:Text(scene.sceneName), onPressed:()async{await ref.read(sceneProvider.notifier).executeScene(scene.sceneId);},);}Widget_buildVoiceButton(BuildContext context){returnFloatingActionButton.extended( onPressed:()=>_showVoiceDialog(context), icon:constIcon(Icons.mic), label:constText('语音控制'),);}void_showVoiceDialog(BuildContext context){showDialog( context: context, builder:(_)=>constVoiceControlDialog(),);}}

语音控制对话框

/// 语音控制对话框classVoiceControlDialogextendsConsumerStatefulWidget{constVoiceControlDialog({super.key});@overrideConsumerState<VoiceControlDialog>createState()=>_VoiceControlDialogState();}class _VoiceControlDialogState extendsConsumerState<VoiceControlDialog>{ bool _isListening =false;String _recognizedText ='';VoiceResult? _result;@overrideWidgetbuild(BuildContext context){returnAlertDialog( title:constText('语音控制'), content:SizedBox( width:300, child:Column( mainAxisSize:MainAxisSize.min, children:[// 麦克风动画_buildMicrophoneAnimation(),constSizedBox(height:24),// 识别文本if(_recognizedText.isNotEmpty)Text( _recognizedText, textAlign:TextAlign.center, style:constTextStyle(fontSize:16),),constSizedBox(height:16),// 执行结果if(_result !=null)Container( padding:constEdgeInsets.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,),constSizedBox(width:8),Expanded(child:Text(_result!.message)),],),),constSizedBox(height:8),// 提示文本Text('说出指令,如:"打开客厅灯"', style:TextStyle( fontSize:12, color:Colors.grey[600],),),],),), actions:[TextButton( onPressed:()=>Navigator.pop(context), child:constText('关闭'),),],);}Widget_buildMicrophoneAnimation(){returnGestureDetector( onTap: _isListening ?null: _startListening, child:AnimatedContainer( duration:constDuration(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 =awaitHarmonyVoiceChannel.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.etsimport distributedDevice from'@ohos.distributedDevice';import{ MethodChannel }from'@ohos.flutter';exportclassHarmonyIotService{private flutterChannel: MethodChannel |null=null;private deviceCallbacks: Map<string,(data: ESObject)=>void>=newMap();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':returnawaitthis._handleDiscoverDevices();case'sendCommand':returnawaitthis._handleSendCommand(args);case'startVoice':returnawaitthis._handleStartVoice(args);default:returnnull;}});}privateasync_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});}});// 等待设备发现完成awaitnewPromise(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';}privateasync_handleSendCommand(args: Record<string, Object>):Promise<boolean>{try{const deviceId = args['deviceId']asstring;const command = args as Record<string, Object>;// 通过HiLink协议发送控制命令const success =awaitthis._sendHiLinkCommand(deviceId, command);// 通知Flutter命令结果if(success){this._notifyStateChange(deviceId, command);}return success;}catch(e){console.error('发送命令失败:', e);returnfalse;}}privateasync_sendHiLinkCommand( deviceId:string, command: Record<string, Object>):Promise<boolean>{// HiLink协议实现returntrue;}private_notifyStateChange( deviceId:string, command: Record<string, Object>):void{this.flutterChannel?.invokeMethod('onDeviceStateChanged',{'deviceId': deviceId,'data': command });}privateasync_handleStartVoice(args: Record<string, Object>):Promise<string|null>{// 调用鸿蒙语音识别// 返回识别的文本return'打开客厅灯';}private_startDeviceDiscovery():void{// 持续发现设备}destroy():void{ distributedDevice.stopDeviceDiscovery(1);this.flutterChannel =null;}}

总结

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

  1. 系统架构:四层分离的智能家居系统设计
  2. 设备模型:统一抽象的智能设备模型
  3. 设备管理:发现、控制、批量操作
  4. 场景引擎:自动化场景编排与触发
  5. 语音控制:自然语言理解与执行
  6. UI实现:响应式的智能家居控制界面

通过这套方案,开发者可以快速构建功能完整的智能家居应用,充分利用鸿蒙分布式能力实现全场景智慧生活体验。


相关资源

Read more

我用6个AI测了一圈,谁是国产Agent第一名,答案出奇地一致

我做了一个有点无聊但结果挺有意思的实验:用6个主流 AI,问同一个问题——“国产 AI Agent 谁最强,给我排个前三”。 结果出奇地整齐。 先问海外的 为了避免"自家夸自家"的嫌疑,先从理论上没有利益关系的海外模型问起。 ChatGPT 的答案是:百度、腾讯、阿里。 Gemini 给了略微不同的排法:百度、阿里、字节——但百度还是第一。 Gemini 在回答里用了"基建狂魔"来描述百度,说百度在芯片、云、模型、应用层都有自己的布局。这个词没什么水分,讲的是一件具体的事。 再问国内的 国内四家的结论更集中。 DeepSeek:百度、腾讯、阿里。 文心:百度、腾讯、阿里—

【Vibe Coding】一口气搞懂AI黑话:Vibe Coding、Agent、提示词、MCP、Skills全解析

你是否也被AI领域的各种新名词轰炸得头晕眼花? Vibe Coding、AI Agent、提示词(Prompt)、MCP(Model Context Protocol)、Skills… 这些听起来高大上的术语到底是什么意思?它们之间有什么关系? 本文将用最通俗易懂的语言 + 生动比喻,带你一次性理清这些核心概念! 🚀 引言:AI正在改变我们“造物”的方式 随着大模型能力的飞速提升,AI不再仅仅是聊天问答工具。我们正在进入一个“AI驱动创造”的新时代: ✅ 用自然语言指挥AI写代码(Vibe Coding) ✅ 让AI像私人助理一样自主完成任务(AI Agent) ✅ 通过精准指令释放AI潜能(提示词工程) ✅ 赋予AI记忆与联网能力(MCP) ✅ 为AI安装“手脚”操作现实世界(Skills) 理解这些概念,是掌握下一代AI开发范式的关键! 🌈 一、Vibe Coding:用“感觉”写代码,告别996 大白话解释

从 “吹爆” 到 “冷静”:AIGC + 低代码为何难破企业级开发的硬骨头?

从 “吹爆” 到 “冷静”:AIGC + 低代码为何难破企业级开发的硬骨头?

目录 一、价值基础:AIGC与低代码的“天然契合”为何成立? 1.1 开发链路的“痛点互补” 1.2 开发门槛的“双重降低” 1.3 迭代效率的“指数提升” 二、道阻且长:AIGC+低代码融合的四大核心壁垒 2.1 需求层:意图理解的“模糊性陷阱” 2.2 开发层:逻辑生成的“严谨性缺陷” 规则冲突:看似合理的“逻辑陷阱” 边界缺失:未考虑的“异常场景” 2.3 集成层:系统对接的“兼容性壁垒” 2.4 运维层:性能与安全的“隐性风险” 三、理性破局:

【Claude Code解惑】深度评测:Claude Code vs. GitHub Copilot CLI,谁才是终端之王?

【Claude Code解惑】深度评测:Claude Code vs. GitHub Copilot CLI,谁才是终端之王?

深度评测:Claude Code vs. GitHub Copilot CLI,谁才是终端之王? 目录 1. 引言与背景 2. 原理解释(深入浅出) 3. 10分钟快速上手(可复现) 4. 代码实现与工程要点 5. 应用场景与案例 6. 实验设计与结果分析 7. 性能分析与技术对比 8. 消融研究与可解释性 9. 可靠性、安全与合规 10. 工程化与生产部署 11. 常见问题与解决方案(FAQ) 12. 创新性与差异性 13. 局限性与开放挑战 14. 未来工作与路线图 15. 扩展阅读与资源 16. 图示与交互 17. 术语表与速查表 18. 互动与社区 0.