flutter_bluetooth_basic/ios/Classes/FlutterBluetoothBasicPlugin.m

184 lines
6.5 KiB
Objective-C

#import "FlutterBluetoothBasicPlugin.h"
#import "ConnecterManager.h"
@interface FlutterBluetoothBasicPlugin ()
@property(nonatomic, retain) NSObject<FlutterPluginRegistrar> *registrar;
@property(nonatomic, retain) FlutterMethodChannel *channel;
@property(nonatomic, retain) BluetoothPrintStreamHandler *stateStreamHandler;
@property(nonatomic) NSMutableDictionary *scannedPeripherals;
@end
@implementation FlutterBluetoothBasicPlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
FlutterMethodChannel* channel = [FlutterMethodChannel
methodChannelWithName:NAMESPACE @"/methods"
binaryMessenger:[registrar messenger]];
FlutterEventChannel* stateChannel = [FlutterEventChannel eventChannelWithName:NAMESPACE @"/state" binaryMessenger:[registrar messenger]];
FlutterBluetoothBasicPlugin* instance = [[FlutterBluetoothBasicPlugin alloc] init];
instance.channel = channel;
instance.scannedPeripherals = [NSMutableDictionary new];
// STATE
BluetoothPrintStreamHandler* stateStreamHandler = [[BluetoothPrintStreamHandler alloc] init];
[stateChannel setStreamHandler:stateStreamHandler];
instance.stateStreamHandler = stateStreamHandler;
[registrar addMethodCallDelegate:instance channel:channel];
}
- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
NSLog(@"call method -> %@", call.method);
if ([@"state" isEqualToString:call.method]) {
result(nil);
} else if([@"isAvailable" isEqualToString:call.method]) {
result(@(YES));
} else if([@"isConnected" isEqualToString:call.method]) {
result(@(NO));
} else if([@"isOn" isEqualToString:call.method]) {
result(@(YES));
}else if([@"startScan" isEqualToString:call.method]) {
NSLog(@"getDevices method -> %@", call.method);
[self.scannedPeripherals removeAllObjects];
if (Manager.bleConnecter == nil) {
[Manager didUpdateState:^(NSInteger state) {
switch (state) {
case CBCentralManagerStateUnsupported:
NSLog(@"The platform/hardware doesn't support Bluetooth Low Energy.");
break;
case CBCentralManagerStateUnauthorized:
NSLog(@"The app is not authorized to use Bluetooth Low Energy.");
break;
case CBCentralManagerStatePoweredOff:
NSLog(@"Bluetooth is currently powered off.");
break;
case CBCentralManagerStatePoweredOn:
[self startScan];
NSLog(@"Bluetooth power on");
break;
case CBCentralManagerStateUnknown:
default:
break;
}
}];
} else {
[self startScan];
}
result(nil);
} else if([@"stopScan" isEqualToString:call.method]) {
[Manager stopScan];
result(nil);
} else if([@"connect" isEqualToString:call.method]) {
NSDictionary *device = [call arguments];
@try {
NSLog(@"connect device begin -> %@", [device objectForKey:@"name"]);
CBPeripheral *peripheral = [_scannedPeripherals objectForKey:[device objectForKey:@"address"]];
self.state = ^(ConnectState state) {
[self updateConnectState:state];
};
[Manager connectPeripheral:peripheral options:nil timeout:2 connectBlack: self.state];
result(nil);
} @catch(FlutterError *e) {
result(e);
}
} else if([@"disconnect" isEqualToString:call.method]) {
@try {
[Manager close];
result(nil);
} @catch(FlutterError *e) {
result(e);
}
} else if([@"writeData" isEqualToString:call.method]) {
@try {
NSDictionary *args = [call arguments];
NSMutableArray *bytes = [args objectForKey:@"bytes"];
NSNumber* lenBuf = [args objectForKey:@"length"];
int len = [lenBuf intValue];
char cArray[len];
for (int i = 0; i < len; ++i) {
// NSLog(@"** ind_%d (d): %@, %d", i, bytes[i], [bytes[i] charValue]);
cArray[i] = [bytes[i] charValue];
}
NSData *data2 = [NSData dataWithBytes:cArray length:sizeof(cArray)];
// NSLog(@"bytes in hex: %@", [data2 description]);
[Manager write:data2];
result(nil);
} @catch(FlutterError *e) {
result(e);
}
}
}
-(void)startScan {
[Manager scanForPeripheralsWithServices:nil options:nil discover:^(CBPeripheral * _Nullable peripheral, NSDictionary<NSString *,id> * _Nullable advertisementData, NSNumber * _Nullable RSSI) {
if (peripheral.name != nil) {
NSLog(@"find device -> %@", peripheral.name);
[self.scannedPeripherals setObject:peripheral forKey:[[peripheral identifier] UUIDString]];
NSDictionary *device = [NSDictionary dictionaryWithObjectsAndKeys:peripheral.identifier.UUIDString,@"address",peripheral.name,@"name",nil,@"type",nil];
[_channel invokeMethod:@"ScanResult" arguments:device];
}
}];
}
-(void)updateConnectState:(ConnectState)state {
dispatch_async(dispatch_get_main_queue(), ^{
NSNumber *ret = @0;
switch (state) {
case CONNECT_STATE_CONNECTING:
NSLog(@"status -> %@", @"Connecting ...");
ret = @0;
break;
case CONNECT_STATE_CONNECTED:
NSLog(@"status -> %@", @"Connection success");
ret = @1;
break;
case CONNECT_STATE_FAILT:
NSLog(@"status -> %@", @"Connection failed");
ret = @0;
break;
case CONNECT_STATE_DISCONNECT:
NSLog(@"status -> %@", @"Disconnected");
ret = @0;
break;
default:
NSLog(@"status -> %@", @"Connection timed out");
ret = @0;
break;
}
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:ret,@"id",nil];
if(_stateStreamHandler.sink != nil) {
self.stateStreamHandler.sink([dict objectForKey:@"id"]);
}
});
}
@end
@implementation BluetoothPrintStreamHandler
- (FlutterError*)onListenWithArguments:(id)arguments eventSink:(FlutterEventSink)eventSink {
self.sink = eventSink;
return nil;
}
- (FlutterError*)onCancelWithArguments:(id)arguments {
self.sink = nil;
return nil;
}
@end