flutter_zebra_scale 1.0.10 copy "flutter_zebra_scale: ^1.0.10" to clipboard
flutter_zebra_scale: ^1.0.10 copied to clipboard

Flutter plugin for Zebra Scale SDK

example/lib/main.dart

import 'package:flutter/material.dart';
import 'dart:async';

import 'package:flutter/services.dart';
import 'package:flutter_zebra_scale/flutter_zebra_scale.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String _platformVersion = 'Unknown';
  String _statusMessage = 'Ready';
  bool _isInitialized = false;
  bool _isConnected = false;
  int? _connectedScannerId;
  final TextEditingController _scannerIdController = TextEditingController();
  final _flutterZebraScalePlugin = FlutterZebraScale();

  // Scale state
  bool _isScaleEnabled = false;
  bool _isLiveWeightRunning = false;
  String _weight = '';
  String _weightMode = '';
  String _weightStatus = '';

  // Event state
  StreamSubscription<Map<String, dynamic>>? _eventSubscription;
  List<String> _eventLog = [];
  String _lastBarcode = '';
  String _lastBarcodeType = '';

  // Scanner list state
  List<Map<String, dynamic>> _availableScanners = [];
  List<Map<String, dynamic>> _activeScanners = [];
  bool _isLoadingScanners = false;

  @override
  void initState() {
    super.initState();
    initPlatformState();
    _setupLiveWeightListener();
    _setupEventListener();
  }

  @override
  void dispose() {
    _scannerIdController.dispose();
    _eventSubscription?.cancel();
    _flutterZebraScalePlugin.stopLiveWeight();
    super.dispose();
  }

  void _setupLiveWeightListener() {
    // Set up method channel to listen for live weight updates
    const MethodChannel channel = MethodChannel('flutter_zebra_scale');
    channel.setMethodCallHandler((call) async {
      if (call.method == 'onLiveWeightUpdate') {
        final data = call.arguments as Map<Object?, Object?>;
        if (mounted) {
          setState(() {
            _weight = data['weight']?.toString() ?? '';
            _weightMode = data['weightMode']?.toString() ?? '';
            _weightStatus = data['statusText']?.toString() ?? '';
          });
        }
      }
    });
  }

  void _setupEventListener() {
    _eventSubscription = _flutterZebraScalePlugin.getEventStream().listen(
      (event) {
        if (!mounted) return;

        final eventType = event['eventType'] as String?;
        // Safer extraction: platform may send Map<Object?, Object?>
        Map<String, dynamic>? data;
        final dataRaw = event['data'];
        if (dataRaw is Map) {
          try {
            data = Map<String, dynamic>.from(
              dataRaw.map((k, v) => MapEntry(k?.toString() ?? '', v)),
            );
          } catch (_) {
            data = null;
          }
        }

        setState(() {
          // Add to event log (keep last 20 events)
          _eventLog.insert(
            0,
            '[$eventType] ${DateTime.now().toString().substring(11, 19)}',
          );
          if (_eventLog.length > 20) {
            _eventLog.removeLast();
          }

          // Handle specific events
          switch (eventType) {
            case 'barcode':
              if (data != null) {
                _lastBarcode = data['barcodeData']?.toString() ?? '';
                _lastBarcodeType = data['barcodeType']?.toString() ?? '';
                _statusMessage = 'Barcode scanned: $_lastBarcode';
              } else {
                _statusMessage = 'Barcode event received (data null)';
              }
              break;

            case 'scannerAppeared':
              if (data != null) {
                final scannerName =
                    data['scannerName']?.toString() ?? 'Unknown';
                _statusMessage = 'Scanner appeared: $scannerName';
                // Auto-refresh scanner list when a new scanner appears
                Future.delayed(const Duration(milliseconds: 500), () {
                  if (mounted) {
                    _refreshScannersList();
                  }
                });
              }
              break;

            case 'scannerDisappeared':
              if (data != null) {
                final scannerId = data['scannerID']?.toString() ?? 'Unknown';
                _statusMessage = 'Scanner disappeared: $scannerId';
              }
              break;

            case 'sessionEstablished':
              if (data != null) {
                final scannerName =
                    data['scannerName']?.toString() ?? 'Unknown';
                _statusMessage = 'Connected to: $scannerName';
                _isConnected = true;
                _connectedScannerId = data['scannerID'] as int?;
              }
              break;

            case 'sessionTerminated':
              if (data != null) {
                final scannerId = data['scannerID']?.toString() ?? 'Unknown';
                _statusMessage = 'Disconnected from scanner: $scannerId';
                _isConnected = false;
                _connectedScannerId = null;
              }
              break;
          }
        });
      },
      onError: (error) {
        if (mounted) {
          setState(() {
            _statusMessage = 'Event error: $error';
          });
        }
      },
    );
  }

  // Platform messages are asynchronous, so we initialize in an async method.
  Future<void> initPlatformState() async {
    String platformVersion;
    // Platform messages may fail, so we use a try/catch PlatformException.
    // We also handle the message potentially returning null.
    try {
      platformVersion =
          await _flutterZebraScalePlugin.getPlatformVersion() ??
          'Unknown platform version';
    } on PlatformException {
      platformVersion = 'Failed to get platform version.';
    }

    // If the widget was removed from the tree while the asynchronous platform
    // message was in flight, we want to discard the reply rather than calling
    // setState to update our non-existent appearance.
    if (!mounted) return;

    setState(() {
      _platformVersion = platformVersion;
    });
  }

  Future<void> _initializeSDK() async {
    setState(() {
      _statusMessage = 'Initializing SDK...';
    });

    try {
      final success = await _flutterZebraScalePlugin.initialize();
      if (mounted) {
        setState(() {
          _isInitialized = success;
          if (success) {
            _statusMessage = 'SDK initialized successfully';
            // Enable scanner detection and Bluetooth discovery after initialization
            _enableScannerDetection();
          } else {
            _statusMessage = 'Failed to initialize SDK';
          }
        });
      }
    } on PlatformException catch (e) {
      if (mounted) {
        setState(() {
          _statusMessage = 'Error: ${e.message}';
        });
      }
    } catch (e) {
      if (mounted) {
        setState(() {
          _statusMessage = 'Error: $e';
        });
      }
    }
  }

  Future<void> _enableScannerDetection() async {
    try {
      // Enable scanner detection
      await _flutterZebraScalePlugin.enableScannersDetection(true);
      // Enable Bluetooth scanner discovery
      await _flutterZebraScalePlugin.enableBluetoothScannerDiscovery(true);
      if (mounted) {
        setState(() {
          _statusMessage = 'Scanner detection enabled. Waiting for scanners...';
        });
        // Wait a bit for scanners to be discovered, then refresh the list
        Future.delayed(const Duration(seconds: 2), () {
          if (mounted) {
            _loadAvailableScanners();
          }
        });
      }
    } catch (e) {
      if (mounted) {
        setState(() {
          _statusMessage = 'Error enabling scanner detection: $e';
        });
      }
    }
  }

  Future<void> _connectToScanner() async {
    final scannerIdText = _scannerIdController.text.trim();
    if (scannerIdText.isEmpty) {
      setState(() {
        _statusMessage = 'Please enter a scanner ID';
      });
      return;
    }

    final scannerId = int.tryParse(scannerIdText);
    if (scannerId == null || scannerId <= 0) {
      setState(() {
        _statusMessage = 'Invalid scanner ID. Must be a positive number';
      });
      return;
    }

    setState(() {
      _statusMessage = 'Connecting to scanner $scannerId...';
    });

    try {
      final success = await _flutterZebraScalePlugin.connect(scannerId);
      if (mounted) {
        setState(() {
          if (success) {
            _isConnected = true;
            _connectedScannerId = scannerId;
            _statusMessage = 'Connected to scanner $scannerId';
          } else {
            _isConnected = false;
            _connectedScannerId = null;
            _statusMessage = 'Failed to connect to scanner $scannerId';
          }
        });
      }
    } on PlatformException catch (e) {
      if (mounted) {
        setState(() {
          _isConnected = false;
          _connectedScannerId = null;
          _statusMessage = 'Error connecting: ${e.message}';
        });
      }
    } catch (e) {
      if (mounted) {
        setState(() {
          _isConnected = false;
          _connectedScannerId = null;
          _statusMessage = 'Error: $e';
        });
      }
    }
  }

  Future<void> _disconnectFromScanner() async {
    if (!_isConnected || _connectedScannerId == null) {
      setState(() {
        _statusMessage = 'No scanner connected';
      });
      return;
    }

    final scannerId = _connectedScannerId!;
    setState(() {
      _statusMessage = 'Disconnecting from scanner $scannerId...';
    });

    try {
      // Stop live weight if running
      if (_isLiveWeightRunning) {
        await _flutterZebraScalePlugin.stopLiveWeight();
      }

      final success = await _flutterZebraScalePlugin.disconnect(scannerId);
      if (mounted) {
        setState(() {
          _isConnected = false;
          _connectedScannerId = null;
          _isScaleEnabled = false;
          _isLiveWeightRunning = false;
          _weight = '';
          _weightMode = '';
          _weightStatus = '';
          _statusMessage = success
              ? 'Disconnected from scanner $scannerId'
              : 'Failed to disconnect from scanner $scannerId';
        });
      }
    } on PlatformException catch (e) {
      if (mounted) {
        setState(() {
          _statusMessage = 'Error disconnecting: ${e.message}';
        });
      }
    } catch (e) {
      if (mounted) {
        setState(() {
          _statusMessage = 'Error: $e';
        });
      }
    }
  }

  Future<void> _enableScale() async {
    if (!_isConnected || _connectedScannerId == null) {
      setState(() {
        _statusMessage = 'Please connect to a scanner first';
      });
      return;
    }

    setState(() {
      _statusMessage = 'Enabling scale...';
    });

    try {
      final success = await _flutterZebraScalePlugin.enableScale(
        _connectedScannerId!,
      );
      if (mounted) {
        setState(() {
          _isScaleEnabled = success;
          _statusMessage = success ? 'Scale enabled' : 'Failed to enable scale';
        });
      }
    } catch (e) {
      if (mounted) {
        setState(() {
          _statusMessage = 'Error: $e';
        });
      }
    }
  }

  Future<void> _disableScale() async {
    if (!_isConnected || _connectedScannerId == null) {
      return;
    }

    // Stop live weight if running
    if (_isLiveWeightRunning) {
      await _flutterZebraScalePlugin.stopLiveWeight();
    }

    setState(() {
      _statusMessage = 'Disabling scale...';
    });

    try {
      final success = await _flutterZebraScalePlugin.disableScale(
        _connectedScannerId!,
      );
      if (mounted) {
        setState(() {
          _isScaleEnabled = !success;
          _isLiveWeightRunning = false;
          _weight = '';
          _weightMode = '';
          _weightStatus = '';
          _statusMessage = success
              ? 'Scale disabled'
              : 'Failed to disable scale';
        });
      }
    } catch (e) {
      if (mounted) {
        setState(() {
          _statusMessage = 'Error: $e';
        });
      }
    }
  }

  Future<void> _readWeight() async {
    if (!_isConnected || _connectedScannerId == null) {
      setState(() {
        _statusMessage = 'Please connect to a scanner first';
      });
      return;
    }

    setState(() {
      _statusMessage = 'Reading weight...';
    });

    try {
      final weightData = await _flutterZebraScalePlugin.readWeight(
        _connectedScannerId!,
      );
      if (mounted) {
        setState(() {
          if (weightData != null) {
            _weight = weightData['weight']?.toString() ?? '';
            _weightMode = weightData['weightMode']?.toString() ?? '';
            _weightStatus = weightData['statusText']?.toString() ?? '';
            _statusMessage = 'Weight read successfully';
          } else {
            _statusMessage = 'Failed to read weight';
          }
        });
      }
    } catch (e) {
      if (mounted) {
        setState(() {
          _statusMessage = 'Error: $e';
        });
      }
    }
  }

  Future<void> _zeroScale() async {
    if (!_isConnected || _connectedScannerId == null) {
      setState(() {
        _statusMessage = 'Please connect to a scanner first';
      });
      return;
    }

    setState(() {
      _statusMessage = 'Zeroing scale...';
    });

    try {
      final success = await _flutterZebraScalePlugin.zeroScale(
        _connectedScannerId!,
      );
      if (mounted) {
        setState(() {
          _statusMessage = success ? 'Scale zeroed' : 'Failed to zero scale';
        });
      }
    } catch (e) {
      if (mounted) {
        setState(() {
          _statusMessage = 'Error: $e';
        });
      }
    }
  }

  Future<void> _resetScale() async {
    if (!_isConnected || _connectedScannerId == null) {
      setState(() {
        _statusMessage = 'Please connect to a scanner first';
      });
      return;
    }

    setState(() {
      _statusMessage = 'Resetting scale...';
    });

    try {
      final success = await _flutterZebraScalePlugin.resetScale(
        _connectedScannerId!,
      );
      if (mounted) {
        setState(() {
          _statusMessage = success ? 'Scale reset' : 'Failed to reset scale';
        });
      }
    } catch (e) {
      if (mounted) {
        setState(() {
          _statusMessage = 'Error: $e';
        });
      }
    }
  }

  Future<void> _startLiveWeight() async {
    if (!_isConnected || _connectedScannerId == null) {
      setState(() {
        _statusMessage = 'Please connect to a scanner first';
      });
      return;
    }

    setState(() {
      _statusMessage = 'Starting live weight...';
    });

    try {
      final success = await _flutterZebraScalePlugin.startLiveWeight(
        _connectedScannerId!,
      );
      if (mounted) {
        setState(() {
          _isLiveWeightRunning = success;
          _statusMessage = success
              ? 'Live weight started'
              : 'Failed to start live weight';
        });
      }
    } catch (e) {
      if (mounted) {
        setState(() {
          _statusMessage = 'Error: $e';
        });
      }
    }
  }

  Future<void> _stopLiveWeight() async {
    setState(() {
      _statusMessage = 'Stopping live weight...';
    });

    try {
      final success = await _flutterZebraScalePlugin.stopLiveWeight();
      if (mounted) {
        setState(() {
          _isLiveWeightRunning = !success;
          _statusMessage = success
              ? 'Live weight stopped'
              : 'Failed to stop live weight';
        });
      }
    } catch (e) {
      if (mounted) {
        setState(() {
          _statusMessage = 'Error: $e';
        });
      }
    }
  }

  Future<void> _loadAvailableScanners() async {
    setState(() {
      _isLoadingScanners = true;
      _statusMessage = 'Loading available scanners...';
    });

    try {
      final result = await _flutterZebraScalePlugin.getAvailableScanners();
      if (mounted) {
        setState(() {
          _availableScanners =
              (result['scanners'] as List?)
                  ?.map((s) => Map<String, dynamic>.from(s as Map))
                  .toList() ??
              [];
          _isLoadingScanners = false;
          _statusMessage = 'Found ${result['count']} available scanner(s)';
        });
      }
    } catch (e) {
      if (mounted) {
        setState(() {
          _isLoadingScanners = false;
          _statusMessage = 'Error loading scanners: $e';
        });
      }
    }
  }

  Future<void> _loadActiveScanners() async {
    setState(() {
      _isLoadingScanners = true;
      _statusMessage = 'Loading active scanners...';
    });

    try {
      final result = await _flutterZebraScalePlugin.getActiveScanners();
      if (mounted) {
        setState(() {
          _activeScanners =
              (result['scanners'] as List?)
                  ?.map((s) => Map<String, dynamic>.from(s as Map))
                  .toList() ??
              [];
          _isLoadingScanners = false;
          _statusMessage = 'Found ${result['count']} active scanner(s)';
        });
      }
    } catch (e) {
      if (mounted) {
        setState(() {
          _isLoadingScanners = false;
          _statusMessage = 'Error loading active scanners: $e';
        });
      }
    }
  }

  Future<void> _refreshScannersList() async {
    setState(() {
      _isLoadingScanners = true;
      _statusMessage = 'Refreshing scanner list...';
    });

    try {
      // Use updateScannersList which gets both available and active scanners
      final result = await _flutterZebraScalePlugin.updateScannersList();
      if (mounted) {
        final allScanners =
            (result['scanners'] as List?)
                ?.map((s) => Map<String, dynamic>.from(s as Map))
                .toList() ??
            [];

        // Separate into available and active
        _availableScanners = allScanners
            .where((s) => s['isActive'] != true)
            .toList();
        _activeScanners = allScanners
            .where((s) => s['isActive'] == true)
            .toList();

        setState(() {
          _isLoadingScanners = false;
          _statusMessage =
              'Found ${result['count']} scanner(s) (${_availableScanners.length} available, ${_activeScanners.length} active)';
        });
      }
    } catch (e) {
      if (mounted) {
        setState(() {
          _isLoadingScanners = false;
          _statusMessage = 'Error refreshing scanner list: $e';
        });
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Zebra Scanner Example'),
          backgroundColor: Colors.blue,
        ),
        body: SingleChildScrollView(
          padding: const EdgeInsets.all(16.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              // Platform Version Card
              Card(
                child: Padding(
                  padding: const EdgeInsets.all(16.0),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      const Text(
                        'Platform Info',
                        style: TextStyle(
                          fontSize: 18,
                          fontWeight: FontWeight.bold,
                        ),
                      ),
                      const SizedBox(height: 8),
                      Text('Running on: $_platformVersion'),
                    ],
                  ),
                ),
              ),
              const SizedBox(height: 16),

              // Status Card
              Card(
                color: _isConnected
                    ? Colors.green.shade50
                    : Colors.grey.shade100,
                child: Padding(
                  padding: const EdgeInsets.all(16.0),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Row(
                        children: [
                          Icon(
                            _isConnected ? Icons.check_circle : Icons.info,
                            color: _isConnected ? Colors.green : Colors.grey,
                          ),
                          const SizedBox(width: 8),
                          const Text(
                            'Status',
                            style: TextStyle(
                              fontSize: 18,
                              fontWeight: FontWeight.bold,
                            ),
                          ),
                        ],
                      ),
                      const SizedBox(height: 8),
                      Text(_statusMessage),
                      if (_isInitialized)
                        Padding(
                          padding: const EdgeInsets.only(top: 4.0),
                          child: Row(
                            children: [
                              Icon(Icons.check, size: 16, color: Colors.green),
                              const SizedBox(width: 4),
                              const Text(
                                'SDK Initialized',
                                style: TextStyle(
                                  fontSize: 12,
                                  color: Colors.green,
                                ),
                              ),
                            ],
                          ),
                        ),
                      if (_isConnected && _connectedScannerId != null)
                        Padding(
                          padding: const EdgeInsets.only(top: 8.0),
                          child: Text(
                            'Connected Scanner ID: $_connectedScannerId',
                            style: const TextStyle(
                              fontWeight: FontWeight.bold,
                              color: Colors.green,
                            ),
                          ),
                        ),
                    ],
                  ),
                ),
              ),
              const SizedBox(height: 16),

              // Initialize Button
              ElevatedButton.icon(
                onPressed: _initializeSDK,
                icon: const Icon(Icons.settings),
                label: const Text('Initialize SDK'),
                style: ElevatedButton.styleFrom(
                  padding: const EdgeInsets.symmetric(vertical: 16),
                ),
              ),
              const SizedBox(height: 16),

              // Scanner List Section
              const Divider(),
              const SizedBox(height: 8),
              const Text(
                'Scanner Discovery',
                style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
              ),
              const SizedBox(height: 16),

              // Scanner List Buttons
              Row(
                children: [
                  Expanded(
                    child: ElevatedButton.icon(
                      onPressed: _isLoadingScanners
                          ? null
                          : _loadAvailableScanners,
                      icon: _isLoadingScanners
                          ? const SizedBox(
                              width: 16,
                              height: 16,
                              child: CircularProgressIndicator(strokeWidth: 2),
                            )
                          : const Icon(Icons.search),
                      label: const Text('Available Scanners'),
                      style: ElevatedButton.styleFrom(
                        padding: const EdgeInsets.symmetric(vertical: 12),
                      ),
                    ),
                  ),
                  const SizedBox(width: 8),
                  Expanded(
                    child: ElevatedButton.icon(
                      onPressed: _isLoadingScanners
                          ? null
                          : _loadActiveScanners,
                      icon: _isLoadingScanners
                          ? const SizedBox(
                              width: 16,
                              height: 16,
                              child: CircularProgressIndicator(strokeWidth: 2),
                            )
                          : const Icon(Icons.link),
                      label: const Text('Active Scanners'),
                      style: ElevatedButton.styleFrom(
                        padding: const EdgeInsets.symmetric(vertical: 12),
                        backgroundColor: Colors.green,
                        foregroundColor: Colors.white,
                      ),
                    ),
                  ),
                ],
              ),
              const SizedBox(height: 8),
              ElevatedButton.icon(
                onPressed: _isLoadingScanners ? null : _refreshScannersList,
                icon: _isLoadingScanners
                    ? const SizedBox(
                        width: 16,
                        height: 16,
                        child: CircularProgressIndicator(strokeWidth: 2),
                      )
                    : const Icon(Icons.refresh),
                label: const Text('Refresh Scanner List'),
                style: ElevatedButton.styleFrom(
                  padding: const EdgeInsets.symmetric(vertical: 12),
                  backgroundColor: Colors.blue,
                  foregroundColor: Colors.white,
                ),
              ),
              const SizedBox(height: 16),

              // Available Scanners List
              if (_availableScanners.isNotEmpty) ...[
                Text(
                  'Available Scanners (${_availableScanners.length})',
                  style: const TextStyle(
                    fontSize: 16,
                    fontWeight: FontWeight.bold,
                  ),
                ),
                const SizedBox(height: 8),
                ..._availableScanners.map((scanner) {
                  return Card(
                    margin: const EdgeInsets.only(bottom: 8),
                    child: ListTile(
                      leading: Icon(
                        scanner['isActive'] == true
                            ? Icons.check_circle
                            : Icons.radio_button_unchecked,
                        color: scanner['isActive'] == true
                            ? Colors.green
                            : Colors.grey,
                      ),
                      title: Text(
                        scanner['scannerName']?.toString() ?? 'Unknown',
                        style: const TextStyle(fontWeight: FontWeight.bold),
                      ),
                      subtitle: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Text('ID: ${scanner['scannerID']}'),
                          Text(
                            'Type: ${scanner['connectionTypeName'] ?? 'Unknown'}',
                          ),
                          if (scanner['scannerModel']?.toString().isNotEmpty ==
                              true)
                            Text('Model: ${scanner['scannerModel']}'),
                          if (scanner['scannerSerialNumber']
                                  ?.toString()
                                  .isNotEmpty ==
                              true)
                            Text('Serial: ${scanner['scannerSerialNumber']}'),
                        ],
                      ),
                      trailing: scanner['isActive'] == true
                          ? const Chip(
                              label: Text('Active'),
                              backgroundColor: Colors.green,
                              labelStyle: TextStyle(color: Colors.white),
                            )
                          : ElevatedButton(
                              onPressed: () {
                                final scannerId = scanner['scannerID'] as int?;
                                if (scannerId != null) {
                                  _scannerIdController.text = scannerId
                                      .toString();
                                  _connectToScanner();
                                }
                              },
                              child: const Text('Connect'),
                            ),
                    ),
                  );
                }),
                const SizedBox(height: 16),
              ],

              // Active Scanners List
              if (_activeScanners.isNotEmpty) ...[
                Text(
                  'Active Scanners (${_activeScanners.length})',
                  style: const TextStyle(
                    fontSize: 16,
                    fontWeight: FontWeight.bold,
                  ),
                ),
                const SizedBox(height: 8),
                ..._activeScanners.map((scanner) {
                  return Card(
                    margin: const EdgeInsets.only(bottom: 8),
                    color: Colors.green.shade50,
                    child: ListTile(
                      leading: const Icon(
                        Icons.check_circle,
                        color: Colors.green,
                      ),
                      title: Text(
                        scanner['scannerName']?.toString() ?? 'Unknown',
                        style: const TextStyle(fontWeight: FontWeight.bold),
                      ),
                      subtitle: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          Text('ID: ${scanner['scannerID']}'),
                          Text(
                            'Type: ${scanner['connectionTypeName'] ?? 'Unknown'}',
                          ),
                          if (scanner['scannerModel']?.toString().isNotEmpty ==
                              true)
                            Text('Model: ${scanner['scannerModel']}'),
                          if (scanner['scannerSerialNumber']
                                  ?.toString()
                                  .isNotEmpty ==
                              true)
                            Text('Serial: ${scanner['scannerSerialNumber']}'),
                        ],
                      ),
                      trailing: const Chip(
                        label: Text('Connected'),
                        backgroundColor: Colors.green,
                        labelStyle: TextStyle(color: Colors.white),
                      ),
                    ),
                  );
                }),
                const SizedBox(height: 16),
              ],

              // Scanner ID Input
              Card(
                child: Padding(
                  padding: const EdgeInsets.all(16.0),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      const Text(
                        'Scanner ID',
                        style: TextStyle(
                          fontSize: 18,
                          fontWeight: FontWeight.bold,
                        ),
                      ),
                      const SizedBox(height: 8),
                      TextField(
                        controller: _scannerIdController,
                        keyboardType: TextInputType.number,
                        decoration: const InputDecoration(
                          hintText: 'Enter scanner ID (e.g., 123)',
                          border: OutlineInputBorder(),
                          prefixIcon: Icon(Icons.scanner),
                        ),
                      ),
                    ],
                  ),
                ),
              ),
              const SizedBox(height: 16),

              // Connect Button
              ElevatedButton.icon(
                onPressed: _isConnected ? null : _connectToScanner,
                icon: const Icon(Icons.link),
                label: const Text('Connect'),
                style: ElevatedButton.styleFrom(
                  padding: const EdgeInsets.symmetric(vertical: 16),
                  backgroundColor: Colors.green,
                  foregroundColor: Colors.white,
                ),
              ),
              const SizedBox(height: 8),

              // Disconnect Button
              ElevatedButton.icon(
                onPressed: _isConnected ? _disconnectFromScanner : null,
                icon: const Icon(Icons.link_off),
                label: const Text('Disconnect'),
                style: ElevatedButton.styleFrom(
                  padding: const EdgeInsets.symmetric(vertical: 16),
                  backgroundColor: Colors.red,
                  foregroundColor: Colors.white,
                ),
              ),
              const SizedBox(height: 24),

              // Barcode Section
              const Divider(),
              const SizedBox(height: 8),
              const Text(
                'Barcode Scanner',
                style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
              ),
              const SizedBox(height: 16),

              // Last Barcode Card
              if (_lastBarcode.isNotEmpty)
                Card(
                  color: Colors.green.shade50,
                  child: Padding(
                    padding: const EdgeInsets.all(16.0),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        const Row(
                          children: [
                            Icon(Icons.qr_code_scanner, color: Colors.green),
                            SizedBox(width: 8),
                            Text(
                              'Last Scanned Barcode',
                              style: TextStyle(
                                fontSize: 18,
                                fontWeight: FontWeight.bold,
                              ),
                            ),
                          ],
                        ),
                        const SizedBox(height: 12),
                        Text(
                          _lastBarcode,
                          style: const TextStyle(
                            fontSize: 24,
                            fontWeight: FontWeight.bold,
                            color: Colors.green,
                          ),
                        ),
                        if (_lastBarcodeType.isNotEmpty) ...[
                          const SizedBox(height: 8),
                          Text(
                            'Type: $_lastBarcodeType',
                            style: const TextStyle(
                              fontSize: 14,
                              color: Colors.grey,
                            ),
                          ),
                        ],
                      ],
                    ),
                  ),
                )
              else
                Card(
                  child: Padding(
                    padding: const EdgeInsets.all(16.0),
                    child: Row(
                      children: [
                        const Icon(Icons.qr_code_scanner, color: Colors.grey),
                        const SizedBox(width: 8),
                        Text(
                          _isConnected
                              ? 'Scan a barcode to see it here'
                              : 'Connect to scanner to scan barcodes',
                          style: const TextStyle(color: Colors.grey),
                        ),
                      ],
                    ),
                  ),
                ),
              const SizedBox(height: 16),

              // Event Log Section
              const Text(
                'Event Log',
                style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
              ),
              const SizedBox(height: 8),
              Card(
                child: Container(
                  height: 150,
                  padding: const EdgeInsets.all(8.0),
                  child: _eventLog.isEmpty
                      ? const Center(
                          child: Text(
                            'No events yet',
                            style: TextStyle(color: Colors.grey),
                          ),
                        )
                      : ListView.builder(
                          itemCount: _eventLog.length,
                          itemBuilder: (context, index) {
                            return Padding(
                              padding: const EdgeInsets.symmetric(
                                vertical: 2.0,
                              ),
                              child: Text(
                                _eventLog[index],
                                style: const TextStyle(
                                  fontSize: 12,
                                  fontFamily: 'monospace',
                                ),
                              ),
                            );
                          },
                        ),
                ),
              ),
              const SizedBox(height: 24),

              // Scale Section
              if (_isConnected) ...[
                const Divider(),
                const SizedBox(height: 8),
                const Text(
                  'Scale Controls',
                  style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
                ),
                const SizedBox(height: 16),

                // Enable/Disable Scale Toggle
                Card(
                  child: SwitchListTile(
                    title: const Text('Enable Scale'),
                    subtitle: Text(
                      _isScaleEnabled
                          ? 'Scale is enabled'
                          : 'Scale is disabled',
                    ),
                    value: _isScaleEnabled,
                    onChanged: _isConnected
                        ? (value) {
                            if (value) {
                              _enableScale();
                            } else {
                              _disableScale();
                            }
                          }
                        : null,
                  ),
                ),
                const SizedBox(height: 16),

                // Weight Display Card
                if (_weight.isNotEmpty || _weightStatus.isNotEmpty)
                  Card(
                    color: Colors.blue.shade50,
                    child: Padding(
                      padding: const EdgeInsets.all(16.0),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          const Text(
                            'Weight Reading',
                            style: TextStyle(
                              fontSize: 18,
                              fontWeight: FontWeight.bold,
                            ),
                          ),
                          const SizedBox(height: 12),
                          if (_weight.isNotEmpty)
                            Row(
                              children: [
                                Text(
                                  _weight,
                                  style: const TextStyle(
                                    fontSize: 32,
                                    fontWeight: FontWeight.bold,
                                    color: Colors.blue,
                                  ),
                                ),
                                if (_weightMode.isNotEmpty) ...[
                                  const SizedBox(width: 8),
                                  Text(
                                    _weightMode,
                                    style: const TextStyle(
                                      fontSize: 20,
                                      color: Colors.grey,
                                    ),
                                  ),
                                ],
                              ],
                            ),
                          if (_weightStatus.isNotEmpty) ...[
                            const SizedBox(height: 8),
                            Text(
                              'Status: $_weightStatus',
                              style: const TextStyle(
                                fontSize: 14,
                                color: Colors.grey,
                              ),
                            ),
                          ],
                        ],
                      ),
                    ),
                  ),
                const SizedBox(height: 16),

                // Scale Control Buttons
                Row(
                  children: [
                    Expanded(
                      child: ElevatedButton.icon(
                        onPressed: _isScaleEnabled && !_isLiveWeightRunning
                            ? _readWeight
                            : null,
                        icon: const Icon(Icons.scale),
                        label: const Text('Read Weight'),
                        style: ElevatedButton.styleFrom(
                          padding: const EdgeInsets.symmetric(vertical: 12),
                        ),
                      ),
                    ),
                    const SizedBox(width: 8),
                    Expanded(
                      child: ElevatedButton.icon(
                        onPressed: _isScaleEnabled
                            ? (_isLiveWeightRunning
                                  ? _stopLiveWeight
                                  : _startLiveWeight)
                            : null,
                        icon: Icon(
                          _isLiveWeightRunning ? Icons.stop : Icons.play_arrow,
                        ),
                        label: Text(
                          _isLiveWeightRunning ? 'Stop Live' : 'Live Weight',
                        ),
                        style: ElevatedButton.styleFrom(
                          padding: const EdgeInsets.symmetric(vertical: 12),
                          backgroundColor: _isLiveWeightRunning
                              ? Colors.orange
                              : Colors.green,
                          foregroundColor: Colors.white,
                        ),
                      ),
                    ),
                  ],
                ),
                const SizedBox(height: 8),
                Row(
                  children: [
                    Expanded(
                      child: ElevatedButton.icon(
                        onPressed: _isScaleEnabled ? _zeroScale : null,
                        icon: const Icon(Icons.exposure_zero),
                        label: const Text('Zero Scale'),
                        style: ElevatedButton.styleFrom(
                          padding: const EdgeInsets.symmetric(vertical: 12),
                          backgroundColor: Colors.blue,
                          foregroundColor: Colors.white,
                        ),
                      ),
                    ),
                    const SizedBox(width: 8),
                    Expanded(
                      child: ElevatedButton.icon(
                        onPressed: _isScaleEnabled ? _resetScale : null,
                        icon: const Icon(Icons.refresh),
                        label: const Text('Reset Scale'),
                        style: ElevatedButton.styleFrom(
                          padding: const EdgeInsets.symmetric(vertical: 12),
                          backgroundColor: Colors.purple,
                          foregroundColor: Colors.white,
                        ),
                      ),
                    ),
                  ],
                ),
              ],
            ],
          ),
        ),
      ),
    );
  }
}