概述:智能家居控制中心的核心价值
随着物联网技术的快速发展,智能家居设备数量激增,用户迫切需要统一的控制中心来管理各类设备。基于HarmonyOS的分布式能力,我们可以构建一个能够自动发现、统一管理、跨设备控制的智能家居控制中心。
本项目将实现以下核心功能:智能设备自动发现与认证、设备状态实时同步、跨设备控制指令下发、场景化智能联动。这些功能基于HarmonyOS的分布式设备管理 和分布式任务调度能力实现。
环境配置与项目初始化
开发环境要求
- DevEco Studio 4.0或更高版本
- HarmonyOS 5.0 SDK,API Version 12+
- 支持分布式能力的真机设备(手机、平板、智慧屏等)
创建项目与配置权限
在module.json5中配置智能家居控制中心所需的权限:
{
"module": {
"requestPermissions": [
{
"name": "ohos.permission.DISTRIBUTED_DATASYNC",
"reason": "$string:distributed_datasync_reason",
"usedScene": {
"ability": [".MainAbility"],
"when": "inuse"
}
},
{
"name": "ohos.permission.GET_DISTRIBUTED_DEVICE_INFO"
},
{
"name": "ohos.permission.ACCESS_SERVICE_DM",
"reason": "用于设备发现和认证"
},
{
"name": "ohos.permission.DISCOVER_HARDWARE",
"reason": "用于发现智能家居设备"
}
]
}
}
项目架构设计
分层架构规划
entry/src/main/ets/
├── common
│ ├── constants
│ └── utils
├── model
│ ├── DeviceInfo.ets # 设备信息模型
│ └── SceneInfo.ets # 场景信息模型
├── pages
│ ├── DeviceListPage.ets # 设备列表页
│ ├── DeviceDetailPage.ets # 设备详情页
│ └── SceneManagePage.ets # 场景管理页
├── view
│ ├── DeviceCard.ets # 设备卡片组件
│ ├── SceneCard.ets # 场景卡片组件
│ └── ControlPanel.ets # 控制面板组件
├── viewmodel
│ ├── DeviceManager.ets # 设备管理视图模型
│ └── SceneManager.ets # 场景管理视图模型
└── service
├── DeviceService.ets # 设备服务
└── DistributedService.ets # 分布式服务
设备信息模型设计
定义统一的设备数据模型,支持多种类型的智能家居设备:
// model/DeviceInfo.ets
export enum DeviceType {
LIGHT = 'light',
THERMOSTAT = 'thermostat',
PLUG = 'plug',
SENSOR = 'sensor',
CAMERA = 'camera'
}
export enum DeviceStatus {
ONLINE = 'online',
OFFLINE = 'offline',
BUSY = 'busy'
}
export class DeviceInfo {
deviceId: string = '';
deviceName: string = '';
deviceType: DeviceType = DeviceType.LIGHT;
status: DeviceStatus = DeviceStatus.OFFLINE;
capabilities: string[] = []; // 设备能力列表
room: string = ''; // 所属房间
lastSeen: number = 0; // 最后在线时间
isDistributed: boolean = false; // 是否支持分布式控制
properties: Map<string, any> = new Map(); // 设备属性
constructor(data?: any) {
if (data) {
this.deviceId = data.deviceId || '';
this.deviceName = data.deviceName || '';
this.deviceType = data.deviceType || DeviceType.LIGHT;
this.status = data.status || DeviceStatus.OFFLINE;
this.capabilities = data.capabilities || [];
this.room = data.room || '';
this.isDistributed = data.isDistributed || false;
if (data.properties) {
Object.keys(data.properties).forEach(key => {
this.properties.set(key, data.properties[key]);
});
}
}
}
// 更新设备属性
updateProperty(key: string, value: any): void {
this.properties.set(key, value);
}
// 获取设备属性
getProperty(key: string): any {
return this.properties.get(key);
}
// 转换为可序列化对象
toObject(): any {
const obj: any = {
deviceId: this.deviceId,
deviceName: this.deviceName,
deviceType: this.deviceType,
status: this.status,
capabilities: this.capabilities,
room: this.room,
lastSeen: this.lastSeen,
isDistributed: this.isDistributed
};
// 转换Map为普通对象
const props: any = {};
this.properties.forEach((value, key) => {
props[key] = value;
});
obj.properties = props;
return obj;
}
}
设备发现与管理服务
设备发现服务实现
// service/DeviceService.ets
import deviceManager from '@ohos.distributedHardware.deviceManager';
export class DeviceService {
private deviceMag: deviceManager.DeviceManager;
private discoveredDevices: deviceManager.DeviceInfo[] = [];
private trustedDevices: deviceManager.DeviceInfo[] = [];
// 初始化设备管理服务
async initialize(): Promise<void> {
return new Promise((resolve, reject) => {
deviceManager.createDeviceManager('com.example.smarthome', (err, data) => {
if (err) {
console.error('创建设备管理器失败:', err);
reject(err);
return;
}
this.deviceMag = data;
// 注册设备状态监听
this.registerDeviceListeners();
// 获取已信任设备列表
this.getTrustedDevices();
resolve();
});
});
}
// 注册设备状态监听器
private registerDeviceListeners(): void {
// 监听设备发现
this.deviceMag.on('deviceFound', (data) => {
this.onDeviceFound(data);
});
// 监听设备离线
this.deviceMag.on('deviceOffline', (data) => {
this.onDeviceOffline(data);
});
// 监听设备状态变化
this.deviceMag.on('deviceStateChange', (data) => {
this.onDeviceStateChange(data);
});
}
// 开始设备发现
startDiscovery(): void {
if (!this.deviceMag) {
console.error('设备管理器未初始化');
return;
}
try {
const discoverParams = {
// 发现智能家居设备
deviceFilter: ['light', 'thermostat', 'plug', 'sensor'],
// 5分钟超时
timeout: 300000
};
this.deviceMag.startDeviceDiscovery(discoverParams);
console.info('开始设备发现');
} catch (error) {
console.error('启动设备发现失败:', error);
}
}
// 停止设备发现
stopDiscovery(): void {
if (this.deviceMag) {
this.deviceMag.stopDeviceDiscovery();
console.info('停止设备发现');
}
}
// 设备发现回调
private onDeviceFound(data: deviceManager.DeviceInfo): void {
const existingIndex = this.discoveredDevices.findIndex(device =>
device.deviceId === data.deviceId
);
if (existingIndex === -1) {
this.discoveredDevices.push(data);
console.info(`发现新设备: ${data.deviceName}, ID: ${data.deviceId}`);
// 通知UI更新
this.notifyDeviceUpdate();
}
}
// 获取可信设备列表
private getTrustedDevices(): void {
try {
this.trustedDevices = this.deviceMag.getTrustedDeviceListSync();
console.info(`获取到 ${this.trustedDevices.length} 个可信设备`);
} catch (error) {
console.error('获取可信设备列表失败:', error);
}
}
// 设备认证
async authenticateDevice(deviceId: string): Promise<boolean> {
return new Promise((resolve) => {
try {
this.deviceMag.authenticateDevice(deviceId, (err, data) => {
if (err) {
console.error('设备认证失败:', err);
resolve(false);
return;
}
console.info('设备认证成功');
resolve(true);
});
} catch (error) {
console.error('设备认证异常:', error);
resolve(false);
}
});
}
// 通知UI更新
private notifyDeviceUpdate(): void {
// 通过AppStorage或EventHub通知UI层
AppStorage.setOrCreate('discoveredDevices', this.discoveredDevices);
AppStorage.setOrCreate('trustedDevices', this.trustedDevices);
}
}
设备列表页面实现
多端适配的设备列表布局
// pages/DeviceListPage.ets
@Entry
@Component
struct DeviceListPage {
@State currentTab: number = 0;
@StorageLink('discoveredDevices') discoveredDevices: deviceManager.DeviceInfo[] = [];
@StorageLink('trustedDevices') trustedDevices: deviceManager.DeviceInfo[] = [];
@State isLoading: boolean = true;
private deviceService: DeviceService = new DeviceService();
async aboutToAppear() {
await this.deviceService.initialize();
this.deviceService.startDiscovery();
this.isLoading = false;
}
aboutToDisappear() {
this.deviceService.stopDiscovery();
}
build() {
Column() {
// 顶部标题和搜索栏
this.buildHeader()
// 标签页
Tabs({ index: this.currentTab }) {
// 全部设备标签页
TabContent() {
this.buildAllDevicesTab()
}.tabBar('全部设备')
// 按房间分类标签页
TabContent() {
this.buildRoomsTab()
}.tabBar('房间')
// 场景标签页
TabContent() {
this.buildScenesTab()
}.tabBar('场景')
}
.onChange((index: number) => {
this.currentTab = index;
})
.layoutWeight(1)
}
.height('100%')
.width('100%')
.backgroundColor('#F5F5F5')
}
@Builder
buildHeader() {
Column() {
Row() {
Text('智能家居控制中心')
.fontSize(24)
.fontWeight(FontWeight.Bold)
.layoutWeight(1)
Button('扫描')
.fontSize(14)
.onClick(() => {
this.deviceService.startDiscovery();
})
}
.padding(16)
.width('100%')
// 搜索栏
TextInput({ placeholder: '搜索设备...' })
.width('90%')
.height(40)
.backgroundColor(Color.White)
.padding(8)
.margin({ bottom: 16 })
.borderRadius(20)
}
.backgroundColor(Color.White)
}
@Builder
buildAllDevicesTab() {
if (this.isLoading) {
LoadingProgress()
.width(50)
.height(50)
.margin({ top: 100 })
} else if (this.trustedDevices.length === 0) {
this.buildEmptyState()
} else {
GridRow({
columns: {
sm: 4,
md: 8,
lg: 12
},
breakpoints: {
value: ['320vp', '600vp', '840vp']
},
gutter: { x: 12, y: 12 }
}) {
GridCol({
span: { sm: 4, md: 8, lg: 12 }
}) {
List({ space: 12 }) {
ForEach(this.trustedDevices, (device: deviceManager.DeviceInfo) => {
ListItem() {
DeviceCard({ device: device })
.onClick(() => {
this.navigateToDetail(device);
})
}
}, (device: deviceManager.DeviceInfo) => device.deviceId)
}
.width('100%')
.layoutWeight(1)
}
}
.padding(16)
}
}
@Builder
buildEmptyState() {
Column() {
Image($rawfile('ic_empty_devices'))
.width(120)
.height(120)
.margin({ bottom: 24 })
Text('未发现设备')
.fontSize(18)
.fontColor('#666666')
.margin({ bottom: 8 })
Text('请确保设备已开启并在同一网络下')
.fontSize(14)
.fontColor('#999999')
.margin({ bottom: 24 })
Button('重新扫描')
.backgroundColor('#0A59F7')
.fontColor(Color.White)
.onClick(() => {
this.deviceService.startDiscovery();
})
}
.width('100%')
.height(400)
.justifyContent(FlexAlign.Center)
}
private navigateToDetail(device: deviceManager.DeviceInfo): void {
router.pushUrl({
url: 'pages/DeviceDetailPage',
params: { deviceId: device.deviceId }
});
}
}
设备控制卡片组件
可复用的设备控制UI
// view/DeviceCard.ets
@Component
export struct DeviceCard {
@Prop device: deviceManager.DeviceInfo;
@State isConnected: boolean = false;
build() {
Column() {
// 设备图标和状态
Row() {
this.buildDeviceIcon()
Column() {
Text(this.device.deviceName)
.fontSize(16)
.fontColor('#000000')
.maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis })
Text(this.isConnected ? '在线' : '离线')
.fontSize(12)
.fontColor(this.isConnected ? '#00B96B' : '#999999')
}
.layoutWeight(1)
.margin({ left: 12 })
// 连接状态指示器
Circle({ width: 8, height: 8 })
.fill(this.isConnected ? '#00B96B' : '#FF4D4F')
.margin({ right: 8 })
}
.width('100%')
.margin({ bottom: 16 })
// 设备控制区域
this.buildControlPanel()
}
.padding(16)
.backgroundColor(Color.White)
.borderRadius(12)
.shadow({ radius: 4, color: '#10000000', offsetX: 0, offsetY: 2 })
.width('100%')
.height(180)
.onClick(() => {
// 处理设备点击事件
})
}
@Builder
buildDeviceIcon() {
const iconConfig = this.getDeviceIconConfig();
Column() {
Image(iconConfig.icon)
.width(32)
.height(32)
.objectFit(ImageFit.Contain)
}
.width(56)
.height(56)
.backgroundColor(iconConfig.bgColor)
.borderRadius(28)
.justifyContent(FlexAlign.Center)
}
@Builder
buildControlPanel() {
const deviceType = this.getDeviceType();
if (deviceType === DeviceType.LIGHT) {
this.buildLightControl()
} else if (deviceType === DeviceType.THERMOSTAT) {
this.buildThermostatControl()
} else if (deviceType === DeviceType.PLUG) {
this.buildPlugControl()
} else {
this.buildDefaultControl()
}
}
@Builder
buildLightControl() {
Row() {
Toggle({ type: ToggleType.Checkbox, isOn: false })
.onChange((isOn) => {
this.controlDevice(isOn ? 'turnOn' : 'turnOff');
})
Text('开关')
.fontSize(14)
.margin({ left: 8 })
.layoutWeight(1)
Slider({ value: 50, min: 0, max: 100, style: SliderStyle.OutSet })
.onChange((value) => {
this.controlDevice('setBrightness', { brightness: value });
})
.width(80)
}
.width('100%')
.alignItems(VerticalAlign.Center)
}
private getDeviceType(): DeviceType {
// 根据设备信息判断设备类型
// 实际项目中应从设备属性中获取
if (this.device.deviceName.includes('灯') || this.device.deviceName.includes('Light')) {
return DeviceType.LIGHT;
} else if (this.device.deviceName.includes('空调') || this.device.deviceName.includes('Thermostat')) {
return DeviceType.THERMOSTAT;
} else if (this.device.deviceName.includes('插座') || this.device.deviceName.includes('Plug')) {
return DeviceType.PLUG;
}
return DeviceType.LIGHT;
}
private getDeviceIconConfig(): { icon: Resource, bgColor: Resource } {
const deviceType = this.getDeviceType();
switch (deviceType) {
case DeviceType.LIGHT:
return {
icon: $r('app.media.ic_light'),
bgColor: $r('app.color.light_bg')
};
case DeviceType.THERMOSTAT:
return {
icon: $r('app.media.ic_thermostat'),
bgColor: $r('app.color.thermostat_bg')
};
case DeviceType.PLUG:
return {
icon: $r('app.media.ic_plug'),
bgColor: $r('app.color.plug_bg')
};
default:
return {
icon: $r('app.media.ic_device'),
bgColor: $r('app.color.default_bg')
};
}
}
private controlDevice(command: string, params?: any): void {
// 发送设备控制指令
console.info(`控制设备: ${this.device.deviceId}, 命令: ${command}`, params);
}
}
分布式设备控制服务
跨设备控制指令下发
// service/DistributedService.ets
import distributedDeviceManager from '@ohos.distributedHardware.deviceManager';
export class DistributedService {
private deviceMag: distributedDeviceManager.DeviceManager;
// 发送控制指令到设备
async sendControlCommand(deviceId: string, command: string, params?: any): Promise<boolean> {
return new Promise((resolve) => {
try {
const want = {
deviceId: deviceId,
bundleName: 'com.example.smarthome.device',
abilityName: 'DeviceControlAbility',
parameters: {
command: command,
params: params || {},
timestamp: new Date().getTime()
}
};
featureAbility.startAbility(want)
.then(() => {
console.info(`控制指令发送成功: ${command} to ${deviceId}`);
resolve(true);
})
.catch((error) => {
console.error(`控制指令发送失败: ${error}`);
resolve(false);
});
} catch (error) {
console.error('发送控制指令异常:', error);
resolve(false);
}
});
}
// 批量控制设备
async batchControlDevices(deviceIds: string[], command: string, params?: any): Promise<boolean[]> {
const results: Promise<boolean>[] = deviceIds.map(deviceId =>
this.sendControlCommand(deviceId, command, params)
);
return Promise.all(results);
}
// 创建设备组
async createDeviceGroup(deviceIds: string[], groupName: string): Promise<string> {
return new Promise((resolve) => {
try {
const groupId = this.generateGroupId();
// 保存设备组信息到分布式数据
this.saveDeviceGroup(groupId, deviceIds, groupName)
.then(() => {
console.info(`设备组创建成功: ${groupName}`);
resolve(groupId);
})
.catch((error) => {
console.error('设备组创建失败:', error);
resolve('');
});
} catch (error) {
console.error('创建设备组异常:', error);
resolve('');
}
});
}
private generateGroupId(): string {
return `group_${new Date().getTime()}_${Math.random().toString(36).substr(2, 9)}`;
}
private async saveDeviceGroup(groupId: string, deviceIds: string[], groupName: string): Promise<void> {
// 使用分布式数据管理保存设备组信息
const kvManager = distributedData.createKVManager({
bundleName: 'com.example.smarthome',
userInfo: {
userId: 'defaultUser',
userType: distributedData.UserType.SAME_USER_ID
}
});
const kvStore = await kvManager.getKVStore('device_groups', {
createIfMissing: true
});
const groupInfo = {
groupId: groupId,
groupName: groupName,
deviceIds: deviceIds,
createTime: new Date().getTime()
};
await kvStore.put(groupId, JSON.stringify(groupInfo));
}
}
场景化智能联动
智能场景管理
// model/SceneInfo.ets
export enum SceneTriggerType {
TIME = 'time', // 时间触发
DEVICE = 'device', // 设备状态触发
MANUAL = 'manual' // 手动触发
}
export class SceneAction {
deviceId: string = '';
command: string = '';
params: any = {};
constructor(deviceId: string, command: string, params?: any) {
this.deviceId = deviceId;
this.command = command;
this.params = params || {};
}
}
export class SceneInfo {
sceneId: string = '';
sceneName: string = '';
triggerType: SceneTriggerType = SceneTriggerType.MANUAL;
triggerCondition: any = {}; // 触发条件
actions: SceneAction[] = []; // 场景动作
isEnabled: boolean = true;
createTime: number = 0;
constructor(data?: any) {
if (data) {
this.sceneId = data.sceneId || this.generateSceneId();
this.sceneName = data.sceneName || '';
this.triggerType = data.triggerType || SceneTriggerType.MANUAL;
this.triggerCondition = data.triggerCondition || {};
this.actions = (data.actions || []).map((action: any) =>
new SceneAction(action.deviceId, action.command, action.params)
);
this.isEnabled = data.isEnabled !== undefined ? data.isEnabled : true;
this.createTime = data.createTime || new Date().getTime();
}
}
private generateSceneId(): string {
return `scene_${new Date().getTime()}_${Math.random().toString(36).substr(2, 9)}`;
}
// 添加场景动作
addAction(deviceId: string, command: string, params?: any): void {
this.actions.push(new SceneAction(deviceId, command, params));
}
// 执行场景
async execute(): Promise<boolean[]> {
const distributedService = new DistributedService();
const results: Promise<boolean>[] = [];
for (const action of this.actions) {
results.push(
distributedService.sendControlCommand(
action.deviceId,
action.command,
action.params
)
);
}
return Promise.all(results);
}
}
多端适配与响应式布局
基于栅格系统的布局适配
// common/constants/Breakpoints.ets
export class CommonConstants {
// 断点定义
static readonly BREAKPOINT_SM: string = 'sm'; // 小屏设备 < 600vp
static readonly BREAKPOINT_MD: string = 'md'; // 中屏设备 600vp - 840vp
static readonly BREAKPOINT_LG: string = 'lg'; // 大屏设备 > 840vp
// 设备类型
static readonly DEVICE_TYPE_PHONE: string = 'phone';
static readonly DEVICE_TYPE_TABLET: string = 'tablet';
static readonly DEVICE_TYPE_TV: string = 'tv';
static readonly DEVICE_TYPE_WEARABLE: string = 'wearable';
// 布局配置
static readonly GRID_COLUMNS_SM: number = 4;
static readonly GRID_COLUMNS_MD: number = 8;
static readonly GRID_COLUMNS_LG: number = 12;
static getCurrentBreakpoint(): string {
const screenWidth = display.getDefaultDisplaySync().width;
if (screenWidth < 600) {
return this.BREAKPOINT_SM;
} else if (screenWidth < 840) {
return this.BREAKPOINT_MD;
} else {
return this.BREAKPOINT_LG;
}
}
static getGridColumns(): number {
const breakpoint = this.getCurrentBreakpoint();
switch (breakpoint) {
case this.BREAKPOINT_SM:
return this.GRID_COLUMNS_SM;
case this.BREAKPOINT_MD:
return this.GRID_COLUMNS_MD;
case this.BREAKPOINT_LG:
return this.GRID_COLUMNS_LG;
default:
return this.GRID_COLUMNS_MD;
}
}
}
测试与优化建议
分布式功能测试要点
- 设备发现测试:验证在不同网络环境下设备的发现能力
- 控制指令测试:测试控制指令的发送成功率和响应时间
- 跨设备同步测试:验证设备状态在多设备间的同步一致性
- 性能测试:测试大量设备同时在线时的系统性能
性能优化建议
// 设备状态缓存优化
export class DeviceStateCache {
private static instance: DeviceStateCache;
private cache: Map<string, any> = new Map();
private maxSize: number = 1000;
private ttl: number = 300000; // 5分钟
static getInstance(): DeviceStateCache {
if (!DeviceStateCache.instance) {
DeviceStateCache.instance = new DeviceStateCache();
}
return DeviceStateCache.instance;
}
set(key: string, value: any): void {
if (this.cache.size >= this.maxSize) {
this.evictOldest();
}
this.cache.set(key, {
value: value,
timestamp: new Date().getTime()
});
}
get(key: string): any {
const item = this.cache.get(key);
if (!item) return null;
// 检查是否过期
if (new Date().getTime() - item.timestamp > this.ttl) {
this.cache.delete(key);
return null;
}
return item.value;
}
private evictOldest(): void {
let oldestKey: string = '';
let oldestTime: number = Infinity;
this.cache.forEach((value, key) => {
if (value.timestamp < oldestTime) {
oldestTime = value.timestamp;
oldestKey = key;
}
});
if (oldestKey) {
this.cache.delete(oldestKey);
}
}
}
项目总结与扩展方向
本智能家居控制中心项目展示了HarmonyOS在物联网领域的强大能力。通过本项目,你已掌握:
- 分布式设备管理的完整实现流程
- 跨设备控制指令的下发机制
- 场景化智能联动的业务逻辑设计
- 多端适配的响应式布局方案
扩展功能建议
- 实现语音控制集成(集成语音助手)
- 添加能耗统计功能
- 实现自动化规则引擎
- 添加设备固件OTA升级功能
- 实现家庭安防联动功能
这个项目为智能家居生态开发提供了坚实基础,下一步可以探索更复杂的AIoT场景集成和商业化应用部署。