You can use the sub-device management feature to connect sub-devices of a gateway to IoT Platform. This topic describes how to configure and develop a gateway and its sub-device, and connect the sub-device to IoT Platform.
Features
You can perform the following operations to manage the sub-devices of gateways: dynamically register sub-devices, add and delete sub-devices, query all sub-devices under a gateway from IoT Platform, connect sub-devices to and disconnect sub-devices from IoT Platform, and listen to messages about disabling and deleting sub-devices. You can also use gateways to communicate with IoT Platform on behalf of their sub-devices. A gateway is a device that can directly connect to IoT Platform, and can directly use all the preceding capabilities. You must configure the connection and data communication channels between the gateway and its sub-devices before you can connect the sub-devices to IoT Platform.
Development
Gateway development
To create a gateway product in the IoT Platform console, you can perform the following operations: set the Node Type parameter to Gateway device, select an authentication mode for the gateway, and specify a topic or define a Thing Specification Language (TSL) model based on features of the gateway. You can also develop features of the gateway based on previous topics.
The following sub-device management features are supported:
The gateway discovers and connects to a sub-device.
Alibaba Cloud does not provide sample code for discovering and connecting a sub-device to the gateway. You need to write your own code.
The gateway obtains the certificate of the sub-device.
For more information, see the "Obtain the certificate of a sub-device" section in this topic.
IoT Platform manages sub-devices of a gateway.
When a gateway discovers and connects to a sub-device, you must call the related SDK API to add a sub-device. The gateway obtains the certificate information of the sub-device and then calls the related SDK API to connect the sub-device to IoT Platform.
NoteIf IoT Platform attempts to manage a disconnected sub-device, the failure result is returned immediately. You do not need to wait for an error message or timeout message that is returned by the gateway for the downstream command from IoT Platform.
The gateway synchronizes the sub-device status to the IoT Platform console.
After a gateway notifies IoT Platform that a sub-device is connected, the gateway must submit the status of the sub-device to IoT Platform. This ensures that the actual sub-device status is synchronized in the IoT Platform console.
NoteIf you define the features of a sub-device in a TSL model and the sub-device connects to the gateway, the gateway must submit the latest property values of the sub-device to IoT Platform.
If a sub-device is disconnected from the gateway and IoT Platform, the gateway must call the related SDK API to notify IoT Platform that the sub-device is disconnected.
If the property values of a connected sub-device change, the gateway must submit the latest property values to IoT Platform at the earliest opportunity.
If the gateway is disconnected from and then connects to IoT Platform due to network disruption or a gateway restart, the gateway must call related SDK APIs to add all sub-devices and notify IoT Platform that the sub-devices are connected again. If the gateway cannot ensure that the property values of a sub-device remains unchanged before and after the gateway is reconnected, the gateway must submit the latest property values of the sub-device to IoT Platform.
The sub-device receives messages sent from IoT Platform.
When the gateway receives a command sent from IoT Platform to a sub-device, the gateway must convert the data into a format that is supported by the sub-device. Alibaba Cloud does not provide the sample code. You can use a custom method to develop the data conversion function.
Sub-device development
If you are a device manufacturer who wants to define a sub-device product in the IoT Platform console, you can perform the following operations: set the Node Type parameter to Gateway sub-device and select an authentication mode for the product.
Alibaba Cloud does not provide SDKs for sub-devices. The device manufacturer must reach an agreement with the gateway manufacturer on the protocol that is used to manage the sub-devices. The following sub-device management operations are included: the gateway discovers a sub-device, the gateway connects to the sub-device, the sub-device disconnects from the gateway, and the gateway sends commands from IoT Platform to sub-devices.
Verify and connect a sub-device to IoT Platform by using the gateway
Obtain the certificate of the sub-device
You must use the gateway to register the sub-device in IoT Platform before you connect the sub-device to IoT Platform. The certificate of the sub-device is required for device verification during the sub-device registration. The gateway can use one of the following methods to obtain the sub-device certificate based on business requirements:
Obtain the certificate from the sub-device
A protocol is defined between the gateway and the sub-device. After the gateway discovers and connects to the sub-device, the gateway obtains the sub-device certificate. Alibaba Cloud does not provide protocols. The gateway manufacturer and sub-device manufacturer can define and implement a custom protocol.
Preset the sub-device certificate
This method can be used when the following conditions are met: the gateway can obtain the information of the sub-device before the connection process is initiated, and you can configure the sub-device certificate in the gateway. This feature must be implemented by the gateway manufacturer.
Obtain the sub-device certificate during dynamic registration
The gateway can discover and connect to a sub-device by using a protocol, and obtain the model (the model parameter) and unique identifier (such as the SN and MAC address) of the sub-device. If the gateway fails to obtain the DeviceSecret of the sub-device, perform the following steps:
Add a product for the sub-device in the IoT Platform console. IoT Platform generates a ProductKey for the sub-device.
Use the gateway to map the sub-device model (the model parameter) and the ProductKey generated in the IoT Platform console and set the DeviceName parameter in the IoT Platform console to the unique identifier of the device. The gateway manufacturer implements the mapping between the sub-device model and the ProductKey on the gateway.
The gateway uses the dynamic registration feature of IoT Platform to obtain the DeviceSecret of the sub-device from IoT Platform. This way, the gateway obtains the complete sub-device certificate.
Enable the gateway
When you initialize the gateway, set the enableGateway
option to true
. For more information, see the description about the ioTDMConfig.enableGateway
option in the "Unique-certificate-per-device verification" section of the Verify and connect a device topic.
// By default, the gateway is disabled. After the gateway is enabled, the gateway module is initialized to obtain the sub-device list of the gateway module from IoT Platform.
ioTDMConfig.enableGateway = true;
Dynamically register the sub-device
Dynamically register the sub-device by using the ProductKey and DeviceName
To add a sub-device to the gateway, you must perform dynamic registration to obtain the sub-device certificate. Make sure that the dynamic registration feature is enabled in the IoT Platform console. You can dynamically register multiple sub-devices and obtain all sub-device certificates.
Skip this step if the required sub-device certificate is available on premises. If a sub-device is bound to another gateway, the sub-device certificate is not returned for the dynamic registration request.
LinkKit.getInstance().getGateway().gatewaySubDevicRegister(getSubDevList(), new IConnectSendListener() {
@Override
public void onResponse(ARequest aRequest, AResponse aResponse) {
ALog.d(TAG, "onResponse() called with: aRequest = [" + aRequest + "], aResponse = [" + (aResponse == null ? "null" : aResponse.data) + "]");
try {
// The dynamic registration of the sub-device is successful.
ResponseModel<List<DeviceInfo>> response = JSONObject.parseObject(aResponse.data.toString(), new TypeReference<ResponseModel<List<DeviceInfo>>>() {
}.getType());
// The response indicates whether the dynamic registration is successful. For example, the HTTP status code 200 indicates that the dynamic registration is successful.
// Save the sub-device certificate.
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onFailure(ARequest aRequest, AError aError) {
// The sub-device failed to be dynamically registered.
}
});
Dynamically register the sub-device by using the ProductKey, DeviceName, and ProductSecret
If you have obtained the ProductKey, DeviceName, and ProductSecret of the sub-device and need to perform preemptive dynamic registration, you can use this method to dynamically register the sub-device. When you perform preemptive dynamic registration, the sub-device certificate is returned even if the sub-device is bound to another gateway.
To use this dynamic registration method, you must obtain the ProductSecret of the sub-device. This method is less secure than the previous dynamic registration method.
We recommend that you use configuration over-the-air (COTA) to deliver the ProductKey, DeviceName, and ProductSecret of a sub-device to the gateway, and then perform preemptive dynamic registration.
Scenarios
This method is applicable when you need to unbind a sub-device from Gateway A and then bind the sub-device to Gateway B.
Sample code
// This dynamic registration method requires that you obtain the ProductSecret of the sub-device in advance. Therefore, this method is less secure than the dynamic registration method of using the ProductKey and DeviceName.
// This dynamic registration method can be used together with COTA to deliver the ProductKey, DeviceName, and ProductSecret of the sub-device from IoT Platform.
// After the gateway receives the ProductKey, DeviceName, and ProductSecret, dynamic registration is completed.
// This sample code can be used when you want to change the gateway to which a sub-device is bound.
MqttPublishRequest request = new MqttPublishRequest();
final RequestModel requestModel = new RequestModel();
requestModel.id = String.valueOf(IDGenerater.generateId());
requestModel.version = "1.0";
requestModel.method = GatewayChannel.METHOD_PRESET_SUBDEV_REGITER;
request.isRPC = true;
JSONObject jsonObject = new JSONObject();
JSONArray jsonArray = new JSONArray();
for (int i = 0; i < presetSubdevList.size(); i++) {
DeviceInfo itemDev = presetSubdevList.get(i);
Map<String, String> itemMap = new HashMap<>();
itemMap.put("productKey", itemDev.productKey);
itemMap.put("deviceName", itemDev.deviceName);
itemMap.put("random", RandomStringUtil.getRandomString(10));
String sign = SignUtils.hmacSign(itemMap, itemDev.productSecret);
itemMap.put("sign", sign);
itemMap.put("signMethod", "hmacsha1");
jsonArray.add(itemMap);
}
jsonObject.put("proxieds", jsonArray);
requestModel.params = jsonObject;
request.payloadObj = requestModel.toString();
LinkKit.getInstance().getGateway().subDevicRegister(request, new IConnectSendListener() {
@Override
public void onResponse(ARequest aRequest, AResponse aResponse) {
ALog.d(TAG, "onResponse() called with: aRequest = [" + aRequest + "], aResponse = [" + aResponse + "]");
try {
showToast("The dynamic registration result of the sub-device is received.");
ResponseModel<Map<String, List<DeviceInfo>>> responseModel = JSONObject.parseObject(aResponse.data.toString(),
new TypeReference<ResponseModel<Map<String, List<DeviceInfo>>>>() {
}.getType());
// Save the certificate information of the sub-device.
ALog.d(TAG, "onResponse responseModel=" + JSONObject.toJSONString(responseModel));
// {"code":200,"data":{"failures":[],"successes":[{"deviceSecret":"xxx","productKey":"xxx","deviceName":"xxx"}]},"id":"1","message":"success","method":"thing.proxy.provisioning.product_register","version":"1.0"}
// The list of sub-devices that are registered.
List<DeviceInfo> successList = responseModel.data.get("successes");
// The list of sub-devices that failed to be registered.
List<DeviceInfo> failList = responseModel.data.get("failures");
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onFailure(ARequest aRequest, AError aError) {
ALog.d(TAG, "onFailure() called with: aRequest = [" + aRequest + "], aError = [" + aError + "]");
}
});
Connect the sub-device to IoT Platform by using the gateway
Query the sub-devices
The following sample code shows how to obtain sub-devices that are added to IoT Platform.
LinkKit.getInstance().getGateway().gatewayGetSubDevices(new IConnectSendListener() {
@Override
public void onResponse(ARequest aRequest, AResponse aResponse) {
// The sub-devices that are returned.
try {
ResponseModel<List<DeviceInfo>> response = JSONObject.parseObject(aResponse.data.toString(), new TypeReference<ResponseModel<List<DeviceInfo>>>() {
}.getType());
// Manage the sub-devices based on your business requirements.
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onFailure(ARequest aRequest, AError aError) {
// The sub-device query failed.
}
});
Add the sub-device
The following sample code shows how to add a topological relationship between a gateway and a sub-device after you obtain the sub-device certificate.
final DeviceInfo deviceInfo = new DeviceInfo();
deviceInfo.productKey=productKey; // Required certificate information. The ProductKey of the product to which the sub-device belongs.
deviceInfo.deviceName=deviceName; // Required certificate information. The DeviceName of the sub-device.
LinkKit.getInstance().getGateway().gatewayAddSubDevice(deviceinfo, new ISubDeviceConnectListener() {
@Override
public String getSignMethod() {
// The signature method that is used to sign the request.
return "hmacsha1";
}
@Override
public String getSignValue() {
// Generate a signature based on the DeviceSecret.
Map<String, String> signMap = new HashMap<>();
signMap.put("productKey", info.productKey);
signMap.put("deviceName", info.deviceName);
// signMap.put("timestamp", String.valueOf(System.currentTimeMillis()));
signMap.put("clientId", getClientId());
return SignUtils.hmacSign(signMap, info.deviceSecret);
}
@Override
public String getClientId() {
// The clientId parameter can only be set to a fixed value.
return "id";
}
@Override
public void onConnectResult(boolean isSuccess, ISubDeviceChannel iSubDeviceChannel, AError aError) {
// Handle the result of the operation for adding the topological relationship between the sub-device and the gateway.
if (isSuccess) {
// After the topological relationship is added, you can use the gateway to connect the sub-device to IoT Platform.
// subDevOnline(null);
}
}
@Override
public void onDataPush(String s, AMessage message) {
// The downstream data about the sub-device is received: topic=" + s + ", data=" + message.
// If the downstream data is about disabling, removing, or adding the sub-device or invoking a service, the returned message.data is byte[].
}
});
Remove the sub-device
The following sample code shows how to remove a sub-device from a gateway.
final DeviceInfo deviceInfo = new DeviceInfo();
deviceInfo.productKey = productKey; // Required. The ProductKey of the product to which the sub-device belongs.
deviceInfo.deviceName = deviceName; // Required. The DeviceName of the sub-device.
LinkKit.getInstance().getGateway().gatewayDeleteSubDevice(deviceinfo, new ISubDeviceRemoveListener() {
@Override
public void onSuceess() {
// The sub-device is removed.
}
@Override
public void onFailed(AError aError) {
// The sub-device failed to be removed.
}
});
Connect the sub-device
Before you call the gatewaySubDeviceLogin operation to connect a sub-device to IoT Platform, make sure that you have bound the sub-device to a gateway.
API operations are called in an asynchronous manner. Therefore, the gatewaySubDeviceLogin operation cannot be placed in the next line of the gatewayAddSubDevice operation. The gatewaySubDeviceLogin operation must be called in the callback that indicates that the sub-device is added.
The following sample code shows how to connect a sub-device to IoT Platform after the sub-device is connected to the gateway. After the sub-device is connected to IoT Platform, you can manage the sub-devices in the IoT Platform console, such as message subscription and publishing.
final DeviceInfo deviceInfo = new DeviceInfo();
deviceInfo.productKey = productKey; // Required. The ProductKey of the product to which the sub-device belongs.
deviceInfo.deviceName = deviceName; // Required. The DeviceName of the sub-device.
LinkKit.getInstance().getGateway().gatewaySubDeviceLogin(deviceinfo, new ISubDeviceActionListener() {
@Override
public void onSuccess() {
// The sub-device is connected to IoT Platform.
// After the sub-device is connected to IoT Platform, the sub-device can subscribe to notifications from IoT Platform, such as notifications about sub-device disablement or removal.
// subDevDisable(null);
// subDevDelete(null);
}
@Override
public void onFailed(AError aError) {
ALog.d(TAG, "onFailed() called with: aError = [" + aError + "]");
}
});
Disconnect the sub-device from IoT Platform
After a sub-device is disconnected from IoT Platform, the gateway must notify IoT Platform that the sub-device is disconnected to prevent IoT Platform from sending data to the sub-device. After a sub-device is disconnected from IoT Platform, you cannot publish messages to the sub-device or configure the sub-device to subscribe to or unsubscribe from messages.
final DeviceInfo deviceInfo = new DeviceInfo();
deviceInfo.productKey = productKey; // Required. The ProductKey of the product to which the sub-device belongs.
deviceInfo.deviceName = deviceName; // Required. The DeviceName of the sub-device.
LinkKit.getInstance().getGateway().gatewaySubDeviceLogout(deviceinfo, new ISubDeviceActionListener() {
@Override
public void onSuccess() {
// The sub-device is disconnected from IoT Platform.
}
@Override
public void onFailed(AError aError) {
// The sub-device failed to be disconnected from IoT Platform.
}
});
Listen to the sub-device disablement
You can use a gateway to manage sub-devices in the IoT Platform console. For example, you can enable, disable, or remove sub-devices, and delete the topological relationship between a sub-device and a gateway.
IoT Platform only generates downstream notifications about disabling sub-devices. When a sub-device is disabled in the IoT Platform console, the sub-device is disconnected. Then, the gateway cannot serve as the proxy for the sub-device to communicate with IoT Platform.
final DeviceInfo deviceInfo = new DeviceInfo();
deviceInfo.productKey = productKey; // Required. The ProductKey of the product to which the sub-device belongs.
deviceInfo.deviceName = deviceName; // Required. The DeviceName of the sub-device.
LinkKit.getInstance().getGateway().gatewaySetSubDeviceDisableListener(deviceinfo, new IConnectRrpcListener() {
@Override
public void onSubscribeSuccess(ARequest aRequest) {
// The subscription to the notifications is successful.
}
@Override
public void onSubscribeFailed(ARequest aRequest, AError aError) {
// The subscription to the notifications failed.
}
@Override
public void onReceived(ARequest aRequest, IConnectRrpcHandle iConnectRrpcHandle) {
// The notification about disabling the sub-device.
iConnectRrpcHandle.onRrpcResponse(null, null);
}
@Override
public void onResponseSuccess(ARequest aRequest) {
Log.d(TAG, "onResponseSuccess() called with: aRequest = [" + aRequest + "]");
}
@Override
public void onResponseFailed(ARequest aRequest, AError aError) {
Log.d(TAG, "onResponseFailed() called with: aRequest = [" + aRequest + "], aError = [" + aError + "]");
}
});
Implement communication between the sub-device and IoT Platform by using the gateway
Establish TSL-based communication
Initialize the TSL model for the sub-device
The initSubDeviceThing operation can be called only after the sub-device is added to a gateway and connected to IoT Platform.
ImportantAPI operations are called in an asynchronous manner. Therefore, the initSubDeviceThing operation cannot be placed in the next line of the gatewaySubDeviceLogin operation. The initSubDeviceThing operation must be called in the callback that indicates that the sub-device is connected to IoT Platform.
DeviceInfo deviceInfo = new DeviceInfo(); deviceInfo.productKey = productKey; deviceInfo.deviceName = deviceName; // deviceInfo.deviceSecret = "xxxx"; Map<String, ValueWrapper> subDevInitState = new HashMap<>(); // subDevInitState.put(); // Configure the parameter based on your business requirements. String tsl = null;// Configure the parameter based on your business requirements. By default, this parameter is left empty, which indicates that the latest TSL model is obtained from IoT Platform. LinkKit.getInstance().getGateway().initSubDeviceThing(tsl, deviceInfo, subDevInitState, new IDMCallback<InitResult>() { @Override public void onSuccess(InitResult initResult) { // After the TSL model is initialized, you can perform operations such as service registration and data submission. } @Override public void onFailure(AError aError) { // The sub-device failed to be initialized. } });
The API operation for using the TSL model of a sub-device is the same as that for using the TSL model of a directly connected device. The following sample code shows how to obtain an
IThing
instance.// Obtain an IThing instance. IThing thing = LinkKit.getInstance().getGateway().getSubDeviceThing(mBaseInfo).first; // The thing parameter may be empty, for example, if the sub-device does not log on to IoT Platform, the TSL model is not initialized, the sub-device is not added to a gateway, or the sub-device is disconnected. // The error message is returned in LinkKit.getInstance().getGateway().getSubDeviceThing(mBaseInfo).second. // Check whether the function returns an empty value. thing.thingPropertyPost(reportData, new IPublishResourceListener() { @Override public void onSuccess(String s, Object o) { // The sub-device status is submitted. } @Override public void onError(String s, AError aError) { // The sub-device status failed to be submitted. } });
You can deinitialize the TSL model of a sub-device and delete relevant data.
Next time you want to use the TSL model, you must request the sub-device to log on to IoT Platform and reinitialize the TSL model.
LinkKit.getInstance().getGateway().uninitSubDeviceThing(mBaseInfo);
Basic communication
Use the gateway as a proxy to transmit data between the sub-device and IoT Platform.
final DeviceInfo deviceInfo = new DeviceInfo();
deviceInfo.productKey = productKey; // Required. The ProductKey of the product to which the sub-device belongs.
deviceInfo.deviceName = deviceName; // Required. The DeviceName of the sub-device.
String topic = xxx;
String publishData = xxx;
// Subscribe to a topic.
LinkKit.getInstance().getGateway().gatewaySubDeviceSubscribe(topic, deviceinfo, new ISubDeviceActionListener() {
@Override
public void onSuccess() {
// The subscription is successful.
}
@Override
public void onFailed(AError aError) {
// The subscription failed.
}
});
// Publish a message.
LinkKit.getInstance().getGateway().gatewaySubDevicePublish(topic, publishData, deviceinfo, new ISubDeviceActionListener() {
@Override
public void onSuccess() {
// The message is published.
}
@Override
public void onFailed(AError aError) {
// The message failed to be published.
}
});
// Unsubscribe from the topic.
LinkKit.getInstance().getGateway().gatewaySubDeviceUnsubscribe(topic, deviceinfo, new ISubDeviceActionListener() {
@Override
public void onSuccess() {
// The unsubscription is successful.
}
@Override
public void onFailed(AError aError) {
// The unsubscription failed.
}
});