全部產品
Search
文件中心

IoT Platform:網關與子裝置

更新時間:Jun 30, 2024

如果當前裝置是一個網關,且該網關下的子裝置需接入雲端,此時需要使用子裝置管理功能。

子裝置動態註冊

網關子裝置管理提供子裝置動態註冊、擷取雲端網關下子裝置列表、添加子裝置、刪除子裝置、子裝置上線、子裝置下線、監聽子裝置禁用和刪除的訊息、代理子裝置資料上下行的能力。

網關本身是一個直連裝置,網關使用子裝置管理的功能前,需要網關已經串連到阿里雲物聯網平台。網關裝置的開發,請參見認證與串連基於MQTT Topic通訊

子裝置的動態註冊是指網關根據子裝置的productKeydeviceName向雲端擷取子裝置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雲端建立拓撲關係的過程,子裝置要通過網關實現資料上下雲,必須首先跟網關建立拓撲關係。拓撲關係建立後一直存在,直到刪除拓撲關係。

添加子裝置存在兩種方式:

  • 通過動態註冊網關擷取到了子裝置的認證資訊。 範例程式碼如下:

       __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 聲明中介紹。
                        

從網關刪除子裝置

刪除子裝置與網關拓撲關係的範例程式碼如下:

    __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 ? @"失敗":@"成功"]];
                       });
                   }];
}