added dependency checking
- Dependency install states will be checked and will be automatically installed if it isn't.
This commit is contained in:
		
							parent
							
								
									87bd857bfb
								
							
						
					
					
						commit
						32c837bfb2
					
				
					 1 changed files with 343 additions and 303 deletions
				
			
		
							
								
								
									
										116
									
								
								dance.py
									
										
									
									
									
								
							
							
						
						
									
										116
									
								
								dance.py
									
										
									
									
									
								
							|  | @ -1,3 +1,36 @@ | |||
| import os | ||||
| 
 | ||||
| def check_dependencies():  | ||||
|     def check_dependency_aiohttp():  | ||||
|         while True: | ||||
|             try:  | ||||
|                 import aiohttp | ||||
|             except:  | ||||
|                 os.system('pip3 install aiohttp==3.7.4') | ||||
|             else:  | ||||
|                 break | ||||
| 
 | ||||
|     def check_dependency_hidapi(): | ||||
|         while True:  | ||||
|             try:  | ||||
|                 import hid | ||||
|             except:  | ||||
|                 os.system('pip3 install hidapi'); os.system('pip3 install hid') | ||||
|             else:  | ||||
|                 break | ||||
| 
 | ||||
|     def check_dependency_websockets(): | ||||
|         while True:  | ||||
|             try:  | ||||
|                 import websockets | ||||
|             except:  | ||||
|                 os.system('pip3 install websockets') | ||||
|             else:  | ||||
|                 break | ||||
|      | ||||
|     check_dependency_aiohttp(); check_dependency_hidapi(); check_dependency_websockets() | ||||
| 
 | ||||
| 
 | ||||
| import asyncio | ||||
| import json | ||||
| import logging | ||||
|  | @ -13,33 +46,33 @@ import hid | |||
| from aiohttp import WSMsgType, web | ||||
| 
 | ||||
| from joydance import JoyDance, PairingState | ||||
| from joydance.constants import (DEFAULT_CONFIG, JOYDANCE_VERSION, | ||||
|                                 WsSubprotocolVersion) | ||||
| from joydance.constants import (DEFAULT_CONFIG, JOYDANCE_VERSION, WsSubprotocolVersion) | ||||
| from pycon import ButtonEventJoyCon, JoyCon | ||||
| from pycon.constants import JOYCON_PRODUCT_IDS, JOYCON_VENDOR_ID | ||||
| 
 | ||||
| logging.getLogger('asyncio').setLevel(logging.WARNING) | ||||
| 
 | ||||
| 
 | ||||
| class WsCommand(Enum): | ||||
| def main():  | ||||
|     try: | ||||
|         class WsCommand(Enum): | ||||
|             GET_JOYCON_LIST = 'get_joycon_list' | ||||
|             CONNECT_JOYCON = 'connect_joycon' | ||||
|             DISCONNECT_JOYCON = 'disconnect_joycon' | ||||
|             UPDATE_JOYCON_STATE = 'update_joycon_state' | ||||
| 
 | ||||
| 
 | ||||
| class PairingMethod(Enum): | ||||
|         class PairingMethod(Enum): | ||||
|             DEFAULT = 'default' | ||||
|             FAST = 'fast' | ||||
|             STADIA = 'stadia' | ||||
|             OLD = 'old' | ||||
| 
 | ||||
| 
 | ||||
| REGEX_PAIRING_CODE = re.compile(r'^\d{6}$') | ||||
| REGEX_LOCAL_IP_ADDRESS = re.compile(r'^(192\.168|10.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5]))\.((\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.)(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$') | ||||
|         REGEX_PAIRING_CODE = re.compile(r'^\d{6}$') | ||||
|         REGEX_LOCAL_IP_ADDRESS = re.compile(r'^(192\.168|10.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5]))\.((\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.)(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$') | ||||
| 
 | ||||
| 
 | ||||
| async def get_device_ids(): | ||||
|         async def get_device_ids(): | ||||
|             devices = hid.enumerate(JOYCON_VENDOR_ID, 0) | ||||
| 
 | ||||
|             out = [] | ||||
|  | @ -65,7 +98,7 @@ async def get_device_ids(): | |||
|             return out | ||||
| 
 | ||||
| 
 | ||||
| async def get_joycon_list(app): | ||||
|         async def get_joycon_list(app): | ||||
|             joycons = [] | ||||
|             devices = await get_device_ids() | ||||
| 
 | ||||
|  | @ -106,7 +139,7 @@ async def get_joycon_list(app): | |||
|             return sorted(joycons, key=lambda x: (x['name'], x['color'], x['serial'])) | ||||
| 
 | ||||
| 
 | ||||
| async def connect_joycon(app, ws, data): | ||||
|         async def connect_joycon(app, ws, data): | ||||
|             async def on_joydance_state_changed(serial, state): | ||||
|                 print(serial, state) | ||||
|                 app['joycons_info'][serial]['state'] = state.value | ||||
|  | @ -171,7 +204,7 @@ async def connect_joycon(app, ws, data): | |||
|             asyncio.create_task(joydance.pair()) | ||||
| 
 | ||||
| 
 | ||||
| async def disconnect_joycon(app, ws, data): | ||||
|         async def disconnect_joycon(app, ws, data): | ||||
|             print(data) | ||||
|             serial = data['joycon_serial'] | ||||
|             joydance = app['joydance_connections'][serial] | ||||
|  | @ -187,7 +220,7 @@ async def disconnect_joycon(app, ws, data): | |||
|                 pass | ||||
| 
 | ||||
| 
 | ||||
| def parse_config(): | ||||
|         def parse_config(): | ||||
|             parser = ConfigParser() | ||||
|             parser.read('config.cfg') | ||||
| 
 | ||||
|  | @ -226,15 +259,15 @@ def parse_config(): | |||
|             return parser | ||||
| 
 | ||||
| 
 | ||||
| def is_valid_pairing_code(val): | ||||
|         def is_valid_pairing_code(val): | ||||
|             return re.match(REGEX_PAIRING_CODE, val) is not None | ||||
| 
 | ||||
| 
 | ||||
| def is_valid_ip_address(val): | ||||
|         def is_valid_ip_address(val): | ||||
|             return re.match(REGEX_LOCAL_IP_ADDRESS, val) is not None | ||||
| 
 | ||||
| 
 | ||||
| def is_valid_pairing_method(val): | ||||
|         def is_valid_pairing_method(val): | ||||
|             return val in [ | ||||
|                 PairingMethod.DEFAULT.value, | ||||
|                 PairingMethod.FAST.value, | ||||
|  | @ -243,7 +276,7 @@ def is_valid_pairing_method(val): | |||
|             ] | ||||
| 
 | ||||
| 
 | ||||
| def get_host_ip(): | ||||
|         def get_host_ip(): | ||||
|             try: | ||||
|                 for ip in socket.gethostbyname_ex(socket.gethostname())[2]: | ||||
|                     if ip.startswith('192.168') or ip.startswith('10.'): | ||||
|  | @ -254,32 +287,28 @@ def get_host_ip(): | |||
|             return None | ||||
| 
 | ||||
| 
 | ||||
| def save_config(parser): | ||||
|         def save_config(parser): | ||||
|             with open('config.cfg', 'w') as fp: | ||||
|                 parser.write(fp) | ||||
| 
 | ||||
| 
 | ||||
| async def on_startup(app): | ||||
|     print(''' | ||||
|      ░░  ░░░░░░  ░░    ░░ ░░░░░░   ░░░░░  ░░░    ░░  ░░░░░░ ░░░░░░░ | ||||
|      ▒▒ ▒▒    ▒▒  ▒▒  ▒▒  ▒▒   ▒▒ ▒▒   ▒▒ ▒▒▒▒   ▒▒ ▒▒      ▒▒ | ||||
|      ▒▒ ▒▒    ▒▒   ▒▒▒▒   ▒▒   ▒▒ ▒▒▒▒▒▒▒ ▒▒ ▒▒  ▒▒ ▒▒      ▒▒▒▒▒ | ||||
| ▓▓   ▓▓ ▓▓    ▓▓    ▓▓    ▓▓   ▓▓ ▓▓   ▓▓ ▓▓  ▓▓ ▓▓ ▓▓      ▓▓ | ||||
|  █████   ██████     ██    ██████  ██   ██ ██   ████  ██████ ███████ | ||||
| 
 | ||||
| Open http://localhost:32623 in your browser.''') | ||||
|         async def on_startup(app): | ||||
|             os.system('clear') | ||||
| 
 | ||||
|             # Check for update | ||||
|             async with aiohttp.ClientSession() as session: | ||||
|                 async with session.get('https://api.github.com/repos/redphx/joydance/releases/latest', ssl=False) as resp: | ||||
|                     json_body = await resp.json() | ||||
|                     latest_version = json_body['tag_name'][1:] | ||||
|             print('Running version {}.'.format(JOYDANCE_VERSION)) | ||||
|                     print('JoyDance V{}.'.format(JOYDANCE_VERSION)) | ||||
|                     if JOYDANCE_VERSION != latest_version: | ||||
|                         print('\033[93m{}\033[00m'.format('Version {} is available: https://github.com/redphx/joydance'.format(latest_version))) | ||||
|              | ||||
|             time.sleep(2) | ||||
|             os.system('open "http://localhost:32623"') | ||||
| 
 | ||||
| async def html_handler(request): | ||||
| 
 | ||||
|         async def html_handler(request): | ||||
|             config = dict((parse_config()).items('joydance')) | ||||
|             with open('static/index.html', 'r') as f: | ||||
|                 html = f.read() | ||||
|  | @ -288,7 +317,7 @@ async def html_handler(request): | |||
|                 return web.Response(text=html, content_type='text/html') | ||||
| 
 | ||||
| 
 | ||||
| async def ws_send_response(ws, cmd, data): | ||||
|         async def ws_send_response(ws, cmd, data): | ||||
|             resp = { | ||||
|                 'cmd': 'resp_' + cmd.value, | ||||
|                 'data': data, | ||||
|  | @ -296,7 +325,7 @@ async def ws_send_response(ws, cmd, data): | |||
|             await ws.send_json(resp) | ||||
| 
 | ||||
| 
 | ||||
| async def websocket_handler(request): | ||||
|         async def websocket_handler(request): | ||||
|             ws = web.WebSocketResponse() | ||||
|             await ws.prepare(request) | ||||
| 
 | ||||
|  | @ -325,21 +354,32 @@ async def websocket_handler(request): | |||
|             return ws | ||||
| 
 | ||||
| 
 | ||||
| def favicon_handler(request): | ||||
|         def favicon_handler(request): | ||||
|             return web.FileResponse('static/favicon.png') | ||||
| 
 | ||||
| 
 | ||||
| app = web.Application() | ||||
| app['joydance_connections'] = {} | ||||
| app['joycons_info'] = {} | ||||
|         app = web.Application() | ||||
|         app['joydance_connections'] = {} | ||||
|         app['joycons_info'] = {} | ||||
| 
 | ||||
| app.on_startup.append(on_startup) | ||||
| app.add_routes([ | ||||
|         app.on_startup.append(on_startup) | ||||
|         app.add_routes([ | ||||
|             web.get('/', html_handler), | ||||
|             web.get('/favicon.png', favicon_handler), | ||||
|             web.get('/ws', websocket_handler), | ||||
|             web.static('/css', 'static/css'), | ||||
|             web.static('/js', 'static/js'), | ||||
| ]) | ||||
|         ]) | ||||
| 
 | ||||
| web.run_app(app, port=32623) | ||||
|         web.run_app(app, port=32623) | ||||
|      | ||||
|     except KeyboardInterrupt:  | ||||
|         os.system('clear') | ||||
|         return(0) | ||||
|      | ||||
|     except TypeError:  | ||||
|         os.system('clear') | ||||
|         return(0) | ||||
| 
 | ||||
| check_dependencies() | ||||
| main() | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue