open_earable_flutter 2.2.1 copy "open_earable_flutter: ^2.2.1" to clipboard
open_earable_flutter: ^2.2.1 copied to clipboard

This package provides functionality for interacting with OpenEarable devices. Control LED colors, control audio, and access raw sensor data.

example/lib/main.dart

import 'dart:async';

import 'package:example/widgets/button_state_widget.dart';
import 'package:example/widgets/fota/firmware_update.dart';
import 'package:open_earable_flutter/open_earable_flutter.dart';
import 'package:example/global_theme.dart';
import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'package:provider/provider.dart';

import 'widgets/frequency_player_widget.dart';
import 'widgets/jingle_player_widget.dart';
import 'widgets/rgb_led_control_widget.dart';
import 'widgets/sensor_configuration_view.dart';
import 'widgets/audio_player_control_widget.dart';
import 'widgets/sensor_view.dart';
import 'widgets/storage_path_audio_player_widget.dart';
import 'widgets/grouped_box.dart';

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

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

  @override
  MyAppState createState() => MyAppState();
}

class MyAppState extends State<MyApp> {
  final WearableManager _wearableManager = WearableManager();
  StreamSubscription? _scanSubscription;
  List discoveredDevices = [];

  DiscoveredDevice? _connectingDevice;
  Wearable? _connectedDevice;

  // Get devices for auto connect
  static List<String> get _autoConnectDevices {
    const devicesString =
        String.fromEnvironment("AUTO_CONNECT_DEVICES", defaultValue: "");
    if (devicesString.isEmpty) return [];
    return devicesString
        .split(",")
        .map((device) => device.trim())
        .where((device) => device.isNotEmpty)
        .toList();
  }

  @override
  void initState() {
    super.initState();

    // Start scanning for devices if not in web
    if (!kIsWeb) _startScanning();

    // Start auto connecting to devices specified in _autoConnectDevices
    _wearableManager.setAutoConnect(_autoConnectDevices);

    // Deal with new connected devices
    _wearableManager.connectStream.listen((wearable) {
      setState(() {
        _connectedDevice = wearable;
        _connectingDevice = null;
      });
      wearable.addDisconnectListener(() {
        if (_connectedDevice?.deviceId == wearable.deviceId) {
          setState(() {
            _connectedDevice = null;
          });
        }
      });
    });

    // Deal with new connecting devices
    _wearableManager.connectingStream.listen((device) {
      setState(() {
        _connectingDevice = device;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
        create: (context) => FirmwareUpdateRequestProvider(),
        builder: (context, child) => MaterialApp(
              theme: materialTheme,
              home: _materialApp(context),
            ));
  }

  Widget _materialApp(BuildContext context) {
    List<SensorView>? sensorViews;
    List<SensorConfigurationView>? sensorConfigurationViews;
    if (_connectedDevice != null) {
      sensorViews = SensorView.createSensorViews(_connectedDevice!);
      sensorConfigurationViews =
          SensorConfigurationView.createSensorConfigurationViews(
        _connectedDevice!,
      );
    }

    return Scaffold(
        appBar: AppBar(
          title: const Text('Bluetooth Devices'),
        ),
        body: SingleChildScrollView(
            child: Padding(
          padding: const EdgeInsets.all(12.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              const Padding(
                padding: EdgeInsets.fromLTRB(33, 16, 0, 0),
                child: Text(
                  "SCANNED DEVICES",
                  style: TextStyle(
                    fontWeight: FontWeight.bold,
                    fontSize: 12.0,
                  ),
                ),
              ),
              Visibility(
                visible: discoveredDevices.isNotEmpty,
                child: Container(
                  decoration: BoxDecoration(
                    border: Border.all(
                      color: Colors.grey,
                      width: 1.0,
                    ),
                    borderRadius: BorderRadius.circular(8.0),
                  ),
                  child: ListView.builder(
                    padding: EdgeInsets.zero,
                    physics: const NeverScrollableScrollPhysics(),
                    // Disable scrolling,
                    shrinkWrap: true,
                    itemCount: discoveredDevices.length,
                    itemBuilder: (BuildContext context, int index) {
                      final device = discoveredDevices[index];
                      final provider =
                          context.read<FirmwareUpdateRequestProvider>();
                      return Column(
                        children: [
                          ListTile(
                            title: Text(device.name),
                            titleTextStyle: const TextStyle(fontSize: 16),
                            visualDensity: const VisualDensity(
                                horizontal: -4, vertical: -4),
                            trailing: _buildTrailingWidget(device.id,
                                Theme.of(context).colorScheme.secondary),
                            onTap: () async {
                              Wearable wearable = await _wearableManager
                                  .connectToDevice(device);
                              provider.setSelectedPeripheral(wearable);
                            },
                          ),
                          if (index != discoveredDevices.length - 1)
                            const Divider(
                              height: 1.0,
                              thickness: 1.0,
                              color: Colors.grey,
                              indent: 16.0,
                              endIndent: 0.0,
                            ),
                        ],
                      );
                    },
                  ),
                ),
              ),
              Center(
                child: ElevatedButton(
                  onPressed: _startScanning,
                  child: const Text('Restart Scan'),
                ),
              ),
              if (_connectedDevice != null)
                GroupedBox(
                  title: "Device Info",
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Text(
                        "Name:                    ${_connectedDevice?.name}",
                      ),
                      if (_connectedDevice is DeviceIdentifier)
                        FutureBuilder<String?>(
                          future: (_connectedDevice as DeviceIdentifier)
                              .readDeviceIdentifier(),
                          builder: (context, snapshot) {
                            return Text(
                              "Device Identifier:   ${snapshot.data}",
                            );
                          },
                        ),
                      if (_connectedDevice is DeviceFirmwareVersion)
                        FutureBuilder<String?>(
                          future: (_connectedDevice as DeviceFirmwareVersion)
                              .readDeviceFirmwareVersion(),
                          builder: (context, snapshot) {
                            return Row(children: [
                              Text(
                                "Firmware Version:  ${snapshot.data}",
                              ),
                              const Spacer(),
                              ElevatedButton(
                                  onPressed: () {
                                    Navigator.push(
                                      context,
                                      MaterialPageRoute(
                                        builder: (context) => Scaffold(
                                          appBar: AppBar(
                                              title: const Text(
                                                  "Update Firmware")),
                                          body: const FirmwareUpdateWidget(),
                                        ),
                                      ),
                                    );
                                  },
                                  child: const Text("Update Firmware"))
                            ]);
                          },
                        ),
                      if (_connectedDevice is DeviceHardwareVersion)
                        FutureBuilder<String?>(
                          future: (_connectedDevice as DeviceHardwareVersion)
                              .readDeviceHardwareVersion(),
                          builder: (context, snapshot) {
                            return Text(
                              "Hardware Version: ${snapshot.data}",
                            );
                          },
                        ),
                    ],
                  ),
                ),
              if (_connectedDevice is RgbLed)
                GroupedBox(
                  title: "RGB LED",
                  child:
                      RgbLedControlWidget(rgbLed: _connectedDevice as RgbLed),
                ),
              if (_connectedDevice is ButtonManager)
                GroupedBox(
                  title: "Button State",
                  child: ButtonStateWidget(buttonManager: _connectedDevice as ButtonManager),
                ),
              if (_connectedDevice is FrequencyPlayer)
                GroupedBox(
                  title: "Frequency Player",
                  child: FrequencyPlayerWidget(
                    frequencyPlayer: _connectedDevice as FrequencyPlayer,
                  ),
                ),
              if (_connectedDevice is JinglePlayer)
                GroupedBox(
                  title: "Jingle Player",
                  child: JinglePlayerWidget(
                    jinglePlayer: _connectedDevice as JinglePlayer,
                  ),
                ),
              if (_connectedDevice is StoragePathAudioPlayer)
                GroupedBox(
                  title: "Storage Path Audio Player",
                  child: StoragePathAudioPlayerWidget(
                    audioPlayer: _connectedDevice as StoragePathAudioPlayer,
                  ),
                ),
              if (_connectedDevice is AudioPlayerControls)
                GroupedBox(
                  title: "Audio Player Controls",
                  child: AudioPlayerControlWidget(
                    audioPlayerControls:
                        _connectedDevice as AudioPlayerControls,
                  ),
                ),
              if (sensorConfigurationViews != null)
                GroupedBox(
                  title: "Sensor Configurations",
                  child: Column(
                    children: sensorConfigurationViews,
                  ),
                ),
              if (sensorViews != null)
                GroupedBox(
                  title: "Sensors",
                  child: Column(
                    children: sensorViews
                        .map((e) => Padding(
                              padding: const EdgeInsets.only(
                                bottom: 6.0,
                                top: 6.0,
                              ),
                              child: e,
                            ))
                        .toList(),
                  ),
                ),
            ]
                .map((e) => Padding(
                      padding: const EdgeInsets.only(
                        bottom: 8.0,
                        top: 8.0,
                      ),
                      child: e,
                    ))
                .toList(),
          ),
        )));
  }

  Widget _buildTrailingWidget(String id, Color successColor) {
    if (_connectedDevice?.deviceId == id) {
      return Icon(size: 24, Icons.check, color: successColor);
    } else if (_connectingDevice?.id == id) {
      return const SizedBox(
        height: 24,
        width: 24,
        child: CircularProgressIndicator(strokeWidth: 2),
      );
    }
    return const SizedBox.shrink();
  }

  void _startScanning() async {
    discoveredDevices.clear();

    _wearableManager.startScan();
    _scanSubscription?.cancel();
    _scanSubscription = _wearableManager.scanStream.listen((incomingDevice) {
      if (incomingDevice.name.isNotEmpty &&
          !discoveredDevices.any((device) => device.id == incomingDevice.id)) {
        setState(() {
          discoveredDevices.add(incomingDevice);
        });
      }
    });
  }
}
2
likes
140
points
265
downloads

Publisher

unverified uploader

Weekly Downloads

This package provides functionality for interacting with OpenEarable devices. Control LED colors, control audio, and access raw sensor data.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

bloc, convert, equatable, file_picker, flutter, flutter_archive, flutter_bloc, http, json_annotation, logger, mcumgr_flutter, meta, path_provider, permission_handler, provider, pub_semver, rxdart, tuple, typed_data, universal_ble, uuid

More

Packages that depend on open_earable_flutter