1369 lines
48 KiB
Plaintext
1369 lines
48 KiB
Plaintext
//
|
|
// UnityBluetoothLE.h
|
|
// Unity-iPhone
|
|
//
|
|
// Created by Tony Pitman on 03/05/2014.
|
|
//
|
|
//
|
|
|
|
#import "UnityBluetoothLE.h"
|
|
|
|
const char _messageDelimeter = '~';
|
|
|
|
extern "C" {
|
|
|
|
UnityBluetoothLE *_unityBluetoothLE = nil;
|
|
|
|
void _iOSBluetoothLELogString (NSString *message) {
|
|
|
|
NSLog (message);
|
|
}
|
|
|
|
void _iOSBluetoothLELog (char *message) {
|
|
|
|
_iOSBluetoothLELogString ([NSString stringWithFormat:@"%s", message]);
|
|
}
|
|
|
|
void _iOSBluetoothLEInitialize (BOOL asCentral, BOOL asPeripheral) {
|
|
|
|
_unityBluetoothLE = [UnityBluetoothLE new];
|
|
[_unityBluetoothLE initialize:asCentral asPeripheral:asPeripheral];
|
|
}
|
|
|
|
void _iOSBluetoothLEDeInitialize () {
|
|
|
|
if (_unityBluetoothLE != nil) {
|
|
|
|
[_unityBluetoothLE deInitialize];
|
|
[_unityBluetoothLE release];
|
|
_unityBluetoothLE = nil;
|
|
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", "DeInitialized");
|
|
}
|
|
}
|
|
|
|
void _iOSBluetoothLEPauseMessages (BOOL pause) {
|
|
|
|
if (_unityBluetoothLE != nil)
|
|
[_unityBluetoothLE pauseMessages:pause];
|
|
}
|
|
|
|
void _iOSBluetoothLEScanForPeripheralsWithServices (char *serviceUUIDsStringRaw, bool allowDuplicates, bool rssiOnly, bool clearPeripheralList, int recordType) {
|
|
|
|
if (_unityBluetoothLE != nil)
|
|
{
|
|
_unityBluetoothLE._rssiOnly = rssiOnly;
|
|
|
|
NSMutableArray *actualUUIDs = nil;
|
|
|
|
if (serviceUUIDsStringRaw != nil)
|
|
{
|
|
NSString *serviceUUIDsString = [NSString stringWithFormat:@"%s", serviceUUIDsStringRaw];
|
|
NSArray *serviceUUIDs = [serviceUUIDsString componentsSeparatedByString:@"|"];
|
|
|
|
if (serviceUUIDs.count > 0)
|
|
{
|
|
actualUUIDs = [[NSMutableArray alloc] init];
|
|
|
|
for (NSString* sUUID in serviceUUIDs)
|
|
[actualUUIDs addObject:[CBUUID UUIDWithString:sUUID]];
|
|
}
|
|
}
|
|
|
|
NSDictionary *options = nil;
|
|
if (allowDuplicates)
|
|
options = @{ CBCentralManagerScanOptionAllowDuplicatesKey: @YES };
|
|
|
|
[_unityBluetoothLE scanForPeripheralsWithServices:actualUUIDs options:options clearPeripheralList:clearPeripheralList recordType:recordType];
|
|
}
|
|
}
|
|
|
|
void _iOSBluetoothLEStopScan () {
|
|
|
|
if (_unityBluetoothLE != nil)
|
|
[_unityBluetoothLE stopScan];
|
|
}
|
|
|
|
void _iOSBluetoothLERetrieveListOfPeripheralsWithServices (char *serviceUUIDsStringRaw) {
|
|
|
|
if (_unityBluetoothLE != nil)
|
|
{
|
|
NSMutableArray *actualUUIDs = nil;
|
|
|
|
if (serviceUUIDsStringRaw != nil)
|
|
{
|
|
NSString *serviceUUIDsString = [NSString stringWithFormat:@"%s", serviceUUIDsStringRaw];
|
|
NSArray *serviceUUIDs = [serviceUUIDsString componentsSeparatedByString:@"|"];
|
|
|
|
if (serviceUUIDs.count > 0)
|
|
{
|
|
actualUUIDs = [[NSMutableArray alloc] init];
|
|
|
|
for (NSString* sUUID in serviceUUIDs)
|
|
[actualUUIDs addObject:[CBUUID UUIDWithString:sUUID]];
|
|
}
|
|
}
|
|
|
|
[_unityBluetoothLE retrieveListOfPeripheralsWithServices:actualUUIDs];
|
|
}
|
|
}
|
|
|
|
void _iOSBluetoothLEConnectToPeripheral (char *name) {
|
|
|
|
if (_unityBluetoothLE && name != nil)
|
|
[_unityBluetoothLE connectToPeripheral:[NSString stringWithFormat:@"%s", name]];
|
|
}
|
|
|
|
void _iOSBluetoothLEDisconnectPeripheral (char *name) {
|
|
|
|
if (_unityBluetoothLE && name != nil)
|
|
[_unityBluetoothLE disconnectPeripheral:[NSString stringWithFormat:@"%s", name]];
|
|
}
|
|
|
|
void _iOSBluetoothLEReadCharacteristic (char *name, char *service, char *characteristic) {
|
|
|
|
if (_unityBluetoothLE && name != nil && service != nil && characteristic != nil)
|
|
[_unityBluetoothLE readCharacteristic:[NSString stringWithFormat:@"%s", name] service:[NSString stringWithFormat:@"%s", service] characteristic:[NSString stringWithFormat:@"%s", characteristic]];
|
|
}
|
|
|
|
void _iOSBluetoothLEWriteCharacteristic (char *name, char *service, char *characteristic, unsigned char *data, int length, BOOL withResponse) {
|
|
|
|
if (_unityBluetoothLE && name != nil && service != nil && characteristic != nil && data != nil && length > 0)
|
|
[_unityBluetoothLE writeCharacteristic:[NSString stringWithFormat:@"%s", name] service:[NSString stringWithFormat:@"%s", service] characteristic:[NSString stringWithFormat:@"%s", characteristic] data:[NSData dataWithBytes:data length:length] withResponse:withResponse];
|
|
}
|
|
|
|
void _iOSBluetoothLESubscribeCharacteristic (char *name, char *service, char *characteristic) {
|
|
|
|
if (_unityBluetoothLE && name != nil && service != nil && characteristic != nil)
|
|
[_unityBluetoothLE subscribeCharacteristic:[NSString stringWithFormat:@"%s", name] service:[NSString stringWithFormat:@"%s", service] characteristic:[NSString stringWithFormat:@"%s", characteristic]];
|
|
}
|
|
|
|
void _iOSBluetoothLEUnSubscribeCharacteristic (char *name, char *service, char *characteristic) {
|
|
|
|
if (_unityBluetoothLE && name != nil && service != nil && characteristic != nil)
|
|
[_unityBluetoothLE unsubscribeCharacteristic:[NSString stringWithFormat:@"%s", name] service:[NSString stringWithFormat:@"%s", service] characteristic:[NSString stringWithFormat:@"%s", characteristic]];
|
|
}
|
|
|
|
void _iOSBluetoothLEDisconnectAll () {
|
|
|
|
if (_unityBluetoothLE != nil)
|
|
[_unityBluetoothLE disconnectAll];
|
|
}
|
|
|
|
void _iOSBluetoothLERequestMtu (char *name, int mtu) {
|
|
|
|
if (_unityBluetoothLE != nil)
|
|
[_unityBluetoothLE requestMtu:[NSString stringWithFormat:@"%s", name] mtu:mtu];
|
|
}
|
|
|
|
void _iOSBluetoothLEReadRSSI (char *name) {
|
|
|
|
if (_unityBluetoothLE != nil)
|
|
[_unityBluetoothLE readRSSI:[NSString stringWithFormat:@"%s", name]];
|
|
}
|
|
|
|
#if !TARGET_OS_TV
|
|
void _iOSBluetoothLEScanForBeacons (char *proximityUUIDsStringRaw) {
|
|
|
|
if (_unityBluetoothLE != nil)
|
|
{
|
|
NSMutableArray *actualUUIDs = nil;
|
|
|
|
if (proximityUUIDsStringRaw != nil)
|
|
{
|
|
NSString *proximityUUIDsString = [NSString stringWithFormat:@"%s", proximityUUIDsStringRaw];
|
|
NSArray *proximityUUIDs = [proximityUUIDsString componentsSeparatedByString:@"|"];
|
|
|
|
if (proximityUUIDs.count > 0)
|
|
{
|
|
NSMutableArray<CLBeaconRegion *> *beaconRegions = [[NSMutableArray<CLBeaconRegion *> alloc] init];
|
|
|
|
for (NSString* sUUID in proximityUUIDs)
|
|
{
|
|
NSArray *parts = [sUUID componentsSeparatedByString:@":"];
|
|
if (parts.count == 2)
|
|
{
|
|
if (@available(iOS 13.0, *)) {
|
|
CLBeaconRegion *beaconRegion = [[CLBeaconRegion alloc] initWithUUID:[[NSUUID alloc] initWithUUIDString:parts[0]] identifier:parts[1]];
|
|
[beaconRegions addObject:beaconRegion];
|
|
} else {
|
|
CLBeaconRegion *beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:[[NSUUID alloc] initWithUUIDString:parts[0]] identifier:parts[1]];
|
|
[beaconRegions addObject:beaconRegion];
|
|
}
|
|
|
|
[_unityBluetoothLE scanForBeacons:beaconRegions];
|
|
}
|
|
else
|
|
{
|
|
NSString *message = [NSString stringWithFormat:@"Error~iBeacon Scanning missing identifiers"];
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String] );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NSString *message = [NSString stringWithFormat:@"Error~iBeacon Scanning requires proximity UUIDs"];
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String] );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
NSString *message = [NSString stringWithFormat:@"Error~iBeacon Scanning requires proximity UUIDs"];
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String] );
|
|
}
|
|
}
|
|
}
|
|
|
|
void _iOSBluetoothLEStopBeaconScan () {
|
|
|
|
if (_unityBluetoothLE != nil)
|
|
[_unityBluetoothLE stopBeaconScan];
|
|
}
|
|
|
|
void _iOSBluetoothLEPeripheralName (char *newName) {
|
|
|
|
if (_unityBluetoothLE != nil && newName != nil)
|
|
[_unityBluetoothLE peripheralName:[[NSString alloc] initWithUTF8String:newName]];
|
|
}
|
|
|
|
void _iOSBluetoothLECreateService (char *uuid, BOOL primary) {
|
|
|
|
if (_unityBluetoothLE != nil)
|
|
[_unityBluetoothLE createService:[NSString stringWithFormat:@"%s", uuid] primary:primary];
|
|
}
|
|
|
|
void _iOSBluetoothLERemoveService (char *uuid) {
|
|
|
|
if (_unityBluetoothLE != nil)
|
|
[_unityBluetoothLE removeService:[NSString stringWithFormat:@"%s", uuid]];
|
|
}
|
|
|
|
void _iOSBluetoothLERemoveServices () {
|
|
|
|
if (_unityBluetoothLE != nil)
|
|
[_unityBluetoothLE removeServices];
|
|
}
|
|
|
|
void _iOSBluetoothLECreateCharacteristic (char *uuid, int properties, int permissions, unsigned char *data, int length) {
|
|
|
|
if (_unityBluetoothLE != nil) {
|
|
|
|
NSData *value = nil;
|
|
if (data != nil)
|
|
value = [[NSData alloc] initWithBytes:data length:length];
|
|
|
|
[_unityBluetoothLE createCharacteristic:[NSString stringWithFormat:@"%s", uuid] properties:properties permissions:permissions value:value];
|
|
}
|
|
}
|
|
|
|
void _iOSBluetoothLERemoveCharacteristic (char *uuid) {
|
|
|
|
if (_unityBluetoothLE != nil)
|
|
[_unityBluetoothLE removeCharacteristic:[NSString stringWithFormat:@"%s", uuid]];
|
|
}
|
|
|
|
void _iOSBluetoothLERemoveCharacteristics () {
|
|
|
|
if (_unityBluetoothLE != nil)
|
|
[_unityBluetoothLE removeCharacteristics];
|
|
}
|
|
|
|
void _iOSBluetoothLEStartAdvertising () {
|
|
|
|
if (_unityBluetoothLE != nil)
|
|
[_unityBluetoothLE startAdvertising];
|
|
}
|
|
|
|
void _iOSBluetoothLEStopAdvertising () {
|
|
|
|
if (_unityBluetoothLE != nil)
|
|
[_unityBluetoothLE stopAdvertising];
|
|
}
|
|
|
|
void _iOSBluetoothLEUpdateCharacteristicValue (char *uuid, unsigned char *data, int length) {
|
|
|
|
if (_unityBluetoothLE != nil) {
|
|
|
|
NSData *value = nil;
|
|
if (data != nil)
|
|
value = [[NSData alloc] initWithBytes:data length:length];
|
|
|
|
[_unityBluetoothLE updateCharacteristicValue:[NSString stringWithFormat:@"%s", uuid] value:value];
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
@implementation UnityBluetoothLE
|
|
|
|
@synthesize _peripherals;
|
|
@synthesize _rssiOnly;
|
|
|
|
- (void)initialize:(BOOL)asCentral asPeripheral:(BOOL)asPeripheral
|
|
{
|
|
_mtu = 20;
|
|
|
|
_isPaused = FALSE;
|
|
_isInitializing = TRUE;
|
|
|
|
_centralManager = nil;
|
|
#if !TARGET_OS_TV
|
|
_peripheralManager = nil;
|
|
_services = nil;
|
|
_characteristics = nil;
|
|
_allCharacteristics = nil;
|
|
#endif
|
|
if (asCentral)
|
|
_centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
|
|
|
|
#if !TARGET_OS_TV
|
|
if (asPeripheral)
|
|
_peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil];
|
|
|
|
_services = [[NSMutableDictionary alloc] init];
|
|
_characteristics = [[NSMutableDictionary alloc] init];
|
|
_allCharacteristics = [[NSMutableDictionary alloc] init];
|
|
#endif
|
|
|
|
_peripherals = [[NSMutableDictionary alloc] init];
|
|
}
|
|
|
|
- (void)deInitialize
|
|
{
|
|
if (_backgroundMessages != nil)
|
|
{
|
|
for (UnityMessage *message in _backgroundMessages)
|
|
{
|
|
if (message != nil)
|
|
{
|
|
[message deInitialize];
|
|
[message release];
|
|
}
|
|
}
|
|
|
|
[_backgroundMessages release];
|
|
_backgroundMessages = nil;
|
|
}
|
|
|
|
#if !TARGET_OS_TV
|
|
if (_peripheralManager != nil)
|
|
[self stopAdvertising];
|
|
|
|
[self removeCharacteristics];
|
|
[self removeServices];
|
|
#endif
|
|
|
|
if (_centralManager != nil)
|
|
[self stopScan];
|
|
|
|
[_peripherals removeAllObjects];
|
|
}
|
|
|
|
- (void)pauseMessages:(BOOL)isPaused
|
|
{
|
|
if (isPaused != _isPaused) {
|
|
|
|
if (_backgroundMessages == nil)
|
|
_backgroundMessages = [[NSMutableArray alloc] init];
|
|
|
|
_isPaused = isPaused;
|
|
|
|
// if we are not paused now since we know we changed state
|
|
// that means we were paused so we need to pump the saved
|
|
// messages to Unity
|
|
if (isPaused) {
|
|
|
|
if (_backgroundMessages != nil) {
|
|
|
|
for (UnityMessage *message in _backgroundMessages) {
|
|
|
|
if (message != nil) {
|
|
|
|
[message sendUnityMessage];
|
|
[message deInitialize];
|
|
[message release];
|
|
}
|
|
}
|
|
|
|
[_backgroundMessages removeAllObjects];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#if !TARGET_OS_TV
|
|
- (void)createService:(NSString *)uuid primary:(BOOL)primary
|
|
{
|
|
CBUUID *cbuuid = [CBUUID UUIDWithString:uuid];
|
|
CBMutableService *service = [[CBMutableService alloc] initWithType:cbuuid primary:primary];
|
|
|
|
NSMutableArray *characteristics = [[NSMutableArray alloc] init];
|
|
|
|
NSEnumerator *enumerator = [_characteristics keyEnumerator];
|
|
id key;
|
|
while ((key = [enumerator nextObject]))
|
|
{
|
|
CBCharacteristic *characteristic = [_characteristics objectForKey:key];
|
|
[_characteristics removeObjectForKey:key];
|
|
[characteristics addObject:characteristic];
|
|
[_allCharacteristics setObject:characteristic forKey:[characteristic UUID]];
|
|
}
|
|
[_characteristics removeAllObjects];
|
|
|
|
service.characteristics = characteristics;
|
|
|
|
[_services setObject:service forKey:cbuuid];
|
|
|
|
if (_peripheralManager != nil)
|
|
{
|
|
[_peripheralManager addService:service];
|
|
}
|
|
}
|
|
|
|
- (void)removeService:(NSString *)uuid
|
|
{
|
|
if (_services != nil)
|
|
{
|
|
if (_peripheralManager != nil)
|
|
{
|
|
CBMutableService *service = [_services objectForKey:uuid];
|
|
if (service != nil)
|
|
[_peripheralManager removeService:service];
|
|
}
|
|
|
|
[_services removeObjectForKey:uuid];
|
|
}
|
|
}
|
|
|
|
- (void)removeServices
|
|
{
|
|
if (_services != nil)
|
|
{
|
|
[_services removeAllObjects];
|
|
|
|
if (_peripheralManager != nil)
|
|
[_peripheralManager removeAllServices];
|
|
}
|
|
|
|
if (_allCharacteristics != nil)
|
|
[_allCharacteristics removeAllObjects];
|
|
}
|
|
|
|
- (void)peripheralName:(NSString *)newName
|
|
{
|
|
_peripheralName = newName;
|
|
}
|
|
|
|
- (void)createCharacteristic:(NSString *)uuid properties:(CBCharacteristicProperties)properties permissions:(CBAttributePermissions)permissions value:(NSData *)value
|
|
{
|
|
CBUUID *cbuuid = [CBUUID UUIDWithString:uuid];
|
|
CBCharacteristic *characteristic = [[CBMutableCharacteristic alloc] initWithType:cbuuid properties:properties value:value permissions:permissions];
|
|
|
|
[_characteristics setObject:characteristic forKey:cbuuid];
|
|
}
|
|
|
|
- (void)removeCharacteristic:(NSString *)uuid
|
|
{
|
|
if (_characteristics != nil)
|
|
[_characteristics removeObjectForKey:uuid];
|
|
}
|
|
|
|
- (void)removeCharacteristics
|
|
{
|
|
if (_characteristics != nil)
|
|
[_characteristics removeAllObjects];
|
|
}
|
|
|
|
- (void)startAdvertising
|
|
{
|
|
if (_peripheralManager != nil && _services != nil)
|
|
{
|
|
NSMutableArray *services = [[NSMutableArray alloc] init];
|
|
|
|
NSEnumerator *enumerator = [_services keyEnumerator];
|
|
id key;
|
|
while ((key = [enumerator nextObject]))
|
|
{
|
|
CBMutableService *service = [_services objectForKey:key];
|
|
[services addObject:service.UUID];
|
|
}
|
|
|
|
if (_peripheralName == nil)
|
|
_peripheralName = @"";
|
|
|
|
[_peripheralManager startAdvertising:@{ CBAdvertisementDataServiceUUIDsKey : services, CBAdvertisementDataLocalNameKey : _peripheralName }];
|
|
}
|
|
}
|
|
|
|
- (void)stopAdvertising
|
|
{
|
|
if (_peripheralManager != nil)
|
|
{
|
|
[_peripheralManager stopAdvertising];
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", "StoppedAdvertising");
|
|
}
|
|
}
|
|
|
|
- (void)updateCharacteristicValue:(NSString *)uuid value:(NSData *)value
|
|
{
|
|
if (_allCharacteristics != nil)
|
|
{
|
|
CBUUID *cbuuid = [CBUUID UUIDWithString:uuid];
|
|
CBMutableCharacteristic *characteristic = [_allCharacteristics objectForKey:cbuuid];
|
|
if (characteristic != nil)
|
|
{
|
|
characteristic.value = value;
|
|
if (_peripheralManager != nil)
|
|
[_peripheralManager updateValue:value forCharacteristic:characteristic onSubscribedCentrals:nil];
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)requestMtu:(NSString *)name mtu:(int)mtu
|
|
{
|
|
_mtu = mtu;
|
|
|
|
NSString *message = [NSString stringWithFormat:@"MtuChanged~%@~%d", name, _mtu];
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String]);
|
|
}
|
|
|
|
- (void)scanForBeacons:(NSArray<CLBeaconRegion *>*)beaconRegions
|
|
{
|
|
if ([CLLocationManager isRangingAvailable])
|
|
{
|
|
_locationManager = [CLLocationManager new];
|
|
_locationManager.delegate = self;
|
|
|
|
[_locationManager requestWhenInUseAuthorization];
|
|
|
|
for (CLBeaconRegion *region in beaconRegions)
|
|
[_locationManager startRangingBeaconsInRegion:region];
|
|
}
|
|
else
|
|
{
|
|
NSString *message = [NSString stringWithFormat:@"Error~iBeacon Ranging is not available"];
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String] );
|
|
}
|
|
}
|
|
|
|
- (void) stopBeaconScan
|
|
{
|
|
if (_locationManager != nil)
|
|
{
|
|
for (CLBeaconRegion *region in _locationManager.rangedRegions)
|
|
[_locationManager stopRangingBeaconsInRegion:region];
|
|
|
|
[_locationManager release];
|
|
_locationManager = nil;
|
|
}
|
|
}
|
|
|
|
// beacon delegate implementation
|
|
- (void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray<CLBeacon *> *)beacons inRegion:(CLBeaconRegion *)region
|
|
{
|
|
NSString *message;
|
|
for (CLBeacon *beacon in beacons)
|
|
{
|
|
message = [NSString stringWithFormat:@"DiscoveredBeacon~%@~%ld~%ld~%ld~%ld~%ld", [beacon.proximityUUID.UUIDString stringByReplacingOccurrencesOfString:@"-" withString:@""], beacon.major.longValue, beacon.minor.longValue, (long)beacon.rssi, (long)0, (long)beacon.proximity];
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String]);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
// central delegate implementation
|
|
- (void)scanForPeripheralsWithServices:(NSArray *)serviceUUIDs options:(NSDictionary *)options clearPeripheralList:(BOOL)clearPeripheralList recordType:(int)recordType
|
|
{
|
|
if (_centralManager != nil)
|
|
{
|
|
recordType = recordType;
|
|
if (clearPeripheralList && _peripherals != nil)
|
|
[_peripherals removeAllObjects];
|
|
|
|
[_centralManager scanForPeripheralsWithServices:serviceUUIDs options:options];
|
|
}
|
|
}
|
|
|
|
- (void) stopScan
|
|
{
|
|
if (_centralManager != nil)
|
|
[_centralManager stopScan];
|
|
}
|
|
|
|
- (void)retrieveListOfPeripheralsWithServices:(NSArray *)serviceUUIDs
|
|
{
|
|
if (_centralManager != nil)
|
|
{
|
|
if (_peripherals != nil)
|
|
[_peripherals removeAllObjects];
|
|
|
|
NSArray * list = [_centralManager retrieveConnectedPeripheralsWithServices:serviceUUIDs];
|
|
if (list != nil)
|
|
{
|
|
for (int i = 0; i < list.count; ++i)
|
|
{
|
|
CBPeripheral *peripheral = [list objectAtIndex:i];
|
|
if (peripheral != nil)
|
|
{
|
|
NSString *identifier = [[peripheral identifier] UUIDString];
|
|
NSString *name = [peripheral name];
|
|
|
|
NSString *message = [NSString stringWithFormat:@"RetrievedConnectedPeripheral~%@~%@", identifier, name];
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String]);
|
|
|
|
[_peripherals setObject:peripheral forKey:identifier];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)connectToPeripheral:(NSString *)name
|
|
{
|
|
if (_peripherals != nil && name != nil)
|
|
{
|
|
CBPeripheral *peripheral = [_peripherals objectForKey:name];
|
|
if (peripheral != nil)
|
|
[_centralManager connectPeripheral:peripheral options:nil];
|
|
}
|
|
}
|
|
|
|
- (void)disconnectAll
|
|
{
|
|
if (_peripherals != nil && [_peripherals count] > 0)
|
|
{
|
|
NSArray* keys = [_peripherals allKeys];
|
|
for(NSString* key in keys)
|
|
{
|
|
CBPeripheral *peripheral = [_peripherals objectForKey:key];
|
|
if (peripheral != nil)
|
|
[_centralManager cancelPeripheralConnection:peripheral];
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)disconnectPeripheral:(NSString *)name
|
|
{
|
|
if (_peripherals != nil && name != nil)
|
|
{
|
|
CBPeripheral *peripheral = [_peripherals objectForKey:name];
|
|
if (peripheral != nil)
|
|
{
|
|
[_centralManager cancelPeripheralConnection:peripheral];
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)readRSSI:(NSString *)name
|
|
{
|
|
if (_peripherals != nil && name != nil)
|
|
{
|
|
CBPeripheral *peripheral = [_peripherals objectForKey:name];
|
|
if (peripheral != nil)
|
|
{
|
|
[peripheral readRSSI];
|
|
}
|
|
}
|
|
}
|
|
|
|
- (CBCharacteristic *)getCharacteristic:(NSString *)name service:(NSString *)serviceString characteristic:(NSString *)characteristicString
|
|
{
|
|
CBCharacteristic *returnCharacteristic = nil;
|
|
|
|
if (name != nil && serviceString != nil && characteristicString != nil && _peripherals != nil)
|
|
{
|
|
CBPeripheral *peripheral = [_peripherals objectForKey:name];
|
|
if (peripheral != nil)
|
|
{
|
|
CBUUID *serviceUUID = [CBUUID UUIDWithString:serviceString];
|
|
CBUUID *characteristicUUID = [CBUUID UUIDWithString:characteristicString];
|
|
|
|
for (CBService *service in peripheral.services)
|
|
{
|
|
if ([service.UUID isEqual:serviceUUID])
|
|
{
|
|
for (CBCharacteristic *characteristic in service.characteristics)
|
|
{
|
|
if ([characteristic.UUID isEqual:characteristicUUID])
|
|
{
|
|
returnCharacteristic = characteristic;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return returnCharacteristic;
|
|
}
|
|
|
|
- (void)readCharacteristic:(NSString *)name service:(NSString *)serviceString characteristic:(NSString *)characteristicString
|
|
{
|
|
if (name != nil && serviceString != nil && characteristicString != nil && _peripherals != nil)
|
|
{
|
|
CBPeripheral *peripheral = [_peripherals objectForKey:name];
|
|
if (peripheral != nil)
|
|
{
|
|
CBCharacteristic *characteristic = [_unityBluetoothLE getCharacteristic:name service:serviceString characteristic:characteristicString];
|
|
if (characteristic != nil)
|
|
[peripheral readValueForCharacteristic:characteristic];
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)writeCharacteristic:(NSString *)name service:(NSString *)serviceString characteristic:(NSString *)characteristicString data:(NSData *)data withResponse:(BOOL)withResponse
|
|
{
|
|
if (name != nil && serviceString != nil && characteristicString != nil && _peripherals != nil && data != nil)
|
|
{
|
|
CBPeripheral *peripheral = [_peripherals objectForKey:name];
|
|
if (peripheral != nil)
|
|
{
|
|
CBCharacteristic *characteristic = [_unityBluetoothLE getCharacteristic:name service:serviceString characteristic:characteristicString];
|
|
if (characteristic != nil)
|
|
{
|
|
CBCharacteristicWriteType type = CBCharacteristicWriteWithoutResponse;
|
|
if (withResponse)
|
|
type = CBCharacteristicWriteWithResponse;
|
|
|
|
[self writeCharactersticBytes:peripheral characteristic:characteristic data:data withResponse:type];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)subscribeCharacteristic:(NSString *)name service:(NSString *)serviceString characteristic:(NSString *)characteristicString
|
|
{
|
|
if (name != nil && serviceString != nil && characteristicString != nil && _peripherals != nil)
|
|
{
|
|
CBPeripheral *peripheral = [_peripherals objectForKey:name];
|
|
if (peripheral != nil)
|
|
{
|
|
CBCharacteristic *characteristic = [_unityBluetoothLE getCharacteristic:name service:serviceString characteristic:characteristicString];
|
|
if (characteristic != nil)
|
|
[peripheral setNotifyValue:YES forCharacteristic:characteristic];
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)unsubscribeCharacteristic:(NSString *)name service:(NSString *)serviceString characteristic:(NSString *)characteristicString
|
|
{
|
|
if (name != nil && serviceString != nil && characteristicString != nil && _peripherals != nil)
|
|
{
|
|
CBPeripheral *peripheral = [_peripherals objectForKey:name];
|
|
if (peripheral != nil)
|
|
{
|
|
CBCharacteristic *characteristic = [_unityBluetoothLE getCharacteristic:name service:serviceString characteristic:characteristicString];
|
|
if (characteristic != nil)
|
|
[peripheral setNotifyValue:NO forCharacteristic:characteristic];
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)centralManagerDidUpdateState:(CBCentralManager *)central
|
|
{
|
|
switch (central.state)
|
|
{
|
|
case CBCentralManagerStateUnsupported:
|
|
{
|
|
NSLog(@"Central State: Unsupported");
|
|
|
|
NSString *message = [NSString stringWithFormat:@"Error~Bluetooth LE Not Supported"];
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String] );
|
|
} break;
|
|
|
|
case CBCentralManagerStateUnauthorized:
|
|
{
|
|
NSLog(@"Central State: Unauthorized");
|
|
|
|
NSString *message = [NSString stringWithFormat:@"Error~Bluetooth LE Not Authorized"];
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String] );
|
|
} break;
|
|
|
|
case CBCentralManagerStatePoweredOff:
|
|
{
|
|
NSLog(@"Central State: Powered Off");
|
|
|
|
NSString *message = [NSString stringWithFormat:@"Error~Bluetooth LE Powered Off"];
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String] );
|
|
} break;
|
|
|
|
case CBCentralManagerStatePoweredOn:
|
|
{
|
|
NSLog(@"Central State: Powered On");
|
|
if (_isInitializing)
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", "Initialized");
|
|
_isInitializing = FALSE;
|
|
} break;
|
|
|
|
case CBCentralManagerStateUnknown:
|
|
{
|
|
NSLog(@"Central State: Unknown");
|
|
|
|
NSString *message = [NSString stringWithFormat:@"Error~Bluetooth LE Unknown"];
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String] );
|
|
} break;
|
|
|
|
default:
|
|
{
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
- (void)centralManager:(CBCentralManager *)central didRetrievePeripherals:(NSArray *)peripherals
|
|
{
|
|
|
|
}
|
|
|
|
- (void)centralManager:(CBCentralManager *)central didRetrieveConnectedPeripherals:(NSArray *)peripherals
|
|
{
|
|
|
|
}
|
|
|
|
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
|
|
{
|
|
if (error)
|
|
{
|
|
NSString *message = [NSString stringWithFormat:@"Error~%@", error.description];
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String] );
|
|
}
|
|
}
|
|
|
|
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
|
|
{
|
|
if (_peripherals != nil && peripheral != nil)
|
|
{
|
|
NSString *name = [advertisementData objectForKey:CBAdvertisementDataLocalNameKey];
|
|
if (name == nil)
|
|
name = peripheral.name;
|
|
if (name == nil)
|
|
name = @"No Name";
|
|
|
|
if (name != nil)
|
|
{
|
|
NSString *identifier = nil;
|
|
|
|
NSString *foundPeripheral = [self findPeripheralName:peripheral];
|
|
if (foundPeripheral == nil)
|
|
identifier = [[peripheral identifier] UUIDString];
|
|
else
|
|
identifier = foundPeripheral;
|
|
|
|
NSString *message = nil;
|
|
|
|
if (advertisementData != nil && [advertisementData objectForKey:CBAdvertisementDataManufacturerDataKey] != nil)
|
|
{
|
|
NSData* bytes = [advertisementData objectForKey:CBAdvertisementDataManufacturerDataKey];
|
|
message = [NSString stringWithFormat:@"DiscoveredPeripheral~%@~%@~%@~%@", identifier, name, RSSI, [UnityBluetoothLE base64StringFromData:bytes length:bytes.length]];
|
|
}
|
|
else if (RSSI != 0 && _rssiOnly)
|
|
{
|
|
message = [NSString stringWithFormat:@"DiscoveredPeripheral~%@~%@~%@~", identifier, name, RSSI];
|
|
}
|
|
else
|
|
{
|
|
message = [NSString stringWithFormat:@"DiscoveredPeripheral~%@~%@", identifier, name];
|
|
}
|
|
|
|
if (message != nil)
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String]);
|
|
|
|
[_peripherals setObject:peripheral forKey:identifier];
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error
|
|
{
|
|
if (_peripherals != nil)
|
|
{
|
|
NSString *foundPeripheral = [self findPeripheralName:peripheral];
|
|
if (foundPeripheral != nil)
|
|
{
|
|
NSString *message = [NSString stringWithFormat:@"DisconnectedPeripheral~%@", foundPeripheral];
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String]);
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
|
|
{
|
|
NSString *foundPeripheral = [self findPeripheralName:peripheral];
|
|
if (foundPeripheral != nil)
|
|
{
|
|
NSString *message = [NSString stringWithFormat:@"ConnectedPeripheral~%@", foundPeripheral];
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String]);
|
|
peripheral.delegate = self;
|
|
[peripheral discoverServices:nil];
|
|
}
|
|
}
|
|
|
|
- (CBPeripheral *) findPeripheralInList:(CBPeripheral*)peripheral
|
|
{
|
|
CBPeripheral *foundPeripheral = nil;
|
|
|
|
NSEnumerator *enumerator = [_peripherals keyEnumerator];
|
|
id key;
|
|
while ((key = [enumerator nextObject]))
|
|
{
|
|
CBPeripheral *tempPeripheral = [_peripherals objectForKey:key];
|
|
if ([tempPeripheral isEqual:peripheral])
|
|
{
|
|
foundPeripheral = tempPeripheral;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return foundPeripheral;
|
|
}
|
|
|
|
- (NSString *) findPeripheralName:(CBPeripheral*)peripheral
|
|
{
|
|
NSString *foundPeripheral = nil;
|
|
|
|
NSEnumerator *enumerator = [_peripherals keyEnumerator];
|
|
id key;
|
|
while ((key = [enumerator nextObject]))
|
|
{
|
|
CBPeripheral *tempPeripheral = [_peripherals objectForKey:key];
|
|
if ([tempPeripheral isEqual:peripheral])
|
|
{
|
|
foundPeripheral = key;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return foundPeripheral;
|
|
}
|
|
|
|
// central peripheral delegate implementation
|
|
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error
|
|
{
|
|
if (error)
|
|
{
|
|
NSString *message = [NSString stringWithFormat:@"Error~%@", error.description];
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String] );
|
|
}
|
|
else
|
|
{
|
|
NSString *foundPeripheral = [self findPeripheralName:peripheral];
|
|
if (foundPeripheral != nil)
|
|
{
|
|
for (CBService *service in peripheral.services)
|
|
{
|
|
NSString *message = [NSString stringWithFormat:@"DiscoveredService~%@~%@", foundPeripheral, [service UUID]];
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String]);
|
|
|
|
[peripheral discoverCharacteristics:nil forService:service];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error
|
|
{
|
|
if (error)
|
|
{
|
|
NSString *message = [NSString stringWithFormat:@"Error~%@", error.description];
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String] );
|
|
}
|
|
else
|
|
{
|
|
NSString *foundPeripheral = [self findPeripheralName:peripheral];
|
|
if (foundPeripheral != nil)
|
|
{
|
|
for (CBCharacteristic *characteristic in service.characteristics)
|
|
{
|
|
NSString *message = [NSString stringWithFormat:@"DiscoveredCharacteristic~%@~%@~%@", foundPeripheral, [service UUID], [characteristic UUID]];
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
|
|
{
|
|
if (error)
|
|
{
|
|
NSString *message = [NSString stringWithFormat:@"Error~%@", error.description];
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String] );
|
|
}
|
|
else
|
|
{
|
|
NSString *foundPeripheral = [self findPeripheralName:peripheral];
|
|
if (foundPeripheral != nil)
|
|
{
|
|
if (characteristic.value != nil)
|
|
{
|
|
NSString *message = [NSString stringWithFormat:@"DidUpdateValueForCharacteristic~%@~%@~%@", foundPeripheral, [characteristic UUID], [UnityBluetoothLE base64StringFromData:characteristic.value length:characteristic.value.length]];
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String]);
|
|
//NSString *message = [UnityBluetoothLE base64StringFromData:characteristic.value length:characteristic.value.length];
|
|
//UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothData", [message UTF8String] );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)writeCharactersticBytesReset
|
|
{
|
|
_writeCharacteristicBytes = nil;
|
|
_writeCharacteristicLength = 0;
|
|
_writeCharacteristicPosition = 0;
|
|
_writeCharacteristicBytesToWrite = 0;
|
|
_writeCharacteristicWithResponse = CBCharacteristicWriteWithResponse;
|
|
_writeCharacteristicRetries = 3;
|
|
}
|
|
|
|
- (void)writeCharactersticBytes:(CBPeripheral *)peripheral characteristic:(CBCharacteristic *)characteristic data:(NSData *)data withResponse:(CBCharacteristicWriteType)withResponse
|
|
{
|
|
if (_writeCharacteristicBytes == nil && (_mtu == 0 || data.length > _mtu))
|
|
{
|
|
_writeCharacteristicLength = data.length;
|
|
_writeCharacteristicBytes = (unsigned char*)malloc(_writeCharacteristicLength);
|
|
memcpy(_writeCharacteristicBytes, [data bytes], _writeCharacteristicLength);
|
|
_writeCharacteristicPosition = 0;
|
|
_writeCharacteristicWithResponse = withResponse;
|
|
if (_mtu == 0)
|
|
_writeCharacteristicBytesToWrite = _writeCharacteristicLength;
|
|
else
|
|
_writeCharacteristicBytesToWrite = _mtu;
|
|
}
|
|
|
|
NSLog(@"write characteristic block");
|
|
|
|
if (_writeCharacteristicBytes != nil)
|
|
{
|
|
NSMutableData *newData = [NSMutableData dataWithCapacity:_writeCharacteristicBytesToWrite];
|
|
[newData appendBytes:&_writeCharacteristicBytes[_writeCharacteristicPosition] length:_writeCharacteristicBytesToWrite];
|
|
data = newData;
|
|
NSLog(@"data: %@", data);
|
|
}
|
|
|
|
NSLog(@"writing %ld bytes, %ld with response", data.length, withResponse);
|
|
[peripheral writeValue:data forCharacteristic:characteristic type:withResponse];
|
|
|
|
if (withResponse == CBCharacteristicWriteWithoutResponse)
|
|
{
|
|
double delayInSeconds = 0.01;
|
|
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
|
|
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
|
|
[self writeNextPacket:peripheral characteristic:characteristic];
|
|
});
|
|
}
|
|
}
|
|
|
|
- (void)writeNextPacket:(CBPeripheral *)peripheral characteristic:(CBCharacteristic *)characteristic
|
|
{
|
|
if (_writeCharacteristicLength > _writeCharacteristicPosition + _writeCharacteristicBytesToWrite)
|
|
{
|
|
_writeCharacteristicPosition += _writeCharacteristicBytesToWrite;
|
|
if (_writeCharacteristicPosition + _writeCharacteristicBytesToWrite > _writeCharacteristicLength)
|
|
_writeCharacteristicBytesToWrite = _writeCharacteristicLength - _writeCharacteristicPosition;
|
|
|
|
NSMutableData *data = [NSMutableData dataWithCapacity:_writeCharacteristicLength];
|
|
[data appendBytes:_writeCharacteristicBytes length:_writeCharacteristicLength];
|
|
[self writeCharactersticBytes:peripheral characteristic:characteristic data:data withResponse:_writeCharacteristicWithResponse];
|
|
}
|
|
else
|
|
{
|
|
[self writeCharactersticBytesReset];
|
|
NSString *message = [NSString stringWithFormat:@"DidWriteCharacteristic~%@", characteristic.UUID];
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String] );
|
|
}
|
|
}
|
|
|
|
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
|
|
{
|
|
if (error)
|
|
{
|
|
NSString *message = [NSString stringWithFormat:@"Error~%@", error.description];
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String] );
|
|
}
|
|
else
|
|
{
|
|
NSLog(@"%ld bytes written, %ld position, %ld length, %ld with response", _writeCharacteristicBytesToWrite, _writeCharacteristicPosition, _writeCharacteristicLength, _writeCharacteristicWithResponse);
|
|
|
|
if (_writeCharacteristicBytesToWrite > 0)
|
|
{
|
|
[self writeNextPacket:peripheral characteristic:characteristic];
|
|
}
|
|
else
|
|
{
|
|
NSString *message = [NSString stringWithFormat:@"DidWriteCharacteristic~%@", characteristic.UUID];
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String] );
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
|
|
{
|
|
if (error)
|
|
{
|
|
NSString *message = [NSString stringWithFormat:@"Error~%@", error.description];
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String] );
|
|
}
|
|
else
|
|
{
|
|
NSString *foundPeripheral = [self findPeripheralName:peripheral];
|
|
if (foundPeripheral != nil)
|
|
{
|
|
NSString *message = [NSString stringWithFormat:@"DidUpdateNotificationStateForCharacteristic~%@~%@", foundPeripheral, characteristic.UUID];
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String] );
|
|
}
|
|
}
|
|
}
|
|
|
|
- (void)peripheral:(CBPeripheral *) peripheral didReadRSSI:(NSNumber *)RSSI error:(NSError *)error
|
|
{
|
|
if (error)
|
|
{
|
|
NSString *message = [NSString stringWithFormat:@"Error~%@", error.description];
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String] );
|
|
}
|
|
else
|
|
{
|
|
NSString *foundPeripheral = [self findPeripheralName:peripheral];
|
|
if (foundPeripheral != nil)
|
|
{
|
|
NSString *message = [NSString stringWithFormat:@"DidReadRSSI~%@~%@", foundPeripheral, RSSI];
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String] );
|
|
}
|
|
}
|
|
}
|
|
|
|
#if !TARGET_OS_TV
|
|
// peripheral manager delegate implementation
|
|
- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral
|
|
{
|
|
_iOSBluetoothLELogString ([NSString stringWithFormat:@"Peripheral State Update: %d", (int)peripheral.state]);
|
|
if (_isInitializing && peripheral.state == CBPeripheralManagerStatePoweredOn)
|
|
{
|
|
_isInitializing = FALSE;
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", "Initialized");
|
|
}
|
|
}
|
|
|
|
- (void)peripheralManager:(CBPeripheralManager *)peripheral didAddService:(CBService *)service error:(NSError *)error
|
|
{
|
|
if (error)
|
|
{
|
|
NSString *message = [NSString stringWithFormat:@"Error~%@", error.description];
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String] );
|
|
}
|
|
else
|
|
{
|
|
NSString *message = [NSString stringWithFormat:@"ServiceAdded~%@", service.UUID];
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String] );
|
|
}
|
|
}
|
|
|
|
- (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral error:(NSError *)error
|
|
{
|
|
if (error)
|
|
{
|
|
NSString *message = [NSString stringWithFormat:@"Error~%@", error.description];
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String] );
|
|
}
|
|
else
|
|
{
|
|
NSString *message = [NSString stringWithFormat:@"StartedAdvertising"];
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String] );
|
|
}
|
|
}
|
|
|
|
- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBCharacteristic *)characteristic
|
|
{
|
|
|
|
}
|
|
|
|
- (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didUnsubscribeFromCharacteristic:(CBCharacteristic *)characteristic
|
|
{
|
|
|
|
}
|
|
|
|
- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveReadRequest:(CBATTRequest *)request
|
|
{
|
|
BOOL success = FALSE;
|
|
|
|
if (_peripheralManager != nil)
|
|
{
|
|
CBMutableCharacteristic *characteristic = [_allCharacteristics objectForKey:request.characteristic.UUID];
|
|
|
|
if (characteristic != nil)
|
|
{
|
|
request.value = [characteristic.value subdataWithRange:NSMakeRange(request.offset, characteristic.value.length - request.offset)];
|
|
[_peripheralManager respondToRequest:request withResult:CBATTErrorSuccess];
|
|
|
|
success = TRUE;
|
|
}
|
|
}
|
|
|
|
if (!success)
|
|
[_peripheralManager respondToRequest:request withResult:CBATTErrorAttributeNotFound];
|
|
}
|
|
|
|
- (void)peripheralManager:(CBPeripheralManager *)peripheral didReceiveWriteRequests:(NSArray *)requests
|
|
{
|
|
BOOL success = FALSE;
|
|
|
|
if (_peripheralManager != nil)
|
|
{
|
|
for (int i = 0; i < requests.count; ++i)
|
|
{
|
|
CBATTRequest *request = [requests objectAtIndex:i];
|
|
if (request != nil)
|
|
{
|
|
CBMutableCharacteristic *characteristic = [_allCharacteristics objectForKey:request.characteristic.UUID];
|
|
|
|
if (characteristic != nil)
|
|
{
|
|
characteristic.value = request.value;
|
|
|
|
NSString *message = [NSString stringWithFormat:@"PeripheralReceivedWriteData~%@~%@", [characteristic UUID], [UnityBluetoothLE base64StringFromData:characteristic.value length:characteristic.value.length]];
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String]);
|
|
|
|
success = TRUE;
|
|
}
|
|
else
|
|
{
|
|
success = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
success = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (success)
|
|
[_peripheralManager respondToRequest:[requests objectAtIndex:0] withResult:CBATTErrorSuccess];
|
|
else
|
|
[_peripheralManager respondToRequest:[requests objectAtIndex:0] withResult:CBATTErrorAttributeNotFound];
|
|
}
|
|
#endif
|
|
|
|
- (void)sendUnityMessage:(BOOL)isString message:(NSString *)message
|
|
{
|
|
if (_isPaused) {
|
|
|
|
if (_backgroundMessages != nil) {
|
|
|
|
UnityMessage *unitymessage = [[UnityMessage alloc] init];
|
|
if (unitymessage != nil) {
|
|
|
|
[unitymessage initialize:isString message:message];
|
|
[_backgroundMessages addObject:unitymessage];
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
|
|
if (isString)
|
|
{
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [message UTF8String] );
|
|
}
|
|
else
|
|
{
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothData", [message UTF8String] );
|
|
}
|
|
}
|
|
}
|
|
|
|
static char base64EncodingTable[64] =
|
|
{
|
|
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
|
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
|
|
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
|
|
'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
|
|
};
|
|
|
|
+ (NSString *) base64StringFromData: (NSData *)data length: (int)length
|
|
{
|
|
unsigned long ixtext, lentext;
|
|
long ctremaining;
|
|
unsigned char input[3], output[4];
|
|
short i, charsonline = 0, ctcopy;
|
|
const unsigned char *raw;
|
|
NSMutableString *result;
|
|
|
|
lentext = [data length];
|
|
if (lentext < 1)
|
|
return @"";
|
|
result = [NSMutableString stringWithCapacity: lentext];
|
|
raw = (const unsigned char *)[data bytes];
|
|
ixtext = 0;
|
|
|
|
while (true) {
|
|
ctremaining = lentext - ixtext;
|
|
if (ctremaining <= 0)
|
|
break;
|
|
for (i = 0; i < 3; i++) {
|
|
unsigned long ix = ixtext + i;
|
|
if (ix < lentext)
|
|
input[i] = raw[ix];
|
|
else
|
|
input[i] = 0;
|
|
}
|
|
output[0] = (input[0] & 0xFC) >> 2;
|
|
output[1] = ((input[0] & 0x03) << 4) | ((input[1] & 0xF0) >> 4);
|
|
output[2] = ((input[1] & 0x0F) << 2) | ((input[2] & 0xC0) >> 6);
|
|
output[3] = input[2] & 0x3F;
|
|
ctcopy = 4;
|
|
switch (ctremaining) {
|
|
case 1:
|
|
ctcopy = 2;
|
|
break;
|
|
case 2:
|
|
ctcopy = 3;
|
|
break;
|
|
}
|
|
|
|
for (i = 0; i < ctcopy; i++)
|
|
[result appendString: [NSString stringWithFormat: @"%c", base64EncodingTable[output[i]]]];
|
|
|
|
for (i = ctcopy; i < 4; i++)
|
|
[result appendString: @"="];
|
|
|
|
ixtext += 3;
|
|
charsonline += 4;
|
|
|
|
if ((length > 0) && (charsonline >= length))
|
|
charsonline = 0;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
#pragma mark Internal
|
|
|
|
@end
|
|
|
|
@implementation UnityMessage
|
|
|
|
- (void)initialize:(BOOL)isString message:(NSString *)message
|
|
{
|
|
_isString = isString;
|
|
_message = [message copy];
|
|
}
|
|
|
|
- (void)deInitialize
|
|
{
|
|
if (_message != nil)
|
|
[_message release];
|
|
_message = nil;
|
|
}
|
|
|
|
- (void)sendUnityMessage
|
|
{
|
|
if (_message != nil) {
|
|
|
|
if (_isString)
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothMessage", [_message UTF8String] );
|
|
else
|
|
UnitySendMessage ("BluetoothLEReceiver", "OnBluetoothData", [_message UTF8String] );
|
|
}
|
|
}
|
|
|
|
@end
|