蓝牙编程
最近公司新来了一部蓝牙小票机器,需要对其进行编程,所以 阅读起了iOS蓝牙编程的官方文档,昨日测试成功,想写下点心得,方便以后查看。言归正传。iOS的蓝牙框架是支持蓝牙4.0协议的。
理解iOS CoreBluetooth两个很重要的概念,Central 和 Periperal Devices
这两个概念可以用传统的模式client-server来理解,central意思是中心,其作用类似server,periperal就是外设,一般携带有数据,我们需要去其中获取数据,下图是苹果官网的例子,peripheral是心跳仪,按期作用,我们去这个外设中取心跳数据,则心跳仪的作用就类似server了,我们的手机去心跳仪中获取数据,类似client。
Peripheral如何让central知道它的存在呢?peripheral.比如上图的心跳仪,通过不断广播自己的存在,并且在广播过程中附带广告包(advertising packet),不知道这样翻译是否正确,不对请指正一下。如同好像有个设备在喊,Here~我是心跳仪器,我是心跳仪器,这是我提供的服务(广告包)。Central发现有个设备在呐喊,就说:“那我看看需不需要你提供服务,拿来我看看”。这样你就发现了这个设备,并且获取到它提供的服务。<img style="width: 630px; height: 88.0349px;" src="http://www.2cto.com/uploadfile/Collfiles/20141201/2014120109200052.png" alt="" http:="" www.2cto.com="" kf="" ware="" vc="" "="" target="_blank" class="keylink">vcHL1eK49nBlcmlwaGVyYWyjrL3T18XE473Qy/y747Goy/zM4bmptcS3/s7xo6zV4rj2cGVyaXBoZXJhbLvhu+OxqMv509C3/s7xuPjE46GjscjI59DEzPjSx8b3zOG5qcG91tZzZXJ2aWNlo6zJ6LG40MXPonNlcnZpY2XT68r9vt278cihc2VydmljZS7V4tH5xOO+zdaqtcDT0MTEvLjW1rf+zvHBy6GjCjMuyLu688Tjv8nS1LbUxOO40NDLyKS1xLf+zvG9+NDQstnX96GjscjI587Sw8e21Mr9vt278cihtcS3/s7xuNDQy8iko6zO0r7NttTV4rj2u/HIobXEt/7O8cu1o6y4+M7SxOO1xMv509C1xGNoYXJhY3RlcmlzY3Msy/nT0LXEzNjV96GjvNnJ6NXiyrG68sv8t7W72MG9uPbM2NX3o6zSu7j2ysfQxMz4yv2+3bXEY2hhcmFjdGVyaXN0aWMswe3N4tK7uPbKx9DEzPjRucGmyv2+3aOoz7mx4LXEo6mho8Tjvs2/ydLUttTG5MzY1fe9+NDQtsHQtLLZ1/ejrNXiwO+78cihstnX96Osvs3Kx7bBstnX96Gju/HIobW9ttTTpsr9vt3UtM23Cjxicj4KCr+00rvPwsC019S52c34tcS94bm5zbwKPGltZyBzcmM9"http://www.2cto.com/uploadfile/Collfiles/20141201/2014120109200053.png" alt="\">
介绍完这些概念,我们来看看实际代码应该如何填写.这里对于我的蓝牙小票机来编写的,因为我要对蓝牙小票机器进行写操作,手机是搜索peripharal的,所以手机为central,小票机为peripharal1.首先导入这个框架2.该框架有主要有几个类值得我们注意,CBCentralManager,也就是我们之前提到的Central,可以用来发现外设的。
|
#
import
<corebluetooth corebluetooth.h=
""
>
@interface
ViewController () <cbcentralmanagerdelegate>
@property
(nonatomic, retain) CBCentralManager *centralManager;
@end
@implementation
ViewController
- (
void
)viewDidLoad {
[
super
viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
}</cbcentralmanagerdelegate></corebluetooth>
|
1
|
|
|
/*
Invoked whenever the central manager's state is updated.
*/
- (
void
)centralManagerDidUpdateState:(CBCentralManager *)central
{
NSString * state = nil;
switch
([central state])
{
case
CBCentralManagerStateUnsupported:
state = @
"The platform/hardware doesn't support Bluetooth Low Energy."
;
break
;
case
CBCentralManagerStateUnauthorized:
state = @
"The app is not authorized to use Bluetooth Low Energy."
;
break
;
case
CBCentralManagerStatePoweredOff:
state = @
"Bluetooth is currently powered off."
;
break
;
case
CBCentralManagerStatePoweredOn:
state = @
"work"
;
break
;
case
CBCentralManagerStateUnknown:
default
:
;
}
NSLog(@
"Central manager state: %@"
, state);
}
|
3.现在可以连接扫描外设了
- (IBAction)scan:(id)sender {
[self.centralManager scanForPeripheralsWithServices:nil options:nil];
}
|
这个方法如果传入的事nil,代表扫描所有外设。
|
- (IBAction)scan:(id)sender {
[self.centralManager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:@
"FFE0"
]] options:nil];
}
|
- (
void
)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
static
int
i =
0
;
NSString *str = [NSString stringWithFormat:@
"Did discover peripheral. peripheral: %@ rssi: %@, UUID: %@ advertisementData: %@ "
, peripheral, RSSI, peripheral.UUID, advertisementData];
NSLog(@
"%@"
,str);
[self.discoverdPeriparals addObject:peripheral];
}
|
从广播数据中可以看到一个服务UUIDs,因为广播数据有数量大小限制,数据比较少。不过目前我们只是发现了这个设备,假设该设备已经是我们感兴趣的设备,你可以通过[self.centralManager stopScan]来停止扫描,也可以继续扫描。
4.连接发现的外设
- (IBAction)connect:(id)sender {
[self.centralManager connectPeripheral:[self.discoverdPeriparals firstObject] options:nil];
}
|
1
|
|
1
2
3
4
5
6
7
8
9
10
11
|
/*
Invoked whenever a connection is succesfully created with the peripheral.
Discover available services on the peripheral
*/
- (
void
)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
NSLog(@
"Did connect to peripheral: %@"
, peripheral);
peripheral.delegate = self;
[central stopScan];
[peripheral discoverServices:nil];
}
|
1
|
<span style=
"font-size:18px;"
>[peripheral discoverServices:@[[CBUUID UUIDWithString:@
"FFE0"
]]];</span>
|
- (
void
)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
if
(error)
{
NSLog(@
"Discovered services for %@ with error: %@"
, peripheral.name, [error localizedDescription]);
return
;
}
for
(CBService *service in peripheral.services)
{
NSLog(@
"Service found with UUID: %@"
, service.UUID);
if
([service.UUID isEqual:[CBUUID UUIDWithString:@
"FFE0"
]])
{
[peripheral discoverCharacteristics:nil forService:service];
}
}
}
|
这里看到返回了两个服务,因为需要FFE0,所以让该服务返回对应的characteristics.
1
|
[peripheral discoverCharacteristics:nil forService:service];
|
|
- (
void
)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
{
if
(error)
{
NSLog(@
"Discovered characteristics for %@ with error: %@"
, service.UUID, [error localizedDescription]);
return
;
}
for
(CBCharacteristic * characteristic in service.characteristics)
{
DLog(@
"%@"
,<span style=
"font-family: Arial, Helvetica, sans-serif;"
>characteristic</span>);
if
( [characteristic.UUID isEqual:[CBUUID UUIDWithString:@
"FFE1"
]])
{
self.p = peripheral;
self.c = characteristic;
//read
//[testPeripheral readValueForCharacteristic:characteristic];
NSLog(@
"Found a Device Manufacturer Name Characteristic - Read manufacturer name"
);
}
}
}
|
|
- (
void
)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSString *RStr = @
"2764"
;
NSMutableString *str = [NSMutableString
new
];
[str appendFormat:@
"%c"
,
28
];
[str appendFormat:@
"%c"
,
33
];
[str appendFormat:@
"%c"
,
8
];
[self.p writeValue:[str dataUsingEncoding:CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000)] forCharacteristic:self.c type:CBCharacteristicWriteWithResponse];
RStr = @
"吴水凤 你好呀!!!\n\n\n\n\n\n\n\n"
;
[self.p writeValue:[RStr dataUsingEncoding:CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000)] forCharacteristic:self.c type:CBCharacteristicWriteWithResponse];
}
|
补充: 如果该特征是可以读特征,你可以对该特征进行订阅。
[peripheral setNotifyValue:YES forCharacteristic:interestingCharacteristic];
该方法回调peripheral:didUpdateValueForCharacteristic:error:方法
1
|
|
如果想要了解更多,建议查看iOS官方文档提供的CoreBluetooth programming guid.小弟就写到这了。