提交 9e92dfaa 编写于 作者: D duangavin123

update 导入OpenHarmony工程

Signed-off-by: Nduangavin123 <duanxichao@huawei.com>
上级 2b41e5c9
......@@ -2,27 +2,6 @@
- [Mini- and Small-System Devices](device-lite.md)
- [WLAN-connected Products](device-wlan.md)
- [OneHop](device-wlan-touch.md)
- [Overview](onehop-overview.md)
- [Preparations](onehop-dev-prerequisites.md)
- [Developing the Hi3861 Development Board](onehop-dev-hi3861.md)
- [Developing Atomic Services](onehop-dev-atomic-service.md)
- [Writing an NFC Tag](onehop-write-nfc-info.md)
- [Configuring a Service Association Intent](onehop-configuration-device-tag.md)
- [Tapping to Launch an Atomic Service](onehop-open-atomic-service.md)
- [References](onehop-reference-info.md)
- [Development Guidelines on the Network Configuration Atomic Service](guide-atomic-service-netconfig.md)
- [How to Develop](guide-atomic-service-netconfig-overview.md)
- [Introduction to the Core Code](guide-atomic-service-netconfig-logic.md)
- [Calling of Network Configuration APIs](guide-atomic-service-netconfig-api.md)
- [FAQs](faqs.md)
- [Development Guidelines on the Device Control Atomic Service](guide-atomic-service-device-ctrl.md)
- [How to Develop](guide-atomic-service-device-ctrl-overview.md)
- [Introduction to the Core Code Logic](guide-atomic-service-device-ctrl-logic.md)
- [JSON Configuration File Description](guide-atomic-service-device-ctrl-json.md)
- [Overview](guide-atomic-service-device-ctrl-json-intro.md)
- [Configuration Description of Control Components](guide-atomic-service-device-ctrl-json-control.md)
- [Configuration Description of Dialog Components](guide-atomic-service-device-ctrl-json-dialog.md)
- [LED Peripheral Control](device-wlan-led.md)
- [LED Peripheral Control](device-wlan-led-outcontrol.md)
- [Third-Party SDK Integration](device-wlan-sdk.md)
......
# FAQs<a name="EN-US_TOPIC_0000001158765981"></a>
1. **Why can't I continue device control after I exit the app and access the control page again?**
Currently, each time you access the app, you must reset the device and configure the network to obtain a new control channel. If the device is not reset, it will maintain the previous network configuration status and the network control fails.
2. **Do I have to use OneHop to access the network configuration feature?**
No. You can also directly open the device configuration page of the **entry** module for network configuration. Taping against an NFC tag is used to start the atomic service and obtain the device information.
3. **After I click the Configure network button, the network configuration progress is stuck at 20% and then a failure message is displayed. What can I do?**
This may occur when the app is killed or exited abnormally last time, as a result of the unstable performance of the network configuration version on the device side.
If the network configuration fails, exit the app, reset the device, and try again.
# Overview<a name="EN-US_TOPIC_0000001205747225"></a>
The JSON configuration file in the template is the basis for the device control UI. The JSON configuration file of the intelligent fan is stored in **control/src/main/resources/rawfile/FAN**. The configuration is as follows:
```
{
"devName": "Intelligent fan",
"devType": "0",
"prodId": "FAN", -- prodId specifies the product name displayed on the device control UI.
"templateUIInfo": [ -- Place preset Control components under templateUIInfo, with one component per line.
{"name": "Power supply"...},
{"name": "Mode"...},
{"name": "Speed control"...},
{"name": "Scheduled shutdown"...}
],
"dialogUIInfo": [ -- Dialog components can be declared under dialogUIInfo. They are displayed only upon click events.
{"name": "Shutdown time"...}
]
}
```
Two types of components \(**Control** and **Dialog** components\) are provided in the template. \(The **Control** components are directly displayed on the UI, and the **Dialog** components are displayed only after being triggered.\) You need to declare these components in the JSON configuration file.
**After modifying the JSON configuration file, reinstall and run the atomic service for the modification to take effect.**
# JSON Configuration File Description<a name="EN-US_TOPIC_0000001158604281"></a>
- **[Overview](guide-atomic-service-device-ctrl-json-intro.md)**
- **[Configuration Description of Control Components](guide-atomic-service-device-ctrl-json-control.md)**
- **[Configuration Description of Dialog Components](guide-atomic-service-device-ctrl-json-dialog.md)**
# Introduction to the Core Code Logic<a name="EN-US_TOPIC_0000001111964324"></a>
- [Core Code Description](#section17354153553419)
## Core Code Description<a name="section17354153553419"></a>
The core logic is described in **DataHandlerAbility.java**. The code process is as follows:
1. After the JS page is started, the JS code requests the template configuration from Java.
JS code:
```
async requestTemplate() {
// This function requests the JSON configuration used for display from Java.
let action = utils.makeAction(ACTION_MESSAGE_CODE_GET_TEMPLATE, {});
let result = await FeatureAbility.callAbility(action);
let resultJson = JSON.parse(result);
if (resultJson.code == 0) {
let template = JSON.parse(resultJson.data);
this.parseJson(template.template);
}
}
```
Java code:
```
private boolean onRemoteRequest(int code, MessageParcel data, MessageParcel reply) {
switch (code) {
case ACTION_MESSAGE_CODE_GET_TEMPLATE: {
reply.writeString(getWriteTemplateString());
break;
}
default: {
reply.writeString("service not defined");
return false;
}
}
return true;
}
```
2. The Java code reads the template configuration file. The configuration file path is specified by **getTemplate** in **DataHandlerAbility**. The path can be a local path or a URL.
```
private ZSONObject getTemplate() {
// source indicates whether the JSON configuration file is from a local file or an online file.
final String source = "local";
// configDir indicates the directory.
final String configDir = SampleDeviceDataHandler.EXAMPLE_TEMPLATE_FILE_DIR + "/" + productName;
// configPath indicates the URL of the JSON configuration file. You can change it corresponding
// to your product name or device ID.
final String configPath = configDir + "/" + productName + "_" + language + ".json";
ZSONObject result = null;
if (LOCAL.equals(source)) {
try {
Resource resource = abilityContext.getResourceManager().getRawFileEntry(configPath).openRawFile();
byte[] tmp = new byte[1024 * 1024];
int reads = resource.read(tmp);
if (reads != -1) {
String jsonString = new String(tmp, 0, reads, StandardCharsets.UTF_8);
result = ZSONObject.stringToZSON(jsonString);
}
} catch (IOException e) {
HiLog.error(LABEL_LOG, "Failed to open the template from the local file.");
}
} else {
try {
URL url = new URL(configPath);
URLConnection urlc = url.openConnection();
urlc.connect();
try (InputStream is = urlc.getInputStream();
InputStreamReader isReader = new InputStreamReader(is, StandardCharsets.UTF_8);
BufferedReader reader = new BufferedReader(isReader)) {
StringBuilder sb = new StringBuilder();
String str;
while ((str = reader.readLine()) != null) {
sb.append(str);
}
result = ZSONObject.stringToZSON(sb.toString());
}
} catch (IOException e) {
HiLog.error(LABEL_LOG, "Failed to open the template from the URL.");
}
}
if (result != null) {
// iconUrl is the icon's prefix path. Here we use /common/productName in the js module. You can change it into your
// cloud url. All icon files must be under iconUrl.
result.put("iconUrl", SampleDeviceDataHandler.EXAMPLE_RESOURCE_DIR + "/" + productName);
// deviceIcon is the product icon's file name. It must be under iconUrl.
result.put("deviceIcon", "/" + productName + ".png");
// logoIcon is the product logo's file name. It must be under iconUrl.
result.put("logoIcon", "/logo.png");
}
return result;
}
```
3. After obtaining the configuration, the JS code requests device data from Java.
JS code:
```
async getData() {
let action = utils.makeAction(ACTION_MESSAGE_CODE_GET_DATA, {});
await FeatureAbility.callAbility(action);
}
```
Java code:
```
private boolean onRemoteRequest(int code, MessageParcel data, MessageParcel reply) {
switch (code) {
case ACTION_MESSAGE_CODE_GET_DATA: {
deviceDataHandler.getData();
break;
}
default: {
reply.writeString("service not defined");
return false;
}
}
return true;
}
```
4. The Java code initializes the device data and calls **BaseDeviceDataHandler\#initProfileData** to return all profile data of the device.
```
NetworkDeviceDataHandler(String deviceId, DeviceDataCallback deviceDataCallback) {
super(deviceId, deviceDataCallback);
dataModel = fanDataModel;
mainHandler = new EventHandler(EventRunner.getMainEventRunner());
mainHandler.postTask(() -> initProfileData(0, "", dataModel.recoverData()));
}
```
For example, the initial data of the intelligent fan in the template is as follows:
```
private final DeviceDataModel fanDataModel = new DeviceDataModel() {
@Override
public Map<String, Object> recoverData() {
dataMap.put("switch/on", 0);
dataMap.put("windMode/mode", 0);
dataMap.put("windGear/gear", 0);
dataMap.put("shutdown/mode", 0);
return dataMap;
}
}
```
5. When a click event occurs on the JS page that has data loaded, **BaseDeviceDataHandler\#modifyDeviceProperty** is called and sent to the device. In this case, the UI does not change. After the device responds, **BaseDeviceDataHandler\#onDeviceDataChange** is called back to return the changed data to the UI layer. Now the UI is automatically refreshed.
In the template, the logic for the intelligent fan to send messages to the device is as follows:
```
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) -> {
if (code == 0) {
HiLog.info(LABEL_LOG, "Message sent successfully " + message);
dataMap.putAll(tmpMap);
mainHandler.postTask(() -> onDeviceDataChange(dataMap));
} else {
HiLog.error(LABEL_LOG, "Failed to send message, code = " +
code + " control message = " + controlMessage);
}
});
}
```
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>The template supports only message delivery from the mobile phone to the device. The function of sending messages from the device to the mobile phone will be supported in the future.
# How to Develop<a name="EN-US_TOPIC_0000001158604283"></a>
- [Overview](#section117101122133917)
- [Introduction to the Template](#section16117463402)
- [Sending Messages to Devices \(NAN Channel Available\)](#section536518118361)
- [Defining the UI of the Device Control Atomic Service](#section737418403116)
## Overview<a name="section117101122133917"></a>
The **OneHop Device Ability \(JS\)** template helps you implement the complete process of **OneHop, network configuration, and device control**. By default, the template project presents the effect of an intelligent fan. You can customize the device by referring to [Defining the UI of the Device Control Atomic Service](#section737418403116).
The template project consists of two parts:
**Network configuration atomic service \(entry module\)**
**Device control atomic service \(control module\)**
This document provides guidance on developing the device control atomic service \(control module\). For details about how to develop the network configuration atomic service \(entry module\), see [Development Guidelines on the Network Configuration Atomic Service](guide-atomic-service-netconfig-overview.md).
## Introduction to the Template<a name="section16117463402"></a>
The directory structure of the **control** module in the **OneHop Device Ability \(JS\)** template project is as follows:
```
├─control
│ └─ailife-view // This directory does not need to be modified.
│ ├─control // Component container
│ │ ├─display // Component used for information presentation
│ │ ├─enum // Component used to present enumerations
│ │ ├─increasedecrease // Component to provide the increase and decrease operations
│ │ ├─item // Child components
│ │ ├─multifunction // Multi-function components
│ │ ├─progress // Component to present a progress bar
│ │ └─reversal // Component to provide a switch
│ ├─customdisplay // Custom display area
│ ├─dialog // Dialog box container
│ │ ├─dialogbox
│ │ ├─enumlist // Dialog box used to present enumerations
│ │ ├─info // Dialog box used for information presentation
│ │ ├─picker // Picker
│ │ └─radiolist // Dialog box used to provide radio buttons
│ ├─observed
│ └─utils
└─src
└─main
├─java // For details about the content in this directory, see the class definition below.
├─js
│ └─default
│ ├─common // Local resource files, which are mainly icon resources
│ │ └─FAN
│ │ ic_on.png
│ │ ic_off.png
│ │ ...
│ └─pages
│ └─index
│ index.js // Start JS
└─resources
└─rawfile
├─FAN
FAN_en.json // Local template configuration file in English
FAN_zh.json // Local template configuration file in Chinese
```
The following table describes the classes in the source code directory **src/main/java**.
<a name="table1763715163417"></a>
<table><thead align="left"><tr id="row1270013153413"><th class="cellrowborder" valign="top" width="28.52%" id="mcps1.1.3.1.1"><p id="p20933112381015"><a name="p20933112381015"></a><a name="p20933112381015"></a>Java</p>
</th>
<th class="cellrowborder" valign="top" width="71.48%" id="mcps1.1.3.1.2"><p id="p07009114346"><a name="p07009114346"></a><a name="p07009114346"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row2070019113416"><td class="cellrowborder" valign="top" width="28.52%" headers="mcps1.1.3.1.1 "><p id="p137003123411"><a name="p137003123411"></a><a name="p137003123411"></a>MyApplication</p>
</td>
<td class="cellrowborder" valign="top" width="71.48%" headers="mcps1.1.3.1.2 "><p id="p5700131153412"><a name="p5700131153412"></a><a name="p5700131153412"></a>Application entry class.</p>
</td>
</tr>
<tr id="row1700121133420"><td class="cellrowborder" valign="top" width="28.52%" headers="mcps1.1.3.1.1 "><p id="p11700201193415"><a name="p11700201193415"></a><a name="p11700201193415"></a>ControlMainAbility</p>
</td>
<td class="cellrowborder" valign="top" width="71.48%" headers="mcps1.1.3.1.2 "><p id="p37001219341"><a name="p37001219341"></a><a name="p37001219341"></a>Entry class to start the JS page.</p>
</td>
</tr>
<tr id="row18700715343"><td class="cellrowborder" valign="top" width="28.52%" headers="mcps1.1.3.1.1 "><p id="p1670011118348"><a name="p1670011118348"></a><a name="p1670011118348"></a>BaseDeviceDataHandler</p>
</td>
<td class="cellrowborder" valign="top" width="71.48%" headers="mcps1.1.3.1.2 "><p id="p97001814349"><a name="p97001814349"></a><a name="p97001814349"></a>Abstract class for device data exchange.</p>
</td>
</tr>
<tr id="row1170019193416"><td class="cellrowborder" valign="top" width="28.52%" headers="mcps1.1.3.1.1 "><p id="p4700111343"><a name="p4700111343"></a><a name="p4700111343"></a>NetworkDeviceDataHandler</p>
</td>
<td class="cellrowborder" valign="top" width="71.48%" headers="mcps1.1.3.1.2 "><p id="p570118193413"><a name="p570118193413"></a><a name="p570118193413"></a>Inherits from the abstract class <strong id="b14468115182816"><a name="b14468115182816"></a><a name="b14468115182816"></a>BaseDeviceDataHandler</strong> to implement device data exchange in Neighbor Awareness Networking (NAN) connection mode. You can modify the code based on the device in use.</p>
</td>
</tr>
<tr id="row11701111143410"><td class="cellrowborder" valign="top" width="28.52%" headers="mcps1.1.3.1.1 "><p id="p10701218342"><a name="p10701218342"></a><a name="p10701218342"></a>SampleDeviceDataHandler</p>
</td>
<td class="cellrowborder" valign="top" width="71.48%" headers="mcps1.1.3.1.2 "><p id="p7701161173414"><a name="p7701161173414"></a><a name="p7701161173414"></a>Inherits from the abstract class <strong id="b127801919153320"><a name="b127801919153320"></a><a name="b127801919153320"></a>BaseDeviceDataHandler</strong>. This provides sample code, and you do not need to modify the code.</p>
</td>
</tr>
<tr id="row670141203410"><td class="cellrowborder" valign="top" width="28.52%" headers="mcps1.1.3.1.1 "><p id="p1970119114344"><a name="p1970119114344"></a><a name="p1970119114344"></a>DataHandlerAbility</p>
</td>
<td class="cellrowborder" valign="top" width="71.48%" headers="mcps1.1.3.1.2 "><p id="p1370113115344"><a name="p1370113115344"></a><a name="p1370113115344"></a>Implements a channel for message exchange between a Java-based system and a JS-based one.</p>
</td>
</tr>
</tbody>
</table>
<a name="table36377582916"></a>
<table><thead align="left"><tr id="row1363810581196"><th class="cellrowborder" valign="top" width="28.52%" id="mcps1.1.3.1.1"><p id="p13513164112106"><a name="p13513164112106"></a><a name="p13513164112106"></a><strong id="b251316417107"><a name="b251316417107"></a><a name="b251316417107"></a>JS</strong></p>
</th>
<th class="cellrowborder" valign="top" width="71.48%" id="mcps1.1.3.1.2"><p id="p06383581290"><a name="p06383581290"></a><a name="p06383581290"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row1763835810916"><td class="cellrowborder" valign="top" width="28.52%" headers="mcps1.1.3.1.1 "><p id="p06381581496"><a name="p06381581496"></a><a name="p06381581496"></a>control/ailife-view</p>
</td>
<td class="cellrowborder" valign="top" width="71.48%" headers="mcps1.1.3.1.2 "><p id="p116381658694"><a name="p116381658694"></a><a name="p116381658694"></a>Home appliance components, which can be referenced in the JSON configuration file.</p>
</td>
</tr>
<tr id="row126381658793"><td class="cellrowborder" valign="top" width="28.52%" headers="mcps1.1.3.1.1 "><p id="p1963817584912"><a name="p1963817584912"></a><a name="p1963817584912"></a>index.js</p>
</td>
<td class="cellrowborder" valign="top" width="71.48%" headers="mcps1.1.3.1.2 "><p id="p963835816912"><a name="p963835816912"></a><a name="p963835816912"></a>Device control home page. Different components under <strong id="b15756344203518"><a name="b15756344203518"></a><a name="b15756344203518"></a>ailife-view</strong> are loaded based on the JSON configuration file.</p>
</td>
</tr>
</tbody>
</table>
## Sending Messages to Devices \(NAN Channel Available\)<a name="section536518118361"></a>
The **OneHop Device Ability \(JS\)** template implements delivery of messages to devices by calling Java APIs. You can invoke this template in **NetworkDeviceDataHandler**.
**JS API: NetConfig.sendMessage\(commonInfo, message, callbackFunc\)**
- Dependency: The **fa-netconfig.js** file in the template is imported.
- Note:
1. Set **commonInfo** to the configured channel's session ID, which is obtained by the network configuration atomic service.
2. Set **message** to the message \(in a string\) to be sent to the device.
3. **callbackFunc** specifies whether the message is successfully sent.
Example:
```
sendMessage: function () {
let callbackFunc = function (value) {
// sendMessage callback
};
let commonInfo = {
sessionId: getApp(this).ConfigParams.deviceInfo.sessionId
};
getApp(this).Netconfig.sendMessage(commonInfo, message, callbackFunc).then(
function (result) {
let ret = JSON.parse(result);
// sendMessage message delivery result
});
}
```
**Java API: NetConfigApi._getInstance_\(\).sendMessage\(CommonInfo commonInfo, String message, BaseCallback<String\> callback\)**
Dependency: Add **implementation\(group:'com.huawei.hilink',name:'ailifeability',version:'1.0.0.1',ext:'har'\)** to **dependencies** in the **build.gradle** file.
Note:
1. Set **commonInfo** to the configured channel's session ID, which is obtained by the network configuration atomic service.
2. Set **message** to the message \(in a string\) to be sent to the device.
3. **callback** specifies whether the message is successfully sent.
Example:
```
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) -> {
if (code == 0) {
HiLog.info(LABEL_LOG, "Message sent successfully" + message);
dataMap.putAll(tmpMap);
mainHandler.postTask(() -> onDeviceDataChange(dataMap));
} else {
HiLog.error(LABEL_LOG, "Failed to send the message. Code =" +
code + " control message = " + controlMessage);
}
});
}
```
## Defining the UI of the Device Control Atomic Service<a name="section737418403116"></a>
This section describes how to develop the device control UI. There are two methods:
1. Use preset components and configure the JSON configuration file. Using this method, you can quickly create the device control UI. In addition, every component on the UI is bound with a click event and processing logic.
2. Use native components to develop the device control UI from the scratch. This method provides more flexibility.
This section describes the procedure using the first method. The development procedure using the second method will be provided later.
The template provides a variety of UI components in **control/ailife-view** and defines a set of JSON configuration rules. This set of rules references custom UI components to generate a custom device control UI.
The component reference code in **control/src/main/js/default/pages/index/index.hml** is as follows. \(For details about the component style, see [JSON Configuration File Description](guide-atomic-service-device-ctrl-json-intro.md).\)
![](figures/component-reference-code.png)
**To build a device control UI by using preset components, perform the following steps:**
1. Declare the JSON configuration file that describes the UI and save the file in the **control/src/main/resources/rawfile/<deviceName\>** directory.
For details about the fields in the JSON configuration file, see [JSON Configuration File Description](guide-atomic-service-device-ctrl-json-intro.md). The file name must be <deviceName\>\_<language\>.json.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>The template provides four samples: lamp, toothbrush, soy milk maker, and intelligent fan. The configuration files are **LAMP.json**, **TOOTHBRUSH.json**, **SOYMILKMACHINE.json**, and **FAN.json**, respectively.
>By default, **FAN.json** is used.
![](figures/control-module.png)
2. Use UX icon resources, which can be local or online resources.
To use local resources, pack them to the **control/src/main/js/default/common/_<deviceName\>_** directory. Then you can directly reference them in the JSON configuration file.
![](figures/control-module-icon.png)
To use online resources, you must add the resource URL to the code. Specifically, in the **getTemplate** method of **DataHandlerAbility.java**, set **iconUrl** to the resource URL. The resource referenced in the JSON configuration file is the relative path of the resource URL. The following is an example of the part in the **getTemplate** method that needs to be modified:
```
if (result != null) {
// iconUrl is the icon's prefix path. Here we use /common/productName in the JS module. You can change it to your URL. All icon files must be under iconUrl.
result.put("iconUrl", SampleDeviceDataHandler.EXAMPLE_RESOURCE_DIR + "/" + productName);
// deviceIcon is the product icon's file name. It must be under iconUrl.
result.put("deviceIcon", "/" + productName + ".png");
// logoIcon is the product logo's file name. It must be under iconUrl.
result.put("logoIcon", "/logo.png");
}
```
3. Set **DEVICE\_DATA\_MODE** in **DataHandlerAbility.java** to **DEVICE\_DATA\_MODE\_NETWORK\_DEVICE**. Then, you can use **NetworkDeviceDataHandler.java** to process data and control devices in seconds.
For details, see **fanDataModel** in **NetworkDeviceDataHandler.java**. The template has implemented the data processing logic of the intelligent fan. This processing logic converts the data passed by the click events into instructions and sends the instructions to the device. You can add your own device processing logic by referring to the fan model.
```
public class NetworkDeviceDataHandler extends BaseDeviceDataHandler {
private static final HiLogLabel LABEL_LOG = new HiLogLabel(HiLog.DEBUG, 0, "MessageDataHandler");
private static String sessionId = null;
private final DeviceDataModel dataModel;
private final EventHandler mainHandler;
private final Map<String, Object> dataMap = new HashMap<>();
private final DeviceDataModel fanDataModel = new DeviceDataModel() {
@Override
public Map<String, Object> recoverData() {
dataMap.put("switch/on", 0);
dataMap.put("windMode/mode", 0);
dataMap.put("windGear/gear", 0);
dataMap.put("shutdown/mode", 0);
return dataMap;
}
}
}
```
To learn more about the code processing flow, see [Core Code Description](guide-atomic-service-device-ctrl-logic.md#section17354153553419).
# Development Guidelines on the Device Control Atomic Service<a name="EN-US_TOPIC_0000001158764269"></a>
- **[How to Develop](guide-atomic-service-device-ctrl-overview.md)**
- **[Introduction to the Core Code Logic](guide-atomic-service-device-ctrl-logic.md)**
- **[JSON Configuration File Description](guide-atomic-service-device-ctrl-json.md)**
# Introduction to the Core Code<a name="EN-US_TOPIC_0000001111806146"></a>
The core code in the project is described as follows:
1. After the **MainAbility** is started, the Java code uses **nanSessionId** read from the **intent** for network configuration and uses **productId** to determine the type of the device to connect. By default, a smart fan is used.
For details about how to read device information, see **onStart** in **MainAbility.java**.
In addition, register **abilityContext** and **sessionId** with the network configuration SDK.
```
String sessionId = intent.getStringParam("nanSessionId");
if ("null".equals(sessionId) || "".equals(sessionId)) {
NetConfigAbility.register(this, null);
} else {
NetConfigAbility.register(this, sessionId);
}
```
2. The Java code passes **productId**, **productName**, and **sessionId** read from the **MainAbility** to JS.
For details on the code, see **MainAbility.java**.
```
IntentParams intentParams = intent.getParams();
if (intentParams != null) {
intentParams.setParam("productId", productId);
intentParams.setParam("productName", productName);
intentParams.setParam("sessionId", sessionId);
setPageParams(null, intentParams);
}
```
3. The JS code displays the device icon based on **productName**. For details on the code, see **device.js**.
```
onInit() {
this.deviceName = this.$t('strings.device-name');
this.deviceImg = '/common/img/' + this.productName + ".png";
getApp(this).Product.productName = this.productName;
getApp(this).Product.productId = this.productId;
getApp(this).ConfigParams.sessionId = this.sessionId;
}
```
4. After you click the **Configure network** button, the network configuration logic is executed. For details on the code, see **netconfig.js**.
1. Discover the nearest device through Neighbor Awareness Networking \(NAN\) broadcast.
```
discoverDevice() {
let scanInfo = {
duration: 30,
lockTime: 60,
sessionId: getApp(this).ConfigParams.sessionId
};
// Step 1 Discover the device through NAN broadcast.
getApp(this).NetConfig.discoveryByNAN(scanInfo, (result) => {
if (result.code == 0) {
this.progress = this.progressStatus[1];
this.desc = this.descStatus[1];
getApp(this).ConfigParams.deviceInfo = result.data;
this.registerDisconnectCallback(result.data.sessionId);
this.connectDevice();
} else {
this.progress = this.progressStatus[4];
this.desc = this.failDescStatus[1];
this.disconnectDevice();
}
});
}
```
2. Connect to the device.
```
connectDevice() {
let connectInfo = {
targetDeviceId: getApp(this).ConfigParams.deviceInfo.productId,
type: 0,
pin: '0123456789012345',
password: getApp(this).ConfigParams.deviceInfo.sn,
sessionId: getApp(this).ConfigParams.deviceInfo.sessionId
};
// Step 2 Connect the device.
getApp(this).NetConfig.connectDevice(connectInfo, (result) => {
if (result.code === 0) {
this.progress = this.progressStatus[2];
this.desc = this.descStatus[2];
this.getWifiInfo();
} else {
this.progress = this.progressStatus[4];
this.desc = this.failDescStatus[2];
this.disconnectDevice();
}
});
}
```
3. Obtain the Wi-Fi information used by the phone.
```
getWifiInfo() {
// Step 3 Obtain the Wi-Fi information used by the phone for connection.
getApp(this).NetConfig.getWifiList((result) => {
if (result.code == 0 && result.data && result.data.length > 0) {
this.progress = this.progressStatus[3];
this.desc = this.descStatus[3];
this.configDevice(result.data[0]);
} else {
this.progress = this.progressStatus[4];
this.desc = this.descStatus[3];
this.disconnectDevice();
}
});
}
```
4. Configure the network for the device. After the configuration is successful, the device control page is displayed.
```
async configDevice(wifiApInfo) {
let netConfigInfo = {
ssid: wifiApInfo.ssid,
ssidPassword: '',
isDefaultPassword: true,
channel: wifiApInfo.channel,
sessionId: getApp(this).ConfigParams.deviceInfo.sessionId,
type: 0,
wifiApId: wifiApInfo.wifiApId,
vendorData: '',
timeout: 30,
paramValid: true
};
// Step 4 Configure the device network.
getApp(this).NetConfig.configDeviceNet('deviceInfo', 'accountInfo', netConfigInfo, (result) => {
if (result.code == 0) {
this.progress = this.progressStatus[4];
this.desc = this.descStatus[4];
this.registerMsgReceive()
// Step 5 Display the device control page after a successful network configuration.
this.goToControl();
} else {
this.progress = this.progressStatus[4];
this.desc = this.failDescStatus[4];
this.disconnectDevice();
}
});
}
```
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>By default, the template project redirects to the device control page configured in the **control** module. You can modify the code for redirection to a custom device control page. Note that **sessionId** must be passed to subsequent pages for sending messages to the device.
>The JS API for sending messages to devices is **NetConfig.sendMessage\(commonInfo, message, callbackFunc\)**.
>The Java API for sending messages to devices is **NetConfigApi._getInstance_\(\).sendMessage\(CommonInfo, String, BaseCallback<String\>\)**.
# How to Develop<a name="EN-US_TOPIC_0000001158765979"></a>
- [Overview](#section117101122133917)
- [Project Structure](#section163058534218)
- [Defining the UI of the Network Configuration Atomic Service](#section129531555424)
## Overview<a name="section117101122133917"></a>
The **OneHop Device Ability \(JS\)** template helps you implement the complete process of **OneHop, network configuration, and device control**. By default, the template project presents the effect of a smart fan. You can customize the device by referring to [Defining the UI of the Network Configuration Atomic Service](#section129531555424).
The template project consists of two parts:
**Network configuration atomic service \(entry module\)**
**Device control atomic service \(control module\)**
This document provides guidance on developing the network configuration atomic service \(entry module\). For details about how to develop the device control atomic service \(control module\), see [Development Guidelines on the Device Control Atomic Service](guide-atomic-service-device-ctrl-overview.md).
## Project Structure<a name="section163058534218"></a>
The following figure shows the directory structure of the **entry** module in the **OneHop Device Ability \(JS\)** template project.
![](figures/project-structure.png)
The following table describes the classes in the source code directory.
<a name="table21156122315"></a>
<table><thead align="left"><tr id="row81671115238"><th class="cellrowborder" valign="top" width="22.36%" id="mcps1.1.3.1.1"><p id="p181670112231"><a name="p181670112231"></a><a name="p181670112231"></a>Class</p>
</th>
<th class="cellrowborder" valign="top" width="77.64%" id="mcps1.1.3.1.2"><p id="p18167111122313"><a name="p18167111122313"></a><a name="p18167111122313"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row141674115231"><td class="cellrowborder" colspan="2" valign="top" headers="mcps1.1.3.1.1 mcps1.1.3.1.2 "><p id="p11679172319"><a name="p11679172319"></a><a name="p11679172319"></a><strong id="b1716713114234"><a name="b1716713114234"></a><a name="b1716713114234"></a>Java</strong></p>
</td>
</tr>
<tr id="row1516781132314"><td class="cellrowborder" valign="top" width="22.36%" headers="mcps1.1.3.1.1 "><p id="p116751132311"><a name="p116751132311"></a><a name="p116751132311"></a>MyApplication</p>
</td>
<td class="cellrowborder" valign="top" width="77.64%" headers="mcps1.1.3.1.2 "><p id="p2016719117238"><a name="p2016719117238"></a><a name="p2016719117238"></a>Application entry class.</p>
</td>
</tr>
<tr id="row101670192310"><td class="cellrowborder" valign="top" width="22.36%" headers="mcps1.1.3.1.1 "><p id="p4167121172314"><a name="p4167121172314"></a><a name="p4167121172314"></a>MainAbility</p>
</td>
<td class="cellrowborder" valign="top" width="77.64%" headers="mcps1.1.3.1.2 "><p id="p016718116235"><a name="p016718116235"></a><a name="p016718116235"></a>Entry class to start the JS page and process device information read from an NFC tag.</p>
</td>
</tr>
<tr id="row71685114234"><td class="cellrowborder" colspan="2" valign="top" headers="mcps1.1.3.1.1 mcps1.1.3.1.2 "><p id="p21681513237"><a name="p21681513237"></a><a name="p21681513237"></a><strong id="b21688112316"><a name="b21688112316"></a><a name="b21688112316"></a>JS</strong></p>
</td>
</tr>
<tr id="row5168101192316"><td class="cellrowborder" valign="top" width="22.36%" headers="mcps1.1.3.1.1 "><p id="p10168117236"><a name="p10168117236"></a><a name="p10168117236"></a>default/pages/device/device.js</p>
</td>
<td class="cellrowborder" valign="top" width="77.64%" headers="mcps1.1.3.1.2 "><p id="p181681518237"><a name="p181681518237"></a><a name="p181681518237"></a>Device introduction page, which is displayed after a OneHop operation.</p>
</td>
</tr>
<tr id="row1016814111235"><td class="cellrowborder" valign="top" width="22.36%" headers="mcps1.1.3.1.1 "><p id="p1816814112316"><a name="p1816814112316"></a><a name="p1816814112316"></a>default/pages/netconfig/netconfig.js</p>
</td>
<td class="cellrowborder" valign="top" width="77.64%" headers="mcps1.1.3.1.2 "><p id="p111681119236"><a name="p111681119236"></a><a name="p111681119236"></a>Network configuration page, which is responsible for the logic related to network configuration. This page is displayed after you click <strong id="b198725743613"><a name="b198725743613"></a><a name="b198725743613"></a>Configure network</strong> on the device introduction page.</p>
</td>
</tr>
</tbody>
</table>
## Defining the UI of the Network Configuration Atomic Service<a name="section129531555424"></a>
1. Process the product ID read from the NFC tag in the **onStart** method of the **MainAbility**. **You can map productId to a different device type and change productName to a specific device name**. By default, a smart fan is used.
```
@Override
public void onStart(Intent intent) {
intent.setParam("window_modal", 3);
setInstanceName(JS_MODULE);
Object productInfo = Objects.requireNonNull(intent.getParams()).getParam("productInfo");
if (productInfo != null) {
productId = (String) productInfo;
// Modify your product name according to your product ID in the NFC tag.
productName = "FAN";
}
}
```
2. Place the product diagram in the resource directory for UI display. **Note that the file name must be <deviceName\>.png and the device name must be the same as the value of productName.**
![](figures/place-product-diagram.png)
The product diagram is displayed on the device introduction page and network configuration page.
3. Add **deviceType: 1** to the **goToControl** method of **entry\\src\\main\\js\\default\\pages\\netconfig\\netconfig.js** to improve the stability of network configuration.
```
goToControl() {
let target = {
bundleName: 'com.example.middleplatform.deviceoperate',
abilityName: 'com.example.middleplatform.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();
}
```
# Development Guidelines on the Network Configuration Atomic Service<a name="EN-US_TOPIC_0000001111966036"></a>
- **[How to Develop](guide-atomic-service-netconfig-overview.md)**
- **[Introduction to the Core Code](guide-atomic-service-netconfig-logic.md)**
- **[Calling of Network Configuration APIs](guide-atomic-service-netconfig-api.md)**
- **[FAQs](faqs.md)**
# Configuring a Service Association Intent<a name="EN-US_TOPIC_0000001168233266"></a>
Configure the association intent for the atomic service on the HUAWEI Ability Gallery to match the product ID in the NFC tag. This way, users can tap their phone against the NFC tag to obtain the atomic service information and thereby launch the network configuration atomic service.
Let's see how to configure the association intent for an atomic service on the HUAWEI Ability Gallery.
1. Use a Huawei developer account that has completed identity verification to log in to the [HUAWEI Developers](https://developer.huawei.com/consumer/en/). Then, access the console.
![](figures/console.png)
2. Choose **Ecosystem services** \> **Smart services** and access HUAWEI Ability Gallery. If this is the first time you use HUAWEI Ability Gallery, read and sign the **HUAWEI Ability Gallery Service Agreement**.
![](figures/ability-gallery-service.png)
3. Click the **Create ability** button and then select **HarmonyOS test ability**.
![](figures/harmonyos-test-ability.png)
4. Set **Ability name**, **Category**, and **Default language**, and then click **Create**.
![](figures/harmonyos-test-ability-model.png)
5. Configure the ability information, including the following:
- Basic information, such as the ability version number, version description, and ability level. When you are done, click **Save**.
- Display information, such as the brief description, developer brand, and ability icon. Be sure to upload the large icon of the ability. When you are done, click **Save**.
6. Choose **Configure** \> **HarmonyOS tags** and click **Add** to add a device tag. Set **Product model** to the product ID you have obtained in the HUAWEI DevEco Assistant app, and **Product sub-model** to **00**, and then click **Save**.
![](figures/harmonyos-tag.png)
7. Choose **Configure** \> **FA information**, configure the FA basic information and setting mode, and then click **Save**.
- Basic information: Set **Type** to **APK/RPK/FA/H5 link**.
- Setting mode: Configure **FA Link** fields.
- **App package**: Enter the value of **bundleName** in the **config.json** file.
- **Module name**: Enter the value of **moduleName** in the **config.json** file of the entry module \(network configuration module\).
- **Ability name**: Enter the value of **mainAbility** in the **config.json** file of the entry module \(network configuration module\).
![](figures/fa-information.png)
8. On the **Test** tab page, click **Prepare test** to start the test. The test is valid for one month. After the validity period expires, click **Prepare again**.
![](figures/ability-test.png)
# Developing Atomic Services<a name="EN-US_TOPIC_0000001213473151"></a>
Use the **OneHop Device Ability\(JS\)** template to implement the process from tapping and network configuration to device control. The HarmonyOS atomic service development for OneHop involves the network configuration atomic service and the device control atomic service. Before you proceed with the following procedure, make sure you have installed [DevEco Studio 3.0 Beta1](https://developer.harmonyos.com/cn/develop/deveco-studio#download_beta) or later and [built the development environment](https://developer.harmonyos.com/en/docs/documentation/doc-guides/installation_process-0000001071425528).
1. Open the DevEco Studio project wizard using either of the following methods:
- If no project is open, select **Create Project** on the welcome page.
- If a project is already open, choose **File** \> **New** \> **New Project** from the menu bar.
2. In the project wizard, click **Template Market** and download the **OneHop Device Ability\(JS\)** template.
![](figures/choose-template.png)
3. Return to the project creation page. From the template list, select the downloaded **OneHop Device Ability** template and click **Next** to configure the project.
4. In the project configuration, set **Project Type** to **Service**, select **Show in Service Center**, and click **Finish**.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>Generally, the device control and network configuration atomic services are started by OneHop. In the debugging phase, to start these atomic services directly by touching the respective app icon on the phone's home screen, you can change the value of the **installationFree** field in the project **config.json** file to **false**. After the debugging is complete, change the value back to **true**.
![](figures/configure-project.png)
5. In the **entry\\src\\main\\js\\default\\pages\\netconfig\\netconfig.js** file, add **deviceType: 1** to the **goToControl** method, so that the atomic services can be started from the local device.
```
goToControl() {
let target = {
bundleName: 'com.example.middleplatform.deviceoperate',
abilityName: 'com.example.middleplatform.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();
}
```
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>The **OneHop Device Ability\(JS\)** template has been preconfigured with the network configuration and device control atomic services of an intelligent fan. To modify the UI and functions of these atomic services, refer to the following:
>- Network configuration atomic service: [Development Guidelines on the Network Configuration Atomic Service](guide-atomic-service-netconfig-overview.md)
>- Device control atomic service: [Development Guidelines on the Device Control Atomic Service](guide-atomic-service-device-ctrl-overview.md)
6. Sign the atomic services so they can run on Huawei phones. For detailed operations, see [Automatically Signing Your App Using DevEco Studio](https://developer.harmonyos.com/en/docs/documentation/doc-guides/ide_debug_device-0000001053822404#section837891802519).
7. On the DevEco Studio menu bar, choose **Run** \> **Edit Configurations**. Then, select **Deploy Multi Hap Packages** under the **entry** module, so that the **control** module \(device control atomic service\) is automatically installed on the device when the **entry** module \(network configuration atomic service\) is run.
![](figures/edit-configurations.png)
8. On the toolbar, select the **entry** module and click **Run** to install the network configuration and device control atomic services on the device.
In the **entry\\src\\main\\resources\\base\\element\\string.json** file, **entry\_MainAbility** indicates the name of the network configuration atomic service. You can change it to whatever you prefer.
In the **control\\src\\main\\resources\\base\\element\\string.json** file, **control\_ControlMainAbility** indicates the name of the device control atomic service. You can change it to whatever you prefer.
![](figures/run-entry.png)
9. On the phone's home screen, click the **Net Config** button and check whether the device authentication atomic service is started, as shown below.
![](figures/network-configuration.png)
# Developing the Hi3861 Development Board<a name="EN-US_TOPIC_0000001167754794"></a>
- [Writing Source Code](#section103951747175415)
- [Compiling Source Code](#section188441785558)
- [Burning Source Code](#section91141823135914)
Use the DevEco Device Tool to develop, compile, and burn the Hi3861 source code in the Ubuntu development environment. For details, see [Ubuntu Development Environment](https://device.harmonyos.com/en/docs/ide/user-guides/install_ubuntu-0000001072959308).
## Writing Source Code<a name="section103951747175415"></a>
1. Decompress the Hi3861 source code package. In DevEco Device Tool, click **Import Project** to open the source code file.
![](figures/import-project.png)
2. When a message is displayed to indicate that the selected directory is not a project directory, click **Import** to continue.
![](figures/import-project-confirm.png)
3. Set **MCU** to **Hi3861**, **Board** to **Hi3861**, and **Framework** to **Hb**, and then click **Import**.
![](figures/import-project-setting.png)
4. Copy the **hals** and **winder** folders in the Hi3861 demo code to the **applications/sample/wifi-iot/app/** directory in the source code project.
![](figures/copy-hals-and-winder.png)
5. Open the **device/hisilicon/hispark\_pegasus/hi3861\_adapter/hals/communication/wifi\_lite/wifiservice/source/wifi\_device.c** file and comment out the following code:
```
if (LockWifiEventLock() != WIFI_SUCCESS) {
return;
}
if (UnlockWifiEventLock() != WIFI_SUCCESS) {
return;
}
```
6. Open the **device/hisilicon/hispark\_pegasus/sdk\_liteos/build/config/usr\_config.mk** file, find **CONFIG\_I2C\_SUPPORT is not set**, uncomment it, and change it to **CONFIG\_I2C\_SUPPORT=y**.
![](figures/set-config-i2c-support.png)
7. Open the **applications/sample/wifi-iot/app/BUILD.gn** file, change **startup** in the **features** field to **winder**, and add the index **deps** of the **winder** module. Sample code is as follows:
```
import("//build/lite/config/component/lite_component.gni")
lite_component("app") {
features = [
"winder",
]
deps = [ "//applications/sample/wifi-iot/app/hals:hi3861_hals" ]
}
```
## Compiling Source Code<a name="section188441785558"></a>
Use DevEco Device Tool to compile the source code.
1. Download and decompress the tools listed below.
<a name="table197391139175613"></a>
<table><thead align="left"><tr id="en-us_topic_0000001192526021_row6207164803718"><th class="cellrowborder" valign="top" width="19.121912191219124%" id="mcps1.1.4.1.1"><p id="en-us_topic_0000001192526021_p1220714482376"><a name="en-us_topic_0000001192526021_p1220714482376"></a><a name="en-us_topic_0000001192526021_p1220714482376"></a>Tool</p>
</th>
<th class="cellrowborder" valign="top" width="55.055505550555054%" id="mcps1.1.4.1.2"><p id="en-us_topic_0000001192526021_p4207184820378"><a name="en-us_topic_0000001192526021_p4207184820378"></a><a name="en-us_topic_0000001192526021_p4207184820378"></a>How to Obtain</p>
</th>
<th class="cellrowborder" valign="top" width="25.82258225822582%" id="mcps1.1.4.1.3"><p id="en-us_topic_0000001192526021_p420724863714"><a name="en-us_topic_0000001192526021_p420724863714"></a><a name="en-us_topic_0000001192526021_p420724863714"></a>Path in Tools</p>
</th>
</tr>
</thead>
<tbody><tr id="en-us_topic_0000001192526021_row46755108331"><td class="cellrowborder" valign="top" width="19.121912191219124%" headers="mcps1.1.4.1.1 "><p id="en-us_topic_0000001192526021_p19675161073317"><a name="en-us_topic_0000001192526021_p19675161073317"></a><a name="en-us_topic_0000001192526021_p19675161073317"></a>GN</p>
</td>
<td class="cellrowborder" valign="top" width="55.055505550555054%" headers="mcps1.1.4.1.2 "><p id="en-us_topic_0000001192526021_p1857514815456"><a name="en-us_topic_0000001192526021_p1857514815456"></a><a name="en-us_topic_0000001192526021_p1857514815456"></a><a href="https://repo.huaweicloud.com/harmonyos/compiler/gn/1717/linux/gn-linux-x86-1717.tar.gz" target="_blank" rel="noopener noreferrer">https://repo.huaweicloud.com/harmonyos/compiler/gn/1717/linux/gn-linux-x86-1717.tar.gz</a></p>
</td>
<td class="cellrowborder" valign="top" width="25.82258225822582%" headers="mcps1.1.4.1.3 "><p id="en-us_topic_0000001192526021_p16261055122016"><a name="en-us_topic_0000001192526021_p16261055122016"></a><a name="en-us_topic_0000001192526021_p16261055122016"></a>Folder where <strong id="b18697112316348"><a name="b18697112316348"></a><a name="b18697112316348"></a>gn.exe</strong> is located.</p>
</td>
</tr>
<tr id="en-us_topic_0000001192526021_row429115712472"><td class="cellrowborder" valign="top" width="19.121912191219124%" headers="mcps1.1.4.1.1 "><p id="en-us_topic_0000001192526021_p1558143018453"><a name="en-us_topic_0000001192526021_p1558143018453"></a><a name="en-us_topic_0000001192526021_p1558143018453"></a>Ninja</p>
</td>
<td class="cellrowborder" valign="top" width="55.055505550555054%" headers="mcps1.1.4.1.2 "><p id="en-us_topic_0000001192526021_p117021959204517"><a name="en-us_topic_0000001192526021_p117021959204517"></a><a name="en-us_topic_0000001192526021_p117021959204517"></a><a href="https://repo.huaweicloud.com/harmonyos/compiler/ninja/1.9.0/linux/ninja.1.9.0.tar" target="_blank" rel="noopener noreferrer">https://repo.huaweicloud.com/harmonyos/compiler/ninja/1.9.0/linux/ninja.1.9.0.tar</a></p>
</td>
<td class="cellrowborder" valign="top" width="25.82258225822582%" headers="mcps1.1.4.1.3 "><p id="en-us_topic_0000001192526021_p126125572018"><a name="en-us_topic_0000001192526021_p126125572018"></a><a name="en-us_topic_0000001192526021_p126125572018"></a>Folder where <strong id="b187123163361"><a name="b187123163361"></a><a name="b187123163361"></a>ninja.exe</strong> is located.</p>
</td>
</tr>
<tr id="en-us_topic_0000001192526021_row72912072477"><td class="cellrowborder" valign="top" width="19.121912191219124%" headers="mcps1.1.4.1.1 "><p id="en-us_topic_0000001192526021_p12396121984619"><a name="en-us_topic_0000001192526021_p12396121984619"></a><a name="en-us_topic_0000001192526021_p12396121984619"></a>gcc_riscv32</p>
</td>
<td class="cellrowborder" valign="top" width="55.055505550555054%" headers="mcps1.1.4.1.2 "><p id="en-us_topic_0000001192526021_p42070254469"><a name="en-us_topic_0000001192526021_p42070254469"></a><a name="en-us_topic_0000001192526021_p42070254469"></a><a href="https://repo.huaweicloud.com/harmonyos/compiler/gcc_riscv32/7.3.0/linux/gcc_riscv32-linux-7.3.0.tar.gz" target="_blank" rel="noopener noreferrer">https://repo.huaweicloud.com/harmonyos/compiler/gcc_riscv32/7.3.0/linux/gcc_riscv32-linux-7.3.0.tar.gz</a></p>
</td>
<td class="cellrowborder" valign="top" width="25.82258225822582%" headers="mcps1.1.4.1.3 "><p id="en-us_topic_0000001192526021_p5261855182018"><a name="en-us_topic_0000001192526021_p5261855182018"></a><a name="en-us_topic_0000001192526021_p5261855182018"></a><strong id="b798284818378"><a name="b798284818378"></a><a name="b798284818378"></a>gcc_riscv32</strong> folder.</p>
</td>
</tr>
</tbody>
</table>
2. In DevEco Device Tool, choose **Tools**, and then click **Add user component** to add Gn, Ninja, and gcc\_riscv32. When adding the tools, note that the tool names cannot be changed.
![](figures/add_tools.png)
3. Go to ![](figures/2021-01-27_170334-9.png) \> **PROJECT TASKS** \> **Build** to start compilation.
![](figures/build-project.png)
4. Wait until **SUCCESS** is displayed in the **TERMINAL** window, indicating that the compilation is complete.
![](figures/build-success.png)
## Burning Source Code<a name="section91141823135914"></a>
1. Connect the PC and the target development board through the USB port. For details, see [Hi3861 Development Board](https://device.harmonyos.com/en/docs/start/introduce/oem_minitinier_des_3861-0000001105041324).
2. <a name="en-us_topic_0000001056563976_li848662117291"></a>Open Device Manager, and then check and record the serial port number corresponding to the development board.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>If the serial port number is not displayed correctly, follow the steps described in [Installing the Serial Port Driver on Hi3861 V100](https://device.harmonyos.com/en/docs/ide/user-guides/hi3861-drivers-0000001058153433).
![](figures/hi3861-record-the-serial-port-number-10.png)
3. In DevEco Device Tool, choose **QUICK ACCESS** \> **DevEco Home** \> **Projects**, and then click **Settings**.
![](figures/project_settings.png)
4. On the **Partition Configuration** tab page, modify the settings. Unless otherwise required, you can leave the fields at their default settings.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>If you obtain the file to be burnt by way of copying, manually change the path of the file to be burnt: Click the tab of the file to be burnt, select **Partition\_bin** from the **New Option** drop-down list box in **Partition Settings**, and set the path of the file to be burnt in **Partition\_bin**.
5. On the **hi3861** tab page, set the burning options.
- **upload\_port**: Select the serial port number obtained in [2](#en-us_topic_0000001056563976_li848662117291).
- **upload\_protocol**: Select the programming protocol. For Windows, set this parameter to **burn-serial** or **hiburn-serial**. For Linux, set this parameter to **hiburn-serial**.
- **upload\_partitions**: Select the file to be burned. **hi3861\_app** is selected by default.
![](figures/burn_settings.png)
6. Click **Save** on the top to save your settings.
7. Open the project file. In the DevEco Device Tool window, go to **PROJECT TASKS** \> **hi3861** \> **Upload** to start burning.
![](figures/hi3861-upload-11.png)
8. When the following information is displayed, press the RST button on the development board to restart it.
![](figures/hi3861-restart-the-development-board-12.png)
9. Wait until the burning is complete. When the following message is displayed, the burning is successful.
![](figures/hi3861-burning-succeeded-13.png)
# Preparations<a name="EN-US_TOPIC_0000001213554677"></a>
To develop OneHop, you need to develop the HarmonyOS atomic service and Hi3861 development board. Before you start, make the following preparations:
**Preparations for HarmonyOS atomic service development:**
- Prepare a Huawei Mate series or P series phone that has been updated to HarmonyOS 2.0.0.168 or later.
- Download [DevEco Studio 3.0 Beta1](https://developer.harmonyos.com/cn/develop/deveco-studio#download_beta) and [build the development environment](https://developer.harmonyos.com/en/docs/documentation/doc-guides/installation_process-0000001071425528).
- Download and install the HUAWEI DevEco Assistant app from Huawei AppGallery.
- Prepare an NFC tag. You can tap the NFC tag with your phone to ensure that the NFC function is available.
- Go to **Settings** \> **Apps & services** \> **Apps**, search for **AI Life Service**, and check whether the version of AI Life is 12.0.2.306 or later. If not, open the AI Life app on your Huawei phone, go to **Me** \> **Settings** \> **Check for updates**, and update AI Life Service.
**Preparations for the development of the Hi3861 development board:**
- Prepare the Hi3861 development board \(HiSpark Wi-Fi IoT Smart Home Development Kit\).
- Download the [HUAWEI DevEco Device Tool 3.0 Beta1](https://device.harmonyos.com/cn/ide#download_beta) Linux version and [build the Ubuntu development environment](https://device.harmonyos.com/en/docs/documentation/guide/install_ubuntu-0000001072959308).
- Obtain the OpenHarmony 1.1.0 LTS source code. For details, see [Source Code Acquisition](https://gitee.com/openharmony/docs/blob/master/en/release-notes/openharmony-1-1-0-lts.md).
- [Obtain the Hi3861 demo code](https://gitee.com/openharmony-sig/knowledge_demo_smart_home/tree/master/dev/team_x/demo_winder) for network configuration and reception of device control instructions.
Now, before you proceed with the development, take a look at the development process below.
![](figures/onehop-develop-procedure.png)
# Tapping to Launch an Atomic Service<a name="EN-US_TOPIC_0000001213714629"></a>
When the phone is tapped against the NFC tag of the Hi3861 development board, the phone automatically connects to Hi3861 on the same WLAN, and launches the network configuration/device control atomic service.
![](figures/launch-atomic-service-procedure.png)
Before using OneHop to launch the atomic service, you must log in to your phone with the HUAWEI ID used to request the product ID in the HUAWEI DevEco Assistant app.
1. Enable NFC on your phone and make sure your phone is connected to a WLAN.
2. Before tapping the NFC tag, press the **RST** button on the Hi3861 development board to reset it.
3. Tap the NFC tag against the back of your phone. The screen shown below will be displayed on the phone.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>When tapping the NFC tag, keep the phone within 5 cm away from the development board. If no device is detected, tap the NFC tag again.
![](figures/network-configuration-14.png)
4. Touch **Net Config** and wait until the device is authenticated.
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>If an error message is displayed to indicate that device scanning fails, perform the following operations to troubleshoot:
>1. Disconnect your phone from the WLAN, and then connect your phone to the WLAN again.
>2. Press the **RST** button on the Hi3861 development board to reset it.
>3. Tap the NFC tag again.
![](figures/link-device.png)
5. After the network configuration is complete, the device control page is automatically displayed in half-screen mode. Swipe up on the page and touch **view more** to switch to full-screen mode.
![](figures/control.png)
6. Perform operations on the device control page. Then, check the LCD of the Hi3861 development board to find out whether your instructions are received properly.
![](figures/control-more.png)
Congratulations! You have completed the development of the Hop feature.
# Overview<a name="EN-US_TOPIC_0000001168073314"></a>
>![](../public_sys-resources/icon-note.gif) **NOTE:**
>This guide is prepared for the purpose of helping individual developers to try out the HarmonyOS's OneHop feature. Do not use it to develop or release a commercial solution of OneHop.
The OneHop feature in HarmonyOS is designed for multi-device collaboration. By leveraging the Near Field Communication \(NFC\) protocol, the feature simplifies connections between phones and other devices with a single tap. Combined with the phone's atomic service capabilities, OneHop offers seamless service hopping between devices, complete with lightning-fast device pairing and effortless remote control.
With HarmonyOS's OneHop and atomic service capabilities, your development work is so much easier, thanks to template code and APIs that span the entire process, including atomic service network configuration templates and control templates. You only need to modify the configuration items in the template code to complete the development of atomic services. Then, leverage the OneHop capability to start atomic services for lightning-fast device pairing and convenient device control. The OneHop feature provides the following functions:
- **Fast device connection**
OneHop initiates a device connection process. When the user taps their phone against an unconnected device, the atomic service on the phone is started to quickly complete the pairing between the phone and the device.
- **Quick control**
Most device control functions can be implemented through the service widgets of atomic services.
- **Service expansion**
To enrich the user experience and accommodate more use cases, you can develop interaction features for atomic services and provide these features through the service widget UI.
![](figures/onehop-procedure.png)
# References<a name="EN-US_TOPIC_0000001167914760"></a>
- **[Development Guidelines on the Network Configuration Atomic Service](guide-atomic-service-netconfig.md)**
- **[Development Guidelines on the Device Control Atomic Service](guide-atomic-service-device-ctrl.md)**
# Writing an NFC Tag<a name="EN-US_TOPIC_0000001213473149"></a>
Use the HUAWEI DevEco Assistant app to apply for a product ID and write the product ID to the NFC tag.
1. Enable NFC on your phone.
2. Open the HUAWEI DevEco Assistant app and click the **NFC** tab at the bottom.
![](figures/choose-nfc.png)
3. Touch **Select**. If you have not logged in, log in with your HUAWEI ID first.
![](figures/choose-product-id.png)
4. Click **Request** and enter the name of the atomic service package. The name must be the same as the value of **bundleName** in the **config.json** file under **src \> main** of the module. The system will automatically allocate a product ID. You can apply for a maximum of three valid product IDs with one HUAWEI ID. The validity period of each product ID is one month. After a product ID expires, you can request a new one.
![](figures/request-product-id.png)
5. Select a product ID.
![](figures/choose-requested-product-id.png)
6. Enter the SN of the Hi3861 development board. The SN is only required when you need to obtain device information through the NFC tag.
![](figures/set-sn-number.png)
7. Touch **Write to buffer** to write the data to the buffer.
![](figures/write-to-buffer.png)
8. Place your phone close to the NFC tag. The data in the buffer starts being written to the NFC tag. After the writing is complete, the status changes to **No data in buffer**.
![](figures/written-to-tag.png)
......@@ -2,27 +2,6 @@
- [轻量和小型系统设备](device-lite.md)
- [WLAN连接类产品](device-wlan.md)
- [碰一碰](device-wlan-touch.md)
- [碰一碰概述](onehop-overview.md)
- [准备工作](onehop-dev-prerequisites.md)
- [开发Hi3861设备侧功能](onehop-dev-hi3861.md)
- [开发原子化服务](onehop-dev-atomic-service.md)
- [写入NFC标签信息](onehop-write-nfc-info.md)
- [配置服务关联意图](onehop-configuration-device-tag.md)
- [碰一碰拉起原子化服务](onehop-open-atomic-service.md)
- [参考信息](onehop-reference-info.md)
- [设备配网原子化服务开发指导](guide-atomic-service-netconfig.md)
- [开发指导](guide-atomic-service-netconfig-overview.md)
- [核心代码逻辑介绍](guide-atomic-service-netconfig-logic.md)
- [配网接口调用](guide-atomic-service-netconfig-api.md)
- [常见问题](faqs.md)
- [设备控制原子化服务开发指导](guide-atomic-service-device-ctrl.md)
- [开发指导](guide-atomic-service-device-ctrl-overview.md)
- [核心代码逻辑介绍](guide-atomic-service-device-ctrl-logic.md)
- [JSON文件配置说明](guide-atomic-service-device-ctrl-json.md)
- [概述](guide-atomic-service-device-ctrl-json-intro.md)
- [Control类型控件配置说明](guide-atomic-service-device-ctrl-json-control.md)
- [Dialog类型控件配置说明](guide-atomic-service-device-ctrl-json-dialog.md)
- [LED外设控制](device-wlan-led.md)
- [LED外设控制](oem_wifi_sdk_des.md)
- [集成三方SDK](device-wlan-sdk.md)
......
# 常见问题<a name="ZH-CN_TOPIC_0000001158765981"></a>
1. **应用退出后重新进控制页面,不能继续控制设备?**
目前每次进入应用都要先配网获取新的控制通路,同时配网前需要复位设备,否则设备侧会维持上一次配网状态而无法重新配网。
2. **是否必须碰一碰才能进入配网功能?**
直接打开entry的设备配网页也可以配网,碰一碰NFC标签只是用于拉起你的原子化服务应用,并且通过NFC信息获取到碰一碰接触的设备信息。
3. **点击配网后,配网进度卡在20%之后突然显示失败 ?**
由于设备侧配网版本可能不太稳定,这种情况可能会发生在上一次应用页面被杀死或者异常退出的时候。
如果出现配网失败,可以尝试退出应用,复位设备后再尝试。
# 概述<a name="ZH-CN_TOPIC_0000001205747225"></a>
模板中json配置文件为设备控制界面的主要依据,智能电风扇页面json文件路径为control/src/main/resources/rawfile/FAN,配置如下:
```
{
"devName": "智能电风扇",
"devType": "0",
"prodId": "FAN", -- prodId指定了控制界面上的产品图名称
"templateUIInfo": [ -- templateUIInfo下面可以堆砌模板提供的Control类型控件,以行为单位。
{"name": "电源"...},
{"name": "模式"...},
{"name": "档位"...},
{"name": "预约关机"...}
],
"dialogUIInfo": [ -- dialogUIInfo下面可以声明Dialog类型控件,默认不显示, 由点击事件触发弹框
{"name": "关机时间"...}
]
}
```
目前模板里面提供了两种类型的控件(Control类型控件直接显示在界面上, Dialog类型控件需要触发后以弹窗形式展示),在json配置文件里声明不同控件即可。
**修改json配置文件后重新安装运行原子化服务就能显示修改后的效果。**
# JSON文件配置说明<a name="ZH-CN_TOPIC_0000001158604281"></a>
- **[概述](guide-atomic-service-device-ctrl-json-intro.md)**
- **[Control类型控件配置说明](guide-atomic-service-device-ctrl-json-control.md)**
- **[Dialog类型控件配置说明](guide-atomic-service-device-ctrl-json-dialog.md)**
# 设备控制原子化服务开发指导<a name="ZH-CN_TOPIC_0000001158764269"></a>
- **[开发指导](guide-atomic-service-device-ctrl-overview.md)**
- **[核心代码逻辑介绍](guide-atomic-service-device-ctrl-logic.md)**
- **[JSON文件配置说明](guide-atomic-service-device-ctrl-json.md)**
# 设备配网原子化服务开发指导<a name="ZH-CN_TOPIC_0000001111966036"></a>
- **[开发指导](guide-atomic-service-netconfig-overview.md)**
- **[核心代码逻辑介绍](guide-atomic-service-netconfig-logic.md)**
- **[配网接口调用](guide-atomic-service-netconfig-api.md)**
- **[常见问题](faqs.md)**
# 配置服务关联意图<a name="ZH-CN_TOPIC_0000001168233266"></a>
通过在HAG上配置原子化服务的关联意图,在使用手机碰一碰NFC标签后,即可通过NFC标签中的Product ID信息,与HAG中配置的关联意图进行匹配,获取需要拉取的原子化服务信息,从而拉起设备配网原子化服务。
接下来为大家介绍如何在HAG中配置原子化服务的关联意图。
1. 请使用已经实名认证后的华为开发者帐号登录[华为开发者门户](https://developer.huawei.com/consumer/cn/),登录后进入到管理中心。
![](figures/console.png)
2. 选择“生态服务 \> 智慧服务”,然后点击进入华为快服务智慧平台。首次使用,请阅读并签署《华为快服义务智慧平台合作协议》。
![](figures/ability-gallery-service.png)
3. 点击**创建快服务**按钮,然后选择**HarmonyOS测试服务**
![](figures/harmonyos-test-ability.png)
4. 设置“服务名称”、“服务分类”和“默认语言”,然后点击**创建**
![](figures/harmonyos-test-ability-model.png)
5. 设置服务信息,包括“基本信息”和“服务呈现信息”。
- 基本信息:如服务版本号、版本描述和服务分级信息,然后点击**保存**按钮。
- 服务呈现信息:如简要描述、开发者品牌、服务图标等必选项,请注意,**服务大图标**也必须上传,然后点击**保存**
6. 进入“配置 \> HarmonyOS标签”页面,点击**添加**按钮,添加设备标签。其中“产品型号”输入应用调测助手中申请的Product ID,“产品子型号”固定输入00,然后点击**保存**按钮。
![](figures/harmonyos-tag.png)
7. 进入“配置 \> FA信息”页面,设置FA基本信息和配置方式,设置完成后点击**保存**按钮进行保存。
- 基本信息:其中“实现类型”固定选择“APK/RPK/FA/H5 link”。
- FA Link:填写“App名称”、“App包名”、“模块名”和“服务名”,其中:
- “App包名”填写为config.json文件中的bundleName字段取值。
- “模块名”填写为入口原子化服务(即设备配网模块)config.json文件中的moduleName字段取值。
- “服务名”填写为入口原子化服务(即设备配网模块)config.json文件中的mainAbility字段取值。
![](figures/fa-information.png)
8. 进入测试页签,点击**开始测试准备**按钮,启动测试。测试的有效期时间为1个月,到期后请重新点击**重新测试准备**即可。
![](figures/ability-test.png)
接下来在“真机测试”中,点击**创建按钮**,添加真机测试名单。此处填写的华为帐号信息需要与手机上登录的华为帐号保持一致。
![](figures/prototype-test.png)
此差异已折叠。
# 准备工作<a name="ZH-CN_TOPIC_0000001213554677"></a>
开发碰一碰特性,需要涉及Hi3861开发板的开发和HarmonyOS原子化服务的开发两部分。因此,在开发前,请做好如下准备工作:
**HarmonyOS原子化服务开发准备工作:**
- 准备已经升级至HarmonyOS 2系统的华为Mate系列或P系列手机,系统版本号为2.0.0.168及以上。
- 下载[DevEco Studio 3.0 Beta1](https://developer.harmonyos.com/cn/develop/deveco-studio#download_beta)版本,并配置好[DevEco Studio开发环境](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/installation_process-0000001071425528)
- 在华为应用市场,下载并安装“应用调测助手”App,用于写NFC标签。
- 准备1个NFC标签,可以用手机触碰NFC标签,提前确保NFC功能可用。
- 打开手机**设置 \> 应用和服务 \> 应用管理**,搜索“智慧生活基础服务”,检测智慧生活基础服务的版本是否为12.0.2.306及以上。如果不是,请打开华为手机的“智慧生活”App,点击“**我的 \> 设置 \> 检查应用更新**”,更新“智慧生活基础服务”。
**Hi3861开发板开发准备工作:**
- 本指导基于Hi3861开发板为例,请准备Hi3861开发板(HiSpark Wi-Fi IoT智能家居套件)。
- 下载[HUAWEI DevEco Device Tool 3.0 Beta1](https://device.harmonyos.com/cn/ide#download_beta) Linux版本,并搭建好[Ubuntu开发环境](https://device.harmonyos.com/cn/docs/documentation/guide/install_ubuntu-0000001072959308)
- 获取OpenHarmony源码,版本为1.1.0 LTS全量代码,获取方式请参考[源码获取](https://gitee.com/openharmony/docs/blob/master/zh-cn/release-notes/OpenHarmony-1-1-0-LTS.md)
- 获取[Hi3861开发板Demo代码](https://gitee.com/openharmony-sig/knowledge_demo_smart_home/tree/master/dev/team_x/demo_winder),用于Hi3861开发板配网和接收设备控制指令。
接下来,熟悉碰一碰特性的主要开发流程,如下图所示。
![](figures/onehop-develop-procedure.png)
此差异已折叠。
# 参考信息<a name="ZH-CN_TOPIC_0000001167914760"></a>
- **[设备配网原子化服务开发指导](guide-atomic-service-netconfig.md)**
- **[设备控制原子化服务开发指导](guide-atomic-service-device-ctrl.md)**
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册