diff --git a/lib/bluetooth/devices/openbikecontrol/obc_ble_emulator.dart b/lib/bluetooth/devices/openbikecontrol/obc_ble_emulator.dart index d19a41c..4bf514e 100644 --- a/lib/bluetooth/devices/openbikecontrol/obc_ble_emulator.dart +++ b/lib/bluetooth/devices/openbikecontrol/obc_ble_emulator.dart @@ -42,9 +42,11 @@ class OpenBikeControlBluetoothEmulator extends TrainerConnection { print('Peripheral connection state: ${state.state} of ${state.central.uuid}'); if (state.state == ConnectionState.connected) { } else if (state.state == ConnectionState.disconnected) { - core.connection.signalNotification( - AlertNotification(LogLevel.LOGLEVEL_INFO, 'Disconnected from app: ${connectedApp.value?.appId}'), - ); + if (connectedApp.value != null) { + core.connection.signalNotification( + AlertNotification(LogLevel.LOGLEVEL_INFO, 'Disconnected from app: ${connectedApp.value?.appId}'), + ); + } isConnected.value = false; connectedApp.value = null; _central = null; @@ -108,6 +110,7 @@ class OpenBikeControlBluetoothEmulator extends TrainerConnection { final appInfo = OpenBikeProtocolParser.parseAppInfo(value); isConnected.value = true; connectedApp.value = appInfo; + supportedActions = appInfo.supportedButtons.mapNotNull((b) => b.action).toList(); core.connection.signalNotification( AlertNotification(LogLevel.LOGLEVEL_INFO, 'Connected to app: ${appInfo.appId}'), ); @@ -225,18 +228,20 @@ class OpenBikeControlBluetoothEmulator extends TrainerConnection { @override Future sendAction(KeyPair keyPair, {required bool isKeyDown, required bool isKeyUp}) async { - final buttons = keyPair.buttons; + final inGameAction = keyPair.inGameAction; final mappedButtons = connectedApp.value!.supportedButtons.filter( - (supportedButton) => buttons.any((b) => b.action == supportedButton.action), + (supportedButton) => supportedButton.action == inGameAction, ); - if (_central == null) { + if (inGameAction == null) { + return Error('Invalid in-game action for key pair: $keyPair'); + } else if (_central == null) { return Error('No central connected'); } else if (connectedApp.value == null) { return Error('No app info received from central'); } else if (mappedButtons.isEmpty) { - return NotHandled('App does not support all buttons: ${buttons.map((b) => b.name).join(', ')}'); + return NotHandled('App does not support all buttons for action: ${inGameAction.title}'); } if (isKeyDown && isKeyUp) { @@ -255,6 +260,6 @@ class OpenBikeControlBluetoothEmulator extends TrainerConnection { await _peripheralManager.notifyCharacteristic(_central!, _buttonCharacteristic, value: responseData); } - return Success('Buttons ${buttons.map((b) => b.name).join(', ')} sent'); + return Success('Buttons ${inGameAction?.title} sent'); } } diff --git a/lib/bluetooth/devices/openbikecontrol/obc_mdns_emulator.dart b/lib/bluetooth/devices/openbikecontrol/obc_mdns_emulator.dart index 53dab0f..f6e002f 100644 --- a/lib/bluetooth/devices/openbikecontrol/obc_mdns_emulator.dart +++ b/lib/bluetooth/devices/openbikecontrol/obc_mdns_emulator.dart @@ -137,6 +137,8 @@ class OpenBikeControlMdnsEmulator extends TrainerConnection { final appInfo = OpenBikeProtocolParser.parseAppInfo(Uint8List.fromList(data)); isConnected.value = true; connectedApp.value = appInfo; + + supportedActions = appInfo.supportedButtons.mapNotNull((b) => b.action).toList(); core.connection.signalNotification( AlertNotification(LogLevel.LOGLEVEL_INFO, 'Connected to app: ${appInfo.appId}'), ); @@ -160,19 +162,21 @@ class OpenBikeControlMdnsEmulator extends TrainerConnection { @override Future sendAction(KeyPair keyPair, {required bool isKeyDown, required bool isKeyUp}) async { - final buttons = keyPair.buttons; + final inGameAction = keyPair.inGameAction; final mappedButtons = connectedApp.value!.supportedButtons.filter( - (supportedButton) => buttons.any((b) => b.action == supportedButton.action), + (supportedButton) => supportedButton.action == inGameAction, ); - if (_socket == null) { + if (inGameAction == null) { + return Error('Invalid in-game action for key pair: $keyPair'); + } else if (_socket == null) { print('No client connected, cannot send button press'); return Error('No client connected'); } else if (connectedApp.value == null) { return Error('No app info received from central'); } else if (mappedButtons.isEmpty) { - return NotHandled('App does not support all buttons: ${buttons.map((b) => b.name).join(', ')}'); + return NotHandled('App does not support: ${inGameAction.title}'); } if (isKeyDown && isKeyUp) { @@ -191,7 +195,7 @@ class OpenBikeControlMdnsEmulator extends TrainerConnection { _write(_socket!, responseData); } - return Success('Sent ${buttons.map((b) => b.name).join(', ')} button press'); + return Success('Sent ${inGameAction.title} button press'); } void _write(Socket socket, List responseData) { diff --git a/lib/bluetooth/devices/trainer_connection.dart b/lib/bluetooth/devices/trainer_connection.dart index 3ed881c..501b344 100644 --- a/lib/bluetooth/devices/trainer_connection.dart +++ b/lib/bluetooth/devices/trainer_connection.dart @@ -1,11 +1,11 @@ -import 'package:flutter/foundation.dart'; import 'package:bike_control/utils/actions/base_actions.dart'; import 'package:bike_control/utils/keymap/buttons.dart'; import 'package:bike_control/utils/keymap/keymap.dart'; +import 'package:flutter/foundation.dart'; abstract class TrainerConnection { final String title; - final List supportedActions; + List supportedActions; final ValueNotifier isStarted = ValueNotifier(false); final ValueNotifier isConnected = ValueNotifier(false); diff --git a/lib/pages/button_simulator.dart b/lib/pages/button_simulator.dart index 2bdb85a..fabca20 100644 --- a/lib/pages/button_simulator.dart +++ b/lib/pages/button_simulator.dart @@ -1,17 +1,19 @@ -import 'package:dartx/dartx.dart'; -import 'package:flutter/material.dart' show BackButton; -import 'package:flutter/services.dart'; -import 'package:shadcn_flutter/shadcn_flutter.dart'; import 'package:bike_control/bluetooth/devices/trainer_connection.dart'; import 'package:bike_control/pages/touch_area.dart'; import 'package:bike_control/utils/actions/android.dart'; +import 'package:bike_control/utils/actions/base_actions.dart'; import 'package:bike_control/utils/actions/desktop.dart'; import 'package:bike_control/utils/core.dart'; import 'package:bike_control/utils/i18n_extension.dart'; import 'package:bike_control/utils/keymap/buttons.dart'; import 'package:bike_control/utils/keymap/keymap.dart'; import 'package:bike_control/widgets/ui/gradient_text.dart'; +import 'package:bike_control/widgets/ui/toast.dart'; import 'package:bike_control/widgets/ui/warning.dart'; +import 'package:dartx/dartx.dart'; +import 'package:flutter/material.dart' show BackButton; +import 'package:flutter/services.dart'; +import 'package:shadcn_flutter/shadcn_flutter.dart'; class ButtonSimulator extends StatefulWidget { const ButtonSimulator({super.key}); @@ -328,7 +330,7 @@ class _ButtonSimulatorState extends State { ); return; } else { - await connection.sendAction( + final result = await connection.sendAction( KeyPair( buttons: [], physicalKey: null, @@ -338,6 +340,9 @@ class _ButtonSimulatorState extends State { isKeyDown: down, isKeyUp: !down, ); + if (result is! Success) { + buildToast(context, title: result.message); + } } }