+"""Provide a server ControlPi Plugin WSServer for websockets."""
import aiofiles
import aiohttp
import asyncio
import sys
from websockets.datastructures import Headers
from websockets.exceptions import ConnectionClosed
-from websockets.legacy.server import serve, WebSocketServerProtocol
+from websockets.server import serve, WebSocketServerProtocol
from controlpi import (BasePlugin, MessageBus, BusException,
Message, MessageTemplate)
"""
CONF_SCHEMA = {'properties':
- {'host': {'type': 'string'},
- 'port': {'type': 'integer'},
+ {'host': {'type': 'string', 'default': None},
+ 'port': {'type': 'integer', 'default': 80},
'web': {'type': 'object',
'patternProperties':
{'^/[A-Za-z0-9]*$':
"""
def process_conf(self) -> None:
- """Get host, port and path settings from configuration."""
- self._host = None
- if 'host' in self.conf:
- self._host = self.conf['host']
- else:
- print(f"'host' not configured for WSServer '{self.name}'."
- " Serving on all interfaces.")
- self._port = 80
- if 'port' in self.conf:
- self._port = self.conf['port']
- else:
- print(f"'port' not configured for WSServer '{self.name}'."
- " Using port 80.")
+ """Process web configuration."""
self._web_locations = {}
self._web_proxies = {}
if 'web' in self.conf:
if 'module' in path_conf:
# Determine location relative to module directory:
module_file = sys.modules[path_conf['module']].__file__
- module_dir = os.path.dirname(module_file)
- location = os.path.join(module_dir, 'web', location)
+ if module_file:
+ module_dir = os.path.dirname(module_file)
+ location = os.path.join(module_dir, 'web',
+ location)
+ else:
+ continue
else:
# Determine location relative to working directory:
- location = os.path.join(os.getcwd(), location)
+ location = os.path.join(os.getcwd(),
+ location)
self._web_locations[path] = os.path.realpath(location)
elif 'url' in path_conf:
base_url = path_conf['url']
async def _process_request(self, path: str,
request_headers: Headers) -> Response:
+ """Serve as simple web server."""
if 'Upgrade' in request_headers:
return None
status = None
async def _handler(self, websocket: WebSocketServerProtocol,
path: str) -> None:
+ """Create and run connection."""
connection = Connection(self.bus, websocket)
await connection.run()
async def run(self) -> None:
"""Set up websocket server."""
while True:
+ loop = asyncio.get_running_loop()
+ stop = loop.create_future()
try:
async with serve(self._handler,
- host=self._host,
- port=self._port,
+ host=self.conf['host'],
+ port=self.conf['port'],
process_request=self._process_request):
print(f"WSServer '{self.name}'"
- f" serving on port {self._port}.")
- await asyncio.Future()
+ f" serving on port {self.conf['port']}.")
+ await stop
except OSError:
await asyncio.sleep(1)