全部产品
云市场

子设备管理

更新时间:2018-12-22 21:01:34

如果当前设备是一个网关,且该网关下的子设备需接入云端,此时需要使用子设备管理功能。

网关子设备管理提供了子设备动态注册、获取云端网关下子设备列表、添加子设备、删除子设备、子设备上线、子设备下线、监听子设备禁用和删除的消息、代理子设备数据上下行的能力。

网关本身是一个直连设备,网关产品的开发参见前面章节中介绍的“认证与连接”、“自定义MQTT Topic通信”。网关使用子设备管理的功能前,需要网关已经连接到阿里云物联网平台。

子设备动态注册

子设备的动态注册是指网关根据子设备的 productKey/deviceName向云端获取子设备DeviceSecret的过程,网关获取到子设备的DeviceSecret之后,需要将其保存在网关上,即使网关reset也不能将子设备的DeviceSecret丢失;

子设备在商家后台创建时需要开启允许动态注册功能,同时子设备的deviceName需要厂商预先上传到阿里云物联网平台。

示例代码如下:

  1. self.gatewayInterface = [[LinkKitEntry sharedKit] gatewayInterface];
  2. NSMutableArray * subBases = @[].mutableCopy;
  3. for (NSDictionary * subinfo in _subDevices) {
  4. LinkkitDeviceBase * base = [[LinkkitDeviceBase alloc] init];
  5. base.productKey = [subinfo valueForKey:@"productKey"];
  6. base.deviceName = [subinfo valueForKey:@"deviceName"];
  7. [subBases addObject:base];
  8. }
  9. [self.gatewayInterface subDeviceRegisterBatch:subBases
  10. resultBlock:^(NSArray * _Nullable result, NSError * _Nullable error) {
  11. LinkkitLogDebug(@"subDeviceRegisterBatch error : %@", error);
  12. self.subDevicesReg = result;
  13. LinkkitDeviceAuth * authSub = result[0];
  14. /// LinkkitDeviceAuth这个类包含deviceSecret,建议用户将deviceSecret持久保存。当子设备再次上线时,使用保存的子设备三元组进行身份认证。
  15. dispatch_async(dispatch_get_main_queue(), ^{
  16. [self ims_showHUDWithMessage:[NSString stringWithFormat:@"成功注册子设备个数 : %d",
  17. (int)self.subDevicesReg.count]];
  18. });
  19. }];

添加子设备到网关

添加子设备过程实际上是子设备跟网关在本地以及IoT云端建立 Topo 关系的过程,子设备要通过网关实现数据上下云必须首先跟网关建立 topo 关系。topo 关系建立后一直存在,直到删除 topo 关系。

添加子设备存在两种方式:其一:通过动态注册网关获取到了子设备的三元组信息。这种子设备添加到网关的示例代码如下:

  1. __weak typeof (self) weakSelf = self;
  2. LinkkitDeviceAuth * authSub = self.subDevicesReg[0];
  3. [self.gatewayInterface addSubDevice:authSub
  4. delegate:self
  5. resultBlock:^(id<ILKSubDeviceChannel> _Nonnull subChannel, NSError * _Nullable error) {
  6. LinkkitLogDebug(@"subDevice logout add to gateway : %@", error);
  7. weakSelf.subChannel = subChannel;
  8. dispatch_async(dispatch_get_main_queue(), ^{
  9. weakSelf.lableSubState.text = @"已关联至网关";
  10. [weakSelf ims_showHUDWithMessage:[NSString stringWithFormat:@"添加子设备到网关 : %@", error ? @"失败":@"成功"]];
  11. });
  12. }];

其二:子设备本身烧录了设备三元组信息,对于此类设备,切记无需要再去调用 “子设备动态注册” 方法。这种子设备添加到网关的示例代码如下:

  1. __weak typeof (self) weakSelf = self;
  2. LinkkitDeviceBase * devBase = [[LinkkitDeviceBase alloc] init];
  3. devBase.productKey = @"sub device productKey";
  4. devBase.deviceName = @"sub device deviceName";
  5. [self.gatewayInterface addSubDevice:devBase signer:self
  6. delegate:self resultBlock:^(id<ILKSubDeviceChannel> _Nullable subChannel, NSError * _Nullable error) {
  7. LinkkitLogDebug(@"subDevice logout add to gateway : %@", error);
  8. weakSelf.subChannel = subChannel;
  9. dispatch_async(dispatch_get_main_queue(), ^{
  10. weakSelf.lableSubState.text = @"已关联至网关";
  11. [weakSelf ims_showHUDWithMessage:[NSString stringWithFormat:@"添加子设备到网关 : %@", error ? @"失败":@"成功"]];
  12. });
  13. }];
  14. // 其中 signer的具体实现,请参见LinkkitGateway.h 中的 protocol ILKSubDeviceSigner 声明中 介绍。

从网关删除子设备

此处指删除子设备跟网关的 Topo 关系

  1. __weak typeof (self) weakSelf = self;
  2. LinkkitDeviceBase * devBase = [[LinkkitDeviceBase alloc] init];
  3. devBase.productKey = @"sub device productKey";
  4. devBase.deviceName = @"sub device deviceName";
  5. [self.gatewayInterface deleteSubDevice:devBase
  6. resultBlock:^(BOOL succeeded, NSError * _Nullable error) {
  7. LinkkitLogDebug(@"subDevice delete from gateway error : %@", error);
  8. weakSelf.subChannel = nil;
  9. dispatch_async(dispatch_get_main_queue(), ^{
  10. weakSelf.lableSubState.text = @"未关联网关";
  11. [weakSelf ims_showHUDWithMessage:[NSString stringWithFormat:@"从网关删除子设备 : %@", error ? @"失败":@"成功"]];
  12. });
  13. }];

子设备上线

代理子设备上线,子设备必须在上线之后才可以执行子设备的订阅、发布等操作。

  1. __weak typeof (self) weakSelf = self;
  2. [self.subChannel login:^(BOOL succeeded, NSError * _Nullable error) {
  3. LinkkitLogDebug(@"subDevice login error : %@", error);
  4. dispatch_async(dispatch_get_main_queue(), ^{
  5. weakSelf.lableSubState.text = @"已上线";
  6. [weakSelf ims_showHUDWithMessage:[NSString stringWithFormat:@"子设备上线 : %@", error ? @"失败":@"成功"]];
  7. });
  8. }];

子设备下线

子设备下线之后不可以进行子设备的发布、订阅、取消订阅等操作。

  1. __weak typeof (self) weakSelf = self;
  2. [self.subChannel logout:^(BOOL succeeded, NSError * _Nullable error) {
  3. LinkkitLogDebug(@"subDevice logout error : %@", error);
  4. dispatch_async(dispatch_get_main_queue(), ^{
  5. weakSelf.lableSubState.text = @"未上线";
  6. [weakSelf ims_showHUDWithMessage:[NSString stringWithFormat:@"子设备下线 : %@", error ? @"失败":@"成功"]];
  7. });
  8. }];

监听子设备禁用、删除

网关设备可以在云端操作子设备,如禁用子设备、启用子设备、删除和子设备的拓扑关系。目前服务端只支持禁用子设备的下行通知。服务端在禁用子设备的时候会对子设备做下线处理,后续网关将不能代理子设备和云端做通信。可以通过设置子设备 stateListener 来侦听子设备禁用、删除消息

  1. self.subChannel.stateListener = self;

代理子设备基础数据上下行

使用网关的通道执行子设备的数据上下行。

上行数据示例代码:

  1. - (IBAction)onClickUpload:(id)sender {
  2. if (self.subChannel == nil) {
  3. [self ims_showHUDWithMessage:@"请添加子设备并上线"];
  4. return;
  5. }
  6. __weak typeof (self) weakSelf = self;
  7. NSString * topic = self.textFieldPubTopic.text;
  8. NSData * upData = [self.textViewPubContent.text dataUsingEncoding:NSUTF8StringEncoding];
  9. int qos = [self.textFieldQos.text intValue];
  10. [self.subChannel publish:topic data:upData qos:qos
  11. resultBlock:^(BOOL succeeded, NSError * _Nullable error) {
  12. LinkkitLogDebug(@"subDevice upload error : %@", error);
  13. dispatch_async(dispatch_get_main_queue(), ^{
  14. [weakSelf ims_showHUDWithMessage:[NSString stringWithFormat:@"子设备数据上行 : %@", error ? @"失败":@"成功"]];
  15. });
  16. }];
  17. }

说明:关于qos取值,目前阿里云IoT平台只支持 qos取值为[0,1],对于qos=2目前不支持。

如果需要能收到子设备的下推消息,首先需要订阅相关topic示例代码如下:

  1. - (IBAction)onClickSubscribe:(id)sender {
  2. if (self.subChannel == nil) {
  3. [self ims_showHUDWithMessage:@"请添加子设备并上线"];
  4. return;
  5. }
  6. __weak typeof (self) weakSelf = self;
  7. NSString * topic = self.textFieldSubTopic.text;
  8. [self.subChannel subscribe:topic
  9. resultBlock:^(BOOL succeeded, NSError * _Nullable error) {
  10. LinkkitLogDebug(@"subDevice subscribe error : %@", error);
  11. dispatch_async(dispatch_get_main_queue(), ^{
  12. [weakSelf ims_showHUDWithMessage:[NSString stringWithFormat:@"子设备订阅 : %@", error ? @"失败":@"成功"]];
  13. });
  14. }];
  15. }

同时,还需要在添加子设备到网关时传入 ILKSubDeviceDelegate 的实例。ILKSubDeviceDelegate 实现如下所示:

  1. ///侦听子设备与云端的连接状态,即上下线情况
  2. - (void)onConnectResult:(BOOL)success
  3. error:(NSError * _Nullable)err
  4. subDeviceChannel:(nonnull id<ILKSubDeviceChannel>)subDeviceChannel {
  5. if ([self.subChannel.subDeviceProfile.deviceBaseId
  6. isEqualToString:subDeviceChannel.subDeviceProfile.deviceBaseId]) {
  7. //__weak typeof (self) weakSelf = self;
  8. dispatch_async(dispatch_get_main_queue(), ^{
  9. });
  10. } else {
  11. }
  12. }
  13. ///侦听子设备的下推(从云端下推)数据
  14. - (void)onDataPush:(nonnull NSString *)topic data:(nonnull NSData *)data {
  15. NSString * downData = [NSString stringWithFormat:@"收到下推,topic : %@ \r\n", topic];
  16. downData = [downData stringByAppendingString:[NSString stringWithFormat:@"\r\n数据 : %@", data]];
  17. LinkkitLogDebug(@"subDevice recv topic : %@", topic);
  18. dispatch_async(dispatch_get_main_queue(), ^{
  19. self.textViewDownData.text = downData;
  20. });
  21. }

可以通过取消订阅方法来屏蔽某些已经订阅过的消息。示例代码如下:

  1. - (IBAction)onClickUnsubscribe:(id)sender {
  2. if (self.subChannel == nil) {
  3. [self ims_showHUDWithMessage:@"请添加子设备并上线"];
  4. return;
  5. }
  6. __weak typeof (self) weakSelf = self;
  7. NSString * topic = self.textFieldSubTopic.text;
  8. [self.subChannel unsubscribe:topic
  9. resultBlock:^(BOOL succeeded, NSError * _Nullable error) {
  10. LinkkitLogDebug(@"subDevice unsubscribe error : %@", error);
  11. dispatch_async(dispatch_get_main_queue(), ^{
  12. [weakSelf ims_showHUDWithMessage:[NSString stringWithFormat:@"子设备取消订阅 : %@", error ? @"失败":@"成功"]];
  13. });
  14. }];
  15. }