mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2025-12-13 17:50:29 +08:00
using libgpiod for the relay msd
This commit is contained in:
parent
fa5e6735ed
commit
bddabc4742
@ -48,11 +48,6 @@ def _clear_gpio(config: Section) -> None:
|
|||||||
("atx_gpio/power_switch", config.atx.power_switch_pin),
|
("atx_gpio/power_switch", config.atx.power_switch_pin),
|
||||||
("atx_gpio/reset_switch", config.atx.reset_switch_pin),
|
("atx_gpio/reset_switch", config.atx.reset_switch_pin),
|
||||||
] if config.atx.type == "gpio" else []),
|
] if config.atx.type == "gpio" else []),
|
||||||
|
|
||||||
*([
|
|
||||||
("msd_relay/target", config.msd.target_pin),
|
|
||||||
("msd_relay/reset", config.msd.reset_pin),
|
|
||||||
] if config.msd.type == "relay" else []),
|
|
||||||
]:
|
]:
|
||||||
if pin >= 0:
|
if pin >= 0:
|
||||||
logger.info("Writing 0 to GPIO pin=%d (%s)", pin, name)
|
logger.info("Writing 0 to GPIO pin=%d (%s)", pin, name)
|
||||||
|
|||||||
@ -35,12 +35,12 @@ from typing import Optional
|
|||||||
|
|
||||||
import aiofiles
|
import aiofiles
|
||||||
import aiofiles.base
|
import aiofiles.base
|
||||||
|
import gpiod
|
||||||
|
|
||||||
from ...logging import get_logger
|
from ...logging import get_logger
|
||||||
|
|
||||||
from ... import aiotools
|
from ... import aiotools
|
||||||
from ... import aiofs
|
from ... import aiofs
|
||||||
from ... import gpio
|
|
||||||
|
|
||||||
from ...yamlconf import Option
|
from ...yamlconf import Option
|
||||||
|
|
||||||
@ -152,6 +152,59 @@ def _explore_device(device_path: str) -> _DeviceInfo:
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class _Gpio:
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
target_pin: int,
|
||||||
|
reset_pin: int,
|
||||||
|
reset_delay: float,
|
||||||
|
) -> None:
|
||||||
|
|
||||||
|
self.__target_pin = target_pin
|
||||||
|
self.__reset_pin = reset_pin
|
||||||
|
self.__reset_delay = reset_delay
|
||||||
|
|
||||||
|
self.__chip: Optional[gpiod.Chip] = None
|
||||||
|
self.__target_line: Optional[gpiod.Line] = None
|
||||||
|
self.__reset_line: Optional[gpiod.Line] = None
|
||||||
|
|
||||||
|
def open(self) -> None:
|
||||||
|
assert self.__chip is None
|
||||||
|
assert self.__target_line is None
|
||||||
|
assert self.__reset_line is None
|
||||||
|
|
||||||
|
self.__chip = gpiod.Chip("/dev/gpiochip0")
|
||||||
|
|
||||||
|
self.__target_line = self.__chip.get_line(self.__target_pin)
|
||||||
|
self.__target_line.request("kvmd/msd-relay/target", gpiod.LINE_REQ_DIR_OUT, default_val=0)
|
||||||
|
|
||||||
|
self.__reset_line = self.__chip.get_line(self.__reset_pin)
|
||||||
|
self.__reset_line.request("kvmd/msd-relay/reset", gpiod.LINE_REQ_DIR_OUT, default_val=0)
|
||||||
|
|
||||||
|
def close(self) -> None:
|
||||||
|
if self.__chip:
|
||||||
|
self.__chip.close()
|
||||||
|
|
||||||
|
def switch_to_local(self) -> None:
|
||||||
|
assert self.__target_line
|
||||||
|
self.__target_line.set_value(0)
|
||||||
|
|
||||||
|
def switch_to_server(self) -> None:
|
||||||
|
assert self.__target_line
|
||||||
|
self.__target_line.set_value(1)
|
||||||
|
|
||||||
|
@contextlib.asynccontextmanager
|
||||||
|
async def reset(self) -> AsyncGenerator[None, None]:
|
||||||
|
assert self.__reset_line
|
||||||
|
try:
|
||||||
|
self.__reset_line.set_value(1)
|
||||||
|
await asyncio.sleep(self.__reset_delay)
|
||||||
|
self.__reset_line.set_value(0)
|
||||||
|
yield
|
||||||
|
finally:
|
||||||
|
self.__reset_line.set_value(0)
|
||||||
|
|
||||||
|
|
||||||
# =====
|
# =====
|
||||||
class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes
|
class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes
|
||||||
def __init__( # pylint: disable=super-init-not-called
|
def __init__( # pylint: disable=super-init-not-called
|
||||||
@ -165,13 +218,11 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes
|
|||||||
reset_delay: float,
|
reset_delay: float,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
||||||
self.__target_pin = gpio.set_output(target_pin, False)
|
|
||||||
self.__reset_pin = gpio.set_output(reset_pin, False)
|
|
||||||
|
|
||||||
self.__device_path = device_path
|
self.__device_path = device_path
|
||||||
self.__init_delay = init_delay
|
self.__init_delay = init_delay
|
||||||
self.__init_retries = init_retries
|
self.__init_retries = init_retries
|
||||||
self.__reset_delay = reset_delay
|
|
||||||
|
self.__gpio = _Gpio(target_pin, reset_pin, reset_delay)
|
||||||
|
|
||||||
self.__device_info: Optional[_DeviceInfo] = None
|
self.__device_info: Optional[_DeviceInfo] = None
|
||||||
self.__connected = False
|
self.__connected = False
|
||||||
@ -202,6 +253,9 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes
|
|||||||
"reset_delay": Option(1.0, type=valid_float_f01),
|
"reset_delay": Option(1.0, type=valid_float_f01),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def sysprep(self) -> None:
|
||||||
|
self.__gpio.open()
|
||||||
|
|
||||||
async def get_state(self) -> Dict:
|
async def get_state(self) -> Dict:
|
||||||
storage: Optional[Dict] = None
|
storage: Optional[Dict] = None
|
||||||
drive: Optional[Dict] = None
|
drive: Optional[Dict] = None
|
||||||
@ -245,26 +299,18 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes
|
|||||||
|
|
||||||
@aiotools.atomic
|
@aiotools.atomic
|
||||||
async def __inner_reset(self) -> None:
|
async def __inner_reset(self) -> None:
|
||||||
try:
|
async with self.__gpio.reset():
|
||||||
gpio.write(self.__reset_pin, True)
|
self.__gpio.switch_to_local()
|
||||||
await asyncio.sleep(self.__reset_delay)
|
|
||||||
gpio.write(self.__reset_pin, False)
|
|
||||||
|
|
||||||
gpio.write(self.__target_pin, False)
|
|
||||||
self.__connected = False
|
self.__connected = False
|
||||||
|
|
||||||
await self.__load_device_info()
|
await self.__load_device_info()
|
||||||
get_logger(0).info("MSD reset has been successful")
|
get_logger(0).info("MSD reset has been successful")
|
||||||
finally:
|
|
||||||
gpio.write(self.__reset_pin, False)
|
|
||||||
|
|
||||||
@aiotools.atomic
|
@aiotools.atomic
|
||||||
async def cleanup(self) -> None:
|
async def cleanup(self) -> None:
|
||||||
try:
|
try:
|
||||||
await self.__close_device_file()
|
await self.__close_device_file()
|
||||||
finally:
|
finally:
|
||||||
gpio.write(self.__target_pin, False)
|
self.__gpio.close()
|
||||||
gpio.write(self.__reset_pin, False)
|
|
||||||
|
|
||||||
# =====
|
# =====
|
||||||
|
|
||||||
@ -283,7 +329,7 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes
|
|||||||
if self.__connected:
|
if self.__connected:
|
||||||
raise MsdConnectedError()
|
raise MsdConnectedError()
|
||||||
|
|
||||||
gpio.write(self.__target_pin, True)
|
self.__gpio.switch_to_server()
|
||||||
self.__connected = True
|
self.__connected = True
|
||||||
get_logger(0).info("MSD switched to Server")
|
get_logger(0).info("MSD switched to Server")
|
||||||
|
|
||||||
@ -294,12 +340,12 @@ class Plugin(BaseMsd): # pylint: disable=too-many-instance-attributes
|
|||||||
if not self.__connected:
|
if not self.__connected:
|
||||||
raise MsdDisconnectedError()
|
raise MsdDisconnectedError()
|
||||||
|
|
||||||
gpio.write(self.__target_pin, False)
|
self.__gpio.switch_to_local()
|
||||||
try:
|
try:
|
||||||
await self.__load_device_info()
|
await self.__load_device_info()
|
||||||
except Exception:
|
except Exception:
|
||||||
if self.__connected:
|
if self.__connected:
|
||||||
gpio.write(self.__target_pin, True)
|
self.__gpio.switch_to_server()
|
||||||
raise
|
raise
|
||||||
self.__connected = False
|
self.__connected = False
|
||||||
get_logger(0).info("MSD switched to KVM: %s", self.__device_info)
|
get_logger(0).info("MSD switched to KVM: %s", self.__device_info)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user