diff --git a/examples/example_list_connected.py b/examples/example_list_connected.py new file mode 100644 index 0000000..7dfa8fe --- /dev/null +++ b/examples/example_list_connected.py @@ -0,0 +1,121 @@ +""" +Example demonstrating how to retrieve connected TAP devices before establishing connections. +This addresses the issue where the SDK couldn't establish connections with already connected TAPs. + +This example works on both Windows and Unix platforms. +""" + +import asyncio +import platform +import time + + +def OnConnect(identifier, name, fw): + print(f"{identifier} - Connected. Name: {name}, FW Version: {fw}") + + +def OnDisconnect(identifier): + print(f"{identifier} - Disconnected") + + +def OnTapped(identifier, tapcode): + print(f"{identifier} - Tapped: {tapcode}") + + +async def demonstrate_list_connected_taps(): + """ + Demonstrate how to list connected TAP devices before running the SDK. + This helps with debugging connection issues and ensures the SDK can work + with already connected devices. + """ + current_platform = platform.system() + print(f"Running on {current_platform}") + print("=" * 50) + + # Import the SDK (this will automatically choose the right backend) + from tapsdk import TapSDK, TapInputMode + + # Create SDK instance + if current_platform in ["Darwin", "Linux"]: + # Unix platforms use async event loop + loop = asyncio.get_event_loop() + client = TapSDK(loop=loop) + else: + # Windows platform + client = TapSDK() + + print("Checking for connected TAP devices...") + + try: + # List connected TAPs before running the SDK + connected_taps = await client.list_connected_taps() + + if connected_taps: + print(f"Found {len(connected_taps)} connected TAP device(s):") + for i, tap in enumerate(connected_taps): + print(f" {i+1}. {tap}") + else: + print("No connected TAP devices found.") + print("Make sure your TAP device is:") + print(" 1. Powered on") + print(" 2. Paired with your system") + print(" 3. Connected via Bluetooth") + return + + except Exception as e: + print(f"Error retrieving connected TAPs: {e}") + print("This might indicate a compatibility issue with the TAPManager version.") + # Continue anyway, as the SDK might still work + + print("\nStarting SDK...") + + # Register event handlers + if hasattr(client, 'register_connection_events'): + if asyncio.iscoroutinefunction(client.register_connection_events): + await client.register_connection_events(OnConnect) + else: + client.register_connection_events(OnConnect) + + if hasattr(client, 'register_disconnection_events'): + if asyncio.iscoroutinefunction(client.register_disconnection_events): + await client.register_disconnection_events(OnDisconnect) + else: + client.register_disconnection_events(OnDisconnect) + + if hasattr(client, 'register_tap_events'): + if asyncio.iscoroutinefunction(client.register_tap_events): + await client.register_tap_events(OnTapped) + else: + client.register_tap_events(OnTapped) + + # Run the SDK + if asyncio.iscoroutinefunction(client.run): + await client.run() + else: + client.run() + + print("SDK started successfully!") + print("Try tapping on your TAP device...") + + # Set controller mode + if hasattr(client, 'set_input_mode'): + if asyncio.iscoroutinefunction(client.set_input_mode): + await client.set_input_mode(TapInputMode("controller")) + else: + client.set_input_mode(TapInputMode("controller")) + + # Wait a bit to receive events + print("Listening for TAP events for 10 seconds...") + await asyncio.sleep(10) + + print("Example completed!") + + +if __name__ == "__main__": + if platform.system() in ["Darwin", "Linux"]: + # Unix platforms + loop = asyncio.get_event_loop() + loop.run_until_complete(demonstrate_list_connected_taps()) + else: + # Windows platform - create event loop + asyncio.run(demonstrate_list_connected_taps()) \ No newline at end of file diff --git a/examples/example_win.py b/examples/example_win.py index 8497f19..24cad0d 100644 --- a/examples/example_win.py +++ b/examples/example_win.py @@ -63,6 +63,24 @@ def on_raw_sensor_data(identifier, raw_sensor_data): def main(): global tap_instance tap_instance = TapSDK() + + # NEW: List connected TAP devices before starting + print("Checking for connected TAP devices...") + try: + import asyncio + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) + connected_taps = loop.run_until_complete(tap_instance.list_connected_taps()) + if connected_taps: + print(f"Found {len(connected_taps)} connected TAP device(s):") + for i, tap in enumerate(connected_taps): + print(f" {i+1}. {tap}") + else: + print("No connected TAP devices found. Make sure your TAP is paired and connected.") + except Exception as e: + print(f"Could not retrieve connected TAPs: {e}") + print("Continuing anyway...") + tap_instance.run() tap_instance.register_connection_events(on_connect) tap_instance.register_disconnection_events(on_disconnect) diff --git a/tapsdk/TapSDK.py b/tapsdk/TapSDK.py index f93aa62..0f5d9fe 100644 --- a/tapsdk/TapSDK.py +++ b/tapsdk/TapSDK.py @@ -46,4 +46,8 @@ def send_vibration_sequence(self, sequence, identifier): def run(self): raise NotImplementedError + @abc.abstractmethod + async def list_connected_taps(self): + raise NotImplementedError + diff --git a/tapsdk/backends/dotnet/TapSDK.py b/tapsdk/backends/dotnet/TapSDK.py index b218c19..08adacd 100644 --- a/tapsdk/backends/dotnet/TapSDK.py +++ b/tapsdk/backends/dotnet/TapSDK.py @@ -64,5 +64,47 @@ def run(self): self.set_default_input_mode("controller") TAPManager.Instance.Start() + async def list_connected_taps(self): + """ + Get a list of currently connected TAP devices. + Returns a list of TAP device identifiers. + + This method attempts to retrieve connected TAP devices from the TAPManager. + If the TAPManager doesn't expose the expected methods, it will return an empty list. + """ + try: + # Try to get connected taps from the TAPManager + # The exact method name may vary depending on the TAPWin DLL version + if hasattr(TAPManager.Instance, 'GetConnectedTaps'): + connected_taps = TAPManager.Instance.GetConnectedTaps() + if connected_taps is not None: + # Convert .NET collection to Python list + return list(connected_taps) + elif hasattr(TAPManager.Instance, 'GetConnectedDevices'): + connected_devices = TAPManager.Instance.GetConnectedDevices() + if connected_devices is not None: + return list(connected_devices) + elif hasattr(TAPManager.Instance, 'ConnectedTaps'): + # Try accessing as a property + connected_taps = TAPManager.Instance.ConnectedTaps + if connected_taps is not None: + return list(connected_taps) + elif hasattr(TAPManager.Instance, 'ConnectedDevices'): + # Try accessing as a property + connected_devices = TAPManager.Instance.ConnectedDevices + if connected_devices is not None: + return list(connected_devices) + else: + # Log that the method is not available in this version of TAPWin + print("Warning: TAPManager does not expose connected device enumeration methods") + return [] + except Exception as e: + # Handle any other exceptions that might occur + print(f"Error retrieving connected TAP devices: {e}") + return [] + + # If we reach here, no method was found or all returned None + return [] +