Skip to content

Commit b362f54

Browse files
fix: updated the logics
1 parent 4ffb1a9 commit b362f54

File tree

9 files changed

+304
-69
lines changed

9 files changed

+304
-69
lines changed

lib/bademagic_module/bluetooth/base_ble_state.dart

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,18 @@ abstract class NormalBleState extends BleState {
1818
return await processState();
1919
} on Exception catch (e) {
2020
String errorMessage = e.toString().replaceFirst('Exception: ', '');
21-
return CompletedState(isSuccess: false, message: errorMessage);
21+
return CompletedState(
22+
isSuccess: false,
23+
message: errorMessage,
24+
shouldDisconnect: true, // Always disconnect on errors
25+
);
2226
}
2327
}
2428
}
2529

2630
abstract class RetryBleState extends BleState {
2731
final logger = Logger();
2832
final toast = ToastUtils();
29-
3033
final _maxRetries = 3;
3134

3235
Future<BleState?> processState();
@@ -43,6 +46,7 @@ abstract class RetryBleState extends BleState {
4346
logger.e(e);
4447
lastException = e;
4548
attempt++;
49+
4650
if (attempt < _maxRetries) {
4751
logger.d("Retrying ($attempt/$_maxRetries)...");
4852
} else {
@@ -53,9 +57,10 @@ abstract class RetryBleState extends BleState {
5357
}
5458
}
5559

56-
// After max retries, return a CompletedState indicating failure.
5760
return CompletedState(
58-
isSuccess: false,
59-
message: lastException?.toString() ?? "Unknown error");
61+
isSuccess: false,
62+
message: lastException?.toString() ?? "Unknown error",
63+
shouldDisconnect: true, // Always disconnect after max retries
64+
);
6065
}
6166
}

lib/bademagic_module/bluetooth/completed_state.dart

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,40 @@ class CompletedState extends NormalBleState {
66
final String message;
77
final TransferMode? mode;
88
final bool shouldDisconnect;
9+
final DataTransferManager? manager; // Add manager reference
910

1011
CompletedState({
1112
required this.isSuccess,
1213
required this.message,
1314
this.mode,
1415
this.shouldDisconnect = false,
16+
this.manager, // Add manager parameter
1517
});
1618

1719
@override
1820
Future<BleState?> processState() async {
21+
// Handle disconnection if required
22+
if (shouldDisconnect && manager?.connectedDevice != null) {
23+
try {
24+
logger.d("Disconnecting device as requested...");
25+
26+
// For streaming mode, exit streaming first
27+
if (mode == TransferMode.streaming && manager!.isStreamingActive) {
28+
await manager!.exitStreamingMode();
29+
await Future.delayed(const Duration(milliseconds: 200));
30+
}
31+
32+
await manager!.connectedDevice!.disconnect();
33+
await Future.delayed(const Duration(milliseconds: 700));
34+
manager!.clearConnectedDevice();
35+
36+
logger.d("Device disconnected successfully");
37+
} catch (e) {
38+
logger.e("Error during disconnection: $e");
39+
}
40+
}
41+
42+
// Show user feedback
1943
if (isSuccess) {
2044
toast.showToast(message);
2145
} else {

lib/bademagic_module/bluetooth/connect_state.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ class ConnectState extends NormalBleState {
3232
isSuccess: false,
3333
message: "Failed to connect to device. Please retry.",
3434
mode: manager.mode,
35-
shouldDisconnect: true, // ensure cleanup
35+
shouldDisconnect: true,
36+
manager: manager, // Add this line
3637
);
3738
}
3839
}

lib/bademagic_module/bluetooth/datagenerator.dart

Lines changed: 114 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
// Enhanced DataTransferManager with streaming support
21
import 'dart:async';
32
import 'package:badgemagic/bademagic_module/models/data.dart';
43
import 'package:badgemagic/bademagic_module/utils/data_to_bytearray_converter.dart';
54
import 'package:badgemagic/bademagic_module/utils/file_helper.dart';
5+
import 'package:badgemagic/bademagic_module/utils/converters.dart';
6+
import 'package:badgemagic/bademagic_module/utils/byte_array_utils.dart';
67
import 'package:badgemagic/providers/badge_message_provider.dart';
78
import 'package:badgemagic/providers/imageprovider.dart';
89
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
@@ -12,7 +13,7 @@ import 'package:logger/logger.dart';
1213
enum TransferMode { legacy, streaming }
1314

1415
class DataTransferManager {
15-
final Data? data; // Make nullable for streaming-only usage
16+
final Data? data;
1617
TransferMode mode;
1718

1819
BluetoothDevice? connectedDevice;
@@ -30,19 +31,96 @@ class DataTransferManager {
3031
final FileHelper fileHelper = FileHelper();
3132
final InlineImageProvider controllerData =
3233
GetIt.instance<InlineImageProvider>();
34+
final Converters _converters = Converters();
3335
final Logger logger = Logger();
3436

3537
bool isStreamingActive = false;
3638

39+
// NEW: Streaming state management
40+
Map<String, dynamic>? _pendingStreamData;
41+
bool _isStreamingReady = false;
42+
3743
DataTransferManager(this.data, {this.mode = TransferMode.legacy});
3844

3945
// Factory constructors for convenience
4046
factory DataTransferManager.forLegacy(Data data) =>
4147
DataTransferManager(data, mode: TransferMode.legacy);
42-
43-
factory DataTransferManager.forStreaming(Data data) =>
48+
factory DataTransferManager.forStreaming() =>
4449
DataTransferManager(null, mode: TransferMode.streaming);
4550

51+
// NEW: Store parameters for streaming use after connection
52+
void setPendingStreamData(Map<String, dynamic> streamData) {
53+
_pendingStreamData = streamData;
54+
logger.d("Stored pending stream data: ${streamData.keys}");
55+
}
56+
57+
Map<String, dynamic> getPendingStreamData() {
58+
return _pendingStreamData ?? {};
59+
}
60+
61+
// NEW: Check if streaming connection is established and ready
62+
bool isStreamingConnectionReady() {
63+
return _isStreamingReady &&
64+
connectedDevice != null &&
65+
streamingWriteCharacteristic != null &&
66+
isStreamingActive;
67+
}
68+
69+
// NEW: Mark streaming as ready (called from WriteState)
70+
void setStreamingReady(bool ready) {
71+
_isStreamingReady = ready;
72+
logger.d("Streaming ready state: $ready");
73+
}
74+
75+
// NEW: Process the actual streaming content using your Converters
76+
Future<bool> processStreamingContent() async {
77+
if (_pendingStreamData == null) {
78+
logger.e("No pending stream data");
79+
return false;
80+
}
81+
82+
try {
83+
Map<String, dynamic> params = _pendingStreamData!;
84+
logger.i("Processing streaming content: '${params['text']}'");
85+
86+
String text = params['text'] ?? "";
87+
if (text.isEmpty) {
88+
logger.w("Empty text for streaming");
89+
return false;
90+
}
91+
92+
// Use your existing Converters class for text to hex conversion
93+
List<String> hexStrings =
94+
await _converters.messageTohex(text, params['isInverted'] ?? false);
95+
96+
if (hexStrings.isEmpty) {
97+
logger.w("No hex data generated for streaming");
98+
return false;
99+
}
100+
101+
logger.d("Generated ${hexStrings.length} hex strings for streaming");
102+
103+
// Convert hex to bitmap using your existing utility
104+
List<List<bool>> bitmap = hexStringToBool(hexStrings.join());
105+
106+
// Convert bitmap to column format for streaming
107+
List<int> columns = convertBitmapToColumns(bitmap);
108+
109+
logger.i("Streaming ${columns.length} columns");
110+
111+
// Stream the bitmap
112+
bool success = await streamBitmap(columns);
113+
114+
// Clear pending data after processing
115+
_pendingStreamData = null;
116+
117+
return success;
118+
} catch (e) {
119+
logger.e("Error processing streaming content: $e");
120+
return false;
121+
}
122+
}
123+
46124
Future<List<List<int>>> generateDataChunk() async {
47125
if (data == null) throw Exception("No data provided for legacy transfer");
48126
return converter.convert(data!);
@@ -57,6 +135,8 @@ class DataTransferManager {
57135
notificationSubscription?.cancel();
58136
notificationSubscription = null;
59137
isStreamingActive = false;
138+
_isStreamingReady = false;
139+
_pendingStreamData = null;
60140
}
61141

62142
/// Handle error codes from streaming badge
@@ -88,14 +168,16 @@ class DataTransferManager {
88168
}
89169
}
90170

91-
/// Stream bitmap data (for streaming mode)
171+
/// Stream bitmap data (enhanced with better logging)
92172
Future<bool> streamBitmap(List<int> bitmap) async {
93173
if (!isStreamingActive || streamingWriteCharacteristic == null) {
94174
logger.e("Streaming not active or characteristic unavailable");
95175
return false;
96176
}
97177

98178
try {
179+
logger.i("Streaming bitmap with ${bitmap.length} columns");
180+
99181
List<int> command = [0x03]; // stream_bitmap function code
100182

101183
// Convert bitmap to 16-bit words (little-endian)
@@ -104,26 +186,41 @@ class DataTransferManager {
104186
command.add((column >> 8) & 0xFF);
105187
}
106188

189+
logger.d("Sending ${command.length} bytes to streaming characteristic");
190+
107191
await streamingWriteCharacteristic!
108192
.write(command, withoutResponse: false);
109-
logger.d("Bitmap streamed successfully, ${bitmap.length} columns");
193+
194+
// Wait for processing
195+
await Future.delayed(const Duration(milliseconds: 200));
196+
197+
logger.i("Bitmap streamed successfully, ${bitmap.length} columns");
110198
return true;
111199
} catch (e) {
112200
logger.e("Failed to stream bitmap: $e");
113201
return false;
114202
}
115203
}
116204

117-
/// Enter streaming mode
205+
/// Enter streaming mode (enhanced)
118206
Future<bool> enterStreamingMode() async {
119-
if (streamingWriteCharacteristic == null) return false;
207+
if (streamingWriteCharacteristic == null) {
208+
logger.e("Streaming write characteristic not available");
209+
return false;
210+
}
120211

121212
try {
213+
logger.i("Entering streaming mode...");
214+
122215
List<int> command = [0x02, 0x00]; // Enter streaming mode
123216
await streamingWriteCharacteristic!
124217
.write(command, withoutResponse: false);
125-
await Future.delayed(const Duration(milliseconds: 100));
218+
219+
// Wait for device to enter streaming mode
220+
await Future.delayed(const Duration(milliseconds: 200));
221+
126222
isStreamingActive = true;
223+
logger.i("Successfully entered streaming mode");
127224
return true;
128225
} catch (e) {
129226
logger.e("Failed to enter streaming mode: $e");
@@ -136,10 +233,18 @@ class DataTransferManager {
136233
if (streamingWriteCharacteristic == null) return false;
137234

138235
try {
236+
logger.i("Exiting streaming mode...");
237+
139238
List<int> command = [0x02, 0x01]; // Exit streaming mode
140239
await streamingWriteCharacteristic!
141240
.write(command, withoutResponse: false);
241+
242+
await Future.delayed(const Duration(milliseconds: 100));
243+
142244
isStreamingActive = false;
245+
_isStreamingReady = false;
246+
247+
logger.i("Successfully exited streaming mode");
143248
return true;
144249
} catch (e) {
145250
logger.e("Failed to exit streaming mode: $e");

lib/bademagic_module/bluetooth/write_state.dart

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ class WriteState extends NormalBleState {
6161
isSuccess: true,
6262
message: "Data transferred successfully",
6363
mode: TransferMode.legacy,
64-
shouldDisconnect: true, // ✅ disconnect after legacy
64+
shouldDisconnect: true,
65+
manager: manager, // Add this line
6566
);
6667
}
6768
}
@@ -129,11 +130,16 @@ class WriteState extends NormalBleState {
129130

130131
if (success) {
131132
logger.d("Streaming mode activated successfully");
133+
134+
// CRITICAL: Mark streaming as ready for content processing
135+
manager.setStreamingReady(true);
136+
132137
return CompletedState(
133138
isSuccess: true,
134-
message: "Streaming mode activated. Ready to stream bitmaps.",
139+
message: "Streaming mode activated. Processing content...",
135140
mode: TransferMode.streaming,
136-
shouldDisconnect: false, // ✅ stay connected for streaming
141+
shouldDisconnect: false, // Keep connection alive
142+
manager: manager,
137143
);
138144
} else {
139145
throw Exception("Failed to activate streaming mode");

lib/providers/animation_badge_provider.dart

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,7 @@ class AnimationBadgeProvider extends ChangeNotifier {
322322
logger.i(
323323
"Starting streaming transfer with aniIndex=$aniIndex, speed=$selectedSpeed");
324324

325+
// ✅ CRITICAL FIX: Use useStreaming parameter, not isSavedBadge
325326
await badgeData.checkAndTransfer(
326327
inlineImageProvider.getController().text,
327328
flash,
@@ -330,13 +331,13 @@ class AnimationBadgeProvider extends ChangeNotifier {
330331
selectedSpeed,
331332
modeValueMap[aniIndex],
332333
null,
333-
true, // 🚨 IMPORTANT: mark streaming = true
334+
false, // ✅ isSavedBadge should be false for new transfers
335+
useStreaming: true, // ✅ THIS is the correct streaming parameter
334336
);
335-
336-
ToastUtils().showToast("Streaming transfer started");
337337
} catch (e) {
338-
logger.e("Error in handleStreamingTransfer");
339-
ToastUtils().showErrorToast("Streaming transfer failed: $e");
338+
logger.e("Error in handleStreamingTransfer: $e");
339+
ToastUtils().showErrorToast("❌ Streaming transfer failed: $e");
340+
rethrow;
340341
}
341342
}
342343
}

0 commit comments

Comments
 (0)