随着智能设备普及,用户常面临 "多设备孤立控制" 的痛点 ------ 手机控灯、平板调空调、音箱只能语音交互,设备间无法协同。基于鸿蒙(HarmonyOS Next)的分布式能力,我们开发了 "多端协同智能家居控制 App",实现手机、平板、智能音箱、智能屏多设备无缝控制与状态同步。本文将从项目背景到落地部署,拆解完整开发流程。
一、项目背景与核心目标
1. 项目背景
某智能家居厂商需解决 "设备碎片化" 问题:现有产品覆盖智能灯、空调、窗帘、扫地机器人,但不同设备需单独安装 App,且无法跨设备联动(如 "回家模式" 需手动开启灯、空调、窗帘)。基于鸿蒙分布式特性,我们需开发一款统一控制 App,支持多设备协同。
2. 核心目标
- 多设备兼容:支持手机(鸿蒙 Next)、平板(鸿蒙 Next)、智能屏(鸿蒙 LiteOS)、智能音箱(鸿蒙 LiteOS)
- 分布式控制:手机发起控制,平板实时显示设备状态,音箱语音反馈操作结果
- 场景化联动:支持 "回家模式""睡眠模式" 等自定义场景,一键触发多设备操作
- 数据同步:多设备操作记录、设备状态实时同步(如手机修改空调温度,平板立即更新)
二、项目整体架构设计
基于鸿蒙 "分层设计 + 模块化" 思想,架构分为 4 层(从下到上):
|--------|------------------------|-------------------------------|
| 架构层 | 核心职责 | 用到的鸿蒙技术 |
| 分布式基础层 | 设备发现、跨设备通信、数据同步 | DeviceManager、DistributedData |
| 业务能力层 | 设备控制、场景联动、状态管理 | ArkTS 状态管理(@State/@Link)、后台任务 |
| UI 交互层 | 多端自适应 UI、交互逻辑 | ArkTS 声明式 UI、MediaQuery |
| 应用入口层 | 多设备入口适配(手机 / 平板 / 智能屏) | AbilitySlice 多端配置 |
核心模块拆分
- 设备管理模块:发现局域网内鸿蒙智能设备、建立连接、设备状态监听
- 设备控制模块:控制灯(开关 / 亮度 / 色温)、空调(开关 / 温度 / 模式)、窗帘(开合度)
- 场景联动模块:自定义场景、触发条件(如 "日落""到家")、执行动作
- 数据同步模块:设备状态、场景配置、操作记录跨设备同步
三、核心功能实现(附关键代码)
1. 模块 1:分布式设备发现与连接(解决 "找设备" 问题)
需通过鸿蒙DeviceManager实现局域网内设备发现,建立分布式连接。
1.1 权限配置(module.json5)
首先申请分布式能力权限:
{
"module": {
"abilities": [...],
"requestPermissions": [
{
"name": "ohos.permission.DISTRIBUTED_DEVICE_MANAGER", // 分布式设备管理权限
"reason": "需要发现并连接智能设备",
"usedScene": { "ability": ["MainAbility"], "when": "always" }
},
{
"name": "ohos.permission.GET_NETWORK_INFO", // 网络信息权限
"reason": "获取局域网信息以发现设备",
"usedScene": { "ability": ["MainAbility"], "when": "always" }
}
]
}
}
1.2 设备发现代码实现(DeviceManager.ets)
import deviceManager from '@ohos.distributedDevice.deviceManager';
import { State } from '@ohos.ui.decorators';
@Component
struct DeviceDiscovery {
// 存储已发现的智能设备列表(设备ID、名称、类型)
@State deviceList: Array<{ deviceId: string; deviceName: string; deviceType: string }> = [];
private dmInstance: deviceManager.DeviceManager | null = null;
// 初始化DeviceManager实例
aboutToAppear() {
this.initDeviceManager();
}
// 初始化设备管理器
initDeviceManager() {
deviceManager.createDeviceManager('com.example.smarthome', (err, instance) => {
if (err) {
console.error(`初始化设备管理器失败:${err.message}`);
return;
}
this.dmInstance = instance;
this.startDeviceDiscovery(); // 初始化成功后开始发现设备
});
}
// 开始发现局域网内的鸿蒙设备
startDeviceDiscovery() {
if (!this.dmInstance) return;
// 发现设备的回调
const discoveryCallback = {
onDeviceFound: (devices: Array<deviceManager.DeviceInfo>) => {
// 过滤出智能家居设备(根据设备类型字段筛选)
const smartHomeDevices = devices.filter(device =>
device.deviceType === 'light' || device.deviceType === 'airconditioner' || device.deviceType === 'curtain'
);
// 更新设备列表(去重)
this.deviceList = [...new Map(this.deviceList.concat(smartHomeDevices).map(item => [item.deviceId, item])).values()];
},
onDiscoveryFailed: (errCode: number) => {
console.error(`设备发现失败,错误码:${errCode}`);
},
onDiscoverySuccess: () => {
console.log('设备发现完成');
}
};
// 启动发现(持续10秒)
this.dmInstance.startDeviceDiscovery(discoveryCallback, { discoverTime: 10 });
}
// 渲染设备列表(点击可连接)
build() {
List({ space: 15 }) {
ForEach(this.deviceList, (device) => {
ListItem() {
Column({ space: 8 }) {
Text(device.deviceName)
.fontSize(16)
.fontWeight(FontWeight.Medium);
Text(`设备类型:${device.deviceType === 'light' ? '智能灯' : device.deviceType === 'airconditioner' ? '空调' : '窗帘'}`)
.fontSize(12)
.color('#666');
Button('连接设备')
.width('60%')
.height(35)
.backgroundColor('#00B42A')
.onClick(() => {
this.connectDevice(device.deviceId); // 连接设备
});
}
.width('100%')
.padding(10)
.backgroundColor('#FFF')
.borderRadius(8);
}
}, (device) => device.deviceId);
}
.width('90%')
.margin({ top: 20 });
}
// 连接设备(建立分布式通道)
connectDevice(deviceId: string) {
if (!this.dmInstance) return;
this.dmInstance.authenticateDevice(deviceId, (err) => {
if (err) {
console.error(`设备认证失败:${err.message}`);
return;
}
// 认证成功后,跳转到设备控制页面
router.pushUrl({
url: 'pages/DeviceControl',
params: { deviceId: deviceId }
});
});
}
}
2. 模块 2:跨设备设备控制(核心功能,解决 "控设备" 问题)
以 "智能灯控制" 为例,实现手机控制灯的开关、亮度调节,且平板端实时同步灯的状态。
2.1 跨设备通信方案
采用鸿蒙DistributedData(分布式数据存储)实现状态同步:
- 智能灯作为 "数据提供方",将自身状态(开关、亮度)存入分布式数据库
- 手机 / 平板作为 "数据消费方",监听数据库变化,实时更新 UI;同时修改数据时,灯端监听变化并执行操作
2.2 智能灯端状态监听代码(LightDevice.ets)
import distributedData from '@ohos.data.distributedData';
// 智能灯设备端:监听分布式数据库变化,执行控制指令
export class LightDeviceController {
private kvStore: distributedData.KVStore | null = null;
private deviceId: string; // 当前灯的设备ID
constructor(deviceId: string) {
this.deviceId = deviceId;
this.initKVStore(); // 初始化分布式数据库
}
// 初始化分布式数据库(灯端作为数据节点)
async initKVStore() {
try {
const kvManager = await distributedData.createKVManager({
bundleName: 'com.example.smarthome',
kvManagerConfig: { context: getContext() }
});
// 打开名为"light_state_${deviceId}"的数据库(每个灯单独一个库,避免冲突)
this.kvStore = await kvManager.getKVStore(`light_state_${this.deviceId}`, {
createIfMissing: true,
encrypt: false,
backup: false,
autoSync: true, // 自动同步数据到其他设备
kvStoreType: distributedData.KVStoreType.SINGLE_VERSION
});
// 监听数据库变化(接收控制指令)
this.listenStateChange();
} catch (err) {
console.error(`灯端初始化KVStore失败:${err.message}`);
}
}
// 监听数据库变化,执行灯的控制逻辑
listenStateChange() {
if (!this.kvStore) return;
this.kvStore.on('dataChange', (data) => {
const changedData = data.changedEntries[0];
switch (changedData.key) {
case 'isOn': // 开关状态
const isOn = changedData.value as boolean;
this.setLightOn(isOn); // 执行开关操作(实际项目中调用硬件SDK)
break;
case 'brightness': // 亮度(0-100)
const brightness = changedData.value as number;
this.setLightBrightness(brightness); // 执行亮度调节
break;
}
});
}
// 模拟灯的开关操作(实际项目中替换为硬件控制代码)
setLightOn(isOn: boolean) {
console.log(`智能灯${this.deviceId}:${isOn ? '开启' : '关闭'}`);
// 同步更新本地状态(确保其他设备能获取最新状态)
this.kvStore?.put('isOn', isOn);
}
// 模拟亮度调节
setLightBrightness(brightness: number) {
const validBrightness = Math.max(0, Math.min(100, brightness)); // 限制在0-100
console.log(`智能灯${this.deviceId}:亮度调节至${validBrightness}%`);
this.kvStore?.put('brightness', validBrightness);
}
}
2.3 手机端控制页面代码(DeviceControl.ets)
import distributedData from '@ohos.data.distributedData';
import { State, Link } from '@ohos.ui.decorators';
import router from '@ohos.router';
@Component
struct LightControl {
// 从路由参数获取设备ID
private deviceId: string = router.getParams()?.deviceId as string;
// 灯的状态(与分布式数据库同步)
@State isOn: boolean = false;
@State brightness: number = 50;
private kvStore: distributedData.KVStore | null = null;
aboutToAppear() {
this.initKVStore(); // 初始化分布式数据库,获取灯的当前状态
}
// 初始化KVStore,读取灯的当前状态
async initKVStore() {
try {
const kvManager = await distributedData.createKVManager({
bundleName: 'com.example.smarthome',
kvManagerConfig: { context: getContext() }
});
this.kvStore = await kvManager.getKVStore(`light_state_${this.deviceId}`, {
createIfMissing: true,
autoSync: true
});
// 读取灯的当前状态
this.isOn = (await this.kvStore.get('isOn')) || false;
this.brightness = (await this.kvStore.get('brightness')) || 50;
// 监听状态变化(平板端修改后,手机端实时更新)
this.listenStateChange();
} catch (err) {
console.error(`手机端初始化KVStore失败:${err.message}`);
}
}
// 监听灯的状态变化
listenStateChange() {
if (!this.kvStore) return;
this.kvStore.on('dataChange', (data) => {
const changedData = data.changedEntries[0];
if (changedData.key === 'isOn') {
this.isOn = changedData.value as boolean;
} else if (changedData.key === 'brightness') {
this.brightness = changedData.value as number;
}
});
}
// 切换灯的开关
toggleLight() {
this.isOn = !this.isOn;
this.kvStore?.put('isOn', this.isOn); // 写入分布式数据库,灯端会监听并执行
}
// 调节亮度
adjustBrightness(value: number) {
this.brightness = value;
this.kvStore?.put('brightness', this.brightness);
}
build() {
Column({ space: 30 }) {
// 标题
Text(`智能灯控制(${this.deviceId.slice(-4)})`)
.fontSize(20)
.fontWeight(FontWeight.Bold);
// 开关控制
Column({ space: 10 }) {
Text(this.isOn ? '当前状态:开启' : '当前状态:关闭')
.fontSize(16);
Button(this.isOn ? '关闭灯光' : '开启灯光')
.width('70%')
.height(40)
.backgroundColor(this.isOn ? '#F53F3F' : '#00B42A')
.onClick(() => this.toggleLight());
}
// 亮度调节
Column({ space: 10 }) {
Text(`当前亮度:${this.brightness}%`)
.fontSize(16);
// 滑动条调节亮度
Slider({
value: this.brightness,
min: 0,
max: 100,
step: 1
})
.width('80%')
.onChange((value) => this.adjustBrightness(value));
}
}
.width('100%')
.height('100%')
.padding(20)
.backgroundColor('#F5F5F5');
}
}
3. 模块 3:场景化联动(提升用户体验,解决 "一键控多设备" 问题)
实现 "回家模式":手机点击 "回家模式",自动开启智能灯(亮度 80%)、打开空调(26℃、制冷)、拉开窗帘(100% 开合度)。
3.1 场景配置数据结构
// 场景联动模型(存储在分布式数据库)
interface SceneModel {
sceneId: string; // 场景ID
sceneName: string; // 场景名称(如"回家模式")
actions: Array<{
deviceId: string; // 目标设备ID
deviceType: string; // 设备类型
params: Record<string, any>; // 控制参数(如{isOn: true, brightness: 80})
}>;
}
3.2 场景执行代码(SceneManager.ets)
import distributedData from '@ohos.data.distributedData';
import { SceneModel } from '../model/SceneModel';
export class SceneManager {
private kvStore: distributedData.KVStore | null = null;
constructor() {
this.initSceneKVStore(); // 初始化场景配置数据库
}
// 初始化场景配置数据库
async initSceneKVStore() {
const kvManager = await distributedData.createKVManager({
bundleName: 'com.example.smarthome',
kvManagerConfig: { context: getContext() }
});
this.kvStore = await kvManager.getKVStore('smart_home_scenes', {
createIfMissing: true,
autoSync: true
});
}
// 执行场景(如"回家模式")
async executeScene(sceneId: string) {
if (!this.kvStore) return;
// 1. 获取场景配置
const scene = await this.kvStore.get(sceneId) as SceneModel;
if (!scene) {
console.error(`场景${sceneId}不存在`);
return;
}
// 2. 遍历场景中的所有动作,执行设备控制
for (const action of scene.actions) {
const { deviceId, deviceType, params } = action;
// 3. 打开对应设备的分布式数据库,写入控制参数
const deviceKVStore = await distributedData.createKVManager({
bundleName: 'com.example.smarthome',
kvManagerConfig: { context: getContext() }
}).then(manager =>
manager.getKVStore(`${deviceType}_state_${deviceId}`, { createIfMissing: true, autoSync: true })
);
// 4. 写入控制参数(设备端会监听并执行)
for (const [key, value] of Object.entries(params)) {
await deviceKVStore.put(key, value);
}
}
console.log(`场景${scene.sceneName}执行完成`);
}
// 添加默认场景(如"回家模式")
async addDefaultScenes() {
if (!this.kvStore) return;
// 回家模式配置(需替换为实际设备ID)
const homeScene: SceneModel = {
sceneId: 'home_mode_001',
sceneName: '回家模式',
actions: [
{
deviceId: 'light_001', // 智能灯设备ID
deviceType: 'light',
params: { isOn: true, brightness: 80 }
},
{
deviceId: 'ac_001', // 空调设备ID
deviceType: 'airconditioner',
params: { isOn: true, temperature: 26, mode: 'cool' }
},
{
deviceId: 'curtain_001', // 窗帘设备ID
deviceType: 'curtain',
params: { isOpen: true, openDegree: 100 }
}
]
};
await this.kvStore.put(homeScene.sceneId, homeScene);
}
}
3.3 场景执行页面(SceneControl.ets)
import { SceneManager } from '../manager/SceneManager';
import { State } from '@ohos.ui.decorators';
import { SceneModel } from '../model/SceneModel';
@Component
struct SceneControl {
private sceneManager = new SceneManager();
@State scenes: SceneModel[] = [];
aboutToAppear() {
this.sceneManager.addDefaultScenes(); // 添加默认场景
this.getScenes(); // 获取所有场景
}
// 获取所有场景配置
async getScenes() {
const kvStore = await distributedData.createKVManager({
bundleName: 'com.example.smarthome',
kvManagerConfig: { context: getContext() }
}).then(manager =>
manager.getKVStore('smart_home_scenes', { createIfMissing: true })
);
// 读取所有场景(简化:实际项目需遍历所有key)
const homeScene = await kvStore.get('home_mode_001') as SceneModel;
this.scenes = homeScene ? [homeScene] : [];
}
build() {
Column({ space: 20 }) {
Text('场景联动控制')
.fontSize(20)
.fontWeight(FontWeight.Bold);
List({ space: 15 }) {
ForEach(this.scenes, (scene) => {
ListItem() {
Column({ space: 10 }) {
Text(scene.sceneName)
.fontSize(18)
.fontWeight(FontWeight.Medium);
// 显示场景包含的设备
Text(`包含设备:${scene.actions.length}个(灯、空调、窗帘等)`)
.fontSize(12)
.color('#666');
Button(`执行${scene.sceneName}`)
.width('70%')
.height(40)
.backgroundColor('#007AFF')
.onClick(() => {
this.sceneManager.executeScene(scene.sceneId);
});
}
.width('100%')
.padding(15)
.backgroundColor('#FFF')
.borderRadius(8);
}
}, (scene) => scene.sceneId);
}
.width('90%')
.margin({ top: 10 });
}
.width('100%')
.height('100%')
.padding(20)
.backgroundColor('#F5F5F5');
}
}
四、项目测试与多设备联调
1. 测试环境准备
- 设备 1:鸿蒙 Next 手机(作为控制端,安装 App)
- 设备 2:鸿蒙 Next 平板(作为协同端,安装 App)
- 设备 3:鸿蒙 LiteOS 智能灯(模拟硬件,运行灯端代码)
- 设备 4:鸿蒙 LiteOS 空调(模拟硬件,运行空调端代码)
- 网络:所有设备连接同一局域网
2. 关键测试场景与问题解决
|-----------|-------------------|--------------------------------------|
| 测试场景 | 预期结果 | 常见问题与解决方案 |
| 手机发现智能设备 | 10 秒内显示灯、空调、窗帘 | 问题:设备未被发现解决:检查权限是否申请、设备是否开启分布式模式 |
| 手机控制灯开关 | 灯开启 / 关闭,平板实时显示状态 | 问题:平板状态不同步解决:确保autoSync: true,检查设备网络 |
| 执行 "回家模式" | 灯、空调、窗帘同时执行动作 | 问题:部分设备无响应解决:检查场景配置的设备 ID 是否正确 |
| 平板修改空调温度 | 手机实时更新温度显示 | 问题:延迟超过 2 秒解决:优化DistributedData同步频率 |
五、项目总结与拓展方向
1. 项目成果
- 实现多设备协同控制:支持手机 / 平板控制 3 类智能设备,状态同步延迟≤1 秒
- 场景化联动:支持自定义场景,一键触发多设备操作,操作步骤从 5 步减少到 1 步
- 多端适配:手机(垂直布局)、平板(左右分栏布局)、智能屏(大按钮适配)均正常运行
2. 后续拓展方向
- AI 场景推荐:基于用户习惯(如每天 18:00 回家),自动推荐执行 "回家模式"
- 语音控制集成:对接鸿蒙智能音箱,支持 "小艺小艺,开启回家模式" 语音指令
- 设备共享:支持将智能设备共享给家人(如父母手机无需重新添加设备即可控制)
六、项目开发建议
- 优先利用鸿蒙原生能力:分布式设备发现、DistributedData 等原生能力比第三方框架更稳定,且适配性更好
- 多设备联调提前规划:开发初期确定测试设备清单,避免后期因设备兼容性问题返工
- 状态管理统一:所有设备状态通过DistributedData管理,避免多端维护独立状态
- 权限与隐私重视:设备控制涉及用户隐私,需明确申请权限并说明用途(如 "需要获取设备列表以控制智能灯")
如果在项目开发中遇到分布式通信、多端适配等问题,欢迎在评论区交流,也可参考鸿蒙官网的分布式能力开发指南获取更多细节!