//
// LeDiscovery.h
// JK_xuXuKou
//
// Created by vita on 15/8/25.
// Copyright (c) 2015年 ZZ_Macpro. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <CoreBluetooth/CoreBluetooth.h>
#import <UIKit/UIKit.h>
#import "FMDB.h"
@interface LeDiscovery : NSObject
typedef enum {
temperatureWarning,
peeWarning,
} warningStyle;
- (void)countData;
// 周边设备群
@property (nonatomic, strong) NSMutableArray *peripheralArray;
@property (nonatomic, strong) CBPeripheral *connectPeripheral;
// 发现的周边设备
@property (nonatomic, strong) CBPeripheral *discoveredPeripheral;
// 中央设备管理者
@property (nonatomic, strong) CBCentralManager *manager;
@property (nonatomic, strong) NSString *reciveString;
@property (nonatomic, strong) NSMutableArray *peripheralModelArray;
/**当前温度*/
@property (nonatomic, strong) NSNumber *temperature;
/**当前湿度*/
@property (nonatomic, strong) NSNumber *humidity;
/**当前电量*/
@property (nonatomic, strong) NSNumber *battery;
/**当前时间*/
@property (nonatomic, strong) NSNumber *time;
@property (nonatomic, strong) NSDate *disConnectBluetoothTime; //断开蓝牙的时间
@property (nonatomic, assign) NSInteger clickTimes; //点击蓝牙连接的次数
@property (nonatomic, assign) BOOL isLine; //判断蓝牙是否连接(设备成功)
@property (nonatomic, assign) BOOL preChangePeripheral; //判断是否手动更换连接设备
@property (nonatomic, assign) NSInteger count; //通知的数量
+ (LeDiscovery *) sharedInstance;
/****************************************************************************/
/* Actions */
/****************************************************************************/
- (CBCentralManagerState) startScanningForUUIDString:(NSString *)uuidString;
- (void) stopScanning;
- (void) connectPeripheral:(CBPeripheral*)peripheral;
- (void) disconnectPeripheral:(CBPeripheral*)peripheral;
- (void) centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral;
@end
//
// LeDiscovery.m
// JK_xuXuKou
//
// Created by vita on 15/8/25.
// Copyright (c) 2015年 ZZ_Macpro. All rights reserved.
//
#import <CoreBluetooth/CoreBluetooth.h>
#import "LeDiscovery.h"
#import "MBProgressHUD+MJ.h"
@interface LeDiscovery () <CBCentralManagerDelegate,CBPeripheralDelegate>
@end
@implementation LeDiscovery
#pragma mark --------------------------- 蓝牙设备 ---------------------------
+ (LeDiscovery*) sharedInstance
{
static LeDiscovery *helper;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (helper == nil) {
helper = [[LeDiscovery alloc] init];
}
});
return helper;;
}
- (LeDiscovery*) init
{
self = [super init];
if (self) {
/**
B-1.创建中央设备
*/
_manager =[[CBCentralManager alloc]initWithDelegate:self queue:nil];
/**
B-2.实例化周边设备群(数组)
*/
_peripheralArray = [[NSMutableArray alloc] init];
[self creatSQLite];
}
return self;
}
#pragma mark --------------------------- 蓝牙操作 ---------------------------
/****************************************************************************/
/* 扫描设备 scan/disscan */
/****************************************************************************/
/**
* 检查蓝牙状态
*/
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
if (central.state != CBCentralManagerStatePoweredOn)
{
// NSLog(@"请打开蓝牙!");
_disConnectBluetoothTime = [NSDate date];
return;
}
if (_connectPeripheral) {
[self.manager connectPeripheral:_connectPeripheral options:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] forKey:CBConnectPeripheralOptionNotifyOnDisconnectionKey]];
return;
}
//扫描指定设备
[self startScanningForUUIDString:SERVICE_UUID];
}
/**
* 检测到蓝牙开启,扫描设备
*/
- (CBCentralManagerState) startScanningForUUIDString:(NSString *)uuidString;
{
[_manager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:uuidString]] options:nil];
CBCentralManagerState currentState = [_manager state];
return currentState;
}
/**
* 停止扫描设备
*/
- (void)stopScanning
{
[self.manager stopScan];
// NSLog(@"关闭扫描");
}
/****************************************************************************/
/* 发现设备 Discovery */
/****************************************************************************/
/**
* 3.发现外设
*
* @param central 中央设备
* @param peripheral 周边设备
* @param advertisementData 响应数据
* @param RSSI 信号强度
*/
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
NSUserDefaults *perialUUIDString = [NSUserDefaults standardUserDefaults];
NSString *str = [perialUUIDString objectForKey:@"UUIDString"];
if ([str isEqualToString:peripheral.identifier.UUIDString]) {
[self.manager connectPeripheral:peripheral options:nil];
}
//保存搜索到的设备 到 周边设备数组
if ([_peripheralArray containsObject:peripheral]) {
return;
} else {
[_peripheralArray addObject:peripheral];
}
}
/****************************************************************************/
/* 连接设备 Connection/Disconnection */
/****************************************************************************/
- (void)connectPeripheral:(CBPeripheral*)peripheral
{
if (_connectPeripheral) {
[self.manager cancelPeripheralConnection:_connectPeripheral];
}
[self.manager connectPeripheral:peripheral options:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] forKey:CBConnectPeripheralOptionNotifyOnDisconnectionKey]];
}
- (void)disconnectPeripheral:(CBPeripheral*)peripheral
{
[self.manager cancelPeripheralConnection:peripheral];
}
#pragma mark --------------------------- 连接设备后的操作 ---------------------------
/**
* 5.连接外设成功调用
*/
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
// 停止扫描
_disConnectBluetoothTime = nil;
[_manager stopScan];
_connectPeripheral = peripheral;
// 设置代理
_connectPeripheral.delegate = self;
// 扫描服务
[_connectPeripheral discoverServices:@[[CBUUID UUIDWithString:SERVICE_UUID]]];
// NSLog(@"连接成功");
self.isLine = YES;
NSUserDefaults *perialUUIDString = [NSUserDefaults standardUserDefaults];
[perialUUIDString setObject:peripheral.identifier.UUIDString forKey:@"UUIDString"];
[perialUUIDString synchronize];
}
/**
* 5-1.当已经与peripheral建立的连接断开时调用
*/
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
// NSLog(@"重连中!!!");
self.isLine = NO;
_preChangePeripheral = NO;
NSLog(@"断线重连接!!!");
[self.manager connectPeripheral:_connectPeripheral options:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] forKey:CBConnectPeripheralOptionNotifyOnDisconnectionKey]];
}
/**
* 5-2.当central管理者与peripheral建立连接失败时调用
*/
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
{
// NSLog(@"连接失败,正在重试");
// _disConnectBluetoothTime = [NSDate date];
// [self countDisConnectTime];
self.isLine = NO;
[self startScanningForUUIDString:SERVICE_UUID];
}
/****************************************************************************/
/* 发现设备的服务和特征 Discover Services、Characteristics */
/****************************************************************************/
/**
* 6.发现服务
*/
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
for (CBService *service in peripheral.services)
{
// NSLog(@"服务 UUID: %@", service.UUID);
[_connectPeripheral discoverCharacteristics:nil forService:service];
}
}
/**
* 7.发现特征
*
* @param peripheral 周边设备
* @param service 发现的服务
* @param error 错误信息
*/
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
// 服务UUID匹配
if ([service.UUID isEqual:[CBUUID UUIDWithString:SERVICE_UUID]]) {
for (CBCharacteristic *characteristic in service.characteristics)
{
// 特征UUID匹配
// NSLog(@"特征 UUID: %@", characteristic.UUID);
// 开启监听 开启了才能执行下面的接受数据
if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:CHARACTERISTIC02_UUID]]) {
uint8_t value[] = {0x55, 0x03};
[_connectPeripheral writeValue:[NSData dataWithBytes:&value length:sizeof(value)] forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];
}
if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:CHARACTERISTIC01_UUID]]) {
[_connectPeripheral setNotifyValue:YES forCharacteristic:characteristic];
}
}
}
}
/****************************************************************************/
/* 接收数据 */
/****************************************************************************/
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
if (error) {
// NSLog(@"didWriteValueForCharacteristic error:%@",error.description);
}
}
/**
* 8.接收数据
*
* @param peripheral 外部设备
* @param characteristic 外设特征
* @param error 错误信息
*/
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
if (error)
{
NSLog(@"didUpdateValueForCharacteristic error : %@", error.localizedDescription);
return;
}
// NSLog(@"设备 :%@ %@",self.connectPeripheral.identifier.UUIDString,peripheral.identifier.UUIDString);
if([characteristic.UUID isEqual:[CBUUID UUIDWithString:CHARACTERISTIC01_UUID]]){
if (characteristic.value.length > 7) {
//将接收到的十六进制数据 转成 十六进制字符串
NSString *reciveString = [NSString stringWithFormat:@"%@", [self hexadecimalString:characteristic.value]];
NSUserDefaults *productDefault = [NSUserDefaults standardUserDefaults];
NSString *productNumber = [reciveString substringWithRange:NSMakeRange(7, 17)];
[productDefault setObject:productNumber forKey:@"productNumber"];
[productDefault synchronize];
}else{
//将接收到的十六进制数据 转成 十六进制字符串
NSString *reciveString = [NSString stringWithFormat:@"%@", [self hexadecimalString:characteristic.value]];
if (characteristic.value) {
self.isLine = YES;
} else {
self.isLine = NO;
}
// NSLog(@"%@",reciveString);
//转成十进制数字 并 打印
[self transformDataWithString:reciveString];
}
}
}
/**
* 8-1.十六进制Data 转成 十六进制字符串
*/
- (NSString *)hexadecimalString :(NSData *)data
{
/* Returns hexadecimal string of NSData. Empty string if data is empty. */
const unsigned char *dataBuffer = (const unsigned char *)[data bytes];
if (!dataBuffer)
return [NSString string];
NSUInteger dataLength = [data length];
NSMutableString *hexString = [NSMutableString stringWithCapacity:(dataLength * 2)];
for (int i = 0; i < dataLength; ++i)
[hexString appendString:[NSString stringWithFormat:@"%02lx", (unsigned long)dataBuffer[i]]];
return [NSString stringWithString:hexString];
}
/**
* 8-2.十六进制字符串转成数字
*
* @param str 十六进制字符串
*/
- (void)transformDataWithString: (NSString*)str
{
//记录当前时间
_time = [NSNumber numberWithLongLong:[self countCurrentDay]];
//接收的数据长度 为 14(温度、湿度) 或者 8(电池电量),数据发送顺序为 14、14、8、14、14、8......
if (str.length > 8) {
//当前温度数据
_temperature = [NSNumber numberWithInteger: strtoul([[str substringWithRange:NSMakeRange(4, 4)] UTF8String],0,16)];
//当前湿度数据
_humidity = [NSNumber numberWithInteger: strtoul([[str substringWithRange:NSMakeRange(8, 4)] UTF8String],0,16) ];
[self insertSQLite:_temperature :_humidity :_battery :_time];
} else{
//电池电量数据
_battery = [NSNumber numberWithInteger: strtoul([[str substringWithRange:NSMakeRange(4, 2)] UTF8String],0,16)];
}
}
#pragma mark --------------------------- 将NSDate 直接转成 yyyyMMddHHmmss ---------------------------
//计算当前日期
- (long long) countCurrentDay
{
NSDateFormatter *dateformatter=[[NSDateFormatter alloc] init];
[dateformatter setDateFormat:@"yyyyMMddHHmmss"];
NSString *today = [NSString stringWithFormat:@"%lld",[[dateformatter stringFromDate:[NSDate date]] longLongValue]];
long long now = [today longLongValue];
return now;
}
//计算断开连接时间
- (NSInteger)countDisConnectTime
{
if (!_disConnectBluetoothTime)
return 0;
else{
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSCalendarUnit unitFlags = NSMinuteCalendarUnit;
NSDateComponents *time = [calendar components:unitFlags fromDate:_disConnectBluetoothTime toDate:[NSDate date] options:0];
if(_connectPeripheral.state == CBPeripheralStateDisconnected)
return [time minute];
else
return 0;
}
}
@end