-
Notifications
You must be signed in to change notification settings - Fork 201
/
Copy pathbluetooth_print.dart
159 lines (124 loc) · 4.38 KB
/
bluetooth_print.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:rxdart/rxdart.dart';
import 'bluetooth_print_model.dart';
class BluetoothPrint {
static const String NAMESPACE = 'bluetooth_print';
static const int CONNECTED = 1;
static const int DISCONNECTED = 0;
static const MethodChannel _channel =
const MethodChannel('$NAMESPACE/methods');
static const EventChannel _stateChannel =
const EventChannel('$NAMESPACE/state');
Stream<MethodCall> get _methodStream => _methodStreamController.stream;
final StreamController<MethodCall> _methodStreamController =
StreamController.broadcast();
BluetoothPrint._() {
_channel.setMethodCallHandler((MethodCall call) async {
_methodStreamController.add(call);
});
}
static BluetoothPrint _instance = new BluetoothPrint._();
static BluetoothPrint get instance => _instance;
Future<bool> get isAvailable async =>
await _channel.invokeMethod('isAvailable').then<bool>((d) => d);
Future<bool> get isOn async =>
await _channel.invokeMethod('isOn').then<bool>((d) => d);
Future<bool?> get isConnected async =>
await _channel.invokeMethod('isConnected');
BehaviorSubject<bool> _isScanning = BehaviorSubject.seeded(false);
Stream<bool> get isScanning => _isScanning.stream;
BehaviorSubject<List<BluetoothDevice>> _scanResults =
BehaviorSubject.seeded([]);
Stream<List<BluetoothDevice>> get scanResults => _scanResults.stream;
PublishSubject _stopScanPill = new PublishSubject();
/// Gets the current state of the Bluetooth module
Stream<int> get state async* {
yield await _channel.invokeMethod('state').then((s) => s);
yield* _stateChannel.receiveBroadcastStream().map((s) => s);
}
/// Starts a scan for Bluetooth Low Energy devices
/// Timeout closes the stream after a specified [Duration]
Stream<BluetoothDevice> scan({
Duration? timeout,
}) async* {
if (_isScanning.value == true) {
throw Exception('Another scan is already in progress.');
}
// Emit to isScanning
_isScanning.add(true);
final killStreams = <Stream>[];
killStreams.add(_stopScanPill);
if (timeout != null) {
killStreams.add(Rx.timer(null, timeout));
}
// Clear scan results list
_scanResults.add(<BluetoothDevice>[]);
try {
await _channel.invokeMethod('startScan');
} catch (e) {
print('Error starting scan.');
_stopScanPill.add(null);
_isScanning.add(false);
throw e;
}
yield* BluetoothPrint.instance._methodStream
.where((m) => m.method == "ScanResult")
.map((m) => m.arguments)
.takeUntil(Rx.merge(killStreams))
.doOnDone(stopScan)
.map((map) {
final device = BluetoothDevice.fromJson(Map<String, dynamic>.from(map));
final List<BluetoothDevice> list = _scanResults.value;
int newIndex = -1;
list.asMap().forEach((index, e) {
if (e.address == device.address) {
newIndex = index;
}
});
if (newIndex != -1) {
list[newIndex] = device;
} else {
list.add(device);
}
_scanResults.add(list);
return device;
});
}
Future startScan({
Duration? timeout,
}) async {
await scan(timeout: timeout).drain();
return _scanResults.value;
}
/// Stops a scan for Bluetooth Low Energy devices
Future stopScan() async {
await _channel.invokeMethod('stopScan');
_stopScanPill.add(null);
_isScanning.add(false);
}
Future<dynamic> connect(BluetoothDevice device) =>
_channel.invokeMethod('connect', device.toJson());
Future<dynamic> disconnect() => _channel.invokeMethod('disconnect');
Future<dynamic> destroy() => _channel.invokeMethod('destroy');
Future<dynamic> printReceipt(
Map<String, dynamic> config, List<LineText> data) {
Map<String, Object> args = Map();
args['config'] = config;
args['data'] = data.map((m) {
return m.toJson();
}).toList();
_channel.invokeMethod('printReceipt', args);
return Future.value(true);
}
Future<dynamic> printLabel(Map<String, dynamic> config, List<LineText> data) {
Map<String, Object> args = Map();
args['config'] = config;
args['data'] = data.map((m) {
return m.toJson();
}).toList();
_channel.invokeMethod('printLabel', args);
return Future.value(true);
}
Future<dynamic> printTest() => _channel.invokeMethod('printTest');
}