72小时极速上手OpenHarmony智能家居开发:从环境搭建到多设备联动全攻略

72小时极速上手OpenHarmony智能家居开发:从环境搭建到多设备联动全攻略

【免费下载链接】knowledge_demo_smart_home ​本仓库的样例都是基于智能家居,从客厅到卧室,从中控到sensor,开发者可以体验各种家居的开发样例,打造自己的家居体验,享受万物互联的快感。 【免费下载链接】knowledge_demo_smart_home 项目地址: https://gitcode.com/openharmony-sig/knowledge_demo_smart_home

你是否还在为智能家居设备碎片化开发烦恼?是否因配网复杂、协议不统一而放弃项目?本文将带你从零开始,72小时内掌握OpenHarmony智能家居开发全流程,完成从环境搭建到多设备联动的实战项目。读完本文你将获得:

  • 一套完整的OpenHarmony智能家居开发环境
  • 智能设备无感配网核心技术
  • 多设备联动场景开发能力
  • 数字管家应用全流程开发经验

一、项目架构与核心价值

OpenHarmony-SIG/knowledge_demo_smart_home项目提供了从设备端到应用端的完整智能家居解决方案,通过数字管家应用实现多设备统一管理与场景联动。项目采用分层架构设计,确保各模块解耦与可扩展性:

mermaid

1.1 核心功能模块

模块功能描述技术栈
FA应用设备控制、场景编排、用户管理ArkUI、JavaScript
Server服务设备管理、日程调度、消息转发Spring Boot、MySQL、RabbitMQ
设备端传感器数据采集、执行器控制C、IoT SDK
Profile模型设备能力描述、数据交互规范JSON Schema

1.2 解决的核心痛点

  • 配网复杂:采用NAN协议实现无感配网,无需手动输入WiFi密码
  • 协议碎片化:统一Profile设备模型定义,支持跨厂商设备互联
  • 场景联动难:可视化日程编排系统,轻松实现多设备协同场景
  • 开发门槛高:提供完整demo代码与文档,降低智能家居开发难度

二、开发环境极速搭建

2.1 硬件准备清单

设备推荐型号用途
开发板BearPi-HM Nano智能设备原型开发
手机HarmonyOS 2.0+数字管家应用运行
NFC标签兼容ISO 14443A设备身份标识
传感器模块E53-SC1拓展板环境数据采集

2.2 软件环境配置

2.2.1 DevEco Studio安装
# 下载DevEco Studio 3.0 Beta1及以上版本
wget https://developer.harmonyos.com/cn/develop/deveco-studio#download

# 安装依赖
sudo apt-get install libnss3-dev libxss1 libasound2 libx11-xcb1

# 赋予执行权限并安装
chmod +x deveco-studio-*.bin
./deveco-studio-*.bin
2.2.2 SDK配置

启动DevEco Studio后,在SDK Manager中安装以下组件:

  • OpenHarmony SDK API Version 6
  • Node.js 14.19.1
  • HarmonyOS Legacy SDK
2.2.3 代码仓库获取
git clone https://gitcode.com/openharmony-sig/knowledge_demo_smart_home
cd knowledge_demo_smart_home

三、设备端开发实战

3.1 智能台灯设备开发

以智能台灯为例,完整实现设备端开发流程:

3.1.1 硬件连接

E53-SC1拓展板与BearPi-HM Nano连接方式:

  • SDA -> GPIO0
  • SCL -> GPIO1
  • PWM -> GPIO2
  • 电源 -> 3.3V
  • 地线 -> GND
3.1.2 设备端代码结构
team_x/smart_lamp/
├── include/            # 头文件目录
│   ├── lamp_control.h  # 台灯控制接口
│   └── sensor.h        # 传感器数据采集接口
├── src/                # 源代码目录
│   ├── main.c          # 程序入口
│   ├── lamp_control.c  # 台灯控制实现
│   └── sensor.c        # 传感器数据采集实现
└── BUILD.gn            # 编译配置文件
3.1.3 核心代码实现

主程序入口 (main.c)

#include "ohos_init.h"
#include "kernel_init.h"
#include "lamp_control.h"
#include "sensor.h"
#include "iot_wifi.h"
#include "network_config_service.h"

void LampDeviceInit(void)
{
    // 初始化传感器
    SensorInit();
    
    // 初始化台灯控制
    LampControlInit();
    
    // 初始化WiFi和配网服务
    IoTWiFiInit();
    NetworkConfigServiceStart();
    
    // 启动传感器数据上报线程
    osThreadAttr_t attr;
    attr.name = "SensorReportThread";
    attr.stack_size = 4096;
    attr.priority = osPriorityNormal;
    osThreadNew(SensorReportThread, NULL, &attr);
}

SYS_RUN(LampDeviceInit);

无感配网实现 (network_config.c)

#include "network_config_service.h"
#include "iot_netcfg_nan.h"
#include "iot_wifi.h"

static void OnNetConfigSuccess(const char* ssid, const char* password)
{
    // 配网成功,连接WiFi
    printf("NetConfig success, connecting to %s...\n", ssid);
    IoTWiFiConnect(ssid, password);
    
    // 保存配网信息到KV存储
    SaveWiFiConfig(ssid, password);
    
    // 切换LED状态指示
    SetLedState(LED_STATE_CONNECTED);
}

void NetworkConfigServiceStart(void)
{
    // 检查是否已有保存的WiFi配置
    char ssid[32] = {0};
    char password[64] = {0};
    if (LoadWiFiConfig(ssid, password) == 0) {
        // 已有配置,直接连接
        IoTWiFiConnect(ssid, password);
        SetLedState(LED_STATE_CONNECTED);
        return;
    }
    
    // 无保存配置,启动NAN配网
    NetConfigNanConfig config = {0};
    config.callback = OnNetConfigSuccess;
    config.deviceType = DEVICE_TYPE_LAMP;
    config.nodeId = "Lamp001";
    config.devicePwd = "12345678";
    
    IoTNetcfgNanStart(&config);
    
    // 进入配网状态,LED快闪
    SetLedState(LED_STATE_CONFIGURING);
}

3.2 设备固件烧录

3.2.1 烧录工具配置
  1. 安装CH340驱动
sudo apt-get install linux-headers-$(uname -r)
git clone https://github.com/juliagoda/CH341SER.git
cd CH341SER
make
sudo make load
  1. 使用HiBurn工具烧录
# 下载HiBurn工具
wget https://harmonyos.51cto.com/resource/29 -O HiBurn.zip
unzip HiBurn.zip
chmod +x HiBurn/HiBurn.exe

# 启动HiBurn并配置
wine HiBurn/HiBurn.exe
3.2.2 烧录步骤
  1. 选择串口:点击"Refresh"后选择识别到的COM端口
  2. 设置波特率:921600
  3. 选择固件:dev/docs/quick_start/resource/image/Hi3861_wifiiot_app_allinone.bin
  4. 勾选"Auto burn",点击"Connect"
  5. 按下开发板RESET键开始烧录

四、FA应用开发详解

4.1 数字管家应用结构

FA/DistSchedule/
├── entry/                      # 主应用模块
│   ├── src/main/js/            # JS代码目录
│   │   ├── default/            # 默认应用
│   │   │   ├── pages/          # 页面目录
│   │   │   │   ├── index/      # 首页
│   │   │   │   ├── device/     # 设备控制页
│   │   │   │   └── scene/      # 场景编排页
│   │   │   ├── app.js          # 应用入口
│   │   │   └── config.json     # 应用配置
│   └── src/main/resource/      # 资源文件
└── netconfig/                  # 配网模块
    └── src/main/js/            # 配网页面代码

4.2 设备控制页面开发

设备控制页 (device/index.hml)

<div class="device-page">
    <div class="device-header">
        <image src="/common/lamp.png" class="device-icon"></image>
        <text class="device-name">{{deviceName}}</text>
        <switch checked="{{isOn}}" onchange="togglePower" class="power-switch"></switch>
    </div>
    
    <div class="device-control" if="{{isOn}}">
        <text class="control-label">亮度调节</text>
        <slider value="{{brightness}}" min="1" max="100" step="1" onchange="setBrightness" class="brightness-slider"></slider>
        <text class="brightness-value">{{brightness}}%</text>
        
        <text class="control-label">色温调节</text>
        <div class="color-temp">
            <div class="temp-option" style="background-color: #FFE0B2;" onclick="setTemp(2700)"></div>
            <div class="temp-option" style="background-color: #FFF9C4;" onclick="setTemp(4000)"></div>
            <div class="temp-option" style="background-color: #E3F2FD;" onclick="setTemp(6500)"></div>
        </div>
    </div>
    
    <div class="scene-link" onclick="gotoScene">
        <text class="link-text">添加到场景</text>
        <image src="/common/arrow-right.png" class="link-icon"></image>
    </div>
</div>

页面样式 (device/index.css)

.device-page {
    flex-direction: column;
    padding: 20px;
    background-color: #F5F5F5;
}

.device-header {
    flex-direction: row;
    align-items: center;
    padding: 15px;
    background-color: #FFFFFF;
    border-radius: 12px;
    margin-bottom: 20px;
}

.device-icon {
    width: 60px;
    height: 60px;
    margin-right: 15px;
}

.device-name {
    flex: 1;
    font-size: 20px;
    font-weight: bold;
}

.power-switch {
    width: 50px;
    height: 30px;
}

.device-control {
    flex-direction: column;
    padding: 20px;
    background-color: #FFFFFF;
    border-radius: 12px;
}

.control-label {
    font-size: 16px;
    color: #666666;
    margin: 15px 0 5px 0;
}

.brightness-slider {
    width: 100%;
    height: 6px;
    margin: 10px 0;
}

.brightness-value {
    font-size: 14px;
    color: #333333;
    text-align: right;
    margin-bottom: 20px;
}

.color-temp {
    flex-direction: row;
    justify-content: space-between;
    margin: 10px 0;
}

.temp-option {
    width: 60px;
    height: 60px;
    border-radius: 8px;
}

.scene-link {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    padding: 15px;
    background-color: #FFFFFF;
    border-radius: 12px;
    margin-top: 20px;
}

.link-text {
    font-size: 16px;
    color: #007AFF;
}

.link-icon {
    width: 20px;
    height: 20px;
}

页面逻辑 (device/index.js)

import deviceService from '../../common/deviceService';

export default {
    data: {
        deviceName: '智能台灯',
        deviceId: '',
        isOn: false,
        brightness: 80,
        colorTemp: 4000
    },
    
    onInit() {
        // 获取设备信息
        this.deviceId = this.$routerParams.deviceId;
        this.deviceName = this.$routerParams.deviceName || '智能台灯';
        
        // 订阅设备状态更新
        deviceService.subscribeDeviceStatus(this.deviceId, (status) => {
            this.isOn = status.power;
            this.brightness = status.brightness;
            this.colorTemp = status.colorTemp;
        });
        
        // 获取当前设备状态
        deviceService.getDeviceStatus(this.deviceId).then(status => {
            this.isOn = status.power;
            this.brightness = status.brightness;
            this.colorTemp = status.colorTemp;
        });
    },
    
    togglePower(checked) {
        this.isOn = checked.checked;
        deviceService.controlDevice(this.deviceId, {
            power: this.isOn
        });
    },
    
    setBrightness(e) {
        this.brightness = e.value;
        deviceService.controlDevice(this.deviceId, {
            brightness: this.brightness
        });
    },
    
    setTemp(temp) {
        this.colorTemp = temp;
        deviceService.controlDevice(this.deviceId, {
            colorTemp: this.colorTemp
        });
    },
    
    gotoScene() {
        this.$router.push({
            uri: '/pages/scene/add',
            params: {
                deviceId: this.deviceId,
                deviceName: this.deviceName
            }
        });
    }
};

4.3 应用签名与安装

  1. 在AGC创建应用

    • 访问https://developer.huawei.com/consumer/cn/service/josp/agc/index.html
    • 创建新项目并添加应用,获取应用包名
  2. 配置应用签名

# 在项目根目录执行
hdc shell bm get -u > signature.p7b
keytool -importcert -file signature.p7b -keystore debug.keystore -alias ohos
  1. 编译并安装应用
# 编译HAP包
hvigor build -p ohos-arm64 -r release

# 安装到设备
hdc install entry/build/outputs/hap/release/entry-release-arm64.hap
hdc install netconfig/build/outputs/hap/release/netconfig-release-arm64.hap

五、无感配网核心技术

5.1 NAN协议配网原理

NAN (Neighbor Awareness Networking) 协议是一种Wi-Fi直连技术,允许设备在不连接AP的情况下发现邻近设备并进行通信。智能家居无感配网流程如下:

mermaid

5.2 NFC标签数据格式

NFC标签存储设备配网所需的关键信息,格式定义如下:

字段ID名称长度描述示例值
1产品ID24字节IoT平台设备产品标识6128c7b60ad1ed0286680f19
2NodeID8字节设备节点标识Lamp01
3设备密钥8字节设备认证密码12345678
4配网类型1字节0:无需配网 1:NAN+SoftAP 2:SoftAP 3:BLE 4:NAN1
5AP热点名12字节设备自身热点名teamX-Lamp01

5.3 NFC标签写入工具

使用应用调测助手写入NFC标签:

  1. 安装应用调测助手APP
  2. 选择"NFC标签写入"功能
  3. 输入设备配网信息
  4. 将手机贴近NFC标签完成写入

六、服务端部署与集成

6.1 服务端架构

Server模块采用Spring Boot分层架构,实现设备管理、用户管理、日程调度等核心功能:

Server/
├── distschedule-core/       # 入口模块
│   ├── src/main/java/com/keno/distschedule/
│   │   ├── controller/      # API控制器
│   │   └── DistscheduleApplication.java # 应用入口
├── distschedule-service/    # 业务逻辑模块
│   └── src/main/java/com/keno/distschedule/service/
└── distschedule-dao/        # 数据访问模块
    └── src/main/java/com/keno/distschedule/dao/

6.2 Docker容器化部署

使用Docker Compose一键部署服务端组件:

docker-compose.yml

version: '3'

services:
  mysql:
    image: mysql:5.7
    container_name: distschedule-mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: 123456
      MYSQL_DATABASE: distschedule
    ports:
      - "3306:3306"
    volumes:
      - mysql-data:/var/lib/mysql
      - ./distschedule-dao/src/main/resources/db/migration:/docker-entrypoint-initdb.d

  rabbitmq:
    image: rabbitmq:3-management
    container_name: distschedule-rabbitmq
    restart: always
    ports:
      - "5672:5672"
      - "15672:15672"
    environment:
      RABBITMQ_DEFAULT_USER: guest
      RABBITMQ_DEFAULT_PASS: guest

  server:
    build: .
    container_name: distschedule-server
    restart: always
    depends_on:
      - mysql
      - rabbitmq
    ports:
      - "8080:8080"
    environment:
      SPRING_PROFILES_ACTIVE: docker
      SPRING_DATASOURCE_URL: jdbc:mysql://mysql:3306/distschedule
      SPRING_DATASOURCE_USERNAME: root
      SPRING_DATASOURCE_PASSWORD: 123456
      SPRING_RABBITMQ_HOST: rabbitmq
    volumes:
      - ./application-docker.properties:/app/config/application-docker.properties

volumes:
  mysql-data:

部署命令:

cd Server
mvn clean package -Dmaven.test.skip=true
docker-compose up -d

七、多设备联动场景开发

7.1 场景编排数据模型

场景由触发器和执行动作组成,数据模型定义如下:

场景数据结构

{
  "sceneId": "scene_001",
  "name": "回家模式",
  "icon": "home",
  "trigger": {
    "type": "time",
    "value": "18:00",
    "repeat": "1111100" // 周一至周五
  },
  "actions": [
    {
      "deviceId": "lamp_001",
      "property": "power",
      "value": true
    },
    {
      "deviceId": "curtain_001",
      "property": "position",
      "value": 50
    },
    {
      "deviceId": "humidifier_001",
      "property": "power",
      "value": true,
      "delay": 300 // 延迟5分钟执行
    }
  ]
}

7.2 场景执行引擎实现

场景调度服务 (SceneScheduler.java)

@Service
public class SceneScheduler {
    @Autowired
    private SceneDao sceneDao;
    
    @Autowired
    private DeviceService deviceService;
    
    @Autowired
    private Scheduler scheduler;
    
    @PostConstruct
    public void init() {
        // 加载所有场景并调度
        List<Scene> scenes = sceneDao.findAllEnabledScenes();
        for (Scene scene : scenes) {
            scheduleScene(scene);
        }
    }
    
    public void scheduleScene(Scene scene) {
        // 根据触发器类型调度场景
        if ("time".equals(scene.getTrigger().getType())) {
            scheduleTimeTriggeredScene(scene);
        } else if ("device".equals(scene.getTrigger().getType())) {
            registerDeviceTriggeredScene(scene);
        }
    }
    
    private void scheduleTimeTriggeredScene(Scene scene) {
        String cronExpression = buildCronExpression(scene.getTrigger());
        scheduler.schedule(new SceneJob(scene, deviceService), new CronTrigger(cronExpression));
    }
    
    private String buildCronExpression(Trigger trigger) {
        // 将时间触发器转换为Cron表达式
        String[] timeParts = trigger.getValue().split(":");
        int hour = Integer.parseInt(timeParts[0]);
        int minute = Integer.parseInt(timeParts[1]);
        
        // 根据重复模式设置星期几
        String repeat = trigger.getRepeat();
        StringBuilder cron = new StringBuilder();
        cron.append("0 ").append(minute).append(" ").append(hour).append(" ? * ");
        
        // 解析重复模式(1111100 -> 周一至周五)
        List<Integer> weekdays = new ArrayList<>();
        for (int i = 0; i < repeat.length(); i++) {
            if (repeat.charAt(i) == '1') {
                // Cron星期几从1(周日)到7(周六)
                int cronDay = i == 0 ? 7 : i;
                weekdays.add(cronDay);
            }
        }
        
        if (weekdays.isEmpty()) {
            cron.append("?"); // 不重复
        } else {
            cron.append(StringUtils.join(weekdays, ","));
        }
        
        return cron.toString();
    }
    
    public void executeScene(Scene scene) {
        log.info("Executing scene: {}", scene.getName());
        
        // 执行场景中的所有动作
        for (SceneAction action : scene.getActions()) {
            if (action.getDelay() > 0) {
                // 延迟执行
                scheduler.schedule(() -> executeAction(action), 
                    new Date(System.currentTimeMillis() + action.getDelay() * 1000));
            } else {
                // 立即执行
                executeAction(action);
            }
        }
    }
    
    private void executeAction(SceneAction action) {
        try {
            deviceService.controlDevice(action.getDeviceId(), 
                Collections.singletonMap(action.getProperty(), action.getValue()));
        } catch (Exception e) {
            log.error("Failed to execute action for device {}: {}", 
                action.getDeviceId(), e.getMessage());
        }
    }
}

7.3 场景编排页面开发

场景编辑页面 (scene/edit.hml)

<div class="scene-edit">
    <div class="scene-header">
        <text class="title">编辑场景</text>
        <button class="save-btn" onclick="saveScene">保存</button>
    </div>
    
    <div class="scene-form">
        <div class="form-item">
            <text class="label">场景名称</text>
            <input type="text" value="{{sceneName}}" onchange="updateName" placeholder="请输入场景名称"></input>
        </div>
        
        <div class="form-item">
            <text class="label">触发方式</text>
            <select value="{{triggerType}}" onchange="changeTriggerType">
                <option value="time">定时触发</option>
                <option value="device">设备触发</option>
                <option value="manual">手动执行</option>
            </select>
        </div>
        
        <div class="trigger-config" if="{{triggerType == 'time'}}">
            <div class="time-picker">
                <timepicker type="time" selected="{{triggerTime}}" onchange="setTriggerTime"></timepicker>
            </div>
            <div class="repeat-config">
                <text class="repeat-label">重复</text>
                <div class="weekdays">
                    <div class="day-item" onclick="toggleRepeat(0)">
                        <text class="{{repeat[0] ? 'active' : ''}}">日</text>
                    </div>
                    <div class="day-item" onclick="toggleRepeat(1)">
                        <text class="{{repeat[1] ? 'active' : ''}}">一</text>
                    </div>
                    <!-- 其他星期 -->
                </div>
            </div>
        </div>
        
        <div class="action-list">
            <div class="action-header">
                <text class="header-text">执行动作 ({{actions.length}})</text>
                <button class="add-action" onclick="addAction">+ 添加动作</button>
            </div>
            
            <list class="actions">
                <list-item for="{{actions}}" class="action-item">
                    <div class="action-info">
                        <image src="{{$item.icon}}" class="device-icon"></image>
                        <div class="action-detail">
                            <text class="device-name">{{$item.deviceName}}</text>
                            <text class="action-desc">{{$item.actionDesc}}</text>
                        </div>
                    </div>
                    <button class="delete-action" onclick="deleteAction($idx)">删除</button>
                </list-item>
            </list>
        </div>
    </div>
</div>

八、项目部署与测试

8.1 完整部署流程

mermaid

8.2 测试用例设计

设备配网测试

测试项测试步骤预期结果
NFC唤醒1. 手机开启NFC
2. 碰一碰设备NFC标签
成功唤醒数字管家配网页面
无感配网1. 设备进入配网模式
2. 手机碰一碰设备
配网成功,设备上线
配网失败处理1. 断开WiFi
2. 尝试配网
显示配网失败提示,提供重试按钮

设备控制测试

测试项测试步骤预期结果
电源控制1. 在设备页面点击开关
2. 观察设备状态
设备状态与控制一致,响应时间<2s
亮度调节1. 拖动亮度滑块
2. 观察设备亮度变化
亮度平滑变化,与滑块位置一致
多设备并发控制1. 同时控制3个设备
2. 观察各设备响应
所有设备均能正确响应,无超时

场景联动测试

测试项测试步骤预期结果
定时场景1. 设置1分钟后执行场景
2. 等待触发
场景按时执行,所有动作完成
手动场景1. 在场景列表点击执行
2. 观察设备状态
场景立即执行,设备状态正确变化
设备触发场景1. 触发设备状态变化
2. 观察联动设备
联动设备按预期执行动作

九、总结与进阶方向

9.1 项目成果总结

通过本文指南,你已完成以下内容:

  1. 搭建了完整的OpenHarmony智能家居开发环境
  2. 开发了智能台灯设备端固件
  3. 实现了数字管家应用的设备控制与场景编排功能
  4. 掌握了NAN协议无感配网技术
  5. 部署了服务端并实现多设备联动

9.2 进阶学习方向

  1. 设备接入扩展

    • 学习Profile模型定义,接入新类型设备
    • 开发自定义传感器驱动
  2. AI能力集成

    • 集成语音识别,实现语音控制
    • 开发基于用户行为的场景推荐算法
  3. 安全增强

    • 实现设备端OTA升级功能
    • 开发基于数字证书的设备认证机制
  4. 性能优化

    • 优化设备端功耗,延长续航
    • 实现服务端集群部署,提高并发处理能力

9.3 学习资源推荐

  • 官方文档:https://developer.harmonyos.com/cn/docs/documentation/doc-guides/start-overview-0000001054129005
  • 代码仓库:https://gitcode.com/openharmony-sig/knowledge_demo_smart_home
  • 开发社区:https://harmonyos.51cto.com/forum-4-1.html
  • 视频教程:https://developer.harmonyos.com/cn/develop/videos

通过本项目实战,你已具备OpenHarmony智能家居开发的核心能力。继续深入学习与实践,你将能够构建更复杂的智能家居系统,为用户创造更智能、更便捷的生活体验。现在就开始你的智能家居开发之旅吧!

【免费下载链接】knowledge_demo_smart_home ​本仓库的样例都是基于智能家居,从客厅到卧室,从中控到sensor,开发者可以体验各种家居的开发样例,打造自己的家居体验,享受万物互联的快感。 【免费下载链接】knowledge_demo_smart_home 项目地址: https://gitcode.com/openharmony-sig/knowledge_demo_smart_home

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值