簡介
碰一碰特性是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燈進行開關操作。