You can use the sub-device management feature when you connect sub-devices of a gateway to IoT Platform.
Perform dynamic registration
This feature allows you to dynamically register sub-devices, query sub-devices of a gateway, add and remove sub-devices, connect sub-devices, and disconnect sub-devices. You can also listen to messages about disabling and removing sub-devices, and manage communication between sub-devices and IoT Platform.
A gateway is a directly connected device. For more information about how to develop a gateway, see the following topics: Authentication and connection, and MQTT topic-based communication. To manage sub-devices of a gateway, you must connect the gateway to IoT Platform.
During dynamic registration, you request the DeviceSecret of a sub-device from IoT Platform by using the ProductKey and DeviceName. After you obtain the DeviceSecret, you must persist it on the gateway. This way, the DeviceSecret of the sub-device cannot be lost even if the gateway is reset.
The sub-device manufacturer must enable the dynamic registration feature in IoT Platform, and upload a DeviceName to IoT Platform.
Sample code:
self.gatewayInterface = [[LinkKitEntry sharedKit] gatewayInterface];
NSMutableArray * subBases = @[].mutableCopy;
for (NSDictionary * subinfo in _subDevices) {
LinkkitDeviceBase * base = [[LinkkitDeviceBase alloc] init];
base.productKey = [subinfo valueForKey:@"productKey"];
base.deviceName = [subinfo valueForKey:@"deviceName"];
[subBases addObject:base];
}
[self.gatewayInterface subDeviceRegisterBatch:subBases
resultBlock:^(NSArray * _Nullable result, NSError * _Nullable error) {
LinkkitLogDebug(@"subDeviceRegisterBatch error : %@", error);
self.subDevicesReg = result;
LinkkitDeviceAuth * authSub = result[0];
/// The LinkkitDeviceAuth class contains the DeviceSecret. We recommend that you persist the DeviceSecret. When the sub-device goes online again, you must use the saved ProductKey, DeviceName, and DeviceSecret for authentication.
dispatch_async(dispatch_get_main_queue(), ^{
[self ims_showHUDWithMessage:[NSString stringWithFormat:@ "The number of registered sub-devices: %@",
(int)self.subDevicesReg.count]];
});
}];
Add sub-devices to a gateway
Adding a sub-device indicates establishing a topological relationship between the sub-device and the gateway on premises and in IoT Platform. A topological relationship must be established before the gateway can be used as a proxy of the sub-device to send upstream and downstream data. After a sub-device is added, the topological relationship remains until you remove the sub-device.
You can use the following methods to add a sub-device:
- Obtain the ProductKey, DeviceName, and DeviceSecret of the sub-device by using dynamic registration. Sample code:
__weak typeof (self) weakSelf = self; LinkkitDeviceAuth * authSub = self.subDevicesReg[0]; [self.gatewayInterface addSubDevice:authSub delegate:self resultBlock:^(id<ILKSubDeviceChannel> _Nonnull subChannel, NSError * _Nullable error) { LinkkitLogDebug(@"subDevice logout add to gateway : %@", error); weakSelf.subChannel = subChannel; dispatch_async(dispatch_get_main_queue(), ^{ weakSelf.lableSubState.text = @ "Associated with the gateway"; [weakSelf ims_showHUDWithMessage:[NSString stringWithFormat:@ "Add the sub-device to the gateway :%@", error? @ "Failure":@ "Success"]]; }); }];
- Use the ProductKey, DeviceName, and DeviceSecret that is burned to the sub-device. In this scenario, you do not need to perform dynamic registration. Sample code:
__weak typeof (self) weakSelf = self; LinkkitDeviceBase * devBase = [[LinkkitDeviceBase alloc] init]; devBase.productKey = @"sub device productKey"; devBase.deviceName = @"sub device deviceName"; [self.gatewayInterface addSubDevice:devBase signer:self delegate:self resultBlock:^(id<ILKSubDeviceChannel> _Nullable subChannel, NSError * _Nullable error) { LinkkitLogDebug(@"subDevice logout add to gateway : %@", error); weakSelf.subChannel = subChannel; dispatch_async(dispatch_get_main_queue(), ^{ weakSelf.lableSubState.text = @ "Associated with the gateway"; [weakSelf ims_showHUDWithMessage:[NSString stringWithFormat:@ "Add the sub-device to the gateway :%@", error? @ "Failure":@ "Success"]]; }); }]; // For more information about how to configure a signer, see protocol ILKSubDeviceSigner in the LinkkitGateway.h header file.
Remove sub-devices from a gateway
Removing a sub-device indicates deleting the topological relationship between the sub-device and the gateway.
__weak typeof (self) weakSelf = self;
LinkkitDeviceBase * devBase = [[LinkkitDeviceBase alloc] init];
devBase.productKey = @"sub device productKey";
devBase.deviceName = @"sub device deviceName";
[self.gatewayInterface deleteSubDevice:devBase
resultBlock:^(BOOL succeeded, NSError * _Nullable error) {
LinkkitLogDebug(@"subDevice delete from gateway error : %@", error);
weakSelf.subChannel = nil;
dispatch_async(dispatch_get_main_queue(), ^{
weakSelf.lableSubState.text = @ "Unassociated with the gateway";
[weakSelf ims_showHUDWithMessage:[NSString stringWithFormat:@ "Remove the sub-device from the gateway :%@", error? @ "Failure":@ "Success"]];
});
}];
Connect sub-devices to IoT Platform
You can use a gateway to connect a sub-device to IoT Platform. You can subscribe to topics and publish messages to topics only after the sub-device is connected to IoT Platform.
__weak typeof (self) weakSelf = self;
[self.subChannel login:^(BOOL succeeded, NSError * _Nullable error) {
LinkkitLogDebug(@"subDevice login error : %@", error);
dispatch_async(dispatch_get_main_queue(), ^{
weakSelf.lableSubState.text = @ "The sub-device is online";
[weakSelf ims_showHUDWithMessage:[NSString stringWithFormat:@ "Connect the sub-device to IoT Platform :%@", error? @ "Failure":@ "Success"]];
});
}];
Disconnect sub-devices from IoT Platform
After a sub-device is disconnected, you cannot subscribe to topics, publish messages to topics, or unsubscribe from topics.
__weak typeof (self) weakSelf = self;
[self.subChannel logout:^(BOOL succeeded, NSError * _Nullable error) {
LinkkitLogDebug(@"subDevice logout error : %@", error);
dispatch_async(dispatch_get_main_queue(), ^{
weakSelf.lableSubState.text = @ "The sub-device is offline";
[weakSelf ims_showHUDWithMessage:[NSString stringWithFormat:@ "Disconnect the sub-device from IoT Platform :%@", error? @ "Failure":@ "Success"]];
});
}];
Listen to messages about disabling and removing sub-devices
You can use a gateway to enable and disable sub-devices, and remove sub-devices from the on-premises topology of the gateway. IoT Platform can send only the downstream messages about disabling sub-devices. When you disable a sub-device, the sub-device is disconnected from IoT Platform. Then, the gateway cannot be used a proxy of the sub-device to communicate with IoT Platform. You can set a stateListener to listen to messages about disabling and removing sub-devices.
self.subChannel.stateListener = self;
Forward upstream and downstream data
You can use a gateway to forward upstream data to IoT Platform and downstream data to sub-devices.
The following sample code can be used to forward upstream data:
- (IBAction)onClickUpload:(id)sender {
if (self.subChannel == nil) {
[self ims_showHUDWithMessage:@ "Add the sub-device and connect it to IoT Platform"];
return;
}
__weak typeof (self) weakSelf = self;
NSString * topic = self.textFieldPubTopic.text;
NSData * upData = [self.textViewPubContent.text dataUsingEncoding:NSUTF8StringEncoding];
int qos = [self.textFieldQos.text intValue];
[self.subChannel publish:topic data:upData qos:qos
resultBlock:^(BOOL succeeded, NSError * _Nullable error) {
LinkkitLogDebug(@"subDevice upload error : %@", error);
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf ims_showHUDWithMessage:[NSString stringWithFormat:@ "Forward upstream data to IoT Platform :%@", error? @ "Failure":@ "Success"]];
});
}];
}
Note: 1. You can set the quality of service (QoS) level to only 0 or 1. You cannot set the QoS level to 2.
To receive downstream data, you must subscribe to topics. The following sample code can be used:
- (IBAction)onClickSubscribe:(id)sender {
if (self.subChannel == nil) {
[self ims_showHUDWithMessage:@ "Add the sub-device and connect it to IoT Platform"];
return;
}
__weak typeof (self) weakSelf = self;
NSString * topic = self.textFieldSubTopic.text;
[self.subChannel subscribe:topic
resultBlock:^(BOOL succeeded, NSError * _Nullable error) {
LinkkitLogDebug(@"subDevice subscribe error : %@", error);
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf ims_showHUDWithMessage:[NSString stringWithFormat:@ "Subscribe to a topic:%@", error? @ "Failure":@ "Success"]];
});
}];
}
When you add a sub-device to the gateway, you must import the ILKSubDeviceDelegate instance. The following sample code can be used:
/// Listen to the status of the connection between the sub-device and IoT Platform.
- (void)onConnectResult:(BOOL)success
error:(NSError * _Nullable)err
subDeviceChannel:(nonnull id<ILKSubDeviceChannel>)subDeviceChannel {
if ([self.subChannel.subDeviceProfile.deviceBaseId
isEqualToString:subDeviceChannel.subDeviceProfile.deviceBaseId]) {
//__weak typeof (self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
});
} else {
}
}
/// Listen to downstream messages.
- (void)onDataPush:(nonnull NSString *)topic data:(nonnull NSData *)data {
NSString * downData = [NSString stringWithFormat:@ "The downstream message is received, topic :%@ \r\n", topic];
downData = [downData stringByAppendingString:[NSString stringWithFormat:@ "\r \ndata :%@", data]];
LinkkitLogDebug(@"subDevice recv topic : %@", topic);
dispatch_async(dispatch_get_main_queue(), ^{
self.textViewDownData.text = downData;
});
}
You can unsubscribe from a topic to block messages that have been received. The following code can be used:
- (IBAction)onClickUnsubscribe:(id)sender {
if (self.subChannel == nil) {
[self ims_showHUDWithMessage:@ "Add the sub-device and connect it to IoT Platform"];
return;
}
__weak typeof (self) weakSelf = self;
NSString * topic = self.textFieldSubTopic.text;
[self.subChannel unsubscribe:topic
resultBlock:^(BOOL succeeded, NSError * _Nullable error) {
LinkkitLogDebug(@"subDevice unsubscribe error : %@", error);
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf ims_showHUDWithMessage:[NSString stringWithFormat:@ "Unsubscribe from a topic:%@", error? @ "Failure":@ "Success"]];
});
}];
}