Add Stadia support (#8)

* Log some info

* Fix pairing url and include TLS certificate in the connection request

* Try to fix crashing related to shortcuts

* Add print_exc()

* Fix crash when pressing buttons on Joy-Con (L)

* Linting

* Add "Stadia" pairing method
This commit is contained in:
redphx 2022-04-23 09:35:27 +07:00 committed by GitHub
parent 2ebd7be378
commit e89be3166f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 69 additions and 33 deletions

View file

@ -5,6 +5,7 @@ import socket
import ssl
import time
from enum import Enum
from urllib.parse import urlparse
import aiohttp
import websockets
@ -56,6 +57,7 @@ class JoyDance:
self.host_ip_addr = host_ip_addr
self.console_ip_addr = console_ip_addr
self.host_port = self.get_random_port()
self.tls_certificate = None
self.accel_acquisition_freq_hz = accel_acquisition_freq_hz
self.accel_acquisition_latency = accel_acquisition_latency
@ -114,7 +116,17 @@ class JoyDance:
raise Exception('ERROR: Invalid pairing code!')
json_body = await resp.json()
self.pairing_url = json_body['pairingUrl'].replace('https://', 'wss://') + 'smartphone'
import pprint
pprint.pprint(json_body)
self.pairing_url = json_body['pairingUrl'].replace('https://', 'wss://')
if not self.pairing_url.endswith('/'):
self.pairing_url += '/'
self.pairing_url += 'smartphone'
self.tls_certificate = json_body['tlsCertificate']
print(self.pairing_url)
self.requires_punch_pairing = json_body.get('requiresPunchPairing', False)
async def send_initiate_punch_pairing(self):
@ -205,7 +217,7 @@ class JoyDance:
await self.send_message('JD_CancelKeyboard_PhoneCommandData')
elif __class == 'JD_PhoneUiSetupData':
self.is_input_allowed = True
shortcuts = set()
self.available_shortcuts = set()
if message.get('setupData', {}).get('gameplaySetup', {}).get('pauseSlider', {}):
self.available_shortcuts.add(Command.PAUSE)
@ -274,7 +286,7 @@ class JoyDance:
delta_time += (end - start) * 1000
async def send_command(self):
''' Capture Joycon's input and send to console. Only works on procol v2 '''
''' Capture Joycon's input and send to console. Only works on protocol v2 '''
if self.protocol_version == WsSubprotocolVersion.V1:
return
@ -351,12 +363,15 @@ class JoyDance:
await asyncio.sleep(0.01)
except Exception as e:
print(e)
import traceback
traceback.print_exc()
await self.disconnect()
async def connect_ws(self):
server_hostname = None
if self.protocol_version == WsSubprotocolVersion.V1:
ssl_context = None
server_hostname = None
else:
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ssl_context.set_ciphers('ALL')
@ -364,7 +379,16 @@ class JoyDance:
ssl_context.check_hostname = False
ssl_context.verify_mode = ssl.CERT_NONE
server_hostname = self.console_conn.getpeername()[0] if self.console_conn else None
if self.tls_certificate:
ssl_context.load_verify_locations(cadata=self.tls_certificate)
if '192.168' in self.pairing_url:
if self.console_conn:
server_hostname = self.console_conn.getpeername()[0]
else:
# Stadia
tmp = urlparse(self.pairing_url)
server_hostname = tmp.hostname
subprotocol = WS_SUBPROTOCOLS[self.protocol_version.value]
try:
@ -387,7 +411,8 @@ class JoyDance:
except websockets.ConnectionClosed:
await self.on_state_changed(self.joycon.serial, PairingState.ERROR_CONSOLE_CONNECTION)
await self.disconnect(close_ws=False)
except Exception:
except Exception as e:
print(e)
await self.on_state_changed(self.joycon.serial, PairingState.ERROR_CONSOLE_CONNECTION)
await self.disconnect(close_ws=False)

View file

@ -129,8 +129,8 @@ SHORTCUT_MAPPING = {
}
# Same with Joy-Con (L)
SHORTCUT_MAPPING[JoyConButton.UP] = JoyConButton.X
SHORTCUT_MAPPING[JoyConButton.LEFT] = JoyConButton.Y
SHORTCUT_MAPPING[JoyConButton.MINUS] = JoyConButton.PLUS
SHORTCUT_MAPPING[JoyConButton.L] = JoyConButton.R
SHORTCUT_MAPPING[JoyConButton.ZL] = JoyConButton.ZR
SHORTCUT_MAPPING[JoyConButton.UP] = SHORTCUT_MAPPING[JoyConButton.X]
SHORTCUT_MAPPING[JoyConButton.LEFT] = SHORTCUT_MAPPING[JoyConButton.Y]
SHORTCUT_MAPPING[JoyConButton.MINUS] = SHORTCUT_MAPPING[JoyConButton.PLUS]
SHORTCUT_MAPPING[JoyConButton.L] = SHORTCUT_MAPPING[JoyConButton.R]
SHORTCUT_MAPPING[JoyConButton.ZL] = SHORTCUT_MAPPING[JoyConButton.ZR]