Skip to content

Instantly share code, notes, and snippets.

@t-kashima
Created March 29, 2013 02:51
Show Gist options
  • Save t-kashima/5268425 to your computer and use it in GitHub Desktop.
Save t-kashima/5268425 to your computer and use it in GitHub Desktop.
//
// ViewController.h
// Bluetooth
//
#import <UIKit/UIKit.h>
#import <CoreBluetooth/CoreBluetooth.h>
@interface ViewController : UIViewController <CBCentralManagerDelegate, CBPeripheralManagerDelegate, CBPeripheralDelegate>
@property (weak, nonatomic) IBOutlet UITextView *textView;
- (IBAction)actionConnect:(id)sender;
- (IBAction)actionPeripheral:(id)sender;
@end
//
// ViewController.m
// Bluetooth
//
#import "ViewController.h"
@interface ViewController ()
@property (strong, nonatomic) CBCentralManager *centralManager;
@property (strong, nonatomic) CBPeripheralManager *peripheralManager;
@property (strong, nonatomic) CBPeripheral *aPeripheral;
@property (strong, nonatomic) NSData *dataToSend;
@property (nonatomic, readwrite) NSInteger sendDataIndex;
@property (strong, nonatomic) CBMutableCharacteristic *transferCharacteristic;
@property (strong, nonatomic) NSMutableData *receivedData;
@end
#define ADVERTISEMENT_NAME @"TestApp"
#define SERVICE_ID @"2145B0A7-CC2E-49C2-BCCA-B55A703CD030"
#define CHARASTERISTIC_ID @"B4DA0427-EE1D-4D16-8BC8-4B95EA15D0C0"
#define MAX_MTU 20
@implementation ViewController
@synthesize textView;
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (IBAction)actionConnect:(id)sender
{
[self startScan];
}
- (IBAction)actionPeripheral:(id)sender
{
[self startPeripheral];
}
-(void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral {
switch(peripheral.state) {
case CBPeripheralManagerStatePoweredOn:
[self setupService];
break;
default:
NSLog(@"Peripheral Manager did change state");
break;
}
}
- (void)setupService
{
CBMutableService *service = [[CBMutableService alloc]
initWithType:[CBUUID UUIDWithString:SERVICE_ID]
primary:YES];
self.transferCharacteristic =
[[CBMutableCharacteristic alloc]
initWithType:[CBUUID UUIDWithString:CHARASTERISTIC_ID]
properties:CBCharacteristicPropertyNotify
value:nil
permissions:CBAttributePermissionsReadable];
service.characteristics = @[self.transferCharacteristic];
[self.peripheralManager addService:service];
}
- (void)peripheralManager:(CBPeripheralManager *)peripheral
central:(CBCentral *)central
didSubscribeToCharacteristic:(CBCharacteristic *)characteristic
{
self.dataToSend = [@"Hello, world!" dataUsingEncoding:NSUTF8StringEncoding];
self.sendDataIndex = 0;
[self sendData];
}
- (void)sendData
{
static BOOL sendingEOM = NO;
if (sendingEOM) {
BOOL didSend = [self.peripheralManager updateValue:[@"EOM" dataUsingEncoding:NSUTF8StringEncoding]
forCharacteristic:self.transferCharacteristic
onSubscribedCentrals:nil];
if (didSend) {
sendingEOM = NO;
NSLog(@"Sent:EOM");
}
return;
}
if (self.sendDataIndex >= self.dataToSend.length) {
return;
}
BOOL didSend = YES;
while(didSend) {
NSInteger amountToSend = self.dataToSend.length - self.sendDataIndex;
if (amountToSend > MAX_MTU) {
amountToSend = MAX_MTU;
}
NSData *chunk = [NSData dataWithBytes:(self.dataToSend.bytes + self.sendDataIndex) length:amountToSend];
didSend = [self.peripheralManager updateValue:chunk forCharacteristic:self.transferCharacteristic onSubscribedCentrals:nil];
if (!didSend) {
return;
}
self.sendDataIndex += amountToSend;
NSLog(@"Sending: %d / %d", self.sendDataIndex, self.dataToSend.length);
if (self.sendDataIndex >= self.dataToSend.length) {
sendingEOM = YES;
BOOL eomSent = [self.peripheralManager updateValue:[@"EOM" dataUsingEncoding:NSUTF8StringEncoding] forCharacteristic:self.transferCharacteristic onSubscribedCentrals:nil];
if (eomSent) {
sendingEOM = NO;
NSLog(@"Sent: EOM");
}
return;
}
}
}
- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic
{
NSLog(@"Central unsubscribed from characteristic");
}
- (void)peripheralManagerIsReadyToUpdateSubscribers:(CBPeripheralManager *)peripheral
{
NSLog(@"isReadyRestart");
[self sendData];
}
- (void)peripheralManager:(CBPeripheralManager *)peripheral
didAddService:(CBService *)service
error:(NSError *)error
{
if (error != nil) {
return;
}
NSLog(@"Start advertising.");
[self.peripheralManager startAdvertising:@{CBAdvertisementDataLocalNameKey: ADVERTISEMENT_NAME,
CBAdvertisementDataServiceUUIDsKey: @[[CBUUID UUIDWithString:SERVICE_ID]]}];
}
- (void)startPeripheral
{
self.peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil];
}
- (void)startScan
{
self.receivedData = [[NSMutableData alloc] init];
self.centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
}
- (void)centralManager:(CBCentralManager *)central
didDiscoverPeripheral:(CBPeripheral *)peripheral
advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
{
NSLog(@"Peripheral discovered %@ %@ %@", RSSI, peripheral.UUID, advertisementData);
if ([[advertisementData objectForKey:@"kCBAdvDataLocalName"] isEqual:ADVERTISEMENT_NAME]) {
[self.centralManager stopScan];
self.aPeripheral = peripheral;
[self.centralManager connectPeripheral:peripheral options:nil];
}
}
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
NSLog(@"centralManagerDidConnectPeripheral");
[self.aPeripheral setDelegate:self];
[self.aPeripheral discoverServices:@[[CBUUID UUIDWithString:SERVICE_ID]]];
}
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
{
NSLog(@"DiscoverService:%d", [peripheral.services count]);
if (error) {
NSLog(@"Error discovering service: %@", [error localizedDescription]);
return;
}
for (CBService *service in peripheral.services) {
NSLog(@"Service found with UUID: %@", service.UUID);
if ([service.UUID isEqual:[CBUUID UUIDWithString:SERVICE_ID]]) {
[self.aPeripheral discoverCharacteristics:@[[CBUUID UUIDWithString:CHARASTERISTIC_ID]] forService:service];
}
}
}
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
NSLog(@"DiscoverCharacteristics");
if (error) {
NSLog(@"Error discovering characteristic: %@", [error localizedDescription]);
return;
}
if ([service.UUID isEqual:[CBUUID UUIDWithString:SERVICE_ID]]) {
for (CBCharacteristic *characteristic in service.characteristics) {
if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:CHARASTERISTIC_ID]]) {
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
}
}
}
}
- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
if (error) {
NSLog(@"Error changing notification state: %@", error.localizedDescription);
}
if (![characteristic.UUID isEqual:[CBUUID UUIDWithString:CHARASTERISTIC_ID]]) {
return;
}
if (characteristic.isNotifying) {
NSLog(@"Notification began on %@", characteristic);
} else {
NSLog(@"Notification stopped on %@. Disconnecting", characteristic);
[self.centralManager cancelPeripheralConnection:self.aPeripheral];
}
}
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
{
if (error) {
NSLog(@"Error changing reading request: %@", error.localizedDescription);
}
NSLog(@"Received response.");
NSString *stringFromData = [[NSString alloc] initWithData:characteristic.value encoding:NSUTF8StringEncoding];
if ([stringFromData isEqualToString:@"EOM"]) {
NSLog(@"EOM");
NSString *string = [[NSString alloc] initWithData:self.receivedData encoding:NSUTF8StringEncoding];
textView.text = string;
NSLog(@"Loading a data: %@", string);
[peripheral setNotifyValue:NO forCharacteristic:characteristic];
[self.centralManager cancelPeripheralConnection:peripheral];
}
[self.receivedData appendData:characteristic.value];
NSLog(@"Received data length: %d", [self.receivedData length]);
}
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
{
switch (central.state) {
case CBCentralManagerStatePoweredOn:
NSLog(@"Scanning...");
[self.centralManager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:SERVICE_ID]]
options:@{CBCentralManagerScanOptionAllowDuplicatesKey:@(YES)}];
break;
default:
NSLog(@"Failed getting a Bluetooth.");
break;
}
}
@end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment