|
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
import asyncio
|
|
import asyncio
|
|
import gzip
|
|
import gzip
|
|
import json
|
|
import json
|
|
|
|
+import logging
|
|
import re
|
|
import re
|
|
from dataclasses import dataclass
|
|
from dataclasses import dataclass
|
|
from typing import TYPE_CHECKING, Any, AsyncIterator, Dict, Optional
|
|
from typing import TYPE_CHECKING, Any, AsyncIterator, Dict, Optional
|
|
@@ -34,6 +35,7 @@ class Air:
|
|
def __init__(self, token: str) -> None:
|
|
def __init__(self, token: str) -> None:
|
|
import httpx # pylint: disable=import-outside-toplevel
|
|
import httpx # pylint: disable=import-outside-toplevel
|
|
|
|
|
|
|
|
+ self.log = logging.getLogger('nicegui.air')
|
|
self.token = token
|
|
self.token = token
|
|
self.relay = socketio.AsyncClient()
|
|
self.relay = socketio.AsyncClient()
|
|
self.client = httpx.AsyncClient(app=core.app)
|
|
self.client = httpx.AsyncClient(app=core.app)
|
|
@@ -172,28 +174,35 @@ class Air:
|
|
|
|
|
|
async def connect(self) -> None:
|
|
async def connect(self) -> None:
|
|
"""Connect to the NiceGUI On Air server."""
|
|
"""Connect to the NiceGUI On Air server."""
|
|
- if self.connecting or self.relay.connected:
|
|
|
|
|
|
+ if self.connecting:
|
|
|
|
+ self.log.debug('Already connecting.')
|
|
return
|
|
return
|
|
|
|
+ if self.relay.connected:
|
|
|
|
+ return
|
|
|
|
+ self.log.debug('Going to connect...')
|
|
self.connecting = True
|
|
self.connecting = True
|
|
backoff_time = 1
|
|
backoff_time = 1
|
|
try:
|
|
try:
|
|
while True:
|
|
while True:
|
|
try:
|
|
try:
|
|
if self.relay.connected:
|
|
if self.relay.connected:
|
|
- await self.relay.disconnect()
|
|
|
|
|
|
+ await asyncio.wait_for(self.disconnect(), timeout=5)
|
|
|
|
+ self.log.debug('Connecting...')
|
|
await self.relay.connect(
|
|
await self.relay.connect(
|
|
f'{RELAY_HOST}?device_token={self.token}',
|
|
f'{RELAY_HOST}?device_token={self.token}',
|
|
socketio_path='/on_air/socket.io',
|
|
socketio_path='/on_air/socket.io',
|
|
transports=['websocket', 'polling'], # favor websocket over polling
|
|
transports=['websocket', 'polling'], # favor websocket over polling
|
|
)
|
|
)
|
|
|
|
+ self.log.debug('Connected.')
|
|
break
|
|
break
|
|
except socketio.exceptions.ConnectionError:
|
|
except socketio.exceptions.ConnectionError:
|
|
- pass
|
|
|
|
|
|
+ self.log.debug('Connection error.', stack_info=True)
|
|
except ValueError: # NOTE this sometimes happens when the internal socketio client is not yet ready
|
|
except ValueError: # NOTE this sometimes happens when the internal socketio client is not yet ready
|
|
- pass
|
|
|
|
|
|
+ self.log.debug('ValueError while connecting.', stack_info=True)
|
|
except Exception:
|
|
except Exception:
|
|
log.exception('Could not connect to NiceGUI On Air server.')
|
|
log.exception('Could not connect to NiceGUI On Air server.')
|
|
|
|
|
|
|
|
+ self.log.debug(f'Retrying in {backoff_time} seconds...')
|
|
await asyncio.sleep(backoff_time)
|
|
await asyncio.sleep(backoff_time)
|
|
backoff_time = min(backoff_time * 2, 32)
|
|
backoff_time = min(backoff_time * 2, 32)
|
|
finally:
|
|
finally:
|
|
@@ -201,11 +210,13 @@ class Air:
|
|
|
|
|
|
async def disconnect(self) -> None:
|
|
async def disconnect(self) -> None:
|
|
"""Disconnect from the NiceGUI On Air server."""
|
|
"""Disconnect from the NiceGUI On Air server."""
|
|
|
|
+ self.log.debug('Disconnecting...')
|
|
if self.relay.connected:
|
|
if self.relay.connected:
|
|
await self.relay.disconnect()
|
|
await self.relay.disconnect()
|
|
for stream in self.streams.values():
|
|
for stream in self.streams.values():
|
|
await stream.response.aclose()
|
|
await stream.response.aclose()
|
|
self.streams.clear()
|
|
self.streams.clear()
|
|
|
|
+ self.log.debug('Disconnected.')
|
|
|
|
|
|
async def emit(self, message_type: str, data: Dict[str, Any], room: str) -> None:
|
|
async def emit(self, message_type: str, data: Dict[str, Any], room: str) -> None:
|
|
"""Emit a message to the NiceGUI On Air server."""
|
|
"""Emit a message to the NiceGUI On Air server."""
|