Gateways and sub-devices
You can use the sub-device management feature to connect sub-devices of a gateway to IoT Platform.
Dynamically register sub-devices
The sub-device management feature allows you to dynamically register sub-devices, query the sub-devices of a gateway, add and remove sub-devices, connect sub-devices, and disconnect sub-devices. You can also listen to messages when sub-devices are disabled and removed, and manage communication between sub-devices and IoT Platform.
A gateway is a device that can be directly connected to IoT Platform. To manage the sub-devices of a gateway, you must connect the gateway to IoT Platform. For more information about how to configure a gateway, see Verify and connect a device and Communication by using MQTT topics.
During dynamic registration, the DeviceSecret of a sub-device is requested from IoT Platform by using the ProductKey and DeviceName. After you obtain the DeviceSecret, you must persist the DeviceSecret on the gateway. This way, the DeviceSecret of the sub-device is not lost regardless of whether 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. The next time the sub-device goes online, you must use the saved device certificate for verification.
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
If you add a sub-device to a gateway, a topological relationship is established between the sub-device and the gateway on premises and in IoT Platform. Before a sub-device can send upstream and downstream data by using a gateway, a topological relationship must be established between the sub-device and the gateway. After a sub-device is added, the topological relationship remains in effect until you remove the sub-device.
You can use the following methods to add a sub-device:
Obtain the device certificate of the sub-device by dynamically registering the corresponding gateway. 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"]]; }); }];If the device certificate of a sub-device is burned to the sub-device, 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
The following sample code shows how to remove a sub-device from the corresponding 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 a sub-device to IoT Platform
Before you can subscribe to a topic for a sub-device and publish messages to the topic, you must connect the sub-device to IoT Platform. Sample code that you can use to connect a sub-device to IoT Platform by using a gateway:
__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 a sub-device from IoT Platform
You cannot perform operations such as publish, subscribe, and unsubscribe on an offline sub-device. The following sample code shows how to disconnect a sub-device from IoT Platform:
__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 when sub-devices are disabled and removed
You can use a gateway to perform operations on a sub-device in the IoT Platform console. For example, you can disable and enable sub-devices, and delete the topological relationship between a sub-device and a gateway. IoT Platform supports only downstream notifications when you disable sub-devices. If you disable a sub-device in the IoT Platform console, the sub-device is disconnected. The gateway cannot communicate with IoT Platform on behalf of the sub-device. You can configure a stateListener to listen to messages when sub-devices are disabled and removed.
self.subChannel.stateListener = self;
Transmit upstream and downstream data
Use the gateway as a proxy to transmit data between a sub-device and IoT Platform.
The following sample code shows how to transmit upstream data:
- (IBAction)onClickUpload:(id)sender {
if (self.subChannel == nil) {
[self ims_showHUDWithMessage:@ "Add a sub-device and connect the sub-device 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"]];
});
}];
}
IoT Platform supports only quality of service (QoS) 0 and QoS 1 messages.
If a sub-device needs to receive downstream data from IoT Platform, you must subscribe to the corresponding topics for the sub-device. Sample code:
- (IBAction)onClickSubscribe:(id)sender {
if (self.subChannel == nil) {
[self ims_showHUDWithMessage:@ "Add a sub-device and connect the sub-device 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 a gateway, you must specify an ILKSubDeviceDelegate instance. Sample code:
/// 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 data.
- (void)onDataPush:(nonnull NSString *)topic data:(nonnull NSData *)data {
NSString * downData = [NSString stringWithFormat:@ "The downstream data 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 are received. Example:
- (IBAction)onClickUnsubscribe:(id)sender {
if (self.subChannel == nil) {
[self ims_showHUDWithMessage:@ "Add a sub-device and connect the sub-device 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"]];
});
}];
}