1. 程式人生 > >MQTT(二)----- iOS使用

MQTT(二)----- iOS使用

第一步:安裝
目前,使用的是Pod生成的MQTTClient第三方庫,直接下載就行 pod 'MQTTClient’

第二步:繫結
繫結前需要設定幾個屬性,主要有:
帳號、密碼、clientId、ip、埠。
其次,還要注意這個庫是沒有連線中斷自動重連的。所以需要監聽他的狀態。

#pragma mark - 繫結
- (void)bindWithUserName:(NSString *)username password:(NSString *)password cliendId:(NSString *)cliendId isSSL:(BOOL)isSSL{
    
    self.username = username;
    self.password = password;
    self.cliendId = cliendId;
    
    self.mySession = [[MQTTSession alloc]initWithClientId:self.cliendId userName:self.username password:self.password keepAlive:60 cleanSession:YES will:NO willTopic:nil willMsg:nil willQoS:MQTTQosLevelAtLeastOnce willRetainFlag:NO protocolLevel:4 queue:dispatch_get_main_queue() securityPolicy:[self customSecurityPolicy] certificates:nil];
    
    self.isDiscontent = NO;

    self.mySession.delegate = self;
    
    [self.mySession connectToHost:AddressOfMQTTServer port:self.isSSL?PortOfMQTTServerWithSSL:PortOfMQTTServer usingSSL:isSSL];
    
    [self.mySession addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];
    
    
}

- (MQTTSSLSecurityPolicy *)customSecurityPolicy
{
    NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"ca" ofType:@"crt"];
    
    NSData *certData = [NSData dataWithContentsOfFile:cerPath];
    
    MQTTSSLSecurityPolicy *securityPolicy = [MQTTSSLSecurityPolicy policyWithPinningMode:MQTTSSLPinningModeNone];
    
    securityPolicy.allowInvalidCertificates = YES;
    securityPolicy.validatesCertificateChain = YES;
    securityPolicy.validatesDomainName = NO;
    securityPolicy.pinnedCertificates = @[certData];
    return securityPolicy;
}

當繫結完成之後,會打印出以下的資訊。
在這裡插入圖片描述
第三步:設定斷線重連

#pragma mark ---- 狀態

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    
    
    switch (self.mySession.status) {
        case MQTTSessionStatusClosed:
            NSLog(@"連線關閉");
            if (!self.isDiscontent) [self.mySession connect]; //這個是為了區分是主動斷開還是被動斷開。
            break;
        case MQTTSessionStatusConnected:
            NSLog(@"連線成功");
            [self subscribeTopicInArray];//這個是為了避免有部分訂閱命令再連線完成前傳送,導致訂閱失敗。
            break;
        case MQTTSessionStatusConnecting:
            NSLog(@"連線中");
            
            break;
        case MQTTSessionStatusError:
            NSLog(@"連線錯誤");
            
            break;
        case MQTTSessionStatusDisconnecting:
            NSLog(@"正在斷開連線");
            
        default:
            break;
    }
    
}

第四步:訂閱命令

#pragma mark - 訂閱
- (void)subscribeTopic:(NSString *)topic {
    if (self.mySession.status != MQTTSessionStatusConnected  && ![self.subArray containsObject:topic]) {
        
        [self.subArray addObject:topic];
        return;
    }
    __weak typeof(self) weakSelf = self;
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        dispatch_async(dispatch_get_main_queue(), ^{
            
            [self.mySession subscribeToTopic:topic atLevel:MQTTQosLevelAtLeastOnce subscribeHandler:^(NSError *error, NSArray<NSNumber *> *gQoss) {
                if (error) {
                    NSLog(@"subscribeTopic failed ----- topic = %@ \n %@",topic,error.localizedDescription);
                    [weakSelf.subArray addObject:topic];
                    [weakSelf subscribeTopicInArray];
                } else {
                    if ([weakSelf.subArray containsObject:topic]) {
                        [weakSelf.subArray removeObject:topic];
                    }
                    
                    NSLog(@"subscribeTopic sucessfull 成功! topic = %@  \n %@",topic,gQoss);
                }
            }];
            
        });
    });
}

取消訂閱

#pragma mark - 取消訂閱
- (void)unsubscribeTopic:(NSString *)topic {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        dispatch_async(dispatch_get_main_queue(), ^{
            
            [self.mySession unsubscribeTopic:topic unsubscribeHandler:^(NSError *error) {
                if (error) {
                    NSLog(@"unsubscribeTopic failed ----- topic = %@ \n %@",topic,error.localizedDescription);
                } else {
                    NSLog(@"unsubscribeTopic sucessfull 成功! topic = %@ ",topic);
                }
            }];
        });
    });
}

釋出訊息

#pragma mark - 釋出訊息
- (void)sendDataToTopic:(NSString *)topic dict:(NSDictionary *)dict {    
    [self.mySession publishJson:dict onTopic:topic];    
}

資料接收回調

#pragma mark MQTTSessionDelegate
- (void)newMessage:(MQTTSession *)session data:(NSData *)data onTopic:(NSString *)topic qos:(MQTTQosLevel)qos retained:(BOOL)retained mid:(unsigned int)mid {
    NSLog(@"thl -----  data = %@ \n -------- topic:%@ --------- \n",data,topic);
    
    if (self.delegate && [self.delegate respondsToSelector:@selector(MQTTClientModel_newMessage:data:onTopic:qos:retained:mid:)]) {
        [self.delegate MQTTClientModel_newMessage:session data:data onTopic:topic qos:qos retained:retained mid:mid];
    }
    
}

主動斷開

- (void)disconnect {
    
    [self.mySession removeObserver:self forKeyPath:@"status"];
    
    self.isDiscontent = YES;
    [self.mySession disconnect];
    
}