diff --git a/lib/Backend/Bluetooth/bluetooth_manager_plus.dart b/lib/Backend/Bluetooth/bluetooth_manager_plus.dart index 2dcfe751..7b5f82e5 100644 --- a/lib/Backend/Bluetooth/bluetooth_manager_plus.dart +++ b/lib/Backend/Bluetooth/bluetooth_manager_plus.dart @@ -192,6 +192,13 @@ Future initFlutterBluePlus(InitFlutterBluePlusRef ref) async { //_bluetoothPlusLogger.info('${event.device} ${event.services}'); //Subscribes to all characteristics for (BluetoothService service in event.services) { + BluetoothUartService? bluetoothUartService = uartServices.firstWhereOrNull( + (element) => element.bleDeviceService == service.serviceUuid.str, + ); + if (bluetoothUartService != null) { + BaseStatefulDevice? statefulDevice = ref.read(knownDevicesProvider)[event.device.remoteId.str]; + statefulDevice?.bluetoothUartService.value = bluetoothUartService; + } for (BluetoothCharacteristic characteristic in service.characteristics) { await characteristic.setNotifyValue(true); } @@ -221,7 +228,7 @@ Future initFlutterBluePlus(InitFlutterBluePlusRef ref) async { statefulDevice.messageHistory.add(MessageHistoryEntry(type: MessageHistoryType.receive, message: "Unknown: ${values.toString()}")); return; } - } else if (bluetoothCharacteristic.characteristicUuid == Guid(statefulDevice.baseDeviceDefinition.bleRxCharacteristic)) { + } else if (statefulDevice.bluetoothUartService.value != null || bluetoothCharacteristic.characteristicUuid == Guid(statefulDevice.bluetoothUartService.value!.bleRxCharacteristic)) { String value = ""; try { value = const Utf8Decoder().convert(values); @@ -413,9 +420,9 @@ Future sendMessage(BaseStatefulDevice device, List message, {bool wit return; } BluetoothDevice? bluetoothDevice = flutterBluePlus.connectedDevices.firstWhereOrNull((element) => element.remoteId.str == device.baseStoredDevice.btMACAddress); - if (bluetoothDevice != null) { + if (bluetoothDevice != null && device.bluetoothUartService.value != null) { BluetoothCharacteristic? bluetoothCharacteristic = - bluetoothDevice.servicesList.firstWhereOrNull((element) => element.uuid == Guid(device.baseDeviceDefinition.bleDeviceService))?.characteristics.firstWhereOrNull((element) => element.characteristicUuid == Guid(device.baseDeviceDefinition.bleTxCharacteristic)); + bluetoothDevice.servicesList.firstWhereOrNull((element) => element.uuid == Guid(device.bluetoothUartService.value!.bleDeviceService))?.characteristics.firstWhereOrNull((element) => element.characteristicUuid == Guid(device.bluetoothUartService.value!.bleTxCharacteristic)); if (bluetoothCharacteristic == null) { return; } diff --git a/lib/Backend/Definitions/Device/device_definition.dart b/lib/Backend/Definitions/Device/device_definition.dart index f6a7eb47..7154a562 100644 --- a/lib/Backend/Definitions/Device/device_definition.dart +++ b/lib/Backend/Definitions/Device/device_definition.dart @@ -123,14 +123,33 @@ enum DeviceState { standby, runAction, busy } enum GlowtipStatus { glowtip, noGlowtip, unknown } +@freezed +class BluetoothUartService with _$BluetoothUartService { + const factory BluetoothUartService({ + required String bleDeviceService, + required String bleRxCharacteristic, + required String bleTxCharacteristic, + }) = _BluetoothUartService; +} + +final List uartServices = const [ + BluetoothUartService( + bleDeviceService: "3af2108b-d066-42da-a7d4-55648fa0a9b6", + bleRxCharacteristic: "c6612b64-0087-4974-939e-68968ef294b0", + bleTxCharacteristic: "5bfd6484-ddee-4723-bfe6-b653372bbfd6", + ), + BluetoothUartService( + bleDeviceService: "927dee04-ddd4-4582-8e42-69dc9fbfae66", + bleRxCharacteristic: "0b646a19-371e-4327-b169-9632d56c0e84", + bleTxCharacteristic: "05e026d8-b395-4416-9f8a-c00d6c3781b9", + ), +]; + @freezed class BaseDeviceDefinition with _$BaseDeviceDefinition { const factory BaseDeviceDefinition({ required String uuid, required String btName, - required String bleDeviceService, - required String bleRxCharacteristic, - required String bleTxCharacteristic, required DeviceType deviceType, @Default("") String fwURL, Version? minVersion, @@ -142,6 +161,7 @@ class BaseDeviceDefinition with _$BaseDeviceDefinition { class BaseStatefulDevice { final BaseDeviceDefinition baseDeviceDefinition; final BaseStoredDevice baseStoredDevice; + final ValueNotifier bluetoothUartService = ValueNotifier(null); final ValueNotifier batteryLevel = ValueNotifier(-1); final ValueNotifier batteryCharging = ValueNotifier(false); final ValueNotifier batteryLow = ValueNotifier(false); @@ -167,7 +187,9 @@ class BaseStatefulDevice { BaseStatefulDevice(this.baseDeviceDefinition, this.baseStoredDevice) { commandQueue = CommandQueue(this); - rxCharacteristicStream = flutterBluePlus.events.onCharacteristicReceived.asBroadcastStream().where((event) => event.device.remoteId.str == baseStoredDevice.btMACAddress && event.characteristic.characteristicUuid.str == baseDeviceDefinition.bleRxCharacteristic).map((event) { + rxCharacteristicStream = flutterBluePlus.events.onCharacteristicReceived.asBroadcastStream().where((event) { + return event.device.remoteId.str == baseStoredDevice.btMACAddress && bluetoothUartService.value != null && event.characteristic.characteristicUuid.str == bluetoothUartService.value!.bleRxCharacteristic; + }).map((event) { try { return const Utf8Decoder().convert(event.value); } catch (e) { @@ -175,6 +197,7 @@ class BaseStatefulDevice { } return ""; }).where((event) => event.isNotEmpty); + deviceConnectionState.addListener(() { if (deviceConnectionState.value == ConnectivityState.disconnected) { reset(); diff --git a/lib/Backend/device_registry.dart b/lib/Backend/device_registry.dart index d3a04626..88c6b98b 100644 --- a/lib/Backend/device_registry.dart +++ b/lib/Backend/device_registry.dart @@ -18,9 +18,6 @@ class DeviceRegistry { BaseDeviceDefinition( uuid: "798e1528-2832-4a87-93d7-4d1b25a2f418", btName: "MiTail", - bleDeviceService: "3af2108b-d066-42da-a7d4-55648fa0a9b6", - bleRxCharacteristic: "c6612b64-0087-4974-939e-68968ef294b0", - bleTxCharacteristic: "5bfd6484-ddee-4723-bfe6-b653372bbfd6", deviceType: DeviceType.tail, fwURL: "https://thetailcompany.com/fw/mitailfw", minVersion: Version(major: 5, minor: 0, patch: 0), @@ -28,18 +25,12 @@ class DeviceRegistry { BaseDeviceDefinition( uuid: "9c5f3692-1c6e-4d46-b607-4f6f4a6e28ee", btName: "(!)Tail1", - bleDeviceService: "3af2108b-d066-42da-a7d4-55648fa0a9b6", - bleRxCharacteristic: "c6612b64-0087-4974-939e-68968ef294b0", - bleTxCharacteristic: "5bfd6484-ddee-4723-bfe6-b653372bbfd6", deviceType: DeviceType.tail, unsupported: true, ), BaseDeviceDefinition( uuid: "5fb21175-fef4-448a-a38b-c472d935abab", btName: "minitail", - bleDeviceService: "3af2108b-d066-42da-a7d4-55648fa0a9b6", - bleRxCharacteristic: "c6612b64-0087-4974-939e-68968ef294b0", - bleTxCharacteristic: "5bfd6484-ddee-4723-bfe6-b653372bbfd6", deviceType: DeviceType.miniTail, fwURL: "https://thetailcompany.com/fw/mini", minVersion: Version(major: 5, minor: 0, patch: 0), @@ -47,9 +38,6 @@ class DeviceRegistry { BaseDeviceDefinition( uuid: "e790f509-f95b-4eb4-b649-5b43ee1eee9c", btName: "flutter", - bleDeviceService: "3af2108b-d066-42da-a7d4-55648fa0a9b6", - bleRxCharacteristic: "c6612b64-0087-4974-939e-68968ef294b0", - bleTxCharacteristic: "5bfd6484-ddee-4723-bfe6-b653372bbfd6", deviceType: DeviceType.wings, fwURL: "https://thetailcompany.com/fw/flutter", minVersion: Version(major: 5, minor: 0, patch: 0), @@ -57,18 +45,12 @@ class DeviceRegistry { BaseDeviceDefinition( uuid: "927dee04-ddd4-4582-8e42-69dc9fbfae66", btName: "EG2", - bleDeviceService: "927dee04-ddd4-4582-8e42-69dc9fbfae66", - bleRxCharacteristic: "0b646a19-371e-4327-b169-9632d56c0e84", - bleTxCharacteristic: "05e026d8-b395-4416-9f8a-c00d6c3781b9", deviceType: DeviceType.ears, fwURL: "https://thetailcompany.com/fw/eg", ), BaseDeviceDefinition( uuid: "ba2f2b00-8f65-4cc3-afad-58ba1fccd62d", btName: "EarGear", - bleDeviceService: "927dee04-ddd4-4582-8e42-69dc9fbfae66", - bleRxCharacteristic: "0b646a19-371e-4327-b169-9632d56c0e84", - bleTxCharacteristic: "05e026d8-b395-4416-9f8a-c00d6c3781b9", deviceType: DeviceType.ears, unsupported: true, ), @@ -82,8 +64,12 @@ class DeviceRegistry { return allDevices.firstWhere((BaseDeviceDefinition element) => element.btName.toLowerCase() == id.toLowerCase()); } - static List getAllIds() { - return allDevices.map((BaseDeviceDefinition e) => e.bleDeviceService).toSet().toList(); + static BuiltList getAllIds() { + return uartServices + .map( + (e) => e.bleDeviceService, + ) + .toBuiltList(); } } diff --git a/lib/Frontend/Widgets/manage_gear.dart b/lib/Frontend/Widgets/manage_gear.dart index 4d2b2d93..436824cb 100644 --- a/lib/Frontend/Widgets/manage_gear.dart +++ b/lib/Frontend/Widgets/manage_gear.dart @@ -355,6 +355,7 @@ class _ManageGearDebugState extends State { Text("UNSUPPORTED: ${widget.device.baseDeviceDefinition.unsupported}"), Text("MIN FIRMWARE: ${widget.device.baseDeviceDefinition.minVersion}"), Text("NVS Config: ${widget.device.gearConfigInfo.value}"), + Text("UART Service: ${widget.device.bluetoothUartService.value}"), ], ), ), diff --git a/test/Backend/device_registry_test.dart b/test/Backend/device_registry_test.dart index fe793324..0151ca0d 100644 --- a/test/Backend/device_registry_test.dart +++ b/test/Backend/device_registry_test.dart @@ -140,7 +140,7 @@ void main() { }); }); test('Get all service IDs', () { - List allIds = DeviceRegistry.getAllIds(); + BuiltList allIds = DeviceRegistry.getAllIds(); expect(allIds.length, 2); String itemsAsList = allIds.toString(); expect(itemsAsList, "[3af2108b-d066-42da-a7d4-55648fa0a9b6, 927dee04-ddd4-4582-8e42-69dc9fbfae66]");