远程台灯功能 原创 精华
简介
碰一碰特性是HarmonyOS具备的多终端业务协同技术。通过碰一碰的交互方式,可以将手机和全场景设备连接起来。再通过手机端的原子化服务能力,快速完成配网、远程控制。解决了应用与设备之间接续慢、配网复杂、传输难的问题,为用户带来无缝切换的流畅体验。
本篇Codelab将指导大家如何开发一个模拟的“远程台灯”案例。在本案例中,通过手机碰一碰NFC标签,可以从HAG获取到关联意图信息。通过获取到的关联意图信息,可以拉起对应的原子化服务。该原子化服务通过调用hilink接口,并结合设备侧代码实现,可以完成开发板与手机间的配网并建立通信通道。完成此步骤后,即可通过手机控制Hi3861开发版中LED灯的开关了。
通过该案例,大家将会学会:
通过碰一碰能力,拉起手机端原子化服务。
快速完成手机与设备的配网。
通过手机对设备进行控制。
说明: 本指导仅用于个人开发者体验HarmonyOS碰一碰特性,不能作为商用方案进行碰一碰特性的开发和上架。
实物简介
Hi3861开发板
华为手机,系统版本为HarmonyOS 2.0.0.168及以上,手机具体型号为Mate 40 Pro。将手机上智慧生活基础服务升级至12.0.0.306及以上版本。具体操作步骤如下:
查看“智慧生活基础服务”版本,打开手机“设置>应用服务>应用管理”,搜索“智慧生活基础服务”。
升级“智慧生活基础服务”,打开手机“智慧生活”App,点击“我的 > 设置 > 检查应用更新”,更新“智慧生活基础服务”。
Hi3861开发板
本样例基于Hi3861开发板开发,请准备Hi3861开发板(HiSpark Wi-Fi IoT智能家居套件)。包含开发板主板、底板和OLED板。
HarmonyOS原子化服务开发
创建工程
设备配网原子化服务(entry)
设备控制原子化服务(control)
本案例将要实现“碰一碰-拉起原子化服务-设备配网-设备控制”的完整流程,整个流程都要基于手机端的原子化服务实现。开发原子化服务使用的工具为DevEco Studio 3.0 Beta2,关于工具配置请查看官方指导文档搭建开发环境流程。
打开创建工程向导界面,选择“Empty Ability”模板创建原子化服务,用于设备配网。
在工程配置中,Project type选择“Atomic Service”,并打开“Show in Service Center”选项,点击Finish按钮即可完成创建设备配网原子化服务。
在已创建好的“entry”目录上右击,选择“Empty Ability”模板新建一个Module,用于设备控制。
在模块配置界面,“Module type”中选择的“Feature”,点击“Next”。
配置Module的“Page ability name”,点击“Finish”完成创建。
设备配网原子化服务(entry)
配网过程需要依赖hilink的接口,因此首先需要在entry\build.gradle中加入对hilink的依赖。
dependencies {
...
ohosTestImplementation 'com.huawei.ohos.testkit:runner:2.0.0.200'
}
手机碰一碰nfc标签,将会拉起用于配网的原子化服务(entry模块)。在服务的入口MainAbility中,完成了对nfc中的产品信息的读取,以及将“abilityContext”和从意图中获取的“nanSessionId”注册到用于配网的NetConfigAbility中。
// 读取产品信息
Object productInfo = Objects.requireNonNull(intent.getParams()).getParam("productInfo");
if (productInfo != null) {
productId = (String) productInfo;
}
// 从intent中读取的nanSessionId用于配网,同时需要将abilityContext和sessionId注册到NetConfigAbility中
String sessionId = intent.getStringParam("nanSessionId");
if ("null".equals(sessionId) || "".equals(sessionId)) {
NetConfigAbility.register(this, null);
} else {
NetConfigAbility.register(this, sessionId);
}
entry模块的主界面在初始化时,会将产品信息和“nanSessionId”在应用中保存传递。
onInit() {
this.deviceName = this.$t('strings.device-name');
this.deviceImg = '/common/images/LED.png';
getApp(this).Product.productName = this.productName;
getApp(this).Product.productId = this.productId;
getApp(this).ConfigParams.sessionId = this.sessionId;
}
点击主界面的“配网”按钮,会默认进行配网操作。主要分为5个步骤,均依赖hilink接口实现,具体代码可查看netconfig.js。
通过NAN广播服务搜索设备。
getApp(this).NetConfig.discoveryByNAN(scanInfo, (result) => {
if (result.code == 0) {
// 成功发现设备
} else {
...
}
});
连接设备。
getApp(this).NetConfig.connectDevice(connectInfo, (result) => {
if (result.code === 0) {
// 设备连接成功
} else {
...
}
});
获取wifi信息。
getApp(this).NetConfig.getWifiList((result) => {
if (result.code == 0 && result.data && result.data.length > 0) {
// 获取wifi信息成功
} else {
...
}
});
对设备进行网络配置。
getApp(this).NetConfig.configDeviceNet('deviceInfo', 'accountInfo', netConfigInfo, (result) => {
if (result.code == 0) {
// 设备网络配置成功
} else {
...
}
});
配网成功,跳转至设备控制模块。
goToControl() {
let target = {
bundleName: 'com.huawei.smartlamp.hmservice',
abilityName: 'com.huawei.smartlamp.ControlMainAbility',
deviceType: 1,// 从本地设备中拉起原子化服务
data: {
session_id: getApp(this).ConfigParams.deviceInfo.sessionId,
product_id: getApp(this).Product.productId,
product_name: getApp(this).Product.productName
}
}
FeatureAbility.startAbility(target);
app.terminate()
}
设备控制原子化服务(control)
通过control模块控制开发版led灯的开关,依赖hilink的接口发送指令,因此需要在control\build.gradle添加对应依赖。
dependencies { ... implementation(group: 'com.huawei.hilink', name: 'ailifeability', version: '1.0.0.1', ext: 'har')}
当成功完成设备配网后,手机会自动拉起设备控制原子化服务(control)。在控制服务界面点击开关按钮时,会利用FeatureAbility模块(JS端SDK接口)的能力,调用PA向开发板发送指令,NetConfigApi由引入的hilink模块提供。
private void sendMessage(String message, HashMap<String, Object> tmpMap) { CommonInfo commonInfo = new CommonInfo(); commonInfo.setSessionId(sessionId); HiLog.error(LABEL_LOG, "sessionId " + sessionId); NetConfigApi.getInstance().sendMessage(commonInfo, message, (code, controlMessage, str) -> { ... });}
Hi3861开发环境准备
Hi3861支持多种开发环境的搭建:
搭建Windows开发环境
搭建Windows+Ubuntu混合开发环境
搭建Ubuntu开发环境
开发者可以根据自身的情况搭建合适的开发环境。
源码下载与编译前准备
代码下载
编译前准备
本案例将使用Ubuntu开发环境,基于OpenHarmony-3.0-LTS源码进行开发。
代码下载
通过repo工具下载OpenHarmony-3.0-LTS的源码:
repo init -u https://gitee.com/openharmony/manifest.git -b OpenHarmony-3.0-LTS --no-repo-verify
repo sync -c
repo forall -c 'git lfs pull'
编译前准备
编译前,需要调整OpenHarmony源码,并添加设备侧代码,以实现设备配网与设备控制的功能。
修改device/hisilicon/hispark_pegasus/sdk_liteos/build/config/usr_config.mk文件,开启对I2C的支持。
CONFIG_I2C_SUPPORT=y
修改device/hisilicon/hispark_pegasus/hi3861_adapter/hals/communication/wifi_lite/wifiservice/source/wifi_hotspot.c文件,在EnableHotspot函数中注释如下代码。
//if (SetHotspotIpConfig() != WIFI_SUCCESS) {
// return ERROR_WIFI_UNKNOWN;
//}
修改device/hisilicon/hispark_pegasus/hi3861_adapter/hals/communication/wifi_lite/wifiservice/source/wifi_device.c文件,在DispatchConnectEvent函数中注释StaSetWifiNetConfig相关代码。
//StaSetWifiNetConfig(HI_WIFI_EVT_CONNECTED);
//StaSetWifiNetConfig(HI_WIFI_EVT_DISCONNECTED);
修改base/security/huks/interfaces/innerkits/huks_lite/BUILD.gn文件,注释如下代码。
#sources += [ “hks_tmp_client.c” ]
在OpenHarmony源码的third_party目录下,添加IoTDA平台SDK。
在vendor目录下,添加设备侧代码team_x。目录结构如下图所示。
“common”中主要包含本样例依赖的头文件和类库文件。“smart_lamp”中则包含了本样例中设备侧的核心代码。“smart_lamp”目录结构如下图所示。
样例入口文件iot_main.c位于demo_smartlamp/src目录下,当启动开发板时,会启动入口线程任务。在该任务中,开发板会完成I2C初始化、OLED初始化,进入配网状态并注册网络监听事件。
static void *LampTask(const char *arg)
{
(void)arg;
WINDBG("LampTask Enter! \n");
LampInit();
(void)memset_s(&g_lamp, sizeof(g_lamp), 0x00, sizeof(g_lamp));
NetCfgRegister(LampNetEventHandler); // 进入配网状态并注册网络监听事件
LampShowInfo(); // 显示LED初始状态
}
配网成功,并成功注册网络监听事件后,手机端每次发送指令,都会触发监听事件,从而对开发板设备上LED灯进行开关控制。
static int LampNetEventHandler(NET_EVENT_TYPE event, void *data)
{
switch (event) {
case NET_EVENT_RECV_DATA: // 接收到网络信息(FA发送的消息)
LampProcessAppMessage((const char *)data, strlen(data)); // 处理对应的信息
break;
default:
break;
}
return 0;
}
编译和烧录
编译
进入源码根目录,首次编译,输入编译命令“hb set”。随后在Input code path命令行中键入“.”,指定OpenHarmony工程编译根目录后回车。
选择智能台灯“smart_lamp”并回车,输入“hb build”命令进行编译,屏幕出现:BUILD SUCCESS字样,说明编译成功。
烧录
将编译生成文件下载至本地Windows环境。
将Hi3861通过TypeC数据线与电脑连接。
使用Hiburn工具进行烧录:
点击“Refresh”按钮,更新com端口信息。在“COM”处选择Hi3861开发板对应的COM口。选择编译生成的二进制文件,勾选“Auto burn”,随后点击“connect”按钮。此时点击Hi3861开发板上的“RST”键,进行烧录。
查看烧录进度,等待进度跑完,则烧录完成。可点击“Disconnect”断开连接。
源码下载与编译前准备
代码下载
编译前准备
本案例将使用Ubuntu开发环境,基于OpenHarmony-3.0-LTS源码进行开发。
代码下载
通过repo工具下载OpenHarmony-3.0-LTS的源码:
repo init -u https://gitee.com/openharmony/manifest.git -b OpenHarmony-3.0-LTS --no-repo-verify
repo sync -c
repo forall -c 'git lfs pull'
编译前准备
编译前,需要调整OpenHarmony源码,并添加设备侧代码,以实现设备配网与设备控制的功能。
修改device/hisilicon/hispark_pegasus/sdk_liteos/build/config/usr_config.mk文件,开启对I2C的支持。
CONFIG_I2C_SUPPORT=y
修改device/hisilicon/hispark_pegasus/hi3861_adapter/hals/communication/wifi_lite/wifiservice/source/wifi_hotspot.c文件,在EnableHotspot函数中注释如下代码。
//if (SetHotspotIpConfig() != WIFI_SUCCESS) {
// return ERROR_WIFI_UNKNOWN;
//}
修改device/hisilicon/hispark_pegasus/hi3861_adapter/hals/communication/wifi_lite/wifiservice/source/wifi_device.c文件,在DispatchConnectEvent函数中注释StaSetWifiNetConfig相关代码。
//StaSetWifiNetConfig(HI_WIFI_EVT_CONNECTED);
//StaSetWifiNetConfig(HI_WIFI_EVT_DISCONNECTED);
修改device/hisilicon/hispark_pegasus/sdk_liteos/BUILD.gn文件,在deps中添加如下代码。
deps = [
...
"//build/lite:product",
]
修改base/security/huks/interfaces/innerkits/huks_lite/BUILD.gn文件,注释如下代码。
#sources += [ "hks_tmp_client.c" ]
在OpenHarmony源码的third_party目录下,添加IoTDA平台SDK。
在vendor目录下,添加设备侧代码team_x。目录结构如下图所示。
“common”中主要包含本样例依赖的头文件和类库文件。“smart_lamp”中则包含了本样例中设备侧的核心代码。“smart_lamp”目录结构如下图所示。
static void *LampTask(const char *arg)
{
(void)arg;
WINDBG("LampTask Enter! \n");
LampInit();
(void)memset_s(&g_lamp, sizeof(g_lamp), 0x00, sizeof(g_lamp));
NetCfgRegister(LampNetEventHandler); // 进入配网状态并注册网络监听事件
LampShowInfo(); // 显示LED初始状态
}
配网成功,并成功注册网络监听事件后,手机端每次发送指令,都会触发监听事件,从而对开发板设备上LED灯进行开关控制。
static int LampNetEventHandler(NET_EVENT_TYPE event, void *data)
{
switch (event) {
case NET_EVENT_RECV_DATA: // 接收到网络信息(FA发送的消息)
LampProcessAppMessage((const char *)data, strlen(data)); // 处理对应的信息
break;
default:
break;
}
return 0;
}
编译
进入源码根目录,首次编译,输入编译命令“hb set”。随后在Input code path命令行中键入“.”,指定OpenHarmony工程编译根目录后回车。
选择智能台灯“smart_lamp”并回车,输入“hb build”命令进行编译,屏幕出现:BUILD SUCCESS字样,说明编译成功。
烧录
将编译生成文件下载至本地Windows环境。
将Hi3861通过TypeC数据线与电脑连接。
使用Hiburn工具进行烧录:
点击“Refresh”按钮,更新com端口信息。在“COM”处选择Hi3861开发板对应的COM口。选择编译生成的二进制文件,勾选“Auto burn”,随后点击“connect”按钮。此时点击Hi3861开发板上的“RST”键,进行烧录。
查看烧录进度,等待进度跑完,则烧录完成。可点击“Disconnect”断开连接。
设备配网
使用应用调测助手App,在NFC标签中写入对应的标签信息,具体请参考写入NFC标签信息。
通过在HAG上配置原子化关联意图,在手机碰一碰NFC标签后,即可获取需要拉取的原子化服务信息,具体请参考配置服务关联意图。
在手机上安装开发好的原子化服务。注意该项目包含两个模块,签名需要使用项目级签名。
打开Run > Edit Configurations, 勾选entry模块下的“Deploy Multi Hap Packages”选项,表示在运行entry模块(设备配网原子化服务)时,同时会在手机中安装control模块(设备控制原子化服务)。
打开手机NFC功能,确认手机已经接入WLAN无线网络。使用手机背部接触NFC标签,手机会弹出以下页面。
点击Hi3861开发板的RST复位按键,点击手机上的配网按钮,即开始手机与开发板的配网过程。配网成功后,手机应用将自动跳转至控制界面,如下图。
操作体验
配网成功后,即可通过手机对Hi3861开发板LED灯进行开关操作。
感谢指导,新知识get!