Commit b412622d authored by Andrey's avatar Andrey

Added PrinterBluetoothManager class

parent 96ba0941
import 'dart:async'; import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'package:esc_pos_printer/esc_pos_printer.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bluetooth_basic/flutter_bluetooth_basic.dart'; // import 'package:flutter_bluetooth_basic/flutter_bluetooth_basic.dart';
import 'package:oktoast/oktoast.dart'; import 'package:oktoast/oktoast.dart';
void main() => runApp(MyApp()); void main() => runApp(MyApp());
...@@ -24,111 +25,48 @@ class MyApp extends StatelessWidget { ...@@ -24,111 +25,48 @@ class MyApp extends StatelessWidget {
class MyHomePage extends StatefulWidget { class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key); MyHomePage({Key key, this.title}) : super(key: key);
final String title; final String title;
// final FlutterBlue flutterBlue = FlutterBlue.instance;
@override @override
_MyHomePageState createState() => _MyHomePageState(); _MyHomePageState createState() => _MyHomePageState();
} }
class _MyHomePageState extends State<MyHomePage> { class _MyHomePageState extends State<MyHomePage> {
BluetoothManager bluetoothManager = BluetoothManager.instance; PrinterBluetoothManager printerManager = PrinterBluetoothManager();
bool _connected = false; List<PrinterBluetooth> _devices = [];
bool _isScanning = false;
bool _isPrinting = false;
List<BluetoothDevice> _devices = [];
StreamSubscription _scanResultsSubscription;
StreamSubscription _isScanningSubscription;
void _startScanDevices() { @override
setState(() { void initState() {
_devices = []; super.initState();
});
bluetoothManager.startScan(timeout: Duration(seconds: 4));
_scanResultsSubscription = printerManager.scanResults.listen((devices) async {
bluetoothManager.scanResults.listen((devices) async { print('UI: Devices found ${devices.length}');
setState(() { setState(() {
_devices = devices; _devices = devices;
}); });
}); });
_isScanningSubscription =
bluetoothManager.isScanning.listen((isScanningCurrent) async {
// If isScanning value changed (scan just stopped)
if (_isScanning && !isScanningCurrent) {
_scanResultsSubscription.cancel();
_isScanningSubscription.cancel();
} }
void _startScanDevices() {
setState(() { setState(() {
_isScanning = isScanningCurrent; _devices = [];
});
}); });
printerManager.startScan(Duration(seconds: 4));
} }
void _stopScanDevices() { void _stopScanDevices() {
bluetoothManager.stopScan(); printerManager.stopScan();
} }
Future _runDelayed(int seconds) { // Future _runDelayed(int seconds) {
return Future<dynamic>.delayed(Duration(seconds: seconds)); // return Future<dynamic>.delayed(Duration(seconds: seconds));
} // }
void _testPrint(BluetoothDevice printer) async { void _testPrint(PrinterBluetooth printer) async {
const int timeout = 5; try {
if (_isScanning) { printer.printLine('hello');
showToast('Print failed (scanning in progress)'); } catch (e) {
return; print(e.toString());
} }
if (_isPrinting) {
showToast('Print failed (another printing in progress)');
return;
}
_isPrinting = true;
// We have to rescan before connecting, otherwise we can connect only once
await bluetoothManager.startScan(timeout: Duration(seconds: 1));
await bluetoothManager.stopScan();
// Connect
await bluetoothManager.connect(printer);
// Subscribe to the events
bluetoothManager.state.listen((state) async {
switch (state) {
case BluetoothManager.CONNECTED:
print('********************* CONNECTED');
// to avoid double call
if (!_connected) {
print('@@@@SEND DATA......');
final List<int> bytes = latin1.encode('test!\n\n\n').toList();
await bluetoothManager.writeData(bytes);
showToast('Data sent');
}
// TODO sending disconnect signal should be event-based
_runDelayed(3).then((dynamic v) async {
print('@@@@DISCONNECTING......');
await bluetoothManager.disconnect();
_isPrinting = false;
});
_connected = true;
break;
case BluetoothManager.DISCONNECTED:
print('********************* DISCONNECTED');
_connected = false;
break;
default:
break;
}
});
// Printing timeout
_runDelayed(timeout).then((dynamic v) async {
if (_isPrinting) {
_isPrinting = false;
showToast('Print failed');
}
});
} }
@override @override
...@@ -174,15 +112,23 @@ class _MyHomePageState extends State<MyHomePage> { ...@@ -174,15 +112,23 @@ class _MyHomePageState extends State<MyHomePage> {
), ),
); );
}), }),
floatingActionButton: _isScanning floatingActionButton: StreamBuilder<bool>(
? FloatingActionButton( stream: printerManager.isScanningStream,
initialData: false,
builder: (c, snapshot) {
if (snapshot.data) {
return FloatingActionButton(
child: Icon(Icons.stop), child: Icon(Icons.stop),
onPressed: _stopScanDevices, onPressed: _stopScanDevices,
backgroundColor: Colors.red, backgroundColor: Colors.red,
) );
: FloatingActionButton( } else {
return FloatingActionButton(
child: Icon(Icons.search), child: Icon(Icons.search),
onPressed: _startScanDevices, onPressed: _startScanDevices,
);
}
},
), ),
); );
} }
......
...@@ -10,10 +10,8 @@ dependencies: ...@@ -10,10 +10,8 @@ dependencies:
sdk: flutter sdk: flutter
cupertino_icons: ^0.1.2 cupertino_icons: ^0.1.2
oktoast: ^2.3.0 oktoast: ^2.3.0
flutter_bluetooth_basic: esc_pos_printer:
git: path: ../../
url: git://github.com/andrey-ushakov/flutter_bluetooth_basic
ref: master
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:
......
...@@ -11,3 +11,4 @@ export './src/enums.dart'; ...@@ -11,3 +11,4 @@ export './src/enums.dart';
export './src/pos_column.dart'; export './src/pos_column.dart';
export './src/pos_styles.dart'; export './src/pos_styles.dart';
export './src/printer.dart'; export './src/printer.dart';
export './src/printer_bluetooth_manager.dart';
/*
* esc_pos_printer
* Created by Andrey Ushakov
*
* Copyright (c) 2020. All rights reserved.
* See LICENSE for distribution and usage details.
*/
import 'dart:async';
import 'dart:convert';
import 'package:rxdart/rxdart.dart';
// import 'dart:convert';
// import 'dart:io';
// import 'dart:typed_data';
// import 'package:gbk_codec/gbk_codec.dart';
// import 'package:hex/hex.dart';
// import 'package:image/image.dart';
// import 'barcode.dart';
// import 'commands.dart';
// import 'enums.dart';
// import 'pos_column.dart';
// import 'pos_styles.dart';
import 'package:flutter_bluetooth_basic/flutter_bluetooth_basic.dart';
/// Bluetooth printer
class PrinterBluetooth {
PrinterBluetooth(this._device);
final BluetoothDevice _device;
// final BluetoothManager _bluetoothManager = BluetoothManager.instance;
final PrinterBluetoothManager _manager = PrinterBluetoothManager();
bool _isPrinting = false;
String get name => _device.name;
String get address => _device.address;
int get type => _device.type;
Future _runDelayed(int seconds) {
return Future<dynamic>.delayed(Duration(seconds: seconds));
}
void printLine(String text) async {
const int timeout = 5;
print('============ ${_manager._isScanning}');
// if (_bluetoothManager.is) {
// showToast('Print failed (scanning in progress)');
// return;
// }
if (_isPrinting) {
throw Exception('Print failed (another printing in progress)');
}
_isPrinting = true;
// We have to rescan before connecting, otherwise we can connect only once
await _manager._bluetoothManager.startScan(timeout: Duration(seconds: 1));
await _manager._bluetoothManager.stopScan();
// Connect
await _manager._bluetoothManager.connect(_device);
// Subscribe to the events
_manager._bluetoothManager.state.listen((state) async {
switch (state) {
case BluetoothManager.CONNECTED:
print('********************* CONNECTED');
// to avoid double call
// if (!_connected) {
if (_device.connected == null || !_device.connected) {
print('@@@@SEND DATA......');
final List<int> bytes = latin1.encode('test!\n\n\n').toList();
await _manager._bluetoothManager.writeData(bytes);
// showToast('Data sent'); TODO
// return 0;
}
// TODO sending disconnect signal should be event-based
_runDelayed(3).then((dynamic v) async {
print('@@@@DISCONNECTING......');
await _manager._bluetoothManager.disconnect();
_isPrinting = false;
});
// _connected = true;
break;
case BluetoothManager.DISCONNECTED:
print('********************* DISCONNECTED');
// _connected = false;
break;
default:
break;
}
// return 0;
});
// Printing timeout
_runDelayed(timeout).then((dynamic v) async {
if (_isPrinting) {
_isPrinting = false;
throw Exception('Print failed (timeout)');
}
});
}
}
/// Bluetooth printer
/// // TODO rename to BluetoothScanner
class PrinterBluetoothManager {
final BluetoothManager _bluetoothManager = BluetoothManager.instance;
// bool _connected = false;
bool _isScanning = false;
// bool _isPrinting = false;
StreamSubscription _scanResultsSubscription;
StreamSubscription _isScanningSubscription;
Stream<bool> get isScanningStream => _bluetoothManager.isScanning;
BehaviorSubject<List<PrinterBluetooth>> _scanResults =
BehaviorSubject.seeded([]);
Stream<List<PrinterBluetooth>> get scanResults => _scanResults.stream;
void startScan(Duration timeout) async {
_scanResults.add(<PrinterBluetooth>[]);
_bluetoothManager.startScan(timeout: Duration(seconds: 4));
_scanResultsSubscription = _bluetoothManager.scanResults.listen((devices) {
_scanResults.add(devices.map((d) => PrinterBluetooth(d)).toList());
});
// TODO move listener to constructor
_isScanningSubscription =
_bluetoothManager.isScanning.listen((isScanningCurrent) async {
// If isScanning value changed (scan just stopped)
if (_isScanning && !isScanningCurrent) {
_scanResultsSubscription.cancel();
_isScanningSubscription.cancel();
}
_isScanning = isScanningCurrent;
});
}
void stopScan() async {
await _bluetoothManager.stopScan();
}
}
...@@ -13,6 +13,7 @@ dependencies: ...@@ -13,6 +13,7 @@ dependencies:
hex: ^0.1.2 hex: ^0.1.2
image: ^2.1.4 image: ^2.1.4
gbk_codec: ^0.3.1+3 gbk_codec: ^0.3.1+3
rxdart: ^0.23.1
flutter_bluetooth_basic: flutter_bluetooth_basic:
git: git:
url: git://github.com/andrey-ushakov/flutter_bluetooth_basic url: git://github.com/andrey-ushakov/flutter_bluetooth_basic
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment