416 lines
13 KiB
Objective-C
Executable File
416 lines
13 KiB
Objective-C
Executable File
//
|
||
// ENBPDevice.m
|
||
// ENBLEProject
|
||
//
|
||
// Created by lvwang2002 on 16/4/8.
|
||
// Copyright © 2016年 Facebook. All rights reserved.
|
||
//
|
||
|
||
#import "ENBPDevice.h"
|
||
#define kStartCheck @"开始测量"
|
||
#define kStopCheck @"停止测量"
|
||
|
||
// 发给血压计 (带校验码)
|
||
Byte SEND_CHECK_POWER_PRESSURE[] = { 0xcc, 0x85, 0x02, 0x03, 0x04, 0x04, 0x00, 0x01 };// 查询电量
|
||
Byte SEND_CONNECT_PRESSURE[] = { 0xcc, 0x85, 0x02, 0x03, 0x01, 0x01, 0x00, 0x01 };// 连接血压计
|
||
Byte SEND_START_PRESSURE[] = { 0xcc, 0x85, 0x02, 0x03, 0x01, 0x02, 0x00, 0x02 };// 开始测量
|
||
Byte SEND_STOP_PRESSURE[] = { 0xcc, 0x85, 0x02, 0x03, 0x01, 0x03, 0x00, 0x03 };// 停止测量
|
||
Byte SEND_CLOSE_PRESSURE[] = { 0xcc, 0x85, 0x02, 0x03, 0x01, 0x04, 0x00, 0x04 };// 关仪器
|
||
|
||
// 收到血压计之后(血压计还会回复指令)匹配是否成功的字节数组 (带校验码)
|
||
Byte RECEIVE_CHECK_POWER_PRESSURE[] = { 0xaa, 0x85, 0x02, 0x04, 0x04, 0x04 };// 查询电量(数组中没有放入校验码,和数据,共3个字节)
|
||
Byte RECEIVE_CONNECT_PRESSURE[] = { 0xaa, 0x85, 0x02, 0x03, 0x01, 0x01, 0x00, 0x01 };// 连接血压计
|
||
Byte RECEIVE_START_PRESSURE[] = { 0xaa, 0x85, 0x02, 0x03, 0x01, 0x02, 0x00, 0x02 };// 开始测量
|
||
Byte RECEIVE_STOP_PRESSURE[] = { 0xaa, 0x85, 0x02, 0x03, 0x01, 0x03, 0x00, 0x03 };// 停止测量
|
||
Byte RECEIVE_CLOSE_PRESSURE[] = { 0xaa, 0x85, 0x02, 0x03, 0x01, 0x04, 0x00, 0x04 };// 关仪器
|
||
Byte RECEIVE_RESULT[] = { 0xaa, 0x85, 0x02, 0x0f, 0x01};// 接收结果
|
||
|
||
Byte error_state_a = 0x01;// 请检查血压计佩戴是否正确
|
||
Byte error_state_b = 0x02;// 血压计袖带过松或漏气
|
||
Byte error_state_c = 0x04;// 请保持安静 ,重新测量
|
||
Byte error_state_d = 0x07;// 血压计电量低,请充电
|
||
Byte error_state_e = 0x15;// 测量出错,请重新测量 EE21
|
||
@implementation ENBPDevice{
|
||
BOOL _connected;
|
||
NSArray *_characteristics;
|
||
}
|
||
-(id)initWithPeripheral:(CBPeripheral *)peripheral WithCentralManager:(CBCentralManager *)centerManager WithDevice:(BLEDevice *)device{
|
||
self = [super initWithPeripheral:peripheral WithCentralManager:centerManager WithDevice:device];
|
||
if(self){
|
||
_connected = NO;
|
||
}
|
||
return self;
|
||
}
|
||
|
||
/**
|
||
* 4.发现外围服务
|
||
*
|
||
* @param peripheral 外围设备
|
||
* @param error 错误信息
|
||
*/
|
||
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
|
||
if (error){
|
||
NSLog(@"didDiscoverServices : %@", [error localizedDescription]);
|
||
// [self cleanup];
|
||
return;
|
||
}
|
||
|
||
for (CBService * service in _peripheral.services) {
|
||
/**
|
||
* 查找自己需要的UUID的服务
|
||
*/
|
||
if ([[_device.advertisementData[@"kCBAdvDataServiceUUIDs"] firstObject] isEqual:service.UUID]) {
|
||
|
||
/**
|
||
* 查找外围设备特性
|
||
*/
|
||
[_peripheral discoverCharacteristics:nil forService:service];
|
||
return;
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 5.发现外围设备特性
|
||
*
|
||
* @param peripheral 外围设备
|
||
* @param service 外围设备服务
|
||
* @param error 错误信息
|
||
*/
|
||
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{
|
||
if (error){
|
||
NSLog(@"didDiscoverCharacteristicsForService error : %@", [error localizedDescription]);
|
||
return;
|
||
}
|
||
|
||
_characteristics = service.characteristics;
|
||
/**
|
||
* 开启通知(外围设备发数据能收到) service.characteristics 里面两个FFF1(通知的) FFF2(写入的)
|
||
*/
|
||
|
||
[_peripheral setNotifyValue:YES forCharacteristic:[service.characteristics firstObject]];
|
||
|
||
[_peripheral writeValue:[NSData dataWithBytes:SEND_CONNECT_PRESSURE length:8] forCharacteristic:[service.characteristics lastObject] type:CBCharacteristicWriteWithoutResponse];
|
||
}
|
||
|
||
/**
|
||
* 6.发送数据到外围设备回调
|
||
*
|
||
* @param peripheral 外围设备
|
||
* @param characteristic 外围设备特性
|
||
* @param error 错误信息
|
||
*/
|
||
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
|
||
{
|
||
NSLog(@"%@---",error);
|
||
}
|
||
|
||
/**
|
||
* 6.外围设备发送数据到蓝牙中心
|
||
*
|
||
* @param peripheral 外围设备
|
||
* @param characteristic 外围设备特性
|
||
* @param error 错误信息
|
||
*/
|
||
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
|
||
{
|
||
// byte error_state_a = 0x01;// 请检查血压计佩戴是否正确
|
||
// byte error_state_b = 0x02;// 血压计袖带过松或漏气
|
||
// byte error_state_c = 0x04;// 请保持安静 ,重新测量
|
||
// byte error_state_d = 0x07;// 血压计电量低,请充电
|
||
// // byte error_state_e = 0x15;// 测量出错,请重新测量 EE21
|
||
|
||
NSData *data = characteristic.value;
|
||
Byte * byte = (Byte *)[data bytes];
|
||
|
||
//判断是否是连接
|
||
{
|
||
NSData * connectData = [NSData dataWithBytes:RECEIVE_CONNECT_PRESSURE length:8];
|
||
BOOL flag = NO;
|
||
if (connectData.length == data.length) {
|
||
for (int i=0; i<connectData.length; i++) {
|
||
if (RECEIVE_CONNECT_PRESSURE[i] != byte[i]) {
|
||
flag = YES;
|
||
break;
|
||
}
|
||
}
|
||
}else{
|
||
flag = YES;
|
||
}
|
||
|
||
if(!flag){
|
||
_connected = YES;
|
||
if([self.deviceDelegate respondsToSelector:@selector(onConnectedBPWithDevice:)]){
|
||
[(id)self.deviceDelegate onConnectedBPWithDevice:_device];
|
||
};
|
||
return;
|
||
}
|
||
}
|
||
|
||
//获取电池电量
|
||
{
|
||
NSData * powerData = [NSData dataWithBytes:RECEIVE_CHECK_POWER_PRESSURE length:6];
|
||
BOOL power = YES;
|
||
if (data.length >= powerData.length) {
|
||
for (NSInteger i = 0; i<powerData.length; i++) {
|
||
if (RECEIVE_CHECK_POWER_PRESSURE[i] != byte[i]) {
|
||
power = NO;
|
||
break;
|
||
}
|
||
}
|
||
|
||
}else{
|
||
power = NO;
|
||
}
|
||
|
||
if(power){
|
||
NSMutableArray * array = [NSMutableArray array];
|
||
|
||
for(int i=0;i<[data length];i++){
|
||
NSString *newHexStr = [NSString stringWithFormat:@"%x",byte[i]]; ///16进制数
|
||
if([newHexStr length]==1){
|
||
newHexStr = [NSString stringWithFormat:@"0%@",newHexStr];
|
||
}
|
||
|
||
[array addObject:newHexStr];
|
||
}
|
||
|
||
/** 计算电池电量 */
|
||
unsigned long batteryPower = strtoul([[NSString stringWithFormat:@"%@%@",array[array.count - 3],array[array.count - 2]] UTF8String], 0, 16);
|
||
NSLog(@"%ld",strtoul([[NSString stringWithFormat:@"%@%@",array[array.count - 3],array[array.count - 2]] UTF8String], 0, 16));
|
||
|
||
if(batteryPower<3600){
|
||
dispatch_async(dispatch_get_main_queue(), ^{
|
||
if([self.deviceDelegate respondsToSelector:@selector(onLowPowerWithDevice:)]){
|
||
[(id)self.deviceDelegate onLowPowerWithDevice:_device];
|
||
}
|
||
});
|
||
return;
|
||
}
|
||
|
||
|
||
// 发送消息到外围设备
|
||
[_peripheral writeValue:[NSData dataWithBytes:SEND_START_PRESSURE length:8] forCharacteristic:[_characteristics lastObject] type:CBCharacteristicWriteWithoutResponse];
|
||
|
||
dispatch_async(dispatch_get_main_queue(), ^{
|
||
if([self.deviceDelegate respondsToSelector:@selector(onBatteryPower:WithDevice:)]){
|
||
[(id)self.deviceDelegate onBatteryPower:batteryPower WithDevice:_device];
|
||
}
|
||
});
|
||
|
||
|
||
return;
|
||
}
|
||
|
||
}
|
||
|
||
//血压过程数据
|
||
{
|
||
if (data.length == 13) {
|
||
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(onDeviceStopTest) object:nil];
|
||
|
||
NSMutableArray * array = [NSMutableArray array];
|
||
for(int i=0;i<[data length];i++){
|
||
NSString *newHexStr = [NSString stringWithFormat:@"%d",byte[i]]; ///10进制数
|
||
if([newHexStr length]==1){
|
||
newHexStr = [NSString stringWithFormat:@"0%@",newHexStr];
|
||
}
|
||
|
||
[array addObject:newHexStr];
|
||
}
|
||
// int d5 = UtilityBase.toTenInt(dataList
|
||
// .get(totalSize - 7));
|
||
// NSLog(@"%@",array);
|
||
NSInteger d4 = [array[array.count - 6] integerValue];
|
||
// int d3 = UtilityBase.toTenInt(dataList
|
||
// .get(totalSize - 5));
|
||
// int d2 = UtilityBase.toTenInt(dataList
|
||
// .get(totalSize - 4));
|
||
NSInteger d1 = [array[array.count - 3] integerValue];
|
||
// int d0 = UtilityBase.toTenInt(dataList
|
||
// .get(totalSize - 2));
|
||
NSInteger p = (d4 << 8) + (d4 ^ d1);
|
||
|
||
// self.numLabel.text = [NSString stringWithFormat:@"%03ld",(long)p];
|
||
|
||
[self performSelector:@selector(onDeviceStopTest) withObject:nil afterDelay:6];
|
||
dispatch_async(dispatch_get_main_queue(), ^{
|
||
if([self.deviceDelegate respondsToSelector:@selector(onProgressValue:WithDevice:)]){
|
||
[(id)self.deviceDelegate onProgressValue:p WithDevice:_device];
|
||
}
|
||
});
|
||
return;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
//血压测量结果
|
||
{
|
||
if(data.length == 20){
|
||
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(onDeviceStopTest) object:nil];
|
||
NSData * resultData = [NSData dataWithBytes:RECEIVE_RESULT length:5];
|
||
if (data.length >= resultData.length) {
|
||
|
||
for (NSInteger i = 0; i<resultData.length; i++) {
|
||
if (RECEIVE_RESULT[i] != byte[i]) {
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
// [self.noResponseTime invalidate];
|
||
// self.noResponseTime = nil;
|
||
NSMutableArray * array = [NSMutableArray array];
|
||
|
||
for(NSInteger i=0;i<[data length];i++){
|
||
NSString *newHexStr = [NSString stringWithFormat:@"%d",byte[i]]; ///10进制数
|
||
|
||
[array addObject:newHexStr];
|
||
}
|
||
NSInteger pul_0 = [array[array.count - 2] integerValue];
|
||
NSInteger pul_1 = [array[array.count - 3] integerValue];
|
||
NSInteger dia_0 = [array[array.count - 4] integerValue];
|
||
NSInteger dia_1 = [array[array.count - 5] integerValue];
|
||
NSInteger sys_0 = [array[array.count - 6] integerValue];
|
||
NSInteger sys_1 = [array[array.count - 7] integerValue];
|
||
|
||
NSInteger pul = pul_1 ^ pul_0; // 脉搏
|
||
NSInteger dia = dia_1 ^ dia_0; // 舒张压
|
||
NSInteger sys = sys_1 ^ sys_0; // 收缩压
|
||
|
||
NSString *result= [NSString stringWithFormat:@"脉搏:%ld舒张压:%ld收缩压:%ld",(long)pul,(long)dia,(long)sys];
|
||
NSLog(@"result:%@",result);
|
||
// [self saveAndPostWithPul:pul andDia:dia andSys:sys];
|
||
NSDictionary *info = @{
|
||
@"pul":@(pul),
|
||
@"dia":@(dia),
|
||
@"sys":@(sys)
|
||
};
|
||
|
||
dispatch_async(dispatch_get_main_queue(), ^{
|
||
[(id)self.deviceDelegate onResult:info WithDevice:_device];
|
||
});
|
||
|
||
return;
|
||
}
|
||
}
|
||
|
||
//血压测量错误
|
||
{
|
||
if (data.length == 8){
|
||
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(onDeviceStopTest) object:nil];
|
||
NSData * stopCheckData = [NSData dataWithBytes:RECEIVE_STOP_PRESSURE length:8];
|
||
BOOL flag1 = NO;
|
||
BOOL flag2 = NO;
|
||
if (stopCheckData.length == data.length) {
|
||
for (int i=0; i<stopCheckData.length; i++) {
|
||
if (RECEIVE_STOP_PRESSURE[i] != byte[i]) {
|
||
flag1 = YES;
|
||
// break;
|
||
}
|
||
|
||
if (RECEIVE_CLOSE_PRESSURE[i] != byte[i]) {
|
||
flag2 = YES;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (flag1 == NO || flag2 == NO) {
|
||
// self.startCheck = NO;
|
||
// [self.noResponseTime invalidate];
|
||
// self.noResponseTime = nil;
|
||
}
|
||
|
||
// 血压测量异常错误提示
|
||
BOOL error = NO;
|
||
NSString *errorInfo;
|
||
if(byte[6] == error_state_a) // EE1
|
||
{
|
||
// [MBProgressHUD showLineMessage:@"请检查血压计佩戴是否正确"];
|
||
errorInfo = @"请检查血压计佩戴是否正确";
|
||
error = YES;
|
||
}else if (byte[6] == error_state_b) // EE2
|
||
{
|
||
// [MBProgressHUD showLineMessage:@"血压计袖带过松或漏气"];
|
||
errorInfo = @"血压计袖带过松或漏气";
|
||
error = YES;
|
||
}else if (byte[6] == error_state_c) // EE4
|
||
{
|
||
// [MBProgressHUD showLineMessage:@"请保持安静重新测量"];
|
||
errorInfo = @"请保持安静重新测量";
|
||
error = YES;
|
||
}else if (byte[6] == error_state_d) // EE7
|
||
{
|
||
// [MBProgressHUD showLineMessage:@"血压计电量低,请充电"];
|
||
errorInfo = @"血压计电量低,请充电";
|
||
error = YES;
|
||
} else if (byte[6] == error_state_e) { // EE21
|
||
// [MBProgressHUD showLineMessage:@"测量出错,请重新测量"];
|
||
errorInfo = @"测量出错,请重新测量";
|
||
error = YES;
|
||
}
|
||
|
||
if (error) {
|
||
// self.startCheck = NO;
|
||
// [self.noResponseTime invalidate];
|
||
// self.noResponseTime = nil;
|
||
// [self back];
|
||
dispatch_async(dispatch_get_main_queue(), ^{
|
||
if([self.deviceDelegate respondsToSelector:@selector(onError:WithDevice:)]){
|
||
[(id)self.deviceDelegate onError:errorInfo WithDevice:_device];
|
||
};
|
||
});
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
}
|
||
|
||
/* 开始测量 */
|
||
-(void)startTest{
|
||
if(_peripheral == nil || _characteristics == nil){
|
||
return;
|
||
}
|
||
|
||
if(_characteristics.count <= 0){
|
||
return;
|
||
}
|
||
|
||
[_peripheral writeValue:[NSData dataWithBytes:SEND_CHECK_POWER_PRESSURE length:8] forCharacteristic:[_characteristics lastObject] type:CBCharacteristicWriteWithoutResponse];
|
||
|
||
}
|
||
|
||
/** 停止测量 */
|
||
-(void)stopTest{
|
||
if(_peripheral == nil || _characteristics == nil){
|
||
return;
|
||
}
|
||
|
||
if(_characteristics.count <= 0){
|
||
return;
|
||
}
|
||
|
||
dispatch_async([[ENBLEDeviceManager shareDeviceManager] getPostQueue], ^{
|
||
[_peripheral writeValue:[NSData dataWithBytes:SEND_STOP_PRESSURE length:8] forCharacteristic:[_characteristics lastObject] type:CBCharacteristicWriteWithoutResponse];
|
||
});
|
||
}
|
||
|
||
|
||
-(void)onDeviceStopTest{
|
||
dispatch_async(dispatch_get_main_queue(), ^{
|
||
if([self.deviceDelegate respondsToSelector:@selector(onError:WithDevice:)]){
|
||
[(id)self.deviceDelegate onError:@"设备停止测量" WithDevice:_device];
|
||
}
|
||
});
|
||
}
|
||
|
||
/** 得到设备显示名字 */
|
||
-(NSString *)getDeviceDisplayName{
|
||
return @"脉搏波血压计";
|
||
}
|
||
|
||
|
||
|
||
@end
|