bluetooth_connection_plugin 1.0.0 copy "bluetooth_connection_plugin: ^1.0.0" to clipboard
bluetooth_connection_plugin: ^1.0.0 copied to clipboard

A Flutter plugin for connecting to Bluetooth devices, specifically designed for weighing machines and similar devices. Supports device discovery, connection, data reading, and real-time weight monitoring.

example/lib/main.dart

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

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Bluetooth Connection Plugin Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        useMaterial3: true,
      ),
      home: const BluetoothDemoScreen(),
    );
  }
}

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

  @override
  State<BluetoothDemoScreen> createState() => _BluetoothDemoScreenState();
}

class _BluetoothDemoScreenState extends State<BluetoothDemoScreen> {
  List<BluetoothDeviceInfo> pairedDevices = [];
  bool isLoading = false;
  bool isConnecting = false;
  Map<String, dynamic>? connectedDevice;
  String? connectingDeviceAddress;
  List<String> receivedData = [];
  String currentWeight = 'No weight data';
  bool isGettingWeight = false;

  @override
  void initState() {
    super.initState();
    BluetoothConnectionPlugin.initialize();
  }

  Future<void> getPairedDevices() async {
    setState(() {
      isLoading = true;
    });

    try {
      final List<Map<String, dynamic>> result =
          await BluetoothConnectionPlugin.getPairedDevices();
      setState(() {
        pairedDevices =
            result.map((item) => BluetoothDeviceInfo.fromMap(item)).toList();
        isLoading = false;
      });

      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text('Found ${pairedDevices.length} paired devices'),
            backgroundColor: Colors.green,
          ),
        );
      }
    } on BluetoothException catch (e) {
      setState(() {
        isLoading = false;
      });

      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text('Error: ${e.message}'),
            backgroundColor: Colors.red,
          ),
        );
      }
    }
  }

  Future<void> connectToDevice(String deviceAddress, String deviceName) async {
    setState(() {
      isConnecting = true;
      connectingDeviceAddress = deviceAddress;
    });

    try {
      final Map<String, dynamic> result =
          await BluetoothConnectionPlugin.connectToDevice(deviceAddress);

      setState(() {
        connectedDevice = result;
        isConnecting = false;
        connectingDeviceAddress = null;
      });

      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text('Connected to $deviceName'),
            backgroundColor: Colors.green,
          ),
        );
      }
    } on BluetoothException catch (e) {
      setState(() {
        isConnecting = false;
        connectingDeviceAddress = null;
      });

      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text('Connection failed: ${e.message}'),
            backgroundColor: Colors.red,
          ),
        );
      }
    }
  }

  Future<void> disconnectDevice() async {
    try {
      await BluetoothConnectionPlugin.disconnectDevice();
      setState(() {
        connectedDevice = null;
        receivedData.clear();
      });

      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(
            content: Text('Disconnected from device'),
            backgroundColor: Colors.orange,
          ),
        );
      }
    } on BluetoothException catch (e) {
      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text('Disconnect failed: ${e.message}'),
            backgroundColor: Colors.red,
          ),
        );
      }
    }
  }

  Future<void> getWeight() async {
    setState(() {
      isGettingWeight = true;
    });

    try {
      final BluetoothData result = await BluetoothConnectionPlugin.readData();

      setState(() {
        if (result.data.isNotEmpty) {
          String cleanWeight = result.cleanWeight;

          // Only add to receivedData if it's different from the last reading
          String timestampStr = result.dateTime.toString().substring(11, 19);
          String newEntry = '$timestampStr: $cleanWeight';

          // Avoid duplicate consecutive readings
          if (receivedData.isEmpty || receivedData.last != newEntry) {
            currentWeight = cleanWeight;
            receivedData.add(newEntry);

            // Keep only last 20 readings to prevent UI clutter
            if (receivedData.length > 20) {
              receivedData.removeAt(0);
            }
          }
        } else {
          currentWeight = 'No data received';
        }
        isGettingWeight = false;
      });

      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text(result.data.isNotEmpty
                ? 'Weight: ${result.cleanWeight}'
                : 'No weight data received'),
            backgroundColor:
                result.data.isNotEmpty ? Colors.green : Colors.orange,
          ),
        );
      }
    } on BluetoothException catch (e) {
      setState(() {
        currentWeight = 'Error reading weight';
        isGettingWeight = false;
      });

      if (mounted) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text('Failed to get weight: ${e.message}'),
            backgroundColor: Colors.red,
          ),
        );
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Bluetooth Connection Plugin Demo'),
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        actions: [
          if (connectedDevice != null)
            IconButton(
              icon: const Icon(Icons.bluetooth_connected),
              onPressed: disconnectDevice,
              tooltip: 'Disconnect',
            ),
        ],
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: SingleChildScrollView(
          child: Column(
            children: [
              // Connection status card
              if (connectedDevice != null)
                Card(
                  color: Colors.green.shade50,
                  child: Padding(
                    padding: const EdgeInsets.all(16.0),
                    child: Column(
                      children: [
                        Row(
                          children: [
                            const Icon(Icons.bluetooth_connected,
                                color: Colors.green),
                            const SizedBox(width: 8),
                            Expanded(
                              child: Column(
                                crossAxisAlignment: CrossAxisAlignment.start,
                                children: [
                                  Text(
                                    'Connected to: ${connectedDevice!['deviceName']}',
                                    style: const TextStyle(
                                        fontWeight: FontWeight.bold),
                                  ),
                                  Text(
                                      'Address: ${connectedDevice!['deviceAddress']}'),
                                ],
                              ),
                            ),
                            ElevatedButton(
                              onPressed: disconnectDevice,
                              style: ElevatedButton.styleFrom(
                                backgroundColor: Colors.red,
                                foregroundColor: Colors.white,
                              ),
                              child: const Text('Disconnect'),
                            ),
                          ],
                        ),
                        const SizedBox(height: 16),
                        // Data control buttons
                        Row(
                          children: [
                            ElevatedButton.icon(
                              onPressed: () {
                                setState(() {
                                  receivedData.clear();
                                });
                              },
                              icon: const Icon(Icons.clear),
                              label: const Text('Clear'),
                              style: ElevatedButton.styleFrom(
                                backgroundColor: Colors.grey,
                                foregroundColor: Colors.white,
                              ),
                            ),
                          ],
                        ),
                        const SizedBox(height: 16),
                        // Weight section
                        Container(
                          padding: const EdgeInsets.all(12),
                          decoration: BoxDecoration(
                            border: Border.all(color: Colors.grey.shade300),
                            borderRadius: BorderRadius.circular(8),
                            color: Colors.grey.shade50,
                          ),
                          child: Row(
                            children: [
                              const Icon(Icons.monitor_weight,
                                  color: Colors.blue),
                              const SizedBox(width: 8),
                              Expanded(
                                child: Column(
                                  crossAxisAlignment: CrossAxisAlignment.start,
                                  children: [
                                    const Text(
                                      'Current Weight:',
                                      style: TextStyle(
                                        fontSize: 12,
                                        color: Colors.grey,
                                      ),
                                    ),
                                    Text(
                                      currentWeight,
                                      style: const TextStyle(
                                        fontSize: 16,
                                        fontWeight: FontWeight.bold,
                                        fontFamily: 'monospace',
                                      ),
                                    ),
                                  ],
                                ),
                              ),
                              const SizedBox(width: 8),
                              ElevatedButton.icon(
                                onPressed: isGettingWeight ? null : getWeight,
                                icon: isGettingWeight
                                    ? const SizedBox(
                                        width: 16,
                                        height: 16,
                                        child: CircularProgressIndicator(
                                            strokeWidth: 2),
                                      )
                                    : const Icon(Icons.refresh),
                                label: Text(isGettingWeight
                                    ? 'Getting...'
                                    : 'Get Weight'),
                                style: ElevatedButton.styleFrom(
                                  backgroundColor: Colors.blue,
                                  foregroundColor: Colors.white,
                                ),
                              ),
                            ],
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              const SizedBox(height: 16),
              if (connectedDevice == null)
                Center(
                  child: ElevatedButton(
                    onPressed: isLoading ? null : getPairedDevices,
                    child: isLoading
                        ? const Row(
                            mainAxisSize: MainAxisSize.min,
                            children: [
                              SizedBox(
                                width: 20,
                                height: 20,
                                child:
                                    CircularProgressIndicator(strokeWidth: 2),
                              ),
                              SizedBox(width: 8),
                              Text('Loading...'),
                            ],
                          )
                        : const Text('Get Paired Devices'),
                  ),
                ),
              const SizedBox(height: 20),
              // Paired devices section
              if (connectedDevice == null)
                SizedBox(
                  height: 300,
                  child: pairedDevices.isEmpty
                      ? const Center(
                          child: Text(
                            'No paired devices found.\nTap the button to scan for paired devices.',
                            textAlign: TextAlign.center,
                            style: TextStyle(fontSize: 16, color: Colors.grey),
                          ),
                        )
                      : ListView.builder(
                          itemCount: pairedDevices.length,
                          itemBuilder: (context, index) {
                            final device = pairedDevices[index];
                            final isCurrentlyConnecting = isConnecting &&
                                connectingDeviceAddress == device.address;

                            return Card(
                              margin: const EdgeInsets.symmetric(vertical: 4),
                              child: ListTile(
                                leading: Icon(
                                  Icons.bluetooth,
                                  color: Colors.blue,
                                ),
                                title: Text(
                                  device.name,
                                  style: const TextStyle(
                                      fontWeight: FontWeight.bold),
                                ),
                                subtitle: Column(
                                  crossAxisAlignment: CrossAxisAlignment.start,
                                  children: [
                                    Text('Address: ${device.address}'),
                                    Text('Type: ${device.type}'),
                                  ],
                                ),
                                trailing: isCurrentlyConnecting
                                    ? const SizedBox(
                                        width: 20,
                                        height: 20,
                                        child: CircularProgressIndicator(
                                            strokeWidth: 2),
                                      )
                                    : const Icon(Icons.arrow_forward_ios,
                                        size: 16),
                                onTap: () {
                                  if (!isConnecting) {
                                    connectToDevice(
                                        device.address, device.name);
                                  }
                                },
                              ),
                            );
                          },
                        ),
                ),
              // Data display section
              if (connectedDevice != null && receivedData.isNotEmpty) ...[
                const SizedBox(height: 16),
                Card(
                  child: Padding(
                    padding: const EdgeInsets.all(16.0),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      children: [
                        Row(
                          children: [
                            const Icon(Icons.data_usage, color: Colors.blue),
                            const SizedBox(width: 8),
                            Text(
                              'Received Data (${receivedData.length} messages)',
                              style: const TextStyle(
                                fontWeight: FontWeight.bold,
                                fontSize: 16,
                              ),
                            ),
                          ],
                        ),
                        const SizedBox(height: 8),
                        Container(
                          height: 200,
                          width: double.infinity,
                          decoration: BoxDecoration(
                            border: Border.all(color: Colors.grey.shade300),
                            borderRadius: BorderRadius.circular(8),
                          ),
                          child: ListView.builder(
                            itemCount: receivedData.length,
                            itemBuilder: (context, index) {
                              return Padding(
                                padding: const EdgeInsets.symmetric(
                                  horizontal: 8,
                                  vertical: 2,
                                ),
                                child: Text(
                                  receivedData[index],
                                  style: const TextStyle(
                                    fontFamily: 'monospace',
                                    fontSize: 12,
                                  ),
                                ),
                              );
                            },
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            ],
          ),
        ),
      ),
    );
  }
}
0
likes
0
points
21
downloads

Publisher

unverified uploader

Weekly Downloads

A Flutter plugin for connecting to Bluetooth devices, specifically designed for weighing machines and similar devices. Supports device discovery, connection, data reading, and real-time weight monitoring.

Repository (GitHub)
View/report issues

Topics

#bluetooth #weighing-machine #iot #device-communication #serial-communication

Documentation

Documentation

License

unknown (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on bluetooth_connection_plugin

Packages that implement bluetooth_connection_plugin