【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

AI如何助力六花直装V8.3.9的自动化开发与测试

快速体验 1. 打开 InsCode(快马)平台 https://www.inscode.net 2. 输入框内输入如下内容: 使用AI模型分析六花直装V8.3.9的更新日志,自动生成代码补丁和测试用例。输入更新内容描述,AI自动识别关键功能点并生成对应的代码修改建议,包括新增模块的代码框架、API接口调整等。同时,AI可以生成自动化测试脚本,验证新功能的稳定性和兼容性。支持多种编程语言和测试框架,适用于快速迭代开发。 1. 点击'项目生成'按钮,等待项目生成完整后预览效果 AI如何助力六花直装V8.3.9的自动化开发与测试 最近在跟进六花直装V8.3.9版本的开发过程中,我发现AI辅助开发工具确实能大幅提升效率。特别是对于这种需要频繁迭代更新的项目,从代码生成到测试验证,AI都能提供很好的支持。下面分享下我的实际体验。 1. 更新日志的智能分析 每次版本更新都会有详细的更新日志,但人工阅读和分析这些内容需要花费不少时间。通过AI工具,可以快速提取关键功能点和修改内容。比如输入&

CodeBuddy Code + 腾讯混元打造“AI识菜通“

CodeBuddy Code + 腾讯混元打造“AI识菜通“

目录 CodeBuddy Code + 腾讯混元打造"AI识菜通" CodeBuddy Code使用指南 1. 背景信息 2. 下载安装 3. 登录 4. 测试 腾讯混元API接入指南 1. 开通腾讯混元大模型 2. 获取腾讯云密钥 3. 腾讯混元API文档 AI识菜通开发指南 1. 开发提示词 2. CodeBuddy.md开发文档 3. 全速开发 成果展示 1. 部署阶段 2. 首页 3. 设置API密钥 4. 识别菜单 5. 点餐进入购物车 CodeBuddy Code + 腾讯混元打造"AI识菜通" CodeBuddy

神的泪水-构建与解析:基于多AI模型并行的内容生成与对比分析工作流

神的泪水-构建与解析:基于多AI模型并行的内容生成与对比分析工作流

摘要 在人工智能迅猛发展的今天,大型语言模型(LLM)已成为内容创作、数据分析和自动化任务的核心驱动力。然而,不同模型在架构、训练数据和优化目标上的差异,导致其在处理相同任务时会产生风格、侧重点和准确性各不相同的输出。因此,如何高效、直观地对不同模型的输出进行横向对比,以选择最适合特定场景的模型,成为了一个亟待解决的课题。本文将详细拆解一个专为AI内容对比输出而设计的工作流,通过具体实例分析其构建逻辑、运行机制和应用价值,并进一步探讨其在模型评估、提示词工程优化及未来多智能体协作系统中的广阔前景。 1. 引言:从单一模型到多模型并行处理的范式转变 过去,我们与AI的交互多是“单线程”的:向一个特定的AI模型提出问题,然后接收并评估其返回的唯一答案。这种模式虽然直接,但存在明显的局限性。用户无法即时获知其他模型可能提供的不同见解或更优答案,评估过程也因此变得线性而低效。为了打破这一瓶颈,一种新的范式——多模型并行处理——应运而生。 多模型并行处理的核心思想是,将同一个输入或指令同时分发给多个不同的AI模型,并收集它们各自的输出。这种方法不仅能够实现对模型能力和特性的“同场竞技”

重磅官宣!Token 官方中文名定了——「词元」,AI 术语终于有了统一标准

今天(3月24日)科技圈迎来一个里程碑式的消息:国家数据局在国新办新闻发布会上正式官宣,AI 领域核心术语 Token 的中文标准译名,确定为「词元」✅ 从此,困扰业内多年的 Token 译名乱象,终于有了官方定论。 作为每天和大模型、AI 交互的从业者/爱好者,相信大家都有过这样的困扰:同样是 Token,在区块链里叫「代币」,在网络安全领域叫「令牌」,在大模型场景里,有人叫「标记」,有人干脆不翻译直接用英文,甚至还有「模元」「智元」等多种民间译法,跨场景沟通时经常出现理解偏差。 而这次官方定调「词元」,绝非简单的翻译统一,背后藏着对 AI 核心逻辑的精准解读,也预示着我国 AI 产业的规范化再进一步。 一、官方定名核心要点,必看! * 发布主体:国家数据局局长刘烈宏在国新办发布会、中国发展高层论坛上正式使用「