[文章]远程台灯功能

阅读量0
0
3
简介

碰一碰特性是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的接口,因此首先需要在entryuild.gradle中加入对hilink的依赖。
  1. dependencies {
  2.     ...
  3.     ohosTestImplementation 'com.huawei.ohos.testkit:runner:2.0.0.200'
  4. }
复制代码
手机碰一碰nfc标签,将会拉起用于配网的原子化服务(entry模块)。在服务的入口MainAbility中,完成了对nfc中的产品信息的读取,以及将“abilityContext”和从意图中获取的“nanSessionId”注册到用于配网的NetConfigAbility中。
  1. // 读取产品信息
  2. Object productInfo = Objects.requireNonNull(intent.getParams()).getParam("productInfo");
  3. if (productInfo != null) {
  4.     productId = (String) productInfo;
  5. }

  6. // 从intent中读取的nanSessionId用于配网,同时需要将abilityContext和sessionId注册到NetConfigAbility中
  7. String sessionId = intent.getStringParam("nanSessionId");
  8. if ("null".equals(sessionId) || "".equals(sessionId)) {
  9.     NetConfigAbility.register(this, null);
  10. } else {
  11.     NetConfigAbility.register(this, sessionId);
  12. }
复制代码
entry模块的主界面在初始化时,会将产品信息和“nanSessionId”在应用中保存传递。
  1. onInit() {
  2.     this.deviceName = this.$t('strings.device-name');
  3.     this.deviceImg = '/common/images/LED.png';
  4.     getApp(this).Product.productName = this.productName;
  5.     getApp(this).Product.productId = this.productId;
  6.     getApp(this).ConfigParams.sessionId = this.sessionId;
  7. }
复制代码
点击主界面的“配网”按钮,会默认进行配网操作。主要分为5个步骤,均依赖hilink接口实现,具体代码可查看netconfig.js。
通过NAN广播服务搜索设备。
  1. getApp(this).NetConfig.discoveryByNAN(scanInfo, (result) => {
  2.     if (result.code == 0) {
  3.        // 成功发现设备
  4.     } else {
  5.        ...
  6.     }
  7. });
复制代码
连接设备。
  1. getApp(this).NetConfig.connectDevice(connectInfo, (result) => {
  2.     if (result.code === 0) {
  3.         // 设备连接成功
  4.     } else {
  5.         ...
  6.     }
  7. });
复制代码
获取wifi信息
  1. getApp(this).NetConfig.getWifiList((result) => {
  2.     if (result.code == 0 && result.data && result.data.length > 0) {
  3.         // 获取wifi信息成功
  4.     } else {
  5.         ...
  6.     }
  7. });
复制代码

对设备进行网络配置。
  1. getApp(this).NetConfig.configDeviceNet('deviceInfo', 'accountInfo', netConfigInfo, (result) => {
  2.     if (result.code == 0) {
  3.         // 设备网络配置成功
  4.     } else {
  5.         ...
  6.     }
  7. });
复制代码
配网成功,跳转至设备控制模块
  1. goToControl() {
  2.     let target = {
  3.         bundleName: 'com.huawei.smartlamp.hmservice',
  4.         abilityName: 'com.huawei.smartlamp.ControlMainAbility',
  5.         deviceType: 1,// 从本地设备中拉起原子化服务
  6.         data: {
  7.             session_id: getApp(this).ConfigParams.deviceInfo.sessionId,
  8.             product_id: getApp(this).Product.productId,
  9.             product_name: getApp(this).Product.productName
  10.         }
  11.     }
  12.     FeatureAbility.startAbility(target);
  13.     app.terminate()
  14. }
复制代码

设备控制原子化服务(control)
通过control模块控制开发版led灯的开关,依赖hilink的接口发送指令,因此需要在controluild.gradle添加对应依赖。
  1. dependencies {    ...    implementation(group: 'com.huawei.hilink', name: 'ailifeability', version: '1.0.0.1', ext: 'har')}
复制代码
当成功完成设备配网后,手机会自动拉起设备控制原子化服务(control)。在控制服务界面点击开关按钮时,会利用FeatureAbility模块(JS端SDK接口)的能力,调用PA向开发板发送指令,NetConfigApi由引入的hilink模块提供。
  1. 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的源码:
  1. repo init -u https://gitee.com/openharmony/manifest.git -b OpenHarmony-3.0-LTS --no-repo-verify
  2. repo sync -c
  3. repo forall -c 'git lfs pull'
复制代码

编译前准备
编译前,需要调整OpenHarmony源码,并添加设备侧代码,以实现设备配网与设备控制的功能。
修改device/hisilicon/hispark_pegasus/sdk_liteos/build/config/usr_config.mk文件,开启对I2C的支持。
  1. CONFIG_I2C_SUPPORT=y
复制代码
修改device/hisilicon/hispark_pegasus/hi3861_adapter/hals/communication
  1. //if (SetHotspotIpConfig() != WIFI_SUCCESS) {
  2. //    return ERROR_WIFI_UNKNOWN;
  3. //}
复制代码

修改device/hisilicon/hispark_pegasus/hi3861_adapter/hals/communication/wifi_lite/wifiservice/source/wifi_device.c文件,在DispatchConnectEvent函数中注释StaSetWifiNetConfig相关代码。
  1. //StaSetWifiNetConfig(HI_WIFI_EVT_CONNECTED);
  2. //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初始化,进入配网状态并注册网络监听事件。
  1. static void *LampTask(const char *arg)
  2. {
  3.     (void)arg;
  4.     WINDBG("LampTask Enter!
  5. ");
  6.     LampInit();
  7.     (void)memset_s(&g_lamp, sizeof(g_lamp), 0x00, sizeof(g_lamp));

  8.     NetCfgRegister(LampNetEventHandler);  // 进入配网状态并注册网络监听事件
  9.     LampShowInfo();       // 显示LED初始状态
  10. }
复制代码
配网成功,并成功注册网络监听事件后,手机端每次发送指令,都会触发监听事件,从而对开发板设备上LED灯进行开关控制。
  1. static int LampNetEventHandler(NET_EVENT_TYPE event, void *data)
  2. {
  3.     switch (event) {
  4.         case NET_EVENT_RECV_DATA: // 接收到网络信息(FA发送的消息)
  5.             LampProcessAppMessage((const char *)data, strlen(data)); // 处理对应的信息
  6.             break;
  7.         default:
  8.             break;
  9.     }
  10.     return 0;
  11. }
复制代码

编译和烧录
编译

进入源码根目录,首次编译,输入编译命令“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的源码:
  1. repo init -u https://gitee.com/openharmony/manifest.git -b OpenHarmony-3.0-LTS --no-repo-verify
  2. repo sync -c
  3. repo forall -c 'git lfs pull'
复制代码

编译前准备
编译前,需要调整OpenHarmony源码,并添加设备侧代码,以实现设备配网与设备控制的功能。
修改device/hisilicon/hispark_pegasus/sdk_liteos/build/config/usr_config.mk文件,开启对I2C的支持。
  1. CONFIG_I2C_SUPPORT=y
复制代码
修改device/hisilicon/hispark_pegasus/hi3861_adapter/hals/communication/wifi_lite/wifiservice/source/wifi_hotspot.c文件,在EnableHotspot函数中注释如下代码。
  1. //if (SetHotspotIpConfig() != WIFI_SUCCESS) {
  2. //    return ERROR_WIFI_UNKNOWN;
  3. //}
复制代码
修改device/hisilicon/hispark_pegasus/hi3861_adapter/hals/communication/wifi_lite/wifiservice/source/wifi_device.c文件,在DispatchConnectEvent函数中注释StaSetWifiNetConfig相关代码。
  1. //StaSetWifiNetConfig(HI_WIFI_EVT_CONNECTED);
  2. //StaSetWifiNetConfig(HI_WIFI_EVT_DISCONNECTED);
复制代码
修改device/hisilicon/hispark_pegasus/sdk_liteos/BUILD.gn文件,在deps中添加如下代码。
  1. deps = [
  2.     ...
  3.     "//build/lite:product",
  4.   ]
复制代码
修改base/security/huks/interfaces/innerkits/huks_lite/BUILD.gn文件,注释如下代码。
  1. #sources += [ "hks_tmp_client.c" ]
复制代码
在OpenHarmony源码的third_party目录下,添加IoTDA平台SDK。

在vendor目录下,添加设备侧代码team_x。目录结构如下图所示。
“common”中主要包含本样例依赖的头文件和类库文件。“smart_lamp”中则包含了本样例中设备侧的核心代码。“smart_lamp”目录结构如下图所示。

  1. static void *LampTask(const char *arg)
  2. {
  3.     (void)arg;
  4.     WINDBG("LampTask Enter!
  5. ");
  6.     LampInit();
  7.     (void)memset_s(&g_lamp, sizeof(g_lamp), 0x00, sizeof(g_lamp));

  8.     NetCfgRegister(LampNetEventHandler);  // 进入配网状态并注册网络监听事件
  9.     LampShowInfo();       // 显示LED初始状态
  10. }
复制代码
配网成功,并成功注册网络监听事件后,手机端每次发送指令,都会触发监听事件,从而对开发板设备上LED灯进行开关控制。
  1. static int LampNetEventHandler(NET_EVENT_TYPE event, void *data)
  2. {
  3.     switch (event) {
  4.         case NET_EVENT_RECV_DATA: // 接收到网络信息(FA发送的消息)
  5.             LampProcessAppMessage((const char *)data, strlen(data)); // 处理对应的信息
  6.             break;
  7.         default:
  8.             break;
  9.     }
  10.     return 0;
  11. }
复制代码

编译
进入源码根目录,首次编译,输入编译命令“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灯进行开关操作。


回帖

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容图片侵权或者其他问题,请联系本站作侵删。 侵权投诉
链接复制成功,分享给好友