更新时间:2018-12-22 21:01
如果当前设备是一个网关,且该网关下的子设备需接入云端,此时需要使用子设备管理功能。
网关子设备管理提供了子设备动态注册、获取云端网关下子设备列表、添加子设备、删除子设备、子设备上线、子设备下线、监听子设备禁用和删除的消息、代理子设备数据上下行的能力。
网关本身是一个直连设备,网关产品的开发参见前面章节中介绍的“认证与连接”、“自定义MQTT Topic通信”。网关使用子设备管理的功能前,需要网关已经连接到阿里云物联网平台。
子设备的动态注册是指网关根据子设备的 productKey/deviceName向云端获取子设备DeviceSecret的过程,网关获取到子设备的DeviceSecret之后,需要将其保存在网关上,即使网关reset也不能将子设备的DeviceSecret丢失;
子设备在商家后台创建时需要开启允许动态注册功能,同时子设备的deviceName需要厂商预先上传到阿里云物联网平台。
示例代码如下:
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];
/// LinkkitDeviceAuth这个类包含deviceSecret,建议用户将deviceSecret持久保存。当子设备再次上线时,使用保存的子设备三元组进行身份认证。
dispatch_async(dispatch_get_main_queue(), ^{
[self ims_showHUDWithMessage:[NSString stringWithFormat:@"成功注册子设备个数 : %d",
(int)self.subDevicesReg.count]];
});
}];
添加子设备过程实际上是子设备跟网关在本地以及IoT云端建立 Topo 关系的过程,子设备要通过网关实现数据上下云必须首先跟网关建立 topo 关系。topo 关系建立后一直存在,直到删除 topo 关系。
添加子设备存在两种方式:其一:通过动态注册网关获取到了子设备的三元组信息。这种子设备添加到网关的示例代码如下:
__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 = @"已关联至网关";
[weakSelf ims_showHUDWithMessage:[NSString stringWithFormat:@"添加子设备到网关 : %@", error ? @"失败":@"成功"]];
});
}];
其二:子设备本身烧录了设备三元组信息,对于此类设备,切记无需要再去调用 “子设备动态注册” 方法。这种子设备添加到网关的示例代码如下:
__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 = @"已关联至网关";
[weakSelf ims_showHUDWithMessage:[NSString stringWithFormat:@"添加子设备到网关 : %@", error ? @"失败":@"成功"]];
});
}];
// 其中 signer的具体实现,请参见LinkkitGateway.h 中的 protocol ILKSubDeviceSigner 声明中 介绍。
此处指删除子设备跟网关的 Topo 关系
__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 = @"未关联网关";
[weakSelf ims_showHUDWithMessage:[NSString stringWithFormat:@"从网关删除子设备 : %@", error ? @"失败":@"成功"]];
});
}];
代理子设备上线,子设备必须在上线之后才可以执行子设备的订阅、发布等操作。
__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 = @"已上线";
[weakSelf ims_showHUDWithMessage:[NSString stringWithFormat:@"子设备上线 : %@", error ? @"失败":@"成功"]];
});
}];
子设备下线之后不可以进行子设备的发布、订阅、取消订阅等操作。
__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 = @"未上线";
[weakSelf ims_showHUDWithMessage:[NSString stringWithFormat:@"子设备下线 : %@", error ? @"失败":@"成功"]];
});
}];
网关设备可以在云端操作子设备,如禁用子设备、启用子设备、删除和子设备的拓扑关系。目前服务端只支持禁用子设备的下行通知。服务端在禁用子设备的时候会对子设备做下线处理,后续网关将不能代理子设备和云端做通信。可以通过设置子设备 stateListener 来侦听子设备禁用、删除消息
self.subChannel.stateListener = self;
使用网关的通道执行子设备的数据上下行。
上行数据示例代码:
- (IBAction)onClickUpload:(id)sender {
if (self.subChannel == nil) {
[self ims_showHUDWithMessage:@"请添加子设备并上线"];
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:@"子设备数据上行 : %@", error ? @"失败":@"成功"]];
});
}];
}
说明:关于qos取值,目前阿里云IoT平台只支持 qos取值为[0,1],对于qos=2目前不支持。
如果需要能收到子设备的下推消息,首先需要订阅相关topic示例代码如下:
- (IBAction)onClickSubscribe:(id)sender {
if (self.subChannel == nil) {
[self ims_showHUDWithMessage:@"请添加子设备并上线"];
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:@"子设备订阅 : %@", error ? @"失败":@"成功"]];
});
}];
}
同时,还需要在添加子设备到网关时传入 ILKSubDeviceDelegate 的实例。ILKSubDeviceDelegate 实现如下所示:
///侦听子设备与云端的连接状态,即上下线情况
- (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 {
}
}
///侦听子设备的下推(从云端下推)数据
- (void)onDataPush:(nonnull NSString *)topic data:(nonnull NSData *)data {
NSString * downData = [NSString stringWithFormat:@"收到下推,topic : %@ \r\n", topic];
downData = [downData stringByAppendingString:[NSString stringWithFormat:@"\r\n数据 : %@", data]];
LinkkitLogDebug(@"subDevice recv topic : %@", topic);
dispatch_async(dispatch_get_main_queue(), ^{
self.textViewDownData.text = downData;
});
}
可以通过取消订阅方法来屏蔽某些已经订阅过的消息。示例代码如下:
- (IBAction)onClickUnsubscribe:(id)sender {
if (self.subChannel == nil) {
[self ims_showHUDWithMessage:@"请添加子设备并上线"];
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:@"子设备取消订阅 : %@", error ? @"失败":@"成功"]];
});
}];
}
在文档使用中是否遇到以下问题
更多建议
匿名提交