184 lines
6.5 KiB
Objective-C
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
|