# How to Develop - [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 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 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**.

Java

Description

MyApplication

Application entry class.

ControlMainAbility

Entry class to start the JS page.

BaseDeviceDataHandler

Abstract class for device data exchange.

NetworkDeviceDataHandler

Inherits from the abstract class BaseDeviceDataHandler to implement device data exchange in Neighbor Awareness Networking (NAN) connection mode. You can modify the code based on the device in use.

SampleDeviceDataHandler

Inherits from the abstract class BaseDeviceDataHandler. This provides sample code, and you do not need to modify the code.

DataHandlerAbility

Implements a channel for message exchange between a Java-based system and a JS-based one.

JS

Description

control/ailife-view

Home appliance components, which can be referenced in the JSON configuration file.

index.js

Device control home page. Different components under ailife-view are loaded based on the JSON configuration file.

## Sending Messages to Devices \(NAN Channel Available\) 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 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 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 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/** 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 \_.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/__** 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 dataMap = new HashMap<>(); private final DeviceDataModel fanDataModel = new DeviceDataModel() { @Override public Map 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).