長連接通道SDK
長連接通道SDK,提供IoT業(yè)務(wù)協(xié)議封裝的云端數(shù)據(jù)下行能力,為App提供訂閱、發(fā)布消息的能力和支持請求響應(yīng)模型。
依賴SDK | 概述 |
日志 | 基礎(chǔ)依賴SDK,提供客戶端統(tǒng)一日志打印,日志等級控制,分模塊日志隔離等能力。 |
API 通道 | 提供API通道能力,和基礎(chǔ)環(huán)境配置信息。 |
初始化
初始化的操作請參見SDK初始化。
使用說明
SDK封裝了上行RPC請求、訂閱、取消訂閱等接口,詳細(xì)接口參見長連接服務(wù)。
SDK中描述的Topic都是簡短的Topic。例如完整的上行請求Topic:/sys/{productKey}/{deviceName}/app/up/test/publish。
上行請求SDK內(nèi)部會判斷補(bǔ)齊/sys/{productKey}/{deviceName}/app/up/,在調(diào)用SDK入?yún)⒌臅r候只需要輸入/test/publish即可。
對應(yīng)的下行Topic,例如完整的設(shè)備狀態(tài)變化下行Topic是/sys/{productKey}/{deviceName}/app/down/things/status。SDK回調(diào)里面只會露出/things/status,自動截斷掉/sys/{productKey}/{deviceName}/app/down前綴。
業(yè)務(wù)請求響應(yīng)模型
這個接口實際上是封裝了一個Remote Procedure Call的過程。我以用戶賬號綁定通道的示例來說明內(nèi)部邏輯:用戶賬號綁定通道的Topic為:/sys/{productKey}/{deviceName}/app/up/account/bind。
在向這個Topic發(fā)布數(shù)據(jù)前,先訂閱這個Topic對應(yīng)的Reply Topic,其格式如下所示 /sys/{productKey}/{deviceName}/app/down/account/bind_reply。訂閱成功后才開始發(fā)布數(shù)據(jù),IoT用戶中心在收到SDK 發(fā)布到/sys/{productKey}/{deviceName}/app/up/account/bind這個Topic的數(shù)據(jù)后,完成賬號綁定的業(yè)務(wù)邏輯后,會往/sys/{productKey}/{deviceName}/app/down/account/bind_reply這個Topic發(fā)布響應(yīng)數(shù)據(jù)。SDK在收到這個reply Topic的數(shù)據(jù)后,將響應(yīng)結(jié)果通過respHandler回調(diào)給用戶,從而完成整個業(yè)務(wù)邏輯。
#import <AlinkAppExpress/LKAppExpress.h>
//由于長連接通道 SDK,會在內(nèi)部邏輯中補(bǔ)齊 '/sys/{productKey}/{deviceName}/app/up' 部分,
//所以使用者在這個 API 時,只要傳這一段的后邊部分即 '/account/bind' 即可了。
[[LKAppExpress sharedInstance] invokeWithTopic : @"/account/bind" opts:nil params:@{@"iotToken":iotToken}
respHandler:^(LKAppExpResponse * _Nonnull response) {
LKAELogDebug(@"bindAccount result : %@", response);
}];
訂閱Topic
長連接通道SDK,采用MQTT協(xié)議,基于訂閱/發(fā)布模型設(shè)計。訂閱某個Topic后,當(dāng)其他服務(wù)或者終端往這個Topic發(fā)布消息時,便能收到消息。下邊以訂閱用戶所綁定設(shè)備屬性變化的Topic為例。
Topic全路徑為:/sys/{productKey}/{deviceName}/app/down/thing/properties。由于長連接通道 SDK,會在內(nèi)部邏輯中補(bǔ)齊/sys/{productKey}/{deviceName}/app/down部分,所以使用者在調(diào)用訂閱Topic API 時,只要整個Topic 的后邊部分即/thing/properties即可。其他Topic依次類推。
#import <AlinkAppExpress/LKAppExpress.h>
//以訂閱用戶所綁定的設(shè)備屬性變化事件為例,詳細(xì)的使用說明請參考 api reference
[[LKAppExpress sharedInstance]subscribe:@"/thing/properties" complete:^(NSError * _Nullable error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error == nil) {
[_tipsLabel setText:@"訂閱成功"];
} else {
[_tipsLabel setText:@"訂閱失敗"];
}
});
}];
取消訂閱Topic
取消訂閱是訂閱的逆過程,二者遵循同樣的Topic規(guī)則。仍然以取消訂閱用戶所綁定設(shè)備屬性變化的Topic為例。
#import <AlinkAppExpress/LKAppExpress.h>
// 詳細(xì)的使用說明請參考 api reference
[[LKAppExpress sharedInstance]unsubscribe:@"/thing/properties" complete:^(NSError * _Nullable error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error == nil) {
[_tipsLabel setText:@"取消訂閱成功"];
} else {
[_tipsLabel setText:@"取消訂閱失敗"];
}
});
}];
Publish數(shù)據(jù)
長連接通道SDK基于訂閱/發(fā)布模型設(shè)計。既可以訂閱Topic,也可以往某個Topic發(fā)布數(shù)據(jù)。下邊以往Topic:/sys/{productKey}/{deviceName}/app/up/test/publish發(fā)送數(shù)據(jù)為例。
由于長連接通道SDK,會在內(nèi)部邏輯中補(bǔ)齊/sys/{productKey}/{deviceName}/app/up部分,所以使用者在調(diào)用Publish數(shù)據(jù)API時,只要傳這一段的后邊部分即/test/publish即可。
#import <AlinkAppExpress/LKAppExpress.h>
NSString * text = @"{\"input\":\"Hello World\"}";
NSData *data = [text dataUsingEncoding:NSUTF8StringEncoding];
if (data == nil) {
return;
}
NSError *error;
NSDictionary *params = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
if (error) {
return;
}
[[LKAppExpress sharedInstance]publish:@"/test/publish" params:params
complete:^(NSError * _Nonnull error) {
dispatch_async(dispatch_get_main_queue(), ^{
if (error == nil) {
[_tipsLabel setText:@"publish成功"];
} else {
[_tipsLabel setText:@"publish失敗"];
}
});
}];
注冊下行Listener
注冊下行Listener,才能接收到訂閱過的Topic數(shù)據(jù),參見長鏈接服務(wù)消息下行API。
#import <AlinkAppExpress/LKAppExpress.h>
@interface TestDownstreamListener : NSObject <LKAppExpDownListener>
@end
@implementation TestDownstreamListener
- (void)onDownstream:(NSString * _Nonnull)topic data:(id _Nullable)data {
NSLog(@"onDownstream topic : %@", topic);
NSLog(@"onDownstream data : %@", data);
NSDictionary * replyDict = nil;
if ([data isKindOfClass:[NSString class]]) {
NSData * replyData = [data dataUsingEncoding:NSUTF8StringEncoding];
replyDict = [NSJSONSerialization JSONObjectWithData:replyData options:NSJSONReadingMutableLeaves error:nil];
} else if ([data isKindOfClass:[NSDictionary class]]) {
replyDict = data;
}
if (replyDict == nil) {
return;
}
}
- (BOOL)shouldHandle:(NSString * _Nonnull)topic {
if ([topic isEqualToString:@"/thing/properties"]) {
return YES;//返回YES,說明對此topic感興趣,SDK會調(diào)用[listener onDownstream:data:]
}
return NO;
}
@end
self.testListner = [TestDownstreamListener new];//sdk不會strong持有此listener,開發(fā)者自己保證listener不被釋放.
[[LKAppExpress sharedInstance]addDownStreamListener:YES listener:self.testListner]
解綁長連接通道與賬號
在初始化時,已實現(xiàn)長連接通道與賬號的綁定,此時如果您需要解綁長連接通道與賬號,參照以下代碼執(zhí)行。
如需解綁長連接通道跟用戶賬號的綁定,請在賬號登出前操作,否則會導(dǎo)致解綁失敗。
#import <AlinkAppExpress/LKAppExpress.h>
#import <IMSAuthentication/IMSCredentialManager.h>
#pragma mark - 取消長連接通道關(guān)聯(lián)
NSString *topic = @"/account/unbind";
[[LKAppExpress sharedInstance] invokeWithTopic:topic opts:nil params:@{} respHandler:^(LKAppExpResponse * _Nonnull response) {
if (![response successed]) {
IMSLifeLogVerbose(@"解綁長連接推送失敗");
}
}];