180E7D112BD8FF11008558E8 /* libbz2.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 180E7D102BD8FF11008558E8 /* libbz2.tbd */; };
180E7D132BD8FF3A008558E8 /* libiconv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 180E7D122BD8FF3A008558E8 /* libiconv.tbd */; };
180E7D152BD8FF5C008558E8 /* liblzma.5.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 180E7D142BD8FF5C008558E8 /* liblzma.5.tbd */; };
+ 181CE5C12C6EED9900EF8D07 /* AiAliAuthManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 181CE5BF2C6EED9900EF8D07 /* AiAliAuthManager.h */; };
+ 181CE5C22C6EED9900EF8D07 /* AiAliAuthManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 181CE5C02C6EED9900EF8D07 /* AiAliAuthManager.m */; };
184A71022BDA4C050025A332 /* AFSecurityPolicy.h in Headers */ = {isa = PBXBuildFile; fileRef = 184A70F42BDA4C040025A332 /* AFSecurityPolicy.h */; };
184A71032BDA4C050025A332 /* AFNetworkReachabilityManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 184A70F52BDA4C040025A332 /* AFNetworkReachabilityManager.h */; };
184A71042BDA4C050025A332 /* AFURLSessionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 184A70F62BDA4C040025A332 /* AFURLSessionManager.h */; };
180E7D102BD8FF11008558E8 /* libbz2.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libbz2.tbd; path = usr/lib/libbz2.tbd; sourceTree = SDKROOT; };
180E7D122BD8FF3A008558E8 /* libiconv.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libiconv.tbd; path = usr/lib/libiconv.tbd; sourceTree = SDKROOT; };
180E7D142BD8FF5C008558E8 /* liblzma.5.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = liblzma.5.tbd; path = usr/lib/liblzma.5.tbd; sourceTree = SDKROOT; };
+ 181CE5BF2C6EED9900EF8D07 /* AiAliAuthManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AiAliAuthManager.h; sourceTree = "<group>"; };
+ 181CE5C02C6EED9900EF8D07 /* AiAliAuthManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AiAliAuthManager.m; sourceTree = "<group>"; };
184A70F42BDA4C040025A332 /* AFSecurityPolicy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFSecurityPolicy.h; sourceTree = "<group>"; };
184A70F52BDA4C040025A332 /* AFNetworkReachabilityManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFNetworkReachabilityManager.h; sourceTree = "<group>"; };
184A70F62BDA4C040025A332 /* AFURLSessionManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFURLSessionManager.h; sourceTree = "<group>"; };
180E7B4D2BD7BD81008558E8 /* AiFrameManager.m */,
180E7B472BD7BD7F008558E8 /* AiAuthManager.h */,
180E7B522BD7BD82008558E8 /* AiAuthManager.m */,
+ 181CE5BF2C6EED9900EF8D07 /* AiAliAuthManager.h */,
+ 181CE5C02C6EED9900EF8D07 /* AiAliAuthManager.m */,
184A711D2BDD11C70025A332 /* AiTrippleModel.h */,
184A711E2BDD11C70025A332 /* AiTrippleModel.m */,
184A71222BDE2DA60025A332 /* AiSecretModel.h */,
180E7BE62BD7BD84008558E8 /* AiAudioDecoder.h in Headers */,
180E7CCB2BD8FC4E008558E8 /* encryption_info.h in Headers */,
180E7C8F2BD8FC4E008558E8 /* blowfish.h in Headers */,
+ 181CE5C12C6EED9900EF8D07 /* AiAliAuthManager.h in Headers */,
180E7CF52BD8FC4F008558E8 /* jni.h in Headers */,
180E7CF62BD8FC4F008558E8 /* packet.h in Headers */,
180E7C882BD8FC4E008558E8 /* hwcontext.h in Headers */,
180E7BE72BD7BD84008558E8 /* AiAudioManager.m in Sources */,
189C15872C05726600676A80 /* AiConnectManager.m in Sources */,
180E7BDF2BD7BD84008558E8 /* AiMouseConfig.m in Sources */,
+ 181CE5C22C6EED9900EF8D07 /* AiAliAuthManager.m in Sources */,
184A710D2BDA4C050025A332 /* AFSecurityPolicy.m in Sources */,
180E7B552BD7BD83008558E8 /* AiAudioDecoder.m in Sources */,
18AD83262BFAE8B9009BDE3B /* AiDeviceInfoManager.m in Sources */,
--- /dev/null
+//
+// AiAliAuthManager.m
+// AiMouseSdk
+//
+// Created by incar on 2024/7/29.
+//
+
+#import "AiAliAuthManager.h"
+#import "AiMouseTools.h"
+#import "AFNetworking.h"
+
+
+const NSString *regionId = @"cn-shenzhen";
+const NSString *accessKeyId = @"LTAI5t8xTtovaeJCHJyA91ou";
+const NSString *accessKeySecret = @"Yqbfke4QOX16b0rFYrCiknLsN9EZRe";
+const NSString *productKey = @"k1kijocAl8M";
+const NSString *productSecret = @"dCQesgqCwnLqybDJ";
+const NSString *instanceId = @"iot-040adh4x";
+
+@interface AiAliAuthManager ()
+@property (nonatomic,strong)AiMouseDeviceInfo *deviceInfo;
+@property (nonatomic,strong)NSString *token;
+@end
+
+@implementation AiAliAuthManager
+
+///将设备密钥密钥写到硬件
+-(void)sendDeviceSecretCmd:(NSString *)deviceSecret{
+ [self.deviceInfo setValue:deviceSecret forKey:@"deviceSecret"];
+ if (self.setDeviceSecret) {
+ self.setDeviceSecret(deviceSecret, ^(BOOL isSuccess) {
+ [self loginRequest];
+ });
+ }
+}
+
+- (void)loginWith:(AiMouseDeviceInfo *)info{
+ self.deviceInfo = info;
+ if (![info valueForKey:@"productKey"] || ![info valueForKey:@"secretKey"] || !info.sn || !info.sn) {
+ [self showLog:@"获取设备信息错误,鉴权失败!"];
+ return;
+ }
+ if([[info valueForKey:@"deviceSecret"] isKindOfClass:[NSString class]] && ([(NSString *)[info valueForKey:@"deviceSecret"] length] > 2)){
+ //已注册过,直接登录
+ [self loginRequest];
+ }
+ else{
+ //未注册
+ [self registerReuest];
+ }
+}
+
+- (void)showLog:(NSString *)log {
+ if (self.outputLog) self.outputLog([NSString stringWithFormat:@"[auth]%@",log]);
+}
+
+#pragma mark - register
+- (NSString *)signText:(NSDictionary *)param{
+ NSMutableArray<NSString *> *keys = [NSMutableArray arrayWithArray:param.allKeys];
+ [keys sortUsingComparator:^NSComparisonResult(NSString *obj1, NSString *obj2) {
+ return [obj1 compare:obj2];
+ }];
+
+ NSMutableArray *items = [[NSMutableArray alloc] init];
+ for (NSString *key in keys) {
+ NSString *value = [NSString stringWithFormat:@"%@=%@",key,param[key]];
+ [items addObject:value];
+ }
+ NSString *text = [items componentsJoinedByString:@"&"];
+ NSString *text1 = [self utf8Code:text];
+ NSString *textToSign = [NSString stringWithFormat:@"GET&%@&%@",[self utf8Code:@"/"],text1];
+ return textToSign;
+}
+
+- (NSString *)utf8Code:(NSString *)text{
+ NSCharacterSet *allowedCharacters = [NSCharacterSet characterSetWithCharactersInString:@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~"];
+ NSString *encode = [text stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacters];
+ if (encode.length) {
+ return encode;
+ }
+ return text;
+}
+
+- (NSString *)getFullParams:(NSDictionary *)param{
+ NSMutableArray<NSString *> *keys = [NSMutableArray arrayWithArray:param.allKeys];
+ [keys sortUsingComparator:^NSComparisonResult(NSString *obj1, NSString *obj2) {
+ return [obj1 compare:obj2];
+ }];
+
+ NSMutableArray *items = [[NSMutableArray alloc] init];
+ for (NSString *key in keys) {
+ NSString *value = [NSString stringWithFormat:@"%@=%@",key,param[key]];
+ [items addObject:value];
+ }
+ NSString *text = [items componentsJoinedByString:@"&"];
+ return text;
+}
+
+- (void)registerReuest{
+// C0310000A58A 8228bd13d8ef4bed091a9f3d6c384b51
+// C0310000A58A 62c5bfb84f79e387036c29a2e0ceef80
+
+ NSMutableDictionary *params = [NSMutableDictionary dictionaryWithDictionary:@{
+ @"Action":@"RegisterDevice",
+ @"ProductKey":productKey,
+ @"IotInstanceId":instanceId,
+// @"DeviceName":@"C0310000A59C",
+ @"DeviceName": self.deviceInfo.mac,
+ }] ;
+ params[@"Format"] = @"JSON";
+ params[@"Version"] = @"2018-01-20";
+ params[@"AccessKeyId"] = accessKeyId;//阿里云颁发给用户的访问服务所用的密钥ID。登录阿里云控制台,将鼠标指针移至账号头像上,然后单击AccessKey管理,跳转至AccessKey页面,即可创建和查看AccessKey。
+ params[@"Timestamp"] = [AiMouseTools getCurrentTime];//例如,2016-01-04T12:00:00Z表示北京时间2016年01月04日20点0分0秒 @"2024-08-05T10:07:39Z"
+ params[@"SignatureVersion"] = @"1.0";//签名算法版本。目前版本是1.0。
+ params[@"SignatureNonce"] = [AiMouseTools randomString:14];//唯一随机数。用于防止网络重放攻击。用户在不同请求中要使用不同的随机数值。
+ params[@"RegionId"] = regionId;//设备所在地域(与控制台上的地域对应)的ID,如cn-shanghai。
+ params[@"SignatureMethod"] = @"HMAC-SHA1";//签名方式,目前支持HMAC-SHA1
+
+ NSString *sginText = [self signText:params];
+ sginText = [sginText stringByReplacingOccurrencesOfString:@"%3A" withString:@"%253A"];
+
+ NSString *key = [NSString stringWithFormat:@"%@&",accessKeySecret];
+ NSString *sign = [[AiMouseTools stringToHmacSha1:key text:sginText] lowercaseString];
+ NSString *base64 = [AiMouseTools dataWithHexString:sign].base64Encoding;
+// NSLog(@"key = %@",key);
+// NSLog(@"sginText = %@",sginText);
+// NSLog(@"sign = %@",sign);
+// NSLog(@"base64 = %@",base64);
+ params[@"Signature"] = base64;
+
+ NSString *url = @"https://iot.cn-shenzhen.aliyuncs.com";
+ [self showLog:[NSString stringWithFormat:@"%@ %@",url,params]];
+// [self showLog: [NSString stringWithFormat:@"%@?%@",url,[self getFullParams:params]]];
+
+ AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
+ manager.responseSerializer =[AFHTTPResponseSerializer serializer];
+ manager.requestSerializer = [AFJSONRequestSerializer serializer];
+ [manager GET:url parameters:params headers:@{} progress:^(NSProgress * _Nonnull downloadProgress) {
+
+ } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
+ NSString *str = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
+ [self showLog:[NSString stringWithFormat:@" %@",str]];
+ NSDictionary *dict = [AiMouseTools dataToDictionary:responseObject];
+ NSDictionary *data = dict[@"Data"];
+ if([data isKindOfClass:[NSDictionary class]] ){
+ NSString *deviceSecret = data[@"DeviceSecret"];
+ if ([deviceSecret isKindOfClass:[NSString class]] && deviceSecret.length > 0) {
+ [self sendDeviceSecretCmd:deviceSecret];
+ [self showLog:@"激活成功"];
+ }
+ else{
+ [self showLog:dict[@"ErrorMessage"]];
+ if(self.authCallBack)self.authCallBack(false);
+ }
+ }
+ else{
+ [self showLog:dict[@"ErrorMessage"]];
+ if(self.authCallBack)self.authCallBack(false);
+ }
+ } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
+ [self showLog:[NSString stringWithFormat:@"error = %@",error]];
+ if(self.authCallBack)self.authCallBack(false);
+ }];
+}
+
+#pragma mark - login
+- (void)loginRequest{
+// NSString *bid = [self.deviceInfo valueForKey:@"productKey"];//品牌ID,管理中心获取
+// NSString *deviceId = self.deviceInfo.mac;//设备ID
+// NSString *deviceSecret = [self.deviceInfo valueForKey:@"deviceSecret"];//注册返回的密码
+
+ NSMutableDictionary *params = [NSMutableDictionary dictionaryWithDictionary:@{
+ @"clientId": self.deviceInfo.mac,
+ @"productKey": productKey,
+ @"deviceName": self.deviceInfo.mac,
+ @"timestamp": [NSString stringWithFormat:@"%ld",(NSInteger)([[NSDate date] timeIntervalSince1970]*1000 - 8*60*60)],
+ }];
+
+
+ NSString *sginText = [self loginSignText:params];
+ NSString *deviceSecret = [self.deviceInfo valueForKey:@"deviceSecret"];//注册返回的密码
+
+ [self showLog:[NSString stringWithFormat:@"text = %@",sginText]];
+ [self showLog:[NSString stringWithFormat:@"deviceSecret = %@",deviceSecret]];
+ NSString *sign = [[AiMouseTools stringToHmacSha1:deviceSecret text:sginText] lowercaseString];
+ [self showLog:[NSString stringWithFormat:@"sign = %@",sign]];
+ params[@"sign"] = sign;
+ params[@"version"] = @"default";
+ params[@"signmethod"] = @"hmacsha1";
+
+ NSString *url = @"https://iot-040adh4x.http.iothub.aliyuncs.com/auth";
+ [self showLog:[NSString stringWithFormat:@"阿里登录%@ %@",url,params]];
+
+ AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
+ manager.responseSerializer =[AFHTTPResponseSerializer serializer];
+ manager.requestSerializer = [AFJSONRequestSerializer serializer];
+// AFSecurityPolicy *policy = [AFSecurityPolicy defaultPolicy];
+// policy.allowInvalidCertificates = YES;
+// policy.validatesDomainName = NO;
+// manager.securityPolicy = policy;
+
+ [manager POST:url parameters:params headers:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
+ NSString *str = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
+ [self showLog:[NSString stringWithFormat:@"%@",str]];
+ NSDictionary *dict = [AiMouseTools dataToDictionary:responseObject];
+ NSString *code = dict[@"code"];
+ NSString *token = [dict valueForKeyPath:@"info.token"];
+ if(code.integerValue == 0){
+ self.token = token;
+ [self showLog:@"=====ali登录成功 ====="];
+ if(self.authCallBack)self.authCallBack(true);
+ }
+// else if(code.integerValue == 50021 ){
+// //密码错误,重置过
+// [self registerReuest];
+// }
+ else{
+ if(self.authCallBack)self.authCallBack(false);
+ }
+ } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
+ [self showLog:[NSString stringWithFormat:@"error = %@",error]];
+ if(self.authCallBack)self.authCallBack(false);
+ }];
+}
+
+- (NSString *)loginSignText:(NSDictionary *)param{
+ NSMutableArray<NSString *> *keys = [NSMutableArray arrayWithArray:param.allKeys];
+ [keys sortUsingComparator:^NSComparisonResult(NSString *obj1, NSString *obj2) {
+ return [obj1 compare:obj2];
+ }];
+
+ NSMutableArray *items = [[NSMutableArray alloc] init];
+ for (NSString *key in keys) {
+ NSString *value = [NSString stringWithFormat:@"%@%@",key,param[key]];
+ [items addObject:value];
+ }
+ NSString *text = [items componentsJoinedByString:@""];
+ return text;
+}
+
+@end
#import "AiMouseSdk.h"
#import "AiDeviceInfoManager.h"
#import "AiAuthManager.h"
+#import "AiAliAuthManager.h"
#import "AiAudioManager.h"
#import "AiMouseTools.h"
#import "AiMouseTools2.h"
#import "AiRecordManager.h"
#import "AiConnectManager.h"
+#define kIsAliChannal true
+
@interface AiMouseDeviceInfo()
@property (nonatomic, strong) NSString *productKey;/// 品牌key
@property (nonatomic, strong) NSString *secretKey;/// 品牌Secret
@interface AiMouse()<AiConnectManagerDelegate>
@property (nonatomic, assign) AiMouseLogLevel logLevel;
@property (nonatomic, strong) AiAuthManager *authManager;
+@property (nonatomic, strong) AiAliAuthManager *aliAuthManager;
@property (nonatomic, strong) AiAudioManager *audioManager;
@property (nonatomic, strong) AiRecordManager *recordManager;
@property (nonatomic, strong) void (^authBlock)(AiMouseAuthState state);
}
-(NSString *)version{
- return @"1.0.31";
+ return @"1.0.32";
}
-(AiDeviceInfoManager *)deviceInfoManager{
}
return _authManager;
}
+
+-(AiAliAuthManager *)aliAuthManager{
+ if (!_aliAuthManager) {
+ _aliAuthManager = [[AiAliAuthManager alloc] init];
+ __weak typeof(self) ws = self;
+ _aliAuthManager.outputLog = ^(NSString * _Nonnull log) {
+ [ws showLog:log];
+ };
+ _aliAuthManager.setDeviceSecret = ^(NSString * _Nonnull value, AiAliCmdFinishBlock _Nonnull finished) {
+ [ws setDeviceSecret:value completation:finished];
+ };
+ _aliAuthManager.authCallBack = ^(BOOL isSuccess) {
+ [ws authResult:isSuccess];
+// [ws setDeviceSecret:@"" completation:nil];
+ };
+ }
+ return _aliAuthManager;
+}
+
-(AiAudioManager *)audioManager{
if (!_audioManager) {
_audioManager = [[AiAudioManager alloc] init];
ws.authBlock(AiMouseAuthState_Failure);
}
else{
- [ws.authManager loginWith:deviceInfo];
+ if(kIsAliChannal){
+ [ws.aliAuthManager loginWith:deviceInfo];
+ }
+ else{
+ [ws.authManager loginWith:deviceInfo];
+ }
}
}];
}
return digest;
}
+
++ (NSData *)dataWithHexString:(NSString *)hexStr {
+ hexStr = [hexStr stringByReplacingOccurrencesOfString:@" " withString:@""];
+ hexStr = [hexStr lowercaseString];
+ NSUInteger len = hexStr.length;
+ if (!len) return nil;
+ unichar *buf = malloc(sizeof(unichar) * len);
+ if (!buf) return nil;
+ [hexStr getCharacters:buf range:NSMakeRange(0, len)];
+
+ NSMutableData *result = [NSMutableData data];
+ unsigned char bytes;
+ char str[3] = { '\0', '\0', '\0' };
+ int i;
+ for (i = 0; i < len / 2; i++) {
+ str[0] = buf[i * 2];
+ str[1] = buf[i * 2 + 1];
+ bytes = strtol(str, NULL, 16);
+ [result appendBytes:&bytes length:1];
+ }
+ free(buf);
+ return result;
+}
+
++(NSString *)randomString:(NSInteger)length {
+ char letters[52] = "1234567891234567891234567891234567891234567891234567";
+// char letters[10] = "012345678901234567890123456789012345678901234567890123456789";
+ char *output = malloc(sizeof(char) * (length + 1));
+ for (int i = 0; i < length; i++) {
+ int index = arc4random_uniform(52);
+ output[i] = letters[index];
+ }
+ output[length] = '\0';
+
+ return [[NSString alloc] initWithBytesNoCopy:output length:length encoding:NSUTF8StringEncoding freeWhenDone:YES];
+}
+
++(NSString *)getCurrentTime{
+// @"2024-08-05T10:07:39Z"
+ NSDate *date = [NSDate date];
+// NSLog(@"当前零时区时间 %@", date);
+
+ NSDateFormatter *dateFormaterA = [[NSDateFormatter alloc]init];
+ [dateFormaterA setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT"]]; // 设置时区为格林尼治标准时区
+ [dateFormaterA setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
+ NSString *dateStrA = [dateFormaterA stringFromDate:date];
+ NSString *text1 = [[dateStrA componentsSeparatedByString:@" "] componentsJoinedByString:@"T"];
+ NSString *text2 = [text1 stringByAppendingString:@"Z"];
+// NSLog(@"%@",text2);
+
+
+ // 如果你需要将这个UTC时间显示为格林尼治时间,你可以这样做:
+// NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
+// [dateFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"GMT"]]; // 设置时区为格林尼治标准时区
+// NSString *gmTimeString = [dateFormatter stringFromDate:date]; // 将UTC日期转换为字符串表示形式,时区设置为GMT
+// NSLog(@"%@ == ",gmTimeString);
+
+ return text2;
+}
@end