mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2025-12-12 01:00:29 +08:00
meta, refactoring
This commit is contained in:
parent
4294eed14e
commit
17c6b9e31f
2
Makefile
2
Makefile
@ -7,7 +7,7 @@ TESTENV_CMD ?= /bin/bash -c " \
|
|||||||
&& rm -rf /etc/nginx/* \
|
&& rm -rf /etc/nginx/* \
|
||||||
&& cp -r /usr/share/kvmd/configs/nginx/* /etc/nginx \
|
&& cp -r /usr/share/kvmd/configs/nginx/* /etc/nginx \
|
||||||
&& mkdir -p /etc/kvmd \
|
&& mkdir -p /etc/kvmd \
|
||||||
&& cp /usr/share/kvmd/configs/kvmd/logging.yaml /etc/kvmd/logging.yaml \
|
&& cp /usr/share/kvmd/configs/kvmd/{meta.yaml,logging.yaml} /etc/kvmd \
|
||||||
&& cp /testenv/kvmd.yaml /etc/kvmd \
|
&& cp /testenv/kvmd.yaml /etc/kvmd \
|
||||||
&& nginx -c /etc/nginx/nginx.conf \
|
&& nginx -c /etc/nginx/nginx.conf \
|
||||||
&& ln -s $(TESTENV_VIDEO) /dev/kvmd-streamer \
|
&& ln -s $(TESTENV_VIDEO) /dev/kvmd-streamer \
|
||||||
|
|||||||
@ -1,9 +1,15 @@
|
|||||||
|
# Don't touch this file otherwise your device may stop working.
|
||||||
|
# You can find a workable configuration in /usr/share/kvmd/configs/kvmd.
|
||||||
|
|
||||||
kvmd:
|
kvmd:
|
||||||
server:
|
server:
|
||||||
host: 127.0.0.1
|
host: 127.0.0.1
|
||||||
port: 8081
|
port: 8081
|
||||||
heartbeat: 3.0
|
heartbeat: 3.0
|
||||||
|
|
||||||
|
info:
|
||||||
|
meta: /etc/kvmd/meta.yaml
|
||||||
|
|
||||||
log:
|
log:
|
||||||
services:
|
services:
|
||||||
- kvmd.service
|
- kvmd.service
|
||||||
@ -26,7 +32,6 @@ kvmd:
|
|||||||
|
|
||||||
click_delay: 0.1
|
click_delay: 0.1
|
||||||
long_click_delay: 5.5
|
long_click_delay: 5.5
|
||||||
|
|
||||||
state_poll: 0.1
|
state_poll: 0.1
|
||||||
|
|
||||||
msd:
|
msd:
|
||||||
@ -49,6 +54,7 @@ kvmd:
|
|||||||
init_delay: 1.0
|
init_delay: 1.0
|
||||||
init_restart_after: 0.0
|
init_restart_after: 0.0
|
||||||
shutdown_delay: 10.0
|
shutdown_delay: 10.0
|
||||||
|
state_poll: 1.0
|
||||||
|
|
||||||
quality: 80
|
quality: 80
|
||||||
desired_fps: 0
|
desired_fps: 0
|
||||||
@ -71,6 +77,4 @@ kvmd:
|
|||||||
- "--port={port}"
|
- "--port={port}"
|
||||||
- "--drop-same-frames=30"
|
- "--drop-same-frames=30"
|
||||||
|
|
||||||
state_poll: 1.0
|
|
||||||
|
|
||||||
logging: !include logging.yaml
|
logging: !include logging.yaml
|
||||||
|
|||||||
@ -1,9 +1,15 @@
|
|||||||
|
# Don't touch this file otherwise your device may stop working.
|
||||||
|
# You can find a workable configuration in /usr/share/kvmd/configs/kvmd.
|
||||||
|
|
||||||
kvmd:
|
kvmd:
|
||||||
server:
|
server:
|
||||||
host: 127.0.0.1
|
host: 127.0.0.1
|
||||||
port: 8081
|
port: 8081
|
||||||
heartbeat: 3.0
|
heartbeat: 3.0
|
||||||
|
|
||||||
|
info:
|
||||||
|
meta: /etc/kvmd/meta.yaml
|
||||||
|
|
||||||
log:
|
log:
|
||||||
services:
|
services:
|
||||||
- kvmd.service
|
- kvmd.service
|
||||||
@ -26,7 +32,6 @@ kvmd:
|
|||||||
|
|
||||||
click_delay: 0.1
|
click_delay: 0.1
|
||||||
long_click_delay: 5.5
|
long_click_delay: 5.5
|
||||||
|
|
||||||
state_poll: 0.1
|
state_poll: 0.1
|
||||||
|
|
||||||
msd:
|
msd:
|
||||||
@ -49,6 +54,7 @@ kvmd:
|
|||||||
init_delay: 1.0
|
init_delay: 1.0
|
||||||
init_restart_after: 1.0
|
init_restart_after: 1.0
|
||||||
shutdown_delay: 10.0
|
shutdown_delay: 10.0
|
||||||
|
state_poll: 1.0
|
||||||
|
|
||||||
quality: 80
|
quality: 80
|
||||||
desired_fps: 0
|
desired_fps: 0
|
||||||
@ -72,6 +78,4 @@ kvmd:
|
|||||||
- "--host={host}"
|
- "--host={host}"
|
||||||
- "--port={port}"
|
- "--port={port}"
|
||||||
|
|
||||||
state_poll: 1.0
|
|
||||||
|
|
||||||
logging: !include logging.yaml
|
logging: !include logging.yaml
|
||||||
|
|||||||
9
configs/kvmd/meta.yaml
Normal file
9
configs/kvmd/meta.yaml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# You can write down any information and it will be available
|
||||||
|
# at the address /kvmd/info (if you use default nginx config).
|
||||||
|
# If server.host (str) will be defained then this value
|
||||||
|
# will be displayed in the web interface.
|
||||||
|
|
||||||
|
server:
|
||||||
|
host: localhost
|
||||||
|
|
||||||
|
kvm: {}
|
||||||
@ -1,15 +1,10 @@
|
|||||||
import os
|
|
||||||
import argparse
|
import argparse
|
||||||
import logging
|
import logging
|
||||||
import logging.config
|
import logging.config
|
||||||
|
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
from typing import IO
|
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
import yaml
|
from .yaml import load_yaml_file
|
||||||
import yaml.loader
|
|
||||||
import yaml.nodes
|
|
||||||
|
|
||||||
|
|
||||||
# =====
|
# =====
|
||||||
@ -18,32 +13,9 @@ def init() -> Dict:
|
|||||||
parser.add_argument("-c", "--config", required=True, metavar="<path>")
|
parser.add_argument("-c", "--config", required=True, metavar="<path>")
|
||||||
options = parser.parse_args()
|
options = parser.parse_args()
|
||||||
|
|
||||||
config: Dict = _load_yaml_file(options.config)
|
config: Dict = load_yaml_file(options.config)
|
||||||
|
|
||||||
logging.captureWarnings(True)
|
logging.captureWarnings(True)
|
||||||
logging.config.dictConfig(config["logging"])
|
logging.config.dictConfig(config["logging"])
|
||||||
|
|
||||||
return config
|
return config
|
||||||
|
|
||||||
|
|
||||||
# =====
|
|
||||||
def _load_yaml_file(path: str) -> Any:
|
|
||||||
with open(path) as yaml_file:
|
|
||||||
try:
|
|
||||||
return yaml.load(yaml_file, _YamlLoader)
|
|
||||||
except Exception:
|
|
||||||
# Reraise internal exception as standard ValueError and show the incorrect file
|
|
||||||
raise ValueError("Incorrect YAML syntax in file '{}'".format(path))
|
|
||||||
|
|
||||||
|
|
||||||
class _YamlLoader(yaml.loader.Loader): # pylint: disable=too-many-ancestors
|
|
||||||
def __init__(self, yaml_file: IO) -> None:
|
|
||||||
yaml.loader.Loader.__init__(self, yaml_file)
|
|
||||||
self.__root = os.path.dirname(yaml_file.name)
|
|
||||||
|
|
||||||
def include(self, node: yaml.nodes.Node) -> str:
|
|
||||||
path = os.path.join(self.__root, self.construct_scalar(node)) # pylint: disable=no-member
|
|
||||||
return _load_yaml_file(path)
|
|
||||||
|
|
||||||
|
|
||||||
_YamlLoader.add_constructor("!include", _YamlLoader.include) # pylint: disable=no-member
|
|
||||||
|
|||||||
@ -42,6 +42,7 @@ def main() -> None:
|
|||||||
reset_switch=int(config["atx"]["pinout"]["reset_switch"]),
|
reset_switch=int(config["atx"]["pinout"]["reset_switch"]),
|
||||||
click_delay=float(config["atx"]["click_delay"]),
|
click_delay=float(config["atx"]["click_delay"]),
|
||||||
long_click_delay=float(config["atx"]["long_click_delay"]),
|
long_click_delay=float(config["atx"]["long_click_delay"]),
|
||||||
|
state_poll=float(config["atx"]["state_poll"]),
|
||||||
)
|
)
|
||||||
|
|
||||||
msd = MassStorageDevice(
|
msd = MassStorageDevice(
|
||||||
@ -62,6 +63,7 @@ def main() -> None:
|
|||||||
sync_delay=float(config["streamer"]["sync_delay"]),
|
sync_delay=float(config["streamer"]["sync_delay"]),
|
||||||
init_delay=float(config["streamer"]["init_delay"]),
|
init_delay=float(config["streamer"]["init_delay"]),
|
||||||
init_restart_after=float(config["streamer"]["init_restart_after"]),
|
init_restart_after=float(config["streamer"]["init_restart_after"]),
|
||||||
|
state_poll=float(config["streamer"]["state_poll"]),
|
||||||
|
|
||||||
quality=int(config["streamer"]["quality"]),
|
quality=int(config["streamer"]["quality"]),
|
||||||
desired_fps=int(config["streamer"]["desired_fps"]),
|
desired_fps=int(config["streamer"]["desired_fps"]),
|
||||||
@ -83,9 +85,8 @@ def main() -> None:
|
|||||||
msd=msd,
|
msd=msd,
|
||||||
streamer=streamer,
|
streamer=streamer,
|
||||||
|
|
||||||
|
meta_path=str(config["info"]["meta"]),
|
||||||
heartbeat=float(config["server"]["heartbeat"]),
|
heartbeat=float(config["server"]["heartbeat"]),
|
||||||
atx_state_poll=float(config["atx"]["state_poll"]),
|
|
||||||
streamer_state_poll=float(config["streamer"]["state_poll"]),
|
|
||||||
streamer_shutdown_delay=float(config["streamer"]["shutdown_delay"]),
|
streamer_shutdown_delay=float(config["streamer"]["shutdown_delay"]),
|
||||||
msd_chunk_size=int(config["msd"]["chunk_size"]),
|
msd_chunk_size=int(config["msd"]["chunk_size"]),
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
from typing import AsyncGenerator
|
||||||
|
|
||||||
from ...logging import get_logger
|
from ...logging import get_logger
|
||||||
|
|
||||||
@ -13,16 +14,17 @@ class AtxIsBusy(aioregion.RegionIsBusyError):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Atx:
|
class Atx: # pylint: disable=too-many-instance-attributes
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
power_led: int,
|
power_led: int,
|
||||||
hdd_led: int,
|
hdd_led: int,
|
||||||
|
|
||||||
power_switch: int,
|
power_switch: int,
|
||||||
reset_switch: int,
|
reset_switch: int,
|
||||||
|
|
||||||
click_delay: float,
|
click_delay: float,
|
||||||
long_click_delay: float,
|
long_click_delay: float,
|
||||||
|
state_poll: float,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
||||||
self.__power_led = gpio.set_input(power_led)
|
self.__power_led = gpio.set_input(power_led)
|
||||||
@ -33,6 +35,8 @@ class Atx:
|
|||||||
self.__click_delay = click_delay
|
self.__click_delay = click_delay
|
||||||
self.__long_click_delay = long_click_delay
|
self.__long_click_delay = long_click_delay
|
||||||
|
|
||||||
|
self.__state_poll = state_poll
|
||||||
|
|
||||||
self.__region = aioregion.AioExclusiveRegion(AtxIsBusy)
|
self.__region = aioregion.AioExclusiveRegion(AtxIsBusy)
|
||||||
|
|
||||||
def get_state(self) -> Dict:
|
def get_state(self) -> Dict:
|
||||||
@ -44,6 +48,11 @@ class Atx:
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async def poll_state(self) -> AsyncGenerator[Dict, None]:
|
||||||
|
while True:
|
||||||
|
yield self.get_state()
|
||||||
|
await asyncio.sleep(self.__state_poll)
|
||||||
|
|
||||||
async def click_power(self) -> None:
|
async def click_power(self) -> None:
|
||||||
await self.__click(self.__power_switch, self.__click_delay)
|
await self.__click(self.__power_switch, self.__click_delay)
|
||||||
get_logger().info("Clicked power")
|
get_logger().info("Clicked power")
|
||||||
|
|||||||
@ -18,6 +18,8 @@ from ...logging import Log
|
|||||||
|
|
||||||
from ...aioregion import RegionIsBusyError
|
from ...aioregion import RegionIsBusyError
|
||||||
|
|
||||||
|
from ...yaml import load_yaml_file
|
||||||
|
|
||||||
from ... import __version__
|
from ... import __version__
|
||||||
|
|
||||||
from .hid import Hid
|
from .hid import Hid
|
||||||
@ -111,9 +113,8 @@ class Server: # pylint: disable=too-many-instance-attributes
|
|||||||
msd: MassStorageDevice,
|
msd: MassStorageDevice,
|
||||||
streamer: Streamer,
|
streamer: Streamer,
|
||||||
|
|
||||||
|
meta_path: str,
|
||||||
heartbeat: float,
|
heartbeat: float,
|
||||||
atx_state_poll: float,
|
|
||||||
streamer_state_poll: float,
|
|
||||||
streamer_shutdown_delay: float,
|
streamer_shutdown_delay: float,
|
||||||
msd_chunk_size: int,
|
msd_chunk_size: int,
|
||||||
|
|
||||||
@ -126,9 +127,8 @@ class Server: # pylint: disable=too-many-instance-attributes
|
|||||||
self.__msd = msd
|
self.__msd = msd
|
||||||
self.__streamer = streamer
|
self.__streamer = streamer
|
||||||
|
|
||||||
|
self.__meta_path = meta_path
|
||||||
self.__heartbeat = heartbeat
|
self.__heartbeat = heartbeat
|
||||||
self.__atx_state_poll = atx_state_poll
|
|
||||||
self.__streamer_state_poll = streamer_state_poll
|
|
||||||
self.__streamer_shutdown_delay = streamer_shutdown_delay
|
self.__streamer_shutdown_delay = streamer_shutdown_delay
|
||||||
self.__msd_chunk_size = msd_chunk_size
|
self.__msd_chunk_size = msd_chunk_size
|
||||||
|
|
||||||
@ -190,6 +190,7 @@ class Server: # pylint: disable=too-many-instance-attributes
|
|||||||
"streamer": await self.__streamer.get_version(),
|
"streamer": await self.__streamer.get_version(),
|
||||||
},
|
},
|
||||||
"streamer": self.__streamer.get_app(),
|
"streamer": self.__streamer.get_app(),
|
||||||
|
"meta": load_yaml_file(self.__meta_path),
|
||||||
})
|
})
|
||||||
|
|
||||||
@_wrap_exceptions_for_web("Log error")
|
@_wrap_exceptions_for_web("Log error")
|
||||||
@ -198,7 +199,7 @@ class Server: # pylint: disable=too-many-instance-attributes
|
|||||||
follow = _valid_bool("follow", request.query.get("follow", "false"))
|
follow = _valid_bool("follow", request.query.get("follow", "false"))
|
||||||
response = aiohttp.web.StreamResponse(status=200, reason="OK", headers={"Content-Type": "text/plain"})
|
response = aiohttp.web.StreamResponse(status=200, reason="OK", headers={"Content-Type": "text/plain"})
|
||||||
await response.prepare(request)
|
await response.prepare(request)
|
||||||
async for record in self.__log.log(seek, follow):
|
async for record in self.__log.poll_log(seek, follow):
|
||||||
await response.write(("[%s %s] --- %s" % (
|
await response.write(("[%s %s] --- %s" % (
|
||||||
record["dt"].strftime("%Y-%m-%d %H:%M:%S"),
|
record["dt"].strftime("%Y-%m-%d %H:%M:%S"),
|
||||||
record["service"],
|
record["service"],
|
||||||
@ -431,17 +432,15 @@ class Server: # pylint: disable=too-many-instance-attributes
|
|||||||
|
|
||||||
@_system_task
|
@_system_task
|
||||||
async def __poll_atx_state(self) -> None:
|
async def __poll_atx_state(self) -> None:
|
||||||
while True:
|
async for state in self.__atx.poll_state():
|
||||||
if self.__sockets:
|
if self.__sockets:
|
||||||
await self.__broadcast_event("atx_state", **self.__atx.get_state())
|
await self.__broadcast_event("atx_state", **state)
|
||||||
await asyncio.sleep(self.__atx_state_poll)
|
|
||||||
|
|
||||||
@_system_task
|
@_system_task
|
||||||
async def __poll_streamer_state(self) -> None:
|
async def __poll_streamer_state(self) -> None:
|
||||||
while True:
|
async for state in self.__streamer.poll_state():
|
||||||
if self.__sockets:
|
if self.__sockets:
|
||||||
await self.__broadcast_event("streamer_state", **(await self.__streamer.get_state()))
|
await self.__broadcast_event("streamer_state", **state)
|
||||||
await asyncio.sleep(self.__streamer_state_poll)
|
|
||||||
|
|
||||||
async def __broadcast_event(self, event: str, **kwargs: Dict) -> None:
|
async def __broadcast_event(self, event: str, **kwargs: Dict) -> None:
|
||||||
await asyncio.gather(*[
|
await asyncio.gather(*[
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import asyncio.subprocess
|
|||||||
|
|
||||||
from typing import List
|
from typing import List
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
|
from typing import AsyncGenerator
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
@ -15,13 +16,15 @@ from ... import gpio
|
|||||||
|
|
||||||
# =====
|
# =====
|
||||||
class Streamer: # pylint: disable=too-many-instance-attributes
|
class Streamer: # pylint: disable=too-many-instance-attributes
|
||||||
def __init__( # pylint: disable=too-many-arguments
|
def __init__( # pylint: disable=too-many-arguments,too-many-locals
|
||||||
self,
|
self,
|
||||||
cap_power: int,
|
cap_power: int,
|
||||||
conv_power: int,
|
conv_power: int,
|
||||||
|
|
||||||
sync_delay: float,
|
sync_delay: float,
|
||||||
init_delay: float,
|
init_delay: float,
|
||||||
init_restart_after: float,
|
init_restart_after: float,
|
||||||
|
state_poll: float,
|
||||||
|
|
||||||
quality: int,
|
quality: int,
|
||||||
desired_fps: int,
|
desired_fps: int,
|
||||||
@ -38,9 +41,11 @@ class Streamer: # pylint: disable=too-many-instance-attributes
|
|||||||
|
|
||||||
self.__cap_power = (gpio.set_output(cap_power) if cap_power > 0 else cap_power)
|
self.__cap_power = (gpio.set_output(cap_power) if cap_power > 0 else cap_power)
|
||||||
self.__conv_power = (gpio.set_output(conv_power) if conv_power > 0 else conv_power)
|
self.__conv_power = (gpio.set_output(conv_power) if conv_power > 0 else conv_power)
|
||||||
|
|
||||||
self.__sync_delay = sync_delay
|
self.__sync_delay = sync_delay
|
||||||
self.__init_delay = init_delay
|
self.__init_delay = init_delay
|
||||||
self.__init_restart_after = init_restart_after
|
self.__init_restart_after = init_restart_after
|
||||||
|
self.__state_poll = state_poll
|
||||||
|
|
||||||
self.__params = {
|
self.__params = {
|
||||||
"quality": quality,
|
"quality": quality,
|
||||||
@ -99,6 +104,11 @@ class Streamer: # pylint: disable=too-many-instance-attributes
|
|||||||
"state": state,
|
"state": state,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async def poll_state(self) -> AsyncGenerator[Dict, None]:
|
||||||
|
while True:
|
||||||
|
yield (await self.get_state())
|
||||||
|
await asyncio.sleep(self.__state_poll)
|
||||||
|
|
||||||
def get_app(self) -> str:
|
def get_app(self) -> str:
|
||||||
return os.path.basename(self.__cmd[0])
|
return os.path.basename(self.__cmd[0])
|
||||||
|
|
||||||
|
|||||||
@ -33,7 +33,7 @@ class Log:
|
|||||||
self.__services = services
|
self.__services = services
|
||||||
self.__loop = loop
|
self.__loop = loop
|
||||||
|
|
||||||
async def log(self, seek: int, follow: bool) -> AsyncGenerator[Dict, None]:
|
async def poll_log(self, seek: int, follow: bool) -> AsyncGenerator[Dict, None]:
|
||||||
reader = systemd.journal.Reader()
|
reader = systemd.journal.Reader()
|
||||||
reader.this_boot()
|
reader.this_boot()
|
||||||
reader.this_machine()
|
reader.this_machine()
|
||||||
|
|||||||
31
kvmd/yaml.py
Normal file
31
kvmd/yaml.py
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
from typing import IO
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
import yaml.loader
|
||||||
|
import yaml.nodes
|
||||||
|
|
||||||
|
|
||||||
|
# =====
|
||||||
|
def load_yaml_file(path: str) -> Any:
|
||||||
|
with open(path) as yaml_file:
|
||||||
|
try:
|
||||||
|
return yaml.load(yaml_file, _YamlLoader)
|
||||||
|
except Exception:
|
||||||
|
# Reraise internal exception as standard ValueError and show the incorrect file
|
||||||
|
raise ValueError("Incorrect YAML syntax in file '{}'".format(path))
|
||||||
|
|
||||||
|
|
||||||
|
class _YamlLoader(yaml.loader.Loader): # pylint: disable=too-many-ancestors
|
||||||
|
def __init__(self, yaml_file: IO) -> None:
|
||||||
|
yaml.loader.Loader.__init__(self, yaml_file)
|
||||||
|
self.__root = os.path.dirname(yaml_file.name)
|
||||||
|
|
||||||
|
def include(self, node: yaml.nodes.Node) -> str:
|
||||||
|
path = os.path.join(self.__root, self.construct_scalar(node)) # pylint: disable=no-member
|
||||||
|
return load_yaml_file(path)
|
||||||
|
|
||||||
|
|
||||||
|
_YamlLoader.add_constructor("!include", _YamlLoader.include) # pylint: disable=no-member
|
||||||
@ -4,6 +4,9 @@ kvmd:
|
|||||||
port: 8081
|
port: 8081
|
||||||
heartbeat: 3.0
|
heartbeat: 3.0
|
||||||
|
|
||||||
|
info:
|
||||||
|
meta: /etc/kvmd/meta.yaml
|
||||||
|
|
||||||
log:
|
log:
|
||||||
services:
|
services:
|
||||||
- kvmd.service
|
- kvmd.service
|
||||||
@ -25,7 +28,6 @@ kvmd:
|
|||||||
|
|
||||||
click_delay: 0.1
|
click_delay: 0.1
|
||||||
long_click_delay: 5.5
|
long_click_delay: 5.5
|
||||||
|
|
||||||
state_poll: 0.1
|
state_poll: 0.1
|
||||||
|
|
||||||
msd:
|
msd:
|
||||||
@ -48,6 +50,7 @@ kvmd:
|
|||||||
init_delay: 1.0
|
init_delay: 1.0
|
||||||
init_restart_after: 1.0
|
init_restart_after: 1.0
|
||||||
shutdown_delay: 10.0
|
shutdown_delay: 10.0
|
||||||
|
state_poll: 1.0
|
||||||
|
|
||||||
quality: 80
|
quality: 80
|
||||||
desired_fps: 0
|
desired_fps: 0
|
||||||
@ -66,6 +69,4 @@ kvmd:
|
|||||||
- "--host=0.0.0.0"
|
- "--host=0.0.0.0"
|
||||||
- "--port={port}"
|
- "--port={port}"
|
||||||
|
|
||||||
state_poll: 1.0
|
|
||||||
|
|
||||||
logging: !include logging.yaml
|
logging: !include logging.yaml
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user