最近公司实现实时传输数据,使用的是MQTT实现的,接下来描述一下内容,当作是笔记了
一. MQTT
一个物联网项目中用到了MQTT协议, 可以用来做设备与软件之间的互通.
MQTT: 即时通讯协议, 传输层协议
二. 常用:
1.MQTTKit(已经不维护了)
2.MQTTClient
a.设置地址端口, 账号密码等基本信息
b.订阅主题(可以订阅多个主题)
c.实现代理回调方法(处理数据)
三. 三种消息传输方式:(看情况使用)
a.至多一次 (会发生消息丢失或重复)
b.至少一次 (确保消息到达, 会发生消息重复)
c.只有一次 (确保消息到达一次)
四、引入库
pod 'MQTTClient'
pod 'MQTTClient/Min'
pod 'MQTTClient/Manager'
pod 'MQTTClient/Websocket'
这里采用的是MQTTClient开源库开发。如果后台的MQTT服务用的ws,则还需要导入pod 'MQTTClient/Websocket',此处根据自身需要pod即可。
五、 代码:
#import <MQTTClient/MQTTClient.h>
#import <MQTTClient/MQTTSessionManager.h>
配置基本信息
- (void)setParameterWithManager
{
/**
host: 服务器地址
port: 服务器端口
tls: 是否使用tls协议,mosca是支持tls的,如果使用了要设置成true
keepalive: 心跳时间,单位秒,每隔固定时间发送心跳包, 心跳间隔不得大于120s
clean: session是否清除,这个需要注意,如果是false,代表保持登录,如果客户端离线了再次登录就可以接收到离线消息
auth: 是否使用登录验证
user: 用户名
pass: 密码
willTopic: 订阅主题
willMsg: 自定义的离线消息
willQos: 接收离线消息的级别
clientId: 客户端id,需要特别指出的是这个id需要全局唯一,因为服务端是根据这个来区分不同的客户端的,默认情况下一个id登录后,假如有另外的连接以这个id登录,上一个连接会被踢下线, 我使用的设备UUID
*/
NSString *clientId = [UIDevice currentDevice].identifierForVendor.UUIDString;
self.sessionManager = [[MQTTSessionManager alloc] init];
[self.sessionManager connectTo:MQTTHOST
port:MQTTPORT
tls:false
keepalive:60 //心跳间隔不得大于120s
clean:true
auth:true
user:MQTTUSERNAME
pass:MQTTPASSWORD
will:false
willTopic:nil
willMsg:nil
willQos:0
willRetainFlag:false
withClientId:clientId];
self.sessionManager.delegate = self;
// 添加监听状态观察者
[self.sessionManager addObserver:self
forKeyPath:@"state"
options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
context:nil];
// 订阅主题 NSDictionary类型,Object 为 QoS,key 为 Topic
self.sessionManager.subscriptions = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:MQTTQosLevelExactlyOnce] forKey:@"你要订阅的主题(和后台商量好)"];
}
监听连接状态
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
switch (self.sessionManager.state) {
case MQTTSessionManagerStateClosed:
NSLog(@"连接已经关闭");
break;
case MQTTSessionManagerStateClosing:
NSLog(@"连接正在关闭");
break;
case MQTTSessionManagerStateConnected:
NSLog(@"已经连接");
break;
case MQTTSessionManagerStateConnecting:
NSLog(@"正在连接中");
break;
case MQTTSessionManagerStateError: {
NSString *errorCode = self.sessionManager.lastErrorCode.localizedDescription;
NSLog(@"连接异常 ----- %@",errorCode);
}
break;
case MQTTSessionManagerStateStarting:
NSLog(@"开始连接");
break;
default:
break;
}
}
处理数据
// 实现MQTTSessionManagerDelegate代理方法,处理数据。
- (void)handleMessage:(NSData *)data onTopic:(NSString *)topic retained:(BOOL)retained
{
NSLog(@"主题:%@",topic);
NSString *dataString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSData * newData = [dataString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:newData options:NSJSONReadingMutableLeaves error:nil];
NSLog(@"数据:%@",jsonDict);
}
最后不要忘记移除观察者, 否则程序会崩溃
[self.sessionManager removeObserver:self forKeyPath:@"state"];
网友评论