You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
459 lines
14 KiB
459 lines
14 KiB
// |
|
// BluetoothTool.m |
|
// BluetoothDemo |
|
// |
|
// Created by mac on 17/3/16. |
|
// Copyright © 2017年 . All rights reserved. |
|
// |
|
|
|
#import "BluetoothToolFireBoltt.h" |
|
#import <AddressBookUI/AddressBookUI.h> //通讯录库 |
|
#import "BLETools.h" |
|
#import "BLEConstFireBoltt.h" |
|
#import "BluetoothFireBoltt.h" |
|
#import "FireBoltt-Swift.h" |
|
|
|
@implementation BluetoothToolFireBoltt |
|
|
|
|
|
/** |
|
CRC校验数据是否正确 |
|
*/ |
|
+ (BOOL)checkCRCWithData:(NSMutableData *)data { |
|
// 取出CRC |
|
// int crc = [BluetoothTool intFromHexSrting:[NSString stringWithFormat:@"%02x%02x",((Byte*)([data bytes]))[4],((Byte*)([data bytes]))[5]]]; |
|
Byte *bytes = (Byte *)[data bytes]; |
|
// 利用位移管道运算转整数 modify by fangtao 2018.12.01 |
|
int crc = (bytes[4] & 0xff) << 8 | (bytes[5] & 0xff); |
|
// L2层数据 |
|
NSData *contentData = [data subdataWithRange:NSMakeRange(8, data.length - 8)]; |
|
// 重新根据contentData计算CRC |
|
int dataCrc = 0xff; |
|
int contentLength = (int)contentData.length; |
|
Byte *contentBytes = (Byte *)[contentData bytes]; |
|
for (int i = 0; i <contentLength ; i++) { |
|
dataCrc^= contentBytes[i] & 0xFF; |
|
// NSLog(@"dataCrc == ++ %d",dataCrc); |
|
for (int j = 0; j < 8; j++) { |
|
if((dataCrc & 1) !=0){ |
|
dataCrc >>=1; |
|
dataCrc^=0xB8; |
|
}else{ |
|
dataCrc>>=1; |
|
} |
|
} |
|
} |
|
// 如果相等则正确 |
|
if (crc == dataCrc) { |
|
return YES; |
|
} |
|
return NO; |
|
} |
|
|
|
/** |
|
* 16进制字符串转10进制数字 |
|
* |
|
* @param hexString 16进制字符串 |
|
* |
|
* @return 十进制数据 |
|
*/ |
|
+ (int)intFromHexSrting:(NSString *)hexString { |
|
|
|
NSLog(@"%@",hexString); |
|
if (!hexString) { |
|
return 0; |
|
} |
|
#warning 陈廷峰此处有几率闪退,出现请告知 |
|
NSString * temp10 = [NSString stringWithFormat:@"%lu",strtoul([hexString UTF8String],0,16)]; |
|
return [temp10 intValue]; |
|
} |
|
|
|
/** |
|
10进制转16进制字符串 |
|
|
|
@param hexNumber 10进制 |
|
|
|
@return 十六进制字符串 |
|
*/ |
|
+ (NSString *)stringWithHexNumber:(int)hexNumber { |
|
// 固件升级情况下处理一个字节超过255的情况 |
|
if (hexNumber > 255) { |
|
hexNumber = 0; |
|
} |
|
char hexChar[6]; |
|
sprintf(hexChar, "%02x", (int)hexNumber); |
|
|
|
NSString *hexString = [NSString stringWithCString:hexChar encoding:NSUTF8StringEncoding]; |
|
|
|
return hexString; |
|
} |
|
|
|
/** |
|
获取系统当前时区时间数据 |
|
*/ |
|
+ (NSData *)getCurrenTime { |
|
|
|
// 手环设置时间最后拼接一个12/24小时制,hasAMPM NO:24小时 YES:12小时 |
|
NSString *formatStringForHours = [NSDateFormatter dateFormatFromTemplate:@"j" options:0 locale:[NSLocale currentLocale]]; |
|
NSRange containsA = [formatStringForHours rangeOfString:@"a"]; |
|
BOOL hasAMPM = containsA.location != NSNotFound; |
|
NSMutableData *data = [NSMutableData dataWithData:[BluetoothToolFireBoltt getTimeDataWithTime:@[[NSString stringWithFormat:@"%ld", (long)[[NSDate date] timeIntervalSince1970]]] cmdType:BleCMD_setIngTime]]; |
|
[data appendBytes:&(hasAMPM) length:1]; |
|
NSData *zooeData = [[NSString stringWithFormat:@"%@",[NSTimeZone systemTimeZone]] dataUsingEncoding:NSUTF8StringEncoding]; |
|
[data appendData:zooeData]; |
|
|
|
// NSMutableData *TotalTimeData = [[NSMutableData alloc] init]; |
|
// |
|
// NSData *timeData = [[NSString stringWithFormat:@"%ld", (long)[[NSDate date] timeIntervalSince1970]] dataUsingEncoding:NSUTF8StringEncoding]; |
|
// NSData *zooeData = [[NSString stringWithFormat:@"%@",[NSTimeZone systemTimeZone]] dataUsingEncoding:NSUTF8StringEncoding]; |
|
// // 分隔符 |
|
// NSData *charData = [@"|" dataUsingEncoding:NSUTF8StringEncoding]; |
|
// [TotalTimeData appendData:zooeData]; |
|
// [TotalTimeData appendData:charData]; |
|
// [TotalTimeData appendData:timeData]; |
|
|
|
return data; |
|
} |
|
|
|
|
|
/** |
|
获取当前手机中的通讯录(字节流) |
|
|
|
@return 20个联系人为一个数据,用数组将所有返回 |
|
*/ |
|
+ (NSMutableArray *)getCurrenContactPeploe { |
|
|
|
// 10个联系人为一组 |
|
NSInteger contactCount = 10; |
|
|
|
// 联系人数据数组 |
|
NSMutableArray *contactPeplpeArr = [[NSMutableArray alloc] init]; |
|
|
|
// 获取手机中所有通讯录(姓名|电话) |
|
NSMutableArray *contactPeplpe = [self contactPeploe]; |
|
|
|
// 10个联系人为一个完整数据包 |
|
NSInteger count = contactPeplpe.count / contactCount; |
|
|
|
for (int i = 0; i <= count; i++) { |
|
|
|
NSString *contactStr = [[NSString alloc] init]; |
|
NSData *data = [[NSData alloc] init]; |
|
|
|
if (i < count) { |
|
|
|
// 将10个联系人拼接成字符串 |
|
contactStr = [[contactPeplpe subarrayWithRange:NSMakeRange(i * contactCount, contactCount)] componentsJoinedByString:@"^"]; |
|
data = [contactStr dataUsingEncoding:NSUTF8StringEncoding]; |
|
|
|
}else if (contactPeplpe.count % contactCount) { |
|
|
|
// 最后不足10个联系人的数据 |
|
contactStr = [[contactPeplpe subarrayWithRange:NSMakeRange(i * contactCount, contactPeplpe.count % contactCount)] componentsJoinedByString:@"^"]; |
|
data = [contactStr dataUsingEncoding:NSUTF8StringEncoding]; |
|
} |
|
|
|
if (data.length) { |
|
[contactPeplpeArr addObject:data]; |
|
} |
|
} |
|
|
|
return contactPeplpeArr; |
|
} |
|
|
|
|
|
|
|
/** |
|
获取当前手机中的通讯录 |
|
|
|
@return 所有联系人数据 |
|
*/ |
|
+ (NSMutableArray *)contactPeploe |
|
{ |
|
|
|
// 通讯录数组 |
|
NSMutableArray *contactArr = [NSMutableArray new]; |
|
|
|
//新建一个通讯录类 |
|
ABAddressBookRef addressBooks = nil; |
|
|
|
if ([[UIDevice currentDevice].systemVersion floatValue] >= 6.0) |
|
{ |
|
addressBooks = ABAddressBookCreateWithOptions(NULL, NULL); |
|
|
|
//获取通讯录权限 |
|
|
|
dispatch_semaphore_t sema = dispatch_semaphore_create(0); |
|
|
|
ABAddressBookRequestAccessWithCompletion(addressBooks, ^(bool granted, CFErrorRef error){dispatch_semaphore_signal(sema);}); |
|
|
|
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); |
|
|
|
}else{ |
|
|
|
addressBooks = ABAddressBookCreate(); |
|
} |
|
|
|
//获取通讯录中的所有人 |
|
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBooks); |
|
//通讯录中人数 |
|
CFIndex nPeople = ABAddressBookGetPersonCount(addressBooks); |
|
|
|
//循环,获取每个人的个人信息 |
|
for (NSInteger i = 0; i < nPeople; i++) |
|
{ |
|
// 通讯录字符串--- 姓名|电话 |
|
NSString *contactStr = [NSString new]; |
|
|
|
//获取个人 |
|
ABRecordRef person = CFArrayGetValueAtIndex(allPeople, i); |
|
//获取个人名字 |
|
CFTypeRef abName = ABRecordCopyValue(person, kABPersonFirstNameProperty); |
|
CFTypeRef abLastName = ABRecordCopyValue(person, kABPersonLastNameProperty); |
|
CFStringRef abFullName = ABRecordCopyCompositeName(person); |
|
NSString *nameString = (__bridge NSString *)abName; |
|
NSString *lastNameString = (__bridge NSString *)abLastName; |
|
|
|
if ((__bridge id)abFullName != nil) { |
|
nameString = (__bridge NSString *)abFullName; |
|
} else { |
|
if ((__bridge id)abLastName != nil) |
|
{ |
|
nameString = [NSString stringWithFormat:@"%@ %@", nameString, lastNameString]; |
|
} |
|
} |
|
|
|
ABPropertyID multiProperties[] = { |
|
kABPersonPhoneProperty, |
|
kABPersonEmailProperty |
|
}; |
|
NSInteger multiPropertiesTotal = sizeof(multiProperties) / sizeof(ABPropertyID); |
|
for (NSInteger j = 0; j < multiPropertiesTotal; j++) { |
|
|
|
ABPropertyID property = multiProperties[j]; |
|
ABMultiValueRef valuesRef = ABRecordCopyValue(person, property); |
|
NSInteger valuesCount = 0; |
|
if (valuesRef != nil) valuesCount = ABMultiValueGetCount(valuesRef); |
|
|
|
if (valuesCount == 0) { |
|
CFRelease(valuesRef); |
|
continue; |
|
} |
|
|
|
//获取电话号码和email |
|
for (NSInteger k = 0; k < valuesCount; k++) { |
|
CFTypeRef value = ABMultiValueCopyValueAtIndex(valuesRef, k); |
|
switch (j) { |
|
case 0: {// Phone number |
|
|
|
// 拼接姓名以及电话 |
|
NSString *telString = [(__bridge NSString*)value stringByReplacingOccurrencesOfString:@"-" withString:@""]; |
|
contactStr = [NSString stringWithFormat:@"%@\n%@",nameString,telString]; |
|
break; |
|
} |
|
} |
|
|
|
CFRelease(value); |
|
} |
|
|
|
CFRelease(valuesRef); |
|
} |
|
|
|
//将个人信息添加到数组中,循环完成后addressBookTemp中包含所有联系人的信息 |
|
if (contactStr.length) { |
|
[contactArr addObject:contactStr]; |
|
} |
|
|
|
if (abName) CFRelease(abName); |
|
if (abLastName) CFRelease(abLastName); |
|
if (abFullName) CFRelease(abFullName); |
|
} |
|
|
|
return contactArr; |
|
} |
|
|
|
/** |
|
将时间戳转数组为Data发送给设备 |
|
|
|
@param timeArr 时间戳数组 |
|
@param type 请求类型 |
|
|
|
*/ |
|
+ (NSData *)getTimeDataWithTime:(NSArray *)timeArr |
|
cmdType:(BleCMD_FireBoltt)type { |
|
NSMutableData *timeData = [NSMutableData new]; |
|
|
|
for (int i = 0 ; i<timeArr.count;i++) { |
|
NSString *time = timeArr[i]; |
|
NSString *timeStr = [NSString new]; |
|
|
|
if (type == BleCMD_setIngTime) {//时间设置 |
|
|
|
timeStr = [BLETools nsdateToTime:time.longLongValue formatStr:@"yy-MM-dd-HH-mm-ss"]; |
|
}else{//健康数据时间组 |
|
if (timeArr.count == 1) { |
|
// timeStr = [time isEqualToString:@""] ? @"00-00-00-00-00-00" :[BLETools nsdateToTime:time.longLongValue formatStr:@"yy-MM-dd-HH-mm-ss"]; |
|
timeStr = [time isEqualToString:@""] ? @"00-00-00" :[BLETools nsdateToTime:time.longLongValue formatStr:@"yy-MM-dd"]; |
|
} |
|
} |
|
|
|
// 将年月日时分秒转成1字节16进制data |
|
NSArray *arr = [timeStr componentsSeparatedByString:@"-"]; |
|
for (int i = 0; i < arr.count; i ++) { |
|
|
|
int byte = [arr[i] intValue]; |
|
if (byte>2000) { |
|
byte = byte%200; |
|
} |
|
[timeData appendBytes:&byte length:1]; |
|
} |
|
} |
|
return timeData; |
|
} |
|
|
|
/** |
|
将闹钟数据转成Data |
|
|
|
@param arr 闹钟数组 |
|
|
|
*/ |
|
+ (NSData *)getAlarmClockDataWithArr:(NSArray *)arr { |
|
|
|
Byte buffer[25]; |
|
|
|
for (int i = 0; i < 5; i ++) { |
|
|
|
AlarmModel *model = [[AlarmModel alloc] init]; |
|
// 不足五个闹钟,则给空闹钟 |
|
if (arr.count <= i) { |
|
model.Hour = @"00"; |
|
model.Minutes = @"00"; |
|
model.Cycle = @"0000000"; |
|
model.IsOpen = NO; |
|
// 标签 0 无效 1有效 |
|
buffer[3 + i * 5] = 0; |
|
|
|
|
|
}else { |
|
model = arr[i]; |
|
// 标签 |
|
buffer[3 + i * 5] = 1; |
|
} |
|
|
|
// 时 分 |
|
//NSArray *timeArr = [model.alarmTime componentsSeparatedByString:@":"]; |
|
buffer[0 + i * 5] = [model.Hour intValue]; |
|
buffer[1 + i * 5] = [model.Minutes intValue]; |
|
|
|
// 周期 |
|
const char *cycleStr = [model.Cycle cStringUsingEncoding:NSUTF8StringEncoding]; |
|
int cycle = 0; |
|
|
|
for (int j = 0; j < 7; j ++) { |
|
|
|
if (cycleStr[j] == '1') { |
|
|
|
cycle += 1 * pow(2, j); |
|
} |
|
} |
|
|
|
buffer[2 + i * 5] = cycle; |
|
|
|
// 开关 |
|
buffer[4 + i * 5] = model.IsOpen; |
|
|
|
} |
|
NSData *data = [NSData dataWithBytes:buffer length:25]; |
|
|
|
return data; |
|
} |
|
|
|
|
|
/** |
|
构造L1层第二个字节 |
|
|
|
@param err 1:对的 0:错的 |
|
@param ack 1:回复 0:命令 |
|
@param vision 版本 |
|
*/ |
|
+ (Byte)stitchWithErr:(int)err Ack:(int)ack Vision:(int)vision { |
|
|
|
int a = 0 * pow(2, 7) + 0 * pow(2, 6) + err * pow(2, 5) + ack * pow(2, 4) + vision; |
|
|
|
return a; |
|
} |
|
|
|
/** |
|
倒序mac地址 |
|
*/ |
|
+ (NSString *)getInvertedOrderMacWithData:(NSData *)data { |
|
|
|
NSString *macTemp = data.description; |
|
|
|
NSMutableString *mutableMac = [[NSMutableString alloc]init];; |
|
if (macTemp) { |
|
|
|
macTemp = [macTemp stringByReplacingOccurrencesOfString:@" " withString:@""]; |
|
macTemp = [macTemp stringByReplacingOccurrencesOfString:@"<" withString:@""]; |
|
macTemp = [macTemp stringByReplacingOccurrencesOfString:@">" withString:@""]; |
|
macTemp = [macTemp substringFromIndex:4]; |
|
|
|
for (int i = 0; i<6; i++) { |
|
NSString *str = [macTemp substringWithRange:NSMakeRange(macTemp.length-2-i*2, 2)]; |
|
if (i==5) { |
|
[mutableMac appendString:[NSString stringWithFormat:@"%@",str]]; |
|
|
|
} |
|
else{ |
|
[mutableMac appendString:[NSString stringWithFormat:@"%@:",str]]; |
|
} |
|
} |
|
} |
|
|
|
return mutableMac; |
|
} |
|
|
|
|
|
/** |
|
正序mac地址 |
|
*/ |
|
+ (NSString *)getPositiveSequenceMacWithData:(NSData *)data { |
|
NSString *dataStr = [self hexStringFromData:data]; |
|
NSMutableString *mutableMac = [[NSMutableString alloc]init];; |
|
if (dataStr) { |
|
dataStr = [dataStr stringByReplacingOccurrencesOfString:@" " withString:@""]; |
|
dataStr = [dataStr stringByReplacingOccurrencesOfString:@"<" withString:@""]; |
|
dataStr = [dataStr stringByReplacingOccurrencesOfString:@">" withString:@""]; |
|
for (int i = 0; i < 6; i++) { |
|
NSString *str = [dataStr substringWithRange:NSMakeRange(i*2, 2)]; |
|
if (i == 5) { |
|
[mutableMac appendString:[NSString stringWithFormat:@"%@",str]]; |
|
}else { |
|
[mutableMac appendString:[NSString stringWithFormat:@"%@:",str]]; |
|
} |
|
} |
|
} |
|
return [mutableMac uppercaseString]; |
|
} |
|
|
|
/** |
|
Data转16进制字符串 |
|
*/ |
|
+ (NSString *)hexStringFromData:(NSData*)data { |
|
if (![data isKindOfClass:[NSData class]]) { |
|
return nil; |
|
} |
|
if (data == nil) { |
|
return nil; |
|
} |
|
NSMutableString *hexString = [NSMutableString string]; |
|
const unsigned char *p = [data bytes]; |
|
for (int i=0; i < [data length]; i++) { |
|
[hexString appendFormat:@"%02x", *p++]; |
|
} |
|
return hexString; |
|
} |
|
|
|
|
|
|
|
@end
|
|
|