#import
#import
#import
#define channelOnPeropheral @"BleContectModelChannel"
NS_ASSUME_NONNULL_BEGIN
@interface BleContectModel : NSObject
@property(strong, nonatomic)FBluetooth *Fblue;//蓝牙类
@property __block NSMutableArray *services;//蓝牙服务数组
@property(strong,nonatomic)dispatch_source_t gcdTimer;
@property(strong,nonatomic)CBPeripheral *currPeripheral;//蓝牙硬件
@property(strong, nonatomic)NSMutableData *bluedata;
@property(strong, nonatomic)NSString *datelength;//返回数据长度计算
@property(strong, nonatomic)CBCharacteristic *writeCharacteristic;//写入特征
@property(assign, nonatomic)BOOL isKey;//是否是加密数据
@property(assign, nonatomic)BOOL blockIsSendData;//判断连接蓝牙后是否直接发送数据
@property(assign, nonatomic)BOOL timerIsRun;//判断定时器是否运行
@property(assign, nonatomic)NSInteger gcdIdx;
@property (nonatomic, copy) void(^block25)(void);//新设备绑定,发送手机号返回结果
@property (nonatomic, copy) void(^block23)(void);//新设备绑定,时间同步返回结果
@property (nonatomic, copy) void(^block36)(void);//新设备绑定,验证信道密码
@property (nonatomic, copy) void(^block34)(void);//新设备绑定,注册设备
@property (nonatomic, copy) void(^sendbindblock)(void);//新设备绑定,加密后block返回
@property (nonatomic, copy) void(^blueErrorBlock)(NSString *error); //新设备绑定,蓝牙返回错误
@property (nonatomic, copy) void(^blueSendData)(void); //block 蓝牙返回的数据
//初始化
+ (instancetype)shared;
//发送cmd命令到蓝牙,并等待返回数据
+ (void)sendDatacmd:(NSString *)packetType
packetLength:(NSString *)packetLength
cmd:(NSString *)cmd
payload:(NSString *)payload
nativeId:(NSString *)nativeId
success:(void (^)(NSString *msg))success
fail:(void (^)(NSString *msg))fail;
//绑定设备
+ (void)bindBlowerDevice:(NSString *)phone success:(void (^)(NSString *msg))success fail:(void (^)(NSString *msg))fail;
+ (void)bisciddsex:(NSData *)data;
-(void)FblueDelegate:(NSString *)bind;
-(void)CBPeripheralManagerStatePoweredOn;
// 校验CRC
- (BOOL)checkCRC:(NSData *)didGetData;
// 断开后重连
-(void)beginscan;
@end
---------------------- .m文件 -----------------------
#import "BleContectModel.h"
#import "NSTimer+Addition.h"
#import "NoumenonModel.h"
#import "YUTimer.h"
#import "Common.h"
#import "DataMgr.h"
#define blueName @"蓝牙名字"
#define uuidStrHont0 @"自己的UUID"
#define uuidWrite @"自己的UUID"
#define uuidNotify2 @"自己的UUID"
#define uuidHistoryNotify3 @"自己的UUID"
//#define blueName @"蓝牙名字"
//#define uuidStrHont @"自己的UUID"
//#define uuidOther @"自己的UUID"
//#define uuidMOM @"自己的UUID"
// 秘钥
uint8_t KeyaSph[16] =
{
};
uint8_t KeyTSph[16] =
{
};
//公钥 二进制文件
//uint8_t Key_ContcaSph[16] =
//{
// 0x07, 0xba, 0x06, 0xa7, 0x66, 0xcf, 0xfd, 0xa6, 0x3b, 0x58, 0xb9, 0x63, 0x97, 0x83, 0x75, 0x5F
//};
uint8_t Key_ContcaSph[16] =
{
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16
};
@interface SphygmomanometerBleContectModel ()
@property (nonatomic,strong) NSTimer* updateTimer;
@property (nonatomic,assign) BOOL isRepeat;
@property (nonatomic,assign) BOOL isCmd; //是否允许发送Cmd
@property (nonatomic , assign) int threeIndex; // 参数three标识 未了看log 定义标识
@property (nonatomic, strong) YUTimer *timerIndex;
@property (nonatomic , copy) NSString *TypeFour;// 参数配置分发:
@property (nonatomic , copy) NSString *modelFive; //模式
@property (nonatomic , copy) NSString *autoHandSix; // 0:自動/1:手動/FF:skip
@property (nonatomic , copy) NSString *flowSeven;
@property (nonatomic , copy) NSString *longShotEight;
@property (nonatomic , copy) NSString *otherNine;//
@property (nonatomic , copy) NSString *productKey; //16位随机数秘钥
@property (nonatomic, assign) int seqNumber;
@property (nonatomic, strong) NoumenonModel *model;
@property (nonatomic , strong) NSMutableData *subcontractData; // 分包接收 A6 数据
@property (nonatomic , assign) BOOL isTimeOut;
@property (nonatomic , copy) NSString *nativeId;
@property (nonatomic , assign) BOOL dataEnd; // 数据是否接收完成
@property (nonatomic , assign) BOOL oneFor; // 只遍历一次
@property (nonatomic , copy) NSString *packetType;
@property (nonatomic , copy) NSString *packetLength;
@property (nonatomic , assign) BOOL isSecret; // 是否是秘钥
@property (nonatomic , assign) int packLengthTmp;
@property (nonatomic , strong) NSMutableArray *pinArray;
@property (nonatomic , strong) CBCharacteristic *notify2Characteristic;
@property (nonatomic , strong) CBCharacteristic *notify3Characteristic;
@property (nonatomic , assign) BOOL onceRunning;
@end
@implementation SphygmomanometerBleContectModel
//重写init
- (instancetype)init {
self = [super init];
if (self) {
self.seqNumber = 1;
self.model = [[NoumenonModel alloc]init];
//初始化对象
_Fblue = [FBluetooth shareFBluetooth];
[_Fblue cancelAllPeripheralsConnection];
[_Fblue cancelScan];
_Fblue.scanForPeripherals().begin();
_gcdTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
_oneFor = NO;
_pinArray = [[NSMutableArray alloc]init];
// [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(CBPeripheralManagerStatePoweredOn) name:@"CBPeripheralManagerStatePoweredOn" object:nil];
}
return self;
}
//监听蓝牙是否打开
-(void)CBPeripheralManagerStatePoweredOn{
[_Fblue cancelAllPeripheralsConnection];
_Fblue.scanForPeripherals().begin();
}
- (UIViewController *)findCurrentViewController
{
UIWindow *window = [[UIApplication sharedApplication].delegate window];
UIViewController *topViewController = [window rootViewController];
while (true) {
if (topViewController.presentedViewController) {
topViewController = topViewController.presentedViewController;
} else if ([topViewController isKindOfClass:[UINavigationController class]] && [(UINavigationController*)topViewController topViewController]) {
topViewController = [(UINavigationController *)topViewController topViewController];
} else if ([topViewController isKindOfClass:[UITabBarController class]]) {
UITabBarController *tab = (UITabBarController *)topViewController;
topViewController = tab.selectedViewController;
} else {
break;
}
}
return topViewController;
}
- (NSMutableData *)subcontractData {
if (_subcontractData == nil) {
_subcontractData = [[NSMutableData alloc]init];
}
return _subcontractData;
}
//蓝牙的block
-(void)FblueDelegate:(NSString *)bind{
self.isRepeat = YES;
self.isCmd = NO;
// ---- 500 毫秒 ----
__weak typeof(self) weakSelf = self;
[_Fblue setBlockOnCentralManagerDidUpdateState:^(CBCentralManager *central) {
//手机蓝牙是否开启
if (@available(iOS 10.0, *)) {
if (central.state == CBManagerStatePoweredOff) {
if (weakSelf.blueErrorBlock != nil) {
weakSelf.blueErrorBlock(@"请打开蓝牙开关");
}
}
} else {
}
}];
//设置扫描到设备的委托
[_Fblue setBlockOnDiscoverToPeripherals:^(CBCentralManager *central, CBPeripheral *peripheral, NSDictionary *advertisementData, NSNumber *RSSI) {
NSLog(@"搜索到了设备:%@",peripheral.name);
[[NSNotificationCenter defaultCenter] postNotificationName:@"otherBleContentSuccess" object:nil userInfo:nil];
if ([peripheral.name containsString:blueName]) {
weakSelf.currPeripheral = peripheral;
// 搜索到了设备就停止扫描
[weakSelf.Fblue cancelScan];
if ([bind isEqualToString:@"bind"]) {
weakSelf.Fblue.having(weakSelf.currPeripheral).and.channel(channelOnPeropheral).then.connectToPeripherals().discoverServices().discoverCharacteristics().readValueForCharacteristic().discoverDescriptorsForCharacteristic().begin();
} else {
weakSelf.Fblue.having(weakSelf.currPeripheral).and.channel(channelOnPeropheral).then.connectToPeripherals().discoverServices().discoverCharacteristics().discoverDescriptorsForCharacteristic().begin();
}
}
}];
//设置查找设备的过滤器
[_Fblue setFilterOnDiscoverPeripherals:^BOOL(NSString *peripheralName, NSDictionary *advertisementData, NSNumber *RSSI) {
NSLog(@"搜索设备:%@",peripheralName);
if ([peripheralName containsString:blueName]) {
return YES;
}
return NO;
}];
NSDictionary *scanForPeripheralsWithOptions = @{CBCentralManagerScanOptionAllowDuplicatesKey:@YES};
//设置设备连接成功的委托,同一个_Fblue对象,使用不同的channel切换委托回调
[_Fblue setBlockOnConnectedAtChannel:channelOnPeropheral block:^(CBCentralManager *central, CBPeripheral *peripheral) {
weakSelf.currPeripheral = peripheral;
CBUUID *macServiceUUID = [CBUUID UUIDWithString:@"180A"];
[peripheral discoverServices:@[macServiceUUID]];
// PANAQBLE EH-XD30_B923 // 暂时 固定值 避免其他人连接 上传时把 B923删除 EH-XD30_B325是吹风机蓝牙名称
NSLog(@"蓝牙名字:%@",peripheral.name);
// liuwen bletest123
if ([peripheral.name containsString:blueName]) {
// [[NSNotificationCenter defaultCenter] postNotification:[[NSNotification alloc]initWithName:@"deviceConnect" object:@"1" userInfo:nil]];
// [[NSUserDefaults standardUserDefaults] setObject:@"yes" forKey:@"deviceConnect"];
}
}];
//设置设备连接失败的委托
[_Fblue setBlockOnFailToConnectAtChannel:channelOnPeropheral block:^(CBCentralManager *central, CBPeripheral *peripheral, NSError *error) {
NSLog(@"设备:%@--连接失败",peripheral.name);
if ([peripheral.name containsString:blueName]) {
}
}];
//设置设备断开连接的委托
[_Fblue setBlockOnDisconnectAtChannel:channelOnPeropheral block:^(CBCentralManager *central, CBPeripheral *peripheral, NSError *error) {
NSLog(@"设备:%@--断开连接",peripheral.name);
// 想H5发送断开链接操作
[[NSNotificationCenter defaultCenter] postNotificationName:@"SphygmomanometerBleDiscontect" object:nil userInfo:nil];
weakSelf.updateTimer = nil;
[weakSelf.updateTimer invalidate];
weakSelf.currPeripheral = nil;
weakSelf.writeCharacteristic = nil;
weakSelf.timerIsRun = NO;
}];
//设置发现设service的Characteristics的委托 == old
[_Fblue setBlockOnDiscoverCharacteristicsAtChannel:channelOnPeropheral block:^(CBPeripheral *peripheral, CBService *service, NSError *error) {
NSLog(@"===service name:%@",service.UUID);
NSLog(@"peripheral.name:%@",peripheral.name);
// weakSelf.writeCharacteristic = nil;
if ([bind isEqualToString:@"bind"]) {
if ([service.UUID.UUIDString isEqualToString:uuidStrHont0]) {
// 00001C00-D102-11E2-9B23-000E5B00A5A5
[weakSelf insertService:service];
}
} else {
}
}];
NSDictionary *connectOptions = @{CBConnectPeripheralOptionNotifyOnConnectionKey:@YES,
CBConnectPeripheralOptionNotifyOnDisconnectionKey:@YES,
CBConnectPeripheralOptionNotifyOnNotificationKey:@YES};
[_Fblue setFOptionsAtChannel:channelOnPeropheral scanForPeripheralsWithOptions:scanForPeripheralsWithOptions connectPeripheralWithOptions:connectOptions scanForPeripheralsWithServices:nil discoverWithServices:nil discoverWithCharacteristics:nil];
[_Fblue setBlockOnDidWriteValueForCharacteristicAtChannel:channelOnPeropheral block:^(CBCharacteristic *characteristic, NSError *error) {
NSLog(@"---\\????\\---%@", characteristic);
}];
[weakSelf.Fblue setBlockOnReadValueForCharacteristicAtChannel:channelOnPeropheral block:^(CBPeripheral *peripheral, CBCharacteristic *characteristic, NSError *error) {
if ([[NSUserDefaults standardUserDefaults] objectForKey:@"bleMAC"] == nil) {
if ([characteristic.UUID.UUIDString isEqualToString:@"2A23"]) {
NSString *value = [NSString stringWithFormat:@"%@",characteristic.value];
NSMutableString *macString = [[NSMutableString alloc] init];
[macString appendString:[[value substringWithRange:NSMakeRange(12, 2)] uppercaseString]];
[macString appendString:[[value substringWithRange:NSMakeRange(14, 2)] uppercaseString]];
[macString appendString:[[value substringWithRange:NSMakeRange(16, 2)] uppercaseString]];
[macString appendString:[[value substringWithRange:NSMakeRange(5, 2)] uppercaseString]];
[macString appendString:[[value substringWithRange:NSMakeRange(7, 2)] uppercaseString]];
[macString appendString:[[value substringWithRange:NSMakeRange(10, 2)] uppercaseString]];
NSLog(@"macstring:%@", macString);
[[NSUserDefaults standardUserDefaults] setObject:macString forKey:@"bleMAC"];
if (self.sendbindblock != nil) {
weakSelf.sendbindblock();
}
} else {
return;
}
}
}];
}
- (void)timeer {
__block NSInteger second = 0.8;
//(1)
dispatch_queue_t quene = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//(2)
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, quene);
//(3)
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
//(4)
dispatch_source_set_event_handler(timer, ^{
dispatch_async(dispatch_get_main_queue(), ^{
if (second == 0) {
//如果超时添加Bool值
self.isCmd = YES;
self.isRepeat = YES;
dispatch_cancel(timer);
} else {
second--;
}
});
});
//(5)
dispatch_resume(timer);
}
//#pragma mark - 轮循方法
//- (void)repeatData {
// if ([[[NSUserDefaults standardUserDefaults] objectForKey:@"deviceConnect"] isEqualToString:@"yes"]) {
// if (self.updateTimer != nil) {
// NSLog(@"轮循方法");
// if (self.isRepeat == YES) {
// // 发送数据
// [SphygmomanometerBleContectModel sendDatacmd:@"A3" payload:@"" success:^(NSString * _Nonnull msg) {
// NSLog(@"%@",msg);
// } fail:^(NSString * _Nonnull msg) {
// NSLog(@"%@",msg);
// }];
// }
// }
// }
//}
//遍历获取特征
-(void)insertService:(CBService *)service {
for (int row=(int)service.characteristics.count-1;row>=0;row--) {
NSLog(@"<<<<<<<<+++:%@", service.characteristics[row]);
if ([service.characteristics[row].UUID.UUIDString isEqualToString:uuidWrite]) {
_writeCharacteristic = service.characteristics[row];
} else if ([service.characteristics[row].UUID.UUIDString isEqualToString:uuidNotify2]) {
_notify2Characteristic = service.characteristics[row];
// 去注册notify 一个notify服务,对应一个write服务,可以write的时候把notify的订阅开启,接收完把notify的订阅关掉
// 关闭订阅的代码 [self->_Fblue cancelNotify:self.currPeripheral characteristic:characteristic];
[self setnotif:service.characteristics[row]];
} //最好把注册服务分开写
// else if ([service.characteristics[row].UUID.UUIDString isEqualToString:uuidHistoryNotify3]) {
// _notify3Characteristic = service.characteristics[row];
// // 不去注册notify [注]
// [self setnotif:service.characteristics[row]];
// }
}
[self sendrandNums];
_isSecret = YES;
}
//发送数据到蓝牙。需要处理分包发送,每次发送20字节
-(void)sendDatacmd:(NSString *)cmd payload:(NSString *)payload{
if (self.currPeripheral == nil || _writeCharacteristic == nil) {
return;
}
// 开订阅
if (_notify2Characteristic != nil) {
[self setnotif:_notify2Characteristic];
}
if (_notify3Characteristic != nil) {
[self setnotif:_notify3Characteristic];
}
NSData *writeData = [self sendDatatoBlue:cmd payLoad:payload];
for (int i = 0; i < writeData.length; i += 20) {
if ((i + 20) <= [writeData length]) {
NSString *rangeStr = [NSString stringWithFormat:@"%i,%i", i, 20];
NSData *subData = [writeData subdataWithRange:NSRangeFromString(rangeStr)];
NSLog(@"subDataUUUUU:%d:%@",i,subData);
[self.currPeripheral writeValue:subData forCharacteristic:_writeCharacteristic type:CBCharacteristicWriteWithResponse];
} else {
NSString *rangeStr = [NSString stringWithFormat:@"%i,%i", i, (int)([writeData length] - i)];
NSData *subData = [writeData subdataWithRange:NSRangeFromString(rangeStr)];
NSLog(@"subDataXXXXX:%d:%@",i,subData);
[self.currPeripheral writeValue:subData forCharacteristic:_writeCharacteristic type:CBCharacteristicWriteWithResponse];
}
}
}
//发送16位随机数,获取秘钥
-(void)sendrandNums {
//没有发现服务就退出,不能注释掉
if (self.currPeripheral == nil || _writeCharacteristic == nil) {
return;
}
NSString *randStr = @"";
for (int i = 0;i<16; i++) {
// NSUInteger r = arc4random_uniform(255); //随机数
NSUInteger r = (18 + (arc4random() % (255 - 18 + 1)));
randStr = [NSString stringWithFormat:@"%@%@",randStr,[FToy getHexByDecimal:r]];
}
_productKey = randStr;
NSData *tempData = [FToy convertHexStrToData:randStr];
// 发送16位随机数时 已经把 Kaya赋值了,等待回来解析数据把解析完的数据在存入到Kaya 中
NSData *writeData = [SphygmomanometerBleContectModel sendrandNumspayload:@[randStr]];
// 保存起来 蓝牙会返回给新秘钥 用 productKey 解密 用 解出来之后的 秘钥
// 16位随机数 写入秘钥中,蓝牙回来的时候用秘钥解密
NSLog(@"16位随机数是:%@",_productKey);
for (int i = 0; i < 16; i++) {
NSString *rangeStr = [NSString stringWithFormat:@"%i,%i", i, 1];
NSData *as = [tempData subdataWithRange:NSRangeFromString(rangeStr)]; //ios 的二进制(16)
/// 把解析回来的数据 把之前的私钥替换掉,之后发数据是都用私钥
KeyTSph[i] = [FToy ConvertDataToInt:as];
}
NSLog(@"fuqiang发送随机数%@",writeData);
for (int i = 0; i < writeData.length; i += 20) {
if ((i + 20) <= [writeData length]) {
NSString *rangeStr = [NSString stringWithFormat:@"%i,%i", i, 20];
NSData *subData = [writeData subdataWithRange:NSRangeFromString(rangeStr)];
NSLog(@"subData+++:%d:%@",i,subData);
[self.currPeripheral writeValue:subData forCharacteristic:_writeCharacteristic type:CBCharacteristicWriteWithResponse];
} else {
NSString *rangeStr = [NSString stringWithFormat:@"%i,%i", i, (int)([writeData length] - i)];
NSData *subData = [writeData subdataWithRange:NSRangeFromString(rangeStr)];
NSLog(@"subData+++:%d:%@",i,subData);
[self.currPeripheral writeValue:subData forCharacteristic:_writeCharacteristic type:CBCharacteristicWriteWithResponse];
}
}
}
//蓝牙断开后重开扫描
-(void)beginscan{
_Fblue = [FBluetooth shareFBluetooth];
[_Fblue cancelAllPeripheralsConnection];
[_Fblue cancelScan];
_Fblue.scanForPeripherals().begin();
[[SphygmomanometerBleContectModel shared] FblueDelegate:@"bind"];
}
//蓝牙监听,接受返回值
-(void)setnotif:(CBCharacteristic *)characteristic{
NSLog(@"????%@", characteristic.UUID);
// 把需要订阅的特正 发送给蓝牙, notify 注册yes (封装的已经做好)
__weak typeof(self)weakSelf = self;
[_Fblue notify:self.currPeripheral
characteristic:characteristic
block:^(CBPeripheral *peripheral, CBCharacteristic *characteristics, NSError *error) {
NSString *dataStr = [[[[characteristics.value description] stringByReplacingOccurrencesOfString:@"<"withString:@""]stringByReplacingOccurrencesOfString:@">" withString:@""]stringByReplacingOccurrencesOfString:@" " withString:@""];
NSLog(@"收到数据:%@",dataStr);
if (self.blueSendData != nil) {
self.blueSendData();
}
NSMutableArray *byteArray = [NSMutableArray array];
// 美隔两个截取字符串
for (int i = 0 ; i < dataStr.length ; i += 2) {
NSString *strTmp = [dataStr substringWithRange:NSMakeRange(i, 2)];
[byteArray addObject:strTmp];
}
if ([characteristic.UUID.UUIDString isEqualToString:uuidNotify2]) {
if (byteArray.count > 0) {
if ([byteArray[0] isEqualToString:@"fd"] ) { // 秘钥反信
[SphygmomanometerBleContectModel keyAesDec:characteristics.value];
// if(weakSelf.updateTimer == nil) {
// weakSelf.updateTimer = [NSTimer scheduledTimerWithTimeInterval:0.8 block:^{
// if (self.isRepeat == YES) {
// [self timeer];
// // 轮询方法
// // [self repeatData];
// self.isRepeat = NO;
// }
// } repeats:YES];
// [weakSelf.updateTimer fire];
// }
return;
} else {
[SphygmomanometerBleContectModel bisciddsex:characteristics.value];
NSLog(@"--------:%@",characteristic.value);
// 关订阅
// [self->_Fblue cancelNotify:self.currPeripheral characteristic:characteristic];
}
}
}
else { // 03一对多 不能关订阅
[[NSUserDefaults standardUserDefaults] setObject:characteristics.value forKey:@"charValue"];
[SphygmomanometerBleContectModel bisciddsex:characteristics.value];
}
}];
}
#pragma mark - 锁蓝牙类方法
//单利模式,初始化
+ (instancetype)shared {
static SphygmomanometerBleContectModel *share = nil;
static dispatch_once_t oneToken;
dispatch_once(&oneToken, ^{
share = [[SphygmomanometerBleContectModel alloc]init];
});
return share;
}
//发送数据到蓝牙
- (NSData *)sendDatatoBlue:(NSString *)Cmd payLoad:(NSString *)payLoad {
// 体脂秤
_isTimeOut = YES;
NSMutableData *newdata = [[NSMutableData alloc]init];
NSData *header = [FToy convertHexStrToData:_packetType];
NSData *length = [FToy convertHexStrToData:_packetLength];
[newdata appendData:header];
[newdata appendData:length];
NSMutableData *aesData = [[NSMutableData alloc]init];
NSData *playLoadZero = [FToy convertHexStrToData:payLoad];
[aesData appendData:playLoadZero];
NSData *payloadCome = [SphygmomanometerBleContectModel aesEncrypt:aesData typeFlag:2];
[newdata appendData: payloadCome];
// 原来有crc加密
NSData *crcCome = [SphygmomanometerBleContectModel crcCome:newdata];
[newdata appendData: crcCome];
// 超时时间
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if (self->_isTimeOut == YES) { // 超时
NSLog(@"%@",@"超时");
[self centerSendData:NO data:[NSData new] errorCode:@"1"];
} else { // 没有超时
NSLog(@"%@",@"不超时");
}
});
return newdata;
}
//解析返回的私钥
+ (void)keyAesDec:(NSData *)data {
NSString *dataStr_Aes = [[[[data description] stringByReplacingOccurrencesOfString:@"<"withString:@""]stringByReplacingOccurrencesOfString:@">" withString:@""]stringByReplacingOccurrencesOfString:@" " withString:@""];
NSInteger datelength = [FToy getDecimalByBinary:[FToy getBinaryByHex:[dataStr_Aes substringWithRange:NSMakeRange(2,2)]]];
NSString *rangeStr = [NSString stringWithFormat:@"%i,%li", 2, (long)datelength];
NSData *Aes_ayData = [data subdataWithRange:NSRangeFromString(rangeStr)];
// 用私钥解密,私钥匙 _productKey 用公钥加密时写入了 二进制私钥文件
NSData *aesData = [SphygmomanometerBleContectModel aesDecryp:Aes_ayData typeFlag:3];
NSLog(@"收到解密数据:%@",aesData);
for (int i = 0; i < 16; i++) {
NSString *rangeStr = [NSString stringWithFormat:@"%i,%i", i, 1];
NSData *as = [aesData subdataWithRange:NSRangeFromString(rangeStr)]; //ios 的二进制(16)
/// 把解析回来的数据 把之前的私钥替换掉,之后发数据是都用私钥
KeyaSph[i] = [FToy ConvertDataToInt:as];
}
}
//发送随机数给蓝牙,获取秘钥
+ (NSData *)sendrandNumspayload:(NSArray *)payload {
NSString *payload1 = @"";
//计算length
NSString *str = payload[0];
payload1 = str;
NSData *payloadData1 = [FToy convertHexStrToData:payload1];
NSMutableData *newdata = [[NSMutableData alloc]init];
[newdata appendData:payloadData1];
NSMutableData *aesData = [[NSMutableData alloc]init];
NSData *typeCome = [FToy convertHexStrToData:@"FE"];
[aesData appendData: typeCome];
NSData *payloadCome = [SphygmomanometerBleContectModel aesEncrypt:newdata typeFlag:1];
NSData *lenCome = [FToy convertHexStrToData:@"10"];
[aesData appendData: lenCome];
[aesData appendData: payloadCome];
NSData *crcCome = [SphygmomanometerBleContectModel crcCome:aesData];
[aesData appendData: crcCome];
return aesData;
}
//计算crc
+ (NSData *)crcCome:(NSData *)data{
int crc = 0;
for (int i = 0; i < data.length; i++) {
NSString *rangeStr = [NSString stringWithFormat:@"%i,%i", i, 1];
NSData *as = [data subdataWithRange:NSRangeFromString(rangeStr)];
crc = crc + [FToy ConvertDataToInt:as];
}
NSString *crcCome = [FToy getHexByDecimal:crc];
for (int i = 0; i < 4 - crcCome.length; i++) {
crcCome = [NSString stringWithFormat:@"0%@",crcCome];
}
return [FToy convertHexStrToData:crcCome];
}
//aes解密
+ (NSData *)aesDecryp:(NSData *)data typeFlag:(NSInteger)flag{
//flag = 1 获取秘钥,key使用公钥; flag = 2 发送cmd指令,key使用秘钥
cf_aes_context stu;
if (flag == 1) {
cf_aes_init(&stu, Key_ContcaSph, 16);
} else if (flag == 2) {
cf_aes_init(&stu, KeyaSph, 16);
} else if (flag == 3) {
cf_aes_init(&stu, KeyTSph, 16);
}
//解密数据数组
uint8_t out_data[16] =
{
};
uint8_t aesclo[16];
NSMutableData *newdata = [[NSMutableData alloc]init];
for (int i = 0; i < data.length; i++) {
//16位一组解密
int flag = (i)%16;
NSString *rangeStr = [NSString stringWithFormat:@"%i,%i", i, 1];
NSData *as = [data subdataWithRange:NSRangeFromString(rangeStr)];
aesclo[flag] = [FToy ConvertDataToInt:as];
if (flag == 15) {
cf_aes_decrypt(&stu, aesclo, out_data);
for (int i = 0; i < 16; i++) {
NSInteger it = out_data[i];
[newdata appendData:[NSData dataWithBytes: &it length: 1]];
}
for (int i = 0; i < 16; i++) {
aesclo[i] = 0;
}
}
}
return newdata;
}
//aes加密
+ (NSData *)aesEncrypt:(NSMutableData *)data typeFlag:(NSInteger)flag{
//flag = 1 获取秘钥,key使用公钥; flag = 2 发送cmd指令,key使用秘钥
//16位一组加密,不足16位补0
NSInteger addCount = 16 - (data.length%16);
if (data.length%16 != 0) {
for (int i = 0; i < addCount; i++) {
[data appendData:[FToy convertHexStrToData:@"00"]];
}
}
cf_aes_context stu;
if (flag == 1) {
cf_aes_init(&stu, Key_ContcaSph, 16);
}else if (flag == 2) {
cf_aes_init(&stu, KeyaSph, 16);
}else if (flag == 3) {
cf_aes_init(&stu, KeyTSph, 16);
}
//加密数据数组
uint8_t out_data[16] =
{
};
uint8_t aesclo[16];
NSMutableData *newdata = [[NSMutableData alloc]init];
for (int i = 0; i < data.length; i++) {
//16位一组加密
int flag = (i)%16;
NSString *rangeStr = [NSString stringWithFormat:@"%i,%i", i, 1];
NSData *as = [data subdataWithRange:NSRangeFromString(rangeStr)];
aesclo[flag] = [FToy ConvertDataToInt:as];
if (flag == 15) {
cf_aes_encrypt(&stu, aesclo, out_data);
for (int i = 0; i < 16; i++) {
NSInteger it = out_data[i];
[newdata appendData:[NSData dataWithBytes: &it length: 1]];
}
for (int i = 0; i < 16; i++) {
aesclo[i] = 0x00;
}
}
}
return newdata;
}
+ (NSString *)DictionaryToString:(NSDictionary *)initDic {
NSError * err;
NSString * jsonString;
if (!initDic || [initDic count] == 0) {
return @"";
}
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:initDic options:NSJSONWritingPrettyPrinted error:&err];
if (!jsonData) {
return @"";
}else{
jsonString = [[NSString alloc]initWithData:jsonData encoding:NSUTF8StringEncoding];
}
return jsonString;
}
// 发送数据
+ (void)sendDatacmd:(NSString *)packetType
packetLength:(NSString *)packetLength
cmd:(NSString *)cmd
payload:(NSString *)payload
nativeId:(NSString *)nativeId
success:(void (^)(NSString *msg))success
fail:(void (^)(NSString *msg))fail{
SphygmomanometerBleContectModel *Lockblue = [SphygmomanometerBleContectModel shared];
[Lockblue FblueDelegate:@"cmd"];
__weak typeof(Lockblue) weakLockblue = Lockblue;
__strong typeof(weakLockblue) strongSelf = weakLockblue;
Lockblue.blockIsSendData = YES;
Lockblue.nativeId = nativeId;
Lockblue.packetType = packetType;
Lockblue.packetLength = packetLength;
Lockblue.onceRunning = NO;
weakLockblue.blueSendData = ^{
success(@"成功");
};
if (Lockblue.timerIsRun == NO) {
Lockblue.gcdIdx = 0;
Lockblue.timerIsRun = YES;
}
if (Lockblue.writeCharacteristic != nil) {
if (payload == nil) {
payload = @"";
}
// 发送数据
[strongSelf sendDatacmd:cmd payload:payload];
strongSelf.blockIsSendData = NO;
} else {
[Lockblue sendrandNums];
}
}
+ (void)bindBlowerDevice:(NSString *)phone success:(void (^)(NSString *msg))success fail:(void (^)(NSString *msg))fail{
SphygmomanometerBleContectModel *Lockblue = [SphygmomanometerBleContectModel shared];
[Lockblue FblueDelegate:@"bind"];
__weak typeof(Lockblue) weakLockblue = Lockblue;
weakLockblue.blueErrorBlock = ^(NSString * _Nonnull error) {
fail(error);
};
Lockblue.blockIsSendData = YES;
if (Lockblue.timerIsRun == NO) {
Lockblue.gcdIdx = 0;
Lockblue.timerIsRun = YES;
}
weakLockblue.sendbindblock = ^{
success(@"设备绑定成功");
};
}
- (YUTimer *)timerIndex {
if (_timerIndex == nil) {
_timerIndex = [[YUTimer alloc] init];
}
return _timerIndex;
}
#pragma mark - 解析数据
+ (void)bisciddsex:(NSData *)data {
SphygmomanometerBleContectModel *Lockblue = [SphygmomanometerBleContectModel shared];
__weak typeof(Lockblue) weakLockblue = Lockblue;
// ----- 是不是分包的处理 -----
NSString *dataLength = [[[[data description] stringByReplacingOccurrencesOfString:@"<"withString:@""]stringByReplacingOccurrencesOfString:@">" withString:@""]stringByReplacingOccurrencesOfString:@" " withString:@""];
NSString *packLength = [dataLength substringWithRange:NSMakeRange(2, 2)];
// 16进制-->二进制
NSString *secondNumber = [FToy getBinaryByHex:packLength];
// 2进制-->十进制
NSInteger tenNumber = [FToy getDecimalByBinary:secondNumber];
// ----- 是不是分包的处理 -----
NSString *rangeStr = NULL;
NSData *Aes_ayData = NULL;
if (tenNumber > 16) {
rangeStr = [NSString stringWithFormat:@"%i,%lu", 2, ((dataLength.length)/2) - 4];
Aes_ayData = [data subdataWithRange:NSRangeFromString(rangeStr)];
} else {
rangeStr = [NSString stringWithFormat:@"%i,%li", 2, (long)16];
Aes_ayData = [data subdataWithRange:NSRangeFromString(rangeStr)];
}
// 用私钥解密,私钥匙 _productKey 用公钥加密时写入了 二进制私钥文件
NSData *aesData = [SphygmomanometerBleContectModel aesDecryp:Aes_ayData typeFlag:2];
// ---- 数据放在数组中截取 -----
NSString *dataStr = [[[[aesData description] stringByReplacingOccurrencesOfString:@"<"withString:@""]stringByReplacingOccurrencesOfString:@">" withString:@""]stringByReplacingOccurrencesOfString:@" " withString:@""];
NSMutableArray *byteArray = [NSMutableArray array];
// 美隔两个截取字符串
for (int i = 0 ; i < dataStr.length ; i += 2) {
NSString *strTmp = [dataStr substringWithRange:NSMakeRange(i, 2)];
[byteArray addObject:strTmp];
}
NSLog(@"byteArray----:%@",byteArray);
// SphygmomanometerBleContectModel *Lockblue = [SphygmomanometerBleContectModel shared];
// __weak typeof(Lockblue) weakLockblue = Lockblue;
// 接收到数据没有超时
Lockblue.isTimeOut = NO;
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(timeOutFun) object:nil];
if (Lockblue.isSecret == YES) {
if (tenNumber > 16) {
if (Lockblue.onceRunning == NO) {
if ([weakLockblue checkCRC:data]) { //CRC校验正确
// 大于16字节只执行一次
[Lockblue centerSendData:YES data:aesData errorCode:@"0"];
Lockblue.onceRunning = YES;
} else {
NSLog(@"%@",@"CRC校验错误");
[Lockblue centerSendData:NO data:[NSData new] errorCode:@"2"];
}
}
} else {
if (Lockblue.onceRunning == NO) {
if ([weakLockblue checkCRC:data]) {
[Lockblue centerSendData:YES data:aesData errorCode:@"0"];
} else {
NSLog(@"%@",@"CRC校验错误");
[Lockblue centerSendData:NO data:[NSData new] errorCode:@"2"];
}
}
}
} else {
NSLog(@"%@",@"秘钥执行不发送数据给H5");
Lockblue.isSecret = NO;
}
}
- (void)timeOutFun {
NSLog(@"体脂计 A5超时");
[self centerSendData:NO data:[NSData new] errorCode:@"1"];
}
- (void)centerSendData:(BOOL)success data:(NSData *)data errorCode:(NSString *)coerrorCodede {
NSString *lastDataStr = [[[[data description] stringByReplacingOccurrencesOfString:@"<"withString:@""]stringByReplacingOccurrencesOfString:@">" withString:@""]stringByReplacingOccurrencesOfString:@" " withString:@""];
NSLog(@"向H5发送的数据%@",lastDataStr);
if (success) {
NSDictionary *dic = @{
@"errorCode":@(0),
@"nativeId":@([_nativeId intValue]),
@"results":lastDataStr
};
[[NSNotificationCenter defaultCenter] postNotificationName:@"SphygmomanometerBleContectModelNotification" object:nil userInfo:dic];
} else {
NSDictionary *dic = @{
@"errorCode":@([coerrorCodede intValue]),
@"nativeId":@([_nativeId intValue]),
@"results":@""
};
[[NSNotificationCenter defaultCenter] postNotificationName:@"SphygmomanometerBleContectModelNotification" object:nil userInfo:dic];
}
}
#pragma mark - 校验CRC
- (BOOL)checkCRC:(NSData *)didGetData {
NSString *dataStr = [[[[didGetData description] stringByReplacingOccurrencesOfString:@"<"withString:@""]stringByReplacingOccurrencesOfString:@">" withString:@""]stringByReplacingOccurrencesOfString:@" " withString:@""];
// dataStr = @"0710150a3b146b54bb6b3a5c86cb9f6f9e82067f";
NSMutableArray *byteArray = [NSMutableArray array];
// 美隔两个截取字符串
for (int i = 0 ; i < dataStr.length - 4; i += 2) {
NSString *strTmp = [dataStr substringWithRange:NSMakeRange(i, 2)];
// 16进制-->二进制
NSString *secondNumber = [FToy getBinaryByHex:strTmp];
// 2进制-->十进制
NSInteger tenNumber = [FToy getDecimalByBinary:secondNumber];
[byteArray addObject:[NSNumber numberWithInteger:tenNumber]];
}
// NSLog(@"UUUUUUUU:%@",byteArray);
int ind = 0;
for (NSNumber *number in byteArray) {
ind = ind + [number intValue];
}
NSLog(@"十进制数加和:%d",ind);
NSString *strInt = [NSString stringWithFormat:@"%d",ind];
// 10 --> 16
NSString *strLast = [FToy getHexByDecimal:[strInt integerValue]].lowercaseString;
if (strLast.length == 4) {
strLast = [NSString stringWithFormat:@"%@",strLast];
} else if (strLast.length == 3) {
strLast = [NSString stringWithFormat:@"0%@",strLast];
} else if (strLast.length == 2) {
strLast = [NSString stringWithFormat:@"00%@",strLast];
} else if (strLast.length == 1) {
strLast = [NSString stringWithFormat:@"000%@",strLast];
} else {
}
NSString *strMMP = [dataStr substringFromIndex:dataStr.length - 4];
NSLog(@"strMMP:%@",strMMP);
if ([strMMP isEqualToString:strLast]) {
NSLog(@"%@",@"YES");
return YES;
} else {
NSLog(@"%@",@"NO");
return NO;
}
}