快速使用MQTT iOS版 SDK实现消息收发

本文介绍快速使用 MQTT iOS版SDK 实现MQTT客户端消息的自收自发。

1.1 部署iOS开发环境

  • 下载安装xcode
  • 下载安装cocoapods,本文以cocoapods为例。

1.2 导入项目依赖

在项目的podfile文件中设置如下:

source 'https://github.com/CocoaPods/Specs.git'
    platform :ios, '10.0'
    pod 'MQTTClient'
    pod 'AFNetworking'
    pod 'MBProgressHUD'
    pod 'Masonry'
    pod 'MJRefresh'
    pod 'YYModel'
    
    target 'MQTTChat' do
    end

2.1 获取初始化信息

登录console后台
1.点击菜单栏【MQTT】→【服务概览】→【服务配置】,获取「连接地址」、「连接端口」、「AppID」以「及REST API地址」等信息。
注:clientID由两部分组成,组织形式为“deviceID@AppID”,deviceID由用户自定义,AppID见【服务配置】。
示例:正确的clientID格式为:“device001@aitbj0”;
2.点击菜单栏【应用概览】→【应用详情】→【开发者ID】,获取「Client ID」与「ClientSecret」信息。
3.初始化代码

self.rootTopic = @"t1";
    
    // appID 通过console后台[MQTT]->[服务概览]->[服务配置]下[AppID]获取
    self.appId = @"ff6sc0";
    
    //环信MQTT服务器地址 通过console后台[MQTT]->[服务概览]->[服务配置]下[连接地址]获取
    self.host = @"ff6sc0.cn1.mqtt.chat";
    
    //环信MQTT REST API地址 通过console后台[MQTT]->[服务概览]->[服务配置]下[REST API地址]获取
    self.restapi = @"https://api.cn1.mqtt.chat/app/ff6sc0";
    
    //开发者ID 通过console后台[应用概览]->[应用详情]->[开发者ID]下[ Client ID]获取
    self.appClientId = @"YXA67-uKaalmThCOut6Q8uPLSg";
    
    // 开发者密钥 通过console后台[应用概览]->[应用详情]->[开发者ID]下[ ClientSecret]获取
    self.appClientSecret = @"YXA63CFpMQFai4MdTDdGN92BBoG6_6g";
    
    // 协议服务端口 通过console后台[MQTT]->[服务概览]->[服务配置]下[连接端口]获取
    self.port = 1883;
    self.qos = 0;
    self.tls = 0;
    
    // 自定义deviceID
    self.deviceId = [UIDevice currentDevice].identifierForVendor.UUIDString;
    
    //开发者ID 通过console后台[应用概览]->[应用详情]->[开发者ID]下[ Client ID]获取
    self.clientId = [NSString stringWithFormat:@"%@@%@",self.deviceId,self.appId];

2.2 获取token

//获取应用token
- (void)getAppTokenWithAppClientId:(NSString *)appClientId
                   appClientSecret:(NSString *)appClientSecret
                        completion:(void (^)(NSString *appToken,NSInteger expires))response {
    
       //环信MQTT REST API地址 通过console后台[MQTT]->[服务概览]->[服务配置]下[REST API地址]获取
       NSString *urlString = [NSString stringWithFormat:@"%@/openapi/rm/app/token",self.restapi];
    
       //初始化一个AFHTTPSessionManager
       AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
       //设置请求体数据为json类型
       manager.requestSerializer = [AFJSONRequestSerializer serializer];
       //设置响应体数据为json类型
       manager.responseSerializer = [AFJSONResponseSerializer serializer];
       //请求体,参数(NSDictionary 类型)
   
       NSDictionary *parameters = @{@"appClientId":appClientId,
                                    @"appClientSecret":appClientSecret
                                    };

    __block NSString *token  = @"";
    [manager POST:urlString
       parameters:parameters
          headers:@{}
         progress:nil
          success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            NSError *error = nil;
            NSData *jsonData = [NSJSONSerialization dataWithJSONObject:responseObject options:NSJSONWritingPrettyPrinted error:&error];
            NSDictionary *jsonDic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error];
            NSLog(@"%s jsonDic:%@",__func__,jsonDic);
            NSDictionary *body = jsonDic[@"body"];
            token = body[@"access_token"];
            NSInteger expire_in = [body[@"expires_in"] integerValue];
            response(token,expire_in);
        }
          failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            NSLog(@"%s error:%@",__func__,error.debugDescription);
            response(token,0);
        }];
}


//获取用户token
- (void)getUserTokenWithUsername:(NSString *)username
                        appToken:(NSString *)appToken
                        clientId:(NSString *)clientId
                         expires:(NSInteger)expires
                      completion:(void (^)(NSString *userToken))response {
    
       //环信MQTT REST API地址 通过console后台[MQTT]->[服务概览]->[服务配置]下[REST API地址]获取
       NSString *urlString = [NSString stringWithFormat:@"%@/openapi/rm/user/token",self.restapi];
    
       //初始化一个AFHTTPSessionManager
       AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
       //设置请求体数据为json类型
       manager.requestSerializer = [AFJSONRequestSerializer serializer];
       //设置响应体数据为json类型
       manager.responseSerializer = [AFJSONResponseSerializer serializer];
       //请求体,参数(NSDictionary 类型)
   
    
    NSDictionary *parameters = @{
                                 @"username":username,
                                 @"expires_in":@(expires),//过期时间,单位为秒,默认为3天,如需调整,可提工单调整
                                 @"cid":clientId
                                    };
    NSLog(@"%s\n urlString:%@\n parameters:%@\n",__func__,urlString,parameters);

    __block NSString *token  = @"";
    
    [manager POST:urlString
       parameters:parameters
          headers:@{@"Authorization":appToken}
         progress:nil
          success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            NSError *error = nil;
            NSData *jsonData = [NSJSONSerialization dataWithJSONObject:responseObject options:NSJSONWritingPrettyPrinted error:&error];
            NSDictionary *jsonDic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error];
            NSLog(@"%s jsonDic:%@",__func__,jsonDic);
            NSDictionary *body = jsonDic[@"body"];
            token = body[@"access_token"];

            response(token);
        }
          failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            NSLog(@"%s error:%@",__func__,error.debugDescription);
            response(token);
        }];
}

2.3 连接服务器

配置连接密码、cleansession标志、心跳间隔、超时时间等信息,调用connect()函数连接至环信MQTT消息云。

// 从console管理平台获取连接地址
			[self.manager connectTo:self.host
			                   port:self.port
			                    tls:self.tls
			              keepalive:45
			                  clean:true
			                   auth:true
			                   user:userName
			                   pass:userToken
			                   will:false
			              willTopic:nil
			                willMsg:nil
			                willQos:MQTTQosLevelAtMostOnce
			         willRetainFlag:false
			           withClientId:self.clientId
			         securityPolicy:nil
			           certificates:nil
			          protocolLevel:MQTTProtocolVersion50
			         connectHandler:^(NSError *error) {
			}];             

2.4 订阅(subscribe)

2.4.1 订阅主题&取消订阅主题

当客户端成功连接环信MQTT消息云后,通过设置subscriptions参数值实现订阅主题与取消订阅主题 。当subscriptions非空时,订阅主题;当subscriptions为空时,取消订阅主题;

/**
   订阅主题
   格式为 xxx/xxx/xxx 可以为多级话题 @{@"xxx/xxx/xxx...":@(1)}
   qos定义{ 0: 最多一次,1:至少一次 2:仅一次}
  */
   self.manager.subscriptions = @{[NSString stringWithFormat:@"%@/IOS", self.rootTopic]:@(self.qos),[NSString stringWithFormat:@"%@/IOS_TestToic", self.rootTopic]:@(1)};
   
   /**
    取消订阅主题
   */
   self.manager.subscriptions = @{};

2.4.2 接收消息

接收从服务器接受订阅消息。

/*
     * MQTTSessionManagerDelegate
    */
   - (void)handleMessage:(NSData *)data onTopic:(NSString *)topic retained:(BOOL)retained {
     /*
      * MQTTClient: process received message
      */
    
    NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    [self.receiveMsgs insertObject:[NSString stringWithFormat:@"RecvMsg from Topic: %@ Body: %@", topic, dataString] atIndex:0];
    [self.tableView reloadData];
    
  }
  

2.5 发布消息(publish)

向指定topic发送消息

- (void)send {
    /*
     * MQTTClient: send data to broker
     */
    
    [self.manager sendData:[self.messageTextField.text dataUsingEncoding:NSUTF8StringEncoding]
                     topic:[NSString stringWithFormat:@"%@/%@",
                            self.rootTopic,
                            @"IOS"]//此处设置多级子topic
                       qos:self.qos
                    retain:FALSE];
  }

2.6 断开连接

MQTT client发送断开连接请求。

/*
     * 断开连接
    */
   - (void)disConnect {
      [self.manager disconnectWithDisconnectHandler:^(NSError *error) {
       }];
      self.manager.subscriptions = @{};
   }
   

2.7 重新连接

MQTT client发送重新连接请求。

/*
   * 重新连接
  */
  - (void)connect {
    [self.manager connectToLast:^(NSError *error) {
            
    }];
  }
  • 完整demo示例,请参见demo下载
  • 目前MQTT客户端支持多种语言,请参见 SDK下载
  • 如果您在使用MQTT服务中,有任何疑问和建议,欢迎您联系我们