tocoteron / joycon-python

driver for Joy-Con (Nintendo Switch)
Other
116 stars 27 forks source link

how to prevent auto-sleep? #29

Open ericries opened 2 years ago

ericries commented 2 years ago

I have an app where the joycons are connected to bluetooth but can be idle for a long period of time. I'm finding that the joycons turn themselves off after a while, even though I am actively talking to them via the joycon-python api. Is there any way to prevent this?

pbsds commented 2 years ago

Are you just reading, or are you writing to it? Changing the LEDs could keep it awake.

ericries commented 2 years ago

Thanks for the suggestion. I'm just sending rumble commands, basically using command 0x10 with rumble data to activate, along with (0x01,0x48,0x00) to turn the rumble off.

I'll try changing the LED periodically. Do you have a specific command or option you think would work best? set_player_lamp_on maybe?

pbsds commented 2 years ago

Flashing leds likely won't work if rumbling doesn't. Have you looked into whether nintendo labo auto-sleeps?

ericries commented 2 years ago

forgive me, I don't know what the nintendo labo is. can you point me in the right direction? can you share a bit about why that info is helpful?

pbsds commented 2 years ago

Nintendo Labo are cardboard toys that you put a joycon into, turning that cardboard into some game controller. This is mainly achieved using the gyro, the accelerometer and the IR camera. A few of these toys make the buttons inaccessible, making me think there has to be either some flag or mode that does what you need. When i think about it, the ring fit switch game also should require disabling the auto-sleep.

ericries commented 2 years ago

I've been banging my head against this all day, reading as much as I can find about the joycon reverse engineering efforts.

I wrote a script that drives a single joycon on my laptop as long as it can. It very suspiciously loses its connection around 900 seconds every time, which really suggests some kind of internal timeout. I can't figure out how refresh it though.

I've also read the source code for tons of other joycon hid apis from other languages (they are really quite interesting). The chromium folks have a pretty comprehensive implementation, for example: https://chromium.googlesource.com/chromium/src/+/HEAD/device/gamepad/nintendo_controller.cc

but I don't see anyone doing anything special to keep the connection alive. I feel like I must be missing something obvious, but I'm running out of things to try. I implemented a number of the other subcommands (like USB Timeout, "shipment" etc) but to no avail. I would grateful if anyone can suggest anything else to try.

NanoExplorer commented 7 months ago

Hi! I'm encountering the same problem. This is pretty late but the 'hack' I implemented is to periodically close the hid device and reopen it. In my first test this extended the connection lifetime to 20 minutes (up from 15 but I'd like to see at least an hour.)

The reason I tested this idea is that if I close the python program and reopen it, the 15 minute timeout clock seems to begin when I open the program as opposed to when I first connected the joycon.

pbsds commented 7 months ago

perhaps the timeout is a hard limit? the wiiu pro controller will time out unless you press the A button, no matter if you press any of the other buttons. On the switch pro controller I've noticed that if you enable the gyro it will stay connected, but this will also burn the battery quite a lot faster.

NanoExplorer commented 7 months ago

I don't know. When using this library I am pressing buttons on the joycon, which doesn't help. And on the other side of things, there are a couple other libraries that don't have this issue (like SDL I think and Steam). I tried digging around in the SDL source code but couldn't find anything particularly useful. And since they're not like sending special packets to the joycon, I wonder if somehow the OS doesn't see our low level packet exchanges and disconnects the controller because it appears idle? I should mention I'm on Mac.

ericries commented 5 months ago

@NanoExplorer I think that makes a lot of sense. I've been wondering for a while now if it could be a MacOS bluetooth driver issue, but I hadn't thought of any way to test that or make progress on it. Let me know if you ever found a solution?

NanoExplorer commented 5 months ago

Since I have the luxury of pressing buttons and could deal with a couple seconds of delay every fifteen minutes, I just made my script catch the errors that were being thrown on disconnect and then wait for a reconnect. I don't know of any way to test it either.

ericries commented 5 months ago

Let me know if you're interested in debugging this further. I feel like with multiple people/machines/joycons we are much more likely to be able to find the issue using some kind of test script.

I've also thought about digging into the underlying macos gamepad API. maybe there's some kind of keepalive in the driver we could activate

ericries commented 5 months ago

perhaps the timeout is a hard limit? the wiiu pro controller will time out unless you press the A button, no matter if you press any of the other buttons. On the switch pro controller I've noticed that if you enable the gyro it will stay connected, but this will also burn the battery quite a lot faster.

It doesn't appear to be a hard limit, since we have examples of programs that seem to be able to connect to the joycon indefinitely. On macos there is an API in the IOKit that seems to allow more flexibility (including notifications when an HID device is connected/disconnected) that I think could be very useful for debugging: https://stackoverflow.com/questions/9918429/how-to-know-when-a-hid-usb-bluetooth-device-is-connected-in-cocoa

but sadly I don't know enough about cocoa to be able to access this api. does anyone know anything about how to do it?

NanoExplorer commented 5 months ago

I'd definitely be willing to debug, but I don't have time to contribute to development.

ericries commented 5 months ago

That sounds good. I'd be glad to have the help. What kind of hardware/software are you testing on?

I noticed that the pyglet library (https://pyglet.org/) has a cocoa-based IOKit HID library, so I was playing around with that to see if I can get reliable OS-level notifications when the joycon is connected/disconnected. Open to other places to start debugging, too.