mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2025-12-12 01:00:29 +08:00
big config refactoring
This commit is contained in:
parent
cdddf10b5d
commit
7d79f48fd8
@ -7,21 +7,18 @@ kvmd:
|
||||
port: 8081
|
||||
|
||||
hid:
|
||||
pinout:
|
||||
reset: 4
|
||||
reset_pin: 4
|
||||
device: /dev/kvmd-hid
|
||||
|
||||
atx:
|
||||
pinout:
|
||||
power_led: 24
|
||||
hdd_led: 22
|
||||
power_switch: 23
|
||||
reset_switch: 27
|
||||
power_led_pin: 24
|
||||
hdd_led_pin: 22
|
||||
power_switch_pin: 23
|
||||
reset_switch_pin: 27
|
||||
|
||||
msd:
|
||||
pinout:
|
||||
target: 12
|
||||
reset: 13
|
||||
target_pin: 12
|
||||
reset_pin: 13
|
||||
device: /dev/kvmd-msd
|
||||
|
||||
streamer:
|
||||
|
||||
@ -7,27 +7,23 @@ kvmd:
|
||||
port: 8081
|
||||
|
||||
hid:
|
||||
pinout:
|
||||
reset: 4
|
||||
reset_pin: 4
|
||||
device: /dev/kvmd-hid
|
||||
|
||||
atx:
|
||||
pinout:
|
||||
power_led: 24
|
||||
hdd_led: 22
|
||||
power_switch: 23
|
||||
reset_switch: 27
|
||||
power_led_pin: 24
|
||||
hdd_led_pin: 22
|
||||
power_switch_pin: 23
|
||||
reset_switch_pin: 27
|
||||
|
||||
msd:
|
||||
pinout:
|
||||
target: 12
|
||||
reset: 13
|
||||
target_pin: 12
|
||||
reset_pin: 13
|
||||
device: /dev/kvmd-msd
|
||||
|
||||
streamer:
|
||||
pinout:
|
||||
cap: 17
|
||||
conv: 18
|
||||
cap_pin: 17
|
||||
conv_pin: 18
|
||||
init_restart_after: 1
|
||||
host: 127.0.0.1
|
||||
port: 8082
|
||||
|
||||
@ -111,87 +111,83 @@ def _get_config_scheme() -> Dict:
|
||||
return {
|
||||
"kvmd": {
|
||||
"server": {
|
||||
"host": Option(default="localhost"),
|
||||
"port": Option(default=0),
|
||||
"unix": Option(default="", type=_as_optional_path),
|
||||
"unix_rm": Option(default=False),
|
||||
"unix_mode": Option(default=0),
|
||||
"heartbeat": Option(default=3.0),
|
||||
"access_log_format": Option(default="[%P / %{X-Real-IP}i] '%r' => %s; size=%b ---"
|
||||
" referer='%{Referer}i'; user_agent='%{User-Agent}i'"),
|
||||
"host": Option("localhost"),
|
||||
"port": Option(0),
|
||||
"unix": Option("", type=_as_optional_path, rename="unix_path"),
|
||||
"unix_rm": Option(False),
|
||||
"unix_mode": Option(0),
|
||||
"heartbeat": Option(3.0),
|
||||
"access_log_format": Option("[%P / %{X-Real-IP}i] '%r' => %s; size=%b ---"
|
||||
" referer='%{Referer}i'; user_agent='%{User-Agent}i'"),
|
||||
},
|
||||
|
||||
"auth": {
|
||||
"htpasswd": Option(default="/etc/kvmd/htpasswd", type=_as_path),
|
||||
"htpasswd": Option("/etc/kvmd/htpasswd", type=_as_path, rename="htpasswd_path"),
|
||||
},
|
||||
|
||||
"info": {
|
||||
"meta": Option(default="/etc/kvmd/meta.yaml", type=_as_path),
|
||||
"extras": Option(default="/usr/share/kvmd/extras", type=_as_path),
|
||||
"meta": Option("/etc/kvmd/meta.yaml", type=_as_path, rename="meta_path"),
|
||||
"extras": Option("/usr/share/kvmd/extras", type=_as_path, rename="extras_path"),
|
||||
},
|
||||
|
||||
"hid": {
|
||||
"pinout": {
|
||||
"reset": Option(default=0, type=_as_pin),
|
||||
},
|
||||
"reset_delay": Option(default=0.1),
|
||||
"device": Option(default="", type=_as_path),
|
||||
"speed": Option(default=115200),
|
||||
"read_timeout": Option(default=2.0),
|
||||
"read_retries": Option(default=10),
|
||||
"common_retries": Option(default=100),
|
||||
"retries_delay": Option(default=0.1),
|
||||
"noop": Option(default=False),
|
||||
"state_poll": Option(default=0.1),
|
||||
"reset_pin": Option(0, type=_as_pin),
|
||||
"reset_delay": Option(0.1),
|
||||
|
||||
"device": Option("", type=_as_path, rename="device_path"),
|
||||
"speed": Option(115200),
|
||||
"read_timeout": Option(2.0),
|
||||
"read_retries": Option(10),
|
||||
"common_retries": Option(100),
|
||||
"retries_delay": Option(0.1),
|
||||
"noop": Option(False),
|
||||
|
||||
"state_poll": Option(0.1),
|
||||
},
|
||||
|
||||
"atx": {
|
||||
"pinout": {
|
||||
"power_led": Option(default=0, type=_as_pin),
|
||||
"hdd_led": Option(default=0, type=_as_pin),
|
||||
"power_switch": Option(default=0, type=_as_pin),
|
||||
"reset_switch": Option(default=0, type=_as_pin),
|
||||
},
|
||||
"click_delay": Option(default=0.1),
|
||||
"long_click_delay": Option(default=5.5),
|
||||
"state_poll": Option(default=0.1),
|
||||
"power_led_pin": Option(0, type=_as_pin),
|
||||
"hdd_led_pin": Option(0, type=_as_pin),
|
||||
|
||||
"power_switch_pin": Option(0, type=_as_pin),
|
||||
"reset_switch_pin": Option(0, type=_as_pin),
|
||||
"click_delay": Option(0.1),
|
||||
"long_click_delay": Option(5.5),
|
||||
|
||||
"state_poll": Option(0.1),
|
||||
},
|
||||
|
||||
"msd": {
|
||||
"pinout": {
|
||||
"target": Option(default=0, type=_as_pin),
|
||||
"reset": Option(default=0, type=_as_pin),
|
||||
},
|
||||
"device": Option(default="", type=_as_path),
|
||||
"init_delay": Option(default=2.0),
|
||||
"reset_delay": Option(default=1.0),
|
||||
"write_meta": Option(default=True),
|
||||
"chunk_size": Option(default=65536),
|
||||
"target_pin": Option(0, type=_as_pin),
|
||||
"reset_pin": Option(0, type=_as_pin),
|
||||
"device": Option("", type=_as_path, rename="device_path"),
|
||||
"init_delay": Option(2.0),
|
||||
"reset_delay": Option(1.0),
|
||||
"write_meta": Option(True),
|
||||
"chunk_size": Option(65536),
|
||||
},
|
||||
|
||||
"streamer": {
|
||||
"pinout": {
|
||||
"cap": Option(default=-1, type=_as_optional_pin),
|
||||
"conv": Option(default=-1, type=_as_optional_pin),
|
||||
},
|
||||
"cap_pin": Option(-1, type=_as_optional_pin),
|
||||
"conv_pin": Option(-1, type=_as_optional_pin),
|
||||
|
||||
"sync_delay": Option(default=1.0),
|
||||
"init_delay": Option(default=1.0),
|
||||
"init_restart_after": Option(default=0.0),
|
||||
"shutdown_delay": Option(default=10.0),
|
||||
"state_poll": Option(default=1.0),
|
||||
"sync_delay": Option(1.0),
|
||||
"init_delay": Option(1.0),
|
||||
"init_restart_after": Option(0.0),
|
||||
"shutdown_delay": Option(10.0),
|
||||
"state_poll": Option(1.0),
|
||||
|
||||
"quality": Option(default=80),
|
||||
"desired_fps": Option(default=0),
|
||||
"quality": Option(80),
|
||||
"desired_fps": Option(0),
|
||||
|
||||
"host": Option(default="localhost"),
|
||||
"port": Option(default=0),
|
||||
"unix": Option(default="", type=_as_optional_path),
|
||||
"timeout": Option(default=2.0),
|
||||
"host": Option("localhost"),
|
||||
"port": Option(0),
|
||||
"unix": Option("", type=_as_optional_path, rename="unix_path"),
|
||||
"timeout": Option(2.0),
|
||||
|
||||
"cmd": Option(default=["/bin/true"], type=_as_string_list),
|
||||
"cmd": Option(["/bin/true"], type=_as_string_list),
|
||||
},
|
||||
},
|
||||
|
||||
"logging": Option(default={}),
|
||||
"logging": Option({}),
|
||||
}
|
||||
|
||||
@ -20,101 +20,18 @@ from .server import Server
|
||||
def main() -> None:
|
||||
config = init("kvmd", description="The main Pi-KVM daemon")[2].kvmd
|
||||
with gpio.bcm():
|
||||
# pylint: disable=protected-access
|
||||
loop = asyncio.get_event_loop()
|
||||
|
||||
auth_manager = AuthManager(
|
||||
htpasswd_path=config.auth.htpasswd,
|
||||
)
|
||||
|
||||
info_manager = InfoManager(
|
||||
meta_path=config.info.meta,
|
||||
extras_path=config.info.extras,
|
||||
loop=loop,
|
||||
)
|
||||
|
||||
log_reader = LogReader(loop)
|
||||
|
||||
hid = Hid(
|
||||
reset=config.hid.pinout.reset,
|
||||
reset_delay=config.hid.reset_delay,
|
||||
|
||||
device_path=config.hid.device,
|
||||
speed=config.hid.speed,
|
||||
read_timeout=config.hid.read_timeout,
|
||||
read_retries=config.hid.read_retries,
|
||||
common_retries=config.hid.common_retries,
|
||||
retries_delay=config.hid.retries_delay,
|
||||
noop=config.hid.noop,
|
||||
|
||||
state_poll=config.hid.state_poll,
|
||||
)
|
||||
|
||||
atx = Atx(
|
||||
power_led=config.atx.pinout.power_led,
|
||||
hdd_led=config.atx.pinout.hdd_led,
|
||||
power_switch=config.atx.pinout.power_switch,
|
||||
reset_switch=config.atx.pinout.reset_switch,
|
||||
|
||||
click_delay=config.atx.click_delay,
|
||||
long_click_delay=config.atx.long_click_delay,
|
||||
state_poll=config.atx.state_poll,
|
||||
)
|
||||
|
||||
msd = MassStorageDevice(
|
||||
target=config.msd.pinout.target,
|
||||
reset=config.msd.pinout.reset,
|
||||
|
||||
device_path=config.msd.device,
|
||||
init_delay=config.msd.init_delay,
|
||||
reset_delay=config.msd.reset_delay,
|
||||
write_meta=config.msd.write_meta,
|
||||
|
||||
loop=loop,
|
||||
)
|
||||
|
||||
streamer = Streamer(
|
||||
cap_power=config.streamer.pinout.cap,
|
||||
conv_power=config.streamer.pinout.conv,
|
||||
sync_delay=config.streamer.sync_delay,
|
||||
init_delay=config.streamer.init_delay,
|
||||
init_restart_after=config.streamer.init_restart_after,
|
||||
state_poll=config.streamer.state_poll,
|
||||
|
||||
quality=config.streamer.quality,
|
||||
desired_fps=config.streamer.desired_fps,
|
||||
|
||||
host=config.streamer.host,
|
||||
port=config.streamer.port,
|
||||
unix_path=config.streamer.unix,
|
||||
timeout=config.streamer.timeout,
|
||||
|
||||
cmd=config.streamer.cmd,
|
||||
|
||||
loop=loop,
|
||||
)
|
||||
|
||||
Server(
|
||||
auth_manager=auth_manager,
|
||||
info_manager=info_manager,
|
||||
log_reader=log_reader,
|
||||
auth_manager=AuthManager(**config.auth._unpack_renamed()),
|
||||
info_manager=InfoManager(loop=loop, **config.info._unpack_renamed()),
|
||||
log_reader=LogReader(loop=loop),
|
||||
|
||||
hid=hid,
|
||||
atx=atx,
|
||||
msd=msd,
|
||||
streamer=streamer,
|
||||
|
||||
access_log_format=config.server.access_log_format,
|
||||
heartbeat=config.server.heartbeat,
|
||||
streamer_shutdown_delay=config.streamer.shutdown_delay,
|
||||
msd_chunk_size=config.msd.chunk_size,
|
||||
hid=Hid(**config.hid._unpack_renamed()),
|
||||
atx=Atx(**config.atx._unpack_renamed()),
|
||||
msd=MassStorageDevice(loop=loop, **config.msd._unpack_renamed()),
|
||||
streamer=Streamer(loop=loop, **config.streamer._unpack_renamed()),
|
||||
|
||||
loop=loop,
|
||||
).run(
|
||||
host=config.server.host,
|
||||
port=config.server.port,
|
||||
unix_path=config.server.unix,
|
||||
unix_rm=config.server.unix_rm,
|
||||
unix_mode=config.server.unix_mode,
|
||||
)
|
||||
|
||||
).run(**config.server._unpack_renamed())
|
||||
get_logger().info("Bye-bye")
|
||||
|
||||
@ -17,21 +17,22 @@ class AtxIsBusy(aioregion.RegionIsBusyError):
|
||||
class Atx: # pylint: disable=too-many-instance-attributes
|
||||
def __init__(
|
||||
self,
|
||||
power_led: int,
|
||||
hdd_led: int,
|
||||
power_switch: int,
|
||||
reset_switch: int,
|
||||
power_led_pin: int,
|
||||
hdd_led_pin: int,
|
||||
|
||||
power_switch_pin: int,
|
||||
reset_switch_pin: int,
|
||||
click_delay: float,
|
||||
long_click_delay: float,
|
||||
|
||||
state_poll: float,
|
||||
) -> None:
|
||||
|
||||
self.__power_led = gpio.set_input(power_led)
|
||||
self.__hdd_led = gpio.set_input(hdd_led)
|
||||
self.__power_led_pin = gpio.set_input(power_led_pin)
|
||||
self.__hdd_led_pin = gpio.set_input(hdd_led_pin)
|
||||
|
||||
self.__power_switch = gpio.set_output(power_switch)
|
||||
self.__reset_switch = gpio.set_output(reset_switch)
|
||||
self.__power_switch_pin = gpio.set_output(power_switch_pin)
|
||||
self.__reset_switch_pin = gpio.set_output(reset_switch_pin)
|
||||
self.__click_delay = click_delay
|
||||
self.__long_click_delay = long_click_delay
|
||||
|
||||
@ -43,8 +44,8 @@ class Atx: # pylint: disable=too-many-instance-attributes
|
||||
return {
|
||||
"busy": self.__region.is_busy(),
|
||||
"leds": {
|
||||
"power": (not gpio.read(self.__power_led)),
|
||||
"hdd": (not gpio.read(self.__hdd_led)),
|
||||
"power": (not gpio.read(self.__power_led_pin)),
|
||||
"hdd": (not gpio.read(self.__hdd_led_pin)),
|
||||
},
|
||||
}
|
||||
|
||||
@ -55,15 +56,15 @@ class Atx: # pylint: disable=too-many-instance-attributes
|
||||
|
||||
async def click_power(self) -> None:
|
||||
get_logger().info("Clicking power ...")
|
||||
await self.__click(self.__power_switch, self.__click_delay)
|
||||
await self.__click(self.__power_switch_pin, self.__click_delay)
|
||||
|
||||
async def click_power_long(self) -> None:
|
||||
get_logger().info("Clicking power (long press) ...")
|
||||
await self.__click(self.__power_switch, self.__long_click_delay)
|
||||
await self.__click(self.__power_switch_pin, self.__long_click_delay)
|
||||
|
||||
async def click_reset(self) -> None:
|
||||
get_logger().info("Clicking reset")
|
||||
await self.__click(self.__reset_switch, self.__click_delay)
|
||||
await self.__click(self.__reset_switch_pin, self.__click_delay)
|
||||
|
||||
async def __click(self, pin: int, delay: float) -> None:
|
||||
self.__region.enter()
|
||||
|
||||
@ -85,7 +85,7 @@ class _MouseWheelEvent(NamedTuple):
|
||||
class Hid(multiprocessing.Process): # pylint: disable=too-many-instance-attributes
|
||||
def __init__( # pylint: disable=too-many-arguments
|
||||
self,
|
||||
reset: int,
|
||||
reset_pin: int,
|
||||
reset_delay: float,
|
||||
|
||||
device_path: str,
|
||||
@ -101,7 +101,7 @@ class Hid(multiprocessing.Process): # pylint: disable=too-many-instance-attribu
|
||||
|
||||
super().__init__(daemon=True)
|
||||
|
||||
self.__reset = gpio.set_output(reset)
|
||||
self.__reset_pin = gpio.set_output(reset_pin)
|
||||
self.__reset_delay = reset_delay
|
||||
|
||||
self.__device_path = device_path
|
||||
@ -137,9 +137,9 @@ class Hid(multiprocessing.Process): # pylint: disable=too-many-instance-attribu
|
||||
|
||||
async def reset(self) -> None:
|
||||
async with self.__lock:
|
||||
gpio.write(self.__reset, True)
|
||||
gpio.write(self.__reset_pin, True)
|
||||
await asyncio.sleep(self.__reset_delay)
|
||||
gpio.write(self.__reset, False)
|
||||
gpio.write(self.__reset_pin, False)
|
||||
|
||||
async def send_key_event(self, key: str, state: bool) -> None:
|
||||
if not self.__stop_event.is_set():
|
||||
@ -188,7 +188,7 @@ class Hid(multiprocessing.Process): # pylint: disable=too-many-instance-attribu
|
||||
else:
|
||||
get_logger().warning("Emergency cleaning up HID events ...")
|
||||
self.__emergency_clear_events()
|
||||
gpio.write(self.__reset, False)
|
||||
gpio.write(self.__reset_pin, False)
|
||||
|
||||
def __unsafe_clear_events(self) -> None:
|
||||
for button in self.__pressed_mouse_buttons:
|
||||
|
||||
@ -167,24 +167,26 @@ def _msd_operated(method: Callable) -> Callable:
|
||||
class MassStorageDevice: # pylint: disable=too-many-instance-attributes
|
||||
def __init__(
|
||||
self,
|
||||
target: int,
|
||||
reset: int,
|
||||
target_pin: int,
|
||||
reset_pin: int,
|
||||
|
||||
device_path: str,
|
||||
init_delay: float,
|
||||
reset_delay: float,
|
||||
write_meta: bool,
|
||||
chunk_size: int,
|
||||
|
||||
loop: asyncio.AbstractEventLoop,
|
||||
) -> None:
|
||||
|
||||
self.__target = gpio.set_output(target)
|
||||
self.__reset = gpio.set_output(reset)
|
||||
self.__target_pin = gpio.set_output(target_pin)
|
||||
self.__reset_pin = gpio.set_output(reset_pin)
|
||||
|
||||
self._device_path = device_path
|
||||
self.__init_delay = init_delay
|
||||
self.__reset_delay = reset_delay
|
||||
self.__write_meta = write_meta
|
||||
self.chunk_size = chunk_size
|
||||
|
||||
self.__loop = loop
|
||||
|
||||
@ -236,15 +238,15 @@ class MassStorageDevice: # pylint: disable=too-many-instance-attributes
|
||||
|
||||
async def cleanup(self) -> None:
|
||||
await self.__close_device_file()
|
||||
gpio.write(self.__target, False)
|
||||
gpio.write(self.__reset, False)
|
||||
gpio.write(self.__target_pin, False)
|
||||
gpio.write(self.__reset_pin, False)
|
||||
|
||||
@_msd_operated
|
||||
async def connect_to_kvm(self, no_delay: bool=False) -> Dict:
|
||||
with self.__region:
|
||||
if self.__device_info:
|
||||
raise MsdAlreadyConnectedToKvmError()
|
||||
gpio.write(self.__target, False)
|
||||
gpio.write(self.__target_pin, False)
|
||||
if not no_delay:
|
||||
await asyncio.sleep(self.__init_delay)
|
||||
await self.__load_device_info()
|
||||
@ -258,7 +260,7 @@ class MassStorageDevice: # pylint: disable=too-many-instance-attributes
|
||||
with self.__region:
|
||||
if not self.__device_info:
|
||||
raise MsdAlreadyConnectedToPcError()
|
||||
gpio.write(self.__target, True)
|
||||
gpio.write(self.__target_pin, True)
|
||||
self.__device_info = None
|
||||
state = self.get_state()
|
||||
await self.__state_queue.put(state)
|
||||
@ -269,9 +271,9 @@ class MassStorageDevice: # pylint: disable=too-many-instance-attributes
|
||||
async def reset(self) -> None:
|
||||
with self.__region:
|
||||
get_logger().info("Mass-storage device reset")
|
||||
gpio.write(self.__reset, True)
|
||||
gpio.write(self.__reset_pin, True)
|
||||
await asyncio.sleep(self.__reset_delay)
|
||||
gpio.write(self.__reset, False)
|
||||
gpio.write(self.__reset_pin, False)
|
||||
await self.__state_queue.put(self.get_state())
|
||||
|
||||
@_msd_operated
|
||||
|
||||
@ -209,7 +209,7 @@ class _Events(Enum):
|
||||
|
||||
|
||||
class Server: # pylint: disable=too-many-instance-attributes
|
||||
def __init__( # pylint: disable=too-many-arguments
|
||||
def __init__(
|
||||
self,
|
||||
auth_manager: AuthManager,
|
||||
info_manager: InfoManager,
|
||||
@ -220,11 +220,6 @@ class Server: # pylint: disable=too-many-instance-attributes
|
||||
msd: MassStorageDevice,
|
||||
streamer: Streamer,
|
||||
|
||||
access_log_format: str,
|
||||
heartbeat: float,
|
||||
streamer_shutdown_delay: float,
|
||||
msd_chunk_size: int,
|
||||
|
||||
loop: asyncio.AbstractEventLoop,
|
||||
) -> None:
|
||||
|
||||
@ -237,13 +232,9 @@ class Server: # pylint: disable=too-many-instance-attributes
|
||||
self.__msd = msd
|
||||
self.__streamer = streamer
|
||||
|
||||
self.__access_log_format = access_log_format
|
||||
self.__heartbeat = heartbeat
|
||||
self.__streamer_shutdown_delay = streamer_shutdown_delay
|
||||
self.__msd_chunk_size = msd_chunk_size
|
||||
|
||||
self.__loop = loop
|
||||
|
||||
self.__heartbeat: Optional[float] = None # Assigned in run() for consistance
|
||||
self.__sockets: Set[aiohttp.web.WebSocketResponse] = set()
|
||||
self.__sockets_lock = asyncio.Lock()
|
||||
|
||||
@ -252,11 +243,22 @@ class Server: # pylint: disable=too-many-instance-attributes
|
||||
self.__reset_streamer = False
|
||||
self.__streamer_params = streamer.get_params()
|
||||
|
||||
def run(self, host: str, port: int, unix_path: str, unix_rm: bool, unix_mode: int) -> None:
|
||||
def run(
|
||||
self,
|
||||
host: str,
|
||||
port: int,
|
||||
unix_path: str,
|
||||
unix_rm: bool,
|
||||
unix_mode: int,
|
||||
heartbeat: float,
|
||||
access_log_format: str,
|
||||
) -> None:
|
||||
|
||||
self.__hid.start()
|
||||
|
||||
setproctitle.setproctitle("[main] " + setproctitle.getproctitle())
|
||||
|
||||
self.__heartbeat = heartbeat
|
||||
app = aiohttp.web.Application(loop=self.__loop)
|
||||
app.on_shutdown.append(self.__on_shutdown)
|
||||
app.on_cleanup.append(self.__on_cleanup)
|
||||
@ -290,7 +292,7 @@ class Server: # pylint: disable=too-many-instance-attributes
|
||||
|
||||
aiohttp.web.run_app(
|
||||
app=app,
|
||||
access_log_format=self.__access_log_format,
|
||||
access_log_format=access_log_format,
|
||||
print=self.__run_app_print,
|
||||
**socket_kwargs,
|
||||
)
|
||||
@ -354,6 +356,7 @@ class Server: # pylint: disable=too-many-instance-attributes
|
||||
@_exposed("GET", "/ws")
|
||||
async def __ws_handler(self, request: aiohttp.web.Request) -> aiohttp.web.WebSocketResponse:
|
||||
logger = get_logger(0)
|
||||
assert self.__heartbeat is not None
|
||||
ws = aiohttp.web.WebSocketResponse(heartbeat=self.__heartbeat)
|
||||
await ws.prepare(request)
|
||||
await self.__register_socket(ws)
|
||||
@ -476,7 +479,7 @@ class Server: # pylint: disable=too-many-instance-attributes
|
||||
logger.info("Writing image %r to mass-storage device ...", image_name)
|
||||
await self.__msd.write_image_info(image_name, False)
|
||||
while True:
|
||||
chunk = await field.read_chunk(self.__msd_chunk_size)
|
||||
chunk = await field.read_chunk(self.__msd.chunk_size)
|
||||
if not chunk:
|
||||
break
|
||||
written = await self.__msd.write_image_chunk(chunk)
|
||||
@ -581,7 +584,7 @@ class Server: # pylint: disable=too-many-instance-attributes
|
||||
if not self.__streamer.is_running():
|
||||
await self.__streamer.start(self.__streamer_params)
|
||||
elif prev > 0 and cur == 0:
|
||||
shutdown_at = time.time() + self.__streamer_shutdown_delay
|
||||
shutdown_at = time.time() + self.__streamer.shutdown_delay
|
||||
elif prev == 0 and cur == 0 and time.time() > shutdown_at:
|
||||
if self.__streamer.is_running():
|
||||
await self.__streamer.stop()
|
||||
|
||||
@ -19,12 +19,13 @@ from ... import gpio
|
||||
class Streamer: # pylint: disable=too-many-instance-attributes
|
||||
def __init__( # pylint: disable=too-many-arguments,too-many-locals
|
||||
self,
|
||||
cap_power: int,
|
||||
conv_power: int,
|
||||
cap_pin: int,
|
||||
conv_pin: int,
|
||||
|
||||
sync_delay: float,
|
||||
init_delay: float,
|
||||
init_restart_after: float,
|
||||
shutdown_delay: float,
|
||||
state_poll: float,
|
||||
|
||||
quality: int,
|
||||
@ -40,12 +41,13 @@ class Streamer: # pylint: disable=too-many-instance-attributes
|
||||
loop: asyncio.AbstractEventLoop,
|
||||
) -> None:
|
||||
|
||||
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.__cap_pin = (gpio.set_output(cap_pin) if cap_pin > 0 else cap_pin)
|
||||
self.__conv_pin = (gpio.set_output(conv_pin) if conv_pin > 0 else conv_pin)
|
||||
|
||||
self.__sync_delay = sync_delay
|
||||
self.__init_delay = init_delay
|
||||
self.__init_restart_after = init_restart_after
|
||||
self.shutdown_delay = shutdown_delay
|
||||
self.__state_poll = state_poll
|
||||
|
||||
self.__params = {
|
||||
@ -155,12 +157,12 @@ class Streamer: # pylint: disable=too-many-instance-attributes
|
||||
|
||||
async def __set_hw_enabled(self, enabled: bool) -> None:
|
||||
# XXX: This sequence is very important to enable converter and cap board
|
||||
if self.__cap_power > 0:
|
||||
gpio.write(self.__cap_power, enabled)
|
||||
if self.__conv_power > 0:
|
||||
if self.__cap_pin > 0:
|
||||
gpio.write(self.__cap_pin, enabled)
|
||||
if self.__conv_pin > 0:
|
||||
if enabled:
|
||||
await asyncio.sleep(self.__sync_delay)
|
||||
gpio.write(self.__conv_power, enabled)
|
||||
gpio.write(self.__conv_pin, enabled)
|
||||
if enabled:
|
||||
await asyncio.sleep(self.__init_delay)
|
||||
|
||||
|
||||
@ -44,35 +44,52 @@ class Section(dict):
|
||||
dict.__init__(self)
|
||||
self.__meta: Dict[str, Dict[str, Any]] = {}
|
||||
|
||||
def _set_meta(self, name: str, default: Any, help: str) -> None: # pylint: disable=redefined-builtin
|
||||
self.__meta[name] = {
|
||||
def _unpack_renamed(self) -> Dict[str, Any]:
|
||||
unpacked: Dict[str, Any] = {}
|
||||
for (key, value) in self.items():
|
||||
assert not isinstance(value, Section), (key, value)
|
||||
key = (self.__meta[key]["rename"] or key)
|
||||
unpacked[key] = value
|
||||
return unpacked
|
||||
|
||||
def _set_meta(self, key: str, default: Any, help: str, rename: str) -> None: # pylint: disable=redefined-builtin
|
||||
self.__meta[key] = {
|
||||
"default": default,
|
||||
"help": help,
|
||||
"rename": rename,
|
||||
}
|
||||
|
||||
def _get_default(self, name: str) -> Any:
|
||||
return self.__meta[name]["default"]
|
||||
def _get_default(self, key: str) -> Any:
|
||||
return self.__meta[key]["default"]
|
||||
|
||||
def _get_help(self, name: str) -> str:
|
||||
return self.__meta[name]["help"]
|
||||
def _get_help(self, key: str) -> str:
|
||||
return self.__meta[key]["help"]
|
||||
|
||||
def __getattribute__(self, name: str) -> Any:
|
||||
if name in self:
|
||||
return self[name]
|
||||
def __getattribute__(self, key: str) -> Any:
|
||||
if key in self:
|
||||
return self[key]
|
||||
else: # For pickling
|
||||
return dict.__getattribute__(self, name)
|
||||
return dict.__getattribute__(self, key)
|
||||
|
||||
|
||||
class Option:
|
||||
__type = type
|
||||
|
||||
def __init__(self, default: Any, help: str="", type: Optional[Callable[[Any], Any]]=None) -> None: # pylint: disable=redefined-builtin
|
||||
def __init__(
|
||||
self,
|
||||
default: Any,
|
||||
help: str="", # pylint: disable=redefined-builtin
|
||||
type: Optional[Callable[[Any], Any]]=None, # pylint: disable=redefined-builtin
|
||||
rename: str="",
|
||||
) -> None:
|
||||
|
||||
self.default = default
|
||||
self.help = help
|
||||
self.type: Callable[[Any], Any] = (type or (self.__type(default) if default is not None else str)) # type: ignore
|
||||
self.rename = rename
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return "<Option(default={self.default}, type={self.type}, help={self.help})>".format(self=self)
|
||||
return "<Option(default={self.default}, type={self.type}, help={self.help}, rename={self.rename})>".format(self=self)
|
||||
|
||||
|
||||
# =====
|
||||
@ -93,9 +110,10 @@ def make_config(raw: Dict[str, Any], scheme: Dict[str, Any], _keys: Tuple[str, .
|
||||
raise ValueError("Invalid value '{value}' for key '{key}'".format(key=full_name, value=value))
|
||||
config[key] = value
|
||||
config._set_meta( # pylint: disable=protected-access
|
||||
name=key,
|
||||
key=key,
|
||||
default=option.default,
|
||||
help=option.help,
|
||||
rename=option.rename,
|
||||
)
|
||||
elif isinstance(option, dict):
|
||||
config[key] = make_config(raw.get(key, {}), option, full_key)
|
||||
|
||||
@ -4,28 +4,24 @@ kvmd:
|
||||
port: 8081
|
||||
|
||||
hid:
|
||||
pinout:
|
||||
reset: 4
|
||||
reset_pin: 4
|
||||
device: /dev/ttyS10
|
||||
noop: true
|
||||
|
||||
atx:
|
||||
pinout:
|
||||
power_led: 24
|
||||
hdd_led: 22
|
||||
power_switch: 23
|
||||
reset_switch: 27
|
||||
power_led_pin: 24
|
||||
hdd_led_pin: 22
|
||||
power_switch_pin: 23
|
||||
reset_switch_pin: 27
|
||||
|
||||
msd:
|
||||
pinout:
|
||||
target: 12
|
||||
reset: 13
|
||||
target_pin: 12
|
||||
reset_pin: 13
|
||||
device: /dev/kvmd-msd
|
||||
|
||||
streamer:
|
||||
pinout:
|
||||
cap: 17
|
||||
conv: 18
|
||||
cap_pin: 17
|
||||
conv_pin: 18
|
||||
init_restart_after: 1
|
||||
host: 127.0.0.1
|
||||
port: 8082
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user