svc: Load URL list from file
Instead of hard-coding the list of URLs to open, we'll read it from a JSON file on the disk. The file contains a mapping of monitor names to URLs, e.g. ```json { "HDMI-1": "http://my.site.one", "HDMI-2": "http://my.site.two" } ```master
parent
939f24d79f
commit
dbf266de5b
|
@ -86,3 +86,8 @@ async def refresh_screen(number: int):
|
||||||
@app.on_event('shutdown')
|
@app.on_event('shutdown')
|
||||||
async def on_shutdown():
|
async def on_shutdown():
|
||||||
await svc.shutdown()
|
await svc.shutdown()
|
||||||
|
|
||||||
|
|
||||||
|
@app.on_event('startup')
|
||||||
|
async def on_startup():
|
||||||
|
await svc.startup()
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import json
|
||||||
import logging
|
import logging
|
||||||
from typing import List, Optional
|
from pathlib import Path
|
||||||
|
from typing import Dict, List, Optional
|
||||||
|
|
||||||
import pydantic
|
import pydantic
|
||||||
from aiomarionette import Marionette, WindowRect
|
from aiomarionette import Marionette, WindowRect
|
||||||
|
@ -10,11 +12,6 @@ from .xrandr import MonitorConfig
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
URLS = [
|
|
||||||
'https://grafana.pyrocufflink.blue/d/p3CPbi87z/hud?kiosk',
|
|
||||||
'https://grafana.pyrocufflink.blue/d/lGT5FHOnz/home?kiosk',
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class NoMonitorConfig(Exception):
|
class NoMonitorConfig(Exception):
|
||||||
'''Raised when no monitor config has been provided yet'''
|
'''Raised when no monitor config has been provided yet'''
|
||||||
|
@ -33,6 +30,9 @@ class HUDService:
|
||||||
self.port: Optional[int] = None
|
self.port: Optional[int] = None
|
||||||
self.monitor_config: Optional[MonitorConfig] = None
|
self.monitor_config: Optional[MonitorConfig] = None
|
||||||
self.marionette: Optional[Marionette] = None
|
self.marionette: Optional[Marionette] = None
|
||||||
|
self.urls: Dict[str, str] = {}
|
||||||
|
|
||||||
|
self.urls_file = Path('urls.json')
|
||||||
|
|
||||||
async def get_screens(self) -> List[HUDScreen]:
|
async def get_screens(self) -> List[HUDScreen]:
|
||||||
assert self.marionette
|
assert self.marionette
|
||||||
|
@ -57,29 +57,55 @@ class HUDService:
|
||||||
'Initializing display for %d monitors',
|
'Initializing display for %d monitors',
|
||||||
len(self.monitor_config.monitors),
|
len(self.monitor_config.monitors),
|
||||||
)
|
)
|
||||||
window = await self.marionette.new_window('window')
|
window: Optional[str] = await self.marionette.new_window('window')
|
||||||
for handle in await self.marionette.get_window_handles():
|
for handle in await self.marionette.get_window_handles():
|
||||||
if handle == window:
|
if handle == window:
|
||||||
continue
|
continue
|
||||||
await self.marionette.switch_to_window(handle)
|
await self.marionette.switch_to_window(handle)
|
||||||
await self.marionette.close_window()
|
await self.marionette.close_window()
|
||||||
tasks = []
|
tasks = []
|
||||||
for i, monitor in enumerate(self.monitor_config.monitors):
|
for monitor in self.monitor_config.monitors:
|
||||||
try:
|
try:
|
||||||
url = URLS[i]
|
url = self.urls[monitor.name]
|
||||||
except IndexError:
|
except KeyError:
|
||||||
break
|
continue
|
||||||
|
if window is None:
|
||||||
|
window = await self.marionette.new_window('window')
|
||||||
await self.marionette.switch_to_window(window)
|
await self.marionette.switch_to_window(window)
|
||||||
await self.marionette.set_window_rect(
|
await self.marionette.set_window_rect(
|
||||||
x=monitor.pos_x,
|
x=monitor.pos_x,
|
||||||
y=1,
|
y=1,
|
||||||
)
|
)
|
||||||
await self.marionette.fullscreen()
|
await self.marionette.fullscreen()
|
||||||
log.info('Screen %d: Opening URL %s', i, url)
|
log.info('Screen %s: Opening URL %s', monitor.name, url)
|
||||||
tasks.append(asyncio.create_task(self.marionette.navigate(url)))
|
tasks.append(asyncio.create_task(self.marionette.navigate(url)))
|
||||||
if i + 1 < min(len(URLS), len(self.monitor_config.monitors)):
|
window = None
|
||||||
window = await self.marionette.new_window('window')
|
if tasks:
|
||||||
await asyncio.wait(tasks)
|
await asyncio.wait(tasks)
|
||||||
|
|
||||||
|
def load_urls(self) -> None:
|
||||||
|
try:
|
||||||
|
f = self.urls_file.open(encoding='utf-8')
|
||||||
|
except FileNotFoundError:
|
||||||
|
return
|
||||||
|
except OSError as e:
|
||||||
|
log.error('Could not load URL list: %s', e)
|
||||||
|
return
|
||||||
|
log.info('Loading URL list from %s', self.urls_file)
|
||||||
|
with f:
|
||||||
|
try:
|
||||||
|
value = json.load(f)
|
||||||
|
except ValueError as e:
|
||||||
|
log.error('Failed to load URL list: %s', e)
|
||||||
|
return
|
||||||
|
if isinstance(value, dict):
|
||||||
|
self.urls = value
|
||||||
|
else:
|
||||||
|
log.error(
|
||||||
|
'Invalid URL list: found %r, expected %r',
|
||||||
|
type(value),
|
||||||
|
dict,
|
||||||
|
)
|
||||||
|
|
||||||
async def refresh_screen(self, number: int) -> None:
|
async def refresh_screen(self, number: int) -> None:
|
||||||
assert self.marionette
|
assert self.marionette
|
||||||
|
@ -101,3 +127,7 @@ class HUDService:
|
||||||
if self.marionette is not None:
|
if self.marionette is not None:
|
||||||
await self.marionette.close()
|
await self.marionette.close()
|
||||||
self.marionette = None
|
self.marionette = None
|
||||||
|
|
||||||
|
async def startup(self) -> None:
|
||||||
|
loop = asyncio.get_running_loop()
|
||||||
|
await loop.run_in_executor(None, self.load_urls)
|
||||||
|
|
Loading…
Reference in New Issue