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