Tuya Mesh

Last Updated on : 2024-08-01 06:17:26download

This topic describes the implementation of communication over Bluetooth based on Tuya’s proprietary mesh networking technology, also known as Tuya mesh. Each Tuya mesh device serves as a child node, and multiple mesh devices form a mesh network, in which the child nodes communicate with each other by advertising. App users can access one of the mesh devices to access and control all devices on the mesh network.
This topic provides development guidance on pairing, control, and management of devices that use Tuya mesh. For more information about Bluetooth mesh concepts, see Bluetooth Mesh.

Preparation

  • System requirements: Bluetooth connectivity requires Android 4.3 and later, and the Smart Life App SDK supports Android 4.4 and later.

  • Manifest permissions:

    // Android 11 and earlier versions
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    // Android 12 and later versions
    <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
    <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    
  • Precheck of Bluetooth permissions: This percheck is essential. Otherwise, the app cannot use Bluetooth connectivity as expected.

    • Check whether the location feature is enabled for an app before it uses Bluetooth connectivity or starts scanning.
    • Check whether the Bluetooth feature is enabled.

      This precheck is not provided by the Smart Life App SDK. You can manually perform the precheck.

  • Initialize a home: Before the development of Tuya mesh capabilities, get familiar with Smart Life App SDK. All Tuya mesh operations are implemented based on the initialized home data. For more information, see Home Management.

Management

Create Tuya mesh network

A home can belong to multiple mesh networks, but one mesh network is recommended for each home.

API description

void createBlueMesh(String meshName, IThingResultCallback<BlueMeshBean> callback);

Parameters

Parameter Type Description
meshName String The name of a mesh network, with up to 16 bytes.
callback IThingResultCallback The callback.

Example

ThingHomeSdk.newHomeInstance("homeId").createBlueMesh("meshName", new IThingResultCallback<BlueMeshBean>() {
	@Override
	public void onError(String errorCode, String errorMsg) {
	}

	@Override
	public void onSuccess(BlueMeshBean blueMeshBean) {
	}
});

Delete Tuya mesh network

API description

void removeMesh(IResultCallback callback);

Parameters

Parameter Type Description
callback IResultCallback The callback.

Example

ThingHomeSdk.newBlueMeshDeviceInstance(meshId).removeMesh(new IResultCallback() {
	@Override
	public void onError(String errorCode, String errorMsg) {
	}

	@Override
	public void onSuccess() {
	}
});

Query list of mesh networks in home

API description

List<BlueMeshBean> getMeshList();

Example

IThingHome mThingHome = ThingHomeSdk.newHomeInstance("homeId");
if (mThingHome.getHomeBean() != null){
	List<BlueMeshBean> meshList = mThingHome.getHomeBean().getMeshList();
	BlueMeshBean meshBean= meshList.get(0);
}

Query list of mesh sub-devices

API description

List<DeviceBean> getMeshSubDevList();

Example

List<DeviceBean> meshSubDevList = ThingHomeSdk.newBlueMeshDeviceInstance("meshId").getMeshSubDevList();

Query and destroy mesh instance

We recommend that you destroy the current mesh instance and initialize the mesh instance for the target home when you switch between homes.

API description

// Initializes the mesh network.
ThingHomeSdk.getThingBlueMeshClient().initMesh(String meshId);

// Destroys the current mesh network.
ThingHomeSdk.getThingBlueMeshClient().destroyMesh();

Connect to and disconnect from mesh sub-device

IThingBlueMeshClient provides API methods to start a connection, close a connection, start scanning, and stop scanning.

API description

// Starts a connection.
ThingHomeSdk.getThingBlueMeshClient().startClient(mBlueMeshBean);

// Closes a connection.
ThingHomeSdk.getThingBlueMeshClient().stopClient();

// Starts scanning.
ThingHomeSdk.getThingBlueMeshClient().startSearch()

// Stops scanning.
ThingHomeSdk.getThingBlueMeshClient().stopSearch();

After a connection is started, available devices are scanned for in the background until a device is connected. The background scanning will consume resources. You can start and stop scanning to control the background scanning.

  • Before startClient() is called, the API methods of startSearch() and stopSearch() are invalid.
  • After a mesh network is connected, the API methods of startSearch() and stopSearch() are also invalid.

Pairing

Mesh devices to be paired are classified into:

  • A common Tuya mesh device that runs without a gateway, also known as a mesh sub-device

  • A mesh gateway

    Common mesh sub-devices include smart lights, smart sockets, and low-power products. All mesh devices without mesh gateway capabilities can be regarded as common Tuya mesh devices.

Reset device

The default name of a device in the reset state is out_of_mesh and the default password is 123456. The following list describes common device resetting methods.

Product category Reset method State ready for pairing
Lighting Turn on and off the light consecutively three times in a row The indicator is blinking quickly.
Socket Press and hold the on/off button for three seconds The indicator is blinking quickly.
Gateway product Press and hold the on/off button for three seconds The red and blue indicators are blinking quickly.
Low power device Press and hold the on/off button for three seconds Press the on/off button once again to see that the indicator is steady on. The pairing process must be completed when the indicator is on.
Alarm Press and hold the on/off button for three seconds The indicator is blinking quickly.

Scan for sub-devices ready for pairing

You must check Bluetooth and location permissions and then start scanning for mesh devices ready for pairing.

API description

// Starts scanning.
void startSearch();
// Stops scanning.
void stopSearch();

Example

IThingBlueMeshSearchListener iThingBlueMeshSearchListener = new IThingBlueMeshSearchListener() {
	@Override
	public void onSearched(SearchDeviceBean deviceBean) {
	}

	@Override
	public void onSearchFinish() {
	}
};

SearchBuilder searchBuilder = new SearchBuilder()
				// The name of the device to be scanned for. Default value: `out_of_mesh` to represent the name of the device in the pairing state.
				.setMeshName("out_of_mesh")
				.setTimeOut(100) // The duration of the scanning. Unit: seconds.
				.setThingBlueMeshSearchListener(iThingBlueMeshSearchListener).build();

IThingBlueMeshSearch mMeshSearch = ThingHomeSdk.getThingBlueMeshConfig().newThingBlueMeshSearch(searchBuilder);

// Starts scanning.
mMeshSearch.startSearch();

// Stops scanning.
mMeshSearch.stopSearch();

Pair mesh sub-devices

API description

// Starts pairing.
void startActivator();

// Stops pairing.
void stopActivator();

Parameters

Parameter String Description
mSearchDeviceBeans List The set of devices ready for pairing.
timeout Int The timeout value of a pairing task. Default value: 100. Unit: seconds.
ssid String The name of the Wi-Fi network to which a paired device is connected.
password String The password of the Wi-Fi network to which a paired device is connected.
mMeshBean MeshBean MeshBean
homeId Long The home to which the mesh network of the paired device belongs.
version String
  • Pair common mesh devices: 1.0
  • Pair gateway devices: 2.2

Example

// Pairs a common mesh device.
ThingBlueMeshActivatorBuilder thingBlueMeshActivatorBuilder = new ThingBlueMeshActivatorBuilder()
				.setSearchDeviceBeans(foundDevices)
				.setVersion("1.0")
				.setBlueMeshBean(mMeshBean)
				.setTimeOut(timeOut)
				.setThingBlueMeshActivatorListener(new IThingBlueMeshActivatorListener() {
	@Override
	public void onSuccess(DeviceBean deviceBean) {
	}

	@Override
	public void onError(String errorCode, String errorMsg) {
	}

	@Override
	public void onFinish() {
	}});

IThingBlueMeshActivator iThingBlueMeshActivator = ThingHomeSdk.getThingBlueMeshConfig().newActivator(thingBlueMeshActivatorBuilder);
// Starts pairing.
iThingBlueMeshActivator.startActivator();

// Stops pairing.
iThingBlueMeshActivator.stopActivator();

A mesh gateway

API description

// Starts pairing.
void startActivator();
// Stops pairing.
void stopActivator();

Parameters

Parameter String Description
mSearchDeviceBeans List The set of devices ready for pairing.
timeout Int The timeout value of a pairing task. Default value: 100. Unit: seconds.
ssid String The name of the Wi-Fi network to which a paired device is connected.
password String The password of the Wi-Fi network to which a paired device is connected.
mMeshBean MeshBean MeshBean
homeId Long The home to which the mesh network of the paired device belongs.
version String
  • Pair common mesh devices: 1.0
  • Pair gateway devices: 2.2

Example

// Pairs the gateway.
ThingBlueMeshActivatorBuilder thingBlueMeshActivatorBuilder = new ThingBlueMeshActivatorBuilder()
				.setWifiSsid(mSsid)
				.setWifiPassword(mPassword)
				.setSearchDeviceBeans(foundDevices)
				.setVersion("2.2 ")
				.setBlueMeshBean(mMeshBean)
				.setHomeId("homeId")
				.setThingBlueMeshActivatorListener(new IThingBlueMeshActivatorListener() {
				@Override
				public void onSuccess(DeviceBean devBean) {
					// The callback to invoke when a single device is paired.
					L.d(TAG, "startConfig success");
				}

				@Override
				public void onError(String errorCode, String errorMsg) {
					// The callback to invoke when a single device failed to be paired.
					// The error code. See the subsequent list of pairing error codes.
				L.d(TAG, "errorCode: " + errorCode + " errorMsg: " + errorMsg);
				}

				@Override
				public void onFinish() {
					// The callback to invoke when all devices are paired.
				}
				});
IThingBlueMeshActivator iThingBlueMeshActivator = ThingHomeSdk.getThingBlueMeshConfig().newWifiActivator(thingBlueMeshActivatorBuilder);

// Starts pairing.
iThingBlueMeshActivator.startActivator();

// Stops pairing.
//iThingBlueMeshActivator.stopActivator();

Error codes

Error code Description
13007 Failed to log in to the device.
13004 Failed to reset the device address.
13005 The upper limit for the number of device addresses is reached.
13007 The SSID is empty.
13011 The pairing task timed out.

Device

Check mesh device type

API description

DeviceBean deviceBean=ThingHomeSdk.getDataInstance().getDeviceBean(mDevId);
// Checks whether the Tuya mesh device is a gateway or a sub-device.
if(deviceBean.isBlueMesh()){
	L.d(TAG, "This device is blue mesh device");
}

// Checks whether a Tuya mesh gateway is used.
if(deviceBean.isBlueMeshWifi()){
	L.d(TAG, "This device is blue mesh wifi device");
}

Rename a mesh sub-device

API description

void renameMeshSubDev(String devId, String name, IResultCallback callback);

Parameters

Parameter Type Description
devId String The device ID.
name String The new name of the device.
callback IResultCallback The callback.

Example

mThingBlueMesh.renameMeshSubDev(devBean.getDevId(),"Device name", new IResultCallback() {
			@Override
			public void onError(String code, String errorMsg) {
			}

			@Override
			public void onSuccess() {
			}
		});

Determine status of connection to mesh network and to gateway

Example

DeviceBean deviceBean=ThingHomeSdk.getDataInstance().getDeviceBean(mDevId);
DeviceBean gwBean=ThingHomeSdk.getDataInstance().getDeviceBean(deviceBean.getParentId());

// The overall status of device connection to the local mesh network and gateway.
boolean online=deviceBean.getIsOnline()
// The status of device connection to the local Tuya mesh network.
boolean localOnline=deviceBean.getIsLocalOnline()
// The status of device connection to the gateway. The gateway is regarded to be online only when the gateway and its sub-devices are both online.
boolean wifiOnline=deviceBean.isCloudOnline() && gwBean.getIsOnline()

Remove mesh sub-device

API description

void removeMeshSubDev(String devId, IResultCallback callback);

Parameters

Parameter Type Description
devId String The device ID.
pcc String The category and type of the device.
callback IResultCallback The callback.

Example

mThingBlueMesh.removeMeshSubDev(devBean.getDevId(), new IResultCallback(){
@Override
public void onError(String code, String errorMsg) {
	Toast.makeText(mContext, "Failed to remove a sub-device"+ errorMsg,   Toast.LENGTH_LONG).show();
}

@Override
public void onSuccess() {
	Toast.makeText(mContext, "Sub-device removed successfully", Toast.LENGTH_LONG).show();
}
});

Query mesh sub-device status

The data point (DP) information returned from the cloud might not be the real-time data of the specified device. You can run the following command to query the current DP value of the device. The result is returned by the method onDpUpdate of IMeshDevListener.

API description

void querySubDevStatusByLocal(String pcc, String nodeId, IResultCallback callback);

Parameters

Parameter Type Description
pcc String The category and type of the device.
nodeId String The value of NodeId for the device.
callback IResultCallback The callback.

Example

mThingBlueMeshDevice.querySubDevStatusByLocal(devBean.getCategory(), devBean.getNodeId(), new IResultCallback() {
			@Override
			public void onError(String code, String errorMsg) {
			}

			@Override
			public void onSuccess() {
			}
		});

Device group

The IThingGroup class provides operations to manage Tuya mesh groups.

Determine mesh group

You can check whether MeshId is used by a group to determine whether it is a mesh group or a common Wi-Fi group.

API description

GroupBean groupBean=ThingHomeSdk.getDataInstance().getGroupBean("groupId");
if(!TextUtils.isEmpty(groupBean.getMeshId())){
	L.d(TAG, "This group is a Bluetooth mesh group");
}

Create mesh group

Each mesh network supports up to 28,672 groups. In the response to group creation, the group ID ranges from 8000 to EFFF in hexadecimal and can be locally maintained.

API description

void addGroup(String name, String pcc, String localId,IAddGroupCallback callback);

Parameters

Parameter Description
name The name of the group.
pcc The categories and types of devices in the group. Different types of devices can be created in a group. FF01 specifies the lighting category.
localId The value of localId for the group. Valid values: 8000 to EFFF in hexadecimal.
callback The callback.

Example

mIThingBlueMesh.addGroup("Group name","Category and type", "8001", new IAddGroupCallback() {
@Override
public void onError(String errorCode, String errorMsg) {
}

@Override
public void onSuccess(long groupId) {
}
});

Add sub-devices to mesh group

API description

void addDevice(String devId,IResultCallback callback);

Parameters

Parameter Type Description
devId String The device ID.
callback IResultCallback The callback.

Example

IThingGroup mGroup = ThingHomeSdk.newBlueMeshGroupInstance(groupId);
mGroup.addDevice("devId", new IResultCallback() {
@Override
public void onError(String code, String errorMsg) {
}

@Override
public void onSuccess() {
}
});

Remove sub-devices from group

API description

void removeDevice(String devId,IResultCallback callback);

Parameters

Parameter Type Description
devId String The device ID.
callback IResultCallback The callback.

Example

IThingGroup mGroup = ThingHomeSdk.newBlueMeshGroupInstance(groupId);
mGroup.removeDevice("devId", new IResultCallback() {
@Override
public void onError(String code, String errorMsg) {
}

@Override
public void onSuccess() {
}
});

Delete mesh group

API description

void dismissGroup(IResultCallback callback);

Parameters

Parameter Type Description
callback IResultCallback The callback.

API description

IThingGroup mGroup = ThingHomeSdk.newBlueMeshGroupInstance(groupId);
mGroup.dismissGroup(new IResultCallback() {
@Override
public void onError(String code, String errorMsg) {
}

@Override
public void onSuccess() {
}
});

Rename mesh group

API description

void renameGroup(String groupName,IResultCallback callback);

Parameters

Parameter Type Description
groupName String The new name of the group.
callback IResultCallback The callback.

Example

IThingGroup mGroup = ThingHomeSdk.newBlueMeshGroupInstance(groupId);
mGroup.renameGroup("Group name",new IResultCallback() {
@Override
public void onError(String code, String errorMsg) {
}

@Override
public void onSuccess() {
}
});

Control

Smart devices are managed with DPs. Tuya mesh devices are also controlled by device DPs. The IThingBlueMeshDevice class provides operations to manage Tuya mesh devices.

Command format

Send a control command in the following format:

{
	"(dpId)":"(dpValue)"
}

For more information about DPs, see Data points.

Control devices

API description

void publishDps(String nodeId, String pcc, String dps, IResultCallback callback);

Parameters

Parameter Description
nodeId The local ID of a sub-device.
pcc The product category and type of a sub-device.
dps The list of DPs.
callback The callback.

Example

String dps = {"1":false};
IThingBlueMeshDevice mThingBlueMeshDevice=ThingHomeSdk.newBlueMeshDeviceInstance("meshId");
mThingBlueMeshDevice.publishDps(devBean.getNodeId(), devBean.getCategory(), dps, new IResultCallback() {
@Override
public void onError(String s, String s1) {
}

@Override
public void onSuccess() {
}
});

Send DPs to control a group

API description

void multicastDps(String localId, String pcc, String dps, IResultCallback callback)

Parameters

Parameter Description
localId The local ID of a group.
pcc The product category and type of a sub-device.
dps The list of DPs.
callback The callback.

Example

String dps = {"1":false};
IThingBlueMeshDevice mThingBlueMeshDevice= ThingHomeSdk.newBlueMeshDeviceInstance("meshId");
mThingBlueMeshDevice.multicastDps(groupBean.getLocalId(), devBean.getCategory(), dps, new IResultCallback() {
@Override
public void onError(String errorCode, String errorMsg) {
}

@Override
public void onSuccess() {
}
});

Listen for mesh data

Device information on a Tuya mesh network, such as DP data, status changes, device name, and device removal, is synchronized to IMeshDevListener in real time.

Example

mThingBlueMeshDevice.registerMeshDevListener(new IMeshDevListener() {

/**
	* Data is updated.
	* @param nodeId    The value of `nodeId` for the device.
	* @param dps       DP data.
	* @param isFromLocal   The data source. Valid values: `true` to indicate the local Tuya mesh network, and `false` to indicate the cloud.
	*/
@Override
public void onDpUpdate(String nodeId, String dps,boolean isFromLocal) {
// Returns `DeviceBean` by using `node`.
DeviceBean deviceBean = mThingBlueMeshDevice.getMeshSubDevBeanByNodeId(nodeId);
}

/**
	* Device status is reported.
	* @param online    The list of online devices.
	* @param offline   The list of offline devices.
	* @param gwId      The source of the status. If `gwId` is not empty, the cloud returns the status. `gwId` indicates the ID of the gateway that reports the data. If `gwId` is empty, the local Bluetooth mesh network returns the status.
	*/
@Override
public void onStatusChanged(List<String> online, List<String> offline,String gwId) {
}

/**
	* The network status is changed.
	* @param devId
	* @param status
	*/
@Override
public void onNetworkStatusChanged(String devId, boolean status) {

}

/**
	* The Raw type of data is reported.
	* @param bytes
	*/
@Override
public void onRawDataUpdate(byte[] bytes) {

}

/**
	* Device information such as the device name is modified.
	* @param bytes
	*/
@Override
public void onDevInfoUpdate(String devId) {
}
/**
	* The device is removed.
	* @param devId
	*/
@Override
public void onRemoved(String devId) {
}
});

Update

Tuya mesh shares the same logic of device firmware updates as Bluetooth mesh. For more information, see Firmware updates for Bluetooth mesh.