Last Updated on : 2024-06-26 07:16:37download
This topic describes how to implement the Device Pairing BizBundle SDK to meet your business needs, using common Bluetooth devices and wired gateways as examples.
There are various types of Bluetooth devices. See Bluetooth Devices for details.
If your app on Android 12 or later does not support iBeacon devices, you only need to include the Bluetooth scan permission.
If your app is on Android 11 or earlier or supports iBeacon devices, you need to include the Bluetooth scan and location permissions.
If iBeacon is not supported, add the following permissions in AndroidManifest
:
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"
android:usesPermissionFlags="neverForLocation"/>
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE"/>
If iBeacon is supported, add the following permissions in AndroidManifest
:
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
After the necessary permissions are granted, the app can start Bluetooth device discovery.
val scankey = ThingActivatorCoreKit.getScanDeviceManager()
.startBlueToothDeviceSearch(
25 * 1000L,
arrayListOf(ScanType.MESH, ScanType.SIG_MESH, ScanType.SINGLE, ScanType.THING_BEACON),
object : ThingActivatorScanCallback {
override fun deviceFound(deviceBean: ThingActivatorScanDeviceBean) {
// Device discovery
}
override fun deviceRepeat(deviceBean: ThingActivatorScanDeviceBean) {
// Repeated discovery
}
override fun deviceUpdate(deviceBean: ThingActivatorScanDeviceBean) {
// Device capability update. This method will not be called back during a scan for a single Bluetooth device.
}
override fun scanFailure(failureBean: ThingActivatorScanFailureBean) {
// Device discovery failed
}
override fun scanFinish() {
// Search finished
}
}
After the deviceFound
callback returns the device information, your app will present the UI accordingly.
The prerequisites vary by device type. If ThingDeviceActiveModeEnum.BLE_WIFI
or ThingDeviceActiveModeEnum.MULT_MODE
is discovered, the page prompting the user to enter Wi-Fi credentials is required. For more information about pairing parameters, see Bluetooth Device Pairing.
When a device starts pairing, you can get the result through the following callback.
...
object : IThingDeviceActiveListener {
override fun onActiveError(errorBean: ThingDeviceActiveErrorBean) {
// Pairing failed.
}
override fun onActiveLimited(limitBean: ThingDeviceActiveLimitBean) {
// Pairing restricted.
}
override fun onActiveSuccess(deviceBean: DeviceBean) {
// Pairing succeeded.
}
override fun onBind(devId: String) {
}
override fun onFind(devId: String) {
}
onActiveSuccess
returns DeviceBean
, indicating pairing succeeds. The onActiveLimited
method exposes two types of limitations.
In both cases, if the device cannot be unpaired from the associated account, the user can request a reset to unbind the device. For more information, see FAQ UI BizBundle.
The mobile phone and the wired gateway are connected to the same router.
Case 1: Scan for devices along with other scan capabilities.
Your app needs to scan for multiple types of devices at the same time, such as Bluetooth and wired gateways. In this case, Bluetooth scan and wired gateway scan methods are called, requiring a unique identifier to match the discovered devices with the paired ones. Given the complexity of this process, it is recommended to adopt composite scan.
val scanKey = ThingActivatorCoreKit.getScanDeviceManager()
.startScan(
ThingActivatorScanBuilder().apply {
setScanTypeList(arrayListOf(ThingActivatorScanType.LOCAL_GATEWAY,ThingActivatorScanType.BLUETOOTH))
setBlueScanDeviceTypeList(arrayListOf(ScanType.MESH, ScanType.SIG_MESH, ScanType.SINGLE, ScanType.THING_BEACON))
setMillisTimeOut(100*1000L)
},
object :ThingActivatorScanCallback{
override fun deviceFound(deviceBean: ThingActivatorScanDeviceBean) {
//Device discovery
}
override fun deviceRepeat(deviceBean: ThingActivatorScanDeviceBean) {
//Repeated discovery
}
override fun deviceUpdate(deviceBean: ThingActivatorScanDeviceBean) {
//Device capability update
}
override fun scanFailure(failureBean: ThingActivatorScanFailureBean) {
//Device discovery failed
}
override fun scanFinish() {
//Search finished
}
}
)
Composite scan enables the discovered Bluetooth device and wired gateway to be returned with the same callback and unified data entity, eliminating the need for data unity and unique identifiers.
Case 2: Independent scanning
If your app only needs to scan for wired gateways, you can use the respective scan method.
ThingActivatorCoreKit.getScanDeviceManager().startLocalGatewayDeviceSearch(
60*1000L,
object :ThingActivatorScanCallback{
override fun deviceFound(deviceBean: ThingActivatorScanDeviceBean) {
//Device discovery
}
override fun deviceRepeat(deviceBean: ThingActivatorScanDeviceBean) {
//Repeated discovery
}
override fun deviceUpdate(deviceBean: ThingActivatorScanDeviceBean) {
//Device capability update
}
override fun scanFailure(failureBean: ThingActivatorScanFailureBean) {
//Device discovery failed
}
override fun scanFinish() {
//Search finished
}
}
)
After a device is discovered using either of the scan methods mentioned above, it can be paired through the following method.
val builder = ThingDeviceActiveBuilder()
.setActiveModel(ThingDeviceActiveModeEnum.WN)
.setActivatorScanDeviceBean(thingActivatorScanDeviceBean) //Scan the obtained entity.
.setTimeOut(timeout)
.setListener(object : IThingDeviceActiveListener {
override fun onFind(devId: String) {
}
override fun onBind(devId: String) {
}
override fun onActiveSuccess(deviceBean: DeviceBean) {
}
override fun onActiveError(errorBean: ThingDeviceActiveErrorBean) {
}
override fun onActiveLimited(limitBean: ThingDeviceActiveLimitBean) {
}
})
val activeManager = ThingActivatorCoreKit.getActiveManager().newThingActiveManager()
activeManager.startActive(builder)
onActiveSuccess
returns DeviceBean
, indicating pairing succeeds.
A Zigbee device relies on a Zigbee gateway to connect to the cloud. Therefore, the pairing process requires a specific gateway that processes device activation and notifications. The target gateway must be online.
Filter the devices in the current home.
Find suitable Zigbee gateways and make sure they are online.
Select the preferred gateway.
If there is no suitable gateway, prompt the user to add one.
val activedGatewayList: MutableList<DeviceBean> = ArrayList()
val list = getDeviceList()
for (deviceBean in list) {
if (deviceBean.hasConfigZigbee()) {
activedGatewayList.add(deviceBean)
}
}
val scankey = ThingActivatorCoreKit.getScanDeviceManager()
.startGatewaySubDeviceSearch(
gatewayId,
25 * 1000L,
object : ThingActivatorScanCallback {
override fun deviceFound(deviceBean: ThingActivatorScanDeviceBean) {
//Device discovery
}
override fun deviceRepeat(deviceBean: ThingActivatorScanDeviceBean) {
//Repeated discovery
}
override fun deviceUpdate(deviceBean: ThingActivatorScanDeviceBean) {
}
override fun scanFailure(failureBean: ThingActivatorScanFailureBean) {
//Device discovery failed
}
override fun scanFinish() {
//Search finished
}
}
After a Zigbee sub-device is discovered, pass in the result with the pairing method to obtain the DeviceBean
.
val builder = ThingDeviceActiveBuilder()
.setActiveModel(ThingDeviceActiveModeEnum.SUB)
.setSubSearchBeans(thingActivatorScanDeviceBeans) //Scan the obtained entity.
.setTimeOut(timeout)
.setListener(object : IThingDeviceActiveListener {
override fun onFind(devId: String) {
}
override fun onBind(devId: String) {
}
override fun onActiveSuccess(deviceBean: DeviceBean) {
}
override fun onActiveError(errorBean: ThingDeviceActiveErrorBean) {
}
override fun onActiveLimited(limitBean: ThingDeviceActiveLimitBean) {
}
})
val activeManager = ThingActivatorCoreKit.getActiveManager().newThingActiveManager()
activeManager.startActive(builder)
Android 6.0 (API level 23) and later support Matter devices. see Prepare for Integration with Matter Device to configure the prerequisites.
val scankey = ThingActivatorCoreKit.getScanDeviceManager()
.startMatterDeviceSearch(
25 * 1000L,
object : ThingActivatorScanCallback {
override fun deviceFound(deviceBean: ThingActivatorScanDeviceBean) {
//Device discovery
}
override fun deviceRepeat(deviceBean: ThingActivatorScanDeviceBean) {
//Repeated discovery
}
override fun deviceUpdate(deviceBean: ThingActivatorScanDeviceBean) {
}
override fun scanFailure(failureBean: ThingActivatorScanFailureBean) {
//Device discovery failed
}
override fun scanFinish() {
//Search finished
}
}
val builder = ThingDeviceActiveBuilder()
.setActiveModel(ThingDeviceActiveModeEnum.MATTER_DISCOVERY)
.setActivatorScanDeviceBean(thingActivatorScanDeviceBean) //Scan the obtained entity.
.setTimeOut(timeout)
.setRelationId(homeId)
.setListener(object : IThingDeviceActiveListener {
override fun onFind(devId: String) {
}
override fun onBind(devId: String) {
}
override fun onActiveSuccess(deviceBean: DeviceBean) {
}
override fun onActiveError(errorBean: ThingDeviceActiveErrorBean) {
}
override fun onActiveLimited(limitBean: ThingDeviceActiveLimitBean) {
}
})
val activeManager = ThingActivatorCoreKit.getActiveManager().newThingActiveManager()
activeManager.startActive(builder)
interface ThingActivatorScanCallback {
/**
* Device discovery
*/
fun deviceFound(deviceBean: ThingActivatorScanDeviceBean)
/**
* Device capability update
*/
fun deviceUpdate(deviceBean: ThingActivatorScanDeviceBean)
/**
* Repeated reporting
*/
fun deviceRepeat(deviceBean: ThingActivatorScanDeviceBean)
/**
* Search finished
*/
fun scanFinish()
/**
* Search error
*/
fun scanFailure(failureBean: ThingActivatorScanFailureBean)
}
If you are using the composite scan with both Bluetooth and Pegasus pairing enabled, the device will be returned through deviceFound
when it is first discovered over Bluetooth. After the device is then discovered by Pegasus pairing, it will be returned through deviceUpdate
. Replace the previously saved scanDeviceBean
with the new entity.
In Bluetooth mode, the app may receive duplicate advertising packets from the device. The deviceRepeat
callback will return the repeatedly discovered device.
interface IThingDeviceActiveListener {
/**
* Device discovery
* @param devId Device ID
*/ fun onFind(devId: String)
/**
* Bind the device.
* @param devId Device ID
*/ fun onBind(devId: String)
/**
* Activation succeeded.
* @param deviceBean Device data model.
*/
fun onActiveSuccess(deviceBean: DeviceBean)
/**
* Activation failed.
*
* @param errorBean Error message
*/
fun onActiveError(errorBean: ThingDeviceActiveErrorBean)
/**
* Activation is restricted, due to such as strong binding, two-way binding, or guest mode.
*
* @param limitBean Includes basic device information
*/
fun onActiveLimited(limitBean: ThingDeviceActiveLimitBean)
}
Perform the following steps to enable or disable strong binding for a product.
Log in to the Tuya Developer Platform.
Select a product and click Develop in the Operation column.
In the Function Definition step, scroll down to Advanced Functions and find Device Binding Mode. Toggle it on or off as desired.
Device binding is restricted by both the PID and the app. You can specify the app that a PID can be bound with and the device that an app can be connected to. A device can only be bound when both the app and the device meet the restriction.
By default, there are no restrictions for both the PID and app, allowing them to be connected freely.
Is this page helpful?
YesFeedbackIs this page helpful?
YesFeedback